From 9b4d5e339b3dc45846f47cc1e39d5e15e29ae0c1 Mon Sep 17 00:00:00 2001 From: TheCoreDev Date: Thu, 14 Jan 2021 18:04:26 +0100 Subject: [PATCH] Initial commit --- .env.dist | 2 + .gitattributes | 1 + .gitignore | 81 + .htaccess | 3 + CHANGELOG.md | 1312 ++ CONTRIBUTORS.md | 51 + COPYRIGHT.txt | 4 + LICENSE.txt | 165 + Readme.md | 227 + Thelia | 5 + UPDATE.md | 68 + UPGRADE-2.3.md | 131 + composer.json | 101 + composer.lock | 5426 +++++++ core/LICENSE.txt | 165 + core/Readme.md | 47 + core/Thelia | 58 + core/bootstrap.php | 102 + core/composer.json | 79 + core/composer.lock | 5372 +++++++ core/lib/Thelia/Action/Address.php | 108 + core/lib/Thelia/Action/Administrator.php | 155 + core/lib/Thelia/Action/Api.php | 65 + core/lib/Thelia/Action/Area.php | 137 + core/lib/Thelia/Action/Attribute.php | 157 + core/lib/Thelia/Action/AttributeAv.php | 119 + core/lib/Thelia/Action/BaseAction.php | 146 + core/lib/Thelia/Action/BaseCachedFile.php | 290 + core/lib/Thelia/Action/Brand.php | 175 + core/lib/Thelia/Action/Cache.php | 96 + core/lib/Thelia/Action/Cart.php | 546 + core/lib/Thelia/Action/Category.php | 268 + core/lib/Thelia/Action/Config.php | 128 + core/lib/Thelia/Action/Content.php | 263 + core/lib/Thelia/Action/Country.php | 121 + core/lib/Thelia/Action/Coupon.php | 466 + core/lib/Thelia/Action/Currency.php | 219 + core/lib/Thelia/Action/Customer.php | 292 + core/lib/Thelia/Action/CustomerTitle.php | 111 + core/lib/Thelia/Action/Delivery.php | 79 + core/lib/Thelia/Action/Document.php | 125 + core/lib/Thelia/Action/Export.php | 79 + core/lib/Thelia/Action/Feature.php | 159 + core/lib/Thelia/Action/FeatureAv.php | 119 + core/lib/Thelia/Action/File.php | 175 + core/lib/Thelia/Action/Folder.php | 208 + core/lib/Thelia/Action/Hook.php | 168 + core/lib/Thelia/Action/HttpException.php | 114 + core/lib/Thelia/Action/Image.php | 431 + core/lib/Thelia/Action/Import.php | 79 + core/lib/Thelia/Action/Lang.php | 283 + core/lib/Thelia/Action/MailingSystem.php | 51 + core/lib/Thelia/Action/Message.php | 116 + core/lib/Thelia/Action/MetaData.php | 75 + core/lib/Thelia/Action/Module.php | 467 + core/lib/Thelia/Action/ModuleHook.php | 252 + core/lib/Thelia/Action/Newsletter.php | 120 + core/lib/Thelia/Action/Order.php | 753 + core/lib/Thelia/Action/OrderStatus.php | 147 + core/lib/Thelia/Action/Payment.php | 65 + core/lib/Thelia/Action/Pdf.php | 56 + core/lib/Thelia/Action/Product.php | 960 ++ core/lib/Thelia/Action/ProductSaleElement.php | 521 + core/lib/Thelia/Action/Profile.php | 151 + core/lib/Thelia/Action/RedirectException.php | 60 + core/lib/Thelia/Action/Sale.php | 498 + core/lib/Thelia/Action/ShippingZone.php | 63 + core/lib/Thelia/Action/State.php | 103 + core/lib/Thelia/Action/Tax.php | 95 + core/lib/Thelia/Action/TaxRule.php | 205 + core/lib/Thelia/Action/Template.php | 288 + core/lib/Thelia/Action/Translation.php | 372 + core/lib/Thelia/Cart/CartTrait.php | 54 + .../Command/AdminUpdatePasswordCommand.php | 98 + .../lib/Thelia/Command/BaseModuleGenerate.php | 112 + core/lib/Thelia/Command/CacheClear.php | 112 + core/lib/Thelia/Command/ClearImageCache.php | 53 + core/lib/Thelia/Command/ConfigCommand.php | 225 + .../Thelia/Command/ContainerAwareCommand.php | 133 + core/lib/Thelia/Command/CreateAdminUser.php | 205 + .../Thelia/Command/DiffDatabaseCommand.php | 88 + core/lib/Thelia/Command/ExportCommand.php | 241 + core/lib/Thelia/Command/GenerateResources.php | 101 + .../lib/Thelia/Command/GenerateSQLCommand.php | 221 + core/lib/Thelia/Command/HookCleanCommand.php | 157 + core/lib/Thelia/Command/ImportCommand.php | 141 + core/lib/Thelia/Command/Install.php | 345 + .../Thelia/Command/ModuleActivateCommand.php | 93 + .../Command/ModuleDeactivateCommand.php | 134 + .../Thelia/Command/ModuleGenerateCommand.php | 235 + .../Command/ModuleGenerateModelCommand.php | 115 + .../Command/ModuleGenerateSqlCommand.php | 86 + core/lib/Thelia/Command/ModuleListCommand.php | 87 + .../Thelia/Command/ModulePositionCommand.php | 219 + .../Thelia/Command/ModuleRefreshCommand.php | 62 + .../Command/Output/TheliaConsoleOutput.php | 43 + .../Thelia/Command/ReloadDatabaseCommand.php | 61 + .../Command/SaleCheckActivationCommand.php | 47 + .../Skeleton/Module/Class.php.template | 28 + .../Command/Skeleton/Module/I18n/en_US.php | 4 + .../Command/Skeleton/Module/I18n/fr_FR.php | 4 + .../Thelia/Command/Skeleton/Module/Readme.md | 55 + .../Command/Skeleton/Module/composer.json | 12 + .../Thelia/Command/Skeleton/Module/config.xml | 50 + .../Command/Skeleton/Module/config_dev.xml | 50 + .../Command/Skeleton/Module/config_prod.xml | 50 + .../Command/Skeleton/Module/config_test.xml | 50 + .../Thelia/Command/Skeleton/Module/module.xml | 43 + .../Command/Skeleton/Module/routing.xml | 31 + .../Thelia/Command/Skeleton/Module/schema.xml | 25 + .../Thelia/Command/UpdateCurrenciesRates.php | 73 + .../Thelia/Condition/ConditionCollection.php | 191 + .../Thelia/Condition/ConditionEvaluator.php | 95 + .../lib/Thelia/Condition/ConditionFactory.php | 157 + .../Thelia/Condition/ConditionOrganizer.php | 35 + .../Condition/ConditionOrganizerInterface.php | 32 + .../Implementation/AbstractMatchCountries.php | 155 + .../Implementation/CartContainsCategories.php | 200 + .../Implementation/CartContainsProducts.php | 195 + .../Implementation/ConditionAbstract.php | 351 + .../Implementation/ConditionInterface.php | 107 + .../Implementation/ForSomeCustomers.php | 190 + .../Implementation/MatchBillingCountries.php | 94 + .../Implementation/MatchDeliveryCountries.php | 96 + .../Implementation/MatchForEveryone.php | 117 + .../Implementation/MatchForTotalAmount.php | 224 + .../Implementation/MatchForXArticles.php | 187 + .../MatchForXArticlesIncludeQuantity.php | 82 + .../Condition/Implementation/StartDate.php | 184 + core/lib/Thelia/Condition/Operators.php | 108 + .../Condition/SerializableCondition.php | 32 + .../Thelia/Config/DatabaseConfiguration.php | 105 + .../Config/DatabaseConfigurationSource.php | 140 + core/lib/Thelia/Config/I18n/ar_SA.php | 404 + core/lib/Thelia/Config/I18n/cs_CZ.php | 79 + core/lib/Thelia/Config/I18n/de_DE.php | 792 + core/lib/Thelia/Config/I18n/el_GR.php | 33 + core/lib/Thelia/Config/I18n/en_US.php | 866 ++ core/lib/Thelia/Config/I18n/es_ES.php | 823 ++ core/lib/Thelia/Config/I18n/fa_IR.php | 762 + core/lib/Thelia/Config/I18n/fr_FR.php | 866 ++ core/lib/Thelia/Config/I18n/he_IL.php | 51 + core/lib/Thelia/Config/I18n/hu_HU.php | 314 + core/lib/Thelia/Config/I18n/id_ID.php | 695 + core/lib/Thelia/Config/I18n/it_IT.php | 297 + core/lib/Thelia/Config/I18n/nl_NL.php | 24 + core/lib/Thelia/Config/I18n/pl_PL.php | 363 + core/lib/Thelia/Config/I18n/pt_BR.php | 232 + core/lib/Thelia/Config/I18n/pt_PT.php | 12 + core/lib/Thelia/Config/I18n/ro_RO.php | 12 + core/lib/Thelia/Config/I18n/ru_RU.php | 830 ++ core/lib/Thelia/Config/I18n/sk_SK.php | 518 + core/lib/Thelia/Config/I18n/tr_TR.php | 768 + core/lib/Thelia/Config/I18n/uk_UA.php | 201 + core/lib/Thelia/Config/I18n/zh_CN.php | 64 + core/lib/Thelia/Config/Resources/action.xml | 244 + core/lib/Thelia/Config/Resources/command.xml | 33 + core/lib/Thelia/Config/Resources/config.xml | 382 + core/lib/Thelia/Config/Resources/coupon.xml | 134 + core/lib/Thelia/Config/Resources/export.xml | 136 + core/lib/Thelia/Config/Resources/form-api.xml | 28 + .../lib/Thelia/Config/Resources/form-type.xml | 335 + core/lib/Thelia/Config/Resources/form.xml | 171 + core/lib/Thelia/Config/Resources/import.xml | 85 + core/lib/Thelia/Config/Resources/loop.xml | 75 + core/lib/Thelia/Config/Resources/routing.xml | 88 + .../Thelia/Config/Resources/routing/admin.xml | 1606 ++ .../Thelia/Config/Resources/routing/api.xml | 279 + core/lib/Thelia/Config/Resources/stack.xml | 24 + core/lib/Thelia/Config/Resources/test.xml | 28 + .../Thelia/Config/Resources/translation.xml | 68 + .../Admin/AbstractCrudController.php | 676 + .../Admin/AbstractSeoCrudController.php | 222 + .../Controller/Admin/AddressController.php | 322 + .../Controller/Admin/AdminController.php | 33 + .../Controller/Admin/AdminLogsController.php | 64 + .../Admin/AdministratorController.php | 201 + .../Admin/AdvancedConfigurationController.php | 108 + .../Thelia/Controller/Admin/ApiController.php | 210 + .../Controller/Admin/AreaController.php | 440 + .../Admin/AttributeAvController.php | 183 + .../Controller/Admin/AttributeController.php | 266 + .../Controller/Admin/BaseAdminController.php | 402 + .../Controller/Admin/BrandController.php | 282 + .../Controller/Admin/CategoryController.php | 405 + .../Controller/Admin/ConfigController.php | 205 + .../Admin/ConfigStoreController.php | 137 + .../Admin/ConfigurationController.php | 33 + .../Controller/Admin/ContentController.php | 413 + .../Controller/Admin/CountryController.php | 344 + .../Controller/Admin/CouponController.php | 884 ++ .../Controller/Admin/CurrencyController.php | 265 + .../Controller/Admin/CustomerController.php | 254 + .../Controller/Admin/ExportController.php | 249 + .../Controller/Admin/FeatureAvController.php | 185 + .../Controller/Admin/FeatureController.php | 266 + .../Controller/Admin/FileController.php | 866 ++ .../Controller/Admin/FolderController.php | 337 + .../Controller/Admin/HomeController.php | 30 + .../Controller/Admin/HookController.php | 474 + .../Controller/Admin/ImportController.php | 242 + .../Controller/Admin/LangController.php | 456 + .../Controller/Admin/LanguageController.php | 32 + .../Admin/MailingSystemController.php | 156 + .../Controller/Admin/MessageController.php | 330 + .../Controller/Admin/ModuleController.php | 480 + .../Controller/Admin/ModuleHookController.php | 399 + .../Controller/Admin/OrderController.php | 241 + .../Admin/OrderStatusController.php | 293 + .../Controller/Admin/ProductController.php | 1951 +++ .../Controller/Admin/ProfileController.php | 444 + .../Controller/Admin/SaleController.php | 405 + .../Controller/Admin/SessionController.php | 317 + .../Admin/ShippingZoneController.php | 149 + .../Controller/Admin/StateController.php | 244 + .../Controller/Admin/SystemLogController.php | 165 + .../Thelia/Controller/Admin/TaxController.php | 218 + .../Controller/Admin/TaxRuleController.php | 422 + .../Controller/Admin/TemplateController.php | 373 + .../Controller/Admin/ToolsController.php | 33 + .../Admin/TranslationsController.php | 359 + .../Api/AbstractCrudApiController.php | 505 + .../Controller/Api/AttributeAvController.php | 112 + .../Controller/Api/BaseApiController.php | 125 + .../Thelia/Controller/Api/BrandController.php | 112 + .../Controller/Api/CategoryController.php | 152 + .../Controller/Api/CountryController.php | 112 + .../Controller/Api/CurrencyController.php | 112 + .../Controller/Api/CustomerController.php | 216 + .../Thelia/Controller/Api/ImageController.php | 374 + .../Thelia/Controller/Api/IndexController.php | 31 + .../Thelia/Controller/Api/LangController.php | 112 + .../Controller/Api/ProductController.php | 189 + .../Api/ProductSaleElementsController.php | 467 + .../Thelia/Controller/Api/TaxController.php | 112 + .../Controller/Api/TaxRuleController.php | 257 + .../Thelia/Controller/Api/TitleController.php | 235 + core/lib/Thelia/Controller/BaseController.php | 631 + .../Controller/Front/BaseFrontController.php | 134 + .../Controller/Front/DefaultController.php | 76 + core/lib/Thelia/Core/Application.php | 82 + .../Thelia/Core/Archiver/AbstractArchiver.php | 89 + .../Core/Archiver/Archiver/TarArchiver.php | 84 + .../Core/Archiver/Archiver/TarBz2Archiver.php | 47 + .../Core/Archiver/Archiver/TarGzArchiver.php | 47 + .../Core/Archiver/Archiver/ZipArchiver.php | 79 + .../Core/Archiver/ArchiverInterface.php | 115 + .../Thelia/Core/Archiver/ArchiverManager.php | 165 + core/lib/Thelia/Core/Bundle/TheliaBundle.php | 72 + .../Core/Controller/ControllerResolver.php | 92 + .../CurrencyConverterProviderPass.php | 56 + .../Compiler/FallbackParserPass.php | 47 + .../Compiler/RegisterArchiverPass.php | 54 + .../Compiler/RegisterAssetFilterPass.php | 73 + .../Compiler/RegisterCouponConditionPass.php | 56 + .../Compiler/RegisterCouponPass.php | 54 + .../Compiler/RegisterFormExtensionPass.php | 66 + .../Compiler/RegisterHookListenersPass.php | 421 + .../Compiler/RegisterRouterPass.php | 87 + .../Compiler/RegisterSerializerPass.php | 54 + .../Compiler/StackPass.php | 71 + .../Compiler/TranslatorPass.php | 48 + .../Loader/XmlFileLoader.php | 795 + .../Loader/schema/dic/config/thelia-1.0.xsd | 380 + .../DependencyInjection/TheliaContainer.php | 53 + core/lib/Thelia/Core/Event/AccessoryEvent.php | 45 + core/lib/Thelia/Core/Event/ActionEvent.php | 65 + .../Address/AddressCreateOrUpdateEvent.php | 297 + .../Core/Event/Address/AddressEvent.php | 40 + .../Administrator/AdministratorEvent.php | 159 + .../AdministratorUpdatePasswordEvent.php | 75 + .../Thelia/Core/Event/Api/ApiCreateEvent.php | 64 + .../Thelia/Core/Event/Api/ApiDeleteEvent.php | 45 + .../Thelia/Core/Event/Api/ApiUpdateEvent.php | 69 + .../Core/Event/Area/AreaAddCountryEvent.php | 72 + .../Core/Event/Area/AreaCreateEvent.php | 41 + .../Core/Event/Area/AreaDeleteEvent.php | 51 + core/lib/Thelia/Core/Event/Area/AreaEvent.php | 59 + .../Event/Area/AreaRemoveCountryEvent.php | 48 + .../Core/Event/Area/AreaUpdateEvent.php | 41 + .../Event/Area/AreaUpdatePostageEvent.php | 69 + .../Attribute/AttributeAvCreateEvent.php | 56 + .../Attribute/AttributeAvDeleteEvent.php | 39 + .../Core/Event/Attribute/AttributeAvEvent.php | 46 + .../Attribute/AttributeAvUpdateEvent.php | 79 + .../Event/Attribute/AttributeCreateEvent.php | 56 + .../Event/Attribute/AttributeDeleteEvent.php | 39 + .../Core/Event/Attribute/AttributeEvent.php | 46 + .../Event/Attribute/AttributeUpdateEvent.php | 79 + .../Core/Event/Brand/BrandCreateEvent.php | 85 + .../Core/Event/Brand/BrandDeleteEvent.php | 52 + .../Thelia/Core/Event/Brand/BrandEvent.php | 64 + .../Brand/BrandToggleVisibilityEvent.php | 22 + .../Core/Event/Brand/BrandUpdateEvent.php | 135 + .../Thelia/Core/Event/Cache/CacheEvent.php | 81 + .../lib/Thelia/Core/Event/CachedFileEvent.php | 83 + .../Core/Event/Cart/CartCreateEvent.php | 41 + .../Core/Event/Cart/CartDuplicationEvent.php | 43 + core/lib/Thelia/Core/Event/Cart/CartEvent.php | 188 + .../Event/Cart/CartItemDuplicationItem.php | 56 + .../Thelia/Core/Event/Cart/CartItemEvent.php | 31 + .../Core/Event/Cart/CartPersistEvent.php | 60 + .../Core/Event/Cart/CartRestoreEvent.php | 41 + .../Category/CategoryAddContentEvent.php | 37 + .../CategoryAssociatedContentEvent.php | 46 + .../Event/Category/CategoryCreateEvent.php | 69 + .../Category/CategoryDeleteContentEvent.php | 37 + .../Event/Category/CategoryDeleteEvent.php | 39 + .../Core/Event/Category/CategoryEvent.php | 46 + .../CategoryToggleVisibilityEvent.php | 17 + .../Event/Category/CategoryUpdateEvent.php | 113 + .../Core/Event/Config/ConfigCreateEvent.php | 96 + .../Core/Event/Config/ConfigDeleteEvent.php | 39 + .../Thelia/Core/Event/Config/ConfigEvent.php | 46 + .../Core/Event/Config/ConfigUpdateEvent.php | 79 + .../Core/Event/Contact/ContactEvent.php | 123 + .../Event/Content/ContentAddFolderEvent.php | 51 + .../Core/Event/Content/ContentCreateEvent.php | 106 + .../Core/Event/Content/ContentDeleteEvent.php | 65 + .../Core/Event/Content/ContentEvent.php | 63 + .../Content/ContentRemoveFolderEvent.php | 22 + .../Content/ContentToggleVisibilityEvent.php | 22 + .../Core/Event/Content/ContentUpdateEvent.php | 116 + .../Core/Event/Country/CountryCreateEvent.php | 176 + .../Core/Event/Country/CountryDeleteEvent.php | 50 + .../Core/Event/Country/CountryEvent.php | 61 + .../Country/CountryToggleDefaultEvent.php | 40 + .../Country/CountryToggleVisibilityEvent.php | 23 + .../Core/Event/Country/CountryUpdateEvent.php | 159 + .../Core/Event/Coupon/CouponConsumeEvent.php | 145 + .../Coupon/CouponCreateOrUpdateEvent.php | 462 + .../Core/Event/Coupon/CouponDeleteEvent.php | 70 + .../Event/Currency/CurrencyChangeEvent.php | 52 + .../Event/Currency/CurrencyCreateEvent.php | 96 + .../Event/Currency/CurrencyDeleteEvent.php | 24 + .../Core/Event/Currency/CurrencyEvent.php | 77 + .../Event/Currency/CurrencyUpdateEvent.php | 69 + .../Currency/CurrencyUpdateRateEvent.php | 41 + .../Customer/CustomerCreateOrUpdateEvent.php | 344 + .../Core/Event/Customer/CustomerEvent.php | 57 + .../Event/Customer/CustomerLoginEvent.php | 18 + .../CustomerTitle/CustomerTitleEvent.php | 144 + .../Thelia/Core/Event/DefaultActionEvent.php | 17 + .../Event/Delivery/DeliveryPostageEvent.php | 277 + .../Event/Delivery/PickupLocationEvent.php | 293 + .../Core/Event/Document/DocumentEvent.php | 74 + core/lib/Thelia/Core/Event/ExportEvent.php | 158 + .../Event/Feature/FeatureAvCreateEvent.php | 56 + .../Event/Feature/FeatureAvDeleteEvent.php | 39 + .../Core/Event/Feature/FeatureAvEvent.php | 46 + .../Event/Feature/FeatureAvUpdateEvent.php | 79 + .../Core/Event/Feature/FeatureCreateEvent.php | 56 + .../Core/Event/Feature/FeatureDeleteEvent.php | 39 + .../Core/Event/Feature/FeatureEvent.php | 46 + .../Core/Event/Feature/FeatureUpdateEvent.php | 79 + .../FeatureProductDeleteEvent.php | 60 + .../FeatureProduct/FeatureProductEvent.php | 46 + .../FeatureProductUpdateEvent.php | 112 + .../Event/File/FileCreateOrUpdateEvent.php | 168 + .../Core/Event/File/FileDeleteEvent.php | 61 + .../Event/File/FileToggleVisibilityEvent.php | 53 + .../Core/Event/Folder/FolderCreateEvent.php | 107 + .../Core/Event/Folder/FolderDeleteEvent.php | 50 + .../Thelia/Core/Event/Folder/FolderEvent.php | 63 + .../Folder/FolderToggleVisibilityEvent.php | 22 + .../Core/Event/Folder/FolderUpdateEvent.php | 112 + .../Core/Event/GenerateRewrittenUrlEvent.php | 103 + .../Core/Event/Hook/BaseHookRenderEvent.php | 162 + .../Core/Event/Hook/HookCreateAllEvent.php | 241 + .../Core/Event/Hook/HookCreateEvent.php | 153 + .../Core/Event/Hook/HookDeactivationEvent.php | 51 + .../Core/Event/Hook/HookDeleteEvent.php | 51 + core/lib/Thelia/Core/Event/Hook/HookEvent.php | 48 + .../Core/Event/Hook/HookRenderBlockEvent.php | 94 + .../Core/Event/Hook/HookRenderEvent.php | 73 + .../Event/Hook/HookToggleActivationEvent.php | 51 + .../Core/Event/Hook/HookToggleNativeEvent.php | 46 + .../Core/Event/Hook/HookUpdateEvent.php | 126 + .../Core/Event/Hook/ModuleHookCreateEvent.php | 131 + .../Core/Event/Hook/ModuleHookDeleteEvent.php | 51 + .../Core/Event/Hook/ModuleHookEvent.php | 48 + .../Hook/ModuleHookToggleActivationEvent.php | 22 + .../Core/Event/Hook/ModuleHookUpdateEvent.php | 62 + .../Thelia/Core/Event/Image/ImageEvent.php | 260 + core/lib/Thelia/Core/Event/ImportEvent.php | 123 + .../Core/Event/Lang/LangCreateEvent.php | 245 + .../Event/Lang/LangDefaultBehaviorEvent.php | 49 + .../Core/Event/Lang/LangDeleteEvent.php | 54 + core/lib/Thelia/Core/Event/Lang/LangEvent.php | 62 + .../Core/Event/Lang/LangToggleActiveEvent.php | 22 + .../Event/Lang/LangToggleDefaultEvent.php | 54 + .../Event/Lang/LangToggleVisibleEvent.php | 22 + .../Core/Event/Lang/LangUpdateEvent.php | 54 + .../Loop/LoopExtendsArgDefinitionsEvent.php | 27 + .../Event/Loop/LoopExtendsBuildArrayEvent.php | 66 + .../LoopExtendsBuildModelCriteriaEvent.php | 46 + .../Core/Event/Loop/LoopExtendsEvent.php | 57 + .../Loop/LoopExtendsInitializeArgsEvent.php | 56 + .../Loop/LoopExtendsParseResultsEvent.php | 46 + .../Thelia/Core/Event/LostPasswordEvent.php | 36 + .../Core/Event/MailTransporterEvent.php | 41 + .../MailingSystem/MailingSystemEvent.php | 172 + .../Core/Event/Message/MessageCreateEvent.php | 70 + .../Core/Event/Message/MessageDeleteEvent.php | 39 + .../Core/Event/Message/MessageEvent.php | 46 + .../Core/Event/Message/MessageUpdateEvent.php | 133 + .../MetaData/MetaDataCreateOrUpdateEvent.php | 50 + .../Event/MetaData/MetaDataDeleteEvent.php | 105 + .../Core/Event/MetaData/MetaDataEvent.php | 51 + .../Core/Event/Module/ModuleDeleteEvent.php | 84 + .../Thelia/Core/Event/Module/ModuleEvent.php | 162 + .../Core/Event/Module/ModuleInstallEvent.php | 106 + .../Module/ModuleToggleActivationEvent.php | 126 + .../Core/Event/Newsletter/NewsletterEvent.php | 175 + ...pdateOperationOnOrderStatusChangeEvent.php | 81 + .../Core/Event/Order/OrderAddressEvent.php | 260 + .../Thelia/Core/Event/Order/OrderEvent.php | 378 + .../Core/Event/Order/OrderManualEvent.php | 141 + .../Core/Event/Order/OrderPaymentEvent.php | 73 + .../Core/Event/Order/OrderProductEvent.php | 54 + .../OrderStatus/OrderStatusCreateEvent.php | 22 + .../OrderStatus/OrderStatusDeleteEvent.php | 22 + .../Event/OrderStatus/OrderStatusEvent.php | 221 + .../OrderStatus/OrderStatusUpdateEvent.php | 51 + .../Core/Event/Payment/BasePaymentEvent.php | 55 + .../Event/Payment/IsValidPaymentEvent.php | 117 + .../Payment/ManageStockOnCreationEvent.php | 53 + core/lib/Thelia/Core/Event/PdfEvent.php | 231 + .../Product/ProductAddAccessoryEvent.php | 37 + .../Event/Product/ProductAddCategoryEvent.php | 37 + .../Event/Product/ProductAddContentEvent.php | 37 + .../Product/ProductAssociatedContentEvent.php | 46 + .../Core/Event/Product/ProductCloneEvent.php | 118 + .../ProductCombinationGenerationEvent.php | 157 + .../Core/Event/Product/ProductCreateEvent.php | 246 + .../Product/ProductDeleteAccessoryEvent.php | 37 + .../Product/ProductDeleteCategoryEvent.php | 39 + .../Product/ProductDeleteContentEvent.php | 37 + .../Core/Event/Product/ProductDeleteEvent.php | 46 + .../Core/Event/Product/ProductEvent.php | 46 + .../Event/Product/ProductSetTemplateEvent.php | 53 + .../Product/ProductToggleVisibilityEvent.php | 17 + .../Core/Event/Product/ProductUpdateEvent.php | 120 + ...rtualProductOrderDownloadResponseEvent.php | 78 + .../VirtualProductOrderHandleEvent.php | 144 + .../ProductSaleElementCreateEvent.php | 70 + .../ProductSaleElementDeleteEvent.php | 72 + .../ProductSaleElementEvent.php | 43 + .../ProductSaleElementUpdateEvent.php | 340 + .../Core/Event/Profile/ProfileEvent.php | 160 + .../Sale/ProductSaleStatusUpdateEvent.php | 22 + .../Event/Sale/SaleActiveStatusCheckEvent.php | 23 + .../Core/Event/Sale/SaleClearStatusEvent.php | 22 + .../Core/Event/Sale/SaleCreateEvent.php | 84 + .../Core/Event/Sale/SaleDeleteEvent.php | 52 + core/lib/Thelia/Core/Event/Sale/SaleEvent.php | 64 + .../Event/Sale/SaleToggleActivityEvent.php | 22 + .../Core/Event/Sale/SaleUpdateEvent.php | 276 + core/lib/Thelia/Core/Event/SessionEvent.php | 84 + .../ShippingZone/ShippingZoneAddAreaEvent.php | 72 + .../ShippingZoneRemoveAreaEvent.php | 22 + .../Core/Event/State/StateCreateEvent.php | 119 + .../Core/Event/State/StateDeleteEvent.php | 50 + .../Thelia/Core/Event/State/StateEvent.php | 61 + .../State/StateToggleVisibilityEvent.php | 23 + .../Core/Event/State/StateUpdateEvent.php | 51 + core/lib/Thelia/Core/Event/Tax/TaxEvent.php | 122 + .../Thelia/Core/Event/Tax/TaxRuleEvent.php | 134 + .../Template/TemplateAddAttributeEvent.php | 39 + .../Template/TemplateAddFeatureEvent.php | 39 + .../Event/Template/TemplateCreateEvent.php | 43 + .../Template/TemplateDeleteAttributeEvent.php | 39 + .../Event/Template/TemplateDeleteEvent.php | 53 + .../Template/TemplateDeleteFeatureEvent.php | 39 + .../Event/Template/TemplateDuplicateEvent.php | 50 + .../Core/Event/Template/TemplateEvent.php | 59 + .../Event/Template/TemplateUpdateEvent.php | 62 + core/lib/Thelia/Core/Event/TheliaEvents.php | 1187 ++ .../lib/Thelia/Core/Event/TheliaFormEvent.php | 58 + .../Core/Event/ToggleVisibilityEvent.php | 57 + .../Event/Translation/TranslationEvent.php | 284 + .../Core/Event/UpdateFilePositionEvent.php | 49 + .../Thelia/Core/Event/UpdatePositionEvent.php | 139 + core/lib/Thelia/Core/Event/UpdateSeoEvent.php | 175 + core/lib/Thelia/Core/Event/ViewCheckEvent.php | 67 + .../Core/EventListener/ControllerListener.php | 107 + .../Core/EventListener/ErrorListener.php | 141 + .../Core/EventListener/RequestListener.php | 319 + .../Core/EventListener/ResponseListener.php | 63 + .../Core/EventListener/SessionListener.php | 72 + .../Core/EventListener/ViewListener.php | 156 + .../Thelia/Core/Form/TheliaFormFactory.php | 58 + .../Core/Form/TheliaFormFactoryInterface.php | 29 + .../Thelia/Core/Form/TheliaFormValidator.php | 124 + .../Form/TheliaFormValidatorInterface.php | 42 + .../Core/Form/Type/AbstractTheliaType.php | 76 + .../Core/Form/Type/CustomerTitleI18nType.php | 67 + .../Core/Form/Type/CustomerTitleType.php | 64 + .../Core/Form/Type/Field/AbstractIdType.php | 90 + .../Core/Form/Type/Field/AccessoryIdType.php | 43 + .../Core/Form/Type/Field/AddressIdType.php | 43 + .../Core/Form/Type/Field/AdminIdType.php | 43 + .../Core/Form/Type/Field/AdminLogIdType.php | 43 + .../Thelia/Core/Form/Type/Field/ApiIdType.php | 43 + .../Type/Field/AreaDeliveryModuleIdType.php | 43 + .../Core/Form/Type/Field/AreaIdType.php | 43 + .../Form/Type/Field/AttributeAvIdType.php | 43 + .../Core/Form/Type/Field/AttributeIdType.php | 43 + .../Type/Field/AttributeTemplateIdType.php | 43 + .../Core/Form/Type/Field/BrandIdType.php | 43 + .../Core/Form/Type/Field/CartIdType.php | 43 + .../Core/Form/Type/Field/CartItemIdType.php | 43 + .../Field/CategoryAssociatedContentIdType.php | 43 + .../Core/Form/Type/Field/CategoryIdType.php | 43 + .../Core/Form/Type/Field/ContentIdType.php | 43 + .../Core/Form/Type/Field/CountryIdType.php | 43 + .../Core/Form/Type/Field/CouponIdType.php | 43 + .../Core/Form/Type/Field/CurrencyIdType.php | 43 + .../Core/Form/Type/Field/CustomerIdType.php | 43 + .../Form/Type/Field/CustomerTitleIdType.php | 43 + .../Form/Type/Field/ExportCategoryIdType.php | 43 + .../Core/Form/Type/Field/ExportIdType.php | 43 + .../Core/Form/Type/Field/FeatureAvIdType.php | 43 + .../Core/Form/Type/Field/FeatureIdType.php | 43 + .../Form/Type/Field/FeatureProductIdType.php | 43 + .../Form/Type/Field/FeatureTemplateIdType.php | 43 + .../Core/Form/Type/Field/FolderIdType.php | 43 + .../Form/Type/Field/FormFirewallIdType.php | 43 + .../Core/Form/Type/Field/HookIdType.php | 43 + .../Form/Type/Field/ImportCategoryIdType.php | 43 + .../Core/Form/Type/Field/ImportIdType.php | 43 + .../Core/Form/Type/Field/LangIdType.php | 43 + .../Core/Form/Type/Field/MessageIdType.php | 43 + .../Core/Form/Type/Field/MetaDataIdType.php | 43 + .../Form/Type/Field/ModuleConfigIdType.php | 43 + .../Core/Form/Type/Field/ModuleHookIdType.php | 43 + .../Core/Form/Type/Field/ModuleIdType.php | 43 + .../Core/Form/Type/Field/NewsletterIdType.php | 43 + .../Form/Type/Field/OrderAddressIdType.php | 43 + .../Form/Type/Field/OrderCouponIdType.php | 43 + .../Core/Form/Type/Field/OrderIdType.php | 43 + ...OrderProductAttributeCombinationIdType.php | 43 + .../Form/Type/Field/OrderProductIdType.php | 43 + .../Form/Type/Field/OrderProductTaxIdType.php | 43 + .../Form/Type/Field/OrderStatusIdType.php | 43 + .../Field/ProductAssociatedContentIdType.php | 43 + .../Core/Form/Type/Field/ProductIdType.php | 42 + .../Type/Field/ProductSaleElementsIdType.php | 43 + .../Core/Form/Type/Field/ProfileIdType.php | 43 + .../Core/Form/Type/Field/ResourceIdType.php | 43 + .../Form/Type/Field/RewritingUrlIdType.php | 43 + .../Core/Form/Type/Field/SaleIdType.php | 43 + .../Form/Type/Field/SaleProductIdType.php | 43 + .../Core/Form/Type/Field/StateIdType.php | 43 + .../Thelia/Core/Form/Type/Field/TaxIdType.php | 43 + .../Core/Form/Type/Field/TaxRuleIdType.php | 43 + .../Core/Form/Type/Field/TemplateIdType.php | 43 + core/lib/Thelia/Core/Form/Type/ImageType.php | 45 + .../Form/Type/ProductSaleElementsType.php | 138 + .../Core/Form/Type/StandardFieldsType.php | 45 + .../Thelia/Core/Form/Type/TaxRuleI18nType.php | 58 + .../lib/Thelia/Core/Form/Type/TaxRuleType.php | 90 + core/lib/Thelia/Core/Form/Type/TheliaType.php | 52 + core/lib/Thelia/Core/Hook/BaseHook.php | 445 + core/lib/Thelia/Core/Hook/DefaultHook.php | 23 + core/lib/Thelia/Core/Hook/Fragment.php | 77 + core/lib/Thelia/Core/Hook/FragmentBag.php | 134 + core/lib/Thelia/Core/Hook/HookDefinition.php | 26 + core/lib/Thelia/Core/Hook/HookHelper.php | 539 + .../Core/HttpFoundation/JsonResponse.php | 67 + .../Thelia/Core/HttpFoundation/Request.php | 182 + .../Thelia/Core/HttpFoundation/Response.php | 43 + .../Core/HttpFoundation/Session/Session.php | 411 + core/lib/Thelia/Core/HttpKernel/Client.php | 41 + .../Exception/NotFountHttpException.php | 36 + .../Exception/RedirectException.php | 45 + .../Fragment/InlineFragmentRenderer.php | 60 + .../Core/HttpKernel/HttpCache/HttpCache.php | 58 + .../Generator/Builder/Om/EventBuilder.php | 21 + .../Builder/Om/ExtensionObjectBuilder.php | 21 + .../Builder/Om/ExtensionQueryBuilder.php | 21 + .../Om/ExtensionQueryInheritanceBuilder.php | 21 + .../Generator/Builder/Om/InterfaceBuilder.php | 21 + .../Om/Mixin/ImplementationClassTrait.php | 34 + .../Builder/Om/Mixin/StubClassTrait.php | 45 + .../Builder/Om/MultiExtendObjectBuilder.php | 21 + .../Generator/Builder/Om/ObjectBuilder.php | 21 + .../Generator/Builder/Om/QueryBuilder.php | 21 + .../Builder/Om/QueryInheritanceBuilder.php | 21 + .../Generator/Builder/Om/TableMapBuilder.php | 21 + .../Generator/Builder/ResolverBuilder.php | 17 + .../Core/Propel/Schema/SchemaCombiner.php | 412 + .../Core/Propel/Schema/SchemaLocator.php | 273 + core/lib/Thelia/Core/PropelInitService.php | 464 + .../Thelia/Core/Routing/RewritingRouter.php | 279 + .../Thelia/Core/Security/AccessManager.php | 94 + .../AdminTokenAuthenticator.php | 26 + ...AdminUsernamePasswordFormAuthenticator.php | 29 + .../Authentication/AuthenticatorInterface.php | 21 + .../CustomerTokenAuthenticator.php | 26 + ...tomerUsernamePasswordFormAuthenticator.php | 32 + .../Authentication/TokenAuthenticator.php | 45 + .../UsernamePasswordFormAuthenticator.php | 97 + .../Exception/AuthenticationException.php | 39 + .../Exception/AuthorizationException.php | 17 + .../CustomerNotConfirmedException.php | 44 + .../Security/Exception/ResourceException.php | 28 + .../TokenAuthenticationException.php | 17 + .../Exception/UsernameNotFoundException.php | 17 + .../Exception/WrongPasswordException.php | 17 + .../Core/Security/Resource/AdminResources.php | 215 + core/lib/Thelia/Core/Security/Role/Role.php | 46 + .../Core/Security/Role/RoleInterface.php | 35 + .../Thelia/Core/Security/SecurityContext.php | 262 + .../Security/Token/CookieTokenProvider.php | 43 + .../Core/Security/Token/TokenProvider.php | 41 + .../Core/Security/User/UserInterface.php | 111 + .../Security/User/UserPermissionsTrait.php | 55 + .../UserProvider/AdminTokenUserProvider.php | 28 + .../UserProvider/AdminUserProvider.php | 36 + .../CustomerTokenUserProvider.php | 28 + .../UserProvider/CustomerUserProvider.php | 28 + .../UserProvider/TokenUserProvider.php | 20 + .../UserProvider/UserProviderInterface.php | 26 + .../Core/Serializer/AbstractSerializer.php | 33 + .../Serializer/Serializer/CSVSerializer.php | 160 + .../Serializer/Serializer/JSONSerializer.php | 67 + .../Serializer/Serializer/XMLSerializer.php | 158 + .../Serializer/Serializer/YAMLSerializer.php | 53 + .../Core/Serializer/SerializerInterface.php | 89 + .../Core/Serializer/SerializerManager.php | 141 + .../Thelia/Core/Stack/ParamInitMiddleware.php | 168 + .../Thelia/Core/Stack/SessionMiddleware.php | 82 + .../Template/Assets/AssetManagerInterface.php | 71 + .../Assets/AssetResolverInterface.php | 82 + .../Template/Assets/AsseticAssetManager.php | 323 + .../Assets/Filter/LessDotPhpFilter.php | 99 + .../Element/ArraySearchLoopInterface.php | 28 + .../Core/Template/Element/BaseI18nLoop.php | 108 + .../Thelia/Core/Template/Element/BaseLoop.php | 779 + .../Exception/ElementNotFoundException.php | 17 + .../Exception/InvalidElementException.php | 17 + .../Element/Exception/LoopException.php | 35 + .../Element/Exception/SearchLoopException.php | 29 + .../Core/Template/Element/FlashMessage.php | 113 + .../Core/Template/Element/LoopResult.php | 214 + .../Core/Template/Element/LoopResultRow.php | 51 + .../Element/PropelSearchLoopInterface.php | 28 + .../Template/Element/SearchLoopInterface.php | 40 + .../Element/StandardI18nFieldsSearchTrait.php | 56 + .../Exception/InvalidDescriptorException.php | 22 + .../Exception/ResourceNotFoundException.php | 17 + .../Template/Exception/TemplateException.php | 22 + .../Thelia/Core/Template/Loop/Accessory.php | 124 + .../lib/Thelia/Core/Template/Loop/Address.php | 149 + core/lib/Thelia/Core/Template/Loop/Admin.php | 94 + .../Thelia/Core/Template/Loop/Archiver.php | 96 + core/lib/Thelia/Core/Template/Loop/Area.php | 163 + .../Core/Template/Loop/Argument/Argument.php | 220 + .../Loop/Argument/ArgumentCollection.php | 194 + .../Core/Template/Loop/AssociatedContent.php | 165 + .../Thelia/Core/Template/Loop/Attribute.php | 203 + .../Template/Loop/AttributeAvailability.php | 174 + .../Template/Loop/AttributeCombination.php | 158 + core/lib/Thelia/Core/Template/Loop/Auth.php | 101 + .../Core/Template/Loop/BaseSpecificModule.php | 122 + core/lib/Thelia/Core/Template/Loop/Brand.php | 281 + core/lib/Thelia/Core/Template/Loop/Cart.php | 150 + .../Thelia/Core/Template/Loop/Category.php | 348 + .../Core/Template/Loop/CategoryPath.php | 125 + .../Core/Template/Loop/CategoryTree.php | 167 + core/lib/Thelia/Core/Template/Loop/Config.php | 174 + .../lib/Thelia/Core/Template/Loop/Content.php | 381 + .../lib/Thelia/Core/Template/Loop/Country.php | 209 + .../Thelia/Core/Template/Loop/CountryArea.php | 145 + core/lib/Thelia/Core/Template/Loop/Coupon.php | 279 + .../Thelia/Core/Template/Loop/Currency.php | 190 + .../Thelia/Core/Template/Loop/Customer.php | 285 + .../Thelia/Core/Template/Loop/Delivery.php | 208 + .../Thelia/Core/Template/Loop/Document.php | 322 + core/lib/Thelia/Core/Template/Loop/Export.php | 41 + .../Core/Template/Loop/ExportCategory.php | 31 + .../lib/Thelia/Core/Template/Loop/Feature.php | 255 + .../Template/Loop/FeatureAvailability.php | 154 + .../Core/Template/Loop/FeatureValue.php | 164 + core/lib/Thelia/Core/Template/Loop/Feed.php | 86 + core/lib/Thelia/Core/Template/Loop/Folder.php | 307 + .../Thelia/Core/Template/Loop/FolderPath.php | 117 + .../Thelia/Core/Template/Loop/FolderTree.php | 128 + core/lib/Thelia/Core/Template/Loop/Hook.php | 197 + core/lib/Thelia/Core/Template/Loop/Image.php | 432 + core/lib/Thelia/Core/Template/Loop/Import.php | 41 + .../Core/Template/Loop/ImportCategory.php | 31 + .../Template/Loop/ImportExportCategory.php | 142 + .../Core/Template/Loop/ImportExportType.php | 200 + core/lib/Thelia/Core/Template/Loop/Lang.php | 172 + .../lib/Thelia/Core/Template/Loop/Message.php | 127 + core/lib/Thelia/Core/Template/Loop/Module.php | 355 + .../Core/Template/Loop/ModuleConfig.php | 96 + .../Thelia/Core/Template/Loop/ModuleHook.php | 175 + core/lib/Thelia/Core/Template/Loop/Order.php | 414 + .../Core/Template/Loop/OrderAddress.php | 90 + .../Thelia/Core/Template/Loop/OrderCoupon.php | 118 + .../Core/Template/Loop/OrderProduct.php | 202 + .../Loop/OrderProductAttributeCombination.php | 110 + .../Core/Template/Loop/OrderProductTax.php | 80 + .../Thelia/Core/Template/Loop/OrderStatus.php | 125 + .../lib/Thelia/Core/Template/Loop/Payment.php | 77 + .../lib/Thelia/Core/Template/Loop/Product.php | 1228 ++ .../Template/Loop/ProductSaleElements.php | 333 + .../Loop/ProductSaleElementsDocument.php | 145 + .../Loop/ProductSaleElementsImage.php | 145 + .../Core/Template/Loop/ProductTemplate.php | 94 + .../lib/Thelia/Core/Template/Loop/Profile.php | 90 + .../Thelia/Core/Template/Loop/Resource.php | 166 + core/lib/Thelia/Core/Template/Loop/Sale.php | 272 + .../Thelia/Core/Template/Loop/Serializer.php | 88 + core/lib/Thelia/Core/Template/Loop/State.php | 159 + core/lib/Thelia/Core/Template/Loop/Tax.php | 163 + .../lib/Thelia/Core/Template/Loop/TaxRule.php | 125 + .../Core/Template/Loop/TaxRuleCountry.php | 135 + .../Thelia/Core/Template/Loop/Template.php | 94 + core/lib/Thelia/Core/Template/Loop/Title.php | 88 + .../Parser/ParserAssetResolverFallback.php | 99 + .../Core/Template/Parser/ParserFallback.php | 169 + .../Template/Parser/ParserHelperFallback.php | 38 + .../Thelia/Core/Template/ParserContext.php | 336 + .../Core/Template/ParserHelperInterface.php | 28 + .../Thelia/Core/Template/ParserInterface.php | 163 + .../Template/Smarty/AbstractSmartyPlugin.php | 26 + .../Smarty/SmartyPluginDescriptor.php | 26 + .../Core/Template/TemplateDefinition.php | 227 + .../Core/Template/TemplateHelperInterface.php | 63 + .../Core/Template/TheliaTemplateHelper.php | 151 + .../Template/Validator/TemplateDescriptor.php | 249 + .../Validator/TemplateDescriptorValidator.php | 140 + .../Template/Validator/TemplateValidator.php | 209 + .../schema/template/template-1_0.xsd | 133 + core/lib/Thelia/Core/Thelia.php | 592 + .../Thelia/Core/TheliaContainerBuilder.php | 34 + core/lib/Thelia/Core/TheliaHttpKernel.php | 80 + core/lib/Thelia/Core/TheliaKernelEvents.php | 28 + .../Thelia/Core/Translation/Translator.php | 117 + core/lib/Thelia/Coupon/BaseFacade.php | 357 + core/lib/Thelia/Coupon/CouponFactory.php | 155 + core/lib/Thelia/Coupon/CouponManager.php | 422 + core/lib/Thelia/Coupon/FacadeInterface.php | 197 + .../lib/Thelia/Coupon/Type/AbstractRemove.php | 107 + .../Type/AbstractRemoveOnAttributeValues.php | 189 + .../Type/AbstractRemoveOnCategories.php | 163 + .../Coupon/Type/AbstractRemoveOnProducts.php | 173 + .../AmountAndPercentageCouponInterface.php | 66 + .../Thelia/Coupon/Type/AmountCouponTrait.php | 93 + .../lib/Thelia/Coupon/Type/CouponAbstract.php | 521 + .../Thelia/Coupon/Type/CouponInterface.php | 251 + core/lib/Thelia/Coupon/Type/FreeProduct.php | 330 + .../Coupon/Type/PercentageCouponTrait.php | 94 + .../Type/RemoveAmountOnAttributeValues.php | 64 + .../Coupon/Type/RemoveAmountOnCategories.php | 65 + .../Coupon/Type/RemoveAmountOnProducts.php | 69 + .../RemovePercentageOnAttributeValues.php | 70 + .../Type/RemovePercentageOnCategories.php | 67 + .../Type/RemovePercentageOnProducts.php | 74 + core/lib/Thelia/Coupon/Type/RemoveXAmount.php | 80 + .../lib/Thelia/Coupon/Type/RemoveXPercent.php | 77 + .../Thelia/Exception/AdminAccessDenied.php | 22 + .../Exception/CouponExpiredException.php | 40 + .../Exception/CouponNoUsageLeftException.php | 39 + .../Exception/CouponNotReleaseException.php | 38 + .../Thelia/Exception/CustomerException.php | 22 + .../Thelia/Exception/DocumentException.php | 25 + core/lib/Thelia/Exception/FileException.php | 25 + .../Exception/FileNotFoundException.php | 22 + .../Exception/FileNotReadableException.php | 22 + .../lib/Thelia/Exception/HttpUrlException.php | 22 + core/lib/Thelia/Exception/ImageException.php | 25 + .../Exception/InactiveCouponException.php | 34 + .../Thelia/Exception/InvalidCartException.php | 17 + .../Exception/InvalidConditionException.php | 38 + .../InvalidConditionOperatorException.php | 39 + .../InvalidConditionValueException.php | 39 + .../Exception/InvalidModuleException.php | 50 + .../Exception/MemberAccessException.php | 17 + .../Exception/MissingFacadeException.php | 35 + core/lib/Thelia/Exception/ModuleException.php | 28 + .../Exception/NotImplementedException.php | 26 + core/lib/Thelia/Exception/OrderException.php | 42 + .../Thelia/Exception/TaxEngineException.php | 45 + .../Exception/TheliaProcessException.php | 43 + core/lib/Thelia/Exception/TypeException.php | 28 + .../UnmatchableConditionException.php | 23 + .../Exception/UrlRewritingException.php | 32 + .../Files/Exception/ProcessFileException.php | 22 + core/lib/Thelia/Files/FileConfiguration.php | 51 + core/lib/Thelia/Files/FileManager.php | 269 + core/lib/Thelia/Files/FileModelInterface.php | 153 + .../Thelia/Files/FileModelParentInterface.php | 18 + .../Form/AddressCountryValidationTrait.php | 74 + core/lib/Thelia/Form/AddressCreateForm.php | 197 + core/lib/Thelia/Form/AddressUpdateForm.php | 34 + core/lib/Thelia/Form/AdminCreatePassword.php | 70 + core/lib/Thelia/Form/AdminLogin.php | 57 + core/lib/Thelia/Form/AdminLostPassword.php | 36 + .../Thelia/Form/AdministratorCreationForm.php | 181 + .../Form/AdministratorModificationForm.php | 103 + core/lib/Thelia/Form/Api/ApiCreateForm.php | 81 + core/lib/Thelia/Form/Api/ApiEmptyForm.php | 28 + core/lib/Thelia/Form/Api/ApiUpdateForm.php | 73 + .../Api/Category/CategoryCreationForm.php | 28 + .../Api/Category/CategoryModificationForm.php | 28 + .../Form/Api/Customer/CustomerCreateForm.php | 44 + .../Form/Api/Customer/CustomerLogin.php | 54 + .../Form/Api/Customer/CustomerUpdateForm.php | 38 + .../Form/Api/Product/ProductCreationForm.php | 57 + .../Api/Product/ProductModificationForm.php | 28 + .../ProductSaleElementsForm.php | 61 + core/lib/Thelia/Form/Area/AreaCountryForm.php | 80 + core/lib/Thelia/Form/Area/AreaCreateForm.php | 55 + .../Form/Area/AreaDeleteCountryForm.php | 79 + .../Thelia/Form/Area/AreaModificationForm.php | 45 + core/lib/Thelia/Form/Area/AreaPostageForm.php | 75 + .../Form/Area/CountryListValidationTrait.php | 64 + .../Thelia/Form/AttributeAvCreationForm.php | 49 + .../lib/Thelia/Form/AttributeCreationForm.php | 50 + .../Thelia/Form/AttributeModificationForm.php | 42 + core/lib/Thelia/Form/BaseForm.php | 468 + .../Thelia/Form/Brand/BrandCreationForm.php | 81 + .../Form/Brand/BrandDocumentModification.php | 29 + .../Form/Brand/BrandImageModification.php | 29 + .../Form/Brand/BrandModificationForm.php | 61 + core/lib/Thelia/Form/BruteforceForm.php | 37 + .../lib/Thelia/Form/Cache/AssetsFlushForm.php | 39 + core/lib/Thelia/Form/Cache/CacheFlushForm.php | 39 + .../ImagesAndDocumentsCacheFlushForm.php | 39 + core/lib/Thelia/Form/CartAdd.php | 148 + core/lib/Thelia/Form/CategoryCreationForm.php | 77 + .../Form/CategoryDocumentModification.php | 40 + .../Thelia/Form/CategoryImageModification.php | 40 + .../Thelia/Form/CategoryModificationForm.php | 79 + core/lib/Thelia/Form/ConfigCreationForm.php | 77 + .../Thelia/Form/ConfigModificationForm.php | 62 + core/lib/Thelia/Form/ConfigStoreForm.php | 270 + core/lib/Thelia/Form/ContactForm.php | 97 + core/lib/Thelia/Form/ContentCreationForm.php | 55 + .../Form/ContentDocumentModification.php | 40 + .../Thelia/Form/ContentImageModification.php | 40 + .../Thelia/Form/ContentModificationForm.php | 42 + core/lib/Thelia/Form/CountryCreationForm.php | 109 + .../Thelia/Form/CountryModificationForm.php | 62 + core/lib/Thelia/Form/CouponCode.php | 75 + core/lib/Thelia/Form/CouponCreationForm.php | 346 + core/lib/Thelia/Form/CurrencyCreationForm.php | 130 + .../Thelia/Form/CurrencyModificationForm.php | 32 + core/lib/Thelia/Form/CustomerCreateForm.php | 145 + core/lib/Thelia/Form/CustomerLogin.php | 123 + .../Thelia/Form/CustomerLostPasswordForm.php | 85 + .../Form/CustomerPasswordUpdateForm.php | 97 + .../Thelia/Form/CustomerProfileUpdateForm.php | 83 + core/lib/Thelia/Form/CustomerUpdateForm.php | 229 + core/lib/Thelia/Form/Definition/AdminForm.php | 168 + core/lib/Thelia/Form/Definition/ApiForm.php | 36 + core/lib/Thelia/Form/Definition/FrontForm.php | 37 + core/lib/Thelia/Form/EmptyForm.php | 53 + .../Exception/FormValidationException.php | 17 + .../Exception/ProductNotFoundException.php | 17 + .../Form/Exception/StockNotFoundException.php | 17 + core/lib/Thelia/Form/ExportForm.php | 126 + .../lib/Thelia/Form/FeatureAvCreationForm.php | 50 + core/lib/Thelia/Form/FeatureCreationForm.php | 60 + .../Thelia/Form/FeatureModificationForm.php | 42 + core/lib/Thelia/Form/FirewallForm.php | 122 + core/lib/Thelia/Form/FolderCreationForm.php | 56 + .../Form/FolderDocumentModification.php | 40 + .../Thelia/Form/FolderImageModification.php | 40 + .../Thelia/Form/FolderModificationForm.php | 36 + core/lib/Thelia/Form/HookCreationForm.php | 115 + core/lib/Thelia/Form/HookModificationForm.php | 63 + .../Form/Image/DocumentModification.php | 71 + .../Thelia/Form/Image/ImageModification.php | 78 + core/lib/Thelia/Form/ImportForm.php | 73 + core/lib/Thelia/Form/InstallStep3Form.php | 100 + core/lib/Thelia/Form/Lang/LangCreateForm.php | 138 + .../Form/Lang/LangDefaultBehaviorForm.php | 71 + core/lib/Thelia/Form/Lang/LangUpdateForm.php | 42 + core/lib/Thelia/Form/Lang/LangUrlEvent.php | 35 + core/lib/Thelia/Form/Lang/LangUrlForm.php | 76 + .../Form/MailingSystemModificationForm.php | 95 + core/lib/Thelia/Form/MessageCreationForm.php | 80 + .../Thelia/Form/MessageModificationForm.php | 138 + .../lib/Thelia/Form/MessageSendSampleForm.php | 41 + .../Thelia/Form/ModuleHookCreationForm.php | 245 + .../Form/ModuleHookModificationForm.php | 45 + .../Thelia/Form/ModuleImageModification.php | 29 + core/lib/Thelia/Form/ModuleInstallForm.php | 193 + .../Thelia/Form/ModuleModificationForm.php | 65 + core/lib/Thelia/Form/NewsletterForm.php | 97 + .../Thelia/Form/NewsletterUnsubscribeForm.php | 62 + core/lib/Thelia/Form/OrderDelivery.php | 85 + core/lib/Thelia/Form/OrderPayment.php | 95 + .../OrderStatus/OrderStatusCreationForm.php | 157 + .../OrderStatusModificationForm.php | 43 + core/lib/Thelia/Form/OrderUpdateAddress.php | 213 + core/lib/Thelia/Form/ProductCloneForm.php | 57 + .../Form/ProductCombinationGenerationForm.php | 97 + core/lib/Thelia/Form/ProductCreationForm.php | 121 + .../ProductDefaultSaleElementUpdateForm.php | 101 + .../Form/ProductDocumentModification.php | 40 + .../Thelia/Form/ProductImageModification.php | 40 + .../Thelia/Form/ProductModificationForm.php | 81 + .../Form/ProductSaleElementUpdateForm.php | 147 + core/lib/Thelia/Form/ProfileCreationForm.php | 70 + .../Thelia/Form/ProfileModificationForm.php | 64 + .../Form/ProfileUpdateModuleAccessForm.php | 87 + .../Form/ProfileUpdateResourceAccessForm.php | 87 + .../lib/Thelia/Form/Sale/SaleCreationForm.php | 85 + .../Thelia/Form/Sale/SaleModificationForm.php | 256 + core/lib/Thelia/Form/SeoFieldsTrait.php | 104 + core/lib/Thelia/Form/SeoForm.php | 55 + .../Form/ShippingZone/ShippingZoneAddArea.php | 74 + .../ShippingZone/ShippingZoneRemoveArea.php | 29 + .../Form/StandardDescriptionFieldsTrait.php | 120 + .../Thelia/Form/State/StateCreationForm.php | 87 + .../Form/State/StateModificationForm.php | 40 + .../Form/SystemLogConfigurationForm.php | 74 + core/lib/Thelia/Form/TaxCreationForm.php | 160 + core/lib/Thelia/Form/TaxModificationForm.php | 61 + core/lib/Thelia/Form/TaxRuleCreationForm.php | 36 + .../Thelia/Form/TaxRuleModificationForm.php | 56 + .../Thelia/Form/TaxRuleTaxListUpdateForm.php | 193 + core/lib/Thelia/Form/TemplateCreationForm.php | 51 + .../Thelia/Form/TemplateModificationForm.php | 41 + core/lib/Thelia/Handler/ExportHandler.php | 302 + core/lib/Thelia/Handler/ImportHandler.php | 310 + .../Thelia/ImportExport/AbstractHandler.php | 23 + .../ImportExport/Export/AbstractExport.php | 549 + .../Export/ArrayAbstractExport.php | 61 + .../ImportExport/Export/ExportHandler.php | 25 + .../Export/JsonFileAbstractExport.php | 114 + .../Export/PropelCollectionAbstractExport.php | 97 + .../Export/Type/ContentExport.php | 109 + .../Export/Type/CustomerExport.php | 95 + .../Export/Type/MailingExport.php | 61 + .../ImportExport/Export/Type/OrderExport.php | 180 + .../Export/Type/ProductI18nExport.php | 83 + .../Export/Type/ProductPricesExport.php | 84 + .../Export/Type/ProductSEOExport.php | 76 + .../Export/Type/ProductTaxedPricesExport.php | 89 + .../ImportExport/Import/AbstractImport.php | 224 + .../ImportExport/Import/ImportHandler.php | 25 + .../Import/Type/ProductPricesImport.php | 88 + .../Import/Type/ProductStockImport.php | 54 + core/lib/Thelia/Install/BaseInstall.php | 50 + .../Install/CheckDatabaseConnection.php | 104 + core/lib/Thelia/Install/CheckPermission.php | 395 + core/lib/Thelia/Install/Database.php | 280 + .../Exception/AlreadyInstallException.php | 22 + .../Install/Exception/InstallException.php | 21 + .../Install/Exception/UpToDateException.php | 22 + .../Install/Exception/UpdateException.php | 41 + core/lib/Thelia/Install/Update.php | 600 + .../Thelia/Log/AbstractTlogDestination.php | 99 + .../Log/Destination/TlogDestinationFile.php | 133 + .../Log/Destination/TlogDestinationHtml.php | 66 + .../TlogDestinationJavascriptConsole.php | 43 + .../Log/Destination/TlogDestinationNull.php | 38 + .../Log/Destination/TlogDestinationPopup.php | 104 + .../Log/Destination/TlogDestinationPopup.tpl | 52 + .../TlogDestinationRotatingFile.php | 119 + .../Log/Destination/TlogDestinationText.php | 43 + core/lib/Thelia/Log/Tlog.php | 722 + core/lib/Thelia/Log/TlogDestinationConfig.php | 98 + core/lib/Thelia/Mailer/MailerFactory.php | 376 + core/lib/Thelia/Model/Accessory.php | 91 + core/lib/Thelia/Model/AccessoryQuery.php | 20 + core/lib/Thelia/Model/Address.php | 104 + core/lib/Thelia/Model/AddressQuery.php | 20 + core/lib/Thelia/Model/Admin.php | 120 + core/lib/Thelia/Model/AdminLog.php | 50 + core/lib/Thelia/Model/AdminLogQuery.php | 58 + core/lib/Thelia/Model/AdminQuery.php | 20 + core/lib/Thelia/Model/Api.php | 152 + core/lib/Thelia/Model/ApiQuery.php | 19 + core/lib/Thelia/Model/Area.php | 61 + core/lib/Thelia/Model/AreaDeliveryModule.php | 9 + .../Thelia/Model/AreaDeliveryModuleQuery.php | 50 + core/lib/Thelia/Model/AreaQuery.php | 20 + core/lib/Thelia/Model/Attribute.php | 83 + core/lib/Thelia/Model/AttributeAv.php | 92 + core/lib/Thelia/Model/AttributeAvI18n.php | 11 + .../lib/Thelia/Model/AttributeAvI18nQuery.php | 20 + core/lib/Thelia/Model/AttributeAvQuery.php | 20 + .../lib/Thelia/Model/AttributeCombination.php | 9 + .../Model/AttributeCombinationQuery.php | 20 + core/lib/Thelia/Model/AttributeI18n.php | 11 + core/lib/Thelia/Model/AttributeI18nQuery.php | 20 + core/lib/Thelia/Model/AttributeQuery.php | 20 + core/lib/Thelia/Model/AttributeTemplate.php | 33 + .../Thelia/Model/AttributeTemplateQuery.php | 20 + core/lib/Thelia/Model/Brand.php | 100 + core/lib/Thelia/Model/BrandDocument.php | 130 + core/lib/Thelia/Model/BrandDocumentI18n.php | 11 + .../Thelia/Model/BrandDocumentI18nQuery.php | 20 + core/lib/Thelia/Model/BrandDocumentQuery.php | 20 + core/lib/Thelia/Model/BrandI18n.php | 25 + core/lib/Thelia/Model/BrandI18nQuery.php | 20 + core/lib/Thelia/Model/BrandImage.php | 130 + core/lib/Thelia/Model/BrandImageI18n.php | 11 + core/lib/Thelia/Model/BrandImageI18nQuery.php | 20 + core/lib/Thelia/Model/BrandImageQuery.php | 20 + core/lib/Thelia/Model/BrandQuery.php | 20 + .../Model/Breadcrumb/BrandBreadcrumbTrait.php | 42 + .../Model/Breadcrumb/BreadcrumbInterface.php | 31 + .../Breadcrumb/CatalogBreadcrumbTrait.php | 86 + .../Breadcrumb/FolderBreadcrumbTrait.php | 96 + core/lib/Thelia/Model/Cart.php | 270 + core/lib/Thelia/Model/CartItem.php | 268 + core/lib/Thelia/Model/CartItemQuery.php | 20 + core/lib/Thelia/Model/CartQuery.php | 20 + core/lib/Thelia/Model/Category.php | 233 + .../Model/CategoryAssociatedContent.php | 79 + .../Model/CategoryAssociatedContentQuery.php | 20 + core/lib/Thelia/Model/CategoryDocument.php | 140 + .../lib/Thelia/Model/CategoryDocumentI18n.php | 11 + .../Model/CategoryDocumentI18nQuery.php | 20 + .../Thelia/Model/CategoryDocumentQuery.php | 20 + core/lib/Thelia/Model/CategoryI18n.php | 24 + core/lib/Thelia/Model/CategoryI18nQuery.php | 20 + core/lib/Thelia/Model/CategoryImage.php | 140 + core/lib/Thelia/Model/CategoryImageI18n.php | 11 + .../Thelia/Model/CategoryImageI18nQuery.php | 20 + core/lib/Thelia/Model/CategoryImageQuery.php | 20 + core/lib/Thelia/Model/CategoryQuery.php | 170 + core/lib/Thelia/Model/CategoryVersion.php | 9 + .../lib/Thelia/Model/CategoryVersionQuery.php | 20 + core/lib/Thelia/Model/Config.php | 107 + core/lib/Thelia/Model/ConfigI18n.php | 11 + core/lib/Thelia/Model/ConfigI18nQuery.php | 20 + core/lib/Thelia/Model/ConfigQuery.php | 330 + core/lib/Thelia/Model/Content.php | 244 + core/lib/Thelia/Model/ContentDocument.php | 140 + core/lib/Thelia/Model/ContentDocumentI18n.php | 11 + .../Thelia/Model/ContentDocumentI18nQuery.php | 20 + .../lib/Thelia/Model/ContentDocumentQuery.php | 20 + core/lib/Thelia/Model/ContentFolder.php | 18 + core/lib/Thelia/Model/ContentFolderQuery.php | 20 + core/lib/Thelia/Model/ContentI18n.php | 24 + core/lib/Thelia/Model/ContentI18nQuery.php | 20 + core/lib/Thelia/Model/ContentImage.php | 138 + core/lib/Thelia/Model/ContentImageI18n.php | 11 + .../Thelia/Model/ContentImageI18nQuery.php | 20 + core/lib/Thelia/Model/ContentImageQuery.php | 20 + core/lib/Thelia/Model/ContentQuery.php | 63 + core/lib/Thelia/Model/ContentVersion.php | 9 + core/lib/Thelia/Model/ContentVersionQuery.php | 20 + core/lib/Thelia/Model/Country.php | 198 + core/lib/Thelia/Model/CountryArea.php | 9 + core/lib/Thelia/Model/CountryAreaQuery.php | 42 + core/lib/Thelia/Model/CountryI18n.php | 11 + core/lib/Thelia/Model/CountryI18nQuery.php | 20 + core/lib/Thelia/Model/CountryQuery.php | 20 + core/lib/Thelia/Model/Coupon.php | 315 + core/lib/Thelia/Model/CouponCountry.php | 9 + core/lib/Thelia/Model/CouponCountryQuery.php | 20 + core/lib/Thelia/Model/CouponCustomerCount.php | 9 + .../Thelia/Model/CouponCustomerCountQuery.php | 20 + core/lib/Thelia/Model/CouponI18n.php | 11 + core/lib/Thelia/Model/CouponI18nQuery.php | 20 + core/lib/Thelia/Model/CouponModule.php | 9 + core/lib/Thelia/Model/CouponModuleQuery.php | 20 + core/lib/Thelia/Model/CouponQuery.php | 20 + core/lib/Thelia/Model/CouponVersion.php | 9 + core/lib/Thelia/Model/CouponVersionQuery.php | 20 + core/lib/Thelia/Model/Currency.php | 115 + core/lib/Thelia/Model/CurrencyI18n.php | 11 + core/lib/Thelia/Model/CurrencyI18nQuery.php | 20 + core/lib/Thelia/Model/CurrencyQuery.php | 20 + core/lib/Thelia/Model/Customer.php | 445 + core/lib/Thelia/Model/CustomerQuery.php | 41 + core/lib/Thelia/Model/CustomerTitle.php | 35 + core/lib/Thelia/Model/CustomerTitleI18n.php | 11 + .../Thelia/Model/CustomerTitleI18nQuery.php | 20 + core/lib/Thelia/Model/CustomerTitleQuery.php | 20 + core/lib/Thelia/Model/CustomerVersion.php | 9 + .../lib/Thelia/Model/CustomerVersionQuery.php | 20 + .../Exception/InvalidArgumentException.php | 16 + .../Thelia/Model/Exception/ModelException.php | 17 + core/lib/Thelia/Model/Export.php | 110 + core/lib/Thelia/Model/ExportCategory.php | 26 + core/lib/Thelia/Model/ExportCategoryI18n.php | 11 + .../Thelia/Model/ExportCategoryI18nQuery.php | 20 + core/lib/Thelia/Model/ExportCategoryQuery.php | 20 + core/lib/Thelia/Model/ExportI18n.php | 11 + core/lib/Thelia/Model/ExportI18nQuery.php | 20 + core/lib/Thelia/Model/ExportQuery.php | 20 + core/lib/Thelia/Model/Feature.php | 83 + core/lib/Thelia/Model/FeatureAv.php | 92 + core/lib/Thelia/Model/FeatureAvI18n.php | 11 + core/lib/Thelia/Model/FeatureAvI18nQuery.php | 20 + core/lib/Thelia/Model/FeatureAvQuery.php | 20 + core/lib/Thelia/Model/FeatureI18n.php | 11 + core/lib/Thelia/Model/FeatureI18nQuery.php | 20 + core/lib/Thelia/Model/FeatureProduct.php | 114 + core/lib/Thelia/Model/FeatureProductQuery.php | 81 + core/lib/Thelia/Model/FeatureQuery.php | 20 + core/lib/Thelia/Model/FeatureTemplate.php | 34 + .../lib/Thelia/Model/FeatureTemplateQuery.php | 20 + core/lib/Thelia/Model/Folder.php | 168 + core/lib/Thelia/Model/FolderDocument.php | 137 + core/lib/Thelia/Model/FolderDocumentI18n.php | 11 + .../Thelia/Model/FolderDocumentI18nQuery.php | 20 + core/lib/Thelia/Model/FolderDocumentQuery.php | 20 + core/lib/Thelia/Model/FolderI18n.php | 24 + core/lib/Thelia/Model/FolderI18nQuery.php | 20 + core/lib/Thelia/Model/FolderImage.php | 137 + core/lib/Thelia/Model/FolderImageI18n.php | 11 + .../lib/Thelia/Model/FolderImageI18nQuery.php | 20 + core/lib/Thelia/Model/FolderImageQuery.php | 20 + core/lib/Thelia/Model/FolderQuery.php | 97 + core/lib/Thelia/Model/FolderVersion.php | 9 + core/lib/Thelia/Model/FolderVersionQuery.php | 20 + core/lib/Thelia/Model/FormFirewall.php | 26 + core/lib/Thelia/Model/FormFirewallQuery.php | 20 + core/lib/Thelia/Model/Hook.php | 9 + core/lib/Thelia/Model/HookI18n.php | 11 + core/lib/Thelia/Model/HookI18nQuery.php | 20 + core/lib/Thelia/Model/HookQuery.php | 20 + core/lib/Thelia/Model/IgnoredModuleHook.php | 9 + .../Thelia/Model/IgnoredModuleHookQuery.php | 19 + core/lib/Thelia/Model/Import.php | 31 + core/lib/Thelia/Model/ImportCategory.php | 26 + core/lib/Thelia/Model/ImportCategoryI18n.php | 11 + .../Thelia/Model/ImportCategoryI18nQuery.php | 20 + core/lib/Thelia/Model/ImportCategoryQuery.php | 20 + core/lib/Thelia/Model/ImportI18n.php | 11 + core/lib/Thelia/Model/ImportI18nQuery.php | 20 + core/lib/Thelia/Model/ImportQuery.php | 20 + core/lib/Thelia/Model/Lang.php | 130 + core/lib/Thelia/Model/LangQuery.php | 29 + core/lib/Thelia/Model/Message.php | 205 + core/lib/Thelia/Model/MessageI18n.php | 11 + core/lib/Thelia/Model/MessageI18nQuery.php | 20 + core/lib/Thelia/Model/MessageQuery.php | 35 + core/lib/Thelia/Model/MessageVersion.php | 9 + core/lib/Thelia/Model/MessageVersionQuery.php | 20 + core/lib/Thelia/Model/MetaData.php | 59 + core/lib/Thelia/Model/MetaDataQuery.php | 102 + core/lib/Thelia/Model/Module.php | 338 + core/lib/Thelia/Model/ModuleConfig.php | 9 + core/lib/Thelia/Model/ModuleConfigI18n.php | 11 + .../Thelia/Model/ModuleConfigI18nQuery.php | 20 + core/lib/Thelia/Model/ModuleConfigQuery.php | 113 + core/lib/Thelia/Model/ModuleHook.php | 22 + core/lib/Thelia/Model/ModuleHookQuery.php | 20 + core/lib/Thelia/Model/ModuleI18n.php | 11 + core/lib/Thelia/Model/ModuleI18nQuery.php | 20 + core/lib/Thelia/Model/ModuleImage.php | 130 + core/lib/Thelia/Model/ModuleImageI18n.php | 11 + .../lib/Thelia/Model/ModuleImageI18nQuery.php | 20 + core/lib/Thelia/Model/ModuleImageQuery.php | 20 + core/lib/Thelia/Model/ModuleQuery.php | 97 + core/lib/Thelia/Model/Newsletter.php | 9 + core/lib/Thelia/Model/NewsletterQuery.php | 20 + core/lib/Thelia/Model/Order.php | 539 + core/lib/Thelia/Model/OrderAddress.php | 9 + core/lib/Thelia/Model/OrderAddressQuery.php | 20 + core/lib/Thelia/Model/OrderCoupon.php | 27 + core/lib/Thelia/Model/OrderCouponCountry.php | 9 + .../Thelia/Model/OrderCouponCountryQuery.php | 20 + core/lib/Thelia/Model/OrderCouponModule.php | 9 + .../Thelia/Model/OrderCouponModuleQuery.php | 20 + core/lib/Thelia/Model/OrderCouponQuery.php | 20 + core/lib/Thelia/Model/OrderPostage.php | 104 + core/lib/Thelia/Model/OrderProduct.php | 65 + .../OrderProductAttributeCombination.php | 9 + .../OrderProductAttributeCombinationQuery.php | 20 + core/lib/Thelia/Model/OrderProductQuery.php | 72 + core/lib/Thelia/Model/OrderProductTax.php | 9 + .../lib/Thelia/Model/OrderProductTaxQuery.php | 20 + core/lib/Thelia/Model/OrderQuery.php | 187 + core/lib/Thelia/Model/OrderStatus.php | 123 + core/lib/Thelia/Model/OrderStatusI18n.php | 11 + .../lib/Thelia/Model/OrderStatusI18nQuery.php | 20 + core/lib/Thelia/Model/OrderStatusQuery.php | 174 + core/lib/Thelia/Model/OrderVersion.php | 9 + core/lib/Thelia/Model/OrderVersionQuery.php | 20 + core/lib/Thelia/Model/PickupLocation.php | 189 + .../Thelia/Model/PickupLocationAddress.php | 358 + core/lib/Thelia/Model/Product.php | 376 + .../Thelia/Model/ProductAssociatedContent.php | 91 + .../Model/ProductAssociatedContentQuery.php | 20 + core/lib/Thelia/Model/ProductCategory.php | 18 + .../lib/Thelia/Model/ProductCategoryQuery.php | 20 + core/lib/Thelia/Model/ProductDocument.php | 140 + core/lib/Thelia/Model/ProductDocumentI18n.php | 11 + .../Thelia/Model/ProductDocumentI18nQuery.php | 20 + .../lib/Thelia/Model/ProductDocumentQuery.php | 20 + core/lib/Thelia/Model/ProductI18n.php | 24 + core/lib/Thelia/Model/ProductI18nQuery.php | 20 + core/lib/Thelia/Model/ProductImage.php | 139 + core/lib/Thelia/Model/ProductImageI18n.php | 11 + .../Thelia/Model/ProductImageI18nQuery.php | 20 + core/lib/Thelia/Model/ProductImageQuery.php | 20 + core/lib/Thelia/Model/ProductPrice.php | 9 + core/lib/Thelia/Model/ProductPriceQuery.php | 20 + core/lib/Thelia/Model/ProductQuery.php | 62 + core/lib/Thelia/Model/ProductSaleElements.php | 131 + .../ProductSaleElementsProductDocument.php | 9 + ...roductSaleElementsProductDocumentQuery.php | 19 + .../Model/ProductSaleElementsProductImage.php | 9 + .../ProductSaleElementsProductImageQuery.php | 19 + .../Thelia/Model/ProductSaleElementsQuery.php | 20 + core/lib/Thelia/Model/ProductVersion.php | 9 + core/lib/Thelia/Model/ProductVersionQuery.php | 20 + core/lib/Thelia/Model/Profile.php | 10 + core/lib/Thelia/Model/ProfileI18n.php | 11 + core/lib/Thelia/Model/ProfileI18nQuery.php | 20 + core/lib/Thelia/Model/ProfileModule.php | 9 + core/lib/Thelia/Model/ProfileModuleQuery.php | 20 + core/lib/Thelia/Model/ProfileQuery.php | 32 + core/lib/Thelia/Model/ProfileResource.php | 9 + .../lib/Thelia/Model/ProfileResourceQuery.php | 20 + core/lib/Thelia/Model/Resource.php | 9 + core/lib/Thelia/Model/ResourceI18n.php | 11 + core/lib/Thelia/Model/ResourceI18nQuery.php | 20 + core/lib/Thelia/Model/ResourceQuery.php | 20 + core/lib/Thelia/Model/RewritingArgument.php | 9 + .../Thelia/Model/RewritingArgumentQuery.php | 20 + core/lib/Thelia/Model/RewritingUrl.php | 27 + core/lib/Thelia/Model/RewritingUrlQuery.php | 124 + core/lib/Thelia/Model/Sale.php | 160 + core/lib/Thelia/Model/SaleI18n.php | 11 + core/lib/Thelia/Model/SaleI18nQuery.php | 20 + core/lib/Thelia/Model/SaleOffsetCurrency.php | 9 + .../Thelia/Model/SaleOffsetCurrencyQuery.php | 20 + core/lib/Thelia/Model/SaleProduct.php | 9 + core/lib/Thelia/Model/SaleProductQuery.php | 20 + core/lib/Thelia/Model/SaleQuery.php | 20 + core/lib/Thelia/Model/State.php | 61 + core/lib/Thelia/Model/StateI18n.php | 9 + core/lib/Thelia/Model/StateI18nQuery.php | 19 + core/lib/Thelia/Model/StateQuery.php | 19 + core/lib/Thelia/Model/Tax.php | 89 + core/lib/Thelia/Model/TaxI18n.php | 11 + core/lib/Thelia/Model/TaxI18nQuery.php | 20 + core/lib/Thelia/Model/TaxQuery.php | 20 + core/lib/Thelia/Model/TaxRule.php | 38 + core/lib/Thelia/Model/TaxRuleCountry.php | 9 + core/lib/Thelia/Model/TaxRuleCountryQuery.php | 20 + core/lib/Thelia/Model/TaxRuleI18n.php | 11 + core/lib/Thelia/Model/TaxRuleI18nQuery.php | 20 + core/lib/Thelia/Model/TaxRuleQuery.php | 73 + core/lib/Thelia/Model/Template.php | 79 + core/lib/Thelia/Model/TemplateI18n.php | 11 + core/lib/Thelia/Model/TemplateI18nQuery.php | 20 + core/lib/Thelia/Model/TemplateQuery.php | 20 + .../Model/Tools/I18nTimestampableTrait.php | 48 + .../Thelia/Model/Tools/ModelCriteriaTools.php | 273 + .../Model/Tools/ModelEventDispatcherTrait.php | 69 + .../Model/Tools/PositionManagementTrait.php | 216 + .../Thelia/Model/Tools/ProductPriceTools.php | 59 + .../Thelia/Model/Tools/UrlRewritingTrait.php | 223 + .../Module/AbstractAdminResourcesCompiler.php | 56 + .../Thelia/Module/AbstractDeliveryModule.php | 57 + .../AbstractDeliveryModuleWithState.php | 58 + .../Thelia/Module/AbstractPaymentModule.php | 117 + core/lib/Thelia/Module/BaseModule.php | 809 + .../lib/Thelia/Module/BaseModuleInterface.php | 250 + .../Module/BasePaymentModuleController.php | 274 + .../Thelia/Module/DeliveryModuleInterface.php | 51 + .../DeliveryModuleWithStateInterface.php | 54 + .../Module/Exception/DeliveryException.php | 17 + .../Exception/InvalidXmlDocumentException.php | 22 + .../Module/ModuleDescriptorValidator.php | 132 + core/lib/Thelia/Module/ModuleManagement.php | 225 + .../Thelia/Module/PaymentModuleInterface.php | 53 + .../Module/Validator/ModuleDefinition.php | 249 + .../Module/Validator/ModuleValidator.php | 532 + .../Module/schema/module/module-2_1.xsd | 159 + .../Module/schema/module/module-2_2.xsd | 187 + .../Thelia/Module/schema/module/module.xsd | 110 + .../Thelia/Rewriting/RewritingResolver.php | 83 + .../Thelia/Rewriting/RewritingRetriever.php | 104 + core/lib/Thelia/TaxEngine/BaseTaxType.php | 130 + core/lib/Thelia/TaxEngine/Calculator.php | 403 + .../TaxEngine/OrderProductTaxCollection.php | 116 + core/lib/Thelia/TaxEngine/TaxEngine.php | 174 + .../TaxType/FeatureFixAmountTaxType.php | 88 + .../TaxEngine/TaxType/FixAmountTaxType.php | 54 + .../TaxEngine/TaxType/PricePercentTaxType.php | 54 + .../TaxTypeRequirementDefinition.php | 71 + core/lib/Thelia/Tools/AddressFormat.php | 231 + core/lib/Thelia/Tools/DateTimeFormat.php | 54 + .../Tools/FileDownload/FileDownloader.php | 145 + .../FileDownload/FileDownloaderAwareTrait.php | 47 + .../FileDownload/FileDownloaderInterface.php | 43 + core/lib/Thelia/Tools/I18n.php | 142 + core/lib/Thelia/Tools/Image.php | 32 + core/lib/Thelia/Tools/MoneyFormat.php | 115 + core/lib/Thelia/Tools/NumberFormat.php | 65 + core/lib/Thelia/Tools/Password.php | 54 + core/lib/Thelia/Tools/RememberMeTrait.php | 62 + core/lib/Thelia/Tools/Rest/ResponseRest.php | 97 + core/lib/Thelia/Tools/TokenProvider.php | 156 + core/lib/Thelia/Tools/URL.php | 357 + .../Version/Constraints/BaseConstraint.php | 73 + .../Version/Constraints/ConstraintEqual.php | 26 + .../Version/Constraints/ConstraintGreater.php | 30 + .../Constraints/ConstraintInterface.php | 38 + .../Version/Constraints/ConstraintLower.php | 30 + .../Constraints/ConstraintNearlyEqual.php | 35 + core/lib/Thelia/Tools/Version/Version.php | 134 + .../Thelia/Type/AlphaNumStringListType.php | 53 + core/lib/Thelia/Type/AlphaNumStringType.php | 47 + core/lib/Thelia/Type/AnyListType.php | 46 + core/lib/Thelia/Type/AnyType.php | 47 + core/lib/Thelia/Type/BaseType.php | 49 + core/lib/Thelia/Type/BooleanOrBothType.php | 53 + core/lib/Thelia/Type/BooleanType.php | 47 + core/lib/Thelia/Type/EnumListType.php | 89 + core/lib/Thelia/Type/EnumType.php | 56 + .../lib/Thelia/Type/FloatToFloatArrayType.php | 57 + core/lib/Thelia/Type/FloatType.php | 47 + core/lib/Thelia/Type/IntListType.php | 53 + .../Thelia/Type/IntToCombinedIntsListType.php | 127 + .../Type/IntToCombinedStringsListType.php | 173 + core/lib/Thelia/Type/IntType.php | 47 + core/lib/Thelia/Type/JsonType.php | 49 + core/lib/Thelia/Type/ModelType.php | 66 + core/lib/Thelia/Type/ModelValidIdType.php | 88 + core/lib/Thelia/Type/TypeCollection.php | 142 + core/lib/Thelia/Type/TypeInterface.php | 32 + core/local/modules/HookTest/Config/config.xml | 55 + core/local/modules/HookTest/Config/module.xml | 18 + .../local/modules/HookTest/Hook/FrontHook.php | 170 + core/local/modules/HookTest/HookTest.php | 21 + core/local/modules/HookTest/I18n/en_US.php | 8 + core/local/modules/HookTest/I18n/fr_FR.php | 7 + .../I18n/frontOffice/default/en_US.php | 5 + .../I18n/frontOffice/default/fr_FR.php | 4 + core/local/modules/HookTest/composer.json | 10 + .../frontOffice/default/assets/css/print.css | 1 + .../frontOffice/default/assets/css/style1.css | 1 + .../frontOffice/default/assets/css/style2.css | 1 + .../frontOffice/default/assets/css/style3.css | 1 + .../frontOffice/default/assets/css/styles.css | 1 + .../frontOffice/default/assets/js/script.js | 1 + .../templates/frontOffice/default/dump.txt | 2 + .../default/main-navbar-secondary.html | 71 + .../frontOffice/default/override-assets.html | 13 + .../frontOffice/default/override1.html | 1 + .../frontOffice/default/override2.html | 1 + .../frontOffice/default/override3.html | 1 + .../templates/frontOffice/default/render.html | 2 + .../hooktest/assets/css/style2.css | 1 + .../frontOffice/hooktest/override2.html | 1 + .../frontOffice/hooktest/composer.json | 10 + .../hooktest/includes/single-product.html | 110 + .../templates/frontOffice/hooktest/index.html | 24 + .../templates/frontOffice/hooktest/layout.tpl | 110 + .../modules/HookTest/assets/css/style3.css | 1 + .../hooktest/modules/HookTest/override3.html | 1 + docker-compose.yml | 36 + index.html | 11 + local/.gitkeep | 0 local/I18n/.gitkeep | 0 local/backup/.gitkeep | 0 local/config/.gitkeep | 0 local/config/.htaccess | 2 + local/config/Readme.md | 35 + local/config/composer.json | 10 + local/config/database.yml.sample | 6 + local/config/schema.xml | 1939 +++ local/media/.gitkeep | 0 local/modules/Carousel/CHANGELOG.md | 6 + local/modules/Carousel/Carousel.php | 109 + local/modules/Carousel/Config/config.xml | 25 + local/modules/Carousel/Config/module.xml | 24 + local/modules/Carousel/Config/routing.xml | 42 + local/modules/Carousel/Config/schema.xml | 29 + local/modules/Carousel/Config/sql/destroy.sql | 6 + local/modules/Carousel/Config/thelia.sql | 51 + .../modules/Carousel/Config/update/2.4.0.sql | 1 + .../Controller/ConfigurationController.php | 189 + .../Carousel/Form/CarouselImageForm.php | 56 + .../Carousel/Form/CarouselUpdateForm.php | 228 + local/modules/Carousel/Hook/BackHook.php | 48 + .../I18n/backOffice/default/de_DE.php | 14 + .../I18n/backOffice/default/en_US.php | 15 + .../I18n/backOffice/default/fr_FR.php | 15 + .../I18n/backOffice/default/ru_RU.php | 14 + .../I18n/backOffice/default/tr_TR.php | 14 + local/modules/Carousel/I18n/de_DE.php | 20 + local/modules/Carousel/I18n/en_US.php | 22 + local/modules/Carousel/I18n/fr_FR.php | 27 + local/modules/Carousel/I18n/it_IT.php | 11 + local/modules/Carousel/I18n/ru_RU.php | 21 + local/modules/Carousel/I18n/tr_TR.php | 20 + local/modules/Carousel/Loop/CarouselLoop.php | 242 + local/modules/Carousel/Model/Carousel.php | 113 + local/modules/Carousel/Model/CarouselI18n.php | 10 + .../Carousel/Model/CarouselI18nQuery.php | 21 + .../modules/Carousel/Model/CarouselQuery.php | 25 + local/modules/Carousel/Readme.md | 69 + local/modules/Carousel/composer.json | 11 + .../default/assets/js/module-configuration.js | 6 + .../default/module_configuration.html | 179 + .../frontOffice/default/carousel.html | 24 + local/modules/Cheque/Cheque.php | 74 + local/modules/Cheque/Config/config.xml | 25 + local/modules/Cheque/Config/module.xml | 25 + local/modules/Cheque/Config/routing.xml | 9 + local/modules/Cheque/Config/setup.sql | 32 + .../Cheque/Controller/ConfigureController.php | 98 + .../modules/Cheque/Form/ConfigurationForm.php | 90 + local/modules/Cheque/Hook/HookManager.php | 34 + .../Cheque/I18n/backOffice/default/de_DE.php | 5 + .../Cheque/I18n/backOffice/default/en_US.php | 5 + .../Cheque/I18n/backOffice/default/fr_FR.php | 5 + .../Cheque/I18n/backOffice/default/ru_RU.php | 5 + .../Cheque/I18n/backOffice/default/tr_TR.php | 5 + local/modules/Cheque/I18n/de_DE.php | 11 + local/modules/Cheque/I18n/en_US.php | 11 + local/modules/Cheque/I18n/fr_FR.php | 11 + .../Cheque/I18n/frontOffice/default/de_DE.php | 6 + .../Cheque/I18n/frontOffice/default/en_US.php | 6 + .../Cheque/I18n/frontOffice/default/fr_FR.php | 6 + .../Cheque/I18n/frontOffice/default/ru_RU.php | 6 + .../Cheque/I18n/frontOffice/default/tr_TR.php | 6 + local/modules/Cheque/I18n/ru_RU.php | 11 + local/modules/Cheque/I18n/tr_TR.php | 11 + local/modules/Cheque/LICENSE.txt | 165 + .../Listener/SendPaymentConfirmationEmail.php | 85 + local/modules/Cheque/composer.json | 11 + local/modules/Cheque/images/cheque.png | Bin 0 -> 24812 bytes .../default/module_configuration.html | 55 + .../order-placed.additional-payment-info.html | 21 + local/modules/Colissimo/Colissimo.php | 180 + local/modules/Colissimo/Config/config.xml | 40 + local/modules/Colissimo/Config/module.xml | 18 + local/modules/Colissimo/Config/prices.json | 64 + local/modules/Colissimo/Config/routing.xml | 21 + local/modules/Colissimo/Config/thelia.sql | 32 + .../Colissimo/Controller/Configuration.php | 77 + .../Colissimo/Controller/EditPrices.php | 84 + local/modules/Colissimo/Controller/Export.php | 166 + .../Colissimo/Controller/FreeShipping.php | 62 + .../EventListener/AreaDeletedListener.php | 53 + .../modules/Colissimo/Form/Configuration.php | 59 + local/modules/Colissimo/Form/Export.php | 122 + local/modules/Colissimo/Form/FreeShipping.php | 62 + local/modules/Colissimo/Hook/HookManager.php | 31 + .../I18n/backOffice/default/de_DE.php | 25 + .../I18n/backOffice/default/en_US.php | 36 + .../I18n/backOffice/default/fr_FR.php | 37 + .../I18n/backOffice/default/it_IT.php | 13 + .../I18n/backOffice/default/ru_RU.php | 38 + .../I18n/backOffice/default/tr_TR.php | 34 + local/modules/Colissimo/I18n/de_DE.php | 14 + local/modules/Colissimo/I18n/en_US.php | 14 + local/modules/Colissimo/I18n/fr_FR.php | 14 + local/modules/Colissimo/I18n/ru_RU.php | 15 + local/modules/Colissimo/I18n/tr_TR.php | 14 + local/modules/Colissimo/LICENSE.txt | 165 + local/modules/Colissimo/Listener/SendMail.php | 104 + .../Colissimo/Loop/CheckRightsLoop.php | 100 + local/modules/Colissimo/Loop/NotSendLoop.php | 74 + local/modules/Colissimo/Loop/Price.php | 73 + .../Colissimo/Model/ColissimoQuery.php | 66 + .../Config/Base/ColissimoConfigValue.php | 25 + .../Model/Config/ColissimoConfigValue.php | 24 + local/modules/Colissimo/THELIA_INET.FMT | 23 + local/modules/Colissimo/composer.json | 11 + .../documentation/TarifsAvril2013.pdf | Bin 0 -> 184810 bytes .../Colissimo/documentation/readme.txt | 3 + .../assets/js/module-configuration-js.html | 36 + .../default/module_configuration.html | 316 + local/modules/FreeOrder/Config/config.xml | 6 + local/modules/FreeOrder/Config/module.xml | 27 + local/modules/FreeOrder/FreeOrder.php | 41 + local/modules/FreeOrder/LICENSE.txt | 165 + local/modules/FreeOrder/Readme.md | 25 + local/modules/FreeOrder/composer.json | 11 + local/modules/Front/Config/config.xml | 26 + local/modules/Front/Config/front.xml | 276 + local/modules/Front/Config/module.xml | 29 + .../Front/Controller/AddressController.php | 273 + .../Front/Controller/CartController.php | 250 + .../Front/Controller/ContactController.php | 90 + .../Front/Controller/CouponController.php | 168 + .../Front/Controller/CustomerController.php | 613 + .../Front/Controller/FeedController.php | 202 + .../Front/Controller/NewsletterController.php | 164 + .../Front/Controller/OrderController.php | 605 + .../Front/Controller/SitemapController.php | 152 + local/modules/Front/Front.php | 31 + local/modules/Front/I18n/de_DE.php | 22 + local/modules/Front/I18n/en_US.php | 24 + local/modules/Front/I18n/fr_FR.php | 23 + local/modules/Front/I18n/it_IT.php | 7 + local/modules/Front/I18n/ru_RU.php | 25 + local/modules/Front/I18n/tr_TR.php | 22 + local/modules/Front/LICENSE.txt | 165 + local/modules/Front/composer.json | 11 + local/modules/HookAdminHome/Config/config.xml | 43 + local/modules/HookAdminHome/Config/module.xml | 32 + .../modules/HookAdminHome/Config/routing.xml | 28 + .../Controller/ConfigurationController.php | 72 + .../Controller/HomeController.php | 156 + .../HookAdminHome/Form/Configuration.php | 93 + .../modules/HookAdminHome/Hook/AdminHook.php | 85 + .../HookAdminHome/Hook/HookAdminManager.php | 15 + local/modules/HookAdminHome/HookAdminHome.php | 46 + local/modules/HookAdminHome/I18n/ar_SA.php | 5 + .../I18n/backOffice/default/ar_SA.php | 11 + .../I18n/backOffice/default/cs_CZ.php | 31 + .../I18n/backOffice/default/de_DE.php | 30 + .../I18n/backOffice/default/en_US.php | 33 + .../I18n/backOffice/default/es_ES.php | 31 + .../I18n/backOffice/default/fr_FR.php | 34 + .../I18n/backOffice/default/it_IT.php | 32 + .../I18n/backOffice/default/pt_BR.php | 6 + .../I18n/backOffice/default/ru_RU.php | 31 + .../I18n/backOffice/default/tr_TR.php | 31 + local/modules/HookAdminHome/I18n/cs_CZ.php | 7 + local/modules/HookAdminHome/I18n/de_DE.php | 7 + local/modules/HookAdminHome/I18n/en_US.php | 7 + local/modules/HookAdminHome/I18n/es_ES.php | 6 + local/modules/HookAdminHome/I18n/fr_FR.php | 8 + local/modules/HookAdminHome/I18n/id_ID.php | 5 + local/modules/HookAdminHome/I18n/it_IT.php | 6 + local/modules/HookAdminHome/I18n/ru_RU.php | 7 + local/modules/HookAdminHome/I18n/tr_TR.php | 7 + local/modules/HookAdminHome/LICENSE.txt | 165 + local/modules/HookAdminHome/composer.json | 11 + .../backOffice/default/admin-home-config.html | 87 + .../default/ajax/thelia_news_feed.html | 29 + .../backOffice/default/assets/css/home.css | 1 + .../backOffice/default/assets/less/home.less | 45 + .../backOffice/default/block-information.html | 59 + .../default/block-month-sales-statistics.html | 48 + .../backOffice/default/block-news-js.html | 7 + .../backOffice/default/block-news.html | 5 + .../default/block-sales-statistics.html | 100 + .../default/block-statistics-js.html | 207 + .../backOffice/default/block-statistics.html | 34 + .../default/block-thelia-information.html | 25 + .../default/hook-admin-home-config.html | 1 + local/modules/HookAnalytics/Config/config.xml | 21 + local/modules/HookAnalytics/Config/module.xml | 24 + .../modules/HookAnalytics/Config/routing.xml | 10 + .../Controller/Configuration.php | 57 + .../HookAnalytics/Form/Configuration.php | 54 + .../modules/HookAnalytics/Hook/FrontHook.php | 33 + local/modules/HookAnalytics/HookAnalytics.php | 20 + .../I18n/backOffice/default/de_DE.php | 7 + .../I18n/backOffice/default/en_US.php | 7 + .../I18n/backOffice/default/fr_FR.php | 7 + .../I18n/backOffice/default/it_IT.php | 5 + .../I18n/backOffice/default/ru_RU.php | 7 + .../I18n/backOffice/default/tr_TR.php | 7 + local/modules/HookAnalytics/I18n/de_DE.php | 5 + local/modules/HookAnalytics/I18n/en_US.php | 5 + local/modules/HookAnalytics/I18n/fr_FR.php | 5 + .../I18n/frontOffice/default/de_DE.php | 10 + .../I18n/frontOffice/default/en_US.php | 10 + .../I18n/frontOffice/default/fr_FR.php | 10 + .../I18n/frontOffice/default/it_IT.php | 10 + .../I18n/frontOffice/default/ru_RU.php | 10 + .../I18n/frontOffice/default/tr_TR.php | 10 + local/modules/HookAnalytics/I18n/it_IT.php | 5 + local/modules/HookAnalytics/I18n/ru_RU.php | 5 + local/modules/HookAnalytics/I18n/tr_TR.php | 5 + local/modules/HookAnalytics/LICENSE.txt | 165 + local/modules/HookAnalytics/composer.json | 11 + .../default/assets/js/module-configuration.js | 29 + .../default/module_configuration.html | 52 + local/modules/HookCart/Config/config.xml | 15 + local/modules/HookCart/Config/module.xml | 24 + local/modules/HookCart/HookCart.php | 20 + .../I18n/frontOffice/default/de_DE.php | 9 + .../I18n/frontOffice/default/en_US.php | 9 + .../I18n/frontOffice/default/fr_FR.php | 9 + .../I18n/frontOffice/default/it_IT.php | 9 + .../I18n/frontOffice/default/ru_RU.php | 9 + .../I18n/frontOffice/default/tr_TR.php | 9 + local/modules/HookCart/LICENSE.txt | 165 + local/modules/HookCart/composer.json | 11 + .../frontOffice/default/assets/css/styles.css | 0 .../default/main-navbar-secondary.html | 3 + .../frontOffice/default/mini-cart.html | 73 + local/modules/HookContact/Config/config.xml | 13 + local/modules/HookContact/Config/module.xml | 24 + local/modules/HookContact/Hook/FrontHook.php | 39 + local/modules/HookContact/HookContact.php | 20 + local/modules/HookContact/I18n/de_DE.php | 5 + local/modules/HookContact/I18n/en_US.php | 5 + local/modules/HookContact/I18n/fr_FR.php | 5 + .../I18n/frontOffice/default/fr_FR.php | 5 + .../I18n/frontOffice/default/ru_RU.php | 5 + local/modules/HookContact/I18n/it_IT.php | 5 + local/modules/HookContact/I18n/ru_RU.php | 5 + local/modules/HookContact/I18n/tr_TR.php | 5 + local/modules/HookContact/LICENSE.txt | 165 + local/modules/HookContact/composer.json | 11 + .../frontOffice/default/main-footer-body.html | 25 + local/modules/HookCurrency/Config/config.xml | 13 + local/modules/HookCurrency/Config/module.xml | 24 + local/modules/HookCurrency/HookCurrency.php | 20 + local/modules/HookCurrency/LICENSE.txt | 165 + local/modules/HookCurrency/composer.json | 11 + .../default/main-navbar-secondary.html | 10 + local/modules/HookCustomer/Config/config.xml | 14 + local/modules/HookCustomer/Config/module.xml | 24 + local/modules/HookCustomer/HookCustomer.php | 20 + .../I18n/frontOffice/default/de_DE.php | 13 + .../I18n/frontOffice/default/en_US.php | 13 + .../I18n/frontOffice/default/fr_FR.php | 13 + .../I18n/frontOffice/default/it_IT.php | 13 + .../I18n/frontOffice/default/ru_RU.php | 13 + .../I18n/frontOffice/default/tr_TR.php | 13 + local/modules/HookCustomer/LICENSE.txt | 165 + local/modules/HookCustomer/composer.json | 11 + .../frontOffice/default/assets/css/styles.css | 0 .../default/main-navbar-secondary.html | 43 + local/modules/HookLang/Config/config.xml | 13 + local/modules/HookLang/Config/module.xml | 24 + local/modules/HookLang/HookLang.php | 20 + local/modules/HookLang/LICENSE.txt | 165 + local/modules/HookLang/composer.json | 11 + .../default/main-navbar-secondary.html | 10 + local/modules/HookLinks/Config/config.xml | 13 + local/modules/HookLinks/Config/module.xml | 24 + local/modules/HookLinks/Hook/FrontHook.php | 38 + local/modules/HookLinks/HookLinks.php | 20 + local/modules/HookLinks/I18n/de_DE.php | 5 + local/modules/HookLinks/I18n/en_US.php | 5 + local/modules/HookLinks/I18n/fr_FR.php | 5 + .../I18n/frontOffice/default/de_DE.php | 10 + .../I18n/frontOffice/default/en_US.php | 10 + .../I18n/frontOffice/default/fr_FR.php | 10 + .../I18n/frontOffice/default/it_IT.php | 10 + .../I18n/frontOffice/default/ru_RU.php | 10 + .../I18n/frontOffice/default/tr_TR.php | 10 + local/modules/HookLinks/I18n/it_IT.php | 5 + local/modules/HookLinks/I18n/ru_RU.php | 5 + local/modules/HookLinks/I18n/tr_TR.php | 5 + local/modules/HookLinks/LICENSE.txt | 165 + local/modules/HookLinks/composer.json | 11 + .../frontOffice/default/main-footer-body.html | 15 + .../modules/HookNavigation/Config/config.xml | 17 + .../modules/HookNavigation/Config/module.xml | 24 + .../modules/HookNavigation/Config/routing.xml | 9 + .../HookNavigationConfigController.php | 75 + .../Form/HookNavigationConfigForm.php | 55 + .../modules/HookNavigation/Hook/FrontHook.php | 51 + .../modules/HookNavigation/HookNavigation.php | 24 + .../I18n/backOffice/default/de_DE.php | 11 + .../I18n/backOffice/default/en_US.php | 10 + .../I18n/backOffice/default/fr_FR.php | 10 + .../I18n/backOffice/default/it_IT.php | 7 + .../I18n/backOffice/default/ru_RU.php | 10 + .../I18n/backOffice/default/tr_TR.php | 11 + local/modules/HookNavigation/I18n/en_US.php | 8 + local/modules/HookNavigation/I18n/fr_FR.php | 8 + .../I18n/frontOffice/default/de_DE.php | 6 + .../I18n/frontOffice/default/en_US.php | 8 + .../I18n/frontOffice/default/fr_FR.php | 8 + .../I18n/frontOffice/default/it_IT.php | 8 + .../I18n/frontOffice/default/ru_RU.php | 8 + .../I18n/frontOffice/default/tr_TR.php | 6 + local/modules/HookNavigation/I18n/it_IT.php | 5 + local/modules/HookNavigation/I18n/ru_RU.php | 8 + local/modules/HookNavigation/LICENSE.txt | 165 + .../Config/Base/HookNavigationConfigValue.php | 23 + .../Config/HookNavigationConfigValue.php | 23 + local/modules/HookNavigation/composer.json | 11 + .../default/hooknavigation-configuration.html | 116 + .../frontOffice/default/main-footer-body.html | 17 + .../default/main-footer-bottom.html | 7 + .../default/main-navbar-primary.html | 56 + .../modules/HookNewsletter/Config/config.xml | 13 + .../modules/HookNewsletter/Config/module.xml | 24 + .../modules/HookNewsletter/Hook/FrontHook.php | 37 + .../modules/HookNewsletter/HookNewsletter.php | 20 + local/modules/HookNewsletter/I18n/de_DE.php | 5 + local/modules/HookNewsletter/I18n/en_US.php | 5 + local/modules/HookNewsletter/I18n/fr_FR.php | 5 + .../I18n/frontOffice/default/de_DE.php | 8 + .../I18n/frontOffice/default/en_US.php | 8 + .../I18n/frontOffice/default/fr_FR.php | 8 + .../I18n/frontOffice/default/it_IT.php | 6 + .../I18n/frontOffice/default/ru_RU.php | 8 + .../I18n/frontOffice/default/tr_TR.php | 8 + local/modules/HookNewsletter/I18n/it_IT.php | 5 + local/modules/HookNewsletter/I18n/ru_RU.php | 5 + local/modules/HookNewsletter/I18n/tr_TR.php | 5 + local/modules/HookNewsletter/LICENSE.txt | 165 + local/modules/HookNewsletter/composer.json | 11 + .../frontOffice/default/main-footer-body.html | 13 + .../modules/HookProductsNew/Config/config.xml | 13 + .../modules/HookProductsNew/Config/module.xml | 24 + .../HookProductsNew/HookProductsNew.php | 20 + .../I18n/frontOffice/default/de_DE.php | 6 + .../I18n/frontOffice/default/en_US.php | 6 + .../I18n/frontOffice/default/fr_FR.php | 6 + .../I18n/frontOffice/default/it_IT.php | 6 + .../I18n/frontOffice/default/ru_RU.php | 6 + .../I18n/frontOffice/default/tr_TR.php | 6 + local/modules/HookProductsNew/LICENSE.txt | 165 + local/modules/HookProductsNew/composer.json | 11 + .../frontOffice/default/home-body.html | 59 + .../HookProductsOffer/Config/config.xml | 13 + .../HookProductsOffer/Config/module.xml | 24 + .../HookProductsOffer/HookProductsOffer.php | 20 + .../I18n/frontOffice/default/de_DE.php | 6 + .../I18n/frontOffice/default/en_US.php | 6 + .../I18n/frontOffice/default/fr_FR.php | 6 + .../I18n/frontOffice/default/it_IT.php | 6 + .../I18n/frontOffice/default/ru_RU.php | 6 + .../I18n/frontOffice/default/tr_TR.php | 6 + local/modules/HookProductsOffer/LICENSE.txt | 165 + local/modules/HookProductsOffer/composer.json | 11 + .../frontOffice/default/home-body.html | 39 + local/modules/HookSearch/Config/config.xml | 15 + local/modules/HookSearch/Config/module.xml | 24 + local/modules/HookSearch/HookSearch.php | 20 + .../I18n/frontOffice/default/de_DE.php | 8 + .../I18n/frontOffice/default/en_US.php | 8 + .../I18n/frontOffice/default/fr_FR.php | 8 + .../I18n/frontOffice/default/it_IT.php | 8 + .../I18n/frontOffice/default/ru_RU.php | 8 + .../I18n/frontOffice/default/tr_TR.php | 8 + local/modules/HookSearch/LICENSE.txt | 165 + local/modules/HookSearch/composer.json | 11 + .../frontOffice/default/assets/css/styles.css | 11 + .../default/main-navbar-primary.html | 11 + .../default/main-navbar-secondary.html | 7 + local/modules/HookSocial/Config/config.xml | 21 + local/modules/HookSocial/Config/module.xml | 24 + local/modules/HookSocial/Config/routing.xml | 10 + .../HookSocial/Controller/Configuration.php | 61 + .../modules/HookSocial/Form/Configuration.php | 86 + local/modules/HookSocial/Hook/FrontHook.php | 37 + local/modules/HookSocial/HookSocial.php | 20 + .../I18n/backOffice/default/de_DE.php | 6 + .../I18n/backOffice/default/en_US.php | 7 + .../I18n/backOffice/default/fr_FR.php | 7 + .../I18n/backOffice/default/it_IT.php | 6 + .../I18n/backOffice/default/ru_RU.php | 7 + .../I18n/backOffice/default/tr_TR.php | 7 + local/modules/HookSocial/I18n/de_DE.php | 12 + local/modules/HookSocial/I18n/en_US.php | 12 + local/modules/HookSocial/I18n/fr_FR.php | 12 + .../I18n/frontOffice/default/de_DE.php | 10 + .../I18n/frontOffice/default/en_US.php | 10 + .../I18n/frontOffice/default/fr_FR.php | 10 + .../I18n/frontOffice/default/it_IT.php | 10 + .../I18n/frontOffice/default/ru_RU.php | 11 + .../I18n/frontOffice/default/tr_TR.php | 10 + local/modules/HookSocial/I18n/it_IT.php | 12 + local/modules/HookSocial/I18n/ru_RU.php | 12 + local/modules/HookSocial/I18n/tr_TR.php | 12 + local/modules/HookSocial/LICENSE.txt | 165 + local/modules/HookSocial/composer.json | 11 + .../default/assets/js/module-configuration.js | 28 + .../default/module_configuration.html | 94 + .../frontOffice/default/assets/css/styles.css | 0 .../frontOffice/default/main-footer-body.html | 86 + .../TheliaMigrateCountry/Config/config.xml | 27 + .../TheliaMigrateCountry/Config/module.xml | 26 + .../TheliaMigrateCountry/Config/routing.xml | 15 + .../Controller/MigrateController.php | 175 + .../EventListeners/MigrateCountryListener.php | 155 + .../Events/MigrateCountryEvent.php | 117 + .../Events/MigrateCountryEvents.php | 24 + .../Form/CountryStateMigrationForm.php | 54 + .../Form/Type/CountryStateMigrationType.php | 114 + .../I18n/backOffice/default/en_US.php | 31 + .../I18n/backOffice/default/fr_FR.php | 31 + .../I18n/backOffice/default/it_IT.php | 19 + .../I18n/backOffice/default/ru_RU.php | 31 + .../TheliaMigrateCountry/I18n/en_US.php | 8 + .../TheliaMigrateCountry/I18n/fr_FR.php | 8 + .../TheliaMigrateCountry/I18n/it_IT.php | 8 + .../TheliaMigrateCountry/I18n/ru_RU.php | 8 + .../modules/TheliaMigrateCountry/LICENSE.txt | 165 + local/modules/TheliaMigrateCountry/Readme.md | 18 + .../TheliaMigrateCountry.php | 28 + .../TheliaMigrateCountry/composer.json | 11 + .../configuration-shipping-bottom.html | 6 + .../backOffice/default/countries-migrate.html | 299 + local/modules/TheliaSmarty/CREDITS.md | 40 + .../Compiler/RegisterParserPluginPass.php | 48 + local/modules/TheliaSmarty/Config/config.xml | 158 + local/modules/TheliaSmarty/Config/module.xml | 28 + local/modules/TheliaSmarty/I18n/en_US.php | 21 + local/modules/TheliaSmarty/I18n/fr_FR.php | 21 + local/modules/TheliaSmarty/I18n/ru_RU.php | 20 + local/modules/TheliaSmarty/I18n/tr_TR.php | 21 + local/modules/TheliaSmarty/LICENSE.txt | 165 + local/modules/TheliaSmarty/Readme.md | 2 + .../Template/AbstractSmartyPlugin.php | 133 + .../Template/Assets/SmartyAssetsManager.php | 271 + .../Template/Assets/SmartyAssetsResolver.php | 311 + .../Exception/SmartyPluginException.php | 22 + .../Template/Plugins/AdminUtilities.php | 184 + .../TheliaSmarty/Template/Plugins/Assets.php | 106 + .../TheliaSmarty/Template/Plugins/Cache.php | 144 + .../Template/Plugins/CartPostage.php | 269 + .../Template/Plugins/DataAccessFunctions.php | 973 ++ .../TheliaSmarty/Template/Plugins/Esi.php | 73 + .../Template/Plugins/FlashMessage.php | 155 + .../TheliaSmarty/Template/Plugins/Form.php | 1066 ++ .../TheliaSmarty/Template/Plugins/Format.php | 500 + .../TheliaSmarty/Template/Plugins/Hook.php | 491 + .../TheliaSmarty/Template/Plugins/Module.php | 106 + .../TheliaSmarty/Template/Plugins/Render.php | 167 + .../Template/Plugins/Security.php | 146 + .../Template/Plugins/TheliaLoop.php | 496 + .../Template/Plugins/Translation.php | 125 + .../TheliaSmarty/Template/Plugins/Type.php | 47 + .../Template/Plugins/UrlGenerator.php | 405 + .../Template/Plugins/VarDumper.php | 72 + .../TheliaSmarty/Template/SmartyHelper.php | 178 + .../TheliaSmarty/Template/SmartyParser.php | 640 + .../Template/SmartyPluginDescriptor.php | 92 + .../Plugin/Controller/TestController.php | 49 + .../Tests/Template/Plugin/FormTest.php | 186 + .../Tests/Template/Plugin/FormatTest.php | 232 + .../Tests/Template/Plugin/RenderTest.php | 80 + .../Template/Plugin/SmartyPluginTestCase.php | 112 + .../Tests/Template/Plugin/fixtures/test.html | 1 + .../Plugin/fixtures/testFormatMoney.html | 1 + .../Template/Plugin/fixtures/testMethod.html | 1 + .../Template/Plugin/fixtures/testParams.html | 1 + .../Plugin/fixtures/testQueryArray.html | 1 + .../Plugin/fixtures/testQueryString.html | 1 + .../Template/Plugin/fixtures/testRequest.html | 1 + .../Tests/Template/SmartyHelperTest.php | 128 + local/modules/TheliaSmarty/TheliaSmarty.php | 33 + local/modules/TheliaSmarty/composer.json | 11 + local/modules/Tinymce/CHANGELOG.md | 5 + local/modules/Tinymce/Config/config.xml | 25 + local/modules/Tinymce/Config/module.xml | 18 + local/modules/Tinymce/Config/routing.xml | 9 + .../Controller/ConfigureController.php | 128 + .../Tinymce/Form/ConfigurationForm.php | 161 + local/modules/Tinymce/Hook/HookManager.php | 31 + .../Tinymce/I18n/backOffice/default/de_DE.php | 5 + .../Tinymce/I18n/backOffice/default/en_US.php | 7 + .../Tinymce/I18n/backOffice/default/fr_FR.php | 17 + .../Tinymce/I18n/backOffice/default/ru_RU.php | 17 + .../Tinymce/I18n/backOffice/default/tr_TR.php | 7 + local/modules/Tinymce/I18n/en_US.php | 15 + local/modules/Tinymce/I18n/fr_FR.php | 15 + local/modules/Tinymce/I18n/it_IT.php | 6 + local/modules/Tinymce/I18n/ru_RU.php | 16 + local/modules/Tinymce/I18n/tr_TR.php | 15 + local/modules/Tinymce/LICENSE.txt | 165 + .../js/tinymce/filemanager/ajax_calls.php | 719 + .../js/tinymce/filemanager/config/.htaccess | 1 + .../js/tinymce/filemanager/config/config.php | 602 + .../js/tinymce/filemanager/css/style.css | 36 + .../js/tinymce/filemanager/dialog.php | 1161 ++ .../js/tinymce/filemanager/execute.php | 524 + .../js/tinymce/filemanager/force_download.php | 151 + .../filemanager/img/clipboard_apply.png | Bin 0 -> 189 bytes .../filemanager/img/clipboard_clear.png | Bin 0 -> 195 bytes .../js/tinymce/filemanager/img/copy.png | Bin 0 -> 238 bytes .../js/tinymce/filemanager/img/cut.png | Bin 0 -> 173 bytes .../js/tinymce/filemanager/img/date.png | Bin 0 -> 611 bytes .../js/tinymce/filemanager/img/dimension.png | Bin 0 -> 489 bytes .../js/tinymce/filemanager/img/down.png | Bin 0 -> 163 bytes .../js/tinymce/filemanager/img/download.png | Bin 0 -> 674 bytes .../js/tinymce/filemanager/img/duplicate.png | Bin 0 -> 245 bytes .../js/tinymce/filemanager/img/edit_img.png | Bin 0 -> 673 bytes .../js/tinymce/filemanager/img/file_edit.png | Bin 0 -> 764 bytes .../img/glyphicons-halflings-white.png | Bin 0 -> 8583 bytes .../filemanager/img/glyphicons-halflings.png | Bin 0 -> 15602 bytes .../js/tinymce/filemanager/img/ico/ac3.jpg | Bin 0 -> 1692 bytes .../js/tinymce/filemanager/img/ico/accdb.jpg | Bin 0 -> 2613 bytes .../js/tinymce/filemanager/img/ico/ade.jpg | Bin 0 -> 2290 bytes .../js/tinymce/filemanager/img/ico/adp.jpg | Bin 0 -> 2290 bytes .../js/tinymce/filemanager/img/ico/ai.jpg | Bin 0 -> 1776 bytes .../js/tinymce/filemanager/img/ico/aiff.jpg | Bin 0 -> 1717 bytes .../js/tinymce/filemanager/img/ico/avi.jpg | Bin 0 -> 1548 bytes .../js/tinymce/filemanager/img/ico/bmp.jpg | Bin 0 -> 1979 bytes .../js/tinymce/filemanager/img/ico/c4d.jpg | Bin 0 -> 6241 bytes .../js/tinymce/filemanager/img/ico/css.jpg | Bin 0 -> 1722 bytes .../js/tinymce/filemanager/img/ico/csv.jpg | Bin 0 -> 2558 bytes .../tinymce/filemanager/img/ico/default.jpg | Bin 0 -> 1723 bytes .../js/tinymce/filemanager/img/ico/dmg.jpg | Bin 0 -> 1579 bytes .../js/tinymce/filemanager/img/ico/doc.jpg | Bin 0 -> 2511 bytes .../js/tinymce/filemanager/img/ico/docx.jpg | Bin 0 -> 2511 bytes .../js/tinymce/filemanager/img/ico/dwg.jpg | Bin 0 -> 5457 bytes .../js/tinymce/filemanager/img/ico/dxf.jpg | Bin 0 -> 5419 bytes .../tinymce/filemanager/img/ico/favicon.ico | Bin 0 -> 1150 bytes .../js/tinymce/filemanager/img/ico/fla.jpg | Bin 0 -> 1859 bytes .../js/tinymce/filemanager/img/ico/flv.jpg | Bin 0 -> 1806 bytes .../js/tinymce/filemanager/img/ico/folder.png | Bin 0 -> 737 bytes .../filemanager/img/ico/folder_back.png | Bin 0 -> 1128 bytes .../js/tinymce/filemanager/img/ico/gif.jpg | Bin 0 -> 1979 bytes .../js/tinymce/filemanager/img/ico/gz.jpg | Bin 0 -> 1718 bytes .../js/tinymce/filemanager/img/ico/html.jpg | Bin 0 -> 2152 bytes .../js/tinymce/filemanager/img/ico/iso.jpg | Bin 0 -> 1496 bytes .../js/tinymce/filemanager/img/ico/jpeg.jpg | Bin 0 -> 1960 bytes .../js/tinymce/filemanager/img/ico/jpg.jpg | Bin 0 -> 1979 bytes .../js/tinymce/filemanager/img/ico/log.jpg | Bin 0 -> 1765 bytes .../js/tinymce/filemanager/img/ico/m4a.jpg | Bin 0 -> 1529 bytes .../js/tinymce/filemanager/img/ico/mdb.jpg | Bin 0 -> 2613 bytes .../js/tinymce/filemanager/img/ico/mid.jpg | Bin 0 -> 1630 bytes .../js/tinymce/filemanager/img/ico/mov.jpg | Bin 0 -> 1574 bytes .../js/tinymce/filemanager/img/ico/mp3.jpg | Bin 0 -> 1555 bytes .../js/tinymce/filemanager/img/ico/mp4.jpg | Bin 0 -> 1529 bytes .../js/tinymce/filemanager/img/ico/mpeg.jpg | Bin 0 -> 1589 bytes .../js/tinymce/filemanager/img/ico/mpg.jpg | Bin 0 -> 1532 bytes .../js/tinymce/filemanager/img/ico/odb.jpg | Bin 0 -> 1748 bytes .../js/tinymce/filemanager/img/ico/odf.jpg | Bin 0 -> 1760 bytes .../js/tinymce/filemanager/img/ico/odg.jpg | Bin 0 -> 1748 bytes .../js/tinymce/filemanager/img/ico/odp.jpg | Bin 0 -> 1760 bytes .../js/tinymce/filemanager/img/ico/ods.jpg | Bin 0 -> 1748 bytes .../js/tinymce/filemanager/img/ico/odt.jpg | Bin 0 -> 1748 bytes .../js/tinymce/filemanager/img/ico/ogg.jpg | Bin 0 -> 1557 bytes .../js/tinymce/filemanager/img/ico/otg.jpg | Bin 0 -> 1759 bytes .../js/tinymce/filemanager/img/ico/otp.jpg | Bin 0 -> 1870 bytes .../js/tinymce/filemanager/img/ico/ots.jpg | Bin 0 -> 1748 bytes .../js/tinymce/filemanager/img/ico/ott.jpg | Bin 0 -> 1748 bytes .../js/tinymce/filemanager/img/ico/pdf.jpg | Bin 0 -> 2050 bytes .../js/tinymce/filemanager/img/ico/png.jpg | Bin 0 -> 1979 bytes .../js/tinymce/filemanager/img/ico/ppt.jpg | Bin 0 -> 2386 bytes .../js/tinymce/filemanager/img/ico/pptx.jpg | Bin 0 -> 2479 bytes .../js/tinymce/filemanager/img/ico/psd.jpg | Bin 0 -> 2110 bytes .../js/tinymce/filemanager/img/ico/rar.jpg | Bin 0 -> 1718 bytes .../js/tinymce/filemanager/img/ico/rtf.jpg | Bin 0 -> 2511 bytes .../js/tinymce/filemanager/img/ico/skp.jpg | Bin 0 -> 6347 bytes .../js/tinymce/filemanager/img/ico/sql.jpg | Bin 0 -> 1695 bytes .../js/tinymce/filemanager/img/ico/stp.jpg | Bin 0 -> 5539 bytes .../js/tinymce/filemanager/img/ico/svg.jpg | Bin 0 -> 1979 bytes .../js/tinymce/filemanager/img/ico/tar.jpg | Bin 0 -> 1747 bytes .../js/tinymce/filemanager/img/ico/tiff.jpg | Bin 0 -> 1953 bytes .../js/tinymce/filemanager/img/ico/txt.jpg | Bin 0 -> 1765 bytes .../js/tinymce/filemanager/img/ico/vwx.jpg | Bin 0 -> 5463 bytes .../js/tinymce/filemanager/img/ico/wav.jpg | Bin 0 -> 1557 bytes .../js/tinymce/filemanager/img/ico/webm.jpg | Bin 0 -> 1548 bytes .../js/tinymce/filemanager/img/ico/wma.jpg | Bin 0 -> 1548 bytes .../js/tinymce/filemanager/img/ico/xhtml.jpg | Bin 0 -> 1920 bytes .../js/tinymce/filemanager/img/ico/xls.jpg | Bin 0 -> 2691 bytes .../js/tinymce/filemanager/img/ico/xlsx.jpg | Bin 0 -> 2539 bytes .../js/tinymce/filemanager/img/ico/xml.jpg | Bin 0 -> 1714 bytes .../js/tinymce/filemanager/img/ico/zip.jpg | Bin 0 -> 1718 bytes .../tinymce/filemanager/img/ico_dark/ac3.jpg | Bin 0 -> 3462 bytes .../filemanager/img/ico_dark/accdb.jpg | Bin 0 -> 4130 bytes .../tinymce/filemanager/img/ico_dark/ade.jpg | Bin 0 -> 4126 bytes .../tinymce/filemanager/img/ico_dark/adp.jpg | Bin 0 -> 4126 bytes .../tinymce/filemanager/img/ico_dark/ai.jpg | Bin 0 -> 3416 bytes .../tinymce/filemanager/img/ico_dark/aiff.jpg | Bin 0 -> 3454 bytes .../tinymce/filemanager/img/ico_dark/avi.jpg | Bin 0 -> 3461 bytes .../tinymce/filemanager/img/ico_dark/bmp.jpg | Bin 0 -> 3754 bytes .../tinymce/filemanager/img/ico_dark/css.jpg | Bin 0 -> 3444 bytes .../tinymce/filemanager/img/ico_dark/csv.jpg | Bin 0 -> 4189 bytes .../filemanager/img/ico_dark/default.jpg | Bin 0 -> 3783 bytes .../tinymce/filemanager/img/ico_dark/dmg.jpg | Bin 0 -> 3619 bytes .../tinymce/filemanager/img/ico_dark/doc.jpg | Bin 0 -> 4081 bytes .../tinymce/filemanager/img/ico_dark/docx.jpg | Bin 0 -> 4075 bytes .../filemanager/img/ico_dark/favicon.ico | Bin 0 -> 1150 bytes .../tinymce/filemanager/img/ico_dark/fla.jpg | Bin 0 -> 3608 bytes .../tinymce/filemanager/img/ico_dark/flv.jpg | Bin 0 -> 3572 bytes .../filemanager/img/ico_dark/folder.png | Bin 0 -> 535 bytes .../filemanager/img/ico_dark/folder_back.png | Bin 0 -> 1128 bytes .../tinymce/filemanager/img/ico_dark/gif.jpg | Bin 0 -> 3754 bytes .../tinymce/filemanager/img/ico_dark/gz.jpg | Bin 0 -> 3372 bytes .../tinymce/filemanager/img/ico_dark/html.jpg | Bin 0 -> 3719 bytes .../tinymce/filemanager/img/ico_dark/iso.jpg | Bin 0 -> 3576 bytes .../tinymce/filemanager/img/ico_dark/jpeg.jpg | Bin 0 -> 3700 bytes .../tinymce/filemanager/img/ico_dark/jpg.jpg | Bin 0 -> 3754 bytes .../tinymce/filemanager/img/ico_dark/log.jpg | Bin 0 -> 3804 bytes .../tinymce/filemanager/img/ico_dark/m4a.jpg | Bin 0 -> 3379 bytes .../tinymce/filemanager/img/ico_dark/mdb.jpg | Bin 0 -> 4130 bytes .../tinymce/filemanager/img/ico_dark/mid.jpg | Bin 0 -> 3383 bytes .../tinymce/filemanager/img/ico_dark/mov.jpg | Bin 0 -> 3439 bytes .../tinymce/filemanager/img/ico_dark/mp3.jpg | Bin 0 -> 3335 bytes .../tinymce/filemanager/img/ico_dark/mp4.jpg | Bin 0 -> 3415 bytes .../tinymce/filemanager/img/ico_dark/mpeg.jpg | Bin 0 -> 3470 bytes .../tinymce/filemanager/img/ico_dark/mpg.jpg | Bin 0 -> 3459 bytes .../tinymce/filemanager/img/ico_dark/odb.jpg | Bin 0 -> 3581 bytes .../tinymce/filemanager/img/ico_dark/odf.jpg | Bin 0 -> 3590 bytes .../tinymce/filemanager/img/ico_dark/odg.jpg | Bin 0 -> 3581 bytes .../tinymce/filemanager/img/ico_dark/odp.jpg | Bin 0 -> 3590 bytes .../tinymce/filemanager/img/ico_dark/ods.jpg | Bin 0 -> 3581 bytes .../tinymce/filemanager/img/ico_dark/odt.jpg | Bin 0 -> 3581 bytes .../tinymce/filemanager/img/ico_dark/ogg.jpg | Bin 0 -> 3440 bytes .../tinymce/filemanager/img/ico_dark/otg.jpg | Bin 0 -> 3561 bytes .../tinymce/filemanager/img/ico_dark/otp.jpg | Bin 0 -> 3559 bytes .../tinymce/filemanager/img/ico_dark/ots.jpg | Bin 0 -> 3581 bytes .../tinymce/filemanager/img/ico_dark/ott.jpg | Bin 0 -> 3581 bytes .../tinymce/filemanager/img/ico_dark/pdf.jpg | Bin 0 -> 3705 bytes .../tinymce/filemanager/img/ico_dark/png.jpg | Bin 0 -> 3754 bytes .../tinymce/filemanager/img/ico_dark/ppt.jpg | Bin 0 -> 4035 bytes .../tinymce/filemanager/img/ico_dark/pptx.jpg | Bin 0 -> 4089 bytes .../tinymce/filemanager/img/ico_dark/psd.jpg | Bin 0 -> 3859 bytes .../tinymce/filemanager/img/ico_dark/rar.jpg | Bin 0 -> 3387 bytes .../tinymce/filemanager/img/ico_dark/rtf.jpg | Bin 0 -> 4081 bytes .../tinymce/filemanager/img/ico_dark/sql.jpg | Bin 0 -> 3766 bytes .../tinymce/filemanager/img/ico_dark/svg.jpg | Bin 0 -> 3754 bytes .../tinymce/filemanager/img/ico_dark/tar.jpg | Bin 0 -> 3346 bytes .../tinymce/filemanager/img/ico_dark/tiff.jpg | Bin 0 -> 3798 bytes .../tinymce/filemanager/img/ico_dark/txt.jpg | Bin 0 -> 3804 bytes .../tinymce/filemanager/img/ico_dark/wav.jpg | Bin 0 -> 3440 bytes .../tinymce/filemanager/img/ico_dark/webm.jpg | Bin 0 -> 3476 bytes .../tinymce/filemanager/img/ico_dark/wma.jpg | Bin 0 -> 3461 bytes .../filemanager/img/ico_dark/xhtml.jpg | Bin 0 -> 3653 bytes .../tinymce/filemanager/img/ico_dark/xls.jpg | Bin 0 -> 4183 bytes .../tinymce/filemanager/img/ico_dark/xlsx.jpg | Bin 0 -> 4250 bytes .../tinymce/filemanager/img/ico_dark/xml.jpg | Bin 0 -> 3774 bytes .../tinymce/filemanager/img/ico_dark/zip.jpg | Bin 0 -> 3372 bytes .../js/tinymce/filemanager/img/info.png | Bin 0 -> 345 bytes .../js/tinymce/filemanager/img/key.png | Bin 0 -> 185 bytes .../js/tinymce/filemanager/img/label.png | Bin 0 -> 479 bytes .../js/tinymce/filemanager/img/loading.gif | Bin 0 -> 1688 bytes .../js/tinymce/filemanager/img/logo.png | Bin 0 -> 24774 bytes .../js/tinymce/filemanager/img/preview.png | Bin 0 -> 376 bytes .../js/tinymce/filemanager/img/processing.gif | Bin 0 -> 3209 bytes .../js/tinymce/filemanager/img/rename.png | Bin 0 -> 262 bytes .../js/tinymce/filemanager/img/size.png | Bin 0 -> 660 bytes .../js/tinymce/filemanager/img/sort.png | Bin 0 -> 584 bytes .../filemanager/img/storing_animation.gif | Bin 0 -> 3887 bytes .../js/tinymce/filemanager/img/trans.jpg | Bin 0 -> 4024 bytes .../js/tinymce/filemanager/img/up.png | Bin 0 -> 163 bytes .../js/tinymce/filemanager/img/upload.png | Bin 0 -> 324 bytes .../js/tinymce/filemanager/img/url.png | Bin 0 -> 593 bytes .../js/tinymce/filemanager/img/zip.png | Bin 0 -> 819 bytes .../tinymce/filemanager/include/FtpClient.php | 884 ++ .../filemanager/include/FtpException.php | 20 + .../filemanager/include/FtpWrapper.php | 115 + .../tinymce/filemanager/include/Response.php | 365 + .../tinymce/filemanager/include/ftp_class.php | 82 + .../filemanager/include/mime_type_lib.php | 340 + .../include/php_image_magician.php | 3783 +++++ .../js/tinymce/filemanager/include/utils.php | 1164 ++ .../tinymce/filemanager/js/ZeroClipboard.swf | Bin 0 -> 4036 bytes .../js/tinymce/filemanager/js/include.js | 2 + .../filemanager/js/jPlayer/MIT-LICENSE.txt | 21 + .../tinymce/filemanager/js/jPlayer/README.md | 32 + .../js/jPlayer/actionscript/Jplayer.as | 638 + .../js/jPlayer/actionscript/Jplayer.fla | Bin 0 -> 61952 bytes .../happyworm/jPlayer/ConnectManager.as | 295 + .../happyworm/jPlayer/JplayerEvent.as | 68 + .../happyworm/jPlayer/JplayerMp3.as | 367 + .../happyworm/jPlayer/JplayerMp4.as | 412 + .../happyworm/jPlayer/JplayerRtmp.as | 983 ++ .../happyworm/jPlayer/JplayerStatus.as | 110 + .../happyworm/jPlayer/TraceOut.as | 62 + .../js/jPlayer/add-on/jplayer.playlist.js | 496 + .../js/jPlayer/add-on/jplayer.playlist.min.js | 2 + .../add-on/jquery.jplayer.inspector.js | 338 + .../add-on/jquery.jplayer.inspector.min.js | 2 + .../js/jPlayer/jplayer.jquery.json | 33 + .../js/jPlayer/jplayer/jquery.jplayer.js | 3506 +++++ .../js/jPlayer/jplayer/jquery.jplayer.min.js | 3 + .../js/jPlayer/jplayer/jquery.jplayer.swf | Bin 0 -> 13714 bytes .../js/jPlayer/jquery.jplayer/Jplayer.swf | Bin 0 -> 14085 bytes .../jPlayer/jquery.jplayer/jquery.jplayer.js | 2840 ++++ .../filemanager/js/jPlayer/package.json | 27 + .../js/jPlayer/popcorn/popcorn.jplayer.js | 579 + .../js/jPlayer/popcorn/popcorn.jplayer.min.js | 2 + .../blue.monday/css/jplayer.blue.monday.css | 551 + .../css/jplayer.blue.monday.min.css | 1 + .../blue.monday/image/jplayer.blue.monday.jpg | Bin 0 -> 23189 bytes .../image/jplayer.blue.monday.seeking.gif | Bin 0 -> 3284 bytes .../image/jplayer.blue.monday.video.play.png | Bin 0 -> 17692 bytes .../skin/blue.monday/jplayer.blue.monday.css | 640 + .../skin/blue.monday/jplayer.blue.monday.jpg | Bin 0 -> 23189 bytes .../jplayer.blue.monday.seeking.gif | Bin 0 -> 3284 bytes .../jplayer.blue.monday.video.play.png | Bin 0 -> 17692 bytes .../jplayer.blue.monday.audio.playlist.html | 42 + .../jplayer.blue.monday.audio.single.html | 37 + .../jplayer.blue.monday.audio.stream.html | 24 + .../jplayer.blue.monday.video.playlist.html | 52 + .../jplayer.blue.monday.video.single.html | 43 + .../jPlayer/skin/blue.monday/skin.handlebars | 40 + .../skin/pink.flag/css/jplayer.pink.flag.css | 572 + .../pink.flag/css/jplayer.pink.flag.min.css | 1 + .../pink.flag/image/jplayer.pink.flag.jpg | Bin 0 -> 18426 bytes .../image/jplayer.pink.flag.seeking.gif | Bin 0 -> 3284 bytes .../image/jplayer.pink.flag.video.play.png | Bin 0 -> 17692 bytes .../jplayer.pink.flag.audio.playlist.html | 42 + .../jplayer.pink.flag.audio.single.html | 37 + .../jplayer.pink.flag.audio.stream.html | 24 + .../jplayer.pink.flag.video.playlist.html | 52 + .../jplayer.pink.flag.video.single.html | 43 + .../blue.monday/jplayer.blue.monday.css | 640 + .../blue.monday/jplayer.blue.monday.jpg | Bin 0 -> 23189 bytes .../jplayer.blue.monday.seeking.gif | Bin 0 -> 3284 bytes .../jplayer.blue.monday.video.play.png | Bin 0 -> 17692 bytes .../skin_ol/blue.monday/skin.handlebars | 40 + .../skin_ol/pink.flag/jplayer.pink.flag.css | 670 + .../skin_ol/pink.flag/jplayer.pink.flag.jpg | Bin 0 -> 18426 bytes .../pink.flag/jplayer.pink.flag.seeking.gif | Bin 0 -> 3284 bytes .../jplayer.pink.flag.video.play.png | Bin 0 -> 17692 bytes .../filemanager/js/modernizr.custom.js | 1 + .../js/tinymce/filemanager/js/plugins.js | 12 + .../js/tinymce/filemanager/lang/az_AZ.php | 123 + .../js/tinymce/filemanager/lang/bg_BG.php | 123 + .../js/tinymce/filemanager/lang/ca.php | 122 + .../js/tinymce/filemanager/lang/cs.php | 123 + .../js/tinymce/filemanager/lang/da.php | 123 + .../js/tinymce/filemanager/lang/de.php | 123 + .../js/tinymce/filemanager/lang/el_GR.php | 123 + .../js/tinymce/filemanager/lang/en_EN.php | 123 + .../js/tinymce/filemanager/lang/es.php | 123 + .../js/tinymce/filemanager/lang/fa.php | 122 + .../js/tinymce/filemanager/lang/fr_FR.php | 123 + .../js/tinymce/filemanager/lang/he_IL.php | 124 + .../js/tinymce/filemanager/lang/hr.php | 123 + .../js/tinymce/filemanager/lang/hu_HU.php | 123 + .../js/tinymce/filemanager/lang/id.php | 123 + .../js/tinymce/filemanager/lang/it.php | 123 + .../js/tinymce/filemanager/lang/ja.php | 123 + .../js/tinymce/filemanager/lang/languages.php | 40 + .../js/tinymce/filemanager/lang/lt.php | 123 + .../js/tinymce/filemanager/lang/mn_MN.php | 123 + .../js/tinymce/filemanager/lang/nb_NO.php | 123 + .../js/tinymce/filemanager/lang/nl.php | 123 + .../js/tinymce/filemanager/lang/pl.php | 123 + .../js/tinymce/filemanager/lang/pt_BR.php | 123 + .../js/tinymce/filemanager/lang/pt_PT.php | 123 + .../js/tinymce/filemanager/lang/ro.php | 123 + .../js/tinymce/filemanager/lang/ru.php | 122 + .../js/tinymce/filemanager/lang/sk.php | 123 + .../js/tinymce/filemanager/lang/sl.php | 123 + .../js/tinymce/filemanager/lang/sv_SE.php | 123 + .../js/tinymce/filemanager/lang/tr_TR.php | 123 + .../js/tinymce/filemanager/lang/uk_UA.php | 123 + .../js/tinymce/filemanager/lang/vi.php | 123 + .../js/tinymce/filemanager/lang/zh_CN.php | 123 + .../js/tinymce/filemanager/plugin.min.js | 1 + .../js/tinymce/filemanager/upload.php | 283 + .../js/tinymce/filemanager/uploader/index.php | 166 + .../tinymce/filemanager/uploader/jupload.php | 772 + .../tinymce/filemanager/uploader/success.jpg | Bin 0 -> 6344 bytes .../tinymce/filemanager/uploader/success.php | 19 + .../filemanager/uploader/wjhk.jupload.jar | Bin 0 -> 343591 bytes .../Tinymce/Resources/js/tinymce/langs/cs.js | 197 + .../Tinymce/Resources/js/tinymce/langs/de.js | 197 + .../Tinymce/Resources/js/tinymce/langs/es.js | 197 + .../Resources/js/tinymce/langs/fr_FR.js | 197 + .../Tinymce/Resources/js/tinymce/langs/it.js | 197 + .../Resources/js/tinymce/langs/readme.md | 3 + .../Tinymce/Resources/js/tinymce/langs/ru.js | 197 + .../Tinymce/Resources/js/tinymce/license.txt | 504 + .../js/tinymce/plugins/advlist/plugin.min.js | 1 + .../js/tinymce/plugins/anchor/plugin.min.js | 1 + .../js/tinymce/plugins/autolink/plugin.min.js | 1 + .../tinymce/plugins/autoresize/plugin.min.js | 1 + .../js/tinymce/plugins/autosave/plugin.min.js | 1 + .../js/tinymce/plugins/bbcode/plugin.min.js | 1 + .../js/tinymce/plugins/charmap/plugin.min.js | 1 + .../js/tinymce/plugins/code/plugin.min.js | 1 + .../tinymce/plugins/codesample/css/prism.css | 138 + .../tinymce/plugins/codesample/plugin.min.js | 1 + .../tinymce/plugins/colorpicker/plugin.min.js | 1 + .../tinymce/plugins/contextmenu/plugin.min.js | 1 + .../plugins/directionality/plugin.min.js | 1 + .../plugins/emoticons/img/smiley-cool.gif | Bin 0 -> 354 bytes .../plugins/emoticons/img/smiley-cry.gif | Bin 0 -> 329 bytes .../emoticons/img/smiley-embarassed.gif | Bin 0 -> 331 bytes .../emoticons/img/smiley-foot-in-mouth.gif | Bin 0 -> 342 bytes .../plugins/emoticons/img/smiley-frown.gif | Bin 0 -> 340 bytes .../plugins/emoticons/img/smiley-innocent.gif | Bin 0 -> 336 bytes .../plugins/emoticons/img/smiley-kiss.gif | Bin 0 -> 338 bytes .../plugins/emoticons/img/smiley-laughing.gif | Bin 0 -> 343 bytes .../emoticons/img/smiley-money-mouth.gif | Bin 0 -> 321 bytes .../plugins/emoticons/img/smiley-sealed.gif | Bin 0 -> 323 bytes .../plugins/emoticons/img/smiley-smile.gif | Bin 0 -> 344 bytes .../emoticons/img/smiley-surprised.gif | Bin 0 -> 338 bytes .../emoticons/img/smiley-tongue-out.gif | Bin 0 -> 328 bytes .../emoticons/img/smiley-undecided.gif | Bin 0 -> 337 bytes .../plugins/emoticons/img/smiley-wink.gif | Bin 0 -> 350 bytes .../plugins/emoticons/img/smiley-yell.gif | Bin 0 -> 336 bytes .../tinymce/plugins/emoticons/plugin.min.js | 1 + .../js/tinymce/plugins/example/dialog.html | 8 + .../js/tinymce/plugins/example/plugin.min.js | 1 + .../plugins/example_dependency/plugin.min.js | 1 + .../js/tinymce/plugins/fullpage/plugin.min.js | 1 + .../tinymce/plugins/fullscreen/plugin.min.js | 1 + .../js/tinymce/plugins/hr/plugin.min.js | 1 + .../js/tinymce/plugins/image/plugin.min.js | 1 + .../tinymce/plugins/imagetools/plugin.min.js | 1 + .../tinymce/plugins/importcss/plugin.min.js | 1 + .../plugins/insertdatetime/plugin.min.js | 1 + .../js/tinymce/plugins/layer/plugin.min.js | 1 + .../plugins/legacyoutput/plugin.min.js | 1 + .../js/tinymce/plugins/link/plugin.min.js | 1 + .../js/tinymce/plugins/lists/plugin.min.js | 1 + .../js/tinymce/plugins/media/moxieplayer.swf | Bin 0 -> 20017 bytes .../js/tinymce/plugins/media/plugin.min.js | 1 + .../tinymce/plugins/nonbreaking/plugin.min.js | 1 + .../tinymce/plugins/noneditable/plugin.min.js | 1 + .../tinymce/plugins/pagebreak/plugin.min.js | 1 + .../js/tinymce/plugins/paste/plugin.min.js | 1 + .../js/tinymce/plugins/preview/plugin.min.js | 1 + .../js/tinymce/plugins/print/plugin.min.js | 1 + .../responsivefilemanager/editor_plugin.js | 126 + .../responsivefilemanager/img/insertfile.gif | Bin 0 -> 3325 bytes .../plugins/responsivefilemanager/plugin.js | 79 + .../responsivefilemanager/plugin.min.js | 9 + .../js/tinymce/plugins/save/plugin.min.js | 1 + .../plugins/searchreplace/plugin.min.js | 1 + .../plugins/spellchecker/plugin.min.js | 1 + .../js/tinymce/plugins/tabfocus/plugin.min.js | 1 + .../js/tinymce/plugins/table/plugin.min.js | 2 + .../js/tinymce/plugins/template/plugin.min.js | 1 + .../tinymce/plugins/textcolor/plugin.min.js | 1 + .../tinymce/plugins/textpattern/plugin.min.js | 1 + .../plugins/visualblocks/css/visualblocks.css | 135 + .../plugins/visualblocks/plugin.min.js | 1 + .../tinymce/plugins/visualchars/plugin.min.js | 1 + .../tinymce/plugins/wordcount/plugin.min.js | 1 + .../js/tinymce/plugins/youtube/README.md | 78 + .../js/tinymce/plugins/youtube/css/styles.css | 9 + .../youtube/img/Google-YouTube-128.png | Bin 0 -> 11800 bytes .../tinymce/plugins/youtube/img/youtube.gif | Bin 0 -> 212 bytes .../js/tinymce/plugins/youtube/js/main.js | 807 + .../plugins/youtube/js/vendor/jquery.js | 6 + .../js/tinymce/plugins/youtube/langs/de.js | 10 + .../js/tinymce/plugins/youtube/langs/en.js | 12 + .../js/tinymce/plugins/youtube/langs/es.js | 10 + .../js/tinymce/plugins/youtube/langs/fr_FR.js | 12 + .../js/tinymce/plugins/youtube/langs/hu.js | 10 + .../js/tinymce/plugins/youtube/langs/it.js | 10 + .../js/tinymce/plugins/youtube/langs/pl.js | 10 + .../js/tinymce/plugins/youtube/langs/pt_BR.js | 10 + .../js/tinymce/plugins/youtube/langs/ru.js | 10 + .../js/tinymce/plugins/youtube/plugin.js | 51 + .../js/tinymce/plugins/youtube/plugin.min.js | 22 + .../tinymce/plugins/youtube/view/forms.html | 65 + .../js/tinymce/plugins/youtube/youtube.html | 20 + .../skins/lightgray/content.inline.min.css | 154 + .../tinymce/skins/lightgray/content.min.css | 1 + .../skins/lightgray/fonts/tinymce-small.eot | Bin 0 -> 9492 bytes .../skins/lightgray/fonts/tinymce-small.svg | 63 + .../skins/lightgray/fonts/tinymce-small.ttf | Bin 0 -> 9304 bytes .../skins/lightgray/fonts/tinymce-small.woff | Bin 0 -> 9380 bytes .../tinymce/skins/lightgray/fonts/tinymce.eot | Bin 0 -> 14308 bytes .../tinymce/skins/lightgray/fonts/tinymce.svg | 98 + .../tinymce/skins/lightgray/fonts/tinymce.ttf | Bin 0 -> 14144 bytes .../skins/lightgray/fonts/tinymce.woff | Bin 0 -> 14220 bytes .../js/tinymce/skins/lightgray/img/anchor.gif | Bin 0 -> 53 bytes .../js/tinymce/skins/lightgray/img/loader.gif | Bin 0 -> 2608 bytes .../js/tinymce/skins/lightgray/img/object.gif | Bin 0 -> 152 bytes .../js/tinymce/skins/lightgray/img/trans.gif | Bin 0 -> 43 bytes .../tinymce/skins/lightgray/skin.ie7.min.css | 1 + .../js/tinymce/skins/lightgray/skin.min.css | 1 + .../js/tinymce/themes/modern/theme.min.js | 1 + .../Resources/js/tinymce/tinymce.min.js | 13 + .../Tinymce/Smarty/TinyMCELanguage.php | 73 + local/modules/Tinymce/Tinymce.php | 108 + local/modules/Tinymce/composer.json | 11 + .../backOffice/default/assets/css/editor.less | 6 + .../default/module_configuration.html | 106 + .../backOffice/default/tinymce_init.tpl | 123 + .../VirtualProductControl/Config/config.xml | 15 + .../VirtualProductControl/Config/module.xml | 20 + .../Hook/VirtualProductHook.php | 62 + .../I18n/backOffice/default/de_DE.php | 5 + .../I18n/backOffice/default/en_US.php | 5 + .../I18n/backOffice/default/fr_FR.php | 5 + .../I18n/backOffice/default/it_IT.php | 5 + .../I18n/backOffice/default/tr_TR.php | 5 + .../VirtualProductControl/I18n/de_DE.php | 5 + .../VirtualProductControl/I18n/en_US.php | 4 + .../VirtualProductControl/I18n/fr_FR.php | 5 + .../VirtualProductControl/I18n/it_IT.php | 5 + .../VirtualProductControl/I18n/ru_RU.php | 4 + .../VirtualProductControl/I18n/tr_TR.php | 5 + .../modules/VirtualProductControl/LICENSE.txt | 165 + .../VirtualProductControl.php | 20 + .../VirtualProductControl/composer.json | 11 + .../default/virtual-delivery-warning.html | 7 + .../VirtualProductDelivery/Config/config.xml | 27 + .../VirtualProductDelivery/Config/module.xml | 24 + .../EventListeners/SendMail.php | 122 + .../EventListeners/VirtualProductEvents.php | 119 + .../Events/VirtualProductDeliveryEvents.php | 26 + .../Hook/HookManager.php | 39 + .../VirtualProductDelivery/I18n/de_DE.php | 8 + .../I18n/email/default/en_US.php | 10 + .../I18n/email/default/fr_FR.php | 10 + .../I18n/email/default/it_IT.php | 10 + .../I18n/email/default/ru_RU.php | 9 + .../I18n/email/default/tr_TR.php | 10 + .../VirtualProductDelivery/I18n/en_US.php | 8 + .../VirtualProductDelivery/I18n/fr_FR.php | 8 + .../I18n/frontOffice/default/de_DE.php | 9 + .../I18n/frontOffice/default/en_US.php | 9 + .../I18n/frontOffice/default/fr_FR.php | 9 + .../I18n/frontOffice/default/it_IT.php | 8 + .../I18n/frontOffice/default/ru_RU.php | 9 + .../I18n/frontOffice/default/tr_TR.php | 9 + .../VirtualProductDelivery/I18n/it_IT.php | 7 + .../I18n/pdf/default/de_DE.php | 5 + .../I18n/pdf/default/en_US.php | 5 + .../I18n/pdf/default/fr_FR.php | 5 + .../I18n/pdf/default/it_IT.php | 5 + .../I18n/pdf/default/ru_RU.php | 5 + .../I18n/pdf/default/tr_TR.php | 5 + .../VirtualProductDelivery/I18n/ru_RU.php | 8 + .../VirtualProductDelivery/I18n/tr_TR.php | 8 + .../VirtualProductDelivery/LICENSE.txt | 165 + .../VirtualProductDelivery.php | 109 + .../VirtualProductDelivery/composer.json | 11 + .../default/virtual-product-download.html | 29 + .../default/virtual-product-download.txt | 26 + .../default/account-order-after-products.html | 24 + .../frontOffice/default/delivery-address.html | 6 + .../pdf/default/delivery-address.html | 3 + php-cs | 26 + php-cs.bat | 27 + phpunit.xml | 28 + reset_install.bat | 53 + reset_install.sh | 46 + run-tests.sh | 36 + setup/.gitkeep | 0 setup/.htaccess | 2 + setup/I18n/ar_SA.php | 14 + setup/I18n/cs_CZ.php | 9 + setup/I18n/de_DE.php | 1037 ++ setup/I18n/el_GR.php | 7 + setup/I18n/en_US.php | 1476 ++ setup/I18n/es_ES.php | 1071 ++ setup/I18n/fa_IR.php | 311 + setup/I18n/fr_FR.php | 1460 ++ setup/I18n/hu_HU.php | 17 + setup/I18n/id_ID.php | 49 + setup/I18n/it_IT.php | 165 + setup/I18n/pl_PL.php | 479 + setup/I18n/pt_BR.php | 72 + setup/I18n/pt_PT.php | 5 + setup/I18n/ru_RU.php | 1449 ++ setup/I18n/sk_SK.php | 527 + setup/I18n/tr_TR.php | 1020 ++ setup/I18n/uk_UA.php | 8 + setup/Readme.md | 35 + setup/composer.json | 11 + setup/faker-assets/FreeSans.ttf | Bin 0 -> 714456 bytes setup/faker.php | 1212 ++ ...er_100categories_1000products_4locales.php | 200 + setup/faker_add_ecotax.php | 153 + setup/import.php | 736 + setup/import/brand.csv | 8 + setup/import/categories.csv | 5 + setup/import/colors.csv | 13 + setup/import/contents.csv | 12 + setup/import/folders.csv | 4 + setup/import/images/BRAND-1.png | Bin 0 -> 2971 bytes setup/import/images/BRAND-2.png | Bin 0 -> 4475 bytes setup/import/images/BRAND-3.png | Bin 0 -> 4211 bytes setup/import/images/BRAND-4.png | Bin 0 -> 3385 bytes setup/import/images/BRAND-5.png | Bin 0 -> 2537 bytes setup/import/images/BRAND-6.png | Bin 0 -> 3120 bytes setup/import/images/BRAND-7.png | Bin 0 -> 2493 bytes setup/import/images/PROD001-1.jpg | Bin 0 -> 51530 bytes setup/import/images/PROD001-2.jpg | Bin 0 -> 107655 bytes setup/import/images/PROD001-3.jpg | Bin 0 -> 102141 bytes setup/import/images/PROD001-4.jpg | Bin 0 -> 110433 bytes setup/import/images/PROD001-5.jpg | Bin 0 -> 104065 bytes setup/import/images/PROD002-1.jpg | Bin 0 -> 141375 bytes setup/import/images/PROD002-2.jpg | Bin 0 -> 126842 bytes setup/import/images/PROD002-3.jpg | Bin 0 -> 74860 bytes setup/import/images/PROD002-4.jpg | Bin 0 -> 130917 bytes setup/import/images/PROD002-5.jpg | Bin 0 -> 129799 bytes setup/import/images/PROD002-6.jpg | Bin 0 -> 129033 bytes setup/import/images/PROD003-1.jpg | Bin 0 -> 161005 bytes setup/import/images/PROD003-2.jpg | Bin 0 -> 273666 bytes setup/import/images/PROD003-3.jpg | Bin 0 -> 260235 bytes setup/import/images/PROD004-1.jpg | Bin 0 -> 222092 bytes setup/import/images/PROD004-2.jpg | Bin 0 -> 126083 bytes setup/import/images/PROD005-1.jpg | Bin 0 -> 159109 bytes setup/import/images/PROD005-2.jpg | Bin 0 -> 144986 bytes setup/import/images/PROD005-3.jpg | Bin 0 -> 144428 bytes setup/import/images/PROD005-4.jpg | Bin 0 -> 80662 bytes setup/import/images/PROD005-5.jpg | Bin 0 -> 147598 bytes setup/import/images/PROD005-6.jpg | Bin 0 -> 142119 bytes setup/import/images/PROD006-1.jpg | Bin 0 -> 212734 bytes setup/import/images/PROD006-2.jpg | Bin 0 -> 130205 bytes setup/import/images/PROD006-3.jpg | Bin 0 -> 212881 bytes setup/import/images/PROD006-4.jpg | Bin 0 -> 207544 bytes setup/import/images/PROD006-5.jpg | Bin 0 -> 207550 bytes setup/import/images/PROD006-6.jpg | Bin 0 -> 203885 bytes setup/import/images/PROD007-1.jpg | Bin 0 -> 259549 bytes setup/import/images/PROD007-2.jpg | Bin 0 -> 162689 bytes setup/import/images/PROD007-3.jpg | Bin 0 -> 253321 bytes setup/import/images/PROD007-4.jpg | Bin 0 -> 252812 bytes setup/import/images/PROD008-1.jpg | Bin 0 -> 181374 bytes setup/import/images/PROD008-2.jpg | Bin 0 -> 123162 bytes setup/import/images/PROD008-3.jpg | Bin 0 -> 187983 bytes setup/import/images/PROD008-4.jpg | Bin 0 -> 194568 bytes setup/import/images/PROD008-5.jpg | Bin 0 -> 187981 bytes setup/import/images/PROD009-1.jpg | Bin 0 -> 129523 bytes setup/import/images/PROD009-2.jpg | Bin 0 -> 125658 bytes setup/import/images/PROD009-3.jpg | Bin 0 -> 75371 bytes setup/import/images/PROD010-1.jpg | Bin 0 -> 270871 bytes setup/import/images/PROD010-2.jpg | Bin 0 -> 163859 bytes setup/import/images/PROD010-3.jpg | Bin 0 -> 269221 bytes setup/import/images/PROD010-4.jpg | Bin 0 -> 260667 bytes setup/import/images/PROD011-1.jpg | Bin 0 -> 102640 bytes setup/import/images/PROD011-2.jpg | Bin 0 -> 110539 bytes setup/import/images/PROD011-3.jpg | Bin 0 -> 62472 bytes setup/import/images/PROD011-4.jpg | Bin 0 -> 108904 bytes setup/import/images/PROD012-1.jpg | Bin 0 -> 102300 bytes setup/import/images/PROD012-2.jpg | Bin 0 -> 69442 bytes setup/import/images/PROD013-1.jpg | Bin 0 -> 78899 bytes setup/import/images/PROD014-1.jpg | Bin 0 -> 110756 bytes setup/import/images/PROD014-2.jpg | Bin 0 -> 102460 bytes setup/import/images/PROD014-3.jpg | Bin 0 -> 53851 bytes setup/import/images/PROD014-4.jpg | Bin 0 -> 104170 bytes setup/import/images/PROD015-1.jpg | Bin 0 -> 47001 bytes setup/import/images/PROD015-2.jpg | Bin 0 -> 56064 bytes setup/import/images/PROD016-1.jpg | Bin 0 -> 137406 bytes setup/import/images/PROD017-1.jpg | Bin 0 -> 236732 bytes setup/import/images/PROD017-2.jpg | Bin 0 -> 147344 bytes setup/import/images/PROD017-3.jpg | Bin 0 -> 228760 bytes setup/import/images/PROD017-4.jpg | Bin 0 -> 226685 bytes setup/import/images/PROD018-1.jpg | Bin 0 -> 123433 bytes setup/import/images/PROD019-1.jpg | Bin 0 -> 151176 bytes setup/import/images/PROD019-2.jpg | Bin 0 -> 149869 bytes setup/import/images/PROD019-3.jpg | Bin 0 -> 84850 bytes setup/import/images/PROD019-4.jpg | Bin 0 -> 139488 bytes setup/import/images/PROD019-5.jpg | Bin 0 -> 143401 bytes setup/import/images/PROD020-1.jpg | Bin 0 -> 98667 bytes setup/import/images/PROD021-1.jpg | Bin 0 -> 106484 bytes setup/import/images/PROD021-2.jpg | Bin 0 -> 99998 bytes setup/import/images/PROD021-3.jpg | Bin 0 -> 96702 bytes setup/import/images/PROD021-4.jpg | Bin 0 -> 57175 bytes setup/import/images/PROD022-1.jpg | Bin 0 -> 103553 bytes setup/import/images/PROD022-2.jpg | Bin 0 -> 171743 bytes setup/import/images/PROD022-3.jpg | Bin 0 -> 161598 bytes setup/import/images/PROD022-4.jpg | Bin 0 -> 159802 bytes setup/import/images/PROD022-5.jpg | Bin 0 -> 161319 bytes setup/import/images/PROD023-1.jpg | Bin 0 -> 110195 bytes setup/import/images/PROD023-2.jpg | Bin 0 -> 105260 bytes setup/import/images/PROD023-3.jpg | Bin 0 -> 62720 bytes setup/import/images/PROD023-4.jpg | Bin 0 -> 107624 bytes setup/import/images/PROD023-5.jpg | Bin 0 -> 105364 bytes setup/import/images/PROD023-6.jpg | Bin 0 -> 105234 bytes setup/import/images/PROD024-1.jpg | Bin 0 -> 223246 bytes setup/import/images/PROD024-2.jpg | Bin 0 -> 222622 bytes setup/import/images/PROD024-3.jpg | Bin 0 -> 227376 bytes setup/import/images/PROD024-4.jpg | Bin 0 -> 216044 bytes setup/import/images/PROD024-5.jpg | Bin 0 -> 142595 bytes setup/import/images/PROD025-1.jpg | Bin 0 -> 132408 bytes setup/import/images/PROD025-2.jpg | Bin 0 -> 213549 bytes setup/import/images/PROD025-3.jpg | Bin 0 -> 208498 bytes setup/import/images/PROD026-1.jpg | Bin 0 -> 62512 bytes setup/import/images/PROD027-1.jpg | Bin 0 -> 69921 bytes setup/import/images/PROD028-1.jpg | Bin 0 -> 88061 bytes setup/import/images/PROD029-1.jpg | Bin 0 -> 69804 bytes setup/import/images/PROD030-1.jpg | Bin 0 -> 102772 bytes setup/import/images/PROD030-2.jpg | Bin 0 -> 95951 bytes setup/import/images/PROD030-3.jpg | Bin 0 -> 125918 bytes setup/import/images/PROD030-4.jpg | Bin 0 -> 98349 bytes setup/import/materials.csv | 6 + setup/import/products.csv | 35 + setup/insert.sql | 12146 ++++++++++++++++ setup/insert.sql.tpl | 3503 +++++ setup/tax_faker.php | 137 + setup/thelia.sql | 3473 +++++ setup/update.php | 298 + setup/update/instruction/2.3.0-alpha1.md | 10 + setup/update/php/.gitkeep | 0 setup/update/php/2.0.7.php | 7 + setup/update/php/2.1.3.php | 7 + setup/update/php/2.2.0-beta1.php | 42 + setup/update/php/2.2.0-beta3.php | 53 + setup/update/php/2.3.0-alpha2.php | 29 + setup/update/php/2.4.0.php | 38 + setup/update/sql/.gitkeep | 0 setup/update/sql/2.0.0-RC1.sql | 24 + setup/update/sql/2.0.0-beta2.sql | 362 + setup/update/sql/2.0.0-beta3.sql | 53 + setup/update/sql/2.0.0-beta4.sql | 26 + setup/update/sql/2.0.0.sql | 60 + setup/update/sql/2.0.1.sql | 86 + setup/update/sql/2.0.10.sql | 8 + setup/update/sql/2.0.11.sql | 8 + setup/update/sql/2.0.12.sql | 8 + setup/update/sql/2.0.2.sql | 129 + setup/update/sql/2.0.3-beta.sql | 596 + setup/update/sql/2.0.3-beta2.sql | 9 + setup/update/sql/2.0.3.sql | 6 + setup/update/sql/2.0.4.sql | 42 + setup/update/sql/2.0.5.sql | 24 + setup/update/sql/2.0.6.sql | 8 + setup/update/sql/2.0.7.sql | 8 + setup/update/sql/2.0.8.sql | 8 + setup/update/sql/2.0.9.sql | 8 + setup/update/sql/2.1.0-alpha1.sql | 3209 ++++ setup/update/sql/2.1.0-alpha2.sql | 181 + setup/update/sql/2.1.0-beta1.sql | 280 + setup/update/sql/2.1.0-beta2.sql | 31 + setup/update/sql/2.1.0.sql | 54 + setup/update/sql/2.1.1.sql | 10 + setup/update/sql/2.1.10.sql | 9 + setup/update/sql/2.1.11.sql | 9 + setup/update/sql/2.1.2.sql | 46 + setup/update/sql/2.1.3.sql | 16 + setup/update/sql/2.1.4.sql | 27 + setup/update/sql/2.1.5.sql | 32 + setup/update/sql/2.1.6.sql | 11 + setup/update/sql/2.1.7.sql | 45 + setup/update/sql/2.1.8.sql | 9 + setup/update/sql/2.1.9.sql | 9 + setup/update/sql/2.2.0-alpha1.sql | 417 + setup/update/sql/2.2.0-alpha2.sql | 51 + setup/update/sql/2.2.0-beta1.sql | 40 + setup/update/sql/2.2.0-beta2.sql | 5 + setup/update/sql/2.2.0-beta3.sql | 69 + setup/update/sql/2.2.0.sql | 9 + setup/update/sql/2.2.1.sql | 45 + setup/update/sql/2.2.2.sql | 9 + setup/update/sql/2.2.3.sql | 11 + setup/update/sql/2.2.4.sql | 9 + setup/update/sql/2.2.6.sql | 9 + setup/update/sql/2.3.0-alpha1.sql | 2010 +++ setup/update/sql/2.3.0-alpha2.sql | 239 + setup/update/sql/2.3.0-beta1.sql | 18 + setup/update/sql/2.3.0-beta2.sql | 12 + setup/update/sql/2.3.0.sql | 12 + setup/update/sql/2.3.1.sql | 9 + setup/update/sql/2.3.2.sql | 9 + setup/update/sql/2.3.3.sql | 9 + setup/update/sql/2.3.4.sql | 448 + setup/update/sql/2.3.5.sql | 9 + setup/update/sql/2.4.0-alpha1.sql | 9 + setup/update/sql/2.4.0-alpha2.sql | 21 + setup/update/sql/2.4.0.sql | 9 + setup/update/sql/2.4.1.sql | 9 + setup/update/sql/2.4.2.sql | 9 + setup/update/sql/2.4.3.sql | 28 + setup/update/tpl/2.0.0-RC1.sql.tpl | 24 + setup/update/tpl/2.0.0-beta2.sql.tpl | 362 + setup/update/tpl/2.0.0-beta3.sql.tpl | 53 + setup/update/tpl/2.0.0-beta4.sql.tpl | 26 + setup/update/tpl/2.0.0.sql.tpl | 60 + setup/update/tpl/2.0.1.sql.tpl | 62 + setup/update/tpl/2.0.10.sql.tpl | 8 + setup/update/tpl/2.0.11.sql.tpl | 8 + setup/update/tpl/2.0.12.sql.tpl | 8 + setup/update/tpl/2.0.2.sql.tpl | 129 + setup/update/tpl/2.0.3-beta.sql.tpl | 590 + setup/update/tpl/2.0.3-beta2.sql.tpl | 9 + setup/update/tpl/2.0.3.sql.tpl | 6 + setup/update/tpl/2.0.4.sql.tpl | 42 + setup/update/tpl/2.0.5.sql.tpl | 24 + setup/update/tpl/2.0.6.sql.tpl | 8 + setup/update/tpl/2.0.7.sql.tpl | 8 + setup/update/tpl/2.0.8.sql.tpl | 8 + setup/update/tpl/2.0.9.sql.tpl | 8 + setup/update/tpl/2.1.0-alpha1.sql.tpl | 1616 ++ setup/update/tpl/2.1.0-alpha2.sql.tpl | 118 + setup/update/tpl/2.1.0-beta1.sql.tpl | 160 + setup/update/tpl/2.1.0-beta2.sql.tpl | 25 + setup/update/tpl/2.1.0.sql.tpl | 42 + setup/update/tpl/2.1.1.sql.tpl | 10 + setup/update/tpl/2.1.10.sql.tpl | 9 + setup/update/tpl/2.1.11.sql.tpl | 9 + setup/update/tpl/2.1.2.sql.tpl | 46 + setup/update/tpl/2.1.3.sql.tpl | 16 + setup/update/tpl/2.1.4.sql.tpl | 24 + setup/update/tpl/2.1.5.sql.tpl | 29 + setup/update/tpl/2.1.6.sql.tpl | 11 + setup/update/tpl/2.1.7.sql.tpl | 45 + setup/update/tpl/2.1.8.sql.tpl | 9 + setup/update/tpl/2.1.9.sql.tpl | 9 + setup/update/tpl/2.2.0-alpha1.sql.tpl | 222 + setup/update/tpl/2.2.0-alpha2.sql.tpl | 36 + setup/update/tpl/2.2.0-beta1.sql.tpl | 34 + setup/update/tpl/2.2.0-beta2.sql.tpl | 5 + setup/update/tpl/2.2.0-beta3.sql.tpl | 51 + setup/update/tpl/2.2.0.sql.tpl | 9 + setup/update/tpl/2.2.1.sql.tpl | 45 + setup/update/tpl/2.2.2.sql.tpl | 9 + setup/update/tpl/2.2.3.sql.tpl | 11 + setup/update/tpl/2.2.4.sql.tpl | 9 + setup/update/tpl/2.2.6.sql.tpl | 9 + setup/update/tpl/2.3.0-alpha1.sql.tpl | 909 ++ setup/update/tpl/2.3.0-alpha2.sql.tpl | 182 + setup/update/tpl/2.3.0-beta1.sql.tpl | 18 + setup/update/tpl/2.3.0-beta2.sql.tpl | 12 + setup/update/tpl/2.3.0.sql.tpl | 12 + setup/update/tpl/2.3.1.sql.tpl | 9 + setup/update/tpl/2.3.2.sql.tpl | 9 + setup/update/tpl/2.3.3.sql.tpl | 9 + setup/update/tpl/2.3.4.sql.tpl | 143 + setup/update/tpl/2.3.5.sql.tpl | 9 + setup/update/tpl/2.4.0-alpha1.sql.tpl | 9 + setup/update/tpl/2.4.0-alpha2.sql.tpl | 21 + setup/update/tpl/2.4.0.sql.tpl | 9 + setup/update/tpl/2.4.1.sql.tpl | 9 + setup/update/tpl/2.4.2.sql.tpl | 9 + setup/update/tpl/2.4.3.sql.tpl | 25 + templates/backOffice/default/404.html | 9 + templates/backOffice/default/I18n/ar_SA.php | 341 + templates/backOffice/default/I18n/cs_CZ.php | 39 + templates/backOffice/default/I18n/de_DE.php | 1287 ++ templates/backOffice/default/I18n/el_GR.php | 62 + templates/backOffice/default/I18n/en_US.php | 1351 ++ templates/backOffice/default/I18n/es_ES.php | 1297 ++ templates/backOffice/default/I18n/fa_IR.php | 1222 ++ templates/backOffice/default/I18n/fr_FR.php | 1351 ++ templates/backOffice/default/I18n/he_IL.php | 8 + templates/backOffice/default/I18n/hu_HU.php | 851 ++ templates/backOffice/default/I18n/id_ID.php | 121 + templates/backOffice/default/I18n/it_IT.php | 1241 ++ templates/backOffice/default/I18n/nl_NL.php | 66 + templates/backOffice/default/I18n/pl_PL.php | 163 + templates/backOffice/default/I18n/pt_BR.php | 352 + templates/backOffice/default/I18n/pt_PT.php | 51 + templates/backOffice/default/I18n/ru_RU.php | 1307 ++ templates/backOffice/default/I18n/sk_SK.php | 488 + templates/backOffice/default/I18n/tr_TR.php | 1225 ++ templates/backOffice/default/I18n/uk_UA.php | 21 + templates/backOffice/default/I18n/zh_CN.php | 13 + templates/backOffice/default/LICENSE.txt | 165 + templates/backOffice/default/Readme.md | 18 + templates/backOffice/default/admin-layout.tpl | 227 + templates/backOffice/default/admin-logs.html | 229 + .../backOffice/default/administrators.html | 431 + .../default/advanced-configuration.html | 81 + .../backOffice/default/ajax/export-modal.html | 44 + .../backOffice/default/ajax/import-modal.html | 38 + .../default/ajax/language-update-modal.html | 99 + templates/backOffice/default/ajax/logger.html | 11 + .../default/ajax/module-information.html | 152 + .../default/ajax/product-attributes-tab.html | 267 + .../default/ajax/product-related-tab.html | 623 + .../ajax/pse-image-document-assoc-modal.html | 93 + .../ajax/sale-edit-product-attributes.html | 33 + .../default/ajax/sale-edit-products.html | 72 + .../default/ajax/template-attribute-list.html | 138 + .../default/ajax/template-feature-list.html | 140 + templates/backOffice/default/api.html | 262 + .../backOffice/default/assets/css/styles.css | 9758 +++++++++++++ .../glyphicons-halflings-regular.eot | Bin 0 -> 20335 bytes .../glyphicons-halflings-regular.svg | 229 + .../glyphicons-halflings-regular.ttf | Bin 0 -> 41280 bytes .../glyphicons-halflings-regular.woff | Bin 0 -> 23320 bytes .../default/assets/fonts/thelia/thelia.eot | Bin 0 -> 6300 bytes .../default/assets/fonts/thelia/thelia.svg | 38 + .../default/assets/fonts/thelia/thelia.ttf | Bin 0 -> 6140 bytes .../default/assets/fonts/thelia/thelia.woff | Bin 0 -> 6216 bytes .../default/assets/img/ajax-loader.gif | Bin 0 -> 13582 bytes .../backOffice/default/assets/img/bg.jpg | Bin 0 -> 50205 bytes .../backOffice/default/assets/img/clear.png | Bin 0 -> 509 bytes .../default/assets/img/deconnexion.png | Bin 0 -> 3718 bytes .../backOffice/default/assets/img/favicon.ico | Bin 0 -> 3447 bytes .../default/assets/img/flags/ad.png | Bin 0 -> 263 bytes .../default/assets/img/flags/ae.png | Bin 0 -> 107 bytes .../default/assets/img/flags/af.png | Bin 0 -> 259 bytes .../default/assets/img/flags/ag.png | Bin 0 -> 302 bytes .../default/assets/img/flags/ai.png | Bin 0 -> 332 bytes .../default/assets/img/flags/al.png | Bin 0 -> 291 bytes .../default/assets/img/flags/am.png | Bin 0 -> 105 bytes .../default/assets/img/flags/an.png | Bin 0 -> 145 bytes .../default/assets/img/flags/ao.png | Bin 0 -> 241 bytes .../default/assets/img/flags/aq.png | Bin 0 -> 382 bytes .../default/assets/img/flags/ar.png | Bin 0 -> 209 bytes .../default/assets/img/flags/as.png | Bin 0 -> 448 bytes .../default/assets/img/flags/at.png | Bin 0 -> 98 bytes .../default/assets/img/flags/au.png | Bin 0 -> 228 bytes .../default/assets/img/flags/aw.png | Bin 0 -> 182 bytes .../default/assets/img/flags/ax.png | Bin 0 -> 121 bytes .../default/assets/img/flags/az.png | Bin 0 -> 267 bytes .../default/assets/img/flags/ba.png | Bin 0 -> 355 bytes .../default/assets/img/flags/bb.png | Bin 0 -> 159 bytes .../default/assets/img/flags/bd.png | Bin 0 -> 211 bytes .../default/assets/img/flags/be.png | Bin 0 -> 102 bytes .../default/assets/img/flags/bf.png | Bin 0 -> 166 bytes .../default/assets/img/flags/bg.png | Bin 0 -> 103 bytes .../default/assets/img/flags/bh.png | Bin 0 -> 129 bytes .../default/assets/img/flags/bi.png | Bin 0 -> 454 bytes .../default/assets/img/flags/bj.png | Bin 0 -> 106 bytes .../default/assets/img/flags/bl.png | Bin 0 -> 539 bytes .../default/assets/img/flags/bm.png | Bin 0 -> 321 bytes .../default/assets/img/flags/bn.png | Bin 0 -> 518 bytes .../default/assets/img/flags/bo.png | Bin 0 -> 236 bytes .../default/assets/img/flags/br.png | Bin 0 -> 432 bytes .../default/assets/img/flags/bs.png | Bin 0 -> 171 bytes .../default/assets/img/flags/bt.png | Bin 0 -> 449 bytes .../default/assets/img/flags/bw.png | Bin 0 -> 108 bytes .../default/assets/img/flags/by.png | Bin 0 -> 151 bytes .../default/assets/img/flags/bz.png | Bin 0 -> 337 bytes .../default/assets/img/flags/ca.png | Bin 0 -> 177 bytes .../default/assets/img/flags/cc.png | Bin 0 -> 259 bytes .../default/assets/img/flags/cd.png | Bin 0 -> 432 bytes .../default/assets/img/flags/cf.png | Bin 0 -> 162 bytes .../default/assets/img/flags/cg.png | Bin 0 -> 152 bytes .../default/assets/img/flags/ch.png | Bin 0 -> 100 bytes .../default/assets/img/flags/ci.png | Bin 0 -> 100 bytes .../default/assets/img/flags/ck.png | Bin 0 -> 331 bytes .../default/assets/img/flags/cl.png | Bin 0 -> 150 bytes .../default/assets/img/flags/cm.png | Bin 0 -> 163 bytes .../default/assets/img/flags/cn.png | Bin 0 -> 310 bytes .../default/assets/img/flags/co.png | Bin 0 -> 108 bytes .../default/assets/img/flags/cr.png | Bin 0 -> 110 bytes .../default/assets/img/flags/cs.png | Bin 0 -> 221 bytes .../default/assets/img/flags/cu.png | Bin 0 -> 215 bytes .../default/assets/img/flags/cv.png | Bin 0 -> 138 bytes .../default/assets/img/flags/cw.png | Bin 0 -> 191 bytes .../default/assets/img/flags/cx.png | Bin 0 -> 390 bytes .../default/assets/img/flags/cy.png | Bin 0 -> 364 bytes .../default/assets/img/flags/de.png | Bin 0 -> 102 bytes .../default/assets/img/flags/dj.png | Bin 0 -> 228 bytes .../default/assets/img/flags/dk.png | Bin 0 -> 106 bytes .../default/assets/img/flags/dm.png | Bin 0 -> 333 bytes .../default/assets/img/flags/do.png | Bin 0 -> 142 bytes .../default/assets/img/flags/dz.png | Bin 0 -> 309 bytes .../default/assets/img/flags/ec.png | Bin 0 -> 264 bytes .../default/assets/img/flags/ee.png | Bin 0 -> 102 bytes .../default/assets/img/flags/eg.png | Bin 0 -> 199 bytes .../default/assets/img/flags/eh.png | Bin 0 -> 248 bytes .../default/assets/img/flags/en.png | Bin 0 -> 353 bytes .../default/assets/img/flags/er.png | Bin 0 -> 421 bytes .../default/assets/img/flags/es.png | Bin 0 -> 221 bytes .../default/assets/img/flags/et.png | Bin 0 -> 420 bytes .../default/assets/img/flags/eu.png | Bin 0 -> 316 bytes .../default/assets/img/flags/fi.png | Bin 0 -> 103 bytes .../default/assets/img/flags/fj.png | Bin 0 -> 387 bytes .../default/assets/img/flags/fk.png | Bin 0 -> 344 bytes .../default/assets/img/flags/fm.png | Bin 0 -> 198 bytes .../default/assets/img/flags/fo.png | Bin 0 -> 122 bytes .../default/assets/img/flags/fr.png | Bin 0 -> 100 bytes .../default/assets/img/flags/ga.png | Bin 0 -> 108 bytes .../default/assets/img/flags/gb.png | Bin 0 -> 626 bytes .../default/assets/img/flags/gd.png | Bin 0 -> 313 bytes .../default/assets/img/flags/ge.png | Bin 0 -> 122 bytes .../default/assets/img/flags/gg.png | Bin 0 -> 124 bytes .../default/assets/img/flags/gh.png | Bin 0 -> 162 bytes .../default/assets/img/flags/gi.png | Bin 0 -> 245 bytes .../default/assets/img/flags/gl.png | Bin 0 -> 196 bytes .../default/assets/img/flags/gm.png | Bin 0 -> 115 bytes .../default/assets/img/flags/gn.png | Bin 0 -> 103 bytes .../default/assets/img/flags/gq.png | Bin 0 -> 308 bytes .../default/assets/img/flags/gr.png | Bin 0 -> 141 bytes .../default/assets/img/flags/gs.png | Bin 0 -> 455 bytes .../default/assets/img/flags/gt.png | Bin 0 -> 198 bytes .../default/assets/img/flags/gu.png | Bin 0 -> 228 bytes .../default/assets/img/flags/gw.png | Bin 0 -> 149 bytes .../default/assets/img/flags/gy.png | Bin 0 -> 393 bytes .../default/assets/img/flags/hk.png | Bin 0 -> 418 bytes .../default/assets/img/flags/hn.png | Bin 0 -> 154 bytes .../default/assets/img/flags/hr.png | Bin 0 -> 391 bytes .../default/assets/img/flags/ht.png | Bin 0 -> 206 bytes .../default/assets/img/flags/hu.png | Bin 0 -> 104 bytes .../default/assets/img/flags/ic.png | Bin 0 -> 183 bytes .../default/assets/img/flags/id.png | Bin 0 -> 98 bytes .../default/assets/img/flags/ie.png | Bin 0 -> 99 bytes .../default/assets/img/flags/il.png | Bin 0 -> 180 bytes .../default/assets/img/flags/im.png | Bin 0 -> 367 bytes .../default/assets/img/flags/in.png | Bin 0 -> 194 bytes .../default/assets/img/flags/iq.png | Bin 0 -> 269 bytes .../default/assets/img/flags/ir.png | Bin 0 -> 356 bytes .../default/assets/img/flags/is.png | Bin 0 -> 124 bytes .../default/assets/img/flags/it.png | Bin 0 -> 100 bytes .../default/assets/img/flags/je.png | Bin 0 -> 403 bytes .../default/assets/img/flags/jm.png | Bin 0 -> 392 bytes .../default/assets/img/flags/jo.png | Bin 0 -> 236 bytes .../default/assets/img/flags/jp.png | Bin 0 -> 155 bytes .../default/assets/img/flags/ke.png | Bin 0 -> 324 bytes .../default/assets/img/flags/kg.png | Bin 0 -> 380 bytes .../default/assets/img/flags/kh.png | Bin 0 -> 232 bytes .../default/assets/img/flags/ki.png | Bin 0 -> 517 bytes .../default/assets/img/flags/km.png | Bin 0 -> 272 bytes .../default/assets/img/flags/kn.png | Bin 0 -> 403 bytes .../default/assets/img/flags/kp.png | Bin 0 -> 197 bytes .../default/assets/img/flags/kr.png | Bin 0 -> 413 bytes .../default/assets/img/flags/kw.png | Bin 0 -> 185 bytes .../default/assets/img/flags/ky.png | Bin 0 -> 338 bytes .../default/assets/img/flags/kz.png | Bin 0 -> 405 bytes .../default/assets/img/flags/la.png | Bin 0 -> 175 bytes .../default/assets/img/flags/lb.png | Bin 0 -> 213 bytes .../default/assets/img/flags/lc.png | Bin 0 -> 197 bytes .../default/assets/img/flags/li.png | Bin 0 -> 216 bytes .../default/assets/img/flags/lk.png | Bin 0 -> 325 bytes .../default/assets/img/flags/lr.png | Bin 0 -> 142 bytes .../default/assets/img/flags/ls.png | Bin 0 -> 200 bytes .../default/assets/img/flags/lt.png | Bin 0 -> 108 bytes .../default/assets/img/flags/lu.png | Bin 0 -> 105 bytes .../default/assets/img/flags/lv.png | Bin 0 -> 99 bytes .../default/assets/img/flags/ly.png | Bin 0 -> 212 bytes .../default/assets/img/flags/ma.png | Bin 0 -> 302 bytes .../default/assets/img/flags/mc.png | Bin 0 -> 98 bytes .../default/assets/img/flags/md.png | Bin 0 -> 190 bytes .../default/assets/img/flags/me.png | Bin 0 -> 323 bytes .../default/assets/img/flags/mf.png | Bin 0 -> 161 bytes .../default/assets/img/flags/mg.png | Bin 0 -> 101 bytes .../default/assets/img/flags/mh.png | Bin 0 -> 382 bytes .../default/assets/img/flags/mk.png | Bin 0 -> 378 bytes .../default/assets/img/flags/ml.png | Bin 0 -> 103 bytes .../default/assets/img/flags/mm.png | Bin 0 -> 195 bytes .../default/assets/img/flags/mn.png | Bin 0 -> 225 bytes .../default/assets/img/flags/mo.png | Bin 0 -> 413 bytes .../default/assets/img/flags/mp.png | Bin 0 -> 548 bytes .../default/assets/img/flags/mq.png | Bin 0 -> 202 bytes .../default/assets/img/flags/mr.png | Bin 0 -> 250 bytes .../default/assets/img/flags/ms.png | Bin 0 -> 346 bytes .../default/assets/img/flags/mt.png | Bin 0 -> 114 bytes .../default/assets/img/flags/mu.png | Bin 0 -> 116 bytes .../default/assets/img/flags/mv.png | Bin 0 -> 201 bytes .../default/assets/img/flags/mw.png | Bin 0 -> 193 bytes .../default/assets/img/flags/mx.png | Bin 0 -> 207 bytes .../default/assets/img/flags/my.png | Bin 0 -> 236 bytes .../default/assets/img/flags/mz.png | Bin 0 -> 315 bytes .../default/assets/img/flags/na.png | Bin 0 -> 452 bytes .../default/assets/img/flags/nc.png | Bin 0 -> 325 bytes .../default/assets/img/flags/ne.png | Bin 0 -> 153 bytes .../default/assets/img/flags/nf.png | Bin 0 -> 295 bytes .../default/assets/img/flags/ng.png | Bin 0 -> 98 bytes .../default/assets/img/flags/ni.png | Bin 0 -> 210 bytes .../default/assets/img/flags/nl.png | Bin 0 -> 104 bytes .../default/assets/img/flags/no.png | Bin 0 -> 124 bytes .../default/assets/img/flags/np.png | Bin 0 -> 241 bytes .../default/assets/img/flags/nr.png | Bin 0 -> 172 bytes .../default/assets/img/flags/nu.png | Bin 0 -> 252 bytes .../default/assets/img/flags/nz.png | Bin 0 -> 200 bytes .../default/assets/img/flags/om.png | Bin 0 -> 198 bytes .../default/assets/img/flags/pa.png | Bin 0 -> 174 bytes .../default/assets/img/flags/pe.png | Bin 0 -> 98 bytes .../default/assets/img/flags/pf.png | Bin 0 -> 217 bytes .../default/assets/img/flags/pg.png | Bin 0 -> 444 bytes .../default/assets/img/flags/ph.png | Bin 0 -> 342 bytes .../default/assets/img/flags/pk.png | Bin 0 -> 306 bytes .../default/assets/img/flags/pl.png | Bin 0 -> 102 bytes .../default/assets/img/flags/pn.png | Bin 0 -> 423 bytes .../default/assets/img/flags/pr.png | Bin 0 -> 216 bytes .../default/assets/img/flags/ps.png | Bin 0 -> 157 bytes .../default/assets/img/flags/pt.png | Bin 0 -> 303 bytes .../default/assets/img/flags/pw.png | Bin 0 -> 209 bytes .../default/assets/img/flags/py.png | Bin 0 -> 197 bytes .../default/assets/img/flags/qa.png | Bin 0 -> 190 bytes .../default/assets/img/flags/ro.png | Bin 0 -> 103 bytes .../default/assets/img/flags/rs.png | Bin 0 -> 331 bytes .../default/assets/img/flags/ru.png | Bin 0 -> 98 bytes .../default/assets/img/flags/rw.png | Bin 0 -> 182 bytes .../default/assets/img/flags/sa.png | Bin 0 -> 426 bytes .../default/assets/img/flags/sb.png | Bin 0 -> 306 bytes .../default/assets/img/flags/sc.png | Bin 0 -> 314 bytes .../default/assets/img/flags/sd.png | Bin 0 -> 156 bytes .../default/assets/img/flags/se.png | Bin 0 -> 109 bytes .../default/assets/img/flags/sg.png | Bin 0 -> 253 bytes .../default/assets/img/flags/sh.png | Bin 0 -> 333 bytes .../default/assets/img/flags/si.png | Bin 0 -> 177 bytes .../default/assets/img/flags/sk.png | Bin 0 -> 225 bytes .../default/assets/img/flags/sl.png | Bin 0 -> 104 bytes .../default/assets/img/flags/sm.png | Bin 0 -> 291 bytes .../default/assets/img/flags/sn.png | Bin 0 -> 160 bytes .../default/assets/img/flags/so.png | Bin 0 -> 192 bytes .../default/assets/img/flags/sr.png | Bin 0 -> 166 bytes .../default/assets/img/flags/ss.png | Bin 0 -> 289 bytes .../default/assets/img/flags/st.png | Bin 0 -> 243 bytes .../default/assets/img/flags/sv.png | Bin 0 -> 209 bytes .../default/assets/img/flags/sy.png | Bin 0 -> 161 bytes .../default/assets/img/flags/sz.png | Bin 0 -> 366 bytes .../default/assets/img/flags/tc.png | Bin 0 -> 312 bytes .../default/assets/img/flags/td.png | Bin 0 -> 103 bytes .../default/assets/img/flags/tf.png | Bin 0 -> 224 bytes .../default/assets/img/flags/tg.png | Bin 0 -> 174 bytes .../default/assets/img/flags/th.png | Bin 0 -> 110 bytes .../default/assets/img/flags/tj.png | Bin 0 -> 203 bytes .../default/assets/img/flags/tk.png | Bin 0 -> 260 bytes .../default/assets/img/flags/tl.png | Bin 0 -> 277 bytes .../default/assets/img/flags/tm.png | Bin 0 -> 392 bytes .../default/assets/img/flags/tn.png | Bin 0 -> 271 bytes .../default/assets/img/flags/to.png | Bin 0 -> 114 bytes .../default/assets/img/flags/toto.png | Bin 0 -> 176 bytes .../default/assets/img/flags/tr.png | Bin 0 -> 311 bytes .../default/assets/img/flags/tt.png | Bin 0 -> 358 bytes .../default/assets/img/flags/tv.png | Bin 0 -> 398 bytes .../default/assets/img/flags/tw.png | Bin 0 -> 205 bytes .../default/assets/img/flags/tz.png | Bin 0 -> 415 bytes .../default/assets/img/flags/ua.png | Bin 0 -> 102 bytes .../default/assets/img/flags/ug.png | Bin 0 -> 188 bytes .../default/assets/img/flags/unknown.png | Bin 0 -> 176 bytes .../default/assets/img/flags/us.png | Bin 0 -> 120 bytes .../default/assets/img/flags/uy.png | Bin 0 -> 216 bytes .../default/assets/img/flags/uz.png | Bin 0 -> 163 bytes .../default/assets/img/flags/va.png | Bin 0 -> 202 bytes .../default/assets/img/flags/vc.png | Bin 0 -> 217 bytes .../default/assets/img/flags/ve.png | Bin 0 -> 302 bytes .../default/assets/img/flags/vg.png | Bin 0 -> 337 bytes .../default/assets/img/flags/vi.png | Bin 0 -> 500 bytes .../default/assets/img/flags/vn.png | Bin 0 -> 193 bytes .../default/assets/img/flags/vu.png | Bin 0 -> 302 bytes .../default/assets/img/flags/wf.png | Bin 0 -> 182 bytes .../default/assets/img/flags/ws.png | Bin 0 -> 236 bytes .../default/assets/img/flags/ye.png | Bin 0 -> 103 bytes .../default/assets/img/flags/yt.png | Bin 0 -> 482 bytes .../default/assets/img/flags/za.png | Bin 0 -> 348 bytes .../default/assets/img/flags/zm.png | Bin 0 -> 189 bytes .../default/assets/img/flags/zw.png | Bin 0 -> 300 bytes .../backOffice/default/assets/img/header.jpg | Bin 0 -> 10939 bytes .../backOffice/default/assets/img/loading.gif | Bin 0 -> 1849 bytes .../default/assets/img/logo-dark.png | Bin 0 -> 2880 bytes .../default/assets/img/logo-light.png | Bin 0 -> 3540 bytes .../default/assets/img/logo-thelia-34px.png | Bin 0 -> 5479 bytes .../default/assets/img/logo-white.png | Bin 0 -> 2931 bytes .../backOffice/default/assets/img/logo.png | Bin 0 -> 8016 bytes .../default/assets/img/top-bar-logo-save.png | Bin 0 -> 5696 bytes .../default/assets/img/top-bar-logo.png | Bin 0 -> 7224 bytes .../bootstrap-datetimepicker.min.css | 5 + .../bootstrap-datetimepicker.min.js | 9 + .../bootstrap-editable/bootstrap-editable.js | 6632 +++++++++ .../js/bootstrap-select/bootstrap-select.js | 709 + .../js/bootstrap-switch/bootstrap-switch.js | 382 + .../default/assets/js/bootstrap/bootstrap.js | 2114 +++ .../backOffice/default/assets/js/cookie.js | 63 + .../backOffice/default/assets/js/coupon.js | 322 + .../default/assets/js/document-upload.js | 208 + .../backOffice/default/assets/js/dropzone.js | 1758 +++ .../assets/js/image-picker/image-picker.css | 29 + .../js/image-picker/image-picker.min.js | 7 + .../default/assets/js/image-upload.js | 271 + .../assets/js/jqplot/jquery.jqplot.min.js | 3 + .../plugins/jqplot.BezierCurveRenderer.min.js | 3 + .../jqplot/plugins/jqplot.barRenderer.min.js | 3 + .../plugins/jqplot.blockRenderer.min.js | 3 + .../plugins/jqplot.bubbleRenderer.min.js | 3 + .../jqplot.canvasAxisLabelRenderer.min.js | 3 + .../jqplot.canvasAxisTickRenderer.min.js | 3 + .../plugins/jqplot.canvasOverlay.min.js | 3 + .../plugins/jqplot.canvasTextRenderer.min.js | 3 + .../jqplot.categoryAxisRenderer.min.js | 3 + .../js/jqplot/plugins/jqplot.ciParser.min.js | 3 + .../js/jqplot/plugins/jqplot.cursor.min.js | 3 + .../plugins/jqplot.dateAxisRenderer.min.js | 3 + .../plugins/jqplot.donutRenderer.min.js | 3 + .../js/jqplot/plugins/jqplot.dragable.min.js | 3 + .../jqplot.enhancedLegendRenderer.min.js | 3 + .../plugins/jqplot.funnelRenderer.min.js | 3 + .../jqplot/plugins/jqplot.highlighter.min.js | 3 + .../js/jqplot/plugins/jqplot.json2.min.js | 3 + .../plugins/jqplot.logAxisRenderer.min.js | 3 + .../plugins/jqplot.mekkoAxisRenderer.min.js | 3 + .../plugins/jqplot.mekkoRenderer.min.js | 3 + .../plugins/jqplot.meterGaugeRenderer.min.js | 3 + .../js/jqplot/plugins/jqplot.mobile.min.js | 3 + .../jqplot/plugins/jqplot.ohlcRenderer.min.js | 3 + .../jqplot/plugins/jqplot.pieRenderer.min.js | 3 + .../jqplot/plugins/jqplot.pointLabels.min.js | 3 + .../plugins/jqplot.pyramidAxisRenderer.min.js | 3 + .../plugins/jqplot.pyramidGridRenderer.min.js | 3 + .../plugins/jqplot.pyramidRenderer.min.js | 3 + .../js/jqplot/plugins/jqplot.trendline.min.js | 3 + .../assets/js/jquery-ui-1.10.3.custom.min.js | 7 + .../default/assets/js/jquery.min.js | 6 + .../default/assets/js/jquery.typewatch.js | 94 + .../i18n/jquery.ui.datepicker-es_ES.js | 23 + .../i18n/jquery.ui.datepicker-fr_FR.js | 25 + .../i18n/jquery.ui.datepicker-it_IT.js.js | 23 + .../jquery.ui.datepicker/i18n/readme.txt | 5 + .../jquery.ui.datepicker.css | 175 + .../jquery.ui.datepicker.js | 2059 +++ .../assets/js/jquery.ui/jquery.ui.theme.css | 410 + .../backOffice/default/assets/js/json2.js | 486 + .../default/assets/js/libs/jquery.js | 6 + .../assets/js/libs/jquery.toolbar.min.js | 2 + .../default/assets/js/libs/metis-menu.min.js | 10 + .../default/assets/js/libs/respond.min.js | 6 + .../default/assets/js/libs/underscore-min.js | 6 + .../backOffice/default/assets/js/main.js | 91 + .../assets/js/moment-with-locales.min.js | 10 + .../assets/js/tablesorter/jquery.metadata.js | 116 + .../js/tablesorter/jquery.tablesorter.min.js | 1477 ++ ...ry.tablesorter.widgets-filter-formatter.js | 826 ++ .../tablesorter/jquery.tablesorter.widgets.js | 1208 ++ .../default/assets/js/thelia-states.js | 67 + .../default/assets/less/bootstrap/alerts.less | 68 + .../default/assets/less/bootstrap/badges.less | 55 + .../assets/less/bootstrap/bootstrap.less | 50 + .../assets/less/bootstrap/breadcrumbs.less | 26 + .../assets/less/bootstrap/button-groups.less | 240 + .../assets/less/bootstrap/buttons.less | 157 + .../assets/less/bootstrap/carousel.less | 243 + .../default/assets/less/bootstrap/close.less | 33 + .../default/assets/less/bootstrap/code.less | 68 + .../less/bootstrap/component-animations.less | 31 + .../assets/less/bootstrap/dropdowns.less | 221 + .../default/assets/less/bootstrap/forms.less | 540 + .../assets/less/bootstrap/glyphicons.less | 233 + .../default/assets/less/bootstrap/grid.less | 84 + .../assets/less/bootstrap/input-groups.less | 166 + .../assets/less/bootstrap/jumbotron.less | 48 + .../default/assets/less/bootstrap/labels.less | 64 + .../assets/less/bootstrap/list-group.less | 131 + .../default/assets/less/bootstrap/media.less | 56 + .../default/assets/less/bootstrap/mixins.less | 39 + .../assets/less/bootstrap/mixins/alerts.less | 14 + .../bootstrap/mixins/background-variant.less | 8 + .../less/bootstrap/mixins/border-radius.less | 18 + .../assets/less/bootstrap/mixins/buttons.less | 50 + .../less/bootstrap/mixins/center-block.less | 7 + .../less/bootstrap/mixins/clearfix.less | 22 + .../assets/less/bootstrap/mixins/forms.less | 81 + .../less/bootstrap/mixins/gradients.less | 59 + .../less/bootstrap/mixins/grid-framework.less | 91 + .../assets/less/bootstrap/mixins/grid.less | 122 + .../less/bootstrap/mixins/hide-text.less | 21 + .../assets/less/bootstrap/mixins/image.less | 34 + .../assets/less/bootstrap/mixins/labels.less | 12 + .../less/bootstrap/mixins/list-group.less | 29 + .../less/bootstrap/mixins/nav-divider.less | 10 + .../bootstrap/mixins/nav-vertical-align.less | 9 + .../assets/less/bootstrap/mixins/opacity.less | 8 + .../less/bootstrap/mixins/pagination.less | 23 + .../assets/less/bootstrap/mixins/panels.less | 24 + .../less/bootstrap/mixins/progress-bar.less | 10 + .../less/bootstrap/mixins/reset-filter.less | 8 + .../assets/less/bootstrap/mixins/resize.less | 6 + .../mixins/responsive-visibility.less | 15 + .../assets/less/bootstrap/mixins/size.less | 10 + .../less/bootstrap/mixins/tab-focus.less | 9 + .../less/bootstrap/mixins/table-row.less | 28 + .../less/bootstrap/mixins/text-emphasis.less | 8 + .../less/bootstrap/mixins/text-overflow.less | 8 + .../bootstrap/mixins/vendor-prefixes.less | 224 + .../default/assets/less/bootstrap/modals.less | 150 + .../default/assets/less/bootstrap/navbar.less | 655 + .../default/assets/less/bootstrap/navs.less | 242 + .../assets/less/bootstrap/normalize.less | 425 + .../default/assets/less/bootstrap/pager.less | 55 + .../assets/less/bootstrap/pagination.less | 88 + .../default/assets/less/bootstrap/panels.less | 243 + .../assets/less/bootstrap/popovers.less | 133 + .../default/assets/less/bootstrap/print.less | 101 + .../assets/less/bootstrap/progress-bars.less | 105 + .../less/bootstrap/responsive-embed.less | 34 + .../less/bootstrap/responsive-utilities.less | 194 + .../assets/less/bootstrap/scaffolding.less | 150 + .../default/assets/less/bootstrap/tables.less | 233 + .../default/assets/less/bootstrap/theme.less | 258 + .../assets/less/bootstrap/thumbnails.less | 36 + .../assets/less/bootstrap/tooltip.less | 95 + .../default/assets/less/bootstrap/type.less | 313 + .../assets/less/bootstrap/utilities.less | 57 + .../assets/less/bootstrap/variables.less | 847 ++ .../default/assets/less/bootstrap/wells.less | 29 + .../backOffice/default/assets/less/main.less | 5 + .../less/thelia/bootstrap-editable.less | 655 + .../assets/less/thelia/bootstrap-select.less | 275 + .../assets/less/thelia/bootstrap-switch.less | 159 + .../assets/less/thelia/breadcrumbs.less | 20 + .../default/assets/less/thelia/buttons.less | 14 + .../assets/less/thelia/datepicker.less | 109 + .../default/assets/less/thelia/dropzone.less | 160 + .../default/assets/less/thelia/fonts.less | 72 + .../default/assets/less/thelia/forms.less | 225 + .../default/assets/less/thelia/grid.less | 43 + .../default/assets/less/thelia/jqplot.less | 27 + .../default/assets/less/thelia/labels.less | 10 + .../default/assets/less/thelia/logger.less | 28 + .../assets/less/thelia/login-page.less | 60 + .../default/assets/less/thelia/mixins.less | 81 + .../default/assets/less/thelia/modals.less | 66 + .../default/assets/less/thelia/navbar.less | 128 + .../assets/less/thelia/responsive.less | 24 + .../assets/less/thelia/scaffolding.less | 31 + .../default/assets/less/thelia/tables.less | 121 + .../assets/less/thelia/tablesorter.less | 58 + .../default/assets/less/thelia/thelia.less | 669 + .../default/assets/less/thelia/toolbar.less | 273 + .../default/assets/less/thelia/type.less | 114 + .../default/assets/less/thelia/variables.less | 100 + .../default/assets/less/thelia/wizard.less | 129 + .../backOffice/default/attribute-edit.html | 340 + templates/backOffice/default/attributes.html | 366 + templates/backOffice/default/brand-edit.html | 268 + templates/backOffice/default/brands.html | 324 + templates/backOffice/default/categories.html | 929 ++ .../backOffice/default/category-edit.html | 438 + templates/backOffice/default/composer.json | 10 + .../backOffice/default/config-store.html | 192 + .../backOffice/default/configs/variables.conf | 3 + .../backOffice/default/configuration.html | 423 + .../backOffice/default/content-edit.html | 339 + templates/backOffice/default/countries.html | 311 + .../backOffice/default/country-edit.html | 156 + .../backOffice/default/coupon-create.html | 58 + templates/backOffice/default/coupon-list.html | 299 + .../backOffice/default/coupon-update.html | 75 + .../condition-fragments/base-input-text.html | 12 + .../cart-contains-categories-condition.html | 15 + .../cart-contains-products-condition.html | 15 + .../cart-item-count-condition.html | 12 + .../cart-total-amount-condition.html | 21 + .../condition-selector.html | 6 + .../countries-condition.html | 15 + .../currency-selector.html | 6 + .../customers-condition.html | 15 + .../quantity-selector.html | 10 + .../start-date-condition.html | 9 + .../default/coupon/condition-input-ajax.html | 7 + .../backOffice/default/coupon/conditions.html | 24 + templates/backOffice/default/coupon/form.html | 296 + .../ajax-attribute-avs-list.html | 3 + .../type-fragments/ajax-products-list.html | 3 + .../base-remove-on-attributes.html | 67 + .../base-remove-on-categories.html | 22 + .../base-remove-on-products.html | 67 + .../coupon/type-fragments/free-product.html | 69 + .../remove-amount-on-attributes.html | 16 + .../remove-amount-on-categories.html | 16 + .../remove-amount-on-products.html | 16 + .../remove-percentage-on-attributes.html | 14 + .../remove-percentage-on-categories.html | 14 + .../remove-percentage-on-products.html | 14 + .../type-fragments/remove-x-amount.html | 11 + .../type-fragments/remove-x-percent.html | 9 + .../coupon/type-fragments/remove-x.html | 4 + .../default/create-password-success.html | 25 + .../backOffice/default/create-password.html | 60 + templates/backOffice/default/currencies.html | 443 + .../backOffice/default/currency-edit.html | 126 + .../backOffice/default/customer-edit.html | 462 + templates/backOffice/default/customers.html | 431 + .../backOffice/default/document-edit.html | 139 + templates/backOffice/default/error.html | 19 + templates/backOffice/default/export-page.html | 117 + templates/backOffice/default/export.html | 256 + .../backOffice/default/feature-edit.html | 334 + templates/backOffice/default/features.html | 367 + templates/backOffice/default/folder-edit.html | 298 + templates/backOffice/default/folders.html | 686 + .../form-field-attributes-renderer.html | 78 + .../forms/standard/form-field-renderer.html | 161 + .../backOffice/default/general_error.html | 24 + templates/backOffice/default/home.html | 58 + templates/backOffice/default/hook-edit.html | 98 + templates/backOffice/default/hooks.html | 555 + templates/backOffice/default/image-edit.html | 146 + templates/backOffice/default/import-page.html | 95 + templates/backOffice/default/import.html | 211 + .../admin-utilities-position-block.html | 7 + ...dmin-utilities-sortable-column-header.html | 10 + .../default/includes/catalog-breadcrumb.html | 28 + .../default/includes/confirmation-modal.html | 36 + .../includes/content-folder-management.html | 100 + .../customer_address_form_fields.html | 78 + .../includes/document-upload-form.html | 68 + .../includes/document-upload-list-ajax.html | 49 + .../default/includes/export-form-body.html | 196 + .../default/includes/folder-breadcrumb.html | 28 + .../includes/generic-confirm-dialog.html | 45 + .../includes/generic-create-dialog.html | 45 + .../default/includes/generic-js-dialog.html | 60 + .../includes/generic-warning-dialog.html | 34 + .../default/includes/hook-edition.js.inc | 89 + .../default/includes/image-upload-form.html | 92 + .../includes/image-upload-list-ajax.html | 82 + .../default/includes/import-form-body.html | 46 + .../default/includes/inner-form-toolbar.html | 65 + .../default/includes/main-menu.html | 288 + .../default/includes/module-block.html | 226 + .../default/includes/module-errors.html | 17 + .../default/includes/module-hook-block.html | 92 + .../default/includes/module-install.html | 83 + .../default/includes/module-tab-content.html | 19 + .../default/includes/notifications.html | 13 + .../default/includes/pagination.html | 73 + .../default/includes/product-general-tab.html | 156 + .../default/includes/product-prices-tab.html | 837 ++ .../backOffice/default/includes/seo-tab.html | 52 + .../standard-description-form-fields.html | 6 + templates/backOffice/default/languages.html | 390 + templates/backOffice/default/login.html | 87 + .../backOffice/default/lost-password.html | 62 + .../backOffice/default/mailing-system.html | 171 + .../backOffice/default/message-edit.html | 400 + templates/backOffice/default/messages.html | 220 + .../backOffice/default/module-configure.html | 36 + templates/backOffice/default/module-edit.html | 137 + .../backOffice/default/module-hook-edit.html | 117 + .../backOffice/default/module-hooks.html | 446 + templates/backOffice/default/modules.html | 238 + templates/backOffice/default/order-edit.html | 909 ++ .../backOffice/default/order-status-edit.html | 172 + .../backOffice/default/order-status.html | 261 + templates/backOffice/default/orders.html | 239 + .../backOffice/default/product-edit.html | 811 ++ .../backOffice/default/profile-edit.html | 349 + templates/backOffice/default/profiles.html | 282 + .../backOffice/default/renderer/buttons.html | 274 + templates/backOffice/default/sale-edit.html | 509 + templates/backOffice/default/sales.html | 333 + templates/backOffice/default/search.html | 947 ++ .../default/shipping-configuration-edit.html | 421 + .../default/shipping-configuration.html | 189 + .../default/shipping-zones-edit.html | 176 + .../backOffice/default/shipping-zones.html | 118 + .../backOffice/default/simple-layout.tpl | 130 + templates/backOffice/default/state-edit.html | 109 + templates/backOffice/default/states.html | 277 + templates/backOffice/default/system-logs.html | 221 + templates/backOffice/default/tax-edit.html | 169 + .../backOffice/default/tax-rule-edit.html | 915 ++ templates/backOffice/default/taxes-rules.html | 441 + .../backOffice/default/template-edit.html | 219 + templates/backOffice/default/template.xml | 43 + templates/backOffice/default/templates.html | 246 + templates/backOffice/default/tools.html | 84 + .../backOffice/default/translations.html | 546 + .../backOffice/default/variable-edit.html | 130 + templates/backOffice/default/variables.html | 343 + templates/email/default/I18n/ar_SA.php | 32 + templates/email/default/I18n/cs_CZ.php | 68 + templates/email/default/I18n/de_DE.php | 68 + templates/email/default/I18n/el_GR.php | 32 + templates/email/default/I18n/en_US.php | 84 + templates/email/default/I18n/es_ES.php | 68 + templates/email/default/I18n/fa_IR.php | 68 + templates/email/default/I18n/fr_FR.php | 84 + templates/email/default/I18n/hu_HU.php | 67 + templates/email/default/I18n/id_ID.php | 40 + templates/email/default/I18n/it_IT.php | 20 + templates/email/default/I18n/pl_PL.php | 41 + templates/email/default/I18n/pt_BR.php | 68 + templates/email/default/I18n/pt_PT.php | 5 + templates/email/default/I18n/ru_RU.php | 79 + templates/email/default/I18n/sk_SK.php | 68 + templates/email/default/I18n/tr_TR.php | 68 + templates/email/default/LICENSE.txt | 165 + templates/email/default/README | 71 + templates/email/default/Readme.md | 18 + .../default/account_changed_by_admin.html | 31 + .../default/account_changed_by_admin.txt | 18 + .../default/account_created_by_admin.html | 31 + .../default/account_created_by_admin.txt | 16 + templates/email/default/admin_password.html | 26 + templates/email/default/admin_password.txt | 10 + templates/email/default/assets/img/header.jpg | Bin 0 -> 74372 bytes templates/email/default/assets/img/logo.gif | Bin 0 -> 2159 bytes templates/email/default/composer.json | 10 + .../email/default/customer_confirmation.html | 29 + .../email/default/customer_confirmation.txt | 11 + .../email/default/default-html-layout.tpl | 26 + .../email/default/default-text-layout.tpl | 26 + templates/email/default/email-layout.tpl | 482 + .../newsletter_subscription_confirmation.html | 24 + .../newsletter_subscription_confirmation.txt | 10 + .../email/default/order_confirmation.html | 149 + .../email/default/order_confirmation.txt | 54 + .../email/default/order_notification.html | 129 + .../email/default/order_notification.txt | 52 + templates/email/default/password.html | 26 + templates/email/default/password.txt | 12 + templates/email/default/template.xml | 43 + templates/frontOffice/default/.gitignore | 2 + templates/frontOffice/default/404.html | 39 + templates/frontOffice/default/Gruntfile.js | 229 + templates/frontOffice/default/I18n/ar_SA.php | 199 + templates/frontOffice/default/I18n/cs_CZ.php | 250 + templates/frontOffice/default/I18n/de_DE.php | 256 + templates/frontOffice/default/I18n/el_GR.php | 201 + templates/frontOffice/default/I18n/en_US.php | 276 + templates/frontOffice/default/I18n/es_ES.php | 262 + templates/frontOffice/default/I18n/fa_IR.php | 259 + templates/frontOffice/default/I18n/fr_FR.php | 272 + templates/frontOffice/default/I18n/hu_HU.php | 204 + templates/frontOffice/default/I18n/id_ID.php | 50 + templates/frontOffice/default/I18n/it_IT.php | 198 + templates/frontOffice/default/I18n/nl_NL.php | 8 + templates/frontOffice/default/I18n/pl_PL.php | 116 + templates/frontOffice/default/I18n/pt_BR.php | 253 + templates/frontOffice/default/I18n/pt_PT.php | 67 + templates/frontOffice/default/I18n/ru_RU.php | 263 + templates/frontOffice/default/I18n/sk_SK.php | 254 + templates/frontOffice/default/I18n/tr_TR.php | 257 + templates/frontOffice/default/I18n/uk_UA.php | 7 + templates/frontOffice/default/LICENSE.txt | 165 + templates/frontOffice/default/Readme.md | 38 + .../frontOffice/default/account-order.html | 289 + .../frontOffice/default/account-password.html | 108 + .../frontOffice/default/account-update.html | 186 + templates/frontOffice/default/account.html | 222 + .../frontOffice/default/address-update.html | 322 + templates/frontOffice/default/address.html | 307 + .../ajax/order-delivery-module-list.html | 62 + .../default/assets/dist/css/thelia.min.css | 8 + .../glyphicons-halflings-regular.eot | Bin 0 -> 20127 bytes .../glyphicons-halflings-regular.svg | 288 + .../glyphicons-halflings-regular.ttf | Bin 0 -> 45404 bytes .../glyphicons-halflings-regular.woff | Bin 0 -> 23424 bytes .../glyphicons-halflings-regular.woff2 | Bin 0 -> 18028 bytes .../dist/fonts/fontawesome/FontAwesome.otf | Bin 0 -> 93888 bytes .../fonts/fontawesome/fontawesome-webfont.eot | Bin 0 -> 60767 bytes .../fonts/fontawesome/fontawesome-webfont.svg | 565 + .../fonts/fontawesome/fontawesome-webfont.ttf | Bin 0 -> 122092 bytes .../fontawesome/fontawesome-webfont.woff | Bin 0 -> 71508 bytes .../fontawesome/fontawesome-webfont.woff2 | Bin 0 -> 56780 bytes .../default/assets/dist/img/118x85.png | Bin 0 -> 1642 bytes .../default/assets/dist/img/1200x390.png | Bin 0 -> 11534 bytes .../default/assets/dist/img/218x146.png | Bin 0 -> 2043 bytes .../default/assets/dist/img/280x196.png | Bin 0 -> 2846 bytes .../default/assets/dist/img/560x445.png | Bin 0 -> 6299 bytes .../default/assets/dist/img/700x320.png | Bin 0 -> 12739 bytes .../default/assets/dist/img/ajax-loader.gif | Bin 0 -> 13582 bytes .../assets/dist/img/american-express.png | Bin 0 -> 3753 bytes .../assets/dist/img/carousel/slider2.jpg | Bin 0 -> 91091 bytes .../assets/dist/img/carousel/slider3.jpg | Bin 0 -> 40715 bytes .../default/assets/dist/img/cheque.png | Bin 0 -> 4090 bytes .../default/assets/dist/img/email/header.jpg | Bin 0 -> 73024 bytes .../default/assets/dist/img/email/logo.gif | Bin 0 -> 2159 bytes .../default/assets/dist/img/email/logo.png | Bin 0 -> 2593 bytes .../default/assets/dist/img/favicon.ico | Bin 0 -> 1150 bytes .../default/assets/dist/img/favicon.png | Bin 0 -> 355 bytes .../assets/dist/img/googlemap-icon.png | Bin 0 -> 565 bytes .../default/assets/dist/img/header.jpg | Bin 0 -> 74372 bytes .../default/assets/dist/img/kwixo.png | Bin 0 -> 3940 bytes .../default/assets/dist/img/logo.gif | Bin 0 -> 2159 bytes .../default/assets/dist/img/logo.png | Bin 0 -> 2593 bytes .../default/assets/dist/img/mastercard.png | Bin 0 -> 3733 bytes .../dist/img/payment/american-express.png | Bin 0 -> 3713 bytes .../assets/dist/img/payment/cheque.png | Bin 0 -> 4050 bytes .../default/assets/dist/img/payment/kwixo.png | Bin 0 -> 3901 bytes .../assets/dist/img/payment/mastercard.png | Bin 0 -> 3693 bytes .../default/assets/dist/img/payment/visa.png | Bin 0 -> 3118 bytes .../assets/dist/img/product/1/118x85.png | Bin 0 -> 1535 bytes .../default/assets/dist/img/slider1.jpg | Bin 0 -> 99226 bytes .../default/assets/dist/img/slider2.jpg | Bin 0 -> 93797 bytes .../default/assets/dist/img/slider3.jpg | Bin 0 -> 41738 bytes .../default/assets/dist/img/visa.png | Bin 0 -> 3158 bytes .../default/assets/dist/js/thelia.min.js | 1 + .../default/assets/dist/js/vendors/bootbox.js | 985 ++ .../assets/dist/js/vendors/bootstrap.min.js | 7 + .../assets/dist/js/vendors/html5shiv.min.js | 4 + .../assets/dist/js/vendors/jquery.min.js | 5 + .../assets/dist/js/vendors/respond.min.js | 5 + .../default/assets/src/css/thelia.css | 11075 ++++++++++++++ .../glyphicons-halflings-regular.eot | Bin 0 -> 20127 bytes .../glyphicons-halflings-regular.svg | 288 + .../glyphicons-halflings-regular.ttf | Bin 0 -> 45404 bytes .../glyphicons-halflings-regular.woff | Bin 0 -> 23424 bytes .../glyphicons-halflings-regular.woff2 | Bin 0 -> 18028 bytes .../src/fonts/fontawesome/FontAwesome.otf | Bin 0 -> 93888 bytes .../fonts/fontawesome/fontawesome-webfont.eot | Bin 0 -> 60767 bytes .../fonts/fontawesome/fontawesome-webfont.svg | 565 + .../fonts/fontawesome/fontawesome-webfont.ttf | Bin 0 -> 122092 bytes .../fontawesome/fontawesome-webfont.woff | Bin 0 -> 71508 bytes .../fontawesome/fontawesome-webfont.woff2 | Bin 0 -> 56780 bytes .../default/assets/src/img/218x146.png | Bin 0 -> 2132 bytes .../default/assets/src/img/280x196.png | Bin 0 -> 2950 bytes .../default/assets/src/img/ajax-loader.gif | Bin 0 -> 13582 bytes .../default/assets/src/img/email/header.jpg | Bin 0 -> 74372 bytes .../default/assets/src/img/email/logo.gif | Bin 0 -> 2159 bytes .../default/assets/src/img/email/logo.png | Bin 0 -> 2593 bytes .../default/assets/src/img/favicon.ico | Bin 0 -> 1150 bytes .../default/assets/src/img/favicon.png | Bin 0 -> 1415 bytes .../default/assets/src/img/logo.gif | Bin 0 -> 2159 bytes .../default/assets/src/img/logo.png | Bin 0 -> 2593 bytes .../assets/src/img/product/1/118x85.png | Bin 0 -> 1642 bytes .../default/assets/src/js/thelia.js | 715 + .../default/assets/src/js/vendors/bootbox.js | 985 ++ .../assets/src/js/vendors/bootstrap.js | 2363 +++ .../assets/src/js/vendors/html5shiv.js | 326 + .../default/assets/src/js/vendors/jquery.js | 9210 ++++++++++++ .../default/assets/src/js/vendors/respond.js | 341 + .../default/assets/src/less/thelia.less | 11 + .../assets/src/less/thelia/account.less | 40 + .../default/assets/src/less/thelia/brand.less | 32 + .../assets/src/less/thelia/breadcrumbs.less | 4 + .../default/assets/src/less/thelia/cart.less | 50 + .../assets/src/less/thelia/category.less | 82 + .../assets/src/less/thelia/checkout.less | 24 + .../assets/src/less/thelia/filters.less | 15 + .../assets/src/less/thelia/folder.less | 37 + .../assets/src/less/thelia/footer.less | 35 + .../default/assets/src/less/thelia/forms.less | 11 + .../assets/src/less/thelia/header.less | 42 + .../assets/src/less/thelia/import.less | 29 + .../assets/src/less/thelia/navbar.less | 68 + .../assets/src/less/thelia/pagination.less | 11 + .../assets/src/less/thelia/product.less | 71 + .../assets/src/less/thelia/toolbars.less | 34 + .../assets/src/less/thelia/variables.less | 90 + .../default/assets/src/less/theme/alerts.less | 16 + .../default/assets/src/less/theme/blocks.less | 233 + .../default/assets/src/less/theme/brand.less | 25 + .../assets/src/less/theme/breadcrumbs.less | 10 + .../assets/src/less/theme/buttons.less | 53 + .../default/assets/src/less/theme/cart.less | 17 + .../assets/src/less/theme/category.less | 46 + .../assets/src/less/theme/checkout.less | 94 + .../assets/src/less/theme/filters.less | 22 + .../default/assets/src/less/theme/folder.less | 24 + .../default/assets/src/less/theme/footer.less | 69 + .../default/assets/src/less/theme/forms.less | 48 + .../default/assets/src/less/theme/global.less | 105 + .../default/assets/src/less/theme/header.less | 27 + .../default/assets/src/less/theme/import.less | 43 + .../default/assets/src/less/theme/labels.less | 16 + .../default/assets/src/less/theme/navbar.less | 60 + .../assets/src/less/theme/page-error.less | 19 + .../assets/src/less/theme/page-home.less | 22 + .../default/assets/src/less/theme/panels.less | 40 + .../default/assets/src/less/theme/price.less | 20 + .../assets/src/less/theme/product.less | 110 + .../assets/src/less/theme/scaffolding.less | 3 + .../default/assets/src/less/theme/tables.less | 126 + .../default/assets/src/less/theme/theme.less | 1245 ++ .../assets/src/less/theme/toolbars.less | 40 + .../assets/src/less/theme/variables.less | 128 + .../src/less/vendors/bootstrap/alerts.less | 73 + .../src/less/vendors/bootstrap/badges.less | 66 + .../src/less/vendors/bootstrap/bootstrap.less | 56 + .../less/vendors/bootstrap/breadcrumbs.less | 26 + .../less/vendors/bootstrap/button-groups.less | 244 + .../src/less/vendors/bootstrap/buttons.less | 166 + .../src/less/vendors/bootstrap/carousel.less | 270 + .../src/less/vendors/bootstrap/close.less | 34 + .../src/less/vendors/bootstrap/code.less | 69 + .../bootstrap/component-animations.less | 33 + .../src/less/vendors/bootstrap/dropdowns.less | 216 + .../src/less/vendors/bootstrap/forms.less | 613 + .../less/vendors/bootstrap/glyphicons.less | 305 + .../src/less/vendors/bootstrap/grid.less | 84 + .../less/vendors/bootstrap/input-groups.less | 171 + .../src/less/vendors/bootstrap/jumbotron.less | 54 + .../src/less/vendors/bootstrap/labels.less | 64 + .../less/vendors/bootstrap/list-group.less | 130 + .../src/less/vendors/bootstrap/media.less | 66 + .../src/less/vendors/bootstrap/mixins.less | 40 + .../less/vendors/bootstrap/mixins/alerts.less | 14 + .../bootstrap/mixins/background-variant.less | 9 + .../bootstrap/mixins/border-radius.less | 18 + .../vendors/bootstrap/mixins/buttons.less | 65 + .../bootstrap/mixins/center-block.less | 7 + .../vendors/bootstrap/mixins/clearfix.less | 22 + .../less/vendors/bootstrap/mixins/forms.less | 85 + .../vendors/bootstrap/mixins/gradients.less | 59 + .../bootstrap/mixins/grid-framework.less | 91 + .../less/vendors/bootstrap/mixins/grid.less | 122 + .../vendors/bootstrap/mixins/hide-text.less | 21 + .../less/vendors/bootstrap/mixins/image.less | 33 + .../less/vendors/bootstrap/mixins/labels.less | 12 + .../vendors/bootstrap/mixins/list-group.less | 30 + .../vendors/bootstrap/mixins/nav-divider.less | 10 + .../bootstrap/mixins/nav-vertical-align.less | 9 + .../vendors/bootstrap/mixins/opacity.less | 8 + .../vendors/bootstrap/mixins/pagination.less | 24 + .../less/vendors/bootstrap/mixins/panels.less | 24 + .../bootstrap/mixins/progress-bar.less | 10 + .../bootstrap/mixins/reset-filter.less | 8 + .../vendors/bootstrap/mixins/reset-text.less | 18 + .../less/vendors/bootstrap/mixins/resize.less | 6 + .../mixins/responsive-visibility.less | 15 + .../less/vendors/bootstrap/mixins/size.less | 10 + .../vendors/bootstrap/mixins/tab-focus.less | 9 + .../vendors/bootstrap/mixins/table-row.less | 28 + .../bootstrap/mixins/text-emphasis.less | 9 + .../bootstrap/mixins/text-overflow.less | 8 + .../bootstrap/mixins/vendor-prefixes.less | 227 + .../src/less/vendors/bootstrap/modals.less | 150 + .../src/less/vendors/bootstrap/navbar.less | 660 + .../src/less/vendors/bootstrap/navs.less | 242 + .../src/less/vendors/bootstrap/normalize.less | 424 + .../src/less/vendors/bootstrap/pager.less | 54 + .../less/vendors/bootstrap/pagination.less | 89 + .../src/less/vendors/bootstrap/panels.less | 271 + .../src/less/vendors/bootstrap/popovers.less | 131 + .../src/less/vendors/bootstrap/print.less | 101 + .../less/vendors/bootstrap/progress-bars.less | 87 + .../vendors/bootstrap/responsive-embed.less | 35 + .../bootstrap/responsive-utilities.less | 194 + .../less/vendors/bootstrap/scaffolding.less | 161 + .../src/less/vendors/bootstrap/tables.less | 234 + .../src/less/vendors/bootstrap/theme.less | 291 + .../less/vendors/bootstrap/thumbnails.less | 36 + .../src/less/vendors/bootstrap/tooltip.less | 101 + .../src/less/vendors/bootstrap/type.less | 302 + .../src/less/vendors/bootstrap/utilities.less | 55 + .../src/less/vendors/bootstrap/variables.less | 869 ++ .../src/less/vendors/bootstrap/wells.less | 29 + .../less/vendors/fontawesome/animated.less | 34 + .../vendors/fontawesome/bordered-pulled.less | 16 + .../src/less/vendors/fontawesome/core.less | 13 + .../less/vendors/fontawesome/fixed-width.less | 6 + .../vendors/fontawesome/font-awesome.less | 17 + .../src/less/vendors/fontawesome/icons.less | 596 + .../src/less/vendors/fontawesome/larger.less | 13 + .../src/less/vendors/fontawesome/list.less | 19 + .../src/less/vendors/fontawesome/mixins.less | 27 + .../src/less/vendors/fontawesome/path.less | 15 + .../vendors/fontawesome/rotated-flipped.less | 20 + .../src/less/vendors/fontawesome/stacked.less | 20 + .../less/vendors/fontawesome/variables.less | 606 + .../frontOffice/default/badresponse.html | 51 + templates/frontOffice/default/bower.json | 22 + templates/frontOffice/default/brand.html | 178 + templates/frontOffice/default/cart.html | 297 + templates/frontOffice/default/category.html | 149 + templates/frontOffice/default/composer.json | 10 + .../default/configs/variables.conf | 21 + .../frontOffice/default/contact-success.html | 13 + templates/frontOffice/default/contact.html | 118 + templates/frontOffice/default/content.html | 110 + templates/frontOffice/default/currency.html | 39 + templates/frontOffice/default/error.html | 36 + templates/frontOffice/default/feed.html | 108 + templates/frontOffice/default/folder.html | 159 + .../default/includes/addedToCart.html | 63 + .../default/includes/asides/articles.html | 19 + .../default/includes/brand-menu.html | 20 + .../frontOffice/default/includes/empty.html | 10 + .../frontOffice/default/includes/menu.html | 76 + .../default/includes/meta-seo.html | 6 + .../default/includes/mini-cart.html | 1 + .../default/includes/product-empty.html | 34 + .../default/includes/single-product.html | 122 + .../frontOffice/default/includes/toolbar.html | 74 + templates/frontOffice/default/index.html | 29 + templates/frontOffice/default/language.html | 39 + templates/frontOffice/default/layout.tpl | 306 + templates/frontOffice/default/login.html | 115 + .../frontOffice/default/misc/breadcrumb.tpl | 22 + .../default/misc/checkout-progress.tpl | 28 + .../frontOffice/default/modal-address.html | 0 .../default/newsletter-unsubscribe.html | 57 + templates/frontOffice/default/newsletter.html | 79 + .../frontOffice/default/order-delivery.html | 186 + .../frontOffice/default/order-failed.html | 71 + .../frontOffice/default/order-invoice.html | 463 + .../default/order-payment-gateway.html | 92 + .../frontOffice/default/order-placed.html | 76 + templates/frontOffice/default/package.json | 27 + templates/frontOffice/default/password.html | 80 + templates/frontOffice/default/product.html | 479 + templates/frontOffice/default/register.html | 354 + templates/frontOffice/default/sale.html | 110 + templates/frontOffice/default/search.html | 58 + templates/frontOffice/default/sitemap.html | 73 + templates/frontOffice/default/template.xml | 43 + templates/frontOffice/default/view_all.html | 66 + templates/pdf/default/I18n/ar_SA.php | 18 + templates/pdf/default/I18n/cs_CZ.php | 21 + templates/pdf/default/I18n/de_DE.php | 31 + templates/pdf/default/I18n/el_GR.php | 15 + templates/pdf/default/I18n/en_US.php | 33 + templates/pdf/default/I18n/es_ES.php | 31 + templates/pdf/default/I18n/fa_IR.php | 31 + templates/pdf/default/I18n/fr_FR.php | 33 + templates/pdf/default/I18n/hu_HU.php | 18 + templates/pdf/default/I18n/id_ID.php | 17 + templates/pdf/default/I18n/it_IT.php | 17 + templates/pdf/default/I18n/nl_NL.php | 6 + templates/pdf/default/I18n/pl_PL.php | 18 + templates/pdf/default/I18n/pt_BR.php | 21 + templates/pdf/default/I18n/pt_PT.php | 15 + templates/pdf/default/I18n/ru_RU.php | 29 + templates/pdf/default/I18n/sk_SK.php | 24 + templates/pdf/default/I18n/tr_TR.php | 31 + templates/pdf/default/LICENSE.txt | 165 + templates/pdf/default/Readme.md | 18 + templates/pdf/default/composer.json | 10 + templates/pdf/default/delivery.html | 281 + templates/pdf/default/invoice.html | 369 + templates/pdf/default/template.xml | 43 + tests/functionnal/casperjs/conf/local.js | 59 + .../functionnal/casperjs/exe/back/10_pages.js | 164 + .../functionnal/casperjs/exe/front/10_home.js | 17 + .../casperjs/exe/front/20_register.js | 139 + .../casperjs/exe/front/30_login.js | 102 + .../functionnal/casperjs/exe/front/40_cart.js | 76 + .../casperjs/exe/front/50-order-process.js | 54 + .../casperjs/exe/front/60-newsletter.js | 249 + .../casperjs/exe/hook/10_position.js | 141 + .../casperjs/exe/hook/20_activation.js | 221 + .../Thelia/Tests/Action/AddressTest.php | 184 + .../Thelia/Tests/Action/AdministratorTest.php | 178 + .../phpunit/Thelia/Tests/Action/AreaTest.php | 142 + .../Thelia/Tests/Action/AttributeAvTest.php | 105 + .../Thelia/Tests/Action/AttributeTest.php | 95 + .../Thelia/Tests/Action/BaseAction.php | 50 + .../phpunit/Thelia/Tests/Action/BrandTest.php | 251 + .../phpunit/Thelia/Tests/Action/CacheTest.php | 68 + .../Thelia/Tests/Action/CategoryTest.php | 189 + .../Thelia/Tests/Action/ConfigTest.php | 152 + .../Thelia/Tests/Action/ContentTest.php | 373 + .../Thelia/Tests/Action/CountryTest.php | 138 + .../Thelia/Tests/Action/CurrencyTest.php | 195 + .../Thelia/Tests/Action/CustomerTest.php | 187 + .../Thelia/Tests/Action/DocumentTest.php | 280 + .../Thelia/Tests/Action/FeatureAvTest.php | 119 + .../Thelia/Tests/Action/FeatureTest.php | 99 + .../Thelia/Tests/Action/FolderTest.php | 319 + .../phpunit/Thelia/Tests/Action/HookTest.php | 224 + .../Thelia/Tests/Action/I18nTestTrait.php | 53 + .../phpunit/Thelia/Tests/Action/ImageTest.php | 396 + .../phpunit/Thelia/Tests/Action/LangTest.php | 231 + .../Thelia/Tests/Action/MessageTest.php | 121 + .../Thelia/Tests/Action/MetaDataTest.php | 189 + .../Thelia/Tests/Action/ModuleHookTest.php | 137 + .../Thelia/Tests/Action/NewsletterTest.php | 118 + .../Thelia/Tests/Action/OrderStatusTest.php | 226 + .../phpunit/Thelia/Tests/Action/OrderTest.php | 772 + tests/phpunit/Thelia/Tests/Action/PdfTest.php | 36 + .../Thelia/Tests/Action/ProductTest.php | 1142 ++ .../Thelia/Tests/Action/ProfileTest.php | 134 + .../Tests/Action/RewrittenUrlTestTrait.php | 113 + .../phpunit/Thelia/Tests/Action/SaleTest.php | 230 + .../phpunit/Thelia/Tests/Action/StateTest.php | 110 + .../documents/sources/test-document-1.txt | 1 + .../documents/sources/test-document-2.txt | 1 + .../assets/images/sources/test-image-1.png | Bin 0 -> 13736 bytes .../assets/images/sources/test-image-2.png | Bin 0 -> 6010 bytes .../assets/images/sources/test-image-3.png | Bin 0 -> 6568 bytes .../assets/images/sources/test-image-4.png | Bin 0 -> 9154 bytes .../assets/images/sources/test-image-5.png | Bin 0 -> 17175 bytes .../assets/images/sources/test-image-6.png | Bin 0 -> 14973 bytes .../assets/images/sources/test-image-7.png | Bin 0 -> 5651 bytes .../assets/images/sources/test-image-8.png | Bin 0 -> 5811 bytes .../assets/images/sources/test-image-9.png | Bin 0 -> 11126 bytes .../Thelia/Tests/Api/ApiSendJsonTest.php | 42 + .../Tests/Api/AttributeAvControllerTest.php | 104 + .../Thelia/Tests/Api/BrandControllerTest.php | 159 + .../Tests/Api/CategoryControllerTest.php | 243 + .../Tests/Api/CountryControllerTest.php | 103 + .../Tests/Api/CurrencyControllerTest.php | 103 + .../Tests/Api/CustomerControllerTest.php | 390 + .../Thelia/Tests/Api/IndexControllerTest.php | 36 + .../Thelia/Tests/Api/LangControllerTest.php | 103 + .../Tests/Api/ProductControllerTest.php | 276 + .../Tests/Api/ProductImageControllerTest.php | 318 + .../Api/ProductSaleElementsControllerTest.php | 472 + .../Thelia/Tests/Api/TaxControllerTest.php | 103 + .../Tests/Api/TaxRuleControllerTest.php | 307 + .../Thelia/Tests/Api/TitleControllerTest.php | 374 + .../Thelia/Tests/Api/fixtures/base.png | Bin 0 -> 77464 bytes .../Thelia/Tests/Api/fixtures/fail.pdf | Bin 0 -> 160051 bytes tests/phpunit/Thelia/Tests/ApiTestCase.php | 43 + .../Thelia/Tests/Command/BaseCommandTest.php | 35 + .../Thelia/Tests/Command/CacheClearTest.php | 123 + .../Tests/Command/ConfigCommandTest.php | 281 + .../Command/ModuleActivateCommandTest.php | 106 + .../Command/ModuleDeactivateCommandTest.php | 106 + .../Command/ModuleGenerateCommandTest.php | 131 + .../Command/ModuleRefreshCommandTest.php | 107 + .../SaleCheckActivationCommandTest.php | 115 + .../Condition/ConditionCollectionTest.php | 170 + .../Condition/ConditionEvaluatorTest.php | 193 + .../Tests/Condition/ConditionFactoryTest.php | 439 + .../CartContainsCategoriesTest.php | 360 + .../CartContainsProductsTest.php | 360 + .../Implementation/ForSomeCustomersTest.php | 299 + .../MatchBillingCountriesTest.php | 307 + .../MatchDeliveryCountriesTest.php | 304 + .../Implementation/MatchForEveryoneTest.php | 184 + .../MatchForTotalAmountTest.php | 946 ++ .../Implementation/MatchForXArticlesTest.php | 716 + .../Implementation/StartDateTest.php | 325 + .../Thelia/Tests/Condition/OperatorsTest.php | 96 + .../Thelia/Tests/Config/RoutesConfigTest.php | 280 + .../Thelia/Tests/ContainerAwareTestCase.php | 128 + .../Tests/Controller/ControllerTestBase.php | 40 + .../Controller/DefaultControllerTest.php | 100 + .../Controller/ProductControllerTest.php | 146 + .../Core/Archiver/ArchiverManagerTest.php | 294 + .../Tests/Core/Event/ActionEventTest.php | 64 + .../Thelia/Tests/Core/Event/FooEvent.php | 64 + .../EventListener/RequestListenerTest.php | 75 + .../Tests/Core/Form/TheliaFormFactoryTest.php | 114 + .../Thelia/Tests/Core/Hook/HookTest.php | 291 + .../Tests/Core/HttpFoundation/RequestTest.php | 53 + .../HttpFoundation/Session/SessionTest.php | 257 + .../Expectation/SchemaCombineExpectation.php | 149 + .../Schema/Fixtures/schema/1.bar.schema.xml | 19 + .../Schema/Fixtures/schema/2.bar.schema.xml | 10 + .../Schema/Fixtures/schema/foo.schema.xml | 6 + .../Core/Propel/Schema/SchemaCombinerTest.php | 450 + .../Core/Routing/RewritingRouterTest.php | 209 + .../Serializer/JSONSerializerTest.php | 98 + .../Core/Serializer/SerializerManagerTest.php | 271 + .../Core/Template/Element/BaseLoopTestor.php | 176 + .../Core/Template/Loop/AccessoryTest.php | 39 + .../Tests/Core/Template/Loop/AddressTest.php | 39 + .../Loop/Argument/ArgumentCollectionTest.php | 100 + .../Template/Loop/AssociatedContentTest.php | 39 + .../Loop/AttributeAvailabilityTest.php | 39 + .../Loop/AttributeCombinationTest.php | 39 + .../Core/Template/Loop/AttributeTest.php | 39 + .../Tests/Core/Template/Loop/BrandTest.php | 62 + .../Tests/Core/Template/Loop/CategoryTest.php | 63 + .../Tests/Core/Template/Loop/ContentTest.php | 62 + .../Tests/Core/Template/Loop/CountryTest.php | 39 + .../Tests/Core/Template/Loop/CurrencyTest.php | 39 + .../Tests/Core/Template/Loop/CustomerTest.php | 39 + .../Tests/Core/Template/Loop/DocumentTest.php | 71 + .../Template/Loop/FeatureAvailabilityTest.php | 39 + .../Tests/Core/Template/Loop/FeatureTest.php | 39 + .../Core/Template/Loop/FeatureValueTest.php | 39 + .../Tests/Core/Template/Loop/FolderTest.php | 63 + .../Tests/Core/Template/Loop/HookTest.php | 47 + .../Tests/Core/Template/Loop/ImageTest.php | 71 + .../Core/Template/Loop/ModuleConfigTest.php | 132 + .../Core/Template/Loop/ModuleHookTest.php | 48 + .../Template/Loop/ProductSaleElementTest.php | 39 + .../Tests/Core/Template/Loop/ProductTest.php | 91 + .../Tests/Core/Template/Loop/SaleTest.php | 52 + .../Tests/Core/Template/Loop/TaxRuleTest.php | 52 + .../Tests/Core/Template/Loop/TitleTest.php | 39 + .../Thelia/Tests/Coupon/CouponFactoryTest.php | 562 + .../Thelia/Tests/Coupon/CouponManagerTest.php | 766 + .../Tests/Coupon/Type/FreeProductTest.php | 466 + .../RemoveAmountOnAttributeValuesTest.php | 422 + .../Type/RemoveAmountOnCategoriesTest.php | 347 + .../Type/RemoveAmountOnProductsTest.php | 367 + .../RemovePercentageOnAttributeValuesTest.php | 458 + .../Type/RemovePercentageOnCategoriesTest.php | 388 + .../Type/RemovePercentageOnProductsTest.php | 410 + .../Tests/Coupon/Type/RemoveXAmountTest.php | 210 + .../Tests/Coupon/Type/RemoveXPercentTest.php | 205 + .../Thelia/Tests/Files/FileManagerTest.php | 439 + .../Thelia/Tests/Files/fixtures/test.gif | Bin 0 -> 35 bytes .../Thelia/Tests/Files/fixtures/test.txt | Bin 0 -> 35 bytes .../phpunit/Thelia/Tests/Form/CartAddTest.php | 19 + .../Thelia/Tests/Form/FirewallTest.php | 172 + .../Thelia/Tests/Form/OrderDeliveryTest.php | 20 + tests/phpunit/Thelia/Tests/Log/TlogTest.php | 183 + .../Thelia/Tests/Model/CurrencyTest.php | 32 + .../Thelia/Tests/Model/FeatureProductTest.php | 85 + .../Thelia/Tests/Model/MessageTest.php | 338 + .../Thelia/Tests/Model/ModuleConfigTest.php | 129 + .../Thelia/Tests/Module/BaseModuleTestor.php | 40 + .../Authors/Module1/Config/config.xml | 0 .../Authors/Module1/Config/module.xml | 45 + .../Authors/Module2/Config/config.xml | 0 .../Authors/Module2/Config/module.xml | 41 + .../Authors/Module3/Config/config.xml | 0 .../Authors/Module3/Config/module.xml | 39 + .../Validator/Module1/Config/config.xml | 0 .../Validator/Module1/Config/module.xml | 20 + .../Validator/Module2/Config/config.xml | 0 .../Validator/Module2/Config/module.xml | 25 + .../Validator/Module3/Config/config.xml | 0 .../Validator/Module4/Config/module.xml | 20 + .../Validator/Module5/Config/config.xml | 0 .../Validator/Module5/Config/module.xml | 6 + .../Module/Validator/ModuleValidatorTest.php | 204 + .../Thelia/Tests/Resources/Form/TestForm.php | 58 + .../Tests/Resources/Form/Type/TestType.php | 37 + .../Tests/Rewriting/BaseRewritingObject.php | 95 + .../Tests/Rewriting/CategoryRewritingTest.php | 31 + .../Tests/Rewriting/ContentRewritingTest.php | 31 + .../Tests/Rewriting/FolderRewritingTest.php | 31 + .../Tests/Rewriting/ProductRewriteTest.php | 34 + .../Tests/Rewriting/RewritingResolverTest.php | 144 + .../Rewriting/RewritingRetrieverTest.php | 118 + .../Thelia/Tests/TaxEngine/CalculatorTest.php | 324 + .../Thelia/Tests/TestCaseWithURLToolSetup.php | 82 + .../Thelia/Tests/Tools/FakeFileDownloader.php | 42 + .../Thelia/Tests/Tools/FileDownloaderTest.php | 69 + .../Thelia/Tests/Tools/PasswordTest.php | 39 + tests/phpunit/Thelia/Tests/Tools/URLTest.php | 293 + .../Thelia/Tests/Tools/Version/Version.php | 163 + .../Thelia/Tests/Tools/fixtures/test.xml | 0 .../Tests/Type/AlphaNumStringListTypeTest.php | 42 + .../Tests/Type/AlphaNumStringTypeTest.php | 32 + .../Thelia/Tests/Type/AnyListTypeTest.php | 60 + .../phpunit/Thelia/Tests/Type/AnyTypeTest.php | 29 + .../Thelia/Tests/Type/BooleanTypeTest.php | 46 + .../Thelia/Tests/Type/EnumListTypeTest.php | 39 + .../Thelia/Tests/Type/EnumTypeTest.php | 32 + .../Thelia/Tests/Type/FloatTypeTest.php | 31 + .../Thelia/Tests/Type/IntListTypeTest.php | 38 + .../Type/IntToCombinedIntsListTypeTest.php | 53 + .../Type/IntToCombinedStringsListTypeTest.php | 92 + .../phpunit/Thelia/Tests/Type/IntTypeTest.php | 31 + .../Thelia/Tests/Type/JsonTypeTest.php | 36 + .../Thelia/Tests/Type/TypeCollectionTest.php | 64 + tests/phpunit/Thelia/Tests/WebTestCase.php | 72 + tests/phpunit/Thelia/Tests/bootstrap.php | 21 + tests/travis/install-casperjs.sh | 11 + unit-tests.bat | 22 + unit-tests.sh | 23 + web/favicon.ico | Bin 0 -> 1150 bytes web/index.php | 40 + web/index_dev.php | 45 + web/robots.txt | 11 + 3786 files changed, 440841 insertions(+) create mode 100644 .env.dist create mode 100644 .gitattributes create mode 100644 .gitignore create mode 100644 .htaccess create mode 100644 CHANGELOG.md create mode 100644 CONTRIBUTORS.md create mode 100644 COPYRIGHT.txt create mode 100644 LICENSE.txt create mode 100644 Readme.md create mode 100644 Thelia create mode 100644 UPDATE.md create mode 100644 UPGRADE-2.3.md create mode 100644 composer.json create mode 100644 composer.lock create mode 100644 core/LICENSE.txt create mode 100644 core/Readme.md create mode 100644 core/Thelia create mode 100644 core/bootstrap.php create mode 100644 core/composer.json create mode 100644 core/composer.lock create mode 100644 core/lib/Thelia/Action/Address.php create mode 100644 core/lib/Thelia/Action/Administrator.php create mode 100644 core/lib/Thelia/Action/Api.php create mode 100644 core/lib/Thelia/Action/Area.php create mode 100644 core/lib/Thelia/Action/Attribute.php create mode 100644 core/lib/Thelia/Action/AttributeAv.php create mode 100644 core/lib/Thelia/Action/BaseAction.php create mode 100644 core/lib/Thelia/Action/BaseCachedFile.php create mode 100644 core/lib/Thelia/Action/Brand.php create mode 100644 core/lib/Thelia/Action/Cache.php create mode 100644 core/lib/Thelia/Action/Cart.php create mode 100644 core/lib/Thelia/Action/Category.php create mode 100644 core/lib/Thelia/Action/Config.php create mode 100644 core/lib/Thelia/Action/Content.php create mode 100644 core/lib/Thelia/Action/Country.php create mode 100644 core/lib/Thelia/Action/Coupon.php create mode 100644 core/lib/Thelia/Action/Currency.php create mode 100644 core/lib/Thelia/Action/Customer.php create mode 100644 core/lib/Thelia/Action/CustomerTitle.php create mode 100644 core/lib/Thelia/Action/Delivery.php create mode 100644 core/lib/Thelia/Action/Document.php create mode 100644 core/lib/Thelia/Action/Export.php create mode 100644 core/lib/Thelia/Action/Feature.php create mode 100644 core/lib/Thelia/Action/FeatureAv.php create mode 100644 core/lib/Thelia/Action/File.php create mode 100644 core/lib/Thelia/Action/Folder.php create mode 100644 core/lib/Thelia/Action/Hook.php create mode 100644 core/lib/Thelia/Action/HttpException.php create mode 100644 core/lib/Thelia/Action/Image.php create mode 100644 core/lib/Thelia/Action/Import.php create mode 100644 core/lib/Thelia/Action/Lang.php create mode 100644 core/lib/Thelia/Action/MailingSystem.php create mode 100644 core/lib/Thelia/Action/Message.php create mode 100644 core/lib/Thelia/Action/MetaData.php create mode 100644 core/lib/Thelia/Action/Module.php create mode 100644 core/lib/Thelia/Action/ModuleHook.php create mode 100644 core/lib/Thelia/Action/Newsletter.php create mode 100644 core/lib/Thelia/Action/Order.php create mode 100644 core/lib/Thelia/Action/OrderStatus.php create mode 100644 core/lib/Thelia/Action/Payment.php create mode 100644 core/lib/Thelia/Action/Pdf.php create mode 100644 core/lib/Thelia/Action/Product.php create mode 100644 core/lib/Thelia/Action/ProductSaleElement.php create mode 100644 core/lib/Thelia/Action/Profile.php create mode 100644 core/lib/Thelia/Action/RedirectException.php create mode 100644 core/lib/Thelia/Action/Sale.php create mode 100644 core/lib/Thelia/Action/ShippingZone.php create mode 100644 core/lib/Thelia/Action/State.php create mode 100644 core/lib/Thelia/Action/Tax.php create mode 100644 core/lib/Thelia/Action/TaxRule.php create mode 100644 core/lib/Thelia/Action/Template.php create mode 100644 core/lib/Thelia/Action/Translation.php create mode 100644 core/lib/Thelia/Cart/CartTrait.php create mode 100644 core/lib/Thelia/Command/AdminUpdatePasswordCommand.php create mode 100644 core/lib/Thelia/Command/BaseModuleGenerate.php create mode 100644 core/lib/Thelia/Command/CacheClear.php create mode 100644 core/lib/Thelia/Command/ClearImageCache.php create mode 100644 core/lib/Thelia/Command/ConfigCommand.php create mode 100644 core/lib/Thelia/Command/ContainerAwareCommand.php create mode 100644 core/lib/Thelia/Command/CreateAdminUser.php create mode 100644 core/lib/Thelia/Command/DiffDatabaseCommand.php create mode 100644 core/lib/Thelia/Command/ExportCommand.php create mode 100644 core/lib/Thelia/Command/GenerateResources.php create mode 100644 core/lib/Thelia/Command/GenerateSQLCommand.php create mode 100644 core/lib/Thelia/Command/HookCleanCommand.php create mode 100644 core/lib/Thelia/Command/ImportCommand.php create mode 100644 core/lib/Thelia/Command/Install.php create mode 100644 core/lib/Thelia/Command/ModuleActivateCommand.php create mode 100644 core/lib/Thelia/Command/ModuleDeactivateCommand.php create mode 100644 core/lib/Thelia/Command/ModuleGenerateCommand.php create mode 100644 core/lib/Thelia/Command/ModuleGenerateModelCommand.php create mode 100644 core/lib/Thelia/Command/ModuleGenerateSqlCommand.php create mode 100644 core/lib/Thelia/Command/ModuleListCommand.php create mode 100644 core/lib/Thelia/Command/ModulePositionCommand.php create mode 100644 core/lib/Thelia/Command/ModuleRefreshCommand.php create mode 100644 core/lib/Thelia/Command/Output/TheliaConsoleOutput.php create mode 100644 core/lib/Thelia/Command/ReloadDatabaseCommand.php create mode 100644 core/lib/Thelia/Command/SaleCheckActivationCommand.php create mode 100644 core/lib/Thelia/Command/Skeleton/Module/Class.php.template create mode 100644 core/lib/Thelia/Command/Skeleton/Module/I18n/en_US.php create mode 100644 core/lib/Thelia/Command/Skeleton/Module/I18n/fr_FR.php create mode 100644 core/lib/Thelia/Command/Skeleton/Module/Readme.md create mode 100644 core/lib/Thelia/Command/Skeleton/Module/composer.json create mode 100644 core/lib/Thelia/Command/Skeleton/Module/config.xml create mode 100644 core/lib/Thelia/Command/Skeleton/Module/config_dev.xml create mode 100644 core/lib/Thelia/Command/Skeleton/Module/config_prod.xml create mode 100644 core/lib/Thelia/Command/Skeleton/Module/config_test.xml create mode 100644 core/lib/Thelia/Command/Skeleton/Module/module.xml create mode 100644 core/lib/Thelia/Command/Skeleton/Module/routing.xml create mode 100644 core/lib/Thelia/Command/Skeleton/Module/schema.xml create mode 100644 core/lib/Thelia/Command/UpdateCurrenciesRates.php create mode 100644 core/lib/Thelia/Condition/ConditionCollection.php create mode 100644 core/lib/Thelia/Condition/ConditionEvaluator.php create mode 100644 core/lib/Thelia/Condition/ConditionFactory.php create mode 100644 core/lib/Thelia/Condition/ConditionOrganizer.php create mode 100644 core/lib/Thelia/Condition/ConditionOrganizerInterface.php create mode 100644 core/lib/Thelia/Condition/Implementation/AbstractMatchCountries.php create mode 100644 core/lib/Thelia/Condition/Implementation/CartContainsCategories.php create mode 100644 core/lib/Thelia/Condition/Implementation/CartContainsProducts.php create mode 100644 core/lib/Thelia/Condition/Implementation/ConditionAbstract.php create mode 100644 core/lib/Thelia/Condition/Implementation/ConditionInterface.php create mode 100644 core/lib/Thelia/Condition/Implementation/ForSomeCustomers.php create mode 100644 core/lib/Thelia/Condition/Implementation/MatchBillingCountries.php create mode 100644 core/lib/Thelia/Condition/Implementation/MatchDeliveryCountries.php create mode 100644 core/lib/Thelia/Condition/Implementation/MatchForEveryone.php create mode 100644 core/lib/Thelia/Condition/Implementation/MatchForTotalAmount.php create mode 100644 core/lib/Thelia/Condition/Implementation/MatchForXArticles.php create mode 100644 core/lib/Thelia/Condition/Implementation/MatchForXArticlesIncludeQuantity.php create mode 100644 core/lib/Thelia/Condition/Implementation/StartDate.php create mode 100644 core/lib/Thelia/Condition/Operators.php create mode 100644 core/lib/Thelia/Condition/SerializableCondition.php create mode 100644 core/lib/Thelia/Config/DatabaseConfiguration.php create mode 100644 core/lib/Thelia/Config/DatabaseConfigurationSource.php create mode 100644 core/lib/Thelia/Config/I18n/ar_SA.php create mode 100644 core/lib/Thelia/Config/I18n/cs_CZ.php create mode 100644 core/lib/Thelia/Config/I18n/de_DE.php create mode 100644 core/lib/Thelia/Config/I18n/el_GR.php create mode 100644 core/lib/Thelia/Config/I18n/en_US.php create mode 100644 core/lib/Thelia/Config/I18n/es_ES.php create mode 100644 core/lib/Thelia/Config/I18n/fa_IR.php create mode 100644 core/lib/Thelia/Config/I18n/fr_FR.php create mode 100644 core/lib/Thelia/Config/I18n/he_IL.php create mode 100644 core/lib/Thelia/Config/I18n/hu_HU.php create mode 100644 core/lib/Thelia/Config/I18n/id_ID.php create mode 100644 core/lib/Thelia/Config/I18n/it_IT.php create mode 100644 core/lib/Thelia/Config/I18n/nl_NL.php create mode 100644 core/lib/Thelia/Config/I18n/pl_PL.php create mode 100644 core/lib/Thelia/Config/I18n/pt_BR.php create mode 100644 core/lib/Thelia/Config/I18n/pt_PT.php create mode 100644 core/lib/Thelia/Config/I18n/ro_RO.php create mode 100644 core/lib/Thelia/Config/I18n/ru_RU.php create mode 100644 core/lib/Thelia/Config/I18n/sk_SK.php create mode 100644 core/lib/Thelia/Config/I18n/tr_TR.php create mode 100644 core/lib/Thelia/Config/I18n/uk_UA.php create mode 100644 core/lib/Thelia/Config/I18n/zh_CN.php create mode 100644 core/lib/Thelia/Config/Resources/action.xml create mode 100644 core/lib/Thelia/Config/Resources/command.xml create mode 100644 core/lib/Thelia/Config/Resources/config.xml create mode 100644 core/lib/Thelia/Config/Resources/coupon.xml create mode 100644 core/lib/Thelia/Config/Resources/export.xml create mode 100644 core/lib/Thelia/Config/Resources/form-api.xml create mode 100644 core/lib/Thelia/Config/Resources/form-type.xml create mode 100644 core/lib/Thelia/Config/Resources/form.xml create mode 100644 core/lib/Thelia/Config/Resources/import.xml create mode 100644 core/lib/Thelia/Config/Resources/loop.xml create mode 100644 core/lib/Thelia/Config/Resources/routing.xml create mode 100644 core/lib/Thelia/Config/Resources/routing/admin.xml create mode 100644 core/lib/Thelia/Config/Resources/routing/api.xml create mode 100644 core/lib/Thelia/Config/Resources/stack.xml create mode 100644 core/lib/Thelia/Config/Resources/test.xml create mode 100644 core/lib/Thelia/Config/Resources/translation.xml create mode 100644 core/lib/Thelia/Controller/Admin/AbstractCrudController.php create mode 100644 core/lib/Thelia/Controller/Admin/AbstractSeoCrudController.php create mode 100644 core/lib/Thelia/Controller/Admin/AddressController.php create mode 100644 core/lib/Thelia/Controller/Admin/AdminController.php create mode 100644 core/lib/Thelia/Controller/Admin/AdminLogsController.php create mode 100644 core/lib/Thelia/Controller/Admin/AdministratorController.php create mode 100644 core/lib/Thelia/Controller/Admin/AdvancedConfigurationController.php create mode 100644 core/lib/Thelia/Controller/Admin/ApiController.php create mode 100644 core/lib/Thelia/Controller/Admin/AreaController.php create mode 100644 core/lib/Thelia/Controller/Admin/AttributeAvController.php create mode 100644 core/lib/Thelia/Controller/Admin/AttributeController.php create mode 100644 core/lib/Thelia/Controller/Admin/BaseAdminController.php create mode 100644 core/lib/Thelia/Controller/Admin/BrandController.php create mode 100644 core/lib/Thelia/Controller/Admin/CategoryController.php create mode 100644 core/lib/Thelia/Controller/Admin/ConfigController.php create mode 100644 core/lib/Thelia/Controller/Admin/ConfigStoreController.php create mode 100644 core/lib/Thelia/Controller/Admin/ConfigurationController.php create mode 100644 core/lib/Thelia/Controller/Admin/ContentController.php create mode 100644 core/lib/Thelia/Controller/Admin/CountryController.php create mode 100644 core/lib/Thelia/Controller/Admin/CouponController.php create mode 100644 core/lib/Thelia/Controller/Admin/CurrencyController.php create mode 100644 core/lib/Thelia/Controller/Admin/CustomerController.php create mode 100644 core/lib/Thelia/Controller/Admin/ExportController.php create mode 100644 core/lib/Thelia/Controller/Admin/FeatureAvController.php create mode 100644 core/lib/Thelia/Controller/Admin/FeatureController.php create mode 100644 core/lib/Thelia/Controller/Admin/FileController.php create mode 100644 core/lib/Thelia/Controller/Admin/FolderController.php create mode 100644 core/lib/Thelia/Controller/Admin/HomeController.php create mode 100644 core/lib/Thelia/Controller/Admin/HookController.php create mode 100644 core/lib/Thelia/Controller/Admin/ImportController.php create mode 100644 core/lib/Thelia/Controller/Admin/LangController.php create mode 100644 core/lib/Thelia/Controller/Admin/LanguageController.php create mode 100644 core/lib/Thelia/Controller/Admin/MailingSystemController.php create mode 100644 core/lib/Thelia/Controller/Admin/MessageController.php create mode 100644 core/lib/Thelia/Controller/Admin/ModuleController.php create mode 100644 core/lib/Thelia/Controller/Admin/ModuleHookController.php create mode 100644 core/lib/Thelia/Controller/Admin/OrderController.php create mode 100644 core/lib/Thelia/Controller/Admin/OrderStatusController.php create mode 100644 core/lib/Thelia/Controller/Admin/ProductController.php create mode 100644 core/lib/Thelia/Controller/Admin/ProfileController.php create mode 100644 core/lib/Thelia/Controller/Admin/SaleController.php create mode 100644 core/lib/Thelia/Controller/Admin/SessionController.php create mode 100644 core/lib/Thelia/Controller/Admin/ShippingZoneController.php create mode 100644 core/lib/Thelia/Controller/Admin/StateController.php create mode 100644 core/lib/Thelia/Controller/Admin/SystemLogController.php create mode 100644 core/lib/Thelia/Controller/Admin/TaxController.php create mode 100644 core/lib/Thelia/Controller/Admin/TaxRuleController.php create mode 100644 core/lib/Thelia/Controller/Admin/TemplateController.php create mode 100644 core/lib/Thelia/Controller/Admin/ToolsController.php create mode 100644 core/lib/Thelia/Controller/Admin/TranslationsController.php create mode 100644 core/lib/Thelia/Controller/Api/AbstractCrudApiController.php create mode 100644 core/lib/Thelia/Controller/Api/AttributeAvController.php create mode 100644 core/lib/Thelia/Controller/Api/BaseApiController.php create mode 100644 core/lib/Thelia/Controller/Api/BrandController.php create mode 100644 core/lib/Thelia/Controller/Api/CategoryController.php create mode 100644 core/lib/Thelia/Controller/Api/CountryController.php create mode 100644 core/lib/Thelia/Controller/Api/CurrencyController.php create mode 100644 core/lib/Thelia/Controller/Api/CustomerController.php create mode 100644 core/lib/Thelia/Controller/Api/ImageController.php create mode 100644 core/lib/Thelia/Controller/Api/IndexController.php create mode 100644 core/lib/Thelia/Controller/Api/LangController.php create mode 100644 core/lib/Thelia/Controller/Api/ProductController.php create mode 100644 core/lib/Thelia/Controller/Api/ProductSaleElementsController.php create mode 100644 core/lib/Thelia/Controller/Api/TaxController.php create mode 100644 core/lib/Thelia/Controller/Api/TaxRuleController.php create mode 100644 core/lib/Thelia/Controller/Api/TitleController.php create mode 100644 core/lib/Thelia/Controller/BaseController.php create mode 100644 core/lib/Thelia/Controller/Front/BaseFrontController.php create mode 100644 core/lib/Thelia/Controller/Front/DefaultController.php create mode 100644 core/lib/Thelia/Core/Application.php create mode 100644 core/lib/Thelia/Core/Archiver/AbstractArchiver.php create mode 100644 core/lib/Thelia/Core/Archiver/Archiver/TarArchiver.php create mode 100644 core/lib/Thelia/Core/Archiver/Archiver/TarBz2Archiver.php create mode 100644 core/lib/Thelia/Core/Archiver/Archiver/TarGzArchiver.php create mode 100644 core/lib/Thelia/Core/Archiver/Archiver/ZipArchiver.php create mode 100644 core/lib/Thelia/Core/Archiver/ArchiverInterface.php create mode 100644 core/lib/Thelia/Core/Archiver/ArchiverManager.php create mode 100644 core/lib/Thelia/Core/Bundle/TheliaBundle.php create mode 100644 core/lib/Thelia/Core/Controller/ControllerResolver.php create mode 100644 core/lib/Thelia/Core/DependencyInjection/Compiler/CurrencyConverterProviderPass.php create mode 100644 core/lib/Thelia/Core/DependencyInjection/Compiler/FallbackParserPass.php create mode 100644 core/lib/Thelia/Core/DependencyInjection/Compiler/RegisterArchiverPass.php create mode 100644 core/lib/Thelia/Core/DependencyInjection/Compiler/RegisterAssetFilterPass.php create mode 100644 core/lib/Thelia/Core/DependencyInjection/Compiler/RegisterCouponConditionPass.php create mode 100644 core/lib/Thelia/Core/DependencyInjection/Compiler/RegisterCouponPass.php create mode 100644 core/lib/Thelia/Core/DependencyInjection/Compiler/RegisterFormExtensionPass.php create mode 100644 core/lib/Thelia/Core/DependencyInjection/Compiler/RegisterHookListenersPass.php create mode 100644 core/lib/Thelia/Core/DependencyInjection/Compiler/RegisterRouterPass.php create mode 100644 core/lib/Thelia/Core/DependencyInjection/Compiler/RegisterSerializerPass.php create mode 100644 core/lib/Thelia/Core/DependencyInjection/Compiler/StackPass.php create mode 100644 core/lib/Thelia/Core/DependencyInjection/Compiler/TranslatorPass.php create mode 100644 core/lib/Thelia/Core/DependencyInjection/Loader/XmlFileLoader.php create mode 100644 core/lib/Thelia/Core/DependencyInjection/Loader/schema/dic/config/thelia-1.0.xsd create mode 100644 core/lib/Thelia/Core/DependencyInjection/TheliaContainer.php create mode 100644 core/lib/Thelia/Core/Event/AccessoryEvent.php create mode 100644 core/lib/Thelia/Core/Event/ActionEvent.php create mode 100644 core/lib/Thelia/Core/Event/Address/AddressCreateOrUpdateEvent.php create mode 100644 core/lib/Thelia/Core/Event/Address/AddressEvent.php create mode 100644 core/lib/Thelia/Core/Event/Administrator/AdministratorEvent.php create mode 100644 core/lib/Thelia/Core/Event/Administrator/AdministratorUpdatePasswordEvent.php create mode 100644 core/lib/Thelia/Core/Event/Api/ApiCreateEvent.php create mode 100644 core/lib/Thelia/Core/Event/Api/ApiDeleteEvent.php create mode 100644 core/lib/Thelia/Core/Event/Api/ApiUpdateEvent.php create mode 100644 core/lib/Thelia/Core/Event/Area/AreaAddCountryEvent.php create mode 100644 core/lib/Thelia/Core/Event/Area/AreaCreateEvent.php create mode 100644 core/lib/Thelia/Core/Event/Area/AreaDeleteEvent.php create mode 100644 core/lib/Thelia/Core/Event/Area/AreaEvent.php create mode 100644 core/lib/Thelia/Core/Event/Area/AreaRemoveCountryEvent.php create mode 100644 core/lib/Thelia/Core/Event/Area/AreaUpdateEvent.php create mode 100644 core/lib/Thelia/Core/Event/Area/AreaUpdatePostageEvent.php create mode 100644 core/lib/Thelia/Core/Event/Attribute/AttributeAvCreateEvent.php create mode 100644 core/lib/Thelia/Core/Event/Attribute/AttributeAvDeleteEvent.php create mode 100644 core/lib/Thelia/Core/Event/Attribute/AttributeAvEvent.php create mode 100644 core/lib/Thelia/Core/Event/Attribute/AttributeAvUpdateEvent.php create mode 100644 core/lib/Thelia/Core/Event/Attribute/AttributeCreateEvent.php create mode 100644 core/lib/Thelia/Core/Event/Attribute/AttributeDeleteEvent.php create mode 100644 core/lib/Thelia/Core/Event/Attribute/AttributeEvent.php create mode 100644 core/lib/Thelia/Core/Event/Attribute/AttributeUpdateEvent.php create mode 100644 core/lib/Thelia/Core/Event/Brand/BrandCreateEvent.php create mode 100644 core/lib/Thelia/Core/Event/Brand/BrandDeleteEvent.php create mode 100644 core/lib/Thelia/Core/Event/Brand/BrandEvent.php create mode 100644 core/lib/Thelia/Core/Event/Brand/BrandToggleVisibilityEvent.php create mode 100644 core/lib/Thelia/Core/Event/Brand/BrandUpdateEvent.php create mode 100644 core/lib/Thelia/Core/Event/Cache/CacheEvent.php create mode 100644 core/lib/Thelia/Core/Event/CachedFileEvent.php create mode 100644 core/lib/Thelia/Core/Event/Cart/CartCreateEvent.php create mode 100644 core/lib/Thelia/Core/Event/Cart/CartDuplicationEvent.php create mode 100644 core/lib/Thelia/Core/Event/Cart/CartEvent.php create mode 100644 core/lib/Thelia/Core/Event/Cart/CartItemDuplicationItem.php create mode 100644 core/lib/Thelia/Core/Event/Cart/CartItemEvent.php create mode 100644 core/lib/Thelia/Core/Event/Cart/CartPersistEvent.php create mode 100644 core/lib/Thelia/Core/Event/Cart/CartRestoreEvent.php create mode 100644 core/lib/Thelia/Core/Event/Category/CategoryAddContentEvent.php create mode 100644 core/lib/Thelia/Core/Event/Category/CategoryAssociatedContentEvent.php create mode 100644 core/lib/Thelia/Core/Event/Category/CategoryCreateEvent.php create mode 100644 core/lib/Thelia/Core/Event/Category/CategoryDeleteContentEvent.php create mode 100644 core/lib/Thelia/Core/Event/Category/CategoryDeleteEvent.php create mode 100644 core/lib/Thelia/Core/Event/Category/CategoryEvent.php create mode 100644 core/lib/Thelia/Core/Event/Category/CategoryToggleVisibilityEvent.php create mode 100644 core/lib/Thelia/Core/Event/Category/CategoryUpdateEvent.php create mode 100644 core/lib/Thelia/Core/Event/Config/ConfigCreateEvent.php create mode 100644 core/lib/Thelia/Core/Event/Config/ConfigDeleteEvent.php create mode 100644 core/lib/Thelia/Core/Event/Config/ConfigEvent.php create mode 100644 core/lib/Thelia/Core/Event/Config/ConfigUpdateEvent.php create mode 100644 core/lib/Thelia/Core/Event/Contact/ContactEvent.php create mode 100644 core/lib/Thelia/Core/Event/Content/ContentAddFolderEvent.php create mode 100644 core/lib/Thelia/Core/Event/Content/ContentCreateEvent.php create mode 100644 core/lib/Thelia/Core/Event/Content/ContentDeleteEvent.php create mode 100644 core/lib/Thelia/Core/Event/Content/ContentEvent.php create mode 100644 core/lib/Thelia/Core/Event/Content/ContentRemoveFolderEvent.php create mode 100644 core/lib/Thelia/Core/Event/Content/ContentToggleVisibilityEvent.php create mode 100644 core/lib/Thelia/Core/Event/Content/ContentUpdateEvent.php create mode 100644 core/lib/Thelia/Core/Event/Country/CountryCreateEvent.php create mode 100644 core/lib/Thelia/Core/Event/Country/CountryDeleteEvent.php create mode 100644 core/lib/Thelia/Core/Event/Country/CountryEvent.php create mode 100644 core/lib/Thelia/Core/Event/Country/CountryToggleDefaultEvent.php create mode 100644 core/lib/Thelia/Core/Event/Country/CountryToggleVisibilityEvent.php create mode 100644 core/lib/Thelia/Core/Event/Country/CountryUpdateEvent.php create mode 100644 core/lib/Thelia/Core/Event/Coupon/CouponConsumeEvent.php create mode 100644 core/lib/Thelia/Core/Event/Coupon/CouponCreateOrUpdateEvent.php create mode 100644 core/lib/Thelia/Core/Event/Coupon/CouponDeleteEvent.php create mode 100644 core/lib/Thelia/Core/Event/Currency/CurrencyChangeEvent.php create mode 100644 core/lib/Thelia/Core/Event/Currency/CurrencyCreateEvent.php create mode 100644 core/lib/Thelia/Core/Event/Currency/CurrencyDeleteEvent.php create mode 100644 core/lib/Thelia/Core/Event/Currency/CurrencyEvent.php create mode 100644 core/lib/Thelia/Core/Event/Currency/CurrencyUpdateEvent.php create mode 100644 core/lib/Thelia/Core/Event/Currency/CurrencyUpdateRateEvent.php create mode 100644 core/lib/Thelia/Core/Event/Customer/CustomerCreateOrUpdateEvent.php create mode 100644 core/lib/Thelia/Core/Event/Customer/CustomerEvent.php create mode 100644 core/lib/Thelia/Core/Event/Customer/CustomerLoginEvent.php create mode 100644 core/lib/Thelia/Core/Event/CustomerTitle/CustomerTitleEvent.php create mode 100644 core/lib/Thelia/Core/Event/DefaultActionEvent.php create mode 100644 core/lib/Thelia/Core/Event/Delivery/DeliveryPostageEvent.php create mode 100644 core/lib/Thelia/Core/Event/Delivery/PickupLocationEvent.php create mode 100644 core/lib/Thelia/Core/Event/Document/DocumentEvent.php create mode 100644 core/lib/Thelia/Core/Event/ExportEvent.php create mode 100644 core/lib/Thelia/Core/Event/Feature/FeatureAvCreateEvent.php create mode 100644 core/lib/Thelia/Core/Event/Feature/FeatureAvDeleteEvent.php create mode 100644 core/lib/Thelia/Core/Event/Feature/FeatureAvEvent.php create mode 100644 core/lib/Thelia/Core/Event/Feature/FeatureAvUpdateEvent.php create mode 100644 core/lib/Thelia/Core/Event/Feature/FeatureCreateEvent.php create mode 100644 core/lib/Thelia/Core/Event/Feature/FeatureDeleteEvent.php create mode 100644 core/lib/Thelia/Core/Event/Feature/FeatureEvent.php create mode 100644 core/lib/Thelia/Core/Event/Feature/FeatureUpdateEvent.php create mode 100644 core/lib/Thelia/Core/Event/FeatureProduct/FeatureProductDeleteEvent.php create mode 100644 core/lib/Thelia/Core/Event/FeatureProduct/FeatureProductEvent.php create mode 100644 core/lib/Thelia/Core/Event/FeatureProduct/FeatureProductUpdateEvent.php create mode 100644 core/lib/Thelia/Core/Event/File/FileCreateOrUpdateEvent.php create mode 100644 core/lib/Thelia/Core/Event/File/FileDeleteEvent.php create mode 100644 core/lib/Thelia/Core/Event/File/FileToggleVisibilityEvent.php create mode 100644 core/lib/Thelia/Core/Event/Folder/FolderCreateEvent.php create mode 100644 core/lib/Thelia/Core/Event/Folder/FolderDeleteEvent.php create mode 100644 core/lib/Thelia/Core/Event/Folder/FolderEvent.php create mode 100644 core/lib/Thelia/Core/Event/Folder/FolderToggleVisibilityEvent.php create mode 100644 core/lib/Thelia/Core/Event/Folder/FolderUpdateEvent.php create mode 100644 core/lib/Thelia/Core/Event/GenerateRewrittenUrlEvent.php create mode 100644 core/lib/Thelia/Core/Event/Hook/BaseHookRenderEvent.php create mode 100644 core/lib/Thelia/Core/Event/Hook/HookCreateAllEvent.php create mode 100644 core/lib/Thelia/Core/Event/Hook/HookCreateEvent.php create mode 100644 core/lib/Thelia/Core/Event/Hook/HookDeactivationEvent.php create mode 100644 core/lib/Thelia/Core/Event/Hook/HookDeleteEvent.php create mode 100644 core/lib/Thelia/Core/Event/Hook/HookEvent.php create mode 100644 core/lib/Thelia/Core/Event/Hook/HookRenderBlockEvent.php create mode 100644 core/lib/Thelia/Core/Event/Hook/HookRenderEvent.php create mode 100644 core/lib/Thelia/Core/Event/Hook/HookToggleActivationEvent.php create mode 100644 core/lib/Thelia/Core/Event/Hook/HookToggleNativeEvent.php create mode 100644 core/lib/Thelia/Core/Event/Hook/HookUpdateEvent.php create mode 100644 core/lib/Thelia/Core/Event/Hook/ModuleHookCreateEvent.php create mode 100644 core/lib/Thelia/Core/Event/Hook/ModuleHookDeleteEvent.php create mode 100644 core/lib/Thelia/Core/Event/Hook/ModuleHookEvent.php create mode 100644 core/lib/Thelia/Core/Event/Hook/ModuleHookToggleActivationEvent.php create mode 100644 core/lib/Thelia/Core/Event/Hook/ModuleHookUpdateEvent.php create mode 100644 core/lib/Thelia/Core/Event/Image/ImageEvent.php create mode 100644 core/lib/Thelia/Core/Event/ImportEvent.php create mode 100644 core/lib/Thelia/Core/Event/Lang/LangCreateEvent.php create mode 100644 core/lib/Thelia/Core/Event/Lang/LangDefaultBehaviorEvent.php create mode 100644 core/lib/Thelia/Core/Event/Lang/LangDeleteEvent.php create mode 100644 core/lib/Thelia/Core/Event/Lang/LangEvent.php create mode 100644 core/lib/Thelia/Core/Event/Lang/LangToggleActiveEvent.php create mode 100644 core/lib/Thelia/Core/Event/Lang/LangToggleDefaultEvent.php create mode 100644 core/lib/Thelia/Core/Event/Lang/LangToggleVisibleEvent.php create mode 100644 core/lib/Thelia/Core/Event/Lang/LangUpdateEvent.php create mode 100644 core/lib/Thelia/Core/Event/Loop/LoopExtendsArgDefinitionsEvent.php create mode 100644 core/lib/Thelia/Core/Event/Loop/LoopExtendsBuildArrayEvent.php create mode 100644 core/lib/Thelia/Core/Event/Loop/LoopExtendsBuildModelCriteriaEvent.php create mode 100644 core/lib/Thelia/Core/Event/Loop/LoopExtendsEvent.php create mode 100644 core/lib/Thelia/Core/Event/Loop/LoopExtendsInitializeArgsEvent.php create mode 100644 core/lib/Thelia/Core/Event/Loop/LoopExtendsParseResultsEvent.php create mode 100644 core/lib/Thelia/Core/Event/LostPasswordEvent.php create mode 100644 core/lib/Thelia/Core/Event/MailTransporterEvent.php create mode 100644 core/lib/Thelia/Core/Event/MailingSystem/MailingSystemEvent.php create mode 100644 core/lib/Thelia/Core/Event/Message/MessageCreateEvent.php create mode 100644 core/lib/Thelia/Core/Event/Message/MessageDeleteEvent.php create mode 100644 core/lib/Thelia/Core/Event/Message/MessageEvent.php create mode 100644 core/lib/Thelia/Core/Event/Message/MessageUpdateEvent.php create mode 100644 core/lib/Thelia/Core/Event/MetaData/MetaDataCreateOrUpdateEvent.php create mode 100644 core/lib/Thelia/Core/Event/MetaData/MetaDataDeleteEvent.php create mode 100644 core/lib/Thelia/Core/Event/MetaData/MetaDataEvent.php create mode 100644 core/lib/Thelia/Core/Event/Module/ModuleDeleteEvent.php create mode 100644 core/lib/Thelia/Core/Event/Module/ModuleEvent.php create mode 100644 core/lib/Thelia/Core/Event/Module/ModuleInstallEvent.php create mode 100644 core/lib/Thelia/Core/Event/Module/ModuleToggleActivationEvent.php create mode 100644 core/lib/Thelia/Core/Event/Newsletter/NewsletterEvent.php create mode 100644 core/lib/Thelia/Core/Event/Order/GetStockUpdateOperationOnOrderStatusChangeEvent.php create mode 100644 core/lib/Thelia/Core/Event/Order/OrderAddressEvent.php create mode 100644 core/lib/Thelia/Core/Event/Order/OrderEvent.php create mode 100644 core/lib/Thelia/Core/Event/Order/OrderManualEvent.php create mode 100644 core/lib/Thelia/Core/Event/Order/OrderPaymentEvent.php create mode 100644 core/lib/Thelia/Core/Event/Order/OrderProductEvent.php create mode 100644 core/lib/Thelia/Core/Event/OrderStatus/OrderStatusCreateEvent.php create mode 100644 core/lib/Thelia/Core/Event/OrderStatus/OrderStatusDeleteEvent.php create mode 100644 core/lib/Thelia/Core/Event/OrderStatus/OrderStatusEvent.php create mode 100644 core/lib/Thelia/Core/Event/OrderStatus/OrderStatusUpdateEvent.php create mode 100644 core/lib/Thelia/Core/Event/Payment/BasePaymentEvent.php create mode 100644 core/lib/Thelia/Core/Event/Payment/IsValidPaymentEvent.php create mode 100644 core/lib/Thelia/Core/Event/Payment/ManageStockOnCreationEvent.php create mode 100644 core/lib/Thelia/Core/Event/PdfEvent.php create mode 100644 core/lib/Thelia/Core/Event/Product/ProductAddAccessoryEvent.php create mode 100644 core/lib/Thelia/Core/Event/Product/ProductAddCategoryEvent.php create mode 100644 core/lib/Thelia/Core/Event/Product/ProductAddContentEvent.php create mode 100644 core/lib/Thelia/Core/Event/Product/ProductAssociatedContentEvent.php create mode 100644 core/lib/Thelia/Core/Event/Product/ProductCloneEvent.php create mode 100644 core/lib/Thelia/Core/Event/Product/ProductCombinationGenerationEvent.php create mode 100644 core/lib/Thelia/Core/Event/Product/ProductCreateEvent.php create mode 100644 core/lib/Thelia/Core/Event/Product/ProductDeleteAccessoryEvent.php create mode 100644 core/lib/Thelia/Core/Event/Product/ProductDeleteCategoryEvent.php create mode 100644 core/lib/Thelia/Core/Event/Product/ProductDeleteContentEvent.php create mode 100644 core/lib/Thelia/Core/Event/Product/ProductDeleteEvent.php create mode 100644 core/lib/Thelia/Core/Event/Product/ProductEvent.php create mode 100644 core/lib/Thelia/Core/Event/Product/ProductSetTemplateEvent.php create mode 100644 core/lib/Thelia/Core/Event/Product/ProductToggleVisibilityEvent.php create mode 100644 core/lib/Thelia/Core/Event/Product/ProductUpdateEvent.php create mode 100644 core/lib/Thelia/Core/Event/Product/VirtualProductOrderDownloadResponseEvent.php create mode 100644 core/lib/Thelia/Core/Event/Product/VirtualProductOrderHandleEvent.php create mode 100644 core/lib/Thelia/Core/Event/ProductSaleElement/ProductSaleElementCreateEvent.php create mode 100644 core/lib/Thelia/Core/Event/ProductSaleElement/ProductSaleElementDeleteEvent.php create mode 100644 core/lib/Thelia/Core/Event/ProductSaleElement/ProductSaleElementEvent.php create mode 100644 core/lib/Thelia/Core/Event/ProductSaleElement/ProductSaleElementUpdateEvent.php create mode 100644 core/lib/Thelia/Core/Event/Profile/ProfileEvent.php create mode 100644 core/lib/Thelia/Core/Event/Sale/ProductSaleStatusUpdateEvent.php create mode 100644 core/lib/Thelia/Core/Event/Sale/SaleActiveStatusCheckEvent.php create mode 100644 core/lib/Thelia/Core/Event/Sale/SaleClearStatusEvent.php create mode 100644 core/lib/Thelia/Core/Event/Sale/SaleCreateEvent.php create mode 100644 core/lib/Thelia/Core/Event/Sale/SaleDeleteEvent.php create mode 100644 core/lib/Thelia/Core/Event/Sale/SaleEvent.php create mode 100644 core/lib/Thelia/Core/Event/Sale/SaleToggleActivityEvent.php create mode 100644 core/lib/Thelia/Core/Event/Sale/SaleUpdateEvent.php create mode 100644 core/lib/Thelia/Core/Event/SessionEvent.php create mode 100644 core/lib/Thelia/Core/Event/ShippingZone/ShippingZoneAddAreaEvent.php create mode 100644 core/lib/Thelia/Core/Event/ShippingZone/ShippingZoneRemoveAreaEvent.php create mode 100644 core/lib/Thelia/Core/Event/State/StateCreateEvent.php create mode 100644 core/lib/Thelia/Core/Event/State/StateDeleteEvent.php create mode 100644 core/lib/Thelia/Core/Event/State/StateEvent.php create mode 100644 core/lib/Thelia/Core/Event/State/StateToggleVisibilityEvent.php create mode 100644 core/lib/Thelia/Core/Event/State/StateUpdateEvent.php create mode 100644 core/lib/Thelia/Core/Event/Tax/TaxEvent.php create mode 100644 core/lib/Thelia/Core/Event/Tax/TaxRuleEvent.php create mode 100644 core/lib/Thelia/Core/Event/Template/TemplateAddAttributeEvent.php create mode 100644 core/lib/Thelia/Core/Event/Template/TemplateAddFeatureEvent.php create mode 100644 core/lib/Thelia/Core/Event/Template/TemplateCreateEvent.php create mode 100644 core/lib/Thelia/Core/Event/Template/TemplateDeleteAttributeEvent.php create mode 100644 core/lib/Thelia/Core/Event/Template/TemplateDeleteEvent.php create mode 100644 core/lib/Thelia/Core/Event/Template/TemplateDeleteFeatureEvent.php create mode 100644 core/lib/Thelia/Core/Event/Template/TemplateDuplicateEvent.php create mode 100644 core/lib/Thelia/Core/Event/Template/TemplateEvent.php create mode 100644 core/lib/Thelia/Core/Event/Template/TemplateUpdateEvent.php create mode 100644 core/lib/Thelia/Core/Event/TheliaEvents.php create mode 100644 core/lib/Thelia/Core/Event/TheliaFormEvent.php create mode 100644 core/lib/Thelia/Core/Event/ToggleVisibilityEvent.php create mode 100644 core/lib/Thelia/Core/Event/Translation/TranslationEvent.php create mode 100644 core/lib/Thelia/Core/Event/UpdateFilePositionEvent.php create mode 100644 core/lib/Thelia/Core/Event/UpdatePositionEvent.php create mode 100644 core/lib/Thelia/Core/Event/UpdateSeoEvent.php create mode 100644 core/lib/Thelia/Core/Event/ViewCheckEvent.php create mode 100644 core/lib/Thelia/Core/EventListener/ControllerListener.php create mode 100644 core/lib/Thelia/Core/EventListener/ErrorListener.php create mode 100644 core/lib/Thelia/Core/EventListener/RequestListener.php create mode 100644 core/lib/Thelia/Core/EventListener/ResponseListener.php create mode 100644 core/lib/Thelia/Core/EventListener/SessionListener.php create mode 100644 core/lib/Thelia/Core/EventListener/ViewListener.php create mode 100644 core/lib/Thelia/Core/Form/TheliaFormFactory.php create mode 100644 core/lib/Thelia/Core/Form/TheliaFormFactoryInterface.php create mode 100644 core/lib/Thelia/Core/Form/TheliaFormValidator.php create mode 100644 core/lib/Thelia/Core/Form/TheliaFormValidatorInterface.php create mode 100644 core/lib/Thelia/Core/Form/Type/AbstractTheliaType.php create mode 100644 core/lib/Thelia/Core/Form/Type/CustomerTitleI18nType.php create mode 100644 core/lib/Thelia/Core/Form/Type/CustomerTitleType.php create mode 100644 core/lib/Thelia/Core/Form/Type/Field/AbstractIdType.php create mode 100644 core/lib/Thelia/Core/Form/Type/Field/AccessoryIdType.php create mode 100644 core/lib/Thelia/Core/Form/Type/Field/AddressIdType.php create mode 100644 core/lib/Thelia/Core/Form/Type/Field/AdminIdType.php create mode 100644 core/lib/Thelia/Core/Form/Type/Field/AdminLogIdType.php create mode 100644 core/lib/Thelia/Core/Form/Type/Field/ApiIdType.php create mode 100644 core/lib/Thelia/Core/Form/Type/Field/AreaDeliveryModuleIdType.php create mode 100644 core/lib/Thelia/Core/Form/Type/Field/AreaIdType.php create mode 100644 core/lib/Thelia/Core/Form/Type/Field/AttributeAvIdType.php create mode 100644 core/lib/Thelia/Core/Form/Type/Field/AttributeIdType.php create mode 100644 core/lib/Thelia/Core/Form/Type/Field/AttributeTemplateIdType.php create mode 100644 core/lib/Thelia/Core/Form/Type/Field/BrandIdType.php create mode 100644 core/lib/Thelia/Core/Form/Type/Field/CartIdType.php create mode 100644 core/lib/Thelia/Core/Form/Type/Field/CartItemIdType.php create mode 100644 core/lib/Thelia/Core/Form/Type/Field/CategoryAssociatedContentIdType.php create mode 100644 core/lib/Thelia/Core/Form/Type/Field/CategoryIdType.php create mode 100644 core/lib/Thelia/Core/Form/Type/Field/ContentIdType.php create mode 100644 core/lib/Thelia/Core/Form/Type/Field/CountryIdType.php create mode 100644 core/lib/Thelia/Core/Form/Type/Field/CouponIdType.php create mode 100644 core/lib/Thelia/Core/Form/Type/Field/CurrencyIdType.php create mode 100644 core/lib/Thelia/Core/Form/Type/Field/CustomerIdType.php create mode 100644 core/lib/Thelia/Core/Form/Type/Field/CustomerTitleIdType.php create mode 100644 core/lib/Thelia/Core/Form/Type/Field/ExportCategoryIdType.php create mode 100644 core/lib/Thelia/Core/Form/Type/Field/ExportIdType.php create mode 100644 core/lib/Thelia/Core/Form/Type/Field/FeatureAvIdType.php create mode 100644 core/lib/Thelia/Core/Form/Type/Field/FeatureIdType.php create mode 100644 core/lib/Thelia/Core/Form/Type/Field/FeatureProductIdType.php create mode 100644 core/lib/Thelia/Core/Form/Type/Field/FeatureTemplateIdType.php create mode 100644 core/lib/Thelia/Core/Form/Type/Field/FolderIdType.php create mode 100644 core/lib/Thelia/Core/Form/Type/Field/FormFirewallIdType.php create mode 100644 core/lib/Thelia/Core/Form/Type/Field/HookIdType.php create mode 100644 core/lib/Thelia/Core/Form/Type/Field/ImportCategoryIdType.php create mode 100644 core/lib/Thelia/Core/Form/Type/Field/ImportIdType.php create mode 100644 core/lib/Thelia/Core/Form/Type/Field/LangIdType.php create mode 100644 core/lib/Thelia/Core/Form/Type/Field/MessageIdType.php create mode 100644 core/lib/Thelia/Core/Form/Type/Field/MetaDataIdType.php create mode 100644 core/lib/Thelia/Core/Form/Type/Field/ModuleConfigIdType.php create mode 100644 core/lib/Thelia/Core/Form/Type/Field/ModuleHookIdType.php create mode 100644 core/lib/Thelia/Core/Form/Type/Field/ModuleIdType.php create mode 100644 core/lib/Thelia/Core/Form/Type/Field/NewsletterIdType.php create mode 100644 core/lib/Thelia/Core/Form/Type/Field/OrderAddressIdType.php create mode 100644 core/lib/Thelia/Core/Form/Type/Field/OrderCouponIdType.php create mode 100644 core/lib/Thelia/Core/Form/Type/Field/OrderIdType.php create mode 100644 core/lib/Thelia/Core/Form/Type/Field/OrderProductAttributeCombinationIdType.php create mode 100644 core/lib/Thelia/Core/Form/Type/Field/OrderProductIdType.php create mode 100644 core/lib/Thelia/Core/Form/Type/Field/OrderProductTaxIdType.php create mode 100644 core/lib/Thelia/Core/Form/Type/Field/OrderStatusIdType.php create mode 100644 core/lib/Thelia/Core/Form/Type/Field/ProductAssociatedContentIdType.php create mode 100644 core/lib/Thelia/Core/Form/Type/Field/ProductIdType.php create mode 100644 core/lib/Thelia/Core/Form/Type/Field/ProductSaleElementsIdType.php create mode 100644 core/lib/Thelia/Core/Form/Type/Field/ProfileIdType.php create mode 100644 core/lib/Thelia/Core/Form/Type/Field/ResourceIdType.php create mode 100644 core/lib/Thelia/Core/Form/Type/Field/RewritingUrlIdType.php create mode 100644 core/lib/Thelia/Core/Form/Type/Field/SaleIdType.php create mode 100644 core/lib/Thelia/Core/Form/Type/Field/SaleProductIdType.php create mode 100644 core/lib/Thelia/Core/Form/Type/Field/StateIdType.php create mode 100644 core/lib/Thelia/Core/Form/Type/Field/TaxIdType.php create mode 100644 core/lib/Thelia/Core/Form/Type/Field/TaxRuleIdType.php create mode 100644 core/lib/Thelia/Core/Form/Type/Field/TemplateIdType.php create mode 100644 core/lib/Thelia/Core/Form/Type/ImageType.php create mode 100644 core/lib/Thelia/Core/Form/Type/ProductSaleElementsType.php create mode 100644 core/lib/Thelia/Core/Form/Type/StandardFieldsType.php create mode 100644 core/lib/Thelia/Core/Form/Type/TaxRuleI18nType.php create mode 100644 core/lib/Thelia/Core/Form/Type/TaxRuleType.php create mode 100644 core/lib/Thelia/Core/Form/Type/TheliaType.php create mode 100644 core/lib/Thelia/Core/Hook/BaseHook.php create mode 100644 core/lib/Thelia/Core/Hook/DefaultHook.php create mode 100644 core/lib/Thelia/Core/Hook/Fragment.php create mode 100644 core/lib/Thelia/Core/Hook/FragmentBag.php create mode 100644 core/lib/Thelia/Core/Hook/HookDefinition.php create mode 100644 core/lib/Thelia/Core/Hook/HookHelper.php create mode 100644 core/lib/Thelia/Core/HttpFoundation/JsonResponse.php create mode 100644 core/lib/Thelia/Core/HttpFoundation/Request.php create mode 100644 core/lib/Thelia/Core/HttpFoundation/Response.php create mode 100644 core/lib/Thelia/Core/HttpFoundation/Session/Session.php create mode 100644 core/lib/Thelia/Core/HttpKernel/Client.php create mode 100644 core/lib/Thelia/Core/HttpKernel/Exception/NotFountHttpException.php create mode 100644 core/lib/Thelia/Core/HttpKernel/Exception/RedirectException.php create mode 100644 core/lib/Thelia/Core/HttpKernel/Fragment/InlineFragmentRenderer.php create mode 100644 core/lib/Thelia/Core/HttpKernel/HttpCache/HttpCache.php create mode 100644 core/lib/Thelia/Core/Propel/Generator/Builder/Om/EventBuilder.php create mode 100644 core/lib/Thelia/Core/Propel/Generator/Builder/Om/ExtensionObjectBuilder.php create mode 100644 core/lib/Thelia/Core/Propel/Generator/Builder/Om/ExtensionQueryBuilder.php create mode 100644 core/lib/Thelia/Core/Propel/Generator/Builder/Om/ExtensionQueryInheritanceBuilder.php create mode 100644 core/lib/Thelia/Core/Propel/Generator/Builder/Om/InterfaceBuilder.php create mode 100644 core/lib/Thelia/Core/Propel/Generator/Builder/Om/Mixin/ImplementationClassTrait.php create mode 100644 core/lib/Thelia/Core/Propel/Generator/Builder/Om/Mixin/StubClassTrait.php create mode 100644 core/lib/Thelia/Core/Propel/Generator/Builder/Om/MultiExtendObjectBuilder.php create mode 100644 core/lib/Thelia/Core/Propel/Generator/Builder/Om/ObjectBuilder.php create mode 100644 core/lib/Thelia/Core/Propel/Generator/Builder/Om/QueryBuilder.php create mode 100644 core/lib/Thelia/Core/Propel/Generator/Builder/Om/QueryInheritanceBuilder.php create mode 100644 core/lib/Thelia/Core/Propel/Generator/Builder/Om/TableMapBuilder.php create mode 100644 core/lib/Thelia/Core/Propel/Generator/Builder/ResolverBuilder.php create mode 100644 core/lib/Thelia/Core/Propel/Schema/SchemaCombiner.php create mode 100644 core/lib/Thelia/Core/Propel/Schema/SchemaLocator.php create mode 100644 core/lib/Thelia/Core/PropelInitService.php create mode 100644 core/lib/Thelia/Core/Routing/RewritingRouter.php create mode 100644 core/lib/Thelia/Core/Security/AccessManager.php create mode 100644 core/lib/Thelia/Core/Security/Authentication/AdminTokenAuthenticator.php create mode 100644 core/lib/Thelia/Core/Security/Authentication/AdminUsernamePasswordFormAuthenticator.php create mode 100644 core/lib/Thelia/Core/Security/Authentication/AuthenticatorInterface.php create mode 100644 core/lib/Thelia/Core/Security/Authentication/CustomerTokenAuthenticator.php create mode 100644 core/lib/Thelia/Core/Security/Authentication/CustomerUsernamePasswordFormAuthenticator.php create mode 100644 core/lib/Thelia/Core/Security/Authentication/TokenAuthenticator.php create mode 100644 core/lib/Thelia/Core/Security/Authentication/UsernamePasswordFormAuthenticator.php create mode 100644 core/lib/Thelia/Core/Security/Exception/AuthenticationException.php create mode 100644 core/lib/Thelia/Core/Security/Exception/AuthorizationException.php create mode 100644 core/lib/Thelia/Core/Security/Exception/CustomerNotConfirmedException.php create mode 100644 core/lib/Thelia/Core/Security/Exception/ResourceException.php create mode 100644 core/lib/Thelia/Core/Security/Exception/TokenAuthenticationException.php create mode 100644 core/lib/Thelia/Core/Security/Exception/UsernameNotFoundException.php create mode 100644 core/lib/Thelia/Core/Security/Exception/WrongPasswordException.php create mode 100644 core/lib/Thelia/Core/Security/Resource/AdminResources.php create mode 100644 core/lib/Thelia/Core/Security/Role/Role.php create mode 100644 core/lib/Thelia/Core/Security/Role/RoleInterface.php create mode 100644 core/lib/Thelia/Core/Security/SecurityContext.php create mode 100644 core/lib/Thelia/Core/Security/Token/CookieTokenProvider.php create mode 100644 core/lib/Thelia/Core/Security/Token/TokenProvider.php create mode 100644 core/lib/Thelia/Core/Security/User/UserInterface.php create mode 100644 core/lib/Thelia/Core/Security/User/UserPermissionsTrait.php create mode 100644 core/lib/Thelia/Core/Security/UserProvider/AdminTokenUserProvider.php create mode 100644 core/lib/Thelia/Core/Security/UserProvider/AdminUserProvider.php create mode 100644 core/lib/Thelia/Core/Security/UserProvider/CustomerTokenUserProvider.php create mode 100644 core/lib/Thelia/Core/Security/UserProvider/CustomerUserProvider.php create mode 100644 core/lib/Thelia/Core/Security/UserProvider/TokenUserProvider.php create mode 100644 core/lib/Thelia/Core/Security/UserProvider/UserProviderInterface.php create mode 100644 core/lib/Thelia/Core/Serializer/AbstractSerializer.php create mode 100644 core/lib/Thelia/Core/Serializer/Serializer/CSVSerializer.php create mode 100644 core/lib/Thelia/Core/Serializer/Serializer/JSONSerializer.php create mode 100644 core/lib/Thelia/Core/Serializer/Serializer/XMLSerializer.php create mode 100644 core/lib/Thelia/Core/Serializer/Serializer/YAMLSerializer.php create mode 100644 core/lib/Thelia/Core/Serializer/SerializerInterface.php create mode 100644 core/lib/Thelia/Core/Serializer/SerializerManager.php create mode 100644 core/lib/Thelia/Core/Stack/ParamInitMiddleware.php create mode 100644 core/lib/Thelia/Core/Stack/SessionMiddleware.php create mode 100644 core/lib/Thelia/Core/Template/Assets/AssetManagerInterface.php create mode 100644 core/lib/Thelia/Core/Template/Assets/AssetResolverInterface.php create mode 100644 core/lib/Thelia/Core/Template/Assets/AsseticAssetManager.php create mode 100644 core/lib/Thelia/Core/Template/Assets/Filter/LessDotPhpFilter.php create mode 100644 core/lib/Thelia/Core/Template/Element/ArraySearchLoopInterface.php create mode 100644 core/lib/Thelia/Core/Template/Element/BaseI18nLoop.php create mode 100644 core/lib/Thelia/Core/Template/Element/BaseLoop.php create mode 100644 core/lib/Thelia/Core/Template/Element/Exception/ElementNotFoundException.php create mode 100644 core/lib/Thelia/Core/Template/Element/Exception/InvalidElementException.php create mode 100644 core/lib/Thelia/Core/Template/Element/Exception/LoopException.php create mode 100644 core/lib/Thelia/Core/Template/Element/Exception/SearchLoopException.php create mode 100644 core/lib/Thelia/Core/Template/Element/FlashMessage.php create mode 100644 core/lib/Thelia/Core/Template/Element/LoopResult.php create mode 100644 core/lib/Thelia/Core/Template/Element/LoopResultRow.php create mode 100644 core/lib/Thelia/Core/Template/Element/PropelSearchLoopInterface.php create mode 100644 core/lib/Thelia/Core/Template/Element/SearchLoopInterface.php create mode 100644 core/lib/Thelia/Core/Template/Element/StandardI18nFieldsSearchTrait.php create mode 100644 core/lib/Thelia/Core/Template/Exception/InvalidDescriptorException.php create mode 100644 core/lib/Thelia/Core/Template/Exception/ResourceNotFoundException.php create mode 100644 core/lib/Thelia/Core/Template/Exception/TemplateException.php create mode 100644 core/lib/Thelia/Core/Template/Loop/Accessory.php create mode 100644 core/lib/Thelia/Core/Template/Loop/Address.php create mode 100644 core/lib/Thelia/Core/Template/Loop/Admin.php create mode 100644 core/lib/Thelia/Core/Template/Loop/Archiver.php create mode 100644 core/lib/Thelia/Core/Template/Loop/Area.php create mode 100644 core/lib/Thelia/Core/Template/Loop/Argument/Argument.php create mode 100644 core/lib/Thelia/Core/Template/Loop/Argument/ArgumentCollection.php create mode 100644 core/lib/Thelia/Core/Template/Loop/AssociatedContent.php create mode 100644 core/lib/Thelia/Core/Template/Loop/Attribute.php create mode 100644 core/lib/Thelia/Core/Template/Loop/AttributeAvailability.php create mode 100644 core/lib/Thelia/Core/Template/Loop/AttributeCombination.php create mode 100644 core/lib/Thelia/Core/Template/Loop/Auth.php create mode 100644 core/lib/Thelia/Core/Template/Loop/BaseSpecificModule.php create mode 100644 core/lib/Thelia/Core/Template/Loop/Brand.php create mode 100644 core/lib/Thelia/Core/Template/Loop/Cart.php create mode 100644 core/lib/Thelia/Core/Template/Loop/Category.php create mode 100644 core/lib/Thelia/Core/Template/Loop/CategoryPath.php create mode 100644 core/lib/Thelia/Core/Template/Loop/CategoryTree.php create mode 100644 core/lib/Thelia/Core/Template/Loop/Config.php create mode 100644 core/lib/Thelia/Core/Template/Loop/Content.php create mode 100644 core/lib/Thelia/Core/Template/Loop/Country.php create mode 100644 core/lib/Thelia/Core/Template/Loop/CountryArea.php create mode 100644 core/lib/Thelia/Core/Template/Loop/Coupon.php create mode 100644 core/lib/Thelia/Core/Template/Loop/Currency.php create mode 100644 core/lib/Thelia/Core/Template/Loop/Customer.php create mode 100644 core/lib/Thelia/Core/Template/Loop/Delivery.php create mode 100644 core/lib/Thelia/Core/Template/Loop/Document.php create mode 100644 core/lib/Thelia/Core/Template/Loop/Export.php create mode 100644 core/lib/Thelia/Core/Template/Loop/ExportCategory.php create mode 100644 core/lib/Thelia/Core/Template/Loop/Feature.php create mode 100644 core/lib/Thelia/Core/Template/Loop/FeatureAvailability.php create mode 100644 core/lib/Thelia/Core/Template/Loop/FeatureValue.php create mode 100644 core/lib/Thelia/Core/Template/Loop/Feed.php create mode 100644 core/lib/Thelia/Core/Template/Loop/Folder.php create mode 100644 core/lib/Thelia/Core/Template/Loop/FolderPath.php create mode 100644 core/lib/Thelia/Core/Template/Loop/FolderTree.php create mode 100644 core/lib/Thelia/Core/Template/Loop/Hook.php create mode 100644 core/lib/Thelia/Core/Template/Loop/Image.php create mode 100644 core/lib/Thelia/Core/Template/Loop/Import.php create mode 100644 core/lib/Thelia/Core/Template/Loop/ImportCategory.php create mode 100644 core/lib/Thelia/Core/Template/Loop/ImportExportCategory.php create mode 100644 core/lib/Thelia/Core/Template/Loop/ImportExportType.php create mode 100644 core/lib/Thelia/Core/Template/Loop/Lang.php create mode 100644 core/lib/Thelia/Core/Template/Loop/Message.php create mode 100644 core/lib/Thelia/Core/Template/Loop/Module.php create mode 100644 core/lib/Thelia/Core/Template/Loop/ModuleConfig.php create mode 100644 core/lib/Thelia/Core/Template/Loop/ModuleHook.php create mode 100644 core/lib/Thelia/Core/Template/Loop/Order.php create mode 100644 core/lib/Thelia/Core/Template/Loop/OrderAddress.php create mode 100644 core/lib/Thelia/Core/Template/Loop/OrderCoupon.php create mode 100644 core/lib/Thelia/Core/Template/Loop/OrderProduct.php create mode 100644 core/lib/Thelia/Core/Template/Loop/OrderProductAttributeCombination.php create mode 100644 core/lib/Thelia/Core/Template/Loop/OrderProductTax.php create mode 100644 core/lib/Thelia/Core/Template/Loop/OrderStatus.php create mode 100644 core/lib/Thelia/Core/Template/Loop/Payment.php create mode 100644 core/lib/Thelia/Core/Template/Loop/Product.php create mode 100644 core/lib/Thelia/Core/Template/Loop/ProductSaleElements.php create mode 100644 core/lib/Thelia/Core/Template/Loop/ProductSaleElementsDocument.php create mode 100644 core/lib/Thelia/Core/Template/Loop/ProductSaleElementsImage.php create mode 100644 core/lib/Thelia/Core/Template/Loop/ProductTemplate.php create mode 100644 core/lib/Thelia/Core/Template/Loop/Profile.php create mode 100644 core/lib/Thelia/Core/Template/Loop/Resource.php create mode 100644 core/lib/Thelia/Core/Template/Loop/Sale.php create mode 100644 core/lib/Thelia/Core/Template/Loop/Serializer.php create mode 100644 core/lib/Thelia/Core/Template/Loop/State.php create mode 100644 core/lib/Thelia/Core/Template/Loop/Tax.php create mode 100644 core/lib/Thelia/Core/Template/Loop/TaxRule.php create mode 100644 core/lib/Thelia/Core/Template/Loop/TaxRuleCountry.php create mode 100644 core/lib/Thelia/Core/Template/Loop/Template.php create mode 100644 core/lib/Thelia/Core/Template/Loop/Title.php create mode 100644 core/lib/Thelia/Core/Template/Parser/ParserAssetResolverFallback.php create mode 100644 core/lib/Thelia/Core/Template/Parser/ParserFallback.php create mode 100644 core/lib/Thelia/Core/Template/Parser/ParserHelperFallback.php create mode 100644 core/lib/Thelia/Core/Template/ParserContext.php create mode 100644 core/lib/Thelia/Core/Template/ParserHelperInterface.php create mode 100644 core/lib/Thelia/Core/Template/ParserInterface.php create mode 100644 core/lib/Thelia/Core/Template/Smarty/AbstractSmartyPlugin.php create mode 100644 core/lib/Thelia/Core/Template/Smarty/SmartyPluginDescriptor.php create mode 100644 core/lib/Thelia/Core/Template/TemplateDefinition.php create mode 100644 core/lib/Thelia/Core/Template/TemplateHelperInterface.php create mode 100644 core/lib/Thelia/Core/Template/TheliaTemplateHelper.php create mode 100644 core/lib/Thelia/Core/Template/Validator/TemplateDescriptor.php create mode 100644 core/lib/Thelia/Core/Template/Validator/TemplateDescriptorValidator.php create mode 100644 core/lib/Thelia/Core/Template/Validator/TemplateValidator.php create mode 100644 core/lib/Thelia/Core/Template/Validator/schema/template/template-1_0.xsd create mode 100644 core/lib/Thelia/Core/Thelia.php create mode 100644 core/lib/Thelia/Core/TheliaContainerBuilder.php create mode 100644 core/lib/Thelia/Core/TheliaHttpKernel.php create mode 100644 core/lib/Thelia/Core/TheliaKernelEvents.php create mode 100644 core/lib/Thelia/Core/Translation/Translator.php create mode 100644 core/lib/Thelia/Coupon/BaseFacade.php create mode 100644 core/lib/Thelia/Coupon/CouponFactory.php create mode 100644 core/lib/Thelia/Coupon/CouponManager.php create mode 100644 core/lib/Thelia/Coupon/FacadeInterface.php create mode 100644 core/lib/Thelia/Coupon/Type/AbstractRemove.php create mode 100644 core/lib/Thelia/Coupon/Type/AbstractRemoveOnAttributeValues.php create mode 100644 core/lib/Thelia/Coupon/Type/AbstractRemoveOnCategories.php create mode 100644 core/lib/Thelia/Coupon/Type/AbstractRemoveOnProducts.php create mode 100644 core/lib/Thelia/Coupon/Type/AmountAndPercentageCouponInterface.php create mode 100644 core/lib/Thelia/Coupon/Type/AmountCouponTrait.php create mode 100644 core/lib/Thelia/Coupon/Type/CouponAbstract.php create mode 100644 core/lib/Thelia/Coupon/Type/CouponInterface.php create mode 100644 core/lib/Thelia/Coupon/Type/FreeProduct.php create mode 100644 core/lib/Thelia/Coupon/Type/PercentageCouponTrait.php create mode 100644 core/lib/Thelia/Coupon/Type/RemoveAmountOnAttributeValues.php create mode 100644 core/lib/Thelia/Coupon/Type/RemoveAmountOnCategories.php create mode 100644 core/lib/Thelia/Coupon/Type/RemoveAmountOnProducts.php create mode 100644 core/lib/Thelia/Coupon/Type/RemovePercentageOnAttributeValues.php create mode 100644 core/lib/Thelia/Coupon/Type/RemovePercentageOnCategories.php create mode 100644 core/lib/Thelia/Coupon/Type/RemovePercentageOnProducts.php create mode 100644 core/lib/Thelia/Coupon/Type/RemoveXAmount.php create mode 100644 core/lib/Thelia/Coupon/Type/RemoveXPercent.php create mode 100644 core/lib/Thelia/Exception/AdminAccessDenied.php create mode 100644 core/lib/Thelia/Exception/CouponExpiredException.php create mode 100644 core/lib/Thelia/Exception/CouponNoUsageLeftException.php create mode 100644 core/lib/Thelia/Exception/CouponNotReleaseException.php create mode 100644 core/lib/Thelia/Exception/CustomerException.php create mode 100644 core/lib/Thelia/Exception/DocumentException.php create mode 100644 core/lib/Thelia/Exception/FileException.php create mode 100644 core/lib/Thelia/Exception/FileNotFoundException.php create mode 100644 core/lib/Thelia/Exception/FileNotReadableException.php create mode 100644 core/lib/Thelia/Exception/HttpUrlException.php create mode 100644 core/lib/Thelia/Exception/ImageException.php create mode 100644 core/lib/Thelia/Exception/InactiveCouponException.php create mode 100644 core/lib/Thelia/Exception/InvalidCartException.php create mode 100644 core/lib/Thelia/Exception/InvalidConditionException.php create mode 100644 core/lib/Thelia/Exception/InvalidConditionOperatorException.php create mode 100644 core/lib/Thelia/Exception/InvalidConditionValueException.php create mode 100644 core/lib/Thelia/Exception/InvalidModuleException.php create mode 100644 core/lib/Thelia/Exception/MemberAccessException.php create mode 100644 core/lib/Thelia/Exception/MissingFacadeException.php create mode 100644 core/lib/Thelia/Exception/ModuleException.php create mode 100644 core/lib/Thelia/Exception/NotImplementedException.php create mode 100644 core/lib/Thelia/Exception/OrderException.php create mode 100644 core/lib/Thelia/Exception/TaxEngineException.php create mode 100644 core/lib/Thelia/Exception/TheliaProcessException.php create mode 100644 core/lib/Thelia/Exception/TypeException.php create mode 100644 core/lib/Thelia/Exception/UnmatchableConditionException.php create mode 100644 core/lib/Thelia/Exception/UrlRewritingException.php create mode 100644 core/lib/Thelia/Files/Exception/ProcessFileException.php create mode 100644 core/lib/Thelia/Files/FileConfiguration.php create mode 100644 core/lib/Thelia/Files/FileManager.php create mode 100644 core/lib/Thelia/Files/FileModelInterface.php create mode 100644 core/lib/Thelia/Files/FileModelParentInterface.php create mode 100644 core/lib/Thelia/Form/AddressCountryValidationTrait.php create mode 100644 core/lib/Thelia/Form/AddressCreateForm.php create mode 100644 core/lib/Thelia/Form/AddressUpdateForm.php create mode 100644 core/lib/Thelia/Form/AdminCreatePassword.php create mode 100644 core/lib/Thelia/Form/AdminLogin.php create mode 100644 core/lib/Thelia/Form/AdminLostPassword.php create mode 100644 core/lib/Thelia/Form/AdministratorCreationForm.php create mode 100644 core/lib/Thelia/Form/AdministratorModificationForm.php create mode 100644 core/lib/Thelia/Form/Api/ApiCreateForm.php create mode 100644 core/lib/Thelia/Form/Api/ApiEmptyForm.php create mode 100644 core/lib/Thelia/Form/Api/ApiUpdateForm.php create mode 100644 core/lib/Thelia/Form/Api/Category/CategoryCreationForm.php create mode 100644 core/lib/Thelia/Form/Api/Category/CategoryModificationForm.php create mode 100644 core/lib/Thelia/Form/Api/Customer/CustomerCreateForm.php create mode 100644 core/lib/Thelia/Form/Api/Customer/CustomerLogin.php create mode 100644 core/lib/Thelia/Form/Api/Customer/CustomerUpdateForm.php create mode 100644 core/lib/Thelia/Form/Api/Product/ProductCreationForm.php create mode 100644 core/lib/Thelia/Form/Api/Product/ProductModificationForm.php create mode 100644 core/lib/Thelia/Form/Api/ProductSaleElements/ProductSaleElementsForm.php create mode 100644 core/lib/Thelia/Form/Area/AreaCountryForm.php create mode 100644 core/lib/Thelia/Form/Area/AreaCreateForm.php create mode 100644 core/lib/Thelia/Form/Area/AreaDeleteCountryForm.php create mode 100644 core/lib/Thelia/Form/Area/AreaModificationForm.php create mode 100644 core/lib/Thelia/Form/Area/AreaPostageForm.php create mode 100644 core/lib/Thelia/Form/Area/CountryListValidationTrait.php create mode 100644 core/lib/Thelia/Form/AttributeAvCreationForm.php create mode 100644 core/lib/Thelia/Form/AttributeCreationForm.php create mode 100644 core/lib/Thelia/Form/AttributeModificationForm.php create mode 100644 core/lib/Thelia/Form/BaseForm.php create mode 100644 core/lib/Thelia/Form/Brand/BrandCreationForm.php create mode 100644 core/lib/Thelia/Form/Brand/BrandDocumentModification.php create mode 100644 core/lib/Thelia/Form/Brand/BrandImageModification.php create mode 100644 core/lib/Thelia/Form/Brand/BrandModificationForm.php create mode 100644 core/lib/Thelia/Form/BruteforceForm.php create mode 100644 core/lib/Thelia/Form/Cache/AssetsFlushForm.php create mode 100644 core/lib/Thelia/Form/Cache/CacheFlushForm.php create mode 100644 core/lib/Thelia/Form/Cache/ImagesAndDocumentsCacheFlushForm.php create mode 100644 core/lib/Thelia/Form/CartAdd.php create mode 100644 core/lib/Thelia/Form/CategoryCreationForm.php create mode 100644 core/lib/Thelia/Form/CategoryDocumentModification.php create mode 100644 core/lib/Thelia/Form/CategoryImageModification.php create mode 100644 core/lib/Thelia/Form/CategoryModificationForm.php create mode 100644 core/lib/Thelia/Form/ConfigCreationForm.php create mode 100644 core/lib/Thelia/Form/ConfigModificationForm.php create mode 100644 core/lib/Thelia/Form/ConfigStoreForm.php create mode 100644 core/lib/Thelia/Form/ContactForm.php create mode 100644 core/lib/Thelia/Form/ContentCreationForm.php create mode 100644 core/lib/Thelia/Form/ContentDocumentModification.php create mode 100644 core/lib/Thelia/Form/ContentImageModification.php create mode 100644 core/lib/Thelia/Form/ContentModificationForm.php create mode 100644 core/lib/Thelia/Form/CountryCreationForm.php create mode 100644 core/lib/Thelia/Form/CountryModificationForm.php create mode 100644 core/lib/Thelia/Form/CouponCode.php create mode 100644 core/lib/Thelia/Form/CouponCreationForm.php create mode 100644 core/lib/Thelia/Form/CurrencyCreationForm.php create mode 100644 core/lib/Thelia/Form/CurrencyModificationForm.php create mode 100644 core/lib/Thelia/Form/CustomerCreateForm.php create mode 100644 core/lib/Thelia/Form/CustomerLogin.php create mode 100644 core/lib/Thelia/Form/CustomerLostPasswordForm.php create mode 100644 core/lib/Thelia/Form/CustomerPasswordUpdateForm.php create mode 100644 core/lib/Thelia/Form/CustomerProfileUpdateForm.php create mode 100644 core/lib/Thelia/Form/CustomerUpdateForm.php create mode 100644 core/lib/Thelia/Form/Definition/AdminForm.php create mode 100644 core/lib/Thelia/Form/Definition/ApiForm.php create mode 100644 core/lib/Thelia/Form/Definition/FrontForm.php create mode 100644 core/lib/Thelia/Form/EmptyForm.php create mode 100644 core/lib/Thelia/Form/Exception/FormValidationException.php create mode 100644 core/lib/Thelia/Form/Exception/ProductNotFoundException.php create mode 100644 core/lib/Thelia/Form/Exception/StockNotFoundException.php create mode 100644 core/lib/Thelia/Form/ExportForm.php create mode 100644 core/lib/Thelia/Form/FeatureAvCreationForm.php create mode 100644 core/lib/Thelia/Form/FeatureCreationForm.php create mode 100644 core/lib/Thelia/Form/FeatureModificationForm.php create mode 100644 core/lib/Thelia/Form/FirewallForm.php create mode 100644 core/lib/Thelia/Form/FolderCreationForm.php create mode 100644 core/lib/Thelia/Form/FolderDocumentModification.php create mode 100644 core/lib/Thelia/Form/FolderImageModification.php create mode 100644 core/lib/Thelia/Form/FolderModificationForm.php create mode 100644 core/lib/Thelia/Form/HookCreationForm.php create mode 100644 core/lib/Thelia/Form/HookModificationForm.php create mode 100644 core/lib/Thelia/Form/Image/DocumentModification.php create mode 100644 core/lib/Thelia/Form/Image/ImageModification.php create mode 100644 core/lib/Thelia/Form/ImportForm.php create mode 100644 core/lib/Thelia/Form/InstallStep3Form.php create mode 100644 core/lib/Thelia/Form/Lang/LangCreateForm.php create mode 100644 core/lib/Thelia/Form/Lang/LangDefaultBehaviorForm.php create mode 100644 core/lib/Thelia/Form/Lang/LangUpdateForm.php create mode 100644 core/lib/Thelia/Form/Lang/LangUrlEvent.php create mode 100644 core/lib/Thelia/Form/Lang/LangUrlForm.php create mode 100644 core/lib/Thelia/Form/MailingSystemModificationForm.php create mode 100644 core/lib/Thelia/Form/MessageCreationForm.php create mode 100644 core/lib/Thelia/Form/MessageModificationForm.php create mode 100644 core/lib/Thelia/Form/MessageSendSampleForm.php create mode 100644 core/lib/Thelia/Form/ModuleHookCreationForm.php create mode 100644 core/lib/Thelia/Form/ModuleHookModificationForm.php create mode 100644 core/lib/Thelia/Form/ModuleImageModification.php create mode 100644 core/lib/Thelia/Form/ModuleInstallForm.php create mode 100644 core/lib/Thelia/Form/ModuleModificationForm.php create mode 100644 core/lib/Thelia/Form/NewsletterForm.php create mode 100644 core/lib/Thelia/Form/NewsletterUnsubscribeForm.php create mode 100644 core/lib/Thelia/Form/OrderDelivery.php create mode 100644 core/lib/Thelia/Form/OrderPayment.php create mode 100644 core/lib/Thelia/Form/OrderStatus/OrderStatusCreationForm.php create mode 100644 core/lib/Thelia/Form/OrderStatus/OrderStatusModificationForm.php create mode 100644 core/lib/Thelia/Form/OrderUpdateAddress.php create mode 100644 core/lib/Thelia/Form/ProductCloneForm.php create mode 100644 core/lib/Thelia/Form/ProductCombinationGenerationForm.php create mode 100644 core/lib/Thelia/Form/ProductCreationForm.php create mode 100644 core/lib/Thelia/Form/ProductDefaultSaleElementUpdateForm.php create mode 100644 core/lib/Thelia/Form/ProductDocumentModification.php create mode 100644 core/lib/Thelia/Form/ProductImageModification.php create mode 100644 core/lib/Thelia/Form/ProductModificationForm.php create mode 100644 core/lib/Thelia/Form/ProductSaleElementUpdateForm.php create mode 100644 core/lib/Thelia/Form/ProfileCreationForm.php create mode 100644 core/lib/Thelia/Form/ProfileModificationForm.php create mode 100644 core/lib/Thelia/Form/ProfileUpdateModuleAccessForm.php create mode 100644 core/lib/Thelia/Form/ProfileUpdateResourceAccessForm.php create mode 100644 core/lib/Thelia/Form/Sale/SaleCreationForm.php create mode 100644 core/lib/Thelia/Form/Sale/SaleModificationForm.php create mode 100644 core/lib/Thelia/Form/SeoFieldsTrait.php create mode 100644 core/lib/Thelia/Form/SeoForm.php create mode 100644 core/lib/Thelia/Form/ShippingZone/ShippingZoneAddArea.php create mode 100644 core/lib/Thelia/Form/ShippingZone/ShippingZoneRemoveArea.php create mode 100644 core/lib/Thelia/Form/StandardDescriptionFieldsTrait.php create mode 100644 core/lib/Thelia/Form/State/StateCreationForm.php create mode 100644 core/lib/Thelia/Form/State/StateModificationForm.php create mode 100644 core/lib/Thelia/Form/SystemLogConfigurationForm.php create mode 100644 core/lib/Thelia/Form/TaxCreationForm.php create mode 100644 core/lib/Thelia/Form/TaxModificationForm.php create mode 100644 core/lib/Thelia/Form/TaxRuleCreationForm.php create mode 100644 core/lib/Thelia/Form/TaxRuleModificationForm.php create mode 100644 core/lib/Thelia/Form/TaxRuleTaxListUpdateForm.php create mode 100644 core/lib/Thelia/Form/TemplateCreationForm.php create mode 100644 core/lib/Thelia/Form/TemplateModificationForm.php create mode 100644 core/lib/Thelia/Handler/ExportHandler.php create mode 100644 core/lib/Thelia/Handler/ImportHandler.php create mode 100644 core/lib/Thelia/ImportExport/AbstractHandler.php create mode 100644 core/lib/Thelia/ImportExport/Export/AbstractExport.php create mode 100644 core/lib/Thelia/ImportExport/Export/ArrayAbstractExport.php create mode 100644 core/lib/Thelia/ImportExport/Export/ExportHandler.php create mode 100644 core/lib/Thelia/ImportExport/Export/JsonFileAbstractExport.php create mode 100644 core/lib/Thelia/ImportExport/Export/PropelCollectionAbstractExport.php create mode 100644 core/lib/Thelia/ImportExport/Export/Type/ContentExport.php create mode 100644 core/lib/Thelia/ImportExport/Export/Type/CustomerExport.php create mode 100644 core/lib/Thelia/ImportExport/Export/Type/MailingExport.php create mode 100644 core/lib/Thelia/ImportExport/Export/Type/OrderExport.php create mode 100644 core/lib/Thelia/ImportExport/Export/Type/ProductI18nExport.php create mode 100644 core/lib/Thelia/ImportExport/Export/Type/ProductPricesExport.php create mode 100644 core/lib/Thelia/ImportExport/Export/Type/ProductSEOExport.php create mode 100644 core/lib/Thelia/ImportExport/Export/Type/ProductTaxedPricesExport.php create mode 100644 core/lib/Thelia/ImportExport/Import/AbstractImport.php create mode 100644 core/lib/Thelia/ImportExport/Import/ImportHandler.php create mode 100644 core/lib/Thelia/ImportExport/Import/Type/ProductPricesImport.php create mode 100644 core/lib/Thelia/ImportExport/Import/Type/ProductStockImport.php create mode 100644 core/lib/Thelia/Install/BaseInstall.php create mode 100644 core/lib/Thelia/Install/CheckDatabaseConnection.php create mode 100644 core/lib/Thelia/Install/CheckPermission.php create mode 100644 core/lib/Thelia/Install/Database.php create mode 100644 core/lib/Thelia/Install/Exception/AlreadyInstallException.php create mode 100644 core/lib/Thelia/Install/Exception/InstallException.php create mode 100644 core/lib/Thelia/Install/Exception/UpToDateException.php create mode 100644 core/lib/Thelia/Install/Exception/UpdateException.php create mode 100644 core/lib/Thelia/Install/Update.php create mode 100644 core/lib/Thelia/Log/AbstractTlogDestination.php create mode 100644 core/lib/Thelia/Log/Destination/TlogDestinationFile.php create mode 100644 core/lib/Thelia/Log/Destination/TlogDestinationHtml.php create mode 100644 core/lib/Thelia/Log/Destination/TlogDestinationJavascriptConsole.php create mode 100644 core/lib/Thelia/Log/Destination/TlogDestinationNull.php create mode 100644 core/lib/Thelia/Log/Destination/TlogDestinationPopup.php create mode 100644 core/lib/Thelia/Log/Destination/TlogDestinationPopup.tpl create mode 100644 core/lib/Thelia/Log/Destination/TlogDestinationRotatingFile.php create mode 100644 core/lib/Thelia/Log/Destination/TlogDestinationText.php create mode 100644 core/lib/Thelia/Log/Tlog.php create mode 100644 core/lib/Thelia/Log/TlogDestinationConfig.php create mode 100644 core/lib/Thelia/Mailer/MailerFactory.php create mode 100644 core/lib/Thelia/Model/Accessory.php create mode 100644 core/lib/Thelia/Model/AccessoryQuery.php create mode 100644 core/lib/Thelia/Model/Address.php create mode 100644 core/lib/Thelia/Model/AddressQuery.php create mode 100644 core/lib/Thelia/Model/Admin.php create mode 100644 core/lib/Thelia/Model/AdminLog.php create mode 100644 core/lib/Thelia/Model/AdminLogQuery.php create mode 100644 core/lib/Thelia/Model/AdminQuery.php create mode 100644 core/lib/Thelia/Model/Api.php create mode 100644 core/lib/Thelia/Model/ApiQuery.php create mode 100644 core/lib/Thelia/Model/Area.php create mode 100644 core/lib/Thelia/Model/AreaDeliveryModule.php create mode 100644 core/lib/Thelia/Model/AreaDeliveryModuleQuery.php create mode 100644 core/lib/Thelia/Model/AreaQuery.php create mode 100644 core/lib/Thelia/Model/Attribute.php create mode 100644 core/lib/Thelia/Model/AttributeAv.php create mode 100644 core/lib/Thelia/Model/AttributeAvI18n.php create mode 100644 core/lib/Thelia/Model/AttributeAvI18nQuery.php create mode 100644 core/lib/Thelia/Model/AttributeAvQuery.php create mode 100644 core/lib/Thelia/Model/AttributeCombination.php create mode 100644 core/lib/Thelia/Model/AttributeCombinationQuery.php create mode 100644 core/lib/Thelia/Model/AttributeI18n.php create mode 100644 core/lib/Thelia/Model/AttributeI18nQuery.php create mode 100644 core/lib/Thelia/Model/AttributeQuery.php create mode 100644 core/lib/Thelia/Model/AttributeTemplate.php create mode 100644 core/lib/Thelia/Model/AttributeTemplateQuery.php create mode 100644 core/lib/Thelia/Model/Brand.php create mode 100644 core/lib/Thelia/Model/BrandDocument.php create mode 100644 core/lib/Thelia/Model/BrandDocumentI18n.php create mode 100644 core/lib/Thelia/Model/BrandDocumentI18nQuery.php create mode 100644 core/lib/Thelia/Model/BrandDocumentQuery.php create mode 100644 core/lib/Thelia/Model/BrandI18n.php create mode 100644 core/lib/Thelia/Model/BrandI18nQuery.php create mode 100644 core/lib/Thelia/Model/BrandImage.php create mode 100644 core/lib/Thelia/Model/BrandImageI18n.php create mode 100644 core/lib/Thelia/Model/BrandImageI18nQuery.php create mode 100644 core/lib/Thelia/Model/BrandImageQuery.php create mode 100644 core/lib/Thelia/Model/BrandQuery.php create mode 100644 core/lib/Thelia/Model/Breadcrumb/BrandBreadcrumbTrait.php create mode 100644 core/lib/Thelia/Model/Breadcrumb/BreadcrumbInterface.php create mode 100644 core/lib/Thelia/Model/Breadcrumb/CatalogBreadcrumbTrait.php create mode 100644 core/lib/Thelia/Model/Breadcrumb/FolderBreadcrumbTrait.php create mode 100644 core/lib/Thelia/Model/Cart.php create mode 100644 core/lib/Thelia/Model/CartItem.php create mode 100644 core/lib/Thelia/Model/CartItemQuery.php create mode 100644 core/lib/Thelia/Model/CartQuery.php create mode 100644 core/lib/Thelia/Model/Category.php create mode 100644 core/lib/Thelia/Model/CategoryAssociatedContent.php create mode 100644 core/lib/Thelia/Model/CategoryAssociatedContentQuery.php create mode 100644 core/lib/Thelia/Model/CategoryDocument.php create mode 100644 core/lib/Thelia/Model/CategoryDocumentI18n.php create mode 100644 core/lib/Thelia/Model/CategoryDocumentI18nQuery.php create mode 100644 core/lib/Thelia/Model/CategoryDocumentQuery.php create mode 100644 core/lib/Thelia/Model/CategoryI18n.php create mode 100644 core/lib/Thelia/Model/CategoryI18nQuery.php create mode 100644 core/lib/Thelia/Model/CategoryImage.php create mode 100644 core/lib/Thelia/Model/CategoryImageI18n.php create mode 100644 core/lib/Thelia/Model/CategoryImageI18nQuery.php create mode 100644 core/lib/Thelia/Model/CategoryImageQuery.php create mode 100644 core/lib/Thelia/Model/CategoryQuery.php create mode 100644 core/lib/Thelia/Model/CategoryVersion.php create mode 100644 core/lib/Thelia/Model/CategoryVersionQuery.php create mode 100644 core/lib/Thelia/Model/Config.php create mode 100644 core/lib/Thelia/Model/ConfigI18n.php create mode 100644 core/lib/Thelia/Model/ConfigI18nQuery.php create mode 100644 core/lib/Thelia/Model/ConfigQuery.php create mode 100644 core/lib/Thelia/Model/Content.php create mode 100644 core/lib/Thelia/Model/ContentDocument.php create mode 100644 core/lib/Thelia/Model/ContentDocumentI18n.php create mode 100644 core/lib/Thelia/Model/ContentDocumentI18nQuery.php create mode 100644 core/lib/Thelia/Model/ContentDocumentQuery.php create mode 100644 core/lib/Thelia/Model/ContentFolder.php create mode 100644 core/lib/Thelia/Model/ContentFolderQuery.php create mode 100644 core/lib/Thelia/Model/ContentI18n.php create mode 100644 core/lib/Thelia/Model/ContentI18nQuery.php create mode 100644 core/lib/Thelia/Model/ContentImage.php create mode 100644 core/lib/Thelia/Model/ContentImageI18n.php create mode 100644 core/lib/Thelia/Model/ContentImageI18nQuery.php create mode 100644 core/lib/Thelia/Model/ContentImageQuery.php create mode 100644 core/lib/Thelia/Model/ContentQuery.php create mode 100644 core/lib/Thelia/Model/ContentVersion.php create mode 100644 core/lib/Thelia/Model/ContentVersionQuery.php create mode 100644 core/lib/Thelia/Model/Country.php create mode 100644 core/lib/Thelia/Model/CountryArea.php create mode 100644 core/lib/Thelia/Model/CountryAreaQuery.php create mode 100644 core/lib/Thelia/Model/CountryI18n.php create mode 100644 core/lib/Thelia/Model/CountryI18nQuery.php create mode 100644 core/lib/Thelia/Model/CountryQuery.php create mode 100644 core/lib/Thelia/Model/Coupon.php create mode 100644 core/lib/Thelia/Model/CouponCountry.php create mode 100644 core/lib/Thelia/Model/CouponCountryQuery.php create mode 100644 core/lib/Thelia/Model/CouponCustomerCount.php create mode 100644 core/lib/Thelia/Model/CouponCustomerCountQuery.php create mode 100644 core/lib/Thelia/Model/CouponI18n.php create mode 100644 core/lib/Thelia/Model/CouponI18nQuery.php create mode 100644 core/lib/Thelia/Model/CouponModule.php create mode 100644 core/lib/Thelia/Model/CouponModuleQuery.php create mode 100644 core/lib/Thelia/Model/CouponQuery.php create mode 100644 core/lib/Thelia/Model/CouponVersion.php create mode 100644 core/lib/Thelia/Model/CouponVersionQuery.php create mode 100644 core/lib/Thelia/Model/Currency.php create mode 100644 core/lib/Thelia/Model/CurrencyI18n.php create mode 100644 core/lib/Thelia/Model/CurrencyI18nQuery.php create mode 100644 core/lib/Thelia/Model/CurrencyQuery.php create mode 100644 core/lib/Thelia/Model/Customer.php create mode 100644 core/lib/Thelia/Model/CustomerQuery.php create mode 100644 core/lib/Thelia/Model/CustomerTitle.php create mode 100644 core/lib/Thelia/Model/CustomerTitleI18n.php create mode 100644 core/lib/Thelia/Model/CustomerTitleI18nQuery.php create mode 100644 core/lib/Thelia/Model/CustomerTitleQuery.php create mode 100644 core/lib/Thelia/Model/CustomerVersion.php create mode 100644 core/lib/Thelia/Model/CustomerVersionQuery.php create mode 100644 core/lib/Thelia/Model/Exception/InvalidArgumentException.php create mode 100644 core/lib/Thelia/Model/Exception/ModelException.php create mode 100644 core/lib/Thelia/Model/Export.php create mode 100644 core/lib/Thelia/Model/ExportCategory.php create mode 100644 core/lib/Thelia/Model/ExportCategoryI18n.php create mode 100644 core/lib/Thelia/Model/ExportCategoryI18nQuery.php create mode 100644 core/lib/Thelia/Model/ExportCategoryQuery.php create mode 100644 core/lib/Thelia/Model/ExportI18n.php create mode 100644 core/lib/Thelia/Model/ExportI18nQuery.php create mode 100644 core/lib/Thelia/Model/ExportQuery.php create mode 100644 core/lib/Thelia/Model/Feature.php create mode 100644 core/lib/Thelia/Model/FeatureAv.php create mode 100644 core/lib/Thelia/Model/FeatureAvI18n.php create mode 100644 core/lib/Thelia/Model/FeatureAvI18nQuery.php create mode 100644 core/lib/Thelia/Model/FeatureAvQuery.php create mode 100644 core/lib/Thelia/Model/FeatureI18n.php create mode 100644 core/lib/Thelia/Model/FeatureI18nQuery.php create mode 100644 core/lib/Thelia/Model/FeatureProduct.php create mode 100644 core/lib/Thelia/Model/FeatureProductQuery.php create mode 100644 core/lib/Thelia/Model/FeatureQuery.php create mode 100644 core/lib/Thelia/Model/FeatureTemplate.php create mode 100644 core/lib/Thelia/Model/FeatureTemplateQuery.php create mode 100644 core/lib/Thelia/Model/Folder.php create mode 100644 core/lib/Thelia/Model/FolderDocument.php create mode 100644 core/lib/Thelia/Model/FolderDocumentI18n.php create mode 100644 core/lib/Thelia/Model/FolderDocumentI18nQuery.php create mode 100644 core/lib/Thelia/Model/FolderDocumentQuery.php create mode 100644 core/lib/Thelia/Model/FolderI18n.php create mode 100644 core/lib/Thelia/Model/FolderI18nQuery.php create mode 100644 core/lib/Thelia/Model/FolderImage.php create mode 100644 core/lib/Thelia/Model/FolderImageI18n.php create mode 100644 core/lib/Thelia/Model/FolderImageI18nQuery.php create mode 100644 core/lib/Thelia/Model/FolderImageQuery.php create mode 100644 core/lib/Thelia/Model/FolderQuery.php create mode 100644 core/lib/Thelia/Model/FolderVersion.php create mode 100644 core/lib/Thelia/Model/FolderVersionQuery.php create mode 100644 core/lib/Thelia/Model/FormFirewall.php create mode 100644 core/lib/Thelia/Model/FormFirewallQuery.php create mode 100644 core/lib/Thelia/Model/Hook.php create mode 100644 core/lib/Thelia/Model/HookI18n.php create mode 100644 core/lib/Thelia/Model/HookI18nQuery.php create mode 100644 core/lib/Thelia/Model/HookQuery.php create mode 100644 core/lib/Thelia/Model/IgnoredModuleHook.php create mode 100644 core/lib/Thelia/Model/IgnoredModuleHookQuery.php create mode 100644 core/lib/Thelia/Model/Import.php create mode 100644 core/lib/Thelia/Model/ImportCategory.php create mode 100644 core/lib/Thelia/Model/ImportCategoryI18n.php create mode 100644 core/lib/Thelia/Model/ImportCategoryI18nQuery.php create mode 100644 core/lib/Thelia/Model/ImportCategoryQuery.php create mode 100644 core/lib/Thelia/Model/ImportI18n.php create mode 100644 core/lib/Thelia/Model/ImportI18nQuery.php create mode 100644 core/lib/Thelia/Model/ImportQuery.php create mode 100644 core/lib/Thelia/Model/Lang.php create mode 100644 core/lib/Thelia/Model/LangQuery.php create mode 100644 core/lib/Thelia/Model/Message.php create mode 100644 core/lib/Thelia/Model/MessageI18n.php create mode 100644 core/lib/Thelia/Model/MessageI18nQuery.php create mode 100644 core/lib/Thelia/Model/MessageQuery.php create mode 100644 core/lib/Thelia/Model/MessageVersion.php create mode 100644 core/lib/Thelia/Model/MessageVersionQuery.php create mode 100644 core/lib/Thelia/Model/MetaData.php create mode 100644 core/lib/Thelia/Model/MetaDataQuery.php create mode 100644 core/lib/Thelia/Model/Module.php create mode 100644 core/lib/Thelia/Model/ModuleConfig.php create mode 100644 core/lib/Thelia/Model/ModuleConfigI18n.php create mode 100644 core/lib/Thelia/Model/ModuleConfigI18nQuery.php create mode 100644 core/lib/Thelia/Model/ModuleConfigQuery.php create mode 100644 core/lib/Thelia/Model/ModuleHook.php create mode 100644 core/lib/Thelia/Model/ModuleHookQuery.php create mode 100644 core/lib/Thelia/Model/ModuleI18n.php create mode 100644 core/lib/Thelia/Model/ModuleI18nQuery.php create mode 100644 core/lib/Thelia/Model/ModuleImage.php create mode 100644 core/lib/Thelia/Model/ModuleImageI18n.php create mode 100644 core/lib/Thelia/Model/ModuleImageI18nQuery.php create mode 100644 core/lib/Thelia/Model/ModuleImageQuery.php create mode 100644 core/lib/Thelia/Model/ModuleQuery.php create mode 100644 core/lib/Thelia/Model/Newsletter.php create mode 100644 core/lib/Thelia/Model/NewsletterQuery.php create mode 100644 core/lib/Thelia/Model/Order.php create mode 100644 core/lib/Thelia/Model/OrderAddress.php create mode 100644 core/lib/Thelia/Model/OrderAddressQuery.php create mode 100644 core/lib/Thelia/Model/OrderCoupon.php create mode 100644 core/lib/Thelia/Model/OrderCouponCountry.php create mode 100644 core/lib/Thelia/Model/OrderCouponCountryQuery.php create mode 100644 core/lib/Thelia/Model/OrderCouponModule.php create mode 100644 core/lib/Thelia/Model/OrderCouponModuleQuery.php create mode 100644 core/lib/Thelia/Model/OrderCouponQuery.php create mode 100644 core/lib/Thelia/Model/OrderPostage.php create mode 100644 core/lib/Thelia/Model/OrderProduct.php create mode 100644 core/lib/Thelia/Model/OrderProductAttributeCombination.php create mode 100644 core/lib/Thelia/Model/OrderProductAttributeCombinationQuery.php create mode 100644 core/lib/Thelia/Model/OrderProductQuery.php create mode 100644 core/lib/Thelia/Model/OrderProductTax.php create mode 100644 core/lib/Thelia/Model/OrderProductTaxQuery.php create mode 100644 core/lib/Thelia/Model/OrderQuery.php create mode 100644 core/lib/Thelia/Model/OrderStatus.php create mode 100644 core/lib/Thelia/Model/OrderStatusI18n.php create mode 100644 core/lib/Thelia/Model/OrderStatusI18nQuery.php create mode 100644 core/lib/Thelia/Model/OrderStatusQuery.php create mode 100644 core/lib/Thelia/Model/OrderVersion.php create mode 100644 core/lib/Thelia/Model/OrderVersionQuery.php create mode 100644 core/lib/Thelia/Model/PickupLocation.php create mode 100644 core/lib/Thelia/Model/PickupLocationAddress.php create mode 100644 core/lib/Thelia/Model/Product.php create mode 100644 core/lib/Thelia/Model/ProductAssociatedContent.php create mode 100644 core/lib/Thelia/Model/ProductAssociatedContentQuery.php create mode 100644 core/lib/Thelia/Model/ProductCategory.php create mode 100644 core/lib/Thelia/Model/ProductCategoryQuery.php create mode 100644 core/lib/Thelia/Model/ProductDocument.php create mode 100644 core/lib/Thelia/Model/ProductDocumentI18n.php create mode 100644 core/lib/Thelia/Model/ProductDocumentI18nQuery.php create mode 100644 core/lib/Thelia/Model/ProductDocumentQuery.php create mode 100644 core/lib/Thelia/Model/ProductI18n.php create mode 100644 core/lib/Thelia/Model/ProductI18nQuery.php create mode 100644 core/lib/Thelia/Model/ProductImage.php create mode 100644 core/lib/Thelia/Model/ProductImageI18n.php create mode 100644 core/lib/Thelia/Model/ProductImageI18nQuery.php create mode 100644 core/lib/Thelia/Model/ProductImageQuery.php create mode 100644 core/lib/Thelia/Model/ProductPrice.php create mode 100644 core/lib/Thelia/Model/ProductPriceQuery.php create mode 100644 core/lib/Thelia/Model/ProductQuery.php create mode 100644 core/lib/Thelia/Model/ProductSaleElements.php create mode 100644 core/lib/Thelia/Model/ProductSaleElementsProductDocument.php create mode 100644 core/lib/Thelia/Model/ProductSaleElementsProductDocumentQuery.php create mode 100644 core/lib/Thelia/Model/ProductSaleElementsProductImage.php create mode 100644 core/lib/Thelia/Model/ProductSaleElementsProductImageQuery.php create mode 100644 core/lib/Thelia/Model/ProductSaleElementsQuery.php create mode 100644 core/lib/Thelia/Model/ProductVersion.php create mode 100644 core/lib/Thelia/Model/ProductVersionQuery.php create mode 100644 core/lib/Thelia/Model/Profile.php create mode 100644 core/lib/Thelia/Model/ProfileI18n.php create mode 100644 core/lib/Thelia/Model/ProfileI18nQuery.php create mode 100644 core/lib/Thelia/Model/ProfileModule.php create mode 100644 core/lib/Thelia/Model/ProfileModuleQuery.php create mode 100644 core/lib/Thelia/Model/ProfileQuery.php create mode 100644 core/lib/Thelia/Model/ProfileResource.php create mode 100644 core/lib/Thelia/Model/ProfileResourceQuery.php create mode 100644 core/lib/Thelia/Model/Resource.php create mode 100644 core/lib/Thelia/Model/ResourceI18n.php create mode 100644 core/lib/Thelia/Model/ResourceI18nQuery.php create mode 100644 core/lib/Thelia/Model/ResourceQuery.php create mode 100644 core/lib/Thelia/Model/RewritingArgument.php create mode 100644 core/lib/Thelia/Model/RewritingArgumentQuery.php create mode 100644 core/lib/Thelia/Model/RewritingUrl.php create mode 100644 core/lib/Thelia/Model/RewritingUrlQuery.php create mode 100644 core/lib/Thelia/Model/Sale.php create mode 100644 core/lib/Thelia/Model/SaleI18n.php create mode 100644 core/lib/Thelia/Model/SaleI18nQuery.php create mode 100644 core/lib/Thelia/Model/SaleOffsetCurrency.php create mode 100644 core/lib/Thelia/Model/SaleOffsetCurrencyQuery.php create mode 100644 core/lib/Thelia/Model/SaleProduct.php create mode 100644 core/lib/Thelia/Model/SaleProductQuery.php create mode 100644 core/lib/Thelia/Model/SaleQuery.php create mode 100644 core/lib/Thelia/Model/State.php create mode 100644 core/lib/Thelia/Model/StateI18n.php create mode 100644 core/lib/Thelia/Model/StateI18nQuery.php create mode 100644 core/lib/Thelia/Model/StateQuery.php create mode 100644 core/lib/Thelia/Model/Tax.php create mode 100644 core/lib/Thelia/Model/TaxI18n.php create mode 100644 core/lib/Thelia/Model/TaxI18nQuery.php create mode 100644 core/lib/Thelia/Model/TaxQuery.php create mode 100644 core/lib/Thelia/Model/TaxRule.php create mode 100644 core/lib/Thelia/Model/TaxRuleCountry.php create mode 100644 core/lib/Thelia/Model/TaxRuleCountryQuery.php create mode 100644 core/lib/Thelia/Model/TaxRuleI18n.php create mode 100644 core/lib/Thelia/Model/TaxRuleI18nQuery.php create mode 100644 core/lib/Thelia/Model/TaxRuleQuery.php create mode 100644 core/lib/Thelia/Model/Template.php create mode 100644 core/lib/Thelia/Model/TemplateI18n.php create mode 100644 core/lib/Thelia/Model/TemplateI18nQuery.php create mode 100644 core/lib/Thelia/Model/TemplateQuery.php create mode 100644 core/lib/Thelia/Model/Tools/I18nTimestampableTrait.php create mode 100644 core/lib/Thelia/Model/Tools/ModelCriteriaTools.php create mode 100644 core/lib/Thelia/Model/Tools/ModelEventDispatcherTrait.php create mode 100644 core/lib/Thelia/Model/Tools/PositionManagementTrait.php create mode 100644 core/lib/Thelia/Model/Tools/ProductPriceTools.php create mode 100644 core/lib/Thelia/Model/Tools/UrlRewritingTrait.php create mode 100644 core/lib/Thelia/Module/AbstractAdminResourcesCompiler.php create mode 100644 core/lib/Thelia/Module/AbstractDeliveryModule.php create mode 100644 core/lib/Thelia/Module/AbstractDeliveryModuleWithState.php create mode 100644 core/lib/Thelia/Module/AbstractPaymentModule.php create mode 100644 core/lib/Thelia/Module/BaseModule.php create mode 100644 core/lib/Thelia/Module/BaseModuleInterface.php create mode 100644 core/lib/Thelia/Module/BasePaymentModuleController.php create mode 100644 core/lib/Thelia/Module/DeliveryModuleInterface.php create mode 100644 core/lib/Thelia/Module/DeliveryModuleWithStateInterface.php create mode 100644 core/lib/Thelia/Module/Exception/DeliveryException.php create mode 100644 core/lib/Thelia/Module/Exception/InvalidXmlDocumentException.php create mode 100644 core/lib/Thelia/Module/ModuleDescriptorValidator.php create mode 100644 core/lib/Thelia/Module/ModuleManagement.php create mode 100644 core/lib/Thelia/Module/PaymentModuleInterface.php create mode 100644 core/lib/Thelia/Module/Validator/ModuleDefinition.php create mode 100644 core/lib/Thelia/Module/Validator/ModuleValidator.php create mode 100644 core/lib/Thelia/Module/schema/module/module-2_1.xsd create mode 100644 core/lib/Thelia/Module/schema/module/module-2_2.xsd create mode 100644 core/lib/Thelia/Module/schema/module/module.xsd create mode 100644 core/lib/Thelia/Rewriting/RewritingResolver.php create mode 100644 core/lib/Thelia/Rewriting/RewritingRetriever.php create mode 100644 core/lib/Thelia/TaxEngine/BaseTaxType.php create mode 100644 core/lib/Thelia/TaxEngine/Calculator.php create mode 100644 core/lib/Thelia/TaxEngine/OrderProductTaxCollection.php create mode 100644 core/lib/Thelia/TaxEngine/TaxEngine.php create mode 100644 core/lib/Thelia/TaxEngine/TaxType/FeatureFixAmountTaxType.php create mode 100644 core/lib/Thelia/TaxEngine/TaxType/FixAmountTaxType.php create mode 100644 core/lib/Thelia/TaxEngine/TaxType/PricePercentTaxType.php create mode 100644 core/lib/Thelia/TaxEngine/TaxTypeRequirementDefinition.php create mode 100644 core/lib/Thelia/Tools/AddressFormat.php create mode 100644 core/lib/Thelia/Tools/DateTimeFormat.php create mode 100644 core/lib/Thelia/Tools/FileDownload/FileDownloader.php create mode 100644 core/lib/Thelia/Tools/FileDownload/FileDownloaderAwareTrait.php create mode 100644 core/lib/Thelia/Tools/FileDownload/FileDownloaderInterface.php create mode 100644 core/lib/Thelia/Tools/I18n.php create mode 100644 core/lib/Thelia/Tools/Image.php create mode 100644 core/lib/Thelia/Tools/MoneyFormat.php create mode 100644 core/lib/Thelia/Tools/NumberFormat.php create mode 100644 core/lib/Thelia/Tools/Password.php create mode 100644 core/lib/Thelia/Tools/RememberMeTrait.php create mode 100644 core/lib/Thelia/Tools/Rest/ResponseRest.php create mode 100644 core/lib/Thelia/Tools/TokenProvider.php create mode 100644 core/lib/Thelia/Tools/URL.php create mode 100644 core/lib/Thelia/Tools/Version/Constraints/BaseConstraint.php create mode 100644 core/lib/Thelia/Tools/Version/Constraints/ConstraintEqual.php create mode 100644 core/lib/Thelia/Tools/Version/Constraints/ConstraintGreater.php create mode 100644 core/lib/Thelia/Tools/Version/Constraints/ConstraintInterface.php create mode 100644 core/lib/Thelia/Tools/Version/Constraints/ConstraintLower.php create mode 100644 core/lib/Thelia/Tools/Version/Constraints/ConstraintNearlyEqual.php create mode 100644 core/lib/Thelia/Tools/Version/Version.php create mode 100644 core/lib/Thelia/Type/AlphaNumStringListType.php create mode 100644 core/lib/Thelia/Type/AlphaNumStringType.php create mode 100644 core/lib/Thelia/Type/AnyListType.php create mode 100644 core/lib/Thelia/Type/AnyType.php create mode 100644 core/lib/Thelia/Type/BaseType.php create mode 100644 core/lib/Thelia/Type/BooleanOrBothType.php create mode 100644 core/lib/Thelia/Type/BooleanType.php create mode 100644 core/lib/Thelia/Type/EnumListType.php create mode 100644 core/lib/Thelia/Type/EnumType.php create mode 100644 core/lib/Thelia/Type/FloatToFloatArrayType.php create mode 100644 core/lib/Thelia/Type/FloatType.php create mode 100644 core/lib/Thelia/Type/IntListType.php create mode 100644 core/lib/Thelia/Type/IntToCombinedIntsListType.php create mode 100644 core/lib/Thelia/Type/IntToCombinedStringsListType.php create mode 100644 core/lib/Thelia/Type/IntType.php create mode 100644 core/lib/Thelia/Type/JsonType.php create mode 100644 core/lib/Thelia/Type/ModelType.php create mode 100644 core/lib/Thelia/Type/ModelValidIdType.php create mode 100644 core/lib/Thelia/Type/TypeCollection.php create mode 100644 core/lib/Thelia/Type/TypeInterface.php create mode 100644 core/local/modules/HookTest/Config/config.xml create mode 100644 core/local/modules/HookTest/Config/module.xml create mode 100644 core/local/modules/HookTest/Hook/FrontHook.php create mode 100644 core/local/modules/HookTest/HookTest.php create mode 100644 core/local/modules/HookTest/I18n/en_US.php create mode 100644 core/local/modules/HookTest/I18n/fr_FR.php create mode 100644 core/local/modules/HookTest/I18n/frontOffice/default/en_US.php create mode 100644 core/local/modules/HookTest/I18n/frontOffice/default/fr_FR.php create mode 100644 core/local/modules/HookTest/composer.json create mode 100644 core/local/modules/HookTest/templates/frontOffice/default/assets/css/print.css create mode 100644 core/local/modules/HookTest/templates/frontOffice/default/assets/css/style1.css create mode 100644 core/local/modules/HookTest/templates/frontOffice/default/assets/css/style2.css create mode 100644 core/local/modules/HookTest/templates/frontOffice/default/assets/css/style3.css create mode 100644 core/local/modules/HookTest/templates/frontOffice/default/assets/css/styles.css create mode 100644 core/local/modules/HookTest/templates/frontOffice/default/assets/js/script.js create mode 100644 core/local/modules/HookTest/templates/frontOffice/default/dump.txt create mode 100644 core/local/modules/HookTest/templates/frontOffice/default/main-navbar-secondary.html create mode 100644 core/local/modules/HookTest/templates/frontOffice/default/override-assets.html create mode 100644 core/local/modules/HookTest/templates/frontOffice/default/override1.html create mode 100644 core/local/modules/HookTest/templates/frontOffice/default/override2.html create mode 100644 core/local/modules/HookTest/templates/frontOffice/default/override3.html create mode 100644 core/local/modules/HookTest/templates/frontOffice/default/render.html create mode 100644 core/local/modules/HookTest/templates/frontOffice/hooktest/assets/css/style2.css create mode 100644 core/local/modules/HookTest/templates/frontOffice/hooktest/override2.html create mode 100644 core/templates/frontOffice/hooktest/composer.json create mode 100644 core/templates/frontOffice/hooktest/includes/single-product.html create mode 100644 core/templates/frontOffice/hooktest/index.html create mode 100644 core/templates/frontOffice/hooktest/layout.tpl create mode 100644 core/templates/frontOffice/hooktest/modules/HookTest/assets/css/style3.css create mode 100644 core/templates/frontOffice/hooktest/modules/HookTest/override3.html create mode 100644 docker-compose.yml create mode 100644 index.html create mode 100644 local/.gitkeep create mode 100644 local/I18n/.gitkeep create mode 100644 local/backup/.gitkeep create mode 100644 local/config/.gitkeep create mode 100644 local/config/.htaccess create mode 100644 local/config/Readme.md create mode 100644 local/config/composer.json create mode 100644 local/config/database.yml.sample create mode 100644 local/config/schema.xml create mode 100644 local/media/.gitkeep create mode 100644 local/modules/Carousel/CHANGELOG.md create mode 100644 local/modules/Carousel/Carousel.php create mode 100644 local/modules/Carousel/Config/config.xml create mode 100644 local/modules/Carousel/Config/module.xml create mode 100644 local/modules/Carousel/Config/routing.xml create mode 100644 local/modules/Carousel/Config/schema.xml create mode 100644 local/modules/Carousel/Config/sql/destroy.sql create mode 100644 local/modules/Carousel/Config/thelia.sql create mode 100644 local/modules/Carousel/Config/update/2.4.0.sql create mode 100644 local/modules/Carousel/Controller/ConfigurationController.php create mode 100644 local/modules/Carousel/Form/CarouselImageForm.php create mode 100644 local/modules/Carousel/Form/CarouselUpdateForm.php create mode 100644 local/modules/Carousel/Hook/BackHook.php create mode 100644 local/modules/Carousel/I18n/backOffice/default/de_DE.php create mode 100644 local/modules/Carousel/I18n/backOffice/default/en_US.php create mode 100644 local/modules/Carousel/I18n/backOffice/default/fr_FR.php create mode 100644 local/modules/Carousel/I18n/backOffice/default/ru_RU.php create mode 100644 local/modules/Carousel/I18n/backOffice/default/tr_TR.php create mode 100644 local/modules/Carousel/I18n/de_DE.php create mode 100644 local/modules/Carousel/I18n/en_US.php create mode 100644 local/modules/Carousel/I18n/fr_FR.php create mode 100644 local/modules/Carousel/I18n/it_IT.php create mode 100644 local/modules/Carousel/I18n/ru_RU.php create mode 100644 local/modules/Carousel/I18n/tr_TR.php create mode 100644 local/modules/Carousel/Loop/CarouselLoop.php create mode 100644 local/modules/Carousel/Model/Carousel.php create mode 100644 local/modules/Carousel/Model/CarouselI18n.php create mode 100644 local/modules/Carousel/Model/CarouselI18nQuery.php create mode 100644 local/modules/Carousel/Model/CarouselQuery.php create mode 100644 local/modules/Carousel/Readme.md create mode 100644 local/modules/Carousel/composer.json create mode 100644 local/modules/Carousel/templates/backOffice/default/assets/js/module-configuration.js create mode 100644 local/modules/Carousel/templates/backOffice/default/module_configuration.html create mode 100644 local/modules/Carousel/templates/frontOffice/default/carousel.html create mode 100644 local/modules/Cheque/Cheque.php create mode 100644 local/modules/Cheque/Config/config.xml create mode 100644 local/modules/Cheque/Config/module.xml create mode 100644 local/modules/Cheque/Config/routing.xml create mode 100644 local/modules/Cheque/Config/setup.sql create mode 100644 local/modules/Cheque/Controller/ConfigureController.php create mode 100644 local/modules/Cheque/Form/ConfigurationForm.php create mode 100644 local/modules/Cheque/Hook/HookManager.php create mode 100644 local/modules/Cheque/I18n/backOffice/default/de_DE.php create mode 100644 local/modules/Cheque/I18n/backOffice/default/en_US.php create mode 100644 local/modules/Cheque/I18n/backOffice/default/fr_FR.php create mode 100644 local/modules/Cheque/I18n/backOffice/default/ru_RU.php create mode 100644 local/modules/Cheque/I18n/backOffice/default/tr_TR.php create mode 100644 local/modules/Cheque/I18n/de_DE.php create mode 100644 local/modules/Cheque/I18n/en_US.php create mode 100644 local/modules/Cheque/I18n/fr_FR.php create mode 100644 local/modules/Cheque/I18n/frontOffice/default/de_DE.php create mode 100644 local/modules/Cheque/I18n/frontOffice/default/en_US.php create mode 100644 local/modules/Cheque/I18n/frontOffice/default/fr_FR.php create mode 100644 local/modules/Cheque/I18n/frontOffice/default/ru_RU.php create mode 100644 local/modules/Cheque/I18n/frontOffice/default/tr_TR.php create mode 100644 local/modules/Cheque/I18n/ru_RU.php create mode 100644 local/modules/Cheque/I18n/tr_TR.php create mode 100644 local/modules/Cheque/LICENSE.txt create mode 100644 local/modules/Cheque/Listener/SendPaymentConfirmationEmail.php create mode 100644 local/modules/Cheque/composer.json create mode 100644 local/modules/Cheque/images/cheque.png create mode 100644 local/modules/Cheque/templates/backOffice/default/module_configuration.html create mode 100644 local/modules/Cheque/templates/frontOffice/default/order-placed.additional-payment-info.html create mode 100755 local/modules/Colissimo/Colissimo.php create mode 100755 local/modules/Colissimo/Config/config.xml create mode 100755 local/modules/Colissimo/Config/module.xml create mode 100755 local/modules/Colissimo/Config/prices.json create mode 100755 local/modules/Colissimo/Config/routing.xml create mode 100644 local/modules/Colissimo/Config/thelia.sql create mode 100755 local/modules/Colissimo/Controller/Configuration.php create mode 100755 local/modules/Colissimo/Controller/EditPrices.php create mode 100644 local/modules/Colissimo/Controller/Export.php create mode 100644 local/modules/Colissimo/Controller/FreeShipping.php create mode 100644 local/modules/Colissimo/EventListener/AreaDeletedListener.php create mode 100644 local/modules/Colissimo/Form/Configuration.php create mode 100644 local/modules/Colissimo/Form/Export.php create mode 100644 local/modules/Colissimo/Form/FreeShipping.php create mode 100644 local/modules/Colissimo/Hook/HookManager.php create mode 100644 local/modules/Colissimo/I18n/backOffice/default/de_DE.php create mode 100644 local/modules/Colissimo/I18n/backOffice/default/en_US.php create mode 100644 local/modules/Colissimo/I18n/backOffice/default/fr_FR.php create mode 100644 local/modules/Colissimo/I18n/backOffice/default/it_IT.php create mode 100644 local/modules/Colissimo/I18n/backOffice/default/ru_RU.php create mode 100644 local/modules/Colissimo/I18n/backOffice/default/tr_TR.php create mode 100644 local/modules/Colissimo/I18n/de_DE.php create mode 100644 local/modules/Colissimo/I18n/en_US.php create mode 100644 local/modules/Colissimo/I18n/fr_FR.php create mode 100644 local/modules/Colissimo/I18n/ru_RU.php create mode 100644 local/modules/Colissimo/I18n/tr_TR.php create mode 100644 local/modules/Colissimo/LICENSE.txt create mode 100755 local/modules/Colissimo/Listener/SendMail.php create mode 100755 local/modules/Colissimo/Loop/CheckRightsLoop.php create mode 100644 local/modules/Colissimo/Loop/NotSendLoop.php create mode 100755 local/modules/Colissimo/Loop/Price.php create mode 100644 local/modules/Colissimo/Model/ColissimoQuery.php create mode 100644 local/modules/Colissimo/Model/Config/Base/ColissimoConfigValue.php create mode 100644 local/modules/Colissimo/Model/Config/ColissimoConfigValue.php create mode 100644 local/modules/Colissimo/THELIA_INET.FMT create mode 100644 local/modules/Colissimo/composer.json create mode 100755 local/modules/Colissimo/documentation/TarifsAvril2013.pdf create mode 100755 local/modules/Colissimo/documentation/readme.txt create mode 100644 local/modules/Colissimo/templates/backOffice/default/assets/js/module-configuration-js.html create mode 100755 local/modules/Colissimo/templates/backOffice/default/module_configuration.html create mode 100644 local/modules/FreeOrder/Config/config.xml create mode 100644 local/modules/FreeOrder/Config/module.xml create mode 100644 local/modules/FreeOrder/FreeOrder.php create mode 100644 local/modules/FreeOrder/LICENSE.txt create mode 100644 local/modules/FreeOrder/Readme.md create mode 100644 local/modules/FreeOrder/composer.json create mode 100644 local/modules/Front/Config/config.xml create mode 100644 local/modules/Front/Config/front.xml create mode 100644 local/modules/Front/Config/module.xml create mode 100644 local/modules/Front/Controller/AddressController.php create mode 100644 local/modules/Front/Controller/CartController.php create mode 100644 local/modules/Front/Controller/ContactController.php create mode 100644 local/modules/Front/Controller/CouponController.php create mode 100644 local/modules/Front/Controller/CustomerController.php create mode 100644 local/modules/Front/Controller/FeedController.php create mode 100644 local/modules/Front/Controller/NewsletterController.php create mode 100644 local/modules/Front/Controller/OrderController.php create mode 100644 local/modules/Front/Controller/SitemapController.php create mode 100644 local/modules/Front/Front.php create mode 100644 local/modules/Front/I18n/de_DE.php create mode 100644 local/modules/Front/I18n/en_US.php create mode 100644 local/modules/Front/I18n/fr_FR.php create mode 100644 local/modules/Front/I18n/it_IT.php create mode 100644 local/modules/Front/I18n/ru_RU.php create mode 100644 local/modules/Front/I18n/tr_TR.php create mode 100644 local/modules/Front/LICENSE.txt create mode 100644 local/modules/Front/composer.json create mode 100644 local/modules/HookAdminHome/Config/config.xml create mode 100644 local/modules/HookAdminHome/Config/module.xml create mode 100644 local/modules/HookAdminHome/Config/routing.xml create mode 100644 local/modules/HookAdminHome/Controller/ConfigurationController.php create mode 100644 local/modules/HookAdminHome/Controller/HomeController.php create mode 100644 local/modules/HookAdminHome/Form/Configuration.php create mode 100644 local/modules/HookAdminHome/Hook/AdminHook.php create mode 100644 local/modules/HookAdminHome/Hook/HookAdminManager.php create mode 100644 local/modules/HookAdminHome/HookAdminHome.php create mode 100644 local/modules/HookAdminHome/I18n/ar_SA.php create mode 100644 local/modules/HookAdminHome/I18n/backOffice/default/ar_SA.php create mode 100644 local/modules/HookAdminHome/I18n/backOffice/default/cs_CZ.php create mode 100644 local/modules/HookAdminHome/I18n/backOffice/default/de_DE.php create mode 100644 local/modules/HookAdminHome/I18n/backOffice/default/en_US.php create mode 100644 local/modules/HookAdminHome/I18n/backOffice/default/es_ES.php create mode 100644 local/modules/HookAdminHome/I18n/backOffice/default/fr_FR.php create mode 100644 local/modules/HookAdminHome/I18n/backOffice/default/it_IT.php create mode 100644 local/modules/HookAdminHome/I18n/backOffice/default/pt_BR.php create mode 100644 local/modules/HookAdminHome/I18n/backOffice/default/ru_RU.php create mode 100644 local/modules/HookAdminHome/I18n/backOffice/default/tr_TR.php create mode 100644 local/modules/HookAdminHome/I18n/cs_CZ.php create mode 100644 local/modules/HookAdminHome/I18n/de_DE.php create mode 100644 local/modules/HookAdminHome/I18n/en_US.php create mode 100644 local/modules/HookAdminHome/I18n/es_ES.php create mode 100644 local/modules/HookAdminHome/I18n/fr_FR.php create mode 100644 local/modules/HookAdminHome/I18n/id_ID.php create mode 100644 local/modules/HookAdminHome/I18n/it_IT.php create mode 100644 local/modules/HookAdminHome/I18n/ru_RU.php create mode 100644 local/modules/HookAdminHome/I18n/tr_TR.php create mode 100644 local/modules/HookAdminHome/LICENSE.txt create mode 100644 local/modules/HookAdminHome/composer.json create mode 100644 local/modules/HookAdminHome/templates/backOffice/default/admin-home-config.html create mode 100644 local/modules/HookAdminHome/templates/backOffice/default/ajax/thelia_news_feed.html create mode 100644 local/modules/HookAdminHome/templates/backOffice/default/assets/css/home.css create mode 100644 local/modules/HookAdminHome/templates/backOffice/default/assets/less/home.less create mode 100644 local/modules/HookAdminHome/templates/backOffice/default/block-information.html create mode 100644 local/modules/HookAdminHome/templates/backOffice/default/block-month-sales-statistics.html create mode 100644 local/modules/HookAdminHome/templates/backOffice/default/block-news-js.html create mode 100644 local/modules/HookAdminHome/templates/backOffice/default/block-news.html create mode 100644 local/modules/HookAdminHome/templates/backOffice/default/block-sales-statistics.html create mode 100644 local/modules/HookAdminHome/templates/backOffice/default/block-statistics-js.html create mode 100644 local/modules/HookAdminHome/templates/backOffice/default/block-statistics.html create mode 100644 local/modules/HookAdminHome/templates/backOffice/default/block-thelia-information.html create mode 100644 local/modules/HookAdminHome/templates/backOffice/default/hook-admin-home-config.html create mode 100644 local/modules/HookAnalytics/Config/config.xml create mode 100644 local/modules/HookAnalytics/Config/module.xml create mode 100644 local/modules/HookAnalytics/Config/routing.xml create mode 100644 local/modules/HookAnalytics/Controller/Configuration.php create mode 100644 local/modules/HookAnalytics/Form/Configuration.php create mode 100644 local/modules/HookAnalytics/Hook/FrontHook.php create mode 100644 local/modules/HookAnalytics/HookAnalytics.php create mode 100644 local/modules/HookAnalytics/I18n/backOffice/default/de_DE.php create mode 100644 local/modules/HookAnalytics/I18n/backOffice/default/en_US.php create mode 100644 local/modules/HookAnalytics/I18n/backOffice/default/fr_FR.php create mode 100644 local/modules/HookAnalytics/I18n/backOffice/default/it_IT.php create mode 100644 local/modules/HookAnalytics/I18n/backOffice/default/ru_RU.php create mode 100644 local/modules/HookAnalytics/I18n/backOffice/default/tr_TR.php create mode 100644 local/modules/HookAnalytics/I18n/de_DE.php create mode 100644 local/modules/HookAnalytics/I18n/en_US.php create mode 100644 local/modules/HookAnalytics/I18n/fr_FR.php create mode 100644 local/modules/HookAnalytics/I18n/frontOffice/default/de_DE.php create mode 100644 local/modules/HookAnalytics/I18n/frontOffice/default/en_US.php create mode 100644 local/modules/HookAnalytics/I18n/frontOffice/default/fr_FR.php create mode 100644 local/modules/HookAnalytics/I18n/frontOffice/default/it_IT.php create mode 100644 local/modules/HookAnalytics/I18n/frontOffice/default/ru_RU.php create mode 100644 local/modules/HookAnalytics/I18n/frontOffice/default/tr_TR.php create mode 100644 local/modules/HookAnalytics/I18n/it_IT.php create mode 100644 local/modules/HookAnalytics/I18n/ru_RU.php create mode 100644 local/modules/HookAnalytics/I18n/tr_TR.php create mode 100644 local/modules/HookAnalytics/LICENSE.txt create mode 100644 local/modules/HookAnalytics/composer.json create mode 100644 local/modules/HookAnalytics/templates/backOffice/default/assets/js/module-configuration.js create mode 100644 local/modules/HookAnalytics/templates/backOffice/default/module_configuration.html create mode 100644 local/modules/HookCart/Config/config.xml create mode 100644 local/modules/HookCart/Config/module.xml create mode 100644 local/modules/HookCart/HookCart.php create mode 100644 local/modules/HookCart/I18n/frontOffice/default/de_DE.php create mode 100644 local/modules/HookCart/I18n/frontOffice/default/en_US.php create mode 100644 local/modules/HookCart/I18n/frontOffice/default/fr_FR.php create mode 100644 local/modules/HookCart/I18n/frontOffice/default/it_IT.php create mode 100644 local/modules/HookCart/I18n/frontOffice/default/ru_RU.php create mode 100644 local/modules/HookCart/I18n/frontOffice/default/tr_TR.php create mode 100644 local/modules/HookCart/LICENSE.txt create mode 100644 local/modules/HookCart/composer.json create mode 100644 local/modules/HookCart/templates/frontOffice/default/assets/css/styles.css create mode 100644 local/modules/HookCart/templates/frontOffice/default/main-navbar-secondary.html create mode 100644 local/modules/HookCart/templates/frontOffice/default/mini-cart.html create mode 100644 local/modules/HookContact/Config/config.xml create mode 100644 local/modules/HookContact/Config/module.xml create mode 100644 local/modules/HookContact/Hook/FrontHook.php create mode 100644 local/modules/HookContact/HookContact.php create mode 100644 local/modules/HookContact/I18n/de_DE.php create mode 100644 local/modules/HookContact/I18n/en_US.php create mode 100644 local/modules/HookContact/I18n/fr_FR.php create mode 100644 local/modules/HookContact/I18n/frontOffice/default/fr_FR.php create mode 100644 local/modules/HookContact/I18n/frontOffice/default/ru_RU.php create mode 100644 local/modules/HookContact/I18n/it_IT.php create mode 100644 local/modules/HookContact/I18n/ru_RU.php create mode 100644 local/modules/HookContact/I18n/tr_TR.php create mode 100644 local/modules/HookContact/LICENSE.txt create mode 100644 local/modules/HookContact/composer.json create mode 100644 local/modules/HookContact/templates/frontOffice/default/main-footer-body.html create mode 100644 local/modules/HookCurrency/Config/config.xml create mode 100644 local/modules/HookCurrency/Config/module.xml create mode 100644 local/modules/HookCurrency/HookCurrency.php create mode 100644 local/modules/HookCurrency/LICENSE.txt create mode 100644 local/modules/HookCurrency/composer.json create mode 100644 local/modules/HookCurrency/templates/frontOffice/default/main-navbar-secondary.html create mode 100644 local/modules/HookCustomer/Config/config.xml create mode 100644 local/modules/HookCustomer/Config/module.xml create mode 100644 local/modules/HookCustomer/HookCustomer.php create mode 100644 local/modules/HookCustomer/I18n/frontOffice/default/de_DE.php create mode 100644 local/modules/HookCustomer/I18n/frontOffice/default/en_US.php create mode 100644 local/modules/HookCustomer/I18n/frontOffice/default/fr_FR.php create mode 100644 local/modules/HookCustomer/I18n/frontOffice/default/it_IT.php create mode 100644 local/modules/HookCustomer/I18n/frontOffice/default/ru_RU.php create mode 100644 local/modules/HookCustomer/I18n/frontOffice/default/tr_TR.php create mode 100644 local/modules/HookCustomer/LICENSE.txt create mode 100644 local/modules/HookCustomer/composer.json create mode 100644 local/modules/HookCustomer/templates/frontOffice/default/assets/css/styles.css create mode 100644 local/modules/HookCustomer/templates/frontOffice/default/main-navbar-secondary.html create mode 100644 local/modules/HookLang/Config/config.xml create mode 100644 local/modules/HookLang/Config/module.xml create mode 100644 local/modules/HookLang/HookLang.php create mode 100644 local/modules/HookLang/LICENSE.txt create mode 100644 local/modules/HookLang/composer.json create mode 100644 local/modules/HookLang/templates/frontOffice/default/main-navbar-secondary.html create mode 100644 local/modules/HookLinks/Config/config.xml create mode 100644 local/modules/HookLinks/Config/module.xml create mode 100644 local/modules/HookLinks/Hook/FrontHook.php create mode 100644 local/modules/HookLinks/HookLinks.php create mode 100644 local/modules/HookLinks/I18n/de_DE.php create mode 100644 local/modules/HookLinks/I18n/en_US.php create mode 100644 local/modules/HookLinks/I18n/fr_FR.php create mode 100644 local/modules/HookLinks/I18n/frontOffice/default/de_DE.php create mode 100644 local/modules/HookLinks/I18n/frontOffice/default/en_US.php create mode 100644 local/modules/HookLinks/I18n/frontOffice/default/fr_FR.php create mode 100644 local/modules/HookLinks/I18n/frontOffice/default/it_IT.php create mode 100644 local/modules/HookLinks/I18n/frontOffice/default/ru_RU.php create mode 100644 local/modules/HookLinks/I18n/frontOffice/default/tr_TR.php create mode 100644 local/modules/HookLinks/I18n/it_IT.php create mode 100644 local/modules/HookLinks/I18n/ru_RU.php create mode 100644 local/modules/HookLinks/I18n/tr_TR.php create mode 100644 local/modules/HookLinks/LICENSE.txt create mode 100644 local/modules/HookLinks/composer.json create mode 100644 local/modules/HookLinks/templates/frontOffice/default/main-footer-body.html create mode 100644 local/modules/HookNavigation/Config/config.xml create mode 100644 local/modules/HookNavigation/Config/module.xml create mode 100644 local/modules/HookNavigation/Config/routing.xml create mode 100644 local/modules/HookNavigation/Controller/HookNavigationConfigController.php create mode 100644 local/modules/HookNavigation/Form/HookNavigationConfigForm.php create mode 100644 local/modules/HookNavigation/Hook/FrontHook.php create mode 100644 local/modules/HookNavigation/HookNavigation.php create mode 100644 local/modules/HookNavigation/I18n/backOffice/default/de_DE.php create mode 100644 local/modules/HookNavigation/I18n/backOffice/default/en_US.php create mode 100644 local/modules/HookNavigation/I18n/backOffice/default/fr_FR.php create mode 100644 local/modules/HookNavigation/I18n/backOffice/default/it_IT.php create mode 100644 local/modules/HookNavigation/I18n/backOffice/default/ru_RU.php create mode 100644 local/modules/HookNavigation/I18n/backOffice/default/tr_TR.php create mode 100644 local/modules/HookNavigation/I18n/en_US.php create mode 100644 local/modules/HookNavigation/I18n/fr_FR.php create mode 100644 local/modules/HookNavigation/I18n/frontOffice/default/de_DE.php create mode 100644 local/modules/HookNavigation/I18n/frontOffice/default/en_US.php create mode 100644 local/modules/HookNavigation/I18n/frontOffice/default/fr_FR.php create mode 100644 local/modules/HookNavigation/I18n/frontOffice/default/it_IT.php create mode 100644 local/modules/HookNavigation/I18n/frontOffice/default/ru_RU.php create mode 100644 local/modules/HookNavigation/I18n/frontOffice/default/tr_TR.php create mode 100644 local/modules/HookNavigation/I18n/it_IT.php create mode 100644 local/modules/HookNavigation/I18n/ru_RU.php create mode 100644 local/modules/HookNavigation/LICENSE.txt create mode 100644 local/modules/HookNavigation/Model/Config/Base/HookNavigationConfigValue.php create mode 100644 local/modules/HookNavigation/Model/Config/HookNavigationConfigValue.php create mode 100644 local/modules/HookNavigation/composer.json create mode 100644 local/modules/HookNavigation/templates/backOffice/default/hooknavigation-configuration.html create mode 100644 local/modules/HookNavigation/templates/frontOffice/default/main-footer-body.html create mode 100644 local/modules/HookNavigation/templates/frontOffice/default/main-footer-bottom.html create mode 100644 local/modules/HookNavigation/templates/frontOffice/default/main-navbar-primary.html create mode 100644 local/modules/HookNewsletter/Config/config.xml create mode 100644 local/modules/HookNewsletter/Config/module.xml create mode 100644 local/modules/HookNewsletter/Hook/FrontHook.php create mode 100644 local/modules/HookNewsletter/HookNewsletter.php create mode 100644 local/modules/HookNewsletter/I18n/de_DE.php create mode 100644 local/modules/HookNewsletter/I18n/en_US.php create mode 100644 local/modules/HookNewsletter/I18n/fr_FR.php create mode 100644 local/modules/HookNewsletter/I18n/frontOffice/default/de_DE.php create mode 100644 local/modules/HookNewsletter/I18n/frontOffice/default/en_US.php create mode 100644 local/modules/HookNewsletter/I18n/frontOffice/default/fr_FR.php create mode 100644 local/modules/HookNewsletter/I18n/frontOffice/default/it_IT.php create mode 100644 local/modules/HookNewsletter/I18n/frontOffice/default/ru_RU.php create mode 100644 local/modules/HookNewsletter/I18n/frontOffice/default/tr_TR.php create mode 100644 local/modules/HookNewsletter/I18n/it_IT.php create mode 100644 local/modules/HookNewsletter/I18n/ru_RU.php create mode 100644 local/modules/HookNewsletter/I18n/tr_TR.php create mode 100644 local/modules/HookNewsletter/LICENSE.txt create mode 100644 local/modules/HookNewsletter/composer.json create mode 100644 local/modules/HookNewsletter/templates/frontOffice/default/main-footer-body.html create mode 100644 local/modules/HookProductsNew/Config/config.xml create mode 100644 local/modules/HookProductsNew/Config/module.xml create mode 100644 local/modules/HookProductsNew/HookProductsNew.php create mode 100644 local/modules/HookProductsNew/I18n/frontOffice/default/de_DE.php create mode 100644 local/modules/HookProductsNew/I18n/frontOffice/default/en_US.php create mode 100644 local/modules/HookProductsNew/I18n/frontOffice/default/fr_FR.php create mode 100644 local/modules/HookProductsNew/I18n/frontOffice/default/it_IT.php create mode 100644 local/modules/HookProductsNew/I18n/frontOffice/default/ru_RU.php create mode 100644 local/modules/HookProductsNew/I18n/frontOffice/default/tr_TR.php create mode 100644 local/modules/HookProductsNew/LICENSE.txt create mode 100644 local/modules/HookProductsNew/composer.json create mode 100644 local/modules/HookProductsNew/templates/frontOffice/default/home-body.html create mode 100644 local/modules/HookProductsOffer/Config/config.xml create mode 100644 local/modules/HookProductsOffer/Config/module.xml create mode 100644 local/modules/HookProductsOffer/HookProductsOffer.php create mode 100644 local/modules/HookProductsOffer/I18n/frontOffice/default/de_DE.php create mode 100644 local/modules/HookProductsOffer/I18n/frontOffice/default/en_US.php create mode 100644 local/modules/HookProductsOffer/I18n/frontOffice/default/fr_FR.php create mode 100644 local/modules/HookProductsOffer/I18n/frontOffice/default/it_IT.php create mode 100644 local/modules/HookProductsOffer/I18n/frontOffice/default/ru_RU.php create mode 100644 local/modules/HookProductsOffer/I18n/frontOffice/default/tr_TR.php create mode 100644 local/modules/HookProductsOffer/LICENSE.txt create mode 100644 local/modules/HookProductsOffer/composer.json create mode 100644 local/modules/HookProductsOffer/templates/frontOffice/default/home-body.html create mode 100644 local/modules/HookSearch/Config/config.xml create mode 100644 local/modules/HookSearch/Config/module.xml create mode 100644 local/modules/HookSearch/HookSearch.php create mode 100644 local/modules/HookSearch/I18n/frontOffice/default/de_DE.php create mode 100644 local/modules/HookSearch/I18n/frontOffice/default/en_US.php create mode 100644 local/modules/HookSearch/I18n/frontOffice/default/fr_FR.php create mode 100644 local/modules/HookSearch/I18n/frontOffice/default/it_IT.php create mode 100644 local/modules/HookSearch/I18n/frontOffice/default/ru_RU.php create mode 100644 local/modules/HookSearch/I18n/frontOffice/default/tr_TR.php create mode 100644 local/modules/HookSearch/LICENSE.txt create mode 100644 local/modules/HookSearch/composer.json create mode 100644 local/modules/HookSearch/templates/frontOffice/default/assets/css/styles.css create mode 100644 local/modules/HookSearch/templates/frontOffice/default/main-navbar-primary.html create mode 100644 local/modules/HookSearch/templates/frontOffice/default/main-navbar-secondary.html create mode 100644 local/modules/HookSocial/Config/config.xml create mode 100644 local/modules/HookSocial/Config/module.xml create mode 100644 local/modules/HookSocial/Config/routing.xml create mode 100644 local/modules/HookSocial/Controller/Configuration.php create mode 100644 local/modules/HookSocial/Form/Configuration.php create mode 100644 local/modules/HookSocial/Hook/FrontHook.php create mode 100644 local/modules/HookSocial/HookSocial.php create mode 100644 local/modules/HookSocial/I18n/backOffice/default/de_DE.php create mode 100644 local/modules/HookSocial/I18n/backOffice/default/en_US.php create mode 100644 local/modules/HookSocial/I18n/backOffice/default/fr_FR.php create mode 100644 local/modules/HookSocial/I18n/backOffice/default/it_IT.php create mode 100644 local/modules/HookSocial/I18n/backOffice/default/ru_RU.php create mode 100644 local/modules/HookSocial/I18n/backOffice/default/tr_TR.php create mode 100644 local/modules/HookSocial/I18n/de_DE.php create mode 100644 local/modules/HookSocial/I18n/en_US.php create mode 100644 local/modules/HookSocial/I18n/fr_FR.php create mode 100644 local/modules/HookSocial/I18n/frontOffice/default/de_DE.php create mode 100644 local/modules/HookSocial/I18n/frontOffice/default/en_US.php create mode 100644 local/modules/HookSocial/I18n/frontOffice/default/fr_FR.php create mode 100644 local/modules/HookSocial/I18n/frontOffice/default/it_IT.php create mode 100644 local/modules/HookSocial/I18n/frontOffice/default/ru_RU.php create mode 100644 local/modules/HookSocial/I18n/frontOffice/default/tr_TR.php create mode 100644 local/modules/HookSocial/I18n/it_IT.php create mode 100644 local/modules/HookSocial/I18n/ru_RU.php create mode 100644 local/modules/HookSocial/I18n/tr_TR.php create mode 100644 local/modules/HookSocial/LICENSE.txt create mode 100644 local/modules/HookSocial/composer.json create mode 100644 local/modules/HookSocial/templates/backOffice/default/assets/js/module-configuration.js create mode 100644 local/modules/HookSocial/templates/backOffice/default/module_configuration.html create mode 100644 local/modules/HookSocial/templates/frontOffice/default/assets/css/styles.css create mode 100644 local/modules/HookSocial/templates/frontOffice/default/main-footer-body.html create mode 100644 local/modules/TheliaMigrateCountry/Config/config.xml create mode 100644 local/modules/TheliaMigrateCountry/Config/module.xml create mode 100644 local/modules/TheliaMigrateCountry/Config/routing.xml create mode 100644 local/modules/TheliaMigrateCountry/Controller/MigrateController.php create mode 100644 local/modules/TheliaMigrateCountry/EventListeners/MigrateCountryListener.php create mode 100644 local/modules/TheliaMigrateCountry/Events/MigrateCountryEvent.php create mode 100644 local/modules/TheliaMigrateCountry/Events/MigrateCountryEvents.php create mode 100644 local/modules/TheliaMigrateCountry/Form/CountryStateMigrationForm.php create mode 100644 local/modules/TheliaMigrateCountry/Form/Type/CountryStateMigrationType.php create mode 100644 local/modules/TheliaMigrateCountry/I18n/backOffice/default/en_US.php create mode 100644 local/modules/TheliaMigrateCountry/I18n/backOffice/default/fr_FR.php create mode 100644 local/modules/TheliaMigrateCountry/I18n/backOffice/default/it_IT.php create mode 100644 local/modules/TheliaMigrateCountry/I18n/backOffice/default/ru_RU.php create mode 100644 local/modules/TheliaMigrateCountry/I18n/en_US.php create mode 100644 local/modules/TheliaMigrateCountry/I18n/fr_FR.php create mode 100644 local/modules/TheliaMigrateCountry/I18n/it_IT.php create mode 100644 local/modules/TheliaMigrateCountry/I18n/ru_RU.php create mode 100644 local/modules/TheliaMigrateCountry/LICENSE.txt create mode 100644 local/modules/TheliaMigrateCountry/Readme.md create mode 100644 local/modules/TheliaMigrateCountry/TheliaMigrateCountry.php create mode 100644 local/modules/TheliaMigrateCountry/composer.json create mode 100644 local/modules/TheliaMigrateCountry/templates/backOffice/default/configuration-shipping-bottom.html create mode 100644 local/modules/TheliaMigrateCountry/templates/backOffice/default/countries-migrate.html create mode 100644 local/modules/TheliaSmarty/CREDITS.md create mode 100644 local/modules/TheliaSmarty/Compiler/RegisterParserPluginPass.php create mode 100644 local/modules/TheliaSmarty/Config/config.xml create mode 100644 local/modules/TheliaSmarty/Config/module.xml create mode 100644 local/modules/TheliaSmarty/I18n/en_US.php create mode 100644 local/modules/TheliaSmarty/I18n/fr_FR.php create mode 100644 local/modules/TheliaSmarty/I18n/ru_RU.php create mode 100644 local/modules/TheliaSmarty/I18n/tr_TR.php create mode 100644 local/modules/TheliaSmarty/LICENSE.txt create mode 100644 local/modules/TheliaSmarty/Readme.md create mode 100644 local/modules/TheliaSmarty/Template/AbstractSmartyPlugin.php create mode 100644 local/modules/TheliaSmarty/Template/Assets/SmartyAssetsManager.php create mode 100644 local/modules/TheliaSmarty/Template/Assets/SmartyAssetsResolver.php create mode 100644 local/modules/TheliaSmarty/Template/Exception/SmartyPluginException.php create mode 100644 local/modules/TheliaSmarty/Template/Plugins/AdminUtilities.php create mode 100644 local/modules/TheliaSmarty/Template/Plugins/Assets.php create mode 100644 local/modules/TheliaSmarty/Template/Plugins/Cache.php create mode 100644 local/modules/TheliaSmarty/Template/Plugins/CartPostage.php create mode 100644 local/modules/TheliaSmarty/Template/Plugins/DataAccessFunctions.php create mode 100644 local/modules/TheliaSmarty/Template/Plugins/Esi.php create mode 100644 local/modules/TheliaSmarty/Template/Plugins/FlashMessage.php create mode 100644 local/modules/TheliaSmarty/Template/Plugins/Form.php create mode 100644 local/modules/TheliaSmarty/Template/Plugins/Format.php create mode 100644 local/modules/TheliaSmarty/Template/Plugins/Hook.php create mode 100644 local/modules/TheliaSmarty/Template/Plugins/Module.php create mode 100644 local/modules/TheliaSmarty/Template/Plugins/Render.php create mode 100644 local/modules/TheliaSmarty/Template/Plugins/Security.php create mode 100644 local/modules/TheliaSmarty/Template/Plugins/TheliaLoop.php create mode 100644 local/modules/TheliaSmarty/Template/Plugins/Translation.php create mode 100644 local/modules/TheliaSmarty/Template/Plugins/Type.php create mode 100644 local/modules/TheliaSmarty/Template/Plugins/UrlGenerator.php create mode 100644 local/modules/TheliaSmarty/Template/Plugins/VarDumper.php create mode 100644 local/modules/TheliaSmarty/Template/SmartyHelper.php create mode 100644 local/modules/TheliaSmarty/Template/SmartyParser.php create mode 100644 local/modules/TheliaSmarty/Template/SmartyPluginDescriptor.php create mode 100644 local/modules/TheliaSmarty/Tests/Template/Plugin/Controller/TestController.php create mode 100644 local/modules/TheliaSmarty/Tests/Template/Plugin/FormTest.php create mode 100644 local/modules/TheliaSmarty/Tests/Template/Plugin/FormatTest.php create mode 100644 local/modules/TheliaSmarty/Tests/Template/Plugin/RenderTest.php create mode 100644 local/modules/TheliaSmarty/Tests/Template/Plugin/SmartyPluginTestCase.php create mode 100644 local/modules/TheliaSmarty/Tests/Template/Plugin/fixtures/test.html create mode 100644 local/modules/TheliaSmarty/Tests/Template/Plugin/fixtures/testFormatMoney.html create mode 100644 local/modules/TheliaSmarty/Tests/Template/Plugin/fixtures/testMethod.html create mode 100644 local/modules/TheliaSmarty/Tests/Template/Plugin/fixtures/testParams.html create mode 100644 local/modules/TheliaSmarty/Tests/Template/Plugin/fixtures/testQueryArray.html create mode 100644 local/modules/TheliaSmarty/Tests/Template/Plugin/fixtures/testQueryString.html create mode 100644 local/modules/TheliaSmarty/Tests/Template/Plugin/fixtures/testRequest.html create mode 100644 local/modules/TheliaSmarty/Tests/Template/SmartyHelperTest.php create mode 100644 local/modules/TheliaSmarty/TheliaSmarty.php create mode 100644 local/modules/TheliaSmarty/composer.json create mode 100644 local/modules/Tinymce/CHANGELOG.md create mode 100644 local/modules/Tinymce/Config/config.xml create mode 100644 local/modules/Tinymce/Config/module.xml create mode 100644 local/modules/Tinymce/Config/routing.xml create mode 100644 local/modules/Tinymce/Controller/ConfigureController.php create mode 100644 local/modules/Tinymce/Form/ConfigurationForm.php create mode 100644 local/modules/Tinymce/Hook/HookManager.php create mode 100644 local/modules/Tinymce/I18n/backOffice/default/de_DE.php create mode 100644 local/modules/Tinymce/I18n/backOffice/default/en_US.php create mode 100644 local/modules/Tinymce/I18n/backOffice/default/fr_FR.php create mode 100644 local/modules/Tinymce/I18n/backOffice/default/ru_RU.php create mode 100644 local/modules/Tinymce/I18n/backOffice/default/tr_TR.php create mode 100644 local/modules/Tinymce/I18n/en_US.php create mode 100644 local/modules/Tinymce/I18n/fr_FR.php create mode 100644 local/modules/Tinymce/I18n/it_IT.php create mode 100644 local/modules/Tinymce/I18n/ru_RU.php create mode 100644 local/modules/Tinymce/I18n/tr_TR.php create mode 100644 local/modules/Tinymce/LICENSE.txt create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/ajax_calls.php create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/config/.htaccess create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/config/config.php create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/css/style.css create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/dialog.php create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/execute.php create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/force_download.php create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/clipboard_apply.png create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/clipboard_clear.png create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/copy.png create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/cut.png create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/date.png create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/dimension.png create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/down.png create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/download.png create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/duplicate.png create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/edit_img.png create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/file_edit.png create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/glyphicons-halflings-white.png create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/glyphicons-halflings.png create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/ac3.jpg create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/accdb.jpg create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/ade.jpg create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/adp.jpg create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/ai.jpg create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/aiff.jpg create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/avi.jpg create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/bmp.jpg create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/c4d.jpg create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/css.jpg create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/csv.jpg create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/default.jpg create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/dmg.jpg create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/doc.jpg create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/docx.jpg create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/dwg.jpg create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/dxf.jpg create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/favicon.ico create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/fla.jpg create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/flv.jpg create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/folder.png create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/folder_back.png create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/gif.jpg create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/gz.jpg create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/html.jpg create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/iso.jpg create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/jpeg.jpg create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/jpg.jpg create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/log.jpg create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/m4a.jpg create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/mdb.jpg create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/mid.jpg create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/mov.jpg create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/mp3.jpg create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/mp4.jpg create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/mpeg.jpg create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/mpg.jpg create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/odb.jpg create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/odf.jpg create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/odg.jpg create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/odp.jpg create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/ods.jpg create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/odt.jpg create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/ogg.jpg create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/otg.jpg create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/otp.jpg create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/ots.jpg create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/ott.jpg create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/pdf.jpg create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/png.jpg create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/ppt.jpg create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/pptx.jpg create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/psd.jpg create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/rar.jpg create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/rtf.jpg create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/skp.jpg create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/sql.jpg create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/stp.jpg create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/svg.jpg create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/tar.jpg create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/tiff.jpg create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/txt.jpg create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/vwx.jpg create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/wav.jpg create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/webm.jpg create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/wma.jpg create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/xhtml.jpg create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/xls.jpg create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/xlsx.jpg create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/xml.jpg create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/zip.jpg create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/ac3.jpg create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/accdb.jpg create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/ade.jpg create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/adp.jpg create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/ai.jpg create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/aiff.jpg create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/avi.jpg create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/bmp.jpg create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/css.jpg create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/csv.jpg create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/default.jpg create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/dmg.jpg create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/doc.jpg create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/docx.jpg create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/favicon.ico create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/fla.jpg create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/flv.jpg create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/folder.png create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/folder_back.png create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/gif.jpg create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/gz.jpg create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/html.jpg create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/iso.jpg create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/jpeg.jpg create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/jpg.jpg create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/log.jpg create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/m4a.jpg create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/mdb.jpg create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/mid.jpg create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/mov.jpg create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/mp3.jpg create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/mp4.jpg create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/mpeg.jpg create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/mpg.jpg create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/odb.jpg create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/odf.jpg create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/odg.jpg create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/odp.jpg create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/ods.jpg create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/odt.jpg create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/ogg.jpg create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/otg.jpg create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/otp.jpg create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/ots.jpg create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/ott.jpg create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/pdf.jpg create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/png.jpg create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/ppt.jpg create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/pptx.jpg create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/psd.jpg create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/rar.jpg create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/rtf.jpg create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/sql.jpg create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/svg.jpg create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/tar.jpg create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/tiff.jpg create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/txt.jpg create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/wav.jpg create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/webm.jpg create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/wma.jpg create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/xhtml.jpg create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/xls.jpg create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/xlsx.jpg create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/xml.jpg create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/zip.jpg create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/info.png create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/key.png create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/label.png create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/loading.gif create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/logo.png create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/preview.png create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/processing.gif create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/rename.png create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/size.png create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/sort.png create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/storing_animation.gif create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/trans.jpg create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/up.png create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/upload.png create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/url.png create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/img/zip.png create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/include/FtpClient.php create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/include/FtpException.php create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/include/FtpWrapper.php create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/include/Response.php create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/include/ftp_class.php create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/include/mime_type_lib.php create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/include/php_image_magician.php create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/include/utils.php create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/js/ZeroClipboard.swf create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/js/include.js create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/js/jPlayer/MIT-LICENSE.txt create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/js/jPlayer/README.md create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/js/jPlayer/actionscript/Jplayer.as create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/js/jPlayer/actionscript/Jplayer.fla create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/js/jPlayer/actionscript/happyworm/jPlayer/ConnectManager.as create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/js/jPlayer/actionscript/happyworm/jPlayer/JplayerEvent.as create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/js/jPlayer/actionscript/happyworm/jPlayer/JplayerMp3.as create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/js/jPlayer/actionscript/happyworm/jPlayer/JplayerMp4.as create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/js/jPlayer/actionscript/happyworm/jPlayer/JplayerRtmp.as create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/js/jPlayer/actionscript/happyworm/jPlayer/JplayerStatus.as create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/js/jPlayer/actionscript/happyworm/jPlayer/TraceOut.as create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/js/jPlayer/add-on/jplayer.playlist.js create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/js/jPlayer/add-on/jplayer.playlist.min.js create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/js/jPlayer/add-on/jquery.jplayer.inspector.js create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/js/jPlayer/add-on/jquery.jplayer.inspector.min.js create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/js/jPlayer/jplayer.jquery.json create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/js/jPlayer/jplayer/jquery.jplayer.js create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/js/jPlayer/jplayer/jquery.jplayer.min.js create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/js/jPlayer/jplayer/jquery.jplayer.swf create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/js/jPlayer/jquery.jplayer/Jplayer.swf create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/js/jPlayer/jquery.jplayer/jquery.jplayer.js create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/js/jPlayer/package.json create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/js/jPlayer/popcorn/popcorn.jplayer.js create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/js/jPlayer/popcorn/popcorn.jplayer.min.js create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/js/jPlayer/skin/blue.monday/css/jplayer.blue.monday.css create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/js/jPlayer/skin/blue.monday/css/jplayer.blue.monday.min.css create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/js/jPlayer/skin/blue.monday/image/jplayer.blue.monday.jpg create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/js/jPlayer/skin/blue.monday/image/jplayer.blue.monday.seeking.gif create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/js/jPlayer/skin/blue.monday/image/jplayer.blue.monday.video.play.png create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/js/jPlayer/skin/blue.monday/jplayer.blue.monday.css create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/js/jPlayer/skin/blue.monday/jplayer.blue.monday.jpg create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/js/jPlayer/skin/blue.monday/jplayer.blue.monday.seeking.gif create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/js/jPlayer/skin/blue.monday/jplayer.blue.monday.video.play.png create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/js/jPlayer/skin/blue.monday/mustache/jplayer.blue.monday.audio.playlist.html create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/js/jPlayer/skin/blue.monday/mustache/jplayer.blue.monday.audio.single.html create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/js/jPlayer/skin/blue.monday/mustache/jplayer.blue.monday.audio.stream.html create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/js/jPlayer/skin/blue.monday/mustache/jplayer.blue.monday.video.playlist.html create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/js/jPlayer/skin/blue.monday/mustache/jplayer.blue.monday.video.single.html create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/js/jPlayer/skin/blue.monday/skin.handlebars create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/js/jPlayer/skin/pink.flag/css/jplayer.pink.flag.css create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/js/jPlayer/skin/pink.flag/css/jplayer.pink.flag.min.css create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/js/jPlayer/skin/pink.flag/image/jplayer.pink.flag.jpg create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/js/jPlayer/skin/pink.flag/image/jplayer.pink.flag.seeking.gif create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/js/jPlayer/skin/pink.flag/image/jplayer.pink.flag.video.play.png create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/js/jPlayer/skin/pink.flag/mustache/jplayer.pink.flag.audio.playlist.html create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/js/jPlayer/skin/pink.flag/mustache/jplayer.pink.flag.audio.single.html create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/js/jPlayer/skin/pink.flag/mustache/jplayer.pink.flag.audio.stream.html create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/js/jPlayer/skin/pink.flag/mustache/jplayer.pink.flag.video.playlist.html create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/js/jPlayer/skin/pink.flag/mustache/jplayer.pink.flag.video.single.html create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/js/jPlayer/skin_ol/blue.monday/jplayer.blue.monday.css create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/js/jPlayer/skin_ol/blue.monday/jplayer.blue.monday.jpg create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/js/jPlayer/skin_ol/blue.monday/jplayer.blue.monday.seeking.gif create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/js/jPlayer/skin_ol/blue.monday/jplayer.blue.monday.video.play.png create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/js/jPlayer/skin_ol/blue.monday/skin.handlebars create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/js/jPlayer/skin_ol/pink.flag/jplayer.pink.flag.css create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/js/jPlayer/skin_ol/pink.flag/jplayer.pink.flag.jpg create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/js/jPlayer/skin_ol/pink.flag/jplayer.pink.flag.seeking.gif create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/js/jPlayer/skin_ol/pink.flag/jplayer.pink.flag.video.play.png create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/js/modernizr.custom.js create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/js/plugins.js create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/lang/az_AZ.php create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/lang/bg_BG.php create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/lang/ca.php create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/lang/cs.php create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/lang/da.php create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/lang/de.php create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/lang/el_GR.php create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/lang/en_EN.php create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/lang/es.php create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/lang/fa.php create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/lang/fr_FR.php create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/lang/he_IL.php create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/lang/hr.php create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/lang/hu_HU.php create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/lang/id.php create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/lang/it.php create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/lang/ja.php create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/lang/languages.php create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/lang/lt.php create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/lang/mn_MN.php create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/lang/nb_NO.php create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/lang/nl.php create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/lang/pl.php create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/lang/pt_BR.php create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/lang/pt_PT.php create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/lang/ro.php create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/lang/ru.php create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/lang/sk.php create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/lang/sl.php create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/lang/sv_SE.php create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/lang/tr_TR.php create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/lang/uk_UA.php create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/lang/vi.php create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/lang/zh_CN.php create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/plugin.min.js create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/upload.php create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/uploader/index.php create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/uploader/jupload.php create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/uploader/success.jpg create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/uploader/success.php create mode 100644 local/modules/Tinymce/Resources/js/tinymce/filemanager/uploader/wjhk.jupload.jar create mode 100644 local/modules/Tinymce/Resources/js/tinymce/langs/cs.js create mode 100644 local/modules/Tinymce/Resources/js/tinymce/langs/de.js create mode 100644 local/modules/Tinymce/Resources/js/tinymce/langs/es.js create mode 100644 local/modules/Tinymce/Resources/js/tinymce/langs/fr_FR.js create mode 100644 local/modules/Tinymce/Resources/js/tinymce/langs/it.js create mode 100644 local/modules/Tinymce/Resources/js/tinymce/langs/readme.md create mode 100644 local/modules/Tinymce/Resources/js/tinymce/langs/ru.js create mode 100644 local/modules/Tinymce/Resources/js/tinymce/license.txt create mode 100644 local/modules/Tinymce/Resources/js/tinymce/plugins/advlist/plugin.min.js create mode 100644 local/modules/Tinymce/Resources/js/tinymce/plugins/anchor/plugin.min.js create mode 100644 local/modules/Tinymce/Resources/js/tinymce/plugins/autolink/plugin.min.js create mode 100644 local/modules/Tinymce/Resources/js/tinymce/plugins/autoresize/plugin.min.js create mode 100644 local/modules/Tinymce/Resources/js/tinymce/plugins/autosave/plugin.min.js create mode 100644 local/modules/Tinymce/Resources/js/tinymce/plugins/bbcode/plugin.min.js create mode 100644 local/modules/Tinymce/Resources/js/tinymce/plugins/charmap/plugin.min.js create mode 100644 local/modules/Tinymce/Resources/js/tinymce/plugins/code/plugin.min.js create mode 100644 local/modules/Tinymce/Resources/js/tinymce/plugins/codesample/css/prism.css create mode 100644 local/modules/Tinymce/Resources/js/tinymce/plugins/codesample/plugin.min.js create mode 100644 local/modules/Tinymce/Resources/js/tinymce/plugins/colorpicker/plugin.min.js create mode 100644 local/modules/Tinymce/Resources/js/tinymce/plugins/contextmenu/plugin.min.js create mode 100644 local/modules/Tinymce/Resources/js/tinymce/plugins/directionality/plugin.min.js create mode 100644 local/modules/Tinymce/Resources/js/tinymce/plugins/emoticons/img/smiley-cool.gif create mode 100644 local/modules/Tinymce/Resources/js/tinymce/plugins/emoticons/img/smiley-cry.gif create mode 100644 local/modules/Tinymce/Resources/js/tinymce/plugins/emoticons/img/smiley-embarassed.gif create mode 100644 local/modules/Tinymce/Resources/js/tinymce/plugins/emoticons/img/smiley-foot-in-mouth.gif create mode 100644 local/modules/Tinymce/Resources/js/tinymce/plugins/emoticons/img/smiley-frown.gif create mode 100644 local/modules/Tinymce/Resources/js/tinymce/plugins/emoticons/img/smiley-innocent.gif create mode 100644 local/modules/Tinymce/Resources/js/tinymce/plugins/emoticons/img/smiley-kiss.gif create mode 100644 local/modules/Tinymce/Resources/js/tinymce/plugins/emoticons/img/smiley-laughing.gif create mode 100644 local/modules/Tinymce/Resources/js/tinymce/plugins/emoticons/img/smiley-money-mouth.gif create mode 100644 local/modules/Tinymce/Resources/js/tinymce/plugins/emoticons/img/smiley-sealed.gif create mode 100644 local/modules/Tinymce/Resources/js/tinymce/plugins/emoticons/img/smiley-smile.gif create mode 100644 local/modules/Tinymce/Resources/js/tinymce/plugins/emoticons/img/smiley-surprised.gif create mode 100644 local/modules/Tinymce/Resources/js/tinymce/plugins/emoticons/img/smiley-tongue-out.gif create mode 100644 local/modules/Tinymce/Resources/js/tinymce/plugins/emoticons/img/smiley-undecided.gif create mode 100644 local/modules/Tinymce/Resources/js/tinymce/plugins/emoticons/img/smiley-wink.gif create mode 100644 local/modules/Tinymce/Resources/js/tinymce/plugins/emoticons/img/smiley-yell.gif create mode 100644 local/modules/Tinymce/Resources/js/tinymce/plugins/emoticons/plugin.min.js create mode 100644 local/modules/Tinymce/Resources/js/tinymce/plugins/example/dialog.html create mode 100644 local/modules/Tinymce/Resources/js/tinymce/plugins/example/plugin.min.js create mode 100644 local/modules/Tinymce/Resources/js/tinymce/plugins/example_dependency/plugin.min.js create mode 100644 local/modules/Tinymce/Resources/js/tinymce/plugins/fullpage/plugin.min.js create mode 100644 local/modules/Tinymce/Resources/js/tinymce/plugins/fullscreen/plugin.min.js create mode 100644 local/modules/Tinymce/Resources/js/tinymce/plugins/hr/plugin.min.js create mode 100644 local/modules/Tinymce/Resources/js/tinymce/plugins/image/plugin.min.js create mode 100644 local/modules/Tinymce/Resources/js/tinymce/plugins/imagetools/plugin.min.js create mode 100644 local/modules/Tinymce/Resources/js/tinymce/plugins/importcss/plugin.min.js create mode 100644 local/modules/Tinymce/Resources/js/tinymce/plugins/insertdatetime/plugin.min.js create mode 100644 local/modules/Tinymce/Resources/js/tinymce/plugins/layer/plugin.min.js create mode 100644 local/modules/Tinymce/Resources/js/tinymce/plugins/legacyoutput/plugin.min.js create mode 100644 local/modules/Tinymce/Resources/js/tinymce/plugins/link/plugin.min.js create mode 100644 local/modules/Tinymce/Resources/js/tinymce/plugins/lists/plugin.min.js create mode 100644 local/modules/Tinymce/Resources/js/tinymce/plugins/media/moxieplayer.swf create mode 100644 local/modules/Tinymce/Resources/js/tinymce/plugins/media/plugin.min.js create mode 100644 local/modules/Tinymce/Resources/js/tinymce/plugins/nonbreaking/plugin.min.js create mode 100644 local/modules/Tinymce/Resources/js/tinymce/plugins/noneditable/plugin.min.js create mode 100644 local/modules/Tinymce/Resources/js/tinymce/plugins/pagebreak/plugin.min.js create mode 100644 local/modules/Tinymce/Resources/js/tinymce/plugins/paste/plugin.min.js create mode 100644 local/modules/Tinymce/Resources/js/tinymce/plugins/preview/plugin.min.js create mode 100644 local/modules/Tinymce/Resources/js/tinymce/plugins/print/plugin.min.js create mode 100644 local/modules/Tinymce/Resources/js/tinymce/plugins/responsivefilemanager/editor_plugin.js create mode 100644 local/modules/Tinymce/Resources/js/tinymce/plugins/responsivefilemanager/img/insertfile.gif create mode 100644 local/modules/Tinymce/Resources/js/tinymce/plugins/responsivefilemanager/plugin.js create mode 100644 local/modules/Tinymce/Resources/js/tinymce/plugins/responsivefilemanager/plugin.min.js create mode 100644 local/modules/Tinymce/Resources/js/tinymce/plugins/save/plugin.min.js create mode 100644 local/modules/Tinymce/Resources/js/tinymce/plugins/searchreplace/plugin.min.js create mode 100644 local/modules/Tinymce/Resources/js/tinymce/plugins/spellchecker/plugin.min.js create mode 100644 local/modules/Tinymce/Resources/js/tinymce/plugins/tabfocus/plugin.min.js create mode 100644 local/modules/Tinymce/Resources/js/tinymce/plugins/table/plugin.min.js create mode 100644 local/modules/Tinymce/Resources/js/tinymce/plugins/template/plugin.min.js create mode 100644 local/modules/Tinymce/Resources/js/tinymce/plugins/textcolor/plugin.min.js create mode 100644 local/modules/Tinymce/Resources/js/tinymce/plugins/textpattern/plugin.min.js create mode 100644 local/modules/Tinymce/Resources/js/tinymce/plugins/visualblocks/css/visualblocks.css create mode 100644 local/modules/Tinymce/Resources/js/tinymce/plugins/visualblocks/plugin.min.js create mode 100644 local/modules/Tinymce/Resources/js/tinymce/plugins/visualchars/plugin.min.js create mode 100644 local/modules/Tinymce/Resources/js/tinymce/plugins/wordcount/plugin.min.js create mode 100644 local/modules/Tinymce/Resources/js/tinymce/plugins/youtube/README.md create mode 100644 local/modules/Tinymce/Resources/js/tinymce/plugins/youtube/css/styles.css create mode 100644 local/modules/Tinymce/Resources/js/tinymce/plugins/youtube/img/Google-YouTube-128.png create mode 100644 local/modules/Tinymce/Resources/js/tinymce/plugins/youtube/img/youtube.gif create mode 100644 local/modules/Tinymce/Resources/js/tinymce/plugins/youtube/js/main.js create mode 100644 local/modules/Tinymce/Resources/js/tinymce/plugins/youtube/js/vendor/jquery.js create mode 100644 local/modules/Tinymce/Resources/js/tinymce/plugins/youtube/langs/de.js create mode 100644 local/modules/Tinymce/Resources/js/tinymce/plugins/youtube/langs/en.js create mode 100644 local/modules/Tinymce/Resources/js/tinymce/plugins/youtube/langs/es.js create mode 100644 local/modules/Tinymce/Resources/js/tinymce/plugins/youtube/langs/fr_FR.js create mode 100644 local/modules/Tinymce/Resources/js/tinymce/plugins/youtube/langs/hu.js create mode 100644 local/modules/Tinymce/Resources/js/tinymce/plugins/youtube/langs/it.js create mode 100644 local/modules/Tinymce/Resources/js/tinymce/plugins/youtube/langs/pl.js create mode 100644 local/modules/Tinymce/Resources/js/tinymce/plugins/youtube/langs/pt_BR.js create mode 100644 local/modules/Tinymce/Resources/js/tinymce/plugins/youtube/langs/ru.js create mode 100644 local/modules/Tinymce/Resources/js/tinymce/plugins/youtube/plugin.js create mode 100644 local/modules/Tinymce/Resources/js/tinymce/plugins/youtube/plugin.min.js create mode 100644 local/modules/Tinymce/Resources/js/tinymce/plugins/youtube/view/forms.html create mode 100644 local/modules/Tinymce/Resources/js/tinymce/plugins/youtube/youtube.html create mode 100644 local/modules/Tinymce/Resources/js/tinymce/skins/lightgray/content.inline.min.css create mode 100644 local/modules/Tinymce/Resources/js/tinymce/skins/lightgray/content.min.css create mode 100644 local/modules/Tinymce/Resources/js/tinymce/skins/lightgray/fonts/tinymce-small.eot create mode 100644 local/modules/Tinymce/Resources/js/tinymce/skins/lightgray/fonts/tinymce-small.svg create mode 100644 local/modules/Tinymce/Resources/js/tinymce/skins/lightgray/fonts/tinymce-small.ttf create mode 100644 local/modules/Tinymce/Resources/js/tinymce/skins/lightgray/fonts/tinymce-small.woff create mode 100644 local/modules/Tinymce/Resources/js/tinymce/skins/lightgray/fonts/tinymce.eot create mode 100644 local/modules/Tinymce/Resources/js/tinymce/skins/lightgray/fonts/tinymce.svg create mode 100644 local/modules/Tinymce/Resources/js/tinymce/skins/lightgray/fonts/tinymce.ttf create mode 100644 local/modules/Tinymce/Resources/js/tinymce/skins/lightgray/fonts/tinymce.woff create mode 100644 local/modules/Tinymce/Resources/js/tinymce/skins/lightgray/img/anchor.gif create mode 100644 local/modules/Tinymce/Resources/js/tinymce/skins/lightgray/img/loader.gif create mode 100644 local/modules/Tinymce/Resources/js/tinymce/skins/lightgray/img/object.gif create mode 100644 local/modules/Tinymce/Resources/js/tinymce/skins/lightgray/img/trans.gif create mode 100644 local/modules/Tinymce/Resources/js/tinymce/skins/lightgray/skin.ie7.min.css create mode 100644 local/modules/Tinymce/Resources/js/tinymce/skins/lightgray/skin.min.css create mode 100644 local/modules/Tinymce/Resources/js/tinymce/themes/modern/theme.min.js create mode 100644 local/modules/Tinymce/Resources/js/tinymce/tinymce.min.js create mode 100644 local/modules/Tinymce/Smarty/TinyMCELanguage.php create mode 100644 local/modules/Tinymce/Tinymce.php create mode 100644 local/modules/Tinymce/composer.json create mode 100644 local/modules/Tinymce/templates/backOffice/default/assets/css/editor.less create mode 100644 local/modules/Tinymce/templates/backOffice/default/module_configuration.html create mode 100644 local/modules/Tinymce/templates/backOffice/default/tinymce_init.tpl create mode 100644 local/modules/VirtualProductControl/Config/config.xml create mode 100644 local/modules/VirtualProductControl/Config/module.xml create mode 100644 local/modules/VirtualProductControl/Hook/VirtualProductHook.php create mode 100644 local/modules/VirtualProductControl/I18n/backOffice/default/de_DE.php create mode 100644 local/modules/VirtualProductControl/I18n/backOffice/default/en_US.php create mode 100644 local/modules/VirtualProductControl/I18n/backOffice/default/fr_FR.php create mode 100644 local/modules/VirtualProductControl/I18n/backOffice/default/it_IT.php create mode 100644 local/modules/VirtualProductControl/I18n/backOffice/default/tr_TR.php create mode 100644 local/modules/VirtualProductControl/I18n/de_DE.php create mode 100644 local/modules/VirtualProductControl/I18n/en_US.php create mode 100644 local/modules/VirtualProductControl/I18n/fr_FR.php create mode 100644 local/modules/VirtualProductControl/I18n/it_IT.php create mode 100644 local/modules/VirtualProductControl/I18n/ru_RU.php create mode 100644 local/modules/VirtualProductControl/I18n/tr_TR.php create mode 100644 local/modules/VirtualProductControl/LICENSE.txt create mode 100644 local/modules/VirtualProductControl/VirtualProductControl.php create mode 100644 local/modules/VirtualProductControl/composer.json create mode 100644 local/modules/VirtualProductControl/templates/backOffice/default/virtual-delivery-warning.html create mode 100644 local/modules/VirtualProductDelivery/Config/config.xml create mode 100644 local/modules/VirtualProductDelivery/Config/module.xml create mode 100644 local/modules/VirtualProductDelivery/EventListeners/SendMail.php create mode 100644 local/modules/VirtualProductDelivery/EventListeners/VirtualProductEvents.php create mode 100644 local/modules/VirtualProductDelivery/Events/VirtualProductDeliveryEvents.php create mode 100644 local/modules/VirtualProductDelivery/Hook/HookManager.php create mode 100644 local/modules/VirtualProductDelivery/I18n/de_DE.php create mode 100644 local/modules/VirtualProductDelivery/I18n/email/default/en_US.php create mode 100644 local/modules/VirtualProductDelivery/I18n/email/default/fr_FR.php create mode 100644 local/modules/VirtualProductDelivery/I18n/email/default/it_IT.php create mode 100644 local/modules/VirtualProductDelivery/I18n/email/default/ru_RU.php create mode 100644 local/modules/VirtualProductDelivery/I18n/email/default/tr_TR.php create mode 100644 local/modules/VirtualProductDelivery/I18n/en_US.php create mode 100644 local/modules/VirtualProductDelivery/I18n/fr_FR.php create mode 100644 local/modules/VirtualProductDelivery/I18n/frontOffice/default/de_DE.php create mode 100644 local/modules/VirtualProductDelivery/I18n/frontOffice/default/en_US.php create mode 100644 local/modules/VirtualProductDelivery/I18n/frontOffice/default/fr_FR.php create mode 100644 local/modules/VirtualProductDelivery/I18n/frontOffice/default/it_IT.php create mode 100644 local/modules/VirtualProductDelivery/I18n/frontOffice/default/ru_RU.php create mode 100644 local/modules/VirtualProductDelivery/I18n/frontOffice/default/tr_TR.php create mode 100644 local/modules/VirtualProductDelivery/I18n/it_IT.php create mode 100644 local/modules/VirtualProductDelivery/I18n/pdf/default/de_DE.php create mode 100644 local/modules/VirtualProductDelivery/I18n/pdf/default/en_US.php create mode 100644 local/modules/VirtualProductDelivery/I18n/pdf/default/fr_FR.php create mode 100644 local/modules/VirtualProductDelivery/I18n/pdf/default/it_IT.php create mode 100644 local/modules/VirtualProductDelivery/I18n/pdf/default/ru_RU.php create mode 100644 local/modules/VirtualProductDelivery/I18n/pdf/default/tr_TR.php create mode 100644 local/modules/VirtualProductDelivery/I18n/ru_RU.php create mode 100644 local/modules/VirtualProductDelivery/I18n/tr_TR.php create mode 100644 local/modules/VirtualProductDelivery/LICENSE.txt create mode 100644 local/modules/VirtualProductDelivery/VirtualProductDelivery.php create mode 100644 local/modules/VirtualProductDelivery/composer.json create mode 100644 local/modules/VirtualProductDelivery/templates/email/default/virtual-product-download.html create mode 100644 local/modules/VirtualProductDelivery/templates/email/default/virtual-product-download.txt create mode 100644 local/modules/VirtualProductDelivery/templates/frontOffice/default/account-order-after-products.html create mode 100644 local/modules/VirtualProductDelivery/templates/frontOffice/default/delivery-address.html create mode 100644 local/modules/VirtualProductDelivery/templates/pdf/default/delivery-address.html create mode 100644 php-cs create mode 100644 php-cs.bat create mode 100644 phpunit.xml create mode 100644 reset_install.bat create mode 100644 reset_install.sh create mode 100644 run-tests.sh create mode 100644 setup/.gitkeep create mode 100644 setup/.htaccess create mode 100644 setup/I18n/ar_SA.php create mode 100644 setup/I18n/cs_CZ.php create mode 100644 setup/I18n/de_DE.php create mode 100644 setup/I18n/el_GR.php create mode 100644 setup/I18n/en_US.php create mode 100644 setup/I18n/es_ES.php create mode 100644 setup/I18n/fa_IR.php create mode 100644 setup/I18n/fr_FR.php create mode 100644 setup/I18n/hu_HU.php create mode 100644 setup/I18n/id_ID.php create mode 100644 setup/I18n/it_IT.php create mode 100644 setup/I18n/pl_PL.php create mode 100644 setup/I18n/pt_BR.php create mode 100644 setup/I18n/pt_PT.php create mode 100644 setup/I18n/ru_RU.php create mode 100644 setup/I18n/sk_SK.php create mode 100644 setup/I18n/tr_TR.php create mode 100644 setup/I18n/uk_UA.php create mode 100644 setup/Readme.md create mode 100644 setup/composer.json create mode 100644 setup/faker-assets/FreeSans.ttf create mode 100644 setup/faker.php create mode 100644 setup/faker_100categories_1000products_4locales.php create mode 100644 setup/faker_add_ecotax.php create mode 100644 setup/import.php create mode 100644 setup/import/brand.csv create mode 100644 setup/import/categories.csv create mode 100644 setup/import/colors.csv create mode 100644 setup/import/contents.csv create mode 100644 setup/import/folders.csv create mode 100644 setup/import/images/BRAND-1.png create mode 100644 setup/import/images/BRAND-2.png create mode 100644 setup/import/images/BRAND-3.png create mode 100644 setup/import/images/BRAND-4.png create mode 100644 setup/import/images/BRAND-5.png create mode 100644 setup/import/images/BRAND-6.png create mode 100644 setup/import/images/BRAND-7.png create mode 100644 setup/import/images/PROD001-1.jpg create mode 100644 setup/import/images/PROD001-2.jpg create mode 100644 setup/import/images/PROD001-3.jpg create mode 100644 setup/import/images/PROD001-4.jpg create mode 100644 setup/import/images/PROD001-5.jpg create mode 100644 setup/import/images/PROD002-1.jpg create mode 100644 setup/import/images/PROD002-2.jpg create mode 100644 setup/import/images/PROD002-3.jpg create mode 100644 setup/import/images/PROD002-4.jpg create mode 100644 setup/import/images/PROD002-5.jpg create mode 100644 setup/import/images/PROD002-6.jpg create mode 100644 setup/import/images/PROD003-1.jpg create mode 100644 setup/import/images/PROD003-2.jpg create mode 100644 setup/import/images/PROD003-3.jpg create mode 100644 setup/import/images/PROD004-1.jpg create mode 100644 setup/import/images/PROD004-2.jpg create mode 100644 setup/import/images/PROD005-1.jpg create mode 100644 setup/import/images/PROD005-2.jpg create mode 100644 setup/import/images/PROD005-3.jpg create mode 100644 setup/import/images/PROD005-4.jpg create mode 100644 setup/import/images/PROD005-5.jpg create mode 100644 setup/import/images/PROD005-6.jpg create mode 100644 setup/import/images/PROD006-1.jpg create mode 100644 setup/import/images/PROD006-2.jpg create mode 100644 setup/import/images/PROD006-3.jpg create mode 100644 setup/import/images/PROD006-4.jpg create mode 100644 setup/import/images/PROD006-5.jpg create mode 100644 setup/import/images/PROD006-6.jpg create mode 100644 setup/import/images/PROD007-1.jpg create mode 100644 setup/import/images/PROD007-2.jpg create mode 100644 setup/import/images/PROD007-3.jpg create mode 100644 setup/import/images/PROD007-4.jpg create mode 100644 setup/import/images/PROD008-1.jpg create mode 100644 setup/import/images/PROD008-2.jpg create mode 100644 setup/import/images/PROD008-3.jpg create mode 100644 setup/import/images/PROD008-4.jpg create mode 100644 setup/import/images/PROD008-5.jpg create mode 100644 setup/import/images/PROD009-1.jpg create mode 100644 setup/import/images/PROD009-2.jpg create mode 100644 setup/import/images/PROD009-3.jpg create mode 100644 setup/import/images/PROD010-1.jpg create mode 100644 setup/import/images/PROD010-2.jpg create mode 100644 setup/import/images/PROD010-3.jpg create mode 100644 setup/import/images/PROD010-4.jpg create mode 100644 setup/import/images/PROD011-1.jpg create mode 100644 setup/import/images/PROD011-2.jpg create mode 100644 setup/import/images/PROD011-3.jpg create mode 100644 setup/import/images/PROD011-4.jpg create mode 100644 setup/import/images/PROD012-1.jpg create mode 100644 setup/import/images/PROD012-2.jpg create mode 100644 setup/import/images/PROD013-1.jpg create mode 100644 setup/import/images/PROD014-1.jpg create mode 100644 setup/import/images/PROD014-2.jpg create mode 100644 setup/import/images/PROD014-3.jpg create mode 100644 setup/import/images/PROD014-4.jpg create mode 100644 setup/import/images/PROD015-1.jpg create mode 100644 setup/import/images/PROD015-2.jpg create mode 100644 setup/import/images/PROD016-1.jpg create mode 100644 setup/import/images/PROD017-1.jpg create mode 100644 setup/import/images/PROD017-2.jpg create mode 100644 setup/import/images/PROD017-3.jpg create mode 100644 setup/import/images/PROD017-4.jpg create mode 100644 setup/import/images/PROD018-1.jpg create mode 100644 setup/import/images/PROD019-1.jpg create mode 100644 setup/import/images/PROD019-2.jpg create mode 100644 setup/import/images/PROD019-3.jpg create mode 100644 setup/import/images/PROD019-4.jpg create mode 100644 setup/import/images/PROD019-5.jpg create mode 100644 setup/import/images/PROD020-1.jpg create mode 100644 setup/import/images/PROD021-1.jpg create mode 100644 setup/import/images/PROD021-2.jpg create mode 100644 setup/import/images/PROD021-3.jpg create mode 100644 setup/import/images/PROD021-4.jpg create mode 100644 setup/import/images/PROD022-1.jpg create mode 100644 setup/import/images/PROD022-2.jpg create mode 100644 setup/import/images/PROD022-3.jpg create mode 100644 setup/import/images/PROD022-4.jpg create mode 100644 setup/import/images/PROD022-5.jpg create mode 100644 setup/import/images/PROD023-1.jpg create mode 100644 setup/import/images/PROD023-2.jpg create mode 100644 setup/import/images/PROD023-3.jpg create mode 100644 setup/import/images/PROD023-4.jpg create mode 100644 setup/import/images/PROD023-5.jpg create mode 100644 setup/import/images/PROD023-6.jpg create mode 100644 setup/import/images/PROD024-1.jpg create mode 100644 setup/import/images/PROD024-2.jpg create mode 100644 setup/import/images/PROD024-3.jpg create mode 100644 setup/import/images/PROD024-4.jpg create mode 100644 setup/import/images/PROD024-5.jpg create mode 100644 setup/import/images/PROD025-1.jpg create mode 100644 setup/import/images/PROD025-2.jpg create mode 100644 setup/import/images/PROD025-3.jpg create mode 100644 setup/import/images/PROD026-1.jpg create mode 100644 setup/import/images/PROD027-1.jpg create mode 100644 setup/import/images/PROD028-1.jpg create mode 100644 setup/import/images/PROD029-1.jpg create mode 100644 setup/import/images/PROD030-1.jpg create mode 100644 setup/import/images/PROD030-2.jpg create mode 100644 setup/import/images/PROD030-3.jpg create mode 100644 setup/import/images/PROD030-4.jpg create mode 100644 setup/import/materials.csv create mode 100644 setup/import/products.csv create mode 100644 setup/insert.sql create mode 100644 setup/insert.sql.tpl create mode 100644 setup/tax_faker.php create mode 100644 setup/thelia.sql create mode 100644 setup/update.php create mode 100644 setup/update/instruction/2.3.0-alpha1.md create mode 100644 setup/update/php/.gitkeep create mode 100644 setup/update/php/2.0.7.php create mode 100644 setup/update/php/2.1.3.php create mode 100644 setup/update/php/2.2.0-beta1.php create mode 100644 setup/update/php/2.2.0-beta3.php create mode 100644 setup/update/php/2.3.0-alpha2.php create mode 100644 setup/update/php/2.4.0.php create mode 100644 setup/update/sql/.gitkeep create mode 100644 setup/update/sql/2.0.0-RC1.sql create mode 100644 setup/update/sql/2.0.0-beta2.sql create mode 100644 setup/update/sql/2.0.0-beta3.sql create mode 100644 setup/update/sql/2.0.0-beta4.sql create mode 100644 setup/update/sql/2.0.0.sql create mode 100644 setup/update/sql/2.0.1.sql create mode 100644 setup/update/sql/2.0.10.sql create mode 100644 setup/update/sql/2.0.11.sql create mode 100644 setup/update/sql/2.0.12.sql create mode 100644 setup/update/sql/2.0.2.sql create mode 100644 setup/update/sql/2.0.3-beta.sql create mode 100644 setup/update/sql/2.0.3-beta2.sql create mode 100644 setup/update/sql/2.0.3.sql create mode 100644 setup/update/sql/2.0.4.sql create mode 100644 setup/update/sql/2.0.5.sql create mode 100644 setup/update/sql/2.0.6.sql create mode 100644 setup/update/sql/2.0.7.sql create mode 100644 setup/update/sql/2.0.8.sql create mode 100644 setup/update/sql/2.0.9.sql create mode 100644 setup/update/sql/2.1.0-alpha1.sql create mode 100644 setup/update/sql/2.1.0-alpha2.sql create mode 100644 setup/update/sql/2.1.0-beta1.sql create mode 100644 setup/update/sql/2.1.0-beta2.sql create mode 100644 setup/update/sql/2.1.0.sql create mode 100644 setup/update/sql/2.1.1.sql create mode 100644 setup/update/sql/2.1.10.sql create mode 100644 setup/update/sql/2.1.11.sql create mode 100644 setup/update/sql/2.1.2.sql create mode 100644 setup/update/sql/2.1.3.sql create mode 100644 setup/update/sql/2.1.4.sql create mode 100644 setup/update/sql/2.1.5.sql create mode 100644 setup/update/sql/2.1.6.sql create mode 100644 setup/update/sql/2.1.7.sql create mode 100644 setup/update/sql/2.1.8.sql create mode 100644 setup/update/sql/2.1.9.sql create mode 100644 setup/update/sql/2.2.0-alpha1.sql create mode 100644 setup/update/sql/2.2.0-alpha2.sql create mode 100644 setup/update/sql/2.2.0-beta1.sql create mode 100644 setup/update/sql/2.2.0-beta2.sql create mode 100644 setup/update/sql/2.2.0-beta3.sql create mode 100644 setup/update/sql/2.2.0.sql create mode 100644 setup/update/sql/2.2.1.sql create mode 100644 setup/update/sql/2.2.2.sql create mode 100644 setup/update/sql/2.2.3.sql create mode 100644 setup/update/sql/2.2.4.sql create mode 100644 setup/update/sql/2.2.6.sql create mode 100644 setup/update/sql/2.3.0-alpha1.sql create mode 100644 setup/update/sql/2.3.0-alpha2.sql create mode 100644 setup/update/sql/2.3.0-beta1.sql create mode 100644 setup/update/sql/2.3.0-beta2.sql create mode 100644 setup/update/sql/2.3.0.sql create mode 100644 setup/update/sql/2.3.1.sql create mode 100644 setup/update/sql/2.3.2.sql create mode 100644 setup/update/sql/2.3.3.sql create mode 100644 setup/update/sql/2.3.4.sql create mode 100644 setup/update/sql/2.3.5.sql create mode 100644 setup/update/sql/2.4.0-alpha1.sql create mode 100644 setup/update/sql/2.4.0-alpha2.sql create mode 100644 setup/update/sql/2.4.0.sql create mode 100644 setup/update/sql/2.4.1.sql create mode 100644 setup/update/sql/2.4.2.sql create mode 100644 setup/update/sql/2.4.3.sql create mode 100644 setup/update/tpl/2.0.0-RC1.sql.tpl create mode 100644 setup/update/tpl/2.0.0-beta2.sql.tpl create mode 100644 setup/update/tpl/2.0.0-beta3.sql.tpl create mode 100644 setup/update/tpl/2.0.0-beta4.sql.tpl create mode 100644 setup/update/tpl/2.0.0.sql.tpl create mode 100644 setup/update/tpl/2.0.1.sql.tpl create mode 100644 setup/update/tpl/2.0.10.sql.tpl create mode 100644 setup/update/tpl/2.0.11.sql.tpl create mode 100644 setup/update/tpl/2.0.12.sql.tpl create mode 100644 setup/update/tpl/2.0.2.sql.tpl create mode 100644 setup/update/tpl/2.0.3-beta.sql.tpl create mode 100644 setup/update/tpl/2.0.3-beta2.sql.tpl create mode 100644 setup/update/tpl/2.0.3.sql.tpl create mode 100644 setup/update/tpl/2.0.4.sql.tpl create mode 100644 setup/update/tpl/2.0.5.sql.tpl create mode 100644 setup/update/tpl/2.0.6.sql.tpl create mode 100644 setup/update/tpl/2.0.7.sql.tpl create mode 100644 setup/update/tpl/2.0.8.sql.tpl create mode 100644 setup/update/tpl/2.0.9.sql.tpl create mode 100644 setup/update/tpl/2.1.0-alpha1.sql.tpl create mode 100644 setup/update/tpl/2.1.0-alpha2.sql.tpl create mode 100644 setup/update/tpl/2.1.0-beta1.sql.tpl create mode 100644 setup/update/tpl/2.1.0-beta2.sql.tpl create mode 100644 setup/update/tpl/2.1.0.sql.tpl create mode 100644 setup/update/tpl/2.1.1.sql.tpl create mode 100644 setup/update/tpl/2.1.10.sql.tpl create mode 100644 setup/update/tpl/2.1.11.sql.tpl create mode 100644 setup/update/tpl/2.1.2.sql.tpl create mode 100644 setup/update/tpl/2.1.3.sql.tpl create mode 100644 setup/update/tpl/2.1.4.sql.tpl create mode 100644 setup/update/tpl/2.1.5.sql.tpl create mode 100644 setup/update/tpl/2.1.6.sql.tpl create mode 100644 setup/update/tpl/2.1.7.sql.tpl create mode 100644 setup/update/tpl/2.1.8.sql.tpl create mode 100644 setup/update/tpl/2.1.9.sql.tpl create mode 100644 setup/update/tpl/2.2.0-alpha1.sql.tpl create mode 100644 setup/update/tpl/2.2.0-alpha2.sql.tpl create mode 100644 setup/update/tpl/2.2.0-beta1.sql.tpl create mode 100644 setup/update/tpl/2.2.0-beta2.sql.tpl create mode 100644 setup/update/tpl/2.2.0-beta3.sql.tpl create mode 100644 setup/update/tpl/2.2.0.sql.tpl create mode 100644 setup/update/tpl/2.2.1.sql.tpl create mode 100644 setup/update/tpl/2.2.2.sql.tpl create mode 100644 setup/update/tpl/2.2.3.sql.tpl create mode 100644 setup/update/tpl/2.2.4.sql.tpl create mode 100644 setup/update/tpl/2.2.6.sql.tpl create mode 100644 setup/update/tpl/2.3.0-alpha1.sql.tpl create mode 100644 setup/update/tpl/2.3.0-alpha2.sql.tpl create mode 100644 setup/update/tpl/2.3.0-beta1.sql.tpl create mode 100644 setup/update/tpl/2.3.0-beta2.sql.tpl create mode 100644 setup/update/tpl/2.3.0.sql.tpl create mode 100644 setup/update/tpl/2.3.1.sql.tpl create mode 100644 setup/update/tpl/2.3.2.sql.tpl create mode 100644 setup/update/tpl/2.3.3.sql.tpl create mode 100644 setup/update/tpl/2.3.4.sql.tpl create mode 100644 setup/update/tpl/2.3.5.sql.tpl create mode 100644 setup/update/tpl/2.4.0-alpha1.sql.tpl create mode 100644 setup/update/tpl/2.4.0-alpha2.sql.tpl create mode 100644 setup/update/tpl/2.4.0.sql.tpl create mode 100644 setup/update/tpl/2.4.1.sql.tpl create mode 100644 setup/update/tpl/2.4.2.sql.tpl create mode 100644 setup/update/tpl/2.4.3.sql.tpl create mode 100644 templates/backOffice/default/404.html create mode 100644 templates/backOffice/default/I18n/ar_SA.php create mode 100644 templates/backOffice/default/I18n/cs_CZ.php create mode 100644 templates/backOffice/default/I18n/de_DE.php create mode 100644 templates/backOffice/default/I18n/el_GR.php create mode 100644 templates/backOffice/default/I18n/en_US.php create mode 100644 templates/backOffice/default/I18n/es_ES.php create mode 100644 templates/backOffice/default/I18n/fa_IR.php create mode 100644 templates/backOffice/default/I18n/fr_FR.php create mode 100644 templates/backOffice/default/I18n/he_IL.php create mode 100644 templates/backOffice/default/I18n/hu_HU.php create mode 100644 templates/backOffice/default/I18n/id_ID.php create mode 100644 templates/backOffice/default/I18n/it_IT.php create mode 100644 templates/backOffice/default/I18n/nl_NL.php create mode 100644 templates/backOffice/default/I18n/pl_PL.php create mode 100644 templates/backOffice/default/I18n/pt_BR.php create mode 100644 templates/backOffice/default/I18n/pt_PT.php create mode 100644 templates/backOffice/default/I18n/ru_RU.php create mode 100644 templates/backOffice/default/I18n/sk_SK.php create mode 100644 templates/backOffice/default/I18n/tr_TR.php create mode 100644 templates/backOffice/default/I18n/uk_UA.php create mode 100644 templates/backOffice/default/I18n/zh_CN.php create mode 100644 templates/backOffice/default/LICENSE.txt create mode 100644 templates/backOffice/default/Readme.md create mode 100644 templates/backOffice/default/admin-layout.tpl create mode 100644 templates/backOffice/default/admin-logs.html create mode 100644 templates/backOffice/default/administrators.html create mode 100644 templates/backOffice/default/advanced-configuration.html create mode 100644 templates/backOffice/default/ajax/export-modal.html create mode 100644 templates/backOffice/default/ajax/import-modal.html create mode 100644 templates/backOffice/default/ajax/language-update-modal.html create mode 100644 templates/backOffice/default/ajax/logger.html create mode 100644 templates/backOffice/default/ajax/module-information.html create mode 100644 templates/backOffice/default/ajax/product-attributes-tab.html create mode 100644 templates/backOffice/default/ajax/product-related-tab.html create mode 100644 templates/backOffice/default/ajax/pse-image-document-assoc-modal.html create mode 100644 templates/backOffice/default/ajax/sale-edit-product-attributes.html create mode 100644 templates/backOffice/default/ajax/sale-edit-products.html create mode 100644 templates/backOffice/default/ajax/template-attribute-list.html create mode 100644 templates/backOffice/default/ajax/template-feature-list.html create mode 100644 templates/backOffice/default/api.html create mode 100644 templates/backOffice/default/assets/css/styles.css create mode 100644 templates/backOffice/default/assets/fonts/bootstrap/glyphicons-halflings-regular.eot create mode 100644 templates/backOffice/default/assets/fonts/bootstrap/glyphicons-halflings-regular.svg create mode 100644 templates/backOffice/default/assets/fonts/bootstrap/glyphicons-halflings-regular.ttf create mode 100644 templates/backOffice/default/assets/fonts/bootstrap/glyphicons-halflings-regular.woff create mode 100644 templates/backOffice/default/assets/fonts/thelia/thelia.eot create mode 100644 templates/backOffice/default/assets/fonts/thelia/thelia.svg create mode 100644 templates/backOffice/default/assets/fonts/thelia/thelia.ttf create mode 100644 templates/backOffice/default/assets/fonts/thelia/thelia.woff create mode 100644 templates/backOffice/default/assets/img/ajax-loader.gif create mode 100644 templates/backOffice/default/assets/img/bg.jpg create mode 100644 templates/backOffice/default/assets/img/clear.png create mode 100644 templates/backOffice/default/assets/img/deconnexion.png create mode 100644 templates/backOffice/default/assets/img/favicon.ico create mode 100644 templates/backOffice/default/assets/img/flags/ad.png create mode 100644 templates/backOffice/default/assets/img/flags/ae.png create mode 100644 templates/backOffice/default/assets/img/flags/af.png create mode 100644 templates/backOffice/default/assets/img/flags/ag.png create mode 100644 templates/backOffice/default/assets/img/flags/ai.png create mode 100644 templates/backOffice/default/assets/img/flags/al.png create mode 100644 templates/backOffice/default/assets/img/flags/am.png create mode 100644 templates/backOffice/default/assets/img/flags/an.png create mode 100644 templates/backOffice/default/assets/img/flags/ao.png create mode 100644 templates/backOffice/default/assets/img/flags/aq.png create mode 100644 templates/backOffice/default/assets/img/flags/ar.png create mode 100644 templates/backOffice/default/assets/img/flags/as.png create mode 100644 templates/backOffice/default/assets/img/flags/at.png create mode 100644 templates/backOffice/default/assets/img/flags/au.png create mode 100644 templates/backOffice/default/assets/img/flags/aw.png create mode 100644 templates/backOffice/default/assets/img/flags/ax.png create mode 100644 templates/backOffice/default/assets/img/flags/az.png create mode 100644 templates/backOffice/default/assets/img/flags/ba.png create mode 100644 templates/backOffice/default/assets/img/flags/bb.png create mode 100644 templates/backOffice/default/assets/img/flags/bd.png create mode 100644 templates/backOffice/default/assets/img/flags/be.png create mode 100644 templates/backOffice/default/assets/img/flags/bf.png create mode 100644 templates/backOffice/default/assets/img/flags/bg.png create mode 100644 templates/backOffice/default/assets/img/flags/bh.png create mode 100644 templates/backOffice/default/assets/img/flags/bi.png create mode 100644 templates/backOffice/default/assets/img/flags/bj.png create mode 100644 templates/backOffice/default/assets/img/flags/bl.png create mode 100644 templates/backOffice/default/assets/img/flags/bm.png create mode 100644 templates/backOffice/default/assets/img/flags/bn.png create mode 100644 templates/backOffice/default/assets/img/flags/bo.png create mode 100644 templates/backOffice/default/assets/img/flags/br.png create mode 100644 templates/backOffice/default/assets/img/flags/bs.png create mode 100644 templates/backOffice/default/assets/img/flags/bt.png create mode 100644 templates/backOffice/default/assets/img/flags/bw.png create mode 100644 templates/backOffice/default/assets/img/flags/by.png create mode 100644 templates/backOffice/default/assets/img/flags/bz.png create mode 100644 templates/backOffice/default/assets/img/flags/ca.png create mode 100644 templates/backOffice/default/assets/img/flags/cc.png create mode 100644 templates/backOffice/default/assets/img/flags/cd.png create mode 100644 templates/backOffice/default/assets/img/flags/cf.png create mode 100644 templates/backOffice/default/assets/img/flags/cg.png create mode 100644 templates/backOffice/default/assets/img/flags/ch.png create mode 100644 templates/backOffice/default/assets/img/flags/ci.png create mode 100644 templates/backOffice/default/assets/img/flags/ck.png create mode 100644 templates/backOffice/default/assets/img/flags/cl.png create mode 100644 templates/backOffice/default/assets/img/flags/cm.png create mode 100644 templates/backOffice/default/assets/img/flags/cn.png create mode 100644 templates/backOffice/default/assets/img/flags/co.png create mode 100644 templates/backOffice/default/assets/img/flags/cr.png create mode 100644 templates/backOffice/default/assets/img/flags/cs.png create mode 100644 templates/backOffice/default/assets/img/flags/cu.png create mode 100644 templates/backOffice/default/assets/img/flags/cv.png create mode 100644 templates/backOffice/default/assets/img/flags/cw.png create mode 100644 templates/backOffice/default/assets/img/flags/cx.png create mode 100644 templates/backOffice/default/assets/img/flags/cy.png create mode 100644 templates/backOffice/default/assets/img/flags/de.png create mode 100644 templates/backOffice/default/assets/img/flags/dj.png create mode 100644 templates/backOffice/default/assets/img/flags/dk.png create mode 100644 templates/backOffice/default/assets/img/flags/dm.png create mode 100644 templates/backOffice/default/assets/img/flags/do.png create mode 100644 templates/backOffice/default/assets/img/flags/dz.png create mode 100644 templates/backOffice/default/assets/img/flags/ec.png create mode 100644 templates/backOffice/default/assets/img/flags/ee.png create mode 100644 templates/backOffice/default/assets/img/flags/eg.png create mode 100644 templates/backOffice/default/assets/img/flags/eh.png create mode 100644 templates/backOffice/default/assets/img/flags/en.png create mode 100644 templates/backOffice/default/assets/img/flags/er.png create mode 100644 templates/backOffice/default/assets/img/flags/es.png create mode 100644 templates/backOffice/default/assets/img/flags/et.png create mode 100644 templates/backOffice/default/assets/img/flags/eu.png create mode 100644 templates/backOffice/default/assets/img/flags/fi.png create mode 100644 templates/backOffice/default/assets/img/flags/fj.png create mode 100644 templates/backOffice/default/assets/img/flags/fk.png create mode 100644 templates/backOffice/default/assets/img/flags/fm.png create mode 100644 templates/backOffice/default/assets/img/flags/fo.png create mode 100644 templates/backOffice/default/assets/img/flags/fr.png create mode 100644 templates/backOffice/default/assets/img/flags/ga.png create mode 100644 templates/backOffice/default/assets/img/flags/gb.png create mode 100644 templates/backOffice/default/assets/img/flags/gd.png create mode 100644 templates/backOffice/default/assets/img/flags/ge.png create mode 100644 templates/backOffice/default/assets/img/flags/gg.png create mode 100644 templates/backOffice/default/assets/img/flags/gh.png create mode 100644 templates/backOffice/default/assets/img/flags/gi.png create mode 100644 templates/backOffice/default/assets/img/flags/gl.png create mode 100644 templates/backOffice/default/assets/img/flags/gm.png create mode 100644 templates/backOffice/default/assets/img/flags/gn.png create mode 100644 templates/backOffice/default/assets/img/flags/gq.png create mode 100644 templates/backOffice/default/assets/img/flags/gr.png create mode 100644 templates/backOffice/default/assets/img/flags/gs.png create mode 100644 templates/backOffice/default/assets/img/flags/gt.png create mode 100644 templates/backOffice/default/assets/img/flags/gu.png create mode 100644 templates/backOffice/default/assets/img/flags/gw.png create mode 100644 templates/backOffice/default/assets/img/flags/gy.png create mode 100644 templates/backOffice/default/assets/img/flags/hk.png create mode 100644 templates/backOffice/default/assets/img/flags/hn.png create mode 100644 templates/backOffice/default/assets/img/flags/hr.png create mode 100644 templates/backOffice/default/assets/img/flags/ht.png create mode 100644 templates/backOffice/default/assets/img/flags/hu.png create mode 100644 templates/backOffice/default/assets/img/flags/ic.png create mode 100644 templates/backOffice/default/assets/img/flags/id.png create mode 100644 templates/backOffice/default/assets/img/flags/ie.png create mode 100644 templates/backOffice/default/assets/img/flags/il.png create mode 100644 templates/backOffice/default/assets/img/flags/im.png create mode 100644 templates/backOffice/default/assets/img/flags/in.png create mode 100644 templates/backOffice/default/assets/img/flags/iq.png create mode 100644 templates/backOffice/default/assets/img/flags/ir.png create mode 100644 templates/backOffice/default/assets/img/flags/is.png create mode 100644 templates/backOffice/default/assets/img/flags/it.png create mode 100644 templates/backOffice/default/assets/img/flags/je.png create mode 100644 templates/backOffice/default/assets/img/flags/jm.png create mode 100644 templates/backOffice/default/assets/img/flags/jo.png create mode 100644 templates/backOffice/default/assets/img/flags/jp.png create mode 100644 templates/backOffice/default/assets/img/flags/ke.png create mode 100644 templates/backOffice/default/assets/img/flags/kg.png create mode 100644 templates/backOffice/default/assets/img/flags/kh.png create mode 100644 templates/backOffice/default/assets/img/flags/ki.png create mode 100644 templates/backOffice/default/assets/img/flags/km.png create mode 100644 templates/backOffice/default/assets/img/flags/kn.png create mode 100644 templates/backOffice/default/assets/img/flags/kp.png create mode 100644 templates/backOffice/default/assets/img/flags/kr.png create mode 100644 templates/backOffice/default/assets/img/flags/kw.png create mode 100644 templates/backOffice/default/assets/img/flags/ky.png create mode 100644 templates/backOffice/default/assets/img/flags/kz.png create mode 100644 templates/backOffice/default/assets/img/flags/la.png create mode 100644 templates/backOffice/default/assets/img/flags/lb.png create mode 100644 templates/backOffice/default/assets/img/flags/lc.png create mode 100644 templates/backOffice/default/assets/img/flags/li.png create mode 100644 templates/backOffice/default/assets/img/flags/lk.png create mode 100644 templates/backOffice/default/assets/img/flags/lr.png create mode 100644 templates/backOffice/default/assets/img/flags/ls.png create mode 100644 templates/backOffice/default/assets/img/flags/lt.png create mode 100644 templates/backOffice/default/assets/img/flags/lu.png create mode 100644 templates/backOffice/default/assets/img/flags/lv.png create mode 100644 templates/backOffice/default/assets/img/flags/ly.png create mode 100644 templates/backOffice/default/assets/img/flags/ma.png create mode 100644 templates/backOffice/default/assets/img/flags/mc.png create mode 100644 templates/backOffice/default/assets/img/flags/md.png create mode 100644 templates/backOffice/default/assets/img/flags/me.png create mode 100644 templates/backOffice/default/assets/img/flags/mf.png create mode 100644 templates/backOffice/default/assets/img/flags/mg.png create mode 100644 templates/backOffice/default/assets/img/flags/mh.png create mode 100644 templates/backOffice/default/assets/img/flags/mk.png create mode 100644 templates/backOffice/default/assets/img/flags/ml.png create mode 100644 templates/backOffice/default/assets/img/flags/mm.png create mode 100644 templates/backOffice/default/assets/img/flags/mn.png create mode 100644 templates/backOffice/default/assets/img/flags/mo.png create mode 100644 templates/backOffice/default/assets/img/flags/mp.png create mode 100644 templates/backOffice/default/assets/img/flags/mq.png create mode 100644 templates/backOffice/default/assets/img/flags/mr.png create mode 100644 templates/backOffice/default/assets/img/flags/ms.png create mode 100644 templates/backOffice/default/assets/img/flags/mt.png create mode 100644 templates/backOffice/default/assets/img/flags/mu.png create mode 100644 templates/backOffice/default/assets/img/flags/mv.png create mode 100644 templates/backOffice/default/assets/img/flags/mw.png create mode 100644 templates/backOffice/default/assets/img/flags/mx.png create mode 100644 templates/backOffice/default/assets/img/flags/my.png create mode 100644 templates/backOffice/default/assets/img/flags/mz.png create mode 100644 templates/backOffice/default/assets/img/flags/na.png create mode 100644 templates/backOffice/default/assets/img/flags/nc.png create mode 100644 templates/backOffice/default/assets/img/flags/ne.png create mode 100644 templates/backOffice/default/assets/img/flags/nf.png create mode 100644 templates/backOffice/default/assets/img/flags/ng.png create mode 100644 templates/backOffice/default/assets/img/flags/ni.png create mode 100644 templates/backOffice/default/assets/img/flags/nl.png create mode 100644 templates/backOffice/default/assets/img/flags/no.png create mode 100644 templates/backOffice/default/assets/img/flags/np.png create mode 100644 templates/backOffice/default/assets/img/flags/nr.png create mode 100644 templates/backOffice/default/assets/img/flags/nu.png create mode 100644 templates/backOffice/default/assets/img/flags/nz.png create mode 100644 templates/backOffice/default/assets/img/flags/om.png create mode 100644 templates/backOffice/default/assets/img/flags/pa.png create mode 100644 templates/backOffice/default/assets/img/flags/pe.png create mode 100644 templates/backOffice/default/assets/img/flags/pf.png create mode 100644 templates/backOffice/default/assets/img/flags/pg.png create mode 100644 templates/backOffice/default/assets/img/flags/ph.png create mode 100644 templates/backOffice/default/assets/img/flags/pk.png create mode 100644 templates/backOffice/default/assets/img/flags/pl.png create mode 100644 templates/backOffice/default/assets/img/flags/pn.png create mode 100644 templates/backOffice/default/assets/img/flags/pr.png create mode 100644 templates/backOffice/default/assets/img/flags/ps.png create mode 100644 templates/backOffice/default/assets/img/flags/pt.png create mode 100644 templates/backOffice/default/assets/img/flags/pw.png create mode 100644 templates/backOffice/default/assets/img/flags/py.png create mode 100644 templates/backOffice/default/assets/img/flags/qa.png create mode 100644 templates/backOffice/default/assets/img/flags/ro.png create mode 100644 templates/backOffice/default/assets/img/flags/rs.png create mode 100644 templates/backOffice/default/assets/img/flags/ru.png create mode 100644 templates/backOffice/default/assets/img/flags/rw.png create mode 100644 templates/backOffice/default/assets/img/flags/sa.png create mode 100644 templates/backOffice/default/assets/img/flags/sb.png create mode 100644 templates/backOffice/default/assets/img/flags/sc.png create mode 100644 templates/backOffice/default/assets/img/flags/sd.png create mode 100644 templates/backOffice/default/assets/img/flags/se.png create mode 100644 templates/backOffice/default/assets/img/flags/sg.png create mode 100644 templates/backOffice/default/assets/img/flags/sh.png create mode 100644 templates/backOffice/default/assets/img/flags/si.png create mode 100644 templates/backOffice/default/assets/img/flags/sk.png create mode 100644 templates/backOffice/default/assets/img/flags/sl.png create mode 100644 templates/backOffice/default/assets/img/flags/sm.png create mode 100644 templates/backOffice/default/assets/img/flags/sn.png create mode 100644 templates/backOffice/default/assets/img/flags/so.png create mode 100644 templates/backOffice/default/assets/img/flags/sr.png create mode 100644 templates/backOffice/default/assets/img/flags/ss.png create mode 100644 templates/backOffice/default/assets/img/flags/st.png create mode 100644 templates/backOffice/default/assets/img/flags/sv.png create mode 100644 templates/backOffice/default/assets/img/flags/sy.png create mode 100644 templates/backOffice/default/assets/img/flags/sz.png create mode 100644 templates/backOffice/default/assets/img/flags/tc.png create mode 100644 templates/backOffice/default/assets/img/flags/td.png create mode 100644 templates/backOffice/default/assets/img/flags/tf.png create mode 100644 templates/backOffice/default/assets/img/flags/tg.png create mode 100644 templates/backOffice/default/assets/img/flags/th.png create mode 100644 templates/backOffice/default/assets/img/flags/tj.png create mode 100644 templates/backOffice/default/assets/img/flags/tk.png create mode 100644 templates/backOffice/default/assets/img/flags/tl.png create mode 100644 templates/backOffice/default/assets/img/flags/tm.png create mode 100644 templates/backOffice/default/assets/img/flags/tn.png create mode 100644 templates/backOffice/default/assets/img/flags/to.png create mode 100644 templates/backOffice/default/assets/img/flags/toto.png create mode 100644 templates/backOffice/default/assets/img/flags/tr.png create mode 100644 templates/backOffice/default/assets/img/flags/tt.png create mode 100644 templates/backOffice/default/assets/img/flags/tv.png create mode 100644 templates/backOffice/default/assets/img/flags/tw.png create mode 100644 templates/backOffice/default/assets/img/flags/tz.png create mode 100644 templates/backOffice/default/assets/img/flags/ua.png create mode 100644 templates/backOffice/default/assets/img/flags/ug.png create mode 100644 templates/backOffice/default/assets/img/flags/unknown.png create mode 100644 templates/backOffice/default/assets/img/flags/us.png create mode 100644 templates/backOffice/default/assets/img/flags/uy.png create mode 100644 templates/backOffice/default/assets/img/flags/uz.png create mode 100644 templates/backOffice/default/assets/img/flags/va.png create mode 100644 templates/backOffice/default/assets/img/flags/vc.png create mode 100644 templates/backOffice/default/assets/img/flags/ve.png create mode 100644 templates/backOffice/default/assets/img/flags/vg.png create mode 100644 templates/backOffice/default/assets/img/flags/vi.png create mode 100644 templates/backOffice/default/assets/img/flags/vn.png create mode 100644 templates/backOffice/default/assets/img/flags/vu.png create mode 100644 templates/backOffice/default/assets/img/flags/wf.png create mode 100644 templates/backOffice/default/assets/img/flags/ws.png create mode 100644 templates/backOffice/default/assets/img/flags/ye.png create mode 100644 templates/backOffice/default/assets/img/flags/yt.png create mode 100644 templates/backOffice/default/assets/img/flags/za.png create mode 100644 templates/backOffice/default/assets/img/flags/zm.png create mode 100644 templates/backOffice/default/assets/img/flags/zw.png create mode 100644 templates/backOffice/default/assets/img/header.jpg create mode 100644 templates/backOffice/default/assets/img/loading.gif create mode 100644 templates/backOffice/default/assets/img/logo-dark.png create mode 100644 templates/backOffice/default/assets/img/logo-light.png create mode 100644 templates/backOffice/default/assets/img/logo-thelia-34px.png create mode 100644 templates/backOffice/default/assets/img/logo-white.png create mode 100644 templates/backOffice/default/assets/img/logo.png create mode 100644 templates/backOffice/default/assets/img/top-bar-logo-save.png create mode 100644 templates/backOffice/default/assets/img/top-bar-logo.png create mode 100644 templates/backOffice/default/assets/js/bootstrap-datetimepicker/bootstrap-datetimepicker.min.css create mode 100644 templates/backOffice/default/assets/js/bootstrap-datetimepicker/bootstrap-datetimepicker.min.js create mode 100644 templates/backOffice/default/assets/js/bootstrap-editable/bootstrap-editable.js create mode 100644 templates/backOffice/default/assets/js/bootstrap-select/bootstrap-select.js create mode 100644 templates/backOffice/default/assets/js/bootstrap-switch/bootstrap-switch.js create mode 100644 templates/backOffice/default/assets/js/bootstrap/bootstrap.js create mode 100644 templates/backOffice/default/assets/js/cookie.js create mode 100644 templates/backOffice/default/assets/js/coupon.js create mode 100644 templates/backOffice/default/assets/js/document-upload.js create mode 100644 templates/backOffice/default/assets/js/dropzone.js create mode 100644 templates/backOffice/default/assets/js/image-picker/image-picker.css create mode 100644 templates/backOffice/default/assets/js/image-picker/image-picker.min.js create mode 100644 templates/backOffice/default/assets/js/image-upload.js create mode 100644 templates/backOffice/default/assets/js/jqplot/jquery.jqplot.min.js create mode 100644 templates/backOffice/default/assets/js/jqplot/plugins/jqplot.BezierCurveRenderer.min.js create mode 100644 templates/backOffice/default/assets/js/jqplot/plugins/jqplot.barRenderer.min.js create mode 100644 templates/backOffice/default/assets/js/jqplot/plugins/jqplot.blockRenderer.min.js create mode 100644 templates/backOffice/default/assets/js/jqplot/plugins/jqplot.bubbleRenderer.min.js create mode 100644 templates/backOffice/default/assets/js/jqplot/plugins/jqplot.canvasAxisLabelRenderer.min.js create mode 100644 templates/backOffice/default/assets/js/jqplot/plugins/jqplot.canvasAxisTickRenderer.min.js create mode 100644 templates/backOffice/default/assets/js/jqplot/plugins/jqplot.canvasOverlay.min.js create mode 100644 templates/backOffice/default/assets/js/jqplot/plugins/jqplot.canvasTextRenderer.min.js create mode 100644 templates/backOffice/default/assets/js/jqplot/plugins/jqplot.categoryAxisRenderer.min.js create mode 100644 templates/backOffice/default/assets/js/jqplot/plugins/jqplot.ciParser.min.js create mode 100644 templates/backOffice/default/assets/js/jqplot/plugins/jqplot.cursor.min.js create mode 100644 templates/backOffice/default/assets/js/jqplot/plugins/jqplot.dateAxisRenderer.min.js create mode 100644 templates/backOffice/default/assets/js/jqplot/plugins/jqplot.donutRenderer.min.js create mode 100644 templates/backOffice/default/assets/js/jqplot/plugins/jqplot.dragable.min.js create mode 100644 templates/backOffice/default/assets/js/jqplot/plugins/jqplot.enhancedLegendRenderer.min.js create mode 100644 templates/backOffice/default/assets/js/jqplot/plugins/jqplot.funnelRenderer.min.js create mode 100644 templates/backOffice/default/assets/js/jqplot/plugins/jqplot.highlighter.min.js create mode 100644 templates/backOffice/default/assets/js/jqplot/plugins/jqplot.json2.min.js create mode 100644 templates/backOffice/default/assets/js/jqplot/plugins/jqplot.logAxisRenderer.min.js create mode 100644 templates/backOffice/default/assets/js/jqplot/plugins/jqplot.mekkoAxisRenderer.min.js create mode 100644 templates/backOffice/default/assets/js/jqplot/plugins/jqplot.mekkoRenderer.min.js create mode 100644 templates/backOffice/default/assets/js/jqplot/plugins/jqplot.meterGaugeRenderer.min.js create mode 100644 templates/backOffice/default/assets/js/jqplot/plugins/jqplot.mobile.min.js create mode 100644 templates/backOffice/default/assets/js/jqplot/plugins/jqplot.ohlcRenderer.min.js create mode 100644 templates/backOffice/default/assets/js/jqplot/plugins/jqplot.pieRenderer.min.js create mode 100644 templates/backOffice/default/assets/js/jqplot/plugins/jqplot.pointLabels.min.js create mode 100644 templates/backOffice/default/assets/js/jqplot/plugins/jqplot.pyramidAxisRenderer.min.js create mode 100644 templates/backOffice/default/assets/js/jqplot/plugins/jqplot.pyramidGridRenderer.min.js create mode 100644 templates/backOffice/default/assets/js/jqplot/plugins/jqplot.pyramidRenderer.min.js create mode 100644 templates/backOffice/default/assets/js/jqplot/plugins/jqplot.trendline.min.js create mode 100644 templates/backOffice/default/assets/js/jquery-ui-1.10.3.custom.min.js create mode 100644 templates/backOffice/default/assets/js/jquery.min.js create mode 100644 templates/backOffice/default/assets/js/jquery.typewatch.js create mode 100644 templates/backOffice/default/assets/js/jquery.ui/jquery.ui.datepicker/i18n/jquery.ui.datepicker-es_ES.js create mode 100644 templates/backOffice/default/assets/js/jquery.ui/jquery.ui.datepicker/i18n/jquery.ui.datepicker-fr_FR.js create mode 100644 templates/backOffice/default/assets/js/jquery.ui/jquery.ui.datepicker/i18n/jquery.ui.datepicker-it_IT.js.js create mode 100644 templates/backOffice/default/assets/js/jquery.ui/jquery.ui.datepicker/i18n/readme.txt create mode 100644 templates/backOffice/default/assets/js/jquery.ui/jquery.ui.datepicker/jquery.ui.datepicker.css create mode 100644 templates/backOffice/default/assets/js/jquery.ui/jquery.ui.datepicker/jquery.ui.datepicker.js create mode 100644 templates/backOffice/default/assets/js/jquery.ui/jquery.ui.theme.css create mode 100644 templates/backOffice/default/assets/js/json2.js create mode 100644 templates/backOffice/default/assets/js/libs/jquery.js create mode 100644 templates/backOffice/default/assets/js/libs/jquery.toolbar.min.js create mode 100644 templates/backOffice/default/assets/js/libs/metis-menu.min.js create mode 100644 templates/backOffice/default/assets/js/libs/respond.min.js create mode 100644 templates/backOffice/default/assets/js/libs/underscore-min.js create mode 100644 templates/backOffice/default/assets/js/main.js create mode 100644 templates/backOffice/default/assets/js/moment-with-locales.min.js create mode 100644 templates/backOffice/default/assets/js/tablesorter/jquery.metadata.js create mode 100644 templates/backOffice/default/assets/js/tablesorter/jquery.tablesorter.min.js create mode 100644 templates/backOffice/default/assets/js/tablesorter/jquery.tablesorter.widgets-filter-formatter.js create mode 100644 templates/backOffice/default/assets/js/tablesorter/jquery.tablesorter.widgets.js create mode 100644 templates/backOffice/default/assets/js/thelia-states.js create mode 100644 templates/backOffice/default/assets/less/bootstrap/alerts.less create mode 100644 templates/backOffice/default/assets/less/bootstrap/badges.less create mode 100644 templates/backOffice/default/assets/less/bootstrap/bootstrap.less create mode 100644 templates/backOffice/default/assets/less/bootstrap/breadcrumbs.less create mode 100644 templates/backOffice/default/assets/less/bootstrap/button-groups.less create mode 100644 templates/backOffice/default/assets/less/bootstrap/buttons.less create mode 100644 templates/backOffice/default/assets/less/bootstrap/carousel.less create mode 100644 templates/backOffice/default/assets/less/bootstrap/close.less create mode 100644 templates/backOffice/default/assets/less/bootstrap/code.less create mode 100644 templates/backOffice/default/assets/less/bootstrap/component-animations.less create mode 100644 templates/backOffice/default/assets/less/bootstrap/dropdowns.less create mode 100644 templates/backOffice/default/assets/less/bootstrap/forms.less create mode 100644 templates/backOffice/default/assets/less/bootstrap/glyphicons.less create mode 100644 templates/backOffice/default/assets/less/bootstrap/grid.less create mode 100644 templates/backOffice/default/assets/less/bootstrap/input-groups.less create mode 100644 templates/backOffice/default/assets/less/bootstrap/jumbotron.less create mode 100644 templates/backOffice/default/assets/less/bootstrap/labels.less create mode 100644 templates/backOffice/default/assets/less/bootstrap/list-group.less create mode 100644 templates/backOffice/default/assets/less/bootstrap/media.less create mode 100644 templates/backOffice/default/assets/less/bootstrap/mixins.less create mode 100644 templates/backOffice/default/assets/less/bootstrap/mixins/alerts.less create mode 100644 templates/backOffice/default/assets/less/bootstrap/mixins/background-variant.less create mode 100644 templates/backOffice/default/assets/less/bootstrap/mixins/border-radius.less create mode 100644 templates/backOffice/default/assets/less/bootstrap/mixins/buttons.less create mode 100644 templates/backOffice/default/assets/less/bootstrap/mixins/center-block.less create mode 100644 templates/backOffice/default/assets/less/bootstrap/mixins/clearfix.less create mode 100644 templates/backOffice/default/assets/less/bootstrap/mixins/forms.less create mode 100644 templates/backOffice/default/assets/less/bootstrap/mixins/gradients.less create mode 100644 templates/backOffice/default/assets/less/bootstrap/mixins/grid-framework.less create mode 100644 templates/backOffice/default/assets/less/bootstrap/mixins/grid.less create mode 100644 templates/backOffice/default/assets/less/bootstrap/mixins/hide-text.less create mode 100644 templates/backOffice/default/assets/less/bootstrap/mixins/image.less create mode 100644 templates/backOffice/default/assets/less/bootstrap/mixins/labels.less create mode 100644 templates/backOffice/default/assets/less/bootstrap/mixins/list-group.less create mode 100644 templates/backOffice/default/assets/less/bootstrap/mixins/nav-divider.less create mode 100644 templates/backOffice/default/assets/less/bootstrap/mixins/nav-vertical-align.less create mode 100644 templates/backOffice/default/assets/less/bootstrap/mixins/opacity.less create mode 100644 templates/backOffice/default/assets/less/bootstrap/mixins/pagination.less create mode 100644 templates/backOffice/default/assets/less/bootstrap/mixins/panels.less create mode 100644 templates/backOffice/default/assets/less/bootstrap/mixins/progress-bar.less create mode 100644 templates/backOffice/default/assets/less/bootstrap/mixins/reset-filter.less create mode 100644 templates/backOffice/default/assets/less/bootstrap/mixins/resize.less create mode 100644 templates/backOffice/default/assets/less/bootstrap/mixins/responsive-visibility.less create mode 100644 templates/backOffice/default/assets/less/bootstrap/mixins/size.less create mode 100644 templates/backOffice/default/assets/less/bootstrap/mixins/tab-focus.less create mode 100644 templates/backOffice/default/assets/less/bootstrap/mixins/table-row.less create mode 100644 templates/backOffice/default/assets/less/bootstrap/mixins/text-emphasis.less create mode 100644 templates/backOffice/default/assets/less/bootstrap/mixins/text-overflow.less create mode 100644 templates/backOffice/default/assets/less/bootstrap/mixins/vendor-prefixes.less create mode 100644 templates/backOffice/default/assets/less/bootstrap/modals.less create mode 100644 templates/backOffice/default/assets/less/bootstrap/navbar.less create mode 100644 templates/backOffice/default/assets/less/bootstrap/navs.less create mode 100644 templates/backOffice/default/assets/less/bootstrap/normalize.less create mode 100644 templates/backOffice/default/assets/less/bootstrap/pager.less create mode 100644 templates/backOffice/default/assets/less/bootstrap/pagination.less create mode 100644 templates/backOffice/default/assets/less/bootstrap/panels.less create mode 100644 templates/backOffice/default/assets/less/bootstrap/popovers.less create mode 100644 templates/backOffice/default/assets/less/bootstrap/print.less create mode 100644 templates/backOffice/default/assets/less/bootstrap/progress-bars.less create mode 100644 templates/backOffice/default/assets/less/bootstrap/responsive-embed.less create mode 100644 templates/backOffice/default/assets/less/bootstrap/responsive-utilities.less create mode 100644 templates/backOffice/default/assets/less/bootstrap/scaffolding.less create mode 100644 templates/backOffice/default/assets/less/bootstrap/tables.less create mode 100644 templates/backOffice/default/assets/less/bootstrap/theme.less create mode 100644 templates/backOffice/default/assets/less/bootstrap/thumbnails.less create mode 100644 templates/backOffice/default/assets/less/bootstrap/tooltip.less create mode 100644 templates/backOffice/default/assets/less/bootstrap/type.less create mode 100644 templates/backOffice/default/assets/less/bootstrap/utilities.less create mode 100644 templates/backOffice/default/assets/less/bootstrap/variables.less create mode 100644 templates/backOffice/default/assets/less/bootstrap/wells.less create mode 100644 templates/backOffice/default/assets/less/main.less create mode 100644 templates/backOffice/default/assets/less/thelia/bootstrap-editable.less create mode 100644 templates/backOffice/default/assets/less/thelia/bootstrap-select.less create mode 100644 templates/backOffice/default/assets/less/thelia/bootstrap-switch.less create mode 100644 templates/backOffice/default/assets/less/thelia/breadcrumbs.less create mode 100644 templates/backOffice/default/assets/less/thelia/buttons.less create mode 100644 templates/backOffice/default/assets/less/thelia/datepicker.less create mode 100644 templates/backOffice/default/assets/less/thelia/dropzone.less create mode 100644 templates/backOffice/default/assets/less/thelia/fonts.less create mode 100644 templates/backOffice/default/assets/less/thelia/forms.less create mode 100644 templates/backOffice/default/assets/less/thelia/grid.less create mode 100644 templates/backOffice/default/assets/less/thelia/jqplot.less create mode 100644 templates/backOffice/default/assets/less/thelia/labels.less create mode 100644 templates/backOffice/default/assets/less/thelia/logger.less create mode 100644 templates/backOffice/default/assets/less/thelia/login-page.less create mode 100644 templates/backOffice/default/assets/less/thelia/mixins.less create mode 100644 templates/backOffice/default/assets/less/thelia/modals.less create mode 100644 templates/backOffice/default/assets/less/thelia/navbar.less create mode 100644 templates/backOffice/default/assets/less/thelia/responsive.less create mode 100644 templates/backOffice/default/assets/less/thelia/scaffolding.less create mode 100644 templates/backOffice/default/assets/less/thelia/tables.less create mode 100644 templates/backOffice/default/assets/less/thelia/tablesorter.less create mode 100644 templates/backOffice/default/assets/less/thelia/thelia.less create mode 100644 templates/backOffice/default/assets/less/thelia/toolbar.less create mode 100644 templates/backOffice/default/assets/less/thelia/type.less create mode 100644 templates/backOffice/default/assets/less/thelia/variables.less create mode 100644 templates/backOffice/default/assets/less/thelia/wizard.less create mode 100644 templates/backOffice/default/attribute-edit.html create mode 100644 templates/backOffice/default/attributes.html create mode 100644 templates/backOffice/default/brand-edit.html create mode 100644 templates/backOffice/default/brands.html create mode 100644 templates/backOffice/default/categories.html create mode 100644 templates/backOffice/default/category-edit.html create mode 100644 templates/backOffice/default/composer.json create mode 100644 templates/backOffice/default/config-store.html create mode 100644 templates/backOffice/default/configs/variables.conf create mode 100644 templates/backOffice/default/configuration.html create mode 100644 templates/backOffice/default/content-edit.html create mode 100644 templates/backOffice/default/countries.html create mode 100644 templates/backOffice/default/country-edit.html create mode 100644 templates/backOffice/default/coupon-create.html create mode 100644 templates/backOffice/default/coupon-list.html create mode 100644 templates/backOffice/default/coupon-update.html create mode 100644 templates/backOffice/default/coupon/condition-fragments/base-input-text.html create mode 100644 templates/backOffice/default/coupon/condition-fragments/cart-contains-categories-condition.html create mode 100644 templates/backOffice/default/coupon/condition-fragments/cart-contains-products-condition.html create mode 100644 templates/backOffice/default/coupon/condition-fragments/cart-item-count-condition.html create mode 100644 templates/backOffice/default/coupon/condition-fragments/cart-total-amount-condition.html create mode 100644 templates/backOffice/default/coupon/condition-fragments/condition-selector.html create mode 100644 templates/backOffice/default/coupon/condition-fragments/countries-condition.html create mode 100644 templates/backOffice/default/coupon/condition-fragments/currency-selector.html create mode 100644 templates/backOffice/default/coupon/condition-fragments/customers-condition.html create mode 100644 templates/backOffice/default/coupon/condition-fragments/quantity-selector.html create mode 100644 templates/backOffice/default/coupon/condition-fragments/start-date-condition.html create mode 100644 templates/backOffice/default/coupon/condition-input-ajax.html create mode 100644 templates/backOffice/default/coupon/conditions.html create mode 100644 templates/backOffice/default/coupon/form.html create mode 100644 templates/backOffice/default/coupon/type-fragments/ajax-attribute-avs-list.html create mode 100644 templates/backOffice/default/coupon/type-fragments/ajax-products-list.html create mode 100644 templates/backOffice/default/coupon/type-fragments/base-remove-on-attributes.html create mode 100644 templates/backOffice/default/coupon/type-fragments/base-remove-on-categories.html create mode 100644 templates/backOffice/default/coupon/type-fragments/base-remove-on-products.html create mode 100644 templates/backOffice/default/coupon/type-fragments/free-product.html create mode 100644 templates/backOffice/default/coupon/type-fragments/remove-amount-on-attributes.html create mode 100644 templates/backOffice/default/coupon/type-fragments/remove-amount-on-categories.html create mode 100644 templates/backOffice/default/coupon/type-fragments/remove-amount-on-products.html create mode 100644 templates/backOffice/default/coupon/type-fragments/remove-percentage-on-attributes.html create mode 100644 templates/backOffice/default/coupon/type-fragments/remove-percentage-on-categories.html create mode 100644 templates/backOffice/default/coupon/type-fragments/remove-percentage-on-products.html create mode 100644 templates/backOffice/default/coupon/type-fragments/remove-x-amount.html create mode 100644 templates/backOffice/default/coupon/type-fragments/remove-x-percent.html create mode 100644 templates/backOffice/default/coupon/type-fragments/remove-x.html create mode 100644 templates/backOffice/default/create-password-success.html create mode 100644 templates/backOffice/default/create-password.html create mode 100644 templates/backOffice/default/currencies.html create mode 100644 templates/backOffice/default/currency-edit.html create mode 100644 templates/backOffice/default/customer-edit.html create mode 100644 templates/backOffice/default/customers.html create mode 100644 templates/backOffice/default/document-edit.html create mode 100644 templates/backOffice/default/error.html create mode 100644 templates/backOffice/default/export-page.html create mode 100644 templates/backOffice/default/export.html create mode 100644 templates/backOffice/default/feature-edit.html create mode 100644 templates/backOffice/default/features.html create mode 100644 templates/backOffice/default/folder-edit.html create mode 100644 templates/backOffice/default/folders.html create mode 100644 templates/backOffice/default/forms/standard/form-field-attributes-renderer.html create mode 100644 templates/backOffice/default/forms/standard/form-field-renderer.html create mode 100644 templates/backOffice/default/general_error.html create mode 100644 templates/backOffice/default/home.html create mode 100644 templates/backOffice/default/hook-edit.html create mode 100644 templates/backOffice/default/hooks.html create mode 100644 templates/backOffice/default/image-edit.html create mode 100644 templates/backOffice/default/import-page.html create mode 100644 templates/backOffice/default/import.html create mode 100644 templates/backOffice/default/includes/admin-utilities-position-block.html create mode 100644 templates/backOffice/default/includes/admin-utilities-sortable-column-header.html create mode 100644 templates/backOffice/default/includes/catalog-breadcrumb.html create mode 100644 templates/backOffice/default/includes/confirmation-modal.html create mode 100644 templates/backOffice/default/includes/content-folder-management.html create mode 100644 templates/backOffice/default/includes/customer_address_form_fields.html create mode 100644 templates/backOffice/default/includes/document-upload-form.html create mode 100644 templates/backOffice/default/includes/document-upload-list-ajax.html create mode 100644 templates/backOffice/default/includes/export-form-body.html create mode 100644 templates/backOffice/default/includes/folder-breadcrumb.html create mode 100644 templates/backOffice/default/includes/generic-confirm-dialog.html create mode 100644 templates/backOffice/default/includes/generic-create-dialog.html create mode 100644 templates/backOffice/default/includes/generic-js-dialog.html create mode 100644 templates/backOffice/default/includes/generic-warning-dialog.html create mode 100644 templates/backOffice/default/includes/hook-edition.js.inc create mode 100644 templates/backOffice/default/includes/image-upload-form.html create mode 100644 templates/backOffice/default/includes/image-upload-list-ajax.html create mode 100644 templates/backOffice/default/includes/import-form-body.html create mode 100644 templates/backOffice/default/includes/inner-form-toolbar.html create mode 100644 templates/backOffice/default/includes/main-menu.html create mode 100644 templates/backOffice/default/includes/module-block.html create mode 100644 templates/backOffice/default/includes/module-errors.html create mode 100644 templates/backOffice/default/includes/module-hook-block.html create mode 100644 templates/backOffice/default/includes/module-install.html create mode 100644 templates/backOffice/default/includes/module-tab-content.html create mode 100644 templates/backOffice/default/includes/notifications.html create mode 100644 templates/backOffice/default/includes/pagination.html create mode 100644 templates/backOffice/default/includes/product-general-tab.html create mode 100644 templates/backOffice/default/includes/product-prices-tab.html create mode 100644 templates/backOffice/default/includes/seo-tab.html create mode 100644 templates/backOffice/default/includes/standard-description-form-fields.html create mode 100644 templates/backOffice/default/languages.html create mode 100644 templates/backOffice/default/login.html create mode 100644 templates/backOffice/default/lost-password.html create mode 100644 templates/backOffice/default/mailing-system.html create mode 100644 templates/backOffice/default/message-edit.html create mode 100644 templates/backOffice/default/messages.html create mode 100644 templates/backOffice/default/module-configure.html create mode 100644 templates/backOffice/default/module-edit.html create mode 100644 templates/backOffice/default/module-hook-edit.html create mode 100644 templates/backOffice/default/module-hooks.html create mode 100644 templates/backOffice/default/modules.html create mode 100644 templates/backOffice/default/order-edit.html create mode 100644 templates/backOffice/default/order-status-edit.html create mode 100644 templates/backOffice/default/order-status.html create mode 100644 templates/backOffice/default/orders.html create mode 100644 templates/backOffice/default/product-edit.html create mode 100644 templates/backOffice/default/profile-edit.html create mode 100644 templates/backOffice/default/profiles.html create mode 100644 templates/backOffice/default/renderer/buttons.html create mode 100644 templates/backOffice/default/sale-edit.html create mode 100644 templates/backOffice/default/sales.html create mode 100644 templates/backOffice/default/search.html create mode 100644 templates/backOffice/default/shipping-configuration-edit.html create mode 100644 templates/backOffice/default/shipping-configuration.html create mode 100644 templates/backOffice/default/shipping-zones-edit.html create mode 100644 templates/backOffice/default/shipping-zones.html create mode 100644 templates/backOffice/default/simple-layout.tpl create mode 100644 templates/backOffice/default/state-edit.html create mode 100644 templates/backOffice/default/states.html create mode 100644 templates/backOffice/default/system-logs.html create mode 100644 templates/backOffice/default/tax-edit.html create mode 100644 templates/backOffice/default/tax-rule-edit.html create mode 100644 templates/backOffice/default/taxes-rules.html create mode 100644 templates/backOffice/default/template-edit.html create mode 100644 templates/backOffice/default/template.xml create mode 100644 templates/backOffice/default/templates.html create mode 100644 templates/backOffice/default/tools.html create mode 100644 templates/backOffice/default/translations.html create mode 100644 templates/backOffice/default/variable-edit.html create mode 100644 templates/backOffice/default/variables.html create mode 100644 templates/email/default/I18n/ar_SA.php create mode 100644 templates/email/default/I18n/cs_CZ.php create mode 100644 templates/email/default/I18n/de_DE.php create mode 100644 templates/email/default/I18n/el_GR.php create mode 100644 templates/email/default/I18n/en_US.php create mode 100644 templates/email/default/I18n/es_ES.php create mode 100644 templates/email/default/I18n/fa_IR.php create mode 100644 templates/email/default/I18n/fr_FR.php create mode 100644 templates/email/default/I18n/hu_HU.php create mode 100644 templates/email/default/I18n/id_ID.php create mode 100644 templates/email/default/I18n/it_IT.php create mode 100644 templates/email/default/I18n/pl_PL.php create mode 100644 templates/email/default/I18n/pt_BR.php create mode 100644 templates/email/default/I18n/pt_PT.php create mode 100644 templates/email/default/I18n/ru_RU.php create mode 100644 templates/email/default/I18n/sk_SK.php create mode 100644 templates/email/default/I18n/tr_TR.php create mode 100644 templates/email/default/LICENSE.txt create mode 100644 templates/email/default/README create mode 100644 templates/email/default/Readme.md create mode 100644 templates/email/default/account_changed_by_admin.html create mode 100644 templates/email/default/account_changed_by_admin.txt create mode 100644 templates/email/default/account_created_by_admin.html create mode 100644 templates/email/default/account_created_by_admin.txt create mode 100644 templates/email/default/admin_password.html create mode 100644 templates/email/default/admin_password.txt create mode 100644 templates/email/default/assets/img/header.jpg create mode 100644 templates/email/default/assets/img/logo.gif create mode 100644 templates/email/default/composer.json create mode 100644 templates/email/default/customer_confirmation.html create mode 100644 templates/email/default/customer_confirmation.txt create mode 100644 templates/email/default/default-html-layout.tpl create mode 100644 templates/email/default/default-text-layout.tpl create mode 100644 templates/email/default/email-layout.tpl create mode 100644 templates/email/default/newsletter_subscription_confirmation.html create mode 100644 templates/email/default/newsletter_subscription_confirmation.txt create mode 100644 templates/email/default/order_confirmation.html create mode 100644 templates/email/default/order_confirmation.txt create mode 100644 templates/email/default/order_notification.html create mode 100644 templates/email/default/order_notification.txt create mode 100644 templates/email/default/password.html create mode 100644 templates/email/default/password.txt create mode 100644 templates/email/default/template.xml create mode 100644 templates/frontOffice/default/.gitignore create mode 100644 templates/frontOffice/default/404.html create mode 100644 templates/frontOffice/default/Gruntfile.js create mode 100644 templates/frontOffice/default/I18n/ar_SA.php create mode 100644 templates/frontOffice/default/I18n/cs_CZ.php create mode 100644 templates/frontOffice/default/I18n/de_DE.php create mode 100644 templates/frontOffice/default/I18n/el_GR.php create mode 100644 templates/frontOffice/default/I18n/en_US.php create mode 100644 templates/frontOffice/default/I18n/es_ES.php create mode 100644 templates/frontOffice/default/I18n/fa_IR.php create mode 100644 templates/frontOffice/default/I18n/fr_FR.php create mode 100644 templates/frontOffice/default/I18n/hu_HU.php create mode 100644 templates/frontOffice/default/I18n/id_ID.php create mode 100644 templates/frontOffice/default/I18n/it_IT.php create mode 100644 templates/frontOffice/default/I18n/nl_NL.php create mode 100644 templates/frontOffice/default/I18n/pl_PL.php create mode 100644 templates/frontOffice/default/I18n/pt_BR.php create mode 100644 templates/frontOffice/default/I18n/pt_PT.php create mode 100644 templates/frontOffice/default/I18n/ru_RU.php create mode 100644 templates/frontOffice/default/I18n/sk_SK.php create mode 100644 templates/frontOffice/default/I18n/tr_TR.php create mode 100644 templates/frontOffice/default/I18n/uk_UA.php create mode 100644 templates/frontOffice/default/LICENSE.txt create mode 100644 templates/frontOffice/default/Readme.md create mode 100644 templates/frontOffice/default/account-order.html create mode 100644 templates/frontOffice/default/account-password.html create mode 100644 templates/frontOffice/default/account-update.html create mode 100644 templates/frontOffice/default/account.html create mode 100644 templates/frontOffice/default/address-update.html create mode 100644 templates/frontOffice/default/address.html create mode 100644 templates/frontOffice/default/ajax/order-delivery-module-list.html create mode 100644 templates/frontOffice/default/assets/dist/css/thelia.min.css create mode 100644 templates/frontOffice/default/assets/dist/fonts/bootstrap/glyphicons-halflings-regular.eot create mode 100644 templates/frontOffice/default/assets/dist/fonts/bootstrap/glyphicons-halflings-regular.svg create mode 100644 templates/frontOffice/default/assets/dist/fonts/bootstrap/glyphicons-halflings-regular.ttf create mode 100644 templates/frontOffice/default/assets/dist/fonts/bootstrap/glyphicons-halflings-regular.woff create mode 100644 templates/frontOffice/default/assets/dist/fonts/bootstrap/glyphicons-halflings-regular.woff2 create mode 100644 templates/frontOffice/default/assets/dist/fonts/fontawesome/FontAwesome.otf create mode 100644 templates/frontOffice/default/assets/dist/fonts/fontawesome/fontawesome-webfont.eot create mode 100644 templates/frontOffice/default/assets/dist/fonts/fontawesome/fontawesome-webfont.svg create mode 100644 templates/frontOffice/default/assets/dist/fonts/fontawesome/fontawesome-webfont.ttf create mode 100644 templates/frontOffice/default/assets/dist/fonts/fontawesome/fontawesome-webfont.woff create mode 100644 templates/frontOffice/default/assets/dist/fonts/fontawesome/fontawesome-webfont.woff2 create mode 100644 templates/frontOffice/default/assets/dist/img/118x85.png create mode 100644 templates/frontOffice/default/assets/dist/img/1200x390.png create mode 100644 templates/frontOffice/default/assets/dist/img/218x146.png create mode 100644 templates/frontOffice/default/assets/dist/img/280x196.png create mode 100644 templates/frontOffice/default/assets/dist/img/560x445.png create mode 100644 templates/frontOffice/default/assets/dist/img/700x320.png create mode 100644 templates/frontOffice/default/assets/dist/img/ajax-loader.gif create mode 100644 templates/frontOffice/default/assets/dist/img/american-express.png create mode 100644 templates/frontOffice/default/assets/dist/img/carousel/slider2.jpg create mode 100644 templates/frontOffice/default/assets/dist/img/carousel/slider3.jpg create mode 100644 templates/frontOffice/default/assets/dist/img/cheque.png create mode 100644 templates/frontOffice/default/assets/dist/img/email/header.jpg create mode 100644 templates/frontOffice/default/assets/dist/img/email/logo.gif create mode 100644 templates/frontOffice/default/assets/dist/img/email/logo.png create mode 100644 templates/frontOffice/default/assets/dist/img/favicon.ico create mode 100644 templates/frontOffice/default/assets/dist/img/favicon.png create mode 100644 templates/frontOffice/default/assets/dist/img/googlemap-icon.png create mode 100644 templates/frontOffice/default/assets/dist/img/header.jpg create mode 100644 templates/frontOffice/default/assets/dist/img/kwixo.png create mode 100644 templates/frontOffice/default/assets/dist/img/logo.gif create mode 100644 templates/frontOffice/default/assets/dist/img/logo.png create mode 100644 templates/frontOffice/default/assets/dist/img/mastercard.png create mode 100644 templates/frontOffice/default/assets/dist/img/payment/american-express.png create mode 100644 templates/frontOffice/default/assets/dist/img/payment/cheque.png create mode 100644 templates/frontOffice/default/assets/dist/img/payment/kwixo.png create mode 100644 templates/frontOffice/default/assets/dist/img/payment/mastercard.png create mode 100644 templates/frontOffice/default/assets/dist/img/payment/visa.png create mode 100644 templates/frontOffice/default/assets/dist/img/product/1/118x85.png create mode 100644 templates/frontOffice/default/assets/dist/img/slider1.jpg create mode 100644 templates/frontOffice/default/assets/dist/img/slider2.jpg create mode 100644 templates/frontOffice/default/assets/dist/img/slider3.jpg create mode 100644 templates/frontOffice/default/assets/dist/img/visa.png create mode 100644 templates/frontOffice/default/assets/dist/js/thelia.min.js create mode 100644 templates/frontOffice/default/assets/dist/js/vendors/bootbox.js create mode 100644 templates/frontOffice/default/assets/dist/js/vendors/bootstrap.min.js create mode 100644 templates/frontOffice/default/assets/dist/js/vendors/html5shiv.min.js create mode 100644 templates/frontOffice/default/assets/dist/js/vendors/jquery.min.js create mode 100644 templates/frontOffice/default/assets/dist/js/vendors/respond.min.js create mode 100644 templates/frontOffice/default/assets/src/css/thelia.css create mode 100644 templates/frontOffice/default/assets/src/fonts/bootstrap/glyphicons-halflings-regular.eot create mode 100644 templates/frontOffice/default/assets/src/fonts/bootstrap/glyphicons-halflings-regular.svg create mode 100644 templates/frontOffice/default/assets/src/fonts/bootstrap/glyphicons-halflings-regular.ttf create mode 100644 templates/frontOffice/default/assets/src/fonts/bootstrap/glyphicons-halflings-regular.woff create mode 100644 templates/frontOffice/default/assets/src/fonts/bootstrap/glyphicons-halflings-regular.woff2 create mode 100644 templates/frontOffice/default/assets/src/fonts/fontawesome/FontAwesome.otf create mode 100644 templates/frontOffice/default/assets/src/fonts/fontawesome/fontawesome-webfont.eot create mode 100644 templates/frontOffice/default/assets/src/fonts/fontawesome/fontawesome-webfont.svg create mode 100644 templates/frontOffice/default/assets/src/fonts/fontawesome/fontawesome-webfont.ttf create mode 100644 templates/frontOffice/default/assets/src/fonts/fontawesome/fontawesome-webfont.woff create mode 100644 templates/frontOffice/default/assets/src/fonts/fontawesome/fontawesome-webfont.woff2 create mode 100644 templates/frontOffice/default/assets/src/img/218x146.png create mode 100644 templates/frontOffice/default/assets/src/img/280x196.png create mode 100644 templates/frontOffice/default/assets/src/img/ajax-loader.gif create mode 100644 templates/frontOffice/default/assets/src/img/email/header.jpg create mode 100644 templates/frontOffice/default/assets/src/img/email/logo.gif create mode 100644 templates/frontOffice/default/assets/src/img/email/logo.png create mode 100644 templates/frontOffice/default/assets/src/img/favicon.ico create mode 100644 templates/frontOffice/default/assets/src/img/favicon.png create mode 100644 templates/frontOffice/default/assets/src/img/logo.gif create mode 100644 templates/frontOffice/default/assets/src/img/logo.png create mode 100644 templates/frontOffice/default/assets/src/img/product/1/118x85.png create mode 100644 templates/frontOffice/default/assets/src/js/thelia.js create mode 100644 templates/frontOffice/default/assets/src/js/vendors/bootbox.js create mode 100644 templates/frontOffice/default/assets/src/js/vendors/bootstrap.js create mode 100644 templates/frontOffice/default/assets/src/js/vendors/html5shiv.js create mode 100644 templates/frontOffice/default/assets/src/js/vendors/jquery.js create mode 100644 templates/frontOffice/default/assets/src/js/vendors/respond.js create mode 100644 templates/frontOffice/default/assets/src/less/thelia.less create mode 100644 templates/frontOffice/default/assets/src/less/thelia/account.less create mode 100644 templates/frontOffice/default/assets/src/less/thelia/brand.less create mode 100644 templates/frontOffice/default/assets/src/less/thelia/breadcrumbs.less create mode 100644 templates/frontOffice/default/assets/src/less/thelia/cart.less create mode 100644 templates/frontOffice/default/assets/src/less/thelia/category.less create mode 100644 templates/frontOffice/default/assets/src/less/thelia/checkout.less create mode 100644 templates/frontOffice/default/assets/src/less/thelia/filters.less create mode 100644 templates/frontOffice/default/assets/src/less/thelia/folder.less create mode 100644 templates/frontOffice/default/assets/src/less/thelia/footer.less create mode 100644 templates/frontOffice/default/assets/src/less/thelia/forms.less create mode 100644 templates/frontOffice/default/assets/src/less/thelia/header.less create mode 100644 templates/frontOffice/default/assets/src/less/thelia/import.less create mode 100644 templates/frontOffice/default/assets/src/less/thelia/navbar.less create mode 100644 templates/frontOffice/default/assets/src/less/thelia/pagination.less create mode 100644 templates/frontOffice/default/assets/src/less/thelia/product.less create mode 100644 templates/frontOffice/default/assets/src/less/thelia/toolbars.less create mode 100644 templates/frontOffice/default/assets/src/less/thelia/variables.less create mode 100644 templates/frontOffice/default/assets/src/less/theme/alerts.less create mode 100644 templates/frontOffice/default/assets/src/less/theme/blocks.less create mode 100644 templates/frontOffice/default/assets/src/less/theme/brand.less create mode 100644 templates/frontOffice/default/assets/src/less/theme/breadcrumbs.less create mode 100644 templates/frontOffice/default/assets/src/less/theme/buttons.less create mode 100644 templates/frontOffice/default/assets/src/less/theme/cart.less create mode 100644 templates/frontOffice/default/assets/src/less/theme/category.less create mode 100644 templates/frontOffice/default/assets/src/less/theme/checkout.less create mode 100644 templates/frontOffice/default/assets/src/less/theme/filters.less create mode 100644 templates/frontOffice/default/assets/src/less/theme/folder.less create mode 100644 templates/frontOffice/default/assets/src/less/theme/footer.less create mode 100644 templates/frontOffice/default/assets/src/less/theme/forms.less create mode 100644 templates/frontOffice/default/assets/src/less/theme/global.less create mode 100644 templates/frontOffice/default/assets/src/less/theme/header.less create mode 100644 templates/frontOffice/default/assets/src/less/theme/import.less create mode 100644 templates/frontOffice/default/assets/src/less/theme/labels.less create mode 100644 templates/frontOffice/default/assets/src/less/theme/navbar.less create mode 100644 templates/frontOffice/default/assets/src/less/theme/page-error.less create mode 100644 templates/frontOffice/default/assets/src/less/theme/page-home.less create mode 100644 templates/frontOffice/default/assets/src/less/theme/panels.less create mode 100644 templates/frontOffice/default/assets/src/less/theme/price.less create mode 100644 templates/frontOffice/default/assets/src/less/theme/product.less create mode 100644 templates/frontOffice/default/assets/src/less/theme/scaffolding.less create mode 100644 templates/frontOffice/default/assets/src/less/theme/tables.less create mode 100644 templates/frontOffice/default/assets/src/less/theme/theme.less create mode 100644 templates/frontOffice/default/assets/src/less/theme/toolbars.less create mode 100644 templates/frontOffice/default/assets/src/less/theme/variables.less create mode 100644 templates/frontOffice/default/assets/src/less/vendors/bootstrap/alerts.less create mode 100644 templates/frontOffice/default/assets/src/less/vendors/bootstrap/badges.less create mode 100644 templates/frontOffice/default/assets/src/less/vendors/bootstrap/bootstrap.less create mode 100644 templates/frontOffice/default/assets/src/less/vendors/bootstrap/breadcrumbs.less create mode 100644 templates/frontOffice/default/assets/src/less/vendors/bootstrap/button-groups.less create mode 100644 templates/frontOffice/default/assets/src/less/vendors/bootstrap/buttons.less create mode 100644 templates/frontOffice/default/assets/src/less/vendors/bootstrap/carousel.less create mode 100644 templates/frontOffice/default/assets/src/less/vendors/bootstrap/close.less create mode 100644 templates/frontOffice/default/assets/src/less/vendors/bootstrap/code.less create mode 100644 templates/frontOffice/default/assets/src/less/vendors/bootstrap/component-animations.less create mode 100644 templates/frontOffice/default/assets/src/less/vendors/bootstrap/dropdowns.less create mode 100644 templates/frontOffice/default/assets/src/less/vendors/bootstrap/forms.less create mode 100644 templates/frontOffice/default/assets/src/less/vendors/bootstrap/glyphicons.less create mode 100644 templates/frontOffice/default/assets/src/less/vendors/bootstrap/grid.less create mode 100644 templates/frontOffice/default/assets/src/less/vendors/bootstrap/input-groups.less create mode 100644 templates/frontOffice/default/assets/src/less/vendors/bootstrap/jumbotron.less create mode 100644 templates/frontOffice/default/assets/src/less/vendors/bootstrap/labels.less create mode 100644 templates/frontOffice/default/assets/src/less/vendors/bootstrap/list-group.less create mode 100644 templates/frontOffice/default/assets/src/less/vendors/bootstrap/media.less create mode 100644 templates/frontOffice/default/assets/src/less/vendors/bootstrap/mixins.less create mode 100644 templates/frontOffice/default/assets/src/less/vendors/bootstrap/mixins/alerts.less create mode 100644 templates/frontOffice/default/assets/src/less/vendors/bootstrap/mixins/background-variant.less create mode 100644 templates/frontOffice/default/assets/src/less/vendors/bootstrap/mixins/border-radius.less create mode 100644 templates/frontOffice/default/assets/src/less/vendors/bootstrap/mixins/buttons.less create mode 100644 templates/frontOffice/default/assets/src/less/vendors/bootstrap/mixins/center-block.less create mode 100644 templates/frontOffice/default/assets/src/less/vendors/bootstrap/mixins/clearfix.less create mode 100644 templates/frontOffice/default/assets/src/less/vendors/bootstrap/mixins/forms.less create mode 100644 templates/frontOffice/default/assets/src/less/vendors/bootstrap/mixins/gradients.less create mode 100644 templates/frontOffice/default/assets/src/less/vendors/bootstrap/mixins/grid-framework.less create mode 100644 templates/frontOffice/default/assets/src/less/vendors/bootstrap/mixins/grid.less create mode 100644 templates/frontOffice/default/assets/src/less/vendors/bootstrap/mixins/hide-text.less create mode 100644 templates/frontOffice/default/assets/src/less/vendors/bootstrap/mixins/image.less create mode 100644 templates/frontOffice/default/assets/src/less/vendors/bootstrap/mixins/labels.less create mode 100644 templates/frontOffice/default/assets/src/less/vendors/bootstrap/mixins/list-group.less create mode 100644 templates/frontOffice/default/assets/src/less/vendors/bootstrap/mixins/nav-divider.less create mode 100644 templates/frontOffice/default/assets/src/less/vendors/bootstrap/mixins/nav-vertical-align.less create mode 100644 templates/frontOffice/default/assets/src/less/vendors/bootstrap/mixins/opacity.less create mode 100644 templates/frontOffice/default/assets/src/less/vendors/bootstrap/mixins/pagination.less create mode 100644 templates/frontOffice/default/assets/src/less/vendors/bootstrap/mixins/panels.less create mode 100644 templates/frontOffice/default/assets/src/less/vendors/bootstrap/mixins/progress-bar.less create mode 100644 templates/frontOffice/default/assets/src/less/vendors/bootstrap/mixins/reset-filter.less create mode 100644 templates/frontOffice/default/assets/src/less/vendors/bootstrap/mixins/reset-text.less create mode 100644 templates/frontOffice/default/assets/src/less/vendors/bootstrap/mixins/resize.less create mode 100644 templates/frontOffice/default/assets/src/less/vendors/bootstrap/mixins/responsive-visibility.less create mode 100644 templates/frontOffice/default/assets/src/less/vendors/bootstrap/mixins/size.less create mode 100644 templates/frontOffice/default/assets/src/less/vendors/bootstrap/mixins/tab-focus.less create mode 100644 templates/frontOffice/default/assets/src/less/vendors/bootstrap/mixins/table-row.less create mode 100644 templates/frontOffice/default/assets/src/less/vendors/bootstrap/mixins/text-emphasis.less create mode 100644 templates/frontOffice/default/assets/src/less/vendors/bootstrap/mixins/text-overflow.less create mode 100644 templates/frontOffice/default/assets/src/less/vendors/bootstrap/mixins/vendor-prefixes.less create mode 100644 templates/frontOffice/default/assets/src/less/vendors/bootstrap/modals.less create mode 100644 templates/frontOffice/default/assets/src/less/vendors/bootstrap/navbar.less create mode 100644 templates/frontOffice/default/assets/src/less/vendors/bootstrap/navs.less create mode 100644 templates/frontOffice/default/assets/src/less/vendors/bootstrap/normalize.less create mode 100644 templates/frontOffice/default/assets/src/less/vendors/bootstrap/pager.less create mode 100644 templates/frontOffice/default/assets/src/less/vendors/bootstrap/pagination.less create mode 100644 templates/frontOffice/default/assets/src/less/vendors/bootstrap/panels.less create mode 100644 templates/frontOffice/default/assets/src/less/vendors/bootstrap/popovers.less create mode 100644 templates/frontOffice/default/assets/src/less/vendors/bootstrap/print.less create mode 100644 templates/frontOffice/default/assets/src/less/vendors/bootstrap/progress-bars.less create mode 100644 templates/frontOffice/default/assets/src/less/vendors/bootstrap/responsive-embed.less create mode 100644 templates/frontOffice/default/assets/src/less/vendors/bootstrap/responsive-utilities.less create mode 100644 templates/frontOffice/default/assets/src/less/vendors/bootstrap/scaffolding.less create mode 100644 templates/frontOffice/default/assets/src/less/vendors/bootstrap/tables.less create mode 100644 templates/frontOffice/default/assets/src/less/vendors/bootstrap/theme.less create mode 100644 templates/frontOffice/default/assets/src/less/vendors/bootstrap/thumbnails.less create mode 100644 templates/frontOffice/default/assets/src/less/vendors/bootstrap/tooltip.less create mode 100644 templates/frontOffice/default/assets/src/less/vendors/bootstrap/type.less create mode 100644 templates/frontOffice/default/assets/src/less/vendors/bootstrap/utilities.less create mode 100644 templates/frontOffice/default/assets/src/less/vendors/bootstrap/variables.less create mode 100644 templates/frontOffice/default/assets/src/less/vendors/bootstrap/wells.less create mode 100644 templates/frontOffice/default/assets/src/less/vendors/fontawesome/animated.less create mode 100644 templates/frontOffice/default/assets/src/less/vendors/fontawesome/bordered-pulled.less create mode 100644 templates/frontOffice/default/assets/src/less/vendors/fontawesome/core.less create mode 100644 templates/frontOffice/default/assets/src/less/vendors/fontawesome/fixed-width.less create mode 100644 templates/frontOffice/default/assets/src/less/vendors/fontawesome/font-awesome.less create mode 100644 templates/frontOffice/default/assets/src/less/vendors/fontawesome/icons.less create mode 100644 templates/frontOffice/default/assets/src/less/vendors/fontawesome/larger.less create mode 100644 templates/frontOffice/default/assets/src/less/vendors/fontawesome/list.less create mode 100644 templates/frontOffice/default/assets/src/less/vendors/fontawesome/mixins.less create mode 100644 templates/frontOffice/default/assets/src/less/vendors/fontawesome/path.less create mode 100644 templates/frontOffice/default/assets/src/less/vendors/fontawesome/rotated-flipped.less create mode 100644 templates/frontOffice/default/assets/src/less/vendors/fontawesome/stacked.less create mode 100644 templates/frontOffice/default/assets/src/less/vendors/fontawesome/variables.less create mode 100644 templates/frontOffice/default/badresponse.html create mode 100644 templates/frontOffice/default/bower.json create mode 100644 templates/frontOffice/default/brand.html create mode 100644 templates/frontOffice/default/cart.html create mode 100644 templates/frontOffice/default/category.html create mode 100644 templates/frontOffice/default/composer.json create mode 100644 templates/frontOffice/default/configs/variables.conf create mode 100644 templates/frontOffice/default/contact-success.html create mode 100644 templates/frontOffice/default/contact.html create mode 100644 templates/frontOffice/default/content.html create mode 100644 templates/frontOffice/default/currency.html create mode 100644 templates/frontOffice/default/error.html create mode 100644 templates/frontOffice/default/feed.html create mode 100644 templates/frontOffice/default/folder.html create mode 100644 templates/frontOffice/default/includes/addedToCart.html create mode 100644 templates/frontOffice/default/includes/asides/articles.html create mode 100644 templates/frontOffice/default/includes/brand-menu.html create mode 100644 templates/frontOffice/default/includes/empty.html create mode 100644 templates/frontOffice/default/includes/menu.html create mode 100644 templates/frontOffice/default/includes/meta-seo.html create mode 100644 templates/frontOffice/default/includes/mini-cart.html create mode 100644 templates/frontOffice/default/includes/product-empty.html create mode 100644 templates/frontOffice/default/includes/single-product.html create mode 100644 templates/frontOffice/default/includes/toolbar.html create mode 100644 templates/frontOffice/default/index.html create mode 100644 templates/frontOffice/default/language.html create mode 100644 templates/frontOffice/default/layout.tpl create mode 100644 templates/frontOffice/default/login.html create mode 100644 templates/frontOffice/default/misc/breadcrumb.tpl create mode 100644 templates/frontOffice/default/misc/checkout-progress.tpl create mode 100644 templates/frontOffice/default/modal-address.html create mode 100644 templates/frontOffice/default/newsletter-unsubscribe.html create mode 100644 templates/frontOffice/default/newsletter.html create mode 100644 templates/frontOffice/default/order-delivery.html create mode 100644 templates/frontOffice/default/order-failed.html create mode 100644 templates/frontOffice/default/order-invoice.html create mode 100644 templates/frontOffice/default/order-payment-gateway.html create mode 100644 templates/frontOffice/default/order-placed.html create mode 100644 templates/frontOffice/default/package.json create mode 100644 templates/frontOffice/default/password.html create mode 100644 templates/frontOffice/default/product.html create mode 100644 templates/frontOffice/default/register.html create mode 100644 templates/frontOffice/default/sale.html create mode 100644 templates/frontOffice/default/search.html create mode 100644 templates/frontOffice/default/sitemap.html create mode 100644 templates/frontOffice/default/template.xml create mode 100644 templates/frontOffice/default/view_all.html create mode 100644 templates/pdf/default/I18n/ar_SA.php create mode 100644 templates/pdf/default/I18n/cs_CZ.php create mode 100644 templates/pdf/default/I18n/de_DE.php create mode 100644 templates/pdf/default/I18n/el_GR.php create mode 100644 templates/pdf/default/I18n/en_US.php create mode 100644 templates/pdf/default/I18n/es_ES.php create mode 100644 templates/pdf/default/I18n/fa_IR.php create mode 100644 templates/pdf/default/I18n/fr_FR.php create mode 100644 templates/pdf/default/I18n/hu_HU.php create mode 100644 templates/pdf/default/I18n/id_ID.php create mode 100644 templates/pdf/default/I18n/it_IT.php create mode 100644 templates/pdf/default/I18n/nl_NL.php create mode 100644 templates/pdf/default/I18n/pl_PL.php create mode 100644 templates/pdf/default/I18n/pt_BR.php create mode 100644 templates/pdf/default/I18n/pt_PT.php create mode 100644 templates/pdf/default/I18n/ru_RU.php create mode 100644 templates/pdf/default/I18n/sk_SK.php create mode 100644 templates/pdf/default/I18n/tr_TR.php create mode 100644 templates/pdf/default/LICENSE.txt create mode 100644 templates/pdf/default/Readme.md create mode 100644 templates/pdf/default/composer.json create mode 100644 templates/pdf/default/delivery.html create mode 100644 templates/pdf/default/invoice.html create mode 100644 templates/pdf/default/template.xml create mode 100644 tests/functionnal/casperjs/conf/local.js create mode 100644 tests/functionnal/casperjs/exe/back/10_pages.js create mode 100644 tests/functionnal/casperjs/exe/front/10_home.js create mode 100644 tests/functionnal/casperjs/exe/front/20_register.js create mode 100644 tests/functionnal/casperjs/exe/front/30_login.js create mode 100644 tests/functionnal/casperjs/exe/front/40_cart.js create mode 100644 tests/functionnal/casperjs/exe/front/50-order-process.js create mode 100644 tests/functionnal/casperjs/exe/front/60-newsletter.js create mode 100644 tests/functionnal/casperjs/exe/hook/10_position.js create mode 100644 tests/functionnal/casperjs/exe/hook/20_activation.js create mode 100644 tests/phpunit/Thelia/Tests/Action/AddressTest.php create mode 100644 tests/phpunit/Thelia/Tests/Action/AdministratorTest.php create mode 100644 tests/phpunit/Thelia/Tests/Action/AreaTest.php create mode 100644 tests/phpunit/Thelia/Tests/Action/AttributeAvTest.php create mode 100644 tests/phpunit/Thelia/Tests/Action/AttributeTest.php create mode 100644 tests/phpunit/Thelia/Tests/Action/BaseAction.php create mode 100644 tests/phpunit/Thelia/Tests/Action/BrandTest.php create mode 100644 tests/phpunit/Thelia/Tests/Action/CacheTest.php create mode 100644 tests/phpunit/Thelia/Tests/Action/CategoryTest.php create mode 100644 tests/phpunit/Thelia/Tests/Action/ConfigTest.php create mode 100644 tests/phpunit/Thelia/Tests/Action/ContentTest.php create mode 100644 tests/phpunit/Thelia/Tests/Action/CountryTest.php create mode 100644 tests/phpunit/Thelia/Tests/Action/CurrencyTest.php create mode 100644 tests/phpunit/Thelia/Tests/Action/CustomerTest.php create mode 100644 tests/phpunit/Thelia/Tests/Action/DocumentTest.php create mode 100644 tests/phpunit/Thelia/Tests/Action/FeatureAvTest.php create mode 100644 tests/phpunit/Thelia/Tests/Action/FeatureTest.php create mode 100644 tests/phpunit/Thelia/Tests/Action/FolderTest.php create mode 100644 tests/phpunit/Thelia/Tests/Action/HookTest.php create mode 100644 tests/phpunit/Thelia/Tests/Action/I18nTestTrait.php create mode 100644 tests/phpunit/Thelia/Tests/Action/ImageTest.php create mode 100644 tests/phpunit/Thelia/Tests/Action/LangTest.php create mode 100644 tests/phpunit/Thelia/Tests/Action/MessageTest.php create mode 100644 tests/phpunit/Thelia/Tests/Action/MetaDataTest.php create mode 100644 tests/phpunit/Thelia/Tests/Action/ModuleHookTest.php create mode 100644 tests/phpunit/Thelia/Tests/Action/NewsletterTest.php create mode 100644 tests/phpunit/Thelia/Tests/Action/OrderStatusTest.php create mode 100644 tests/phpunit/Thelia/Tests/Action/OrderTest.php create mode 100644 tests/phpunit/Thelia/Tests/Action/PdfTest.php create mode 100644 tests/phpunit/Thelia/Tests/Action/ProductTest.php create mode 100644 tests/phpunit/Thelia/Tests/Action/ProfileTest.php create mode 100644 tests/phpunit/Thelia/Tests/Action/RewrittenUrlTestTrait.php create mode 100644 tests/phpunit/Thelia/Tests/Action/SaleTest.php create mode 100644 tests/phpunit/Thelia/Tests/Action/StateTest.php create mode 100644 tests/phpunit/Thelia/Tests/Action/assets/documents/sources/test-document-1.txt create mode 100644 tests/phpunit/Thelia/Tests/Action/assets/documents/sources/test-document-2.txt create mode 100644 tests/phpunit/Thelia/Tests/Action/assets/images/sources/test-image-1.png create mode 100644 tests/phpunit/Thelia/Tests/Action/assets/images/sources/test-image-2.png create mode 100644 tests/phpunit/Thelia/Tests/Action/assets/images/sources/test-image-3.png create mode 100644 tests/phpunit/Thelia/Tests/Action/assets/images/sources/test-image-4.png create mode 100644 tests/phpunit/Thelia/Tests/Action/assets/images/sources/test-image-5.png create mode 100644 tests/phpunit/Thelia/Tests/Action/assets/images/sources/test-image-6.png create mode 100644 tests/phpunit/Thelia/Tests/Action/assets/images/sources/test-image-7.png create mode 100644 tests/phpunit/Thelia/Tests/Action/assets/images/sources/test-image-8.png create mode 100644 tests/phpunit/Thelia/Tests/Action/assets/images/sources/test-image-9.png create mode 100644 tests/phpunit/Thelia/Tests/Api/ApiSendJsonTest.php create mode 100644 tests/phpunit/Thelia/Tests/Api/AttributeAvControllerTest.php create mode 100644 tests/phpunit/Thelia/Tests/Api/BrandControllerTest.php create mode 100644 tests/phpunit/Thelia/Tests/Api/CategoryControllerTest.php create mode 100644 tests/phpunit/Thelia/Tests/Api/CountryControllerTest.php create mode 100644 tests/phpunit/Thelia/Tests/Api/CurrencyControllerTest.php create mode 100644 tests/phpunit/Thelia/Tests/Api/CustomerControllerTest.php create mode 100644 tests/phpunit/Thelia/Tests/Api/IndexControllerTest.php create mode 100644 tests/phpunit/Thelia/Tests/Api/LangControllerTest.php create mode 100644 tests/phpunit/Thelia/Tests/Api/ProductControllerTest.php create mode 100644 tests/phpunit/Thelia/Tests/Api/ProductImageControllerTest.php create mode 100644 tests/phpunit/Thelia/Tests/Api/ProductSaleElementsControllerTest.php create mode 100644 tests/phpunit/Thelia/Tests/Api/TaxControllerTest.php create mode 100644 tests/phpunit/Thelia/Tests/Api/TaxRuleControllerTest.php create mode 100644 tests/phpunit/Thelia/Tests/Api/TitleControllerTest.php create mode 100644 tests/phpunit/Thelia/Tests/Api/fixtures/base.png create mode 100644 tests/phpunit/Thelia/Tests/Api/fixtures/fail.pdf create mode 100644 tests/phpunit/Thelia/Tests/ApiTestCase.php create mode 100644 tests/phpunit/Thelia/Tests/Command/BaseCommandTest.php create mode 100644 tests/phpunit/Thelia/Tests/Command/CacheClearTest.php create mode 100644 tests/phpunit/Thelia/Tests/Command/ConfigCommandTest.php create mode 100644 tests/phpunit/Thelia/Tests/Command/ModuleActivateCommandTest.php create mode 100644 tests/phpunit/Thelia/Tests/Command/ModuleDeactivateCommandTest.php create mode 100644 tests/phpunit/Thelia/Tests/Command/ModuleGenerateCommandTest.php create mode 100644 tests/phpunit/Thelia/Tests/Command/ModuleRefreshCommandTest.php create mode 100644 tests/phpunit/Thelia/Tests/Command/SaleCheckActivationCommandTest.php create mode 100644 tests/phpunit/Thelia/Tests/Condition/ConditionCollectionTest.php create mode 100644 tests/phpunit/Thelia/Tests/Condition/ConditionEvaluatorTest.php create mode 100644 tests/phpunit/Thelia/Tests/Condition/ConditionFactoryTest.php create mode 100644 tests/phpunit/Thelia/Tests/Condition/Implementation/CartContainsCategoriesTest.php create mode 100644 tests/phpunit/Thelia/Tests/Condition/Implementation/CartContainsProductsTest.php create mode 100644 tests/phpunit/Thelia/Tests/Condition/Implementation/ForSomeCustomersTest.php create mode 100644 tests/phpunit/Thelia/Tests/Condition/Implementation/MatchBillingCountriesTest.php create mode 100644 tests/phpunit/Thelia/Tests/Condition/Implementation/MatchDeliveryCountriesTest.php create mode 100644 tests/phpunit/Thelia/Tests/Condition/Implementation/MatchForEveryoneTest.php create mode 100644 tests/phpunit/Thelia/Tests/Condition/Implementation/MatchForTotalAmountTest.php create mode 100644 tests/phpunit/Thelia/Tests/Condition/Implementation/MatchForXArticlesTest.php create mode 100644 tests/phpunit/Thelia/Tests/Condition/Implementation/StartDateTest.php create mode 100644 tests/phpunit/Thelia/Tests/Condition/OperatorsTest.php create mode 100644 tests/phpunit/Thelia/Tests/Config/RoutesConfigTest.php create mode 100644 tests/phpunit/Thelia/Tests/ContainerAwareTestCase.php create mode 100644 tests/phpunit/Thelia/Tests/Controller/ControllerTestBase.php create mode 100644 tests/phpunit/Thelia/Tests/Controller/DefaultControllerTest.php create mode 100644 tests/phpunit/Thelia/Tests/Controller/ProductControllerTest.php create mode 100644 tests/phpunit/Thelia/Tests/Core/Archiver/ArchiverManagerTest.php create mode 100644 tests/phpunit/Thelia/Tests/Core/Event/ActionEventTest.php create mode 100644 tests/phpunit/Thelia/Tests/Core/Event/FooEvent.php create mode 100644 tests/phpunit/Thelia/Tests/Core/EventListener/RequestListenerTest.php create mode 100644 tests/phpunit/Thelia/Tests/Core/Form/TheliaFormFactoryTest.php create mode 100644 tests/phpunit/Thelia/Tests/Core/Hook/HookTest.php create mode 100644 tests/phpunit/Thelia/Tests/Core/HttpFoundation/RequestTest.php create mode 100644 tests/phpunit/Thelia/Tests/Core/HttpFoundation/Session/SessionTest.php create mode 100644 tests/phpunit/Thelia/Tests/Core/Propel/Schema/Fixtures/Expectation/SchemaCombineExpectation.php create mode 100644 tests/phpunit/Thelia/Tests/Core/Propel/Schema/Fixtures/schema/1.bar.schema.xml create mode 100644 tests/phpunit/Thelia/Tests/Core/Propel/Schema/Fixtures/schema/2.bar.schema.xml create mode 100644 tests/phpunit/Thelia/Tests/Core/Propel/Schema/Fixtures/schema/foo.schema.xml create mode 100644 tests/phpunit/Thelia/Tests/Core/Propel/Schema/SchemaCombinerTest.php create mode 100644 tests/phpunit/Thelia/Tests/Core/Routing/RewritingRouterTest.php create mode 100644 tests/phpunit/Thelia/Tests/Core/Serializer/Serializer/JSONSerializerTest.php create mode 100644 tests/phpunit/Thelia/Tests/Core/Serializer/SerializerManagerTest.php create mode 100644 tests/phpunit/Thelia/Tests/Core/Template/Element/BaseLoopTestor.php create mode 100644 tests/phpunit/Thelia/Tests/Core/Template/Loop/AccessoryTest.php create mode 100644 tests/phpunit/Thelia/Tests/Core/Template/Loop/AddressTest.php create mode 100644 tests/phpunit/Thelia/Tests/Core/Template/Loop/Argument/ArgumentCollectionTest.php create mode 100644 tests/phpunit/Thelia/Tests/Core/Template/Loop/AssociatedContentTest.php create mode 100644 tests/phpunit/Thelia/Tests/Core/Template/Loop/AttributeAvailabilityTest.php create mode 100644 tests/phpunit/Thelia/Tests/Core/Template/Loop/AttributeCombinationTest.php create mode 100644 tests/phpunit/Thelia/Tests/Core/Template/Loop/AttributeTest.php create mode 100644 tests/phpunit/Thelia/Tests/Core/Template/Loop/BrandTest.php create mode 100644 tests/phpunit/Thelia/Tests/Core/Template/Loop/CategoryTest.php create mode 100644 tests/phpunit/Thelia/Tests/Core/Template/Loop/ContentTest.php create mode 100644 tests/phpunit/Thelia/Tests/Core/Template/Loop/CountryTest.php create mode 100644 tests/phpunit/Thelia/Tests/Core/Template/Loop/CurrencyTest.php create mode 100644 tests/phpunit/Thelia/Tests/Core/Template/Loop/CustomerTest.php create mode 100644 tests/phpunit/Thelia/Tests/Core/Template/Loop/DocumentTest.php create mode 100644 tests/phpunit/Thelia/Tests/Core/Template/Loop/FeatureAvailabilityTest.php create mode 100644 tests/phpunit/Thelia/Tests/Core/Template/Loop/FeatureTest.php create mode 100644 tests/phpunit/Thelia/Tests/Core/Template/Loop/FeatureValueTest.php create mode 100644 tests/phpunit/Thelia/Tests/Core/Template/Loop/FolderTest.php create mode 100644 tests/phpunit/Thelia/Tests/Core/Template/Loop/HookTest.php create mode 100644 tests/phpunit/Thelia/Tests/Core/Template/Loop/ImageTest.php create mode 100644 tests/phpunit/Thelia/Tests/Core/Template/Loop/ModuleConfigTest.php create mode 100644 tests/phpunit/Thelia/Tests/Core/Template/Loop/ModuleHookTest.php create mode 100644 tests/phpunit/Thelia/Tests/Core/Template/Loop/ProductSaleElementTest.php create mode 100644 tests/phpunit/Thelia/Tests/Core/Template/Loop/ProductTest.php create mode 100644 tests/phpunit/Thelia/Tests/Core/Template/Loop/SaleTest.php create mode 100644 tests/phpunit/Thelia/Tests/Core/Template/Loop/TaxRuleTest.php create mode 100644 tests/phpunit/Thelia/Tests/Core/Template/Loop/TitleTest.php create mode 100644 tests/phpunit/Thelia/Tests/Coupon/CouponFactoryTest.php create mode 100644 tests/phpunit/Thelia/Tests/Coupon/CouponManagerTest.php create mode 100644 tests/phpunit/Thelia/Tests/Coupon/Type/FreeProductTest.php create mode 100644 tests/phpunit/Thelia/Tests/Coupon/Type/RemoveAmountOnAttributeValuesTest.php create mode 100644 tests/phpunit/Thelia/Tests/Coupon/Type/RemoveAmountOnCategoriesTest.php create mode 100644 tests/phpunit/Thelia/Tests/Coupon/Type/RemoveAmountOnProductsTest.php create mode 100644 tests/phpunit/Thelia/Tests/Coupon/Type/RemovePercentageOnAttributeValuesTest.php create mode 100644 tests/phpunit/Thelia/Tests/Coupon/Type/RemovePercentageOnCategoriesTest.php create mode 100644 tests/phpunit/Thelia/Tests/Coupon/Type/RemovePercentageOnProductsTest.php create mode 100644 tests/phpunit/Thelia/Tests/Coupon/Type/RemoveXAmountTest.php create mode 100644 tests/phpunit/Thelia/Tests/Coupon/Type/RemoveXPercentTest.php create mode 100644 tests/phpunit/Thelia/Tests/Files/FileManagerTest.php create mode 100644 tests/phpunit/Thelia/Tests/Files/fixtures/test.gif create mode 100644 tests/phpunit/Thelia/Tests/Files/fixtures/test.txt create mode 100644 tests/phpunit/Thelia/Tests/Form/CartAddTest.php create mode 100644 tests/phpunit/Thelia/Tests/Form/FirewallTest.php create mode 100644 tests/phpunit/Thelia/Tests/Form/OrderDeliveryTest.php create mode 100644 tests/phpunit/Thelia/Tests/Log/TlogTest.php create mode 100644 tests/phpunit/Thelia/Tests/Model/CurrencyTest.php create mode 100644 tests/phpunit/Thelia/Tests/Model/FeatureProductTest.php create mode 100644 tests/phpunit/Thelia/Tests/Model/MessageTest.php create mode 100644 tests/phpunit/Thelia/Tests/Model/ModuleConfigTest.php create mode 100644 tests/phpunit/Thelia/Tests/Module/BaseModuleTestor.php create mode 100644 tests/phpunit/Thelia/Tests/Module/Validator/Authors/Module1/Config/config.xml create mode 100644 tests/phpunit/Thelia/Tests/Module/Validator/Authors/Module1/Config/module.xml create mode 100644 tests/phpunit/Thelia/Tests/Module/Validator/Authors/Module2/Config/config.xml create mode 100644 tests/phpunit/Thelia/Tests/Module/Validator/Authors/Module2/Config/module.xml create mode 100644 tests/phpunit/Thelia/Tests/Module/Validator/Authors/Module3/Config/config.xml create mode 100644 tests/phpunit/Thelia/Tests/Module/Validator/Authors/Module3/Config/module.xml create mode 100644 tests/phpunit/Thelia/Tests/Module/Validator/Module1/Config/config.xml create mode 100644 tests/phpunit/Thelia/Tests/Module/Validator/Module1/Config/module.xml create mode 100644 tests/phpunit/Thelia/Tests/Module/Validator/Module2/Config/config.xml create mode 100644 tests/phpunit/Thelia/Tests/Module/Validator/Module2/Config/module.xml create mode 100644 tests/phpunit/Thelia/Tests/Module/Validator/Module3/Config/config.xml create mode 100644 tests/phpunit/Thelia/Tests/Module/Validator/Module4/Config/module.xml create mode 100644 tests/phpunit/Thelia/Tests/Module/Validator/Module5/Config/config.xml create mode 100644 tests/phpunit/Thelia/Tests/Module/Validator/Module5/Config/module.xml create mode 100644 tests/phpunit/Thelia/Tests/Module/Validator/ModuleValidatorTest.php create mode 100644 tests/phpunit/Thelia/Tests/Resources/Form/TestForm.php create mode 100644 tests/phpunit/Thelia/Tests/Resources/Form/Type/TestType.php create mode 100644 tests/phpunit/Thelia/Tests/Rewriting/BaseRewritingObject.php create mode 100644 tests/phpunit/Thelia/Tests/Rewriting/CategoryRewritingTest.php create mode 100644 tests/phpunit/Thelia/Tests/Rewriting/ContentRewritingTest.php create mode 100644 tests/phpunit/Thelia/Tests/Rewriting/FolderRewritingTest.php create mode 100644 tests/phpunit/Thelia/Tests/Rewriting/ProductRewriteTest.php create mode 100644 tests/phpunit/Thelia/Tests/Rewriting/RewritingResolverTest.php create mode 100644 tests/phpunit/Thelia/Tests/Rewriting/RewritingRetrieverTest.php create mode 100644 tests/phpunit/Thelia/Tests/TaxEngine/CalculatorTest.php create mode 100644 tests/phpunit/Thelia/Tests/TestCaseWithURLToolSetup.php create mode 100644 tests/phpunit/Thelia/Tests/Tools/FakeFileDownloader.php create mode 100644 tests/phpunit/Thelia/Tests/Tools/FileDownloaderTest.php create mode 100644 tests/phpunit/Thelia/Tests/Tools/PasswordTest.php create mode 100644 tests/phpunit/Thelia/Tests/Tools/URLTest.php create mode 100644 tests/phpunit/Thelia/Tests/Tools/Version/Version.php create mode 100644 tests/phpunit/Thelia/Tests/Tools/fixtures/test.xml create mode 100644 tests/phpunit/Thelia/Tests/Type/AlphaNumStringListTypeTest.php create mode 100644 tests/phpunit/Thelia/Tests/Type/AlphaNumStringTypeTest.php create mode 100644 tests/phpunit/Thelia/Tests/Type/AnyListTypeTest.php create mode 100644 tests/phpunit/Thelia/Tests/Type/AnyTypeTest.php create mode 100644 tests/phpunit/Thelia/Tests/Type/BooleanTypeTest.php create mode 100644 tests/phpunit/Thelia/Tests/Type/EnumListTypeTest.php create mode 100644 tests/phpunit/Thelia/Tests/Type/EnumTypeTest.php create mode 100644 tests/phpunit/Thelia/Tests/Type/FloatTypeTest.php create mode 100644 tests/phpunit/Thelia/Tests/Type/IntListTypeTest.php create mode 100644 tests/phpunit/Thelia/Tests/Type/IntToCombinedIntsListTypeTest.php create mode 100644 tests/phpunit/Thelia/Tests/Type/IntToCombinedStringsListTypeTest.php create mode 100644 tests/phpunit/Thelia/Tests/Type/IntTypeTest.php create mode 100644 tests/phpunit/Thelia/Tests/Type/JsonTypeTest.php create mode 100644 tests/phpunit/Thelia/Tests/Type/TypeCollectionTest.php create mode 100644 tests/phpunit/Thelia/Tests/WebTestCase.php create mode 100644 tests/phpunit/Thelia/Tests/bootstrap.php create mode 100644 tests/travis/install-casperjs.sh create mode 100644 unit-tests.bat create mode 100644 unit-tests.sh create mode 100644 web/favicon.ico create mode 100644 web/index.php create mode 100644 web/index_dev.php create mode 100644 web/robots.txt diff --git a/.env.dist b/.env.dist new file mode 100644 index 00000000..b3c87774 --- /dev/null +++ b/.env.dist @@ -0,0 +1,2 @@ +# This file is a "template" of which env vars need to be defined for your application +# Copy this file to .env file for development, create environment variables when deploying to production \ No newline at end of file diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 00000000..a19ade07 --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +CHANGELOG.md merge=union diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..381b5d94 --- /dev/null +++ b/.gitignore @@ -0,0 +1,81 @@ +local/config/build.properties +local/config/config_db.php +local/config/build +local/config/database.yml +local/config/database.yml.sample.save +local/config/key +core/vendor +local/config/runtime-conf.xml +cache/* +log/* +bin/* +local/session/* +coverage +.idea +.buildpath +.project +.settings/ +local/media/documents/* +local/media/images/* +!local/media/images/store/favicon.png +!local/media/images/store/logo.png +!local/media/images/store/banner.jpg +web/assets/* +web/cache/* +web/tinymce +web/media +phpdoc*.log +xhprof/ +phpunit.phar +.DS_Store +phpmyadmin +composer.phar +web/.htaccess +local/I18n/*.php +.docker/mysql-data/* +!.docker/mysql-data/.gitkeep + +# Ignore everything in the "modules" directory, except the "default modules" +local/modules/* +!local/modules/Cheque/ +!local/modules/Carousel/ +!local/modules/Front/ +!local/modules/FreeOrder/ +!local/modules/Tinymce/ +!local/modules/Colissimo/ +!local/modules/Hook*/ +!local/modules/VirtualProductDelivery/ +!local/modules/VirtualProductControl/ +!local/modules/TheliaSmarty/ +!local/modules/TheliaMigrateCountry/ +local/modules/HookTest/ + +# Ignore everything in the "templates" directory, except the "default template" +templates/* +!templates/frontOffice +templates/frontOffice/* +!templates/frontOffice/default +!templates/backOffice +templates/backOffice/* +!templates/backOffice/default +!templates/email +templates/email/* +!templates/email/default +!templates/pdf +templates/pdf/* +!templates/pdf/default + +#Ignore CodeKit +codekit-config.json +config.codekit +.codekit-cache + +#MacOS +.DS_Store + +# Ignore casperjs screenshots +tests/functionnal/casperjs/screenshot/ +tests/phpunit/Thelia/Tests/Api/fixtures/visuel*.png +/.docker/ +/.github/ +/.well-known/ diff --git a/.htaccess b/.htaccess new file mode 100644 index 00000000..d239cf73 --- /dev/null +++ b/.htaccess @@ -0,0 +1,3 @@ +# +#RedirectMatch 301 ^/$ https://auxbieauxlegumes.fr/web +# diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 00000000..badaa04f --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,1312 @@ +# 2.4.3 +- #2792 Add GithubActions +- #2791 Fix compatibility to composer 2 +- #2790 Fix state not checked in deliveries modules +- #2788 Fix issue #2787 TinyMce add link to img doesn't work +- #2785 Add config value to disallow module install by ZIP +- #2784 Fix TinyMce - display preview thumbs in a subfolder +- #2783 Fix state tax in product loop +- #2782 Fix typo in base tax rule names +- #2781 Improved the readme file +- #2780 Fix a bug where the path isn't correct if the template is in a directory +- #2779 Force return to page 1 after changing the limit of displayed products… +- #2777 The checkbox not appear on the product page - Tab Image +- #2776 Fix issue #2516 loop search_in param doesn't work +- #2775 Added tweeter feed to admin home +# 2.4.2 +- #2773 Add description to module composer skeleton +- #2772 Update default config values +- #2771 Better default tax rules names +- #2770 Add shared option for services (from SF 2.8) +# 2.4.1 +- #2765 Tax and Taxed price variables are now rounded in OrderProduct loop +- #2764 Fix MoneyFormat when have space in number +- #2763 Improvement on delivery events +- #2762 Fix total prices and taxes in order edit page +- #2761 Improve DeliveryPostage event to get more data +- #2760 Improve Pickup locations +- #2758 add a new event MODULE_DELIVERY_GET_PICKUP_LOCATION +- #2757 Fix model generation at module activation +- #2756 Fix Url are not rewritten if no locale in url +- #2754 Fix remove zero decimal on number > 1000 +- #2752 Order by alpha_reverse returns an error in feature-availability loops +- #2748 Upgrade docker compose to a more mordern stack +# 2.4.0 +- #2740 Fix defaultErrorFallback templateDfinition replacement +- #2739 Fix ignored_module_hook table update +- #2738 removed versionnable from schema example +- #2737 Add php < 7.4 requirements +- #2736 Optimized exports with JSON cache file and SQL request +- #2735 Tax calculation fixes, revamped +- #2734 Use select instead of input fields to choose template in B.O configuration parameter +- #2733 Carousel module improvements +- #2732 Sales are now considered done a invoice date +- #2731 Fix #2693 contents url on search page +- #2730 Fix issue #2698 bug on sales management +- #2729 Discount field is no longer require in CustomUpdateForm +- #2728 Fixed casperjs path +- #2724 Better discount calculation for untaxed prices +- #2721 Fix template delete issue +- #2718 Bump symfony/security from 2.8.47 to 2.8.50 +- #2717 Fix coupon condition matching +- #2716 New reference related parameters to order loop +- #2715 Fix bad success url for image form +- #2713 Bump symfony/http-foundation from 2.8.47 to 2.8.52 +- #2712 Bump symfony/cache from 3.4.18 to 3.4.35 +- #2710 Bump symfony/dependency-injection from 2.8.47 to 2.8.50 +- #2707 Improve product edit +- #2706 Fix mailing export col names +- #2705 Move date filtering to query initialization +- #2704 Fix double "[]" on choice render multiple +- #2697 Fix missing event in isStockManagedOnOrderCreation +- #2696 Add ID and ORDER_PRODUCT_ID to order_product_attribute_combination loop +- #2695 An empty cart is not a virtual cart +- #2691 Modules documentation display improvements +- #2687 Added a findAllChildId() method +- #2685 Added arrow navigation to documents and images management +- #2683 Fix tax rule collection query build when a state ID is passed to getTaxCalculatorCollection() +- #2681 Fix I18n when strictly mode is enable and only one I18n is present +- #2676 Fix Tlog on reponse when ConfigQuery is not generated on cache +- #2677 Profile management improvement +- #2673 Added quantity parameter to "Added to cart" popup url +- #2672 Improved import/export loops +- #2671 A 'change.pse' event is triggered on PSE value change +- #2670 Add company on BO customer address information +- #2665 Fix bad translation key +- #2664 Add BO brand search +- #2663 Improve SHOW_HOOK +- #2661 Fix issue #2660 +- #2659 Improved ajax management in CartController +- #2658 Customer email language fix when sent from the BO +- #2657 Add option to show/Hide stats bloc +- #2655 Update var name error MailerFactory.php +- #2651 Allow to load tax rule without country +- #2650 Fix attribute-edit.html smarty error +- #2649 Docker & Docker compose update +- #2648 Fix #2647 Wrong edition URL in message template +- #2646 Fix #2592 Add Delivery address in order loop search in +- #2645 Add new event on contact submit +- #2644 Change two redirection from 302 to 301 +- #2642 Fix missing parent preSave and postSave in Models +- #2640 Update address-update.html +- #2638 Remove Tlog in Propel init +- #2637 New "visible" parameter to pse loop +- #2634 Add phone on create customer modal +- #2633 Update propel dependency +- #2630 Change travis configuration, composer propel repo, root-namespace special compiled PHP functions +- #2629 Improve invoice and delivery interface +- #2628 Fix bo search order status color +- #2626 Front template improvements +- #2625 Disabled output compression when generating site map +- #2624 Exclude base_url from URL parameters +- #2623 Fix Tax calculator on country with state +- #2622 Propel schema generation is now protected from concurrency +- #2621 Add sort options to PSE loop, and allow to return all PSE +- #2618 Fix smarty cache default value, add country and customer_discount +- #2617 Added missing argument 'code' to the Coupon loop +- #2616 Allow use of CDN (e.g. alternate URL) on assets and documents +- #2615 feature_values filter is now working in Product loop +- #2614 Shipping zone configuration improvement +- #2613 Pagination fix +- #2611 Fixed loop arguments cache initialisation +- #2610 MailerFactory::send() is now wrapped in an exception handler +- #2609 Order details improvements +- #2608 Fix required fields for form smtp configuration +- #2607 Fix postage update when cart or coupon changes +- #2606 Added 3 new outputs to order loop +- #2605 Fix wrong order total (issue #2604) +- #2603 Added tax rule ID parameters to product loop +- #2602 Shipping zones button is no longer extra small in module list +- #2600 Check if symlink() is working when installing Thelia +- #2595 Fix Issue #2504 +- #2593 Add css class "pse_id_field" +- #2590 Fix non-numeric values in PDF templates +- #2589 Added invoice-date order criteria +- #2587 Add cache for loop ArgDefinitions +- #2586 Fix for #2505 BackOffice dashboard refresh button +- #2585 Improve propel cache +- #2584 Fix for getting choices options in forms +- #2582 Fix loop feature, filter template +- #2581 Composer remove useless dependency ramsey/array_column +- #2580 Fix module postActivation with new propel integration +- #2579 Composer remove symfony/icu on thelia core +- #2577 Set the error URL of the payment form +- #2576 Add deprecated model event +- #2575 Remove symfony/icu +- #2574 A missing hook will throw an error in dev mode only +- #2573 BO UI Fix btn edit content +- #2571 Fix thelia migration 2.3.4 -> 2.4.0-alpha2 +- #2570 Fix count null value php7.2 +- #2569 Prepare version 2.4.0-alpha2 +- #2568 Implementation symfony dotenv +- #2567 fix invalid exception +- #2566 Update composer file core +- #2565 Change Thelia dev ip protection +- #2564 Added call to parent method in model's event dispatching methods +- #2563 Removed all round() from the code +- #2561 Order status management improvement +- #2560 Lang should be active and currency visible to be used in front office +- #2558 BO UI renderer btn create +- #2557 BO UI Add possibility to remove btn text +- #2556 Update propel with event dispatcher +- #2555 The 'zip' extension is required to install modules +- #2553 PHP 7.2 forms buildForm() signature fix +- #2552 Minor back-office UI improvements +- #2551 Fix #2525 microdata +- #2547 BO new buttons integration +- #2546 Undefined loop should be in the loop stack +- #2545 Customer preferred language selection +- #2544 Fix constants propel deprecated +- #2543 Changed Travis CI config to use trusty distribution +- #2542 Smarty upgrade to version 3.1.33 +- #2541 add remove_zero_decimal parameter +- #2540 Add gitignore .DS_Store +- #2538 Minor code style fixes +- #2537 test if the module exists on the file system before generation cache +- #2536 Propel generation path fix +- #2535 Fix not countable args +- #2534 Composer update dependencies, fix symfony/var-sumper required version and add polyfill php7.3 +- #2533 Fix an infinite loop when the cache is cleared +- #2532 Add url sitemap.xml +- #2528 Patch for PRODUCT page +- #2524 wrong class name on Contact subject field +- #2522 Add email with mailto directly on order +- #2521 Add a new export "product I18n" +- #2519 Added ordering by PSE reference in PSE loop +- #2518 Fixed multiple times the same line in results +- #2517 fix/choice-render-multiple +- #2512 add missing formError use on 2.3 branch +- #2509 A "tinymce-editor-setup" event is sent when TinyMCE is ready +- #2507 Fix sale activation after sale update +- #2503 Added an explanatory message to disconnected exception +- #2502 Added category and brand ID in sidebar hooks +- #2501 PHP 7.1 compatibility fix in ExportHandler +- #2500 Fix newsletter unsubscribe/subscribe +- #2499 Using better headers to generate PDF response +- #2498 Fix for PHP 7.1 warning A non-numeric value encountered +- #2497 Remove unnecessary openssl extension install step +- #2495 Prevent setting the only default PSE to non-default +- #2494 Fixed Carousel module translations +- #2493 Keep product price & information when deleting the last PSE of a product +- #2492 Removed useless notice log +- #2489 fix order color issue in customer edit form +- #2487 Update composer.json of Thelia core + +# 2.4.0-alpha2 + +- #2486 Add compatibility with php 7.2 +- #2486 Update to Symfony 2.8.35 +- #2486 Add Symfony VarDumper for dev environment +- #2486 Update to Propel Alpha 8, special thanks to @bcbrr +- #2486 Update to Html2Pdf 5.2 +- #2483 Fix color status in search order +- #2482 Fix FreeOrder: round total amount to avoid problems with floats + +# 2.4.0-alpha1 + +- (related to #2266) Fix #2226 : Bad parsing of web version in db update script +- (related to #2265) Fix #2225 : Wrong version displayed in db update script +- (related to #2264) Fix #2263 : check php extension "dom" is installed +- (related to #2261) Cast position_delegate virtual column to number in product loop +- (related to #2259) Coupon - fix cart contains products & cart contains categories conditions +- (related to #2257) Coupon - fix order coupon amount +- (related to #2256) Coupon - add available on special offers in remove x amount type +- (related to #2255) Moved php shebang in the right file +- (related to #2254) Add parameter "module_code" to "modules.table-row" +- (related to #2251) Remove a forgotten debug instruction +- (related to #2250) Fix hook register listener that throws unucessary exceptions +- (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) Fixes #2229 : bad resource code in MailingSystemController class +- (related to #2239) Fixes #2233 : customer profile update +- (related to #2238) New method to save order transaction ref +- (related to #2237) Fixed cancelPayment method in BasePaymentModuleController class +- (related to #2235) Add amount in order coupon loop parse results +- (related to #2232) Moved to container-based infrastructure for Travis CI +- (related to #2231) Fix #2215 : loop pagination cache +- (related to #2230) Hook fixes +- (related to #2227) Fix for two problems with CART_FINDITEM event processing +- (related to #2224) Added simple message processing to MailerFactory +- (related to #2222) Fix duplicates in country loop when used with "with_area" argument +- (related to #2221) Completed default email template FR and EN translations +- (related to #2220) French translations +- (related to #2219) Fix coupons issues +- (related to #2217) Protected/hidden modules +- (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 #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 #2201) Deprecated class NotFountHttpException because typo and removed deprecated classes +- (related to #2198) Cancel coupon usage on order cancel +- (related to #2197) Pagination of coupon list +- (related to #2191) Update BO typo +- (related to #2190) Home stats improvements +- (related to #2189) Huge performance improvement in feature-availability loop +- (related to #2188) A more effective way to solve issue #2061 +- (related to #2187) Merge versions 2.1.10 2.2.4 2.3.2 in master branch +- (related to #2181) Fix CSV export cached file size +- (related to #2178) Add a coupon type to offer a product +- (related to #2174) PSR-6 + thelia.cache service and smarty cache block +- (related to #2173) Fix customer discount apply on backoffice +- (related to #2171) Fix sql syntax in setup/update/tpl/2.4.0-alpha1.sql.tpl +- (related to #2170) Fix #2166 : array to string conversion when php setup/update.php +- (related to #2168) Router redirect to last rewriting_url +- (related to #2167) Add global variable `app` to Smarty +- (related to #2166) Fixed the update process when thelia.net is out of order +- (related to #2165) Add replyTo parameter in mailer factory +- (related to #2164) Add confirmation email option after customer creation +- (related to #2163) Update fr_FR.php +- (related to #2161) State Fixes +- (related to #2160) Added missing home.block 'class' parameter +- (related to #2157) Prevent an infinite loop in new product dialog +- (related to #2155) Injects versions 2.1.9 2.2.3 2.3.1 in the master branch +- (related to #2154) Test range dates exists before testing type +- (related to #2153) Lighten placeholders color +- (related to #2150) Fix form and validator translations +- (related to #2149) Fixed status_id parameter access +- (related to #2148) Added search by EAN code to product sale elements loop +- (related to #2147) Fixed help text display if show_label is false +- (related to #2146) Fix search in i18n fields when backend_context=1, and search improvements +- (related to #2145) Fix for taxes & tax rules description display in Taxes rules page. +- (related to #2144) Fix sql_mode +- (related to #2143) Change order_adress in account-order +- (related to #2142) Force utf8 on thelia update +- (related to #2139) Start page correction +- (related to #2135) Fix ressources check for translation view +- (related to #2133) Add ORDER_UPDATE_TRANSACTION_REF event +- (related to #2132) Fix change default category and default folder +- (related to #2129) Fix order export date interval +- (related to #2128) Fix checkout issues +- (related to #2127) Fix for 2.3.0 BC break. +- (related to #2125) fix construct in GenerateRewrittenUrlEvent +- (related to #2123) Init Version 2.4.0-alpha1 +- (related to #2109) Module routers priority improvement (issue #2108) +- (related to #2107) Add create function for AlphaNumStringType argument +- (related to #2106) Added order-invoice form hooks +- (related to #2093) Fix #1662 add of hooks in pdf email and account-order +- (related to #2082) Fix issue #2003 : product and pse ref in invoice template +- (related to #2081) Order Status + + +# 2.3.3 + +- (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 + +- (related to #2150) Fix form and validator translations +- (related to #2147) Fixed help text display if show_label is false +- (related to #2145) Fix for taxes & tax rules description display in Taxes rules page +- (related to #2144) Fix automatic configuration for the sql_mode +- (related to #2142) Force utf8 on thelia update +- (related to #2139) Start page correction for the loops +- (related to #2135) Fix ressources check for translation view +- (related to #2132) Fix change default category and default folder. Since the pull request #2066, it's no longer possible to change the default category of a product or the default folder of a content. +- (related to #2129) Fix order export date interval +- (related to #2128) Fix address state check in delivery cost estimation and fix login error due to symfony update +- (related to #2127) Fix 2.3.0 major BC break in Thelia\Core\Event\Order\OrderPaymentEvent +- (related to #2125) Fix construct in GenerateRewrittenUrlEvent + +# 2.3.0 + +- #2121 Fix possible Compile Error in delivery loop +- #2117 Fix Admin update, the password is no longer required for update of an admin +- #2118 Module TinyMCE, fix the path for the Java uploader +- #2120 Fix {count} in search context, {count} doesn't work when searching (since 2.3.0 alpha-1) +- #2116 Updated translations from Crowdin +- #2110 Added a way to set specific date/time format for lang, fixed date/time format for fr_FR + +# 2.3.0-beta2 + +- #2030 Fix ziparchive not found, add a message to prevent that the zip extension was not found on the server +- #2104 Fixed update function issue in Colissimo module +- #2096 #2103 Fix currency change, an exception was thrown if the currency does not exist +- #2097 Fixed and improved cancel order processing +- #2095 Updated translations from Crowdin +- #2092 Fix Module TheliaSmarty, replace the request service by requestStack service +- #2091 Fixed NO_ENGINE_SUBSTITUTION setting for MariaDB +- #2090 Fix GenerateRewrittenUrlEvent, add getters and setters +- #2084 Check if customer exist in coupon builder + +# 2.3.0-beta1 + +- #2062 Remove composer dependency leafo/lessphp +- #2060 Fix BC, TaxRule action introduces a compatibility break +- #2080 Fix missing function `addoutputfields` in the loops +- #2078 Fixed checkbox and radio automatic rendrering. The "checked" status of checkboxes and radios was not correctly managed by form-field-attributes-renderer.html +- #2079 BackOffice : UX improvements on tablets, the right menu was too broad +- #2067 Fix esi render. The sub-request was not a Thelia request +- #2066 Fix the problem of position if a product or content in several sections and folders +- #2073 Use template default fallback in View Listener. Module views was not properly processed when the active front template is not "default" +- #2068 Fix customer edit view ACL, replace `update` by `view` for edit a customer +- #2063 Fix, when deleting a product with a free text feature value, the free text feature value was not removed +- #2058 Fix bug when sending the attribute combination builder form if the user had not selected attribute +- #2056 Fix UX bug on product list in the frontOffice, the grid icon or the list icon do not lock +- #2040 Fix bug when change image position on the module config page. The trait `PositionManagementTrait` was missing in `ModuleImage` +- #2054 Fix the update process for the Collissimo module + +# 2.3.0-alpha2 + +- #1985 Add delivery and payment events `MODULE_PAYMENT_IS_VALID`, `MODULE_PAYMENT_MANAGE_STOCK`, `MODULE_DELIVERY_GET_POSTAGE` +- #2045 Moves the backOffice statistics in the new module HookAdminHome +- #2044 Add possibility to change number by default of results per page for the product list, the order list and the customer list in the backOffice +- #2042 Avoid having too many results in the backOffice search page +- #2021 Fixes hooks `mini-cart`, `sale.top`, `sale.bottom`, `sale.main-top`, `sale.main-bottom`, `sale.content-top`, `sale.content-bottom`, `sale.stylesheet`, `sale.after-javascript-include`, `sale.javascript-initialization`, `account-order.invoice-address-bottom`, `account-order.delivery-address-bottom` +- #2041 Fix possible circular reference for category tree and folder tree +- #2039 Disable the output of the url by the loops on the BackOffice +- #2034 Add column position in attribute combination table +- #2028 Fixed translation regexp prefix for templates +- #2027 Confirmation email when subscribing to newsletter, and subscription cancel page +- #2017 Add constraint of unicity in create and update hook form +- #2012 Checking MySQL version to set sql_mode automatically, this fixed the compatibility with MySQL > 5.6 for modes `STRICT_TRANS_TABLES`, `NO_ENGINE_SUBSTITUTION` +- #2009 Display PSE ref in backOffice order edit for the product list +- #2001 Check PHP version before trying to do anything in install process +- #1999 Fix Folder breadcrumb, the parent url was not good if you edit a picture in a folder or a content +- #1998 Add not blank constraint on zipcode in address create form +- #1988 Fix hide module-install if auth are not right in the BackOffice +- #1907 Administrators should now have an email address. They may use login name or email to log in the back-office. They could now create a new a password if they forgot it. New minimum_admin_password_length and enable_lost_admin_password_recovery configuration variable. +- #1962 Fix exception when cloning a product if the i18n in specific locale does not exist +- #1933 #2006 #2016 #2033 Upgrade Symfony 2.3 to Symfony 2.8 +- #1995 Added order search options, improved search page in the backOffice +- #1994 Allow coupon in first cart step +- #1993 Fix the default language isocode link in backOffice languages page +- #1992 Add method to find category path `Thelia/Model/CategoryQuery::getPathToCategory` +- #1977 Fixed translation domain in NewsletterController +- #1980 Update database schema to increase module version field to 25 chars. +- #1971 #1973 Adds an address email to the administrator profile and adds the password lost functionality for administrators +- #1970 Add `CartDuplicationEvent` which provide both original and duplicated cart to listeners +- #1967 Module Colissimo : Replace country title by isoalpha2 in export for expeditor +- #1964 Fixed cart not deleted after an order placed +- #1960 Add events `CART_ITEM_CREATE_BEFORE` and `CART_ITEM_UPDATE_BEFORE` +- #1959 Add the ability to format an address by country +- #1907 Administrator email management and features + - adds an address email to the administrator profile + - This address email can now be used to login just like the login name + - An administrator could now recover a lost password, just like a regular customer +- #1958 Fix missing success_url on Brand SEO update +- #1956 Fix UX right class in brand products pagination in the frontOffice +- #1948 Allow to define custom delimiter and enclosure char for CSV serializer +- #1947 Added a way to get category/product from related content ID +- #1946 Fix l'inclusion automatique of the TaxType class only if extension == php +- #1939 Add `visible` and `visible_reverse` values in Product Loop order argument +- #1936 Fixed the module name vefication for command `module:position` +- #1931 Add a optional parameters CC and BCC in method `\Thelia\Mailer\MailerFactory::sendEmailMessage` +- #1929 Mod: BaseController useFallbackTemplate set to true by default +- #1928 Hook DI alert messages thrown as exceptions in dev. mode +- #1926 Fix redirection after coupon consume +- #1923 Re enabled functional tests for back office +- #1922 Colissimo Move the prices from a json to a config +- #1921 Modules 'configuration' and 'hook' buttons behavior fix +- #1920 Fixed coupons conditions label translation +- #1917 Fixed translations bug in user mode with view only missing translations activated +- #1916 Fix upload document. The document title is missing after upload +- #1914 The module list in the translation page is now ordered by module code instead of module title +- #1913 Conservation the emails after unsubscribe on newsletter +- #1911 Add 'admin_current_location' arg for 'main.in-top-menu-items' Hook +- #1908 A fix for "terms & conditions" bootbox height +- #1906 Fix coupon create form data +- #1904 Update tinyMCE +- #1903 Added missing generateErrorRedirect() +- #1895 Add a link to the contact page in the front footer and update bootstrap +- #1881 Display only the zones affected to Colissimo in the backOffice +- #1853 Coupon, add condition match for cart item include quantity +- #1815 #1963 #1984 #1989 #1997 #2013 #2019 Import/export complete rework + +# 2.3.0-alpha1 + +- #1907 Administrators should now have an email address. They may use login name or email to log in the back-office. They could now create a new a password if they forgot it. New ```minimum_admin_password_length``` and ```enable_lost_admin_password_recovery``` configuration variable. +- #1902 Update Colissimo export, add link to order and to customer, add package weight +- #1801 Fixed cart duplication conditions at user login/logout +- #1892 Add a name verification when creating a module with a command +- #1891 Add primary key in ```coupon_customer_count``` and ```ignored_module_hook``` tables. +- #1701 This PR improves the Order::createOrder() so that the method could be used to duplicate an order by re-using the delivery and invoice addresses defined in the original order. +- #1823 Add states/provinces concept. The objective of this PR is to separate states/provinces of countries. For now, the concept of states/provinces was managed in country model which was not the best way. +- #1878 Add module code in the lists of the BackOffice for a better understanding. +- #1832 Language improvement. Add the possibility to disable a language. It's possible to disable the language only for the front. +- #1851 Add in the module Tinymce, the possibility to choose in which text areas the editor will be used. +- #1840 Add the possibility to generate an url with the arguments ```router``` and ```route_id``` in the smarty function ```url```. Documentation ```http://doc.thelia.net/en/documentation/templates/urls-and-paths.html``` +- #1872 Add next/prev buttons for orders and customers. Modify the loops of brands, categories, folders and contents so that the queries to get the next and previous objects are sent only when it is needed. +- #1850 #1859 Add hooks for email template +- #1845 Add price including taxes in the combination creation pop-up in the BackOffice +- #1868 Allow to open order-edit.html template with a specific module tab +- #1861 Add links to the appropriate pages +- #1860 Change version of Symfony Yaml components +- #1843 Fix smarty form_collection_field, a performance problem was introduced after this PR: #1613 because ​the Form::createView() method create all form view on each call. +- #1856 Convert order.invoice_date to datetime column +- #1852 Add the possibility to disable the generation of url for the loops, adds argument ```return_url``` in loops, the default value for argument ```return_url``` is ```true``` +- #1857 Fix of hookblack : order.tab +- #1792 Update module Carousel, change the location of saving of the images +- #1844 #1848 Added hooks in the right column part of the edtion form of brand, content, category folder and product templates : + - ```brand.modification.form-right.top```, ```brand.modification.form-right.bottom``` + - ```category.modification.form-right.top```, ```category.modification.form-right.bottom``` + - ```content.modification.form-right.top```, ```content.modification.form-right.bottom``` + - ```folder.modification.form-right.top```, ```folder.modification.form-right.bottom``` + - ```product.modification.form-right.top```, ```product.modification.form-right.bottom``` +- #1835 Add the product combination in PDF delivery +- #1788 Remove all the AdminIncludes from the core modules. +- #1841 Add the possibility to create a product combination with several same attribute inside (2 colors in one product sales elements). +- #1830 Fix attribute title in the modal "create a new combination" +- #1780 Currency improvements. Add the possibility to disable a currency. Add the possibility to change the position of the currency symbol. Resolve #1446 +- #1825 Add message if thelia project is not installed +- #1714 #1839 #1833 Hook improvements + - Add new syntax to hook on a hook. Documentation ```http://doc.thelia.net/en/documentation/modules/hooks/index.html``` + - Add command ```php Thelia hook``` +- #1824 #1829 Fix the admin home stats, On page load, the month sent to Thelia was bad +- #1821 Fix the value for constant ```AdminForm::LANG_DEFAULT_BEHAVIOR```, Resolve ##1820 +- #1818 Fix BackOffice menu, hook block to integrate main link if it's used +- #1816 Fix the total price of cart if the items have a quantity greater than one, Resolve #1772, add new methods ```getTotalRealTaxedPrice```, ```getTotalTaxedPrice```, ```getTotalTaxedPromoPrice``` in the model ```Thelia\Model\CartItem``` +- #1783 Fix product price exports. Resolve #1078 #1610 +- #1808 Add customer's company in order mails and PDF +- #1780 Adds the ability to disable a currency and change the position of the currency symbol +- #1806 Fix the event dispatched before decoding of the import, ```TheliaEvents::IMPORT_AFTER_DECODE``` to ```TheliaEvents::IMPORT_BEFORE_DECODE``` +- #1799 Fixed the redirection to rewritten URL +- #1725 Added new attributes and some aliases to the {cart} substitution + - A new `weight` attribute is added, to get the cart total weight. + - A new `total_price_without_discount` attribute is added, to get the cart total amount without taxes, excluding discount. + - The following aliases of existing attributes are added, to provide a better english syntax, or a more accurate name : + - `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` +- #1802 After upload, The image file name is no longer the default image title +- #1805 Add a new parameter ```locale``` for the module_config smarty plugin +- #1796 Fix regression in OrderAddressEvent cell phone can not be required in the constructor +- #1787 Add loop Overriding, Documentation ```http://doc.thelia.net/en/documentation/loop/extend.html``` +- #1785 Fix undesirable carts, persist only non empty carts +- #1790 Update the default PSE ref when the product ref is updated +- #1778 #1797 Add ```manual``` and ```manuel_reverse``` order in attributeCombination loop +- #1766 Add order by ```id``` and ```id_reverse``` in product_sale_element loop +- #1760 Set order status as paid when the FreeOrder module is used to "pay" an order +- #1751 Fix for undefined currency exchange rate, add error message in the currency configuration page when an exchange rate could not be found +- #1769 Increase API key size to 48 +- #1771 Add argument ```customer_id``` for hook customer.edit-js +- #1753 Fix the rounding of prices in the order product loop +- #1768 Update composer.lock file, update of the dependency thelia/currency-converter to version 1.0.1 +- #1752 Add addValues method in EnumListType +- #1746 Removes deprecated classes and methods for the version 2.3 +- #1745 Fix output value IS_DEFAULT in the product_sale_elements loop +- #1754 Add homepage redirection on /admin/login if the admin is already authenticate. Before this change, there was a render +- #1765 Fix for prev/next queries in Category and Content loops, and add prev/next in Product and Folder loop +- #1759 Fix for parent attribute and new exclude_parent attribute of Category loop +- #1750 Add EQUAL to product loop filter by min or max +- #1727 Add template & stock inputs on product creation +- #1722 Replaced parameter "locale" with "lang" in generated URL +- #1732 Update sql constraint for table product_sale_elements_product_image and product_sale_elements_product_document +- #1730 Change layout to only cache assets/dist +- #1734 Fix critical performance issue on ProductController HydrateObjectForm +- #1733 Fix order attribute in BaseHook +- #1729 Fix all useless DIRECTORY_SEPARATOR +- #1726 Fix method setRangeDate variable +- #1718 Autocomplete combination generation form with default pse values +- #1699 Fix missing use for BirthdayType +- #1713 Add more options for content, folder and order in search results +- #1706 Fix form coupon not found in frontOffice order invoice +- #1700 Fix source priority in ```ParserContext::getForm``` +- #1588 Add document tab in frontOffice product page +- #1668 Add height limit for the select fields in the Attributes and Features tab of the admin product edit page +- #1669 Add options ```exclude_status, status_code, exclude_status_code``` and output value ```STATUS_CODE``` in Order 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` + + +# 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 + +- (related to #2147) Fixed help text display if show_label is false +- (related to #2144) Fix automatic configuration for the sql_mode +- (related to #2142) Force utf8 on thelia update +- (related to #2139) Start page correction for the loops +- (related to #2135) Fix ressources check for translation view +- (related to #2125) Fix construct in GenerateRewrittenUrlEvent +- (related to #2118) Module TinyMCE, fix the path for the Java uploader +- (related to #2096) Fix currency change, an exception was thrown if the currency does not exist +- (related to #2090) Fix GenerateRewrittenUrlEvent, add getters and setters +- (related to #2084) Check if customer exist in coupon builder +- (related to #2080) Fix missing function `addoutputfields` in the loops +- (related to #2078) Fixed checkbox and radio automatic rendrering. The "checked" status of checkboxes and radios was not correctly managed by form-field-attributes-renderer.html +- (related to #2068) Use template default fallback in View Listener. Module views was not properly processed when the active front template is not "default" +- (related to #2068) Fix customer edit view ACL, replace `update` by `view` for edit a customer +- (related to #2058) Fix bug when sending the attribute combination builder form if the user had not selected attribute +- (related to #2052) Fix #2040 Missing trait PositionManagementTrait in ModuleImage +- (related to #2041) Fix possible circular reference for category tree and folder tree +- (related to #2017) Add constraint of unicity in create and update hook form +- (related to #2012) Checking MySQL version to set sql_mode automatically, this fixed the compatibility with MySQL > 5.6 for modes `STRICT_TRANS_TABLES`, `NO_ENGINE_SUBSTITUTION` +- (related to #2010) Improve product price edition tab +- (related to #2005) Use a wider version requirement on thelia/installer for setup/ +- (related to #1999) Fix Folder breadcrumb, the parent url was not good if you edit a picture in a folder or a content +- (related to #1980) Update database schema to increase module version field to 25 chars. +- (related to #1967) Module Colissimo : Replace country title by isoalpha2 in export for expeditor +- (related to #1962) Fix exception when cloning a product if the i18n in specific locale does not exist +- (related to #1958) Fix missing success_url on Brand SEO update +- (related to #1956) Fix UX right class in brand products pagination in the frontOffice +- (related to #1946) Fix the automatic inclusion of the TaxType class only if extension == php +- (related to #1939) Add `visible` and `visible_reverse` values in Product Loop order argument +- (related to #1936) Fixed the module name verification for command `module:position` +- (related to #1928) Hook DI alert messages thrown as exceptions in dev. mode +- (related to #1921) Modules 'configuration' and 'hook' buttons behavior fix +- (related to #1920) Fixed coupons conditions label translation +- (related to #1917) Fixed translations bug in user mode with view only missing translations activated +- (related to #1914) The module list in the translation page is now ordered by module code instead of module title +- (related to #1908) A fix for "terms & conditions" bootbox height +- (related to #1906) Fix coupon create form data +- (related to #1799) Fixed the redirection to rewritten URL +- (related to #1797) Fix order manual and manual_reverse in AttributeCombination loop +- #1901 Update Colissimo export, add link to order and to customer, add package weight + +# 2.2.2 + +- #1901 Update Colissimo export, add link to order and to customer, add package weight +- (related to #1857) Fix of hookblack : order.tab +- (related to #1843) Fix smarty form_collection_field, a performance problem was introduced after this PR: #1613 because ​the Form::createView() method create all form view on each call. +- (related to #1830) Fix attribute title in the modal "create a new combination" +- (related to #1825) Add message if thelia project is not installed +- (related to #1824 #1829) Fix the admin home stats, On page load, the month sent to Thelia was bad +- (related to #1821) Fix the value for constant AdminForm::LANG_DEFAULT_BEHAVIOR, Resolve ##1820 +- (related to #1818) Fix menu hook block to integrate main link if it's used #1818 +- (related to #1806) Fix the event dispatched before decoding of the import, TheliaEvents::IMPORT_AFTER_DECODE to TheliaEvents::IMPORT_BEFORE_DECODE +- (related to #1796) Fix regression in OrderAddressEvent cell phone can not be required in the constructor +- (related to #1790) Update the default PSE ref when the product ref is updated +- (related to #1783) Fix product price exports. Resolve #1078 #1610 +- (related to #1771) Add argument customer_id for hook customer.edit-js +- (related to #1769) Increase API key size to 48 +- (related to #1768) Update composer.lock file, update of the dependency thelia/currency-converter to version 1.0.1 +- (related to #1760) Set order status as paid when the FreeOrder module is used to "pay" an order +- (related to #1753) Fix the rounding of prices in the order product loop +- (related to #1751) Fix for undefined currency exchange rate, add error message in the currency configuration page when an +- (related to #1750) Add EQUAL to product loop filter by min or max +- (related to #1747) Fixed success_url check for contact form +- (related to #1745) Fix output value IS_DEFAULT in the product_sale_elements loop + +# 2.2.1 + +- (related to #1699) Fix missing use for BirthdayType +- (related to #1700) Fix form retrieving +- (related to #1706) Fix coupon form +- (related to #1713) Add more options for content, folder and order in search results +- (related to #1722) Replaced parameter "locale" with "lang" in URL generated +- (related to #1724) Fix customer update input ID and indentation +- (related to #1726) Fix method setRangeDate variable in ExportHandler +- (related to #1729) Fix all useless DIRECTORY_SEPARATOR +- (related to #1730) Change layout to only cache assets/dist +- (related to #1732) Update sql constraint for table product_sale_elements_product_image and product_sale_elements_product_document +- (related to #1733) Fix order attribute in BaseHook +- (related to #1734) Fix critical performance issue on ProductController HydrateObjectForm +- (related to #1727) Add template & stock inputs on product creation + +# 2.2.0 + +- #1692 Fix amounts displayed on the PDF invoice when a postage with tax is used (fixes #1693 and #1694) +- #1692 Fix translations for HookNavigation module +- #1692 Update hooktest-template and hooktest-module to prevent thelia-installer conflicts +- #1692 Update French, German, Italian translations +- #1692 Add Turkish translation +- #1688 Fix the permission messages in Thelia installer +- #1686 Use createForm method for front forms ```thelia.coupon.code, thelia.order.delivery, thelia.order.payment``` +- #1667 Fix #1666 Display an error when trying to delete a customer which has orders +- #1665 Fix form field type date in Smarty plugin form, checks if the field type is a BirthdayType for assign a smarty variable [years, month, days] +- #1659 Fix Administrator edit action in the BackOffice, it was impossible to edit an administrator + +# 2.2.0-beta3 + +- #1653 Remove ```AdminIncludes``` folder in the module generation +- #1649 Add index in table rewriting_url +- #1644 Allow relative path use with Tlog +- #1640 Add docker and docker-compose configuration +- #1637 Fix admin API edit button +- #1635 Add unit tests for the routing files (admin, api, front) +- #1634 Remove leftover uncallable routes (admin) +- #1631 Remove duplicate route (admin) +- #1629 Fix errors reporting of admin hooks +- #1632 Fix pagination infinite URL ; redirect on page 1 when changing products per page limit to avoid having no product on the page +- #1616 Improve statistic on homepage, add datetimepicker and fix first order +- #1601 Add set error in TheliaFormValidator when form is not valid +- #1585 Add parameters in frontOffice hooks +- #1587 Fix redirect url for the folder image and folder document +- #1590 Fix Thelia request initialization +- #1593 Fix form serialization in session that contain uploaded files +- #1594 update symfony/validator version to 2.3.31 +- #1598 composer.json update dependency fzaninotto/faker to stable version 1.5 +- #1583 Add German translations +- #1615 New TheliaEvents::CART_FINDITEM event to improve cart management flexibility +- #1618 Configurable faker +- #1581 Fix the prices precision + - Not round the prices without tax in back office + - Change the type for the price columns in database. New type : decimal(16,6) + +##DEPRECATED + +- Deprecated AdminIncludes, it's better to use the hooks + +# 2.2.0-beta2 + +- Add module image edition in backoffice +- The language change links should now use the locale instead of the language code, e.g. http://www.yourshop/some-page?lang=fr_FR instead if http://www.yourshop/some-page?lang=fr. Backward compatibility is provided. +- Order status added by modules have their CSS label color handled or have a default color +- New login page style +- New general style of backoffice +- New dashboard arrangement + +# 2.2.0-beta1 + +- Fix currency create action to set the by_default field properly. +- Add missing column default_template_id in category_version table +- The product parameter of the feature_value loop is no longer mandatory +- The product parameter new $PRODUCT variable is deprecated. $PRODUCT_ID should be used instead. +- Fix smarty `format_date` function to use consistent format when `locale` attribute is used. +- A product and all it's dependencies can now be cloned +- Fix index form error information session cleaning +- Feature's free text values now handle i18n +- URLs now have no problem with accents or case +- Add order by ```weight``` and ```weight_reverse``` in product sale elements loop +- Add the ability to remove arguments in loops. +- new back-office is enhanced with a group button actions and a new layout +- Added an optional 'ajax-view' parameter to card add form +- Add validation groups in form from parser context +- Feature value are not translatable +- Allow multiple authors in module.xml file. Fixed #1459 +- Display the mini cart with a hook. Fixed #1233 +- Add date range for order export +- Klik&Pay is no more a submodule + +# 2.2.0-alpha2 + +- Add a front office way to make an address the default one +- New translation domain that allows to redefine translation strings globally or specifically to a domain. By the way, we can safely update Thelia, modules, templates without overwriting specific translations. +- Remove ```currency_rate_update_url``` in ```setup/insert.sql``` +- Add Cellphone to order address +- Add AnyListTypeArgument for loop argument +- New command ```module:position```. This command can changes module position +- Fix session serialisation +- Create a template context +- Allow relative path for the file logger from THELIA_ROOT constant +- Form error information are stored in the user session +- Fix redirection with slash ended uri. Fix #1331 +- Config ```images_library_path``` and ```documents_library_path``` are now used everywhere +- Messages dispatched before and after content creation +- Add link to open pdf directly in browser in BO order/update +- Added wysiwyg.js hook where it was missing. +- Fix hook attribute in pdf template. The hook was never called. +- Cellphone column Added in order_address table +- Default front office template revamped : + - bower and grunt can be used (but not mandatory, you can still use assetic) + - less than 4095 css selectors (IE9 compatibility) + - bootstrap is now fully used + - this template is documented in its readme +- Force locale in session when loading a rewriten url +- Thelia is now fully usable with HTTPS protocol +- Do not delete the default product_sale_elements when the template of a product change +- Added standard 'error_url' parameter, like 'success_url' +- controller type can be found in the request (#1238) +- new helper to get order weight +- update selected delivery address in order process when customer change it +- new hooks for delivery modules in backoffice and pdf to add extra information + +# 2.2.0-alpha1 + +- Add module code ($CODE variable) into payment loop outputs +- Add the 'images-folder' tag into module.xml file to deploy the modules images +- Add the 'module:list' command, that shows the modules state +- Update Admin Logs to add the resource ID when available. +- Add render smarty function, that executes the controller given in the action parameter. +- Allow modules to use document and image loop with the ```query_namespace``` argument +- Enable image zoom in image loop before cropping to guarantee that the resulting image will match the required size, even if the original image is smaller. This feature is active only if the ```allow_zoom``` parameter is true. +- When in development mode, an exception is thrown when an error occurs when processing assets, thus helping to diagnose missing files, LESS syntax errors, and the like. +- Change default order for cart loop +- New module_config Smarty function: {module_config module="module-code" key="parameter-name} +- Do not register previous url on XmlHttpRequest +- Add ACL on documents and images tabs. +- Add confirmation modal on documents deletion +- Add shop language choice on install wizard +- Remove redundant * on product-edit +- Add parameter "page_param_name" for template admin pagination.html. if "page_param_name" is empty, then the name of the parameter is "page" +- Add "Refunded" order status +- Add environment specific config file loading in modules +- Add the possibility for customers to change their email, backoffice configuration variables customer_change_email +- Add confirmation email for customers, backoffice configuration variables customer_confirm_email +- Refactor ```Thelia\Controller\BaseController::createForm``` into a factory service ```Thelia\Core\Form\TheliaFormFactory``` +- Refactor ```Thelia\Controller\BaseController::validateForm``` and ```Thelia\Controller\BaseController::getErrorMessages``` into a service ```Thelia\Core\Form\TheliaFormValidator``` +- Add the `failsafe=[true|false]` parameter to the assets Smarty functions (stylesheets, images, javascripts). +- A country could belong to more than one shipping zone. +- Add the `exclude_area` parameter to the Country loop. +- The Country loop now returns a proper country ISO code, left-padded with zeros, e.g. '004' instead of '4' +- The Country::getAreaId() method is DEPRECATED. +- Add the `country` and `order` parameters to Area loop +- Add the `area` parameter to Module loop +- Improved Shipping zones management +- Add cache on the graph of the home page, possibility to disable cache or change ttl cache, with the configuration variable admin_cache_home_stats_ttl +- New feature: a default product template could be defined in categories. Products created in this category will get this default product template. If no default product template is defined in a given category, it will be searched in parent categories. +- New main navigation style and position +- jquery.ui.datepicker is now DEPRECATED and will be REMOVED in 2.3. Please use boostrap-datepicker +- Add ```thelia.logger``` service to prepare the transition with another logger. +- Add 62 new admin hook +- Add stacked current form into parser context. It allows to have nested forms while using the new way to write forms. +- Module information and documentation could be viewed directly from the module list +- Add the possibility to translate text in the sql files (insert.sql, update/sql/\*.sql). to generate sql files use command `php Thelia generate:sql`. Translation can be made in the back office, in the translation page. +- format_date smarty function now handle symfony form type ```date```, ```datetime``` and ```time``` view value. +- Allow BaseController::generateOrderPdf to generate a pdf without having the rights +- SHOW_HOOK now displays parameters +- Add fallback for email template for mails sent from a module. If the template file does not exist in the current email template, it will use the one that comes with the module. +- Add dispatch of console events +- Refactor VirtualProductDelivery module. The email sending is now triggered from a new event to gain more flexibility. Now, email messages use smarty file templates located in `templates/email/default`. +- Added capability to use translator in module functions `preActivation` and `postActivation` +- Add environment aware database connection +- new 'asset' Smarty function, to get the URL of an arbitrary file from template assets, such as a video or a font. +- Imagine package is updated to 0.6.2, which provides a better support for transparency. +- 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 + + +# 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 + +- (related to #2144) Fix automatic configuration for the sql_mode +- (related to #2139) Start page correction for the loops +- (related to #2135) Fix ressources check for translation view +- (related to #2125) fix construct in GenerateRewrittenUrlEvent +- (related to #1920) Fixed coupons conditions label translation +- (related to #1946) Fix TaxType class only if extension == php +- (related to #1958) Missing success_url on Brand SEO update +- (related to #1967) Replace country title by isoalpha2 in export for expeditor +- (related to #1999) Update FolderBreadcrumbTrait.php +- (related to #2005) Use a wider version requirement on thelia/installer for setup +- (related to #2091) Checking MySQL version to set sql_mode automatically +- (related to #2041) Fix possible circular reference for category tree and folder tree +- (related to #2058) Fix Bug on submit combination builder empty form +- (related to #2068) Fix customer edit access +- (related to #2073) Use template default fallback in View Listener + +# 2.1.8 + +- Fix Colissimo module external-schema (related to #1838) +- Fix attribute title in the modal "create a new combination" (related to #1830) +- Add message if thelia project is not installed (related to #1825) +- Fix the event dispatched before decoding of the import, TheliaEvents::IMPORT_AFTER_DECODE to TheliaEvents::IMPORT_BEFORE_DECODE (related to #1806) +- Update the default PSE ref when the product ref is updated (related to #1790) +- Sanitize the get arguments for admin stats (related to #1782) +- Add argument customer_id for hook customer.edit-js (related #1771) +- Increase API key size to 48 (related #1769) +- Fix for undefined currency exchange rate, add error message in the currency configuration page when an exchange rate could not be found (related #1751) +- Fix the rounding of prices in the order product loop (related to #1753) +- Add EQUAL to product loop filter by min or max (related to #1750) +- Fix output value IS_DEFAULT in the product_sale_elements loop (related to #1745) + +# 2.1.7 + +- Fix all useless DIRECTORY_SEPARATOR (related to #1729) +- Update sql constraint for table product_sale_elements_product_image and product_sale_elements_product_document (related to #1732) +- Fix order attribute in BaseHook (related to #1733) +- Fix critical performance issue on ProductController HydrateObjectForm (related to #1734) +- Replaced parameter "locale" with "lang" in URL generated (related to #1722) + +# 2.1.6 + +- Fix amounts displayed on the PDF invoice when a postage with tax is used (fixes #1693 and #1694). +- Check virtualProducts of order before send mail ```mail_virtualproduct``` +- Add 'step' to input type number to be able to create and edit weight slices price +- Fix pagination infinite URL ; redirect on page 1 when changing products per page limit to avoid having no product on the page +- Allow relative path use with Tlog +- Prevent obscure "[] this value cannot be null" messages. +- Prevent short research and keep research in input +- Fix meta return array +- Fix hook position +- Fix Protocol-relative URL for HTTPS +- Update Copyright +- Fix translations and standardize Import and Export texts +- Fix the prices precision + +# 2.1.5 + +- Klik&Pay is no more a submodule +- default category's parent is now 0 +- 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 +- keep break line in ACE editor + +# 2.1.4 + +- Add ```export.top``` and ```export.bottom``` hooks +- Fix slash ended rewritten url redirection +- Remove ```currency_rate_update_url``` in ```setup/insert.sql``` +- Allow relative path for the file logger from THELIA_ROOT +- Fixed product loop behavior when category_default is set +- Force locale in session when loading a rewriten url +- Add port parameter for installing thelia with cli tools +- Change default param of the isPaid function, true is the good default parameter. + +# 2.1.3 + +- Add ```\Thelia\Model\OrderProduct::setCartItemId``` and ```\Thelia\Model\OrderProduct::getCartItemId``` to remove the typo with ```cartIemId``` +- A notice is displayed when the product's template is changed +- Security fix on authentication +- Rename cookie related config variables. They were prefixed with "thelia_" on insert, but not in the code + +## DEPRECATED + +- ```\Thelia\Model\OrderProduct::setCartIemId``` Because of a typo +- ```\Thelia\Model\OrderProduct::getCartIemId``` Because of a typo too + +# 2.1.2 + +- Add the possibility to delete a coupon from the backoffice. +- module list is now reversed. Delivery modules appear first, then payment and finally classic modules. +- display a loader when a module is uploaded +- Change product prices export and import format to be compatible, now using product_sale_elements id as key to identify PSE. +- Fix unused variable in ```Thelia\Controller\Api\CustomerController::getDeleteEvent``` +- change default order for cart loop. +- Add missing static keyword for ```Thelia\Core\HttpFoundation\JsonResponse::createError``` +- Do not register previous url on XmlHttpRequest +- Fix deploy image directory destination +- Fix redirect response if a AuthenticationException is catched +- The PaymentModule log default level is now INFO instead of ERROR +- Direct instantiations of Thelia forms is deprecated. BaseController::createForm() should be used instead. +- Prevent XSS injection in error.html template +- The hook method is now stored in the ignored_module_hook table +- Allow to hardlink TinyMCE rather than symlink +- Add bootstrap paths for thelia-project +- Enlarge order dropdown menu to prevent wrapping in some languages +- Fixed langugage when previewing e-mails + +# 2.1.1 + +- Fix update process from Thelia 2.0.* to 2.1.* + +# 2.1.0 + +- abilities to translate email and pdf templates in modules +- support of taxes for postage amount +- sales modify price on update only if the sale is currently active +- cart can be used without thelia cart cookie. Set cart.use_persistent_cookie to 0 in your config variable panel. +- hook contains more information like the id of the current object you are working on. +- fix module skeleton location + + +# 2.1.0-beta2 + +- config : + - environment variable can be used in the database.yml file. See [https://github.com/thelia/thelia/pull/968](https://github.com/thelia/thelia/pull/968) + - Allow other projects to override thelia directories constants by using composer "autoload"["file"] entries +- smarty: + - Add the "current" argument on smarty "url" function that allows you to get the same page but with differant url parameters +- new method ```manageStockOnCreation``` in PaymentModuleInterface. If return false, the stock will be decreased on paid status instead of order creation. +- Thelia: + - Split Thelia on multiple repositories to allow a better version management with composer. For creating a new project, see [https://github.com/thelia/thelia-project] + - Extract all the default modules into other repositories + - Field type : + - added area_id, category_id, folder_id, content_id + - thelia type support render_form_field +- loop `product_sale_elements` : added `ref` argument and implemented `SearchLoopInterface` +- Updated `hasVirtualProduct` in `Order` model to not test the presence of filename, as modules could implement the process differently +- new method ```Thelia\Model\Module::getDeliveryModuleInstance()``` return the delivery module instance for the current record. +- 'freesans' is now the default font of PDF documents +- Anonymous cart is no longer duplicated on customer login + + +# 2.1.0-beta1 + +- Autoload : the autoloader can be cached with Apc or XCache. See new index.php file. +- Update : add missing API table creation +- The default Tlog level is now TLog::ERROR instead of Tlog::DEBUG +- Add error message pages instead of white pages. But you can disable them by setting 0 into the config variable "error_message.show". +- Front Office Template: new page to display the details of an order +- email can be previewed in the back office +- some smarty classes are still present in the core of thelia not to break backward compatibility. Those classes will be deleted in version 2.3 : + * Thelia\Core\Template\Smarty\AbstractSmartyPlugin + * Thelia\Core\Template\Smarty\SmartyPluginDescriptor +- the default address label is now translated +- fixed "strictly use the requested language" +- new config variable : + * session_config.lifetime : Life time of the session cookie in the customer browser, in seconds + * error_message.show : Show error message instead of a white page on a server error + * error_message.page_name : Filename of the error page. Default : error.html +- All cs issues are fixed, Thelia is now fully PSR2 compliant +- Allow possibility to upload a module with github suffix (eg : paypal-master.zip) +- Added a fallback for template to use the default template. it's useful for modules that are used on a website that doesn't use the default template + +# 2.1.0-alpha2 + +- Update Process : + - update command has been removed and replaced by a php script and a web wizard. Read the UPDATE.md file +- Templating : + - Smarty is now a dedicated Module and no more present in the core of Thelia + - All the template logic works now with abstracted class or interface, so it is possible to create a new Module for +an other template engine + - A new interface has been introduced, the ParserHelperInterface : its purpose is to parse a string and get all +parser's function and block with theirs arguments. + - A new service has been introduced : thelia.parser.helper and it must be the implementation of ParserHelperInterface + - If you want to create a new Template module, you must declare those services : + - thelia.parser : the class that implements ParserInterface + - thelia.parser.helper : the class that implements ParserHelperInterface + - thelia.parser.asset.resolver : the class that implements AssetResolverInterface +- Routing : + - new notation ```a:b:c``` => ```Foo:Bar:Baz``` will execute ```Foo\Controller\BarController::BazAction``` method +- Module : + - New schema for modules + - Module installation from back office + - Dependency check to Thelia version and other modules during installation, activation, deactivation and deletion +- Smarty : + - new plugin ```flash``` to support symfony flash message. + - new plugin ```default_locale```. This function is used for forcing the usage of a specific locale in all your template. Useful for email and pdf. eg : ```{default_locale locale="en_US"}``` + - function ```intl``` has a new argument : ```locale```. If used, this locale will be used instead of session's locale +- Loop : + - new method addOutputFields in order to add custom fields in an overridden loop +- Tests: + - Move tests from ```core/lib/Thelia/Tests``` to ```tests/phpunit/Thelia/Tests``` + - Update PHPUnit from 4.1.3 to 4.1.6 +- Symfony components: + - Update from 2.3.* to 2.3.21 +- REST API: + - Implement the first version of the REST API. You can find the documentation [here](http://doc.thelia.net/en/documentation/api/authentication.html) +- Forms: New implementation of Symfony form component that now handles form types, form extensions and form type extensions + - You can use the tags ```thelia.form.type```, ```thelia.form.extension``` and ```thelia.form.type_extension``` to declare yours + - Implementation of many form types for thelia, see the namespace Thelia\Core\Form\Type + +## DEPRECATED + +- ```\Thelia\Core\HttpFoundation\Session\Session::getCart``` is deprecated. Use ```getSessionCart``` instead. +- ```\Thelia\Cart\CartTrait``` trait is deprecated. Use ```\Thelia\Core\HttpFoundation\Session\Session::getSessionCart``` for retrieving a valid cart. + +#2.1.0-alpha1 + +- Added sale management feature +- Added `module_id` parameter to Area loop +- Added "Shipping configuration" button to the delivery module list, with a warning if no shipping zone is assigned to the module. +- Added the `show_label` parameter to the `render_form_field Smarty` function. +- Added the `exclude` parameter to `form_hidden_field` function. +- Added the `product` parameter to the `attribute_availability` loop. +- Added the `sale` parameter to the `product` loop. +- Added visible argument to image/document classes +- Added `new`, `promo` and `default` parameters to `product_sale_elements` loop +- Added `store_notification_emails`, which contains the recipients of shop notification (such as order placed) +- Added admin notification e-mail for order placed +- Improved other emails (specially text versions) +- Added ORDER_SEND_NOTIFICATION_EMAIL event +- class-loader component is removed, it was not used anymore. +- Updating stock when changing order : canceled status +- Added virtual products feature. + - Added new delivery module for virtual products. +- Added meta data feature to associate core elements and various data. +- Added `allow_negative_stock` configuration variable to allow negative stock or not (default is no) +- Added the ModuleConfig table, to provide modules an easy way to store their configuration parameters, with I18n if required. +- Added the `module-config` loop +- Added getConfigValue() and setConfigValue() static helper methods to BaseModule to offer an easy way to get/set a module parameters +- Refactored the Cheque module, to use the new ModuleConfig, and send an email to the customer when its payment is received. +- Added the wysywig.js hook to official hooks, so that any page which needs a WYSYWIG editor will only have to put this hook in the JS section to get one. +- Refactored Tynimce module according to wysywig.js hook +- Moved cart and order flush in the Order action, triggered by the ORDER_CART_CLEAR event. Payment modules which redirects to a non-strandard route (e.g., not /order/placed/{order_id}) should fire this event. +- Refactored assets generation. +- `file` parameter of asset related smarty functions (`stylesheets`, `javascripts`, ìmages`, ...) should not contains ../ +- Added remember me feature for customer sign in process + +##DEPRECATED + +Redirect methods are deprecated. You have now two ways for generating a redirect response : +- Throwing a Thelia\Core\HttpKernel\Exception\RedirectException with a given URL +- If you are in a controller, return an instance of \Symfony\Component\HttpFoundation\RedirectResponse +- Never ever send a response. Only the HttpKernel class is allowed to do that. + +### Deprecated methods : + +- Thelia\Controller\BaseController::redirect +- Thelia\Controller\BaseController::redirectSuccess +- Thelia\Controller\BaseController::redirectToRoute + +# 2.0.12 + +- Sanitize the get arguments for admin stats (related to #1782) +- Add EQUAL to product loop filter by min or max (related to #1750) +- Fix output value IS_DEFAULT in the product_sale_elements loop (related to #1745) + +# 2.0.11 + +- Fix critical performance issue on ProductController HydrateObjectForm (related to #1734) + +# 2.0.10 + +- Add 'step' to input type number to be able to create and edit weight slices price +- Fix pagination infinite URL ; redirect on page 1 when changing products per page limit to avoid having no product on the page +- Allow relative path use with Tlog +- Prevent obscur "[] this value cannot be null" messages. +- Prevent short research and keep research in input +- Fix Protocol-relative URL for HTTPS +- Fix fatal error that occurs when store does not use the default order_configuration email + +# 2.0.9 + +- Klik&Pay is no more a submodule + +# 2.0.8 + +- Allow relative path from thelia root for the file logger (by default log/log-thelia.txt) +- Force rediction on admin login even when connected to the front + +# 2.0.7 + +- Change TokenProvider behavior to be more flexible +- More secure csrf token +- Fix ```templates/backOffice/default/includes/inner-form-toolbar.html``` change currency destination +- Fix install bug if the admin password doesn't match + +# 2.0.6 + +- Do not register previous url on XmlHttpRequest + +# 2.0.5 + +- add new function to smarty ```set_previous_url```. The parameter ```ignore_current``` allows you to ignore the current url and it will not be store as a previous url +- 'freesans' is now the default font of PDF documents +- fix bug with cart foreign key constraint #926 +- fix typo with '}' #999 +- add missing 'admin.search' resource +- add default translation for '/ajax/mini-cart' +- fix product add to cart +- fix form firewall variable name +- add more module includes in order-edit.html +- do not allow failure anymore on travis php5.6 + +#2.0.4 + +- Updating stock when changing order : canceled status +- order table is versionnable now. +- product_sale_elements_id is added to order_product table. + +#2.0.3 + +- Fix js syntax in order-delivery template +- price are now save without any round. + /!\ Check in your templates if you are using format_money or format_number function. Don't display prices directly. +- change Argument type for ref parameter in Product loop +- Fix export template +- [Tinymce]fix invisible thumb in file manager + +#2.0.3-beta2 + +- fix update process +- fix coupons trait +- update schema adding new constraints on foreign keys +- previous url is now saved in session. use ```{navigate to="previous"}``` in your template + +#2.0.3-beta + +- New coupon type: Free product if selected products are in the cart. +- New feature: Product Brands / Suppliers management +- New 'brand' loop and substitution. product, image and document loop have been updated. +- Images and document processing have been refactored. +- Added store description field for SEO +- Added code editor on textarea on email templates page +- Fixed issues on position tests +- Fixed issues on RSS feed links +- Update SwiftMailer +- Fix bugs on customer change password form and module "order by title" +- Add the ability to place a firewall on forms. To use this in a module, extend Thelia\Form\FirewallForm instead of BaseForm +- Add Exports and Imports management +- Default front office template: + - Display enhancement + - Optimization of the uses of Thelia loops to gain performances and consistency + - Optimization for SEO : meta description fallback, title on category page, ... + - new PSE layout in product page, attributes are separated + - Support of 'check-available-stock' config variable + - Terms and conditions agreement is now in the order process +- Default pdf template: + - Added list of amount by tax rule + - Display enhancement + - Added legal information about the store +- Demo: + - Support for brand + - Added folders and contents data. + +#2.0.2 + +- Coupon UI has been redesigned. +- New coupon types: + - Constant discount on selected products + - Constant discount on products of selected categories + - Percentage discount on selected products + - Percentage discount on products of selected categories +- New coupon conditions : + - Start date + - Billing country + - Shipping country + - Cart contains product + - Cart contains product from category + - For specific customers +- Free shipping can now be restricted to some countries and/or shipping methods +- session initialization use now event dispatcher : + - name event : thelia_kernel.session (see Thelia\Core\TheliakernelEvents::SESSION + - class event : Thelia\Core\Event\SessionEvent + - example : Thelia\Core\EventListener\SessionListener +- Creation of Thelia\Core\TheliakernelEvents class for referencing kernel event +- Add new command line that refresh modules list `Thelia module:refresh` +- Coupon internals have been simplified and improved. +- Error messages are displayed in install process +- Add pagination on catalog page in Back-Office +- Add Hong Kong to country list +- Fixed issue #452 when installing Thelia on database with special characters +- implement search on content, folder and category loop. +- all form are documented +- template exists for managing google sitemap : sitemap.html + +#2.0.1 + +- possibility to apply a permanent discount on a customer +- display estimated shipping on cart page +- export newsletter subscribers list +- Fix redirect issues +- enhancement of coupon UI +- enhancement of admin menu. Coupon is now in Tools menu +- front office, email and pdf templates are translated in Russian and Czech +- fix bugs : https://github.com/thelia/thelia/issues?milestone=4&page=1&state=closed + +#2.0.0 + +- Coupons values are re-evaluated when a product quantity is changed in the shopping cart +- You can declare new compilerPass in modules. See Thelia\Module\BaseModule::getCompilers phpDoc +- Add ability to load assets from another template. See https://gist.github.com/lunika/9365180 +- allow possibility to use Dependency Injection compiler in Thelia modules +- Add Deactivate Module Command Line +- Add indexes to database to improve performance +- Order and customer references are more human readable than before +- Refactor intl process. A domain is created for each templates and modules : + - core => for thelia core translations + - bo.template_name (eg : bo.default) => for each backoffice template + - fo.template_name (eg : fo.default) => for each frontoffice template + - pdf.template_name (eg : pdf.default) => for each pdf template + - email.template_name (eg : email.default) => for each email template + - modules : + - module_code (eg : paypal) => fore module core translations + - module_code.ai (eg : paypal.ai) => used in AdminIncludes templates + - bo.module_code.template_name (eg : bo.paypal.default) => used in back office template + - fo.module_code.template_name (eg : fo.paypal.default) => used in front office template +- new parameter for smarty ```intl``` function. The parameter ```d``` allow you to specify the translation domain (as explain before). This parameter is optional +- the ```d``` can be omitted if you use ```{default_translation_domain domain='bo.default'}``` in your layout. If you use this smarty function, the ```d``` parameter is automatically set with the domain specify in ```default_translation_domain``` function +- We changed Thelia's license. Thelia is published under the LGPL 3.0+ License + + +#2.0.0-RC1 + +- Remove container from BaseAction. +- fix sending mail on order creation +- less files in default templates are already compiled in css. +- all validator message are translated +- type argument is now a default argument and used for generating loop cache +- fix total amount without discount in backoffice. Fix #235 +- description is not required anymore in coupon form. Fix #233 +- Do not allow to cumulate the same coupon many times. Fix #217 +- colissimo module is now fully configurable +- test suite are executed on PHP 5.4, 5.5, 5.6 and HHVM. Thelia is not fully compatible with HHVM +- add new attributes to loop pager (http://doc.thelia.net/en/documentation/loop/index.html#page-loop) +- we created a new github repo dedicated for modules : https://github.com/thelia-modules + +#2.0.0-beta4 + +- Tinymce is now a dedicated module. You need to activate it. +- Fix PDF creation. Bug #180 +- Fix many translation issues. +- The TaxManager is now a service +- Loop output is now put in cache for better performance +- loop count is refactored. It used now count propel method instead of classic loop method +- UTF-8 is used during install process, no more encoding problem in database now +- an admin can now choose a prefered locale and switch language in admin panel +- module repository is available on github : https://github.com/thelia-modules +- import module from Thelia 1 is available. It works from Thelia 1.4.2 : https://github.com/thelia-modules/importT1 + +#2.0.0-beta3 + +- Coupon effect inputs are now more customisable (input text, select, ajax, etc.. are usable) and unlimited amount of input for coupon effect are now possible too +- when a category is deleted, all subcategories are deleted +- delete products when categories are removed. Works only when the category is the default one for this product +- Manager update exists now. Run ```php Thelia thelia:update``` +- Coupon works now +- Improved tax rule configuration + +#2.0.0-beta2 + +- http://doc.thelia.net is available in beta. +- Increase performance in prod mode. +- Front part (routes and controller) are now a dedicated module. +- allow to create a customer in admin panel +- translation is implemented : + - I18n directory in template or module. + - multiple extensions are available. We choose to use php but you can use other. + - You can translate your template or module from the admin. +- Admin hooks exist. With this hooks, a module can insert code in admin pages +- Admin hooks can be display using SHOW_INCLUDE=1 in your query string and in dev mode (http://doc.thelia.net/en/documentation/modules/hook.html) +- change memory_limit parameter in installation process. 128M is now needed +- assets can be used from template directory and from module +- Product, Category, Folder and Content have a dedicated SEO panel +- Allow to configure store information like email, address, phone number, etc. +- email management : http://doc.thelia.net/en/documentation/templates/emails.html +- "How to contribute ?" see http://doc.thelia.net/en/documentation/contribute.html +-Cache http (use it carefully, default template is not compatible with this cache) : + - if you don't know http specification, learn it first http://www.w3.org/Protocols/rfc2616/rfc2616.html + - esi tag integrated, use {render_esi path="http://your-taget.tld/resource"} + - if no reverse proxy detected, html is render instead of esi tag + - if you can't install a reverse proxy like varnish, use the HttpCache (just uncomment line 14 in web/index.php file) + - resources : + - http://www.mnot.net/cache_docs/ (fr) + - http://tomayko.com/writings/things-caches-do (en) + - http://symfony.com/doc/current/book/http_cache.html#http-cache-introduction (en and fr) diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md new file mode 100644 index 00000000..fac1790f --- /dev/null +++ b/CONTRIBUTORS.md @@ -0,0 +1,51 @@ +CONTRIBUTORS +============ + +If you contributes or contributed to this project and do not appear in this list below, +please email us (info@thelia.net) or fork this file on GitHub and send a pull-request. + + - Manuel Raynaud (lunika) + - Franck Allimant (roadster31) + - Etienne Roudeix (etienneroudeix) + - Benjamin Perche (lovenunu) + - Julien Chanseaume (bibich) + - Christophe Laffont (touffies) + - Michaël Espeche (mespeche) + - Gilles Bourgeat (gillesbourgeat) + - Guillaume Morel (gmorel) + - Yochima (Yochima) + - Goleo Bruno (badsuricate) + - (zzuutt) + - Jérôme Billiras (bilhackmac) + - Emmanuel Nurit (enurit) + - (Asturyan) + - Etienne Perriere (Mertiozys) + - (griotteau) + - Alban Baixas (Alban-io) + - Christophe (InformatiqueProg) + - (jodeq) + - (nicolasleon) + - Chevrier (AnthonyMeedle) + - Romain Ducher (air-dex) + - Antony Penalver (Soldras) + - David Rimbault (Id4v) + - Stéphanie Pinet (stephaniepinet) + - Damien Foulhoux (Lucanis) + - Vincent Lopes-Vicente (lopes-vincent) + - (alex63530) + - Arnault Pachot (apachot) + - Cédric Sibaud (csibaud) + - Stéphane Calisti (csteph85) + - Alex Rock Ancelet (Pierstoval) + - Baptiste Cabarrou (bcabarrou) + - Adrien Bourroux (driou) + - (AdeDidou) + - DirtyF (DirtyF) + - (xockduo) + - Michaël Marinetti (Asenar) + - Mickaël (Kira-kyuukyoku) + - Quentin Dufour (superboum) + - Lespes (knjeurope) + - Tarun Garg (tarun1793) + - poum (poum) + - Luis Cordova (cordoval) diff --git a/COPYRIGHT.txt b/COPYRIGHT.txt new file mode 100644 index 00000000..68ed34bf --- /dev/null +++ b/COPYRIGHT.txt @@ -0,0 +1,4 @@ +THELIA +Copyright (C) 2005-2015 OpenStudio + +THELIA application uses externals components and libraries which are released under their own LGPL compatible license terms. diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 00000000..65c5ca88 --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,165 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + + This version of the GNU Lesser General Public License incorporates +the terms and conditions of version 3 of the GNU General Public +License, supplemented by the additional permissions listed below. + + 0. Additional Definitions. + + As used herein, "this License" refers to version 3 of the GNU Lesser +General Public License, and the "GNU GPL" refers to version 3 of the GNU +General Public License. + + "The Library" refers to a covered work governed by this License, +other than an Application or a Combined Work as defined below. + + An "Application" is any work that makes use of an interface provided +by the Library, but which is not otherwise based on the Library. +Defining a subclass of a class defined by the Library is deemed a mode +of using an interface provided by the Library. + + A "Combined Work" is a work produced by combining or linking an +Application with the Library. The particular version of the Library +with which the Combined Work was made is also called the "Linked +Version". + + The "Minimal Corresponding Source" for a Combined Work means the +Corresponding Source for the Combined Work, excluding any source code +for portions of the Combined Work that, considered in isolation, are +based on the Application, and not on the Linked Version. + + The "Corresponding Application Code" for a Combined Work means the +object code and/or source code for the Application, including any data +and utility programs needed for reproducing the Combined Work from the +Application, but excluding the System Libraries of the Combined Work. + + 1. Exception to Section 3 of the GNU GPL. + + You may convey a covered work under sections 3 and 4 of this License +without being bound by section 3 of the GNU GPL. + + 2. Conveying Modified Versions. + + If you modify a copy of the Library, and, in your modifications, a +facility refers to a function or data to be supplied by an Application +that uses the facility (other than as an argument passed when the +facility is invoked), then you may convey a copy of the modified +version: + + a) under this License, provided that you make a good faith effort to + ensure that, in the event an Application does not supply the + function or data, the facility still operates, and performs + whatever part of its purpose remains meaningful, or + + b) under the GNU GPL, with none of the additional permissions of + this License applicable to that copy. + + 3. Object Code Incorporating Material from Library Header Files. + + The object code form of an Application may incorporate material from +a header file that is part of the Library. You may convey such object +code under terms of your choice, provided that, if the incorporated +material is not limited to numerical parameters, data structure +layouts and accessors, or small macros, inline functions and templates +(ten or fewer lines in length), you do both of the following: + + a) Give prominent notice with each copy of the object code that the + Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the object code with a copy of the GNU GPL and this license + document. + + 4. Combined Works. + + You may convey a Combined Work under terms of your choice that, +taken together, effectively do not restrict modification of the +portions of the Library contained in the Combined Work and reverse +engineering for debugging such modifications, if you also do each of +the following: + + a) Give prominent notice with each copy of the Combined Work that + the Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the Combined Work with a copy of the GNU GPL and this license + document. + + c) For a Combined Work that displays copyright notices during + execution, include the copyright notice for the Library among + these notices, as well as a reference directing the user to the + copies of the GNU GPL and this license document. + + d) Do one of the following: + + 0) Convey the Minimal Corresponding Source under the terms of this + License, and the Corresponding Application Code in a form + suitable for, and under terms that permit, the user to + recombine or relink the Application with a modified version of + the Linked Version to produce a modified Combined Work, in the + manner specified by section 6 of the GNU GPL for conveying + Corresponding Source. + + 1) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (a) uses at run time + a copy of the Library already present on the user's computer + system, and (b) will operate properly with a modified version + of the Library that is interface-compatible with the Linked + Version. + + e) Provide Installation Information, but only if you would otherwise + be required to provide such information under section 6 of the + GNU GPL, and only to the extent that such information is + necessary to install and execute a modified version of the + Combined Work produced by recombining or relinking the + Application with a modified version of the Linked Version. (If + you use option 4d0, the Installation Information must accompany + the Minimal Corresponding Source and Corresponding Application + Code. If you use option 4d1, you must provide the Installation + Information in the manner specified by section 6 of the GNU GPL + for conveying Corresponding Source.) + + 5. Combined Libraries. + + You may place library facilities that are a work based on the +Library side by side in a single library together with other library +facilities that are not Applications and are not covered by this +License, and convey such a combined library under terms of your +choice, if you do both of the following: + + a) Accompany the combined library with a copy of the same work based + on the Library, uncombined with any other library facilities, + conveyed under the terms of this License. + + b) Give prominent notice with the combined library that part of it + is a work based on the Library, and explaining where to find the + accompanying uncombined form of the same work. + + 6. Revised Versions of the GNU Lesser General Public License. + + The Free Software Foundation may publish revised and/or new versions +of the GNU Lesser General Public License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. + + Each version is given a distinguishing version number. If the +Library as you received it specifies that a certain numbered version +of the GNU Lesser General Public License "or any later version" +applies to it, you have the option of following the terms and +conditions either of that published version or of any later version +published by the Free Software Foundation. If the Library as you +received it does not specify a version number of the GNU Lesser +General Public License, you may choose any version of the GNU Lesser +General Public License ever published by the Free Software Foundation. + + If the Library as you received it specifies that a proxy can decide +whether future versions of the GNU Lesser General Public License shall +apply, that proxy's public statement of acceptance of any version is +permanent authorization for you to choose that version for the +Library. diff --git a/Readme.md b/Readme.md new file mode 100644 index 00000000..a77c974f --- /dev/null +++ b/Readme.md @@ -0,0 +1,227 @@ +Readme +====== + +## Warning +### This is the development repository of Thelia. If you want to create a project, please take a look at [thelia/thelia-project](https://github.com/thelia/thelia-project) + +If you want to download a packaged, ready-to-use distribution of the most recent version of Thelia please download [thelia.zip](https://thelia.net/download/thelia.zip) + +Thelia +------ +[![Actions Status: test](https://github.com/thelia/thelia/workflows/test/badge.svg)](https://github.com/thelia/thelia/actions?query=workflow%3A"test") +[![Scrutinizer Quality Score](https://scrutinizer-ci.com/g/thelia/thelia/badges/quality-score.png?s=61e3e04a69bffd71c29b08e5392080317a546716)](https://scrutinizer-ci.com/g/thelia/thelia/) +[![License](https://poser.pugx.org/thelia/thelia/license.png)](https://packagist.org/packages/thelia/thelia) + +[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. + +A repository containing all thelia modules is available at this address : https://github.com/thelia-modules + +Compatibility +------------ + +| | Thelia 2.1 | Thelia 2.2 | Thelia 2.3 | Thelia 2.4 | +| ------------- |:-------------:| -----:| -----:| -----:| +| PHP | 5.4 5.5 5.6 | 5.4 5.5 5.6 | 5.5 5.6 7.0 7.1 | 5.6 7.0 7.1 7.2 7.3 | +| MySQL | 5.5 5.6 | 5.5 5.6 | 5.5 5.6 | 5.5 5.6 5.7 | +| Symfony | 2.3 | 2.3 | 2.8 | 2.8 | + +Requirements +------------ + +* PHP + * Required extensions : + * PDO_Mysql + * openssl + * intl + * gd + * curl + * dom + * safe_mode off + * memory_limit at least 128M, preferably 256. + * post\_max\_size 20M + * upload\_max\_filesize 2M + * date.timezone must be defined +* Web Server Apache 2 or Nginx +* MySQL 5 + + +### MySQL 5.6 + +As of MySQL 5.6, default configuration sets the sql_mode value to + +``` +STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION +``` + +This 'STRICT_TRANS_TABLES' configuration results in SQL errors when no default value is defined on NOT NULL columns and the value is empty or invalid. + +You can edit this default config in ` /etc/my.cnf ` and change the sql_mode to remove the STRICT_TRANS_TABLES part + +``` +[mysqld] +sql_mode=NO_ENGINE_SUBSTITUTION +``` + +Assuming your sql_mode is the default one, you can change the value directly on the run by running the following SQL Command + +```sql +SET @@GLOBAL.sql_mode='NO_ENGINE_SUBSTITUTION', @@SESSION.sql_mode='NO_ENGINE_SUBSTITUTION' +``` + +For more information on sql_mode you can consult the [MySQL doc](https://dev.mysql.com/doc/refman/5.0/fr/server-sql-mode.html "sql Mode") + +## Archive builders +Thelia's archive builder's needs external libraries. +For zip archives, you need PECL zip. See [PHP Doc](https://php.net/manual/en/zip.installation.php) + +For tar archives, you need PECL phar. Moreover, you need to deactivate php.ini option "phar.readonly": +```ini +phar.readonly = Off +``` + +For tar.bz2 archives, you need tar's dependencies and the extension "bzip2". See [PHP Doc](https://php.net/manual/fr/book.bzip2.php) + +For tar.gz archives, you need tar's dependencies and the extension "zlib". See [PHP Doc](https://fr2.php.net/manual/fr/book.zlib.php) + +## Download Thelia 2 and install its dependencies + +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 + +``` bash +$ git clone --recursive https://github.com/thelia/thelia path +$ cd path +$ git checkout 2.4.3 (2.3.5 or 2.2.6) +$ curl -sS https://getcomposer.org/installer | php +$ php composer.phar install +``` + +### Using composer for both download and dependencies + +``` bash +$ curl -sS https://getcomposer.org/installer | php +$ php composer.phar create-project thelia/thelia path/ 2.4.3 (2.3.5 or 2.2.6) +``` + +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 + +You can install Thelia by two different way + +### Using install wizard + +Installing thelia with the web install wizard allow to create an administrator, add some informations about your shop, etc + +First of all, you have to configure a vhost as describe in [configuration](https://doc.thelia.net/en/documentation/configuration.html) section. + +The install wizard in accessible with your favorite browser : + +``` bash +https://yourdomain.tld/[/subdomain_if_needed]/install +``` + +For example, I have thelia downloaded at https://thelia.net and my vhost is correctly configured, I have to reach this address : + +``` bash +https://thelia.net/install +``` + +### Using cli tools + +``` bash +$ 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. + +### Docker and docker compose + +This repo contains all the configuration needed to run Thelia with docker and docker-compose. +Warning, this docker configuration is not ready for production. + +It requires obviously [docker](https://docker.com/) and [docker-compose](https://docs.docker.com/compose/) + +To install Thelia within Docker, run : + +``` +docker-compose up -d +docker-compose exec php-fpm composer install +docker-compose exec php-fpm php Thelia thelia:install +``` + +By default if you haven't changed the `docker-compose.yml` you'll have to answer these questions like this + +``` +Database host [default: localhost] : mariadb +``` +``` +Database port [default: 3306] : 3306 +``` +``` +Database name (if database does not exist, Thelia will try to create it) : thelia +``` + +``` +Database username : thelia +``` + +``` +Database pasword : thelia +``` + +Next just go to http://localhost:8080 and you should see your Thelia installed ! + +tip : create an alias for docker-compose, it's boring to write it all the time + +If you want add some sample data just execute this command (still in your container) +``` bash +docker-compose exec php-fpm php setup/import.php +``` + +If you want to access your database from your computer (with DBeaver, Sequel Pro or anything else) by default the host is `localhost` and the port is `8086` + +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 +``` + +Documentation +------------- + +Thelia documentation is available at https://doc.thelia.net + + +Contribute +---------- + +See the documentation : http://doc.thelia.net/en/documentation/contribute.html + + +If you submit modifications that adds new data or change the structure of the database, take a look to https://doc.thelia.net/en/documentation/contribute.html#sql-scripts-modification + +Usage +----- + +Consult the page : https://localhost/thelia/web/index_dev.php + +You can create a virtual host and choose the web folder for root directory. + +To run tests (phpunit required) : + +``` bash +$ phpunit +``` + +We still have a lot of work to achieve but enjoy this part. diff --git a/Thelia b/Thelia new file mode 100644 index 00000000..33cbe879 --- /dev/null +++ b/Thelia @@ -0,0 +1,5 @@ +#!/usr/bin/env php + +- Extract the zip in a temporary directory +- Then you should replace (not only copy) all the files from the new Thelia version : + - all files from root directory + - bin (*optional*) + - core (**mandatory**) + - setup (**mandatory**) +- Then, you have to merge (copy in your existent directories) these other directories. Normally, + you haven't modify files inside these directories (just created new ones - like your frontOffice template). + But If you have modified files, you should proceed carefully and try to report all your changes. + - local/config + - local/modules + - templates + - web + + +## 2. Update database + +Then you have 2 different ways to proceed. In each method, a backup of your database can be automatically +performed if you want to. If an error is encountered, then your database will be restored. +But if your database is quite large, it's better to make a backup manually. + +### 2.1. use the update script + +In a command shell, go to the root directory of your installation, run and follow instructions : + +```bash +php setup/update.php +``` + +### 2.2. use the update wizard + +An update wizard is available in the ```web/install``` directory. It's the same directory used by the install wizard. + +**You have to protect the web folder if your site is public (htaccess, List of allowed IP, ...).** + +The update wizard in accessible with your favorite browser : + +```bash +http://yourdomain.tld/[/subdomain_if_needed]/install +``` + +Note: + +- the wizard is available only if your Thelia is not already in the latest version. +- at the end of the process, the install directory will be removed. + + +## 3. Clear cache + +Once the update is done successfully, you have to clear all caches : + +- clear all caches in all environment : + - ```php Thelia cache:clear``` + - ```php Thelia cache:clear --env=prod``` + +If the command fails, you can do it manually. Just delete the content of +the ```cache``` and ```web/cache``` directories. \ No newline at end of file diff --git a/UPGRADE-2.3.md b/UPGRADE-2.3.md new file mode 100644 index 00000000..e5620ec5 --- /dev/null +++ b/UPGRADE-2.3.md @@ -0,0 +1,131 @@ + +UPGRADE FROM 2.2 to 2.3 +======================= + + +EventDispatcher +---------------- + + * The `getDispatcher()` and `getName()` methods from `Symfony\Component\EventDispatcher\Event` + are deprecated, the event dispatcher instance and event name can be received in the listener call instead. + + Before: + + ```php + use Symfony\Component\EventDispatcher\Event; + + class Foo + { + public function myFooListener(Event $event) + { + $dispatcher = $event->getDispatcher(); + $eventName = $event->getName(); + $dispatcher->dispatch('log', $event); + + // ... more code + } + } + ``` + + After: + + ```php + use Symfony\Component\EventDispatcher\Event; + use Symfony\Component\EventDispatcher\EventDispatcherInterface; + + class MyListenerClass + { + public function myListenerMethod(Event $event, $eventName, EventDispatcherInterface $dispatcher) + { + $dispatcher->dispatch('log', $event); + + // ... more code + } + } + ``` + + While this above is sufficient for most uses, **if your module must be compatible with versions less than 2.3, or if your module uses multiple EventDispatcher instances,** you might need to specifically inject a known instance of the `EventDispatcher` into your listeners. This could be done using constructor or setter injection as follows: + + ```php + use Symfony\Component\EventDispatcher\EventDispatcherInterface; + + class MyListenerClass + { + protected $dispatcher = null; + + public function __construct(EventDispatcherInterface $dispatcher) + { + $this->dispatcher = $dispatcher; + } + } + ``` + +Request and RequestStack +---------------- + + * The `Request` service are deprecated, you must now use the `RequestStack` service. + + ##### In your loops + The way to recover the request does not change. + + To get the current request + + ```php + class MyLoopClass extends BaseLoop implements PropelSearchLoopInterface + { + public function buildModelCriteria() + { + // Get the current request + $request = $this->getCurrentRequest(); + // Or + $request = $this->requestStack->getCurrentRequest(); + + // ... more code + } + } + ``` + + ##### In your controllers + It's not recommended to use `getRequest()` and `getSession()`, the Request instance can be received in the action method parameters. + However, the `getRequest()` method returns the current request. + **Warning !!** This is not compatible with Thelia 2.0, because it uses Symfony 2.2 + + To get the current request + + ```php + use Thelia\Core\HttpFoundation\Request; + + class MyControllerClass extends ... + { + public function MyActionMethod(Request $request, $query_parameters ...) + { + $session = $request->getSession(); + // ... more code + } + } + ``` + +Container Scopes +---------------- + + * The "container scopes" concept no longer exists in Thelia 2.3. + For backward compatibility, the attributes `scope` is automatically removed of the xml configuration files. + **Warning !!** The attributes `scope` are always needed for your modules compatible with Thelia < 2.3. + [See the Symfony documentation for more information](http://symfony.com/doc/2.8/cookbook/service_container/scopes.html) + + +Unit Test +---------------- + + * The `SecurityContext`, `ParserContext`, `TokenProvider`, `TheliaFormFactory`, `TaxEngine` services are no longer dependent on "Request", but "RequestSTack". + This may break your unit tests. + +For more information about the upgrade from Symfony 2.3 to Symfony 2.8 +---------------- + +[Upgrade from Symfony 2.3 to 2.4](https://github.com/symfony/symfony/blob/2.8/UPGRADE-2.4.md) +[Upgrade from Symfony 2.4 to 2.5](https://github.com/symfony/symfony/blob/2.8/UPGRADE-2.5.md) +[Upgrade from Symfony 2.5 to 2.6](https://github.com/symfony/symfony/blob/2.8/UPGRADE-2.6.md) +[Upgrade from Symfony 2.6 to 2.7](https://github.com/symfony/symfony/blob/2.8/UPGRADE-2.7.md) +[Upgrade from Symfony 2.7 to 2.8](https://github.com/symfony/symfony/blob/2.8/UPGRADE-2.8.md) +[Upgrade from Symfony 2.8 to 3.0](https://github.com/symfony/symfony/blob/2.8/UPGRADE-3.0.md) diff --git a/composer.json b/composer.json new file mode 100644 index 00000000..265673c4 --- /dev/null +++ b/composer.json @@ -0,0 +1,101 @@ +{ + "name": "thelia/thelia", + "description": "Thelia is an ecommerce CMS.", + "license": "LGPL-3.0+", + "homepage": "http://thelia.net/", + "keywords": [ + "ecommerce", + "cms", + "cms ecommerce", + "ecommerce cms" + ], + "support": { + "forum": "http://thelia.net/forum", + "wiki": "http://doc.thelia.net" + }, + "require": { + "php": ">=5.6 <7.4", + "ircmaxell/password-compat": "1.0.*", + "psr/log": "1.0", + "symfony/config": "2.8.*", + "symfony/console": "2.8.*", + "symfony/dependency-injection": "2.8.*", + "symfony/event-dispatcher": "2.8.*", + "symfony/http-kernel": "2.8.*", + "symfony/routing": "2.8.*", + "symfony/filesystem": "2.8.*", + "symfony/yaml": "2.8.*", + "symfony/translation": "2.8.*", + "symfony-cmf/routing": "1.3.*", + "symfony/validator": "2.8.*", + "symfony/options-resolver": "2.8.*", + "symfony/security": "2.8.*", + "symfony/expression-language": "2.8.*", + "symfony/process": "2.8.*", + "symfony/dom-crawler": "2.8.*", + "symfony/property-access": "2.8.*", + "symfony/serializer": "2.8.*", + "symfony/finder": "2.8.*", + "symfony/browser-kit": "2.8.*", + "symfony/http-foundation": "2.8.*", + "symfony/form": "2.8.*", + "symfony/class-loader": "2.8.*", + "symfony/dotenv": "^3.4|^4.0", + "stack/builder": "1.0.*", + "thelia/currency-converter": "~1.0", + "doctrine/cache": "1.5.*", + "kriswallsmith/assetic": "1.3.*", + "ptachoire/cssembed": "1.0.*", + "simplepie/simplepie": "1.3.*", + "imagine/imagine": "0.7.1", + "swiftmailer/swiftmailer": "5.4.*", + "oyejorge/less.php": "1.7.*", + "michelf/php-markdown": "1.6.*", + "smarty/smarty": "3.1.33", + "commerceguys/addressing": "0.8.*", + "symfony/cache": "^3.4|^4.0", + "symfony/polyfill-php56": "^1.0", + "symfony/polyfill-php70": "^1.0", + "symfony/polyfill-php71": "^1.0", + "symfony/polyfill-php72": "^1.0", + "spipu/html2pdf": "^5.0", + "symfony/polyfill-php73": "^1.0", + "symfony/lock": "^3.4|^4.0", + "thelia/propel": "dev-thelia-2.4", + "symfony/var-dumper": "^2.0|^3.0|^4.0", + "thelia/colissimo-module": "^2.4", + "thelia/smarty-module": "^2.4" + }, + "require-dev": { + "fzaninotto/faker": "1.5.*", + "thelia/hooktest-module": "~1.1", + "thelia/hooktest-template": "~1.1", + "phpunit/phpunit": "^5.0" + }, + "minimum-stability": "stable", + "config": { + "vendor-dir": "core/vendor", + "bin-dir": "bin" + }, + "autoload": { + "psr-4": { + "Thelia\\": "core/lib/Thelia" + }, + "psr-0": { + "": "local/modules/" + }, + "files": [ + "core/bootstrap.php" + ] + }, + "autoload-dev": { + "psr-4": { + "Thelia\\Tests\\" : "tests/phpunit/Thelia/Tests" + } + }, + "extra": { + "branch-alias": { + "dev-master": "2.4-dev" + } + } +} diff --git a/composer.lock b/composer.lock new file mode 100644 index 00000000..f33ebb82 --- /dev/null +++ b/composer.lock @@ -0,0 +1,5426 @@ +{ + "_readme": [ + "This file locks the dependencies of your project to a known state", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", + "This file is @generated automatically" + ], + "content-hash": "e6f383fd8a02cb1279f5ca2e0c78d2c6", + "packages": [ + { + "name": "commerceguys/addressing", + "version": "v0.8.4", + "source": { + "type": "git", + "url": "https://github.com/commerceguys/addressing.git", + "reference": "5d8d13bfaed08119be763da2a0fc9f38fff8af54" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/commerceguys/addressing/zipball/5d8d13bfaed08119be763da2a0fc9f38fff8af54", + "reference": "5d8d13bfaed08119be763da2a0fc9f38fff8af54", + "shasum": "" + }, + "require": { + "commerceguys/enum": "~1.0", + "doctrine/collections": "~1.0", + "php": ">=5.4.0" + }, + "require-dev": { + "mikey179/vfsstream": "1.*", + "phpunit/phpunit": "~4.0", + "squizlabs/php_codesniffer": "2.*", + "symfony/intl": ">=2.3", + "symfony/validator": ">=2.3" + }, + "suggest": { + "commerceguys/intl": "to use it as the source of country data", + "symfony/form": "to generate Symfony address forms", + "symfony/intl": "to use it as the source of country data", + "symfony/validator": "to validate addresses" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "0.x-dev" + } + }, + "autoload": { + "psr-4": { + "CommerceGuys\\Addressing\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Bojan Zivanovic" + }, + { + "name": "Damien Tournoud" + } + ], + "description": "Addressing library powered by Google's address data.", + "keywords": [ + "address", + "internationalization", + "localization", + "postal" + ], + "time": "2016-09-05T18:45:53+00:00" + }, + { + "name": "commerceguys/enum", + "version": "v1.0", + "source": { + "type": "git", + "url": "https://github.com/commerceguys/enum.git", + "reference": "1d9db2dbeb1a02500e7a14589ae2f9cb402c5c95" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/commerceguys/enum/zipball/1d9db2dbeb1a02500e7a14589ae2f9cb402c5c95", + "reference": "1d9db2dbeb1a02500e7a14589ae2f9cb402c5c95", + "shasum": "" + }, + "require": { + "php": ">=5.4.0" + }, + "require-dev": { + "phpunit/phpunit": "~4.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "CommerceGuys\\Enum\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Bojan Zivanovic" + } + ], + "description": "A PHP 5.4+ enumeration library.", + "time": "2015-02-27T21:36:56+00:00" + }, + { + "name": "doctrine/cache", + "version": "v1.5.4", + "source": { + "type": "git", + "url": "https://github.com/doctrine/cache.git", + "reference": "47cdc76ceb95cc591d9c79a36dc3794975b5d136" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/cache/zipball/47cdc76ceb95cc591d9c79a36dc3794975b5d136", + "reference": "47cdc76ceb95cc591d9c79a36dc3794975b5d136", + "shasum": "" + }, + "require": { + "php": ">=5.3.2" + }, + "conflict": { + "doctrine/common": ">2.2,<2.4" + }, + "require-dev": { + "phpunit/phpunit": ">=3.7", + "predis/predis": "~1.0", + "satooshi/php-coveralls": "~0.6" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.5.x-dev" + } + }, + "autoload": { + "psr-4": { + "Doctrine\\Common\\Cache\\": "lib/Doctrine/Common/Cache" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + } + ], + "description": "Caching library offering an object-oriented API for many cache backends", + "homepage": "http://www.doctrine-project.org", + "keywords": [ + "cache", + "caching" + ], + "time": "2015-12-19T05:03:47+00:00" + }, + { + "name": "doctrine/collections", + "version": "1.6.7", + "source": { + "type": "git", + "url": "https://github.com/doctrine/collections.git", + "reference": "55f8b799269a1a472457bd1a41b4f379d4cfba4a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/collections/zipball/55f8b799269a1a472457bd1a41b4f379d4cfba4a", + "reference": "55f8b799269a1a472457bd1a41b4f379d4cfba4a", + "shasum": "" + }, + "require": { + "php": "^7.1.3 || ^8.0" + }, + "require-dev": { + "doctrine/coding-standard": "^6.0", + "phpstan/phpstan-shim": "^0.9.2", + "phpunit/phpunit": "^7.0", + "vimeo/psalm": "^3.8.1" + }, + "type": "library", + "autoload": { + "psr-4": { + "Doctrine\\Common\\Collections\\": "lib/Doctrine/Common/Collections" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + } + ], + "description": "PHP Doctrine Collections library that adds additional functionality on top of PHP arrays.", + "homepage": "https://www.doctrine-project.org/projects/collections.html", + "keywords": [ + "array", + "collections", + "iterators", + "php" + ], + "time": "2020-07-27T17:53:49+00:00" + }, + { + "name": "imagine/imagine", + "version": "v0.7.1", + "source": { + "type": "git", + "url": "https://github.com/avalanche123/Imagine.git", + "reference": "a9a702a946073cbca166718f1b02a1e72d742daa" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/avalanche123/Imagine/zipball/a9a702a946073cbca166718f1b02a1e72d742daa", + "reference": "a9a702a946073cbca166718f1b02a1e72d742daa", + "shasum": "" + }, + "require": { + "php": ">=5.3.2" + }, + "require-dev": { + "sami/sami": "^3.3", + "symfony/phpunit-bridge": "^3.2" + }, + "suggest": { + "ext-gd": "to use the GD implementation", + "ext-gmagick": "to use the Gmagick implementation", + "ext-imagick": "to use the Imagick implementation" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-develop": "0.7-dev" + } + }, + "autoload": { + "psr-0": { + "Imagine": "lib/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Bulat Shakirzyanov", + "email": "mallluhuct@gmail.com", + "homepage": "http://avalanche123.com" + } + ], + "description": "Image processing for PHP 5.3", + "homepage": "http://imagine.readthedocs.org/", + "keywords": [ + "drawing", + "graphics", + "image manipulation", + "image processing" + ], + "time": "2017-05-16T10:31:22+00:00" + }, + { + "name": "ircmaxell/password-compat", + "version": "v1.0.4", + "source": { + "type": "git", + "url": "https://github.com/ircmaxell/password_compat.git", + "reference": "5c5cde8822a69545767f7c7f3058cb15ff84614c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ircmaxell/password_compat/zipball/5c5cde8822a69545767f7c7f3058cb15ff84614c", + "reference": "5c5cde8822a69545767f7c7f3058cb15ff84614c", + "shasum": "" + }, + "require-dev": { + "phpunit/phpunit": "4.*" + }, + "type": "library", + "autoload": { + "files": [ + "lib/password.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Anthony Ferrara", + "email": "ircmaxell@php.net", + "homepage": "http://blog.ircmaxell.com" + } + ], + "description": "A compatibility library for the proposed simplified password hashing algorithm: https://wiki.php.net/rfc/password_hash", + "homepage": "https://github.com/ircmaxell/password_compat", + "keywords": [ + "hashing", + "password" + ], + "time": "2014-11-20T16:49:30+00:00" + }, + { + "name": "kriswallsmith/assetic", + "version": "v1.3.2", + "source": { + "type": "git", + "url": "https://github.com/kriswallsmith/assetic.git", + "reference": "9928f7c4ad98b234e3559d1049abd13387f86db5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/kriswallsmith/assetic/zipball/9928f7c4ad98b234e3559d1049abd13387f86db5", + "reference": "9928f7c4ad98b234e3559d1049abd13387f86db5", + "shasum": "" + }, + "require": { + "php": ">=5.3.1", + "symfony/process": "~2.1|~3.0" + }, + "conflict": { + "twig/twig": "<1.23" + }, + "require-dev": { + "cssmin/cssmin": "3.0.1", + "joliclic/javascript-packer": "1.1", + "kamicane/packager": "1.0", + "leafo/lessphp": "^0.3.7", + "leafo/scssphp": "~0.1", + "mrclay/minify": "~2.2", + "patchwork/jsqueeze": "~1.0|~2.0", + "phpunit/phpunit": "~4.8", + "psr/log": "~1.0", + "ptachoire/cssembed": "~1.0", + "symfony/phpunit-bridge": "~2.7|~3.0", + "twig/twig": "~1.8|~2.0" + }, + "suggest": { + "leafo/lessphp": "Assetic provides the integration with the lessphp LESS compiler", + "leafo/scssphp": "Assetic provides the integration with the scssphp SCSS compiler", + "leafo/scssphp-compass": "Assetic provides the integration with the SCSS compass plugin", + "patchwork/jsqueeze": "Assetic provides the integration with the JSqueeze JavaScript compressor", + "ptachoire/cssembed": "Assetic provides the integration with phpcssembed to embed data uris", + "twig/twig": "Assetic provides the integration with the Twig templating engine" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.4-dev" + } + }, + "autoload": { + "psr-0": { + "Assetic": "src/" + }, + "files": [ + "src/functions.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Kris Wallsmith", + "email": "kris.wallsmith@gmail.com", + "homepage": "http://kriswallsmith.net/" + } + ], + "description": "Asset Management for PHP", + "homepage": "https://github.com/kriswallsmith/assetic", + "keywords": [ + "assets", + "compression", + "minification" + ], + "time": "2015-11-12T13:51:40+00:00" + }, + { + "name": "michelf/php-markdown", + "version": "1.6.0", + "source": { + "type": "git", + "url": "https://github.com/michelf/php-markdown.git", + "reference": "156e56ee036505ec637d761ee62dc425d807183c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/michelf/php-markdown/zipball/156e56ee036505ec637d761ee62dc425d807183c", + "reference": "156e56ee036505ec637d761ee62dc425d807183c", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-lib": "1.4.x-dev" + } + }, + "autoload": { + "psr-0": { + "Michelf": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Michel Fortin", + "email": "michel.fortin@michelf.ca", + "homepage": "https://michelf.ca/", + "role": "Developer" + }, + { + "name": "John Gruber", + "homepage": "https://daringfireball.net/" + } + ], + "description": "PHP Markdown", + "homepage": "https://michelf.ca/projects/php-markdown/", + "keywords": [ + "markdown" + ], + "time": "2015-12-24T01:37:31+00:00" + }, + { + "name": "oyejorge/less.php", + "version": "v1.7.0.14", + "source": { + "type": "git", + "url": "https://github.com/oyejorge/less.php.git", + "reference": "42925c5a01a07d67ca7e82dfc8fb31814d557bc9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/oyejorge/less.php/zipball/42925c5a01a07d67ca7e82dfc8fb31814d557bc9", + "reference": "42925c5a01a07d67ca7e82dfc8fb31814d557bc9", + "shasum": "" + }, + "require": { + "php": ">=5.3" + }, + "require-dev": { + "phpunit/phpunit": "~4.8.24" + }, + "bin": [ + "bin/lessc" + ], + "type": "library", + "autoload": { + "psr-0": { + "Less": "lib/" + }, + "classmap": [ + "lessc.inc.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache-2.0" + ], + "authors": [ + { + "name": "Matt Agar", + "homepage": "https://github.com/agar" + }, + { + "name": "Martin Jantošovič", + "homepage": "https://github.com/Mordred" + }, + { + "name": "Josh Schmidt", + "homepage": "https://github.com/oyejorge" + } + ], + "description": "PHP port of the Javascript version of LESS http://lesscss.org (Originally maintained by Josh Schmidt)", + "homepage": "http://lessphp.gpeasy.com", + "keywords": [ + "css", + "less", + "less.js", + "lesscss", + "php", + "stylesheet" + ], + "abandoned": true, + "time": "2017-03-28T22:19:25+00:00" + }, + { + "name": "psr/cache", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/php-fig/cache.git", + "reference": "d11b50ad223250cf17b86e38383413f5a6764bf8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/cache/zipball/d11b50ad223250cf17b86e38383413f5a6764bf8", + "reference": "d11b50ad223250cf17b86e38383413f5a6764bf8", + "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": "2016-08-06T20:24:11+00:00" + }, + { + "name": "psr/log", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/log.git", + "reference": "fe0936ee26643249e916849d48e3a51d5f5e278b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/log/zipball/fe0936ee26643249e916849d48e3a51d5f5e278b", + "reference": "fe0936ee26643249e916849d48e3a51d5f5e278b", + "shasum": "" + }, + "type": "library", + "autoload": { + "psr-0": { + "Psr\\Log\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interface for logging libraries", + "keywords": [ + "log", + "psr", + "psr-3" + ], + "time": "2012-12-21T11:40:51+00:00" + }, + { + "name": "psr/simple-cache", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/php-fig/simple-cache.git", + "reference": "408d5eafb83c57f6365a3ca330ff23aa4a5fa39b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/simple-cache/zipball/408d5eafb83c57f6365a3ca330ff23aa4a5fa39b", + "reference": "408d5eafb83c57f6365a3ca330ff23aa4a5fa39b", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\SimpleCache\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interfaces for simple caching", + "keywords": [ + "cache", + "caching", + "psr", + "psr-16", + "simple-cache" + ], + "time": "2017-10-23T01:57:42+00:00" + }, + { + "name": "ptachoire/cssembed", + "version": "v1.0.2", + "source": { + "type": "git", + "url": "https://github.com/krichprollsch/phpCssEmbed.git", + "reference": "406c6d5b846cafa9186f9944a6210d0e6fed154b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/krichprollsch/phpCssEmbed/zipball/406c6d5b846cafa9186f9944a6210d0e6fed154b", + "reference": "406c6d5b846cafa9186f9944a6210d0e6fed154b", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "type": "library", + "autoload": { + "psr-0": { + "CssEmbed": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Pierre Tachoire", + "email": "pierre.tachoire@gmail.com" + } + ], + "description": "Css url embed library.", + "homepage": "https://github.com/krichprollsch/phpCssEmbed", + "keywords": [ + "css", + "url" + ], + "time": "2013-07-22T20:01:48+00:00" + }, + { + "name": "simplepie/simplepie", + "version": "1.3.1", + "source": { + "type": "git", + "url": "https://github.com/simplepie/simplepie.git", + "reference": "ce53709778bc1e2e4deda1651b66e5081398d5cc" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/simplepie/simplepie/zipball/ce53709778bc1e2e4deda1651b66e5081398d5cc", + "reference": "ce53709778bc1e2e4deda1651b66e5081398d5cc", + "shasum": "" + }, + "require": { + "php": ">=5.2.0" + }, + "type": "library", + "autoload": { + "psr-0": { + "SimplePie": "library" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Ryan Parman", + "homepage": "http://ryanparman.com/", + "role": "Creator, alumnus developer" + }, + { + "name": "Geoffrey Sneddon", + "homepage": "http://gsnedders.com/", + "role": "Alumnus developer" + }, + { + "name": "Ryan McCue", + "email": "me@ryanmccue.info", + "homepage": "http://ryanmccue.info/", + "role": "Developer" + } + ], + "description": "A simple Atom/RSS parsing library for PHP", + "homepage": "http://simplepie.org/", + "keywords": [ + "atom", + "feeds", + "rss" + ], + "time": "2012-10-30T17:54:03+00:00" + }, + { + "name": "smarty/smarty", + "version": "v3.1.33", + "source": { + "type": "git", + "url": "https://github.com/smarty-php/smarty.git", + "reference": "dd55b23121e55a3b4f1af90a707a6c4e5969530f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/smarty-php/smarty/zipball/dd55b23121e55a3b4f1af90a707a6c4e5969530f", + "reference": "dd55b23121e55a3b4f1af90a707a6c4e5969530f", + "shasum": "" + }, + "require": { + "php": ">=5.2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.1.x-dev" + } + }, + "autoload": { + "files": [ + "libs/bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "LGPL-3.0" + ], + "authors": [ + { + "name": "Monte Ohrt", + "email": "monte@ohrt.com" + }, + { + "name": "Uwe Tews", + "email": "uwe.tews@googlemail.com" + }, + { + "name": "Rodney Rehm", + "email": "rodney.rehm@medialize.de" + } + ], + "description": "Smarty - the compiling PHP template engine", + "homepage": "http://www.smarty.net", + "keywords": [ + "templating" + ], + "time": "2018-09-12T20:54:16+00:00" + }, + { + "name": "spipu/html2pdf", + "version": "v5.2.2", + "source": { + "type": "git", + "url": "https://github.com/spipu/html2pdf.git", + "reference": "e6d8ca22347b6691bb8c2652212b1be2c89b3eff" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/spipu/html2pdf/zipball/e6d8ca22347b6691bb8c2652212b1be2c89b3eff", + "reference": "e6d8ca22347b6691bb8c2652212b1be2c89b3eff", + "shasum": "" + }, + "require": { + "ext-gd": "*", + "ext-mbstring": "*", + "php": "^5.6 || ^7.0", + "tecnickcom/tcpdf": "^6.2" + }, + "require-dev": { + "phake/phake": "^2.0", + "phpunit/phpunit": "^5.0" + }, + "suggest": { + "ext-gd": "Allows to embed images into the PDF", + "fagundes/zff-html2pdf": "if you need to integrate Html2Pdf with Zend Framework 2 (zf2)" + }, + "type": "library", + "autoload": { + "psr-4": { + "Spipu\\Html2Pdf\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "OSL-3.0" + ], + "authors": [ + { + "name": "Spipu", + "homepage": "https://github.com/spipu", + "role": "Developer" + } + ], + "description": "Html2Pdf is a HTML to PDF converter written in PHP5 (it uses TCPDF). OFFICIAL PACKAGE", + "homepage": "http://html2pdf.fr/", + "keywords": [ + "html", + "html2pdf", + "pdf" + ], + "time": "2020-03-22T16:23:26+00:00" + }, + { + "name": "stack/builder", + "version": "v1.0.6", + "source": { + "type": "git", + "url": "https://github.com/stackphp/builder.git", + "reference": "a4faaa6f532c6086bc66c29e1bc6c29593e1ca7c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/stackphp/builder/zipball/a4faaa6f532c6086bc66c29e1bc6c29593e1ca7c", + "reference": "a4faaa6f532c6086bc66c29e1bc6c29593e1ca7c", + "shasum": "" + }, + "require": { + "php": ">=7.2.0", + "symfony/http-foundation": "~2.1|~3.0|~4.0|~5.0", + "symfony/http-kernel": "~2.1|~3.0|~4.0|~5.0" + }, + "require-dev": { + "phpunit/phpunit": "~8.0", + "symfony/routing": "^5.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "psr-0": { + "Stack": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Igor Wiedler", + "email": "igor@wiedler.ch" + } + ], + "description": "Builder for stack middleware based on HttpKernelInterface.", + "keywords": [ + "stack" + ], + "time": "2020-01-30T12:17:27+00:00" + }, + { + "name": "swiftmailer/swiftmailer", + "version": "v5.4.12", + "source": { + "type": "git", + "url": "https://github.com/swiftmailer/swiftmailer.git", + "reference": "181b89f18a90f8925ef805f950d47a7190e9b950" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/swiftmailer/swiftmailer/zipball/181b89f18a90f8925ef805f950d47a7190e9b950", + "reference": "181b89f18a90f8925ef805f950d47a7190e9b950", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "mockery/mockery": "~0.9.1", + "symfony/phpunit-bridge": "~3.2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.4-dev" + } + }, + "autoload": { + "files": [ + "lib/swift_required.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Chris Corbyn" + }, + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + } + ], + "description": "Swiftmailer, free feature-rich PHP mailer", + "homepage": "https://swiftmailer.symfony.com", + "keywords": [ + "email", + "mail", + "mailer" + ], + "time": "2018-07-31T09:26:32+00:00" + }, + { + "name": "symfony-cmf/routing", + "version": "1.3.0", + "source": { + "type": "git", + "url": "https://github.com/symfony-cmf/Routing.git", + "reference": "8e87981d72c6930a27585dcd3119f3199f6cb2a6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony-cmf/Routing/zipball/8e87981d72c6930a27585dcd3119f3199f6cb2a6", + "reference": "8e87981d72c6930a27585dcd3119f3199f6cb2a6", + "shasum": "" + }, + "require": { + "php": ">=5.3.3", + "psr/log": "~1.0", + "symfony/http-kernel": "~2.2", + "symfony/routing": "~2.2" + }, + "require-dev": { + "symfony/config": "~2.2", + "symfony/dependency-injection": "~2.0@stable", + "symfony/event-dispatcher": "~2.1" + }, + "suggest": { + "symfony/event-dispatcher": "DynamicRouter can optionally trigger an event at the start of matching. Minimal version ~2.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.3-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Cmf\\Component\\Routing\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Symfony CMF Community", + "homepage": "https://github.com/symfony-cmf/Routing/contributors" + } + ], + "description": "Extends the Symfony2 routing component for dynamic routes and chaining several routers", + "homepage": "http://cmf.symfony.com", + "keywords": [ + "database", + "routing" + ], + "time": "2014-10-20T20:55:17+00:00" + }, + { + "name": "symfony/browser-kit", + "version": "v2.8.52", + "source": { + "type": "git", + "url": "https://github.com/symfony/browser-kit.git", + "reference": "b507697225f32a76a9d333d0766fb46353e9d00d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/browser-kit/zipball/b507697225f32a76a9d333d0766fb46353e9d00d", + "reference": "b507697225f32a76a9d333d0766fb46353e9d00d", + "shasum": "" + }, + "require": { + "php": ">=5.3.9", + "symfony/dom-crawler": "~2.1|~3.0.0" + }, + "require-dev": { + "symfony/css-selector": "^2.0.5|~3.0.0", + "symfony/process": "~2.3.34|^2.7.6|~3.0.0" + }, + "suggest": { + "symfony/process": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.8-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\BrowserKit\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony BrowserKit Component", + "homepage": "https://symfony.com", + "time": "2018-11-26T06:55:10+00:00" + }, + { + "name": "symfony/cache", + "version": "v4.1.12", + "source": { + "type": "git", + "url": "https://github.com/symfony/cache.git", + "reference": "399ddbf0ff98f42593827141b5fcd95d51c36b28" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/cache/zipball/399ddbf0ff98f42593827141b5fcd95d51c36b28", + "reference": "399ddbf0ff98f42593827141b5fcd95d51c36b28", + "shasum": "" + }, + "require": { + "php": "^7.1.3", + "psr/cache": "~1.0", + "psr/log": "~1.0", + "psr/simple-cache": "^1.0" + }, + "conflict": { + "symfony/var-dumper": "<3.4" + }, + "provide": { + "psr/cache-implementation": "1.0", + "psr/simple-cache-implementation": "1.0" + }, + "require-dev": { + "cache/integration-tests": "dev-master", + "doctrine/cache": "~1.6", + "doctrine/dbal": "~2.4", + "predis/predis": "~1.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.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 Cache component with PSR-6, PSR-16, and tags", + "homepage": "https://symfony.com", + "keywords": [ + "caching", + "psr6" + ], + "time": "2019-04-16T09:37:00+00:00" + }, + { + "name": "symfony/class-loader", + "version": "v2.8.52", + "source": { + "type": "git", + "url": "https://github.com/symfony/class-loader.git", + "reference": "8194721a1e2768cfb95079581889c41eec7a5959" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/class-loader/zipball/8194721a1e2768cfb95079581889c41eec7a5959", + "reference": "8194721a1e2768cfb95079581889c41eec7a5959", + "shasum": "" + }, + "require": { + "php": ">=5.3.9", + "symfony/polyfill-apcu": "~1.1" + }, + "require-dev": { + "symfony/finder": "^2.0.5|~3.0.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.8-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\ClassLoader\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony ClassLoader Component", + "homepage": "https://symfony.com", + "time": "2018-11-11T11:18:13+00:00" + }, + { + "name": "symfony/config", + "version": "v2.8.52", + "source": { + "type": "git", + "url": "https://github.com/symfony/config.git", + "reference": "7dd5f5040dc04c118d057fb5886563963eb70011" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/config/zipball/7dd5f5040dc04c118d057fb5886563963eb70011", + "reference": "7dd5f5040dc04c118d057fb5886563963eb70011", + "shasum": "" + }, + "require": { + "php": ">=5.3.9", + "symfony/filesystem": "~2.3|~3.0.0", + "symfony/polyfill-ctype": "~1.8" + }, + "require-dev": { + "symfony/yaml": "~2.7|~3.0.0" + }, + "suggest": { + "symfony/yaml": "To use the yaml reference dumper" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.8-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Config\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Config Component", + "homepage": "https://symfony.com", + "time": "2018-11-26T09:38:12+00:00" + }, + { + "name": "symfony/console", + "version": "v2.8.52", + "source": { + "type": "git", + "url": "https://github.com/symfony/console.git", + "reference": "cbcf4b5e233af15cd2bbd50dee1ccc9b7927dc12" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/console/zipball/cbcf4b5e233af15cd2bbd50dee1ccc9b7927dc12", + "reference": "cbcf4b5e233af15cd2bbd50dee1ccc9b7927dc12", + "shasum": "" + }, + "require": { + "php": ">=5.3.9", + "symfony/debug": "^2.7.2|~3.0.0", + "symfony/polyfill-mbstring": "~1.0" + }, + "require-dev": { + "psr/log": "~1.0", + "symfony/event-dispatcher": "~2.1|~3.0.0", + "symfony/process": "~2.1|~3.0.0" + }, + "suggest": { + "psr/log-implementation": "For using the console logger", + "symfony/event-dispatcher": "", + "symfony/process": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.8-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Console\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Console Component", + "homepage": "https://symfony.com", + "time": "2018-11-20T15:55:20+00:00" + }, + { + "name": "symfony/debug", + "version": "v2.8.52", + "source": { + "type": "git", + "url": "https://github.com/symfony/debug.git", + "reference": "74251c8d50dd3be7c4ce0c7b862497cdc641a5d0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/debug/zipball/74251c8d50dd3be7c4ce0c7b862497cdc641a5d0", + "reference": "74251c8d50dd3be7c4ce0c7b862497cdc641a5d0", + "shasum": "" + }, + "require": { + "php": ">=5.3.9", + "psr/log": "~1.0" + }, + "conflict": { + "symfony/http-kernel": ">=2.3,<2.3.24|~2.4.0|>=2.5,<2.5.9|>=2.6,<2.6.2" + }, + "require-dev": { + "symfony/class-loader": "~2.2|~3.0.0", + "symfony/http-kernel": "~2.3.24|~2.5.9|^2.6.2|~3.0.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.8-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Debug\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Debug Component", + "homepage": "https://symfony.com", + "time": "2018-11-11T11:18:13+00:00" + }, + { + "name": "symfony/dependency-injection", + "version": "v2.8.52", + "source": { + "type": "git", + "url": "https://github.com/symfony/dependency-injection.git", + "reference": "c306198fee8f872a8f5f031e6e4f6f83086992d8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/c306198fee8f872a8f5f031e6e4f6f83086992d8", + "reference": "c306198fee8f872a8f5f031e6e4f6f83086992d8", + "shasum": "" + }, + "require": { + "php": ">=5.3.9" + }, + "conflict": { + "symfony/expression-language": "<2.6" + }, + "require-dev": { + "symfony/config": "~2.2|~3.0.0", + "symfony/expression-language": "~2.6|~3.0.0", + "symfony/yaml": "~2.3.42|~2.7.14|~2.8.7|~3.0.7" + }, + "suggest": { + "symfony/config": "", + "symfony/expression-language": "For using expressions in service container configuration", + "symfony/proxy-manager-bridge": "Generate service proxies to lazy load them", + "symfony/yaml": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.8-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\DependencyInjection\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony DependencyInjection Component", + "homepage": "https://symfony.com", + "time": "2019-04-16T11:33:46+00:00" + }, + { + "name": "symfony/dom-crawler", + "version": "v2.8.52", + "source": { + "type": "git", + "url": "https://github.com/symfony/dom-crawler.git", + "reference": "2cdc7d3909eea6f982a6298d2e9ab7db01b6403c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/dom-crawler/zipball/2cdc7d3909eea6f982a6298d2e9ab7db01b6403c", + "reference": "2cdc7d3909eea6f982a6298d2e9ab7db01b6403c", + "shasum": "" + }, + "require": { + "php": ">=5.3.9", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-mbstring": "~1.0" + }, + "require-dev": { + "symfony/css-selector": "~2.8|~3.0.0" + }, + "suggest": { + "symfony/css-selector": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.8-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\DomCrawler\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony DomCrawler Component", + "homepage": "https://symfony.com", + "time": "2018-11-24T22:30:19+00:00" + }, + { + "name": "symfony/dotenv", + "version": "v4.4.18", + "source": { + "type": "git", + "url": "https://github.com/symfony/dotenv.git", + "reference": "2befc49ec50b4d6ffd100b332389260c9069ba1c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/dotenv/zipball/2befc49ec50b4d6ffd100b332389260c9069ba1c", + "reference": "2befc49ec50b4d6ffd100b332389260c9069ba1c", + "shasum": "" + }, + "require": { + "php": ">=7.1.3" + }, + "require-dev": { + "symfony/process": "^3.4.2|^4.0|^5.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Dotenv\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Registers environment variables from a .env file", + "homepage": "https://symfony.com", + "keywords": [ + "dotenv", + "env", + "environment" + ], + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2020-12-08T16:59:59+00:00" + }, + { + "name": "symfony/event-dispatcher", + "version": "v2.8.52", + "source": { + "type": "git", + "url": "https://github.com/symfony/event-dispatcher.git", + "reference": "a77e974a5fecb4398833b0709210e3d5e334ffb0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/a77e974a5fecb4398833b0709210e3d5e334ffb0", + "reference": "a77e974a5fecb4398833b0709210e3d5e334ffb0", + "shasum": "" + }, + "require": { + "php": ">=5.3.9" + }, + "require-dev": { + "psr/log": "~1.0", + "symfony/config": "^2.0.5|~3.0.0", + "symfony/dependency-injection": "~2.6|~3.0.0", + "symfony/expression-language": "~2.6|~3.0.0", + "symfony/stopwatch": "~2.3|~3.0.0" + }, + "suggest": { + "symfony/dependency-injection": "", + "symfony/http-kernel": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.8-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\EventDispatcher\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony EventDispatcher Component", + "homepage": "https://symfony.com", + "time": "2018-11-21T14:20:20+00:00" + }, + { + "name": "symfony/expression-language", + "version": "v2.8.52", + "source": { + "type": "git", + "url": "https://github.com/symfony/expression-language.git", + "reference": "fa9be1b831859b56d244137fabbfd01a46dbdb36" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/expression-language/zipball/fa9be1b831859b56d244137fabbfd01a46dbdb36", + "reference": "fa9be1b831859b56d244137fabbfd01a46dbdb36", + "shasum": "" + }, + "require": { + "php": ">=5.3.9" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.8-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\ExpressionLanguage\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony ExpressionLanguage Component", + "homepage": "https://symfony.com", + "time": "2018-11-11T11:18:13+00:00" + }, + { + "name": "symfony/filesystem", + "version": "v2.8.52", + "source": { + "type": "git", + "url": "https://github.com/symfony/filesystem.git", + "reference": "7ae46872dad09dffb7fe1e93a0937097339d0080" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/7ae46872dad09dffb7fe1e93a0937097339d0080", + "reference": "7ae46872dad09dffb7fe1e93a0937097339d0080", + "shasum": "" + }, + "require": { + "php": ">=5.3.9", + "symfony/polyfill-ctype": "~1.8" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.8-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Filesystem\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Filesystem Component", + "homepage": "https://symfony.com", + "time": "2018-11-11T11:18:13+00:00" + }, + { + "name": "symfony/finder", + "version": "v2.8.52", + "source": { + "type": "git", + "url": "https://github.com/symfony/finder.git", + "reference": "1444eac52273e345d9b95129bf914639305a9ba4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/finder/zipball/1444eac52273e345d9b95129bf914639305a9ba4", + "reference": "1444eac52273e345d9b95129bf914639305a9ba4", + "shasum": "" + }, + "require": { + "php": ">=5.3.9" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.8-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Finder\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Finder Component", + "homepage": "https://symfony.com", + "time": "2018-11-11T11:18:13+00:00" + }, + { + "name": "symfony/form", + "version": "v2.8.52", + "source": { + "type": "git", + "url": "https://github.com/symfony/form.git", + "reference": "74382a47aa97496d181fbb598822fdfb9e1744e4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/form/zipball/74382a47aa97496d181fbb598822fdfb9e1744e4", + "reference": "74382a47aa97496d181fbb598822fdfb9e1744e4", + "shasum": "" + }, + "require": { + "php": ">=5.3.9", + "symfony/event-dispatcher": "~2.1|~3.0.0", + "symfony/intl": "~2.7.25|^2.8.18|~3.2.5", + "symfony/options-resolver": "~2.6", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-mbstring": "~1.0", + "symfony/property-access": "~2.3|~3.0.0" + }, + "conflict": { + "phpunit/phpunit": "<4.8.35|<5.4.3,>=5.0", + "symfony/doctrine-bridge": "<2.7", + "symfony/framework-bundle": "<2.7", + "symfony/twig-bridge": "<2.7" + }, + "require-dev": { + "doctrine/collections": "~1.0", + "symfony/dependency-injection": "~2.7|~3.0.0", + "symfony/http-foundation": "~2.2|~3.0.0", + "symfony/http-kernel": "~2.4|~3.0.0", + "symfony/security-csrf": "^2.8.31|^3.3.13", + "symfony/translation": "^2.0.5|~3.0.0", + "symfony/validator": "^2.8.18|~3.2.5" + }, + "suggest": { + "symfony/framework-bundle": "For templating with PHP.", + "symfony/security-csrf": "For protecting forms against CSRF attacks.", + "symfony/twig-bridge": "For templating with Twig.", + "symfony/validator": "For form validation." + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.8-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Form\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Form Component", + "homepage": "https://symfony.com", + "time": "2018-12-06T11:12:46+00:00" + }, + { + "name": "symfony/http-foundation", + "version": "v2.8.52", + "source": { + "type": "git", + "url": "https://github.com/symfony/http-foundation.git", + "reference": "3929d9fe8148d17819ad0178c748b8d339420709" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/3929d9fe8148d17819ad0178c748b8d339420709", + "reference": "3929d9fe8148d17819ad0178c748b8d339420709", + "shasum": "" + }, + "require": { + "php": ">=5.3.9", + "symfony/polyfill-mbstring": "~1.1", + "symfony/polyfill-php54": "~1.0", + "symfony/polyfill-php55": "~1.0" + }, + "require-dev": { + "symfony/expression-language": "~2.4|~3.0.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.8-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\HttpFoundation\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony HttpFoundation Component", + "homepage": "https://symfony.com", + "time": "2019-11-12T12:34:41+00:00" + }, + { + "name": "symfony/http-kernel", + "version": "v2.8.52", + "source": { + "type": "git", + "url": "https://github.com/symfony/http-kernel.git", + "reference": "c3be27b8627cd5ee8dfa8d1b923982f618ec521c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/http-kernel/zipball/c3be27b8627cd5ee8dfa8d1b923982f618ec521c", + "reference": "c3be27b8627cd5ee8dfa8d1b923982f618ec521c", + "shasum": "" + }, + "require": { + "php": ">=5.3.9", + "psr/log": "~1.0", + "symfony/debug": "^2.6.2", + "symfony/event-dispatcher": "^2.6.7|~3.0.0", + "symfony/http-foundation": "~2.7.36|~2.8.29|~3.1.6", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-php56": "~1.8" + }, + "conflict": { + "symfony/config": "<2.7", + "twig/twig": "<1.34|<2.4,>=2" + }, + "require-dev": { + "symfony/browser-kit": "~2.3|~3.0.0", + "symfony/class-loader": "~2.1|~3.0.0", + "symfony/config": "~2.8", + "symfony/console": "~2.3|~3.0.0", + "symfony/css-selector": "^2.0.5|~3.0.0", + "symfony/dependency-injection": "~2.8|~3.0.0", + "symfony/dom-crawler": "^2.0.5|~3.0.0", + "symfony/expression-language": "~2.4|~3.0.0", + "symfony/finder": "^2.0.5|~3.0.0", + "symfony/process": "^2.0.5|~3.0.0", + "symfony/routing": "~2.8|~3.0.0", + "symfony/stopwatch": "~2.3|~3.0.0", + "symfony/templating": "~2.2|~3.0.0", + "symfony/translation": "^2.0.5|~3.0.0", + "symfony/var-dumper": "~2.6|~3.0.0" + }, + "suggest": { + "symfony/browser-kit": "", + "symfony/class-loader": "", + "symfony/config": "", + "symfony/console": "", + "symfony/dependency-injection": "", + "symfony/finder": "", + "symfony/var-dumper": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.8-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\HttpKernel\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony HttpKernel Component", + "homepage": "https://symfony.com", + "time": "2019-11-13T08:36:16+00:00" + }, + { + "name": "symfony/intl", + "version": "v3.2.14", + "source": { + "type": "git", + "url": "https://github.com/symfony/intl.git", + "reference": "3fd98dde8e7d1c34c974d65b09e9c32abe88dafe" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/intl/zipball/3fd98dde8e7d1c34c974d65b09e9c32abe88dafe", + "reference": "3fd98dde8e7d1c34c974d65b09e9c32abe88dafe", + "shasum": "" + }, + "require": { + "php": ">=5.5.9", + "symfony/polyfill-intl-icu": "~1.0" + }, + "require-dev": { + "symfony/filesystem": "~2.8|~3.0" + }, + "suggest": { + "ext-intl": "to use the component with locales other than \"en\"" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.2-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Intl\\": "" + }, + "classmap": [ + "Resources/stubs" + ], + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" + }, + { + "name": "Eriksen Costa", + "email": "eriksen.costa@infranology.com.br" + }, + { + "name": "Igor Wiedler", + "email": "igor@wiedler.ch" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "A PHP replacement layer for the C intl extension that includes additional data from the ICU library.", + "homepage": "https://symfony.com", + "keywords": [ + "i18n", + "icu", + "internationalization", + "intl", + "l10n", + "localization" + ], + "time": "2017-11-16T17:55:54+00:00" + }, + { + "name": "symfony/lock", + "version": "v4.4.18", + "source": { + "type": "git", + "url": "https://github.com/symfony/lock.git", + "reference": "8017f2ecc7de4b6cc1585d502e65ea4f56d42051" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/lock/zipball/8017f2ecc7de4b6cc1585d502e65ea4f56d42051", + "reference": "8017f2ecc7de4b6cc1585d502e65ea4f56d42051", + "shasum": "" + }, + "require": { + "php": ">=7.1.3", + "psr/log": "~1.0" + }, + "conflict": { + "doctrine/dbal": "<2.5" + }, + "require-dev": { + "doctrine/dbal": "^2.5|^3.0", + "predis/predis": "~1.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Lock\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jérémy Derussé", + "email": "jeremy@derusse.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Lock Component", + "homepage": "https://symfony.com", + "keywords": [ + "cas", + "flock", + "locking", + "mutex", + "redlock", + "semaphore" + ], + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2020-12-14T10:21:37+00:00" + }, + { + "name": "symfony/options-resolver", + "version": "v2.8.52", + "source": { + "type": "git", + "url": "https://github.com/symfony/options-resolver.git", + "reference": "7aaab725bb58f0e18aa12c61bdadd4793ab4c32b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/options-resolver/zipball/7aaab725bb58f0e18aa12c61bdadd4793ab4c32b", + "reference": "7aaab725bb58f0e18aa12c61bdadd4793ab4c32b", + "shasum": "" + }, + "require": { + "php": ">=5.3.9" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.8-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\OptionsResolver\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony OptionsResolver Component", + "homepage": "https://symfony.com", + "keywords": [ + "config", + "configuration", + "options" + ], + "time": "2018-11-11T11:18:13+00:00" + }, + { + "name": "symfony/polyfill-apcu", + "version": "v1.22.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-apcu.git", + "reference": "3b3944f40987b9d3f9b9147f86c32df87d9f3505" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-apcu/zipball/3b3944f40987b9d3f9b9147f86c32df87d9f3505", + "reference": "3b3944f40987b9d3f9b9147f86c32df87d9f3505", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.22-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Apcu\\": "" + }, + "files": [ + "bootstrap.php" + ] + }, + "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 polyfill backporting apcu_* functions to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "apcu", + "compatibility", + "polyfill", + "portable", + "shim" + ], + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2021-01-07T16:49:33+00:00" + }, + { + "name": "symfony/polyfill-ctype", + "version": "v1.22.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-ctype.git", + "reference": "c6c942b1ac76c82448322025e084cadc56048b4e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/c6c942b1ac76c82448322025e084cadc56048b4e", + "reference": "c6c942b1ac76c82448322025e084cadc56048b4e", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "suggest": { + "ext-ctype": "For best performance" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.22-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Ctype\\": "" + }, + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Gert de Pagter", + "email": "BackEndTea@gmail.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for ctype functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "ctype", + "polyfill", + "portable" + ], + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2021-01-07T16:49:33+00:00" + }, + { + "name": "symfony/polyfill-intl-icu", + "version": "v1.22.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-intl-icu.git", + "reference": "b2b1e732a6c039f1a3ea3414b3379a2433e183d6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-intl-icu/zipball/b2b1e732a6c039f1a3ea3414b3379a2433e183d6", + "reference": "b2b1e732a6c039f1a3ea3414b3379a2433e183d6", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "suggest": { + "ext-intl": "For best performance and support of other locales than \"en\"" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.22-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Intl\\Icu\\": "" + }, + "classmap": [ + "Resources/stubs" + ], + "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 polyfill for intl's ICU-related data and classes", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "icu", + "intl", + "polyfill", + "portable", + "shim" + ], + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2021-01-07T16:49:33+00:00" + }, + { + "name": "symfony/polyfill-mbstring", + "version": "v1.22.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-mbstring.git", + "reference": "f377a3dd1fde44d37b9831d68dc8dea3ffd28e13" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/f377a3dd1fde44d37b9831d68dc8dea3ffd28e13", + "reference": "f377a3dd1fde44d37b9831d68dc8dea3ffd28e13", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "suggest": { + "ext-mbstring": "For best performance" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.22-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Mbstring\\": "" + }, + "files": [ + "bootstrap.php" + ] + }, + "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 polyfill for the Mbstring extension", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "mbstring", + "polyfill", + "portable", + "shim" + ], + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2021-01-07T16:49:33+00:00" + }, + { + "name": "symfony/polyfill-php54", + "version": "v1.20.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php54.git", + "reference": "37285b1d5d13f37c8bee546d8d2ad0353460c4c7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php54/zipball/37285b1d5d13f37c8bee546d8d2ad0353460c4c7", + "reference": "37285b1d5d13f37c8bee546d8d2ad0353460c4c7", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "type": "metapackage", + "extra": { + "branch-alias": { + "dev-main": "1.20-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "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 polyfill backporting some PHP 5.4+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2020-10-23T14:02:19+00:00" + }, + { + "name": "symfony/polyfill-php55", + "version": "v1.20.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php55.git", + "reference": "c17452124a883900e1d73961f9075a638399c1a0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php55/zipball/c17452124a883900e1d73961f9075a638399c1a0", + "reference": "c17452124a883900e1d73961f9075a638399c1a0", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "type": "metapackage", + "extra": { + "branch-alias": { + "dev-main": "1.20-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "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 polyfill backporting some PHP 5.5+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2020-10-23T14:02:19+00:00" + }, + { + "name": "symfony/polyfill-php56", + "version": "v1.20.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php56.git", + "reference": "54b8cd7e6c1643d78d011f3be89f3ef1f9f4c675" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php56/zipball/54b8cd7e6c1643d78d011f3be89f3ef1f9f4c675", + "reference": "54b8cd7e6c1643d78d011f3be89f3ef1f9f4c675", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "type": "metapackage", + "extra": { + "branch-alias": { + "dev-main": "1.20-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "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 polyfill backporting some PHP 5.6+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2020-10-23T14:02:19+00:00" + }, + { + "name": "symfony/polyfill-php70", + "version": "v1.20.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php70.git", + "reference": "5f03a781d984aae42cebd18e7912fa80f02ee644" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php70/zipball/5f03a781d984aae42cebd18e7912fa80f02ee644", + "reference": "5f03a781d984aae42cebd18e7912fa80f02ee644", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "type": "metapackage", + "extra": { + "branch-alias": { + "dev-main": "1.20-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "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 polyfill backporting some PHP 7.0+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2020-10-23T14:02:19+00:00" + }, + { + "name": "symfony/polyfill-php71", + "version": "v1.20.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php71.git", + "reference": "2d6cdeca7ea470e50db9e544c9ec4b1955036c22" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php71/zipball/2d6cdeca7ea470e50db9e544c9ec4b1955036c22", + "reference": "2d6cdeca7ea470e50db9e544c9ec4b1955036c22", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "type": "metapackage", + "extra": { + "branch-alias": { + "dev-main": "1.20-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "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 polyfill backporting some PHP 7.1+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2020-10-23T14:02:19+00:00" + }, + { + "name": "symfony/polyfill-php72", + "version": "v1.22.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php72.git", + "reference": "cc6e6f9b39fe8075b3dabfbaf5b5f645ae1340c9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/cc6e6f9b39fe8075b3dabfbaf5b5f645ae1340c9", + "reference": "cc6e6f9b39fe8075b3dabfbaf5b5f645ae1340c9", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.22-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Php72\\": "" + }, + "files": [ + "bootstrap.php" + ] + }, + "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 polyfill backporting some PHP 7.2+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2021-01-07T16:49:33+00:00" + }, + { + "name": "symfony/polyfill-php73", + "version": "v1.22.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php73.git", + "reference": "a678b42e92f86eca04b7fa4c0f6f19d097fb69e2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/a678b42e92f86eca04b7fa4c0f6f19d097fb69e2", + "reference": "a678b42e92f86eca04b7fa4c0f6f19d097fb69e2", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.22-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Php73\\": "" + }, + "files": [ + "bootstrap.php" + ], + "classmap": [ + "Resources/stubs" + ] + }, + "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 polyfill backporting some PHP 7.3+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2021-01-07T16:49:33+00:00" + }, + { + "name": "symfony/polyfill-util", + "version": "v1.22.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-util.git", + "reference": "ccda17fe137336f3c2c5321167c4a5e26371171a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-util/zipball/ccda17fe137336f3c2c5321167c4a5e26371171a", + "reference": "ccda17fe137336f3c2c5321167c4a5e26371171a", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.22-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Util\\": "" + } + }, + "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 utilities for portability of PHP codes", + "homepage": "https://symfony.com", + "keywords": [ + "compat", + "compatibility", + "polyfill", + "shim" + ], + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2021-01-07T16:49:33+00:00" + }, + { + "name": "symfony/process", + "version": "v2.8.52", + "source": { + "type": "git", + "url": "https://github.com/symfony/process.git", + "reference": "c3591a09c78639822b0b290d44edb69bf9f05dc8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/process/zipball/c3591a09c78639822b0b290d44edb69bf9f05dc8", + "reference": "c3591a09c78639822b0b290d44edb69bf9f05dc8", + "shasum": "" + }, + "require": { + "php": ">=5.3.9" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.8-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Process\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Process Component", + "homepage": "https://symfony.com", + "time": "2018-11-11T11:18:13+00:00" + }, + { + "name": "symfony/property-access", + "version": "v2.8.52", + "source": { + "type": "git", + "url": "https://github.com/symfony/property-access.git", + "reference": "c8f10191183be9bb0d5a1b8364d3891f1bde07b6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/property-access/zipball/c8f10191183be9bb0d5a1b8364d3891f1bde07b6", + "reference": "c8f10191183be9bb0d5a1b8364d3891f1bde07b6", + "shasum": "" + }, + "require": { + "php": ">=5.3.9", + "symfony/polyfill-ctype": "~1.8" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.8-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\PropertyAccess\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony PropertyAccess Component", + "homepage": "https://symfony.com", + "keywords": [ + "access", + "array", + "extraction", + "index", + "injection", + "object", + "property", + "property path", + "reflection" + ], + "time": "2018-11-11T11:18:13+00:00" + }, + { + "name": "symfony/routing", + "version": "v2.8.52", + "source": { + "type": "git", + "url": "https://github.com/symfony/routing.git", + "reference": "8b0df6869d1997baafff6a1541826eac5a03d067" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/routing/zipball/8b0df6869d1997baafff6a1541826eac5a03d067", + "reference": "8b0df6869d1997baafff6a1541826eac5a03d067", + "shasum": "" + }, + "require": { + "php": ">=5.3.9" + }, + "conflict": { + "symfony/config": "<2.7" + }, + "require-dev": { + "doctrine/annotations": "~1.0", + "psr/log": "~1.0", + "symfony/config": "~2.7|~3.0.0", + "symfony/expression-language": "~2.4|~3.0.0", + "symfony/http-foundation": "~2.3|~3.0.0", + "symfony/yaml": "^2.0.5|~3.0.0" + }, + "suggest": { + "doctrine/annotations": "For using the annotation loader", + "symfony/config": "For using the all-in-one router or any loader", + "symfony/dependency-injection": "For loading routes from a service", + "symfony/expression-language": "For using expression matching", + "symfony/http-foundation": "For using a Symfony Request object", + "symfony/yaml": "For using the YAML loader" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.8-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Routing\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Routing Component", + "homepage": "https://symfony.com", + "keywords": [ + "router", + "routing", + "uri", + "url" + ], + "time": "2018-11-20T15:55:20+00:00" + }, + { + "name": "symfony/security", + "version": "v2.8.52", + "source": { + "type": "git", + "url": "https://github.com/symfony/security.git", + "reference": "b9e9130cf348d4e85e37ba1d0d27263e33b97534" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/security/zipball/b9e9130cf348d4e85e37ba1d0d27263e33b97534", + "reference": "b9e9130cf348d4e85e37ba1d0d27263e33b97534", + "shasum": "" + }, + "require": { + "php": ">=5.3.9", + "symfony/event-dispatcher": "~2.2|~3.0.0", + "symfony/http-foundation": "^2.7.38|~3.3.13", + "symfony/http-kernel": "~2.4|~3.0.0", + "symfony/polyfill-php55": "~1.0", + "symfony/polyfill-php56": "~1.0", + "symfony/polyfill-php70": "~1.0", + "symfony/polyfill-util": "~1.0", + "symfony/property-access": "~2.3|~3.0.0", + "symfony/security-acl": "~2.7|~3.0.0" + }, + "conflict": { + "symfony/http-foundation": "~2.8,<2.8.31" + }, + "replace": { + "symfony/security-core": "self.version", + "symfony/security-csrf": "self.version", + "symfony/security-guard": "self.version", + "symfony/security-http": "self.version" + }, + "require-dev": { + "psr/log": "~1.0", + "symfony/expression-language": "~2.6|~3.0.0", + "symfony/finder": "~2.3|~3.0.0", + "symfony/ldap": "~2.8|~3.0.0", + "symfony/polyfill-intl-icu": "~1.0", + "symfony/routing": "~2.2|~3.0.0", + "symfony/validator": "~2.7.25|^2.8.18|~3.2.5" + }, + "suggest": { + "symfony/expression-language": "For using the expression voter", + "symfony/form": "", + "symfony/ldap": "For using the LDAP user and authentication providers", + "symfony/routing": "For using the HttpUtils class to create sub-requests, redirect the user, and match URLs", + "symfony/validator": "For using the user password constraint" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.8-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Security\\": "" + }, + "exclude-from-classmap": [ + "/Core/Tests/", + "/Csrf/Tests/", + "/Guard/Tests/", + "/Http/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Security Component", + "homepage": "https://symfony.com", + "time": "2019-04-16T10:01:12+00:00" + }, + { + "name": "symfony/security-acl", + "version": "v3.0.4", + "source": { + "type": "git", + "url": "https://github.com/symfony/security-acl.git", + "reference": "dc8f10b3bda34e9ddcad49edc7accf61f31fce43" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/security-acl/zipball/dc8f10b3bda34e9ddcad49edc7accf61f31fce43", + "reference": "dc8f10b3bda34e9ddcad49edc7accf61f31fce43", + "shasum": "" + }, + "require": { + "php": ">=5.5.9", + "symfony/security-core": "^2.8|^3.0|^4.0|^5.0" + }, + "require-dev": { + "doctrine/common": "~2.2", + "doctrine/dbal": "~2.2", + "psr/log": "~1.0", + "symfony/phpunit-bridge": "^2.8|^3.0|^4.0|^5.0" + }, + "suggest": { + "doctrine/dbal": "For using the built-in ACL implementation", + "symfony/class-loader": "For using the ACL generateSql script", + "symfony/finder": "For using the ACL generateSql script" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Security\\Acl\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Security Component - ACL (Access Control List)", + "homepage": "https://symfony.com", + "time": "2019-12-12T09:55:57+00:00" + }, + { + "name": "symfony/serializer", + "version": "v2.8.52", + "source": { + "type": "git", + "url": "https://github.com/symfony/serializer.git", + "reference": "2939e67396f7356aace05c90e5913736fcb46a20" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/serializer/zipball/2939e67396f7356aace05c90e5913736fcb46a20", + "reference": "2939e67396f7356aace05c90e5913736fcb46a20", + "shasum": "" + }, + "require": { + "php": ">=5.3.9", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-php55": "~1.0" + }, + "require-dev": { + "doctrine/annotations": "~1.0", + "doctrine/cache": "~1.0", + "symfony/config": "~2.2|~3.0.0", + "symfony/property-access": "~2.3|~3.0.0", + "symfony/yaml": "^2.0.5|~3.0.0" + }, + "suggest": { + "doctrine/annotations": "For using the annotation mapping. You will also need doctrine/cache.", + "doctrine/cache": "For using the default cached annotation reader and metadata cache.", + "symfony/config": "For using the XML mapping loader.", + "symfony/property-access": "For using the ObjectNormalizer.", + "symfony/yaml": "For using the default YAML mapping loader." + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.8-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Serializer\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Serializer Component", + "homepage": "https://symfony.com", + "time": "2018-11-11T11:18:13+00:00" + }, + { + "name": "symfony/translation", + "version": "v2.8.52", + "source": { + "type": "git", + "url": "https://github.com/symfony/translation.git", + "reference": "fc58c2a19e56c29f5ba2736ec40d0119a0de2089" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/translation/zipball/fc58c2a19e56c29f5ba2736ec40d0119a0de2089", + "reference": "fc58c2a19e56c29f5ba2736ec40d0119a0de2089", + "shasum": "" + }, + "require": { + "php": ">=5.3.9", + "symfony/polyfill-mbstring": "~1.0" + }, + "conflict": { + "symfony/config": "<2.7" + }, + "require-dev": { + "psr/log": "~1.0", + "symfony/config": "~2.8", + "symfony/intl": "~2.7.25|^2.8.18|~3.2.5", + "symfony/yaml": "~2.2|~3.0.0" + }, + "suggest": { + "psr/log-implementation": "To use logging capability in translator", + "symfony/config": "", + "symfony/yaml": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.8-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Translation\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Translation Component", + "homepage": "https://symfony.com", + "time": "2018-11-24T21:16:41+00:00" + }, + { + "name": "symfony/validator", + "version": "v2.8.52", + "source": { + "type": "git", + "url": "https://github.com/symfony/validator.git", + "reference": "d5d2090bba3139d8ddb79959fbf516e87238fe3a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/validator/zipball/d5d2090bba3139d8ddb79959fbf516e87238fe3a", + "reference": "d5d2090bba3139d8ddb79959fbf516e87238fe3a", + "shasum": "" + }, + "require": { + "php": ">=5.3.9", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-mbstring": "~1.0", + "symfony/translation": "~2.4|~3.0.0" + }, + "require-dev": { + "doctrine/annotations": "~1.0", + "doctrine/cache": "~1.0", + "egulias/email-validator": "^1.2.1", + "symfony/config": "~2.2|~3.0.0", + "symfony/expression-language": "~2.4|~3.0.0", + "symfony/http-foundation": "~2.3|~3.0.0", + "symfony/intl": "~2.7.25|^2.8.18|~3.2.5", + "symfony/property-access": "~2.3|~3.0.0", + "symfony/yaml": "^2.0.5|~3.0.0" + }, + "suggest": { + "doctrine/annotations": "For using the annotation mapping. You will also need doctrine/cache.", + "doctrine/cache": "For using the default cached annotation reader and metadata cache.", + "egulias/email-validator": "Strict (RFC compliant) email validation", + "symfony/config": "", + "symfony/expression-language": "For using the 2.4 Expression validator", + "symfony/http-foundation": "", + "symfony/intl": "", + "symfony/property-access": "For using the 2.4 Validator API", + "symfony/yaml": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.8-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Validator\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Validator Component", + "homepage": "https://symfony.com", + "time": "2018-11-14T14:06:48+00:00" + }, + { + "name": "symfony/var-dumper", + "version": "v4.0.15", + "source": { + "type": "git", + "url": "https://github.com/symfony/var-dumper.git", + "reference": "3af63f44ddb45b03af4d172a4ce3e5c58b25fc5b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/3af63f44ddb45b03af4d172a4ce3e5c58b25fc5b", + "reference": "3af63f44ddb45b03af4d172a4ce3e5c58b25fc5b", + "shasum": "" + }, + "require": { + "php": "^7.1.3", + "symfony/polyfill-mbstring": "~1.0", + "symfony/polyfill-php72": "~1.5" + }, + "conflict": { + "phpunit/phpunit": "<4.8.35|<5.4.3,>=5.0" + }, + "require-dev": { + "ext-iconv": "*", + "twig/twig": "~1.34|~2.4" + }, + "suggest": { + "ext-iconv": "To convert non-UTF-8 strings to UTF-8 (or symfony/polyfill-iconv in case ext-iconv cannot be used).", + "ext-intl": "To show region name in time zone dump" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0-dev" + } + }, + "autoload": { + "files": [ + "Resources/functions/dump.php" + ], + "psr-4": { + "Symfony\\Component\\VarDumper\\": "" + }, + "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 mechanism for exploring and dumping PHP variables", + "homepage": "https://symfony.com", + "keywords": [ + "debug", + "dump" + ], + "time": "2018-07-26T11:22:46+00:00" + }, + { + "name": "symfony/yaml", + "version": "v2.8.52", + "source": { + "type": "git", + "url": "https://github.com/symfony/yaml.git", + "reference": "02c1859112aa779d9ab394ae4f3381911d84052b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/yaml/zipball/02c1859112aa779d9ab394ae4f3381911d84052b", + "reference": "02c1859112aa779d9ab394ae4f3381911d84052b", + "shasum": "" + }, + "require": { + "php": ">=5.3.9", + "symfony/polyfill-ctype": "~1.8" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.8-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Yaml\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Yaml Component", + "homepage": "https://symfony.com", + "time": "2018-11-11T11:18:13+00:00" + }, + { + "name": "tecnickcom/tcpdf", + "version": "6.3.5", + "source": { + "type": "git", + "url": "https://github.com/tecnickcom/TCPDF.git", + "reference": "19a535eaa7fb1c1cac499109deeb1a7a201b4549" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/tecnickcom/TCPDF/zipball/19a535eaa7fb1c1cac499109deeb1a7a201b4549", + "reference": "19a535eaa7fb1c1cac499109deeb1a7a201b4549", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "type": "library", + "autoload": { + "classmap": [ + "config", + "include", + "tcpdf.php", + "tcpdf_parser.php", + "tcpdf_import.php", + "tcpdf_barcodes_1d.php", + "tcpdf_barcodes_2d.php", + "include/tcpdf_colors.php", + "include/tcpdf_filters.php", + "include/tcpdf_font_data.php", + "include/tcpdf_fonts.php", + "include/tcpdf_images.php", + "include/tcpdf_static.php", + "include/barcodes/datamatrix.php", + "include/barcodes/pdf417.php", + "include/barcodes/qrcode.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "LGPL-3.0-only" + ], + "authors": [ + { + "name": "Nicola Asuni", + "email": "info@tecnick.com", + "role": "lead" + } + ], + "description": "TCPDF is a PHP class for generating PDF documents and barcodes.", + "homepage": "http://www.tcpdf.org/", + "keywords": [ + "PDFD32000-2008", + "TCPDF", + "barcodes", + "datamatrix", + "pdf", + "pdf417", + "qrcode" + ], + "time": "2020-02-14T14:20:12+00:00" + }, + { + "name": "thelia/colissimo-module", + "version": "2.4.3", + "source": { + "type": "git", + "url": "https://github.com/thelia-modules/Colissimo.git", + "reference": "b08153915f717017290dc0711ddaea2194f045a2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thelia-modules/Colissimo/zipball/b08153915f717017290dc0711ddaea2194f045a2", + "reference": "b08153915f717017290dc0711ddaea2194f045a2", + "shasum": "" + }, + "require": { + "thelia/installer": "~1.1" + }, + "type": "thelia-module", + "extra": { + "installer-name": "Colissimo" + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "LGPL-3.0+" + ], + "time": "2020-11-02T13:55:41+00:00" + }, + { + "name": "thelia/currency-converter", + "version": "1.0.2", + "source": { + "type": "git", + "url": "https://github.com/thelia/CurrencyConverter.git", + "reference": "93dae743cf7cd82cf169012bfd6a8dd43d68b974" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thelia/CurrencyConverter/zipball/93dae743cf7cd82cf169012bfd6a8dd43d68b974", + "reference": "93dae743cf7cd82cf169012bfd6a8dd43d68b974", + "shasum": "" + }, + "require": { + "php": ">=5.4.0", + "thelia/math-tools": "~1.0" + }, + "require-dev": { + "phpunit/phpunit": "~4.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Thelia\\CurrencyConverter\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "LGPL-3.0+" + ], + "authors": [ + { + "name": "Manuel Raynaud", + "email": "manu@thelia.net" + } + ], + "description": "php 5.4 currency tools", + "time": "2017-09-30T16:33:49+00:00" + }, + { + "name": "thelia/installer", + "version": "1.3", + "source": { + "type": "git", + "url": "https://github.com/thelia/installer.git", + "reference": "dca473563e05011c7aea3aaebc6f154fef4187fe" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thelia/installer/zipball/dca473563e05011c7aea3aaebc6f154fef4187fe", + "reference": "dca473563e05011c7aea3aaebc6f154fef4187fe", + "shasum": "" + }, + "require": { + "composer-plugin-api": "^1.0||^2.0" + }, + "require-dev": { + "composer/composer": "1.0.*@dev||2.0.*@dev" + }, + "type": "composer-plugin", + "extra": { + "class": "Thelia\\Composer\\TheliaInstallerPlugin" + }, + "autoload": { + "psr-0": { + "Thelia\\Composer": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "LGPL-3.0-or-later" + ], + "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": "2020-10-26T10:32:18+00:00" + }, + { + "name": "thelia/math-tools", + "version": "1.0.2", + "source": { + "type": "git", + "url": "https://github.com/thelia/math-tools.git", + "reference": "4e66cd5448531a6eaf565acd8b69d9c693da7a3a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thelia/math-tools/zipball/4e66cd5448531a6eaf565acd8b69d9c693da7a3a", + "reference": "4e66cd5448531a6eaf565acd8b69d9c693da7a3a", + "shasum": "" + }, + "require-dev": { + "phpunit/phpunit": "4.1.*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "psr-4": { + "Thelia\\Math\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "LGPL" + ], + "authors": [ + { + "name": "Benjamin Perche", + "email": "bperche@openstudio.com" + } + ], + "description": "Number management library", + "time": "2015-11-05T15:52:55+00:00" + }, + { + "name": "thelia/propel", + "version": "dev-thelia-2.4", + "source": { + "type": "git", + "url": "https://github.com/thelia/Propel2.git", + "reference": "0d49917d48475c54c4ae6c8f780d1838aa810d5d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thelia/Propel2/zipball/0d49917d48475c54c4ae6c8f780d1838aa810d5d", + "reference": "0d49917d48475c54c4ae6c8f780d1838aa810d5d", + "shasum": "" + }, + "require": { + "php": ">=5.5|^7.0", + "psr/log": "~1.0", + "symfony/config": "~2.3||~3.0", + "symfony/console": "~2.3||~3.0", + "symfony/event-dispatcher": "*", + "symfony/filesystem": "~2.3||~3.0", + "symfony/finder": "~2.3||~3.0", + "symfony/validator": "~2.3||~3.0.0||~3.1.0||^3.2.4", + "symfony/yaml": "~2.3||~3.0" + }, + "require-dev": { + "monolog/monolog": "~1.3", + "phpunit/phpunit": "~4.0||~5.0" + }, + "suggest": { + "monolog/monolog": "The recommended logging library to use with Propel." + }, + "bin": [ + "bin/propel" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" + } + }, + "autoload": { + "psr-0": { + "Propel": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "William Durand", + "email": "william.durand1@gmail.com" + } + ], + "description": "Propel2 is an open-source Object-Relational Mapping (ORM) for PHP 5.5 and up.", + "homepage": "http://www.propelorm.org/", + "keywords": [ + "Active Record", + "orm", + "persistence" + ], + "time": "2020-03-25T14:16:18+00:00" + }, + { + "name": "thelia/smarty-module", + "version": "2.4.3", + "source": { + "type": "git", + "url": "https://github.com/thelia-modules/TheliaSmarty.git", + "reference": "b0ad6eeedc8db894ca2598abccbc3ed260c46360" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thelia-modules/TheliaSmarty/zipball/b0ad6eeedc8db894ca2598abccbc3ed260c46360", + "reference": "b0ad6eeedc8db894ca2598abccbc3ed260c46360", + "shasum": "" + }, + "require": { + "thelia/installer": "~1.1" + }, + "type": "thelia-module", + "extra": { + "installer-name": "TheliaSmarty" + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "LGPL-3.0+" + ], + "time": "2020-10-28T09:44:45+00:00" + } + ], + "packages-dev": [ + { + "name": "doctrine/instantiator", + "version": "1.4.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/instantiator.git", + "reference": "d56bf6102915de5702778fe20f2de3b2fe570b5b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/instantiator/zipball/d56bf6102915de5702778fe20f2de3b2fe570b5b", + "reference": "d56bf6102915de5702778fe20f2de3b2fe570b5b", + "shasum": "" + }, + "require": { + "php": "^7.1 || ^8.0" + }, + "require-dev": { + "doctrine/coding-standard": "^8.0", + "ext-pdo": "*", + "ext-phar": "*", + "phpbench/phpbench": "^0.13 || 1.0.0-alpha2", + "phpstan/phpstan": "^0.12", + "phpstan/phpstan-phpunit": "^0.12", + "phpunit/phpunit": "^7.0 || ^8.0 || ^9.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Marco Pivetta", + "email": "ocramius@gmail.com", + "homepage": "https://ocramius.github.io/" + } + ], + "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", + "homepage": "https://www.doctrine-project.org/projects/instantiator.html", + "keywords": [ + "constructor", + "instantiate" + ], + "funding": [ + { + "url": "https://www.doctrine-project.org/sponsorship.html", + "type": "custom" + }, + { + "url": "https://www.patreon.com/phpdoctrine", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/doctrine%2Finstantiator", + "type": "tidelift" + } + ], + "time": "2020-11-10T18:47:58+00:00" + }, + { + "name": "fzaninotto/faker", + "version": "v1.5.0", + "source": { + "type": "git", + "url": "https://github.com/fzaninotto/Faker.git", + "reference": "d0190b156bcca848d401fb80f31f504f37141c8d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/fzaninotto/Faker/zipball/d0190b156bcca848d401fb80f31f504f37141c8d", + "reference": "d0190b156bcca848d401fb80f31f504f37141c8d", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "phpunit/phpunit": "~4.0", + "squizlabs/php_codesniffer": "~1.5" + }, + "suggest": { + "ext-intl": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.5.x-dev" + } + }, + "autoload": { + "psr-4": { + "Faker\\": "src/Faker/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "François Zaninotto" + } + ], + "description": "Faker is a PHP library that generates fake data for you.", + "keywords": [ + "data", + "faker", + "fixtures" + ], + "abandoned": true, + "time": "2015-05-29T06:29:14+00:00" + }, + { + "name": "myclabs/deep-copy", + "version": "1.10.2", + "source": { + "type": "git", + "url": "https://github.com/myclabs/DeepCopy.git", + "reference": "776f831124e9c62e1a2c601ecc52e776d8bb7220" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/776f831124e9c62e1a2c601ecc52e776d8bb7220", + "reference": "776f831124e9c62e1a2c601ecc52e776d8bb7220", + "shasum": "" + }, + "require": { + "php": "^7.1 || ^8.0" + }, + "replace": { + "myclabs/deep-copy": "self.version" + }, + "require-dev": { + "doctrine/collections": "^1.0", + "doctrine/common": "^2.6", + "phpunit/phpunit": "^7.1" + }, + "type": "library", + "autoload": { + "psr-4": { + "DeepCopy\\": "src/DeepCopy/" + }, + "files": [ + "src/DeepCopy/deep_copy.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Create deep copies (clones) of your objects", + "keywords": [ + "clone", + "copy", + "duplicate", + "object", + "object graph" + ], + "funding": [ + { + "url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy", + "type": "tidelift" + } + ], + "time": "2020-11-13T09:40:50+00:00" + }, + { + "name": "phpdocumentor/reflection-common", + "version": "2.2.0", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/ReflectionCommon.git", + "reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/1d01c49d4ed62f25aa84a747ad35d5a16924662b", + "reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-2.x": "2.x-dev" + } + }, + "autoload": { + "psr-4": { + "phpDocumentor\\Reflection\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jaap van Otterdijk", + "email": "opensource@ijaap.nl" + } + ], + "description": "Common reflection classes used by phpdocumentor to reflect the code structure", + "homepage": "http://www.phpdoc.org", + "keywords": [ + "FQSEN", + "phpDocumentor", + "phpdoc", + "reflection", + "static analysis" + ], + "time": "2020-06-27T09:03:43+00:00" + }, + { + "name": "phpdocumentor/reflection-docblock", + "version": "5.2.2", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", + "reference": "069a785b2141f5bcf49f3e353548dc1cce6df556" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/069a785b2141f5bcf49f3e353548dc1cce6df556", + "reference": "069a785b2141f5bcf49f3e353548dc1cce6df556", + "shasum": "" + }, + "require": { + "ext-filter": "*", + "php": "^7.2 || ^8.0", + "phpdocumentor/reflection-common": "^2.2", + "phpdocumentor/type-resolver": "^1.3", + "webmozart/assert": "^1.9.1" + }, + "require-dev": { + "mockery/mockery": "~1.3.2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.x-dev" + } + }, + "autoload": { + "psr-4": { + "phpDocumentor\\Reflection\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mike van Riel", + "email": "me@mikevanriel.com" + }, + { + "name": "Jaap van Otterdijk", + "email": "account@ijaap.nl" + } + ], + "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", + "time": "2020-09-03T19:13:55+00:00" + }, + { + "name": "phpdocumentor/type-resolver", + "version": "1.4.0", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/TypeResolver.git", + "reference": "6a467b8989322d92aa1c8bf2bebcc6e5c2ba55c0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/6a467b8989322d92aa1c8bf2bebcc6e5c2ba55c0", + "reference": "6a467b8989322d92aa1c8bf2bebcc6e5c2ba55c0", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0", + "phpdocumentor/reflection-common": "^2.0" + }, + "require-dev": { + "ext-tokenizer": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-1.x": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "phpDocumentor\\Reflection\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mike van Riel", + "email": "me@mikevanriel.com" + } + ], + "description": "A PSR-5 based resolver of Class names, Types and Structural Element Names", + "time": "2020-09-17T18:55:26+00:00" + }, + { + "name": "phpspec/prophecy", + "version": "v1.10.3", + "source": { + "type": "git", + "url": "https://github.com/phpspec/prophecy.git", + "reference": "451c3cd1418cf640de218914901e51b064abb093" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpspec/prophecy/zipball/451c3cd1418cf640de218914901e51b064abb093", + "reference": "451c3cd1418cf640de218914901e51b064abb093", + "shasum": "" + }, + "require": { + "doctrine/instantiator": "^1.0.2", + "php": "^5.3|^7.0", + "phpdocumentor/reflection-docblock": "^2.0|^3.0.2|^4.0|^5.0", + "sebastian/comparator": "^1.2.3|^2.0|^3.0|^4.0", + "sebastian/recursion-context": "^1.0|^2.0|^3.0|^4.0" + }, + "require-dev": { + "phpspec/phpspec": "^2.5 || ^3.2", + "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.5 || ^7.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.10.x-dev" + } + }, + "autoload": { + "psr-4": { + "Prophecy\\": "src/Prophecy" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Konstantin Kudryashov", + "email": "ever.zet@gmail.com", + "homepage": "http://everzet.com" + }, + { + "name": "Marcello Duarte", + "email": "marcello.duarte@gmail.com" + } + ], + "description": "Highly opinionated mocking framework for PHP 5.3+", + "homepage": "https://github.com/phpspec/prophecy", + "keywords": [ + "Double", + "Dummy", + "fake", + "mock", + "spy", + "stub" + ], + "time": "2020-03-05T15:02:03+00:00" + }, + { + "name": "phpunit/php-code-coverage", + "version": "4.0.8", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-code-coverage.git", + "reference": "ef7b2f56815df854e66ceaee8ebe9393ae36a40d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/ef7b2f56815df854e66ceaee8ebe9393ae36a40d", + "reference": "ef7b2f56815df854e66ceaee8ebe9393ae36a40d", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-xmlwriter": "*", + "php": "^5.6 || ^7.0", + "phpunit/php-file-iterator": "^1.3", + "phpunit/php-text-template": "^1.2", + "phpunit/php-token-stream": "^1.4.2 || ^2.0", + "sebastian/code-unit-reverse-lookup": "^1.0", + "sebastian/environment": "^1.3.2 || ^2.0", + "sebastian/version": "^1.0 || ^2.0" + }, + "require-dev": { + "ext-xdebug": "^2.1.4", + "phpunit/phpunit": "^5.7" + }, + "suggest": { + "ext-xdebug": "^2.5.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sb@sebastian-bergmann.de", + "role": "lead" + } + ], + "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", + "homepage": "https://github.com/sebastianbergmann/php-code-coverage", + "keywords": [ + "coverage", + "testing", + "xunit" + ], + "time": "2017-04-02T07:44:40+00:00" + }, + { + "name": "phpunit/php-file-iterator", + "version": "1.4.5", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-file-iterator.git", + "reference": "730b01bc3e867237eaac355e06a36b85dd93a8b4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/730b01bc3e867237eaac355e06a36b85dd93a8b4", + "reference": "730b01bc3e867237eaac355e06a36b85dd93a8b4", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.4.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sb@sebastian-bergmann.de", + "role": "lead" + } + ], + "description": "FilterIterator implementation that filters files based on a list of suffixes.", + "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", + "keywords": [ + "filesystem", + "iterator" + ], + "time": "2017-11-27T13:52:08+00:00" + }, + { + "name": "phpunit/php-text-template", + "version": "1.2.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-text-template.git", + "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/31f8b717e51d9a2afca6c9f046f5d69fc27c8686", + "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Simple template engine.", + "homepage": "https://github.com/sebastianbergmann/php-text-template/", + "keywords": [ + "template" + ], + "time": "2015-06-21T13:50:34+00:00" + }, + { + "name": "phpunit/php-timer", + "version": "1.0.9", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-timer.git", + "reference": "3dcf38ca72b158baf0bc245e9184d3fdffa9c46f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/3dcf38ca72b158baf0bc245e9184d3fdffa9c46f", + "reference": "3dcf38ca72b158baf0bc245e9184d3fdffa9c46f", + "shasum": "" + }, + "require": { + "php": "^5.3.3 || ^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sb@sebastian-bergmann.de", + "role": "lead" + } + ], + "description": "Utility class for timing", + "homepage": "https://github.com/sebastianbergmann/php-timer/", + "keywords": [ + "timer" + ], + "time": "2017-02-26T11:10:40+00:00" + }, + { + "name": "phpunit/php-token-stream", + "version": "2.0.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-token-stream.git", + "reference": "791198a2c6254db10131eecfe8c06670700904db" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/791198a2c6254db10131eecfe8c06670700904db", + "reference": "791198a2c6254db10131eecfe8c06670700904db", + "shasum": "" + }, + "require": { + "ext-tokenizer": "*", + "php": "^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^6.2.4" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Wrapper around PHP's tokenizer extension.", + "homepage": "https://github.com/sebastianbergmann/php-token-stream/", + "keywords": [ + "tokenizer" + ], + "abandoned": true, + "time": "2017-11-27T05:48:46+00:00" + }, + { + "name": "phpunit/phpunit", + "version": "5.7.27", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/phpunit.git", + "reference": "b7803aeca3ccb99ad0a506fa80b64cd6a56bbc0c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/b7803aeca3ccb99ad0a506fa80b64cd6a56bbc0c", + "reference": "b7803aeca3ccb99ad0a506fa80b64cd6a56bbc0c", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-json": "*", + "ext-libxml": "*", + "ext-mbstring": "*", + "ext-xml": "*", + "myclabs/deep-copy": "~1.3", + "php": "^5.6 || ^7.0", + "phpspec/prophecy": "^1.6.2", + "phpunit/php-code-coverage": "^4.0.4", + "phpunit/php-file-iterator": "~1.4", + "phpunit/php-text-template": "~1.2", + "phpunit/php-timer": "^1.0.6", + "phpunit/phpunit-mock-objects": "^3.2", + "sebastian/comparator": "^1.2.4", + "sebastian/diff": "^1.4.3", + "sebastian/environment": "^1.3.4 || ^2.0", + "sebastian/exporter": "~2.0", + "sebastian/global-state": "^1.1", + "sebastian/object-enumerator": "~2.0", + "sebastian/resource-operations": "~1.0", + "sebastian/version": "^1.0.6|^2.0.1", + "symfony/yaml": "~2.1|~3.0|~4.0" + }, + "conflict": { + "phpdocumentor/reflection-docblock": "3.0.2" + }, + "require-dev": { + "ext-pdo": "*" + }, + "suggest": { + "ext-xdebug": "*", + "phpunit/php-invoker": "~1.1" + }, + "bin": [ + "phpunit" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.7.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "The PHP Unit Testing framework.", + "homepage": "https://phpunit.de/", + "keywords": [ + "phpunit", + "testing", + "xunit" + ], + "time": "2018-02-01T05:50:59+00:00" + }, + { + "name": "phpunit/phpunit-mock-objects", + "version": "3.4.4", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git", + "reference": "a23b761686d50a560cc56233b9ecf49597cc9118" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/a23b761686d50a560cc56233b9ecf49597cc9118", + "reference": "a23b761686d50a560cc56233b9ecf49597cc9118", + "shasum": "" + }, + "require": { + "doctrine/instantiator": "^1.0.2", + "php": "^5.6 || ^7.0", + "phpunit/php-text-template": "^1.2", + "sebastian/exporter": "^1.2 || ^2.0" + }, + "conflict": { + "phpunit/phpunit": "<5.4.0" + }, + "require-dev": { + "phpunit/phpunit": "^5.4" + }, + "suggest": { + "ext-soap": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.2.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sb@sebastian-bergmann.de", + "role": "lead" + } + ], + "description": "Mock Object library for PHPUnit", + "homepage": "https://github.com/sebastianbergmann/phpunit-mock-objects/", + "keywords": [ + "mock", + "xunit" + ], + "abandoned": true, + "time": "2017-06-30T09:13:00+00:00" + }, + { + "name": "sebastian/code-unit-reverse-lookup", + "version": "1.0.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", + "reference": "1de8cd5c010cb153fcd68b8d0f64606f523f7619" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/1de8cd5c010cb153fcd68b8d0f64606f523f7619", + "reference": "1de8cd5c010cb153fcd68b8d0f64606f523f7619", + "shasum": "" + }, + "require": { + "php": ">=5.6" + }, + "require-dev": { + "phpunit/phpunit": "^8.5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Looks up which function or method a line of code belongs to", + "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-11-30T08:15:22+00:00" + }, + { + "name": "sebastian/comparator", + "version": "1.2.4", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/comparator.git", + "reference": "2b7424b55f5047b47ac6e5ccb20b2aea4011d9be" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/2b7424b55f5047b47ac6e5ccb20b2aea4011d9be", + "reference": "2b7424b55f5047b47ac6e5ccb20b2aea4011d9be", + "shasum": "" + }, + "require": { + "php": ">=5.3.3", + "sebastian/diff": "~1.2", + "sebastian/exporter": "~1.2 || ~2.0" + }, + "require-dev": { + "phpunit/phpunit": "~4.4" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.2.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@2bepublished.at" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Provides the functionality to compare PHP values for equality", + "homepage": "http://www.github.com/sebastianbergmann/comparator", + "keywords": [ + "comparator", + "compare", + "equality" + ], + "time": "2017-01-29T09:50:25+00:00" + }, + { + "name": "sebastian/diff", + "version": "1.4.3", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/diff.git", + "reference": "7f066a26a962dbe58ddea9f72a4e82874a3975a4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/7f066a26a962dbe58ddea9f72a4e82874a3975a4", + "reference": "7f066a26a962dbe58ddea9f72a4e82874a3975a4", + "shasum": "" + }, + "require": { + "php": "^5.3.3 || ^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.4-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Kore Nordmann", + "email": "mail@kore-nordmann.de" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Diff implementation", + "homepage": "https://github.com/sebastianbergmann/diff", + "keywords": [ + "diff" + ], + "time": "2017-05-22T07:24:03+00:00" + }, + { + "name": "sebastian/environment", + "version": "2.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/environment.git", + "reference": "5795ffe5dc5b02460c3e34222fee8cbe245d8fac" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/5795ffe5dc5b02460c3e34222fee8cbe245d8fac", + "reference": "5795ffe5dc5b02460c3e34222fee8cbe245d8fac", + "shasum": "" + }, + "require": { + "php": "^5.6 || ^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^5.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Provides functionality to handle HHVM/PHP environments", + "homepage": "http://www.github.com/sebastianbergmann/environment", + "keywords": [ + "Xdebug", + "environment", + "hhvm" + ], + "time": "2016-11-26T07:53:53+00:00" + }, + { + "name": "sebastian/exporter", + "version": "2.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/exporter.git", + "reference": "ce474bdd1a34744d7ac5d6aad3a46d48d9bac4c4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/ce474bdd1a34744d7ac5d6aad3a46d48d9bac4c4", + "reference": "ce474bdd1a34744d7ac5d6aad3a46d48d9bac4c4", + "shasum": "" + }, + "require": { + "php": ">=5.3.3", + "sebastian/recursion-context": "~2.0" + }, + "require-dev": { + "ext-mbstring": "*", + "phpunit/phpunit": "~4.4" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@2bepublished.at" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" + } + ], + "description": "Provides the functionality to export PHP variables for visualization", + "homepage": "http://www.github.com/sebastianbergmann/exporter", + "keywords": [ + "export", + "exporter" + ], + "time": "2016-11-19T08:54:04+00:00" + }, + { + "name": "sebastian/global-state", + "version": "1.1.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/global-state.git", + "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bc37d50fea7d017d3d340f230811c9f1d7280af4", + "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "phpunit/phpunit": "~4.2" + }, + "suggest": { + "ext-uopz": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Snapshotting of global state", + "homepage": "http://www.github.com/sebastianbergmann/global-state", + "keywords": [ + "global state" + ], + "time": "2015-10-12T03:26:01+00:00" + }, + { + "name": "sebastian/object-enumerator", + "version": "2.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/object-enumerator.git", + "reference": "1311872ac850040a79c3c058bea3e22d0f09cbb7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/1311872ac850040a79c3c058bea3e22d0f09cbb7", + "reference": "1311872ac850040a79c3c058bea3e22d0f09cbb7", + "shasum": "" + }, + "require": { + "php": ">=5.6", + "sebastian/recursion-context": "~2.0" + }, + "require-dev": { + "phpunit/phpunit": "~5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Traverses array structures and object graphs to enumerate all referenced objects", + "homepage": "https://github.com/sebastianbergmann/object-enumerator/", + "time": "2017-02-18T15:18:39+00:00" + }, + { + "name": "sebastian/recursion-context", + "version": "2.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/recursion-context.git", + "reference": "2c3ba150cbec723aa057506e73a8d33bdb286c9a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/2c3ba150cbec723aa057506e73a8d33bdb286c9a", + "reference": "2c3ba150cbec723aa057506e73a8d33bdb286c9a", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "phpunit/phpunit": "~4.4" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" + } + ], + "description": "Provides functionality to recursively process PHP variables", + "homepage": "http://www.github.com/sebastianbergmann/recursion-context", + "time": "2016-11-19T07:33:16+00:00" + }, + { + "name": "sebastian/resource-operations", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/resource-operations.git", + "reference": "ce990bb21759f94aeafd30209e8cfcdfa8bc3f52" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/ce990bb21759f94aeafd30209e8cfcdfa8bc3f52", + "reference": "ce990bb21759f94aeafd30209e8cfcdfa8bc3f52", + "shasum": "" + }, + "require": { + "php": ">=5.6.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Provides a list of PHP built-in functions that operate on resources", + "homepage": "https://www.github.com/sebastianbergmann/resource-operations", + "time": "2015-07-28T20:34:47+00:00" + }, + { + "name": "sebastian/version", + "version": "2.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/version.git", + "reference": "99732be0ddb3361e16ad77b68ba41efc8e979019" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/99732be0ddb3361e16ad77b68ba41efc8e979019", + "reference": "99732be0ddb3361e16ad77b68ba41efc8e979019", + "shasum": "" + }, + "require": { + "php": ">=5.6" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library that helps with managing the version number of Git-hosted PHP projects", + "homepage": "https://github.com/sebastianbergmann/version", + "time": "2016-10-03T07:35:21+00:00" + }, + { + "name": "thelia/hooktest-module", + "version": "1.1", + "source": { + "type": "git", + "url": "https://github.com/thelia/HookTest-module.git", + "reference": "32891857fd1e8e9ca5b7a9dbb0960ef3dd525fcb" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thelia/HookTest-module/zipball/32891857fd1e8e9ca5b7a9dbb0960ef3dd525fcb", + "reference": "32891857fd1e8e9ca5b7a9dbb0960ef3dd525fcb", + "shasum": "" + }, + "require": { + "thelia/installer": "~1.1" + }, + "type": "thelia-module", + "extra": { + "installer-name": "HookTest" + }, + "notification-url": "https://packagist.org/downloads/", + "time": "2014-12-24T09:52:09+00:00" + }, + { + "name": "thelia/hooktest-template", + "version": "1.1", + "source": { + "type": "git", + "url": "https://github.com/thelia/hooktest-template.git", + "reference": "bb0a26df8ecfe7e41e2e391adb22360201088dda" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thelia/hooktest-template/zipball/bb0a26df8ecfe7e41e2e391adb22360201088dda", + "reference": "bb0a26df8ecfe7e41e2e391adb22360201088dda", + "shasum": "" + }, + "require": { + "thelia/installer": "~1.1" + }, + "type": "thelia-frontoffice-template", + "extra": { + "installer-name": "hooktest" + }, + "notification-url": "https://packagist.org/downloads/", + "time": "2014-12-24T09:51:48+00:00" + }, + { + "name": "webmozart/assert", + "version": "1.9.1", + "source": { + "type": "git", + "url": "https://github.com/webmozart/assert.git", + "reference": "bafc69caeb4d49c39fd0779086c03a3738cbb389" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/webmozart/assert/zipball/bafc69caeb4d49c39fd0779086c03a3738cbb389", + "reference": "bafc69caeb4d49c39fd0779086c03a3738cbb389", + "shasum": "" + }, + "require": { + "php": "^5.3.3 || ^7.0 || ^8.0", + "symfony/polyfill-ctype": "^1.8" + }, + "conflict": { + "phpstan/phpstan": "<0.12.20", + "vimeo/psalm": "<3.9.1" + }, + "require-dev": { + "phpunit/phpunit": "^4.8.36 || ^7.5.13" + }, + "type": "library", + "autoload": { + "psr-4": { + "Webmozart\\Assert\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" + } + ], + "description": "Assertions to validate method input/output with nice error messages.", + "keywords": [ + "assert", + "check", + "validate" + ], + "time": "2020-07-08T17:02:28+00:00" + } + ], + "aliases": [], + "minimum-stability": "stable", + "stability-flags": { + "thelia/propel": 20 + }, + "prefer-stable": false, + "prefer-lowest": false, + "platform": { + "php": ">=5.6 <7.4" + }, + "platform-dev": [], + "plugin-api-version": "1.1.0" +} diff --git a/core/LICENSE.txt b/core/LICENSE.txt new file mode 100644 index 00000000..65c5ca88 --- /dev/null +++ b/core/LICENSE.txt @@ -0,0 +1,165 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + + This version of the GNU Lesser General Public License incorporates +the terms and conditions of version 3 of the GNU General Public +License, supplemented by the additional permissions listed below. + + 0. Additional Definitions. + + As used herein, "this License" refers to version 3 of the GNU Lesser +General Public License, and the "GNU GPL" refers to version 3 of the GNU +General Public License. + + "The Library" refers to a covered work governed by this License, +other than an Application or a Combined Work as defined below. + + An "Application" is any work that makes use of an interface provided +by the Library, but which is not otherwise based on the Library. +Defining a subclass of a class defined by the Library is deemed a mode +of using an interface provided by the Library. + + A "Combined Work" is a work produced by combining or linking an +Application with the Library. The particular version of the Library +with which the Combined Work was made is also called the "Linked +Version". + + The "Minimal Corresponding Source" for a Combined Work means the +Corresponding Source for the Combined Work, excluding any source code +for portions of the Combined Work that, considered in isolation, are +based on the Application, and not on the Linked Version. + + The "Corresponding Application Code" for a Combined Work means the +object code and/or source code for the Application, including any data +and utility programs needed for reproducing the Combined Work from the +Application, but excluding the System Libraries of the Combined Work. + + 1. Exception to Section 3 of the GNU GPL. + + You may convey a covered work under sections 3 and 4 of this License +without being bound by section 3 of the GNU GPL. + + 2. Conveying Modified Versions. + + If you modify a copy of the Library, and, in your modifications, a +facility refers to a function or data to be supplied by an Application +that uses the facility (other than as an argument passed when the +facility is invoked), then you may convey a copy of the modified +version: + + a) under this License, provided that you make a good faith effort to + ensure that, in the event an Application does not supply the + function or data, the facility still operates, and performs + whatever part of its purpose remains meaningful, or + + b) under the GNU GPL, with none of the additional permissions of + this License applicable to that copy. + + 3. Object Code Incorporating Material from Library Header Files. + + The object code form of an Application may incorporate material from +a header file that is part of the Library. You may convey such object +code under terms of your choice, provided that, if the incorporated +material is not limited to numerical parameters, data structure +layouts and accessors, or small macros, inline functions and templates +(ten or fewer lines in length), you do both of the following: + + a) Give prominent notice with each copy of the object code that the + Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the object code with a copy of the GNU GPL and this license + document. + + 4. Combined Works. + + You may convey a Combined Work under terms of your choice that, +taken together, effectively do not restrict modification of the +portions of the Library contained in the Combined Work and reverse +engineering for debugging such modifications, if you also do each of +the following: + + a) Give prominent notice with each copy of the Combined Work that + the Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the Combined Work with a copy of the GNU GPL and this license + document. + + c) For a Combined Work that displays copyright notices during + execution, include the copyright notice for the Library among + these notices, as well as a reference directing the user to the + copies of the GNU GPL and this license document. + + d) Do one of the following: + + 0) Convey the Minimal Corresponding Source under the terms of this + License, and the Corresponding Application Code in a form + suitable for, and under terms that permit, the user to + recombine or relink the Application with a modified version of + the Linked Version to produce a modified Combined Work, in the + manner specified by section 6 of the GNU GPL for conveying + Corresponding Source. + + 1) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (a) uses at run time + a copy of the Library already present on the user's computer + system, and (b) will operate properly with a modified version + of the Library that is interface-compatible with the Linked + Version. + + e) Provide Installation Information, but only if you would otherwise + be required to provide such information under section 6 of the + GNU GPL, and only to the extent that such information is + necessary to install and execute a modified version of the + Combined Work produced by recombining or relinking the + Application with a modified version of the Linked Version. (If + you use option 4d0, the Installation Information must accompany + the Minimal Corresponding Source and Corresponding Application + Code. If you use option 4d1, you must provide the Installation + Information in the manner specified by section 6 of the GNU GPL + for conveying Corresponding Source.) + + 5. Combined Libraries. + + You may place library facilities that are a work based on the +Library side by side in a single library together with other library +facilities that are not Applications and are not covered by this +License, and convey such a combined library under terms of your +choice, if you do both of the following: + + a) Accompany the combined library with a copy of the same work based + on the Library, uncombined with any other library facilities, + conveyed under the terms of this License. + + b) Give prominent notice with the combined library that part of it + is a work based on the Library, and explaining where to find the + accompanying uncombined form of the same work. + + 6. Revised Versions of the GNU Lesser General Public License. + + The Free Software Foundation may publish revised and/or new versions +of the GNU Lesser General Public License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. + + Each version is given a distinguishing version number. If the +Library as you received it specifies that a certain numbered version +of the GNU Lesser General Public License "or any later version" +applies to it, you have the option of following the terms and +conditions either of that published version or of any later version +published by the Free Software Foundation. If the Library as you +received it does not specify a version number of the GNU Lesser +General Public License, you may choose any version of the GNU Lesser +General Public License ever published by the Free Software Foundation. + + If the Library as you received it specifies that a proxy can decide +whether future versions of the GNU Lesser General Public License shall +apply, that proxy's public statement of acceptance of any version is +permanent authorization for you to choose that version for the +Library. diff --git a/core/Readme.md b/core/Readme.md new file mode 100644 index 00000000..4f8445b3 --- /dev/null +++ b/core/Readme.md @@ -0,0 +1,47 @@ +Readme +====== + +## This is the repository of Thelia core. All the pull requests on this repo will be ignored. +### If you want to create a project, please take a look at [thelia/thelia-project](https://github.com/thelia/thelia-project) +### If you want to contribute to Thelia, please take a look at [thelia/thelia](https://github.com/thelia/thelia) + +Thelia +------ +[![Build Status](https://travis-ci.org/thelia/thelia.png?branch=master)](https://travis-ci.org/thelia/thelia) [![License](https://poser.pugx.org/thelia/thelia/license.png)](https://packagist.org/packages/thelia/thelia) [![Scrutinizer Quality Score](https://scrutinizer-ci.com/g/thelia/thelia/badges/quality-score.png?s=61e3e04a69bffd71c29b08e5392080317a546716)](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. + +This is the new major version of Thelia. + +You can download this version and have a try or take a look at the source code (or anything you wish, respecting LGPL). See http://thelia.net/ web site for more information. + +A repository containing all thelia modules is available at this address : https://github.com/thelia-modules + + +Compatibility +------------ + +| | Thelia 2.1 | Thelia 2.2 | Thelia 2.3 | Thelia 2.4 | +| ------------- |:-------------:| -----:| -----:| -----:| +| PHP | 5.4 5.5 5.6 | 5.4 5.5 5.6 | 5.5 5.6 7.0 7.1 | 5.6 7.0 7.1 7.2 | +| MySQL | 5.5 5.6 | 5.5 5.6 | 5.5 5.6 | 5.5 5.6 5.7 | +| Symfony | 2.3 | 2.3 | 2.8 | 2.8 | + +Requirements +------------ + +* PHP + * Required extensions : + * PDO_Mysql + * openssl + * intl + * gd + * curl + * dom + * safe_mode off + * memory_limit at least 128M, preferably 256. + * post\_max\_size 20M + * upload\_max\_filesize 2M + * date.timezone must be defined +* Web Server Apache 2 or Nginx +* MySQL 5 diff --git a/core/Thelia b/core/Thelia new file mode 100644 index 00000000..da56bdb1 --- /dev/null +++ b/core/Thelia @@ -0,0 +1,58 @@ +load(THELIA_ROOT.'.env'); +} + +$input = new ArgvInput(); +$env = $input->getParameterOption(array('--env', '-e'), getenv('THELIA_ENV') ?: 'dev'); +$debug = getenv('THELIA_DEBUG') !== '0' && !$input->hasParameterOption(array('--no-debug', '')) && $env !== 'prod'; + +$thelia = new Thelia($env, $debug); +$application = new Application($thelia); +$application->getContainer()->get('thelia.translator'); +$application->run($input, new TheliaConsoleOutput()); diff --git a/core/bootstrap.php b/core/bootstrap.php new file mode 100644 index 00000000..67ab2c8f --- /dev/null +++ b/core/bootstrap.php @@ -0,0 +1,102 @@ +getUriForPath('/install')); + } else { + header($_SERVER['SERVER_PROTOCOL'] . ' 500 Thelia is not installed', true, 500); + die(sprintf( + "Thelia is not installed. More information\n", + "http://doc.thelia.net/en/documentation/installation/index.html#using-cli-tools" + )); + } +} diff --git a/core/composer.json b/core/composer.json new file mode 100644 index 00000000..ba5a653b --- /dev/null +++ b/core/composer.json @@ -0,0 +1,79 @@ +{ + "name": "thelia/core", + "description": "Core of Thelia ecommerce CMS.", + "license": "LGPL-3.0+", + "homepage": "http://thelia.net/", + "support": { + "forum": "http://thelia.net/forum", + "wiki": "http://doc.thelia.net" + }, + "require": { + "php": "^5.6|^7.0", + "ircmaxell/password-compat": "1.0.*", + "psr/log": "1.0", + "symfony/config": "2.8.*", + "symfony/console": "2.8.*", + "symfony/dependency-injection": "2.8.*", + "symfony/event-dispatcher": "2.8.*", + "symfony/http-kernel": "2.8.*", + "symfony/routing": "2.8.*", + "symfony/filesystem": "2.8.*", + "symfony/yaml": "2.8.*", + "symfony/translation": "2.8.*", + "symfony-cmf/routing": "1.3.*", + "symfony/validator": "2.8.*", + "symfony/options-resolver": "2.8.*", + "symfony/security": "2.8.*", + "symfony/expression-language": "2.8.*", + "symfony/process": "2.8.*", + "symfony/dom-crawler": "2.8.*", + "symfony/property-access": "2.8.*", + "symfony/serializer": "2.8.*", + "symfony/finder": "2.8.*", + "symfony/browser-kit": "2.8.*", + "symfony/http-foundation": "2.8.*", + "symfony/form": "2.8.*", + "symfony/class-loader": "2.8.*", + "symfony/dotenv": "^3.4|^4.0", + "stack/builder": "1.0.*", + "thelia/currency-converter": "~1.0", + "doctrine/cache": "1.5.*", + "kriswallsmith/assetic": "1.3.*", + "ptachoire/cssembed": "1.0.*", + "simplepie/simplepie": "1.3.*", + "imagine/imagine": "0.7.1", + "swiftmailer/swiftmailer": "5.4.*", + "oyejorge/less.php": "1.7.*", + "michelf/php-markdown": "1.6.*", + "smarty/smarty": "3.1.33", + "thelia/propel": "dev-thelia-2.4", + "commerceguys/addressing": "0.8.*", + "symfony/cache": "^3.4|^4.0", + "symfony/polyfill-php56": "^1.0", + "symfony/polyfill-php70": "^1.0", + "symfony/polyfill-php71": "^1.0", + "symfony/polyfill-php72": "^1.0", + "spipu/html2pdf": "^5.0", + "symfony/polyfill-php73": "^1.0", + "symfony/lock": "^3.4|^4.0" + }, + "require-dev": { + "fzaninotto/faker": "1.5.*", + "thelia/hooktest-module": "~1.1", + "thelia/hooktest-template": "~1.1", + "phpunit/phpunit": "^5.0", + "symfony/var-dumper": "^2.0|^3.0|^4.0" + }, + "bin": [ + "Thelia" + ], + "minimum-stability": "stable", + "autoload": { + "psr-4": { + "Thelia\\": "lib/Thelia/" + }, + "files": [ + "bootstrap.php" + ] + } +} diff --git a/core/composer.lock b/core/composer.lock new file mode 100644 index 00000000..5aef0be7 --- /dev/null +++ b/core/composer.lock @@ -0,0 +1,5372 @@ +{ + "_readme": [ + "This file locks the dependencies of your project to a known state", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", + "This file is @generated automatically" + ], + "content-hash": "e995acd0837f6fc83e31662dd1eaff20", + "packages": [ + { + "name": "commerceguys/addressing", + "version": "v0.8.4", + "source": { + "type": "git", + "url": "https://github.com/commerceguys/addressing.git", + "reference": "5d8d13bfaed08119be763da2a0fc9f38fff8af54" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/commerceguys/addressing/zipball/5d8d13bfaed08119be763da2a0fc9f38fff8af54", + "reference": "5d8d13bfaed08119be763da2a0fc9f38fff8af54", + "shasum": "" + }, + "require": { + "commerceguys/enum": "~1.0", + "doctrine/collections": "~1.0", + "php": ">=5.4.0" + }, + "require-dev": { + "mikey179/vfsstream": "1.*", + "phpunit/phpunit": "~4.0", + "squizlabs/php_codesniffer": "2.*", + "symfony/intl": ">=2.3", + "symfony/validator": ">=2.3" + }, + "suggest": { + "commerceguys/intl": "to use it as the source of country data", + "symfony/form": "to generate Symfony address forms", + "symfony/intl": "to use it as the source of country data", + "symfony/validator": "to validate addresses" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "0.x-dev" + } + }, + "autoload": { + "psr-4": { + "CommerceGuys\\Addressing\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Bojan Zivanovic" + }, + { + "name": "Damien Tournoud" + } + ], + "description": "Addressing library powered by Google's address data.", + "keywords": [ + "address", + "internationalization", + "localization", + "postal" + ], + "time": "2016-09-05T18:45:53+00:00" + }, + { + "name": "commerceguys/enum", + "version": "v1.0", + "source": { + "type": "git", + "url": "https://github.com/commerceguys/enum.git", + "reference": "1d9db2dbeb1a02500e7a14589ae2f9cb402c5c95" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/commerceguys/enum/zipball/1d9db2dbeb1a02500e7a14589ae2f9cb402c5c95", + "reference": "1d9db2dbeb1a02500e7a14589ae2f9cb402c5c95", + "shasum": "" + }, + "require": { + "php": ">=5.4.0" + }, + "require-dev": { + "phpunit/phpunit": "~4.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "CommerceGuys\\Enum\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Bojan Zivanovic" + } + ], + "description": "A PHP 5.4+ enumeration library.", + "time": "2015-02-27T21:36:56+00:00" + }, + { + "name": "doctrine/cache", + "version": "v1.5.4", + "source": { + "type": "git", + "url": "https://github.com/doctrine/cache.git", + "reference": "47cdc76ceb95cc591d9c79a36dc3794975b5d136" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/cache/zipball/47cdc76ceb95cc591d9c79a36dc3794975b5d136", + "reference": "47cdc76ceb95cc591d9c79a36dc3794975b5d136", + "shasum": "" + }, + "require": { + "php": ">=5.3.2" + }, + "conflict": { + "doctrine/common": ">2.2,<2.4" + }, + "require-dev": { + "phpunit/phpunit": ">=3.7", + "predis/predis": "~1.0", + "satooshi/php-coveralls": "~0.6" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.5.x-dev" + } + }, + "autoload": { + "psr-4": { + "Doctrine\\Common\\Cache\\": "lib/Doctrine/Common/Cache" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + } + ], + "description": "Caching library offering an object-oriented API for many cache backends", + "homepage": "http://www.doctrine-project.org", + "keywords": [ + "cache", + "caching" + ], + "time": "2015-12-19T05:03:47+00:00" + }, + { + "name": "doctrine/collections", + "version": "1.6.7", + "source": { + "type": "git", + "url": "https://github.com/doctrine/collections.git", + "reference": "55f8b799269a1a472457bd1a41b4f379d4cfba4a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/collections/zipball/55f8b799269a1a472457bd1a41b4f379d4cfba4a", + "reference": "55f8b799269a1a472457bd1a41b4f379d4cfba4a", + "shasum": "" + }, + "require": { + "php": "^7.1.3 || ^8.0" + }, + "require-dev": { + "doctrine/coding-standard": "^6.0", + "phpstan/phpstan-shim": "^0.9.2", + "phpunit/phpunit": "^7.0", + "vimeo/psalm": "^3.8.1" + }, + "type": "library", + "autoload": { + "psr-4": { + "Doctrine\\Common\\Collections\\": "lib/Doctrine/Common/Collections" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + } + ], + "description": "PHP Doctrine Collections library that adds additional functionality on top of PHP arrays.", + "homepage": "https://www.doctrine-project.org/projects/collections.html", + "keywords": [ + "array", + "collections", + "iterators", + "php" + ], + "time": "2020-07-27T17:53:49+00:00" + }, + { + "name": "imagine/imagine", + "version": "v0.7.1", + "source": { + "type": "git", + "url": "https://github.com/avalanche123/Imagine.git", + "reference": "a9a702a946073cbca166718f1b02a1e72d742daa" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/avalanche123/Imagine/zipball/a9a702a946073cbca166718f1b02a1e72d742daa", + "reference": "a9a702a946073cbca166718f1b02a1e72d742daa", + "shasum": "" + }, + "require": { + "php": ">=5.3.2" + }, + "require-dev": { + "sami/sami": "^3.3", + "symfony/phpunit-bridge": "^3.2" + }, + "suggest": { + "ext-gd": "to use the GD implementation", + "ext-gmagick": "to use the Gmagick implementation", + "ext-imagick": "to use the Imagick implementation" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-develop": "0.7-dev" + } + }, + "autoload": { + "psr-0": { + "Imagine": "lib/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Bulat Shakirzyanov", + "email": "mallluhuct@gmail.com", + "homepage": "http://avalanche123.com" + } + ], + "description": "Image processing for PHP 5.3", + "homepage": "http://imagine.readthedocs.org/", + "keywords": [ + "drawing", + "graphics", + "image manipulation", + "image processing" + ], + "time": "2017-05-16T10:31:22+00:00" + }, + { + "name": "ircmaxell/password-compat", + "version": "v1.0.4", + "source": { + "type": "git", + "url": "https://github.com/ircmaxell/password_compat.git", + "reference": "5c5cde8822a69545767f7c7f3058cb15ff84614c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ircmaxell/password_compat/zipball/5c5cde8822a69545767f7c7f3058cb15ff84614c", + "reference": "5c5cde8822a69545767f7c7f3058cb15ff84614c", + "shasum": "" + }, + "require-dev": { + "phpunit/phpunit": "4.*" + }, + "type": "library", + "autoload": { + "files": [ + "lib/password.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Anthony Ferrara", + "email": "ircmaxell@php.net", + "homepage": "http://blog.ircmaxell.com" + } + ], + "description": "A compatibility library for the proposed simplified password hashing algorithm: https://wiki.php.net/rfc/password_hash", + "homepage": "https://github.com/ircmaxell/password_compat", + "keywords": [ + "hashing", + "password" + ], + "time": "2014-11-20T16:49:30+00:00" + }, + { + "name": "kriswallsmith/assetic", + "version": "v1.3.2", + "source": { + "type": "git", + "url": "https://github.com/kriswallsmith/assetic.git", + "reference": "9928f7c4ad98b234e3559d1049abd13387f86db5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/kriswallsmith/assetic/zipball/9928f7c4ad98b234e3559d1049abd13387f86db5", + "reference": "9928f7c4ad98b234e3559d1049abd13387f86db5", + "shasum": "" + }, + "require": { + "php": ">=5.3.1", + "symfony/process": "~2.1|~3.0" + }, + "conflict": { + "twig/twig": "<1.23" + }, + "require-dev": { + "cssmin/cssmin": "3.0.1", + "joliclic/javascript-packer": "1.1", + "kamicane/packager": "1.0", + "leafo/lessphp": "^0.3.7", + "leafo/scssphp": "~0.1", + "mrclay/minify": "~2.2", + "patchwork/jsqueeze": "~1.0|~2.0", + "phpunit/phpunit": "~4.8", + "psr/log": "~1.0", + "ptachoire/cssembed": "~1.0", + "symfony/phpunit-bridge": "~2.7|~3.0", + "twig/twig": "~1.8|~2.0" + }, + "suggest": { + "leafo/lessphp": "Assetic provides the integration with the lessphp LESS compiler", + "leafo/scssphp": "Assetic provides the integration with the scssphp SCSS compiler", + "leafo/scssphp-compass": "Assetic provides the integration with the SCSS compass plugin", + "patchwork/jsqueeze": "Assetic provides the integration with the JSqueeze JavaScript compressor", + "ptachoire/cssembed": "Assetic provides the integration with phpcssembed to embed data uris", + "twig/twig": "Assetic provides the integration with the Twig templating engine" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.4-dev" + } + }, + "autoload": { + "psr-0": { + "Assetic": "src/" + }, + "files": [ + "src/functions.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Kris Wallsmith", + "email": "kris.wallsmith@gmail.com", + "homepage": "http://kriswallsmith.net/" + } + ], + "description": "Asset Management for PHP", + "homepage": "https://github.com/kriswallsmith/assetic", + "keywords": [ + "assets", + "compression", + "minification" + ], + "time": "2015-11-12T13:51:40+00:00" + }, + { + "name": "michelf/php-markdown", + "version": "1.6.0", + "source": { + "type": "git", + "url": "https://github.com/michelf/php-markdown.git", + "reference": "156e56ee036505ec637d761ee62dc425d807183c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/michelf/php-markdown/zipball/156e56ee036505ec637d761ee62dc425d807183c", + "reference": "156e56ee036505ec637d761ee62dc425d807183c", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-lib": "1.4.x-dev" + } + }, + "autoload": { + "psr-0": { + "Michelf": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Michel Fortin", + "email": "michel.fortin@michelf.ca", + "homepage": "https://michelf.ca/", + "role": "Developer" + }, + { + "name": "John Gruber", + "homepage": "https://daringfireball.net/" + } + ], + "description": "PHP Markdown", + "homepage": "https://michelf.ca/projects/php-markdown/", + "keywords": [ + "markdown" + ], + "time": "2015-12-24T01:37:31+00:00" + }, + { + "name": "oyejorge/less.php", + "version": "v1.7.0.14", + "source": { + "type": "git", + "url": "https://github.com/oyejorge/less.php.git", + "reference": "42925c5a01a07d67ca7e82dfc8fb31814d557bc9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/oyejorge/less.php/zipball/42925c5a01a07d67ca7e82dfc8fb31814d557bc9", + "reference": "42925c5a01a07d67ca7e82dfc8fb31814d557bc9", + "shasum": "" + }, + "require": { + "php": ">=5.3" + }, + "require-dev": { + "phpunit/phpunit": "~4.8.24" + }, + "bin": [ + "bin/lessc" + ], + "type": "library", + "autoload": { + "psr-0": { + "Less": "lib/" + }, + "classmap": [ + "lessc.inc.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache-2.0" + ], + "authors": [ + { + "name": "Matt Agar", + "homepage": "https://github.com/agar" + }, + { + "name": "Martin Jantošovič", + "homepage": "https://github.com/Mordred" + }, + { + "name": "Josh Schmidt", + "homepage": "https://github.com/oyejorge" + } + ], + "description": "PHP port of the Javascript version of LESS http://lesscss.org (Originally maintained by Josh Schmidt)", + "homepage": "http://lessphp.gpeasy.com", + "keywords": [ + "css", + "less", + "less.js", + "lesscss", + "php", + "stylesheet" + ], + "abandoned": true, + "time": "2017-03-28T22:19:25+00:00" + }, + { + "name": "psr/cache", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/php-fig/cache.git", + "reference": "d11b50ad223250cf17b86e38383413f5a6764bf8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/cache/zipball/d11b50ad223250cf17b86e38383413f5a6764bf8", + "reference": "d11b50ad223250cf17b86e38383413f5a6764bf8", + "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": "2016-08-06T20:24:11+00:00" + }, + { + "name": "psr/log", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/log.git", + "reference": "fe0936ee26643249e916849d48e3a51d5f5e278b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/log/zipball/fe0936ee26643249e916849d48e3a51d5f5e278b", + "reference": "fe0936ee26643249e916849d48e3a51d5f5e278b", + "shasum": "" + }, + "type": "library", + "autoload": { + "psr-0": { + "Psr\\Log\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interface for logging libraries", + "keywords": [ + "log", + "psr", + "psr-3" + ], + "time": "2012-12-21T11:40:51+00:00" + }, + { + "name": "psr/simple-cache", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/php-fig/simple-cache.git", + "reference": "408d5eafb83c57f6365a3ca330ff23aa4a5fa39b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/simple-cache/zipball/408d5eafb83c57f6365a3ca330ff23aa4a5fa39b", + "reference": "408d5eafb83c57f6365a3ca330ff23aa4a5fa39b", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\SimpleCache\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interfaces for simple caching", + "keywords": [ + "cache", + "caching", + "psr", + "psr-16", + "simple-cache" + ], + "time": "2017-10-23T01:57:42+00:00" + }, + { + "name": "ptachoire/cssembed", + "version": "v1.0.2", + "source": { + "type": "git", + "url": "https://github.com/krichprollsch/phpCssEmbed.git", + "reference": "406c6d5b846cafa9186f9944a6210d0e6fed154b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/krichprollsch/phpCssEmbed/zipball/406c6d5b846cafa9186f9944a6210d0e6fed154b", + "reference": "406c6d5b846cafa9186f9944a6210d0e6fed154b", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "type": "library", + "autoload": { + "psr-0": { + "CssEmbed": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Pierre Tachoire", + "email": "pierre.tachoire@gmail.com" + } + ], + "description": "Css url embed library.", + "homepage": "https://github.com/krichprollsch/phpCssEmbed", + "keywords": [ + "css", + "url" + ], + "time": "2013-07-22T20:01:48+00:00" + }, + { + "name": "simplepie/simplepie", + "version": "1.3.1", + "source": { + "type": "git", + "url": "https://github.com/simplepie/simplepie.git", + "reference": "ce53709778bc1e2e4deda1651b66e5081398d5cc" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/simplepie/simplepie/zipball/ce53709778bc1e2e4deda1651b66e5081398d5cc", + "reference": "ce53709778bc1e2e4deda1651b66e5081398d5cc", + "shasum": "" + }, + "require": { + "php": ">=5.2.0" + }, + "type": "library", + "autoload": { + "psr-0": { + "SimplePie": "library" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Ryan Parman", + "homepage": "http://ryanparman.com/", + "role": "Creator, alumnus developer" + }, + { + "name": "Geoffrey Sneddon", + "homepage": "http://gsnedders.com/", + "role": "Alumnus developer" + }, + { + "name": "Ryan McCue", + "email": "me@ryanmccue.info", + "homepage": "http://ryanmccue.info/", + "role": "Developer" + } + ], + "description": "A simple Atom/RSS parsing library for PHP", + "homepage": "http://simplepie.org/", + "keywords": [ + "atom", + "feeds", + "rss" + ], + "time": "2012-10-30T17:54:03+00:00" + }, + { + "name": "smarty/smarty", + "version": "v3.1.33", + "source": { + "type": "git", + "url": "https://github.com/smarty-php/smarty.git", + "reference": "dd55b23121e55a3b4f1af90a707a6c4e5969530f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/smarty-php/smarty/zipball/dd55b23121e55a3b4f1af90a707a6c4e5969530f", + "reference": "dd55b23121e55a3b4f1af90a707a6c4e5969530f", + "shasum": "" + }, + "require": { + "php": ">=5.2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.1.x-dev" + } + }, + "autoload": { + "files": [ + "libs/bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "LGPL-3.0" + ], + "authors": [ + { + "name": "Monte Ohrt", + "email": "monte@ohrt.com" + }, + { + "name": "Uwe Tews", + "email": "uwe.tews@googlemail.com" + }, + { + "name": "Rodney Rehm", + "email": "rodney.rehm@medialize.de" + } + ], + "description": "Smarty - the compiling PHP template engine", + "homepage": "http://www.smarty.net", + "keywords": [ + "templating" + ], + "time": "2018-09-12T20:54:16+00:00" + }, + { + "name": "spipu/html2pdf", + "version": "v5.2.2", + "source": { + "type": "git", + "url": "https://github.com/spipu/html2pdf.git", + "reference": "e6d8ca22347b6691bb8c2652212b1be2c89b3eff" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/spipu/html2pdf/zipball/e6d8ca22347b6691bb8c2652212b1be2c89b3eff", + "reference": "e6d8ca22347b6691bb8c2652212b1be2c89b3eff", + "shasum": "" + }, + "require": { + "ext-gd": "*", + "ext-mbstring": "*", + "php": "^5.6 || ^7.0", + "tecnickcom/tcpdf": "^6.2" + }, + "require-dev": { + "phake/phake": "^2.0", + "phpunit/phpunit": "^5.0" + }, + "suggest": { + "ext-gd": "Allows to embed images into the PDF", + "fagundes/zff-html2pdf": "if you need to integrate Html2Pdf with Zend Framework 2 (zf2)" + }, + "type": "library", + "autoload": { + "psr-4": { + "Spipu\\Html2Pdf\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "OSL-3.0" + ], + "authors": [ + { + "name": "Spipu", + "homepage": "https://github.com/spipu", + "role": "Developer" + } + ], + "description": "Html2Pdf is a HTML to PDF converter written in PHP5 (it uses TCPDF). OFFICIAL PACKAGE", + "homepage": "http://html2pdf.fr/", + "keywords": [ + "html", + "html2pdf", + "pdf" + ], + "time": "2020-03-22T16:23:26+00:00" + }, + { + "name": "stack/builder", + "version": "v1.0.6", + "source": { + "type": "git", + "url": "https://github.com/stackphp/builder.git", + "reference": "a4faaa6f532c6086bc66c29e1bc6c29593e1ca7c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/stackphp/builder/zipball/a4faaa6f532c6086bc66c29e1bc6c29593e1ca7c", + "reference": "a4faaa6f532c6086bc66c29e1bc6c29593e1ca7c", + "shasum": "" + }, + "require": { + "php": ">=7.2.0", + "symfony/http-foundation": "~2.1|~3.0|~4.0|~5.0", + "symfony/http-kernel": "~2.1|~3.0|~4.0|~5.0" + }, + "require-dev": { + "phpunit/phpunit": "~8.0", + "symfony/routing": "^5.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "psr-0": { + "Stack": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Igor Wiedler", + "email": "igor@wiedler.ch" + } + ], + "description": "Builder for stack middleware based on HttpKernelInterface.", + "keywords": [ + "stack" + ], + "time": "2020-01-30T12:17:27+00:00" + }, + { + "name": "swiftmailer/swiftmailer", + "version": "v5.4.12", + "source": { + "type": "git", + "url": "https://github.com/swiftmailer/swiftmailer.git", + "reference": "181b89f18a90f8925ef805f950d47a7190e9b950" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/swiftmailer/swiftmailer/zipball/181b89f18a90f8925ef805f950d47a7190e9b950", + "reference": "181b89f18a90f8925ef805f950d47a7190e9b950", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "mockery/mockery": "~0.9.1", + "symfony/phpunit-bridge": "~3.2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.4-dev" + } + }, + "autoload": { + "files": [ + "lib/swift_required.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Chris Corbyn" + }, + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + } + ], + "description": "Swiftmailer, free feature-rich PHP mailer", + "homepage": "https://swiftmailer.symfony.com", + "keywords": [ + "email", + "mail", + "mailer" + ], + "time": "2018-07-31T09:26:32+00:00" + }, + { + "name": "symfony-cmf/routing", + "version": "1.3.0", + "source": { + "type": "git", + "url": "https://github.com/symfony-cmf/Routing.git", + "reference": "8e87981d72c6930a27585dcd3119f3199f6cb2a6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony-cmf/Routing/zipball/8e87981d72c6930a27585dcd3119f3199f6cb2a6", + "reference": "8e87981d72c6930a27585dcd3119f3199f6cb2a6", + "shasum": "" + }, + "require": { + "php": ">=5.3.3", + "psr/log": "~1.0", + "symfony/http-kernel": "~2.2", + "symfony/routing": "~2.2" + }, + "require-dev": { + "symfony/config": "~2.2", + "symfony/dependency-injection": "~2.0@stable", + "symfony/event-dispatcher": "~2.1" + }, + "suggest": { + "symfony/event-dispatcher": "DynamicRouter can optionally trigger an event at the start of matching. Minimal version ~2.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.3-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Cmf\\Component\\Routing\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Symfony CMF Community", + "homepage": "https://github.com/symfony-cmf/Routing/contributors" + } + ], + "description": "Extends the Symfony2 routing component for dynamic routes and chaining several routers", + "homepage": "http://cmf.symfony.com", + "keywords": [ + "database", + "routing" + ], + "time": "2014-10-20T20:55:17+00:00" + }, + { + "name": "symfony/browser-kit", + "version": "v2.8.52", + "source": { + "type": "git", + "url": "https://github.com/symfony/browser-kit.git", + "reference": "b507697225f32a76a9d333d0766fb46353e9d00d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/browser-kit/zipball/b507697225f32a76a9d333d0766fb46353e9d00d", + "reference": "b507697225f32a76a9d333d0766fb46353e9d00d", + "shasum": "" + }, + "require": { + "php": ">=5.3.9", + "symfony/dom-crawler": "~2.1|~3.0.0" + }, + "require-dev": { + "symfony/css-selector": "^2.0.5|~3.0.0", + "symfony/process": "~2.3.34|^2.7.6|~3.0.0" + }, + "suggest": { + "symfony/process": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.8-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\BrowserKit\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony BrowserKit Component", + "homepage": "https://symfony.com", + "time": "2018-11-26T06:55:10+00:00" + }, + { + "name": "symfony/cache", + "version": "v4.1.12", + "source": { + "type": "git", + "url": "https://github.com/symfony/cache.git", + "reference": "399ddbf0ff98f42593827141b5fcd95d51c36b28" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/cache/zipball/399ddbf0ff98f42593827141b5fcd95d51c36b28", + "reference": "399ddbf0ff98f42593827141b5fcd95d51c36b28", + "shasum": "" + }, + "require": { + "php": "^7.1.3", + "psr/cache": "~1.0", + "psr/log": "~1.0", + "psr/simple-cache": "^1.0" + }, + "conflict": { + "symfony/var-dumper": "<3.4" + }, + "provide": { + "psr/cache-implementation": "1.0", + "psr/simple-cache-implementation": "1.0" + }, + "require-dev": { + "cache/integration-tests": "dev-master", + "doctrine/cache": "~1.6", + "doctrine/dbal": "~2.4", + "predis/predis": "~1.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.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 Cache component with PSR-6, PSR-16, and tags", + "homepage": "https://symfony.com", + "keywords": [ + "caching", + "psr6" + ], + "time": "2019-04-16T09:37:00+00:00" + }, + { + "name": "symfony/class-loader", + "version": "v2.8.52", + "source": { + "type": "git", + "url": "https://github.com/symfony/class-loader.git", + "reference": "8194721a1e2768cfb95079581889c41eec7a5959" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/class-loader/zipball/8194721a1e2768cfb95079581889c41eec7a5959", + "reference": "8194721a1e2768cfb95079581889c41eec7a5959", + "shasum": "" + }, + "require": { + "php": ">=5.3.9", + "symfony/polyfill-apcu": "~1.1" + }, + "require-dev": { + "symfony/finder": "^2.0.5|~3.0.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.8-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\ClassLoader\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony ClassLoader Component", + "homepage": "https://symfony.com", + "time": "2018-11-11T11:18:13+00:00" + }, + { + "name": "symfony/config", + "version": "v2.8.52", + "source": { + "type": "git", + "url": "https://github.com/symfony/config.git", + "reference": "7dd5f5040dc04c118d057fb5886563963eb70011" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/config/zipball/7dd5f5040dc04c118d057fb5886563963eb70011", + "reference": "7dd5f5040dc04c118d057fb5886563963eb70011", + "shasum": "" + }, + "require": { + "php": ">=5.3.9", + "symfony/filesystem": "~2.3|~3.0.0", + "symfony/polyfill-ctype": "~1.8" + }, + "require-dev": { + "symfony/yaml": "~2.7|~3.0.0" + }, + "suggest": { + "symfony/yaml": "To use the yaml reference dumper" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.8-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Config\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Config Component", + "homepage": "https://symfony.com", + "time": "2018-11-26T09:38:12+00:00" + }, + { + "name": "symfony/console", + "version": "v2.8.52", + "source": { + "type": "git", + "url": "https://github.com/symfony/console.git", + "reference": "cbcf4b5e233af15cd2bbd50dee1ccc9b7927dc12" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/console/zipball/cbcf4b5e233af15cd2bbd50dee1ccc9b7927dc12", + "reference": "cbcf4b5e233af15cd2bbd50dee1ccc9b7927dc12", + "shasum": "" + }, + "require": { + "php": ">=5.3.9", + "symfony/debug": "^2.7.2|~3.0.0", + "symfony/polyfill-mbstring": "~1.0" + }, + "require-dev": { + "psr/log": "~1.0", + "symfony/event-dispatcher": "~2.1|~3.0.0", + "symfony/process": "~2.1|~3.0.0" + }, + "suggest": { + "psr/log-implementation": "For using the console logger", + "symfony/event-dispatcher": "", + "symfony/process": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.8-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Console\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Console Component", + "homepage": "https://symfony.com", + "time": "2018-11-20T15:55:20+00:00" + }, + { + "name": "symfony/debug", + "version": "v2.8.52", + "source": { + "type": "git", + "url": "https://github.com/symfony/debug.git", + "reference": "74251c8d50dd3be7c4ce0c7b862497cdc641a5d0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/debug/zipball/74251c8d50dd3be7c4ce0c7b862497cdc641a5d0", + "reference": "74251c8d50dd3be7c4ce0c7b862497cdc641a5d0", + "shasum": "" + }, + "require": { + "php": ">=5.3.9", + "psr/log": "~1.0" + }, + "conflict": { + "symfony/http-kernel": ">=2.3,<2.3.24|~2.4.0|>=2.5,<2.5.9|>=2.6,<2.6.2" + }, + "require-dev": { + "symfony/class-loader": "~2.2|~3.0.0", + "symfony/http-kernel": "~2.3.24|~2.5.9|^2.6.2|~3.0.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.8-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Debug\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Debug Component", + "homepage": "https://symfony.com", + "time": "2018-11-11T11:18:13+00:00" + }, + { + "name": "symfony/dependency-injection", + "version": "v2.8.52", + "source": { + "type": "git", + "url": "https://github.com/symfony/dependency-injection.git", + "reference": "c306198fee8f872a8f5f031e6e4f6f83086992d8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/c306198fee8f872a8f5f031e6e4f6f83086992d8", + "reference": "c306198fee8f872a8f5f031e6e4f6f83086992d8", + "shasum": "" + }, + "require": { + "php": ">=5.3.9" + }, + "conflict": { + "symfony/expression-language": "<2.6" + }, + "require-dev": { + "symfony/config": "~2.2|~3.0.0", + "symfony/expression-language": "~2.6|~3.0.0", + "symfony/yaml": "~2.3.42|~2.7.14|~2.8.7|~3.0.7" + }, + "suggest": { + "symfony/config": "", + "symfony/expression-language": "For using expressions in service container configuration", + "symfony/proxy-manager-bridge": "Generate service proxies to lazy load them", + "symfony/yaml": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.8-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\DependencyInjection\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony DependencyInjection Component", + "homepage": "https://symfony.com", + "time": "2019-04-16T11:33:46+00:00" + }, + { + "name": "symfony/dom-crawler", + "version": "v2.8.52", + "source": { + "type": "git", + "url": "https://github.com/symfony/dom-crawler.git", + "reference": "2cdc7d3909eea6f982a6298d2e9ab7db01b6403c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/dom-crawler/zipball/2cdc7d3909eea6f982a6298d2e9ab7db01b6403c", + "reference": "2cdc7d3909eea6f982a6298d2e9ab7db01b6403c", + "shasum": "" + }, + "require": { + "php": ">=5.3.9", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-mbstring": "~1.0" + }, + "require-dev": { + "symfony/css-selector": "~2.8|~3.0.0" + }, + "suggest": { + "symfony/css-selector": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.8-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\DomCrawler\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony DomCrawler Component", + "homepage": "https://symfony.com", + "time": "2018-11-24T22:30:19+00:00" + }, + { + "name": "symfony/dotenv", + "version": "v4.4.18", + "source": { + "type": "git", + "url": "https://github.com/symfony/dotenv.git", + "reference": "2befc49ec50b4d6ffd100b332389260c9069ba1c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/dotenv/zipball/2befc49ec50b4d6ffd100b332389260c9069ba1c", + "reference": "2befc49ec50b4d6ffd100b332389260c9069ba1c", + "shasum": "" + }, + "require": { + "php": ">=7.1.3" + }, + "require-dev": { + "symfony/process": "^3.4.2|^4.0|^5.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Dotenv\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Registers environment variables from a .env file", + "homepage": "https://symfony.com", + "keywords": [ + "dotenv", + "env", + "environment" + ], + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2020-12-08T16:59:59+00:00" + }, + { + "name": "symfony/event-dispatcher", + "version": "v2.8.52", + "source": { + "type": "git", + "url": "https://github.com/symfony/event-dispatcher.git", + "reference": "a77e974a5fecb4398833b0709210e3d5e334ffb0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/a77e974a5fecb4398833b0709210e3d5e334ffb0", + "reference": "a77e974a5fecb4398833b0709210e3d5e334ffb0", + "shasum": "" + }, + "require": { + "php": ">=5.3.9" + }, + "require-dev": { + "psr/log": "~1.0", + "symfony/config": "^2.0.5|~3.0.0", + "symfony/dependency-injection": "~2.6|~3.0.0", + "symfony/expression-language": "~2.6|~3.0.0", + "symfony/stopwatch": "~2.3|~3.0.0" + }, + "suggest": { + "symfony/dependency-injection": "", + "symfony/http-kernel": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.8-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\EventDispatcher\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony EventDispatcher Component", + "homepage": "https://symfony.com", + "time": "2018-11-21T14:20:20+00:00" + }, + { + "name": "symfony/expression-language", + "version": "v2.8.52", + "source": { + "type": "git", + "url": "https://github.com/symfony/expression-language.git", + "reference": "fa9be1b831859b56d244137fabbfd01a46dbdb36" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/expression-language/zipball/fa9be1b831859b56d244137fabbfd01a46dbdb36", + "reference": "fa9be1b831859b56d244137fabbfd01a46dbdb36", + "shasum": "" + }, + "require": { + "php": ">=5.3.9" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.8-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\ExpressionLanguage\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony ExpressionLanguage Component", + "homepage": "https://symfony.com", + "time": "2018-11-11T11:18:13+00:00" + }, + { + "name": "symfony/filesystem", + "version": "v2.8.52", + "source": { + "type": "git", + "url": "https://github.com/symfony/filesystem.git", + "reference": "7ae46872dad09dffb7fe1e93a0937097339d0080" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/7ae46872dad09dffb7fe1e93a0937097339d0080", + "reference": "7ae46872dad09dffb7fe1e93a0937097339d0080", + "shasum": "" + }, + "require": { + "php": ">=5.3.9", + "symfony/polyfill-ctype": "~1.8" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.8-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Filesystem\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Filesystem Component", + "homepage": "https://symfony.com", + "time": "2018-11-11T11:18:13+00:00" + }, + { + "name": "symfony/finder", + "version": "v2.8.52", + "source": { + "type": "git", + "url": "https://github.com/symfony/finder.git", + "reference": "1444eac52273e345d9b95129bf914639305a9ba4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/finder/zipball/1444eac52273e345d9b95129bf914639305a9ba4", + "reference": "1444eac52273e345d9b95129bf914639305a9ba4", + "shasum": "" + }, + "require": { + "php": ">=5.3.9" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.8-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Finder\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Finder Component", + "homepage": "https://symfony.com", + "time": "2018-11-11T11:18:13+00:00" + }, + { + "name": "symfony/form", + "version": "v2.8.52", + "source": { + "type": "git", + "url": "https://github.com/symfony/form.git", + "reference": "74382a47aa97496d181fbb598822fdfb9e1744e4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/form/zipball/74382a47aa97496d181fbb598822fdfb9e1744e4", + "reference": "74382a47aa97496d181fbb598822fdfb9e1744e4", + "shasum": "" + }, + "require": { + "php": ">=5.3.9", + "symfony/event-dispatcher": "~2.1|~3.0.0", + "symfony/intl": "~2.7.25|^2.8.18|~3.2.5", + "symfony/options-resolver": "~2.6", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-mbstring": "~1.0", + "symfony/property-access": "~2.3|~3.0.0" + }, + "conflict": { + "phpunit/phpunit": "<4.8.35|<5.4.3,>=5.0", + "symfony/doctrine-bridge": "<2.7", + "symfony/framework-bundle": "<2.7", + "symfony/twig-bridge": "<2.7" + }, + "require-dev": { + "doctrine/collections": "~1.0", + "symfony/dependency-injection": "~2.7|~3.0.0", + "symfony/http-foundation": "~2.2|~3.0.0", + "symfony/http-kernel": "~2.4|~3.0.0", + "symfony/security-csrf": "^2.8.31|^3.3.13", + "symfony/translation": "^2.0.5|~3.0.0", + "symfony/validator": "^2.8.18|~3.2.5" + }, + "suggest": { + "symfony/framework-bundle": "For templating with PHP.", + "symfony/security-csrf": "For protecting forms against CSRF attacks.", + "symfony/twig-bridge": "For templating with Twig.", + "symfony/validator": "For form validation." + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.8-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Form\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Form Component", + "homepage": "https://symfony.com", + "time": "2018-12-06T11:12:46+00:00" + }, + { + "name": "symfony/http-foundation", + "version": "v2.8.52", + "source": { + "type": "git", + "url": "https://github.com/symfony/http-foundation.git", + "reference": "3929d9fe8148d17819ad0178c748b8d339420709" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/3929d9fe8148d17819ad0178c748b8d339420709", + "reference": "3929d9fe8148d17819ad0178c748b8d339420709", + "shasum": "" + }, + "require": { + "php": ">=5.3.9", + "symfony/polyfill-mbstring": "~1.1", + "symfony/polyfill-php54": "~1.0", + "symfony/polyfill-php55": "~1.0" + }, + "require-dev": { + "symfony/expression-language": "~2.4|~3.0.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.8-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\HttpFoundation\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony HttpFoundation Component", + "homepage": "https://symfony.com", + "time": "2019-11-12T12:34:41+00:00" + }, + { + "name": "symfony/http-kernel", + "version": "v2.8.52", + "source": { + "type": "git", + "url": "https://github.com/symfony/http-kernel.git", + "reference": "c3be27b8627cd5ee8dfa8d1b923982f618ec521c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/http-kernel/zipball/c3be27b8627cd5ee8dfa8d1b923982f618ec521c", + "reference": "c3be27b8627cd5ee8dfa8d1b923982f618ec521c", + "shasum": "" + }, + "require": { + "php": ">=5.3.9", + "psr/log": "~1.0", + "symfony/debug": "^2.6.2", + "symfony/event-dispatcher": "^2.6.7|~3.0.0", + "symfony/http-foundation": "~2.7.36|~2.8.29|~3.1.6", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-php56": "~1.8" + }, + "conflict": { + "symfony/config": "<2.7", + "twig/twig": "<1.34|<2.4,>=2" + }, + "require-dev": { + "symfony/browser-kit": "~2.3|~3.0.0", + "symfony/class-loader": "~2.1|~3.0.0", + "symfony/config": "~2.8", + "symfony/console": "~2.3|~3.0.0", + "symfony/css-selector": "^2.0.5|~3.0.0", + "symfony/dependency-injection": "~2.8|~3.0.0", + "symfony/dom-crawler": "^2.0.5|~3.0.0", + "symfony/expression-language": "~2.4|~3.0.0", + "symfony/finder": "^2.0.5|~3.0.0", + "symfony/process": "^2.0.5|~3.0.0", + "symfony/routing": "~2.8|~3.0.0", + "symfony/stopwatch": "~2.3|~3.0.0", + "symfony/templating": "~2.2|~3.0.0", + "symfony/translation": "^2.0.5|~3.0.0", + "symfony/var-dumper": "~2.6|~3.0.0" + }, + "suggest": { + "symfony/browser-kit": "", + "symfony/class-loader": "", + "symfony/config": "", + "symfony/console": "", + "symfony/dependency-injection": "", + "symfony/finder": "", + "symfony/var-dumper": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.8-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\HttpKernel\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony HttpKernel Component", + "homepage": "https://symfony.com", + "time": "2019-11-13T08:36:16+00:00" + }, + { + "name": "symfony/intl", + "version": "v3.2.14", + "source": { + "type": "git", + "url": "https://github.com/symfony/intl.git", + "reference": "3fd98dde8e7d1c34c974d65b09e9c32abe88dafe" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/intl/zipball/3fd98dde8e7d1c34c974d65b09e9c32abe88dafe", + "reference": "3fd98dde8e7d1c34c974d65b09e9c32abe88dafe", + "shasum": "" + }, + "require": { + "php": ">=5.5.9", + "symfony/polyfill-intl-icu": "~1.0" + }, + "require-dev": { + "symfony/filesystem": "~2.8|~3.0" + }, + "suggest": { + "ext-intl": "to use the component with locales other than \"en\"" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.2-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Intl\\": "" + }, + "classmap": [ + "Resources/stubs" + ], + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" + }, + { + "name": "Eriksen Costa", + "email": "eriksen.costa@infranology.com.br" + }, + { + "name": "Igor Wiedler", + "email": "igor@wiedler.ch" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "A PHP replacement layer for the C intl extension that includes additional data from the ICU library.", + "homepage": "https://symfony.com", + "keywords": [ + "i18n", + "icu", + "internationalization", + "intl", + "l10n", + "localization" + ], + "time": "2017-11-16T17:55:54+00:00" + }, + { + "name": "symfony/lock", + "version": "v4.4.18", + "source": { + "type": "git", + "url": "https://github.com/symfony/lock.git", + "reference": "8017f2ecc7de4b6cc1585d502e65ea4f56d42051" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/lock/zipball/8017f2ecc7de4b6cc1585d502e65ea4f56d42051", + "reference": "8017f2ecc7de4b6cc1585d502e65ea4f56d42051", + "shasum": "" + }, + "require": { + "php": ">=7.1.3", + "psr/log": "~1.0" + }, + "conflict": { + "doctrine/dbal": "<2.5" + }, + "require-dev": { + "doctrine/dbal": "^2.5|^3.0", + "predis/predis": "~1.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Lock\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jérémy Derussé", + "email": "jeremy@derusse.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Lock Component", + "homepage": "https://symfony.com", + "keywords": [ + "cas", + "flock", + "locking", + "mutex", + "redlock", + "semaphore" + ], + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2020-12-14T10:21:37+00:00" + }, + { + "name": "symfony/options-resolver", + "version": "v2.8.52", + "source": { + "type": "git", + "url": "https://github.com/symfony/options-resolver.git", + "reference": "7aaab725bb58f0e18aa12c61bdadd4793ab4c32b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/options-resolver/zipball/7aaab725bb58f0e18aa12c61bdadd4793ab4c32b", + "reference": "7aaab725bb58f0e18aa12c61bdadd4793ab4c32b", + "shasum": "" + }, + "require": { + "php": ">=5.3.9" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.8-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\OptionsResolver\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony OptionsResolver Component", + "homepage": "https://symfony.com", + "keywords": [ + "config", + "configuration", + "options" + ], + "time": "2018-11-11T11:18:13+00:00" + }, + { + "name": "symfony/polyfill-apcu", + "version": "v1.22.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-apcu.git", + "reference": "3b3944f40987b9d3f9b9147f86c32df87d9f3505" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-apcu/zipball/3b3944f40987b9d3f9b9147f86c32df87d9f3505", + "reference": "3b3944f40987b9d3f9b9147f86c32df87d9f3505", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.22-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Apcu\\": "" + }, + "files": [ + "bootstrap.php" + ] + }, + "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 polyfill backporting apcu_* functions to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "apcu", + "compatibility", + "polyfill", + "portable", + "shim" + ], + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2021-01-07T16:49:33+00:00" + }, + { + "name": "symfony/polyfill-ctype", + "version": "v1.22.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-ctype.git", + "reference": "c6c942b1ac76c82448322025e084cadc56048b4e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/c6c942b1ac76c82448322025e084cadc56048b4e", + "reference": "c6c942b1ac76c82448322025e084cadc56048b4e", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "suggest": { + "ext-ctype": "For best performance" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.22-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Ctype\\": "" + }, + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Gert de Pagter", + "email": "BackEndTea@gmail.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for ctype functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "ctype", + "polyfill", + "portable" + ], + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2021-01-07T16:49:33+00:00" + }, + { + "name": "symfony/polyfill-intl-icu", + "version": "v1.22.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-intl-icu.git", + "reference": "b2b1e732a6c039f1a3ea3414b3379a2433e183d6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-intl-icu/zipball/b2b1e732a6c039f1a3ea3414b3379a2433e183d6", + "reference": "b2b1e732a6c039f1a3ea3414b3379a2433e183d6", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "suggest": { + "ext-intl": "For best performance and support of other locales than \"en\"" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.22-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Intl\\Icu\\": "" + }, + "classmap": [ + "Resources/stubs" + ], + "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 polyfill for intl's ICU-related data and classes", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "icu", + "intl", + "polyfill", + "portable", + "shim" + ], + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2021-01-07T16:49:33+00:00" + }, + { + "name": "symfony/polyfill-mbstring", + "version": "v1.22.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-mbstring.git", + "reference": "f377a3dd1fde44d37b9831d68dc8dea3ffd28e13" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/f377a3dd1fde44d37b9831d68dc8dea3ffd28e13", + "reference": "f377a3dd1fde44d37b9831d68dc8dea3ffd28e13", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "suggest": { + "ext-mbstring": "For best performance" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.22-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Mbstring\\": "" + }, + "files": [ + "bootstrap.php" + ] + }, + "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 polyfill for the Mbstring extension", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "mbstring", + "polyfill", + "portable", + "shim" + ], + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2021-01-07T16:49:33+00:00" + }, + { + "name": "symfony/polyfill-php54", + "version": "v1.20.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php54.git", + "reference": "37285b1d5d13f37c8bee546d8d2ad0353460c4c7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php54/zipball/37285b1d5d13f37c8bee546d8d2ad0353460c4c7", + "reference": "37285b1d5d13f37c8bee546d8d2ad0353460c4c7", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "type": "metapackage", + "extra": { + "branch-alias": { + "dev-main": "1.20-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "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 polyfill backporting some PHP 5.4+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2020-10-23T14:02:19+00:00" + }, + { + "name": "symfony/polyfill-php55", + "version": "v1.20.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php55.git", + "reference": "c17452124a883900e1d73961f9075a638399c1a0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php55/zipball/c17452124a883900e1d73961f9075a638399c1a0", + "reference": "c17452124a883900e1d73961f9075a638399c1a0", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "type": "metapackage", + "extra": { + "branch-alias": { + "dev-main": "1.20-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "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 polyfill backporting some PHP 5.5+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2020-10-23T14:02:19+00:00" + }, + { + "name": "symfony/polyfill-php56", + "version": "v1.20.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php56.git", + "reference": "54b8cd7e6c1643d78d011f3be89f3ef1f9f4c675" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php56/zipball/54b8cd7e6c1643d78d011f3be89f3ef1f9f4c675", + "reference": "54b8cd7e6c1643d78d011f3be89f3ef1f9f4c675", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "type": "metapackage", + "extra": { + "branch-alias": { + "dev-main": "1.20-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "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 polyfill backporting some PHP 5.6+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2020-10-23T14:02:19+00:00" + }, + { + "name": "symfony/polyfill-php70", + "version": "v1.20.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php70.git", + "reference": "5f03a781d984aae42cebd18e7912fa80f02ee644" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php70/zipball/5f03a781d984aae42cebd18e7912fa80f02ee644", + "reference": "5f03a781d984aae42cebd18e7912fa80f02ee644", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "type": "metapackage", + "extra": { + "branch-alias": { + "dev-main": "1.20-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "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 polyfill backporting some PHP 7.0+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2020-10-23T14:02:19+00:00" + }, + { + "name": "symfony/polyfill-php71", + "version": "v1.20.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php71.git", + "reference": "2d6cdeca7ea470e50db9e544c9ec4b1955036c22" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php71/zipball/2d6cdeca7ea470e50db9e544c9ec4b1955036c22", + "reference": "2d6cdeca7ea470e50db9e544c9ec4b1955036c22", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "type": "metapackage", + "extra": { + "branch-alias": { + "dev-main": "1.20-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "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 polyfill backporting some PHP 7.1+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2020-10-23T14:02:19+00:00" + }, + { + "name": "symfony/polyfill-php72", + "version": "v1.22.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php72.git", + "reference": "cc6e6f9b39fe8075b3dabfbaf5b5f645ae1340c9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/cc6e6f9b39fe8075b3dabfbaf5b5f645ae1340c9", + "reference": "cc6e6f9b39fe8075b3dabfbaf5b5f645ae1340c9", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.22-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Php72\\": "" + }, + "files": [ + "bootstrap.php" + ] + }, + "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 polyfill backporting some PHP 7.2+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2021-01-07T16:49:33+00:00" + }, + { + "name": "symfony/polyfill-php73", + "version": "v1.22.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php73.git", + "reference": "a678b42e92f86eca04b7fa4c0f6f19d097fb69e2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/a678b42e92f86eca04b7fa4c0f6f19d097fb69e2", + "reference": "a678b42e92f86eca04b7fa4c0f6f19d097fb69e2", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.22-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Php73\\": "" + }, + "files": [ + "bootstrap.php" + ], + "classmap": [ + "Resources/stubs" + ] + }, + "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 polyfill backporting some PHP 7.3+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2021-01-07T16:49:33+00:00" + }, + { + "name": "symfony/polyfill-util", + "version": "v1.22.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-util.git", + "reference": "ccda17fe137336f3c2c5321167c4a5e26371171a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-util/zipball/ccda17fe137336f3c2c5321167c4a5e26371171a", + "reference": "ccda17fe137336f3c2c5321167c4a5e26371171a", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.22-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Util\\": "" + } + }, + "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 utilities for portability of PHP codes", + "homepage": "https://symfony.com", + "keywords": [ + "compat", + "compatibility", + "polyfill", + "shim" + ], + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2021-01-07T16:49:33+00:00" + }, + { + "name": "symfony/process", + "version": "v2.8.52", + "source": { + "type": "git", + "url": "https://github.com/symfony/process.git", + "reference": "c3591a09c78639822b0b290d44edb69bf9f05dc8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/process/zipball/c3591a09c78639822b0b290d44edb69bf9f05dc8", + "reference": "c3591a09c78639822b0b290d44edb69bf9f05dc8", + "shasum": "" + }, + "require": { + "php": ">=5.3.9" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.8-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Process\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Process Component", + "homepage": "https://symfony.com", + "time": "2018-11-11T11:18:13+00:00" + }, + { + "name": "symfony/property-access", + "version": "v2.8.52", + "source": { + "type": "git", + "url": "https://github.com/symfony/property-access.git", + "reference": "c8f10191183be9bb0d5a1b8364d3891f1bde07b6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/property-access/zipball/c8f10191183be9bb0d5a1b8364d3891f1bde07b6", + "reference": "c8f10191183be9bb0d5a1b8364d3891f1bde07b6", + "shasum": "" + }, + "require": { + "php": ">=5.3.9", + "symfony/polyfill-ctype": "~1.8" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.8-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\PropertyAccess\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony PropertyAccess Component", + "homepage": "https://symfony.com", + "keywords": [ + "access", + "array", + "extraction", + "index", + "injection", + "object", + "property", + "property path", + "reflection" + ], + "time": "2018-11-11T11:18:13+00:00" + }, + { + "name": "symfony/routing", + "version": "v2.8.52", + "source": { + "type": "git", + "url": "https://github.com/symfony/routing.git", + "reference": "8b0df6869d1997baafff6a1541826eac5a03d067" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/routing/zipball/8b0df6869d1997baafff6a1541826eac5a03d067", + "reference": "8b0df6869d1997baafff6a1541826eac5a03d067", + "shasum": "" + }, + "require": { + "php": ">=5.3.9" + }, + "conflict": { + "symfony/config": "<2.7" + }, + "require-dev": { + "doctrine/annotations": "~1.0", + "psr/log": "~1.0", + "symfony/config": "~2.7|~3.0.0", + "symfony/expression-language": "~2.4|~3.0.0", + "symfony/http-foundation": "~2.3|~3.0.0", + "symfony/yaml": "^2.0.5|~3.0.0" + }, + "suggest": { + "doctrine/annotations": "For using the annotation loader", + "symfony/config": "For using the all-in-one router or any loader", + "symfony/dependency-injection": "For loading routes from a service", + "symfony/expression-language": "For using expression matching", + "symfony/http-foundation": "For using a Symfony Request object", + "symfony/yaml": "For using the YAML loader" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.8-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Routing\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Routing Component", + "homepage": "https://symfony.com", + "keywords": [ + "router", + "routing", + "uri", + "url" + ], + "time": "2018-11-20T15:55:20+00:00" + }, + { + "name": "symfony/security", + "version": "v2.8.52", + "source": { + "type": "git", + "url": "https://github.com/symfony/security.git", + "reference": "b9e9130cf348d4e85e37ba1d0d27263e33b97534" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/security/zipball/b9e9130cf348d4e85e37ba1d0d27263e33b97534", + "reference": "b9e9130cf348d4e85e37ba1d0d27263e33b97534", + "shasum": "" + }, + "require": { + "php": ">=5.3.9", + "symfony/event-dispatcher": "~2.2|~3.0.0", + "symfony/http-foundation": "^2.7.38|~3.3.13", + "symfony/http-kernel": "~2.4|~3.0.0", + "symfony/polyfill-php55": "~1.0", + "symfony/polyfill-php56": "~1.0", + "symfony/polyfill-php70": "~1.0", + "symfony/polyfill-util": "~1.0", + "symfony/property-access": "~2.3|~3.0.0", + "symfony/security-acl": "~2.7|~3.0.0" + }, + "conflict": { + "symfony/http-foundation": "~2.8,<2.8.31" + }, + "replace": { + "symfony/security-core": "self.version", + "symfony/security-csrf": "self.version", + "symfony/security-guard": "self.version", + "symfony/security-http": "self.version" + }, + "require-dev": { + "psr/log": "~1.0", + "symfony/expression-language": "~2.6|~3.0.0", + "symfony/finder": "~2.3|~3.0.0", + "symfony/ldap": "~2.8|~3.0.0", + "symfony/polyfill-intl-icu": "~1.0", + "symfony/routing": "~2.2|~3.0.0", + "symfony/validator": "~2.7.25|^2.8.18|~3.2.5" + }, + "suggest": { + "symfony/expression-language": "For using the expression voter", + "symfony/form": "", + "symfony/ldap": "For using the LDAP user and authentication providers", + "symfony/routing": "For using the HttpUtils class to create sub-requests, redirect the user, and match URLs", + "symfony/validator": "For using the user password constraint" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.8-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Security\\": "" + }, + "exclude-from-classmap": [ + "/Core/Tests/", + "/Csrf/Tests/", + "/Guard/Tests/", + "/Http/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Security Component", + "homepage": "https://symfony.com", + "time": "2019-04-16T10:01:12+00:00" + }, + { + "name": "symfony/security-acl", + "version": "v3.0.4", + "source": { + "type": "git", + "url": "https://github.com/symfony/security-acl.git", + "reference": "dc8f10b3bda34e9ddcad49edc7accf61f31fce43" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/security-acl/zipball/dc8f10b3bda34e9ddcad49edc7accf61f31fce43", + "reference": "dc8f10b3bda34e9ddcad49edc7accf61f31fce43", + "shasum": "" + }, + "require": { + "php": ">=5.5.9", + "symfony/security-core": "^2.8|^3.0|^4.0|^5.0" + }, + "require-dev": { + "doctrine/common": "~2.2", + "doctrine/dbal": "~2.2", + "psr/log": "~1.0", + "symfony/phpunit-bridge": "^2.8|^3.0|^4.0|^5.0" + }, + "suggest": { + "doctrine/dbal": "For using the built-in ACL implementation", + "symfony/class-loader": "For using the ACL generateSql script", + "symfony/finder": "For using the ACL generateSql script" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Security\\Acl\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Security Component - ACL (Access Control List)", + "homepage": "https://symfony.com", + "time": "2019-12-12T09:55:57+00:00" + }, + { + "name": "symfony/serializer", + "version": "v2.8.52", + "source": { + "type": "git", + "url": "https://github.com/symfony/serializer.git", + "reference": "2939e67396f7356aace05c90e5913736fcb46a20" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/serializer/zipball/2939e67396f7356aace05c90e5913736fcb46a20", + "reference": "2939e67396f7356aace05c90e5913736fcb46a20", + "shasum": "" + }, + "require": { + "php": ">=5.3.9", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-php55": "~1.0" + }, + "require-dev": { + "doctrine/annotations": "~1.0", + "doctrine/cache": "~1.0", + "symfony/config": "~2.2|~3.0.0", + "symfony/property-access": "~2.3|~3.0.0", + "symfony/yaml": "^2.0.5|~3.0.0" + }, + "suggest": { + "doctrine/annotations": "For using the annotation mapping. You will also need doctrine/cache.", + "doctrine/cache": "For using the default cached annotation reader and metadata cache.", + "symfony/config": "For using the XML mapping loader.", + "symfony/property-access": "For using the ObjectNormalizer.", + "symfony/yaml": "For using the default YAML mapping loader." + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.8-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Serializer\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Serializer Component", + "homepage": "https://symfony.com", + "time": "2018-11-11T11:18:13+00:00" + }, + { + "name": "symfony/translation", + "version": "v2.8.52", + "source": { + "type": "git", + "url": "https://github.com/symfony/translation.git", + "reference": "fc58c2a19e56c29f5ba2736ec40d0119a0de2089" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/translation/zipball/fc58c2a19e56c29f5ba2736ec40d0119a0de2089", + "reference": "fc58c2a19e56c29f5ba2736ec40d0119a0de2089", + "shasum": "" + }, + "require": { + "php": ">=5.3.9", + "symfony/polyfill-mbstring": "~1.0" + }, + "conflict": { + "symfony/config": "<2.7" + }, + "require-dev": { + "psr/log": "~1.0", + "symfony/config": "~2.8", + "symfony/intl": "~2.7.25|^2.8.18|~3.2.5", + "symfony/yaml": "~2.2|~3.0.0" + }, + "suggest": { + "psr/log-implementation": "To use logging capability in translator", + "symfony/config": "", + "symfony/yaml": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.8-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Translation\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Translation Component", + "homepage": "https://symfony.com", + "time": "2018-11-24T21:16:41+00:00" + }, + { + "name": "symfony/validator", + "version": "v2.8.52", + "source": { + "type": "git", + "url": "https://github.com/symfony/validator.git", + "reference": "d5d2090bba3139d8ddb79959fbf516e87238fe3a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/validator/zipball/d5d2090bba3139d8ddb79959fbf516e87238fe3a", + "reference": "d5d2090bba3139d8ddb79959fbf516e87238fe3a", + "shasum": "" + }, + "require": { + "php": ">=5.3.9", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-mbstring": "~1.0", + "symfony/translation": "~2.4|~3.0.0" + }, + "require-dev": { + "doctrine/annotations": "~1.0", + "doctrine/cache": "~1.0", + "egulias/email-validator": "^1.2.1", + "symfony/config": "~2.2|~3.0.0", + "symfony/expression-language": "~2.4|~3.0.0", + "symfony/http-foundation": "~2.3|~3.0.0", + "symfony/intl": "~2.7.25|^2.8.18|~3.2.5", + "symfony/property-access": "~2.3|~3.0.0", + "symfony/yaml": "^2.0.5|~3.0.0" + }, + "suggest": { + "doctrine/annotations": "For using the annotation mapping. You will also need doctrine/cache.", + "doctrine/cache": "For using the default cached annotation reader and metadata cache.", + "egulias/email-validator": "Strict (RFC compliant) email validation", + "symfony/config": "", + "symfony/expression-language": "For using the 2.4 Expression validator", + "symfony/http-foundation": "", + "symfony/intl": "", + "symfony/property-access": "For using the 2.4 Validator API", + "symfony/yaml": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.8-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Validator\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Validator Component", + "homepage": "https://symfony.com", + "time": "2018-11-14T14:06:48+00:00" + }, + { + "name": "symfony/yaml", + "version": "v2.8.52", + "source": { + "type": "git", + "url": "https://github.com/symfony/yaml.git", + "reference": "02c1859112aa779d9ab394ae4f3381911d84052b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/yaml/zipball/02c1859112aa779d9ab394ae4f3381911d84052b", + "reference": "02c1859112aa779d9ab394ae4f3381911d84052b", + "shasum": "" + }, + "require": { + "php": ">=5.3.9", + "symfony/polyfill-ctype": "~1.8" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.8-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Yaml\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Yaml Component", + "homepage": "https://symfony.com", + "time": "2018-11-11T11:18:13+00:00" + }, + { + "name": "tecnickcom/tcpdf", + "version": "6.3.5", + "source": { + "type": "git", + "url": "https://github.com/tecnickcom/TCPDF.git", + "reference": "19a535eaa7fb1c1cac499109deeb1a7a201b4549" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/tecnickcom/TCPDF/zipball/19a535eaa7fb1c1cac499109deeb1a7a201b4549", + "reference": "19a535eaa7fb1c1cac499109deeb1a7a201b4549", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "type": "library", + "autoload": { + "classmap": [ + "config", + "include", + "tcpdf.php", + "tcpdf_parser.php", + "tcpdf_import.php", + "tcpdf_barcodes_1d.php", + "tcpdf_barcodes_2d.php", + "include/tcpdf_colors.php", + "include/tcpdf_filters.php", + "include/tcpdf_font_data.php", + "include/tcpdf_fonts.php", + "include/tcpdf_images.php", + "include/tcpdf_static.php", + "include/barcodes/datamatrix.php", + "include/barcodes/pdf417.php", + "include/barcodes/qrcode.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "LGPL-3.0-only" + ], + "authors": [ + { + "name": "Nicola Asuni", + "email": "info@tecnick.com", + "role": "lead" + } + ], + "description": "TCPDF is a PHP class for generating PDF documents and barcodes.", + "homepage": "http://www.tcpdf.org/", + "keywords": [ + "PDFD32000-2008", + "TCPDF", + "barcodes", + "datamatrix", + "pdf", + "pdf417", + "qrcode" + ], + "time": "2020-02-14T14:20:12+00:00" + }, + { + "name": "thelia/currency-converter", + "version": "1.0.2", + "source": { + "type": "git", + "url": "https://github.com/thelia/CurrencyConverter.git", + "reference": "93dae743cf7cd82cf169012bfd6a8dd43d68b974" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thelia/CurrencyConverter/zipball/93dae743cf7cd82cf169012bfd6a8dd43d68b974", + "reference": "93dae743cf7cd82cf169012bfd6a8dd43d68b974", + "shasum": "" + }, + "require": { + "php": ">=5.4.0", + "thelia/math-tools": "~1.0" + }, + "require-dev": { + "phpunit/phpunit": "~4.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Thelia\\CurrencyConverter\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "LGPL-3.0+" + ], + "authors": [ + { + "name": "Manuel Raynaud", + "email": "manu@thelia.net" + } + ], + "description": "php 5.4 currency tools", + "time": "2017-09-30T16:33:49+00:00" + }, + { + "name": "thelia/math-tools", + "version": "1.0.2", + "source": { + "type": "git", + "url": "https://github.com/thelia/math-tools.git", + "reference": "4e66cd5448531a6eaf565acd8b69d9c693da7a3a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thelia/math-tools/zipball/4e66cd5448531a6eaf565acd8b69d9c693da7a3a", + "reference": "4e66cd5448531a6eaf565acd8b69d9c693da7a3a", + "shasum": "" + }, + "require-dev": { + "phpunit/phpunit": "4.1.*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "psr-4": { + "Thelia\\Math\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "LGPL" + ], + "authors": [ + { + "name": "Benjamin Perche", + "email": "bperche@openstudio.com" + } + ], + "description": "Number management library", + "time": "2015-11-05T15:52:55+00:00" + }, + { + "name": "thelia/propel", + "version": "dev-thelia-2.4", + "source": { + "type": "git", + "url": "https://github.com/thelia/Propel2.git", + "reference": "0d49917d48475c54c4ae6c8f780d1838aa810d5d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thelia/Propel2/zipball/0d49917d48475c54c4ae6c8f780d1838aa810d5d", + "reference": "0d49917d48475c54c4ae6c8f780d1838aa810d5d", + "shasum": "" + }, + "require": { + "php": ">=5.5|^7.0", + "psr/log": "~1.0", + "symfony/config": "~2.3||~3.0", + "symfony/console": "~2.3||~3.0", + "symfony/event-dispatcher": "*", + "symfony/filesystem": "~2.3||~3.0", + "symfony/finder": "~2.3||~3.0", + "symfony/validator": "~2.3||~3.0.0||~3.1.0||^3.2.4", + "symfony/yaml": "~2.3||~3.0" + }, + "require-dev": { + "monolog/monolog": "~1.3", + "phpunit/phpunit": "~4.0||~5.0" + }, + "suggest": { + "monolog/monolog": "The recommended logging library to use with Propel." + }, + "bin": [ + "bin/propel" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" + } + }, + "autoload": { + "psr-0": { + "Propel": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "William Durand", + "email": "william.durand1@gmail.com" + } + ], + "description": "Propel2 is an open-source Object-Relational Mapping (ORM) for PHP 5.5 and up.", + "homepage": "http://www.propelorm.org/", + "keywords": [ + "Active Record", + "orm", + "persistence" + ], + "time": "2020-03-25T14:16:18+00:00" + } + ], + "packages-dev": [ + { + "name": "doctrine/instantiator", + "version": "1.4.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/instantiator.git", + "reference": "d56bf6102915de5702778fe20f2de3b2fe570b5b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/instantiator/zipball/d56bf6102915de5702778fe20f2de3b2fe570b5b", + "reference": "d56bf6102915de5702778fe20f2de3b2fe570b5b", + "shasum": "" + }, + "require": { + "php": "^7.1 || ^8.0" + }, + "require-dev": { + "doctrine/coding-standard": "^8.0", + "ext-pdo": "*", + "ext-phar": "*", + "phpbench/phpbench": "^0.13 || 1.0.0-alpha2", + "phpstan/phpstan": "^0.12", + "phpstan/phpstan-phpunit": "^0.12", + "phpunit/phpunit": "^7.0 || ^8.0 || ^9.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Marco Pivetta", + "email": "ocramius@gmail.com", + "homepage": "https://ocramius.github.io/" + } + ], + "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", + "homepage": "https://www.doctrine-project.org/projects/instantiator.html", + "keywords": [ + "constructor", + "instantiate" + ], + "funding": [ + { + "url": "https://www.doctrine-project.org/sponsorship.html", + "type": "custom" + }, + { + "url": "https://www.patreon.com/phpdoctrine", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/doctrine%2Finstantiator", + "type": "tidelift" + } + ], + "time": "2020-11-10T18:47:58+00:00" + }, + { + "name": "fzaninotto/faker", + "version": "v1.5.0", + "source": { + "type": "git", + "url": "https://github.com/fzaninotto/Faker.git", + "reference": "d0190b156bcca848d401fb80f31f504f37141c8d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/fzaninotto/Faker/zipball/d0190b156bcca848d401fb80f31f504f37141c8d", + "reference": "d0190b156bcca848d401fb80f31f504f37141c8d", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "phpunit/phpunit": "~4.0", + "squizlabs/php_codesniffer": "~1.5" + }, + "suggest": { + "ext-intl": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.5.x-dev" + } + }, + "autoload": { + "psr-4": { + "Faker\\": "src/Faker/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "François Zaninotto" + } + ], + "description": "Faker is a PHP library that generates fake data for you.", + "keywords": [ + "data", + "faker", + "fixtures" + ], + "abandoned": true, + "time": "2015-05-29T06:29:14+00:00" + }, + { + "name": "myclabs/deep-copy", + "version": "1.10.2", + "source": { + "type": "git", + "url": "https://github.com/myclabs/DeepCopy.git", + "reference": "776f831124e9c62e1a2c601ecc52e776d8bb7220" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/776f831124e9c62e1a2c601ecc52e776d8bb7220", + "reference": "776f831124e9c62e1a2c601ecc52e776d8bb7220", + "shasum": "" + }, + "require": { + "php": "^7.1 || ^8.0" + }, + "replace": { + "myclabs/deep-copy": "self.version" + }, + "require-dev": { + "doctrine/collections": "^1.0", + "doctrine/common": "^2.6", + "phpunit/phpunit": "^7.1" + }, + "type": "library", + "autoload": { + "psr-4": { + "DeepCopy\\": "src/DeepCopy/" + }, + "files": [ + "src/DeepCopy/deep_copy.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Create deep copies (clones) of your objects", + "keywords": [ + "clone", + "copy", + "duplicate", + "object", + "object graph" + ], + "funding": [ + { + "url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy", + "type": "tidelift" + } + ], + "time": "2020-11-13T09:40:50+00:00" + }, + { + "name": "phpdocumentor/reflection-common", + "version": "2.2.0", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/ReflectionCommon.git", + "reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/1d01c49d4ed62f25aa84a747ad35d5a16924662b", + "reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-2.x": "2.x-dev" + } + }, + "autoload": { + "psr-4": { + "phpDocumentor\\Reflection\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jaap van Otterdijk", + "email": "opensource@ijaap.nl" + } + ], + "description": "Common reflection classes used by phpdocumentor to reflect the code structure", + "homepage": "http://www.phpdoc.org", + "keywords": [ + "FQSEN", + "phpDocumentor", + "phpdoc", + "reflection", + "static analysis" + ], + "time": "2020-06-27T09:03:43+00:00" + }, + { + "name": "phpdocumentor/reflection-docblock", + "version": "5.2.2", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", + "reference": "069a785b2141f5bcf49f3e353548dc1cce6df556" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/069a785b2141f5bcf49f3e353548dc1cce6df556", + "reference": "069a785b2141f5bcf49f3e353548dc1cce6df556", + "shasum": "" + }, + "require": { + "ext-filter": "*", + "php": "^7.2 || ^8.0", + "phpdocumentor/reflection-common": "^2.2", + "phpdocumentor/type-resolver": "^1.3", + "webmozart/assert": "^1.9.1" + }, + "require-dev": { + "mockery/mockery": "~1.3.2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.x-dev" + } + }, + "autoload": { + "psr-4": { + "phpDocumentor\\Reflection\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mike van Riel", + "email": "me@mikevanriel.com" + }, + { + "name": "Jaap van Otterdijk", + "email": "account@ijaap.nl" + } + ], + "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", + "time": "2020-09-03T19:13:55+00:00" + }, + { + "name": "phpdocumentor/type-resolver", + "version": "1.4.0", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/TypeResolver.git", + "reference": "6a467b8989322d92aa1c8bf2bebcc6e5c2ba55c0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/6a467b8989322d92aa1c8bf2bebcc6e5c2ba55c0", + "reference": "6a467b8989322d92aa1c8bf2bebcc6e5c2ba55c0", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0", + "phpdocumentor/reflection-common": "^2.0" + }, + "require-dev": { + "ext-tokenizer": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-1.x": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "phpDocumentor\\Reflection\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mike van Riel", + "email": "me@mikevanriel.com" + } + ], + "description": "A PSR-5 based resolver of Class names, Types and Structural Element Names", + "time": "2020-09-17T18:55:26+00:00" + }, + { + "name": "phpspec/prophecy", + "version": "v1.10.3", + "source": { + "type": "git", + "url": "https://github.com/phpspec/prophecy.git", + "reference": "451c3cd1418cf640de218914901e51b064abb093" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpspec/prophecy/zipball/451c3cd1418cf640de218914901e51b064abb093", + "reference": "451c3cd1418cf640de218914901e51b064abb093", + "shasum": "" + }, + "require": { + "doctrine/instantiator": "^1.0.2", + "php": "^5.3|^7.0", + "phpdocumentor/reflection-docblock": "^2.0|^3.0.2|^4.0|^5.0", + "sebastian/comparator": "^1.2.3|^2.0|^3.0|^4.0", + "sebastian/recursion-context": "^1.0|^2.0|^3.0|^4.0" + }, + "require-dev": { + "phpspec/phpspec": "^2.5 || ^3.2", + "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.5 || ^7.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.10.x-dev" + } + }, + "autoload": { + "psr-4": { + "Prophecy\\": "src/Prophecy" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Konstantin Kudryashov", + "email": "ever.zet@gmail.com", + "homepage": "http://everzet.com" + }, + { + "name": "Marcello Duarte", + "email": "marcello.duarte@gmail.com" + } + ], + "description": "Highly opinionated mocking framework for PHP 5.3+", + "homepage": "https://github.com/phpspec/prophecy", + "keywords": [ + "Double", + "Dummy", + "fake", + "mock", + "spy", + "stub" + ], + "time": "2020-03-05T15:02:03+00:00" + }, + { + "name": "phpunit/php-code-coverage", + "version": "4.0.8", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-code-coverage.git", + "reference": "ef7b2f56815df854e66ceaee8ebe9393ae36a40d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/ef7b2f56815df854e66ceaee8ebe9393ae36a40d", + "reference": "ef7b2f56815df854e66ceaee8ebe9393ae36a40d", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-xmlwriter": "*", + "php": "^5.6 || ^7.0", + "phpunit/php-file-iterator": "^1.3", + "phpunit/php-text-template": "^1.2", + "phpunit/php-token-stream": "^1.4.2 || ^2.0", + "sebastian/code-unit-reverse-lookup": "^1.0", + "sebastian/environment": "^1.3.2 || ^2.0", + "sebastian/version": "^1.0 || ^2.0" + }, + "require-dev": { + "ext-xdebug": "^2.1.4", + "phpunit/phpunit": "^5.7" + }, + "suggest": { + "ext-xdebug": "^2.5.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sb@sebastian-bergmann.de", + "role": "lead" + } + ], + "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", + "homepage": "https://github.com/sebastianbergmann/php-code-coverage", + "keywords": [ + "coverage", + "testing", + "xunit" + ], + "time": "2017-04-02T07:44:40+00:00" + }, + { + "name": "phpunit/php-file-iterator", + "version": "1.4.5", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-file-iterator.git", + "reference": "730b01bc3e867237eaac355e06a36b85dd93a8b4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/730b01bc3e867237eaac355e06a36b85dd93a8b4", + "reference": "730b01bc3e867237eaac355e06a36b85dd93a8b4", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.4.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sb@sebastian-bergmann.de", + "role": "lead" + } + ], + "description": "FilterIterator implementation that filters files based on a list of suffixes.", + "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", + "keywords": [ + "filesystem", + "iterator" + ], + "time": "2017-11-27T13:52:08+00:00" + }, + { + "name": "phpunit/php-text-template", + "version": "1.2.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-text-template.git", + "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/31f8b717e51d9a2afca6c9f046f5d69fc27c8686", + "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Simple template engine.", + "homepage": "https://github.com/sebastianbergmann/php-text-template/", + "keywords": [ + "template" + ], + "time": "2015-06-21T13:50:34+00:00" + }, + { + "name": "phpunit/php-timer", + "version": "1.0.9", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-timer.git", + "reference": "3dcf38ca72b158baf0bc245e9184d3fdffa9c46f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/3dcf38ca72b158baf0bc245e9184d3fdffa9c46f", + "reference": "3dcf38ca72b158baf0bc245e9184d3fdffa9c46f", + "shasum": "" + }, + "require": { + "php": "^5.3.3 || ^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sb@sebastian-bergmann.de", + "role": "lead" + } + ], + "description": "Utility class for timing", + "homepage": "https://github.com/sebastianbergmann/php-timer/", + "keywords": [ + "timer" + ], + "time": "2017-02-26T11:10:40+00:00" + }, + { + "name": "phpunit/php-token-stream", + "version": "2.0.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-token-stream.git", + "reference": "791198a2c6254db10131eecfe8c06670700904db" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/791198a2c6254db10131eecfe8c06670700904db", + "reference": "791198a2c6254db10131eecfe8c06670700904db", + "shasum": "" + }, + "require": { + "ext-tokenizer": "*", + "php": "^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^6.2.4" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Wrapper around PHP's tokenizer extension.", + "homepage": "https://github.com/sebastianbergmann/php-token-stream/", + "keywords": [ + "tokenizer" + ], + "abandoned": true, + "time": "2017-11-27T05:48:46+00:00" + }, + { + "name": "phpunit/phpunit", + "version": "5.7.27", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/phpunit.git", + "reference": "b7803aeca3ccb99ad0a506fa80b64cd6a56bbc0c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/b7803aeca3ccb99ad0a506fa80b64cd6a56bbc0c", + "reference": "b7803aeca3ccb99ad0a506fa80b64cd6a56bbc0c", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-json": "*", + "ext-libxml": "*", + "ext-mbstring": "*", + "ext-xml": "*", + "myclabs/deep-copy": "~1.3", + "php": "^5.6 || ^7.0", + "phpspec/prophecy": "^1.6.2", + "phpunit/php-code-coverage": "^4.0.4", + "phpunit/php-file-iterator": "~1.4", + "phpunit/php-text-template": "~1.2", + "phpunit/php-timer": "^1.0.6", + "phpunit/phpunit-mock-objects": "^3.2", + "sebastian/comparator": "^1.2.4", + "sebastian/diff": "^1.4.3", + "sebastian/environment": "^1.3.4 || ^2.0", + "sebastian/exporter": "~2.0", + "sebastian/global-state": "^1.1", + "sebastian/object-enumerator": "~2.0", + "sebastian/resource-operations": "~1.0", + "sebastian/version": "^1.0.6|^2.0.1", + "symfony/yaml": "~2.1|~3.0|~4.0" + }, + "conflict": { + "phpdocumentor/reflection-docblock": "3.0.2" + }, + "require-dev": { + "ext-pdo": "*" + }, + "suggest": { + "ext-xdebug": "*", + "phpunit/php-invoker": "~1.1" + }, + "bin": [ + "phpunit" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.7.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "The PHP Unit Testing framework.", + "homepage": "https://phpunit.de/", + "keywords": [ + "phpunit", + "testing", + "xunit" + ], + "time": "2018-02-01T05:50:59+00:00" + }, + { + "name": "phpunit/phpunit-mock-objects", + "version": "3.4.4", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git", + "reference": "a23b761686d50a560cc56233b9ecf49597cc9118" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/a23b761686d50a560cc56233b9ecf49597cc9118", + "reference": "a23b761686d50a560cc56233b9ecf49597cc9118", + "shasum": "" + }, + "require": { + "doctrine/instantiator": "^1.0.2", + "php": "^5.6 || ^7.0", + "phpunit/php-text-template": "^1.2", + "sebastian/exporter": "^1.2 || ^2.0" + }, + "conflict": { + "phpunit/phpunit": "<5.4.0" + }, + "require-dev": { + "phpunit/phpunit": "^5.4" + }, + "suggest": { + "ext-soap": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.2.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sb@sebastian-bergmann.de", + "role": "lead" + } + ], + "description": "Mock Object library for PHPUnit", + "homepage": "https://github.com/sebastianbergmann/phpunit-mock-objects/", + "keywords": [ + "mock", + "xunit" + ], + "abandoned": true, + "time": "2017-06-30T09:13:00+00:00" + }, + { + "name": "sebastian/code-unit-reverse-lookup", + "version": "1.0.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", + "reference": "1de8cd5c010cb153fcd68b8d0f64606f523f7619" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/1de8cd5c010cb153fcd68b8d0f64606f523f7619", + "reference": "1de8cd5c010cb153fcd68b8d0f64606f523f7619", + "shasum": "" + }, + "require": { + "php": ">=5.6" + }, + "require-dev": { + "phpunit/phpunit": "^8.5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Looks up which function or method a line of code belongs to", + "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-11-30T08:15:22+00:00" + }, + { + "name": "sebastian/comparator", + "version": "1.2.4", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/comparator.git", + "reference": "2b7424b55f5047b47ac6e5ccb20b2aea4011d9be" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/2b7424b55f5047b47ac6e5ccb20b2aea4011d9be", + "reference": "2b7424b55f5047b47ac6e5ccb20b2aea4011d9be", + "shasum": "" + }, + "require": { + "php": ">=5.3.3", + "sebastian/diff": "~1.2", + "sebastian/exporter": "~1.2 || ~2.0" + }, + "require-dev": { + "phpunit/phpunit": "~4.4" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.2.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@2bepublished.at" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Provides the functionality to compare PHP values for equality", + "homepage": "http://www.github.com/sebastianbergmann/comparator", + "keywords": [ + "comparator", + "compare", + "equality" + ], + "time": "2017-01-29T09:50:25+00:00" + }, + { + "name": "sebastian/diff", + "version": "1.4.3", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/diff.git", + "reference": "7f066a26a962dbe58ddea9f72a4e82874a3975a4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/7f066a26a962dbe58ddea9f72a4e82874a3975a4", + "reference": "7f066a26a962dbe58ddea9f72a4e82874a3975a4", + "shasum": "" + }, + "require": { + "php": "^5.3.3 || ^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.4-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Kore Nordmann", + "email": "mail@kore-nordmann.de" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Diff implementation", + "homepage": "https://github.com/sebastianbergmann/diff", + "keywords": [ + "diff" + ], + "time": "2017-05-22T07:24:03+00:00" + }, + { + "name": "sebastian/environment", + "version": "2.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/environment.git", + "reference": "5795ffe5dc5b02460c3e34222fee8cbe245d8fac" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/5795ffe5dc5b02460c3e34222fee8cbe245d8fac", + "reference": "5795ffe5dc5b02460c3e34222fee8cbe245d8fac", + "shasum": "" + }, + "require": { + "php": "^5.6 || ^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^5.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Provides functionality to handle HHVM/PHP environments", + "homepage": "http://www.github.com/sebastianbergmann/environment", + "keywords": [ + "Xdebug", + "environment", + "hhvm" + ], + "time": "2016-11-26T07:53:53+00:00" + }, + { + "name": "sebastian/exporter", + "version": "2.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/exporter.git", + "reference": "ce474bdd1a34744d7ac5d6aad3a46d48d9bac4c4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/ce474bdd1a34744d7ac5d6aad3a46d48d9bac4c4", + "reference": "ce474bdd1a34744d7ac5d6aad3a46d48d9bac4c4", + "shasum": "" + }, + "require": { + "php": ">=5.3.3", + "sebastian/recursion-context": "~2.0" + }, + "require-dev": { + "ext-mbstring": "*", + "phpunit/phpunit": "~4.4" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@2bepublished.at" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" + } + ], + "description": "Provides the functionality to export PHP variables for visualization", + "homepage": "http://www.github.com/sebastianbergmann/exporter", + "keywords": [ + "export", + "exporter" + ], + "time": "2016-11-19T08:54:04+00:00" + }, + { + "name": "sebastian/global-state", + "version": "1.1.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/global-state.git", + "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bc37d50fea7d017d3d340f230811c9f1d7280af4", + "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "phpunit/phpunit": "~4.2" + }, + "suggest": { + "ext-uopz": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Snapshotting of global state", + "homepage": "http://www.github.com/sebastianbergmann/global-state", + "keywords": [ + "global state" + ], + "time": "2015-10-12T03:26:01+00:00" + }, + { + "name": "sebastian/object-enumerator", + "version": "2.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/object-enumerator.git", + "reference": "1311872ac850040a79c3c058bea3e22d0f09cbb7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/1311872ac850040a79c3c058bea3e22d0f09cbb7", + "reference": "1311872ac850040a79c3c058bea3e22d0f09cbb7", + "shasum": "" + }, + "require": { + "php": ">=5.6", + "sebastian/recursion-context": "~2.0" + }, + "require-dev": { + "phpunit/phpunit": "~5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Traverses array structures and object graphs to enumerate all referenced objects", + "homepage": "https://github.com/sebastianbergmann/object-enumerator/", + "time": "2017-02-18T15:18:39+00:00" + }, + { + "name": "sebastian/recursion-context", + "version": "2.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/recursion-context.git", + "reference": "2c3ba150cbec723aa057506e73a8d33bdb286c9a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/2c3ba150cbec723aa057506e73a8d33bdb286c9a", + "reference": "2c3ba150cbec723aa057506e73a8d33bdb286c9a", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "phpunit/phpunit": "~4.4" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" + } + ], + "description": "Provides functionality to recursively process PHP variables", + "homepage": "http://www.github.com/sebastianbergmann/recursion-context", + "time": "2016-11-19T07:33:16+00:00" + }, + { + "name": "sebastian/resource-operations", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/resource-operations.git", + "reference": "ce990bb21759f94aeafd30209e8cfcdfa8bc3f52" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/ce990bb21759f94aeafd30209e8cfcdfa8bc3f52", + "reference": "ce990bb21759f94aeafd30209e8cfcdfa8bc3f52", + "shasum": "" + }, + "require": { + "php": ">=5.6.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Provides a list of PHP built-in functions that operate on resources", + "homepage": "https://www.github.com/sebastianbergmann/resource-operations", + "time": "2015-07-28T20:34:47+00:00" + }, + { + "name": "sebastian/version", + "version": "2.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/version.git", + "reference": "99732be0ddb3361e16ad77b68ba41efc8e979019" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/99732be0ddb3361e16ad77b68ba41efc8e979019", + "reference": "99732be0ddb3361e16ad77b68ba41efc8e979019", + "shasum": "" + }, + "require": { + "php": ">=5.6" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library that helps with managing the version number of Git-hosted PHP projects", + "homepage": "https://github.com/sebastianbergmann/version", + "time": "2016-10-03T07:35:21+00:00" + }, + { + "name": "symfony/var-dumper", + "version": "v4.0.15", + "source": { + "type": "git", + "url": "https://github.com/symfony/var-dumper.git", + "reference": "3af63f44ddb45b03af4d172a4ce3e5c58b25fc5b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/3af63f44ddb45b03af4d172a4ce3e5c58b25fc5b", + "reference": "3af63f44ddb45b03af4d172a4ce3e5c58b25fc5b", + "shasum": "" + }, + "require": { + "php": "^7.1.3", + "symfony/polyfill-mbstring": "~1.0", + "symfony/polyfill-php72": "~1.5" + }, + "conflict": { + "phpunit/phpunit": "<4.8.35|<5.4.3,>=5.0" + }, + "require-dev": { + "ext-iconv": "*", + "twig/twig": "~1.34|~2.4" + }, + "suggest": { + "ext-iconv": "To convert non-UTF-8 strings to UTF-8 (or symfony/polyfill-iconv in case ext-iconv cannot be used).", + "ext-intl": "To show region name in time zone dump" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0-dev" + } + }, + "autoload": { + "files": [ + "Resources/functions/dump.php" + ], + "psr-4": { + "Symfony\\Component\\VarDumper\\": "" + }, + "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 mechanism for exploring and dumping PHP variables", + "homepage": "https://symfony.com", + "keywords": [ + "debug", + "dump" + ], + "time": "2018-07-26T11:22:46+00:00" + }, + { + "name": "thelia/hooktest-module", + "version": "1.1", + "source": { + "type": "git", + "url": "https://github.com/thelia/HookTest-module.git", + "reference": "32891857fd1e8e9ca5b7a9dbb0960ef3dd525fcb" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thelia/HookTest-module/zipball/32891857fd1e8e9ca5b7a9dbb0960ef3dd525fcb", + "reference": "32891857fd1e8e9ca5b7a9dbb0960ef3dd525fcb", + "shasum": "" + }, + "require": { + "thelia/installer": "~1.1" + }, + "type": "thelia-module", + "extra": { + "installer-name": "HookTest" + }, + "notification-url": "https://packagist.org/downloads/", + "time": "2014-12-24T09:52:09+00:00" + }, + { + "name": "thelia/hooktest-template", + "version": "1.1", + "source": { + "type": "git", + "url": "https://github.com/thelia/hooktest-template.git", + "reference": "bb0a26df8ecfe7e41e2e391adb22360201088dda" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thelia/hooktest-template/zipball/bb0a26df8ecfe7e41e2e391adb22360201088dda", + "reference": "bb0a26df8ecfe7e41e2e391adb22360201088dda", + "shasum": "" + }, + "require": { + "thelia/installer": "~1.1" + }, + "type": "thelia-frontoffice-template", + "extra": { + "installer-name": "hooktest" + }, + "notification-url": "https://packagist.org/downloads/", + "time": "2014-12-24T09:51:48+00:00" + }, + { + "name": "thelia/installer", + "version": "1.3", + "source": { + "type": "git", + "url": "https://github.com/thelia/installer.git", + "reference": "dca473563e05011c7aea3aaebc6f154fef4187fe" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thelia/installer/zipball/dca473563e05011c7aea3aaebc6f154fef4187fe", + "reference": "dca473563e05011c7aea3aaebc6f154fef4187fe", + "shasum": "" + }, + "require": { + "composer-plugin-api": "^1.0||^2.0" + }, + "require-dev": { + "composer/composer": "1.0.*@dev||2.0.*@dev" + }, + "type": "composer-plugin", + "extra": { + "class": "Thelia\\Composer\\TheliaInstallerPlugin" + }, + "autoload": { + "psr-0": { + "Thelia\\Composer": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "LGPL-3.0-or-later" + ], + "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": "2020-10-26T10:32:18+00:00" + }, + { + "name": "webmozart/assert", + "version": "1.9.1", + "source": { + "type": "git", + "url": "https://github.com/webmozart/assert.git", + "reference": "bafc69caeb4d49c39fd0779086c03a3738cbb389" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/webmozart/assert/zipball/bafc69caeb4d49c39fd0779086c03a3738cbb389", + "reference": "bafc69caeb4d49c39fd0779086c03a3738cbb389", + "shasum": "" + }, + "require": { + "php": "^5.3.3 || ^7.0 || ^8.0", + "symfony/polyfill-ctype": "^1.8" + }, + "conflict": { + "phpstan/phpstan": "<0.12.20", + "vimeo/psalm": "<3.9.1" + }, + "require-dev": { + "phpunit/phpunit": "^4.8.36 || ^7.5.13" + }, + "type": "library", + "autoload": { + "psr-4": { + "Webmozart\\Assert\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" + } + ], + "description": "Assertions to validate method input/output with nice error messages.", + "keywords": [ + "assert", + "check", + "validate" + ], + "time": "2020-07-08T17:02:28+00:00" + } + ], + "aliases": [], + "minimum-stability": "stable", + "stability-flags": { + "thelia/propel": 20 + }, + "prefer-stable": false, + "prefer-lowest": false, + "platform": { + "php": "^5.6|^7.0" + }, + "platform-dev": [], + "plugin-api-version": "1.1.0" +} diff --git a/core/lib/Thelia/Action/Address.php b/core/lib/Thelia/Action/Address.php new file mode 100644 index 00000000..6cc2e52a --- /dev/null +++ b/core/lib/Thelia/Action/Address.php @@ -0,0 +1,108 @@ + + */ +class Address extends BaseAction implements EventSubscriberInterface +{ + public function create(AddressCreateOrUpdateEvent $event, $eventName, EventDispatcherInterface $dispatcher) + { + $address = new AddressModel(); + $address->setCustomer($event->getCustomer()); + $this->createOrUpdate($address, $event, $dispatcher); + } + + public function update(AddressCreateOrUpdateEvent $event, $eventName, EventDispatcherInterface $dispatcher) + { + $addressModel = $event->getAddress(); + + $this->createOrUpdate($addressModel, $event, $dispatcher); + } + + public function delete(AddressEvent $event) + { + $address = $event->getAddress(); + + $address->delete(); + } + + public function useDefault(AddressEvent $event) + { + $address = $event->getAddress(); + + $address->makeItDefault(); + } + + protected function createOrUpdate(AddressModel $addressModel, AddressCreateOrUpdateEvent $event, $dispatcher) + { + $addressModel->setDispatcher($dispatcher); + $con = Propel::getWriteConnection(AddressTableMap::DATABASE_NAME); + $con->beginTransaction(); + try { + $addressModel + ->setLabel($event->getLabel()) + ->setTitleId($event->getTitle()) + ->setFirstname($event->getFirstname()) + ->setLastname($event->getLastname()) + ->setAddress1($event->getAddress1()) + ->setAddress2($event->getAddress2()) + ->setAddress3($event->getAddress3()) + ->setZipcode($event->getZipcode()) + ->setCity($event->getCity()) + ->setCountryId($event->getCountry()) + ->setStateId($event->getState()) + ->setCellphone($event->getCellphone()) + ->setPhone($event->getPhone()) + ->setCompany($event->getCompany()) + ->save() + ; + + if ($event->getIsDefault() && !$addressModel->getIsDefault()) { + $addressModel->makeItDefault(); + } + + $event->setAddress($addressModel); + $con->commit(); + } catch (PropelException $e) { + $con->rollback(); + throw $e; + } + } + + /** + * {@inheritdoc} + */ + public static function getSubscribedEvents() + { + return array( + TheliaEvents::ADDRESS_CREATE => array("create", 128), + TheliaEvents::ADDRESS_UPDATE => array("update", 128), + TheliaEvents::ADDRESS_DELETE => array("delete", 128), + TheliaEvents::ADDRESS_DEFAULT => array('useDefault', 128), + ); + } +} diff --git a/core/lib/Thelia/Action/Administrator.php b/core/lib/Thelia/Action/Administrator.php new file mode 100644 index 00000000..369aeee8 --- /dev/null +++ b/core/lib/Thelia/Action/Administrator.php @@ -0,0 +1,155 @@ +mailer = $mailer; + $this->tokenProvider = $tokenProvider; + } + + /** + * @param AdministratorEvent $event + * @param $eventName + * @param EventDispatcherInterface $dispatcher + */ + public function create(AdministratorEvent $event, $eventName, EventDispatcherInterface $dispatcher) + { + $administrator = new AdminModel(); + + $administrator + ->setDispatcher($dispatcher) + ->setFirstname($event->getFirstname()) + ->setLastname($event->getLastname()) + ->setEmail($event->getEmail()) + ->setLogin($event->getLogin()) + ->setPassword($event->getPassword()) + ->setProfileId($event->getProfile()) + ->setLocale($event->getLocale()) + ; + + $administrator->save(); + + $event->setAdministrator($administrator); + } + + /** + * @param AdministratorEvent $event + * @param $eventName + * @param EventDispatcherInterface $dispatcher + */ + public function update(AdministratorEvent $event, $eventName, EventDispatcherInterface $dispatcher) + { + if (null !== $administrator = AdminQuery::create()->findPk($event->getId())) { + $administrator + ->setDispatcher($dispatcher) + ->setFirstname($event->getFirstname()) + ->setLastname($event->getLastname()) + ->setLogin($event->getLogin()) + ->setEmail($event->getEmail()) + ->setProfileId($event->getProfile()) + ->setLocale($event->getLocale()) + ; + + if ('' !== $event->getPassword()) { + $administrator->setPassword($event->getPassword()); + } + + $administrator->save(); + + $event->setAdministrator($administrator); + } + } + + /** + * @param AdministratorEvent $event + */ + public function delete(AdministratorEvent $event) + { + if (null !== $administrator = AdminQuery::create()->findPk($event->getId())) { + $administrator + ->delete() + ; + + $event->setAdministrator($administrator); + } + } + + public function updatePassword(AdministratorUpdatePasswordEvent $event) + { + $admin = $event->getAdmin(); + + $admin + ->setPassword($event->getPassword()) + ->setPasswordRenewToken(null) + ->save(); + } + + public function createPassword(AdministratorEvent $event) + { + $admin = $event->getAdministrator(); + + $email = $admin->getEmail(); + + if (! empty($email)) { + $renewToken = $this->tokenProvider->getToken(); + + $admin + ->setPasswordRenewToken($renewToken) + ->save(); + + $this->mailer->sendEmailMessage( + 'new_admin_password', + [ ConfigQuery::getStoreEmail() => ConfigQuery::getStoreName() ], + [ $email => $admin->getFirstname() . ' ' . $admin->getLastname() ], + [ + 'token' => $renewToken, + 'admin' => $admin + ] + ); + } + } + + /** + * {@inheritdoc} + */ + public static function getSubscribedEvents() + { + return array( + TheliaEvents::ADMINISTRATOR_CREATE => array('create', 128), + TheliaEvents::ADMINISTRATOR_UPDATE => array('update', 128), + TheliaEvents::ADMINISTRATOR_DELETE => array('delete', 128), + TheliaEvents::ADMINISTRATOR_UPDATEPASSWORD => array('updatePassword', 128), + TheliaEvents::ADMINISTRATOR_CREATEPASSWORD => array('createPassword', 128) + ); + } +} diff --git a/core/lib/Thelia/Action/Api.php b/core/lib/Thelia/Action/Api.php new file mode 100644 index 00000000..58e9e13c --- /dev/null +++ b/core/lib/Thelia/Action/Api.php @@ -0,0 +1,65 @@ + + */ +class Api extends BaseAction implements EventSubscriberInterface +{ + public function createApi(ApiCreateEvent $event) + { + $api = new ApiModel(); + + $api->setLabel($event->getLabel()) + ->setProfileId($event->getProfile()) + ->save() + ; + } + + public function deleteApi(ApiDeleteEvent $event) + { + $api = $event->getApi(); + + $api->delete(); + } + + public function updateApi(ApiUpdateEvent $event) + { + $api = $event->getApi(); + + $api->setProfileId($event->getProfile()) + ->save(); + } + + /** + * {@inheritdoc} + */ + public static function getSubscribedEvents() + { + return [ + TheliaEvents::API_CREATE => ['createApi', 128], + TheliaEvents::API_DELETE => ['deleteApi', 128], + TheliaEvents::API_UPDATE => ['updateApi', 128], + ]; + } +} diff --git a/core/lib/Thelia/Action/Area.php b/core/lib/Thelia/Action/Area.php new file mode 100644 index 00000000..1ea3de14 --- /dev/null +++ b/core/lib/Thelia/Action/Area.php @@ -0,0 +1,137 @@ + + */ +class Area extends BaseAction implements EventSubscriberInterface +{ + public function addCountry(AreaAddCountryEvent $event) + { + $countryIds = $event->getCountryId(); + + $areaId = $event->getAreaId(); + + foreach ($countryIds as $countryId) { + $countryArea = new CountryArea(); + + $country = explode('-', $countryId); + if (\count($country) === 1) { + $country[1] = null; + } + if ($country[1] == 0) { + $country[1] = null; + } + + $countryArea + ->setAreaId($areaId) + ->setCountryId($country[0]) + ->setStateId($country[1]) + ->save() + ; + } + + $event->setArea(AreaQuery::create()->findPk($areaId)); + } + + public function removeCountry(AreaRemoveCountryEvent $event) + { + CountryAreaQuery::create() + ->filterByCountryId($event->getCountryId()) + ->filterByStateId($event->getStateId()) + ->filterByAreaId($event->getAreaId()) + ->delete(); + + if (null !== $area = AreaQuery::create()->findPk($event->getAreaId())) { + $event->setArea($area); + } + } + + public function updatePostage(AreaUpdatePostageEvent $event, $eventName, EventDispatcherInterface $dispatcher) + { + if (null !== $area = AreaQuery::create()->findPk($event->getAreaId())) { + $area->setDispatcher($dispatcher); + $area + ->setPostage($event->getPostage()) + ->save(); + + $event->setArea($area); + } + } + + public function delete(AreaDeleteEvent $event, $eventName, EventDispatcherInterface $dispatcher) + { + if (null !== $area = AreaQuery::create()->findPk($event->getAreaId())) { + $area->setDispatcher($dispatcher); + $area->delete(); + + $event->setArea($area); + } + } + + public function create(AreaCreateEvent $event, $eventName, EventDispatcherInterface $dispatcher) + { + $area = new AreaModel(); + + $area + ->setDispatcher($dispatcher) + ->setName($event->getAreaName()) + ->save(); + + $event->setArea($area); + } + + public function update(AreaUpdateEvent $event, $eventName, EventDispatcherInterface $dispatcher) + { + if (null !== $area = AreaQuery::create()->findPk($event->getAreaId())) { + $area + ->setDispatcher($dispatcher) + ->setName($event->getAreaName()) + ->save(); + + $event->setArea($area); + } + } + + /** + * {@inheritdoc} + */ + public static function getSubscribedEvents() + { + return array( + TheliaEvents::AREA_ADD_COUNTRY => array('addCountry', 128), + TheliaEvents::AREA_REMOVE_COUNTRY => array('removeCountry', 128), + TheliaEvents::AREA_POSTAGE_UPDATE => array('updatePostage', 128), + TheliaEvents::AREA_DELETE => array('delete', 128), + TheliaEvents::AREA_CREATE => array('create', 128), + TheliaEvents::AREA_UPDATE => array('update', 128) + ); + } +} diff --git a/core/lib/Thelia/Action/Attribute.php b/core/lib/Thelia/Action/Attribute.php new file mode 100644 index 00000000..d6faf7e6 --- /dev/null +++ b/core/lib/Thelia/Action/Attribute.php @@ -0,0 +1,157 @@ +setDispatcher($dispatcher) + ->setLocale($event->getLocale()) + ->setTitle($event->getTitle()) + ->save() + ; + + $event->setAttribute($attribute); + + // Add atribute to all product templates if required + if ($event->getAddToAllTemplates() != 0) { + $this->doAddToAllTemplates($attribute); + } + } + + /** + * Change a product attribute + * + * @param AttributeUpdateEvent $event + * @param $eventName + * @param EventDispatcherInterface $dispatcher + */ + public function update(AttributeUpdateEvent $event, $eventName, EventDispatcherInterface $dispatcher) + { + if (null !== $attribute = AttributeQuery::create()->findPk($event->getAttributeId())) { + $attribute + ->setDispatcher($dispatcher) + + ->setLocale($event->getLocale()) + ->setTitle($event->getTitle()) + ->setDescription($event->getDescription()) + ->setChapo($event->getChapo()) + ->setPostscriptum($event->getPostscriptum()) + + ->save(); + + $event->setAttribute($attribute); + } + } + + /** + * Delete a product attribute entry + * + * @param AttributeDeleteEvent $event + * @param $eventName + * @param EventDispatcherInterface $dispatcher + */ + public function delete(AttributeDeleteEvent $event, $eventName, EventDispatcherInterface $dispatcher) + { + if (null !== ($attribute = AttributeQuery::create()->findPk($event->getAttributeId()))) { + $attribute + ->setDispatcher($dispatcher) + ->delete() + ; + + $event->setAttribute($attribute); + } + } + + /** + * Changes position, selecting absolute ou relative change. + * + * @param UpdatePositionEvent $event + * @param $eventName + * @param EventDispatcherInterface $dispatcher + */ + public function updatePosition(UpdatePositionEvent $event, $eventName, EventDispatcherInterface $dispatcher) + { + $this->genericUpdatePosition(AttributeQuery::create(), $event, $dispatcher); + } + + protected function doAddToAllTemplates(AttributeModel $attribute) + { + $templates = TemplateQuery::create()->find(); + + foreach ($templates as $template) { + $attribute_template = new AttributeTemplate(); + + if (null === AttributeTemplateQuery::create()->filterByAttribute($attribute)->filterByTemplate($template)->findOne()) { + $attribute_template + ->setAttribute($attribute) + ->setTemplate($template) + ->save() + ; + } + } + } + + public function addToAllTemplates(AttributeEvent $event) + { + $this->doAddToAllTemplates($event->getAttribute()); + } + + public function removeFromAllTemplates(AttributeEvent $event) + { + // Delete this attribute from all product templates + AttributeTemplateQuery::create()->filterByAttribute($event->getAttribute())->delete(); + } + + /** + * {@inheritdoc} + */ + public static function getSubscribedEvents() + { + return array( + TheliaEvents::ATTRIBUTE_CREATE => array("create", 128), + TheliaEvents::ATTRIBUTE_UPDATE => array("update", 128), + TheliaEvents::ATTRIBUTE_DELETE => array("delete", 128), + TheliaEvents::ATTRIBUTE_UPDATE_POSITION => array("updatePosition", 128), + + TheliaEvents::ATTRIBUTE_REMOVE_FROM_ALL_TEMPLATES => array("removeFromAllTemplates", 128), + TheliaEvents::ATTRIBUTE_ADD_TO_ALL_TEMPLATES => array("addToAllTemplates", 128), + + ); + } +} diff --git a/core/lib/Thelia/Action/AttributeAv.php b/core/lib/Thelia/Action/AttributeAv.php new file mode 100644 index 00000000..8f30767b --- /dev/null +++ b/core/lib/Thelia/Action/AttributeAv.php @@ -0,0 +1,119 @@ +setDispatcher($dispatcher) + + ->setAttributeId($event->getAttributeId()) + ->setLocale($event->getLocale()) + ->setTitle($event->getTitle()) + + ->save() + ; + + $event->setAttributeAv($attribute); + } + + /** + * Change a product attribute + * + * @param AttributeAvUpdateEvent $event + * @param $eventName + * @param EventDispatcherInterface $dispatcher + */ + public function update(AttributeAvUpdateEvent $event, $eventName, EventDispatcherInterface $dispatcher) + { + if (null !== $attribute = AttributeAvQuery::create()->findPk($event->getAttributeAvId())) { + $attribute + ->setDispatcher($dispatcher) + + ->setLocale($event->getLocale()) + ->setTitle($event->getTitle()) + ->setDescription($event->getDescription()) + ->setChapo($event->getChapo()) + ->setPostscriptum($event->getPostscriptum()) + + ->save(); + + $event->setAttributeAv($attribute); + } + } + + /** + * Delete a product attribute entry + * + * @param AttributeAvDeleteEvent $event + * @param $eventName + * @param EventDispatcherInterface $dispatcher + */ + public function delete(AttributeAvDeleteEvent $event, $eventName, EventDispatcherInterface $dispatcher) + { + if (null !== ($attribute = AttributeAvQuery::create()->findPk($event->getAttributeAvId()))) { + $attribute + ->setDispatcher($dispatcher) + ->delete() + ; + + $event->setAttributeAv($attribute); + } + } + + /** + * Changes position, selecting absolute ou relative change. + * + * @param UpdatePositionEvent $event + * @param $eventName + * @param EventDispatcherInterface $dispatcher + */ + public function updatePosition(UpdatePositionEvent $event, $eventName, EventDispatcherInterface $dispatcher) + { + $this->genericUpdatePosition(AttributeAvQuery::create(), $event); + } + + /** + * {@inheritdoc} + */ + public static function getSubscribedEvents() + { + return array( + TheliaEvents::ATTRIBUTE_AV_CREATE => array("create", 128), + TheliaEvents::ATTRIBUTE_AV_UPDATE => array("update", 128), + TheliaEvents::ATTRIBUTE_AV_DELETE => array("delete", 128), + TheliaEvents::ATTRIBUTE_AV_UPDATE_POSITION => array("updatePosition", 128), + ); + } +} diff --git a/core/lib/Thelia/Action/BaseAction.php b/core/lib/Thelia/Action/BaseAction.php new file mode 100644 index 00000000..5361c9c4 --- /dev/null +++ b/core/lib/Thelia/Action/BaseAction.php @@ -0,0 +1,146 @@ +findPk($event->getObjectId())) { + if (!isset(class_uses($object)['Thelia\Model\Tools\PositionManagementTrait'])) { + throw new \InvalidArgumentException("Your model does not implement the PositionManagementTrait trait"); + } + + $object->setDispatcher($dispatcher !== null ? $dispatcher : $event->getDispatcher()); + + $mode = $event->getMode(); + + if ($mode == UpdatePositionEvent::POSITION_ABSOLUTE) { + $object->changeAbsolutePosition($event->getPosition()); + } elseif ($mode == UpdatePositionEvent::POSITION_UP) { + $object->movePositionUp(); + } elseif ($mode == UpdatePositionEvent::POSITION_DOWN) { + $object->movePositionDown(); + } + } + } + + /** + * @param ModelCriteria $query + * @param UpdatePositionEvent $event + * @param EventDispatcherInterface|null $dispatcher + * + * @since 2.3 + */ + protected function genericUpdateDelegatePosition(ModelCriteria $query, UpdatePositionEvent $event, EventDispatcherInterface $dispatcher = null) + { + if (null !== $object = $query->findOne()) { + if (!isset(class_uses($object)['Thelia\Model\Tools\PositionManagementTrait'])) { + throw new \InvalidArgumentException("Your model does not implement the PositionManagementTrait trait"); + } + + //$object->setDispatcher($dispatcher !== null ? $dispatcher : $event->getDispatcher()); + + $mode = $event->getMode(); + + if ($mode == UpdatePositionEvent::POSITION_ABSOLUTE) { + $object->changeAbsolutePosition($event->getPosition()); + } elseif ($mode == UpdatePositionEvent::POSITION_UP) { + $object->movePositionUp(); + } elseif ($mode == UpdatePositionEvent::POSITION_DOWN) { + $object->movePositionDown(); + } + } + } + + /** + * Changes SEO Fields for an object. + * + * @param ModelCriteria $query + * @param UpdateSeoEvent $event + * @param EventDispatcherInterface $dispatcher + * + * @return mixed an SEOxxx object + * @throws FormValidationException if a rewritten URL cannot be created + */ + protected function genericUpdateSeo(ModelCriteria $query, UpdateSeoEvent $event, EventDispatcherInterface $dispatcher = null) + { + if (null !== $object = $query->findPk($event->getObjectId())) { + $object + //for backward compatibility + ->setDispatcher($dispatcher !== null ? $dispatcher : $event->getDispatcher()) + + ->setLocale($event->getLocale()) + ->setMetaTitle($event->getMetaTitle()) + ->setMetaDescription($event->getMetaDescription()) + ->setMetaKeywords($event->getMetaKeywords()) + + ->save() + ; + + // Update the rewritten URL, if required + try { + $object->setRewrittenUrl($event->getLocale(), $event->getUrl()); + } catch (UrlRewritingException $e) { + throw new FormValidationException($e->getMessage(), $e->getCode()); + } + + $event->setObject($object); + } + + return $object; + } + + /** + * Toggle visibility for an object + * + * @param ModelCriteria $query + * @param ToggleVisibilityEvent $event + * @param EventDispatcherInterface $dispatcher + * + * @return mixed + */ + public function genericToggleVisibility(ModelCriteria $query, ToggleVisibilityEvent $event, EventDispatcherInterface $dispatcher = null) + { + if (null !== $object = $query->findPk($event->getObjectId())) { + $newVisibility = !$object->getVisible(); + $object + //for backward compatibility + ->setDispatcher($dispatcher !== null ? $dispatcher : $event->getDispatcher()) + ->setVisible($newVisibility) + ->save() + ; + + $event->setObject($object); + } + + return $object; + } +} diff --git a/core/lib/Thelia/Action/BaseCachedFile.php b/core/lib/Thelia/Action/BaseCachedFile.php new file mode 100644 index 00000000..ff146e51 --- /dev/null +++ b/core/lib/Thelia/Action/BaseCachedFile.php @@ -0,0 +1,290 @@ +), + * and cached in the web space (by default in web/local/). + * + * In the file cache directory, a subdirectory for files categories (eg. product, category, folder, etc.) is + * automatically created, and the cached file is created here. Plugin may use their own subdirectory as required. + * + * A copy (or symbolic link, by default) of the original file is created in the cache. + * + * @package Thelia\Action + * @author Franck Allimant + * + */ +abstract class BaseCachedFile extends BaseAction +{ + /** + * @var FileManager + */ + protected $fileManager; + + /** @var null|string */ + protected $cdnBaseUrl; + + public function __construct(FileManager $fileManager) + { + $this->fileManager = $fileManager; + + $this->cdnBaseUrl = ConfigQuery::read('cdn.documents-base-url', null); + } + + /** + * @return string root of the file cache directory in web space + */ + abstract protected function getCacheDirFromWebRoot(); + + /** + * @param string $url the fully qualified CDN URL that will be used to create doucments URL. + */ + public function setCdnBaseUrl($url) + { + $this->cdnBaseUrl = $url; + } + + /** + * Clear the file cache. Is a subdirectory is specified, only this directory is cleared. + * If no directory is specified, the whole cache is cleared. + * Only files are deleted, directories will remain. + * + * @param CachedFileEvent $event + */ + public function clearCache(CachedFileEvent $event) + { + $path = $this->getCachePath($event->getCacheSubdirectory(), false); + + $this->clearDirectory($path); + } + + /** + * Recursively clears the specified directory. + * + * @param string $path the directory path + */ + protected function clearDirectory($path) + { + $iterator = new \DirectoryIterator($path); + + /** @var \DirectoryIterator $fileinfo */ + foreach ($iterator as $fileinfo) { + if ($fileinfo->isDot()) { + continue; + } + + if ($fileinfo->isFile() || $fileinfo->isLink()) { + @unlink($fileinfo->getPathname()); + } elseif ($fileinfo->isDir()) { + $this->clearDirectory($fileinfo->getPathname()); + } + } + } + + /** + * Return the absolute URL to the cached file + * + * @param string $subdir the subdirectory related to cache base + * @param string $safe_filename the safe filename, as returned by getCacheFilePath() + * @return string the absolute URL to the cached file + */ + protected function getCacheFileURL($subdir, $safe_filename) + { + $path = $this->getCachePathFromWebRoot($subdir); + + return URL::getInstance()->absoluteUrl(sprintf("%s/%s", $path, $safe_filename), null, URL::PATH_TO_FILE, $this->cdnBaseUrl); + } + + /** + * Return the full path of the cached file + * + * @param string $subdir the subdirectory related to cache base + * @param string $filename the filename + * @param boolean $forceOriginalFile if true, the original file path in the cache dir is returned. + * @param string $hashed_options a hash of transformation options, or null if no transformations have been applied + * @return string the cache directory path relative to Web Root + */ + protected function getCacheFilePath($subdir, $filename, $forceOriginalFile = false, $hashed_options = null) + { + $path = $this->getCachePath($subdir); + + $safe_filename = preg_replace("[^:alnum:\-\._]", "-", strtolower(basename($filename))); + + // Keep original safe name if no tranformations are applied + if ($forceOriginalFile || $hashed_options == null) { + return sprintf("%s/%s", $path, $safe_filename); + } else { + return sprintf("%s/%s-%s", $path, $hashed_options, $safe_filename); + } + } + + /** + * Return the cache directory path relative to Web Root + * + * @param string $subdir the subdirectory related to cache base, or null to get the cache directory only. + * @return string the cache directory path relative to Web Root + */ + protected function getCachePathFromWebRoot($subdir = null) + { + $cache_dir_from_web_root = $this->getCacheDirFromWebRoot(); + + if ($subdir != null) { + $safe_subdir = basename($subdir); + + $path = sprintf("%s/%s", $cache_dir_from_web_root, $safe_subdir); + } else { + $path = $cache_dir_from_web_root; + } + + // Check if path is valid, e.g. in the cache dir + return $path; + } + + /** + * Return the absolute cache directory path + * + * @param string $subdir the subdirectory related to cache base, or null to get the cache base directory. + * @param bool $create_if_not_exists create the directory if it is not found + * + * @throws \RuntimeException if cache directory cannot be created + * @throws \InvalidArgumentException ii path is invalid, e.g. not in the cache dir + * + * @return string the absolute cache directory path + */ + protected function getCachePath($subdir = null, $create_if_not_exists = true) + { + $cache_base = $this->getCachePathFromWebRoot($subdir); + + $web_root = rtrim(THELIA_WEB_DIR, '/'); + + $path = sprintf("%s/%s", $web_root, $cache_base); + + // Create directory (recursively) if it does not exists. + if ($create_if_not_exists && !is_dir($path)) { + if (!@mkdir($path, 0777, true)) { + throw new \RuntimeException(sprintf("Failed to create %s file in cache directory", $path)); + } + } + + // Check if path is valid, e.g. in the cache dir + $cache_base = realpath(sprintf("%s/%s", $web_root, $this->getCachePathFromWebRoot())); + + if (strpos(realpath($path), $cache_base) !== 0) { + throw new \InvalidArgumentException(sprintf("Invalid cache path %s, with subdirectory %s", $path, $subdir)); + } + + return $path; + } + + /** + * Take care of saving a file in the database and file storage + * + * @param FileCreateOrUpdateEvent $event Image event + * + * @throws \Thelia\Exception\FileException|\Exception + * + */ + public function saveFile(FileCreateOrUpdateEvent $event) + { + $model = $event->getModel(); + $model->setFile(sprintf("tmp/%s", $event->getUploadedFile()->getFilename())); + $con = Propel::getWriteConnection(ProductImageTableMap::DATABASE_NAME); + $con->beginTransaction(); + + try { + $nbModifiedLines = $model->save($con); + $event->setModel($model); + + if (!$nbModifiedLines) { + throw new FileException( + sprintf( + 'File "%s" (type %s) with parent id %s failed to be saved', + $event->getParentName(), + \get_class($model), + $event->getParentId() + ) + ); + } + + $newUploadedFile = $this->fileManager->copyUploadedFile($event->getModel(), $event->getUploadedFile()); + + $event->setUploadedFile($newUploadedFile); + $con->commit(); + } catch (\Exception $e) { + $con->rollBack(); + + throw $e; + } + } + + /** + * Take care of updating file in the database and file storage + * + * @param FileCreateOrUpdateEvent $event Image event + * + * @throws \Thelia\Exception\FileException + */ + public function updateFile(FileCreateOrUpdateEvent $event) + { + // Copy and save file + if ($event->getUploadedFile()) { + // Remove old picture file from file storage + $url = $event->getModel()->getUploadDir() . '/' . $event->getOldModel()->getFile(); + unlink(str_replace('..', '', $url)); + + $newUploadedFile = $this->fileManager->copyUploadedFile($event->getModel(), $event->getUploadedFile()); + $event->setUploadedFile($newUploadedFile); + } + + // Update image modifications + $event->getModel()->save(); + + $event->setModel($event->getModel()); + } + + /** + * Deleting file in the database and in storage + * + * @param FileDeleteEvent $event Image event + */ + public function deleteFile(FileDeleteEvent $event) + { + $this->fileManager->deleteFile($event->getFileToDelete()); + } + + public function updatePosition(UpdateFilePositionEvent $event, $eventName, EventDispatcherInterface $dispatcher) + { + $this->genericUpdatePosition($event->getQuery(), $event, $dispatcher); + } + + public function toggleVisibility(FileToggleVisibilityEvent $event, $eventName, EventDispatcherInterface $dispatcher) + { + $this->genericToggleVisibility($event->getQuery(), $event, $dispatcher); + } +} diff --git a/core/lib/Thelia/Action/Brand.php b/core/lib/Thelia/Action/Brand.php new file mode 100644 index 00000000..690d4fb0 --- /dev/null +++ b/core/lib/Thelia/Action/Brand.php @@ -0,0 +1,175 @@ + + */ +class Brand extends BaseAction implements EventSubscriberInterface +{ + public function create(BrandCreateEvent $event) + { + $brand = new BrandModel(); + + $brand + ->setVisible($event->getVisible()) + ->setLocale($event->getLocale()) + ->setTitle($event->getTitle()) + ->save() + ; + + $event->setBrand($brand); + } + + /** + * process update brand + * + * @param BrandUpdateEvent $event + * @param $eventName + * @param EventDispatcherInterface $dispatcher + */ + public function update(BrandUpdateEvent $event, $eventName, EventDispatcherInterface $dispatcher) + { + if (null !== $brand = BrandQuery::create()->findPk($event->getBrandId())) { + $brand->setDispatcher($dispatcher); + + $brand + ->setVisible($event->getVisible()) + ->setLogoImageId(\intval($event->getLogoImageId()) == 0 ? null : $event->getLogoImageId()) + ->setLocale($event->getLocale()) + ->setTitle($event->getTitle()) + ->setDescription($event->getDescription()) + ->setChapo($event->getChapo()) + ->setPostscriptum($event->getPostscriptum()) + ->save() + ; + + $event->setBrand($brand); + } + } + + /** + * Toggle Brand visibility + * + * @param BrandToggleVisibilityEvent $event + * @param string $eventName + * @param EventDispatcherInterface $dispatcher + * @throws \Exception + * @throws \Propel\Runtime\Exception\PropelException + */ + public function toggleVisibility(BrandToggleVisibilityEvent $event, $eventName, EventDispatcherInterface $dispatcher) + { + $brand = $event->getBrand(); + + $brand + ->setDispatcher($dispatcher) + ->setVisible(!$brand->getVisible()) + ->save(); + + $event->setBrand($brand); + } + + /** + * Change Brand SEO + * + * @param UpdateSeoEvent $event + * @param $eventName + * @param EventDispatcherInterface $dispatcher + * @return Object + */ + public function updateSeo(UpdateSeoEvent $event, $eventName, EventDispatcherInterface $dispatcher) + { + return $this->genericUpdateSeo(BrandQuery::create(), $event, $dispatcher); + } + + public function delete(BrandDeleteEvent $event, $eventName, EventDispatcherInterface $dispatcher) + { + if (null !== $brand = BrandQuery::create()->findPk($event->getBrandId())) { + $brand->setDispatcher($dispatcher)->delete(); + + $event->setBrand($brand); + } + } + + public function updatePosition(UpdatePositionEvent $event, $eventName, EventDispatcherInterface $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} + */ + public static function getSubscribedEvents() + { + return array( + TheliaEvents::BRAND_CREATE => array('create', 128), + TheliaEvents::BRAND_UPDATE => array('update', 128), + TheliaEvents::BRAND_DELETE => array('delete', 128), + + TheliaEvents::BRAND_UPDATE_SEO => array('updateSeo', 128), + + TheliaEvents::BRAND_UPDATE_POSITION => array('updatePosition', 128), + TheliaEvents::BRAND_TOGGLE_VISIBILITY => array('toggleVisibility', 128), + + TheliaEvents::VIEW_CHECK => array('viewCheck', 128), + TheliaEvents::VIEW_BRAND_ID_NOT_VISIBLE => array('viewBrandIdNotVisible', 128), + ); + } +} diff --git a/core/lib/Thelia/Action/Cache.php b/core/lib/Thelia/Action/Cache.php new file mode 100644 index 00000000..e0dfedcc --- /dev/null +++ b/core/lib/Thelia/Action/Cache.php @@ -0,0 +1,96 @@ + + * @author Gilles Bourgeat + */ +class Cache extends BaseAction implements EventSubscriberInterface +{ + /** @var AdapterInterface */ + protected $adapter; + + /** + * @var CacheEvent[] + */ + protected $onTerminateCacheClearEvents = []; + + /** + * CacheListener constructor. + * @param AdapterInterface $adapter + */ + public function __construct(AdapterInterface $adapter) + { + $this->adapter = $adapter; + } + + public function cacheClear(CacheEvent $event) + { + if (!$event->isOnKernelTerminate()) { + $this->execCacheClear($event); + return; + } + + $findDir = false; + foreach ($this->onTerminateCacheClearEvents as $cacheEvent) { + if ($cacheEvent->getDir() === $event->getDir()) { + $findDir = true; + break; + } + } + + if (!$findDir) { + $this->onTerminateCacheClearEvents[] = $event; + } + } + + public function onTerminate() + { + foreach ($this->onTerminateCacheClearEvents as $cacheEvent) { + $this->execCacheClear($cacheEvent); + } + } + + protected function execCacheClear(CacheEvent $event) + { + $this->adapter->clear(); + + $dir = $event->getDir(); + + $fs = new Filesystem(); + $fs->remove($dir); + } + + /** + * {@inheritdoc} + */ + public static function getSubscribedEvents() + { + return array( + TheliaEvents::CACHE_CLEAR => ['cacheClear', 128], + KernelEvents::TERMINATE => ['onTerminate', 128], + ConsoleEvents::TERMINATE => ['onTerminate', 128] + ); + } +} diff --git a/core/lib/Thelia/Action/Cart.php b/core/lib/Thelia/Action/Cart.php new file mode 100644 index 00000000..c17ec65d --- /dev/null +++ b/core/lib/Thelia/Action/Cart.php @@ -0,0 +1,546 @@ + + */ +class Cart extends BaseAction implements EventSubscriberInterface +{ + /** @var RequestStack */ + protected $requestStack; + + /** @var TokenProvider */ + protected $tokenProvider; + + public function __construct(RequestStack $requestStack, TokenProvider $tokenProvider) + { + $this->requestStack = $requestStack; + + $this->tokenProvider = $tokenProvider; + } + + public function persistCart(CartPersistEvent $event) + { + $cart = $event->getCart(); + + if ($cart->isNew()) { + $cart + ->setToken($this->generateCartCookieIdentifier()) + ->save(); + $this->getSession()->setSessionCart($cart); + } + } + + /** + * add an article in the current cart + * + * @param \Thelia\Core\Event\Cart\CartEvent $event + * @param $eventName + * @param EventDispatcherInterface $dispatcher + */ + public function addItem(CartEvent $event, $eventName, EventDispatcherInterface $dispatcher) + { + $cart = $event->getCart(); + $newness = $event->getNewness(); + $append = $event->getAppend(); + $quantity = $event->getQuantity(); + $currency = $cart->getCurrency(); + $customer = $cart->getCustomer(); + $discount = 0; + + if ($cart->isNew()) { + $persistEvent = new CartPersistEvent($cart); + $dispatcher->dispatch(TheliaEvents::CART_PERSIST, $persistEvent); + } + + if (null !== $customer && $customer->getDiscount() > 0) { + $discount = $customer->getDiscount(); + } + + $productSaleElementsId = $event->getProductSaleElementsId(); + $productId = $event->getProduct(); + + // Search for an identical item in the cart + $findItemEvent = clone $event; + + $dispatcher->dispatch(TheliaEvents::CART_FINDITEM, $findItemEvent); + + $cartItem = $findItemEvent->getCartItem(); + + if ($cartItem === null || $newness) { + $productSaleElements = ProductSaleElementsQuery::create()->findPk($productSaleElementsId); + + if (null !== $productSaleElements) { + $productPrices = $productSaleElements->getPricesByCurrency($currency, $discount); + + $cartItem = $this->doAddItem($dispatcher, $cart, $productId, $productSaleElements, $quantity, $productPrices); + } + } elseif ($append && $cartItem !== null) { + $cartItem->addQuantity($quantity)->save(); + } + + $event->setCartItem($cartItem); + } + + /** + * + * Delete specify article present into cart + * + * @param \Thelia\Core\Event\Cart\CartEvent $event + */ + public function deleteItem(CartEvent $event) + { + if (null !== $cartItemId = $event->getCartItemId()) { + $cart = $event->getCart(); + CartItemQuery::create() + ->filterByCartId($cart->getId()) + ->filterById($cartItemId) + ->delete(); + + // Force an update of the Cart object to provide + // to other listeners an updated CartItem collection. + $cart->clearCartItems(); + } + } + + /** + * Clear the cart + * @param CartEvent $event + */ + public function clear(CartEvent $event) + { + if (null !== $cart = $event->getCart()) { + $cart->delete(); + } + } + + /** + * + * Modify article's quantity + * + * don't use Form here just test the Request. + * + * @param \Thelia\Core\Event\Cart\CartEvent $event + * @param $eventName + * @param EventDispatcherInterface $dispatcher + */ + public function changeItem(CartEvent $event, $eventName, EventDispatcherInterface $dispatcher) + { + if ((null !== $cartItemId = $event->getCartItemId()) && (null !== $quantity = $event->getQuantity())) { + $cart = $event->getCart(); + + $cartItem = CartItemQuery::create() + ->filterByCartId($cart->getId()) + ->filterById($cartItemId) + ->findOne(); + + if ($cartItem) { + $event->setCartItem( + $this->updateQuantity($dispatcher, $cartItem, $quantity) + ); + } + } + } + + public function updateCart(CurrencyChangeEvent $event, $eventName, EventDispatcherInterface $dispatcher) + { + $cart = $event->getRequest()->getSession()->getSessionCart($dispatcher); + + if (null !== $cart) { + $this->updateCartPrices($cart, $event->getCurrency()); + } + } + + /** + * + * Refresh article's price + * + * @param \Thelia\Model\Cart $cart + * @param \Thelia\Model\Currency $currency + */ + public function updateCartPrices(CartModel $cart, CurrencyModel $currency) + { + $customer = $cart->getCustomer(); + $discount = 0; + + if (null !== $customer && $customer->getDiscount() > 0) { + $discount = $customer->getDiscount(); + } + + // cart item + foreach ($cart->getCartItems() as $cartItem) { + $productSaleElements = $cartItem->getProductSaleElements(); + + $productPrice = $productSaleElements->getPricesByCurrency($currency, $discount); + + $cartItem + ->setPrice($productPrice->getPrice()) + ->setPromoPrice($productPrice->getPromoPrice()); + + $cartItem->save(); + } + + // update the currency cart + $cart->setCurrencyId($currency->getId()); + $cart->save(); + } + + /** + * increase the quantity for an existing cartItem + * + * @param EventDispatcherInterface $dispatcher + * @param CartItem $cartItem + * @param float $quantity + * + * @throws \Exception + * @throws \Propel\Runtime\Exception\PropelException + * @return CartItem + */ + protected function updateQuantity(EventDispatcherInterface $dispatcher, CartItem $cartItem, $quantity) + { + $cartItem->setDisptacher($dispatcher); + $cartItem->updateQuantity($quantity) + ->save(); + + return $cartItem; + } + + /** + * try to attach a new item to an existing cart + * + * @param EventDispatcherInterface $dispatcher + * @param \Thelia\Model\Cart $cart + * @param int $productId + * @param ProductSaleElements $productSaleElements + * @param float $quantity + * @param ProductPriceTools $productPrices + * + * @return CartItem + */ + protected function doAddItem( + EventDispatcherInterface $dispatcher, + CartModel $cart, + $productId, + ProductSaleElements $productSaleElements, + $quantity, + ProductPriceTools $productPrices + ) { + $cartItem = new CartItem(); + $cartItem->setDisptacher($dispatcher); + $cartItem + ->setCart($cart) + ->setProductId($productId) + ->setProductSaleElementsId($productSaleElements->getId()) + ->setQuantity($quantity) + ->setPrice($productPrices->getPrice()) + ->setPromoPrice($productPrices->getPromoPrice()) + ->setPromo($productSaleElements->getPromo()) + ->setPriceEndOfLife(time() + ConfigQuery::read("cart.priceEOF", 60*60*24*30)) + ->save(); + + return $cartItem; + } + + /** + * find a specific record in CartItem table using the Cart id, the product id + * and the product_sale_elements id + * + * @param int $cartId + * @param int $productId + * @param int $productSaleElementsId + * @return CartItem + * + * @deprecated this method is deprecated. Dispatch a TheliaEvents::CART_FINDITEM instead + */ + protected function findItem($cartId, $productId, $productSaleElementsId) + { + return CartItemQuery::create() + ->filterByCartId($cartId) + ->filterByProductId($productId) + ->filterByProductSaleElementsId($productSaleElementsId) + ->findOne(); + } + + /** + * Find a specific record in CartItem table using the current CartEvent + * + * @param CartEvent $event the cart event + */ + public function findCartItem(CartEvent $event) + { + // 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()) + ->filterByProductId($event->getProduct()) + ->filterByProductSaleElementsId($event->getProductSaleElementsId()) + ->findOne()) { + $event->setCartItem($foundItem); + } + } + + /** + * Search if cart already exists in session. If not try to restore it from the cart cookie, + * or duplicate an old one. + * + * @param CartRestoreEvent $cartRestoreEvent + * @param $eventName + * @param EventDispatcherInterface $dispatcher + */ + public function restoreCurrentCart(CartRestoreEvent $cartRestoreEvent, $eventName, EventDispatcherInterface $dispatcher) + { + $cookieName = ConfigQuery::read("cart.cookie_name", 'thelia_cart'); + $persistentCookie = ConfigQuery::read("cart.use_persistent_cookie", 1); + + $cart = null; + + if ($this->requestStack->getCurrentRequest()->cookies->has($cookieName) && $persistentCookie) { + $cart = $this->managePersistentCart($cartRestoreEvent, $cookieName, $dispatcher); + } elseif (!$persistentCookie) { + $cart = $this->manageNonPersistentCookie($cartRestoreEvent, $dispatcher); + } + + // Still no cart ? Create a new one. + if (null === $cart) { + $cart = $this->dispatchNewCart($dispatcher); + } + + $cartRestoreEvent->setCart($cart); + } + + /** + * The cart token is not saved in a cookie, if the cart is present in session, we just change the customer id + * if needed or create duplicate the current cart if the customer is not the same as customer already present in + * the cart. + * + * @param CartRestoreEvent $cartRestoreEvent + * @param EventDispatcherInterface $dispatcher + * @return CartModel + * @throws \Exception + * @throws \Propel\Runtime\Exception\PropelException + */ + protected function manageNonPersistentCookie(CartRestoreEvent $cartRestoreEvent, EventDispatcherInterface $dispatcher) + { + $cart = $cartRestoreEvent->getCart(); + + if (null === $cart) { + $cart = $this->dispatchNewCart($dispatcher); + } else { + $cart = $this->manageCartDuplicationAtCustomerLogin($cart, $dispatcher); + } + + return $cart; + } + + /** + * + * The cart token is saved in a cookie so we try to retrieve it. Then the customer is checked. + * + * @param CartRestoreEvent $cartRestoreEvent + * @param $cookieName + * @param EventDispatcherInterface $dispatcher + * @return CartModel + * @throws \Exception + * @throws \Propel\Runtime\Exception\PropelException + */ + protected function managePersistentCart(CartRestoreEvent $cartRestoreEvent, $cookieName, EventDispatcherInterface $dispatcher) + { + // The cart cookie exists -> get the cart token + $token = $this->requestStack->getCurrentRequest()->cookies->get($cookieName); + + // Check if a cart exists for this token + if (null !== $cart = CartQuery::create()->findOneByToken($token)) { + $cart = $this->manageCartDuplicationAtCustomerLogin($cart, $dispatcher); + } + + return $cart; + } + + protected function manageCartDuplicationAtCustomerLogin(CartModel $cart, EventDispatcherInterface $dispatcher) + { + /** @var CustomerModel $customer */ + if (null !== $customer = $this->getSession()->getCustomerUser()) { + // Check if we have to duplicate the existing cart. + + $duplicateCart = true; + + // A customer is logged in. + if (null === $cart->getCustomerId()) { + // If the customer has a discount, whe have to duplicate the cart, + // so that the discount will be applied to the products in cart. + + if (0 === $customer->getDiscount() || 0 === $cart->countCartItems()) { + // If no discount, or an empty cart, there's no need to duplicate. + $duplicateCart = false; + } + } + + if ($duplicateCart) { + // Duplicate the cart + $cart = $this->duplicateCart($dispatcher, $cart, $customer); + } else { + // No duplication required, just assign the cart to the customer + $cart->setCustomerId($customer->getId())->save(); + } + } elseif ($cart->getCustomerId() != null) { + // The cart belongs to another user + if (0 === $cart->countCartItems()) { + // No items in cart, assign it to nobody. + $cart->setCustomerId(null)->save(); + } else { + // Some itemls in cart, duplicate it without assigning a customer ID. + $cart = $this->duplicateCart($dispatcher, $cart); + } + } + + return $cart; + } + + /** + * @param EventDispatcherInterface $dispatcher + * @return CartModel + */ + protected function dispatchNewCart(EventDispatcherInterface $dispatcher) + { + $cartCreateEvent = new CartCreateEvent(); + + $dispatcher->dispatch(TheliaEvents::CART_CREATE_NEW, $cartCreateEvent); + + return $cartCreateEvent->getCart(); + } + + /** + * Create a new, empty cart object, and assign it to the current customer, if any. + * + * @param CartCreateEvent $cartCreateEvent + */ + public function createEmptyCart(CartCreateEvent $cartCreateEvent) + { + $cart = new CartModel(); + + $cart->setCurrency($this->getSession()->getCurrency(true)); + + /** @var CustomerModel $customer */ + if (null !== $customer = $this->getSession()->getCustomerUser()) { + $cart->setCustomer(CustomerQuery::create()->findPk($customer->getId())); + } + + $this->getSession()->setSessionCart($cart); + + if (ConfigQuery::read("cart.use_persistent_cookie", 1) == 1) { + // set cart_use_cookie to "" to remove the cart cookie + // see Thelia\Core\EventListener\ResponseListener + $this->getSession()->set("cart_use_cookie", ""); + } + + $cartCreateEvent->setCart($cart); + } + + /** + * Duplicate an existing Cart. If a customer ID is provided the created cart will be attached to this customer. + * + * @param EventDispatcherInterface $dispatcher + * @param CartModel $cart + * @param CustomerModel $customer + * @return CartModel + */ + protected function duplicateCart(EventDispatcherInterface $dispatcher, CartModel $cart, CustomerModel $customer = null) + { + $newCart = $cart->duplicate( + $this->generateCartCookieIdentifier(), + $customer, + $this->getSession()->getCurrency(), + $dispatcher + ); + + $cartEvent = new CartDuplicationEvent($newCart, $cart); + $dispatcher->dispatch(TheliaEvents::CART_DUPLICATE, $cartEvent); + + return $cartEvent->getDuplicatedCart(); + } + + /** + * Generate the cart cookie identifier, or return null if the cart is only managed in the session object, + * not in a client cookie. + * + * @return string + */ + protected function generateCartCookieIdentifier() + { + $id = null; + + if (ConfigQuery::read("cart.use_persistent_cookie", 1) == 1) { + $id = $this->tokenProvider->getToken(); + $this->getSession()->set('cart_use_cookie', $id); + } + + return $id; + } + + /** + * {@inheritdoc} + */ + public static function getSubscribedEvents() + { + return array( + TheliaEvents::CART_PERSIST => array("persistCart", 128), + TheliaEvents::CART_RESTORE_CURRENT => array("restoreCurrentCart", 128), + TheliaEvents::CART_CREATE_NEW => array("createEmptyCart", 128), + TheliaEvents::CART_ADDITEM => array("addItem", 128), + TheliaEvents::CART_FINDITEM => array("findCartItem", 128), + TheliaEvents::CART_DELETEITEM => array("deleteItem", 128), + TheliaEvents::CART_UPDATEITEM => array("changeItem", 128), + TheliaEvents::CART_CLEAR => array("clear", 128), + TheliaEvents::CHANGE_DEFAULT_CURRENCY => array("updateCart", 128), + ); + } + + /** + * Returns the session from the current request + * + * @return \Thelia\Core\HttpFoundation\Session\Session + */ + protected function getSession() + { + return $this->requestStack->getCurrentRequest()->getSession(); + } +} diff --git a/core/lib/Thelia/Action/Category.php b/core/lib/Thelia/Action/Category.php new file mode 100644 index 00000000..382847f0 --- /dev/null +++ b/core/lib/Thelia/Action/Category.php @@ -0,0 +1,268 @@ +setDispatcher($dispatcher) + + ->setLocale($event->getLocale()) + ->setParent($event->getParent()) + ->setVisible($event->getVisible()) + ->setTitle($event->getTitle()) + + ->save() + ; + + $event->setCategory($category); + } + + /** + * Change a category + * + * @param \Thelia\Core\Event\Category\CategoryUpdateEvent $event + * @param $eventName + * @param EventDispatcherInterface $dispatcher + */ + public function update(CategoryUpdateEvent $event, $eventName, EventDispatcherInterface $dispatcher) + { + if (null !== $category = CategoryQuery::create()->findPk($event->getCategoryId())) { + $category + ->setDispatcher($dispatcher) + ->setDefaultTemplateId($event->getDefaultTemplateId() == 0 ? null : $event->getDefaultTemplateId()) + ->setLocale($event->getLocale()) + ->setTitle($event->getTitle()) + ->setDescription($event->getDescription()) + ->setChapo($event->getChapo()) + ->setPostscriptum($event->getPostscriptum()) + + ->setParent($event->getParent()) + ->setVisible($event->getVisible()) + + ->save(); + + $event->setCategory($category); + } + } + + /** + * Change a Category SEO + * + * @param UpdateSeoEvent $event + * @param $eventName + * @param EventDispatcherInterface $dispatcher + * @return Object + */ + public function updateSeo(UpdateSeoEvent $event, $eventName, EventDispatcherInterface $dispatcher) + { + return $this->genericUpdateSeo(CategoryQuery::create(), $event, $dispatcher); + } + + /** + * Delete a category entry + * + * @param \Thelia\Core\Event\Category\CategoryDeleteEvent $event + * @param $eventName + * @param EventDispatcherInterface $dispatcher + * @throws \Exception + */ + public function delete(CategoryDeleteEvent $event, $eventName, EventDispatcherInterface $dispatcher) + { + if (null !== $category = CategoryQuery::create()->findPk($event->getCategoryId())) { + $con = Propel::getWriteConnection(CategoryTableMap::DATABASE_NAME); + $con->beginTransaction(); + + try { + $fileList = ['images' => [], 'documentList' => []]; + + // Get category's files to delete after category deletion + $fileList['images']['list'] = CategoryImageQuery::create() + ->findByCategoryId($event->getCategoryId()); + $fileList['images']['type'] = TheliaEvents::IMAGE_DELETE; + + $fileList['documentList']['list'] = CategoryDocumentQuery::create() + ->findByCategoryId($event->getCategoryId()); + $fileList['documentList']['type'] = TheliaEvents::DOCUMENT_DELETE; + + // Delete category + $category + ->setDispatcher($dispatcher) + ->delete($con); + + $event->setCategory($category); + + // Dispatch delete category's files event + foreach ($fileList as $fileTypeList) { + foreach ($fileTypeList['list'] as $fileToDelete) { + $fileDeleteEvent = new FileDeleteEvent($fileToDelete); + $dispatcher->dispatch($fileTypeList['type'], $fileDeleteEvent); + } + } + + $con->commit(); + } catch (\Exception $e) { + $con->rollback(); + throw $e; + } + } + } + + /** + * Toggle category visibility. No form used here + * + * @param CategoryToggleVisibilityEvent $event + * @param $eventName + * @param EventDispatcherInterface $dispatcher + */ + public function toggleVisibility(CategoryToggleVisibilityEvent $event, $eventName, EventDispatcherInterface $dispatcher) + { + $category = $event->getCategory(); + + $category + ->setDispatcher($dispatcher) + ->setVisible($category->getVisible() ? false : true) + ->save() + ; + + $event->setCategory($category); + } + + /** + * Changes position, selecting absolute ou relative change. + * + * @param UpdatePositionEvent $event + * @param $eventName + * @param EventDispatcherInterface $dispatcher + */ + public function updatePosition(UpdatePositionEvent $event, $eventName, EventDispatcherInterface $dispatcher) + { + $this->genericUpdatePosition(CategoryQuery::create(), $event, $dispatcher); + } + + public function addContent(CategoryAddContentEvent $event, $eventName, EventDispatcherInterface $dispatcher) + { + if (CategoryAssociatedContentQuery::create() + ->filterByContentId($event->getContentId()) + ->filterByCategory($event->getCategory())->count() <= 0) { + $content = new CategoryAssociatedContent(); + + $content + ->setDispatcher($dispatcher) + ->setCategory($event->getCategory()) + ->setContentId($event->getContentId()) + ->save() + ; + } + } + + public function removeContent(CategoryDeleteContentEvent $event, $eventName, EventDispatcherInterface $dispatcher) + { + $content = CategoryAssociatedContentQuery::create() + ->filterByContentId($event->getContentId()) + ->filterByCategory($event->getCategory())->findOne() + ; + + if ($content !== null) { + $content + ->setDispatcher($dispatcher) + ->delete(); + } + } + + /** + * 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} + */ + public static function getSubscribedEvents() + { + return array( + TheliaEvents::CATEGORY_CREATE => array("create", 128), + TheliaEvents::CATEGORY_UPDATE => array("update", 128), + TheliaEvents::CATEGORY_DELETE => array("delete", 128), + TheliaEvents::CATEGORY_TOGGLE_VISIBILITY => array("toggleVisibility", 128), + + TheliaEvents::CATEGORY_UPDATE_POSITION => array("updatePosition", 128), + TheliaEvents::CATEGORY_UPDATE_SEO => array("updateSeo", 128), + + TheliaEvents::CATEGORY_ADD_CONTENT => array("addContent", 128), + TheliaEvents::CATEGORY_REMOVE_CONTENT => array("removeContent", 128), + + TheliaEvents::VIEW_CHECK => array('viewCheck', 128), + TheliaEvents::VIEW_CATEGORY_ID_NOT_VISIBLE => array('viewcategoryIdNotVisible', 128), + ); + } +} diff --git a/core/lib/Thelia/Action/Config.php b/core/lib/Thelia/Action/Config.php new file mode 100644 index 00000000..2b4e3cdc --- /dev/null +++ b/core/lib/Thelia/Action/Config.php @@ -0,0 +1,128 @@ +setDispatcher($dispatcher) + ->setName($event->getEventName()) + ->setValue($event->getValue()) + ->setLocale($event->getLocale()) + ->setTitle($event->getTitle()) + ->setHidden($event->getHidden()) + ->setSecured($event->getSecured()) + ->save(); + + $event->setConfig($config); + } + + /** + * Change a configuration entry value + * + * @param \Thelia\Core\Event\Config\ConfigUpdateEvent $event + * @param $eventName + * @param EventDispatcherInterface $dispatcher + */ + public function setValue(ConfigUpdateEvent $event, $eventName, EventDispatcherInterface $dispatcher) + { + if (null !== $config = ConfigQuery::create()->findPk($event->getConfigId())) { + if ($event->getValue() !== $config->getValue()) { + $config->setDispatcher($dispatcher)->setValue($event->getValue())->save(); + + $event->setConfig($config); + } + } + } + + /** + * Change a configuration entry + * + * @param \Thelia\Core\Event\Config\ConfigUpdateEvent $event + * @param $eventName + * @param EventDispatcherInterface $dispatcher + */ + public function modify(ConfigUpdateEvent $event, $eventName, EventDispatcherInterface $dispatcher) + { + if (null !== $config = ConfigQuery::create()->findPk($event->getConfigId())) { + $config->setDispatcher($dispatcher) + ->setName($event->getEventName()) + ->setValue($event->getValue()) + ->setHidden($event->getHidden()) + ->setSecured($event->getSecured()) + ->setLocale($event->getLocale()) + ->setTitle($event->getTitle()) + ->setDescription($event->getDescription()) + ->setChapo($event->getChapo()) + ->setPostscriptum($event->getPostscriptum()) + ->save(); + + $event->setConfig($config); + } + } + + /** + * Delete a configuration entry + * + * @param \Thelia\Core\Event\Config\ConfigDeleteEvent $event + * @param $eventName + * @param EventDispatcherInterface $dispatcher + */ + public function delete(ConfigDeleteEvent $event, $eventName, EventDispatcherInterface $dispatcher) + { + if (null !== ($config = ConfigQuery::create()->findPk($event->getConfigId()))) { + if (!$config->getSecured()) { + $config->setDispatcher($dispatcher)->delete(); + + $event->setConfig($config); + } + } + } + + /** + * {@inheritDoc} + */ + public static function getSubscribedEvents() + { + return array( + TheliaEvents::CONFIG_CREATE => array( + "create", 128 + ), TheliaEvents::CONFIG_SETVALUE => array( + "setValue", 128 + ), TheliaEvents::CONFIG_UPDATE => array( + "modify", 128 + ), TheliaEvents::CONFIG_DELETE => array( + "delete", 128 + ), + ); + } +} diff --git a/core/lib/Thelia/Action/Content.php b/core/lib/Thelia/Action/Content.php new file mode 100644 index 00000000..96e3c6ab --- /dev/null +++ b/core/lib/Thelia/Action/Content.php @@ -0,0 +1,263 @@ + + */ +class Content extends BaseAction implements EventSubscriberInterface +{ + public function create(ContentCreateEvent $event, $eventName, EventDispatcherInterface $dispatcher) + { + $content = (new ContentModel) + ->setDispatcher($dispatcher) + ->setVisible($event->getVisible()) + ->setLocale($event->getLocale()) + ->setTitle($event->getTitle()) + ->create($event->getDefaultFolder()) + ; + + $event->setContent($content); + } + + /** + * process update content + * + * @param ContentUpdateEvent $event + * @param $eventName + * @param EventDispatcherInterface $dispatcher + * @throws PropelException + * @throws \Exception + */ + public function update(ContentUpdateEvent $event, $eventName, EventDispatcherInterface $dispatcher) + { + if (null !== $content = ContentQuery::create()->findPk($event->getContentId())) { + $con = Propel::getWriteConnection(ContentTableMap::DATABASE_NAME); + $con->beginTransaction(); + + $content->setDispatcher($dispatcher); + try { + $content + ->setVisible($event->getVisible()) + ->setLocale($event->getLocale()) + ->setTitle($event->getTitle()) + ->setDescription($event->getDescription()) + ->setChapo($event->getChapo()) + ->setPostscriptum($event->getPostscriptum()) + ->save($con) + ; + + $content->setDefaultFolder($event->getDefaultFolder()); + + $event->setContent($content); + $con->commit(); + } catch (PropelException $e) { + $con->rollBack(); + throw $e; + } + } + } + + /** + * Change Content SEO + * + * @param UpdateSeoEvent $event + * @param $eventName + * @param EventDispatcherInterface $dispatcher + * @return Object + */ + public function updateSeo(UpdateSeoEvent $event, $eventName, EventDispatcherInterface $dispatcher) + { + return $this->genericUpdateSeo(ContentQuery::create(), $event, $dispatcher); + } + + public function updatePosition(UpdatePositionEvent $event, $eventName, EventDispatcherInterface $dispatcher) + { + $this->genericUpdateDelegatePosition( + ContentFolderQuery::create() + ->filterByContentId($event->getObjectId()) + ->filterByFolderId($event->getReferrerId()), + $event, + $dispatcher + ); + } + + public function toggleVisibility(ContentToggleVisibilityEvent $event, $eventName, EventDispatcherInterface $dispatcher) + { + $content = $event->getContent(); + + $content + ->setDispatcher($dispatcher) + ->setVisible(!$content->getVisible()) + ->save(); + + $event->setContent($content); + } + + public function delete(ContentDeleteEvent $event, $eventName, EventDispatcherInterface $dispatcher) + { + if (null !== $content = ContentQuery::create()->findPk($event->getContentId())) { + $con = Propel::getWriteConnection(ContentTableMap::DATABASE_NAME); + $con->beginTransaction(); + + try { + $fileList = ['images' => [], 'documentList' => []]; + + $defaultFolderId = $content->getDefaultFolderId(); + + // Get content's files to delete after content deletion + $fileList['images']['list'] = ContentImageQuery::create() + ->findByContentId($event->getContentId()); + $fileList['images']['type'] = TheliaEvents::IMAGE_DELETE; + + $fileList['documentList']['list'] = ContentDocumentQuery::create() + ->findByContentId($event->getContentId()); + $fileList['documentList']['type'] = TheliaEvents::DOCUMENT_DELETE; + + // Delete content + $content->setDispatcher($dispatcher) + ->delete($con); + + $event->setDefaultFolderId($defaultFolderId); + $event->setContent($content); + + // Dispatch delete content's files event + foreach ($fileList as $fileTypeList) { + foreach ($fileTypeList['list'] as $fileToDelete) { + $fileDeleteEvent = new FileDeleteEvent($fileToDelete); + $dispatcher->dispatch($fileTypeList['type'], $fileDeleteEvent); + } + } + + $con->commit(); + } catch (\Exception $e) { + $con->rollback(); + throw $e; + } + } + } + + /** + * + * associate a folder to a content if the association already does not exists + * + * @param ContentAddFolderEvent $event + */ + public function addFolder(ContentAddFolderEvent $event) + { + if (ContentFolderQuery::create() + ->filterByContent($event->getContent()) + ->filterByFolderId($event->getFolderId()) + ->count() <= 0 + ) { + $contentFolder = (new ContentFolder()) + ->setFolderId($event->getFolderId()) + ->setContent($event->getContent()) + ->setDefaultFolder(false); + + $contentFolder + ->setPosition($contentFolder->getNextPosition()) + ->save(); + } + } + + public function removeFolder(ContentRemoveFolderEvent $event) + { + $contentFolder = ContentFolderQuery::create() + ->filterByContent($event->getContent()) + ->filterByFolderId($event->getFolderId()) + ->findOne(); + + if (null !== $contentFolder) { + $contentFolder->delete(); + } + } + + /** + * 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} + */ + public static function getSubscribedEvents() + { + return array( + TheliaEvents::CONTENT_CREATE => array('create', 128), + TheliaEvents::CONTENT_UPDATE => array('update', 128), + TheliaEvents::CONTENT_DELETE => array('delete', 128), + TheliaEvents::CONTENT_TOGGLE_VISIBILITY => array('toggleVisibility', 128), + + TheliaEvents::CONTENT_UPDATE_POSITION => array('updatePosition', 128), + TheliaEvents::CONTENT_UPDATE_SEO => array('updateSeo', 128), + + TheliaEvents::CONTENT_ADD_FOLDER => array('addFolder', 128), + TheliaEvents::CONTENT_REMOVE_FOLDER => array('removeFolder', 128), + + TheliaEvents::VIEW_CHECK => array('viewCheck', 128), + TheliaEvents::VIEW_CONTENT_ID_NOT_VISIBLE => array('viewContentIdNotVisible', 128), + ); + } +} diff --git a/core/lib/Thelia/Action/Country.php b/core/lib/Thelia/Action/Country.php new file mode 100644 index 00000000..898d9416 --- /dev/null +++ b/core/lib/Thelia/Action/Country.php @@ -0,0 +1,121 @@ + + */ +class Country extends BaseAction implements EventSubscriberInterface +{ + public function create(CountryCreateEvent $event) + { + $country = new CountryModel(); + + $country + ->setVisible($event->isVisible()) + ->setIsocode($event->getIsocode()) + ->setIsoalpha2($event->getIsoAlpha2()) + ->setIsoalpha3($event->getIsoAlpha3()) + ->setHasStates($event->isHasStates()) + ->setLocale($event->getLocale()) + ->setTitle($event->getTitle()) + ->save(); + + $event->setCountry($country); + } + + public function update(CountryUpdateEvent $event) + { + if (null !== $country = CountryQuery::create()->findPk($event->getCountryId())) { + $country + ->setVisible($event->isVisible()) + ->setIsocode($event->getIsocode()) + ->setIsoalpha2($event->getIsoAlpha2()) + ->setIsoalpha3($event->getIsoAlpha3()) + ->setHasStates($event->isHasStates()) + ->setNeedZipCode($event->isNeedZipCode()) + ->setZipCodeFormat($event->getZipCodeFormat()) + ->setLocale($event->getLocale()) + ->setTitle($event->getTitle()) + ->setChapo($event->getChapo()) + ->setDescription($event->getDescription()) + ->save(); + + $event->setCountry($country); + } + } + + public function delete(CountryDeleteEvent $event) + { + if (null !== $country = CountryQuery::create()->findPk($event->getCountryId())) { + $country->delete(); + + $event->setCountry($country); + } + } + + public function toggleDefault(CountryToggleDefaultEvent $event) + { + if (null !== $country = CountryQuery::create()->findPk($event->getCountryId())) { + $country->toggleDefault(); + + $event->setCountry($country); + } + } + + /** + * Toggle Country visibility + * + * @param CountryToggleVisibilityEvent $event + * @param $eventName + * @param EventDispatcherInterface $dispatcher + */ + public function toggleVisibility(CountryToggleVisibilityEvent $event, $eventName, EventDispatcherInterface $dispatcher) + { + $country = $event->getCountry(); + + $country + ->setDispatcher($dispatcher) + ->setVisible(!$country->getVisible()) + ->save(); + + $event->setCountry($country); + } + + /** + * {@inheritdoc} + */ + public static function getSubscribedEvents() + { + return array( + TheliaEvents::COUNTRY_CREATE => array('create', 128), + TheliaEvents::COUNTRY_UPDATE => array('update', 128), + TheliaEvents::COUNTRY_DELETE => array('delete', 128), + TheliaEvents::COUNTRY_TOGGLE_DEFAULT => array('toggleDefault', 128), + TheliaEvents::COUNTRY_TOGGLE_VISIBILITY => array('toggleVisibility', 128) + ); + } +} diff --git a/core/lib/Thelia/Action/Coupon.php b/core/lib/Thelia/Action/Coupon.php new file mode 100644 index 00000000..0f6b3a28 --- /dev/null +++ b/core/lib/Thelia/Action/Coupon.php @@ -0,0 +1,466 @@ +, Franck Allimant + * + */ +class Coupon extends BaseAction implements EventSubscriberInterface +{ + /** @var RequestStack */ + protected $requestStack; + + /** @var CouponFactory $couponFactory */ + protected $couponFactory; + + /** @var CouponManager $couponManager */ + protected $couponManager; + + /** @var ConditionInterface $noConditionRule */ + protected $noConditionRule; + + /** @var ConditionFactory $conditionFactory */ + protected $conditionFactory; + + public function __construct( + RequestStack $requestStack, + CouponFactory $couponFactory, + CouponManager $couponManager, + ConditionInterface $noConditionRule, + ConditionFactory $conditionFactory + ) { + $this->requestStack = $requestStack; + $this->couponFactory = $couponFactory; + $this->couponManager = $couponManager; + $this->noConditionRule = $noConditionRule; + $this->conditionFactory = $conditionFactory; + } + + /** + * Occurring when a Coupon is about to be created + * + * @param CouponCreateOrUpdateEvent $event Event creation or update Coupon + * @param $eventName + * @param EventDispatcherInterface $dispatcher + */ + public function create(CouponCreateOrUpdateEvent $event, $eventName, EventDispatcherInterface $dispatcher) + { + $coupon = new CouponModel(); + + $this->createOrUpdate($coupon, $event, $dispatcher); + } + + /** + * Occurring when a Coupon is about to be updated + * + * @param CouponCreateOrUpdateEvent $event Event creation or update Coupon + * @param $eventName + * @param EventDispatcherInterface $dispatcher + */ + public function update(CouponCreateOrUpdateEvent $event, $eventName, EventDispatcherInterface $dispatcher) + { + $coupon = $event->getCouponModel(); + + $this->createOrUpdate($coupon, $event, $dispatcher); + } + + public function delete(CouponDeleteEvent $event) + { + $coupon = $event->getCoupon(); + + if (null === $coupon) { + throw new \InvalidArgumentException( + sprintf( + "The coupon id '%d' doesn't exist", + $event->getCouponId() + ) + ); + } + + $coupon->delete(); + + $event->setCoupon(null); + } + + /** + * Occurring when a Coupon condition is about to be updated + * + * @param CouponCreateOrUpdateEvent $event Event creation or update Coupon condition + * @param $eventName + * @param EventDispatcherInterface $dispatcher + */ + public function updateCondition(CouponCreateOrUpdateEvent $event, $eventName, EventDispatcherInterface $dispatcher) + { + $modelCoupon = $event->getCouponModel(); + + $this->createOrUpdateCondition($modelCoupon, $event, $dispatcher); + } + + /** + * Clear all coupons in session. + * + * @param Event $event + * @param $eventName + * @param EventDispatcherInterface $dispatcher + */ + public function clearAllCoupons(Event $event, $eventName, EventDispatcherInterface $dispatcher) + { + // Tell coupons to clear any data they may have stored + $this->couponManager->clear(); + + $this->getSession()->setConsumedCoupons(array()); + + $this->updateOrderDiscount($event, $eventName, $dispatcher); + } + + /** + * Occurring when a Coupon condition is about to be consumed + * + * @param CouponConsumeEvent $event Event consuming Coupon + * @param $eventName + * @param EventDispatcherInterface $dispatcher + */ + public function consume(CouponConsumeEvent $event, $eventName, EventDispatcherInterface $dispatcher) + { + $totalDiscount = 0; + $isValid = false; + + /** @var CouponInterface $coupon */ + $coupon = $this->couponFactory->buildCouponFromCode($event->getCode()); + + if ($coupon) { + $isValid = $coupon->isMatching(); + + if ($isValid) { + $this->couponManager->pushCouponInSession($event->getCode()); + $totalDiscount = $this->couponManager->getDiscount(); + + $this->getSession() + ->getSessionCart($dispatcher) + ->setDiscount($totalDiscount) + ->save(); + + $this->getSession() + ->getOrder() + ->setDiscount($totalDiscount) + ; + } + } + + $event->setIsValid($isValid); + $event->setDiscount($totalDiscount); + } + + public function updateOrderDiscount(Event $event, $eventName, EventDispatcherInterface $dispatcher) + { + $discount = $this->couponManager->getDiscount(); + + $this->getSession() + ->getSessionCart($dispatcher) + ->setDiscount($discount) + ->save(); + + $this->getSession() + ->getOrder() + ->setDiscount($discount); + } + + /** + * Call the Model and delegate the create or delete action + * Feed the Event with the updated model + * + * @param CouponModel $coupon Model to save + * @param CouponCreateOrUpdateEvent $event Event containing data + * @param EventDispatcherInterface $dispatcher + */ + protected function createOrUpdate(CouponModel $coupon, CouponCreateOrUpdateEvent $event, EventDispatcherInterface $dispatcher) + { + $coupon->setDispatcher($dispatcher); + + // Set default condition if none found + /** @var ConditionInterface $noConditionRule */ + $noConditionRule = $this->noConditionRule; + /** @var ConditionFactory $conditionFactory */ + $conditionFactory = $this->conditionFactory; + $couponRuleCollection = new ConditionCollection(); + $couponRuleCollection[] = $noConditionRule; + $defaultSerializedRule = $conditionFactory->serializeConditionCollection( + $couponRuleCollection + ); + + $coupon->createOrUpdate( + $event->getCode(), + $event->getTitle(), + $event->getEffects(), + $event->getServiceId(), + $event->isRemovingPostage(), + $event->getShortDescription(), + $event->getDescription(), + $event->isEnabled(), + $event->getExpirationDate(), + $event->isAvailableOnSpecialOffers(), + $event->isCumulative(), + $event->getMaxUsage(), + $defaultSerializedRule, + $event->getLocale(), + $event->getFreeShippingForCountries(), + $event->getFreeShippingForMethods(), + $event->getPerCustomerUsageCount(), + $event->getStartDate() + ); + + $event->setCouponModel($coupon); + } + + /** + * Call the Model and delegate the create or delete action + * Feed the Event with the updated model + * + * @param CouponModel $coupon Model to save + * @param CouponCreateOrUpdateEvent $event Event containing data + * @param EventDispatcherInterface $dispatcher + */ + protected function createOrUpdateCondition(CouponModel $coupon, CouponCreateOrUpdateEvent $event, EventDispatcherInterface $dispatcher) + { + $coupon->setDispatcher($dispatcher); + + /** @var ConditionFactory $conditionFactory */ + $conditionFactory = $this->conditionFactory; + + $coupon->createOrUpdateConditions( + $conditionFactory->serializeConditionCollection($event->getConditions()), + $event->getLocale() + ); + + $event->setCouponModel($coupon); + } + + /** + * @param \Thelia\Core\Event\Order\OrderEvent $event + */ + public function testFreePostage(OrderEvent $event) + { + $order = $event->getOrder(); + + if ($this->couponManager->isCouponRemovingPostage($order)) { + $order->setPostage(0); + + $event->setOrder($order); + + $event->stopPropagation(); + } + } + + /** + * @param \Thelia\Core\Event\Order\OrderEvent $event + * + * @throws \Exception if something goes wrong. + * @param $eventName + * @param EventDispatcherInterface $dispatcher + */ + public function afterOrder(OrderEvent $event, $eventName, EventDispatcherInterface $dispatcher) + { + /** @var CouponInterface[] $consumedCoupons */ + $consumedCoupons = $this->couponManager->getCouponsKept(); + + if (\is_array($consumedCoupons) && \count($consumedCoupons) > 0) { + $con = Propel::getWriteConnection(OrderCouponTableMap::DATABASE_NAME); + $con->beginTransaction(); + + try { + foreach ($consumedCoupons as $couponCode) { + $couponQuery = CouponQuery::create(); + $couponModel = $couponQuery->findOneByCode($couponCode->getCode()); + $couponModel->setLocale($this->getSession()->getLang()->getLocale()); + + /* decrease coupon quantity */ + $this->couponManager->decrementQuantity($couponModel, $event->getOrder()->getCustomerId()); + + /* memorize coupon */ + $orderCoupon = new OrderCoupon(); + $orderCoupon->setOrder($event->getOrder()) + ->setCode($couponModel->getCode()) + ->setType($couponModel->getType()) + ->setAmount($couponCode->exec()) + + ->setTitle($couponModel->getTitle()) + ->setShortDescription($couponModel->getShortDescription()) + ->setDescription($couponModel->getDescription()) + + ->setStartDate($couponModel->getStartDate()) + ->setExpirationDate($couponModel->getExpirationDate()) + ->setIsCumulative($couponModel->getIsCumulative()) + ->setIsRemovingPostage($couponModel->getIsRemovingPostage()) + ->setIsAvailableOnSpecialOffers($couponModel->getIsAvailableOnSpecialOffers()) + ->setSerializedConditions($couponModel->getSerializedConditions()) + ->setPerCustomerUsageCount($couponModel->getPerCustomerUsageCount()) + ; + $orderCoupon->save(); + + // Copy order coupon free shipping data for countries and modules + $couponCountries = CouponCountryQuery::create()->filterByCouponId($couponModel->getId())->find(); + + /** @var CouponCountry $couponCountry */ + foreach ($couponCountries as $couponCountry) { + $occ = new OrderCouponCountry(); + + $occ + ->setCouponId($orderCoupon->getId()) + ->setCountryId($couponCountry->getCountryId()) + ->save(); + ; + } + + $couponModules = CouponModuleQuery::create()->filterByCouponId($couponModel->getId())->find(); + + /** @var CouponModule $couponModule */ + foreach ($couponModules as $couponModule) { + $ocm = new OrderCouponModule(); + + $ocm + ->setCouponId($orderCoupon->getId()) + ->setModuleId($couponModule->getModuleId()) + ->save(); + ; + } + } + + $con->commit(); + } catch (\Exception $ex) { + $con->rollBack(); + + throw($ex); + } + } + + // Clear all coupons. + $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} + */ + public static function getSubscribedEvents() + { + return array( + TheliaEvents::COUPON_CREATE => array("create", 128), + TheliaEvents::COUPON_UPDATE => array("update", 128), + TheliaEvents::COUPON_DELETE => array("delete", 128), + TheliaEvents::COUPON_CONSUME => array("consume", 128), + TheliaEvents::COUPON_CLEAR_ALL => array("clearAllCoupons", 128), + TheliaEvents::COUPON_CONDITION_UPDATE => array("updateCondition", 128), + TheliaEvents::ORDER_SET_POSTAGE => array("testFreePostage", 132), + TheliaEvents::ORDER_BEFORE_PAYMENT => array("afterOrder", 128), + TheliaEvents::ORDER_UPDATE_STATUS => array("orderStatusChange", 10), + TheliaEvents::CART_ADDITEM => array("updateOrderDiscount", 10), + TheliaEvents::CART_UPDATEITEM => array("updateOrderDiscount", 10), + TheliaEvents::CART_DELETEITEM => array("updateOrderDiscount", 10), + TheliaEvents::CUSTOMER_LOGIN => array("updateOrderDiscount", 10) + ); + } + + /** + * Returns the session from the current request + * + * @return \Thelia\Core\HttpFoundation\Session\Session + */ + protected function getSession() + { + return $this->requestStack->getCurrentRequest()->getSession(); + } +} diff --git a/core/lib/Thelia/Action/Currency.php b/core/lib/Thelia/Action/Currency.php new file mode 100644 index 00000000..b62dd4e5 --- /dev/null +++ b/core/lib/Thelia/Action/Currency.php @@ -0,0 +1,219 @@ +currencyConverter = $currencyConverter; + } + + /** + * Create a new currencyuration entry + * + * @param \Thelia\Core\Event\Currency\CurrencyCreateEvent $event + * @param $eventName + * @param EventDispatcherInterface $dispatcher + */ + public function create(CurrencyCreateEvent $event, $eventName, EventDispatcherInterface $dispatcher) + { + $currency = new CurrencyModel(); + + $isDefault = CurrencyQuery::create()->count() === 0; + + $currency + ->setDispatcher($dispatcher) + ->setLocale($event->getLocale()) + ->setName($event->getCurrencyName()) + ->setSymbol($event->getSymbol()) + ->setFormat($event->getFormat()) + ->setRate($event->getRate()) + ->setCode(strtoupper($event->getCode())) + ->setByDefault($isDefault) + ->save() + ; + + $event->setCurrency($currency); + } + + /** + * Change a currency + * + * @param \Thelia\Core\Event\Currency\CurrencyUpdateEvent $event + * @param $eventName + * @param EventDispatcherInterface $dispatcher + */ + public function update(CurrencyUpdateEvent $event, $eventName, EventDispatcherInterface $dispatcher) + { + if (null !== $currency = CurrencyQuery::create()->findPk($event->getCurrencyId())) { + $currency + ->setDispatcher($dispatcher) + + ->setLocale($event->getLocale()) + ->setName($event->getCurrencyName()) + ->setSymbol($event->getSymbol()) + ->setFormat($event->getFormat()) + ->setRate($event->getRate()) + ->setCode(strtoupper($event->getCode())) + + ->save(); + + $event->setCurrency($currency); + } + } + + /** + * Set the default currency + * + * @param CurrencyUpdateEvent $event + * @param $eventName + * @param EventDispatcherInterface $dispatcher + */ + public function setDefault(CurrencyUpdateEvent $event, $eventName, EventDispatcherInterface $dispatcher) + { + if (null !== $currency = CurrencyQuery::create()->findPk($event->getCurrencyId())) { + // Reset default status + CurrencyQuery::create()->filterByByDefault(true)->update(array('ByDefault' => false)); + + $currency + ->setDispatcher($dispatcher) + ->setVisible($event->getVisible()) + ->setByDefault($event->getIsDefault()) + ->save() + ; + + // Update rates when setting a new default currency + if ($event->getIsDefault()) { + $updateRateEvent = new CurrencyUpdateRateEvent(); + + $dispatcher->dispatch(TheliaEvents::CURRENCY_UPDATE_RATES, $updateRateEvent); + } + + $event->setCurrency($currency); + } + } + + /** + * @param CurrencyUpdateEvent $event + */ + public function setVisible(CurrencyUpdateEvent $event) + { + if (null !== $currency = CurrencyQuery::create()->findPk($event->getCurrencyId())) { + if (!$currency->getByDefault()) { + $currency->setVisible($event->getVisible())->save(); + } + } + } + + /** + * Delete a currencyuration entry + * + * @param \Thelia\Core\Event\Currency\CurrencyDeleteEvent $event + * @param $eventName + * @param EventDispatcherInterface $dispatcher + */ + public function delete(CurrencyDeleteEvent $event, $eventName, EventDispatcherInterface $dispatcher) + { + if (null !== ($currency = CurrencyQuery::create()->findPk($event->getCurrencyId()))) { + if ($currency->getByDefault()) { + throw new \RuntimeException( + Translator::getInstance()->trans('It is not allowed to delete the default currency') + ); + } + + $currency + ->setDispatcher($dispatcher) + ->delete() + ; + + $event->setCurrency($currency); + } + } + + public function updateRates(CurrencyUpdateRateEvent $event) + { + if (null === $defaultCurrency = CurrencyQuery::create()->findOneByByDefault(true)) { + throw new \RuntimeException('Unable to find a default currency, please define a default currency.'); + } + + $defaultCurrency->setRate(1)->save(); + + $currencies = CurrencyQuery::create()->filterByByDefault(false); + $baseValue = new Number('1'); + + /** @var \Thelia\Model\Currency $currency */ + foreach ($currencies as $currency) { + try { + $rate = $this->currencyConverter + ->from($defaultCurrency->getCode()) + ->to($currency->getCode()) + ->convert($baseValue); + + $currency->setRate($rate->getNumber(-1))->save(); + } catch (CurrencyNotFoundException $ex) { + Tlog::getInstance()->addError( + sprintf("Unable to find exchange rate for currency %s, ID %d", $currency->getCode(), $currency->getId()) + ); + $event->addUndefinedRate($currency->getId()); + } + } + } + + /** + * Changes position, selecting absolute ou relative change. + * + * @param UpdatePositionEvent $event + * @param string $eventName + * @param EventDispatcherInterface $dispatcher + */ + public function updatePosition(UpdatePositionEvent $event, $eventName, EventDispatcherInterface $dispatcher) + { + $this->genericUpdatePosition(CurrencyQuery::create(), $event, $dispatcher); + } + + /** + * {@inheritDoc} + */ + public static function getSubscribedEvents() + { + return array( + TheliaEvents::CURRENCY_CREATE => array("create", 128), + TheliaEvents::CURRENCY_UPDATE => array("update", 128), + TheliaEvents::CURRENCY_DELETE => array("delete", 128), + TheliaEvents::CURRENCY_SET_DEFAULT => array("setDefault", 128), + TheliaEvents::CURRENCY_SET_VISIBLE => array("setVisible", 128), + TheliaEvents::CURRENCY_UPDATE_RATES => array("updateRates", 128), + TheliaEvents::CURRENCY_UPDATE_POSITION => array("updatePosition", 128) + ); + } +} diff --git a/core/lib/Thelia/Action/Customer.php b/core/lib/Thelia/Action/Customer.php new file mode 100644 index 00000000..b6e8c709 --- /dev/null +++ b/core/lib/Thelia/Action/Customer.php @@ -0,0 +1,292 @@ + + */ +class Customer extends BaseAction implements EventSubscriberInterface +{ + /** @var SecurityContext */ + protected $securityContext; + + /** @var MailerFactory */ + protected $mailer; + + /** @var RequestStack */ + protected $requestStack; + + public function __construct(SecurityContext $securityContext, MailerFactory $mailer, RequestStack $requestStack = null) + { + $this->securityContext = $securityContext; + $this->mailer = $mailer; + $this->requestStack = $requestStack; + } + + /** + * @param CustomerCreateOrUpdateEvent $event + * @param $eventName + * @param EventDispatcherInterface $dispatcher + * @throws \Propel\Runtime\Exception\PropelException + */ + public function create(CustomerCreateOrUpdateEvent $event, $eventName, EventDispatcherInterface $dispatcher) + { + $customer = new CustomerModel(); + + $plainPassword = $event->getPassword(); + + $this->createOrUpdateCustomer($customer, $event, $dispatcher); + + if ($event->getNotifyCustomerOfAccountCreation()) { + $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) { + $this->mailer->sendEmailToCustomer( + 'customer_confirmation', + $customer, + ['customer_id' => $customer->getId()] + ); + } + } + + /** + * @param CustomerCreateOrUpdateEvent $event + * @param $eventName + * @param EventDispatcherInterface $dispatcher + * @throws \Propel\Runtime\Exception\PropelException + */ + public function modify(CustomerCreateOrUpdateEvent $event, $eventName, EventDispatcherInterface $dispatcher) + { + $plainPassword = $event->getPassword(); + + $customer = $event->getCustomer(); + + $emailChanged = $customer->getEmail() !== $event->getEmail(); + + $this->createOrUpdateCustomer($customer, $event, $dispatcher); + + if ($event->getNotifyCustomerOfAccountModification() && (! empty($plainPassword) || $emailChanged)) { + $this->mailer->sendEmailToCustomer('customer_account_changed', $customer, ['password' => $plainPassword]); + } + } + + /** + * @param CustomerCreateOrUpdateEvent $event + * @param $eventName + * @param EventDispatcherInterface $dispatcher + * @throws \Propel\Runtime\Exception\PropelException + */ + public function updateProfile(CustomerCreateOrUpdateEvent $event, $eventName, EventDispatcherInterface $dispatcher) + { + $customer = $event->getCustomer(); + + $customer->setDispatcher($dispatcher); + + if ($event->getTitle() !== null) { + $customer->setTitleId($event->getTitle()); + } + + if ($event->getFirstname() !== null) { + $customer->setFirstname($event->getFirstname()); + } + + if ($event->getLastname() !== null) { + $customer->setLastname($event->getLastname()); + } + + if ($event->getEmail() !== null) { + $customer->setEmail($event->getEmail(), $event->getEmailUpdateAllowed()); + } + + if ($event->getPassword() !== null) { + $customer->setPassword($event->getPassword()); + } + + if ($event->getReseller() !== null) { + $customer->setReseller($event->getReseller()); + } + + if ($event->getSponsor() !== null) { + $customer->setSponsor($event->getSponsor()); + } + + if ($event->getDiscount() !== null) { + $customer->setDiscount($event->getDiscount()); + } + + if ($event->getLangId() !== null) { + $customer->setLangId($event->getLangId()); + } + + $customer->save(); + + $event->setCustomer($customer); + } + + /** + * @param CustomerEvent $event + * @throws \Propel\Runtime\Exception\PropelException + */ + public function delete(CustomerEvent $event) + { + if (null !== $customer = $event->getCustomer()) { + if (true === $customer->hasOrder()) { + throw new CustomerException(Translator::getInstance()->trans("Impossible to delete a customer who already have orders")); + } + + $customer->delete(); + } + } + + /** + * @param CustomerModel $customer + * @param CustomerCreateOrUpdateEvent $event + * @param EventDispatcherInterface $dispatcher + * @throws \Propel\Runtime\Exception\PropelException + */ + private function createOrUpdateCustomer(CustomerModel $customer, CustomerCreateOrUpdateEvent $event, EventDispatcherInterface $dispatcher) + { + $customer->setDispatcher($dispatcher); + + $customer->createOrUpdate( + $event->getTitle(), + $event->getFirstname(), + $event->getLastname(), + $event->getAddress1(), + $event->getAddress2(), + $event->getAddress3(), + $event->getPhone(), + $event->getCellphone(), + $event->getZipcode(), + $event->getCity(), + $event->getCountry(), + $event->getEmail(), + $event->getPassword(), + $event->getLangId(), + $event->getReseller(), + $event->getSponsor(), + $event->getDiscount(), + $event->getCompany(), + $event->getRef(), + $event->getEmailUpdateAllowed(), + $event->getState() + ); + + $event->setCustomer($customer); + } + + public function login(CustomerLoginEvent $event) + { + $customer = $event->getCustomer(); + + if (method_exists($customer, 'clearDispatcher')) { + $customer->clearDispatcher(); + } + + $this->securityContext->setCustomerUser($event->getCustomer()); + + // Set the preferred customer language + if (null !== $this->requestStack + && + ! empty($customer->getLangId()) + && + (null !== $lang = LangQuery::create()->findPk($customer->getLangId())) + ) { + $this->requestStack->getCurrentRequest()->getSession()->setLang($lang); + } + } + + /** + * Perform user logout. The user is redirected to the provided view, if any. + * + * @param ActionEvent $event + */ + public function logout(/** @noinspection PhpUnusedParameterInspection */ ActionEvent $event) + { + $this->securityContext->clearCustomerUser(); + } + + /** + * @param LostPasswordEvent $event + * @throws \Propel\Runtime\Exception\PropelException + */ + public function lostPassword(LostPasswordEvent $event) + { + if (null !== $customer = CustomerQuery::create()->filterByEmail($event->getEmail())->findOne()) { + $password = Password::generateRandom(8); + + $customer + ->setPassword($password) + ->save() + ; + + $this->mailer->sendEmailToCustomer('lost_password', $customer, ['password' => $password]); + } + } + + /** + * {@inheritdoc} + */ + public static function getSubscribedEvents() + { + return array( + TheliaEvents::CUSTOMER_CREATEACCOUNT => array('create', 128), + TheliaEvents::CUSTOMER_UPDATEACCOUNT => array('modify', 128), + TheliaEvents::CUSTOMER_UPDATEPROFILE => array('updateProfile', 128), + TheliaEvents::CUSTOMER_LOGOUT => array('logout', 128), + TheliaEvents::CUSTOMER_LOGIN => array('login', 128), + TheliaEvents::CUSTOMER_DELETEACCOUNT => array('delete', 128), + TheliaEvents::LOST_PASSWORD => array('lostPassword', 128), + TheliaEvents::SEND_ACCOUNT_CONFIRMATION_EMAIL => array('customerConfirmationEmail', 128) + ); + } +} diff --git a/core/lib/Thelia/Action/CustomerTitle.php b/core/lib/Thelia/Action/CustomerTitle.php new file mode 100644 index 00000000..8e3aed0a --- /dev/null +++ b/core/lib/Thelia/Action/CustomerTitle.php @@ -0,0 +1,111 @@ + + */ +class CustomerTitle extends BaseAction implements EventSubscriberInterface +{ + public function create(CustomerTitleEvent $event) + { + $this->createOrUpdate($event, new CustomerTitleModel()); + } + + public function update(CustomerTitleEvent $event) + { + $this->checkCustomerTitle($event); + + $this->createOrUpdate($event, $event->getCustomerTitle()); + } + + public function delete(CustomerTitleEvent $event) + { + $this->checkCustomerTitle($event); + + $con = Propel::getConnection(CustomerTitleTableMap::DATABASE_NAME); + $con->beginTransaction(); + + try { + $event->getCustomerTitle()->delete(); + + $con->commit(); + } catch (\Exception $e) { + $con->rollBack(); + + throw $e; + } + + $event->setCustomerTitle(null); + } + + protected function checkCustomerTitle(CustomerTitleEvent $event) + { + if (null === $event->getCustomerTitle()) { + throw new \LogicException( + "You must set the customer title before its update" + ); + } + } + + protected function createOrUpdate(CustomerTitleEvent $event, CustomerTitleModel $customerTitle) + { + $con = Propel::getConnection(CustomerTitleTableMap::DATABASE_NAME); + $con->beginTransaction(); + + $i18n = $customerTitle->getTranslation($event->getLocale(), $con); + + try { + $i18n + ->setShort($event->getShort()) + ->setLong($event->getLong()) + ; + + $customerTitle->save($con); + + if ($event->isDefault()) { + $customerTitle->toggleDefault($con); + $event->setDefault(false); + } + + $con->commit(); + } catch (\Exception $e) { + $con->rollBack(); + + throw $e; + } + + $event->setCustomerTitle($customerTitle); + } + + /** + * {@inheritdoc} + */ + public static function getSubscribedEvents() + { + return array( + TheliaEvents::CUSTOMER_TITLE_CREATE => array("create"), + TheliaEvents::CUSTOMER_TITLE_UPDATE => array("update"), + TheliaEvents::CUSTOMER_TITLE_DELETE => array("delete"), + ); + } +} diff --git a/core/lib/Thelia/Action/Delivery.php b/core/lib/Thelia/Action/Delivery.php new file mode 100644 index 00000000..f6d01536 --- /dev/null +++ b/core/lib/Thelia/Action/Delivery.php @@ -0,0 +1,79 @@ + + */ +class Delivery implements EventSubscriberInterface +{ + /** + * Get postage from module using the classical module functions + * + * @param DeliveryPostageEvent $event + */ + public function getPostage(DeliveryPostageEvent $event, $eventName, EventDispatcherInterface $dispatcher) + { + /** @var AbstractDeliveryModule $module */ + $module = $event->getModule(); + + // dispatch event to target specific module + $dispatcher->dispatch( + TheliaEvents::getModuleEvent( + TheliaEvents::MODULE_DELIVERY_GET_POSTAGE, + $module->getCode() + ), + $event + ); + + if ($event->isPropagationStopped()) { + return; + } + + // Add state param to isValidDelivery only if module handle state + $isValidModule = $module instanceof DeliveryModuleWithStateInterface + ? $module->isValidDelivery($event->getCountry(), $event->getState()) + : $module->isValidDelivery($event->getCountry()); + + $event->setValidModule($isValidModule) + ->setDeliveryMode($module->getDeliveryMode()); + + if ($event->isValidModule()) { + // Add state param to getPostage only if module handle state + $modulePostage = $module instanceof DeliveryModuleWithStateInterface + ? $module->getPostage($event->getCountry(), $event->getState()) + : $module->getPostage($event->getCountry()); + + $event->setPostage($modulePostage); + } + } + + /** + * @inheritdoc + */ + public static function getSubscribedEvents() + { + return [ + TheliaEvents::MODULE_DELIVERY_GET_POSTAGE => ['getPostage', 128] + ]; + } +} diff --git a/core/lib/Thelia/Action/Document.php b/core/lib/Thelia/Action/Document.php new file mode 100644 index 00000000..310a45c5 --- /dev/null +++ b/core/lib/Thelia/Action/Document.php @@ -0,0 +1,125 @@ + + * + */ +class Document extends BaseCachedFile implements EventSubscriberInterface +{ + /** + * @var string Config key for document delivery mode + */ + const CONFIG_DELIVERY_MODE = 'original_document_delivery_mode'; + + /** + * @return string root of the document cache directory in web space + */ + protected function getCacheDirFromWebRoot() + { + return ConfigQuery::read('document_cache_dir_from_web_root', 'cache' . DS . 'documents'); + } + + /** + * Process document and write the result in the document cache. + * + * When the original document is required, create either a symbolic link with the + * original document in the cache dir, or copy it in the cache dir if it's not already done. + * + * This method updates the cache_file_path and file_url attributes of the event + * + * @param DocumentEvent $event Event + * + * @throws \Thelia\Exception\DocumentException + * @throws \InvalidArgumentException , DocumentException + */ + public function processDocument(DocumentEvent $event) + { + $subdir = $event->getCacheSubdirectory(); + $sourceFile = $event->getSourceFilepath(); + + if (null == $subdir || null == $sourceFile) { + throw new \InvalidArgumentException("Cache sub-directory and source file path cannot be null"); + } + + $originalDocumentPathInCache = $this->getCacheFilePath($subdir, $sourceFile, true); + + if (! file_exists($originalDocumentPathInCache)) { + if (! file_exists($sourceFile)) { + throw new DocumentException(sprintf("Source document file %s does not exists.", $sourceFile)); + } + + $mode = ConfigQuery::read(self::CONFIG_DELIVERY_MODE, 'symlink'); + + if ($mode == 'symlink') { + if (false === symlink($sourceFile, $originalDocumentPathInCache)) { + throw new DocumentException(sprintf("Failed to create symbolic link for %s in %s document cache directory", basename($sourceFile), $subdir)); + } + } else { + // mode = 'copy' + if (false === @copy($sourceFile, $originalDocumentPathInCache)) { + throw new DocumentException(sprintf("Failed to copy %s in %s document cache directory", basename($sourceFile), $subdir)); + } + } + } + + // Compute the document URL + $documentUrl = $this->getCacheFileURL($subdir, basename($originalDocumentPathInCache)); + + // Update the event with file path and file URL + $event->setDocumentPath($documentUrl); + $event->setDocumentUrl(URL::getInstance()->absoluteUrl($documentUrl, null, URL::PATH_TO_FILE, $this->cdnBaseUrl)); + } + + /** + * {@inheritdoc} + */ + public static function getSubscribedEvents() + { + return array( + TheliaEvents::DOCUMENT_PROCESS => array("processDocument", 128), + + // Implemented in parent class BaseCachedFile + TheliaEvents::DOCUMENT_CLEAR_CACHE => array("clearCache", 128), + TheliaEvents::DOCUMENT_DELETE => array("deleteFile", 128), + TheliaEvents::DOCUMENT_SAVE => array("saveFile", 128), + TheliaEvents::DOCUMENT_UPDATE => array("updateFile", 128), + TheliaEvents::DOCUMENT_UPDATE_POSITION => array("updatePosition", 128), + TheliaEvents::DOCUMENT_TOGGLE_VISIBILITY => array("toggleVisibility", 128), + ); + } +} diff --git a/core/lib/Thelia/Action/Export.php b/core/lib/Thelia/Action/Export.php new file mode 100644 index 00000000..915e6827 --- /dev/null +++ b/core/lib/Thelia/Action/Export.php @@ -0,0 +1,79 @@ + + */ +class Export extends BaseAction implements EventSubscriberInterface +{ + /** + * @var \Thelia\Handler\ExportHandler The export handler + */ + protected $handler; + + /** + * @param \Thelia\Handler\ExportHandler $exportHandler The export handler + */ + public function __construct(ExportHandler $exportHandler) + { + $this->handler = $exportHandler; + } + + public static function getSubscribedEvents() + { + return [ + TheliaEvents::EXPORT_CHANGE_POSITION => [ + ['exportChangePosition', 128] + ], + TheliaEvents::EXPORT_CATEGORY_CHANGE_POSITION => [ + ['exportCategoryChangePosition', 128] + ] + ]; + } + + /** + * Handle export change position event + * + * @param UpdatePositionEvent $updatePositionEvent + * @param $eventName + * @param EventDispatcherInterface $dispatcher + */ + public function exportChangePosition(UpdatePositionEvent $updatePositionEvent, $eventName, EventDispatcherInterface $dispatcher) + { + $this->handler->getExport($updatePositionEvent->getObjectId(), true); + $this->genericUpdatePosition(new ExportQuery, $updatePositionEvent, $dispatcher); + } + + /** + * Handle export category change position event + * + * @param UpdatePositionEvent $updatePositionEvent + * @param $eventName + * @param EventDispatcherInterface $dispatcher + */ + public function exportCategoryChangePosition(UpdatePositionEvent $updatePositionEvent, $eventName, EventDispatcherInterface $dispatcher) + { + $this->handler->getCategory($updatePositionEvent->getObjectId(), true); + $this->genericUpdatePosition(new ExportCategoryQuery, $updatePositionEvent, $dispatcher); + } +} diff --git a/core/lib/Thelia/Action/Feature.php b/core/lib/Thelia/Action/Feature.php new file mode 100644 index 00000000..adf3d575 --- /dev/null +++ b/core/lib/Thelia/Action/Feature.php @@ -0,0 +1,159 @@ +setDispatcher($dispatcher) + + ->setLocale($event->getLocale()) + ->setTitle($event->getTitle()) + + ->save() + ; + + $event->setFeature($feature); + + // Add atribute to all product templates if required + if ($event->getAddToAllTemplates() != 0) { + $this->doAddToAllTemplates($feature); + } + } + + /** + * Change a product feature + * + * @param \Thelia\Core\Event\Feature\FeatureUpdateEvent $event + * @param $eventName + * @param EventDispatcherInterface $dispatcher + */ + public function update(FeatureUpdateEvent $event, $eventName, EventDispatcherInterface $dispatcher) + { + if (null !== $feature = FeatureQuery::create()->findPk($event->getFeatureId())) { + $feature + ->setDispatcher($dispatcher) + + ->setLocale($event->getLocale()) + ->setTitle($event->getTitle()) + ->setDescription($event->getDescription()) + ->setChapo($event->getChapo()) + ->setPostscriptum($event->getPostscriptum()) + + ->save(); + + $event->setFeature($feature); + } + } + + /** + * Delete a product feature entry + * + * @param FeatureDeleteEvent $event + * @param $eventName + * @param EventDispatcherInterface $dispatcher + */ + public function delete(FeatureDeleteEvent $event, $eventName, EventDispatcherInterface $dispatcher) + { + if (null !== ($feature = FeatureQuery::create()->findPk($event->getFeatureId()))) { + $feature + ->setDispatcher($dispatcher) + ->delete() + ; + + $event->setFeature($feature); + } + } + + /** + * Changes position, selecting absolute ou relative change. + * + * @param UpdatePositionEvent $event + * @param $eventName + * @param EventDispatcherInterface $dispatcher + */ + public function updatePosition(UpdatePositionEvent $event, $eventName, EventDispatcherInterface $dispatcher) + { + $this->genericUpdatePosition(FeatureQuery::create(), $event, $dispatcher); + } + + protected function doAddToAllTemplates(FeatureModel $feature) + { + $templates = TemplateQuery::create()->find(); + + foreach ($templates as $template) { + $feature_template = new FeatureTemplate(); + + if (null === FeatureTemplateQuery::create()->filterByFeature($feature)->filterByTemplate($template)->findOne()) { + $feature_template + ->setFeature($feature) + ->setTemplate($template) + ->save() + ; + } + } + } + + public function addToAllTemplates(FeatureEvent $event) + { + $this->doAddToAllTemplates($event->getFeature()); + } + + public function removeFromAllTemplates(FeatureEvent $event) + { + // Delete this feature from all product templates + FeatureTemplateQuery::create()->filterByFeature($event->getFeature())->delete(); + } + + /** + * {@inheritDoc} + */ + public static function getSubscribedEvents() + { + return array( + TheliaEvents::FEATURE_CREATE => array("create", 128), + TheliaEvents::FEATURE_UPDATE => array("update", 128), + TheliaEvents::FEATURE_DELETE => array("delete", 128), + TheliaEvents::FEATURE_UPDATE_POSITION => array("updatePosition", 128), + + TheliaEvents::FEATURE_REMOVE_FROM_ALL_TEMPLATES => array("removeFromAllTemplates", 128), + TheliaEvents::FEATURE_ADD_TO_ALL_TEMPLATES => array("addToAllTemplates", 128), + + ); + } +} diff --git a/core/lib/Thelia/Action/FeatureAv.php b/core/lib/Thelia/Action/FeatureAv.php new file mode 100644 index 00000000..e9fea53b --- /dev/null +++ b/core/lib/Thelia/Action/FeatureAv.php @@ -0,0 +1,119 @@ +setDispatcher($dispatcher) + + ->setFeatureId($event->getFeatureId()) + ->setLocale($event->getLocale()) + ->setTitle($event->getTitle()) + + ->save() + ; + + $event->setFeatureAv($feature); + } + + /** + * Change a product feature + * + * @param FeatureAvUpdateEvent $event + * @param $eventName + * @param EventDispatcherInterface $dispatcher + */ + public function update(FeatureAvUpdateEvent $event, $eventName, EventDispatcherInterface $dispatcher) + { + if (null !== $feature = FeatureAvQuery::create()->findPk($event->getFeatureAvId())) { + $feature + ->setDispatcher($dispatcher) + + ->setLocale($event->getLocale()) + ->setTitle($event->getTitle()) + ->setDescription($event->getDescription()) + ->setChapo($event->getChapo()) + ->setPostscriptum($event->getPostscriptum()) + + ->save(); + + $event->setFeatureAv($feature); + } + } + + /** + * Delete a product feature entry + * + * @param FeatureAvDeleteEvent $event + * @param $eventName + * @param EventDispatcherInterface $dispatcher + */ + public function delete(FeatureAvDeleteEvent $event, $eventName, EventDispatcherInterface $dispatcher) + { + if (null !== ($feature = FeatureAvQuery::create()->findPk($event->getFeatureAvId()))) { + $feature + ->setDispatcher($dispatcher) + ->delete() + ; + + $event->setFeatureAv($feature); + } + } + + /** + * Changes position, selecting absolute ou relative change. + * + * @param UpdatePositionEvent $event + * @param $eventName + * @param EventDispatcherInterface $dispatcher + */ + public function updatePosition(UpdatePositionEvent $event, $eventName, EventDispatcherInterface $dispatcher) + { + $this->genericUpdatePosition(FeatureAvQuery::create(), $event, $dispatcher); + } + + /** + * {@inheritDoc} + */ + public static function getSubscribedEvents() + { + return array( + TheliaEvents::FEATURE_AV_CREATE => array("create", 128), + TheliaEvents::FEATURE_AV_UPDATE => array("update", 128), + TheliaEvents::FEATURE_AV_DELETE => array("delete", 128), + TheliaEvents::FEATURE_AV_UPDATE_POSITION => array("updatePosition", 128), + ); + } +} diff --git a/core/lib/Thelia/Action/File.php b/core/lib/Thelia/Action/File.php new file mode 100644 index 00000000..cf7a76ca --- /dev/null +++ b/core/lib/Thelia/Action/File.php @@ -0,0 +1,175 @@ + + */ +class File extends BaseAction implements EventSubscriberInterface +{ + public function cloneFile(ProductCloneEvent $event, $eventName, EventDispatcherInterface $dispatcher) + { + $originalProductId = $event->getOriginalProduct()->getId(); + $clonedProduct = $event->getClonedProduct(); + + foreach ($event->getTypes() as $type) { + $originalProductFiles = []; + + switch ($type) { + case 'images': + $originalProductFiles = ProductImageQuery::create() + ->findByProductId($originalProductId); + break; + + case 'documents': + $originalProductFiles = ProductDocumentQuery::create() + ->findByProductId($originalProductId); + break; + } + + // Set clone's files + /** @var ProductDocument|ProductImage $originalProductFile */ + foreach ($originalProductFiles as $originalProductFile) { + $srcPath = $originalProductFile->getUploadDir() . DS . $originalProductFile->getFile(); + + if (file_exists($srcPath)) { + $ext = pathinfo($srcPath, PATHINFO_EXTENSION); + + $clonedProductFile = []; + + switch ($type) { + case 'images': + $fileName = $clonedProduct->getRef().'.'.$ext; + $clonedProductFile = new ProductImage(); + break; + + case 'documents': + $fileName = pathinfo($originalProductFile->getFile(), PATHINFO_FILENAME).'-'.$clonedProduct->getRef().'.'.$ext; + $clonedProductFile = new ProductDocument(); + break; + } + + // Copy a temporary file of the source file as it will be deleted by IMAGE_SAVE or DOCUMENT_SAVE event + $srcTmp = $srcPath.'.tmp'; + copy($srcPath, $srcTmp); + + // Get file mimeType + $finfo = new \finfo(); + $fileMimeType = $finfo->file($srcPath, FILEINFO_MIME_TYPE); + + // Get file event's parameters + $clonedProductFile + ->setProductId($clonedProduct->getId()) + ->setVisible($originalProductFile->getVisible()) + ->setPosition($originalProductFile->getPosition()) + ->setLocale($clonedProduct->getLocale()) + ->setTitle($clonedProduct->getTitle()); + + $clonedProductCopiedFile = new UploadedFile($srcPath, $fileName, $fileMimeType, filesize($srcPath), null, true); + + // Create and dispatch event + $clonedProductCreateFileEvent = new FileCreateOrUpdateEvent($clonedProduct->getId()); + $clonedProductCreateFileEvent + ->setModel($clonedProductFile) + ->setUploadedFile($clonedProductCopiedFile) + ->setParentName($clonedProduct->getTitle()); + + $originalProductFileI18ns = []; + + switch ($type) { + case 'images': + $dispatcher->dispatch(TheliaEvents::IMAGE_SAVE, $clonedProductCreateFileEvent); + + // Get original product image I18n + $originalProductFileI18ns = ProductImageI18nQuery::create() + ->findById($originalProductFile->getId()); + break; + + case 'documents': + $dispatcher->dispatch(TheliaEvents::DOCUMENT_SAVE, $clonedProductCreateFileEvent); + + // Get original product document I18n + $originalProductFileI18ns = ProductDocumentI18nQuery::create() + ->findById($originalProductFile->getId()); + break; + } + + // Set temporary source file as original one + rename($srcTmp, $srcPath); + + // Clone file's I18n + $this->cloneFileI18n($originalProductFileI18ns, $clonedProductFile, $type, $event, $dispatcher); + } else { + Tlog::getInstance()->addWarning("Failed to find media file $srcPath"); + } + } + } + } + + public function cloneFileI18n($originalProductFileI18ns, $clonedProductFile, $type, ProductCloneEvent $event, EventDispatcherInterface $dispatcher) + { + // Set clone files I18n + /** @var ProductDocumentI18n $originalProductFileI18n */ + foreach ($originalProductFileI18ns as $originalProductFileI18n) { + // Update file with current I18n info. Update or create I18n according to existing or absent Locale in DB + $clonedProductFile + ->setLocale($originalProductFileI18n->getLocale()) + ->setTitle($originalProductFileI18n->getTitle()) + ->setDescription($originalProductFileI18n->getDescription()) + ->setChapo($originalProductFileI18n->getChapo()) + ->setPostscriptum($originalProductFileI18n->getPostscriptum()); + + // Create and dispatch event + $clonedProductUpdateFileEvent = new FileCreateOrUpdateEvent($event->getClonedProduct()->getId()); + $clonedProductUpdateFileEvent->setModel($clonedProductFile); + + switch ($type) { + case 'images': + $dispatcher->dispatch(TheliaEvents::IMAGE_UPDATE, $clonedProductUpdateFileEvent); + break; + + case 'documents': + $dispatcher->dispatch(TheliaEvents::DOCUMENT_UPDATE, $clonedProductUpdateFileEvent); + break; + } + } + } + + /** + * {@inheritdoc} + */ + public static function getSubscribedEvents() + { + return array( + TheliaEvents::FILE_CLONE => array("cloneFile", 128) + ); + } +} diff --git a/core/lib/Thelia/Action/Folder.php b/core/lib/Thelia/Action/Folder.php new file mode 100644 index 00000000..747e02ed --- /dev/null +++ b/core/lib/Thelia/Action/Folder.php @@ -0,0 +1,208 @@ + + */ +class Folder extends BaseAction implements EventSubscriberInterface +{ + public function update(FolderUpdateEvent $event, $eventName, EventDispatcherInterface $dispatcher) + { + if (null !== $folder = FolderQuery::create()->findPk($event->getFolderId())) { + $folder->setDispatcher($dispatcher); + + $folder + ->setParent($event->getParent()) + ->setVisible($event->getVisible()) + ->setLocale($event->getLocale()) + ->setTitle($event->getTitle()) + ->setDescription($event->getDescription()) + ->setChapo($event->getChapo()) + ->setPostscriptum($event->getPostscriptum()) + ->save(); + ; + + $event->setFolder($folder); + } + } + + /** + * Change Folder SEO + * + * @param UpdateSeoEvent $event + * @param $eventName + * @param EventDispatcherInterface $dispatcher + * @return Object + */ + public function updateSeo(UpdateSeoEvent $event, $eventName, EventDispatcherInterface $dispatcher) + { + return $this->genericUpdateSeo(FolderQuery::create(), $event, $dispatcher); + } + + public function delete(FolderDeleteEvent $event, $eventName, EventDispatcherInterface $dispatcher) + { + if (null !== $folder = FolderQuery::create()->findPk($event->getFolderId())) { + $con = Propel::getWriteConnection(FolderTableMap::DATABASE_NAME); + $con->beginTransaction(); + + try { + $fileList = ['images' => [], 'documentList' => []]; + + // Get folder's files to delete after folder deletion + $fileList['images']['list'] = FolderImageQuery::create() + ->findByFolderId($event->getFolderId()); + $fileList['images']['type'] = TheliaEvents::IMAGE_DELETE; + + $fileList['documentList']['list'] = FolderDocumentQuery::create() + ->findByFolderId($event->getFolderId()); + $fileList['documentList']['type'] = TheliaEvents::DOCUMENT_DELETE; + + // Delete folder + $folder->setDispatcher($dispatcher) + ->delete($con); + + $event->setFolder($folder); + + // Dispatch delete folder's files event + foreach ($fileList as $fileTypeList) { + foreach ($fileTypeList['list'] as $fileToDelete) { + $fileDeleteEvent = new FileDeleteEvent($fileToDelete); + $dispatcher->dispatch($fileTypeList['type'], $fileDeleteEvent); + } + } + + $con->commit(); + } catch (\Exception $e) { + $con->rollback(); + throw $e; + } + } + } + + public function create(FolderCreateEvent $event, $eventName, EventDispatcherInterface $dispatcher) + { + $folder = new FolderModel(); + $folder->setDispatcher($dispatcher); + + $folder + ->setParent($event->getParent()) + ->setVisible($event->getVisible()) + ->setLocale($event->getLocale()) + ->setTitle($event->getTitle()) + ->save(); + + $event->setFolder($folder); + } + + public function toggleVisibility(FolderToggleVisibilityEvent $event, $eventName, EventDispatcherInterface $dispatcher) + { + $folder = $event->getFolder(); + + $folder + ->setDispatcher($dispatcher) + ->setVisible(!$folder->getVisible()) + ->save(); + + $event->setFolder($folder); + } + + public function updatePosition(UpdatePositionEvent $event, $eventName, EventDispatcherInterface $dispatcher) + { + if (null !== $folder = FolderQuery::create()->findPk($event->getObjectId())) { + $folder->setDispatcher($dispatcher); + + switch ($event->getMode()) { + case UpdatePositionEvent::POSITION_ABSOLUTE: + $folder->changeAbsolutePosition($event->getPosition()); + break; + case UpdatePositionEvent::POSITION_DOWN: + $folder->movePositionDown(); + break; + case UpdatePositionEvent::POSITION_UP: + $folder->movePositionUp(); + break; + } + } + } + + /** + * 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} + */ + public static function getSubscribedEvents() + { + return array( + TheliaEvents::FOLDER_CREATE => array("create", 128), + TheliaEvents::FOLDER_UPDATE => array("update", 128), + TheliaEvents::FOLDER_DELETE => array("delete", 128), + TheliaEvents::FOLDER_TOGGLE_VISIBILITY => array("toggleVisibility", 128), + + TheliaEvents::FOLDER_UPDATE_POSITION => array("updatePosition", 128), + TheliaEvents::FOLDER_UPDATE_SEO => array('updateSeo', 128), + + TheliaEvents::VIEW_CHECK => array('viewCheck', 128), + TheliaEvents::VIEW_FOLDER_ID_NOT_VISIBLE => array('viewFolderIdNotVisible', 128), + ); + } +} diff --git a/core/lib/Thelia/Action/Hook.php b/core/lib/Thelia/Action/Hook.php new file mode 100644 index 00000000..a4517333 --- /dev/null +++ b/core/lib/Thelia/Action/Hook.php @@ -0,0 +1,168 @@ + + */ +class Hook extends BaseAction implements EventSubscriberInterface +{ + /** @var string */ + protected $cacheDir; + + public function __construct($cacheDir) + { + $this->cacheDir = $cacheDir; + } + + public function create(HookCreateEvent $event, $eventName, EventDispatcherInterface $dispatcher) + { + $hook = new HookModel(); + + $hook + ->setLocale($event->getLocale()) + ->setCode($event->getCode()) + ->setType($event->getType()) + ->setNative($event->getNative()) + ->setActivate($event->getActive()) + ->setTitle($event->getTitle()) + ->save(); + + $event->setHook($hook); + + $this->cacheClear($dispatcher); + } + + public function update(HookUpdateEvent $event, $eventName, EventDispatcherInterface $dispatcher) + { + if (null !== $hook = HookQuery::create()->findPk($event->getHookId())) { + $hook + ->setLocale($event->getLocale()) + ->setCode($event->getCode()) + ->setType($event->getType()) + ->setNative($event->getNative()) + ->setActivate($event->getActive()) + ->setBlock($event->getBlock()) + ->setByModule($event->getByModule()) + ->setTitle($event->getTitle()) + ->setChapo($event->getChapo()) + ->setDescription($event->getDescription()) + ->save(); + + $event->setHook($hook); + $this->cacheClear($dispatcher); + } + } + + public function delete(HookDeleteEvent $event, $eventName, EventDispatcherInterface $dispatcher) + { + if (null !== $hook = HookQuery::create()->findPk($event->getHookId())) { + $hook->delete(); + $event->setHook($hook); + + $this->cacheClear($dispatcher); + } + } + + public function createAll(HookCreateAllEvent $event) + { + $hook = new HookModel(); + + $hook + ->setLocale($event->getLocale()) + ->setCode($event->getCode()) + ->setType($event->getType()) + ->setNative($event->getNative()) + ->setActivate($event->getActive()) + ->setBlock($event->getBlock()) + ->setByModule($event->getByModule()) + ->setTitle($event->getTitle()) + ->setChapo($event->getChapo()) + ->setDescription($event->getDescription()) + ->save(); + + $event->setHook($hook); + } + + public function deactivation(HookDeactivationEvent $event) + { + if (null !== $hook = HookQuery::create()->findPk($event->getHookId())) { + $hook + ->setActivate(false) + ->save(); + $event->setHook($hook); + } + } + + public function toggleNative(HookToggleNativeEvent $event) + { + if (null !== $hook = HookQuery::create()->findPk($event->getHookId())) { + $hook + ->setNative(!$hook->getNative()) + ->save(); + $event->setHook($hook); + } + } + + public function toggleActivation(HookToggleActivationEvent $event, $eventName, EventDispatcherInterface $dispatcher) + { + if (null !== $hook = HookQuery::create()->findPk($event->getHookId())) { + $hook + ->setActivate(!$hook->getActivate()) + ->save(); + $event->setHook($hook); + + $this->cacheClear($dispatcher); + } + } + + protected function cacheClear(EventDispatcherInterface $dispatcher) + { + $cacheEvent = new CacheEvent($this->cacheDir); + + $dispatcher->dispatch(TheliaEvents::CACHE_CLEAR, $cacheEvent); + } + + /** + * {@inheritdoc} + */ + public static function getSubscribedEvents() + { + return array( + TheliaEvents::HOOK_CREATE => array('create', 128), + TheliaEvents::HOOK_UPDATE => array('update', 128), + TheliaEvents::HOOK_DELETE => array('delete', 128), + TheliaEvents::HOOK_TOGGLE_ACTIVATION => array('toggleActivation', 128), + TheliaEvents::HOOK_TOGGLE_NATIVE => array('toggleNative', 128), + TheliaEvents::HOOK_CREATE_ALL => array('createAll', 128), + TheliaEvents::HOOK_DEACTIVATION => array('deactivation', 128), + + ); + } +} diff --git a/core/lib/Thelia/Action/HttpException.php b/core/lib/Thelia/Action/HttpException.php new file mode 100644 index 00000000..0cf5c285 --- /dev/null +++ b/core/lib/Thelia/Action/HttpException.php @@ -0,0 +1,114 @@ + + * @author Manuel Raynaud + */ +class HttpException extends BaseAction implements EventSubscriberInterface +{ + /** @var ParserInterface */ + protected $parser; + + public function __construct(ParserInterface $parser) + { + $this->parser = $parser; + } + + public function checkHttpException(GetResponseForExceptionEvent $event) + { + $exception = $event->getException(); + if ($exception instanceof NotFoundHttpException) { + $this->display404($event); + } + + if ($exception instanceof AdminAccessDenied) { + $this->displayAdminGeneralError($event); + } + + if ($exception instanceof BaseHttpException && null === $event->getResponse()) { + $this->displayException($event); + } + } + + protected function displayAdminGeneralError(GetResponseForExceptionEvent $event) + { + // Define the template thant shoud be used + $this->parser->setTemplateDefinition( + $this->parser->getTemplateHelper()->getActiveAdminTemplate() + ); + + $message = $event->getException()->getMessage(); + + $response = Response::create( + $this->parser->render( + 'general_error.html', + array( + "error_message" => $message + ) + ), + 403 + ); + + $event->setResponse($response); + } + + protected function display404(GetResponseForExceptionEvent $event) + { + // Define the template thant shoud be used + $this->parser->setTemplateDefinition( + $this->parser->getTemplateHelper()->getActiveFrontTemplate() + ); + + $response = new Response($this->parser->render(ConfigQuery::getPageNotFoundView()), 404); + + $event->setResponse($response); + } + + protected function displayException(GetResponseForExceptionEvent $event) + { + /** @var \Symfony\Component\HttpKernel\Exception\HttpException $exception */ + $exception = $event->getException(); + $event->setResponse( + new Response( + $exception->getMessage(), + $exception->getStatusCode(), + $exception->getHeaders() + ) + ); + } + + /** + * {@inheritdoc} + */ + public static function getSubscribedEvents() + { + return array( + KernelEvents::EXCEPTION => ["checkHttpException", 128], + ); + } +} diff --git a/core/lib/Thelia/Action/Image.php b/core/lib/Thelia/Action/Image.php new file mode 100644 index 00000000..64b9d599 --- /dev/null +++ b/core/lib/Thelia/Action/Image.php @@ -0,0 +1,431 @@ + + * + */ +class Image extends BaseCachedFile implements EventSubscriberInterface +{ + // Resize mode constants + const EXACT_RATIO_WITH_BORDERS = 1; + const EXACT_RATIO_WITH_CROP = 2; + const KEEP_IMAGE_RATIO = 3; + + /** + * @return string root of the image cache directory in web space + */ + protected function getCacheDirFromWebRoot() + { + return ConfigQuery::read('image_cache_dir_from_web_root', 'cache' . DS . 'images'); + } + + /** + * Process image and write the result in the image cache. + * + * If the image already exists in cache, the cache file is immediately returned, without any processing + * If the original (full resolution) image is required, create either a symbolic link with the + * original image in the cache dir, or copy it in the cache dir. + * + * This method updates the cache_file_path and file_url attributes of the event + * + * @param ImageEvent $event + * @param string $eventName + * @param EventDispatcherInterface $dispatcher + * + * @throws \Thelia\Exception\ImageException + * @throws \InvalidArgumentException + */ + public function processImage(ImageEvent $event, $eventName, EventDispatcherInterface $dispatcher) + { + $subdir = $event->getCacheSubdirectory(); + $source_file = $event->getSourceFilepath(); + + if (null == $subdir || null == $source_file) { + throw new \InvalidArgumentException("Cache sub-directory and source file path cannot be null"); + } + + // Find cached file path + $cacheFilePath = $this->getCacheFilePath($subdir, $source_file, $event->isOriginalImage(), $event->getOptionsHash()); + + $originalImagePathInCache = $this->getCacheFilePath($subdir, $source_file, true); + + if (! file_exists($cacheFilePath)) { + if (! file_exists($source_file)) { + throw new ImageException(sprintf("Source image file %s does not exists.", $source_file)); + } + + // Create a cached version of the original image in the web space, if not exists + + if (! file_exists($originalImagePathInCache)) { + $mode = ConfigQuery::read('original_image_delivery_mode', 'symlink'); + + if ($mode == 'symlink') { + if (false === symlink($source_file, $originalImagePathInCache)) { + throw new ImageException(sprintf("Failed to create symbolic link for %s in %s image cache directory", basename($source_file), $subdir)); + } + } else { + // mode = 'copy' + if (false === @copy($source_file, $originalImagePathInCache)) { + throw new ImageException(sprintf("Failed to copy %s in %s image cache directory", basename($source_file), $subdir)); + } + } + } + + // Process image only if we have some transformations to do. + if (! $event->isOriginalImage()) { + // We have to process the image. + $imagine = $this->createImagineInstance(); + + $image = $imagine->open($source_file); + + if ($image) { + // Allow image pre-processing (watermarging, or other stuff...) + $event->setImageObject($image); + $dispatcher->dispatch(TheliaEvents::IMAGE_PREPROCESSING, $event); + $image = $event->getImageObject(); + + $background_color = $event->getBackgroundColor(); + + $palette = new RGB(); + + if ($background_color != null) { + $bg_color = $palette->color($background_color); + } else { + // Define a fully transparent white background color + $bg_color = $palette->color('fff', 0); + } + + // Apply resize + $image = $this->applyResize( + $imagine, + $image, + $event->getWidth(), + $event->getHeight(), + $event->getResizeMode(), + $bg_color, + $event->getAllowZoom() + ); + + // Rotate if required + $rotation = \intval($event->getRotation()); + + if ($rotation != 0) { + $image->rotate($rotation, $bg_color); + } + + // Flip + // Process each effects + foreach ($event->getEffects() as $effect) { + $effect = trim(strtolower($effect)); + + $params = explode(':', $effect); + + switch ($params[0]) { + + case 'greyscale': + case 'grayscale': + $image->effects()->grayscale(); + break; + + case 'negative': + $image->effects()->negative(); + break; + + case 'horizontal_flip': + case 'hflip': + $image->flipHorizontally(); + break; + + case 'vertical_flip': + case 'vflip': + $image->flipVertically(); + break; + + case 'gamma': + // Syntax: gamma:value. Exemple: gamma:0.7 + if (isset($params[1])) { + $gamma = \floatval($params[1]); + + $image->effects()->gamma($gamma); + } + break; + + case 'colorize': + // Syntax: colorize:couleur. Exemple: colorize:#ff00cc + if (isset($params[1])) { + $the_color = $palette->color($params[1]); + + $image->effects()->colorize($the_color); + } + break; + + case 'blur': + if (isset($params[1])) { + $blur_level = \intval($params[1]); + + $image->effects()->blur($blur_level); + } + break; + } + } + + $quality = $event->getQuality(); + + if (\is_null($quality)) { + $quality = ConfigQuery::read('default_images_quality_percent', 75); + } + + // Allow image post-processing (watermarging, or other stuff...) + $event->setImageObject($image); + $dispatcher->dispatch(TheliaEvents::IMAGE_POSTPROCESSING, $event); + $image = $event->getImageObject(); + + $image->save( + $cacheFilePath, + array('quality' => $quality) + ); + } else { + throw new ImageException(sprintf("Source file %s cannot be opened.", basename($source_file))); + } + } + } + + // Compute the image URL + $processed_image_url = $this->getCacheFileURL($subdir, basename($cacheFilePath)); + + // compute the full resolution image path in cache + $original_image_url = $this->getCacheFileURL($subdir, basename($originalImagePathInCache)); + + // Update the event with file path and file URL + $event->setCacheFilepath($cacheFilePath); + $event->setCacheOriginalFilepath($originalImagePathInCache); + + $event->setFileUrl(URL::getInstance()->absoluteUrl($processed_image_url, null, URL::PATH_TO_FILE, $this->cdnBaseUrl)); + $event->setOriginalFileUrl(URL::getInstance()->absoluteUrl($original_image_url, null, URL::PATH_TO_FILE, $this->cdnBaseUrl)); + } + + /** + * Process image resizing, with borders or cropping. If $dest_width and $dest_height + * are both null, no resize is performed. + * + * @param ImagineInterface $imagine the Imagine instance + * @param ImageInterface $image the image to process + * @param int $dest_width the required width + * @param int $dest_height the required height + * @param int $resize_mode the resize mode (crop / bands / keep image ratio)p + * @param string $bg_color the bg_color used for bands + * @param bool $allow_zoom if true, image may be zoomed to matchrequired size. If false, image is not zoomed. + * @return ImageInterface the resized image. + */ + protected function applyResize( + ImagineInterface $imagine, + ImageInterface $image, + $dest_width, + $dest_height, + $resize_mode, + $bg_color, + $allow_zoom = false + ) { + if (! (\is_null($dest_width) && \is_null($dest_height))) { + $width_orig = $image->getSize()->getWidth(); + $height_orig = $image->getSize()->getHeight(); + + $ratio = $width_orig / $height_orig; + + if (\is_null($dest_width)) { + $dest_width = $dest_height * $ratio; + } + + if (\is_null($dest_height)) { + $dest_height = $dest_width / $ratio; + } + + if (\is_null($resize_mode)) { + $resize_mode = self::KEEP_IMAGE_RATIO; + } + + $width_diff = $dest_width / $width_orig; + $height_diff = $dest_height / $height_orig; + + $delta_x = $delta_y = $border_width = $border_height = 0; + + if ($width_diff > 1 && $height_diff > 1) { + // Set the default final size. If zoom is allowed, we will get the required + // 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 + // not smaller than the required size, zooming it if required. + if ($resize_mode == self::EXACT_RATIO_WITH_CROP) { + if ($allow_zoom) { + if ($width_diff > $height_diff) { + $resize_width = $dest_width; + $resize_height = \intval($height_orig * $dest_width / $width_orig); + $delta_y = ($resize_height - $dest_height) / 2; + } else { + $resize_height = $dest_height; + $resize_width = \intval(($width_orig * $resize_height) / $height_orig); + $delta_x = ($resize_width - $dest_width) / 2; + } + } else { + // No zoom : final image may be smaller than the required size. + $dest_width = $resize_width; + $dest_height = $resize_height; + } + } + } elseif ($width_diff > $height_diff) { + // Image height > image width + $resize_height = $dest_height; + $resize_width = \intval(($width_orig * $resize_height) / $height_orig); + + if ($resize_mode == self::EXACT_RATIO_WITH_CROP) { + $resize_width = $dest_width; + $resize_height = \intval($height_orig * $dest_width / $width_orig); + $delta_y = ($resize_height - $dest_height) / 2; + } elseif ($resize_mode != self::EXACT_RATIO_WITH_BORDERS) { + $dest_width = $resize_width; + } + } else { + // Image width > image height + $resize_width = $dest_width; + $resize_height = \intval($height_orig * $dest_width / $width_orig); + + if ($resize_mode == self::EXACT_RATIO_WITH_CROP) { + $resize_height = $dest_height; + $resize_width = \intval(($width_orig * $resize_height) / $height_orig); + $delta_x = ($resize_width - $dest_width) / 2; + } elseif ($resize_mode != self::EXACT_RATIO_WITH_BORDERS) { + $dest_height = $resize_height; + } + } + + $image->resize(new Box($resize_width, $resize_height)); + + if ($resize_mode == self::EXACT_RATIO_WITH_BORDERS) { + $border_width = \intval(($dest_width - $resize_width) / 2); + $border_height = \intval(($dest_height - $resize_height) / 2); + + $canvas = new Box($dest_width, $dest_height); + + return $imagine->create($canvas, $bg_color) + ->paste($image, new Point($border_width, $border_height)); + } elseif ($resize_mode == self::EXACT_RATIO_WITH_CROP) { + $image->crop( + new Point($delta_x, $delta_y), + new Box($dest_width, $dest_height) + ); + } + } + + return $image; + } + + /** + * Create a new Imagine object using current driver configuration + * + * @return ImagineInterface + */ + protected function createImagineInstance() + { + $driver = ConfigQuery::read("imagine_graphic_driver", "gd"); + + switch ($driver) { + case 'imagick': + $image = new ImagickImagine(); + break; + + case 'gmagick': + $image = new GmagickImagine(); + break; + + case 'gd': + default: + $image = new Imagine(); + } + + return $image; + } + + /** + * {@inheritdoc} + */ + public static function getSubscribedEvents() + { + return array( + TheliaEvents::IMAGE_PROCESS => array("processImage", 128), + + // Implemented in parent class BaseCachedFile + TheliaEvents::IMAGE_CLEAR_CACHE => array("clearCache", 128), + TheliaEvents::IMAGE_DELETE => array("deleteFile", 128), + TheliaEvents::IMAGE_SAVE => array("saveFile", 128), + TheliaEvents::IMAGE_UPDATE => array("updateFile", 128), + TheliaEvents::IMAGE_UPDATE_POSITION => array("updatePosition", 128), + TheliaEvents::IMAGE_TOGGLE_VISIBILITY => array("toggleVisibility", 128), + ); + } +} diff --git a/core/lib/Thelia/Action/Import.php b/core/lib/Thelia/Action/Import.php new file mode 100644 index 00000000..d610d1c1 --- /dev/null +++ b/core/lib/Thelia/Action/Import.php @@ -0,0 +1,79 @@ + + */ +class Import extends BaseAction implements EventSubscriberInterface +{ + /** + * @var \Thelia\Handler\ImportHandler The import handler + */ + protected $handler; + + /** + * @param \Thelia\Handler\ImportHandler $importHandler The import handler + */ + public function __construct(ImportHandler $importHandler) + { + $this->handler = $importHandler; + } + + public static function getSubscribedEvents() + { + return [ + TheliaEvents::IMPORT_CHANGE_POSITION => [ + ['importChangePosition', 128] + ], + TheliaEvents::IMPORT_CATEGORY_CHANGE_POSITION => [ + ['importCategoryChangePosition', 128] + ] + ]; + } + + /** + * Handle import change position event + * + * @param UpdatePositionEvent $updatePositionEvent + * @param $eventName + * @param EventDispatcherInterface $dispatcher + */ + public function importChangePosition(UpdatePositionEvent $updatePositionEvent, $eventName, EventDispatcherInterface $dispatcher) + { + $this->handler->getImport($updatePositionEvent->getObjectId(), true); + $this->genericUpdatePosition(new ImportQuery, $updatePositionEvent, $dispatcher); + } + + /** + * Handle import category change position event + * + * @param UpdatePositionEvent $updatePositionEvent + * @param $eventName + * @param EventDispatcherInterface $dispatcher + */ + public function importCategoryChangePosition(UpdatePositionEvent $updatePositionEvent, $eventName, EventDispatcherInterface $dispatcher) + { + $this->handler->getCategory($updatePositionEvent->getObjectId(), true); + $this->genericUpdatePosition(new ImportCategoryQuery, $updatePositionEvent, $dispatcher); + } +} diff --git a/core/lib/Thelia/Action/Lang.php b/core/lib/Thelia/Action/Lang.php new file mode 100644 index 00000000..b0fa3d97 --- /dev/null +++ b/core/lib/Thelia/Action/Lang.php @@ -0,0 +1,283 @@ + + */ +class Lang extends BaseAction implements EventSubscriberInterface +{ + /** @var TemplateHelperInterface */ + protected $templateHelper; + + /** @var RequestStack */ + protected $requestStack; + + public function __construct(TemplateHelperInterface $templateHelper, RequestStack $requestStack) + { + $this->templateHelper = $templateHelper; + $this->requestStack = $requestStack; + } + + /** + * @param LangUpdateEvent $event + * @param $eventName + * @param EventDispatcherInterface $dispatcher + * @throws \Propel\Runtime\Exception\PropelException + */ + public function update(LangUpdateEvent $event, $eventName, EventDispatcherInterface $dispatcher) + { + if (null !== $lang = LangQuery::create()->findPk($event->getId())) { + $lang->setDispatcher($dispatcher); + + $lang->setTitle($event->getTitle()) + ->setLocale($event->getLocale()) + ->setCode($event->getCode()) + ->setDateTimeFormat($event->getDateTimeFormat()) + ->setDateFormat($event->getDateFormat()) + ->setTimeFormat($event->getTimeFormat()) + ->setDecimalSeparator($event->getDecimalSeparator()) + ->setThousandsSeparator($event->getThousandsSeparator()) + ->setDecimals($event->getDecimals()) + ->save(); + + $event->setLang($lang); + } + } + + /** + * @param LangToggleDefaultEvent $event + * @param $eventName + * @param EventDispatcherInterface $dispatcher + * @throws \Propel\Runtime\Exception\PropelException + */ + public function toggleDefault(LangToggleDefaultEvent $event, $eventName, EventDispatcherInterface $dispatcher) + { + if (null !== $lang = LangQuery::create()->findPk($event->getLangId())) { + $lang->setDispatcher($dispatcher); + + $lang->toggleDefault(); + + $event->setLang($lang); + } + } + + /** + * @param LangToggleActiveEvent $event + * @throws \Propel\Runtime\Exception\PropelException + */ + public function toggleActive(LangToggleActiveEvent $event) + { + if (null !== $lang = LangQuery::create()->findPk($event->getLangId())) { + if ($lang->getByDefault()) { + throw new \RuntimeException( + Translator::getInstance()->trans('Cannot disable the default language') + ); + } + + $lang->setActive($lang->getActive() ? 0 : 1); + + if (!$lang->getActive()) { + $lang->setVisible(0); + } + + $lang->save(); + + $event->setLang($lang); + } + } + + /** + * @param LangToggleVisibleEvent $event + * @throws \Propel\Runtime\Exception\PropelException + */ + public function toggleVisible(LangToggleVisibleEvent $event) + { + if (null !== $lang = LangQuery::create()->findPk($event->getLangId())) { + if ($lang->getByDefault()) { + throw new \RuntimeException( + Translator::getInstance()->trans('Cannot hide the default language') + ); + } + + $lang->setVisible($lang->getVisible() ? 0 : 1); + + if (!$lang->getActive() && $lang->getVisible()) { + $lang->setActive(1); + } + + $lang->save(); + + $event->setLang($lang); + } + } + + /** + * @param LangCreateEvent $event + * @param $eventName + * @param EventDispatcherInterface $dispatcher + * @throws \Propel\Runtime\Exception\PropelException + */ + public function create(LangCreateEvent $event, $eventName, EventDispatcherInterface $dispatcher) + { + $lang = new LangModel(); + + $lang + ->setDispatcher($dispatcher) + ->setTitle($event->getTitle()) + ->setCode($event->getCode()) + ->setLocale($event->getLocale()) + ->setDateTimeFormat($event->getDateTimeFormat()) + ->setDateFormat($event->getDateFormat()) + ->setTimeFormat($event->getTimeFormat()) + ->setDecimalSeparator($event->getDecimalSeparator()) + ->setThousandsSeparator($event->getThousandsSeparator()) + ->setDecimals($event->getDecimals()) + ->save(); + + $event->setLang($lang); + } + + /** + * @param LangDeleteEvent $event + * @param $eventName + * @param EventDispatcherInterface $dispatcher + * @throws \Propel\Runtime\Exception\PropelException + */ + public function delete(LangDeleteEvent $event, $eventName, EventDispatcherInterface $dispatcher) + { + if (null !== $lang = LangQuery::create()->findPk($event->getLangId())) { + if ($lang->getByDefault()) { + throw new \RuntimeException( + Translator::getInstance()->trans('It is not allowed to delete the default language') + ); + } + + $lang->setDispatcher($dispatcher) + ->delete(); + + /** @var Session $session */ + $session = $this->requestStack->getCurrentRequest()->getSession(); + + // If we've just deleted the current admin edition language, set it to the default one. + if ($lang->getId() == $session->getAdminEditionLang()->getId()) { + $session->setAdminEditionLang(LangModel::getDefaultLanguage()); + } + + // If we've just deleted the current admin language, set it to the default one. + if ($lang->getId() == $session->getLang()->getId()) { + $session->setLang(LangModel::getDefaultLanguage()); + } + + $event->setLang($lang); + } + } + + /** + * @param LangDefaultBehaviorEvent $event + * @throws \Exception + * @throws \Propel\Runtime\Exception\PropelException + */ + public function defaultBehavior(LangDefaultBehaviorEvent $event) + { + ConfigQuery::create() + ->filterByName('default_lang_without_translation') + ->update(array('Value' => $event->getDefaultBehavior())); + } + + /** + * @param LangUrlEvent $event + * @throws \Exception + * @throws \Propel\Runtime\Exception\PropelException + */ + public function langUrl(LangUrlEvent $event) + { + foreach ($event->getUrl() as $id => $url) { + LangQuery::create() + ->filterById($id) + ->update(array('Url' => $url)); + } + } + + public function fixMissingFlag(LangEvent $event) + { + // Be sure that a lang have a flag, otherwise copy the + // "unknown" flag + $adminTemplate = $this->templateHelper->getActiveAdminTemplate(); + $unknownFlag = ConfigQuery::getUnknownFlagPath(); + + try { + $unknownFlagPath = $adminTemplate->getTemplateFilePath($unknownFlag); + + // Check if the country flag exists + $countryFlag = rtrim(dirname($unknownFlagPath), DS).DS.$event->getLang()->getCode().'.png'; + + if (! file_exists($countryFlag)) { + $fs = new Filesystem(); + + $fs->copy($unknownFlagPath, $countryFlag); + } + } catch (TemplateException $ex) { + throw new \RuntimeException( + Translator::getInstance()->trans( + "The image which replaces an undefined country flag (%file) was not found. Please check unknown-flag-path configuration variable, and check that the image exists.", + array("%file" => $unknownFlag) + ), + 0, + $ex + ); + } + } + + /** + * {@inheritdoc} + */ + public static function getSubscribedEvents() + { + return array( + TheliaEvents::LANG_UPDATE => array('update', 128), + TheliaEvents::LANG_TOGGLEDEFAULT => array('toggleDefault', 128), + TheliaEvents::LANG_TOGGLEACTIVE => array('toggleActive', 128), + TheliaEvents::LANG_TOGGLEVISIBLE => array('toggleVisible', 128), + TheliaEvents::LANG_CREATE => array('create', 128), + TheliaEvents::LANG_DELETE => array('delete', 128), + TheliaEvents::LANG_DEFAULTBEHAVIOR => array('defaultBehavior', 128), + TheliaEvents::LANG_URL => array('langUrl', 128), + TheliaEvents::LANG_FIX_MISSING_FLAG => array('fixMissingFlag', 128) + ); + } +} diff --git a/core/lib/Thelia/Action/MailingSystem.php b/core/lib/Thelia/Action/MailingSystem.php new file mode 100644 index 00000000..9d322972 --- /dev/null +++ b/core/lib/Thelia/Action/MailingSystem.php @@ -0,0 +1,51 @@ +getEnabled()) { + ConfigQuery::enableSmtp(); + } else { + ConfigQuery::disableSmtp(); + } + ConfigQuery::setSmtpHost($event->getHost()); + ConfigQuery::setSmtpPort($event->getPort()); + ConfigQuery::setSmtpEncryption($event->getEncryption()); + ConfigQuery::setSmtpUsername($event->getUsername()); + ConfigQuery::setSmtpPassword($event->getPassword()); + ConfigQuery::setSmtpAuthMode($event->getAuthMode()); + ConfigQuery::setSmtpTimeout($event->getTimeout()); + ConfigQuery::setSmtpSourceIp($event->getSourceIp()); + } + + /** + * {@inheritDoc} + */ + public static function getSubscribedEvents() + { + return array( + TheliaEvents::MAILING_SYSTEM_UPDATE => array("update", 128), + ); + } +} diff --git a/core/lib/Thelia/Action/Message.php b/core/lib/Thelia/Action/Message.php new file mode 100644 index 00000000..f78d307d --- /dev/null +++ b/core/lib/Thelia/Action/Message.php @@ -0,0 +1,116 @@ +setDispatcher($dispatcher) + + ->setName($event->getMessageName()) + ->setLocale($event->getLocale()) + ->setTitle($event->getTitle()) + ->setSecured($event->getSecured()) + + ->save() + ; + + $event->setMessage($message); + } + + /** + * Change a message + * + * @param \Thelia\Core\Event\Message\MessageUpdateEvent $event + * @param $eventName + * @param EventDispatcherInterface $dispatcher + */ + public function modify(MessageUpdateEvent $event, $eventName, EventDispatcherInterface $dispatcher) + { + if (null !== $message = MessageQuery::create()->findPk($event->getMessageId())) { + $message + ->setDispatcher($dispatcher) + + ->setName($event->getMessageName()) + ->setSecured($event->getSecured()) + + ->setLocale($event->getLocale()) + + ->setTitle($event->getTitle()) + ->setSubject($event->getSubject()) + + ->setHtmlMessage($event->getHtmlMessage()) + ->setTextMessage($event->getTextMessage()) + + ->setHtmlLayoutFileName($event->getHtmlLayoutFileName()) + ->setHtmlTemplateFileName($event->getHtmlTemplateFileName()) + ->setTextLayoutFileName($event->getTextLayoutFileName()) + ->setTextTemplateFileName($event->getTextTemplateFileName()) + + ->save(); + + $event->setMessage($message); + } + } + + /** + * Delete a messageuration entry + * + * @param \Thelia\Core\Event\Message\MessageDeleteEvent $event + * @param $eventName + * @param EventDispatcherInterface $dispatcher + */ + public function delete(MessageDeleteEvent $event, $eventName, EventDispatcherInterface $dispatcher) + { + if (null !== ($message = MessageQuery::create()->findPk($event->getMessageId()))) { + $message + ->setDispatcher($dispatcher) + ->delete() + ; + + $event->setMessage($message); + } + } + + /** + * {@inheritDoc} + */ + public static function getSubscribedEvents() + { + return array( + TheliaEvents::MESSAGE_CREATE => array("create", 128), + TheliaEvents::MESSAGE_UPDATE => array("modify", 128), + TheliaEvents::MESSAGE_DELETE => array("delete", 128), + ); + } +} diff --git a/core/lib/Thelia/Action/MetaData.php b/core/lib/Thelia/Action/MetaData.php new file mode 100644 index 00000000..b718630f --- /dev/null +++ b/core/lib/Thelia/Action/MetaData.php @@ -0,0 +1,75 @@ + + */ +class MetaData extends BaseAction implements EventSubscriberInterface +{ + public function createOrUpdate(MetaDataCreateOrUpdateEvent $event) + { + $metaData = MetaDataQuery::create() + ->filterByMetaKey($event->getMetaKey()) + ->filterByElementKey($event->getElementKey()) + ->filterByElementId($event->getElementId()) + ->findOne(); + + if (null === $metaData) { + $metaData = new MetaDataModel(); + $metaData + ->setMetaKey($event->getMetaKey()) + ->setElementKey($event->getElementkey()) + ->setElementId($event->getElementId()); + } + $metaData-> + setValue($event->getValue()); + $metaData->save(); + + $event->setMetaData($metaData); + } + + public function delete(MetaDataDeleteEvent $event) + { + $metaData = MetaDataQuery::create() + ->filterByMetaKey($event->getMetaKey()) + ->filterByElementKey($event->getElementKey()) + ->filterByElementId($event->getElementId()) + ->findOne(); + $event->setMetaData($metaData); + if (null !== $metaData) { + $metaData->delete(); + } + } + + /** + * @inheritdoc + */ + public static function getSubscribedEvents() + { + return array( + TheliaEvents::META_DATA_CREATE => array('createOrUpdate', 128), + TheliaEvents::META_DATA_UPDATE => array('createOrUpdate', 128), + TheliaEvents::META_DATA_DELETE => array('delete', 128), + ); + } +} diff --git a/core/lib/Thelia/Action/Module.php b/core/lib/Thelia/Action/Module.php new file mode 100644 index 00000000..c3d55345 --- /dev/null +++ b/core/lib/Thelia/Action/Module.php @@ -0,0 +1,467 @@ + + */ +class Module extends BaseAction implements EventSubscriberInterface +{ + /** @var ContainerInterface */ + protected $container; + + public function __construct(ContainerInterface $container) + { + $this->container = $container; + } + + public function toggleActivation(ModuleToggleActivationEvent $event, $eventName, EventDispatcherInterface $dispatcher) + { + if (null !== $module = ModuleQuery::create()->findPk($event->getModuleId())) { + $moduleInstance = $module->createInstance(); + + if (method_exists($moduleInstance, 'setContainer')) { + $moduleInstance->setContainer($this->container); + if ($module->getActivate() == BaseModule::IS_ACTIVATED) { + $moduleInstance->deActivate($module); + } else { + $moduleInstance->activate($module); + } + } + + $event->setModule($module); + + $this->cacheClear($dispatcher); + } + } + + public function checkToggleActivation(ModuleToggleActivationEvent $event, $eventName, EventDispatcherInterface $dispatcher) + { + if (true === $event->isNoCheck()) { + return; + } + + if (null !== $module = ModuleQuery::create()->findPk($event->getModuleId())) { + try { + 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()) { + $this->recursiveDeactivation($event, $eventName, $dispatcher); + } + $this->checkDeactivation($module); + } else { + if ($event->isRecursive()) { + $this->recursiveActivation($event, $eventName, $dispatcher); + } + $this->checkActivation($module); + } + } catch (\Exception $ex) { + $event->stopPropagation(); + throw $ex; + } + } + } + + /** + * Check if module can be activated : supported version of Thelia, module dependencies. + * + * @param \Thelia\Model\Module $module + * @throws Exception if activation fails. + * @return bool true if the module can be activated, otherwise false + */ + private function checkActivation($module) + { + try { + $moduleValidator = new ModuleValidator($module->getAbsoluteBaseDir()); + $moduleValidator->validate(false); + } catch (\Exception $ex) { + throw $ex; + } + + return true; + } + + /** + * Check if module can be deactivated safely because other modules + * could have dependencies to this module + * + * @param \Thelia\Model\Module $module + * @return bool true if the module can be deactivated, otherwise false + */ + private function checkDeactivation($module) + { + $moduleValidator = new ModuleValidator($module->getAbsoluteBaseDir()); + + $modules = $moduleValidator->getModulesDependOf(); + + if (\count($modules) > 0) { + $moduleList = implode(', ', array_column($modules, 'code')); + + $message = (\count($modules) == 1) + ? Translator::getInstance()->trans( + '%s has dependency to module %s. You have to deactivate this module before.' + ) + : Translator::getInstance()->trans( + '%s have dependencies to module %s. You have to deactivate these modules before.' + ); + + throw new ModuleException( + sprintf($message, $moduleList, $moduleValidator->getModuleDefinition()->getCode()) + ); + } + + return true; + } + + + /** + * Get dependencies of the current module and activate it if needed + * + * @param ModuleToggleActivationEvent $event + * @param $eventName + * @param EventDispatcherInterface $dispatcher + */ + public function recursiveActivation(ModuleToggleActivationEvent $event, $eventName, EventDispatcherInterface $dispatcher) + { + if (null !== $module = ModuleQuery::create()->findPk($event->getModuleId())) { + $moduleValidator = new ModuleValidator($module->getAbsoluteBaseDir()); + $dependencies = $moduleValidator->getCurrentModuleDependencies(); + foreach ($dependencies as $defMod) { + $submodule = ModuleQuery::create() + ->findOneByCode($defMod["code"]); + if ($submodule && $submodule->getActivate() != BaseModule::IS_ACTIVATED) { + $subevent = new ModuleToggleActivationEvent($submodule->getId()); + $subevent->setRecursive(true); + $dispatcher->dispatch(TheliaEvents::MODULE_TOGGLE_ACTIVATION, $subevent); + } + } + } + } + + /** + * Get modules having current module in dependence and deactivate it if needed + * + * @param ModuleToggleActivationEvent $event + * @param $eventName + * @param EventDispatcherInterface $dispatcher + */ + public function recursiveDeactivation(ModuleToggleActivationEvent $event, $eventName, EventDispatcherInterface $dispatcher) + { + if (null !== $module = ModuleQuery::create()->findPk($event->getModuleId())) { + $moduleValidator = new ModuleValidator($module->getAbsoluteBaseDir()); + $dependencies = $moduleValidator->getModulesDependOf(true); + foreach ($dependencies as $defMod) { + $submodule = ModuleQuery::create() + ->findOneByCode($defMod["code"]); + if ($submodule && $submodule->getActivate() == BaseModule::IS_ACTIVATED) { + $subevent = new ModuleToggleActivationEvent($submodule->getId()); + $subevent->setRecursive(true); + $dispatcher->dispatch(TheliaEvents::MODULE_TOGGLE_ACTIVATION, $subevent); + } + } + } + } + + public function delete(ModuleDeleteEvent $event, $eventName, EventDispatcherInterface $dispatcher) + { + $con = Propel::getWriteConnection(ModuleTableMap::DATABASE_NAME); + $con->beginTransaction(); + + if (null !== $module = ModuleQuery::create()->findPk($event->getModuleId(), $con)) { + try { + if (null === $module->getFullNamespace()) { + throw new \LogicException( + Translator::getInstance()->trans( + 'Cannot instantiate module "%name%": the namespace is null. Maybe the model is not loaded ?', + ['%name%' => $module->getCode()] + ) + ); + } + + // If the module is referenced by an order, display a meaningful error + // instead of 'delete cannot delete' caused by a constraint violation. + // FIXME: we hav to find a way to delete modules used by order. + if (OrderQuery::create()->filterByDeliveryModuleId($module->getId())->count() > 0 + || + OrderQuery::create()->filterByPaymentModuleId($module->getId())->count() > 0 + ) { + throw new \LogicException( + Translator::getInstance()->trans( + 'The module "%name%" is currently in use by at least one order, and can\'t be deleted.', + ['%name%' => $module->getCode()] + ) + ); + } + + 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 + $instance = $module->createInstance(); + + // Then, if module is activated, check if we can deactivate it + if ($module->getActivate()) { + // check for modules that depend of this one + $this->checkDeactivation($module); + } + + $instance->setContainer($this->container); + + $path = $module->getAbsoluteBaseDir(); + + $instance->destroy($con, $event->getDeleteData()); + + $fs = new Filesystem(); + $fs->remove($path); + } catch (\ReflectionException $ex) { + // Happens probably because the module directory has been deleted. + // Log a warning, and delete the database entry. + Tlog::getInstance()->addWarning( + Translator::getInstance()->trans( + 'Failed to create instance of module "%name%" when trying to delete module. Module directory has probably been deleted', + ['%name%' => $module->getCode()] + ) + ); + } catch (FileNotFoundException $fnfe) { + // The module directory has been deleted. + // Log a warning, and delete the database entry. + Tlog::getInstance()->addWarning( + Translator::getInstance()->trans( + 'Module "%name%" directory was not found', + ['%name%' => $module->getCode()] + ) + ); + } + + $module->delete($con); + + $con->commit(); + + $event->setModule($module); + $this->cacheClear($dispatcher); + } catch (\Exception $e) { + $con->rollBack(); + throw $e; + } + } + } + + /** + * @param ModuleEvent $event + * @param $eventName + * @param EventDispatcherInterface $dispatcher + */ + public function update(ModuleEvent $event, $eventName, EventDispatcherInterface $dispatcher) + { + if (null !== $module = ModuleQuery::create()->findPk($event->getId())) { + $module + ->setDispatcher($dispatcher) + ->setLocale($event->getLocale()) + ->setTitle($event->getTitle()) + ->setChapo($event->getChapo()) + ->setDescription($event->getDescription()) + ->setPostscriptum($event->getPostscriptum()); + + $module->save(); + + $event->setModule($module); + } + } + + /** + * @param \Thelia\Core\Event\Module\ModuleInstallEvent $event + * @param $eventName + * @param EventDispatcherInterface $dispatcher + * + * @throws \Exception + * @throws \Symfony\Component\Filesystem\Exception\IOException + * @throws \Exception + */ + public function install(ModuleInstallEvent $event, $eventName, EventDispatcherInterface $dispatcher) + { + $moduleDefinition = $event->getModuleDefinition(); + + $oldModule = ModuleQuery::create()->findOneByFullNamespace($moduleDefinition->getNamespace()); + + $fs = new Filesystem(); + + $activated = false; + + // check existing module + if (null !== $oldModule) { + $activated = $oldModule->getActivate(); + + if ($activated) { + // deactivate + $toggleEvent = new ModuleToggleActivationEvent($oldModule->getId()); + // disable the check of the module because it's already done + $toggleEvent->setNoCheck(true); + + $dispatcher->dispatch(TheliaEvents::MODULE_TOGGLE_ACTIVATION, $toggleEvent); + } + + // delete + $modulePath = $oldModule->getAbsoluteBaseDir(); + + $deleteEvent = new ModuleDeleteEvent($oldModule); + + try { + $dispatcher->dispatch(TheliaEvents::MODULE_DELETE, $deleteEvent); + } catch (Exception $ex) { + // if module has not been deleted + if ($fs->exists($modulePath)) { + throw $ex; + } + } + } + + // move new module + $modulePath = sprintf('%s%s', THELIA_MODULE_DIR, $event->getModuleDefinition()->getCode()); + + try { + $fs->mirror($event->getModulePath(), $modulePath); + } catch (IOException $ex) { + if (!$fs->exists($modulePath)) { + throw $ex; + } + } + + // Update the module + $moduleDescriptorFile = sprintf('%s%s%s%s%s', $modulePath, DS, 'Config', DS, 'module.xml'); + $moduleManagement = new ModuleManagement($this->container); + $file = new SplFileInfo($moduleDescriptorFile); + $module = $moduleManagement->updateModule($file, $this->container); + + // activate if old was activated + if ($activated) { + $toggleEvent = new ModuleToggleActivationEvent($module->getId()); + $toggleEvent->setNoCheck(true); + + $dispatcher->dispatch(TheliaEvents::MODULE_TOGGLE_ACTIVATION, $toggleEvent); + } + + $event->setModule($module); + } + + /** + * Call the payment method of the payment module of the given order + * + * @param OrderPaymentEvent $event + * + * @throws \RuntimeException if no payment module can be found. + */ + public function pay(OrderPaymentEvent $event) + { + $order = $event->getOrder(); + + /* call pay method */ + if (null === $paymentModule = ModuleQuery::create()->findPk($order->getPaymentModuleId())) { + throw new \RuntimeException( + Translator::getInstance()->trans( + "Failed to find a payment Module with ID=%mid for order ID=%oid", + [ + "%mid" => $order->getPaymentModuleId(), + "%oid" => $order->getId() + ] + ) + ); + } + + $paymentModuleInstance = $paymentModule->getPaymentModuleInstance($this->container); + + $response = $paymentModuleInstance->pay($order); + + if (null !== $response && $response instanceof Response) { + $event->setResponse($response); + } + } + + /** + * Changes position, selecting absolute ou relative change. + * + * @param UpdatePositionEvent $event + * @param $eventName + * @param EventDispatcherInterface $dispatcher + */ + public function updatePosition(UpdatePositionEvent $event, $eventName, EventDispatcherInterface $dispatcher) + { + $this->genericUpdatePosition(ModuleQuery::create(), $event, $dispatcher); + + $this->cacheClear($dispatcher); + } + + protected function cacheClear(EventDispatcherInterface $dispatcher) + { + $cacheEvent = new CacheEvent( + $this->container->getParameter('kernel.cache_dir') + ); + + $dispatcher->dispatch(TheliaEvents::CACHE_CLEAR, $cacheEvent); + } + + /** + * @inheritdoc + */ + public static function getSubscribedEvents() + { + return [ + TheliaEvents::MODULE_TOGGLE_ACTIVATION => [ + ['checkToggleActivation', 255], + ['toggleActivation', 128], + ], + TheliaEvents::MODULE_UPDATE_POSITION => ['updatePosition', 128], + TheliaEvents::MODULE_DELETE => ['delete', 128], + TheliaEvents::MODULE_UPDATE => ['update', 128], + TheliaEvents::MODULE_INSTALL => ['install', 128], + TheliaEvents::MODULE_PAY => ['pay', 128], + ]; + } +} diff --git a/core/lib/Thelia/Action/ModuleHook.php b/core/lib/Thelia/Action/ModuleHook.php new file mode 100644 index 00000000..d556ed15 --- /dev/null +++ b/core/lib/Thelia/Action/ModuleHook.php @@ -0,0 +1,252 @@ + + */ +class ModuleHook extends BaseAction implements EventSubscriberInterface +{ + /** @var string */ + protected $cacheDir; + + public function __construct($cacheDir) + { + $this->cacheDir = $cacheDir; + } + + public function toggleModuleActivation(ModuleToggleActivationEvent $event) + { + if (null !== $module = ModuleQuery::create()->findPk($event->getModuleId())) { + ModuleHookQuery::create() + ->filterByModuleId($module->getId()) + ->update(array('ModuleActive' => ($module->getActivate() == BaseModule::IS_ACTIVATED))); + } + + return $event; + } + + public function deleteModule(ModuleDeleteEvent $event) + { + if ($event->getModuleId()) { + ModuleHookQuery::create() + ->filterByModuleId($event->getModuleId()) + ->delete(); + } + + return $event; + } + + protected function isModuleActive($module_id) + { + if (null !== $module = ModuleQuery::create()->findPk($module_id)) { + return $module->getActivate(); + } + + return false; + } + + protected function isHookActive($hook_id) + { + if (null !== $hook = HookQuery::create()->findPk($hook_id)) { + return $hook->getActivate(); + } + + return false; + } + + protected function getLastPositionInHook($hook_id) + { + $result = ModuleHookQuery::create() + ->filterByHookId($hook_id) + ->withColumn('MAX(ModuleHook.position)', 'maxPos') + ->groupBy('ModuleHook.hook_id') + ->select(array('maxPos')) + ->findOne(); + + return \intval($result) + 1; + } + + public function createModuleHook(ModuleHookCreateEvent $event) + { + $moduleHook = new ModuleHookModel(); + + // todo: test if classname and method exists + $moduleHook + ->setModuleId($event->getModuleId()) + ->setHookId($event->getHookId()) + ->setActive(false) + ->setClassname($event->getClassname()) + ->setMethod($event->getMethod()) + ->setModuleActive($this->isModuleActive($event->getModuleId())) + ->setHookActive($this->isHookActive($event->getHookId())) + ->setPosition($this->getLastPositionInHook($event->getHookId())) + ->setTemplates($event->getTemplates()) + ->save(); + + // Be sure to delete this module hook from the ignored module hook table + IgnoredModuleHookQuery::create() + ->filterByHookId($event->getHookId()) + ->filterByModuleId($event->getModuleId()) + ->delete(); + + $event->setModuleHook($moduleHook); + } + + public function updateModuleHook(ModuleHookUpdateEvent $event, $eventName, EventDispatcherInterface $dispatcher) + { + if (null !== $moduleHook = ModuleHookQuery::create()->findPk($event->getModuleHookId())) { + // todo: test if classname and method exists + $moduleHook + ->setHookId($event->getHookId()) + ->setModuleId($event->getModuleId()) + ->setClassname($event->getClassname()) + ->setMethod($event->getMethod()) + ->setActive($event->getActive()) + ->setHookActive($this->isHookActive($event->getHookId())) + ->setTemplates($event->getTemplates()) + ->save(); + + $event->setModuleHook($moduleHook); + + $this->cacheClear($dispatcher); + } + } + + public function deleteModuleHook(ModuleHookDeleteEvent $event, $eventName, EventDispatcherInterface $dispatcher) + { + if (null !== $moduleHook = ModuleHookQuery::create()->findPk($event->getModuleHookId())) { + $moduleHook->delete(); + $event->setModuleHook($moduleHook); + + // Prevent hook recreation by RegisterListenersPass::registerHook() + // We store the method here to be able to retreive it when + // we need to get all hook declared by a module + $imh = new IgnoredModuleHook(); + $imh + ->setModuleId($moduleHook->getModuleId()) + ->setHookId($moduleHook->getHookId()) + ->setMethod($moduleHook->getMethod()) + ->setClassname($moduleHook->getClassname()) + ->save(); + + $this->cacheClear($dispatcher); + } + } + + public function toggleModuleHookActivation(ModuleHookToggleActivationEvent $event, $eventName, EventDispatcherInterface $dispatcher) + { + if (null !== $moduleHook = $event->getModuleHook()) { + if ($moduleHook->getModuleActive()) { + $moduleHook->setActive(!$moduleHook->getActive()); + $moduleHook->save(); + } else { + throw new \LogicException(Translator::getInstance()->trans("The module has to be activated.")); + } + } + $this->cacheClear($dispatcher); + + return $event; + } + + /** + * Changes position, selecting absolute ou relative change. + * + * @param UpdatePositionEvent $event + * @param $eventName + * @param EventDispatcherInterface $dispatcher + * + * @return UpdatePositionEvent $event + */ + public function updateModuleHookPosition(UpdatePositionEvent $event, $eventName, EventDispatcherInterface $dispatcher) + { + $this->genericUpdatePosition(ModuleHookQuery::create(), $event, $dispatcher); + $this->cacheClear($dispatcher); + + return $event; + } + + public function updateHook(HookUpdateEvent $event, $eventName, EventDispatcherInterface $dispatcher) + { + if ($event->hasHook()) { + $hook = $event->getHook(); + ModuleHookQuery::create() + ->filterByHookId($hook->getId()) + ->update(array('HookActive' => $hook->getActivate())); + $this->cacheClear($dispatcher); + } + } + + public function toggleHookActivation(HookToggleActivationEvent $event, $eventName, EventDispatcherInterface $dispatcher) + { + if ($event->hasHook()) { + $hook = $event->getHook(); + ModuleHookQuery::create() + ->filterByHookId($hook->getId()) + ->update(array('HookActive' => $hook->getActivate())); + $this->cacheClear($dispatcher); + } + } + + protected function cacheClear(EventDispatcherInterface $dispatcher) + { + $cacheEvent = new CacheEvent($this->cacheDir); + + $dispatcher->dispatch(TheliaEvents::CACHE_CLEAR, $cacheEvent); + } + + /** + * {@inheritdoc} + */ + public static function getSubscribedEvents() + { + return array( + TheliaEvents::MODULE_HOOK_CREATE => array('createModuleHook', 128), + TheliaEvents::MODULE_HOOK_UPDATE => array('updateModuleHook', 128), + TheliaEvents::MODULE_HOOK_DELETE => array('deleteModuleHook', 128), + TheliaEvents::MODULE_HOOK_UPDATE_POSITION => array('updateModuleHookPosition', 128), + TheliaEvents::MODULE_HOOK_TOGGLE_ACTIVATION => array('toggleModuleHookActivation', 128), + + TheliaEvents::MODULE_TOGGLE_ACTIVATION => array('toggleModuleActivation', 64), + TheliaEvents::MODULE_DELETE => array('deleteModule', 64), + + TheliaEvents::HOOK_TOGGLE_ACTIVATION => array('toggleHookActivation', 64), + TheliaEvents::HOOK_UPDATE => array('updateHook', 64), + + ); + } +} diff --git a/core/lib/Thelia/Action/Newsletter.php b/core/lib/Thelia/Action/Newsletter.php new file mode 100644 index 00000000..be214c44 --- /dev/null +++ b/core/lib/Thelia/Action/Newsletter.php @@ -0,0 +1,120 @@ + + */ +class Newsletter extends BaseAction implements EventSubscriberInterface +{ + /** @var MailerFactory */ + protected $mailer; + + /** @var EventDispatcherInterface */ + protected $dispatcher; + + public function __construct(MailerFactory $mailer, EventDispatcherInterface $dispatcher) + { + $this->mailer = $mailer; + $this->dispatcher = $dispatcher; + } + + public function subscribe(NewsletterEvent $event) + { + // test if the email is already registered and unsubscribed + if (null === $newsletter = NewsletterQuery::create()->findOneByEmail($event->getEmail())) { + $newsletter = new NewsletterModel(); + } + + $newsletter + ->setEmail($event->getEmail()) + ->setFirstname($event->getFirstname()) + ->setLastname($event->getLastname()) + ->setLocale($event->getLocale()) + ->setUnsubscribed(false) + ->save(); + + $event->setNewsletter($newsletter); + + if (ConfigQuery::getNotifyNewsletterSubscription()) { + $this->dispatcher->dispatch(TheliaEvents::NEWSLETTER_CONFIRM_SUBSCRIPTION, $event); + } + } + + public function unsubscribe(NewsletterEvent $event) + { + if (null !== $nl = NewsletterQuery::create()->findPk($event->getId())) { + $nl + ->setUnsubscribed(true) + ->save(); + + $event->setNewsletter($nl); + } + } + + public function update(NewsletterEvent $event) + { + if (null !== $nl = NewsletterQuery::create()->findPk($event->getId())) { + $nl->setEmail($event->getEmail()) + ->setFirstname($event->getFirstname()) + ->setLastname($event->getLastname()) + ->setUnsubscribed(false) + ->setLocale($event->getLocale()) + ->save(); + + $event->setNewsletter($nl); + } + } + + /** + * @since 2.3.0-alpha2 + */ + public function confirmSubscription(NewsletterEvent $event) + { + $this->mailer->sendEmailMessage( + 'newsletter_subscription_confirmation', + [ ConfigQuery::getStoreEmail() => ConfigQuery::getStoreName() ], + [ $event->getEmail() => $event->getFirstname()." ".$event->getLastname() ], + [ + 'email' => $event->getEmail(), + 'firstname' => $event->getFirstname(), + 'lastname' => $event->getLastname() + ], + $event->getLocale() + ); + } + + /** + * {@inheritdoc} + */ + public static function getSubscribedEvents() + { + return array( + TheliaEvents::NEWSLETTER_SUBSCRIBE => array('subscribe', 128), + TheliaEvents::NEWSLETTER_UPDATE => array('update', 128), + TheliaEvents::NEWSLETTER_UNSUBSCRIBE => array('unsubscribe', 128), + TheliaEvents::NEWSLETTER_CONFIRM_SUBSCRIPTION => array('confirmSubscription', 128) + ); + } +} diff --git a/core/lib/Thelia/Action/Order.php b/core/lib/Thelia/Action/Order.php new file mode 100644 index 00000000..383232c9 --- /dev/null +++ b/core/lib/Thelia/Action/Order.php @@ -0,0 +1,753 @@ + + * @author Franck Allimant + */ +class Order extends BaseAction implements EventSubscriberInterface +{ + /** @var RequestStack */ + protected $requestStack; + + /** @var MailerFactory */ + protected $mailer; + + /** @var SecurityContext */ + protected $securityContext; + + public function __construct(RequestStack $requestStack, MailerFactory $mailer, SecurityContext $securityContext) + { + $this->requestStack = $requestStack; + $this->mailer = $mailer; + $this->securityContext = $securityContext; + } + + /** + * @param \Thelia\Core\Event\Order\OrderEvent $event + */ + public function setDeliveryAddress(OrderEvent $event) + { + $order = $event->getOrder(); + + $order->setChoosenDeliveryAddress($event->getDeliveryAddress()); + + $event->setOrder($order); + } + + /** + * @param \Thelia\Core\Event\Order\OrderEvent $event + */ + public function setDeliveryModule(OrderEvent $event) + { + $order = $event->getOrder(); + + $deliveryModuleId = $event->getDeliveryModule(); + + $order->setDeliveryModuleId($deliveryModuleId); + + // Reset postage cost if the delivery module had been removed + if ($deliveryModuleId <= 0) { + $order->setPostage(0); + $order->setPostageTax(0); + $order->setPostageTaxRuleTitle(null); + } + + $event->setOrder($order); + } + + /** + * @param \Thelia\Core\Event\Order\OrderEvent $event + */ + public function setPostage(OrderEvent $event) + { + $order = $event->getOrder(); + + $order->setPostage($event->getPostage()); + $order->setPostageTax($event->getPostageTax()); + $order->setPostageTaxRuleTitle($event->getPostageTaxRuleTitle()); + + $event->setOrder($order); + } + + /** + * @param \Thelia\Core\Event\Order\OrderEvent $event + */ + public function setInvoiceAddress(OrderEvent $event) + { + $order = $event->getOrder(); + + $order->setChoosenInvoiceAddress($event->getInvoiceAddress()); + + $event->setOrder($order); + } + + /** + * @param \Thelia\Core\Event\Order\OrderEvent $event + */ + public function setPaymentModule(OrderEvent $event) + { + $order = $event->getOrder(); + + $order->setPaymentModuleId($event->getPaymentModule()); + + $event->setOrder($order); + } + + /** + * @param EventDispatcherInterface $dispatcher + * @param ModelOrder $sessionOrder + * @param CurrencyModel $currency + * @param LangModel $lang + * @param CartModel $cart + * @param UserInterface $customer + * @param bool $unusedArgument deprecated argument. Will be removed in 2.5 + * @param bool $useOrderDefinedAddresses if true, the delivery and invoice OrderAddresses will be used instead of creating new OrderAdresses using Order::getChoosenXXXAddress() + * @return ModelOrder + * @throws \Exception + * @throws \Propel\Runtime\Exception\PropelException + */ + protected function createOrder( + EventDispatcherInterface $dispatcher, + ModelOrder $sessionOrder, + CurrencyModel $currency, + LangModel $lang, + CartModel $cart, + UserInterface $customer, + $unusedArgument = null, + $useOrderDefinedAddresses = false + ) { + $con = Propel::getConnection( + OrderTableMap::DATABASE_NAME + ); + + $con->beginTransaction(); + + $placedOrder = $sessionOrder->copy(); + + // Be sure to create a brand new order, as copy raises the modified flag for all fields + // and will also copy order reference and id. + $placedOrder->setId(null)->setRef(null)->setNew(true); + + // Dates should be marked as not updated so that Propel will update them. + $placedOrder->resetModified(OrderTableMap::COL_CREATED_AT); + $placedOrder->resetModified(OrderTableMap::COL_UPDATED_AT); + $placedOrder->resetModified(OrderTableMap::COL_VERSION_CREATED_AT); + + $placedOrder->setDispatcher($dispatcher); + + $cartItems = $cart->getCartItems(); + + /* fulfill order */ + $placedOrder->setCustomerId($customer->getId()); + $placedOrder->setCurrencyId($currency->getId()); + $placedOrder->setCurrencyRate($currency->getRate()); + $placedOrder->setLangId($lang->getId()); + + if ($useOrderDefinedAddresses) { + $taxCountry = + OrderAddressQuery::create() + ->findPk($placedOrder->getDeliveryOrderAddressId()) + ->getCountry() + ; + } else { + $deliveryAddress = AddressQuery::create()->findPk($sessionOrder->getChoosenDeliveryAddress()); + $invoiceAddress = AddressQuery::create()->findPk($sessionOrder->getChoosenInvoiceAddress()); + + /* hard save the delivery and invoice addresses */ + $deliveryOrderAddress = new OrderAddress(); + $deliveryOrderAddress + ->setCustomerTitleId($deliveryAddress->getTitleId()) + ->setCompany($deliveryAddress->getCompany()) + ->setFirstname($deliveryAddress->getFirstname()) + ->setLastname($deliveryAddress->getLastname()) + ->setAddress1($deliveryAddress->getAddress1()) + ->setAddress2($deliveryAddress->getAddress2()) + ->setAddress3($deliveryAddress->getAddress3()) + ->setZipcode($deliveryAddress->getZipcode()) + ->setCity($deliveryAddress->getCity()) + ->setPhone($deliveryAddress->getPhone()) + ->setCellphone($deliveryAddress->getCellphone()) + ->setCountryId($deliveryAddress->getCountryId()) + ->setStateId($deliveryAddress->getStateId()) + ->save($con); + + $invoiceOrderAddress = new OrderAddress(); + $invoiceOrderAddress + ->setCustomerTitleId($invoiceAddress->getTitleId()) + ->setCompany($invoiceAddress->getCompany()) + ->setFirstname($invoiceAddress->getFirstname()) + ->setLastname($invoiceAddress->getLastname()) + ->setAddress1($invoiceAddress->getAddress1()) + ->setAddress2($invoiceAddress->getAddress2()) + ->setAddress3($invoiceAddress->getAddress3()) + ->setZipcode($invoiceAddress->getZipcode()) + ->setCity($invoiceAddress->getCity()) + ->setPhone($invoiceAddress->getPhone()) + ->setCellphone($invoiceAddress->getCellphone()) + ->setCountryId($invoiceAddress->getCountryId()) + ->setStateId($deliveryAddress->getStateId()) + ->save($con); + + $placedOrder->setDeliveryOrderAddressId($deliveryOrderAddress->getId()); + $placedOrder->setInvoiceOrderAddressId($invoiceOrderAddress->getId()); + + $taxCountry = $deliveryAddress->getCountry(); + } + + $placedOrder->setStatusId( + OrderStatusQuery::getNotPaidStatus()->getId() + ); + + $placedOrder->setCartId($cart->getId()); + + /* memorize discount */ + $placedOrder->setDiscount( + $cart->getDiscount() + ); + + $placedOrder->save($con); + + $manageStock = $placedOrder->isStockManagedOnOrderCreation($dispatcher); + + /* fulfill order_products and decrease stock */ + + foreach ($cartItems as $cartItem) { + $product = $cartItem->getProduct(); + + /* get translation */ + /** @var ProductI18n $productI18n */ + $productI18n = I18n::forceI18nRetrieving($lang->getLocale(), 'Product', $product->getId()); + + $pse = $cartItem->getProductSaleElements(); + + // get the virtual document path + $virtualDocumentEvent = new VirtualProductOrderHandleEvent($placedOrder, $pse->getId()); + // essentially used for virtual product. modules that handles virtual product can + // allow the use of stock even for virtual products + $useStock = true; + $virtual = 0; + + // if the product is virtual, dispatch an event to collect information + if ($product->getVirtual() === 1) { + $dispatcher->dispatch(TheliaEvents::VIRTUAL_PRODUCT_ORDER_HANDLE, $virtualDocumentEvent); + $useStock = $virtualDocumentEvent->isUseStock(); + $virtual = $virtualDocumentEvent->isVirtual() ? 1 : 0; + } + + /* check still in stock */ + if ($cartItem->getQuantity() > $pse->getQuantity() + && true === ConfigQuery::checkAvailableStock() + && $useStock) { + throw new TheliaProcessException("Not enough stock", TheliaProcessException::CART_ITEM_NOT_ENOUGH_STOCK, $cartItem); + } + + if ($useStock && $manageStock) { + /* decrease stock for non virtual product */ + $allowNegativeStock = \intval(ConfigQuery::read('allow_negative_stock', 0)); + $newStock = $pse->getQuantity() - $cartItem->getQuantity(); + //Forbid negative stock + if ($newStock < 0 && 0 === $allowNegativeStock) { + $newStock = 0; + } + $pse->setQuantity( + $newStock + ); + + $pse->save($con); + } + + /* get tax */ + /** @var TaxRuleI18n $taxRuleI18n */ + $taxRuleI18n = I18n::forceI18nRetrieving($lang->getLocale(), 'TaxRule', $product->getTaxRuleId()); + + $taxDetail = $product->getTaxRule()->getTaxDetail( + $product, + $taxCountry, + $cartItem->getPrice(), + $cartItem->getPromoPrice(), + $lang->getLocale() + ); + + $orderProduct = new OrderProduct(); + $orderProduct + ->setOrderId($placedOrder->getId()) + ->setProductRef($product->getRef()) + ->setProductSaleElementsRef($pse->getRef()) + ->setProductSaleElementsId($pse->getId()) + ->setTitle($productI18n->getTitle()) + ->setChapo($productI18n->getChapo()) + ->setDescription($productI18n->getDescription()) + ->setPostscriptum($productI18n->getPostscriptum()) + ->setVirtual($virtual) + ->setVirtualDocument($virtualDocumentEvent->getPath()) + ->setQuantity($cartItem->getQuantity()) + ->setPrice($cartItem->getPrice()) + ->setPromoPrice($cartItem->getPromoPrice()) + ->setWasNew($pse->getNewness()) + ->setWasInPromo($cartItem->getPromo()) + ->setWeight($pse->getWeight()) + ->setTaxRuleTitle($taxRuleI18n->getTitle()) + ->setTaxRuleDescription($taxRuleI18n->getDescription()) + ->setEanCode($pse->getEanCode()) + ->setCartItemId($cartItem->getId()) + ->setDispatcher($dispatcher) + ->save($con) + ; + + /* fulfill order_product_tax */ + /** @var OrderProductTax $tax */ + foreach ($taxDetail as $tax) { + $tax->setOrderProductId($orderProduct->getId()); + $tax->save($con); + } + + /* fulfill order_attribute_combination and decrease stock */ + foreach ($pse->getAttributeCombinations() as $attributeCombination) { + /** @var \Thelia\Model\Attribute $attribute */ + $attribute = I18n::forceI18nRetrieving($lang->getLocale(), 'Attribute', $attributeCombination->getAttributeId()); + + /** @var \Thelia\Model\AttributeAv $attributeAv */ + $attributeAv = I18n::forceI18nRetrieving($lang->getLocale(), 'AttributeAv', $attributeCombination->getAttributeAvId()); + + $orderAttributeCombination = new OrderProductAttributeCombination(); + $orderAttributeCombination + ->setOrderProductId($orderProduct->getId()) + ->setAttributeTitle($attribute->getTitle()) + ->setAttributeChapo($attribute->getChapo()) + ->setAttributeDescription($attribute->getDescription()) + ->setAttributePostscriptum($attribute->getPostscriptum()) + ->setAttributeAvTitle($attributeAv->getTitle()) + ->setAttributeAvChapo($attributeAv->getChapo()) + ->setAttributeAvDescription($attributeAv->getDescription()) + ->setAttributeAvPostscriptum($attributeAv->getPostscriptum()) + ->save($con); + } + } + + $con->commit(); + + return $placedOrder; + } + + /** + * Create an order outside of the front-office context, e.g. manually from the back-office. + * @param OrderManualEvent $event + * @param $eventName + * @param EventDispatcherInterface $dispatcher + * @throws \Exception + * @throws \Propel\Runtime\Exception\PropelException + */ + public function createManual(OrderManualEvent $event, $eventName, EventDispatcherInterface $dispatcher) + { + $event->setPlacedOrder( + $this->createOrder( + $dispatcher, + $event->getOrder(), + $event->getCurrency(), + $event->getLang(), + $event->getCart(), + $event->getCustomer(), + null, + $event->getUseOrderDefinedAddresses() + ) + ); + + $event->setOrder(new OrderModel()); + } + + /** + * @param OrderEvent $event + * + * @throws \Thelia\Exception\TheliaProcessException + * @param $eventName + * @param EventDispatcherInterface $dispatcher + * @throws \Exception + * @throws \Propel\Runtime\Exception\PropelException + */ + public function create(OrderEvent $event, $eventName, EventDispatcherInterface $dispatcher) + { + $session = $this->getSession(); + + $order = $event->getOrder(); + $paymentModule = ModuleQuery::create()->findPk($order->getPaymentModuleId()); + + $placedOrder = $this->createOrder( + $dispatcher, + $event->getOrder(), + $session->getCurrency(), + $session->getLang(), + $session->getSessionCart($dispatcher), + $this->securityContext->getCustomerUser() + ); + + $dispatcher->dispatch(TheliaEvents::ORDER_BEFORE_PAYMENT, new OrderEvent($placedOrder)); + + /* but memorize placed order */ + $event->setOrder(new OrderModel()); + $event->setPlacedOrder($placedOrder); + + /* call pay method */ + $payEvent = new OrderPaymentEvent($placedOrder); + + $dispatcher->dispatch(TheliaEvents::MODULE_PAY, $payEvent); + + if ($payEvent->hasResponse()) { + $event->setResponse($payEvent->getResponse()); + } + } + + /** + * @param OrderEvent $event + * @param $eventName + * @param EventDispatcherInterface $dispatcher + */ + public function orderBeforePayment(OrderEvent $event, $eventName, EventDispatcherInterface $dispatcher) + { + $dispatcher->dispatch(TheliaEvents::ORDER_SEND_CONFIRMATION_EMAIL, clone $event); + + $dispatcher->dispatch(TheliaEvents::ORDER_SEND_NOTIFICATION_EMAIL, clone $event); + } + + /** + * Clear the cart and the order in the customer session once the order is placed, + * and the payment performed. + * + * @param OrderEvent $event + * @param $eventName + * @param EventDispatcherInterface $dispatcher + */ + public function orderCartClear(/** @noinspection PhpUnusedParameterInspection */ OrderEvent $event, $eventName, EventDispatcherInterface $dispatcher) + { + // Empty cart and clear current order + $session = $this->getSession(); + + $session->clearSessionCart($dispatcher); + + $session->setOrder(new OrderModel()); + } + + /** + * @param OrderEvent $event + * + * @throws \Exception if the message cannot be loaded. + */ + public function sendConfirmationEmail(OrderEvent $event) + { + $this->mailer->sendEmailToCustomer( + 'order_confirmation', + $event->getOrder()->getCustomer(), + [ + 'order_id' => $event->getOrder()->getId(), + 'order_ref' => $event->getOrder()->getRef() + ] + ); + } + + /** + * @param OrderEvent $event + * + * @throws \Exception if the message cannot be loaded. + */ + public function sendNotificationEmail(OrderEvent $event) + { + $this->mailer->sendEmailToShopManagers( + 'order_notification', + [ + 'order_id' => $event->getOrder()->getId(), + 'order_ref' => $event->getOrder()->getRef() + ] + ); + } + + /** + * @param OrderEvent $event + * @param $eventName + * @param EventDispatcherInterface $dispatcher + * @throws \Exception + * @throws \Propel\Runtime\Exception\PropelException + */ + public function updateStatus(OrderEvent $event, $eventName, EventDispatcherInterface $dispatcher) + { + $order = $event->getOrder(); + $newStatus = $event->getStatus(); + + $con = Propel::getConnection(OrderTableMap::DATABASE_NAME); + + // Prevent partial stock update on status change. + $con->beginTransaction(); + + try { + $this->updateQuantity($order, $newStatus, $dispatcher); + + $order->setStatusId($newStatus)->save(); + + $event->setOrder($order); + + $con->commit(); + } catch (\Exception $ex) { + $con->rollBack(); + + throw $ex; + } + } + + /** + * Check if a stock update is required on order products for a given order status change, and compute if + * the stock should be decreased or increased. + * + * @param GetStockUpdateOperationOnOrderStatusChangeEvent $event + * @param $eventName + * @param EventDispatcherInterface $dispatcher + * @throws \Propel\Runtime\Exception\PropelException + */ + public function getStockUpdateOnOrderStatusChange(GetStockUpdateOperationOnOrderStatusChangeEvent $event, $eventName, EventDispatcherInterface $dispatcher) + { + // The order + $order = $event->getOrder(); + + // The new order status + $newStatus = $event->getNewOrderStatus(); + + if ($newStatus->getId() !== $order->getStatusId()) { + // We have to change the stock in the following cases : + // 1) The order is currently paid, and will become unpaid (get products back in stock unconditionnaly) + // 2) The order is currently unpaid, and will become paid (remove products from stock, except if was done at order creation $manageStockOnCreation == false) + // 3) The order is currently NOT PAID, and will become canceled or the like (get products back in stock if it was done at order creation $manageStockOnCreation == true) + + // We consider the ManageStockOnCreation flag only if the order status as not yet changed. + // Count distinct order statuses (e.g. NOT_PAID to something else) in the order version table. + if (OrderVersionQuery::create()->groupByStatusId()->filterById($order->getId())->count() > 1) { + // A status change occured. Ignore $manageStockOnCreation + $manageStockOnCreation = false; + } else { + // A status has not yet occured. Consider the ManageStockOnCreation flag + $manageStockOnCreation = $order->isStockManagedOnOrderCreation($dispatcher); + } + + if (($order->isPaid(false) && $newStatus->isNotPaid(false)) // Case 1 + || + ($order->isNotPaid(true) && $newStatus->isNotPaid(false) && $manageStockOnCreation === true) // Case 3 + ) { + $event->setOperation($event::INCREASE_STOCK); + } + + if ($order->isNotPaid(false) // Case 2 + && + $newStatus->isPaid(false) + && + $manageStockOnCreation === false) { + $event->setOperation($event::DECREASE_STOCK); + } + + Tlog::getInstance()->addInfo( + "Checking stock operation for status change of order : " . $order->getRef() + . ", version: " . $order->getVersion() + . ", manageStockOnCreation: " . ($manageStockOnCreation ? 0 : 1) + . ", paid:" . ($order->isPaid(false) ? 1 : 0) + . ", is not paid:" . ($order->isNotPaid(false) ? 1 : 0) + . ", new status paid:" . ($newStatus->isPaid(false) ? 1 : 0) + . ", new status is not paid:" . ($newStatus->isNotPaid(false) ? 1 : 0) + . " = operation: " . $event->getOperation() + ); + } + } + + /** + * Update order products stock after an order status change + * + * @param OrderModel $order + * @param int $newStatus the new status ID + * @throws \Exception + * @throws \Propel\Runtime\Exception\PropelException + */ + protected function updateQuantity(ModelOrder $order, $newStatus, EventDispatcherInterface $dispatcher) + { + if ($newStatus !== $order->getStatusId()) { + if (null !== $newStatusModel = OrderStatusQuery::create()->findPk($newStatus)) { + $operationEvent = new GetStockUpdateOperationOnOrderStatusChangeEvent($order, $newStatusModel); + + $dispatcher->dispatch( + TheliaEvents::ORDER_GET_STOCK_UPDATE_OPERATION_ON_ORDER_STATUS_CHANGE, + $operationEvent + ); + + if ($operationEvent->getOperation() !== $operationEvent::DO_NOTHING) { + $orderProductList = $order->getOrderProducts(); + + /** @var OrderProduct $orderProduct */ + foreach ($orderProductList as $orderProduct) { + $productSaleElementsId = $orderProduct->getProductSaleElementsId(); + + /** @var ProductSaleElements $productSaleElements */ + if (null !== $productSaleElements = ProductSaleElementsQuery::create()->findPk($productSaleElementsId)) { + $offset = 0; + + if ($operationEvent->getOperation() == $operationEvent::INCREASE_STOCK) { + $offset = $orderProduct->getQuantity(); + } elseif ($operationEvent->getOperation() == $operationEvent::DECREASE_STOCK) { + /* Check if we have enough stock */ + if ($orderProduct->getQuantity() > $productSaleElements->getQuantity() && true === ConfigQuery::checkAvailableStock()) { + throw new TheliaProcessException($productSaleElements->getRef() . " : Not enough stock 2"); + } + + $offset = -$orderProduct->getQuantity(); + } + + Tlog::getInstance()->addError("Product stock: " . $productSaleElements->getQuantity() . " -> " . ($productSaleElements->getQuantity() + $offset)); + + $productSaleElements + ->setQuantity($productSaleElements->getQuantity() + $offset) + ->save(); + } + } + } + } + } + } + + /** + * @param OrderEvent $event + * @throws \Propel\Runtime\Exception\PropelException + */ + public function updateDeliveryRef(OrderEvent $event) + { + $order = $event->getOrder(); + + $order->setDeliveryRef($event->getDeliveryRef())->save(); + + $event->setOrder($order); + } + + /** + * @param OrderEvent $event + * @throws \Propel\Runtime\Exception\PropelException + */ + public function updateTransactionRef(OrderEvent $event) + { + $order = $event->getOrder(); + + $order->setTransactionRef($event->getTransactionRef())->save(); + + $event->setOrder($order); + } + + /** + * @param OrderAddressEvent $event + * @throws \Propel\Runtime\Exception\PropelException + */ + public function updateAddress(OrderAddressEvent $event) + { + $orderAddress = $event->getOrderAddress(); + + $orderAddress + ->setCustomerTitleId($event->getTitle()) + ->setCompany($event->getCompany()) + ->setFirstname($event->getFirstname()) + ->setLastname($event->getLastname()) + ->setAddress1($event->getAddress1()) + ->setAddress2($event->getAddress2()) + ->setAddress3($event->getAddress3()) + ->setZipcode($event->getZipcode()) + ->setCity($event->getCity()) + ->setCountryId($event->getCountry()) + ->setStateId($event->getState()) + ->setPhone($event->getPhone()) + ->setCellphone($event->getCellphone()) + ->save() + ; + + $event->setOrderAddress($orderAddress); + } + + /** + * {@inheritdoc} + */ + public static function getSubscribedEvents() + { + return array( + TheliaEvents::ORDER_SET_DELIVERY_ADDRESS => [ "setDeliveryAddress", 128 ], + TheliaEvents::ORDER_SET_DELIVERY_MODULE => [ "setDeliveryModule", 128 ], + TheliaEvents::ORDER_SET_POSTAGE => [ "setPostage", 128 ], + TheliaEvents::ORDER_SET_INVOICE_ADDRESS => [ "setInvoiceAddress", 128 ], + TheliaEvents::ORDER_SET_PAYMENT_MODULE => [ "setPaymentModule", 128 ], + TheliaEvents::ORDER_PAY => [ "create", 128 ], + TheliaEvents::ORDER_CART_CLEAR => [ "orderCartClear", 128 ], + TheliaEvents::ORDER_BEFORE_PAYMENT => [ "orderBeforePayment", 128 ], + TheliaEvents::ORDER_SEND_CONFIRMATION_EMAIL => [ "sendConfirmationEmail", 128 ], + TheliaEvents::ORDER_SEND_NOTIFICATION_EMAIL => [ "sendNotificationEmail", 128 ], + TheliaEvents::ORDER_UPDATE_STATUS => [ "updateStatus", 128 ], + TheliaEvents::ORDER_UPDATE_DELIVERY_REF => [ "updateDeliveryRef", 128 ], + TheliaEvents::ORDER_UPDATE_TRANSACTION_REF => [ "updateTransactionRef", 128 ], + TheliaEvents::ORDER_UPDATE_ADDRESS => [ "updateAddress", 128 ], + TheliaEvents::ORDER_CREATE_MANUAL => [ "createManual", 128 ], + TheliaEvents::ORDER_GET_STOCK_UPDATE_OPERATION_ON_ORDER_STATUS_CHANGE => [ "getStockUpdateOnOrderStatusChange", 128 ], + ); + } + + /** + * Returns the session from the current request + * + * @return \Thelia\Core\HttpFoundation\Session\Session + */ + protected function getSession() + { + /** @var Request $request */ + $request = $this->requestStack->getCurrentRequest(); + + return $request->getSession(); + } +} diff --git a/core/lib/Thelia/Action/OrderStatus.php b/core/lib/Thelia/Action/OrderStatus.php new file mode 100644 index 00000000..212e2c20 --- /dev/null +++ b/core/lib/Thelia/Action/OrderStatus.php @@ -0,0 +1,147 @@ + + * @since 2.4 + */ +class OrderStatus extends BaseAction implements EventSubscriberInterface +{ + /** + * @param OrderStatusCreateEvent $event + */ + public function create(OrderStatusCreateEvent $event) + { + $this->createOrUpdate($event, new OrderStatusModel()); + } + + /** + * @param OrderStatusUpdateEvent $event + */ + public function update(OrderStatusUpdateEvent $event) + { + $orderStatus = $this->getOrderStatus($event); + $this->createOrUpdate($event, $orderStatus); + } + + /** + * @param OrderStatusDeleteEvent $event + * @throws \Exception + */ + public function delete(OrderStatusDeleteEvent $event) + { + $orderStatus = $this->getOrderStatus($event); + + if ($orderStatus->getProtectedStatus()) { + throw new \Exception( + Translator::getInstance()->trans('This status is protected.') + . ' ' . Translator::getInstance()->trans('You can not delete it.') + ); + } + + if (null !== OrderQuery::create()->findOneByStatusId($orderStatus->getId())) { + throw new \Exception( + Translator::getInstance()->trans('Some commands use this status.') + . ' ' . Translator::getInstance()->trans('You can not delete it.') + ); + } + + $orderStatus->delete(); + + $event->setOrderStatus($orderStatus); + } + + /** + * {@inheritdoc} + */ + public static function getSubscribedEvents() + { + return array( + TheliaEvents::ORDER_STATUS_CREATE => ["create", 128], + TheliaEvents::ORDER_STATUS_UPDATE => ["update", 128], + TheliaEvents::ORDER_STATUS_DELETE => ["delete", 128], + TheliaEvents::ORDER_STATUS_UPDATE_POSITION => ["updatePosition", 128] + ); + } + + /** + * @param OrderStatusEvent $event + * @param OrderStatusModel $orderStatus + */ + protected function createOrUpdate(OrderStatusEvent $event, OrderStatusModel $orderStatus) + { + $orderStatus + ->setCode(!$orderStatus->getProtectedStatus() ? $event->getCode() : $orderStatus->getCode()) + ->setColor($event->getColor()) + // i18n + ->setLocale($event->getLocale()) + ->setTitle($event->getTitle()) + ->setDescription($event->getDescription()) + ->setPostscriptum($event->getPostscriptum()) + ->setChapo($event->getChapo()); + + if ($orderStatus->getId() === null) { + $orderStatus->setPosition( + OrderStatusQuery::create()->orderByPosition(Criteria::DESC)->findOne()->getPosition() + 1 + ); + } + + $orderStatus->save(); + + $event->setOrderStatus($orderStatus); + } + + /** + * Changes position, selecting absolute ou relative change. + * + * @param UpdatePositionEvent $event + * @param $eventName + * @param EventDispatcherInterface $dispatcher + */ + public function updatePosition(UpdatePositionEvent $event, $eventName, EventDispatcherInterface $dispatcher) + { + $this->genericUpdatePosition(OrderStatusQuery::create(), $event, $dispatcher); + } + + /** + * @param OrderStatusUpdateEvent $event + * @return OrderStatusModel + */ + protected function getOrderStatus(OrderStatusUpdateEvent $event) + { + if (null === $orderStatus = OrderStatusQuery::create()->findOneById($event->getId())) { + throw new \LogicException( + "Order status not found" + ); + } + + return $orderStatus; + } +} diff --git a/core/lib/Thelia/Action/Payment.php b/core/lib/Thelia/Action/Payment.php new file mode 100644 index 00000000..221b804c --- /dev/null +++ b/core/lib/Thelia/Action/Payment.php @@ -0,0 +1,65 @@ + + */ +class Payment implements EventSubscriberInterface +{ + /** + * Check if a module is valid + * + * @param IsValidPaymentEvent $event + */ + public function isValid(IsValidPaymentEvent $event, $eventName, EventDispatcherInterface $dispatcher) + { + $module = $event->getModule(); + + // dispatch event to target specific module + $dispatcher->dispatch( + TheliaEvents::getModuleEvent( + TheliaEvents::MODULE_PAYMENT_IS_VALID, + $module->getCode() + ), + $event + ); + + if ($event->isPropagationStopped()) { + return; + } + + // call legacy module method + $event->setValidModule($module->isValidPayment()) + ->setMinimumAmount($module->getMinimumAmount()) + ->setMaximumAmount($module->getMaximumAmount()); + } + + /** + * @inheritdoc + */ + public static function getSubscribedEvents() + { + return [ + TheliaEvents::MODULE_PAYMENT_IS_VALID => ['isValid', 128], + ]; + } +} diff --git a/core/lib/Thelia/Action/Pdf.php b/core/lib/Thelia/Action/Pdf.php new file mode 100644 index 00000000..cfa99119 --- /dev/null +++ b/core/lib/Thelia/Action/Pdf.php @@ -0,0 +1,56 @@ + + */ +class Pdf extends BaseAction implements EventSubscriberInterface +{ + public function generatePdf(PdfEvent $event) + { + $html2pdf = new Html2Pdf( + $event->getOrientation(), + $event->getFormat(), + $event->getLang(), + $event->getUnicode(), + $event->getEncoding(), + $event->getMarges() + ); + + $html2pdf->setDefaultFont($event->getFontName()); + + $html2pdf->pdf->SetDisplayMode('real'); + + $html2pdf->writeHTML($event->getContent()); + + $event->setPdf($html2pdf->output('output.pdf', 'S')); + } + + /** + * {@inheritdoc} + */ + public static function getSubscribedEvents() + { + return array( + TheliaEvents::GENERATE_PDF => array("generatePdf", 128) + ); + } +} diff --git a/core/lib/Thelia/Action/Product.php b/core/lib/Thelia/Action/Product.php new file mode 100644 index 00000000..0a7fa52c --- /dev/null +++ b/core/lib/Thelia/Action/Product.php @@ -0,0 +1,960 @@ +eventDispatcher = $eventDispatcher; + } + + /** + * Create a new product entry + * + * @param \Thelia\Core\Event\Product\ProductCreateEvent $event + */ + public function create(ProductCreateEvent $event) + { + $defaultTaxRuleId = null; + if (null !== $defaultTaxRule = TaxRuleQuery::create()->findOneByIsDefault(true)) { + $defaultTaxRuleId = $defaultTaxRule->getId(); + } + + $product = new ProductModel(); + + $product + ->setDispatcher($this->eventDispatcher) + + ->setRef($event->getRef()) + ->setLocale($event->getLocale()) + ->setTitle($event->getTitle()) + ->setVisible($event->getVisible() ? 1 : 0) + ->setVirtual($event->getVirtual() ? 1 : 0) + ->setTemplateId($event->getTemplateId()) + + ->create( + $event->getDefaultCategory(), + $event->getBasePrice(), + $event->getCurrencyId(), + // Set the default tax rule if not defined + $event->getTaxRuleId() ?: $defaultTaxRuleId, + $event->getBaseWeight(), + $event->getBaseQuantity() + ) + ; + + $event->setProduct($product); + } + + /******************* + * CLONING PROCESS * + *******************/ + + /** + * @param ProductCloneEvent $event + * @throws \Exception + */ + public function cloneProduct(ProductCloneEvent $event) + { + $con = Propel::getWriteConnection(ProductTableMap::DATABASE_NAME); + $con->beginTransaction(); + + try { + // Get important datas + $lang = $event->getLang(); + $originalProduct = $event->getOriginalProduct(); + + if (null === $originalProductDefaultI18n = ProductI18nQuery::create() + ->findPk([$originalProduct->getId(), $lang])) { + // No i18n entry for the current language. Try to find one for creating the product. + // It will be updated later by updateClone() + $originalProductDefaultI18n = ProductI18nQuery::create() + ->findOneById($originalProduct->getId()) + ; + } + + $originalProductDefaultPrice = ProductPriceQuery::create() + ->findOneByProductSaleElementsId($originalProduct->getDefaultSaleElements()->getId()); + + // Cloning process + + $this->createClone($event, $originalProductDefaultI18n, $originalProductDefaultPrice); + + $this->updateClone($event, $originalProductDefaultPrice); + + $this->cloneFeatureCombination($event); + + $this->cloneAssociatedContent($event); + + $this->cloneAccessories($event); + + $this->cloneAdditionalCategories($event); + + // Dispatch event for file cloning + $this->eventDispatcher->dispatch(TheliaEvents::FILE_CLONE, $event); + + // Dispatch event for PSE cloning + $this->eventDispatcher->dispatch(TheliaEvents::PSE_CLONE, $event); + + $con->commit(); + } catch (\Exception $e) { + $con->rollBack(); + throw $e; + } + } + + public function createClone(ProductCloneEvent $event, ProductI18n $originalProductDefaultI18n, ProductPrice $originalProductDefaultPrice) + { + // Build event and dispatch creation of the clone product + $createCloneEvent = new ProductCreateEvent(); + $createCloneEvent + ->setTitle($originalProductDefaultI18n->getTitle()) + ->setRef($event->getRef()) + ->setLocale($event->getLang()) + ->setVisible(0) + ->setVirtual($event->getOriginalProduct()->getVirtual()) + ->setTaxRuleId($event->getOriginalProduct()->getTaxRuleId()) + ->setDefaultCategory($event->getOriginalProduct()->getDefaultCategoryId()) + ->setBasePrice($originalProductDefaultPrice->getPrice()) + ->setCurrencyId($originalProductDefaultPrice->getCurrencyId()) + ->setBaseWeight($event->getOriginalProduct()->getDefaultSaleElements()->getWeight()); + + $this->eventDispatcher->dispatch(TheliaEvents::PRODUCT_CREATE, $createCloneEvent); + + $event->setClonedProduct($createCloneEvent->getProduct()); + } + + public function updateClone(ProductCloneEvent $event, ProductPrice $originalProductDefaultPrice) + { + // Get original product's I18ns + $originalProductI18ns = ProductI18nQuery::create() + ->findById($event->getOriginalProduct()->getId()); + + /** @var ProductI18n $originalProductI18n */ + foreach ($originalProductI18ns as $originalProductI18n) { + $clonedProductUpdateEvent = new ProductUpdateEvent($event->getClonedProduct()->getId()); + $clonedProductUpdateEvent + ->setRef($event->getClonedProduct()->getRef()) + ->setVisible($event->getClonedProduct()->getVisible()) + ->setVirtual($event->getClonedProduct()->getVirtual()) + + ->setLocale($originalProductI18n->getLocale()) + ->setTitle($originalProductI18n->getTitle()) + ->setChapo($originalProductI18n->getChapo()) + ->setDescription($originalProductI18n->getDescription()) + ->setPostscriptum($originalProductI18n->getPostscriptum()) + + ->setBasePrice($originalProductDefaultPrice->getPrice()) + ->setCurrencyId($originalProductDefaultPrice->getCurrencyId()) + ->setBaseWeight($event->getOriginalProduct()->getDefaultSaleElements()->getWeight()) + ->setTaxRuleId($event->getOriginalProduct()->getTaxRuleId()) + ->setBrandId($event->getOriginalProduct()->getBrandId()) + ->setDefaultCategory($event->getOriginalProduct()->getDefaultCategoryId()); + + $this->eventDispatcher->dispatch(TheliaEvents::PRODUCT_UPDATE, $clonedProductUpdateEvent); + + // SEO info + $clonedProductUpdateSeoEvent = new UpdateSeoEvent($event->getClonedProduct()->getId()); + $clonedProductUpdateSeoEvent + ->setLocale($originalProductI18n->getLocale()) + ->setMetaTitle($originalProductI18n->getMetaTitle()) + ->setMetaDescription($originalProductI18n->getMetaDescription()) + ->setMetaKeywords($originalProductI18n->getMetaKeywords()) + ->setUrl(null); + $this->eventDispatcher->dispatch(TheliaEvents::PRODUCT_UPDATE_SEO, $clonedProductUpdateSeoEvent); + } + + $event->setClonedProduct($clonedProductUpdateEvent->getProduct()); + + // Set clone's template + $clonedProductUpdateTemplateEvent = new ProductSetTemplateEvent( + $event->getClonedProduct(), + $event->getOriginalProduct()->getTemplateId(), + $originalProductDefaultPrice->getCurrencyId() + ); + + $this->eventDispatcher->dispatch(TheliaEvents::PRODUCT_SET_TEMPLATE, $clonedProductUpdateTemplateEvent); + } + + public function cloneFeatureCombination(ProductCloneEvent $event) + { + // Get original product FeatureProduct list + $originalProductFeatureList = FeatureProductQuery::create() + ->findByProductId($event->getOriginalProduct()->getId()); + + // Set clone product FeatureProducts + /** @var FeatureProduct $originalProductFeature */ + foreach ($originalProductFeatureList as $originalProductFeature) { + // Get original FeatureAvI18n list + $originalProductFeatureAvI18nList = FeatureAvI18nQuery::create() + ->findById($originalProductFeature->getFeatureAvId()); + + /** @var FeatureAvI18n $originalProductFeatureAvI18n */ + foreach ($originalProductFeatureAvI18nList as $originalProductFeatureAvI18n) { + // Create a FeatureProduct for each FeatureAv (not for each FeatureAvI18n) + $clonedProductCreateFeatureEvent = new FeatureProductUpdateEvent( + $event->getClonedProduct()->getId(), + $originalProductFeature->getFeatureId(), + $originalProductFeature->getFeatureAvId() + ); + $clonedProductCreateFeatureEvent->setLocale($originalProductFeatureAvI18n->getLocale()); + + // If it's a free text value, pass the FeatureAvI18n's title as featureValue to the event + if ($originalProductFeature->getIsFreeText()) { + $clonedProductCreateFeatureEvent->setFeatureValue($originalProductFeatureAvI18n->getTitle()); + $clonedProductCreateFeatureEvent->setIsTextValue(true); + } + + $this->eventDispatcher->dispatch(TheliaEvents::PRODUCT_FEATURE_UPDATE_VALUE, $clonedProductCreateFeatureEvent); + } + } + } + + public function cloneAssociatedContent(ProductCloneEvent $event) + { + // Get original product associated contents + $originalProductAssocConts = ProductAssociatedContentQuery::create() + ->findByProductId($event->getOriginalProduct()->getId()); + + // Set clone product associated contents + /** @var ProductAssociatedContent $originalProductAssocCont */ + foreach ($originalProductAssocConts as $originalProductAssocCont) { + $clonedProductCreatePAC = new ProductAddContentEvent($event->getClonedProduct(), $originalProductAssocCont->getContentId()); + $this->eventDispatcher->dispatch(TheliaEvents::PRODUCT_ADD_CONTENT, $clonedProductCreatePAC); + } + } + + public function cloneAccessories(ProductCloneEvent $event) + { + // Get original product accessories + $originalProductAccessoryList = AccessoryQuery::create() + ->findByProductId($event->getOriginalProduct()->getId()); + + // Set clone product accessories + /** @var Accessory $originalProductAccessory */ + foreach ($originalProductAccessoryList as $originalProductAccessory) { + $clonedProductAddAccessoryEvent = new ProductAddAccessoryEvent($event->getClonedProduct(), $originalProductAccessory->getAccessory()); + $this->eventDispatcher->dispatch(TheliaEvents::PRODUCT_ADD_ACCESSORY, $clonedProductAddAccessoryEvent); + } + } + + public function cloneAdditionalCategories(ProductCloneEvent $event) + { + // Get original product additional categories + $originalProductAdditionalCategoryList = ProductCategoryQuery::create() + ->filterByProductId($event->getOriginalProduct()->getId()) + ->filterByDefaultCategory(false) + ->find(); + + // Set clone product additional categories + /** @var ProductCategory $originalProductCategory */ + foreach ($originalProductAdditionalCategoryList as $originalProductCategory) { + $clonedProductAddCategoryEvent = new ProductAddCategoryEvent($event->getClonedProduct(), $originalProductCategory->getCategoryId()); + $this->eventDispatcher->dispatch(TheliaEvents::PRODUCT_ADD_CATEGORY, $clonedProductAddCategoryEvent); + } + } + + /*************** + * END CLONING * + ***************/ + + /** + * Change a product + * + * @param \Thelia\Core\Event\Product\ProductUpdateEvent $event + * @throws PropelException + * @throws \Exception + */ + public function update(ProductUpdateEvent $event) + { + if (null !== $product = ProductQuery::create()->findPk($event->getProductId())) { + $con = Propel::getWriteConnection(ProductTableMap::DATABASE_NAME); + $con->beginTransaction(); + + try { + $prevRef = $product->getRef(); + + $product + ->setDispatcher($this->eventDispatcher) + ->setRef($event->getRef()) + ->setLocale($event->getLocale()) + ->setTitle($event->getTitle()) + ->setDescription($event->getDescription()) + ->setChapo($event->getChapo()) + ->setPostscriptum($event->getPostscriptum()) + ->setVisible($event->getVisible() ? 1 : 0) + ->setVirtual($event->getVirtual() ? 1 : 0) + ->setBrandId($event->getBrandId() <= 0 ? null : $event->getBrandId()) + + ->save($con) + ; + + // Update default PSE (if product has no attributes and the product's ref change) + $defaultPseRefChange = $prevRef !== $product->getRef() + && 0 === $product->getDefaultSaleElements()->countAttributeCombinations(); + if ($defaultPseRefChange) { + $defaultPse = $product->getDefaultSaleElements(); + $defaultPse->setRef($product->getRef())->save(); + } + + // Update default category (if required) + $product->setDefaultCategory($event->getDefaultCategory()); + + $event->setProduct($product); + $con->commit(); + } catch (PropelException $e) { + $con->rollBack(); + throw $e; + } + } + } + + /** + * @param UpdateSeoEvent $event + * @param $eventName + * @param EventDispatcherInterface $dispatcher + * @return mixed + */ + public function updateSeo(UpdateSeoEvent $event, $eventName, EventDispatcherInterface $dispatcher) + { + return $this->genericUpdateSeo(ProductQuery::create(), $event, $dispatcher); + } + + /** + * Delete a product entry + * + * @param \Thelia\Core\Event\Product\ProductDeleteEvent $event + * @throws \Exception + */ + public function delete(ProductDeleteEvent $event) + { + if (null !== $product = ProductQuery::create()->findPk($event->getProductId())) { + $con = Propel::getWriteConnection(ProductTableMap::DATABASE_NAME); + $con->beginTransaction(); + + try { + $fileList = ['images' => [], 'documentList' => []]; + + // Get product's files to delete after product deletion + $fileList['images']['list'] = ProductImageQuery::create() + ->findByProductId($event->getProductId()); + $fileList['images']['type'] = TheliaEvents::IMAGE_DELETE; + + $fileList['documentList']['list'] = ProductDocumentQuery::create() + ->findByProductId($event->getProductId()); + $fileList['documentList']['type'] = TheliaEvents::DOCUMENT_DELETE; + + // Delete product + $product + ->setDispatcher($this->eventDispatcher) + ->delete($con) + ; + + $event->setProduct($product); + + // Dispatch delete product's files event + foreach ($fileList as $fileTypeList) { + foreach ($fileTypeList['list'] as $fileToDelete) { + $fileDeleteEvent = new FileDeleteEvent($fileToDelete); + $this->eventDispatcher->dispatch($fileTypeList['type'], $fileDeleteEvent); + } + } + + $con->commit(); + } catch (\Exception $e) { + $con->rollBack(); + throw $e; + } + } + } + + /** + * Toggle product visibility. No form used here + * + * @param ProductToggleVisibilityEvent $event + */ + public function toggleVisibility(ProductToggleVisibilityEvent $event) + { + $product = $event->getProduct(); + + $product + ->setDispatcher($this->eventDispatcher) + ->setVisible($product->getVisible() ? false : true) + ->save() + ; + + $event->setProduct($product); + } + + /** + * Changes position, selecting absolute ou relative change. + * + * @param UpdatePositionEvent $event + * @param $eventName + * @param EventDispatcherInterface $dispatcher + */ + public function updatePosition(UpdatePositionEvent $event, $eventName, EventDispatcherInterface $dispatcher) + { + $this->genericUpdateDelegatePosition( + ProductCategoryQuery::create() + ->filterByProductId($event->getObjectId()) + ->filterByCategoryId($event->getReferrerId()), + $event, + $dispatcher + ); + } + + public function addContent(ProductAddContentEvent $event) + { + if (ProductAssociatedContentQuery::create() + ->filterByContentId($event->getContentId()) + ->filterByProduct($event->getProduct())->count() <= 0) { + $content = new ProductAssociatedContent(); + + $content + ->setDispatcher($this->eventDispatcher) + ->setProduct($event->getProduct()) + ->setContentId($event->getContentId()) + ->save() + ; + } + } + + public function removeContent(ProductDeleteContentEvent $event) + { + $content = ProductAssociatedContentQuery::create() + ->filterByContentId($event->getContentId()) + ->filterByProduct($event->getProduct())->findOne() + ; + + if ($content !== null) { + $content + ->setDispatcher($this->eventDispatcher) + ->delete() + ; + } + } + + public function addCategory(ProductAddCategoryEvent $event) + { + if (ProductCategoryQuery::create() + ->filterByProduct($event->getProduct()) + ->filterByCategoryId($event->getCategoryId()) + ->count() <= 0) { + $productCategory = (new ProductCategory()) + ->setProduct($event->getProduct()) + ->setCategoryId($event->getCategoryId()) + ->setDefaultCategory(false); + + $productCategory + ->setPosition($productCategory->getNextPosition()) + ->save(); + } + } + + public function removeCategory(ProductDeleteCategoryEvent $event) + { + $productCategory = ProductCategoryQuery::create() + ->filterByProduct($event->getProduct()) + ->filterByCategoryId($event->getCategoryId()) + ->findOne(); + + if ($productCategory != null) { + $productCategory->delete(); + } + } + + public function addAccessory(ProductAddAccessoryEvent $event) + { + if (AccessoryQuery::create() + ->filterByAccessory($event->getAccessoryId()) + ->filterByProductId($event->getProduct()->getId())->count() <= 0) { + $accessory = new Accessory(); + + $accessory + ->setDispatcher($this->eventDispatcher) + ->setProductId($event->getProduct()->getId()) + ->setAccessory($event->getAccessoryId()) + ->save() + ; + } + } + + public function removeAccessory(ProductDeleteAccessoryEvent $event) + { + $accessory = AccessoryQuery::create() + ->filterByAccessory($event->getAccessoryId()) + ->filterByProductId($event->getProduct()->getId())->findOne() + ; + + if ($accessory !== null) { + $accessory + ->setDispatcher($this->eventDispatcher) + ->delete() + ; + } + } + + public function setProductTemplate(ProductSetTemplateEvent $event) + { + $con = Propel::getWriteConnection(ProductTableMap::DATABASE_NAME); + + $con->beginTransaction(); + + try { + $product = $event->getProduct(); + + // Check differences between current coobination and the next one, and clear obsoletes values. + $nextTemplateId = $event->getTemplateId(); + $currentTemplateId = $product->getTemplateId(); + + // 1. Process product features. + + $currentFeatures = FeatureTemplateQuery::create() + ->filterByTemplateId($currentTemplateId) + ->select([ FeatureTemplateTableMap::COL_FEATURE_ID ]) + ->find($con); + + $nextFeatures = FeatureTemplateQuery::create() + ->filterByTemplateId($nextTemplateId) + ->select([ FeatureTemplateTableMap::COL_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::COL_ATTRIBUTE_ID ]) + ->find($con); + + $nextAttributes = AttributeTemplateQuery::create() + ->filterByTemplateId($nextTemplateId) + ->select([ AttributeTemplateTableMap::COL_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()); + + // Find PSE which includes $attributesToDelete for the current product/ + $pseToDelete = ProductSaleElementsQuery::create() + ->filterByProductId($product->getId()) + ->useAttributeCombinationQuery() + ->filterByAttributeId($attributesToDelete, Criteria::IN) + ->endUse() + ->select([ ProductSaleElementsTableMap::COL_ID ]) + ->find(); + + // Delete obsolete PSEs + foreach ($pseToDelete->getData() as $pseId) { + $this->eventDispatcher->dispatch( + TheliaEvents::PRODUCT_DELETE_PRODUCT_SALE_ELEMENT, + new ProductSaleElementDeleteEvent( + $pseId, + CurrencyModel::getDefaultCurrency()->getId() + ) + ); + } + + // Update the product template + $template_id = $event->getTemplateId(); + + // Set it to null if it's zero. + if ($template_id <= 0) { + $template_id = null; + } + + $product->setTemplateId($template_id)->save($con); + + $product->clearProductSaleElementss(); + + $event->setProduct($product); + + // Store all the stuff ! + $con->commit(); + } catch (\Exception $ex) { + $con->rollBack(); + + throw $ex; + } + } + + /** + * Changes accessry position, selecting absolute ou relative change. + * + * @param UpdatePositionEvent $event + * @param $eventName + * @param EventDispatcherInterface $dispatcher + * @return Object + */ + public function updateAccessoryPosition(UpdatePositionEvent $event, $eventName, EventDispatcherInterface $dispatcher) + { + return $this->genericUpdatePosition(AccessoryQuery::create(), $event, $dispatcher); + } + + /** + * Changes position, selecting absolute ou relative change. + * + * @param UpdatePositionEvent $event + * @param $eventName + * @param EventDispatcherInterface $dispatcher + * @return Object + */ + public function updateContentPosition(UpdatePositionEvent $event, $eventName, EventDispatcherInterface $dispatcher) + { + return $this->genericUpdatePosition(ProductAssociatedContentQuery::create(), $event, $dispatcher); + } + + /** + * Update the value of a product feature. + * + * @param FeatureProductUpdateEvent $event + */ + public function updateFeatureProductValue(FeatureProductUpdateEvent $event) + { + // Prepare the FeatureAv's ID + $featureAvId = $event->getFeatureValue(); + + // Search for existing FeatureProduct + $featureProductQuery = FeatureProductQuery::create() + ->filterByProductId($event->getProductId()) + ->filterByFeatureId($event->getFeatureId()) + ; + + // If it's not a free text value, we can filter by the event's featureValue (which is an ID) + if ($event->getFeatureValue() !== null && $event->getIsTextValue() === false) { + $featureProductQuery->filterByFeatureAvId($featureAvId); + } + + $featureProduct = $featureProductQuery->findOne(); + + // If the FeatureProduct does not exist, create it + if ($featureProduct === null) { + $featureProduct = new FeatureProduct(); + + $featureProduct + ->setDispatcher($this->eventDispatcher) + ->setProductId($event->getProductId()) + ->setFeatureId($event->getFeatureId()) + ; + + // If it's a free text value, create a FeatureAv to handle i18n + if ($event->getIsTextValue() === true) { + $featureProduct->setIsFreeText(true); + + $createFeatureAvEvent = new FeatureAvCreateEvent(); + $createFeatureAvEvent + ->setFeatureId($event->getFeatureId()) + ->setLocale($event->getLocale()) + ->setTitle($event->getFeatureValue()); + $this->eventDispatcher->dispatch(TheliaEvents::FEATURE_AV_CREATE, $createFeatureAvEvent); + + $featureAvId = $createFeatureAvEvent->getFeatureAv()->getId(); + } + } // Else if the FeatureProduct exists and is a free text value + elseif ($featureProduct !== null && $event->getIsTextValue() === true) { + // Get the FeatureAv + $freeTextFeatureAv = FeatureAvQuery::create() + ->filterByFeatureProduct($featureProduct) + ->findOneByFeatureId($event->getFeatureId()); + + // Get the FeatureAvI18n by locale + $freeTextFeatureAvI18n = FeatureAvI18nQuery::create() + ->filterById($freeTextFeatureAv->getId()) + ->findOneByLocale($event->getLocale()); + + // Nothing found for this lang and the new value is not empty : create FeatureAvI18n + if ($freeTextFeatureAvI18n === null && !empty($featureAvId)) { + $featureAvI18n = new FeatureAvI18n(); + $featureAvI18n + ->setId($freeTextFeatureAv->getId()) + ->setLocale($event->getLocale()) + ->setTitle($event->getFeatureValue()) + ->save(); + + $featureAvId = $featureAvI18n->getId(); + } // Else if i18n exists but new value is empty : delete FeatureAvI18n + elseif ($freeTextFeatureAvI18n !== null && empty($featureAvId)) { + $freeTextFeatureAvI18n->delete(); + + // Check if there are still some FeatureAvI18n for this FeatureAv + $freeTextFeatureAvI18ns = FeatureAvI18nQuery::create() + ->findById($freeTextFeatureAv->getId()); + + // If there are no more FeatureAvI18ns for this FeatureAv, remove the corresponding FeatureProduct & FeatureAv + if (\count($freeTextFeatureAvI18ns) == 0) { + $deleteFeatureProductEvent = new FeatureProductDeleteEvent($event->getProductId(), $event->getFeatureId()); + $this->eventDispatcher->dispatch(TheliaEvents::PRODUCT_FEATURE_DELETE_VALUE, $deleteFeatureProductEvent); + + $deleteFeatureAvEvent = new FeatureAvDeleteEvent($freeTextFeatureAv->getId()); + $this->eventDispatcher->dispatch(TheliaEvents::FEATURE_AV_DELETE, $deleteFeatureAvEvent); + } + return; + } // Else if a FeatureAvI18n is found and the new value is not empty : update existing FeatureAvI18n + elseif ($freeTextFeatureAvI18n !== null && !empty($featureAvId)) { + $freeTextFeatureAvI18n->setTitle($featureAvId); + $freeTextFeatureAvI18n->save(); + + $featureAvId = $freeTextFeatureAvI18n->getId(); + } //To prevent Integrity constraint violation + elseif (empty($featureAvId)) { + return; + } + } + + $featureProduct->setFeatureAvId($featureAvId); + + $featureProduct->save(); + + $event->setFeatureProduct($featureProduct); + } + + /** + * Delete a product feature value + * + * @param FeatureProductDeleteEvent $event + */ + public function deleteFeatureProductValue(FeatureProductDeleteEvent $event) + { + FeatureProductQuery::create() + ->filterByProductId($event->getProductId()) + ->filterByFeatureId($event->getFeatureId()) + ->delete() + ; + } + + public function deleteImagePSEAssociations(FileDeleteEvent $event) + { + $model = $event->getFileToDelete(); + + if ($model instanceof ProductImage) { + $model->getProductSaleElementsProductImages()->delete(); + } + } + + public function deleteDocumentPSEAssociations(FileDeleteEvent $event) + { + $model = $event->getFileToDelete(); + + if ($model instanceof ProductDocument) { + $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::COL_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} + */ + public static function getSubscribedEvents() + { + return array( + TheliaEvents::PRODUCT_CREATE => array("create", 128), + TheliaEvents::PRODUCT_CLONE => array("cloneProduct", 128), + TheliaEvents::PRODUCT_UPDATE => array("update", 128), + TheliaEvents::PRODUCT_DELETE => array("delete", 128), + TheliaEvents::PRODUCT_TOGGLE_VISIBILITY => array("toggleVisibility", 128), + + TheliaEvents::PRODUCT_UPDATE_POSITION => array("updatePosition", 128), + TheliaEvents::PRODUCT_UPDATE_SEO => array("updateSeo", 128), + + TheliaEvents::PRODUCT_ADD_CONTENT => array("addContent", 128), + TheliaEvents::PRODUCT_REMOVE_CONTENT => array("removeContent", 128), + TheliaEvents::PRODUCT_UPDATE_CONTENT_POSITION => array("updateContentPosition", 128), + + TheliaEvents::PRODUCT_ADD_ACCESSORY => array("addAccessory", 128), + TheliaEvents::PRODUCT_REMOVE_ACCESSORY => array("removeAccessory", 128), + TheliaEvents::PRODUCT_UPDATE_ACCESSORY_POSITION => array("updateAccessoryPosition", 128), + + TheliaEvents::PRODUCT_ADD_CATEGORY => array("addCategory", 128), + TheliaEvents::PRODUCT_REMOVE_CATEGORY => array("removeCategory", 128), + + TheliaEvents::PRODUCT_SET_TEMPLATE => array("setProductTemplate", 128), + + TheliaEvents::PRODUCT_FEATURE_UPDATE_VALUE => array("updateFeatureProductValue", 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 + TheliaEvents::IMAGE_DELETE => array("deleteImagePSEAssociations", 192), + TheliaEvents::DOCUMENT_DELETE => array("deleteDocumentPSEAssociations", 192), + + TheliaEvents::VIEW_CHECK => array('viewCheck', 128), + TheliaEvents::VIEW_PRODUCT_ID_NOT_VISIBLE => array('viewProductIdNotVisible', 128), + ); + } +} diff --git a/core/lib/Thelia/Action/ProductSaleElement.php b/core/lib/Thelia/Action/ProductSaleElement.php new file mode 100644 index 00000000..6e01d16a --- /dev/null +++ b/core/lib/Thelia/Action/ProductSaleElement.php @@ -0,0 +1,521 @@ +eventDispatcher = $eventDispatcher; + } + + /** + * Create a new product sale element, with or without combination + * + * @param ProductSaleElementCreateEvent $event + * @throws \Exception + */ + public function create(ProductSaleElementCreateEvent $event) + { + $con = Propel::getWriteConnection(ProductSaleElementsTableMap::DATABASE_NAME); + + $con->beginTransaction(); + + try { + // Check if we have a PSE without combination, this is the "default" PSE. Attach the combination to this PSE + $salesElement = ProductSaleElementsQuery::create() + ->filterByProductId($event->getProduct()->getId()) + ->joinAttributeCombination(null, Criteria::LEFT_JOIN) + ->add(AttributeCombinationTableMap::COL_PRODUCT_SALE_ELEMENTS_ID, null, Criteria::ISNULL) + ->findOne($con); + + if ($salesElement == null) { + // Create a new default product sale element + $salesElement = $event->getProduct()->createProductSaleElement($con, 0, 0, 0, $event->getCurrencyId(), false); + } else { + // This (new) one is the default + $salesElement->setIsDefault(true)->save($con); + } + + // Attach combination, if defined. + $combinationAttributes = $event->getAttributeAvList(); + + if (\count($combinationAttributes) > 0) { + foreach ($combinationAttributes as $attributeAvId) { + $attributeAv = AttributeAvQuery::create()->findPk($attributeAvId); + + if ($attributeAv !== null) { + $attributeCombination = new AttributeCombination(); + + $attributeCombination + ->setAttributeAvId($attributeAvId) + ->setAttribute($attributeAv->getAttribute()) + ->setProductSaleElements($salesElement) + ->save($con); + } + } + } + + $event->setProductSaleElement($salesElement); + + // Store all the stuff ! + $con->commit(); + } catch (\Exception $ex) { + $con->rollback(); + + throw $ex; + } + } + + /** + * Update an existing product sale element + * + * @param ProductSaleElementUpdateEvent $event + * @throws \Exception + */ + public function update(ProductSaleElementUpdateEvent $event) + { + $salesElement = ProductSaleElementsQuery::create()->findPk($event->getProductSaleElementId()); + + $con = Propel::getWriteConnection(ProductSaleElementsTableMap::DATABASE_NAME); + + $con->beginTransaction(); + + try { + // Update the product's tax rule + $event->getProduct()->setTaxRuleId($event->getTaxRuleId())->save($con); + + // If product sale element is not defined, create it. + if ($salesElement == null) { + $salesElement = new ProductSaleElements(); + + $salesElement->setProduct($event->getProduct()); + } + + $defaultStatus = $event->getIsDefault(); + + // If this PSE will become the default one, be sure to have *only one* default for this product + if ($defaultStatus) { + ProductSaleElementsQuery::create() + ->filterByProduct($event->getProduct()) + ->filterByIsDefault(true) + ->filterById($event->getProductSaleElementId(), Criteria::NOT_EQUAL) + ->update(['IsDefault' => false], $con) + ; + } else { + // We will not allow the default PSE to become non default if no other default PSE exists for this product. + if ($salesElement->getIsDefault() && ProductSaleElementsQuery::create() + ->filterByProduct($event->getProduct()) + ->filterByIsDefault(true) + ->filterById($salesElement->getId(), Criteria::NOT_EQUAL) + ->count() === 0) { + // Prevent setting the only default PSE to non-default + $defaultStatus = true; + } + } + + // Update sale element + $salesElement + ->setRef($event->getReference()) + ->setQuantity($event->getQuantity()) + ->setPromo($event->getOnsale()) + ->setNewness($event->getIsnew()) + ->setWeight($event->getWeight()) + ->setIsDefault($defaultStatus) + ->setEanCode($event->getEanCode()) + ->save() + ; + + // Update/create price for current currency + $productPrice = ProductPriceQuery::create() + ->filterByCurrencyId($event->getCurrencyId()) + ->filterByProductSaleElementsId($salesElement->getId()) + ->findOne($con); + + // If price is not defined, create it. + if ($productPrice == null) { + $productPrice = new ProductPrice(); + + $productPrice + ->setProductSaleElements($salesElement) + ->setCurrencyId($event->getCurrencyId()) + ; + } + + // Check if we have to store the price + $productPrice->setFromDefaultCurrency($event->getFromDefaultCurrency()); + + if ($event->getFromDefaultCurrency() == 0) { + // Store the price + $productPrice + ->setPromoPrice($event->getSalePrice()) + ->setPrice($event->getPrice()) + ; + } else { + // Do not store the price. + $productPrice + ->setPromoPrice(0) + ->setPrice(0) + ; + } + + $productPrice->save($con); + + // Store all the stuff ! + $con->commit(); + } catch (\Exception $ex) { + $con->rollback(); + + throw $ex; + } + } + + /** + * Delete a product sale element + * + * @param ProductSaleElementDeleteEvent $event + * @throws \Exception + */ + public function delete(ProductSaleElementDeleteEvent $event) + { + if (null !== $pse = ProductSaleElementsQuery::create()->findPk($event->getProductSaleElementId())) { + $product = $pse->getProduct(); + + $con = Propel::getWriteConnection(ProductSaleElementsTableMap::DATABASE_NAME); + + $con->beginTransaction(); + + try { + // If we are deleting the last PSE of the product, don(t delete it, but insteaf + // transform it into a PSE detached for any attribute combination, so that product + // prices, weight, stock and attributes will not be lost. + if ($product->countSaleElements($con) === 1) { + $pse + ->setIsDefault(true) + ->save($con); + // Delete the related attribute combination. + AttributeCombinationQuery::create() + ->filterByProductSaleElementsId($pse->getId()) + ->delete($con); + } else { + // Delete the PSE + $pse->delete($con); + // If we deleted the default PSE, make the last created one the default + if ($pse->getIsDefault()) { + $newDefaultPse = ProductSaleElementsQuery::create() + ->filterByProductId($product->getId()) + ->filterById($pse->getId(), Criteria::NOT_EQUAL) + ->orderByCreatedAt(Criteria::DESC) + ->findOne($con) + ; + if (null !== $newDefaultPse) { + $newDefaultPse->setIsDefault(true)->save($con); + } + } + } + + // Store all the stuff ! + $con->commit(); + } catch (\Exception $ex) { + $con->rollback(); + + throw $ex; + } + } + } + + /** + * Generate combinations. All existing combinations for the product are deleted. + * + * @param ProductCombinationGenerationEvent $event + * @throws \Exception + */ + public function generateCombinations(ProductCombinationGenerationEvent $event) + { + $con = Propel::getWriteConnection(ProductSaleElementsTableMap::DATABASE_NAME); + + $con->beginTransaction(); + + try { + // Delete all product's productSaleElement + ProductSaleElementsQuery::create()->filterByProductId($event->product->getId())->delete(); + + $isDefault = true; + + // Create all combinations + foreach ($event->getCombinations() as $combinationAttributesAvIds) { + // Create the PSE + $saleElement = $event->getProduct()->createProductSaleElement( + $con, + $event->getWeight(), + $event->getPrice(), + $event->getSalePrice(), + $event->getCurrencyId(), + $isDefault, + $event->getOnsale(), + $event->getIsnew(), + $event->getQuantity(), + $event->getEanCode(), + $event->getReference() + ); + + $isDefault = false; + + $this->createCombination($con, $saleElement, $combinationAttributesAvIds); + } + + // Store all the stuff ! + $con->commit(); + } catch (\Exception $ex) { + $con->rollback(); + + throw $ex; + } + } + + /** + * Create a combination for a given product sale element + * + * @param ConnectionInterface $con the Propel connection + * @param ProductSaleElements $salesElement the product sale element + * @param array $combinationAttributes an array oif attributes av IDs + * @throws \Propel\Runtime\Exception\PropelException + */ + protected function createCombination(ConnectionInterface $con, ProductSaleElements $salesElement, $combinationAttributes) + { + foreach ($combinationAttributes as $attributeAvId) { + $attributeAv = AttributeAvQuery::create()->findPk($attributeAvId); + + if ($attributeAv !== null) { + $attributeCombination = new AttributeCombination(); + + $attributeCombination + ->setAttributeAvId($attributeAvId) + ->setAttribute($attributeAv->getAttribute()) + ->setProductSaleElements($salesElement) + ->save($con); + } + } + } + + /******************* + * CLONING PROCESS * + *******************/ + + /** + * Clone product's PSEs and associated datas + * + * @param ProductCloneEvent $event + * @throws \Propel\Runtime\Exception\PropelException + */ + public function clonePSE(ProductCloneEvent $event) + { + $clonedProduct = $event->getClonedProduct(); + + // Get original product's PSEs + $originalProductPSEs = ProductSaleElementsQuery::create() + ->orderByIsDefault(Criteria::DESC) + ->findByProductId($event->getOriginalProduct()->getId()); + + /** + * Handle PSEs + * + * @var int $key + * @var ProductSaleElements $originalProductPSE + */ + foreach ($originalProductPSEs as $key => $originalProductPSE) { + $currencyId = ProductPriceQuery::create() + ->filterByProductSaleElementsId($originalProductPSE->getId()) + ->select('CURRENCY_ID') + ->findOne(); + + // The default PSE, created at the same time as the clone product, is overwritten + $clonedProductPSEId = $this->createClonePSE($event, $originalProductPSE, $currencyId); + + $this->updateClonePSE($event, $clonedProductPSEId, $originalProductPSE, $key); + + // PSE associated images + $originalProductPSEImages = ProductSaleElementsProductImageQuery::create() + ->findByProductSaleElementsId($originalProductPSE->getId()); + + if (null !== $originalProductPSEImages) { + $this->clonePSEAssociatedFiles($clonedProduct->getId(), $clonedProductPSEId, $originalProductPSEImages, $type = 'image'); + } + + // PSE associated documents + $originalProductPSEDocuments = ProductSaleElementsProductDocumentQuery::create() + ->findByProductSaleElementsId($originalProductPSE->getId()); + + if (null !== $originalProductPSEDocuments) { + $this->clonePSEAssociatedFiles($clonedProduct->getId(), $clonedProductPSEId, $originalProductPSEDocuments, $type = 'document'); + } + } + } + + /** + * @param ProductCloneEvent $event + * @param ProductSaleElements $originalProductPSE + * @param $currencyId + * @return int + * @throws \Propel\Runtime\Exception\PropelException + */ + public function createClonePSE(ProductCloneEvent $event, ProductSaleElements $originalProductPSE, $currencyId) + { + $attributeCombinationList = AttributeCombinationQuery::create() + ->filterByProductSaleElementsId($originalProductPSE->getId()) + ->select(['ATTRIBUTE_AV_ID']) + ->find(); + + $clonedProductCreatePSEEvent = new ProductSaleElementCreateEvent($event->getClonedProduct(), $attributeCombinationList, $currencyId); + $this->eventDispatcher->dispatch(TheliaEvents::PRODUCT_ADD_PRODUCT_SALE_ELEMENT, $clonedProductCreatePSEEvent); + + return $clonedProductCreatePSEEvent->getProductSaleElement()->getId(); + } + + public function updateClonePSE(ProductCloneEvent $event, $clonedProductPSEId, ProductSaleElements $originalProductPSE, $key) + { + $originalProductPSEPrice = ProductPriceQuery::create() + ->findOneByProductSaleElementsId($originalProductPSE->getId()); + + $clonedProductUpdatePSEEvent = new ProductSaleElementUpdateEvent($event->getClonedProduct(), $clonedProductPSEId); + $clonedProductUpdatePSEEvent + ->setReference($event->getClonedProduct()->getRef().'-'.($key + 1)) + ->setIsdefault($originalProductPSE->getIsDefault()) + ->setFromDefaultCurrency(0) + + ->setWeight($originalProductPSE->getWeight()) + ->setQuantity($originalProductPSE->getQuantity()) + ->setOnsale($originalProductPSE->getPromo()) + ->setIsnew($originalProductPSE->getNewness()) + ->setEanCode($originalProductPSE->getEanCode()) + ->setTaxRuleId($event->getOriginalProduct()->getTaxRuleId()) + + ->setPrice($originalProductPSEPrice->getPrice()) + ->setSalePrice($originalProductPSEPrice->getPromoPrice()) + ->setCurrencyId($originalProductPSEPrice->getCurrencyId()); + + $this->eventDispatcher->dispatch(TheliaEvents::PRODUCT_UPDATE_PRODUCT_SALE_ELEMENT, $clonedProductUpdatePSEEvent); + } + + /** + * @param $clonedProductId + * @param $clonedProductPSEId + * @param $originalProductPSEFiles + * @param $type + * @throws \Propel\Runtime\Exception\PropelException + */ + public function clonePSEAssociatedFiles($clonedProductId, $clonedProductPSEId, $originalProductPSEFiles, $type) + { + /** @var ProductSaleElementsDocument|ProductSaleElementsImage $originalProductPSEFile */ + foreach ($originalProductPSEFiles as $originalProductPSEFile) { + $originalProductFilePositionQuery = []; + $originalProductPSEFileId = null; + + // Get file's original position + switch ($type) { + case 'image': + $originalProductFilePositionQuery = ProductImageQuery::create(); + $originalProductPSEFileId = $originalProductPSEFile->getProductImageId(); + break; + case 'document': + $originalProductFilePositionQuery = ProductDocumentQuery::create(); + $originalProductPSEFileId = $originalProductPSEFile->getProductDocumentId(); + break; + } + $originalProductFilePosition = $originalProductFilePositionQuery + ->select(['POSITION']) + ->findPk($originalProductPSEFileId); + + // Get cloned file ID to link to the cloned PSE + switch ($type) { + case 'image': + $clonedProductFileIdToLinkToPSEQuery = ProductImageQuery::create(); + break; + case 'document': + $clonedProductFileIdToLinkToPSEQuery = ProductDocumentQuery::create(); + break; + } + + $clonedProductFileIdToLinkToPSE = $clonedProductFileIdToLinkToPSEQuery + ->filterByProductId($clonedProductId) + ->filterByPosition($originalProductFilePosition) + ->select(['ID']) + ->findOne(); + + // Save association + switch ($type) { + case 'image': + $assoc = new ProductSaleElementsProductImage(); + $assoc->setProductImageId($clonedProductFileIdToLinkToPSE); + break; + case 'document': + $assoc = new ProductSaleElementsProductDocument(); + $assoc->setProductDocumentId($clonedProductFileIdToLinkToPSE); + break; + } + $assoc + ->setProductSaleElementsId($clonedProductPSEId) + ->save(); + } + } + + /*************** + * END CLONING * + ***************/ + + /** + * {@inheritDoc} + */ + public static function getSubscribedEvents() + { + return array( + TheliaEvents::PRODUCT_ADD_PRODUCT_SALE_ELEMENT => array("create", 128), + TheliaEvents::PRODUCT_UPDATE_PRODUCT_SALE_ELEMENT => array("update", 128), + TheliaEvents::PRODUCT_DELETE_PRODUCT_SALE_ELEMENT => array("delete", 128), + TheliaEvents::PRODUCT_COMBINATION_GENERATION => array("generateCombinations", 128), + TheliaEvents::PSE_CLONE => array("clonePSE", 128) + ); + } +} diff --git a/core/lib/Thelia/Action/Profile.php b/core/lib/Thelia/Action/Profile.php new file mode 100644 index 00000000..a49e85d3 --- /dev/null +++ b/core/lib/Thelia/Action/Profile.php @@ -0,0 +1,151 @@ +setDispatcher($dispatcher) + ->setCode($event->getCode()) + ->setLocale($event->getLocale()) + ->setTitle($event->getTitle()) + ->setChapo($event->getChapo()) + ->setDescription($event->getDescription()) + ->setPostscriptum($event->getPostscriptum()) + ; + + $profile->save(); + + $event->setProfile($profile); + } + + /** + * @param ProfileEvent $event + * @param $eventName + * @param EventDispatcherInterface $dispatcher + */ + public function update(ProfileEvent $event, $eventName, EventDispatcherInterface $dispatcher) + { + if (null !== $profile = ProfileQuery::create()->findPk($event->getId())) { + $profile + ->setDispatcher($dispatcher) + ->setLocale($event->getLocale()) + ->setTitle($event->getTitle()) + ->setChapo($event->getChapo()) + ->setDescription($event->getDescription()) + ->setPostscriptum($event->getPostscriptum()) + ; + + $profile->save(); + + $event->setProfile($profile); + } + } + + /** + * @param ProfileEvent $event + */ + public function updateResourceAccess(ProfileEvent $event) + { + if (null !== $profile = ProfileQuery::create()->findPk($event->getId())) { + ProfileResourceQuery::create()->filterByProfileId($event->getId())->delete(); + foreach ($event->getResourceAccess() as $resourceCode => $accesses) { + $manager = new AccessManager(0); + $manager->build($accesses); + + $profileResource = new ProfileResource(); + $profileResource->setProfileId($event->getId()) + ->setResource(ResourceQuery::create()->findOneByCode($resourceCode)) + ->setAccess($manager->getAccessValue()); + + $profileResource->save(); + } + + $event->setProfile($profile); + } + } + + /** + * @param ProfileEvent $event + */ + public function updateModuleAccess(ProfileEvent $event) + { + if (null !== $profile = ProfileQuery::create()->findPk($event->getId())) { + ProfileModuleQuery::create()->filterByProfileId($event->getId())->delete(); + foreach ($event->getModuleAccess() as $moduleCode => $accesses) { + $manager = new AccessManager(0); + $manager->build($accesses); + + $profileModule = new ProfileModule(); + $profileModule->setProfileId($event->getId()) + ->setModule(ModuleQuery::create()->findOneByCode($moduleCode)) + ->setAccess($manager->getAccessValue()); + + $profileModule->save(); + } + + $event->setProfile($profile); + } + } + + /** + * @param ProfileEvent $event + */ + public function delete(ProfileEvent $event) + { + if (null !== $profile = ProfileQuery::create()->findPk($event->getId())) { + $profile + ->delete() + ; + + $event->setProfile($profile); + } + } + + /** + * {@inheritDoc} + */ + public static function getSubscribedEvents() + { + return array( + TheliaEvents::PROFILE_CREATE => array("create", 128), + TheliaEvents::PROFILE_UPDATE => array("update", 128), + TheliaEvents::PROFILE_DELETE => array("delete", 128), + TheliaEvents::PROFILE_RESOURCE_ACCESS_UPDATE => array("updateResourceAccess", 128), + TheliaEvents::PROFILE_MODULE_ACCESS_UPDATE => array("updateModuleAccess", 128), + ); + } +} diff --git a/core/lib/Thelia/Action/RedirectException.php b/core/lib/Thelia/Action/RedirectException.php new file mode 100644 index 00000000..3bdb3fb5 --- /dev/null +++ b/core/lib/Thelia/Action/RedirectException.php @@ -0,0 +1,60 @@ + + */ +class RedirectException extends BaseAction implements EventSubscriberInterface +{ + /** @var URL */ + protected $urlManager; + + public function __construct(URL $urlManager) + { + $this->urlManager = $urlManager; + } + + public function checkRedirectException(GetResponseForExceptionEvent $event) + { + $exception = $event->getException(); + if ($exception instanceof ExceptionRedirectException) { + $response = RedirectResponse::create($exception->getUrl(), $exception->getStatusCode()); + $event->setResponse($response); + } elseif ($exception instanceof AuthenticationException) { + // Redirect to the login template + $response = RedirectResponse::create($this->urlManager->viewUrl($exception->getLoginTemplate())); + $event->setResponse($response); + } + } + + /** + * {@inheritdoc} + */ + public static function getSubscribedEvents() + { + return [ + KernelEvents::EXCEPTION => array("checkRedirectException", 128), + ]; + } +} diff --git a/core/lib/Thelia/Action/Sale.php b/core/lib/Thelia/Action/Sale.php new file mode 100644 index 00000000..07bb2bc4 --- /dev/null +++ b/core/lib/Thelia/Action/Sale.php @@ -0,0 +1,498 @@ + + */ +class Sale extends BaseAction implements EventSubscriberInterface +{ + /** + * Update PSE for a given product + * + * @param array $pseList an array of priduct sale elements + * @param bool $promoStatus true if the PSEs are on sale, false otherwise + * @param int $offsetType the offset type, see SaleModel::OFFSET_* constants + * @param Calculator $taxCalculator the tax calculator + * @param array $saleOffsetByCurrency an array of price offset for each currency (currency ID => offset_amount) + * @param ConnectionInterface $con + * @throws PropelException + */ + protected function updateProductSaleElementsPrices($pseList, $promoStatus, $offsetType, Calculator $taxCalculator, $saleOffsetByCurrency, ConnectionInterface $con) + { + /** @var ProductSaleElements $pse */ + foreach ($pseList as $pse) { + if ($pse->getPromo()!= $promoStatus) { + $pse + ->setPromo($promoStatus) + ->save($con) + ; + } + + /** @var SaleOffsetCurrency $offsetByCurrency */ + foreach ($saleOffsetByCurrency as $currencyId => $offset) { + $productPrice = ProductPriceQuery::create() + ->filterByProductSaleElementsId($pse->getId()) + ->filterByCurrencyId($currencyId) + ->findOne($con); + + if (null !== $productPrice) { + // Get the taxed price + $priceWithTax = $taxCalculator->getTaxedPrice($productPrice->getPrice()); + + // Remove the price offset to get the taxed promo price + switch ($offsetType) { + case SaleModel::OFFSET_TYPE_AMOUNT: + $promoPrice = max(0, $priceWithTax - $offset); + break; + + case SaleModel::OFFSET_TYPE_PERCENTAGE: + $promoPrice = $priceWithTax * (1 - $offset / 100); + break; + + default: + $promoPrice = $priceWithTax; + } + + // and then get the untaxed promo price. + $promoPrice = $taxCalculator->getUntaxedPrice($promoPrice); + + $productPrice + ->setPromoPrice($promoPrice) + ->save($con) + ; + } + } + } + } + /** + * Update the promo status of the sale's selected products and combinations + * + * @param ProductSaleStatusUpdateEvent $event + * @throws \RuntimeException + * @throws \Exception + * @throws \Propel\Runtime\Exception\PropelException + */ + public function updateProductsSaleStatus(ProductSaleStatusUpdateEvent $event) + { + $taxCalculator = new Calculator(); + + $sale = $event->getSale(); + + // Get all selected product sale elements for this sale + if (null !== $saleProducts = SaleProductQuery::create()->filterBySale($sale)->orderByProductId()) { + $saleOffsetByCurrency = $sale->getPriceOffsets(); + + $offsetType = $sale->getPriceOffsetType(); + + $con = Propel::getWriteConnection(SaleTableMap::DATABASE_NAME); + + $con->beginTransaction(); + + try { + /** @var SaleProduct $saleProduct */ + foreach ($saleProducts as $saleProduct) { + // Reset all sale status on product's PSE + ProductSaleElementsQuery::create() + ->filterByProductId($saleProduct->getProductId()) + ->update([ 'Promo' => false], $con) + ; + + $taxCalculator->load( + $saleProduct->getProduct($con), + CountryModel::getShopLocation() + ); + + $attributeAvId = $saleProduct->getAttributeAvId(); + + $pseRequest = ProductSaleElementsQuery::create() + ->filterByProductId($saleProduct->getProductId()) + ; + + // If no attribute AV id is defined, consider ALL product combinations + if (! \is_null($attributeAvId)) { + // Find PSE attached to combination containing this attribute av : + // SELECT * from product_sale_elements pse + // left join attribute_combination ac on ac.product_sale_elements_id = pse.id + // where pse.product_id=363 + // and ac.attribute_av_id = 7 + // group by pse.id + + $pseRequest + ->useAttributeCombinationQuery(null, Criteria::LEFT_JOIN) + ->filterByAttributeAvId($attributeAvId) + ->endUse() + ; + } + + $pseList = $pseRequest->find(); + + if (null !== $pseList) { + $this->updateProductSaleElementsPrices( + $pseList, + $sale->getActive(), + $offsetType, + $taxCalculator, + $saleOffsetByCurrency, + $con + ); + } + } + + $con->commit(); + } catch (PropelException $e) { + $con->rollback(); + throw $e; + } + } + } + + /** + * Create a new Sale + * + * @param SaleCreateEvent $event + */ + public function create(SaleCreateEvent $event) + { + $sale = new SaleModel(); + + $sale + ->setLocale($event->getLocale()) + ->setTitle($event->getTitle()) + ->setSaleLabel($event->getSaleLabel()) + ->save() + ; + + $event->setSale($sale); + } + + /** + * Process update sale + * + * @param SaleUpdateEvent $event + * @param $eventName + * @param EventDispatcherInterface $dispatcher + * @throws PropelException + */ + public function update(SaleUpdateEvent $event, $eventName, EventDispatcherInterface $dispatcher) + { + if (null !== $sale = SaleQuery::create()->findPk($event->getSaleId())) { + $sale->setDispatcher($dispatcher); + + $con = Propel::getWriteConnection(SaleTableMap::DATABASE_NAME); + + $con->beginTransaction(); + + try { + // Disable all promo flag on sale's currently selected products, + // to reset promo status of the products that may have been removed from the selection. + $sale->setActive(false); + + $dispatcher->dispatch( + TheliaEvents::UPDATE_PRODUCT_SALE_STATUS, + new ProductSaleStatusUpdateEvent($sale) + ); + + $sale + ->setActive($event->getActive()) + ->setStartDate($event->getStartDate()) + ->setEndDate($event->getEndDate()) + ->setPriceOffsetType($event->getPriceOffsetType()) + ->setDisplayInitialPrice($event->getDisplayInitialPrice()) + ->setLocale($event->getLocale()) + ->setSaleLabel($event->getSaleLabel()) + ->setTitle($event->getTitle()) + ->setDescription($event->getDescription()) + ->setChapo($event->getChapo()) + ->setPostscriptum($event->getPostscriptum()) + ->save($con) + ; + + $event->setSale($sale); + + // Update price offsets + SaleOffsetCurrencyQuery::create()->filterBySaleId($sale->getId())->delete($con); + + foreach ($event->getPriceOffsets() as $currencyId => $priceOffset) { + $saleOffset = new SaleOffsetCurrency(); + + $saleOffset + ->setCurrencyId($currencyId) + ->setSaleId($sale->getId()) + ->setPriceOffsetValue($priceOffset) + ->save($con) + ; + } + + // Update products + SaleProductQuery::create()->filterBySaleId($sale->getId())->delete($con); + + $productAttributesArray = $event->getProductAttributes(); + + foreach ($event->getProducts() as $productId) { + if (isset($productAttributesArray[$productId])) { + foreach ($productAttributesArray[$productId] as $attributeId) { + $saleProduct = new SaleProduct(); + + $saleProduct + ->setSaleId($sale->getId()) + ->setProductId($productId) + ->setAttributeAvId($attributeId) + ->save($con) + ; + } + } else { + $saleProduct = new SaleProduct(); + + $saleProduct + ->setSaleId($sale->getId()) + ->setProductId($productId) + ->setAttributeAvId(null) + ->save($con) + ; + } + } + + // Update related products sale status if the Sale is active. This is not required if the sale is + // not active, as we de-activated promotion for this sale at the beginning ofd this method + if ($sale->getActive()) { + $dispatcher->dispatch( + TheliaEvents::UPDATE_PRODUCT_SALE_STATUS, + new ProductSaleStatusUpdateEvent($sale) + ); + } + + $con->commit(); + } catch (PropelException $e) { + $con->rollback(); + throw $e; + } + } + } + + /** + * Toggle Sale activity + * + * @param SaleToggleActivityEvent $event + * @param $eventName + * @param EventDispatcherInterface $dispatcher + * @throws \Propel\Runtime\Exception\PropelException + */ + public function toggleActivity(SaleToggleActivityEvent $event, $eventName, EventDispatcherInterface $dispatcher) + { + $sale = $event->getSale(); + + $con = Propel::getWriteConnection(SaleTableMap::DATABASE_NAME); + + $con->beginTransaction(); + + try { + $sale + ->setDispatcher($dispatcher) + ->setActive(!$sale->getActive()) + ->save($con); + + // Update related products sale status + $dispatcher->dispatch( + TheliaEvents::UPDATE_PRODUCT_SALE_STATUS, + new ProductSaleStatusUpdateEvent($sale) + ); + + $event->setSale($sale); + + $con->commit(); + } catch (PropelException $e) { + $con->rollback(); + throw $e; + } + } + + /** + * Delete a sale + * + * @param SaleDeleteEvent $event + * @param $eventName + * @param EventDispatcherInterface $dispatcher + * @throws \Propel\Runtime\Exception\PropelException + */ + public function delete(SaleDeleteEvent $event, $eventName, EventDispatcherInterface $dispatcher) + { + if (null !== $sale = SaleQuery::create()->findPk($event->getSaleId())) { + $con = Propel::getWriteConnection(SaleTableMap::DATABASE_NAME); + + $con->beginTransaction(); + + try { + // Update related products sale status, if required + if ($sale->getActive()) { + $sale->setActive(false); + + // Update related products sale status + $dispatcher->dispatch( + TheliaEvents::UPDATE_PRODUCT_SALE_STATUS, + new ProductSaleStatusUpdateEvent($sale) + ); + } + + $sale->setDispatcher($dispatcher)->delete($con); + + $event->setSale($sale); + + $con->commit(); + } catch (PropelException $e) { + $con->rollback(); + throw $e; + } + } + } + + /** + * Clear all sales + * + * @param SaleClearStatusEvent $event + * @throws \Exception + */ + public function clearStatus(/** @noinspection PhpUnusedParameterInspection */ SaleClearStatusEvent $event) + { + $con = Propel::getWriteConnection(SaleTableMap::DATABASE_NAME); + $con->beginTransaction(); + + try { + // Set the active status of all Sales to false + SaleQuery::create() + ->filterByActive(true) + ->update([ 'Active' => false ], $con) + ; + + // Reset all sale status on PSE + ProductSaleElementsQuery::create() + ->filterByPromo(true) + ->update([ 'Promo' => false], $con) + ; + + $con->commit(); + } catch (PropelException $e) { + $con->rollback(); + throw $e; + } + } + + /** + * This method check the activation and deactivation dates of sales, and perform + * the required action depending on the current date. + * + * @param SaleActiveStatusCheckEvent $event + * @param $eventName + * @param EventDispatcherInterface $dispatcher + * @throws \Propel\Runtime\Exception\PropelException + */ + public function checkSaleActivation(SaleActiveStatusCheckEvent $event, $eventName, EventDispatcherInterface $dispatcher) + { + $con = Propel::getWriteConnection(SaleTableMap::DATABASE_NAME); + $con->beginTransaction(); + + try { + $now = time(); + + // Disable expired sales + if (null !== $salesToDisable = SaleQuery::create() + ->filterByActive(true) + ->filterByEndDate($now, Criteria::LESS_THAN) + ->find()) { + /** @var SaleModel $sale */ + foreach ($salesToDisable as $sale) { + $sale->setActive(false)->save(); + + // Update related products sale status + $dispatcher->dispatch( + TheliaEvents::UPDATE_PRODUCT_SALE_STATUS, + new ProductSaleStatusUpdateEvent($sale) + ); + } + } + + // Enable sales that should be enabled. + if (null !== $salesToEnable = SaleQuery::create() + ->filterByActive(false) + ->filterByStartDate($now, Criteria::LESS_EQUAL) + ->filterByEndDate($now, Criteria::GREATER_EQUAL) + ->find()) { + /** @var SaleModel $sale */ + foreach ($salesToEnable as $sale) { + $sale->setActive(true)->save(); + + // Update related products sale status + $dispatcher->dispatch( + TheliaEvents::UPDATE_PRODUCT_SALE_STATUS, + new ProductSaleStatusUpdateEvent($sale) + ); + } + } + + $con->commit(); + } catch (PropelException $e) { + $con->rollback(); + throw $e; + } + } + + /** + * @inheritdoc + */ + public static function getSubscribedEvents() + { + return array( + TheliaEvents::SALE_CREATE => array('create', 128), + TheliaEvents::SALE_UPDATE => array('update', 128), + TheliaEvents::SALE_DELETE => array('delete', 128), + + TheliaEvents::SALE_TOGGLE_ACTIVITY => array('toggleActivity', 128), + + TheliaEvents::SALE_CLEAR_SALE_STATUS => array('clearStatus', 128), + + TheliaEvents::UPDATE_PRODUCT_SALE_STATUS => array('updateProductsSaleStatus', 128), + + TheliaEvents::CHECK_SALE_ACTIVATION_EVENT => array('checkSaleActivation', 128), + ); + } +} diff --git a/core/lib/Thelia/Action/ShippingZone.php b/core/lib/Thelia/Action/ShippingZone.php new file mode 100644 index 00000000..7cff6e74 --- /dev/null +++ b/core/lib/Thelia/Action/ShippingZone.php @@ -0,0 +1,63 @@ + + */ +class ShippingZone extends BaseAction implements EventSubscriberInterface +{ + public function addArea(ShippingZoneAddAreaEvent $event) + { + $areaDelivery = new AreaDeliveryModule(); + + $areaDelivery + ->setAreaId($event->getAreaId()) + ->setDeliveryModuleId($event->getShippingZoneId()) + ->save(); + } + + public function removeArea(ShippingZoneRemoveAreaEvent $event) + { + $areaDelivery = AreaDeliveryModuleQuery::create() + ->filterByAreaId($event->getAreaId()) + ->filterByDeliveryModuleId($event->getShippingZoneId()) + ->findOne(); + + if ($areaDelivery) { + $areaDelivery->delete(); + } else { + throw new \RuntimeException(sprintf('areaDeliveryModule not found with area_id = %d and delivery_module_id = %d', $event->getAreaId(), $event->getShippingZoneId())); + } + } + + /** + * {@inheritdoc} + */ + public static function getSubscribedEvents() + { + return array( + TheliaEvents::SHIPPING_ZONE_ADD_AREA => array('addArea', 128), + TheliaEvents::SHIPPING_ZONE_REMOVE_AREA => array('removeArea', 128), + ); + } +} diff --git a/core/lib/Thelia/Action/State.php b/core/lib/Thelia/Action/State.php new file mode 100644 index 00000000..d7bbeae3 --- /dev/null +++ b/core/lib/Thelia/Action/State.php @@ -0,0 +1,103 @@ + + */ +class State extends BaseAction implements EventSubscriberInterface +{ + public function create(StateCreateEvent $event) + { + $state = new StateModel(); + + $state + ->setVisible($event->isVisible()) + ->setCountryId($event->getCountry()) + ->setIsocode($event->getIsocode()) + ->setLocale($event->getLocale()) + ->setTitle($event->getTitle()) + ->save() + ; + + $event->setState($state); + } + + public function update(StateUpdateEvent $event) + { + if (null !== $state = StateQuery::create()->findPk($event->getStateId())) { + $state + ->setVisible($event->isVisible()) + ->setCountryId($event->getCountry()) + ->setIsocode($event->getIsocode()) + ->setLocale($event->getLocale()) + ->setTitle($event->getTitle()) + ->save() + ; + + $event->setState($state); + } + } + + public function delete(StateDeleteEvent $event) + { + if (null !== $state = StateQuery::create()->findPk($event->getStateId())) { + $state->delete(); + + $event->setState($state); + } + } + + /** + * Toggle State visibility + * + * @param StateToggleVisibilityEvent $event + */ + public function toggleVisibility(StateToggleVisibilityEvent $event, $eventName, EventDispatcherInterface $dispatcher) + { + $state = $event->getState(); + + $state + ->setDispatcher($dispatcher) + ->setVisible(!$state->getVisible()) + ->save() + ; + + $event->setState($state); + } + + /** + * {@inheritdoc} + */ + public static function getSubscribedEvents() + { + return array( + TheliaEvents::STATE_CREATE => array('create', 128), + TheliaEvents::STATE_UPDATE => array('update', 128), + TheliaEvents::STATE_DELETE => array('delete', 128), + TheliaEvents::STATE_TOGGLE_VISIBILITY => array('toggleVisibility', 128) + ); + } +} diff --git a/core/lib/Thelia/Action/Tax.php b/core/lib/Thelia/Action/Tax.php new file mode 100644 index 00000000..dbde1eff --- /dev/null +++ b/core/lib/Thelia/Action/Tax.php @@ -0,0 +1,95 @@ +setDispatcher($dispatcher) + ->setRequirements($event->getRequirements()) + ->setType($event->getType()) + ->setLocale($event->getLocale()) + ->setTitle($event->getTitle()) + ->setDescription($event->getDescription()) + ; + + $tax->save(); + + $event->setTax($tax); + } + + /** + * @param TaxEvent $event + * @param $eventName + * @param EventDispatcherInterface $dispatcher + */ + public function update(TaxEvent $event, $eventName, EventDispatcherInterface $dispatcher) + { + if (null !== $tax = TaxQuery::create()->findPk($event->getId())) { + $tax + ->setDispatcher($dispatcher) + ->setRequirements($event->getRequirements()) + ->setType($event->getType()) + ->setLocale($event->getLocale()) + ->setTitle($event->getTitle()) + ->setDescription($event->getDescription()) + ; + + $tax->save(); + + $event->setTax($tax); + } + } + + /** + * @param TaxEvent $event + */ + public function delete(TaxEvent $event) + { + if (null !== $tax = TaxQuery::create()->findPk($event->getId())) { + $tax + ->delete() + ; + + $event->setTax($tax); + } + } + + /** + * {@inheritDoc} + */ + public static function getSubscribedEvents() + { + return array( + TheliaEvents::TAX_CREATE => array("create", 128), + TheliaEvents::TAX_UPDATE => array("update", 128), + TheliaEvents::TAX_DELETE => array("delete", 128), + ); + } +} diff --git a/core/lib/Thelia/Action/TaxRule.php b/core/lib/Thelia/Action/TaxRule.php new file mode 100644 index 00000000..8f408806 --- /dev/null +++ b/core/lib/Thelia/Action/TaxRule.php @@ -0,0 +1,205 @@ +setDispatcher($dispatcher) + ->setLocale($event->getLocale()) + ->setTitle($event->getTitle()) + ->setDescription($event->getDescription()) + ; + + $taxRule->save(); + + $event->setTaxRule($taxRule)->setId($taxRule->getId()); + } + + /** + * @param TaxRuleEvent $event + */ + public function update(TaxRuleEvent $event, $eventName, EventDispatcherInterface $dispatcher) + { + if (null !== $taxRule = TaxRuleQuery::create()->findPk($event->getId())) { + $taxRule + ->setDispatcher($dispatcher) + ->setLocale($event->getLocale()) + ->setTitle($event->getTitle()) + ->setDescription($event->getDescription()) + ->save() + ; + + $event->setTaxRule($taxRule); + } + } + + /** + * @param TaxRuleEvent $event + */ + public function updateTaxes(TaxRuleEvent $event) + { + if (null !== $taxRule = TaxRuleQuery::create()->findPk($event->getId())) { + $taxList = $this->getArrayFromJson($event->getTaxList()); + $countryList = $this->getArrayFromJson22Compat($event->getCountryList()); + $countryDeletedList = $this->getArrayFromJson22Compat($event->getCountryDeletedList()); + + /* clean the current tax rule for the countries/states */ + $deletes = array_merge($countryList, $countryDeletedList); + foreach ($deletes as $item) { + TaxRuleCountryQuery::create() + ->filterByTaxRule($taxRule) + ->filterByCountryId(\intval($item[0]), Criteria::EQUAL) + ->filterByStateId(\intval($item[1]) !== 0 ? $item[1] : null, Criteria::EQUAL) + ->delete(); + } + + /* for each country */ + foreach ($countryList as $item) { + $position = 1; + $countryId = \intval($item[0]); + $stateId = \intval($item[1]); + + /* on applique les nouvelles regles */ + foreach ($taxList as $tax) { + if (\is_array($tax)) { + foreach ($tax as $samePositionTax) { + $taxModel = new TaxRuleCountry(); + $taxModel->setTaxRule($taxRule) + ->setCountryId($countryId) + ->setStateId($stateId ?: null) + ->setTaxId($samePositionTax) + ->setPosition($position); + $taxModel->save(); + } + } else { + $taxModel = new TaxRuleCountry(); + $taxModel->setTaxRule($taxRule) + ->setCountryId($countryId) + ->setStateId($stateId ?: null) + ->setTaxId($tax) + ->setPosition($position); + $taxModel->save(); + } + $position++; + } + } + + $event->setTaxRule($taxRule); + } + } + + protected function getArrayFromJson($obj) + { + if (\is_null($obj)) { + $obj = []; + } else { + $obj = \is_array($obj) + ? $obj + : json_decode($obj, true); + } + + return $obj; + } + + /** + * This method ensures compatibility with the 2.2.x country arrays passed throught the TaxRuleEvent + * + * In 2.2.x, the TaxRuleEvent::getXXXCountryList() methods returned an array of country IDs. [ country ID, country ID ...]. + * From 2.3.0-alpha1, these functions are expected to return an array of arrays, each one containing a country ID and + * a state ID. [ [ country ID, state ID], [ country ID, state ID], ...]. + * + * This method checks the $obj parameter, and create a 2.3.0-alpha1 compatible return value if $obj is expressed using + * the 2.2.x form. + * + * @param array $obj + * + * @return array + */ + protected function getArrayFromJson22Compat($obj) + { + $obj = $this->getArrayFromJson($obj); + + if (isset($obj[0]) && ! \is_array($obj[0])) { + $objEx = []; + foreach ($obj as $item) { + $objEx[] = [$item, 0]; + } + + return $objEx; + } + + return $obj; + } + + /** + * @param TaxRuleEvent $event + */ + public function delete(TaxRuleEvent $event) + { + if (null !== $taxRule = TaxRuleQuery::create()->findPk($event->getId())) { + $taxRule + ->delete() + ; + + $event->setTaxRule($taxRule); + } + } + + /** + * @param TaxRuleEvent $event + */ + public function setDefault(TaxRuleEvent $event) + { + if (null !== $taxRule = TaxRuleQuery::create()->findPk($event->getId())) { + TaxRuleQuery::create()->update(array( + "IsDefault" => 0 + )); + + $taxRule->setIsDefault(1)->save(); + + $event->setTaxRule($taxRule); + } + } + + /** + * {@inheritDoc} + */ + public static function getSubscribedEvents() + { + return array( + TheliaEvents::TAX_RULE_CREATE => array("create", 128), + TheliaEvents::TAX_RULE_UPDATE => array("update", 128), + TheliaEvents::TAX_RULE_TAXES_UPDATE => array("updateTaxes", 128), + TheliaEvents::TAX_RULE_DELETE => array("delete", 128), + TheliaEvents::TAX_RULE_SET_DEFAULT => array("setDefault", 128), + ); + } +} diff --git a/core/lib/Thelia/Action/Template.php b/core/lib/Thelia/Action/Template.php new file mode 100644 index 00000000..1defb028 --- /dev/null +++ b/core/lib/Thelia/Action/Template.php @@ -0,0 +1,288 @@ +setDispatcher($dispatcher) + + ->setLocale($event->getLocale()) + ->setName($event->getTemplateName()) + + ->save() + ; + + $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 + * + * @param \Thelia\Core\Event\Template\TemplateUpdateEvent $event + * @param $eventName + * @param EventDispatcherInterface $dispatcher + */ + public function update(TemplateUpdateEvent $event, $eventName, EventDispatcherInterface $dispatcher) + { + if (null !== $template = TemplateQuery::create()->findPk($event->getTemplateId())) { + $template + ->setDispatcher($dispatcher) + + ->setLocale($event->getLocale()) + ->setName($event->getTemplateName()) + ->save(); + + $event->setTemplate($template); + } + } + + /** + * Delete a product template entry + * + * @param \Thelia\Core\Event\Template\TemplateDeleteEvent $event + * @param $eventName + * @param EventDispatcherInterface $dispatcher + * @throws \Exception + */ + public function delete(TemplateDeleteEvent $event, $eventName, EventDispatcherInterface $dispatcher) + { + if (null !== ($template = TemplateQuery::create()->findPk($event->getTemplateId()))) { + // Check if template is used by a product + $productCount = ProductQuery::create()->findByTemplateId($template->getId())->count(); + + if ($productCount <= 0) { + $con = Propel::getWriteConnection(TemplateTableMap::DATABASE_NAME); + $con->beginTransaction(); + + try { + $template + ->setDispatcher($dispatcher) + ->delete($con); + + // 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 + // so let's take care of this. + CategoryQuery::create() + ->filterByDefaultTemplateId($event->getTemplateId()) + ->update([ 'DefaultTemplateId' => null], $con); + + $con->commit(); + } catch (\Exception $ex) { + $con->rollback(); + + throw $ex; + } + } + + $event->setTemplate($template); + + $event->setProductCount($productCount); + } + } + + public function addAttribute(TemplateAddAttributeEvent $event) + { + if (null === AttributeTemplateQuery::create() + ->filterByAttributeId($event->getAttributeId()) + ->filterByTemplate($event->getTemplate()) + ->findOne()) { + $attributeTemplate = new AttributeTemplate(); + + $attributeTemplate + ->setAttributeId($event->getAttributeId()) + ->setTemplate($event->getTemplate()) + ->save() + ; + } + } + + /** + * Changes position, selecting absolute ou relative change. + * + * @param UpdatePositionEvent $event + * @param $eventName + * @param EventDispatcherInterface $dispatcher + */ + public function updateAttributePosition(UpdatePositionEvent $event, $eventName, EventDispatcherInterface $dispatcher) + { + $this->genericUpdatePosition(AttributeTemplateQuery::create(), $event, $dispatcher); + } + + /** + * Changes position, selecting absolute ou relative change. + * + * @param UpdatePositionEvent $event + * @param $eventName + * @param EventDispatcherInterface $dispatcher + */ + public function updateFeaturePosition(UpdatePositionEvent $event, $eventName, EventDispatcherInterface $dispatcher) + { + $this->genericUpdatePosition(FeatureTemplateQuery::create(), $event, $dispatcher); + } + + public function deleteAttribute(TemplateDeleteAttributeEvent $event, $eventName, EventDispatcherInterface $dispatcher) + { + $attributeTemplate = AttributeTemplateQuery::create() + ->filterByAttributeId($event->getAttributeId()) + ->filterByTemplate($event->getTemplate())->findOne() + ; + + if ($attributeTemplate !== null) { + $attributeTemplate + ->setDispatcher($dispatcher) + ->delete(); + } else { + // Prevent event propagation + $event->stopPropagation(); + } + } + + public function addFeature(TemplateAddFeatureEvent $event) + { + if (null === FeatureTemplateQuery::create() + ->filterByFeatureId($event->getFeatureId()) + ->filterByTemplate($event->getTemplate()) + ->findOne() + ) { + $featureTemplate = new FeatureTemplate(); + + $featureTemplate + ->setFeatureId($event->getFeatureId()) + ->setTemplate($event->getTemplate()) + ->save() + ; + } + } + + public function deleteFeature(TemplateDeleteFeatureEvent $event, $eventName, EventDispatcherInterface $dispatcher) + { + $featureTemplate = FeatureTemplateQuery::create() + ->filterByFeatureId($event->getFeatureId()) + ->filterByTemplate($event->getTemplate())->findOne() + ; + + if ($featureTemplate !== null) { + $featureTemplate + ->setDispatcher($dispatcher) + ->delete(); + } else { + // Prevent event propagation + $event->stopPropagation(); + } + } + + /** + * {@inheritDoc} + */ + public static function getSubscribedEvents() + { + return array( + TheliaEvents::TEMPLATE_CREATE => array("create", 128), + TheliaEvents::TEMPLATE_UPDATE => array("update", 128), + TheliaEvents::TEMPLATE_DELETE => array("delete", 128), + TheliaEvents::TEMPLATE_DUPLICATE => array("duplicate", 128), + + TheliaEvents::TEMPLATE_ADD_ATTRIBUTE => array("addAttribute", 128), + TheliaEvents::TEMPLATE_DELETE_ATTRIBUTE => array("deleteAttribute", 128), + + TheliaEvents::TEMPLATE_ADD_FEATURE => array("addFeature", 128), + TheliaEvents::TEMPLATE_DELETE_FEATURE => array("deleteFeature", 128), + + TheliaEvents::TEMPLATE_CHANGE_ATTRIBUTE_POSITION => array('updateAttributePosition', 128), + TheliaEvents::TEMPLATE_CHANGE_FEATURE_POSITION => array('updateFeaturePosition', 128), + ); + } +} diff --git a/core/lib/Thelia/Action/Translation.php b/core/lib/Thelia/Action/Translation.php new file mode 100644 index 00000000..e5dc022a --- /dev/null +++ b/core/lib/Thelia/Action/Translation.php @@ -0,0 +1,372 @@ + + */ +class Translation extends BaseAction implements EventSubscriberInterface +{ + /** @var ContainerInterface */ + protected $container; + + public function __construct(ContainerInterface $container) + { + $this->container = $container; + } + + public function getTranslatableStrings(TranslationEvent $event) + { + $stringCount = $this->walkDir( + $event->getDirectory(), + $event->getMode(), + $event->getLocale(), + $event->getDomain(), + $strings + ); + + $event + ->setTranslatableStrings($strings) + ->setTranslatableStringCount($stringCount) + ; + } + /** + * Recursively examine files in a directory tree, and extract translatable strings. + * + * Returns an array of translatable strings, each item having with the following structure: + * 'files' an array of file names in which the string appears, + * 'text' the translatable text + * 'translation' => the text translation, or an empty string if none available. + * 'dollar' => true if the translatable text contains a $ + * + * @param string $directory the path to the directory to examine + * @param string $walkMode type of file scanning: WALK_MODE_PHP or WALK_MODE_TEMPLATE + * @param string $currentLocale the current locale + * @param string $domain the translation domain (fontoffice, backoffice, module, etc...) + * @param array $strings the list of strings + * @throws \InvalidArgumentException if $walkMode contains an invalid value + * @return number the total number of translatable texts + */ + protected function walkDir($directory, $walkMode, $currentLocale, $domain, &$strings) + { + $numTexts = 0; + + if ($walkMode == TranslationEvent::WALK_MODE_PHP) { + $prefix = '\-\>[\s]*trans[\s]*\([\s]*'; + + $allowedExts = array('php'); + } elseif ($walkMode == TranslationEvent::WALK_MODE_TEMPLATE) { + $prefix = '\{intl(?:.*?)[\s]l=[\s]*'; + + $allowedExts = array('html', 'tpl', 'xml', 'txt'); + } else { + throw new \InvalidArgumentException( + Translator::getInstance()->trans( + 'Invalid value for walkMode parameter: %value', + array('%value' => $walkMode) + ) + ); + } + + try { + Tlog::getInstance()->debug("Walking in $directory, in mode $walkMode"); + + /** @var \DirectoryIterator $fileInfo */ + foreach (new \DirectoryIterator($directory) as $fileInfo) { + if ($fileInfo->isDot()) { + continue; + } + + if ($fileInfo->isDir()) { + $numTexts += $this->walkDir( + $fileInfo->getPathName(), + $walkMode, + $currentLocale, + $domain, + $strings + ); + } + + if ($fileInfo->isFile()) { + $ext = $fileInfo->getExtension(); + + if (\in_array($ext, $allowedExts)) { + if ($content = file_get_contents($fileInfo->getPathName())) { + $short_path = $this->normalizePath($fileInfo->getPathName()); + + Tlog::getInstance()->debug("Examining file $short_path\n"); + + $matches = array(); + + if (preg_match_all( + '/'.$prefix.'((?debug("Strings found: ", $matches[2]); + + $idx = 0; + + foreach ($matches[2] as $match) { + $hash = md5($match); + + if (isset($strings[$hash])) { + if (! \in_array($short_path, $strings[$hash]['files'])) { + $strings[$hash]['files'][] = $short_path; + } + } else { + $numTexts++; + + // remove \' (or \"), that will prevent the translator to work properly, as + // "abc \def\" ghi" will be passed as abc "def" ghi to the translator. + + $quote = $matches[1][$idx]; + + $match = str_replace("\\$quote", $quote, $match); + + // Ignore empty strings + if (\strlen($match) == 0) { + continue; + } + + $strings[$hash] = array( + 'files' => array($short_path), + 'text' => $match, + 'translation' => Translator::getInstance()->trans( + $match, + [], + $domain, + $currentLocale, + false, + false + ), + 'custom_fallback' => Translator::getInstance()->trans( + sprintf( + Translator::GLOBAL_FALLBACK_KEY, + $domain, + $match + ), + [], + Translator::GLOBAL_FALLBACK_DOMAIN, + $currentLocale, + false, + false + ), + 'global_fallback' => Translator::getInstance()->trans( + $match, + [], + Translator::GLOBAL_FALLBACK_DOMAIN, + $currentLocale, + false, + false + ), + 'dollar' => strstr($match, '$') !== false + ); + } + + $idx++; + } + } + } + } + } + } + } catch (\UnexpectedValueException $ex) { + // Directory does not exists => ignore it. + } + + return $numTexts; + } + + public function writeTranslationFile(TranslationEvent $event, $eventName, EventDispatcherInterface $dispatcher) + { + $file = $event->getTranslationFilePath(); + + $fs = new Filesystem(); + + if (! $fs->exists($file) && true === $event->isCreateFileIfNotExists()) { + $dir = dirname($file); + + if (! $fs->exists($file)) { + $fs->mkdir($dir); + + $this->cacheClear($dispatcher); + } + } + + if ($fp = @fopen($file, 'w')) { + fwrite($fp, '<' . "?php\n\n"); + fwrite($fp, "return array(\n"); + + $texts = $event->getTranslatableStrings(); + $translations = $event->getTranslatedStrings(); + + // Sort keys alphabetically while keeping index + asort($texts); + + foreach ($texts as $key => $text) { + // Write only defined (not empty) translations + if (! empty($translations[$key])) { + $text = str_replace("'", "\'", $text); + + $translation = str_replace("'", "\'", $translations[$key]); + + fwrite($fp, sprintf(" '%s' => '%s',\n", $text, $translation)); + } + } + + fwrite($fp, ");\n"); + + @fclose($fp); + } else { + throw new \RuntimeException( + Translator::getInstance()->trans( + 'Failed to open translation file %file. Please be sure that this file is writable by your Web server', + array('%file' => $file) + ) + ); + } + } + + public function writeFallbackFile(TranslationEvent $event, $eventName, EventDispatcherInterface $dispatcher) + { + $file = THELIA_LOCAL_DIR . 'I18n' . DS . $event->getLocale() . '.php'; + + $fs = new Filesystem(); + $translations = []; + + if (! $fs->exists($file)) { + if (true === $event->isCreateFileIfNotExists()) { + $dir = dirname($file); + $fs->mkdir($dir); + + $this->cacheClear($dispatcher); + } else { + throw new \RuntimeException( + Translator::getInstance()->trans( + 'Failed to open translation file %file. Please be sure that this file is writable by your Web server', + array('%file' => $file) + ) + ); + } + } else { + /*$loader = new PhpFileLoader(); + $catalogue = $loade r->load($file); + $translations = $catalogue->all(); + */ + $translations = require $file; + + if (! \is_array($translations)) { + $translations = []; + } + } + + if ($fp = @fopen($file, 'w')) { + $texts = $event->getTranslatableStrings(); + $customs = $event->getCustomFallbackStrings(); + $globals = $event->getGlobalFallbackStrings(); + + // just reset current translations for this domain to remove strings that do not exist anymore + $translations[$event->getDomain()] = []; + + foreach ($texts as $key => $text) { + if (!empty($customs[$key])) { + $translations[$event->getDomain()][$text] = $customs[$key]; + } + + if (!empty($globals[$key])) { + $translations[$text] = $globals[$key]; + } else { + unset($translations[$text]); + } + } + + fwrite($fp, '<' . "?php\n\n"); + fwrite($fp, "return [\n"); + + // Sort keys alphabetically while keeping index + ksort($translations); + + foreach ($translations as $key => $text) { + // Write only defined (not empty) translations + if (!empty($translations[$key])) { + if (\is_array($translations[$key])) { + $key = str_replace("'", "\'", $key); + fwrite($fp, sprintf(" '%s' => [\n", $key)); + ksort($translations[$key]); + foreach ($translations[$key] as $subKey => $subText) { + $subKey = str_replace("'", "\'", $subKey); + $translation = str_replace("'", "\'", $subText); + fwrite($fp, sprintf(" '%s' => '%s',\n", $subKey, $translation)); + } + fwrite($fp, " ],\n"); + } else { + $key = str_replace("'", "\'", $key); + $translation = str_replace("'", "\'", $text); + fwrite($fp, sprintf(" '%s' => '%s',\n", $key, $translation)); + } + } + } + + fwrite($fp, "];\n"); + + @fclose($fp); + } + } + + protected function normalizePath($path) + { + $path = str_replace( + str_replace('\\', '/', THELIA_ROOT), + '', + str_replace('\\', '/', realpath($path)) + ); + + return ltrim($path, '/'); + } + + protected function cacheClear(EventDispatcherInterface $dispatcher) + { + $cacheEvent = new CacheEvent( + $this->container->getParameter('kernel.cache_dir') + ); + + $dispatcher->dispatch(TheliaEvents::CACHE_CLEAR, $cacheEvent); + } + + /** + * {@inheritdoc} + */ + public static function getSubscribedEvents() + { + return array( + TheliaEvents::TRANSLATION_GET_STRINGS => array('getTranslatableStrings', 128), + TheliaEvents::TRANSLATION_WRITE_FILE => [ + ['writeTranslationFile', 128], + ['writeFallbackFile', 128] + ] + ); + } +} diff --git a/core/lib/Thelia/Cart/CartTrait.php b/core/lib/Thelia/Cart/CartTrait.php new file mode 100644 index 00000000..59382c8e --- /dev/null +++ b/core/lib/Thelia/Cart/CartTrait.php @@ -0,0 +1,54 @@ + + * + * @deprecated CartTrait is deprecated, please use Session::getSessionCart method instead + */ +trait CartTrait +{ + /** + * + * search if cart already exists in session. If not try to create a new one or duplicate an old one. + * + * @param EventDispatcherInterface $dispatcher the event dispatcher + * @param \Symfony\Component\HttpFoundation\Request $request + * @deprecated use Session::getSessionCart method instead + * @return \Thelia\Model\Cart + */ + public function getCart(EventDispatcherInterface $dispatcher, Request $request) + { + trigger_error( + 'CartTrait is deprecated, please use Session::getSessionCart method instead', + E_USER_DEPRECATED + ); + + return $request->getSession()->getSessionCart($dispatcher); + } +} diff --git a/core/lib/Thelia/Command/AdminUpdatePasswordCommand.php b/core/lib/Thelia/Command/AdminUpdatePasswordCommand.php new file mode 100644 index 00000000..7a77d23e --- /dev/null +++ b/core/lib/Thelia/Command/AdminUpdatePasswordCommand.php @@ -0,0 +1,98 @@ + + */ +class AdminUpdatePasswordCommand extends ContainerAwareCommand +{ + protected function init() + { + $container = $this->getContainer(); + + $request = new Request(); + $request->setSession(new Session(new MockArraySessionStorage())); + + /** @var RequestStack $requestStack */ + $requestStack = $container->get('request_stack'); + $requestStack->push($request); + } + + /** + * Configures the current command. + */ + protected function configure() + { + $this + ->setName('admin:updatePassword') + ->setDescription('change administrator password') + ->setHelp('The admin:updatePassword command allows you to change the password for a given administrator') + ->addArgument( + 'login', + InputArgument::REQUIRED, + 'Login for administrator you want to change the password' + ) + ->addOption( + 'password', + null, + InputOption::VALUE_REQUIRED, + 'Desired password. If this option is omitted, a random password is generated and shown in this prompt after' + ) + ; + } + + protected function execute(InputInterface $input, OutputInterface $output) + { + $this->init(); + + $login = $input->getArgument('login'); + + if (null === $admin = AdminQuery::create()->filterByLogin($login)->findOne()) { + throw new \RuntimeException(sprintf('Admin with login %s does not exists', $login)); + } + + $password = $input->getOption('password') ?: Password::generateRandom(); + + $event = new AdministratorUpdatePasswordEvent($admin); + $event->setPassword($password); + + $this->getDispatcher()->dispatch(TheliaEvents::ADMINISTRATOR_UPDATEPASSWORD, $event); + + $output->writeln(array( + '', + sprintf('admin %s password updated', $login), + sprintf('new password is : %s', $password), + '' + )); + } +} diff --git a/core/lib/Thelia/Command/BaseModuleGenerate.php b/core/lib/Thelia/Command/BaseModuleGenerate.php new file mode 100644 index 00000000..b5420a93 --- /dev/null +++ b/core/lib/Thelia/Command/BaseModuleGenerate.php @@ -0,0 +1,112 @@ + + */ +abstract class BaseModuleGenerate extends ContainerAwareCommand +{ + protected $module; + protected $moduleDirectory; + + protected $reservedKeyWords = array( + 'thelia' + ); + + protected $neededDirectories = array( + 'Config', + 'Model', + 'Loop', + 'Command', + 'Controller', + 'EventListeners', + 'I18n', + 'templates', + 'Hook', + ); + + protected function verifyExistingModule() + { + if (file_exists($this->moduleDirectory)) { + throw new \RuntimeException( + sprintf( + "%s module already exists. Use --force option to force generation.", + $this->module + ) + ); + } + } + + protected function formatModuleName($name) + { + if (\in_array(strtolower($name), $this->reservedKeyWords)) { + throw new \RuntimeException(sprintf("%s module name is a reserved keyword", $name)); + } + + return ucfirst($name); + } + + protected function validModuleName($name) + { + if (!preg_match('#^[A-Z]([A-Za-z\d])+$#', $name)) { + throw new \RuntimeException( + sprintf("%s module name is not a valid name, it must be in CamelCase. (ex: MyModuleName)", $name) + ); + } + } + + protected function checkModuleSchema() + { + $moduleValidator = new ModuleValidator($this->moduleDirectory); + $moduleValidator->checkModulePropelSchema(); + } + + protected function generateGlobalSchemaForModule() + { + /** @var SchemaLocator $schemaLocator */ + $schemaLocator = $this->getContainer()->get('thelia.propel.schema.locator'); + /** @var PropelInitService $propelInitService */ + $propelInitService = $this->getContainer()->get('thelia.propel.init'); + + $schemaCombiner = new SchemaCombiner( + $schemaLocator->findForModules([$this->module]) + ); + + $fs = new Filesystem(); + $schemasDir = "{$propelInitService->getPropelCacheDir()}/schema-{$this->module}"; + $fs->mkdir($schemasDir); + + foreach ($schemaCombiner->getDatabases() as $database) { + file_put_contents( + "{$schemasDir}/{$database}.schema.xml", + $schemaCombiner->getCombinedDocument($database)->saveXML() + ); + } + + return $schemasDir; + } +} diff --git a/core/lib/Thelia/Command/CacheClear.php b/core/lib/Thelia/Command/CacheClear.php new file mode 100644 index 00000000..eb0f55c5 --- /dev/null +++ b/core/lib/Thelia/Command/CacheClear.php @@ -0,0 +1,112 @@ + + * + */ +class CacheClear extends ContainerAwareCommand +{ + protected function configure() + { + $this + ->setName("cache:clear") + ->setDescription("Invalidate all caches") + ->addOption( + "without-assets", + null, + InputOption::VALUE_NONE, + "do not clear the assets cache in the web space" + ) + ->addOption( + 'with-images', + null, + InputOption::VALUE_NONE, + 'clear images generated in `image_cache_dir_from_web_root` or web/cache/images directory' + ) + ->addOption( + 'with-documents', + null, + InputOption::VALUE_NONE, + 'clear documents generated in `document_cache_dir_from_web_root` or web/cache/documents directory' + ) + ; + } + + protected function execute(InputInterface $input, OutputInterface $output) + { + $cacheDir = $this->getContainer()->getParameter("kernel.cache_dir"); + + $this->clearCache($cacheDir, $output); + + if (!$input->getOption('without-assets')) { + $this->clearCache(THELIA_WEB_DIR . ConfigQuery::read('asset_dir_from_web_root', 'assets'), $output); + } + + if ($input->getOption('with-images')) { + $this->clearCache( + THELIA_WEB_DIR . ConfigQuery::read( + 'image_cache_dir_from_web_root', + 'cache' . DS . 'images' + ), + $output + ); + } + + if ($input->getOption('with-documents')) { + $this->clearCache( + THELIA_WEB_DIR . ConfigQuery::read( + 'document_cache_dir_from_web_root', + 'cache' . DS . 'documents' + ), + $output + ); + } + } + + protected function clearCache($dir, OutputInterface $output) + { + $output->writeln(sprintf("Clearing cache in %s directory", $dir)); + + try { + $cacheEvent = new CacheEvent($dir, false); + $this->getDispatcher()->dispatch(TheliaEvents::CACHE_CLEAR, $cacheEvent); + } catch (\UnexpectedValueException $e) { + // throws same exception code for does not exist and permission denied ... + if (!file_exists($dir)) { + $output->writeln(sprintf("%s cache dir already cleared", $dir)); + + return; + } + + throw $e; + } catch (IOException $e) { + $output->writeln(sprintf("Error during clearing of cache : %s", $e->getMessage())); + } + + $output->writeln(sprintf("%s cache directory cleared successfully", $dir)); + } +} diff --git a/core/lib/Thelia/Command/ClearImageCache.php b/core/lib/Thelia/Command/ClearImageCache.php new file mode 100644 index 00000000..5ef0ffba --- /dev/null +++ b/core/lib/Thelia/Command/ClearImageCache.php @@ -0,0 +1,53 @@ +setName("image-cache:clear") + ->setDescription("Empty part or whole web space image cache") + ->addArgument("subdir", InputArgument::OPTIONAL, "Clear only the specified subdirectory") + ; + } + + protected function execute(InputInterface $input, OutputInterface $output) + { + $request = new Request(); + + try { + $event = new ImageEvent($request); + + $subdir = $input->getArgument('subdir'); + + if (! \is_null($subdir)) { + $event->setCacheSubdirectory($subdir); + } + + $this->getDispatcher()->dispatch(TheliaEvents::IMAGE_CLEAR_CACHE, $event); + + $output->writeln(sprintf('%s image cache successfully cleared.', \is_null($subdir) ? 'Entire' : ucfirst($subdir))); + } catch (\Exception $ex) { + $output->writeln(sprintf("Failed to clear image cache: %s", $ex->getMessage())); + } + } +} diff --git a/core/lib/Thelia/Command/ConfigCommand.php b/core/lib/Thelia/Command/ConfigCommand.php new file mode 100644 index 00000000..3bf4a4c6 --- /dev/null +++ b/core/lib/Thelia/Command/ConfigCommand.php @@ -0,0 +1,225 @@ + + */ +class ConfigCommand extends ContainerAwareCommand +{ + protected function configure() + { + $this + ->setName("thelia:config") + ->setDescription("Manage configuration variables") + ->addArgument( + 'COMMAND', + InputArgument::REQUIRED, + 'Command : list, get, set, delete' + ) + ->addArgument( + 'name', + InputArgument::OPTIONAL, + 'The variable name' + ) + ->addArgument( + 'value', + InputArgument::OPTIONAL, + 'The variable value' + ) + ->addOption( + 'secured', + null, + InputOption::VALUE_NONE, + 'When setting a new variable tell variable is secured.' + ) + ->addOption( + 'visible', + null, + InputOption::VALUE_NONE, + 'When setting a new variable tell variable is visible.' + ) + ; + } + + protected function execute(InputInterface $input, OutputInterface $output) + { + $command = $input->getArgument("COMMAND"); + + switch ($command) { + case "list": + $this->listConfig($input, $output); + break; + + case "get": + $this->getConfig($input, $output); + break; + + case "set": + $this->setConfig($input, $output); + break; + + case "delete": + $this->deleteConfig($input, $output); + break; + + default: + $output->writeln( + "Unknown argument 'COMMAND' : list, get, set, delete" + ); + } + } + + private function listConfig(InputInterface $input, OutputInterface $output) + { + $output->writeln([ + "", + "Variables list", + "" + ]); + + $vars = ConfigQuery::create() + ->orderByName() + ->find() + ; + + $rows = []; + + /** @var Config $var */ + foreach ($vars as $var) { + $rows[] = [ + $var->getName(), + $var->getValue(), + $var->getSecured() !== 0 ? "yes" : "no", + $var->getHidden() !== 0 ? "yes" : "no" + ]; + } + + $table = new Table($output); + $table + ->setHeaders(['Name', 'Value', 'secured', 'hidden']) + ->setRows($rows) + ; + $table->render(); + } + + private function getConfig(InputInterface $input, OutputInterface $output) + { + $varName = $input->getArgument("name"); + + if (null === $varName) { + $output->writeln( + "Need argument 'name' for get command" + ); + return; + } + + $var = ConfigQuery::create()->findOneByName($varName); + + $out = []; + + if (null === $var) { + $out[] = sprintf( + "Unknown variable '%s'", + $varName + ); + } else { + $out = [ + sprintf('%12s: <%3$s>%s', "Name", $var->getName(), "info"), + sprintf('%12s: <%3$s>%s', "Value", $var->getValue(), "info"), + sprintf('%12s: <%3$s>%s', "Secured", $var->getSecured() ? "yes" : "no", "info"), + sprintf('%12s: <%3$s>%s', "Hidden", $var->getHidden() ? "yes" : "no", "info"), + sprintf('%12s: <%3$s>%s', "Title", $var->getTitle(), "info"), + sprintf('%12s: <%3$s>%s', "Description", $var->getDescription(), "info"), + ]; + } + + $output->writeln($out); + } + + + private function setConfig(InputInterface $input, OutputInterface $output) + { + $varName = $input->getArgument("name"); + $varValue = $input->getArgument("value"); + + if (null === $varName || null === $varValue) { + $output->writeln( + "Need argument 'name' and 'value' for set command" + ); + return; + } + + ConfigQuery::write( + $varName, + $varValue, + $input->getOption("secured"), + !$input->getOption("visible") + ); + + $output->writeln("Variable has been set"); + } + + private function deleteConfig(InputInterface $input, OutputInterface $output) + { + $varName = $input->getArgument("name"); + + if (null === $varName) { + $output->writeln( + "Need argument 'name' for get command" + ); + return; + } + + $var = ConfigQuery::create()->findOneByName($varName); + + if (null === $var) { + $output->writeln( + sprintf( + "Unknown variable '%s'", + $varName + ) + ); + } else { + $var->delete(); + $output->writeln( + sprintf( + "Variable '%s' has been deleted", + $varName + ) + ); + } + } +} diff --git a/core/lib/Thelia/Command/ContainerAwareCommand.php b/core/lib/Thelia/Command/ContainerAwareCommand.php new file mode 100644 index 00000000..d861a8ae --- /dev/null +++ b/core/lib/Thelia/Command/ContainerAwareCommand.php @@ -0,0 +1,133 @@ + + * @author Gilles Bourgeat + */ +class ContainerAwareCommand extends Command implements ContainerAwareInterface +{ + /** + * @var ContainerInterface + */ + private $container; + + /** + * @return ContainerInterface + */ + protected function getContainer() + { + if (null === $this->container) { + /** @var Application $application */ + $application = $this->getApplication(); + $this->container = $application->getKernel()->getContainer(); + } + + return $this->container; + } + + /** + * @see ContainerAwareInterface::setContainer() + * @param ContainerInterface $container + */ + public function setContainer(ContainerInterface $container = null) + { + $this->container = $container; + } + + /** + * @return \Symfony\Component\EventDispatcher\EventDispatcher + */ + public function getDispatcher() + { + $container = $this->getContainer(); + + // Initialize Thelia translator, if not already done. + try { + Translator::getInstance(); + } catch (\Exception $ex) { + $this->container->get('thelia.translator'); + } + + return $container->get('event_dispatcher'); + } + + /** + * For init an Request, if your command has need an Request + * @param Lang|null $lang + * @since 2.3 + */ + protected function initRequest(Lang $lang = null) + { + $container = $this->getContainer(); + + $request = Request::create($this->getBaseUrl($lang)); + $request->setSession(new Session(new MockArraySessionStorage())); + $container->set("request_stack", new RequestStack()); + $container->get('request_stack')->push($request); + + $requestContext = new RequestContext(); + $requestContext->fromRequest($request); + $url = $container->get('thelia.url.manager'); + $url->setRequestContext($requestContext); + $this->getContainer()->get('router.admin')->setContext($requestContext); + } + + /** + * @param Lang|null $lang + * @return string + * @since 2.3 + */ + protected function getBaseUrl(Lang $lang = null) + { + $baseUrl = ''; + + if ((int) ConfigQuery::read('one_domain_foreach_lang') === 1) { + if ($lang === null) { + $lang = LangQuery::create()->findOneByByDefault(true); + } + + $baseUrl = $lang->getUrl(); + } + + $baseUrl = trim($baseUrl); + + if (empty($baseUrl)) { + $baseUrl = ConfigQuery::read('url_site'); + } + + if (empty($baseUrl)) { + $baseUrl = 'http://localhost'; + } + + return $baseUrl; + } +} diff --git a/core/lib/Thelia/Command/CreateAdminUser.php b/core/lib/Thelia/Command/CreateAdminUser.php new file mode 100644 index 00000000..6c5e2eef --- /dev/null +++ b/core/lib/Thelia/Command/CreateAdminUser.php @@ -0,0 +1,205 @@ +setName("admin:create") + ->setDescription("Create a new administrator user") + ->setHelp("The admin:create command create a new administration user.") + ->addOption( + 'login_name', + null, + InputOption::VALUE_OPTIONAL, + 'Admin login name', + null + ) + ->addOption( + 'first_name', + null, + InputOption::VALUE_OPTIONAL, + 'User first name', + null + ) + ->addOption( + "last_name", + null, + InputOption::VALUE_OPTIONAL, + 'User last name', + null + ) + ->addOption( + "email", + null, + InputOption::VALUE_OPTIONAL, + 'Admin email address', + null + ) + ->addOption( + "locale", + null, + InputOption::VALUE_OPTIONAL, + 'Preferred locale (default: en_US)', + null + ) + ->addOption( + 'password', + null, + InputOption::VALUE_OPTIONAL, + 'Password', + null + ) + ; + } + + protected function execute(InputInterface $input, OutputInterface $output) + { + $output->writeln('Please enter the admin user information:'); + + /** @var Admin $admin */ + $admin = $this->getAdminInfo($input, $output); + + $admin->save(); + + $output->writeln(array( + "", + "User ".$admin->getLogin()." successfully created.", + "" + )); + } + + protected function enterData( + QuestionHelper $helper, + InputInterface $input, + OutputInterface $output, + $label, + $errorMessage, + $hidden = false + ) { + $question = new Question($this->decorateInfo($label)); + + if ($hidden) { + $question->setHidden(true); + $question->setHiddenFallback(false); + } + + $question->setValidator(function ($value) use (&$errorMessage) { + if (trim($value) == '') { + throw new \Exception($errorMessage); + } + + return $value; + }); + + return $helper->ask($input, $output, $question); + } + + /** + * Ask to user all needed information + * + * @param InputInterface $input + * @param OutputInterface $output + * @return array + */ + protected function getAdminInfo(InputInterface $input, OutputInterface $output) + { + /** @var QuestionHelper $helper */ + $helper = $this->getHelper('question'); + + $admin = new Admin(); + + $admin->setLogin($input->getOption("login_name") ?: $this->enterLogin($helper, $input, $output)); + $admin->setFirstname($input->getOption("first_name") ?: $this->enterData($helper, $input, $output, "User first name : ", "Please enter user first name.")); + $admin->setLastname($input->getOption("last_name") ?: $this->enterData($helper, $input, $output, "User last name : ", "Please enter user last name.")); + + $admin->setLocale($input->getOption("locale") ?: 'en_US'); + $admin->setEmail($input->getOption("email") ?: $this->enterEmail($helper, $input, $output)); + + do { + $password = $input->getOption("password") ?: $this->enterData($helper, $input, $output, "Password : ", "Please enter a password.", true); + $password_again = $input->getOption("password") ?: $this->enterData($helper, $input, $output, "Password (again): ", "Please enter the password again.", true); + + if (! empty($password) && $password == $password_again) { + $admin->setPassword($password); + + break; + } + + $output->writeln("Passwords are different, please try again."); + } while (true); + + $admin->setProfile(null); + + return $admin; + } + + protected function decorateInfo($text) + { + return sprintf("%s", $text); + } + + + protected function enterLogin(QuestionHelper $helper, InputInterface $input, OutputInterface $output) + { + $question = new Question($this->decorateInfo("Admin login name : ")); + + $question->setValidator(function ($answer) { + $answer = trim($answer); + if (empty($answer)) { + throw new \RuntimeException("Please enter a login name."); + } + + if (AdminQuery::create()->findOneByLogin($answer)) { + throw new \RuntimeException("An administrator with this login already exists."); + } + + return $answer; + }); + + return $helper->ask($input, $output, $question); + } + + protected function enterEmail(QuestionHelper $helper, InputInterface $input, OutputInterface $output) + { + $question = new Question($this->decorateInfo("Admin email or empty value : ")); + + $question->setValidator(function ($answer) { + $answer = trim($answer); + if (!empty($answer) && !filter_var($answer, FILTER_VALIDATE_EMAIL)) { + throw new \RuntimeException("Please enter an email or an empty value."); + } + + if (AdminQuery::create()->findOneByEmail($answer)) { + throw new \RuntimeException("An administrator with this email already exists."); + } + + return !empty($answer) ? $answer : uniqid('CHANGE_ME_'); + }); + + return $helper->ask($input, $output, $question); + } +} diff --git a/core/lib/Thelia/Command/DiffDatabaseCommand.php b/core/lib/Thelia/Command/DiffDatabaseCommand.php new file mode 100644 index 00000000..3f775254 --- /dev/null +++ b/core/lib/Thelia/Command/DiffDatabaseCommand.php @@ -0,0 +1,88 @@ +setName('thelia:dev:db:diff') + ->setDescription('Generate SQL to update the database(s) structure to the global Propel schema'); + } + + protected function execute(InputInterface $input, OutputInterface $output) + { + /** @var FormatterHelper $formatter */ + $formatter = $this->getHelper('formatter'); + + $output->writeln($formatter->formatBlock( + 'This is an experimental command that may be changed or removed at any time.', + 'bg=yellow;fg=black' + )); + + /** @var PropelInitService $propelInitService */ + $propelInitService = $this->getContainer()->get('thelia.propel.init'); + + // rebuild the global schema + $propelInitService->buildPropelGlobalSchema(); + + // call the Propel migration:diff command + $fs = new Filesystem(); + $fs->remove($propelInitService->getPropelMigrationDir()); + + $propelInitService->runCommand( + new PropelMigrationDiffCommand(), + [ + '--config-dir' => $propelInitService->getPropelConfigDir(), + '--schema-dir' => $propelInitService->getPropelSchemaDir(), + '--output-dir' => $propelInitService->getPropelMigrationDir(), + ] + ); + + // get the generated migration class + $finder = new Finder(); + $finder + ->files() + ->in($propelInitService->getPropelMigrationDir()); + + if ($finder->count() != 1) { + $output->writeln('Could not find the generated migration class.'); + return; + } + + // get the first (and only) found file + $i = $finder->getIterator(); + $i->rewind(); + /** @var SplFileInfo $migration */ + $migration = $i->current(); + + // instantiate the migration class + require $migration->getRealPath(); + $migrationClassName = pathinfo($migration->getFilename(), PATHINFO_FILENAME); + $migrationClass = new $migrationClassName(); + + // output the generated SQL + foreach ($migrationClass->getUpSQL() as $databaseName => $upSQL) { + $output->writeln("-- DATABASE {$databaseName}, UP"); + $output->writeln($upSQL); + } + foreach ($migrationClass->getDownSQL() as $databaseName => $downSQL) { + $output->writeln("-- DATABASE {$databaseName}, DOWN"); + $output->writeln($downSQL); + } + } +} diff --git a/core/lib/Thelia/Command/ExportCommand.php b/core/lib/Thelia/Command/ExportCommand.php new file mode 100644 index 00000000..2fc138b6 --- /dev/null +++ b/core/lib/Thelia/Command/ExportCommand.php @@ -0,0 +1,241 @@ + + */ +class ExportCommand extends ContainerAwareCommand +{ + protected function configure() + { + $this + ->setName('export') + ->setDescription('Export data') + ->setHelp('The export command run selected export') + ->addArgument( + 'ref', + InputArgument::OPTIONAL, + 'Export reference.' + ) + ->addArgument( + 'serializer', + InputArgument::OPTIONAL, + 'Serializer identifier.' + ) + ->addArgument( + 'archiver', + InputArgument::OPTIONAL, + 'Archiver identifier.' + ) + ->addOption( + 'locale', + null, + InputOption::VALUE_REQUIRED, + 'Locale for export', + 'en_US' + ) + ->addOption( + 'list-export', + null, + InputOption::VALUE_NONE, + 'List available exports and exit.' + ) + ->addOption( + 'list-serializer', + null, + InputOption::VALUE_NONE, + 'List available serializers and exit.' + ) + ->addOption( + 'list-archiver', + null, + InputOption::VALUE_NONE, + 'List available archivers and exit.' + ) + ; + } + + protected function execute(InputInterface $input, OutputInterface $output) + { + if ($input->getOption('list-export')) { + $this->listExport($output); + + return; + } + + if ($input->getOption('list-serializer')) { + $this->listSerializer($output); + + return; + } + + if ($input->getOption('list-archiver')) { + $this->listArchiver($output); + + return; + } + + $exportRef = $input->getArgument('ref'); + $serializer = $input->getArgument('serializer'); + if ($exportRef === null || $serializer === null) { + throw new \RuntimeException( + 'Not enough arguments.' . PHP_EOL . 'If no options are provided, ref and serializer arguments are required.' + ); + } + + /** @var \Thelia\Handler\ExportHandler $exportHandler */ + $exportHandler = $this->getContainer()->get('thelia.export.handler'); + + $export = $exportHandler->getExportByRef($exportRef); + if ($export === null) { + throw new \RuntimeException( + $exportRef . ' export doesn\'t exist.' + ); + } + + $serializerManager = $this->getContainer()->get(RegisterSerializerPass::MANAGER_SERVICE_ID); + $serializer = $serializerManager->get($serializer); + + $archiver = null; + if ($input->getArgument('archiver')) { + /** @var \Thelia\Core\Archiver\ArchiverManager $archiverManager */ + $archiverManager = $this->getContainer()->get(RegisterArchiverPass::MANAGER_SERVICE_ID); + $archiver = $archiverManager->get($input->getArgument('archiver')); + } + + $exportEvent = $exportHandler->export( + $export, + $serializer, + $archiver, + (new LangQuery)->findOneByLocale($input->getOption('locale')) + ); + + $formattedLine = $this->getHelper('formatter')->formatBlock( + 'Export finish', + 'fg=black;bg=green', + true + ); + $output->writeln($formattedLine); + $output->writeln('Export available at path:'); + $output->writeln('' . $exportEvent->getFilePath() . ''); + } + + /** + * Output available exports + * + * @param \Symfony\Component\Console\Output\OutputInterface $output An output interface + */ + protected function listExport(OutputInterface $output) + { + $table = new Table($output); + + foreach ((new ExportQuery)->find() as $export) { + $table->addRow([ + $export->getRef(), + $export->getTitle(), + $export->getDescription() + ]); + } + + $table + ->setHeaders([ + 'Reference', + 'Title', + 'Description' + ]) + ->render() + ; + } + + /** + * Output available serializers + * + * @param \Symfony\Component\Console\Output\OutputInterface $output An output interface + */ + protected function listSerializer(OutputInterface $output) + { + $table = new Table($output); + + /** @var SerializerManager $serializerManager */ + $serializerManager = $this->getContainer()->get(RegisterSerializerPass::MANAGER_SERVICE_ID); + + /** @var SerializerInterface $serializer */ + foreach ($serializerManager->getSerializers() as $serializer) { + $table->addRow([ + $serializer->getId(), + $serializer->getName(), + $serializer->getExtension(), + $serializer->getMimeType() + ]); + } + + $table + ->setHeaders([ + 'Id', + 'Name', + 'Extension', + 'MIME type' + ]) + ->render() + ; + } + + /** + * Output available archivers + * + * @param \Symfony\Component\Console\Output\OutputInterface $output An output interface + */ + protected function listArchiver(OutputInterface $output) + { + $table = new Table($output); + + /** @var ArchiverManager $archiverManager */ + $archiverManager = $this->getContainer()->get(RegisterArchiverPass::MANAGER_SERVICE_ID); + + /** @var ArchiverInterface $archiver */ + foreach ($archiverManager->getArchivers(true) as $archiver) { + $table->addRow([ + $archiver->getId(), + $archiver->getName(), + $archiver->getExtension(), + $archiver->getMimeType() + ]); + } + + $table + ->setHeaders([ + 'Id', + 'Name', + 'Extension', + 'MIME type' + ]) + ->render() + ; + } +} diff --git a/core/lib/Thelia/Command/GenerateResources.php b/core/lib/Thelia/Command/GenerateResources.php new file mode 100644 index 00000000..ecee1127 --- /dev/null +++ b/core/lib/Thelia/Command/GenerateResources.php @@ -0,0 +1,101 @@ +setName("thelia:generate-resources") + ->setDescription("Outputs admin resources") + ->setHelp("The thelia:generate-resources outputs admin resources.") + ->addOption( + 'output', + null, + InputOption::VALUE_OPTIONAL, + 'Output format amid (string, sql, sql-i18n)', + null + ) + ; + } + + protected function execute(InputInterface $input, OutputInterface $output) + { + $class = new \ReflectionClass('Thelia\Core\Security\Resource\AdminResources'); + + $constants = $class->getConstants(); + + if (\count($constants) == 0) { + throw new \RuntimeException('No resources found'); + } + + switch ($input->getOption("output")) { + case 'sql': + $output->writeln( + 'INSERT INTO ' . ResourceTableMap::TABLE_NAME . ' (`id`, `code`, `created_at`, `updated_at`) VALUES ' + ); + $compteur = 0; + foreach ($constants as $constant => $value) { + if ($constant == AdminResources::SUPERADMINISTRATOR) { + continue; + } + $compteur++; + $output->writeln( + "($compteur, '$value', NOW(), NOW())" . ($constant === key(\array_slice($constants, -1, 1, true)) ? ';' : ',') + ); + } + break; + case 'sql-i18n': + $output->writeln( + 'INSERT INTO ' . ResourceI18nTableMap::TABLE_NAME . ' (`id`, `locale`, `title`) VALUES ' + ); + $compteur = 0; + foreach ($constants as $constant => $value) { + if ($constant == AdminResources::SUPERADMINISTRATOR) { + continue; + } + + $compteur++; + + $title = ucwords(str_replace('.', ' / ', str_replace('admin.', '', $value))); + + $output->writeln( + "($compteur, 'en_US', '$title')," + ); + $output->writeln( + "($compteur, 'fr_FR', '$title')" . ($constant === key(\array_slice($constants, -1, 1, true)) ? ';' : ',') + ); + } + break; + default: + foreach ($constants as $constant => $value) { + if ($constant == AdminResources::SUPERADMINISTRATOR) { + continue; + } + $output->writeln('[' . $constant . "] => " . $value); + } + break; + } + } +} diff --git a/core/lib/Thelia/Command/GenerateSQLCommand.php b/core/lib/Thelia/Command/GenerateSQLCommand.php new file mode 100644 index 00000000..973920da --- /dev/null +++ b/core/lib/Thelia/Command/GenerateSQLCommand.php @@ -0,0 +1,221 @@ + + */ +class GenerateSQLCommand extends ContainerAwareCommand +{ + /** @var Translator $translator */ + protected $translator = null; + + /** @var SmartyParser $parser */ + protected $parser = null; + + /** @var \PDO */ + protected $con; + + /** @var array */ + protected $locales; + + protected function configure() + { + $this + ->setName("generate:sql") + ->setDescription("Generate SQL files (insert.sql, update*.sql)") + ->addOption( + "locales", + null, + InputOption::VALUE_OPTIONAL, + "generate only for only specific locales (separated by a ,) : fr_FR,es_ES or es_ES" + ); + } + + protected function execute(InputInterface $input, OutputInterface $output) + { + $this->init($input); + + // Main insert.sql file + $content = file_get_contents(THELIA_SETUP_DIRECTORY . 'insert.sql.tpl'); + $version = Version::parse(); + $content = $this->parser->renderString($content, $version, false); + + if (false === file_put_contents(THELIA_SETUP_DIRECTORY . 'insert.sql', $content)) { + $output->writeln("Can't write file " . THELIA_SETUP_DIRECTORY . 'insert.sql'); + } else { + $output->writeln("File " . THELIA_SETUP_DIRECTORY . 'insert.sql generated successfully.'); + } + + // sql update files + $finder = Finder::create() + ->name('*.tpl') + ->depth(0) + ->in(THELIA_SETUP_DIRECTORY . 'update' . DS . 'tpl'); + + /** @var \SplFileInfo $file */ + foreach ($finder as $file) { + $content = file_get_contents($file->getRealPath()); + $content = $this->parser->renderString($content, [], false); + + $destination = THELIA_SETUP_DIRECTORY . 'update' . DS . 'sql' . DS . $file->getBasename('.tpl'); + + if (false === file_put_contents($destination, $content)) { + $output->writeln("Can't write file " . $destination); + } else { + $output->writeln("File " . $destination . ' generated successfully.'); + } + } + } + + protected function init(InputInterface $input) + { + $this->initRequest(); + + $container = $this->getContainer(); + + $this->translator = $container->get('thelia.translator'); + $this->parser = $container->get('thelia.parser'); + + $this->con = Propel::getConnection(ProductTableMap::DATABASE_NAME); + + $this->initLocales($input); + + $this->initParser(); + } + + /** + * @param InputInterface $input + * @return array + */ + protected function initLocales(InputInterface $input) + { + $this->locales = []; + $availableLocales = []; + + $finder = Finder::create() + ->name('*.php') + ->depth(0) + ->sortByName() + ->in(THELIA_SETUP_DIRECTORY . 'I18n'); + + // limit to only some locale(s) + $localesToKeep = $input->getOption("locales"); + if (!empty($localesToKeep)) { + $localesToKeep = explode(',', $localesToKeep); + } else { + $localesToKeep = null; + } + + /** @var \SplFileInfo $file */ + foreach ($finder as $file) { + $locale = $file->getBasename('.php'); + $availableLocales[] = $locale; + + if (empty($localesToKeep) || \in_array($locale, $localesToKeep)) { + $this->locales[] = $locale; + $this->translator->addResource( + 'php', + $file->getRealPath(), + $locale, + 'install' + ); + } + } + + if (empty($this->locales)) { + throw new \RuntimeException( + sprintf( + "You should at least generate sql for one locale. Available locales : %s", + implode(', ', $availableLocales) + ) + ); + } + } + + /** + * Initialize the smarty parser. + * + * The intl function is replaced, and locales are assigned. + * + * @throws \SmartyException + */ + protected function initParser() + { + $this->parser->unregisterPlugin('function', 'intl'); + $this->parser->registerPlugin('function', 'intl', [$this, 'translate']); + $this->parser->assign("locales", $this->locales); + } + + /** + * Smarty function that replace the classic `intl` function. + * + * The attributes of the function are: + * - `l`: the key + * - `locale`: the locale. eg.: fr_FR + * - `in_string`: set to 1 not add simple quote around the string. (default = 0) + * - `use_default`: set to 1 to use the `l` string as a fallback. (default = 0) + * + * @param $params + * @param $smarty + * @return string + */ + public function translate($params, $smarty) + { + $translation = ''; + + if (empty($params["l"])) { + throw new RuntimeException('Translation Error. Key is empty.'); + } elseif (empty($params["locale"])) { + throw new RuntimeException('Translation Error. Locale is empty.'); + } else { + $inString = (0 !== \intval($params["in_string"])); + $useDefault = (0 !== \intval($params["use_default"])); + + $translation = $this->translator->trans( + $params["l"], + [], + 'install', + $params["locale"], + $useDefault + ); + + if (empty($translation)) { + $translation = ($inString) ? '' : "NULL"; + } else { + $translation = $this->con->quote($translation); + // remove quote + if ($inString) { + $translation = substr($translation, 1, -1); + } + } + } + + return $translation; + } +} diff --git a/core/lib/Thelia/Command/HookCleanCommand.php b/core/lib/Thelia/Command/HookCleanCommand.php new file mode 100644 index 00000000..85fc52d7 --- /dev/null +++ b/core/lib/Thelia/Command/HookCleanCommand.php @@ -0,0 +1,157 @@ + + * + */ +class HookCleanCommand extends ContainerAwareCommand +{ + protected function configure() + { + $this + ->setName("hook:clean") + ->setDescription("Clean hooks. It will delete all hooks, then recreate it.") + ->addOption( + "assume-yes", + 'y', + InputOption::VALUE_NONE, + 'Assume to answer yes to all questions' + ) + ->addArgument( + "module", + InputArgument::OPTIONAL, + "The module code to clean up" + ); + } + + protected function execute(InputInterface $input, OutputInterface $output) + { + try { + $module = $this->getModule($input); + + if (!$this->askConfirmation($input, $output)) { + return; + } + + $this->deleteHooks($module); + + $output->writeln("Hooks have been successfully deleted"); + + $this->clearCache($output); + } catch (\Exception $ex) { + $output->writeln(sprintf("%s", $ex->getMessage())); + } + } + + private function getModule(InputInterface $input) + { + $module = null; + $moduleCode = $input->getArgument("module"); + + if (!empty($moduleCode)) { + if (null === $module = ModuleQuery::create()->findOneByCode($moduleCode)) { + throw new \RuntimeException(sprintf("Module %s does not exist.", $moduleCode)); + } + } + + return $module; + } + + 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 = "Would you like to delete all hooks "; + $questionText .= (empty($moduleCode)) + ? "of all modules" + : "of module " . $moduleCode; + $questionText .= " ? (yes, or no) "; + + $question = new ConfirmationQuestion($questionText, false); + + if (!$helper->ask($input, $output, $question)) { + $output->writeln("No hooks deleted"); + return false; + } + } + + return true; + } + + /** + * Delete module hooks + * + * @param Module|null $module if specified it will only delete hooks related to this module. + * @throws \Exception + * @throws \Propel\Runtime\Exception\PropelException + */ + protected function deleteHooks($module) + { + $query = ModuleHookQuery::create(); + if (null !== $module) { + $query + ->filterByModule($module) + ->delete(); + } else { + $query->deleteAll(); + } + + $query = IgnoredModuleHookQuery::create(); + if (null !== $module) { + $query + ->filterByModule($module) + ->delete(); + } else { + $query->deleteAll(); + } + } + + /** + * @param OutputInterface $output + * @throws \Exception + */ + protected function clearCache(OutputInterface $output) + { + try { + $cacheDir = $this->getContainer()->getParameter("kernel.cache_dir"); + $cacheEvent = new CacheEvent($cacheDir); + $this->getDispatcher()->dispatch(TheliaEvents::CACHE_CLEAR, $cacheEvent); + } catch (\Exception $ex) { + throw new \Exception(sprintf("Error during clearing of cache : %s", $ex->getMessage())); + } + } +} diff --git a/core/lib/Thelia/Command/ImportCommand.php b/core/lib/Thelia/Command/ImportCommand.php new file mode 100644 index 00000000..37c2ab90 --- /dev/null +++ b/core/lib/Thelia/Command/ImportCommand.php @@ -0,0 +1,141 @@ + + */ +class ImportCommand extends ContainerAwareCommand +{ + protected function configure() + { + $this + ->setName('import') + ->setDescription('Import data') + ->setHelp('The import command run selected import') + ->addArgument( + 'ref', + InputArgument::OPTIONAL, + 'Import reference.' + ) + ->addArgument( + 'filePath', + InputArgument::OPTIONAL, + 'File path to import' + ) + ->addOption( + 'locale', + null, + InputOption::VALUE_REQUIRED, + 'Locale for export', + 'en_US' + ) + ->addOption( + 'list', + null, + InputOption::VALUE_NONE, + 'List available imports and exit.' + ) + ; + } + + protected function execute(InputInterface $input, OutputInterface $output) + { + if ($input->getOption('list')) { + $this->listImport($output); + + return; + } + + $importRef = $input->getArgument('ref'); + $path = $input->getArgument('filePath'); + if ($importRef === null || $path === null) { + throw new \RuntimeException( + 'Not enough arguments.' . PHP_EOL . 'If no options are provided, ref and filePath arguments are required.' + ); + } + + /** @var \Thelia\Handler\ImportHandler $importHandler */ + $importHandler = $this->getContainer()->get('thelia.import.handler'); + + $import = $importHandler->getImportByRef($importRef); + if ($import === null) { + throw new \RuntimeException( + $importRef . ' import doesn\'t exist.' + ); + } + + $importEvent = $importHandler->import( + $import, + new File($input->getArgument('filePath')), + (new LangQuery)->findOneByLocale($input->getOption('locale')) + ); + + $formattedLine = $this->getHelper('formatter')->formatBlock( + 'Successfully import ' . $importEvent->getImport()->getImportedRows() . ' row(s)', + 'fg=black;bg=green', + true + ); + $output->writeln($formattedLine); + + if (\count($importEvent->getErrors()) > 0) { + $formattedLine = $this->getHelper('formatter')->formatBlock( + 'With error', + 'fg=black;bg=yellow', + true + ); + $output->writeln($formattedLine); + + foreach ($importEvent->getErrors() as $error) { + $output->writeln('' . $error . ''); + } + } + } + + /** + * Output available imports + * + * @param \Symfony\Component\Console\Output\OutputInterface $output An output interface + */ + protected function listImport(OutputInterface $output) + { + $table = new Table($output); + + foreach ((new ImportQuery)->find() as $import) { + $table->addRow([ + $import->getRef(), + $import->getTitle(), + $import->getDescription() + ]); + } + + $table + ->setHeaders([ + 'Reference', + 'Title', + 'Description' + ]) + ->render() + ; + } +} diff --git a/core/lib/Thelia/Command/Install.php b/core/lib/Thelia/Command/Install.php new file mode 100644 index 00000000..2c2b8abe --- /dev/null +++ b/core/lib/Thelia/Command/Install.php @@ -0,0 +1,345 @@ + + */ +class Install extends ContainerAwareCommand +{ + /** + * Configure the command + */ + protected function configure() + { + $this + ->setName("thelia:install") + ->setDescription("Install thelia using cli tools. For now Thelia only use mysql database") + ->setHelp("The thelia:install command install Thelia database and create config file needed.") + ->addOption( + "db_host", + null, + InputOption::VALUE_OPTIONAL, + "host for your database", + "localhost" + ) + ->addOption( + "db_username", + null, + InputOption::VALUE_OPTIONAL, + "username for your database" + ) + ->addOption( + "db_password", + null, + InputOption::VALUE_OPTIONAL, + "password for your database" + ) + ->addOption( + "db_name", + null, + InputOption::VALUE_OPTIONAL, + "database name" + ) + ->addOption( + "db_port", + null, + InputOption::VALUE_OPTIONAL, + "database port", + "3306" + ) + ; + } + + protected function execute(InputInterface $input, OutputInterface $output) + { + $output->writeln(array( + '', + 'Welcome to Thelia install process', + 'You need information about your database configuration (host, username, password, database name, etc)', + '', + 'Caution : You are installing Thelia in cli mode, we verify some information, but this information are only available for the cli php sapi', + 'This informations can be different in your apache or cgi php.ini files', + '' + )); + + $this->checkPermission($output); + + $connectionInfo = array( + "host" => $input->getOption("db_host"), + "dbName" => $input->getOption("db_name"), + "username" => $input->getOption("db_username"), + "password" => $input->getOption("db_password"), + "port" => $input->getOption("db_port") + ); + + while (false === $connection = $this->tryConnection($connectionInfo, $output)) { + $connectionInfo = $this->getConnectionInfo($input, $output); + } + + $database = new Database($connection); + + $database->createDatabase($connectionInfo["dbName"]); + + $output->writeln(array( + "", + "Creating Thelia database, please wait", + "" + )); + $database->insertSql($connectionInfo["dbName"]); + $this->manageSecret($database); + + $output->writeln(array( + "", + "Database created without errors", + "Creating file configuration, please wait", + "" + )); + + $this->createConfigFile($connectionInfo); + + $output->writeln(array( + "", + "Config file created with success. Your thelia is installed", + "" + )); + } + + protected function manageSecret(Database $database) + { + $secret = TokenProvider::generateToken(); + $sql = "UPDATE `config` SET `value`=? WHERE `name`='form.secret'"; + $database->execute($sql, [$secret]); + } + + /** + * Test if needed directories have write permission + * + * @param \Symfony\Component\Console\Output\OutputInterface $output + */ + protected function checkPermission(OutputInterface $output) + { + $output->writeln(array( + "Checking some permissions" + )); + + /** @var Translator $translator */ + $translator = $this->getContainer()->get('thelia.translator'); + + $permissions = new CheckPermission(false, $translator); + $isValid = $permissions->exec(); + + foreach ($permissions->getValidationMessages() as $item => $data) { + if ($data['status']) { + $output->writeln( + array( + sprintf( + "%s ... %s", + $data['text'], + "Ok" + ) + ) + ); + } else { + $output->writeln(array( + sprintf( + "%s %s", + $data['text'], + sprintf("%s", $data["hint"]) + ) + )); + } + } + + if (false === $isValid) { + throw new \RuntimeException('Please put correct permissions and reload install process'); + } + } + + /** + * rename database config file and complete it + * + * @param array $connectionInfo + */ + protected function createConfigFile($connectionInfo) + { + $fs = new Filesystem(); + + $sampleConfigFile = THELIA_CONF_DIR . "database.yml.sample"; + $configFile = THELIA_CONF_DIR . "database.yml"; + + $fs->copy($sampleConfigFile, $configFile, true); + + $configContent = file_get_contents($configFile); + + $configContent = str_replace("%DRIVER%", "mysql", $configContent); + $configContent = str_replace("%USERNAME%", $connectionInfo["username"], $configContent); + $configContent = str_replace("%PASSWORD%", $connectionInfo["password"], $configContent); + $configContent = str_replace( + "%DSN%", + sprintf("mysql:host=%s;dbname=%s;port=%s", $connectionInfo["host"], $connectionInfo["dbName"], $connectionInfo['port']), + $configContent + ); + + file_put_contents($configFile, $configContent); + + $fs->remove($this->getContainer()->getParameter("kernel.cache_dir")); + } + + /** + * test database access + * + * @param $connectionInfo + * @param OutputInterface $output + * @return bool|\PDO + */ + protected function tryConnection($connectionInfo, OutputInterface $output) + { + if (\is_null($connectionInfo["dbName"])) { + return false; + } + + $dsn = "mysql:host=%s;port=%s"; + + try { + $connection = new \PDO( + sprintf($dsn, $connectionInfo["host"], $connectionInfo["port"]), + $connectionInfo["username"], + $connectionInfo["password"] + ); + $connection->query('SET NAMES \'UTF8\''); + } catch (\PDOException $e) { + $output->writeln(array( + "Wrong connection information" + )); + + return false; + } + + return $connection; + } + + /** + * Ask to user all needed information + * + * @param InputInterface $input + * @param OutputInterface $output + * @return array + */ + protected function getConnectionInfo(InputInterface $input, OutputInterface $output) + { + /** @var QuestionHelper $helper */ + $helper = $this->getHelper('question'); + + $connectionInfo = array(); + + $connectionInfo['host'] = $this->enterData( + $helper, + $input, + $output, + "Database host [default: localhost] : ", + "You must specify a database host", + false, + "localhost" + ); + + $connectionInfo['port'] = $this->enterData( + $helper, + $input, + $output, + "Database port [default: 3306] : ", + "You must specify a database port", + false, + "3306" + ); + + $connectionInfo['dbName'] = $this->enterData( + $helper, + $input, + $output, + "Database name (if database does not exist, Thelia will try to create it) : ", + "You must specify a database name" + ); + + $connectionInfo['username'] = $this->enterData( + $helper, + $input, + $output, + "Database username : ", + "You must specify a database username" + ); + + $connectionInfo['password'] = $this->enterData( + $helper, + $input, + $output, + "Database password : ", + "You must specify a database username", + true, + null, + true + ); + + return $connectionInfo; + } + + protected function enterData( + QuestionHelper $helper, + InputInterface $input, + OutputInterface $output, + $label, + $errorMessage, + $hidden = false, + $defaultValue = null, + $beEmpty = false + ) { + $question = new Question($label, $defaultValue); + + if ($hidden) { + $question->setHidden(true); + $question->setHiddenFallback(false); + } + + $question->setValidator(function ($value) use (&$errorMessage, &$beEmpty) { + if (trim($value) == '') { + if (\is_null($value) && !$beEmpty) { + throw new \Exception($errorMessage); + } + } + + return $value; + }); + + return $helper->ask($input, $output, $question); + } + + protected function decorateInfo($text) + { + return sprintf("%s", $text); + } +} diff --git a/core/lib/Thelia/Command/ModuleActivateCommand.php b/core/lib/Thelia/Command/ModuleActivateCommand.php new file mode 100644 index 00000000..abaa5dd6 --- /dev/null +++ b/core/lib/Thelia/Command/ModuleActivateCommand.php @@ -0,0 +1,93 @@ + + * + */ +class ModuleActivateCommand extends BaseModuleGenerate +{ + protected function configure() + { + $this + ->setName("module:activate") + ->setDescription("Activates a module") + ->addOption( + "with-dependencies", + null, + InputOption::VALUE_NONE, + 'activate module recursively' + ) + ->addArgument( + "module", + InputArgument::REQUIRED, + "module to activate" + ); + } + + protected function execute(InputInterface $input, OutputInterface $output) + { + $moduleCode = $this->formatModuleName($input->getArgument("module")); + + $module = ModuleQuery::create()->findOneByCode($moduleCode); + + if (null === $module) { + throw new \RuntimeException(sprintf("module %s not found", $moduleCode)); + } + + if ($module->getActivate() == BaseModule::IS_ACTIVATED) { + throw new \RuntimeException(sprintf("module %s is already actived", $moduleCode)); + } + + + try { + $event = new ModuleToggleActivationEvent($module->getId()); + if ($input->getOption("with-dependencies")) { + $event->setRecursive(true); + } + + $this->getDispatcher()->dispatch(TheliaEvents::MODULE_TOGGLE_ACTIVATION, $event); + } catch (\Exception $e) { + throw new \RuntimeException( + sprintf( + "Activation fail with Exception : [%d] %s", + $e->getCode(), + $e->getMessage() + ) + ); + } + + //impossible to change output class in CommandTester... + if (method_exists($output, "renderBlock")) { + $output->renderBlock(array( + '', + sprintf("Activation succeed for module %s", $moduleCode), + '' + ), "bg=green;fg=black"); + } + } +} diff --git a/core/lib/Thelia/Command/ModuleDeactivateCommand.php b/core/lib/Thelia/Command/ModuleDeactivateCommand.php new file mode 100644 index 00000000..a79d4580 --- /dev/null +++ b/core/lib/Thelia/Command/ModuleDeactivateCommand.php @@ -0,0 +1,134 @@ + + * + */ +class ModuleDeactivateCommand extends BaseModuleGenerate +{ + protected function configure() + { + $this + ->setName("module:deactivate") + ->setDescription("Deactivate a module") + ->addOption( + "with-dependencies", + null, + InputOption::VALUE_NONE, + 'activate module recursively' + ) + ->addArgument( + "module", + InputArgument::REQUIRED, + "module to deactivate" + ) + ->addOption( + "assume-yes", + 'y', + InputOption::VALUE_NONE, + 'Assume to deactivate a mandatory module' + ) + ; + } + + protected function execute(InputInterface $input, OutputInterface $output) + { + $moduleCode = $this->formatModuleName($input->getArgument("module")); + + $module = ModuleQuery::create()->findOneByCode($moduleCode); + + if (null === $module) { + throw new \RuntimeException(sprintf("module %s not found", $moduleCode)); + } + + if ($module->getActivate() == BaseModule::IS_NOT_ACTIVATED) { + throw new \RuntimeException(sprintf("module %s is already deactivated", $moduleCode)); + } + + + try { + $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")) { + $event->setRecursive(true); + } + $this->getDispatcher()->dispatch(TheliaEvents::MODULE_TOGGLE_ACTIVATION, $event); + } catch (\Exception $e) { + throw new \RuntimeException(sprintf("Deactivation fail with Exception : [%d] %s", $e->getCode(), $e->getMessage())); + } + + //impossible to change output class in CommandTester... + if (method_exists($output, "renderBlock")) { + $output->renderBlock(array( + '', + sprintf("Deactivation succeed for module %s", $moduleCode), + '' + ), "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; + } +} diff --git a/core/lib/Thelia/Command/ModuleGenerateCommand.php b/core/lib/Thelia/Command/ModuleGenerateCommand.php new file mode 100644 index 00000000..bfe5d716 --- /dev/null +++ b/core/lib/Thelia/Command/ModuleGenerateCommand.php @@ -0,0 +1,235 @@ + + */ +class ModuleGenerateCommand extends BaseModuleGenerate +{ + protected function configure() + { + $this + ->setName("module:generate") + ->setDescription("generate all needed files for creating a new Module") + ->addArgument( + "name", + InputArgument::REQUIRED, + "name wanted for your Module" + ) + ->addOption( + 'force', + null, + InputOption::VALUE_NONE, + 'If defined, it will update the module with missing directories and files (no overrides).' + ) + ; + } + + protected function execute(InputInterface $input, OutputInterface $output) + { + $this->module = $this->formatModuleName($input->getArgument("name")); + $this->moduleDirectory = THELIA_MODULE_DIR . $this->module; + + $this->validModuleName($this->module); + + try { + $this->verifyExistingModule(); + } catch (\RuntimeException $ex) { + if (false === $input->getOption('force')) { + throw $ex; + } + } + + $this->createDirectories(); + $this->createFiles(); + if (method_exists($output, "renderBlock")) { + // impossible to change output class in CommandTester... + $output->renderBlock(array( + '', + sprintf("module %s create with success", $this->module), + "You can now configure your module and complete module.xml file", + '' + ), "bg=green;fg=black"); + } + } + + private function createDirectories() + { + $fs = new Filesystem(); + + if (!$fs->exists($this->moduleDirectory)) { + $fs->mkdir($this->moduleDirectory); + } + + foreach ($this->neededDirectories as $directory) { + if (!$fs->exists($this->moduleDirectory . DIRECTORY_SEPARATOR . $directory)) { + $fs->mkdir($this->moduleDirectory . DIRECTORY_SEPARATOR . $directory); + } + } + } + + protected function copyConfigFile($filename, $skeletonDir, Filesystem $fs) + { + $filename = $this->moduleDirectory . DIRECTORY_SEPARATOR . "Config" . DIRECTORY_SEPARATOR . $filename; + if (!$fs->exists($filename)) { + $configContent = file_get_contents($skeletonDir . "config.xml"); + + $configContent = str_replace("%%CLASSNAME%%", $this->module, $configContent); + $configContent = str_replace("%%NAMESPACE%%", $this->module, $configContent); + $configContent = str_replace("%%NAMESPACE_LOWER%%", strtolower($this->module), $configContent); + + file_put_contents( + $filename, + $configContent + ); + } + } + + private function createFiles() + { + $fs = new Filesystem(); + + try { + $skeletonDir = str_replace("/", DIRECTORY_SEPARATOR, __DIR__ . "/Skeleton/Module/"); + + // config.xml file + $this->copyConfigFile("config.xml", $skeletonDir, $fs); + $this->copyConfigFile("config_prod.xml", $skeletonDir, $fs); + $this->copyConfigFile("config_dev.xml", $skeletonDir, $fs); + $this->copyConfigFile("config_test.xml", $skeletonDir, $fs); + + // Readme.md file + $filename = $this->moduleDirectory . DIRECTORY_SEPARATOR . "Readme.md"; + if (!$fs->exists($filename)) { + $readmeContent = file_get_contents($skeletonDir . "Readme.md"); + + // generate title for readme + preg_match_all('!([A-Z][A-Z0-9]*(?=$|[A-Z][a-z0-9])|[A-Za-z][a-z0-9]+)!', $this->module, $readmeTitle); + $composerFinalName = strtolower(implode("-", $readmeTitle[0])); + + $readmeContent = str_replace("%%MODULENAME%%", $this->module, $readmeContent); + $readmeContent = str_replace("%%MODULENAMETITLE%%", implode(" ", $readmeTitle[0]), $readmeContent); + $readmeContent = str_replace("%%COMPOSERNAME%%", $composerFinalName, $readmeContent); + + file_put_contents($filename, $readmeContent); + } + + // composer.json file + $filename = $this->moduleDirectory . DIRECTORY_SEPARATOR . "composer.json"; + if (!$fs->exists($filename)) { + $composerContent = file_get_contents($skeletonDir . "composer.json"); + + // generate composer module name + preg_match_all('!([A-Z][A-Z0-9]*(?=$|[A-Z][a-z0-9])|[A-Za-z][a-z0-9]+)!', $this->module, $composerName); + + $composerContent = str_replace("%%MODULENAME%%", $this->module, $composerContent); + $composerContent = str_replace("%%COMPOSERNAME%%", strtolower(implode("-", $composerName[0])), $composerContent); + + file_put_contents($filename, $composerContent); + } + + // module.xml file + $filename = $this->moduleDirectory . DIRECTORY_SEPARATOR . "Config". DIRECTORY_SEPARATOR . "module.xml"; + if (!$fs->exists($filename)) { + $moduleContent = file_get_contents($skeletonDir . "module.xml"); + + $moduleContent = str_replace("%%CLASSNAME%%", $this->module, $moduleContent); + $moduleContent = str_replace("%%NAMESPACE%%", $this->module, $moduleContent); + + file_put_contents($filename, $moduleContent); + } + + // PHP Class template + $filename = $this->moduleDirectory . DIRECTORY_SEPARATOR . $this->module . ".php"; + if (!$fs->exists($filename)) { + $classContent = file_get_contents($skeletonDir . "Class.php.template"); + + $classContent = str_replace("%%CLASSNAME%%", $this->module, $classContent); + $classContent = str_replace("%%NAMESPACE%%", $this->module, $classContent); + $classContent = str_replace("%%DOMAINNAME%%", strtolower($this->module), $classContent); + + file_put_contents($filename, $classContent); + } + + // schema.xml file + $filename = $this->moduleDirectory . DIRECTORY_SEPARATOR . "Config" . DIRECTORY_SEPARATOR . "schema.xml"; + if (!$fs->exists($filename)) { + $schemaContent = file_get_contents($skeletonDir . "schema.xml"); + + $fs = new Filesystem(); + + // for backward compatibility + if ($fs->exists(THELIA_VENDOR . 'thelia/propel/resources/xsd')) { + $endPath = THELIA_VENDOR . 'thelia/propel/resources/xsd'; + } else { + $endPath = THELIA_VENDOR . 'propel/propel/resources/xsd'; + } + + $schemaContent = str_replace("%%NAMESPACE%%", $this->module, $schemaContent); + $schemaContent = str_replace( + '%%XSD_LOCATION%%', + $fs->makePathRelative( + $endPath, + $this->moduleDirectory + ) . 'database.xsd', + $schemaContent + ); + + file_put_contents($filename, $schemaContent); + } + + // routing.xml file + $filename = $this->moduleDirectory . DIRECTORY_SEPARATOR . "Config" . DIRECTORY_SEPARATOR . "routing.xml"; + if (!$fs->exists($filename)) { + $routingContent = file_get_contents($skeletonDir . "routing.xml"); + + $routingContent = str_replace("%%NAMESPACE%%", $this->module, $routingContent); + $routingContent = str_replace("%%CLASSNAME_LOWER%%", strtolower($this->module), $routingContent); + + file_put_contents($filename, $routingContent); + } + + // I18n sample files + $filename = $this->moduleDirectory . DIRECTORY_SEPARATOR . "I18n" . DIRECTORY_SEPARATOR . "fr_FR.php"; + if (!$fs->exists($filename)) { + $fs->copy( + $skeletonDir . DIRECTORY_SEPARATOR . "I18n" . DIRECTORY_SEPARATOR . "fr_FR.php", + $filename + ); + } + + $filename = $this->moduleDirectory . DIRECTORY_SEPARATOR . "I18n" . DIRECTORY_SEPARATOR . "en_US.php"; + if (!$fs->exists($filename)) { + $fs->copy( + $skeletonDir . DIRECTORY_SEPARATOR . "I18n" . DIRECTORY_SEPARATOR . "en_US.php", + $this->moduleDirectory . DIRECTORY_SEPARATOR . "I18n" . DIRECTORY_SEPARATOR . "en_US.php" + ); + } + } catch (\Exception $ex) { + $fs->remove($this->moduleDirectory); + + throw $ex; + } + } +} diff --git a/core/lib/Thelia/Command/ModuleGenerateModelCommand.php b/core/lib/Thelia/Command/ModuleGenerateModelCommand.php new file mode 100644 index 00000000..a4b8fba9 --- /dev/null +++ b/core/lib/Thelia/Command/ModuleGenerateModelCommand.php @@ -0,0 +1,115 @@ + + */ +class ModuleGenerateModelCommand extends BaseModuleGenerate +{ + protected function configure() + { + $this + ->setName("module:generate:model") + ->setDescription("generate model for a specific module") + ->addArgument( + "name", + InputArgument::REQUIRED, + "module name" + ) + ->addOption( + "generate-sql", + null, + InputOption::VALUE_NONE, + "with this option generate sql file at the same time" + ) + ; + } + + public function execute(InputInterface $input, OutputInterface $output) + { + $this->module = $this->formatModuleName($input->getArgument("name")); + $this->moduleDirectory = THELIA_MODULE_DIR . $this->module; + + $fs = new Filesystem(); + + if ($fs->exists($this->moduleDirectory) === false) { + throw new \RuntimeException(sprintf("%s module does not exists", $this->module)); + } + + if ($fs->exists($this->moduleDirectory . DS . "Config" . DS . "schema.xml") === false) { + throw new \RuntimeException("schema.xml not found in Config directory. Needed file for generating model"); + } + + $this->checkModuleSchema(); + + $this->generateModel($output); + + /** @var FormatterHelper $formatter */ + $formatter = $this->getHelper('formatter'); + $formattedBlock = $formatter->formatBlock( + 'Model generated successfully', + 'bg=green;fg=black' + ); + $output->writeln($formattedBlock); + + if ($input->getOption("generate-sql")) { + $output->writeln(' '); + $this->generateSql($output); + } + } + + protected function generateSql(OutputInterface $output) + { + $command = $this->getApplication()->find("module:generate:sql"); + + $command->run( + new ArrayInput(array( + "command" => $command->getName(), + "name" => $this->module + )), + $output + ); + } + + protected function generateModel(OutputInterface $output) + { + $schemaDir = $this->generateGlobalSchemaForModule(); + + /** @var PropelInitService $propelInitService */ + $propelInitService = $this->getContainer()->get('thelia.propel.init'); + + $propelInitService->runCommand( + new ModelBuildCommand(), + [ + "--config-dir" => $propelInitService->getPropelConfigDir(), + "--schema-dir" => $schemaDir, + ], + $output + ); + } +} diff --git a/core/lib/Thelia/Command/ModuleGenerateSqlCommand.php b/core/lib/Thelia/Command/ModuleGenerateSqlCommand.php new file mode 100644 index 00000000..a17fa33e --- /dev/null +++ b/core/lib/Thelia/Command/ModuleGenerateSqlCommand.php @@ -0,0 +1,86 @@ + + */ +class ModuleGenerateSqlCommand extends BaseModuleGenerate +{ + public function configure() + { + $this + ->setName("module:generate:sql") + ->setDescription("Generate the sql from schema.xml file") + ->addArgument( + "name", + InputArgument::REQUIRED, + "Module name" + ) + ; + } + + public function execute(InputInterface $input, OutputInterface $output) + { + $this->module = $this->formatModuleName($input->getArgument("name")); + $this->moduleDirectory = THELIA_MODULE_DIR . $this->module; + + $fs = new Filesystem(); + + if ($fs->exists($this->moduleDirectory) === false) { + throw new \RuntimeException(sprintf("%s module does not exists", $this->module)); + } + + if ($fs->exists($this->moduleDirectory . DS . "Config" . DS . "schema.xml") === false) { + throw new \RuntimeException("schema.xml not found in Config directory. Needed file for generating model"); + } + + $this->checkModuleSchema(); + + /** @var PropelInitService $propelInitService */ + $propelInitService = $this->getContainer()->get('thelia.propel.init'); + + $propelInitService->runCommand( + new SqlBuildCommand(), + [ + "--output-dir" => "{$this->moduleDirectory}/Config", + "--schema-dir" => "{$this->moduleDirectory}/Config", + "--config-dir" => $propelInitService->getPropelConfigDir(), + ], + $output + ); + + /** @var FormatterHelper $formatter */ + $formatter = $this->getHelper('formatter'); + $formattedBlock = $formatter->formatBlock( + [ + 'Sql generated successfully', + 'File available in your module config directory', + ], + 'bg=green;fg=black' + ); + $output->writeln($formattedBlock); + } +} diff --git a/core/lib/Thelia/Command/ModuleListCommand.php b/core/lib/Thelia/Command/ModuleListCommand.php new file mode 100644 index 00000000..3f15c125 --- /dev/null +++ b/core/lib/Thelia/Command/ModuleListCommand.php @@ -0,0 +1,87 @@ + + */ +class ModuleListCommand extends ContainerAwareCommand +{ + protected function configure() + { + $this + ->setName('module:list') + ->setDescription('List the modules') + ; + } + + /** + * @param InputInterface $input + * @param OutputInterface $output + * @return int|null|void + */ + protected function execute(InputInterface $input, OutputInterface $output) + { + $helper = new Table($output); + $helper->addRows($this->getModulesData()); + + $helper + ->setHeaders(["Code", "Active", "Type", "Version"]) + ->render() + ; + } + + protected function getModulesData() + { + $moduleData = ModuleQuery::create() + ->orderByType() + ->addAsColumn("code", ModuleTableMap::COL_CODE) + ->addAsColumn("active", "IF(".ModuleTableMap::COL_ACTIVATE.", \"Yes\", \"No\")") + ->addAsColumn("type", ModuleTableMap::COL_TYPE) + ->addAsColumn("version", ModuleTableMap::COL_VERSION) + ->select([ + "code", + "active", + "type", + "version", + ]) + ->find() + ->toArray() + ; + + foreach ($moduleData as &$row) { + switch ($row["type"]) { + case BaseModule::CLASSIC_MODULE_TYPE: + $row["type"] = "classic"; + break; + case BaseModule::DELIVERY_MODULE_TYPE: + $row["type"] = "delivery"; + break; + case BaseModule::PAYMENT_MODULE_TYPE: + $row["type"] = "payment"; + break; + } + } + + return $moduleData; + } +} diff --git a/core/lib/Thelia/Command/ModulePositionCommand.php b/core/lib/Thelia/Command/ModulePositionCommand.php new file mode 100644 index 00000000..cf98ec19 --- /dev/null +++ b/core/lib/Thelia/Command/ModulePositionCommand.php @@ -0,0 +1,219 @@ + + */ +class ModulePositionCommand extends ContainerAwareCommand +{ + /** + * @var \Thelia\Model\ModuleQuery + */ + protected $moduleQuery; + + /** + * @var array Modules list + */ + protected $modulesList = []; + + /** + * @var array Modules positions list + */ + protected $positionsList = []; + + public function __construct($name = null) + { + parent::__construct($name); + + $this->moduleQuery = new ModuleQuery; + } + + protected function configure() + { + $this + ->setName('module:position') + ->setDescription('Set module(s) position') + ->addArgument( + 'modules', + InputArgument::REQUIRED | InputArgument::IS_ARRAY, + 'Module in format moduleName:[+|-]position where position is an integer or up or down.' + ) + ; + } + + protected function execute(InputInterface $input, OutputInterface $output) + { + $argsList = $input->getArgument('modules'); + array_walk($argsList, [$this, 'checkModuleArgument']); + + if (!$this->checkPositions($input, $output, $isAbsolute)) { + return; + } + + if ($isAbsolute) { + array_multisort($this->positionsList, SORT_ASC, SORT_REGULAR, $this->modulesList); + } + + $maxPositionByType = $this->cleanPosition(); + + foreach ($this->modulesList as $moduleIdx => $moduleName) { + $this->moduleQuery->clear(); + $module = $this->moduleQuery->findOneByCode($moduleName); + $position = $this->positionsList[$moduleIdx]; + + if ($position === 'up') { + $event = new UpdatePositionEvent($module->getId(), UpdatePositionEvent::POSITION_UP); + } elseif ($position === 'down') { + $event = new UpdatePositionEvent($module->getId(), UpdatePositionEvent::POSITION_DOWN); + } else { + if ($position[0] === '+' || $position[0] === '-') { + $position = $module->getPosition() + $position; + } + + if ($position < 1) { + $position = 1; + } + + $maxPosition = $maxPositionByType[$module->getType()]; + if ($position > $maxPosition) { + $position = $maxPosition; + } + + $event = new UpdatePositionEvent($module->getId(), UpdatePositionEvent::POSITION_ABSOLUTE, $position); + } + + $this->getDispatcher()->dispatch(TheliaEvents::MODULE_UPDATE_POSITION, $event); + } + + /** @var FormatterHelper $formatter */ + $formatter = $this->getHelper('formatter'); + $formattedBlock = $formatter->formatBlock('Module position(s) updated', 'bg=green;fg=black', true); + $output->writeln($formattedBlock); + } + + /** + * Check a module argument format + * + * @param string $paramValue + * + * @throws \InvalidArgumentException + * @throws \RuntimeException + */ + protected function checkModuleArgument($paramValue) + { + if (!preg_match('#^([a-z0-9]+):([\+-]?[0-9]+|up|down)$#i', $paramValue, $matches)) { + throw new \InvalidArgumentException( + 'Arguments must be in format moduleName:[+|-]position where position is an integer or up or down.' + ); + } + + $this->moduleQuery->clear(); + $module = $this->moduleQuery->findOneByCode($matches[1]); + if ($module === null) { + throw new \RuntimeException(sprintf('%s module does not exists. Try to refresh first.', $matches[1])); + } + + $this->modulesList[] = $matches[1]; + $this->positionsList[] = $matches[2]; + } + + /** + * Reorder modules positions (without holes) + * + * @return array Maximum position by type + */ + protected function cleanPosition() + { + $modulesType = []; + + $this->moduleQuery->clear(); + $modules = $this->moduleQuery->orderByPosition(Criteria::ASC); + + /** @var \Thelia\Model\Module $module */ + foreach ($modules as $module) { + if (!isset($modulesType[$module->getType()])) { + $modulesType[$module->getType()] = 0; + } + + $module + ->setPosition(++$modulesType[$module->getType()]) + ->save() + ; + } + + return $modulesType; + } + + /** + * Check positions consistency + * + * @param InputInterface $input An InputInterface instance + * @param OutputInterface $output An OutputInterface instance + * @param bool $isAbsolute Set to true or false according to position values + * + * @throws \InvalidArgumentException + * + * @return bool Continue or stop command + */ + protected function checkPositions(InputInterface $input, OutputInterface $output, &$isAbsolute = false) + { + $isRelative = false; + foreach (array_count_values($this->positionsList) as $value => $count) { + if (\is_int($value) && $value[0] !== '+' && $value[0] !== '-') { + $isAbsolute = true; + + if ($count > 1) { + throw new \InvalidArgumentException('Two (or more) absolute positions are identical.'); + } + } else { + $isRelative = true; + } + } + + if ($isAbsolute && $isRelative) { + /** @var FormatterHelper $formatter */ + $formatter = $this->getHelper('formatter'); + $formattedBlock = $formatter->formatBlock( + 'Mix absolute and relative positions may produce unexpected results !', + 'bg=yellow;fg=black', + true + ); + $output->writeln($formattedBlock); + + /** @var QuestionHelper $helper */ + $helper = $this->getHelper('question'); + + $question = new ConfirmationQuestion('Do you want to continue ? y/[n]', false); + + return $helper->ask($input, $output, $question); + } + + return true; + } +} diff --git a/core/lib/Thelia/Command/ModuleRefreshCommand.php b/core/lib/Thelia/Command/ModuleRefreshCommand.php new file mode 100644 index 00000000..6bb11e33 --- /dev/null +++ b/core/lib/Thelia/Command/ModuleRefreshCommand.php @@ -0,0 +1,62 @@ + + */ +class ModuleRefreshCommand extends ContainerAwareCommand +{ + protected function configure() + { + $this + ->setName('module:refresh') + ->setDescription('Refresh modules list'); + } + + protected function execute(InputInterface $input, OutputInterface $output) + { + try { + $moduleManagement = new ModuleManagement($this->getContainer()); + $moduleManagement->updateModules($this->getContainer()); + } catch (InvalidModuleException $ime) { + throw new \RuntimeException( + sprintf('One or more modules could not be refreshed : %s', $ime->getErrorsAsString("\n")) + ); + } catch (\Exception $e) { + throw new \RuntimeException( + sprintf('Refresh modules list fail with Exception : [%d] %s', $e->getCode(), $e->getMessage()) + ); + } + + if (method_exists($output, 'renderBlock')) { + $output->renderBlock( + [ + '', + 'Modules list successfully refreshed', + '' + ], + 'bg=green;fg=black' + ); + } + } +} diff --git a/core/lib/Thelia/Command/Output/TheliaConsoleOutput.php b/core/lib/Thelia/Command/Output/TheliaConsoleOutput.php new file mode 100644 index 00000000..2fed4381 --- /dev/null +++ b/core/lib/Thelia/Command/Output/TheliaConsoleOutput.php @@ -0,0 +1,43 @@ + $length) ? $strlen($message) : $length; + } + $output = array(); + foreach ($messages as $message) { + $output[] = "<" . $style . ">" . " " . $message . str_repeat(' ', $length - $strlen($message)) . " "; + } + + $this->writeln($output); + } +} diff --git a/core/lib/Thelia/Command/ReloadDatabaseCommand.php b/core/lib/Thelia/Command/ReloadDatabaseCommand.php new file mode 100644 index 00000000..34b95095 --- /dev/null +++ b/core/lib/Thelia/Command/ReloadDatabaseCommand.php @@ -0,0 +1,61 @@ + + */ +class ReloadDatabaseCommand extends BaseModuleGenerate +{ + public function configure() + { + $this + ->setName("thelia:dev:reloadDB") + ->setDescription("erase current database and create new one") +/* ->addOption( + "load-fixtures", + null, + InputOption::VALUE_NONE, + "load fixtures in databases" + )*/ + ; + } + + public function execute(InputInterface $input, OutputInterface $output) + { + /** @var ConnectionWrapper $connection */ + $connection = Propel::getConnection(ProductTableMap::DATABASE_NAME); + $connection = $connection->getWrappedConnection(); + + $database = new Database($connection); + $output->writeln(array( + '', + 'starting reloaded database, please wait' + )); + $database->insertSql(); + $output->writeln(array( + '', + 'Database reloaded with success', + '' + )); + } +} diff --git a/core/lib/Thelia/Command/SaleCheckActivationCommand.php b/core/lib/Thelia/Command/SaleCheckActivationCommand.php new file mode 100644 index 00000000..46c610e0 --- /dev/null +++ b/core/lib/Thelia/Command/SaleCheckActivationCommand.php @@ -0,0 +1,47 @@ + + */ +class SaleCheckActivationCommand extends ContainerAwareCommand +{ + public function configure() + { + $this + ->setName("sale:check-activation") + ->setDescription("check the activation and deactivation dates of sales, and perform the required action depending on the current date."); + } + + public function execute(InputInterface $input, OutputInterface $output) + { + try { + $this->getDispatcher()->dispatch( + TheliaEvents::CHECK_SALE_ACTIVATION_EVENT, + new SaleActiveStatusCheckEvent() + ); + + $output->writeln("Sale verification processed successfully"); + } catch (\Exception $ex) { + $output->writeln(sprintf("Error : %s", $ex->getMessage())); + } + } +} diff --git a/core/lib/Thelia/Command/Skeleton/Module/Class.php.template b/core/lib/Thelia/Command/Skeleton/Module/Class.php.template new file mode 100644 index 00000000..29c66da8 --- /dev/null +++ b/core/lib/Thelia/Command/Skeleton/Module/Class.php.template @@ -0,0 +1,28 @@ + 'The displayed english string', +); diff --git a/core/lib/Thelia/Command/Skeleton/Module/I18n/fr_FR.php b/core/lib/Thelia/Command/Skeleton/Module/I18n/fr_FR.php new file mode 100644 index 00000000..37086245 --- /dev/null +++ b/core/lib/Thelia/Command/Skeleton/Module/I18n/fr_FR.php @@ -0,0 +1,4 @@ + 'La traduction française de la chaine', +); diff --git a/core/lib/Thelia/Command/Skeleton/Module/Readme.md b/core/lib/Thelia/Command/Skeleton/Module/Readme.md new file mode 100644 index 00000000..0cab46bd --- /dev/null +++ b/core/lib/Thelia/Command/Skeleton/Module/Readme.md @@ -0,0 +1,55 @@ +# %%MODULENAMETITLE%% + +Add a short description here. You can also add a screenshot if needed. + +## Installation + +### Manually + +* Copy the module into ```/local/modules/``` directory and be sure that the name of the module is %%MODULENAME%%. +* Activate it in your thelia administration panel + +### Composer + +Add it in your main thelia composer.json file + +``` +composer require your-vendor/%%COMPOSERNAME%%-module:~1.0 +``` + +## Usage + +Explain here how to use your module, how to configure it, etc. + +## Hook + +If your module use one or more hook, fill this part. Explain which hooks are used. + + +## Loop + +If your module declare one or more loop, describe them here like this : + +[loop name] + +### Input arguments + +|Argument |Description | +|--- |--- | +|**arg1** | describe arg1 with an exemple. | +|**arg2** | describe arg2 with an exemple. | + +### Output arguments + +|Variable |Description | +|--- |--- | +|$VAR1 | describe $VAR1 variable | +|$VAR2 | describe $VAR2 variable | + +### Exemple + +Add a complete exemple of your loop + +## Other ? + +If you have other think to put, feel free to complete your readme as you want. diff --git a/core/lib/Thelia/Command/Skeleton/Module/composer.json b/core/lib/Thelia/Command/Skeleton/Module/composer.json new file mode 100644 index 00000000..076254f6 --- /dev/null +++ b/core/lib/Thelia/Command/Skeleton/Module/composer.json @@ -0,0 +1,12 @@ +{ + "name": "your-vendor/%%COMPOSERNAME%%-module", + "description": "%%MODULENAME%% module for Thelia", + "license": "LGPL-3.0-or-later", + "type": "thelia-module", + "require": { + "thelia/installer": "~1.1" + }, + "extra": { + "installer-name": "%%MODULENAME%%" + } +} \ No newline at end of file diff --git a/core/lib/Thelia/Command/Skeleton/Module/config.xml b/core/lib/Thelia/Command/Skeleton/Module/config.xml new file mode 100644 index 00000000..7a8d0ec8 --- /dev/null +++ b/core/lib/Thelia/Command/Skeleton/Module/config.xml @@ -0,0 +1,50 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/core/lib/Thelia/Command/Skeleton/Module/config_dev.xml b/core/lib/Thelia/Command/Skeleton/Module/config_dev.xml new file mode 100644 index 00000000..7a8d0ec8 --- /dev/null +++ b/core/lib/Thelia/Command/Skeleton/Module/config_dev.xml @@ -0,0 +1,50 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/core/lib/Thelia/Command/Skeleton/Module/config_prod.xml b/core/lib/Thelia/Command/Skeleton/Module/config_prod.xml new file mode 100644 index 00000000..7a8d0ec8 --- /dev/null +++ b/core/lib/Thelia/Command/Skeleton/Module/config_prod.xml @@ -0,0 +1,50 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/core/lib/Thelia/Command/Skeleton/Module/config_test.xml b/core/lib/Thelia/Command/Skeleton/Module/config_test.xml new file mode 100644 index 00000000..7a8d0ec8 --- /dev/null +++ b/core/lib/Thelia/Command/Skeleton/Module/config_test.xml @@ -0,0 +1,50 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/core/lib/Thelia/Command/Skeleton/Module/module.xml b/core/lib/Thelia/Command/Skeleton/Module/module.xml new file mode 100644 index 00000000..e06c75dc --- /dev/null +++ b/core/lib/Thelia/Command/Skeleton/Module/module.xml @@ -0,0 +1,43 @@ + + + %%NAMESPACE%%\%%CLASSNAME%% + + Automatically generated module - please update module.xml file + + + + Module généré automatiquement - éditez le fichier module.xml + + + + + en_US + fr_FR + + + + + + + + + classic + + 2.4.3 + other + 0 + 0 + diff --git a/core/lib/Thelia/Command/Skeleton/Module/routing.xml b/core/lib/Thelia/Command/Skeleton/Module/routing.xml new file mode 100644 index 00000000..12c942d0 --- /dev/null +++ b/core/lib/Thelia/Command/Skeleton/Module/routing.xml @@ -0,0 +1,31 @@ + + + + + + + diff --git a/core/lib/Thelia/Command/Skeleton/Module/schema.xml b/core/lib/Thelia/Command/Skeleton/Module/schema.xml new file mode 100644 index 00000000..4cf2caba --- /dev/null +++ b/core/lib/Thelia/Command/Skeleton/Module/schema.xml @@ -0,0 +1,25 @@ + + + + diff --git a/core/lib/Thelia/Command/UpdateCurrenciesRates.php b/core/lib/Thelia/Command/UpdateCurrenciesRates.php new file mode 100644 index 00000000..19ea1bb7 --- /dev/null +++ b/core/lib/Thelia/Command/UpdateCurrenciesRates.php @@ -0,0 +1,73 @@ + + */ +class UpdateCurrenciesRates extends ContainerAwareCommand +{ + protected function configure() + { + $this + ->setName("currency:update-rates") + ->setDescription("Update currency rates") + ; + } + + protected function execute(InputInterface $input, OutputInterface $output) + { + /** @var EventDispatcherInterface $dispatcher */ + try { + $event = new CurrencyUpdateRateEvent(); + + $this->getDispatcher()->dispatch(TheliaEvents::CURRENCY_UPDATE_RATES, $event); + + if ($event->hasUndefinedRates()) { + $output->writeln("Rate was not found for the following currencies:"); + + $undefinedCurrencies = CurrencyQuery::create() + ->filterById($event->getUndefinedRates()) + ->find(); + + /** @var Currency $currency */ + foreach ($undefinedCurrencies as $currency) { + $output->writeln(" -" . $currency->getName() . " (".$currency->getCode()."), current rate is " . $currency->getRate()); + } + + $output->writeln("Update done with errors"); + } else { + $output->writeln("Update done withour errors"); + + return 1; + } + } catch (\Exception $ex) { + // Any error + $output->writeln("Update failed: " . $ex->getMessage() . ""); + + return 2; + } + + return 0; + } +} diff --git a/core/lib/Thelia/Condition/ConditionCollection.php b/core/lib/Thelia/Condition/ConditionCollection.php new file mode 100644 index 00000000..e8c3d677 --- /dev/null +++ b/core/lib/Thelia/Condition/ConditionCollection.php @@ -0,0 +1,191 @@ + + * + */ +class ConditionCollection implements Iterator, Countable, ArrayAccess +{ + /** @var ConditionInterface[] */ + protected $conditions = []; + + /** + * (PHP 5 >= 5.0.0) + * Return the current element + * @link http://php.net/manual/en/iterator.current.php + * + * @return mixed Can return any type. + */ + public function current() + { + $var = current($this->conditions); + + return $var; + } + + /** + * (PHP 5 >= 5.0.0) + * Move forward to next element + * @link http://php.net/manual/en/iterator.next.php + * + * @return void Any returned value is ignored. + */ + public function next() + { + next($this->conditions); + } + + /** + * (PHP 5 >= 5.0.0) + * Return the key of the current element + * @link http://php.net/manual/en/iterator.key.php + * + * @return mixed scalar on success, or null on failure. + */ + public function key() + { + $var = key($this->conditions); + + return $var; + } + + /** + * (PHP 5 >= 5.0.0) + * Checks if current position is valid + * @link http://php.net/manual/en/iterator.valid.php + * + * @return boolean The return value will be casted to boolean and then evaluated. + * Returns true on success or false on failure. + */ + public function valid() + { + $key = key($this->conditions); + $var = ($key !== null && $key !== false); + + return $var; + } + + /** + * (PHP 5 >= 5.0.0) + * Rewind the Iterator to the first element + * @link http://php.net/manual/en/iterator.rewind.php + * + * @return void Any returned value is ignored. + */ + public function rewind() + { + reset($this->conditions); + } + + /** + * (PHP 5 >= 5.1.0) + * Count elements of an object + * @link http://php.net/manual/en/countable.count.php + * + * @return int The custom count as an integer. + * The return value is cast to an integer. + */ + public function count() + { + return \count($this->conditions); + } + + /** + * (PHP 5 >= 5.0.0) + * Whether a offset exists + * @link http://php.net/manual/en/arrayaccess.offsetexists.php + * @param mixed $offset + * An offset to check for. + * + * @return boolean true on success or false on failure. + * The return value will be casted to boolean if non-boolean was returned. + */ + public function offsetExists($offset) + { + return isset($this->conditions[$offset]); + } + + /** + * (PHP 5 >= 5.0.0) + * Offset to retrieve + * @link http://php.net/manual/en/arrayaccess.offsetget.php + * @param mixed $offset + * The offset to retrieve. + * + * @return mixed Can return all value types. + */ + public function offsetGet($offset) + { + return isset($this->conditions[$offset]) ? $this->conditions[$offset] : null; + } + + /** + * (PHP 5 >= 5.0.0) + * Offset to set + * @link http://php.net/manual/en/arrayaccess.offsetset.php + * @param mixed $offset + * The offset to assign the value to. + * @param mixed $value + * The value to set. + * + * @return void + */ + public function offsetSet($offset, $value) + { + if (\is_null($offset)) { + $this->conditions[] = $value; + } else { + $this->conditions[$offset] = $value; + } + } + + /** + * (PHP 5 >= 5.0.0) + * Offset to unset + * @link http://php.net/manual/en/arrayaccess.offsetunset.php + * @param mixed $offset + * The offset to unset. + * + * @return void + */ + public function offsetUnset($offset) + { + unset($this->conditions[$offset]); + } + + /** + * Allow to compare 2 set of conditions + * + * @return string Jsoned data + */ + public function __toString() + { + $arrayToSerialize = []; + /** @var ConditionInterface $condition */ + foreach ($this as $condition) { + $arrayToSerialize[] = $condition->getSerializableCondition(); + } + + return json_encode($arrayToSerialize); + } +} diff --git a/core/lib/Thelia/Condition/ConditionEvaluator.php b/core/lib/Thelia/Condition/ConditionEvaluator.php new file mode 100644 index 00000000..f1f5686b --- /dev/null +++ b/core/lib/Thelia/Condition/ConditionEvaluator.php @@ -0,0 +1,95 @@ + + * + */ +class ConditionEvaluator +{ + /** + * Check if an Event matches SerializableCondition + * + * @param ConditionCollection $conditions Conditions to check against the Event + * + * @return bool + */ + public function isMatching(ConditionCollection $conditions) + { + $isMatching = true; + /** @var ConditionInterface $condition */ + foreach ($conditions as $condition) { + if (!$condition->isMatching()) { + return false; + } + } + + return $isMatching; + } + + /** + * Do variable comparison + * + * @param mixed $v1 Variable 1 + * @param string $o Operator ex : Operators::DIFFERENT + * @param mixed $v2 Variable 2 + * + * @throws \Exception + * @return bool + */ + public function variableOpComparison($v1, $o, $v2) + { + switch ($o) { + case Operators::DIFFERENT: + // != + return ($v1 != $v2); + + case Operators::SUPERIOR: + // > + return ($v1 > $v2); + + case Operators::SUPERIOR_OR_EQUAL: + // >= + return ($v1 >= $v2); + + case Operators::INFERIOR: + // < + return ($v1 < $v2); + + case Operators::INFERIOR_OR_EQUAL: + // <= + return ($v1 <= $v2); + + case Operators::EQUAL: + // == + return ($v1 == $v2); + + case Operators::IN: + // in + return (\in_array($v1, $v2)); + + case Operators::OUT: + // not in + return (!\in_array($v1, $v2)); + + default: + throw new \Exception('Unrecognized operator ' . $o); + } + } +} diff --git a/core/lib/Thelia/Condition/ConditionFactory.php b/core/lib/Thelia/Condition/ConditionFactory.php new file mode 100644 index 00000000..1def860c --- /dev/null +++ b/core/lib/Thelia/Condition/ConditionFactory.php @@ -0,0 +1,157 @@ + + * + */ +class ConditionFactory +{ + /** @var ContainerInterface Service Container */ + protected $container = null; + + /** @var FacadeInterface Provide necessary value from Thelia */ + protected $adapter; + + /** @var array ConditionCollection to process*/ + protected $conditions = null; + + /** + * Constructor + * + * @param ContainerInterface $container Service container + */ + public function __construct(ContainerInterface $container) + { + $this->container = $container; + $this->adapter = $container->get('thelia.facade'); + } + + /** + * Serialize a collection of conditions + * + * @param ConditionCollection $collection A collection of conditions + * + * @return string A ready to be stored Condition collection + */ + public function serializeConditionCollection(ConditionCollection $collection) + { + if ($collection->count() == 0) { + /** @var ConditionInterface $conditionNone */ + $conditionNone = $this->container->get( + 'thelia.condition.match_for_everyone' + ); + $collection[] = $conditionNone; + } + $serializableConditions = []; + /** @var $condition ConditionInterface */ + foreach ($collection as $condition) { + $serializableConditions[] = $condition->getSerializableCondition(); + } + + return base64_encode(json_encode($serializableConditions)); + } + + /** + * Unserialize a collection of conditions + * + * @param string $serializedConditions Serialized Conditions + * + * @return ConditionCollection Conditions ready to be processed + */ + public function unserializeConditionCollection($serializedConditions) + { + $unserializedConditions = json_decode(base64_decode($serializedConditions)); + + $collection = new ConditionCollection(); + + if (!empty($unserializedConditions)) { + /** @var SerializableCondition $condition */ + foreach ($unserializedConditions as $condition) { + if ($this->container->has($condition->conditionServiceId)) { + /** @var ConditionInterface $conditionManager */ + $conditionManager = $this->build( + $condition->conditionServiceId, + (array) $condition->operators, + (array) $condition->values + ); + $collection[] = clone $conditionManager; + } + } + } + + return $collection; + } + + /** + * Build a Condition from form + * + * @param string $conditionServiceId Condition class name + * @param array $operators Condition Operator (<, >, = ) + * @param array $values Values setting this Condition + * + * @throws \InvalidArgumentException + * @return ConditionInterface Ready to use Condition or false + */ + public function build($conditionServiceId, array $operators, array $values) + { + if (!$this->container->has($conditionServiceId)) { + return false; + } + + /** @var ConditionInterface $condition */ + $condition = $this->container->get($conditionServiceId); + $condition->setValidatorsFromForm($operators, $values); + + return clone $condition; + } + + /** + * Get Condition inputs from serviceId + * + * @param string $conditionServiceId ConditionManager class name + * + * @return array Ready to be drawn condition inputs + */ + public function getInputsFromServiceId($conditionServiceId) + { + if (!$this->container->has($conditionServiceId)) { + return false; + } + + /** @var ConditionInterface $condition */ + $condition = $this->container->get($conditionServiceId); + + return $this->getInputsFromConditionInterface($condition); + } + + /** + * Get Condition inputs from serviceId + * + * @param ConditionInterface $condition ConditionManager + * + * @return array Ready to be drawn condition inputs + */ + public function getInputsFromConditionInterface(ConditionInterface $condition) + { + return $condition->getValidators(); + } +} diff --git a/core/lib/Thelia/Condition/ConditionOrganizer.php b/core/lib/Thelia/Condition/ConditionOrganizer.php new file mode 100644 index 00000000..dcd3a9f6 --- /dev/null +++ b/core/lib/Thelia/Condition/ConditionOrganizer.php @@ -0,0 +1,35 @@ + + * + */ +class ConditionOrganizer implements ConditionOrganizerInterface +{ + /** + * Organize ConditionInterface + * + * @param array $conditions Array of ConditionInterface + * + * @return array Array of ConditionInterface sorted + */ + public function organize(array $conditions) + { + // @todo: Implement organize() method. + } +} diff --git a/core/lib/Thelia/Condition/ConditionOrganizerInterface.php b/core/lib/Thelia/Condition/ConditionOrganizerInterface.php new file mode 100644 index 00000000..8d056d5e --- /dev/null +++ b/core/lib/Thelia/Condition/ConditionOrganizerInterface.php @@ -0,0 +1,32 @@ + + * + */ +interface ConditionOrganizerInterface +{ + /** + * Organize ConditionInterface + * + * @param array $conditions Array of ConditionInterface + * + * @return array Array of ConditionInterface sorted + */ + public function organize(array $conditions); +} diff --git a/core/lib/Thelia/Condition/Implementation/AbstractMatchCountries.php b/core/lib/Thelia/Condition/Implementation/AbstractMatchCountries.php new file mode 100644 index 00000000..66826510 --- /dev/null +++ b/core/lib/Thelia/Condition/Implementation/AbstractMatchCountries.php @@ -0,0 +1,155 @@ + + * + */ +abstract class AbstractMatchCountries extends ConditionAbstract +{ + /** Condition 1st parameter : quantity */ + const COUNTRIES_LIST = 'countries'; + + /** + * @inheritdoc + */ + public function __construct(FacadeInterface $facade) + { + $this->availableOperators = [ + self::COUNTRIES_LIST => [ + Operators::IN, + Operators::OUT + ] + ]; + + parent::__construct($facade); + } + + abstract protected function getSummaryLabel($cntryStrList, $i18nOperator); + + abstract protected function getFormLabel(); + + /** + * @inheritdoc + */ + public function setValidatorsFromForm(array $operators, array $values) + { + $this->checkComparisonOperatorValue($operators, self::COUNTRIES_LIST); + + // Use default values if data is not defined. + if (! isset($operators[self::COUNTRIES_LIST]) || ! isset($values[self::COUNTRIES_LIST])) { + $operators[self::COUNTRIES_LIST] = Operators::IN; + $values[self::COUNTRIES_LIST] = []; + } + + // Be sure that the value is an array, make one if required + if (! \is_array($values[self::COUNTRIES_LIST])) { + $values[self::COUNTRIES_LIST] = array($values[self::COUNTRIES_LIST]); + } + + // Check that at least one category is selected + if (empty($values[self::COUNTRIES_LIST])) { + throw new InvalidConditionValueException( + \get_class(), + self::COUNTRIES_LIST + ); + } + + $this->operators = [ self::COUNTRIES_LIST => $operators[self::COUNTRIES_LIST] ]; + $this->values = [ self::COUNTRIES_LIST => $values[self::COUNTRIES_LIST] ]; + + return $this; + } + + /** + * @inheritdoc + */ + public function isMatching() + { + // The delivery address should match one of the selected countries. + + /* TODO !!!! */ + + return $this->conditionValidator->variableOpComparison( + $this->facade->getNbArticlesInCart(), + $this->operators[self::COUNTRIES_LIST], + $this->values[self::COUNTRIES_LIST] + ); + } + + /** + * @inheritdoc + */ + public function getSummary() + { + $i18nOperator = Operators::getI18n( + $this->translator, + $this->operators[self::COUNTRIES_LIST] + ); + + $cntryStrList = ''; + + $cntryIds = $this->values[self::COUNTRIES_LIST]; + + if (null !== $cntryList = CountryQuery::create()->findPks($cntryIds)) { + /** @var Country $cntry */ + foreach ($cntryList as $cntry) { + $cntryStrList .= $cntry->setLocale($this->getCurrentLocale())->getTitle() . ', '; + } + + $cntryStrList = rtrim($cntryStrList, ', '); + } + + return $this->getSummaryLabel($cntryStrList, $i18nOperator); + } + + /** + * @inheritdoc + */ + protected function generateInputs() + { + return array( + self::COUNTRIES_LIST => array( + 'availableOperators' => $this->availableOperators[self::COUNTRIES_LIST], + 'value' => '', + 'selectedOperator' => Operators::IN + ) + ); + } + + /** + * @inheritdoc + */ + public function drawBackOfficeInputs() + { + return $this->facade->getParser()->render( + 'coupon/condition-fragments/countries-condition.html', + [ + 'operatorSelectHtml' => $this->drawBackOfficeInputOperators(self::COUNTRIES_LIST), + 'countries_field_name' => self::COUNTRIES_LIST, + 'values' => isset($this->values[self::COUNTRIES_LIST]) ? $this->values[self::COUNTRIES_LIST] : array(), + 'countryLabel' => $this->getFormLabel() + ] + ); + } +} diff --git a/core/lib/Thelia/Condition/Implementation/CartContainsCategories.php b/core/lib/Thelia/Condition/Implementation/CartContainsCategories.php new file mode 100644 index 00000000..d8aba696 --- /dev/null +++ b/core/lib/Thelia/Condition/Implementation/CartContainsCategories.php @@ -0,0 +1,200 @@ + + * + */ +class CartContainsCategories extends ConditionAbstract +{ + /** Condition 1st parameter : quantity */ + const CATEGORIES_LIST = 'categories'; + + /** + * @inheritdoc + */ + public function __construct(FacadeInterface $facade) + { + $this->availableOperators = [ + self::CATEGORIES_LIST => [ + Operators::IN, + Operators::OUT + ] + ]; + + parent::__construct($facade); + } + + /** + * @inheritdoc + */ + public function getServiceId() + { + return 'thelia.condition.cart_contains_categories'; + } + + /** + * @inheritdoc + */ + public function setValidatorsFromForm(array $operators, array $values) + { + $this->checkComparisonOperatorValue($operators, self::CATEGORIES_LIST); + + // Use default values if data is not defined. + if (! isset($operators[self::CATEGORIES_LIST]) || ! isset($values[self::CATEGORIES_LIST])) { + $operators[self::CATEGORIES_LIST] = Operators::IN; + $values[self::CATEGORIES_LIST] = []; + } + + // Be sure that the value is an array, make one if required + if (! \is_array($values[self::CATEGORIES_LIST])) { + $values[self::CATEGORIES_LIST] = array($values[self::CATEGORIES_LIST]); + } + + // Check that at least one category is selected + if (empty($values[self::CATEGORIES_LIST])) { + throw new InvalidConditionValueException( + \get_class(), + self::CATEGORIES_LIST + ); + } + + $this->operators = [ self::CATEGORIES_LIST => $operators[self::CATEGORIES_LIST] ]; + $this->values = [ self::CATEGORIES_LIST => $values[self::CATEGORIES_LIST] ]; + + return $this; + } + + /** + * @inheritdoc + */ + public function isMatching() + { + $cartItems = $this->facade->getCart()->getCartItems(); + + /** @var CartItem $cartItem */ + foreach ($cartItems as $cartItem) { + $categories = $cartItem->getProduct()->getCategories(); + + /** @var Category $category */ + foreach ($categories as $category) { + if ($this->conditionValidator->variableOpComparison( + $category->getId(), + $this->operators[self::CATEGORIES_LIST], + $this->values[self::CATEGORIES_LIST] + )) { + return true; + } + } + } + return false; + } + + /** + * @inheritdoc + */ + public function getName() + { + return $this->translator->trans( + 'Cart contains categories condition', + [] + ); + } + + /** + * @inheritdoc + */ + public function getToolTip() + { + $toolTip = $this->translator->trans( + 'The coupon applies if the cart contains at least one product of the selected categories', + [] + ); + + return $toolTip; + } + + /** + * @inheritdoc + */ + public function getSummary() + { + $i18nOperator = Operators::getI18n( + $this->translator, + $this->operators[self::CATEGORIES_LIST] + ); + + $catStrList = ''; + + $catIds = $this->values[self::CATEGORIES_LIST]; + + if (null !== $catList = CategoryQuery::create()->findPks($catIds)) { + /** @var Category $cat */ + foreach ($catList as $cat) { + $catStrList .= $cat->setLocale($this->getCurrentLocale())->getTitle() . ', '; + } + + $catStrList = rtrim($catStrList, ', '); + } + + $toolTip = $this->translator->trans( + 'At least one of cart products categories is %op% %categories_list%', + [ + '%categories_list%' => $catStrList, + '%op%' => $i18nOperator + ] + ); + + return $toolTip; + } + + /** + * @inheritdoc + */ + protected function generateInputs() + { + return array( + self::CATEGORIES_LIST => array( + 'availableOperators' => $this->availableOperators[self::CATEGORIES_LIST], + 'value' => '', + 'selectedOperator' => Operators::IN + ) + ); + } + + /** + * @inheritdoc + */ + public function drawBackOfficeInputs() + { + return $this->facade->getParser()->render( + 'coupon/condition-fragments/cart-contains-categories-condition.html', + [ + 'operatorSelectHtml' => $this->drawBackOfficeInputOperators(self::CATEGORIES_LIST), + 'categories_field_name' => self::CATEGORIES_LIST, + 'values' => isset($this->values[self::CATEGORIES_LIST]) ? $this->values[self::CATEGORIES_LIST] : array() + ] + ); + } +} diff --git a/core/lib/Thelia/Condition/Implementation/CartContainsProducts.php b/core/lib/Thelia/Condition/Implementation/CartContainsProducts.php new file mode 100644 index 00000000..c8364d5c --- /dev/null +++ b/core/lib/Thelia/Condition/Implementation/CartContainsProducts.php @@ -0,0 +1,195 @@ + + * + */ +class CartContainsProducts extends ConditionAbstract +{ + /** Condition 1st parameter : quantity */ + const PRODUCTS_LIST = 'products'; + + /** + * @inheritdoc + */ + public function __construct(FacadeInterface $facade) + { + $this->availableOperators = [ + self::PRODUCTS_LIST => [ + Operators::IN, + Operators::OUT + ] + ]; + + parent::__construct($facade); + } + + /** + * @inheritdoc + */ + public function getServiceId() + { + return 'thelia.condition.cart_contains_products'; + } + + /** + * @inheritdoc + */ + public function setValidatorsFromForm(array $operators, array $values) + { + $this->checkComparisonOperatorValue($operators, self::PRODUCTS_LIST); + + // Use default values if data is not defined. + if (! isset($operators[self::PRODUCTS_LIST]) || ! isset($values[self::PRODUCTS_LIST])) { + $operators[self::PRODUCTS_LIST] = Operators::IN; + $values[self::PRODUCTS_LIST] = []; + } + + // Be sure that the value is an array, make one if required + if (! \is_array($values[self::PRODUCTS_LIST])) { + $values[self::PRODUCTS_LIST] = array($values[self::PRODUCTS_LIST]); + } + + // Check that at least one product is selected + if (empty($values[self::PRODUCTS_LIST])) { + throw new InvalidConditionValueException( + \get_class(), + self::PRODUCTS_LIST + ); + } + + $this->operators = [ self::PRODUCTS_LIST => $operators[self::PRODUCTS_LIST] ]; + $this->values = [ self::PRODUCTS_LIST => $values[self::PRODUCTS_LIST] ]; + + return $this; + } + + /** + * @inheritdoc + */ + public function isMatching() + { + $cartItems = $this->facade->getCart()->getCartItems(); + + /** @var CartItem $cartItem */ + foreach ($cartItems as $cartItem) { + if ($this->conditionValidator->variableOpComparison( + $cartItem->getProduct()->getId(), + $this->operators[self::PRODUCTS_LIST], + $this->values[self::PRODUCTS_LIST] + )) { + return true; + } + } + return false; + } + + /** + * @inheritdoc + */ + public function getName() + { + return $this->translator->trans( + 'Cart contains specific products', + [] + ); + } + + /** + * @inheritdoc + */ + public function getToolTip() + { + $toolTip = $this->translator->trans( + 'The coupon applies if the cart contains at least one product of the specified product list', + [] + ); + + return $toolTip; + } + + /** + * @inheritdoc + */ + public function getSummary() + { + $i18nOperator = Operators::getI18n( + $this->translator, + $this->operators[self::PRODUCTS_LIST] + ); + + $prodStrList = ''; + + $prodIds = $this->values[self::PRODUCTS_LIST]; + + if (null !== $prodList = ProductQuery::create()->findPks($prodIds)) { + /** @var Product $prod */ + foreach ($prodList as $prod) { + $prodStrList .= $prod->setLocale($this->getCurrentLocale())->getTitle() . ', '; + } + + $prodStrList = rtrim($prodStrList, ', '); + } + + $toolTip = $this->translator->trans( + 'Cart contains at least a product %op% %products_list%', + [ + '%products_list%' => $prodStrList, + '%op%' => $i18nOperator + ] + ); + + return $toolTip; + } + + /** + * @inheritdoc + */ + protected function generateInputs() + { + return array( + self::PRODUCTS_LIST => array( + 'availableOperators' => $this->availableOperators[self::PRODUCTS_LIST], + 'value' => '', + 'selectedOperator' => Operators::IN + ) + ); + } + + /** + * @inheritdoc + */ + public function drawBackOfficeInputs() + { + return $this->facade->getParser()->render( + 'coupon/condition-fragments/cart-contains-products-condition.html', + [ + 'operatorSelectHtml' => $this->drawBackOfficeInputOperators(self::PRODUCTS_LIST), + 'products_field_name' => self::PRODUCTS_LIST, + 'values' => isset($this->values[self::PRODUCTS_LIST]) ? $this->values[self::PRODUCTS_LIST] : array() + ] + ); + } +} diff --git a/core/lib/Thelia/Condition/Implementation/ConditionAbstract.php b/core/lib/Thelia/Condition/Implementation/ConditionAbstract.php new file mode 100644 index 00000000..3f6effa3 --- /dev/null +++ b/core/lib/Thelia/Condition/Implementation/ConditionAbstract.php @@ -0,0 +1,351 @@ + + * + */ +abstract class ConditionAbstract implements ConditionInterface +{ + /** @var array Available Operators (Operators::CONST) */ + protected $availableOperators = []; + + /** @var array Parameters validating parameters against */ + protected $validators = []; + + /** @var FacadeInterface Provide necessary value from Thelia */ + protected $facade = null; + + /** @var Translator Service Translator */ + protected $translator = null; + + /** @var array Operators set by Admin in BackOffice */ + protected $operators = []; + + /** @var array Values set by Admin in BackOffice */ + protected $values = []; + + /** @var ConditionEvaluator Conditions validator */ + protected $conditionValidator = null; + + /** + * Constructor + * + * @param FacadeInterface $facade Service Facade + */ + public function __construct(FacadeInterface $facade) + { + $this->facade = $facade; + $this->translator = $facade->getTranslator(); + $this->conditionValidator = $facade->getConditionEvaluator(); + } + + /** + * @param array $operatorList the list of comparison operator values, as entered in the condition parameter form + * @param string $parameterName the name of the parameter to check + * + * @return $this + * + * @throws \Thelia\Exception\InvalidConditionOperatorException if the operator value is not in the allowed value + */ + protected function checkComparisonOperatorValue($operatorList, $parameterName) + { + $isOperator1Legit = $this->isOperatorLegit( + $operatorList[$parameterName], + $this->availableOperators[$parameterName] + ); + + if (!$isOperator1Legit) { + throw new InvalidConditionOperatorException( + \get_class(), + $parameterName + ); + } + + return $this; + } + + /** + * Return all validators + * + * @return array + */ + public function getValidators() + { + $this->validators = $this->generateInputs(); + + $translatedInputs = []; + + foreach ($this->validators as $key => $validator) { + $translatedOperators = []; + + foreach ($validator['availableOperators'] as $availableOperators) { + $translatedOperators[$availableOperators] = Operators::getI18n( + $this->translator, + $availableOperators + ); + } + + $validator['availableOperators'] = $translatedOperators; + + $translatedInputs[$key] = $validator; + } + + $validators = [ + 'inputs' => $translatedInputs, + 'setOperators' => $this->operators, + 'setValues' => $this->values + ]; + + return $validators; + } + + /** + * Generate inputs ready to be drawn. + * + * TODO: what these "inputs ready to be drawn" is not clear. + * + * @throws \Thelia\Exception\NotImplementedException + * @return array + */ + protected function generateInputs() + { + throw new \Thelia\Exception\NotImplementedException( + 'The generateInputs method must be implemented in ' . \get_class() + ); + } + + /** + * Get ConditionManager Service id + * + * @return string + */ + public function getServiceId() + { + throw new \Thelia\Exception\NotImplementedException( + 'The getServiceId method must be implemented in ' . \get_class() + ); + } + + /** + * Validate if Operator given is available for this Condition + * + * @param string $operator Operator to validate ex < + * @param array $availableOperators Available operators + * + * @return bool + */ + protected function isOperatorLegit($operator, array $availableOperators) + { + return \in_array($operator, $availableOperators); + } + + /** + * Return a serializable Condition + * + * @return SerializableCondition + */ + public function getSerializableCondition() + { + $serializableCondition = new SerializableCondition(); + $serializableCondition->conditionServiceId = $this->getServiceId(); + $serializableCondition->operators = $this->operators; + + $serializableCondition->values = $this->values; + + return $serializableCondition; + } + + /** + * Check if currency if valid or not + * + * @param string $currencyValue Currency EUR|USD|.. + * + * @return bool + * @throws \Thelia\Exception\InvalidConditionValueException + */ + protected function isCurrencyValid($currencyValue) + { + $availableCurrencies = $this->facade->getAvailableCurrencies(); + /** @var Currency $currency */ + $currencyFound = false; + foreach ($availableCurrencies as $currency) { + if ($currencyValue == $currency->getCode()) { + $currencyFound = true; + } + } + if (!$currencyFound) { + throw new InvalidConditionValueException( + \get_class(), + 'currency' + ); + } + + return true; + } + + /** + * Check if price is valid + * + * @param float $priceValue Price value to check + * + * @return bool + * @throws \Thelia\Exception\InvalidConditionValueException + */ + protected function isPriceValid($priceValue) + { + $floatType = new FloatType(); + if (!$floatType->isValid($priceValue) || $priceValue <= 0) { + throw new InvalidConditionValueException( + \get_class(), + 'price' + ); + } + + return true; + } + + /** + * Draw the operator input displayed in the BackOffice + * allowing Admin to set its Coupon Conditions + * + * @param string $inputKey Input key (ex: self::INPUT1) + * + * @return string HTML string + */ + protected function drawBackOfficeInputOperators($inputKey) + { + $html = ''; + + $inputs = $this->getValidators(); + + if (isset($inputs['inputs'][$inputKey])) { + $html = $this->facade->getParser()->render( + 'coupon/condition-fragments/condition-selector.html', + [ + 'operators' => $inputs['inputs'][$inputKey]['availableOperators'], + 'value' => isset($this->operators[$inputKey]) ? $this->operators[$inputKey] : '', + 'inputKey' => $inputKey + ] + ); + } + + return $html; + } + + /** + * Draw the base input displayed in the BackOffice + * allowing Admin to set its Coupon Conditions + * + * @param string $label I18n input label + * @param string $inputKey Input key (ex: self::INPUT1) + * + * @return string HTML string + */ + protected function drawBackOfficeBaseInputsText($label, $inputKey) + { + $operatorSelectHtml = $this->drawBackOfficeInputOperators($inputKey); + + $currentValue = ''; + if (isset($this->values) && isset($this->values[$inputKey])) { + $currentValue = $this->values[$inputKey]; + } + + return $this->facade->getParser()->render( + 'coupon/conditions-fragments/base-input-text.html', + [ + 'label' => $label, + 'inputKey' => $inputKey, + 'currentValue' => $currentValue, + 'operatorSelectHtml' => $operatorSelectHtml + ] + ); + } + + /** + * Draw the quantity input displayed in the BackOffice + * allowing Admin to set its Coupon Conditions + * + * @param string $inputKey Input key (ex: self::INPUT1) + * @param int $max Maximum selectable + * @param int $min Minimum selectable + * + * @return string HTML string + */ + protected function drawBackOfficeInputQuantityValues($inputKey, $max = 10, $min = 0) + { + return $this->facade->getParser()->render( + 'coupon/condition-fragments/quantity-selector.html', + [ + 'min' => $min, + 'max' => $max, + 'value' => isset($this->values[$inputKey]) ? $this->values[$inputKey] : '', + 'inputKey' => $inputKey + ] + ); + } + + /** + * Draw the currency input displayed in the BackOffice + * allowing Admin to set its Coupon Conditions + * + * @param string $inputKey Input key (ex: self::INPUT1) + * + * @return string HTML string + */ + protected function drawBackOfficeCurrencyInput($inputKey) + { + $currencies = CurrencyQuery::create()->find(); + + $cleanedCurrencies = []; + + /** @var Currency $currency */ + foreach ($currencies as $currency) { + $cleanedCurrencies[$currency->getCode()] = $currency->getSymbol(); + } + + return $this->facade->getParser()->render( + 'coupon/condition-fragments/currency-selector.html', + [ + 'currencies' => $cleanedCurrencies, + 'value' => isset($this->values[$inputKey]) ? $this->values[$inputKey] : '', + 'inputKey' => $inputKey + ] + ); + } + + /** + * A helper to het the current locale. + * + * @return string the current locale. + */ + protected function getCurrentLocale() + { + return $this->facade->getRequest()->getSession()->getLang()->getLocale(); + } +} diff --git a/core/lib/Thelia/Condition/Implementation/ConditionInterface.php b/core/lib/Thelia/Condition/Implementation/ConditionInterface.php new file mode 100644 index 00000000..f1d839cb --- /dev/null +++ b/core/lib/Thelia/Condition/Implementation/ConditionInterface.php @@ -0,0 +1,107 @@ + + * + */ +interface ConditionInterface +{ + /** + * Constructor + * + * @param FacadeInterface $adapter Service adapter + */ + public function __construct(FacadeInterface $adapter); + + /** + * Get Condition Service id + * + * @return string + */ + public function getServiceId(); + + /** + * Check validators relevancy and store them + * + * @param array $operators an array of operators (greater than, less than, etc.) entered in the condition parameter input form, one for each condition defined by the Condition + * @param array $values an array of values entered in in the condition parameter input form, one for each condition defined by the Condition + * + * @throws InvalidConditionOperatorException + * @throws InvalidConditionValueException + * + * @return $this + */ + public function setValidatorsFromForm(array $operators, array $values); + + /** + * Test if the current application state matches conditions + * + * @return bool + */ + public function isMatching(); + + /** + * Get I18n name + * + * @return string + */ + public function getName(); + + /** + * Get I18n tooltip + * Explain in detail what the Condition checks + * + * @return string + */ + public function getToolTip(); + + /** + * Get I18n summary + * Explain briefly the condition with given values + * + * @return string + */ + public function getSummary(); + + /** + * Return all validators + * + * @return array + */ + public function getValidators(); + + /** + * Return a serializable Condition + * + * @return SerializableCondition + */ + public function getSerializableCondition(); + + /** + * Draw the input displayed in the BackOffice + * allowing Admin to set its Coupon Conditions + * + * @return string HTML string + */ + public function drawBackOfficeInputs(); +} diff --git a/core/lib/Thelia/Condition/Implementation/ForSomeCustomers.php b/core/lib/Thelia/Condition/Implementation/ForSomeCustomers.php new file mode 100644 index 00000000..d05b8c2a --- /dev/null +++ b/core/lib/Thelia/Condition/Implementation/ForSomeCustomers.php @@ -0,0 +1,190 @@ + + * + */ +class ForSomeCustomers extends ConditionAbstract +{ + const CUSTOMERS_LIST = 'customers'; + + /** + * @inheritdoc + */ + public function __construct(FacadeInterface $facade) + { + $this->availableOperators = [ + self::CUSTOMERS_LIST => [ + Operators::IN, + Operators::OUT + ] + ]; + + parent::__construct($facade); + } + + /** + * @inheritdoc + */ + public function getServiceId() + { + return 'thelia.condition.for_some_customers'; + } + + /** + * @inheritdoc + */ + public function setValidatorsFromForm(array $operators, array $values) + { + $this->checkComparisonOperatorValue($operators, self::CUSTOMERS_LIST); + + // Use default values if data is not defined. + if (! isset($operators[self::CUSTOMERS_LIST]) || ! isset($values[self::CUSTOMERS_LIST])) { + $operators[self::CUSTOMERS_LIST] = Operators::IN; + $values[self::CUSTOMERS_LIST] = []; + } + + // Be sure that the value is an array, make one if required + if (! \is_array($values[self::CUSTOMERS_LIST])) { + $values[self::CUSTOMERS_LIST] = array($values[self::CUSTOMERS_LIST]); + } + + // Check that at least one product is selected + if (empty($values[self::CUSTOMERS_LIST])) { + throw new InvalidConditionValueException( + \get_class(), + self::CUSTOMERS_LIST + ); + } + + $this->operators = [ self::CUSTOMERS_LIST => $operators[self::CUSTOMERS_LIST] ]; + $this->values = [ self::CUSTOMERS_LIST => $values[self::CUSTOMERS_LIST] ]; + + return $this; + } + + /** + * @inheritdoc + */ + public function isMatching() + { + if (null === $customer = $this->facade->getCustomer()) { + throw new UnmatchableConditionException(); + } + + return $this->conditionValidator->variableOpComparison( + $customer->getId(), + $this->operators[self::CUSTOMERS_LIST], + $this->values[self::CUSTOMERS_LIST] + ); + } + + /** + * @inheritdoc + */ + public function getName() + { + return $this->translator->trans( + 'For one ore more customers', + [] + ); + } + + /** + * @inheritdoc + */ + public function getToolTip() + { + $toolTip = $this->translator->trans( + 'The coupon applies to some customers only', + [] + ); + + return $toolTip; + } + + /** + * @inheritdoc + */ + public function getSummary() + { + $i18nOperator = Operators::getI18n( + $this->translator, + $this->operators[self::CUSTOMERS_LIST] + ); + + $custStrList = ''; + + $custIds = $this->values[self::CUSTOMERS_LIST]; + + if (null !== $custList = CustomerQuery::create()->findPks($custIds)) { + /** @var Customer $cust */ + foreach ($custList as $cust) { + $custStrList .= $cust->getLastname() . ' ' . $cust->getFirstname() . ' ('.$cust->getRef().'), '; + } + + $custStrList = rtrim($custStrList, ', '); + } + + $toolTip = $this->translator->trans( + 'Customer is %op% %customer_list%', + [ + '%customer_list%' => $custStrList, + '%op%' => $i18nOperator + ] + ); + + return $toolTip; + } + + /** + * @inheritdoc + */ + protected function generateInputs() + { + return array( + self::CUSTOMERS_LIST => array( + 'availableOperators' => $this->availableOperators[self::CUSTOMERS_LIST], + 'value' => '', + 'selectedOperator' => Operators::IN + ) + ); + } + + /** + * @inheritdoc + */ + public function drawBackOfficeInputs() + { + return $this->facade->getParser()->render( + 'coupon/condition-fragments/customers-condition.html', + [ + 'operatorSelectHtml' => $this->drawBackOfficeInputOperators(self::CUSTOMERS_LIST), + 'customers_field_name' => self::CUSTOMERS_LIST, + 'values' => isset($this->values[self::CUSTOMERS_LIST]) ? $this->values[self::CUSTOMERS_LIST] : array() + ] + ); + } +} diff --git a/core/lib/Thelia/Condition/Implementation/MatchBillingCountries.php b/core/lib/Thelia/Condition/Implementation/MatchBillingCountries.php new file mode 100644 index 00000000..23b685e9 --- /dev/null +++ b/core/lib/Thelia/Condition/Implementation/MatchBillingCountries.php @@ -0,0 +1,94 @@ + + * + */ +class MatchBillingCountries extends AbstractMatchCountries +{ + /** + * @inheritdoc + */ + public function getServiceId() + { + return 'thelia.condition.match_billing_countries'; + } + + /** + * @inheritdoc + */ + public function isMatching() + { + if (null === $customer = $this->facade->getCustomer()) { + throw new UnmatchableConditionException(); + } + + $billingAddress = $customer->getDefaultAddress(); + + return $this->conditionValidator->variableOpComparison( + $billingAddress->getCountryId(), + $this->operators[self::COUNTRIES_LIST], + $this->values[self::COUNTRIES_LIST] + ); + } + + /** + * @inheritdoc + */ + public function getName() + { + return $this->translator->trans( + 'Billing country', + [] + ); + } + + /** + * @inheritdoc + */ + public function getToolTip() + { + $toolTip = $this->translator->trans( + 'The coupon applies to the selected billing countries', + [] + ); + + return $toolTip; + } + + protected function getSummaryLabel($cntryStrList, $i18nOperator) + { + return $this->translator->trans( + 'Only if order billing country is %op% %countries_list%', + [ + '%countries_list%' => $cntryStrList, + '%op%' => $i18nOperator + ] + ); + } + + protected function getFormLabel() + { + return $this->translator->trans( + 'Billing country is', + [] + ); + } +} diff --git a/core/lib/Thelia/Condition/Implementation/MatchDeliveryCountries.php b/core/lib/Thelia/Condition/Implementation/MatchDeliveryCountries.php new file mode 100644 index 00000000..b7468415 --- /dev/null +++ b/core/lib/Thelia/Condition/Implementation/MatchDeliveryCountries.php @@ -0,0 +1,96 @@ + + * + */ +class MatchDeliveryCountries extends AbstractMatchCountries +{ + /** + * @inheritdoc + */ + public function getServiceId() + { + return 'thelia.condition.match_delivery_countries'; + } + + /** + * @inheritdoc + */ + public function isMatching() + { + if (null === $customer = $this->facade->getCustomer()) { + throw new UnmatchableConditionException(); + } + + if (null === $deliveryAddress = $this->facade->getDeliveryAddress()) { + throw new UnmatchableConditionException(); + } + + return $this->conditionValidator->variableOpComparison( + $deliveryAddress->getCountryId(), + $this->operators[self::COUNTRIES_LIST], + $this->values[self::COUNTRIES_LIST] + ); + } + + /** + * @inheritdoc + */ + public function getName() + { + return $this->translator->trans( + 'Delivery country', + [] + ); + } + + /** + * @inheritdoc + */ + public function getToolTip() + { + $toolTip = $this->translator->trans( + 'The coupon applies to the selected delivery countries', + [] + ); + + return $toolTip; + } + + protected function getSummaryLabel($cntryStrList, $i18nOperator) + { + return $this->translator->trans( + 'Only if order shipping country is %op% %countries_list%', + [ + '%countries_list%' => $cntryStrList, + '%op%' => $i18nOperator + ] + ); + } + + protected function getFormLabel() + { + return $this->translator->trans( + 'Delivery country is', + [] + ); + } +} diff --git a/core/lib/Thelia/Condition/Implementation/MatchForEveryone.php b/core/lib/Thelia/Condition/Implementation/MatchForEveryone.php new file mode 100644 index 00000000..121afe3e --- /dev/null +++ b/core/lib/Thelia/Condition/Implementation/MatchForEveryone.php @@ -0,0 +1,117 @@ + + * + */ +class MatchForEveryone extends ConditionAbstract +{ + /** + * @inheritdoc + */ + public function __construct(FacadeInterface $facade) + { + // Define the allowed comparison operators + $this->availableOperators = []; + + parent::__construct($facade); + } + + /** + * @inheritdoc + */ + public function getServiceId() + { + return 'thelia.condition.match_for_everyone'; + } + + /** + * @inheritdoc + */ + public function setValidatorsFromForm(array $operators, array $values) + { + $this->operators = []; + $this->values = []; + + return $this; + } + + /** + * @inheritdoc + */ + public function isMatching() + { + return true; + } + + /** + * @inheritdoc + */ + public function getName() + { + return $this->translator->trans( + 'Unconditional usage', + [] + ); + } + + /** + * @inheritdoc + */ + public function getToolTip() + { + $toolTip = $this->translator->trans( + 'This condition is always true', + [] + ); + + return $toolTip; + } + + /** + * @inheritdoc + */ + public function getSummary() + { + $toolTip = $this->translator->trans( + 'Unconditionnal usage', + [] + ); + + return $toolTip; + } + + /** + * @inheritdoc + */ + protected function generateInputs() + { + return []; + } + + /** + * @inheritdoc + */ + public function drawBackOfficeInputs() + { + // No input + return ''; + } +} diff --git a/core/lib/Thelia/Condition/Implementation/MatchForTotalAmount.php b/core/lib/Thelia/Condition/Implementation/MatchForTotalAmount.php new file mode 100644 index 00000000..5ea5d39a --- /dev/null +++ b/core/lib/Thelia/Condition/Implementation/MatchForTotalAmount.php @@ -0,0 +1,224 @@ +, Franck Allimant + * + */ +class MatchForTotalAmount extends ConditionAbstract +{ + /** Condition 1st parameter : price */ + const CART_TOTAL = 'price'; + + /** Condition 1st parameter : currency */ + const CART_CURRENCY = 'currency'; + + public function __construct(FacadeInterface $facade) + { + // Define the allowed comparison operators + $this->availableOperators = [ + self::CART_TOTAL => [ + Operators::INFERIOR, + Operators::INFERIOR_OR_EQUAL, + Operators::EQUAL, + Operators::SUPERIOR_OR_EQUAL, + Operators::SUPERIOR + ], + self::CART_CURRENCY => [ + Operators::EQUAL, + ] + ]; + + parent::__construct($facade); + } + + /** + * @inheritdoc + */ + public function getServiceId() + { + return 'thelia.condition.match_for_total_amount'; + } + + /** + * @inheritdoc + */ + public function setValidatorsFromForm(array $operators, array $values) + { + $this + ->checkComparisonOperatorValue($operators, self::CART_TOTAL) + ->checkComparisonOperatorValue($operators, self::CART_CURRENCY); + + $this->isPriceValid($values[self::CART_TOTAL]); + + $this->isCurrencyValid($values[self::CART_CURRENCY]); + + $this->operators = array( + self::CART_TOTAL => $operators[self::CART_TOTAL], + self::CART_CURRENCY => $operators[self::CART_CURRENCY], + ); + $this->values = array( + self::CART_TOTAL => $values[self::CART_TOTAL], + self::CART_CURRENCY => $values[self::CART_CURRENCY], + ); + + return $this; + } + + /** + * Test if Customer meets conditions + * + * @return bool + */ + public function isMatching() + { + $condition1 = $this->conditionValidator->variableOpComparison( + $this->facade->getCartTotalTaxPrice(), + $this->operators[self::CART_TOTAL], + $this->values[self::CART_TOTAL] + ); + + if ($condition1) { + $condition2 = $this->conditionValidator->variableOpComparison( + $this->facade->getCheckoutCurrency(), + $this->operators[self::CART_CURRENCY], + $this->values[self::CART_CURRENCY] + ); + + if ($condition2) { + return true; + } + } + + return false; + } + + /** + * @inheritdoc + */ + public function getName() + { + return $this->translator->trans( + 'Cart total amount', + [] + ); + } + + /** + * @inheritdoc + */ + public function getToolTip() + { + $toolTip = $this->translator->trans( + 'Check the total Cart amount in the given currency', + [] + ); + + return $toolTip; + } + + /** + * @inheritdoc + */ + public function getSummary() + { + $i18nOperator = Operators::getI18n( + $this->translator, + $this->operators[self::CART_TOTAL] + ); + + $toolTip = $this->translator->trans( + 'If cart total amount is %operator% %amount% %currency%', + array( + '%operator%' => $i18nOperator, + '%amount%' => $this->values[self::CART_TOTAL], + '%currency%' => $this->values[self::CART_CURRENCY] + ) + ); + + return $toolTip; + } + + /** + * @inheritdoc + */ + protected function generateInputs() + { + $currencies = CurrencyQuery::create()->filterByVisible(true)->find(); + + $cleanedCurrencies = []; + + /** @var Currency $currency */ + foreach ($currencies as $currency) { + $cleanedCurrencies[$currency->getCode()] = $currency->getSymbol(); + } + + return array( + self::CART_TOTAL => array( + 'availableOperators' => $this->availableOperators[self::CART_TOTAL], + 'availableValues' => '', + 'value' => '', + 'selectedOperator' => '' + ), + self::CART_CURRENCY => array( + 'availableOperators' => $this->availableOperators[self::CART_CURRENCY], + 'availableValues' => $cleanedCurrencies, + 'value' => '', + 'selectedOperator' => Operators::EQUAL + ) + ); + } + + /** + * @inheritdoc + */ + public function drawBackOfficeInputs() + { + $labelPrice = $this->facade + ->getTranslator() + ->trans('Cart total amount is', []); + + $html = $this->drawBackOfficeBaseInputsText($labelPrice, self::CART_TOTAL); + + return $html; + } + + /** + * @inheritdoc + */ + protected function drawBackOfficeBaseInputsText($label, $inputKey) + { + return $this->facade->getParser()->render( + 'coupon/condition-fragments/cart-total-amount-condition.html', + [ + 'label' => $label, + 'inputKey' => $inputKey, + 'value' => isset($this->values[$inputKey]) ? $this->values[$inputKey] : '', + 'field_1_name' => self::CART_TOTAL, + 'field_2_name' => self::CART_CURRENCY, + 'operatorSelectHtml' => $this->drawBackOfficeInputOperators(self::CART_TOTAL), + 'currencySelectHtml' => $this->drawBackOfficeCurrencyInput(self::CART_CURRENCY), + ] + ); + } +} diff --git a/core/lib/Thelia/Condition/Implementation/MatchForXArticles.php b/core/lib/Thelia/Condition/Implementation/MatchForXArticles.php new file mode 100644 index 00000000..4af45add --- /dev/null +++ b/core/lib/Thelia/Condition/Implementation/MatchForXArticles.php @@ -0,0 +1,187 @@ +, Franck Allimant + * + */ +class MatchForXArticles extends ConditionAbstract +{ + /** Condition 1st parameter : quantity */ + const CART_QUANTITY = 'quantity'; + + /** + * @inheritdoc + */ + public function __construct(FacadeInterface $facade) + { + $this->availableOperators = array( + self::CART_QUANTITY => array( + Operators::INFERIOR, + Operators::INFERIOR_OR_EQUAL, + Operators::EQUAL, + Operators::SUPERIOR_OR_EQUAL, + Operators::SUPERIOR + ) + ); + + parent::__construct($facade); + } + + /** + * @inheritdoc + */ + public function getServiceId() + { + return 'thelia.condition.match_for_x_articles'; + } + + /** + * @inheritdoc + */ + public function setValidatorsFromForm(array $operators, array $values) + { + $this->checkComparisonOperatorValue($operators, self::CART_QUANTITY); + + if (\intval($values[self::CART_QUANTITY]) <= 0) { + throw new InvalidConditionValueException( + \get_class(), + 'quantity' + ); + } + + $this->operators = [ + self::CART_QUANTITY => $operators[self::CART_QUANTITY] + ]; + + $this->values = [ + self::CART_QUANTITY => $values[self::CART_QUANTITY] + ]; + + return $this; + } + + /** + * @inheritdoc + */ + public function isMatching() + { + $condition1 = $this->conditionValidator->variableOpComparison( + $this->facade->getNbArticlesInCart(), + $this->operators[self::CART_QUANTITY], + $this->values[self::CART_QUANTITY] + ); + + if ($condition1) { + return true; + } + + return false; + } + + /** + * @inheritdoc + */ + public function getName() + { + return $this->translator->trans( + 'Cart item count', + [] + ); + } + + /** + * @inheritdoc + */ + public function getToolTip() + { + $toolTip = $this->translator->trans( + 'The cart item count should match the condition', + [] + ); + + return $toolTip; + } + + /** + * @inheritdoc + */ + public function getSummary() + { + $i18nOperator = Operators::getI18n( + $this->translator, + $this->operators[self::CART_QUANTITY] + ); + + $toolTip = $this->translator->trans( + 'If cart item count is %operator% %quantity%', + array( + '%operator%' => $i18nOperator, + '%quantity%' => $this->values[self::CART_QUANTITY] + ) + ); + + return $toolTip; + } + + /** + * @inheritdoc + */ + protected function generateInputs() + { + return array( + self::CART_QUANTITY => array( + 'availableOperators' => $this->availableOperators[self::CART_QUANTITY], + 'value' => '', + 'selectedOperator' => '' + ) + ); + } + + /** + * @inheritdoc + */ + public function drawBackOfficeInputs() + { + $labelQuantity = $this->facade + ->getTranslator() + ->trans('Cart item count is'); + + $html = $this->drawBackOfficeBaseInputsText($labelQuantity, self::CART_QUANTITY); + + return $html; + } + + /** + * @inheritdoc + */ + protected function drawBackOfficeBaseInputsText($label, $inputKey) + { + return $this->facade->getParser()->render( + 'coupon/condition-fragments/cart-item-count-condition.html', + [ + 'label' => $label, + 'operatorSelectHtml' => $this->drawBackOfficeInputOperators($inputKey), + 'quantitySelectHtml' => $this->drawBackOfficeInputQuantityValues($inputKey, 20, 1) + ] + ); + } +} diff --git a/core/lib/Thelia/Condition/Implementation/MatchForXArticlesIncludeQuantity.php b/core/lib/Thelia/Condition/Implementation/MatchForXArticlesIncludeQuantity.php new file mode 100644 index 00000000..8eaa2fef --- /dev/null +++ b/core/lib/Thelia/Condition/Implementation/MatchForXArticlesIncludeQuantity.php @@ -0,0 +1,82 @@ + + */ +class MatchForXArticlesIncludeQuantity extends MatchForXArticles +{ + /** + * @inheritdoc + */ + public function getServiceId() + { + return 'thelia.condition.match_for_x_articles_include_quantity'; + } + + /** + * @inheritdoc + */ + public function getName() + { + return $this->translator->trans('Cart item include quantity count'); + } + + /** + * @inheritdoc + */ + public function isMatching() + { + return $this->conditionValidator->variableOpComparison( + $this->facade->getNbArticlesInCartIncludeQuantity(), + $this->operators[self::CART_QUANTITY], + $this->values[self::CART_QUANTITY] + ); + } + + /** + * @inheritdoc + */ + public function drawBackOfficeInputs() + { + $labelQuantity = $this->facade->getTranslator()->trans('Cart item include quantity count is'); + + return $this->drawBackOfficeBaseInputsText($labelQuantity, self::CART_QUANTITY); + } + + /** + * @inheritdoc + */ + public function getSummary() + { + $i18nOperator = Operators::getI18n( + $this->translator, + $this->operators[self::CART_QUANTITY] + ); + + $toolTip = $this->translator->trans( + 'If cart item (include quantity) count is %operator% %quantity%', + array( + '%operator%' => $i18nOperator, + '%quantity%' => $this->values[self::CART_QUANTITY] + ) + ); + + return $toolTip; + } +} diff --git a/core/lib/Thelia/Condition/Implementation/StartDate.php b/core/lib/Thelia/Condition/Implementation/StartDate.php new file mode 100644 index 00000000..c3c5018f --- /dev/null +++ b/core/lib/Thelia/Condition/Implementation/StartDate.php @@ -0,0 +1,184 @@ + + * + */ +class StartDate extends ConditionAbstract +{ + const START_DATE = 'start_date'; + + /** + * @inheritdoc + */ + public function __construct(FacadeInterface $facade) + { + $this->availableOperators = [ + self::START_DATE => [ + Operators::SUPERIOR_OR_EQUAL + ] + ]; + + parent::__construct($facade); + } + + /** + * @inheritdoc + */ + public function getServiceId() + { + return 'thelia.condition.start_date'; + } + + /** + * @inheritdoc + */ + public function setValidatorsFromForm(array $operators, array $values) + { + $this->checkComparisonOperatorValue($operators, self::START_DATE); + + if (! isset($values[self::START_DATE])) { + $values[self::START_DATE] = time(); + } + + // Parse the entered date to get a timestamp, if we don't already have one + if (!\is_int($values[self::START_DATE])) { + $date = \DateTime::createFromFormat($this->getDateFormat(), $values[self::START_DATE]); + + // Check that the date is valid + if (false === $date) { + throw new InvalidConditionValueException( + \get_class(), + self::START_DATE + ); + } + + $timestamp = $date->getTimestamp(); + } else { + $timestamp = $values[self::START_DATE]; + } + + $this->operators = [ self::START_DATE => $operators[self::START_DATE] ]; + $this->values = [ self::START_DATE => $timestamp ]; + + return $this; + } + + /** + * @inheritdoc + */ + public function isMatching() + { + return $this->conditionValidator->variableOpComparison( + time(), + $this->operators[self::START_DATE], + $this->values[self::START_DATE] + ); + } + + /** + * @inheritdoc + */ + public function getName() + { + return $this->translator->trans( + 'Start date', + [] + ); + } + + /** + * @inheritdoc + */ + public function getToolTip() + { + $toolTip = $this->translator->trans( + 'The coupon is valid after a given date', + [] + ); + + return $toolTip; + } + + /** + * @inheritdoc + */ + public function getSummary() + { + $date = new \DateTime(); + $date->setTimestamp($this->values[self::START_DATE]); + $strDate = $date->format($this->getDateFormat()); + + $toolTip = $this->translator->trans( + 'Valid only from %date% to the coupon expiration date', + [ + '%date%' => $strDate, + ], + 'condition' + ); + + return $toolTip; + } + + private function getDateFormat() + { + return DateTimeFormat::getInstance($this->facade->getRequest())->getFormat("date"); + } + + /** + * @inheritdoc + */ + protected function generateInputs() + { + return array( + self::START_DATE => array( + 'availableOperators' => $this->availableOperators[self::START_DATE], + 'value' => '', + 'selectedOperator' => Operators::SUPERIOR_OR_EQUAL + ) + ); + } + + /** + * @inheritdoc + */ + public function drawBackOfficeInputs() + { + if (isset($this->values[self::START_DATE])) { + $date = new \DateTime(); + + $date->setTimestamp($this->values[self::START_DATE]); + + $strDate = $date->format($this->getDateFormat()); + } else { + $strDate = ''; + } + + return $this->facade->getParser()->render('coupon/condition-fragments/start-date-condition.html', [ + 'fieldName' => self::START_DATE, + 'criteria' => Operators::SUPERIOR_OR_EQUAL, + 'dateFormat' => $this->getDateFormat(), + 'currentValue' => $strDate + ]); + } +} diff --git a/core/lib/Thelia/Condition/Operators.php b/core/lib/Thelia/Condition/Operators.php new file mode 100644 index 00000000..955859f5 --- /dev/null +++ b/core/lib/Thelia/Condition/Operators.php @@ -0,0 +1,108 @@ + + * + */ +abstract class Operators +{ + /** Param1 is inferior to Param2 */ + const INFERIOR = '<'; + /** Param1 is inferior to Param2 */ + const INFERIOR_OR_EQUAL = '<='; + /** Param1 is equal to Param2 */ + const EQUAL = '=='; + /** Param1 is superior to Param2 */ + const SUPERIOR_OR_EQUAL = '>='; + /** Param1 is superior to Param2 */ + const SUPERIOR = '>'; + /** Param1 is different to Param2 */ + const DIFFERENT = '!='; + /** Param1 is in Param2 */ + const IN = 'in'; + /** Param1 is not in Param2 */ + const OUT = 'out'; + + /** + * Get operator translation + * + * @param Translator $translator Provide necessary value from Thelia + * @param string $operator Operator const + * + * @return string + */ + public static function getI18n(Translator $translator, $operator) + { + $ret = $operator; + switch ($operator) { + case self::INFERIOR: + $ret = $translator->trans( + 'Less than', + [] + ); + break; + case self::INFERIOR_OR_EQUAL: + $ret = $translator->trans( + 'Less than or equals', + [] + ); + break; + case self::EQUAL: + $ret = $translator->trans( + 'Equal to', + [] + ); + break; + case self::SUPERIOR_OR_EQUAL: + $ret = $translator->trans( + 'Greater than or equals', + [] + ); + break; + case self::SUPERIOR: + $ret = $translator->trans( + 'Greater than', + [] + ); + break; + case self::DIFFERENT: + $ret = $translator->trans( + 'Not equal to', + [] + ); + break; + case self::IN: + $ret = $translator->trans( + 'In', + [] + ); + break; + case self::OUT: + $ret = $translator->trans( + 'Not in', + [] + ); + break; + default: + } + + return $ret; + } +} diff --git a/core/lib/Thelia/Condition/SerializableCondition.php b/core/lib/Thelia/Condition/SerializableCondition.php new file mode 100644 index 00000000..a214d7f0 --- /dev/null +++ b/core/lib/Thelia/Condition/SerializableCondition.php @@ -0,0 +1,32 @@ + + * + */ +class SerializableCondition +{ + /** @var string Condition Service id */ + public $conditionServiceId = null; + + /** @var array Operators set by Admin for this Condition */ + public $operators = []; + + /** @var array Values set by Admin for this Condition */ + public $values = []; +} diff --git a/core/lib/Thelia/Config/DatabaseConfiguration.php b/core/lib/Thelia/Config/DatabaseConfiguration.php new file mode 100644 index 00000000..1a12a6f9 --- /dev/null +++ b/core/lib/Thelia/Config/DatabaseConfiguration.php @@ -0,0 +1,105 @@ +root('database'); + $databaseNodeBuilder = $databaseNode->children(); + + $connectionNode = $this->buildConnectionNode('connection', false); + $databaseNodeBuilder->append($connectionNode); + + $connectionsNode = $this->buildConnectionNode('connections', true); + $connectionsNode + ->validate() + ->ifTrue( + function ($connections) { + return !isset($connections[static::THELIA_CONNECTION_NAME]); + } + ) + ->thenInvalid( + "The '" . static::THELIA_CONNECTION_NAME . "' connection must be defined." + ); + $databaseNodeBuilder->append($connectionsNode); + + $databaseNode + ->validate() + ->ifTrue( + function ($database) { + return !empty($database['connection']) && !empty($database['connections']); + } + ) + ->thenInvalid( + "The 'database' node must contain either a 'connection' node or a 'connections' node, but not both." + ); + + return $treeBuilder; + } + + /** + * Build a configuration node describing one or more database connection + * @param string $rootName Node name. + * @param bool $isArray Whether the node is a single connection or an array of connections. + * @return ArrayNodeDefinition|NodeDefinition Connection(s) node. + */ + public function buildConnectionNode($rootName, $isArray) + { + $treeBuilder = new TreeBuilder(); + $connectionNode = $treeBuilder->root($rootName); + if ($isArray) { + /** @var ArrayNodeDefinition $connectionNodePrototype */ + $connectionNodePrototype = $connectionNode->prototype('array'); + $connectionNodeBuilder = $connectionNodePrototype->children(); + } else { + $connectionNodeBuilder = $connectionNode->children(); + } + + $connectionNodeBuilder->scalarNode('driver') + ->defaultValue('mysql'); + + $connectionNodeBuilder->scalarNode('user') + ->defaultValue('root'); + + $connectionNodeBuilder->scalarNode('password') + ->defaultValue(''); + + $connectionNodeBuilder->scalarNode('dsn') + ->cannotBeEmpty(); + + $connectionNodeBuilder->scalarNode('classname') + ->defaultValue('\Propel\Runtime\Connection\ConnectionWrapper'); + + return $connectionNode; + } +} diff --git a/core/lib/Thelia/Config/DatabaseConfigurationSource.php b/core/lib/Thelia/Config/DatabaseConfigurationSource.php new file mode 100644 index 00000000..a94650b7 --- /dev/null +++ b/core/lib/Thelia/Config/DatabaseConfigurationSource.php @@ -0,0 +1,140 @@ + connection ParameterBag]. + * @var array + */ + protected $connections; + + /** + * @param array $theliaDatabaseConfiguration Thelia database configuration. + * @param array $envParameters Environment parameters. + */ + public function __construct( + array $theliaDatabaseConfiguration, + array $envParameters + ) { + $configurationProcessor = new Processor(); + $configuration = $configurationProcessor->processConfiguration( + new DatabaseConfiguration(), + $theliaDatabaseConfiguration + ); + + if (isset($configuration['connection'])) { + // single connection format + $this->addConnection( + DatabaseConfiguration::THELIA_CONNECTION_NAME, + $configuration['connection'], + $envParameters + ); + } elseif (isset($configuration['connections'])) { + // multiple connections format + foreach ($configuration['connections'] as $connectionName => $connectionParameters) { + $this->addConnection( + $connectionName, + $connectionParameters, + $envParameters + ); + } + } else { + throw new \LogicException( + "No 'connection' or 'connections' node under the 'database' node." + . " This is checked at configuration validation, and should not happen." + ); + } + + if (!isset($this->connections[DatabaseConfiguration::THELIA_CONNECTION_NAME])) { + throw new \LogicException( + "Connection '" . DatabaseConfiguration::THELIA_CONNECTION_NAME . "' is not defined." + . " This is checked at configuration validation, and should not happen." + ); + } + } + + /** + * Create and resolve a ParameterBag for a connection. + * Add the bag to the connections map. + * @param string $name Connection name. + * @param array $parameters Connection parameters. + * @param array $envParameters Environment parameters. + */ + protected function addConnection($name, array $parameters = [], array $envParameters = []) + { + $connectionParameterBag = new ParameterBag($envParameters); + $connectionParameterBag->add($parameters); + $connectionParameterBag->resolve(); + $this->connections[$name] = $connectionParameterBag; + } + + /** + * @return array Propel configuration values. + */ + public function getPropelConnectionsConfiguration() + { + $propelConnections = []; + /** + * @var string $connectionName + * @var ParameterBag $connectionParameterBag + */ + foreach ($this->connections as $connectionName => $connectionParameterBag) { + $propelConnections[$connectionName] = [ + 'adapter' => $connectionParameterBag->get('driver'), + 'dsn' => $connectionParameterBag->get('dsn'), + 'user' => $connectionParameterBag->get('user'), + 'password' => $connectionParameterBag->get('password'), + 'classname' => $connectionParameterBag->get('classname'), + 'settings' => [ + 'queries' => [ + "SET NAMES 'UTF8'", + ], + ], + ]; + } + + $propelConfiguration = []; + $propelConfiguration['propel']['database']['connections'] = $propelConnections; + $propelConfiguration['propel']['runtime']['defaultConnection'] = DatabaseConfiguration::THELIA_CONNECTION_NAME; + + return $propelConfiguration; + } + + /** + * @return \PDO Thelia database connection. + * @throws \PDOException + */ + public function getTheliaConnectionPDO() + { + /** @var ParameterBag $theliaConnectionParameterBag */ + $theliaConnectionParameterBag = $this->connections[DatabaseConfiguration::THELIA_CONNECTION_NAME]; + + return new \PDO( + $theliaConnectionParameterBag->get('dsn'), + $theliaConnectionParameterBag->get('user'), + $theliaConnectionParameterBag->get('password'), + [ + \PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES 'UTF8'", + ] + ); + } +} diff --git a/core/lib/Thelia/Config/I18n/ar_SA.php b/core/lib/Thelia/Config/I18n/ar_SA.php new file mode 100644 index 00000000..923b0fbb --- /dev/null +++ b/core/lib/Thelia/Config/I18n/ar_SA.php @@ -0,0 +1,404 @@ + ' content creation form', + ' note: only non-visible documents can be associated.' => ' ملاحظة: فقط الوثائق غير مرئية يمكن أن يرتبط بها.', + '"%param" parameter cannot be empty in loop type: %type, name: %name' => 'لا يمكن إبقاء حقل النوع %param و حقل الإسم %name فارغاً', + '"%param" parameter is missing in loop type: %type, name: %name' => '%param حقل النوع %type أو حقل الإسم %name مفقود', + '%module (version: %version)' => 'الوحدة النمطية % (الإصدار: الإصدار %)', + '%obj SEO modification' => 'تعديل هدف %obj المسئول الاقتصادي', + '%obj creation' => '%obj إنشاء', + '%obj modification' => '%obj تعديل', + '%obj%s deleted successfully' => '%obj%s تم الحذف بنجاح', + '%s has dependency to module %s. You have to deactivate this module before.' => '%s يحتوي تبعية للوحده النمطيه %s. يجب عليك تعطيل هذه الوحدة اولا.', + '%s have dependencies to module %s. You have to deactivate these modules before.' => '%s لها تبعيات للوحدة النمطية %s. يجب عليك تعطيل هذه الوحدات المعروضة.', + '%type% position updated' => '%type% تم تحديث الموضع', + '%type% visibility updated' => '%type% تم تحديث الرؤية', + 'A comma separated list of email addresses' => 'قائمة عناوين بريد الكتروني مفصولة بفاصلة', + 'A currency with code "%name" already exists.' => 'بعمله مع رمز "%name" موجود بالفعل.', + 'A descriptive title' => 'عنوان تفصيلي', + 'A message with name "%name" already exists.' => 'رسالة باسم "%name" موجودة بالفعل .', + 'A name such as Europe or Overseas' => 'اسم مثل أوروبا أو الخارج', + 'A product with reference %ref already exists. Please choose another reference.' => 'مرجع المنتج % ref متوفر بالفعل ، الرجاء اختيار مرجع آخر .', + 'A short description, used when a summary or an introduction is required' => 'وصف قصير، يستخدم عند طلب ملخص أو مقدمة', + 'A short text, used when an additional or supplemental information is required.' => 'نص قصير، يستخدم عند طلب معلومات إضافية.', + 'A user already exists with this email address. Please login or if you\'ve forgotten your password, go to Reset Your Password.' => 'هذا المستخدم موجود بالفعل مع عنوان هذا البريد الإلكتروني ، الرجاء تسجيل الدخول أو إذا كنت قد نسيت كلمة المرور الخاصة بك ، انتقل إلى "إعادة تعيين كلمة المرور الخاصة بك" .', + 'A value for attribute "%name" is already present in the combination' => 'القيمة للسمة "%name" موجودة بالفعل في المجموع', + 'A variable with name "%name" already exists.' => 'الاسم الظاهر متغير مع اسم "%name" موجود مسبقاً .', + 'Activate logs only for these IP Addresses' => 'تفعيل سجلات لعناوين IP هذه فقط', + 'Activate logs only for these files' => 'تنشيط سجلات لهذه الملفات فقط', + 'Activate this sale' => 'قم بتغعيل هذا الخصم', + 'Active' => 'مفعل', + 'Add to all product templates' => 'إضافة إلى كافة قوالب المنتج', + 'Additional address' => 'عنوان إضافي', + 'Additional address information' => 'معلومات العنوان الإضافية', + 'Address ID not found' => 'لم يتم العثور على معرف العنوان', + 'Address Line 2' => 'سطر العنوان 2', + 'Address Line 3' => 'سطر العنوان 3', + 'Address creation' => 'إنشاء العنوان', + 'Address label' => 'تعريف العنوان', + 'Address update' => 'تحديث العنوان', + 'Address.' => 'العنوان.', + 'Administrator' => 'المدير', + 'Administrator ID not found' => 'لم يتم العثور على معرف المسؤول', + 'Administrators' => 'المسؤولين', + 'Advertise this product as new' => 'الإعلان عن هذا المنتج كمنتج جديد', + 'Alerts' => 'تنبيهات', + 'All Products' => 'جميع المنتجات', + 'All countries' => 'كافة الدول', + 'All shipping methods' => 'جميع وسائل النقل', + 'Amount' => 'القيمة', + 'Apply exchange rates on price in %sym' => 'تطبيق أسعار الصرف في السعر %sym', + 'Archive Format' => 'شكل الأرشيف', + 'Associate documents' => 'ربط المستندات', + 'Associate images' => 'ربط الصور', + 'At least one of cart products categories is %op% %categories_list%' => 'هناك فئه من فئات منتجات العربة وهي %op% %categories_list%', + 'Attribut' => 'سمة', + 'Attribute ID:Attribute AV ID' => 'معرف السمة : معرف السمة AV', + 'Attribute value' => 'مقدار السمة', + 'Attributes' => 'عنوان الصفحة', + 'Attributes value' => 'مقدار السمات', + 'Auth mode' => 'وضع المصادقة', + 'Available quantity' => 'الكمية المتوفرة', + 'Available quantity *' => 'الكمية المتوفرة *', + 'Available shipping zones' => 'مناطق الشحن المتاحة', + 'Back Office' => 'ادارة النظام', + 'Bad tax list JSON' => 'قائمة الضرائب السيئة JSON', + 'Billing country' => 'دولة إرسال الفاتوره', + 'Billing country is' => 'دولة إرسال الفاتوره هي', + 'Brand' => 'العلامة التجارية', + 'Brand / Supplier' => 'مورد/ العلامة التجارية', + 'Brand name' => 'إسم العلامة التجارية', + 'Brands' => 'العلامات التجارية', + 'Business ID' => 'معرف وحدة الأعمال', + 'By Module' => 'من الوحدة النمطية', + 'CSS' => 'CSS', + 'CSS stylesheet' => 'ملفات CSS', + 'Cannot find a default country. Please define one.' => 'لا يمكن العثور على عنوان البلد الافتراضي ، الرجاء تحديد عنوان بلد آخر.', + 'Cannot find the shop country. Please select a shop country.' => 'لا يمكن العثور على بلد المحل ، الرجاء تحديد محل في بلد آخر.', + 'Cannot instantiate module "%name%": the namespace is null. Maybe the model is not loaded ?' => 'لا يمكن إنشاء الوحدة النمطية "%name%": مساحة اسم فارغة. ربما لم يتم تحميل النموذج؟', + 'Cart' => 'السله', + 'Cart contains at least a product %op% %products_list%' => 'العربة تحتوي على منتج واحد على الاقل %op% %products_list%', + 'Cart contains categories condition' => 'العربه تحتوي على شرط الفئات', + 'Cart contains specific products' => 'العربه تحتوي على منتجات محددة', + 'Cart item count' => 'عدد العناصر في العربة', + 'Cart item count is' => 'عدد العناصر في السلة', + 'Cart total amount' => 'المبلغ الإجمالي للعربة', + 'Cart total amount is' => 'إجمالي المبلغ في السلة', + 'Catalog' => 'دليل', + 'Catalog configuration' => 'إعدادات البيان المصور (الكتالوج)', + 'Categories' => 'الفئات', + 'Category' => 'الفئة', + 'Category page' => 'صفحة الفئات', + 'Category title' => 'عنوان الفئة', + 'Cellphone' => 'الهاتف المحمول', + 'Check the total Cart amount in the given currency' => 'التحقق من المبلغ الإجمالي في السلة بالعملة المحددة', + 'City' => 'المدينة', + 'Code' => 'الرمز', + 'Combination builder' => 'منشئ مجموعة', + 'Compagny' => 'الكيماويات', + 'Company' => 'شركة', + 'Company Name' => 'اسم الشركة', + 'Conclusion' => 'استنتاج', + 'Configuration' => 'لوحة التحكم', + 'Constant amount' => 'المبلغ الثابت', + 'Constant amount found in one of the product\'s feature' => 'المبلغ الثابت موجود في ميزة واحدة من المنتج', + 'Content title *' => 'عنوان المحتوى *', + 'Countries' => 'البلدان', + 'Country' => 'الدولة', + 'Country ID not found' => 'لم يتم العثور على معرف البلد', + 'Country title' => 'عنوان البلد', + 'Coupon' => 'قسيمة خصم', + 'Critical' => 'الحرجة', + 'Currency' => 'عملة', + 'Currency name' => 'اسم العملة', + 'Current Password' => 'كلمة السر الحالية', + 'Customer' => 'العميل', + 'Customers' => 'العملاء', + 'Dashboard' => 'لوحة المعلومات', + 'Date \'%date\' is invalid, please enter a valid date using %fmt format' => 'التاريخ \'%date\' غير صالح ، الرجاء إدخال تاريخ صحيح باستخدام المنسق %fmt', + 'Debug' => 'التصحيح', + 'Default folder *' => 'المجلد الافتراضي *', + 'Default product category *' => 'فئة المنتج الافتراضي *', + 'Default product sale element' => 'عنصر بيع المنتج الافتراضي', + 'Delivery module ID not found' => 'لم يتم العثور على معرف الوحدة النمطية للتسليم', + 'Detailed description' => 'وصف مفصل', + 'Disabled' => 'تعطيل', + 'EAN Code' => 'كود EAN', + 'Edit' => 'تحرير', + 'Email Address' => 'عنوان البريد الإلكتروني', + 'Email address' => 'عنوان البريد الإلكتروني', + 'Emergency' => 'حالات الطوارئ', + 'Enable remote SMTP use' => 'تمكين استخدام SMTP البعيد', + 'Encryption' => 'التشفير', + 'Error during %action process : %error. Exception was %exc' => 'حدث خطأ أثناء العملية %action: %error. وكان الاستثناء هو %exc', + 'Error occured while processing order ref. %ref, ID %id: %err' => 'حدث خطأ أثناء معالجة أمر الرقم % ref ، معرف %id: %err', + 'Errors' => 'أخطاء', + 'Failed to create instance of module "%name%" when trying to delete module. Module directory has probably been deleted' => 'فشل في إنشاء مثيل من الوحدة النمطية "%name%" عند محاولة حذف الوحدة النمطية. ربما تم حذف دليل الوحدة النمطية', + 'Failed to find a payment Module with ID=%mid for order ID=%oid' => 'فشل في العثور على معرف الدفع ID=%mid لمعرف الطلب ID =%oid', + 'Failed to open translation file %file. Please be sure that this file is writable by your Web server' => 'فشل في فتح %file ملف الترجمة ، الرجاء التأكد من أن هذا الملف قابل لللكتابة فيه بواسطة خادم الاستضافة الخاص بك', + 'Failed to update language definition: %ex' => 'فشل تحديث تعريف اللغة: %ex', + 'Fax' => 'فاكس', + 'Feature value does not match FLOAT format' => 'قيمة السمة لا تتطابق مع عدد التنسيق العشري', + 'Features value' => 'عدد الميزات', + 'File format' => 'صيغة الملف', + 'File is too large, please retry with a file having a size less than %size%.' => 'حجم الملف كبير جداً، الرجاء إعادة المحاولة مع ملف بحجم أقل من %size%.', + 'File to upload' => 'ملف التحميل', + 'Files with the following extension are not allowed: %extension, please do an archive of the file if you want to upload it' => 'الملفات ذات الملحق التالي: %extension غير مسموحة، الرجاء حفظ الملف بأرشيف إذا كنت تريد تحميله', + 'First Name' => 'الاسم الأول', + 'Firstname' => 'الاسم الأول', + 'Fixed Amount Discount' => 'مبلغ الخصم الثابت', + 'Fixed amount discount for selected attribute values' => 'خصم مبلغ ثابت اقدار السمة المحددة', + 'Fixed amount discount for selected categories' => 'خصم مبلغ ثابت للفئات المختارة', + 'Fixed amount discount for selected products' => 'خصم مبلغ ثابت للمنتجات المختارة', + 'Folder' => 'مجلّد', + 'Folder page' => 'صفحة المجلد', + 'Folder title *' => 'عنوان المجلد *', + 'For one ore more customers' => 'لعميل او اكثر', + 'Free product when buying one or more selected products' => 'منتج مجاني عند شراء قطعة أو أكثر من منتجات محدده', + 'Front Office' => 'الواجهة', + 'Full Name' => 'الاسم الكامل', + 'Greater than' => 'أكبر من', + 'Greater than or equals' => 'أكبر من أو يساوي', + 'HTML Message' => 'رسالة بتنسيق HTML', + 'HTML layout' => 'تصميم HTML', + 'Home' => 'صفحة البداية', + 'Home page' => 'الصفحة الرئيسية', + 'Hook' => 'هوك', + 'Hook block' => 'ربط كتلة', + 'Hook code' => 'ربط الرمز', + 'Hook create form' => 'ربط استمارة الانشاء', + 'Hook title' => 'ربط عنوان', + 'Hooks' => 'روابط', + 'Host' => 'المضيف / Host', + 'I would like to receive the newsletter or the latest news.' => 'أود أن أتلقى رسائل اخبارية للمستجدات.', + 'ISO 639-1 Code' => 'رمز الأيزو 639-1', + 'ISO Alpha-2 code' => 'رمز ISO ألفا-2', + 'ISO Alpha-3 code' => 'رمز ISO ألفا-2', + 'If a translation is missing or incomplete :' => 'إذا كانت الترجمة مفقودة أو غير كاملة:', + 'If cart item count is %operator% %quantity%' => 'إذا كان عدد العناصر في السلة %operator% %quantity%', + 'If cart total amount is %operator% %amount% %currency%' => 'إذا كان المبلغ الإجمالي في السلة %operator% %amount% %currency%', + 'If checked, this hook will be used by a hook block. If not, by hook function.' => 'إذا تم اختيار الربط، سيتم استخدام هذا الربط بكتلة ربط. إذا لم يكن الأمر كذلك، سيتم عن طريق وظيفة ربط.', + 'Image' => 'صورة', + 'Impossible to delete a customer who already have orders' => 'من المستحيل حذف العملاء الذين لديهم طلبات مسبقة', + 'In' => 'في', + 'Include documents' => 'الملفات المرفقة', + 'Include images' => 'الصور المرفقة', + 'Information' => 'معلومات', + 'Invalid product_sale_elements' => 'Product_sale_elements غير صالحة', + 'Invalid value "%value" for "%param" parameter in loop type: %type, name: %name' => 'قيمة غير صالحة "value%" لـ "%param" في حلقة النوع: type% ، والاسم: %name', + 'Invalid value for walkMode parameter: %value' => 'قيمة غير صالحة للـ walkMode علامة: %value', + 'Invoice' => 'الفاتورة', + 'Invoice choice' => 'خيار الفاتورة', + 'Is it the default product sale element ?' => 'هل هو عنصر بيع لمنتج افتراضي؟', + 'It is not allowed to delete the default currency' => 'لا يسمح بحذف العملة الرئيسية', + 'It is not allowed to delete the default language' => 'لا يسمح بحذف اللغة الرئيسية', + 'JavaScript' => 'جافا سكريبت', + 'Keep the most important part of your description in the first 150-160 characters.' => 'قم بصياغة أهم جزء من الوصف الخاص بك بالأحرف 150-160 الأولى.', + 'Language' => 'اللّغة', + 'Language name' => 'اسم اللغة', + 'Last Name' => 'الاسم الأخير', + 'Lastname' => 'الإسم الأخير', + 'Layout' => 'مخطط التصميم', + 'Less than' => 'أقل من', + 'Less than or equals' => 'أقل من أو يساوي', + 'Log format *' => 'تنسيق السجل *', + 'Log level *' => 'مستوى التسجيل *', + 'Login failed. Please check your username and password.' => 'فشل في تسجيل الدخول . الرجاء التحقق من اسم المستخدم وكلمة المرور الخاصة بك .', + 'Login page' => 'صفحة تسجيل الدّخول', + 'Logs' => 'السجلات', + 'Loop cannot implements multiple Search Interfaces : `PropelSearchLoopInterface`, `ArraySearchLoopInterface`' => 'لا يمكن أن تقوم بتنفيذ بحث في حلقات متعددة "واجهات البحث":`PropelSearchLoopInterface`, `ArraySearchLoopInterface`', + 'Loop must implements \'PropelSearchLoopInterface\' to be timestampable' => 'يجب أن تنفذ حلقة \'PropelSearchLoopInterface\' كي تكون متواقته', + 'Loop must implements \'PropelSearchLoopInterface\' to be versionable' => 'يجب أن تنفذ حلقة \'PropelSearchLoopInterface\' كي يتم نشرها', + 'Loop must implements one of the following interfaces : `PropelSearchLoopInterface`, `ArraySearchLoopInterface`' => 'يجب تنفيذ حلقة واحدة من الواجهات التالية: `PropelSearchLoopInterface`, `ArraySearchLoopInterface`', + 'Lost password' => 'فقدت كلمة المرور', + 'Mail template name' => 'اسم قالب البريد', + 'Mail template purpose' => 'الغرض من قالب البريد', + 'Main address' => 'العنوان الرئيسي', + 'Main area' => 'المساحة الرئيسية', + 'Make sure it uses keywords found within the page itself.' => 'تأكد من أنها تستخدم الكلمات ذات الدلالات المجدية الموجودة في نفس الصفحة.', + 'Make sure that your title is clear, and contains many of the keywords within the page itself.' => 'تأكد من أن العنوان الخاص بك واضح، ويحتوي على العديد من الكلمات ذات الدلالات المجدية ضمن نفس الصفحة.', + 'Make this address as my primary address' => 'جعل هذا العنوان كعنوان بريدي أساسي', + 'Maximum usage count reached for coupon %code' => 'لقد بلغ عدد مرات استخدام القسيم ة%code الحد الأقصى', + 'Message' => 'الرسالة', + 'Message name' => 'اسم الرسالة', + 'Message subject' => 'موضوع الرسالة', + 'Messages' => 'الرسائل', + 'Meta Description' => 'وصف مبسط', + 'Meta Keywords' => 'كلمات رئيسية مبسطه', + 'Method Name' => 'اسم الأسلوب', + 'Missing or invalid data: %s' => 'بيانات مفقودة أو غير صحيحة: %s', + 'Module ID not found' => 'لم يتم العثور على معرف الوحدة النمطية', + 'Name' => 'الإسم', + 'Name *' => 'الإسم *', + 'Name of the HTML layout file' => 'اسم ملف تخطيط HTML', + 'Name of the HTML template file' => 'اسم ملف قالب HTML', + 'Name of the text layout file' => 'اسم ملف تخطيط النص', + 'Name of the text template file' => 'اسم ملف قالب النص', + 'New Password' => 'كلمة المرور الجديدة', + 'No %obj was created.' => 'لا %obj تم عمله.', + 'No %obj was updated.' => 'لم يتم تحديث %obj.', + 'No module found for code \'%item\'' => 'لا توجد وحدة للتعليمات البرمجية \'%item\'', + 'No, I am a new customer.' => 'لا، أنا عميل جديد.', + 'Not in' => 'ليس', + 'Notices' => 'إشعارات', + 'Order address ID not found' => 'لم يتم العثور على عنوان الطلب', + 'Order ref. %ref is now unpaid.' => 'رقم الطلب % ref لم يسدد بعد.', + 'Order ref. %ref, ID %id has been successfully paid.' => 'طلب رقم % ref، معرف %id قد تم دفعه / تسديده بنجاح.', + 'Page Title' => 'عنوان الصفحة', + 'Parent folder *' => 'المجلد الأصل *', + 'Password' => 'كلمة المرور', + 'Password *' => 'كلمة المرور *', + 'Password confirmation' => 'تأكيد كلمة السر', + 'Percentage of the product price' => 'النسبة المئوية لسعر المنتج', + 'Phone' => 'الهاتف', + 'Please accept the Terms and conditions in order to register.' => 'الرجاء قراءة الشروط و الأحكام و الموافقة عليه من أجل التسجيل.', + 'Please check your input: %error' => 'الرجاء التحقق من المدخلات الخاصة بك: %error', + 'Please enter your email address' => 'الرجاء إدخال عنوان بريدك الإلكتروني', + 'Please enter your password' => 'الرجاء ادخال كلمة المرور الخاصة بك', + 'Port' => 'منفذ Port', + 'Postage' => 'الارسالية', + 'Preferred locale' => 'اللغة المفضلة', + 'Prevent mailing template modification or deletion, except for super-admin' => 'منع تعديل أو حذف قالب البريد ، باستثناء المشرف الأساسي', + 'Prevent variable modification or deletion, except for super-admin' => 'منع التعديل أو الحذف ، باستثناء المشرف الأساسي', + 'Price currency *' => 'سعر العملة *', + 'Processing cancelation of payment for order ref. %ref' => 'جاري إلغاء الدفع للطلب رقم %ref', + 'Processing confirmation of order ref. %ref, ID %id' => 'جاري استكمال اجراءات الدفع للطلب رقم ref% ، %id', + 'Prodcut ID *' => 'رقم تعريف المنتج', + 'Product ID' => 'رقم تعريف المنتج', + 'Product ID *' => 'رقم تعريف المنتج *', + 'Product base price excluding taxes *' => 'سعر المنتج الأساسي باستثناء الضرائب *', + 'Product base price with taxes' => 'سعر المنتج الأساسي مع الضرائب', + 'Product price excluding taxes' => 'سعر المنتج باستثناء الضرائب', + 'Product price excluding taxes *' => 'سعر المنتج باستثناء الضرائب *', + 'Product price including taxes' => 'سعر المنتج مع الضرائب', + 'Product reference *' => 'مرجعية المنتج *', + 'Product sale element ID *' => 'معرف عنصر بيع المنتج *', + 'Product template' => 'قالب المنتج', + 'ProductSaleElement modification' => 'تعديل ProductSaleElement', + 'Profile' => 'الملف الشخصي', + 'Profile Code' => 'المدونة الشخصية', + 'Profile ID not found' => 'معرف التشكيل الجانبي غير متوفر', + 'Profile `code` already exists' => 'رمز الملف الشخصي \'code\' موجود بالفعل', + 'Purpose *' => 'الغرض *', + 'Quantity' => 'الكمية', + 'Redirecting ...' => 'إعادة التحويل...', + 'Redirecting to %url' => 'إعادة التحويل إلى %url', + 'Reference' => 'مرجع', + 'Reference *' => 'مرجع *', + 'Register' => 'إنشاء حساب', + 'Remember me ?' => 'تذكرني ؟', + 'Remove X percent to total cart' => 'إزالة X في المائة إلى إجمالي السلة', + 'Replace by the default language' => 'استبدال باللغة الافتراضية', + 'Replace current document by this file' => 'استبدال الوثيقة الحالية بهذا الملف', + 'Replace current image by this file' => 'استبدال الصورة الحالية بهذا الملف', + 'Rewriten URL' => 'اعادة كتابة URL', + 'Rotated Text File' => 'تدوير ملف النص', + 'Sale price excluding taxes' => 'سعر البيع باستثناء الضرائب', + 'Sale price including taxes' => 'سعر البيع بما في ذلك الضرائب', + 'Search' => 'بحث', + 'Select the brand logo' => 'حدد شعار العلامة التجارية', + 'Select the brand logo amongst the brand images' => 'حدد شعار العلامة التجارية من بين صور العلامة التجارية', + 'Select the categories of the products covered by this operation' => 'حدد فئات المنتجات التي تشملها هذه العملية', + 'Select the countries to delete from this shipping zone' => 'حدد البلدان للحذف من منطقة الشحن', + 'Select the countries to include in this shipping zone' => 'حدد البلدان للادراج في منطقة الشحن', + 'Select the discount type that will be applied to original product prices' => 'حدد نوع الخصم الذي سيتم تطبيقه على أسعار المنتج الأصلي', + 'Select the parent category of this category.' => 'حدد فئة الأصل من هذه الفئة.', + 'Select the product attributes included in this operation' => 'حدد سمات المنتج المدرجة في هذه العملية', + 'Select the product brand, or supplier.' => 'حدد المنتج العلامة التجارية، أو المورد.', + 'Select the products covered by this operation' => 'حدد المنتجات التي تشملها هذه العملية', + 'Select the virtual document' => 'حدد المستند الافتراضي', + 'Service ID' => 'معرف الخدمة', + 'Shipping zone name' => 'اسم منطقة الشحن', + 'Short additional text' => 'نصوص إضافية قصيرة', + 'Short description text' => 'نص الوصف القصير', + 'Show redirections *' => 'إظهار عمليات إعادة التوجيه *', + 'Sitemap' => 'خريطة الموقع', + 'Sorry, an error occured.' => 'عذراً، حدث خطأ.', + 'Sorry, an error occured: %msg' => 'عذراً، حدث خطأ: % msg', + 'Sorry, an error occured: %s' => 'عذراً، حدث خطأ: %s', + 'Sorry, an error occurred: %err' => 'عذراً، حدث خطأ: %err', + 'Sorry, you are not allowed to perform this action.' => 'آسف، غير مسموح لك بتنفيذ هذا الإجراء.', + 'Sorry, you\'re not allowed to perform this action' => 'آسف، غير مسموح لك بتنفيذ هذا الإجراء', + 'Source IP' => 'مصدر IP', + 'Start date' => 'تاريخ بداية النشر', + 'Start date of sales' => 'تاريخ البدء للمبيعات', + 'Store Business Identification Number (SIRET, etc).' => 'تخزين "رقم تعريف الأعمال التجارية" (SIRET، إلخ).', + 'Store Information' => 'تخزين المعلومات', + 'Store configuration failed.' => 'فشل في تكوين مخزن.', + 'Store description' => 'وصف المتجر', + 'Store email address' => 'تخزين عنوان البريد الإلكتروني', + 'Store logs into text file' => 'تخزين السجلات بصيغة ملف نصي', + 'Store logs into text file, up to a certian size, then a new file is created' => 'تخزين سجلات إلى ملف نصي، تصل إلى حجم معين، ثم يتم إنشاء ملف جديد آخر', + 'Store name' => 'اسم المخزن', + 'Street Address' => 'عنوان الشارع', + 'Street Address ' => 'عنوان الشارع ', + 'Strictly use the requested language' => 'استخدام اللغة المطلوبة بدقة', + 'Subject' => 'الموضوع', + 'Summary' => 'الملخص', + 'System' => 'نظام', + 'System configuration' => 'إعدادات النظام', + 'System log configuration failed.' => 'فشل تكوين سجل النظام.', + 'Tax ID not found in tax list JSON' => 'معرف الضريبة غير موجود في قائمة الضرائب JSON', + 'Tax list is not valid JSON' => 'قائمة الضرائب ليست JSON صالحة', + 'Tax rule ID not found' => 'لم يتم العثور على معرف القاعدة الضريبية', + 'Tax rule for this product *' => 'القاعدة الضريبية لهذا المنتج *', + 'Template' => 'قالب', + 'Template Name *' => 'اسم النموذج *', + 'Text File' => 'ملف نصي', + 'Text Message' => 'رسالة نصية', + 'The %name module definition has not been initialized.' => 'لم تتم تعريف الوحدة النمطية %name.', + 'The %name module descriptor has not been initialized.' => 'لم تتم تعريف وصف الوحدة النمطية %name.', + 'The %obj_name id \'%id\' doesn\'t exist' => 'معرف %obj_name \'%id\' غير موجود', + 'The HTML TITLE element is the most important element on your web page.' => 'عنصر عنوان HTML هو أهم عنصر على صفحة الويب الخاصة بك.', + 'The brand name or title' => 'اسم العلامة التجارية أو العنوان', + 'The cart item count should match the condition' => 'يجب أن يطابق عدد العناصر في السلة مع الشروط', + 'The image which replaces an undefined country flag (%file) was not found. Please check unknown-flag-path configuration variable, and check that the image exists.' => 'لم يتم العثور على الصورة التي تريد استبدالها بعلم بلد غير معروف (%file). الرجاء التحقق من مسار تكوين unknown-flag-path ، واختيار الصورة الموجودة.', + 'This condition is always true' => 'هذا الشرط صحيحاً دائماً', + 'This content is online.' => 'هذا المحتوى مفعل حالياً على الإنترنت.', + 'This coupon does not exists' => 'هذه القسيمة غير موجودة', + 'This coupon will offert a flat percentage off a shopper\'s entire order (not applied to shipping costs or tax rates). If the discount is greater than the total order corst, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.' => 'هذه القسيمة سوف تعرض نسبة مئوية ثابتة خارج النظام بأكمله للمتسوقين (لا تطبق على أسعار الضريبة أو تكاليف الشحن). إذا كان الخصم أكبر من مجموع الطلب الإجمالي، سيكون فقط على العميل مبلغ قيمة الشحن، أو لا شيء من قيمة الشحن إذا كانت القسيمة توفر شحناً مجانياً.', + 'This coupon will subtracts a set amount from the total cost of an order. If the discount is greater than the total order corst, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.' => 'وسوف تطرح هذه القسيمة كمية محددة من التكلفة الإجمالية للطلب. إذا كان الخصم أكبر من إجمالي قيمة الطلب، سيكون فقط على العميل مبلغ قيمة الشحن، أو لا شيء من قيمة الشحن إذا كانت القسيمة توفر شحناً مجانياً.', + 'This email already exists.' => 'هذا البريد الإلكتروني موجود بالفعل.', + 'This email does not exists' => 'هذا البريد الإلكتروني غير موجود', + 'This folder is online.' => 'هذا المجلد متوفر على الإنترنت.', + 'This product is on sale' => 'هذا المنتج متوفر للبيع', + 'This product is online' => 'هذا المنتج متوفر حالياً', + 'This product_sale_elements_id does not exists for this product : %d' => 'لا يوجد هذا product_sale_elements_id لهذا المنتج: %d', + 'This template is in use in some of your products, and cannot be deleted. Delete it from all your products and try again.' => 'هذا القالب هو قيد الاستخدام في بعض المنتجات الخاصة بك، ولا يمكن حذفه. قم بحذف جميع المنتجات الخاصة بك وحاول مرة أخرى.', + 'This value should not be blank.' => 'لا ينبغي أن تكون هذه القيمة فارغة.', + 'Timeout' => 'انتهاء المهلة', + 'Title' => 'العنوان', + 'Title *' => 'العنوان *', + 'Title ID not found' => 'لم يتم العثور على معرف عنوان', + 'Type' => 'النوع', + 'Unable to process your request. Please try again (%err).' => 'غير قادر على معالجة الطلب الخاص بك. الرجاء المحاولة مرة أخرى (%err).', + 'Unconditional usage' => 'الاستخدام غير مشروط', + 'Unconditionnal usage' => 'الاستخدام غير مشروط', + 'Undefined loop argument "%name"' => 'الحلقة الوسيطة غير معرفة "%name"', + 'Undefined search mode \'%mode\'' => 'وضع البحث غير معروف \'%\'', + 'Unknown order ID: %id' => 'طلب غير معروف: %id', + 'Unsupported magic method %name. only getArgname() is supported.' => '%name الأسلوب السحري غير معتمد. معتمد فقط من getArgname().', + 'Username' => 'اسم المستخدم', + 'Value' => 'القيمة', + 'Value *' => 'القيمة *', + 'Warnings' => 'تحذيرات', + 'Weight' => 'الوزن', + 'Yes, I have a password :' => 'نعم، لدى كلمة مرور:', + 'You are already registered!' => 'أنت مسجل بالفعل !', + 'Your Email Address' => 'عنوان البريد الإلكتروني الخاص بك', + 'Your Message' => 'رسالتك', + 'Your current password does not match.' => 'كلمة المرور الحالية الخاصة بك غير مطابقة.', + 'Zip code' => 'الرمز البريدي', + 'date format' => 'صيغة التاريخ', + 'delivery module %s is not a Thelia\Module\DeliveryModuleInterface' => 'وحدة التسليم النمطية %s غير متوفرة Thelia\Module\DeliveryModuleInterface', + 'language locale' => 'اللغة المحلية', + 'mailing system modification' => 'تعديل النظام البريدي', + 'password confirmation is not the same as password field' => 'كلمة المرور غير متطابقة', + 'password must be composed of at least 4 characters' => 'يجب أن تتألف كلمة المرور من 4 أحرف على الأقل', + 'payment module %s is not a Thelia\Module\PaymentModuleInterface' => 'الوحدة النمطية للدفع ليست متوفرة %s Thelia\Module\PaymentModuleInterface', + 'permanent discount (in percent)' => 'خصم دائم (في المائة)', + 'quantity value is not valid' => 'قيمة الكمية غير صالحة', + 'this product id does not exists : %d' => 'معرف هذا المنتج غير موجود: %d', + 'time format' => 'صيغة الوقت', +]; diff --git a/core/lib/Thelia/Config/I18n/cs_CZ.php b/core/lib/Thelia/Config/I18n/cs_CZ.php new file mode 100644 index 00000000..532502b9 --- /dev/null +++ b/core/lib/Thelia/Config/I18n/cs_CZ.php @@ -0,0 +1,79 @@ + '"%param" parametr nemůže být prázdný ve smyčce typu: % typ, název: %name', + '"%param" parameter is missing in loop type: %type, name: %name' => 'Chybí parametr "%param" ve smyčce typu: % typ, název: %name', + '%obj SEO modification' => '%obj SEO modifikace', + '%obj creation' => '%obj vznik', + '%obj modification' => '%obj modifikace', + 'A currency with code "%name" already exists.' => 'Měna s kódem "%name" již existuje.', + 'A message with name "%name" already exists.' => 'Zpráva s názvem "%name" již existuje.', + 'A product with reference %ref already exists. Please choose another reference.' => 'Výrobek s odkazem %ref již existuje. Zvolte prosím jiný odkaz.', + 'A user already exists with this email address. Please login or if you\'ve forgotten your password, go to Reset Your Password.' => 'Uživatel s touto e-mailovou adresou již existuje. Prosím přihlašte se nebo pokud jste zapomněli své heslo, přejděte na obnovení hesla.', + 'A value for attribute "%name" is already present in the combination' => 'Hodnota pro atribut "%name" je již použita', + 'A variable with name "%name" already exists.' => 'Proměnná s názvem "%name" již existuje.', + 'Activate logs only for these IP Addresses' => 'Aktivovat logování pouze pro tyto adresy IP', + 'Activate logs only for these files' => 'Aktivovat logování pouze pro tyto soubory', + 'Address ID not found' => 'ID adresy nebylo nalezeno', + 'Address Line 2' => 'Řádek adresy 2', + 'Address Line 3' => 'Řádek adresy 3', + 'Address label' => 'Adresní štítek', + 'Address update' => 'Aktualizace adresy', + 'Administrator ID not found' => 'ID Správce nebylo nalezeno', + 'Advertise this product as new' => 'Inzerovat tento produkt jako nový', + 'Alerts' => 'Upozornění', + 'Amount' => 'Množství', + 'Apply exchange rates on price in %sym' => 'Použít směnné kurzy na cenu v %sym', + 'Attribute ID:Attribute AV ID' => 'ID Atributu: Attribute AV ID', + 'Auth mode' => 'Režim ověřování', + 'Available quantity' => 'Dostupné množství', + 'Available quantity *' => 'Dostupné množství *', + 'Available shipping zones' => 'Dostupné dopravní zóny', + 'Bad tax list JSON' => 'Špatný JSON daňový seznam', + 'Business ID' => 'ID podniku', + 'Cannot find a default country. Please define one.' => 'Nelze najít výchozí zemi. Prosím definujte alespoň jednu.', + 'Cart' => 'Košík', + 'Cart item count is' => 'Počet položek v košíku je', + 'Cart total amount is' => 'Celková částka je', + 'Catalog configuration' => 'Konfigurace katalogu', + 'Categories' => 'Kategorie', + 'Category' => 'Kategorie', + 'Category page' => 'Stránka kategorie', + 'Cellphone' => 'Mobilní telefon', + 'Change password' => 'Změnit heslo', + 'Check country iso codes here.' => 'Zkontrolujte ISO kódy země ve Wikipedii.', + 'Check the total Cart amount in the given currency' => 'Zkontrolovat celkovou částku košíku v dané měně', + 'Compagny' => 'Společnost', + 'Company Name' => 'Jméno společnosti', + 'Conclusion' => 'Závěr', + 'Confirm Email Address' => 'Potvrďte svou e-mailovou adresu', + 'Confirm Email address' => 'Potvrďte svou e-mailovou adresu', + 'Constant amount' => 'Konstantní částka', + 'Contact and sender email address' => 'Kontakt a e-mailová adresa odesílatele', + 'Contact page' => 'Kontaktní stránka', + 'Content' => 'Obsah', + 'Content page' => 'Stránka obsahu', + 'Content title *' => 'Titulek obsahu', + 'Contents' => 'Obsah', + 'Country ID not found' => 'ID země nebyl nalezen', + 'Country title' => 'Název země', + 'Coupon %code is expired.' => 'Vypršela platnost kuponu %code.', + 'Coupon code %code is disabled.' => 'Kupon %code je zakázán.', + 'Critical' => 'Kritický', + 'Currency' => 'Měna', + 'Current Password' => 'Současné heslo', + 'Debug' => 'Debug', + 'Decimal places' => 'Počet desetinných míst', + 'Default folder *' => 'Výchozí složka *', + 'Default product category *' => 'Výchozí kategorie produktu *', + 'Edit' => 'Upravit', + 'Email address' => 'E-mailová adresa', + 'Home' => 'Domů', + 'Language' => 'Jazyk', + 'Name' => 'Název', + 'Password' => 'Heslo', + 'Quantity' => 'Množství', + 'Register' => 'Registrace', + 'Search' => 'Vyhledávání', + 'Start date' => 'Date de début de validité', +]; diff --git a/core/lib/Thelia/Config/I18n/de_DE.php b/core/lib/Thelia/Config/I18n/de_DE.php new file mode 100644 index 00000000..805624d8 --- /dev/null +++ b/core/lib/Thelia/Config/I18n/de_DE.php @@ -0,0 +1,792 @@ + 'Inhalts-Erstellungsformular', + ' note: only non-visible documents can be associated.' => ' Hinweis: Nur unsichtbare Dokumente können zugewiesen werden.', + '"%param" parameter cannot be empty in loop type: %type, name: %name' => '"%param" Parameter darf im Loop-Typ nicht leer sein: %type, Name: %name', + '"%param" parameter is missing in loop type: %type, name: %name' => '"%param" Parameter fehlt im Loop-Typ: % Typ, Name: %name', + '%module (version: %version)' => '%module (Version: %version)', + '%obj SEO modification' => '%obj SEO Bearbeitung', + '%obj creation' => '%obj Erstellung', + '%obj modification' => '%obj Bearbeitung', + '%obj%s deleted successfully' => '%obj%s erfolgreich gelöscht', + '%s has dependency to module %s. You have to deactivate this module before.' => '%s ist abhängig von Modul %s. Sie müssen dieses Modul zuerst deaktivieren.', + '%s have dependencies to module %s. You have to deactivate these modules before.' => '%s ist abhängig von Modul %s. Sie müssen dieses Modul zuerst deaktivieren.', + '%type% position updated' => '%type% Position aktualisiert', + '%type% visibility updated' => '%type% Sichtbarkeit aktualisiert', + 'A comma separated list of email addresses' => 'Eine durch Komma getrennte Liste der E-Mail-Adressen', + 'A currency with code "%name" already exists.' => 'Eine Währung mit dem Code "%name" existiert bereits.', + 'A descriptive title' => 'Beschreibungstitel', + 'A message with name "%name" already exists.' => 'Ein Nachricht mit dem Namen "%name" existiert bereits.', + 'A name such as Europe or Overseas' => 'Eine Name wie Europa oder Übersee', + 'A product with reference %ref already exists. Please choose another reference.' => 'Ein Produkt mit der Referenz %ref existiert bereits. Bitte wählen Sie eine andere Referenz.', + 'A short description, used when a summary or an introduction is required' => 'Kurzbeschreibung (wird benutzt wenn eine Zusammenfassung der eine Einleitung nötig ist)', + 'A short text, used when an additional or supplemental information is required.' => 'Ein kurzer Text, der verwendet wird, wenn eine zusätzliche oder ergänzende Information erforderlich ist.', + 'A user already exists with this email address. Please login or if you\'ve forgotten your password, go to Reset Your Password.' => 'Ein Benutzer mit dieser E-Mail-Adresse existiert bereits. Bitte melden Sie sich an - oder klicken Sie auf "Passwort zurücksetzen", wenn Sie Ihr Passwort vergessen haben.', + 'A value for attribute "%name" is already present in the combination' => 'Für das Attribut "%name" ist in dieser Kombination bereits ein Wert vorhanden', + 'A variable with name "%name" already exists.' => 'Eine Variable mit dem Namen "%name" ist bereits vorhanden.', + 'Activate logs only for these IP Addresses' => 'Protokolle nur für diese IP Adressen aktivieren', + 'Activate logs only for these files' => 'Protokolle nur für diese Dateien aktivieren', + 'Activate this sale' => 'Dieses Sonderangebot aktivieren', + 'Active' => 'Aktiv', + 'Add to all product templates' => 'Zu allen Produktvorlagen hinzufügen', + 'Additional address' => 'Zusätzliche Adresse', + 'Additional address information' => 'Zusätzliche Adressinformationen', + 'Address ID not found' => 'Die Adress-ID wurde nicht gefunden', + 'Address Line 2' => 'Adresse Zeile 2', + 'Address Line 3' => 'Adresse Zeile 3', + 'Address creation' => 'Adresse erstellen', + 'Address label' => 'Adress-Etikett', + 'Address update' => 'Adresse bearbeiten', + 'Address.' => 'Adresse', + 'Addresses for this country need a zip code' => 'Adressen für dieses Land benötigen eine Postleitzahl', + 'Administrator' => 'Administrator', + 'Administrator ID not found' => 'Die Administrator-ID wurde nicht gefunden', + 'Administrator email address' => 'E-Mail des Administrators', + 'Administrators' => 'Administratoren', + 'Advertise this product as new' => 'Dieses Produkt als Neuheit bewerben', + 'Alerts' => 'Warnungen', + 'All Products' => 'Alle Produkte', + 'All countries' => 'Alle Länder', + 'All shipping methods' => 'Alle Liefermethoden', + 'Amount' => 'Betrag', + 'An administrator with thie email address already exists' => 'Ein Administrator mit diesen e-Mail-Adresse ist bereits vorhanden', + 'Apply exchange rates on price in %sym' => 'Wechselkurse auf Preise in %sym anwenden', + 'Archive Format' => 'Archivformat', + 'Associate documents' => 'Zugeordnete Dokumente', + 'Associate images' => 'Zugehörige Bilder', + 'At least one of cart products categories is %op% %categories_list%' => 'Mindestens eine Kategorie der Produkte im Warenkorb ist %op% %categories_list% ', + 'Attribut' => 'Attribut', + 'Attribute ID:Attribute AV ID' => 'Attribut ID:Attribut AV ID', + 'Attribute value' => 'Attributwert', + 'Attributes' => 'Deklinationen', + 'Attributes value' => 'Attributwerte', + 'Auth mode' => 'Authentifizierungs Modus', + 'Available quantity' => 'Verfügbare Menge', + 'Available quantity *' => 'Verfügbare Menge *', + 'Available shipping zones' => 'Verfügbaren Lieferzonen', + 'Back Office' => 'Back-Office', + 'Bad tax list JSON' => 'Schlechter Taxliste JSON', + 'Billing country' => 'Rechnungsland', + 'Billing country is' => 'Rechnungsland ist', + 'Brand' => 'Marke', + 'Brand / Supplier' => 'Marke / Anbieter', + 'Brand name' => 'Markenname', + 'Brands' => 'Marken', + 'Business ID' => 'Unternehmens-ID', + 'By Module' => 'Nach Modul', + 'CSS' => 'CSS', + 'CSS stylesheet' => 'CSS Stylesheet', + 'Cannot find a default country. Please define one.' => 'Es wurde kein Standard-Land gefunden. Bitte definieren Sie eines.', + 'Cannot find the shop country. Please select a shop country.' => 'Das Shop-Land wurde nicht gefunden. Bitte wählen Sie eines aus.', + 'Cannot instantiate module "%name%": the namespace is null. Maybe the model is not loaded ?' => 'Modul "%name%" kann nicht instanziiert werden: der Namespace ist null. Vielleicht ist das Modul nicht geladen?', + 'Cart' => 'Warenkorb', + 'Cart contains at least a product %op% %products_list%' => 'Der Warenkorb enthält mindestens ein Produkt %op% %products_list% ', + 'Cart contains categories condition' => 'Der Warenkorb enthält Kategorie-Bedingungen', + 'Cart contains specific products' => 'Der Warenkorb enthält spezifische Produkte', + 'Cart item count' => 'Warenkorb Artikelanzahl', + 'Cart item count is' => 'Warenkorb Artikelanzahl ist', + 'Cart total amount' => 'Warenkorb-Betrag', + 'Cart total amount is' => 'Warenkorb-Betrag ist ', + 'Catalog' => 'Katalog', + 'Catalog configuration' => 'Katalog-Konfiguration', + 'Categories' => 'Kategorien', + 'Category' => 'Kategorie', + 'Category page' => 'Kategorie-Seite', + 'Category title' => 'Kategorie Titel', + 'Cellphone' => 'Mobiltelefonnummer', + 'Change password' => 'Passwort ändern', + 'Check country iso codes here.' => 'Länder ISO Codes hier.', + 'Check the total Cart amount in the given currency' => 'Prüfen Sie die Warenkorb-Gesamtsumme in der angegebene Währung', + 'City' => 'Stadt', + 'Code' => 'Code', + 'Combination builder' => 'Kombinations-Builder ', + 'Compagny' => 'Firma', + 'Company' => 'Firma', + 'Company Name' => 'Firma', + 'Conclusion' => 'Abschluss', + 'Configuration' => 'Einstellungen', + 'Confirm Email Address' => 'E-Mail Adresse bestätigen', + 'Confirm Email address' => 'E-Mail Adresse bestätigen', + 'Constant amount' => 'Festbetrag', + 'Constant amount found in one of the product\'s feature' => 'Fixbetrag in eine Funktion das Produkt gefunden', + 'Contact and sender email address' => 'Kontakt und Absender E-Mail Adresse ', + 'Contact page' => 'Kontakt-Seite', + 'Content' => 'Inhalt', + 'Content page' => 'Inhalt-Seite', + 'Content title *' => 'Inhalt Titel *', + 'Contents' => 'Inhalte', + 'Core hook of Thelia.' => 'Andockpunkt der Thelia.', + 'Countries' => 'Länder', + 'Country' => 'Land', + 'Country ID %id not found' => 'Land ID %id wurde nicht gefunden', + 'Country ID not found' => 'Land ID wurde nicht gefunden', + 'Country list is not valid JSON' => 'Liste der Länder ist kein gültiges JSON Format', + 'Country title' => 'Land Titel', + 'Coupon' => 'Gutschein', + 'Coupon %code is expired.' => 'Gutschein %code ist abgelaufen', + 'Coupon %code is not release.' => 'Der Gutschein %code ist nicht veröffentlicht.', + 'Coupon code %code is disabled.' => 'Gutschein Code %code ist deaktiviert', + 'Critical' => 'Kritisch', + 'Curency selection page' => 'Währungswahl-Seite', + 'Currencies' => 'Währungen', + 'Currency' => 'Währung', + 'Currency name' => 'Währungsname', + 'Current Password' => 'Aktuelles Passwort', + 'Customer' => 'Kunde', + 'Customer is %op% %customer_list%' => 'Der Kunde ist %op% %customer_list% ', + 'Customers' => 'Kunden', + 'Dashboard' => 'Dashboard', + 'Date \'%date\' is invalid, please enter a valid date using %fmt format' => 'Datum \'%date\' ist ungültig, bitte geben Sie eine gültige Datum mit dem %fmt Format', + 'Debug' => 'Fehlersuche', + 'Decimal places' => 'Anzahl der Nachkommastellen', + 'Default folder *' => 'Standart Ordner *', + 'Default product category *' => 'Standart Produkt Kategorie *', + 'Default product sale element' => 'Standart product sale element', + 'Default product template' => 'Standart Produkt Template', + 'Deleting %obj% for %id% with parent id %parentId%' => 'Stornierung von %obj% für %id% mit Eltern ID %parentId%', + 'Delivery' => 'Lieferung', + 'Delivery choice' => 'Liefer-Methode', + 'Delivery country' => 'Lieferland', + 'Delivery country is' => 'Lieferland ist ', + 'Delivery module ID not found' => 'Liefermodul ID wurde niht gefunden', + 'Delivery zone' => 'Lieferzone', + 'Detailed description' => 'Detaillierte Beschreibung', + 'Disabled' => 'Deaktiviert ', + 'Discount type' => 'Rabatt-Typ', + 'Display initial product prices on front-office' => 'Grundproduktpreis im Front-Office anzeigen', + 'Do compress' => 'Komprimieren', + 'Document' => 'Dokument', + 'Don\'t repeat keywords over and over in a row. Rather, put in keyword phrases.' => 'Wiederholen Sie nicht zu oft die Stichwörter. ', + 'EAN Code' => 'EAN-Code', + 'Edit' => 'Ändern', + 'Edit JavaScript' => 'JavaScript bearbeiten', + 'Email Address' => 'E-Mail Adresse', + 'Email address' => 'E-mail Adresse', + 'Email addresses of notification recipients' => 'E-Mail-Adressen der Benachrichtigungsempfänger', + 'Email test from : %store%' => 'E-mail Test vom : %store%', + 'Emergency' => 'Notfall', + 'Enable remote SMTP use' => 'Remoteverwendung SMTP aktivieren', + 'Encryption' => 'Verschlüsselung', + 'End date of sales' => 'Sonderangebot Endedatum', + 'Enter here the brand name in the default language (%title%)' => 'Eintragen Sie hier die Markenname in der standart Sprache (%title%)', + 'Enter here the category title in the default language (%title%)' => 'Geben Sie hier ein den Kategorie Titel in der standart Sprache (%title%)', + 'Enter here the mail template purpose in the default language (%title%)' => 'Eintragen Sie hier den E-Mail Template Betreff in der standart Sprache (%title%)', + 'Enter here the sale name in the default language (%title%)' => 'Schreiben Sie hier ein die Sonderangebots-Name in der standart Sprache (%title%)', + 'Enter the new password' => 'Neues Kennwort eingeben', + 'Enter the new password again' => 'Neues Passwort erneut eingeben', + 'Equal to' => 'Gleich als', + 'Error during %action process : %error. Exception was %exc' => 'Fehler während %action : %error. Exception : %exc', + 'Error occured while processing order ref. %ref, ID %id: %err' => 'Fehler bei der Bestellverarbeitung Ref. %ref, ID %id; %err', + 'Error occured.' => 'Ein Fehler ist aufgetreten', + 'Errors' => 'Ferhler', + 'Export' => 'Export', + 'Fail to delete %obj% for %id% with parent id %parentId% (Exception : %e%)' => '%obj% zu %id% mit parent id %parentId% konnte nicht gelöscht werden. (Exception : %e%)', + 'Fail to update %type% position: %err%' => 'Fehler bei der Aktualisierung der Position %type% : %err%', + 'Fail to update %type% visibility: %err%' => 'Die Sichtbarkeit von %type% konnte nicht geändert werden: %err%', + 'Failed to create instance of module "%name%" when trying to delete module. Module directory has probably been deleted' => 'Fehler beim Erstellen der Instanz des Moduls "%name%", beim Versuch das Modul zu löschen. Das Modul-Verzeichnis wurde wahrscheinlich gelöscht', + 'Failed to create new hook %s' => 'Fehler beim Erstellung einem neues Hook %s', + 'Failed to deactivate hook with id %s' => 'Fehler beim Deaktivierung dem Hook id %s', + 'Failed to delete selected countries' => 'Fehler beim Löschung den gewählten Länder', + 'Failed to find a payment Module with ID=%mid for order ID=%oid' => 'Kein Zahlungsmodul wurde gefunden mit ID=%mid oder für Bestellung ID=%oid', + 'Failed to load descriptor (module.xml) for module ID "%id".' => 'Fehler beim Laden der Deskriptor-Datei (module.xml) für Modul-ID "%id".', + 'Failed to load message with code \'%code%\', propably because it does\'nt exists.' => 'Fehler bei der Ladung der Nachricht \'%code%\', wahrscheinlich weil es nicht existiert.', + 'Failed to open a writing stream on the file: %file' => 'Unmöglich im Datei %file zu schreiben', + 'Failed to open translation file %file. Please be sure that this file is writable by your Web server' => 'Fehler beim Öffnung der Übersetzungdatei %file. Bitte prüfen Sie, dass diese Datei durch Ihren Web-Server schreibbar ist.', + 'Failed to send message %code. Failed recipients: %failed_addresses' => 'Fehler Bei der Sendung der Nachricht %code. Nicht erreichbaren Empfänger : %failed_adresses', + 'Failed to update language definition: %ex' => 'Fehler bei der Sprachdefinitions-Aktualisierung : %ex', + 'Fax' => 'Fax', + 'Feature' => 'Charakteristik', + 'Feature value does not match FLOAT format' => 'Charakteristik Angabe stimmt den FLOAT Format nicht überein', + 'Features' => 'Charakteristiken', + 'Features value' => 'Charakteristik-Angabe', + 'File format' => 'Datei Format', + 'File is too large, please retry with a file having a size less than %size%.' => 'Die Datei ist zu schwer, bitte versuchen Sie es erneut mit einer leichtere Datei. Weniger als %size%.', + 'File to upload' => 'Datei zu senden', + 'Files with the following extension are not allowed: %extension, please do an archive of the file if you want to upload it' => 'Dateien mit der folgenden Erweiterung sind nicht erlaubt : %extension, bitte komprimmieren Sie die Datei wenn Sie es hochladen möchten', + 'First Name' => 'Vorname', + 'Firstname' => 'Vorname', + 'Fixed Amount Discount' => 'Festbetrag Discount', + 'Fixed amount discount for selected attribute values' => 'Festbetrag Discount für ausgewählten Deklinationsangaben', + 'Fixed amount discount for selected categories' => 'Fesbetrag Rabatt für ausgewählte Kategorien', + 'Fixed amount discount for selected products' => 'Festbetrag Discount für ausgwählten Produkten', + 'Folder' => 'Ordner', + 'Folder page' => 'Ordner-Seite', + 'Folder title *' => 'Ordner-Titel *', + 'For one ore more customers' => 'Für einen oder mehrere Kunden', + 'Free product when buying one or more selected products' => 'Kostenloses Produkt beim Kaufen eines oder mehrere gewählten Produkte ', + 'Front Office' => 'Front Office', + 'Full Name' => 'Name', + 'Greater than' => 'Größer als', + 'Greater than or equals' => 'Größer oder gleich als', + 'HTML Message' => 'HTML Nachricht ', + 'HTML layout' => 'HTML-Layout', + 'Home' => 'Startseite', + 'Home page' => 'Startseite', + 'Hook' => 'Andockpunkt (Hook)', + 'Hook block' => 'Andockpunkt Block', + 'Hook code' => 'Andockpunkt Code', + 'Hook create form' => 'Andockpunkt-Erstellungsformular', + 'Hook title' => 'Andockpunkt Titel', + 'Hooks' => 'Andockpunkte', + 'Host' => 'Host', + 'I would like to receive the newsletter or the latest news.' => 'Ich möchte den Newsletter abonnieren', + 'ISO 4217 code' => 'ISO 4217 Code', + 'ISO 639-1 Code' => 'ISO 639-1 Code', + 'ISO Alpha-2 code' => 'ISO-Alpha-2-code', + 'ISO Alpha-3 code' => 'ISO-Alpha-3 code', + 'ISO Code' => 'ISO-Code', + 'If a translation is missing or incomplete :' => 'Wenn eine Übersetzung fehlet oder unvollständig ist :', + 'If cart item count is %operator% %quantity%' => 'Warenkorb Artikelanzahl ist strong>%operator% %quantity% ', + 'If cart total amount is %operator% %amount% %currency%' => 'Wenn die Warenkorb-Gesamtsumme ist %operator% %amount% %currency% ', + 'If checked, this hook will be used by a hook block. If not, by hook function.' => 'Wenn aktiviert, dieses Hook wird durch einen Hook Block benutzt. Wenn nicht, durch eine Hook Funktion', + 'Image' => 'Bild', + 'Import successfully done, %count row(s) have been changed' => 'Import erfolgreich durchgeführt, %count Zeile(n) wurde(n) geändert', + 'Impossible to delete a customer who already have orders' => 'Nicht möglich einen Kunde mit Bestellungen zu löschen', + 'In' => 'In', + 'Include documents' => 'Dokumente Einschließen', + 'Include images' => 'Bilder Einschließen', + 'Information' => 'Informationen', + 'Invalid product_sale_elements' => 'Ungültigen product_sale_elements', + 'Invalid username or email.' => 'Ungültiger Benutzername oder Kennwort.', + 'Invalid value "%value" for "%param" parameter in loop type: %type, name: %name' => 'Ungültiger Wert "%" für "%param"-Parameter im Loop-Typ: % Typ, Name: %name', + 'Invalid value for walkMode parameter: %value' => 'Ungültige Angabe für den WalkMode Parameter : %value', + 'Invoice' => 'Rechnung', + 'Invoice choice' => 'Zahlungs-Methode', + 'Is it the default product sale element ?' => 'Ist es den standart product sale element ?', + 'It is not allowed to delete the default currency' => 'Es ist nicht erlaubt, die Standardwährung zu löschen', + 'It is not allowed to delete the default language' => 'Es ist nicht erlaubt, die Standardsprache zu löschen', + 'JavaScript' => 'JavaScript', + 'Keep the most important part of your description in the first 150-160 characters.' => 'Schreiben Sie den wichtigsten Teil Ihrer beschreibung in den ersten 150-160 Zeichen.', + 'Language' => 'Sprache', + 'Language name' => 'Sprachname', + 'Languages' => 'Sprachen', + 'Last Name' => 'Nachname', + 'Lastname' => 'Nachname', + 'Layout' => 'Layout', + 'Less than' => 'Wenig als', + 'Less than or equals' => 'Wenig oder gleich als', + 'Log format *' => 'Log Format *', + 'Log level *' => 'Log-Level *', + 'Login failed. Please check your username and password.' => 'Fehler bei der Anmeldung. Bitte überprüfen Sie Ihre Benutzername und Ihr Passwort.', + 'Login name' => 'Benutzername', + 'Login page' => 'Anmeldung-Seite', + 'Logs' => 'Log', + 'Loop cannot implements multiple Search Interfaces : `PropelSearchLoopInterface`, `ArraySearchLoopInterface`' => 'Der Loop kann nicht mehrere Such-Schnittstellen ausführen: \'PropelSearchLoopInterface\', \'ArraySearchLoopInterface\'', + 'Loop must implements \'PropelSearchLoopInterface\' to be timestampable' => 'Der Loop benötigt \'PropelSearchLoopInterface\' als timestampable', + 'Loop must implements \'PropelSearchLoopInterface\' to be versionable' => 'Der Loop benötigt \'PropelSearchLoopInterface\' als versionable', + 'Loop must implements one of the following interfaces : `PropelSearchLoopInterface`, `ArraySearchLoopInterface`' => 'Der Loop muss eine der folgenden Schnittstellen enthalten: \'PropelSearchLoopInterface\', \'ArraySearchLoopInterface\'', + 'Lost password' => 'Passwort vergessen', + 'Mail template name' => 'Mail Template Name', + 'Mail template purpose' => 'Mail Template Betreff', + 'Mailing system' => 'Mailing System', + 'Main address' => 'Hauptadresse', + 'Main area' => 'Hauptbereich', + 'Make sure it uses keywords found within the page itself.' => 'Verwenden Stichwörter die auf der Seite sind. ', + 'Make sure that your title is clear, and contains many of the keywords within the page itself.' => 'Ihr Titel muss klar sein, und viele Keywords enthalten.', + 'Make this address as my primary address' => 'Als Standardadresse speichern', + 'Maximum usage count reached for coupon %code' => 'Maximale Verwendungsanzahl für den Gutschein %code erreicht', + 'Message' => 'Nachricht', + 'Message name' => 'Nachricht name', + 'Message subject' => 'Nachricht Betreff', + 'Messages' => 'Nachrichten', + 'Meta Description' => 'Metabeschreibung', + 'Meta Keywords' => 'Meta-Schlüsselwörter', + 'Method Name' => 'Methode-Name', + 'Missing or invalid data: %s' => 'Fehlenden oder ungültigen Daten: %s', + 'Module' => 'Modul', + 'Module "%name%" directory was not found' => 'Der Modul "%name%" Ordner wurde nicht gefunden', + 'Module %name directory doesn\'t exists.' => 'Modul %name Ordner existiert nicht', + 'Module %name should have a config.xml in the Config directory.' => 'Das Modul %name soll einen config.xml im Config Ordner haben. ', + 'Module %name should have a module.xml in the Config directory.' => 'Das Modul %name soll einen module.xml im Config Ordner haben. ', + 'Module ID "%id" was not found.' => 'Modul ID "%id" wurde nicht gefunden.', + 'Module ID not found' => 'Modul ID wurde nicht gefunden', + 'Module hook' => 'Modul Hook', + 'Modules' => 'Module', + 'More information about ISO 4217' => 'Weitere Informationen über ISO 4217', + 'Name' => 'Name', + 'Name *' => 'Name *', + 'Name of the HTML layout file' => 'Name der HTML-Layout Datei', + 'Name of the HTML template file' => 'Name der HTML-Template Datei', + 'Name of the text layout file' => 'Name der Text-Layout Datei', + 'Name of the text template file' => 'Name der Text-Template datei', + 'Native' => 'Nativ', + 'New Password' => 'Neues Passwort', + 'Newsletter page' => 'Newsletter-Seite', + 'No %obj was created.' => 'Kein %obj wurde erstellt', + 'No %obj was updated.' => 'Kein %obj wurde aktualisiert.', + 'No module found for code \'%item\'' => 'Kein Modul wurde gefunden für den Code \'%item\'', + 'No, I am a new customer.' => 'Nein, ich bin ein neuer Kunde.', + 'None' => 'Keine Angabe', + 'Not equal to' => 'Nicht gleich als', + 'Not in' => 'Nicht in', + 'Notices' => 'Hinweise', + 'Numerical ISO Code' => 'Numerischer ISO-Code', + 'Only files having the following mime type are allowed: %types%' => 'Nur Dateien mit den folgenden MIME-Typen sind erlaubt: %types%', + 'Only hookable modules are displayed in this menu.' => 'Nur hookable Modulen werden in diesem Menü angezeigt.', + 'Only if order billing country is %op% %countries_list%' => 'Nur wenn der Rechnungsland %op% %countries_list% ist', + 'Only if order shipping country is %op% %countries_list%' => 'Nur wenn das Land %op% %countries_list% ist', + 'Order' => 'Bestellung', + 'Order address ID not found' => 'Bestellungsadresse ID wurde nicht gefunden', + 'Order failed' => 'Ausfall der Bestellung', + 'Order ref. %ref is now unpaid.' => 'Bestellung Nr. %ref ist jetzt unbezahlt.', + 'Order ref. %ref, ID %id has been successfully paid.' => 'Bestellung Ref. %ref, ID %id wurde erfolgreich bezahlt. ', + 'Orders' => 'Bestellungen', + 'Overall' => 'Für alle Kunde', + 'Page 404' => 'Seite 404', + 'Page Title' => 'Seitetitel', + 'Parent category' => 'Übergeordnete Kategorie', + 'Parent folder *' => 'Übergeordneter Ordner *', + 'Password' => 'Passwort', + 'Password *' => 'Passwort *', + 'Password confirmation' => 'Passwort-Bestätigung', + 'Payment failed' => 'Ausfall der Zahlung', + 'Payment gateway' => 'Zahlungs-Gateway', + 'Per customer' => 'Pro Kunde', + 'Percent' => 'Prozent', + 'Percentage' => 'Prozent', + 'Percentage discount for selected attribute values' => 'Prozentualen Rabatt für ausgewählte Deklinationsangabe', + 'Percentage discount for selected categories' => 'Prozent Discount für die ausgewählten Kategorien', + 'Percentage discount for selected products' => 'Prozent Discount für die ausgewählten Produkten', + 'Percentage of the product price' => 'Prozent des Produktpreises', + 'Phone' => 'Telefon', + 'Placed order' => 'Erteilten Auftrag', + 'Please accept the Terms and conditions in order to register.' => 'Bitte akzeptieren Sie die AGB um zu registrieren.', + 'Please check your input: %error' => 'Bitte überprüfen Sie Ihre Eingabe : %error', + 'Please enter a valid email address' => 'Bitte geben Sie eine gültige E-Mail-Adresse ein', + 'Please enter your email address' => 'Bitte geben Sie Ihre E-Mail-Adresse ein', + 'Please enter your password' => 'Bitte geben Sie Ihr Passwort ein', + 'Please select a category' => 'Bitte wählen Sie eine Kategorie', + 'Please select an attribute' => 'Bitte wählen Sie eine Deklination', + 'Please select at least one attribute value' => 'Bitte wählen Sie mindestens eine Deklination', + 'Please select at least one category' => 'Bitte wählen Sie mindestens eine Kategorie', + 'Please select at least one product' => 'Bitte wählen Sie mindestens ein Produkt', + 'Please select the category of the offred product' => 'Bitte wählen Sie die Produkt-Kategorie ', + 'Please select the offered product' => 'Bitte wählen Sie das Produkt ', + 'Please upload a valid Zip file' => 'Bitte laden Sie eine gültige Zip-Datei', + 'Port' => 'Port', + 'Postage' => 'Porto', + 'Preferred locale' => 'Gewünschte Sprache', + 'Prevent mailing template modification or deletion, except for super-admin' => 'Mailling Templates Bearbeitung oder Löschung verhindern, außer für den Administrator', + 'Prevent variable modification or deletion, except for super-admin' => 'Variable Änderung oder Löschung verhindern, Ausnahme für Superadministratoren. ', + 'Price currency *' => 'Währung *', + 'Processing cancelation of payment for order ref. %ref' => 'Verarbeitung der Zahlungsabbruch für die Bestellung Ref. %ref', + 'Processing confirmation of order ref. %ref, ID %id' => 'Verarbeitung der Bestellbestätigung Ref. %ref, ID %id', + 'Prodcut ID *' => 'Produkt ID *', + 'Product' => 'Produkt', + 'Product ID' => 'Produkt ID', + 'Product ID *' => 'Podukt ID *', + 'Product attributes' => 'Produktdeklinationen', + 'Product base price excluding taxes *' => 'Produkt Grundpreis ohne MwSt. *', + 'Product base price with taxes' => 'Produkt Grundpreis mit MwSt. *', + 'Product categories' => 'Produkt Kategorien', + 'Product clone' => 'Produkt Klon', + 'Product loop' => 'Produkt Loop', + 'Product page' => 'Produkt-Seite', + 'Product price excluding taxes' => 'Produkt Preis ohne MwSt.', + 'Product price excluding taxes *' => 'Produkt Preis exkl. Taxen *', + 'Product price including taxes' => 'Produkt Preis inkl. Taxen *', + 'Product price offset for each currency' => 'Preisunterschied für jede Währung', + 'Product reference (must be unique)' => 'Produkt Referenz (muss einzig sein)', + 'Product reference *' => 'Produktreferenz *', + 'Product sale element ID *' => 'Product sale element ID *', + 'Product template' => 'Produkt Template', + 'Product title' => 'Produkt Titel', + 'ProductSaleElement modification' => 'ProductSaleElement Bearbeitung ', + 'Products' => 'Produkte', + 'Profile' => 'Profil', + 'Profile Code' => 'Profil Code', + 'Profile ID not found' => 'Profil ID wurde nicht gefunden', + 'Profile `code` already exists' => 'Profil `code` existiert bereits', + 'Profiles' => 'Profile', + 'Purpose' => 'Zweck', + 'Purpose *' => 'Betreff *', + 'Quantity' => 'Menge', + 'Range date End' => 'Endedatum', + 'Range date Start' => 'Anfangsdatum', + 'Rate' => 'Kurs', + 'Redirecting ...' => 'Weiterleitung ...', + 'Redirecting to %url' => 'Weiterleitung auf %url', + 'Reference' => 'Referenz', + 'Reference *' => 'Referenz *', + 'Register' => 'Registrieren', + 'Remember me ?' => 'Mich erinnern ?', + 'Remove X percent to total cart' => 'Entfernt X Prozent der gesamten Warenkorb', + 'Replace by the default language' => 'Durch die Standartsprache ersetzen', + 'Replace current document by this file' => 'Aktueller Dokument durch diese Datei ersetzen', + 'Replace current image by this file' => 'Aktuelles Bild durch dieses Datei ersetzen', + 'Reseller' => 'Händler', + 'Rewriten URL' => 'Rewritten URL', + 'Rotated Text File' => 'Gedrehter Text Datei', + 'Sale announce label' => 'Sonderangebots-Schlagwort', + 'Sale price excluding taxes' => 'Discount Nettopreis ', + 'Sale price including taxes' => 'Discount Preis einschl. MwSt.', + 'Sale title' => 'Sonderangebots-Titel', + 'Saving %obj% for %parentName% parent id %parentId%' => 'Speichern von %obj% für %parentName% mit parent id %parentId%', + 'Search' => 'Suchen', + 'Search page' => 'Suchseite', + 'Select a default template for new products created in this category' => 'Wählen Sie ein standart Template für neue Produkte die in dieser Kategorie erstellet werden', + 'Select the brand logo' => 'Wählen Sie das Markenlogo', + 'Select the brand logo amongst the brand images' => 'Wählen Sie das Logo aus die Markenbilder', + 'Select the categories of the products covered by this operation' => 'Wählen Sie die betroffene Produktkategorie aus', + 'Select the countries to delete from this shipping zone' => 'Wählen Sie die Länder die von dieser Liefezonen entfernt werden', + 'Select the countries to include in this shipping zone' => 'Wählen Sie die Länder aus die in dieser Versandzone gehören', + 'Select the discount type that will be applied to original product prices' => 'Wählen Sie aus den Discount-Typ der für Grundproduktpreise benutzt wird. ', + 'Select the parent category of this category.' => 'Wählen Sie die Übergeordnete Kategorie dieser Kategorie.', + 'Select the product attributes included in this operation' => 'Wählen Sie die betroffene Produktdeklination', + 'Select the product brand, or supplier.' => 'Wählen Sie die Marke oder den Anbieter aus', + 'Select the products covered by this operation' => 'Wählen Sie betroffenen Produkte', + 'Select the virtual document' => 'Wählen Sie das virtuelles Dokument', + 'Service ID' => 'Service ID', + 'Shipping configuration' => 'Lieferungskonfiguration', + 'Shipping zone name' => 'Lieferzone Name', + 'Short additional text' => 'Kurzer zusätzlicher Text', + 'Short description text' => 'Kurzes Beschreibungstext', + 'Show redirections *' => 'Weiterleitungen anzeigen *', + 'Sitemap' => 'Sitemap', + 'Sorry, an error occured.' => 'Es tut uns Leid, aber ein Fehler ist aufgetreten', + 'Sorry, an error occured: %msg' => 'Es tut uns Leid, aber ein Fehler ist aufgetreten : %msg', + 'Sorry, an error occured: %s' => 'Es tut uns Leid, aber ein Fehler ist aufgetreten: %s', + 'Sorry, an error occurred: %err' => 'Es tut uns Leid, aber ein Fehler ist aufgetreten : %err', + 'Sorry, you are not allowed to perform this action.' => 'Es tut uns Leid, aber Sie sind nicht berechtigt, diese Aktion durchzuführen', + 'Sorry, you\'re not allowed to perform this action' => 'Es tut uns Leid, aber Sie sind nicht berechtigt, diese Aktion durchzuführen', + 'Source IP' => 'Quell-IP', + 'Start date' => 'Startdatum', + 'Start date of sales' => 'Sonderangebot Startdatum', + 'State *' => 'Bundesland *', + 'State ID %id not found' => 'Bundesland ID %id wurde nicht gefunden', + 'State title' => 'Name d. Bundeslandes', + 'Stock' => 'Lagerbestand', + 'Store Business Identification Number (SIRET, etc).' => 'Shop Business Identification Number', + 'Store Information' => 'Shop Informationen', + 'Store configuration failed.' => 'Fehler beim Shop-Konfiguration', + 'Store description' => 'Shop Beschreibung', + 'Store email address' => 'Shop E-Mail Adresse', + 'Store logs into text file' => 'Logs in der Text Datei speichern', + 'Store logs into text file, up to a certian size, then a new file is created' => 'Speichert Logs in einer Text Datei bis zu einer bestimmte Größe, dann wird eine neue Datei erstellt. ', + 'Store name' => 'Shop Name', + 'Street Address' => 'Straße', + 'Street Address ' => 'Adresse', + 'Strictly use the requested language' => 'Verwenden Sie unbedingt die gewünschte Sprache', + 'Subject' => 'Betreff', + 'Summary' => 'Zusammenfassung', + 'Symbol' => 'Symbol', + 'System' => 'System', + 'System configuration' => 'System-Konfiguration', + 'System log configuration failed.' => 'Systemprotokoll-Konfiguration ist fehlgeschlagen.', + 'Tax' => 'Taxe', + 'Tax ID not found in tax list JSON' => 'Taxe ID im Taxliste JSON nicht gefunden', + 'Tax list is not valid JSON' => 'Der JSON der Taxliste ist ungültig', + 'Tax rule ID not found' => 'Taxregel ID wurde nicht gefunden', + 'Tax rule for this product *' => 'Taxregel für dieses Produkt *', + 'Taxes' => 'Taxen', + 'Taxes rules' => 'Taxregeln', + 'Template' => 'Vorlage', + 'Template Name *' => 'Template-Name *', + 'Templates' => 'Vorlagen', + 'Text File' => 'Text Datei', + 'Text Message' => 'Text Nachricht', + 'The %name module definition has not been initialized.' => 'Die %name Modul-Definition wurde nicht initialisiert.', + 'The %name module descriptor has not been initialized.' => 'Der %name Modul-Deskriptor wurde nicht initialisiert.', + 'The %obj_name id \'%id\' doesn\'t exist' => 'Die %obj_name ID \'%id\' existiert nicht', + 'The HTML TITLE element is the most important element on your web page.' => 'Das HTML-Titel-Element ist das wichtigstes Element auf Ihre Webseite.', + 'The brand name or title' => 'Markenname oder Titel', + 'The cart item count should match the condition' => 'Warenkorb Artikelanzahl sollte der Bedingung entsprechen', + 'The category title' => 'Der Kategorie Titel', + 'The class "%class" doesn\'t exist' => 'Die Klasse "%class" ist nicht vorhanden', + 'The class "%class" must extend %baseClass' => 'Die Klasse "%class" muss %baseClass erweitern', + 'The container should not be null in this form. Please use the FormFactory to get an instance.' => 'Der Container in diesem Formular darf nicht null sein. Bitte benutzen Sie die FormFactory um eine Instanz abzurufen.', + 'The coupon applies if the cart contains at least one product of the selected categories' => 'Der Gutschein gilt wenn der Warenkorb mindestens ein Produkt von der angegebene Kategorieliste enthält', + 'The coupon applies if the cart contains at least one product of the specified product list' => 'Der Gutschein gilt wenn der Warenkorb mindestens ein Produkt von der angegebene Produktliste enthält', + 'The coupon applies to some customers only' => 'Der Gutschein gilt nur für einige Kunden', + 'The coupon applies to the selected billing countries' => 'Der Gutschein gilt für die ausgewählten Rechnungsländer', + 'The coupon applies to the selected delivery countries' => 'Der Gutschein gilt für den ausgewählten Lieferländer', + 'The coupon code \'%code\' already exist. Please choose another coupon code' => 'Gutschein Code \'%code\' existiert bereits. Bitte wähle SIe einen anderen Gutchein Code. ', + 'The coupon code \'%code\' already exists. Please choose another coupon code' => 'Gutschein Code \'%code\' existiert bereits. Bitte wähle SIe einen anderen Gutchein Code. ', + 'The coupon is valid after a given date' => 'Der Gutschein ist gültig nach einem bestimmtes Datum', + 'The date after which sales are de-activated. Please use %fmt format.' => 'Der Zeitpunkt, ab dem die Sondeangeboten deaktiviert sind. Bitte benutzen Sie das Format %fmt.', + 'The date from which sales are active. Please use %fmt format.' => 'Der Zeitpunkt, ab dem die Sondeangeboten aktiv sind. Bitte benutzen Sie das Format %fmt.', + 'The detailed description.' => 'Die detaillierte Beschreibung.', + 'The extension "%extension" is not allowed' => 'Die Erweiterung "%extension" ist nicht erlaubt', + 'The file %path has been successfully downloaded' => 'Die Datei %path wurde heruntergeladen', + 'The following columns are missing: %columns' => 'Die folgenden Spalten fehlen: %columns', + 'The image which replaces an undefined country flag (%file) was not found. Please check unknown-flag-path configuration variable, and check that the image exists.' => 'Das Bild, das einen nicht definierten Landesflagge (%file) ersetzt, wurde nicht gefunden. Bitte überprüfen Sie die unknown-flag-path Konfigurationsvariable, und überprüfen Sie, dass das Bild existiert. ', + 'The language "%id" doesn\'t exist' => 'Die Sprache "%id" existiert nicht', + 'The lost admin password recovery feature is disabled.' => 'Die Passwort-Wiederherstell-Funktion für Administratoren ist deaktiviert.', + 'The mailing template in HTML format.' => 'Der Mailing Template im HTML Format', + 'The mailing template in text-only format.' => 'Der Mailing Template im Text Format ', + 'The method %method% doesn\'t exist in classname %classname%' => 'Die Methode %method% existiert in %classname% nicht', + 'The method name that will handle the hook event.' => 'Der Methodenname, die den Hook-Ereignis behandelt.', + 'The module "%name%" is currently in use by at least one order, and can\'t be deleted.' => 'Das Modul "%name%" ist in mindestens einer Bestellung benutzt und kann nicht gelöscht werden.', + 'The module %module has been installed successfully.' => 'Das Modul wurde erfolgreich installiert.', + 'The module %name is already installed in the same or greater version.' => 'Das Modul %name ist schon in der selbe oder neuere Version installiert', + 'The module %name requires Thelia %version or newer' => 'Das Modul %name benötigt Thelia %version oder neuere', + 'The module has to be activated.' => 'Das Modul muss aktiviert sein.', + 'The module is not valid : %message' => 'Das Modul ist nicht gültig : %message', + 'The module zip file' => 'Modul Zip-Datei', + 'The product document id %id doesn\'t exists' => 'Die product document ID %id existiert nicht', + 'The product image id %id doesn\'t exists' => 'Die product image ID %id existiert nicht', + 'The product sale element id %id doesn\'t exist' => 'Die product sale element ID %id existiert nicht', + 'The product sale elements id %id doesn\'t exist' => 'Die product sale element ID %id existiert nicht', + 'The product sale elements id %id doesn\'t exists' => 'Die product sale element ID %id existiert nicht', + 'The rate from %currencyCode: Price in %currencyCode x rate = Price in this currency' => 'Wechselkurs vom %currencyCode: Preis in %currencyCode * Kurs = Preis in dieser Währung', + 'The resource %res has not been found' => 'Die Ressource %res wurde nicht gefunden', + 'The sale announce label, such as Sales ! or Flash Sales !' => 'Sonderangebots-Schlagwort zb, Sales ! oder Flash Sales !', + 'The sale name or descriptive title' => 'Sonderangebots-Titel oder beschreibenden Titel', + 'The sale name or title' => 'Sonderangebot Name oder Titel', + 'The service id that will handle the hook (defined in the config.xml file of the module).' => 'Der Service-ID, die den Hook behandelt (definiert in der Datei config.xml des Moduls).', + 'The store fax number.' => 'Shop Faxnummer', + 'The store phone number.' => 'Shop Telefonnummer', + 'The type %type is not valid' => 'Der Typ %type ist nicht gültig', + 'The zip code format' => 'Das Postleitzahl-format', + 'There are no files to associate.' => 'Es gibt keine Dateien zu assoziieren.', + 'There is no id "%id" in the export categories' => 'Es gibt kein ID "%id" in den Import-Kategorien', + 'There is no id "%id" in the exports' => 'Es gibt keine ID "%id" in den Exporten', + 'There is no id "%id" in the import categories' => 'Die ID "id" existiert im Kategorie Import nicht', + 'There is no id "%id" in the imports' => 'Die ID "id" existiert im Import nicht', + 'There\'s a conflict between your file extension "%ext" and the mime type "%mime"' => 'Es gibt einen Konflikt zwischen Ihre Dateierweiterung "%ext" und den MIME-Typ "%mime"', + 'This PHP extension should be installed and loaded.' => 'Diese PHP-Erweiterung sollte installiert und geladen werden.', + 'This administrator login already exists' => 'Dieser Administrator-Zugang ist bereits vorhanden', + 'This brand is online' => 'Diese Marke ist online', + 'This category is online' => 'Diese Kategorie Titel', + 'This condition is always true' => 'Diese Kondition ist immer war', + 'This content is online.' => 'Dieses Inhalt ist online.', + 'This coupon adds a free product to the cart if one of the selected products is in the cart.' => 'Dieser Gutschein fügt ein kostenloses Produkt hinzu, wenn sich eines der ausgewählten Produkte im Warenkorb befindet.', + 'This coupon does not exists' => 'Dieser Gutschein existiert nicht', + 'This coupon subtracts from the order total a percentage of the price of each product which belongs to the selected categories. If the discount is greater than the total order, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.' => 'Dieser Gutschein subtrahiert von der Bestellung einen Prozentsatz des Preises von jedem Produkt den ausgewählten Kategorien. Wenn der Rabatt größer als der Gesamtauftrag ist, wird den Kunde nur die versandkosten bezahlen, oder nichts, wenn der Gutschein auch eine Kostenlose Lieferung bietet.', + 'This coupon subtracts from the order total the specified percentage of each product price which uses the selected attribute values. If the discount is greater than the total order, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.' => 'Dieser Gutschein subtrahiert den angegebenen Prozentsatz von der Bestellsumme für jedes ausgewählte Produkt mit den angegeben Attributwerten. Wenn der Rabatt größer als der Gesamtauftrag ist, werden dem Kunden nur die Versandkosten berechnet, oder nichts, wenn der Gutschein auch eine kostenlose Lieferung beinhaltet.', + 'This coupon subtracts from the order total the specified percentage of each selected product price. If the discount is greater than the total order, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.' => 'Dieser Gutschein subtrahiert von der Summe der Bestellung den angegebenen Prozentsatz des jeweils ausgewählten Produktpreis. Wenn der Rabatt größer als die Auftragssumme ist, zahlt der Kunde nur den Versand, oder gar nichts wenn der Gutschein auch kostenlosen Versand bietet.', + 'This coupon subtracts the specified amount from the order total for each product which belongs to the selected categories. If the discount is greater than the total order, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.' => 'Dieser Gutschein subtrahiert die angegebene Menge von der Auftragssumme für jedes Produkt, der zu den ausgewählten Kategorien gehört. Wenn der Rabatt größer als der Gesamtauftrag ist, wird der Kunden nur die Versandkosten bezahlen oder nichts, wenn der Gutschein auch einen kostenlosen Versand bietet.', + 'This coupon subtracts the specified amount from the order total for each product which uses the selected attribute values. If the discount is greater than the total order, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.' => 'Dieser Gutschein subtrahiert die angegebene Menge von der Bestellsumme für jedes ausgewählten Produkt mit den ausgewählten Deklinationen. Wenn der Rabatt größer als der Gesamtauftrag ist, wird den Kunde nur die versandkosten bezahlen, oder nichts, wenn der Gutschein auch eine Kostenlose Lieferung bietet.', + 'This coupon subtracts the specified amount from the order total for each selected product. If the discount is greater than the total order, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.' => 'Dieser Gutschein subtrahiert die angegebene Menge von der Bestellsumme für jedes ausgewählten Produkt. Wenn der Rabatt größer als der Gesamtauftrag ist, wird den Kunde nur die versandkosten bezahlen, oder nichts, wenn der Gutschein auch eine Kostenlose Lieferung bietet.', + 'This coupon will offert a flat percentage off a shopper\'s entire order (not applied to shipping costs or tax rates). If the discount is greater than the total order corst, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.' => 'Dieser Gutschein bietet einen fixen Prozentsatz-Rabatt auf den Bestellwert (ausgenommen Versandkosten und Steuern). Wenn der Rabatt den Bestellwert übersteigt, zahlt der Kunde nur die Versandkosten, oder gar nichts, wenn der Gutschein kostenlosen Versand beeinhaltet.', + 'This coupon will subtracts a set amount from the total cost of an order. If the discount is greater than the total order corst, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.' => 'Dieser Gutschein subtrahiert eine festgelegte Menge von der Bestellsumme. Wenn der Rabatt größer als der Gesamtauftrag ist, wird den Kunde nur die versandkosten bezahlen, oder nichts, wenn der Gutschein auch eine Kostenlose Lieferung bietet.', + 'This document is online' => 'Dieser Dokument ist online', + 'This email already exists.' => 'Diese E-Mail existiert bereits.', + 'This email does not exists' => 'Diese E-mail existiert nicht', + 'This folder is online.' => 'Diesen Ordner is Online. ', + 'This hook is specific to a module (delivery/payment modules).' => 'Dieses Hook ist spezifisch für ein Modul (Liefer- / Zahlungsmodule).', + 'This image is online' => 'Dieses Bild ist online', + 'This is a comma separated list of email addresses where store notifications (such as order placed) are sent.' => 'Liste von E-Mail Adressen für die Shop Benachrichtigungen (Neue Bestellung, usw.)', + 'This is an identifier that will be used in the code to get this message' => 'Es ist eine Kennung, die im Code verwendet wird um diese Nachricht zu erhalten', + 'This is the contact email address, and the sender email of all e-mails sent by your store.' => 'Kontakt E-Mail-Adresse und E-Mail-Absender aller E-Mails die von Ihrem Shop gesendet werden. ', + 'This is the message purpose, such as \'Order confirmation\'.' => 'Nachricht Betreff, wie "Bestellungs Bestätigung" ', + 'This is the subject of the e-mail, such as \'Your order is confirmed\'.' => 'Betreff der E-Mail, wie \'Ihre Bestellung wird bestätigt\'.', + 'This module has no Markdown documentation.' => 'Dieses Modul hat keine Markdown Dokumentation', + 'This product does not have a physical presence' => 'Dieses Produkt ist virtuell', + 'This product is on sale' => 'Sonderangebot Produkt', + 'This product is online' => 'Dieses Produkt ist online', + 'This product reference is already assigned to another product.' => 'Diese Produkt Referenz', + 'This product_sale_elements_id does not exists for this product : %d' => 'Diese product_sale_elements_id existiert für dieses Produkt nicht : %d', + 'This template is in use in some of your products, and cannot be deleted. Delete it from all your products and try again.' => 'Diese Vorlage wird für Produkte benutzt und kann nicht gelöscht werden. Löschen Sie die Vorlage von allen Ihren Produkten und versuchen Sie es erneut.', + 'This the unique name of this message. Do not change this value unless you understand what you do.' => 'Das ist die eindeutige Name der Nachricht. Ändern Sie diesen Wert nur wenn Sie genau verstehen was Sie tun. ', + 'This value should not be blank.' => 'Diese Angabe soll nicht leer sein', + 'Timeout' => 'Zeitüberschreitung', + 'Title' => 'Titel', + 'Title *' => 'Titel *', + 'Title ID not found' => 'Titel ID wurde nicht gefunden', + 'To activate module %name, the following modules should be activated first: %modules' => 'Um das Modul %name zu aktivieren, müssen zuerst die folgenden Modulen aktivert werden : %modules', + 'Tools' => 'Werkzeuge', + 'Translations' => 'Übersetzungen', + 'Tried to download a file, but the URL was not valid: %url' => 'Versucht die Datei herunterzuladen, aber die URL war nicht gültig: %url', + 'Type' => 'Typ', + 'URL_ALREADY_EXISTS' => 'URL_ALREADY_EXISTS', + 'Unable to get module code from the fullnamespace element of the module descriptor: \'%val\'' => 'Der Modulecode aus dem Fullnamespace Element des Deskriptors konnte nicht erhalten werden: \' % Val\'', + 'Unable to process your request. Please try again (%err).' => 'Die Anfrage konnte nicht bearbeitet werden. Bitte versuchen Sie es erneut (%err).', + 'Unconditional usage' => 'Bedingungslose Nutzung', + 'Unconditionnal usage' => 'Bedingungslose Nutzung', + 'Undefined loop argument "%name"' => 'Undefiniertes Loop-Argument "%name"', + 'Undefined search mode \'%mode\'' => 'Undefinierter Suchmodus \' %\'', + 'Unknown order ID: %id' => 'Unbekannte Bestellung ID: %id', + 'Unsupported magic method %name. only getArgname() is supported.' => 'Nicht unterstützte magische Methode %name. Nur getArgname() wird unterstützt.', + 'Unsupported type' => 'Nicht unterstützte Typ', + 'Update customer account' => 'Kundenkonto aktualisieren', + 'Use the keyword phrase in your URL.' => 'Verwenden Sie Keywords in Ihren URL.', + 'Used in your store front' => 'Im Front Shop angezeigt', + 'Username' => 'Benutzername', + 'Username or e-mail address *' => 'Benutzername oder E-mail Adresse *', + 'Valid only from %date% to the coupon expiration date' => 'Gültig vom %date% bis dem Ablaufsdatum des Gutscheins. ', + 'Value' => 'Angabe', + 'Value %val for Discount Amount is invalid. Please enter a positive value.' => 'Der Wert %val für den Preis Rabatt ist ungültig. Bitte geben Sie einen positiven Wert. ', + 'Value %val for Percent Discount is invalid. Please enter a positive value between 1 and 100.' => 'Der Wert %val für den Prozentualen Rabatt ist ungültig. Bitte geben Sie einen positiven Wert zwischen 1 und 100. ', + 'Value *' => 'Angabe *', + 'Value create form' => 'Angabe-Erstellungsformular', + 'Variable' => 'Angabe', + 'Variables' => 'Angaben', + 'Virtual document' => 'Virtuelles Dokument', + 'Warnings' => 'Warnungen', + 'We\'re sorry, this PDF invoice is not available at the moment.' => 'Leider ist diese PDF-Rechnung im Moment nicht verfügbar.', + 'Weight' => 'Gewicht', + 'Wrong form method, %s expected.' => 'Ungültige HTTP-Methode, %s erwartet. ', + 'Yes, I have a password :' => 'Ja, ich habe ein Passwort :', + 'You are already registered!' => 'Sie sind bereits registriert!', + 'You don\'t need to use commas or other punctuations.' => 'Sie brauchen keine Komma oder Satzzeichen verwenden', + 'You have to configure your store email first !' => 'Sie müssen Ihre Shop E-Mail zuerst konfigurieren !', + 'You should select a state for this country.' => 'Wählen Sie ein Bundesland für dieses Land.', + 'You\'ve submitted this form too many times. ' => 'Sie haben dieses Formular zu oft vorgelegt.', + 'Your Email Address' => 'Ihre E-mail Adresse', + 'Your Message' => 'Ihre Nachricht', + 'Your configuration seems to be ok. Checked out your mailbox : %email%' => 'Ihre Konfiguration ist in Ordnung. Überprüfen Sie Ihre Mailbox : %email%', + 'Your current password does not match.' => 'Das Passwort stimmt nicht überein', + 'Your zip must contain 1 root directory which is the root folder directory of your module' => 'Ihre Zip-Datei muss einen Root-Ordner enthalten, der Ihre Moduldateien beinhaltet', + 'Zip code' => 'PLZ', + 'Zone' => 'Zone', + 'accessories table header' => 'Zubehör-Tabellenkopf', + 'accessories table row' => 'Zubehör-Tabellenzeile', + 'add to all form' => 'Zu Allen hinzufügen Formular', + 'additional information' => 'weitere Informationen', + 'address create form' => 'Adresse-Erstellungs-Formular', + 'address delete form' => 'Adresse-Löschungs-Formular', + 'address update form' => 'Adresse-Aktualisierungs-Formular', + 'after addresse area' => 'Nach dem Adressebereich', + 'after combinations' => 'Nach den Kombinationen', + 'after footer' => 'Nach dem Footer', + 'after javascript include' => 'Nach Integration von Javascript', + 'after javascript initialisation' => 'Nach Initialisierung von Javascript', + 'after product listing' => 'Nach der Produktliste', + 'after the information area' => 'Nach dem Informationsbereich', + 'after the main content area' => 'Nach dem Hauptinhaltsbereich', + 'after the opening of the body tag' => 'Nach der Eröffnung des Body-Tags', + 'after the opening of the head tag' => 'Nach der Eröffnung des Head-Tags', + 'after the order summary' => 'Nach der Bestellzusammenfassung', + 'after top bar' => 'Nach dem Top-Bar', + 'after top menu' => 'Nach dem Top-Menü', + 'api id %id does not exists' => 'Api ID %id existiert nicht', + 'at the bottom' => 'Unten', + 'at the bottom of column 1' => 'Unten der Spalte 1', + 'at the bottom of information area' => 'Unten am Informationsbereich', + 'at the bottom of the catalog' => 'Unten dem Katalog', + 'at the bottom of the detail area' => 'Unten dem Detailbereich', + 'at the bottom of the footer' => 'Unten am Footer', + 'at the bottom of the form' => 'Unten dem Formular', + 'at the bottom of the header' => 'Untem dem Header', + 'at the bottom of the main area' => 'Untem dem Hauptgebiet', + 'at the bottom of the shipping area' => 'Untem dem Lieferbereich', + 'at the bottom of the sidebar' => 'Unten dem Sidebar', + 'at the bottom of the system area' => 'Unten dem Systembereich', + 'at the bottom of the top bar' => 'Unten dem Top-Bar', + 'at the top' => 'Oben', + 'at the top of the catalog area' => 'Oben dem Katalog', + 'at the top of the column' => 'Oben der Spalte', + 'at the top of the configuration' => 'Oben an der Konfiguration', + 'at the top of the detail' => 'Oben dem Detailbereich', + 'at the top of the footer' => 'Oben dem Footer', + 'at the top of the form' => 'Oben dem Formular', + 'at the top of the header' => 'Oben dem Header', + 'at the top of the main area' => 'Oben dem Hauptgebiet', + 'at the top of the shipping area' => 'Oben dem Lieferbereich', + 'at the top of the sidebar' => 'Oben dem Sidebar', + 'at the top of the system area' => 'Oben dem Systembereich', + 'at the top of the top bar' => 'Oben dem Top-Bar', + 'attributes table header' => 'Deklinations-Tabellenkopf', + 'attributes table row' => 'Deklinations-Tabellenzeile', + 'before combinations' => 'Vor den Kombinationen', + 'before footer' => 'Vor dem Footer', + 'before the end body tag' => 'Vor dem Ende des Body-Tags', + 'before the end of the head tag' => 'Vor dem Ende des Head-Tags', + 'before the main content area' => 'Vor dem Hauptinhaltsbereich', + 'before top menu' => 'Vor Top-Menü', + 'before topbar' => 'Vor dem Top-Bar', + 'block' => 'Block', + 'bottom' => 'Unten', + 'bottom of the footer' => 'Unter dem Footer', + 'cURL errno %errno, http code %http_code on link "%path": %error' => 'cURL errno %errno, http code %http_code zu link "%path": %error', + 'caption' => 'Beschreibung', + 'categories table header' => 'Kategorien-Tabellenkopf', + 'categories table row' => 'Kategorien-Tabellenzeile', + 'combination delete form' => 'Kombinations-Löschungs-Formular', + 'combinations list caption' => 'Kombinationsliste-Beschreibung', + 'configuration' => 'Konfiguration', + 'configuration JavaScript' => 'JavaScript-Konfiguration', + 'configuration bottom' => 'Unten an der Konfiguration', + 'content' => 'Inhalt', + 'content area' => 'Inhaltsbereich', + 'content delete form' => 'Inhalts-Löschungsformular', + 'content edit JavaScript' => 'Inhalt-Bearbeitung Javascript', + 'contents table header' => 'Inhlats-Tabellenkopf', + 'contents table row' => 'Inhalts-Tabellenzeile', + 'context' => 'Kontext', + 'country delete form' => 'Land-Löschungsformular', + 'create JavaScript' => 'Erstellung Javascript', + 'create form' => 'Erstellungsformular', + 'customer account' => 'Kundenkonto', + 'date format' => 'Datum Format', + 'decimal separator' => 'Dezimaltrennzeichen', + 'delete form' => 'Löschungsformular', + 'delivery address' => 'Liefer-Adresse', + 'delivery module %s is not a Thelia\Module\DeliveryModuleInterface' => 'Liefermodul %s ist nicht ein Thelia\Module\DeliveryModuleInterface ', + 'details pricing form' => 'Preise-Detailsformular', + 'details promotion form' => 'Sonderangebot-Detailsformular', + 'email' => 'E-mail', + 'email confirmation is not the same as email field' => 'E-Mail Bestätigung ist nicht die selbe als die erste E-Mail Adresse', + 'email system JavaScript' => 'E-MailSystem Javascript', + 'extra area' => 'Zusätzliches Bereich', + 'extra payment zone' => 'Zusätzliche Zahlungsgebiet', + 'features table row' => 'Charakteristik-Tabellenzeile', + 'features-table-header' => 'Charakteristik-Tabellenkopf', + 'folders table header' => 'Ordner-Tabellenkopf', + 'folders table row' => 'Ordner-Tabellenzeile', + 'footer body' => 'Footer Body', + 'header' => 'Header', + 'hook delete form' => 'Hook-Löschungsformular', + 'hook edit JavaScript' => 'Hook Bearbeitung Javascript', + 'hour(s)' => 'Stunde(n)', + 'id delete form' => 'ID-Löschungsformular', + 'if successful response' => 'wenn erfolgreiche Antwort', + 'imprint' => 'Impressum', + 'in footer' => 'Im Footer', + 'in the header' => 'Im Header', + 'in the menu catalog' => 'In dem Katalogs-Menü', + 'in the menu configuration' => 'In dem Konfigurations-Menü', + 'in the menu customers' => 'In dem Kunde-Menü', + 'in the menu folders' => 'In dem Ordner-Menü', + 'in the menu modules' => 'In dem Modul-Menü', + 'in the menu orders' => 'In dem Bestellungs-Menü', + 'in the menu tools' => 'In dem Werkzeug-Menü', + 'in top menu items' => 'Top-Menü Elemente', + 'inside top bar' => 'In der Titelleiste', + 'javascript' => 'Javascript', + 'javascript initialization' => 'Javascript-Initialisation', + 'label' => 'Label', + 'language locale' => 'Sprache der Locale', + 'language selection page' => 'Sprachwahl-Seite', + 'list JavaScript' => 'Liste Javascript', + 'list caption' => 'Liste-Bildunterschrift', + 'list header' => 'Liste-Tabellenkopf', + 'list row' => 'Liste Zeile', + 'logs JavaScript' => 'Logs JavaScript', + 'mailing system modification' => 'Mailing System Bearbeitung', + 'main area' => 'Hauptgebiet', + 'middle' => 'Mitte', + 'minute(s)' => 'Minute(n)', + 'password confirmation is not the same as password field' => 'Die Passwort-Bestätigung sctimmt nicht', + 'password must be composed of at least 4 characters' => 'Das Passwort muss aus mindestens 4 Zeichen bestehen', + 'payment module %s is not a Thelia\Module\PaymentModuleInterface' => 'Zahlungsmodul %s ist nicht ein Thelia\Module\PaymentModuleInterface ', + 'pdf' => 'Pdf', + 'permanent discount (in percent)' => 'Dauerrabatt', + 'photo gallery' => 'Foto-Galerie', + 'plain, login, cram-md5 or empty' => 'normal, login, cram-md5 oder leer', + 'primary navigation' => 'Hauptnavigation', + 'product list' => 'Produkt Liste', + 'quantity value is not valid' => 'Menge Angabe ist nicht gültig', + 'remove to all form' => 'Multipel Löschungsformular', + 'row' => 'Zeile', + 'rule create form' => 'Regel-Erstellungsformular', + 'rule delete form' => 'Regel-Löschungsformular', + 'rule edit JavaScript' => 'Regel Bearbeitung Javascript', + 'secondary navigation' => 'Sekundäre Navigation', + 'ssl, tls or empty' => 'SSL, TLS oder leer', + 'stock edit form' => 'Lager-Bearbeiungsformular', + 'table header' => 'Tabellenkopf', + 'table row' => 'Tabellenzeile', + 'tax rule' => 'Taxregelung', + 'the body of the sidebar' => 'Der Körper der Sidebar', + 'this product id does not exists : %d' => 'Diese Produkt ID existiert nicht : %d', + 'thousands separator' => 'Tausender-Trennzeichen', + 'time format' => 'Zeit Format', + 'type' => 'Typ', + 'update JavaScript' => 'JavaScript aktualisieren', + 'update form' => 'Formular aktualisieren', + 'value table header' => 'Angabe-Tabellenkopf', + 'value table row' => 'Angabe-Tabellenzeile', +]; diff --git a/core/lib/Thelia/Config/I18n/el_GR.php b/core/lib/Thelia/Config/I18n/el_GR.php new file mode 100644 index 00000000..3e468245 --- /dev/null +++ b/core/lib/Thelia/Config/I18n/el_GR.php @@ -0,0 +1,33 @@ + 'η παράμετρος "%param" δεν μπορεί να είναι κενή στο βρόχο τύπο: %type, name:%name', + '"%param" parameter is missing in loop type: %type, name: %name' => 'η παράμετρος "%param" δεν υπάρχει στο βρόχο τύπος: %type, όνομα: %name', + '%obj creation' => 'δημιουργία %obj', + '%obj modification' => 'τροποποίηση %obj', + 'Address Line 2' => 'Διεύθυνση γραμμή 2', + 'Address Line 3' => 'Διεύθυνση γραμμή 3', + 'Address label' => 'Ετικέτα διεύθυνσης', + 'Address update' => 'Ενημέρωση διεύθυνσης', + 'Administrator ID not found' => 'ID διαχειριστή δεν βρέθηκε', + 'Amount' => 'Ποσό', + 'Business ID' => 'ID επιχείρησης', + 'Cannot find a default country. Please define one.' => 'Δεν μπορώ να βρω την χώρα προεπιλογής. Παρακαλώ καθορίστε την.', + 'Cart' => 'Καλάθι', + 'Categories' => 'Kατηγορίες', + 'Currency' => 'Nόμισμα', + 'Edit' => 'Επεξεργασία', + 'Email address' => 'Διεύθυνση E-mail', + 'Error occured while processing order ref. %ref, ID %id: %err' => 'Error occured while processing order ref. %ref, ID %id: %err', + 'Home' => 'Αρχή', + 'Language' => 'Γλώσσα', + 'Name' => 'Όνομα', + 'Password' => 'Κωδικός', + 'Quantity' => 'Ποσότητα', + 'Register' => 'Καταχώρηση', + 'Search' => 'Αναζήτηση', + 'Sorry, an error occured: %msg' => 'Sorry, an error occured: %msg', + 'Store logs into text file, up to a certian size, then a new file is created' => 'Store logs into text file, up to a certian size, then a new file is created', + 'This coupon will offert a flat percentage off a shopper\'s entire order (not applied to shipping costs or tax rates). If the discount is greater than the total order corst, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.' => 'This coupon will offert a flat percentage off a shopper\'s entire order (not applied to shipping costs or tax rates). If the discount is greater than the total order corst, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.', + 'This coupon will subtracts a set amount from the total cost of an order. If the discount is greater than the total order corst, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.' => 'This coupon will subtracts a set amount from the total cost of an order. If the discount is greater than the total order corst, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.', +]; diff --git a/core/lib/Thelia/Config/I18n/en_US.php b/core/lib/Thelia/Config/I18n/en_US.php new file mode 100644 index 00000000..34bb8ff6 --- /dev/null +++ b/core/lib/Thelia/Config/I18n/en_US.php @@ -0,0 +1,866 @@ + ' content creation form', + ' 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 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)', + '%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 creation' => '%obj creation', + '%obj modification' => '%obj modification', + '%obj%s deleted successfully' => '%obj%s deleted successfully', + '%s has dependency to module %s. You have to deactivate this module before.' => '%s has dependency to module %s. You have to deactivate this module before.', + '%s have dependencies to module %s. You have to deactivate these modules before.' => '%s have dependencies to module %s. You have to deactivate these modules before.', + '%type% position updated' => '%type% position updated', + '%type% visibility updated' => '%type% visibility updated', + 'A Hook with code %name already exists. Please choose another code.' => 'A Hook with code %name already exists. Please choose another code.', + 'A comma separated list of email addresses' => 'A comma separated list of email addresses', + 'A currency with code "%name" already exists.' => 'A currency with code "%name" already exists.', + 'A descriptive title' => 'A descriptive title', + 'A message with name "%name" already exists.' => 'A message with name "%name" already exists.', + 'A name such as Europe or Overseas' => 'A name such as Europe or Overseas', + 'A product with reference %ref already exists. Please choose another reference.' => 'A product with reference %ref already exists. Please choose another reference.', + 'A short description, used when a summary or an introduction is required' => 'A short description, used when a summary or an introduction is required', + 'A short text, used when an additional or supplemental information is required.' => 'A short text, used when an additional or supplemental information is required.', + 'A user already exists with this email address. Please login or if you\'ve forgotten your password, go to Reset Your Password.' => 'A user already exists with this email address. Please login or if you\'ve forgotten your password, go to Reset Your Password.', + 'A value for attribute "%name" is already present in the combination' => 'A value for attribute "%name" is already present in the combination', + 'A variable with name "%name" already exists.' => 'A variable with name "%name" already exists.', + 'Activate logs only for these IP Addresses' => 'Activate logs only for these IP Addresses', + 'Activate logs only for these files' => 'Activate logs only for these files', + 'Activate this sale' => 'Activate this sale', + 'Active' => 'Active', + 'Add to all product templates' => 'Add to all product templates', + 'Additional address' => 'Additional address', + 'Additional address information' => 'Additional address information', + 'Address ID not found' => 'Address ID not found', + 'Address Line 2' => 'Address Line 2', + 'Address Line 3' => 'Address Line 3', + 'Address creation' => 'Address creation', + 'Address label' => 'Address label', + 'Address update' => 'Address update', + 'Address.' => 'Address.', + 'Addresses for this country need a zip code' => 'Addresses for this country need a zip code', + 'Administrator' => 'Administrator', + 'Administrator ID not found' => 'Administrator ID not found', + 'Administrator email address' => 'Administrator email address', + 'Administrators' => 'Administrators', + 'Advertise this product as new' => 'Advertise this product as new', + 'Alerts' => 'Alerts', + 'All Products' => 'All Products', + 'All countries' => 'All countries', + 'All shipping methods' => 'All shipping methods', + '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 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', + 'Archive Format' => 'Archive Format', + 'Associate documents' => 'Associate documents', + 'Associate images' => 'Associate images', + 'At least one of cart products categories is %op% %categories_list%' => 'At least one of cart products categories is %op% %categories_list%', + 'Attribut' => 'Attribut', + 'Attribute ID:Attribute AV ID' => 'Attribute ID:Attribute AV ID', + 'Attribute value' => 'Attribute value', + 'Attributes' => 'Attributes', + 'Attributes value' => 'Attributes value', + 'Auth mode' => 'Auth mode', + 'Automatic rendered templates' => 'Automatic rendered templates', + 'Available quantity' => 'Available quantity', + 'Available quantity *' => 'Available quantity *', + 'Available shipping zones' => 'Available shipping zones', + 'Back Office' => 'Back Office', + 'Bad tax list JSON' => 'Bad tax list JSON', + 'Banner' => 'Banner', + 'Banner of the website. Used in the e-mails send to the customers.' => 'Banner displayed in the e-mails sent to your customers.', + 'Billing country' => 'Billing country', + 'Billing country is' => 'Billing country is', + 'Brand' => 'Brand', + 'Brand / Supplier' => 'Brand / Supplier', + 'Brand name' => 'Brand name', + 'Brands' => 'Brands', + 'Business ID' => 'Business ID', + 'By Module' => 'By Module', + 'CSS' => 'CSS', + '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 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 hide the default language' => 'Cannot hide the default language', + 'Cannot instantiate module "%name%": the namespace is null. Maybe the model is not loaded ?' => 'Cannot instantiate module "%name%": the namespace is null. Maybe the model is not loaded ?', + 'Cart' => 'Cart', + 'Cart contains at least a product %op% %products_list%' => 'Cart contains at least a product %op% %products_list%', + 'Cart contains categories condition' => 'Cart contains categories condition', + 'Cart contains specific products' => 'Cart contains specific products', + 'Cart item count' => 'Cart item count', + 'Cart item count is' => 'Cart item count is', + 'Cart item include quantity count' => 'Cart item include quantity count', + 'Cart item include quantity count is' => 'Cart item include quantity count is', + 'Cart total amount' => 'Cart total amount', + 'Cart total amount is' => 'Cart total amount is', + 'Catalog' => 'Catalog', + 'Catalog configuration' => 'Catalog configuration', + 'Categories' => 'Categories', + 'Category' => 'Category', + 'Category page' => 'Category page', + 'Category title' => 'Category title', + 'Cellphone' => 'Cellphone', + 'Change password' => 'Change password', + 'Check country iso codes here.' => 'Check country iso codes in Wikipedia.', + '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', + 'Code' => 'Code', + 'Combination builder' => 'Combination builder', + 'Compagny' => 'Compagny', + 'Company' => 'Company', + 'Company Name' => 'Company Name', + 'Conclusion' => 'Conclusion', + 'Configuration' => 'Configuration', + 'Confirm Email Address' => 'Confirm your e-mail address', + 'Confirm Email address' => 'Confirm your e-mail address', + 'Constant amount' => 'Constant amount', + 'Constant amount found in one of the product\'s feature' => 'Constant amount found in one of the product\'s feature', + 'Contact and sender email address' => 'Contact and sender email address', + 'Contact page' => 'Contact page', + 'Content' => 'Content', + 'Content page' => 'Content page', + 'Content title *' => 'Content title *', + 'Contents' => 'Contents', + 'Copy of %tpl' => 'Copy of %tpl', + 'Core hook of Thelia.' => 'Core hook of Thelia.', + 'Countries' => 'Countries', + 'Country' => 'Country', + 'Country ID %id not found' => 'Country ID %id not found', + 'Country ID not found' => 'Country ID not found', + 'Country list is not valid JSON' => 'Country list is not valid JSON', + 'Country title' => 'Country title', + 'Coupon' => 'Coupon', + 'Coupon %code is expired.' => 'Coupon %code is expired.', + 'Coupon %code is not release.' => 'Coupon %code is not release.', + 'Coupon code %code is disabled.' => 'Coupon code %code is disabled.', + 'Critical' => 'Critical', + 'Curency selection page' => 'Curency selection page', + 'Currencies' => 'Currencies', + 'Currency' => 'Currency', + 'Currency name' => 'Currency name', + 'Current Password' => 'Current Password', + 'Customer' => 'Customer', + 'Customer is %op% %customer_list%' => 'Customer is %op% %customer_list%', + 'Customers' => 'Customers', + 'Dashboard' => 'Dashboard', + 'Date \'%date\' is invalid, please enter a valid date using %fmt format' => 'Date \'%date\' is invalid, please enter a valid date using %fmt format', + 'Debug' => 'Debug', + 'Decimal places' => 'Decimal places', + 'Default folder *' => 'Default folder *', + 'Default product category *' => 'Default product category *', + 'Default product sale element' => 'Default product sale element', + 'Default product template' => 'Default product template', + 'Deleting %obj% for %id% with parent id %parentId%' => 'Deleting %obj% for %id% with parent id %parentId%', + 'Delivery' => 'Delivery', + 'Delivery choice' => 'Delivery choice', + 'Delivery country' => 'Delivery country', + 'Delivery country is' => 'Delivery country is', + 'Delivery module ID not found' => 'Delivery module ID not found', + 'Delivery zone' => 'Delivery zone', + 'Detailed description' => 'Detailed description', + 'Disabled' => 'Disabled', + 'Discount type' => 'Discount type', + 'Display initial product prices on front-office' => 'Display initial product prices on front-office', + 'Do compress' => 'Do compress', + 'Document' => 'Document', + 'Don\'t repeat keywords over and over in a row. Rather, put in keyword phrases.' => 'Don\'t repeat keywords over and over in a row. Rather, put in keyword phrases.', + 'EAN Code' => 'EAN Code', + 'Edit' => 'Edit', + 'Edit JavaScript' => 'Edit JavaScript', + 'Email Address' => 'Email Address', + 'Email address' => 'Email address', + 'Email addresses of notification recipients' => 'Email addresses of notification recipients', + 'Email test from : %store%' => 'Email test from : %store%', + 'Emergency' => 'Emergency', + 'Enable remote SMTP use' => 'Enable remote SMTP use', + 'Encryption' => 'Encryption', + 'End date of sales' => 'End date of sales', + '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 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 the new password' => 'Enter the new password', + 'Enter the new password again' => 'Enter the new password again', + 'Equal to' => 'Equal to', + '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.' => '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 :
%errors' => 'Error(s) in import :
%errors', + 'Errors' => 'Errors', + 'Export' => 'Export', + 'Fail to delete %obj% for %id% with parent id %parentId% (Exception : %e%)' => 'Fail to delete %obj% for %id% with parent id %parentId% (Exception : %e%)', + 'Fail to update %type% position: %err%' => 'Fail to update %type% position: %err%', + 'Fail to update %type% visibility: %err%' => 'Fail to update %type% visibility: %err%', + 'Failed to create instance of module "%name%" when trying to delete module. Module directory has probably been deleted' => 'Failed to create instance of module "%name%" when trying to delete module. Module directory has probably been deleted', + 'Failed to create new hook %s' => 'Failed to create new hook %s', + 'Failed to deactivate hook with id %s' => 'Failed to deactivate hook with id %s', + 'Failed to delete selected countries' => 'Failed to delete selected countries', + 'Failed to find a payment Module with ID=%mid for order ID=%oid' => 'Failed to find a payment Module with ID=%mid for order ID=%oid', + 'Failed to load descriptor (module.xml) for module ID "%id".' => 'Failed to load descriptor (module.xml) for module ID "%id".', + 'Failed to load message with code \'%code%\', propably because it does\'nt exists.' => 'Failed to load message with code \'%code%\', probably because it does\'nt exists.', + 'Failed to open a writing stream on the file: %file' => 'Failed to open a writing stream on the file: %file', + 'Failed to open translation file %file. Please be sure that this file is writable by your Web server' => 'Failed to open translation file %file. Please be sure that this file is writable by your Web server', + 'Failed to send message %code. Failed recipients: %failed_addresses' => 'Failed to send message %code. Failed recipients: %failed_addresses', + 'Failed to update language definition: %ex' => 'Failed to update language definition: %ex', + 'Favicon image' => 'Favicon image', + 'Fax' => 'Fax', + 'Feature' => 'Feature', + 'Feature value does not match FLOAT format' => 'Feature value does not match FLOAT format', + 'Features' => 'Features', + 'Features value' => 'Features value', + 'File format' => 'File format', + 'File is too large, please retry with a file having a size less than %size%.' => 'File is too large, please retry with a file having a size less than %size%.', + 'File to upload' => 'File to upload', + 'Files with the following extension are not allowed: %extension, please do an archive of the file if you want to upload it' => 'Files with the following extension are not allowed: %extension, please do an archive of the file if you want to upload it', + 'First Name' => 'First Name', + 'Firstname' => 'Firstname', + 'Fixed Amount Discount' => 'Fixed Amount Discount', + 'Fixed amount discount for selected attribute values' => 'Fixed amount discount for selected attribute values', + 'Fixed amount discount for selected categories' => 'Fixed amount discount for selected categories', + 'Fixed amount discount for selected products' => 'Fixed amount discount for selected products', + 'Folder' => 'Folder', + 'Folder page' => 'Folder page', + 'Folder title *' => 'Folder title *', + 'For one ore more customers' => 'For one ore more customers', + 'Format' => 'Format', + 'Free product when buying one or more selected products' => 'Free product when buying one or more selected products', + 'Front Office' => 'Front Office', + 'Full Name' => 'Full Name', + 'Further submissions will be ignored during %time' => 'Further submissions will be ignored during %time', + 'Greater than' => 'Greater than', + 'Greater than or equals' => 'Greater than or equals', + 'HTML Message' => 'HTML Message', + 'HTML layout' => 'HTML layout', + 'Home' => 'Home', + 'Home page' => 'Home page', + 'Hook' => 'Hook', + 'Hook block' => 'Hook block', + 'Hook code' => 'Hook code', + 'Hook create form' => 'Hook creation form', + 'Hook title' => 'Hook title', + 'Hooks' => 'Hooks', + 'Host' => 'Host', + 'I would like to receive the newsletter or the latest news.' => 'I would like to receive the newsletter or the latest news.', + 'ISO 4217 code' => 'ISO 4217 code', + 'ISO 639-1 Code' => 'ISO 639-1 Code', + 'ISO Alpha-2 code' => 'ISO Alpha-2 code', + 'ISO Alpha-3 code' => 'ISO Alpha-3 code', + 'ISO Code' => 'ISO Code', + 'Icon of the website. Only PNG and ICO files are allowed.' => 'Icon of the website. Only PNG and ICO files are allowed.', + 'If a translation is missing or incomplete :' => 'If a translation is missing or incomplete :', + 'If cart item (include quantity) count is %operator% %quantity%' => 'If cart item (include quantity) count is %operator% %quantity%', + 'If cart item count is %operator% %quantity%' => 'If cart item count is %operator% %quantity%', + 'If cart total amount is %operator% %amount% %currency%' => 'If cart total amount is %operator% %amount% %currency%', + 'If checked, this hook will be used by a hook block. If not, by hook function.' => 'If checked, this hook will be used by a hook block. If not, by hook function.', + 'If you use automatic insert templates, you should use the method %method%' => 'If you use automatic insert templates, you should use the method %method%', + 'Image' => 'Image', + 'Import successfully done, %count row(s) have been changed' => 'Import successfully done, %count row(s) have been changed', + 'Impossible to check value `%value` for `%type` type' => 'Impossible to check value `%value` for `%type` type', + 'Impossible to delete a customer who already have orders' => 'Impossible to delete a customer who already have orders', + 'In' => 'In', + 'Include documents' => 'Include documents', + 'Include images' => 'Include images', + 'Information' => 'Information', + 'Invalid product_sale_elements' => 'Invalid product_sale_elements', + 'Invalid username or email.' => 'Invalid username or email.', + 'Invalid value "%value" for "%param" parameter in loop type: %type, name: %name' => 'Invalid value "%value" for "%param" parameter in loop type: %type, name: %name', + 'Invalid value for walkMode parameter: %value' => 'Invalid value for walkMode parameter: %value', + 'Invoice' => 'Invoice', + 'Invoice choice' => 'Invoice choice', + 'Is it the default product sale element ?' => 'Is it the default product sale element ?', + 'Iso code for states. It depends of the country.' => 'Iso code for states. It depends of the country.', + 'It is not allowed to delete the default currency' => 'It is not allowed to delete the default currency', + 'It is not allowed to delete the default language' => 'It is not allowed to delete the default language', + 'JavaScript' => 'JavaScript', + 'Keep the most important part of your description in the first 150-160 characters.' => 'Keep the most important part of your description in the first 150-160 characters.', + 'Language' => 'Language', + 'Language name' => 'Language name', + 'Languages' => 'Languages', + 'Last Name' => 'Last Name', + 'Lastname' => 'Lastname', + 'Layout' => 'Layout', + 'Leave blank to keep current customer password' => 'Leave blank to keep current customer password', + 'Less than' => 'Less than', + 'Less than or equals' => 'Less than or equals', + 'Log format *' => 'Log format *', + 'Log level *' => 'Log level *', + 'Login failed. Please check your username and password.' => 'Login failed. Please check your username and password.', + 'Login name' => 'Login name', + 'Login page' => 'Login page', + 'Logs' => 'Logs', + 'Loop cannot implements multiple Search Interfaces : `PropelSearchLoopInterface`, `ArraySearchLoopInterface`' => 'Loop cannot implements multiple Search Interfaces : `PropelSearchLoopInterface`, `ArraySearchLoopInterface`', + 'Loop must implements \'PropelSearchLoopInterface\' to be timestampable' => 'Loop must implements \'PropelSearchLoopInterface\' to be timestampable', + 'Loop must implements \'PropelSearchLoopInterface\' to be versionable' => 'Loop must implements \'PropelSearchLoopInterface\' to be versionable', + 'Loop must implements one of the following interfaces : `PropelSearchLoopInterface`, `ArraySearchLoopInterface`' => 'Loop must implements one of the following interfaces : `PropelSearchLoopInterface`, `ArraySearchLoopInterface`', + 'Lost password' => 'Lost password', + 'Mail template name' => 'Mail template name', + 'Mail template purpose' => 'Mail template purpose', + 'Mailing system' => 'Mailing system', + 'Main address' => 'Main address', + 'Main area' => 'Main area', + 'Make sure it uses keywords found within the page itself.' => 'Make sure it uses keywords found within the page itself.', + 'Make sure that your title is clear, and contains many of the keywords within the page itself.' => 'Make sure that your title is clear, and contains many of the keywords within the page itself.', + 'Make this address as my primary address' => 'Make this address as my primary address', + 'Maximum usage count reached for coupon %code' => 'Maximum usage count reached for coupon %code', + 'Message' => 'Message', + 'Message name' => 'Message name', + 'Message subject' => 'Message subject', + 'Messages' => 'Messages', + 'Meta Description' => 'Meta Description', + 'Meta Keywords' => 'Meta Keywords', + 'Method Name' => 'Method Name', + 'Missing or invalid data: %s' => 'Missing or invalid data: %s', + 'Module' => 'Module', + 'Module "%name%" directory was not found' => 'Module "%name%" directory was not found', + 'Module %name directory doesn\'t exists.' => 'Module %name directory doesn\'t exists.', + 'Module %name should have a config.xml in the Config directory.' => 'Module %name should have a config.xml in the Config directory.', + 'Module %name should have a module.xml in the Config directory.' => 'Module %name should have a module.xml in the Config directory.', + 'Module ID "%id" was not found.' => 'Module ID "%id" was not found.', + 'Module ID not found' => 'Module ID not found', + 'Module hook' => 'Module hook', + 'Modules' => 'Modules', + 'More information about ISO 4217' => 'More information about ISO 4217', + 'Name' => 'Name', + 'Name *' => 'Name *', + 'Name of the HTML layout file' => 'Name of the HTML layout file', + 'Name of the HTML template file' => 'Name of the HTML template file', + 'Name of the text layout file' => 'Name of the text layout file', + 'Name of the text template file' => 'Name of the text template file', + 'Native' => 'Native', + 'New Password' => 'New Password', + 'Newsletter page' => 'Newsletter page', + 'No %obj was created.' => 'No %obj was created.', + 'No %obj was updated.' => 'No %obj was updated.', + 'No module found for code \'%item\'' => 'No module found for code \'%item\'', + 'No, I am a new customer.' => 'No, I am a new customer.', + 'None' => 'None', + 'Not equal to' => 'Not equal to', + 'Not in' => 'Not in', + 'Notices' => 'Notices', + 'Numerical ISO Code' => 'Numerical ISO Code', + 'Only files having the following mime type are allowed: %types%' => 'Only files having the following mime type are allowed: %types%', + 'Only hookable modules are displayed in this menu.' => 'Only hookable modules are displayed in this menu.', + 'Only if order billing country is %op% %countries_list%' => 'Le pays de facturation de la commande est %op% %countries_list% ', + 'Only if order shipping country is %op% %countries_list%' => 'Le pays de livraison de la commande est %op% %countries_list% ', + 'Order' => 'Order', + 'Order address ID not found' => 'Order address ID not found', + 'Order failed' => 'Order failed', + '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 status code' => 'Order status code', + 'Order status color' => 'Order status color', + 'Order status name' => 'Order status name', + 'Orders' => 'Orders', + 'Overall' => 'Overall', + 'Page 404' => 'Page 404', + 'Page Title' => 'Page Title', + 'Parent category' => 'Parent category', + 'Parent folder *' => 'Parent folder *', + 'Password' => 'Password', + 'Password *' => 'Password *', + 'Password confirmation' => 'Password confirmation', + 'Payment failed' => 'Payment failed', + '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', + 'Percent' => 'Percent', + 'Percentage' => 'Percentage', + 'Percentage discount for selected attribute values' => 'Percentage discount for selected attribute values', + 'Percentage discount for selected categories' => 'Percentage discount for selected categories', + 'Percentage discount for selected products' => 'Percentage discount for selected products', + 'Percentage of the product price' => 'Percentage of the product price', + 'Phone' => 'Phone', + 'Placed order' => 'Placed order', + 'Please accept the Terms and conditions in order to register.' => 'Please accept the Terms and conditions in order to register.', + 'Please check your input: %error' => 'Please check your input: %error', + 'Please enter a valid email address' => 'Please enter a valid email address', + 'Please enter your email address' => 'Please enter your email address', + 'Please enter your password' => 'Please enter your password', + 'Please select a category' => 'Please select a category', + 'Please select an attribute' => 'Please select an attribute', + 'Please select at least one attribute value' => 'Please select at least one attribute value', + 'Please select at least one category' => 'Please select at least one category', + 'Please select at least one product' => 'Please select at least one product', + 'Please select the category of the offred product' => 'Please select the category of the offred product', + 'Please select the offered product' => 'Please select the offered product', + 'Please upload a valid Zip file' => 'Please upload a valid Zip file', + 'Port' => 'Port', + 'Postage' => 'Postage', + 'Preferred language' => 'Preferred language', + 'Preferred locale' => 'Preferred locale', + 'Prevent mailing template modification or deletion, except for super-admin' => 'Prevent mailing template modification or deletion, except for super-admin', + 'Prevent variable modification or deletion, except for super-admin' => 'Prevent variable modification or deletion, except for super-admin', + 'Price currency *' => 'Price currency *', + 'Processing cancelation of payment for order ref. %ref' => 'Processing cancelation of payment for order ref. %ref', + 'Processing confirmation of order ref. %ref, ID %id' => 'Processing confirmation of order ref. %ref, ID %id', + 'Prodcut ID *' => 'Prodcut ID *', + 'Product' => 'Product', + 'Product ID' => 'Product ID', + 'Product ID *' => 'Product ID *', + 'Product attributes' => 'Product attributes', + 'Product base price excluding taxes *' => 'Product base price excluding taxes *', + 'Product base price with taxes' => 'Product base price with taxes', + 'Product categories' => 'Product categories', + 'Product clone' => 'Product clone', + 'Product loop' => 'Product loop', + 'Product page' => 'Product page', + 'Product price excluding taxes' => 'Product price excluding taxes', + 'Product price excluding taxes *' => 'Product price excluding taxes *', + 'Product price including taxes' => 'Product price including taxes', + 'Product price offset for each currency' => 'Product price offset for each currency', + 'Product reference (must be unique)' => 'Product reference (must be unique)', + 'Product reference *' => 'Product reference *', + 'Product sale element ID *' => 'Product sale element ID *', + 'Product template' => 'Product template', + 'Product title' => 'Product title', + 'ProductSaleElement modification' => 'ProductSaleElement modification', + 'Products' => 'Products', + 'Profile' => 'Profile', + 'Profile Code' => 'Profile Code', + 'Profile ID not found' => 'Profile ID not found', + 'Profile `code` already exists' => 'Profile `code` already exists', + 'Profiles' => 'Profiles', + 'Purpose' => 'Purpose', + 'Purpose *' => 'Purpose *', + 'Quantity' => 'Quantity', + 'Range date End' => 'Range date End', + 'Range date Start' => 'Range date Start', + 'Rate' => 'Rate', + 'Rate from %currencyCode' => 'Rate from %currencyCode', + 'Recipient e-mail address' => 'Recipient e-mail address', + 'Redirecting ...' => 'Redirecting ...', + 'Redirecting to %url' => 'Redirecting to %url', + 'Reference' => 'Reference', + 'Reference *' => 'Reference *', + 'Register' => 'Register', + 'Remember me ?' => 'Remember me ?', + 'Remove X percent to total cart' => 'Remove X percent to total cart', + 'Replace by the default language' => 'Replace by the default language', + 'Replace current document by this file' => 'Replace current document by this file', + 'Replace current image by this file' => 'Replace current image by this file', + 'Reseller' => 'Reseller', + 'Rewriten URL' => 'Rewriten URL', + 'Rotated Text File' => 'Rotated Text File', + 'Sale announce label' => 'Sale announce label', + 'Sale price excluding taxes' => 'Sale price excluding taxes', + 'Sale price including taxes' => 'Sale price including taxes', + 'Sale title' => 'Sale title', + 'Saving %obj% for %parentName% parent id %parentId%' => 'Saving %obj% for %parentName% parent id %parentId%', + 'Search' => 'Search', + 'Search page' => 'Search page', + 'Select a default template for new products created in this category' => 'Select a default template for new products created in this category', + 'Select the brand logo' => 'Select the brand logo', + 'Select the brand logo amongst the brand images' => 'Select the brand logo amongst the brand images', + 'Select the categories of the products covered by this operation' => 'Select the categories of the products covered by this operation', + 'Select the countries to delete from this shipping zone' => 'Select the countries to delete from this shipping zone', + 'Select the countries to include in this shipping zone' => 'Select the countries to include in this shipping zone', + 'Select the discount type that will be applied to original product prices' => 'Select the discount type that will be applied to original product prices', + 'Select the parent category of this category.' => 'Select the parent category of this category.', + 'Select the product attributes included in this operation' => 'Select the product attributes included in this operation', + '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 virtual document' => 'Select the virtual document', + 'Send test e-mail to:' => 'Send test e-mail to:', + 'Service ID' => 'Service ID', + 'Shipping configuration' => 'Shipping configuration', + 'Shipping zone name' => 'Shipping zone name', + 'Short additional text' => 'Short additional text', + 'Short description text' => 'Short description text', + 'Show redirections *' => 'Show redirections *', + '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: %msg' => 'Sorry, an error occurred: %msg', + 'Sorry, an error occured: %s' => 'Sorry, an error occurred: %s', + 'Sorry, an error occurred: %err' => 'Sorry, an error occurred: %err', + 'Sorry, no email defined for this administrator.' => 'Sorry, no email defined for this administrator.', + 'Sorry, you are not allowed to perform this action.' => 'Sorry, you are not allowed to perform this action.', + 'Sorry, you\'re not allowed to perform this action' => 'Sorry, you\'re not allowed to perform this action', + 'Source IP' => 'Source IP', + 'Start date' => 'Start date', + 'Start date and expiration date are inconsistent' => 'Start date and expiration date are inconsistent', + 'Start date of sales' => 'Start date of sales', + 'State *' => 'State *', + 'State ID %id not found' => 'State ID %id not found', + 'State title' => 'State title', + 'Stock' => 'Stock', + 'Store Business Identification Number (SIRET, etc).' => 'Store Business Identification Number (SIRET, etc).', + 'Store Information' => 'Store Information', + 'Store configuration failed.' => 'Store configuration failed.', + 'Store description' => 'Store description', + 'Store email address' => 'Store email address', + 'Store logo' => 'Store logo', + 'Store logs into text file' => 'Store logs into text file', + 'Store logs into text file, up to a certian size, then a new file is created' => 'Store logs into text file, up to a certain size, then a new file is created', + 'Store name' => 'Store name', + 'Street Address' => 'Street Address', + 'Street Address ' => 'Street Address ', + 'Strictly use the requested language' => 'Strictly use the requested language', + 'Subject' => 'Subject', + 'Summary' => 'Summary', + 'Symbol' => 'Symbol', + 'System' => 'System', + 'System configuration' => 'System configuration', + 'System log configuration failed.' => 'System log configuration failed.', + 'Tax' => 'Tax', + 'Tax ID not found in tax list JSON' => 'Tax ID not found in tax list JSON', + 'Tax list is not valid JSON' => 'Tax list is not valid JSON', + 'Tax rule ID not found' => 'Tax rule ID not found', + 'Tax rule for this product *' => 'Tax rule for this product *', + 'Taxes' => 'Taxes', + 'Taxes rules' => 'Taxes rules', + 'Template' => 'Template', + 'Template Name *' => 'Template Name *', + 'Templates' => 'Templates', + 'Text File' => 'Text File', + 'Text Message' => 'Text Message', + 'The %name module definition has not been initialized.' => 'The %name module definition has not been initialized.', + 'The %name module descriptor has not been initialized.' => 'The %name module descriptor has not been initialized.', + 'The %obj_name id \'%id\' doesn\'t exist' => 'The %obj_name id \'%id\' doesn\'t exist', + 'The HTML TITLE element is the most important element on your web page.' => 'The HTML TITLE element is the most important element on your web page.', + '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.', + 'The archiver identifier "%archiverId" doesn\’t exist' => 'The archiver identifier "%archiverId" doesn\’t exist', + 'The brand name or title' => 'The brand name or title', + 'The cart item count should match the condition' => 'The cart item count should match the condition', + 'The category title' => 'The category title', + 'The class "%class" doesn\'t exist' => 'The class "%class" doesn\'t exist', + 'The class "%class" must extend %baseClass' => 'The class "%class" must extend %baseClass', + 'The container should not be null in this form. Please use the FormFactory to get an instance.' => 'The container should not be null in this form. Please use the FormFactory to get an instance.', + 'The coupon applies if the cart contains at least one product of the selected categories' => 'The coupon applies if the cart contains at least one product of the selected categories', + 'The coupon applies if the cart contains at least one product of the specified product list' => 'The coupon applies if the cart contains at least one product of the specified product list', + 'The coupon applies to some customers only' => 'The coupon applies to some customers only', + 'The coupon applies to the selected billing countries' => 'The coupon applies to the selected billing countries', + 'The coupon applies to the selected delivery countries' => 'Ce code promo s\'applique seulement aux pays de facturation sélectionnés', + 'The coupon code \'%code\' already exist. Please choose another coupon code' => 'The coupon code \'%code\' already exist. Please choose another coupon code', + 'The coupon code \'%code\' already exists. Please choose another coupon code' => 'The coupon code \'%code\' already exists. Please choose another coupon code', + 'The coupon is valid after a given date' => 'Le code promo est valide seulement à partir d\'une certaine date', + 'The date after which sales are de-activated. Please use %fmt format.' => 'The date after which sales are de-activated. Please use %fmt format.', + 'The date from which sales are active. Please use %fmt format.' => 'The date from which sales are active. Please use %fmt format.', + 'The detailed description.' => 'The detailed description.', + 'The email address "%mail" was not found.' => 'The email address "%mail" was not found.', + 'The extension "%extension" is not allowed' => 'The extension "%extension" is not allowed', + 'The file %path has been successfully downloaded' => 'The file %path has been successfully downloaded', + 'The following columns are missing: %columns' => 'The following columns are missing: %columns', + 'The image which replaces an undefined country flag (%file) was not found. Please check unknown-flag-path configuration variable, and check that the image exists.' => 'The image which replaces an undefined country flag (%file) was not found. Please check unknown-flag-path configuration variable, and check that the image exists.', + 'The language "%id" doesn\'t exist' => 'The language "%id" doesn\'t exist', + '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 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 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 %module has been installed successfully.' => 'The module %module has been installed successfully.', + 'The module %name is already installed in the same or greater version.' => 'The module %name is already installed in the same or greater version.', + 'The module %name requires Thelia %version or newer' => 'The module %name requires Thelia %version or newer', + '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 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 parent template "%parent" of template "%name" could not be found' => 'The parent template "%parent" of template "%name" could not be found', + '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 sale element id %id doesn\'t exist' => 'The product sale element id %id doesn\'t exist', + 'The product sale elements id %id doesn\'t exist' => 'The product sale elements id %id doesn\'t exist', + 'The product sale elements id %id doesn\'t exists' => 'The product sale elements id %id doesn\'t exists', + 'The rate from %currencyCode: Price in %currencyCode x rate = Price in this currency' => 'The rate from %currencyCode: Price in %currencyCode x rate = Price in this currency', + 'The resource %res has not been found' => 'The resource %res has not been found', + 'The sale announce label, such as Sales ! or Flash Sales !' => 'The sale announce label, such as Sales ! or Flash Sales !', + 'The sale name or descriptive title' => 'The sale name or descriptive title', + 'The sale name or title' => 'The sale name or title', + 'The serializer identifier "%serializerId" doesn\’t exist' => 'The serializer identifier "%serializerId" doesn\’t exist', + 'The service id that will handle the hook (defined in the config.xml file of the module).' => 'The service id that will handle the hook (defined in the config.xml file of the module).', + 'The store fax number.' => 'The store fax number.', + 'The store phone number.' => 'The store phone number.', + 'The symbol, such as $, £, €...' => 'The symbol, such as $, £, €...', + 'The template "%name" requires Thelia %version or newer' => 'The template "%name" requires Thelia %version or newer', + 'The type %type is not valid' => 'The type %type is not valid', + 'The zip code format' => 'The zip code format', + 'There are no files to associate.' => 'There are no files to associate.', + 'There is no id "%id" in the export categories' => 'There is no id "%id" in the export categories', + 'There is no id "%id" in the exports' => 'There is no id "%id" in the exports', + 'There is no id "%id" in the import categories' => 'There is no id "%id" in the import categories', + 'There is no id "%id" in the imports' => 'There is no id "%id" in the imports', + 'There is no id "%ref" in the imports' => 'There is no id "%ref" in the imports', + 'There is no ref "%ref" in the exports' => 'There is no ref "%ref" in the exports', + 'There\'s a conflict between your file extension "%ext" and the mime type "%mime"' => 'There\'s a conflict between your file extension "%ext" and the mime type "%mime"', + 'This PHP extension should be installed and loaded.' => 'This PHP extension should be installed and loaded.', + 'This administrator login already exists' => 'This administrator login already exists', + 'This brand is online' => 'This brand 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 content is online.' => 'This content is online.', + 'This country has states / provinces' => 'This country has states / provinces', + 'This country is online' => 'This country is online', + 'This coupon adds a free product to the cart if one of the selected products is in the cart.' => 'This coupon adds a free product to the cart if one of the selected products is in the cart.', + 'This coupon does not exists' => 'This coupon does not exists', + 'This coupon subtracts from the order total a percentage of the price of each product which belongs to the selected categories. If the discount is greater than the total order, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.' => 'This coupon subtracts from the order total a percentage of the price of each product which belongs to the selected categories. If the discount is greater than the total order, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.', + 'This coupon subtracts from the order total the specified percentage of each product price which uses the selected attribute values. If the discount is greater than the total order, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.' => 'This coupon subtracts from the order total the specified percentage of each product price which uses the selected attribute values. If the discount is greater than the total order, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.', + 'This coupon subtracts from the order total the specified percentage of each selected product price. If the discount is greater than the total order, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.' => 'This coupon subtracts from the order total the specified percentage of each selected product price. If the discount is greater than the total order, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.', + 'This coupon subtracts the specified amount from the order total for each product which belongs to the selected categories. If the discount is greater than the total order, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.' => 'This coupon subtracts the specified amount from the order total for each product which belongs to the selected categories. If the discount is greater than the total order, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.', + 'This coupon subtracts the specified amount from the order total for each product which uses the selected attribute values. If the discount is greater than the total order, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.' => 'This coupon subtracts the specified amount from the order total for each product which uses the selected attribute values. If the discount is greater than the total order, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.', + 'This coupon subtracts the specified amount from the order total for each selected product. If the discount is greater than the total order, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.' => 'This coupon subtracts the specified amount from the order total for each selected product. If the discount is greater than the total order, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.', + 'This coupon will offert a flat percentage off a shopper\'s entire order (not applied to shipping costs or tax rates). If the discount is greater than the total order corst, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.' => 'This coupon will offert a flat percentage off a shopper\'s entire order (not applied to shipping costs or tax rates). If the discount is greater than the total order cost, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.', + 'This coupon will subtracts a set amount from the total cost of an order. If the discount is greater than the total order corst, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.' => 'This coupon will subtracts a set amount from the total cost of an order. If the discount is greater than the total order cost, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.', + 'This document is online' => 'This document is online', + 'This email already exists.' => 'This email already exists.', + 'This email does not exists' => 'This email does not exists', + 'This folder is online.' => 'This folder is online.', + 'This hook is specific to a module (delivery/payment modules).' => 'This hook is specific to a module (delivery/payment modules).', + '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 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 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 subject of the e-mail, such as \'Your order is confirmed\'.' => 'This is the subject of the e-mail, such as \'Your order is confirmed\'.', + 'This module has no Markdown documentation.' => 'This module has no Markdown documentation.', + 'This product does not have a physical presence' => 'This product does not have a physical presence', + 'This product is on sale' => 'This product is on sale', + 'This product is online' => 'This product is online', + 'This product reference is already assigned to another product.' => 'This product reference is already assigned to another product.', + '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 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 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 zip code should respect the following format : %format.' => 'This zip code should respect the following format : %format.', + 'Timeout' => 'Timeout', + 'Title' => 'Title', + 'Title *' => 'Title *', + 'Title ID not found' => 'Title ID not found', + 'To activate module %name, the following modules should be activated first: %modules' => 'To activate module %name, the following modules should be activated first: %modules', + 'Tools' => 'Tools', + 'Translations' => 'Translations', + 'Tried to download a file, but the URL was not valid: %url' => 'Tried to download a file, but the URL was not valid: %url', + 'Type' => 'Type', + 'URL_ALREADY_EXISTS' => 'This URL already exists', + 'Unable to get module code from the fullnamespace element of the module descriptor: \'%val\'' => 'Unable to get module code from the fullnamespace element of the module descriptor: \'%val\'', + 'Unable to process your request. Please try again (%err).' => 'Unable to process your request. Please try again (%err).', + 'Unconditional usage' => 'Unconditional usage', + 'Unconditionnal usage' => 'Unconditional usage', + 'Undefined loop argument "%name"' => 'Undefined loop argument "%name"', + 'Undefined search mode \'%mode\'' => 'Undefined search mode \'%mode\'', + 'Unknown order ID: %id' => 'Unknown order ID: %id', + 'Unsupported magic method %name. only getArgname() is supported.' => 'Unsupported magic method %name. only getArgname() is supported.', + 'Unsupported type' => 'Unsupported type', + 'Update customer account' => 'Update customer account', + 'Use a N for a number, L for Letter, C for an iso code for the state.' => 'Use a N for a number, L for Letter, C for an iso code for the state.', + 'Use the keyword phrase in your URL.' => 'Use the keyword phrase in your URL.', + 'Used in your store front' => 'Used in your store front', + 'Username' => 'Username', + 'Username or e-mail address *' => 'Username or e-mail address *', + 'Valid only from %date% to the coupon expiration date' => 'Valid only from %date% to the coupon expiration date', + 'Value' => 'Value', + 'Value %val for Discount Amount is invalid. Please enter a positive value.' => 'Value %val for Discount Amount is invalid. Please enter a positive value.', + 'Value %val for Percent Discount is invalid. Please enter a positive value between 1 and 100.' => 'Value %val for Percent Discount is invalid. Please enter a positive value between 1 and 100.', + 'Value *' => 'Value *', + 'Value create form' => 'Value creation form', + 'Variable' => 'Variable', + 'Variables' => 'Variables', + 'Virtual document' => 'Virtual document', + 'Warnings' => 'Warnings', + 'We\'re sorry, this PDF invoice is not available at the moment.' => 'We\'re sorry, this PDF invoice is not available at the moment.', + 'Weight' => 'Weight', + 'When using the %method% method you can automatically render or dump templates or add CSS and JS files (e.g.: render:mytemplate.html;js:assets/js/myjs.js)' => 'When using the %method% method you can automatically render or dump templates or add CSS and JS files (e.g.: render:mytemplate.html;js:assets/js/myjs.js)', + 'Wrong country definition' => 'Wrong country definition', + 'Wrong form method, %s expected.' => 'Wrong form method, %s expected.', + 'Yes, I have a password :' => 'Yes, I have a password :', + '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 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 should select a state for this country.' => 'You should select a state for this country.', + 'You\'re not currently connected to the administration panel. Please log in to access this page' => 'You\'re not currently connected to the administration panel. Please log in to access this page', + 'You\'ve submitted this form too many times. ' => 'You\'ve submitted this form too many times. ', + 'Your Email Address' => 'Your Email Address', + 'Your Message' => 'Your Message', + 'Your configuration seems to be ok. Checked out your mailbox : %email%' => 'Your configuration seems to be ok. Checked out your mailbox : %email%', + 'Your current password does not match.' => 'Your current password does not match.', + 'Your zip must contain 1 root directory which is the root folder directory of your module' => 'Your zip must contain 1 root directory which is the root folder directory of your module', + 'Zip code' => 'Zip code', + 'Zone' => 'Zone', + 'accessories table header' => 'accessories table header', + 'accessories table row' => 'accessories table row', + 'add to all form' => 'add to all form', + 'additional information' => 'additional information', + 'address create form' => 'address creation form', + 'address delete form' => 'address deletion form', + 'address update form' => 'address update form', + 'after addresse area' => 'after address area', + 'after combinations' => 'after combinations', + 'after footer' => 'after footer', + 'after javascript include' => 'after javascript include', + 'after javascript initialisation' => 'after javascript initialization', + 'after product listing' => 'after product listing', + 'after the information area' => 'after the information area', + 'after the main content area' => 'after the main content area', + 'after the opening of the body tag' => 'after the opening of the body tag', + 'after the opening of the head tag' => 'after the opening of the head tag', + 'after the order summary' => 'after the order summary', + 'after top bar' => 'after top bar', + 'after top menu' => 'after top menu', + 'api id %id does not exists' => 'api id %id does not exists', + 'at the bottom' => 'at the bottom', + 'at the bottom of column 1' => 'at the bottom of column 1', + 'at the bottom of information area' => 'at the bottom of information area', + 'at the bottom of the catalog' => 'at the bottom of the catalog', + 'at the bottom of the detail area' => 'at the bottom of the detail area', + 'at the bottom of the footer' => 'at the bottom of the footer', + 'at the bottom of the form' => 'at the bottom of the form', + 'at the bottom of the header' => 'at the bottom of the header', + 'at the bottom of the main area' => 'at the bottom of the main area', + 'at the bottom of the shipping area' => 'at the bottom of the shipping area', + 'at the bottom of the sidebar' => 'at the bottom of the sidebar', + 'at the bottom of the system area' => 'at the bottom of the system area', + 'at the bottom of the top bar' => 'at the bottom of the top bar', + 'at the top' => 'at the top', + 'at the top of the catalog area' => 'at the top of the catalog area', + 'at the top of the column' => 'at the top of the column', + 'at the top of the configuration' => 'at the top of the configuration', + 'at the top of the detail' => 'at the top of the detail', + 'at the top of the footer' => 'at the top of the footer', + 'at the top of the form' => 'at the top of the form', + 'at the top of the header' => 'at the top of the header', + 'at the top of the main area' => 'at the top of the main area', + 'at the top of the shipping area' => 'at the top of the shipping area', + 'at the top of the sidebar' => 'at the top of the sidebar', + 'at the top of the system area' => 'at the top of the system area', + 'at the top of the top bar' => 'at the top of the top bar', + 'attributes table header' => 'attributes table header', + 'attributes table row' => 'attributes table row', + 'before combinations' => 'before combinations', + 'before footer' => 'before footer', + 'before the end body tag' => 'before the end body tag', + 'before the end of the head tag' => 'before the end of the head tag', + 'before the main content area' => 'before the main content area', + 'before top menu' => 'before top menu', + 'before topbar' => 'before topbar', + 'block' => 'block', + 'bottom' => 'bottom', + 'bottom of the footer' => 'bottom of the footer', + 'cURL errno %errno, http code %http_code on link "%path": %error' => 'cURL errno %errno, http code %http_code on link "%path": %error', + 'caption' => 'caption', + 'categories table header' => 'categories table header', + 'categories table row' => 'categories table row', + 'combination delete form' => 'combination deletion form', + 'combinations list caption' => 'combinations list caption', + 'configuration' => 'configuration', + 'configuration JavaScript' => 'configuration JavaScript', + 'configuration bottom' => 'configuration bottom', + 'content' => 'content', + 'content area' => 'content area', + 'content delete form' => 'content deletion form', + 'content edit JavaScript' => 'content edit JavaScript', + 'contents table header' => 'contents table header', + 'contents table row' => 'contents table row', + 'context' => 'context', + 'country delete form' => 'country deletion form', + 'create JavaScript' => 'create JavaScript', + 'create form' => 'creation form', + 'customer account' => 'customer account', + 'date format' => 'date format', + 'date/time format' => 'date/time format', + 'decimal separator' => 'decimal separator', + 'delete form' => 'delete form', + 'delivery address' => 'delivery address', + 'delivery module %s is not a Thelia\Module\DeliveryModuleInterface' => 'delivery module %s is not a Thelia\Module\DeliveryModuleInterface', + 'details pricing form' => 'details pricing form', + 'details promotion form' => 'details promotion form', + 'email' => 'email', + 'email confirmation is not the same as email field' => 'The two email addresses are not identical', + 'email system JavaScript' => 'email system JavaScript', + 'extra area' => 'extra area', + 'extra payment zone' => 'extra payment zone', + 'features table row' => 'features table row', + 'features-table-header' => 'features-table-header', + 'folders table header' => 'folders table header', + 'folders table row' => 'folders table row', + 'footer body' => 'footer body', + 'header' => 'header', + 'hook delete form' => 'hook deletion form', + 'hook edit JavaScript' => 'hook edit JavaScript', + 'hour(s)' => 'hour(s)', + 'id delete form' => 'id deletion form', + 'if successful response' => 'if successful response', + 'imprint' => 'imprint', + 'in footer' => 'in footer', + 'in the header' => 'in the header', + 'in the menu catalog' => 'in the menu catalog', + 'in the menu configuration' => 'in the menu configuration', + 'in the menu customers' => 'in the menu customers', + 'in the menu folders' => 'in the menu folders', + 'in the menu modules' => 'in the menu modules', + 'in the menu orders' => 'in the menu orders', + 'in the menu tools' => 'in the menu tools', + 'in top menu items' => 'in top menu items', + 'inside top bar' => 'inside top bar', + 'javascript' => 'javascript', + 'javascript initialization' => 'javascript initialization', + 'label' => 'label', + 'language locale' => 'language locale', + 'language selection page' => 'language selection page', + 'list JavaScript' => 'list JavaScript', + 'list caption' => 'list caption', + 'list header' => 'list header', + 'list row' => 'list row', + 'logs JavaScript' => 'logs JavaScript', + 'mailing system modification' => 'mailing system modification', + 'main area' => 'main area', + 'middle' => 'middle', + 'minute(s)' => 'minute(s)', + 'password confirmation is not the same as password field' => 'password confirmation is not the same as password field', + 'password must be composed of at least 4 characters' => 'password must be composed of at least 4 characters', + 'payment module %s is not a Thelia\Module\PaymentModuleInterface' => 'payment module %s is not a Thelia\Module\PaymentModuleInterface', + 'pdf' => 'pdf', + 'permanent discount (in percent)' => 'permanent discount (in percent)', + 'photo gallery' => 'photo gallery', + 'plain, login, cram-md5 or empty' => 'plain, login, cram-md5 or empty', + 'primary navigation' => 'primary navigation', + 'product list' => 'product list', + 'quantity value is not valid' => 'quantity value is not valid', + 'received value `%value` does not match `%type` type' => 'received value `%value` does not match `%type` type', + 'remove to all form' => 'remove to all form', + 'row' => 'row', + 'rule create form' => 'rule creation form', + 'rule delete form' => 'rule deletion form', + 'rule edit JavaScript' => 'rule edit JavaScript', + 'secondary navigation' => 'secondary navigation', + 'ssl, tls or empty' => 'ssl, tls or empty', + 'stock edit form' => 'stock edit form', + 'table header' => 'table header', + 'table row' => 'table row', + 'tax rule' => 'tax rule', + 'the body of the sidebar' => 'the body of the sidebar', + 'this product id does not exists : %d' => 'this product id does not exists : %d', + 'thousands separator' => 'thousands separator', + 'time format' => 'time format', + 'type' => 'type', + 'update JavaScript' => 'update JavaScript', + 'update form' => 'update form', + 'value table header' => 'value table header', + 'value table row' => 'value table row', +); diff --git a/core/lib/Thelia/Config/I18n/es_ES.php b/core/lib/Thelia/Config/I18n/es_ES.php new file mode 100644 index 00000000..b8728f35 --- /dev/null +++ b/core/lib/Thelia/Config/I18n/es_ES.php @@ -0,0 +1,823 @@ + ' formulario de creación de contenido', + ' note: only non-visible documents can be associated.' => ' nota: sólo los documentos no visibles pueden ser asociados.', + '"%param" parameter cannot be empty in loop type: %type, name: %name' => 'El parámetro "%param" no puede estar vacío en el bucle tipo: %type, nombre: %name', + '"%param" parameter is missing in loop type: %type, name: %name' => 'Falta el parámetro "%param" en el bucle tipo: %type, nombre: %name', + '%module (version: %version)' => '%module (versión: %version)', + '%n for number, %c for the currency code, %s for the currency symbol' => '%n para el número, %c para el código de moneda, %s para el símbolo de moneda', + '%obj SEO modification' => 'Modificación SEO de %obj', + '%obj creation' => 'Creación de %obj', + '%obj modification' => 'Modificación de %obj', + '%obj%s deleted successfully' => '%obj%s eliminado con éxito', + '%s has dependency to module %s. You have to deactivate this module before.' => '%s tiene dependencia al módulo %s. Tienes que desactivar este módulo antes.', + '%s have dependencies to module %s. You have to deactivate these modules before.' => '%s tienen dependencias al módulo %s. Tienes que desactivar estos módulos antes.', + '%type% position updated' => 'Posición %type% actualizada', + '%type% visibility updated' => 'Visibilidad %type% actualizada', + 'A comma separated list of email addresses' => 'Lista de direcciones de correo electrónico separados por una coma', + 'A currency with code "%name" already exists.' => 'Una moneda con el código "%name" ya existe.', + 'A descriptive title' => 'Un título descriptivo', + 'A message with name "%name" already exists.' => 'Un mensaje con el nombre "%name" ya existe.', + 'A name such as Europe or Overseas' => 'Un nombre como Europa o en el extranjero', + 'A product with reference %ref already exists. Please choose another reference.' => 'Un producto con %ref referencia ya existe. Por favor elige otra referencia.', + 'A short description, used when a summary or an introduction is required' => 'Una descripción corta, utilizada cuando se requiere un resumen o una introducción', + 'A short text, used when an additional or supplemental information is required.' => 'Un texto corto, usado cuando se requiere información adicional o complementaria.', + 'A user already exists with this email address. Please login or if you\'ve forgotten your password, go to Reset Your Password.' => 'Ya existe un usuario con esta dirección de correo electrónico. Por favor inicie sesión o si ha olvidado su contraseña, restablézcala.', + 'A value for attribute "%name" is already present in the combination' => 'Un valor para el atributo "%name" ya está presente en la combinación', + 'A variable with name "%name" already exists.' => 'Una variable con el nombre "%name" ya existe.', + 'Activate logs only for these IP Addresses' => 'Activar logs únicamente para estas direcciones IP', + 'Activate logs only for these files' => 'Activar logs únicamente para estos archivos', + 'Activate this sale' => 'Activar esta venta', + 'Active' => 'Activado', + 'Add to all product templates' => 'Añadir a todas las plantillas de producto', + 'Additional address' => 'Dirección adicional', + 'Additional address information' => 'Información adicional de dirección', + 'Address ID not found' => 'Dirección ID no encontrada', + 'Address Line 2' => 'Dirección - línea 2', + 'Address Line 3' => 'Dirección - línea 3', + 'Address creation' => 'Creación de la dirección', + 'Address label' => 'Nombre de la dirección', + 'Address update' => 'Dirección actualizada', + 'Address.' => 'Dirección.', + 'Addresses for this country need a zip code' => 'Direcciones en este país necesitan un código postal', + 'Administrator' => 'Administrador', + 'Administrator ID not found' => 'ID de administrador no encontrado', + 'Administrator email address' => 'Dirección de correo electrónico del administrador', + 'Administrators' => 'Administradores', + 'Advertise this product as new' => 'Anunciar este producto como novedad', + 'Alerts' => 'Alertas', + 'All Products' => 'Todos los productos', + 'All countries' => 'Todos los países', + 'All shipping methods' => 'Todos los métodos de envío', + 'Amount' => 'Importe', + 'An administrator with this email address already exists' => 'Un administrador con la dirección de correo electrónico ya existe', + 'An invalid token was provided, your password cannot be changed' => 'Se proporcionó un código no válido, no se puede cambiar su contraseña', + 'Apply exchange rates on price in %sym' => 'Aplicar los tipos de cambio sobre el precio en %sym', + 'Archive Format' => 'Formato de archivo', + 'Associate documents' => 'Documentos asociados', + 'Associate images' => 'Imágenes asociadas', + 'At least one of cart products categories is %op% %categories_list%' => 'Al menos una de las categorías de los productos del carro es %op% %categories_list%', + 'Attribut' => 'Atributo', + 'Attribute ID:Attribute AV ID' => 'ID de atributo:AV ID de atributo', + 'Attribute value' => 'Valor del atributo', + 'Attributes' => 'Atributos', + 'Attributes value' => 'Valor de los atributos', + 'Auth mode' => 'Auth mode', + 'Automatic rendered templates' => 'Plantillas interpretadas automáticamente', + 'Available quantity' => 'Cantidad disponible', + 'Available quantity *' => 'Cantidad disponible *', + 'Available shipping zones' => 'Zonas de envío disponibles', + 'Back Office' => 'Panel de administración', + 'Bad tax list JSON' => 'Lista JSON de impuestos errónea', + 'Billing country' => 'País de facturación', + 'Billing country is' => 'El país de facturación es', + 'Brand' => 'Marca', + 'Brand / Supplier' => 'Marca / fabricante', + 'Brand name' => 'Nombre de la marca', + 'Brands' => 'Marcas', + 'Business ID' => 'NIF', + 'By Module' => 'Por módulo', + 'CSS' => 'CSS', + 'CSS stylesheet' => 'Hoja de estilos CSS', + 'Cannot disable the default language' => 'No es posible desactivar el idioma por defecto', + 'Cannot find a default country. Please define one.' => 'No se encuentra el país por defecto. Por favor defina uno.', + 'Cannot find the shop country. Please select a shop country.' => 'No se encuentra el país de compra. Por favor seleccione uno.', + 'Cannot hide the default language' => 'No puede ocultar el idioma por defecto', + 'Cannot instantiate module "%name%": the namespace is null. Maybe the model is not loaded ?' => 'No se puede crear una instancia de módulo "%name%": el espacio de nombres es nulo. ¿Tal vez el modelo no está cargado?', + 'Cart' => 'Carrito', + 'Cart contains at least a product %op% %products_list%' => 'El carro contiene al menos un producto %op% %products_list%', + 'Cart contains categories condition' => 'El carrito contiene condición de categorías', + 'Cart contains specific products' => 'Carro contiene productos específicos', + 'Cart item count' => 'Número de items en el carro', + 'Cart item count is' => 'El número de elementos en el carro es', + 'Cart item include quantity count' => 'Artículo del carro incluye cuenta de la cantidad', + 'Cart item include quantity count is' => 'Artículo del carro incluye cantidad es', + 'Cart total amount' => 'Importe total del carro', + 'Cart total amount is' => 'El importe total del carro es', + 'Catalog' => 'Catálogo', + 'Catalog configuration' => 'Configuración del catálogo', + 'Categories' => 'Categorías', + 'Category' => 'Categoria', + 'Category page' => 'Página de la categoría', + 'Category title' => 'Título de la categoría', + 'Cellphone' => 'Teléfono móvil', + 'Change password' => 'Cambiar contraseña', + 'Check country iso codes here.' => 'Revisa los códigos ISO de cada país en Wikipedia.', + 'Check the total Cart amount in the given currency' => 'Compruebe la cantidad total de la compra en la moneda determinada', + 'City' => 'Ciudad', + 'Code' => 'Código', + 'Combination builder' => 'Constructor de combinación', + 'Compagny' => 'Empresa', + 'Company' => 'Empresa', + 'Company Name' => 'Nombre de la empresa', + 'Conclusion' => 'Conclusión', + 'Configuration' => 'Configuración', + 'Confirm Email Address' => 'Confirme su correo electrónico', + 'Confirm Email address' => 'Confirme su correo electrónico', + 'Constant amount' => 'Importe constante', + 'Constant amount found in one of the product\'s feature' => 'Importe constante encontrado en una de las características del producto', + 'Contact and sender email address' => 'Dirección de correo electrónico de contacto y el remitente', + 'Contact page' => 'Página de contacto', + 'Content' => 'Contenido', + 'Content page' => 'Página de contenido', + 'Content title *' => 'Título del contenido *', + 'Contents' => 'Contenidos', + 'Core hook of Thelia.' => 'Raiz central de Thelia.', + 'Countries' => 'Países', + 'Country' => 'País', + 'Country ID %id not found' => 'ID de país %id no encontrado', + 'Country ID not found' => 'ID País no encontrado', + 'Country list is not valid JSON' => 'Lista de países no es JSON válido', + 'Country title' => 'Título del país', + 'Coupon' => 'Cupón', + 'Coupon %code is expired.' => 'El cupón %code expiró.', + 'Coupon %code is not release.' => 'Cupón %code no está liberado.', + 'Coupon code %code is disabled.' => 'El código de cupón %code está deshabilitado.', + 'Critical' => 'Critico', + 'Curency selection page' => 'Página de selección de moneda', + 'Currencies' => 'Monedas', + 'Currency' => 'Divisa', + 'Currency name' => 'Nombre de la moneda', + 'Current Password' => 'Contraseña actual', + 'Customer' => 'Cliente', + 'Customer is %op% %customer_list%' => 'El cliente es %op% %customer_list%', + 'Customers' => 'Clientes', + 'Dashboard' => 'Panel de Control', + 'Date \'%date\' is invalid, please enter a valid date using %fmt format' => 'La fecha \'%date\' no es válida, por favor ingresa una fecha válida usando el formato %fmt', + 'Debug' => 'Debug', + 'Decimal places' => 'Cantidad de decimales', + 'Default folder *' => 'Carpeta por defecto *', + 'Default product category *' => 'Categoría del producto por defecto *', + 'Default product sale element' => 'Elemento de venta de producto predeterminado', + 'Default product template' => 'Plantilla de producto por defecto', + 'Deleting %obj% for %id% with parent id %parentId%' => 'Eliminando %obj% para %id% con id de padre %parentId%', + 'Delivery' => 'Envío', + 'Delivery choice' => 'Opción de entrega', + 'Delivery country' => 'País de entrega', + 'Delivery country is' => 'El país de entrega es', + 'Delivery module ID not found' => 'ID de módulo de entrega no encontrado', + 'Delivery zone' => 'Zona de entrega', + 'Detailed description' => 'Descripción detallada', + 'Disabled' => 'Desactivado', + 'Discount type' => 'Tipo de descuento', + 'Display initial product prices on front-office' => 'Mostrar precios de productos iniciales sobre front-office', + 'Do compress' => 'Comprimir', + 'Document' => 'Documento', + 'Don\'t repeat keywords over and over in a row. Rather, put in keyword phrases.' => 'No repetir palabras una y otra vez en una fila. Mejor poner frases de palabras clave.', + 'EAN Code' => 'Código EAN', + 'Edit' => 'Editar', + 'Edit JavaScript' => 'Editar el JavaScript', + 'Email Address' => 'Dirección de correo electrónico', + 'Email address' => 'Dirección de correo electrónico', + 'Email addresses of notification recipients' => 'Direcciones de correo electrónico de destinatarios de notificación', + 'Email test from : %store%' => 'Correo electrónico de prueba: %store%', + 'Emergency' => 'Emergencia', + 'Enable remote SMTP use' => 'Activar el uso de SMTP remoto', + 'Encryption' => 'Cifrado', + 'End date of sales' => 'Fecha de fin de ventas', + 'Enter here the brand name in the default language (%title%)' => 'Introduzca aquí el nombre de la marca en el idioma por defecto (%title%)', + 'Enter here the category title in the default language (%title%)' => 'Escriba aquí el título de la categoría en el idioma por defecto (%title%)', + 'Enter here the mail template purpose in the default language (%title%)' => 'Ingrese aquí la finalidad de la plantilla de correo en el idioma por defecto (%title%)', + 'Enter here the sale name in the default language (%title%)' => 'Introduce el nombre de la venta en el lenguaje por defecto (%title%)', + 'Enter the new password' => 'Introduzca la nueva contraseña', + 'Enter the new password again' => 'Introduzca la nueva contraseña otra vez', + 'Equal to' => 'Igual a', + 'Error during %action process : %error. Exception was %exc' => 'Error mientras %action proceso: %error. Excepción %esc', + 'Error occured while processing order ref. %ref, ID %id: %err' => 'Ocurrió un error de procesamiento de pedido ref. %ref, ID %id: %err', + 'Error occured.' => 'Se produjo un error.', + 'Error(s) in import :
%errors' => 'Errores en la importación: < br / >%errors', + 'Errors' => 'Errores', + 'Export' => 'Exportar', + 'Fail to delete %obj% for %id% with parent id %parentId% (Exception : %e%)' => 'Fallo borrando %obj% para %id% con id de padre %parentId% (Excepción: %e%)', + 'Fail to update %type% position: %err%' => 'Fallo de actualización %type% posición: %err%', + 'Fail to update %type% visibility: %err%' => 'Fallo de actualización %type% visibilidad: %err%', + 'Failed to create instance of module "%name%" when trying to delete module. Module directory has probably been deleted' => 'No se pudo crear instancia del módulo "%name%" al intentar borrar el módulo. El directorio del módulo probablemente se ha eliminado', + 'Failed to create new hook %s' => 'Fallo al crear nuevo Hook %s', + 'Failed to deactivate hook with id %s' => 'No se pudo desactivar el Hook con el id %s', + 'Failed to delete selected countries' => 'Error al eliminar determinados países', + 'Failed to find a payment Module with ID=%mid for order ID=%oid' => 'Fallo buscando módulo de pago con ID=%mid para pedido ID=%oid', + 'Failed to load descriptor (module.xml) for module ID "%id".' => 'Error al cargar el descriptor (module.xml) para la identificación del módulo "%id".', + 'Failed to load message with code \'%code%\', propably because it does\'nt exists.' => 'Fallo cargando mensaje con el código \'%code%\', probablemente porque no existe.', + 'Failed to open a writing stream on the file: %file' => 'Error intentando escribir archivo: %file', + 'Failed to open translation file %file. Please be sure that this file is writable by your Web server' => 'Error al abrir archivo de traducción %file. Por favor, asegúrate de que este fichero tiene permisos de escritura', + 'Failed to send message %code. Failed recipients: %failed_addresses' => 'Fallo enviando mensaje %code. Fallo en destinatarios: %failed_addresses', + 'Failed to update language definition: %ex' => 'No se pudo actualizar la definición de lengua: %ex', + 'Fax' => 'Fax', + 'Feature' => 'Característica', + 'Feature value does not match FLOAT format' => 'Valor de característica no coincide con el formato FLOAT', + 'Features' => 'Características', + 'Features value' => 'Valor de características', + 'File format' => 'Formato de archivo', + 'File is too large, please retry with a file having a size less than %size%.' => 'El archivo es demasiado grande, por favor vuelva a intentarlo con un archivo de tamaño inferior a %size%.', + 'File to upload' => 'Archivo a subir', + 'Files with the following extension are not allowed: %extension, please do an archive of the file if you want to upload it' => 'No se permiten archivos con la siguiente extensión: %extension, por favor, haz un archivo del fichero si quieres subirlo', + 'First Name' => 'Nombre', + 'Firstname' => 'Nombre', + 'Fixed Amount Discount' => 'Descuento de cantidad fija', + 'Fixed amount discount for selected attribute values' => 'Descuento del importe fijo para los valores del atributo seleccionado', + 'Fixed amount discount for selected categories' => 'Importe de descuento fijo para las categorías seleccionadas', + 'Fixed amount discount for selected products' => 'Cantidad fija de descuento en productos seleccionados', + 'Folder' => 'Carpeta', + 'Folder page' => 'Página de carpeta', + 'Folder title *' => 'Título de la carpeta *', + 'For one ore more customers' => 'Para un cliente o más', + 'Format' => 'Formato', + 'Free product when buying one or more selected products' => 'Productos gratis en compras de uno o más de los productos seleccionados', + 'Front Office' => 'Front Office', + 'Full Name' => 'Nombre completo', + 'Greater than' => 'Mayor que', + 'Greater than or equals' => 'Mayor o igual a', + 'HTML Message' => 'Mensaje HTML', + 'HTML layout' => 'Diseño HTML', + 'Home' => 'Página de inicio', + 'Home page' => 'Página de inicio', + 'Hook' => 'Hook', + 'Hook block' => 'Bloqueo de Hook', + 'Hook code' => 'Código de Hook', + 'Hook create form' => 'Formulario de creación de Hook', + 'Hook title' => 'Título de Hook', + 'Hooks' => 'Hooks', + 'Host' => 'Hostname', + 'I would like to receive the newsletter or the latest news.' => 'Me gustaría recibir el boletín de noticias o las últimas noticias.', + 'ISO 4217 code' => 'Código ISO 4217', + 'ISO 639-1 Code' => 'Código ISO 639-1', + 'ISO Alpha-2 code' => 'Código ISO Alpha-2', + 'ISO Alpha-3 code' => 'Código ISO Alpha-3', + 'ISO Code' => 'Código ISO', + 'If a translation is missing or incomplete :' => 'Si falta una traducción o esta incompleta:', + 'If cart item (include quantity) count is %operator% %quantity%' => 'Si elemento de carro (incluir cantidad) es %operator% %quantity%', + 'If cart item count is %operator% %quantity%' => 'Si el número de artículos en el carrito es %operator% %quantity%', + 'If cart total amount is %operator% %amount% %currency%' => 'Si la cantidad total del carrito es %operator% %amount% %currency%', + 'If checked, this hook will be used by a hook block. If not, by hook function.' => 'Si es seleccionao, este Hook se utilizará por un bloque de Hook. Si no por una función de Hook.', + 'If you use automatic insert templates, you should use the method %method%' => 'Si utiliza plantillas de inserción automática, usted debe utilizar el método %method%', + 'Image' => 'Imagen', + 'Import successfully done, %count row(s) have been changed' => 'Importación realizada con éxito, %count fila(s) se han cambiado', + 'Impossible to check value `%value` for `%type` type' => 'Imposible verificar el valor \' %\' para el tipo %', + 'Impossible to delete a customer who already have orders' => 'Imposible eliminar a un cliente que ya tiene pedidos', + 'In' => 'En', + 'Include documents' => 'Incluir documentos', + 'Include images' => 'Incluir imágenes', + 'Information' => 'Información', + 'Invalid product_sale_elements' => 'product_sale_elements no válidos', + 'Invalid username or email.' => 'Nombre de usuario o correo electrónico no válido.', + 'Invalid value "%value" for "%param" parameter in loop type: %type, name: %name' => 'Valor inválido "%value" para parámetro "%param" de tipo loop: %type, nombre: %name', + 'Invalid value for walkMode parameter: %value' => 'Valor inválido para walkMode parámetro: valor %', + 'Invoice' => 'Factura', + 'Invoice choice' => 'Opción de factura', + 'Is it the default product sale element ?' => '¿Es el elemento de venta de producto predeterminado?', + 'Iso code for states. It depends of the country.' => 'Código Iso para los Estados. Depende del país.', + 'It is not allowed to delete the default currency' => 'No está permitido eliminar la moneda por defecto', + 'It is not allowed to delete the default language' => 'No está permitido eliminar el idioma por defecto', + 'JavaScript' => 'JavaScript', + 'Keep the most important part of your description in the first 150-160 characters.' => 'Mantén la parte más importante de la descripción en los primeros 150-160 caracteres.', + 'Language' => 'Idioma', + 'Language name' => 'Nombre del idioma', + 'Languages' => 'Idiomas', + 'Last Name' => 'Apellidos', + 'Lastname' => 'Apellido', + 'Layout' => 'Diseño', + 'Less than' => 'Menos que', + 'Less than or equals' => 'Menor o igual a', + 'Log format *' => 'Formato de log *', + 'Log level *' => 'Nivel de log *', + 'Login failed. Please check your username and password.' => 'Error de inicio de sesión. Por favor comprueba tu nombre de usuario y contraseña.', + 'Login name' => 'Nombre usuario', + 'Login page' => 'Página de Login', + 'Logs' => 'Logs', + 'Loop cannot implements multiple Search Interfaces : `PropelSearchLoopInterface`, `ArraySearchLoopInterface`' => 'El loop no implementa varias Interfaces de búsqueda: \'PropelSearchLoopInterface\', \'ArraySearchLoopInterface\'', + 'Loop must implements \'PropelSearchLoopInterface\' to be timestampable' => 'El Loop debe implementar \'PropelSearchLoopInterface\' para usar timestamp', + 'Loop must implements \'PropelSearchLoopInterface\' to be versionable' => 'El loop debe implementar \'PropelSearchLoopInterface\' para ser versionable', + 'Loop must implements one of the following interfaces : `PropelSearchLoopInterface`, `ArraySearchLoopInterface`' => 'El loop debe implementar una de las siguientes interfaces: `PropelSearchLoopInterface`, `ArraySearchLoopInterface`', + 'Lost password' => 'Contraseña perdida', + 'Mail template name' => 'Nombre de plantilla de correo', + 'Mail template purpose' => 'Título de plantilla de correo', + 'Mailing system' => 'Sistema de correo electrónico', + 'Main address' => 'Dirección principal', + 'Main area' => 'Área principal', + 'Make sure it uses keywords found within the page itself.' => 'Asegúrate de utilizar palabras clave que se encuentran dentro de la propia página.', + 'Make sure that your title is clear, and contains many of the keywords within the page itself.' => 'Asegúrate de que el título es claro y contiene muchas de las palabras clave dentro de la propia página.', + 'Make this address as my primary address' => 'Elegir esta dirección como dirección principal', + 'Maximum usage count reached for coupon %code' => 'Recuento de usos máximo alcanzado para cupón %code', + 'Message' => 'Mensaje', + 'Message name' => 'Nombre del mensaje', + 'Message subject' => 'Tema del mensaje', + 'Messages' => 'Mensajes', + 'Meta Description' => 'Meta Description', + 'Meta Keywords' => 'Meta Keywords', + 'Method Name' => 'Nombre del método', + 'Missing or invalid data: %s' => 'Faltan datos o no son válidos: %s', + 'Module' => 'Módulo', + 'Module "%name%" directory was not found' => 'No se encuentra el directorio del módulo "%name%"', + 'Module %name directory doesn\'t exists.' => 'El directorio del módulo %name no existe.', + 'Module %name should have a config.xml in the Config directory.' => 'El módulo %name debe tener un archivo config.xml en el directorio Config.', + 'Module %name should have a module.xml in the Config directory.' => 'El módulo %name debe tener un archivo config.xml en el directorio Config.', + 'Module ID "%id" was not found.' => 'No se encontró el módulo ID "%id".', + 'Module ID not found' => 'ID del módulo no encontrado', + 'Module hook' => 'Hook de módulo', + 'Modules' => 'Módulos', + 'More information about ISO 4217' => 'Más información sobre ISO 4217', + 'Name' => 'Nombre', + 'Name *' => 'Nombre *', + 'Name of the HTML layout file' => 'Nombre del archivo de diseño HTML', + 'Name of the HTML template file' => 'Nombre del archivo de plantilla HTML', + 'Name of the text layout file' => 'Nombre del archivo de diseño textual', + 'Name of the text template file' => 'Nombre del archivo de plantilla textual', + 'Native' => 'Nativo', + 'New Password' => 'Nueva contraseña', + 'Newsletter page' => 'Página de Newsletter', + 'No %obj was created.' => 'Ningún %obj ha sido creado.', + 'No %obj was updated.' => 'Ningún %obj ha sido actualizado.', + 'No module found for code \'%item\'' => 'Ningún módulo para código \'%item\'', + 'No, I am a new customer.' => 'No, soy un nuevo cliente.', + 'None' => 'Ninguno', + 'Not equal to' => 'No igual a', + 'Not in' => 'No en', + 'Notices' => 'Avisos', + 'Numerical ISO Code' => 'Código ISO numérico', + 'Only files having the following mime type are allowed: %types%' => 'Se permiten sólo archivos con el siguiente tipo MIME: %types%', + 'Only hookable modules are displayed in this menu.' => 'Sólo módulos adheribles a Hooks se muestran en este menú.', + 'Only if order billing country is %op% %countries_list%' => 'Solo si el país de facturación es %op% %countries_list% ', + 'Only if order shipping country is %op% %countries_list%' => 'Solo si el país de envío del pedido es %op% %countries_list% ', + 'Order' => 'Pedido', + 'Order address ID not found' => 'No se encontró la ID de la dirección de pedido', + 'Order failed' => 'Pedido fallido', + 'Order ref. %ref is now unpaid.' => 'Pedido Ref. %ref está sin pagar.', + 'Order ref. %ref, ID %id has been successfully paid.' => 'Pedido Ref. %ref, ID %id se ha pagado con éxito.', + 'Orders' => 'Pedidos', + 'Overall' => 'General', + 'Page 404' => 'Página 404', + 'Page Title' => 'Título de la página', + 'Parent category' => 'Categoría padre', + 'Parent folder *' => 'Carpeta superior *', + 'Password' => 'Contraseña', + 'Password *' => 'Contraseña *', + 'Password confirmation' => 'Confirmación de la contraseña', + 'Payment failed' => 'Pago fallido', + 'Payment gateway' => 'Pasarela de pago', + 'Per customer' => 'Por cliente', + 'Percent' => 'Porcentaje', + 'Percentage' => 'Porcentaje', + 'Percentage discount for selected attribute values' => 'Porcentaje de descuento para los valores de atributo seleccionado', + 'Percentage discount for selected categories' => 'Porcentaje de descuento para las categorías seleccionadas', + 'Percentage discount for selected products' => 'Porcentaje de descuento para productos seleccionados', + 'Percentage of the product price' => 'Porcentaje del precio del producto', + 'Phone' => 'Teléfono', + 'Placed order' => 'Pedido realizado', + 'Please accept the Terms and conditions in order to register.' => 'Por favor acepta los términos y condiciones para poder inscribirte.', + 'Please check your input: %error' => 'Por favor comprueba tu texto: %error', + 'Please enter a valid email address' => 'Por favor ingresa una dirección de correo electrónico válida', + 'Please enter your email address' => 'Por favor, introduce tu e-Mail', + 'Please enter your password' => 'Por favor introduce tu contraseña', + 'Please select a category' => 'Por favor selecciona una categoría', + 'Please select an attribute' => 'Por favor, selecciona un atributo', + 'Please select at least one attribute value' => 'Por favor selecciona al menos un valor de atributo', + 'Please select at least one category' => 'Por favor, selecciona al menos una categoría', + 'Please select at least one product' => 'Por favor selecciona al menos un producto', + 'Please select the category of the offred product' => 'Por favor selecciona la categoría de los productos ofertados', + 'Please select the offered product' => 'Por favor selecciona el producto ofrecido', + 'Please upload a valid Zip file' => 'Por favor, sube un archivo Zip válido', + 'Port' => 'Puerto', + 'Postage' => 'Gastos de envío', + 'Preferred locale' => 'Local preferida', + 'Prevent mailing template modification or deletion, except for super-admin' => 'Prevenir la modification o la supresión de la plantilla de e-Mail, excepto por el Super-Administrador', + 'Prevent variable modification or deletion, except for super-admin' => 'Prevenir la modification o la supresión de la variable, excepto por el Super-Administrador', + 'Price currency *' => 'Precio de divisa *', + 'Processing cancelation of payment for order ref. %ref' => 'Proceso de cancelación de pago de pedido ref. %ref', + 'Processing confirmation of order ref. %ref, ID %id' => 'Procesando confirmación de pedido ref. %ref, ID %id', + 'Prodcut ID *' => 'ID del producto *', + 'Product' => 'Producto', + 'Product ID' => 'ID del producto', + 'Product ID *' => 'ID del producto *', + 'Product attributes' => 'Atributos del producto', + 'Product base price excluding taxes *' => 'Precio base del producto sin impuestos *', + 'Product base price with taxes' => 'Precio base del producto con impuestos', + 'Product categories' => 'Categorías de productos', + 'Product clone' => 'Clonar producto', + 'Product loop' => 'Loop de producto', + 'Product page' => 'Página de producto', + 'Product price excluding taxes' => 'Precio del producto sin impuestos', + 'Product price excluding taxes *' => 'Precio del producto sin impuestos *', + 'Product price including taxes' => 'Precio del producto con impuestos', + 'Product price offset for each currency' => 'Cambio de precio de producto para cada moneda', + 'Product reference (must be unique)' => 'Referencia del producto (debe ser única)', + 'Product reference *' => 'Referencia del producto *', + 'Product sale element ID *' => 'ID del elemento del producto de venta *', + 'Product template' => 'Plantilla de producto', + 'Product title' => 'Título del producto', + 'ProductSaleElement modification' => 'ProductSaleElement modificación', + 'Products' => 'Productos', + 'Profile' => 'Perfil', + 'Profile Code' => 'Código de perfil', + 'Profile ID not found' => 'Identificador de perfil no encontrado', + 'Profile `code` already exists' => 'Perfil \'código\' ya existe', + 'Profiles' => 'Perfiles', + 'Purpose' => 'Propósito', + 'Purpose *' => 'Propósito *', + 'Quantity' => 'Cantidad', + 'Range date End' => 'Rango fecha final', + 'Range date Start' => 'Rango fecha inicio', + 'Rate' => 'Tipo de cambio', + 'Rate from %currencyCode' => 'Tasa de %currencyCode', + 'Redirecting ...' => 'Redirigiendo...', + 'Redirecting to %url' => 'Redirigiendo hacia %url', + 'Reference' => 'Referencia', + 'Reference *' => 'Referencia *', + 'Register' => 'Registrarse', + 'Remember me ?' => 'Recordarme ?', + 'Remove X percent to total cart' => 'Quitar X por ciento al total del carrito', + 'Replace by the default language' => 'Remplazar por el idioma predeterminado', + 'Replace current document by this file' => 'Sustituir el documento actual por este archivo', + 'Replace current image by this file' => 'Reemplazar imagen actual por este archivo', + 'Reseller' => 'Distribuidor', + 'Rewriten URL' => 'URL reescrita', + 'Rotated Text File' => 'Archivo de texto rotado', + 'Sale announce label' => 'Etiqueta de anuncio de venta', + 'Sale price excluding taxes' => 'Precio de venta sin impuestos', + 'Sale price including taxes' => 'Precio de venta con impuestos', + 'Sale title' => 'Título de venta', + 'Saving %obj% for %parentName% parent id %parentId%' => 'Guardando %obj% para %parentName% parent id %parentId%', + 'Search' => 'Buscar', + 'Search page' => 'Página de búsqueda', + 'Select a default template for new products created in this category' => 'Seleccionar una plantilla predeterminada para los nuevos productos de esta categoría', + 'Select the brand logo' => 'Seleccione el logotipo de la marca', + 'Select the brand logo amongst the brand images' => 'Selecciona el logotipo de la marca entre las imágenes', + 'Select the categories of the products covered by this operation' => 'Selecciona las categorías de los productos cubiertos por esta operación', + 'Select the countries to delete from this shipping zone' => 'Selecciona los países de esta zona de envío', + 'Select the countries to include in this shipping zone' => 'Selecciona los países para incluir en esta zona de envío', + 'Select the discount type that will be applied to original product prices' => 'Selecciona el tipo de descuento que se aplicará a los precios originales de los productos', + 'Select the parent category of this category.' => 'Selecciona la categoría principal para esta categoría.', + 'Select the product attributes included in this operation' => 'Selecciona los atributos de los productos incluidos en esta operación', + 'Select the product brand, or supplier.' => 'Selecciona la marca del producto o proveedor.', + 'Select the products covered by this operation' => 'Selecciona los productos cubiertos por esta operación', + 'Select the virtual document' => 'Selecciona el documento virtual', + 'Service ID' => 'ID de servicio', + 'Shipping configuration' => 'Configuración de envío', + 'Shipping zone name' => 'Nombre de la zona de envío', + 'Short additional text' => 'Texto corto adicional', + 'Short description text' => 'Breve descripción', + 'Show redirections *' => 'Mostrar redirecciones *', + 'Sitemap' => 'Mapa del sitio', + 'Sorry, an error occured.' => 'Lo sentimos, se ha producido un error.', + 'Sorry, an error occured: %msg' => 'Lo sentimos, se ha producido un error: msg %', + 'Sorry, an error occured: %s' => 'Lo sentimos, se ha producido un error: %s', + 'Sorry, an error occurred: %err' => 'Lo sentimos, ha ocurrido un error: %err', + 'Sorry, no email defined for this administrator.' => 'Lo sentimos, no hay correo electrónico definido para este administrador.', + 'Sorry, you are not allowed to perform this action.' => 'Lo sentimos, acción no permitida.', + 'Sorry, you\'re not allowed to perform this action' => 'Lo sentimos, no tienes permitido realizar esta acción', + 'Source IP' => 'IP de origen', + 'Start date' => 'Fecha de inicio', + 'Start date and expiration date are inconsistent' => 'Fecha de inicio y fecha de vencimiento son incompatibles', + 'Start date of sales' => 'Fecha de inicio de ventas', + 'State *' => 'Estado *', + 'State ID %id not found' => 'ID estado %id no encontrado', + 'State title' => 'Título estado', + 'Stock' => 'Existencias', + 'Store Business Identification Number (SIRET, etc).' => 'Almacenar el número de identificación de empresa (CIF, VAT, etc.).', + 'Store Information' => 'Información de la tienda', + 'Store configuration failed.' => 'Falló la configuración de la tienda.', + 'Store description' => 'Descripción de la tienda', + 'Store email address' => 'Dirección de correo electrónico de la tienda', + 'Store logs into text file' => 'Almacenar logs en ficheros de texto', + 'Store logs into text file, up to a certian size, then a new file is created' => 'Almacenar logs en ficheros de texto, a partir de un tamaño máximo se crea un nuevo archivo', + 'Store name' => 'Nombre de la tienda', + 'Street Address' => 'Dirección de la calle', + 'Street Address ' => 'Dirección de la calle ', + 'Strictly use the requested language' => 'Utilizar estrictamente el idioma solicitado', + 'Subject' => 'Asunto', + 'Summary' => 'Resumen', + 'Symbol' => 'Símbolo', + 'System' => 'Sistema', + 'System configuration' => 'Configuración del sistema', + 'System log configuration failed.' => 'Error de configuración del sistema de logs.', + 'Tax' => 'Impuestos', + 'Tax ID not found in tax list JSON' => 'IVA/VAT no se encuentran en lista de impuesto JSON', + 'Tax list is not valid JSON' => 'Lista de impuesto no es JSON válido', + 'Tax rule ID not found' => 'Regla de impuestos no encontrada', + 'Tax rule for this product *' => 'Regla de impuestos para este producto *', + 'Taxes' => 'Impuestos', + 'Taxes rules' => 'Reglas de impuestos', + 'Template' => 'Plantilla', + 'Template Name *' => 'Nombre de la plantilla *', + 'Templates' => 'Plantillas', + 'Text File' => 'Archivo de texto', + 'Text Message' => 'Mensaje de texto', + 'The %name module definition has not been initialized.' => 'La definición del módulo %name no ha sido inicializada.', + 'The %name module descriptor has not been initialized.' => 'El descriptor de módulo %name no se ha inicializado.', + 'The %obj_name id \'%id\' doesn\'t exist' => 'El id de %obj_name \'%id\' no existe', + 'The HTML TITLE element is the most important element on your web page.' => 'El elemento de título HTML es el más importante en la página web.', + 'The archiver identifier "%archiverId" doesn\’t exist' => 'El archivador identificador "%archiverId" no existen', + 'The brand name or title' => 'La marca o el título', + 'The cart item count should match the condition' => 'El número de artículos de carrito debe coincidir con la condición', + 'The category title' => 'El título de la categoría', + 'The class "%class" doesn\'t exist' => 'No existe la clase "%class"', + 'The class "%class" must extend %baseClass' => 'La clase "%class" debe extender a %baseClass', + 'The container should not be null in this form. Please use the FormFactory to get an instance.' => 'El contenedor no debe ser nulo en este formulario. Utilice el FormFactory para obtener una instancia.', + 'The coupon applies if the cart contains at least one product of the selected categories' => 'El cupón se aplica si el carrito contiene al menos un producto de las categorías seleccionadas', + 'The coupon applies if the cart contains at least one product of the specified product list' => 'El cupón se aplica si el carrito contiene al menos un producto de la lista del producto especificado', + 'The coupon applies to some customers only' => 'El cupón se aplica solo a algunos clientes', + 'The coupon applies to the selected billing countries' => 'El cupón se aplica a los países y facturación seleccionados', + 'The coupon applies to the selected delivery countries' => 'El cupón de descuento se aplica a los países de envío seleccionados', + 'The coupon code \'%code\' already exist. Please choose another coupon code' => 'El código de cupón \'%code\' ya existe. Por favor, elija otro código de cupón', + 'The coupon code \'%code\' already exists. Please choose another coupon code' => 'El código de cupón \'%code\' ya existe. Por favor, elija otro código de cupón', + 'The coupon is valid after a given date' => 'El cupón de descuento es válido tras la fecha indicada', + 'The date after which sales are de-activated. Please use %fmt format.' => 'La fecha tras la cual las ventas están desactivadas. Por favor usar formato %fmt .', + 'The date from which sales are active. Please use %fmt format.' => 'La fecha desde la que las ventas se activan. Por favor usar formato %fmt .', + 'The detailed description.' => 'La descripción detallada.', + 'The extension "%extension" is not allowed' => 'No se permite la extensión "%extension"', + 'The file %path has been successfully downloaded' => 'El archivo %path se ha descargado con éxito', + 'The following columns are missing: %columns' => 'Faltan las siguientes columnas: %columns', + 'The image which replaces an undefined country flag (%file) was not found. Please check unknown-flag-path configuration variable, and check that the image exists.' => 'No se encuentra la imagen que sustituye a una bandera de país indefinido (%file). Por favor comprueba la variable de configuración de ruta de la bandera y comprueba que la imagen existe.', + 'The language "%id" doesn\'t exist' => 'No existe el idioma "%id"', + 'The lost admin password recovery feature is disabled.' => 'Se desactiva la función de recuperación de contraseña de administrador perdida.', + 'The mailing template in HTML format.' => 'La plantilla de correo electrónico en formato HTML.', + 'The mailing template in text-only format.' => 'La plantilla de correo electrónico únicamente en formato texto.', + 'The method %method% doesn\'t exist in classname %classname%' => 'El método %method% no existe en la clase %classname%', + 'The method name that will handle the hook event.' => 'El nombre del método que controlará el evento de Hook.', + 'The module "%name%" is currently in use by at least one order, and can\'t be deleted.' => 'El módulo "%name%" está actualmente en uso por al menos un pedido y no se puede eliminar.', + 'The module %module has been installed successfully.' => 'El módulo %module se ha instalado con éxito.', + 'The module %name is already installed in the same or greater version.' => 'Ya está instalado el módulo %name en la misma versión o superior.', + 'The module %name requires Thelia %version or newer' => 'El módulo %name necesita Thelia %version o más reciente', + 'The module has to be activated.' => 'El módulo tiene que ser activado.', + 'The module is not valid : %message' => 'El módulo no es válido: %message', + 'The module zip file' => 'El zip del módulo', + 'The product document id %id doesn\'t exists' => 'No existe el id de documento %id', + 'The product image id %id doesn\'t exists' => 'No existe el id de imagen %id', + 'The product sale element id %id doesn\'t exist' => 'No existe la id de elemento del producto de venta %id', + 'The product sale elements id %id doesn\'t exist' => 'El elemento de venta del producto id %id no existe', + 'The product sale elements id %id doesn\'t exists' => 'El elemento de venta del producto id %id no existe', + 'The rate from %currencyCode: Price in %currencyCode x rate = Price in this currency' => 'La tasa de %currencyCode: precio en %currencyCode x tasa = precio en esta moneda', + 'The resource %res has not been found' => 'El recurso %res no ha sido encontrado', + 'The sale announce label, such as Sales ! or Flash Sales !' => 'Etiqueta de anuncio de venta, como ventas! o Super ventas!', + 'The sale name or descriptive title' => 'Nombre de la venta o título descriptivo', + 'The sale name or title' => 'Nombre de la venta o título', + 'The serializer identifier "%serializerId" doesn\’t exist' => 'El serializador identificador "%serializerId" no existe', + 'The service id that will handle the hook (defined in the config.xml file of the module).' => 'Id de servicio que va a controlar el Hook (definido en el archivo config.xml del módulo).', + 'The store fax number.' => 'El número de fax de la tienda.', + 'The store phone number.' => 'El número de teléfono de la tienda.', + 'The symbol, such as $, £, €...' => 'El símbolo, como $, £, €...', + 'The type %type is not valid' => 'El tipo %type no es válido', + 'The zip code format' => 'El formato de código postal', + 'There are no files to associate.' => 'No hay ningún archivo para asociar.', + 'There is no id "%id" in the export categories' => 'No hay ninguna id "%id" en las categorías de exportación', + 'There is no id "%id" in the exports' => 'No hay ninguna id "%id" en las exportaciones', + 'There is no id "%id" in the import categories' => 'No hay ninguna id "%id" en las categorías de exportación', + 'There is no id "%id" in the imports' => 'No hay ninguna id "%id" en las exportaciones', + 'There is no id "%ref" in the imports' => 'No hay ningún id "% ref" en las importaciones', + 'There is no ref "%ref" in the exports' => 'No hay referencia "ref %" en las exportaciones', + 'There\'s a conflict between your file extension "%ext" and the mime type "%mime"' => 'Hay un conflicto entre la extensión de archivo "%ext" y el tipo MIME "%mime"', + 'This PHP extension should be installed and loaded.' => 'Esta extensión PHP debería instalarse y ser cargada.', + 'This administrator login already exists' => 'Este inicio de sesión de administrador ya existe', + 'This brand is online' => 'Esta marca está en línea', + 'This category is online' => 'Esta categoría está en línea', + 'This condition is always true' => 'Esta condición siempre es verdadera', + 'This content is online.' => 'Este contenido está en línea.', + 'This country has states / provinces' => 'Este país tiene estados / provincias', + 'This country is online' => 'Este país está en línea', + 'This coupon adds a free product to the cart if one of the selected products is in the cart.' => 'Este cupón añade un producto gratis al carrito si uno de los productos seleccionados ya está en el carrito.', + 'This coupon does not exists' => 'Este cupón no existe', + 'This coupon subtracts from the order total a percentage of the price of each product which belongs to the selected categories. If the discount is greater than the total order, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.' => 'Este cupón resta del total del pedido un porcentaje del precio de cada producto que pertenece a las categorías seleccionadas. Si el descuento es mayor que el total del pedido, el cliente sólo pagará el envío, o nada si el cupón también ofrece envío gratuito.', + 'This coupon subtracts from the order total the specified percentage of each product price which uses the selected attribute values. If the discount is greater than the total order, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.' => 'Este cupón resta del total del pedido el porcentaje indicado de cada precio de producto que utiliza los valores de atributo seleccionado. Si el descuento es mayor que el total del pedido, el cliente sólo pagará el envío, o nada si el cupón también ofrece envío gratuito.', + 'This coupon subtracts from the order total the specified percentage of each selected product price. If the discount is greater than the total order, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.' => 'Este cupón resta del total del pedido el porcentaje especificado de precio de cada producto seleccionado. Si el descuento es mayor que el total del pedido, el cliente sólo pagará el envío, o nada si el cupón también ofrece envío gratuito.', + 'This coupon subtracts the specified amount from the order total for each product which belongs to the selected categories. If the discount is greater than the total order, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.' => 'Este cupón resta del total del pedido un porcentaje del precio de cada producto perteneciente a las categorías seleccionadas. Si el descuento es mayor que el total del pedido, el cliente sólo pagará el envío, o nada si el cupón también ofrece envío gratuito.', + 'This coupon subtracts the specified amount from the order total for each product which uses the selected attribute values. If the discount is greater than the total order, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.' => 'Este cupón resta del total del pedido un porcentaje del precio de cada producto perteneciente a las categorías seleccionadas. Si el descuento es mayor que el total del pedido, el cliente sólo pagará el envío, o nada si el cupón también ofrece envío gratuito.', + 'This coupon subtracts the specified amount from the order total for each selected product. If the discount is greater than the total order, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.' => 'Este cupón resta la cantidad del total del pedido para cada producto seleccionado. Si el descuento es mayor que el total del pedido, el cliente sólo pagará el envío, o nada si el cupón también ofrece envío gratuito.', + 'This coupon will offert a flat percentage off a shopper\'s entire order (not applied to shipping costs or tax rates). If the discount is greater than the total order corst, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.' => 'Este cupón aplicará un porcentaje fijo sobre todo el pedido de un comprador (excluyendo gastos de envío o impuestos). Si el descuento es mayor que el costo total del pedido, el cliente sólo pagará el envío, o nada si el cupón también ofrece envío gratuito.', + 'This coupon will subtracts a set amount from the total cost of an order. If the discount is greater than the total order corst, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.' => 'Este cupón resta una cantidad del coste total de un pedido. Si el descuento es mayor que dicho coste, el cliente sólo pagará el envío, o nada si el cupón también ofrece envío gratuito.', + 'This document is online' => 'Este documento está online', + 'This email already exists.' => 'Este correo electrónico ya existe.', + 'This email does not exists' => 'Este e-mail no existe', + 'This folder is online.' => 'Esta carpeta está en línea.', + 'This hook is specific to a module (delivery/payment modules).' => 'Este Hook es específico de un módulo (módulos de entrega/pago).', + 'This image is online' => 'Esta imagen está en línea', + 'This is a comma separated list of email addresses where store notifications (such as order placed) are sent.' => 'Esta es una lista separada por comas de direcciones de correo electrónico que reciben notificaciones de tienda (por ejemplo, pedido).', + 'This is an identifier that will be used in the code to get this message' => 'Esto es un identificador que se utilizará en el código para hacer llegar este mensaje', + 'This is the contact email address, and the sender email of all e-mails sent by your store.' => 'Esta es la dirección de correo electrónico de contacto y el correo electrónico de remitente de los e-mails enviados por tu tienda.', + 'This is the message purpose, such as \'Order confirmation\'.' => 'Este es el propósito del mensaje, por ejemplo confirmación de orden.', + 'This is the name used on the login screen' => 'Este es el nombre utilizado en la pantalla de inicio de sesión', + 'This is the subject of the e-mail, such as \'Your order is confirmed\'.' => 'Este es el asunto del mensaje, por ejemplo \'se confirma su pedido\'.', + 'This module has no Markdown documentation.' => 'Este módulo no tiene documentación de ningún descuento.', + 'This product does not have a physical presence' => 'Este producto no tiene presencia física', + 'This product is on sale' => 'Este producto está en venta', + 'This product is online' => 'Este producto está en línea', + 'This product reference is already assigned to another product.' => 'Esta referencia de producto ya está asignada a otro producto.', + 'This product_sale_elements_id does not exists for this product : %d' => 'Este product_sale_elements_id no existe para este producto: %d', + 'This state doesn\'t belong to this country.' => 'Este estado no pertenece a este país.', + 'This state is online' => 'Este estado está en línea', + 'This template is in use in some of your products, and cannot be deleted. Delete it from all your products and try again.' => 'Esta plantilla está en uso en algunos productos y no se puede eliminar. Puedes eliminarla de todos estos productos y vuelver a intentarlo.', + 'This the unique name of this message. Do not change this value unless you understand what you do.' => 'Este el nombre único de este mensaje. No cambies este valor a menos que entiendas lo que haces.', + 'This value should not be blank.' => 'Este valor no debe estar vacío.', + 'This zip code should respect the following format : %format.' => 'Este código postal debe respetar el siguiente formato: %format.', + 'Timeout' => 'Timeout', + 'Title' => 'Título', + 'Title *' => 'Título *', + 'Title ID not found' => 'Título ID no encontrado', + 'To activate module %name, the following modules should be activated first: %modules' => 'Para activar el módulo %name, deben activarse primero los siguientes módulos: $modules', + 'Tools' => 'Herramientas', + 'Translations' => 'Traducciones', + 'Tried to download a file, but the URL was not valid: %url' => 'No se puede descargar archivo, URL no válida: %url', + 'Type' => 'Tipo', + 'URL_ALREADY_EXISTS' => 'La URL ya existe', + 'Unable to get module code from the fullnamespace element of the module descriptor: \'%val\'' => 'No se puede obtener código del módulo del elemento fullnamespace del descriptor de módulo: \' % val\'', + 'Unable to process your request. Please try again (%err).' => 'No se puede procesar solicitud. Por favor, inténtalo de nuevo (%err).', + 'Unconditional usage' => 'Uso incondicional', + 'Unconditionnal usage' => 'Uso incondicional', + 'Undefined loop argument "%name"' => 'Argumento de loop indefinido "%name"', + 'Undefined search mode \'%mode\'' => 'Modo de búsqueda \' %mode\' indefinido', + 'Unknown order ID: %id' => 'ID orden desconocida: %id', + 'Unsupported magic method %name. only getArgname() is supported.' => 'Método mágico %name no soportado. Solamente getArgname() es soportado.', + 'Unsupported type' => 'Tipo no compatible', + 'Update customer account' => 'Actualizar cuenta de cliente', + 'Use a N for a number, L for Letter, C for an iso code for the state.' => 'Use N para un número, L para la letra C para un código iso para este estado.', + 'Use the keyword phrase in your URL.' => 'Utilizar la frase de palabra clav en la URL.', + 'Used in your store front' => 'Utilizado en tu front end de tienda', + 'Username' => 'Nombre de usuario', + 'Username or e-mail address *' => 'Nombre de usuario o dirección de correo electrónico *', + 'Valid only from %date% to the coupon expiration date' => 'Vigencia a partir de %date% desde fecha de vencimiento del cupón', + 'Value' => 'Valor', + 'Value %val for Discount Amount is invalid. Please enter a positive value.' => 'Valor %val de descuento no es válido. Por favor, introduzca un valor positivo.', + 'Value %val for Percent Discount is invalid. Please enter a positive value between 1 and 100.' => 'Valor %val para porcentaje de descuento no es válido. Introduzca un valor positivo entre 1 y 100.', + 'Value *' => 'Valor *', + 'Value create form' => 'Formulario de creación de valor', + 'Variable' => 'Variable', + 'Variables' => 'Variables', + 'Virtual document' => 'Documento virtual', + 'Warnings' => 'Alertas', + 'We\'re sorry, this PDF invoice is not available at the moment.' => 'Lo sentimos, esta factura PDF no está disponible en este momento.', + 'Weight' => 'Peso', + 'When using the %method% method you can automatically render or dump templates or add CSS and JS files (e.g.: render:mytemplate.html;js:assets/js/myjs.js)' => 'Cuando se utiliza el método %method% automáticamente puede representar o descargar plantillas o añadir archivos CSS y JS (por ejemplo: render:mytemplate.html;js:assets/js/myjs.js)', + 'Wrong country definition' => 'Definición de país equivocada', + 'Wrong form method, %s expected.' => 'Método de forma incorrecta, Se esperaba %s.', + 'Yes, I have a password :' => 'Sí, tengo una contraseña:', + 'You are already registered!' => 'Ya estás registrado!', + 'You don\'t need to use commas or other punctuations.' => 'No necesitas usar comas u otros signos de puntuación.', + 'You have to configure your store email first !' => 'Primero tienes que configurar el correo electrónico de tu tienda!', + 'You should select a state for this country.' => 'Se debe seleccionar un estado para este país.', + 'You\'ve submitted this form too many times. ' => 'Has enviado este formulario demasiadas veces. ', + 'Your Email Address' => 'Tu dirección de correo electrónico', + 'Your Message' => 'Tu mensaje', + 'Your configuration seems to be ok. Checked out your mailbox : %email%' => 'La configuración parece estar bien. Extraído de tu buzón de correo: %email%', + 'Your current password does not match.' => 'No coincide con tu contraseña actual.', + 'Your zip must contain 1 root directory which is the root folder directory of your module' => 'Tu archivo zip debe contener un directorio raíz que es el directorio de la carpeta de raíz del módulo', + 'Zip code' => 'Código postal', + 'Zone' => 'Zona', + 'accessories table header' => 'encabezado de la tabla de accesorios', + 'accessories table row' => 'fila de la tabla de accesorios', + 'add to all form' => 'añadir a todos los formularios', + 'additional information' => 'información adicional', + 'address create form' => 'formulario de creación de dirección', + 'address delete form' => 'formulario de eliminación de la dirección', + 'address update form' => 'formulario de actualización de dirección', + 'after addresse area' => 'después de área de la dirección', + 'after combinations' => 'después de las combinaciones', + 'after footer' => 'después del pie de página', + 'after javascript include' => 'después de inclir javascript', + 'after javascript initialisation' => 'después de la inicialización de javascript', + 'after product listing' => 'después de la lista de productos', + 'after the information area' => 'después de la zona de información', + 'after the main content area' => 'después el área de contenido principal', + 'after the opening of the body tag' => 'después de la apertura de la etiqueta body', + 'after the opening of the head tag' => 'después de la apertura de la etiqueta head', + 'after the order summary' => 'tras el resumen del pedido', + 'after top bar' => 'después de la barra superior', + 'after top menu' => 'después del menú principal', + 'api id %id does not exists' => 'api id %id no existe', + 'at the bottom' => 'en la parte inferior', + 'at the bottom of column 1' => 'en la parte inferior de la columna 1', + 'at the bottom of information area' => 'en la parte inferior del área de la información', + 'at the bottom of the catalog' => 'en la parte inferior del catálogo', + 'at the bottom of the detail area' => 'en la parte inferior de la zona de detalle', + 'at the bottom of the footer' => 'en la parte inferior del pie de página', + 'at the bottom of the form' => 'en la parte inferior del formulario', + 'at the bottom of the header' => 'en la parte inferior de la cabecera', + 'at the bottom of the main area' => 'en la parte inferior del área principal', + 'at the bottom of the shipping area' => 'en la parte inferior de la zona de envío', + 'at the bottom of the sidebar' => 'en la parte inferior de la barra lateral', + 'at the bottom of the system area' => 'en la parte inferior de la zona del sistema', + 'at the bottom of the top bar' => 'en la parte inferior de la barra superior', + 'at the top' => 'en la parte superior', + 'at the top of the catalog area' => 'en la parte superior de la zona de catálogo', + 'at the top of the column' => 'en la parte superior de la columna', + 'at the top of the configuration' => 'en la parte superior de la configuración', + 'at the top of the detail' => 'en la parte superior del detalle', + 'at the top of the footer' => 'en la parte superior del pie de página', + 'at the top of the form' => 'en la parte superior del formulario', + 'at the top of the header' => 'en la parte superior de la cabecera', + 'at the top of the main area' => 'en la parte superior del área principal', + 'at the top of the shipping area' => 'en la parte superior de la zona de envío', + 'at the top of the sidebar' => 'en la parte superior de la barra lateral', + 'at the top of the system area' => 'en la parte superior de la zona del sistema', + 'at the top of the top bar' => 'en la parte superior de la barra superior', + 'attributes table header' => 'encabezado de la tabla de atributos', + 'attributes table row' => 'fila de la tabla de atributos', + 'before combinations' => 'antes de las combinaciones', + 'before footer' => 'antes de pie de página', + 'before the end body tag' => 'antes de la etiqueta final del cuerpo', + 'before the end of the head tag' => 'antes del final de la etiqueta head', + 'before the main content area' => 'antes el área de contenido principal', + 'before top menu' => 'antes del menú principal', + 'before topbar' => 'antes de la barra superior', + 'block' => 'bloque', + 'bottom' => 'parte inferior', + 'bottom of the footer' => 'parte inferior del pie de página', + 'cURL errno %errno, http code %http_code on link "%path": %error' => 'cURL error %errno, código http %http_code en enlace "%path": %error', + 'caption' => 'texto', + 'categories table header' => 'encabezado de la tabla de categorías', + 'categories table row' => 'fila de la tabla de categorías', + 'combination delete form' => 'formulario de eliminación de combinación', + 'combinations list caption' => 'título de lista de combinaciones', + 'configuration' => 'configuración', + 'configuration JavaScript' => 'configuración de JavaScript', + 'configuration bottom' => 'configuración de la parte inferior', + 'content' => 'contenido', + 'content area' => 'área de contenido', + 'content delete form' => 'formulario de eliminación de contenido', + 'content edit JavaScript' => 'editar contenido JavaScript', + 'contents table header' => 'encabezado de la tabla de contenido', + 'contents table row' => 'fila de la tabla de contenido', + 'context' => 'contexto', + 'country delete form' => 'formulario de eliminación de país', + 'create JavaScript' => 'crear JavaScript', + 'create form' => 'formulario de creación', + 'customer account' => 'cuenta de cliente', + 'date format' => 'Formato de fecha', + 'decimal separator' => 'separador decimal', + 'delete form' => 'formulario de eliminación', + 'delivery address' => 'dirección de entraga', + 'delivery module %s is not a Thelia\Module\DeliveryModuleInterface' => 'módulo de entrega %s no es un Thelia\Module\DeliveryModuleInterface', + 'details pricing form' => 'formulario de información de precios', + 'details promotion form' => 'formulario de detalles de promoción', + 'email' => 'correo electrónico', + 'email confirmation is not the same as email field' => 'Las dos direcciones de correo electrónico no son idénticas', + 'email system JavaScript' => 'sistema de correo electrónico JavaScript', + 'extra area' => 'zona extra', + 'extra payment zone' => 'zona de pago extra', + 'features table row' => 'fila con tabla de características', + 'features-table-header' => 'encabezado de tabla de características', + 'folders table header' => 'encabezado de la tabla de carpetas', + 'folders table row' => 'fila de la tabla carpetas', + 'footer body' => 'cuerpo de pie de página', + 'header' => 'cabecera', + 'hook delete form' => 'formulario de eliminación de Hook', + 'hook edit JavaScript' => 'hook de edición JavaScript', + 'hour(s)' => 'hora(s)', + 'id delete form' => 'formulario de eliminación de Id', + 'if successful response' => 'si la respuesta es correcta', + 'imprint' => 'aviso legal', + 'in footer' => 'en pie de página', + 'in the header' => 'en la cabecera', + 'in the menu catalog' => 'en el menú catálogo', + 'in the menu configuration' => 'en el menú configuración', + 'in the menu customers' => 'en el menú clientes', + 'in the menu folders' => 'en el menú carpetas', + 'in the menu modules' => 'en el menú módulos', + 'in the menu orders' => 'en el menú pedidos', + 'in the menu tools' => 'en el menú herramientas', + 'in top menu items' => 'en el menú superior', + 'inside top bar' => 'dentro de la barra superior', + 'javascript' => 'JavaScript', + 'javascript initialization' => 'inicialización de JavaScript', + 'label' => 'etiqueta', + 'language locale' => 'Idioma del servidor web', + 'language selection page' => 'página de selección de idioma', + 'list JavaScript' => 'lista JavaScript', + 'list caption' => 'título de la lista', + 'list header' => 'encabezado de lista', + 'list row' => 'fila de la lista', + 'logs JavaScript' => 'logs de JavaScript', + 'mailing system modification' => 'modificación del sistema de correo', + 'main area' => 'área principal', + 'middle' => 'en medio', + 'minute(s)' => 'minuto(s)', + 'password confirmation is not the same as password field' => 'la confirmación de la contraseña no coincide con el campo de contraseña', + 'password must be composed of at least 4 characters' => 'la contraseña debe contener al menos 4 caracteres', + 'payment module %s is not a Thelia\Module\PaymentModuleInterface' => 'el módulo de pago %s no es un Thelia\Module\PaymentModuleInterface', + 'pdf' => 'pdf', + 'permanent discount (in percent)' => 'descuento permanente (en porcentaje)', + 'photo gallery' => 'galería de fotos', + 'plain, login, cram-md5 or empty' => 'plano, login, cram-md5 o vacío', + 'primary navigation' => 'navegación principal', + 'product list' => 'lista de productos', + 'quantity value is not valid' => 'la cantidad no es válida', + 'received value `%value` does not match `%type` type' => 'valor recibido \' %\' no coincide con tipo %', + 'remove to all form' => 'formulario de eliminación múltiple', + 'row' => 'fila', + 'rule create form' => 'formulario de creación de reglas', + 'rule delete form' => 'formulario de eliminación de regla', + 'rule edit JavaScript' => 'edición de regla JavaScript', + 'secondary navigation' => 'navegación secundaria', + 'ssl, tls or empty' => 'ssl, tls o vacío', + 'stock edit form' => 'formulario de edición de stock', + 'table header' => 'encabezado tabla', + 'table row' => 'fila de la tabla', + 'tax rule' => 'regla de impuestos', + 'the body of the sidebar' => 'el cuerpo de la barra lateral', + 'this product id does not exists : %d' => 'esta id de producto no existe : %d', + 'thousands separator' => 'separador de miles', + 'time format' => 'formato de hora', + 'type' => 'tipo', + 'update JavaScript' => 'actualizar JavaScript', + 'update form' => 'formulario de actualización', + 'value table header' => 'encabezado de la tabla de valor', + 'value table row' => 'fila de la tabla de valor', +]; diff --git a/core/lib/Thelia/Config/I18n/fa_IR.php b/core/lib/Thelia/Config/I18n/fa_IR.php new file mode 100644 index 00000000..44b66d9c --- /dev/null +++ b/core/lib/Thelia/Config/I18n/fa_IR.php @@ -0,0 +1,762 @@ + ' فرم ایجاد محتوا', + ' note: only non-visible documents can be associated.' => ' توجه: تنها مستندات غیر قابل رویت می‌توانن الصاق شوند.', + '"%param" parameter cannot be empty in loop type: %type, name: %name' => 'پارامتر "%param" نمی‌تواند در نوع حلقه %type با نام %name خالی باشد', + '"%param" parameter is missing in loop type: %type, name: %name' => 'پارامتر "%param" در نوع حلقه %type با نام %name گم شده است', + '%module (version: %version)' => '%module (نسخه: %version)', + '%obj SEO modification' => 'ویرایش %obj SEO', + '%obj creation' => '%obj ایجاد شد', + '%obj modification' => 'اصلاح %obj', + '%obj%s deleted successfully' => '%obj%s با موفقیت پاک شد', + '%s has dependency to module %s. You have to deactivate this module before.' => '%s وابسته است به این ماژول %s. شما باید اول این ماژول را غیر فعال کنید.', + '%s have dependencies to module %s. You have to deactivate these modules before.' => '%s وابستگی‌های دارد به ماژول %s. شما باید اول این ماژول را غیر فعال کنید.', + '%type% position updated' => 'محل %type% بروز شد', + '%type% visibility updated' => 'نمایش %type% بروز شد', + 'A comma separated list of email addresses' => 'لیست ایمیل‌ها (جدا شده با کاما)', + 'A currency with code "%name" already exists.' => 'ارز با کد "%name" هم اکنون وجود دارد.', + 'A descriptive title' => 'عنوان توصیفی', + 'A message with name "%name" already exists.' => 'یک پیام با نام "%name" هم اکنون وجود دارد.', + 'A name such as Europe or Overseas' => 'یک نام مثل اروپا یا خارج از کشور', + 'A product with reference %ref already exists. Please choose another reference.' => 'یک محصول با شماره %ref هم اکنون وجود دارد. لطفا یک شماره دیگر انتخاب کنید.', + 'A short description, used when a summary or an introduction is required' => 'یک توضیح خلاصه. زمانی که یک خلاصه یا مقدمه مورد نیاز است، استفاده می‌شود', + 'A short text, used when an additional or supplemental information is required.' => 'متن کوتاه، زمانی که اطلاعات اضافی و تکمیلی مورد نیاز است، استفاده می شود.', + 'A user already exists with this email address. Please login or if you\'ve forgotten your password, go to Reset Your Password.' => 'یک کاربر با این آدرس ایمیل وجود دارد. لطفا وارد شوید ویا در صورت فراموشی رمزعبور، درخواست رمزعبور جدید بدهید.', + 'A value for attribute "%name" is already present in the combination' => 'مقدار برای خصوصیت "%name" از قبل در ترکیب ارائه شده', + 'A variable with name "%name" already exists.' => 'یک نام متغیر با نام "%name" هم اکنون وجود دارد.', + 'Activate logs only for these IP Addresses' => 'فعال کردن لاگ تنها برای این آدرس‌های IP', + 'Activate logs only for these files' => 'فعال کردن لاگ تنها برای این فایل‌ها', + 'Activate this sale' => 'فعال کردن این حراج', + 'Active' => 'فعال', + 'Add to all product templates' => 'اضافه کردن به تمام قالب‌های محصول', + 'Additional address' => 'آدرس اضافی', + 'Additional address information' => 'اطلاعات بیشتر در مورد آدرس', + 'Address ID not found' => 'شناسه آدرس یافت نشد', + 'Address Line 2' => 'آدرس دوم', + 'Address Line 3' => 'آدرس سوم', + 'Address creation' => 'ایجاد آدرس', + 'Address label' => 'برچسب آدرس', + 'Address update' => 'به روز رسانی نشانی', + 'Address.' => 'آدرس.', + 'Administrator' => 'مدیر', + 'Administrator ID not found' => 'شناسه مدیر پیدا نشد', + 'Administrators' => 'ادمین', + 'Advertise this product as new' => 'تبلیغ این محصول به عنوان محصول جدید', + 'Alerts' => 'هشدارها', + 'All Products' => 'تمام محصولات', + 'All countries' => 'تمام کشورها', + 'All shipping methods' => 'تمام شیوه‌های حمل و نقل', + 'Amount' => 'مقدار', + 'Apply exchange rates on price in %sym' => 'اعمال نرخ واحد پولی به قیمت در %sym', + 'Archive Format' => 'قالب بایگانی', + 'Associate documents' => 'اسناد مرتبط', + 'Associate images' => 'تصاویر مرتبط', + 'At least one of cart products categories is %op% %categories_list%' => 'حداقل یکی از محصولات دسته‌ها %op% %categories_list% است', + 'Attribut' => 'خصوصیت', + 'Attribute ID:Attribute AV ID' => 'خصوصیت ID:Attribute AV ID', + 'Attribute value' => 'مقدار خصوصیت', + 'Attributes' => 'خصوصیت‌ها', + 'Attributes value' => 'مقدار خصوصیات', + 'Auth mode' => 'حالت شناسایی', + 'Available quantity' => 'تعداد در دسترس', + 'Available quantity *' => 'تعداد در دسترس *', + 'Available shipping zones' => 'مناطق حمل و نقل در دسترس', + 'Back Office' => 'بخش مديريت', + 'Bad tax list JSON' => 'لیست JSON نامعتبر مالیات', + 'Billing country' => 'کشور صادر کننده‌ی صورت حساب', + 'Billing country is' => 'کشور صادر کننده‌ی صورت حساب', + 'Brand' => 'برند', + 'Brand / Supplier' => 'برند / تامین کننده', + 'Brand name' => 'نام برند', + 'Brands' => 'برندها', + 'Business ID' => 'شناسه کسب و کار', + 'By Module' => 'بوسیله ماژول', + 'CSS' => 'CSS', + 'CSS stylesheet' => 'CSS stylesheet', + 'Cannot find a default country. Please define one.' => 'کشور پیش‌فرض یافت نشد. لطفا یکی را انتخاب کنید.', + 'Cannot find the shop country. Please select a shop country.' => 'کشور فروشگاه پیدا نشد. لطفا یک کشور را انتخاب نمایید.', + 'Cannot instantiate module "%name%": the namespace is null. Maybe the model is not loaded ?' => 'نمی‌توان ماژول "%name%" را نمایش داد: namespace-اش نال است. شاید ماژول لود نشده است؟', + 'Cart' => 'سبد خرید', + 'Cart contains at least a product %op% %products_list%' => 'سبد خرید شامل حداقل یک محصول %op% %products_list% است', + 'Cart contains categories condition' => 'سبد خرید شامل شروط دسته بندها است', + 'Cart contains specific products' => 'سبد خرید شامل محصولات مشخصی است', + 'Cart item count' => 'تعداد اقلام سبد خرید', + 'Cart item count is' => 'تعداد اقلام سبد خرید', + 'Cart total amount' => 'مبلغ کل سبد خرید', + 'Cart total amount is' => 'مقدار کل سبد خرید', + 'Catalog' => 'کاتالوگ', + 'Catalog configuration' => 'پیکربندی کاتالوگ', + 'Categories' => 'دسته بندی‌ها', + 'Category' => 'دسته‌بندی', + 'Category page' => 'صفحه دسته‌بندی', + 'Category title' => 'عنوان دسته', + 'Cellphone' => 'تلفن همراه', + 'Change password' => 'تغییر رمز عبور', + 'Check country iso codes here.' => 'بررسی کدهای iso در ویکی‌پدیا.', + 'Check the total Cart amount in the given currency' => 'مقدار کل سبد خرید را با واحد پولی داده شده بررسی کنید', + 'City' => 'شهر', + 'Code' => 'کد', + 'Combination builder' => 'ترکیب ساز', + 'Compagny' => 'شرکت', + 'Company' => 'شرکت', + 'Company Name' => 'نام شرکت', + 'Conclusion' => 'نتيجه گيری', + 'Configuration' => 'پیکربندی', + 'Confirm Email Address' => 'تایید آدرس ایمیل', + 'Confirm Email address' => 'تایید آدرس ایمیل', + 'Constant amount' => 'مقدار ثابت', + 'Constant amount found in one of the product\'s feature' => 'مقدار ثابت در یکی از ویژگی‌های محصول پیدا شده', + 'Contact and sender email address' => 'تماس با ما و فرستنده ایمیل', + 'Contact page' => 'صفحه تماس', + 'Content' => 'محتوا', + 'Content page' => 'صفحه محتوا', + 'Content title *' => 'عنوان محتوا*', + 'Contents' => 'محتوا', + 'Core hook of Thelia.' => 'قلاب هسته از تلیا.', + 'Countries' => 'كشور‌ها', + 'Country' => 'كشور', + 'Country ID not found' => 'شناسه کشور یافت نشد', + 'Country title' => 'عنوان کشور', + 'Coupon' => 'کوپن', + 'Coupon %code is expired.' => 'کد %code منقضی شده است.', + 'Coupon code %code is disabled.' => 'کد تخفیف %code غیرفعال است.', + 'Critical' => 'بحرانی', + 'Curency selection page' => 'صفحه انتخاب واحد پول', + 'Currencies' => 'ارزها', + 'Currency' => 'ارز', + 'Currency name' => 'نام واحد پولی', + 'Current Password' => 'رمزعبور فعلی', + 'Customer' => 'مشتری', + 'Customer is %op% %customer_list%' => 'مشتری %op% %customer_list%', + 'Customers' => 'مشتریان', + 'Dashboard' => 'پیشخوان', + 'Date \'%date\' is invalid, please enter a valid date using %fmt format' => 'تاریخ \'%date\' نامعتبر است لطفا یک تاریخ معتبر با قالب %fmt وارد کنید', + 'Debug' => 'اشکال زدایی', + 'Decimal places' => 'محل اعشار', + 'Default folder *' => 'پوشه پیش‌فرض*', + 'Default product category *' => 'دسته پیش‌فرض محصول*', + 'Default product sale element' => 'عنصر پیش فرض حراج محصول', + 'Default product template' => 'قالب پیش‌فرض محصول', + 'Deleting %obj% for %id% with parent id %parentId%' => 'حذف %obj% برای %id% با شناسه مادر %parentId%', + 'Delivery' => 'تحویل', + 'Delivery choice' => 'انتخاب تحویل', + 'Delivery country' => 'کشور تحویل', + 'Delivery country is' => 'کشور تحویل', + 'Delivery module ID not found' => 'شناسه ماژول تحویل یافت نشد', + 'Delivery zone' => 'منطقه تحویل', + 'Detailed description' => 'شرح مفصل', + 'Disabled' => 'غیرفعال شده', + 'Discount type' => 'نوع تخفیف', + 'Display initial product prices on front-office' => 'نمایش قیمت‌های اولیه‌ي محصولات در فروشگاه', + 'Do compress' => 'فشرده سازی', + 'Document' => 'مستندات', + 'Don\'t repeat keywords over and over in a row. Rather, put in keyword phrases.' => 'کلمات کلیدی را در یک خط به صورت مداوم تکرار نکنید. می‌توانید آن‌ها را در قسمت کلمات کلیدی قرار دهید.', + 'EAN Code' => 'بارکد', + 'Edit' => 'ويرايش', + 'Edit JavaScript' => 'ویرایش جاوااسکریپت', + 'Email Address' => 'آدرس ایمیل', + 'Email address' => 'نشانی ایمیل', + 'Email addresses of notification recipients' => 'آدرس‌های ایمیل گیرندگان اعلان', + 'Email test from : %store%' => 'فرم تست ایمیل: %store%', + 'Emergency' => 'اضطراری', + 'Enable remote SMTP use' => 'فعال سازی استفاده از پروتکل SMTP', + 'Encryption' => 'رمزگذاری', + 'End date of sales' => 'تاریخ پایان حراج', + 'Enter here the brand name in the default language (%title%)' => 'وارد کردن نام برند در زبان پیش‌فرض (%title%)', + 'Enter here the category title in the default language (%title%)' => 'وارد کردن عنوان دسته در زبان پیش‌فرض (%title%)', + 'Enter here the mail template purpose in the default language (%title%)' => 'وارد کردن موضوع قالب ایمیل در زبان پیش‌فرض (%title%)', + 'Enter here the sale name in the default language (%title%)' => 'وارد کردن نام فروش در زبان پیش‌فرض (%title%)', + 'Equal to' => 'برابر با', + 'Error during %action process : %error. Exception was %exc' => 'خطا هنگام پردازش %action: %error. رد شده بوسیله %exc', + 'Error occured while processing order ref. %ref, ID %id: %err' => 'هنگام پردازش کد سفارش خطای رخ داده است. %ref, ID %id: %err', + 'Error occured.' => 'خطایی رخ داده است.', + 'Errors' => 'خطاها', + 'Export' => 'خروجی گرفتن', + 'Fail to delete %obj% for %id% with parent id %parentId% (Exception : %e%)' => 'ناموفق در حذف %obj% برای %id% با شناسه‌ی والد %parentId% (خطا: %e%)', + 'Fail to update %type% position: %err%' => 'ناموفق در آپدیت جایگاه %type%: %err%', + 'Fail to update %type% visibility: %err%' => 'ناموفق در آپدیت وضعیت نمایش %type%: %err%', + 'Failed to create instance of module "%name%" when trying to delete module. Module directory has probably been deleted' => 'هنگام حذف ماژول «%name%»، ایجاد نمونه‌ی ماژول موفقیت ناموفق بود. احتمالا دایرکتوری ماژول حذف شده است', + 'Failed to create new hook %s' => 'مشکل هنگام ایجاد قلاب جدید %s', + 'Failed to deactivate hook with id %s' => 'مشکل هنگام غیرفعال کردن قلاب با شناسه %s', + 'Failed to delete selected countries' => 'عدم موفقیت در پاک کردن کشورهای انتخاب شده', + 'Failed to find a payment Module with ID=%mid for order ID=%oid' => 'مشکل هنگام یافتن یک ماژول پرداخت با شناسه %mid برای سفارش با شناسه %oid', + 'Failed to load descriptor (module.xml) for module ID "%id".' => 'مشکل در بارگذاری توصیف‌گر (module.xml) برای ماژول با شناسه "%id".', + 'Failed to load message with code \'%code%\', propably because it does\'nt exists.' => 'مشکل هنگام بارگذاری پیام با کد \'%code%\' (احتمالا وجود ندارد).', + 'Failed to open a writing stream on the file: %file' => 'ناموفق برای باز کردن استریم نوشتن بر روی فایل: %file', + 'Failed to open translation file %file. Please be sure that this file is writable by your Web server' => 'ناموفق در بازکردن فایل ترجمه‌ی %file. لطفا از اینکه این فایل بر روی وب سرور قابل نوشتن است،‌ اطمینان حاصل کنید', + 'Failed to send message %code. Failed recipients: %failed_addresses' => 'عدم موفقیت در ارسال پیام %code. مشکل در ارسال به: %failed_addresses', + 'Failed to update language definition: %ex' => 'مشکل در بروزرسانی تعریف زبان: %ex', + 'Fax' => 'فکس', + 'Feature' => 'ویژگی', + 'Feature value does not match FLOAT format' => 'مقدار ویژگی با فرمت FLOAT هم‌خوانی ندارد', + 'Features' => 'ویژگی‌ها', + 'Features value' => 'مقدار ویژگی', + 'File format' => 'فرمت فایل', + 'File is too large, please retry with a file having a size less than %size%.' => 'فایل بیش از حد بزرگ است. لطفا با اندازه‌ای کمتر از %size% امتحان کنید.', + 'File to upload' => 'فایل برای آپلود', + 'Files with the following extension are not allowed: %extension, please do an archive of the file if you want to upload it' => 'فایل‌ها با پسوندهای %extension مجاز نیستند، لطفا برای آپلود آن‌ها را به صورت فشرده در بیاورید', + 'First Name' => 'نام', + 'Firstname' => 'نام', + 'Fixed Amount Discount' => 'تخفیف مقدار ثابت', + 'Fixed amount discount for selected attribute values' => 'تخفیف مقدار ثابت برای ویژگی‌های انتخاب شده', + 'Fixed amount discount for selected categories' => 'تخفیف مقدار ثابت برای دسته‌های انتخاب شده', + 'Fixed amount discount for selected products' => 'تخفیف مقدار ثابت برای محصولات انتخاب شده', + 'Folder' => 'پوشه', + 'Folder page' => 'صفحه پوشه', + 'Folder title *' => 'عنوان پوشه*', + 'For one ore more customers' => 'برای یک یا بیشتر از مشتری(ها)', + 'Free product when buying one or more selected products' => 'محصول رایگان درهنگام خرید یک یا بیشتر از محصولات انتخاب شده', + 'Front Office' => 'بخش فروشگاهی', + 'Full Name' => 'نام و نام خانوادگی', + 'Greater than' => 'بیش‌تر از', + 'Greater than or equals' => 'بزرگ‌تر یا مساوی', + 'HTML Message' => 'پیام HTML', + 'HTML layout' => 'چیدمان HTML', + 'Home' => 'خانه', + 'Home page' => 'صفحه نخست', + 'Hook' => 'قلاب', + 'Hook block' => 'بلوک قلاب', + 'Hook code' => 'کد قلاب', + 'Hook create form' => 'فرم ایجاد قلاب', + 'Hook title' => 'عنوان قلاب', + 'Hooks' => 'قلاب‌ها', + 'Host' => 'میزبان', + 'I would like to receive the newsletter or the latest news.' => 'مایل به دریافت خبرنامه هستم.', + 'ISO 4217 code' => 'کد ISO 4217', + 'ISO 639-1 Code' => 'کد ISO 639-1', + 'ISO Alpha-2 code' => 'کد ISO Alpha-2', + 'ISO Alpha-3 code' => 'کد ISO Alpha-3', + 'ISO Code' => 'کد ISO', + 'If a translation is missing or incomplete :' => 'اگر ترجمه از بین رفته یا ناقص است:', + 'If cart item count is %operator% %quantity%' => 'اکر تعداد آیتم سبدخرید برابر بود با %operator% %quantity%', + 'If cart total amount is %operator% %amount% %currency%' => 'اگر مبلغ کل سبد خرید برابر بود با %operator% %amount% %currency%', + 'If checked, this hook will be used by a hook block. If not, by hook function.' => 'در صورت فعال بودن این قلاب بوسیله قلاب بلوک و درغیر اینصورت بوسیله قلاب تابع استفاده می‌شود.', + 'Image' => 'تصویر', + 'Impossible to delete a customer who already have orders' => 'امکان پاک کردن مشتری با سابقه خرید وجود ندارد', + 'In' => 'در', + 'Include documents' => 'شامل اسناد', + 'Include images' => 'شامل تصاویر', + 'Information' => 'اطلاعات', + 'Invalid product_sale_elements' => 'Product_sale_elements نامعتبر', + 'Invalid value "%value" for "%param" parameter in loop type: %type, name: %name' => 'مقدار نامعتبر "%value" برای پارامتر "%param" در نوع حلقه، نام: %name', + 'Invalid value for walkMode parameter: %value' => 'مقدار نامعتبر برای پارامتر walkMode: %value', + 'Invoice' => 'فاکتور', + 'Invoice choice' => 'انتخاب صورت حساب', + 'Is it the default product sale element ?' => 'آیا این المان پیشفرض فروش محصول است؟', + 'It is not allowed to delete the default currency' => 'امکان پاک کردن کشور پیشفرض وجود ندارد', + 'It is not allowed to delete the default language' => 'امکان پاک کردن زبان پیشفرض وجود ندارد', + 'JavaScript' => 'جاوا اسکریپت', + 'Keep the most important part of your description in the first 150-160 characters.' => 'مهمترین قسمت از توضیحات را در ۱۵۰-۱۶۰ کاراکتر اول قرار دهید.', + 'Language' => 'زبان', + 'Language name' => 'نام زبان', + 'Languages' => 'زبان‌‌‌‌‌‌ها', + 'Last Name' => 'نام خانوادگی', + 'Lastname' => 'نام خانوادگی', + 'Layout' => 'چیدمان', + 'Less than' => 'کمتر از', + 'Less than or equals' => 'کمتر یا مساوی', + 'Log format *' => 'قالب لاگ*', + 'Log level *' => 'سطح لاگ*', + 'Login failed. Please check your username and password.' => 'خطا در ورود. لطفا نام کاربری و رمزعبور را بررسی نمایید.', + 'Login page' => 'صفحه ورود', + 'Logs' => 'لاگ‌ها', + 'Loop cannot implements multiple Search Interfaces : `PropelSearchLoopInterface`, `ArraySearchLoopInterface`' => 'حلقه نمی‌تواند چند واسط جستجو داشته باشد: `PropelSearchLoopInterface`, `ArraySearchLoopInterface`', + 'Loop must implements \'PropelSearchLoopInterface\' to be timestampable' => 'حلقه باید \'PropelSearchLoopInterface\' را به صورت timestampable اجرا کند', + 'Loop must implements \'PropelSearchLoopInterface\' to be versionable' => 'حلقه باید \'PropelSearchLoopInterface\' را به صورت نسخه پذیر اجرا کند', + 'Loop must implements one of the following interfaces : `PropelSearchLoopInterface`, `ArraySearchLoopInterface`' => 'حلقه باید واسط‌های `PropelSearchLoopInterface`, `ArraySearchLoopInterface` را اجرا کند', + 'Lost password' => 'فراموشی رمزعبور', + 'Mail template name' => 'نام قالب ایمیل', + 'Mail template purpose' => 'هدف قالب ایمیل', + 'Mailing system' => 'سیستم ایمیلی', + 'Main address' => 'آدرس اصلی', + 'Main area' => 'منطقه اصلی', + 'Make sure it uses keywords found within the page itself.' => 'مطمئن شوید که کلید واژه های کلیدی که در خود صفحه به کار رفته است استفاده می‌کند.', + 'Make sure that your title is clear, and contains many of the keywords within the page itself.' => 'از مشخص بودن عنوان اطمینان حاصل کنید و کلمات کلیدی زیاد را در خود صفحه قرار دهید.', + 'Make this address as my primary address' => 'تبدیل این آدرس به آدرس اصلی من', + 'Maximum usage count reached for coupon %code' => 'محدودیت استفاده از کد تخفیف %code به اتمام رسیده است', + 'Message' => 'پيام', + 'Message name' => 'نام پیام', + 'Message subject' => 'موضوع پیام', + 'Messages' => 'پیام‌ها', + 'Meta Description' => 'توضیحات متا', + 'Meta Keywords' => 'کلمات کلیدی متا', + 'Method Name' => 'نام روش', + 'Missing or invalid data: %s' => 'داده گم شده یا نامعتبر: %s', + 'Module' => 'ماژول', + 'Module "%name%" directory was not found' => 'پوشه ماژول "%name%" یافت نشد', + 'Module %name directory doesn\'t exists.' => 'پوشه ماژول %name پیدا نشد.', + 'Module %name should have a config.xml in the Config directory.' => 'ماژول %name باید دارای فایل config.xml در پوشه تنظیمات باشد.', + 'Module %name should have a module.xml in the Config directory.' => 'ماژول %name باید دارای فایل module.xml در پوشه تنظیمات باشد.', + 'Module ID "%id" was not found.' => 'شناسه ماژول "%id" یافت نشد.', + 'Module ID not found' => 'شناسه ماژول یافت نشد', + 'Module hook' => 'قلاب ماژول', + 'Modules' => 'ماژول‌ها', + 'More information about ISO 4217' => 'اطلاعات بیشتر در مورد ISO 4217', + 'Name' => 'نام', + 'Name *' => 'نام*', + 'Name of the HTML layout file' => 'نام فایل HTML طرح بندی', + 'Name of the HTML template file' => 'نام فایل HTML قالب', + 'Name of the text layout file' => 'نام فایل متنی ساختار طرح', + 'Name of the text template file' => 'نام فایل متنی قالب', + 'Native' => 'محلی', + 'New Password' => 'رمز عبور جدید', + 'Newsletter page' => 'صفحه خبرنامه', + 'No %obj was created.' => '%obj ساخته نشد.', + 'No %obj was updated.' => '%obj بروز نشد.', + 'No module found for code \'%item\'' => 'ماژولی برای کد \'%item\' پیدا نشد', + 'No, I am a new customer.' => 'خیر، من یک مشتری جدید هستم.', + 'None' => 'هیچکدام', + 'Not equal to' => 'نامساوی با', + 'Not in' => 'وجود ندارد در', + 'Notices' => 'اعلامیه', + 'Numerical ISO Code' => 'کدد عددی ISO', + 'Only files having the following mime type are allowed: %types%' => 'تنها فایل‌هایی با پسوند %types% قابل قبول هستند', + 'Only hookable modules are displayed in this menu.' => 'تنها ماژول‌های دارای قلاب در این منو نمایش داده می‌شود.', + 'Only if order billing country is %op% %countries_list%' => 'تنها در صورتی که آدرس صورت حساب کشور برابر باشد با %op% %countries_list% ', + 'Only if order shipping country is %op% %countries_list%' => 'تنها در صورتی که آدرس حمل کشور برابر باشد با %op% %countries_list% ', + 'Order' => 'سفارش', + 'Order address ID not found' => 'شناسه آدرس سفارش یافت نشد', + 'Order failed' => 'سفارش انجام نشد', + 'Order ref. %ref is now unpaid.' => 'سفارش %ref در حال حاضر پرداخت نگردیده است.', + 'Order ref. %ref, ID %id has been successfully paid.' => 'سفارش %ref با شناسه‌ی %id با موفقیت پرداخت شد.', + 'Orders' => 'سفارش', + 'Overall' => 'مجموع', + 'Page 404' => 'صفحه ۴۰۴', + 'Page Title' => 'عنوان صفحه', + 'Parent category' => 'شاخه مادر', + 'Parent folder *' => 'پوشه مادر *', + 'Password' => 'رمز عبور', + 'Password *' => 'رمز عبور *', + 'Password confirmation' => 'تایید رمز عبور', + 'Payment failed' => 'پرداخت ناموفق بود', + 'Payment gateway' => 'درگاه پرداخت', + 'Per customer' => 'در هر مشتری', + 'Percentage' => 'درصد', + 'Percentage discount for selected attribute values' => 'تخفیف درصدی برای مقادیر خصوصیت انتخاب شده', + 'Percentage discount for selected categories' => 'تخفیف درصدی برای دسته‌های انتخاب شده', + 'Percentage discount for selected products' => 'تخفیف درصدی برای محصولات انتخاب شده', + 'Percentage of the product price' => 'درصد از قیمت محصول', + 'Phone' => 'تلفن ثابت', + 'Placed order' => 'سفارشات ثبت شده', + 'Please accept the Terms and conditions in order to register.' => 'لطفا قوانین و مقررات سفارش را برای ثبت نام، تایید کنید.', + 'Please check your input: %error' => 'لطفا ورودی خود را بررسی کنید: %error', + 'Please enter your email address' => 'لطفا آدرس ایمیل خود را وارد کنید', + 'Please enter your password' => 'لطفا رمزعبور خود را وارد کنید', + 'Please select a category' => 'لطفا یک دسته را انتخاب کنید', + 'Please select an attribute' => 'لطفا یک ویژگی را انتخاب کنید', + 'Please select at least one attribute value' => 'حداقل یک مقدار ویژگی را انتخاب کنید', + 'Please select at least one category' => 'حداقل یک دسته را انتخاب کنید', + 'Please select at least one product' => 'حداقل یک محصول را انتخاب کنید', + 'Please select the category of the offred product' => 'لطفا یک دسته برای محصولات پیشنهادی را انتخاب کنید', + 'Please select the offered product' => 'لطفا محصول پیشنهاد داده شده را انتخاب کنید', + 'Please upload a valid Zip file' => 'لطفا یک فایل Zip معتبر آپلود کنید', + 'Port' => 'درگاه', + 'Postage' => 'هزینه پست', + 'Preferred locale' => 'زبان ارجح', + 'Prevent mailing template modification or deletion, except for super-admin' => 'جلوگیری از ویرایش یا حدف قالب‌های ایمیلی، به غیر از مدیر کل', + 'Prevent variable modification or deletion, except for super-admin' => 'جلوگیری از ویرایش یا حدف متغیرها، به غیر از مدیر کل', + 'Price currency *' => 'واحد پول قیمت*', + 'Processing cancelation of payment for order ref. %ref' => 'در حال انجام لغو پرداخت برای سفارش %ref', + 'Processing confirmation of order ref. %ref, ID %id' => 'در حال انجام تایید سفارش %ref با شناسه‌ی %id', + 'Prodcut ID *' => 'شناسه محصول *', + 'Product' => 'محصول', + 'Product ID' => 'شناسه محصول', + 'Product ID *' => 'شناسه محصول *', + 'Product attributes' => 'مشخصه‌های محصول', + 'Product base price excluding taxes *' => 'قیمت پایه‌ی محصول بدون در نظر گرفتن مالیات *', + 'Product base price with taxes' => 'قیمت محصول همراه با مالیات', + 'Product categories' => 'دسته‌های محصول', + 'Product clone' => 'کپی محصول', + 'Product loop' => 'حلقه محصول', + 'Product page' => 'صفحه محصول', + 'Product price excluding taxes' => 'قیمت محصول بدون مالیات', + 'Product price excluding taxes *' => 'قیمت محصول بدون مالیات *', + 'Product price including taxes' => 'قیمت محصول با مالیات', + 'Product price offset for each currency' => 'حاشیه‌ی قیمت محصول برای هر واحد پولی', + 'Product reference (must be unique)' => 'شناسه محصول (باید یکتا باشد)', + 'Product reference *' => 'شناسه محصول *', + 'Product sale element ID *' => 'شناسه عنصر حراج محصول *', + 'Product template' => 'قالب محصول', + 'Product title' => 'عنوان کالا', + 'ProductSaleElement modification' => 'تغییر ProductSaleElement', + 'Products' => 'محصولات', + 'Profile' => 'پروفایل', + 'Profile Code' => 'کد پروفایل', + 'Profile ID not found' => 'شناسه حساب کاربری پیدا نشد', + 'Profile `code` already exists' => 'کد حساب کاربری هم اکنون وجود دارد', + 'Profiles' => 'پروفایل‌ها', + 'Purpose' => 'هدف', + 'Purpose *' => 'هدف *', + 'Quantity' => 'تعداد', + 'Range date End' => 'محدوده تاریخ پایان', + 'Range date Start' => 'محدوده تاریخ شروع', + 'Rate' => 'نرخ', + 'Redirecting ...' => 'تغییر مسیر...', + 'Redirecting to %url' => 'تغییر مسیر به %url', + 'Reference' => 'مرجع', + 'Reference *' => 'مرجع *', + 'Register' => 'عضویت', + 'Remember me ?' => 'بخاطر سپردن', + 'Remove X percent to total cart' => 'حدف فلان درصد از سبد خرید', + 'Replace by the default language' => 'جایگزینی با زبان پیش‌فرض', + 'Replace current document by this file' => 'جایگزینی مستند کنونی با این فایل', + 'Replace current image by this file' => 'جایگزینی تصویر کنونی با این فایل', + 'Reseller' => 'نماینده فروش', + 'Rewriten URL' => 'بازنویسی URL', + 'Rotated Text File' => 'گردش فایل متنی', + 'Sale announce label' => 'برچسب اعلان حراج', + 'Sale price excluding taxes' => 'قیمت فروش بدون مالیات', + 'Sale price including taxes' => 'قیمت فروش با مالیات', + 'Sale title' => 'عنوان فروش', + 'Saving %obj% for %parentName% parent id %parentId%' => 'ذخیره %obj% برای %parentName% با شناسه مادر %parentId%', + 'Search' => 'جستجو', + 'Search page' => 'صفحه جستجو', + 'Select a default template for new products created in this category' => 'انتخاب قالب پیش‌فرض برای محصولات جدید ایجاد شده در این دسته', + 'Select the brand logo' => 'انتخاب لوگوی برند', + 'Select the brand logo amongst the brand images' => 'انتخاب لوگو برند از میان تصاویر', + 'Select the categories of the products covered by this operation' => 'انتخاب دسته‌های محصول پوشش داده شده توسط این اقدام', + 'Select the countries to delete from this shipping zone' => 'انتخاب کشورها برای حذف از این ناحیه حمل و نقل', + 'Select the countries to include in this shipping zone' => 'انتخاب کشورها برای افزودن به این ناحیه حمل و نقل', + 'Select the discount type that will be applied to original product prices' => 'انتخاب نوع تخفیف برای اعمال به قیمت‌های اصلی محصول', + 'Select the parent category of this category.' => 'انتخاب دسته مادر.', + 'Select the product attributes included in this operation' => 'انتخاب خصوصیات محصول شامل شده در این عملیات', + 'Select the product brand, or supplier.' => 'انتخاب برند یا تامین کننده محصول.', + 'Select the products covered by this operation' => 'انتخاب محصولات پوشش داده شده توسط این اقدام', + 'Select the virtual document' => 'انتخاب سند مجازی', + 'Service ID' => 'شناسه سرویس', + 'Shipping configuration' => 'پیکربندی حمل و نقل', + 'Shipping zone name' => 'نام منطقه حمل و نقل', + 'Short additional text' => 'متن کوتاه اضافی', + 'Short description text' => 'متن توضیحات کوتاه', + 'Show redirections *' => 'نمایش ری‌دایرکشن‌ها *', + 'Sitemap' => 'نقشه سایت', + 'Sorry, an error occured.' => 'متاسفیم، یک خطا رخ داد.', + 'Sorry, an error occured: %msg' => 'متاسفیم، یک خطا رخ داد: %msg', + 'Sorry, an error occured: %s' => 'متاسفیم، یک خطا رخ داد: %s', + 'Sorry, an error occurred: %err' => 'متاسفیم، یک خطا رخ داد: %err', + 'Sorry, you are not allowed to perform this action.' => 'متاسفیم، شما مجاز به انجام این کار نیستید.', + 'Sorry, you\'re not allowed to perform this action' => 'متاسفیم، شما مجاز به انجام این کار نیستید', + 'Source IP' => 'منبع IP', + 'Start date' => 'تاریخ شروع', + 'Start date of sales' => 'تاریخ شروع فروش', + 'Stock' => 'موجودی', + 'Store Business Identification Number (SIRET, etc).' => 'ذخیره‌ی شماره شناسایی اقتصادی', + 'Store Information' => 'اطلاعات فروشگاه', + 'Store configuration failed.' => 'ذخیره تنظیمات ناموفق بود.', + 'Store description' => 'توضیحات فروشگاه', + 'Store email address' => 'آدرس ایمیل فروشگاه', + 'Store logs into text file' => 'ذخیره لاگ‌ها در فایل متنی', + 'Store logs into text file, up to a certian size, then a new file is created' => 'ذخیره لاگ‌ها در فایل متنی تا رسیدن به حجم مشخص و سپس ایجاد فایل جدید', + 'Store name' => 'نام فروشگاه', + 'Street Address' => 'آدرس خیابان', + 'Street Address ' => 'آدرس خیابان ', + 'Strictly use the requested language' => 'تاکیدا استفاده از زبان درخواست شده', + 'Subject' => 'موضوع', + 'Summary' => 'چکیده', + 'Symbol' => 'نماد', + 'System' => 'سیستم', + 'System configuration' => 'پیکربندی سیستم', + 'System log configuration failed.' => 'پیکربندی لاگ سیستم انجام نشد.', + 'Tax' => 'مالیات', + 'Tax ID not found in tax list JSON' => 'شناسه مالیات در لیست JSON مالیات یافت نشد', + 'Tax list is not valid JSON' => 'لیست مالیات یک فایل JSON معتبر نیست', + 'Tax rule ID not found' => 'شناسه قانون مالیات یافت نشد', + 'Tax rule for this product *' => 'قانون مالیات برای این محصول *', + 'Taxes' => 'ماليات‌ها', + 'Taxes rules' => 'قوانین مالیاتی', + 'Template' => 'قالب', + 'Template Name *' => 'نام قالب *', + 'Templates' => 'قالب‌ها', + 'Text File' => 'متن فایل', + 'Text Message' => 'متن پیام', + 'The %name module definition has not been initialized.' => 'تعریف ماژول %name راه اندازی نشد.', + 'The %name module descriptor has not been initialized.' => 'توصیف ماژول %name راه اندازی نشد.', + 'The %obj_name id \'%id\' doesn\'t exist' => 'شناسه %obj_name \'%id\' وجود ندارد', + 'The HTML TITLE element is the most important element on your web page.' => 'المان عنوان مهمترین قسمت در صفحه وب شما است.', + 'The brand name or title' => 'نام برند', + 'The cart item count should match the condition' => 'تعداد آیتم سبدخرید باید با شرایط مسابقه هم‌خوانی داشته باشد', + 'The category title' => 'عنوان دسته', + 'The class "%class" doesn\'t exist' => 'کلاس "%class" وجود ندارد', + 'The class "%class" must extend %baseClass' => 'کلاس "%class" باید گسترش دهنده %baseClass باشد', + 'The container should not be null in this form. Please use the FormFactory to get an instance.' => 'کانتینر نبایستی در این فرم خالی باشد. لطفا از FormFactory برای گرفتن یک نمونه استفاده کنید.', + 'The coupon applies if the cart contains at least one product of the selected categories' => 'کد تخفیف زمانی که حداقل یک محصول از دسته‌های انتخاب شده در سبدخرید قرار داشته باشد، اعمال می‌گردد', + 'The coupon applies if the cart contains at least one product of the specified product list' => 'کد تخفیف زمانی که حداقل یک محصول از لیست مشخص شده در سبدخرید قرار داشته باشد، اعمال می‌گردد', + 'The coupon applies to some customers only' => 'کد تخفیف تنها شامل برخی از مشتریان می‌شود', + 'The coupon applies to the selected billing countries' => 'کد تخفیف به صورت حساب کشورهای انتخاب شده اعمال می‌شود', + 'The coupon applies to the selected delivery countries' => 'کد تخفیف به مقصد حمل کشورهای انتخاب شده اعمال می‌شود', + 'The coupon code \'%code\' already exist. Please choose another coupon code' => 'کد تخفیف \'%code\' وجود دارد. لطفا یک کد دیگر را امتحان کنید', + 'The coupon code \'%code\' already exists. Please choose another coupon code' => 'کد تخفیف \'%code\' وجود دارد. لطفا یک کد دیگر را امتحان کنید', + 'The coupon is valid after a given date' => 'کد تحفیف بعد از تاریخ مشخص شده فعال می‌شود', + 'The date after which sales are de-activated. Please use %fmt format.' => 'لطفا برای تاریخی که بعد از غیرفعال شدن هر حراج زده می‌شود از این فرمت %fmt استفاده کنید.', + 'The date from which sales are active. Please use %fmt format.' => 'لطفا برای تاریخی که بعد از فعال شدن هر حراج زده می‌شود، از این فرمت %fmt استفاده کنید.', + 'The detailed description.' => 'توضیحات مفصل.', + 'The file %path has been successfully downloaded' => 'فایل %path با موفقیت دانلود شد', + 'The following columns are missing: %columns' => 'ستون‌های زیر یافت نشده است: %columns', + 'The image which replaces an undefined country flag (%file) was not found. Please check unknown-flag-path configuration variable, and check that the image exists.' => 'تصویر (%file) پرچمی که برای تصویر پرچم هر کشوری که پرچمش پیدا نشود با آن جایگزین می‌شود. لطفا مسیر پرچم‌هایی که شناسایی نشده اند را در قسمت پیکربندی متغیرها بررسی کنید و چک کنید که آیا تصویرش وجود دارد یا خیر.', + 'The language "%id" doesn\'t exist' => 'زبان "%id" وجود ندارد', + 'The mailing template in HTML format.' => 'قالب ایمیل در فرمت HTML.', + 'The mailing template in text-only format.' => 'قالب ایمیل در فرمت متن خام.', + '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.' => 'ماژول "%name%" هم اکنون حداقل برای یک سفارش استفاده شده است و نمی‌تواند پاک شود.', + 'The module %module has been installed successfully.' => 'ماژول %module با موفقیت نصب شد.', + 'The module %name is already installed in the same or greater version.' => 'ماژول %name هم اکنون با همین نسخه ویا نسخه بالاتر نصب شده است.', + 'The module %name requires Thelia %version or newer' => 'ماژول %name نیازمند تلیا با نسخه %version و بالاتر است', + 'The module has to be activated.' => 'ماژول فعال شد.', + 'The module is not valid : %message' => 'ماژول معتبر نیست: %message', + 'The module zip file' => 'فایل zip ماژول', + 'The product document id %id doesn\'t exists' => 'شناسه %id محتوای محصول وجود ندارد', + 'The product image id %id doesn\'t exists' => 'شناسه تصویر %id محصول وجود ندارد', + 'The product sale element id %id doesn\'t exist' => 'شناسه‌ی %id عنصر حراج محصول وجود ندارد', + 'The product sale elements id %id doesn\'t exist' => 'شناسه‌ی %id عنصرهای حراج محصول وجود ندارد', + 'The product sale elements id %id doesn\'t exists' => 'شناسه‌ی %id عنصر حراج محصول وجود ندارد', + 'The resource %res has not been found' => 'منبع %res یافت می‌نشد', + 'The sale announce label, such as Sales ! or Flash Sales !' => 'برچسب اعلان حراج می‌تواند چیزی شبیه به عبارات «حراج»! یا «حراج ویژه» باشد!', + 'The sale name or descriptive title' => 'نام حراج یا عنوان توصيفی', + 'The sale name or title' => 'نام فروش یا عنوان', + 'The service id that will handle the hook (defined in the config.xml file of the module).' => 'شناسه‌ی سرویسی که مسولیت مدیریت قلاب را دارد در فایل config.xml ماژول تعریف شده است.', + 'The store fax number.' => 'شماره فکس فروشگاه.', + 'The store phone number.' => 'شماره تماس فروشگاه.', + 'The type %type is not valid' => 'نوع %type معتبر نیست', + 'There are no files to associate.' => 'هیچ فایل مرتبطی وجود ندارد.', + 'There is no id "%id" in the export categories' => 'شناسه "%id" در خروجی دسته‌ها وجود ندارد', + 'There is no id "%id" in the exports' => 'شناسه "%id" در خروجی‌ها وجود ندارد', + 'There is no id "%id" in the import categories' => 'شناسه "%id" در ورود دسته‌ها وجود ندارد', + 'There is no id "%id" in the imports' => 'شناسه "%id" در ورود وجود نداشت', + 'There\'s a conflict between your file extension "%ext" and the mime type "%mime"' => 'در اینجا تداخلی بین پسوند %ext فایل شما و نوع میمه‌ "%mime" رخ داده است', + 'This PHP extension should be installed and loaded.' => 'این افزودنی PHP باید نصب و اجرا شود.', + 'This brand is online' => 'این برند فعال است', + 'This category is online' => 'این دسته فعال است', + 'This condition is always true' => 'شرط همیشه درست است', + 'This content is online.' => 'محتوا فعال است.', + 'This coupon adds a free product to the cart if one of the selected products is in the cart.' => 'این کد تخفیف در صورتی که محصولات انتخاب شده در سبد خرید قرار بگیرند، یک محصول رایگان را به سبد خرید اضافه می‌کند.', + 'This coupon does not exists' => 'این کد تخفیف وجود ندارد', + 'This coupon subtracts from the order total a percentage of the price of each product which belongs to the selected categories. If the discount is greater than the total order, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.' => 'این کد تخفیف از مجموع سفارش یک درصد از قیمت هریک از دسته‌های انتخاب شده را کم می‌کند. درصورتی که این مقدار بیش از مجموع سفارش باشد، مشتری تنها هزینه حجم و نقل را می‌پردازد مگر در حالتی که کدتخفیف شامل حمل رایگان نیز باشد.', + 'This coupon subtracts from the order total the specified percentage of each product price which uses the selected attribute values. If the discount is greater than the total order, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.' => 'این کد تخفیف از مجموع سفارش، درصد مشخص شده از مقادر خصوصیات انتخاب شده را کم می‌کند. درصورتی که این مقدار بیش از مجموع سفارش باشد، مشتری تنها هزینه حجم و نقل را می‌پردازد مگر در حالتی که کدتخفیف شامل حمل رایگان نیز باشد.', + 'This document is online' => 'این نوشته فعال است', + 'This email already exists.' => 'این ایمیل در حال حاضر وجود دارد.', + 'This email does not exists' => 'این ایمیل وجود ندارد', + 'This folder is online.' => 'این پوشه فعال است.', + 'This hook is specific to a module (delivery/payment modules).' => 'این قالب برای ماژول خاصی تعبیه شده (ماژول‌های پرداخت/تحویل).', + 'This image is online' => 'این تصویر فعال است', + '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 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 subject of the e-mail, such as \'Your order is confirmed\'.' => 'این قسمت مشخص کننده‌ی موضوع ایمیل است، مانند «سفارش شما تایید شد».', + 'This module has no Markdown documentation.' => 'این ماژول مستندات مارک دانی ندارد.', + 'This product does not have a physical presence' => 'این محصول ابعاد فیزیکی ندارد', + 'This product is on sale' => 'این محصول در حراج است', + 'This product is online' => 'این محصول فعال است', + 'This product reference is already assigned to another product.' => 'این مرجع محصول قبلا به محصول دیگری اختصاص داده شده است.', + 'This product_sale_elements_id does not exists for this product : %d' => 'این product_sale_elements_id برای این محصول وجود ندارد: %d', + '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 value should not be blank.' => 'این مقدار نباید خالی باشد.', + 'Timeout' => 'زمان پایان', + 'Title' => 'عنوان', + 'Title *' => 'عنوان *', + 'Title ID not found' => 'شناسه عنوان یافت نشد', + 'To activate module %name, the following modules should be activated first: %modules' => 'برای فعال کردن ماژول %name، ماژول‌های زیر باید ابتدا فعال شود: %modules', + 'Tools' => 'ابزارها', + 'Translations' => 'ترجمه‌ها', + 'Tried to download a file, but the URL was not valid: %url' => 'سعی در دانلود یک فایل، اما آدرس معتبر نیست: %url', + 'Type' => 'نوع', + 'URL_ALREADY_EXISTS' => 'این آدرس هم اکنون وجود دارد', + 'Unable to get module code from the fullnamespace element of the module descriptor: \'%val\'' => 'قادر به دریافت کد ماژول از عنصر fullnamespace ماژول descriptor نیست: \'%val\'', + 'Unable to process your request. Please try again (%err).' => 'قادر به پردازش درخواست شما نیست. لطفا دوباره سعی کنید (%err).', + 'Unconditional usage' => 'استفاده بی قید و شرط', + 'Unconditionnal usage' => 'استفاده بی قید و شرط', + 'Undefined loop argument "%name"' => 'آرگومان "%name" لوپ ناشناخته است', + 'Undefined search mode \'%mode\'' => 'این حالت جستجو \'%mode\' ناشناخته است', + 'Unknown order ID: %id' => 'شناسه سفارش ناشناخته: %id', + 'Unsupported magic method %name. only getArgname() is supported.' => 'عدم پشتیبانی از روش %name. تنها getArgname() پشتیبانی می‌شود.', + 'Unsupported type' => 'نوع پشتیبانی نشده', + 'Update customer account' => 'بروزرسانی حساب کاربری مشتری', + 'Use the keyword phrase in your URL.' => 'لز عبارت کلیدی در URL خود استفاده کنید.', + 'Used in your store front' => 'استفاده شده در ویترین فروشگاه', + 'Username' => 'نام کاربری', + 'Valid only from %date% to the coupon expiration date' => 'فقط از این تاریخ %date% به بعد قادر به تعیین تاریخ انقضا کوپن هستید', + 'Value' => 'مقدار', + 'Value %val for Discount Amount is invalid. Please enter a positive value.' => 'مقدار %val برای میزان تخفیف نامعتبر است. لطفا یک مقدار مثبت وارد کنید.', + 'Value %val for Percent Discount is invalid. Please enter a positive value between 1 and 100.' => 'مقدار %val برای درصد تخفیف نامعتبر است. لطفا یک مقدار مثبت عددی بین بازه‌ی ۰ تا ۱۰۰ وارد کنید.', + 'Value *' => 'مقدار *', + 'Value create form' => 'فرم ایجاد مقدار', + 'Variable' => 'متغیر', + 'Variables' => 'متغیرها', + 'Virtual document' => 'سند مجازی', + 'Warnings' => 'هشدارها', + 'We\'re sorry, this PDF invoice is not available at the moment.' => 'متاسفیم، نسخه PDF صورت حساب در حال حاضر وجود ندارد.', + 'Weight' => 'وزن', + 'Wrong form method, %s expected.' => 'خطا از سمت متد، انتظار می‌رود از %s است.', + 'Yes, I have a password :' => 'بله، رمزعبور دارم:', + 'You are already registered!' => 'شما هم اکنون ثبت نام کرده‌اید!', + 'You don\'t need to use commas or other punctuations.' => 'شما لازم نیست از کاما یا نقطه گذاری دیگری استفاده کنید.', + 'You have to configure your store email first !' => 'شما باید ابتدا ایمیل فروشگاه خود را مشخص کنید!', + 'You\'ve submitted this form too many times. ' => 'شما بیش از اندازه این فرم را ارسال کرده‌اید. ', + 'Your Email Address' => 'آدرس ایمیل شما', + 'Your Message' => 'پیام شما', + 'Your configuration seems to be ok. Checked out your mailbox : %email%' => 'تنظیمات شما به نظر درست می‌رسد. ایمیل خود را بررسی کنید:‌ %email%', + 'Your current password does not match.' => 'رمزعبور فعلی شما مطابقت ندارد.', + 'Your zip must contain 1 root directory which is the root folder directory of your module' => 'فایل zip بایستی شامل یک دایرکتوری روت باشد که آن همان پوشه دایرکتوری ماژول شما است', + 'Zip code' => 'کد پستی', + 'Zone' => 'منطقه', + 'accessories table header' => 'سرآیند جدول ملحقات', + 'accessories table row' => 'ردیف جدول ملحقات', + 'add to all form' => 'افزودن به تمام فرم‌ها', + 'additional information' => 'اطلاعات اضافی', + 'address create form' => 'فرم ایجاد آدرس', + 'address delete form' => 'فرم پاک کردن آدرس', + 'address update form' => 'فرم بروزرسانی آدرس', + 'after addresse area' => 'بعد از قسمت آدرس', + 'after combinations' => 'پس از ترکیب', + 'after footer' => 'بعد از فوتر', + 'after javascript include' => 'بعد از وارد کردن جاوا اسکریپت', + 'after javascript initialisation' => 'پس از مقداردهی اولیه‌ی جاوا اسکریپت', + 'after product listing' => 'بعد از لیست محصول', + 'after the information area' => 'پس از منطقه اطلاعات', + 'after the main content area' => 'بعد از قسمت محتوای اصلی', + 'after the opening of the body tag' => 'بعد از باز شدن تگ body', + 'after the opening of the head tag' => 'بعد از باز شدن تگ head', + 'after the order summary' => 'بعد از خلاصه سفارش', + 'after top bar' => 'بعد از نوار بالا', + 'after top menu' => 'بعد از منوی بالا', + 'api id %id does not exists' => 'شناسه api %id وجود ندارد', + 'at the bottom' => 'در پایین', + 'at the bottom of column 1' => 'در پایین ستون 1', + 'at the bottom of information area' => 'در پایین منطقه اطلاعات', + 'at the bottom of the catalog' => 'در پایین کاتالوگ', + 'at the bottom of the detail area' => 'در پایین فضای جزئیات', + 'at the bottom of the footer' => 'در پایین فوتر', + 'at the bottom of the form' => 'در پایین فرم', + 'at the bottom of the header' => 'در پایین هدر', + 'at the bottom of the main area' => 'در پایین ناحیه‌ی اصلی', + 'at the bottom of the shipping area' => 'در پایین ناحیه‌ی حمل و نقل', + 'at the bottom of the sidebar' => 'در پایین نوار کناری', + 'at the bottom of the system area' => 'در پایین منطقه سیستم', + 'at the bottom of the top bar' => 'در پایین نوار بالا', + 'at the top' => 'در بالای', + 'at the top of the catalog area' => 'در بالای بخش کاتالوگ', + 'at the top of the column' => 'در بالای ستون', + 'at the top of the configuration' => 'در بالای قسمت پیکربندی', + 'at the top of the detail' => 'بالای بخش جزئیات', + 'at the top of the footer' => 'بالای فوتر', + 'at the top of the form' => 'بالای فرم', + 'at the top of the header' => 'بالای هدر', + 'at the top of the main area' => 'بالای بخش اصلی', + 'at the top of the shipping area' => 'بالای بخش حمل و نقل', + 'at the top of the sidebar' => 'بالای نوار کناری', + 'at the top of the system area' => 'بالای بخش سیستم', + 'at the top of the top bar' => 'بالای نوار بالا', + 'attributes table header' => 'خصوصیت هدر جدول', + 'attributes table row' => 'خصوصیت ردیف جدول', + 'before combinations' => 'قبل از ترکیب', + 'before footer' => 'قبل از فوتر', + 'before the end body tag' => 'قبل از بسته شدن تگ body', + 'before the end of the head tag' => 'قبل از بسته شدن تگ head', + 'before the main content area' => 'قبل از قسمت محتوای اصلی', + 'before top menu' => 'قبل از منوی بالا', + 'before topbar' => 'قبل از topbar', + 'block' => 'بلوک', + 'bottom' => 'پایین', + 'bottom of the footer' => 'پایین فوتر', + 'cURL errno %errno, http code %http_code on link "%path": %error' => 'cURL errno %errno, http code %http_code on link "%path": %error', + 'caption' => 'شرح', + 'categories table header' => 'هدر جدول دسته بندی', + 'categories table row' => 'ردیف جدول دسته بندی', + 'combination delete form' => 'فرم حذف ترکیب', + 'combinations list caption' => 'توضیحات لیست ترکیبات', + 'configuration' => 'پیکربندی', + 'configuration JavaScript' => 'پیکربندی جاوااسکریپت', + 'configuration bottom' => 'تنظیمات پایین', + 'content' => 'محتوا', + 'content area' => 'قسمت محتوا', + 'content delete form' => 'فرم پاک کردن محتوا', + 'content edit JavaScript' => 'جاوا اسکریپت ویرایش مطالب', + 'contents table header' => 'هدر جدول محتویات', + 'contents table row' => 'ردیف جدول محتویات', + 'context' => 'چهار چوب', + 'country delete form' => 'فرم حذف کشور', + 'create JavaScript' => 'ایجاد جاوااسکریپت', + 'create form' => 'فرم ایجاد', + 'customer account' => 'حساب مشتری', + 'date format' => 'قالب تاریخ', + 'decimal separator' => 'جداکننده ده دهی', + 'delete form' => 'حذف فرم', + 'delivery address' => 'آدرس تحویل', + 'delivery module %s is not a Thelia\Module\DeliveryModuleInterface' => 'ماژول تحویل %s یک Thelia\Module\DeliveryModuleInterface نیست', + 'details pricing form' => 'فرم جزئیات قیمت‌گذاری', + 'details promotion form' => 'فرم جزئیات پروموشن', + 'email' => 'ایمیل', + 'email confirmation is not the same as email field' => 'آدرس‌های ایمیل یکسال نیست', + 'email system JavaScript' => 'جاوا اسکریپت سیستم ایمیل', + 'extra area' => 'قسمت اضافی', + 'extra payment zone' => 'ناحیه پرداخت های اضافی', + 'features table row' => 'ردیف جدول ویژگی‌ها', + 'features-table-header' => 'هدر جدول ویژگی‌ها', + 'folders table header' => 'هدر جدول پوشه‌ها', + 'folders table row' => 'ردیف جدول پوشه‌ها', + 'footer body' => 'بدنه فوتر', + 'header' => 'هدر', + 'hook delete form' => 'فرم حذف قلاب', + 'hook edit JavaScript' => 'قلاب ویرایش جاوا اسکریپت', + 'hour(s)' => 'ساعت(ها)', + 'id delete form' => 'شناسه فرم حذف', + 'if successful response' => 'درصورت پاسخ موفق', + 'imprint' => 'مهر زدن', + 'in footer' => 'در فوتر', + 'in the header' => 'در هدر', + 'in the menu catalog' => 'در منوی کاتالوگ', + 'in the menu configuration' => 'در منوی پیکربندی', + 'in the menu customers' => 'در منوی مشتریان', + 'in the menu folders' => 'در منوی پوشه‌ها', + 'in the menu modules' => 'در منوی ماژول‌ها', + 'in the menu orders' => 'در منوی سفارش‌ها', + 'in the menu tools' => 'در منوی ابزارها', + 'in top menu items' => 'در بالای آیتم‌های منو', + 'inside top bar' => 'در نوار بالا', + 'javascript' => 'جاوااسکریپت', + 'javascript initialization' => 'راه اندازی جاوااسکریپت', + 'label' => 'برچسب', + 'language locale' => 'زبان محلی', + 'language selection page' => 'صفحه انتخاب زبان', + 'list JavaScript' => 'لیست جاوا اسکریپت', + 'list caption' => 'توضیحات لیست', + 'list header' => 'هدر لیست', + 'list row' => 'ردیف لیست', + 'logs JavaScript' => 'لاگ‌های جاوااسکریپت', + 'mailing system modification' => 'اصلاح سیستم پستی', + 'main area' => 'بخش اصلی', + 'middle' => 'وسط', + 'minute(s)' => 'دقیقه', + 'password confirmation is not the same as password field' => 'رمزعبور یکسان نیست', + 'password must be composed of at least 4 characters' => 'رمز عبور باید حداقل 4 کاراکتر باشد', + 'payment module %s is not a Thelia\Module\PaymentModuleInterface' => 'ماژول پرداخت %s از نوع رابط ماژول پرداخت تلیا PaymentModuleInterface پیروی نمی‌کند', + 'pdf' => 'pdf', + 'permanent discount (in percent)' => 'تخفیف دائمی (به درصد)', + 'photo gallery' => 'گالری تصویر', + 'plain, login, cram-md5 or empty' => 'plain, login, cram-md5 or empty', + 'primary navigation' => 'منوی اصلی', + 'product list' => 'لیست محصولات', + 'quantity value is not valid' => 'مقدار موجودی معتبر نیست', + 'remove to all form' => 'حذف از تمام فرم‌ها', + 'row' => 'ردیف', + 'rule create form' => 'فرم ایجاد قانون', + 'rule delete form' => 'فرم حذف قانون', + 'rule edit JavaScript' => 'جاوا اسکریپت ویرایش قانون', + 'secondary navigation' => 'منوی ثانویه', + 'ssl, tls or empty' => 'ssl، tls ویا خالی', + 'stock edit form' => 'فرم ویرایش موجودی', + 'table header' => 'هدر جدول', + 'table row' => 'ردیف جدول', + 'tax rule' => 'قانون مالیات', + 'the body of the sidebar' => 'بدنه‌ی نوار کناری', + 'this product id does not exists : %d' => 'شناسه محصول %d وجود ندارد', + 'thousands separator' => 'جدا کننده هزار', + 'time format' => 'قالب زمان', + 'type' => 'نوع', + 'update JavaScript' => 'بروزرسانی جاوااسکریپت', + 'update form' => 'فرم بروزرسانی', + 'value table header' => 'مقدار هدر جدول', + 'value table row' => 'مقدار ردیف جدول', +]; diff --git a/core/lib/Thelia/Config/I18n/fr_FR.php b/core/lib/Thelia/Config/I18n/fr_FR.php new file mode 100644 index 00000000..3df9007d --- /dev/null +++ b/core/lib/Thelia/Config/I18n/fr_FR.php @@ -0,0 +1,866 @@ + '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.', + '"%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 is missing in loop type: %type, name: %name' => 'Le paramètre "%param" est absent dans la boucle type: %type, nom: %name ', + '#000000' => '#000000', + '%module (version: %version)' => '%module (version: %version)', + '%n for number, %c for the currency code, %s for the currency symbol' => '%n pour le nombre, %c pour le code de devise, %s pour le symbole monétaire', + '%obj SEO modification' => 'Modification SEO de %obj', + '%obj creation' => 'Création de %obj', + '%obj modification' => 'Modification de %obj', + '%obj%s deleted successfully' => '%obj%s ont été supprimé(e)s', + '%s has dependency to module %s. You have to deactivate this module before.' => '%s a une dépendance au module %s. Vous devez d\'abord désactiver ce module.', + '%s have dependencies to module %s. You have to deactivate these modules before.' => '%s a des dépendances aux modules %s. Vous devez d\'abord désactiver ces modules.', + '%type% position updated' => 'Mise à jour de la position de %type%', + '%type% visibility updated' => 'La visibilité de %type% mise à jour', + 'A Hook with code %name already exists. Please choose another code.' => 'Le code %name est déjà utilisé par un autre Hook. Merci d\'en choisir un autre.', + 'A comma separated list of email addresses' => 'Une liste d\'adresses e-mail séparées par des virgules', + 'A currency with code "%name" already exists.' => 'Une devise avec la code "%name" existe déjà', + 'A descriptive title' => 'Un titre descriptif', + 'A message with name "%name" already exists.' => 'Un message avec le nom "%name" existe déjà.', + 'A name such as Europe or Overseas' => 'Un nom comme Europe ou Outre-Mer', + 'A product with reference %ref already exists. Please choose another reference.' => 'Un produit portant la référfence %ref existe déja. Merci de choisir une autre référence.', + 'A short description, used when a summary or an introduction is required' => 'Une courte description, utilisée lorsqu\'un résumé ou une introduction est requise', + 'A short text, used when an additional or supplemental information is required.' => 'Un texte court, utilisé quand une conclusion ou une information complémentaire est nécessaire.', + 'A user already exists with this email address. Please login or if you\'ve forgotten your password, go to Reset Your Password.' => 'Un utilisateur existe déjà avec cette adresse email. Connectez-vous ou demandez une ré-initialisation de votre mot de passe.', + 'A value for attribute "%name" is already present in the combination' => 'Une valeur pour la déclinaison "%name" est déjà présente dans la combinaison', + 'A variable with name "%name" already exists.' => 'Une variable avec le nom "%name" existe déjà.', + 'Activate logs only for these IP Addresses' => 'Activer les logs uniquement pour ces adresses IP', + 'Activate logs only for these files' => 'Activer les logs uniquement pour ces fichiers', + 'Activate this sale' => 'Activer cette promotion', + 'Active' => 'Actif', + 'Add to all product templates' => 'Ajouter à tous les gabarits de produit', + 'Additional address' => 'Adresse complémentaire', + 'Additional address information' => 'Complément d\'adresse', + 'Address ID not found' => 'ID de l\'adresse non trouvé', + 'Address Line 2' => 'Adresse suite', + 'Address Line 3' => 'Adresse suite', + 'Address creation' => 'Création adresse', + 'Address label' => 'Libellé', + 'Address update' => 'Mise à jour de l\'adresse', + 'Address.' => 'Adresse', + 'Addresses for this country need a zip code' => 'Les adresses pour ce pays nécessitent un code postal', + 'Administrator' => 'Administrateur', + 'Administrator ID not found' => 'ID de l\'administrateur non trouvé', + 'Administrator email address' => 'Adresse e-mail de l\'administrateur', + 'Administrators' => 'Administrateurs', + 'Advertise this product as new' => 'Afficher ce produit comme nouveau', + 'Alerts' => 'Alertes', + 'All Products' => 'Tous les produits', + 'All countries' => 'Tous les pays', + 'All shipping methods' => 'Tous les modes de livraison', + 'Amount' => 'Montant', + 'An administrator with thie email address already exists' => 'Cet emailm est déjà utilisé par un autre administrateur.', + 'An administrator with this email address already exists' => 'Un compte administrateur avec cette adresse mail existe déjà', + 'An invalid token was provided, your password cannot be changed' => 'Un jeton non valide a été fourni, votre mot de passe ne peuvent pas être modifié', + 'Apply exchange rates on price in %sym' => 'Appliquer le taux de change sur le prix en %sym', + 'Archive Format' => 'Format d\'archive', + 'Associate documents' => 'Documents associés', + 'Associate images' => 'Images associées', + 'At least one of cart products categories is %op% %categories_list%' => 'Au moins une des catégories des produits présents dans le panier %op% %categories_list% ', + 'Attribut' => 'Attribut', + 'Attribute ID:Attribute AV ID' => 'Déclinaison ID : Valeur de déclinaison ID', + 'Attribute value' => 'Valeur d\'attribut', + 'Attributes' => 'Attributs', + 'Attributes value' => 'Valeur des attributs', + 'Auth mode' => 'Mode d\'authentification', + 'Automatic rendered templates' => 'Templates générés automatiquement', + 'Available quantity' => 'Quantité disponible', + 'Available quantity *' => 'Quantité disponible *', + 'Available shipping zones' => 'Zones de livraison disponibles', + 'Back Office' => 'Back Office', + '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 is' => 'Le pays de facturation est', + 'Brand' => 'Marque', + 'Brand / Supplier' => 'Marque / Fournisseur', + 'Brand name' => 'Nom de la marque', + 'Brands' => 'Marques', + 'Business ID' => 'ID du business', + 'By Module' => 'Par module', + 'CSS' => '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 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 hide the default language' => 'Impossible de masquer la langue par défaut', + 'Cannot instantiate module "%name%": the namespace is null. Maybe the model is not loaded ?' => 'Ne peut instancier le module "%name%": le namespace est null. Peut-être que le modèle n\'est pas chargé ?', + 'Cart' => 'Panier', + 'Cart contains at least a product %op% %products_list%' => 'Le panier contient au moins un produit %op% %products_list% ', + 'Cart contains categories condition' => 'Valable si le panier contient/ne contient pas des produits appartenant à certaines catégories', + 'Cart contains specific products' => 'Valable si le panier contient certains produits', + 'Cart item count' => 'Nombre d\'articles dans le panier', + 'Cart item count is' => 'Le nombre d\'articles dans le panier est', + 'Cart item include quantity count' => 'Nombre d\'articles quantité incluse dans le panier', + 'Cart item include quantity count is' => 'Le nombre d\'articles quantité incluse dans le panier est', + 'Cart total amount' => 'Montant total du panier', + 'Cart total amount is' => 'Le total du panier est', + 'Catalog' => 'Catalogue', + 'Catalog configuration' => 'Configuration du catalogue', + 'Categories' => 'Rubriques', + 'Category' => 'Catégorie', + 'Category page' => 'Page catégorie', + 'Category title' => 'Titre de la rubrique', + 'Cellphone' => 'Numéro de portable', + 'Change password' => 'Changement de mot de passe', + 'Check country iso codes here.' => 'Vous trouverez les codes ISO des pays sur Wikipedia.', + 'Check the total Cart amount in the given currency' => 'Applique une condition sur le montant total du panier dans la devise indiquée.', + 'Choice a color for this order status code' => 'Choisissez la couleur à associer à ce statut', + 'City' => 'Ville', + 'Code' => 'Code', + 'Combination builder' => 'Générateur de combinaison', + 'Compagny' => 'Société', + 'Company' => 'Entreprise', + 'Company Name' => 'Nom de la société', + 'Conclusion' => 'Conclusion', + 'Configuration' => 'Configuration', + 'Confirm Email Address' => 'Confirmez votre adresse e-mail', + 'Confirm Email address' => 'Confirmez votre adresse e-mail', + 'Constant amount' => 'Montant fixe', + 'Constant amount found in one of the product\'s feature' => 'Montant fixe trouvé depuis une caractéristique produit', + 'Contact and sender email address' => 'Adresse e-mail de contact, et d\'envoi des mails de la boutique', + 'Contact page' => 'Page contact', + 'Content' => 'Contenu', + 'Content page' => 'Page de contenu', + 'Content title *' => 'Titre du contenu *', + 'Contents' => 'Contenus', + 'Copy of %tpl' => 'Copie de %tpl', + 'Core hook of Thelia.' => 'Point d\'accroche Thelia officiel', + 'Countries' => 'Pays', + 'Country' => 'Pays', + 'Country ID %id not found' => 'L\'ID pays \'%id\' est introuvable', + 'Country ID not found' => 'ID du pays non trouvé', + 'Country list is not valid JSON' => 'Le JSON de la liste des pays n\'est pas valide', + 'Country title' => 'Titre du pays', + 'Coupon' => 'Code promo', + 'Coupon %code is expired.' => 'La date limite d\'utilisation du coupon %code est dépassée.', + 'Coupon %code is not release.' => 'Le code promo \'%code\' n\'est pas valide.', + 'Coupon code %code is disabled.' => 'Le code promo %code est désactivé.', + 'Critical' => 'Critique', + 'Curency selection page' => 'Page du choix de la device', + 'Currencies' => 'Devises', + 'Currency' => 'Devise', + 'Currency name' => 'Nom de la devise', + 'Current Password' => 'Mot de passe actuel.', + 'Customer' => 'Client', + 'Customer is %op% %customer_list%' => 'Le client est %op% %customer_list% ', + 'Customers' => 'Clients', + 'Dashboard' => 'Tableau de bord', + 'Date \'%date\' is invalid, please enter a valid date using %fmt format' => 'La date \'%date\' est incorrecte, merci d\'indiquer une date au format %fmt', + 'Debug' => 'Débug', + 'Decimal places' => 'Nombre de chiffres après la virgule', + 'Default folder *' => 'Dossier par défaut *', + 'Default product category *' => 'Catégorie du produit par défaut *', + 'Default product sale element' => 'Product Sale Element par défaut', + 'Default product template' => 'Gabarit de produit par défaut', + 'Deleting %obj% for %id% with parent id %parentId%' => 'Suppression de %obj%, ID %id%, ID parent %parentId%', + 'Delivery' => 'Bon de livraison', + 'Delivery choice' => 'Choix du transporteur', + 'Delivery country' => 'Pays de livraison', + 'Delivery country is' => 'Le pays de livraison est', + 'Delivery module ID not found' => 'Id du module de livraison non trouvé', + 'Delivery zone' => 'Zone de livraison', + 'Detailed description' => 'Description détaillée', + 'Disabled' => 'Désactivé', + 'Discount type' => 'Type de remise', + 'Display initial product prices on front-office' => 'Afficher le prix non soldé dans le front-office', + 'Do compress' => 'Compresser', + 'Document' => 'Document', + 'Don\'t repeat keywords over and over in a row. Rather, put in keyword phrases.' => 'Ne répétez pas sans cesse les même mots-clés dans une ligne. Préférez utiliser des expressions de mots-clés', + 'EAN Code' => 'Code EAN', + 'Edit' => 'Modifier', + 'Edit JavaScript' => 'Editez le Javascript', + 'Email Address' => 'Adresse mail', + 'Email address' => 'Adresse e-mail', + 'Email addresses of notification recipients' => 'Adresses e-mails des destinataires des notifications', + 'Email test from : %store%' => 'E-mail de test de : %store%', + 'Emergency' => 'Urgence', + 'Enable remote SMTP use' => 'Activer l\'utilisation d\'un serveur SMTP distant.', + 'Encryption' => 'Chiffrement', + 'End date of sales' => 'Date de fin de la promotion', + 'Enter here the brand name in the default language (%title%)' => 'Indiquez le nom de la marque dans la langue par défaut (%title%)', + 'Enter here the category title in the default language (%title%)' => 'Entrez ici le titre de la catégorie dans la langue par défaut (%title%)', + 'Enter here the mail template purpose in the default language (%title%)' => 'Indiquez la fonction de ce message dans la langue par défaut (%title%)', + 'Enter here the order status code' => 'Indiquez ici le code de ce statut de commande', + 'Enter here the order status name in the default language (%title%)' => 'Indiquez le libellé de ce statut dans la langue par défaut (%title%) ', + 'Enter here the sale name in the default language (%title%)' => 'Indiquez le titre de cette promotion dans la langue par défaut (%title%)', + 'Enter the new password' => 'Saisissez le nouveau mot de passe', + 'Enter the new password again' => 'Raisissez le nouveau mot de passe', + 'Equal to' => 'Egal à', + 'Error during %action process : %error. Exception was %exc' => 'Erreur lors de %action: %error. Exception: %exc ', + 'Error occured while processing order ref. %ref, ID %id: %err' => 'Un erreur est survenue pendant le traitement de la commande ref. %ref, ID %id; %err', + 'Error occured.' => 'Une erreur s\'est produite', + 'Error occurred while cancelling order ref. %ref, ID %id: %err' => 'Une erreur est survenue lors de l\'annulation de la commande %ref, ID %id: %err', + 'Error occurred while saving payment transaction %transaction_ref for order ID %id.' => 'La transaction %transaction_ref n\'a pas pu être enregistrée pour la commande ID %id.', + 'Error(s) in import :
%errors' => 'Erreur(s) dans l\'import :
%errors', + 'Errors' => 'Erreurs', + 'Export' => 'Export', + 'Fail to delete %obj% for %id% with parent id %parentId% (Exception : %e%)' => 'Ne peut supprimer %obj% ID %id% ID parent %parentId% (Exception : %e%)', + 'Fail to update %type% position: %err%' => 'Erreur lors de la mise à jour de la position de %type% : %err%', + 'Fail to update %type% visibility: %err%' => 'Impossible de mettre à jour la visibilité de %type% : %err%', + 'Failed to create instance of module "%name%" when trying to delete module. Module directory has probably been deleted' => 'Ne peut créer une instance du module "%name%" lors de la suppression du module. Le répertoire du module à sans doute été supprimé manuellement.', + 'Failed to create new hook %s' => 'Impossible de créer le nouveau point d\'accroche %s', + 'Failed to deactivate hook with id %s' => 'Impossible de désactiver le point d\'accroche avec l\'id : %s', + 'Failed to delete selected countries' => 'La suppression des pays sélectionnés a échoué.', + 'Failed to find a payment Module with ID=%mid for order ID=%oid' => 'Ne peut trouver le module de paiement ID=%mid pour la commande ID=%oid ', + 'Failed to load descriptor (module.xml) for module ID "%id".' => 'Le descripteur (module.xml) n\'a pas pu être chargé pour le module ID "%id"', + 'Failed to load message with code \'%code%\', propably because it does\'nt exists.' => 'Impossible de trouver un message ayant le code \'%code%\'.', + 'Failed to open a writing stream on the file: %file' => 'Impossible d\'écrire le fichier %file', + '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 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', + 'Feature' => 'Caractéristique', + 'Feature value does not match FLOAT format' => 'valeur de caractéristique n\'est pas un FLOAT', + 'Features' => 'Caractéristiques', + 'Features value' => 'Valeur de caractéristiques', + 'File format' => 'Format de fichier', + 'File is too large, please retry with a file having a size less than %size%.' => 'La taille de ce fichier est trop importante. Merci d\'envoyer des fichier dont la taille est inférieure à %size%.', + 'File to upload' => 'Fichier à envoyer', + 'Files with the following extension are not allowed: %extension, please do an archive of the file if you want to upload it' => 'Les fichiers avec l\'extension suivante ne sont pas acceptés: %extension, veuillez créer une archive contenant ce fichier si vous voulez l\'envoyer', + 'First Name' => 'Prénom', + 'Firstname' => 'Prénom', + 'Fixed Amount Discount' => 'Remise sur total panier - montant fixe', + 'Fixed amount discount for selected attribute values' => 'Remise sur valeur de caractéristique - montant fixe', + 'Fixed amount discount for selected categories' => 'Remise sur catégorie - montant fixe', + 'Fixed amount discount for selected products' => 'Remise sur produit - montant fixe', + 'Folder' => 'Dossier', + 'Folder page' => 'Page dossier', + 'Folder title *' => 'Titre du dossier *', + 'For one ore more customers' => 'Valable pour un ou plusieurs clients', + 'Format' => 'Format', + 'Free product when buying one or more selected products' => 'Produit offert pour l\'achat d\'un ou plusieurs produits', + 'Front Office' => 'Front Office', + 'Full Name' => 'Nom complet', + 'Further submissions will be ignored during %time' => 'Les accès à ce formulaire seront bloqués pendant %time', + 'Greater than' => 'Supérieur à', + 'Greater than or equals' => 'Supérieur ou égal à', + 'HTML Message' => 'Message au format HTML', + 'HTML layout' => 'Structure HTML', + 'Home' => 'Accueil', + 'Home page' => 'Page d\'accueil', + 'Hook' => 'Point d\'accroche', + 'Hook block' => 'Point d\'accroche de type bloc', + 'Hook code' => 'Code du point d\'accroche', + 'Hook create form' => 'Formulaire de création de point d\'accroche', + 'Hook title' => 'Titre du point d\'accroche', + 'Hooks' => 'Points d\'accroche', + '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.', + 'ISO 4217 code' => 'Code ISO 4217', + 'ISO 639-1 Code' => 'Code ISO 639-1', + 'ISO Alpha-2 code' => 'Code ISO Alpha-2', + 'ISO Alpha-3 code' => 'Code ISO Alpha-3', + 'ISO Code' => 'Code ISO', + '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.', + 'If a translation is missing or incomplete :' => 'Si une traduction est manquante ou incomplète :', + 'If cart item (include quantity) count is %operator% %quantity%' => 'Le nombre d\'articles (quantité incluse) dans le panier est %operator% %quantity% ', + 'If cart item count is %operator% %quantity%' => 'Le nombre d\'articles dans le panier est %operator% %quantity% ', + 'If cart total amount is %operator% %amount% %currency%' => 'Si le total du panier est %operator% %amount% %currency% ', + 'If checked, this hook will be used by a hook block. If not, by hook function.' => 'Indique que ce point d\'accroche utilise un bloc Smarty hookBlock. sinon une fonction Smarty hook.', + 'If you use automatic insert templates, you should use the method %method%' => 'Si vous utilisez les modèles d\'insertion automatique, vous devez utiliser la méthode %method%', + 'Image' => 'Image', + 'Import successfully done, %count row(s) have been changed' => 'L\'import s\'est correctement déroulé, %count ligne(s) ont été modifiées', + 'Impossible to check value `%value` for `%type` type' => 'Impossible de vérifier la valeur `%value` pour le type `%type`', + 'Impossible to delete a customer who already have orders' => 'Impossible de supprimer un client si celui-ci a déjà une commande', + 'In' => 'Compris dans', + 'Include documents' => 'Inclure les documents', + 'Include images' => 'Inclure les images', + 'Information' => 'Information', + 'Invalid product_sale_elements' => 'product_sale_elements invalide', + 'Invalid username or email.' => 'Nom d\'utilisateur ou mot de passe invalide.', + 'Invalid value "%value" for "%param" parameter in loop type: %type, name: %name' => 'La valeur "%value" est invalide pour le paramètre "%param" dans la boucle type: %type, nom: %name ', + 'Invalid value for walkMode parameter: %value' => 'Valeur incorrecte pour le paramètre walkMode : %value', + 'Invoice' => 'Facture', + 'Invoice choice' => 'Choix du mode de paiement', + 'Is it the default product sale element ?' => 'Est-ce la déclinaison du produit par défaut ?', + 'Iso code for states. It depends of the country.' => 'Code ISO pour les États. Cela dépend du pays.', + 'It is not allowed to delete the default currency' => 'Il n\'est pas possible de supprimer la devise par défaut', + 'It is not allowed to delete the default language' => 'Il n\'est pas possible de supprimer la langue par défaut', + 'JavaScript' => 'JavaScript', + 'Keep the most important part of your description in the first 150-160 characters.' => 'Votre description ne devrait pas dépasser 150 à 160 caractères', + 'Language' => 'Langue', + 'Language name' => 'Nom de la langue', + 'Languages' => 'Langues', + 'Last Name' => 'Nom', + 'Lastname' => 'Nom', + 'Layout' => 'Mise en page', + 'Leave blank to keep current customer password' => 'Laissez ce champ vide pour ne pas changer le mot de passe', + 'Less than' => 'Inférieur à', + 'Less than or equals' => 'Inférieur ou égal à', + 'Log format *' => 'Format des logs *', + 'Log level *' => 'Niveau de log *', + 'Login failed. Please check your username and password.' => 'Erreur de login. Veuillez vérifier votre login et votre mot de passe.', + 'Login name' => 'Identifiant', + 'Login page' => 'Page de connexion', + 'Logs' => 'Historiques', + 'Loop cannot implements multiple Search Interfaces : `PropelSearchLoopInterface`, `ArraySearchLoopInterface`' => 'Une boucle ne peut implémenter plusieurs Search Interfaces : `PropelSearchLoopInterface`, `ArraySearchLoopInterface`', + 'Loop must implements \'PropelSearchLoopInterface\' to be timestampable' => 'Les classes \'boucle\' doivent implémenter \'PropelSearchLoopInterface\' pour être horodatables', + 'Loop must implements \'PropelSearchLoopInterface\' to be versionable' => 'Les classes \'boucle\' doivent implémenter \'PropelSearchLoopInterface\' pour être versonnables', + 'Loop must implements one of the following interfaces : `PropelSearchLoopInterface`, `ArraySearchLoopInterface`' => 'Une boucle doit implémenter au moins une de ces interfaces : `PropelSearchLoopInterface`, `ArraySearchLoopInterface`', + 'Lost password' => 'Mot de passe perdu', + 'Mail template name' => 'Nom de ce gabarit e-mail', + 'Mail template purpose' => 'Fonction de ce message', + 'Mailing system' => 'Envoi des e-mails', + 'Main address' => 'Adresse principale', + 'Main area' => 'Zone principale', + 'Make sure it uses keywords found within the page itself.' => 'Assurez vous d\'utiliser des mots-clés présents dans la page courante', + 'Make sure that your title is clear, and contains many of the keywords within the page itself.' => 'Assurez-vous d\'avoir un titre clair et qui contient les mots-clés correspondant à la page en cours', + 'Make this address as my primary address' => 'Choisir cette adresse comme adresse par défaut', + 'Maximum usage count reached for coupon %code' => 'Le nombre maximum d\'utilisation pour le coupon %code est dépassé.', + 'Message' => 'Message', + 'Message name' => 'Nom du message', + 'Message subject' => 'Sujet', + 'Messages' => 'Messages', + 'Meta Description' => 'Meta description', + 'Meta Keywords' => 'Meta keywords', + 'Method Name' => 'Nom de la méthode', + 'Missing or invalid data: %s' => 'Donnée manquante ou non valide : %s', + 'Module' => 'Module', + 'Module "%name%" directory was not found' => 'Le répertoire du module "%name%" n\'a pas été trouvé', + 'Module %name directory doesn\'t exists.' => 'Le répertoire du module %name n\'existe pas.', + 'Module %name should have a config.xml in the Config directory.' => 'Le répertoire Config du module %name doit contenir un fichier config.xml.', + 'Module %name should have a module.xml in the Config directory.' => 'Le répertoire Config du module %name doit contenir un fichier module.xml.', + 'Module ID "%id" was not found.' => 'Le module ID "%id" n\'a pas été trouvé.', + 'Module ID not found' => 'Id du module non trouvé', + 'Module hook' => 'Points d\'accroche des modules', + 'Modules' => 'Modules', + 'More information about ISO 4217' => 'Plus d\'information à propos de l\'ISO 4217', + 'Name' => 'Nom', + 'Name *' => 'Nom *', + 'Name of the HTML layout file' => 'Nom du layout HTML', + 'Name of the HTML template file' => 'Nom du template HTML', + 'Name of the text layout file' => 'Nom du layout texte', + 'Name of the text template file' => 'Nom du template texte', + 'Native' => 'Natif', + 'New Password' => 'Nouveau mot de passe.', + 'Newsletter page' => 'Page newsletter', + 'No %obj was created.' => 'aucun %obj n\'a été créé.', + 'No %obj was updated.' => 'Aucun %obj mis à jour', + 'No module found for code \'%item\'' => 'Aucun module trouvé pour \'%item\' ', + 'No, I am a new customer.' => 'Non, je suis un nouveau client.', + 'None' => 'Aucun', + 'Not equal to' => 'N\'est pas égal à', + 'Not in' => 'Non compris dans', + 'Notices' => 'Notices', + 'Numerical ISO Code' => 'Code ISO numérique', + 'Only files having the following mime type are allowed: %types%' => 'Seuls les types MIME autorisés sont les suivants: %types%', + 'Only hookable modules are displayed in this menu.' => 'Seul les modules qu\'il est possible de placer dans un point d\'accroche sont affichés', + 'Only if order billing country is %op% %countries_list%' => 'Si le pays de facturation %op% %countries_list% ', + 'Only if order shipping country is %op% %countries_list%' => 'Si le pays de livraison %op% %countries_list% ', + 'Order' => 'Commande', + 'Order address ID not found' => 'ID de l\'adresse de la commande non trouvé', + 'Order failed' => 'Echec de la commande', + 'Order ref. %ref is now unpaid.' => 'La commande %ref, ID %id est désormais non payée', + 'Order ref. %ref, ID %id has been successfully paid.' => 'La commande ref. %ref, ID %id a été correctement payée', + 'Order status code' => 'Code du statut de commande', + 'Order status color' => 'Couleur associée à ce statut', + 'Order status name' => 'Libellé du statut de commande', + 'Orders' => 'Commandes', + 'Overall' => 'Pour tous les clients', + 'Page 404' => 'Page introuvable', + 'Page Title' => 'Titre de la page', + 'Parent category' => 'Catégorie parent', + 'Parent folder *' => 'Dossier parent *', + 'Password' => 'Mot de passe', + 'Password *' => 'Mot de passe *', + 'Password confirmation' => 'Confirmation du mot de passe.', + 'Payment failed' => 'Echec du paiement', + 'Payment gateway' => 'Passerelle de paiement', + 'Payment module ID not found' => 'ID du module de paiement non trouvé', + 'Payment transaction %transaction_ref for order ref. %ref, ID %id has been successfully saved.' => 'La transaction %transaction_ref pour la commande ref. %ref ID %id a bien été enregistrée', + 'Per customer' => 'Par client', + 'Percent' => 'Pourcent', + 'Percentage' => 'Pourcentage', + 'Percentage discount for selected attribute values' => 'Remise sur valeur de caractéristique - pourcentage', + 'Percentage discount for selected categories' => 'Remise sur catégorie - pourcentage', + 'Percentage discount for selected products' => 'Remise sur produit - pourcentage', + 'Percentage of the product price' => 'Pourcentage du prix du produit', + 'Phone' => 'Téléphone', + 'Placed order' => 'Commande terminée', + 'Please accept the Terms and conditions in order to register.' => 'Veuillez accepter les termes et conditions pour vous inscrire.', + 'Please check your input: %error' => 'Merci de vérifier votre saisie: %error', + 'Please enter a valid email address' => 'Veuillez saisir une adresse email valide', + 'Please enter your email address' => 'Renseignez votre adresse mail', + 'Please enter your password' => 'Entrez votre mot de passe.', + 'Please select a category' => 'Merci de choisir une catégorie', + 'Please select an attribute' => 'Merci de choisir une déclinaison', + 'Please select at least one attribute value' => 'Merci de choisir au moins une valeur de déclinaison', + 'Please select at least one category' => 'Merci de choisir au moins une catégorie.', + 'Please select at least one product' => 'Merci de choisir au moins un produit', + 'Please select the category of the offred product' => 'Merci de choisir la catégorie du produit offert', + 'Please select the offered product' => 'Merci de choisir le produit offert', + 'Please upload a valid Zip file' => 'Veuillez uploader un fichier Zip valide', + 'Port' => 'Port', + 'Postage' => 'Frais de livraison', + 'Preferred language' => 'Langue préférée', + 'Preferred locale' => 'locale souhaitée', + 'Prevent mailing template modification or deletion, except for super-admin' => 'Prévenir la suppression ou la modification des templates de mail, excepté pour les super-administrateurs.', + 'Prevent variable modification or deletion, except for super-admin' => 'Prévenir la suppression ou la modification de variables, excepté pour les super-administrateurs.', + 'Price currency *' => 'Devise *', + 'Processing cancelation of payment for order ref. %ref' => 'Traitement de l\'annulation du paiement de la commande %ref, ID %id', + 'Processing confirmation of order ref. %ref, ID %id' => 'Traitement de la confirmation de la commande %ref, ID %id', + 'Prodcut ID *' => 'ID du produit *', + 'Product' => 'Produit', + 'Product ID' => 'ID produit', + 'Product ID *' => 'ID produit *', + 'Product attributes' => 'Attributs produit', + 'Product base price excluding taxes *' => 'Prix du produit Hors Taxe *', + 'Product base price with taxes' => 'Prix du produit TTC', + 'Product categories' => 'Catégories de produits', + 'Product clone' => 'Clonage du produit', + 'Product loop' => 'Boucle produit', + 'Product page' => 'Page produit', + 'Product price excluding taxes' => 'Prix du produit Hors Taxes', + 'Product price excluding taxes *' => 'prix HT', + 'Product price including taxes' => 'Prix du produit taxes incluses', + 'Product price offset for each currency' => 'Différence de prix pour chaque devise', + 'Product reference (must be unique)' => 'Référence produit (doit être unique)', + 'Product reference *' => 'Référence du produit *', + 'Product sale element ID *' => 'ID de la déclinaison du produit *', + 'Product template' => 'Gabarit du produit', + 'Product title' => 'Titre du produit', + 'ProductSaleElement modification' => 'Modification de la déclinaison du produit', + 'Products' => 'Produits', + 'Profile' => 'Profil', + 'Profile Code' => 'Profil', + 'Profile ID not found' => 'ID du profil non trouvé', + 'Profile `code` already exists' => 'Le `code` du profil existe déjà', + 'Profiles' => 'Profils', + 'Purpose' => 'Objet', + 'Purpose *' => 'Objet', + 'Quantity' => 'Quantité', + 'Range date End' => 'Date de fin', + 'Range date Start' => 'Date de début', + 'Rate' => 'Taux', + 'Rate from %currencyCode' => 'Taux pour %currencyCode', + 'Recipient e-mail address' => 'Adresse e-mail du destinataire', + 'Redirecting ...' => 'Redirection ...', + 'Redirecting to %url' => 'Redirection vers %url', + 'Reference' => 'Référence', + 'Reference *' => 'Référence *', + 'Register' => 'S\'inscrire', + 'Remember me ?' => 'Se souvenir de moi ?', + 'Remove X percent to total cart' => 'Remise sur total panier - pourcentage', + 'Replace by the default language' => 'Remplacer par la langue par défaut', + 'Replace current document by this file' => 'Remplacer le document courant par ce fichier', + 'Replace current image by this file' => 'Remplacer l\'image courante par ce fichier', + 'Reseller' => 'Revendeur', + 'Rewriten URL' => 'URL re-écrite', + 'Rotated Text File' => 'Rotation du fichier texte', + 'Sale announce label' => 'Accroche de cette promotion', + 'Sale price excluding taxes' => 'Prix promo HT', + 'Sale price including taxes' => 'Prix promo TTC', + 'Sale title' => 'Titre de la promotion', + 'Saving %obj% for %parentName% parent id %parentId%' => 'Enregistrement de %obj% pour %parentName% ID parent %parentId%', + 'Search' => 'Recherche', + 'Search page' => 'Page de recherche', + 'Select a default template for new products created in this category' => 'Choisissez le gabarit qui sera appliqué aux nouveaux produits de cette rubrique', + 'Select the brand logo' => 'Logo de la marque', + 'Select the brand logo amongst the brand images' => 'Choisissez le logo de la marque parmi les images associées à cette marque', + 'Select the categories of the products covered by this operation' => 'Choisissez les catégories de produit incluses dans cette promotion', + 'Select the countries to delete from this shipping zone' => 'Choisissez les pays à retirer de cette zone de livraison', + 'Select the countries to include in this shipping zone' => 'Choisissez les pays à inclure dans cette zone', + 'Select the discount type that will be applied to original product prices' => 'Choisissez le type de remise à appliquer aux prix des produits', + 'Select the parent category of this category.' => 'Choisissez la catégorie parente de cette catégorie', + 'Select the product attributes included in this operation' => 'Choisissez les déclinaisons incluses dans cette promotion', + '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 virtual document' => 'Sélectionnez le document virtuel', + 'Send test e-mail to:' => 'Envoyer un email de test à: ', + 'Service ID' => 'ID du service', + 'Shipping configuration' => 'Configuration du transport', + 'Shipping zone name' => 'Nom de la zone de livraison', + 'Short additional text' => 'Un court texte supplémentaire', + 'Short description text' => 'Un court texte de description', + 'Show redirections *' => 'Montrer les redirections *', + 'Sitemap' => 'Sitemap', + 'Some commands use this status.' => 'Il existe des commandes qui utilisent ce statut', + 'Something goes wrong, the message was not sent to recipient. Error is : %err' => 'Quelque chose n\'a pas fonctionné, le message n\'a pas pu être envoyé. L\'erreur est : %err', + 'Sorry, an error occured.' => 'Désolé, une erreur est survenue.', + 'Sorry, an error occured: %msg' => 'Désolé, une erreur est survenue : %msg', + 'Sorry, an error occured: %s' => 'Désolé, une erreur est survenue : %s', + 'Sorry, an error occurred: %err' => 'Désolé, une erreur est survenue: %err', + 'Sorry, no email defined for this administrator.' => 'Désolé, aucun e-mail défini pour cet administrateur.', + 'Sorry, you are not allowed to perform this action.' => 'Désolé, vous n\'êtes pas autorisé à réaliser cette action.', + 'Sorry, you\'re not allowed to perform this action' => 'Désolé, vous n\'êtes pas autorisé à réaliser cette action.', + 'Source IP' => 'IP source', + 'Start date' => 'Date de début ', + 'Start date and expiration date are inconsistent' => 'Les date de début et date d\'expiration sont incompatibles', + 'Start date of sales' => 'Date de début de la promotion', + 'State *' => 'État/région *', + 'State ID %id not found' => 'L\'ID pays \'%id\' est introuvable', + 'State title' => 'Nom de l\'état', + 'Stock' => 'Stock', + 'Store Business Identification Number (SIRET, etc).' => 'Identifiant de la boutique (SIRET, etc)', + 'Store Information' => 'Information boutique', + 'Store configuration failed.' => 'Erreur de configuration du magasin.', + 'Store description' => 'Description 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, 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', + 'Street Address' => 'Adresse', + 'Street Address ' => 'Rue', + 'Strictly use the requested language' => 'Utiliser strictement la langue demandée', + 'Subject' => 'Sujet', + 'Summary' => 'Résumé', + 'Symbol' => 'Symbole', + 'System' => 'Système', + 'System configuration' => 'Paramètres système', + 'System log configuration failed.' => 'Erreur du configurateur de log system.', + 'Tax' => 'Taxe', + 'Tax ID not found in tax list JSON' => 'ID de la taxe non trouvé dans le JSON de la liste des taxes', + 'Tax list is not valid JSON' => 'Le JSON de la liste des taxes n\'est pas valide', + 'Tax rule ID not found' => 'ID de la règle de taxe non trouvé', + 'Tax rule for this product *' => 'Règle de taxe pour ce produit *', + 'Taxes' => 'Taxes', + 'Taxes rules' => 'Règles de taxes', + 'Template' => 'Gabarit', + 'Template Name *' => 'Nom du gabarit *', + 'Templates' => 'Gabarits de produit', + 'Text File' => 'Fichier texte', + 'Text Message' => 'Message au format texte', + 'The %name module definition has not been initialized.' => 'La définition du module %name n\'a pas été initialisée.', + 'The %name module descriptor has not been initialized.' => 'La descripteur du module %name n\'a pas été initialisée.', + 'The %obj_name id \'%id\' doesn\'t exist' => '%obj_name avec l\'ID \'%id\' n\'existe pas', + 'The HTML TITLE element is the most important element on your web page.' => 'L\'élément HTML TITLE est le plus important dans votre page', + 'The archiver :name is not available. Please install the php extension :extension first.' => 'L\'archiveur :name n\'est pas disponible. Vous devez installer l\'extension PHP :extension.', + 'The archiver identifier "%archiverId" doesn\’t exist' => 'L\'identifiant d\'archiveur «%archiverId » n"existe pas', + 'The brand name or title' => 'Le nom ou le titre de la marque', + 'The cart item count should match the condition' => 'Le nombre d\'articles dans le panier doit vérifier la condition', + 'The category title' => 'Titre de cette catégorie', + 'The class "%class" doesn\'t exist' => 'La classe "%class" n\'existe pas', + 'The class "%class" must extend %baseClass' => 'La classe "%class" doit hériter de %baseClass', + 'The container should not be null in this form. Please use the FormFactory to get an instance.' => 'Le container ne doit pas être null dans ce formulaire. Veuillez utiliser le FormFactory pour récupérer l\'instance.', + 'The coupon applies if the cart contains at least one product of the selected categories' => 'Le code promo est valable si le panier contient/ne contient pas des produits appartenant aux catégories sélectionnées', + 'The coupon applies if the cart contains at least one product of the specified product list' => 'Le code promo est valable si le panier contient/ne contient pas au moins un des produits selectionnés', + 'The coupon applies to some customers only' => 'Ce code promo est valable pour les clients sélectionnés', + 'The coupon applies to the selected billing countries' => 'Ce code promo s\'applique pour les pays de facturation sélectionnés', + 'The coupon applies to the selected delivery countries' => 'Ce code promo s\'applique pour les pays de livraison sélectionnés', + 'The coupon code \'%code\' already exist. Please choose another coupon code' => 'Un code promo avec le code \'%code\' existe déjà. Merci de choisir un autre code', + 'The coupon code \'%code\' already exists. Please choose another coupon code' => 'Le code \'%code\' existe déjà. Merci de choisir un autre code pour cette promotion', + 'The coupon is valid after a given date' => 'Le code promo est valide à partir de cette date', + 'The date after which sales are de-activated. Please use %fmt format.' => 'Date après laquelle cette promotion sera désactivée', + 'The date from which sales are active. Please use %fmt format.' => 'Date à partir de laquelle cette promotion sera activé', + 'The detailed description.' => 'La description détaillée.', + 'The email address "%mail" was not found.' => 'L\'adresse email "%mail" n\'as pas été trouvée.', + 'The extension "%extension" is not allowed' => 'L\'extension "%extension" n\'est pas autorisée', + 'The file %path has been successfully downloaded' => 'Le fichier %path a été téléchargé', + 'The following columns are missing: %columns' => 'Il manque les colonnes suivantes: %columns', + 'The image which replaces an undefined country flag (%file) was not found. Please check unknown-flag-path configuration variable, and check that the image exists.' => 'L\'image qui remplace un drapeau de pays manquant (%file) n\'a pas été trouvée. Merci de vérifier la variable de configuration unknown-flag-path.', + 'The language "%id" doesn\'t exist' => 'L\'id de langue "%id" n\'existe pas', + 'The lost admin password recovery feature is disabled.' => 'La fonction de récupération de mot de passe perdu administrateur est désactivée.', + 'The mailing template in HTML format.' => 'Le template du mail au format HTML', + 'The mailing template in text-only format.' => 'Le template du mail au format texte', + 'The message has been successfully sent to %recipient.' => 'Le message a bien été envoyé à %recipient. ', + '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 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é 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 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 is not valid : %message' => 'Le module n\'est pas valide : %message', + 'The module zip file' => 'Le fichier Zip du module', + 'The order status code' => 'Le code du statut de commande', + 'The order status name or title' => 'Le libellé ou le nom du statut de commande', + 'The parent template "%parent" of template "%name" could not be found' => 'Le template parent "%parent" du template "%name" n\'a pas été trouvé', + 'The product document id %id doesn\'t exists' => 'Le document %id du produit n\'existe pas', + 'The product image id %id doesn\'t exists' => 'L\'image %id du produit n\'existe pas', + 'The product sale element id %id doesn\'t exist' => 'L\'id de déclinaison de produit %id n\'existe pas', + 'The product sale elements id %id doesn\'t exist' => 'La déclinaison avec l\'id %id n\'existe pas', + 'The product sale elements id %id doesn\'t exists' => 'La déclinaison avec l\'id %id n\'existe pas', + 'The rate from %currencyCode: Price in %currencyCode x rate = Price in this currency' => 'Le taux de converstion par rapport à %currencyCode : Prix en %currencyCode * taux = Prix dans la devise', + 'The resource %res has not been found' => 'La ressource %res n\'a pas été trouvé', + 'The sale announce label, such as Sales ! or Flash Sales !' => 'L\'accroche de cette promotion, comme "Socles d\'été !" ou "Ventes Flash !"', + 'The sale name or descriptive title' => 'Nom de la promotion, ou titre descriptif', + 'The sale name or title' => 'Nom ou titre de cette promotion', + 'The serializer identifier "%serializerId" doesn\’t exist' => 'L\'identifiant du serializer "%serializerId" n\'existe pas', + 'The service id that will handle the hook (defined in the config.xml file of the module).' => 'L\'ID du service qui va traiter le point d\'accroche (défini dans le fichier config.xml du module)', + 'The store fax number.' => 'Numéro de fax', + 'The store phone number.' => 'Téléphone de la boutique', + 'The symbol, such as $, £, €...' => 'Le symbole, tel que $, £, €, ...', + 'The template "%name" requires Thelia %version or newer' => 'Le template "%name" requiert Thelia %version au minimum', + 'The type %type is not valid' => 'Le type %type n\'est pas valide', + 'The zip code format' => 'Le format de code postal', + 'There are no files to associate.' => 'Il n\'y a aucun fichier à associer.', + 'There is no id "%id" in the export categories' => 'L\'id de catégorie d\'export "%id" n\'existe pas', + 'There is no id "%id" in the exports' => 'L\'id d\'export "%id" n\'existe pas', + 'There is no id "%id" in the import categories' => 'L\'id de catégorie d\'import "%id" n\'existe pas', + 'There is no id "%id" in the imports' => 'L\'id d\'import "%id" n\'existe pas', + 'There is no id "%ref" in the imports' => 'L\'import "%ref" n\'existe pas', + 'There is no ref "%ref" in the exports' => 'L\'export "%ref" n\'existe pas', + 'There\'s a conflict between your file extension "%ext" and the mime type "%mime"' => 'Il y a un conflit entre l\'extension "%ext" et le type MIME "%mime" ', + 'This PHP extension should be installed and loaded.' => 'Cette extension PHP doit être installée et chargée.', + 'This administrator login already exists' => 'Ce login administrateur existe déjà', + 'This brand is online' => 'Cette marque est en ligne', + 'This category is online' => 'Cette catégorie est en ligne', + 'This code is already used.' => 'Ce code est déjà utilisé par un autre statut.', + 'This condition is always true' => 'Cette condition est troujours vérifiée', + 'This content is online.' => 'Ce contenu est en ligne.', + 'This country has states / provinces' => 'Ce pays possède des états / provinces', + 'This country is online' => 'Ce pays est en ligne', + 'This coupon adds a free product to the cart if one of the selected products is in the cart.' => 'Ce coupon ajoute un produit gratuit (sous forme de remise) au panier, si un des produits indiqués est présent dans le panier.', + 'This coupon does not exists' => 'Ce code promo n\'existe pas', + 'This coupon subtracts from the order total a percentage of the price of each product which belongs to the selected categories. If the discount is greater than the total order, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.' => 'Ce code promo retire du total de la commande le pourcentage indiqué du prix de chacun des produits appartenant aux catégories sélectionnées. Si la remise est supérieure au total de la commande, seul le port sera dû, à moins que le code promo n\'offre aussi le port.', + 'This coupon subtracts from the order total the specified percentage of each product price which uses the selected attribute values. If the discount is greater than the total order, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.' => 'Ce code promo retire du total de la commande le pourcentage indiqué du prix de chacun des produits ayant au moins une des valeurs de déclinaisons indiquées. Si la remise est supérieure au total de la commande, seul le port sera dû, à moins que le code promo n\'offre aussi le port.', + 'This coupon subtracts from the order total the specified percentage of each selected product price. If the discount is greater than the total order, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.' => 'Ce code promo retire du total de la commande le pourcentage indiqué du prix de chacun des produits sélectionnés. Si la remise est supérieure au total de la commande, seul le port sera dû, à moins que le code promo n\'offre aussi le port.', + 'This coupon subtracts the specified amount from the order total for each product which belongs to the selected categories. If the discount is greater than the total order, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.' => 'Ce code promo retire le montant indiqué du total de la commande pour chacun des produits appartenant aux catégories sélectionnées. Si la remise est supérieure au total de la commande, seul le port sera dû, à moins que le code promo n\'offre aussi le port.', + 'This coupon subtracts the specified amount from the order total for each product which uses the selected attribute values. If the discount is greater than the total order, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.' => 'Ce code promo retire le montant indiqué du total de la commande pour chacun des produits ayant au moins une des valeurs de déclinaisons indiquées. Si la remise est supérieure au total de la commande, seul le port sera dû, à moins que le code promo n\'offre aussi le port.', + 'This coupon subtracts the specified amount from the order total for each selected product. If the discount is greater than the total order, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.' => 'Ce code promo retire le montant indiqué du total de la commande pour chacun des produits sélectionnés. Si la remise est supérieure au total de la commande, seul le port sera dû, à moins que le code promo n\'offre aussi le port.', + 'This coupon will offert a flat percentage off a shopper\'s entire order (not applied to shipping costs or tax rates). If the discount is greater than the total order corst, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.' => 'Ce code promo retire le pourcentage indiqué du total de la commande, hors frais de port et taxes. Si la remise est supérieur au total de la commande, seul le port sera facturé, à moins que le code promo n\'offre aussi les frais port.', + 'This coupon will subtracts a set amount from the total cost of an order. If the discount is greater than the total order corst, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.' => 'Ce code promo retire le montant indiqué du total de la commande, hors frais de port et taxes. Si la remise est supérieur au total de la commande, seul le port sera facturé, à moins que le code promo n\'offre aussi les frais port.', + 'This document is online' => 'Le document est en ligne', + 'This email already exists.' => 'Cette adresse e-mail existe déjà', + 'This email does not exists' => 'Cette adresse e-mail n\'existe pas', + 'This folder is online.' => 'Ce dossier est en ligne.', + 'This hook is specific to a module (delivery/payment modules).' => 'Ce point d\'accroche est spécifique à un module (généralement pour les modules de livraison et paiements).', + 'This image is online' => 'L\'image est en ligne', + 'This is a comma separated list of email addresses where store notifications (such as order placed) are sent.' => 'Indiquez la liste des adresses e-mails, séparées par des virgules, auxquelles seront envoyées les notification de la boutique, comme les nouvelles commandes.', + 'This is an identifier that will be used in the code to get this message' => 'Il s\'agit d\'un identifiant qui sera utilisé pour récupérer le message.', + 'This is not a hexadecimal color.' => 'Ce n\'est pas une couleur hexadecimale valide.', + 'This is not a valid code.' => 'Ce code n\'est pas valide.', + 'This is the contact email address, and the sender email of all e-mails sent by your store.' => 'Il s\'agit de l\'adresse de contact, et de l\'adresse de l\'expéditeur des mails envoyés par la boutique', + 'This is the message purpose, such as \'Order confirmation\'.' => 'Titre du message (ex : confirmation de commande)', + 'This is the name used on the login screen' => 'C\'est le nom utilisé sur l\'écran de connexion', + 'This is the subject of the e-mail, such as \'Your order is confirmed\'.' => 'Sujet du message (ex : votre commande est validée)', + 'This module has no Markdown documentation.' => 'Ce module n\'a pas de documentation Markdown', + 'This product does not have a physical presence' => 'Ce produit n\'a pas de présence physique', + 'This product is on sale' => 'Ce produit est en promo', + 'This product is online' => 'Ce produit est en ligne', + 'This product reference is already assigned to another product.' => 'Cette référence est déjà assignée à un produit.', + 'This product_sale_elements_id does not exists for this product : %d' => 'Le product_sale_elements_id n\'existe pas pour ce produit : %d', + 'This state doesn\'t belong to this country.' => 'Cet état n\'appartient pas à ce pays.', + 'This state is online' => 'Cet état est en ligne', + 'This status is protected.' => 'Ce statut de commande est protégé', + 'This template is in use in some of your products, and cannot be deleted. Delete it from all your products and try again.' => 'Ce gabarit est utilisé par des produits, et ne peut être supprimé. Retirez-le de tous vos produits, et ré-essayez.', + 'This the unique name of this message. Do not change this value unless you understand what you do.' => 'Ceci est le nom unique du message. Ne le modifiez que si vous savez ce que vous faîtes', + 'This value should not be blank.' => 'Cette valeur ne doit pas être vide.', + 'This zip code should respect the following format : %format.' => 'Ce code postal doit respecter le format suivant : %format.', + 'Timeout' => 'Délai d\'attente expiré', + 'Title' => 'Titre', + 'Title *' => 'Titre *', + 'Title ID not found' => 'ID de la civilité non trouvé', + 'To activate module %name, the following modules should be activated first: %modules' => 'Pour activer le module %name, les modules suivants doivent être tout d\'abord activés: %modules', + 'Tools' => 'Outils', + 'Translations' => 'Traductions', + 'Tried to download a file, but the URL was not valid: %url' => 'Le fichier n\'a pas été téléchargé, l\'url n\'est pas valide: %url', + 'Type' => 'Type', + 'URL_ALREADY_EXISTS' => 'Cette URL existe déjà', + 'Unable to get module code from the fullnamespace element of the module descriptor: \'%val\'' => 'Impossible de récupérer le code du module depuis le namespace complet du descripteur du module : \'%val\'', + 'Unable to process your request. Please try again (%err).' => 'Echec lors du traitement de votre requête. Merci de ré-essayer (%err).', + 'Unconditional usage' => 'Utilisable sans conditions', + 'Unconditionnal usage' => 'Utilisable sans conditions', + 'Undefined loop argument "%name"' => 'Argument de boucle invalide: "%name" ', + 'Undefined search mode \'%mode\'' => 'Mode de recherche \'%mode\' invalide', + 'Unknown order ID: %id' => 'La commande ID %id est inconnue.', + 'Unsupported magic method %name. only getArgname() is supported.' => 'La méthode magique %name n\'est pas supportée. Seule get() est supporté..', + 'Unsupported type' => 'Type non supporté', + 'Update customer account' => 'Modification compte client', + 'Use a N for a number, L for Letter, C for an iso code for the state.' => 'Utilisez un N pour un nombre, L pour une lettre, C pour un code iso de l\'état.', + 'Use the keyword phrase in your URL.' => 'Utilisez des mots clés dans votre URL', + 'Used in your store front' => 'Affiché sur votre boutique', + 'Username' => 'Nom d\'utilisateur', + 'Username or e-mail address *' => 'Nom d\'utilisateur ou adresse e-mail *', + 'Valid only from %date% to the coupon expiration date' => 'Valide uniquement à partir de %date% à la date d\'expiration de coupon', + 'Value' => 'Valeur', + 'Value %val for Discount Amount is invalid. Please enter a positive value.' => 'La valeur %val pour le montant de la remise est invalide. Merci d\'indiquer une valeur positive.', + 'Value %val for Percent Discount is invalid. Please enter a positive value between 1 and 100.' => 'La valeur %val pour le pourcentage de remise est invalide. Merci d\'indiquer un nombre entre 1 et 100', + 'Value *' => 'Valeur *', + 'Value create form' => 'Formulaire de création de valeur', + 'Variable' => 'Variable', + 'Variables' => 'Variables', + 'Virtual document' => 'Produit virtuel', + 'Warnings' => 'Avertissements', + 'We\'re sorry, this PDF invoice is not available at the moment.' => 'Nous sommes désolé, cette facture n\'est pas disponible pour le moment', + 'Weight' => 'Poids', + 'When using the %method% method you can automatically render or dump templates or add CSS and JS files (e.g.: render:mytemplate.html;js:assets/js/myjs.js)' => 'Lorsque vous utilisez la méthode %method%, vous pouvez automatiquement faire le rendu d\'un template ou injecter le contenu d\'un fichier ou ajouter des fichiers CSS et JS (par exemple : render:mytemplate.html;js:assets/js/myjs.js)', + 'Wrong country definition' => 'La définition du pays est incorrecte', + 'Wrong form method, %s expected.' => 'Méthode HTTP invalide : %s attendu.', + 'Yes, I have a password :' => 'Oui, j\'ai un mot de passe :', + 'You are already registered!' => 'Vous êtes déjà enregistré !', + 'You can not delete it.' => 'Il n\'est pas possible de le supprimer', + 'You don\'t need to use commas or other punctuations.' => 'Vous n\'avez pas besoin d\'utiliser de virgules ou d\'autres signes de ponctuation', + 'You have to configure your store email first !' => 'Vous devez d\'abord configurer l\'e-mail de votre boutique !', + 'You must select at least one attribute.' => 'Vous devez choisir au moins une déclinaison.', + 'You should select a state for this country.' => 'Vous devez sélectionner un État pour ce pays.', + 'You\'re not currently connected to the administration panel. Please log in to access this page' => 'Vous n\'êtes pas connecté à l\'administration de la boutique. Merci de vous identifier pour accéder à cette page.', + 'You\'ve submitted this form too many times. ' => 'Vous avez envoyé ce formulaire de trop nombreuses fois.', + 'Your Email Address' => 'Votre adresse mail', + 'Your Message' => 'Votre message', + 'Your configuration seems to be ok. Checked out your mailbox : %email%' => 'Votre configuration semble correct. Vérifiez vos e-mails : %email%', + 'Your current password does not match.' => 'Votre mot de passe actuel ne correspond pas', + 'Your zip must contain 1 root directory which is the root folder directory of your module' => 'Le fichier Zip doit contenir un seul dossier racine qui est la racine de votre module', + 'Zip code' => 'Code postal', + 'Zone' => 'Zone', + 'accessories table header' => 'colonne tableau accessoires', + 'accessories table row' => 'ligne tableau accessoires', + 'add to all form' => 'formulaire ajouter à tous', + 'additional information' => 'informations additionnelles', + 'address create form' => 'formulaire de création d\'adresse', + 'address delete form' => 'formulaire de suppression adresse', + 'address update form' => 'formulaire de modification adresse', + 'after addresse area' => 'après la zone d\'adresses', + 'after combinations' => 'après les déclinaisons', + 'after footer' => 'après le pied', + 'after javascript include' => 'après l\'inclusion des javascript', + 'after javascript initialisation' => 'après l\'initialisation du javascript', + 'after product listing' => 'après la liste des produits', + 'after the information area' => 'après la zone d\'informations', + 'after the main content area' => 'en dessous de la zone de contenu principale', + 'after the opening of the body tag' => 'après l\'ouverture de la balise body', + 'after the opening of the head tag' => 'après l\'ouverture de la balise head', + 'after the order summary' => 'après le résumé de la commande', + 'after top bar' => 'après la barre de titre', + 'after top menu' => 'après le menu haut', + 'api id %id does not exists' => 'L\'id API %id n\'existe pas', + 'at the bottom' => 'en bas', + 'at the bottom of column 1' => 'en bas de la colonne 1', + 'at the bottom of information area' => 'en bas de la zone d\'informations', + 'at the bottom of the catalog' => 'en bas du catalogue', + 'at the bottom of the detail area' => 'en dessous de la zone de détail', + 'at the bottom of the footer' => 'en bas du pied de page', + 'at the bottom of the form' => 'en bas du formulaire', + 'at the bottom of the header' => 'en bas du header', + 'at the bottom of the main area' => 'en bas de la zone principal', + 'at the bottom of the shipping area' => 'en bas de la zone livraison', + 'at the bottom of the sidebar' => 'en bas de la sidebar', + 'at the bottom of the system area' => 'en bas de la zone système', + 'at the bottom of the top bar' => 'en bas de la barre supérieure', + 'at the top' => 'en haut', + 'at the top of the catalog area' => 'en haut de la zone catalogue', + 'at the top of the column' => 'en haut de la colonne', + 'at the top of the configuration' => 'en haut de la configuration ', + 'at the top of the detail' => 'en haut de la zone détail', + 'at the top of the footer' => 'en haut du pied de page', + 'at the top of the form' => 'en haut du formulaire', + 'at the top of the header' => 'en haut du header', + 'at the top of the main area' => 'en haut de la zone principal', + 'at the top of the shipping area' => 'en haut de la zone livraison', + 'at the top of the sidebar' => 'en haut de la sidebar', + 'at the top of the system area' => 'en haut de la zone système', + 'at the top of the top bar' => 'en haut de la barre supérieure', + 'attributes table header' => 'colonne tableau attributs', + 'attributes table row' => 'ligne tableau attributs', + 'before combinations' => 'avant les déclinaisons', + 'before footer' => 'avant le pied', + 'before the end body tag' => 'avant la fin de la balise body', + 'before the end of the head tag' => 'avant la fin de la balise head', + 'before the main content area' => 'au dessus de la zone de contenu principale', + 'before top menu' => 'avant le menu haut', + 'before topbar' => 'avant la barre de titre', + 'block' => 'bloc', + 'bottom' => 'bas', + 'bottom of the footer' => 'en bas du pied de page', + 'cURL errno %errno, http code %http_code on link "%path": %error' => 'cURL errno %errno, http code %http_code pour le lien "%path": %error', + 'caption' => 'légende', + 'categories table header' => 'colonne tableau catégories', + 'categories table row' => 'ligne tableau catégories', + 'combination delete form' => 'formulaire de suppression de combinaison', + 'combinations list caption' => 'légende de la liste des déclinaisons', + 'configuration' => 'configuration', + 'configuration JavaScript' => 'JavaScript configuration', + 'configuration bottom' => 'en dessous de la configuration', + 'content' => 'contenu', + 'content area' => 'zone de contenu', + 'content delete form' => 'formulaire de suppression contenu', + 'content edit JavaScript' => 'JavaScript modification contenu', + 'contents table header' => 'colonne tableau contenus', + 'contents table row' => 'ligne tableau contenus', + 'context' => 'contexte', + 'country delete form' => 'formulaire de suppression de pays', + 'create JavaScript' => 'JavaScript création', + 'create form' => 'formulaire de création', + 'customer account' => 'Compte client', + 'date format' => 'format de date', + 'date/time format' => 'format date/heure', + 'decimal separator' => 'séparateur décimal', + 'delete form' => 'formulaire de suppression', + 'delivery address' => 'adresse de livraison', + 'delivery module %s is not a Thelia\Module\DeliveryModuleInterface' => 'Le module de livraison %s n\'est pas du type Thelia\Module\DeliveryModuleInterface', + 'details pricing form' => 'Formulaire détails des prix', + 'details promotion form' => 'Formulaire détail promotion', + 'email' => 'e-mail', + 'email confirmation is not the same as email field' => 'Les adresses e-mail indiquées sont différentes.', + 'email system JavaScript' => 'JavaScript système de e-mails', + 'extra area' => 'zone supplémentaire', + 'extra payment zone' => 'zone de paiement supplémentaire', + 'features table row' => 'ligne tableau caractéristiques', + 'features-table-header' => 'colonne tableau caractéristiques', + 'folders table header' => 'colonne tableau dossiers', + 'folders table row' => 'ligne tableau dossiers', + 'footer body' => 'corps du pied de page', + 'header' => 'en-tête', + 'hook delete form' => 'Formulaire de suppression de point d\'accroche', + 'hook edit JavaScript' => 'JavaScript modification de point d\'accroche', + 'hour(s)' => 'heure(s)', + 'id delete form' => 'formulaire de suppression ID', + 'if successful response' => 'en cas de succès', + 'imprint' => 'mentions légales', + 'in footer' => 'dans le pied', + 'in the header' => 'dans l\'en-tête', + 'in the menu catalog' => 'dans le menu catalogue', + 'in the menu configuration' => 'dans le menu configuration', + 'in the menu customers' => 'dans le menu clients', + 'in the menu folders' => 'dans le menu dossiers', + 'in the menu modules' => 'dans le menu modules', + 'in the menu orders' => 'dans le menu commandes', + 'in the menu tools' => 'dans le menu outils', + 'in top menu items' => 'éléments du menu haut', + 'inside top bar' => 'dans la barre de titre', + 'javascript' => 'javascript', + 'javascript initialization' => 'initialisation du javascript', + 'label' => 'libellé', + 'language locale' => 'locale de la langue', + 'language selection page' => 'Page du choix du langage', + 'list JavaScript' => 'JavaScript des listes', + 'list caption' => 'légende de la liste', + 'list header' => 'en-tête de la liste', + 'list row' => 'ligne tableau', + 'logs JavaScript' => 'JavaScript logs', + 'mailing system modification' => 'Modification du système d\'envoi de mail.', + 'main area' => 'zone principale', + 'middle' => 'au milieu', + 'minute(s)' => 'minute(s)', + 'password confirmation is not the same as password field' => 'le mot de passe de confirmation n\'est pas le même que le champ mot de passe', + 'password must be composed of at least 4 characters' => 'le mot de passe doit être composé d\'au moins 4 caractères', + 'payment module %s is not a Thelia\Module\PaymentModuleInterface' => 'Le module de paiement %s n\'est pas une instance de Thelia\Module\PaymentModuleInterface ', + 'pdf' => 'pdf', + 'permanent discount (in percent)' => 'Remise permanente (en pourcentage)', + 'photo gallery' => 'gallerie photos', + 'plain, login, cram-md5 or empty' => 'plain, login, cram-md5 ou vide', + 'primary navigation' => 'navigation principale', + 'product list' => 'liste produit', + 'quantity value is not valid' => 'la valeur de la quantité n\'est pas valide', + 'received value `%value` does not match `%type` type' => 'la valeur reçue `%value` ne correspond pas à `%type`', + 'remove to all form' => 'formulaire de suppression multiple', + 'row' => 'ligne', + 'rule create form' => 'Formulaire de création de règles', + 'rule delete form' => 'Formulaire de suppression de règle', + 'rule edit JavaScript' => 'JavaScript modification règle', + 'secondary navigation' => 'Navigation secondaire', + 'ssl, tls or empty' => 'ssl, tls ou vide', + 'stock edit form' => 'Formulaire de modification du stock', + 'table header' => 'Colonne de tableau', + 'table row' => 'Ligne de tableau', + 'tax rule' => 'Règle de taxe', + 'the body of the sidebar' => 'le corps de la sidebar', + 'this product id does not exists : %d' => 'Cet id produit n\'existe pas : %d', + 'thousands separator' => 'séparateur de milliers', + 'time format' => 'format d\'heure', + 'type' => 'type', + 'update JavaScript' => 'Mettre à jour le JavaScript', + 'update form' => 'Formulaire de modification', + 'value table header' => 'colonne tableau valeur', + 'value table row' => 'ligne tableau valeurs', +); diff --git a/core/lib/Thelia/Config/I18n/he_IL.php b/core/lib/Thelia/Config/I18n/he_IL.php new file mode 100644 index 00000000..ade0991c --- /dev/null +++ b/core/lib/Thelia/Config/I18n/he_IL.php @@ -0,0 +1,51 @@ + ' יצירת תוכן הטופס', + ' note: only non-visible documents can be associated.' => ' הערה: רק מסמכים שאינו גלוי יכול להיות משויך.', + '"%param" parameter cannot be empty in loop type: %type, name: %name' => 'הפרמטר "%param" אינו יכול להיות ריק בסוג לולאה: סוג %, שם: %name', + '"%param" parameter is missing in loop type: %type, name: %name' => 'חסר פרמטר "%param" בסוג לולאה: סוג %, שם: %name', + '%module (version: %version)' => 'מודול % (גירסה: הגירסה %)', + '%obj SEO modification' => 'השינוי SEO %obj', + '%obj creation' => 'יצירת %obj', + '%obj modification' => 'שינוי %obj', + '%obj%s deleted successfully' => '%obj%s נמחק בהצלחה', + '%s has dependency to module %s. You have to deactivate this module before.' => '%s יש תלות כדי %s מודול. אתה צריך לבטל את מודול זה לפני.', + '%s have dependencies to module %s. You have to deactivate these modules before.' => '%s יש תלות מודול %s. אתה צריך לבטל מודולים אלה לפני.', + '%type% position updated' => 'מיקום %type% מעודכן', + '%type% visibility updated' => '%type% ניראות מעודכן', + 'A comma separated list of email addresses' => 'רשימת כתובות דוא ל מופרדים באמצעות פסיקים', + 'A currency with code "%name" already exists.' => 'מטבע עם קוד "%name" כבר קיים.', + 'A descriptive title' => 'כותרת תיאורית', + 'A message with name "%name" already exists.' => 'הודעה עם השם "%name" כבר קיים.', + 'A name such as Europe or Overseas' => 'שם כמו אירופה או בחו', + 'A product with reference %ref already exists. Please choose another reference.' => 'מוצר עם הפניה % ref כבר קיים. אנא בחר אחר הפניה אחרת.', + 'A short description, used when a summary or an introduction is required' => 'תיאור קצר, המשמש בעת סיכום או מבוא נדרש', + 'A short text, used when an additional or supplemental information is required.' => 'טקסט קצר, כאשר נדרש מידע נוסף או משלימה.', + 'A user already exists with this email address. Please login or if you\'ve forgotten your password, go to Reset Your Password.' => 'משתמש קיים כבר עם כתובת הדוא. אנא התחבר או אם תשכח את הסיסמה שלך, ללכת איפוס הסיסמה שלך.', + 'A value for attribute "%name" is already present in the combination' => 'ערך עבור התכונה "%name" מופיע כבר את הצופן', + 'A variable with name "%name" already exists.' => 'משתנה עם השם "%name" כבר קיים.', + 'Activate logs only for these IP Addresses' => 'הפעלת יומני רק עבור כתובות IP אלה', + 'Activate logs only for these files' => 'הפעלת יומני רק עבור קבצים אלה', + 'Activate this sale' => 'להפעיל את המכירה הזאת', + 'Active' => 'פעיל', + 'Additional address information' => 'פרטי כתובת נוספת', + 'Address ID not found' => 'מזהה כתובת לא נמצא', + 'Address Line 2' => 'שורת כתובת 2', + 'Address Line 3' => 'שורת כתובת 3', + 'Address creation' => 'יצירת כתובת', + 'Address label' => 'תוויות כתובת', + 'Address.' => 'כתובת.', + 'Administrator' => 'מנהל מערכת', + 'Administrator ID not found' => 'מזהה מנהל לא נמצא', + 'Advertise this product as new' => 'לפרסם את המוצר הזה כמו חדש', + 'Alerts' => 'התראות', + 'All Products' => 'כל המוצרים', + 'All countries' => 'כל המדינות', + 'All shipping methods' => 'כל שיטות משלוח', + 'Apply exchange rates on price in %sym' => 'למרוח את שערי החליפין המחיר %sym', + 'Archive Format' => 'תבנית ארכיון', + 'Associate documents' => 'לשייך מסמכים', + 'Associate images' => 'לקשר תמונות', + 'At least one of cart products categories is %op% %categories_list%' => 'לפחות אחת מקטגוריות המוצרים העגלה היא %op% %categories_list%', +]; diff --git a/core/lib/Thelia/Config/I18n/hu_HU.php b/core/lib/Thelia/Config/I18n/hu_HU.php new file mode 100644 index 00000000..fc755bbe --- /dev/null +++ b/core/lib/Thelia/Config/I18n/hu_HU.php @@ -0,0 +1,314 @@ + ' tartalom-létrehozó űrlap', + ' note: only non-visible documents can be associated.' => ' Megjegyzés: csak a nem látható dokumentumok társíthatók.', + '%module (version: %version)' => '%module (verzió: %version)', + '%obj SEO modification' => '%obj SEO módosítása', + '%obj creation' => '%obj létrehozása', + '%obj modification' => '%obj módosítása', + '%obj%s deleted successfully' => '%obj%s sikeresen törölve', + 'A comma separated list of email addresses' => 'E-mail címek egy vesszővel elválasztott listája', + 'A currency with code "%name" already exists.' => '"%name" kódú pénznem már létezik.', + 'A name such as Europe or Overseas' => 'név pl. Európai, Tengeren túli stb.', + 'A user already exists with this email address. Please login or if you\'ve forgotten your password, go to Reset Your Password.' => 'Egy felhasználó már létezik ezzel az e-mail címmel. Kérjük, jelentkezzen be, vagy ha elfelejtette a jelszavát, használja a jelszó-emlékeztetőt.', + 'Activate logs only for these IP Addresses' => 'Naplók aktiválása csak ezekhez az IP címekhez', + 'Activate logs only for these files' => 'Naplók aktiválása csak ezekhez a fájlokhoz', + 'Activate this sale' => 'A kampán indítása', + 'Active' => 'Aktív', + 'Add to all product templates' => 'Hozzáadás minden terméksablonhoz', + 'Additional address' => 'Kiegészítő információk', + 'Additional address information' => 'további kiegészítő információk', + 'Address creation' => 'Cím létrehozása', + 'Address label' => 'Címadat azonosítója', + 'Address update' => 'Cím frissítése', + 'Address.' => 'címadat', + 'Administrator' => 'Adminisztrátor', + 'Administrators' => 'Adminisztrátorok', + 'Alerts' => 'Figyelmeztetések', + 'All Products' => 'Minden termék', + 'All countries' => 'Minden ország', + 'All shipping methods' => 'Minden szállítási mód', + 'Amount' => 'Összeg', + 'Associate documents' => 'Dokumentumok társítása', + 'Associate images' => 'Képek társítása', + 'At least one of cart products categories is %op% %categories_list%' => 'Legalább egy termék a kosárban %op% a következő kategóriákban: %categories_list%', + 'Attributes' => 'Tulajdonságok', + 'Back Office' => 'Adminisztrációs felület', + 'Billing country' => 'Számlázási cím(ország)', + 'Billing country is' => 'Számlázási cím(ország)', + 'Brand' => 'Márka', + 'Brand / Supplier' => 'Márka / Beszállító', + 'Brand name' => 'Márka neve', + 'Brands' => 'Márkák', + 'Business ID' => 'Üzleti Azonosító', + 'CSS' => 'CSS', + 'CSS stylesheet' => 'CSS stíluslap', + 'Cannot find a default country. Please define one.' => 'Nem található alapértelmezett ország. Kérjük, hozzon létre egyet!', + 'Cannot find the shop country. Please select a shop country.' => 'Nem találja a bolthoz tartozó ország. Kérjük, válasszon ki egy országot!', + 'Cart' => 'Kosár', + 'Cart contains at least a product %op% %products_list%' => 'A kosárban lévő termékek legalább egyike %op% a következő listában: %products_list%', + 'Cart contains categories condition' => 'A kosár tartalmaz terméket a megadott kategóriából', + 'Cart contains specific products' => 'A kosár tartalmazza a meghatározott termékeket', + 'Cart item count' => 'Kosárban lévő termékek száma', + 'Cart item count is' => 'Kosárban lévő termékek száma', + 'Cart total amount' => 'Kosár összértéke', + 'Cart total amount is' => 'Kosár összértéke', + 'Catalog' => 'Katalógus', + 'Categories' => 'Kategóriák', + 'Category' => 'Kategória', + 'Category page' => 'Kategória oldal', + 'Category title' => 'Kategória nevek', + 'Cellphone' => 'Mobil telefonszám', + 'Check country iso codes here.' => 'Ellenőrizze az országkódokat a Wikipedia-n.', + 'Check the total Cart amount in the given currency' => 'Ellenőrzi a kosár összértékét a megadott pénznemben', + 'City' => 'Város', + 'Code' => 'Kód', + 'Combination builder' => 'Termék-variáció készítő', + 'Company' => 'Cég', + 'Company Name' => 'Cégnév', + 'Configuration' => 'Beállítások', + 'Confirm Email Address' => 'Ismételje meg az email címet', + 'Confirm Email address' => 'Ismételje meg az email címet', + 'Constant amount' => 'Meghatározott érték', + 'Constant amount found in one of the product\'s feature' => 'Meghatározott érték egy konkrét termékjellemzőhöz kötve', + 'Contact page' => 'Kapcsolat oldal', + 'Content' => 'Tartalom', + 'Content page' => 'Tartalmi oldal', + 'Content title *' => 'Tartalom neve *', + 'Contents' => 'Tartalmak', + 'Countries' => 'Országok', + 'Country' => 'Ország', + 'Country ID not found' => 'Ország ID nem található', + 'Country title' => 'Ország név', + 'Coupon' => 'Kupon', + 'Coupon %code is expired.' => 'A "%code" kódú kupon lejárt.', + 'Coupon code %code is disabled.' => 'A "%code" kódú kupon nem érvényes.', + 'Currencies' => 'Pénznemek', + 'Currency' => 'Pénznem', + 'Currency name' => 'Pénznem név', + 'Current Password' => 'Jelenlegi jelszó', + 'Customer' => 'Ügyfél', + 'Customer is %op% %customer_list%' => 'Az ügyfél %op% a következő listában: %customer_list%', + 'Customers' => 'Ügyfelek', + 'Dashboard' => 'Vezérlőpult', + 'Decimal places' => 'Tizedesjegyek száma', + 'Default folder *' => 'Alapértelmezett csoport *', + 'Default product category *' => 'Alapértelmezett termékkategória *', + 'Default product template' => 'Alapértelmezett termék sablon', + 'Delivery' => 'Szállítás', + 'Delivery choice' => 'Szállítási mód', + 'Delivery country' => 'Szállítási cím(ország)', + 'Delivery country is' => 'A szállítási cím(ország)', + 'Delivery zone' => 'Szállítási zóna', + 'Detailed description' => 'Részetes leírás', + 'Discount type' => 'Kedvezmény típus', + 'Display initial product prices on front-office' => 'Az eredeti ár megjelenítése a boltban', + 'Don\'t repeat keywords over and over in a row. Rather, put in keyword phrases.' => 'Figyeljen arra, hogy a kulcsszavak ne ismétlődjenek. Különböző kifejezéseket keressen.', + 'EAN Code' => 'EAN kód', + 'Edit' => 'Szerkesztés', + 'Email Address' => 'Email cím', + 'Email address' => 'Email cím', + 'Email addresses of notification recipients' => 'Értesítések címzettjei', + 'End date of sales' => 'A kampány lejáratának ideje', + 'Enter here the brand name in the default language (%title%)' => 'Itt adhatja meg a márka nevét az alapértelmezett nyelven (%title%)', + 'Enter here the category title in the default language (%title%)' => 'Itt adhatja meg a kategória nevét az alapértelmezett nyelven (%title%)', + 'Enter here the mail template purpose in the default language (%title%)' => 'Itt adhatja meg a levélsablon nevét az alapértelmezett nyelven (%title%)', + 'Enter here the sale name in the default language (%title%)' => 'Adja meg a kampány nevét az alapértelmezett nyelven (%title%)', + 'Equal to' => 'Egyenlő', + 'Feature' => 'Termékjellemző', + 'Features' => 'Jellemzők', + 'First Name' => 'Keresztnév', + 'Firstname' => 'Keresztnév', + 'Fixed Amount Discount' => 'Fix áras kedvezmény', + 'Fixed amount discount for selected attribute values' => 'Fix áras kedvezmény a kijelölt tulajdonságú termékekre', + 'Fixed amount discount for selected categories' => 'Fix áras kedvezmény a kiválasztott kategóriákra', + 'Fixed amount discount for selected products' => 'Fix áras kedvezmény a kiválasztott termékekre', + 'Folder title *' => 'Csoport neve', + 'For one ore more customers' => 'Érvényes a megadott ügyfeleknek', + 'Free product when buying one or more selected products' => 'Ingyenes termék, amennyiben egy vagy több kijelölt terméket vásárol', + 'Full Name' => 'Teljes név', + 'Greater than' => 'Nagyobb mint', + 'Greater than or equals' => 'Nagyobb mint vagy egyenlő', + 'HTML Message' => 'HTML Üzenet', + 'Home' => 'Kezdőoldal', + 'Home page' => 'Kezdőlap', + 'ISO 4217 code' => 'ISO 4217 kód', + 'ISO 639-1 Code' => 'ISO 639-1 kód', + 'ISO Alpha-2 code' => 'ISO Alpha-2 kód', + 'ISO Alpha-3 code' => 'ISO Alpha-3 kód', + 'ISO Code' => 'ISO kód', + 'If cart item count is %operator% %quantity%' => 'Ha a kosárban lévő termékek száma %operator% %quantity%', + 'If cart total amount is %operator% %amount% %currency%' => 'Ha a kosár összértéke %operator% %amount% %currency%', + 'In' => 'Benne van', + 'Invoice' => 'Számla', + 'Keep the most important part of your description in the first 150-160 characters.' => 'A legfontosabb információ a leírás első 150-160 karakterében legyen!', + 'Language' => 'Nyelv', + 'Language name' => 'Nyelv neve', + 'Languages' => 'Nyelvek', + 'Last Name' => 'Vezetéknév', + 'Lastname' => 'Vezetéknév', + 'Less than' => 'Kevesebb mint', + 'Less than or equals' => 'Kevesebb mint vagy egyenlő', + 'Login failed. Please check your username and password.' => 'Sikertelen bejelentkezés. Kérem ellenőrizze a felhasználónevét és jelszavát.', + 'Login page' => 'Bejelentkező oldal', + 'Mail template name' => 'Levélsablon neve', + 'Make sure it uses keywords found within the page itself.' => 'Győződjön meg róla, hogy tartalmazza a termékre jellemző kulcsszavakat.', + 'Make sure that your title is clear, and contains many of the keywords within the page itself.' => 'Győződjön meg róla, hogy a cím érthető és tartalmaz a termékre jellemző kulcsszavakat.', + 'Message' => 'Üzenet', + 'Message subject' => 'Üzenet tárgya', + 'Messages' => 'Üzenetek', + 'Meta Description' => 'Meta Description HTML tartalom', + 'Meta Keywords' => 'Meta Keywords HTML tartalom', + 'More information about ISO 4217' => 'Több információ a ISO 4217 kódról', + 'Name' => 'Név', + 'Name of the HTML layout file' => 'A "HTML layout" file neve', + 'Name of the HTML template file' => 'A "HTML template" file neve', + 'Name of the text layout file' => 'A "Text layout" file neve', + 'Name of the text template file' => 'A "Text template" file neve', + 'New Password' => 'Új jelszó', + 'Newsletter page' => 'Hírlevél oldal', + 'None' => 'Nincs', + 'Not equal to' => 'Nem egyenlő', + 'Not in' => 'Nincs benne', + 'Numerical ISO Code' => 'Numerikus ISO kód', + 'Only if order billing country is %op% %countries_list%' => 'Abban az esetben, ha a számlázási cím %op% %countries_list% ', + 'Only if order shipping country is %op% %countries_list%' => 'Abban az esetben, ha a szállítási cím %op% %countries_list% ', + 'Orders' => 'Megrendelések', + 'Page Title' => 'Oldal cím', + 'Parent category' => 'Szülő kategória', + 'Parent folder *' => 'Szülő csoport *', + 'Password' => 'Jelszó', + 'Password *' => 'Jelszó *', + 'Percentage' => 'Százalékos', + 'Percentage discount for selected attribute values' => 'Százalékos kedvezmény a kijelölt tulajdonságú termékekre', + 'Percentage discount for selected categories' => 'Százalékos kedvezmény a kijelölt kategóriák termékeire', + 'Percentage discount for selected products' => 'Százalékos kedvezmény a kijelölt termékekre', + 'Percentage of the product price' => 'Százalékos érték a termék árához viszonytva', + 'Phone' => 'Telefonszám', + 'Postage' => 'Szállítási költség', + 'Product' => 'Termék', + 'Product attributes' => 'Termék tulajdonságok', + 'Product price offset for each currency' => 'A kedvezmény mértéke az elérhető pénznemekben', + 'Product reference (must be unique)' => 'Termék azonosító (egyedinek kell lennie)', + 'Product reference *' => 'Termék azonosító *', + 'Product title' => 'Termék név', + 'Products' => 'Termékek', + 'Profile' => 'Felhasználói adatok', + 'Quantity' => 'Mennyiség', + 'Reference' => 'Azonosító', + 'Register' => 'Regisztráció', + 'Remember me ?' => 'Bejelentkezés megjegyzése?', + 'Remove X percent to total cart' => 'Megadott százalékkal csökkenti a kosár össz értékét', + 'Replace current image by this file' => 'Jelenlegi kép cseréje a kiválasztott képpel', + 'Reseller' => 'Viszonteladó', + 'Rewriten URL' => 'Megjelenő URL(kerülje az ékezetes betűket és a szóköz karaktert)', + 'Sale announce label' => 'A kampány megnevezése a boltban', + 'Sale title' => 'Kampány neve', + 'Search' => 'Keresés', + 'Select a default template for new products created in this category' => 'Válassza ki az alapértelmezett termék sablont ehhez a kategóriához', + 'Select the brand logo' => 'Válasszon logót', + 'Select the brand logo amongst the brand images' => 'Válasszon logót a márkához. Újat feltölteni a Képek fül alatt tud.', + 'Select the countries to include in this shipping zone' => 'Ehhez a szállítási zónához tartozó országok kiválasztása', + 'Select the discount type that will be applied to original product prices' => 'Válassza ki a kedvezmény típusát, ami a termékek eredeti árát módosítani fogja', + 'Select the parent category of this category.' => 'Válassza ki a szülő kategóriát.', + 'Select the product brand, or supplier.' => 'Válassz márkát/beszállítót.', + 'Shipping configuration' => 'Szállítási beállítások', + 'Shipping zone name' => 'Szállítási zóna név', + 'Short additional text' => 'Rövid kiegészítő szöveg', + 'Short description text' => 'Rövid leírás', + 'Sitemap' => 'Oldaltérkép', + 'Sorry, an error occured.' => 'Elnézést, hiba történt.', + 'Sorry, an error occured: %msg' => 'Elnézést, hiba történt: %msg', + 'Sorry, an error occured: %s' => 'Elnézést, hiba történt: %s', + 'Sorry, an error occurred: %err' => 'Elnézést, hiba történt: %err', + 'Sorry, you are not allowed to perform this action.' => 'Elnézést, nem hajthatja végre ezt a műveletet.', + 'Sorry, you\'re not allowed to perform this action' => 'Elnézést, nem hajthatja végre ezt a műveletet.', + 'Start date' => 'Induló dátum', + 'Start date of sales' => 'Kampány indításának ideje', + 'Stock' => 'Raktár', + 'Store Business Identification Number (SIRET, etc).' => 'Üzleti azonosító', + 'Store Information' => 'Bolt információk', + 'Store description' => 'Bolt leírás', + 'Store email address' => 'Bolt email cím', + 'Store logs into text file' => 'A naplók "text file"-ban tárolása', + 'Store name' => 'Bolt név', + 'Street Address' => 'Utca, házszám', + 'Street Address ' => 'Utca, házszám ', + 'Summary' => 'Leírás (rövid)', + 'Symbol' => 'Pénznem szimbólum', + 'Tax' => 'Adó', + 'Tax rule for this product *' => 'Adó szabály ehhez a termékhez *', + 'Taxes' => 'Adók', + 'Taxes rules' => 'Adószabályok', + 'Template Name *' => 'A sablon neve *', + 'Text Message' => 'Text üzenet', + 'The HTML TITLE element is the most important element on your web page.' => 'The HTML cím fontos SEO elem az oldalon.', + 'The brand name or title' => 'A márka neve vagy címe', + 'The cart item count should match the condition' => 'A kosárban lévő termékek számának egyeznie kell a feltétellel', + 'The category title' => 'A kategória cím', + 'The coupon applies if the cart contains at least one product of the selected categories' => 'A kupon érvényes, ha a kosár tartalmaz legalább egy terméket a kiválasztott kategóriából', + 'The coupon applies if the cart contains at least one product of the specified product list' => 'A kupon érvényes, ha a kosár tartalmaz legelább egy terméket a kiválasztott listából', + 'The coupon applies to some customers only' => 'A kupon csak a megadott ügyfeleknek érvényes', + 'The coupon applies to the selected billing countries' => 'A kupon érvényes a kiválasztott számlázási cím(ország) esetén', + 'The coupon applies to the selected delivery countries' => 'A kupon érvényes a kiválasztott szállítási cím(ország) esetén', + 'The coupon code \'%code\' already exist. Please choose another coupon code' => 'A kupon kód \'%code\' már létezik. Kérem adjon meg más kódot', + 'The coupon code \'%code\' already exists. Please choose another coupon code' => 'A kupon kód \'%code\' már létezik. Kérem adjon meg más kódot', + 'The coupon is valid after a given date' => 'A kupon érvényes a megadott dátum után', + 'The date after which sales are de-activated. Please use %fmt format.' => 'A dátum/idő miután a kampány már nem lesz érvényes. Használja a %fmt dátumformátumot.', + 'The date from which sales are active. Please use %fmt format.' => 'A kampány indulásának dátuma/ideje. Használja a %fmt dátumformátumot.', + 'The detailed description.' => 'Részletes leírás.', + 'The mailing template in HTML format.' => 'A levélsablon HTML formátumban', + 'The mailing template in text-only format.' => 'A levélsablon szöveges formátumban.', + 'The sale announce label, such as Sales ! or Flash Sales !' => 'A kampány bevezetett megnevezése, ami megjelenik a boltban pl. Húsvéti akció! vagy Karácsonyi kiárusítás!', + 'The sale name or descriptive title' => 'A kampány neve(adminisztrációban hivatkozás)', + 'The store fax number.' => 'A bolt fax száma.', + 'The store phone number.' => 'A bolt telefonszáma.', + 'This brand is online' => 'Elérhető az oldalon', + 'This category is online' => 'A kategória online elérhető', + 'This condition is always true' => 'Ez a feltétel mindig teljesül', + 'This content is online.' => 'Elérhető az oldalon.', + 'This coupon adds a free product to the cart if one of the selected products is in the cart.' => 'Ez a kupon ingyenes terméket ad a kosárhoz amennyiben a kiválasztott termékek közül a kosárba került legalább egy.', + 'This coupon subtracts from the order total a percentage of the price of each product which belongs to the selected categories. If the discount is greater than the total order, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.' => 'Ez a kupon a megadott százalékos értékkel csökkenti minden termék értékét a kiválasztott kategóriában. Ha a kedvezmény nagyobb mint a kosár összértéke, az ügyfélnek csak a szállítási költséget kell fizetnie(vagy azt sem ha a kupon ingyenes szállításra is jogosít).', + 'This coupon subtracts from the order total the specified percentage of each product price which uses the selected attribute values. If the discount is greater than the total order, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.' => 'Ez a kupon a megadott százalékos értékkel csökkenti minden kiválasztott tulajdonságú termék értékét. Ha a kedvezmény nagyobb mint a kosár összértéke, az ügyfélnek csak a szállítási költséget kell fizetnie(vagy azt sem ha a kupon ingyenes szállításra is jogosít).', + 'This coupon subtracts from the order total the specified percentage of each selected product price. If the discount is greater than the total order, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.' => 'Ez a kupon a megadott százalékos értékkel csökkenti minden kiválasztott termék értékét. Ha a kedvezmény nagyobb mint a kosár összértéke, az ügyfélnek csak a szállítási költséget kell fizetnie(vagy azt sem ha a kupon ingyenes szállításra is jogosít).', + 'This coupon subtracts the specified amount from the order total for each product which belongs to the selected categories. If the discount is greater than the total order, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.' => 'Ez a kupon a megadott értékkel csökkenti minden termék értékét a kiválasztott kategóriában. Ha a kedvezmény nagyobb mint a kosár összértéke, az ügyfélnek csak a szállítási költséget kell fizetnie(vagy azt sem ha a kupon ingyenes szállításra is jogosít).', + 'This coupon subtracts the specified amount from the order total for each product which uses the selected attribute values. If the discount is greater than the total order, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.' => 'Ez a kupon a megadott értékkel csökkenti minden kiválasztott tulajdonságú termék értékét. Ha a kedvezmény nagyobb mint a kosár összértéke, az ügyfélnek csak a szállítási költséget kell fizetnie(vagy azt sem ha a kupon ingyenes szállításra is jogosít).', + 'This coupon subtracts the specified amount from the order total for each selected product. If the discount is greater than the total order, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.' => 'Ez a kupon a megadott értékkel csökkenti minden termék kiválasztott termék értékét. Ha a kedvezmény nagyobb mint a kosár összértéke, az ügyfélnek csak a szállítási költséget kell fizetnie(vagy azt sem ha a kupon ingyenes szállításra is jogosít).', + 'This coupon will offert a flat percentage off a shopper\'s entire order (not applied to shipping costs or tax rates). If the discount is greater than the total order corst, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.' => 'Ez a kupon a megadott százalékos értékkel csökkenti a kosár tartalmának értékét(nem vonatkozik a szállítási költségre). Ha a kedvezmény nagyobb mint a kosár összértéke, az ügyfélnek csak a szállítási költséget kell fizetnie(vagy azt sem ha a kupon ingyenes szállításra is jogosít).', + 'This coupon will subtracts a set amount from the total cost of an order. If the discount is greater than the total order corst, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.' => 'Ez a kupon a megadott értékkel csökkenti a kosár tartalmának értékét. Ha a kedvezmény nagyobb mint a kosár összértéke, az ügyfélnek csak a szállítási költséget kell fizetnie(vagy azt sem ha a kupon ingyenes szállításra is jogosít).', + 'This document is online' => 'Elérhető az oldalon', + 'This folder is online.' => 'Elérhető az oldalon.', + 'This image is online' => 'A kép elérhető az oldalon', + 'This is a comma separated list of email addresses where store notifications (such as order placed) are sent.' => 'Ez egy vesszővel elválasztott email-lista lehet, a listában szereplő címekre küld a rendszer értesítéseket(pl. megrendelés értesítője)', + 'This is an identifier that will be used in the code to get this message' => 'Ez egy azonosító amivel a programkódban hivatkozhat a sablonra', + 'This is the contact email address, and the sender email of all e-mails sent by your store.' => 'A rendszer ezzel az email címmel küld ki leveleket(mint feladó).', + 'This is the message purpose, such as \'Order confirmation\'.' => '"Beszédes név", ami utal a levél tartalmára pl. \'Megrendelés Visszaigazolása\'.', + 'This is the subject of the e-mail, such as \'Your order is confirmed\'.' => 'A levél tárgya, mint pl. \'Megrendelése jóváhagyásra került\'.', + 'This product does not have a physical presence' => 'Ez a termék fizikailag nem létezik', + 'This product is online' => 'Ez a termék elérhető az oldalon', + 'This the unique name of this message. Do not change this value unless you understand what you do.' => 'Egyedi megnevezés. Ne változtasson rajta, csak amennyiben tisztában azzal amit csinál!', + 'Timeout' => 'Időtúllépés', + 'Title' => 'Név', + 'Title *' => 'Név *', + 'Tools' => 'Eszközök', + 'Translations' => 'Fordítások', + 'Type' => 'Típus', + 'URL_ALREADY_EXISTS' => 'Ez az URL már létezik', + 'Unconditional usage' => 'Feltétel nélküli használat', + 'Unconditionnal usage' => 'Feltétel nélküli használat', + 'Unknown order ID: %id' => 'Ismeretlen megrendelés azonosító ID: %id', + 'Unsupported type' => 'Nem támogatott típus', + 'Username' => 'Felhasználó', + 'Valid only from %date% to the coupon expiration date' => 'Érvényes a %date% dátumtól a kupon lejárati dátumáig', + 'Value' => 'Érték', + 'You don\'t need to use commas or other punctuations.' => 'Nem kell vesszőt vagy más határolót használnia.', + 'Zip code' => 'Irányítószám', + 'date format' => 'Dátum formátum', + 'decimal separator' => 'Tizedesjegy jelölő', + 'email confirmation is not the same as email field' => 'A megadott két email cím nem egyezik', + 'language locale' => 'Nyelv "locale" kódja', + 'permanent discount (in percent)' => 'Állandó kedvezmény (százalékban)', + 'thousands separator' => 'Ezreshatároló jele', + 'time format' => 'Idő formátum', +]; diff --git a/core/lib/Thelia/Config/I18n/id_ID.php b/core/lib/Thelia/Config/I18n/id_ID.php new file mode 100644 index 00000000..e54e3295 --- /dev/null +++ b/core/lib/Thelia/Config/I18n/id_ID.php @@ -0,0 +1,695 @@ + ' formulir pembuatan konten', + ' note: only non-visible documents can be associated.' => ' catatan: hanya dokumen yang tidak terlihat dapat dikaitkan.', + '"%param" parameter cannot be empty in loop type: %type, name: %name' => 'parameter "%param" tidak boleh kosong dalam loop tipe: tipe %, nama: %name', + '"%param" parameter is missing in loop type: %type, name: %name' => '"%param" parameter hilang dalam loop tipe: tipe %, nama: %name', + '%module (version: %version)' => '%module (versi: %versi)', + '%n for number, %c for the currency code, %s for the currency symbol' => '%n untuk angka %c untuk kode mata uang %s untuk simbol mata uang', + '%obj SEO modification' => '%obj SEO modifikasi', + '%obj creation' => 'penciptaan %obj', + '%obj modification' => '%obj modifikasi', + '%obj%s deleted successfully' => 'Semua %obj%s Berhasil dihapus', + '%s has dependency to module %s. You have to deactivate this module before.' => '%s modul terkait %s. Anda harus menonaktifkan modul ini sebelum.', + '%s have dependencies to module %s. You have to deactivate these modules before.' => '%s modul terkait %s. Anda sebelumnya harus menonaktifkan modul-modul ini.', + '%type% position updated' => 'Posisi %type% diperbaharui', + '%type% visibility updated' => 'Penampilan %type% Diperbarui', + 'A comma separated list of email addresses' => 'Daftar alamat email dipisahkan dengan tanda koma', + 'A currency with code "%name" already exists.' => 'Mata uang dengan kode "%name" sudah ada.', + 'A descriptive title' => 'Judul Deskripsi', + 'A message with name "%name" already exists.' => 'Pesan dengan nama "%name" sudah ada.', + 'A name such as Europe or Overseas' => 'Nama seperti Eropa atau luar negeri', + 'A product with reference %ref already exists. Please choose another reference.' => 'Produk dengan referensi % ref sudah ada. Silakan pilih referensi lain.', + 'A short description, used when a summary or an introduction is required' => 'Deskripsi singkat, digunakan untuk ringkasan atau pengenalan', + 'A short text, used when an additional or supplemental information is required.' => 'Teks pendek, untuk informasi tambahan atau seperlunya.', + 'A user already exists with this email address. Please login or if you\'ve forgotten your password, go to Reset Your Password.' => 'Pengguna sudah ada dengan alamat email ini. Silahkan login atau jika Anda lupa password Anda, pergi untuk mereset Password Anda.', + 'A value for attribute "%name" is already present in the combination' => 'Nilai untuk atribut "%name" sudah hadir dalam kombinasi', + 'A variable with name "%name" already exists.' => 'Sebuah variabel dengan nama "%name" sudah ada.', + 'Activate logs only for these IP Addresses' => 'Aktifkan log hanya untuk alamat IP ini', + 'Activate logs only for these files' => 'Aktifkan log hanya untuk file-file ini', + 'Activate this sale' => 'Aktifkan penjualan ini', + 'Active' => 'Aktif', + 'Additional address information' => 'Tambahan Informasi alamat', + 'Address ID not found' => 'ID alamat tidak ditemukan', + 'Address Line 2' => 'Alamat Baris 2', + 'Address Line 3' => 'Alamat baris 3', + 'Address creation' => 'Alamat Pencipta', + 'Address label' => 'Label alamat', + 'Address update' => 'Pembaruan alamat', + 'Address.' => 'Alamat.', + 'Administrator' => 'Administrator', + 'Administrator ID not found' => 'ID Administrator tidak ditemukan', + 'Advertise this product as new' => 'Mengiklankan produk ini seperti baru', + 'Alerts' => 'Peringatan', + 'All Products' => 'Semua Produk', + 'All countries' => 'Semua Negara', + 'All shipping methods' => 'Semua Metode Pengiriman', + 'Amount' => 'Jumlah', + 'Apply exchange rates on price in %sym' => 'Menerapkan nilai tukar pada harga di %sym', + 'Archive Format' => 'Format Arsip', + 'Associate documents' => 'Mengasosiasikan dokumen', + 'Associate images' => 'Mengaitkan gambar', + 'At least one of cart products categories is %op% %categories_list%' => 'Setidaknya salah satu kategori produk keranjang adalah %op% %categories_list%', + 'Attribut' => 'Attribut', + 'Attribute ID:Attribute AV ID' => 'Atribut ID:Attribute AV ID', + 'Attribute value' => 'Nilai atribut', + 'Attributes value' => 'Nilai atribut', + 'Auth mode' => 'Auth modus', + 'Available quantity' => 'Kuantitas yang tersedia', + 'Available quantity *' => 'Kuantitas yang tersedia *', + 'Available shipping zones' => 'Tersedia pengiriman zona', + 'Back Office' => 'Back Office', + 'Bad tax list JSON' => 'Daftar buruk pajak JSON', + 'Billing country' => 'Penagihan negara', + 'Billing country is' => 'Penagihan negara adalah', + 'Brand' => 'Merek', + 'Brand / Supplier' => 'Merek / Supplier', + 'Brand name' => 'Nama merek', + 'Brands' => 'Merek', + 'Business ID' => 'ID bisnis', + 'By Module' => 'Modul oleh', + 'CSS' => 'CSS', + 'CSS stylesheet' => 'CSS stylesheet', + 'Cannot find a default country. Please define one.' => 'Tidak dapat menemukan sebuah negara default. Harap define satu.', + 'Cannot find the shop country. Please select a shop country.' => 'Tidak dapat menemukan toko negara. Silakan pilih negara toko.', + 'Cannot instantiate module "%name%": the namespace is null. Maybe the model is not loaded ?' => 'Modul tidak sesuai dengan "%name%": namespace null. Mungkin model tidak dimuat ?', + 'Cart contains at least a product %op% %products_list%' => 'Keranjang sedikitnya haus berisi %op% %products_list% produk', + 'Cart contains categories condition' => 'Kondisi Keranjang berisi Kategori', + 'Cart contains specific products' => 'Keranjang berisi produk tertentu', + 'Cart item count' => 'Jumlah item dalam keranjang', + 'Cart item count is' => 'Keranjang barang menghitung', + 'Cart total amount' => 'Jumlah total pembelian dalam keranjang', + 'Cart total amount is' => 'Jumlah total keranjang', + 'Catalog configuration' => 'Susunan Katalog', + 'Category' => 'Kategori', + 'Category page' => 'Halaman Kategori', + 'Cellphone' => 'Cellphone', + 'Change password' => 'Ubah Kata Sandi', + 'Check country iso codes here.' => 'Periksa kode iso negara di Wikipedia.', + 'Check the total Cart amount in the given currency' => 'Memeriksa jumlah keranjang dalam mata uang tertentu', + 'Compagny' => 'Compagny', + 'Company Name' => 'Nama perusahaan', + 'Conclusion' => 'Kesimpulan', + 'Confirm Email Address' => 'Konfirmasi alamat email Anda', + 'Confirm Email address' => 'Konfirmasi alamat email Anda', + 'Constant amount' => 'Jumlah tetap', + 'Constant amount found in one of the product\'s feature' => 'Jumlah tetap yang ditemukan dalam salah satu fitur produk', + 'Contact and sender email address' => 'Kontak dan alamat email pengirim', + 'Contact page' => 'Halaman kontak', + 'Content' => 'Konten', + 'Content page' => 'Halaman Konten', + 'Content title *' => 'Judul Konten*', + 'Contents' => 'Konten', + 'Core hook of Thelia.' => 'Congkel inti dari Thelia.', + 'Country ID not found' => 'ID Negara tidak ditemukan', + 'Country title' => 'Nama Negara', + 'Coupon %code is expired.' => 'Kode kupon %code sudah tidak berlaku.', + 'Coupon code %code is disabled.' => 'Kode kupon %code tidak aktif.', + 'Critical' => 'Kritis', + 'Curency selection page' => 'Halaman untuk pemilihan mata uang', + 'Current Password' => 'Password saat ini', + 'Customer is %op% %customer_list%' => 'Daftar pelanggan %op% %customer_list%', + 'Date \'%date\' is invalid, please enter a valid date using %fmt format' => 'Format tanggal \'%date\' tidak benar, tolong masukan tanggal dengan format %fmt', + 'Debug' => 'Debug', + 'Decimal places' => 'Jumlah desimal', + 'Default folder *' => 'Default folder *', + 'Default product category *' => 'Default kategori produk *', + 'Default product sale element' => 'Default elemen produk dijual', + 'Default product template' => 'Default produk template', + 'Deleting %obj% for %id% with parent id %parentId%' => 'Menghapus %obj% untuk %id% dengan induk id %parentId%', + 'Delivery' => 'Pengiriman', + 'Delivery choice' => 'Pilihan pengiriman', + 'Delivery country' => 'Negara pengirim', + 'Delivery country is' => 'Negara pengirim adalah', + 'Delivery module ID not found' => 'ID modul pengiriman tidak ada', + 'Delivery zone' => 'Wilayah pengiriman', + 'Detailed description' => 'Deskripsi detail', + 'Disabled' => 'Dinonaktifkan', + 'Discount type' => 'Jenis Diskon', + 'Display initial product prices on front-office' => 'Tampilkan inisial harga produk di front-office', + 'Do compress' => 'Kompres', + 'Document' => 'Dokumen', + 'Don\'t repeat keywords over and over in a row. Rather, put in keyword phrases.' => 'Jangan ulangi kata kunci secara terus menerus dalam satu waktu. Sebaiknya, masukan dalam kelompok kata kunci.', + 'Edit JavaScript' => 'Mengedit JavaScript', + 'Email Address' => 'Alamat email', + 'Email addresses of notification recipients' => 'Alamat email untuk menerima notifikasi', + 'Email test from : %store%' => 'Pengujian email dari: %store%', + 'Emergency' => 'Darurat', + 'Enable remote SMTP use' => 'Perbolehkan remote dengan SMTP', + 'End date of sales' => 'Tanggal akhir penjualan', + 'Enter here the brand name in the default language (%title%)' => 'Masukan nama merek di sini dalam bahasa default (%title%)', + 'Enter here the category title in the default language (%title%)' => 'Masukan nama kategori di sini dalam bahasa default (%title%)', + 'Enter here the mail template purpose in the default language (%title%)' => 'Masukan template email di sini dalam bahasa default (%title%)', + 'Enter here the sale name in the default language (%title%)' => 'Masukan nama jual di sini dalam bahasa default (%title%)', + 'Equal to' => 'Sama dengan', + 'Error during %action process : %error. Exception was %exc' => 'Error ketika menjalankan %action process : %error. Penyebabnya adalah %exc', + 'Error occured while processing order ref. %ref, ID %id: %err' => 'Error occured while processing order ref. %ref, ID %id: %err', + 'Error occured.' => 'Terjadi error.', + 'Errors' => 'Errors', + 'Fail to delete %obj% for %id% with parent id %parentId% (Exception : %e%)' => 'Gagal menghapus %obj% untuk %id% dengan id induk %parentId% (Penyebab : %e%)', + 'Fail to update %type% position: %err%' => 'Gagal memperbarui %type% posisi: %err%', + 'Fail to update %type% visibility: %err%' => 'Gagal memperbarui %type% visibility: %err%', + 'Failed to create instance of module "%name%" when trying to delete module. Module directory has probably been deleted' => 'Gagal membuat rekap dari modul "%name%" ketika menghapus modul tersebut. Direktori modul mungkin sudah dihapus', + 'Failed to create new hook %s' => 'Gagal membuat pengail baru %s', + 'Failed to deactivate hook with id %s' => 'Gagal menonaktifkan pengail dengan id %s', + 'Failed to delete selected countries' => 'Gagal menghapus negara yang terpilih', + 'Failed to find a payment Module with ID=%mid for order ID=%oid' => 'Pencarian gagal untuk Modul pembayaran dengan ID=%mid pada order ID=%oid', + 'Failed to load descriptor (module.xml) for module ID "%id".' => 'Gagal memuat pendeskripsi (module.xml) pada module ID "%id".', + 'Failed to load message with code \'%code%\', propably because it does\'nt exists.' => 'Gagal memuat pesan dengan kode \'%code%\', mungkin pesan tersebut tidak ada.', + 'Failed to open a writing stream on the file: %file' => 'Gagal membuka aliran penulisan pada file: %file', + 'Failed to open translation file %file. Please be sure that this file is writable by your Web server' => 'Gagal membuka file terjemahan %file. Pastikan bahwa file ini bisa diakses oleh server Web Anda', + 'Failed to send message %code. Failed recipients: %failed_addresses' => 'Gagal untuk mengirim pesan %code. Gagal diterima oleh: %failed_addresses', + 'Failed to update language definition: %ex' => 'Gagal untuk memperbaharui definisi bahasa: %ex', + 'Fax' => 'Fax', + 'Feature' => 'Fitur', + 'Feature value does not match FLOAT format' => 'Nilai fitur tidak sesuai dengan FLOAT format', + 'Features value' => 'Nilai fitur', + 'File format' => 'Format file', + 'File is too large, please retry with a file having a size less than %size%.' => 'File terlalu besar, silakan coba lagi dengan file yang memiliki ukuran kurang dari %size%.', + 'File to upload' => 'File untuk diupload', + 'Files with the following extension are not allowed: %extension, please do an archive of the file if you want to upload it' => 'File dengan ekstensi berikut dilarang: %extension, silakan lakukan Arsip file jika Anda ingin meng-upload-nya', + 'First Name' => 'Nama Depan', + 'Firstname' => 'Nama depan', + 'Fixed Amount Discount' => 'Jumlah diskon tetap', + 'Fixed amount discount for selected attribute values' => 'Diskon Jumlah tetap untuk nilai atribut yang dipilih', + 'Fixed amount discount for selected categories' => 'Jumlah tetap diskon untuk kategori yang dipilih', + 'Fixed amount discount for selected products' => 'Jumlah tetap diskon untuk produk terpilih', + 'Folder' => 'Folder', + 'Folder page' => 'Halaman folder', + 'Folder title *' => 'Nama folder *', + 'For one ore more customers' => 'Untuk satu atau lebih banyak pelanggan', + 'Free product when buying one or more selected products' => 'Bonus produk ketika membeli satu atau lebih pada produk terpilih', + 'Front Office' => 'Front Office', + 'Full Name' => 'Nama lengkap', + 'Greater than' => 'Lebih dari', + 'Greater than or equals' => 'Lebih besar dari atau sama dengan', + 'HTML Message' => 'HTML pesan', + 'HTML layout' => 'Tata letak HTML', + 'Home page' => 'Halaman Utama', + 'Hook' => 'Mengait', + 'Hook block' => 'Blok kaitan', + 'Hook code' => 'Kode kaitan', + 'Hook create form' => 'Pembuatan form untuk kaitan', + 'Hook title' => 'Judul kaitan', + 'Hooks' => 'Kaitan', + 'I would like to receive the newsletter or the latest news.' => 'Saya ingin menerima newsletter atau berita terbaru.', + 'ISO 639-1 Code' => 'ISO 639-1 kode', + 'ISO Alpha-2 code' => 'Kode ISO Alpha-2', + 'ISO Alpha-3 code' => 'Kode ISO Alpha-2', + 'If cart item count is %operator% %quantity%' => 'Jika jumlah item keranjang %operator% %quantity%', + 'If cart total amount is %operator% %amount% %currency%' => 'Jika jumlah total keranjang %operator% %amount% %currency%', + 'If checked, this hook will be used by a hook block. If not, by hook function.' => 'Jika dicentang, kait ini akan digunakan dengan blok kaitan. Jika tidak, akan dihubungkan oleh fungsi.', + 'Image' => 'Gambar', + 'Impossible to delete a customer who already have orders' => 'Mustahil untuk menghapus Pelanggan yang telah memiliki perintah', + 'In' => 'Dalam', + 'Include documents' => 'Termasuk dokumen', + 'Include images' => 'Termasuk gambar', + 'Information' => 'Informasi', + 'Invalid product_sale_elements' => 'Product_sale_elements tidak valid', + 'Invalid value "%value" for "%param" parameter in loop type: %type, name: %name' => 'Nilai salah "% nilai" untuk "%param" parameter dalam loop tipe: tipe %, nama: %name', + 'Invalid value for walkMode parameter: %value' => 'Nilai valid untuk walkMode parameter: % nilai', + 'Invoice' => 'Faktur', + 'Invoice choice' => 'Pilihan faktur', + 'Is it the default product sale element ?' => 'Itu unsur penjualan produk default?', + 'It is not allowed to delete the default currency' => 'Tidak diijinkan untuk menghapus mata uang default', + 'It is not allowed to delete the default language' => 'Tidak diijinkan untuk menghapus bahasa default', + 'JavaScript' => 'JavaScript', + 'Keep the most important part of your description in the first 150-160 characters.' => 'Diskripsikan bagian terpenting dalam diri Anda dalam 150-160 karakter.', + 'Last Name' => 'Nama Belakang', + 'Layout' => 'Tata Letak', + 'Less than' => 'Kurang dari', + 'Less than or equals' => 'Kurang dari atau sama dengan', + 'Log format *' => 'Log format *', + 'Log level *' => 'Login tingkat *', + 'Login failed. Please check your username and password.' => 'Login gagal. Silakan periksa username dan password Anda.', + 'Login page' => 'Halaman Login', + 'Logs' => 'Log', + 'Loop cannot implements multiple Search Interfaces : `PropelSearchLoopInterface`, `ArraySearchLoopInterface`' => 'Loop tidak menerapkan beberapa antarmuka pencarian: \'PropelSearchLoopInterface\', \'ArraySearchLoopInterface\'', + 'Loop must implements \'PropelSearchLoopInterface\' to be timestampable' => 'Loop harus mengimplementasikan \'PropelSearchLoopInterface\' untuk timestampable', + 'Loop must implements \'PropelSearchLoopInterface\' to be versionable' => 'Loop harus mengimplementasikan \'PropelSearchLoopInterface\' untuk versionable', + 'Loop must implements one of the following interfaces : `PropelSearchLoopInterface`, `ArraySearchLoopInterface`' => 'Loop harus menerapkan salah satu antarmuka berikut: \'PropelSearchLoopInterface\', \'ArraySearchLoopInterface\'', + 'Lost password' => 'Lupa kata sandi', + 'Mail template name' => 'Nama template pesan', + 'Mail template purpose' => 'Email template tujuan', + 'Main address' => 'Alamat utama', + 'Main area' => 'Area utama', + 'Make sure it uses keywords found within the page itself.' => 'Pastikan menggunakan kata kunci yang ditemukan dalam halaman itu sendiri.', + 'Make sure that your title is clear, and contains many of the keywords within the page itself.' => 'Pastikan bahwa judul Anda jelas, dan berisi banyak kata kunci dalam halaman itu sendiri.', + 'Make this address as my primary address' => 'Membuat alamat ini sebagai alamat utama saya', + 'Maximum usage count reached for coupon %code' => 'Jumlah maksimum penggunaan mendekati untuk kupon %code', + 'Message' => 'Pesan', + 'Message name' => 'Nama pesan', + 'Message subject' => 'Subjek pesan', + 'Messages' => 'Pesan', + 'Meta Description' => 'Meta Deskripsi', + 'Meta Keywords' => 'Meta Kata Kunci', + 'Method Name' => 'Nama metode', + 'Missing or invalid data: %s' => 'Data yang hilang atau tidak valid: %s', + 'Module "%name%" directory was not found' => 'Modul "%name%" direktori tidak ditemukan', + 'Module %name directory doesn\'t exists.' => 'Direktori modul %name tidak ada.', + 'Module %name should have a config.xml in the Config directory.' => 'Modul %name harus memiliki config.xml dalam direktori Config.', + 'Module %name should have a module.xml in the Config directory.' => 'Modul %name harus memiliki module.xml dalam direktori Config.', + 'Module ID "%id" was not found.' => 'ID Module "%id" tidak ditemukan.', + 'Module ID not found' => 'ID module tidak ditemukan', + 'Module hook' => 'Hook modul', + 'Name *' => 'Nama *', + 'Name of the HTML layout file' => 'Nama dari file tata letak HTML', + 'Name of the HTML template file' => 'Nama file template HTML', + 'Name of the text layout file' => 'Nama file tata letak teks', + 'Name of the text template file' => 'Nama file template teks', + 'Native' => 'Asli', + 'New Password' => 'Kata Sandi baru', + 'Newsletter page' => 'Halaman newsletter', + 'No %obj was created.' => '%obj tidak diciptakan.', + 'No %obj was updated.' => '%obj tidak diperbarui.', + 'No module found for code \'%item\'' => 'Ada modul yang ditemukan untuk kode \'%item\'', + 'No, I am a new customer.' => 'Tidak, saya pelanggan baru.', + 'None' => 'Tidak ada', + 'Not equal to' => 'Tidak sama dengan', + 'Not in' => 'Tidak masuk', + 'Notices' => 'Pemberitahuan', + 'Numerical ISO Code' => 'Kode Numerik ISO', + 'Only files having the following mime type are allowed: %types%' => 'Diperbolehkan hanya file yang memiliki jenis mime berikut: %types%', + 'Only hookable modules are displayed in this menu.' => 'Hanya modul dapat-catut yang ditampilkan dalam menu ini.', + 'Only if order billing country is %op% %countries_list%' => 'Negara penagihan dari order %op% %countries_list% ', + 'Only if order shipping country is %op% %countries_list%' => 'Negara tujuan pengiriman pesanan adalah %op% %countries_list% ', + 'Order' => 'Pesan', + 'Order address ID not found' => 'ID alamat pesanan tidak ditemukan', + 'Order failed' => 'Pemesanan gagal', + 'Order ref. %ref is now unpaid.' => 'Pesanan dengan ref. % ref belum dibayar.', + 'Order ref. %ref, ID %id has been successfully paid.' => 'Pesanan dengan ref. % ref, ID %id berhasil dibayar.', + 'Overall' => 'Keseluruhan', + 'Page 404' => 'Halaman 404', + 'Page Title' => 'Judul Halaman', + 'Parent category' => 'Kategori induk', + 'Parent folder *' => 'Folder induk', + 'Password *' => 'Kata sandi', + 'Password confirmation' => 'Konfirmasi sandi', + 'Payment failed' => 'Pembayaran gagal', + 'Payment gateway' => 'Media Pembayaran', + 'Per customer' => 'Per pelanggan', + 'Percentage' => 'Persentase', + 'Percentage discount for selected attribute values' => 'Persentase diskon untuk nilai atribut yang dipilih', + 'Percentage discount for selected categories' => 'Persentase diskon untuk kategori yang dipilih', + 'Percentage discount for selected products' => 'Diskon persentase untuk produk tertentu', + 'Percentage of the product price' => 'Persentase harga produk', + 'Placed order' => 'Pesan', + 'Please accept the Terms and conditions in order to register.' => 'Harap menerima syarat dan ketentuan untuk mendaftar.', + 'Please check your input: %error' => 'Periksa masukan Anda: %error', + 'Please enter your email address' => 'Harao masukkan alamat email Anda', + 'Please enter your password' => 'Silakan masukkan kata sandi Anda', + 'Please select a category' => 'Silahkan pilih sebuah kategori', + 'Please select an attribute' => 'Silakan pilih sebuah atribut', + 'Please select at least one attribute value' => 'Pilih sedikitnya satu atribut', + 'Please select at least one category' => 'Harap pilih setidaknya satu kategori', + 'Please select at least one product' => 'Harap pilih setidaknya satu produk', + 'Please select the category of the offred product' => 'Silahkan pilih kategori dari produk yang ditawarkan', + 'Please select the offered product' => 'Silahkan pilih produk yang ditawarkan', + 'Please upload a valid Zip file' => 'Silahkan unggah sebuah file Zip yang valid', + 'Preferred locale' => 'Lokal pilihan', + 'Prevent mailing template modification or deletion, except for super-admin' => 'Cegah templat surat diubah atau dihapus, kecuali oleh super-admin', + 'Prevent variable modification or deletion, except for super-admin' => 'Cegah modifikasi dan penghapusan variabel, kecuali oleh super-admin', + 'Price currency *' => 'Harga mata uang *', + 'Processing cancelation of payment for order ref. %ref' => 'Memproses pembatalan pembayaran untuk pesanan ref. % ref', + 'Processing confirmation of order ref. %ref, ID %id' => 'Memproses konfirmasi dari pesanan ref. % ref, ID %id', + 'Prodcut ID *' => 'ID Produk *', + 'Product ID' => 'ID Produk', + 'Product ID *' => 'ID Produk *', + 'Product base price excluding taxes *' => 'Harga dasar produk tidak termasuk pajak *', + 'Product base price with taxes' => 'Harga dasar produk dengan pajak', + 'Product categories' => 'Kategori Produk', + 'Product clone' => 'Produk identik', + 'Product loop' => 'Produk loop', + 'Product page' => 'Halaman produk', + 'Product price excluding taxes' => 'Harga produk tidak termasuk pajak', + 'Product price excluding taxes *' => 'Harga produk tidak termasuk pajak *', + 'Product price including taxes' => 'Harga produk tidak termasuk pajak', + 'Product price offset for each currency' => 'Produk harga offset setiap mata uang', + 'Product reference (must be unique)' => 'Produk referensi (harus unik)', + 'Product reference *' => 'Referensi produk *', + 'Product sale element ID *' => 'Produk dijual elemen ID *', + 'Product template' => 'Produk template', + 'ProductSaleElement modification' => 'ProductSaleElement modifikasi', + 'Profile Code' => 'Kode profil', + 'Profile ID not found' => 'Nomor profil tidak ditemukan', + 'Profile `code` already exists' => 'Profil \'kode\' sudah ada', + 'Purpose *' => 'Tujuan *', + 'Range date End' => 'Rentang tanggal akhir', + 'Range date Start' => 'Rentang tanggal mulai', + 'Redirecting ...' => 'Mengarahkan ...', + 'Redirecting to %url' => 'Mengarahkan ke %url', + 'Reference *' => 'Rujukan *', + 'Remember me ?' => 'Ingat saya ?', + 'Remove X percent to total cart' => 'Hapus X persen ke total keranjang', + 'Replace by the default language' => 'Mengganti dengan bahasa default', + 'Replace current document by this file' => 'Menggantikan dokumen saat ini oleh file ini', + 'Replace current image by this file' => 'Mengganti gambar saat ini oleh file ini', + 'Reseller' => 'Reseller', + 'Rewriten URL' => 'URL yang telah direwrite', + 'Rotated Text File' => 'File teks yang diputar', + 'Sale announce label' => 'Dijual mengumumkan label', + 'Sale price excluding taxes' => 'Harga tidak termasuk pajak', + 'Sale price including taxes' => 'Harga termasuk pajak', + 'Sale title' => 'Dijual judul', + 'Saving %obj% for %parentName% parent id %parentId%' => 'Tabungan %obj% untuk %parentName% orangtua id %parentId%', + 'Search page' => 'Halaman pencarian', + 'Select a default template for new products created in this category' => 'Pilih template default untuk produk-produk baru yang dibuat dalam kategori ini', + 'Select the brand logo' => 'Pilih merek logo', + 'Select the brand logo amongst the brand images' => 'Pilih merek logo antara citra merek', + 'Select the categories of the products covered by this operation' => 'Pilih kategori produk yang tercakup dalam operasi ini', + 'Select the countries to delete from this shipping zone' => 'Pilih negara untuk menghapus dari zona pengiriman ini', + 'Select the countries to include in this shipping zone' => 'Pilih negara-negara yang termasuk dalam zona pengiriman ini', + 'Select the discount type that will be applied to original product prices' => 'Pilih jenis diskon yang akan diterapkan ke asli harga produk', + 'Select the parent category of this category.' => 'Pilih kategori induk kategori ini.', + 'Select the product attributes included in this operation' => 'Memilih atribut produk yang termasuk dalam operasi ini', + 'Select the product brand, or supplier.' => 'Pilih merek produk, atau pemasok.', + 'Select the products covered by this operation' => 'Pilih produk-produk yang tercakup dalam operasi ini', + 'Select the virtual document' => 'Pilih dokumen virtual', + 'Service ID' => 'ID Layanan', + 'Shipping zone name' => 'Nama zona pengiriman', + 'Short additional text' => 'Teks tambahan', + 'Short description text' => 'Teks deskripsi', + 'Show redirections *' => 'Tunjukkan pengalihan *', + 'Sitemap' => 'Peta situs', + 'Sorry, an error occured.' => 'Maaf, terjadi kesalahan.', + 'Sorry, an error occured: %msg' => 'Sorry, an error occured: %msg', + 'Sorry, an error occured: %s' => 'Maaf, terjadi kesalahan: %s', + 'Sorry, an error occurred: %err' => 'Maaf, terjadi kesalahan: %err', + 'Sorry, you are not allowed to perform this action.' => 'Maaf, Anda tidak berhak melakukan aksi ini.', + 'Sorry, you\'re not allowed to perform this action' => 'Maaf, Anda tidak berhak melakukan aksi ini', + 'Start date' => 'Mulai dari tanggal', + 'Start date of sales' => 'Tanggal mulai penjualan', + 'Store Business Identification Number (SIRET, etc).' => 'Nomor identifikasi bisnis toko (SIRET, dll).', + 'Store Information' => 'Informasi Toko', + 'Store configuration failed.' => 'Gagal mengonfigurasi toko.', + 'Store description' => 'Deskripsi toko', + 'Store email address' => 'Alamat email toko', + 'Store logs into text file' => 'Log toko kedalam file teks', + 'Store logs into text file, up to a certian size, then a new file is created' => 'Store logs into text file, up to a certian size, then a new file is created', + 'Store name' => 'Nama toko', + 'Street Address' => 'Alamat', + 'Street Address ' => 'Alamat ', + 'Strictly use the requested language' => 'Diminta menggunakan bahasa yang diseting', + 'Subject' => 'Subjek', + 'Summary' => 'Ringkasan', + 'System' => 'Sistem', + 'System configuration' => 'Konfigurasi sistem', + 'System log configuration failed.' => 'Gagal mengonfigurasi log sistem.', + 'Tax ID not found in tax list JSON' => 'ID pajak tidak ditemukan dalam daftar pajak JSON', + 'Tax list is not valid JSON' => 'Daftar pajak ini bukan JSON yang valid', + 'Tax rule ID not found' => 'ID aturan pajak tidak ditemukan', + 'Tax rule for this product *' => 'Aturan pajak untuk produk ini *', + 'Template' => 'Templat', + 'Template Name *' => 'Nama template *', + 'Text File' => 'File Teks', + 'Text Message' => 'Pesan Teks', + 'The %name module definition has not been initialized.' => 'Definisi modul %name tidak dapat diinisialisasi.', + 'The %name module descriptor has not been initialized.' => 'Pendeskripsi modul %name tidak dapat diinisialisasi.', + 'The %obj_name id \'%id\' doesn\'t exist' => '%obj_name id \'%id\' tidak ada', + 'The HTML TITLE element is the most important element on your web page.' => 'Elemen TITLE HTML adalah unsur terpenting dalam halaman web Anda.', + 'The brand name or title' => 'Nama merek atau judul', + 'The cart item count should match the condition' => 'Jumlah item dalam keranjang harus sesuai kondisi', + 'The category title' => 'Judul kategori', + 'The class "%class" doesn\'t exist' => 'Tidak ada kelas "%class"', + 'The class "%class" must extend %baseClass' => 'Kelas "%class" harus memperpanjang %baseClass', + 'The container should not be null in this form. Please use the FormFactory to get an instance.' => 'Wadah tidak boleh null formulir ini. Gunakan FormFactory untuk mendapatkan instance.', + 'The coupon applies if the cart contains at least one product of the selected categories' => 'Kupon berlaku jika Shopping cart berisi produk setidaknya satu kategori dipilih', + 'The coupon applies if the cart contains at least one product of the specified product list' => 'Kupon berlaku jika Shopping cart berisi setidaknya salah satu produk dari daftar produk-produk tertentu', + 'The coupon applies to some customers only' => 'Kupon berlaku untuk beberapa pelanggan hanya', + 'The coupon applies to the selected billing countries' => 'Kupon berlaku untuk negara-negara penagihan yang dipilih', + 'The coupon applies to the selected delivery countries' => 'Kode kupon EC hanya berlaku untuk dipilih Membayar tagihan', + 'The coupon code \'%code\' already exist. Please choose another coupon code' => 'Kode kupon \'%code\' sudah ada. Silakan pilih lain kode kupon', + 'The coupon code \'%code\' already exists. Please choose another coupon code' => 'Kode kupon \'%code\' sudah ada. Silakan pilih lain kode kupon', + 'The coupon is valid after a given date' => 'Kode kupon hanya berlaku setelah Tanggal tertentu', + 'The date after which sales are de-activated. Please use %fmt format.' => 'Tanggal setelah penjualan de-diaktifkan. Gunakan %fmt format.', + 'The date from which sales are active. Please use %fmt format.' => 'Tanggal yang penjualan aktif. Gunakan %fmt format.', + 'The file %path has been successfully downloaded' => 'File %path telah berhasil download', + 'The following columns are missing: %columns' => 'Kolom berikut hilang: %columns', + 'The image which replaces an undefined country flag (%file) was not found. Please check unknown-flag-path configuration variable, and check that the image exists.' => 'Gambar yang menggantikan bendera negara (%file) tidak ditemukan. Silakan periksa konfigurasi tidak diketahui-bendera-jalan variabel, dan periksa bahwa ada gambar.', + 'The language "%id" doesn\'t exist' => 'Tidak ada bahasa "%id"', + 'The mailing template in HTML format.' => 'Template mailing dalam HTML format.', + 'The mailing template in text-only format.' => 'Template mailing dalam format hanya-teks.', + 'The method name that will handle the hook event.' => 'Nama metode yang akan menangani acara hook.', + 'The module "%name%" is currently in use by at least one order, and can\'t be deleted.' => 'Modul "%name%" yang saat ini digunakan oleh setidaknya satu urutan, dan tidak dapat dihapus.', + 'The module %module has been installed successfully.' => 'Modul % modul telah berhasil diinstall.', + 'The module %name is already installed in the same or greater version.' => '%name modul telah terinstal di versi yang sama atau lebih besar.', + 'The module %name requires Thelia %version or newer' => 'Modul %name memerlukan Thelia % versi atau yang lebih baru', + 'The module has to be activated.' => 'Modul yang harus diaktifkan.', + 'The module is not valid : %message' => 'Modul ini tidak valid: pesan %', + 'The module zip file' => 'File zip modul', + 'The product document id %id doesn\'t exists' => 'Produk id dokumen %id tidak ada', + 'The product image id %id doesn\'t exists' => 'Tidak ada gambar produk id %id', + 'The product sale element id %id doesn\'t exist' => 'Tidak ada produk dijual elemen id %id', + 'The product sale elements id %id doesn\'t exist' => 'Tidak ada produk dijual elemen id %id', + 'The product sale elements id %id doesn\'t exists' => 'Id produk dijual unsur %id tidak ada', + 'The resource %res has not been found' => 'Res % sumber daya belum ditemukan', + 'The sale announce label, such as Sales ! or Flash Sales !' => 'Penjualan mengumumkan label, seperti penjualan! atau Flash penjualan!', + 'The sale name or descriptive title' => 'Nama jualan atau judul deskriptif', + 'The sale name or title' => 'Nama jualan atau judul', + 'The service id that will handle the hook (defined in the config.xml file of the module).' => 'Id layanan yang akan menangani hook (didefinisikan dalam file config.xml pada modul).', + 'The store fax number.' => 'Nomor Faks toko.', + 'The store phone number.' => 'Nomor telepon toko.', + 'The type %type is not valid' => 'Tipe %type ini tidak valid', + 'There are no files to associate.' => 'Tidak ada file untuk mengasosiasi.', + 'There is no id "%id" in the export categories' => 'Tidak ada id "%id" dalam kategori ekspor', + 'There is no id "%id" in the exports' => 'Tidak ada id "%id" dalam ekspor', + 'There is no id "%id" in the import categories' => 'Tidak ada id "%id" dalam kategori impor', + 'There is no id "%id" in the imports' => 'Tidak ada id "%id" dalam impor', + 'There\'s a conflict between your file extension "%ext" and the mime type "%mime"' => 'Ada konflik antara ekstensi file Anda "%ext" dan jenis mime "% mime"', + 'This PHP extension should be installed and loaded.' => 'Ekstensi PHP harus dipasang dan dimuat.', + 'This brand is online' => 'Merek ini online', + 'This category is online' => 'Kategori ini online', + 'This condition is always true' => 'Kondisi ini selalu benar', + 'This content is online.' => 'Konten ini online.', + 'This coupon adds a free product to the cart if one of the selected products is in the cart.' => 'Kupon ini menambahkan produk gratis ke keranjang jika salah satu produk telah dipilih.', + 'This coupon does not exists' => 'Voucher tidak ditemukan', + 'This coupon subtracts from the order total a percentage of the price of each product which belongs to the selected categories. If the discount is greater than the total order, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.' => 'Kupon ini mengurangi sejumlah nilai persentase dari harga setiap produk yang berada pada kategori tertentu. Jika diskon lebih besar dari pada total pesanan, pembeli hanya akan membayar biaya pengiriman, bahkan bisa gratis jika kupon ini juga menawarkan antar gratis.', + 'This coupon subtracts from the order total the specified percentage of each product price which uses the selected attribute values. If the discount is greater than the total order, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.' => 'Kupon ini mengurangi sejumlah nilai persentase harga setiap produk secara spesifik dari total pesanan yang berada pada atribut tertentu. Jika diskon lebih besar dari pada total pesanan, pembeli hanya akan membayar biaya pengiriman, bahkan bisa gratis jika kupon ini juga menawarkan antar gratis.', + 'This coupon subtracts from the order total the specified percentage of each selected product price. If the discount is greater than the total order, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.' => 'Kupon ini mengurangi sejumlah nilai persentase harga setiap produk tertentu dari total pesanan. Jika diskon lebih besar dari pada total pesanan, pembeli hanya akan membayar biaya pengiriman, bahkan bisa gratis jika kupon ini juga menawarkan antar gratis.', + 'This coupon subtracts the specified amount from the order total for each product which belongs to the selected categories. If the discount is greater than the total order, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.' => 'Kupon ini mengurangi sejumlah nilai persentase harga setiap produk secara spesifik dari total pesanan yang berada pada kategori yang dipilih. Jika diskon lebih besar dari pada total pesanan, pembeli hanya akan membayar biaya pengiriman, bahkan bisa gratis jika kupon ini juga menawarkan antar gratis.', + 'This coupon subtracts the specified amount from the order total for each product which uses the selected attribute values. If the discount is greater than the total order, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.' => 'Kupon ini mengurangi sejumlah nilai persentase harga setiap produk secara spesifik dari total pesanan yang berada pada atribut yang dipilih. Jika diskon lebih besar dari pada total pesanan, pembeli hanya akan membayar biaya pengiriman, bahkan bisa gratis jika kupon ini juga menawarkan antar gratis.', + 'This coupon subtracts the specified amount from the order total for each selected product. If the discount is greater than the total order, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.' => 'Kupon ini mengurangi sejumlah nilai persentase harga setiap produk tertentu dari total pesanan. Jika diskon lebih besar dari pada total pesanan, pembeli hanya akan membayar biaya pengiriman, bahkan bisa gratis jika kupon ini juga menawarkan antar gratis.', + 'This coupon will offert a flat percentage off a shopper\'s entire order (not applied to shipping costs or tax rates). If the discount is greater than the total order corst, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.' => 'This coupon will offert a flat percentage off a shopper\'s entire order (not applied to shipping costs or tax rates). If the discount is greater than the total order corst, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.', + 'This coupon will subtracts a set amount from the total cost of an order. If the discount is greater than the total order corst, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.' => 'This coupon will subtracts a set amount from the total cost of an order. If the discount is greater than the total order corst, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.', + 'This document is online' => 'Dokumen ini online', + 'This email already exists.' => 'Email ini sudah ada.', + 'This email does not exists' => 'Email ini tidak ada', + 'This folder is online.' => 'Folder ini online.', + 'This hook is specific to a module (delivery/payment modules).' => 'Hook ini khusus untuk sebuah modul (modul pengiriman/pembayaran).', + 'This image is online' => 'Gambar ini online', + 'This is a comma separated list of email addresses where store notifications (such as order placed) are sent.' => 'Ini adalah daftar yang dipisahkan koma dari alamat email di mana pemberitahuan toko (seperti penempatan pesanan) dikirim.', + 'This is an identifier that will be used in the code to get this message' => 'Ini adalah sebuah identifier yang digunakan dalam kode untuk mendapatkan pesan ini', + 'This is the contact email address, and the sender email of all e-mails sent by your store.' => 'Ini adalah alamat kontak email, dan pengirim email dari semua e-mail yang dikirim oleh toko Anda.', + 'This is the message purpose, such as \'Order confirmation\'.' => 'Tujuan pesan ini, seperti \'Konfirmasi Pesanan\'.', + 'This is the subject of the e-mail, such as \'Your order is confirmed\'.' => 'Ini adalah subyek e-mail, seperti \'pesanan Anda dikonfirmasi\'.', + 'This module has no Markdown documentation.' => 'Modul ini tidak memiliki dokumentasi Markdown.', + 'This product does not have a physical presence' => 'Produk ini tidak memiliki bentuk fisik', + 'This product is on sale' => 'Produk ini dijual', + 'This product is online' => 'Produk ini online', + 'This product reference is already assigned to another product.' => 'Referensi produk ini sudah ditetapkan pada produk yang lain.', + 'This product_sale_elements_id does not exists for this product : %d' => 'Product_sale_elements_id ini tidak ada untuk produk ini: %d', + 'This template is in use in some of your products, and cannot be deleted. Delete it from all your products and try again.' => 'Templat ini digunakan dalam beberapa produk Anda, dan tidak dapat dihapus. Hapus templat ini dari semua produk Anda dan coba lagi.', + 'This the unique name of this message. Do not change this value unless you understand what you do.' => 'Ini nama unik dari pesan. Jangan mengubah nilai ini kecuali Anda memahami apa yang Anda lakukan.', + 'This value should not be blank.' => 'Nilai tidak boleh kosong.', + 'Title *' => 'Judul *', + 'Title ID not found' => 'ID judul tidak ditemukan', + 'To activate module %name, the following modules should be activated first: %modules' => 'Untuk mengaktifkan modul %name, modul berikut harus diaktifkan terlebih dahulu: modul %', + 'Translations' => 'Alih Bahasa', + 'Tried to download a file, but the URL was not valid: %url' => 'Mencoba untuk men-download file, tapi URL itu tidak sah: %url', + 'Type' => 'Tipe', + 'URL_ALREADY_EXISTS' => 'URL ini sudah ada', + 'Unable to get module code from the fullnamespace element of the module descriptor: \'%val\'' => 'Mampu mendapatkan kode modul dari unsur fullnamespace Deskripsi modul: \' % val\'', + 'Unable to process your request. Please try again (%err).' => 'Tidak dapat memproses permintaan Anda. Silakan coba lagi (%err).', + 'Unconditional usage' => 'Unconditionnal usage', + 'Unconditionnal usage' => 'Unconditionnal usage', + 'Undefined loop argument "%name"' => 'Argumen undefined loop "%name"', + 'Undefined search mode \'%mode\'' => 'Moda undefined pencarian \'% mode\'', + 'Unknown order ID: %id' => 'Tidak diketahui order ID: %id', + 'Unsupported magic method %name. only getArgname() is supported.' => '%name metode sihir yang didukung. getArgname() hanya didukung.', + 'Unsupported type' => 'Jenis yang tidak didukung', + 'Update customer account' => 'Memperbarui rekening nasabah', + 'Use the keyword phrase in your URL.' => 'Menggunakan frase kata kunci dalam URL Anda.', + 'Used in your store front' => 'Digunakan di depan toko Anda', + 'Valid only from %date% to the coupon expiration date' => 'Valid hanya dari %date% hingga tanggal kadaluarsa kupon', + 'Value %val for Discount Amount is invalid. Please enter a positive value.' => 'Nilai % val untuk Diskon Terbaik untuk jumlah tidak valid. Masukkan nilai positif.', + 'Value %val for Percent Discount is invalid. Please enter a positive value between 1 and 100.' => 'Nilai % val untuk diskon persen terbaik untuk tidak valid. Masukkan nilai positif antara 1 dan 100.', + 'Value *' => 'Nilai *', + 'Value create form' => 'Nilai penciptaan bentuk', + 'Variable' => 'Variabel', + 'Variables' => 'Variabel', + 'Virtual document' => 'Virtual dokumen', + 'Warnings' => 'Peringatan', + 'We\'re sorry, this PDF invoice is not available at the moment.' => 'Kami minta maaf, faktur PDF ini tidak tersedia saat ini.', + 'Weight' => 'Berat', + 'Wrong form method, %s expected.' => 'Metode salah bentuk, %s yang diharapkan.', + 'Yes, I have a password :' => 'Ya, saya memiliki password:', + 'You are already registered!' => 'Anda sudah terdaftar!', + 'You don\'t need to use commas or other punctuations.' => 'Anda tidak perlu menggunakan koma atau tanda lain.', + 'You have to configure your store email first !' => 'Anda harus mengkonfigurasi email toko Anda pertama!', + 'You\'ve submitted this form too many times. ' => 'Anda telah mengirimkan formulir ini terlalu banyak kali. ', + 'Your Email Address' => 'Alamat Email Anda', + 'Your Message' => 'Pesan Anda', + 'Your configuration seems to be ok. Checked out your mailbox : %email%' => 'Konfigurasi Anda tampaknya ok. Memeriksa kotak pesan: %email%', + 'Your current password does not match.' => 'Password Anda saat ini tidak cocok.', + 'Your zip must contain 1 root directory which is the root folder directory of your module' => 'Anda zip harus berisi 1 direktori root yang merupakan direktori root folder dari modul', + 'Zone' => 'Wilayah', + 'accessories table header' => 'header tabel aksesoris', + 'accessories table row' => 'baris tabel aksesoris', + 'add to all form' => 'tambahkan ke semua bentuk', + 'additional information' => 'Informasi Tambahan', + 'address create form' => 'formulir buatan alamat', + 'address delete form' => 'forulir menghapusan alamat', + 'address update form' => 'formulir pembaruan alamat', + 'after addresse area' => 'area setelah alamat', + 'after combinations' => 'setelah kombinasi', + 'after footer' => 'setelah footer', + 'after javascript include' => 'setelah tercakup javascript', + 'after javascript initialisation' => 'setelah inisialisasi javascript', + 'after product listing' => 'setelah daftar produk', + 'after the information area' => 'setelah area informasi', + 'after the main content area' => 'setelah area konten utama', + 'after the opening of the body tag' => 'setelah pembukaan tag body', + 'after the opening of the head tag' => 'setelah pembukaan tag head', + 'after the order summary' => 'setelah ringkasan pesanan', + 'after top bar' => 'setelah bar bagian atas', + 'after top menu' => 'setelah menu bagian atas', + 'api id %id does not exists' => 'api id %id tidak ada', + 'at the bottom' => 'di bagian bawah', + 'at the bottom of column 1' => 'di bagian bawah dari kolom 1', + 'at the bottom of information area' => 'di bawah area informasi', + 'at the bottom of the catalog' => 'di bagian bawah Katalog', + 'at the bottom of the detail area' => 'di bagian bawah area detail', + 'at the bottom of the footer' => 'di bagian bawah footer', + 'at the bottom of the form' => 'di bagian bawah formulir', + 'at the bottom of the header' => 'di bagian bawah header', + 'at the bottom of the main area' => 'di bagian bawah area utama', + 'at the bottom of the shipping area' => 'di bagian bawah area pengiriman', + 'at the bottom of the sidebar' => 'di bagian bawah bilah sisi', + 'at the bottom of the system area' => 'di bagian bawah area sistem', + 'at the bottom of the top bar' => 'di bagian bawah bilah atas', + 'at the top' => 'di bagian atas', + 'at the top of the catalog area' => 'di bagian atas area katalog', + 'at the top of the column' => 'di bagian atas kolom', + 'at the top of the configuration' => 'di bagian atas konfigurasi', + 'at the top of the detail' => 'di bagian atas detil', + 'at the top of the footer' => 'di bagian atas footer', + 'at the top of the form' => 'di bagian atas formulir', + 'at the top of the header' => 'di bagian atas header', + 'at the top of the main area' => 'di bagian atas area utama', + 'at the top of the shipping area' => 'di bagian atas area pengiriman', + 'at the top of the sidebar' => 'di bagian atas bilah sisi', + 'at the top of the system area' => 'di bagian atas area sistem', + 'at the top of the top bar' => 'di bagian atas bilah atas', + 'attributes table header' => 'atribut header tabel', + 'attributes table row' => 'atribut baris tabel', + 'before combinations' => 'sebelum kombinasi', + 'before footer' => 'sebelum footer', + 'before the end body tag' => 'sebelum tag body', + 'before the end of the head tag' => 'sebelum akhir tag head', + 'before the main content area' => 'sebelum area konten utama', + 'before top menu' => 'sebelum menu paling atas', + 'before topbar' => 'sebelum topbar', + 'block' => 'blok', + 'bottom' => 'bawah', + 'bottom of the footer' => 'bawah footer', + 'cURL errno %errno, http code %http_code on link "%path": %error' => 'cURL errno %errno, kode http http_code % pada link "%path": %error', + 'caption' => 'Keterangan', + 'categories table header' => 'header tabel Kategori', + 'categories table row' => 'baris tabel Kategori', + 'combination delete form' => 'formulir penghapusan kombinasi', + 'combinations list caption' => 'kombinasi daftar Keterangan', + 'configuration' => 'konfigurasi', + 'configuration JavaScript' => 'konfigurasi JavaScript', + 'configuration bottom' => 'konfigurasi bawah', + 'content' => 'konten', + 'content area' => 'area konten', + 'content delete form' => 'formulir penghapusan konten', + 'content edit JavaScript' => 'mengedit konten JavaScript', + 'contents table header' => 'isi judul tabel', + 'contents table row' => 'isi baris tabel', + 'context' => 'konteks', + 'country delete form' => 'formulir penghapusan negara', + 'create JavaScript' => 'membuat JavaScript', + 'create form' => 'formulir kreasi', + 'customer account' => 'akun pelanggan', + 'date format' => 'format tanggal', + 'decimal separator' => 'pemisah desimal', + 'delete form' => 'hapus formulir', + 'delivery address' => 'alamat pengiriman', + 'delivery module %s is not a Thelia\Module\DeliveryModuleInterface' => 'modul pengiriman %s bukan Thelia\Module\DeliveryModuleInterface', + 'details pricing form' => 'formulir detal harga', + 'details promotion form' => 'formulir detal promosi', + 'email' => 'email', + 'email confirmation is not the same as email field' => 'Dua alamat email tidak identik', + 'email system JavaScript' => 'sistem email JavaScript', + 'extra area' => 'area tambahan', + 'extra payment zone' => 'zona pembayaran ekstra', + 'features table row' => 'baris tabel fitur', + 'features-table-header' => 'kepala-tabel-fitur', + 'folders table header' => 'header tabel folder', + 'folders table row' => 'folder baris tabel', + 'footer body' => 'isi footer', + 'header' => 'kepala', + 'hook delete form' => 'formulir pengjapusan hook', + 'hook edit JavaScript' => 'mengedit hook JavaScript', + 'hour(s)' => 'jam', + 'id delete form' => 'formulir penghapusan id', + 'if successful response' => 'respon jika sukses', + 'imprint' => 'jejak', + 'in footer' => 'di footer', + 'in the header' => 'di header', + 'in the menu catalog' => 'dalam menu Katalog', + 'in the menu configuration' => 'dalam menu konfigurasi', + 'in the menu customers' => 'dalam menu pelanggan', + 'in the menu folders' => 'di dalam menu folder', + 'in the menu modules' => 'di dalam menu modul', + 'in the menu orders' => 'di dalam menu pesanan', + 'in the menu tools' => 'di dalam menu peralatan', + 'in top menu items' => 'di atas menu item', + 'inside top bar' => 'di dalam bar bagian atas', + 'javascript' => 'javascript', + 'javascript initialization' => 'inisiasi javascript', + 'label' => 'label', + 'language locale' => 'bahasa lokal', + 'language selection page' => 'halaman pilih bahasa', + 'list JavaScript' => 'daftar JavaScript', + 'list caption' => 'daftar Keterangan', + 'list header' => 'daftar header', + 'list row' => 'daftar baris', + 'logs JavaScript' => 'catatan JavaScript', + 'mailing system modification' => 'modifikasi sistem pesan', + 'main area' => 'area utama', + 'middle' => 'tengah', + 'minute(s)' => 'menit', + 'password confirmation is not the same as password field' => 'konfirmasi password adalah tidak sama dengan sandi yang diketik', + 'password must be composed of at least 4 characters' => 'kata sandi minimal 4 karakter', + 'payment module %s is not a Thelia\Module\PaymentModuleInterface' => 'modul pembayaran %s bukan Thelia\Module\PaymentModuleInterface', + 'pdf' => 'pdf', + 'permanent discount (in percent)' => 'diskon tetap (dalam persen)', + 'photo gallery' => 'galeri foto', + 'plain, login, cram-md5 or empty' => 'polos, login, cram-md5 atau kosong', + 'primary navigation' => 'navigasi utama', + 'product list' => 'daftar produk', + 'quantity value is not valid' => 'jumlah tidak valid', + 'remove to all form' => 'hapus pada semua formulir', + 'row' => 'baris', + 'rule create form' => 'aturan pembuatan formulir', + 'rule delete form' => 'aturan penghapusan formulir', + 'rule edit JavaScript' => 'aturan mengedit JavaScript', + 'secondary navigation' => 'navigasi sekunder', + 'ssl, tls or empty' => 'ssl, tls atau kosong', + 'stock edit form' => 'formulir mengedit stok', + 'table header' => 'header tabel', + 'table row' => 'baris tabel', + 'tax rule' => 'peraturan pajak', + 'the body of the sidebar' => 'di dalam bilah sisi', + 'this product id does not exists : %d' => 'id produk ini tidak ada: %d', + 'thousands separator' => 'pemisah ribuan', + 'time format' => 'format waktu', + 'type' => 'tipe', + 'update JavaScript' => 'pembaruan JavaScript', + 'update form' => 'perbarui formulir', + 'value table header' => 'isi header tabel', + 'value table row' => 'isi baris tabel', +]; diff --git a/core/lib/Thelia/Config/I18n/it_IT.php b/core/lib/Thelia/Config/I18n/it_IT.php new file mode 100644 index 00000000..113a575b --- /dev/null +++ b/core/lib/Thelia/Config/I18n/it_IT.php @@ -0,0 +1,297 @@ + ' modulo di creazione contenuti', + ' note: only non-visible documents can be associated.' => ' Nota: solo i documenti non visibili possono essere associati.', + '%n for number, %c for the currency code, %s for the currency symbol' => '%n per numero, %c per il codice valuta, %s per il simbolo della valuta', + '%obj SEO modification' => 'modifiche SEO %obj', + '%obj creation' => 'creazione di %obj ', + '%obj modification' => 'modifica %obj', + 'A currency with code "%name" already exists.' => 'Una moneta con il codice "%name" esiste già.', + 'A descriptive title' => 'Un titolo descrittivo', + 'A message with name "%name" already exists.' => 'Un messaggio con il nome "%name" esiste già.', + 'A short description, used when a summary or an introduction is required' => 'Una breve descrizione, utilizzata quando è necessario un sommario o un\'introduzione', + 'A variable with name "%name" already exists.' => 'Una variabile con il nome "%name" esiste già.', + 'Activate logs only for these IP Addresses' => 'Attivare log solo per questi indirizzi IP', + 'Activate logs only for these files' => 'Attivare log solo per questi file', + 'Active' => 'Attivo', + 'Add to all product templates' => 'Aggiungere a tutti i template che riguardano i prodotti', + 'Additional address' => 'Indirizzo aggiuntivo', + 'Address Line 2' => 'Indirizzo linea 2', + 'Address Line 3' => 'Indirizzo linea 3', + 'Address label' => 'Etichetta dell\'indirizzo', + 'Address update' => 'Aggiornamento dell\' indirizzo', + 'Address.' => 'Indirizzo.', + 'Addresses for this country need a zip code' => 'Gli indirizzi per questo paese hanno bisogno di un codice postale', + 'Administrator' => 'Amministratore', + 'Administrator email address' => 'Indirizzo email amministratore', + 'Administrators' => 'Amministratori', + 'Advertise this product as new' => 'Pubblicizzare questo prodotto come nuovo', + 'Alerts' => 'Avvisi', + 'All Products' => 'Tutti i prodotti', + 'All countries' => 'Tutti i paesi', + 'Amount' => 'Importo', + 'An administrator with this email address already exists' => 'Un amministratore con questo indirizzo email esiste già', + 'An invalid token was provided, your password cannot be changed' => 'È stato fornito un token non valido, la password non può essere modificata', + 'Apply exchange rates on price in %sym' => 'Applicare i tassi di cambio sui prezzi in %sym', + 'Attribute ID:Attribute AV ID' => 'Attribute ID:Attribute AV ID', + 'Attributes' => 'Declinazioni', + 'Auth mode' => 'Auth mode', + 'Available quantity' => 'Quantità disponibile', + 'Available quantity *' => 'Quantità disponibile *', + 'Billing country is' => 'Il paese di fatturazione è', + 'Brands' => 'Brands', + 'Business ID' => 'Business ID', + 'By Module' => 'Per modulo', + 'CSS' => 'CSS', + 'Cannot disable the default language' => 'Non è possibile disabilitare la lingua predefinita', + 'Cannot find a default country. Please define one.' => 'Non riusciamo a trovare un paese predefinito. Per favore, definirne uno.', + 'Cannot find the shop country. Please select a shop country.' => 'Non riusciamo a trovare il paese di negozio. Si prega di selezionare un paese per il negozio.', + 'Cart' => 'Carrello', + 'Catalog' => 'Catalogo', + 'Categories' => 'Categorie', + 'Category' => 'Categoria', + 'Category title' => 'Titolo della categoria', + 'Cellphone' => 'Cellulare', + 'Change password' => 'Cambia password', + 'City' => 'Città', + 'Code' => 'Codice', + 'Combination builder' => 'Generatore di combinazione', + 'Compagny' => 'Azienda', + 'Company' => 'Azienda', + 'Company Name' => 'Nome della società', + 'Conclusion' => 'Conclusione', + 'Configuration' => 'Impostazioni', + 'Confirm Email Address' => 'Conferma il tuo indirizzo email', + 'Confirm Email address' => 'Conferma il tuo indirizzo email', + 'Constant amount' => 'Importo costante', + 'Constant amount found in one of the product\'s feature' => 'Importo costante trovato in una delle caratteristiche del prodotto', + 'Contact page' => 'Pagina contatti', + 'Content' => 'Contenuto', + 'Content page' => 'Contenuto della pagina', + 'Content title *' => 'Titolo del contenuto *', + 'Contents' => 'Contenuti', + 'Countries' => 'Paesi', + 'Country' => 'Paese', + 'Country title' => 'Titolo del paese', + 'Coupon' => 'Promozione', + 'Critical' => 'Critico', + 'Currencies' => 'Monete', + 'Currency' => 'Valuta', + 'Currency name' => 'Nome della moneta', + 'Current Password' => 'Password attuale', + 'Customer' => 'Cliente', + 'Customers' => 'Clienti', + 'Dashboard' => 'Dashboard', + 'Debug' => 'Eseguire il debug', + 'Default folder *' => 'Cartella predefinita *', + 'Default product category *' => 'Categoria di prodotto predefinita *', + 'Default product sale element' => 'Elemento predefinito di vendita per il prodotto', + 'Detailed description' => 'Descrizione dettagliata', + 'Disabled' => 'Disattivato', + 'Document' => 'Documento', + 'Don\'t repeat keywords over and over in a row. Rather, put in keyword phrases.' => 'Non ripetere parole chiavi più e più volte di fila. Piuttosto, mettere in frasi chiave.', + 'EAN Code' => 'Codice EAN', + 'Edit' => 'Modifica', + 'Email Address' => 'Indirizzo email', + 'Email address' => 'Indirizzo email', + 'Emergency' => 'Emergenza', + 'Enable remote SMTP use' => 'Abilitare l\'utilizzo di un SMTP remoto', + 'Encryption' => 'Crittografia', + 'Enter the new password' => 'Inserisci la nuova password', + 'Enter the new password again' => 'Reinserisci la nuova password', + 'Errors' => 'Errori', + 'Export' => 'Esporta', + 'Failed to update language definition: %ex' => 'Impossibile aggiornare la definizione del linguaggio: %ex', + 'Fax' => 'Fax', + 'Feature value does not match FLOAT format' => 'Il valore della caratteristica non corrisponde al formato FLOAT', + 'Features' => 'Caratteristiche', + 'First Name' => 'Nome', + 'Firstname' => 'Nome', + 'Folder' => 'Cartella', + 'Folder page' => 'Pagina cartella', + 'Folder title *' => 'Titolo della cartella *', + 'Front Office' => 'Front Office', + 'Full Name' => 'Nome e cognome', + 'HTML Message' => 'Messaggio HTML', + 'HTML layout' => 'Layout HTML', + 'Home' => 'Home', + 'Home page' => 'Home page', + 'Hook' => 'Hook', + 'Host' => 'Host', + 'I would like to receive the newsletter or the latest news.' => 'Vorrei ricevere la newsletter o le ultime notizie.', + 'ISO 4217 code' => 'Codice ISO 4217', + 'ISO 639-1 Code' => 'Codice ISO 639-1', + 'ISO Code' => 'Codice ISO', + 'If a translation is missing or incomplete :' => 'Se una traduzione è incompleta o mancante:', + 'Image' => 'Immagine', + 'Information' => 'Informazioni', + 'Invalid product_sale_elements' => 'Product_sale_elements non valido', + 'Invalid username or email.' => 'Nome utente o password non validi.', + 'Invalid value for walkMode parameter: %value' => 'Valore non valido per il parametro walkMode: %value', + 'Is it the default product sale element ?' => 'È l\'elemento predefinito di vendita del prodotto?', + 'Keep the most important part of your description in the first 150-160 characters.' => 'Tenere la parte più importante della tua descrizione nei primi 150-160 caratteri.', + 'Language' => 'Lingua', + 'Language name' => 'Nome della lingua', + 'Languages' => 'Lingue', + 'Last Name' => 'Cognome', + 'Lastname' => 'Cognome', + 'Log format *' => 'Formato di registro *', + 'Log level *' => 'Livello del registro *', + 'Login failed. Please check your username and password.' => 'Accesso non riuscito. Si prega di controllare il nome dell\'utente e la password.', + 'Login name' => 'Nome login', + 'Mailing system' => 'Sistema di mailing', + 'Make sure it uses keywords found within the page itself.' => 'Assicurarsi che utilizza parole chiavi trovate all\'interno della pagina stessa.', + 'Make sure that your title is clear, and contains many of the keywords within the page itself.' => 'Assicurarsi che il titolo è chiaro e contiene molte delle parole chiave all\'interno della pagina stessa.', + 'Make this address as my primary address' => 'Fare questo indirizzo come mio indirizzo primario', + 'Message subject' => 'Oggetto del messaggio', + 'Meta Description' => 'Meta descrizione', + 'Meta Keywords' => 'Meta Keywords', + 'Module' => 'Modulo', + 'Modules' => 'Moduli', + 'More information about ISO 4217' => 'Ulteriori informazioni su ISO 4217', + 'Name' => 'Nome', + 'Name *' => 'Nome *', + 'Name of the HTML layout file' => 'Nome del layout HTML', + 'Name of the HTML template file' => 'Nome del file del template HTML', + 'Name of the text layout file' => 'Nome del file del layout del testo', + 'Name of the text template file' => 'Nome del testo del file del template', + 'New Password' => 'Nuova Password', + 'No %obj was created.' => 'È stato creato nessuno %obj.', + 'No %obj was updated.' => 'Nessun %obj è stato aggiornato.', + 'No, I am a new customer.' => 'No, sono un nuovo cliente.', + 'Notices' => 'Avvisi', + 'Orders' => 'Ordini', + 'Page Title' => 'Titolo della pagina', + 'Parent folder *' => 'Cartella superiore *', + 'Password' => 'Password', + 'Password *' => 'Password *', + 'Password confirmation' => 'Conferma della password', + 'Percentage of the product price' => 'Percentuale del prezzo del prodotto', + 'Phone' => 'Telefono', + 'Please enter a valid email address' => 'Si prega di inserire un indirizzo email valido', + 'Please enter your email address' => 'Inserisci il tuo indirizzo email', + 'Please enter your password' => 'Per favore inserisci la password', + 'Port' => 'Spedizione', + 'Postage' => 'Spese di spedizione', + 'Preferred locale' => 'Impostazioni internazionali preferite', + 'Prevent mailing template modification or deletion, except for super-admin' => 'Prevenire modifiche o cancellazione del template di mailing, ad eccezione del super-admin', + 'Prevent variable modification or deletion, except for super-admin' => 'Prevenire modifiche o cancellazione della variabile, ad eccezione del super-admin', + 'Price currency *' => 'Prezzo della moneta *', + 'Prodcut ID *' => 'ID prodotto *', + 'Product' => 'Prodotto', + 'Product ID' => 'ID prodotto', + 'Product ID *' => 'ID Prodotto *', + 'Product attributes' => 'Attributi del prodotto', + 'Product base price excluding taxes *' => 'Prezzo di base del prodotto escluse le tasse *', + 'Product price excluding taxes' => 'Prezzo del prodotto escluse le tasse', + 'Product price excluding taxes *' => 'Prezzo del prodotto escluse le tasse *', + 'Product price including taxes' => 'Prezzo del prodotto tasse incluse', + 'Product reference *' => 'Riferimento del prodotto *', + 'Product sale element ID *' => 'ID del prodotto venduto *', + 'Product template' => 'Template del prodotto', + 'Product title' => 'Titolo del prodotto', + 'ProductSaleElement modification' => 'modifica del ProductSaleElement', + 'Products' => 'Prodotti', + 'Profile' => 'Profilo', + 'Profile Code' => 'Codice del profilo', + 'Profiles' => 'Profili', + 'Purpose' => 'Scopo', + 'Purpose *' => 'Scopo *', + 'Quantity' => 'Quantità', + 'Rate' => 'Tasso', + 'Redirecting ...' => 'Reindirizzamento ...', + 'Redirecting to %url' => 'Reindirizzamento a %url', + 'Reference' => 'Riferimento', + 'Reference *' => 'Riferimento *', + 'Register' => 'Registrati', + 'Remember me ?' => 'Ricordati di me?', + 'Remove X percent to total cart' => 'Rimuovi X percento al totale del carrello', + 'Replace by the default language' => 'Sostituire la lingua predefinita', + 'Replace current document by this file' => 'Sostituire l\'attuale documento da questo file', + 'Replace current image by this file' => 'Sostituire l\'immagine per questo file', + 'Rewriten URL' => 'URL riscritta', + 'Rotated Text File' => 'File di testo ruotato', + 'Sale price excluding taxes' => 'Prezzo scontato escluse le tasse', + 'Sale price including taxes' => 'Prezzo scontato tasse incluse', + 'Search' => 'Ricerca', + 'Shipping configuration' => 'Configurazione di spedizione', + 'Show redirections *' => 'Visualizza redirezioni *', + 'Sorry, an error occured: %msg' => 'Siamo spiacenti, errore: %msg', + 'Sorry, no email defined for this administrator.' => 'Siamo spiacenti, nessuna email è stata definita per questo amministratore.', + 'Sorry, you are not allowed to perform this action.' => 'Siamo spiacenti, non è consentito eseguire questa azione.', + 'Sorry, you\'re not allowed to perform this action' => 'Siamo spiacenti, non sei autorizzato ad eseguire questa azione', + 'Source IP' => 'IP di origine', + 'State *' => 'Stato *', + 'State ID %id not found' => 'Stato ID %id non trovato', + 'Stock' => 'Magazzino', + 'Store Business Identification Number (SIRET, etc).' => 'Memorizzare il numero di identificazione del Business (SIRET, ecc).', + 'Store configuration failed.' => 'La registrazione della configurazione è fallita.', + 'Store description' => 'Descrizione del negozio', + 'Store email address' => 'Indirizzo email del negozio', + 'Store logs into text file' => 'Archiviare i log in un file di testo', + 'Store logs into text file, up to a certian size, then a new file is created' => 'Archiviare i log in un file di testo, fino ad una certa dimensione, dopo viene creato un nuovo file', + 'Store name' => 'Nome del negozio', + 'Street Address' => 'Indirizzo', + 'Street Address ' => 'Indirizzo ', + 'Strictly use the requested language' => 'Utilizzare rigorosamente la lingua richiesta', + 'Subject' => 'Oggetto', + 'Summary' => 'Riassunto', + 'Symbol' => 'Simbolo', + 'System log configuration failed.' => 'Non e riuscito la configurazione del registro di sistema.', + 'Tax' => 'Tassa', + 'Tax rule for this product *' => 'Regola fiscale per questo prodotto *', + 'Taxes' => 'Tasse', + 'Taxes rules' => 'Regole fiscale', + 'Template Name *' => 'Nome del template *', + 'Templates' => 'Template', + 'Text File' => 'File di testo', + 'Text Message' => 'Messaggio di testo', + 'The HTML TITLE element is the most important element on your web page.' => 'Il HTML TITLE è l\'elemento più importante nella tua pagina web.', + 'The detailed description.' => 'La descrizione dettagliata.', + 'The mailing template in HTML format.' => 'Il template del e-mail in formato HTML.', + 'The mailing template in text-only format.' => 'Il template del e-mail in formato testo solo.', + 'The zip code format' => 'Il formato del codice postale', + 'There is no id "%ref" in the imports' => 'Non c\'è nessun id "%ref" nelle importazioni', + 'There is no ref "%ref" in the exports' => 'Non c\'è nessun rif "%ref" nelle esportazioni', + 'This administrator login already exists' => 'Questo account di accesso amministratore esiste già', + 'This content is online.' => 'Questo contenuto è online.', + 'This country has states / provinces' => 'Questo paese ha stati / province', + 'This country is online' => 'Questo paese è online', + 'This folder is online.' => 'Questa cartella è online.', + 'This is the message purpose, such as \'Order confirmation\'.' => 'Questo è lo scopo del messaggio, ad esempio \'Conferma dell\'ordine\'.', + 'This is the name used on the login screen' => 'Questo è il nome utilizzato nella schermata di login', + 'This is the subject of the e-mail, such as \'Your order is confirmed\'.' => 'Questo è l\'oggetto dell\'e-mail, come \'l\'ordine è confermato\'.', + 'This product is on sale' => 'Questo prodotto è in vendita', + 'This product is online' => 'Questo prodotto è online', + 'This state doesn\'t belong to this country.' => 'Questo stato non appartiene a questo paese.', + 'This state is online' => 'Questo stato è online', + 'This the unique name of this message. Do not change this value unless you understand what you do.' => 'Questo è il nome unico di questo messaggio. Non modificare questo valore a meno che non si capisce cosa fare.', + 'This zip code should respect the following format : %format.' => 'Questo codice postale deve rispettare il seguente formato: %format.', + 'Timeout' => 'Timeout', + 'Title' => 'Titolo', + 'Title *' => 'Titolo *', + 'Tools' => 'Strumenti', + 'Type' => 'Tipo', + 'Use a N for a number, L for Letter, C for an iso code for the state.' => 'Utilizza una N per un numero, L per una lettera, C per un codice iso dello stato.', + 'Use the keyword phrase in your URL.' => 'Utilizzare la frase chiave nell\'URL.', + 'Used in your store front' => 'Utilizzate nel vostro negozio', + 'Username' => 'Nome utente', + 'Username or e-mail address *' => 'Nome utente o indirizzo e-mail *', + 'Value' => 'Valore', + 'Value *' => 'Valore *', + 'Warnings' => 'Avvertenze', + 'Weight' => 'Peso', + 'Wrong country definition' => 'Definizione di paese sbagliata', + 'Yes, I have a password :' => 'Sì, ho una password :', + 'You don\'t need to use commas or other punctuations.' => 'Non è necessario utilizzare virgole o altri segni di interpunzione.', + 'You should select a state for this country.' => 'È necessario selezionare uno stato per questo paese.', + 'Your Email Address' => 'Indirizzo Email', + 'Your Message' => 'Il tuo messaggio', + 'Zip code' => 'Codice postale', + 'date format' => 'Formato della data', + 'language locale' => 'Impostazione regionale della lingua', + 'mailing system modification' => 'modifica del sistema di mailing', + 'received value `%value` does not match `%type` type' => 'il valore ricevuto \'%value\' non corrisponde a \'%type\'', + 'time format' => 'Formato dell\'ora', +]; diff --git a/core/lib/Thelia/Config/I18n/nl_NL.php b/core/lib/Thelia/Config/I18n/nl_NL.php new file mode 100644 index 00000000..5072d775 --- /dev/null +++ b/core/lib/Thelia/Config/I18n/nl_NL.php @@ -0,0 +1,24 @@ + 'Een valuta met de code "%name" bestaat al.', + 'A message with name "%name" already exists.' => 'Er bestaat al een bericht met de naam "%name".', + 'A product with reference %ref already exists. Please choose another reference.' => 'Er bestaat al een product met referentie %ref. Kies aub een andere referentie.', + 'A short description, used when a summary or an introduction is required' => 'Een korte beschrijving, wordt gebruikt wanneer een samenvatting of een inleiding vereist is', + 'A user already exists with this email address. Please login or if you\'ve forgotten your password, go to Reset Your Password.' => 'Er bestaat al een gebruiker met dit e-mailadres. Log in, of als u uw wachtwoord vergeten bent, ga dan naar Wachtwoord opnieuw instellen.', + 'A value for attribute "%name" is already present in the combination' => 'Een waarde voor het kenmerk "%name" is al aanwezig in de combinatie', + 'A variable with name "%name" already exists.' => 'Er bestaat al een variabele met de naam "%name".', + 'Activate logs only for these IP Addresses' => 'Activeer logs alleen voor deze IP adressen', + 'Activate logs only for these files' => 'Activeer logs alleen voor deze bestanden', + 'Add to all product templates' => 'Voeg toe aan alle product templates', + 'Additional address' => 'Adres toevoeging', + 'Address ID not found' => 'Adres ID niet gevonden', + 'All countries' => 'Alle landen', + 'All shipping methods' => 'Alle verzendmethoden', + 'Back Office' => 'Backoffice', + 'Error occured while processing order ref. %ref, ID %id: %err' => 'Error occured while processing order ref. %ref, ID %id: %err', + 'Sorry, an error occured: %msg' => 'Sorry, an error occured: %msg', + 'Store logs into text file, up to a certian size, then a new file is created' => 'Store logs into text file, up to a certian size, then a new file is created', + 'This coupon will offert a flat percentage off a shopper\'s entire order (not applied to shipping costs or tax rates). If the discount is greater than the total order corst, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.' => 'This coupon will offert a flat percentage off a shopper\'s entire order (not applied to shipping costs or tax rates). If the discount is greater than the total order corst, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.', + 'This coupon will subtracts a set amount from the total cost of an order. If the discount is greater than the total order corst, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.' => 'This coupon will subtracts a set amount from the total cost of an order. If the discount is greater than the total order corst, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.', +]; diff --git a/core/lib/Thelia/Config/I18n/pl_PL.php b/core/lib/Thelia/Config/I18n/pl_PL.php new file mode 100644 index 00000000..5790c162 --- /dev/null +++ b/core/lib/Thelia/Config/I18n/pl_PL.php @@ -0,0 +1,363 @@ + ' formularz tworzenia treści', + ' note: only non-visible documents can be associated.' => ' uwaga: tylko niewidoczne dokumenty mogą być powiązane.', + '"%param" parameter cannot be empty in loop type: %type, name: %name' => 'Parametr "%param" nie może być pusty w pętli typu: %type o nazwie: %name', + '"%param" parameter is missing in loop type: %type, name: %name' => 'W pętli typu: %type o nazwie: %name brakuje parametru "%param"', + '%module (version: %version)' => '%module (wersja: %version)', + '%n for number, %c for the currency code, %s for the currency symbol' => '%n dla liczby, %c dla kodu waluty, %s dla symbolu waluty', + '%obj SEO modification' => 'modyfikacja SEO obiektu %obj', + '%obj creation' => 'Tworzenie %obj', + '%obj modification' => 'Modyfikacja %obj', + '%obj%s deleted successfully' => '%obj%s został pomyślnie usunięty', + '%s has dependency to module %s. You have to deactivate this module before.' => '%s posiada zależność do modułu %s. Musisz wyłączyć ten moduł przed.', + '%s have dependencies to module %s. You have to deactivate these modules before.' => '%s posiada zależności do modułu %s. Musisz wyłączyć te moduły przed.', + '%type% position updated' => 'pozycja %type% zaaktualizowana', + '%type% visibility updated' => 'widoczność %type% zaaktualizowany', + 'A currency with code "%name" already exists.' => 'Waluta oznaczona kodem "%name" już istnieje.', + 'A message with name "%name" already exists.' => 'Wiadomość o nazwie "%name" już istnieje.', + 'A name such as Europe or Overseas' => 'Nazwa taka jak Europa lub Zagranica', + 'A product with reference %ref already exists. Please choose another reference.' => 'Produkt odwołujący się do %ref już istnieje. Proszę wybrać inne odwołanie.', + 'A short text, used when an additional or supplemental information is required.' => 'Krótki tekst, używany, gdy wymagane są dodatkowe lub uzupełniające informacje.', + 'A user already exists with this email address. Please login or if you\'ve forgotten your password, go to Reset Your Password.' => 'Użytkownik z podanym adresem email już istnieje. Proszę się zalogować, lub jeżeli zapomniałeś hasła, przejdź do resetowania hasła.', + 'A value for attribute "%name" is already present in the combination' => 'Wartość dla atrybutu "%name" została już wprowadzona w kombinacji', + 'A variable with name "%name" already exists.' => 'Zmienna o nazwie "%name" już istnieje.', + 'Activate logs only for these IP Addresses' => 'Aktywuj logi tylko dla tych adresów IP', + 'Activate logs only for these files' => 'Aktywuj logi tylko dla tych plików', + 'Activate this sale' => 'Uaktywnij ten sprzedaż', + 'Active' => 'Aktywny', + 'Additional address' => 'Dodatkowy adres', + 'Additional address information' => 'Dodatkowe informacje o adresie', + 'Address ID not found' => 'Nie odnaleziono identyfikatora adresu', + 'Address Line 2' => 'Adres 2', + 'Address Line 3' => 'Linia 3', + 'Address creation' => 'Tworzenie adresu', + 'Address label' => 'Etykieta adresu', + 'Address.' => 'Adres.', + 'Administrator' => 'Administrator', + 'Administrator ID not found' => 'Identyfikator administratora nieodnaleziony', + 'Administrators' => 'Administratorzy', + 'Advertise this product as new' => 'Reklamuj ten produkt jako nowy', + 'Alerts' => 'Powiadomienia', + 'All Products' => 'Wszystkie produkty', + 'All countries' => 'Wszystkie kraje', + 'All shipping methods' => 'Wszystkie metody dostawy', + 'Amount' => 'Kwota', + 'Archive Format' => 'Format archiwum', + 'Associate documents' => 'Powiązane dokumenty', + 'Associate images' => 'Powiązane obrazy', + 'At least one of cart products categories is %op% %categories_list%' => 'Przynajmniej jedna z kategorii produktów w koszyku jest %op% %categories_list%', + 'Attribut' => 'Atrybut', + 'Attribute ID:Attribute AV ID' => 'ID Atrybutu: Atrybut AV ID', + 'Attribute value' => 'Wartość atrybutu', + 'Attributes' => 'Atrybuty', + 'Attributes value' => 'Wartości atrybutów', + 'Auth mode' => 'Tryb uwierzytelniania', + 'Automatic rendered templates' => 'Automatycznie renderowane szablony', + 'Available quantity' => 'Dostępna ilość', + 'Available quantity *' => 'Dostępna ilość *', + 'Available shipping zones' => 'Dostępne strefy dostawy', + 'Back Office' => 'Panel administracyjny', + 'Bad tax list JSON' => 'Błędna lista podatków w formacie JSON', + 'Billing country' => 'Kraj rozliczeniowy', + 'Billing country is' => 'Kraj rozliczeniowy jest', + 'Brand' => 'Marka', + 'Brand / Supplier' => 'Marka / Dostawca', + 'Brand name' => 'Nazwa marki', + 'Brands' => 'Marki', + 'Business ID' => 'Identyfikator firmy', + 'CSS' => 'CSS', + 'CSS stylesheet' => 'Arkusz styli CSS', + 'Cannot find the shop country. Please select a shop country.' => 'Nie można odnaleźć kraju sklepu. Proszę wybrać kraj sklepu.', + 'Cannot hide the default language' => 'Nie można ukryć domyślnego języka', + 'Cart' => 'Koszyk', + 'Cart contains categories condition' => 'Koszyk zawiera warunek kategorii', + 'Cart contains specific products' => 'Koszyk zawiera konkretne produkty', + 'Cart item count' => 'Ilość elementów w koszyku', + 'Cart item count is' => 'Ilość elementów w koszyku', + 'Cart item include quantity count' => 'Łączna ilość produktów w koszyku', + 'Cart item include quantity count is' => 'Łączna ilość produktów w koszyku to', + 'Cart total amount' => 'Całkowita kwota koszyka', + 'Cart total amount is' => 'Całkowita kwota koszyka to', + 'Catalog' => 'Katalog', + 'Catalog configuration' => 'Konfiguracja katalogu', + 'Categories' => 'Kategorie', + 'Category' => 'Kategoria', + 'Category page' => 'Kategoria strony', + 'Category title' => 'Tytuł kategorii', + 'Cellphone' => 'Telefon komórkowy', + 'Change password' => 'Zmień hasło', + 'Check country iso codes here.' => 'Sprawdź kod ISO kraju in Wikipedia.', + 'Check the total Cart amount in the given currency' => 'Sprawdź całkowitą kwotę koszyka w podanej walucie', + 'Code' => 'Kod', + 'Combination builder' => 'Generator kombinacji', + 'Compagny' => 'Firma', + 'Company' => 'Firma', + 'Company Name' => 'Nazwa firmy', + 'Conclusion' => 'Wniosek', + 'Configuration' => 'Konfiguracja', + 'Confirm Email Address' => 'Potwierdź swój adres email', + 'Confirm Email address' => 'Potwierdź swój adres email', + 'Constant amount' => 'Stała kwota', + 'Constant amount found in one of the product\'s feature' => 'W jednej z cech produktów znaleziono stałą kwotę', + 'Contact and sender email address' => 'Kontakt i adres email nadawcy', + 'Contact page' => 'Strona kontaktowa', + 'Content' => 'Zawartość', + 'Content page' => 'Zawartość strony', + 'Content title *' => 'Tytuł treści *', + 'Contents' => 'Zawartość', + 'Core hook of Thelia.' => 'Główny hook Thelia.', + 'Country ID %id not found' => 'Kraj o ID %id nie został znaleziony', + 'Country ID not found' => 'ID kraju nieznaleziony', + 'Country list is not valid JSON' => 'Lista krajów nie jest poprawnym formatem JSON', + 'Country title' => 'Tytuł kraju', + 'Coupon %code is expired.' => 'Kupon %code wygasł.', + 'Coupon %code is not release.' => 'Kod kuponu %code jest niepoprawny.', + 'Coupon code %code is disabled.' => 'Kupon %code jest nieaktywny.', + 'Critical' => 'Krytyczny', + 'Curency selection page' => 'Strona wyboru waluty', + 'Currency' => 'Waluta', + 'Current Password' => 'Aktualne hasło', + 'Customer is %op% %customer_list%' => 'Klient jest %op% %customer_list%', + 'Customers' => 'Klienci', + 'Date \'%date\' is invalid, please enter a valid date using %fmt format' => 'Data \'%date\' jest nieprawidłowa, proszę podać prawidłową datę w formacie %fmt', + 'Debug' => 'Debuguj', + 'Decimal places' => 'Miejsca dziesiętne', + 'Default folder *' => 'Domyślny folder *', + 'Default product category *' => 'Domyślna kategoria produktu *', + 'Default product template' => 'Domyślny szablon produktu', + 'Deleting %obj% for %id% with parent id %parentId%' => 'Usuwanie %obj% dla %id% z Id rodzica %parentId%', + 'Delivery' => 'Dostawa', + 'Delivery choice' => 'Wybór dostawy', + 'Delivery country' => 'Kraj dostawy', + 'Delivery country is' => 'Kraj dostawy jest', + 'Delivery module ID not found' => 'ID modułu dostawy nieznaleziony', + 'Delivery zone' => 'Strefa dostawy', + 'Detailed description' => 'Szczegółowy opis', + 'Disabled' => 'Nieaktywny', + 'Discount type' => 'Rodzaj zniżki', + 'Display initial product prices on front-office' => 'Wyświetlaj pierwotne ceny produktów na front-office', + 'Document' => 'Dokument', + 'Edit JavaScript' => 'Edytuj JavaScript', + 'Email Address' => 'Adres email', + 'Emergency' => 'Nagły wypadek', + 'Enable remote SMTP use' => 'Włącz zdalne korzystanie z SMTP', + 'End date of sales' => 'Data zakończenia wyprzedaży', + 'Enter here the brand name in the default language (%title%)' => 'Wprowadź tutaj nazwę marki w domyślnym języku (%title%)', + 'Enter here the category title in the default language (%title%)' => 'Wprowadź tutaj tytuł kategorii w domyślnym języku (%title%)', + 'Enter here the mail template purpose in the default language (%title%)' => 'Wprowadź tutaj szablon wiadomości email w domyślnym języku (%title%)', + 'Enter the new password' => 'Wprowadź nowe hasło', + 'Enter the new password again' => 'Wprowadź hasło ponownie', + 'Equal to' => 'Równy', + 'Error during %action process : %error. Exception was %exc' => 'Błąd podczas procesu %action: %error. Wyjątkiem był %exc', + 'Error occured while processing order ref. %ref, ID %id: %err' => 'Wystąpił błąd podczas przetwarzania zamówienia nr. %ref, ID %id: %err', + 'Error occured.' => 'Wystąpił błąd.', + 'Errors' => 'Błędy', + 'Fail to delete %obj% for %id% with parent id %parentId% (Exception : %e%)' => 'Nie udało się usunąć %obj% dla %id% z rodzicem %parentId% (Wyjątek : %e%)', + 'Fail to update %type% position: %err%' => 'Nie udało się zaktualizować %type% position: %err%', + 'Fail to update %type% visibility: %err%' => 'Nie udało się zaktualizować widoczności %type%: %err%', + 'Failed to create instance of module "%name%" when trying to delete module. Module directory has probably been deleted' => 'Nie udało się utworzyć instancji modułu "%name%" podczas próby usunięcia modułu. Prawdopodobnie usunięto katalog modułu', + 'Failed to create new hook %s' => 'Nie udało się utworzyć nowego hooka %s', + 'Failed to deactivate hook with id %s' => 'Nie udało się zdezaktywować hooka o identyfikatorze %s', + 'Failed to delete selected countries' => 'Nie udało się usunąć wybranych krajów', + 'Failed to find a payment Module with ID=%mid for order ID=%oid' => 'Nie udało się znaleźć modułu o ID=%mid dla zamówienia o ID=%oid', + 'Failed to load message with code \'%code%\', propably because it does\'nt exists.' => 'Nie udało się załadować wiadomości z kodem \'%code%\', prawdopodobnie wiadomość nie istnieje.', + 'Failed to send message %code. Failed recipients: %failed_addresses' => 'Nie udało się wysłać wiadomości %code. Błędni odbiorcy: %failed_addresses', + 'Failed to update language definition: %ex' => 'Nie udało się zaktualizować definicji języka: %ex', + 'Fax' => 'Fax', + 'Feature' => 'Cecha', + 'Feature value does not match FLOAT format' => 'Wartość cechy nie odpowiada formatowi FLOAT', + 'Features value' => 'Wartość cechy', + 'File format' => 'Format pliku', + 'File is too large, please retry with a file having a size less than %size%.' => 'Plik jest zbyt duży, proszę spróbować ponownie z plikiem o rozmiarze mniejszym niż %size%.', + 'File to upload' => 'Plik do wgrania', + 'Files with the following extension are not allowed: %extension, please do an archive of the file if you want to upload it' => 'Pliki z następującymi rozszerzeniami są niedozwolone: %extension, proszę zrobić archiwum pliku jeżeli chcesz go wgrać', + 'First Name' => 'Imię', + 'Firstname' => 'Imię', + 'Fixed Amount Discount' => 'Stała kwota rabatu', + 'Fixed amount discount for selected attribute values' => 'Stała kwota rabatu dla wybranych wartości atrybutu', + 'Fixed amount discount for selected categories' => 'Stała kwota rabatu dla wybranych kategorii', + 'Fixed amount discount for selected products' => 'Stała kwota rabatu dla wybranych produktów', + 'Folder' => 'Katalog', + 'Folder page' => 'Strona katalogu', + 'Folder title *' => 'Tytuł katalogu *', + 'For one ore more customers' => 'Dla jednego lub wielu klientów', + 'Free product when buying one or more selected products' => 'Darmowy produkt przy zakupie jednego lub więcej z wybranych produktów', + 'Front Office' => 'Front Office', + 'Full Name' => 'Imię i nazwisko', + 'Information' => 'Informacje', + 'Invalid product_sale_elements' => 'Nieprawidłowy product_sale_elements', + 'Invalid value "%value" for "%param" parameter in loop type: %type, name: %name' => 'Nieprawidłowa wartość "%value" dla parametru "%param" w pętli typu: %type, nazwa: %name', + 'Invalid value for walkMode parameter: %value' => 'Nieprawidłowa wartość parametru walkMode: %value', + 'Invoice' => 'Faktura', + 'Invoice choice' => 'Wybór faktury', + 'It is not allowed to delete the default currency' => 'Nie wolno usunąć domyślnej waluty', + 'It is not allowed to delete the default language' => 'Nie wolno usunąć domyślnego języka', + 'JavaScript' => 'JavaScript', + 'Keep the most important part of your description in the first 150-160 characters.' => 'Zachowaj najważniejszą część twojego opisu w pierwszych 150-160 znakach.', + 'Language' => 'Język', + 'Last Name' => 'Nazwisko', + 'Lastname' => 'Nazwisko', + 'Layout' => 'Układ', + 'Less than' => 'Mniejszy niż', + 'Less than or equals' => 'Mniejszy niż lub równy', + 'Log format *' => 'Format logów *', + 'Log level *' => 'Poziom logów *', + 'Login failed. Please check your username and password.' => 'Logowanie nie powiodło się. Proszę sprawdzić swoją nazwę użytkownika lub hasło.', + 'Login page' => 'Strona logowania', + 'Logs' => 'Logi', + 'Loop cannot implements multiple Search Interfaces : `PropelSearchLoopInterface`, `ArraySearchLoopInterface`' => 'Pętla nie może implementować wielu interfejsów wyszukiwania: `PropelSearchLoopInterface`, `ArraySearchLoopInterface`', + 'Loop must implements \'PropelSearchLoopInterface\' to be timestampable' => 'Pętla musi implementować \'PropelSearchLoopInterface\' by być timestampable', + 'Loop must implements \'PropelSearchLoopInterface\' to be versionable' => 'Pętla musi implementować \'PropelSearchLoopInterface\' by być wersjonowana', + 'Loop must implements one of the following interfaces : `PropelSearchLoopInterface`, `ArraySearchLoopInterface`' => 'Pętla musi implementować jeden z następujących interfejsów: `PropelSearchLoopInterface`, `ArraySearchLoopInterface`', + 'Lost password' => 'Zagubione hasło', + 'Mail template name' => 'Nazwa szablonu maila', + 'Main address' => 'Główny adres', + 'Main area' => 'Główny obszar', + 'Make sure that your title is clear, and contains many of the keywords within the page itself.' => 'Upewnij się, że twój tytuł jest przejrzysty i zawiera wiele słów kluczowych samej strony.', + 'Make this address as my primary address' => 'Użyj tego adresu jako mojego głównego', + 'Message' => 'Wiadomość', + 'Message subject' => 'Temat wiadomości', + 'Messages' => 'Wiadomości', + 'Meta Description' => 'Meta opis', + 'Meta Keywords' => 'Meta słowa kluczowe', + 'Method Name' => 'Nazwa metody', + 'Missing or invalid data: %s' => 'Brakujące lub nieprawidłowe dane: %s', + 'Module "%name%" directory was not found' => 'Katalog modułu "%name%" nieodnaleziony', + 'Module %name directory doesn\'t exists.' => 'Katalog modułu %name nie istnieje.', + 'Module %name should have a config.xml in the Config directory.' => 'Moduł %name powinien mieć plik config.xml w katalogu Config.', + 'Module %name should have a module.xml in the Config directory.' => 'Moduł %name powinien mieć plik module.xml w katalogu Config.', + 'Module ID "%id" was not found.' => 'Moduł o identyfikatorze "%id" nieodnaleziony.', + 'Module ID not found' => 'Identyfikator modułu nieodnaleziony', + 'Module hook' => 'Hook modułu', + 'Name' => 'Nazwa', + 'Name *' => 'Nazwa *', + 'Name of the HTML layout file' => 'Nazwa pliku z układem HTML', + 'Name of the HTML template file' => 'Nazwa pliku z szablonem HTML', + 'Native' => 'Natywny', + 'New Password' => 'Nowe hasło', + 'Newsletter page' => 'Strona newslettera', + 'No module found for code \'%item\'' => 'Brak modułu dla kodu \'%item\'', + 'No, I am a new customer.' => 'Nie, jestem nowym klientem.', + 'None' => 'Żaden', + 'Not equal to' => 'Różny', + 'Not in' => 'Nie w', + 'Numerical ISO Code' => 'Numeryczny kod ISO', + 'Only files having the following mime type are allowed: %types%' => 'Dozwolone są tylko pliki o następujących typach mime: %types%', + 'Order' => 'Zamówienie', + 'Order address ID not found' => 'Nie odnaleziono ID adresu zamówienia', + 'Order failed' => 'Zamówienie nie powiodło się', + 'Order ref. %ref is now unpaid.' => 'Zamówienie nr. %ref jest teraz niezapłacone.', + 'Order ref. %ref, ID %id has been successfully paid.' => 'Zamówienie nr. %ref o numerze ID %id zostało pomyślnie opłacone.', + 'Page 404' => 'Strona 404', + 'Page Title' => 'Tytuł Strony', + 'Parent category' => 'Kategoria nadrzędna', + 'Parent folder *' => 'Folder nadrzędny *', + 'Password' => 'Hasło', + 'Password *' => 'Hasło *', + 'Please select an attribute' => 'Proszę wybrać atrybut', + 'Please select at least one attribute value' => 'Proszę wybrać przynajmniej jedną wartość atrybutu', + 'Please select at least one category' => 'Proszę wybrać przynajmniej jedną kategorię', + 'Please select at least one product' => 'Proszę wybrać przynajmniej jeden produkt', + 'Please select the category of the offred product' => 'Proszę wybrać kategorię oferowanego produktu', + 'Please select the offered product' => 'Proszę wybrać oferowany produkt', + 'Please upload a valid Zip file' => 'Proszę przesłać prawidłowy plik Zip', + 'Preferred locale' => 'Preferowane ustawienia regionalne', + 'Product template' => 'Szablon produktu', + 'ProductSaleElement modification' => 'Modyfikacja ProductSaleElement', + 'Profile Code' => 'Kod profilu', + 'Profile ID not found' => 'Nie znaleziono ID profilu', + 'Profile `code` already exists' => 'Profil \'kod\' już istnieje', + 'Range date End' => 'Zakres daty końcowej', + 'Range date Start' => 'Zakres daty początkowej', + 'Redirecting ...' => 'Przekierowywanie ...', + 'Redirecting to %url' => 'Przekierowanie na %url', + 'Register' => 'Zarejestruj się', + 'Remember me ?' => 'Zapamiętaj mnie ?', + 'Sale price excluding taxes' => 'Zniżka nie zawiera podatków', + 'Sale price including taxes' => 'Zniżka zawiera podatki', + 'Sale title' => 'Tytuł zniżki', + 'Search' => 'Szukaj', + 'Search page' => 'Strona wyszukiwania', + 'Select a default template for new products created in this category' => 'Wybierz domyślny szablon dla nowych produktów stworzonych w tej kategorii', + 'Select the brand logo' => 'Wybierz logo marki', + 'Select the brand logo amongst the brand images' => 'Wybierz logo marki wśród obrazów marki', + 'Select the categories of the products covered by this operation' => 'Wybierz kategorie produktów objętą przez tą operację', + 'Service ID' => 'Identyfikator usługi', + 'Shipping zone name' => 'Nazwa strefy dostawy', + 'Short additional text' => 'Krótki tekst dodatkowy', + 'Short description text' => 'Krótki opis', + 'Show redirections *' => 'Pokaż przekierowania *', + 'Sitemap' => 'Mapa witryny', + 'Sorry, an error occured.' => 'Przepraszamy, wystąpił błąd.', + 'Sorry, an error occured: %msg' => 'Przepraszamy, wystąpił błąd: %msg', + 'Sorry, an error occured: %s' => 'Przepraszamy, wystąpił błąd: %s', + 'Sorry, an error occurred: %err' => 'Przepraszamy, wystąpił błąd: %err', + 'Text File' => 'Plik tekstowy', + 'Text Message' => 'Wiadomość tekstowa', + 'The brand name or title' => 'Tytuł lub nazwa marki', + 'The category title' => 'Tytuł kategorii', + 'The class "%class" doesn\'t exist' => 'Klasa "%class" nie istnieje', + 'The class "%class" must extend %baseClass' => 'Klasa "%class" musi dziedziczyć po klasie %baseClass', + 'The date after which sales are de-activated. Please use %fmt format.' => 'Data po której wyprzedaże są dezaktywowane. Proszę użyć formatu daty %fmt.', + 'The date from which sales are active. Please use %fmt format.' => 'Data od której wyprzedaże są aktywne. Proszę użyć formatu daty %fmt.', + 'The file %path has been successfully downloaded' => 'Plik %path został pomyślnie pobrany', + 'The following columns are missing: %columns' => 'Brakuje następujących kolumn: %columns', + 'The language "%id" doesn\'t exist' => 'Język "%id" nie istnieje', + 'The mailing template in HTML format.' => 'Szablon wiadomości w formacie HTML.', + 'The mailing template in text-only format.' => 'Szablon wiadomości w formacie tekstowym.', + 'The module "%name%" is currently in use by at least one order, and can\'t be deleted.' => 'Moduł "%name%" jest obecnie używany przez co najmniej jedno zamówienie i nie może zostać usunięty.', + 'The module %module has been installed successfully.' => 'Moduł %module został pomyślnie zainstalowany.', + 'The module %name is already installed in the same or greater version.' => 'Moduł %name jest już zainstalowany w tej samej lub wyższej wersji.', + 'The module %name requires Thelia %version or newer' => 'Moduł %name wymaga wersji %version lub nowszej', + 'This coupon does not exists' => 'Ten kupon nie istnieje', + 'This coupon subtracts from the order total a percentage of the price of each product which belongs to the selected categories. If the discount is greater than the total order, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.' => 'Ten kupon obniża procentowo cenę każdego produktu w zamówieniu, który należy do wybranej kategorii. Jeżeli zniżka jest większa niż całkowita kwota zamówienia klient zapłaci tylko za dostawę lub nic nie zapłaci jeżeli kupon zapewnia również darmową dostawę.', + 'This coupon subtracts from the order total the specified percentage of each product price which uses the selected attribute values. If the discount is greater than the total order, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.' => 'Ten kupon odejmuje od sumy zamówienia określony procent od każdego produktu, który posiada wartości wybranego atrybutu. Jeżeli zniżka jest większa niż całkowita kwota zamówienia, klient zapłaci tylko za dostawę lub nic, jeżeli kupon również zapewnia bezpłatną dostawę.', + 'This coupon subtracts from the order total the specified percentage of each selected product price. If the discount is greater than the total order, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.' => 'Ten kupon odejmuje od sumy zamówienia określony procent od każdego produktu. Jeżeli zniżka jest większa niż całkowita kwota zamówienia, klient zapłaci tylko za dostawę lub nic, jeżeli kupon również zapewnia dodatkową dostawę.', + 'This coupon subtracts the specified amount from the order total for each product which belongs to the selected categories. If the discount is greater than the total order, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.' => 'Ten kupon obniża określoną kwotę każdego produktu w zamówieniu, który należy do wybranej kategorii. Jeżeli zniżka jest większa niż całkowita kwota zamówienia klient zapłaci tylko za dostawę lub nic nie zapłaci jeżeli kupon zapewnia również darmową dostawę.', + 'This coupon subtracts the specified amount from the order total for each product which uses the selected attribute values. If the discount is greater than the total order, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.' => 'Ten kupon obniża określoną kwotę każdego produktu w zamówieniu, który używa wartości wybranego atrybutu. Jeżeli zniżka jest większa niż całkowita kwota zamówienia klient zapłaci tylko za dostawę lub nic nie zapłaci jeżeli kupon zapewnia również darmową dostawę.', + 'This coupon subtracts the specified amount from the order total for each selected product. If the discount is greater than the total order, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.' => 'Ten kupon obniża określoną kwotę każdego produktu w zamówieniu. Jeżeli zniżka jest większa niż całkowita kwota zamówienia klient zapłaci tylko za dostawę lub nic nie zapłaci jeżeli kupon zapewnia również darmową dostawę.', + 'This coupon will subtracts a set amount from the total cost of an order. If the discount is greater than the total order corst, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.' => 'Ten kupon obniża określoną kwotę z całkowitego kosztu zamówienia. Jeżeli zniżka jest większa niż całkowita kwota zamówienia klient zapłaci tylko za dostawę lub nic nie zapłaci jeżeli kupon zapewnia również darmową dostawę.', + 'This document is online' => 'Ten dokument jest online', + 'This email already exists.' => 'Ten email już istnieje.', + 'This email does not exists' => 'Ten email nie istnieje', + 'This folder is online.' => 'Ten folder jest online.', + 'This image is online' => 'Ten obraz jest online', + 'This is an identifier that will be used in the code to get this message' => 'To jest identyfikator, który używany będzie w kodzie do pobrania tej wiadomości', + 'This product does not have a physical presence' => 'Ten produkt nie posiada fizycznej obecności', + 'This product is on sale' => 'Ten produkt jest na wyprzedaży', + 'This product is online' => 'Ten produkt jest online', + 'Title *' => 'Tytuł *', + 'Title ID not found' => 'ID tytułu nie znaleziony', + 'To activate module %name, the following modules should be activated first: %modules' => 'Aby aktywować moduł %name, najpierw powinny zostać aktywowane następujące moduły: %modules', + 'Translations' => 'Tłumaczenia', + 'Type' => 'Typ', + 'URL_ALREADY_EXISTS' => 'Ten URL już istnieje', + 'Unable to process your request. Please try again (%err).' => 'Nie można przetworzyć żądania. Proszę spróbować ponownie (%err).', + 'Undefined loop argument "%name"' => 'Niezdefiniowany argument pętli "%name"', + 'Undefined search mode \'%mode\'' => 'Niezdefiniowany tryb wyszukiwania \'%mode\'', + 'Unknown order ID: %id' => 'Nieznany ID zamówienia: %id', + 'Unsupported magic method %name. only getArgname() is supported.' => 'Nieobsługiwana metoda magiczna %name. Obsługiwana jest tylko metoda getArgname().', + 'Unsupported type' => 'Nieobsługiwany typ', + 'Update customer account' => 'Aktualizacja konta klienta', + 'Use the keyword phrase in your URL.' => 'Użyj słów kluczowych w adresie URL.', + 'block' => 'blok', + 'bottom' => 'dół', + 'configuration' => 'konfiguracja', + 'configuration JavaScript' => 'konfiguracja JavaScript', + 'email confirmation is not the same as email field' => 'Adresy email nie są identyczne', + 'hour(s)' => 'godzina(y)', + 'in the header' => 'w nagłówku', + 'javascript' => 'javascript', + 'javascript initialization' => 'inicjalizacja JavaScript', + 'label' => 'etykieta', + 'photo gallery' => 'galeria zdjęć', + 'plain, login, cram-md5 or empty' => 'zwykły, logowania, cram-md5 lub pusty', + 'product list' => 'lista produktów', + 'row' => 'wiersz', + 'tax rule' => 'zasady podatkowe', + 'thousands separator' => 'separator tysiąca', + 'time format' => 'format czasu', + 'type' => 'typ', +]; diff --git a/core/lib/Thelia/Config/I18n/pt_BR.php b/core/lib/Thelia/Config/I18n/pt_BR.php new file mode 100644 index 00000000..be4eaab6 --- /dev/null +++ b/core/lib/Thelia/Config/I18n/pt_BR.php @@ -0,0 +1,232 @@ + ' formulário de criação de conteúdo', + ' note: only non-visible documents can be associated.' => ' nota: somente documentos não visíveis podem ser associados.', + '"%param" parameter cannot be empty in loop type: %type, name: %name' => '"%param" parâmetro não pode estar vazio loop de tipo: %type, nome: %name', + '"%param" parameter is missing in loop type: %type, name: %name' => 'o parâmetro "%param" está faltando no tipo de laço: % tipo, nome: %name', + '%module (version: %version)' => 'módulo % (versão: % versão)', + '%obj SEO modification' => 'modificação de SEO %obj', + '%obj creation' => 'criação de %obj', + '%obj modification' => 'modificação de %obj', + '%obj%s deleted successfully' => '%obj%s deletado com sucesso', + '%s has dependency to module %s. You have to deactivate this module before.' => '%s tem dependência do módulo %s. Você tem que desativar este módulo antes.', + '%s have dependencies to module %s. You have to deactivate these modules before.' => '%s tem dependências para os módulos %s. Você tem que desativar esse módulos antes.', + '%type% position updated' => '%type% posição atualizada', + '%type% visibility updated' => '%type% visibilidade atualizada', + 'A comma separated list of email addresses' => 'Uma lista de emails separados por vírgula', + 'A currency with code "%name" already exists.' => 'Uma moeda com o código "%name" já existe.', + 'A descriptive title' => 'Um título descritivo', + 'A message with name "%name" already exists.' => 'Uma mensagem com o nome "%name" já existe.', + 'A name such as Europe or Overseas' => 'Um nome como Europa ou Exterior', + 'A product with reference %ref already exists. Please choose another reference.' => 'Um produto com referência %ref já existe. Por favor escolha outra referência.', + 'A short description, used when a summary or an introduction is required' => 'Uma breve descrição, usada quando é necessária um resumo ou uma introdução', + 'A short text, used when an additional or supplemental information is required.' => 'Um texto curto, usado quando informações adicionais ou complementares é necessário.', + 'A user already exists with this email address. Please login or if you\'ve forgotten your password, go to Reset Your Password.' => 'Um usuário com esse endereço de email já existe. Por favor entre ou se você esqueceu sua senha, vá para Restaurar Sua Senha.', + 'A value for attribute "%name" is already present in the combination' => 'Um valor para o atributo "%name" já está presente na combinação', + 'A variable with name "%name" already exists.' => 'Uma variável com o nome "%name" já existe.', + 'Activate logs only for these IP Addresses' => 'Ativar logs somente para esses endereços de IP', + 'Activate logs only for these files' => 'Ativar logs somente para esses arquivos', + 'Activate this sale' => 'Ativar esta venda', + 'Active' => 'Ativo', + 'Add to all product templates' => 'Adicionar para todos os modelos de produto', + 'Additional address' => 'Endereço adicional', + 'Additional address information' => 'Informações adicionais de endereço', + 'Address ID not found' => 'ID de endereço não encontrado', + 'Address Line 2' => 'Linha de Endereço 2', + 'Address Line 3' => 'Linha de Endereço 3', + 'Address creation' => 'Criação de endereço', + 'Address label' => 'Etiqueta de endereço', + 'Address update' => 'Atualização de endereço', + 'Address.' => 'Endereço.', + 'Administrator' => 'Administrador', + 'Administrator ID not found' => 'ID do administrador não encontrado', + 'Administrators' => 'Administradores', + 'Advertise this product as new' => 'Anunciar este produto como novo', + 'Alerts' => 'Alertas', + 'All Products' => 'Todos os produtos', + 'All countries' => 'Todos os países', + 'All shipping methods' => 'Todos os métodos de transporte', + 'Amount' => 'Quantidade', + 'Apply exchange rates on price in %sym' => 'Aplicar taxas de câmbio sobre o preço em %sym', + 'Archive Format' => 'Formato do Arquivo', + 'Associate documents' => 'Associar documentos', + 'Associate images' => 'Associar imagens', + 'At least one of cart products categories is %op% %categories_list%' => 'Pelo menos uma das categorias de produtos do carrinho é %op% %categories_list%', + 'Attribut' => 'Atributo', + 'Attribute ID:Attribute AV ID' => 'Atributo ID de ID:Attribute AV', + 'Attribute value' => 'Valor do atributo', + 'Attributes' => 'Atributos', + 'Attributes value' => 'Valor de atributos', + 'Auth mode' => 'Modo de autenticação', + 'Available quantity' => 'Quantidade disponível', + 'Available quantity *' => 'Quantidade disponível *', + 'Available shipping zones' => 'Zonas de transporte disponível', + 'Back Office' => 'Área Administrativa', + 'Bad tax list JSON' => 'Lista JSON de imposto ruim', + 'Billing country' => 'País de cobrança', + 'Billing country is' => 'País de cobrança é', + 'Brand' => 'Marca', + 'Brand / Supplier' => 'Marca / fornecedor', + 'Brand name' => 'Nome de marca', + 'Brands' => 'Marcas', + 'Business ID' => 'ID do negócio', + 'By Module' => 'Por módulo', + 'CSS' => 'CSS', + 'CSS stylesheet' => 'Folha de estilo CSS', + 'Cannot find a default country. Please define one.' => 'Não foi possível encontrar um país padrão. Por favor, defina um.', + 'Cannot find the shop country. Please select a shop country.' => 'Não foi possível encontrar o país da loja. Por favor selecione um país da loja.', + 'Cannot instantiate module "%name%": the namespace is null. Maybe the model is not loaded ?' => 'Não é possível instanciar o módulo "%name%": o namespace é nulo. Talvez o modelo não tenha sido carregado?', + 'Cart' => 'Carrinho', + 'Cart contains at least a product %op% %products_list%' => 'Carrinho deve conter pelo menos um produto %op% %products_list%', + 'Cart contains categories condition' => 'O carrinho contém condição de categorias', + 'Cart contains specific products' => 'O carrinho contém produtos específicos', + 'Cart item count' => 'Contagem de itens do carrinho', + 'Cart item count is' => 'O numero de itens no carrinho é', + 'Cart total amount' => 'Montante total do carrinho', + 'Cart total amount is' => 'O total de itens no carrinho é', + 'Catalog' => 'Catálogo', + 'Catalog configuration' => 'Configuração de catálogo', + 'Categories' => 'Categorias', + 'Category' => 'Categoria', + 'Category page' => 'Página de categoria', + 'Category title' => 'Título da categoria', + 'Cellphone' => 'Telefone celular', + 'Change password' => 'Alterar senha', + 'Check country iso codes here.' => 'Verifique os códigos ISO de paísna Wikipédia.', + 'Check the total Cart amount in the given currency' => 'Verificar o montante total do carrinho na moeda determinada', + 'City' => 'Cidade', + 'Code' => 'Código', + 'Combination builder' => 'Construtor de combinação', + 'Compagny' => 'Empresa', + 'Company' => 'Empresa', + 'Company Name' => 'Empresa', + 'Conclusion' => 'Conclusão', + 'Configuration' => 'Configuração', + 'Confirm Email Address' => 'Confirme o seu endereço de e-mail', + 'Confirm Email address' => 'Confirme o seu endereço de e-mail', + 'Constant amount' => 'Quantidade constante', + 'Constant amount found in one of the product\'s feature' => 'Quantidade constante em uma das característica do produto', + 'Contact and sender email address' => 'Endereço de e-mail do remetente e contato', + 'Contact page' => 'Página de Contato', + 'Content' => 'Conteúdo', + 'Content page' => 'Página de conteúdo', + 'Content title *' => 'Título do conteúdo *', + 'Contents' => 'Conteúdos', + 'Core hook of Thelia.' => 'Gancho de núcleo de Thelia.', + 'Countries' => 'Países', + 'Country' => 'País', + 'Country ID not found' => 'ID de país não encontrada', + 'Country title' => 'Título do país', + 'Coupon' => 'Cupom', + 'Coupon %code is expired.' => 'Cupom %code expirado.', + 'Coupon code %code is disabled.' => 'Cupom código %code está desativado.', + 'Critical' => 'Crítico', + 'Curency selection page' => 'Página de seleção de numerário', + 'Currencies' => 'Moedas', + 'Currency' => 'Moeda', + 'Currency name' => 'Nome da moeda', + 'Current Password' => 'Senha Atual', + 'Customer' => 'Cliente', + 'Customer is %op% %customer_list%' => 'Cliente é %op% %customer_list%', + 'Customers' => 'Clientes', + 'Dashboard' => 'Dashboard', + 'Date \'%date\' is invalid, please enter a valid date using %fmt format' => 'Data \'%date\' é inválida, por favor, introduza uma data válida usando o formato %fmt', + 'Debug' => 'Depurar/Debug', + 'Decimal places' => 'Casas decimais', + 'Default folder *' => 'Pasta padrão *', + 'Default product category *' => 'Categoria de produto padrão *', + 'Default product sale element' => 'Elemento de venda de produto padrão', + 'Default product template' => 'Modelo do produto padrão', + 'Deleting %obj% for %id% with parent id %parentId%' => 'Exclusão de %obj% para %id% com %parentId% de identificação do pai', + 'Delivery' => 'Entrega', + 'Delivery choice' => 'Escolha da entrega', + 'Delivery country' => 'País de entrega', + 'Delivery country is' => 'País de entrega é', + 'Delivery module ID not found' => 'ID do módulo de entrega não encontrado', + 'Delivery zone' => 'Zona de entrega', + 'Detailed description' => 'Descrição detalhada', + 'Disabled' => 'Desativado', + 'Discount type' => 'Tipo de desconto', + 'Display initial product prices on front-office' => 'Exibir os preços do produto inicial em front-office', + 'Do compress' => 'Comprimir', + 'Document' => 'Documento', + 'Don\'t repeat keywords over and over in a row. Rather, put in keyword phrases.' => 'Não repita palavras-chave várias vezes em uma fileira. Em vez disso, coloque-as em frases-chave.', + 'Edit' => 'Editar', + 'Edit JavaScript' => 'Editar JavaScript', + 'Email Address' => 'Endereço de e-mail', + 'Email addresses of notification recipients' => 'Endereços de e-mail dos destinatários de notificação', + 'Email test from : %store%' => 'Teste de e-mail de: %store%', + 'Emergency' => 'Emergência', + 'Enable remote SMTP use' => 'Ativar a utilização remota do SMTP', + 'End date of sales' => 'Data de término das vendas', + 'Enter here the brand name in the default language (%title%)' => 'Digite aqui o nome da marca na língua padrão (%title%)', + 'Enter here the category title in the default language (%title%)' => 'Digite aqui o título da categoria na língua padrão (%title%)', + 'Enter here the mail template purpose in the default language (%title%)' => 'Digite aqui a finalidade do modelo de correspondência na língua padrão (%title%)', + 'Enter here the sale name in the default language (%title%)' => ' +Digite aqui o nome venda no idioma padrão (%title%)', + 'Equal to' => 'Igual a', + 'Errors' => 'Erros', + 'Fail to delete %obj% for %id% with parent id %parentId% (Exception : %e%)' => 'Falha ao excluir %obj% para %id% com o pai id %parentid% (Exceção: %e%)', + 'Features' => 'Funcionalidades', + 'Folder title *' => 'Título da Pasta *', + 'For one ore more customers' => 'Para um ou mais clientes', + 'Free product when buying one or more selected products' => 'Produto gratuito quando for comprar um ou mais produtos selecionados', + 'Front Office' => 'Loja', + 'Full Name' => 'Nome Completo', + 'Greater than' => 'Maior do que', + 'Greater than or equals' => 'Maior que ou igual a', + 'HTML Message' => 'Mensagem HTML', + 'HTML layout' => 'Layout HTML', + 'Home' => 'Página inicial', + 'Home page' => 'Página Inicial', + 'Hook' => 'Gancho', + 'Hook block' => 'Bloco de gancho', + 'Hook code' => 'Código de gancho', + 'Hook create form' => 'Formulário de criação de gancho', + 'Hook title' => 'Título de gancho', + 'Hooks' => 'Ganchos', + 'Host' => 'Servidor', + 'I would like to receive the newsletter or the latest news.' => 'Eu gostaria de receber a newsletter com as últimas notícias.', + 'ISO 639-1 Code' => 'Código ISO 639-1', + 'ISO Alpha-2 code' => 'Código ISO alfa-2', + 'ISO Alpha-3 code' => 'Código ISO Alfa-3', + 'If cart item count is %operator% %quantity%' => 'Se a contagem de item do carrinho for %operator% %quantity%', + 'If cart total amount is %operator% %amount% %currency%' => 'Se o montante total do carrinho for %operator% %amount% %currency%', + 'If checked, this hook will be used by a hook block. If not, by hook function.' => 'Se marcada, este gancho será usado por um bloco de gancho. Se não, gancho por função.', + 'Image' => 'Imagem', + 'Impossible to delete a customer who already have orders' => 'Impossível de excluir um cliente que já possuí pedidos', + 'In' => 'Em', + 'Include documents' => 'Incluir documentos', + 'Include images' => 'Incluir imagens', + 'Information' => 'Informação', + 'Invoice' => 'Fatura', + 'Invoice choice' => 'Escolha de fatura', + 'JavaScript' => 'JavaScript', + 'Language' => 'Linguagem', + 'Last Name' => 'Sobrenome', + 'Layout' => 'Layout', + 'Less than' => 'Menos de', + 'Less than or equals' => 'Inferior ou igual a', + 'Log format *' => 'Formato de log *', + 'Log level *' => 'Nível de log *', + 'Login failed. Please check your username and password.' => 'Falha no login. Por favor, verifique seu nome de usuário e senha.', + 'Login page' => 'Login page', + 'Logs' => 'Logs', + 'Name' => 'Nome', + 'Notices' => 'Avisos', + 'Numerical ISO Code' => 'Código numérico ISO', + 'Only files having the following mime type are allowed: %types%' => 'São permitidos apenas os arquivos com o tipo de mime a seguir: %types%', + 'Parent category' => 'Categoria pai', + 'Parent folder *' => 'Pasta pai *', + 'Password' => 'Senha', + 'Password *' => 'Senha *', + 'Password confirmation' => 'Confirmação de senha', + 'Payment failed' => 'Falha no Pagamento', + 'Payment gateway' => 'Gateway de pagamento', + 'Per customer' => 'Por cliente', + 'Percentage' => 'Porcentagem', + 'Quantity' => 'Quantidade', + 'Register' => 'Registrar', + 'Search' => 'Procurar', +]; diff --git a/core/lib/Thelia/Config/I18n/pt_PT.php b/core/lib/Thelia/Config/I18n/pt_PT.php new file mode 100644 index 00000000..1466af5f --- /dev/null +++ b/core/lib/Thelia/Config/I18n/pt_PT.php @@ -0,0 +1,12 @@ + 'Atualização de endereço', + 'Amount' => 'Quantidade', + 'Cart' => 'Carrinho', + 'Categories' => 'Categorias', + 'Currency' => 'Moeda', + 'Home' => 'Página Inicial', + 'Language' => 'Idioma', + 'Name' => 'Nome', +]; diff --git a/core/lib/Thelia/Config/I18n/ro_RO.php b/core/lib/Thelia/Config/I18n/ro_RO.php new file mode 100644 index 00000000..bf30c353 --- /dev/null +++ b/core/lib/Thelia/Config/I18n/ro_RO.php @@ -0,0 +1,12 @@ + '"%param" parametrul nu poate fi gol tipul de loop: %type, name: %name', + '"%param" parameter is missing in loop type: %type, name: %name' => '"%param" parametrul lipseste in tipul de loop : %type, name: %name', + '%obj SEO modification' => '%obj modificare SEO', + '%obj creation' => '%obj creare', + '%obj modification' => '%obj modificare', + 'A currency with code "%name" already exists.' => 'O moneda cu numele "%name" deja exista.', + 'A message with name "%name" already exists.' => 'Un mesaj cu numele "%name" exista deja.', + 'A product with reference %ref already exists. Please choose another reference.' => 'Un produs cu referinta %ref exista deja. Va rugam sa alegeti alta referinta.', +]; diff --git a/core/lib/Thelia/Config/I18n/ru_RU.php b/core/lib/Thelia/Config/I18n/ru_RU.php new file mode 100644 index 00000000..e6bd09a0 --- /dev/null +++ b/core/lib/Thelia/Config/I18n/ru_RU.php @@ -0,0 +1,830 @@ + ' форма создания содержимого', + ' note: only non-visible documents can be associated.' => ' Примечание: только не видимые документы могут быть связаны.', + '"%param" parameter cannot be empty in loop type: %type, name: %name' => 'параметр «%param» не может быть пустым в цикле типа: тип %, имя: %name', + '"%param" parameter is missing in loop type: %type, name: %name' => 'отсутствует параметр «%param» в цикле типа : % тип, имя: %name', + '%module (version: %version)' => '%module (версия: %version)', + '%n for number, %c for the currency code, %s for the currency symbol' => '%n для числа, %c для кода валюты, %s для символа валюты', + '%obj SEO modification' => 'модификация SEO %obj', + '%obj creation' => 'Создание %obj', + '%obj modification' => 'модификация %obj', + '%obj%s deleted successfully' => '%obj%s успешно удалены', + '%s has dependency to module %s. You have to deactivate this module before.' => '%s имеет зависимость от модуля %s. Вы должны отключить этот модуль раньше.', + '%s have dependencies to module %s. You have to deactivate these modules before.' => '%s имеют зависимости от модуля %s. Вы должны отключить эти модули раньше.', + '%type% position updated' => '%type% позиция обновлена', + '%type% visibility updated' => '%type% отображение обновлено', + 'A Hook with code %name already exists. Please choose another code.' => 'Хук с кодом %name уже существует. Пожалуйста выберите другой код.', + 'A comma separated list of email addresses' => 'Разделенный запятыми список email адресов', + 'A currency with code "%name" already exists.' => 'Валюта с кодом «%name» уже существует.', + 'A descriptive title' => 'Описательное название', + 'A message with name "%name" already exists.' => 'Сообщение с именем «%name» уже существует.', + 'A name such as Europe or Overseas' => 'Имя, например Европейский или Заморский', + 'A product with reference %ref already exists. Please choose another reference.' => 'Товар с ссылкой %ref уже существует. Пожалуйста, выберите другую ссылку.', + 'A short description, used when a summary or an introduction is required' => 'Краткое описание, используется когда требуется резюме или введение', + 'A short text, used when an additional or supplemental information is required.' => 'Короткий текст, используется, когда требуется дополнительная или дополняющая информация.', + 'A user already exists with this email address. Please login or if you\'ve forgotten your password, go to Reset Your Password.' => 'Пользователь с таким адресом электронной почты уже существует. Пожалуйста войдите в систему, или если вы забыли пароль, перейдите по ссылке "Сброс пароля".', + 'A value for attribute "%name" is already present in the combination' => 'Значение для атрибута «%name» уже присутствует в комбинации', + 'A variable with name "%name" already exists.' => 'Переменная с именем «%name» уже существует.', + 'Activate logs only for these IP Addresses' => 'Активировать журналы только для этих IP-адресов', + 'Activate logs only for these files' => 'Активировать только для этих файлов журналов', + 'Activate this sale' => 'Активировать эту скидку', + 'Active' => 'Активен', + 'Add to all product templates' => 'Добавить ко всем шаблонам товара', + 'Additional address' => 'Дополнительный адрес', + 'Additional address information' => 'Дополнительная информация об адресе', + 'Address ID not found' => 'ID адреса не найден', + 'Address Line 2' => 'Адрес, строка 2', + 'Address Line 3' => 'Адрес, строка 3', + 'Address creation' => 'Создание адреса', + 'Address label' => 'Метка адреса', + 'Address update' => 'Обновить адрес', + 'Address.' => 'Адрес.', + 'Addresses for this country need a zip code' => 'Адресам для этой страны нужен индекс', + 'Administrator' => 'Администратор', + 'Administrator ID not found' => 'ID администратора не найден', + 'Administrator email address' => 'E-mail адрес администратора', + 'Administrators' => 'Администраторы', + 'Advertise this product as new' => 'Рекламировать этот товар, как новый', + 'Alerts' => 'Уведомления', + 'All Products' => 'Все товары', + 'All countries' => 'Все страны', + 'All shipping methods' => 'Все способы доставки', + 'Amount' => 'Количество', + 'An administrator with thie email address already exists' => 'Администратор с таким email адресом уже существует', + 'An administrator with this email address already exists' => 'Администратор с таким email адресом уже существует', + 'An invalid token was provided, your password cannot be changed' => 'Был предоставлен некорректный токен. Пароль не может быть изменен', + 'Apply exchange rates on price in %sym' => 'Применять обменные курсы на цены в %sym', + 'Archive Format' => 'Формат Архива', + 'Associate documents' => 'Связать документы', + 'Associate images' => 'Связать изображения', + 'At least one of cart products categories is %op% %categories_list%' => 'По крайней мере одна из категорий товаров %op% %categories_list%', + 'Attribut' => 'Атрибут', + 'Attribute ID:Attribute AV ID' => 'Атрибут ID ID:Attribute AV', + 'Attribute value' => 'Значение атрибута', + 'Attributes' => 'Атрибуты', + 'Attributes value' => 'Значение атрибутов', + 'Auth mode' => 'Режим аутентификации', + 'Automatic rendered templates' => 'Автоматически сгенерированные шаблоны', + 'Available quantity' => 'Доступное количество', + 'Available quantity *' => 'Доступное количество *', + 'Available shipping zones' => 'Доступные зоны доставки', + 'Back Office' => 'Панель Управления', + 'Bad tax list JSON' => 'Плохой список налогов JSON', + 'Billing country' => 'Страна плательщика', + 'Billing country is' => 'Страна плательщика', + 'Brand' => 'Бренд', + 'Brand / Supplier' => 'Бренд / Поставщик', + 'Brand name' => 'Название Брэнда', + 'Brands' => 'Бренды', + 'Business ID' => 'Бизнес ID', + 'By Module' => 'По модулю', + 'CSS' => 'CSS', + 'CSS stylesheet' => 'Таблица стилей CSS', + 'Cannot disable the default language' => 'Невозможно выключить язык по умолчанию', + 'Cannot find a default country. Please define one.' => 'Пожалуйста, определите страну по умолчанию.', + 'Cannot find the shop country. Please select a shop country.' => 'Пожалуйста, выберите страну для вашего магазина.', + 'Cannot hide the default language' => 'Невозможно скрыть язык по умолчанию', + 'Cannot instantiate module "%name%": the namespace is null. Maybe the model is not loaded ?' => 'Не удается создать экземпляр модуля «%name%»: пространство имен имеет значение null. Может быть модель не загружен?', + 'Cart' => 'Корзина', + 'Cart contains at least a product %op% %products_list%' => 'Корзина содержит по крайней мере товар %op% %products_list%', + 'Cart contains categories condition' => 'Корзина содержит состояния категорий', + 'Cart contains specific products' => 'Корзина содержит конкретные товары', + 'Cart item count' => 'Количество элементов в корзине', + 'Cart item count is' => 'Количество элементов в корзине', + 'Cart item include quantity count' => 'Количество элементов корзины включая объем', + 'Cart item include quantity count is' => 'Количество элементов корзины включая объем', + 'Cart total amount' => 'Общая сумма корзины', + 'Cart total amount is' => 'Общая сумма корзины', + 'Catalog' => 'Каталог', + 'Catalog configuration' => 'Конфигурация каталога', + 'Categories' => 'Категории', + 'Category' => 'Категория', + 'Category page' => 'Страница категории', + 'Category title' => 'Название категории', + 'Cellphone' => 'Мобильный телефон', + 'Change password' => 'Изменить пароль', + 'Check country iso codes here.' => 'Проверьте iso коды стран в Википедии.', + 'Check the total Cart amount in the given currency' => 'Проверить сумму корзину в данной валюте', + 'City' => 'Город', + 'Code' => 'Код', + 'Combination builder' => 'Билдер комбинаций', + 'Compagny' => 'Компания', + 'Company' => 'Название фирмы', + 'Company Name' => 'Название фирмы', + 'Conclusion' => 'Заключение', + 'Configuration' => 'Конфигурация', + 'Confirm Email Address' => 'Подтвердите Ваш адрес электронной почты', + 'Confirm Email address' => 'Подтвердите Ваш адрес электронной почты', + 'Constant amount' => 'Постоянная сумма', + 'Constant amount found in one of the product\'s feature' => 'Фиксированное значение найденное в одной из характеристик товара', + 'Contact and sender email address' => 'Адрес электронной почты контакта и отправителя', + 'Contact page' => 'Контакты', + 'Content' => 'Содержимое', + 'Content page' => 'Страница содержимого', + 'Content title *' => 'Заголовок содержимого *', + 'Contents' => 'Содержимое', + 'Core hook of Thelia.' => 'Хук ядра Thelia.', + 'Countries' => 'Страны', + 'Country' => 'Страна', + 'Country ID %id not found' => 'Страна с ID %id не найдена', + 'Country ID not found' => 'ID страны не найден', + 'Country list is not valid JSON' => 'Некорректный JSON для списка стран', + 'Country title' => 'Название страны', + 'Coupon' => 'Купон', + 'Coupon %code is expired.' => 'Истек срок действия купона %code.', + 'Coupon %code is not release.' => 'Купон %code не выпущен.', + 'Coupon code %code is disabled.' => 'Купон %code отключен.', + 'Critical' => 'Критические', + 'Curency selection page' => 'Страница выбора валюты', + 'Currencies' => 'Валюты', + 'Currency' => 'Валюта', + 'Currency name' => 'Название валюты', + 'Current Password' => 'Текущий пароль', + 'Customer' => 'Клиент', + 'Customer is %op% %customer_list%' => 'Клиент %op% %customer_list%', + 'Customers' => 'Клиенты', + 'Dashboard' => 'Приборная панель', + 'Date \'%date\' is invalid, please enter a valid date using %fmt format' => 'Недопустимая дата \'%date\', пожалуйста, введите корректную дату с использованием формата %fmt', + 'Debug' => 'Отладка', + 'Decimal places' => 'Десятичные знаки', + 'Default folder *' => 'Папка по умолчанию *', + 'Default product category *' => 'Категория товара по умолчанию *', + 'Default product sale element' => 'Элемент продажи товара по умолчанию', + 'Default product template' => 'Шаблон товара по умолчанию', + 'Deleting %obj% for %id% with parent id %parentId%' => 'Удаление %obj% для %id% с id родителя %parentId%', + 'Delivery' => 'Доставка', + 'Delivery choice' => 'Выбор доставки', + 'Delivery country' => 'Страна доставки', + 'Delivery country is' => 'Страна доставки: ', + 'Delivery module ID not found' => 'Не найден ID модуля доставки', + 'Delivery zone' => 'Зона доставки', + 'Detailed description' => 'Подробное описание', + 'Disabled' => 'Отключен', + 'Discount type' => 'Тип скидки', + 'Display initial product prices on front-office' => 'Отображать исходные цены товара в front-office', + 'Do compress' => 'Сжать', + 'Document' => 'Документ', + 'Don\'t repeat keywords over and over in a row. Rather, put in keyword phrases.' => 'Не повторяйте ключевые слова снова и снова в одной строке. Лучше сделайте ключевые фразы.', + 'EAN Code' => 'EAN код', + 'Edit' => 'Редактировать', + 'Edit JavaScript' => 'Редактировать JavaScript', + 'Email Address' => 'Адрес эл.почты', + 'Email address' => 'Адрес электронной почты', + 'Email addresses of notification recipients' => 'Адреса электронной почты получателей уведомлений', + 'Email test from : %store%' => 'Проверка электронной почты от: %store%', + 'Emergency' => 'Чрезвычайные', + 'Enable remote SMTP use' => 'Включение удаленного использования SMTP', + 'Encryption' => 'Шифрование', + 'End date of sales' => 'Дата окончания продаж', + 'Enter here the brand name in the default language (%title%)' => 'Введите здесь имя бренда на языке по умолчанию (%title%)', + 'Enter here the category title in the default language (%title%)' => 'Здесь введите название категории на языке по умолчанию (%title%)', + 'Enter here the mail template purpose in the default language (%title%)' => 'Введите здесь цель шаблона электронной почты на языке по умолчанию (%title%)', + 'Enter here the sale name in the default language (%title%)' => 'Введите здесь имя распродажи на языке по умолчанию (%title%) ', + 'Enter the new password' => 'Введите новый пароль', + 'Enter the new password again' => 'Введите новый пароль еще раз', + 'Equal to' => 'Равно', + 'Error during %action process : %error. Exception was %exc' => 'Ошибка во время обработки %action : %error. Exception : %exc', + 'Error occured while processing order ref. %ref, ID %id: %err' => 'Произошла ошибка во время обработки заказа ref. %ref, ID %id: %err', + 'Error occured.' => 'Произошла ошибка.', + 'Error(s) in import :
%errors' => 'Ошибка(и) в импорте :
%errors', + 'Errors' => 'Ошибки', + 'Export' => 'Экспорт', + 'Fail to delete %obj% for %id% with parent id %parentId% (Exception : %e%)' => 'Ошибка удаления %obj% для %id% с id родителя %parentId% (Exception : %e%)', + 'Fail to update %type% position: %err%' => 'Ошибка при обновлении %type% позиции: %err%', + 'Fail to update %type% visibility: %err%' => 'Ошибка при обновлении %type% видимости: %err%', + 'Failed to create instance of module "%name%" when trying to delete module. Module directory has probably been deleted' => 'Ошибка создания экземпляра модуля "%name%" при попытке удаления модуля. Возможно директория модуля была удалена', + 'Failed to create new hook %s' => 'Ошибка создания нового хука %s', + 'Failed to deactivate hook with id %s' => 'Ошибка деактивации хука с id %s', + 'Failed to delete selected countries' => 'Ошибка удаления выбранных стран', + 'Failed to find a payment Module with ID=%mid for order ID=%oid' => 'Невозможно найти модуль оплаты с ID=%mid для заказа с ID=%oid', + 'Failed to load descriptor (module.xml) for module ID "%id".' => 'Невозможно загрузить описание (module.xml) модуля с ID "%id".', + 'Failed to load message with code \'%code%\', propably because it does\'nt exists.' => 'Ошибка при загрузке сообщения с кодом \'%code%\', возможно потому что оно не существует.', + 'Failed to open a writing stream on the file: %file' => 'Ошибка открытия файла для записи: %file', + 'Failed to open translation file %file. Please be sure that this file is writable by your Web server' => 'Не удалось открыть файл перевода %file. Пожалуйста, убедитесь, что этот файл доступен для записи веб-сервером', + 'Failed to send message %code. Failed recipients: %failed_addresses' => 'Ошибка при отсылке сообщения %code. Ошибочные получатели: %failed_addresses', + 'Failed to update language definition: %ex' => 'Не удалось обновить определения языка: %ex', + 'Fax' => 'Факс', + 'Feature' => 'Характеристика', + 'Feature value does not match FLOAT format' => 'Значение компонента не соответствует формату FLOAT', + 'Features' => 'Характеристики', + 'Features value' => 'Значение характеристик', + 'File format' => 'Формат файла', + 'File is too large, please retry with a file having a size less than %size%.' => 'Слишком большой файл. Попробуйте с файлом размером меньше %size%.', + 'File to upload' => 'Файл для загрузки', + 'Files with the following extension are not allowed: %extension, please do an archive of the file if you want to upload it' => 'Файлы со следующими расширениями не допустимы: %extension, пожалуйста сделайте заархивируйте файл если вы хотите загрузить его', + 'First Name' => 'Имя', + 'Firstname' => 'Имя', + 'Fixed Amount Discount' => 'Сумма фиксированной скидки', + 'Fixed amount discount for selected attribute values' => 'Фиксированная скидка для выбранных значений атрибутов', + 'Fixed amount discount for selected categories' => 'Фиксированная скидка для выбранных категорий', + 'Fixed amount discount for selected products' => 'Фиксированная скидка для выбранных товаров', + 'Folder' => 'Папка', + 'Folder page' => 'Страница папки', + 'Folder title *' => 'Название папки *', + 'For one ore more customers' => 'Для одного или более клиентов', + 'Format' => 'Формат', + 'Free product when buying one or more selected products' => 'Бесплатный товар при покупке одного или более выбранных товаров', + 'Front Office' => 'Магазин', + 'Full Name' => 'Полное имя', + 'Further submissions will be ignored during %time' => 'Последующие отправки будут игнорироваться в течение %time', + 'Greater than' => 'Больше, чем', + 'Greater than or equals' => 'Больше или равно', + 'HTML Message' => 'Сообщение в формате HTML', + 'HTML layout' => 'HTML каркас', + 'Home' => 'Главная', + 'Home page' => 'Домашняя страница', + 'Hook' => 'Хук', + 'Hook block' => 'Хук-блок', + 'Hook code' => 'Код хука', + 'Hook create form' => 'форма создания хука', + 'Hook title' => 'Название хука', + 'Hooks' => 'Хуки', + 'Host' => 'Хост', + 'I would like to receive the newsletter or the latest news.' => 'Я хотел бы подписаться на рассылку новостей.', + 'ISO 4217 code' => 'Код ISO 4217', + 'ISO 639-1 Code' => 'Код ISO 639-1', + 'ISO Alpha-2 code' => 'ISO Alpha-2 код', + 'ISO Alpha-3 code' => 'ISO Alpha-3 код', + 'ISO Code' => 'Код ISO', + 'If a translation is missing or incomplete :' => 'Если перевод не найден или не полный :', + 'If cart item (include quantity) count is %operator% %quantity%' => 'Если количестов элементов корзины (включая объем) %operator% %quantity% ', + 'If cart item count is %operator% %quantity%' => 'Если число элементов в корзине %operator% %quantity%', + 'If cart total amount is %operator% %amount% %currency%' => 'Если общая сумма корзины %operator% %amount% %currency%', + 'If checked, this hook will be used by a hook block. If not, by hook function.' => 'Если установлено, этот хук будет исользоваться хук-блоком. Иначе хук функцией.', + 'If you use automatic insert templates, you should use the method %method%' => 'Если вы используете автоматически вставляемые шаблоны, вы должны использовать метод %method%', + 'Image' => 'Изображение', + 'Import successfully done, %count row(s) have been changed' => 'Импорт успешно осуществлен, %count элементов было изменено', + 'Impossible to check value `%value` for `%type` type' => 'Невозможно проверить`%value` на `%type` тип', + 'Impossible to delete a customer who already have orders' => 'Невозможно удалить клиента, у которого уже есть заказы', + 'In' => 'В', + 'Include documents' => 'Включить документы', + 'Include images' => 'Включить изображения', + 'Information' => 'Сведения', + 'Invalid product_sale_elements' => 'Недопустимый product_sale_elements', + 'Invalid username or email.' => 'Некорректное имя пользователя или email.', + 'Invalid value "%value" for "%param" parameter in loop type: %type, name: %name' => 'Недопустимое значение "%value" для параметра «%param» в цикле типа: тип %, имя: %name', + 'Invalid value for walkMode parameter: %value' => 'Недопустимое значение параметра walkMode: %value', + 'Invoice' => 'счет-фактура', + 'Invoice choice' => 'Выбор счет-фактуры', + 'Is it the default product sale element ?' => 'Это элемент продажи товара по умолчанию ?', + 'Iso code for states. It depends of the country.' => 'Код ISO для штатов. Зависит от страны.', + 'It is not allowed to delete the default currency' => 'Невозможно удалить валюту по умолчанию', + 'It is not allowed to delete the default language' => 'Невозможно удалить язык по умолчанию', + 'JavaScript' => 'JavaScript', + 'Keep the most important part of your description in the first 150-160 characters.' => 'Сохраните самую важную часть описания в первых 150-160 символах.', + 'Language' => 'Язык', + 'Language name' => 'Название языка', + 'Languages' => 'Языки', + 'Last Name' => 'Фамилия', + 'Lastname' => 'Фамилия', + 'Layout' => 'Каркас', + 'Less than' => 'Менее чем', + 'Less than or equals' => 'Меньше или равно', + 'Log format *' => 'Формат журнала *', + 'Log level *' => 'Уровень журнала *', + 'Login failed. Please check your username and password.' => 'Ошибка входа. Пожалуйста, проверьте имя пользователя и пароль.', + 'Login name' => 'Логин', + 'Login page' => 'Страница логина', + 'Logs' => 'Логи', + 'Loop cannot implements multiple Search Interfaces : `PropelSearchLoopInterface`, `ArraySearchLoopInterface`' => 'Цикл не может реализовывать несколько Поисковых Интерфейсов : `PropelSearchLoopInterface`, `ArraySearchLoopInterface`', + 'Loop must implements \'PropelSearchLoopInterface\' to be timestampable' => 'Цикл реализующий \'PropelSearchLoopInterface\' должен быть timestampable', + 'Loop must implements \'PropelSearchLoopInterface\' to be versionable' => 'Цикл реализующий \'PropelSearchLoopInterface\' должен быть versionable', + 'Loop must implements one of the following interfaces : `PropelSearchLoopInterface`, `ArraySearchLoopInterface`' => 'Цикл должен реализовывать один из следующих интерфейсов : `PropelSearchLoopInterface`, `ArraySearchLoopInterface` ', + 'Lost password' => 'Восстановление пароля', + 'Mail template name' => 'Имя шаблона рассылки', + 'Mail template purpose' => 'Назначение шаблона рассылки', + 'Mailing system' => 'Система отправки почты', + 'Main address' => 'Основной адрес', + 'Main area' => 'Основная зона', + 'Make sure it uses keywords found within the page itself.' => 'Убедитесь что используются ключевые слова находящеся непосредственно на странице.', + 'Make sure that your title is clear, and contains many of the keywords within the page itself.' => 'Убедитесь, что ваш заголовок понятен и содержит много ключевых слов относящихся к странице.', + 'Make this address as my primary address' => 'Сделать этот адрес как моим основным адресом', + 'Maximum usage count reached for coupon %code' => 'Достигнуто максимальное количество использований купона %code', + 'Message' => 'Сообщение', + 'Message name' => 'Имя сообщения', + 'Message subject' => 'Тема сообщения', + 'Messages' => 'Сообщения', + 'Meta Description' => 'Описание метаданных', + 'Meta Keywords' => 'Ключевые слова метаданных', + 'Method Name' => 'Имя метода', + 'Missing or invalid data: %s' => 'Пропущены или некорректные данные: %s ', + 'Module' => 'Модуль', + 'Module "%name%" directory was not found' => 'Директория модуля "%name%" не найдена', + 'Module %name directory doesn\'t exists.' => 'Директория модуля %name не существует', + 'Module %name should have a config.xml in the Config directory.' => 'Модуль %name должен иметь config.xml в директории Config', + 'Module %name should have a module.xml in the Config directory.' => 'Модуль %name должен иметь module.xml в директории Config', + 'Module ID "%id" was not found.' => 'Модуль с ID "%id" не найден.', + 'Module ID not found' => 'ID модуля не найден', + 'Module hook' => 'Хук модуля', + 'Modules' => 'Модули', + 'More information about ISO 4217' => 'Больше информации об ISO 4217', + 'Name' => 'Имя', + 'Name *' => 'Имя *', + 'Name of the HTML layout file' => 'Имя файла каркаса HTML', + 'Name of the HTML template file' => 'Имя файла шаблона HTML', + 'Name of the text layout file' => 'Имя файла текстового каркаса ', + 'Name of the text template file' => 'Имя файла текстового шаблона', + 'Native' => 'Родной', + 'New Password' => 'Новый пароль', + 'Newsletter page' => 'Страница рассылок', + 'No %obj was created.' => 'Ни один %obj не был создан.', + 'No %obj was updated.' => 'Ни один %obj не был обновлен.', + 'No module found for code \'%item\'' => 'Ни один модуль не найден для кода \'%item\'', + 'No, I am a new customer.' => 'Нет, я новый клиент.', + 'None' => 'Нет', + 'Not equal to' => 'Не равен', + 'Not in' => 'Не в', + 'Notices' => 'Уведомления', + 'Numerical ISO Code' => 'Числовой ISO код', + 'Only files having the following mime type are allowed: %types%' => 'Допустимы только файлы со следующими mime типами: %types%', + 'Only hookable modules are displayed in this menu.' => 'Только модули с хуками отображены в этом меню.', + 'Only if order billing country is %op% %countries_list%' => 'Только если страна оплаты заказа %op% %countries_list% ', + 'Only if order shipping country is %op% %countries_list%' => 'Только если страна доставки заказа %op% %countries_list% ', + 'Order' => 'Заказ', + 'Order address ID not found' => 'ID адреса заказа не найден', + 'Order failed' => 'Ошибка заказа', + 'Order ref. %ref is now unpaid.' => 'Заказ ref. %ref сейчас не оплачен.', + 'Order ref. %ref, ID %id has been successfully paid.' => 'Заказ ref. %ref, ID %id успешно оплачен.', + 'Orders' => 'Заказы', + 'Overall' => 'Всего', + 'Page 404' => 'Страница 404', + 'Page Title' => 'Заголовок страницы', + 'Parent category' => 'Родительская категория', + 'Parent folder *' => 'Родительская папка *', + 'Password' => 'Пароль', + 'Password *' => 'Пароль *', + 'Password confirmation' => 'Подтверждение пароля', + 'Payment failed' => 'Платеж не прошел', + 'Payment gateway' => 'Платежный путь', + 'Per customer' => 'На клиента', + 'Percent' => 'Процент', + 'Percentage' => 'Процент', + 'Percentage discount for selected attribute values' => 'Процентная скидка для выбранных значений атрибутов', + 'Percentage discount for selected categories' => 'Процентная скидка для выбранных категорий', + 'Percentage discount for selected products' => 'Процентная скидка для выбранных товаров', + 'Percentage of the product price' => 'Процент от цены товара', + 'Phone' => 'Телефон', + 'Placed order' => 'Размещенный заказ', + 'Please accept the Terms and conditions in order to register.' => 'Пожалуйста, примите условия, чтобы зарегистрироваться.', + 'Please check your input: %error' => 'Пожалуйста, проверьте ваш вход: %error', + 'Please enter a valid email address' => 'Пожалуйста, введите корректный email адрес', + 'Please enter your email address' => 'Пожалуйста, введите ваш email', + 'Please enter your password' => 'Пожалуйста, введите ваш пароль', + 'Please select a category' => 'Пожалуйста, выберите категорию', + 'Please select an attribute' => 'Пожалуйста, выберите атрибут', + 'Please select at least one attribute value' => 'Пожалуйста, выберите по крайней мере одно значение атрибута', + 'Please select at least one category' => 'Пожалуйста, выберите по крайней мере одну категорию', + 'Please select at least one product' => 'Пожалуйста выберите хотя бы один товар', + 'Please select the category of the offred product' => 'Пожалуйста, выберите категорию предлагаемого товара', + 'Please select the offered product' => 'Пожалуйста, выберите предлагаемый товар', + 'Please upload a valid Zip file' => 'Пожалуйста загрузить корректный Zip файл', + 'Port' => 'Порт', + 'Postage' => 'Почтовые расходы', + 'Preferred locale' => 'Предпочтительный язык', + 'Prevent mailing template modification or deletion, except for super-admin' => 'Предотвратить изменение или удаление шаблона рассылки, за исключением супер администратора', + 'Prevent variable modification or deletion, except for super-admin' => 'Предотвратить модификацию или удаление переменной, за исключением супер администратора', + 'Price currency *' => 'Валюта цены *', + 'Processing cancelation of payment for order ref. %ref' => 'Обработка отмены оплаты для заказа ref. %ref', + 'Processing confirmation of order ref. %ref, ID %id' => 'Обработка подтверждения заказа ref. %ref, ID %id', + 'Prodcut ID *' => 'ID товара *', + 'Product' => 'Товар', + 'Product ID' => 'ID товара', + 'Product ID *' => 'ID товара *', + 'Product attributes' => 'Атрибуты товара', + 'Product base price excluding taxes *' => 'Базовая цена товара без учета налогов *', + 'Product base price with taxes' => 'Базовая цена товара с учетом налогов', + 'Product categories' => 'Категории товара', + 'Product clone' => 'Клон товара', + 'Product loop' => 'Цикл товара', + 'Product page' => 'Страница товара', + 'Product price excluding taxes' => 'Цена товара без учета налогов', + 'Product price excluding taxes *' => 'Цена товара без учета налогов *', + 'Product price including taxes' => 'Цена товара с учетом налогов', + 'Product price offset for each currency' => 'Сдвиг цены товара для каждой валюты', + 'Product reference (must be unique)' => 'Ссылка на товар (должна быть уникальной)', + 'Product reference *' => 'ССылка на товар *', + 'Product sale element ID *' => 'Элемент продажи товара ID *', + 'Product template' => 'Шаблон товара', + 'Product title' => 'Название товара', + 'ProductSaleElement modification' => 'Модификация ProductSaleElement', + 'Products' => 'Товары', + 'Profile' => 'Профиль', + 'Profile Code' => 'Код профиля', + 'Profile ID not found' => 'Не найден ID профиля', + 'Profile `code` already exists' => 'Профиль `code` уже существует', + 'Profiles' => 'Профили', + 'Purpose' => 'Назначение', + 'Purpose *' => 'Цель *', + 'Quantity' => 'Количество', + 'Range date End' => 'Конец отрезка времени', + 'Range date Start' => 'Начало отрезка времени', + 'Rate' => 'Курс', + 'Rate from %currencyCode' => 'Курс относительно %currencyCode', + 'Redirecting ...' => 'Перенаправление ...', + 'Redirecting to %url' => 'Перенаправление на %url', + 'Reference' => 'Ссылка', + 'Reference *' => 'Ссылка *', + 'Register' => 'Регистрация', + 'Remember me ?' => 'Запомнить меня ?', + 'Remove X percent to total cart' => 'Снять Х процентов с итоговой суммы корзины', + 'Replace by the default language' => 'Заменить языком по умолчанию', + 'Replace current document by this file' => 'Заменить текущий документ на этот файл', + 'Replace current image by this file' => 'Заменить текущее изображение этим файлом', + 'Reseller' => 'Посредник', + 'Rewriten URL' => 'Переписанный URL', + 'Rotated Text File' => 'Текстовый файл с ротацией', + 'Sale announce label' => 'Заголовок распродажи', + 'Sale price excluding taxes' => 'Отпускная цена без учета налогов', + 'Sale price including taxes' => 'Цена продажи с учетом налогов', + 'Sale title' => 'Название распродажи', + 'Saving %obj% for %parentName% parent id %parentId%' => 'Сохранение %obj% для %parentName% id родителя %parentId%', + 'Search' => 'Поиск', + 'Search page' => 'Страница поиска', + 'Select a default template for new products created in this category' => 'Выберите шаблон по умолчанию для товаров создаваемых в этой категории', + 'Select the brand logo' => 'Выберите логотип бренда', + 'Select the brand logo amongst the brand images' => 'Выберите логотип бренд из изображений бренда', + 'Select the categories of the products covered by this operation' => 'Выберите категории товаров покрываемые этой операцией', + 'Select the countries to delete from this shipping zone' => 'Выберите страны удаляемые из этой зоны доставки', + 'Select the countries to include in this shipping zone' => 'Выберите страны включаемые в эту зону доставки', + 'Select the discount type that will be applied to original product prices' => 'Выберите тип скидки которая будет применена к оригинальной цене товара', + 'Select the parent category of this category.' => 'Выберите родительскую категорию для этой категории.', + 'Select the product attributes included in this operation' => 'Выберите атрибуты товара включаемые в эту операцию', + 'Select the product brand, or supplier.' => 'Выберите бренд товара или поставщика.', + 'Select the products covered by this operation' => 'Выберите товары, охватываемые этой операции', + 'Select the virtual document' => 'Выберите виртуальный документ', + 'Service ID' => 'ID службы', + 'Shipping configuration' => 'Конфигурация доставки', + 'Shipping zone name' => 'Название зоны доставки', + 'Short additional text' => 'Дополнительный текст', + 'Short description text' => 'Текст краткого описания', + 'Show redirections *' => 'Показывать перенаправления *', + 'Sitemap' => 'Карта сайта', + 'Sorry, an error occured.' => 'К сожалению, произошла ошибка.', + 'Sorry, an error occured: %msg' => 'К сожалению, произошла ошибка: %msg', + 'Sorry, an error occured: %s' => 'К сожалению, произошла ошибка: %s', + 'Sorry, an error occurred: %err' => 'К сожалению, произошла ошибка: %err', + 'Sorry, no email defined for this administrator.' => 'К сожалению у этого администратора не указан email', + 'Sorry, you are not allowed to perform this action.' => 'К сожалению, вы не можете совершить это действие.', + 'Sorry, you\'re not allowed to perform this action' => 'К сожалению, вы не можете совершить это действие', + 'Source IP' => 'IP источника', + 'Start date' => 'Дата начала', + 'Start date and expiration date are inconsistent' => 'Дата начала и окончания не соответствуют друг другу', + 'Start date of sales' => 'Дата начала продаж', + 'State *' => 'Штат *', + 'State ID %id not found' => 'Штат с ID %id не найден', + 'State title' => 'Название штата', + 'Stock' => 'Остаток на складе', + 'Store Business Identification Number (SIRET, etc).' => 'Идентификационный бизнес номер магазина (SIRET, и т.д.)', + 'Store Information' => 'Информация магазина', + 'Store configuration failed.' => 'Ошибка конфигурации магазина.', + 'Store description' => 'Описание магазина', + 'Store email address' => 'Адрес email магазина', + 'Store logs into text file' => 'Хранить логи в текстовом файле', + 'Store logs into text file, up to a certian size, then a new file is created' => 'Хранить логи в текстовом файле до определенного размера. Затем будет создан новый файл', + 'Store name' => 'Название магазина', + 'Street Address' => 'Адрес', + 'Street Address ' => 'Адрес', + 'Strictly use the requested language' => 'Строго использовать запрошенный язык', + 'Subject' => 'Тема', + 'Summary' => 'Краткое описание', + 'Symbol' => 'Символ', + 'System' => 'Система', + 'System configuration' => 'Конфигурация системы', + 'System log configuration failed.' => 'Ошибка конфигурации системных логов.', + 'Tax' => 'Налог', + 'Tax ID not found in tax list JSON' => 'ID налога не найдено в JSON списке налогов', + 'Tax list is not valid JSON' => 'Некорректный JSON для списка налогов', + 'Tax rule ID not found' => 'Налоговое правило с ID не найдено', + 'Tax rule for this product *' => 'Налоговое правиле для этого товара *', + 'Taxes' => 'Налоги', + 'Taxes rules' => 'Налоговые правила', + 'Template' => 'Шаблон', + 'Template Name *' => 'Имя шаблона *', + 'Templates' => 'Шаблоны', + 'Text File' => 'Текстовый файл', + 'Text Message' => 'Текстовое сообщение', + 'The %name module definition has not been initialized.' => 'Определение модуля %name не может быть инициализировано.', + 'The %name module descriptor has not been initialized.' => 'Дескриптор модуля %name не может быть инициализировано.', + 'The %obj_name id \'%id\' doesn\'t exist' => 'ID %obj_name \'%id\' не существует', + 'The HTML TITLE element is the most important element on your web page.' => 'Элемент HTML TITLE самый важный элемент вашей страницы.', + 'The archiver :name is not available. Please install the php extension :extension first.' => 'Архиватор :name не доступен. Пожалуйста, сначала установите расширение php - :extension ', + 'The archiver identifier "%archiverId" doesn\’t exist' => 'Идентификатор архиватора "%archiverId" не существует', + 'The brand name or title' => 'Имя или заголовок бренда', + 'The cart item count should match the condition' => 'Количество элементов корзины должно соответствовать условию', + 'The category title' => 'Имя категории', + 'The class "%class" doesn\'t exist' => 'Класс "%class" не существует', + 'The class "%class" must extend %baseClass' => 'Класс "%class" должен расширять %baseClass', + 'The container should not be null in this form. Please use the FormFactory to get an instance.' => 'container не должен быть null в этой форме. Используйте FormFactory чтобы получить экземпляр.', + 'The coupon applies if the cart contains at least one product of the selected categories' => 'Купон применяется если корзина содержит по крайне мере один товар из указанных категорий', + 'The coupon applies if the cart contains at least one product of the specified product list' => 'Купон применяется если корзина содержит по крайне мере один товар из указанного списка товаров', + 'The coupon applies to some customers only' => 'Купон применяется только к некоторым клиентам', + 'The coupon applies to the selected billing countries' => 'Купон применяется к выбранным странам оплаты', + 'The coupon applies to the selected delivery countries' => 'Купон применяется к выбранным странам доставки', + 'The coupon code \'%code\' already exist. Please choose another coupon code' => 'Код купона \'%code\' уже существует. Пожалуйста выберите другой код купона', + 'The coupon code \'%code\' already exists. Please choose another coupon code' => 'Код купона \'%code\' уже существует. Пожалуйста выберите другой код купона', + 'The coupon is valid after a given date' => 'Купон действителен после указанной даты', + 'The date after which sales are de-activated. Please use %fmt format.' => 'Дата после которой распродажи деактивируются. Пожалуйста, используйте формат %fmt', + 'The date from which sales are active. Please use %fmt format.' => 'Дата начиная с которой распродажи становятся активными. Пожалуйста, используйте формат %fmt', + 'The detailed description.' => 'Детальное описание', + 'The email address "%mail" was not found.' => 'Адрес email "%mail" не найден.', + 'The extension "%extension" is not allowed' => 'Ресширение "%extension" не позволено', + 'The file %path has been successfully downloaded' => 'Файл %path был успешно скачан', + 'The following columns are missing: %columns' => 'Следующие столбцы пропущены: %columns', + 'The image which replaces an undefined country flag (%file) was not found. Please check unknown-flag-path configuration variable, and check that the image exists.' => 'Изображение, которым заменяется неизвестный флаг страны (%file) не найдено. Пожалуйста проверьте конфигурационную переменную unknown-flag-path и то что изображение существует..', + 'The language "%id" doesn\'t exist' => 'Язык "%id" не существует', + 'The lost admin password recovery feature is disabled.' => 'Востановление пароля администратора отключено.', + 'The mailing template in HTML format.' => 'Шаблон сообщения в формате HTML.', + 'The mailing template in text-only format.' => 'Шаблон рассылки только в текстовом формате.', + 'The method %method% doesn\'t exist in classname %classname%' => 'Метод %method% не существет в классе %classname%', + '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.' => 'Модуль "%name%" сейчас используется по крайне мере в одном заказе и не может быть удален.', + 'The module %module has been installed successfully.' => 'Модуль %module был успешно установлен.', + 'The module %name is already installed in the same or greater version.' => 'Модуль %name уже установлен с такой же или более новой версией.', + 'The module %name requires Thelia %version or newer' => 'Модуль %name требует версию Thelia %version или новее', + 'The module has to be activated.' => 'Модуль активирован.', + 'The module is not valid : %message' => 'Некорректный модуль : %message', + 'The module zip file' => 'Zip файл модуля', + 'The product document id %id doesn\'t exists' => 'Документ товара с id %id не существует', + 'The product image id %id doesn\'t exists' => 'Изображение товара с id %id не существует', + 'The product sale element id %id doesn\'t exist' => 'Элемента продажи товара с id %id не существует', + 'The product sale elements id %id doesn\'t exist' => 'Элементов продажи товара с id %id не существует', + 'The product sale elements id %id doesn\'t exists' => 'Элементов продажи товара с id %id не существует', + 'The rate from %currencyCode: Price in %currencyCode x rate = Price in this currency' => 'Курс относительно %currencyCode: Цена в %currencyCode * курс = Цена в этой валюте', + 'The resource %res has not been found' => 'Ресурс %res не найден', + 'The sale announce label, such as Sales ! or Flash Sales !' => 'Заголовок распродажи, например \'Распродажа !\' или \'Быстрая Распродажа !\'', + 'The sale name or descriptive title' => 'Название распродажи или описательный заголовок', + 'The sale name or title' => 'Название распродажи', + 'The serializer identifier "%serializerId" doesn\’t exist' => 'Идентификатор сериализатора "%serializerId" не существует', + 'The service id that will handle the hook (defined in the config.xml file of the module).' => 'ID сервиса обрабатывающего этот хук (указан в файле config.xml модуля).', + 'The store fax number.' => 'Факс магазина.', + 'The store phone number.' => 'Телефон магазина.', + 'The symbol, such as $, £, €...' => 'Символ, напр. $, £, €...', + 'The type %type is not valid' => 'Некорректный тип %type ', + 'The zip code format' => 'Формат индекса', + 'There are no files to associate.' => 'Нет файлов для привязки', + 'There is no id "%id" in the export categories' => 'Нет id "%id" в экспорте категорий', + 'There is no id "%id" in the exports' => 'Нет id "%id" в экспортах', + 'There is no id "%id" in the import categories' => 'Нет id "%id" в импорте категорий', + 'There is no id "%id" in the imports' => 'Нет id "%id" в импортах', + 'There is no id "%ref" in the imports' => 'Нет ссылки "%ref" в импортах', + 'There is no ref "%ref" in the exports' => 'Нет ссылки "%ref" в экспортах', + 'There\'s a conflict between your file extension "%ext" and the mime type "%mime"' => 'Конфликт расширения "%ext" и mime типа "%mime"', + 'This PHP extension should be installed and loaded.' => 'Это расширение PHP должно быть установлено и загружено.', + 'This administrator login already exists' => 'Логин администратора уже существует', + 'This brand is online' => 'Этот бренд включен', + 'This category is online' => 'Эта категория включена', + 'This condition is always true' => 'Это условие всегда истинно', + 'This content is online.' => 'Контент включен.', + 'This country has states / provinces' => 'У этой страны есть штаты / провинции', + 'This country is online' => 'Эта страна включена', + 'This coupon adds a free product to the cart if one of the selected products is in the cart.' => 'Этот купон добавляет бесплатный товар в корзину, если один из выбранных товаров уже в корзине.', + 'This coupon does not exists' => 'Купон не существует', + 'This coupon subtracts from the order total a percentage of the price of each product which belongs to the selected categories. If the discount is greater than the total order, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.' => 'Этот купон вычитает из общей суммы заказа процент от цены каждого товара, который принадлежит выбранным категориям. Если скидка больше общей стоимости, клиент оплачивает только доставку или ничего, если купон так же предоставляет бесплатную доставку.', + 'This coupon subtracts from the order total the specified percentage of each product price which uses the selected attribute values. If the discount is greater than the total order, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.' => 'Этот купон вычитает из общей суммы заказа указанный процент от каждой цены товара, который использует выбранные значения атрибутов. Если скидка больше общей стоимости, клиент оплачивает только доставку или ничего, если купон так же предоставляет бесплатную доставку.', + 'This coupon subtracts from the order total the specified percentage of each selected product price. If the discount is greater than the total order, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.' => 'Этот купон вычитает из общей суммы заказа указанный процент от каждой выбранной цены товата. Если скидка больше общей стоимости, клиент оплачивает только доставку или ничего, если купон так же предоставляет бесплатную доставку.', + 'This coupon subtracts the specified amount from the order total for each product which belongs to the selected categories. If the discount is greater than the total order, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.' => 'Этот купон вычитает установленую сумму из общей стоимости заказа для каждого товара принадлежащего выбранным категориям. Если скидка больше общей стоимости, клиент оплачивает только доставку или ничего, если купон так же предоставляет бесплатную доставку.', + 'This coupon subtracts the specified amount from the order total for each product which uses the selected attribute values. If the discount is greater than the total order, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.' => 'Этот купон вычитает указанную сумму из общей суммы заказа для каждого товара, который использует выбранное значение атрибута. Если скидка больше общей стоимости, клиент оплачивает только доставку или ничего, если купон так же предоставляет бесплатную доставку.', + 'This coupon subtracts the specified amount from the order total for each selected product. If the discount is greater than the total order, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.' => 'Этот купон вычитает установленую сумму из общей стоимости заказа для каждого выбранного товара. Если скидка больше общей стоимости, клиент оплачивает только доставку или ничего, если купон так же предоставляет бесплатную доставку.', + 'This coupon will offert a flat percentage off a shopper\'s entire order (not applied to shipping costs or tax rates). If the discount is greater than the total order corst, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.' => 'Этот купон будет предлагать фиксированный процент от всего заказа покупателя (не распространяется на стоимость доставки и налогов). Если скидка больше общей стоимости, клиент оплачивает только доставку или ничего, если купон так же предоставляет бесплатную доставку.', + 'This coupon will subtracts a set amount from the total cost of an order. If the discount is greater than the total order corst, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.' => 'Этот купон вычитает установленую сумму из общей стоимости заказа. Если скидка больше общей стоимости, клиент оплачивает только доставку или ничего, если купон так же предоставляет бесплатную доставку.', + 'This document is online' => 'Этот документ включен', + 'This email already exists.' => 'E-mail уже существует.', + 'This email does not exists' => 'Этот email не существует', + 'This folder is online.' => 'Эта папка включена', + 'This hook is specific to a module (delivery/payment modules).' => 'Этот хук специфичен для модуля (модули доставки/оплаты).', + 'This image is online' => 'Это изображение включено', + 'This is a comma separated list of email addresses where store notifications (such as order placed) are sent.' => 'Список адресов email через запятую, куда будут отсылаться уведомления магазина (например по новым заказам).', + 'This is an identifier that will be used in the code to get this message' => 'Идентификатор используемый в коде чтобы получить это сообщение', + 'This is the contact email address, and the sender email of all e-mails sent by your store.' => 'Это контактный адрес email и адрес отправителя для всех сообщений посылаемых вашим магазином.', + 'This is the message purpose, such as \'Order confirmation\'.' => 'Это назначение сообщения, например \'Подтверждение заказа\'.', + 'This is the name used on the login screen' => 'Это имя используемое на странице логина', + 'This is the subject of the e-mail, such as \'Your order is confirmed\'.' => 'Это тема сообщения, например \'Ваш заказ подтвержден\'.', + 'This module has no Markdown documentation.' => 'У этого модуля нет документации в Markdown', + 'This product does not have a physical presence' => 'Это виртуальный товар', + 'This product is on sale' => 'Этот товар в распродаже', + 'This product is online' => 'Этот товар включен', + 'This product reference is already assigned to another product.' => 'Эта ссылка на товар уже назначена другому товару.', + 'This product_sale_elements_id does not exists for this product : %d' => 'Этот product_sale_elements_id не существует для данного товара : %d', + 'This state doesn\'t belong to this country.' => 'Этот штат не принадлежит этой стране.', + 'This state is online' => 'Штат включен', + '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 value should not be blank.' => 'Это значение не может быть пустым.', + 'This zip code should respect the following format : %format.' => 'Индекс должен отвечать следующему формату : %format.', + 'Timeout' => 'Таймаут', + 'Title' => 'Заголовок', + 'Title *' => 'Заголовок *', + 'Title ID not found' => 'ID заголовка не найден', + 'To activate module %name, the following modules should be activated first: %modules' => 'Для акстивации модуля %name, сначала должны быть активированы следующие модули: %modules', + 'Tools' => 'Инструменты', + 'Translations' => 'Переводы', + 'Tried to download a file, but the URL was not valid: %url' => 'Попытка скачать файл, но URL некорректный: %url', + 'Type' => 'Тип', + 'URL_ALREADY_EXISTS' => 'Этот URL уже существует', + 'Unable to get module code from the fullnamespace element of the module descriptor: \'%val\'' => 'Невозможно получить код модуля из элемента fullnamespace дескриптора модуля: \'%val\'', + 'Unable to process your request. Please try again (%err).' => 'Невозможно обработать ваш запрос. Попробуйте еще раз (%err).', + 'Unconditional usage' => 'Безусловное использование', + 'Unconditionnal usage' => 'Безусловное использование', + 'Undefined loop argument "%name"' => 'Неопределенный аргумент цикла "%name"', + 'Undefined search mode \'%mode\'' => 'Неопределенный режим поиска \'%mode\'', + 'Unknown order ID: %id' => 'Не известный ID заказа: %id', + 'Unsupported magic method %name. only getArgname() is supported.' => 'Не поддерживаемый магический метод %name. Только getArgname() поддерживается.', + 'Unsupported type' => 'Неподдерживаемый тип', + 'Update customer account' => 'Обновить аккаунт клиента', + 'Use a N for a number, L for Letter, C for an iso code for the state.' => 'Используйте N для цифры, L для буквы, C для iso кода для штатов.', + 'Use the keyword phrase in your URL.' => 'Используйте ключевую фразу в вашем URL.', + 'Used in your store front' => 'Используется на страницах магазина', + 'Username' => 'Имя пользователя', + 'Username or e-mail address *' => 'Имя пользователя или e-mail адрес *', + 'Valid only from %date% to the coupon expiration date' => 'Действителен начиная с %date% до даты окончания купона', + 'Value' => 'Значение', + 'Value %val for Discount Amount is invalid. Please enter a positive value.' => 'Некорректное значение %val для фиксированной скидки. Пожалейста, введите положительное число.', + 'Value %val for Percent Discount is invalid. Please enter a positive value between 1 and 100.' => 'Некорректное значение %val для процентной скидки. Пожалейста, введите положительное число между 1 и 100.', + 'Value *' => 'Значение *', + 'Value create form' => 'форма создания значения', + 'Variable' => 'Переменная', + 'Variables' => 'Переменные', + 'Virtual document' => 'Виртуальный документ', + 'Warnings' => 'Предупреждения', + 'We\'re sorry, this PDF invoice is not available at the moment.' => 'К сожалению эта счет-фактура в PDF не доступна в текущий момент.', + 'Weight' => 'Вес', + 'When using the %method% method you can automatically render or dump templates or add CSS and JS files (e.g.: render:mytemplate.html;js:assets/js/myjs.js)' => 'Когда используется метод %method% вы можете автоматически генерировать или выводить шаблоны, или добавлять CSS и JS файлы (например: render:mytemplate.html;js:assets/js/myjs.js)', + 'Wrong country definition' => 'Некорректное определение страны', + 'Wrong form method, %s expected.' => 'Некорректный метод формы. Ожидается %s', + 'Yes, I have a password :' => 'Да, у меня есть пароль :', + 'You are already registered!' => 'Вы уже зарегистрированы!', + 'You don\'t need to use commas or other punctuations.' => 'Вам не нужно использовать запятые или другую пунктуацию.', + 'You have to configure your store email first !' => 'Сначала вы должны настроить email магазина !', + 'You must select at least one attribute.' => 'Вы должны выбрать по крайне мере один атрибут.', + 'You should select a state for this country.' => 'Вы должны выбрать штат для этой страны.', + 'You\'ve submitted this form too many times. ' => 'Вы отправили форму слишком много раз', + 'Your Email Address' => 'Ваш Email адрес', + 'Your Message' => 'Сообщение', + 'Your configuration seems to be ok. Checked out your mailbox : %email%' => 'Ваша конфигурация выглядит нормально. Проверьте ваш почтовый ящик : %email%', + 'Your current password does not match.' => 'Текущий пароль не подходит.', + 'Your zip must contain 1 root directory which is the root folder directory of your module' => 'Zip файл должен содержать 1 корневую директорию являющуюся корневой директорией вашего модуля', + 'Zip code' => 'Индекс', + 'Zone' => 'Зона', + 'accessories table header' => 'заголовок таблицы аксессуаров', + 'accessories table row' => 'строка таблицы аксессуаров', + 'add to all form' => 'добавить во все формы', + 'additional information' => 'дополнительная информация', + 'address create form' => 'форма создания адреса', + 'address delete form' => 'форма удаления адреса', + 'address update form' => 'форма обновления адреса', + 'after addresse area' => 'после зоны адреса', + 'after combinations' => 'после комбинаций', + 'after footer' => 'после подвала', + 'after javascript include' => 'после включения javascript', + 'after javascript initialisation' => 'после инициализации javascript', + 'after product listing' => 'после списка товаров', + 'after the information area' => 'после зоны информации', + 'after the main content area' => 'после основной зоны контента', + 'after the opening of the body tag' => 'после открытия тега body', + 'after the opening of the head tag' => 'после открытия тега head', + 'after the order summary' => 'после итогов заказа', + 'after top bar' => 'после верхней панели', + 'after top menu' => 'после верхнего меню', + 'api id %id does not exists' => 'api с id %id не существует', + 'at the bottom' => 'внизу', + 'at the bottom of column 1' => 'внизу столбца 1', + 'at the bottom of information area' => 'внизу зоны информации', + 'at the bottom of the catalog' => 'внизу каталога', + 'at the bottom of the detail area' => 'внизу зоны деталей', + 'at the bottom of the footer' => 'внизу подвала', + 'at the bottom of the form' => 'внизу формы', + 'at the bottom of the header' => 'внизу шапки', + 'at the bottom of the main area' => 'внизу основной зоны', + 'at the bottom of the shipping area' => 'внизу зоны доставки', + 'at the bottom of the sidebar' => 'внизу сайдбара', + 'at the bottom of the system area' => 'внизу системной зоны', + 'at the bottom of the top bar' => 'внизу верхней панели', + 'at the top' => 'вверху', + 'at the top of the catalog area' => 'вверху зоны каталога', + 'at the top of the column' => 'вверху столбца', + 'at the top of the configuration' => 'ввеху конфигурации', + 'at the top of the detail' => 'вверху деталей', + 'at the top of the footer' => 'верх подвала', + 'at the top of the form' => 'вверху формы', + 'at the top of the header' => 'вверху шапки', + 'at the top of the main area' => 'вверху основной зоны', + 'at the top of the shipping area' => 'вверху зоны доставки', + 'at the top of the sidebar' => 'вверху сайдбара', + 'at the top of the system area' => 'вверху системной зоны', + 'at the top of the top bar' => 'вверху верхней панели', + 'attributes table header' => 'заголовок таблицы атрибутов', + 'attributes table row' => 'строка таблицы атрибутов', + 'before combinations' => 'перед комбинациями', + 'before footer' => 'перед подвалом', + 'before the end body tag' => 'перед закрытием тега body', + 'before the end of the head tag' => 'перез закрытием тега head', + 'before the main content area' => 'перед основной зоной контента', + 'before top menu' => 'перед верхним меню', + 'before topbar' => 'перед верхней панелью', + 'block' => 'блок', + 'bottom' => 'низ', + 'bottom of the footer' => 'низ подвала', + 'cURL errno %errno, http code %http_code on link "%path": %error' => 'ошибка cURL %errno, http code %http_code по ссылке "%path": %error', + 'caption' => 'заголовок', + 'categories table header' => 'заголовок таблицы категорий', + 'categories table row' => 'строка таблицы категорий', + 'combination delete form' => 'форма удаления комбинации', + 'combinations list caption' => 'заголовок списка комбинаций', + 'configuration' => 'конфигурация', + 'configuration JavaScript' => 'конфигурация JavaScript', + 'configuration bottom' => 'конфигурация низ', + 'content' => 'контент', + 'content area' => 'зона контента', + 'content delete form' => 'фарма удаления контента', + 'content edit JavaScript' => 'редактирование контента JavaScript', + 'contents table header' => 'заголовок таблицы контентов', + 'contents table row' => 'строка таблицы контентов', + 'context' => 'контекст', + 'country delete form' => 'форма удаления страны', + 'create JavaScript' => 'создать JavaScript', + 'create form' => 'создать форму', + 'customer account' => 'аккаунт клиента', + 'date format' => 'формат даты', + 'date/time format' => 'формат даты/времени', + 'decimal separator' => 'разделитель для десятичной точки', + 'delete form' => 'удалить форму', + 'delivery address' => 'адрес доставки', + 'delivery module %s is not a Thelia\Module\DeliveryModuleInterface' => 'модуль доставки %s не реализует Thelia\Module\DeliveryModuleInterface', + 'details pricing form' => 'форма деталей ценообразования', + 'details promotion form' => 'форма деталей продвижения', + 'email' => 'email', + 'email confirmation is not the same as email field' => 'подтверждение email не совпадает с email', + 'email system JavaScript' => 'система email JavaScript', + 'extra area' => 'дополнительная зона', + 'extra payment zone' => 'дополнительная зона оплаты', + 'features table row' => 'строка таблицы характеристик', + 'features-table-header' => 'заголовок таблицы характеристик', + 'folders table header' => 'заголовок таблицы папок', + 'folders table row' => 'строка таблицы папок', + 'footer body' => 'тело подвала', + 'header' => 'заголовок', + 'hook delete form' => 'форма удаления хука', + 'hook edit JavaScript' => 'редактирования хука JavaScript', + 'hour(s)' => 'часов', + 'id delete form' => 'форма удаления id', + 'if successful response' => 'если успешный ответ', + 'imprint' => 'штамп', + 'in footer' => 'в подвале', + 'in the header' => 'в шапке', + 'in the menu catalog' => 'в меню каталога', + 'in the menu configuration' => 'в меню конфигурации', + 'in the menu customers' => 'в меню клиентов', + 'in the menu folders' => 'в меню папок', + 'in the menu modules' => 'в меню модулей', + 'in the menu orders' => 'в меню заказов', + 'in the menu tools' => 'в меню инструментов', + 'in top menu items' => 'в элементах верхнего меню', + 'inside top bar' => 'внутри верхней панели', + 'javascript' => 'javascript', + 'javascript initialization' => 'инициализация javascript', + 'label' => 'метка', + 'language locale' => 'локаль языка', + 'language selection page' => 'Страница выбора языка', + 'list JavaScript' => 'список JavaScript', + 'list caption' => 'заглавие списка', + 'list header' => 'заголовок списка', + 'list row' => 'список строка', + 'logs JavaScript' => 'логи JavaScript', + 'mailing system modification' => 'модификация системы рассылки', + 'main area' => 'основная зона', + 'middle' => 'середина', + 'minute(s)' => 'минут', + 'password confirmation is not the same as password field' => 'подтверждение пароля не совпадает с паролем', + 'password must be composed of at least 4 characters' => 'пароль должен содержать минимум 4 символа', + 'payment module %s is not a Thelia\Module\PaymentModuleInterface' => 'модуль оплаты %s не реализует Thelia\Module\PaymentModuleInterface', + 'pdf' => 'pdf', + 'permanent discount (in percent)' => 'постоянная скидка (в процентах)', + 'photo gallery' => 'фото галерея', + 'plain, login, cram-md5 or empty' => 'plain, login, cram-md5 или пусто', + 'primary navigation' => 'основная навигация', + 'product list' => 'список товаров', + 'quantity value is not valid' => 'значение количества некорректно', + 'received value `%value` does not match `%type` type' => 'полученное значение `%value` не соответствует типу `%type`', + 'remove to all form' => 'форма удалить все ', + 'row' => 'строка', + 'rule create form' => 'форма создания правила', + 'rule delete form' => 'форма удаления правила', + 'rule edit JavaScript' => 'редактирование правила JavaScript', + 'secondary navigation' => 'вторичная навигация', + 'ssl, tls or empty' => 'ssl, tls или пусто', + 'stock edit form' => 'форма редактирования остатков', + 'table header' => 'заголовок таблицы', + 'table row' => 'строка таблицы', + 'tax rule' => 'налоговое правило', + 'the body of the sidebar' => 'тело сайдбара', + 'this product id does not exists : %d' => 'id товара не существует : %d', + 'thousands separator' => 'разделитель для тысяч', + 'time format' => 'формат времени', + 'type' => 'тип', + 'update JavaScript' => 'обновление JavaScript', + 'update form' => 'форма обновления', + 'value table header' => 'заголовок таблицы значения', + 'value table row' => 'строка таблицы значения', +); diff --git a/core/lib/Thelia/Config/I18n/sk_SK.php b/core/lib/Thelia/Config/I18n/sk_SK.php new file mode 100644 index 00000000..9665ad00 --- /dev/null +++ b/core/lib/Thelia/Config/I18n/sk_SK.php @@ -0,0 +1,518 @@ + ' obsah - fomulár pre tvorbu', + ' note: only non-visible documents can be associated.' => ' poznámka: len neviditeľné dokumenty môžu byť spojené.', + '"%param" parameter cannot be empty in loop type: %type, name: %name' => '"%param" parameter nemôže byť prázdny v loop-e typu: % typ, meno: %name', + '"%param" parameter is missing in loop type: %type, name: %name' => 'Chýba parameter "%param" v loop-e typu: % typ, meno: %name', + '%module (version: %version)' => '%module (verzia: %version)', + '%n for number, %c for the currency code, %s for the currency symbol' => '%n číslo, %c pre kód meny, %s symbolu meny', + '%obj SEO modification' => '%obj SEO úpravy', + '%obj creation' => '%obj vytvorenie', + '%obj modification' => '%obj modifikácia', + '%obj%s deleted successfully' => '%obj%s úspešne vymazané', + '%s has dependency to module %s. You have to deactivate this module before.' => '%s má závislosť na modul %s. Mali by ste predtým deaktivovať tento modul.', + '%s have dependencies to module %s. You have to deactivate these modules before.' => '%s sú závislé od modulu %s. Mali by ste predtým tieto moduly deaktivovať.', + '%type% position updated' => '%type% pozícia aktualizovaná', + '%type% visibility updated' => '%type% viditeľnosť aktualizovaná', + 'A comma separated list of email addresses' => 'Čiarkou oddelený zoznam e-mailových adries', + 'A currency with code "%name" already exists.' => 'Mena s kódom "%name" už existuje.', + 'A descriptive title' => 'Popisný názov', + 'A message with name "%name" already exists.' => 'Správa s názvom "%name" už existuje.', + 'A name such as Europe or Overseas' => 'Názov ako je Európa alebo Zámorie', + 'A product with reference %ref already exists. Please choose another reference.' => 'Výrobok s odkazom % ref už existuje. Zvoľte prosím iný odkaz.', + 'A short description, used when a summary or an introduction is required' => 'Krátky popis, používa sa, keď je vyžadovaný súhrn alebo uvedenie', + 'A short text, used when an additional or supplemental information is required.' => 'Krátky text, používaný, ak sa požadujú dodatočné alebo doplnkové informácie.', + 'A user already exists with this email address. Please login or if you\'ve forgotten your password, go to Reset Your Password.' => 'Užívateľ s takou e-mailovou adresou existuje. Prosím, prihláste sa alebo ak ste zabudli svoje heslo, prejdite na Reset hesla.', + 'A value for attribute "%name" is already present in the combination' => 'Hodnota pre atribút "%name" je už prítomná v danej kombinácii', + 'A variable with name "%name" already exists.' => 'Premenná s názvom "%name" už existuje.', + 'Activate logs only for these IP Addresses' => 'Aktivovať logovacie záznamy len pre tieto IP adresy', + 'Activate logs only for these files' => 'Aktivovať logovacie záznamy len pre tieto súbory', + 'Activate this sale' => 'Aktivovať tento výpredaj', + 'Active' => 'Aktívny', + 'Add to all product templates' => 'Pridať šablóny pre všetky produkty', + 'Additional address' => 'Ďalšie adresy', + 'Additional address information' => 'Doplňujúce informácie o adrese', + 'Address ID not found' => 'ID identifikátor adresy nebol nájdený', + 'Address Line 2' => 'Adresa, riadok 2', + 'Address Line 3' => 'Adresa, riadok 3', + 'Address creation' => 'Vytvorenie adresy', + 'Address label' => 'Menovka s adresou', + 'Address update' => 'Aktualizovať adresu', + 'Address.' => 'Adresa.', + 'Addresses for this country need a zip code' => 'Pre kompletnú adresu je potrebné uviesť Psč', + 'Administrator' => 'Administrátor', + 'Administrator ID not found' => 'ID identifikátor administátora nebol nájdený', + 'Administrator email address' => 'E-mail na Administrátora', + 'Administrators' => 'Správcovia', + 'Advertise this product as new' => 'Propagovať tento produkt ako nový', + 'Alerts' => 'Upozornenia', + 'All Products' => 'Všetky produkty', + 'All countries' => 'Všetky krajiny', + 'All shipping methods' => 'Všetky spôsoby dopravy', + 'Amount' => 'Množstvo', + 'An administrator with this email address already exists' => 'Účet s touto e-mailovou adresou už existuje', + 'An invalid token was provided, your password cannot be changed' => 'Neplatný token boli poskytnuté, nie je možné zmeniť heslo', + 'Apply exchange rates on price in %sym' => 'Uplatňovať výmenný kurz na ceny v %sym', + 'Archive Format' => 'Formát archívu', + 'Associate documents' => 'Pridružené dokumenty', + 'Associate images' => 'Pridružené obrázky', + 'At least one of cart products categories is %op% %categories_list%' => 'Aspoň jedna z kategórií produktov v košíku je %op% %categories_list%', + 'Attribut' => 'Vlastnosť', + 'Attribute ID:Attribute AV ID' => 'Identifikácia atribútu ID:Attribute AV', + 'Attribute value' => 'Hodnota atribútu', + 'Attributes' => 'Vlastnosti', + 'Attributes value' => 'Atribúty hodnota', + 'Auth mode' => 'Režim overovateľa', + 'Automatic rendered templates' => 'Automaticky poskytované šablóny', + 'Available quantity' => 'Dostupné množstvo', + 'Available quantity *' => 'Dostupné množstvo *', + 'Available shipping zones' => 'Dostupné zóny doručenia', + 'Back Office' => 'Back-Office', + 'Bad tax list JSON' => 'Chybný daňový zoznam JSON', + 'Billing country' => 'Krajina pre fakturáciu', + 'Billing country is' => 'Krajina pre fakturáciu je', + 'Brand' => 'Značka', + 'Brand / Supplier' => 'Značku / dodávateľ', + 'Brand name' => 'Názov značky', + 'Brands' => 'Značky', + 'Business ID' => 'ID obchodu', + 'CSS' => 'CSS', + 'Cannot disable the default language' => 'Predvolený jazyk sa nedá zakázať', + 'Cannot find a default country. Please define one.' => 'Nie je možné nájsť predvolenú krajinu. Prosím vyberte jednu.', + 'Cannot hide the default language' => 'Predvolený jazyk sa nedá skryť', + 'Cart' => 'Košík', + 'Cart contains at least a product %op% %products_list%' => 'Košík obsahuje aspoň jeden produkt %op% %products_list%', + 'Cart contains categories condition' => 'Košík obsahuje kategórie stav', + 'Cart contains specific products' => 'Košík obsahuje špecifické produkty', + 'Cart item count' => 'Počet položiek v košíku', + 'Cart item count is' => 'Počet položiek v košíku je', + 'Cart item include quantity count' => 'Košík obsahuje sčítavanie položiek', + 'Cart item include quantity count is' => 'Košík položka zahŕňať množstvo, ako je', + 'Cart total amount' => 'Celková hodnota košíka', + 'Cart total amount is' => 'Celková hodnota košíka je', + 'Catalog' => 'Katalóg', + 'Catalog configuration' => 'Usporiadanie katalógu', + 'Categories' => 'Kategórie', + 'Category' => 'Kategória', + 'Category page' => 'Stránka kategórie', + 'Category title' => 'Názov kategórie', + 'Cellphone' => 'Mobil', + 'Change password' => 'Zmeniť heslo', + 'Check the total Cart amount in the given currency' => 'Skontrolujte, či je celková hodnota košíka vo vybranej mene', + 'City' => 'Mesto', + 'Code' => 'Kód', + 'Compagny' => 'Spoločnosť', + 'Company' => 'Spoločnosť', + 'Company Name' => 'Názov spoločnosti', + 'Conclusion' => 'Záver', + 'Configuration' => 'Konfigurácia', + 'Confirm Email Address' => 'Potvrďte svoju e-mailovú adresu', + 'Confirm Email address' => 'Potvrďte svoju e-mailovú adresu', + 'Constant amount' => 'Konštantná čiastka', + 'Contact and sender email address' => 'Kontakt a e-mailová adresa odosielateľa', + 'Contact page' => 'Kontaktná stránka', + 'Content' => 'Obsah', + 'Content page' => 'Obsah stránky', + 'Content title *' => 'Obsah titulu *', + 'Contents' => 'Obsah', + 'Countries' => 'Krajiny', + 'Country' => 'Krajina', + 'Country ID %id not found' => 'Identifikácia krajiny %id nebol nájdený', + 'Country ID not found' => 'ID krajiny nebol nájdený', + 'Country list is not valid JSON' => 'Zoznam krajín nie je platný JSON', + 'Country title' => 'Názov krajiny', + 'Coupon' => 'Kupón', + 'Coupon %code is expired.' => 'Platnosť kupónu %code vypršala.', + 'Coupon %code is not release.' => '%code kupón nie je voľný.', + 'Coupon code %code is disabled.' => 'Kód kupónu %code je neplatný.', + 'Critical' => 'Kritický', + 'Curency selection page' => 'Stránka výberu meny', + 'Currencies' => 'Meny', + 'Currency' => 'Mena', + 'Currency name' => 'Názov meny', + 'Current Password' => 'Súčasné heslo', + 'Customer' => 'Zákazník', + 'Customer is %op% %customer_list%' => 'Zákazník je %op% %customer_list%', + 'Customers' => 'Zákazníci', + 'Date \'%date\' is invalid, please enter a valid date using %fmt format' => 'Dátum "%date" je neplatný, prosím zadajte platný dátum vo formáte %fmt', + 'Debug' => 'Debug', + 'Decimal places' => 'Desatinné miesta', + 'Default folder *' => 'Predvolený priečinok *', + 'Default product category *' => 'Predvolená Kategória produktu *', + 'Delivery' => 'Doručenie', + 'Delivery choice' => 'Spôsob dodania', + 'Delivery country' => 'Krajina doručenia', + 'Delivery country is' => 'Krajina doručenia je', + 'Delivery module ID not found' => 'ID dodacieho modulu nenájdené', + 'Delivery zone' => 'Zóna dodania', + 'Detailed description' => 'Podrobný popis', + 'Disabled' => 'Zakázané', + 'Discount type' => 'Typ zľavy', + 'Display initial product prices on front-office' => 'Zobraziť ceny pôvodného produktu na front-office', + 'Do compress' => 'Kompresia', + 'Document' => 'Dokument', + 'Don\'t repeat keywords over and over in a row. Rather, put in keyword phrases.' => 'Neopakujte kľúčové slová stále dookola. Skôr dať do kľúčových fráz.', + 'Edit' => 'Upraviť', + 'Edit JavaScript' => 'Upraviť JavaScript', + 'Email Address' => 'Emailová adresa', + 'Email addresses of notification recipients' => 'E-mailové adresy príjemcov upozornení', + 'Email test from : %store%' => 'Emailový test od: %store%', + 'Emergency' => 'Núdzový režim', + 'Encryption' => 'Šifrovanie', + 'End date of sales' => 'Dátum ukončenia výpredaja', + 'Enter here the brand name in the default language (%title%)' => 'Tu zadajte názov značky v predvolenom jazyku (%title%)', + 'Enter here the category title in the default language (%title%)' => 'Tu zadajte názov značky v predvolenom jazyku (%title%)', + 'Enter here the sale name in the default language (%title%)' => 'Tu zadajte názov výpredaja v predvolenom jazyku (%title%)', + 'Enter the new password' => 'Zadajte nové heslo', + 'Enter the new password again' => 'Znova zadajte nové heslo', + 'Equal to' => 'Rovné', + 'Error during %action process : %error. Exception was %exc' => 'Chyba počas %action: %error. Výnimkou bola %exc', + 'Error occured while processing order ref. %ref, ID %id: %err' => 'Chyba pri spracovaní objednávky ref. % ref, ID %id: %err', + 'Error occured.' => 'Vyskytla sa chyba.', + 'Errors' => 'Chyby', + 'Failed to delete selected countries' => 'Nepodarilo sa odstrániť vybrané krajiny', + 'Failed to find a payment Module with ID=%mid for order ID=%oid' => 'Nedokázal nájsť platobný modul s ID = % pre objednávku ID =%oid', + 'Fax' => 'Fax', + 'Feature' => 'Vlastnosť', + 'File format' => 'Formát súboru', + 'File is too large, please retry with a file having a size less than %size%.' => 'Súbor je príliš veľký, zopakujte so súborom s veľkosťou menšou ako %size%.', + 'File to upload' => 'Súbor na nahranie', + 'Files with the following extension are not allowed: %extension, please do an archive of the file if you want to upload it' => 'Nie sú povolené súbory s nasledujúcimi príponami: %extension, prosím urobiť archívneho súboru, ak chcete nahrať', + 'First Name' => 'Meno', + 'Firstname' => 'Meno', + 'Fixed Amount Discount' => 'Pevná výška zľavy', + 'Fixed amount discount for selected categories' => 'Pevná čiastka zľavy pre vybrané kategórie', + 'Fixed amount discount for selected products' => 'Pevná čiastka zľavy pre vybrané produkty', + 'Folder' => 'Priečinok', + 'Folder page' => 'Stránka priečinka', + 'Folder title *' => 'Názov priečinka *', + 'For one ore more customers' => 'Pre jedného alebo viacerých zákazníkov', + 'Format' => 'Formát', + 'Free product when buying one or more selected products' => 'Produkt zadarmo pri kúpe jedného alebo viac vybraných produktov', + 'Front Office' => 'Verejná časť obchodu', + 'Full Name' => 'Celé meno', + 'Greater than' => 'Viac než', + 'Greater than or equals' => 'Väčšia alebo sa rovná', + 'HTML Message' => 'Správy vo formáte HTML', + 'HTML layout' => 'Rozloženie HTML', + 'Home' => 'Úvod', + 'Home page' => 'Úvodná stránka', + 'Hook' => 'Umiestnenie', + 'I would like to receive the newsletter or the latest news.' => 'Chcel by som dostávať newsletter alebo novinky.', + 'ISO 639-1 Code' => 'Kód ISO 639-1', + 'ISO Alpha-2 code' => 'Kód ISO alfa-2', + 'ISO Alpha-3 code' => 'ISO alfa-3 kód', + 'If cart item (include quantity) count is %operator% %quantity%' => 'Ak je počet položiek v košíku %operator% %quantity%', + 'If cart item count is %operator% %quantity%' => 'Ak je počet položiek v košíku %operator% %quantity%', + 'If cart total amount is %operator% %amount% %currency%' => 'Ak je celková hodnota košíka %operator% %amount% %currency%', + 'Image' => 'Obrázok', + 'Impossible to delete a customer who already have orders' => 'Nie je možné odstrániť zákazníkov, ktorí už majú objednávky', + 'In' => 'V', + 'Include documents' => 'Zahŕňa dokumenty', + 'Include images' => 'Zahŕňa obrázky', + 'Information' => 'Informácie', + 'Invalid product_sale_elements' => 'Neplatné product_sale_elements', + 'Invalid username or email.' => 'Neplatné užívateľské meno alebo e-mail.', + 'Invoice' => 'Faktúra', + 'Invoice choice' => 'Výber faktúry', + 'Iso code for states. It depends of the country.' => 'Kód Iso pre štáty. To závisí od krajiny.', + 'It is not allowed to delete the default currency' => 'Nie je povolené odstránenie predvolenej meny', + 'It is not allowed to delete the default language' => 'Nie je povolené odstrániť predvolený jazyk', + 'JavaScript' => 'JavaScript', + 'Language' => 'Jazyk', + 'Last Name' => 'Priezvisko', + 'Layout' => 'Rozloženie', + 'Less than' => 'Menej ako', + 'Less than or equals' => 'Menej ako alebo sa rovná', + 'Login failed. Please check your username and password.' => 'Prihlásenie zlyhalo. Skontrolujte, či ste zadali správne vaše užívateľské meno a heslo.', + 'Login name' => 'Prihlasovacie meno', + 'Login page' => 'Prihlasovacia stránka', + 'Lost password' => 'Zabudnuté heslo', + 'Mail template name' => 'Názov mailovej šablóny', + 'Main address' => 'Hlavná adresa', + 'Make sure it uses keywords found within the page itself.' => 'Uistite sa, že používa slová, ktoré sa nachádzajú na samotnej stránke.', + 'Make sure that your title is clear, and contains many of the keywords within the page itself.' => 'Uistite sa, že vaša hlava je jasná, a obsahuje veľa kľúčových slov v rámci samotnej stránky.', + 'Make this address as my primary address' => 'Zadajte túto adresu ako moju primárnu adresu', + 'Maximum usage count reached for coupon %code' => 'Dosiahli ste maximálny počet užívateľských kupónov %code', + 'Message' => 'Správa', + 'Message name' => 'Názov správy', + 'Message subject' => 'Predmet správy', + 'Messages' => 'Správy', + 'Meta Description' => 'Meta popis', + 'Meta Keywords' => 'Meta kľúčové slová', + 'Method Name' => 'Názov metódy', + 'Missing or invalid data: %s' => 'Chýbajúce alebo neplatné údaje: %s', + 'Module "%name%" directory was not found' => 'Modul "%name%" adresár sa nenašiel', + 'Module %name directory doesn\'t exists.' => 'Modul %name adresár neexistuje.', + 'Name' => 'Názov', + 'Name *' => 'Meno *', + 'New Password' => 'Nové Heslo', + 'Newsletter page' => 'Novinky', + 'No %obj was created.' => '%obj nebola vytvorená.', + 'No %obj was updated.' => '%obj nebol aktualizovaný.', + 'No module found for code \'%item\'' => 'Žiadny modul pre kód "%item" nenájdený', + 'No, I am a new customer.' => 'Som nový zákazník.', + 'None' => 'Žiadne', + 'Not equal to' => 'Nerovná sa', + 'Not in' => 'Nie je v', + 'Notices' => 'Upozornenie', + 'Numerical ISO Code' => 'Číselný ISO kód', + 'Only files having the following mime type are allowed: %types%' => 'Sú povolené iba súbory, ktoré majú tento typ mime: %types%', + 'Order' => 'Objednávka', + 'Order failed' => 'Objednávka zlyhala', + 'Order ref. %ref is now unpaid.' => 'Objednávka č. % ref je momentálne nezaplatená.', + 'Order ref. %ref, ID %id has been successfully paid.' => 'Objednávka ref. % ref, ID %id bola úspešne zaplatená.', + 'Overall' => 'Celkový', + 'Page 404' => 'Strana 404', + 'Page Title' => 'Názov stránky', + 'Parent category' => 'Nadradená kategória', + 'Password' => 'Heslo', + 'Password *' => 'Heslo *', + 'Password confirmation' => 'Potvrdenie hesla', + 'Payment failed' => 'Platba zlyhala', + 'Per customer' => 'Na zákazníka', + 'Percent' => 'Percent', + 'Percentage' => 'Percentuálne', + 'Percentage of the product price' => 'Percento ceny výrobku', + 'Placed order' => 'Zákazky', + 'Please accept the Terms and conditions in order to register.' => 'Akceptujte, prosím, podmienky registrácie.', + 'Please check your input: %error' => 'Skontrolujte svoj vstup: %error', + 'Please enter a valid email address' => 'Prosím, zadajte platnú e-mailovú adresu', + 'Please enter your email address' => 'Zadajte vašu emailovú adresu.', + 'Please enter your password' => 'Prosím zadajte vaše heslo', + 'Please select a category' => 'Vyberte kategóriu', + 'Please select an attribute' => 'Vyberte atribút', + 'Please select at least one attribute value' => 'Vyberte prosím aspoň jednu hodnotu atribútu', + 'Please select at least one category' => 'Vyberte aspoň jednu kategóriu', + 'Please select at least one product' => 'Vyberte prosím aspoň jeden výrobok', + 'Please select the category of the offred product' => 'Vyberte si kategóriu ponúkaného výrobku', + 'Please select the offered product' => 'Vyberte si ponúkaný produkt', + 'Please upload a valid Zip file' => 'Prosím uploadujte platný súbor Zip', + 'Price currency *' => 'Cena v mene', + 'Processing cancelation of payment for order ref. %ref' => 'Spracovanie storno platby za objednávku ref. % ref', + 'Prodcut ID *' => 'Produkt ID *', + 'Product ID' => 'Identifikácia produktu', + 'Product ID *' => 'Kód Produktu ID *', + 'Product base price excluding taxes *' => 'Základná cena tovaru bez dane *', + 'Product base price with taxes' => 'Základná cena výrobku s daňami', + 'Product categories' => 'Kategórie produktov', + 'Product page' => 'Stránka produktu', + 'Product price excluding taxes' => 'Cena tovaru bez dane', + 'Product price excluding taxes *' => 'Cena tovaru bez daní', + 'Product price including taxes' => 'Cena tovaru s daňou', + 'Product reference (must be unique)' => 'Kód produktu (musí byť unikátny)', + 'Product reference *' => 'Kód produktu', + 'Profile Code' => 'Kód profilu', + 'Quantity' => 'Množstvo', + 'Register' => 'Zaregistrovať sa', + 'Remember me ?' => 'Zapamätať si ma?', + 'Remove X percent to total cart' => 'Odstrániť X percent celkového košíka', + 'Sale title' => 'Výpredaj', + 'Search' => 'Hľadať', + 'Search page' => 'Vyhľadať', + 'Select the brand logo' => 'Vyberte logo značky', + 'Shipping zone name' => 'Názov doručovacej zóny', + 'Short additional text' => 'Krátky doplňujúci text', + 'Short description text' => 'Krátky popis', + 'Show redirections *' => 'Zobraziť presmerovanie *', + 'Sitemap' => 'Mapa stránky', + 'Sorry, an error occured.' => 'Je nám ľúto, vyskytla sa chyba.', + 'Sorry, an error occured: %msg' => 'Je nám ľúto, vyskytla sa chyba: % msg', + 'Sorry, an error occured: %s' => 'Je nám ľúto, vyskytla sa chyba: %s', + 'Sorry, an error occurred: %err' => 'Je nám ľúto, vyskytla sa chyba: %err', + 'Sorry, you are not allowed to perform this action.' => 'Ospravedlňujeme sa, ale nemôžete vykonávať túto činnosť.', + 'Sorry, you\'re not allowed to perform this action' => 'Ospravedlňujeme sa, ale nemôžete vykonávať túto činnosť', + 'Start date' => 'Počiatočný Dátum', + 'Start date of sales' => 'Dátum začatia predaja', + 'State *' => 'Štát *', + 'State ID %id not found' => 'Štátna ID %id nebol nájdený', + 'State title' => 'Názov štátu', + 'Stock' => 'Sklad', + 'Store Information' => 'Informácie o e-shope', + 'Store description' => 'Popis obchodu', + 'Store email address' => 'E-mailová adresa obchodu', + 'Store logs into text file' => 'Ukladať záznamy do textového súboru', + 'Store name' => 'Názov obchodu', + 'Street Address' => 'Ulica', + 'Street Address ' => 'Ulica ', + 'Strictly use the requested language' => 'Striktne používať požadovaný jazyk', + 'Subject' => 'Predmet', + 'Summary' => 'Zhrnutie', + 'Symbol' => 'Symbol', + 'System' => 'Systém', + 'System configuration' => 'Konfigurácia systému', + 'Tax' => 'Daň', + 'Tax ID not found in tax list JSON' => 'Daňové identifikačné číslo, ktoré nie je uvedené v zozname daní JSON', + 'Tax list is not valid JSON' => 'Daňové zoznam nie je platný JSON', + 'Tax rule ID not found' => 'Daňové ID nenájdené', + 'Tax rule for this product *' => 'Daňové pravidlo pre tento produkt *', + 'Taxes' => 'Dane', + 'Template' => 'Šablona', + 'Template Name *' => 'Názov šablóny *', + 'Text File' => 'Textový súbor', + 'Text Message' => 'Textová Správa', + 'The %name module definition has not been initialized.' => 'Definícia modulu %name nebola inicializovaná.', + 'The %name module descriptor has not been initialized.' => 'Popisovač modulu %name nebol inicializovaný.', + 'The %obj_name id \'%id\' doesn\'t exist' => '%obj_name id "%id" neexistuje', + 'The HTML TITLE element is the most important element on your web page.' => 'Element HTML TITLE je najdôležitejším prvkom na vašej webovej stránke.', + 'The brand name or title' => 'Značka alebo názov', + 'The cart item count should match the condition' => 'Počet položiek v košíku by mal zodpovedať stavu skladu', + 'The coupon applies if the cart contains at least one product of the selected categories' => 'Kupón platí, pokiaľ košíl obsahuje aspoň jeden produkt z vybraných kategórií', + 'The coupon applies if the cart contains at least one product of the specified product list' => 'Kupón platí, pokiaľ košíl obsahuje aspoň jeden produkt zo špecifického produktového zoznamu', + 'The coupon applies to some customers only' => 'Kupón platí iba pre niektorých zákazníkov', + 'The coupon applies to the selected billing countries' => 'Kupón platí pre vybrané fakturačné krajiny', + 'The coupon code \'%code\' already exist. Please choose another coupon code' => 'Kupon kód "%code" už existuje. Zvoľte iný kód kupónu', + 'The coupon code \'%code\' already exists. Please choose another coupon code' => 'Kupon kód "%code" už existuje. Zvoľte iný kód kupónu', + 'The coupon is valid after a given date' => 'Kód kupónu je platný do určeného dátumu', + 'The date after which sales are de-activated. Please use %fmt format.' => 'Dátum, po ktorom je výpredaj deaktivovaný. Prosím, použite formát %fmt.', + 'The date from which sales are active. Please use %fmt format.' => 'Dátum, po ktorom je výpredaj aktivovaný. Prosím, použite formát %fmt.', + 'The extension "%extension" is not allowed' => 'Prípona "%extension" nie je povolená', + 'The file %path has been successfully downloaded' => 'Súbor %path bol úspešne stiahnutý', + 'The following columns are missing: %columns' => 'Chýbajú nasledovné stĺpce: %columns', + 'The language "%id" doesn\'t exist' => 'Neexistuje jazyk "%id"', + 'The mailing template in HTML format.' => 'Mailová šablóna vo formáte HTML.', + 'The mailing template in text-only format.' => 'Mailová šablóna len v textovom formáte.', + 'The module has to be activated.' => 'Modul musí byť aktivovaný.', + 'The module is not valid : %message' => 'Modul nie je platný: %message', + 'The module zip file' => 'Modul zip súbor', + 'The product document id %id doesn\'t exists' => 'Neexistuje dokument produktu %id', + 'The sale name or title' => 'Výpredajový názov, alebo titul', + 'The store fax number.' => 'Fax obchodu.', + 'The store phone number.' => 'Telefónny kontakt obchodu.', + 'The zip code format' => 'Formát Psč', + 'There are no files to associate.' => 'Nie sú žiadne súbory na priradenie.', + 'There is no id "%id" in the exports' => 'Neexistuje žiadny id "%id" v exporte', + 'There is no id "%id" in the imports' => 'Neexistuje žiadny id "%id" v importe', + 'There is no id "%ref" in the imports' => 'Neexistuje žiadny id "%id" v importe', + 'There is no ref "%ref" in the exports' => 'Neexistuje žiadny id "%id" v exporte', + 'This administrator login already exists' => 'Správca s týmto prihlásením už existuje', + 'This brand is online' => 'Táto značka je online', + 'This category is online' => 'Táto kategória je online', + 'This content is online.' => 'Tento obsah je online.', + 'This country has states / provinces' => 'Táto krajina má štáty / provincie', + 'This country is online' => 'Táto krajina je online', + 'This coupon adds a free product to the cart if one of the selected products is in the cart.' => 'Toto je kupón na bezplatný tovar, ktorý bude automaticky pridaný do vášho košíka, ak tento obsahuje vybraný produkt.', + 'This coupon does not exists' => 'Tento kupón neexistuje', + 'This coupon subtracts from the order total a percentage of the price of each product which belongs to the selected categories. If the discount is greater than the total order, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.' => 'Tento kupón odpočíta z objednávky percentá z ceny každého produktu, ktorý prináleží k vybraným kategóriam. Ak je odpočet väčší ako je celková objednávka, zákazník zaplatí len poštovné alebo nič, ak kupón zahŕňa aj poštovné zdarma.', + 'This coupon subtracts from the order total the specified percentage of each product price which uses the selected attribute values. If the discount is greater than the total order, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.' => 'Tento kupón odpočíta z objednávky percentá z ceny každého produktu, ktorý obsahuje vybrané vlastnosti.. Ak je odpočet väčší ako je celková objednávka, zákazník zaplatí len poštovné alebo nič, ak kupón zahŕňa aj poštovné zdarma.', + 'This document is online' => 'Tento dokument je online', + 'This email already exists.' => 'Tento e-mail už existuje.', + 'This email does not exists' => 'Tento e-mail neexistuje', + 'This folder is online.' => 'Tento priečinok je v režime online.', + 'This image is online' => 'Tento obrázok je online', + 'This is the name used on the login screen' => 'To je meno na prihlasovacej obrazovke', + 'This product is on sale' => 'Tento produkt je vo výpredaji', + 'This product is online' => 'Tento produkt je online', + 'This state is online' => 'Táto krajina je online', + 'Timeout' => 'Časový limit', + 'Title' => 'Oslovenie', + 'Title *' => 'Titul', + 'Title ID not found' => 'Názov ID sa nepodarilo nájsť', + 'Tools' => 'Nástroje', + 'Translations' => 'Preklady', + 'Tried to download a file, but the URL was not valid: %url' => 'Snažil stiahnuť súbor, ale nebola platná adresa URL: %url', + 'URL_ALREADY_EXISTS' => 'Táto adresa URL už existuje', + 'Unable to process your request. Please try again (%err).' => 'Nie je možné spracovať vašu požiadavku. Prosím skúste to znova (%err).', + 'Username' => 'Užívateľské meno', + 'Username or e-mail address *' => 'Užívateľské meno alebo e-mail *', + 'Valid only from %date% to the coupon expiration date' => 'Platný od %date% do platnosti kupónu', + 'Value' => 'Hodnota', + 'Value *' => 'Hodnoty *', + 'Variable' => 'Premenná', + 'Variables' => 'Premenné', + 'Virtual document' => 'Virtuálne dokumenty', + 'Warnings' => 'Upozornenia', + 'We\'re sorry, this PDF invoice is not available at the moment.' => 'Ľutujeme, ale táto faktúra nie je momentálne k dispozícii v PDF.', + 'Weight' => 'Hmotnosť', + 'Yes, I have a password :' => 'Áno, mám heslo:', + 'You are already registered!' => 'Už ste registrovaný!', + 'You don\'t need to use commas or other punctuations.' => 'Nemusíte použiť čiarky alebo inú interpunkciu.', + 'You have to configure your store email first !' => 'Musíte najprv nastaviť e-mail vášho obchodu!', + 'You\'ve submitted this form too many times. ' => 'Odoslali ste tento formulár príliš mnohokrát. ', + 'Your Email Address' => 'Vaša e-mailová adresa', + 'Your Message' => 'Vaša správa', + 'Your current password does not match.' => 'Aktuálne heslo sa nezhoduje.', + 'Zip code' => 'PSČ', + 'Zone' => 'Zóna', + 'add to all form' => 'vyplniť celý formulár', + 'additional information' => 'doplňujúce informácie', + 'address create form' => 'vytvorenie formulára adresy', + 'at the bottom' => 'naspodku', + 'at the bottom of column 1' => 'v spodnej kolónke 1', + 'at the bottom of information area' => 'naspodku informačnej oblasti', + 'at the bottom of the catalog' => 'v spodnej časti katalógu', + 'at the bottom of the main area' => 'v spodnej časti hlavnej oblasti', + 'at the top' => 'hore', + 'at the top of the catalog area' => 'v hornej časti katalógu', + 'at the top of the column' => 'v hornej časti stĺpca', + 'at the top of the configuration' => 'v hornej časti konfigurácie', + 'at the top of the detail' => 'v hornej časti detail', + 'at the top of the footer' => 'v hornej časti päty', + 'at the top of the form' => 'v hornej časti stĺpca', + 'at the top of the header' => 'v hornej časti hlavičky', + 'at the top of the sidebar' => 'v hornej časti bočného panela', + 'caption' => 'titulok', + 'configuration' => 'konfigurácia', + 'configuration JavaScript' => 'konfigurácia JavaScript', + 'content' => 'obsah', + 'contents table row' => 'obsah riadka tabuľky', + 'context' => 'kontext', + 'country delete form' => 'formulár vymazania krajiny', + 'create JavaScript' => 'vytvoriť JavaScript', + 'create form' => 'vytvorenie formulára', + 'customer account' => 'zákaznícky účet', + 'date format' => 'formát dátumu', + 'decimal separator' => 'oddeľovač desatinných miest', + 'delete form' => 'odstrániť formulár', + 'delivery address' => 'adresa dodania', + 'details pricing form' => 'detailný cenový formulár', + 'email' => 'e-mail', + 'email confirmation is not the same as email field' => 'E-mailové adresy nie sú totožné', + 'email system JavaScript' => 'e-mailový systém JavaScript', + 'extra area' => 'Ďalšie oblasti', + 'extra payment zone' => 'extra platobná zóna', + 'header' => 'hlavička', + 'hour(s)' => 'hodina(y)', + 'in the menu catalog' => 'v ponuke katalógu', + 'in the menu configuration' => 'v menu nastavenia', + 'in the menu customers' => 'v menu zákazníci', + 'in the menu folders' => 'v ponuke priečinky', + 'in the menu modules' => 'menu moduly', + 'in the menu orders' => 'v menu ponuky', + 'in the menu tools' => 'v menu nástroje', + 'in top menu items' => 'v hornom menu položky', + 'javascript' => 'javaScript', + 'javascript initialization' => 'inicializácia JavaScript', + 'label' => 'Štítok', + 'language selection page' => 'výber jazyka stránky', + 'list JavaScript' => 'zoznam JavaScript', + 'list caption' => 'zoznam popisov', + 'list header' => 'zoznam hlavička', + 'list row' => 'zoznam riadkov', + 'mailing system modification' => 'modifikácia mailového systému', + 'main area' => 'hlavné oblasti', + 'middle' => 'uprostred', + 'minute(s)' => 'minúta (y)', + 'password confirmation is not the same as password field' => 'potvrdenie hesla nie je rovnaké ako zadaní heslo', + 'password must be composed of at least 4 characters' => 'heslo musí pozostávať aspoň zo 4 znakov', + 'pdf' => 'pdf', + 'permanent discount (in percent)' => 'trvalé zľavy (v percentách)', + 'photo gallery' => 'Fotogaléria', + 'primary navigation' => 'primárna navigácia', + 'product list' => 'Zoznam produktov', + 'quantity value is not valid' => 'Požadované množstvo nie je k na sklade', + 'remove to all form' => 'všetko odstrániť', + 'row' => 'riadok', + 'rule create form' => 'formulár vytvorenia pravidla', + 'rule delete form' => 'pravidlo odstránenia formulára', + 'rule edit JavaScript' => 'upraviť pravidlo JavaScript', + 'secondary navigation' => 'sekundárna navigácia', + 'ssl, tls or empty' => 'ssl, tls alebo prázdne', + 'stock edit form' => 'formulár editácie skladu', + 'tax rule' => 'daňové pravidlo', + 'this product id does not exists : %d' => 'tento produkt neexistuje: %d', + 'thousands separator' => 'oddeľovač tisícov', + 'time format' => 'formát času', + 'update JavaScript' => 'aktualizácia JavaScript', +]; diff --git a/core/lib/Thelia/Config/I18n/tr_TR.php b/core/lib/Thelia/Config/I18n/tr_TR.php new file mode 100644 index 00000000..d62469bd --- /dev/null +++ b/core/lib/Thelia/Config/I18n/tr_TR.php @@ -0,0 +1,768 @@ + 'içerik oluşturma formu', + ' note: only non-visible documents can be associated.' => 'Not: Yalnızca görünür olmayan belgeler ilişkili olabilir.', + '"%param" parameter cannot be empty in loop type: %type, name: %name' => '"%param" parametre dönüştürme türü boş olmaz: %type, isim: %name', + '"%param" parameter is missing in loop type: %type, name: %name' => '"%param" parametre köprü türü eksik: %ype, isim: %name', + '%module (version: %version)' => '% modülü (sürüm: %version)', + '%obj SEO modification' => '%obj seo değiştirme(değişiklik)', + '%obj creation' => '%obj oluşturma', + '%obj modification' => '%obj değişiklik', + '%obj%s deleted successfully' => '%obj%s Başarıyla silindi', + '%s has dependency to module %s. You have to deactivate this module before.' => '%s Modül bağımlılıkları vardır %s. Bu modülü önce devre dışı bırakmak zorundasın.', + '%s have dependencies to module %s. You have to deactivate these modules before.' => '%s modülü %s için bağımlılıkları var. Bu modüller önce devre dışı bırakmak zorundasın.', + '%type% position updated' => '%type% konumunu güncelleme', + '%type% visibility updated' => 'Güncelleme %type% görünürlük', + 'A comma separated list of email addresses' => 'Bir virgülle ayrılmış listesi e-posta adresleri', + 'A currency with code "%name" already exists.' => 'Bir para birimi kodu "%name" ile zaten var.', + 'A descriptive title' => 'Açıklayıcı bir başlık', + 'A message with name "%name" already exists.' => 'Adı "%name" içeren bir ileti zaten var.', + 'A name such as Europe or Overseas' => 'Avrupa veya Yurtdışı gibi bir isim', + 'A product with reference %ref already exists. Please choose another reference.' => 'Bir ürün başvuru %ref ile zaten var. Lütfen başka bir referansı seçin.', + 'A short description, used when a summary or an introduction is required' => 'Bir Özet veya giriş gerekli olduğunda kullanılan kısa bir açıklama', + 'A short text, used when an additional or supplemental information is required.' => 'Bir ek ya da tamamlayıcı bilgi gerekli olduğunda kullanılan kısa bir metin.', + 'A user already exists with this email address. Please login or if you\'ve forgotten your password, go to Reset Your Password.' => 'Bir kullanıcı bu e-posta adresi ile zaten var . Lütfen giriş yapın veya parolanızı unuttuysanız, parolanızı sıfırlamak için gidin.', + 'A value for attribute "%name" is already present in the combination' => '"%name" özniteliği için bir değer zaten kasanın içinde var', + 'A variable with name "%name" already exists.' => 'Bir değişken adı "%name" ile zaten var.', + 'Activate logs only for these IP Addresses' => 'Günlükleri yalnızca bu IP adresleri için etkinleştirmek', + 'Activate logs only for these files' => 'Bu dosya için yalnızca günlükleri etkinleştirme', + 'Activate this sale' => 'Bu satışı etkinleştirin', + 'Active' => 'Aktif', + 'Add to all product templates' => 'Tüm ürün şablonları ekleme', + 'Additional address' => 'Ek adres', + 'Additional address information' => 'Ek adres bilgisi', + 'Address ID not found' => 'Adres ID Bulunamadı', + 'Address Line 2' => 'Adres satırı 2', + 'Address Line 3' => 'Adres satırı 3', + 'Address creation' => 'Adres oluşturma', + 'Address label' => 'Adres etiketi', + 'Address update' => 'Adresi güncelle', + 'Address.' => 'Adres.', + 'Administrator' => 'Yönetici', + 'Administrator ID not found' => 'Yönetici ID Bulunamadı', + 'Administrators' => 'Yönetici', + 'Advertise this product as new' => 'Bu ürün yeni olarak reklam', + 'Alerts' => 'Uyarılar', + 'All Products' => 'Tüm Ürünler', + 'All countries' => 'Bütün ülkeler', + 'All shipping methods' => 'Tüm nakliye yöntemleri', + 'Amount' => 'Tutar', + 'Apply exchange rates on price in %sym' => 'Döviz kurları %sym fiyatlarına uygulayın', + 'Archive Format' => 'Arşiv biçimi', + 'Associate documents' => 'Ortak Belgeler', + 'Associate images' => 'Ortak resimler', + 'At least one of cart products categories is %op% %categories_list%' => 'En az birinin arabası ürün kategorileri %op% %categories_list% olduğunu', + 'Attribut' => 'Özellik', + 'Attribute ID:Attribute AV ID' => 'Öznitelik ID:Attribute AV kimliği', + 'Attribute value' => 'Öznitelik değeri', + 'Attributes' => 'Öznitelikler', + 'Attributes value' => 'Öznitelik değeri', + 'Auth mode' => 'Kimlik doğrulama modu', + 'Available quantity' => 'Mevcut miktar', + 'Available quantity *' => 'Mevcut miktar *', + 'Available shipping zones' => 'Kullanılabilir sevkiyat bölgeleri', + 'Back Office' => 'Yönetim Paneli', + 'Bad tax list JSON' => 'Kötü Kdv listesi JSON', + 'Billing country' => 'Fatura ülke', + 'Billing country is' => 'Fatura ülke', + 'Brand' => 'Marka', + 'Brand / Supplier' => 'Marka / tedarikçi', + 'Brand name' => 'Marka adı', + 'Brands' => 'Markalar', + 'Business ID' => 'İşletme kimliği', + 'By Module' => 'Modülü tarafından', + 'CSS' => 'CSS', + 'CSS stylesheet' => 'CSS stil sayfası', + 'Cannot find a default country. Please define one.' => 'Bu varsayılan ülke bulunmuyor. Lütfen tanımla', + 'Cannot find the shop country. Please select a shop country.' => 'Mağaza ülkesi bulunamıyor. Bir mağaza ülkesi seçiniz.', + 'Cannot instantiate module "%name%": the namespace is null. Maybe the model is not loaded ?' => 'Modülü "%name%" başlatılamıyor: ad alanı boştur. Belki de model dolu değil mi?', + 'Cart' => 'Sepet', + 'Cart contains at least a product %op% %products_list%' => 'En az bir ürün %op% %products_list% sepeti içerir', + 'Cart contains categories condition' => 'Sepet Kategoriler koşulu içeren', + 'Cart contains specific products' => 'Belirli bir ürün alış veriş sepetin içeriyor', + 'Cart item count' => 'Sepetin ürün sayısı', + 'Cart item count is' => 'Sepetin ürün sayısı ', + 'Cart total amount' => 'Sepetin toplam tutarı', + 'Cart total amount is' => 'Sepetin toplam tutarı', + 'Catalog' => 'Katalog', + 'Catalog configuration' => 'Katalog yapılandırma', + 'Categories' => 'Katogoriler', + 'Category' => 'kategori', + 'Category page' => 'Kategori sayfası', + 'Category title' => 'Kategori başlığı', + 'Cellphone' => 'Cep telefonu', + 'Change password' => 'Parolayı değiştir', + 'Check country iso codes here.' => ' Wikipedia ülke ISO kodları kontrol edin.', + 'Check the total Cart amount in the given currency' => 'Verilen para birimindeki toplam sepeti denetleyin', + 'City' => 'Şehir', + 'Code' => 'Kod', + 'Combination builder' => 'Kombinasyon Oluşturucu', + 'Compagny' => 'Compagny', + 'Company' => 'Firma', + 'Company Name' => 'Firma İsmi', + 'Conclusion' => 'Sonuç', + 'Configuration' => 'Ayarlar', + 'Confirm Email Address' => 'E-posta adresinizi onaylayın', + 'Confirm Email address' => 'E-posta adresinizi onaylayın', + 'Constant amount' => 'Sabit tutar', + 'Constant amount found in one of the product\'s feature' => 'Sabit tutar ürünün özelliği buldum', + 'Contact and sender email address' => 'İletişim ve gönderenin e-posta adresi', + 'Contact page' => 'İletişim sayfası', + 'Content' => 'Içerik', + 'Content page' => 'İçerik sayfası', + 'Content title *' => 'İçerik başlığı *', + 'Contents' => 'İçindekiler', + 'Core hook of Thelia.' => 'Thelia çekirdek kanca.', + 'Countries' => 'Ülkeler', + 'Country' => 'Ülke', + 'Country ID not found' => 'Ülke kimliği bulunamadı', + 'Country title' => 'Ülke adı', + 'Coupon' => 'Kupon', + 'Coupon %code is expired.' => 'Kupon %code süresi dolmuş.', + 'Coupon code %code is disabled.' => 'Kupon kodu %code devre dışı bırakılır.', + 'Critical' => 'Kritik', + 'Curency selection page' => 'Curency seçim sayfası', + 'Currencies' => 'Para birimleri', + 'Currency' => 'Para birimi', + 'Currency name' => 'Para birimi adı', + 'Current Password' => 'Geçerli Şifre', + 'Customer' => 'Customer', + 'Customer is %op% %customer_list%' => 'Müşteri %op% %customer_list% olduğunu', + 'Customers' => 'müşteriler', + 'Dashboard' => 'Kontrol paneli', + 'Date \'%date\' is invalid, please enter a valid date using %fmt format' => 'Tarihi \'%date\' geçersiz, lütfen %fmt biçimini kullanarak geçerli bir tarih girin', + 'Debug' => 'Hata Ayıklama', + 'Decimal places' => 'Ondalık basamak', + 'Default folder *' => 'Varsayılan klasör *', + 'Default product category *' => 'Varsayılan ürün kategori *', + 'Default product sale element' => 'Varsayılan ürün satış elemanı', + 'Default product template' => 'Varsayılan ürün şablonu', + 'Deleting %obj% for %id% with parent id %parentId%' => '%obj% %id% ile üst kimliği %parentId% için silme', + 'Delivery' => 'Teslimat', + 'Delivery choice' => 'Teslimat seçimi', + 'Delivery country' => 'Teslimat ülkesi', + 'Delivery country is' => 'Teslimat ülkesi', + 'Delivery module ID not found' => 'Teslim modülü ID değil kurmak', + 'Delivery zone' => 'Teslimat bölgesi', + 'Detailed description' => 'Detaylı açıklama', + 'Disabled' => 'Devre Dışı', + 'Discount type' => 'İndirim türü', + 'Display initial product prices on front-office' => 'İlk ürün fiyatları üzerinde ön büro görüntülemek', + 'Do compress' => 'Sıkıştırma', + 'Document' => 'DÖKÜMAN', + 'Don\'t repeat keywords over and over in a row. Rather, put in keyword phrases.' => 'Defalarca üst üste anahtar kelimeleri tekrar etme. Bunun yerine, Farlı anahtar kelimeler belirle.', + 'EAN Code' => 'EAN kodu', + 'Edit' => 'Düzenle', + 'Edit JavaScript' => 'JavaScript Düzenle', + 'Email Address' => 'E-posta adresi', + 'Email address' => 'Eposta adresi', + 'Email addresses of notification recipients' => 'Uyarı alıcılarının e-posta adresleri', + 'Email test from : %store%' => 'Test e-posta: %store%', + 'Emergency' => 'Acil durum', + 'Enable remote SMTP use' => 'Uzak SMTP kullanmayı etkinleştirme', + 'Encryption' => 'Şifreleme', + 'End date of sales' => 'Bitiş tarihi satış', + 'Enter here the brand name in the default language (%title%)' => 'Burada marka adı varsayılan dili (%title%) girin', + 'Enter here the category title in the default language (%title%)' => 'Varsayılan dili (%title%) kategori başlığı buraya girin', + 'Enter here the mail template purpose in the default language (%title%)' => 'Burada posta şablonu amacı varsayılan dili (%title%) girin', + 'Enter here the sale name in the default language (%title%)' => 'Burada marka adı varsayılan dili (%title%) girin', + 'Equal to' => 'Eşittir', + 'Error during %action process : %error. Exception was %exc' => '%action işlemi sırasında bir hata oluştu: %error. Özel durum %exc yapıldı.', + 'Error occured while processing order ref. %ref, ID %id: %err' => 'İşleme sipariş referans %ref, kimliği %id sırasında hata oluştu: %err', + 'Error occured.' => 'Hata oluştu.', + 'Errors' => 'Hatalar', + 'Export' => 'Dışa aktarma', + 'Fail to delete %obj% for %id% with parent id %parentId% (Exception : %e%)' => '%obj% %id% ile üst kimliği %parentId% için silmek başarısız (özel durum: %e%)', + 'Fail to update %type% position: %err%' => '%type% konumu güncellemek başarısız: %err%', + 'Fail to update %type% visibility: %err%' => '%type% görünürlük güncellemek başarısız: %err%', + 'Failed to create instance of module "%name%" when trying to delete module. Module directory has probably been deleted' => 'Modül silmeyi denerken modülü "%name%" örneğini oluşturma başarısız oldu. Modül dizini muhtemelen silindi', + 'Failed to create new hook %s' => 'Yeni kanca %s oluşturma başarısız oldu', + 'Failed to deactivate hook with id %s' => 'Modül Kanca ile kimliği %s devre dışı bırakma başarısız oldu', + 'Failed to delete selected countries' => 'Seçilen ülkeleri silmek başarısız oldu', + 'Failed to find a payment Module with ID=%mid for order ID=%oid' => 'Bir ödeme modülü kimliğini bulmak başarısız oldu % orta Sipariş No =%oid =', + 'Failed to load descriptor (module.xml) for module ID "%id".' => '"%id" modül kimliği için tanımlayıcısı (module.xml) yüklenemedi.', + 'Failed to load message with code \'%code%\', propably because it does\'nt exists.' => 'Başarısız ileti kodu \'%code%\', ile yüklemek için muhtemelen çünkü o doesnt\'bulunmaktadır.', + 'Failed to open a writing stream on the file: %file' => 'Bir dosya üzerinde bir yazma akış açma başarısız oldu: %file', + 'Failed to open translation file %file. Please be sure that this file is writable by your Web server' => 'Çeviri dosyası %file açma başarısız oldu. Lütfen bu dosyayı, Web sunucunuz tarafından yazılabilir olduğundan emin olun', + 'Failed to send message %code. Failed recipients: %failed_addresses' => 'Mesaj %code gönderemedi. Alıcılar başarısız oldu: %failed_addresses', + 'Failed to update language definition: %ex' => 'Dil tanımı güncelleştirilemedi: %ex', + 'Fax' => 'Fax', + 'Feature' => 'özellik', + 'Feature value does not match FLOAT format' => 'Özellik değeri FLOAT biçimine uymuyor', + 'Features' => 'Özellikler', + 'Features value' => 'Özellik değeri bilgileri', + 'File format' => 'Dosya Biçimi', + 'File is too large, please retry with a file having a size less than %size%.' => 'Dosya çok büyük, lütfen %size% daha az bir boyutlu olan bir dosyayla yeniden deneyin.', + 'File to upload' => 'Yüklemek için dosya seçin', + 'Files with the following extension are not allowed: %extension, please do an archive of the file if you want to upload it' => 'Aşağıdaki uzantılı dosyalar verilir: %extension, bir arşiv dosyası yüklemek istiyorsanız, lütfen seçin', + 'First Name' => 'Adı', + 'Firstname' => 'Adı', + 'Fixed Amount Discount' => 'Sabit tutar iskonto', + 'Fixed amount discount for selected attribute values' => 'Seçilen özellik değerleri için sabit tutar iskonto', + 'Fixed amount discount for selected categories' => 'Seçili kategoriler için sabit tutar iskonto', + 'Fixed amount discount for selected products' => 'Seçili ürünleri için sabit tutar iskonto', + 'Folder' => 'Klasör', + 'Folder page' => 'Klasör sayfası', + 'Folder title *' => 'Klasör Başlığı *', + 'For one ore more customers' => 'Bir veya daha fazla müşteriler için', + 'Free product when buying one or more selected products' => 'Bir satın almak için ücretsiz ürün veya daha fazla seçmek ürünlerden', + 'Front Office' => 'Ön Büro', + 'Full Name' => 'Ad Soyad', + 'Greater than' => 'Daha büyük', + 'Greater than or equals' => 'Büyüktür veya eşittir', + 'HTML Message' => 'HTML mesajı', + 'HTML layout' => 'HTML Düzeni', + 'Home' => 'Ana sayfa', + 'Home page' => 'Ana Sayfa', + 'Hook' => 'Kanca (modül)', + 'Hook block' => 'Kanca modül bloğu', + 'Hook code' => 'Kanca modül kodu', + 'Hook create form' => 'Kanca modül oluşturma formu', + 'Hook title' => 'Kanca modül başlığı', + 'Hooks' => 'Kanca (modül)', + 'Host' => 'Ana bilgisayar', + 'I would like to receive the newsletter or the latest news.' => 'Haber bülteni veya en son haberleri almak istiyor', + 'ISO 4217 code' => 'ISO 4217 kodu', + 'ISO 639-1 Code' => 'ISO 639-1 kodu', + 'ISO Alpha-2 code' => 'ISO Alpha-2 kod', + 'ISO Alpha-3 code' => 'ISO Alpha-3 kodu', + 'ISO Code' => 'ISO kodu', + 'If a translation is missing or incomplete :' => 'Bir çeviri eksik veya tamamlanmamış ise:', + 'If cart item count is %operator% %quantity%' => 'Sepet ürün sayısı %operator% %quantity% ise', + 'If cart total amount is %operator% %amount% %currency%' => 'Sepet toplam tutar %operator% %amount% %currency% ise', + 'If checked, this hook will be used by a hook block. If not, by hook function.' => 'İşaretli değilse, bu kanca kanca bloğu tarafından kullanılır. Eğer yoksa, işlev tarafından kanca.', + 'Image' => 'Resim', + 'Impossible to delete a customer who already have orders' => 'Siparişi verdi Siparişi olan bir müşteriyi silmek imkansız', + 'In' => 'İçinde', + 'Include documents' => 'Belgeler içeriyor', + 'Include images' => 'Görüntüleri dahil', + 'Information' => 'Bilgilendirme', + 'Invalid product_sale_elements' => 'Geçersiz ürün_satış_elemanı', + 'Invalid value "%value" for "%param" parameter in loop type: %type, name: %name' => 'Geçersiz değeri döngü türü parametresinde "%param" için "% değeri": % türü, adı: %name', + 'Invalid value for walkMode parameter: %value' => 'WalkMode parametresi için geçersiz değer: %value', + 'Invoice' => 'Fatura', + 'Invoice choice' => 'Fatura seçimi', + 'Is it the default product sale element ?' => 'Varsayılan ürün satış elemanı mı?', + 'It is not allowed to delete the default currency' => 'Varsayılan para birimini silmek için izin verilmiyor', + 'It is not allowed to delete the default language' => 'Bu varsayılan dili silmek için izin verilmiyor', + 'JavaScript' => 'JavaScript', + 'Keep the most important part of your description in the first 150-160 characters.' => 'Senin açıklama en önemli parçası ilk 150-160 karakteri tutun.', + 'Language' => 'Dil', + 'Language name' => 'Dil adı', + 'Languages' => 'Diller', + 'Last Name' => 'Soyadınız', + 'Lastname' => 'Soyad', + 'Layout' => 'Düzen', + 'Less than' => 'Daha düşük', + 'Less than or equals' => 'Daha az veya eşit', + 'Log format *' => 'Günlük biçimi *', + 'Log level *' => 'Oturum düzeyi *', + 'Login failed. Please check your username and password.' => 'Oturum açma başarısız oldu. Lütfen kullanıcı adınızı ve şifrenizi kontrol edin.', + 'Login page' => 'Giriş sayfası', + 'Logs' => 'Günlükler', + 'Loop cannot implements multiple Search Interfaces : `PropelSearchLoopInterface`, `ArraySearchLoopInterface`' => 'Döngü birden çok arama arabirimleri uygulayan olamaz: \'PropelSearchLoopInterface\', \'ArraySearchLoopInterface\'', + 'Loop must implements \'PropelSearchLoopInterface\' to be timestampable' => 'Döngü gerekir uygular \'PropelSearchLoopInterface\' timestampable olmak', + 'Loop must implements \'PropelSearchLoopInterface\' to be versionable' => 'Döngü gerekir uygular \'PropelSearchLoopInterface\' oluşturulabileceğidir olmak', + 'Loop must implements one of the following interfaces : `PropelSearchLoopInterface`, `ArraySearchLoopInterface`' => 'Döngü aşağıdaki arabirimlerden birini uygulayan gerekir: \'PropelSearchLoopInterface\', \'ArraySearchLoopInterface\'', + 'Lost password' => 'Şifreni mi kaybettin', + 'Mail template name' => 'Posta şablonu adı', + 'Mail template purpose' => 'Posta Şablon amacı', + 'Mailing system' => 'Posta sistemi', + 'Main address' => 'Ana Adres', + 'Main area' => 'Ana alan', + 'Make sure it uses keywords found within the page itself.' => 'Kurmak belgeli tanımlı sayfa içinde anahtar kelimeler kullanıldığından emin olun.', + 'Make sure that your title is clear, and contains many of the keywords within the page itself.' => 'Senin başlık açıktır ve birçok sayfanın kendisi içinde sözcükler içerdiğinden emin olun.', + 'Make this address as my primary address' => 'Benim birinci adres olarak bu adresi yapmak', + 'Maximum usage count reached for coupon %code' => 'Maksimum kullanım sayımı için kupon %code ulaştı', + 'Message' => 'Mesaj', + 'Message name' => 'İleti adı', + 'Message subject' => 'Mesaj konusu', + 'Messages' => 'Mesajlar', + 'Meta Description' => 'Meta açıklama', + 'Meta Keywords' => 'Meta anahtar kelimeleri', + 'Method Name' => 'Yöntem Adı', + 'Missing or invalid data: %s' => 'Eksik veya geçersiz veri: %s', + 'Module' => 'Modülller', + 'Module "%name%" directory was not found' => 'Modülü "%name%" dizini bulunamadı', + 'Module %name directory doesn\'t exists.' => 'Modül %name dizinin var olduğundan değil.', + 'Module %name should have a config.xml in the Config directory.' => 'Modül %name bir config.xml içinde Config dizinine sahip olmalıdır.', + 'Module %name should have a module.xml in the Config directory.' => 'Modül %name bir module.xml Config dizininde olması gerekir.', + 'Module ID "%id" was not found.' => 'Modül kimliği "%id" bulunamadı.', + 'Module ID not found' => 'Modül kimliği bulunamadı', + 'Module hook' => 'Modül kancaları', + 'Modules' => 'Modüller', + 'More information about ISO 4217' => 'ISO 4217 hakkında daha fazla bilgi', + 'Name' => 'Ad', + 'Name *' => 'Ad *', + 'Name of the HTML layout file' => 'HTML Düzeni dosyasının adı', + 'Name of the HTML template file' => 'HTML şablon dosyasının adını', + 'Name of the text layout file' => 'Metin düzeni dosyasının adı', + 'Name of the text template file' => 'Metin şablonu dosyasının adı', + 'Native' => 'Yerli', + 'New Password' => 'Yeni Şifre', + 'Newsletter page' => 'Bülten sayfa', + 'No %obj was created.' => 'Hiçbir %obj oluşturuldu.', + 'No %obj was updated.' => 'Hiçbir %obj güncelleştirildi.', + 'No module found for code \'%item\'' => 'Hiçbir modül kodu için \'%item\' bulunamadı', + 'No, I am a new customer.' => 'Hayır, ben yeni bir müşteriyim.', + 'None' => 'Yok', + 'Not equal to' => 'Eşit değil', + 'Not in' => 'Değil', + 'Notices' => 'Bildirimler', + 'Numerical ISO Code' => 'Sayısal ISO kodu', + 'Only files having the following mime type are allowed: %types%' => 'Yalnızca aşağıdaki MIME türüne sahip dosyalar izin verilir: %types%', + 'Only hookable modules are displayed in this menu.' => 'Sadece hookable modülleri bu menüde görüntülenir.', + 'Only if order billing country is %op% %countries_list%' => 'Sipariş teslim ülkesi %op% %countries_list% öder ', + 'Only if order shipping country is %op% %countries_list%' => 'Sipariş teslim ülkesi %op% %countries_list% öder ', + 'Order' => 'Sipariş', + 'Order address ID not found' => 'Sipariş adresi ID kimliği bulunamadı', + 'Order failed' => 'Sipariş başarısız oldu', + 'Order ref. %ref is now unpaid.' => 'Sipariş referans %ref şu anda ödenmemiş.', + 'Order ref. %ref, ID %id has been successfully paid.' => 'Sipariş referans %ref, kimliği %id başarıyla ödendi.', + 'Orders' => 'siparişler', + 'Overall' => 'Genel', + 'Page 404' => 'Sayfa 404', + 'Page Title' => 'Sayfa Başlığı', + 'Parent category' => 'Ana Kategori', + 'Parent folder *' => 'Ana klasör *', + 'Password' => 'Parola', + 'Password *' => 'Şifre *', + 'Password confirmation' => 'Şifre onaylama', + 'Payment failed' => 'ödemede hata oluştu', + 'Payment gateway' => 'Ödeme ağ geçidi', + 'Per customer' => 'Müşteri başına', + 'Percentage' => 'Yüzde indirim', + 'Percentage discount for selected attribute values' => 'Seçilen özellik değerleri için yüzde indirim', + 'Percentage discount for selected categories' => 'Seçili kategoriler için yüzde indirim', + 'Percentage discount for selected products' => 'Seçili ürünleri için yüzde indirim', + 'Percentage of the product price' => 'Ürün fiyatının yüzdesi', + 'Phone' => 'Telefon', + 'Placed order' => 'Siparişi tamamla', + 'Please accept the Terms and conditions in order to register.' => 'Lütfen kayıt için şartlar ve koşullar kabul.', + 'Please check your input: %error' => 'Lütfen girişinizi denetleyin: %error', + 'Please enter your email address' => 'Lütfen e-posta adresini gir', + 'Please enter your password' => 'Lütfen parolanızı girin', + 'Please select a category' => 'Lütfen bir kategori seçin', + 'Please select an attribute' => 'Lütfen bir Özellik Seçin', + 'Please select at least one attribute value' => 'Lütfen en az bir öznitelik değeri seçin', + 'Please select at least one category' => 'Lütfen en az bir kategori seçin', + 'Please select at least one product' => 'Lütfen en az bir ürün seçiniz', + 'Please select the category of the offred product' => 'Offred ürün kategorisi seçiniz', + 'Please select the offered product' => 'Sunulan ürün seçiniz', + 'Please upload a valid Zip file' => 'Lütfen geçerli bir ZIP dosyası yükleme', + 'Port' => 'Port', + 'Postage' => 'Posta', + 'Preferred locale' => 'Tercih edilen yerel ayarı', + 'Prevent mailing template modification or deletion, except for super-admin' => 'Posta şablonu değiştirme ya da silme, super-yönetici dışında önlem', + 'Prevent variable modification or deletion, except for super-admin' => 'Değişken değiştirme ya da silmek, super-yönetici dışında önlem', + 'Price currency *' => 'Fiyat para birimi *', + 'Processing cancelation of payment for order ref. %ref' => 'İptal sipariş referans %ref için ödeme işleme', + 'Processing confirmation of order ref. %ref, ID %id' => 'İşleme onay sipariş referans %ref, kimliği %id', + 'Prodcut ID *' => 'Ürün kodu *', + 'Product' => 'ürün', + 'Product ID' => 'Ürün ID', + 'Product ID *' => 'Ürün ID *', + 'Product attributes' => 'Ürün özellikleri', + 'Product base price excluding taxes *' => 'Ürün Taban Fiyatı Kdv hariç *', + 'Product base price with taxes' => 'Ürün temel fiyat Kdv ile', + 'Product categories' => 'Ürün Kategorileri', + 'Product clone' => 'Ürün klon', + 'Product loop' => 'Ürün döngüsü', + 'Product page' => 'Ürün sayfası', + 'Product price excluding taxes' => 'Ürün Fiyatı kdv hariç', + 'Product price excluding taxes *' => 'Ürün Fiyatı kdv hariç *', + 'Product price including taxes' => 'Ürün Fiyatı kdv hariç', + 'Product price offset for each currency' => 'Her para birimi için ürün fiyatı mahsup hesabı', + 'Product reference (must be unique)' => 'Ürün başvuru (benzersiz olmalıdır)', + 'Product reference *' => 'Ürün referans *', + 'Product sale element ID *' => 'Ürün satış elemanı kimliği *', + 'Product template' => 'Ürün şablonu', + 'Product title' => 'Ürün başlığı', + 'ProductSaleElement modification' => 'Ürün Satış Element modifikasyonu', + 'Products' => 'ürün', + 'Profile' => 'Profil', + 'Profile Code' => 'Profil kodu', + 'Profile ID not found' => 'Profil ID kimliği bulunamadı', + 'Profile `code` already exists' => 'Profil \'şifre\' zaten var', + 'Profiles' => 'Profiller', + 'Purpose' => 'Amaç', + 'Purpose *' => 'Amaç *', + 'Quantity' => 'Adet', + 'Range date End' => 'Aralığının bitiş tarihi', + 'Range date Start' => 'Aralığının başlangıç tarihi', + 'Rate' => 'Oranı', + 'Redirecting ...' => 'Yönlendirme...', + 'Redirecting to %url' => '%url için yeniden yönlendirme', + 'Reference' => 'referans', + 'Reference *' => 'referans', + 'Register' => 'Kaydol', + 'Remember me ?' => 'Beni hatırla ?', + 'Remove X percent to total cart' => 'Toplam sepeti Kaldır X yüzde', + 'Replace by the default language' => 'Tarafından varsayılan dili değiştirin', + 'Replace current document by this file' => 'Bu dosyadan geçerli belgeyi değiştirmek', + 'Replace current image by this file' => 'Bu dosyadaki şu anki görüntüyü değiştirin', + 'Reseller' => 'Bayi', + 'Rewriten URL' => 'Yazılabilir URL', + 'Rotated Text File' => 'Döndürülmüş metin dosyası', + 'Sale announce label' => 'Satılık ilan etiketi', + 'Sale price excluding taxes' => 'kdv hariç satış fiyatı', + 'Sale price including taxes' => 'kdv hariç satış fiyatı', + 'Sale title' => 'Satış Başlığı', + 'Saving %obj% for %parentName% parent id %parentId%' => '%obj% %parentName% üst kimliği %parentId% için kaydetme', + 'Search' => 'Arama', + 'Search page' => 'Arama sayfası', + 'Select a default template for new products created in this category' => 'Bu kategoride oluşturulan yeni ürünler için bir varsayılan şablon seçin', + 'Select the brand logo' => 'Marka logosu seçin', + 'Select the brand logo amongst the brand images' => 'Marka Resimler arasından marka logosu seçin', + 'Select the categories of the products covered by this operation' => 'Bu işlem tarafından kapsanan ürün kategorilerini seçin', + 'Select the countries to delete from this shipping zone' => 'Bu nakliye bölgesini silmek için ülke seçin', + 'Select the countries to include in this shipping zone' => 'Bu nakliye bölgesini dahil etmek için ülke seçin', + 'Select the discount type that will be applied to original product prices' => 'Orijinal ürün fiyatları için uygulanacak indirim türünü seçin', + 'Select the parent category of this category.' => 'Bu kategorinin ana kategorisini seçin.', + 'Select the product attributes included in this operation' => 'Bu işlem dahil ürün özelliklerini seçin', + 'Select the product brand, or supplier.' => 'Ürün marka veya tedarikçi seçin.', + 'Select the products covered by this operation' => 'Bu işlem tarafından kapsanan ürünler seçin', + 'Select the virtual document' => 'Sanal belgeyi seçin', + 'Service ID' => 'Hizmet kimliği', + 'Shipping configuration' => 'Aktarma yapılandırması', + 'Shipping zone name' => 'Nakliye bölge adı', + 'Short additional text' => 'Kısa ek metin', + 'Short description text' => 'Kısa açıklama metni', + 'Show redirections *' => 'Yeniden yönlendirmelerini göster *', + 'Sitemap' => 'Site Haritası (sitemap)', + 'Sorry, an error occured.' => 'Üzgünüz, bir hata oluştu.', + 'Sorry, an error occured: %msg' => 'Üzgünüz, bir hata oluştu: %msg', + 'Sorry, an error occured: %s' => 'Üzgünüz, bir hata oluştu: %s', + 'Sorry, an error occurred: %err' => 'Üzgünüz, bir hata oluştu: %err', + 'Sorry, you are not allowed to perform this action.' => 'Üzgünüz, sen bu eylemi gerçekleştirmek için iznin yok.', + 'Sorry, you\'re not allowed to perform this action' => 'Üzgünüz, sen bu eylemi gerçekleştirmek için iznin yok', + 'Source IP' => 'Kaynak IP', + 'Start date' => 'Başlangıç tarihi', + 'Start date of sales' => 'Satış başlangıç tarihi', + 'Stock' => 'Stok', + 'Store Business Identification Number (SIRET, etc).' => 'Mağaza iş tanımlama numarası (SIRET, vb).', + 'Store Information' => 'Mağaza Bilgileri', + 'Store configuration failed.' => 'Mağaza yapılandırması başarısız oldu.', + 'Store description' => 'Mağaza açıklama', + 'Store email address' => 'Mağaza e-posta adresi', + 'Store logs into text file' => 'Stok günlükleri içine metin ekle', + 'Store logs into text file, up to a certian size, then a new file is created' => 'O zaman yeni bir dosya oluşturulur stok günlükleri metin dosyası belirli bir boyuta kadar içinde', + 'Store name' => 'Mağaza Adı', + 'Street Address' => 'Cadde', + 'Street Address ' => 'Adresi ', + 'Strictly use the requested language' => 'Kesinlikle istenen dil kullanma', + 'Subject' => 'Konu', + 'Summary' => 'Özet', + 'Symbol' => 'Sembol', + 'System' => 'Sistem', + 'System configuration' => 'Sistem Yapılandırması', + 'System log configuration failed.' => 'Sistem günlüğü yapılandırması başarısız oldu.', + 'Tax' => 'Kdv', + 'Tax ID not found in tax list JSON' => 'Vergi kimlik numarası vergi listesinde JSON dosyası içinde bulunamadı', + 'Tax list is not valid JSON' => 'Vergi listesi geçerli JSON dosyasında geçerli değil', + 'Tax rule ID not found' => 'Vergi kural ID değil kurmak', + 'Tax rule for this product *' => 'Bu ürün için vergi kuralı *', + 'Taxes' => 'Kdv', + 'Taxes rules' => 'Kdv kuralları', + 'Template' => 'Şablon', + 'Template Name *' => 'Şablon adı *', + 'Templates' => 'Şablonlar', + 'Text File' => 'Metin dosyası', + 'Text Message' => 'Metin iletisi', + 'The %name module definition has not been initialized.' => '%name modülünün tanımı başlatılmadı.', + 'The %name module descriptor has not been initialized.' => '%name modülü tanımlayıcısı başlatılmadı.', + 'The %obj_name id \'%id\' doesn\'t exist' => '%obj_name ID \'%id\' yok', + 'The HTML TITLE element is the most important element on your web page.' => 'HTML başlığı web sayfanızdaki en önemli unsur geçer.', + 'The brand name or title' => 'Marka adı veya başlık', + 'The cart item count should match the condition' => 'Sepeti madde sayısı koşulla eşleşmesi', + 'The category title' => 'Kategori başlığı', + 'The class "%class" doesn\'t exist' => '"%class" sınıfı yok', + 'The class "%class" must extend %baseClass' => '"%class" sınıfı %baseClass genişletmeniz gerekir', + 'The container should not be null in this form. Please use the FormFactory to get an instance.' => 'Konteyner bu formda null olmamalıdır. Lütfen bir örnek almak için FormFactory kullanın.', + 'The coupon applies if the cart contains at least one product of the selected categories' => 'Belgili tanımlık at arabası seçili kategoriden en az bir ürün varsa kupon geçerlidir', + 'The coupon applies if the cart contains at least one product of the specified product list' => 'Belirtilen ürün listesinin en az bir ürün sepetin içeriyorsa, kupon geçerlidir', + 'The coupon applies to some customers only' => 'Kupon sadece bazı müşteriler için geçerlidir', + 'The coupon applies to the selected billing countries' => 'Seçilen Fatura ülkelere göre kupon geçerlidir', + 'The coupon applies to the selected delivery countries' => 'Bu kupon kodu yalnızca seçilen ülkeye geçerlidir', + 'The coupon code \'%code\' already exist. Please choose another coupon code' => 'Kupon kodu \'%code\' zaten mevcut. Lütfen başka bir kupon kodunu seçin', + 'The coupon code \'%code\' already exists. Please choose another coupon code' => 'Kupon kodu \'%code\' zaten mevcut. Lütfen başka bir kupon kodunu seçin', + 'The coupon is valid after a given date' => 'Kupon kodu yalnızca belirli bir tarihten itibaren geçerlidir', + 'The date after which sales are de-activated. Please use %fmt format.' => 'Sonra satış de-harekete geçirmek tarih. Lütfen %fmt biçimini kullanın.', + 'The date from which sales are active. Please use %fmt format.' => 'Hangi satış etkin tarih. Lütfen %fmt biçimini kullanın.', + 'The detailed description.' => 'Ayrıntılı açıklama.', + 'The file %path has been successfully downloaded' => 'Dosya %path başarıyla karşıdan yüklenmiş olan', + 'The following columns are missing: %columns' => 'Aşağıdaki sütunları eksik: %columns', + 'The image which replaces an undefined country flag (%file) was not found. Please check unknown-flag-path configuration variable, and check that the image exists.' => 'Bir tanımsız ülke bayrağı (%file) yerini alan görüntü bulunamadı. Bilinmeyen-bayrak-yol yapılandırma değişkeni ve yansıma var onay gözden geçirin.', + 'The language "%id" doesn\'t exist' => '"%id" dil yok', + 'The mailing template in HTML format.' => 'HTML formatında posta şablonu.', + 'The mailing template in text-only format.' => 'Salt metin formatında posta şablonu.', + 'The method name that will handle the hook event.' => 'Kanca olay işleyecek yöntemi adı.', + 'The module "%name%" is currently in use by at least one order, and can\'t be deleted.' => '"%name%" modül şu anda en az bir sipariş tarafından kullanılıyor ve silinemez.', + 'The module %module has been installed successfully.' => 'Modül %modul başarıyla yüklendi.', + 'The module %name is already installed in the same or greater version.' => 'Modül %name aynı veya daha fazla sürümü zaten yüklü.', + 'The module %name requires Thelia %version or newer' => 'Modül %name Thelia %version gerektirir veya daha yeni', + 'The module has to be activated.' => 'Modül aktif olmalı.', + 'The module is not valid : %message' => 'Belgili tanımlık ölçü birimi geçerli değil: %message', + 'The module zip file' => 'Modülü zip dosyası', + 'The product document id %id doesn\'t exists' => 'Değil ürün belge kimliği %id var', + 'The product image id %id doesn\'t exists' => 'Değil ürün görüntü kimliği %id var', + 'The product sale element id %id doesn\'t exist' => 'Ürün satış elemanı kimliği %id yok', + 'The product sale elements id %id doesn\'t exist' => 'Ürün satış elemanı kimliği %id yok', + 'The product sale elements id %id doesn\'t exists' => 'Ürün satış elemanı kimliği %id yok', + 'The resource %res has not been found' => 'Kaynak %res değil bulundu', + 'The sale announce label, such as Sales ! or Flash Sales !' => 'Satış satış gibi etiket anons! veya satış Flash!', + 'The sale name or descriptive title' => 'Satılık Ürün adı veya açıklayıcı bir başlık', + 'The sale name or title' => 'Satılık Ürün adı veya başlık', + 'The service id that will handle the hook (defined in the config.xml file of the module).' => '(Modül config.xml dosyasında tanımlanan) kanca idare edecektir hizmet kimliği.', + 'The store fax number.' => 'Mağaza faks numarası.', + 'The store phone number.' => 'Mağaza telefon numarası.', + 'The type %type is not valid' => 'Türü %type geçerli değil', + 'There are no files to associate.' => 'Ilişkilendirmek için hiçbir dosya bulunmamaktadır.', + 'There is no id "%id" in the export categories' => 'İhracat kategorilerde kimlik yok "%id" olduğunu', + 'There is no id "%id" in the exports' => 'İhracatta kimlik yok "%id" olduğunu', + 'There is no id "%id" in the import categories' => 'İhracat kategorilerde kimlik yok "%id" olduğunu', + 'There is no id "%id" in the imports' => 'İhracatta kimlik yok "%id" olduğunu', + 'There\'s a conflict between your file extension "%ext" and the mime type "%mime"' => 'Dosya uzantısı "%ext" ile "%mime" MIME türü arasında bir çatışma', + 'This PHP extension should be installed and loaded.' => 'Bu PHP uzantısı yüklü ve kurulu olmalıdır', + 'This brand is online' => 'Bu marka yayında', + 'This category is online' => 'Bu kategori yayında', + 'This condition is always true' => 'Bu durum her zaman doğrudur', + 'This content is online.' => 'Bu içerik çevrimiçi durumda.', + 'This coupon adds a free product to the cart if one of the selected products is in the cart.' => 'Seçili ürün sepetinizde ise bu kuponu bir ürün sepetine ekler.', + 'This coupon does not exists' => 'Bu kupon yok', + 'This coupon subtracts from the order total a percentage of the price of each product which belongs to the selected categories. If the discount is greater than the total order, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.' => 'Bu kupon sipariş toplam arasından seçilen kategorilere ait her ürünün fiyatının bir yüzdesi çıkarır. İndirim toplam sipariş büyükse, kupon, aynı zamanda ücretsiz nakliye sağlarsa, müşterinin sadece nakliye, ya da hiçbir şey ödeyecek.', + 'This coupon subtracts from the order total the specified percentage of each product price which uses the selected attribute values. If the discount is greater than the total order, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.' => 'Bu kupon sipariş toplam arasından seçilen özniteliği değerleri kullanan her ürün fiyatının belirtilen yüzdesi çıkarır. İndirim toplam sipariş büyükse, kupon, aynı zamanda ücretsiz nakliye sağlarsa, müşterinin sadece nakliye, ya da hiçbir şey ödeyecek.', + 'This coupon subtracts from the order total the specified percentage of each selected product price. If the discount is greater than the total order, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.' => 'Bu kupon sipariş toplamı her seçili ürün fiyat belirtilen yüzdesi çıkarır. İndirim toplam sipariş büyükse, kupon, aynı zamanda ücretsiz nakliye sağlarsa, müşterinin sadece nakliye, ya da hiçbir şey ödeyecek.', + 'This coupon subtracts the specified amount from the order total for each product which belongs to the selected categories. If the discount is greater than the total order, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.' => 'Bu kupon sipariş toplam arasından seçilen kategorilere ait her ürünün fiyatının bir yüzdesi çıkarır. İndirim toplam sipariş büyükse, kupon, aynı zamanda ücretsiz nakliye sağlarsa, müşterinin sadece nakliye, ya da hiçbir şey ödeyecek.', + 'This coupon subtracts the specified amount from the order total for each product which uses the selected attribute values. If the discount is greater than the total order, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.' => 'Bu kupon sipariş toplam arasından seçilen kategorilere ait her ürünün fiyatının bir yüzdesi çıkarır. İndirim toplam sipariş büyükse, kupon, aynı zamanda ücretsiz nakliye sağlarsa, müşterinin sadece nakliye, ya da hiçbir şey ödeyecek.', + 'This coupon subtracts the specified amount from the order total for each selected product. If the discount is greater than the total order, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.' => 'Bu kupon seçili her ürün için sipariş toplamının belirtilen tutardan çıkarır. İndirim toplam sipariş büyükse, kupon, aynı zamanda ücretsiz nakliye sağlarsa, müşterinin sadece nakliye, ya da hiçbir şey ödeyecek.', + 'This coupon will offert a flat percentage off a shopper\'s entire order (not applied to shipping costs or tax rates). If the discount is greater than the total order corst, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.' => 'Bu kupon kapalı bir alışveriş tüm sipariş (masraf ya da vergi oranları nakliye için uygulanmadı) düz yüzde offert olacak. İndirim toplam sipariş maliyet büyükse, kupon, aynı zamanda ücretsiz nakliye sağlarsa, müşterinin sadece nakliye, ya da hiçbir şey ödeyecek.', + 'This coupon will subtracts a set amount from the total cost of an order. If the discount is greater than the total order corst, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.' => 'Bu kupon toplam maliyet üzerinden bir miktar bir siparişin çıkarır. İndirim toplam sipariş maliyet büyükse, kupon, aynı zamanda ücretsiz nakliye sağlarsa, müşterinin sadece nakliye, ya da hiçbir şey ödeyecek.', + 'This document is online' => 'Bu belge yayında', + 'This email already exists.' => 'Bu email zaten mevcut.', + 'This email does not exists' => 'Böyle bir e-posta adresi yok', + 'This folder is online.' => 'Online klasördür.', + 'This hook is specific to a module (delivery/payment modules).' => 'Bu kanca bir modül (teslimat/ödeme modülleri) özgüdür.', + 'This image is online' => 'Bu resim yayında', + 'This is a comma separated list of email addresses where store notifications (such as order placed) are sent.' => 'Bu e-posta adreslerini, virgülle ayrılmış listesini nerede mağaza bildirimleri (örneğin, sipariş yerleştirilir) gönderilir.', + 'This is an identifier that will be used in the code to get this message' => 'Bu kod, bu mesajı almak için kullanılacak bir tanımlayıcıdır', + 'This is the contact email address, and the sender email of all e-mails sent by your store.' => 'İletişim e-posta adresi ve mağaza tarafından gönderilen tüm e-postaları gönderen e-posta bu.', + 'This is the message purpose, such as \'Order confirmation\'.' => 'Bu mesaj, "Sipariş onayı" gibi amacıdır.', + 'This is the subject of the e-mail, such as \'Your order is confirmed\'.' => '\'Sipariş doğruladı gibi\' e-postanın konusu bu.', + 'This module has no Markdown documentation.' => 'Bu modül yok etiketleme belgelerine sahiptir.', + 'This product does not have a physical presence' => 'Bu ürün fiziksel bir varlığa sahip değil', + 'This product is on sale' => 'Bu ürün indirimde', + 'This product is online' => 'Bu ürün online', + 'This product reference is already assigned to another product.' => 'Bu ürün başvuru zaten başka bir ürün için atanır.', + 'This product_sale_elements_id does not exists for this product : %d' => 'Bu ürün_satış_elementler_id bu ürün için yok: %d', + 'This template is in use in some of your products, and cannot be deleted. Delete it from all your products and try again.' => 'Bu şablon, ürünlerden bazıları kullanılıyor ve silinemez. Tüm ürünleri silin ve yeniden deneyin.', + 'This the unique name of this message. Do not change this value unless you understand what you do.' => 'Bu bu iletinin benzersiz adı. Ne anlamak sürece bu değeri değiştirmeyin.', + 'This value should not be blank.' => 'Bu değer boş olmamalıdır.', + 'Timeout' => 'Zaman Aşımı', + 'Title' => 'Başlık', + 'Title *' => 'Başlık *', + 'Title ID not found' => 'Başlık ID kimliği bulunamadı', + 'To activate module %name, the following modules should be activated first: %modules' => 'Modül %name etkinleştirmek için aşağıdaki modülleri ilk etkinleştirilmesi: %modules', + 'Tools' => 'Araçlar', + 'Translations' => 'Çeviri', + 'Tried to download a file, but the URL was not valid: %url' => 'Bir dosyayı indirmek için çalıştı, ama tanımlık URL geçerli değil: %url', + 'Type' => 'Tür', + 'URL_ALREADY_EXISTS' => 'Bu URL zaten var', + 'Unable to get module code from the fullnamespace element of the module descriptor: \'%val\'' => 'Modül tanımlayıcısı tam ad öğesinden modül kodu alınamadı: \'%val\'', + 'Unable to process your request. Please try again (%err).' => 'İsteğiniz işlenemiyor. Lütfen tekrar deneyin (%err).', + 'Unconditional usage' => 'Koşulsuz kullanım', + 'Unconditionnal usage' => 'Koşulsuz kullanım', + 'Undefined loop argument "%name"' => 'Tanımsız döngü bağımsız değişkeni "%name"', + 'Undefined search mode \'%mode\'' => 'Tanımsız arama modu \'%mode\'', + 'Unknown order ID: %id' => 'Bilinmeyen Sipariş No: %id', + 'Unsupported magic method %name. only getArgname() is supported.' => 'Desteklenmeyen sihirli yöntem %name. Sadece getArgname() desteklenir.', + 'Unsupported type' => 'Desteklenmeyen bir tür', + 'Update customer account' => 'Müşteri hesabını güncelle', + 'Use the keyword phrase in your URL.' => 'Anahtar kelime öbeği URL kullanın.', + 'Used in your store front' => 'Sizin mağaza önünde kullanılan', + 'Username' => 'Kullanıcı Adı', + 'Valid only from %date% to the coupon expiration date' => 'Kupon son kullanma tarihine sadece %date% itibaren geçerli', + 'Value' => 'Fiyat', + 'Value %val for Discount Amount is invalid. Please enter a positive value.' => 'Değer %val iskonto tutarı için geçerli değil. Lütfen pozitif bir değer girin.', + 'Value %val for Percent Discount is invalid. Please enter a positive value between 1 and 100.' => 'Değer %val indirim için geçerli değil. Lütfen 1 ile 100 arasında pozitif bir değer girin.', + 'Value *' => 'Değer *', + 'Value create form' => 'Değer oluşturma formu', + 'Variable' => 'Değişken', + 'Variables' => 'Değişkenler', + 'Virtual document' => 'Sanal belge', + 'Warnings' => 'Uyarılar', + 'We\'re sorry, this PDF invoice is not available at the moment.' => 'Üzgünüz, bu PDF fatura şu anda kullanılabilir değil.', + 'Weight' => 'Ağırlık', + 'Wrong form method, %s expected.' => 'Yanlış form yöntemi, beklenen %s.', + 'Yes, I have a password :' => 'Evet, benim bir şifre var:', + 'You are already registered!' => 'Zaten kayıtlı!', + 'You don\'t need to use commas or other punctuations.' => 'Virgül veya diğer noktalama işaretleri kullanmanız gerekmez.', + 'You have to configure your store email first !' => 'İlk mağaza e-posta yapılandırmak zorunda!', + 'You\'ve submitted this form too many times. ' => 'Bu formu çok kez gönderdiniz. ', + 'Your Email Address' => 'E-posta adresiniz', + 'Your Message' => 'Mesajınız', + 'Your configuration seems to be ok. Checked out your mailbox : %email%' => 'Yapılandırmanız tamam gibi görünüyor. Posta kutunu kontrol: %email%', + 'Your current password does not match.' => 'Geçerli parola yazın eşleşmiyor.', + 'Your zip must contain 1 root directory which is the root folder directory of your module' => 'Senin ZIP modülünüzün kök klasör dizini 1 kök dizin içermelidir', + 'Zip code' => 'Posta Kodu', + 'Zone' => 'Bölge', + 'accessories table header' => 'Aksesuar Tablo üstbilgisi', + 'accessories table row' => 'Aksesuar tablo satırı', + 'add to all form' => 'Tüm forma ekleme', + 'additional information' => 'Ek bilgiler', + 'address create form' => 'adres oluşturma formu', + 'address delete form' => 'adresi silme formu', + 'address update form' => 'adres güncelleştirme formu', + 'after addresse area' => 'sonra adres alanı', + 'after combinations' => 'sonra kombinasyonlar', + 'after footer' => 'altbilgi sonra', + 'after javascript include' => 'sonra JavaScript içerme', + 'after javascript initialisation' => 'sonra JavaScript başlatma', + 'after product listing' => 'sonra ürün listesi', + 'after the information area' => 'sonra bilgi alanı', + 'after the main content area' => 'sonra ana içerik alanı', + 'after the opening of the body tag' => 'gövde etiketini açtıktan sonra', + 'after the opening of the head tag' => 'baş etiketi açtıktan sonra', + 'after the order summary' => 'sonra sipariş Özeti', + 'after top bar' => 'sonra üst çubuğu', + 'after top menu' => 'sonra üst menü', + 'api id %id does not exists' => 'API ID %id mevcut değil', + 'at the bottom' => 'alt kısmında', + 'at the bottom of column 1' => '1 sütun alt kısmında', + 'at the bottom of information area' => 'bilgi alanı alt kısmında', + 'at the bottom of the catalog' => 'Katalog alt kısmında', + 'at the bottom of the detail area' => 'Ayrıntı alanının alt kısmında', + 'at the bottom of the footer' => 'altbilgi alt kısmında', + 'at the bottom of the form' => 'formun alt kısmında', + 'at the bottom of the header' => 'başlık altındaki', + 'at the bottom of the main area' => 'Ana alanının alt kısmında', + 'at the bottom of the shipping area' => 'Sevkiyat alanı alt kısmında', + 'at the bottom of the sidebar' => 'kenar çubuğu alt kısmında', + 'at the bottom of the system area' => 'belgeli tanımlık sistem alan alt kısmında', + 'at the bottom of the top bar' => 'üst çubuğu alt kısmında', + 'at the top' => 'üst kısmında', + 'at the top of the catalog area' => 'Katalog alanının üst kısmında', + 'at the top of the column' => 'sütunun üst kısmında', + 'at the top of the configuration' => 'yapılandırma üst kısmında', + 'at the top of the detail' => 'detay üst kısmında', + 'at the top of the footer' => 'altbilgi üst kısmında', + 'at the top of the form' => 'Formun üst kısmında', + 'at the top of the header' => 'Üstbilgi üst kısmında', + 'at the top of the main area' => 'Ana alanının üst kısmında', + 'at the top of the shipping area' => 'Sevkiyat alanı üst kısımda', + 'at the top of the sidebar' => 'kenar çubuğu üstündeki', + 'at the top of the system area' => 'belgeli tanımlık sistem alan üst kısmında', + 'at the top of the top bar' => 'üst çubuğu üstündeki', + 'attributes table header' => 'özellikleri Tablo üstbilgisi', + 'attributes table row' => 'özellikler tablo satırı', + 'before combinations' => 'önce kombinasyonları', + 'before footer' => 'altbilgisinden önce', + 'before the end body tag' => 'Sonunda vücut etiketinden önce', + 'before the end of the head tag' => 'baş etiketi sona ermeden', + 'before the main content area' => 'önce ana içerik alanı', + 'before top menu' => 'önce üst menü', + 'before topbar' => 'üst çubukta önce', + 'block' => 'blok', + 'bottom' => 'Alt', + 'bottom of the footer' => 'altbilginin alt kısmı', + 'cURL errno %errno, http code %http_code on link "%path": %error' => 'cURL dönen %errno, http kodu % http_code "%path" bağlantısını: %error', + 'caption' => 'resim yazısı', + 'categories table header' => 'Kategoriler tablosu başlığı', + 'categories table row' => 'Kategoriler tablo satırı', + 'combination delete form' => 'kombinasyon silme formu', + 'combinations list caption' => 'kombinasyon listesi başlığı', + 'configuration' => 'Ayarlar', + 'configuration JavaScript' => 'yapılandırma JavaScript', + 'configuration bottom' => 'Yapılandırma alt', + 'content' => 'içerik', + 'content area' => 'içerik alanı', + 'content delete form' => 'içerik silme formu', + 'content edit JavaScript' => 'İçerik düzenleme JavaScript', + 'contents table header' => 'İçindekiler tablosu başlığı', + 'contents table row' => 'içerik tablo satırı', + 'context' => 'içerik', + 'country delete form' => 'ülke silme formu', + 'create JavaScript' => 'JavaScript oluşturmak', + 'create form' => 'oluşturma formu', + 'customer account' => 'Müşteri hesabı', + 'date format' => 'Tarih Biçimi', + 'decimal separator' => 'ondalık ayırıcı', + 'delete form' => 'formu silmek', + 'delivery address' => 'Teslimat adresi', + 'delivery module %s is not a Thelia\Module\DeliveryModuleInterface' => 'teslim modülü %s bir Thelia\Module\DeliveryModuleInterface değil', + 'details pricing form' => 'ayrıntıları fiyatlandırma formu', + 'details promotion form' => 'ayrıntıları tanıtım formu', + 'email' => 'E-posta', + 'email confirmation is not the same as email field' => 'İki e-posta adresleri özdeş değil', + 'email system JavaScript' => 'e-posta sistemi JavaScript', + 'extra area' => 'İlave alan', + 'extra payment zone' => 'ek ödeme bölge', + 'features table row' => 'özellikleri tablo satırı', + 'features-table-header' => 'özellikleri Tablo başlık', + 'folders table header' => 'klasörler Tablo üstbilgisi', + 'folders table row' => 'Klasörler tablo satırı', + 'footer body' => 'altbilgi vücut', + 'header' => 'Üstbilgi', + 'hook delete form' => 'kanca silme formu', + 'hook edit JavaScript' => 'kanca düzenleme JavaScript', + 'hour(s)' => 'Saat', + 'id delete form' => 'kimlik silme formu', + 'if successful response' => 'Eğer başarılı yanıt', + 'imprint' => 'etki', + 'in footer' => 'altbilgi içinde', + 'in the header' => 'Başlıkta', + 'in the menu catalog' => 'Menü katalog', + 'in the menu configuration' => 'Menü yapılandırma', + 'in the menu customers' => 'Menü müşteriler', + 'in the menu folders' => 'Menü klasörlerde', + 'in the menu modules' => 'Menü modülleri', + 'in the menu orders' => 'Menü siparişler', + 'in the menu tools' => 'menü Araçlar', + 'in top menu items' => 'üst menü öğeleri', + 'inside top bar' => 'üst çubuğu içinde', + 'javascript' => 'JavaScript', + 'javascript initialization' => 'JavaScript başlatma', + 'label' => 'etiket', + 'language locale' => 'Yerel dil', + 'language selection page' => 'Dil seçimi sayfası', + 'list JavaScript' => 'JavaScript listesi', + 'list caption' => 'liste resim yazısı', + 'list header' => 'Liste üstbilgisi', + 'list row' => 'liste satır', + 'logs JavaScript' => 'günlükleri JavaScript', + 'mailing system modification' => 'posta sistem değiştirme', + 'main area' => 'Ana alan', + 'middle' => 'ortasında', + 'minute(s)' => 'dakika', + 'password confirmation is not the same as password field' => 'parola onayı parola alanı ile aynı değil', + 'password must be composed of at least 4 characters' => 'Parola en az 4 karakterden oluşmalıdır', + 'payment module %s is not a Thelia\Module\PaymentModuleInterface' => 'ödeme modülü %s bir Thelia\Module\PaymentModuleInterface değil', + 'pdf' => 'PDF', + 'permanent discount (in percent)' => 'kalıcı indirim (yüzde) olarak', + 'photo gallery' => 'Fotoğraf Galerisi', + 'plain, login, cram-md5 or empty' => 'düz, giriş, cram-md5 veya boş', + 'primary navigation' => 'birincil gezinti', + 'product list' => 'Ürün Listesi', + 'quantity value is not valid' => 'miktar değeri geçerli değil', + 'remove to all form' => 'Tüm formu kaldırma', + 'row' => 'satır', + 'rule create form' => 'Kural oluşturma formu', + 'rule delete form' => 'Kural silme formu', + 'rule edit JavaScript' => 'Kuralı Düzenle JavaScript', + 'secondary navigation' => 'İkinci gezinti', + 'ssl, tls or empty' => 'SSL, tls veya boş', + 'stock edit form' => 'stok form düzenleme formu', + 'table header' => 'Tablo üstbilgisi', + 'table row' => 'tablo satırı', + 'tax rule' => 'Kdv kuralı', + 'the body of the sidebar' => 'kenar gövdesi', + 'this product id does not exists : %d' => 'Bu ürün kimliği yok: %d', + 'thousands separator' => 'Binler ayracı', + 'time format' => 'Zaman formatı', + 'type' => 'türü', + 'update JavaScript' => 'Güncelleme JavaScript', + 'update form' => 'güncelleştirme formu', + 'value table header' => 'değeri Tablo üstbilgisi', + 'value table row' => 'değeri tablo satırı', +]; diff --git a/core/lib/Thelia/Config/I18n/uk_UA.php b/core/lib/Thelia/Config/I18n/uk_UA.php new file mode 100644 index 00000000..74d1bd8c --- /dev/null +++ b/core/lib/Thelia/Config/I18n/uk_UA.php @@ -0,0 +1,201 @@ + ' створення форми контенту', + ' note: only non-visible documents can be associated.' => ' Примітка: тільки не видимі документи можуть бути пов\'язані.', + '"%param" parameter cannot be empty in loop type: %type, name: %name' => 'параметр "%param" не може бути пустим, у циклі типу: %type, з імeнем: %name', + '"%param" parameter is missing in loop type: %type, name: %name' => 'відсутній параметр "%param" у циклі типу: %type, з іменем: %name', + '%module (version: %version)' => '%module (версія: %version)', + '%obj SEO modification' => '%obj SEO модифікація', + '%obj creation' => 'створення %obj', + '%obj modification' => '%obj зміна', + '%obj%s deleted successfully' => '%obj%s успішно видалено', + '%s has dependency to module %s. You have to deactivate this module before.' => '%s залежить від модуля %s. Вам доведеться відключити цей модуль спочатку.', + '%s have dependencies to module %s. You have to deactivate these modules before.' => '%s залежать від модуля %s. Вам потрібно вимкнути ці модулі спочатку.', + '%type% position updated' => '%type% оновлено', + '%type% visibility updated' => 'видимість %type% оновлено', + 'A comma separated list of email addresses' => 'Список адрес електронної пошти, розділених комами', + 'A currency with code "%name" already exists.' => 'Валюта з кодом "%name" вже існує.', + 'A descriptive title' => 'Описові назви', + 'A message with name "%name" already exists.' => 'Повідомлення з іменем «%name» вже існує.', + 'A name such as Europe or Overseas' => 'Ім\'я, наприклад, Європа', + 'A product with reference %ref already exists. Please choose another reference.' => 'Продукт з ідентифікатором %ref вже існує. Будь ласка вкажіть інший ідентифікатор.', + 'A short description, used when a summary or an introduction is required' => 'Короткий опис, використовується, коли потрібне резюме або введення', + 'A short text, used when an additional or supplemental information is required.' => 'Короткий текст, використовується, якщо необхідна додаткова або довідкова інформація.', + 'A user already exists with this email address. Please login or if you\'ve forgotten your password, go to Reset Your Password.' => 'Користувач вже існує з такою адресою. Будь ласка увійдіть, або якщо ви забули свій пароль, перейдіть до розділу відновлення пароля.', + 'A value for attribute "%name" is already present in the combination' => 'Значення атрибута "%name" вже присутнє у комбінації', + 'A variable with name "%name" already exists.' => 'Змінна з іменем "%name" вже існує.', + 'Activate logs only for these IP Addresses' => 'Активувати логування лише для цих IP-адрес', + 'Activate logs only for these files' => 'Активувати логування лише для цих файлів', + 'Activate this sale' => 'Активувати цей продаж', + 'Active' => 'Активний', + 'Additional address information' => 'Додаткова адреса', + 'Address ID not found' => 'ID адреси не знайдено', + 'Address Line 2' => 'Адресна стрічка 2', + 'Address Line 3' => 'Адресна стрічка 3', + 'Address creation' => 'Створення адреси', + 'Address label' => 'Адреса', + 'Address.' => 'Адреса.', + 'Administrator' => 'Адміністратор', + 'Administrator ID not found' => 'ID адміністратора не знайдено', + 'Advertise this product as new' => 'Рекламувати цей продукт, як новий', + 'Alerts' => 'Сповіщення', + 'All Products' => 'Всі продукти', + 'All countries' => 'Всі країни', + 'All shipping methods' => 'Всі методи доставки', + 'Apply exchange rates on price in %sym' => 'Застосувати курси валют у вартість в %sym', + 'Archive Format' => 'Формат архіву', + 'Associate documents' => 'Пов\'язані документи', + 'Associate images' => 'Повязані зображення', + 'At least one of cart products categories is %op% %categories_list%' => 'Принаймні одна категорія в корзині є %op% %categories_list%', + 'Attribut' => 'Атрибут', + 'Attribute ID:Attribute AV ID' => 'ID атрибуту: AV ID атрибуту', + 'Attribute value' => 'Значення атрибуту', + 'Attributes value' => 'Значення атрибутів', + 'Auth mode' => 'Режим перевірки автентичності', + 'Available quantity' => 'Доступна кількість', + 'Available quantity *' => 'Доступна кількість *', + 'Available shipping zones' => 'Доступні зони доставки', + 'Back Office' => 'Панель керування', + 'Bad tax list JSON' => 'Поганий податковий список JSON', + 'Billing country' => 'Країни оплати', + 'Billing country is' => 'Країною оплати є', + 'Brand' => 'Торгова марка', + 'Brand / Supplier' => 'Бренд / Постачальник', + 'Brand name' => 'Фірмове найменування', + 'Brands' => 'Бренди', + 'Business ID' => 'Ідентифікатор бізнесу', + 'By Module' => 'Для модуля', + 'CSS' => 'CSS', + 'CSS stylesheet' => 'Таблиці стилів CSS', + 'Cannot find a default country. Please define one.' => 'Не вдається знайти країну за замовчуванням. Будь ласка, вкажіть її.', + 'Cannot find the shop country. Please select a shop country.' => 'Не вдалося знайти країну магазину. Будь ласка, виберіть її.', + 'Cannot instantiate module "%name%": the namespace is null. Maybe the model is not loaded ?' => 'Не вдалося створити екземпляр модуля "%name%": простір імен дорівнює null. Можливо модель не завантажується?', + 'Cart contains at least a product %op% %products_list%' => 'Корзина містить принаймні один продукт %op% %products_list%', + 'Cart contains categories condition' => 'Корзина містить умови категорій', + 'Cart contains specific products' => 'Кошик містить спеціальні продукти', + 'Cart item count' => 'Кількість елементів у корзині', + 'Cart item count is' => 'Кількість елементів у корзині рівний', + 'Cart total amount' => 'Загальна сума', + 'Cart total amount is' => 'Загальна сума рівна', + 'Catalog configuration' => 'Каталог конфігурації', + 'Category' => 'Категорія', + 'Category page' => 'Категорія сторінки', + 'Cellphone' => 'Мобільний телефон', + 'Change password' => 'Змінити пароль', + 'Check country iso codes here.' => 'Перевірте, iso коди країн у Вікіпедії.', + 'Check the total Cart amount in the given currency' => 'Перевірте загальну суму корзини у даній валюті', + 'Compagny' => 'Компанія', + 'Company Name' => 'Назва компанії', + 'Conclusion' => 'Результат', + 'Confirm Email Address' => 'Підтвердіть Вашу адресу електронної пошти', + 'Confirm Email address' => 'Підтвердіть Вашу адресу електронної пошти', + 'Constant amount' => 'Постійний обсяг', + 'Constant amount found in one of the product\'s feature' => 'Постійний обсяг знайдено в одній з властивостей продукту', + 'Contact and sender email address' => 'Адреса електронної пошти відправника та для контактів', + 'Contact page' => 'Сторінка контактів', + 'Content' => 'Контент', + 'Content page' => 'Зміст сторінки', + 'Content title *' => 'Назва', + 'Contents' => 'Зміст', + 'Core hook of Thelia.' => 'Хук ядра Thelia.', + 'Country ID not found' => 'ID країни не знайдено', + 'Country title' => 'Назва країни', + 'Coupon %code is expired.' => 'Термін дії купона %code минув.', + 'Coupon code %code is disabled.' => '%code код купона недійсний.', + 'Critical' => 'Критичний', + 'Curency selection page' => 'Сторінка вибору валюти', + 'Current Password' => 'Поточний пароль', + 'Customer is %op% %customer_list%' => 'Клієнт є %op% %customer_list%', + 'Date \'%date\' is invalid, please enter a valid date using %fmt format' => 'Неприпустима Дата \'%date\', будь-ласка введіть дійсну дату у форматі %fmt', + 'Debug' => 'Налагодження', + 'Decimal places' => 'Десяткові розряди', + 'Default folder *' => 'Папка за замовчуванням *', + 'Default product category *' => 'Категорія продукту за замовчуванням *', + 'Default product sale element' => 'Елемент продажі за замовчуванням', + 'Default product template' => 'Шаблон продукту за замовчуванням', + 'Deleting %obj% for %id% with parent id %parentId%' => 'Видалення %obj% для %id% з батьківським id %parentId%', + 'Delivery' => 'Доставка', + 'Delivery choice' => 'Вибір доставки', + 'Delivery country' => 'Країна доставки', + 'Delivery country is' => 'Країною доставки є', + 'Delivery module ID not found' => 'ID модуля доставки не знайдено', + 'Delivery zone' => 'Зона доставки', + 'Detailed description' => 'Детальний опис', + 'Disabled' => 'Відключено', + 'Discount type' => 'Тип знижки', + 'Display initial product prices on front-office' => 'Відображення вихідної ціни продукту на фронт офісі', + 'Do compress' => 'Стискати', + 'Document' => 'Документ', + 'Don\'t repeat keywords over and over in a row. Rather, put in keyword phrases.' => 'Не повторюйте ключові слова кілька разів поспіль.', + 'Edit JavaScript' => 'Редагувати JavaScript', + 'Email Address' => 'Адреса електронної пошти', + 'Email addresses of notification recipients' => 'Адреси електронної пошти одержувачів повідомлення', + 'Email test from : %store%' => 'Випробування електронної пошти з: %store%', + 'Emergency' => 'Аварійний', + 'Enable remote SMTP use' => 'Увімкнути віддалене використання SMTP', + 'End date of sales' => 'Дата закінчення продажу', + 'Enter here the brand name in the default language (%title%)' => 'Введіть тут назву торгової марки мовою за замовчуванням (%title%)', + 'Enter here the category title in the default language (%title%)' => 'Введіть тут заголовок категорії мовою за замовчуванням (%title%)', + 'Enter here the mail template purpose in the default language (%title%)' => 'Введіть тут шаблон пошти мовою за замовчуванням (%title%)', + 'Enter here the sale name in the default language (%title%)' => 'Введіть тут назву торгової марки мовою за замовчуванням (%title%)', + 'Equal to' => 'Дорівнює', + 'Error during %action process : %error. Exception was %exc' => 'Помилка під час %action процесу: %error. Винятком була %exc', + 'Error occured while processing order ref. %ref, ID %id: %err' => 'Сталася помилка під час обробки замовлення. %ref, ID %id: %err', + 'Error occured.' => 'Виникла помилка.', + 'Errors' => 'Помилки', + 'Fail to delete %obj% for %id% with parent id %parentId% (Exception : %e%)' => 'Не в змозі видалити %obj% для %id% з батьківським id %parentId% (Виняток: %e%)', + 'Fail to update %type% position: %err%' => 'Не вдалось оновити %type% положення: %err%', + 'Fail to update %type% visibility: %err%' => 'Не вдалось оновити %type% видимість: %err%', + 'Failed to create instance of module "%name%" when trying to delete module. Module directory has probably been deleted' => 'Не вдалося створити екземпляр модуля "%name%" при спробі вилучити модуль. Директорії модуля, ймовірно видалено', + 'Failed to create new hook %s' => 'Не вдалося створити новий хук %s', + 'Failed to deactivate hook with id %s' => 'Не вдалося деактивувати хук з id %s', + 'Failed to delete selected countries' => 'Не вдалося видалити вибрані країни', + 'Failed to find a payment Module with ID=%mid for order ID=%oid' => 'Не вдалося знайти модуль оплати з ID = %mid для замовлення ID =%oid', + 'Failed to load descriptor (module.xml) for module ID "%id".' => 'Не вдалося завантажити дескриптор (module.xml) для модуля "%id".', + 'Failed to load message with code \'%code%\', propably because it does\'nt exists.' => 'Не вдалося завантажити повідомлення з кодом \'%code%\', ймовірно тому, що її не існує.', + 'Failed to open a writing stream on the file: %file' => 'Не вдалося відкрити письмового потоку на файл: %file', + 'Failed to open translation file %file. Please be sure that this file is writable by your Web server' => 'Не вдалося відкрити файл перекладу %file. Будь ласка, переконайтесь, що цей файл доступний для запису веб-сервером', + 'Failed to send message %code. Failed recipients: %failed_addresses' => 'Не вдалося надіслати повідомлення %code. Помилкові отримувачі: %failed_addresses', + 'Failed to update language definition: %ex' => 'Не вдалося оновити визначення мови: %ex', + 'Fax' => 'Факс', + 'Feature' => 'Функції', + 'Feature value does not match FLOAT format' => 'Функція значення не відповідає формату FLOAT', + 'Features value' => 'Значення характеристики', + 'File format' => 'Формат файлу', + 'File is too large, please retry with a file having a size less than %size%.' => 'Файл завеликий, спробуйте ще раз з меншим файлом за %size%.', + 'File to upload' => 'Файл для завантаження', + 'Files with the following extension are not allowed: %extension, please do an archive of the file if you want to upload it' => 'Файли з наступними розширеннями не допускаються: %extension, будь ласка, зробіть архів, якщо ви хочете завантажити його', + 'First Name' => 'Ім\'я', + 'Firstname' => 'Ім\'я', + 'Fixed Amount Discount' => 'Знижка на фіксовану суму', + 'Fixed amount discount for selected attribute values' => 'Фіксована сума знижки для значення вибраних атрибутів', + 'Fixed amount discount for selected categories' => 'Фіксована сума знижки для вибраної категорії', + 'Fixed amount discount for selected products' => 'Фіксована сума знижки для вибраних продуктів', + 'Folder' => 'Каталог', + 'Folder page' => 'Сторінка папки', + 'Folder title *' => 'Назва папки *', + 'For one ore more customers' => 'Для одного або більше клієнтів', + 'Free product when buying one or more selected products' => 'Безкоштовний продукт при покупці одного або більше вибраних продуктів', + 'Front Office' => 'Фронт-Офіс', + 'Full Name' => 'Повне ім\'я', + 'Greater than' => 'Більше ніж', + 'Greater than or equals' => 'Більше або дорівнює', + 'HTML Message' => 'HTML повідомлення', + 'HTML layout' => 'HTML макет', + 'Home page' => 'Домашня сторінка', + 'Hook' => 'Хук', + 'Hook block' => 'Хук блок', + 'Hook code' => 'Хук код', + 'Hook create form' => 'Хук створення форми', + 'Hook title' => 'Заголовок хука', + 'Hooks' => 'Хуки', + 'I would like to receive the newsletter or the latest news.' => 'Я хотів би отримувати оновлення або останні новини.', + 'ISO 639-1 Code' => 'Код ISO 639-1', + 'ISO Alpha-2 code' => 'Код ISO Alpha-2', + 'ISO Alpha-3 code' => 'Код ISO Alpha-3', + 'If cart item count is %operator% %quantity%' => 'Якщо кількість елементів в корзині є %operator% %quantity%', + 'If cart total amount is %operator% %amount% %currency%' => 'Якщо загальна сума є %operator% %amount% %currency%', + 'If checked, this hook will be used by a hook block. If not, by hook function.' => 'Якщо відмічено, цей хук буде використовуватись хуком блоку. Якщо ні - хуком функції.', + 'Image' => 'Картинка', +]; diff --git a/core/lib/Thelia/Config/I18n/zh_CN.php b/core/lib/Thelia/Config/I18n/zh_CN.php new file mode 100644 index 00000000..b25ffebd --- /dev/null +++ b/core/lib/Thelia/Config/I18n/zh_CN.php @@ -0,0 +1,64 @@ + ' 创建内容表格', + ' note: only non-visible documents can be associated.' => ' 注:只能关联不可见文档', + '"%param" parameter cannot be empty in loop type: %type, name: %name' => '在循环类型(loop type):%type, name: %name 中 "%param" 参数不能为空', + '"%param" parameter is missing in loop type: %type, name: %name' => '在循环类型 loop type: %type, name: %name 中 "%param"参数缺失', + '%module (version: %version)' => '%module (版本: %version)', + '%obj SEO modification' => '%obj SEO 修改', + '%obj creation' => '%obj 创建', + '%obj modification' => '%obj 修改', + '%obj%s deleted successfully' => '%obj%s 已成功删除', + '%s has dependency to module %s. You have to deactivate this module before.' => '%s 依赖模块 %s 。你需要先停用此模块。', + '%s have dependencies to module %s. You have to deactivate these modules before.' => '%s 依赖模块 %s 。你需要先停用这些模块。', + '%type% position updated' => '%type% 位置更新', + '%type% visibility updated' => '%type% 可见性更新', + 'A comma separated list of email addresses' => '用逗号分隔电子邮件地址', + 'A currency with code "%name" already exists.' => '货币代码"%name"已存在', + 'A descriptive title' => '标题描述', + 'A message with name "%name" already exists.' => '消息名称"%name"已存在', + 'A name such as Europe or Overseas' => '名称如:欧洲、海外', + 'A product with reference %ref already exists. Please choose another reference.' => '产品参考码 %ref 已存在,请选择其他参考码', + 'A short description, used when a summary or an introduction is required' => '简短描述,用于概要介绍', + 'A short text, used when an additional or supplemental information is required.' => '简短文本,用于补充额外的信息', + 'A user already exists with this email address. Please login or if you\'ve forgotten your password, go to Reset Your Password.' => '该电子邮件地址已注册。请登录,如果您忘记了您的密码,请重置您的密码。', + 'A value for attribute "%name" is already present in the combination' => '"%name"的属性值在组合中已存在', + 'A variable with name "%name" already exists.' => '变量名称"%name"已存在。', + 'Activate logs only for these IP Addresses' => '只对这些 IP 地址激活日志', + 'Activate logs only for these files' => '仅对这些文件激活日志', + 'Activate this sale' => '激活此销售', + 'Active' => '激活', + 'Additional address information' => '补充地址信息', + 'Address ID not found' => '找不到地址 ID', + 'Address Line 2' => '地址栏2', + 'Address Line 3' => '地址栏3', + 'Address creation' => '地址创建', + 'Address label' => '地址标签', + 'Address.' => '地址', + 'Administrator' => '管理员', + 'Administrator ID not found' => '管理员 ID未找到', + 'Advertise this product as new' => '作为新产品进行宣传', + 'Alerts' => '提醒', + 'All Products' => '所有产品', + 'All countries' => '所有国家', + 'All shipping methods' => '所有发货方式', + 'Apply exchange rates on price in %sym' => '在 %sym 上应用汇率', + 'Archive Format' => '档案格式', + 'Associate documents' => '关联文档', + 'Associate images' => '关联图像', + 'At least one of cart products categories is %op% %categories_list%' => '至少一个购物车的产品类别是 %op% %categories_list%', + 'Value *' => '值:*', + 'Value create form' => '值创建表单', + 'Variable' => '变量:', + 'Variables' => '变量', + 'Virtual document' => '虚拟文档', + 'Warnings' => '警告', + 'We\'re sorry, this PDF invoice is not available at the moment.' => '我们很抱歉,此 PDF 发票目前不可用。', + 'You\'ve submitted this form too many times. ' => '你已经多次提交这个表格。 ', + 'Your Email Address' => '您的电子邮件地址', + 'Your Message' => '您的消息', + 'Your configuration seems to be ok. Checked out your mailbox : %email%' => '您的配置似乎是正确的。请检查您的邮箱: %email%', + 'Your current password does not match.' => '您的当前密码不匹配。', + 'Zone' => '区域', +]; diff --git a/core/lib/Thelia/Config/Resources/action.xml b/core/lib/Thelia/Config/Resources/action.xml new file mode 100644 index 00000000..2b7a6fd0 --- /dev/null +++ b/core/lib/Thelia/Config/Resources/action.xml @@ -0,0 +1,244 @@ + + + + + + + + + + + + + %kernel.cache_dir% + + + + + %kernel.cache_dir% + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/core/lib/Thelia/Config/Resources/command.xml b/core/lib/Thelia/Config/Resources/command.xml new file mode 100644 index 00000000..6a4ccf58 --- /dev/null +++ b/core/lib/Thelia/Config/Resources/command.xml @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/core/lib/Thelia/Config/Resources/config.xml b/core/lib/Thelia/Config/Resources/config.xml new file mode 100644 index 00000000..24e8581e --- /dev/null +++ b/core/lib/Thelia/Config/Resources/config.xml @@ -0,0 +1,382 @@ + + + + + + Symfony\Component\HttpKernel\HttpCache\Esi + Symfony\Component\HttpKernel\EventListener\EsiListener + Symfony\Component\HttpKernel\Fragment\EsiFragmentRenderer + Thelia\Core\HttpKernel\Fragment\InlineFragmentRenderer + + + + + Thelia\Model\ProductDocument + Thelia\Model\ProductImage + + Thelia\Model\CategoryDocument + Thelia\Model\CategoryImage + + Thelia\Model\ContentDocument + Thelia\Model\ContentImage + + Thelia\Model\FolderDocument + Thelia\Model\FolderImage + + Thelia\Model\BrandDocument + Thelia\Model\BrandImage + + Thelia\Model\ModuleImage + + + + + SUPERADMINISTRATOR + admin.address + admin.configuration.administrator + admin.configuration.advanced + admin.configuration.area + admin.configuration.attribute + admin.brand + admin.category + admin.configuration" + admin.content + admin.configuration.country + admin.configuration.state + admin.coupon + admin.configuration.currency + admin.customer + admin.configuration.feature + admin.folder + admin.home + admin.configuration.language + admin.configuration.mailing-system + admin.configuration.message + admin.module + admin.hook + admin.module-hook + admin.order + admin.configuration.order-status + admin.product + admin.configuration.profile + admin.configuration.shipping-zone + admin.configuration.tax + admin.configuration.template + admin.configuration.system-logs + admin.configuration.admin-logs + admin.configuration.store + admin.configuration.translations + admin.configuration.update + admin.export + admin.import + admin.tools + admin.sales + admin.configuration.api + admin.customer.title + + + + /admin/import + /admin/export + + thelia.token_provider + validators + + + Thelia\Log\Tlog + + + thelia_cache + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + %kernel.debug% + + + + + + + %kernel.environment% + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + %file_model.classes% + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + %kernel.environment% + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + %thelia.token_id% + + + + + + %thelia.validator.translation_domain% + + + + + + + + + + + + + + + + + + + + %thelia.parser.forms% + + + + + %kernel.environment% + + + + + + + + + + + + + + %admin.resources% + + + + + + + + + + + + + + + + + + %thelia.cache.namespace% + 600 + %kernel.cache_dir% + + + diff --git a/core/lib/Thelia/Config/Resources/coupon.xml b/core/lib/Thelia/Config/Resources/coupon.xml new file mode 100644 index 00000000..960c6181 --- /dev/null +++ b/core/lib/Thelia/Config/Resources/coupon.xml @@ -0,0 +1,134 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/core/lib/Thelia/Config/Resources/export.xml b/core/lib/Thelia/Config/Resources/export.xml new file mode 100644 index 00000000..4a36e2f8 --- /dev/null +++ b/core/lib/Thelia/Config/Resources/export.xml @@ -0,0 +1,136 @@ + + + + + + + Customers + Clients + + + Products + Produits + + + Content + Contenu + + + Orders + Commandes + + + Modules + Modules + + + + + + + Mailing + Exporter le nom, prénom et adresse mail des abonnés à la newsletter + + + Mailing + Export the last name, first name and email address of the newsletter subscribers + + + + + + Clients + Exporter toutes les informations à propos de vos clients + + + Customers + Export all the information about your customers + + + + + + Prix des produits Hors-Taxes + Exporter le prix hors taxes de vos produits + + + Product prices excluding taxes + Export the prices of the products excluding taxes + + + + + + Prix des produits TTC + Exporter le prix TTC de vos produits + + + Product prices including taxes + Export the prices of the products including taxes + + + + + + Product SEO information + + Export the SEO information ( rewritten url, meta description and keywords, page title ) of your products + + + + Informations SEO des produits + + Exporter les informations SEO de vos produits + ( url réécrites, meta description et mots clés, titre ) de vos produits + + + + + + + Contents and folder + + Export your contents and their related folders + + + + Contenus et dossiers + + Exporter vos contenus et les dossiers associés + + + + + + + Full orders + + Export your orders + + + + Commandes complètes + + Exporter vos commandes + + + + + + + Product I18n information + + Export the I18n information (title, chapo, description, postscriptum) of your products + + + + Informations I18n des produits + + Exporter les informations I18n de vos produits (titre produit, résumé, description, conclusion) + + + + + diff --git a/core/lib/Thelia/Config/Resources/form-api.xml b/core/lib/Thelia/Config/Resources/form-api.xml new file mode 100644 index 00000000..59274da2 --- /dev/null +++ b/core/lib/Thelia/Config/Resources/form-api.xml @@ -0,0 +1,28 @@ + + + + + +
+ + + + + + + + + + + + + + + + + + + + diff --git a/core/lib/Thelia/Config/Resources/form-type.xml b/core/lib/Thelia/Config/Resources/form-type.xml new file mode 100644 index 00000000..cb34c12a --- /dev/null +++ b/core/lib/Thelia/Config/Resources/form-type.xml @@ -0,0 +1,335 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/core/lib/Thelia/Config/Resources/form.xml b/core/lib/Thelia/Config/Resources/form.xml new file mode 100644 index 00000000..ac3e4abe --- /dev/null +++ b/core/lib/Thelia/Config/Resources/form.xml @@ -0,0 +1,171 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/core/lib/Thelia/Config/Resources/import.xml b/core/lib/Thelia/Config/Resources/import.xml new file mode 100644 index 00000000..751c27bd --- /dev/null +++ b/core/lib/Thelia/Config/Resources/import.xml @@ -0,0 +1,85 @@ + + + + + + Produits + Products + + + Modules + Modules + + + + + + + Importer votre stock + + +
  • id: L'id de la déclinaison de produit
  • +
  • stock: La quantité de la déclinaison
  • + + ]]> +
    +
    + + Import your stock + + +
  • id: The id of your product sale elements
  • +
  • stock: The quantity of product you have
  • + + It can have the column "ean" that defines the product's EAN code. + ]]> +
    +
    +
    + + + + Importer vos prix Hors-Taxes + + +
  • id: L'id de la déclinaison de produit
  • +
  • price: Le prix Hors-Taxes de votre déclinaison de combinaison de produit
  • + + Il peut aussi optionnellement avoir ces colonnes: +
      +
    • currency: Le code de la monnaie (exemple: EUR, USD)
    • +
    • promo_price: Le prix promotionnel Hors-Taxes de votre déclinaison de combinaison de produit
    • +
    • promo: Si cette valeur est a 0, désactive la promotion, si elle est a 1, l'active
    • +
    + ]]> +
    +
    + + Import your prices excluding taxes + + +
  • id: The id of your product sale elements
  • +
  • price: The price excluding taxes of the product attribute combinations
  • + + It may also optionally have those columns: +
      +
    • currency: the currency code (example: EUR, USD)
    • +
    • promo_price: the promo price excluding taxes of the product attribute combinations
    • +
    • promo: If this value is 0, set the product not in promo, if 1, it sets the product in promo
    • +
    + ]]> +
    +
    +
    +
    +
    diff --git a/core/lib/Thelia/Config/Resources/loop.xml b/core/lib/Thelia/Config/Resources/loop.xml new file mode 100644 index 00000000..b5ca1c55 --- /dev/null +++ b/core/lib/Thelia/Config/Resources/loop.xml @@ -0,0 +1,75 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/core/lib/Thelia/Config/Resources/routing.xml b/core/lib/Thelia/Config/Resources/routing.xml new file mode 100644 index 00000000..235ae8d1 --- /dev/null +++ b/core/lib/Thelia/Config/Resources/routing.xml @@ -0,0 +1,88 @@ + + + + + + Symfony\Component\Routing\RequestContext + Thelia\Routing\NullUrlGenerator + Symfony\Cmf\Component\Routing\DynamicRouter + Symfony\Cmf\Component\Routing\ChainRouter + Symfony\Component\Routing\Router + routing.xml + + + + + + + + + + + + + + + + + + + + + %thelia.core_dir%/Config/Resources/routing + + + + + + + + %thelia.module_dir% + + + + + + + + + admin.xml + + %kernel.cache_dir% + %kernel.debug% + + + + + + + + api.xml + + %kernel.cache_dir% + %kernel.debug% + + + + + + + + + + + + + + + + + + + + + + + diff --git a/core/lib/Thelia/Config/Resources/routing/admin.xml b/core/lib/Thelia/Config/Resources/routing/admin.xml new file mode 100644 index 00000000..e6bf58ce --- /dev/null +++ b/core/lib/Thelia/Config/Resources/routing/admin.xml @@ -0,0 +1,1606 @@ + + + + + + + Thelia\Controller\Admin\AdminController::indexAction + 1 + + + + + + Thelia\Controller\Admin\HomeController::defaultAction + + + + + + + Thelia\Controller\Admin\SessionController::showLoginAction + 1 + + + + Thelia\Controller\Admin\SessionController::showLostPasswordAction + 1 + + + + Thelia\Controller\Admin\SessionController::passwordCreateRequestAction + 1 + + + + Thelia\Controller\Admin\SessionController::passwordCreateRequestSuccessAction + 1 + + + + + Thelia\Controller\Admin\SessionController::displayCreateFormAction + .* + 1 + + + + Thelia\Controller\Admin\SessionController::passwordCreatedAction + 1 + + + + Thelia\Controller\Admin\SessionController::passwordCreatedSuccessAction + 1 + + + + Thelia\Controller\Admin\AdministratorController::setEmailAction + + + + + Thelia\Controller\Admin\SessionController::checkLogoutAction + + + + + Thelia\Controller\Admin\SessionController::checkLoginAction + 1 + + + + + + Thelia\Controller\Admin\CategoryController::defaultAction + + + + + + Thelia\Controller\Admin\FileController::saveImageAjaxAction + .* + \d+ + + + Thelia\Controller\Admin\FileController::getImageFormAjaxAction + .* + \d+ + + + Thelia\Controller\Admin\FileController::getImageListAjaxAction + .* + \d+ + + + Thelia\Controller\Admin\FileController::updateImagePositionAction + .* + \d+ + + + Thelia\Controller\Admin\FileController::updateImageTitleAction + .* + \d+ + + + Thelia\Controller\Admin\FileController::toggleVisibilityImageAction + .* + \d+ + + + Thelia\Controller\Admin\FileController::viewImageAction + .* + \d+ + + + Thelia\Controller\Admin\FileController::updateImageAction + .* + \d+ + + + Thelia\Controller\Admin\FileController::deleteImageAction + .* + \d+ + + + + Thelia\Controller\Admin\FileController::saveDocumentAjaxAction + .* + \d+ + + + Thelia\Controller\Admin\FileController::getDocumentFormAjaxAction + .* + \d+ + + + Thelia\Controller\Admin\FileController::getDocumentListAjaxAction + .* + \d+ + + + Thelia\Controller\Admin\FileController::updateDocumentPositionAction + .* + \d+ + + + Thelia\Controller\Admin\FileController::toggleVisibilityDocumentAction + .* + \d+ + + + Thelia\Controller\Admin\FileController::viewDocumentAction + .* + \d+ + + + Thelia\Controller\Admin\FileController::updateDocumentAction + .* + \d+ + + + Thelia\Controller\Admin\FileController::deleteDocumentAction + .* + \d+ + + + + + + Thelia\Controller\Admin\CustomerController::defaultAction + + + + Thelia\Controller\Admin\CustomerController::updateAction + + + + Thelia\Controller\Admin\CustomerController::processUpdateAction + + + + Thelia\Controller\Admin\CustomerController::deleteAction + + + + Thelia\Controller\Admin\CustomerController::createAction + + + + + + + + Thelia\Controller\Admin\AddressController::deleteAction + + + + Thelia\Controller\Admin\AddressController::useAddressAction + + + + Thelia\Controller\Admin\AddressController::createAction + + + + Thelia\Controller\Admin\AddressController::updateAction + + + + Thelia\Controller\Admin\AddressController::processUpdateAction + + + + + + + + Thelia\Controller\Admin\OrderController::indexAction + + + + Thelia\Controller\Admin\OrderController::viewAction + \d+ + + + + Thelia\Controller\Admin\OrderController::updateStatus + + + + Thelia\Controller\Admin\OrderController::updateStatus + + + + Thelia\Controller\Admin\OrderController::updateDeliveryRef + + + + Thelia\Controller\Admin\OrderController::updateAddress + + + + Thelia\Controller\Admin\OrderController::generateInvoicePdf + 0 + [0|1] + \d+ + + + + Thelia\Controller\Admin\OrderController::generateDeliveryPdf + 0 + [0|1] + \d+ + + + + + + + + Thelia\Controller\Admin\OrderStatusController::defaultAction + + + + Thelia\Controller\Admin\OrderStatusController::createAction + + + + Thelia\Controller\Admin\OrderStatusController::updateAction + \d+ + + + + Thelia\Controller\Admin\OrderStatusController::processUpdateAction + \d+ + + + + Thelia\Controller\Admin\OrderStatusController::deleteAction + + + + Thelia\Controller\Admin\OrderStatusController::updatePositionAction + + + + + + + + Thelia\Controller\Admin\CategoryController::defaultAction + + + + Thelia\Controller\Admin\CategoryController::createAction + + + + Thelia\Controller\Admin\CategoryController::updateAction + + + + Thelia\Controller\Admin\CategoryController::processUpdateAction + + + + Thelia\Controller\Admin\CategoryController::processUpdateSeoAction + + + + Thelia\Controller\Admin\CategoryController::setToggleVisibilityAction + + + + Thelia\Controller\Admin\CategoryController::deleteAction + + + + Thelia\Controller\Admin\CategoryController::updatePositionAction + + + + Thelia\Controller\Admin\CategoryController::addRelatedContentAction + + + + Thelia\Controller\Admin\CategoryController::addRelatedPictureAction + + + + Thelia\Controller\Admin\CategoryController::deleteRelatedContentAction + + + + Thelia\Controller\Admin\CategoryController::getAvailableRelatedContentAction + xml|json + + + + + + Thelia\Controller\Admin\ProductController::defaultAction + + + + Thelia\Controller\Admin\ProductController::createAction + + + + Thelia\Controller\Admin\ProductController::cloneAction + + + + Thelia\Controller\Admin\ProductController::updateAction + + + + Thelia\Controller\Admin\ProductController::processUpdateAction + + + + Thelia\Controller\Admin\ProductController::processUpdateSeoAction + + + + Thelia\Controller\Admin\ProductController::setToggleVisibilityAction + + + + Thelia\Controller\Admin\ProductController::deleteAction + + + + Thelia\Controller\Admin\ProductController::updatePositionAction + + + + + + Thelia\Controller\Admin\ProductController::loadRelatedAjaxTabAction + + + + Thelia\Controller\Admin\ProductController::searchCategoryAction + + + + Thelia\Controller\Admin\ProductController::searchProductAction + + + + + + Thelia\Controller\Admin\ProductController::addAdditionalCategoryAction + + + + Thelia\Controller\Admin\ProductController::deleteAdditionalCategoryAction + + + + + + Thelia\Controller\Admin\ProductController::addRelatedContentAction + + + + Thelia\Controller\Admin\ProductController::deleteRelatedContentAction + + + + Thelia\Controller\Admin\ProductController::getAvailableRelatedContentAction + xml|json + + + + Thelia\Controller\Admin\ProductController::updateContentPositionAction + + + + Thelia\Controller\Admin\ProductController::priceCalculator + + + + Thelia\Controller\Admin\ProductController::calculatePrice + + + + Thelia\Controller\Admin\ProductController::loadConvertedPrices + + + + + + Thelia\Controller\Admin\ProductController::addAccessoryAction + + + + Thelia\Controller\Admin\ProductController::deleteAccessoryAction + + + + Thelia\Controller\Admin\ProductController::getAvailableAccessoriesAction + xml|json + + + + Thelia\Controller\Admin\ProductController::updateAccessoryPositionAction + + + + + + Thelia\Controller\Admin\ProductController::loadAttributesAjaxTabAction + + + + Thelia\Controller\Admin\ProductController::setProductTemplateAction + + + + Thelia\Controller\Admin\ProductController::updateAttributesAndFeaturesAction + + + + + + Thelia\Controller\Admin\ProductController::getAttributeValuesAction + xml|json + + + + Thelia\Controller\Admin\ProductController::addAttributeValueToCombinationAction + xml|json + + + + Thelia\Controller\Admin\ProductController::addProductSaleElementAction + + + + Thelia\Controller\Admin\ProductController::deleteProductSaleElementAction + + + + Thelia\Controller\Admin\ProductController::updateProductSaleElementsAction + + + + Thelia\Controller\Admin\ProductController::buildCombinationsAction + + + + Thelia\Controller\Admin\ProductController::updateProductDefaultSaleElementAction + + + + + + Thelia\Controller\Admin\ProductController::productSaleElementsProductImageDocumentAssociation + \d+ + .+ + \d+ + + + + Thelia\Controller\Admin\ProductController::getAjaxProductSaleElementsImagesDocuments + \d+ + .+ + + + + Thelia\Controller\Admin\ProductController::getVirtualDocumentListAjaxAction + \d+ + \d+ + + + + + + + Thelia\Controller\Admin\FolderController::defaultAction + + + + Thelia\Controller\Admin\FolderController::createAction + + + + Thelia\Controller\Admin\FolderController::updateAction + \d+ + + + + Thelia\Controller\Admin\FolderController::setToggleVisibilityAction + + + + Thelia\Controller\Admin\FolderController::processUpdateAction + + + + Thelia\Controller\Admin\FolderController::processUpdateSeoAction + + + + Thelia\Controller\Admin\FolderController::deleteAction + + + + Thelia\Controller\Admin\FolderController::updatePositionAction + + + + + Thelia\Controller\Admin\ContentController::createAction + + + + Thelia\Controller\Admin\ContentController::updateAction + \d+ + + + + Thelia\Controller\Admin\ContentController::processUpdateAction + + + + Thelia\Controller\Admin\ContentController::processUpdateSeoAction + + + + Thelia\Controller\Admin\ContentController::updatePositionAction + + + + Thelia\Controller\Admin\ContentController::setToggleVisibilityAction + + + + Thelia\Controller\Admin\ContentController::deleteAction + + + + Thelia\Controller\Admin\ContentController::addAdditionalFolderAction + + + + Thelia\Controller\Admin\ContentController::removeAdditionalFolderAction + + + + + + + Thelia\Controller\Admin\CouponController::browseAction + + + Thelia\Controller\Admin\CouponController::createAction + + + Thelia\Controller\Admin\CouponController::updateAction + \d+ + + + Thelia\Controller\Admin\CouponController::deleteAction + + + Thelia\Controller\Admin\CouponController::getBackOfficeInputsAjaxAction + .* + + + Thelia\Controller\Admin\CouponController::getBackOfficeConditionSummariesAjaxAction + \d+ + + + Thelia\Controller\Admin\CouponController::getConditionEmptyInputAjaxAction + .* + + + Thelia\Controller\Admin\CouponController::getConditionToUpdateInputAjaxAction + \d+ + \d+ + + + Thelia\Controller\Admin\CouponController::saveConditionsAction + \d+ + + + Thelia\Controller\Admin\CouponController::deleteConditionsAction + \d+ + \d+ + + + + + + Thelia\Controller\Admin\ConfigurationController::indexAction + + + + Thelia\Controller\Admin\ConfigController::defaultAction + + + + Thelia\Controller\Admin\ConfigController::changeValuesAction + + + + Thelia\Controller\Admin\ConfigController::createAction + + + + Thelia\Controller\Admin\ConfigController::updateAction + + + + Thelia\Controller\Admin\ConfigController::processUpdateAction + + + + Thelia\Controller\Admin\ConfigController::deleteAction + + + + + + Thelia\Controller\Admin\ConfigStoreController::defaultAction + + + + Thelia\Controller\Admin\ConfigStoreController::saveAction + + + + + + + Thelia\Controller\Admin\SystemLogController::defaultAction + + + + Thelia\Controller\Admin\SystemLogController::saveAction + + + + + + Thelia\Controller\Admin\MessageController::defaultAction + + + + Thelia\Controller\Admin\MessageController::createAction + + + + Thelia\Controller\Admin\MessageController::updateAction + + + + Thelia\Controller\Admin\MessageController::processUpdateAction + + + + Thelia\Controller\Admin\MessageController::deleteAction + + + + + + Thelia\Controller\Admin\CurrencyController::defaultAction + + + + Thelia\Controller\Admin\CurrencyController::createAction + + + + Thelia\Controller\Admin\CurrencyController::updateAction + + + + Thelia\Controller\Admin\CurrencyController::processUpdateAction + + + + Thelia\Controller\Admin\CurrencyController::setDefaultAction + + + + Thelia\Controller\Admin\CurrencyController::setVisibleAction + + + + Thelia\Controller\Admin\CurrencyController::updatePositionAction + + + + Thelia\Controller\Admin\CurrencyController::updateRatesAction + + + + Thelia\Controller\Admin\CurrencyController::deleteAction + + + + + + + Thelia\Controller\Admin\TemplateController::defaultAction + + + + Thelia\Controller\Admin\TemplateController::createAction + + + + Thelia\Controller\Admin\TemplateController::updateAction + + + + Thelia\Controller\Admin\TemplateController::processUpdateAction + + + + Thelia\Controller\Admin\TemplateController::deleteAction + + + + Thelia\Controller\Admin\TemplateController::duplicateAction + + + + Thelia\Controller\Admin\TemplateController::getAjaxFeaturesAction + + + + Thelia\Controller\Admin\TemplateController::addFeatureAction + + + + Thelia\Controller\Admin\TemplateController::deleteFeatureAction + + + + Thelia\Controller\Admin\TemplateController::updateFeaturePositionAction + + + + Thelia\Controller\Admin\TemplateController::getAjaxAttributesAction + + + + Thelia\Controller\Admin\TemplateController::addAttributeAction + + + + Thelia\Controller\Admin\TemplateController::deleteAttributeAction + + + + Thelia\Controller\Admin\TemplateController::updateAttributePositionAction + + + + + + + Thelia\Controller\Admin\AttributeController::defaultAction + + + + Thelia\Controller\Admin\AttributeController::createAction + + + + Thelia\Controller\Admin\AttributeController::updateAction + + + + Thelia\Controller\Admin\AttributeController::processUpdateAction + + + + Thelia\Controller\Admin\AttributeController::deleteAction + + + + Thelia\Controller\Admin\AttributeController::updatePositionAction + + + + Thelia\Controller\Admin\AttributeController::removeFromAllTemplates + + + + Thelia\Controller\Admin\AttributeController::addToAllTemplates + + + + + Thelia\Controller\Admin\AttributeAvController::createAction + + + + Thelia\Controller\Admin\AttributeAvController::updateAction + + + + Thelia\Controller\Admin\AttributeAvController::processUpdateAction + + + + Thelia\Controller\Admin\AttributeAvController::deleteAction + + + + Thelia\Controller\Admin\AttributeAvController::updatePositionAction + + + + + + + + + + + + Thelia\Controller\Admin\ShippingZoneController::indexAction + + + + Thelia\Controller\Admin\ShippingZoneController::updateAction + \d+ + + + + Thelia\Controller\Admin\ShippingZoneController::addArea + + + + Thelia\Controller\Admin\ShippingZoneController::removeArea + + + + + + + + Thelia\Controller\Admin\AreaController::defaultAction + + + + Thelia\Controller\Admin\AreaController::updateAction + \d+ + + + + Thelia\Controller\Admin\AreaController::processUpdateAction + \d+ + + + + Thelia\Controller\Admin\AreaController::deleteAction + + + + Thelia\Controller\Admin\AreaController::createAction + + + + Thelia\Controller\Admin\AreaController::updatePostageAction + \d+ + + + + Thelia\Controller\Admin\AreaController::addCountry + + + + Thelia\Controller\Admin\AreaController::removeCountry + + + + Thelia\Controller\Admin\AreaController::removeCountries + + + + + + + + Thelia\Controller\Admin\CountryController::defaultAction + + + + Thelia\Controller\Admin\CountryController::createAction + + + + Thelia\Controller\Admin\CountryController::updateAction + \d+ + + + + Thelia\Controller\Admin\CountryController::processUpdateAction + \d+ + + + + Thelia\Controller\Admin\CountryController::deleteAction + + + + Thelia\Controller\Admin\CountryController::toggleDefaultAction + + + + Thelia\Controller\Admin\CountryController::setToggleVisibilityAction + + + + Thelia\Controller\Admin\CountryController::getDataAction + + + + + + + + Thelia\Controller\Admin\StateController::defaultAction + + + + Thelia\Controller\Admin\StateController::createAction + + + + Thelia\Controller\Admin\StateController::updateAction + \d+ + + + + Thelia\Controller\Admin\StateController::processUpdateAction + \d+ + + + + Thelia\Controller\Admin\StateController::deleteAction + + + + Thelia\Controller\Admin\StateController::setToggleVisibilityAction + + + + + + + + Thelia\Controller\Admin\ProfileController::defaultAction + \d+ + + + + Thelia\Controller\Admin\ProfileController::updateAction + \d+ + + + + Thelia\Controller\Admin\ProfileController::createAction + + + + Thelia\Controller\Admin\ProfileController::processUpdateAction + + + + Thelia\Controller\Admin\ProfileController::processUpdateResourceAccess + + + + Thelia\Controller\Admin\ProfileController::processUpdateModuleAccess + + + + Thelia\Controller\Admin\ProfileController::deleteAction + + + + + + + + Thelia\Controller\Admin\AdministratorController::defaultAction + + + + Thelia\Controller\Admin\AdministratorController::viewAction + + + + Thelia\Controller\Admin\AdministratorController::createAction + + + + Thelia\Controller\Admin\AdministratorController::processUpdateAction + + + + Thelia\Controller\Admin\AdministratorController::deleteAction + + + + + + + + Thelia\Controller\Admin\MailingSystemController::defaultAction + + + + Thelia\Controller\Admin\MailingSystemController::updateAction + + + + Thelia\Controller\Admin\MailingSystemController::testAction + + + + + + + + Thelia\Controller\Admin\AdminLogsController::defaultAction + + + + Thelia\Controller\Admin\AdminLogsController::loadLoggerAjaxAction + + + + + + + + Thelia\Controller\Admin\FeatureController::defaultAction + + + + Thelia\Controller\Admin\FeatureController::createAction + + + + Thelia\Controller\Admin\FeatureController::updateAction + + + + Thelia\Controller\Admin\FeatureController::processUpdateAction + + + + Thelia\Controller\Admin\FeatureController::deleteAction + + + + Thelia\Controller\Admin\FeatureController::updatePositionAction + + + + Thelia\Controller\Admin\FeatureController::removeFromAllTemplates + + + + Thelia\Controller\Admin\FeatureController::addToAllTemplates + + + + + Thelia\Controller\Admin\FeatureAvController::createAction + + + + Thelia\Controller\Admin\FeatureAvController::updateAction + + + + Thelia\Controller\Admin\FeatureAvController::processUpdateAction + + + + Thelia\Controller\Admin\FeatureAvController::deleteAction + + + + Thelia\Controller\Admin\FeatureAvController::updatePositionAction + + + + + + + Thelia\Controller\Admin\AdvancedConfigurationController::defaultAction + + + + Thelia\Controller\Admin\AdvancedConfigurationController::flushCacheAction + + + + Thelia\Controller\Admin\AdvancedConfigurationController::flushAssetsAction + + + + Thelia\Controller\Admin\AdvancedConfigurationController::flushImagesAndDocumentsAction + + + + Thelia\Controller\Admin\ApiController::indexAction + + + + Thelia\Controller\Admin\ApiController::createAction + + + + Thelia\Controller\Admin\ApiController::downloadAction + + + + Thelia\Controller\Admin\ApiController::deleteAction + + + + Thelia\Controller\Admin\ApiController::updateAction + + + + Thelia\Controller\Admin\ApiController::processUpdateAction + + + + + + + + Thelia\Controller\Admin\ModuleController::indexAction + + + + Thelia\Controller\Admin\ModuleController::updateAction + \d+ + + + + Thelia\Controller\Admin\ModuleController::processUpdateAction + + + + Thelia\Controller\Admin\ModuleController::toggleActivationAction + \d+ + + + + Thelia\Controller\Admin\ModuleController::deleteAction + + + + Thelia\Controller\Admin\ModuleController::updatePositionAction + + + + Thelia\Controller\Admin\ModuleController::installAction + + + + Thelia\Controller\Admin\ModuleController::informationAction + \d+ + + + + Thelia\Controller\Admin\ModuleController::documentationAction + \d+ + + + + + Thelia\Controller\Admin\ModuleController::configureAction + + + + + + + + + + Thelia\Controller\Admin\HookController::indexAction + + + + Thelia\Controller\Admin\HookController::discoverAction + + + + Thelia\Controller\Admin\HookController::discoverSaveAction + + + + Thelia\Controller\Admin\HookController::createAction + + + + Thelia\Controller\Admin\HookController::updateAction + \d+ + + + + Thelia\Controller\Admin\HookController::processUpdateAction + \d+ + + + + Thelia\Controller\Admin\HookController::deleteAction + + + + Thelia\Controller\Admin\HookController::toggleActivationAction + + + + Thelia\Controller\Admin\HookController::toggleNativeAction + + + + Thelia\Controller\Admin\ModuleHookController::indexAction + + + + Thelia\Controller\Admin\ModuleHookController::createAction + + + + Thelia\Controller\Admin\ModuleHookController::updateAction + \d+ + + + + Thelia\Controller\Admin\ModuleHookController::processUpdateAction + \d+ + + + + Thelia\Controller\Admin\ModuleHookController::deleteAction + + + + Thelia\Controller\Admin\ModuleHookController::toggleActivationAction + \d+ + + + + Thelia\Controller\Admin\ModuleHookController::updatePositionAction + + + + Thelia\Controller\Admin\ModuleHookController::getModuleHookClassnames + + + + Thelia\Controller\Admin\ModuleHookController::getModuleHookMethods + + + + + + + + Thelia\Controller\Admin\TaxController::updateAction + \d+ + + + + Thelia\Controller\Admin\TaxController::createAction + + + + Thelia\Controller\Admin\TaxController::processUpdateAction + + + + Thelia\Controller\Admin\TaxController::deleteAction + + + + + + + + Thelia\Controller\Admin\TaxRuleController::defaultAction + + + + Thelia\Controller\Admin\TaxRuleController::updateAction + \d+ + + + + Thelia\Controller\Admin\TaxRuleController::createAction + + + + Thelia\Controller\Admin\TaxRuleController::processUpdateAction + + + + Thelia\Controller\Admin\TaxRuleController::processUpdateTaxesAction + + + + Thelia\Controller\Admin\TaxRuleController::deleteAction + + + + Thelia\Controller\Admin\TaxRuleController::setDefaultAction + \d+ + + + + Thelia\Controller\Admin\TaxRuleController::specsAction + \d+ + + + + + + + + Thelia\Controller\Admin\LangController::defaultAction + + + + Thelia\Controller\Admin\LangController::updateAction + \d+ + + + + Thelia\Controller\Admin\LangController::processUpdateAction + \d+ + + + + Thelia\Controller\Admin\LangController::toggleDefaultAction + \d+ + + + + Thelia\Controller\Admin\LangController::toggleActiveAction + \d+ + + + + Thelia\Controller\Admin\LangController::toggleVisibleAction + \d+ + + + + Thelia\Controller\Admin\LangController::addAction + + + + Thelia\Controller\Admin\LangController::deleteAction + + + + Thelia\Controller\Admin\LangController::defaultBehaviorAction + + + + Thelia\Controller\Admin\LangController::domainAction + + + + Thelia\Controller\Admin\LangController::activateDomainAction + + + + Thelia\Controller\Admin\LangController::deactivateDomainAction + + + + + + Thelia\Controller\Admin\TranslationsController::defaultAction + + + + Thelia\Controller\Admin\TranslationsController::updateAction + + + + + + Thelia\Controller\Admin\BrandController::defaultAction + + + + Thelia\Controller\Admin\BrandController::createAction + + + + Thelia\Controller\Admin\BrandController::updateAction + \d+ + + + + Thelia\Controller\Admin\BrandController::processUpdateAction + \d+ + + + + Thelia\Controller\Admin\BrandController::processUpdateSeoAction + + + + Thelia\Controller\Admin\BrandController::setToggleVisibilityAction + + + + Thelia\Controller\Admin\BrandController::updatePositionAction + + + + Thelia\Controller\Admin\BrandController::deleteAction + + + + + + Thelia:Admin\Export:index + + + + Thelia:Admin\Export:changeExportPosition + + + + Thelia:Admin\Export:changeCategoryPosition + + + + Thelia:Admin\Export:configure + + \d+ + + + + Thelia:Admin\Export:export + + \d+ + + + + + + Thelia:Admin\Import:index + + + + Thelia:Admin\Import:changeImportPosition + + + + Thelia:Admin\Import:changeCategoryPosition + + + + Thelia:Admin\Import:configure + + \d+ + + + + Thelia:Admin\Import:import + + \d+ + + + + + + Thelia\Controller\Admin\SaleController::defaultAction + + + + Thelia\Controller\Admin\SaleController::resetSaleStatus + + + + Thelia\Controller\Admin\SaleController::checkSalesActivationStatus + + + + Thelia\Controller\Admin\SaleController::createAction + + + + Thelia\Controller\Admin\SaleController::updateAction + \d+ + + + + Thelia\Controller\Admin\SaleController::processUpdateAction + \d+ + + + + Thelia\Controller\Admin\SaleController::deleteAction + + + + Thelia\Controller\Admin\SaleController::updateProductList + \d+ + + + + Thelia\Controller\Admin\SaleController::updateProductAttributes + \d+ + \d+ + + + + Thelia\Controller\Admin\SaleController::toggleActivity + \d+ + + + + + Thelia:Admin\Message:previewAsHtml + \d+ + + + + Thelia:Admin\Message:previewAsText + \d+ + + + + Thelia:Admin\Message:sendSampleByEmail + \d+ + + + + + + Thelia\Controller\Admin\AdminController::processTemplateAction + .* + + + diff --git a/core/lib/Thelia/Config/Resources/routing/api.xml b/core/lib/Thelia/Config/Resources/routing/api.xml new file mode 100644 index 00000000..2d3efb49 --- /dev/null +++ b/core/lib/Thelia/Config/Resources/routing/api.xml @@ -0,0 +1,279 @@ + + + + + + Thelia:Api\Index:index + 1 + + + + + Thelia:Api\Customer:list + + + + Thelia:Api\Customer:get + \d+ + + + + Thelia:Api\Customer:create + + + + Thelia:Api\Customer:update + + + + Thelia:Api\Customer:delete + \d+ + + + + Thelia:Api\Customer:checkLogin + + + + + + Thelia:Api\Title:list + + + + Thelia:Api\Title:create + + + + Thelia:Api\Title:update + + + + Thelia:Api\Title:get + \d+ + + + + Thelia:Api\Title:delete + \d+ + + + + + + Thelia:Api\Product:list + + + + Thelia:Api\Product:getProduct + \d+ + + + + Thelia:Api\Product:update + \d+ + + + + Thelia:Api\Product:create + + + + Thelia:Api\Product:delete + \d+ + + + + + + Thelia:Api\Image:list + Product + \d+ + + + + Thelia:Api\Image:getImage + Product + \d+ + \d+ + + + + Thelia:Api\Image:updateImage + Product + \d+ + \d+ + + + + Thelia:Api\Image:deleteImage + Product + \d+ + \d+ + + + + Thelia:Api\Image:createImage + Product + \d+ + + + + + + + Thelia:Api\ProductSaleElements:list + \d+ + + + + Thelia:Api\ProductSaleElements:getPse + \d+ + + + + Thelia:Api\ProductSaleElements:delete + \d+ + + + + Thelia:Api\ProductSaleElements:create + \d+ + + + + Thelia:Api\ProductSaleElements:update + \d+ + + + + + + + Thelia:Api\Category:list + + + + Thelia:Api\Category:get + \d+ + + + + Thelia:Api\Category:create + + + + Thelia:Api\Category:update + + + + Thelia:Api\Category:delete + \d+ + + + + + + + Thelia:Api\TaxRule:list + + + + Thelia:Api\TaxRule:get + \d+ + + + + Thelia:Api\TaxRule:create + + + + Thelia:Api\TaxRule:update + + + + Thelia:Api\TaxRule:delete + \d+ + + + + + + + Thelia:Api\AttributeAv:list + + + + Thelia:Api\AttributeAv:get + \d+ + + + + + + + + Thelia:Api\Country:list + + + + Thelia:Api\Country:get + \d+ + + + + + + + + Thelia:Api\Tax:list + + + + Thelia:Api\Tax:get + \d+ + + + + + + + + Thelia:Api\Lang:list + + + + Thelia:Api\Lang:get + \d+ + + + + + + + + Thelia:Api\Brand:list + + + + Thelia:Api\Brand:get + \d+ + + + + + + + + Thelia:Api\Currency:list + + + + Thelia:Api\Currency:get + \d+ + + + + diff --git a/core/lib/Thelia/Config/Resources/stack.xml b/core/lib/Thelia/Config/Resources/stack.xml new file mode 100644 index 00000000..800cd91c --- /dev/null +++ b/core/lib/Thelia/Config/Resources/stack.xml @@ -0,0 +1,24 @@ + + + + + + + + %kernel.cache_dir% + %kernel.debug% + %kernel.environment% + + + + + + + + + + + + diff --git a/core/lib/Thelia/Config/Resources/test.xml b/core/lib/Thelia/Config/Resources/test.xml new file mode 100644 index 00000000..a8008a84 --- /dev/null +++ b/core/lib/Thelia/Config/Resources/test.xml @@ -0,0 +1,28 @@ + + + + + + Thelia\Core\HttpKernel\Client + + Symfony\Component\BrowserKit\History + Symfony\Component\BrowserKit\CookieJar + + + + + + %test.client.parameters% + + + + + + + + + + + diff --git a/core/lib/Thelia/Config/Resources/translation.xml b/core/lib/Thelia/Config/Resources/translation.xml new file mode 100644 index 00000000..45046a98 --- /dev/null +++ b/core/lib/Thelia/Config/Resources/translation.xml @@ -0,0 +1,68 @@ + + + + + + Symfony\Component\Translation\Loader\PhpFileLoader + Symfony\Component\Translation\Loader\YamlFileLoader + Symfony\Component\Translation\Loader\XliffFileLoader + Symfony\Component\Translation\Loader\PoFileLoader + Symfony\Component\Translation\Loader\MoFileLoader + Symfony\Component\Translation\Loader\QtFileLoader + Symfony\Component\Translation\Loader\CsvFileLoader + Symfony\Component\Translation\Loader\IcuResFileLoader + Symfony\Component\Translation\Loader\IcuDatFileLoader + Symfony\Component\Translation\Loader\IniFileLoader + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/core/lib/Thelia/Controller/Admin/AbstractCrudController.php b/core/lib/Thelia/Controller/Admin/AbstractCrudController.php new file mode 100644 index 00000000..01fe0ece --- /dev/null +++ b/core/lib/Thelia/Controller/Admin/AbstractCrudController.php @@ -0,0 +1,676 @@ + + */ +abstract class AbstractCrudController extends BaseAdminController +{ + protected $objectName; + + // List ordering + protected $defaultListOrder; + protected $orderRequestParameterName; + + // Permissions + protected $resourceCode; + protected $moduleCode; + + // Events + protected $createEventIdentifier; + protected $updateEventIdentifier; + protected $deleteEventIdentifier; + protected $visibilityToggleEventIdentifier; + protected $changePositionEventIdentifier; + + /** + * @param string $objectName the lower case object name. Example. "message" + * + * @param string $defaultListOrder the default object list order, or null if list is not sortable. Example: manual + * @param string $orderRequestParameterName Name of the request parameter that set the list order (null if list is not sortable) + * + * @param string $resourceCode the 'resource' code. Example: "admin.configuration.message" + * + * @param string $createEventIdentifier the dispatched create TheliaEvent identifier. Example: TheliaEvents::MESSAGE_CREATE + * @param string $updateEventIdentifier the dispatched update TheliaEvent identifier. Example: TheliaEvents::MESSAGE_UPDATE + * @param string $deleteEventIdentifier the dispatched delete TheliaEvent identifier. Example: TheliaEvents::MESSAGE_DELETE + * + * @param string $visibilityToggleEventIdentifier the dispatched visibility toggle TheliaEvent identifier, or null if the object has no visible options. Example: TheliaEvents::MESSAGE_TOGGLE_VISIBILITY + * @param string $changePositionEventIdentifier the dispatched position change TheliaEvent identifier, or null if the object has no position. Example: TheliaEvents::MESSAGE_UPDATE_POSITION + * @param string $moduleCode The module code for ACL + */ + public function __construct( + $objectName, + $defaultListOrder, + $orderRequestParameterName, + $resourceCode, + $createEventIdentifier, + $updateEventIdentifier, + $deleteEventIdentifier, + $visibilityToggleEventIdentifier = null, + $changePositionEventIdentifier = null, + $moduleCode = null + ) { + $this->objectName = $objectName; + + $this->defaultListOrder = $defaultListOrder; + $this->orderRequestParameterName = $orderRequestParameterName; + + $this->resourceCode = $resourceCode; + + $this->createEventIdentifier = $createEventIdentifier; + $this->updateEventIdentifier = $updateEventIdentifier; + $this->deleteEventIdentifier = $deleteEventIdentifier; + $this->visibilityToggleEventIdentifier = $visibilityToggleEventIdentifier; + $this->changePositionEventIdentifier = $changePositionEventIdentifier; + + $this->moduleCode = $moduleCode; + } + + /** + * Return the creation form for this object + * @return BaseForm + */ + abstract protected function getCreationForm(); + + /** + * Return the update form for this object + * @return BaseForm + */ + abstract protected function getUpdateForm(); + + /** + * Hydrate the update form for this object, before passing it to the update template + * + * @param mixed $object + * @return BaseForm + */ + abstract protected function hydrateObjectForm($object); + + /** + * Creates the creation event with the provided form data + * + * @param mixed $formData + * @return \Thelia\Core\Event\ActionEvent + */ + abstract protected function getCreationEvent($formData); + + /** + * Creates the update event with the provided form data + * + * @param mixed $formData + * @return \Thelia\Core\Event\ActionEvent + */ + abstract protected function getUpdateEvent($formData); + + /** + * Creates the delete event with the provided form data + * @return \Thelia\Core\Event\ActionEvent + */ + abstract protected function getDeleteEvent(); + + /** + * Return true if the event contains the object, e.g. the action has updated the object in the event. + * + * @param mixed $event + */ + abstract protected function eventContainsObject($event); + + /** + * Get the created object from an event. + * + * @param mixed $event + */ + abstract protected function getObjectFromEvent($event); + + /** + * Load an existing object from the database + */ + abstract protected function getExistingObject(); + + /** + * Returns the object label form the object event (name, title, etc.) + * + * @param string|null $object + */ + abstract protected function getObjectLabel($object); + + /** + * Returns the object ID from the object + * + * @param int|null $object + */ + abstract protected function getObjectId($object); + + /** + * Render the main list template + * + * @param mixed $currentOrder, if any, null otherwise. + * @return \Thelia\Core\HttpFoundation\Response + */ + abstract protected function renderListTemplate($currentOrder); + + /** + * Render the edition template + * @return \Thelia\Core\HttpFoundation\Response + */ + abstract protected function renderEditionTemplate(); + + /** + * Must return a RedirectResponse instance + * @return \Symfony\Component\HttpFoundation\RedirectResponse + */ + abstract protected function redirectToEditionTemplate(); + + /** + * Must return a RedirectResponse instance + * @return \Symfony\Component\HttpFoundation\RedirectResponse + */ + abstract protected function redirectToListTemplate(); + + /** + * @param $positionChangeMode + * @param $positionValue + * @return ActionEvent + */ + protected function createUpdatePositionEvent($positionChangeMode, $positionValue) + { + throw new \LogicException("Position Update is not supported for this object"); + } + + /** + * @return ActionEvent + */ + protected function createToggleVisibilityEvent() + { + throw new \LogicException("Toggle Visibility is not supported for this object"); + } + + /** + * Put in this method post object creation processing if required. + * + * @param ActionEvent $createEvent the create event + * @return Response a response, or null to continue normal processing + */ + protected function performAdditionalCreateAction($createEvent) + { + return null; + } + + /** + * Put in this method post object update processing if required. + * + * @param ActionEvent $updateEvent the update event + * @return Response a response, or null to continue normal processing + */ + protected function performAdditionalUpdateAction($updateEvent) + { + return null; + } + + /** + * Put in this method post object delete processing if required. + * + * @param ActionEvent $deleteEvent the delete event + * @return Response a response, or null to continue normal processing + */ + protected function performAdditionalDeleteAction($deleteEvent) + { + return null; + } + + /** + * Put in this method post object position change processing if required. + * + * @param ActionEvent $positionChangeEvent the delete event + * @return Response|null a response, or null to continue normal processing + */ + protected function performAdditionalUpdatePositionAction($positionChangeEvent) + { + return null; + } + + /** + * Return the current list order identifier, updating it in the same time. + */ + protected function getCurrentListOrder($update_session = true) + { + return $this->getListOrderFromSession( + $this->objectName, + $this->orderRequestParameterName, + $this->defaultListOrder + ); + } + + protected function getModuleCode() + { + if (null !== $this->moduleCode) { + return [$this->moduleCode]; + } else { + return []; + } + } + + /** + * Render the object list, ensuring the sort order is set. + * + * @return \Thelia\Core\HttpFoundation\Response the response + */ + protected function renderList() + { + return $this->renderListTemplate($this->getCurrentListOrder()); + } + + /** + * The default action is displaying the list. + * + * @return \Thelia\Core\HttpFoundation\Response the response + */ + public function defaultAction() + { + // Check current user authorization + if (null !== $response = $this->checkAuth($this->resourceCode, $this->getModuleCode(), AccessManager::VIEW)) { + return $response; + } + + return $this->renderList(); + } + + /** + * Create a new object + * + * @return \Thelia\Core\HttpFoundation\Response the response + */ + public function createAction() + { + // Check current user authorization + if (null !== $response = $this->checkAuth($this->resourceCode, $this->getModuleCode(), AccessManager::CREATE)) { + return $response; + } + + // Error (Default: false) + $error_msg = false; + + // Create the Creation Form + $creationForm = $this->getCreationForm($this->getRequest()); + + try { + // Check the form against constraints violations + $form = $this->validateForm($creationForm, "POST"); + + // Get the form field values + $data = $form->getData(); + + // Create a new event object with the modified fields + $createEvent = $this->getCreationEvent($data); + $createEvent->bindForm($form); + + // Dispatch Create Event + $this->dispatch($this->createEventIdentifier, $createEvent); + + // Check if object exist + if (! $this->eventContainsObject($createEvent)) { + throw new \LogicException( + $this->getTranslator()->trans("No %obj was created.", ['%obj' => $this->objectName]) + ); + } + + // Log object creation + if (null !== $createdObject = $this->getObjectFromEvent($createEvent)) { + $this->adminLogAppend( + $this->resourceCode, + AccessManager::CREATE, + sprintf( + "%s %s (ID %s) created", + ucfirst($this->objectName), + $this->getObjectLabel($createdObject), + $this->getObjectId($createdObject) + ), + $this->getObjectId($createdObject) + ); + } + + // Execute additional Action + $response = $this->performAdditionalCreateAction($createEvent); + + if ($response == null) { + // Substitute _ID_ in the URL with the ID of the created object + $successUrl = str_replace('_ID_', $this->getObjectId($createdObject), $creationForm->getSuccessUrl()); + + // Redirect to the success URL + return $this->generateRedirect($successUrl); + } else { + return $response; + } + } catch (FormValidationException $ex) { + // Form cannot be validated + $error_msg = $this->createStandardFormValidationErrorMessage($ex); + } catch (\Exception $ex) { + // Any other error + $error_msg = $ex->getMessage(); + } + + if (false !== $error_msg) { + $this->setupFormErrorContext( + $this->getTranslator()->trans("%obj creation", ['%obj' => $this->objectName]), + $error_msg, + $creationForm, + $ex + ); + + // At this point, the form has error, and should be redisplayed. + return $this->renderList(); + } + } + + /** + * Load a object for modification, and display the edit template. + * + * @return \Thelia\Core\HttpFoundation\Response the response + */ + public function updateAction() + { + // Check current user authorization + if (null !== $response = $this->checkAuth($this->resourceCode, $this->getModuleCode(), AccessManager::UPDATE)) { + return $response; + } + + // Load object if exist + if (null !== $object = $this->getExistingObject()) { + // Hydrate the form abd pass it to the parser + $changeForm = $this->hydrateObjectForm($object); + + // Pass it to the parser + $this->getParserContext()->addForm($changeForm); + } + + // Render the edition template. + return $this->renderEditionTemplate(); + } + + /** + * Save changes on a modified object, and either go back to the object list, or stay on the edition page. + * + * @return \Thelia\Core\HttpFoundation\Response the response + */ + public function processUpdateAction() + { + // Check current user authorization + if (null !== $response = $this->checkAuth($this->resourceCode, $this->getModuleCode(), AccessManager::UPDATE)) { + return $response; + } + + // Error (Default: false) + $error_msg = false; + + // Create the Form from the request + $changeForm = $this->getUpdateForm($this->getRequest()); + + try { + // Check the form against constraints violations + $form = $this->validateForm($changeForm, "POST"); + + // Get the form field values + $data = $form->getData(); + + // Create a new event object with the modified fields + $changeEvent = $this->getUpdateEvent($data); + $changeEvent->bindForm($form); + + // Dispatch Update Event + $this->dispatch($this->updateEventIdentifier, $changeEvent); + + // Check if object exist + if (! $this->eventContainsObject($changeEvent)) { + throw new \LogicException( + $this->getTranslator()->trans("No %obj was updated.", ['%obj' => $this->objectName]) + ); + } + + // Log object modification + if (null !== $changedObject = $this->getObjectFromEvent($changeEvent)) { + $this->adminLogAppend( + $this->resourceCode, + AccessManager::UPDATE, + sprintf( + "%s %s (ID %s) modified", + ucfirst($this->objectName), + $this->getObjectLabel($changedObject), + $this->getObjectId($changedObject) + ), + $this->getObjectId($changedObject) + ); + } + + // Execute additional Action + $response = $this->performAdditionalUpdateAction($changeEvent); + + if ($response == null) { + // If we have to stay on the same page, do not redirect to the successUrl, + // just redirect to the edit page again. + if ($this->getRequest()->get('save_mode') == 'stay') { + return $this->redirectToEditionTemplate($this->getRequest()); + } + + // Redirect to the success URL + return $this->generateSuccessRedirect($changeForm); + } else { + return $response; + } + } catch (FormValidationException $ex) { + // Form cannot be validated + $error_msg = $this->createStandardFormValidationErrorMessage($ex); + } catch (\Exception $ex) { + // Any other error + $error_msg = $ex->getMessage(); + } + + if (false !== $error_msg) { + // At this point, the form has errors, and should be redisplayed. + $this->setupFormErrorContext( + $this->getTranslator()->trans("%obj modification", ['%obj' => $this->objectName]), + $error_msg, + $changeForm, + $ex + ); + + return $this->renderEditionTemplate(); + } + } + + /** + * Update object position (only for objects whichsupport that) + * + */ + public function updatePositionAction() + { + // Check current user authorization + if (null !== $response = $this->checkAuth($this->resourceCode, $this->getModuleCode(), AccessManager::UPDATE)) { + return $response; + } + + try { + $mode = $this->getRequest()->get('mode', null); + + if ($mode == 'up') { + $mode = UpdatePositionEvent::POSITION_UP; + } elseif ($mode == 'down') { + $mode = UpdatePositionEvent::POSITION_DOWN; + } else { + $mode = UpdatePositionEvent::POSITION_ABSOLUTE; + } + + $position = $this->getRequest()->get('position', null); + + $event = $this->createUpdatePositionEvent($mode, $position); + + $this->dispatch($this->changePositionEventIdentifier, $event); + } catch (\Exception $ex) { + // Any error + return $this->errorPage($ex); + } + + $response = $this->performAdditionalUpdatePositionAction($event); + + if ($response == null) { + return $this->redirectToListTemplate(); + } else { + return $response; + } + } + + protected function genericUpdatePositionAction($object, $eventName, $doFinalRedirect = true) + { + // Check current user authorization + if (null !== $response = $this->checkAuth($this->resourceCode, $this->getModuleCode(), AccessManager::UPDATE)) { + return $response; + } + + if ($object != null) { + try { + $mode = $this->getRequest()->get('mode', null); + + if ($mode == 'up') { + $mode = UpdatePositionEvent::POSITION_UP; + } elseif ($mode == 'down') { + $mode = UpdatePositionEvent::POSITION_DOWN; + } else { + $mode = UpdatePositionEvent::POSITION_ABSOLUTE; + } + + $position = $this->getRequest()->get('position', null); + + $event = new UpdatePositionEvent($object->getId(), $mode, $position); + + $this->dispatch($eventName, $event); + } catch (\Exception $ex) { + // Any error + return $this->errorPage($ex); + } + } + + if ($doFinalRedirect) { + return $this->redirectToEditionTemplate(); + } + } + + /** + * Online status toggle (only for object which support it) + */ + public function setToggleVisibilityAction() + { + // Check current user authorization + if (null !== $response = $this->checkAuth($this->resourceCode, $this->getModuleCode(), AccessManager::UPDATE)) { + return $response; + } + + $changeEvent = $this->createToggleVisibilityEvent($this->getRequest()); + + try { + $this->dispatch($this->visibilityToggleEventIdentifier, $changeEvent); + } catch (\Exception $ex) { + // Any error + return $this->errorPage($ex); + } + + return $this->nullResponse(); + } + + /** + * Delete an object + * + * @return \Thelia\Core\HttpFoundation\Response the response + */ + public function deleteAction() + { + // Check current user authorization + if (null !== $response = $this->checkAuth($this->resourceCode, $this->getModuleCode(), AccessManager::DELETE)) { + return $response; + } + + try { + // Check token + $this->getTokenProvider()->checkToken( + $this->getRequest()->query->get("_token") + ); + + // Get the currency id, and dispatch the delete request + $deleteEvent = $this->getDeleteEvent(); + + $this->dispatch($this->deleteEventIdentifier, $deleteEvent); + + if (null !== $deletedObject = $this->getObjectFromEvent($deleteEvent)) { + $this->adminLogAppend( + $this->resourceCode, + AccessManager::DELETE, + sprintf( + "%s %s (ID %s) deleted", + ucfirst($this->objectName), + $this->getObjectLabel($deletedObject), + $this->getObjectId($deletedObject) + ), + $this->getObjectId($deletedObject) + ); + } + + $response = $this->performAdditionalDeleteAction($deleteEvent); + + if ($response == null) { + return $this->redirectToListTemplate(); + } else { + return $response; + } + } catch (\Exception $e) { + return $this->renderAfterDeleteError($e); + } + } + + /** + * @param \Exception $e + * @return \Thelia\Core\HttpFoundation\Response + */ + protected function renderAfterDeleteError(\Exception $e) + { + $errorMessage = sprintf( + "Unable to delete '%s'. Error message: %s", + $this->objectName, + $e->getMessage() + ); + + $this->getParserContext() + ->setGeneralError($errorMessage) + ; + + return $this->defaultAction(); + } + + /** + * @return \Thelia\Core\HttpFoundation\Request + * @since 2.3 + */ + protected function getRequest() + { + return $this->container->get('request_stack')->getCurrentRequest(); + } +} diff --git a/core/lib/Thelia/Controller/Admin/AbstractSeoCrudController.php b/core/lib/Thelia/Controller/Admin/AbstractSeoCrudController.php new file mode 100644 index 00000000..5291871f --- /dev/null +++ b/core/lib/Thelia/Controller/Admin/AbstractSeoCrudController.php @@ -0,0 +1,222 @@ + + */ +abstract class AbstractSeoCrudController extends AbstractCrudController +{ + // Events + protected $updateSeoEventIdentifier; + + /** + * @param string $objectName the lower case object name. Example. "message" + * + * @param string $defaultListOrder the default object list order, or null if list is not sortable. Example: manual + * @param string $orderRequestParameterName Name of the request parameter that set the list order (null if list is not sortable) + * + * @param string $resourceCode the 'resource' code. Example: "admin.configuration.message" + * + * @param string $createEventIdentifier the dispatched create TheliaEvent identifier. Example: TheliaEvents::MESSAGE_CREATE + * @param string $updateEventIdentifier the dispatched update TheliaEvent identifier. Example: TheliaEvents::MESSAGE_UPDATE + * @param string $deleteEventIdentifier the dispatched delete TheliaEvent identifier. Example: TheliaEvents::MESSAGE_DELETE + * + * @param string $visibilityToggleEventIdentifier the dispatched visibility toggle TheliaEvent identifier, or null if the object has no visible options. Example: TheliaEvents::MESSAGE_TOGGLE_VISIBILITY + * @param string $changePositionEventIdentifier the dispatched position change TheliaEvent identifier, or null if the object has no position. Example: TheliaEvents::MESSAGE_UPDATE_POSITION + * @param string $updateSeoEventIdentifier the dispatched update SEO change TheliaEvent identifier, or null if the object has no SEO. Example: TheliaEvents::MESSAGE_UPDATE_SEO + * @param string $moduleCode The module code for ACL + */ + public function __construct( + $objectName, + $defaultListOrder, + $orderRequestParameterName, + $resourceCode, + $createEventIdentifier, + $updateEventIdentifier, + $deleteEventIdentifier, + $visibilityToggleEventIdentifier = null, + $changePositionEventIdentifier = null, + $updateSeoEventIdentifier = null, + $moduleCode = null + ) { + parent::__construct( + $objectName, + $defaultListOrder, + $orderRequestParameterName, + $resourceCode, + $createEventIdentifier, + $updateEventIdentifier, + $deleteEventIdentifier, + $visibilityToggleEventIdentifier, + $changePositionEventIdentifier, + $moduleCode + ); + + $this->updateSeoEventIdentifier = $updateSeoEventIdentifier; + } + + /** + * Put in this method post object update SEO processing if required. + * + * @param UpdateSeoEvent $updateSeoEvent the update event + * @return null|Response a response, or null to continue normal processing + */ + protected function performAdditionalUpdateSeoAction($updateSeoEvent) + { + return null; + } + + /** + * Return the update SEO form for this object + */ + protected function getUpdateSeoForm() + { + return $this->createForm(AdminForm::SEO); + } + + /** + * Creates the update SEO event with the provided form data + * + * @param $formData + * @return UpdateSeoEvent + */ + protected function getUpdateSeoEvent($formData) + { + $updateSeoEvent = new UpdateSeoEvent($formData['id']); + + $updateSeoEvent + ->setLocale($formData['locale']) + ->setMetaTitle($formData['meta_title']) + ->setMetaDescription($formData['meta_description']) + ->setMetaKeywords($formData['meta_keywords']) + ->setUrl($formData['url']) + ; + + // Create and dispatch the change event + return $updateSeoEvent; + } + + /** + * Hydrate the SEO form for this object, before passing it to the update template + * + * @param mixed $object + */ + protected function hydrateSeoForm($object) + { + // The "SEO" tab form + $locale = $object->getLocale(); + $data = array( + 'id' => $object->getId(), + 'locale' => $locale, + 'url' => $object->getRewrittenUrl($locale), + 'meta_title' => $object->getMetaTitle(), + 'meta_description' => $object->getMetaDescription(), + 'meta_keywords' => $object->getMetaKeywords() + ); + + $seoForm = $this->createForm(AdminForm::SEO, "form", $data); + $this->getParserContext()->addForm($seoForm); + + // URL based on the language + $this->getParserContext()->set('url_language', $this->getUrlLanguage($locale)); + } + + /** + * Update SEO modification, and either go back to the object list, or stay on the edition page. + * + * @return \Thelia\Core\HttpFoundation\Response the response + */ + public function processUpdateSeoAction() + { + // Check current user authorization + if (null !== $response = $this->checkAuth($this->resourceCode, $this->getModuleCode(), AccessManager::UPDATE)) { + return $response; + } + + // Error (Default: false) + $error_msg = false; + + // Create the Form from the request + $updateSeoForm = $this->getUpdateSeoForm($this->getRequest()); + + // Pass the object id to the request + $this->getRequest()->attributes->set($this->objectName . '_id', $this->getRequest()->get('current_id')); + + try { + // Check the form against constraints violations + $form = $this->validateForm($updateSeoForm, "POST"); + + // Get the form field values + $data = $form->getData(); + + // Create a new event object with the modified fields + $updateSeoEvent = $this->getUpdateSeoEvent($data); + + // Dispatch Update SEO Event + $this->dispatch($this->updateSeoEventIdentifier, $updateSeoEvent); + + // Execute additional Action + $response = $this->performAdditionalUpdateSeoAction($updateSeoEvent); + + if ($response == null) { + // If we have to stay on the same page, do not redirect to the successUrl, + // just redirect to the edit page again. + if ($this->getRequest()->get('save_mode') == 'stay') { + return $this->redirectToEditionTemplate($this->getRequest()); + } + + // Redirect to the success URL + return $this->generateSuccessRedirect($updateSeoForm); + } else { + return $response; + } + } catch (FormValidationException $ex) { + // Form cannot be validated + $error_msg = $this->createStandardFormValidationErrorMessage($ex); + /*} catch (\Exception $ex) { + // Any other error + $error_msg = $ex->getMessage();*/ + } + + // Load object if exist + if (null !== $object = $this->getExistingObject()) { + // Hydrate the form abd pass it to the parser + $changeForm = $this->hydrateObjectForm($object); + + // Pass it to the parser + $this->getParserContext()->addForm($changeForm); + } + + if (false !== $error_msg) { + $this->setupFormErrorContext( + $this->getTranslator()->trans("%obj SEO modification", array('%obj' => $this->objectName)), + $error_msg, + $updateSeoForm, + $ex + ); + + // At this point, the form has errors, and should be redisplayed. + return $this->renderEditionTemplate(); + } + } +} diff --git a/core/lib/Thelia/Controller/Admin/AddressController.php b/core/lib/Thelia/Controller/Admin/AddressController.php new file mode 100644 index 00000000..542e5f3b --- /dev/null +++ b/core/lib/Thelia/Controller/Admin/AddressController.php @@ -0,0 +1,322 @@ + + */ +class AddressController extends AbstractCrudController +{ + public function __construct() + { + parent::__construct( + 'registration_date', + null, + null, + AdminResources::ADDRESS, + TheliaEvents::ADDRESS_CREATE, + TheliaEvents::ADDRESS_UPDATE, + TheliaEvents::ADDRESS_DELETE + ); + } + + public function useAddressAction() + { + if (null !== $response = $this->checkAuth($this->resourceCode, array(), AccessManager::UPDATE)) { + return $response; + } + + $address_id = $this->getRequest()->request->get('address_id'); + + try { + $address = AddressQuery::create()->findPk($address_id); + + if (null === $address) { + throw new \InvalidArgumentException(sprintf('%d address does not exists', $address_id)); + } + + $addressEvent = new AddressEvent($address); + + $this->dispatch(TheliaEvents::ADDRESS_DEFAULT, $addressEvent); + + $this->adminLogAppend( + $this->resourceCode, + AccessManager::UPDATE, + sprintf( + "address %d for customer %d set as default address", + $address_id, + $address->getCustomerId() + ), + $address_id + ); + } catch (\Exception $e) { + \Thelia\Log\Tlog::getInstance()->error(sprintf("error during address setting as default with message %s", $e->getMessage())); + } + + return $this->redirectToEditionTemplate(); + } + + /** + * Return the creation form for this object + */ + protected function getCreationForm() + { + return $this->createForm(AdminForm::ADDRESS_CREATE); + } + + /** + * Return the update form for this object + */ + protected function getUpdateForm() + { + return $this->createForm(AdminForm::ADDRESS_UPDATE); + } + + /** + * Fills in the form data array + * + * @param unknown $object + * @return array + */ + protected function createFormDataArray($object) + { + return array( + "label" => $object->getLabel(), + "title" => $object->getTitleId(), + "firstname" => $object->getFirstname(), + "lastname" => $object->getLastname(), + "address1" => $object->getAddress1(), + "address2" => $object->getAddress2(), + "address3" => $object->getAddress3(), + "zipcode" => $object->getZipcode(), + "city" => $object->getCity(), + "country" => $object->getCountryId(), + "state" => $object->getStateId(), + "cellphone" => $object->getCellphone(), + "phone" => $object->getPhone(), + "company" => $object->getCompany() + ); + } + + /** + * Hydrate the update form for this object, before passing it to the update template + * + * @param \Thelia\Model\Address $object + */ + protected function hydrateObjectForm($object) + { + return $this->createForm(AdminForm::ADDRESS_UPDATE, "form", $this->createFormDataArray($object)); + } + + /** + * Creates the creation event with the provided form data + * + * @param unknown $formData + */ + protected function getCreationEvent($formData) + { + $event = $this->getCreateOrUpdateEvent($formData); + + $customer = CustomerQuery::create()->findPk($this->getRequest()->get("customer_id")); + + $event->setCustomer($customer); + + return $event; + } + + /** + * Creates the update event with the provided form data + * + * @param unknown $formData + */ + protected function getUpdateEvent($formData) + { + $event = $this->getCreateOrUpdateEvent($formData); + + $event->setAddress($this->getExistingObject()); + + return $event; + } + + protected function getCreateOrUpdateEvent($formData) + { + $event = new AddressCreateOrUpdateEvent( + $formData["label"], + $formData["title"], + $formData["firstname"], + $formData["lastname"], + $formData["address1"], + $formData["address2"], + $formData["address3"], + $formData["zipcode"], + $formData["city"], + $formData["country"], + $formData["cellphone"], + $formData["phone"], + $formData["company"], + $formData["is_default"], + $formData["state"] + ); + + return $event; + } + + /** + * Creates the delete event with the provided form data + */ + protected function getDeleteEvent() + { + return new AddressEvent($this->getExistingObject()); + } + + /** + * Return true if the event contains the object, e.g. the action has updated the object in the event. + * + * @param unknown $event + */ + protected function eventContainsObject($event) + { + return null !== $event->getAddress(); + } + + /** + * Get the created object from an event. + * + * @param unknown $createEvent + */ + protected function getObjectFromEvent($event) + { + return null; + } + + /** + * Load an existing object from the database + */ + protected function getExistingObject() + { + return AddressQuery::create()->findPk($this->getRequest()->get('address_id')); + } + + /** + * Returns the object label form the object event (name, title, etc.) + * + * @param unknown $object + */ + protected function getObjectLabel($object) + { + return $object->getLabel(); + } + + /** + * Returns the object ID from the object + * + * @param unknown $object + */ + protected function getObjectId($object) + { + return $object->getId(); + } + + /** + * Render the main list template + * + * @param unknown $currentOrder, if any, null otherwise. + */ + protected function renderListTemplate($currentOrder) + { + // We render here the customer edit template. + return $this->renderEditionTemplate(); + } + + /** + * Render the edition template + */ + protected function renderEditionTemplate() + { + return $this->render('customer-edit', array( + "address_id" => $this->getRequest()->get('address_id'), + "page" => $this->getRequest()->get('page'), + "customer_id" => $this->getCustomerId() + )); + } + + /** + * Redirect to the edition template + */ + protected function redirectToEditionTemplate() + { + // We display here the custromer edition template + return $this->generateRedirectFromRoute( + 'admin.customer.update.view', + [ + "page" => $this->getRequest()->get('page'), + "customer_id" => $this->getCustomerId() + ] + ); + } + + /** + * Redirect to the list template + */ + protected function redirectToListTemplate() + { + // TODO: Implement redirectToListTemplate() method. + } + + /** + * Put in this method post object delete processing if required. + * + * @param \Thelia\Core\Event\AddressEvent $deleteEvent the delete event + * @return Response a response, or null to continue normal processing + */ + protected function performAdditionalDeleteAction($deleteEvent) + { + return $this->redirectToEditionTemplate(); + } + + /** + * Put in this method post object creation processing if required. + * + * @param AddressCreateOrUpdateEvent $createEvent the create event + * @return Response a response, or null to continue normal processing + */ + protected function performAdditionalCreateAction($createEvent) + { + return $this->redirectToEditionTemplate(); + } + + protected function performAdditionalUpdateAction($event) + { + return $this->redirectToEditionTemplate(); + } + + protected function getCustomerId() + { + if (null !== $address = $this->getExistingObject()) { + return $address->getCustomerId(); + } else { + return $this->getRequest()->get('customer_id', 0); + } + } +} diff --git a/core/lib/Thelia/Controller/Admin/AdminController.php b/core/lib/Thelia/Controller/Admin/AdminController.php new file mode 100644 index 00000000..c4567b97 --- /dev/null +++ b/core/lib/Thelia/Controller/Admin/AdminController.php @@ -0,0 +1,33 @@ +getSecurityContext()->hasAdminUser()) { + return new RedirectResponse(URL::getInstance()->absoluteUrl($this->getRoute("admin.login"))); + } + + return $this->render("home"); + } + + public function updateAction() + { + return $this->render("profile-edit"); + } +} diff --git a/core/lib/Thelia/Controller/Admin/AdminLogsController.php b/core/lib/Thelia/Controller/Admin/AdminLogsController.php new file mode 100644 index 00000000..54200512 --- /dev/null +++ b/core/lib/Thelia/Controller/Admin/AdminLogsController.php @@ -0,0 +1,64 @@ +checkAuth(AdminResources::ADMIN_LOG, array(), AccessManager::VIEW)) { + return $response; + } + + // Render the edition template. + return $this->render('admin-logs'); + } + + public function loadLoggerAjaxAction() + { + $entries = array(); + + /** @var AdminLog $entry */ + foreach (AdminLogQuery::getEntries( + $this->getRequest()->request->get('admins', array()), + $this->getRequest()->request->get('fromDate', null), + $this->getRequest()->request->get('toDate', null), + array_merge($this->getRequest()->request->get('resources', array()), $this->getRequest()->request->get('modules', array())), + null + ) as $entry) { + $entries[] = array( + "head" => sprintf( + "%s|%s|%s:%s%s", + date('Y-m-d H:i:s', $entry->getCreatedAt()->getTimestamp()), + $entry->getAdminLogin(), + $entry->getResource(), + $entry->getAction(), + (null !== $entry->getResourceId()) ? ":" . $entry->getResourceId() : "" + ), + "data" => $entry->getMessage(), + ); + } + + return $this->render( + 'ajax/logger', + array( + 'entries' => $entries, + ) + ); + } +} diff --git a/core/lib/Thelia/Controller/Admin/AdministratorController.php b/core/lib/Thelia/Controller/Admin/AdministratorController.php new file mode 100644 index 00000000..d650c3dd --- /dev/null +++ b/core/lib/Thelia/Controller/Admin/AdministratorController.php @@ -0,0 +1,201 @@ +render('administrators', [ 'show_update_dialog' => true ]); + } + + public function setEmailAction() + { + // Open the update dialog for the current administrator, and display the "set email address" notice. + return $this->render( + 'administrators', + [ + 'show_update_dialog' => true, + 'show_email_change_notice' => true + ] + ); + } + + protected function getCreationForm() + { + return $this->createForm(AdminForm::ADMINISTRATOR_CREATION); + } + + protected function getUpdateForm() + { + return $this->createForm(AdminForm::ADMINISTRATOR_MODIFICATION); + } + + protected function getCreationEvent($formData) + { + $event = new AdministratorEvent(); + + $event->setLogin($formData['login']); + $event->setFirstname($formData['firstname']); + $event->setLastname($formData['lastname']); + $event->setPassword($formData['password']); + $event->setProfile($formData['profile'] ? : null); + $event->setLocale($formData['locale']); + $event->setEmail($formData['email']); + + return $event; + } + + protected function getUpdateEvent($formData) + { + $event = new AdministratorEvent(); + + $event->setId($formData['id']); + $event->setLogin($formData['login']); + $event->setFirstname($formData['firstname']); + $event->setLastname($formData['lastname']); + $event->setPassword($formData['password']); + $event->setProfile($formData['profile'] ? : null); + $event->setLocale($formData['locale']); + $event->setEmail($formData['email']); + + return $event; + } + + protected function getDeleteEvent() + { + $event = new AdministratorEvent(); + + $event->setId( + $this->getRequest()->get('administrator_id', 0) + ); + + return $event; + } + + protected function eventContainsObject($event) + { + return $event->hasAdministrator(); + } + + /** + * @param Admin $object + * + * @return \Thelia\Form\BaseForm + */ + protected function hydrateObjectForm($object) + { + $data = array( + 'id' => $object->getId(), + 'firstname' => $object->getFirstname(), + 'lastname' => $object->getLastname(), + 'login' => $object->getLogin(), + 'profile' => $object->getProfileId(), + 'locale' => $object->getLocale(), + 'email' => $object->getEmail() + ); + + // Setup the object form + return $this->createForm(AdminForm::ADMINISTRATOR_MODIFICATION, "form", $data); + } + + protected function getObjectFromEvent($event) + { + return $event->hasAdministrator() ? $event->getAdministrator() : null; + } + + protected function getExistingObject() + { + return AdminQuery::create() + ->findOneById($this->getRequest()->get('administrator_id')); + } + + /** + * @param Admin $object + * @return string + */ + protected function getObjectLabel($object) + { + return $object->getLogin(); + } + + /** + * @param Admin $object + * @return int + */ + protected function getObjectId($object) + { + return $object->getId(); + } + + protected function renderListTemplate($currentOrder) + { + // We always return to the feature edition form + return $this->render( + 'administrators', + array() + ); + } + + protected function renderEditionTemplate() + { + // We always return to the feature edition form + return $this->render('administrators'); + } + + protected function redirectToEditionTemplate() + { + // We always return to the feature edition form + return $this->redirectToListTemplate(); + } + + protected function performAdditionalCreateAction($updateEvent) + { + // We always return to the feature edition form + return $this->redirectToListTemplate(); + } + + protected function performAdditionalUpdateAction($updateEvent) + { + // We always return to the feature edition form + return $this->redirectToListTemplate(); + } + + protected function redirectToListTemplate() + { + return $this->generateRedirectFromRoute( + "admin.configuration.administrators.view" + ); + } +} diff --git a/core/lib/Thelia/Controller/Admin/AdvancedConfigurationController.php b/core/lib/Thelia/Controller/Admin/AdvancedConfigurationController.php new file mode 100644 index 00000000..5084f5dc --- /dev/null +++ b/core/lib/Thelia/Controller/Admin/AdvancedConfigurationController.php @@ -0,0 +1,108 @@ + + */ +class AdvancedConfigurationController extends BaseAdminController +{ + public function defaultAction() + { + if (null !== $result = $this->checkAuth(AdminResources::ADVANCED_CONFIGURATION, [], AccessManager::VIEW)) { + return $result; + } + + return $this->render('advanced-configuration'); + } + + public function flushCacheAction() + { + if (null !== $result = $this->checkAuth(AdminResources::ADVANCED_CONFIGURATION, [], AccessManager::UPDATE)) { + return $result; + } + + $form = $this->createForm(AdminForm::CACHE_FLUSH); + try { + $this->validateForm($form); + + $event = new CacheEvent($this->container->getParameter("kernel.cache_dir")); + $this->dispatch(TheliaEvents::CACHE_CLEAR, $event); + } catch (\Exception $e) { + Tlog::getInstance()->addError(sprintf("Flush cache error: %s", $e->getMessage())); + } + + return $this->generateRedirectFromRoute('admin.configuration.advanced'); + } + + public function flushAssetsAction() + { + if (null !== $result = $this->checkAuth(AdminResources::ADVANCED_CONFIGURATION, [], AccessManager::UPDATE)) { + return $result; + } + + $form = $this->createForm(AdminForm::ASSETS_FLUSH); + try { + $this->validateForm($form); + + $event = new CacheEvent(THELIA_WEB_DIR . "assets"); + $this->dispatch(TheliaEvents::CACHE_CLEAR, $event); + } catch (\Exception $e) { + Tlog::getInstance()->addError(sprintf("Flush assets error: %s", $e->getMessage())); + } + + return $this->generateRedirectFromRoute('admin.configuration.advanced'); + } + + public function flushImagesAndDocumentsAction() + { + if (null !== $result = $this->checkAuth(AdminResources::ADVANCED_CONFIGURATION, [], AccessManager::UPDATE)) { + return $result; + } + + $form = $this->createForm(AdminForm::IMAGES_AND_DOCUMENTS_CACHE_FLUSH); + try { + $this->validateForm($form); + + $event = new CacheEvent( + THELIA_WEB_DIR . ConfigQuery::read( + 'image_cache_dir_from_web_root', + 'cache' . DS . 'images' + ) + ); + $this->dispatch(TheliaEvents::CACHE_CLEAR, $event); + + $event = new CacheEvent( + THELIA_WEB_DIR . ConfigQuery::read( + 'document_cache_dir_from_web_root', + 'cache' . DS . 'documents' + ) + ); + $this->dispatch(TheliaEvents::CACHE_CLEAR, $event); + } catch (\Exception $e) { + Tlog::getInstance()->addError(sprintf("Flush images and document error: %s", $e->getMessage())); + } + + return $this->generateRedirectFromRoute('admin.configuration.advanced'); + } +} diff --git a/core/lib/Thelia/Controller/Admin/ApiController.php b/core/lib/Thelia/Controller/Admin/ApiController.php new file mode 100644 index 00000000..1944f580 --- /dev/null +++ b/core/lib/Thelia/Controller/Admin/ApiController.php @@ -0,0 +1,210 @@ + + */ +class ApiController extends BaseAdminController +{ + protected $api; + + public function downloadAction($api_id) + { + if (null === $response = $this->checkApiAccess($api_id, AccessManager::VIEW)) { + $response = $this->retrieveSecureKey($this->api); + } + + return $response; + } + + public function deleteAction() + { + $api_id = $this->getRequest()->request->get('api_id'); + + if (null === $response = $this->checkApiAccess($api_id, AccessManager::DELETE)) { + $response = $this->deleteApi($this->api); + } + + return $response; + } + + private function deleteApi(Api $api) + { + $event = new ApiDeleteEvent($api); + + $this->dispatch(TheliaEvents::API_DELETE, $event); + + return RedirectResponse::create(URL::getInstance()->absoluteUrl($this->getRoute('admin.configuration.api'))); + } + + /** + * @param Api $api + * @return \Symfony\Component\HttpFoundation\Response + */ + private function retrieveSecureKey(Api $api) + { + $response = Response::create($api->getSecureKey()); + $response->headers->add([ + 'Content-Type' => 'application/octet-stream', + 'Content-disposition' => sprintf('filename=%s.key', $api->getApiKey()) + ]); + + return $response; + } + + public function indexAction() + { + if (null !== $response = $this->checkAuth([AdminResources::API], [], AccessManager::VIEW)) { + return $response; + } + + return $this->renderList(); + } + + public function createAction() + { + if (null !== $response = $this->checkAuth([AdminResources::API], [], AccessManager::CREATE)) { + return $response; + } + + $form = $this->createForm(AdminForm::API_CREATE); + $error_msg = null; + try { + $createForm = $this->validateForm($form); + + $event = new ApiCreateEvent( + $createForm->get('label')->getData(), + $createForm->get('profile')->getData() ?: null + ); + + $this->dispatch(TheliaEvents::API_CREATE, $event); + + return RedirectResponse::create($form->getSuccessUrl()); + } catch (FormValidationException $e) { + $error_msg = $this->createStandardFormValidationErrorMessage($e); + } catch (\Exception $e) { + $error_msg = $e->getMessage(); + } + + if (false !== $error_msg) { + $this->setupFormErrorContext( + $this->getTranslator()->trans("%obj creation", array('%obj' => 'Api')), + $error_msg, + $form, + $e + ); + + // At this point, the form has error, and should be redisplayed. + return $this->renderList(); + } + } + + public function updateAction($api_id) + { + if (null === $response = $this->checkApiAccess($api_id, AccessManager::UPDATE)) { + $form = $this->createForm(AdminForm::API_UPDATE, 'form', ['profile' => $this->api->getProfileId()]); + + $this->getParserContext()->addForm($form); + + $response = $this->renderList($api_id); + } + + return $response; + } + + public function processUpdateAction($api_id) + { + if (null === $response = $this->checkApiAccess($api_id, AccessManager::UPDATE)) { + $response = $this->doUpdate($this->api); + } + + return $response; + } + + private function doUpdate(Api $api) + { + $error_msg = null; + $form = $this->createForm(AdminForm::API_UPDATE); + try { + $updateForm = $this->validateForm($form); + + $event = new ApiUpdateEvent($api, $updateForm->get('profile')->getData() ?: null); + + $this->dispatch(TheliaEvents::API_UPDATE, $event); + + $response = RedirectResponse::create(URL::getInstance()->absoluteUrl($this->getRoute('admin.configuration.api'))); + } catch (FormValidationException $e) { + $error_msg = $this->createStandardFormValidationErrorMessage($e); + } catch (\Exception $e) { + $error_msg = $e->getMessage(); + } + + if (null !== $error_msg) { + $this->setupFormErrorContext( + "foo", + $error_msg, + $form, + $e + ); + + $response = $this->renderList($api->getId()); + } + + return $response; + } + + private function checkApiAccess($api_id, $access) + { + $response = null; + if (null === $response = $this->checkAuth([AdminResources::API], [], AccessManager::UPDATE)) { + $this->api = ApiQuery::create()->findPk($api_id); + + if (null === $this->api) { + $response = $this->errorPage(Translator::getInstance()->trans("api id %id does not exists", ['%id' => $api_id])); + } + } + + return $response; + } + + protected function renderList($api_id = null) + { + $apiAccessList = ApiQuery::create()->find()->toArray(); + + return $this->render( + 'api', + [ + 'api_list' => $apiAccessList, + 'api_id' => $api_id + ] + ); + } +} diff --git a/core/lib/Thelia/Controller/Admin/AreaController.php b/core/lib/Thelia/Controller/Admin/AreaController.php new file mode 100644 index 00000000..bb01b4e0 --- /dev/null +++ b/core/lib/Thelia/Controller/Admin/AreaController.php @@ -0,0 +1,440 @@ + + * @author Franck Allimant + */ +class AreaController extends AbstractCrudController +{ + public function __construct() + { + parent::__construct( + 'area', + null, + null, + AdminResources::AREA, + TheliaEvents::AREA_CREATE, + TheliaEvents::AREA_UPDATE, + TheliaEvents::AREA_DELETE + ); + } + + protected function getAreaId() + { + return $this->getRequest()->get('area_id', 0); + } + + /** + * Return the creation form for this object + */ + protected function getCreationForm() + { + return $this->createForm(AdminForm::AREA_CREATE); + } + + /** + * Return the update form for this object + */ + protected function getUpdateForm() + { + return $this->createForm(AdminForm::AREA_MODIFICATION); + } + + /** + * Hydrate the update form for this object, before passing it to the update template + * + * @param Area $object + * @return BaseForm + */ + protected function hydrateObjectForm($object) + { + $data = array( + 'area_id' => $object->getId(), + 'name' => $object->getName() + ); + + return $this->createForm(AdminForm::AREA_MODIFICATION, 'form', $data); + } + + /** + * Creates the creation event with the provided form data + * + * @param array $formData + * + * @return \Thelia\Core\Event\Area\AreaCreateEvent + */ + protected function getCreationEvent($formData) + { + $event = new AreaCreateEvent(); + + return $this->hydrateEvent($event, $formData); + } + + /** + * Creates the update event with the provided form data + * + * @param array $formData + * @return \Thelia\Core\Event\Area\AreaUpdateEvent + */ + protected function getUpdateEvent($formData) + { + $event = new AreaUpdateEvent(); + + $this->hydrateEvent($event, $formData); + + $event->setAreaId($formData['area_id']); + + return $event; + } + + /** + * @param \Thelia\Core\Event\Area\AreaCreateEvent $event + * @param array $formData + * @return \Thelia\Core\Event\Area\AreaCreateEvent + */ + private function hydrateEvent($event, $formData) + { + $event->setAreaName($formData['name']); + + return $event; + } + + /** + * Creates the delete event with the provided form data + * + * @return AreaDeleteEvent + */ + protected function getDeleteEvent() + { + return new AreaDeleteEvent($this->getAreaId()); + } + + /** + * Return true if the event contains the object, e.g. the action has updated the object in the event. + * + * @param \Thelia\Core\Event\Area\AreaEvent $event + * @return bool + */ + protected function eventContainsObject($event) + { + return $event->hasArea(); + } + + /** + * Get the created object from an event. + * + * @param \Thelia\Core\Event\Area\AreaEvent $event + * @return Area + */ + protected function getObjectFromEvent($event) + { + return $event->getArea(); + } + + /** + * Load an existing object from the database + */ + protected function getExistingObject() + { + return AreaQuery::create()->findPk($this->getAreaId()); + } + + /** + * Returns the object label form the object event (name, title, etc.) + * + * @param \Thelia\Model\Area $object + * @return string + */ + protected function getObjectLabel($object) + { + return $object->getName(); + } + + /** + * Returns the object ID from the object + * + * @param \Thelia\Model\Area $object + * @return int + */ + protected function getObjectId($object) + { + return $object->getId(); + } + + /** + * Render the main list template + * + * @param string|null $currentOrder, if any, null otherwise. + * @return \Thelia\Core\HttpFoundation\Response + */ + protected function renderListTemplate($currentOrder) + { + return $this->render("shipping-configuration"); + } + + /** + * Render the edition template + */ + protected function renderEditionTemplate() + { + return $this->render( + 'shipping-configuration-edit', + array( + 'area_id' => $this->getAreaId() + ) + ); + } + + /** + * Redirect to the edition template + */ + protected function redirectToEditionTemplate() + { + return $this->generateRedirectFromRoute( + 'admin.configuration.shipping-configuration.update.view', + [], + [ + "area_id" => $this->getAreaId() + ] + ); + } + + /** + * Redirect to the list template + */ + protected function redirectToListTemplate() + { + return $this->generateRedirectFromRoute('admin.configuration.shipping-configuration.default'); + } + + /** + * add a country to a define area + */ + public function addCountry() + { + // Check current user authorization + if (null !== $response = $this->checkAuth($this->resourceCode, array(), AccessManager::UPDATE)) { + return $response; + } + + $areaCountryForm = $this->createForm(AdminForm::AREA_COUNTRY); + $error_msg = null; + try { + $form = $this->validateForm($areaCountryForm); + + $event = new AreaAddCountryEvent($form->get('area_id')->getData(), $form->get('country_id')->getData()); + + $this->dispatch(TheliaEvents::AREA_ADD_COUNTRY, $event); + + if (! $this->eventContainsObject($event)) { + throw new \LogicException( + $this->getTranslator()->trans("No %obj was updated.", array('%obj', $this->objectName)) + ); + } + + // Log object modification + if (null !== $changedObject = $this->getObjectFromEvent($event)) { + $this->adminLogAppend( + $this->resourceCode, + AccessManager::UPDATE, + sprintf( + "%s %s (ID %s) modified, new country added", + ucfirst($this->objectName), + $this->getObjectLabel($changedObject), + $this->getObjectId($changedObject) + ), + $this->getObjectId($changedObject) + ); + } + + // Redirect to the success URL + return $this->generateSuccessRedirect($areaCountryForm); + } catch (FormValidationException $ex) { + // Form cannot be validated + $error_msg = $this->createStandardFormValidationErrorMessage($ex); + } catch (\Exception $ex) { + // Any other error + $error_msg = $ex->getMessage(); + } + + $this->setupFormErrorContext( + $this->getTranslator()->trans("%obj modification", array('%obj' => $this->objectName)), + $error_msg, + $areaCountryForm + ); + + // At this point, the form has errors, and should be redisplayed. + return $this->renderEditionTemplate(); + } + + /** + * delete several countries from a shipping zone + */ + public function removeCountries() + { + // Check current user authorization + if (null !== $response = $this->checkAuth($this->resourceCode, array(), AccessManager::UPDATE)) { + return $response; + } + + $areaDeleteCountriesForm = $this->createForm(AdminForm::AREA_DELETE_COUNTRY); + + try { + $form = $this->validateForm($areaDeleteCountriesForm); + + $data = $form->getData(); + + foreach ($data['country_id'] as $countryId) { + $country = explode('-', $countryId); + $this->removeOneCountryFromArea($data['area_id'], $country[0], $country[1]); + } + // Redirect to the success URL + return $this->generateSuccessRedirect($areaDeleteCountriesForm); + } catch (FormValidationException $ex) { + // Form cannot be validated + $error_msg = $this->createStandardFormValidationErrorMessage($ex); + } catch (\Exception $ex) { + // Any other error + $error_msg = $ex->getMessage(); + } + + $this->setupFormErrorContext( + $this->getTranslator()->trans("Failed to delete selected countries"), + $error_msg, + $areaDeleteCountriesForm + ); + + // At this point, the form has errors, and should be redisplayed. + return $this->renderEditionTemplate(); + } + + protected function removeOneCountryFromArea($areaId, $countryId, $stateId) + { + if (\intval($stateId) === 0) { + $stateId = null; + } + + $removeCountryEvent = new AreaRemoveCountryEvent($areaId, $countryId, $stateId); + + $this->dispatch(TheliaEvents::AREA_REMOVE_COUNTRY, $removeCountryEvent); + + if (null !== $changedObject = $this->getObjectFromEvent($removeCountryEvent)) { + $this->adminLogAppend( + $this->resourceCode, + AccessManager::UPDATE, + sprintf( + "%s %s (ID %s) removed country ID %s from shipping zone ID %s", + ucfirst($this->objectName), + $this->getObjectLabel($changedObject), + $this->getObjectId($changedObject), + $countryId, + $areaId + ), + $this->getObjectId($changedObject) + ); + } + } + + public function removeCountry() + { + // Check current user authorization + if (null !== $response = $this->checkAuth($this->resourceCode, array(), AccessManager::UPDATE)) { + return $response; + } + + $this->removeOneCountryFromArea( + $this->getRequest()->get('area_id', 0), + $this->getRequest()->get('country_id', 0), + $this->getRequest()->get('state_id', null) + ); + + return $this->redirectToEditionTemplate(); + } + + public function updatePostageAction() + { + if (null !== $response = $this->checkAuth($this->resourceCode, array(), AccessManager::UPDATE)) { + return $response; + } + + $areaUpdateForm = $this->createForm(AdminForm::AREA_POSTAGE); + $error_msg = null; + + try { + $form = $this->validateForm($areaUpdateForm); + + $event = new AreaUpdatePostageEvent($form->get('area_id')->getData()); + $event->setPostage($form->get('postage')->getData()); + + $this->dispatch(TheliaEvents::AREA_POSTAGE_UPDATE, $event); + + if (! $this->eventContainsObject($event)) { + throw new \LogicException( + $this->getTranslator()->trans("No %obj was updated.", array('%obj', $this->objectName)) + ); + } + + // Log object modification + if (null !== $changedObject = $this->getObjectFromEvent($event)) { + $this->adminLogAppend( + $this->resourceCode, + AccessManager::UPDATE, + sprintf( + "%s %s (ID %s) modified, country remove", + ucfirst($this->objectName), + $this->getObjectLabel($changedObject), + $this->getObjectId($changedObject) + ), + $this->getObjectId($changedObject) + ); + } + + // Redirect to the success URL + return $this->generateSuccessRedirect($areaUpdateForm); + } catch (FormValidationException $ex) { + // Form cannot be validated + $error_msg = $this->createStandardFormValidationErrorMessage($ex); + } catch (\Exception $ex) { + // Any other error + $error_msg = $ex->getMessage(); + } + + $this->setupFormErrorContext( + $this->getTranslator()->trans("%obj modification", array('%obj' => $this->objectName)), + $error_msg, + $areaUpdateForm + ); + + // At this point, the form has errors, and should be redisplayed. + return $this->renderEditionTemplate(); + } +} diff --git a/core/lib/Thelia/Controller/Admin/AttributeAvController.php b/core/lib/Thelia/Controller/Admin/AttributeAvController.php new file mode 100644 index 00000000..6891230d --- /dev/null +++ b/core/lib/Thelia/Controller/Admin/AttributeAvController.php @@ -0,0 +1,183 @@ + + */ +class AttributeAvController extends AbstractCrudController +{ + public function __construct() + { + parent::__construct( + 'attributeav', + 'manual', + 'order', + AdminResources::ATTRIBUTE, + TheliaEvents::ATTRIBUTE_AV_CREATE, + TheliaEvents::ATTRIBUTE_AV_UPDATE, + TheliaEvents::ATTRIBUTE_AV_DELETE, + null, // No visibility toggle + TheliaEvents::ATTRIBUTE_AV_UPDATE_POSITION + ); + } + + protected function getCreationForm() + { + return $this->createForm(AdminForm::ATTRIBUTE_AV_CREATION); + } + + protected function getUpdateForm() + { + throw new \LogicException("Attribute Av. modification is not yet implemented"); + } + + protected function getCreationEvent($formData) + { + $createEvent = new AttributeAvCreateEvent(); + + $createEvent + ->setAttributeId($formData['attribute_id']) + ->setTitle($formData['title']) + ->setLocale($formData["locale"]) + ; + + return $createEvent; + } + + protected function getUpdateEvent($formData) + { + $changeEvent = new AttributeAvUpdateEvent($formData['id']); + + // Create and dispatch the change event + $changeEvent + ->setLocale($formData["locale"]) + ->setTitle($formData['title']) + ->setChapo($formData['chapo']) + ->setDescription($formData['description']) + ->setPostscriptum($formData['postscriptum']) + ; + + return $changeEvent; + } + + protected function createUpdatePositionEvent($positionChangeMode, $positionValue) + { + return new UpdatePositionEvent( + $this->getRequest()->get('attributeav_id', null), + $positionChangeMode, + $positionValue + ); + } + + protected function getDeleteEvent() + { + return new AttributeAvDeleteEvent($this->getRequest()->get('attributeav_id')); + } + + protected function eventContainsObject($event) + { + return $event->hasAttributeAv(); + } + + protected function hydrateObjectForm($object) + { + throw new \LogicException("Attribute Av. modification is not yet implemented"); + } + + protected function getObjectFromEvent($event) + { + return $event->hasAttributeAv() ? $event->getAttributeAv() : null; + } + + protected function getExistingObject() + { + $attributeAv = AttributeAvQuery::create() + ->findOneById($this->getRequest()->get('attributeav_id', 0)); + + if (null !== $attributeAv) { + $attributeAv->setLocale($this->getCurrentEditionLocale()); + } + + return $attributeAv; + } + + /** + * @param AttributeAv $object + * @return string + */ + protected function getObjectLabel($object) + { + return $object->getTitle(); + } + + /** + * @param AttributeAv $object + * @return int + */ + protected function getObjectId($object) + { + return $object->getId(); + } + + protected function getViewArguments() + { + return array( + 'attribute_id' => $this->getRequest()->get('attribute_id'), + 'order' => $this->getCurrentListOrder() + ); + } + + protected function renderListTemplate($currentOrder) + { + // We always return to the attribute edition form + return $this->render( + 'attribute-edit', + $this->getViewArguments() + ); + } + + protected function renderEditionTemplate() + { + // We always return to the attribute edition form + return $this->render('attribute-edit', $this->getViewArguments()); + } + + protected function redirectToEditionTemplate() + { + return $this->generateRedirectFromRoute( + "admin.configuration.attributes.update", + $this->getViewArguments() + ); + } + + protected function redirectToListTemplate() + { + return $this->generateRedirectFromRoute( + "admin.configuration.attributes.update", + $this->getViewArguments() + ); + } +} diff --git a/core/lib/Thelia/Controller/Admin/AttributeController.php b/core/lib/Thelia/Controller/Admin/AttributeController.php new file mode 100644 index 00000000..9bf28928 --- /dev/null +++ b/core/lib/Thelia/Controller/Admin/AttributeController.php @@ -0,0 +1,266 @@ + + */ +class AttributeController extends AbstractCrudController +{ + public function __construct() + { + parent::__construct( + 'attribute', + 'manual', + 'order', + AdminResources::ATTRIBUTE, + TheliaEvents::ATTRIBUTE_CREATE, + TheliaEvents::ATTRIBUTE_UPDATE, + TheliaEvents::ATTRIBUTE_DELETE, + null, // No visibility toggle + TheliaEvents::ATTRIBUTE_UPDATE_POSITION + ); + } + + protected function getCreationForm() + { + return $this->createForm(AdminForm::ATTRIBUTE_CREATION); + } + + protected function getUpdateForm() + { + return $this->createForm(AdminForm::ATTRIBUTE_MODIFICATION); + } + + protected function getCreationEvent($formData) + { + $createEvent = new AttributeCreateEvent(); + + $createEvent + ->setTitle($formData['title']) + ->setLocale($formData["locale"]) + ->setAddToAllTemplates($formData['add_to_all']) + ; + + return $createEvent; + } + + protected function getUpdateEvent($formData) + { + $changeEvent = new AttributeUpdateEvent($formData['id']); + + // Create and dispatch the change event + $changeEvent + ->setLocale($formData["locale"]) + ->setTitle($formData['title']) + ->setChapo($formData['chapo']) + ->setDescription($formData['description']) + ->setPostscriptum($formData['postscriptum']) + ; + + return $changeEvent; + } + + /** + * Process the attributes values (fix it in future version to integrate it in the attribute form as a collection) + * + * @see \Thelia\Controller\Admin\AbstractCrudController::performAdditionalUpdateAction() + */ + protected function performAdditionalUpdateAction($updateEvent) + { + $attr_values = $this->getRequest()->get('attribute_values', null); + + if ($attr_values !== null) { + foreach ($attr_values as $id => $value) { + $event = new AttributeAvUpdateEvent($id); + + $event->setTitle($value); + $event->setLocale($this->getCurrentEditionLocale()); + + $this->dispatch(TheliaEvents::ATTRIBUTE_AV_UPDATE, $event); + } + } + + return null; + } + + protected function createUpdatePositionEvent($positionChangeMode, $positionValue) + { + return new UpdatePositionEvent( + $this->getRequest()->get('attribute_id', null), + $positionChangeMode, + $positionValue + ); + } + + protected function getDeleteEvent() + { + return new AttributeDeleteEvent($this->getRequest()->get('attribute_id')); + } + + protected function eventContainsObject($event) + { + return $event->hasAttribute(); + } + + protected function hydrateObjectForm($object) + { + $data = array( + 'id' => $object->getId(), + 'locale' => $object->getLocale(), + 'title' => $object->getTitle(), + 'chapo' => $object->getChapo(), + 'description' => $object->getDescription(), + 'postscriptum' => $object->getPostscriptum() + ); + + // Setup the object form + return $this->createForm(AdminForm::ATTRIBUTE_MODIFICATION, "form", $data); + } + + protected function getObjectFromEvent($event) + { + return $event->hasAttribute() ? $event->getAttribute() : null; + } + + protected function getExistingObject() + { + $attribute = AttributeQuery::create() + ->findOneById($this->getRequest()->get('attribute_id', 0)); + + if (null !== $attribute) { + $attribute->setLocale($this->getCurrentEditionLocale()); + } + + return $attribute; + } + + /** + * @param Attribute $object + * @return string + */ + protected function getObjectLabel($object) + { + return $object->getTitle(); + } + + /** + * @param Attribute $object + * @return int + */ + protected function getObjectId($object) + { + return $object->getId(); + } + + protected function renderListTemplate($currentOrder) + { + return $this->render('attributes', array('order' => $currentOrder)); + } + + protected function renderEditionTemplate() + { + return $this->render( + 'attribute-edit', + array( + 'attribute_id' => $this->getRequest()->get('attribute_id'), + 'attributeav_order' => $this->getAttributeAvListOrder() + ) + ); + } + + protected function redirectToEditionTemplate() + { + return $this->generateRedirectFromRoute( + "admin.configuration.attributes.update", + [ + 'attribute_id' => $this->getRequest()->get('attribute_id'), + 'attributeav_order' => $this->getAttributeAvListOrder() + ] + ); + } + + protected function redirectToListTemplate() + { + return $this->generateRedirectFromRoute('admin.configuration.attributes.default'); + } + + /** + * Get the Attribute value list order. + * + * @return string the current list order + */ + protected function getAttributeAvListOrder() + { + return $this->getListOrderFromSession( + 'attributeav', + 'attributeav_order', + 'manual' + ); + } + + /** + * Add or Remove from all product templates + */ + protected function addRemoveFromAllTemplates($eventType) + { + // Check current user authorization + if (null !== $response = $this->checkAuth($this->resourceCode, array(), AccessManager::UPDATE)) { + return $response; + } + + try { + if (null !== $object = $this->getExistingObject()) { + $event = new AttributeEvent($object); + + $this->dispatch($eventType, $event); + } + } catch (\Exception $ex) { + // Any error + return $this->errorPage($ex); + } + + return $this->redirectToListTemplate(); + } + + /** + * Remove from all product templates + */ + public function removeFromAllTemplates() + { + return $this->addRemoveFromAllTemplates(TheliaEvents::ATTRIBUTE_REMOVE_FROM_ALL_TEMPLATES); + } + + /** + * Add to all product templates + */ + public function addToAllTemplates() + { + return $this->addRemoveFromAllTemplates(TheliaEvents::ATTRIBUTE_ADD_TO_ALL_TEMPLATES); + } +} diff --git a/core/lib/Thelia/Controller/Admin/BaseAdminController.php b/core/lib/Thelia/Controller/Admin/BaseAdminController.php new file mode 100644 index 00000000..298f106e --- /dev/null +++ b/core/lib/Thelia/Controller/Admin/BaseAdminController.php @@ -0,0 +1,402 @@ +getRequest(), + $this->getSecurityContext()->getAdminUser(), + true, + $resourceId + ); + } + + /** + * This method process the rendering of view called from an admin page + * + * @param string $template the template name + * @return Response the response which contains the rendered view + */ + public function processTemplateAction($template) + { + try { + if (! empty($template)) { + // If we have a view in the URL, render this view + return $this->render($template); + } elseif (null != $view = $this->getRequest()->get('view')) { + return $this->render($view); + } + } catch (\Exception $ex) { + return $this->errorPage($ex->getMessage()); + } + + return $this->pageNotFound(); + } + + /** + * @return string + */ + public function getControllerType() + { + return self::CONTROLLER_TYPE; + } + + /** + * Return a 404 error + * + * @return \Thelia\Core\HttpFoundation\Response + */ + protected function pageNotFound() + { + return new Response($this->renderRaw(self::TEMPLATE_404), 404); + } + + /** + * Return a general error page + * + * @param \Exception|string $message a message string, or an exception instance + * @param int $status the HTTP status (default is 500) + * + * @return \Thelia\Core\HttpFoundation\Response + */ + protected function errorPage($message, $status = 500) + { + if ($message instanceof \Exception) { + $strMessage = $this->getTranslator()->trans( + "Sorry, an error occured: %msg", + [ '%msg' => $message->getMessage() ] + ); + + Tlog::getInstance()->addError($strMessage.": ".$message->getTraceAsString()); + + $message = $strMessage; + } else { + Tlog::getInstance()->addError($message); + } + + return $this->render( + 'general_error', + array( + "error_message" => $message + ), + $status + ); + } + + /** + * Check current admin user authorisations. An ADMIN role is assumed. + * + * @param mixed $resources a single resource or an array of resources. + * @param mixed $modules a single module or an array of modules. + * @param mixed $accesses a single access or an array of accesses. + * + * @return mixed null if authorization is granted, or a Response object which contains the error page otherwise + */ + protected function checkAuth($resources, $modules, $accesses) + { + $resources = \is_array($resources) ? $resources : array($resources); + $modules = \is_array($modules) ? $modules : array($modules); + $accesses = \is_array($accesses) ? $accesses : array($accesses); + + if ($this->getSecurityContext()->isGranted(array("ADMIN"), $resources, $modules, $accesses)) { + // Okay ! + return null; + } + + // Log the problem + $this->adminLogAppend(implode(",", $resources), implode(",", $accesses), "User is not granted for resources %s with accesses %s", implode(", ", $resources), implode(", ", $accesses)); + + return $this->errorPage($this->getTranslator()->trans("Sorry, you're not allowed to perform this action"), 403); + } + + /* + * Create the standard message displayed to the user when the form cannot be validated. + */ + protected function createStandardFormValidationErrorMessage(FormValidationException $exception) + { + return $this->getTranslator()->trans( + "Please check your input: %error", + array( + '%error' => $exception->getMessage() + ) + ); + } + + /** + * Setup the error context when an error occurs in a action method. + * + * @param string $action the action that caused the error (category modification, variable creation, currency update, etc.) + * @param BaseForm $form the form where the error occured, or null if no form was involved + * @param string $error_message the error message + * @param \Exception $exception the exception or null if no exception + */ + protected function setupFormErrorContext($action, $error_message, BaseForm $form = null, \Exception $exception = null) + { + if ($error_message !== false) { + // Log the error message + Tlog::getInstance()->error( + $this->getTranslator()->trans( + "Error during %action process : %error. Exception was %exc", + array( + '%action' => $action, + '%error' => $error_message, + '%exc' => $exception != null ? $exception->getMessage() : 'no exception' + ) + ) + ); + + if ($form != null) { + // Mark the form as errored + $form->setErrorMessage($error_message); + + // Pass it to the parser context + $this->getParserContext()->addForm($form); + } + + // Pass the error message to the parser. + $this->getParserContext()->setGeneralError($error_message); + } + } + + /** + * @param TemplateDefinition $template the template to process + * + * @return ParserInterface instance parser + */ + protected function getParser($template = null) + { + $parser = $this->container->get("thelia.parser"); + + // Define the template that should be used + $parser->setTemplateDefinition( + $template ?: $this->getTemplateHelper()->getActiveAdminTemplate(), + $this->useFallbackTemplate + ); + + return $parser; + } + + /** + * Forwards the request to another controller. + * + * @param string $controller The controller name (a string like BlogBundle:Post:index) + * @param array $path An array of path parameters + * @param array $query An array of query parameters + * + * @return Response A Response instance + */ + protected function forward($controller, array $path = array(), array $query = array()) + { + $path['_controller'] = $controller; + $subRequest = $this->container->get('request_stack')->getCurrentRequest()->duplicate($query, null, $path); + + return $this->container->get('http_kernel')->handle($subRequest, HttpKernelInterface::SUB_REQUEST); + } + + /** + * Get the current edition currency ID, checking if a change was requested in the current request. + */ + protected function getCurrentEditionCurrency() + { + // Return the new language if a change is required. + if (null !== $edit_currency_id = $this->getRequest()->get('edit_currency_id', null)) { + if (null !== $edit_currency = CurrencyQuery::create()->findOneById($edit_currency_id)) { + return $edit_currency; + } + } + + // Otherwise return the lang stored in session. + return $this->getSession()->getAdminEditionCurrency(); + } + + /** + * Get the current edition lang ID, checking if a change was requested in the current request. + */ + protected function getCurrentEditionLang() + { + // Return the new language if a change is required. + if (null !== $edit_language_id = $this->getRequest()->get('edit_language_id', null)) { + if (null !== $edit_language = LangQuery::create()->findOneById($edit_language_id)) { + return $edit_language; + } + } + + // Otherwise return the lang stored in session. + return $this->getSession()->getAdminEditionLang(); + } + + /** + * A simple helper to get the current edition locale. + */ + protected function getCurrentEditionLocale() + { + return $this->getCurrentEditionLang()->getLocale(); + } + + /** + * A simple helper to get the URL based on the language. + * + * @param string $locale the locale, or null to get the current one + * @return null|string the URL for the current language, or null if the "One domain for each lang" feature is disabled. + */ + protected function getUrlLanguage($locale = null) + { + // Check if the functionality is activated + if (!ConfigQuery::isMultiDomainActivated()) { + return null; + } + + // If we don't have a locale value, use the locale value in the session + if (!$locale) { + $locale = $this->getCurrentEditionLocale(); + } + + return LangQuery::create()->findOneByLocale($locale)->getUrl(); + } + + + /** + * Return the current list order identifier for a given object name, + * updating in using the current request. + * + * @param string $objectName the object name (e.g. 'attribute', 'message') + * @param string $requestParameterName the name of the request parameter that defines the list order + * @param string $defaultListOrder the default order to use, if none is defined + * @param bool $updateSession if true, the session will be updated with the current order. + * + * @return String the current list order. + */ + protected function getListOrderFromSession($objectName, $requestParameterName, $defaultListOrder, $updateSession = true) + { + $orderSessionIdentifier = sprintf("admin.%s.currentListOrder", $objectName); + + // Find the current order + $order = $this->getRequest()->get( + $requestParameterName, + $this->getSession()->get($orderSessionIdentifier, $defaultListOrder) + ); + + if ($updateSession) { + $this->getSession()->set($orderSessionIdentifier, $order); + } + return $order; + } + + /** + * Render the given template, and returns the result as an Http Response. + * + * @param string $templateName the complete template name, with extension + * @param array $args the template arguments + * @param int $status http code status + * @return \Thelia\Core\HttpFoundation\Response + */ + protected function render($templateName, $args = array(), $status = 200) + { + $response = $this->renderRaw($templateName, $args); + + if (!$response instanceof \Symfony\Component\HttpFoundation\Response) { + $response = Response::create($response, $status); + } + + return $response; + } + + /** + * Render the given template, and returns the result as a string. + * + * @param string $templateName the complete template name, with extension + * @param array $args the template arguments + * @param null $templateDir + * + * @return string|\Symfony\Component\HttpFoundation\RedirectResponse + */ + protected function renderRaw($templateName, $args = array(), $templateDir = null) + { + // Add the template standard extension + $templateName .= '.html'; + + // Find the current edit language ID + $edition_language = $this->getCurrentEditionLang(); + + // Find the current edit currency ID + $edition_currency = $this->getCurrentEditionCurrency(); + + // Prepare common template variables + $args = array_merge($args, array( + 'edit_language_id' => $edition_language->getId(), + 'edit_language_locale' => $edition_language->getLocale(), + 'edit_currency_id' => $edition_currency->getId(), + )); + + // Update the current edition language & currency in session + $this->getSession() + ->setAdminEditionLang($edition_language) + ->setAdminEditionCurrency($edition_currency) + ; + + // Render the template. + try { + $content = $this->getParser($templateDir)->render($templateName, $args); + } catch (AuthenticationException $ex) { + // User is not authenticated, and templates requires authentication -> redirect to login page + // We user login_tpl as a path, not a template. + $content = RedirectResponse::create(URL::getInstance()->absoluteUrl($ex->getLoginTemplate())); + } catch (AuthorizationException $ex) { + // User is not allowed to perform the required action. Return the error page instead of the requested page. + $content = $this->errorPage($this->getTranslator()->trans("Sorry, you are not allowed to perform this action."), 403); + } + + return $content; + } +} diff --git a/core/lib/Thelia/Controller/Admin/BrandController.php b/core/lib/Thelia/Controller/Admin/BrandController.php new file mode 100644 index 00000000..72fee4d5 --- /dev/null +++ b/core/lib/Thelia/Controller/Admin/BrandController.php @@ -0,0 +1,282 @@ + + */ +class BrandController extends AbstractSeoCrudController +{ + public function __construct() + { + parent::__construct( + 'brand', + 'manual', + 'order', + AdminResources::BRAND, + TheliaEvents::BRAND_CREATE, + TheliaEvents::BRAND_UPDATE, + TheliaEvents::BRAND_DELETE, + TheliaEvents::BRAND_TOGGLE_VISIBILITY, + TheliaEvents::BRAND_UPDATE_POSITION, + TheliaEvents::BRAND_UPDATE_SEO + ); + } + + /** + * Return the creation form for this object + */ + protected function getCreationForm() + { + return $this->createForm(AdminForm::BRAND_CREATION); + } + + /** + * Return the update form for this object + */ + protected function getUpdateForm() + { + return $this->createForm(AdminForm::BRAND_MODIFICATION); + } + + /** + * Hydrate the update form for this object, before passing it to the update template + * + * @param Brand $object + * @return BrandModificationForm $object + */ + protected function hydrateObjectForm($object) + { + // Hydrate the "SEO" tab form + $this->hydrateSeoForm($object); + + // Prepare the data that will hydrate the form + $data = [ + 'id' => $object->getId(), + 'locale' => $object->getLocale(), + 'title' => $object->getTitle(), + 'chapo' => $object->getChapo(), + 'description' => $object->getDescription(), + 'postscriptum' => $object->getPostscriptum(), + 'visible' => $object->getVisible() ? true : false, + 'logo_image_id' => $object->getLogoImageId() + ]; + + // Setup the object form + return $this->createForm(AdminForm::BRAND_MODIFICATION, "form", $data); + } + + /** + * Creates the creation event with the provided form data + * + * @param array $formData + * @return BrandCreateEvent + */ + protected function getCreationEvent($formData) + { + $brandCreateEvent = new BrandCreateEvent(); + + $brandCreateEvent + ->setLocale($formData['locale']) + ->setTitle($formData['title']) + ->setVisible($formData['visible']) + ; + + return $brandCreateEvent; + } + + /** + * Creates the update event with the provided form data + * + * @param array $formData + * @return BrandUpdateEvent + */ + protected function getUpdateEvent($formData) + { + $brandUpdateEvent = new BrandUpdateEvent($formData['id']); + + $brandUpdateEvent + ->setLogoImageId($formData['logo_image_id']) + ->setVisible($formData['visible']) + ->setLocale($formData['locale']) + ->setTitle($formData['title']) + ->setChapo($formData['chapo']) + ->setDescription($formData['description']) + ->setPostscriptum($formData['postscriptum']) + ; + + return $brandUpdateEvent; + } + + /** + * Creates the delete event with the provided form data + * + * @return BrandDeleteEvent + */ + protected function getDeleteEvent() + { + return new BrandDeleteEvent($this->getRequest()->get('brand_id')); + } + + /** + * Return true if the event contains the object, e.g. the action has updated the object in the event. + * + * @param BrandEvent $event + * @return bool + */ + protected function eventContainsObject($event) + { + return $event->hasBrand(); + } + + /** + * Get the created object from an event. + * + * @param $event \Thelia\Core\Event\Brand\BrandEvent + * + * @return null|\Thelia\Model\Brand + */ + protected function getObjectFromEvent($event) + { + return $event->getBrand(); + } + + /** + * Load an existing object from the database + * + * @return \Thelia\Model\Brand + */ + protected function getExistingObject() + { + $brand = BrandQuery::create() + ->findOneById($this->getRequest()->get('brand_id', 0)); + + if (null !== $brand) { + $brand->setLocale($this->getCurrentEditionLocale()); + } + + return $brand; + } + + /** + * Returns the object label form the object event (name, title, etc.) + * + * @param Brand $object + * + * @return string brand title + */ + protected function getObjectLabel($object) + { + return $object->getTitle(); + } + + /** + * Returns the object ID from the object + * + * @param Brand $object + * + * @return int brand id + */ + protected function getObjectId($object) + { + return $object->getId(); + } + + /** + * Render the main list template + * + * @param string $currentOrder, if any, null otherwise. + * + * @return Response + */ + protected function renderListTemplate($currentOrder) + { + $this->getListOrderFromSession('brand', 'order', 'manual'); + + return $this->render('brands', [ + 'order' => $currentOrder, + ]); + } + + protected function getEditionArguments() + { + return [ + 'brand_id' => $this->getRequest()->get('brand_id', 0), + 'current_tab' => $this->getRequest()->get('current_tab', 'general') + ]; + } + + /** + * Render the edition template + */ + protected function renderEditionTemplate() + { + return $this->render('brand-edit', $this->getEditionArguments()); + } + + /** + * Redirect to the edition template + */ + protected function redirectToEditionTemplate() + { + return $this->generateRedirectFromRoute( + 'admin.brand.update', + [], + $this->getEditionArguments() + ); + } + + /** + * Redirect to the list template + */ + protected function redirectToListTemplate() + { + return $this->generateRedirectFromRoute('admin.brand.default'); + } + + /** + * @return BrandToggleVisibilityEvent|void + */ + protected function createToggleVisibilityEvent() + { + return new BrandToggleVisibilityEvent($this->getExistingObject()); + } + + /** + * @inheritdoc + */ + protected function createUpdatePositionEvent($positionChangeMode, $positionValue) + { + return new UpdatePositionEvent( + $this->getRequest()->get('brand_id', null), + $positionChangeMode, + $positionValue + ); + } +} diff --git a/core/lib/Thelia/Controller/Admin/CategoryController.php b/core/lib/Thelia/Controller/Admin/CategoryController.php new file mode 100644 index 00000000..268795fb --- /dev/null +++ b/core/lib/Thelia/Controller/Admin/CategoryController.php @@ -0,0 +1,405 @@ + + */ +class CategoryController extends AbstractSeoCrudController +{ + public function __construct() + { + parent::__construct( + 'category', + 'manual', + 'category_order', + AdminResources::CATEGORY, + TheliaEvents::CATEGORY_CREATE, + TheliaEvents::CATEGORY_UPDATE, + TheliaEvents::CATEGORY_DELETE, + TheliaEvents::CATEGORY_TOGGLE_VISIBILITY, + TheliaEvents::CATEGORY_UPDATE_POSITION, + TheliaEvents::CATEGORY_UPDATE_SEO + ); + } + + protected function getCreationForm() + { + return $this->createForm(AdminForm::CATEGORY_CREATION); + } + + protected function getUpdateForm() + { + return $this->createForm(AdminForm::CATEGORY_MODIFICATION); + } + + protected function getCreationEvent($formData) + { + $createEvent = new CategoryCreateEvent(); + + $createEvent + ->setTitle($formData['title']) + ->setLocale($formData["locale"]) + ->setParent($formData['parent']) + ->setVisible($formData['visible']) + ; + + return $createEvent; + } + + protected function getUpdateEvent($formData) + { + $changeEvent = new CategoryUpdateEvent($formData['id']); + + // Create and dispatch the change event + $changeEvent + ->setLocale($formData['locale']) + ->setTitle($formData['title']) + ->setChapo($formData['chapo']) + ->setDescription($formData['description']) + ->setPostscriptum($formData['postscriptum']) + ->setVisible($formData['visible']) + ->setParent($formData['parent']) + ->setDefaultTemplateId($formData['default_template_id']) + ; + + return $changeEvent; + } + + protected function createUpdatePositionEvent($positionChangeMode, $positionValue) + { + return new UpdatePositionEvent( + $this->getRequest()->get('category_id', null), + $positionChangeMode, + $positionValue + ); + } + + protected function getDeleteEvent() + { + return new CategoryDeleteEvent($this->getRequest()->get('category_id', 0)); + } + + protected function eventContainsObject($event) + { + return $event->hasCategory(); + } + + /** + * @param \Thelia\Model\Category $object + * @return \Thelia\Form\BaseForm + */ + protected function hydrateObjectForm($object) + { + // Hydrate the "SEO" tab form + $this->hydrateSeoForm($object); + + // The "General" tab form + $data = array( + 'id' => $object->getId(), + 'locale' => $object->getLocale(), + 'title' => $object->getTitle(), + 'chapo' => $object->getChapo(), + 'description' => $object->getDescription(), + 'postscriptum' => $object->getPostscriptum(), + 'visible' => $object->getVisible(), + 'parent' => $object->getParent(), + 'default_template_id' => $object->getDefaultTemplateId() + ); + + // Setup the object form + return $this->createForm(AdminForm::CATEGORY_MODIFICATION, "form", $data); + } + + protected function getObjectFromEvent($event) + { + return $event->hasCategory() ? $event->getCategory() : null; + } + + protected function getExistingObject() + { + $category = CategoryQuery::create() + ->findOneById($this->getRequest()->get('category_id', 0)); + + if (null !== $category) { + $category->setLocale($this->getCurrentEditionLocale()); + } + + return $category; + } + + /** + * @param Category $object + * @return string + */ + protected function getObjectLabel($object) + { + return $object->getTitle(); + } + + /** + * @param Category $object + * @return int + */ + protected function getObjectId($object) + { + return $object->getId(); + } + + protected function getEditionArguments() + { + return array( + 'category_id' => $this->getRequest()->get('category_id', 0), + 'folder_id' => $this->getRequest()->get('folder_id', 0), + 'current_tab' => $this->getRequest()->get('current_tab', 'general'), + 'page' => $this->getRequest()->get('page', 1) + ); + } + + protected function renderListTemplate($currentOrder) + { + // Get product order + $product_order = $this->getListOrderFromSession('product', 'product_order', 'manual'); + + return $this->render( + 'categories', + array( + 'category_order' => $currentOrder, + 'product_order' => $product_order, + 'category_id' => $this->getRequest()->get('category_id', 0), + 'page' => $this->getRequest()->get('page', 1) + ) + ); + } + + protected function redirectToListTemplate() + { + return $this->generateRedirectFromRoute( + 'admin.categories.default', + [ + 'category_id' => $this->getRequest()->get('category_id', 0), + 'page' => $this->getRequest()->get('page', 1) + ] + ); + } + + protected function redirectToListTemplateWithId($category_id) + { + $response = null; + if ($category_id > 0) { + $response = $this->generateRedirectFromRoute( + 'admin.categories.default', + ['category_id' => $category_id] + ); + } else { + $response = $this->generateRedirectFromRoute('admin.catalog'); + } + + return $response; + } + + protected function renderEditionTemplate() + { + return $this->render('category-edit', $this->getEditionArguments()); + } + + protected function redirectToEditionTemplate() + { + return $this->generateRedirectFromRoute( + "admin.categories.update", + $this->getEditionArguments() + ); + } + + /** + * Online status toggle category + */ + public function setToggleVisibilityAction() + { + // Check current user authorization + if (null !== $response = $this->checkAuth($this->resourceCode, array(), AccessManager::UPDATE)) { + return $response; + } + + $event = new CategoryToggleVisibilityEvent($this->getExistingObject()); + + try { + $this->dispatch(TheliaEvents::CATEGORY_TOGGLE_VISIBILITY, $event); + } catch (\Exception $ex) { + // Any error + return $this->errorPage($ex); + } + + // Ajax response -> no action + return $this->nullResponse(); + } + + /** + * @param CategoryDeleteEvent $deleteEvent + * @return null|\Symfony\Component\HttpFoundation\Response + */ + protected function performAdditionalDeleteAction($deleteEvent) + { + // Redirect to parent category list + $category_id = $deleteEvent->getCategory()->getParent(); + + return $this->redirectToListTemplateWithId($category_id); + } + + /** + * @param CategoryUpdateEvent $updateEvent + * @return null|\Symfony\Component\HttpFoundation\Response + */ + protected function performAdditionalUpdateAction($updateEvent) + { + $response = null; + if ($this->getRequest()->get('save_mode') != 'stay') { + // Redirect to parent category list + $category_id = $updateEvent->getCategory()->getParent(); + $response = $this->redirectToListTemplateWithId($category_id); + } + + return $response; + } + + /** + * @param UpdatePositionEvent $event + * @return null|\Symfony\Component\HttpFoundation\Response + */ + protected function performAdditionalUpdatePositionAction($event) + { + $category = CategoryQuery::create()->findPk($event->getObjectId()); + $response = null; + if ($category != null) { + // Redirect to parent category list + $category_id = $category->getParent(); + $response = $this->redirectToListTemplateWithId($category_id); + } + + return $response; + } + + public function getAvailableRelatedContentAction($categoryId, $folderId) + { + $result = array(); + + $folders = FolderQuery::create()->filterById($folderId)->find(); + + if ($folders !== null) { + $list = ContentQuery::create() + ->joinWithI18n($this->getCurrentEditionLocale()) + ->filterByFolder($folders, Criteria::IN) + ->filterById( + CategoryAssociatedContentQuery::create()->select('content_id')->findByCategoryId($categoryId), + Criteria::NOT_IN + ) + ->find(); + ; + + if ($list !== null) { + foreach ($list as $item) { + $result[] = array('id' => $item->getId(), 'title' => $item->getTitle()); + } + } + } + + return $this->jsonResponse(json_encode($result)); + } + + public function addRelatedContentAction() + { + // Check current user authorization + if (null !== $response = $this->checkAuth($this->resourceCode, array(), AccessManager::UPDATE)) { + return $response; + } + + $content_id = \intval($this->getRequest()->get('content_id')); + + if ($content_id > 0) { + $event = new CategoryAddContentEvent( + $this->getExistingObject(), + $content_id + ); + + try { + $this->dispatch(TheliaEvents::CATEGORY_ADD_CONTENT, $event); + } catch (\Exception $ex) { + // Any error + return $this->errorPage($ex); + } + } + + return $this->redirectToEditionTemplate(); + } + + /** + * Add category pictures + * + * @return \Thelia\Core\HttpFoundation\Response + */ + public function addRelatedPictureAction() + { + // Check current user authorization + if (null !== $response = $this->checkAuth($this->resourceCode, array(), AccessManager::UPDATE)) { + return $response; + } + + return $this->redirectToEditionTemplate(); + } + + public function deleteRelatedContentAction() + { + // Check current user authorization + if (null !== $response = $this->checkAuth($this->resourceCode, array(), AccessManager::UPDATE)) { + return $response; + } + + $content_id = \intval($this->getRequest()->get('content_id')); + + if ($content_id > 0) { + $event = new CategoryDeleteContentEvent( + $this->getExistingObject(), + $content_id + ); + + try { + $this->dispatch(TheliaEvents::CATEGORY_REMOVE_CONTENT, $event); + } catch (\Exception $ex) { + // Any error + return $this->errorPage($ex); + } + } + + return $this->redirectToEditionTemplate(); + } +} diff --git a/core/lib/Thelia/Controller/Admin/ConfigController.php b/core/lib/Thelia/Controller/Admin/ConfigController.php new file mode 100644 index 00000000..c95c3ded --- /dev/null +++ b/core/lib/Thelia/Controller/Admin/ConfigController.php @@ -0,0 +1,205 @@ + + */ +class ConfigController extends AbstractCrudController +{ + public function __construct() + { + parent::__construct( + 'variable', + 'name', + 'order', + AdminResources::CONFIG, + TheliaEvents::CONFIG_CREATE, + TheliaEvents::CONFIG_UPDATE, + TheliaEvents::CONFIG_DELETE, + null, // No visibility toggle + null // no position change + ); + } + + protected function getCreationForm() + { + return $this->createForm(AdminForm::CONFIG_CREATION); + } + + protected function getUpdateForm() + { + return $this->createForm(AdminForm::CONFIG_MODIFICATION); + } + + protected function getCreationEvent($data) + { + $createEvent = new ConfigCreateEvent(); + + $createEvent + ->setEventName($data['name']) + ->setValue($data['value']) + ->setLocale($data["locale"]) + ->setTitle($data['title']) + ->setHidden($data['hidden']) + ->setSecured($data['secured']) + ; + + return $createEvent; + } + + protected function getUpdateEvent($data) + { + $changeEvent = new ConfigUpdateEvent($data['id']); + + // Create and dispatch the change event + $changeEvent + ->setEventName($data['name']) + ->setValue($data['value']) + ->setHidden($data['hidden']) + ->setSecured($data['secured']) + ->setLocale($data["locale"]) + ->setTitle($data['title']) + ->setChapo($data['chapo']) + ->setDescription($data['description']) + ->setPostscriptum($data['postscriptum']) + ; + + return $changeEvent; + } + + protected function getDeleteEvent() + { + return new ConfigDeleteEvent($this->getRequest()->get('variable_id')); + } + + protected function eventContainsObject($event) + { + return $event->hasConfig(); + } + + protected function hydrateObjectForm($object) + { + // Prepare the data that will hydrate the form + $data = array( + 'id' => $object->getId(), + 'name' => $object->getName(), + 'value' => $object->getValue(), + 'hidden' => $object->getHidden(), + 'secured' => $object->getSecured(), + 'locale' => $object->getLocale(), + 'title' => $object->getTitle(), + 'chapo' => $object->getChapo(), + 'description' => $object->getDescription(), + 'postscriptum' => $object->getPostscriptum() + ); + + // Setup the object form + return $this->createForm(AdminForm::CONFIG_MODIFICATION, "form", $data); + } + + protected function getObjectFromEvent($event) + { + return $event->hasConfig() ? $event->getConfig() : null; + } + + protected function getExistingObject() + { + $config = ConfigQuery::create() + ->findOneById($this->getRequest()->get('variable_id')); + + if (null !== $config) { + $config->setLocale($this->getCurrentEditionLocale()); + } + + return $config; + } + + /** + * @param Config $object + * @return string + */ + protected function getObjectLabel($object) + { + return $object->getName(); + } + + /** + * @param Config $object + * @return int + */ + protected function getObjectId($object) + { + return $object->getId(); + } + + protected function renderListTemplate($currentOrder) + { + return $this->render('variables', array('order' => $currentOrder)); + } + + protected function renderEditionTemplate() + { + return $this->render('variable-edit', array('variable_id' => $this->getRequest()->get('variable_id'))); + } + + protected function redirectToEditionTemplate() + { + return $this->generateRedirectFromRoute( + "admin.configuration.variables.update", + array('variable_id' => $this->getRequest()->get('variable_id')) + ); + } + + protected function redirectToListTemplate() + { + return $this->generateRedirectFromRoute('admin.configuration.variables.default'); + } + + /** + * Change values modified directly from the variable list + * + * @return \Thelia\Core\HttpFoundation\Response the response + */ + public function changeValuesAction() + { + // Check current user authorization + if (null !== $response = $this->checkAuth($this->resourceCode, array(), AccessManager::UPDATE)) { + return $response; + } + + $variables = $this->getRequest()->get('variable', array()); + + // Process all changed variables + foreach ($variables as $id => $value) { + $event = new ConfigUpdateEvent($id); + $event->setValue($value); + + $this->dispatch(TheliaEvents::CONFIG_SETVALUE, $event); + } + + return $this->generateRedirectFromRoute('admin.configuration.variables.default'); + } +} diff --git a/core/lib/Thelia/Controller/Admin/ConfigStoreController.php b/core/lib/Thelia/Controller/Admin/ConfigStoreController.php new file mode 100644 index 00000000..58ebca75 --- /dev/null +++ b/core/lib/Thelia/Controller/Admin/ConfigStoreController.php @@ -0,0 +1,137 @@ + + */ +class ConfigStoreController extends BaseAdminController +{ + protected function renderTemplate() + { + return $this->render('config-store'); + } + + public function defaultAction() + { + if (null !== $response = $this->checkAuth(AdminResources::STORE, array(), AccessManager::VIEW)) { + return $response; + } + + // The form is self-hydrated + $configStoreForm = $this->createForm(AdminForm::CONFIG_STORE); + + $this->getParserContext()->addForm($configStoreForm); + + 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() + { + if (null !== $response = $this->checkAuth(AdminResources::STORE, array(), AccessManager::UPDATE)) { + return $response; + } + + $error_msg = $ex = false; + $response = null; + $configStoreForm = $this->createForm(AdminForm::CONFIG_STORE); + + try { + $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(); + + // Update store + foreach ($data as $name => $value) { + if (!array_key_exists($name, $storeMediaList) && !$configStoreForm->isTemplateDefinedHiddenFieldName($name)) { + ConfigQuery::write($name, $value, false); + } + } + + $this->adminLogAppend(AdminResources::STORE, AccessManager::UPDATE, "Store configuration changed"); + + if ($this->getRequest()->get('save_mode') == 'stay') { + $response = $this->generateRedirectFromRoute('admin.configuration.store.default'); + } else { + $response = $this->generateSuccessRedirect($configStoreForm); + } + } catch (\Exception $ex) { + $error_msg = $ex->getMessage(); + } + + if (false !== $error_msg) { + $this->setupFormErrorContext( + $this->getTranslator()->trans("Store configuration failed."), + $error_msg, + $configStoreForm, + $ex + ); + + $response = $this->renderTemplate(); + } + + return $response; + } +} diff --git a/core/lib/Thelia/Controller/Admin/ConfigurationController.php b/core/lib/Thelia/Controller/Admin/ConfigurationController.php new file mode 100644 index 00000000..2e00866f --- /dev/null +++ b/core/lib/Thelia/Controller/Admin/ConfigurationController.php @@ -0,0 +1,33 @@ + + */ +class ConfigurationController extends BaseAdminController +{ + public function indexAction() + { + if (null !== $response = $this->checkAuth([AdminResources::CONFIG], [], [AccessManager::VIEW])) { + return $response; + } + + return $this->render('configuration'); + } +} diff --git a/core/lib/Thelia/Controller/Admin/ContentController.php b/core/lib/Thelia/Controller/Admin/ContentController.php new file mode 100644 index 00000000..bb17c2b7 --- /dev/null +++ b/core/lib/Thelia/Controller/Admin/ContentController.php @@ -0,0 +1,413 @@ + + */ +class ContentController extends AbstractSeoCrudController +{ + public function __construct() + { + parent::__construct( + 'content', + 'manual', + 'content_order', + AdminResources::CONTENT, + TheliaEvents::CONTENT_CREATE, + TheliaEvents::CONTENT_UPDATE, + TheliaEvents::CONTENT_DELETE, + TheliaEvents::CONTENT_TOGGLE_VISIBILITY, + TheliaEvents::CONTENT_UPDATE_POSITION, + TheliaEvents::CONTENT_UPDATE_SEO + ); + } + + /** + * controller adding content to additional folder + * + * @return mixed|\Thelia\Core\HttpFoundation\Response + */ + public function addAdditionalFolderAction() + { + // Check current user authorization + if (null !== $response = $this->checkAuth($this->resourceCode, array(), AccessManager::UPDATE)) { + return $response; + } + + $folder_id = \intval($this->getRequest()->request->get('additional_folder_id')); + + if ($folder_id > 0) { + $event = new ContentAddFolderEvent( + $this->getExistingObject(), + $folder_id + ); + + try { + $this->dispatch(TheliaEvents::CONTENT_ADD_FOLDER, $event); + } catch (\Exception $e) { + return $this->errorPage($e); + } + } + + return $this->redirectToEditionTemplate(); + } + + /** + * controller removing additional folder to a content + * + * @return mixed|\Thelia\Core\HttpFoundation\Response + */ + public function removeAdditionalFolderAction() + { + // Check current user authorization + if (null !== $response = $this->checkAuth($this->resourceCode, array(), AccessManager::UPDATE)) { + return $response; + } + + $folder_id = \intval($this->getRequest()->request->get('additional_folder_id')); + + if ($folder_id > 0) { + $event = new ContentRemoveFolderEvent( + $this->getExistingObject(), + $folder_id + ); + + try { + $this->dispatch(TheliaEvents::CONTENT_REMOVE_FOLDER, $event); + } catch (\Exception $e) { + return $this->errorPage($e); + } + } + + return $this->redirectToEditionTemplate(); + } + + /** + * Return the creation form for this object + */ + protected function getCreationForm() + { + return $this->createForm(AdminForm::CONTENT_CREATION); + } + + /** + * Return the update form for this object + */ + protected function getUpdateForm() + { + return $this->createForm(AdminForm::CONTENT_MODIFICATION); + } + + /** + * Hydrate the update form for this object, before passing it to the update template + * + * @param Content $object + * @return \Thelia\Form\ContentModificationForm + */ + protected function hydrateObjectForm($object) + { + // Hydrate the "SEO" tab form + $this->hydrateSeoForm($object); + + // Prepare the data that will hydrate the form + $data = array( + 'id' => $object->getId(), + 'locale' => $object->getLocale(), + 'title' => $object->getTitle(), + 'chapo' => $object->getChapo(), + 'description' => $object->getDescription(), + 'postscriptum' => $object->getPostscriptum(), + 'visible' => $object->getVisible() + ); + + // Setup the object form + return $this->createForm(AdminForm::CONTENT_MODIFICATION, "form", $data); + } + + /** + * Creates the creation event with the provided form data + * + * @param array $formData + * @return \Thelia\Core\Event\Content\ContentCreateEvent + */ + protected function getCreationEvent($formData) + { + $contentCreateEvent = new ContentCreateEvent(); + + $contentCreateEvent + ->setLocale($formData['locale']) + ->setDefaultFolder($formData['default_folder']) + ->setTitle($formData['title']) + ->setVisible($formData['visible']) + ; + + return $contentCreateEvent; + } + + /** + * Creates the update event with the provided form data + * + * @param array $formData + * @return \Thelia\Core\Event\Content\ContentUpdateEvent + */ + protected function getUpdateEvent($formData) + { + $contentUpdateEvent = new ContentUpdateEvent($formData['id']); + + $contentUpdateEvent + ->setLocale($formData['locale']) + ->setTitle($formData['title']) + ->setChapo($formData['chapo']) + ->setDescription($formData['description']) + ->setPostscriptum($formData['postscriptum']) + ->setVisible($formData['visible']) + ->setDefaultFolder($formData['default_folder']); + + return $contentUpdateEvent; + } + + /** + * Creates the delete event with the provided form data + */ + protected function getDeleteEvent() + { + return new ContentDeleteEvent($this->getRequest()->get('content_id')); + } + + /** + * Return true if the event contains the object, e.g. the action has updated the object in the event. + * + * @param \Thelia\Core\Event\Content\ContentEvent $event + * @return bool + */ + protected function eventContainsObject($event) + { + return $event->hasContent(); + } + + /** + * Get the created object from an event. + * + * @param $event \Thelia\Core\Event\Content\ContentEvent + * + * @return null|\Thelia\Model\Content + */ + protected function getObjectFromEvent($event) + { + return $event->getContent(); + } + + /** + * Load an existing object from the database + * + * @return \Thelia\Model\Content + */ + protected function getExistingObject() + { + $content = ContentQuery::create() + ->findOneById($this->getRequest()->get('content_id', 0)); + + if (null !== $content) { + $content->setLocale($this->getCurrentEditionLocale()); + } + + return $content; + } + + /** + * Returns the object label form the object event (name, title, etc.) + * + * @param Content $object + * + * @return string content title + * + */ + protected function getObjectLabel($object) + { + return $object->getTitle(); + } + + /** + * Returns the object ID from the object + * + * @param Content $object + * + * @return int content id + */ + protected function getObjectId($object) + { + return $object->getId(); + } + + protected function getFolderId() + { + $folderId = $this->getRequest()->get('folder_id', null); + + if (null === $folderId) { + $content = $this->getExistingObject(); + + if ($content) { + $folderId = $content->getDefaultFolderId(); + } + } + + return $folderId ?: 0; + } + + /** + * Render the main list template + * + * @param int $currentOrder , if any, null otherwise. + * @return \Thelia\Core\HttpFoundation\Response + */ + protected function renderListTemplate($currentOrder) + { + $this->getListOrderFromSession('content', 'content_order', 'manual'); + + return $this->render( + 'folders', + array( + 'content_order' => $currentOrder, + 'parent' => $this->getFolderId() + ) + ); + } + + protected function getEditionArguments() + { + return array( + 'content_id' => $this->getRequest()->get('content_id', 0), + 'current_tab' => $this->getRequest()->get('current_tab', 'general'), + 'folder_id' => $this->getFolderId(), + ); + } + + /** + * Render the edition template + */ + protected function renderEditionTemplate() + { + return $this->render('content-edit', $this->getEditionArguments()); + } + + /** + * Redirect to the edition template + */ + protected function redirectToEditionTemplate() + { + return $this->generateRedirectFromRoute( + 'admin.content.update', + [], + $this->getEditionArguments() + ); + } + + /** + * Redirect to the list template + */ + protected function redirectToListTemplate() + { + return $this->generateRedirectFromRoute( + 'admin.content.default', + ['parent' => $this->getFolderId()] + ); + } + + /** + * @param \Thelia\Core\Event\Content\ContentUpdateEvent $updateEvent + * @return Response|void + */ + protected function performAdditionalUpdateAction($updateEvent) + { + if ($this->getRequest()->get('save_mode') != 'stay') { + return $this->generateRedirectFromRoute( + 'admin.folders.default', + ['parent' => $this->getFolderId()] + ); + } else { + return null; + } + } + + /** + * Put in this method post object delete processing if required. + * + * @param \Thelia\Core\Event\Content\ContentDeleteEvent $deleteEvent the delete event + * @return Response a response, or null to continue normal processing + */ + protected function performAdditionalDeleteAction($deleteEvent) + { + return $this->generateRedirectFromRoute( + 'admin.folders.default', + ['parent' => $deleteEvent->getDefaultFolderId()] + ); + } + + /** + * @param $event \Thelia\Core\Event\UpdatePositionEvent + * @return null|Response + */ + protected function performAdditionalUpdatePositionAction($event) + { + if (null !== $content = ContentQuery::create()->findPk($event->getObjectId())) { + // Redirect to parent category list + return $this->generateRedirectFromRoute( + 'admin.folders.default', + ['parent' => $event->getReferrerId()] + ); + } else { + return null; + } + } + + /** + * @param $positionChangeMode + * @param $positionValue + * @return UpdatePositionEvent|void + */ + protected function createUpdatePositionEvent($positionChangeMode, $positionValue) + { + return new UpdatePositionEvent( + $this->getRequest()->get('content_id', null), + $positionChangeMode, + $positionValue, + $this->getRequest()->get('folder_id', null) + ); + } + + /** + * @return ContentToggleVisibilityEvent|void + */ + protected function createToggleVisibilityEvent() + { + return new ContentToggleVisibilityEvent($this->getExistingObject()); + } +} diff --git a/core/lib/Thelia/Controller/Admin/CountryController.php b/core/lib/Thelia/Controller/Admin/CountryController.php new file mode 100644 index 00000000..8aa280e9 --- /dev/null +++ b/core/lib/Thelia/Controller/Admin/CountryController.php @@ -0,0 +1,344 @@ + + */ +class CountryController extends AbstractCrudController +{ + public function __construct() + { + parent::__construct( + 'country', + 'manual', + 'country_order', + AdminResources::COUNTRY, + TheliaEvents::COUNTRY_CREATE, + TheliaEvents::COUNTRY_UPDATE, + TheliaEvents::COUNTRY_DELETE, + TheliaEvents::COUNTRY_TOGGLE_VISIBILITY + ); + } + + /** + * Return the creation form for this object + */ + protected function getCreationForm() + { + return $this->createForm(AdminForm::COUNTRY_CREATION); + } + + /** + * Return the update form for this object + */ + protected function getUpdateForm() + { + return $this->createForm(AdminForm::COUNTRY_MODIFICATION); + } + + /** + * Hydrate the update form for this object, before passing it to the update template + * + * @param \Thelia\Model\Country $object + * @return BaseForm + */ + protected function hydrateObjectForm($object) + { + $data = array( + 'id' => $object->getId(), + 'locale' => $object->getLocale(), + 'visible' => $object->getVisible() ? true : false, + 'title' => $object->getTitle(), + 'chapo' => $object->getChapo(), + 'description' => $object->getDescription(), + 'postscriptum' => $object->getPostscriptum(), + 'isocode' => $object->getIsocode(), + 'isoalpha2' => $object->getIsoalpha2(), + 'isoalpha3' => $object->getIsoalpha3(), + 'has_states' => $object->getHasStates() ? true : false, + 'need_zip_code' => $object->getNeedZipCode() ? true : false, + 'zip_code_format' => $object->getZipCodeFormat(), + ); + + return $this->createForm(AdminForm::COUNTRY_MODIFICATION, 'form', $data); + } + + /** + * Creates the creation event with the provided form data + * + * @param array $formData + * @return CountryCreateEvent + */ + protected function getCreationEvent($formData) + { + $event = new CountryCreateEvent(); + + return $this->hydrateEvent($event, $formData); + } + + /** + * Creates the update event with the provided form data + * + * @param array $formData + * @return CountryUpdateEvent + */ + protected function getUpdateEvent($formData) + { + $event = new CountryUpdateEvent($formData['id']); + + $event = $this->hydrateEvent($event, $formData); + + $event + ->setChapo($formData['chapo']) + ->setDescription($formData['description']) + ->setPostscriptum($formData['postscriptum']) + ->setNeedZipCode($formData['need_zip_code']) + ->setZipCodeFormat($formData['zip_code_format']) + ; + + return $event; + } + + protected function hydrateEvent($event, $formData) + { + $event + ->setLocale($formData['locale']) + ->setVisible($formData['visible']) + ->setTitle($formData['title']) + ->setIsocode($formData['isocode']) + ->setIsoAlpha2($formData['isoalpha2']) + ->setIsoAlpha3($formData['isoalpha3']) + ->setHasStates($formData['has_states']) + ; + + return $event; + } + + /** + * Creates the delete event with the provided form data + */ + protected function getDeleteEvent() + { + return new CountryDeleteEvent($this->getRequest()->get('country_id')); + } + + /** + * Return true if the event contains the object, e.g. the action has updated the object in the event. + * + * @param unknown $event + */ + protected function eventContainsObject($event) + { + return $event->hasCountry(); + } + + /** + * Get the created object from an event. + * + * @param unknown $createEvent + * @return Country + */ + protected function getObjectFromEvent($event) + { + return $event->getCountry(); + } + + /** + * Load an existing object from the database + */ + protected function getExistingObject() + { + $country = CountryQuery::create() + ->findPk($this->getRequest()->get('country_id', 0)); + + if (null !== $country) { + $country->setLocale($this->getCurrentEditionLocale()); + } + + return $country; + } + + /** + * Returns the object label form the object event (name, title, etc.) + * + * @param \Thelia\Model\Country $object + * @return string + */ + protected function getObjectLabel($object) + { + return $object->getTitle(); + } + + /** + * Returns the object ID from the object + * + * @param \Thelia\Model\Country $object + * @return int + */ + protected function getObjectId($object) + { + return $object->getId(); + } + + /** + * Render the main list template + * + * @param unknown $currentOrder, if any, null otherwise. + * @return Response + */ + protected function renderListTemplate($currentOrder) + { + return $this->render("countries", array("display_country" => 20)); + } + + /** + * Render the edition template + */ + protected function renderEditionTemplate() + { + return $this->render('country-edit', $this->getEditionArgument()); + } + + protected function getEditionArgument() + { + return array( + 'country_id' => $this->getRequest()->get('country_id', 0) + ); + } + + /** + * Redirect to the edition template + */ + protected function redirectToEditionTemplate() + { + return $this->generateRedirectFromRoute( + 'admin.configuration.countries.update', + [], + [ + "country_id" => $this->getRequest()->get('country_id', 0) + ] + ); + } + + /** + * Redirect to the list template + */ + protected function redirectToListTemplate() + { + return $this->generateRedirectFromRoute('admin.configuration.countries.default'); + } + + public function toggleDefaultAction() + { + if (null !== $response = $this->checkAuth($this->resourceCode, array(), AccessManager::UPDATE)) { + return $response; + } + + if (null !== $country_id = $this->getRequest()->get('country_id')) { + $toogleDefaultEvent = new CountryToggleDefaultEvent($country_id); + try { + $this->dispatch(TheliaEvents::COUNTRY_TOGGLE_DEFAULT, $toogleDefaultEvent); + + if ($toogleDefaultEvent->hasCountry()) { + return $this->nullResponse(); + } + } catch (\Exception $ex) { + Tlog::getInstance()->error($ex->getMessage()); + } + } + + return $this->nullResponse(500); + } + + /** + * @return CountryToggleVisibilityEvent|void + */ + protected function createToggleVisibilityEvent() + { + return new CountryToggleVisibilityEvent($this->getExistingObject()); + } + + public function getDataAction($visible = true, $locale = null) + { + $response = $this->checkAuth($this->resourceCode, array(), AccessManager::VIEW); + if (null !== $response) { + return $response; + } + + if (null === $locale) { + $locale = $this->getCurrentEditionLocale(); + } + + $responseData = []; + + /** @var CountryQuery $search */ + $countries = CountryQuery::create() + ->_if($visible) + ->filterByVisible(true) + ->_endif() + ->joinWithI18n($locale) + ; + + /** @var Country $country */ + foreach ($countries as $country) { + $currentCountry = [ + 'id' => $country->getId(), + 'title' => $country->getTitle(), + 'hasStates' => $country->getHasStates(), + 'states' => [] + ]; + + if ($country->getHasStates()) { + $states = StateQuery::create() + ->filterByCountryId($country->getId()) + ->_if($visible) + ->filterByVisible(true) + ->_endif() + ->joinWithI18n($locale) + ; + + /** @var State $state */ + foreach ($states as $state) { + $currentCountry['states'][] = [ + 'id' => $state->getId(), + 'title' => $state->getTitle(), + ]; + } + } + + $responseData[] = $currentCountry; + } + + return $this->jsonResponse(json_encode($responseData)); + } +} diff --git a/core/lib/Thelia/Controller/Admin/CouponController.php b/core/lib/Thelia/Controller/Admin/CouponController.php new file mode 100644 index 00000000..d5459796 --- /dev/null +++ b/core/lib/Thelia/Controller/Admin/CouponController.php @@ -0,0 +1,884 @@ + + * + */ +class CouponController extends BaseAdminController +{ + /** + * Manage Coupons list display + * + * @return \Thelia\Core\HttpFoundation\Response + */ + public function browseAction() + { + if (null !== $response = $this->checkAuth(AdminResources::COUPON, [], AccessManager::VIEW)) { + return $response; + } + + return $this->render('coupon-list', [ + 'coupon_order' => $this->getListOrderFromSession('coupon', 'coupon_order', 'code') + ]); + } + + /** + * Manage Coupons creation display + * + * @return \Thelia\Core\HttpFoundation\Response + */ + public function createAction() + { + if (null !== $response = $this->checkAuth(AdminResources::COUPON, [], AccessManager::CREATE)) { + return $response; + } + + // Parameters given to the template + $args = []; + + $eventToDispatch = TheliaEvents::COUPON_CREATE; + + if ($this->getRequest()->isMethod('POST')) { + if (null !== $response = $this->validateCreateOrUpdateForm( + $eventToDispatch, + 'created', + 'creation' + )) { + return $response; + } + } else { + // If no input for expirationDate, now + 2 months + $defaultDate = new \DateTime(); + $args['nowDate'] = $defaultDate->format($this->getDefaultDateFormat()); + $args['defaultDate'] = $defaultDate->modify('+2 month')->format($this->getDefaultDateFormat()); + } + + $args['dateFormat'] = $this->getDefaultDateFormat(); + $args['availableCoupons'] = $this->getAvailableCoupons(); + $args['urlAjaxAdminCouponDrawInputs'] = $this->getRoute( + 'admin.coupon.draw.inputs.ajax', + ['couponServiceId' => 'couponServiceId'], + Router::ABSOLUTE_URL + ); + $args['formAction'] = 'admin/coupon/create'; + + // Setup empty data if form is already in parser context + $this->getParserContext()->addForm($this->createForm(AdminForm::COUPON_CREATION)); + + return $this->render( + 'coupon-create', + $args + ); + } + + /** + * Manage Coupons edition display + * + * @param int $couponId Coupon id + * + * @return \Thelia\Core\HttpFoundation\Response + */ + public function updateAction($couponId) + { + if (null !== $response = $this->checkAuth(AdminResources::COUPON, [], AccessManager::UPDATE)) { + return $response; + } + + /** @var Coupon $coupon */ + $coupon = CouponQuery::create()->findPk($couponId); + if (null === $coupon) { + return $this->pageNotFound(); + } + + $coupon->setLocale($this->getCurrentEditionLocale()); + + /** @var CouponFactory $couponFactory */ + $couponFactory = $this->container->get('thelia.coupon.factory'); + $couponManager = $couponFactory->buildCouponFromModel($coupon); + + // Parameters given to the template + $args = []; + + $eventToDispatch = TheliaEvents::COUPON_UPDATE; + + // Update + if ($this->getRequest()->isMethod('POST')) { + if (null !== $response = $this->validateCreateOrUpdateForm( + $eventToDispatch, + 'updated', + 'update', + $coupon + )) { + return $response; + } + } else { + // Display + // Prepare the data that will hydrate the form + /** @var ConditionFactory $conditionFactory */ + $conditionFactory = $this->container->get('thelia.condition.factory'); + $conditions = $conditionFactory->unserializeConditionCollection( + $coupon->getSerializedConditions() + ); + + $freeShippingForCountries = $freeShippingForModules = []; + + /** @var CouponCountry $item */ + foreach ($coupon->getFreeShippingForCountries() as $item) { + $freeShippingForCountries[] = $item->getCountryId(); + } + + /** @var CouponModule $item */ + foreach ($coupon->getFreeShippingForModules() as $item) { + $freeShippingForModules[] = $item->getModuleId(); + } + + if (empty($freeShippingForCountries)) { + $freeShippingForCountries[] = 0; + } + if (empty($freeShippingForModules)) { + $freeShippingForModules[] = 0; + } + + $data = [ + 'code' => $coupon->getCode(), + 'title' => $coupon->getTitle(), + 'amount' => $coupon->getAmount(), + 'type' => $coupon->getType(), + 'shortDescription' => $coupon->getShortDescription(), + 'description' => $coupon->getDescription(), + 'isEnabled' => $coupon->getIsEnabled(), + 'startDate' => $coupon->getStartDate($this->getDefaultDateFormat()), + 'expirationDate' => $coupon->getExpirationDate($this->getDefaultDateFormat()), + 'isAvailableOnSpecialOffers' => $coupon->getIsAvailableOnSpecialOffers(), + 'isCumulative' => $coupon->getIsCumulative(), + 'isRemovingPostage' => $coupon->getIsRemovingPostage(), + 'maxUsage' => $coupon->getMaxUsage(), + 'conditions' => $conditions, + 'locale' => $this->getCurrentEditionLocale(), + 'freeShippingForCountries' => $freeShippingForCountries, + 'freeShippingForModules' => $freeShippingForModules, + 'perCustomerUsageCount' => $coupon->getPerCustomerUsageCount(), + ]; + + $args['conditions'] = $this->cleanConditionForTemplate($conditions); + + // Setup the object form + $changeForm = $this->createForm(AdminForm::COUPON_CREATION, 'form', $data); + + // Pass it to the parser + $this->getParserContext()->addForm($changeForm); + } + + $args['couponCode'] = $coupon->getCode(); + $args['couponType'] = $coupon->getType(); + $args['availableCoupons'] = $this->getAvailableCoupons(); + $args['couponInputsHtml'] = $couponManager->drawBackOfficeInputs(); + $args['urlAjaxAdminCouponDrawInputs'] = $this->getRoute( + 'admin.coupon.draw.inputs.ajax', + ['couponServiceId' => 'couponServiceId'], + Router::ABSOLUTE_URL + ); + $args['availableConditions'] = $this->getAvailableConditions(); + $args['urlAjaxGetConditionInputFromServiceId'] = $this->getRoute( + 'admin.coupon.draw.condition.read.inputs.ajax', + ['conditionId' => 'conditionId'], + Router::ABSOLUTE_URL + ); + $args['urlAjaxGetConditionInputFromConditionInterface'] = $this->getRoute( + 'admin.coupon.draw.condition.update.inputs.ajax', + [ + 'couponId' => $couponId, + 'conditionIndex' => 8888888 + ], + Router::ABSOLUTE_URL + ); + + $args['urlAjaxSaveConditions'] = $this->getRoute( + 'admin.coupon.condition.save', + ['couponId' => $couponId], + Router::ABSOLUTE_URL + ); + $args['urlAjaxDeleteConditions'] = $this->getRoute( + 'admin.coupon.condition.delete', + [ + 'couponId' => $couponId, + 'conditionIndex' => 8888888 + ], + Router::ABSOLUTE_URL + ); + $args['urlAjaxGetConditionSummaries'] = $this->getRoute( + 'admin.coupon.draw.condition.summaries.ajax', + ['couponId' => $couponId], + Router::ABSOLUTE_URL + ); + + $args['formAction'] = 'admin/coupon/update/' . $couponId; + + $args['dateFormat'] = $this->getDefaultDateFormat(); + + $args['couponId'] = $couponId; + + return $this->render('coupon-update', $args); + } + + /** + * Manage Coupons read display + * + * @param string $conditionId Condition service id + * + * @return \Thelia\Core\HttpFoundation\Response + */ + public function getConditionEmptyInputAjaxAction($conditionId) + { + if (null !== $response = $this->checkAuth(AdminResources::COUPON, [], AccessManager::VIEW)) { + return $response; + } + + $this->checkXmlHttpRequest(); + + if (! empty($conditionId)) { + /** @var ConditionFactory $conditionFactory */ + $conditionFactory = $this->container->get('thelia.condition.factory'); + $inputs = $conditionFactory->getInputsFromServiceId($conditionId); + + if (!$this->container->has($conditionId)) { + return false; + } + + if ($inputs === null) { + return $this->pageNotFound(); + } + + /** @var ConditionInterface $condition */ + $condition = $this->container->get($conditionId); + + $html = $condition->drawBackOfficeInputs(); + $serviceId = $condition->getServiceId(); + } else { + $html = ''; + $serviceId = ''; + } + + return $this->render( + 'coupon/condition-input-ajax', + [ + 'inputsDrawn' => $html, + 'conditionServiceId' => $serviceId, + 'conditionIndex' => '' + ] + ); + } + + /** + * Manage Coupons read display + * + * @param int $couponId Coupon id being updated + * @param int $conditionIndex Coupon Condition position in the collection + * + * @return \Thelia\Core\HttpFoundation\Response + */ + public function getConditionToUpdateInputAjaxAction($couponId, $conditionIndex) + { + if (null !== $response = $this->checkAuth(AdminResources::COUPON, [], AccessManager::VIEW)) { + return $response; + } + + $this->checkXmlHttpRequest(); + + $search = CouponQuery::create(); + /** @var Coupon $coupon */ + $coupon = $search->findOneById($couponId); + if (!$coupon) { + return $this->pageNotFound(); + } + + /** @var CouponFactory $couponFactory */ + $couponFactory = $this->container->get('thelia.coupon.factory'); + $couponManager = $couponFactory->buildCouponFromModel($coupon); + + if (!$couponManager instanceof CouponInterface) { + return $this->pageNotFound(); + } + + $conditions = $couponManager->getConditions(); + if (!isset($conditions[$conditionIndex])) { + return $this->pageNotFound(); + } + /** @var ConditionInterface $condition */ + $condition = $conditions[$conditionIndex]; + + /** @var ConditionFactory $conditionFactory */ + $conditionFactory = $this->container->get('thelia.condition.factory'); + $inputs = $conditionFactory->getInputsFromConditionInterface($condition); + + if ($inputs === null) { + return $this->pageNotFound(); + } + + return $this->render( + 'coupon/condition-input-ajax', + [ + 'inputsDrawn' => $condition->drawBackOfficeInputs(), + 'conditionServiceId' => $condition->getServiceId(), + 'conditionIndex' => $conditionIndex, + ] + ); + } + + /** + * Manage Coupons read display + * + * @param int $couponId Coupon id + * + * @return \Thelia\Core\HttpFoundation\Response + */ + public function saveConditionsAction($couponId) + { + if (null !== $response = $this->checkAuth(AdminResources::COUPON, [], AccessManager::UPDATE)) { + return $response; + } + + $this->checkXmlHttpRequest(); + + $search = CouponQuery::create(); + /** @var Coupon $coupon */ + $coupon = $search->findOneById($couponId); + if (!$coupon) { + return $this->pageNotFound(); + } + + $conditionToSave = $this->buildConditionFromRequest(); + + /** @var CouponFactory $couponFactory */ + $couponFactory = $this->container->get('thelia.coupon.factory'); + $couponManager = $couponFactory->buildCouponFromModel($coupon); + + if (!$couponManager instanceof CouponInterface) { + return $this->pageNotFound(); + } + + $conditions = $couponManager->getConditions(); + $conditionIndex = $this->getRequest()->request->get('conditionIndex'); + if ($conditionIndex >= 0) { + // Update mode + $conditions[$conditionIndex] = $conditionToSave; + } else { + // Insert mode + $conditions[] = $conditionToSave; + } + $couponManager->setConditions($conditions); + + $this->manageConditionUpdate($coupon, $conditions); + + return new Response(); + } + + /** + * Manage Coupons condition deleteion + * + * @param int $couponId Coupon id + * @param int $conditionIndex Coupon condition index in the collection + * + * @return \Thelia\Core\HttpFoundation\Response + */ + public function deleteConditionsAction($couponId, $conditionIndex) + { + if (null !== $response = $this->checkAuth(AdminResources::COUPON, [], AccessManager::UPDATE)) { + return $response; + } + + $this->checkXmlHttpRequest(); + + $search = CouponQuery::create(); + /** @var Coupon $coupon */ + $coupon = $search->findOneById($couponId); + if (!$coupon) { + return $this->pageNotFound(); + } + + /** @var CouponFactory $couponFactory */ + $couponFactory = $this->container->get('thelia.coupon.factory'); + $couponManager = $couponFactory->buildCouponFromModel($coupon); + + if (!$couponManager instanceof CouponInterface) { + return $this->pageNotFound(); + } + + $conditions = $couponManager->getConditions(); + unset($conditions[$conditionIndex]); + $couponManager->setConditions($conditions); + + $this->manageConditionUpdate($coupon, $conditions); + + return new Response(); + } + + /** + * Log error message + * + * @param string $action Creation|Update|Delete + * @param string $message Message to log + * @param \Exception $e Exception to log + * + * @return $this + */ + protected function logError($action, $message, $e) + { + Tlog::getInstance()->error( + sprintf( + 'Error during Coupon ' . $action . ' process : %s. Exception was %s', + $message, + $e->getMessage() + ) + ); + + return $this; + } + + /** + * Validate the CreateOrUpdate form + * + * @param string $eventToDispatch Event which will activate actions + * @param string $log created|edited + * @param string $action creation|edition + * @param Coupon $model Model if in update mode + * + * @return $this + */ + protected function validateCreateOrUpdateForm($eventToDispatch, $log, $action, Coupon $model = null) + { + // Create the form from the request + $couponForm = $this->getForm($action, $model); + $response = null; + $message = false; + try { + // Check the form against conditions violations + $form = $this->validateForm($couponForm, 'POST'); + + $couponEvent = $this->feedCouponCreateOrUpdateEvent($form, $model); + + // Dispatch Event to the Action + $this->dispatch( + $eventToDispatch, + $couponEvent + ); + + $this->adminLogAppend( + AdminResources::COUPON, + AccessManager::UPDATE, + sprintf( + 'Coupon %s (ID ) ' . $log, + $couponEvent->getTitle(), + $couponEvent->getCouponModel()->getId() + ), + $couponEvent->getCouponModel()->getId() + ); + + if ($this->getRequest()->get('save_mode') == 'stay') { + $response = RedirectResponse::create(str_replace( + '{id}', + $couponEvent->getCouponModel()->getId(), + $couponForm->getSuccessUrl() + )); + } else { + // Redirect to the success URL + $response = RedirectResponse::create( + URL::getInstance()->absoluteUrl($this->getRoute('admin.coupon.list')) + ); + } + } catch (FormValidationException $ex) { + // Invalid data entered + $message = $this->createStandardFormValidationErrorMessage($ex); + } catch (\Exception $ex) { + // Any other error + $message = $this->getTranslator()->trans('Sorry, an error occurred: %err', ['%err' => $ex->getMessage()]); + + $this->logError($action, $message, $ex); + } + + if ($message !== false) { + // Mark the form as with error + $couponForm->setErrorMessage($message); + + // Send the form and the error to the parser + $this->getParserContext() + ->addForm($couponForm) + ->setGeneralError($message); + } + + return $response; + } + + /** + * Get all available conditions + * + * @return array + */ + protected function getAvailableConditions() + { + /** @var CouponManager $couponManager */ + $couponManager = $this->container->get('thelia.coupon.manager'); + $availableConditions = $couponManager->getAvailableConditions(); + $cleanedConditions = []; + /** @var ConditionInterface $availableCondition */ + foreach ($availableConditions as $availableCondition) { + $condition = []; + $condition['serviceId'] = $availableCondition->getServiceId(); + $condition['name'] = $availableCondition->getName(); + $condition['toolTip'] = $availableCondition->getToolTip(); + $cleanedConditions[] = $condition; + } + + return $cleanedConditions; + } + + /** + * Get all available coupons + * + * @return array + */ + protected function getAvailableCoupons() + { + /** @var CouponManager $couponManager */ + $couponManager = $this->container->get('thelia.coupon.manager'); + $availableCoupons = $couponManager->getAvailableCoupons(); + $cleanedCoupons = []; + /** @var CouponInterface $availableCoupon */ + foreach ($availableCoupons as $availableCoupon) { + $condition = []; + $condition['serviceId'] = $availableCoupon->getServiceId(); + $condition['name'] = $availableCoupon->getName(); + $condition['toolTip'] = $availableCoupon->getToolTip(); + + $cleanedCoupons[] = $condition; + } + + return $cleanedCoupons; + } + + /** + * Clean condition for template + * + * @param ConditionCollection $conditions Condition collection + * + * @return array + */ + protected function cleanConditionForTemplate(ConditionCollection $conditions) + { + $cleanedConditions = []; + /** @var $condition ConditionInterface */ + foreach ($conditions as $index => $condition) { + $temp = [ + 'serviceId' => $condition->getServiceId(), + 'index' => $index, + 'name' => $condition->getName(), + 'toolTip' => $condition->getToolTip(), + 'summary' => $condition->getSummary(), + 'validators' => $condition->getValidators() + ]; + $cleanedConditions[] = $temp; + } + + return $cleanedConditions; + } + + /** + * Draw the input displayed in the BackOffice + * allowing Admin to set its Coupon effect + * + * @param string $couponServiceId Coupon service id + * + * @return ResponseRest + */ + public function getBackOfficeInputsAjaxAction($couponServiceId) + { + if (null !== $response = $this->checkAuth(AdminResources::COUPON, [], AccessManager::VIEW)) { + return $response; + } + + if (! empty($couponServiceId)) { + $this->checkXmlHttpRequest(); + + /** @var CouponInterface $coupon */ + $couponManager = $this->container->get($couponServiceId); + + if (!$couponManager instanceof CouponInterface) { + $this->pageNotFound(); + } + + $response = new ResponseRest($couponManager->drawBackOfficeInputs(), 'text'); + } else { + // Return an empty response if the service ID is not defined + // Typically, when the user chooses "Please select a coupon type" + $response = new ResponseRest(''); + } + + return $response; + } + + /** + * Draw the input displayed in the BackOffice + * allowing Admin to set its Coupon effect + * + * @param int $couponId Coupon id + * + * @return ResponseRest + */ + public function getBackOfficeConditionSummariesAjaxAction($couponId) + { + if (null !== $response = $this->checkAuth(AdminResources::COUPON, [], AccessManager::VIEW)) { + return $response; + } + + $this->checkXmlHttpRequest(); + + /** @var Coupon $coupon */ + $coupon = CouponQuery::create()->findPk($couponId); + if (null === $coupon) { + return $this->pageNotFound(); + } + + /** @var CouponFactory $couponFactory */ + $couponFactory = $this->container->get('thelia.coupon.factory'); + $couponManager = $couponFactory->buildCouponFromModel($coupon); + + if (!$couponManager instanceof CouponInterface) { + return $this->pageNotFound(); + } + + $args = []; + $args['conditions'] = $this->cleanConditionForTemplate($couponManager->getConditions()); + + return $this->render('coupon/conditions', $args); + } + + /** + * Feed the Coupon Create or Update event with the User inputs + * + * @param Form $form Form containing user data + * @param Coupon $model Model if in update mode + * + * @return CouponCreateOrUpdateEvent + */ + protected function feedCouponCreateOrUpdateEvent(Form $form, Coupon $model = null) + { + // Get the form field values + $data = $form->getData(); + $serviceId = $data['type']; + + /** @var CouponInterface $coupon */ + $coupon = $this->container->get($serviceId); + + $couponEvent = new CouponCreateOrUpdateEvent( + $data['code'], + $serviceId, + $data['title'], + $coupon->getEffects($data), + $data['shortDescription'], + $data['description'], + $data['isEnabled'], + \DateTime::createFromFormat($this->getDefaultDateFormat(), $data['expirationDate']), + $data['isAvailableOnSpecialOffers'], + $data['isCumulative'], + $data['isRemovingPostage'], + $data['maxUsage'], + $data['locale'], + $data['freeShippingForCountries'], + $data['freeShippingForModules'], + $data['perCustomerUsageCount'], + empty($data['startDate']) ? null : \DateTime::createFromFormat($this->getDefaultDateFormat(), $data['startDate']) + ); + + // If Update mode + if (isset($model)) { + $couponEvent->setCouponModel($model); + } + + return $couponEvent; + } + + /** + * Build ConditionInterface from request + * + * @return ConditionInterface + */ + protected function buildConditionFromRequest() + { + $request = $this->getRequest(); + $post = $request->request->getIterator(); + $serviceId = $request->request->get('categoryCondition'); + $operators = []; + $values = []; + foreach ($post as $key => $input) { + if (isset($input['operator']) && isset($input['value'])) { + $operators[$key] = $input['operator']; + $values[$key] = $input['value']; + } + } + + /** @var ConditionFactory $conditionFactory */ + $conditionFactory = $this->container->get('thelia.condition.factory'); + $conditionToSave = $conditionFactory->build($serviceId, $operators, $values); + + return $conditionToSave; + } + + /** + * Manage how a Condition is updated + * + * @param Coupon $coupon Coupon Model + * @param ConditionCollection $conditions Condition collection + */ + protected function manageConditionUpdate(Coupon $coupon, ConditionCollection $conditions) + { + $couponEvent = new CouponCreateOrUpdateEvent( + $coupon->getCode(), + $coupon->getType(), + $coupon->getTitle(), + $coupon->getEffects(), + $coupon->getShortDescription(), + $coupon->getDescription(), + $coupon->getIsEnabled(), + $coupon->getExpirationDate(), + $coupon->getIsAvailableOnSpecialOffers(), + $coupon->getIsCumulative(), + $coupon->getIsRemovingPostage(), + $coupon->getMaxUsage(), + $coupon->getLocale(), + $coupon->getFreeShippingForCountries(), + $coupon->getFreeShippingForModules(), + $coupon->getPerCustomerUsageCount(), + $coupon->getStartDate() + ); + $couponEvent->setCouponModel($coupon); + $couponEvent->setConditions($conditions); + + $eventToDispatch = TheliaEvents::COUPON_CONDITION_UPDATE; + // Dispatch Event to the Action + $this->dispatch( + $eventToDispatch, + $couponEvent + ); + + $this->adminLogAppend( + AdminResources::COUPON, + AccessManager::UPDATE, + sprintf( + 'Coupon %s (ID %s) conditions updated', + $couponEvent->getCouponModel()->getTitle(), + $couponEvent->getCouponModel()->getType() + ), + $couponEvent->getCouponModel()->getId() + ); + } + + protected function getDefaultDateFormat() + { + return LangQuery::create()->findOneByByDefault(true)->getDatetimeFormat(); + } + + /** + * @param string $action + * @param Coupon|null $coupon + * @return \Thelia\Form\BaseForm + */ + protected function getForm($action, $coupon) + { + $data = array(); + + if (null !== $coupon) { + $data["code"] = $coupon->getCode(); + } + + return $this->createForm(AdminForm::COUPON_CREATION, "form", $data, [ + 'validation_groups' => ["Default", $action] + ]); + } + + public function deleteAction() + { + // Check current user authorization + if (null !== $response = $this->checkAuth(AdminResources::COUPON, [], AccessManager::DELETE)) { + return $response; + } + + try { + // Check token + $this->getTokenProvider()->checkToken( + $this->getRequest()->query->get("_token") + ); + + // Retrieve coupon + $coupon = CouponQuery::create() + ->findPk($couponId = $this->getRequest()->request->get("coupon_id")) + ; + $deleteEvent = new CouponDeleteEvent($couponId, $coupon); + + $this->dispatch(TheliaEvents::COUPON_DELETE, $deleteEvent); + + if (null !== $deletedObject = $deleteEvent->getCoupon()) { + $this->adminLogAppend( + AdminResources::COUPON, + AccessManager::DELETE, + sprintf( + "Coupon %s (ID %s) deleted", + $deletedObject->getCode(), + $deletedObject->getId() + ), + $deletedObject->getId() + ); + } + + return $response = RedirectResponse::create( + URL::getInstance()->absoluteUrl($this->getRoute('admin.coupon.list')) + ); + } catch (\Exception $e) { + $this->getParserContext() + ->setGeneralError($e->getMessage()) + ; + + return $this->browseAction(); + } + } +} diff --git a/core/lib/Thelia/Controller/Admin/CurrencyController.php b/core/lib/Thelia/Controller/Admin/CurrencyController.php new file mode 100644 index 00000000..b830ff0b --- /dev/null +++ b/core/lib/Thelia/Controller/Admin/CurrencyController.php @@ -0,0 +1,265 @@ + + */ +class CurrencyController extends AbstractCrudController +{ + public function __construct() + { + parent::__construct( + 'currency', + 'manual', + 'order', + AdminResources::CURRENCY, + TheliaEvents::CURRENCY_CREATE, + TheliaEvents::CURRENCY_UPDATE, + TheliaEvents::CURRENCY_DELETE, + null, // No visibility toggle + TheliaEvents::CURRENCY_UPDATE_POSITION + ); + } + + protected function getCreationForm() + { + return $this->createForm(AdminForm::CURRENCY_CREATION); + } + + protected function getUpdateForm() + { + return $this->createForm(AdminForm::CURRENCY_MODIFICATION); + } + + protected function getCreationEvent($formData) + { + $createEvent = new CurrencyCreateEvent(); + + $createEvent + ->setCurrencyName($formData['name']) + ->setLocale($formData["locale"]) + ->setSymbol($formData['symbol']) + ->setFormat($formData['format']) + ->setCode($formData['code']) + ->setRate($formData['rate']) + ; + + return $createEvent; + } + + protected function getUpdateEvent($formData) + { + $changeEvent = new CurrencyUpdateEvent($formData['id']); + + // Create and dispatch the change event + $changeEvent + ->setCurrencyName($formData['name']) + ->setLocale($formData["locale"]) + ->setSymbol($formData['symbol']) + ->setFormat($formData['format']) + ->setCode($formData['code']) + ->setRate($formData['rate']) + ; + + return $changeEvent; + } + + protected function createUpdatePositionEvent($positionChangeMode, $positionValue) + { + return new UpdatePositionEvent( + $this->getRequest()->get('currency_id', null), + $positionChangeMode, + $positionValue + ); + } + + protected function getDeleteEvent() + { + return new CurrencyDeleteEvent($this->getRequest()->get('currency_id')); + } + + protected function eventContainsObject($event) + { + return $event->hasCurrency(); + } + + protected function hydrateObjectForm($object) + { + // Prepare the data that will hydrate the form + $data = array( + 'id' => $object->getId(), + 'name' => $object->getName(), + 'locale' => $object->getLocale(), + 'code' => $object->getCode(), + 'symbol' => $object->getSymbol(), + 'format' => $object->getFormat(), + 'rate' => $object->getRate() + ); + + // Setup the object form + return $this->createForm(AdminForm::CURRENCY_MODIFICATION, "form", $data); + } + + protected function getObjectFromEvent($event) + { + return $event->hasCurrency() ? $event->getCurrency() : null; + } + + protected function getExistingObject() + { + $currency = CurrencyQuery::create() + ->findOneById($this->getRequest()->get('currency_id')); + + if (null !== $currency) { + $currency->setLocale($this->getCurrentEditionLocale()); + } + + return $currency; + } + + /** + * @param Currency $object + * @return string + */ + protected function getObjectLabel($object) + { + return $object->getName(); + } + + /** + * @param Currency $object + * @return int + */ + protected function getObjectId($object) + { + return $object->getId(); + } + + protected function renderListTemplate($currentOrder) + { + return $this->render('currencies', array('order' => $currentOrder)); + } + + protected function renderEditionTemplate() + { + return $this->render('currency-edit', array('currency_id' => $this->getRequest()->get('currency_id'))); + } + + protected function redirectToEditionTemplate() + { + return $this->generateRedirectFromRoute( + "admin.configuration.currencies.update", + [ + 'currency_id' => $this->getRequest()->get('currency_id'), + ] + ); + } + + protected function redirectToListTemplate() + { + return $this->generateRedirectFromRoute('admin.configuration.currencies.default'); + } + + /** + * Update currencies rates + */ + public function updateRatesAction() + { + // Check current user authorization + if (null !== $response = $this->checkAuth($this->resourceCode, array(), AccessManager::UPDATE)) { + return $response; + } + + try { + $event = new CurrencyUpdateRateEvent(); + + $this->dispatch(TheliaEvents::CURRENCY_UPDATE_RATES, $event); + + if ($event->hasUndefinedRates()) { + return $this->render('currencies', [ + 'undefined_rates' => $event->getUndefinedRates() + ]); + } + } catch (\Exception $ex) { + // Any error + return $this->errorPage($ex); + } + + return $this->redirectToListTemplate(); + } + + /** + * Sets the default currency + */ + public function setDefaultAction() + { + // Check current user authorization + if (null !== $response = $this->checkAuth($this->resourceCode, array(), AccessManager::UPDATE)) { + return $response; + } + + $changeEvent = new CurrencyUpdateEvent((int) $this->getRequest()->get('currency_id', 0)); + + // Create and dispatch the change event + $changeEvent->setIsDefault(true)->setVisible(1); + + try { + $this->dispatch(TheliaEvents::CURRENCY_SET_DEFAULT, $changeEvent); + } catch (\Exception $ex) { + // Any error + return $this->errorPage($ex); + } + + return $this->redirectToListTemplate(); + } + + /** + * Sets if the currency is visible for Front + */ + public function setVisibleAction() + { + // Check current user authorization + if (null !== $response = $this->checkAuth($this->resourceCode, array(), AccessManager::UPDATE)) { + return $response; + } + + $changeEvent = new CurrencyUpdateEvent((int) $this->getRequest()->get('currency_id', 0)); + + // Create and dispatch the change event + $changeEvent->setVisible((int) $this->getRequest()->get('visible', 0)); + + try { + $this->dispatch(TheliaEvents::CURRENCY_SET_VISIBLE, $changeEvent); + } catch (\Exception $ex) { + // Any error + return $this->errorPage($ex); + } + + return $this->redirectToListTemplate(); + } +} diff --git a/core/lib/Thelia/Controller/Admin/CustomerController.php b/core/lib/Thelia/Controller/Admin/CustomerController.php new file mode 100644 index 00000000..bc229e57 --- /dev/null +++ b/core/lib/Thelia/Controller/Admin/CustomerController.php @@ -0,0 +1,254 @@ + + */ +class CustomerController extends AbstractCrudController +{ + public function __construct() + { + parent::__construct( + 'customer', + 'lastname', + 'customer_order', + AdminResources::CUSTOMER, + TheliaEvents::CUSTOMER_CREATEACCOUNT, + TheliaEvents::CUSTOMER_UPDATEACCOUNT, + TheliaEvents::CUSTOMER_DELETEACCOUNT + ); + } + + protected function getCreationForm() + { + return $this->createForm(AdminForm::CUSTOMER_CREATE); + } + + protected function getUpdateForm() + { + return $this->createForm(AdminForm::CUSTOMER_UPDATE); + } + + protected function getCreationEvent($formData) + { + $event = $this->createEventInstance($formData); + + // Create a secure password + $event->setPassword(Password::generateRandom(8)); + + // We will notify the customer of account creation + $event->setNotifyCustomerOfAccountCreation(true); + + return $event; + } + + protected function getUpdateEvent($formData) + { + $event = $this->createEventInstance($formData); + + $event->setCustomer($this->getExistingObject()); + + // We allow customer email modification + $event->setEmailUpdateAllowed(true); + + return $event; + } + + protected function getDeleteEvent() + { + return new CustomerEvent($this->getExistingObject()); + } + + protected function eventContainsObject($event) + { + return $event->hasCustomer(); + } + + /** + * @param Customer $object + * @return \Thelia\Form\BaseForm + */ + protected function hydrateObjectForm($object) + { + // Get default adress of the customer + $address = $object->getDefaultAddress(); + + // Prepare the data that will hydrate the form + $data = array( + 'id' => $object->getId(), + 'firstname' => $object->getFirstname(), + 'lastname' => $object->getLastname(), + 'email' => $object->getEmail(), + 'lang_id' => $object->getLangId(), + 'title' => $object->getTitleId(), + 'discount' => $object->getDiscount(), + 'reseller' => $object->getReseller() ? true : false, + ); + + if ($address !== null) { + $data['company'] = $address->getCompany(); + $data['address1'] = $address->getAddress1(); + $data['address2'] = $address->getAddress2(); + $data['address3'] = $address->getAddress3(); + $data['phone'] = $address->getPhone(); + $data['cellphone'] = $address->getCellphone(); + $data['zipcode'] = $address->getZipcode(); + $data['city'] = $address->getCity(); + $data['country'] = $address->getCountryId(); + $data['state'] = $address->getStateId(); + } + + // A loop is used in the template + return $this->createForm(AdminForm::CUSTOMER_UPDATE, 'form', $data); + } + + protected function getObjectFromEvent($event) + { + return $event->hasCustomer() ? $event->getCustomer() : null; + } + + /** + * @param $data + * @return \Thelia\Core\Event\Customer\CustomerCreateOrUpdateEvent + */ + private function createEventInstance($data) + { + // Use current language if it is not defined in the form + if (empty($data["lang_id"])) { + $data["lang_id"] = $this->getSession()->getLang()->getId(); + } + + $customerCreateEvent = new CustomerCreateOrUpdateEvent( + $data["title"], + $data["firstname"], + $data["lastname"], + $data["address1"], + $data["address2"], + $data["address3"], + $data["phone"], + $data["cellphone"], + $data["zipcode"], + $data["city"], + $data["country"], + isset($data["email"])?$data["email"]:null, + isset($data["password"]) && ! empty($data["password"]) ? $data["password"]:null, + $data["lang_id"], + isset($data["reseller"])?$data["reseller"]:null, + isset($data["sponsor"])?$data["sponsor"]:null, + isset($data["discount"])?$data["discount"]:null, + isset($data["company"])?$data["company"]:null, + null, + $data["state"] + ); + + return $customerCreateEvent; + } + + protected function getExistingObject() + { + return CustomerQuery::create()->findPk($this->getRequest()->get('customer_id', 0)); + } + + /** + * @param Customer $object + * @return string + */ + protected function getObjectLabel($object) + { + return $object->getRef() . "(".$object->getLastname()." ".$object->getFirstname().")"; + } + + /** + * @param Customer $object + * @return int + */ + protected function getObjectId($object) + { + return $object->getId(); + } + + protected function getEditionArguments() + { + return array( + 'customer_id' => $this->getRequest()->get('customer_id', 0), + 'page' => $this->getRequest()->get('page', 1), + 'page_order' => $this->getRequest()->get('page_order', 1) + ); + } + + protected function renderListTemplate($currentOrder, $customParams = array()) + { + return $this->render( + 'customers', + array_merge(array( + 'customer_order' => $currentOrder, + 'page' => $this->getRequest()->get('page', 1) + ), $customParams) + ); + } + + protected function redirectToListTemplate() + { + return $this->generateRedirectFromRoute( + 'admin.customers', + [ + 'page' => $this->getRequest()->get('page', 1) + ] + ); + } + + protected function renderEditionTemplate() + { + return $this->render('customer-edit', $this->getEditionArguments()); + } + + protected function redirectToEditionTemplate() + { + return $this->generateRedirectFromRoute( + "admin.customer.update.view", + $this->getEditionArguments() + ); + } + + public function deleteAction() + { + $errorMsg = "No error."; + $removalError = false; + + try { + parent::deleteAction(); + } catch (CustomerException $e) { + $errorMsg = $e->getMessage(); + + $removalError = true; + } + + return $this->renderListTemplate($this->getCurrentListOrder(), [ + "removal_error" => $removalError, + "error_message" => $errorMsg + ]); + } +} diff --git a/core/lib/Thelia/Controller/Admin/ExportController.php b/core/lib/Thelia/Controller/Admin/ExportController.php new file mode 100644 index 00000000..47a0640c --- /dev/null +++ b/core/lib/Thelia/Controller/Admin/ExportController.php @@ -0,0 +1,249 @@ + + */ +class ExportController extends BaseAdminController +{ + /** + * Handle default action, that is, list available exports + * + * @param string $_view View to render + * + * @return \Thelia\Core\HttpFoundation\Response + */ + public function indexAction($_view = 'export') + { + $authResponse = $this->checkAuth([AdminResources::EXPORT], [], [AccessManager::VIEW]); + if ($authResponse !== null) { + return $authResponse; + } + + $this->getParserContext() + ->set('category_order', $this->getRequest()->query->get('category_order', 'manual')) + ->set('export_order', $this->getRequest()->query->get('export_order', 'manual')) + ; + + return $this->render($_view); + } + + /** + * Handle export position change action + * + * @return \Thelia\Core\HttpFoundation\Response|\Symfony\Component\HttpFoundation\RedirectResponse + */ + public function changeExportPositionAction() + { + $authResponse = $this->checkAuth([AdminResources::EXPORT], [], [AccessManager::UPDATE]); + if ($authResponse !== null) { + return $authResponse; + } + + $query = $this->getRequest()->query; + + $this->dispatch( + TheliaEvents::EXPORT_CHANGE_POSITION, + new UpdatePositionEvent( + $query->get('id'), + $this->matchPositionMode($query->get('mode')), + $query->get('value') + ) + ); + + return $this->generateRedirectFromRoute('export.list'); + } + + /** + * Handle export category position change action + * + * @return \Thelia\Core\HttpFoundation\Response|\Symfony\Component\HttpFoundation\RedirectResponse + */ + public function changeCategoryPositionAction() + { + $authResponse = $this->checkAuth([AdminResources::EXPORT], [], [AccessManager::UPDATE]); + if ($authResponse !== null) { + return $authResponse; + } + + $query = $this->getRequest()->query; + + $this->dispatch( + TheliaEvents::EXPORT_CATEGORY_CHANGE_POSITION, + new UpdatePositionEvent( + $query->get('id'), + $this->matchPositionMode($query->get('mode')), + $query->get('value') + ) + ); + + return $this->generateRedirectFromRoute('export.list'); + } + + /** + * Match position mode string against position mode constant value + * + * @param null|string $mode Position mode string + * + * @return integer Position mode constant value + */ + protected function matchPositionMode($mode) + { + if ($mode === 'up') { + return UpdatePositionEvent::POSITION_UP; + } + + if ($mode === 'down') { + return UpdatePositionEvent::POSITION_DOWN; + } + + return UpdatePositionEvent::POSITION_ABSOLUTE; + } + + /** + * Display export configuration view + * + * @param integer $id An export identifier + * + * @return \Thelia\Core\HttpFoundation\Response + */ + public function configureAction($id) + { + /** @var \Thelia\Handler\Exporthandler $exportHandler */ + $exportHandler = $this->container->get('thelia.export.handler'); + + $export = $exportHandler->getExport($id); + if ($export === null) { + return $this->pageNotFound(); + } + + // Render standard view or ajax one + $templateName = 'export-page'; + if ($this->getRequest()->isXmlHttpRequest()) { + $templateName = 'ajax/export-modal'; + } + + return $this->render( + $templateName, + [ + 'exportId' => $id, + 'hasImages' => $export->hasImages(), + 'hasDocuments' => $export->hasDocuments(), + 'useRange' => $export->useRangeDate() + ] + ); + } + + /** + * Handle export action + * + * @param integer $id An export identifier + * + * @return \Thelia\Core\HttpFoundation\Response|\Symfony\Component\HttpFoundation\BinaryFileResponse + */ + public function exportAction($id) + { + /** @var \Thelia\Handler\Exporthandler $exportHandler */ + $exportHandler = $this->container->get('thelia.export.handler'); + + $export = $exportHandler->getExport($id); + if ($export === null) { + return $this->pageNotFound(); + } + + $form = $this->createForm(AdminForm::EXPORT); + + try { + $validatedForm = $this->validateForm($form); + + set_time_limit(0); + + $lang = (new LangQuery)->findPk($validatedForm->get('language')->getData()); + + /** @var \Thelia\Core\Serializer\SerializerManager $serializerManager */ + $serializerManager = $this->container->get(RegisterSerializerPass::MANAGER_SERVICE_ID); + $serializer = $serializerManager->get($validatedForm->get('serializer')->getData()); + + $archiver = null; + if ($validatedForm->get('do_compress')->getData()) { + /** @var \Thelia\Core\Archiver\ArchiverManager $archiverManager */ + $archiverManager = $this->container->get(RegisterArchiverPass::MANAGER_SERVICE_ID); + $archiver = $archiverManager->get($validatedForm->get('archiver')->getData()); + } + + $rangeDate = null; + if ($validatedForm->get('range_date_start')->getData() + && $validatedForm->get('range_date_end')->getData() + ) { + $rangeDate = [ + 'start' => $validatedForm->get('range_date_start')->getData(), + 'end' =>$validatedForm->get('range_date_end')->getData() + ]; + } + + $exportEvent = $exportHandler->export( + $export, + $serializer, + $archiver, + $lang, + $validatedForm->get('images')->getData(), + $validatedForm->get('documents')->getData(), + $rangeDate + ); + + $contentType = $exportEvent->getSerializer()->getMimeType(); + $fileExt = $exportEvent->getSerializer()->getExtension(); + + if ($exportEvent->getArchiver() !== null) { + $contentType = $exportEvent->getArchiver()->getMimeType(); + $fileExt = $exportEvent->getArchiver()->getExtension(); + } + + $header = [ + 'Content-Type' => $contentType, + 'Content-Disposition' => sprintf( + '%s; filename="%s.%s"', + ResponseHeaderBag::DISPOSITION_ATTACHMENT, + $exportEvent->getExport()->getFileName(), + $fileExt + ) + ]; + + return new BinaryFileResponse($exportEvent->getFilePath(), 200, $header, false); + } catch (FormValidationException $e) { + $form->setErrorMessage($this->createStandardFormValidationErrorMessage($e)); + } catch (\Exception $e) { + $this->getParserContext()->setGeneralError($e->getMessage()); + } + + $this->getParserContext() + ->addForm($form) + ; + + return $this->configureAction($id); + } +} diff --git a/core/lib/Thelia/Controller/Admin/FeatureAvController.php b/core/lib/Thelia/Controller/Admin/FeatureAvController.php new file mode 100644 index 00000000..6da6d165 --- /dev/null +++ b/core/lib/Thelia/Controller/Admin/FeatureAvController.php @@ -0,0 +1,185 @@ + + */ +class FeatureAvController extends AbstractCrudController +{ + public function __construct() + { + parent::__construct( + 'featureav', + 'manual', + 'order', + AdminResources::FEATURE, + TheliaEvents::FEATURE_AV_CREATE, + TheliaEvents::FEATURE_AV_UPDATE, + TheliaEvents::FEATURE_AV_DELETE, + null, // No visibility toggle + TheliaEvents::FEATURE_AV_UPDATE_POSITION + ); + } + + protected function getCreationForm() + { + return $this->createForm(AdminForm::FEATURE_AV_CREATION); + } + + protected function getUpdateForm() + { + throw new \LogicException("Featiure Av. modification is not yet implemented"); + } + + protected function getCreationEvent($formData) + { + $createEvent = new FeatureAvCreateEvent(); + + $createEvent + ->setFeatureId($formData['feature_id']) + ->setTitle($formData['title']) + ->setLocale($formData["locale"]) + ; + + return $createEvent; + } + + protected function getUpdateEvent($formData) + { + $changeEvent = new FeatureAvUpdateEvent($formData['id']); + + // Create and dispatch the change event + $changeEvent + ->setLocale($formData["locale"]) + ->setTitle($formData['title']) + ->setChapo($formData['chapo']) + ->setDescription($formData['description']) + ->setPostscriptum($formData['postscriptum']) + ; + + return $changeEvent; + } + + protected function createUpdatePositionEvent($positionChangeMode, $positionValue) + { + return new UpdatePositionEvent( + $this->getRequest()->get('featureav_id', null), + $positionChangeMode, + $positionValue + ); + } + + protected function getDeleteEvent() + { + return new FeatureAvDeleteEvent($this->getRequest()->get('featureav_id')); + } + + protected function eventContainsObject($event) + { + return $event->hasFeatureAv(); + } + + protected function hydrateObjectForm($object) + { + throw new \LogicException("Feature Av. modification is not yet implemented"); + } + + protected function getObjectFromEvent($event) + { + return $event->hasFeatureAv() ? $event->getFeatureAv() : null; + } + + protected function getExistingObject() + { + $featureAv = FeatureAvQuery::create() + ->findOneById($this->getRequest()->get('featureav_id', 0)); + + if (null !== $featureAv) { + $featureAv->setLocale($this->getCurrentEditionLocale()); + } + + return $featureAv; + } + + /** + * @param FeatureAv $object + * @return string + */ + protected function getObjectLabel($object) + { + return $object->getTitle(); + } + + /** + * @param FeatureAv $object + * @return int + */ + protected function getObjectId($object) + { + return $object->getId(); + } + + protected function getViewArguments() + { + return array( + 'feature_id' => $this->getRequest()->get('feature_id'), + 'order' => $this->getCurrentListOrder() + ); + } + + protected function renderListTemplate($currentOrder) + { + // We always return to the feature edition form + return $this->render( + 'feature-edit', + $this->getViewArguments() + ); + } + + protected function renderEditionTemplate() + { + // We always return to the feature edition form + return $this->render('feature-edit', $this->getViewArguments()); + } + + protected function redirectToEditionTemplate() + { + // We always return to the feature edition form + return $this->generateRedirectFromRoute( + "admin.configuration.features.update", + $this->getViewArguments() + ); + } + + protected function redirectToListTemplate() + { + return $this->generateRedirectFromRoute( + "admin.configuration.features.update", + $this->getViewArguments() + ); + } +} diff --git a/core/lib/Thelia/Controller/Admin/FeatureController.php b/core/lib/Thelia/Controller/Admin/FeatureController.php new file mode 100644 index 00000000..9db76125 --- /dev/null +++ b/core/lib/Thelia/Controller/Admin/FeatureController.php @@ -0,0 +1,266 @@ + + */ +class FeatureController extends AbstractCrudController +{ + public function __construct() + { + parent::__construct( + 'feature', + 'manual', + 'order', + AdminResources::FEATURE, + TheliaEvents::FEATURE_CREATE, + TheliaEvents::FEATURE_UPDATE, + TheliaEvents::FEATURE_DELETE, + null, // No visibility toggle + TheliaEvents::FEATURE_UPDATE_POSITION + ); + } + + protected function getCreationForm() + { + return $this->createForm(AdminForm::FEATURE_CREATION); + } + + protected function getUpdateForm() + { + return $this->createForm(AdminForm::FEATURE_MODIFICATION); + } + + protected function getCreationEvent($formData) + { + $createEvent = new FeatureCreateEvent(); + + $createEvent + ->setTitle($formData['title']) + ->setLocale($formData["locale"]) + ->setAddToAllTemplates($formData['add_to_all']) + ; + + return $createEvent; + } + + protected function getUpdateEvent($formData) + { + $changeEvent = new FeatureUpdateEvent($formData['id']); + + // Create and dispatch the change event + $changeEvent + ->setLocale($formData["locale"]) + ->setTitle($formData['title']) + ->setChapo($formData['chapo']) + ->setDescription($formData['description']) + ->setPostscriptum($formData['postscriptum']) + ; + + return $changeEvent; + } + + /** + * Process the features values (fix it in future version to integrate it in the feature form as a collection) + * + * @see \Thelia\Controller\Admin\AbstractCrudController::performAdditionalUpdateAction() + */ + protected function performAdditionalUpdateAction($updateEvent) + { + $attr_values = $this->getRequest()->get('feature_values', null); + + if ($attr_values !== null) { + foreach ($attr_values as $id => $value) { + $event = new FeatureAvUpdateEvent($id); + + $event->setTitle($value); + $event->setLocale($this->getCurrentEditionLocale()); + + $this->dispatch(TheliaEvents::FEATURE_AV_UPDATE, $event); + } + } + + return null; + } + + protected function createUpdatePositionEvent($positionChangeMode, $positionValue) + { + return new UpdatePositionEvent( + $this->getRequest()->get('feature_id', null), + $positionChangeMode, + $positionValue + ); + } + + protected function getDeleteEvent() + { + return new FeatureDeleteEvent($this->getRequest()->get('feature_id')); + } + + protected function eventContainsObject($event) + { + return $event->hasFeature(); + } + + protected function hydrateObjectForm($object) + { + $data = array( + 'id' => $object->getId(), + 'locale' => $object->getLocale(), + 'title' => $object->getTitle(), + 'chapo' => $object->getChapo(), + 'description' => $object->getDescription(), + 'postscriptum' => $object->getPostscriptum() + ); + + // Setup the object form + return $this->createForm(AdminForm::FEATURE_MODIFICATION, "form", $data); + } + + protected function getObjectFromEvent($event) + { + return $event->hasFeature() ? $event->getFeature() : null; + } + + protected function getExistingObject() + { + $feature = FeatureQuery::create() + ->findOneById($this->getRequest()->get('feature_id', 0)); + + if (null !== $feature) { + $feature->setLocale($this->getCurrentEditionLocale()); + } + + return $feature; + } + + /** + * @param Feature $object + * @return string + */ + protected function getObjectLabel($object) + { + return $object->getTitle(); + } + + /** + * @param Feature $object + * @return int + */ + protected function getObjectId($object) + { + return $object->getId(); + } + + protected function renderListTemplate($currentOrder) + { + return $this->render('features', array('order' => $currentOrder)); + } + + protected function renderEditionTemplate() + { + return $this->render( + 'feature-edit', + array( + 'feature_id' => $this->getRequest()->get('feature_id'), + 'featureav_order' => $this->getFeatureAvListOrder() + ) + ); + } + + protected function redirectToEditionTemplate() + { + return $this->generateRedirectFromRoute( + "admin.configuration.features.update", + [ + 'feature_id' => $this->getRequest()->get('feature_id'), + 'featureav_order' => $this->getFeatureAvListOrder() + ] + ); + } + + protected function redirectToListTemplate() + { + return $this->generateRedirectFromRoute('admin.configuration.features.default'); + } + + /** + * Get the Feature value list order. + * + * @return string the current list order + */ + protected function getFeatureAvListOrder() + { + return $this->getListOrderFromSession( + 'featureav', + 'featureav_order', + 'manual' + ); + } + + /** + * Add or Remove from all product templates + */ + protected function addRemoveFromAllTemplates($eventType) + { + // Check current user authorization + if (null !== $response = $this->checkAuth($this->resourceCode, array(), AccessManager::UPDATE)) { + return $response; + } + + try { + if (null !== $object = $this->getExistingObject()) { + $event = new FeatureEvent($object); + + $this->dispatch($eventType, $event); + } + } catch (\Exception $ex) { + // Any error + return $this->errorPage($ex); + } + + return $this->redirectToListTemplate(); + } + + /** + * Remove from all product templates + */ + public function removeFromAllTemplates() + { + return $this->addRemoveFromAllTemplates(TheliaEvents::FEATURE_REMOVE_FROM_ALL_TEMPLATES); + } + + /** + * Add to all product templates + */ + public function addToAllTemplates() + { + return $this->addRemoveFromAllTemplates(TheliaEvents::FEATURE_ADD_TO_ALL_TEMPLATES); + } +} diff --git a/core/lib/Thelia/Controller/Admin/FileController.php b/core/lib/Thelia/Controller/Admin/FileController.php new file mode 100644 index 00000000..2976a862 --- /dev/null +++ b/core/lib/Thelia/Controller/Admin/FileController.php @@ -0,0 +1,866 @@ + + * + */ +class FileController extends BaseAdminController +{ + const MODULE_RIGHT = "thelia"; + + /** + * Get the FileManager + * + * @return FileManager + */ + public function getFileManager() + { + return $this->container->get('thelia.file_manager'); + } + + /** + * Manage how a file collection has to be saved + * + * @param int $parentId Parent id owning files being saved + * @param string $parentType Parent Type owning files being saved (product, category, content, etc.) + * @param string $objectType Object type, e.g. image or document + * @param array $validMimeTypes an array of valid mime types. If empty, any mime type is allowed. + * @param array $extBlackList an array of blacklisted extensions. + * @return Response + */ + public function saveFileAjaxAction( + $parentId, + $parentType, + $objectType, + $validMimeTypes = array(), + $extBlackList = array() + ) { + if (null !== $response = $this->checkAuth($this->getAdminResources()->getResource($parentType, static::MODULE_RIGHT), array(), AccessManager::UPDATE)) { + return $response; + } + + $this->checkXmlHttpRequest(); + + + if ($this->getRequest()->isMethod('POST')) { + /** @var UploadedFile $fileBeingUploaded */ + $fileBeingUploaded = $this->getRequest()->files->get('file'); + try { + $this->processFile( + $fileBeingUploaded, + $parentId, + $parentType, + $objectType, + $validMimeTypes, + $extBlackList + ); + } catch (ProcessFileException $e) { + return new ResponseRest($e->getMessage(), 'text', $e->getCode()); + } + + return new ResponseRest(array('status' => true, 'message' => '')); + } + + return new Response('', 404); + } + + /** + * Process file uploaded + * + * @param UploadedFile $fileBeingUploaded + * @param int $parentId + * @param string $parentType + * @param string $objectType + * @param array $validMimeTypes + * @param array $extBlackList + * @return ResponseRest + * + * @deprecated since version 2.3, to be removed in 2.6. Please use the process method File present in the same class. + */ + public function processImage( + $fileBeingUploaded, + $parentId, + $parentType, + $objectType, + $validMimeTypes = array(), + $extBlackList = array() + ) { + @trigger_error('The '.__METHOD__.' method is deprecated since version 2.3 and will be removed in 2.6. Please use the process method File present in the same class.', E_USER_DEPRECATED); + + return $this->processFile($fileBeingUploaded, $parentId, $parentType, $objectType, $validMimeTypes, $extBlackList); + } + + /** + * Process file uploaded + * + * @param UploadedFile $fileBeingUploaded + * @param int $parentId Parent id owning files being saved + * @param string $parentType Parent Type owning files being saved (product, category, content, etc.) + * @param string $objectType Object type, e.g. image or document + * @param array $validMimeTypes an array of valid mime types. If empty, any mime type is allowed. + * @param array $extBlackList an array of blacklisted extensions. + * @return ResponseRest + * + * @since 2.3 + */ + public function processFile( + $fileBeingUploaded, + $parentId, + $parentType, + $objectType, + $validMimeTypes = array(), + $extBlackList = array() + ) { + $fileManager = $this->getFileManager(); + + // Validate if file is too big + if ($fileBeingUploaded->getError() == 1) { + $message = $this->getTranslator() + ->trans( + 'File is too large, please retry with a file having a size less than %size%.', + array('%size%' => ini_get('upload_max_filesize')), + 'core' + ); + + throw new ProcessFileException($message, 403); + } + + $message = null; + $realFileName = $fileBeingUploaded->getClientOriginalName(); + + if (! empty($validMimeTypes)) { + $mimeType = $fileBeingUploaded->getMimeType(); + + if (!isset($validMimeTypes[$mimeType])) { + $message = $this->getTranslator() + ->trans( + 'Only files having the following mime type are allowed: %types%', + [ '%types%' => implode(', ', array_keys($validMimeTypes))] + ); + } else { + $regex = "#^(.+)\.(".implode("|", $validMimeTypes[$mimeType]).")$#i"; + + if (!preg_match($regex, $realFileName)) { + $message = $this->getTranslator() + ->trans( + "There's a conflict between your file extension \"%ext\" and the mime type \"%mime\"", + [ + '%mime' => $mimeType, + '%ext' => $fileBeingUploaded->getClientOriginalExtension() + ] + ); + } + } + } + + if (!empty($extBlackList)) { + $regex = "#^(.+)\.(".implode("|", $extBlackList).")$#i"; + + if (preg_match($regex, $realFileName)) { + $message = $this->getTranslator() + ->trans( + 'Files with the following extension are not allowed: %extension, please do an archive of the file if you want to upload it', + [ + '%extension' => $fileBeingUploaded->getClientOriginalExtension(), + ] + ); + } + } + + if ($message !== null) { + throw new ProcessFileException($message, 415); + } + + $fileModel = $fileManager->getModelInstance($objectType, $parentType); + + $parentModel = $fileModel->getParentFileModel(); + + if ($parentModel === null || $fileModel === null || $fileBeingUploaded === null) { + throw new ProcessFileException('', 404); + } + + $defaultTitle = $parentModel->getTitle(); + + if (empty($defaultTitle) && $objectType !== 'image') { + $defaultTitle = $fileBeingUploaded->getClientOriginalName(); + } + + $fileModel + ->setParentId($parentId) + ->setLocale(Lang::getDefaultLanguage()->getLocale()) + ->setTitle($defaultTitle) + ; + + $fileCreateOrUpdateEvent = new FileCreateOrUpdateEvent($parentId); + $fileCreateOrUpdateEvent->setModel($fileModel); + $fileCreateOrUpdateEvent->setUploadedFile($fileBeingUploaded); + $fileCreateOrUpdateEvent->setParentName($parentModel->getTitle()); + + // Dispatch Event to the Action + $this->dispatch( + TheliaEvents::IMAGE_SAVE, + $fileCreateOrUpdateEvent + ); + + $this->adminLogAppend( + $this->getAdminResources()->getResource($parentType, static::MODULE_RIGHT), + AccessManager::UPDATE, + $this->getTranslator()->trans( + 'Saving %obj% for %parentName% parent id %parentId%', + array( + '%parentName%' => $fileCreateOrUpdateEvent->getParentName(), + '%parentId%' => $fileCreateOrUpdateEvent->getParentId(), + '%obj%' => $objectType + ) + ) + ); + + //return new ResponseRest(array('status' => true, 'message' => '')); + return $fileCreateOrUpdateEvent; + } + + /** + * Manage how a image collection has to be saved + * + * @param int $parentId Parent id owning images being saved + * @param string $parentType Parent Type owning images being saved + * + * @return Response + */ + public function saveImageAjaxAction($parentId, $parentType) + { + $config = FileConfiguration::getImageConfig(); + return $this->saveFileAjaxAction( + $parentId, + $parentType, + $config['objectType'], + $config['validMimeTypes'], + $config['extBlackList'] + ); + } + + /** + * Manage how a document collection has to be saved + * + * @param int $parentId Parent id owning documents being saved + * @param string $parentType Parent Type owning documents being saved + * + * @return Response + */ + public function saveDocumentAjaxAction($parentId, $parentType) + { + $config = FileConfiguration::getDocumentConfig(); + return $this->saveFileAjaxAction( + $parentId, + $parentType, + $config['objectType'], + $config['validMimeTypes'], + $config['extBlackList'] + ); + } + + /** + * Manage how a image list will be displayed in AJAX + * + * @param int $parentId Parent id owning images being saved + * @param string $parentType Parent Type owning images being saved + * + * @return Response + */ + public function getImageListAjaxAction($parentId, $parentType) + { + $this->checkAuth($this->getAdminResources()->getResource($parentType, static::MODULE_RIGHT), array(), AccessManager::UPDATE); + $this->checkXmlHttpRequest(); + + $successUrl = $this->getRequest()->get('successUrl'); + + $args = [ + 'imageType' => $parentType, + 'parentId' => $parentId, + 'successUrl' => $successUrl + ]; + + return $this->render('includes/image-upload-list-ajax', $args); + } + + /** + * Manage how a document list will be displayed in AJAX + * + * @param int $parentId Parent id owning documents being saved + * @param string $parentType Parent Type owning documents being saved + * + * @return Response + */ + public function getDocumentListAjaxAction($parentId, $parentType) + { + $this->checkAuth($this->getAdminResources()->getResource($parentType, static::MODULE_RIGHT), array(), AccessManager::UPDATE); + $this->checkXmlHttpRequest(); + $args = array('documentType' => $parentType, 'parentId' => $parentId); + + return $this->render('includes/document-upload-list-ajax', $args); + } + + /** + * Manage how an image list will be uploaded in AJAX + * + * @param int $parentId Parent id owning images being saved + * @param string $parentType Parent Type owning images being saved + * + * @return Response + */ + public function getImageFormAjaxAction($parentId, $parentType) + { + $this->checkAuth($this->getAdminResources()->getResource($parentType, static::MODULE_RIGHT), array(), AccessManager::UPDATE); + $this->checkXmlHttpRequest(); + $successUrl = $this->getRequest()->get('successUrl'); + + $args = [ + 'imageType' => $parentType, + 'parentId' => $parentId, + 'successUrl' => $successUrl + ]; + + return $this->render('includes/image-upload-form', $args); + } + + /** + * Manage how an document list will be uploaded in AJAX + * + * @param int $parentId Parent id owning documents being saved + * @param string $parentType Parent Type owning documents being saved + * + * @return Response + */ + public function getDocumentFormAjaxAction($parentId, $parentType) + { + $this->checkAuth($this->getAdminResources()->getResource($parentType, static::MODULE_RIGHT), array(), AccessManager::UPDATE); + $this->checkXmlHttpRequest(); + $args = array('documentType' => $parentType, 'parentId' => $parentId); + + return $this->render('includes/document-upload-form', $args); + } + + /** + * Manage how an image is viewed + * + * @param int $imageId Parent id owning images being saved + * @param string $parentType Parent Type owning images being saved + * + * @return Response + */ + public function viewImageAction($imageId, $parentType) + { + if (null !== $response = $this->checkAuth($this->getAdminResources()->getResource($parentType, static::MODULE_RIGHT), array(), AccessManager::UPDATE)) { + return $response; + } + $fileManager = $this->getFileManager(); + $imageModel = $fileManager->getModelInstance('image', $parentType); + + $image = $imageModel->getQueryInstance()->findPk($imageId); + + $redirectUrl = $image->getRedirectionUrl(); + + return $this->render('image-edit', array( + 'imageId' => $imageId, + 'imageType' => $parentType, + 'redirectUrl' => $redirectUrl, + 'formId' => $imageModel->getUpdateFormId(), + 'breadcrumb' => $image->getBreadcrumb( + $this->getRouter($this->getCurrentRouter()), + $this->container, + 'images', + $this->getCurrentEditionLocale() + ) + )); + } + + /** + * Manage how an document is viewed + * + * @param int $documentId Parent id owning images being saved + * @param string $parentType Parent Type owning images being saved + * + * @return Response + */ + public function viewDocumentAction($documentId, $parentType) + { + if (null !== $response = $this->checkAuth($this->getAdminResources()->getResource($parentType, static::MODULE_RIGHT), array(), AccessManager::UPDATE)) { + return $response; + } + + $fileManager = $this->getFileManager(); + $documentModel = $fileManager->getModelInstance('document', $parentType); + + $document = $documentModel->getQueryInstance()->findPk($documentId); + + $redirectUrl = $document->getRedirectionUrl(); + + return $this->render('document-edit', array( + 'documentId' => $documentId, + 'documentType' => $parentType, + 'redirectUrl' => $redirectUrl, + 'formId' => $documentModel->getUpdateFormId(), + 'breadcrumb' => $document->getBreadcrumb( + $this->getRouter($this->getCurrentRouter()), + $this->container, + 'documents', + $this->getCurrentEditionLocale() + ) + )); + } + + /** + * Manage how a file is updated + * + * @param int $fileId File identifier + * @param string $parentType Parent Type owning file being saved + * @param string $objectType the type of the file, image or document + * @param string $eventName the event type. + * + * @return FileModelInterface + */ + protected function updateFileAction($fileId, $parentType, $objectType, $eventName) + { + $message = false; + + $fileManager = $this->getFileManager(); + + $fileModelInstance = $fileManager->getModelInstance($objectType, $parentType); + + $fileUpdateForm = $this->createForm($fileModelInstance->getUpdateFormId()); + + /** @var FileModelInterface $file */ + $file = $fileModelInstance->getQueryInstance()->findPk($fileId); + + try { + $oldFile = clone $file; + + if (null === $file) { + throw new \InvalidArgumentException(sprintf('%d %s id does not exist', $fileId, $objectType)); + } + + $data = $this->validateForm($fileUpdateForm)->getData(); + + $event = new FileCreateOrUpdateEvent(null); + + if (array_key_exists('visible', $data)) { + $file->setVisible($data['visible'] ? 1 : 0); + } + + $file->setLocale($data['locale']); + + if (array_key_exists('title', $data)) { + $file->setTitle($data['title']); + } + if (array_key_exists('chapo', $data)) { + $file->setChapo($data['chapo']); + } + if (array_key_exists('description', $data)) { + $file->setDescription($data['description']); + } + if (array_key_exists('postscriptum', $data)) { + $file->setPostscriptum($data['postscriptum']); + } + + if (isset($data['file'])) { + $file->setFile($data['file']); + } + + $event->setModel($file); + $event->setOldModel($oldFile); + + $files = $this->getRequest()->files; + + $fileForm = $files->get($fileUpdateForm->getName()); + + if (isset($fileForm['file'])) { + $event->setUploadedFile($fileForm['file']); + } + + $this->dispatch($eventName, $event); + + $fileUpdated = $event->getModel(); + + $this->adminLogAppend( + $this->getAdminResources()->getResource($parentType, static::MODULE_RIGHT), + AccessManager::UPDATE, + sprintf( + '%s with Ref %s (ID %d) modified', + ucfirst($objectType), + $fileUpdated->getTitle(), + $fileUpdated->getId() + ), + $fileUpdated->getId() + ); + + if ($this->getRequest()->get('save_mode') == 'close') { + if ($objectType == 'document') { + $tab = 'documents'; + } else { + $tab = 'images'; + } + + return $this->generateRedirect( + URL::getInstance()->absoluteUrl($file->getRedirectionUrl(), ['current_tab' => $tab]) + ); + } else { + return $this->generateSuccessRedirect($fileUpdateForm); + } + } catch (FormValidationException $e) { + $message = sprintf('Please check your input: %s', $e->getMessage()); + } catch (PropelException $e) { + $message = $e->getMessage(); + } catch (\Exception $e) { + $message = sprintf('Sorry, an error occurred: %s', $e->getMessage().' '.$e->getFile()); + } + + if ($message !== false) { + Tlog::getInstance()->error(sprintf('Error during %s editing : %s.', $objectType, $message)); + + $fileUpdateForm->setErrorMessage($message); + + $this->getParserContext() + ->addForm($fileUpdateForm) + ->setGeneralError($message); + } + + return $file; + } + + /** + * Manage how an image is updated + * + * @param int $imageId Parent id owning images being saved + * @param string $parentType Parent Type owning images being saved + * + * @return Response + */ + public function updateImageAction($imageId, $parentType) + { + if (null !== $response = $this->checkAuth($this->getAdminResources()->getResource($parentType, static::MODULE_RIGHT), array(), AccessManager::UPDATE)) { + return $response; + } + + $imageInstance = $this->updateFileAction($imageId, $parentType, 'image', TheliaEvents::IMAGE_UPDATE); + + if ($imageInstance instanceof \Symfony\Component\HttpFoundation\Response) { + return $imageInstance; + } else { + return $this->render('image-edit', array( + 'imageId' => $imageId, + 'imageType' => $parentType, + 'redirectUrl' => $imageInstance->getRedirectionUrl(), + 'formId' => $imageInstance->getUpdateFormId() + )); + } + } + + /** + * Manage how an document is updated + * + * @param int $documentId Parent id owning documents being saved + * @param string $parentType Parent Type owning documents being saved + * + * @return Response + */ + public function updateDocumentAction($documentId, $parentType) + { + if (null !== $response = $this->checkAuth($this->getAdminResources()->getResource($parentType, static::MODULE_RIGHT), array(), AccessManager::UPDATE)) { + return $response; + } + + $documentInstance = $this->updateFileAction($documentId, $parentType, 'document', TheliaEvents::DOCUMENT_UPDATE); + + if ($documentInstance instanceof \Symfony\Component\HttpFoundation\Response) { + return $documentInstance; + } else { + return $this->render('document-edit', array( + 'documentId' => $documentId, + 'documentType' => $parentType, + 'redirectUrl' => $documentInstance->getRedirectionUrl(), + 'formId' => $documentInstance->getUpdateFormId() + )); + } + } + + /** + * Manage how a file has to be deleted + * + * @param int $fileId Parent id owning file being deleted + * @param string $parentType Parent Type owning file being deleted + * @param string $objectType the type of the file, image or document + * @param string $eventName the event type. + * + * @return Response + */ + public function deleteFileAction($fileId, $parentType, $objectType, $eventName) + { + $message = null; + + $this->checkAuth($this->getAdminResources()->getResource($parentType, static::MODULE_RIGHT), array(), AccessManager::UPDATE); + $this->checkXmlHttpRequest(); + + $fileManager = $this->getFileManager(); + $modelInstance = $fileManager->getModelInstance($objectType, $parentType); + + $model = $modelInstance->getQueryInstance()->findPk($fileId); + + if ($model == null) { + return $this->pageNotFound(); + } + + // Feed event + $fileDeleteEvent = new FileDeleteEvent($model); + + // Dispatch Event to the Action + try { + $this->dispatch($eventName, $fileDeleteEvent); + + $this->adminLogAppend( + $this->getAdminResources()->getResource($parentType, static::MODULE_RIGHT), + AccessManager::UPDATE, + $this->getTranslator()->trans( + 'Deleting %obj% for %id% with parent id %parentId%', + array( + '%obj%' => $objectType, + '%id%' => $fileDeleteEvent->getFileToDelete()->getId(), + '%parentId%' => $fileDeleteEvent->getFileToDelete()->getParentId(), + ) + ), + $fileDeleteEvent->getFileToDelete()->getId() + ); + } catch (\Exception $e) { + $message = $this->getTranslator()->trans( + 'Fail to delete %obj% for %id% with parent id %parentId% (Exception : %e%)', + array( + '%obj%' => $objectType, + '%id%' => $fileDeleteEvent->getFileToDelete()->getId(), + '%parentId%' => $fileDeleteEvent->getFileToDelete()->getParentId(), + '%e%' => $e->getMessage() + ) + ); + + $this->adminLogAppend( + $this->getAdminResources()->getResource($parentType, static::MODULE_RIGHT), + AccessManager::UPDATE, + $message, + $fileDeleteEvent->getFileToDelete()->getId() + ); + } + + if (null === $message) { + $message = $this->getTranslator()->trans( + '%obj%s deleted successfully', + ['%obj%' => ucfirst($objectType)], + 'image' + ); + } + + return new Response($message); + } + + /** + * Manage how an image has to be deleted (AJAX) + * + * @param int $imageId Parent id owning image being deleted + * @param string $parentType Parent Type owning image being deleted + * + * @return Response + */ + public function deleteImageAction($imageId, $parentType) + { + return $this->deleteFileAction($imageId, $parentType, 'image', TheliaEvents::IMAGE_DELETE); + } + + /** + * Manage how a document has to be deleted (AJAX) + * + * @param int $documentId Parent id owning document being deleted + * @param string $parentType Parent Type owning document being deleted + * + * @return Response + */ + public function deleteDocumentAction($documentId, $parentType) + { + return $this->deleteFileAction($documentId, $parentType, 'document', TheliaEvents::DOCUMENT_DELETE); + } + + public function updateFilePositionAction($parentType, $parentId, $objectType, $eventName) + { + $message = null; + + $position = $this->getRequest()->request->get('position'); + + $this->checkAuth($this->getAdminResources()->getResource($parentType, static::MODULE_RIGHT), array(), AccessManager::UPDATE); + $this->checkXmlHttpRequest(); + + $fileManager = $this->getFileManager(); + $modelInstance = $fileManager->getModelInstance($objectType, $parentType); + $model = $modelInstance->getQueryInstance()->findPk($parentId); + + if ($model === null || $position === null) { + return $this->pageNotFound(); + } + + // Feed event + $event = new UpdateFilePositionEvent( + $modelInstance->getQueryInstance($parentType), + $parentId, + UpdateFilePositionEvent::POSITION_ABSOLUTE, + $position + ); + + // Dispatch Event to the Action + try { + $this->dispatch($eventName, $event); + } catch (\Exception $e) { + $message = $this->getTranslator()->trans( + 'Fail to update %type% position: %err%', + [ '%type%' => $objectType, '%err%' => $e->getMessage() ] + ); + } + + if (null === $message) { + $message = $this->getTranslator()->trans( + '%type% position updated', + [ '%type%' => ucfirst($objectType) ] + ); + } + + return new Response($message); + } + + public function updateImageTitleAction($imageId, $parentType) + { + if (null !== $response = $this->checkAuth($this->getAdminResources()->getResource($parentType, static::MODULE_RIGHT), array(), AccessManager::UPDATE)) { + return $response; + } + + $fileManager = $this->getFileManager(); + + $fileModelInstance = $fileManager->getModelInstance('image', $parentType); + + /** @var FileModelInterface $file */ + $file = $fileModelInstance->getQueryInstance()->findPk($imageId); + + $new_title = $this->getRequest()->request->get('title'); + $locale = $this->getRequest()->request->get('locale'); + + if (!empty($new_title)) { + $file->setLocale($locale); + $file->setTitle($new_title); + $file->save(); + } + + return $this->generateRedirect( + URL::getInstance()->absoluteUrl($this->getRequest()->request->get('success_url'), ['current_tab' => 'images']) + ); + } + + public function updateImagePositionAction($parentType, /** @noinspection PhpUnusedParameterInspection */ $parentId) + { + $imageId = $this->getRequest()->request->get('image_id'); + + return $this->updateFilePositionAction($parentType, $imageId, 'image', TheliaEvents::IMAGE_UPDATE_POSITION); + } + + public function updateDocumentPositionAction($parentType, /** @noinspection PhpUnusedParameterInspection */ $parentId) + { + $documentId = $this->getRequest()->request->get('document_id'); + + return $this->updateFilePositionAction($parentType, $documentId, 'document', TheliaEvents::DOCUMENT_UPDATE_POSITION); + } + + public function toggleVisibilityFileAction($documentId, $parentType, $objectType, $eventName) + { + $message = null; + + //$position = $this->getRequest()->request->get('position'); + + $this->checkAuth($this->getAdminResources()->getResource($parentType, static::MODULE_RIGHT), array(), AccessManager::UPDATE); + $this->checkXmlHttpRequest(); + + $fileManager = $this->getFileManager(); + $modelInstance = $fileManager->getModelInstance($objectType, $parentType); + + $model = $modelInstance->getQueryInstance()->findPk($documentId); + + if ($model === null) { + return $this->pageNotFound(); + } + + // Feed event + $event = new FileToggleVisibilityEvent( + $modelInstance->getQueryInstance(), + $documentId + ); + + // Dispatch Event to the Action + try { + $this->dispatch($eventName, $event); + } catch (\Exception $e) { + $message = $this->getTranslator()->trans( + 'Fail to update %type% visibility: %err%', + [ '%type%' => $objectType, '%err%' => $e->getMessage() ] + ); + } + + if (null === $message) { + $message = $this->getTranslator()->trans( + '%type% visibility updated', + [ '%type%' => ucfirst($objectType) ] + ); + } + + return new Response($message); + } + + public function toggleVisibilityDocumentAction($parentType, $documentId) + { + return $this->toggleVisibilityFileAction($documentId, $parentType, 'document', TheliaEvents::DOCUMENT_TOGGLE_VISIBILITY); + } + + public function toggleVisibilityImageAction($parentType, $documentId) + { + return $this->toggleVisibilityFileAction($documentId, $parentType, 'image', TheliaEvents::IMAGE_TOGGLE_VISIBILITY); + } +} diff --git a/core/lib/Thelia/Controller/Admin/FolderController.php b/core/lib/Thelia/Controller/Admin/FolderController.php new file mode 100644 index 00000000..cfdd59a4 --- /dev/null +++ b/core/lib/Thelia/Controller/Admin/FolderController.php @@ -0,0 +1,337 @@ + + */ +class FolderController extends AbstractSeoCrudController +{ + public function __construct() + { + parent::__construct( + 'folder', + 'manual', + 'folder_order', + AdminResources::FOLDER, + TheliaEvents::FOLDER_CREATE, + TheliaEvents::FOLDER_UPDATE, + TheliaEvents::FOLDER_DELETE, + TheliaEvents::FOLDER_TOGGLE_VISIBILITY, + TheliaEvents::FOLDER_UPDATE_POSITION, + TheliaEvents::FOLDER_UPDATE_SEO + ); + } + + /** + * Return the creation form for this object + */ + protected function getCreationForm() + { + return $this->createForm(AdminForm::FOLDER_CREATION); + } + + /** + * Return the update form for this object + */ + protected function getUpdateForm() + { + return $this->createForm(AdminForm::FOLDER_MODIFICATION); + } + + /** + * Hydrate the update form for this object, before passing it to the update template + * + * @param \Thelia\Model\Folder $object + * @return BaseForm + */ + protected function hydrateObjectForm($object) + { + // Hydrate the "SEO" tab form + $this->hydrateSeoForm($object); + + // Prepare the data that will hydrate the form + $data = array( + 'id' => $object->getId(), + 'locale' => $object->getLocale(), + 'title' => $object->getTitle(), + 'chapo' => $object->getChapo(), + 'description' => $object->getDescription(), + 'postscriptum' => $object->getPostscriptum(), + 'visible' => $object->getVisible(), + 'parent' => $object->getParent() + ); + + // Setup the object form + return $this->createForm(AdminForm::FOLDER_MODIFICATION, "form", $data); + } + + /** + * Creates the creation event with the provided form data + * + * @param array $formData + * @return FolderCreateEvent + */ + protected function getCreationEvent($formData) + { + $creationEvent = new FolderCreateEvent(); + + $creationEvent + ->setLocale($formData['locale']) + ->setTitle($formData['title']) + ->setVisible($formData['visible']) + ->setParent($formData['parent']); + + return $creationEvent; + } + + /** + * Creates the update event with the provided form data + * + * @param array $formData + * @return FolderUpdateEvent + */ + protected function getUpdateEvent($formData) + { + $updateEvent = new FolderUpdateEvent($formData['id']); + + $updateEvent + ->setLocale($formData['locale']) + ->setTitle($formData['title']) + ->setChapo($formData['chapo']) + ->setDescription($formData['description']) + ->setPostscriptum($formData['postscriptum']) + ->setVisible($formData['visible']) + ->setParent($formData['parent']) + ; + + return $updateEvent; + } + + /** + * Creates the delete event with the provided form data + */ + protected function getDeleteEvent() + { + return new FolderDeleteEvent($this->getRequest()->get('folder_id'), 0); + } + + /** + * @return \Thelia\Core\Event\Folder\FolderToggleVisibilityEvent|void + */ + protected function createToggleVisibilityEvent() + { + return new FolderToggleVisibilityEvent($this->getExistingObject()); + } + + /** + * @param $positionChangeMode + * @param $positionValue + * @return UpdatePositionEvent|void + */ + protected function createUpdatePositionEvent($positionChangeMode, $positionValue) + { + return new UpdatePositionEvent( + $this->getRequest()->get('folder_id', null), + $positionChangeMode, + $positionValue + ); + } + + /** + * Return true if the event contains the object, e.g. the action has updated the object in the event. + * + * @param \Thelia\Core\Event\Folder\FolderEvent $event + * @return bool + */ + protected function eventContainsObject($event) + { + return $event->hasFolder(); + } + + /** + * Get the created object from an event. + * + * @param $event \Thelia\Core\Event\Folder\FolderEvent $event + * + * @return null|\Thelia\Model\Folder + */ + protected function getObjectFromEvent($event) + { + return $event->hasFolder() ? $event->getFolder() : null; + } + + /** + * Load an existing object from the database + */ + protected function getExistingObject() + { + $folder = FolderQuery::create() + ->findOneById($this->getRequest()->get('folder_id', 0)); + + if (null !== $folder) { + $folder->setLocale($this->getCurrentEditionLocale()); + } + + return $folder; + } + + /** + * Returns the object label form the object event (name, title, etc.) + * + * @param Folder $object + * @return string + */ + protected function getObjectLabel($object) + { + return $object->getTitle(); + } + + /** + * Returns the object ID from the object + * + * @param Folder $object + * @return int + */ + protected function getObjectId($object) + { + return $object->getId(); + } + + /** + * Render the main list template + * + * @param int $currentOrder, if any, null otherwise. + * @return Response + */ + protected function renderListTemplate($currentOrder) + { + // Get content order + $content_order = $this->getListOrderFromSession('content', 'content_order', 'manual'); + + return $this->render( + 'folders', + array( + 'folder_order' => $currentOrder, + 'content_order' => $content_order, + 'parent' => $this->getRequest()->get('parent', 0) + ) + ); + } + + /** + * Render the edition template + */ + protected function renderEditionTemplate() + { + return $this->render('folder-edit', $this->getEditionArguments()); + } + + protected function getEditionArguments(Request $request = null) + { + if (null === $request) { + $request = $this->getRequest(); + } + + return array( + 'folder_id' => $request->get('folder_id', 0), + 'current_tab' => $request->get('current_tab', 'general') + ); + } + + /** + * @param \Thelia\Core\Event\Folder\FolderUpdateEvent $updateEvent + * @return Response|void + */ + protected function performAdditionalUpdateAction($updateEvent) + { + if ($this->getRequest()->get('save_mode') != 'stay') { + return $this->generateRedirectFromRoute( + 'admin.folders.default', + ['parent' => $updateEvent->getFolder()->getParent()] + ); + } else { + return null; + } + } + + /** + * Put in this method post object delete processing if required. + * + * @param \Thelia\Core\Event\Folder\FolderDeleteEvent $deleteEvent the delete event + * @return Response a response, or null to continue normal processing + */ + protected function performAdditionalDeleteAction($deleteEvent) + { + return $this->generateRedirectFromRoute( + 'admin.folders.default', + ['parent' => $deleteEvent->getFolder()->getParent()] + ); + } + + /** + * @param $event \Thelia\Core\Event\UpdatePositionEvent + * @return null|Response + */ + protected function performAdditionalUpdatePositionAction($event) + { + $folder = FolderQuery::create()->findPk($event->getObjectId()); + + if ($folder != null) { + return $this->generateRedirectFromRoute( + 'admin.folders.default', + ['parent' => $folder->getParent()] + ); + } else { + return null; + } + } + + /** + * Redirect to the edition template + * + * @param Request|null $request + * @return Response + */ + protected function redirectToEditionTemplate(Request $request = null) + { + return $this->generateRedirectFromRoute('admin.folders.update', [], $this->getEditionArguments($request)); + } + + /** + * Redirect to the list template + */ + protected function redirectToListTemplate() + { + return $this->generateRedirectFromRoute( + 'admin.folders.default', + ['parent' => $this->getRequest()->get('parent', 0)] + ); + } +} diff --git a/core/lib/Thelia/Controller/Admin/HomeController.php b/core/lib/Thelia/Controller/Admin/HomeController.php new file mode 100644 index 00000000..4237009a --- /dev/null +++ b/core/lib/Thelia/Controller/Admin/HomeController.php @@ -0,0 +1,30 @@ +checkAuth(self::RESOURCE_CODE, array(), AccessManager::VIEW)) { + return $response; + } + + // Render the edition template. + return $this->render('home'); + } +} diff --git a/core/lib/Thelia/Controller/Admin/HookController.php b/core/lib/Thelia/Controller/Admin/HookController.php new file mode 100644 index 00000000..44b3947b --- /dev/null +++ b/core/lib/Thelia/Controller/Admin/HookController.php @@ -0,0 +1,474 @@ + + */ +class HookController extends AbstractCrudController +{ + public function __construct() + { + parent::__construct( + 'hook', + 'id', + 'order', + AdminResources::HOOK, + TheliaEvents::HOOK_CREATE, + TheliaEvents::HOOK_UPDATE, + TheliaEvents::HOOK_DELETE + ); + } + + public function indexAction() + { + if (null !== $response = $this->checkAuth(AdminResources::HOOK, [], AccessManager::VIEW)) { + return $response; + } + + return $this->renderList(); + } + + public function discoverAction() + { + if (null !== $response = $this->checkAuth(AdminResources::HOOK, [], AccessManager::VIEW)) { + return $response; + } + + $templateType = \intval($this->getRequest()->get("template_type", TemplateDefinition::FRONT_OFFICE)); + + $json_data = []; + try { + // parse the current template + $hookHelper = $this->container->get("thelia.hookHelper"); + $hooks = $hookHelper->parseActiveTemplate($templateType); + + // official hook + $allHooks = $this->getAllHooks($templateType); + + // diff + $newHooks = []; + $existingHooks = []; + foreach ($hooks as $hook) { + if (array_key_exists($hook["code"], $allHooks)) { + $existingHooks[] = $hook["code"]; + } else { + $newHooks[] = $hook; + } + } + + foreach ($existingHooks as $code) { + unset($allHooks[$code]); + } + + $json_data = [ + "success" => true, + "new" => $newHooks, + "missing" => $allHooks + ]; + + $response = JsonResponse::create($json_data); + } catch (\Exception $e) { + $response = JsonResponse::create(["error" => $e->getMessage()], 500); + } + + return $response; + } + + public function discoverSaveAction() + { + if (null !== $response = $this->checkAuth(AdminResources::HOOK, [], AccessManager::UPDATE)) { + return $response; + } + + $errors = []; + + $templateType = $this->getRequest()->request->get("templateType"); + + // new hooks in the template + if (null !== $newHooks = $this->getRequest()->request->get("new", null)) { + foreach ($newHooks as $hook) { + $event = $this->getDiscoverCreationEvent($hook, $templateType); + + $this->dispatch(TheliaEvents::HOOK_CREATE_ALL, $event); + + if (!$event->hasHook()) { + $errors[] = sprintf( + Translator::getInstance()->trans("Failed to create new hook %s"), + $hook["code"] + ); + } + } + } + + // missing official hooks + if (null !== $missingHooks = $this->getRequest()->request->get("missing")) { + foreach ($missingHooks as $hookId) { + $event = new HookDeactivationEvent($hookId); + + $this->dispatch(TheliaEvents::HOOK_DEACTIVATION, $event); + + if (!$event->hasHook()) { + $errors[] = sprintf( + Translator::getInstance()->trans("Failed to deactivate hook with id %s"), + $hookId + ); + } + } + } + + $json_data = [ + "success" => true + ]; + + if (\count($errors)) { + $response = JsonResponse::create(["error" => $errors], 500); + } else { + $response = JsonResponse::create($json_data); + } + + return $response; + } + + protected function getDiscoverCreationEvent($data, $type) + { + $event = new HookCreateAllEvent(); + + $event + ->setLocale(Lang::getDefaultLanguage()->getLocale()) + ->setType($type) + ->setCode($data['code']) + ->setNative(false) + ->setActive(true) + ->setTitle(($data['title'] != "") ? $data['title'] : $data['code']) + ->setByModule($data['module']) + ->setBlock($data['block']) + ->setChapo("") + ->setDescription(""); + + return $event; + } + + protected function getDeactivationEvent($code, $type) + { + $event = null; + + $hook_id = HookQuery::create() + ->filterByActivate(true, Criteria::EQUAL) + ->filterByType($type, Criteria::EQUAL) + ->filterByCode($code, Criteria::EQUAL) + ->select("Id") + ->findOne(); + + if (null !== $hook_id) { + $event = new HookDeactivationEvent($hook_id); + } + + return $event; + } + + protected function getAllHooks($templateType) + { + // get the all hooks + $hooks = HookQuery::create() + ->filterByType($templateType, Criteria::EQUAL) + ->find(); + + $ret = []; + /** @var Hook $hook */ + foreach ($hooks as $hook) { + $ret[$hook->getCode()] = [ + "id" => $hook->getId(), + "code" => $hook->getCode(), + "native" => $hook->getNative(), + "activate" => $hook->getActivate(), + "title" => $hook->getTitle() + ]; + } + + return $ret; + } + + /** + * Return the creation form for this object + */ + protected function getCreationForm() + { + return $this->createForm(AdminForm::HOOK_CREATION); + } + + /** + * Return the update form for this object + */ + protected function getUpdateForm() + { + return $this->createForm(AdminForm::HOOK_MODIFICATION); + } + + /** + * Hydrate the update form for this object, before passing it to the update template + * + * @param \Thelia\Model\Hook $object + * + * @return \Thelia\Form\HookModificationForm + */ + protected function hydrateObjectForm($object) + { + $data = [ + 'id' => $object->getId(), + 'code' => $object->getCode(), + 'type' => $object->getType(), + 'native' => $object->getNative(), + 'by_module' => $object->getByModule(), + 'block' => $object->getBlock(), + 'active' => $object->getActivate(), + 'locale' => $object->getLocale(), + 'title' => $object->getTitle(), + 'chapo' => $object->getChapo(), + 'description' => $object->getDescription(), + ]; + + return $this->createForm(AdminForm::HOOK_MODIFICATION, 'form', $data); + } + + /** + * Creates the creation event with the provided form data + * + * @param unknown $formData + */ + protected function getCreationEvent($formData) + { + $event = new HookCreateEvent(); + + return $this->hydrateEvent($event, $formData); + } + + /** + * Creates the update event with the provided form data + * + * @param unknown $formData + */ + protected function getUpdateEvent($formData) + { + $event = new HookUpdateEvent($formData['id']); + + return $this->hydrateEvent($event, $formData, true); + } + + protected function hydrateEvent($event, $formData, $update = false) + { + $event + ->setLocale($formData['locale']) + ->setType($formData['type']) + ->setCode($formData['code']) + ->setNative($formData['native']) + ->setActive($formData['active']) + ->setTitle($formData['title']); + if ($update) { + $event + ->setByModule($formData['by_module']) + ->setBlock($formData['block']) + ->setChapo($formData['chapo']) + ->setDescription($formData['description']); + } + + return $event; + } + + /** + * Creates the delete event with the provided form data + */ + protected function getDeleteEvent() + { + return new HookDeleteEvent($this->getRequest()->get('hook_id')); + } + + /** + * Return true if the event contains the object, e.g. the action has updated the object in the event. + * + * @param unknown $event + */ + protected function eventContainsObject($event) + { + return $event->hasHook(); + } + + /** + * Get the created object from an event. + * + * @param unknown $event + * + * @return + * @internal param \Thelia\Controller\Admin\unknown $createEvent + */ + protected function getObjectFromEvent($event) + { + return $event->getHook(); + } + + /** + * Load an existing object from the database + */ + protected function getExistingObject() + { + $hook = HookQuery::create() + ->findPk($this->getRequest()->get('hook_id', 0)); + + if (null !== $hook) { + $hook->setLocale($this->getCurrentEditionLocale()); + } + + return $hook; + } + + /** + * Returns the object label form the object event (name, title, etc.) + * + * @param \Thelia\Model\Hook $object + * + * @return string + */ + protected function getObjectLabel($object) + { + return $object->getTitle(); + } + + /** + * Returns the object ID from the object + * + * @param \Thelia\Model\Hook $object + * + * @return int + */ + protected function getObjectId($object) + { + return $object->getId(); + } + + /** + * Render the main list template + * + * @param unknown $currentOrder , if any, null otherwise. + */ + protected function renderListTemplate($currentOrder) + { + return $this->render("hooks", ['order' => $currentOrder]); + } + + /** + * Render the edition template + */ + protected function renderEditionTemplate() + { + return $this->render('hook-edit', $this->getEditionArgument()); + } + + protected function getEditionArgument() + { + return [ + 'hook_id' => $this->getRequest()->get('hook_id', 0) + ]; + } + + /** + * Redirect to the edition template + */ + protected function redirectToEditionTemplate() + { + return $this->generateRedirectFromRoute( + 'admin.hook.update', + [], + [ + "hook_id" => $this->getRequest()->get('hook_id', 0), + ] + ); + } + + /** + * Redirect to the list template + */ + protected function redirectToListTemplate() + { + return $this->generateRedirectFromRoute('admin.hook'); + } + + public function toggleNativeAction() + { + if (null !== $response = $this->checkAuth($this->resourceCode, [], AccessManager::UPDATE)) { + return $response; + } + + $content = null; + if (null !== $hook_id = $this->getRequest()->get('hook_id')) { + $toggleDefaultEvent = new HookToggleNativeEvent($hook_id); + try { + $this->dispatch(TheliaEvents::HOOK_TOGGLE_NATIVE, $toggleDefaultEvent); + + if ($toggleDefaultEvent->hasHook()) { + return $this->nullResponse(); + } + } catch (\Exception $ex) { + $content = $ex->getMessage(); + Tlog::getInstance()->debug(sprintf("%s", $content)); + } + } + + return $this->nullResponse(500); + } + + public function toggleActivationAction() + { + if (null !== $response = $this->checkAuth($this->resourceCode, [], AccessManager::UPDATE)) { + return $response; + } + + $content = null; + if (null !== $hook_id = $this->getRequest()->get('hook_id')) { + $toggleDefaultEvent = new HookToggleActivationEvent($hook_id); + try { + $this->dispatch(TheliaEvents::HOOK_TOGGLE_ACTIVATION, $toggleDefaultEvent); + + if ($toggleDefaultEvent->hasHook()) { + return $this->nullResponse(); + } + } catch (\Exception $ex) { + $content = $ex->getMessage(); + Tlog::getInstance()->debug(sprintf("%s", $content)); + } + } + + return $this->nullResponse(500); + } +} diff --git a/core/lib/Thelia/Controller/Admin/ImportController.php b/core/lib/Thelia/Controller/Admin/ImportController.php new file mode 100644 index 00000000..b2934f32 --- /dev/null +++ b/core/lib/Thelia/Controller/Admin/ImportController.php @@ -0,0 +1,242 @@ + + */ +class ImportController extends BaseAdminController +{ + /** + * Handle default action, that is, list available imports + * + * @param string $_view View to render + * + * @return \Thelia\Core\HttpFoundation\Response + */ + public function indexAction($_view = 'import') + { + $authResponse = $this->checkAuth([AdminResources::IMPORT], [], [AccessManager::VIEW]); + if ($authResponse !== null) { + return $authResponse; + } + + $this->getParserContext() + ->set('category_order', $this->getRequest()->query->get('category_order', 'manual')) + ->set('import_order', $this->getRequest()->query->get('import_order', 'manual')) + ; + + return $this->render($_view); + } + + /** + * Handle import position change action + * + * @return \Thelia\Core\HttpFoundation\Response|\Symfony\Component\HttpFoundation\RedirectResponse + */ + public function changeImportPositionAction() + { + $authResponse = $this->checkAuth([AdminResources::IMPORT], [], [AccessManager::UPDATE]); + if ($authResponse !== null) { + return $authResponse; + } + + $query = $this->getRequest()->query; + + $this->dispatch( + TheliaEvents::IMPORT_CHANGE_POSITION, + new UpdatePositionEvent( + $query->get('id'), + $this->matchPositionMode($query->get('mode')), + $query->get('value') + ) + ); + + return $this->generateRedirectFromRoute('import.list'); + } + + /** + * Handle import category position change action + * + * @return \Thelia\Core\HttpFoundation\Response|\Symfony\Component\HttpFoundation\RedirectResponse + */ + public function changeCategoryPositionAction() + { + $authResponse = $this->checkAuth([AdminResources::IMPORT], [], [AccessManager::UPDATE]); + if ($authResponse !== null) { + return $authResponse; + } + + $query = $this->getRequest()->query; + + $this->dispatch( + TheliaEvents::IMPORT_CATEGORY_CHANGE_POSITION, + new UpdatePositionEvent( + $query->get('id'), + $this->matchPositionMode($query->get('mode')), + $query->get('value') + ) + ); + + return $this->generateRedirectFromRoute('import.list'); + } + + /** + * Match position mode string against position mode constant value + * + * @param null|string $mode Position mode string + * + * @return integer Position mode constant value + */ + protected function matchPositionMode($mode) + { + if ($mode === 'up') { + return UpdatePositionEvent::POSITION_UP; + } + + if ($mode === 'down') { + return UpdatePositionEvent::POSITION_DOWN; + } + + return UpdatePositionEvent::POSITION_ABSOLUTE; + } + + /** + * Display import configuration view + * + * @param integer $id An import identifier + * + * @return \Thelia\Core\HttpFoundation\Response + */ + public function configureAction($id) + { + /** @var \Thelia\Handler\ImportHandler $importHandler */ + $importHandler = $this->container->get('thelia.import.handler'); + + $import = $importHandler->getImport($id); + if ($import === null) { + return $this->pageNotFound(); + } + + $extensions = []; + $mimeTypes = []; + + /** @var \Thelia\Core\Serializer\AbstractSerializer $serializer */ + foreach ($this->container->get(RegisterSerializerPass::MANAGER_SERVICE_ID)->getSerializers() as $serializer) { + $extensions[] = $serializer->getExtension(); + $mimeTypes[] = $serializer->getMimeType(); + } + + /** @var \Thelia\Core\Archiver\AbstractArchiver $archiver */ + foreach ($this->container->get(RegisterArchiverPass::MANAGER_SERVICE_ID)->getArchivers(true) as $archiver) { + $extensions[] = $archiver->getExtension(); + $mimeTypes[] = $archiver->getMimeType(); + } + + // Render standard view or ajax one + $templateName = 'import-page'; + if ($this->getRequest()->isXmlHttpRequest()) { + $templateName = 'ajax/import-modal'; + } + + return $this->render( + $templateName, + [ + 'importId' => $id, + 'ALLOWED_MIME_TYPES' => implode(', ', $mimeTypes), + 'ALLOWED_EXTENSIONS' => implode(', ', $extensions), + ] + ); + } + + /** + * Handle import action + * + * @param integer $id An import identifier + * + * @return \Thelia\Core\HttpFoundation\Response|\Symfony\Component\HttpFoundation\Response + */ + public function importAction($id) + { + /** @var \Thelia\Handler\Importhandler $importHandler */ + $importHandler = $this->container->get('thelia.import.handler'); + + $import = $importHandler->getImport($id); + if ($import === null) { + return $this->pageNotFound(); + } + + $form = $this->createForm(AdminForm::IMPORT); + + try { + $validatedForm = $this->validateForm($form); + + /** @var \Symfony\Component\HttpFoundation\File\UploadedFile $file */ + $file = $validatedForm->get('file_upload')->getData(); + $file = $file->move( + THELIA_CACHE_DIR . 'import' . DS . (new\DateTime)->format('Ymd'), + uniqid() . '-' . $file->getClientOriginalName() + ); + + $lang = (new LangQuery)->findPk($validatedForm->get('language')->getData()); + + $importEvent = $importHandler->import($import, $file, $lang); + + if (\count($importEvent->getErrors()) > 0) { + $this->getSession()->getFlashBag()->add( + 'thelia.import.error', + $this->getTranslator()->trans( + 'Error(s) in import :
    %errors', + [ + '%errors' => implode('
    ', $importEvent->getErrors()) + ] + ) + ); + } + + $this->getSession()->getFlashBag()->add( + 'thelia.import.success', + $this->getTranslator()->trans( + 'Import successfully done, %count row(s) have been changed', + [ + '%count' => $importEvent->getImport()->getImportedRows() + ] + ) + ); + + return $this->generateRedirectFromRoute('import.view', [], ['id' => $id]); + } catch (FormValidationException $e) { + $form->setErrorMessage($this->createStandardFormValidationErrorMessage($e)); + } catch (\Exception $e) { + $this->getParserContext()->setGeneralError($e->getMessage()); + } + + $this->getParserContext() + ->addForm($form) + ; + + return $this->configureAction($id); + } +} diff --git a/core/lib/Thelia/Controller/Admin/LangController.php b/core/lib/Thelia/Controller/Admin/LangController.php new file mode 100644 index 00000000..908b5133 --- /dev/null +++ b/core/lib/Thelia/Controller/Admin/LangController.php @@ -0,0 +1,456 @@ + + */ +class LangController extends BaseAdminController +{ + public function defaultAction() + { + if (null !== $response = $this->checkAuth(AdminResources::LANGUAGE, array(), AccessManager::VIEW)) { + return $response; + } + return $this->renderDefault(); + } + + public function renderDefault(array $param = array(), $status = 200) + { + $data = array(); + foreach (LangQuery::create()->find() as $lang) { + $data[LangUrlForm::LANG_PREFIX.$lang->getId()] = $lang->getUrl(); + } + $langUrlForm = $this->createForm(AdminForm::LANG_URL, 'form', $data); + $this->getParserContext()->addForm($langUrlForm); + + return $this->render('languages', array_merge($param, array( + 'lang_without_translation' => ConfigQuery::getDefaultLangWhenNoTranslationAvailable(), + 'one_domain_per_lang' => ConfigQuery::isMultiDomainActivated() + )), $status); + } + + public function updateAction($lang_id) + { + if (null !== $response = $this->checkAuth(AdminResources::LANGUAGE, array(), AccessManager::UPDATE)) { + return $response; + } + + $this->checkXmlHttpRequest(); + + $lang = LangQuery::create()->findPk($lang_id); + + $langForm = $this->createForm(AdminForm::LANG_UPDATE, 'form', array( + 'id' => $lang->getId(), + 'title' => $lang->getTitle(), + 'code' => $lang->getCode(), + 'locale' => $lang->getLocale(), + 'date_time_format' => $lang->getDateTimeFormat(), + 'date_format' => $lang->getDateFormat(), + 'time_format' => $lang->getTimeFormat(), + 'decimal_separator' => $lang->getDecimalSeparator(), + 'thousands_separator' => $lang->getThousandsSeparator(), + 'decimals' => $lang->getDecimals(), + )); + + $this->getParserContext()->addForm($langForm); + + return $this->render('ajax/language-update-modal', array( + 'lang_id' => $lang_id + )); + } + + public function processUpdateAction($lang_id) + { + if (null !== $response = $this->checkAuth(AdminResources::LANGUAGE, array(), AccessManager::UPDATE)) { + return $response; + } + + $error_msg = false; + + $langForm = $this->createForm(AdminForm::LANG_UPDATE); + + try { + $form = $this->validateForm($langForm); + + $event = new LangUpdateEvent($form->get('id')->getData()); + $event = $this->hydrateEvent($event, $form); + + $this->dispatch(TheliaEvents::LANG_UPDATE, $event); + + if (false === $event->hasLang()) { + throw new \LogicException( + $this->getTranslator()->trans("No %obj was updated.", array('%obj', 'Lang')) + ); + } + + /** @var Lang $changedObject */ + $changedObject = $event->getLang(); + $this->adminLogAppend( + AdminResources::LANGUAGE, + AccessManager::UPDATE, + sprintf( + "%s %s (ID %s) modified", + 'Lang', + $changedObject->getTitle(), + $changedObject->getId() + ), + $changedObject->getId() + ); + + $response = $this->generateRedirectFromRoute('admin.configuration.languages'); + } catch (\Exception $ex) { + $error_msg = $this->getTranslator()->trans("Failed to update language definition: %ex", array("%ex" => $ex->getMessage())); + Tlog::getInstance()->addError("Failed to update language definition", $ex->getMessage()); + } + + if (false !== $error_msg) { + $response = $this->renderDefault(array('error_message' => $error_msg)); + } + + return $response; + } + + /** + * @param LangCreateEvent $event + * @param Form $form + * @return LangCreateEvent + */ + protected function hydrateEvent($event, Form $form) + { + return $event + ->setTitle($form->get('title')->getData()) + ->setCode($form->get('code')->getData()) + ->setLocale($form->get('locale')->getData()) + ->setDateTimeFormat($form->get('date_time_format')->getData()) + ->setDateFormat($form->get('date_format')->getData()) + ->setTimeFormat($form->get('time_format')->getData()) + ->setDecimalSeparator($form->get('decimal_separator')->getData()) + ->setThousandsSeparator($form->get('thousands_separator')->getData()) + ->setDecimals($form->get('decimals')->getData()) + ; + } + + public function toggleDefaultAction($lang_id) + { + return $this->toggleLangDispatch( + TheliaEvents::LANG_TOGGLEDEFAULT, + new LangToggleDefaultEvent($lang_id) + ); + } + + public function toggleActiveAction($lang_id) + { + return $this->toggleLangDispatch( + TheliaEvents::LANG_TOGGLEACTIVE, + new LangToggleActiveEvent($lang_id) + ); + } + + public function toggleVisibleAction($lang_id) + { + return $this->toggleLangDispatch( + TheliaEvents::LANG_TOGGLEVISIBLE, + new LangToggleVisibleEvent($lang_id) + ); + } + + public function addAction() + { + if (null !== $response = $this->checkAuth(AdminResources::LANGUAGE, array(), AccessManager::CREATE)) { + return $response; + } + + $createForm = $this->createForm(AdminForm::LANG_CREATE); + + $error_msg = false; + $ex = null; + + try { + $form = $this->validateForm($createForm); + + $createEvent = new LangCreateEvent(); + $createEvent = $this->hydrateEvent($createEvent, $form); + + $this->dispatch(TheliaEvents::LANG_CREATE, $createEvent); + + if (false === $createEvent->hasLang()) { + throw new \LogicException( + $this->getTranslator()->trans("No %obj was updated.", array('%obj', 'Lang')) + ); + } + + /** @var Lang $createdObject */ + $createdObject = $createEvent->getLang(); + $this->adminLogAppend( + AdminResources::LANGUAGE, + AccessManager::CREATE, + sprintf( + "%s %s (ID %s) created", + 'Lang', + $createdObject->getTitle(), + $createdObject->getId() + ), + $createdObject->getId() + ); + + $response = $this->generateRedirectFromRoute('admin.configuration.languages'); + } catch (FormValidationException $ex) { + // Form cannot be validated + $error_msg = $this->createStandardFormValidationErrorMessage($ex); + } catch (\Exception $ex) { + // Any other error + $error_msg = $ex->getMessage(); + } + + if (false !== $error_msg) { + $this->setupFormErrorContext( + $this->getTranslator()->trans("%obj creation", array('%obj' => 'Lang')), + $error_msg, + $createForm, + $ex + ); + + // At this point, the form has error, and should be redisplayed. + $response = $this->renderDefault(); + } + + return $response; + } + + public function deleteAction() + { + if (null !== $response = $this->checkAuth(AdminResources::LANGUAGE, array(), AccessManager::DELETE)) { + return $response; + } + + $error_msg = false; + + try { + $this->getTokenProvider()->checkToken( + $this->getRequest()->query->get("_token") + ); + + $deleteEvent = new LangDeleteEvent($this->getRequest()->get('language_id', 0)); + + $this->dispatch(TheliaEvents::LANG_DELETE, $deleteEvent); + + $response = $this->generateRedirectFromRoute('admin.configuration.languages'); + } catch (\Exception $ex) { + Tlog::getInstance()->error(sprintf("error during language removal with message : %s", $ex->getMessage())); + $error_msg = $ex->getMessage(); + } + + if (false !== $error_msg) { + $response = $this->renderDefault(array( + 'error_message' => $error_msg + )); + } + + return $response; + } + + public function defaultBehaviorAction() + { + if (null !== $response = $this->checkAuth(AdminResources::LANGUAGE, array(), AccessManager::UPDATE)) { + return $response; + } + + $error_msg = false; + $ex = null; + + $behaviorForm = $this->createForm(AdminForm::LANG_DEFAULT_BEHAVIOR); + + try { + $form = $this->validateForm($behaviorForm); + + $event = new LangDefaultBehaviorEvent($form->get('behavior')->getData()); + + $this->dispatch(TheliaEvents::LANG_DEFAULTBEHAVIOR, $event); + + $response = $this->generateRedirectFromRoute('admin.configuration.languages'); + } catch (FormValidationException $ex) { + // Form cannot be validated + $error_msg = $this->createStandardFormValidationErrorMessage($ex); + } catch (\Exception $ex) { + // Any other error + $error_msg = $ex->getMessage(); + } + + if (false !== $error_msg) { + $this->setupFormErrorContext( + $this->getTranslator()->trans("%obj creation", array('%obj' => 'Lang')), + $error_msg, + $behaviorForm, + $ex + ); + + // At this point, the form has error, and should be redisplayed. + $response = $this->renderDefault(); + } + + return $response; + } + + public function domainAction() + { + if (null !== $response = $this->checkAuth(AdminResources::LANGUAGE, array(), AccessManager::UPDATE)) { + return $response; + } + + $error_msg = false; + $ex = null; + $langUrlForm = $this->createForm(AdminForm::LANG_URL); + + try { + $form = $this->validateForm($langUrlForm); + + $data = $form->getData(); + $event = new LangUrlEvent(); + foreach ($data as $key => $value) { + if (false !== strpos($key, LangUrlForm::LANG_PREFIX)) { + $event->addUrl(substr($key, \strlen(LangUrlForm::LANG_PREFIX)), $value); + } + } + + $this->dispatch(TheliaEvents::LANG_URL, $event); + + $response = $this->generateRedirectFromRoute('admin.configuration.languages'); + } catch (FormValidationException $ex) { + // Form cannot be validated + $error_msg = $this->createStandardFormValidationErrorMessage($ex); + } catch (\Exception $ex) { + // Any other error + $error_msg = $ex->getMessage(); + } + + if (false !== $error_msg) { + $this->setupFormErrorContext( + $this->getTranslator()->trans("%obj creation", array('%obj' => 'Lang')), + $error_msg, + $langUrlForm, + $ex + ); + + // At this point, the form has error, and should be redisplayed. + $response = $this->renderDefault(); + } + + return $response; + } + + public function activateDomainAction() + { + return $this->domainActivation(1); + } + + public function deactivateDomainAction() + { + return $this->domainActivation(0); + } + + private function domainActivation($activate) + { + if (null !== $response = $this->checkAuth(AdminResources::LANGUAGE, array(), AccessManager::UPDATE)) { + return $response; + } + + ConfigQuery::create() + ->filterByName('one_domain_foreach_lang') + ->update(array('Value' => $activate)); + + return $this->generateRedirectFromRoute('admin.configuration.languages'); + } + + /** + * @param string $eventName + * @param LangEvent $event + * @return Response + */ + protected function toggleLangDispatch($eventName, $event) + { + if (null !== $response = $this->checkAuth(AdminResources::LANGUAGE, array(), AccessManager::UPDATE)) { + return $response; + } + + $errorMessage = null; + + $this->getTokenProvider()->checkToken( + $this->getRequest()->query->get('_token') + ); + + try { + $this->dispatch($eventName, $event); + + if (false === $event->hasLang()) { + throw new \LogicException( + $this->getTranslator()->trans("No %obj was updated.", array('%obj', 'Lang')) + ); + } + + $changedObject = $event->getLang(); + $this->adminLogAppend( + AdminResources::LANGUAGE, + AccessManager::UPDATE, + sprintf( + "%s %s (ID %s) modified", + 'Lang', + $changedObject->getTitle(), + $changedObject->getId() + ), + $changedObject->getId() + ); + } catch (\Exception $e) { + Tlog::getInstance()->error(sprintf("Error on changing languages with message : %s", $e->getMessage())); + $errorMessage = $e->getMessage(); + } + + if ($this->getRequest()->isXmlHttpRequest()) { + return new JsonResponse( + $errorMessage !== null ? ['message' => $errorMessage] : [], + $errorMessage !== null ? 500 : 200 + ); + } + + if ($errorMessage !== null) { + return $this->renderDefault(['error_message' => $errorMessage], 500); + } else { + return $this->generateRedirectFromRoute('admin.configuration.languages'); + } + } +} diff --git a/core/lib/Thelia/Controller/Admin/LanguageController.php b/core/lib/Thelia/Controller/Admin/LanguageController.php new file mode 100644 index 00000000..c720549a --- /dev/null +++ b/core/lib/Thelia/Controller/Admin/LanguageController.php @@ -0,0 +1,32 @@ + + */ +class LanguageController extends BaseAdminController +{ + public function defaultAction() + { + if (null !== $response = $this->checkAuth(AdminResources::LANGUAGE, array(), AccessManager::VIEW)) { + return $response; + } + return $this->render("languages"); + } +} diff --git a/core/lib/Thelia/Controller/Admin/MailingSystemController.php b/core/lib/Thelia/Controller/Admin/MailingSystemController.php new file mode 100644 index 00000000..23ce2a91 --- /dev/null +++ b/core/lib/Thelia/Controller/Admin/MailingSystemController.php @@ -0,0 +1,156 @@ +checkAuth(self::RESOURCE_CODE, array(), AccessManager::VIEW)) { + return $response; + } + + // Hydrate the form abd pass it to the parser + $data = array( + 'enabled' => ConfigQuery::isSmtpEnable() ? true : false, + 'host' => ConfigQuery::getSmtpHost(), + 'port' => ConfigQuery::getSmtpPort(), + 'encryption' => ConfigQuery::getSmtpEncryption(), + 'username' => ConfigQuery::getSmtpUsername(), + 'password' => ConfigQuery::getSmtpPassword(), + 'authmode' => ConfigQuery::getSmtpAuthMode(), + 'timeout' => ConfigQuery::getSmtpTimeout(), + 'sourceip' => ConfigQuery::getSmtpSourceIp(), + ); + + // Setup the object form + $form = $this->createForm(AdminForm::MAILING_SYSTEM_MODIFICATION, "form", $data); + + // Pass it to the parser + $this->getParserContext()->addForm($form); + + // Render the edition template. + return $this->render('mailing-system'); + } + + public function updateAction() + { + // Check current user authorization + if (null !== $response = $this->checkAuth(self::RESOURCE_CODE, array(), AccessManager::UPDATE)) { + return $response; + } + + $error_msg = false; + + // Create the form from the request + $form = $this->createForm(AdminForm::MAILING_SYSTEM_MODIFICATION); + + try { + // Check the form against constraints violations + $formData = $this->validateForm($form, "POST"); + + // Get the form field values + $event = new MailingSystemEvent(); + $event->setEnabled($formData->get('enabled')->getData()); + $event->setHost($formData->get('host')->getData()); + $event->setPort($formData->get('port')->getData()); + $event->setEncryption($formData->get('encryption')->getData()); + $event->setUsername($formData->get('username')->getData()); + $event->setPassword($formData->get('password')->getData()); + $event->setAuthMode($formData->get('authmode')->getData()); + $event->setTimeout($formData->get('timeout')->getData()); + $event->setSourceIp($formData->get('sourceip')->getData()); + + $this->dispatch(TheliaEvents::MAILING_SYSTEM_UPDATE, $event); + + // Redirect to the success URL + $response = $this->generateRedirectFromRoute("admin.configuration.mailing-system.view"); + } catch (FormValidationException $ex) { + // Form cannot be validated + $error_msg = $this->createStandardFormValidationErrorMessage($ex); + } catch (\Exception $ex) { + // Any other error + $error_msg = $ex->getMessage(); + } + + if (false !== $error_msg) { + $this->setupFormErrorContext( + $this->getTranslator()->trans("mailing system modification", array()), + $error_msg, + $form, + $ex + ); + + // At this point, the form has errors, and should be redisplayed. + $response = $this->render('mailing-system'); + } + + return $response; + } + + public function testAction() + { + // Check current user authorization + if (null !== $response = $this->checkAuth(self::RESOURCE_CODE, array(), AccessManager::UPDATE)) { + return $response; + } + + $contactEmail = ConfigQuery::read('store_email'); + $storeName = ConfigQuery::read('store_name', 'Thelia'); + + $json_data = array( + "success" => false, + "message" => "", + ); + + if ($contactEmail) { + $emailTest = $this->getRequest()->get("email", $contactEmail); + + $message = $this->getTranslator()->trans("Email test from : %store%", array("%store%" => $storeName)); + + $htmlMessage = "

    $message

    "; + + $instance = $this->getMailer()->getMessageInstance() + ->addTo($emailTest, $storeName) + ->addFrom($contactEmail, $storeName) + ->setSubject($message) + ->setBody($message, 'text/plain') + ->setBody($htmlMessage, 'text/html') + ; + + try { + $this->getMailer()->send($instance); + $json_data["success"] = true; + $json_data["message"] = $this->getTranslator()->trans("Your configuration seems to be ok. Checked out your mailbox : %email%", array("%email%" => $emailTest)); + } catch (\Exception $ex) { + $json_data["message"] = $ex->getMessage(); + } + } else { + $json_data["message"] = $this->getTranslator()->trans("You have to configure your store email first !"); + } + + $response = JsonResponse::create($json_data); + + return $response; + } +} diff --git a/core/lib/Thelia/Controller/Admin/MessageController.php b/core/lib/Thelia/Controller/Admin/MessageController.php new file mode 100644 index 00000000..33c96219 --- /dev/null +++ b/core/lib/Thelia/Controller/Admin/MessageController.php @@ -0,0 +1,330 @@ + + */ +class MessageController extends AbstractCrudController +{ + public function __construct() + { + parent::__construct( + 'message', + null, // no sort order change + null, // no sort order change + AdminResources::MESSAGE, + TheliaEvents::MESSAGE_CREATE, + TheliaEvents::MESSAGE_UPDATE, + TheliaEvents::MESSAGE_DELETE, + null, // No visibility toggle + null // No position update + ); + } + + protected function getCreationForm() + { + return $this->createForm(AdminForm::MESSAGE_CREATION); + } + + protected function getUpdateForm() + { + return $this->createForm(AdminForm::MESSAGE_MODIFICATION); + } + + protected function getCreationEvent($formData) + { + $createEvent = new MessageCreateEvent(); + + $createEvent + ->setMessageName($formData['name']) + ->setLocale($formData["locale"]) + ->setTitle($formData['title']) + ->setSecured($formData['secured'] ? true : false) + ; + + return $createEvent; + } + + protected function getUpdateEvent($formData) + { + $changeEvent = new MessageUpdateEvent($formData['id']); + + // Create and dispatch the change event + $changeEvent + ->setMessageName($formData['name']) + ->setSecured($formData['secured']) + ->setLocale($formData["locale"]) + ->setTitle($formData['title']) + ->setSubject($formData['subject']) + ->setHtmlLayoutFileName($formData['html_layout_file_name']) + ->setHtmlTemplateFileName($formData['html_template_file_name']) + ->setTextLayoutFileName($formData['text_layout_file_name']) + ->setTextTemplateFileName($formData['text_template_file_name']) + ->setHtmlMessage($formData['html_message']) + ->setTextMessage($formData['text_message']) + ; + + return $changeEvent; + } + + protected function getDeleteEvent() + { + return new MessageDeleteEvent($this->getRequest()->get('message_id')); + } + + protected function eventContainsObject($event) + { + return $event->hasMessage(); + } + + protected function hydrateObjectForm($object) + { + // Prepare the data that will hydrate the form + $data = array( + 'id' => $object->getId(), + 'name' => $object->getName(), + 'secured' => $object->getSecured() ? true : false, + 'locale' => $object->getLocale(), + 'title' => $object->getTitle(), + 'subject' => $object->getSubject(), + 'html_message' => $object->getHtmlMessage(), + 'text_message' => $object->getTextMessage(), + + 'html_layout_file_name' => $object->getHtmlLayoutFileName(), + 'html_template_file_name' => $object->getHtmlTemplateFileName(), + 'text_layout_file_name' => $object->getTextLayoutFileName(), + 'text_template_file_name' => $object->getTextTemplateFileName(), + ); + + // Setup the object form + return $this->createForm(AdminForm::MESSAGE_MODIFICATION, "form", $data); + } + + protected function getObjectFromEvent($event) + { + return $event->hasMessage() ? $event->getMessage() : null; + } + + protected function getExistingObject() + { + $message = MessageQuery::create() + ->findOneById($this->getRequest()->get('message_id', 0)); + + if (null !== $message) { + $message->setLocale($this->getCurrentEditionLocale()); + } + + return $message; + } + + /** + * @param Message $object + * @return string + */ + protected function getObjectLabel($object) + { + return $object->getName(); + } + + /** + * @param Message $object + * @return int + */ + protected function getObjectId($object) + { + return $object->getId(); + } + + protected function renderListTemplate($currentOrder) + { + return $this->render('messages'); + } + + protected function listDirectoryContent($requiredExtension) + { + $list = array(); + + $mailTemplate = $this->getTemplateHelper()->getActiveMailTemplate(); + + $finder = Finder::create()->files()->in($mailTemplate->getAbsolutePath()); + + // Also add parent template files, if any. + /** @var TemplateDefinition $parentTemplate */ + foreach ($mailTemplate->getParentList() as $parentTemplate) { + $finder->in($parentTemplate->getAbsolutePath()); + } + + $finder->ignoreDotFiles(true)->sortByName()->name("*.$requiredExtension"); + + /** @var SplFileInfo $file */ + foreach ($finder as $file) { + $list[] = $file->getRelativePathname(); + } + + // Add modules templates + $modules = ModuleQuery::getActivated(); + /** @var Module $module */ + foreach ($modules as $module) { + $dir = $module->getAbsoluteTemplateBasePath() . DS . TemplateDefinition::EMAIL_SUBDIR . DS . 'default'; + + if (file_exists($dir)) { + $finder = Finder::create() + ->files() + ->in($dir) + ->ignoreDotFiles(true) + ->sortByName() + ->name("*.$requiredExtension"); + + foreach ($finder as $file) { + $fileName = $file->getBasename(); + if (!\in_array($fileName, $list)) { + $list[] = $fileName; + } + } + } + } + + return $list; + } + + protected function renderEditionTemplate() + { + return $this->render('message-edit', array( + 'message_id' => $this->getRequest()->get('message_id'), + 'layout_list' => $this->listDirectoryContent('tpl'), + 'html_template_list' => $this->listDirectoryContent('html'), + 'text_template_list' => $this->listDirectoryContent('txt'), + )); + } + + protected function redirectToEditionTemplate() + { + return $this->generateRedirectFromRoute( + "admin.configuration.messages.update", + [ + 'message_id' => $this->getRequest()->get('message_id') + ] + ); + } + + protected function redirectToListTemplate() + { + return $this->generateRedirectFromRoute('admin.configuration.messages.default'); + } + + public function previewAction($messageId, $html = true) + { + if (null !== $response = $this->checkAuth(AdminResources::MESSAGE, [], AccessManager::VIEW)) { + return $response; + } + + if (null === $message = MessageQuery::create()->findPk($messageId)) { + $this->pageNotFound(); + } + + $parser = $this->getParser($this->getTemplateHelper()->getActiveMailTemplate()); + + foreach ($this->getRequest()->query->all() as $key => $value) { + $parser->assign($key, $value); + } + + if ($html) { + $content = $message->setLocale($this->getCurrentEditionLocale())->getHtmlMessageBody($parser); + } else { + $content = $message->setLocale($this->getCurrentEditionLocale())->getTextMessageBody($parser); + } + + return new Response($content); + } + + public function previewAsHtmlAction($messageId) + { + return $this->previewAction($messageId); + } + + public function previewAsTextAction($messageId) + { + $response = $this->previewAction($messageId, false); + $response->headers->add(["Content-Type" => "text/plain"]); + + 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(); + } + } +} diff --git a/core/lib/Thelia/Controller/Admin/ModuleController.php b/core/lib/Thelia/Controller/Admin/ModuleController.php new file mode 100644 index 00000000..09253784 --- /dev/null +++ b/core/lib/Thelia/Controller/Admin/ModuleController.php @@ -0,0 +1,480 @@ + + */ +class ModuleController extends AbstractCrudController +{ + protected $moduleErrors = []; + + public function __construct() + { + parent::__construct( + 'module', + 'manual', + 'module_order', + AdminResources::MODULE, + null, + TheliaEvents::MODULE_UPDATE, + null, + null, + TheliaEvents::MODULE_UPDATE_POSITION + ); + } + + protected function getCreationForm() + { + return null; + } + + protected function getUpdateForm() + { + return $this->createForm(AdminForm::MODULE_MODIFICATION); + } + + protected function getCreationEvent($formData) + { + return null; + } + + protected function getUpdateEvent($formData) + { + $event = new ModuleEvent(); + + $event->setLocale($formData['locale']); + $event->setId($formData['id']); + $event->setTitle($formData['title']); + $event->setChapo($formData['chapo']); + $event->setDescription($formData['description']); + $event->setPostscriptum($formData['postscriptum']); + + return $event; + } + + protected function getDeleteEvent() + { + return null; + } + + protected function createUpdatePositionEvent($positionChangeMode, $positionValue) + { + return new UpdatePositionEvent( + $this->getRequest()->get('module_id', null), + $positionChangeMode, + $positionValue + ); + } + + protected function eventContainsObject($event) + { + return $event->hasModule(); + } + + protected function hydrateObjectForm($object) + { + $object->setLocale($this->getCurrentEditionLocale()); + $data = array( + 'id' => $object->getId(), + 'locale' => $object->getLocale(), + 'title' => $object->getTitle(), + 'chapo' => $object->getChapo(), + 'description' => $object->getDescription(), + 'postscriptum' => $object->getPostscriptum(), + ); + + // Setup the object form + return $this->createForm(AdminForm::MODULE_MODIFICATION, "form", $data); + } + + protected function getObjectFromEvent($event) + { + return $event->hasModule() ? $event->getModule() : null; + } + + protected function getExistingObject() + { + $module = ModuleQuery::create() + ->findOneById($this->getRequest()->get('module_id', 0)); + + if (null !== $module) { + $module->setLocale($this->getCurrentEditionLocale()); + } + + return $module; + } + + /** + * @param Module $object + * @return string + */ + protected function getObjectLabel($object) + { + return $object->getTitle(); + } + + /** + * @param Module $object + * @return int + */ + protected function getObjectId($object) + { + return $object->getId(); + } + + protected function getViewArguments() + { + return array(); + } + + protected function getRouteArguments($module_id = null) + { + $request = $this->getRequest(); + + return array( + 'module_id' => $module_id === null ? $request->get('module_id') : $module_id, + 'current_tab' => $request->get('current_tab', 'general'), + ); + } + + protected function renderListTemplate($currentOrder) + { + // We always return to the feature edition form + return $this->render( + 'modules', + array( + 'module_order' => $currentOrder, + 'module_errors' => $this->moduleErrors + ) + ); + } + + protected function renderEditionTemplate() + { + // We always return to the feature edition form + return $this->render('module-edit', array_merge($this->getViewArguments(), $this->getRouteArguments())); + } + + protected function redirectToEditionTemplate($request = null, $country = null) + { + return $this->generateRedirectFromRoute( + "admin.module.update", + $this->getViewArguments(), + $this->getRouteArguments() + ); + } + + protected function redirectToListTemplate() + { + return $this->generateRedirectFromRoute("admin.module"); + } + + public function indexAction() + { + if (null !== $response = $this->checkAuth(AdminResources::MODULE, array(), AccessManager::VIEW)) { + return $response; + } + + try { + $moduleManagement = new ModuleManagement($this->getContainer()); + $moduleManagement->updateModules($this->getContainer()); + } catch (InvalidModuleException $ex) { + $this->moduleErrors = $ex->getErrors(); + } catch (Exception $ex) { + Tlog::getInstance()->addError("Failed to get modules list:", $ex); + } + + return $this->renderList(); + } + + public function configureAction($module_code) + { + $module = ModuleQuery::create()->findOneByCode($module_code); + + if (null === $module) { + throw new \InvalidArgumentException(sprintf("Module `%s` does not exists", $module_code)); + } + + if (null !== $response = $this->checkAuth(array(), $module_code, AccessManager::VIEW)) { + return $response; + } + return $this->render( + "module-configure", + array( + "module_code" => $module_code, + ) + ); + } + + public function toggleActivationAction($module_id) + { + if (null !== $response = $this->checkAuth(AdminResources::MODULE, array(), AccessManager::UPDATE)) { + return $response; + } + $message = null; + try { + $event = new ModuleToggleActivationEvent($module_id); + $this->dispatch(TheliaEvents::MODULE_TOGGLE_ACTIVATION, $event); + + if (null === $event->getModule()) { + throw new \LogicException( + $this->getTranslator()->trans("No %obj was updated.", array('%obj' => 'Module')) + ); + } + } catch (\Exception $e) { + $message = $e->getMessage(); + + Tlog::getInstance()->addError("Failed to activate/deactivate module:", $e); + } + + if ($this->getRequest()->isXmlHttpRequest()) { + if ($message) { + $response = $this->jsonResponse(json_encode(array( + "error" => $message + )), 500); + } else { + $response = $this->nullResponse(); + } + } else { + $response = $this->generateRedirectFromRoute('admin.module'); + } + + return $response; + } + + public function deleteAction() + { + if (null !== $response = $this->checkAuth(AdminResources::MODULE, array(), AccessManager::DELETE)) { + return $response; + } + + $message = false; + + try { + $this->getTokenProvider()->checkToken( + $this->getRequest()->query->get("_token") + ); + + $module_id = $this->getRequest()->get('module_id'); + + $deleteEvent = new ModuleDeleteEvent($module_id); + + $deleteEvent->setDeleteData('1' == $this->getRequest()->get('delete-module-data', '0')); + + $this->dispatch(TheliaEvents::MODULE_DELETE, $deleteEvent); + + if ($deleteEvent->hasModule() === false) { + throw new \LogicException( + $this->getTranslator()->trans("No %obj was updated.", array('%obj' => 'Module')) + ); + } + } catch (\Exception $e) { + $message = $e->getMessage(); + + Tlog::getInstance()->addError("Error during module removal", $e); + } + + if (false !== $message) { + $response = $this->render("modules", array( + "error_message" => $message + )); + } else { + $response = $this->generateRedirectFromRoute('admin.module'); + } + + return $response; + } + + public function installAction() + { + if (null !== $response = $this->checkAuth(AdminResources::MODULE, array(), AccessManager::CREATE)) { + return $response; + } + + $newModule = null; + $moduleDefinition = null; + + /** @var ModuleInstallForm $moduleInstall */ + $moduleInstall = $this->createForm(AdminForm::MODULE_INSTALL); + + try { + $this->validateForm($moduleInstall, "post"); + + $moduleDefinition = $moduleInstall->getModuleDefinition(); + $modulePath = $moduleInstall->getModulePath(); + + $moduleInstallEvent = new ModuleInstallEvent(); + $moduleInstallEvent + ->setModulePath($modulePath) + ->setModuleDefinition($moduleDefinition); + + $this->dispatch(TheliaEvents::MODULE_INSTALL, $moduleInstallEvent); + + $newModule = $moduleInstallEvent->getModule(); + + if (null !== $newModule) { + $this->getSession()->getFlashBag()->add( + 'module-installed', + $this->getTranslator()->trans( + 'The module %module has been installed successfully.', + ['%module' => $moduleDefinition->getCode()] + ) + ); + + return $this->generateRedirectFromRoute('admin.module'); + } else { + $message = $this->getTranslator()->trans( + "Sorry, an error occured." + ); + } + } catch (FormValidationException $e) { + $message = $e->getMessage(); + } catch (\Exception $e) { + $message = $this->getTranslator()->trans("Sorry, an error occured: %s", ['%s' => $e->getMessage()]); + } + + Tlog::getInstance()->error(sprintf("Error during module installation process. Exception was %s", $message)); + + $moduleInstall->setErrorMessage($message); + + $this->getParserContext() + ->addForm($moduleInstall) + ->setGeneralError($message); + + return $this->render("modules"); + } + + public function informationAction($module_id) + { + if (null !== $response = $this->checkAuth(AdminResources::MODULE, array(), AccessManager::VIEW)) { + return $response; + } + + $status = 200; + + if (null !== $module = ModuleQuery::create()->findPk($module_id)) { + $title = $module->setLocale($this->getSession()->getLang()->getLocale())->getTitle(); + + // Get the module descriptor + $moduleDescriptor = $module->getAbsoluteConfigPath() . DS . 'module.xml'; + + if (false !== $xmlData = @simplexml_load_file($moduleDescriptor)) { + // Transform the pseudo-array into a real array + $arrayData = json_decode(json_encode((array)$xmlData), 1); + + $content = $this->renderRaw("ajax/module-information", [ + 'moduleId' => $module_id, + 'moduleData' => $arrayData + ]); + } else { + $status = 500; + + $content = $this->getTranslator()->trans( + 'Failed to load descriptor (module.xml) for module ID "%id".', + [ '%id' => $module_id] + ); + } + } else { + $status = 404; + + $title = $this->getTranslator()->trans('Error occured.'); + $content = $this->getTranslator()->trans('Module ID "%id" was not found.', [ '%id' => $module_id]); + } + + return new JsonResponse([ 'title' => $title, 'body' => $content], $status); + } + + public function documentationAction($module_id) + { + if (null !== $response = $this->checkAuth(AdminResources::MODULE, array(), AccessManager::VIEW)) { + return $response; + } + + $status = 200; + + $content = null; + + if (null !== $module = ModuleQuery::create()->findPk($module_id)) { + $title = $module->setLocale($this->getSession()->getLang()->getLocale())->getTitle(); + + $finder = null; + + // Check if the module has declared a documentation + $moduleDescriptor = $module->getAbsoluteConfigPath() . DS . 'module.xml'; + + if (false !== $xmlData = @simplexml_load_file($moduleDescriptor)) { + $documentationDirectory = (string) $xmlData->documentation; + + if (! empty($documentationDirectory)) { + $finder = Finder::create()->files()->in($module->getAbsoluteBaseDir())->name('/.+\.md$/i'); + } + } + + // Fallback to readme.md (if any) + if ($finder == null || $finder->count() == 0) { + $finder = Finder::create()->files()->in($module->getAbsoluteBaseDir())->name('/readme\.md/i'); + } + + // Merge all MD files + if ($finder && $finder->count() > 0) { + $finder->sortByName(); + + /** @var \DirectoryIterator $file */ + foreach ($finder as $file) { + if (false !== $mdDocumentation = @file_get_contents($file->getPathname())) { + if ($content == null) { + $content = ''; + } + $content .= MarkdownExtra::defaultTransform($mdDocumentation); + } + } + } + } else { + $status = 404; + + $title = $this->getTranslator()->trans('Error occured.'); + $content = $this->getTranslator()->trans('Module ID "%id" was not found.', [ '%id' => $module_id]); + } + + if ($content === null) { + $content = $this->getTranslator()->trans("This module has no Markdown documentation."); + } + + return new JsonResponse([ 'title' => $title, 'body' => $content], $status); + } +} diff --git a/core/lib/Thelia/Controller/Admin/ModuleHookController.php b/core/lib/Thelia/Controller/Admin/ModuleHookController.php new file mode 100644 index 00000000..213a5c8b --- /dev/null +++ b/core/lib/Thelia/Controller/Admin/ModuleHookController.php @@ -0,0 +1,399 @@ + + */ +class ModuleHookController extends AbstractCrudController +{ + public function __construct() + { + parent::__construct( + 'hook', + 'manual', + 'hook_order', + AdminResources::MODULE_HOOK, + TheliaEvents::MODULE_HOOK_CREATE, + TheliaEvents::MODULE_HOOK_UPDATE, + TheliaEvents::MODULE_HOOK_DELETE, + null, + TheliaEvents::MODULE_HOOK_UPDATE_POSITION + ); + } + + public function indexAction() + { + if (null !== $response = $this->checkAuth(AdminResources::MODULE_HOOK, [], AccessManager::VIEW)) { + return $response; + } + + return $this->renderList(); + } + + public function toggleActivationAction($module_hook_id) + { + if (null !== $response = $this->checkAuth(AdminResources::MODULE_HOOK, [], AccessManager::UPDATE)) { + return $response; + } + + $message = null; + + $event = new ModuleHookToggleActivationEvent($this->getExistingObject()); + + try { + $this->dispatch(TheliaEvents::MODULE_HOOK_TOGGLE_ACTIVATION, $event); + } catch (\Exception $ex) { + $message = $ex->getMessage(); + } + + if ($this->getRequest()->isXmlHttpRequest()) { + if ($message) { + $response = $this->jsonResponse(json_encode([ "error" => $message]), 500); + } else { + $response = $this->nullResponse(); + } + } else { + $response = $this->generateRedirectFromRoute('admin.module-hook'); + } + + return $response; + } + + protected function createUpdatePositionEvent($positionChangeMode, $positionValue) + { + return new UpdatePositionEvent( + $this->getRequest()->get('module_hook_id', null), + $positionChangeMode, + $positionValue + ); + } + + /** + * Return the creation form for this object + */ + protected function getCreationForm() + { + return $this->createForm(AdminForm::MODULE_HOOK_CREATION); + } + + /** + * Return the update form for this object + */ + protected function getUpdateForm() + { + return $this->createForm(AdminForm::MODULE_HOOK_MODIFICATION); + } + + /** + * Hydrate the update form for this object, before passing it to the update template + * + * @param ModuleHook $object + * @return ModuleHookModificationForm + */ + protected function hydrateObjectForm($object) + { + $data = [ + 'id' => $object->getId(), + 'hook_id' => $object->getHookId(), + 'module_id' => $object->getModuleId(), + 'classname' => $object->getClassname(), + 'method' => $object->getMethod(), + 'active' => $object->getActive(), + 'templates' => $object->getTemplates(), + ]; + + return $this->createForm(AdminForm::MODULE_HOOK_MODIFICATION, 'form', $data); + } + + /** + * Creates the creation event with the provided form data + * + * @param array $formData + * @return ModuleHookCreateEvent + */ + protected function getCreationEvent($formData) + { + $event = new ModuleHookCreateEvent(); + + return $this->hydrateEvent($event, $formData); + } + + /** + * Creates the update event with the provided form data + * + * @param array $formData + * @return ModuleHookUpdateEvent + */ + protected function getUpdateEvent($formData) + { + $event = new ModuleHookUpdateEvent(); + + return $this->hydrateEvent($event, $formData, true); + } + + protected function hydrateEvent($event, $formData, $update = false) + { + if (!$update) { + $event + ->setModuleId($formData['module_id']) + ->setHookId($formData['hook_id']); + } else { + $event + ->setModuleHookId($formData['id']) + ->setModuleId($formData['module_id']) + ->setHookId($formData['hook_id']) + ->setClassname($formData['classname']) + ->setMethod($formData['method']) + ->setActive($formData['active']) + ->setTemplates($formData['templates']) + ; + } + + return $event; + } + + /** + * Creates the delete event with the provided form data + */ + protected function getDeleteEvent() + { + return new ModuleHookDeleteEvent($this->getRequest()->get('module_hook_id')); + } + + /** + * Return true if the event contains the object, e.g. the action has updated the object in the event. + * + * @param ModuleHookEvent $event + * @return bool + */ + protected function eventContainsObject($event) + { + return $event->hasModuleHook(); + } + + /** + * Get the created object from an event. + * + * @param ModuleHookEvent $event + * @return null|ModuleHook + */ + protected function getObjectFromEvent($event) + { + return $event->getModuleHook(); + } + + /** + * Load an existing object from the database + * @return null|ModuleHook + */ + protected function getExistingObject() + { + $moduleHook = ModuleHookQuery::create() + ->findPK($this->getRequest()->get('module_hook_id', 0)); + + return $moduleHook; + } + + /** + * Returns the object label form the object event (name, title, etc.) + * + * @param ModuleHook $object + * @return string + */ + protected function getObjectLabel($object) + { + try { + return sprintf( + "%s on %s", + $object->getModule()->getTitle(), + $object->getHook()->getTitle() + ); + } catch (\Exception $ex) { + return "Undefined module hook"; + } + } + + /** + * Returns the object ID from the object + * + * @param ModuleHook $object + * @return int + */ + protected function getObjectId($object) + { + return $object->getId(); + } + + /** + * Render the main list template + * + * @param string $currentOrder , if any, null otherwise. + * @return Response + */ + protected function renderListTemplate($currentOrder) + { + return $this->render( + 'module-hooks', + ['module_order' => $currentOrder] + ); + } + + /** + * Render the edition template + * @return Response + */ + protected function renderEditionTemplate() + { + return $this->render('module-hook-edit', $this->getEditionArgument()); + } + + /** + * @return array + */ + protected function getEditionArgument() + { + return [ + 'module_hook_id' => $this->getRequest()->get('module_hook_id', 0) + ]; + } + + /** + * Redirect to the edition template + * @return Response + */ + protected function redirectToEditionTemplate($request = null, $country = null) + { + return $this->generateRedirectFromRoute( + "admin.module-hook.update", + $this->getViewArguments(), + $this->getRouteArguments() + ); + } + + /** + * Redirect to the list template + */ + protected function redirectToListTemplate() + { + return $this->generateRedirectFromRoute("admin.module-hook"); + } + + protected function getViewArguments() + { + return []; + } + + protected function getRouteArguments($module_hook_id = null) + { + return [ + 'module_hook_id' => $module_hook_id === null ? $this->getRequest()->get('module_hook_id') : $module_hook_id + ]; + } + + public function getModuleHookClassnames($moduleId) + { + if (null !== $response = $this->checkAuth(AdminResources::MODULE_HOOK, [], AccessManager::VIEW)) { + return $response; + } + + $result = []; + + $moduleHooks = ModuleHookQuery::create() + ->filterByModuleId($moduleId) + ->groupByClassname() + ->find(); + + /** @var ModuleHook $moduleHook */ + foreach ($moduleHooks as $moduleHook) { + $result[] = $moduleHook->getClassname(); + } + + $ignoredModuleHooks = IgnoredModuleHookQuery::create() + ->filterByModuleId($moduleId) + ->groupByClassname() + ->find(); + + /** @var IgnoredModuleHook $moduleHook */ + foreach ($ignoredModuleHooks as $moduleHook) { + $className = $moduleHook->getClassname(); + if (null !== $className && ! \in_array($className, $result)) { + $result[] = $className; + } + } + + sort($result); + + return new JsonResponse($result); + } + + public function getModuleHookMethods($moduleId, $className) + { + if (null !== $response = $this->checkAuth(AdminResources::MODULE_HOOK, [], AccessManager::VIEW)) { + return $response; + } + + $result = [BaseHook::INJECT_TEMPLATE_METHOD_NAME]; + + $moduleHooks = ModuleHookQuery::create() + ->filterByModuleId($moduleId) + ->filterByClassname($className) + ->find(); + + /** @var ModuleHook $moduleHook */ + foreach ($moduleHooks as $moduleHook) { + $method = $moduleHook->getMethod(); + if (! \in_array($method, $result)) { + $result[] = $method; + } + } + + $ignoredModuleHooks = IgnoredModuleHookQuery::create() + ->filterByModuleId($moduleId) + ->filterByClassname($className) + ->find(); + + /** @var IgnoredModuleHook $moduleHook */ + foreach ($ignoredModuleHooks as $moduleHook) { + $method = $moduleHook->getMethod(); + if (! \in_array($method, $result)) { + $result[] = $method; + } + } + + sort($result); + + return new JsonResponse($result); + } +} diff --git a/core/lib/Thelia/Controller/Admin/OrderController.php b/core/lib/Thelia/Controller/Admin/OrderController.php new file mode 100644 index 00000000..1c1cb0e1 --- /dev/null +++ b/core/lib/Thelia/Controller/Admin/OrderController.php @@ -0,0 +1,241 @@ + + */ +class OrderController extends BaseAdminController +{ + public function indexAction() + { + if (null !== $response = $this->checkAuth(AdminResources::ORDER, array(), AccessManager::VIEW)) { + return $response; + } + return $this->render("orders", array( + "display_order" => 20, + "orders_order" => $this->getListOrderFromSession("orders", "orders_order", "create-date-reverse") + )); + } + + public function viewAction($order_id) + { + return $this->render("order-edit", array( + "order_id" => $order_id + )); + } + + public function updateStatus($order_id = null) + { + if (null !== $response = $this->checkAuth(AdminResources::ORDER, array(), AccessManager::UPDATE)) { + return $response; + } + + $message = null; + + try { + if ($order_id === null) { + $order_id = $this->getRequest()->get("order_id"); + } + + $order = OrderQuery::create()->findPk($order_id); + + $statusId = $this->getRequest()->get("status_id"); + $status = OrderStatusQuery::create()->findPk($statusId); + + if (null === $order) { + throw new \InvalidArgumentException("The order you want to update status does not exist"); + } + if (null === $status) { + throw new \InvalidArgumentException("The status you want to set to the order does not exist"); + } + + $event = new OrderEvent($order); + $event->setStatus($statusId); + + $this->dispatch(TheliaEvents::ORDER_UPDATE_STATUS, $event); + } catch (\Exception $e) { + $message = $e->getMessage(); + } + + $params = array(); + + if ($message) { + $params["update_status_error_message"] = $message; + } + + $browsedPage = $this->getRequest()->get("order_page"); + $currentStatus = $this->getRequest()->get("status"); + + if ($browsedPage) { + $params["order_page"] = $browsedPage; + + if (null !== $currentStatus) { + $params["status"] = $currentStatus; + } + + $response = $this->generateRedirectFromRoute("admin.order.list", $params); + } else { + $params["tab"] = $this->getRequest()->get("tab", 'cart'); + + $response = $this->generateRedirectFromRoute("admin.order.update.view", $params, [ 'order_id' => $order_id ]); + } + + return $response; + } + + public function updateDeliveryRef($order_id) + { + if (null !== $response = $this->checkAuth(AdminResources::ORDER, array(), AccessManager::UPDATE)) { + return $response; + } + + $message = null; + + try { + $order = OrderQuery::create()->findPk($order_id); + + $deliveryRef = $this->getRequest()->get("delivery_ref"); + + if (null === $order) { + throw new \InvalidArgumentException("The order you want to update status does not exist"); + } + + $event = new OrderEvent($order); + $event->setDeliveryRef($deliveryRef); + + $this->dispatch(TheliaEvents::ORDER_UPDATE_DELIVERY_REF, $event); + } catch (\Exception $e) { + $message = $e->getMessage(); + } + + $params = array(); + + if ($message) { + $params["update_status_error_message"] = $message; + } + + $params["tab"] = $this->getRequest()->get("tab", 'bill'); + + return $this->generateRedirectFromRoute( + "admin.order.update.view", + $params, + [ 'order_id' => $order_id ] + ); + } + + public function updateAddress($order_id) + { + if (null !== $response = $this->checkAuth(AdminResources::ORDER, array(), AccessManager::UPDATE)) { + return $response; + } + + $message = null; + + $orderUpdateAddress = new OrderUpdateAddress($this->getRequest()); + + try { + $order = OrderQuery::create()->findPk($order_id); + + if (null === $order) { + throw new \InvalidArgumentException("The order you want to update does not exist"); + } + + $form = $this->validateForm($orderUpdateAddress, "post"); + + $orderAddress = OrderAddressQuery::create()->findPk($form->get("id")->getData()); + + if ($orderAddress->getId() !== $order->getInvoiceOrderAddressId() && $orderAddress->getId() !== $order->getDeliveryOrderAddressId()) { + throw new \InvalidArgumentException("The order address you want to update does not belong to the current order not exist"); + } + + $event = new OrderAddressEvent( + $form->get("title")->getData(), + $form->get("firstname")->getData(), + $form->get("lastname")->getData(), + $form->get("address1")->getData(), + $form->get("address2")->getData(), + $form->get("address3")->getData(), + $form->get("zipcode")->getData(), + $form->get("city")->getData(), + $form->get("country")->getData(), + $form->get("phone")->getData(), + $form->get("company")->getData(), + $form->get("cellphone")->getData(), + $form->get("state")->getData() + ); + $event->setOrderAddress($orderAddress); + $event->setOrder($order); + + $this->dispatch(TheliaEvents::ORDER_UPDATE_ADDRESS, $event); + } catch (\Exception $e) { + $message = $e->getMessage(); + } + + $params = array(); + + if ($message) { + $params["update_status_error_message"] = $message; + } + + $params["tab"] = $this->getRequest()->get("tab", 'bill'); + + return $this->generateRedirectFromRoute( + "admin.order.update.view", + $params, + [ 'order_id' => $order_id ] + ); + } + + public function generateInvoicePdf($order_id, $browser) + { + if (null !== $response = $this->checkAuth(AdminResources::ORDER, array(), AccessManager::UPDATE)) { + return $response; + } + return $this->generateBackOfficeOrderPdf($order_id, ConfigQuery::read('pdf_invoice_file', 'invoice'), $browser == 0); + } + + public function generateDeliveryPdf($order_id, $browser) + { + if (null !== $response = $this->checkAuth(AdminResources::ORDER, array(), AccessManager::UPDATE)) { + return $response; + } + return $this->generateBackOfficeOrderPdf($order_id, ConfigQuery::read('pdf_delivery_file', 'delivery'), $browser == 0); + } + + private function generateBackOfficeOrderPdf($order_id, $fileName, $browser) + { + if (null === $response = $this->generateOrderPdf($order_id, $fileName, true, true, $browser == 0)) { + return $this->generateRedirectFromRoute( + "admin.order.update.view", + [], + ['order_id' => $order_id ] + ); + } + + return $response; + } +} diff --git a/core/lib/Thelia/Controller/Admin/OrderStatusController.php b/core/lib/Thelia/Controller/Admin/OrderStatusController.php new file mode 100644 index 00000000..ab1cd19a --- /dev/null +++ b/core/lib/Thelia/Controller/Admin/OrderStatusController.php @@ -0,0 +1,293 @@ + + * @since 2.4 + */ +class OrderStatusController extends AbstractCrudController +{ + public function __construct() + { + parent::__construct( + 'orderstatus', + 'manual', + 'order', + AdminResources::ORDER_STATUS, + TheliaEvents::ORDER_STATUS_CREATE, + TheliaEvents::ORDER_STATUS_UPDATE, + TheliaEvents::ORDER_STATUS_DELETE, + null, + TheliaEvents::ORDER_STATUS_UPDATE_POSITION + ); + } + + /** + * Return the creation form for this object + */ + protected function getCreationForm() + { + return $this->createForm(AdminForm::ORDER_STATUS_CREATION); + } + + /** + * Return the update form for this object + */ + protected function getUpdateForm() + { + return $this->createForm(AdminForm::ORDER_STATUS_MODIFICATION); + } + + /** + * Hydrate the update form for this object, before passing it to the update template + * + * @param OrderStatus $object + * @return OrderStatusModificationForm $object + */ + protected function hydrateObjectForm($object) + { + // Prepare the data that will hydrate the form + $data = [ + 'id' => $object->getId(), + 'locale' => $object->getLocale(), + 'title' => $object->getTitle(), + 'chapo' => $object->getChapo(), + 'description' => $object->getDescription(), + 'postscriptum' => $object->getPostscriptum(), + 'color' => $object->getColor(), + 'code' => $object->getCode() + ]; + + $form = $this->createForm(AdminForm::ORDER_STATUS_MODIFICATION, "form", $data); + + // Setup the object form + return $form; + } + + /** + * Creates the creation event with the provided form data + * + * @param array $formData + * @return OrderStatusCreateEvent + */ + protected function getCreationEvent($formData) + { + $orderStatusCreateEvent = new OrderStatusCreateEvent(); + + $orderStatusCreateEvent + ->setLocale($formData['locale']) + ->setTitle($formData['title']) + ->setCode($formData['code']) + ->setColor($formData['color']) + ; + + return $orderStatusCreateEvent; + } + + /** + * Creates the update event with the provided form data + * + * @param array $formData + * @return OrderStatusUpdateEvent + */ + protected function getUpdateEvent($formData) + { + $orderStatusUpdateEvent = new OrderStatusUpdateEvent($formData['id']); + + $orderStatusUpdateEvent + ->setLocale($formData['locale']) + ->setTitle($formData['title']) + ->setChapo($formData['chapo']) + ->setDescription($formData['description']) + ->setPostscriptum($formData['postscriptum']) + ->setCode($formData['code']) + ->setColor($formData['color']) + ; + + return $orderStatusUpdateEvent; + } + + /** + * Creates the delete event with the provided form data + * + * @return OrderStatusDeleteEvent + * @throws \Exception + */ + protected function getDeleteEvent() + { + return new OrderStatusDeleteEvent((int) $this->getRequest()->get('order_status_id')); + } + + /** + * Return true if the event contains the object, e.g. the action has updated the object in the event. + * + * @param OrderStatusEvent $event + * @return bool + */ + protected function eventContainsObject($event) + { + return $event->hasOrderStatus(); + } + + /** + * Get the created object from an event. + * + * @param $event \Thelia\Core\Event\OrderStatus\OrderStatusEvent + * + * @return null|OrderStatus + */ + protected function getObjectFromEvent($event) + { + return $event->getOrderStatus(); + } + + /** + * Load an existing object from the database + * + * @return \Thelia\Model\OrderStatus + */ + protected function getExistingObject() + { + $orderStatus = OrderStatusQuery::create() + ->findOneById($this->getRequest()->get('order_status_id', 0)); + + if (null !== $orderStatus) { + $orderStatus->setLocale($this->getCurrentEditionLocale()); + } + + return $orderStatus; + } + + /** + * Returns the object label form the object event (name, title, etc.) + * + * @param OrderStatus $object + * + * @return string order status title + */ + protected function getObjectLabel($object) + { + return $object->getTitle(); + } + + /** + * Returns the object ID from the object + * + * @param OrderStatus $object + * + * @return int order status id + */ + protected function getObjectId($object) + { + return $object->getId(); + } + + /** + * Render the main list template + * + * @param string $currentOrder , if any, null otherwise. + * + * @return Response + */ + protected function renderListTemplate($currentOrder) + { + $this->getListOrderFromSession('orderstatus', 'order', 'manual'); + + return $this->render('order-status', [ + 'order' => $currentOrder, + ]); + } + + protected function getEditionArguments() + { + return [ + 'order_status_id' => $this->getRequest()->get('order_status_id', 0), + 'current_tab' => $this->getRequest()->get('current_tab', 'general') + ]; + } + + /** + * Render the edition template + */ + protected function renderEditionTemplate() + { + return $this->render('order-status-edit', $this->getEditionArguments()); + } + + /** + * Redirect to the edition template + */ + protected function redirectToEditionTemplate() + { + return $this->generateRedirectFromRoute( + 'admin.order-status.update', + [], + $this->getEditionArguments() + ); + } + + /** + * Redirect to the list template + */ + protected function redirectToListTemplate() + { + return $this->generateRedirectFromRoute('admin.order-status.default'); + } + + /** + * @param $positionChangeMode + * @param $positionValue + * @return UpdatePositionEvent|void + */ + protected function createUpdatePositionEvent($positionChangeMode, $positionValue) + { + return new UpdatePositionEvent( + $this->getRequest()->get('order_status_id', null), + $positionChangeMode, + $positionValue + ); + } + + /** + * @param $event \Thelia\Core\Event\UpdatePositionEvent + * @return null|Response + */ + protected function performAdditionalUpdatePositionAction($event) + { + $folder = OrderStatusQuery::create()->findPk($event->getObjectId()); + + if ($folder != null) { + return $this->generateRedirectFromRoute( + 'admin.order-status.default' + ); + } else { + return null; + } + } +} diff --git a/core/lib/Thelia/Controller/Admin/ProductController.php b/core/lib/Thelia/Controller/Admin/ProductController.php new file mode 100644 index 00000000..aa391957 --- /dev/null +++ b/core/lib/Thelia/Controller/Admin/ProductController.php @@ -0,0 +1,1951 @@ + + */ +class ProductController extends AbstractSeoCrudController +{ + public function __construct() + { + parent::__construct( + 'product', + 'manual', + 'product_order', + AdminResources::PRODUCT, + TheliaEvents::PRODUCT_CREATE, + TheliaEvents::PRODUCT_UPDATE, + TheliaEvents::PRODUCT_DELETE, + TheliaEvents::PRODUCT_TOGGLE_VISIBILITY, + TheliaEvents::PRODUCT_UPDATE_POSITION, + TheliaEvents::PRODUCT_UPDATE_SEO + ); + } + + /** + * Attributes ajax tab loading + */ + public function loadAttributesAjaxTabAction() + { + return $this->render( + 'ajax/product-attributes-tab', + array( + 'product_id' => $this->getRequest()->get('product_id', 0), + ) + ); + } + + /** + * Related information ajax tab loading + */ + public function loadRelatedAjaxTabAction() + { + return $this->render( + 'ajax/product-related-tab', + array( + 'product_id' => $this->getRequest()->get('product_id', 0), + 'folder_id' => $this->getRequest()->get('folder_id', 0), + 'accessory_category_id' => $this->getRequest()->get('accessory_category_id', 0) + ) + ); + } + + protected function getCreationForm() + { + return $this->createForm(AdminForm::PRODUCT_CREATION); + } + + protected function getUpdateForm() + { + return $this->createForm(AdminForm::PRODUCT_MODIFICATION, "form", [], []); + } + + protected function getCreationEvent($formData) + { + $createEvent = new ProductCreateEvent(); + + $createEvent + ->setRef($formData['ref']) + ->setTitle($formData['title']) + ->setLocale($formData['locale']) + ->setDefaultCategory($formData['default_category']) + ->setVisible($formData['visible']) + ->setVirtual($formData['virtual']) + ->setBasePrice($formData['price']) + ->setBaseWeight($formData['weight']) + ->setCurrencyId($formData['currency']) + ->setTaxRuleId($formData['tax_rule']) + ->setBaseQuantity($formData['quantity']) + ->setTemplateId($formData['template_id']) + ; + + return $createEvent; + } + + protected function getUpdateEvent($formData) + { + $changeEvent = new ProductUpdateEvent($formData['id']); + + $changeEvent + ->setLocale($formData['locale']) + ->setRef($formData['ref']) + ->setTitle($formData['title']) + ->setChapo($formData['chapo']) + ->setDescription($formData['description']) + ->setPostscriptum($formData['postscriptum']) + ->setVisible($formData['visible']) + ->setVirtual($formData['virtual']) + ->setDefaultCategory($formData['default_category']) + ->setBrandId($formData['brand_id']) + ->setVirtualDocumentId($formData['virtual_document_id']) + ; + + // Create and dispatch the change event + return $changeEvent; + } + + protected function createUpdatePositionEvent($positionChangeMode, $positionValue) + { + return new UpdatePositionEvent( + $this->getRequest()->get('product_id', null), + $positionChangeMode, + $positionValue, + $this->getRequest()->get('category_id', null) + ); + } + + protected function getDeleteEvent() + { + return new ProductDeleteEvent($this->getRequest()->get('product_id', 0)); + } + + /** + * @param ProductEvent $event + * @return mixed + */ + protected function eventContainsObject($event) + { + return $event->hasProduct(); + } + + /** + * @param ProductPrice $productPrice + * @param ProductSaleElements $saleElement + * @param Currency $defaultCurrency + * @param Currency $currentCurrency + */ + protected function updatePriceFromDefaultCurrency($productPrice, $saleElement, $defaultCurrency, $currentCurrency) + { + // Get price for default currency + $priceForDefaultCurrency = ProductPriceQuery::create() + ->filterByCurrency($defaultCurrency) + ->filterByProductSaleElements($saleElement) + ->findOne() + ; + + if ($priceForDefaultCurrency !== null) { + $productPrice + ->setPrice($priceForDefaultCurrency->getPrice() * $currentCurrency->getRate()) + ->setPromoPrice($priceForDefaultCurrency->getPromoPrice() * $currentCurrency->getRate()) + ; + } + } + + protected function appendValue(&$array, $key, $value) + { + if (! isset($array[$key])) { + $array[$key] = array(); + } + + $array[$key][] = $value; + } + + /** + * @param Product $object + * @return ProductModificationForm + */ + protected function hydrateObjectForm($object) + { + // Find product's sale elements + $saleElements = ProductSaleElementsQuery::create() + ->filterByProduct($object) + ->find(); + + $defaultCurrency = Currency::getDefaultCurrency(); + $currentCurrency = $this->getCurrentEditionCurrency(); + + // Common parts + $defaultPseData = $combinationPseData = array( + "product_id" => $object->getId(), + "tax_rule" => $object->getTaxRuleId() + ); + + /** @var ProductSaleElements $saleElement */ + foreach ($saleElements as $saleElement) { + // Get the product price for the current currency + $productPrice = ProductPriceQuery::create() + ->filterByCurrency($currentCurrency) + ->filterByProductSaleElements($saleElement) + ->findOne() + ; + + // No one exists ? + if ($productPrice === null) { + $productPrice = new ProductPrice(); + + // If the current currency is not the default one, calculate the price + // using default currency price and current currency rate + if ($currentCurrency->getId() != $defaultCurrency->getId()) { + $productPrice->setFromDefaultCurrency(true); + } + } + + // Caclulate prices if we have to use the rate * default currency price + if ($productPrice->getFromDefaultCurrency() == true) { + $this->updatePriceFromDefaultCurrency($productPrice, $saleElement, $defaultCurrency, $currentCurrency); + } + + $isDefaultPse = \count($saleElement->getAttributeCombinations()) == 0; + + // If this PSE has no combination -> this is the default one + // affect it to the thelia.admin.product_sale_element.update form + if ($isDefaultPse) { + $defaultPseData = array( + "product_sale_element_id" => $saleElement->getId(), + "reference" => $saleElement->getRef(), + "price" => $this->formatPrice($productPrice->getPrice()), + "price_with_tax" => $this->formatPrice($this->computePrice($productPrice->getPrice(), 'without_tax', $object)), + "use_exchange_rate" => $productPrice->getFromDefaultCurrency() ? 1 : 0, + "currency" => $productPrice->getCurrencyId(), + "weight" => $saleElement->getWeight(), + "quantity" => $saleElement->getQuantity(), + "sale_price" => $this->formatPrice($productPrice->getPromoPrice()), + "sale_price_with_tax" => $this->formatPrice($this->computePrice($productPrice->getPromoPrice(), 'without_tax', $object)), + "onsale" => $saleElement->getPromo() > 0 ? 1 : 0, + "isnew" => $saleElement->getNewness() > 0 ? 1 : 0, + "isdefault" => $saleElement->getIsDefault() > 0 ? 1 : 0, + "ean_code" => $saleElement->getEanCode() + ); + } else { + if ($saleElement->getIsDefault()) { + $combinationPseData['default_pse'] = $saleElement->getId(); + $combinationPseData['currency'] = $currentCurrency->getId(); + $combinationPseData['use_exchange_rate'] = $productPrice->getFromDefaultCurrency() ? 1 : 0; + } + + $this->appendValue($combinationPseData, "product_sale_element_id", $saleElement->getId()); + $this->appendValue($combinationPseData, "reference", $saleElement->getRef()); + $this->appendValue($combinationPseData, "price", $this->formatPrice($productPrice->getPrice())); + $this->appendValue($combinationPseData, "price_with_tax", $this->formatPrice($this->computePrice($productPrice->getPrice(), 'without_tax', $object))); + $this->appendValue($combinationPseData, "weight", $saleElement->getWeight()); + $this->appendValue($combinationPseData, "quantity", $saleElement->getQuantity()); + $this->appendValue($combinationPseData, "sale_price", $this->formatPrice($productPrice->getPromoPrice())); + $this->appendValue($combinationPseData, "sale_price_with_tax", $this->formatPrice($this->computePrice($productPrice->getPromoPrice(), 'without_tax', $object))); + $this->appendValue($combinationPseData, "onsale", $saleElement->getPromo() > 0 ? 1 : 0); + $this->appendValue($combinationPseData, "isnew", $saleElement->getNewness() > 0 ? 1 : 0); + $this->appendValue($combinationPseData, "isdefault", $saleElement->getIsDefault() > 0 ? 1 : 0); + $this->appendValue($combinationPseData, "ean_code", $saleElement->getEanCode()); + } + } + + $defaultPseForm = $this->createForm(AdminForm::PRODUCT_DEFAULT_SALE_ELEMENT_UPDATE, "form", $defaultPseData); + $this->getParserContext()->addForm($defaultPseForm); + + $combinationPseForm = $this->createForm(AdminForm::PRODUCT_SALE_ELEMENT_UPDATE, "form", $combinationPseData); + $this->getParserContext()->addForm($combinationPseForm); + + // Hydrate the "SEO" tab form + $this->hydrateSeoForm($object); + + // The "General" tab form + $data = array( + 'id' => $object->getId(), + 'ref' => $object->getRef(), + 'locale' => $object->getLocale(), + 'title' => $object->getTitle(), + 'chapo' => $object->getChapo(), + 'description' => $object->getDescription(), + 'postscriptum' => $object->getPostscriptum(), + 'visible' => $object->getVisible(), + 'virtual' => $object->getVirtual(), + 'default_category' => $object->getDefaultCategoryId(), + 'brand_id' => $object->getBrandId() + ); + + // Virtual document + if (array_key_exists("product_sale_element_id", $defaultPseData)) { + $virtualDocumentId = \intval(MetaDataQuery::getVal('virtual', MetaData::PSE_KEY, $defaultPseData['product_sale_element_id'])); + if ($virtualDocumentId) { + $data["virtual_document_id"] = $virtualDocumentId; + } + } + + // Setup the object form + return $this->createForm(AdminForm::PRODUCT_MODIFICATION, "form", $data, []); + } + + /** + * @param ProductEvent $event + * @return null + */ + protected function getObjectFromEvent($event) + { + return $event->hasProduct() ? $event->getProduct() : null; + } + + protected function getExistingObject() + { + $product = ProductQuery::create() + ->findOneById($this->getRequest()->get('product_id', 0)); + + if (null !== $product) { + $product->setLocale($this->getCurrentEditionLocale()); + } + + return $product; + } + + /** + * @param Product $object + * @return mixed + */ + protected function getObjectLabel($object) + { + return $object->getTitle(); + } + + /** + * @param Product $object + * @return mixed + */ + protected function getObjectId($object) + { + return $object->getId(); + } + + protected function getEditionArguments() + { + return array( + 'category_id' => $this->getCategoryId(), + 'product_id' => $this->getRequest()->get('product_id', 0), + 'folder_id' => $this->getRequest()->get('folder_id', 0), + 'accessory_category_id' => $this->getRequest()->get('accessory_category_id', 0), + 'current_tab' => $this->getRequest()->get('current_tab', 'general'), + 'page' => $this->getRequest()->get('page', 1) + ); + } + + protected function getCategoryId() + { + // Trouver le category_id, soit depuis la reques, souit depuis le produit courant + $category_id = $this->getRequest()->get('category_id', null); + + if ($category_id == null) { + $product = $this->getExistingObject(); + + if ($product !== null) { + $category_id = $product->getDefaultCategoryId(); + } + } + + return $category_id != null ? $category_id : 0; + } + + protected function renderListTemplate($currentOrder) + { + $this->getListOrderFromSession('product', 'product_order', 'manual'); + + return $this->render( + 'categories', + array( + 'product_order' => $currentOrder, + 'category_id' => $this->getCategoryId(), + 'page' => $this->getRequest()->get('page', 1) + ) + ); + } + + protected function redirectToListTemplate() + { + return $this->generateRedirectFromRoute( + 'admin.products.default', + [ + 'category_id' => $this->getCategoryId(), + 'page' => $this->getRequest()->get('page', 1) + ] + ); + } + + protected function renderEditionTemplate() + { + return $this->render('product-edit', $this->getEditionArguments()); + } + + protected function redirectToEditionTemplate() + { + return $this->generateRedirectFromRoute("admin.products.update", $this->getEditionArguments()); + } + + /** + * Online status toggle product + */ + public function setToggleVisibilityAction() + { + // Check current user authorization + if (null !== $response = $this->checkAuth($this->resourceCode, array(), AccessManager::UPDATE)) { + return $response; + } + + $event = new ProductToggleVisibilityEvent($this->getExistingObject()); + + try { + $this->dispatch(TheliaEvents::PRODUCT_TOGGLE_VISIBILITY, $event); + } catch (\Exception $ex) { + // Any error + return $this->errorPage($ex); + } + + // Ajax response -> no action + return $this->nullResponse(); + } + + protected function performAdditionalDeleteAction($deleteEvent) + { + return $this->generateRedirectFromRoute( + 'admin.products.default', + ['category_id' => $this->getCategoryId()] + ); + } + + protected function performAdditionalUpdatePositionAction($positionEvent) + { + return $this->generateRedirectFromRoute( + 'admin.categories.default', + ['category_id' => $this->getCategoryId()] + ); + } + + + /** + * @param ProductUpdateEvent $updateEvent + * + * @return Response + */ + protected function performAdditionalUpdateAction($updateEvent) + { + // Associate the file if it's a virtual product + // and with only 1 PSE + $virtualDocumentId = \intval($updateEvent->getVirtualDocumentId()); + + if ($virtualDocumentId >= 0) { + $defaultPSE = ProductSaleElementsQuery::create() + ->filterByProductId($updateEvent->getProductId()) + ->filterByIsDefault(true) + ->findOne(); + + if (null !== $defaultPSE) { + if ($virtualDocumentId !== 0) { + $assocEvent = new MetaDataCreateOrUpdateEvent('virtual', MetaData::PSE_KEY, $defaultPSE->getId(), $virtualDocumentId); + $this->dispatch(TheliaEvents::META_DATA_UPDATE, $assocEvent); + } else { + $assocEvent = new MetaDataDeleteEvent('virtual', MetaData::PSE_KEY, $defaultPSE->getId()); + $this->dispatch(TheliaEvents::META_DATA_DELETE, $assocEvent); + } + } + } + + return null; + } + + /** + * return a list of document which will be displayed in AJAX + * + * @param $productId + * @param $pseId + * + * @return Response + */ + public function getVirtualDocumentListAjaxAction($productId, $pseId) + { + $this->checkAuth(AdminResources::PRODUCT, array(), AccessManager::VIEW); + $this->checkXmlHttpRequest(); + + $selectedId = \intval(MetaDataQuery::getVal('virtual', MetaData::PSE_KEY, $pseId)); + + $documents = ProductDocumentQuery::create() + ->filterByProductId($productId) + ->filterByVisible(0) + ->orderByPosition() + ->find() + ; + + $results = []; + + if (null !== $documents) { + /** @var ProductDocument $document */ + foreach ($documents as $document) { + $results[] = [ + 'id' => $document->getId(), + 'title' => $document->getTitle(), + 'file' => $document->getFile(), + 'selected' => ($document->getId() == $selectedId) + ]; + } + } + + return $this->jsonResponse(json_encode($results)); + } + + // -- Related content management ------------------------------------------- + + public function getAvailableRelatedContentAction($productId, $folderId) + { + $result = array(); + + $folders = FolderQuery::create()->filterById($folderId)->find(); + + if ($folders !== null) { + $list = ContentQuery::create() + ->joinWithI18n($this->getCurrentEditionLocale()) + ->filterByFolder($folders, Criteria::IN) + ->filterById(ProductAssociatedContentQuery::create()->filterByProductId($productId)->select('content_id')->find(), Criteria::NOT_IN) + ->find(); + ; + + if ($list !== null) { + /** @var Content $item */ + foreach ($list as $item) { + $result[] = array('id' => $item->getId(), 'title' => $item->getTitle()); + } + } + } + + return $this->jsonResponse(json_encode($result)); + } + + public function addRelatedContentAction() + { + // Check current user authorization + if (null !== $response = $this->checkAuth($this->resourceCode, array(), AccessManager::UPDATE)) { + return $response; + } + + $content_id = \intval($this->getRequest()->get('content_id')); + + if ($content_id > 0) { + $event = new ProductAddContentEvent( + $this->getExistingObject(), + $content_id + ); + + try { + $this->dispatch(TheliaEvents::PRODUCT_ADD_CONTENT, $event); + } catch (\Exception $ex) { + // Any error + return $this->errorPage($ex); + } + } + + return $this->redirectToEditionTemplate(); + } + + public function deleteRelatedContentAction() + { + // Check current user authorization + if (null !== $response = $this->checkAuth($this->resourceCode, array(), AccessManager::UPDATE)) { + return $response; + } + + $content_id = \intval($this->getRequest()->get('content_id')); + + if ($content_id > 0) { + $event = new ProductDeleteContentEvent( + $this->getExistingObject(), + $content_id + ); + + try { + $this->dispatch(TheliaEvents::PRODUCT_REMOVE_CONTENT, $event); + } catch (\Exception $ex) { + // Any error + return $this->errorPage($ex); + } + } + + return $this->redirectToEditionTemplate(); + } + + // -- Accessories management ---------------------------------------------- + + public function getAvailableAccessoriesAction($productId, $categoryId) + { + $result = array(); + + $categories = CategoryQuery::create()->filterById($categoryId)->find(); + + if ($categories !== null) { + $list = ProductQuery::create() + ->joinWithI18n($this->getCurrentEditionLocale()) + ->filterByCategory($categories, Criteria::IN) + ->filterById(AccessoryQuery::create()->filterByProductId($productId)->select('accessory')->find(), Criteria::NOT_IN) + ->find(); + ; + + if ($list !== null) { + /** @var Product $item */ + foreach ($list as $item) { + $result[] = array('id' => $item->getId(), 'title' => $item->getTitle()); + } + } + } + + return $this->jsonResponse(json_encode($result)); + } + + public function addAccessoryAction() + { + // Check current user authorization + if (null !== $response = $this->checkAuth($this->resourceCode, array(), AccessManager::UPDATE)) { + return $response; + } + + $accessory_id = \intval($this->getRequest()->get('accessory_id')); + + if ($accessory_id > 0) { + $event = new ProductAddAccessoryEvent( + $this->getExistingObject(), + $accessory_id + ); + + try { + $this->dispatch(TheliaEvents::PRODUCT_ADD_ACCESSORY, $event); + } catch (\Exception $ex) { + // Any error + return $this->errorPage($ex); + } + } + + return $this->redirectToEditionTemplate(); + } + + public function deleteAccessoryAction() + { + // Check current user authorization + if (null !== $response = $this->checkAuth($this->resourceCode, array(), AccessManager::UPDATE)) { + return $response; + } + + $accessory_id = \intval($this->getRequest()->get('accessory_id')); + + if ($accessory_id > 0) { + $event = new ProductDeleteAccessoryEvent( + $this->getExistingObject(), + $accessory_id + ); + + try { + $this->dispatch(TheliaEvents::PRODUCT_REMOVE_ACCESSORY, $event); + } catch (\Exception $ex) { + // Any error + return $this->errorPage($ex); + } + } + + return $this->redirectToEditionTemplate(); + } + + /** + * Update accessory position + */ + public function updateAccessoryPositionAction() + { + $accessory = AccessoryQuery::create()->findPk($this->getRequest()->get('accessory_id', null)); + + return $this->genericUpdatePositionAction( + $accessory, + TheliaEvents::PRODUCT_UPDATE_ACCESSORY_POSITION + ); + } + + /** + * Update related content position + */ + public function updateContentPositionAction() + { + $content = ProductAssociatedContentQuery::create()->findPk($this->getRequest()->get('content_id', null)); + + return $this->genericUpdatePositionAction( + $content, + TheliaEvents::PRODUCT_UPDATE_CONTENT_POSITION + ); + } + + /** + * Change product template for a given product. + * + * @param int $productId + * @return mixed|\Symfony\Component\HttpFoundation\Response + */ + public function setProductTemplateAction($productId) + { + // Check current user authorization + if (null !== $response = $this->checkAuth($this->resourceCode, array(), AccessManager::UPDATE)) { + return $response; + } + + $product = ProductQuery::create()->findPk($productId); + + if ($product != null) { + $template_id = \intval($this->getRequest()->get('template_id', 0)); + + $this->dispatch( + TheliaEvents::PRODUCT_SET_TEMPLATE, + new ProductSetTemplateEvent($product, $template_id, $this->getCurrentEditionCurrency()->getId()) + ); + } + + return $this->redirectToEditionTemplate(); + } + + /** + * Update product attributes and features + * + * @param int $productId + * + * @return \Symfony\Component\HttpFoundation\RedirectResponse|\Symfony\Component\HttpFoundation\Response + * @throws \Propel\Runtime\Exception\PropelException + */ + public function updateAttributesAndFeaturesAction($productId) + { + $product = ProductQuery::create()->findPk($productId); + + if ($product != null) { + $featureTemplate = FeatureTemplateQuery::create()->filterByTemplateId($product->getTemplateId())->find(); + + if ($featureTemplate !== null) { + // Get all features for the template attached to this product + $allFeatures = FeatureQuery::create() + ->filterByFeatureTemplate($featureTemplate) + ->find(); + + $updatedFeatures = array(); + + // Update all features values, starting with feature av. values + $featureValues = $this->getRequest()->get('feature_value', array()); + + foreach ($featureValues as $featureId => $featureValueList) { + // Delete all features av. for this feature. + $event = new FeatureProductDeleteEvent($productId, $featureId); + + $this->dispatch(TheliaEvents::PRODUCT_FEATURE_DELETE_VALUE, $event); + + // Add then all selected values + foreach ($featureValueList as $featureValue) { + $event = new FeatureProductUpdateEvent($productId, $featureId, $featureValue); + + $this->dispatch(TheliaEvents::PRODUCT_FEATURE_UPDATE_VALUE, $event); + } + + $updatedFeatures[] = $featureId; + } + + // Update then features text values + $featureTextValues = $this->getRequest()->get('feature_text_value', array()); + + foreach ($featureTextValues as $featureId => $featureValue) { + // Check if a FeatureProduct exists for this product and this feature (for another lang) + $freeTextFeatureProduct = FeatureProductQuery::create() + ->filterByProductId($productId) + ->filterByIsFreeText(true) + ->findOneByFeatureId($featureId); + + // If no corresponding FeatureProduct exists AND if the feature_text_value is empty, do nothing + if (\is_null($freeTextFeatureProduct) && empty($featureValue)) { + continue; + } + + $event = new FeatureProductUpdateEvent($productId, $featureId, $featureValue, true); + $event->setLocale($this->getCurrentEditionLocale()); + + $this->dispatch(TheliaEvents::PRODUCT_FEATURE_UPDATE_VALUE, $event); + + $updatedFeatures[] = $featureId; + } + + // Delete features which don't have any values + /** @var Feature $feature */ + foreach ($allFeatures as $feature) { + if (! \in_array($feature->getId(), $updatedFeatures)) { + $event = new FeatureProductDeleteEvent($productId, $feature->getId()); + + $this->dispatch(TheliaEvents::PRODUCT_FEATURE_DELETE_VALUE, $event); + } + } + } + } + + // If we have to stay on the same page, do not redirect to the successUrl, + // just redirect to the edit page again. + if ($this->getRequest()->get('save_mode') == 'stay') { + return $this->redirectToEditionTemplate(); + } + + // Redirect to the category/product list + return $this->redirectToListTemplate(); + } + + public function addAdditionalCategoryAction() + { + // Check current user authorization + if (null !== $response = $this->checkAuth($this->resourceCode, array(), AccessManager::UPDATE)) { + return $response; + } + + $category_id = \intval($this->getRequest()->request->get('additional_category_id')); + + if ($category_id > 0) { + $event = new ProductAddCategoryEvent( + $this->getExistingObject(), + $category_id + ); + + try { + $this->dispatch(TheliaEvents::PRODUCT_ADD_CATEGORY, $event); + } catch (\Exception $ex) { + // Any error + return $this->errorPage($ex); + } + } + + return $this->redirectToEditionTemplate(); + } + + public function deleteAdditionalCategoryAction() + { + // Check current user authorization + if (null !== $response = $this->checkAuth($this->resourceCode, array(), AccessManager::UPDATE)) { + return $response; + } + + $category_id = \intval($this->getRequest()->get('additional_category_id')); + + if ($category_id > 0) { + $event = new ProductDeleteCategoryEvent( + $this->getExistingObject(), + $category_id + ); + + try { + $this->dispatch(TheliaEvents::PRODUCT_REMOVE_CATEGORY, $event); + } catch (\Exception $ex) { + // Any error + return $this->errorPage($ex); + } + } + + return $this->redirectToEditionTemplate(); + } + + // -- Product combination management --------------------------------------- + + public function getAttributeValuesAction(/** @noinspection PhpUnusedParameterInspection */ $productId, $attributeId) + { + $result = array(); + + // Get attribute for this product + $attribute = AttributeQuery::create()->findPk($attributeId); + + if ($attribute !== null) { + $values = AttributeAvQuery::create() + ->joinWithI18n($this->getCurrentEditionLocale()) + ->filterByAttribute($attribute) + ->find(); + ; + + if ($values !== null) { + /** @var AttributeAv $value */ + foreach ($values as $value) { + $result[] = array('id' => $value->getId(), 'title' => $value->getTitle()); + } + } + } + + return $this->jsonResponse(json_encode($result)); + } + + public function addAttributeValueToCombinationAction(/** @noinspection PhpUnusedParameterInspection */ $productId, $attributeAvId, $combination) + { + $result = array(); + + // Get attribute for this product + $attributeAv = AttributeAvQuery::create()->joinWithI18n($this->getCurrentEditionLocale())->findPk($attributeAvId); + + if ($attributeAv !== null) { + $addIt = true; + + $attribute = AttributeQuery::create() + ->joinWithI18n($this->getCurrentEditionLocale()) + ->findPk($attributeAv->getAttributeId()); + + // Check if this attribute is not already present + $combinationArray = explode(',', $combination); + + foreach ($combinationArray as $id) { + $attrAv = AttributeAvQuery::create()->joinWithI18n($this->getCurrentEditionLocale())->findPk($id); + + if ($attrAv !== null) { + if ($attrAv->getId() == $attributeAv->getId()) { + $result['error'] = $this->getTranslator()->trans( + 'A value for attribute "%name" is already present in the combination', + array('%name' => $attribute->getTitle() . " : " . $attributeAv->getTitle()) + ); + + $addIt = false; + } + + $subAttribute = AttributeQuery::create() + ->joinWithI18n($this->getCurrentEditionLocale()) + ->findPk($attributeAv->getAttributeId()); + + $result[] = array('id' => $attrAv->getId(), 'title' => $subAttribute->getTitle() . " : " . $attrAv->getTitle()); + } + } + + if ($addIt) { + $result[] = array('id' => $attributeAv->getId(), 'title' => $attribute->getTitle() . " : " . $attributeAv->getTitle()); + } + } + + return $this->jsonResponse(json_encode($result)); + } + + /** + * A a new combination to a product + */ + public function addProductSaleElementAction() + { + // Check current user authorization + if (null !== $response = $this->checkAuth($this->resourceCode, array(), AccessManager::UPDATE)) { + return $response; + } + + $event = new ProductSaleElementCreateEvent( + $this->getExistingObject(), + $this->getRequest()->get('combination_attributes', array()), + $this->getCurrentEditionCurrency()->getId() + ); + + try { + $this->dispatch(TheliaEvents::PRODUCT_ADD_PRODUCT_SALE_ELEMENT, $event); + } catch (\Exception $ex) { + // Any error + return $this->errorPage($ex); + } + + return $this->redirectToEditionTemplate(); + } + + /** + * A a new combination to a product + */ + public function deleteProductSaleElementAction() + { + // Check current user authorization + if (null !== $response = $this->checkAuth($this->resourceCode, array(), AccessManager::UPDATE)) { + return $response; + } + + $event = new ProductSaleElementDeleteEvent( + $this->getRequest()->get('product_sale_element_id', 0), + $this->getCurrentEditionCurrency()->getId() + ); + + try { + $this->dispatch(TheliaEvents::PRODUCT_DELETE_PRODUCT_SALE_ELEMENT, $event); + } catch (\Exception $ex) { + // Any error + return $this->errorPage($ex); + } + + return $this->redirectToEditionTemplate(); + } + + /** + * Process a single PSE update, using form data array. + * + * @param array $data the form data + */ + protected function processSingleProductSaleElementUpdate($data) + { + $event = new ProductSaleElementUpdateEvent( + $this->getExistingObject(), + $data['product_sale_element_id'] + ); + + $event + ->setReference($data['reference']) + ->setPrice($data['price']) + ->setCurrencyId($data['currency']) + ->setWeight($data['weight']) + ->setQuantity($data['quantity']) + ->setSalePrice($data['sale_price']) + ->setOnsale($data['onsale']) + ->setIsnew($data['isnew']) + ->setIsdefault($data['isdefault']) + ->setEanCode($data['ean_code']) + ->setTaxRuleId($data['tax_rule']) + ->setFromDefaultCurrency($data['use_exchange_rate']) + ; + + $this->dispatch(TheliaEvents::PRODUCT_UPDATE_PRODUCT_SALE_ELEMENT, $event); + + // Log object modification + if (null !== $changedObject = $event->getProductSaleElement()) { + $this->adminLogAppend( + $this->resourceCode, + AccessManager::UPDATE, + sprintf( + "Product Sale Element (ID %s) for product reference %s modified", + $changedObject->getId(), + $event->getProduct()->getRef() + ), + $changedObject->getId() + ); + } + } + + /** + * Change a product sale element + * + * @param BaseForm $changeForm + * + * @return mixed|null|\Symfony\Component\HttpFoundation\RedirectResponse|\Symfony\Component\HttpFoundation\Response|Response + */ + protected function processProductSaleElementUpdate($changeForm) + { + // Check current user authorization + if (null !== $response = $this->checkAuth($this->resourceCode, array(), AccessManager::UPDATE)) { + return $response; + } + + try { + // Check the form against constraints violations + $form = $this->validateForm($changeForm, "POST"); + + // Get the form field values + $data = $form->getData(); + + if (\is_array($data['product_sale_element_id'])) { + // Common fields + $tmp_data = array( + 'tax_rule' => $data['tax_rule'], + 'currency' => $data['currency'], + 'use_exchange_rate' => $data['use_exchange_rate'], + ); + + $count = \count($data['product_sale_element_id']); + + for ($idx = 0; $idx < $count; $idx++) { + $tmp_data['product_sale_element_id'] = $pse_id = $data['product_sale_element_id'][$idx]; + $tmp_data['reference'] = $data['reference'][$idx]; + $tmp_data['price'] = $data['price'][$idx]; + $tmp_data['weight'] = $data['weight'][$idx]; + $tmp_data['quantity'] = $data['quantity'][$idx]; + $tmp_data['sale_price'] = $data['sale_price'][$idx]; + $tmp_data['onsale'] = isset($data['onsale'][$idx]) ? 1 : 0; + $tmp_data['isnew'] = isset($data['isnew'][$idx]) ? 1 : 0; + $tmp_data['isdefault'] = $data['default_pse'] == $pse_id; + $tmp_data['ean_code'] = $data['ean_code'][$idx]; + + $this->processSingleProductSaleElementUpdate($tmp_data); + } + } else { + // No need to preprocess data + $this->processSingleProductSaleElementUpdate($data); + } + + // If we have to stay on the same page, do not redirect to the successUrl, just redirect to the edit page again. + if ($this->getRequest()->get('save_mode') == 'stay') { + return $this->redirectToEditionTemplate(); + } + + // Redirect to the success URL + return $this->generateSuccessRedirect($changeForm); + } catch (FormValidationException $ex) { + // Form cannot be validated + $error_msg = $this->createStandardFormValidationErrorMessage($ex); + } catch (\Exception $ex) { + // Any other error + $error_msg = $ex->getMessage(); + } + + $this->setupFormErrorContext( + $this->getTranslator()->trans("ProductSaleElement modification"), + $error_msg, + $changeForm, + $ex + ); + + // At this point, the form has errors, and should be redisplayed. + return $this->renderEditionTemplate(); + } + + /** + * Process the change of product's PSE list. + */ + public function updateProductSaleElementsAction() + { + return $this->processProductSaleElementUpdate( + $this->createForm(AdminForm::PRODUCT_SALE_ELEMENT_UPDATE) + ); + } + + /** + * Update default product sale element (not attached to any combination) + */ + public function updateProductDefaultSaleElementAction() + { + return $this->processProductSaleElementUpdate( + $this->createForm(AdminForm::PRODUCT_DEFAULT_SALE_ELEMENT_UPDATE) + ); + } + + // Create combinations + protected function combine($input, &$output, &$tmp) + { + $current = array_shift($input); + + if (\count($input) > 0) { + foreach ($current as $element) { + $tmp[] = $element; + $this->combine($input, $output, $tmp); + array_pop($tmp); + } + } else { + foreach ($current as $element) { + $tmp[] = $element; + $output[] = $tmp; + array_pop($tmp); + } + } + } + + /** + * Build combinations from the combination output builder + */ + public function buildCombinationsAction() + { + // Check current user authorization + if (null !== $response = $this->checkAuth($this->resourceCode, array(), AccessManager::UPDATE)) { + return $response; + } + + $changeForm = $this->createForm(AdminForm::PRODUCT_COMBINATION_GENERATION); + + try { + // Check the form against constraints violations + $form = $this->validateForm($changeForm, "POST"); + + // Get the form field values + $data = $form->getData(); + + // Rework attributes_av array, to build an array which contains all combinations, + // in the form combination[] = array of combination attributes av IDs + // + // First, create an array of attributes_av ID in the form $attributes_av_list[$attribute_id] = array of attributes_av ID + // from the list of attribute_id:attributes_av ID from the form. + $combinations = $attributes_av_list = $tmp = array(); + + foreach ($data['attribute_av'] as $item) { + list($attribute_id, $attribute_av_id) = explode(':', $item); + + if (! isset($attributes_av_list[$attribute_id])) { + $attributes_av_list[$attribute_id] = array(); + } + + $attributes_av_list[$attribute_id][] = $attribute_av_id; + } + + // Next, recursively combine array + $this->combine($attributes_av_list, $combinations, $tmp); + + // Create event + $event = new ProductCombinationGenerationEvent( + $this->getExistingObject(), + $data['currency'], + $combinations + ); + + $event + ->setReference($data['reference'] == null ? '' : $data['reference']) + ->setPrice($data['price'] == null ? 0 : $data['price']) + ->setWeight($data['weight'] == null ? 0 : $data['weight']) + ->setQuantity($data['quantity'] == null ? 0 : $data['quantity']) + ->setSalePrice($data['sale_price'] == null ? 0 : $data['sale_price']) + ->setOnsale($data['onsale'] == null ? false : $data['onsale']) + ->setIsnew($data['isnew'] == null ? false : $data['isnew']) + ->setEanCode($data['ean_code'] == null ? '' : $data['ean_code']) + ; + + $this->dispatch(TheliaEvents::PRODUCT_COMBINATION_GENERATION, $event); + + // Log object modification + $this->adminLogAppend( + $this->resourceCode, + AccessManager::CREATE, + sprintf( + "Combination generation for product reference %s", + $event->getProduct()->getRef() + ), + $event->getProduct()->getId() + ); + + // Redirect to the success URL + return $this->generateSuccessRedirect($changeForm); + } catch (FormValidationException $ex) { + // Form cannot be validated + $error_msg = $this->createStandardFormValidationErrorMessage($ex); + } catch (\Exception $ex) { + // Any other error + $error_msg = $ex->getMessage(); + } + + $this->setupFormErrorContext( + $this->getTranslator()->trans("Combination builder"), + $error_msg, + $changeForm, + $ex + ); + + // At this point, the form has errors, and should be redisplayed. + return $this->renderEditionTemplate(); + } + + /** + * Invoked through Ajax; this method calculates the taxed price from the untaxed price, and vice versa. + * @since version 2.2 + */ + public function priceCalculator() + { + $return_price = 0; + + $price = \floatval($this->getRequest()->query->get('price', 0)); + $product_id = \intval($this->getRequest()->query->get('product_id', 0)); + $action = $this->getRequest()->query->get('action', ''); // With ot without tax + $convert = \intval($this->getRequest()->query->get('convert_from_default_currency', 0)); + + if (null !== $product = ProductQuery::create()->findPk($product_id)) { + if ($action == 'to_tax') { + $return_price = $this->computePrice($price, 'without_tax', $product); + } elseif ($action == 'from_tax') { + $return_price = $this->computePrice($price, 'with_tax', $product); + } else { + $return_price = $price; + } + + if ($convert != 0) { + $return_price = $price * Currency::getDefaultCurrency()->getRate(); + } + } + + return new JsonResponse(array('result' => $this->formatPrice($return_price))); + } + + /** + * + * Calculate tax or untax price for a non existing product. + * + * For an existing product, use self::priceCaclulator + * + * @return JsonResponse + */ + public function calculatePrice() + { + $return_price = 0; + + $price = \floatval($this->getRequest()->query->get('price')); + $tax_rule_id = \intval($this->getRequest()->query->get('tax_rule')); + $action = $this->getRequest()->query->get('action'); // With ot without tax + + $taxRule = TaxRuleQuery::create()->findPk($tax_rule_id); + + if (null !== $price && null !== $taxRule) { + $calculator = new Calculator(); + + $calculator->loadTaxRuleWithoutProduct( + $taxRule, + Country::getShopLocation() + ); + + if ($action == 'to_tax') { + $return_price = $calculator->getTaxedPrice($price); + } elseif ($action == 'from_tax') { + $return_price = $calculator->getUntaxedPrice($price); + } else { + $return_price = $price; + } + } + + return new JsonResponse(array('result' => $this->formatPrice($return_price))); + } + + /** + * Calculate all prices + * + * @return \Symfony\Component\HttpFoundation\JsonResponse + */ + public function loadConvertedPrices() + { + $product_sale_element_id = \intval($this->getRequest()->get('product_sale_element_id', 0)); + $currency_id = \intval($this->getRequest()->get('currency_id', 0)); + + $price_with_tax = $price_without_tax = $sale_price_with_tax = $sale_price_without_tax = 0; + + if (null !== $pse = ProductSaleElementsQuery::create()->findPk($product_sale_element_id)) { + if ($currency_id > 0 + && + $currency_id != Currency::getDefaultCurrency()->getId() + && + null !== $currency = CurrencyQuery::create()->findPk($currency_id)) { + // Get the default currency price + $productPrice = ProductPriceQuery::create() + ->filterByCurrency(Currency::getDefaultCurrency()) + ->filterByProductSaleElementsId($product_sale_element_id) + ->findOne() + ; + + // Calculate the converted price + if (null !== $productPrice) { + $price_without_tax = $productPrice->getPrice() * $currency->getRate(); + $sale_price_without_tax = $productPrice->getPromoPrice() * $currency->getRate(); + } + } + + if (null !== $product = $pse->getProduct()) { + $price_with_tax = $this->computePrice($price_without_tax, 'with_tax', $product); + $sale_price_with_tax = $this->computePrice($sale_price_without_tax, 'with_tax', $product); + } + } + + return new JsonResponse(array( + 'price_with_tax' => $this->formatPrice($price_with_tax), + 'price_without_tax' => $this->formatPrice($price_without_tax), + 'sale_price_with_tax' => $this->formatPrice($sale_price_with_tax), + 'sale_price_without_tax' => $this->formatPrice($sale_price_without_tax) + )); + } + + /** + * Calculate taxed/untexted price for a product + * + * @param $price + * @param $price_type + * @param Product $product + * @param bool $convert + * @return string + */ + protected function computePrice($price, $price_type, Product $product, $convert = false) + { + $calc = new Calculator(); + + $calc->load( + $product, + Country::getShopLocation() + ); + + if ($price_type == 'without_tax') { + $return_price = $calc->getTaxedPrice($price); + } elseif ($price_type == 'with_tax') { + $return_price = $calc->getUntaxedPrice($price); + } else { + $return_price = $price; + } + + if ($convert != 0) { + $return_price = $price * Currency::getDefaultCurrency()->getRate(); + } + + return \floatval($return_price); + } + + /** + * @param int $pseId + * @param string $type + * @param int $typeId + * @return mixed|\Thelia\Core\HttpFoundation\Response + */ + public function productSaleElementsProductImageDocumentAssociation($pseId, $type, $typeId) + { + /** + * Check user's auth + */ + if (null !== $response = $this->checkAuth(AdminResources::PRODUCT, [], AccessManager::UPDATE)) { + return $response; + } + + $this->checkXmlHttpRequest(); + + /** + * Check given type + */ + + $responseData = []; + + try { + $responseData = $this->getAssociationResponseData($pseId, $type, $typeId); + } catch (\Exception $e) { + $responseData["error"] = $e->getMessage(); + } + + return JsonResponse::create($responseData, isset($responseData["error"]) ? 500 : 200); + } + + public function getAssociationResponseData($pseId, $type, $typeId) + { + $responseData = []; + + if (null !== $msg = $this->checkFileType($type)) { + throw new \Exception($msg); + } + + $responseData["product_sale_elements_id"] = $pseId; + + $pse = ProductSaleElementsQuery::create()->findPk($pseId); + + if (null === $pse) { + throw new \Exception( + $this->getTranslator()->trans( + "The product sale elements id %id doesn't exists", + [ + "%id" => $pseId, + ] + ) + ); + } + + $assoc = null; + + if ($type === "image") { + $image = ProductImageQuery::create()->findPk($typeId); + + if (null === $image) { + throw new \Exception( + $this->getTranslator()->trans( + "The product image id %id doesn't exists", + [ + "%id" => $typeId, + ] + ) + ); + } + + $assoc = ProductSaleElementsProductImageQuery::create() + ->filterByProductSaleElementsId($pseId) + ->findOneByProductImageId($typeId) + ; + + if (null === $assoc) { + $assoc = new ProductSaleElementsProductImage(); + + $assoc + ->setProductSaleElementsId($pseId) + ->setProductImageId($typeId) + ->save() + ; + } else { + $assoc->delete(); + } + + $responseData["product_image_id"] = $typeId; + $responseData["is-associated"] = (int) (!$assoc->isDeleted()); + } elseif ($type === "document") { + $image = ProductDocumentQuery::create()->findPk($typeId); + + if (null === $image) { + throw new \Exception( + $this->getTranslator()->trans( + "The product document id %id doesn't exists", + [ + "%id" => $pseId, + ] + ) + ); + } + + $assoc = ProductSaleElementsProductDocumentQuery::create() + ->filterByProductSaleElementsId($pseId) + ->findOneByProductDocumentId($typeId) + ; + + if (null === $assoc) { + $assoc = new ProductSaleElementsProductDocument(); + + $assoc + ->setProductSaleElementsId($pseId) + ->setProductDocumentId($typeId) + ->save() + ; + } else { + $assoc->delete(); + } + + $responseData["product_document_id"] = $typeId; + $responseData["is-associated"] = (int) (!$assoc->isDeleted()); + } elseif ($type === "virtual") { + $image = ProductDocumentQuery::create()->findPk($typeId); + + if (null === $image) { + throw new \Exception( + $this->getTranslator()->trans( + "The product document id %id doesn't exists", + [ + "%id" => $pseId, + ] + ) + ); + } + + $documentId = \intval(MetaDataQuery::getVal('virtual', MetaData::PSE_KEY, $pseId)); + + if ($documentId === \intval($typeId)) { + $assocEvent = new MetaDataDeleteEvent('virtual', MetaData::PSE_KEY, $pseId); + $this->dispatch(TheliaEvents::META_DATA_DELETE, $assocEvent); + $responseData["is-associated"] = 0; + } else { + $assocEvent = new MetaDataCreateOrUpdateEvent('virtual', MetaData::PSE_KEY, $pseId, $typeId); + $this->dispatch(TheliaEvents::META_DATA_UPDATE, $assocEvent); + $responseData["is-associated"] = 1; + } + + $responseData["product_document_id"] = $typeId; + } + + return $responseData; + } + + public function checkFileType($type) + { + $types = ["image", "document", "virtual"]; + + if (!\in_array($type, $types)) { + return $this->getTranslator()->trans( + "The type %type is not valid", + [ + "%type" => $type, + ] + ); + } + + return null; + } + + public function getAjaxProductSaleElementsImagesDocuments($id, $type) + { + if (null !== $this->checkAuth(AdminResources::PRODUCT, [], AccessManager::VIEW)) { + return JsonResponse::createAuthError(AccessManager::VIEW); + } + + $this->checkXmlHttpRequest(); + + $pse = ProductSaleElementsQuery::create() + ->findPk($id); + + $errorMessage = $this->checkFileType($type); + + if (null === $pse && null === $errorMessage) { + $type = null; + + $errorMessage = $this->getTranslator()->trans( + "The product sale elements id %id doesn't exist", + [ + "%id" => $pse->getId(), + ] + ); + } + + switch ($type) { + case "image": + $modalTitle = $this->getTranslator()->trans("Associate images"); + $data = $this->getPSEImages($pse); + break; + + case "document": + $modalTitle = $this->getTranslator()->trans("Associate documents"); + $data = $this->getPSEDocuments($pse); + break; + + case "virtual": + $modalTitle = $this->getTranslator()->trans("Select the virtual document"); + $data = $this->getPSEVirtualDocument($pse); + break; + + case null: + default: + $modalTitle = $this->getTranslator()->trans("Unsupported type"); + $data = []; + } + + if (empty($data) && null === $errorMessage) { + $errorMessage = $this->getTranslator()->trans("There are no files to associate."); + if ($type === "virtual") { + $errorMessage .= $this->getTranslator()->trans(" note: only non-visible documents can be associated."); + } + } + + $this->getParserContext() + ->set("items", $data) + ->set("type", $type) + ->set("error_message", $errorMessage) + ->set("modal_title", $modalTitle) + ; + + return $this->render("ajax/pse-image-document-assoc-modal"); + } + + protected function getPSEImages(ProductSaleElementsModel $pse) + { + /** + * Compute images with the associated loop + */ + $imageLoop = new Image($this->container); + $imageLoop->initializeArgs([ + "product" => $pse->getProductId(), + "width" => 100, + "height"=> 75, + "resize_mode" => "borders", + ]); + + $images = $imageLoop + ->exec($imagePagination) + ; + + $imageAssoc = ProductSaleElementsProductImageQuery::create() + ->filterByProductSaleElementsId($pse->getId()) + ->find() + ->toArray() + ; + + $data = []; + + /** @var \Thelia\Core\Template\Element\LoopResultRow $image */ + for ($images->rewind(); $images->valid(); $images->next()) { + $image = $images->current(); + + $isAssociated = $this->arrayHasEntries($imageAssoc, [ + "ProductImageId" => $image->get("ID"), + "ProductSaleElementsId" => $pse->getId(), + ]); + + $data[] = [ + "id" => $image->get("ID"), + "url" => $image->get("IMAGE_URL"), + "title" => $image->get("TITLE"), + "is_associated" => $isAssociated, + "filename" => $image->model->getFile(), + ]; + } + + return $data; + } + + protected function getPSEDocuments(ProductSaleElementsModel $pse) + { + /** + * Compute documents with the associated loop + */ + $documentLoop = new Document($this->container); + + $documentLoop->initializeArgs([ + "product" => $pse->getProductId(), + "visible" => BooleanOrBothType::ANY, // Do not restrict on visibility for single association + ]); + + $documents = $documentLoop + ->exec($documentPagination) + ; + + $documentAssoc = ProductSaleElementsProductDocumentQuery::create() + ->useProductSaleElementsQuery() + ->filterById($pse->getId()) + ->endUse() + ->find() + ->toArray() + ; + + $data = []; + + /** @var \Thelia\Core\Template\Element\LoopResultRow $document */ + for ($documents->rewind(); $documents->valid(); $documents->next()) { + $document = $documents->current(); + + $isAssociated = $this->arrayHasEntries($documentAssoc, [ + "ProductDocumentId" => $document->get("ID"), + "ProductSaleElementsId" => $pse->getId(), + ]); + + $data[] = [ + "id" => $document->get("ID"), + "url" => $document->get("DOCUMENT_URL"), + "title" => $document->get("TITLE"), + "is_associated" => $isAssociated, + "filename" => $document->model->getFile(), + ]; + } + + return $data; + } + + protected function getPSEVirtualDocument(ProductSaleElementsModel $pse) + { + /** + * Compute documents with the associated loop + */ + $documentLoop = new Document($this->container); + // select only not visible documents + $documentLoop->initializeArgs([ + "product" => $pse->getProductId(), + "visible" => 0, + ]); + + $documents = $documentLoop + ->exec($documentPagination) + ; + + $documentId = \intval(MetaDataQuery::getVal("virtual", "pse", $pse->getId())); + + $data = []; + + /** @var \Thelia\Core\Template\Element\LoopResultRow $document */ + for ($documents->rewind(); $documents->valid(); $documents->next()) { + $document = $documents->current(); + + $data[] = [ + "id" => $document->get("ID"), + "url" => $document->get("DOCUMENT_URL"), + "title" => $document->get("TITLE"), + "is_associated" => ($documentId === $document->get("ID")), + "filename" => $document->model->getFile(), + ]; + } + + return $data; + } + + protected function arrayHasEntries(array $data, array $entries) + { + $status = false; + $countEntries = \count($entries); + + foreach ($data as &$line) { + $localMatch = 0; + + foreach ($entries as $key => $entry) { + if (isset($line[$key]) && $line[$key] === $entry) { + $localMatch++; + } + } + + if ($localMatch === $countEntries) { + $status = true; + unset($line); + break; + } + } + + return $status; + } + + /** + * @return mixed|\Symfony\Component\HttpFoundation\Response + * @throws \Exception + */ + public function cloneAction() + { + if (null !== $response = $this->checkAuth($this->resourceCode, $this->getModuleCode(), [AccessManager::CREATE, AccessManager::UPDATE])) { + return $response; + } + + // Initialize vars + $cloneProductForm = $this->createForm(AdminForm::PRODUCT_CLONE); + $lang = $this->getSession()->getLang()->getLocale(); + + try { + // Check the form against constraints violations + $form = $this->validateForm($cloneProductForm, "POST"); + + $originalProduct = ProductQuery::create() + ->findPk($form->getData()['productId']); + + // Build and dispatch product clone event + $productCloneEvent = new ProductCloneEvent( + $form->getData()['newRef'], + $lang, + $originalProduct + ); + $this->dispatch(TheliaEvents::PRODUCT_CLONE, $productCloneEvent); + + return $this->generateRedirectFromRoute( + 'admin.products.update', + array('product_id' => $productCloneEvent->getClonedProduct()->getId()) + ); + } catch (FormValidationException $e) { + $this->setupFormErrorContext( + $this->getTranslator()->trans("Product clone"), + $e->getMessage(), + $cloneProductForm, + $e + ); + + return $this->redirectToEditionTemplate(); + } + } + + /** + * @param string $price + * @return float + */ + protected function formatPrice($price) + { + return \floatval(number_format($price, 6, '.', '')); + } + + /** + * @return mixed|\Thelia\Core\HttpFoundation\Response + * @throws \Propel\Runtime\Exception\PropelException + */ + public function searchCategoryAction() + { + $search = '%'.$this->getRequest()->query->get('q').'%'; + + $resultArray = array(); + + $categoriesI18n = CategoryI18nQuery::create()->filterByTitle($search, Criteria::LIKE)->limit(100); + + + /** @var \Thelia\Model\CategoryI18n $categoryI18n */ + foreach ($categoriesI18n as $categoryI18n) { + $category = $categoryI18n->getCategory(); + $resultArray[$category->getId()] = $categoryI18n->getTitle(); + } + + return $this->jsonResponse(json_encode($resultArray)); + } + + /** + * @return mixed|\Thelia\Core\HttpFoundation\Response + * @throws \Propel\Runtime\Exception\PropelException + */ + public function searchProductAction() + { + $search = '%'.$this->getRequest()->query->get('q').'%'; + + $resultArray = array(); + + $productsI18nQuery = ProductI18nQuery::create()->filterByTitle($search, Criteria::LIKE); + + + $category_id = $this->getRequest()->query->get('category_id'); + if($category_id != null){ + $productsI18nQuery + ->useProductQuery() + ->useProductCategoryQuery() + ->filterByCategoryId($category_id) + ->endUse() + ->endUse(); + } + + $products = $productsI18nQuery->limit(100); + + /** @var \Thelia\Model\ProductI18n $product */ + foreach ($products as $product) { + $resultArray[$product->getId()] = $product->getTitle(); + } + + return $this->jsonResponse(json_encode($resultArray)); + } +} diff --git a/core/lib/Thelia/Controller/Admin/ProfileController.php b/core/lib/Thelia/Controller/Admin/ProfileController.php new file mode 100644 index 00000000..d2ebe77a --- /dev/null +++ b/core/lib/Thelia/Controller/Admin/ProfileController.php @@ -0,0 +1,444 @@ +createForm(AdminForm::PROFILE_CREATION); + } + + protected function getUpdateForm() + { + return $this->createForm(AdminForm::PROFILE_MODIFICATION); + } + + protected function getCreationEvent($formData) + { + $event = new ProfileEvent(); + + $event->setLocale($formData['locale']); + $event->setCode($formData['code']); + $event->setTitle($formData['title']); + $event->setChapo($formData['chapo']); + $event->setDescription($formData['description']); + $event->setPostscriptum($formData['postscriptum']); + + return $event; + } + + protected function getUpdateEvent($formData) + { + $event = new ProfileEvent(); + + $event->setLocale($formData['locale']); + $event->setId($formData['id']); + $event->setTitle($formData['title']); + $event->setChapo($formData['chapo']); + $event->setDescription($formData['description']); + $event->setPostscriptum($formData['postscriptum']); + + return $event; + } + + protected function getDeleteEvent() + { + $event = new ProfileEvent(); + + $event->setId( + $this->getRequest()->get('profile_id', 0) + ); + + return $event; + } + + /** + * @param ProfileEvent $event + * @return boolean + */ + protected function eventContainsObject($event) + { + return $event->hasProfile(); + } + + /** + * @param Profile $object + * @return \Thelia\Form\BaseForm + */ + protected function hydrateObjectForm($object) + { + $data = array( + 'id' => $object->getId(), + 'locale' => $object->getLocale(), + 'title' => $object->getTitle(), + 'description' => $object->getDescription(), + 'code' => $object->getCode(), + ); + + // Setup the object form + return $this->createForm(AdminForm::PROFILE_MODIFICATION, "form", $data); + } + + /** + * @param Profile $object + * @return \Thelia\Form\BaseForm + */ + protected function hydrateResourceUpdateForm($object) + { + $data = array( + 'id' => $object->getId(), + ); + + // Setup the object form + return $this->createForm(AdminForm::PROFILE_UPDATE_RESOURCE_ACCESS, "form", $data); + } + + /** + * @param Profile $object + * @return \Thelia\Form\BaseForm + */ + protected function hydrateModuleUpdateForm($object) + { + $data = array( + 'id' => $object->getId(), + ); + + // Setup the object form + return $this->createForm(AdminForm::PROFILE_UPDATE_MODULE_ACCESS, "form", $data); + } + + protected function getObjectFromEvent($event) + { + return $event->hasProfile() ? $event->getProfile() : null; + } + + protected function getExistingObject() + { + $profile = ProfileQuery::create() + ->findOneById($this->getRequest()->get('profile_id', 0)); + + if (null !== $profile) { + $profile->setLocale($this->getCurrentEditionLocale()); + } + + return $profile; + } + + /** + * @param Profile $object + * @return string + */ + protected function getObjectLabel($object) + { + return $object->getTitle(); + } + + /** + * @param Profile $object + * @return int + */ + protected function getObjectId($object) + { + return $object->getId(); + } + + protected function getViewArguments() + { + return (null !== $tab = $this->getRequest()->get('tab')) ? [ 'tab' => $tab ] : []; + } + + protected function getRouteArguments($profile_id = null) + { + return array( + 'profile_id' => $profile_id === null ? $this->getRequest()->get('profile_id') : $profile_id, + ); + } + + protected function renderListTemplate($currentOrder) + { + // We always return to the feature edition form + return $this->render( + 'profiles', + array() + ); + } + + protected function renderEditionTemplate() + { + // We always return to the feature edition form + return $this->render('profile-edit', array_merge($this->getViewArguments(), $this->getRouteArguments())); + } + + protected function redirectToEditionTemplate() + { + // We always return to the feature edition form + return $this->generateRedirectFromRoute( + "admin.configuration.profiles.update", + $this->getViewArguments(), + $this->getRouteArguments() + ); + } + + /** + * Put in this method post object creation processing if required. + * + * @param ProfileEvent $createEvent the create event + * @return \Symfony\Component\HttpFoundation\Response|Response + */ + protected function performAdditionalCreateAction($createEvent) + { + return $this->generateRedirectFromRoute( + "admin.configuration.profiles.update", + $this->getViewArguments(), + $this->getRouteArguments($createEvent->getProfile()->getId()) + ); + } + + protected function redirectToListTemplate() + { + return $this->generateRedirectFromRoute("admin.configuration.profiles.list"); + } + + public function updateAction() + { + if (null !== $response = $this->checkAuth($this->resourceCode, array(), AccessManager::UPDATE)) { + return $response; + } + + $object = $this->getExistingObject(); + + if ($object != null) { + // Hydrate the form and pass it to the parser + $resourceAccessForm = $this->hydrateResourceUpdateForm($object); + $moduleAccessForm = $this->hydrateModuleUpdateForm($object); + + // Pass it to the parser + $this->getParserContext()->addForm($resourceAccessForm); + $this->getParserContext()->addForm($moduleAccessForm); + } + + return parent::updateAction(); + } + + protected function getUpdateResourceAccessEvent($formData) + { + $event = new ProfileEvent(); + + $event->setId($formData['id']); + $event->setResourceAccess($this->getResourceAccess($formData)); + + return $event; + } + + protected function getUpdateModuleAccessEvent($formData) + { + $event = new ProfileEvent(); + + $event->setId($formData['id']); + $event->setModuleAccess($this->getModuleAccess($formData)); + + return $event; + } + + protected function getResourceAccess($formData) + { + $requirements = array(); + foreach ($formData as $data => $value) { + if (!strstr($data, ':')) { + continue; + } + + $explosion = explode(':', $data); + + $prefix = array_shift($explosion); + + if ($prefix != ProfileUpdateResourceAccessForm::RESOURCE_ACCESS_FIELD_PREFIX) { + continue; + } + + $requirements[implode('.', $explosion)] = $value; + } + + return $requirements; + } + + protected function getModuleAccess($formData) + { + $requirements = array(); + foreach ($formData as $data => $value) { + if (!strstr($data, ':')) { + continue; + } + + $explosion = explode(':', $data); + + $prefix = array_shift($explosion); + + if ($prefix != ProfileUpdateModuleAccessForm::MODULE_ACCESS_FIELD_PREFIX) { + continue; + } + + $requirements[implode('.', $explosion)] = $value; + } + + return $requirements; + } + + public function processUpdateResourceAccess() + { + // Check current user authorization + if (null !== $response = $this->checkAuth($this->resourceCode, array(), AccessManager::UPDATE)) { + return $response; + } + + // Create the form from the request + $changeForm = $this->createForm(AdminForm::PROFILE_UPDATE_RESOURCE_ACCESS); + + try { + // Check the form against constraints violations + $form = $this->validateForm($changeForm, "POST"); + + // Get the form field values + $data = $form->getData(); + + $changeEvent = $this->getUpdateResourceAccessEvent($data); + + $this->dispatch(TheliaEvents::PROFILE_RESOURCE_ACCESS_UPDATE, $changeEvent); + + if (! $this->eventContainsObject($changeEvent)) { + throw new \LogicException( + $this->getTranslator()->trans("No %obj was updated.", array('%obj', $this->objectName)) + ); + } + + // Log object modification + if (null !== $changedObject = $this->getObjectFromEvent($changeEvent)) { + $this->adminLogAppend( + $this->resourceCode, + AccessManager::UPDATE, + sprintf( + "%s %s (ID %s) modified", + ucfirst($this->objectName), + $this->getObjectLabel($changedObject), + $this->getObjectId($changedObject) + ), + $this->getObjectId($changedObject) + ); + } + + if ($response == null) { + return $this->redirectToEditionTemplate(); + } else { + return $response; + } + } catch (FormValidationException $ex) { + // Form cannot be validated + $error_msg = $this->createStandardFormValidationErrorMessage($ex); + } catch (\Exception $ex) { + // Any other error + $error_msg = $ex->getMessage(); + } + + $this->setupFormErrorContext($this->getTranslator()->trans("%obj modification", array('%obj' => 'taxrule')), $error_msg, $changeForm, $ex); + + // At this point, the form has errors, and should be redisplayed. + return $this->renderEditionTemplate(); + } + + public function processUpdateModuleAccess() + { + // Check current user authorization + if (null !== $response = $this->checkAuth($this->resourceCode, array(), AccessManager::UPDATE)) { + return $response; + } + + // Create the form from the request + $changeForm = $this->createForm(AdminForm::PROFILE_UPDATE_MODULE_ACCESS); + + try { + // Check the form against constraints violations + $form = $this->validateForm($changeForm, "POST"); + + // Get the form field values + $data = $form->getData(); + + $changeEvent = $this->getUpdateModuleAccessEvent($data); + + $this->dispatch(TheliaEvents::PROFILE_MODULE_ACCESS_UPDATE, $changeEvent); + + if (! $this->eventContainsObject($changeEvent)) { + throw new \LogicException( + $this->getTranslator()->trans("No %obj was updated.", array('%obj', $this->objectName)) + ); + } + + // Log object modification + if (null !== $changedObject = $this->getObjectFromEvent($changeEvent)) { + $this->adminLogAppend( + $this->resourceCode, + AccessManager::UPDATE, + sprintf( + "%s %s (ID %s) modified", + ucfirst($this->objectName), + $this->getObjectLabel($changedObject), + $this->getObjectId($changedObject) + ), + $this->getObjectId($changedObject) + ); + } + + if ($response == null) { + return $this->redirectToEditionTemplate(); + } else { + return $response; + } + } catch (FormValidationException $ex) { + // Form cannot be validated + $error_msg = $this->createStandardFormValidationErrorMessage($ex); + } catch (\Exception $ex) { + // Any other error + $error_msg = $ex->getMessage(); + } + + $this->setupFormErrorContext($this->getTranslator()->trans("%obj modification", array('%obj' => 'taxrule')), $error_msg, $changeForm, $ex); + + // At this point, the form has errors, and should be redisplayed. + return $this->renderEditionTemplate(); + } +} diff --git a/core/lib/Thelia/Controller/Admin/SaleController.php b/core/lib/Thelia/Controller/Admin/SaleController.php new file mode 100644 index 00000000..cd2b8510 --- /dev/null +++ b/core/lib/Thelia/Controller/Admin/SaleController.php @@ -0,0 +1,405 @@ + + */ +class SaleController extends AbstractCrudController +{ + public function __construct() + { + parent::__construct( + 'sale', + 'start-date', + 'order', + AdminResources::SALES, + TheliaEvents::SALE_CREATE, + TheliaEvents::SALE_UPDATE, + TheliaEvents::SALE_DELETE + ); + } + + /** + * Return the creation form for this object + */ + protected function getCreationForm() + { + return $this->createForm(AdminForm::SALE_CREATION); + } + + /** + * Return the update form for this object + */ + protected function getUpdateForm() + { + return $this->createForm(AdminForm::SALE_MODIFICATION); + } + + /** + * Hydrate the update form for this object, before passing it to the update template + * + * @param Sale $sale + * @return SaleModificationForm + */ + protected function hydrateObjectForm($sale) + { + // Find all categories of the selected products + $saleProducts = $sale->getSaleProductList(); + + $categories = $products = [ ]; + + /** @var SaleProduct $saleProduct */ + foreach ($saleProducts as $saleProduct) { + $categories[] = $saleProduct->getProduct()->getDefaultCategoryId(); + $products[$saleProduct->getProduct()->getId()] = $saleProduct->getProduct()->getId(); + } + + $dateFormat = SaleModificationForm::PHP_DATE_FORMAT; + + // Transform the selected attributes list (product_id => array of attributes av id) into + // product_id => comma separated list of attributes av id, to math the collection type (text) + $saleProductsAttributesAvs = $sale->getSaleProductsAttributeList(); + + $product_attributes = []; + + foreach ($saleProductsAttributesAvs as $productId => $saleProductsAttributesAv) { + $product_attributes[$productId] = implode(',', $saleProductsAttributesAv); + } + + // Prepare the data that will hydrate the form + $data = [ + 'id' => $sale->getId(), + 'locale' => $sale->getLocale(), + 'title' => $sale->getTitle(), + 'label' => $sale->getSaleLabel(), + 'chapo' => $sale->getChapo(), + 'description' => $sale->getDescription(), + 'postscriptum' => $sale->getPostscriptum(), + 'active' => $sale->getActive(), + 'display_initial_price' => $sale->getDisplayInitialPrice(), + 'start_date' => $sale->getStartDate($dateFormat), + 'end_date' => $sale->getEndDate($dateFormat), + 'price_offset_type' => $sale->getPriceOffsetType(), + 'price_offset' => $sale->getPriceOffsets(), + 'categories' => $categories, + 'products' => $products, + 'product_attributes' => $product_attributes + ]; + + // Setup the object form + return $this->createForm(AdminForm::SALE_MODIFICATION, "form", $data); + } + + /** + * Creates the creation event with the provided form data + * + * @param array $formData + * @return SaleCreateEvent + */ + protected function getCreationEvent($formData) + { + $saleCreateEvent = new SaleCreateEvent(); + + $saleCreateEvent + ->setLocale($formData['locale']) + ->setTitle($formData['title']) + ->setSaleLabel($formData['label']) + ; + + return $saleCreateEvent; + } + + /** + * Creates the update event with the provided form data + * + * @param array $formData + * @return SaleUpdateEvent + */ + protected function getUpdateEvent($formData) + { + // Build the product attributes array + $productAttributes = []; + + foreach ($formData['product_attributes'] as $productId => $attributeAvIdList) { + if (! empty($attributeAvIdList)) { + $productAttributes[$productId] = explode(',', $attributeAvIdList); + } + } + + $saleUpdateEvent = new SaleUpdateEvent($formData['id']); + + $saleUpdateEvent + ->setStartDate($formData['start_date']) + ->setEndDate($formData['end_date']) + ->setActive($formData['active']) + ->setDisplayInitialPrice($formData['display_initial_price']) + ->setPriceOffsetType($formData['price_offset_type']) + ->setPriceOffsets($formData['price_offset']) + ->setProducts($formData['products']) + ->setProductAttributes($productAttributes) + ->setLocale($formData['locale']) + ->setTitle($formData['title']) + ->setSaleLabel($formData['label']) + ->setChapo($formData['chapo']) + ->setDescription($formData['description']) + ->setPostscriptum($formData['postscriptum']) + ; + + return $saleUpdateEvent; + } + + /** + * Creates the delete event with the provided form data + * + * @return SaleDeleteEvent + */ + protected function getDeleteEvent() + { + return new SaleDeleteEvent($this->getRequest()->get('sale_id')); + } + + /** + * Return true if the event contains the object, e.g. the action has updated the object in the event. + * + * @param SaleEvent $event + * @return bool + */ + protected function eventContainsObject($event) + { + return $event->hasSale(); + } + + /** + * Get the created object from an event. + * + * @param $event \Thelia\Core\Event\Sale\SaleEvent + * + * @return null|\Thelia\Model\Sale + */ + protected function getObjectFromEvent($event) + { + return $event->getSale(); + } + + /** + * Load an existing object from the database + * + * @return \Thelia\Model\Sale + */ + protected function getExistingObject() + { + $sale = SaleQuery::create() + ->findOneById($this->getRequest()->get('sale_id', 0)); + + if (null !== $sale) { + $sale->setLocale($this->getCurrentEditionLocale()); + } + + return $sale; + } + + /** + * Returns the object label form the object event (name, title, etc.) + * + * @param Sale $object + * + * @return string sale title + */ + protected function getObjectLabel($object) + { + return $object->getTitle(); + } + + /** + * Returns the object ID from the object + * + * @param Sale $object + * + * @return int sale id + */ + protected function getObjectId($object) + { + return $object->getId(); + } + + /** + * Render the main list template + * + * @param string $currentOrder, if any, null otherwise. + * + * @return Response + */ + protected function renderListTemplate($currentOrder) + { + $this->getListOrderFromSession('sale', 'order', 'start-date'); + + return $this->render('sales', [ + 'order' => $currentOrder, + ]); + } + + protected function getEditionArguments() + { + return [ + 'sale_id' => $this->getRequest()->get('sale_id', 0) + ]; + } + + /** + * Render the edition template + */ + protected function renderEditionTemplate() + { + return $this->render('sale-edit', $this->getEditionArguments()); + } + + /** + * Redirect to the edition template + */ + protected function redirectToEditionTemplate() + { + return $this->generateRedirectFromRoute('admin.sale.update', [], $this->getEditionArguments()); + } + + /** + * Redirect to the list template + */ + protected function redirectToListTemplate() + { + return $this->generateRedirectFromRoute('admin.sale.default'); + } + + /** + * Toggle activity status of the sale. + * + * @return Response + */ + public function toggleActivity() + { + if (null !== $response = $this->checkAuth(AdminResources::SALES, [], AccessManager::UPDATE)) { + return $response; + } + + try { + $this->dispatch( + TheliaEvents::SALE_TOGGLE_ACTIVITY, + new SaleToggleActivityEvent( + $this->getExistingObject() + ) + ); + } catch (\Exception $ex) { + // Any error + return $this->errorPage($ex); + } + + return $this->nullResponse(); + } + + public function updateProductList() + { + if (null !== $response = $this->checkAuth(AdminResources::SALES, [], AccessManager::UPDATE)) { + return $response; + } + + // Build the list of categories + $categories = ''; + + foreach ($this->getRequest()->get('categories', []) as $category_id) { + $categories .= $category_id . ','; + } + + return $this->render( + 'ajax/sale-edit-products', + [ + 'sale_id' => $this->getRequest()->get('sale_id'), + 'category_list' => rtrim($categories, ','), + 'product_list' => $this->getRequest()->get('products', []) + ] + ); + } + + public function updateProductAttributes() + { + if (null !== $response = $this->checkAuth(AdminResources::SALES, [], AccessManager::UPDATE)) { + return $response; + } + + $selectedAttributesAvId = explode(',', $this->getRequest()->get('selected_attributes_av_id', [])); + + $productId = $this->getRequest()->get('product_id'); + + return $this->render( + 'ajax/sale-edit-product-attributes', + [ + 'product_id' => $productId, + 'selected_attributes_av_id' => $selectedAttributesAvId + ] + ); + } + + public function resetSaleStatus() + { + // Check current user authorization + if (null !== $response = $this->checkAuth(AdminResources::SALES, [], AccessManager::UPDATE)) { + return $response; + } + + try { + $this->dispatch( + TheliaEvents::SALE_CLEAR_SALE_STATUS, + new SaleClearStatusEvent() + ); + } catch (\Exception $ex) { + // Any error + return $this->errorPage($ex); + } + + return $this->redirectToListTemplate(); + } + + public function checkSalesActivationStatus() + { + // We do not check auth, as the related route may be invoked from a cron + try { + $this->dispatch( + TheliaEvents::CHECK_SALE_ACTIVATION_EVENT, + new SaleActiveStatusCheckEvent() + ); + } catch (\Exception $ex) { + // Any error + return $this->errorPage($ex); + } + + return $this->redirectToListTemplate(); + } +} diff --git a/core/lib/Thelia/Controller/Admin/SessionController.php b/core/lib/Thelia/Controller/Admin/SessionController.php new file mode 100644 index 00000000..0a8cdcb9 --- /dev/null +++ b/core/lib/Thelia/Controller/Admin/SessionController.php @@ -0,0 +1,317 @@ +getSecurityContext()->hasAdminUser()) { + // Redirect to the homepage + return new RedirectResponse($this->retrieveUrlFromRouteId('admin.home.view')); + } + + return null; + } + + protected function checkPasswordRecoveryEnabled() + { + // Check if user is already authenticate + if (!\boolval(ConfigQuery::read('enable_lost_admin_password_recovery', false))) { + AdminLog::append( + "admin", + "ADMIN_CREATE_PASSWORD", + "Lost password recovery function invoked", + $this->getRequest() + ); + + // Redirect to the error page + return $this->errorPage($this->getTranslator()->trans("The lost admin password recovery feature is disabled."), 403); + } + } + + public function showLoginAction() + { + if (null !== $response = $this->checkAdminLoggedIn()) { + return $response; + } + + return $this->render("login"); + } + + public function showLostPasswordAction() + { + if ((null !== $response = $this->checkPasswordRecoveryEnabled()) || (null !== $response = $this->checkAdminLoggedIn())) { + return $response; + } + + return $this->render("lost-password"); + } + + + public function passwordCreateRequestAction() + { + if ((null !== $response = $this->checkPasswordRecoveryEnabled()) || (null !== $response = $this->checkAdminLoggedIn())) { + return $response; + } + + $adminLostPasswordForm = $this->createForm(AdminForm::ADMIN_LOST_PASSWORD); + + try { + $form = $this->validateForm($adminLostPasswordForm, "post"); + + $data = $form->getData(); + + // Check if user exists + if (null === $admin = AdminQuery::create()->findOneByEmail($data['username_or_email'])) { + $admin = AdminQuery::create()->findOneByLogin($data['username_or_email']); + } + + if (null === $admin) { + throw new \Exception($this->getTranslator()->trans("Invalid username or email.")); + } + + $email = $admin->getEmail(); + + if (empty($email)) { + throw new \Exception($this->getTranslator()->trans("Sorry, no email defined for this administrator.")); + } + + $this->dispatch(TheliaEvents::ADMINISTRATOR_CREATEPASSWORD, new AdministratorEvent($admin)); + + // Redirect to the success URL + return $this->generateSuccessRedirect($adminLostPasswordForm); + } catch (FormValidationException $ex) { + // Validation problem + $message = $this->createStandardFormValidationErrorMessage($ex); + } catch (\Exception $ex) { + // Log failure + AdminLog::append("admin", "ADMIN_LOST_PASSWORD", $ex->getMessage(), $this->getRequest()); + + $message = $ex->getMessage(); + } + + $this->setupFormErrorContext("Admin password create request", $message, $adminLostPasswordForm, $ex); + + return $this->render("lost-password"); + } + + public function passwordCreateRequestSuccessAction() + { + if ((null !== $response = $this->checkPasswordRecoveryEnabled()) || (null !== $response = $this->checkAdminLoggedIn())) { + return $response; + } + + return $this->render("lost-password", [ 'create_request_success' => true ]); + } + + public function displayCreateFormAction($token) + { + if ((null !== $response = $this->checkPasswordRecoveryEnabled()) || (null !== $response = $this->checkAdminLoggedIn())) { + return $response; + } + + // Check the token + if (null == $admin = AdminQuery::create()->findOneByPasswordRenewToken($token)) { + return $this->render( + "lost-password", + [ 'token_error' => true ] + ); + } + + $this->getSession()->set(self::ADMIN_TOKEN_SESSION_VAR_NAME, $token); + + return $this->render("create-password"); + } + + public function passwordCreatedAction() + { + if ((null !== $response = $this->checkPasswordRecoveryEnabled()) || (null !== $response = $this->checkAdminLoggedIn())) { + return $response; + } + + $adminCreatePasswordForm = $this->createForm(AdminForm::ADMIN_CREATE_PASSWORD); + + try { + $form = $this->validateForm($adminCreatePasswordForm, "post"); + + $data = $form->getData(); + + $token = $this->getSession()->get(self::ADMIN_TOKEN_SESSION_VAR_NAME); + + if (empty($token) || null === $admin = AdminQuery::create()->findOneByPasswordRenewToken($token)) { + throw new \Exception($this->getTranslator()->trans("An invalid token was provided, your password cannot be changed")); + } + + $event = new AdministratorUpdatePasswordEvent($admin); + $event->setPassword($data['password']); + + $this->dispatch(TheliaEvents::ADMINISTRATOR_UPDATEPASSWORD, $event); + + $this->getSession()->set(self::ADMIN_TOKEN_SESSION_VAR_NAME, null); + + return $this->generateSuccessRedirect($adminCreatePasswordForm); + } catch (FormValidationException $ex) { + // Validation problem + $message = $this->createStandardFormValidationErrorMessage($ex); + } catch (\Exception $ex) { + // Log authentication failure + AdminLog::append("admin", "ADMIN_CREATE_PASSWORD", $ex->getMessage(), $this->getRequest()); + + $message = $ex->getMessage(); + } + + $this->setupFormErrorContext("Login process", $message, $adminCreatePasswordForm, $ex); + + return $this->render("create-password"); + } + + public function passwordCreatedSuccessAction() + { + if ((null !== $response = $this->checkPasswordRecoveryEnabled()) || (null !== $response = $this->checkAdminLoggedIn())) { + return $response; + } + + return $this->render("create-password-success"); + } + + public function checkLogoutAction() + { + $this->dispatch(TheliaEvents::ADMIN_LOGOUT); + + $this->getSecurityContext()->clearAdminUser(); + + // Clear the remember me cookie, if any + $this->clearRememberMeCookie($this->getRememberMeCookieName()); + + // Go back to login page. + return $this->generateRedirectFromRoute('admin.login'); + } + + public function checkLoginAction() + { + $request = $this->getRequest(); + + $adminLoginForm = new AdminLogin($request); + + try { + $form = $this->validateForm($adminLoginForm, "post"); + + $authenticator = new AdminUsernamePasswordFormAuthenticator($request, $adminLoginForm); + + /** @var Admin $user */ + $user = $authenticator->getAuthentifiedUser(); + + // Success -> store user in security context + $this->getSecurityContext()->setAdminUser($user); + + // Log authentication success + AdminLog::append("admin", "LOGIN", "Authentication successful", $request, $user, false); + + $this->applyUserLocale($user); + + if (\intval($form->get('remember_me')->getData()) > 0) { + // If a remember me field if present and set in the form, create + // the cookie thant store "remember me" information + $this->createRememberMeCookie( + $user, + $this->getRememberMeCookieName(), + $this->getRememberMeCookieExpiration() + ); + } + + $this->dispatch(TheliaEvents::ADMIN_LOGIN); + + // Check if we have to ask the user to set its address email. + // This is the case if Thelia has been updated from a pre 2.3.0 version + if (false === strpos($user->getEmail(), '@')) { + return $this->generateRedirectFromRoute('admin.set-email-address'); + } + + // Redirect to the success URL, passing the cookie if one exists. + return $this->generateSuccessRedirect($adminLoginForm); + } catch (FormValidationException $ex) { + // Validation problem + $message = $this->createStandardFormValidationErrorMessage($ex); + } catch (AuthenticationException $ex) { + // Log authentication failure + AdminLog::append("admin", "LOGIN", sprintf("Authentication failure for username '%s'", $authenticator->getUsername()), $request); + + $message = $this->getTranslator()->trans("Login failed. Please check your username and password."); + } catch (\Exception $ex) { + // Log authentication failure + AdminLog::append("admin", "LOGIN", sprintf("Undefined error: %s", $ex->getMessage()), $request); + + $message = $this->getTranslator()->trans( + "Unable to process your request. Please try again (%err).", + array("%err" => $ex->getMessage()) + ); + } + + $this->setupFormErrorContext("Login process", $message, $adminLoginForm, $ex); + + // Display the login form again + return $this->render("login"); + } + + /** + * Save user locale preference in session. + * + * @param UserInterface $user + */ + protected function applyUserLocale(UserInterface $user) + { + // Set the current language according to locale preference + $locale = $user->getLocale(); + + if (null === $lang = LangQuery::create()->findOneByLocale($locale)) { + $lang = Lang::getDefaultLanguage(); + } + + $this->getSession()->setLang($lang); + } + + protected function getRememberMeCookieName() + { + return ConfigQuery::read('admin_remember_me_cookie_name', 'armcn'); + } + + protected function getRememberMeCookieExpiration() + { + return ConfigQuery::read('admin_remember_me_cookie_expiration', 2592000 /* 1 month */); + } +} diff --git a/core/lib/Thelia/Controller/Admin/ShippingZoneController.php b/core/lib/Thelia/Controller/Admin/ShippingZoneController.php new file mode 100644 index 00000000..a845133e --- /dev/null +++ b/core/lib/Thelia/Controller/Admin/ShippingZoneController.php @@ -0,0 +1,149 @@ + + */ +class ShippingZoneController extends BaseAdminController +{ + public $objectName = 'areaDeliveryModule'; + + public function indexAction() + { + if (null !== $response = $this->checkAuth(AdminResources::SHIPPING_ZONE, array(), AccessManager::VIEW)) { + return $response; + } + return $this->render("shipping-zones", array("display_shipping_zone" => 20)); + } + + public function updateAction($delivery_module_id) + { + if (null !== $response = $this->checkAuth(AdminResources::SHIPPING_ZONE, array(), AccessManager::VIEW)) { + return $response; + } + + return $this->render( + "shipping-zones-edit", + ["delivery_module_id" => $delivery_module_id] + ); + } + + /** + * @return mixed|\Thelia\Core\HttpFoundation\Response + */ + public function addArea() + { + if (null !== $response = $this->checkAuth(AdminResources::SHIPPING_ZONE, array(), AccessManager::UPDATE)) { + return $response; + } + + $shippingAreaForm = new ShippingZoneAddArea($this->getRequest()); + $error_msg = null; + + try { + $form = $this->validateForm($shippingAreaForm); + + $event = new ShippingZoneAddAreaEvent( + $form->get('area_id')->getData(), + $form->get('shipping_zone_id')->getData() + ); + + $this->dispatch(TheliaEvents::SHIPPING_ZONE_ADD_AREA, $event); + + // Redirect to the success URL + return $this->generateSuccessRedirect($shippingAreaForm); + } catch (FormValidationException $ex) { + // Form cannot be validated + $error_msg = $this->createStandardFormValidationErrorMessage($ex); + } catch (\Exception $ex) { + // Any other error + $error_msg = $ex->getMessage(); + } + + $this->setupFormErrorContext( + $this->getTranslator()->trans("%obj modification", array('%obj' => $this->objectName)), + $error_msg, + $shippingAreaForm + ); + + // At this point, the form has errors, and should be redisplayed. + return $this->renderEditionTemplate(); + } + + public function removeArea() + { + if (null !== $response = $this->checkAuth(AdminResources::SHIPPING_ZONE, array(), AccessManager::UPDATE)) { + return $response; + } + + $shippingAreaForm = new ShippingZoneRemoveArea($this->getRequest()); + $error_msg = null; + + try { + $form = $this->validateForm($shippingAreaForm); + + $event = new ShippingZoneRemoveAreaEvent( + $form->get('area_id')->getData(), + $form->get('shipping_zone_id')->getData() + ); + + $this->dispatch(TheliaEvents::SHIPPING_ZONE_REMOVE_AREA, $event); + + // Redirect to the success URL + return $this->generateSuccessRedirect($shippingAreaForm); + } catch (FormValidationException $ex) { + // Form cannot be validated + $error_msg = $this->createStandardFormValidationErrorMessage($ex); + } catch (\Exception $ex) { + // Any other error + $error_msg = $ex->getMessage(); + } + + $this->setupFormErrorContext( + $this->getTranslator()->trans("%obj modification", array('%obj' => $this->objectName)), + $error_msg, + $shippingAreaForm + ); + + // At this point, the form has errors, and should be redisplayed. + return $this->renderEditionTemplate(); + } + + /** + * Render the edition template + */ + protected function renderEditionTemplate() + { + return $this->render( + "shipping-zones-edit", + ["delivery_module_id" => $this->getDeliveryModuleId()] + ); + } + + protected function getDeliveryModuleId() + { + return $this->getRequest()->get('delivery_module_id', 0); + } +} diff --git a/core/lib/Thelia/Controller/Admin/StateController.php b/core/lib/Thelia/Controller/Admin/StateController.php new file mode 100644 index 00000000..9d4c56de --- /dev/null +++ b/core/lib/Thelia/Controller/Admin/StateController.php @@ -0,0 +1,244 @@ + + */ +class StateController extends AbstractCrudController +{ + public function __construct() + { + parent::__construct( + 'state', + 'manual', + 'state_order', + AdminResources::STATE, + TheliaEvents::STATE_CREATE, + TheliaEvents::STATE_UPDATE, + TheliaEvents::STATE_DELETE, + TheliaEvents::STATE_TOGGLE_VISIBILITY + ); + } + + /** + * Return the creation form for this object + */ + protected function getCreationForm() + { + return $this->createForm(AdminForm::STATE_CREATION); + } + + /** + * Return the update form for this object + */ + protected function getUpdateForm() + { + return $this->createForm(AdminForm::STATE_MODIFICATION); + } + + /** + * Hydrate the update form for this object, before passing it to the update template + * + * @param \Thelia\Model\State $object + */ + protected function hydrateObjectForm($object) + { + $data = array( + 'id' => $object->getId(), + 'locale' => $object->getLocale(), + 'visible' => $object->getVisible() ? true : false, + 'country_id' => $object->getCountryId(), + 'title' => $object->getTitle(), + 'isocode' => $object->getIsocode(), + ); + + return $this->createForm(AdminForm::STATE_MODIFICATION, 'form', $data); + } + + /** + * Creates the creation event with the provided form data + * + * @param unknown $formData + */ + protected function getCreationEvent($formData) + { + $event = new StateCreateEvent(); + + return $this->hydrateEvent($event, $formData); + } + + /** + * Creates the update event with the provided form data + * + * @param unknown $formData + */ + protected function getUpdateEvent($formData) + { + $event = new StateUpdateEvent($formData['id']); + + return $this->hydrateEvent($event, $formData); + } + + protected function hydrateEvent($event, $formData) + { + $event + ->setLocale($formData['locale']) + ->setVisible($formData['visible']) + ->setCountry($formData['country_id']) + ->setTitle($formData['title']) + ->setIsocode($formData['isocode']) + ; + + return $event; + } + + /** + * Creates the delete event with the provided form data + */ + protected function getDeleteEvent() + { + return new StateDeleteEvent($this->getRequest()->get('state_id')); + } + + /** + * Return true if the event contains the object, e.g. the action has updated the object in the event. + * + * @param unknown $event + */ + protected function eventContainsObject($event) + { + return $event->hasState(); + } + + /** + * Get the created object from an event. + * + * @param unknown $createEvent + */ + protected function getObjectFromEvent($event) + { + return $event->getState(); + } + + /** + * Load an existing object from the database + */ + protected function getExistingObject() + { + $state = StateQuery::create() + ->findPk($this->getRequest()->get('state_id', 0)) + ; + + if (null !== $state) { + $state->setLocale($this->getCurrentEditionLocale()); + } + + return $state; + } + + /** + * Returns the object label form the object event (name, title, etc.) + * + * @param \Thelia\Model\State $object + */ + protected function getObjectLabel($object) + { + return $object->getTitle(); + } + + /** + * Returns the object ID from the object + * + * @param \Thelia\Model\State $object + */ + protected function getObjectId($object) + { + return $object->getId(); + } + + /** + * Render the main list template + * + * @param unknown $currentOrder , if any, null otherwise. + */ + protected function renderListTemplate($currentOrder) + { + return $this->render( + "states", + array( + 'page' => $this->getRequest()->get('page', 1), + "page_limit" => $this->getRequest()->get('page_limit', 50), + 'page_order' => $this->getRequest()->get('page_order', 1) + ) + ); + } + + /** + * Render the edition template + */ + protected function renderEditionTemplate() + { + return $this->render('state-edit', $this->getEditionArgument()); + } + + protected function getEditionArgument() + { + return array( + 'state_id' => $this->getRequest()->get('state_id', 0), + 'page' => $this->getRequest()->get('page', 1), + 'page_order' => $this->getRequest()->get('page_order', 1) + ); + } + + /** + * Redirect to the edition template + */ + protected function redirectToEditionTemplate() + { + return $this->generateRedirectFromRoute( + 'admin.configuration.states.update', + [], + [ + "state_id" => $this->getRequest()->get('state_id', 0) + ] + ); + } + + /** + * Redirect to the list template + */ + protected function redirectToListTemplate() + { + return $this->generateRedirectFromRoute('admin.configuration.states.default'); + } + + /** + * @return StateToggleVisibilityEvent|void + */ + protected function createToggleVisibilityEvent() + { + return new StateToggleVisibilityEvent($this->getExistingObject()); + } +} diff --git a/core/lib/Thelia/Controller/Admin/SystemLogController.php b/core/lib/Thelia/Controller/Admin/SystemLogController.php new file mode 100644 index 00000000..b68dbb62 --- /dev/null +++ b/core/lib/Thelia/Controller/Admin/SystemLogController.php @@ -0,0 +1,165 @@ + + */ +class SystemLogController extends BaseAdminController +{ + protected function renderTemplate() + { + $destinations = array(); + + $destination_directories = Tlog::getInstance()->getDestinationsDirectories(); + + foreach ($destination_directories as $dir) { + $this->loadDefinedDestinations($dir, $destinations); + } + + $active_destinations = explode(";", ConfigQuery::read(Tlog::VAR_DESTINATIONS, Tlog::DEFAUT_DESTINATIONS)); + + return $this->render( + 'system-logs', + array( + 'ip_address' => $this->getRequest()->getClientIp(), + 'destinations' => $destinations, + 'active_destinations' => $active_destinations + ) + ); + } + + protected function loadDefinedDestinations($directory, &$destinations) + { + try { + foreach (new \DirectoryIterator($directory) as $fileInfo) { + if ($fileInfo->isDot()) { + continue; + } + + $matches = array(); + + if (preg_match("/([^\.]+)\.php/", $fileInfo->getFilename(), $matches)) { + $classname = $matches[1]; + + if (! isset($destinations[$classname])) { + $full_class_name = "Thelia\\Log\\Destination\\".$classname; + + $destinations[$classname] = new $full_class_name(); + } + } + } + } catch (\UnexpectedValueException $ex) { + // Directory does no exists -> Nothing to do + } + } + + /** + * @return mixed|\Thelia\Core\HttpFoundation\Response + */ + public function defaultAction() + { + if (null !== $response = $this->checkAuth(AdminResources::SYSTEM_LOG, array(), AccessManager::VIEW)) { + return $response; + } + + // Hydrate the general configuration form + $systemLogForm = $this->createForm(AdminForm::SYSTEM_LOG_CONFIGURATION, 'form', array( + 'level' => ConfigQuery::read(Tlog::VAR_LEVEL, Tlog::DEFAULT_LEVEL), + 'format' => ConfigQuery::read(Tlog::VAR_PREFIXE, Tlog::DEFAUT_PREFIXE), + 'show_redirections' => ConfigQuery::read(Tlog::VAR_SHOW_REDIRECT, Tlog::DEFAUT_SHOW_REDIRECT), + 'files' => ConfigQuery::read(Tlog::VAR_FILES, Tlog::DEFAUT_FILES), + 'ip_addresses' => ConfigQuery::read(Tlog::VAR_IP, Tlog::DEFAUT_IP), + )); + + $this->getParserContext()->addForm($systemLogForm); + + return $this->renderTemplate(); + } + + public function saveAction() + { + if (null !== $response = $this->checkAuth(AdminResources::SYSTEM_LOG, array(), AccessManager::UPDATE)) { + return $response; + } + + $error_msg = false; + + $systemLogForm = $this->createForm(AdminForm::SYSTEM_LOG_CONFIGURATION); + + try { + $form = $this->validateForm($systemLogForm); + + $data = $form->getData(); + + ConfigQuery::write(Tlog::VAR_LEVEL, $data['level']); + ConfigQuery::write(Tlog::VAR_PREFIXE, $data['format']); + ConfigQuery::write(Tlog::VAR_SHOW_REDIRECT, $data['show_redirections']); + ConfigQuery::write(Tlog::VAR_FILES, $data['files']); + ConfigQuery::write(Tlog::VAR_IP, $data['ip_addresses']); + + // Save destination configuration + $destinations = $this->getRequest()->get('destinations'); + $configs = $this->getRequest()->get('config'); + + $active_destinations = array(); + + foreach ($destinations as $classname => $destination) { + if (isset($destination['active'])) { + $active_destinations[] = $destination['classname']; + } + + if (isset($configs[$classname])) { + // Update destinations configuration + foreach ($configs[$classname] as $var => $value) { + ConfigQuery::write($var, $value, true, true); + } + } + } + + // Update active destinations list + ConfigQuery::write(Tlog::VAR_DESTINATIONS, implode(';', $active_destinations)); + + $this->adminLogAppend( + AdminResources::SYSTEM_LOG, + AccessManager::UPDATE, + "System log configuration changed" + ); + + $response = $this->generateRedirectFromRoute('admin.configuration.system-logs.default'); + } catch (\Exception $ex) { + $error_msg = $ex->getMessage(); + } + + if (false !== $error_msg) { + $this->setupFormErrorContext( + $this->getTranslator()->trans("System log configuration failed."), + $error_msg, + $systemLogForm, + $ex + ); + + $response = $this->renderTemplate(); + } + + return $response; + } +} diff --git a/core/lib/Thelia/Controller/Admin/TaxController.php b/core/lib/Thelia/Controller/Admin/TaxController.php new file mode 100644 index 00000000..eb338274 --- /dev/null +++ b/core/lib/Thelia/Controller/Admin/TaxController.php @@ -0,0 +1,218 @@ +createForm(AdminForm::TAX_CREATION); + + return $form; + } + + protected function getUpdateForm() + { + return $this->createForm(AdminForm::TAX_MODIFICATION); + } + + protected function getCreationEvent($formData) + { + $event = new TaxEvent(); + + $event->setLocale($formData['locale']); + $event->setTitle($formData['title']); + $event->setDescription($formData['description']); + $event->setType(Tax::unescapeTypeName($formData['type'])); + $event->setRequirements($this->getRequirements($formData['type'], $formData)); + + return $event; + } + + protected function getUpdateEvent($formData) + { + $event = new TaxEvent(); + + $event->setLocale($formData['locale']); + $event->setId($formData['id']); + $event->setTitle($formData['title']); + $event->setDescription($formData['description']); + $event->setType(Tax::unescapeTypeName($formData['type'])); + $event->setRequirements($this->getRequirements($formData['type'], $formData)); + + return $event; + } + + protected function getDeleteEvent() + { + $event = new TaxEvent(); + + $event->setId( + $this->getRequest()->get('tax_id', 0) + ); + + return $event; + } + + protected function eventContainsObject($event) + { + return $event->hasTax(); + } + + protected function hydrateObjectForm($object) + { + $data = array( + 'id' => $object->getId(), + 'locale' => $object->getLocale(), + 'title' => $object->getTitle(), + 'description' => $object->getDescription(), + 'type' => Tax::escapeTypeName($object->getType()), + ); + + // Setup the object form + return $this->createForm( + AdminForm::TAX_MODIFICATION, + "form", + $data + ); + } + + protected function getObjectFromEvent($event) + { + return $event->hasTax() ? $event->getTax() : null; + } + + protected function getExistingObject() + { + $tax = TaxQuery::create() + ->findOneById($this->getRequest()->get('tax_id', 0)); + + if (null !== $tax) { + $tax->setLocale($this->getCurrentEditionLocale()); + } + + return $tax; + } + + /** + * @param Tax $object + * @return string + */ + protected function getObjectLabel($object) + { + return $object->getTitle(); + } + + /** + * @param Tax $object + * @return int + */ + protected function getObjectId($object) + { + return $object->getId(); + } + + protected function getViewArguments() + { + return array(); + } + + protected function getRouteArguments($tax_id = null) + { + return array( + 'tax_id' => $tax_id === null ? $this->getRequest()->get('tax_id') : $tax_id, + ); + } + + protected function renderListTemplate($currentOrder) + { + return $this->render( + 'taxes-rules', + array() + ); + } + + protected function renderEditionTemplate() + { + // We always return to the feature edition form + return $this->render('tax-edit', array_merge($this->getViewArguments(), $this->getRouteArguments())); + } + + protected function redirectToEditionTemplate($request = null, $country = null) + { + return $this->generateRedirectFromRoute( + "admin.configuration.taxes.update", + $this->getViewArguments($country), + $this->getRouteArguments() + ); + } + + /** + * Put in this method post object creation processing if required. + * + * @param TaxEvent $createEvent the create event + * @return Response a response, or null to continue normal processing + */ + protected function performAdditionalCreateAction($createEvent) + { + return $this->generateRedirectFromRoute( + "admin.configuration.taxes.update", + $this->getViewArguments(), + $this->getRouteArguments($createEvent->getTax()->getId()) + ); + } + + protected function redirectToListTemplate() + { + return $this->generateRedirectFromRoute("admin.configuration.taxes-rules.list"); + } + + protected function getRequirements($type, $formData) + { + $requirements = array(); + foreach ($formData as $data => $value) { + if (!strstr($data, ':')) { + continue; + } + + $couple = explode(':', $data); + + if (\count($couple) == 2 && $couple[0] == $type) { + $requirements[$couple[1]] = $value; + } + } + + return $requirements; + } +} diff --git a/core/lib/Thelia/Controller/Admin/TaxRuleController.php b/core/lib/Thelia/Controller/Admin/TaxRuleController.php new file mode 100644 index 00000000..d5a57e2b --- /dev/null +++ b/core/lib/Thelia/Controller/Admin/TaxRuleController.php @@ -0,0 +1,422 @@ +createForm(AdminForm::TAX_CREATION); + + $this->getParserContext()->addForm($taxCreationForm); + + return parent::defaultAction(); + } + + protected function getCreationForm() + { + return $this->createForm(AdminForm::TAX_RULE_CREATION); + } + + protected function getUpdateForm() + { + return $this->createForm(AdminForm::TAX_RULE_MODIFICATION); + } + + protected function getCreationEvent($formData) + { + $event = new TaxRuleEvent(); + + $event->setLocale($formData['locale']); + $event->setTitle($formData['title']); + $event->setDescription($formData['description']); + + return $event; + } + + protected function getUpdateEvent($formData) + { + $event = new TaxRuleEvent(); + + $event->setLocale($formData['locale']); + $event->setId($formData['id']); + $event->setTitle($formData['title']); + $event->setDescription($formData['description']); + + return $event; + } + + protected function getUpdateTaxListEvent($formData) + { + $event = new TaxRuleEvent(); + + $event->setId($formData['id']); + $event->setTaxList($formData['tax_list']); + $event->setCountryList($formData['country_list']); + $event->setCountryDeletedList($formData['country_deleted_list']); + + return $event; + } + + protected function getDeleteEvent() + { + $event = new TaxRuleEvent(); + + $event->setId( + $this->getRequest()->get('tax_rule_id', 0) + ); + + return $event; + } + + protected function eventContainsObject($event) + { + return $event->hasTaxRule(); + } + + protected function hydrateObjectForm($object) + { + $data = array( + 'id' => $object->getId(), + 'locale' => $object->getLocale(), + 'title' => $object->getTitle(), + 'description' => $object->getDescription(), + ); + + // Setup the object form + return $this->createForm(AdminForm::TAX_RULE_MODIFICATION, "form", $data); + } + + /** + * @param TaxRule $object + * @return \Thelia\Form\BaseForm + */ + protected function hydrateTaxUpdateForm($object) + { + $data = array( + 'id' => $object->getId(), + ); + + // Setup the object form + return $this->createForm(AdminForm::TAX_RULE_TAX_LIST_UPDATE, "form", $data); + } + + protected function getObjectFromEvent($event) + { + return $event->hasTaxRule() ? $event->getTaxRule() : null; + } + + protected function getExistingObject() + { + $taxRule = TaxRuleQuery::create() + ->findOneById($this->getRequest()->get('tax_rule_id')); + + if (null !== $taxRule) { + $taxRule->setLocale($this->getCurrentEditionLocale()); + } + + return $taxRule; + } + + /** + * @param TaxRule $object + * @return string + */ + protected function getObjectLabel($object) + { + return $object->getTitle(); + } + + /** + * @param TaxRule $object + * @return int + */ + protected function getObjectId($object) + { + return $object->getId(); + } + + protected function getViewArguments($country = null, $tab = null, $state = null) + { + return array( + 'tab' => $tab === null ? $this->getRequest()->get('tab', 'data') : $tab, + 'country' => $country === null ? $this->getRequest()->get('country', CountryQuery::create()->findOneByByDefault(1)->getId()) : $country, + 'state' => $state, + ); + } + + protected function getRouteArguments($tax_rule_id = null) + { + return array( + 'tax_rule_id' => $tax_rule_id === null ? $this->getRequest()->get('tax_rule_id') : $tax_rule_id, + ); + } + + protected function renderListTemplate($currentOrder) + { + // We always return to the feature edition form + return $this->render( + 'taxes-rules', + array() + ); + } + + protected function renderEditionTemplate() + { + // We always return to the feature edition form + return $this->render('tax-rule-edit', array_merge($this->getViewArguments(), $this->getRouteArguments())); + } + + protected function redirectToEditionTemplate($request = null, $country = null, $state = null) + { + return $this->generateRedirectFromRoute( + "admin.configuration.taxes-rules.update", + $this->getViewArguments($country, null, $state), + $this->getRouteArguments() + ); + } + + /** + * Put in this method post object creation processing if required. + * + * @param TaxRuleEvent $createEvent the create event + * @return Response a response, or null to continue normal processing + */ + protected function performAdditionalCreateAction($createEvent) + { + return $this->generateRedirectFromRoute( + "admin.configuration.taxes-rules.update", + $this->getViewArguments(), + $this->getRouteArguments($createEvent->getTaxRule()->getId()) + ); + } + + protected function redirectToListTemplate() + { + return $this->generateRedirectFromRoute("admin.configuration.taxes-rules.list"); + } + + public function updateAction() + { + if (null !== $response = $this->checkAuth($this->resourceCode, array(), AccessManager::UPDATE)) { + return $response; + } + + $object = $this->getExistingObject(); + + if ($object != null) { + // Hydrate the form abd pass it to the parser + $changeTaxesForm = $this->hydrateTaxUpdateForm($object); + + // Pass it to the parser + $this->getParserContext()->addForm($changeTaxesForm); + } + + return parent::updateAction(); + } + + public function setDefaultAction() + { + if (null !== $response = $this->checkAuth($this->resourceCode, array(), AccessManager::UPDATE)) { + return $response; + } + + $setDefaultEvent = new TaxRuleEvent(); + + $taxRuleId = $this->getRequest()->attributes->get('tax_rule_id'); + + $setDefaultEvent->setId( + $taxRuleId + ); + + $this->dispatch(TheliaEvents::TAX_RULE_SET_DEFAULT, $setDefaultEvent); + + return $this->redirectToListTemplate(); + } + + public function processUpdateTaxesAction() + { + // Check current user authorization + if (null !== $response = $this->checkAuth($this->resourceCode, array(), AccessManager::UPDATE)) { + return $response; + } + + $responseData = [ + "success" => false, + "message" => '' + ]; + + $error_msg = false; + + // Create the form from the request + $changeForm = $this->createForm(AdminForm::TAX_RULE_TAX_LIST_UPDATE); + + try { + // Check the form against constraints violations + $form = $this->validateForm($changeForm, "POST"); + + // Get the form field values + $data = $form->getData(); + + $changeEvent = $this->getUpdateTaxListEvent($data); + + $this->dispatch(TheliaEvents::TAX_RULE_TAXES_UPDATE, $changeEvent); + + if (! $this->eventContainsObject($changeEvent)) { + throw new \LogicException( + $this->getTranslator()->trans("No %obj was updated.", array('%obj', $this->objectName)) + ); + } + + // Log object modification + if (null !== $changedObject = $this->getObjectFromEvent($changeEvent)) { + $this->adminLogAppend( + $this->resourceCode, + AccessManager::UPDATE, + sprintf( + "%s %s (ID %s) modified", + ucfirst($this->objectName), + $this->getObjectLabel($changedObject), + $this->getObjectId($changedObject) + ), + $this->getObjectId($changedObject) + ); + } + + $responseData['success'] = true; + $responseData['data'] = $this->getSpecification( + $changeEvent->getTaxRule()->getId() + ); + + return $this->jsonResponse(json_encode($responseData)); + } catch (FormValidationException $ex) { + // Form cannot be validated + $error_msg = $this->createStandardFormValidationErrorMessage($ex); + } catch (\Exception $ex) { + // Any other error + $error_msg = $ex->getMessage(); + } + + $this->setupFormErrorContext($this->getTranslator()->trans("%obj modification", array('%obj' => 'taxrule')), $error_msg, $changeForm, $ex); + + // At this point, the form has errors, and should be redisplayed. + $responseData["message"] = $error_msg; + + return $this->jsonResponse(json_encode($responseData)); + } + + + /** + * @return Response + */ + public function specsAction($taxRuleId) + { + $data = $this->getSpecification($taxRuleId); + + return $this->jsonResponse(json_encode($data)); + } + + protected function getSpecification($taxRuleId) + { + $taxRuleCountries = TaxRuleCountryQuery::create() + ->filterByTaxRuleId($taxRuleId) + ->orderByCountryId() + ->orderByStateId() + ->orderByPosition() + ->orderByTaxId() + ->find(); + + $specKey = []; + $specifications = []; + $taxRules = []; + + if (!$taxRuleCountries->isEmpty()) { + $taxRuleCountry = $taxRuleCountries->getFirst(); + $currentCountryId = $taxRuleCountry->getCountryId(); + $currentStateId = \intval($taxRuleCountry->getStateId()); + + while (true) { + $hasChanged = $taxRuleCountry === null + || $taxRuleCountry->getCountryId() != $currentCountryId + || \intval($taxRuleCountry->getStateId()) != $currentStateId + ; + + if ($hasChanged) { + $specification = implode(',', $specKey); + + $specifications[] = [ + 'country' => $currentCountryId, + 'state' => $currentStateId, + 'specification' => $specification + ]; + + if (!\in_array($specification, $taxRules)) { + $taxRules[] = $specification; + } + + if (null === $taxRuleCountry) { + break; + } + + $currentCountryId = $taxRuleCountry->getCountryId(); + $currentStateId = \intval($taxRuleCountry->getStateId()); + $specKey = []; + } + + $specKey[] = $taxRuleCountry->getTaxId() . '-' . $taxRuleCountry->getPosition(); + + $taxRuleCountry = $taxRuleCountries->getNext(); + } + } + + $data = [ + 'taxRules' => $taxRules, + 'specifications' => $specifications, + ]; + + return $data; + } +} diff --git a/core/lib/Thelia/Controller/Admin/TemplateController.php b/core/lib/Thelia/Controller/Admin/TemplateController.php new file mode 100644 index 00000000..0c3c5037 --- /dev/null +++ b/core/lib/Thelia/Controller/Admin/TemplateController.php @@ -0,0 +1,373 @@ + + */ +class TemplateController extends AbstractCrudController +{ + public function __construct() + { + parent::__construct( + 'template', + null, + null, + AdminResources::TEMPLATE, + TheliaEvents::TEMPLATE_CREATE, + TheliaEvents::TEMPLATE_UPDATE, + TheliaEvents::TEMPLATE_DELETE, + null, // No visibility toggle + null // No position update + ); + } + + protected function getCreationForm() + { + return $this->createForm(AdminForm::TEMPLATE_CREATION); + } + + protected function getUpdateForm() + { + return $this->createForm(AdminForm::TEMPLATE_MODIFICATION); + } + + protected function getCreationEvent($formData) + { + $createEvent = new TemplateCreateEvent(); + + $createEvent + ->setTemplateName($formData['name']) + ->setLocale($formData["locale"]) + ; + + return $createEvent; + } + + protected function getUpdateEvent($formData) + { + $changeEvent = new TemplateUpdateEvent($formData['id']); + + // Create and dispatch the change event + $changeEvent + ->setLocale($formData["locale"]) + ->setTemplateName($formData['name']) + ; + + // Add feature and attributes list + return $changeEvent; + } + + protected function getDeleteEvent() + { + return new TemplateDeleteEvent($this->getRequest()->get('template_id')); + } + + protected function eventContainsObject($event) + { + return $event->hasTemplate(); + } + + protected function hydrateObjectForm($object) + { + $data = array( + 'id' => $object->getId(), + 'locale' => $object->getLocale(), + 'name' => $object->getName() + ); + + // Setup the object form + return $this->createForm(AdminForm::TEMPLATE_MODIFICATION, "form", $data); + } + + protected function getObjectFromEvent($event) + { + return $event->hasTemplate() ? $event->getTemplate() : null; + } + + protected function getExistingObject() + { + $template = TemplateQuery::create() + ->findOneById($this->getRequest()->get('template_id', 0)); + + if (null !== $template) { + $template->setLocale($this->getCurrentEditionLocale()); + } + + return $template; + } + + /** + * @param Template $object + * @return string + */ + protected function getObjectLabel($object) + { + return $object->getName(); + } + + /** + * @param Template $object + * @return int + */ + protected function getObjectId($object) + { + return $object->getId(); + } + + protected function renderListTemplate($currentOrder) + { + return $this->render('templates', array('order' => $currentOrder)); + } + + protected function renderEditionTemplate() + { + return $this->render( + 'template-edit', + array( + 'template_id' => $this->getRequest()->get('template_id'), + ) + ); + } + + /** + * @param Request $request + * @param int $id + * @return \Symfony\Component\HttpFoundation\Response + */ + protected function redirectToEditionTemplate($request = null, $id = null) + { + return $this->generateRedirectFromRoute( + "admin.configuration.templates.update", + [ + 'template_id' => $id ?: $this->getRequest()->get('template_id'), + ] + ); + } + + protected function redirectToListTemplate() + { + return $this->generateRedirectFromRoute('admin.configuration.templates.default'); + } + + /** + * Process delete failure, which may occurs if template is in use. + * + * @param TemplateDeleteEvent $deleteEvent + * @return null|\Thelia\Core\HttpFoundation\Response + */ + protected function performAdditionalDeleteAction($deleteEvent) + { + if ($deleteEvent->getProductCount() > 0) { + $this->getParserContext()->setGeneralError( + $this->getTranslator()->trans( + "This template is in use in some of your products, and cannot be deleted. Delete it from all your products and try again." + ) + ); + + return $this->renderList(); + } + + // Normal delete processing + 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() + { + return $this->render( + 'ajax/template-feature-list', + array('template_id' => $this->getRequest()->get('template_id')) + ); + } + + public function getAjaxAttributesAction() + { + return $this->render( + 'ajax/template-attribute-list', + array('template_id' => $this->getRequest()->get('template_id')) + ); + } + + public function addAttributeAction() + { + // Check current user authorization + if (null !== $response = $this->checkAuth(AdminResources::TEMPLATE, array(), AccessManager::UPDATE)) { + return $response; + } + + $attribute_id = \intval($this->getRequest()->get('attribute_id')); + + if ($attribute_id > 0) { + $event = new TemplateAddAttributeEvent( + $this->getExistingObject(), + $attribute_id + ); + + try { + $this->dispatch(TheliaEvents::TEMPLATE_ADD_ATTRIBUTE, $event); + } catch (\Exception $ex) { + // Any error + return $this->errorPage($ex); + } + } + + return $this->redirectToEditionTemplate(); + } + + public function deleteAttributeAction() + { + // Check current user authorization + if (null !== $response = $this->checkAuth(AdminResources::TEMPLATE, array(), AccessManager::UPDATE)) { + return $response; + } + + $event = new TemplateDeleteAttributeEvent( + $this->getExistingObject(), + \intval($this->getRequest()->get('attribute_id')) + ); + + try { + $this->dispatch(TheliaEvents::TEMPLATE_DELETE_ATTRIBUTE, $event); + } catch (\Exception $ex) { + // Any error + return $this->errorPage($ex); + } + + return $this->redirectToEditionTemplate(); + } + + public function updateAttributePositionAction() + { + // Find attribute_template + $attributeTemplate = AttributeTemplateQuery::create() + ->filterByTemplateId($this->getRequest()->get('template_id', null)) + ->filterByAttributeId($this->getRequest()->get('attribute_id', null)) + ->findOne() + ; + + return $this->genericUpdatePositionAction( + $attributeTemplate, + TheliaEvents::TEMPLATE_CHANGE_ATTRIBUTE_POSITION + ); + } + + public function addFeatureAction() + { + // Check current user authorization + if (null !== $response = $this->checkAuth(AdminResources::TEMPLATE, array(), AccessManager::UPDATE)) { + return $response; + } + + $feature_id = \intval($this->getRequest()->get('feature_id')); + + if ($feature_id > 0) { + $event = new TemplateAddFeatureEvent( + $this->getExistingObject(), + $feature_id + ); + + try { + $this->dispatch(TheliaEvents::TEMPLATE_ADD_FEATURE, $event); + } catch (\Exception $ex) { + // Any error + return $this->errorPage($ex); + } + } + + return $this->redirectToEditionTemplate(); + } + + public function deleteFeatureAction() + { + // Check current user authorization + if (null !== $response = $this->checkAuth(AdminResources::TEMPLATE, array(), AccessManager::UPDATE)) { + return $response; + } + + $event = new TemplateDeleteFeatureEvent( + $this->getExistingObject(), + \intval($this->getRequest()->get('feature_id')) + ); + + try { + $this->dispatch(TheliaEvents::TEMPLATE_DELETE_FEATURE, $event); + } catch (\Exception $ex) { + // Any error + return $this->errorPage($ex); + } + + return $this->redirectToEditionTemplate(); + } + + public function updateFeaturePositionAction() + { + // Find feature_template + $featureTemplate = FeatureTemplateQuery::create() + ->filterByTemplateId($this->getRequest()->get('template_id', null)) + ->filterByFeatureId($this->getRequest()->get('feature_id', null)) + ->findOne() + ; + + return $this->genericUpdatePositionAction( + $featureTemplate, + TheliaEvents::TEMPLATE_CHANGE_FEATURE_POSITION + ); + } +} diff --git a/core/lib/Thelia/Controller/Admin/ToolsController.php b/core/lib/Thelia/Controller/Admin/ToolsController.php new file mode 100644 index 00000000..32ece22f --- /dev/null +++ b/core/lib/Thelia/Controller/Admin/ToolsController.php @@ -0,0 +1,33 @@ + + */ +class ToolsController extends BaseAdminController +{ + public function indexAction() + { + if (null !== $response = $this->checkAuth([AdminResources::TOOLS], [], [AccessManager::VIEW])) { + return $response; + } + + return $this->render('tools'); + } +} diff --git a/core/lib/Thelia/Controller/Admin/TranslationsController.php b/core/lib/Thelia/Controller/Admin/TranslationsController.php new file mode 100644 index 00000000..ca28992d --- /dev/null +++ b/core/lib/Thelia/Controller/Admin/TranslationsController.php @@ -0,0 +1,359 @@ + + */ +class TranslationsController extends BaseAdminController +{ + /** + * @param string $itemName the modume code + * @return Module the module object + * @throws \InvalidArgumentException if module was not found + */ + protected function getModule($itemName) + { + if (null !== $module = ModuleQuery::create()->findPk($itemName)) { + return $module; + } + + throw new \InvalidArgumentException( + $this->getTranslator()->trans("No module found for code '%item'", ['%item' => $itemName]) + ); + } + + protected function getModuleTemplateNames(Module $module, $templateType) + { + $templates = + $this->getTemplateHelper()->getList( + $templateType, + $module->getAbsoluteTemplateBasePath() + ); + + $names = []; + + foreach ($templates as $template) { + $names[] = $template->getName(); + } + + return $names; + } + + protected function renderTemplate() + { + // Get related strings, if all input data are here + $itemToTranslate = $this->getRequest()->get('item_to_translate'); + + $itemName = $this->getRequest()->get('item_name', ''); + + if ($itemToTranslate == 'mo' && ! empty($itemName)) { + $modulePart = $this->getRequest()->get('module_part', ''); + } else { + $modulePart = false; + } + + $template = $directory = $i18nDirectory = false; + + $walkMode = TranslationEvent::WALK_MODE_TEMPLATE; + + $templateArguments = array( + 'item_to_translate' => $itemToTranslate, + 'item_name' => $itemName, + 'module_part' => $modulePart, + 'view_missing_traductions_only' => $this->getRequest()->get('view_missing_traductions_only'), + 'max_input_vars_warning' => false, + ); + + // Find the i18n directory, and the directory to examine. + + if (! empty($itemName) || $itemToTranslate == 'co' || $itemToTranslate == 'in' || $itemToTranslate == 'wi') { + switch ($itemToTranslate) { + + // Module core + case 'mo': + $module = $this->getModule($itemName); + + if ($modulePart == 'core') { + $directory = $module->getAbsoluteBaseDir(); + $domain = $module->getTranslationDomain(); + $i18nDirectory = $module->getAbsoluteI18nPath(); + $walkMode = TranslationEvent::WALK_MODE_PHP; + } elseif ($modulePart == 'admin-includes') { + $directory = $module->getAbsoluteAdminIncludesPath(); + $domain = $module->getAdminIncludesTranslationDomain(); + $i18nDirectory = $module->getAbsoluteAdminIncludesI18nPath(); + $walkMode = TranslationEvent::WALK_MODE_TEMPLATE; + } elseif (! empty($modulePart)) { + // Front, back, pdf or email office template, + // form of $module_part is [bo|fo|pdf|email].subdir-name + list($type, $subdir) = explode('.', $modulePart); + + switch ($type) { + case 'bo': + $directory = $module->getAbsoluteBackOfficeTemplatePath($subdir); + $domain = $module->getBackOfficeTemplateTranslationDomain($subdir); + $i18nDirectory = $module->getAbsoluteBackOfficeI18nTemplatePath($subdir); + break; + case 'fo': + $directory = $module->getAbsoluteFrontOfficeTemplatePath($subdir); + $domain = $module->getFrontOfficeTemplateTranslationDomain($subdir); + $i18nDirectory = $module->getAbsoluteFrontOfficeI18nTemplatePath($subdir); + break; + case 'email': + $directory = $module->getAbsoluteEmailTemplatePath($subdir); + $domain = $module->getEmailTemplateTranslationDomain($subdir); + $i18nDirectory = $module->getAbsoluteEmailI18nTemplatePath($subdir); + break; + case 'pdf': + $directory = $module->getAbsolutePdfTemplatePath($subdir); + $domain = $module->getPdfTemplateTranslationDomain($subdir); + $i18nDirectory = $module->getAbsolutePdfI18nTemplatePath($subdir); + break; + default: + throw new \InvalidArgumentException("Undefined module template type: '$type'."); + } + + $walkMode = TranslationEvent::WALK_MODE_TEMPLATE; + } + + // Modules translations files are in the cache, and are not always + // updated. Force a reload of the files to get last changes. + if (! empty($domain)) { + $this->loadTranslation($i18nDirectory, $domain); + } + + // List front and back office templates defined by this module + $templateArguments['back_office_templates'] = + implode(',', $this->getModuleTemplateNames($module, TemplateDefinition::BACK_OFFICE)); + + $templateArguments['front_office_templates'] = + implode(',', $this->getModuleTemplateNames($module, TemplateDefinition::FRONT_OFFICE)); + + $templateArguments['email_templates'] = + implode(',', $this->getModuleTemplateNames($module, TemplateDefinition::EMAIL)); + + $templateArguments['pdf_templates'] = + implode(',', $this->getModuleTemplateNames($module, TemplateDefinition::PDF)); + + // Check if we have admin-include files + try { + $finder = Finder::create() + ->files() + ->depth(0) + ->in($module->getAbsoluteAdminIncludesPath()) + ->name('/\.html$/i') + ; + + $hasAdminIncludes = $finder->count() > 0; + } catch (\InvalidArgumentException $ex) { + $hasAdminIncludes = false; + } + + $templateArguments['has_admin_includes'] = $hasAdminIncludes; + + break; + + // Thelia Core + case 'co': + $directory = THELIA_LIB; + $domain = 'core'; + $i18nDirectory = THELIA_LIB . 'Config' . DS . 'I18n'; + $walkMode = TranslationEvent::WALK_MODE_PHP; + break; + + // Thelia Install + case 'in': + $directory = THELIA_SETUP_DIRECTORY; + $domain = 'install'; + $i18nDirectory = THELIA_SETUP_DIRECTORY . 'I18n'; + $walkMode = TranslationEvent::WALK_MODE_TEMPLATE; + // resources not loaded by default + $this->loadTranslation($i18nDirectory, $domain); + break; + + // Thelia Install wizard + case 'wi': + $directory = THELIA_SETUP_WIZARD_DIRECTORY; + $domain = 'wizard'; + $i18nDirectory = THELIA_SETUP_WIZARD_DIRECTORY . 'I18n'; + $walkMode = TranslationEvent::WALK_MODE_PHP; + // resources not loaded by default + $this->loadTranslation($i18nDirectory, $domain); + break; + + // Front-office template + case 'fo': + $template = new TemplateDefinition($itemName, TemplateDefinition::FRONT_OFFICE); + break; + + // Back-office template + case 'bo': + $template = new TemplateDefinition($itemName, TemplateDefinition::BACK_OFFICE); + break; + + // PDF templates + case 'pf': + $template = new TemplateDefinition($itemName, TemplateDefinition::PDF); + break; + + // Email templates + case 'ma': + $template = new TemplateDefinition($itemName, TemplateDefinition::EMAIL); + break; + } + + if ($template) { + $directory = $template->getAbsolutePath(); + + $i18nDirectory = $template->getAbsoluteI18nPath(); + + $domain = $template->getTranslationDomain(); + + // Load translations files if this template is not the current template + // as it is not loaded in Thelia.php + if (! $this->getTemplateHelper()->isActive($template)) { + $this->loadTranslation($i18nDirectory, $domain); + } + } + + // Load strings to translate + if ($directory && ! empty($domain)) { + // Save the string set, if the form was submitted + if ($i18nDirectory) { + $save_mode = $this->getRequest()->get('save_mode', false); + + if ($save_mode !== false) { + $texts = $this->getRequest()->get('text', array()); + + if (! empty($texts)) { + $event = TranslationEvent::createWriteFileEvent( + sprintf("%s".DS."%s.php", $i18nDirectory, $this->getCurrentEditionLocale()), + $texts, + $this->getRequest()->get('translation', []), + true + ); + + $event + ->setDomain($domain) + ->setLocale($this->getCurrentEditionLocale()) + ->setCustomFallbackStrings($this->getRequest()->get('translation_custom', [])) + ->setGlobalFallbackStrings($this->getRequest()->get('translation_global', [])); + + $this->getDispatcher()->dispatch(TheliaEvents::TRANSLATION_WRITE_FILE, $event); + + if ($save_mode == 'stay') { + return $this->generateRedirectFromRoute( + "admin.configuration.translations", + $templateArguments + ); + } else { + return $this->generateRedirect(URL::getInstance()->adminViewUrl('configuration')); + } + } + } + } + + // Load strings + $event = TranslationEvent::createGetStringsEvent( + $directory, + $walkMode, + $this->getCurrentEditionLocale(), + $domain + ); + + $this->getDispatcher()->dispatch(TheliaEvents::TRANSLATION_GET_STRINGS, $event); + + // Estimate number of fields, and compare to php ini max_input_vars + $stringsCount = $event->getTranslatableStringCount() * 4 + 6; + + if ($stringsCount > ini_get('max_input_vars')) { + $templateArguments['max_input_vars_warning'] = true; + $templateArguments['required_max_input_vars'] = $stringsCount; + $templateArguments['current_max_input_vars'] = ini_get('max_input_vars'); + } else { + $templateArguments['all_strings'] = $event->getTranslatableStrings(); + } + + $templateArguments['is_writable'] = $this->checkWritableI18nDirectory(THELIA_LOCAL_DIR . 'I18n'); + } + } + + return $this->render('translations', $templateArguments); + } + + /** + * Check if a directory is writable or if the parent directory is writable + * + * @param string $dir the directory to test + * @return boolean return true if the directory is writable otr if the parent dir is writable. + */ + public function checkWritableI18nDirectory($dir) + { + if (file_exists($dir)) { + return is_writable($dir); + } + + $parentDir = dirname($dir); + + return file_exists($parentDir) && is_writable($parentDir); + } + + public function defaultAction() + { + if (null !== $response = $this->checkAuth(AdminResources::TRANSLATIONS, array(), AccessManager::VIEW)) { + return $response; + } + return $this->renderTemplate(); + } + + public function updateAction() + { + if (null !== $response = $this->checkAuth(AdminResources::LANGUAGE, array(), AccessManager::UPDATE)) { + return $response; + } + return $this->renderTemplate(); + } + + private function loadTranslation($directory, $domain) + { + try { + $finder = Finder::create() + ->files() + ->depth(0) + ->in($directory); + + /** @var \DirectoryIterator $file */ + foreach ($finder as $file) { + list($locale, $format) = explode('.', $file->getBaseName(), 2); + + Translator::getInstance()->addResource($format, $file->getPathname(), $locale, $domain); + } + } catch (\InvalidArgumentException $ex) { + // Ignore missing I18n directories + } + } +} diff --git a/core/lib/Thelia/Controller/Api/AbstractCrudApiController.php b/core/lib/Thelia/Controller/Api/AbstractCrudApiController.php new file mode 100644 index 00000000..47acfd31 --- /dev/null +++ b/core/lib/Thelia/Controller/Api/AbstractCrudApiController.php @@ -0,0 +1,505 @@ + + */ +abstract class AbstractCrudApiController extends BaseApiController +{ + /** + * @var string + * + * The entity name to display errors + */ + protected $objName; + + /** + * @var mixed|array + * + * ACL resources used for rights checking + */ + protected $resources; + + /** + * @var array + * + * Events to call on entity creation + */ + protected $createEvents; + + /** + * @var array + * + * Events to call on entity update + */ + protected $updateEvents; + + /** + * @var array + * + * Events to call on entity deletion + */ + protected $deleteEvents; + + /** + * @var mixed|array + * + * ACL modules used for rights checking + */ + protected $modules; + + /** + * @var integer + * + * limit for the list operation + */ + protected $defaultLoopArgs; + + /** + * @var string + * + * The id parameter used to filter in the loop + */ + protected $idParameterName; + + /** + * @param $objName + * @param $resources + * @param $createEvents + * @param $updateEvents + * @param $deleteEvents + * @param array $modules The module codes related to the ACL + * @param array $defaultLoopArgs The loop default arguments + * @param string $idParameterName The "id" parameter name in your loop. Generally "id" + */ + public function __construct( + $objName, + $resources, + $createEvents, + $updateEvents, + $deleteEvents, + $modules = [], + $defaultLoopArgs = null, + $idParameterName = "id" + ) { + $this->objName = $objName; + $this->resources = $resources; + + $this->initializeEvents([ + "createEvents" => $createEvents, + "updateEvents" => $updateEvents, + "deleteEvents" => $deleteEvents, + ]); + + $this->modules = $modules; + $this->defaultLoopArgs = $defaultLoopArgs ?: ["limit" => 10, "offset" => 0, "visible" => "*"]; + $this->idParameterName = $idParameterName; + } + + /** + * @return JsonResponse + * + * The method provides the "list" feed for an entity. + */ + public function listAction() + { + $this->checkAuth($this->resources, $this->modules, AccessManager::VIEW); + $request = $this->getRequest(); + + if ($request->query->has('id')) { + $request->query->remove('id'); + } + + $params = array_merge( + $this->defaultLoopArgs, + $request->query->all() + ); + + try { + $results = $this->getLoopResults($params); + } catch (\Exception $e) { + throw new HttpException(500, json_encode(["error" => $e->getMessage()])); + } + + return JsonResponse::create($results); + } + + /** + * @param $entityId + * @return \Symfony\Component\HttpFoundation\Response + * + * This method provides the "GET" feed for an entity, + * you can define a route like this: + * + * + * Thelia:Api\MyEntity:get + * \d+ + * + */ + public function getAction($entityId) + { + $this->checkAuth($this->resources, $this->modules, AccessManager::VIEW); + $request = $this->getRequest(); + + $params = array_merge( + $request->query->all(), + [ + $this->idParameterName => $entityId, + ] + ); + + $result = $this->getLoopResults($params); + + if ($result->isEmpty()) { + $this->entityNotFound($entityId); + } + + return JsonResponse::create($result); + } + + /** + * @return JsonResponse + * + * This feed creates your entity. + */ + public function createAction() + { + $this->checkAuth($this->resources, $this->modules, AccessManager::CREATE); + + $baseForm = $this->getCreationForm(); + + $con = Propel::getConnection(); + $con->beginTransaction(); + + try { + $form = $this->validateForm($baseForm); + $data = $form->getData(); + + $event = $this->getCreationEvent($data); + + $dispatcher = $this->getDispatcher(); + foreach ($this->createEvents as $eventName) { + $dispatcher->dispatch($eventName, $event); + } + + $this->afterCreateEvents($event, $data); + + $con->commit(); + } catch (HttpException $e) { + $con->rollBack(); + + return new JsonResponse(["error" => $e->getMessage()], $e->getStatusCode()); + } catch (\Exception $e) { + $con->rollBack(); + + return new JsonResponse(["error" => $e->getMessage()], 500); + } + + $obj = $this->extractObjectFromEvent($event); + $id = $this->extractIdFromObject($obj); + + return new JsonResponse( + $this->getLoopResults( + array_merge( + $this->getRequest()->query->all(), + [$this->idParameterName => $id] + ) + ), + 201 + ); + } + + /** + * @return JsonResponse + * + * Generic action to update an entity + */ + public function updateAction() + { + $this->checkAuth($this->resources, $this->modules, AccessManager::UPDATE); + + $baseForm = $this->getUpdateForm(); + + $baseForm->getFormBuilder() + ->addEventListener( + FormEvents::PRE_SUBMIT, + [$this, "hydrateUpdateForm"] + ) + ; + + $con = Propel::getConnection(); + $con->beginTransaction(); + + try { + $form = $this->validateForm($baseForm); + $data = $form->getData(); + $event = $this->getUpdateEvent($data); + + $dispatcher = $this->getDispatcher(); + foreach ($this->updateEvents as $eventName) { + $dispatcher->dispatch($eventName, $event); + } + + $this->afterUpdateEvents($event, $data); + + $con->commit(); + } catch (HttpException $e) { + $con->rollBack(); + + return new JsonResponse(["error" => $e->getMessage()], $e->getStatusCode()); + } catch (\Exception $e) { + $con->rollBack(); + + return new JsonResponse(["error" => $e->getMessage()], 500); + } + + $obj = $this->extractObjectFromEvent($event); + $id = $this->extractIdFromObject($obj); + + return new JsonResponse( + $this->getLoopResults( + array_merge( + $this->getRequest()->query->all(), + [$this->idParameterName => $id] + ) + ), + 201 + ); + } + + /** + * @param $entityId + * @return JsonResponse|\Thelia\Core\HttpFoundation\Response + * + * generic feed for deleting an entity + */ + public function deleteAction($entityId) + { + $this->checkAuth($this->resources, $this->modules, AccessManager::DELETE); + + $con = Propel::getConnection(); + $con->beginTransaction(); + + try { + $event = $this->getDeleteEvent($entityId); + + $obj = $this->extractObjectFromEvent($event); + + if (null === $obj || false === $obj) { + $this->entityNotFound($entityId); + } + + $dispatcher = $this->getDispatcher(); + foreach ($this->deleteEvents as $eventName) { + $dispatcher->dispatch($eventName, $event); + } + + $con->commit(); + } catch (HttpException $e) { + $con->rollBack(); + + return new JsonResponse(["error" => $e->getMessage()], $e->getStatusCode()); + } catch (\Exception $e) { + $con->rollBack(); + + return new JsonResponse(["error" => $e->getMessage()], 500); + } + + return $this->nullResponse(204); + } + + /** + * @param $loopParams + * @return \Thelia\Core\Template\Element\LoopResult + * + * Returns the current class' loop results with the given parameters + */ + protected function getLoopResults($loopParams) + { + $loop = $this->getLoop(); + $loop->initializeArgs( + array_merge($this->defaultLoopArgs, $loopParams) + ); + + return $loop->exec($pagination); + } + + // Helpers + + /** + * @param $entityId + * + * Throws a 404 exception building an error message with $this->objName and the entity id + */ + protected function entityNotFound($entityId) + { + throw new NotFoundHttpException( + json_encode([ + "error" => sprintf("%s %s %d not found", $this->objName, $this->idParameterName, $entityId) + ]) + ); + } + + /** + * @param $eventsDefinition + * + * Register events into the class' variables + */ + protected function initializeEvents($eventsDefinition) + { + foreach ($eventsDefinition as $variableName => $eventValue) { + $value = array(); + + if (!empty($eventValue) && !\is_array($eventValue)) { + $value = [$eventValue]; + } elseif (\is_array($eventValue)) { + $value = $eventValue; + } + + $this->$variableName = $value; + } + } + + /** + * @param $locale + * @param string $parameterName + * + * This helper defines the lang into the query ( you can use it to force a lang into a loop ) + */ + protected function setLocaleIntoQuery($locale, $parameterName = 'lang') + { + $request = $this->getRequest(); + if (!$request->query->has($parameterName)) { + $request->query->set($parameterName, $locale); + } + } + + // Inner logic, override those methods to use your logic + + /** + * @param mixed $obj + * @return mixed + * + * After having extracted the object, now extract the id. + */ + protected function extractIdFromObject($obj) + { + return $obj->getId(); + } + + /** + * @param FormEvent $event + * + * This method in called on your update form FormEvents::PRE_SUBMIT event. + * + * You can treat the given form, rewrite some data ... + */ + public function hydrateUpdateForm(FormEvent $event) + { + // This method is called on FormEvents::PRE_SUBMIT + } + + /** + * @param Event $event + * @param array $data + * + * Hook after the entity creation + */ + protected function afterCreateEvents(Event $event, array &$data) + { + // This method is called after dispatches in createAction + } + + /** + * @param Event $event + * @param array $data + * + * Hook after the entity update + */ + protected function afterUpdateEvents(Event $event, array &$data) + { + // This method is called after dispatches in updateAction + } + + // Abstract methods + + /** + * @return \Thelia\Core\Template\Element\BaseLoop + * + * Get the entity loop instance + */ + abstract protected function getLoop(); + + /** + * @param array $data + * @return \Thelia\Form\BaseForm + * + * Gives the form used for entities creation. + */ + abstract protected function getCreationForm(array $data = array()); + + /** + * @param array $data + * @return \Thelia\Form\BaseForm + * + * Gives the form used for entities update + */ + abstract protected function getUpdateForm(array $data = array()); + + /** + * @param Event $event + * @return null|mixed + * + * Get the object from the event + * + * if return null or false, the action will throw a 404 + */ + abstract protected function extractObjectFromEvent(Event $event); + + /** + * @param array $data + * @return \Symfony\Component\EventDispatcher\Event + * + * Hydrates an event object to dispatch on creation. + */ + abstract protected function getCreationEvent(array &$data); + + + /** + * @param array $data + * @return \Symfony\Component\EventDispatcher\Event + * + * Hydrates an event object to dispatch on update. + */ + abstract protected function getUpdateEvent(array &$data); + + /** + * @param mixed $entityId + * @return \Symfony\Component\EventDispatcher\Event + * + * Hydrates an event object to dispatch on entity deletion. + */ + abstract protected function getDeleteEvent($entityId); +} diff --git a/core/lib/Thelia/Controller/Api/AttributeAvController.php b/core/lib/Thelia/Controller/Api/AttributeAvController.php new file mode 100644 index 00000000..3d90a8ed --- /dev/null +++ b/core/lib/Thelia/Controller/Api/AttributeAvController.php @@ -0,0 +1,112 @@ + + */ +class AttributeAvController extends AbstractCrudApiController +{ + public function __construct() + { + parent::__construct( + "attribute av", + AdminResources::ATTRIBUTE, + [], + [], + [] + ); + } + + /** + * @return \Thelia\Core\Template\Element\BaseLoop + * + * Get the entity loop instance + */ + protected function getLoop() + { + return new AttributeAvailability($this->container); + } + + /** + * @TODO: Implement Create - Update - Delete + */ + + /** + * @param array $data + * @return \Thelia\Form\BaseForm + * + * Gives the form used for entities creation. + */ + protected function getCreationForm(array $data = array()) + { + } + + /** + * @param array $data + * @return \Thelia\Form\BaseForm + * + * Gives the form used for entities update + */ + protected function getUpdateForm(array $data = array()) + { + } + + /** + * @param Event $event + * @return null|mixed + * + * Get the object from the event + * + * if return null or false, the action will throw a 404 + */ + protected function extractObjectFromEvent(Event $event) + { + } + + /** + * @param array $data + * @return \Symfony\Component\EventDispatcher\Event + * + * Hydrates an event object to dispatch on creation. + */ + protected function getCreationEvent(array &$data) + { + } + + /** + * @param array $data + * @return \Symfony\Component\EventDispatcher\Event + * + * Hydrates an event object to dispatch on update. + */ + protected function getUpdateEvent(array &$data) + { + } + + /** + * @param mixed $entityId + * @return \Symfony\Component\EventDispatcher\Event + * + * Hydrates an event object to dispatch on entity deletion. + */ + protected function getDeleteEvent($entityId) + { + } +} diff --git a/core/lib/Thelia/Controller/Api/BaseApiController.php b/core/lib/Thelia/Controller/Api/BaseApiController.php new file mode 100644 index 00000000..67d48223 --- /dev/null +++ b/core/lib/Thelia/Controller/Api/BaseApiController.php @@ -0,0 +1,125 @@ + + */ +class BaseApiController extends BaseController +{ + const CONTROLLER_TYPE = 'api'; + + const EMPTY_FORM_NAME = "thelia.api.empty"; + + protected $apiUser; + protected $currentRouter = "router.api"; + + protected function checkAuth($resources, $modules, $accesses) + { + $resources = \is_array($resources) ? $resources : array($resources); + $modules = \is_array($modules) ? $modules : array($modules); + $accesses = \is_array($accesses) ? $accesses : array($accesses); + + if (true !== $this->getSecurityContext()->isUserGranted(array("API"), $resources, $modules, $accesses, $this->getApiUser())) { + throw new AccessDeniedHttpException(); + } + } + + public function setApiUser(Api $apiUser) + { + $this->apiUser = $apiUser; + } + + public function getApiUser() + { + return $this->apiUser; + } + + /** + * @param null|mixed $template + * @return a ParserInterface instance parser + */ + protected function getParser($template = null) + { + throw new \RuntimeException("The parser is not available in an API controller"); + } + + /** + * Render the given template, and returns the result as an Http Response. + * + * @param mixed $content the response content + * @param array $args the template arguments + * @param int $status http code status + * @param array $headers The HTTP headers of the response + * @return \Thelia\Core\HttpFoundation\Response + */ + protected function render($content, $args = array(), $status = 200, $headers = array()) + { + return Response::create($this->renderRaw($content), $status, $headers); + } + + /** + * Render the given template, and returns the result as a string. + * + * @param $content + * @param array $args the template arguments + * @param null $templateDir + * + * @return string + */ + protected function renderRaw($content, $args = array(), $templateDir = null) + { + if (\is_array($content)) { + $content = json_encode($content); + } + + return $content; + } + + /** + * @param $name + * @param string $type + * @param array $data + * @param array $options + * @return \Thelia\Form\BaseForm + * + * Deactivate csrf token by default on API + */ + public function createForm($name, $type = "form", array $data = array(), array $options = array()) + { + $options = array_merge( + [ + "csrf_protection" => false, + ], + $options + ); + + return parent::createForm($name, $type, $data, $options); + } + + /** + * @return string + */ + public function getControllerType() + { + return self::CONTROLLER_TYPE; + } +} diff --git a/core/lib/Thelia/Controller/Api/BrandController.php b/core/lib/Thelia/Controller/Api/BrandController.php new file mode 100644 index 00000000..cb664a0c --- /dev/null +++ b/core/lib/Thelia/Controller/Api/BrandController.php @@ -0,0 +1,112 @@ + + */ +class BrandController extends AbstractCrudApiController +{ + public function __construct() + { + parent::__construct( + "brand", + AdminResources::BRAND, + [], + [], + [] + ); + } + + /** + * @return \Thelia\Core\Template\Element\BaseLoop + * + * Get the entity loop instance + */ + protected function getLoop() + { + return new Brand($this->container); + } + + /** + * @TODO: Implement Create - Update - Delete + */ + + /** + * @param array $data + * @return \Thelia\Form\BaseForm + * + * Gives the form used for entities creation. + */ + protected function getCreationForm(array $data = array()) + { + } + + /** + * @param array $data + * @return \Thelia\Form\BaseForm + * + * Gives the form used for entities update + */ + protected function getUpdateForm(array $data = array()) + { + } + + /** + * @param Event $event + * @return null|mixed + * + * Get the object from the event + * + * if return null or false, the action will throw a 404 + */ + protected function extractObjectFromEvent(Event $event) + { + } + + /** + * @param array $data + * @return \Symfony\Component\EventDispatcher\Event + * + * Hydrates an event object to dispatch on creation. + */ + protected function getCreationEvent(array &$data) + { + } + + /** + * @param array $data + * @return \Symfony\Component\EventDispatcher\Event + * + * Hydrates an event object to dispatch on update. + */ + protected function getUpdateEvent(array &$data) + { + } + + /** + * @param mixed $entityId + * @return \Symfony\Component\EventDispatcher\Event + * + * Hydrates an event object to dispatch on entity deletion. + */ + protected function getDeleteEvent($entityId) + { + } +} diff --git a/core/lib/Thelia/Controller/Api/CategoryController.php b/core/lib/Thelia/Controller/Api/CategoryController.php new file mode 100644 index 00000000..cf9e02c9 --- /dev/null +++ b/core/lib/Thelia/Controller/Api/CategoryController.php @@ -0,0 +1,152 @@ + + */ +class CategoryController extends AbstractCrudApiController +{ + public function __construct() + { + parent::__construct( + "category", + AdminResources::CATEGORY, + TheliaEvents::CATEGORY_CREATE, + TheliaEvents::CATEGORY_UPDATE, + TheliaEvents::CATEGORY_DELETE + ); + } + + /** + * @return \Thelia\Core\Template\Element\BaseLoop + * + * Get the entity loop instance + */ + protected function getLoop() + { + return new Category($this->container); + } + + /** + * @param array $data + * @return \Thelia\Form\BaseForm + */ + protected function getCreationForm(array $data = array()) + { + return $this->createForm(ApiForm::CATEGORY_CREATION, "form", $data); + } + + /** + * @param array $data + * @return \Thelia\Form\BaseForm + */ + protected function getUpdateForm(array $data = array()) + { + return $this->createForm(ApiForm::CATEGORY_MODIFICATION, "form", $data, [ + 'method' => 'PUT', + ]); + } + + /** + * @param Event $event + * @return null|mixed + * + * Get the object from the event + * + * if return null or false, the action will throw a 404 + */ + protected function extractObjectFromEvent(Event $event) + { + return $event->getCategory(); + } + + + /** + * @param array $data + * @return \Symfony\Component\EventDispatcher\Event + */ + protected function getCreationEvent(array &$data) + { + $event = new CategoryCreateEvent(); + + $event + ->setLocale($data['locale']) + ->setTitle($data['title']) + ->setVisible($data['visible']) + ->setParent($data['parent']) + ; + + $this->setLocaleIntoQuery($data["locale"]); + + return $event; + } + + /** + * @param array $data + * @return \Symfony\Component\EventDispatcher\Event + */ + protected function getUpdateEvent(array &$data) + { + $event = new CategoryUpdateEvent($data["id"]); + + $event + ->setLocale($data['locale']) + ->setParent($data['parent']) + ->setTitle($data['title']) + ->setVisible($data['visible']) + ->setChapo($data['chapo']) + ->setDescription($data['description']) + ->setPostscriptum($data['postscriptum']) + ->setDefaultTemplateId($data['default_template_id']) + ; + + $this->setLocaleIntoQuery($data["locale"]); + + return $event; + } + + /** + * @param mixed $entityId + * @return \Symfony\Component\EventDispatcher\Event + */ + protected function getDeleteEvent($entityId) + { + $event = new CategoryDeleteEvent($entityId); + $event->setCategory(CategoryQuery::create()->findPk($entityId)); + + return $event; + } + + public function hydrateUpdateForm(FormEvent $event) + { + $id = $event->getData()["id"]; + + if (null === CategoryQuery::create()->findPk($id)) { + $this->entityNotFound($id); + } + } +} diff --git a/core/lib/Thelia/Controller/Api/CountryController.php b/core/lib/Thelia/Controller/Api/CountryController.php new file mode 100644 index 00000000..fe334535 --- /dev/null +++ b/core/lib/Thelia/Controller/Api/CountryController.php @@ -0,0 +1,112 @@ + + */ +class CountryController extends AbstractCrudApiController +{ + public function __construct() + { + parent::__construct( + "country", + AdminResources::COUNTRY, + [], + [], + [] + ); + } + + /** + * @return \Thelia\Core\Template\Element\BaseLoop + * + * Get the entity loop instance + */ + protected function getLoop() + { + return new Country($this->container); + } + + /** + * @TODO: implement Create - Update - Delete + */ + + /** + * @param array $data + * @return \Thelia\Form\BaseForm + * + * Gives the form used for entities creation. + */ + protected function getCreationForm(array $data = array()) + { + } + + /** + * @param array $data + * @return \Thelia\Form\BaseForm + * + * Gives the form used for entities update + */ + protected function getUpdateForm(array $data = array()) + { + } + + /** + * @param Event $event + * @return null|mixed + * + * Get the object from the event + * + * if return null or false, the action will throw a 404 + */ + protected function extractObjectFromEvent(Event $event) + { + } + + /** + * @param array $data + * @return \Symfony\Component\EventDispatcher\Event + * + * Hydrates an event object to dispatch on creation. + */ + protected function getCreationEvent(array &$data) + { + } + + /** + * @param array $data + * @return \Symfony\Component\EventDispatcher\Event + * + * Hydrates an event object to dispatch on update. + */ + protected function getUpdateEvent(array &$data) + { + } + + /** + * @param mixed $entityId + * @return \Symfony\Component\EventDispatcher\Event + * + * Hydrates an event object to dispatch on entity deletion. + */ + protected function getDeleteEvent($entityId) + { + } +} diff --git a/core/lib/Thelia/Controller/Api/CurrencyController.php b/core/lib/Thelia/Controller/Api/CurrencyController.php new file mode 100644 index 00000000..6cc16cd3 --- /dev/null +++ b/core/lib/Thelia/Controller/Api/CurrencyController.php @@ -0,0 +1,112 @@ + + */ +class CurrencyController extends AbstractCrudApiController +{ + public function __construct() + { + parent::__construct( + "currency", + AdminResources::CURRENCY, + [], + [], + [] + ); + } + + /** + * @return \Thelia\Core\Template\Element\BaseLoop + * + * Get the entity loop instance + */ + protected function getLoop() + { + return new Currency($this->container); + } + + /** + * @TODO: Implement Create - Update - Delete + */ + + /** + * @param array $data + * @return \Thelia\Form\BaseForm + * + * Gives the form used for entities creation. + */ + protected function getCreationForm(array $data = array()) + { + } + + /** + * @param array $data + * @return \Thelia\Form\BaseForm + * + * Gives the form used for entities update + */ + protected function getUpdateForm(array $data = array()) + { + } + + /** + * @param Event $event + * @return null|mixed + * + * Get the object from the event + * + * if return null or false, the action will throw a 404 + */ + protected function extractObjectFromEvent(Event $event) + { + } + + /** + * @param array $data + * @return \Symfony\Component\EventDispatcher\Event + * + * Hydrates an event object to dispatch on creation. + */ + protected function getCreationEvent(array &$data) + { + } + + /** + * @param array $data + * @return \Symfony\Component\EventDispatcher\Event + * + * Hydrates an event object to dispatch on update. + */ + protected function getUpdateEvent(array &$data) + { + } + + /** + * @param mixed $entityId + * @return \Symfony\Component\EventDispatcher\Event + * + * Hydrates an event object to dispatch on entity deletion. + */ + protected function getDeleteEvent($entityId) + { + } +} diff --git a/core/lib/Thelia/Controller/Api/CustomerController.php b/core/lib/Thelia/Controller/Api/CustomerController.php new file mode 100644 index 00000000..2e7ac4dd --- /dev/null +++ b/core/lib/Thelia/Controller/Api/CustomerController.php @@ -0,0 +1,216 @@ + + * @author Benjamin Perche + */ +class CustomerController extends AbstractCrudApiController +{ + public function __construct() + { + parent::__construct( + "customer", + AdminResources::CUSTOMER, + TheliaEvents::CUSTOMER_CREATEACCOUNT, + TheliaEvents::CUSTOMER_UPDATEACCOUNT, + TheliaEvents::CUSTOMER_DELETEACCOUNT, + [], + [ + "limit" => 10, + "offset" => 0, + "current" => false, + ] + ); + } + + + /** + * @return \Thelia\Core\Template\Element\BaseLoop + * + * Get the entity loop instance + */ + protected function getLoop() + { + return new Customer($this->container); + } + + /** + * @param array $data + * @return \Thelia\Form\BaseForm + */ + protected function getCreationForm(array $data = array()) + { + return $this->createForm(ApiForm::CUSTOMER_CREATE); + } + + /** + * @param array $data + * @return \Thelia\Form\BaseForm + */ + protected function getUpdateForm(array $data = array()) + { + return $this->createForm( + ApiForm::CUSTOMER_UPDATE, + "form", + [], + ['method' => 'PUT'] + ); + } + + /** + * @param Event $event + * @return null|mixed + * + * Get the object from the event + * + * if return null or false, the action will throw a 404 + */ + protected function extractObjectFromEvent(Event $event) + { + return $event->getCustomer(); + } + + /** + * @param array $data + * @return \Symfony\Component\EventDispatcher\Event + */ + protected function getCreationEvent(array &$data) + { + return $this->hydrateEvent($data); + } + + /** + * @param array $data + * @return \Symfony\Component\EventDispatcher\Event + */ + protected function getUpdateEvent(array &$data) + { + return $this->hydrateEvent($data); + } + + /** + * @param mixed $entityId + * @return \Symfony\Component\EventDispatcher\Event + */ + protected function getDeleteEvent($entityId) + { + $customer = CustomerQuery::create()->findPk($entityId); + + if (null === $customer) { + throw new HttpException(404, sprintf('{"error": "customer with id %d not found"}', $entityId)); + } + + return new CustomerEvent($customer); + } + + protected function hydrateEvent(array $data) + { + $customerCreateEvent = new CustomerCreateOrUpdateEvent( + $data['title'], + $data['firstname'], + $data['lastname'], + $data['address1'], + $data['address2'], + $data['address3'], + $data['phone'], + $data['cellphone'], + $data['zipcode'], + $data['city'], + $data['country'], + $data['email'], + $data['password'], + $data['lang_id'], + isset($data["reseller"]) ? $data["reseller"] : null, + isset($data["sponsor"]) ? $data["sponsor"] : null, + isset($data["discount"]) ? $data["discount"] : null, + $data['company'], + null + ); + + if (isset($data["id"])) { + $customerCreateEvent->setCustomer(CustomerQuery::create()->findPk($data["id"])); + } + + return $customerCreateEvent; + } + + public function deleteAction($entityId) + { + $query = CustomerQuery::create() + ->joinOrder() + ->filterById($entityId) + ->findOne() + ; + + if (null !== $query) { + throw new HttpException(403, json_encode([ + "error" => sprintf("You can't delete the customer %d as he has orders", $entityId), + ])); + } + + return parent::deleteAction($entityId); + } + + /** + * @return \Symfony\Component\HttpFoundation\Response|JsonResponse + * + * Get a customer given its email and password. + * @author Baptiste Cabarrou + */ + public function checkLoginAction() + { + $this->checkAuth($this->resources, $this->modules, AccessManager::VIEW); + + $request = $this->getRequest(); + $customerLoginForm = $this->createForm(ApiForm::CUSTOMER_LOGIN); + + try { + $this->validateForm($customerLoginForm, "post"); + + $authenticator = new CustomerUsernamePasswordFormAuthenticator($request, $customerLoginForm); + /** @var UserInterface $customer */ + $customer = $authenticator->getAuthentifiedUser(); + + return $this->getAction($customer->getId()); + } catch (UsernameNotFoundException $e) { + return new JsonResponse(["error" => $e->getMessage()], 404); + } catch (WrongPasswordException $e) { + return new JsonResponse(["error" => $e->getMessage()], 404); + } catch (HttpException $e) { + return new JsonResponse(["error" => $e->getMessage()], $e->getStatusCode()); + } catch (\Exception $e) { + return new JsonResponse(["error" => $e->getMessage()], 500); + } + } +} diff --git a/core/lib/Thelia/Controller/Api/ImageController.php b/core/lib/Thelia/Controller/Api/ImageController.php new file mode 100644 index 00000000..5742fc40 --- /dev/null +++ b/core/lib/Thelia/Controller/Api/ImageController.php @@ -0,0 +1,374 @@ + + */ +class ImageController extends BaseApiController +{ + /** + * @param integer $entityId source's primary key (product's pk, category's pk, etc) + * @return \Symfony\Component\HttpFoundation\Response + */ + public function listAction($entityId) + { + $request = $this->getRequest(); + + $entity = $request->attributes->get('entity'); + + $this->checkAuth($this->getAdminResources()->getResource($entity), [], AccessManager::VIEW); + + $this->checkEntityExists($entity, $entityId); + + if ($request->query->has('id')) { + $request->query->remove('id'); + } + + $params = array_merge( + [ + 'limit' => 10, + 'offset' => 0, + ], + $request->query->all(), + [ + 'source' => strtolower($entity), + 'source_id' => $entityId + ] + ); + + $imageLoop = new Image($this->getContainer()); + $imageLoop->initializeArgs($params); + + return JsonResponse::create($imageLoop->exec($paginate)); + } + + public function getImageAction($entityId, $imageId) + { + $request = $this->getRequest(); + + $entity = $request->attributes->get('entity'); + + $this->checkAuth($this->getAdminResources()->getResource($entity), [], AccessManager::VIEW); + + $this->checkEntityExists($entity, $entityId); + + $params = array_merge( + $request->query->all(), + [ + 'source' => strtolower($entity), + 'source_id' => $entityId, + 'id' => $imageId + ] + ); + + $imageLoop = new Image($this->getContainer()); + $imageLoop->initializeArgs($params); + + $results = $imageLoop->exec($paginate); + + if ($results->isEmpty()) { + return JsonResponse::create( + array( + 'error' => sprintf('image with id %d not found', $imageId) + ), + 404 + ); + } + + return JsonResponse::create($results); + } + + public function createImageAction($entityId) + { + $request = $this->getRequest(); + + $entity = $request->attributes->get('entity'); + + $this->checkAuth($this->getAdminResources()->getResource($entity), [], AccessManager::UPDATE); + + $fileController = new FileController(); + $fileController->setContainer($this->getContainer()); + + $config = FileConfiguration::getImageConfig(); + $files = $request->files->all(); + + $errors = null; + + foreach ($files as $file) { + $errors = $this->processImage($fileController, $file, $entityId, $entity, $config); + } + + if (!empty($errors)) { + $response = JsonResponse::create($errors, 500); + } else { + $response = $this->listAction($entityId); + $response->setStatusCode(201); + } + + return $response; + } + + public function updateImageAction($entityId, $imageId) + { + $request = $this->getRequest(); + $entity = $request->attributes->get('entity'); + + $this->checkAuth($this->getAdminResources()->getResource($entity), [], AccessManager::UPDATE); + + $this->checkEntityExists($entity, $entityId); + $this->checkImage($entity, $imageId); + + /** + * If there is a file, treat it + */ + $hasImage = $request->files->count() == 1; + + if ($hasImage) { + $this->processImageUpdate($entityId, $entity); + } + + /** + * Then treat i18n form + */ + + $baseForm = $this->createForm(null, "image", [], array( + "csrf_protection" => false, + "method" => "PUT", + )); + + $baseForm->getFormBuilder() + ->addEventListener( + FormEvents::PRE_SUBMIT, + function (FormEvent $event) use ($entity, $imageId) { + $this->onFormPreSubmit($event, $imageId, $entity); + } + ) + ; + + $con = Propel::getConnection(); + $con->beginTransaction(); + + try { + $form = $this->validateForm($baseForm); + $image = $this->checkImage($entity, $imageId); + + foreach ($form->getData()["i18n"] as $locale => $i18nRow) { + $image->getTranslation($locale) + ->setTitle($i18nRow["title"]) + ->setChapo($i18nRow["chapo"]) + ->setDescription($i18nRow["description"]) + ->setPostscriptum($i18nRow["postscriptum"]) + ; + } + + $image->save(); + $con->commit(); + } catch (\Exception $e) { + $con->rollBack(); + + if (!$hasImage) { + throw new HttpException(500, $e->getMessage()); + } + } + + return $this->getImageAction($entityId, $imageId)->setStatusCode(201); + } + + protected function onFormPreSubmit(FormEvent $event, $entityId, $entity) + { + $data = $event->getData(); + $temporaryRegister = array(); + + foreach ($data["i18n"] as $key => &$value) { + $temporaryRegister["i18n"][$value["locale"]] = $value; + + unset($data["i18n"][$key]); + } + + $data = $temporaryRegister; + + $i18ns = $this->getImageI18ns($entity, $entityId); + + foreach ($i18ns as $i18n) { + $row = array( + "locale" => $i18n->getLocale(), + "title" => $i18n->getTitle(), + "chapo" => $i18n->getChapo(), + "description" => $i18n->getDescription(), + "postscriptum" => $i18n->getPostscriptum(), + ); + + if (!isset($data["i18n"][$i18n->getLocale()])) { + $data["i18n"][$i18n->getLocale()] = array(); + } + + $data["i18n"][$i18n->getLocale()] = array_merge( + $row, + $data["i18n"][$i18n->getLocale()] + ); + } + + $event->setData($data); + } + + protected function processImageUpdate($entityId, $entity) + { + $file = $this->getRequest()->files->all(); + reset($file); + $file = current($file); + + $fileController = new FileController(); + $fileController->setContainer($this->getContainer()); + + $config = FileConfiguration::getImageConfig(); + + $errors = $this->processImage($fileController, $file, $entityId, $entity, $config); + + if (!empty($errors)) { + throw new HttpException(500, json_encode($errors), null, ["Content-Type" => "application/json"]); + } + } + + protected function processImage(FileController $fileController, $file, $entityId, $entity, array $config) + { + try { + $fileController->processImage( + $file, + $entityId, + $entity, + $config['objectType'], + $config['validMimeTypes'], + $config['extBlackList'] + ); + } catch (\Exception $e) { + return [ + 'file' => $file->getClientOriginalName(), + 'message' => $e->getMessage(), + ]; + } + + return null; + } + + public function deleteImageAction($entityId, $imageId) + { + $request = $this->getRequest(); + + $entity = $request->attributes->get('entity'); + + $this->checkAuth($this->getAdminResources()->getResource($entity), [], AccessManager::UPDATE); + + $this->checkEntityExists($entity, $entityId); + + $entityModel = $this->checkImage($entity, $imageId); + + if (null === $entityModel) { + throw new HttpException(404, sprintf('{"error": "image with id %d not found"}', $imageId)); + } + + try { + $fileDeleteEvent = new FileDeleteEvent($entityModel); + $this->dispatch(TheliaEvents::IMAGE_DELETE, $fileDeleteEvent); + return Response::create('', 204); + } catch (\Exception $e) { + return JsonResponse::create(['error' => $e->getMessage()], 500); + } + } + + /** + * @param string $entity image's source (eg : Product, Category, etc) + * @param int $entityId source's primary key + */ + protected function checkEntityExists($entity, $entityId) + { + $entity = ucfirst($entity); + + $class = sprintf("Thelia\\Model\\%sQuery", $entity); + + $method = new \ReflectionMethod($class, 'create'); + $search = $method->invoke(null); + + $entityModel = $search->findPk($entityId); + + if (null === $entityModel) { + throw new HttpException( + 404, + sprintf('{"error": "%s with id %d not found"}', $entity, $entityId), + null, + ["Content-Type" => "application/json"] + ); + } + + return $entityModel; + } + + /** + * @param $entity + * @param $imageId + * @return \Thelia\Files\FileModelInterface + */ + protected function checkImage($entity, $imageId) + { + $class = sprintf("Thelia\\Model\\%sImageQuery", ucfirst($entity)); + + $method = new \ReflectionMethod($class, 'create'); + $search = $method->invoke(null); + + $imageModel = $search->findPk($imageId); + + if (null === $imageModel) { + throw new HttpException( + 404, + sprintf('{"error": "image with id %d not found"}', $imageId), + null, + ["Content-Type" => "application/json"] + ); + } + + return $imageModel; + } + + /** + * @param $entity + * @param $imageId + * @return \Propel\Runtime\Collection\ObjectCollection + */ + protected function getImageI18ns($entity, $imageId) + { + $class = sprintf("Thelia\\Model\\%sImageI18nQuery", ucfirst($entity)); + + $method = new \ReflectionMethod($class, 'create'); + $search = $method->invoke(null); + + $search->orderByLocale(); + + return $search->findById($imageId); + } +} diff --git a/core/lib/Thelia/Controller/Api/IndexController.php b/core/lib/Thelia/Controller/Api/IndexController.php new file mode 100644 index 00000000..f27db8ff --- /dev/null +++ b/core/lib/Thelia/Controller/Api/IndexController.php @@ -0,0 +1,31 @@ + + */ +class IndexController extends BaseApiController +{ + public function indexAction() + { + return Response::create("OK"); + } +} diff --git a/core/lib/Thelia/Controller/Api/LangController.php b/core/lib/Thelia/Controller/Api/LangController.php new file mode 100644 index 00000000..f2101ee6 --- /dev/null +++ b/core/lib/Thelia/Controller/Api/LangController.php @@ -0,0 +1,112 @@ + + */ +class LangController extends AbstractCrudApiController +{ + public function __construct() + { + parent::__construct( + "lang", + AdminResources::LANGUAGE, + [], + [], + [] + ); + } + + /** + * @return \Thelia\Core\Template\Element\BaseLoop + * + * Get the entity loop instance + */ + protected function getLoop() + { + return new Lang($this->container); + } + + /** + * @TODO: Implement Create - Update - Delete + */ + + /** + * @param array $data + * @return \Thelia\Form\BaseForm + * + * Gives the form used for entities creation. + */ + protected function getCreationForm(array $data = array()) + { + } + + /** + * @param array $data + * @return \Thelia\Form\BaseForm + * + * Gives the form used for entities update + */ + protected function getUpdateForm(array $data = array()) + { + } + + /** + * @param Event $event + * @return null|mixed + * + * Get the object from the event + * + * if return null or false, the action will throw a 404 + */ + protected function extractObjectFromEvent(Event $event) + { + } + + /** + * @param array $data + * @return \Symfony\Component\EventDispatcher\Event + * + * Hydrates an event object to dispatch on creation. + */ + protected function getCreationEvent(array &$data) + { + } + + /** + * @param array $data + * @return \Symfony\Component\EventDispatcher\Event + * + * Hydrates an event object to dispatch on update. + */ + protected function getUpdateEvent(array &$data) + { + } + + /** + * @param mixed $entityId + * @return \Symfony\Component\EventDispatcher\Event + * + * Hydrates an event object to dispatch on entity deletion. + */ + protected function getDeleteEvent($entityId) + { + } +} diff --git a/core/lib/Thelia/Controller/Api/ProductController.php b/core/lib/Thelia/Controller/Api/ProductController.php new file mode 100644 index 00000000..dfbe406e --- /dev/null +++ b/core/lib/Thelia/Controller/Api/ProductController.php @@ -0,0 +1,189 @@ + + */ +class ProductController extends BaseApiController +{ + public function listAction() + { + $this->checkAuth(AdminResources::PRODUCT, [], AccessManager::VIEW); + $request = $this->getRequest(); + + if ($request->query->has('id')) { + $request->query->remove('id'); + } + + $params = array_merge( + $request->query->all(), + [ + 'limit' => $request->query->get('limit', 10), + 'offset' => $request->query->get('offset', 0) + ] + ); + + return JsonResponse::create($this->baseProductSearch($params)); + } + + public function getProductAction($productId) + { + $this->checkAuth(AdminResources::PRODUCT, [], AccessManager::VIEW); + $request = $this->getRequest(); + + $params = array_merge( + $request->query->all(), + ['id' => $productId] + ); + + $results = $this->baseProductSearch($params); + + if ($results->isEmpty()) { + return JsonResponse::create( + array( + 'error' => sprintf('product with id %d not found', $productId) + ), + 404 + ); + } + + return JsonResponse::create($results); + } + + private function baseProductSearch($params) + { + $productLoop = new Product($this->getContainer()); + $productLoop->initializeArgs($params); + + return $productLoop->exec($paginate); + } + + public function createAction() + { + $this->checkAuth(AdminResources::PRODUCT, [], AccessManager::CREATE); + + $form = $this->createForm(ApiForm::PRODUCT_CREATION, 'form', [], ['csrf_protection' => false]); + + try { + $creationForm = $this->validateForm($form); + + $event = new ProductCreateEvent(); + $event->bindForm($creationForm); + + $this->dispatch(TheliaEvents::PRODUCT_CREATE, $event); + + $product = $event->getProduct(); + + $updateEvent = new ProductUpdateEvent($product->getId()); + + $updateEvent->bindForm($creationForm); + + $this->dispatch(TheliaEvents::PRODUCT_UPDATE, $updateEvent); + + $this->getRequest()->query->set('lang', $creationForm->get('locale')->getData()); + $response = $this->getProductAction($product->getId()); + $response->setStatusCode(201); + + return $response; + } catch (\Exception $e) { + return JsonResponse::create(['error' => $e->getMessage()], 500); + } + } + + public function updateAction($productId) + { + $this->checkAuth(AdminResources::PRODUCT, [], AccessManager::UPDATE); + + $this->checkProductExists($productId); + + $form = $this->createForm( + ApiForm::PRODUCT_MODIFICATION, + 'form', + ['id' => $productId], + [ + 'csrf_protection' => false, + 'method' => 'PUT' + ] + ); + + $request = $this->getRequest(); + + $data = $request->request->all(); + $data['id'] = $productId; + $request->request->add($data); + + try { + $updateForm = $this->validateForm($form); + + $event = new ProductUpdateEvent($productId); + $event->bindForm($updateForm); + + $this->dispatch(TheliaEvents::PRODUCT_UPDATE, $event); + + return JsonResponse::create(null, 204); + } catch (\Exception $e) { + return JsonResponse::create(['error' => $e->getMessage()], 500); + } + } + + public function deleteAction($productId) + { + $this->checkAuth(AdminResources::PRODUCT, [], AccessManager::DELETE); + + $this->checkProductExists($productId); + + try { + $event = new ProductDeleteEvent($productId); + + $this->dispatch(TheliaEvents::PRODUCT_DELETE, $event); + return Response::create('', 204); + } catch (\Exception $e) { + return JsonResponse::create(['error' => $e->getMessage()], 500); + } + } + + /** + * @param $productId + * @throws \Symfony\Component\HttpKernel\Exception\HttpException + */ + protected function checkProductExists($productId) + { + $product = ProductQuery::create() + ->findPk($productId); + + if (null === $product) { + throw new HttpException(404, sprintf('{"error": "product with id %d not found"}', $productId), null, [ + "Content-Type" => "application/json" + ]); + } + } +} diff --git a/core/lib/Thelia/Controller/Api/ProductSaleElementsController.php b/core/lib/Thelia/Controller/Api/ProductSaleElementsController.php new file mode 100644 index 00000000..0c1468e1 --- /dev/null +++ b/core/lib/Thelia/Controller/Api/ProductSaleElementsController.php @@ -0,0 +1,467 @@ + + * + * API Controller for Product sale elements management + */ +class ProductSaleElementsController extends BaseApiController +{ + protected $product; + + /** + * Read actions + */ + + /** + * @param $productId + * @return JsonResponse + * + * List a product pses + */ + public function listAction($productId) + { + $this->checkAuth(AdminResources::PRODUCT, [], AccessManager::VIEW); + + if (null !== $response = $this->checkProduct($productId)) { + return $response; + } + + $request = $this->getRequest(); + + if ($request->query->has('id')) { + $request->query->remove('id'); + } + + $params = array_merge( + array( + "limit" => 10, + "offset" => 0, + ), + $request->query->all(), + array( + "product" => $productId, + ) + ); + + return new JsonResponse($this->getProductSaleElements($params)); + } + + /** + * @param $pseId + * @return JsonResponse + * + * Get a pse details + */ + public function getPseAction($pseId) + { + $this->checkAuth(AdminResources::PRODUCT, [], AccessManager::VIEW); + + $request = $this->getRequest(); + + $params = array_merge( + $request->query->all(), + [ + 'id' => $pseId, + ] + ); + + $results = $this->getProductSaleElements($params); + + if ($results->getCount() == 0) { + return new JsonResponse( + sprintf( + "The product sale elements id '%d' doesn't exist", + $pseId + ), + 404 + ); + } + + return new JsonResponse($results); + } + + /** + * Create action + */ + + /** + * @return JsonResponse + * + * Create product sale elements + */ + public function createAction() + { + $this->checkAuth(AdminResources::PRODUCT, [], AccessManager::CREATE); + + $baseForm = $this->createForm(ApiForm::PRODUCT_SALE_ELEMENTS, "form", [], [ + "validation_groups" => ["create", "Default"], + 'csrf_protection' => false, + "cascade_validation" => true, + ]); + + $con = Propel::getConnection(ProductSaleElementsTableMap::DATABASE_NAME); + $con->beginTransaction(); + + $createdIds = array(); + + try { + $form = $this->validateForm($baseForm); + + $entries = $form->getData(); + + foreach ($entries["pse"] as $entry) { + $createEvent = new ProductSaleElementCreateEvent( + ProductQuery::create()->findPk($entry["product_id"]), + $entry["attribute_av"], + $entry["currency_id"] + ); + + $createEvent->bindForm($form); + + $this->dispatch(TheliaEvents::PRODUCT_ADD_PRODUCT_SALE_ELEMENT, $createEvent); + + $this->processUpdateAction( + $entry, + $pse = $createEvent->getProductSaleElement(), + $createEvent->getProduct() + ); + + $createdIds[] = $pse->getId(); + } + + $con->commit(); + } catch (\Exception $e) { + $con->rollBack(); + + return new JsonResponse(["error" => $e->getMessage()], 500); + } + + return new JsonResponse( + $this->getProductSaleElements( + array_merge( + $this->getRequest()->query->all(), + ["id" => implode(",", $createdIds)] + ) + ), + 201 + ); + } + + /** + * @return JsonResponse + * + * Create product sale elements + */ + public function updateAction() + { + $this->checkAuth(AdminResources::PRODUCT, [], AccessManager::UPDATE); + + $baseForm = $this->createForm(ApiForm::PRODUCT_SALE_ELEMENTS, "form", [], [ + "validation_groups" => ["update", "Default"], + 'csrf_protection' => false, + "cascade_validation" => true, + "method" => "PUT", + ]); + + $baseForm->getFormBuilder() + ->addEventListener( + FormEvents::PRE_SUBMIT, + [$this, "loadProductSaleElements"], + 192 + ); + + $updatedId = array(); + + $con = Propel::getConnection(ProductSaleElementsTableMap::DATABASE_NAME); + $con->beginTransaction(); + + try { + $form = $this->validateForm($baseForm); + + $entries = $form->getData(); + + foreach ($entries["pse"] as $entry) { + $this->processUpdateAction( + $entry, + $pse = ProductSaleElementsQuery::create()->findPk($entry["id"]), + $pse->getProduct() + ); + + $updatedId[] = $pse->getId(); + } + + $con->commit(); + } catch (\Exception $e) { + $con->rollBack(); + + return new JsonResponse(["error" => $e->getMessage()], 500); + } + + return new JsonResponse( + $this->getProductSaleElements( + array_merge( + $this->getRequest()->query->all(), + [ + "id" => implode(",", $updatedId), + "limit" => \count($updatedId), + ] + ) + ), + 201 + ); + } + + /** + * Delete Action + */ + + /** + * @param $pseId + * @return JsonResponse|\Thelia\Core\HttpFoundation\Response + * + * Delete a pse + */ + public function deleteAction($pseId) + { + $this->checkAuth(AdminResources::PRODUCT, [], AccessManager::VIEW); + + $results = $this->getProductSaleElements([ + 'id' => $pseId + ]); + + if ($results->getCount() == 0) { + return new JsonResponse( + sprintf( + "The product sale elements id '%d' doesn't exist", + $pseId + ), + 404 + ); + } + + $event = new ProductSaleElementDeleteEvent($pseId, null); + + try { + $this->dispatch(TheliaEvents::PRODUCT_DELETE_PRODUCT_SALE_ELEMENT, $event); + } catch (\Exception $e) { + return new JsonResponse(array("error" => $e->getMessage()), 500); + } + + return $this->nullResponse(204); + } + + /** + * @param array $data + * @param ProductSaleElements $pse + * @param Product $product + * + * Process update on product sale elements values + */ + protected function processUpdateAction( + array $data, + ProductSaleElements $pse, + Product $product + ) { + list($price, $salePrice) = $this->extractPrices($data); + + $event = new ProductSaleElementUpdateEvent($product, $pse->getId()); + + $event + ->setWeight($data["weight"]) + ->setTaxRuleId($data["tax_rule_id"]) + ->setEanCode($data["ean_code"]) + ->setOnsale($data["onsale"]) + ->setReference($data["reference"]) + ->setIsdefault($data["isdefault"]) + ->setIsnew($data["isnew"]) + ->setCurrencyId($data["currency_id"]) + ->setPrice($price) + ->setSalePrice($salePrice) + ->setQuantity($data["quantity"]) + ->setFromDefaultCurrency($data["use_exchange_rate"]) + ; + + $this->dispatch(TheliaEvents::PRODUCT_UPDATE_PRODUCT_SALE_ELEMENT, $event); + } + + /** + * @param array $data + * @return array + * + * Return the untaxed prices to store + */ + protected function extractPrices(array $data) + { + $calculator = new Calculator(); + + $calculator->loadTaxRuleWithoutProduct( + TaxRuleQuery::create()->findPk($data["tax_rule_id"]), + Country::getShopLocation() + ); + + $price = null === $data["price_with_tax"] ? + $data["price"] : + $calculator->getUntaxedPrice($data["price_with_tax"]) + ; + + $salePrice = null === $data["sale_price_with_tax"] ? + $data["sale_price"] : + $calculator->getUntaxedPrice($data["sale_price_with_tax"]) + ; + + return [$price, $salePrice]; + } + + protected function retrievePrices(ProductSaleElements $pse) + { + $query = ProductPriceQuery::create() + ->useCurrencyQuery() + ->orderByByDefault() + ->endUse() + ; + + $prices = $pse->getProductPrices($query); + + if ($prices->count() === 0) { + return array(null, null, null, null); + } + + /** @var \Thelia\Model\ProductPrice $currentPrices */ + $currentPrices = $prices->get(0); + + return [ + $currentPrices->getPrice(), + $currentPrices->getPromoPrice(), + $currentPrices->getCurrencyId(), + $currentPrices->getFromDefaultCurrency() + ]; + } + + /** + * @param FormEvent $event + * + * Loads initial pse data into a form. + * It is used in for a form event on pse update + */ + public function loadProductSaleElements(FormEvent $event) + { + $productSaleElementIds = array(); + $data = array(); + + foreach ($event->getData()["pse"] as $entry) { + $productSaleElementIds[$entry["id"]] = $entry; + } + + $productSaleElements = ProductSaleElementsQuery::create() + ->findPks(array_keys($productSaleElementIds)) + ; + + /** @var ProductSaleElements $productSaleElement */ + foreach ($productSaleElements as $productSaleElement) { + $product = $productSaleElement->getProduct(); + + list($price, $salePrice, $currencyId, $fromDefaultCurrency) = $this->retrievePrices($productSaleElement); + + $data["pse"][$productSaleElement->getId()] = array_merge( + [ + "id" => $productSaleElement->getId(), + "reference" => $productSaleElement->getRef(), + "tax_rule_id" => $product->getTaxRuleId(), + "ean_code" => $productSaleElement->getEanCode(), + "onsale" => $productSaleElement->getPromo(), + "isdefault" => $productSaleElement->getIsDefault(), + "isnew" => $productSaleElement->getNewness(), + "quantity" => $productSaleElement->getQuantity(), + "weight" => $productSaleElement->getWeight(), + "price" => $price, + "sale_price" => $salePrice, + "currency_id" => $currencyId, + "use_exchange_rate" => $fromDefaultCurrency + ], + $productSaleElementIds[$productSaleElement->getId()] + ); + } + + $event->setData($data); + } + + /** + * @param $productId + * @return null|JsonResponse + * + * Checks if a productId exists + */ + protected function checkProduct($productId) + { + $this->product = ProductQuery::create() + ->findPk($productId) + ; + + if (null === $this->product) { + return new JsonResponse( + [ + "error" => sprintf( + "The product id '%d' doesn't exist", + $productId + ) + ], + 404 + ); + } + + return null; + } + + /** + * @param $params + * @return \Thelia\Core\Template\Element\LoopResult + * + * Return loop results for a product sale element + */ + protected function getProductSaleElements($params) + { + $loop = new ProductSaleElementsLoop($this->container); + $loop->initializeArgs($params); + + return $loop->exec($pagination); + } +} diff --git a/core/lib/Thelia/Controller/Api/TaxController.php b/core/lib/Thelia/Controller/Api/TaxController.php new file mode 100644 index 00000000..0c89c50c --- /dev/null +++ b/core/lib/Thelia/Controller/Api/TaxController.php @@ -0,0 +1,112 @@ + + */ +class TaxController extends AbstractCrudApiController +{ + public function __construct() + { + parent::__construct( + "tax", + AdminResources::TAX, + [], + [], + [] + ); + } + + /** + * @return \Thelia\Core\Template\Element\BaseLoop + * + * Get the entity loop instance + */ + protected function getLoop() + { + return new Tax($this->container); + } + + /** + * @TODO: implement Create - Update - Delete + */ + + /** + * @param array $data + * @return \Thelia\Form\BaseForm + * + * Gives the form used for entities creation. + */ + protected function getCreationForm(array $data = array()) + { + } + + /** + * @param array $data + * @return \Thelia\Form\BaseForm + * + * Gives the form used for entities update + */ + protected function getUpdateForm(array $data = array()) + { + } + + /** + * @param Event $event + * @return null|mixed + * + * Get the object from the event + * + * if return null or false, the action will throw a 404 + */ + protected function extractObjectFromEvent(Event $event) + { + } + + /** + * @param array $data + * @return \Symfony\Component\EventDispatcher\Event + * + * Hydrates an event object to dispatch on creation. + */ + protected function getCreationEvent(array &$data) + { + } + + /** + * @param array $data + * @return \Symfony\Component\EventDispatcher\Event + * + * Hydrates an event object to dispatch on update. + */ + protected function getUpdateEvent(array &$data) + { + } + + /** + * @param mixed $entityId + * @return \Symfony\Component\EventDispatcher\Event + * + * Hydrates an event object to dispatch on entity deletion. + */ + protected function getDeleteEvent($entityId) + { + } +} diff --git a/core/lib/Thelia/Controller/Api/TaxRuleController.php b/core/lib/Thelia/Controller/Api/TaxRuleController.php new file mode 100644 index 00000000..b37f5360 --- /dev/null +++ b/core/lib/Thelia/Controller/Api/TaxRuleController.php @@ -0,0 +1,257 @@ + + * @author manuel raynaud + */ +class TaxRuleController extends AbstractCrudApiController +{ + public function __construct() + { + parent::__construct( + "tax rule", + AdminResources::TAX, + [TheliaEvents::TAX_RULE_CREATE, TheliaEvents::TAX_RULE_TAXES_UPDATE], + [TheliaEvents::TAX_RULE_UPDATE, TheliaEvents::TAX_RULE_TAXES_UPDATE], + TheliaEvents::TAX_RULE_DELETE + ); + } + + + /** + * @return \Thelia\Core\Template\Element\BaseLoop + * + * Get the entity loop instance + */ + protected function getLoop() + { + return new TaxRule($this->container); + } + + /** + * @param array $data + * @return \Thelia\Form\BaseForm + */ + protected function getCreationForm(array $data = array()) + { + return $this->createForm(null, "tax_rule", $data); + } + + /** + * @param array $data + * @return \Thelia\Form\BaseForm + */ + protected function getUpdateForm(array $data = array()) + { + return $this->createForm(null, "tax_rule", $data, array( + "validation_groups" => ["Default", "update"], + "method" => "PUT", + )); + } + + /** + * @param Event $event + * @return null|mixed + * + * Get the object from the event + * + * if return null or false, the action will throw a 404 + */ + protected function extractObjectFromEvent(Event $event) + { + return $event->getTaxRule(); + } + + /** + * @param array $data + * @return \Symfony\Component\EventDispatcher\Event + */ + protected function getCreationEvent(array &$data) + { + return $this->hydrateEvent($data); + } + + /** + * @param array $data + * @return \Symfony\Component\EventDispatcher\Event + */ + protected function getUpdateEvent(array &$data) + { + return $this->hydrateEvent($data); + } + + /** + * @param mixed $entityId + * @return \Symfony\Component\EventDispatcher\Event + */ + protected function getDeleteEvent($entityId) + { + $data = ["id" => $entityId]; + + return $this->hydrateEvent($data); + } + + protected function afterCreateEvents(Event $event, array &$data) + { + $dispatcher = $this->getDispatcher(); + + if ($data["default"]) { + $dispatcher->dispatch(TheliaEvents::TAX_RULE_SET_DEFAULT, $event); + } + + foreach ($data["i18n"] as $i18nRow) { + $this->hydrateI18nEvent($i18nRow, $event); + + foreach ($this->updateEvents as $eventName) { + $dispatcher->dispatch($eventName, $event); + } + } + } + + protected function afterUpdateEvents(Event $event, array &$data) + { + $this->afterCreateEvents($event, $data); + } + + protected function hydrateEvent(array &$data) + { + $event = new TaxRuleEvent(); + + if (isset($data["country"])) { + $event->setCountryList($data["country"]); + } + + if (isset($data["tax"])) { + $event->setTaxList($data["tax"]); + } + + if (isset($data["id"])) { + $event->setId($data["id"]); + $event->setTaxRule(TaxRuleQuery::create()->findPk($data["id"])); + } + + if (isset($data["i18n"]) && null !== $row = array_shift($data["i18n"])) { + $this->hydrateI18nEvent($row, $event); + } + + return $event; + } + + protected function hydrateI18nEvent(array $i18nRow, TaxRuleEvent $event) + { + $event + ->setLocale($i18nRow["locale"]) + ->setTitle($i18nRow["title"]) + ->setDescription($i18nRow["description"]) + ; + } + + public function hydrateUpdateForm(FormEvent $event) + { + $data = $event->getData(); + $keys = array_keys($data["i18n"]); + + foreach ($keys as $key) { + $value = $data["i18n"][$key]; + $data["i18n"][$value["locale"]] = $value; + + unset($data["i18n"][$key]); + } + + $persistentI18n = $this->getI18nPersistentData($data["id"]); + + foreach ($persistentI18n["i18n"] as $locale => $value) { + $data["i18n"][$locale] = array_merge($value, $data["i18n"][$locale]); + } + + $data = array_merge($this->getPersistentData($data["id"]), $data); + + $event->setData($data); + } + + protected function getPersistentData($taxRuleId) + { + $taxRule = TaxRuleQuery::create()->findPk($taxRuleId); + + if (null === $taxRule) { + throw new HttpException(404, json_encode([ + "error" => sprintf("The tax rule %d doesn't exist", $taxRuleId) + ])); + } + + $countries = TaxRuleCountryQuery::create() + ->filterByTaxRuleId($taxRuleId) + ->distinct() + ->select(TaxRuleCountryTableMap::COL_COUNTRY_ID) + ->find() + ->toArray() + ; + + $taxes = TaxRuleCountryQuery::create() + ->filterByTaxRuleId($taxRuleId) + ->distinct() + ->select(TaxRuleCountryTableMap::COL_TAX_ID) + ->find() + ->toArray() + ; + + $data = [ + "default" => (bool) $taxRule->getIsDefault(), + "tax" => $taxes, + "country" => $countries, + ]; + + return $data; + } + + /** + * @param int $taxRuleId + * @return array + */ + protected function getI18nPersistentData($taxRuleId) + { + $i18ns = TaxRuleI18NQuery::create() + ->findById($taxRuleId) + ; + + $data = ['i18n' => []]; + + /** @var \Thelia\Model\TaxRuleI18n $i18n */ + foreach ($i18ns as $i18n) { + $data["i18n"][$i18n->getLocale()] = array( + "locale" => $i18n->getLocale(), + "title" => $i18n->getTitle(), + "description" => $i18n->getDescription(), + ); + } + + return $data; + } +} diff --git a/core/lib/Thelia/Controller/Api/TitleController.php b/core/lib/Thelia/Controller/Api/TitleController.php new file mode 100644 index 00000000..d9153f68 --- /dev/null +++ b/core/lib/Thelia/Controller/Api/TitleController.php @@ -0,0 +1,235 @@ + + * @author Manuel Raynaud + */ +class TitleController extends AbstractCrudApiController +{ + public function __construct() + { + parent::__construct( + "customer title", + AdminResources::TITLE, + [ + TheliaEvents::CUSTOMER_TITLE_BEFORE_CREATE, + TheliaEvents::CUSTOMER_TITLE_CREATE, + TheliaEvents::CUSTOMER_TITLE_AFTER_CREATE, + ], + [ + TheliaEvents::CUSTOMER_TITLE_BEFORE_UPDATE, + TheliaEvents::CUSTOMER_TITLE_UPDATE, + TheliaEvents::CUSTOMER_TITLE_AFTER_UPDATE, + ], + TheliaEvents::CUSTOMER_TITLE_DELETE + ); + } + + + /** + * @return \Thelia\Core\Template\Element\BaseLoop + * + * Get the entity loop instance + */ + protected function getLoop() + { + return new Title($this->container); + } + + /** + * @param array $data + * @return \Thelia\Form\BaseForm + */ + protected function getCreationForm(array $data = array()) + { + return $this->createForm(null, "customer_title", $data); + } + + /** + * @param array $data + * @return \Thelia\Form\BaseForm + */ + protected function getUpdateForm(array $data = array()) + { + return $this->createForm(null, "customer_title", $data, array( + "validation_groups" => ["Default", "update"], + "method" => "PUT", + )); + } + + /** + * @param Event $event + * @return null|mixed + * + * Get the object from the event + * + * if return null or false, the action will throw a 404 + */ + protected function extractObjectFromEvent(Event $event) + { + return $event->getCustomerTitle(); + } + + /** + * @param array $data + * @return \Symfony\Component\EventDispatcher\Event + */ + protected function getCreationEvent(array &$data) + { + return $this->createEvent($data); + } + + /** + * @param array $data + * @return \Symfony\Component\EventDispatcher\Event + */ + protected function getUpdateEvent(array &$data) + { + return $this->createEvent($data); + } + + /** + * @param mixed $entityId + * @return \Symfony\Component\EventDispatcher\Event + */ + protected function getDeleteEvent($entityId) + { + $data = ["title_id" => $entityId]; + + return $this->createEvent($data); + } + + /** + * @param array $data + * @return CustomerTitleEvent + * + * Handler to create the customer title event + */ + protected function createEvent(array &$data) + { + $event = new CustomerTitleEvent(); + + if (isset($data["default"])) { + $event->setDefault($data["default"]); + } + + if (isset($data["title_id"])) { + $event->setCustomerTitle(CustomerTitleQuery::create()->findPk($data["title_id"])); + } + + if (isset($data["i18n"]) && !empty($data["i18n"])) { + $row = array_shift($data["i18n"]); + + $this->hydrateEvent($row, $event); + } + + return $event; + } + + /** + * @param array $i18nRow + * @param CustomerTitleEvent $event + * + * Handler to hydrate the event with i18n data + */ + protected function hydrateEvent(array $i18nRow, CustomerTitleEvent $event) + { + $event + ->setShort($i18nRow["short"]) + ->setLong($i18nRow["long"]) + ->setLocale($i18nRow["locale"]) + ; + } + + protected function afterCreateEvents(Event $event, array &$data) + { + $dispatcher = $this->getDispatcher(); + + while (null !== $i18nRow = array_shift($data["i18n"])) { + $this->hydrateEvent($i18nRow, $event); + + foreach ($this->updateEvents as $eventName) { + $dispatcher->dispatch($eventName, $event); + } + } + } + + protected function afterUpdateEvents(Event $event, array &$data) + { + $this->afterCreateEvents($event, $data); + } + + /** + * @param FormEvent $event + * + * This methods loads current title data into the update form. + * It uses an event to load only needed ids. + */ + public function hydrateUpdateForm(FormEvent $event) + { + $data = $event->getData(); + + $title = CustomerTitleQuery::create()->findPk($data["title_id"]); + + if (null === $title) { + $this->entityNotFound($data["title_id"]); + } + + $data["default"] |= (bool) $title->getByDefault(); + + $titleI18ns = CustomerTitleI18nQuery::create() + ->filterById($data["title_id"]) + ->find() + ->toKeyIndex('Locale') + ; + + $i18n = &$data["i18n"]; + + foreach ($data["i18n"] as $key => $value) { + $i18n[$value["locale"]] = $value; + + unset($i18n[$key]); + } + + + /** @var \Thelia\Model\CustomerTitleI18n $titleI18n */ + foreach ($titleI18ns as $titleI18n) { + $row = array(); + + $row["locale"] = $locale = $titleI18n->getLocale(); + $row["short"] = $titleI18n->getShort(); + $row["long"] = $titleI18n->getLong(); + + if (!isset($i18n[$locale])) { + $i18n[$locale] = array(); + } + + $i18n[$locale] = array_merge($row, $i18n[$locale]); + } + + $event->setData($data); + } +} diff --git a/core/lib/Thelia/Controller/BaseController.php b/core/lib/Thelia/Controller/BaseController.php new file mode 100644 index 00000000..536e183a --- /dev/null +++ b/core/lib/Thelia/Controller/BaseController.php @@ -0,0 +1,631 @@ + + * @author Manuel Raynaud + * @author Benjamin Perche + */ + +abstract class BaseController +{ + use ContainerAwareTrait; + + const EMPTY_FORM_NAME = "thelia.empty"; + + protected $tokenProvider; + + protected $currentRouter; + + protected $translator; + + protected $templateHelper; + + protected $adminResources; + + /** @var bool Fallback on default template when setting the templateDefinition */ + protected $useFallbackTemplate = true; + + /** + * Return an empty response (after an ajax request, for example) + * @param int $status + * @return \Thelia\Core\HttpFoundation\Response + */ + protected function nullResponse($status = 200) + { + return new Response(null, $status); + } + + /** + * @param $jsonData + * @param int $status + * @return Response Return a JSON response + */ + protected function jsonResponse($jsonData, $status = 200) + { + return new Response($jsonData, $status, array('content-type' => 'application/json')); + } + + /** + * @param $pdf + * @param $fileName + * @param int $status + * @param bool $browser + * @return \Symfony\Component\HttpFoundation\Response + */ + protected function pdfResponse($pdf, $fileName, $status = 200, $browser = false) + { + return Response::create( + $pdf, + $status, + array( + 'Content-type' => "application/pdf", + 'Content-Disposition' =>sprintf( + '%s; filename=%s.pdf', + \boolval($browser) === false ? 'attachment' : 'inline', + $fileName + ) + ) + ); + } + + /** + * Dispatch a Thelia event + * + * @param string $eventName a TheliaEvent name, as defined in TheliaEvents class + * @param ActionEvent $event the action event, or null (a DefaultActionEvent will be dispatched) + */ + protected function dispatch($eventName, ActionEvent $event = null) + { + if ($event == null) { + $event = new DefaultActionEvent(); + } + + $this->getDispatcher()->dispatch($eventName, $event); + } + + /** + * Return the event dispatcher, + * + * @return \Symfony\Component\EventDispatcher\EventDispatcher + */ + public function getDispatcher() + { + return $this->container->get('event_dispatcher'); + } + + /** + * return the Translator + * + * @return Translator + */ + public function getTranslator() + { + if (null === $this->translator) { + $this->translator = $this->container->get('thelia.translator'); + } + return $this->translator; + } + + /** + * Return the parser context, + * + * @return ParserContext + */ + protected function getParserContext() + { + return $this->container->get('thelia.parser.context'); + } + + /** + * Return the security context, by default in admin mode. + * + * @return \Thelia\Core\Security\SecurityContext + */ + protected function getSecurityContext() + { + return $this->container->get('thelia.securityContext'); + } + + /** + * @return \Thelia\Core\HttpFoundation\Request + */ + protected function getRequest() + { + return $this->container->get('request_stack')->getCurrentRequest(); + } + + /** + * Returns the session from the current request + * + * @return \Thelia\Core\HttpFoundation\Session\Session + */ + protected function getSession() + { + return $this->container->get('request_stack')->getCurrentRequest()->getSession(); + } + + /** + * @return \Thelia\Tools\TokenProvider + */ + protected function getTokenProvider() + { + if (null === $this->tokenProvider) { + $this->tokenProvider = $this->container->get("thelia.token_provider"); + } + + return $this->tokenProvider; + } + + /** + * @return \Thelia\Core\Template\TemplateHelperInterface + */ + protected function getTemplateHelper() + { + if (null === $this->templateHelper) { + $this->templateHelper = $this->container->get("thelia.template_helper"); + } + + return $this->templateHelper; + } + + /** + * @since 2.3 + * @return \Thelia\Core\Security\Resource\AdminResources + */ + protected function getAdminResources() + { + if (null === $this->adminResources) { + $this->adminResources = $this->container->get("thelia.admin.resources"); + } + + return $this->adminResources; + } + + /** + * Get all errors that occurred in a form + * + * @param \Symfony\Component\Form\Form $form + * @return string the error string + */ + protected function getErrorMessages(Form $form) + { + return $this->getTheliaFormValidator()->getErrorMessages($form); + } + + /** + * Validate a BaseForm + * + * @param BaseForm $aBaseForm the form + * @param string $expectedMethod the expected method, POST or GET, or null for any of them + * @throws FormValidationException is the form contains error, or the method is not the right one + * @return \Symfony\Component\Form\Form Form the symfony form object + */ + protected function validateForm(BaseForm $aBaseForm, $expectedMethod = null) + { + $form = $this->getTheliaFormValidator()->validateForm($aBaseForm, $expectedMethod); + + // At this point, the form is valid (no exception was thrown). Remove it from the error context. + $this->getParserContext()->clearForm($aBaseForm); + + return $form; + } + + /** + * @return \Thelia\Core\Form\TheliaFormValidatorInterface + */ + protected function getTheliaFormValidator() + { + return $this->container->get("thelia.form_validator"); + } + + /** + * @param int $order_id + * @param string $fileName + * @param bool $checkOrderStatus + * @param bool $checkAdminUser + * @return \Symfony\Component\HttpFoundation\Response + */ + protected function generateOrderPdf($order_id, $fileName, $checkOrderStatus = true, $checkAdminUser = true, $browser = false) + { + $order = OrderQuery::create()->findPk($order_id); + + // check if the order has the paid status + if ($checkAdminUser && !$this->getSecurityContext()->hasAdminUser()) { + if ($checkOrderStatus && !$order->isPaid(false)) { + throw new NotFoundHttpException(); + } + } + + $html = $this->renderRaw( + $fileName, + array( + 'order_id' => $order_id + ), + $this->getTemplateHelper()->getActivePdfTemplate() + ); + + try { + $pdfEvent = new PdfEvent($html); + + $this->dispatch(TheliaEvents::GENERATE_PDF, $pdfEvent); + + if ($pdfEvent->hasPdf()) { + return $this->pdfResponse($pdfEvent->getPdf(), $order->getRef(), 200, $browser); + } + } catch (\Exception $e) { + Tlog::getInstance()->error( + sprintf( + 'error during generating invoice pdf for order id : %d with message "%s"', + $order_id, + $e->getMessage() + ) + ); + } + + throw new TheliaProcessException( + $this->getTranslator()->trans( + "We're sorry, this PDF invoice is not available at the moment." + ) + ); + } + + /** + * Search success url in a form if present, in the query string otherwise + * + * @param BaseForm $form + * @return mixed|null|string + */ + protected function retrieveSuccessUrl(BaseForm $form = null) + { + return $this->retrieveFormBasedUrl('success_url', $form); + } + + /** + * Search error url in a form if present, in the query string otherwise + * + * @param BaseForm $form + * @return mixed|null|string + */ + protected function retrieveErrorUrl(BaseForm $form = null) + { + return $this->retrieveFormBasedUrl('error_url', $form); + } + /** + * Search url in a form parameter, or in a request parameter. + * + * @param string $parameterName the form parameter name, or request parameter name. + * @param BaseForm $form the form + * @return mixed|null|string + */ + protected function retrieveFormBasedUrl($parameterName, BaseForm $form = null) + { + $url = null; + + if ($form != null) { + $url = $form->getFormDefinedUrl($parameterName); + } else { + $url = $this->container->get('request_stack')->getCurrentRequest()->get($parameterName); + } + + return $url; + } + + /** + * @param $routeId + * @param array $urlParameters + * @param array $routeParameters + * @param int $referenceType + * @return string + */ + protected function retrieveUrlFromRouteId( + $routeId, + array $urlParameters = [], + array $routeParameters = [], + $referenceType = Router::ABSOLUTE_PATH + ) { + return URL::getInstance()->absoluteUrl( + $this->getRoute( + $routeId, + $routeParameters, + $referenceType + ), + $urlParameters + ); + } + + /** + * + * create an instance of RedirectResponse + * + * @param $url + * @param int $status + * @return \Symfony\Component\HttpFoundation\Response + */ + protected function generateRedirect($url, $status = 302) + { + return RedirectResponse::create($url, $status); + } + + /** + * create an instance of RedirectReponse if a success url is present, return null otherwise + * + * @param BaseForm $form + * @return null|\Symfony\Component\HttpFoundation\Response + */ + protected function generateSuccessRedirect(BaseForm $form = null) + { + if (null !== $url = $this->retrieveSuccessUrl($form)) { + return $this->generateRedirect($url); + } + + return null; + } + + /** + * create an instance of RedirectReponse if a success url is present, return null otherwise + * + * @param BaseForm $form + * @return null|\Symfony\Component\HttpFoundation\Response + */ + protected function generateErrorRedirect(BaseForm $form = null) + { + if (null !== $url = $this->retrieveErrorUrl($form)) { + return $this->generateRedirect($url); + } + + return null; + } + + /** + * + * create an instance of RedriectResponse for a given route id. + * + * @param $routeId + * @param array $urlParameters + * @param array $routeParameters + * @param int $referenceType + * @return \Symfony\Component\HttpFoundation\Response + */ + protected function generateRedirectFromRoute( + $routeId, + array $urlParameters = [], + array $routeParameters = [], + $referenceType = Router::ABSOLUTE_PATH + ) { + return $this->generateRedirect( + $this->retrieveUrlFromRouteId($routeId, $urlParameters, $routeParameters, $referenceType) + ); + } + + /** + * Return the route path defined for the givent route ID + * + * @param string $routeId a route ID, as defines in Config/Resources/routing/admin.xml + * @param mixed $parameters An array of parameters + * @param int $referenceType The type of reference to be generated (one of the constants) + * + * @throws RouteNotFoundException If the named route doesn't exist + * @throws MissingMandatoryParametersException When some parameters are missing that are mandatory for the route + * @throws InvalidParameterException When a parameter value for a placeholder is not correct because + * it does not match the requirement + * @throws \InvalidArgumentException When the router doesn't exist + * @return string The generated URL + * + * @see \Thelia\Controller\BaseController::getRouteFromRouter() + */ + protected function getRoute($routeId, $parameters = array(), $referenceType = Router::ABSOLUTE_URL) + { + return $this->getRouteFromRouter( + $this->getCurrentRouter(), + $routeId, + $parameters, + $referenceType + ); + } + + /** + * Get a route path from the route id. + * + * @param string $routerName Router name + * @param string $routeId The name of the route + * @param mixed $parameters An array of parameters + * @param int $referenceType The type of reference to be generated (one of the constants) + * + * @throws RouteNotFoundException If the named route doesn't exist + * @throws MissingMandatoryParametersException When some parameters are missing that are mandatory for the route + * @throws InvalidParameterException When a parameter value for a placeholder is not correct because + * it does not match the requirement + * @throws \InvalidArgumentException When the router doesn't exist + * @return string The generated URL + */ + protected function getRouteFromRouter( + $routerName, + $routeId, + $parameters = array(), + $referenceType = Router::ABSOLUTE_URL + ) { + /** @var Router $router */ + $router = $this->getRouter($routerName); + + if ($router == null) { + throw new \InvalidArgumentException(sprintf("Router '%s' does not exists.", $routerName)); + } + + return $router->generate($routeId, $parameters, $referenceType); + } + + /** + * @param $routerName + * @return Router + */ + protected function getRouter($routerName) + { + return $this->container->get($routerName); + } + + /** + * Return a 404 error + * @throws \Symfony\Component\HttpKernel\Exception\NotFoundHttpException + */ + protected function pageNotFound() + { + throw new NotFoundHttpException(); + } + + /** + * Check if environment is in debug mode + * + * @return bool + */ + protected function isDebug() + { + return $this->container->getParameter('kernel.debug'); + } + + protected function accessDenied() + { + throw new AccessDeniedHttpException(); + } + + /** + * check if the current http request is a XmlHttpRequest. + * + * If not, send a + */ + protected function checkXmlHttpRequest() + { + if (false === $this->container->get('request_stack')->getCurrentRequest()->isXmlHttpRequest() && false === $this->isDebug()) { + $this->accessDenied(); + } + } + + /** + * + * return an instance of \Swift_Mailer with good Transporter configured. + * + * @return MailerFactory + */ + public function getMailer() + { + return $this->container->get('mailer'); + } + + protected function getCurrentRouter() + { + return $this->currentRouter; + } + + protected function setCurrentRouter($routerId) + { + $this->currentRouter = $routerId; + } + + /** + * @param $name + * @param $type + * @param array $data + * @param array $options + * @return BaseForm + * + * This method builds a thelia form with its name + */ + public function createForm($name, $type = "form", array $data = array(), array $options = array()) + { + if (empty($name)) { + $name = static::EMPTY_FORM_NAME; + } + + return $this->getTheliaFormFactory()->createForm($name, $type, $data, $options); + } + + /** + * @return \Thelia\Core\Form\TheliaFormFactoryInterface + */ + protected function getTheliaFormFactory() + { + return $this->container->get("thelia.form_factory"); + } + + /** + * @return \Symfony\Component\DependencyInjection\ContainerInterface + */ + public function getContainer() + { + return $this->container; + } + + /** + * Return controller type + * + * @return string + */ + abstract public function getControllerType(); + + /** + * @param null|mixed $template + * @return \Thelia\Core\Template\ParserInterface instance parser + */ + abstract protected function getParser($template = null); + + /** + * Render the given template, and returns the result as an Http Response. + * + * @param string $templateName the complete template name, with extension + * @param array $args the template arguments + * @param int $status http code status + * @return \Thelia\Core\HttpFoundation\Response + */ + abstract protected function render($templateName, $args = array(), $status = 200); + + /** + * Render the given template, and returns the result as a string. + * + * @param string $templateName the complete template name, with extension + * @param array $args the template arguments + * @param null $templateDir + * + * @return string + */ + abstract protected function renderRaw($templateName, $args = array(), $templateDir = null); +} diff --git a/core/lib/Thelia/Controller/Front/BaseFrontController.php b/core/lib/Thelia/Controller/Front/BaseFrontController.php new file mode 100644 index 00000000..e5812ed2 --- /dev/null +++ b/core/lib/Thelia/Controller/Front/BaseFrontController.php @@ -0,0 +1,134 @@ +getSecurityContext()->hasCustomerUser() === false) { + throw new RedirectException($this->retrieveUrlFromRouteId('customer.login.process')); + } + } + + /** + * @return string + */ + public function getControllerType() + { + return self::CONTROLLER_TYPE; + } + + protected function checkCartNotEmpty() + { + $cart = $this->getSession()->getSessionCart($this->getDispatcher()); + if ($cart===null || $cart->countCartItems() == 0) { + throw new RedirectException($this->retrieveUrlFromRouteId('cart.view')); + } + } + + protected function checkValidDelivery() + { + $order = $this->getSession()->getOrder(); + if (null === $order + || + null === $order->getChoosenDeliveryAddress() + || + null === $order->getDeliveryModuleId() + || + null === AddressQuery::create()->findPk($order->getChoosenDeliveryAddress()) + || + null === ModuleQuery::create()->findPk($order->getDeliveryModuleId())) { + throw new RedirectException($this->retrieveUrlFromRouteId('order.delivery')); + } + } + + protected function checkValidInvoice() + { + $order = $this->getSession()->getOrder(); + if (null === $order + || + null === $order->getChoosenInvoiceAddress() + || + null === $order->getPaymentModuleId() + || + null === AddressQuery::create()->findPk($order->getChoosenInvoiceAddress()) + || + null === ModuleQuery::create()->findPk($order->getPaymentModuleId())) { + throw new RedirectException($this->retrieveUrlFromRouteId('order.invoice')); + } + } + + /** + * @param TemplateDefinition $template the template to process, or null for using the front template + * + * @return ParserInterface the Thelia parser² + */ + protected function getParser($template = null) + { + $parser = $this->container->get("thelia.parser"); + + // Define the template that should be used + $parser->setTemplateDefinition( + $template ?: $this->getTemplateHelper()->getActiveFrontTemplate(), + $this->useFallbackTemplate + ); + + return $parser; + } + + /** + * Render the given template, and returns the result as an Http Response. + * + * @param string $templateName the complete template name, with extension + * @param array $args the template arguments + * @param int $status http code status + * @return \Thelia\Core\HttpFoundation\Response + */ + protected function render($templateName, $args = array(), $status = 200) + { + return Response::create($this->renderRaw($templateName, $args), $status); + } + + /** + * Render the given template, and returns the result as a string. + * + * @param string $templateName the complete template name, with extension + * @param array $args the template arguments + * @param string$templateDir + * + * @return string + */ + protected function renderRaw($templateName, $args = array(), $templateDir = null) + { + // Add the template standard extension + $templateName .= '.html'; + + // Render the template. + $data = $this->getParser($templateDir)->render($templateName, $args); + + return $data; + } +} diff --git a/core/lib/Thelia/Controller/Front/DefaultController.php b/core/lib/Thelia/Controller/Front/DefaultController.php new file mode 100644 index 00000000..03f2b5bf --- /dev/null +++ b/core/lib/Thelia/Controller/Front/DefaultController.php @@ -0,0 +1,76 @@ + + */ + +class DefaultController extends BaseFrontController +{ + /** + * This is the default Thelia behaviour if no action is defined. + * + * If the request contains a 'view' parameter, this view will be displayed. + * If the request contains a '_view' attribute (set in the route definition, for example), this view will be displayed. + * Otherwise, we will use the "index" view. + * + * Additionaly, if the URL rewriting is enabled, the method will check if a redirect to the pâge rewritten URL should + * be done. + * + * @param \Thelia\Core\HttpFoundation\Request $request + * @throw RedirectException if a redirection to the rewritted URL shoud be done. + */ + public function noAction(Request $request) + { + $view = null; + + if (! $view = $request->query->get('view')) { + if ($request->request->has('view')) { + $view = $request->request->get('view'); + } + } + if (null !== $view) { + $request->attributes->set('_view', $view); + } + + if (null === $view && null === $request->attributes->get("_view")) { + $request->attributes->set("_view", "index"); + } + + if (ConfigQuery::isRewritingEnable()) { + if ($request->attributes->get('_rewritten', false) === false) { + /* Does the query GET parameters match a rewritten URL ? */ + $rewrittenUrl = URL::getInstance()->retrieveCurrent($request); + + if ($rewrittenUrl->rewrittenUrl !== null) { + /* 301 redirection to rewritten URL */ + throw new RedirectException($rewrittenUrl->rewrittenUrl, 301); + } + } + } + } + + public function emptyRoute() + { + return new Response(null, 204); + } +} diff --git a/core/lib/Thelia/Core/Application.php b/core/lib/Thelia/Core/Application.php new file mode 100644 index 00000000..5853e3f6 --- /dev/null +++ b/core/lib/Thelia/Core/Application.php @@ -0,0 +1,82 @@ +kernel = $kernel; + + parent::__construct("Thelia", Thelia::THELIA_VERSION); + + $this->kernel->boot(); + + $this->getDefinition()->addOption(new InputOption('--env', '-e', InputOption::VALUE_REQUIRED, 'The Environment name.', $kernel->getEnvironment())); + $this->getDefinition()->addOption(new InputOption('--no-debug', null, InputOption::VALUE_NONE, 'Switches off debug mode.')); + } + + public function getKernel() + { + return $this->kernel; + } + + public function getContainer() + { + return $this->kernel->getContainer(); + } + + public function doRun(InputInterface $input, OutputInterface $output) + { + $this->registerCommands(); + + /** @var \Symfony\Component\EventDispatcher\ContainerAwareEventDispatcher $eventDispatcher */ + $eventDispatcher = $this->getContainer()->get('event_dispatcher'); + $this->setDispatcher($eventDispatcher); + + return parent::doRun($input, $output); + } + + protected function registerCommands() + { + if (!Thelia::isInstalled()) { + $this->add(new Install()); + return; + } + + $container = $this->kernel->getContainer(); + + foreach ($container->getParameter("command.definition") as $command) { + $r = new \ReflectionClass($command); + + if ($r->isSubclassOf('Symfony\\Component\\Console\\Command\\Command') && !$r->isAbstract()) { + $this->add($r->newInstance()); + } + } + } +} diff --git a/core/lib/Thelia/Core/Archiver/AbstractArchiver.php b/core/lib/Thelia/Core/Archiver/AbstractArchiver.php new file mode 100644 index 00000000..a3265514 --- /dev/null +++ b/core/lib/Thelia/Core/Archiver/AbstractArchiver.php @@ -0,0 +1,89 @@ + + */ +abstract class AbstractArchiver implements ArchiverInterface +{ + /** + * @var mixed The archive resource + */ + protected $archive; + + /** + * @var string Path to archive + */ + protected $archivePath; + + public function __construct($checkIsAvailable = false) + { + if ($checkIsAvailable && !$this->isAvailable()) { + throw new \Exception( + Translator::getInstance()->trans( + "The archiver :name is not available. Please install the php extension :extension first.", + [ + ':name' => $this->getName(), + ':extension' => $this->getExtension(), + ] + ) + ); + } + } + + public function getArchivePath() + { + return $this->archivePath; + } + + public function setArchivePath($archivePath) + { + $this->archivePath = $archivePath; + + return $this; + } + + public function add($path, $pathInArchive = null) + { + $path = realpath($path); + if (!file_exists($path)) { + throw new \RuntimeException('File ' . $path . ' doesn\'t exists'); + } + + if ($pathInArchive === null) { + $pathInArchive = basename($path); + } + + if (is_dir($path)) { + foreach (new \DirectoryIterator($path) as $dirItem) { + if ($dirItem->isDot()) { + continue; + } + $this->add($dirItem->getPathname(), $pathInArchive . DS . $dirItem->getFilename()); + } + } else { + $this->archive->addFile($path, $pathInArchive); + } + + return $this; + } + + public function extract($toPath = null) + { + $this->archive->extractTo($toPath); + } +} diff --git a/core/lib/Thelia/Core/Archiver/Archiver/TarArchiver.php b/core/lib/Thelia/Core/Archiver/Archiver/TarArchiver.php new file mode 100644 index 00000000..543ceece --- /dev/null +++ b/core/lib/Thelia/Core/Archiver/Archiver/TarArchiver.php @@ -0,0 +1,84 @@ + + */ +class TarArchiver extends AbstractArchiver +{ + /** + * @var integer Compression method + */ + const COMPRESSION_METHOD = \Phar::NONE; + + public function getId() + { + return 'thelia.tar'; + } + + public function getName() + { + return 'Tar'; + } + + public function getExtension() + { + return 'tar'; + } + + public function getMimeType() + { + return 'application/x-tar'; + } + + public function isAvailable() + { + return class_exists('\\PharData'); + } + + public function create($baseName) + { + $this->archivePath = $baseName . '.' . $this->getExtension(); + + $this->archive = new \PharData($this->archivePath); + + return $this; + } + + public function open($path) + { + $this->archivePath = $path; + + $this->archive = new \PharData($this->archivePath); + + return $this; + } + + public function save() + { + /** @var \PharData $newArchive */ + $newArchive = $this->archive->compress(static::COMPRESSION_METHOD, $this->getExtension()); + + $fileSystem = new Filesystem; + $fileSystem->remove($this->archivePath); + $fileSystem->rename($newArchive->getPath(), $this->archivePath); + + $this->archive = new \PharData($this->archivePath); + } +} diff --git a/core/lib/Thelia/Core/Archiver/Archiver/TarBz2Archiver.php b/core/lib/Thelia/Core/Archiver/Archiver/TarBz2Archiver.php new file mode 100644 index 00000000..3dc0015b --- /dev/null +++ b/core/lib/Thelia/Core/Archiver/Archiver/TarBz2Archiver.php @@ -0,0 +1,47 @@ + + */ +class TarBz2Archiver extends TarArchiver +{ + const COMPRESSION_METHOD = \Phar::BZ2; + + public function getId() + { + return 'thelia.tar.bz2'; + } + + public function getName() + { + return 'Bzip2'; + } + + public function getExtension() + { + return 'bz2'; + } + + public function getMimeType() + { + return 'application/x-bzip2'; + } + + public function isAvailable() + { + return parent::isAvailable() && extension_loaded('bz2'); + } +} diff --git a/core/lib/Thelia/Core/Archiver/Archiver/TarGzArchiver.php b/core/lib/Thelia/Core/Archiver/Archiver/TarGzArchiver.php new file mode 100644 index 00000000..e6f12413 --- /dev/null +++ b/core/lib/Thelia/Core/Archiver/Archiver/TarGzArchiver.php @@ -0,0 +1,47 @@ + + */ +class TarGzArchiver extends TarArchiver +{ + const COMPRESSION_METHOD = \Phar::GZ; + + public function getId() + { + return 'thelia.tar.gz'; + } + + public function getName() + { + return 'Gz'; + } + + public function getExtension() + { + return 'tgz'; + } + + public function getMimeType() + { + return 'application/x-gzip'; + } + + public function isAvailable() + { + return parent::isAvailable() && extension_loaded('zlib'); + } +} diff --git a/core/lib/Thelia/Core/Archiver/Archiver/ZipArchiver.php b/core/lib/Thelia/Core/Archiver/Archiver/ZipArchiver.php new file mode 100644 index 00000000..dd1915b4 --- /dev/null +++ b/core/lib/Thelia/Core/Archiver/Archiver/ZipArchiver.php @@ -0,0 +1,79 @@ + + */ +class ZipArchiver extends AbstractArchiver +{ + public function getId() + { + return 'thelia.zip'; + } + + public function getName() + { + return 'Zip'; + } + + public function getExtension() + { + return 'zip'; + } + + public function getMimeType() + { + return 'application/zip'; + } + + public function isAvailable() + { + return class_exists('\\ZipArchive'); + } + + public function create($baseName) + { + $this->archive = new \ZipArchive; + + $this->archivePath = $baseName . '.' . $this->getExtension(); + + $this->archive->open($this->archivePath, \ZipArchive::CREATE | \ZipArchive::OVERWRITE); + + return $this; + } + + public function open($path) + { + $this->archive = new \ZipArchive; + + $this->archivePath = $path; + + $this->archive->open($this->archivePath); + + return $this; + } + + public function save() + { + return $this->close(); + } + + public function close() + { + return $this->archive->close(); + } +} diff --git a/core/lib/Thelia/Core/Archiver/ArchiverInterface.php b/core/lib/Thelia/Core/Archiver/ArchiverInterface.php new file mode 100644 index 00000000..77685b9c --- /dev/null +++ b/core/lib/Thelia/Core/Archiver/ArchiverInterface.php @@ -0,0 +1,115 @@ + + */ +interface ArchiverInterface +{ + /** + * Get archiver identifier + * + * @return string The archiver identifier + */ + public function getId(); + + /** + * Get archiver name + * + * @return string The archiver name + */ + public function getName(); + + /** + * Get archiver extension + * + * @return string The archiver extension + */ + public function getExtension(); + + /** + * Get archiver mime type + * + * @return string The archiver mime type + */ + public function getMimeType(); + + /** + * Get archiver availability + * + * @return boolean Archiver availability + */ + public function isAvailable(); + + /** + * Get archive path + * + * @return string + */ + public function getArchivePath(); + + /** + * Set archive path + * + * @param string $archivePath + * + * @return $this Return $this, allow chaining + */ + public function setArchivePath($archivePath); + + /** + * Create a new archive + * + * @param string $baseName The archive name without extension + * + * @return $this Return $this, allow chaining + */ + public function create($baseName); + + /** + * Open an archive + * + * @param string $path Path to archive + * + * @return $this Return $this, allow chaining + */ + public function open($path); + + /** + * Add directory or file to archive + * + * @param string $path + * @param null|string $pathInArchive + * + * @return $this Return $this, allow chaining + */ + public function add($path, $pathInArchive = null); + + /** + * Save archive + * + * @return boolean True on success, false otherwise + */ + public function save(); + + /** + * Extract archive + * + * @param string $toPath Where to extract + * + * @return \Symfony\Component\HttpFoundation\File\File + */ + public function extract($toPath); +} diff --git a/core/lib/Thelia/Core/Archiver/ArchiverManager.php b/core/lib/Thelia/Core/Archiver/ArchiverManager.php new file mode 100644 index 00000000..4a496df5 --- /dev/null +++ b/core/lib/Thelia/Core/Archiver/ArchiverManager.php @@ -0,0 +1,165 @@ + + */ +class ArchiverManager +{ + /** + * @var array List of handled archivers + */ + protected $archivers = []; + + /** + * Reset manager + * + * @return $this Return $this, allow chaining + */ + public function reset() + { + $this->archivers = []; + + return $this; + } + + /** + * Get all archivers or only those match availability + * + * @param null|boolean $isAvailable Filter archivers by availability + * + * @return array All, or filtered by availability, archivers + */ + public function getArchivers($isAvailable = null) + { + if ($isAvailable === null) { + return $this->archivers; + } + + $filteredArchivers = []; + + /** @var \Thelia\Core\Archiver\ArchiverInterface $archiver */ + foreach ($this->archivers as $archiver) { + if ($archiver->isAvailable() === (bool) $isAvailable) { + $filteredArchivers[] = $archiver; + } + } + + return $filteredArchivers; + } + + /** + * Determine if an archiver exists under the given identifier + * + * @param string $archiverId An archiver identifier + * @param boolean $throwException Throw exception if archiver doesn't exists or not + * + * @throws \InvalidArgumentException if the archiver identifier does not exist + * + * @return boolean True if the archiver exists, false otherwise + */ + public function has($archiverId, $throwException = false) + { + $exists = isset($this->archivers[$archiverId]); + + if (!$exists && $throwException) { + throw new \InvalidArgumentException( + Translator::getInstance()->trans( + 'The archiver identifier "%archiverId" doesn\’t exist', + [ + '%archiverId' => $archiverId + ] + ) + ); + } + + return $exists; + } + + /** + * Get an archiver + * + * @param string $archiverId An archiver identifier + * @param null|boolean $isAvailable Filter archiver by availability + * + * @return null|\Thelia\Core\Archiver\ArchiverInterface Return an archiver or null depends on availability + */ + public function get($archiverId, $isAvailable = null) + { + $this->has($archiverId, true); + + if ($isAvailable === null) { + return $this->archivers[$archiverId]; + } + + if ($this->archivers[$archiverId]->isAvailable() === (bool) $isAvailable) { + return $this->archivers[$archiverId]; + } + + return null; + } + + /** + * Set archivers + * + * @param array $archivers An array of archiver + * + * @throws \Exception + * + * @return $this Return $this, allow chaining + */ + public function setArchivers(array $archivers) + { + $this->archivers = []; + + foreach ($archivers as $archiver) { + if (!($archiver instanceof ArchiverInterface)) { + throw new \Exception('ArchiverManager manage only ' . __NAMESPACE__ . '\\ArchiverInterface'); + } + + $this->archivers[$archiver->getId()] = $archiver; + } + + return $this; + } + + /** + * Add an archiver + * + * @param \Thelia\Core\Archiver\ArchiverInterface $archiver An archiver + * + * @return $this Return $this, allow chaining + */ + public function add(ArchiverInterface $archiver) + { + $this->archivers[$archiver->getId()] = $archiver; + + return $this; + } + + /** + * Remove an archiver + * + * @param string $archiverId An archiver identifier + */ + public function remove($archiverId) + { + $this->has($archiverId, true); + + unset($this->archivers[$archiverId]); + } +} diff --git a/core/lib/Thelia/Core/Bundle/TheliaBundle.php b/core/lib/Thelia/Core/Bundle/TheliaBundle.php new file mode 100644 index 00000000..348dc919 --- /dev/null +++ b/core/lib/Thelia/Core/Bundle/TheliaBundle.php @@ -0,0 +1,72 @@ + + */ + +class TheliaBundle extends Bundle +{ + /** + * + * Construct the depency injection builder + * + * @param \Symfony\Component\DependencyInjection\ContainerBuilder $container + */ + + public function build(ContainerBuilder $container) + { + parent::build($container); + + $container + ->addCompilerPass(new FallbackParserPass()) + ->addCompilerPass(new TranslatorPass()) + ->addCompilerPass(new RegisterHookListenersPass(), PassConfig::TYPE_AFTER_REMOVING) + ->addCompilerPass(new RegisterRouterPass()) + ->addCompilerPass(new RegisterCouponPass()) + ->addCompilerPass(new RegisterCouponConditionPass()) + ->addCompilerPass(new RegisterArchiverPass) + ->addCompilerPass(new RegisterAssetFilterPass()) + ->addCompilerPass(new RegisterSerializerPass) + ->addCompilerPass(new StackPass()) + ->addCompilerPass(new RegisterFormExtensionPass()) + ->addCompilerPass(new CurrencyConverterProviderPass()) + ->addCompilerPass(new RegisterListenersPass()) + ; + } +} diff --git a/core/lib/Thelia/Core/Controller/ControllerResolver.php b/core/lib/Thelia/Core/Controller/ControllerResolver.php new file mode 100644 index 00000000..32e04cac --- /dev/null +++ b/core/lib/Thelia/Core/Controller/ControllerResolver.php @@ -0,0 +1,92 @@ + + * @author Franck Allimant + */ +class ControllerResolver extends BaseControllerResolver +{ + protected $container; + + /** + * Constructor. + * + * @param ContainerInterface $container A ContainerInterface instance + * @param LoggerInterface $logger A LoggerInterface instance + */ + public function __construct(ContainerInterface $container, LoggerInterface $logger = null) + { + $this->container = $container; + + parent::__construct($logger); + } + + /** + * Returns a callable for the given controller. + * + * @param string $controller A Controller string + * + * @return mixed A PHP callable + * + * @throws \LogicException When the name could not be parsed + * @throws \InvalidArgumentException When the controller class does not exist + */ + protected function createController($controller) + { + if (false === strpos($controller, '::')) { + $count = substr_count($controller, ':'); + if (2 == $count) { + // controller in the a:b:c notation then + list($moduleName, $controllerName, $method) = explode(':', $controller, 3); + $class = $moduleName . '\\Controller\\' . $controllerName . 'Controller'; + $method .= 'Action'; + } elseif (1 == $count) { + // controller in the service:method notation + list($service, $method) = explode(':', $controller, 2); + + return array($this->container->get($service), $method); + } else { + throw new \LogicException(sprintf('Unable to parse the controller name "%s".', $controller)); + } + } else { + list($class, $method) = explode('::', $controller, 2); + } + + if (!class_exists($class)) { + throw new \InvalidArgumentException(sprintf('Class "%s" does not exist.', $class)); + } + + /** @var BaseController $controller */ + $controller = new $class(); + + $this->container->get('request_stack')->getCurrentRequest()->setControllerType( + $controller->getControllerType() + ); + + if (method_exists($controller, 'setContainer')) { + $controller->setContainer($this->container); + } + + return array($controller, $method); + } +} diff --git a/core/lib/Thelia/Core/DependencyInjection/Compiler/CurrencyConverterProviderPass.php b/core/lib/Thelia/Core/DependencyInjection/Compiler/CurrencyConverterProviderPass.php new file mode 100644 index 00000000..589258b0 --- /dev/null +++ b/core/lib/Thelia/Core/DependencyInjection/Compiler/CurrencyConverterProviderPass.php @@ -0,0 +1,56 @@ + + */ +class CurrencyConverterProviderPass implements CompilerPassInterface +{ + /** + * You can modify the container here before it is dumped to PHP code. + * + * @param ContainerBuilder $container + * + * @api + */ + public function process(ContainerBuilder $container) + { + if (!$container->hasDefinition('currency.converter')) { + return; + } + + $currencyConverter = $container->getDefinition('currency.converter'); + $services = $container->findTaggedServiceIds('currency.converter.provider'); + + $providers = []; + + foreach ($services as $id => $attributes) { + $priority = isset($attributes[0]['priority']) ? $attributes[0]['priority'] : 0; + $providers[$priority] = $id; + } + + if (false === empty($providers)) { + $service = array_pop($providers); + $currencyConverter->addMethodCall('setProvider', [new Reference($service)]); + } else { + throw new \LogicException('the currency converter needs a provider, please define one'); + } + } +} diff --git a/core/lib/Thelia/Core/DependencyInjection/Compiler/FallbackParserPass.php b/core/lib/Thelia/Core/DependencyInjection/Compiler/FallbackParserPass.php new file mode 100644 index 00000000..d8327cc7 --- /dev/null +++ b/core/lib/Thelia/Core/DependencyInjection/Compiler/FallbackParserPass.php @@ -0,0 +1,47 @@ + + */ +class FallbackParserPass implements CompilerPassInterface +{ + /** + * You can modify the container here before it is dumped to PHP code. + * + * @param ContainerBuilder $container + * + * @api + */ + public function process(ContainerBuilder $container) + { + if ($container->has('thelia.parser')) { + return; + } + + $container->addDefinitions( + [ + 'thelia.parser' => new Definition("Thelia\\Core\\Template\\Parser\\ParserFallback"), + 'thelia.parser.helper' => new Definition("Thelia\\Core\\Template\\Parser\\ParserHelperFallback"), + 'thelia.parser.asset.resolver' => new Definition("Thelia\\Core\\Template\\Parser\\ParserHelperFallback") + ] + ); + } +} diff --git a/core/lib/Thelia/Core/DependencyInjection/Compiler/RegisterArchiverPass.php b/core/lib/Thelia/Core/DependencyInjection/Compiler/RegisterArchiverPass.php new file mode 100644 index 00000000..bf7cbc90 --- /dev/null +++ b/core/lib/Thelia/Core/DependencyInjection/Compiler/RegisterArchiverPass.php @@ -0,0 +1,54 @@ + + * @author Jérôme Billiras + */ +class RegisterArchiverPass implements CompilerPassInterface +{ + /** + * @var string Archiver manager service ID + */ + const MANAGER_SERVICE_ID = 'thelia.archiver.manager'; + + /** + * @var string Archiver tag name + */ + const ARCHIVER_SERVICE_TAG = 'thelia.archiver'; + + public function process(ContainerBuilder $container) + { + try { + $manager = $container->getDefinition(self::MANAGER_SERVICE_ID); + } catch (InvalidArgumentException $e) { + return; + } + + foreach (array_keys($container->findTaggedServiceIds(self::ARCHIVER_SERVICE_TAG)) as $serviceId) { + $manager->addMethodCall( + 'add', + [ + new Reference($serviceId) + ] + ); + } + } +} diff --git a/core/lib/Thelia/Core/DependencyInjection/Compiler/RegisterAssetFilterPass.php b/core/lib/Thelia/Core/DependencyInjection/Compiler/RegisterAssetFilterPass.php new file mode 100644 index 00000000..e792c5b5 --- /dev/null +++ b/core/lib/Thelia/Core/DependencyInjection/Compiler/RegisterAssetFilterPass.php @@ -0,0 +1,73 @@ + + */ +class RegisterAssetFilterPass implements CompilerPassInterface +{ + const MANAGER_DEFINITION = "assetic.asset.manager"; + + const SERVICE_TAG = "thelia.asset.filter"; + + /** + * You can modify the container here before it is dumped to PHP code. + * + * @param ContainerBuilder $container Container + * + * @api + */ + public function process(ContainerBuilder $container) + { + if (!$container->hasDefinition(static::MANAGER_DEFINITION)) { + return; + } + + $manager = $container->getDefinition(static::MANAGER_DEFINITION); + $services = $container->findTaggedServiceIds(static::SERVICE_TAG); + + foreach ($services as $id => $attributes) { + if (! isset($attributes[0]['key']) || empty($attributes[0]['key'])) { + throw new \InvalidArgumentException( + sprintf( + 'Service "%s" must define the "key" attribute on "thelia.asset.filter" tag.', + $id + ) + ); + } + + $class = $container->getDefinition($id)->getClass(); + + if (! is_subclass_of($class, '\Assetic\Filter\FilterInterface')) { + throw new \InvalidArgumentException( + sprintf( + 'Service "%s" should implement the \Assetic\Filter\FilterInterface interface', + $id + ) + ); + } + + $manager->addMethodCall( + 'registerAssetFilter', + [ $attributes[0]['key'], new Reference($id) ] + ); + } + } +} diff --git a/core/lib/Thelia/Core/DependencyInjection/Compiler/RegisterCouponConditionPass.php b/core/lib/Thelia/Core/DependencyInjection/Compiler/RegisterCouponConditionPass.php new file mode 100644 index 00000000..123a881b --- /dev/null +++ b/core/lib/Thelia/Core/DependencyInjection/Compiler/RegisterCouponConditionPass.php @@ -0,0 +1,56 @@ + + * + */ +class RegisterCouponConditionPass implements CompilerPassInterface +{ + /** + * You can modify the container here before it is dumped to PHP code. + * + * @param ContainerBuilder $container Container + * + * @api + */ + public function process(ContainerBuilder $container) + { + if (!$container->hasDefinition('thelia.coupon.manager')) { + return; + } + + $couponManager = $container->getDefinition('thelia.coupon.manager'); + $services = $container->findTaggedServiceIds("thelia.coupon.addCondition"); + + foreach ($services as $id => $condition) { + $couponManager->addMethodCall( + 'addAvailableCondition', + array( + new Reference($id) + ) + ); + } + } +} diff --git a/core/lib/Thelia/Core/DependencyInjection/Compiler/RegisterCouponPass.php b/core/lib/Thelia/Core/DependencyInjection/Compiler/RegisterCouponPass.php new file mode 100644 index 00000000..3da3a293 --- /dev/null +++ b/core/lib/Thelia/Core/DependencyInjection/Compiler/RegisterCouponPass.php @@ -0,0 +1,54 @@ + + * + */ +class RegisterCouponPass implements CompilerPassInterface +{ + /** + * You can modify the container here before it is dumped to PHP code. + * + * @param ContainerBuilder $container Container + * + * @api + */ + public function process(ContainerBuilder $container) + { + if (!$container->hasDefinition('thelia.coupon.manager')) { + return; + } + + $couponManager = $container->getDefinition('thelia.coupon.manager'); + $services = $container->findTaggedServiceIds("thelia.coupon.addCoupon"); + + foreach ($services as $id => $rule) { + $couponManager->addMethodCall( + 'addAvailableCoupon', + array( + new Reference($id) + ) + ); + } + } +} diff --git a/core/lib/Thelia/Core/DependencyInjection/Compiler/RegisterFormExtensionPass.php b/core/lib/Thelia/Core/DependencyInjection/Compiler/RegisterFormExtensionPass.php new file mode 100644 index 00000000..aa7a95aa --- /dev/null +++ b/core/lib/Thelia/Core/DependencyInjection/Compiler/RegisterFormExtensionPass.php @@ -0,0 +1,66 @@ + + */ +class RegisterFormExtensionPass implements CompilerPassInterface +{ + /** + * You can modify the container here before it is dumped to PHP code. + * + * @param ContainerBuilder $container + * + * @api + */ + public function process(ContainerBuilder $container) + { + if (!$container->hasDefinition("thelia.form_factory_builder")) { + return; + } + + $formFactoryBuilderDefinition = $container->getDefinition("thelia.form_factory_builder"); + + /** + * Add form extensions + */ + foreach ($container->findTaggedServiceIds("thelia.forms.extension") as $id => $definition) { + $formFactoryBuilderDefinition + ->addMethodCall("addExtension", [new Reference($id)]); + } + + /** + * And form types + */ + foreach ($container->findTaggedServiceIds("thelia.form.type") as $id => $definition) { + $formFactoryBuilderDefinition + ->addMethodCall("addType", [new Reference($id)]); + } + + /** + * And form type extensions + */ + foreach ($container->findTaggedServiceIds("thelia.form.type_extension") as $id => $definition) { + $formFactoryBuilderDefinition + ->addMethodCall("addTypeExtension", [new Reference($id)]); + } + } +} diff --git a/core/lib/Thelia/Core/DependencyInjection/Compiler/RegisterHookListenersPass.php b/core/lib/Thelia/Core/DependencyInjection/Compiler/RegisterHookListenersPass.php new file mode 100644 index 00000000..67a73c4e --- /dev/null +++ b/core/lib/Thelia/Core/DependencyInjection/Compiler/RegisterHookListenersPass.php @@ -0,0 +1,421 @@ + + */ +class RegisterHookListenersPass implements CompilerPassInterface +{ + protected $debugEnabled; + + public function process(ContainerBuilder $container) + { + if (!$container->hasDefinition('event_dispatcher')) { + return; + } + + $definition = $container->getDefinition('event_dispatcher'); + + // We have to check if Propel is initialized before registering hooks + $managers = Propel::getServiceContainer()->getConnectionManagers(); + if (! array_key_exists('thelia', $managers)) { + return; + } + + $this->debugEnabled = $container->getParameter("kernel.debug"); + + if (true === version_compare(ConfigQuery::getTheliaSimpleVersion(), '2.1.0', ">=")) { + $this->processHook($container, $definition); + } + } + + protected function logAlertMessage($message, $failSafe = false) + { + Tlog::getInstance()->addAlert($message); + + if (!$failSafe && $this->debugEnabled) { + throw new \InvalidArgumentException($message); + } + } + + protected function processHook(ContainerBuilder $container, $definition) + { + foreach ($container->findTaggedServiceIds('hook.event_listener') as $id => $events) { + $class = $container->getDefinition($id)->getClass(); + + // the class must extends BaseHook + $implementClass = HookDefinition::BASE_CLASS; + if (! is_subclass_of($class, $implementClass)) { + throw new \InvalidArgumentException(sprintf('Hook class "%s" must extends class "%s".', $class, $implementClass)); + } + + // retrieve the module id + $properties = $container->getDefinition($id)->getProperties(); + $module = null; + if (array_key_exists('module', $properties)) { + $moduleCode = explode(".", $properties['module'])[1]; + $module = ModuleQuery::create()->findOneByCode($moduleCode); + } + + foreach ($events as $hookAttributes) { + $this->registerHook($class, $module, $id, $hookAttributes); + } + } + + // now we can add listeners for active hooks and active module + $this->addHooksMethodCall($container, $definition); + } + + /** + * Create a new hook if the hook definition is valid. + * + * @param string $class the namespace of the class + * @param \Thelia\Model\Module $module the module + * @param string $id the service (hook) id + * @param array $attributes the hook attributes + * + * @throws \InvalidArgumentException + */ + protected function registerHook($class, $module, $id, $attributes) + { + if (!isset($attributes['event'])) { + throw new \InvalidArgumentException(sprintf('Service "%s" must define the "event" attribute on "hook.event_listener" tags.', $id)); + } + + $active = isset($attributes['active']) ? \intval($attributes['active']) : 1; + $attributes['active'] = (1 === $active); + $attributes['templates'] = isset($attributes['templates']) ? \strval($attributes['templates']) : ''; + $attributes['type'] = (isset($attributes['type'])) ? $this->getHookType($attributes['type']) : TemplateDefinition::FRONT_OFFICE; + + if (null === $hook = $this->getHook($attributes['event'], $attributes['type'])) { + return; + } + + $attributes = $this->getMethodName($attributes); + + // test if method exists + $validMethod = true; + if (! $this->isValidHookMethod($class, $attributes['method'], $hook->getBlock())) { + $validMethod = false; + } + + // test if hook is already registered in ModuleHook + $moduleHook = ModuleHookQuery::create() + ->filterByModuleId($module->getId()) + ->filterByHook($hook) + ->filterByMethod($attributes['method']) + ->findOne(); + + if (null === $moduleHook) { + if (!$validMethod) { + $this->logAlertMessage( + sprintf( + "Module [%s] could not be registered hook [%s], method [%s] is not reachable.", + $module->getCode(), + $attributes['event'], + $attributes['method'] + ) + ); + return; + } + + // Assign the module to the hook only if it has not been "deleted" + $ignoreCount = IgnoredModuleHookQuery::create() + ->filterByHook($hook) + ->filterByModuleId($module->getId()) + ->count(); + + if (0 === $ignoreCount) { + // hook for module doesn't exist, we add it with default registered values + $moduleHook = new ModuleHook(); + + $moduleHook->setHook($hook) + ->setModuleId($module->getId()) + ->setClassname($id) + ->setMethod($attributes['method']) + ->setActive($active) + ->setHookActive(true) + ->setModuleActive(true) + ->setPosition(ModuleHook::MAX_POSITION); + + if (isset($attributes['templates'])) { + $moduleHook->setTemplates($attributes['templates']); + } + + $moduleHook->save(); + } + } else { + if (!$validMethod) { + $this->logAlertMessage( + sprintf( + "Module [%s] could not use hook [%s], method [%s] is not reachable anymore.", + $module->getCode(), + $attributes['event'], + $attributes['method'] + ) + ); + + $moduleHook + ->setHookActive(false) + ->save(); + } else { + //$moduleHook->setTemplates($attributes['templates']); + + // Update hook if id was changed in the definition + if ($moduleHook->getClassname() != $id) { + $moduleHook + ->setClassname($id); + } + + $moduleHook->save(); + } + } + } + + + /** + * First the new hooks are positioning next to the last module hook. + * Next, if the module, hook and module hook is active, a new listener is + * added to the service definition. + * + * @param ContainerBuilder $container + * @param Definition $definition The service definition + */ + protected function addHooksMethodCall(ContainerBuilder $container, Definition $definition) + { + $moduleHooks = ModuleHookQuery::create() + ->orderByHookId() + ->orderByPosition() + ->orderById() + ->find(); + + $modulePosition = 0; + $hookId = 0; + /** @var ModuleHook $moduleHook */ + foreach ($moduleHooks as $moduleHook) { + // check if class and method exists + if (!$container->hasDefinition($moduleHook->getClassname())) { + continue; + } + + $hook = $moduleHook->getHook(); + + if (!$this->isValidHookMethod( + $container->getDefinition($moduleHook->getClassname())->getClass(), + $moduleHook->getMethod(), + $hook->getBlock(), + true + ) + ) { + $moduleHook->delete(); + continue; + } + + // manage module hook position for new hook + if ($hookId !== $moduleHook->getHookId()) { + $hookId = $moduleHook->getHookId(); + $modulePosition = 1; + } else { + $modulePosition++; + } + + if ($moduleHook->getPosition() === ModuleHook::MAX_POSITION) { + // new module hook, we set it at the end of the queue for this event + $moduleHook->setPosition($modulePosition)->save(); + } else { + $modulePosition = $moduleHook->getPosition(); + } + + // Add the the new listener for active hooks, we have to reverse the priority and the position + if ($moduleHook->getActive() && $moduleHook->getModuleActive() && $moduleHook->getHookActive()) { + $eventName = sprintf('hook.%s.%s', $hook->getType(), $hook->getCode()); + + // we a register an event which is relative to a specific module + if ($hook->getByModule()) { + $eventName .= '.' . $moduleHook->getModuleId(); + } + + $definition->addMethodCall( + 'addListenerService', + array( + $eventName, + array($moduleHook->getClassname(), $moduleHook->getMethod()), + ModuleHook::MAX_POSITION - $moduleHook->getPosition() + ) + ); + + if ($moduleHook->getTemplates()) { + if ($container->hasDefinition($moduleHook->getClassname())) { + $moduleHookEventName = 'hook.' . $hook->getType() . '.' . $hook->getCode(); + if (true === $moduleHook->getHook()->getByModule()) { + $moduleHookEventName .= '.' . $moduleHook->getModuleId(); + } + $container + ->getDefinition($moduleHook->getClassname()) + ->addMethodCall( + 'addTemplate', + array( + $moduleHookEventName, + $moduleHook->getTemplates() + ) + ) + ; + } + } + } + } + } + + + /** + * get the hook type according to the type attribute of the hook tag + * + * @param string $name + * + * @return int the hook type + */ + protected function getHookType($name) + { + $type = TemplateDefinition::FRONT_OFFICE; + + if (null !== $name && \is_string($name)) { + $name = preg_replace("[^a-z]", "", strtolower(trim($name))); + if (\in_array($name, array('bo', 'back', 'backoffice'))) { + $type = TemplateDefinition::BACK_OFFICE; + } elseif (\in_array($name, array('email'))) { + $type = TemplateDefinition::EMAIL; + } elseif (\in_array($name, array('pdf'))) { + $type = TemplateDefinition::PDF; + } + } + + return $type; + } + + /** + * GfilterByCode($hookName) + ->filterByType($hookType) + ->findOne(); + + if (null === $hook) { + $this->logAlertMessage(sprintf("Hook %s is unknown.", $hookName)); + + return null; + } + + if (! $hook->getActivate()) { + $this->logAlertMessage(sprintf("Hook %s is not activated.", $hookName), true); + } + + return $hook; + } + + /** + * Test if the method that will handled the hook is valid + * + * @param string $className the namespace of the class + * @param string $methodName the method name + * @param bool $block tell if the hook is a block or a function + * + * @return bool + */ + protected function isValidHookMethod($className, $methodName, $block, $failSafe = false) + { + try { + $method = new ReflectionMethod($className, $methodName); + + $parameters = $method->getParameters(); + + $eventType = ($block) ? + HookDefinition::RENDER_BLOCK_EVENT : + HookDefinition::RENDER_FUNCTION_EVENT; + + if (!($parameters[0]->getClass()->getName() == $eventType || is_subclass_of($parameters[0]->getClass()->getName(), $eventType))) { + $this->logAlertMessage(sprintf("Method %s should use an event of type %s. found: %s", $methodName, $eventType, $parameters[0]->getClass()->getName())); + + return false; + } + } catch (ReflectionException $ex) { + $this->logAlertMessage( + sprintf("Method %s does not exist in %s : %s", $methodName, $className, $ex), + $failSafe + ); + + return false; + } + + return true; + } + + /** + * @param $event + * @return mixed + */ + protected function getMethodName($event) + { + if (!isset($event['method'])) { + if (!empty($event['templates'])) { + $event['method'] = BaseHook::INJECT_TEMPLATE_METHOD_NAME; + return $event; + } else { + $callback = function ($matches) { + return strtoupper($matches[0]); + }; + $event['method'] = 'on' . preg_replace_callback( + array( + '/(?<=\b)[a-z]/i', + '/[^a-z0-9]/i', + ), + $callback, + $event['event'] + ); + $event['method'] = preg_replace('/[^a-z0-9]/i', '', $event['method']); + return $event; + } + } + + return $event; + } +} diff --git a/core/lib/Thelia/Core/DependencyInjection/Compiler/RegisterRouterPass.php b/core/lib/Thelia/Core/DependencyInjection/Compiler/RegisterRouterPass.php new file mode 100644 index 00000000..7eb9d782 --- /dev/null +++ b/core/lib/Thelia/Core/DependencyInjection/Compiler/RegisterRouterPass.php @@ -0,0 +1,87 @@ + + */ +class RegisterRouterPass implements CompilerPassInterface +{ + /** + * You can modify the container here before it is dumped to PHP code. + * + * @param ContainerBuilder $container + * + * @api + */ + public function process(ContainerBuilder $container) + { + try { + $chainRouter = $container->getDefinition("router.chainRequest"); + } catch (InvalidArgumentException $e) { + return; + } + + foreach ($container->findTaggedServiceIds("router.register") as $id => $attributes) { + $priority = isset($attributes[0]["priority"]) ? $attributes[0]["priority"] : 0; + $router = $container->getDefinition($id); + $router->addMethodCall("setOption", array("matcher_cache_class", $container::camelize("ProjectUrlMatcher".$id))); + $router->addMethodCall("setOption", array("generator_cache_class", $container::camelize("ProjectUrlGenerator".$id))); + + $chainRouter->addMethodCall("add", array(new Reference($id), $priority)); + } + if (\defined("THELIA_INSTALL_MODE") === false) { + $modules = ModuleQuery::getActivated(); + + /** @var Module $module */ + foreach ($modules as $module) { + $moduleBaseDir = $module->getBaseDir(); + $routingConfigFilePath = $module->getAbsoluteBaseDir() . DS . "Config" . DS . "routing.xml"; + + if (file_exists($routingConfigFilePath)) { + $definition = new Definition( + $container->getParameter("router.class"), + array( + new Reference("router.module.xmlLoader"), + $routingConfigFilePath, + array( + "cache_dir" => $container->getParameter("kernel.cache_dir"), + "debug" => $container->getParameter("kernel.debug"), + "matcher_cache_class" => $container::camelize("ProjectUrlMatcher".$moduleBaseDir), + "generator_cache_class" => $container::camelize("ProjectUrlGenerator".$moduleBaseDir), + ), + new Reference("request.context") + ) + ); + + $container->setDefinition("router.".$moduleBaseDir, $definition); + + $chainRouter->addMethodCall("add", array(new Reference("router.".$moduleBaseDir), 150 + $module->getPosition())); + } + } + } + } +} diff --git a/core/lib/Thelia/Core/DependencyInjection/Compiler/RegisterSerializerPass.php b/core/lib/Thelia/Core/DependencyInjection/Compiler/RegisterSerializerPass.php new file mode 100644 index 00000000..e3766be0 --- /dev/null +++ b/core/lib/Thelia/Core/DependencyInjection/Compiler/RegisterSerializerPass.php @@ -0,0 +1,54 @@ + + * @author Jérôme Billiras + */ +class RegisterSerializerPass implements CompilerPassInterface +{ + /** + * @var string Serializer manager service ID + */ + const MANAGER_SERVICE_ID = 'thelia.serializer.manager'; + + /** + * @var string Serializer tag name + */ + const SERIALIZER_SERVICE_TAG = 'thelia.serializer'; + + public function process(ContainerBuilder $container) + { + try { + $manager = $container->getDefinition(self::MANAGER_SERVICE_ID); + } catch (InvalidArgumentException $e) { + return; + } + + foreach (array_keys($container->findTaggedServiceIds(self::SERIALIZER_SERVICE_TAG)) as $serviceId) { + $manager->addMethodCall( + 'add', + [ + new Reference($serviceId) + ] + ); + } + } +} diff --git a/core/lib/Thelia/Core/DependencyInjection/Compiler/StackPass.php b/core/lib/Thelia/Core/DependencyInjection/Compiler/StackPass.php new file mode 100644 index 00000000..1e12aa1f --- /dev/null +++ b/core/lib/Thelia/Core/DependencyInjection/Compiler/StackPass.php @@ -0,0 +1,71 @@ + + */ +class StackPass implements CompilerPassInterface +{ + /** + * You can modify the container here before it is dumped to PHP code. + * + * @param ContainerBuilder $container + * + * @api + */ + public function process(ContainerBuilder $container) + { + if (!$container->hasDefinition('stack_factory')) { + return; + } + + $stackFactory = $container->getDefinition('stack_factory'); + $stackPriority = []; + + foreach ($container->findTaggedServiceIds('stack_middleware') as $id => $attributes) { + $priority = isset($attributes[0]['priority']) ? $attributes[0]['priority'] : 0; + $stackPriority[$priority][] = $this->retrieveArguments($container, $id); + } + + if (false === empty($stackPriority)) { + $this->addMiddlewares($stackFactory, $stackPriority); + } + } + + protected function addMiddlewares(Definition $stackFactory, $stackMiddlewares) + { + krsort($stackMiddlewares); + + foreach ($stackMiddlewares as $priority => $stacks) { + foreach ($stacks as $arguments) { + $stackFactory->addMethodCall('push', $arguments); + } + } + } + + protected function retrieveArguments(ContainerBuilder $container, $id) + { + $definition = $container->getDefinition($id); + $arguments = $definition->getArguments(); + array_unshift($arguments, $definition->getClass()); + + return $arguments; + } +} diff --git a/core/lib/Thelia/Core/DependencyInjection/Compiler/TranslatorPass.php b/core/lib/Thelia/Core/DependencyInjection/Compiler/TranslatorPass.php new file mode 100644 index 00000000..0cf2f21f --- /dev/null +++ b/core/lib/Thelia/Core/DependencyInjection/Compiler/TranslatorPass.php @@ -0,0 +1,48 @@ + + */ +class TranslatorPass implements CompilerPassInterface +{ + /** + * You can modify the container here before it is dumped to PHP code. + * + * @param ContainerBuilder $container + * + * @api + */ + public function process(ContainerBuilder $container) + { + if (!$container->hasDefinition('thelia.translator')) { + return; + } + + $translator = $container->getDefinition('thelia.translator'); + + foreach ($container->findTaggedServiceIds('translation.loader') as $id => $attributes) { + $translator->addMethodCall('addLoader', array($attributes[0]['alias'], new Reference($id))); + if (isset($attributes[0]['legacy-alias'])) { + $translator->addMethodCall('addLoader', array($attributes[0]['legacy-alias'], new Reference($id))); + } + } + } +} diff --git a/core/lib/Thelia/Core/DependencyInjection/Loader/XmlFileLoader.php b/core/lib/Thelia/Core/DependencyInjection/Loader/XmlFileLoader.php new file mode 100644 index 00000000..7e891b47 --- /dev/null +++ b/core/lib/Thelia/Core/DependencyInjection/Loader/XmlFileLoader.php @@ -0,0 +1,795 @@ + + */ +class XmlFileLoader extends FileLoader +{ + const DEFAULT_HOOK_CLASS = "Thelia\\Core\\Hook\\DefaultHook"; + + /** + * Loads an XML file. + * + * @param mixed $file The resource + * @param string $type The resource type + */ + public function load($file, $type = null) + { + $path = $this->locator->locate($file); + + $xml = $this->parseFile($path); + $xml->registerXPathNamespace('config', 'http://thelia.net/schema/dic/config'); + + $this->removeScope($xml); + + $this->container->addResource(new FileResource($path)); + + $this->parseLoops($xml); + + $this->parseFilters($xml); + + $this->parseTemplateDirectives($xml); + + $this->parseParameters($xml); + + $this->parseCommands($xml); + + $this->parseForms($xml); + + $this->parseDefinitions($xml, $path); + + $this->parseHooks($xml, $path, $type); + + $this->propelOnlyRun( + [$this, "parseExportCategories"], + $xml + ); + + $this->propelOnlyRun( + [$this, "parseExports"], + $xml + ); + + $this->propelOnlyRun( + [$this, "parseImportCategories"], + $xml + ); + + $this->propelOnlyRun( + [$this, "parseImports"], + $xml + ); + } + + public function propelOnlyRun(callable $method, $arg) + { + if (Thelia::isInstalled()) { + \call_user_func($method, $arg); + } + } + + protected function parseCommands(SimpleXMLElement $xml) + { + if (false === $commands = $xml->xpath('//config:commands/config:command')) { + return; + } + try { + $commandConfig = $this->container->getParameter("command.definition"); + } catch (ParameterNotFoundException $e) { + $commandConfig = array(); + } + + foreach ($commands as $command) { + array_push($commandConfig, $this->getAttributeAsPhp($command, "class")); + } + + $this->container->setParameter("command.definition", $commandConfig); + } + + /** + * Parses parameters + * + * @param SimpleXMLElement $xml + */ + protected function parseParameters(SimpleXMLElement $xml) + { + if (!$xml->parameters) { + return; + } + + $this->container->getParameterBag()->add($this->getArgumentsAsPhp($xml->parameters, 'parameter')); + } + + /** + * + * parse Loops property + * + * @param SimpleXMLElement $xml + */ + protected function parseLoops(SimpleXMLElement $xml) + { + if (false === $loops = $xml->xpath('//config:loops/config:loop')) { + return; + } + try { + $loopConfig = $this->container->getParameter("Thelia.parser.loops"); + } catch (ParameterNotFoundException $e) { + $loopConfig = array(); + } + + foreach ($loops as $loop) { + $loopConfig[$this->getAttributeAsPhp($loop, "name")] = $this->getAttributeAsPhp($loop, "class"); + } + + $this->container->setParameter("Thelia.parser.loops", $loopConfig); + } + + protected function parseForms(SimpleXMLElement $xml) + { + if (false === $forms = $xml->xpath('//config:forms/config:form')) { + return; + } + + try { + $formConfig = $this->container->getParameter("Thelia.parser.forms"); + } catch (ParameterNotFoundException $e) { + $formConfig = array(); + } + + foreach ($forms as $form) { + $formConfig[$this->getAttributeAsPhp($form, 'name')] = $this->getAttributeAsPhp($form, 'class'); + } + + $this->container->setParameter('Thelia.parser.forms', $formConfig); + } + + /** + * parse Filters property + * + * @param SimpleXMLElement $xml + */ + protected function parseFilters(SimpleXMLElement $xml) + { + if (false === $filters = $xml->xpath('//config:filters/config:filter')) { + return; + } + try { + $filterConfig = $this->container->getParameter("Thelia.parser.filters"); + } catch (ParameterNotFoundException $e) { + $filterConfig = array(); + } + + foreach ($filters as $filter) { + $filterConfig[$this->getAttributeAsPhp($filter, "name")] = $this->getAttributeAsPhp($filter, "class"); + } + + $this->container->setParameter("Thelia.parser.filters", $filterConfig); + } + + /** + * parse BaseParams property + * + * @param SimpleXMLElement $xml + */ + protected function parseTemplateDirectives(SimpleXMLElement $xml) + { + if (false === $baseParams = $xml->xpath('//config:templateDirectives/config:templateDirective')) { + return; + } + try { + $baseParamConfig = $this->container->getParameter("Thelia.parser.templateDirectives"); + } catch (ParameterNotFoundException $e) { + $baseParamConfig = array(); + } + + foreach ($baseParams as $baseParam) { + $baseParamConfig[$this->getAttributeAsPhp($baseParam, "name")] = $this->getAttributeAsPhp($baseParam, "class"); + } + + $this->container->setParameter("Thelia.parser.templateDirectives", $baseParamConfig); + } + + /** + * Parses multiple definitions + * + * @param SimpleXMLElement $xml + * @param string $file + */ + protected function parseDefinitions(SimpleXMLElement $xml, $file) + { + if (false === $services = $xml->xpath('//config:services/config:service')) { + return; + } + foreach ($services as $service) { + $this->parseDefinition((string) $service['id'], $service, $file); + } + } + + protected function parseDefinition($id, $service, $file) + { + $definition = $this->parseService($id, $service, $file); + if (null !== $definition) { + $this->container->setDefinition($id, $definition); + } + } + + /** + * Parses multiple definitions + * + * @param SimpleXMLElement $xml + * @param string $file + * @param string $type + */ + protected function parseHooks(SimpleXMLElement $xml, $file, $type) + { + if (false === $hooks = $xml->xpath('//config:hooks/config:hook')) { + return; + } + foreach ($hooks as $hook) { + $this->parseHook((string) $hook['id'], $hook, $file, $type); + } + } + + protected function parseHook($id, $hook, $file, $type) + { + if (! isset($hook['class'])) { + $hook['class'] = self::DEFAULT_HOOK_CLASS; + } + + $definition = $this->parseService($id, $hook, $file); + if (null !== $definition) { + if (null !== $type) { + // inject the BaseModule + $definition->setProperty('module', new Reference($type)); + } + $definition->setProperty('parser', new Reference('thelia.parser')); + $definition->setProperty('translator', new Reference('thelia.translator')); + $definition->setProperty('assetsResolver', new Reference('thelia.parser.asset.resolver')); + $definition->setProperty('dispatcher', new Reference('event_dispatcher')); + $this->container->setDefinition($id, $definition); + } + } + + /** + * Parses an individual Definition + * + * @param string $id + * @param SimpleXMLElement $service + * @param string $file + * @return Definition + */ + protected function parseService($id, $service, $file) + { + if ((string) $service['alias']) { + $public = true; + if (isset($service['public'])) { + $public = $this->getAttributeAsPhp($service, 'public'); + } + $this->container->setAlias($id, new Alias((string) $service['alias'], $public)); + + return; + } + + if (isset($service['parent'])) { + $definition = new DefinitionDecorator((string) $service['parent']); + } else { + $definition = new Definition(); + } + + foreach (array('class', 'shared', 'scope', 'public', 'factory-class', 'factory-method', 'factory-service', 'synthetic', 'abstract') as $key) { + if (isset($service[$key])) { + $method = 'set'.str_replace('-', '', $key); + $definition->$method((string) $this->getAttributeAsPhp($service, $key)); + } + } + + if ($service->file) { + $definition->setFile((string) $service->file); + } + + $definition->setArguments($this->getArgumentsAsPhp($service, 'argument')); + $definition->setProperties($this->getArgumentsAsPhp($service, 'property')); + + if (isset($service->configurator)) { + if (isset($service->configurator['function'])) { + $definition->setConfigurator((string) $service->configurator['function']); + } else { + if (isset($service->configurator['service'])) { + $class = new Reference((string) $service->configurator['service'], ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE, false); + } else { + $class = (string) $service->configurator['class']; + } + + $definition->setConfigurator(array($class, (string) $service->configurator['method'])); + } + } + + foreach ($service->call as $call) { + $definition->addMethodCall((string) $call['method'], $this->getArgumentsAsPhp($call, 'argument')); + } + + foreach ($service->tag as $tag) { + $parameters = array(); + foreach ($tag->attributes() as $name => $value) { + if ('name' === $name) { + continue; + } + + $parameters[$name] = XmlUtils::phpize($value); + } + + $definition->addTag((string) $tag['name'], $parameters); + } + + return $definition; + } + + protected function parseExportCategories(SimpleXMLElement $xml) + { + if (false === $exportCategories = $xml->xpath('//config:export_categories/config:export_category')) { + return; + } + + $con = Propel::getWriteConnection(ExportCategoryTableMap::DATABASE_NAME); + $con->beginTransaction(); + + try { + /** @var SimpleXMLElement $exportCategory */ + foreach ($exportCategories as $exportCategory) { + $id = (string) $this->getAttributeAsPhp($exportCategory, "id"); + + $exportCategoryModel = ExportCategoryQuery::create()->findOneByRef($id); + + if ($exportCategoryModel === null) { + $exportCategoryModel = new ExportCategory(); + $exportCategoryModel + ->setRef($id) + ->save($con) + ; + } + + /** @var SimpleXMLElement $child */ + foreach ($exportCategory->children() as $child) { + $locale = (string) $this->getAttributeAsPhp($child, "locale"); + $value = (string) $child; + + $exportCategoryModel + ->setLocale($locale) + ->setTitle($value) + ->save($con); + ; + } + } + + $con->commit(); + } catch (\Exception $e) { + $con->rollBack(); + + Tlog::getInstance()->error($e->getMessage()); + } + } + + protected function parseExports(SimpleXMLElement $xml) + { + if (false === $exports = $xml->xpath('//config:exports/config:export')) { + return; + } + + $con = Propel::getWriteConnection(ExportTableMap::DATABASE_NAME); + $con->beginTransaction(); + + try { + /** @var SimpleXMLElement $export */ + foreach ($exports as $export) { + $id = (string) $this->getAttributeAsPhp($export, "id"); + $class = (string) $this->getAttributeAsPhp($export, "class"); + $categoryRef = (string) $this->getAttributeAsPhp($export, "category_id"); + + if (!class_exists($class)) { + throw new \ErrorException( + "The class \"$class\" doesn't exist" + ); + } + + $category = ExportCategoryQuery::create()->findOneByRef($categoryRef); + + if (null === $category) { + throw new \ErrorException( + "The export category \"$categoryRef\" doesn't exist" + ); + } + + $exportModel = ExportQuery::create()->findOneByRef($id); + + if (null === $exportModel) { + $exportModel = new Export(); + $exportModel + ->setRef($id) + ; + } + + $exportModel + ->setExportCategory($category) + ->setHandleClass($class) + ->save($con) + ; + + /** @var SimpleXMLElement $descriptive */ + foreach ($export->children() as $descriptive) { + $locale = $this->getAttributeAsPhp($descriptive, "locale"); + $title = null; + $description = null; + + /** @var SimpleXMLElement $row */ + foreach ($descriptive->children() as $row) { + switch ($row->getName()) { + case "title": + $title = (string) $row; + break; + case "description": + $description = (string) $row; + break; + } + } + + $exportModel + ->setLocale($locale) + ->setTitle($title) + ->setDescription($description) + ->save($con) + ; + } + } + + $con->commit(); + } catch (\Exception $e) { + $con->rollBack(); + + Tlog::getInstance()->error($e->getMessage()); + } + } + + protected function parseImportCategories(SimpleXMLElement $xml) + { + if (false === $importCategories = $xml->xpath('//config:import_categories/config:import_category')) { + return; + } + + $con = Propel::getWriteConnection(ImportCategoryTableMap::DATABASE_NAME); + $con->beginTransaction(); + + try { + /** @var SimpleXMLElement $importCategory */ + foreach ($importCategories as $importCategory) { + $id = (string) $this->getAttributeAsPhp($importCategory, "id"); + + $importCategoryModel = ImportCategoryQuery::create()->findOneByRef($id); + + if ($importCategoryModel === null) { + $importCategoryModel = new ImportCategory(); + $importCategoryModel + ->setRef($id) + ->save($con) + ; + } + + /** @var SimpleXMLElement $child */ + foreach ($importCategory->children() as $child) { + $locale = (string) $this->getAttributeAsPhp($child, "locale"); + $value = (string) $child; + + $importCategoryModel + ->setLocale($locale) + ->setTitle($value) + ->save($con); + ; + } + } + + $con->commit(); + } catch (\Exception $e) { + $con->rollBack(); + + Tlog::getInstance()->error($e->getMessage()); + } + } + + protected function parseImports(SimpleXMLElement $xml) + { + if (false === $imports = $xml->xpath('//config:imports/config:import')) { + return; + } + + $con = Propel::getWriteConnection(ImportTableMap::DATABASE_NAME); + $con->beginTransaction(); + + try { + /** @var SimpleXMLElement $import */ + foreach ($imports as $import) { + $id = (string) $this->getAttributeAsPhp($import, "id"); + $class = (string) $this->getAttributeAsPhp($import, "class"); + $categoryRef = (string) $this->getAttributeAsPhp($import, "category_id"); + + if (!class_exists($class)) { + throw new \ErrorException( + "The class \"$class\" doesn't exist" + ); + } + + $category = ImportCategoryQuery::create()->findOneByRef($categoryRef); + + if (null === $category) { + throw new \ErrorException( + "The import category \"$categoryRef\" doesn't exist" + ); + } + + $importModel = ImportQuery::create()->findOneByRef($id); + + if (null === $importModel) { + $importModel = new Import(); + $importModel + ->setRef($id) + ; + } + + $importModel + ->setImportCategory($category) + ->setHandleClass($class) + ->save($con) + ; + + /** @var SimpleXMLElement $descriptive */ + foreach ($import->children() as $descriptive) { + $locale = $this->getAttributeAsPhp($descriptive, "locale"); + $title = null; + $description = null; + + /** @var SimpleXMLElement $row */ + foreach ($descriptive->children() as $row) { + switch ($row->getName()) { + case "title": + $title = (string) $row; + break; + case "description": + $description = (string) $row; + break; + } + } + + $importModel + ->setLocale($locale) + ->setTitle($title) + ->setDescription($description) + ->save($con) + ; + } + } + + $con->commit(); + } catch (\Exception $e) { + $con->rollBack(); + + Tlog::getInstance()->error($e->getMessage()); + } + } + + /** + * Parses a XML file. + * + * @param string $file Path to a file + * + * @return SimpleXMLElement + * + * @throws InvalidArgumentException When loading of XML file returns error + */ + protected function parseFile($file) + { + try { + $dom = XmlUtils::loadFile($file, array($this, 'validateSchema')); + } catch (\InvalidArgumentException $e) { + throw new InvalidArgumentException($e->getMessage(), $e->getCode(), $e); + } + + return simplexml_import_dom($dom); + } + + /** + * Validates a documents XML schema. + * + * @param \DOMDocument $dom + * + * @return Boolean + * + * @throws RuntimeException When extension references a non-existent XSD file + */ + public function validateSchema(\DOMDocument $dom) + { + $schemaLocations = array('http://thelia.net/schema/dic/config' => str_replace('\\', '/', __DIR__.'/schema/dic/config/thelia-1.0.xsd')); + + $tmpfiles = array(); + $imports = ''; + foreach ($schemaLocations as $namespace => $location) { + $parts = explode('/', $location); + if (0 === stripos($location, 'phar://')) { + $tmpfile = tempnam(sys_get_temp_dir(), 'sf2'); + if ($tmpfile) { + copy($location, $tmpfile); + $tmpfiles[] = $tmpfile; + $parts = explode('/', str_replace('\\', '/', $tmpfile)); + } + } + $drive = '\\' === DIRECTORY_SEPARATOR ? array_shift($parts).'/' : ''; + $location = 'file:///'.$drive.implode('/', array_map('rawurlencode', $parts)); + + $imports .= sprintf(' '."\n", $namespace, $location); + } + + $source = << + + + +$imports + +EOF + ; + + $valid = @$dom->schemaValidateSource($source); + + foreach ($tmpfiles as $tmpfile) { + @unlink($tmpfile); + } + + return $valid; + } + + /** + * Returns true if this class supports the given resource. + * + * @param mixed $resource A resource + * @param string $type The resource type + * + * @return Boolean true if this class supports the given resource, false otherwise + */ + public function supports($resource, $type = null) + { + // TODO: Implement supports() method. + } + + /** + * Returns arguments as valid PHP types. + * + * @param SimpleXMLElement $xml + * @param $name + * @param bool $lowercase + * @return array + */ + private function getArgumentsAsPhp(SimpleXMLElement $xml, $name, $lowercase = true) + { + $arguments = array(); + foreach ($xml->$name as $arg) { + if (isset($arg['name'])) { + $arg['key'] = (string) $arg['name']; + } + $key = isset($arg['key']) ? (string) $arg['key'] : (!$arguments ? 0 : max(array_keys($arguments)) + 1); + + // parameter keys are case insensitive + if ('parameter' == $name && $lowercase) { + $key = strtolower($key); + } + + // this is used by DefinitionDecorator to overwrite a specific + // argument of the parent definition + if (isset($arg['index'])) { + $key = 'index_'.$arg['index']; + } + + switch ($arg['type']) { + case 'service': + $invalidBehavior = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE; + if (isset($arg['on-invalid']) && 'ignore' == $arg['on-invalid']) { + $invalidBehavior = ContainerInterface::IGNORE_ON_INVALID_REFERENCE; + } elseif (isset($arg['on-invalid']) && 'null' == $arg['on-invalid']) { + $invalidBehavior = ContainerInterface::NULL_ON_INVALID_REFERENCE; + } + + if (isset($arg['strict'])) { + $strict = XmlUtils::phpize($arg['strict']); + } else { + $strict = true; + } + + $arguments[$key] = new Reference((string) $arg['id'], $invalidBehavior, $strict); + break; + case 'expression': + $arguments[$key] = new Expression((string) $arg); + break; + case 'collection': + $arguments[$key] = $this->getArgumentsAsPhp($arg, $name, false); + break; + case 'string': + $arguments[$key] = (string) $arg; + break; + case 'constant': + $arguments[$key] = constant((string) $arg); + break; + default: + $arguments[$key] = XmlUtils::phpize($arg); + } + } + + return $arguments; + } + + /** + * Converts an attribute as a PHP type. + * + * @param SimpleXMLElement $xml + * @param $name + * @return mixed + */ + public function getAttributeAsPhp(SimpleXMLElement $xml, $name) + { + return XmlUtils::phpize($xml[$name]); + } + + private function removeScope(SimpleXMLElement $xml) + { + $nodes = $xml->xpath('//*[@scope]'); + + /** @var \DOMElement $node */ + foreach ($nodes as $node) { + unset($node['scope']); + } + } +} diff --git a/core/lib/Thelia/Core/DependencyInjection/Loader/schema/dic/config/thelia-1.0.xsd b/core/lib/Thelia/Core/DependencyInjection/Loader/schema/dic/config/thelia-1.0.xsd new file mode 100644 index 00000000..b4ca378e --- /dev/null +++ b/core/lib/Thelia/Core/DependencyInjection/Loader/schema/dic/config/thelia-1.0.xsd @@ -0,0 +1,380 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/core/lib/Thelia/Core/DependencyInjection/TheliaContainer.php b/core/lib/Thelia/Core/DependencyInjection/TheliaContainer.php new file mode 100644 index 00000000..3bc2c2ba --- /dev/null +++ b/core/lib/Thelia/Core/DependencyInjection/TheliaContainer.php @@ -0,0 +1,53 @@ + + * @since 2.3 + */ +class TheliaContainer extends Container +{ + /** + * @inheritdoc + */ + public function set($id, $service, $scope = self::SCOPE_CONTAINER) + { + if ($id === 'request' + && php_sapi_name() === "cli" + ) { + if (!isset($this->services['request_stack'])) { + $this->services['request_stack'] = new RequestStack(); + } + + /** @var RequestStack $requestStack */ + $requestStack = $this->services['request_stack']; + + if ($requestStack->getCurrentRequest() === null) { + @trigger_error('Request is deprecated as a service since Thelia 2.3. Please inject your Request in the RequestStack service.', E_USER_DEPRECATED); + /** @var Request $service */ + $requestStack->push($service); + } + } + + parent::set($id, $service, $scope); + } +} diff --git a/core/lib/Thelia/Core/Event/AccessoryEvent.php b/core/lib/Thelia/Core/Event/AccessoryEvent.php new file mode 100644 index 00000000..94e2d974 --- /dev/null +++ b/core/lib/Thelia/Core/Event/AccessoryEvent.php @@ -0,0 +1,45 @@ +accessory = $accessory; + } + + public function hasAccessory() + { + return ! \is_null($this->accessory); + } + + public function getAccessory() + { + return $this->accessory; + } + + public function setAccessory(Accessory $accessory) + { + $this->accessory = $accessory; + + return $this; + } +} diff --git a/core/lib/Thelia/Core/Event/ActionEvent.php b/core/lib/Thelia/Core/Event/ActionEvent.php new file mode 100644 index 00000000..ad51b2d0 --- /dev/null +++ b/core/lib/Thelia/Core/Event/ActionEvent.php @@ -0,0 +1,65 @@ +parameters[$name] = $value; + } + + public function __get($name) + { + if (array_key_exists($name, $this->parameters)) { + return $this->parameters[$name]; + } + + return null; + } + + public function bindForm(Form $form) + { + $fields = $form->getIterator(); + + /** @var \Symfony\Component\Form\Form $field */ + foreach ($fields as $field) { + $functionName = sprintf("set%s", Container::camelize($field->getName())); + if (method_exists($this, $functionName)) { + $getFunctionName = sprintf("get%s", Container::camelize($field->getName())); + if (method_exists($this, $getFunctionName)) { + if (null === $this->{$getFunctionName}()) { + $this->{$functionName}($field->getData()); + } + } else { + $this->{$functionName}($field->getData()); + } + } else { + $this->{$field->getName()} = $field->getData(); + } + } + } +} diff --git a/core/lib/Thelia/Core/Event/Address/AddressCreateOrUpdateEvent.php b/core/lib/Thelia/Core/Event/Address/AddressCreateOrUpdateEvent.php new file mode 100644 index 00000000..8289dc96 --- /dev/null +++ b/core/lib/Thelia/Core/Event/Address/AddressCreateOrUpdateEvent.php @@ -0,0 +1,297 @@ + + */ +class AddressCreateOrUpdateEvent extends ActionEvent +{ + /** + * @var string address label + */ + protected $label; + + /** + * @var int title id + */ + protected $title; + + /** + * @var string|null company name + */ + protected $company; + + /** + * @var string first name + */ + protected $firstname; + + /** + * @var string last name + */ + protected $lastname; + + /** + * @var string address + */ + protected $address1; + + /** + * @var string address line 2 + */ + protected $address2; + + /** + * @var string address line 3 + */ + protected $address3; + + /** + * @var string zipcode + */ + protected $zipcode; + + /** + * @var string city + */ + protected $city; + + /** + * @var int country id + */ + protected $country; + + /** + * @var int state id + */ + protected $state; + + /** + * @var string cell phone + */ + protected $cellphone; + + /** + * @var string phone + */ + protected $phone; + + /** + * @var \Thelia\Model\Customer + */ + protected $customer; + + /** + * @var \Thelia\Model\Address + */ + protected $address; + + /** + * @var int + */ + protected $isDefault; + + public function __construct( + $label, + $title, + $firstname, + $lastname, + $address1, + $address2, + $address3, + $zipcode, + $city, + $country, + $cellphone, + $phone, + $company, + $isDefault = 0, + $state = null + ) { + $this->address1 = $address1; + $this->address2 = $address2; + $this->address3 = $address3; + $this->cellphone = $cellphone; + $this->city = $city; + $this->company = $company; + $this->country = $country; + $this->state = $state; + $this->firstname = $firstname; + $this->label = $label; + $this->lastname = $lastname; + $this->phone = $phone; + $this->title = $title; + $this->zipcode = $zipcode; + $this->isDefault = $isDefault; + } + + /** + * @return string + */ + public function getAddress1() + { + return $this->address1; + } + + /** + * @return string + */ + public function getAddress2() + { + return $this->address2; + } + + /** + * @return string + */ + public function getAddress3() + { + return $this->address3; + } + + /** + * @return string + */ + public function getCellphone() + { + return $this->cellphone; + } + + /** + * @return string + */ + public function getCity() + { + return $this->city; + } + + /** + * @return null|string + */ + public function getCompany() + { + return $this->company; + } + + /** + * @return int + */ + public function getCountry() + { + return $this->country; + } + + /** + * @return int|null + */ + public function getState() + { + return $this->state; + } + + /** + * @return string + */ + public function getFirstname() + { + return $this->firstname; + } + + /** + * @return string + */ + public function getLabel() + { + return $this->label; + } + + /** + * @return string + */ + public function getLastname() + { + return $this->lastname; + } + + /** + * @return string + */ + public function getPhone() + { + return $this->phone; + } + + /** + * @return int + */ + public function getTitle() + { + return $this->title; + } + + /** + * @return string + */ + public function getZipcode() + { + return $this->zipcode; + } + + /** + * @return int + */ + public function getIsDefault() + { + return $this->isDefault; + } + + /** + * @param \Thelia\Model\Customer $customer + */ + public function setCustomer(Customer $customer) + { + $this->customer = $customer; + } + + /** + * @return \Thelia\Model\Customer + */ + public function getCustomer() + { + return $this->customer; + } + + /** + * @param \Thelia\Model\Address $address + */ + public function setAddress(Address $address) + { + $this->address = $address; + $this->setCustomer($address->getCustomer()); + } + + /** + * @return \Thelia\Model\Address + */ + public function getAddress() + { + return $this->address; + } +} diff --git a/core/lib/Thelia/Core/Event/Address/AddressEvent.php b/core/lib/Thelia/Core/Event/Address/AddressEvent.php new file mode 100644 index 00000000..760e36e2 --- /dev/null +++ b/core/lib/Thelia/Core/Event/Address/AddressEvent.php @@ -0,0 +1,40 @@ +address = $address; + } + + /** + * @return \Thelia\Model\Address + */ + public function getAddress() + { + return $this->address; + } +} diff --git a/core/lib/Thelia/Core/Event/Administrator/AdministratorEvent.php b/core/lib/Thelia/Core/Event/Administrator/AdministratorEvent.php new file mode 100644 index 00000000..c1cef4f6 --- /dev/null +++ b/core/lib/Thelia/Core/Event/Administrator/AdministratorEvent.php @@ -0,0 +1,159 @@ +administrator = $administrator; + } + + public function hasAdministrator() + { + return ! \is_null($this->administrator); + } + + public function getAdministrator() + { + return $this->administrator; + } + + public function setAdministrator(Admin $administrator) + { + $this->administrator = $administrator; + + return $this; + } + + public function setId($id) + { + $this->id = $id; + + return $this; + } + + public function getId() + { + return $this->id; + } + + public function setFirstname($firstname) + { + $this->firstname = $firstname; + + return $this; + } + + public function getFirstname() + { + return $this->firstname; + } + + public function setLastname($lastname) + { + $this->lastname = $lastname; + + return $this; + } + + public function getLastname() + { + return $this->lastname; + } + + public function setLogin($login) + { + $this->login = $login; + + return $this; + } + + public function getLogin() + { + return $this->login; + } + + public function setPassword($password) + { + $this->password = $password; + + return $this; + } + + public function getPassword() + { + return $this->password; + } + + public function setProfile($profile) + { + if (0 === $profile) { + $profile = null; + } + + $this->profile = $profile; + + return $this; + } + + public function getProfile() + { + return $this->profile; + } + + public function setLocale($locale) + { + $this->locale = $locale; + + return $this; + } + + public function getLocale() + { + return $this->locale; + } + + /** + * @return string + */ + public function getEmail() + { + return $this->email; + } + + /** + * @param string $email + * + * @return $this + */ + public function setEmail($email) + { + $this->email = $email; + + return $this; + } +} diff --git a/core/lib/Thelia/Core/Event/Administrator/AdministratorUpdatePasswordEvent.php b/core/lib/Thelia/Core/Event/Administrator/AdministratorUpdatePasswordEvent.php new file mode 100644 index 00000000..c2d3c1ce --- /dev/null +++ b/core/lib/Thelia/Core/Event/Administrator/AdministratorUpdatePasswordEvent.php @@ -0,0 +1,75 @@ + + */ +class AdministratorUpdatePasswordEvent extends ActionEvent +{ + /** + * @var \Thelia\Model\Admin + */ + protected $admin; + + /** + * @var string new administrator password + */ + protected $password; + + public function __construct(Admin $admin) + { + $this->admin = $admin; + } + + /** + * @param string $password + */ + public function setPassword($password) + { + $this->password = $password; + + return $this; + } + + /** + * @return string + */ + public function getPassword() + { + return $this->password; + } + + /** + * @param \Thelia\Model\Admin $admin + */ + public function setAdmin(Admin $admin) + { + $this->admin = $admin; + + return $this; + } + + /** + * @return \Thelia\Model\Admin + */ + public function getAdmin() + { + return $this->admin; + } +} diff --git a/core/lib/Thelia/Core/Event/Api/ApiCreateEvent.php b/core/lib/Thelia/Core/Event/Api/ApiCreateEvent.php new file mode 100644 index 00000000..5722446e --- /dev/null +++ b/core/lib/Thelia/Core/Event/Api/ApiCreateEvent.php @@ -0,0 +1,64 @@ + + */ +class ApiCreateEvent extends ActionEvent +{ + protected $label; + protected $profile; + + public function __construct($label, $profile) + { + $this->label = $label; + $this->profile = $profile; + } + + /** + * @param mixed $label + */ + public function setLabel($label) + { + $this->label = $label; + } + + /** + * @return mixed + */ + public function getLabel() + { + return $this->label; + } + + /** + * @param mixed $profile + */ + public function setProfile($profile) + { + $this->profile = $profile; + } + + /** + * @return mixed + */ + public function getProfile() + { + return $this->profile; + } +} diff --git a/core/lib/Thelia/Core/Event/Api/ApiDeleteEvent.php b/core/lib/Thelia/Core/Event/Api/ApiDeleteEvent.php new file mode 100644 index 00000000..60a6a8f2 --- /dev/null +++ b/core/lib/Thelia/Core/Event/Api/ApiDeleteEvent.php @@ -0,0 +1,45 @@ + + */ +class ApiDeleteEvent extends ActionEvent +{ + /** + * @var \Thelia\Model\Api + */ + protected $api; + + /** + * @param $api + */ + public function __construct(Api $api) + { + $this->api = $api; + } + + /** + * @return \Thelia\Model\Api + */ + public function getApi() + { + return $this->api; + } +} diff --git a/core/lib/Thelia/Core/Event/Api/ApiUpdateEvent.php b/core/lib/Thelia/Core/Event/Api/ApiUpdateEvent.php new file mode 100644 index 00000000..68db99b2 --- /dev/null +++ b/core/lib/Thelia/Core/Event/Api/ApiUpdateEvent.php @@ -0,0 +1,69 @@ + + */ +class ApiUpdateEvent extends ActionEvent +{ + protected $api; + + protected $profile; + + public function __construct($api, $profile) + { + $this->api = $api; + $this->profile = $profile; + } + + /** + * @param \Thelia\Model\Api $api + */ + public function setApi($api) + { + $this->api = $api; + + return $this; + } + + /** + * @return \Thelia\Model\Api + */ + public function getApi() + { + return $this->api; + } + + /** + * @param mixed $profile + */ + public function setProfile($profile) + { + $this->profile = $profile; + + return $this; + } + + /** + * @return mixed + */ + public function getProfile() + { + return $this->profile; + } +} diff --git a/core/lib/Thelia/Core/Event/Area/AreaAddCountryEvent.php b/core/lib/Thelia/Core/Event/Area/AreaAddCountryEvent.php new file mode 100644 index 00000000..44f50692 --- /dev/null +++ b/core/lib/Thelia/Core/Event/Area/AreaAddCountryEvent.php @@ -0,0 +1,72 @@ + + */ +class AreaAddCountryEvent extends AreaEvent +{ + protected $areaId; + protected $countryId; + + public function __construct($areaId, $countryId) + { + parent::__construct(); + + $this->areaId = $areaId; + $this->countryId = $countryId; + } + + /** + * @param mixed $areaId + * + * @return $this + */ + public function setAreaId($areaId) + { + $this->areaId = $areaId; + + return $this; + } + + /** + * @return mixed + */ + public function getAreaId() + { + return $this->areaId; + } + + /** + * @param mixed $countryId + * + * @return $this + */ + public function setCountryId($countryId) + { + $this->countryId = $countryId; + + return $this; + } + + /** + * @return mixed + */ + public function getCountryId() + { + return $this->countryId; + } +} diff --git a/core/lib/Thelia/Core/Event/Area/AreaCreateEvent.php b/core/lib/Thelia/Core/Event/Area/AreaCreateEvent.php new file mode 100644 index 00000000..f6b37196 --- /dev/null +++ b/core/lib/Thelia/Core/Event/Area/AreaCreateEvent.php @@ -0,0 +1,41 @@ + + */ +class AreaCreateEvent extends AreaEvent +{ + protected $name; + + /** + * @param mixed $name + */ + public function setAreaName($name) + { + $this->name = $name; + + return $this; + } + + /** + * @return mixed + */ + public function getAreaName() + { + return $this->name; + } +} diff --git a/core/lib/Thelia/Core/Event/Area/AreaDeleteEvent.php b/core/lib/Thelia/Core/Event/Area/AreaDeleteEvent.php new file mode 100644 index 00000000..071e2598 --- /dev/null +++ b/core/lib/Thelia/Core/Event/Area/AreaDeleteEvent.php @@ -0,0 +1,51 @@ + + */ +class AreaDeleteEvent extends AreaEvent +{ + /** + * @var int area id + */ + protected $area_id; + + public function __construct($area_id) + { + $this->area_id = $area_id; + } + + /** + * @param null $area_id + * + * @return $this + */ + public function setAreaId($area_id) + { + $this->area_id = $area_id; + + return $this; + } + + /** + * @return null + */ + public function getAreaId() + { + return $this->area_id; + } +} diff --git a/core/lib/Thelia/Core/Event/Area/AreaEvent.php b/core/lib/Thelia/Core/Event/Area/AreaEvent.php new file mode 100644 index 00000000..41274abb --- /dev/null +++ b/core/lib/Thelia/Core/Event/Area/AreaEvent.php @@ -0,0 +1,59 @@ + + * @deprecated since 2.4, please use \Thelia\Model\Event\AreaEvent + */ +class AreaEvent extends ActionEvent +{ + /** + * @var \Thelia\Model\Area + */ + protected $area; + + public function __construct($area = null) + { + $this->area = $area; + } + + /** + * @param mixed $area + * + * @return $this + */ + public function setArea($area) + { + $this->area = $area; + + return $this; + } + + /** + * @return null|\Thelia\Model\Area + */ + public function getArea() + { + return $this->area; + } + + public function hasArea() + { + return null !== $this->area; + } +} diff --git a/core/lib/Thelia/Core/Event/Area/AreaRemoveCountryEvent.php b/core/lib/Thelia/Core/Event/Area/AreaRemoveCountryEvent.php new file mode 100644 index 00000000..c9f07fd0 --- /dev/null +++ b/core/lib/Thelia/Core/Event/Area/AreaRemoveCountryEvent.php @@ -0,0 +1,48 @@ + + */ +class AreaRemoveCountryEvent extends AreaAddCountryEvent +{ + /** @var int|null */ + protected $stateId; + + public function __construct($areaId, $countryId, $stateId = null) + { + parent::__construct($areaId, $countryId); + + $this->stateId = $stateId; + } + + /** + * @return int|null + */ + public function getStateId() + { + return $this->stateId; + } + + /** + * @param int|null $stateId + */ + public function setStateId($stateId) + { + $this->stateId = $stateId; + return $this; + } +} diff --git a/core/lib/Thelia/Core/Event/Area/AreaUpdateEvent.php b/core/lib/Thelia/Core/Event/Area/AreaUpdateEvent.php new file mode 100644 index 00000000..2f644cd8 --- /dev/null +++ b/core/lib/Thelia/Core/Event/Area/AreaUpdateEvent.php @@ -0,0 +1,41 @@ + + */ +class AreaUpdateEvent extends AreaCreateEvent +{ + protected $area_id; + + /** + * @return int + */ + public function getAreaId() + { + return $this->area_id; + } + + /** + * @param int $area_id + */ + public function setAreaId($area_id) + { + $this->area_id = $area_id; + + return $this; + } +} diff --git a/core/lib/Thelia/Core/Event/Area/AreaUpdatePostageEvent.php b/core/lib/Thelia/Core/Event/Area/AreaUpdatePostageEvent.php new file mode 100644 index 00000000..39b2d6cd --- /dev/null +++ b/core/lib/Thelia/Core/Event/Area/AreaUpdatePostageEvent.php @@ -0,0 +1,69 @@ + + */ +class AreaUpdatePostageEvent extends AreaEvent +{ + protected $area_id; + protected $postage; + + public function __construct($area_id) + { + $this->area_id = $area_id; + } + + /** + * @param mixed $area_id + * + * @return $this + */ + public function setAreaId($area_id) + { + $this->area_id = $area_id; + + return $this; + } + + /** + * @return mixed + */ + public function getAreaId() + { + return $this->area_id; + } + + /** + * @param mixed $postage + * + * @return $this + */ + public function setPostage($postage) + { + $this->postage = $postage; + + return $this; + } + + /** + * @return mixed + */ + public function getPostage() + { + return $this->postage; + } +} diff --git a/core/lib/Thelia/Core/Event/Attribute/AttributeAvCreateEvent.php b/core/lib/Thelia/Core/Event/Attribute/AttributeAvCreateEvent.php new file mode 100644 index 00000000..6cec0ea4 --- /dev/null +++ b/core/lib/Thelia/Core/Event/Attribute/AttributeAvCreateEvent.php @@ -0,0 +1,56 @@ +locale; + } + + public function setLocale($locale) + { + $this->locale = $locale; + + return $this; + } + + public function getTitle() + { + return $this->title; + } + + public function setTitle($title) + { + $this->title = $title; + + return $this; + } + + public function getAttributeId() + { + return $this->attribute_id; + } + + public function setAttributeId($attribute_id) + { + $this->attribute_id = $attribute_id; + + return $this; + } +} diff --git a/core/lib/Thelia/Core/Event/Attribute/AttributeAvDeleteEvent.php b/core/lib/Thelia/Core/Event/Attribute/AttributeAvDeleteEvent.php new file mode 100644 index 00000000..eef95df5 --- /dev/null +++ b/core/lib/Thelia/Core/Event/Attribute/AttributeAvDeleteEvent.php @@ -0,0 +1,39 @@ +setAttributeAvId($attributeAv_id); + } + + public function getAttributeAvId() + { + return $this->attributeAv_id; + } + + public function setAttributeAvId($attributeAv_id) + { + $this->attributeAv_id = $attributeAv_id; + + return $this; + } +} diff --git a/core/lib/Thelia/Core/Event/Attribute/AttributeAvEvent.php b/core/lib/Thelia/Core/Event/Attribute/AttributeAvEvent.php new file mode 100644 index 00000000..dfe6a593 --- /dev/null +++ b/core/lib/Thelia/Core/Event/Attribute/AttributeAvEvent.php @@ -0,0 +1,46 @@ +attributeAv = $attributeAv; + } + + public function hasAttributeAv() + { + return ! \is_null($this->attributeAv); + } + + public function getAttributeAv() + { + return $this->attributeAv; + } + + public function setAttributeAv($attributeAv) + { + $this->attributeAv = $attributeAv; + + return $this; + } +} diff --git a/core/lib/Thelia/Core/Event/Attribute/AttributeAvUpdateEvent.php b/core/lib/Thelia/Core/Event/Attribute/AttributeAvUpdateEvent.php new file mode 100644 index 00000000..795d130c --- /dev/null +++ b/core/lib/Thelia/Core/Event/Attribute/AttributeAvUpdateEvent.php @@ -0,0 +1,79 @@ +setAttributeAvId($attributeAv_id); + } + + public function getAttributeAvId() + { + return $this->attributeAv_id; + } + + public function setAttributeAvId($attributeAv_id) + { + $this->attributeAv_id = $attributeAv_id; + + return $this; + } + + public function getDescription() + { + return $this->description; + } + + public function setDescription($description) + { + $this->description = $description; + + return $this; + } + + public function getChapo() + { + return $this->chapo; + } + + public function setChapo($chapo) + { + $this->chapo = $chapo; + + return $this; + } + + public function getPostscriptum() + { + return $this->postscriptum; + } + + public function setPostscriptum($postscriptum) + { + $this->postscriptum = $postscriptum; + + return $this; + } +} diff --git a/core/lib/Thelia/Core/Event/Attribute/AttributeCreateEvent.php b/core/lib/Thelia/Core/Event/Attribute/AttributeCreateEvent.php new file mode 100644 index 00000000..fbda2b32 --- /dev/null +++ b/core/lib/Thelia/Core/Event/Attribute/AttributeCreateEvent.php @@ -0,0 +1,56 @@ +locale; + } + + public function setLocale($locale) + { + $this->locale = $locale; + + return $this; + } + + public function getTitle() + { + return $this->title; + } + + public function setTitle($title) + { + $this->title = $title; + + return $this; + } + + public function getAddToAllTemplates() + { + return $this->add_to_all_templates; + } + + public function setAddToAllTemplates($add_to_all_templates) + { + $this->add_to_all_templates = $add_to_all_templates; + + return $this; + } +} diff --git a/core/lib/Thelia/Core/Event/Attribute/AttributeDeleteEvent.php b/core/lib/Thelia/Core/Event/Attribute/AttributeDeleteEvent.php new file mode 100644 index 00000000..712f4265 --- /dev/null +++ b/core/lib/Thelia/Core/Event/Attribute/AttributeDeleteEvent.php @@ -0,0 +1,39 @@ +setAttributeId($attribute_id); + } + + public function getAttributeId() + { + return $this->attribute_id; + } + + public function setAttributeId($attribute_id) + { + $this->attribute_id = $attribute_id; + + return $this; + } +} diff --git a/core/lib/Thelia/Core/Event/Attribute/AttributeEvent.php b/core/lib/Thelia/Core/Event/Attribute/AttributeEvent.php new file mode 100644 index 00000000..7a6ded35 --- /dev/null +++ b/core/lib/Thelia/Core/Event/Attribute/AttributeEvent.php @@ -0,0 +1,46 @@ +attribute = $attribute; + } + + public function hasAttribute() + { + return ! \is_null($this->attribute); + } + + public function getAttribute() + { + return $this->attribute; + } + + public function setAttribute($attribute) + { + $this->attribute = $attribute; + + return $this; + } +} diff --git a/core/lib/Thelia/Core/Event/Attribute/AttributeUpdateEvent.php b/core/lib/Thelia/Core/Event/Attribute/AttributeUpdateEvent.php new file mode 100644 index 00000000..191cfecf --- /dev/null +++ b/core/lib/Thelia/Core/Event/Attribute/AttributeUpdateEvent.php @@ -0,0 +1,79 @@ +setAttributeId($attribute_id); + } + + public function getAttributeId() + { + return $this->attribute_id; + } + + public function setAttributeId($attribute_id) + { + $this->attribute_id = $attribute_id; + + return $this; + } + + public function getDescription() + { + return $this->description; + } + + public function setDescription($description) + { + $this->description = $description; + + return $this; + } + + public function getChapo() + { + return $this->chapo; + } + + public function setChapo($chapo) + { + $this->chapo = $chapo; + + return $this; + } + + public function getPostscriptum() + { + return $this->postscriptum; + } + + public function setPostscriptum($postscriptum) + { + $this->postscriptum = $postscriptum; + + return $this; + } +} diff --git a/core/lib/Thelia/Core/Event/Brand/BrandCreateEvent.php b/core/lib/Thelia/Core/Event/Brand/BrandCreateEvent.php new file mode 100644 index 00000000..70721b11 --- /dev/null +++ b/core/lib/Thelia/Core/Event/Brand/BrandCreateEvent.php @@ -0,0 +1,85 @@ + + */ +class BrandCreateEvent extends BrandEvent +{ + protected $title; + protected $locale; + protected $visible; + + /** + * @param string $locale + * + * @return BrandCreateEvent $this + */ + public function setLocale($locale) + { + $this->locale = $locale; + + return $this; + } + + /** + * @return string + */ + public function getLocale() + { + return $this->locale; + } + + /** + * @param string $title + * + * @return BrandCreateEvent $this + */ + public function setTitle($title) + { + $this->title = $title; + + return $this; + } + + /** + * @return string + */ + public function getTitle() + { + return $this->title; + } + + /** + * @param bool $visible + * + * @return BrandCreateEvent $this + */ + public function setVisible($visible) + { + $this->visible = $visible; + + return $this; + } + + /** + * @return bool + */ + public function getVisible() + { + return $this->visible; + } +} diff --git a/core/lib/Thelia/Core/Event/Brand/BrandDeleteEvent.php b/core/lib/Thelia/Core/Event/Brand/BrandDeleteEvent.php new file mode 100644 index 00000000..c9c7944c --- /dev/null +++ b/core/lib/Thelia/Core/Event/Brand/BrandDeleteEvent.php @@ -0,0 +1,52 @@ + + */ +class BrandDeleteEvent extends BrandEvent +{ + /** @var int */ + protected $brand_id; + + /** + * @param int $brand_id + */ + public function __construct($brand_id) + { + $this->brand_id = $brand_id; + } + + /** + * @param int $brand_id + * + * @return BrandDeleteEvent $this + */ + public function setBrandId($brand_id) + { + $this->brand_id = $brand_id; + + return $this; + } + + /** + * @return int + */ + public function getBrandId() + { + return $this->brand_id; + } +} diff --git a/core/lib/Thelia/Core/Event/Brand/BrandEvent.php b/core/lib/Thelia/Core/Event/Brand/BrandEvent.php new file mode 100644 index 00000000..a742d0e7 --- /dev/null +++ b/core/lib/Thelia/Core/Event/Brand/BrandEvent.php @@ -0,0 +1,64 @@ + + * @deprecated since 2.4, please use \Thelia\Model\Event\BrandEvent + */ +class BrandEvent extends ActionEvent +{ + /** + * @var \Thelia\Model\Brand + */ + protected $brand; + + public function __construct(Brand $brand = null) + { + $this->brand = $brand; + } + + /** + * @param \Thelia\Model\Brand $brand + * @return BrandEvent + */ + public function setBrand(Brand $brand) + { + $this->brand = $brand; + + return $this; + } + + /** + * @return \Thelia\Model\Brand + */ + public function getBrand() + { + return $this->brand; + } + + /** + * check if brand exists + * + * @return bool + */ + public function hasBrand() + { + return null !== $this->brand; + } +} diff --git a/core/lib/Thelia/Core/Event/Brand/BrandToggleVisibilityEvent.php b/core/lib/Thelia/Core/Event/Brand/BrandToggleVisibilityEvent.php new file mode 100644 index 00000000..db5b7faa --- /dev/null +++ b/core/lib/Thelia/Core/Event/Brand/BrandToggleVisibilityEvent.php @@ -0,0 +1,22 @@ + + */ +class BrandToggleVisibilityEvent extends BrandEvent +{ +} diff --git a/core/lib/Thelia/Core/Event/Brand/BrandUpdateEvent.php b/core/lib/Thelia/Core/Event/Brand/BrandUpdateEvent.php new file mode 100644 index 00000000..2fc42267 --- /dev/null +++ b/core/lib/Thelia/Core/Event/Brand/BrandUpdateEvent.php @@ -0,0 +1,135 @@ + + */ +class BrandUpdateEvent extends BrandCreateEvent +{ + protected $brandId; + + protected $chapo; + protected $description; + protected $postscriptum; + protected $logo_image_id; + + /** + * @param int $brandId + */ + public function __construct($brandId) + { + $this->brandId = $brandId; + } + + /** + * @param string $chapo + * + * @return BrandUpdateEvent $this + */ + public function setChapo($chapo) + { + $this->chapo = $chapo; + + return $this; + } + + /** + * @return string + */ + public function getChapo() + { + return $this->chapo; + } + + /** + * @param int $brandId + * + * @return BrandUpdateEvent $this + */ + public function setBrandId($brandId) + { + $this->brandId = $brandId; + + return $this; + } + + /** + * @return int + */ + public function getBrandId() + { + return $this->brandId; + } + + /** + * @param string $description + * + * @return BrandUpdateEvent $this + */ + public function setDescription($description) + { + $this->description = $description; + + return $this; + } + + /** + * @return string + */ + public function getDescription() + { + return $this->description; + } + + /** + * @param string $postscriptum + * + * @return BrandUpdateEvent $this + */ + public function setPostscriptum($postscriptum) + { + $this->postscriptum = $postscriptum; + + return $this; + } + + /** + * @return string + */ + public function getPostscriptum() + { + return $this->postscriptum; + } + + /** + * @param int $logo_image_id + * @return $this + */ + public function setLogoImageId($logo_image_id) + { + $this->logo_image_id = $logo_image_id; + + return $this; + } + + /** + * @return int + */ + public function getLogoImageId() + { + return $this->logo_image_id; + } +} diff --git a/core/lib/Thelia/Core/Event/Cache/CacheEvent.php b/core/lib/Thelia/Core/Event/Cache/CacheEvent.php new file mode 100644 index 00000000..d59e3ea0 --- /dev/null +++ b/core/lib/Thelia/Core/Event/Cache/CacheEvent.php @@ -0,0 +1,81 @@ + + * @author Gilles Bourgeat + */ +class CacheEvent extends ActionEvent +{ + /** + * @var string cache directory + */ + protected $dir; + + /** + * @since 2.4.0 + * @var bool + */ + protected $onKernelTerminate = true; + + public function __construct($dir, $onKernelTerminate = true) + { + $this->dir = $dir; + $this->onKernelTerminate = $onKernelTerminate; + } + + /** + * @param string $dir + * + * @return $this + */ + public function setDir($dir) + { + $this->dir = $dir; + + return $this; + } + + /** + * @return string + */ + public function getDir() + { + return $this->dir; + } + + /** + * @since 2.4.0 + * @return bool + */ + public function isOnKernelTerminate() + { + return $this->onKernelTerminate; + } + + /** + * @since 2.4.0 + * @param bool $onKernelTerminate + * @return CacheEvent + */ + public function setOnKernelTerminate($onKernelTerminate) + { + $this->onKernelTerminate = $onKernelTerminate; + return $this; + } +} diff --git a/core/lib/Thelia/Core/Event/CachedFileEvent.php b/core/lib/Thelia/Core/Event/CachedFileEvent.php new file mode 100644 index 00000000..fc7f52c1 --- /dev/null +++ b/core/lib/Thelia/Core/Event/CachedFileEvent.php @@ -0,0 +1,83 @@ +file_url; + } + + public function setFileUrl($file_url) + { + $this->file_url = $file_url; + + return $this; + } + + public function getCacheFilepath() + { + return $this->cache_filepath; + } + + public function setCacheFilepath($cache_filepath) + { + $this->cache_filepath = $cache_filepath; + + return $this; + } + + public function getSourceFilepath() + { + return $this->source_filepath; + } + + public function setSourceFilepath($source_filepath) + { + $this->source_filepath = $source_filepath; + + return $this; + } + + public function getCacheSubdirectory() + { + return $this->cache_subdirectory; + } + + public function setCacheSubdirectory($cache_subdirectory) + { + $this->cache_subdirectory = $cache_subdirectory; + + return $this; + } +} diff --git a/core/lib/Thelia/Core/Event/Cart/CartCreateEvent.php b/core/lib/Thelia/Core/Event/Cart/CartCreateEvent.php new file mode 100644 index 00000000..89233ef8 --- /dev/null +++ b/core/lib/Thelia/Core/Event/Cart/CartCreateEvent.php @@ -0,0 +1,41 @@ +cart; + } + + /** + * @param Cart $cart + * + * @return $this + */ + public function setCart(Cart $cart) + { + $this->cart = $cart; + + return $this; + } +} diff --git a/core/lib/Thelia/Core/Event/Cart/CartDuplicationEvent.php b/core/lib/Thelia/Core/Event/Cart/CartDuplicationEvent.php new file mode 100644 index 00000000..7d6d1cf9 --- /dev/null +++ b/core/lib/Thelia/Core/Event/Cart/CartDuplicationEvent.php @@ -0,0 +1,43 @@ +originalCart = $originalCart; + } + + /** + * @return Cart + */ + public function getDuplicatedCart() + { + return $this->getCart(); + } + + /** + * @return Cart + */ + public function getOriginalCart() + { + return $this->originalCart; + } +} diff --git a/core/lib/Thelia/Core/Event/Cart/CartEvent.php b/core/lib/Thelia/Core/Event/Cart/CartEvent.php new file mode 100644 index 00000000..17967d5e --- /dev/null +++ b/core/lib/Thelia/Core/Event/Cart/CartEvent.php @@ -0,0 +1,188 @@ +cart = $cart; + } + + /** + * @param bool $append + * @return CartEvent + */ + public function setAppend($append) + { + $this->append = $append; + + return $this; + } + + /** + * @return bool + */ + public function getAppend() + { + return $this->append; + } + + /** + * @param CartItem $cartItem + * @return CartEvent + */ + public function setCartItem(CartItem $cartItem) + { + $this->cartItem = $cartItem; + + return $this; + } + + /** + * Clear the current cart item + * + * @return CartEvent + */ + public function clearCartItem() + { + $this->cartItem = null; + + return $this; + } + + /** + * @return CartItem + */ + public function getCartItem() + { + return $this->cartItem; + } + + /** + * @return mixed + */ + public function getCartItemId() + { + return $this->cartItemId; + } + + /** + * @param mixed $cartItemId + * @return $this + */ + public function setCartItemId($cartItemId) + { + $this->cartItemId = $cartItemId; + + return $this; + } + + /** + * @param bool $newness + * @return CartEvent + */ + public function setNewness($newness) + { + $this->newness = $newness; + + return $this; + } + + /** + * @return bool + */ + public function getNewness() + { + return $this->newness; + } + + /** + * @param int $product the product ID + * @return CartEvent + */ + public function setProduct($product) + { + $this->product = $product; + + return $this; + } + + /** + * @return int the product ID + */ + public function getProduct() + { + return $this->product; + } + + /** + * @param int $productSaleElementsId + * @return CartEvent + */ + public function setProductSaleElementsId($productSaleElementsId) + { + $this->productSaleElementsId = $productSaleElementsId; + + return $this; + } + + /** + * @return int + */ + public function getProductSaleElementsId() + { + return $this->productSaleElementsId; + } + + /** + * @param int $quantity + * @return CartEvent + */ + public function setQuantity($quantity) + { + $this->quantity = $quantity; + + return $this; + } + + /** + * @return int + */ + public function getQuantity() + { + return $this->quantity; + } + + /** + * @return \Thelia\Model\Cart + */ + public function getCart() + { + return $this->cart; + } +} diff --git a/core/lib/Thelia/Core/Event/Cart/CartItemDuplicationItem.php b/core/lib/Thelia/Core/Event/Cart/CartItemDuplicationItem.php new file mode 100644 index 00000000..e2e9377e --- /dev/null +++ b/core/lib/Thelia/Core/Event/Cart/CartItemDuplicationItem.php @@ -0,0 +1,56 @@ + + */ +class CartItemDuplicationItem extends ActionEvent +{ + /** + * @var \Thelia\Model\CartItem + */ + protected $oldItem; + + /** + * @var \Thelia\Model\CartItem + */ + protected $newItem; + + public function __construct(CartItem $newItem, CartItem $oldItem) + { + $this->newItem = $newItem; + $this->oldItem = $oldItem; + } + + /** + * @return \Thelia\Model\CartItem + */ + public function getNewItem() + { + return $this->newItem; + } + + /** + * @return \Thelia\Model\CartItem + */ + public function getOldItem() + { + return $this->oldItem; + } +} diff --git a/core/lib/Thelia/Core/Event/Cart/CartItemEvent.php b/core/lib/Thelia/Core/Event/Cart/CartItemEvent.php new file mode 100644 index 00000000..f6222659 --- /dev/null +++ b/core/lib/Thelia/Core/Event/Cart/CartItemEvent.php @@ -0,0 +1,31 @@ +cartItem = $cartItem; + } + + public function getCartItem() + { + return $this->cartItem; + } +} diff --git a/core/lib/Thelia/Core/Event/Cart/CartPersistEvent.php b/core/lib/Thelia/Core/Event/Cart/CartPersistEvent.php new file mode 100644 index 00000000..7c3b8597 --- /dev/null +++ b/core/lib/Thelia/Core/Event/Cart/CartPersistEvent.php @@ -0,0 +1,60 @@ + + */ +class CartPersistEvent extends ActionEvent +{ + /** @var Cart $cart */ + protected $cart; + + public function __construct(Cart $cart) + { + $this->cart = $cart; + } + + /** + * @return Cart + */ + public function getCart() + { + return $this->cart; + } + + /** + * @param Cart $cart + */ + public function setCart($cart) + { + $this->cart = $cart; + return $this; + } + + /** + * check if cart exists + * + * @return bool + */ + public function hasCart() + { + return null !== $this->cart; + } +} diff --git a/core/lib/Thelia/Core/Event/Cart/CartRestoreEvent.php b/core/lib/Thelia/Core/Event/Cart/CartRestoreEvent.php new file mode 100644 index 00000000..d42c1a33 --- /dev/null +++ b/core/lib/Thelia/Core/Event/Cart/CartRestoreEvent.php @@ -0,0 +1,41 @@ +cart; + } + + /** + * @param Cart $cart + * + * @return $this + */ + public function setCart(Cart $cart) + { + $this->cart = $cart; + + return $this; + } +} diff --git a/core/lib/Thelia/Core/Event/Category/CategoryAddContentEvent.php b/core/lib/Thelia/Core/Event/Category/CategoryAddContentEvent.php new file mode 100644 index 00000000..92085aff --- /dev/null +++ b/core/lib/Thelia/Core/Event/Category/CategoryAddContentEvent.php @@ -0,0 +1,37 @@ +content_id = $content_id; + } + + public function getContentId() + { + return $this->content_id; + } + + public function setContentId($content_id) + { + $this->content_id = $content_id; + } +} diff --git a/core/lib/Thelia/Core/Event/Category/CategoryAssociatedContentEvent.php b/core/lib/Thelia/Core/Event/Category/CategoryAssociatedContentEvent.php new file mode 100644 index 00000000..5d469c04 --- /dev/null +++ b/core/lib/Thelia/Core/Event/Category/CategoryAssociatedContentEvent.php @@ -0,0 +1,46 @@ +content = $content; + } + + public function hasCategoryAssociatedContent() + { + return ! \is_null($this->content); + } + + public function getCategoryAssociatedContent() + { + return $this->content; + } + + public function setCategoryAssociatedContent(CategoryAssociatedContent $content) + { + $this->content = $content; + + return $this; + } +} diff --git a/core/lib/Thelia/Core/Event/Category/CategoryCreateEvent.php b/core/lib/Thelia/Core/Event/Category/CategoryCreateEvent.php new file mode 100644 index 00000000..b55104e9 --- /dev/null +++ b/core/lib/Thelia/Core/Event/Category/CategoryCreateEvent.php @@ -0,0 +1,69 @@ +title; + } + + public function setTitle($title) + { + $this->title = $title; + + return $this; + } + + public function getParent() + { + return $this->parent; + } + + public function setParent($parent) + { + $this->parent = $parent; + + return $this; + } + + public function getLocale() + { + return $this->locale; + } + + public function setLocale($locale) + { + $this->locale = $locale; + + return $this; + } + + public function getVisible() + { + return $this->visible; + } + + public function setVisible($visible) + { + $this->visible = $visible; + + return $this; + } +} diff --git a/core/lib/Thelia/Core/Event/Category/CategoryDeleteContentEvent.php b/core/lib/Thelia/Core/Event/Category/CategoryDeleteContentEvent.php new file mode 100644 index 00000000..7b2f77c1 --- /dev/null +++ b/core/lib/Thelia/Core/Event/Category/CategoryDeleteContentEvent.php @@ -0,0 +1,37 @@ +content_id = $content_id; + } + + public function getContentId() + { + return $this->content_id; + } + + public function setContentId($content_id) + { + $this->content_id = $content_id; + } +} diff --git a/core/lib/Thelia/Core/Event/Category/CategoryDeleteEvent.php b/core/lib/Thelia/Core/Event/Category/CategoryDeleteEvent.php new file mode 100644 index 00000000..e435a9c7 --- /dev/null +++ b/core/lib/Thelia/Core/Event/Category/CategoryDeleteEvent.php @@ -0,0 +1,39 @@ +categoryId = $categoryId; + } + + public function getCategoryId() + { + return $this->categoryId; + } + + public function setCategoryId($categoryId) + { + $this->categoryId = $categoryId; + + return $this; + } +} diff --git a/core/lib/Thelia/Core/Event/Category/CategoryEvent.php b/core/lib/Thelia/Core/Event/Category/CategoryEvent.php new file mode 100644 index 00000000..d9b209d8 --- /dev/null +++ b/core/lib/Thelia/Core/Event/Category/CategoryEvent.php @@ -0,0 +1,46 @@ +category = $category; + } + + public function hasCategory() + { + return ! \is_null($this->category); + } + + public function getCategory() + { + return $this->category; + } + + public function setCategory(Category $category) + { + $this->category = $category; + + return $this; + } +} diff --git a/core/lib/Thelia/Core/Event/Category/CategoryToggleVisibilityEvent.php b/core/lib/Thelia/Core/Event/Category/CategoryToggleVisibilityEvent.php new file mode 100644 index 00000000..17f2ce6d --- /dev/null +++ b/core/lib/Thelia/Core/Event/Category/CategoryToggleVisibilityEvent.php @@ -0,0 +1,17 @@ +category_id = $category_id; + } + + public function getCategoryId() + { + return $this->category_id; + } + + public function setCategoryId($category_id) + { + $this->category_id = $category_id; + + return $this; + } + + public function getChapo() + { + return $this->chapo; + } + + public function setChapo($chapo) + { + $this->chapo = $chapo; + + return $this; + } + + public function getDescription() + { + return $this->description; + } + + public function setDescription($description) + { + $this->description = $description; + + return $this; + } + + public function getPostscriptum() + { + return $this->postscriptum; + } + + public function setPostscriptum($postscriptum) + { + $this->postscriptum = $postscriptum; + + return $this; + } + + public function getParent() + { + return $this->parent; + } + + public function setParent($parent) + { + $this->parent = $parent; + + return $this; + } + + /** + * @return int + */ + public function getDefaultTemplateId() + { + return $this->defaultTemplateId; + } + + /** + * @param int $defaultTemplateId + * @return $this + */ + public function setDefaultTemplateId($defaultTemplateId) + { + $this->defaultTemplateId = $defaultTemplateId; + return $this; + } +} diff --git a/core/lib/Thelia/Core/Event/Config/ConfigCreateEvent.php b/core/lib/Thelia/Core/Event/Config/ConfigCreateEvent.php new file mode 100644 index 00000000..7b17582e --- /dev/null +++ b/core/lib/Thelia/Core/Event/Config/ConfigCreateEvent.php @@ -0,0 +1,96 @@ +event_name; + } + + public function setEventName($event_name) + { + $this->event_name = $event_name; + + return $this; + } + + public function getValue() + { + return $this->value; + } + + public function setValue($value) + { + $this->value = $value; + + return $this; + } + + public function getLocale() + { + return $this->locale; + } + + public function setLocale($locale) + { + $this->locale = $locale; + + return $this; + } + + public function getTitle() + { + return $this->title; + } + + public function setTitle($title) + { + $this->title = $title; + + return $this; + } + + public function getHidden() + { + return $this->hidden; + } + + public function setHidden($hidden) + { + $this->hidden = $hidden; + + return $this; + } + + public function getSecured() + { + return $this->secured; + } + + public function setSecured($secured) + { + $this->secured = $secured; + + return $this; + } +} diff --git a/core/lib/Thelia/Core/Event/Config/ConfigDeleteEvent.php b/core/lib/Thelia/Core/Event/Config/ConfigDeleteEvent.php new file mode 100644 index 00000000..26c2c21c --- /dev/null +++ b/core/lib/Thelia/Core/Event/Config/ConfigDeleteEvent.php @@ -0,0 +1,39 @@ +setConfigId($config_id); + } + + public function getConfigId() + { + return $this->config_id; + } + + public function setConfigId($config_id) + { + $this->config_id = $config_id; + + return $this; + } +} diff --git a/core/lib/Thelia/Core/Event/Config/ConfigEvent.php b/core/lib/Thelia/Core/Event/Config/ConfigEvent.php new file mode 100644 index 00000000..abda7d07 --- /dev/null +++ b/core/lib/Thelia/Core/Event/Config/ConfigEvent.php @@ -0,0 +1,46 @@ +config = $config; + } + + public function hasConfig() + { + return ! \is_null($this->config); + } + + public function getConfig() + { + return $this->config; + } + + public function setConfig($config) + { + $this->config = $config; + + return $this; + } +} diff --git a/core/lib/Thelia/Core/Event/Config/ConfigUpdateEvent.php b/core/lib/Thelia/Core/Event/Config/ConfigUpdateEvent.php new file mode 100644 index 00000000..3622d020 --- /dev/null +++ b/core/lib/Thelia/Core/Event/Config/ConfigUpdateEvent.php @@ -0,0 +1,79 @@ +setConfigId($config_id); + } + + public function getConfigId() + { + return $this->config_id; + } + + public function setConfigId($config_id) + { + $this->config_id = $config_id; + + return $this; + } + + public function getDescription() + { + return $this->description; + } + + public function setDescription($description) + { + $this->description = $description; + + return $this; + } + + public function getChapo() + { + return $this->chapo; + } + + public function setChapo($chapo) + { + $this->chapo = $chapo; + + return $this; + } + + public function getPostscriptum() + { + return $this->postscriptum; + } + + public function setPostscriptum($postscriptum) + { + $this->postscriptum = $postscriptum; + + return $this; + } +} diff --git a/core/lib/Thelia/Core/Event/Contact/ContactEvent.php b/core/lib/Thelia/Core/Event/Contact/ContactEvent.php new file mode 100644 index 00000000..1c6a6c5b --- /dev/null +++ b/core/lib/Thelia/Core/Event/Contact/ContactEvent.php @@ -0,0 +1,123 @@ + + * @since 2.4 + */ +class ContactEvent extends ActionEvent +{ + /** @var Form */ + protected $form; + + /** @var string */ + protected $subject; + + /** @var string */ + protected $message; + + /** @var string */ + protected $email; + + /** @var string */ + protected $name; + + public function __construct(Form $form) + { + $this->form = $form; + + $this->subject = $form->get('subject')->getData(); + $this->message = $form->get('message')->getData(); + $this->email = $form->get('email')->getData(); + $this->name = $form->get('name')->getData(); + } + + /** + * @return string + */ + public function getSubject() + { + return $this->subject; + } + + /** + * @param string $subject + * @return ContactEvent + */ + public function setSubject($subject) + { + $this->subject = $subject; + return $this; + } + + /** + * @return string + */ + public function getMessage() + { + return $this->message; + } + + /** + * @param string $message + * @return ContactEvent + */ + public function setMessage($message) + { + $this->message = $message; + return $this; + } + + /** + * @return string + */ + public function getEmail() + { + return $this->email; + } + + /** + * @param string $email + * @return ContactEvent + */ + public function setEmail($email) + { + $this->email = $email; + return $this; + } + + /** + * @return string + */ + public function getName() + { + return $this->name; + } + + /** + * @param string $name + * @return ContactEvent + */ + public function setName($name) + { + $this->name = $name; + return $this; + } + +} \ No newline at end of file diff --git a/core/lib/Thelia/Core/Event/Content/ContentAddFolderEvent.php b/core/lib/Thelia/Core/Event/Content/ContentAddFolderEvent.php new file mode 100644 index 00000000..b55e1f57 --- /dev/null +++ b/core/lib/Thelia/Core/Event/Content/ContentAddFolderEvent.php @@ -0,0 +1,51 @@ + + */ +class ContentAddFolderEvent extends ContentEvent +{ + /** + * @var int folder id + */ + protected $folderId; + + public function __construct(Content $content, $folderId) + { + $this->folderId = $folderId; + + parent::__construct($content); + } + + /** + * @param int $folderId + */ + public function setFolderId($folderId) + { + $this->folderId = $folderId; + } + + /** + * @return int + */ + public function getFolderId() + { + return $this->folderId; + } +} diff --git a/core/lib/Thelia/Core/Event/Content/ContentCreateEvent.php b/core/lib/Thelia/Core/Event/Content/ContentCreateEvent.php new file mode 100644 index 00000000..f56229b7 --- /dev/null +++ b/core/lib/Thelia/Core/Event/Content/ContentCreateEvent.php @@ -0,0 +1,106 @@ + + */ +class ContentCreateEvent extends ContentEvent +{ + protected $title; + protected $default_folder; + protected $locale; + protected $visible; + + /** + * @param mixed $locale + * + * @return $this + */ + public function setLocale($locale) + { + $this->locale = $locale; + + return $this; + } + + /** + * @return mixed + */ + public function getLocale() + { + return $this->locale; + } + + /** + * @param mixed $default_folder + * + * @return $this + */ + public function setDefaultFolder($default_folder) + { + $this->default_folder = $default_folder; + + return $this; + } + + /** + * @return mixed + */ + public function getDefaultFolder() + { + return $this->default_folder; + } + + /** + * @param mixed $visible + * + * @return $this + */ + public function setVisible($visible) + { + $this->visible = $visible; + + return $this; + } + + /** + * @return mixed + */ + public function getVisible() + { + return $this->visible; + } + + /** + * @param mixed $title + * + * @return $this + */ + public function setTitle($title) + { + $this->title = $title; + + return $this; + } + + /** + * @return mixed + */ + public function getTitle() + { + return $this->title; + } +} diff --git a/core/lib/Thelia/Core/Event/Content/ContentDeleteEvent.php b/core/lib/Thelia/Core/Event/Content/ContentDeleteEvent.php new file mode 100644 index 00000000..9f2fa107 --- /dev/null +++ b/core/lib/Thelia/Core/Event/Content/ContentDeleteEvent.php @@ -0,0 +1,65 @@ + + */ +class ContentDeleteEvent extends ContentEvent +{ + /** @var int */ + protected $content_id; + + /** @var int */ + protected $folder_id; + + /** + * @param int $content_id + */ + public function __construct($content_id) + { + $this->content_id = $content_id; + } + + /** + * @param mixed $content_id + * + * @return $this + */ + public function setContentId($content_id) + { + $this->content_id = $content_id; + + return $this; + } + + /** + * @return mixed + */ + public function getContentId() + { + return $this->content_id; + } + + public function setDefaultFolderId($folderid) + { + $this->folder_id = $folderid; + } + + public function getDefaultFolderId() + { + return $this->folder_id; + } +} diff --git a/core/lib/Thelia/Core/Event/Content/ContentEvent.php b/core/lib/Thelia/Core/Event/Content/ContentEvent.php new file mode 100644 index 00000000..21483b57 --- /dev/null +++ b/core/lib/Thelia/Core/Event/Content/ContentEvent.php @@ -0,0 +1,63 @@ + + * @deprecated since 2.4, please use \Thelia\Model\Event\ContentEvent + */ +class ContentEvent extends ActionEvent +{ + /** + * @var \Thelia\Model\Content + */ + protected $content; + + public function __construct(Content $content = null) + { + $this->content = $content; + } + + /** + * @param \Thelia\Model\Content $content + */ + public function setContent(Content $content) + { + $this->content = $content; + + return $this; + } + + /** + * @return \Thelia\Model\Content + */ + public function getContent() + { + return $this->content; + } + + /** + * check if content exists + * + * @return bool + */ + public function hasContent() + { + return null !== $this->content; + } +} diff --git a/core/lib/Thelia/Core/Event/Content/ContentRemoveFolderEvent.php b/core/lib/Thelia/Core/Event/Content/ContentRemoveFolderEvent.php new file mode 100644 index 00000000..8fbcade2 --- /dev/null +++ b/core/lib/Thelia/Core/Event/Content/ContentRemoveFolderEvent.php @@ -0,0 +1,22 @@ + + */ +class ContentRemoveFolderEvent extends ContentAddFolderEvent +{ +} diff --git a/core/lib/Thelia/Core/Event/Content/ContentToggleVisibilityEvent.php b/core/lib/Thelia/Core/Event/Content/ContentToggleVisibilityEvent.php new file mode 100644 index 00000000..cb08096f --- /dev/null +++ b/core/lib/Thelia/Core/Event/Content/ContentToggleVisibilityEvent.php @@ -0,0 +1,22 @@ + + */ +class ContentToggleVisibilityEvent extends ContentEvent +{ +} diff --git a/core/lib/Thelia/Core/Event/Content/ContentUpdateEvent.php b/core/lib/Thelia/Core/Event/Content/ContentUpdateEvent.php new file mode 100644 index 00000000..83458be1 --- /dev/null +++ b/core/lib/Thelia/Core/Event/Content/ContentUpdateEvent.php @@ -0,0 +1,116 @@ + + */ +class ContentUpdateEvent extends ContentCreateEvent +{ + /** @var int */ + protected $content_id; + + protected $chapo; + protected $description; + protected $postscriptum; + + /** + * @param int $content_id + */ + public function __construct($content_id) + { + $this->content_id = $content_id; + } + + /** + * @param mixed $chapo + * + * @return $this + */ + public function setChapo($chapo) + { + $this->chapo = $chapo; + + return $this; + } + + /** + * @return mixed + */ + public function getChapo() + { + return $this->chapo; + } + + /** + * @param mixed $content_id + * + * @return $this + */ + public function setContentId($content_id) + { + $this->content_id = $content_id; + + return $this; + } + + /** + * @return mixed + */ + public function getContentId() + { + return $this->content_id; + } + + /** + * @param mixed $description + * + * @return $this + */ + public function setDescription($description) + { + $this->description = $description; + + return $this; + } + + /** + * @return mixed + */ + public function getDescription() + { + return $this->description; + } + + /** + * @param mixed $postscriptum + * + * @return $this + */ + public function setPostscriptum($postscriptum) + { + $this->postscriptum = $postscriptum; + + return $this; + } + + /** + * @return mixed + */ + public function getPostscriptum() + { + return $this->postscriptum; + } +} diff --git a/core/lib/Thelia/Core/Event/Country/CountryCreateEvent.php b/core/lib/Thelia/Core/Event/Country/CountryCreateEvent.php new file mode 100644 index 00000000..064eba96 --- /dev/null +++ b/core/lib/Thelia/Core/Event/Country/CountryCreateEvent.php @@ -0,0 +1,176 @@ + + */ +class CountryCreateEvent extends CountryEvent +{ + protected $locale; + protected $title; + protected $isocode; + protected $isoAlpha2; + protected $isoAlpha3; + + /** @var bool is visible */ + protected $visible; + /** @var bool has states */ + protected $hasStates; + + protected $area; + + /** + * @param mixed $isoAlpha2 + */ + public function setIsoAlpha2($isoAlpha2) + { + $this->isoAlpha2 = $isoAlpha2; + + return $this; + } + + /** + * @return mixed + */ + public function getIsoAlpha2() + { + return $this->isoAlpha2; + } + + /** + * @param mixed $isoAlpha3 + */ + public function setIsoAlpha3($isoAlpha3) + { + $this->isoAlpha3 = $isoAlpha3; + + return $this; + } + + /** + * @return mixed + */ + public function getIsoAlpha3() + { + return $this->isoAlpha3; + } + + /** + * @param mixed $isocode + */ + public function setIsocode($isocode) + { + $this->isocode = $isocode; + + return $this; + } + + /** + * @return mixed + */ + public function getIsocode() + { + return $this->isocode; + } + + /** + * @param mixed $locale + */ + public function setLocale($locale) + { + $this->locale = $locale; + + return $this; + } + + /** + * @return mixed + */ + public function getLocale() + { + return $this->locale; + } + + /** + * @param mixed $title + */ + public function setTitle($title) + { + $this->title = $title; + + return $this; + } + + /** + * @return mixed + */ + public function getTitle() + { + return $this->title; + } + + /** + * @param int $area + */ + public function setArea($area) + { + $this->area = $area; + + return $this; + } + + /** + * @return int + */ + public function getArea() + { + return $this->area; + } + + /** + * @return boolean + */ + public function isVisible() + { + return $this->visible; + } + + /** + * @param boolean $visible + */ + public function setVisible($visible) + { + $this->visible = $visible; + return $this; + } + + /** + * @return boolean + */ + public function isHasStates() + { + return $this->hasStates; + } + + /** + * @param boolean $hasStates + */ + public function setHasStates($hasStates) + { + $this->hasStates = $hasStates; + return $this; + } +} diff --git a/core/lib/Thelia/Core/Event/Country/CountryDeleteEvent.php b/core/lib/Thelia/Core/Event/Country/CountryDeleteEvent.php new file mode 100644 index 00000000..db4435f4 --- /dev/null +++ b/core/lib/Thelia/Core/Event/Country/CountryDeleteEvent.php @@ -0,0 +1,50 @@ + + */ +class CountryDeleteEvent extends CountryEvent +{ + /** + * @var int country id + */ + protected $country_id; + + /** + * @param int $country_id + */ + public function __construct($country_id) + { + $this->country_id = $country_id; + } + + /** + * @param int $country_id + */ + public function setCountryId($country_id) + { + $this->country_id = $country_id; + } + + /** + * @return int + */ + public function getCountryId() + { + return $this->country_id; + } +} diff --git a/core/lib/Thelia/Core/Event/Country/CountryEvent.php b/core/lib/Thelia/Core/Event/Country/CountryEvent.php new file mode 100644 index 00000000..ffcf53cb --- /dev/null +++ b/core/lib/Thelia/Core/Event/Country/CountryEvent.php @@ -0,0 +1,61 @@ + + * @deprecated since 2.4, please use \Thelia\Model\Event\CountryEvent + */ +class CountryEvent extends ActionEvent +{ + /* + * @var \Thelia\Model\Country + */ + protected $country; + + public function __construct(Country $country = null) + { + $this->country = $country; + } + + /** + * @param mixed $country + */ + public function setCountry(Country $country) + { + $this->country = $country; + + return $this; + } + + /** + * @return null|\Thelia\Model\Country + */ + public function getCountry() + { + return $this->country; + } + + /** + * @return bool + */ + public function hasCountry() + { + return null !== $this->country; + } +} diff --git a/core/lib/Thelia/Core/Event/Country/CountryToggleDefaultEvent.php b/core/lib/Thelia/Core/Event/Country/CountryToggleDefaultEvent.php new file mode 100644 index 00000000..4d3cbdda --- /dev/null +++ b/core/lib/Thelia/Core/Event/Country/CountryToggleDefaultEvent.php @@ -0,0 +1,40 @@ + + */ +class CountryToggleDefaultEvent extends CountryEvent +{ + /** @var int */ + protected $country_id; + + /** + * @param int $country_id + */ + public function __construct($country_id) + { + $this->country_id = $country_id; + } + + /** + * @return mixed + */ + public function getCountryId() + { + return $this->country_id; + } +} diff --git a/core/lib/Thelia/Core/Event/Country/CountryToggleVisibilityEvent.php b/core/lib/Thelia/Core/Event/Country/CountryToggleVisibilityEvent.php new file mode 100644 index 00000000..ba1d57e2 --- /dev/null +++ b/core/lib/Thelia/Core/Event/Country/CountryToggleVisibilityEvent.php @@ -0,0 +1,23 @@ + + */ +class CountryToggleVisibilityEvent extends CountryEvent +{ +} diff --git a/core/lib/Thelia/Core/Event/Country/CountryUpdateEvent.php b/core/lib/Thelia/Core/Event/Country/CountryUpdateEvent.php new file mode 100644 index 00000000..c4268143 --- /dev/null +++ b/core/lib/Thelia/Core/Event/Country/CountryUpdateEvent.php @@ -0,0 +1,159 @@ + + */ +class CountryUpdateEvent extends CountryCreateEvent +{ + /** @var $country_id */ + protected $country_id; + + /** @var bool */ + protected $needZipCode; + + /** @var string */ + protected $zipCodeFormat; + + /** @var string */ + protected $chapo; + + /** @var string */ + protected $description; + + /** @var string */ + protected $postscriptum; + + /** + * @param int $country_id + */ + public function __construct($country_id) + { + $this->country_id = $country_id; + } + + /** + * @param string $chapo + * @return $this + */ + public function setChapo($chapo) + { + $this->chapo = $chapo; + + return $this; + } + + /** + * @return string + */ + public function getChapo() + { + return $this->chapo; + } + + /** + * @param string $description + * @return $this + */ + public function setDescription($description) + { + $this->description = $description; + + return $this; + } + + /** + * @return mixed + */ + public function getDescription() + { + return $this->description; + } + + /** + * @param string $postscriptum + * @return $this + */ + public function setPostscriptum($postscriptum) + { + $this->postscriptum = $postscriptum; + + return $this; + } + + /** + * @return mixed + */ + public function getPostscriptum() + { + return $this->postscriptum; + } + + /** + * @param int $country_id + * @return $this + */ + public function setCountryId($country_id) + { + $this->country_id = $country_id; + + return $this; + } + + /** + * @return int + */ + public function getCountryId() + { + return $this->country_id; + } + + /** + * @return string + */ + public function isNeedZipCode() + { + return $this->needZipCode; + } + + /** + * @param boolean $needZipCode + * @return $this + */ + public function setNeedZipCode($needZipCode) + { + $this->needZipCode = $needZipCode; + return $this; + } + + /** + * @return string + */ + public function getZipCodeFormat() + { + return $this->zipCodeFormat; + } + + /** + * @param string $zipCodeFormat + * @return $this + */ + public function setZipCodeFormat($zipCodeFormat) + { + $this->zipCodeFormat = $zipCodeFormat; + return $this; + } +} diff --git a/core/lib/Thelia/Core/Event/Coupon/CouponConsumeEvent.php b/core/lib/Thelia/Core/Event/Coupon/CouponConsumeEvent.php new file mode 100644 index 00000000..61f1bb21 --- /dev/null +++ b/core/lib/Thelia/Core/Event/Coupon/CouponConsumeEvent.php @@ -0,0 +1,145 @@ + + * + */ +class CouponConsumeEvent extends ActionEvent +{ + /** @var string Coupon code */ + protected $code = null; + + /** @var float Total discount given by this coupon */ + protected $discount = 0; + + /** @var bool If Coupon is valid or if Customer meets coupon conditions */ + protected $isValid = null; + + /** @var bool true if coupon offers free shipping */ + protected $freeShipping = false; + + /** + * Constructor + * + * @param string $code Coupon code + * @param float $discount Total discount given by this coupon + * @param bool $isValid If Coupon is valid or f Customer meets coupon conditions + * @param bool $freeShipping true if coupon offers free shipping + */ + public function __construct($code, $discount = null, $isValid = null, $freeShipping = false) + { + $this->code = $code; + $this->discount = $discount; + $this->discount = $discount; + + $this->freeShipping = $freeShipping; + } + + /** + * @param boolean $freeShipping + */ + public function setFreeShipping($freeShipping) + { + $this->freeShipping = $freeShipping; + + return $this; + } + + /** + * @return boolean + */ + public function getFreeShipping() + { + return $this->freeShipping; + } + + /** + * Set Coupon code + * + * @param string $code Coupon code + * + * @return $this + */ + public function setCode($code) + { + $this->code = $code; + + return $this; + } + + /** + * Get Coupon code + * + * @return string + */ + public function getCode() + { + return $this->code; + } + + /** + * Set total discount given by this coupon + * + * @param float $discount Total discount given by this coupon + * + * @return $this + */ + public function setDiscount($discount) + { + $this->discount = $discount; + + return $this; + } + + /** + * Get total discount given by this coupon + * + * @return float + */ + public function getDiscount() + { + return $this->discount; + } + + /** + * Set if Coupon is valid or if Customer meets coupon conditions + * + * @param boolean $isValid if Coupon is valid or + * if Customer meets coupon conditions + * + * @return $this + */ + public function setIsValid($isValid) + { + $this->isValid = $isValid; + + return $this; + } + + /** + * Get if Coupon is valid or if Customer meets coupon conditions + * + * @return boolean + */ + public function getIsValid() + { + return $this->isValid; + } +} diff --git a/core/lib/Thelia/Core/Event/Coupon/CouponCreateOrUpdateEvent.php b/core/lib/Thelia/Core/Event/Coupon/CouponCreateOrUpdateEvent.php new file mode 100644 index 00000000..327ebd9c --- /dev/null +++ b/core/lib/Thelia/Core/Event/Coupon/CouponCreateOrUpdateEvent.php @@ -0,0 +1,462 @@ + + * + */ +class CouponCreateOrUpdateEvent extends ActionEvent +{ + /** @var ConditionCollection Array of ConditionInterface */ + protected $conditions = null; + + /** @var string Coupon code (ex: XMAS) */ + protected $code = null; + + /** @var string Coupon title (ex: Coupon for XMAS) */ + protected $title = null; + + /** @var string Coupon short description */ + protected $shortDescription = null; + + /** @var string Coupon description */ + protected $description = null; + + /** @var bool if Coupon is enabled */ + protected $isEnabled = false; + + /** @var \DateTime Coupon start date */ + protected $startDate = null; + + /** @var \DateTime Coupon expiration date */ + protected $expirationDate = null; + + /** @var bool if Coupon is cumulative */ + protected $isCumulative = false; + + /** @var bool if Coupon is removing postage */ + protected $isRemovingPostage = false; + + /** @var float Amount that will be removed from the Checkout (Coupon Effect) */ + protected $amount = 0; + + /** @var array Effects ready to be serialized */ + protected $effects = array(); + + /** @var int Max time a Coupon can be used (-1 = unlimited) */ + protected $maxUsage = -1; + + /** @var bool if Coupon is available for Products already on special offers */ + protected $isAvailableOnSpecialOffers = false; + + /** @var Coupon Coupon model */ + protected $couponModel = null; + + /** @var string Coupon Service id */ + protected $serviceId; + + /** @var string Language code ISO (ex: fr_FR) */ + protected $locale = null; + + /** @var array ID of Countries to which shipping is free */ + protected $freeShippingForCountries; + + /** @var array ID of Shipping modules for which shipping is free */ + protected $freeShippingForMethods; + + /** @var true if usage count is per customer only */ + protected $perCustomerUsageCount; + + /** + * Constructor + * + * @param string $code Coupon Code + * @param string $serviceId Coupon Service id + * @param string $title Coupon title + * @param array $effects Coupon effects ready to be serialized + * 'amount' key is mandatory and reflects + * the amount deduced from the cart + * @param string $shortDescription Coupon short description + * @param string $description Coupon description + * @param bool $isEnabled Enable/Disable + * @param \DateTime $expirationDate Coupon expiration date + * @param boolean $isAvailableOnSpecialOffers Is available on special offers + * @param boolean $isCumulative Is cumulative + * @param boolean $isRemovingPostage Is removing Postage + * @param int $maxUsage Coupon quantity + * @param string $locale Coupon Language code ISO (ex: fr_FR) + * @param array $freeShippingForCountries ID of Countries to which shipping is free + * @param array $freeShippingForMethods ID of Shipping modules for which shipping is free + * @param boolean $perCustomerUsageCount Usage count is per customer + * @param \DateTime $startDate Coupon start date + */ + public function __construct( + $code, + $serviceId, + $title, + array $effects, + $shortDescription, + $description, + $isEnabled, + \DateTime $expirationDate, + $isAvailableOnSpecialOffers, + $isCumulative, + $isRemovingPostage, + $maxUsage, + $locale, + $freeShippingForCountries, + $freeShippingForMethods, + $perCustomerUsageCount, + \DateTime $startDate = null + ) { + $this->code = $code; + $this->description = $description; + $this->expirationDate = $expirationDate; + $this->isAvailableOnSpecialOffers = $isAvailableOnSpecialOffers; + $this->isCumulative = $isCumulative; + $this->isEnabled = $isEnabled; + $this->isRemovingPostage = $isRemovingPostage; + $this->maxUsage = $maxUsage; + $this->shortDescription = $shortDescription; + $this->title = $title; + $this->serviceId = $serviceId; + $this->locale = $locale; + $this->setEffects($effects); + $this->freeShippingForCountries = $freeShippingForCountries; + $this->freeShippingForMethods = $freeShippingForMethods; + $this->perCustomerUsageCount = $perCustomerUsageCount; + $this->startDate = $startDate; + } + + /** + * @param true $perCustomerUsageCount + */ + public function setPerCustomerUsageCount($perCustomerUsageCount) + { + $this->perCustomerUsageCount = $perCustomerUsageCount; + + return $this; + } + + /** + * @return true + */ + public function getPerCustomerUsageCount() + { + return $this->perCustomerUsageCount; + } + + /** + * @param array $freeShippingForCountries + * @return $this + */ + public function setFreeShippingForCountries($freeShippingForCountries) + { + $this->freeShippingForCountries = $freeShippingForCountries; + + return $this; + } + + /** + * @return array + */ + public function getFreeShippingForCountries() + { + return $this->freeShippingForCountries; + } + + /** + * @param array $freeShippingForMethods + * @return $this + */ + public function setFreeShippingForMethods($freeShippingForMethods) + { + $this->freeShippingForMethods = $freeShippingForMethods; + + return $this; + } + + /** + * @return array + */ + public function getFreeShippingForMethods() + { + return $this->freeShippingForMethods; + } + + /** + * Return Coupon code (ex: XMAS) + * + * @return string + */ + public function getCode() + { + return $this->code; + } + + /** + * Return Coupon title (ex: Coupon for XMAS) + * + * @return string + */ + public function getTitle() + { + return $this->title; + } + + /** + * Return Coupon short description + * + * @return string + */ + public function getShortDescription() + { + return $this->shortDescription; + } + + /** + * Return Coupon description + * + * @return string + */ + public function getDescription() + { + return $this->description; + } + + /** + * If Coupon is cumulative or prevent any accumulation + * If is cumulative you can sum Coupon effects + * If not cancel all other Coupon and take the last given + * + * @return bool + */ + public function isCumulative() + { + return $this->isCumulative; + } + + /** + * If Coupon is removing Checkout Postage + * + * @return bool + */ + public function isRemovingPostage() + { + return $this->isRemovingPostage; + } + + /** + * Return effects generated by the coupon + * + * @return float Amount removed from the Total Checkout + */ + public function getAmount() + { + return $this->effects['amount']; + } + + /** + * Return Coupon start date + * + * @return \DateTime + */ + public function getStartDate() + { + if ($this->startDate === null) { + return null; + } + return clone $this->startDate; + } + + /** + * Return Coupon expiration date + * + * @return \DateTime + */ + public function getExpirationDate() + { + return clone $this->expirationDate; + } + + /** + * If Coupon is available on special offers + * + * @return boolean + */ + public function isAvailableOnSpecialOffers() + { + return $this->isAvailableOnSpecialOffers; + } + + /** + * Get if Coupon is enabled or not + * + * @return boolean + */ + public function isEnabled() + { + return $this->isEnabled; + } + + /** + * Return how many time the Coupon can be used again + * Ex : -1 unlimited + * + * @return int + */ + public function getMaxUsage() + { + return $this->maxUsage; + } + + /** + * Get Coupon Service id (Type) + * + * @return string + */ + public function getServiceId() + { + return $this->serviceId; + } + + /** + * Coupon Language code ISO (ex: fr_FR) + * + * @return string + */ + public function getLocale() + { + return $this->locale; + } + + /** + * Set effects ready to be serialized + * + * @param array $effects Effect ready to be serialized + * Needs at least the key 'amount' + * with the amount removed from the cart + * @throws \Thelia\Model\Exception\InvalidArgumentException + */ + public function setEffects(array $effects) + { + // Amount is now optionnal. + $this->amount = isset($effects['amount']) ? $effects['amount'] : 0; + + $this->effects = $effects; + } + + /** + * Get effects ready to be serialized + * + * @return array + */ + public function getEffects() + { + return $this->effects; + } + + /** + * Get if the Coupon will be available on special offers or not + * + * @return boolean + */ + public function getIsAvailableOnSpecialOffers() + { + return $this->isAvailableOnSpecialOffers; + } + + /** + * Get if the Coupon effect cancel other Coupon effects + * + * @return boolean + */ + public function getIsCumulative() + { + return $this->isCumulative; + } + + /** + * Get if Coupon is enabled or not + * + * @return boolean + */ + public function getIsEnabled() + { + return $this->isEnabled; + } + + /** + * @return boolean + */ + public function getIsRemovingPostage() + { + return $this->isRemovingPostage; + } + + /** + * Set Coupon Model + * + * @param Coupon $couponModel Coupon Model + * + * @return $this + */ + public function setCouponModel(Coupon $couponModel) + { + $this->couponModel = $couponModel; + + return $this; + } + + /** + * Return Coupon Model + * + * @return \Thelia\Model\Coupon + */ + public function getCouponModel() + { + return $this->couponModel; + } + + /** + * Get Conditions + * + * @return null|ConditionCollection Array of ConditionInterface + */ + public function getConditions() + { + return $this->conditions; + } + + /** + * Set Conditions + * + * @param ConditionCollection $conditions Array of ConditionInterface + * + * @return $this + */ + public function setConditions(ConditionCollection $conditions) + { + $this->conditions = $conditions; + + return $this; + } +} diff --git a/core/lib/Thelia/Core/Event/Coupon/CouponDeleteEvent.php b/core/lib/Thelia/Core/Event/Coupon/CouponDeleteEvent.php new file mode 100644 index 00000000..da38ad2f --- /dev/null +++ b/core/lib/Thelia/Core/Event/Coupon/CouponDeleteEvent.php @@ -0,0 +1,70 @@ + + */ +class CouponDeleteEvent extends ActionEvent +{ + /** @var Coupon */ + protected $coupon; + + protected $couponId; + + public function __construct($couponId, Coupon $coupon = null) + { + $this->coupon = $coupon; + } + + /** + * @return Coupon + */ + public function getCoupon() + { + return $this->coupon; + } + + /** + * @param Coupon $coupon + * @return $this + */ + public function setCoupon(Coupon $coupon = null) + { + $this->coupon = $coupon; + return $this; + } + + /** + * @return mixed + */ + public function getCouponId() + { + return $this->couponId; + } + + /** + * @param mixed $couponId + * @return $this + */ + public function setCouponId($couponId) + { + $this->couponId = $couponId; + return $this; + } +} diff --git a/core/lib/Thelia/Core/Event/Currency/CurrencyChangeEvent.php b/core/lib/Thelia/Core/Event/Currency/CurrencyChangeEvent.php new file mode 100644 index 00000000..75d84101 --- /dev/null +++ b/core/lib/Thelia/Core/Event/Currency/CurrencyChangeEvent.php @@ -0,0 +1,52 @@ + + */ +class CurrencyChangeEvent extends CurrencyEvent +{ + /** @var Request $request */ + protected $request; + + public function __construct(Currency $currency = null, Request $request = null) + { + parent::__construct($currency); + $this->setRequest($request); + } + + /** + * @param Request $request + * @return $this + */ + public function setRequest(Request $request) + { + $this->request = $request; + + return $this; + } + + /** + * @return Request + */ + public function getRequest() + { + return $this->request; + } +} diff --git a/core/lib/Thelia/Core/Event/Currency/CurrencyCreateEvent.php b/core/lib/Thelia/Core/Event/Currency/CurrencyCreateEvent.php new file mode 100644 index 00000000..4c51b635 --- /dev/null +++ b/core/lib/Thelia/Core/Event/Currency/CurrencyCreateEvent.php @@ -0,0 +1,96 @@ +currency_name; + } + + public function setCurrencyName($currency_name) + { + $this->currency_name = $currency_name; + + return $this; + } + + public function getLocale() + { + return $this->locale; + } + + public function setLocale($locale) + { + $this->locale = $locale; + + return $this; + } + + public function getSymbol() + { + return $this->symbol; + } + + public function setSymbol($symbol) + { + $this->symbol = $symbol; + + return $this; + } + + public function getFormat() + { + return $this->format; + } + + public function setFormat($format) + { + $this->format = $format; + + return $this; + } + + public function getCode() + { + return $this->code; + } + + public function setCode($code) + { + $this->code = $code; + + return $this; + } + + public function getRate() + { + return $this->rate; + } + + public function setRate($rate) + { + $this->rate = $rate; + + return $this; + } +} diff --git a/core/lib/Thelia/Core/Event/Currency/CurrencyDeleteEvent.php b/core/lib/Thelia/Core/Event/Currency/CurrencyDeleteEvent.php new file mode 100644 index 00000000..0a68bf70 --- /dev/null +++ b/core/lib/Thelia/Core/Event/Currency/CurrencyDeleteEvent.php @@ -0,0 +1,24 @@ +setCurrencyId($currencyId); + } +} diff --git a/core/lib/Thelia/Core/Event/Currency/CurrencyEvent.php b/core/lib/Thelia/Core/Event/Currency/CurrencyEvent.php new file mode 100644 index 00000000..11e33c1c --- /dev/null +++ b/core/lib/Thelia/Core/Event/Currency/CurrencyEvent.php @@ -0,0 +1,77 @@ +currency = $currency; + } + + /** + * @return bool + */ + public function hasCurrency() + { + return ! \is_null($this->currency); + } + + /** + * @return null|Currency + */ + public function getCurrency() + { + return $this->currency; + } + + /** + * @param Currency $currency + * @return $this + */ + public function setCurrency(Currency $currency) + { + $this->currency = $currency; + + return $this; + } + + /** + * @return mixed + */ + public function getCurrencyId() + { + return $this->currencyId; + } + + /** + * @param int $currencyId + * @return $this + */ + public function setCurrencyId($currencyId) + { + $this->currencyId = $currencyId; + + return $this; + } +} diff --git a/core/lib/Thelia/Core/Event/Currency/CurrencyUpdateEvent.php b/core/lib/Thelia/Core/Event/Currency/CurrencyUpdateEvent.php new file mode 100644 index 00000000..d243a2a4 --- /dev/null +++ b/core/lib/Thelia/Core/Event/Currency/CurrencyUpdateEvent.php @@ -0,0 +1,69 @@ +setCurrencyId($currencyId); + } + + /** + * @return int + */ + public function getIsDefault() + { + return $this->is_default; + } + + /** + * @param $is_default + * @return $this + */ + public function setIsDefault($is_default) + { + $this->is_default = $is_default; + + return $this; + } + + /** + * @return int + */ + public function getVisible() + { + return $this->visible; + } + + /** + * @param $visible + * @return $this + */ + public function setVisible($visible) + { + $this->visible = $visible; + + return $this; + } +} diff --git a/core/lib/Thelia/Core/Event/Currency/CurrencyUpdateRateEvent.php b/core/lib/Thelia/Core/Event/Currency/CurrencyUpdateRateEvent.php new file mode 100644 index 00000000..77b3ce8a --- /dev/null +++ b/core/lib/Thelia/Core/Event/Currency/CurrencyUpdateRateEvent.php @@ -0,0 +1,41 @@ +undefinedRates[] = $currencyId; + } + + public function hasUndefinedRates() + { + return ! empty($this->undefinedRates); + } + + /** + * @return array of currency objects + */ + public function getUndefinedRates() + { + return $this->undefinedRates; + } +} diff --git a/core/lib/Thelia/Core/Event/Customer/CustomerCreateOrUpdateEvent.php b/core/lib/Thelia/Core/Event/Customer/CustomerCreateOrUpdateEvent.php new file mode 100644 index 00000000..310960c0 --- /dev/null +++ b/core/lib/Thelia/Core/Event/Customer/CustomerCreateOrUpdateEvent.php @@ -0,0 +1,344 @@ + + */ +class CustomerCreateOrUpdateEvent extends CustomerEvent +{ + //base parameters for creating new customer + protected $title; + protected $firstname; + protected $lastname; + protected $address1; + protected $address2; + protected $address3; + protected $phone; + protected $cellphone; + protected $zipcode; + protected $city; + protected $country; + protected $state; + protected $email; + protected $password; + protected $langId; + protected $reseller; + protected $sponsor; + protected $discount; + protected $company; + protected $ref; + protected $emailUpdateAllowed; + + /** @var bool */ + protected $notifyCustomerOfAccountCreation; + /** @var bool */ + protected $notifyCustomerOfAccountModification = true; + + /** + * @param int $title the title customer id + * @param string $firstname + * @param string $lastname + * @param string $address1 + * @param string $address2 + * @param string $address3 + * @param string $phone + * @param string $cellphone + * @param string $zipcode + * @param string $city + * @param int $country the country id + * @param string $email + * @param string $password plain password, don't put hash password, it will hashes again + * @param $langId + * @param int $reseller if customer is a reseller + * @param int $sponsor customer's id sponsor + * @param float $discount + * @param string $company + * @param string $ref + * @param int $state thre State ID + */ + public function __construct( + $title, + $firstname, + $lastname, + $address1, + $address2, + $address3, + $phone, + $cellphone, + $zipcode, + $city, + $country, + $email, + $password, + $langId, + $reseller, + $sponsor, + $discount, + $company, + $ref, + $state = null + ) { + parent::__construct(); + + $this->address1 = $address1; + $this->address2 = $address2; + $this->address3 = $address3; + $this->country = $country; + $this->state = $state; + $this->email = $email; + $this->firstname = $firstname; + $this->langId = $langId; + $this->lastname = $lastname; + $this->password = $password; + $this->phone = $phone; + $this->cellphone = $cellphone; + $this->title = $title; + $this->zipcode = $zipcode; + $this->city = $city; + $this->reseller = $reseller; + $this->sponsor = $sponsor; + $this->discount = $discount; + $this->company = $company; + $this->ref = $ref; + } + + /** + * @return mixed + */ + public function getCompany() + { + return $this->company; + } + + /** + * @return string + */ + public function getAddress1() + { + return $this->address1; + } + + /** + * @return string + */ + public function getAddress2() + { + return $this->address2; + } + + /** + * @return string + */ + public function getAddress3() + { + return $this->address3; + } + + /** + * @return int + */ + public function getCountry() + { + return $this->country; + } + + /** + * @return int|null + */ + public function getState() + { + return $this->state; + } + + /** + * @return string + */ + public function getEmail() + { + return $this->email; + } + + /** + * @return string + */ + public function getFirstname() + { + return $this->firstname; + } + + /** + * @return mixed + */ + public function getLangId() + { + return $this->langId; + } + + /** + * @return string + */ + public function getLastname() + { + return $this->lastname; + } + + /** + * @return string + */ + public function getPassword() + { + return $this->password; + } + + /** + * @param string $password + * @return $this + */ + public function setPassword($password) + { + $this->password = $password; + + return $this; + } + + /** + * @return string + */ + public function getPhone() + { + return $this->phone; + } + + /** + * @return string + */ + public function getCellphone() + { + return $this->cellphone; + } + + /** + * @return int + */ + public function getTitle() + { + return $this->title; + } + + /** + * @return string + */ + public function getZipcode() + { + return $this->zipcode; + } + + /** + * @return string + */ + public function getCity() + { + return $this->city; + } + + /** + * @return float + */ + public function getDiscount() + { + return $this->discount; + } + + /** + * @return int + */ + public function getReseller() + { + return $this->reseller; + } + + /** + * @return int + */ + public function getSponsor() + { + return $this->sponsor; + } + + /** + * @return string + */ + public function getRef() + { + return $this->ref; + } + + /** + * @param mixed $emailUpdateAllowed + * @return $this + */ + public function setEmailUpdateAllowed($emailUpdateAllowed) + { + $this->emailUpdateAllowed = $emailUpdateAllowed; + + return $this; + } + + /** + * @return mixed + */ + public function getEmailUpdateAllowed() + { + return $this->emailUpdateAllowed; + } + + /** + * @param bool $notifyCustomerOfAccountCreation + * @return $this + */ + public function setNotifyCustomerOfAccountCreation($notifyCustomerOfAccountCreation) + { + $this->notifyCustomerOfAccountCreation = $notifyCustomerOfAccountCreation; + + return $this; + } + + /** + * @return bool + */ + public function getNotifyCustomerOfAccountCreation() + { + return $this->notifyCustomerOfAccountCreation; + } + + /** + * @return bool + */ + public function getNotifyCustomerOfAccountModification() + { + return $this->notifyCustomerOfAccountModification; + } + + /** + * @param bool $notifyCustomerOfAccountModification + * @return $this + */ + public function setNotifyCustomerOfAccountModification($notifyCustomerOfAccountModification) + { + $this->notifyCustomerOfAccountModification = $notifyCustomerOfAccountModification; + return $this; + } +} diff --git a/core/lib/Thelia/Core/Event/Customer/CustomerEvent.php b/core/lib/Thelia/Core/Event/Customer/CustomerEvent.php new file mode 100644 index 00000000..f2d7c97e --- /dev/null +++ b/core/lib/Thelia/Core/Event/Customer/CustomerEvent.php @@ -0,0 +1,57 @@ +customer = $customer; + } + + /** + * @param Customer $customer + * @return $this + */ + public function setCustomer(Customer $customer) + { + $this->customer = $customer; + + return $this; + } + + /** + * @return null|Customer + */ + public function getCustomer() + { + return $this->customer; + } + + /** + * @return bool + */ + public function hasCustomer() + { + return $this->customer != null; + } +} diff --git a/core/lib/Thelia/Core/Event/Customer/CustomerLoginEvent.php b/core/lib/Thelia/Core/Event/Customer/CustomerLoginEvent.php new file mode 100644 index 00000000..ea0e6f49 --- /dev/null +++ b/core/lib/Thelia/Core/Event/Customer/CustomerLoginEvent.php @@ -0,0 +1,18 @@ + + */ +class CustomerTitleEvent extends ActionEvent +{ + /** + * @var bool + */ + protected $default = false; + + /** + * @var string + */ + protected $short; + + /** + * @var string + */ + protected $long; + + /** + * @var string + */ + protected $locale; + + /** + * @var null|\Thelia\Model\CustomerTitle + */ + protected $customerTitle; + + /** + * @return \Thelia\Model\CustomerTitle + */ + public function getCustomerTitle() + { + return $this->customerTitle; + } + + /** + * @param null|\Thelia\Model\CustomerTitle $customerTitle + * @return $this + */ + public function setCustomerTitle(CustomerTitle $customerTitle = null) + { + $this->customerTitle = $customerTitle; + + return $this; + } + + /** + * @return boolean + */ + public function isDefault() + { + return $this->default; + } + + /** + * @param boolean $default + * @return $this + */ + public function setDefault($default) + { + $this->default = $default; + + return $this; + } + + /** + * @return string + */ + public function getLocale() + { + return $this->locale; + } + + /** + * @param string $locale + * @return $this + */ + public function setLocale($locale) + { + $this->locale = $locale; + + return $this; + } + + /** + * @return string + */ + public function getLong() + { + return $this->long; + } + + /** + * @param string $long + * @return $this + */ + public function setLong($long) + { + $this->long = $long; + + return $this; + } + + /** + * @return string + */ + public function getShort() + { + return $this->short; + } + + /** + * @param string $short + * @return $this + */ + public function setShort($short) + { + $this->short = $short; + + return $this; + } +} diff --git a/core/lib/Thelia/Core/Event/DefaultActionEvent.php b/core/lib/Thelia/Core/Event/DefaultActionEvent.php new file mode 100644 index 00000000..a4d4af46 --- /dev/null +++ b/core/lib/Thelia/Core/Event/DefaultActionEvent.php @@ -0,0 +1,17 @@ + + */ +class DeliveryPostageEvent extends ActionEvent +{ + /** @var BaseModuleInterface */ + protected $module = null; + + /** @var Cart */ + protected $cart = null; + + /** @var Address */ + protected $address = null; + + /** @var Country */ + protected $country = null; + + /** @var State */ + protected $state = null; + + /** @var bool */ + protected $validModule = false; + + /** @var OrderPostage|null */ + protected $postage = null; + + /** + * @var \DateTime|null + */ + protected $deliveryDate = null; + + /** + * @var string + */ + protected $deliveryMode = null; + + /** @var array */ + protected $additionalData = []; + + /** + * DeliveryPostageEvent constructor. + * @param $module + * @param Cart $cart + * @param Address|null $address + * @param Country $country + * @param State $state + */ + public function __construct( + $module, + Cart $cart, + Address $address = null, + Country $country = null, + State $state = null + ) { + $this->module = $module; + $this->cart = $cart; + $this->address = $address; + $this->country = $country; + $this->state = $state; + } + + /** + * @return Cart + */ + public function getCart() + { + return $this->cart; + } + + /** + * @param Cart $cart + * @return DeliveryPostageEvent + */ + public function setCart($cart) + { + $this->cart = $cart; + return $this; + } + + /** + * @return Address + */ + public function getAddress() + { + return $this->address; + } + + /** + * @param Address $address + * @return DeliveryPostageEvent + */ + public function setAddress($address) + { + $this->address = $address; + return $this; + } + + /** + * @return \DateTime|null + */ + public function getDeliveryDate() + { + return $this->deliveryDate; + } + + /** + * @param \DateTime|null $deliveryDate + * @return DeliveryPostageEvent + */ + public function setDeliveryDate($deliveryDate) + { + $this->deliveryDate = $deliveryDate; + return $this; + } + + /** + * @return AbstractDeliveryModule + */ + public function getModule() + { + return $this->module; + } + + /** + * @param AbstractDeliveryModule $module + * @return DeliveryPostageEvent + */ + public function setModule($module) + { + $this->module = $module; + return $this; + } + + /** + * @return null|OrderPostage + */ + public function getPostage() + { + return $this->postage; + } + + /** + * @param null|double|OrderPostage $postage + * @return DeliveryPostageEvent + */ + public function setPostage($postage) + { + $this->postage = OrderPostage::loadFromPostage($postage); + return $this; + } + + /** + * @return boolean + */ + public function isValidModule() + { + return $this->validModule; + } + + /** + * @param boolean $validModule + * @return DeliveryPostageEvent + */ + public function setValidModule($validModule) + { + $this->validModule = $validModule; + return $this; + } + + /** + * @return bool + */ + public function hasAdditionalData() + { + return \count($this->additionalData) > 0; + } + + /** + * @return array + */ + public function getAdditionalData() + { + return $this->additionalData; + } + + /** + * @param array $additionalData + * @return DeliveryPostageEvent + */ + public function setAdditionalData($additionalData) + { + $this->additionalData = $additionalData; + return $this; + } + + /** + * @param string $key the key of the additional data + * @param mixed $value the value of the additional data + * + * @return DeliveryPostageEvent + */ + public function addAdditionalData($key, $value) + { + $this->additionalData[$key] = $value; + + return $this; + } + + /** + * @return Country|null + * @throws \Propel\Runtime\Exception\PropelException + */ + public function getCountry() + { + return $this->getAddress() !== null ? $this->getAddress()->getCountry() : $this->country; + } + + /** + * @return State|null + * @throws \Propel\Runtime\Exception\PropelException + */ + public function getState() + { + return $this->getAddress() !== null ? $this->getAddress()->getState() : $this->state; + } + + /** + * @return mixed + */ + public function getDeliveryMode() + { + return $this->deliveryMode; + } + + /** + * @param mixed $deliveryMode + * + * @return DeliveryPostageEvent + * @throws \Exception + */ + public function setDeliveryMode($deliveryMode) + { + if (!in_array($deliveryMode, ['pickup', 'delivery'])) { + throw new \Exception(Translator::getInstance()->trans('A delivery module can only de of type pickup or delivery')); + } + + $this->deliveryMode = $deliveryMode; + return $this; + } +} diff --git a/core/lib/Thelia/Core/Event/Delivery/PickupLocationEvent.php b/core/lib/Thelia/Core/Event/Delivery/PickupLocationEvent.php new file mode 100644 index 00000000..f3ec7120 --- /dev/null +++ b/core/lib/Thelia/Core/Event/Delivery/PickupLocationEvent.php @@ -0,0 +1,293 @@ + + */ +class PickupLocationEvent extends ActionEvent +{ + /** + * @var string|null + */ + protected $address; + /** + * @var string|null + */ + protected $city; + /** + * @var string|null + */ + protected $zipCode; + /** + * @var State|null + */ + protected $state; + /** + * @var Country|null + */ + protected $country; + /** + * @var integer|null + */ + protected $radius; + /** + * @var integer|null + */ + protected $maxRelays; + /** + * @var integer|null + */ + protected $orderWeight; + /** + * @var array|null + */ + protected $moduleIds; + /** + * @var array + */ + protected $locations = []; + + /** + * PickupLocationEvent constructor. + * + * @param Address|null $addressModel + * @param integer|null $radius + * @param integer|null $maxRelays + * @param string|null $address + * @param string|null $city + * @param string|null $zipCode + * @param integer|null $orderWeight + * @param State|null $state + * @param Country|null $country + * @param array|null $moduleIds + * @throws \Propel\Runtime\Exception\PropelException + */ + public function __construct( + Address $addressModel = null, + $radius = null, + $maxRelays = null, + $address = null, + $city = null, + $zipCode = null, + $orderWeight = null, + State $state = null, + Country $country = null, + array $moduleIds = null + ) { + $this->radius = $radius !== null ? $radius : 20000; + $this->maxRelays = $maxRelays !== null ? $maxRelays : 15; + $this->orderWeight = $orderWeight; + $this->address = $address; + $this->city = $city; + $this->zipCode = $zipCode; + $this->state = $state; + $this->country = $country; + $this->moduleIds = $moduleIds; + + if (null !== $addressModel) { + $this->address = $addressModel->getAddress1(); + $this->city = $addressModel->getCity(); + $this->zipCode = $addressModel->getZipcode(); + $this->state = $addressModel->getState(); + $this->country = $addressModel->getCountry(); + } + + if ($this->address === null && $this->city === null && $this->zipCode === null) { + throw new \Exception("Not enough informations to retrieve pickup locations"); + } + } + + /** + * @return string|null + */ + public function getAddress() + { + return $this->address; + } + + /** + * @param string|null $address + */ + public function setAddress($address) + { + $this->address = $address; + } + + /** + * @return string|null + */ + public function getCity() + { + return $this->city; + } + + /** + * @param string|null $city + */ + public function setCity($city) + { + $this->city = $city; + } + + /** + * @return string|null + */ + public function getZipCode() + { + return $this->zipCode; + } + + /** + * @param string|null $zipCode + */ + public function setZipCode($zipCode) + { + $this->zipCode = $zipCode; + } + + /** + * @return State|null + */ + public function getState() + { + return $this->state; + } + + /** + * @param State|null $state + */ + public function setState($state) + { + $this->state = $state; + } + + /** + * @return Country|null + */ + public function getCountry() + { + return $this->country; + } + + /** + * @param Country|null $country + */ + public function setCountry($country) + { + $this->country = $country; + } + + /** + * @return int|null + */ + public function getRadius() + { + return $this->radius; + } + + /** + * @param int|null $radius + */ + public function setRadius($radius) + { + $this->radius = $radius; + } + + /** + * @return array|null + */ + public function getModuleIds() + { + return $this->moduleIds; + } + + /** + * @param array|null $moduleIds + */ + public function setModuleIds($moduleIds) + { + $this->moduleIds = $moduleIds; + } + + /** @return array */ + public function getLocations() + { + return $this->locations; + } + + /** + * @param $locations PickupLocation[] + * @return PickupLocationEvent + */ + public function setLocations($locations) + { + $this->locations = $locations; + return $this; + } + + /** @param $location PickupLocation + * @return PickupLocationEvent + */ + public function appendLocation($location) + { + $this->locations[] = $location; + return $this; + } + + /** + * @return integer|null + */ + public function getOrderWeight() + { + return $this->orderWeight; + } + + /** + * @param integer|null $orderWeight + * @return PickupLocationEvent + */ + public function setOrderWeight($orderWeight) + { + $this->orderWeight = $orderWeight; + + return $this; + } + + /** + * @return int|null + */ + public function getMaxRelays() + { + return $this->maxRelays; + } + + /** + * @param int|null $maxRelays + * @return PickupLocationEvent + */ + public function setMaxRelays($maxRelays) + { + $this->maxRelays = $maxRelays; + + return $this; + } +} diff --git a/core/lib/Thelia/Core/Event/Document/DocumentEvent.php b/core/lib/Thelia/Core/Event/Document/DocumentEvent.php new file mode 100644 index 00000000..09c2d2b5 --- /dev/null +++ b/core/lib/Thelia/Core/Event/Document/DocumentEvent.php @@ -0,0 +1,74 @@ +documentPath; + } + + /** + * Set Document path + * + * @param string $documentPath the document file path + * + * @return $this + */ + public function setDocumentPath($documentPath) + { + $this->documentPath = $documentPath; + + return $this; + } + + /** + * Get Document URL + * + * @return string The document URL + */ + public function getDocumentUrl() + { + return $this->documentUrl; + } + + /** + * Set Document URL + * + * @param string $documentUrl the document URL + * + * @return $this + */ + public function setDocumentUrl($documentUrl) + { + $this->documentUrl = $documentUrl; + + return $this; + } +} diff --git a/core/lib/Thelia/Core/Event/ExportEvent.php b/core/lib/Thelia/Core/Event/ExportEvent.php new file mode 100644 index 00000000..d7dad839 --- /dev/null +++ b/core/lib/Thelia/Core/Event/ExportEvent.php @@ -0,0 +1,158 @@ + + */ +class ExportEvent extends Event +{ + /** + * @var \Thelia\ImportExport\Export\AbstractExport An export + */ + protected $export; + + /** + * @var \Thelia\Core\Serializer\SerializerInterface A serializer interface + */ + protected $serializer; + + /** + * @var null|\Thelia\Core\Archiver\ArchiverInterface An archiver interface + */ + protected $archiver; + + /** + * @var string Path to generated export + */ + protected $filePath; + + /** + * Event constructor + * + * @param \Thelia\ImportExport\Export\AbstractExport $export An export + * @param \Thelia\Core\Serializer\SerializerInterface $serializer A serializer interface + * @param \Thelia\Core\Archiver\ArchiverInterface $archiver An archiver interface + */ + public function __construct( + AbstractExport $export, + SerializerInterface $serializer, + ArchiverInterface $archiver = null + ) { + $this->export = $export; + $this->serializer = $serializer; + $this->archiver = $archiver; + } + + /** + * Get export + * + * @return \Thelia\ImportExport\Export\AbstractExport An export + */ + public function getExport() + { + return $this->export; + } + + /** + * Set export + * + * @param \Thelia\ImportExport\Export\AbstractExport $export An export + * + * @return $this Return $this, allow chaining + */ + public function setExport(AbstractExport $export) + { + $this->export = $export; + + return $this; + } + + /** + * Get serializer + * + * @return \Thelia\Core\Serializer\SerializerInterface A serializer interface + */ + public function getSerializer() + { + return $this->serializer; + } + + /** + * Set serializer + * + * @param \Thelia\Core\Serializer\SerializerInterface $serializer A serializer interface + * + * @return $this Return $this, allow chaining + */ + public function setSerializer(SerializerInterface $serializer) + { + $this->serializer = $serializer; + + return $this; + } + + /** + * Get archiver + * + * @return mixed|\Thelia\Core\Archiver\ArchiverInterface An archiver interface + */ + public function getArchiver() + { + return $this->archiver; + } + + /** + * Set archiver + * + * @param mixed|\Thelia\Core\Archiver\ArchiverInterface $archiver An archiver interface + * + * @return $this Return $this, allow chaining + */ + public function setArchiver(ArchiverInterface $archiver = null) + { + $this->archiver = $archiver; + + return $this; + } + + /** + * Get export file path + * + * @return string Export file path + */ + public function getFilePath() + { + return $this->filePath; + } + + /** + * Set export file path + * + * @param string $filePath Export file path + * + * @return $this Return $this, allow chaining + */ + public function setFilePath($filePath) + { + $this->filePath = $filePath; + + return $this; + } +} diff --git a/core/lib/Thelia/Core/Event/Feature/FeatureAvCreateEvent.php b/core/lib/Thelia/Core/Event/Feature/FeatureAvCreateEvent.php new file mode 100644 index 00000000..32a1f478 --- /dev/null +++ b/core/lib/Thelia/Core/Event/Feature/FeatureAvCreateEvent.php @@ -0,0 +1,56 @@ +locale; + } + + public function setLocale($locale) + { + $this->locale = $locale; + + return $this; + } + + public function getTitle() + { + return $this->title; + } + + public function setTitle($title) + { + $this->title = $title; + + return $this; + } + + public function getFeatureId() + { + return $this->feature_id; + } + + public function setFeatureId($feature_id) + { + $this->feature_id = $feature_id; + + return $this; + } +} diff --git a/core/lib/Thelia/Core/Event/Feature/FeatureAvDeleteEvent.php b/core/lib/Thelia/Core/Event/Feature/FeatureAvDeleteEvent.php new file mode 100644 index 00000000..999f788c --- /dev/null +++ b/core/lib/Thelia/Core/Event/Feature/FeatureAvDeleteEvent.php @@ -0,0 +1,39 @@ +setFeatureAvId($featureAv_id); + } + + public function getFeatureAvId() + { + return $this->featureAv_id; + } + + public function setFeatureAvId($featureAv_id) + { + $this->featureAv_id = $featureAv_id; + + return $this; + } +} diff --git a/core/lib/Thelia/Core/Event/Feature/FeatureAvEvent.php b/core/lib/Thelia/Core/Event/Feature/FeatureAvEvent.php new file mode 100644 index 00000000..6a48a8a1 --- /dev/null +++ b/core/lib/Thelia/Core/Event/Feature/FeatureAvEvent.php @@ -0,0 +1,46 @@ +featureAv = $featureAv; + } + + public function hasFeatureAv() + { + return ! \is_null($this->featureAv); + } + + public function getFeatureAv() + { + return $this->featureAv; + } + + public function setFeatureAv($featureAv) + { + $this->featureAv = $featureAv; + + return $this; + } +} diff --git a/core/lib/Thelia/Core/Event/Feature/FeatureAvUpdateEvent.php b/core/lib/Thelia/Core/Event/Feature/FeatureAvUpdateEvent.php new file mode 100644 index 00000000..13b1aa56 --- /dev/null +++ b/core/lib/Thelia/Core/Event/Feature/FeatureAvUpdateEvent.php @@ -0,0 +1,79 @@ +setFeatureAvId($featureAv_id); + } + + public function getFeatureAvId() + { + return $this->featureAv_id; + } + + public function setFeatureAvId($featureAv_id) + { + $this->featureAv_id = $featureAv_id; + + return $this; + } + + public function getDescription() + { + return $this->description; + } + + public function setDescription($description) + { + $this->description = $description; + + return $this; + } + + public function getChapo() + { + return $this->chapo; + } + + public function setChapo($chapo) + { + $this->chapo = $chapo; + + return $this; + } + + public function getPostscriptum() + { + return $this->postscriptum; + } + + public function setPostscriptum($postscriptum) + { + $this->postscriptum = $postscriptum; + + return $this; + } +} diff --git a/core/lib/Thelia/Core/Event/Feature/FeatureCreateEvent.php b/core/lib/Thelia/Core/Event/Feature/FeatureCreateEvent.php new file mode 100644 index 00000000..dad266e6 --- /dev/null +++ b/core/lib/Thelia/Core/Event/Feature/FeatureCreateEvent.php @@ -0,0 +1,56 @@ +locale; + } + + public function setLocale($locale) + { + $this->locale = $locale; + + return $this; + } + + public function getTitle() + { + return $this->title; + } + + public function setTitle($title) + { + $this->title = $title; + + return $this; + } + + public function getAddToAllTemplates() + { + return $this->add_to_all_templates; + } + + public function setAddToAllTemplates($add_to_all_templates) + { + $this->add_to_all_templates = $add_to_all_templates; + + return $this; + } +} diff --git a/core/lib/Thelia/Core/Event/Feature/FeatureDeleteEvent.php b/core/lib/Thelia/Core/Event/Feature/FeatureDeleteEvent.php new file mode 100644 index 00000000..545151cf --- /dev/null +++ b/core/lib/Thelia/Core/Event/Feature/FeatureDeleteEvent.php @@ -0,0 +1,39 @@ +setFeatureId($feature_id); + } + + public function getFeatureId() + { + return $this->feature_id; + } + + public function setFeatureId($feature_id) + { + $this->feature_id = $feature_id; + + return $this; + } +} diff --git a/core/lib/Thelia/Core/Event/Feature/FeatureEvent.php b/core/lib/Thelia/Core/Event/Feature/FeatureEvent.php new file mode 100644 index 00000000..17830eb0 --- /dev/null +++ b/core/lib/Thelia/Core/Event/Feature/FeatureEvent.php @@ -0,0 +1,46 @@ +feature = $feature; + } + + public function hasFeature() + { + return ! \is_null($this->feature); + } + + public function getFeature() + { + return $this->feature; + } + + public function setFeature($feature) + { + $this->feature = $feature; + + return $this; + } +} diff --git a/core/lib/Thelia/Core/Event/Feature/FeatureUpdateEvent.php b/core/lib/Thelia/Core/Event/Feature/FeatureUpdateEvent.php new file mode 100644 index 00000000..522b21a3 --- /dev/null +++ b/core/lib/Thelia/Core/Event/Feature/FeatureUpdateEvent.php @@ -0,0 +1,79 @@ +setFeatureId($feature_id); + } + + public function getFeatureId() + { + return $this->feature_id; + } + + public function setFeatureId($feature_id) + { + $this->feature_id = $feature_id; + + return $this; + } + + public function getDescription() + { + return $this->description; + } + + public function setDescription($description) + { + $this->description = $description; + + return $this; + } + + public function getChapo() + { + return $this->chapo; + } + + public function setChapo($chapo) + { + $this->chapo = $chapo; + + return $this; + } + + public function getPostscriptum() + { + return $this->postscriptum; + } + + public function setPostscriptum($postscriptum) + { + $this->postscriptum = $postscriptum; + + return $this; + } +} diff --git a/core/lib/Thelia/Core/Event/FeatureProduct/FeatureProductDeleteEvent.php b/core/lib/Thelia/Core/Event/FeatureProduct/FeatureProductDeleteEvent.php new file mode 100644 index 00000000..ae5050e7 --- /dev/null +++ b/core/lib/Thelia/Core/Event/FeatureProduct/FeatureProductDeleteEvent.php @@ -0,0 +1,60 @@ +product_id = $product_id; + $this->feature_id = $feature_id; + } + + public function getProductId() + { + return $this->product_id; + } + + public function setProductId($product_id) + { + $this->product_id = $product_id; + + return $this; + } + + public function getFeatureId() + { + return $this->feature_id; + } + + public function setFeatureId($feature_id) + { + $this->feature_id = $feature_id; + + return $this; + } +} diff --git a/core/lib/Thelia/Core/Event/FeatureProduct/FeatureProductEvent.php b/core/lib/Thelia/Core/Event/FeatureProduct/FeatureProductEvent.php new file mode 100644 index 00000000..e908e5b5 --- /dev/null +++ b/core/lib/Thelia/Core/Event/FeatureProduct/FeatureProductEvent.php @@ -0,0 +1,46 @@ +featureProduct = $featureProduct; + } + + public function hasFeatureProduct() + { + return ! \is_null($this->featureProduct); + } + + public function getFeatureProduct() + { + return $this->featureProduct; + } + + public function setFeatureProduct($featureProduct) + { + $this->featureProduct = $featureProduct; + + return $this; + } +} diff --git a/core/lib/Thelia/Core/Event/FeatureProduct/FeatureProductUpdateEvent.php b/core/lib/Thelia/Core/Event/FeatureProduct/FeatureProductUpdateEvent.php new file mode 100644 index 00000000..67b11681 --- /dev/null +++ b/core/lib/Thelia/Core/Event/FeatureProduct/FeatureProductUpdateEvent.php @@ -0,0 +1,112 @@ +product_id = $product_id; + $this->feature_id = $feature_id; + $this->feature_value = $feature_value; + $this->setIsTextValue($is_text_value); + } + + /** + * @return int the product id + */ + public function getProductId() + { + return $this->product_id; + } + + /** + * @param $product_id + * @return $this + */ + public function setProductId($product_id) + { + $this->product_id = $product_id; + + return $this; + } + + /** + * @return int + */ + public function getFeatureId() + { + return $this->feature_id; + } + + /** + * @param $feature_id + * @return $this + */ + public function setFeatureId($feature_id) + { + $this->feature_id = $feature_id; + + return $this; + } + + public function getFeatureValue() + { + return $this->feature_value; + } + + public function setFeatureValue($feature_value) + { + $this->feature_value = $feature_value; + + return $this; + } + + public function getIsTextValue() + { + return (bool)$this->is_text_value; + } + + public function setIsTextValue($is_text_value) + { + $this->is_text_value = (bool)$is_text_value; + + return $this; + } + + public function getLocale() + { + return $this->locale; + } + + public function setLocale($locale) + { + $this->locale = $locale; + } +} diff --git a/core/lib/Thelia/Core/Event/File/FileCreateOrUpdateEvent.php b/core/lib/Thelia/Core/Event/File/FileCreateOrUpdateEvent.php new file mode 100644 index 00000000..b1d3876c --- /dev/null +++ b/core/lib/Thelia/Core/Event/File/FileCreateOrUpdateEvent.php @@ -0,0 +1,168 @@ + + * + */ +class FileCreateOrUpdateEvent extends ActionEvent +{ + /** @var FileModelInterface model to save */ + protected $model = array(); + + /** @var FileModelInterface model to save */ + protected $oldModel = array(); + + /** @var UploadedFile Document file to save */ + protected $uploadedFile = null; + + /** @var int Document parent id */ + protected $parentId = null; + + /** @var string Parent name */ + protected $parentName = null; + + /** + * Constructor + * + * @param int $parentId file parent id + */ + public function __construct($parentId) + { + $this->parentId = $parentId; + } + + /** + * Set file to save + * + * @param FileModelInterface $model Document to save + * + * @return $this + */ + public function setModel($model) + { + $this->model = $model; + + return $this; + } + + /** + * Get file being saved + * + * @return FileModelInterface + */ + public function getModel() + { + return $this->model; + } + + /** + * Set Document parent id + * + * @param int $parentId Document parent id + * + * @return $this + */ + public function setParentId($parentId) + { + $this->parentId = $parentId; + + return $this; + } + + /** + * Get Document parent id + * + * @return int + */ + public function getParentId() + { + return $this->parentId; + } + + /** + * Set uploaded file + * + * @param UploadedFile|null $uploadedFile File being uploaded + * + * @return $this + */ + public function setUploadedFile($uploadedFile) + { + $this->uploadedFile = $uploadedFile; + + return $this; + } + + /** + * Get uploaded file + * + * @return UploadedFile|null + */ + public function getUploadedFile() + { + return $this->uploadedFile; + } + + /** + * Set parent name + * + * @param string $parentName Parent name + * + * @return $this + */ + public function setParentName($parentName) + { + $this->parentName = $parentName; + + return $this; + } + + /** + * Get parent name + * + * @return string + */ + public function getParentName() + { + return $this->parentName; + } + + /** + * Set old model value + * + * @param FileModelInterface $oldModel + */ + public function setOldModel($oldModel) + { + $this->oldModel = $oldModel; + } + + /** + * Get old model value + * + * @return FileModelInterface + */ + public function getOldModel() + { + return $this->oldModel; + } +} diff --git a/core/lib/Thelia/Core/Event/File/FileDeleteEvent.php b/core/lib/Thelia/Core/Event/File/FileDeleteEvent.php new file mode 100644 index 00000000..ba803382 --- /dev/null +++ b/core/lib/Thelia/Core/Event/File/FileDeleteEvent.php @@ -0,0 +1,61 @@ + + */ +class FileDeleteEvent extends ActionEvent +{ + /** @var FileModelInterface Image about to be deleted */ + protected $fileToDelete = null; + + /** + * Constructor + * + * @param FileModelInterface $fileToDelete Image about to be deleted + */ + public function __construct($fileToDelete) + { + $this->fileToDelete = $fileToDelete; + } + + /** + * Set Image about to be deleted + * + * @param FileModelInterface $fileToDelete Image about to be deleted + * + * @return $this + */ + public function setFileToDelete($fileToDelete) + { + $this->fileToDelete = $fileToDelete; + + return $this; + } + + /** + * Get Image about to be deleted + * + * @return FileModelInterface + */ + public function getFileToDelete() + { + return $this->fileToDelete; + } +} diff --git a/core/lib/Thelia/Core/Event/File/FileToggleVisibilityEvent.php b/core/lib/Thelia/Core/Event/File/FileToggleVisibilityEvent.php new file mode 100644 index 00000000..daca9673 --- /dev/null +++ b/core/lib/Thelia/Core/Event/File/FileToggleVisibilityEvent.php @@ -0,0 +1,53 @@ + + */ +class FileToggleVisibilityEvent extends ToggleVisibilityEvent +{ + protected $query; + + /** + * @param ModelCriteria $query + * @param $object_id + */ + public function __construct(ModelCriteria $query, $object_id) + { + parent::__construct($object_id); + + $this->setQuery($query); + } + + /** + * @param ModelCriteria $query + */ + public function setQuery(ModelCriteria $query) + { + $this->query = $query; + } + + /** + * @return ModelCriteria|null + */ + public function getQuery() + { + return $this->query; + } +} diff --git a/core/lib/Thelia/Core/Event/Folder/FolderCreateEvent.php b/core/lib/Thelia/Core/Event/Folder/FolderCreateEvent.php new file mode 100644 index 00000000..ff17c409 --- /dev/null +++ b/core/lib/Thelia/Core/Event/Folder/FolderCreateEvent.php @@ -0,0 +1,107 @@ + + */ +class FolderCreateEvent extends FolderEvent +{ + protected $title; + protected $parent; + protected $locale; + protected $visible; + + /** + * @param mixed $locale + * + * @return $this + */ + public function setLocale($locale) + { + $this->locale = $locale; + + return $this; + } + + /** + * @return mixed + */ + public function getLocale() + { + return $this->locale; + } + + /** + * @param mixed $parent + * + * + * @return $this + */ + public function setParent($parent) + { + $this->parent = $parent; + + return $this; + } + + /** + * @return mixed + */ + public function getParent() + { + return $this->parent; + } + + /** + * @param mixed $title + * + * @return $this + */ + public function setTitle($title) + { + $this->title = $title; + + return $this; + } + + /** + * @return mixed + */ + public function getTitle() + { + return $this->title; + } + + /** + * @param mixed $visible + * + * @return $this + */ + public function setVisible($visible) + { + $this->visible = $visible; + + return $this; + } + + /** + * @return mixed + */ + public function getVisible() + { + return $this->visible; + } +} diff --git a/core/lib/Thelia/Core/Event/Folder/FolderDeleteEvent.php b/core/lib/Thelia/Core/Event/Folder/FolderDeleteEvent.php new file mode 100644 index 00000000..baacfd4c --- /dev/null +++ b/core/lib/Thelia/Core/Event/Folder/FolderDeleteEvent.php @@ -0,0 +1,50 @@ + + */ +class FolderDeleteEvent extends FolderEvent +{ + /** + * @var int folder id + */ + protected $folder_id; + + /** + * @param int $folder_id + */ + public function __construct($folder_id) + { + $this->folder_id = $folder_id; + } + + /** + * @param int $folder_id + */ + public function setFolderId($folder_id) + { + $this->folder_id = $folder_id; + } + + /** + * @return int + */ + public function getFolderId() + { + return $this->folder_id; + } +} diff --git a/core/lib/Thelia/Core/Event/Folder/FolderEvent.php b/core/lib/Thelia/Core/Event/Folder/FolderEvent.php new file mode 100644 index 00000000..ab29fa65 --- /dev/null +++ b/core/lib/Thelia/Core/Event/Folder/FolderEvent.php @@ -0,0 +1,63 @@ + + * @deprecated since 2.4, please use \Thelia\Model\Event\FolderEvent + */ +class FolderEvent extends ActionEvent +{ + /** + * @var \Thelia\Model\Folder + */ + protected $folder; + + public function __construct(Folder $folder = null) + { + $this->folder = $folder; + } + + /** + * @param \Thelia\Model\Folder $folder + */ + public function setFolder(Folder $folder) + { + $this->folder = $folder; + + return $this; + } + + /** + * @return \Thelia\Model\Folder + */ + public function getFolder() + { + return $this->folder; + } + + /** + * test if a folder object exists + * + * @return bool + */ + public function hasFolder() + { + return null !== $this->folder; + } +} diff --git a/core/lib/Thelia/Core/Event/Folder/FolderToggleVisibilityEvent.php b/core/lib/Thelia/Core/Event/Folder/FolderToggleVisibilityEvent.php new file mode 100644 index 00000000..999f4de4 --- /dev/null +++ b/core/lib/Thelia/Core/Event/Folder/FolderToggleVisibilityEvent.php @@ -0,0 +1,22 @@ + + */ +class FolderToggleVisibilityEvent extends FolderEvent +{ +} diff --git a/core/lib/Thelia/Core/Event/Folder/FolderUpdateEvent.php b/core/lib/Thelia/Core/Event/Folder/FolderUpdateEvent.php new file mode 100644 index 00000000..afc8d421 --- /dev/null +++ b/core/lib/Thelia/Core/Event/Folder/FolderUpdateEvent.php @@ -0,0 +1,112 @@ + + */ +class FolderUpdateEvent extends FolderCreateEvent +{ + /** @var int */ + protected $folder_id; + + protected $chapo; + protected $description; + protected $postscriptum; + + /** + * @param int $folder_id + */ + public function __construct($folder_id) + { + $this->folder_id = $folder_id; + } + + /** + * @param mixed $chapo + * @return $this + */ + public function setChapo($chapo) + { + $this->chapo = $chapo; + + return $this; + } + + /** + * @return mixed + */ + public function getChapo() + { + return $this->chapo; + } + + /** + * @param mixed $description + * @return $this + */ + public function setDescription($description) + { + $this->description = $description; + + return $this; + } + + /** + * @return mixed + */ + public function getDescription() + { + return $this->description; + } + + /** + * @param mixed $folder_id + * @return $this + */ + public function setFolderId($folder_id) + { + $this->folder_id = $folder_id; + + return $this; + } + + /** + * @return mixed + */ + public function getFolderId() + { + return $this->folder_id; + } + + /** + * @param mixed $postscriptum + * @return $this + */ + public function setPostscriptum($postscriptum) + { + $this->postscriptum = $postscriptum; + + return $this; + } + + /** + * @return mixed + */ + public function getPostscriptum() + { + return $this->postscriptum; + } +} diff --git a/core/lib/Thelia/Core/Event/GenerateRewrittenUrlEvent.php b/core/lib/Thelia/Core/Event/GenerateRewrittenUrlEvent.php new file mode 100644 index 00000000..d70cadad --- /dev/null +++ b/core/lib/Thelia/Core/Event/GenerateRewrittenUrlEvent.php @@ -0,0 +1,103 @@ + + */ +class GenerateRewrittenUrlEvent extends ActionEvent +{ + /** @var mixed */ + protected $object; + + /** @var string local */ + protected $locale; + + /** @var string local */ + protected $url; + + /** + * GenerateRewrittenUrlEvent constructor. + * @param $object + * @param $locale + */ + public function __construct($object, $locale) + { + $this->object = $object; + $this->locale = $locale; + } + + /** + * @return string + */ + public function getLocale() + { + return $this->locale; + } + + /** + * @param string $locale + * @return $this + */ + public function setLocale($locale) + { + $this->locale = $locale; + return $this; + } + + /** + * @return mixed + */ + public function getObject() + { + return $this->object; + } + + /** + * @param mixed $object + * @return $this + */ + public function setObject($object) + { + $this->object = $object; + return $this; + } + + /** + * @param $url + * @return $this + */ + public function setUrl($url) + { + $this->url = $url; + return $this; + } + + /** + * @return bool + */ + public function isRewritten() + { + return null !== $this->url; + } + + /** + * @return string + */ + public function getUrl() + { + return $this->url; + } +} diff --git a/core/lib/Thelia/Core/Event/Hook/BaseHookRenderEvent.php b/core/lib/Thelia/Core/Event/Hook/BaseHookRenderEvent.php new file mode 100644 index 00000000..0380a5bc --- /dev/null +++ b/core/lib/Thelia/Core/Event/Hook/BaseHookRenderEvent.php @@ -0,0 +1,162 @@ + + * @author Franck Allimant + */ +class BaseHookRenderEvent extends Event +{ + /** @var string $code the code of the hook */ + protected $code = null; + + /** @var array $arguments an array of arguments passed to the template engine function */ + protected $arguments = []; + + /** @var array $templateVars the variable currently defined in the template */ + protected $templateVars = []; + + public function __construct($code, array $arguments = [], array $templateVars = []) + { + $this->code = $code; + $this->arguments = $arguments; + $this->templateVars = $templateVars; + } + + /** + * Set the code of the hook + * + * @param string $code + * @return $this + */ + public function setCode($code) + { + $this->code = $code; + + return $this; + } + + /** + * Get the code of the hook + * + * @return string + */ + public function getCode() + { + return $this->code; + } + + /** + * Set all arguments + * + * @param array $arguments + * @return $this + */ + public function setArguments($arguments) + { + $this->arguments = $arguments; + + return $this; + } + + /** + * Get all arguments + * + * @return array all arguments + */ + public function getArguments() + { + return $this->arguments; + } + + /** + * Get all template vars + * + * @return array all template vars + */ + public function getTemplateVars() + { + return $this->templateVars; + } + + /** + * add or replace an argument + * + * @param string $key + * @param string $value + * @return $this + */ + public function setArgument($key, $value) + { + $this->arguments[$key] = $value; + + return $this; + } + + /** + * Get an argument + * @param string $key + * @param string|null $default + * @return mixed|null the value of the argument or `$default` if it not exists + */ + public function getArgument($key, $default = null) + { + return array_key_exists($key, $this->arguments) ? $this->arguments[$key] : $default; + } + + /** + * Check if an argument exists with this key + * + * @param $key + * @return bool true if it exists, else false + */ + public function hasArgument($key) + { + return array_key_exists($key, $this->arguments); + } + + + /** + * Return a template variable value. An exception is thorwn if the variable is not defined. + * + * @param string $templateVariableName the variable name + * + * @return mixed the variable value + * @throws \InvalidArgumentException if the variable is not defined + */ + public function getTemplateVar($templateVariableName) + { + if (! isset($this->templateVars[$templateVariableName])) { + throw new \InvalidArgumentException(sprintf("Template variable '%s' is not defined.", $templateVariableName)); + } + + return $this->templateVars[$templateVariableName]; + } + + /** + * Check if a template variable is defined. + * + * @param $templateVariableName + * + * @return bool true if the template variable is defined, false otherwise + */ + public function hasTemplateVar($templateVariableName) + { + return isset($this->templateVars[$templateVariableName]); + } +} diff --git a/core/lib/Thelia/Core/Event/Hook/HookCreateAllEvent.php b/core/lib/Thelia/Core/Event/Hook/HookCreateAllEvent.php new file mode 100644 index 00000000..99321628 --- /dev/null +++ b/core/lib/Thelia/Core/Event/Hook/HookCreateAllEvent.php @@ -0,0 +1,241 @@ + + */ +class HookCreateAllEvent extends HookEvent +{ + /** @var string */ + protected $locale; + + /** @var string */ + protected $code; + + /** @var int */ + protected $type; + + /** @var bool */ + protected $native; + + /** @var bool */ + protected $active; + + /** @var bool */ + protected $by_module; + + /** @var bool */ + protected $block; + + /** @var string */ + protected $title; + + /** @var string */ + protected $chapo; + + /** @var string */ + protected $description; + + /** + * @param string $locale + * @return $this + */ + public function setLocale($locale) + { + $this->locale = $locale; + + return $this; + } + + /** + * @return string + */ + public function getLocale() + { + return $this->locale; + } + + /** + * @param bool $native + * @return $this + */ + public function setNative($native) + { + $this->native = $native; + + return $this; + } + + /** + * @return bool + */ + public function getNative() + { + return $this->native; + } + + /** + * @param string $title + * @return $this + */ + public function setTitle($title) + { + $this->title = $title; + + return $this; + } + + /** + * @return string + */ + public function getTitle() + { + return $this->title; + } + + /** + * @param int $type + * @return $this + */ + public function setType($type) + { + $this->type = $type; + + return $this; + } + + /** + * @return int + */ + public function getType() + { + return $this->type; + } + + /** + * @param bool $active + * @return $this + */ + public function setActive($active) + { + $this->active = $active; + + return $this; + } + + /** + * @return bool + */ + public function getActive() + { + return $this->active; + } + + /** + * @param string $code + * @return $this + */ + public function setCode($code) + { + $this->code = $code; + + return $this; + } + + /** + * @return string + */ + public function getCode() + { + return $this->code; + } + + /** + * @param bool $block + * @return $this + */ + public function setBlock($block) + { + $this->block = $block; + + return $this; + } + + /** + * @return bool + */ + public function getBlock() + { + return $this->block; + } + + /** + * @param bool $by_module + * @return $this + */ + public function setByModule($by_module) + { + $this->by_module = $by_module; + + return $this; + } + + /** + * @return bool + */ + public function getByModule() + { + return $this->by_module; + } + + /** + * @param string $chapo + * @return $this + */ + public function setChapo($chapo) + { + $this->chapo = $chapo; + + return $this; + } + + /** + * @return string + */ + public function getChapo() + { + return $this->chapo; + } + + /** + * @param string $description + * @return $this + */ + public function setDescription($description) + { + $this->description = $description; + + return $this; + } + + /** + * @return string + */ + public function getDescription() + { + return $this->description; + } +} diff --git a/core/lib/Thelia/Core/Event/Hook/HookCreateEvent.php b/core/lib/Thelia/Core/Event/Hook/HookCreateEvent.php new file mode 100644 index 00000000..4f9a18a6 --- /dev/null +++ b/core/lib/Thelia/Core/Event/Hook/HookCreateEvent.php @@ -0,0 +1,153 @@ + + */ +class HookCreateEvent extends HookEvent +{ + /** @var string */ + protected $locale; + + /** @var string */ + protected $code; + + /** @var int */ + protected $type; + + /** @var string */ + protected $title; + + /** @var int */ + protected $native; + + /** @var int */ + protected $active; + + /** + * @param string $locale + * @return $this + */ + public function setLocale($locale) + { + $this->locale = $locale; + + return $this; + } + + /** + * @return string + */ + public function getLocale() + { + return $this->locale; + } + + /** + * @param $native + * @return $this + */ + public function setNative($native) + { + $this->native = $native; + + return $this; + } + + /** + * @return mixed + */ + public function getNative() + { + return $this->native; + } + + /** + * @param $title + * @return $this + */ + public function setTitle($title) + { + $this->title = $title; + + return $this; + } + + /** + * @return mixed + */ + public function getTitle() + { + return $this->title; + } + + /** + * @param $type + * @return $this + */ + public function setType($type) + { + $this->type = $type; + + return $this; + } + + /** + * @return mixed + */ + public function getType() + { + return $this->type; + } + + /** + * @param $active + * @return $this + */ + public function setActive($active) + { + $this->active = $active; + + return $this; + } + + /** + * @return mixed + */ + public function getActive() + { + return $this->active; + } + + /** + * @param $code + * @return $this + */ + public function setCode($code) + { + $this->code = $code; + + return $this; + } + + /** + * @return mixed + */ + public function getCode() + { + return $this->code; + } +} diff --git a/core/lib/Thelia/Core/Event/Hook/HookDeactivationEvent.php b/core/lib/Thelia/Core/Event/Hook/HookDeactivationEvent.php new file mode 100644 index 00000000..edbfd7cb --- /dev/null +++ b/core/lib/Thelia/Core/Event/Hook/HookDeactivationEvent.php @@ -0,0 +1,51 @@ + + */ +class HookDeactivationEvent extends HookEvent +{ + /** @var int */ + protected $hook_id; + + /** + * @param int $hook_id + */ + public function __construct($hook_id) + { + $this->hook_id = $hook_id; + } + + /** + * @param mixed $hook_id + * @return $this + */ + public function setHookId($hook_id) + { + $this->hook_id = $hook_id; + + return $this; + } + + /** + * @return mixed + */ + public function getHookId() + { + return $this->hook_id; + } +} diff --git a/core/lib/Thelia/Core/Event/Hook/HookDeleteEvent.php b/core/lib/Thelia/Core/Event/Hook/HookDeleteEvent.php new file mode 100644 index 00000000..0f9bf2e0 --- /dev/null +++ b/core/lib/Thelia/Core/Event/Hook/HookDeleteEvent.php @@ -0,0 +1,51 @@ + + */ +class HookDeleteEvent extends HookEvent +{ + /** @var int */ + protected $hook_id; + + /** + * @param int $hook_id + */ + public function __construct($hook_id) + { + $this->hook_id = $hook_id; + } + + /** + * @param mixed $hook_id + * @return $this + */ + public function setHookId($hook_id) + { + $this->hook_id = $hook_id; + + return $this; + } + + /** + * @return int + */ + public function getHookId() + { + return $this->hook_id; + } +} diff --git a/core/lib/Thelia/Core/Event/Hook/HookEvent.php b/core/lib/Thelia/Core/Event/Hook/HookEvent.php new file mode 100644 index 00000000..9b9129e6 --- /dev/null +++ b/core/lib/Thelia/Core/Event/Hook/HookEvent.php @@ -0,0 +1,48 @@ + + */ +class HookEvent extends ActionEvent +{ + public $hook = null; + + public function __construct(Hook $hook = null) + { + $this->hook = $hook; + } + + public function hasHook() + { + return ! \is_null($this->hook); + } + + public function getHook() + { + return $this->hook; + } + + public function setHook(Hook $hook) + { + $this->hook = $hook; + + return $this; + } +} diff --git a/core/lib/Thelia/Core/Event/Hook/HookRenderBlockEvent.php b/core/lib/Thelia/Core/Event/Hook/HookRenderBlockEvent.php new file mode 100644 index 00000000..08a1806d --- /dev/null +++ b/core/lib/Thelia/Core/Event/Hook/HookRenderBlockEvent.php @@ -0,0 +1,94 @@ + + */ +class HookRenderBlockEvent extends BaseHookRenderEvent +{ + /** @var FragmentBag $fragmentBag */ + protected $fragmentBag; + + /** @var array fields that can be added, if empty array any fields can be added */ + protected $fields = []; + + public function __construct($code, array $arguments = [], array $fields = [], array $templateVariables = []) + { + parent::__construct($code, $arguments, $templateVariables); + $this->fragmentBag = new FragmentBag(); + $this->fields = $fields; + } + + /** + * Add a new fragment as an array + * + * @param array $data + * @return $this + */ + public function add($data) + { + $fragment = new Fragment($data); + + $this->addFragment($fragment); + + return $this; + } + + /** + * Add a new fragment + * + * @param \Thelia\Core\Hook\Fragment $fragment + * @return $this + */ + public function addFragment(Fragment $fragment) + { + if (!empty($this->fields)) { + $fragment->filter($this->fields); + } + $this->fragmentBag->addFragment($fragment); + + return $this; + } + + /** + * Get all contents + * + * @return FragmentBag + */ + public function get() + { + return $this->fragmentBag; + } + + /** + * @return array + */ + public function getFields() + { + return $this->fields; + } + + /** + * @param array $fields + */ + public function setFields(array $fields) + { + $this->fields = $fields; + } +} diff --git a/core/lib/Thelia/Core/Event/Hook/HookRenderEvent.php b/core/lib/Thelia/Core/Event/Hook/HookRenderEvent.php new file mode 100644 index 00000000..15fbd305 --- /dev/null +++ b/core/lib/Thelia/Core/Event/Hook/HookRenderEvent.php @@ -0,0 +1,73 @@ + + */ +class HookRenderEvent extends BaseHookRenderEvent +{ + /** @var array $fragments an array of fragments collected during the event dispatch */ + protected $fragments; + + public function __construct($code, array $arguments = [], array $templateVariables = []) + { + parent::__construct($code, $arguments, $templateVariables); + $this->fragments = array(); + } + + /** + * Add a new fragment + * + * @param string $content + * @return $this + */ + public function add($content) + { + $this->fragments[] = $content; + + return $this; + } + + /** + * Get an array of all the fragments + * + * @return array + */ + public function get() + { + return $this->fragments; + } + + /** + * Concatenates all fragments in a string. + * + * @param string $glue the glue between fragments + * @param string $before the text before the concatenated string + * @param string $after the text after the concatenated string + * @return string the concatenate string + */ + public function dump($glue = '', $before = '', $after = '') + { + $ret = ''; + if (0 !== \count($this->fragments)) { + $ret = $before . implode($glue, $this->fragments) . $after; + } + + return $ret; + } +} diff --git a/core/lib/Thelia/Core/Event/Hook/HookToggleActivationEvent.php b/core/lib/Thelia/Core/Event/Hook/HookToggleActivationEvent.php new file mode 100644 index 00000000..f1801652 --- /dev/null +++ b/core/lib/Thelia/Core/Event/Hook/HookToggleActivationEvent.php @@ -0,0 +1,51 @@ + + */ +class HookToggleActivationEvent extends HookEvent +{ + /** @var int */ + protected $hook_id; + + /** + * @param int $hook_id + */ + public function __construct($hook_id) + { + $this->hook_id = $hook_id; + } + + /** + * @param mixed $hook_id + * @return $this + */ + public function setHookId($hook_id) + { + $this->hook_id = $hook_id; + + return $this; + } + + /** + * @return mixed + */ + public function getHookId() + { + return $this->hook_id; + } +} diff --git a/core/lib/Thelia/Core/Event/Hook/HookToggleNativeEvent.php b/core/lib/Thelia/Core/Event/Hook/HookToggleNativeEvent.php new file mode 100644 index 00000000..da9b165a --- /dev/null +++ b/core/lib/Thelia/Core/Event/Hook/HookToggleNativeEvent.php @@ -0,0 +1,46 @@ + + */ +class HookToggleNativeEvent extends HookEvent +{ + protected $hook_id; + + public function __construct($hook_id) + { + $this->hook_id = $hook_id; + } + + /** + * @param mixed $hook_id + */ + public function setHookId($hook_id) + { + $this->hook_id = $hook_id; + + return $this; + } + + /** + * @return mixed + */ + public function getHookId() + { + return $this->hook_id; + } +} diff --git a/core/lib/Thelia/Core/Event/Hook/HookUpdateEvent.php b/core/lib/Thelia/Core/Event/Hook/HookUpdateEvent.php new file mode 100644 index 00000000..d66f47dd --- /dev/null +++ b/core/lib/Thelia/Core/Event/Hook/HookUpdateEvent.php @@ -0,0 +1,126 @@ + + */ +class HookUpdateEvent extends HookCreateEvent +{ + protected $hook_id; + protected $by_module; + protected $block; + protected $chapo; + protected $description; + + /** + * @param int $hook_id + */ + public function __construct($hook_id) + { + $this->hook_id = $hook_id; + } + + /** + * @param int $hook_id + * @return $this + */ + public function setHookId($hook_id) + { + $this->hook_id = $hook_id; + + return $this; + } + + /** + * @return \Thelia\Model\Hook + */ + public function getHookId() + { + return $this->hook_id; + } + + /** + * @param mixed $block + */ + public function setBlock($block) + { + $this->block = $block; + + return $this; + } + + /** + * @return mixed + */ + public function getBlock() + { + return $this->block; + } + + /** + * @param mixed $by_module + */ + public function setByModule($by_module) + { + $this->by_module = $by_module; + + return $this; + } + + /** + * @return mixed + */ + public function getByModule() + { + return $this->by_module; + } + + /** + * @param mixed $chapo + */ + public function setChapo($chapo) + { + $this->chapo = $chapo; + + return $this; + } + + /** + * @return mixed + */ + public function getChapo() + { + return $this->chapo; + } + + /** + * @param mixed $description + */ + public function setDescription($description) + { + $this->description = $description; + + return $this; + } + + /** + * @return mixed + */ + public function getDescription() + { + return $this->description; + } +} diff --git a/core/lib/Thelia/Core/Event/Hook/ModuleHookCreateEvent.php b/core/lib/Thelia/Core/Event/Hook/ModuleHookCreateEvent.php new file mode 100644 index 00000000..5b78f97b --- /dev/null +++ b/core/lib/Thelia/Core/Event/Hook/ModuleHookCreateEvent.php @@ -0,0 +1,131 @@ + + */ +class ModuleHookCreateEvent extends ModuleHookEvent +{ + /** @var int */ + protected $module_id; + + /** @var int */ + protected $hook_id; + + /** @var string */ + protected $method; + + /** @var string */ + protected $classname; + + /** @var string */ + protected $templates; + + /** + * @param int $hook_id + * @return $this + */ + public function setHookId($hook_id) + { + $this->hook_id = $hook_id; + + return $this; + } + + /** + * @return int + */ + public function getHookId() + { + return $this->hook_id; + } + + /** + * @param int $module_id + * @return $this + */ + public function setModuleId($module_id) + { + $this->module_id = $module_id; + + return $this; + } + + /** + * @return int + */ + public function getModuleId() + { + return $this->module_id; + } + + /** + * @param string $classname + * @return $this + */ + public function setClassname($classname) + { + $this->classname = $classname; + + return $this; + } + + /** + * @return string + */ + public function getClassname() + { + return $this->classname; + } + + /** + * @param string $method + * @return $this + */ + public function setMethod($method) + { + $this->method = $method; + + return $this; + } + + /** + * @return string + */ + public function getMethod() + { + return $this->method; + } + + /** + * @return string + */ + public function getTemplates() + { + return $this->templates; + } + + /** + * @param string $templates + * @return $this + */ + public function setTemplates($templates) + { + $this->templates = $templates; + + return $this; + } +} diff --git a/core/lib/Thelia/Core/Event/Hook/ModuleHookDeleteEvent.php b/core/lib/Thelia/Core/Event/Hook/ModuleHookDeleteEvent.php new file mode 100644 index 00000000..53918bbf --- /dev/null +++ b/core/lib/Thelia/Core/Event/Hook/ModuleHookDeleteEvent.php @@ -0,0 +1,51 @@ + + */ +class ModuleHookDeleteEvent extends ModuleHookEvent +{ + /** @var int */ + protected $module_hook_id; + + /** + * @param int $module_hook_id + */ + public function __construct($module_hook_id) + { + $this->module_hook_id = $module_hook_id; + } + + /** + * @param mixed $module_hook_id + * @return $this + */ + public function setModuleHookId($module_hook_id) + { + $this->module_hook_id = $module_hook_id; + + return $this; + } + + /** + * @return mixed + */ + public function getModuleHookId() + { + return $this->module_hook_id; + } +} diff --git a/core/lib/Thelia/Core/Event/Hook/ModuleHookEvent.php b/core/lib/Thelia/Core/Event/Hook/ModuleHookEvent.php new file mode 100644 index 00000000..207e921b --- /dev/null +++ b/core/lib/Thelia/Core/Event/Hook/ModuleHookEvent.php @@ -0,0 +1,48 @@ + + */ +class ModuleHookEvent extends ActionEvent +{ + public $moduleHook = null; + + public function __construct(ModuleHook $moduleModuleHook = null) + { + $this->moduleHook = $moduleModuleHook; + } + + public function hasModuleHook() + { + return ! \is_null($this->moduleHook); + } + + public function getModuleHook() + { + return $this->moduleHook; + } + + public function setModuleHook(ModuleHook $moduleHook) + { + $this->moduleHook = $moduleHook; + + return $this; + } +} diff --git a/core/lib/Thelia/Core/Event/Hook/ModuleHookToggleActivationEvent.php b/core/lib/Thelia/Core/Event/Hook/ModuleHookToggleActivationEvent.php new file mode 100644 index 00000000..fe10de91 --- /dev/null +++ b/core/lib/Thelia/Core/Event/Hook/ModuleHookToggleActivationEvent.php @@ -0,0 +1,22 @@ + + */ +class ModuleHookToggleActivationEvent extends ModuleHookEvent +{ +} diff --git a/core/lib/Thelia/Core/Event/Hook/ModuleHookUpdateEvent.php b/core/lib/Thelia/Core/Event/Hook/ModuleHookUpdateEvent.php new file mode 100644 index 00000000..d3d7ecc3 --- /dev/null +++ b/core/lib/Thelia/Core/Event/Hook/ModuleHookUpdateEvent.php @@ -0,0 +1,62 @@ + + */ +class ModuleHookUpdateEvent extends ModuleHookCreateEvent +{ + protected $module_hook_id; + protected $active; + + /** + * @param int $module_hook_id + * @return $this + */ + public function setModuleHookId($module_hook_id) + { + $this->module_hook_id = $module_hook_id; + + return $this; + } + + /** + * @return int + */ + public function getModuleHookId() + { + return $this->module_hook_id; + } + + /** + * @param bool $active + * @return $this + */ + public function setActive($active) + { + $this->active = $active; + + return $this; + } + + /** + * @return bool + */ + public function getActive() + { + return $this->active; + } +} diff --git a/core/lib/Thelia/Core/Event/Image/ImageEvent.php b/core/lib/Thelia/Core/Event/Image/ImageEvent.php new file mode 100644 index 00000000..46f379cf --- /dev/null +++ b/core/lib/Thelia/Core/Event/Image/ImageEvent.php @@ -0,0 +1,260 @@ +width) && empty($this->height) /* && empty($this->resize_mode) && empty($this->background_color) not significant */ + && empty($this->effects) && empty($this->rotation) && empty($this->quality); + } + + /** + * @return string a hash identifiying the processing options + */ + public function getOptionsHash() + { + return md5( + $this->width . $this->height . $this->resize_mode . $this->background_color . implode(',', $this->effects) + . $this->rotation . $this->allowZoom + ); + } + + public function getCategory() + { + return $this->category; + } + + public function setCategory($category) + { + $this->category = $category; + + return $this; + } + + public function getWidth() + { + return $this->width; + } + + public function setWidth($width) + { + $this->width = $width; + + return $this; + } + + public function getHeight() + { + return $this->height; + } + + public function setHeight($height) + { + $this->height = $height; + + return $this; + } + + public function getResizeMode() + { + return $this->resize_mode; + } + + public function setResizeMode($resize_mode) + { + $this->resize_mode = $resize_mode; + + return $this; + } + + public function getBackgroundColor() + { + return $this->background_color; + } + + public function setBackgroundColor($background_color) + { + $this->background_color = $background_color; + + return $this; + } + + public function getEffects() + { + return $this->effects; + } + + public function setEffects(array $effects) + { + $this->effects = $effects; + + return $this; + } + + public function getRotation() + { + return $this->rotation; + } + + public function setRotation($rotation) + { + $this->rotation = $rotation; + + return $this; + } + + public function getQuality() + { + return $this->quality; + } + + public function setQuality($quality) + { + $this->quality = $quality; + + return $this; + } + + public function getOriginalFileUrl() + { + return $this->original_file_url; + } + + public function setOriginalFileUrl($original_file_url) + { + $this->original_file_url = $original_file_url; + + return $this; + } + + public function getCacheOriginalFilepath() + { + return $this->cache_original_filepath; + } + + public function setCacheOriginalFilepath($cache_original_filepath) + { + $this->cache_original_filepath = $cache_original_filepath; + + return $this; + } + + /** + * @param ImageInterface $imageObject + * @return $this + */ + public function setImageObject($imageObject) + { + $this->imageObject = $imageObject; + + return $this; + } + + /** + * @return ImageInterface + */ + public function getImageObject() + { + return $this->imageObject; + } + + /** + * @return bool + */ + public function getAllowZoom() + { + return $this->allowZoom; + } + + /** + * @param bool $allowZoom + * @return $this + */ + public function setAllowZoom($allowZoom) + { + $this->allowZoom = $allowZoom; + + return $this; + } +} diff --git a/core/lib/Thelia/Core/Event/ImportEvent.php b/core/lib/Thelia/Core/Event/ImportEvent.php new file mode 100644 index 00000000..6e930a9c --- /dev/null +++ b/core/lib/Thelia/Core/Event/ImportEvent.php @@ -0,0 +1,123 @@ + + */ +class ImportEvent extends Event +{ + /** + * @var \Thelia\ImportExport\Import\AbstractImport An import + */ + protected $import; + + /** + * @var \Thelia\Core\Serializer\SerializerInterface A serializer interface + */ + protected $serializer; + + /** + * @var array Errors list + */ + protected $errors = []; + + /** + * Event constructor + * + * @param \Thelia\ImportExport\Import\AbstractImport $import An import + * @param \Thelia\Core\Serializer\SerializerInterface $serializer A serializer interface + */ + public function __construct(AbstractImport $import, SerializerInterface $serializer) + { + $this->import = $import; + $this->serializer = $serializer; + } + + /** + * Get import + * + * @return \Thelia\ImportExport\Import\AbstractImport An import + */ + public function getImport() + { + return $this->import; + } + + /** + * Set import + * + * @param \Thelia\ImportExport\Import\AbstractImport $import An import + * + * @return $this Return $this, allow chaining + */ + public function setImport(AbstractImport $import) + { + $this->import = $import; + + return $this; + } + + /** + * Get serializer + * + * @return \Thelia\Core\Serializer\SerializerInterface A serializer interface + */ + public function getSerializer() + { + return $this->serializer; + } + + /** + * Set serializer + * + * @param \Thelia\Core\Serializer\SerializerInterface $serializer A serializer interface + * + * @return $this Return $this, allow chaining + */ + public function setSerializer(SerializerInterface $serializer) + { + $this->serializer = $serializer; + + return $this; + } + + /** + * Get errors + * + * @return array Errors list + */ + public function getErrors() + { + return $this->errors; + } + + /** + * Set errors + * + * @param array $errors Errors list + * + * @return $this Return $this, allow chaining + */ + public function setErrors(array $errors) + { + $this->errors = $errors; + + return $this; + } +} diff --git a/core/lib/Thelia/Core/Event/Lang/LangCreateEvent.php b/core/lib/Thelia/Core/Event/Lang/LangCreateEvent.php new file mode 100644 index 00000000..19ab24c9 --- /dev/null +++ b/core/lib/Thelia/Core/Event/Lang/LangCreateEvent.php @@ -0,0 +1,245 @@ + + */ +class LangCreateEvent extends LangEvent +{ + protected $title; + protected $code; + protected $locale; + protected $date_time_format; + protected $date_format; + protected $time_format; + protected $decimal_separator; + protected $thousands_separator; + protected $decimals; + /** @var bool */ + protected $active; + /** @var bool */ + protected $visible; + + /** + * @param mixed $code + * + * @return $this + */ + public function setCode($code) + { + $this->code = $code; + + return $this; + } + + /** + * @return mixed + */ + public function getCode() + { + return $this->code; + } + + /** + * @return mixed + */ + public function getDateTimeFormat() + { + return $this->date_time_format; + } + + /** + * @param mixed $date_time_format + */ + public function setDateTimeFormat($date_time_format) + { + $this->date_time_format = $date_time_format; + return $this; + } + + + /** + * @param mixed $date_format + * + * @return $this + */ + public function setDateFormat($date_format) + { + $this->date_format = $date_format; + + return $this; + } + + /** + * @return mixed + */ + public function getDateFormat() + { + return $this->date_format; + } + + /** + * @param mixed $locale + * + * @return $this + */ + public function setLocale($locale) + { + $this->locale = $locale; + + return $this; + } + + /** + * @return mixed + */ + public function getLocale() + { + return $this->locale; + } + + /** + * @param mixed $time_format + * + * @return $this + */ + public function setTimeFormat($time_format) + { + $this->time_format = $time_format; + + return $this; + } + + /** + * @return mixed + */ + public function getTimeFormat() + { + return $this->time_format; + } + + /** + * @param mixed $title + * + * @return $this + */ + public function setTitle($title) + { + $this->title = $title; + + return $this; + } + + /** + * @return mixed + */ + public function getTitle() + { + return $this->title; + } + + /** + * @param mixed $decimal_separator + */ + public function setDecimalSeparator($decimal_separator) + { + $this->decimal_separator = $decimal_separator; + + return $this; + } + + /** + * @return mixed + */ + public function getDecimalSeparator() + { + return $this->decimal_separator; + } + + /** + * @param mixed $decimals + */ + public function setDecimals($decimals) + { + $this->decimals = $decimals; + + return $this; + } + + /** + * @return mixed + */ + public function getDecimals() + { + return $this->decimals; + } + + /** + * @param mixed $thousands_separator + */ + public function setThousandsSeparator($thousands_separator) + { + $this->thousands_separator = $thousands_separator; + + return $this; + } + + /** + * @return mixed + */ + public function getThousandsSeparator() + { + return $this->thousands_separator; + } + + /** + * @param bool $active + * @return $this + */ + public function setActive($active) + { + $this->active = $active; + + return $this; + } + + /** + * @return bool + */ + public function getActive() + { + return $this->active; + } + + /** + * @param bool $visible + * @return $this + */ + public function setVisible($visible) + { + $this->visible = $visible; + + return $this; + } + + /** + * @return bool + */ + public function getVisible() + { + return$this->visible; + } +} diff --git a/core/lib/Thelia/Core/Event/Lang/LangDefaultBehaviorEvent.php b/core/lib/Thelia/Core/Event/Lang/LangDefaultBehaviorEvent.php new file mode 100644 index 00000000..ebb0ab8d --- /dev/null +++ b/core/lib/Thelia/Core/Event/Lang/LangDefaultBehaviorEvent.php @@ -0,0 +1,49 @@ + + */ +class LangDefaultBehaviorEvent extends ActionEvent +{ + /** + * @var int default behavior status + */ + protected $defaultBehavior; + + public function __construct($defaultBehavior) + { + $this->defaultBehavior = $defaultBehavior; + } + + /** + * @param int $defaultBehavior + */ + public function setDefaultBehavior($defaultBehavior) + { + $this->defaultBehavior = $defaultBehavior; + } + + /** + * @return int + */ + public function getDefaultBehavior() + { + return $this->defaultBehavior; + } +} diff --git a/core/lib/Thelia/Core/Event/Lang/LangDeleteEvent.php b/core/lib/Thelia/Core/Event/Lang/LangDeleteEvent.php new file mode 100644 index 00000000..fadac7c3 --- /dev/null +++ b/core/lib/Thelia/Core/Event/Lang/LangDeleteEvent.php @@ -0,0 +1,54 @@ + + */ +class LangDeleteEvent extends LangEvent +{ + /** + * @var int + */ + protected $lang_id; + + /** + * @param int $lang_id + */ + public function __construct($lang_id) + { + $this->lang_id = $lang_id; + } + + /** + * @param int $lang_id + * + * @return $this + */ + public function setLangId($lang_id) + { + $this->lang_id = $lang_id; + + return $this; + } + + /** + * @return int + */ + public function getLangId() + { + return $this->lang_id; + } +} diff --git a/core/lib/Thelia/Core/Event/Lang/LangEvent.php b/core/lib/Thelia/Core/Event/Lang/LangEvent.php new file mode 100644 index 00000000..19b5097c --- /dev/null +++ b/core/lib/Thelia/Core/Event/Lang/LangEvent.php @@ -0,0 +1,62 @@ + + * @deprecated since 2.4, please use \Thelia\Model\Event\LangEvent + */ +class LangEvent extends ActionEvent +{ + /** + * @var \Thelia\Model\Lang + */ + protected $lang; + + public function __construct(Lang $lang = null) + { + $this->lang = $lang; + } + + /** + * @param \Thelia\Model\Lang $lang + */ + public function setLang(Lang $lang) + { + $this->lang = $lang; + } + + /** + * @return \Thelia\Model\Lang + */ + public function getLang() + { + return $this->lang; + } + + /** + * + * check if lang object is present + * + * @return bool + */ + public function hasLang() + { + return null !== $this->lang; + } +} diff --git a/core/lib/Thelia/Core/Event/Lang/LangToggleActiveEvent.php b/core/lib/Thelia/Core/Event/Lang/LangToggleActiveEvent.php new file mode 100644 index 00000000..a7a239ba --- /dev/null +++ b/core/lib/Thelia/Core/Event/Lang/LangToggleActiveEvent.php @@ -0,0 +1,22 @@ + + */ +class LangToggleActiveEvent extends LangToggleDefaultEvent +{ +} diff --git a/core/lib/Thelia/Core/Event/Lang/LangToggleDefaultEvent.php b/core/lib/Thelia/Core/Event/Lang/LangToggleDefaultEvent.php new file mode 100644 index 00000000..29d0a926 --- /dev/null +++ b/core/lib/Thelia/Core/Event/Lang/LangToggleDefaultEvent.php @@ -0,0 +1,54 @@ + + */ +class LangToggleDefaultEvent extends LangEvent +{ + /** + * @var int + */ + protected $lang_id; + + /** + * @param int $lang_id + */ + public function __construct($lang_id) + { + $this->lang_id = $lang_id; + } + + /** + * @param int $lang_id + * + * @return $this + */ + public function setLangId($lang_id) + { + $this->lang_id = $lang_id; + + return $this; + } + + /** + * @return int + */ + public function getLangId() + { + return $this->lang_id; + } +} diff --git a/core/lib/Thelia/Core/Event/Lang/LangToggleVisibleEvent.php b/core/lib/Thelia/Core/Event/Lang/LangToggleVisibleEvent.php new file mode 100644 index 00000000..61d53165 --- /dev/null +++ b/core/lib/Thelia/Core/Event/Lang/LangToggleVisibleEvent.php @@ -0,0 +1,22 @@ + + */ +class LangToggleVisibleEvent extends LangToggleDefaultEvent +{ +} diff --git a/core/lib/Thelia/Core/Event/Lang/LangUpdateEvent.php b/core/lib/Thelia/Core/Event/Lang/LangUpdateEvent.php new file mode 100644 index 00000000..79fc5287 --- /dev/null +++ b/core/lib/Thelia/Core/Event/Lang/LangUpdateEvent.php @@ -0,0 +1,54 @@ + + */ +class LangUpdateEvent extends LangCreateEvent +{ + /** + * @var int lang id + */ + protected $id; + + /** + * @param int $id + */ + public function __construct($id) + { + $this->id = $id; + } + + /** + * @param int $id + * + * @return $this + */ + public function setId($id) + { + $this->id = $id; + + return $this; + } + + /** + * @return int + */ + public function getId() + { + return $this->id; + } +} diff --git a/core/lib/Thelia/Core/Event/Loop/LoopExtendsArgDefinitionsEvent.php b/core/lib/Thelia/Core/Event/Loop/LoopExtendsArgDefinitionsEvent.php new file mode 100644 index 00000000..b28da568 --- /dev/null +++ b/core/lib/Thelia/Core/Event/Loop/LoopExtendsArgDefinitionsEvent.php @@ -0,0 +1,27 @@ + + */ +class LoopExtendsArgDefinitionsEvent extends LoopExtendsEvent +{ + public function getArgumentCollection() + { + return $this->loop->getArgumentCollection(); + } +} diff --git a/core/lib/Thelia/Core/Event/Loop/LoopExtendsBuildArrayEvent.php b/core/lib/Thelia/Core/Event/Loop/LoopExtendsBuildArrayEvent.php new file mode 100644 index 00000000..b53dcee4 --- /dev/null +++ b/core/lib/Thelia/Core/Event/Loop/LoopExtendsBuildArrayEvent.php @@ -0,0 +1,66 @@ + + */ +class LoopExtendsBuildArrayEvent extends LoopExtendsEvent +{ + /** + * @var array Build array results + */ + protected $array; + + /** + * Class constructor + * + * @param \Thelia\Core\Template\Element\BaseLoop $loop Loop object + * @param array $array Build array base results + */ + public function __construct(BaseLoop $loop, array $array) + { + parent::__construct($loop); + + $this->array = $array; + } + + /** + * Get build array results + * + * @return array Build array results + */ + public function getArray() + { + 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; + } +} diff --git a/core/lib/Thelia/Core/Event/Loop/LoopExtendsBuildModelCriteriaEvent.php b/core/lib/Thelia/Core/Event/Loop/LoopExtendsBuildModelCriteriaEvent.php new file mode 100644 index 00000000..8ff04611 --- /dev/null +++ b/core/lib/Thelia/Core/Event/Loop/LoopExtendsBuildModelCriteriaEvent.php @@ -0,0 +1,46 @@ + + */ +class LoopExtendsBuildModelCriteriaEvent extends LoopExtendsEvent +{ + /** @var ModelCriteria $modelCriteria */ + protected $modelCriteria; + + /** + * LoopExtendsBuildModelCriteria constructor. + * @param ModelCriteria $modelCriteria + */ + public function __construct(BaseLoop $loop, ModelCriteria $modelCriteria) + { + parent::__construct($loop); + $this->modelCriteria = $modelCriteria; + } + + /** + * @return ModelCriteria + */ + public function getModelCriteria() + { + return $this->modelCriteria; + } +} diff --git a/core/lib/Thelia/Core/Event/Loop/LoopExtendsEvent.php b/core/lib/Thelia/Core/Event/Loop/LoopExtendsEvent.php new file mode 100644 index 00000000..bf5398cf --- /dev/null +++ b/core/lib/Thelia/Core/Event/Loop/LoopExtendsEvent.php @@ -0,0 +1,57 @@ + + */ +class LoopExtendsEvent extends ActionEvent +{ + /** @var BaseLoop|null $loop */ + protected $loop = null; + + /** + * LoopExtendsEvent constructor. + * @param null|BaseLoop $loop + */ + public function __construct(BaseLoop $loop) + { + $this->loop = $loop; + } + + /** + * Get the loop + * + * @return null|BaseLoop + */ + public function getLoop() + { + return $this->loop; + } + + /** + * Get the loop name + * + * @return null|string + */ + public function getLoopName() + { + return $this->loop->getLoopName(); + } +} diff --git a/core/lib/Thelia/Core/Event/Loop/LoopExtendsInitializeArgsEvent.php b/core/lib/Thelia/Core/Event/Loop/LoopExtendsInitializeArgsEvent.php new file mode 100644 index 00000000..4d3a1dd4 --- /dev/null +++ b/core/lib/Thelia/Core/Event/Loop/LoopExtendsInitializeArgsEvent.php @@ -0,0 +1,56 @@ + + */ +class LoopExtendsInitializeArgsEvent extends LoopExtendsEvent +{ + /** @var array the loop parameters when called. an array of name => value pairs */ + protected $loopParameters; + + /** + * LoopExtendsInitializeArgs constructor. + * @param array $loopParameters + */ + public function __construct(BaseLoop $loop, array $loopParameters) + { + parent::__construct($loop); + $this->loopParameters = $loopParameters; + } + + /** + * The loop parameters when called. an array of name => value pairs. + * + * @return array the loop parameters when called. an array of name => value pairs + */ + public function getLoopParameters() + { + return $this->loopParameters; + } + + /** + * @param array $loopParameters + */ + public function setLoopParameters($loopParameters) + { + $this->loopParameters = $loopParameters; + return $this; + } +} diff --git a/core/lib/Thelia/Core/Event/Loop/LoopExtendsParseResultsEvent.php b/core/lib/Thelia/Core/Event/Loop/LoopExtendsParseResultsEvent.php new file mode 100644 index 00000000..a780abb1 --- /dev/null +++ b/core/lib/Thelia/Core/Event/Loop/LoopExtendsParseResultsEvent.php @@ -0,0 +1,46 @@ + + */ +class LoopExtendsParseResultsEvent extends LoopExtendsEvent +{ + /** @var LoopResult $loopResult */ + protected $loopResult; + + /** + * LoopExtendsParseResultsEvent constructor. + * @param LoopResult $loopResult + */ + public function __construct(BaseLoop $loop, LoopResult $loopResult) + { + parent::__construct($loop); + $this->loopResult = $loopResult; + } + + /** + * @return LoopResult + */ + public function getLoopResult() + { + return $this->loopResult; + } +} diff --git a/core/lib/Thelia/Core/Event/LostPasswordEvent.php b/core/lib/Thelia/Core/Event/LostPasswordEvent.php new file mode 100644 index 00000000..0135b0ce --- /dev/null +++ b/core/lib/Thelia/Core/Event/LostPasswordEvent.php @@ -0,0 +1,36 @@ + + */ +class LostPasswordEvent extends ActionEvent +{ + protected $email; + + public function __construct($email) + { + $this->email = $email; + } + + /** + * @return mixed + */ + public function getEmail() + { + return $this->email; + } +} diff --git a/core/lib/Thelia/Core/Event/MailTransporterEvent.php b/core/lib/Thelia/Core/Event/MailTransporterEvent.php new file mode 100644 index 00000000..317f3c34 --- /dev/null +++ b/core/lib/Thelia/Core/Event/MailTransporterEvent.php @@ -0,0 +1,41 @@ + + */ +class MailTransporterEvent extends ActionEvent +{ + /** + * @var \Swift_Transport + */ + protected $transporter; + + public function setMailerTransporter(\Swift_Transport $transporter) + { + $this->transporter = $transporter; + } + + public function getTransporter() + { + return $this->transporter; + } + + public function hasTransporter() + { + return null !== $this->transporter; + } +} diff --git a/core/lib/Thelia/Core/Event/MailingSystem/MailingSystemEvent.php b/core/lib/Thelia/Core/Event/MailingSystem/MailingSystemEvent.php new file mode 100644 index 00000000..29a034dd --- /dev/null +++ b/core/lib/Thelia/Core/Event/MailingSystem/MailingSystemEvent.php @@ -0,0 +1,172 @@ +authMode = $authMode; + } + + /** + * @return null + */ + public function getAuthMode() + { + return $this->authMode; + } + + /** + * @param null $enabled + */ + public function setEnabled($enabled) + { + $this->enabled = $enabled; + } + + /** + * @return null + */ + public function getEnabled() + { + return $this->enabled; + } + + /** + * @param null $encryption + */ + public function setEncryption($encryption) + { + $this->encryption = $encryption; + } + + /** + * @return null + */ + public function getEncryption() + { + return $this->encryption; + } + + /** + * @param null $host + */ + public function setHost($host) + { + $this->host = $host; + } + + /** + * @return null + */ + public function getHost() + { + return $this->host; + } + + /** + * @param null $password + */ + public function setPassword($password) + { + $this->password = $password; + } + + /** + * @return null + */ + public function getPassword() + { + return $this->password; + } + + /** + * @param null $port + */ + public function setPort($port) + { + $this->port = $port; + } + + /** + * @return null + */ + public function getPort() + { + return $this->port; + } + + /** + * @param null $sourceIp + */ + public function setSourceIp($sourceIp) + { + $this->sourceIp = $sourceIp; + } + + /** + * @return null + */ + public function getSourceIp() + { + return $this->sourceIp; + } + + /** + * @param null $timeout + */ + public function setTimeout($timeout) + { + $this->timeout = $timeout; + } + + /** + * @return null + */ + public function getTimeout() + { + return $this->timeout; + } + + /** + * @param null $username + */ + public function setUsername($username) + { + $this->username = $username; + } + + /** + * @return null + */ + public function getUsername() + { + return $this->username; + } +} diff --git a/core/lib/Thelia/Core/Event/Message/MessageCreateEvent.php b/core/lib/Thelia/Core/Event/Message/MessageCreateEvent.php new file mode 100644 index 00000000..f76a5817 --- /dev/null +++ b/core/lib/Thelia/Core/Event/Message/MessageCreateEvent.php @@ -0,0 +1,70 @@ +message_name; + } + + public function setMessageName($message_name) + { + $this->message_name = $message_name; + + return $this; + } + + public function getLocale() + { + return $this->locale; + } + + public function setLocale($locale) + { + $this->locale = $locale; + + return $this; + } + + public function getTitle() + { + return $this->title; + } + + public function setTitle($title) + { + $this->title = $title; + + return $this; + } + + public function getSecured() + { + return $this->secured; + } + + public function setSecured($secured) + { + $this->secured = $secured; + + return $this; + } +} diff --git a/core/lib/Thelia/Core/Event/Message/MessageDeleteEvent.php b/core/lib/Thelia/Core/Event/Message/MessageDeleteEvent.php new file mode 100644 index 00000000..bbeed094 --- /dev/null +++ b/core/lib/Thelia/Core/Event/Message/MessageDeleteEvent.php @@ -0,0 +1,39 @@ +setMessageId($message_id); + } + + public function getMessageId() + { + return $this->message_id; + } + + public function setMessageId($message_id) + { + $this->message_id = $message_id; + + return $this; + } +} diff --git a/core/lib/Thelia/Core/Event/Message/MessageEvent.php b/core/lib/Thelia/Core/Event/Message/MessageEvent.php new file mode 100644 index 00000000..2fe8524a --- /dev/null +++ b/core/lib/Thelia/Core/Event/Message/MessageEvent.php @@ -0,0 +1,46 @@ +message = $message; + } + + public function hasMessage() + { + return ! \is_null($this->message); + } + + public function getMessage() + { + return $this->message; + } + + public function setMessage($message) + { + $this->message = $message; + + return $this; + } +} diff --git a/core/lib/Thelia/Core/Event/Message/MessageUpdateEvent.php b/core/lib/Thelia/Core/Event/Message/MessageUpdateEvent.php new file mode 100644 index 00000000..fe9db86f --- /dev/null +++ b/core/lib/Thelia/Core/Event/Message/MessageUpdateEvent.php @@ -0,0 +1,133 @@ +setMessageId($message_id); + } + + public function getMessageId() + { + return $this->message_id; + } + + public function setMessageId($message_id) + { + $this->message_id = $message_id; + + return $this; + } + + public function getTextMessage() + { + return $this->text_message; + } + + public function setTextMessage($text_message) + { + $this->text_message = $text_message; + + return $this; + } + + public function getHtmlMessage() + { + return $this->html_message; + } + + public function setHtmlMessage($html_message) + { + $this->html_message = $html_message; + + return $this; + } + + public function getSubject() + { + return $this->subject; + } + + public function setSubject($subject) + { + $this->subject = $subject; + + return $this; + } + + public function getHtmlLayoutFileName() + { + return $this->html_layout_file_name; + } + + public function setHtmlLayoutFileName($html_layout_file_name) + { + $this->html_layout_file_name = $html_layout_file_name; + + return $this; + } + + public function getHtmlTemplateFileName() + { + return $this->html_template_file_name; + } + + public function setHtmlTemplateFileName($html_template_file_name) + { + $this->html_template_file_name = $html_template_file_name; + + return $this; + } + + public function getTextLayoutFileName() + { + return $this->text_layout_file_name; + } + + public function setTextLayoutFileName($text_layout_file_name) + { + $this->text_layout_file_name = $text_layout_file_name; + + return $this; + } + + public function getTextTemplateFileName() + { + return $this->text_template_file_name; + } + + public function setTextTemplateFileName($text_template_file_name) + { + $this->text_template_file_name = $text_template_file_name; + + return $this; + } +} diff --git a/core/lib/Thelia/Core/Event/MetaData/MetaDataCreateOrUpdateEvent.php b/core/lib/Thelia/Core/Event/MetaData/MetaDataCreateOrUpdateEvent.php new file mode 100644 index 00000000..dd3c99a7 --- /dev/null +++ b/core/lib/Thelia/Core/Event/MetaData/MetaDataCreateOrUpdateEvent.php @@ -0,0 +1,50 @@ + + */ +class MetaDataCreateOrUpdateEvent extends MetaDataDeleteEvent +{ + protected $value = null; + + public function __construct($metaKey = null, $elementKey = null, $elementId = null, $value = null) + { + parent::__construct($metaKey, $elementKey, $elementId); + + $this->value = $value; + } + + /** + * @param mixed $value + * + * @return $this + */ + public function setValue($value) + { + $this->value = $value; + + return $this; + } + + /** + * @return mixed + */ + public function getValue() + { + return $this->value; + } +} diff --git a/core/lib/Thelia/Core/Event/MetaData/MetaDataDeleteEvent.php b/core/lib/Thelia/Core/Event/MetaData/MetaDataDeleteEvent.php new file mode 100644 index 00000000..a0977335 --- /dev/null +++ b/core/lib/Thelia/Core/Event/MetaData/MetaDataDeleteEvent.php @@ -0,0 +1,105 @@ + + */ +class MetaDataDeleteEvent extends MetaDataEvent +{ + /** @var string */ + protected $metaKey = null; + + /** @var string */ + protected $elementKey = null; + + /** @var int */ + protected $elementId = null; + + /** + * MetaDataDeleteEvent constructor. + * @param string|null $metaKey + * @param string|null $elementKey + * @param int|null $elementId + */ + public function __construct($metaKey = null, $elementKey = null, $elementId = null) + { + parent::__construct(); + + $this->metaKey = $metaKey; + $this->elementKey = $elementKey; + $this->elementId = $elementId; + } + + /** + * @param string $metaKey + * + * @return $this + */ + public function setMetaKey($metaKey) + { + $this->metaKey = $metaKey; + + return $this; + } + + /** + * @return string|null + */ + public function getMetaKey() + { + return $this->metaKey; + } + + /** + * @param $elementKey + * + * @return $this + */ + public function setElementKey($elementKey) + { + $this->elementKey = $elementKey; + + return $this; + } + + /** + * @return null|string + */ + public function getElementKey() + { + return $this->elementKey; + } + + /** + * @param int $elementId + * + * @return $this + */ + public function setElementId($elementId) + { + $this->elementId = $elementId; + + return $this; + } + + /** + * @return int|null + */ + public function getElementId() + { + return $this->elementId; + } +} diff --git a/core/lib/Thelia/Core/Event/MetaData/MetaDataEvent.php b/core/lib/Thelia/Core/Event/MetaData/MetaDataEvent.php new file mode 100644 index 00000000..34d4e0d1 --- /dev/null +++ b/core/lib/Thelia/Core/Event/MetaData/MetaDataEvent.php @@ -0,0 +1,51 @@ + + */ +class MetaDataEvent extends ActionEvent +{ + protected $metaData = null; + + public function __construct(MetaData $metaData = null) + { + $this->metaData = $metaData; + } + + /** + * @param null|\Thelia\Model\MetaData $metaData + * + * @return $this + */ + public function setMetaData($metaData) + { + $this->metaData = $metaData; + + return $this; + } + + /** + * @return null|\Thelia\Model\MetaData + */ + public function getMetaData() + { + return $this->metaData; + } +} diff --git a/core/lib/Thelia/Core/Event/Module/ModuleDeleteEvent.php b/core/lib/Thelia/Core/Event/Module/ModuleDeleteEvent.php new file mode 100644 index 00000000..d9891ec0 --- /dev/null +++ b/core/lib/Thelia/Core/Event/Module/ModuleDeleteEvent.php @@ -0,0 +1,84 @@ + + */ +class ModuleDeleteEvent extends ModuleEvent +{ + /** + * @var int module id + */ + protected $module_id; + protected $delete_data; + + /** + * @var bool + */ + protected $assume_delete; + + public function __construct($module_id, $assume_delete = false) + { + $this->module_id = $module_id; + $this->assume_delete = $assume_delete; + } + + /** + * @param int $module_id + */ + public function setModuleId($module_id) + { + $this->module_id = $module_id; + } + + /** + * @return int + */ + public function getModuleId() + { + return $this->module_id; + } + + public function getDeleteData() + { + return $this->delete_data; + } + + public function setDeleteData($delete_data) + { + $this->delete_data = $delete_data; + + return $this; + } + + /** + * @return boolean + */ + public function getAssumeDelete() + { + return $this->assume_delete; + } + + /** + * @param boolean $recursive + * @return $this; + */ + public function setAssumeDelete($assume_delete) + { + $this->assume_delete = $assume_delete; + return $this; + } +} diff --git a/core/lib/Thelia/Core/Event/Module/ModuleEvent.php b/core/lib/Thelia/Core/Event/Module/ModuleEvent.php new file mode 100644 index 00000000..ebbc94ff --- /dev/null +++ b/core/lib/Thelia/Core/Event/Module/ModuleEvent.php @@ -0,0 +1,162 @@ + + */ +class ModuleEvent extends ActionEvent +{ + /** + * @var \Thelia\Model\Module + */ + protected $module; + + protected $id; + protected $locale; + protected $title; + protected $chapo; + protected $description; + protected $postscriptum; + + /** + * @param mixed $chapo + */ + public function setChapo($chapo) + { + $this->chapo = $chapo; + } + + /** + * @return mixed + */ + public function getChapo() + { + return $this->chapo; + } + + /** + * @param mixed $description + */ + public function setDescription($description) + { + $this->description = $description; + } + + /** + * @return mixed + */ + public function getDescription() + { + return $this->description; + } + + /** + * @param mixed $id + */ + public function setId($id) + { + $this->id = $id; + } + + /** + * @return mixed + */ + public function getId() + { + return $this->id; + } + + /** + * @param mixed $locale + */ + public function setLocale($locale) + { + $this->locale = $locale; + } + + /** + * @return mixed + */ + public function getLocale() + { + return $this->locale; + } + + /** + * @param mixed $postscriptum + */ + public function setPostscriptum($postscriptum) + { + $this->postscriptum = $postscriptum; + } + + /** + * @return mixed + */ + public function getPostscriptum() + { + return $this->postscriptum; + } + + /** + * @param mixed $title + */ + public function setTitle($title) + { + $this->title = $title; + } + + /** + * @return mixed + */ + public function getTitle() + { + return $this->title; + } + + public function __construct(Module $module = null) + { + $this->module = $module; + } + + /** + * @param \Thelia\Model\Module $module + * + * @return $this + */ + public function setModule(Module $module) + { + $this->module = $module; + + return $this; + } + + /** + * @return \Thelia\Model\Module + */ + public function getModule() + { + return $this->module; + } + + public function hasModule() + { + return null !== $this->module; + } +} diff --git a/core/lib/Thelia/Core/Event/Module/ModuleInstallEvent.php b/core/lib/Thelia/Core/Event/Module/ModuleInstallEvent.php new file mode 100644 index 00000000..2afb4578 --- /dev/null +++ b/core/lib/Thelia/Core/Event/Module/ModuleInstallEvent.php @@ -0,0 +1,106 @@ + + */ +class ModuleInstallEvent extends ActionEvent +{ + /** + * @var \Thelia\Model\Module + */ + protected $module; + + /** @var ModuleDefinition $moduleDefinition */ + protected $moduleDefinition; + + /** @var string $modulePath */ + protected $modulePath; + + public function __construct(Module $module = null) + { + $this->module = $module; + } + + /** + * @param \Thelia\Model\Module $module + * + * @return $this + */ + public function setModule(Module $module) + { + $this->module = $module; + + return $this; + } + + /** + * @return \Thelia\Model\Module + */ + public function getModule() + { + return $this->module; + } + + public function hasModule() + { + return null !== $this->module; + } + + /** + * @param ModuleDefinition $moduleDefinition + * + * @return $this + */ + public function setModuleDefinition($moduleDefinition) + { + $this->moduleDefinition = $moduleDefinition; + + return $this; + } + + /** + * @return ModuleDefinition + */ + public function getModuleDefinition() + { + return $this->moduleDefinition; + } + + /** + * @param string $modulePath + * + * @return $this + */ + public function setModulePath($modulePath) + { + $this->modulePath = $modulePath; + + return $this; + } + + /** + * @return string + */ + public function getModulePath() + { + return $this->modulePath; + } +} diff --git a/core/lib/Thelia/Core/Event/Module/ModuleToggleActivationEvent.php b/core/lib/Thelia/Core/Event/Module/ModuleToggleActivationEvent.php new file mode 100644 index 00000000..e919f87a --- /dev/null +++ b/core/lib/Thelia/Core/Event/Module/ModuleToggleActivationEvent.php @@ -0,0 +1,126 @@ + + */ +class ModuleToggleActivationEvent extends ModuleEvent +{ + /** + * @var int + */ + protected $module_id; + + /** + * @var bool + */ + protected $noCheck; + + /** + * @var bool + */ + protected $recursive; + + /** + * @var bool + */ + protected $assume_deactivate; + + + /** + * @param int $module_id + */ + public function __construct($module_id, $assume_deactivate = false) + { + $this->module_id = $module_id; + $this->assume_deactivate = $assume_deactivate; + } + + /** + * @param int $module_id + * + * @return $this + */ + public function setModuleId($module_id) + { + $this->module_id = $module_id; + + return $this; + } + + /** + * @return int + */ + public function getModuleId() + { + return $this->module_id; + } + + /** + * @return boolean + */ + public function isNoCheck() + { + return $this->noCheck; + } + + /** + * @param boolean $noCheck + * @return $this; + */ + public function setNoCheck($noCheck) + { + $this->noCheck = $noCheck; + + return $this; + } + + /** + * @return boolean + */ + public function isRecursive() + { + return $this->recursive; + } + + /** + * @param boolean $recursive + * @return $this; + */ + public function setRecursive($recursive) + { + $this->recursive = $recursive; + return $this; + } + + /** + * @return boolean + */ + public function getAssumeDeactivate() + { + return $this->assume_deactivate; + } + + /** + * @param boolean $recursive + * @return $this; + */ + public function setAssumeDeactivate($assume_deactivate) + { + $this->assume_deactivate = $assume_deactivate; + return $this; + } +} diff --git a/core/lib/Thelia/Core/Event/Newsletter/NewsletterEvent.php b/core/lib/Thelia/Core/Event/Newsletter/NewsletterEvent.php new file mode 100644 index 00000000..cc85106f --- /dev/null +++ b/core/lib/Thelia/Core/Event/Newsletter/NewsletterEvent.php @@ -0,0 +1,175 @@ + + */ +class NewsletterEvent extends ActionEvent +{ + /** + * @var string email to save + */ + protected $id; + + /** + * @var string email to save + */ + protected $email; + + /** + * @var string first name subscriber + */ + protected $firstname; + + /** + * @var string last name subscriber + */ + protected $lastname; + + /** + * @var string current locale + */ + protected $locale; + + /** + * @var \Thelia\Model\Newsletter + */ + protected $newsletter; + + public function __construct($email, $locale) + { + $this->email = $email; + $this->locale = $locale; + } + + /** + * @param \Thelia\Model\Newsletter $newsletter + */ + public function setNewsletter($newsletter) + { + $this->newsletter = $newsletter; + + return $this; + } + + /** + * @return \Thelia\Model\Newsletter + */ + public function getNewsletter() + { + return $this->newsletter; + } + + /** + * @param string $email + * + * @return $this + */ + public function setEmail($email) + { + $this->email = $email; + + return $this; + } + + /** + * @return string + */ + public function getEmail() + { + return $this->email; + } + + /** + * @param string $firstname + * + * @return $this + */ + public function setFirstname($firstname) + { + $this->firstname = $firstname; + + return $this; + } + + /** + * @return string + */ + public function getFirstname() + { + return $this->firstname; + } + + /** + * @param string $lastname + * + * @return $this + */ + public function setLastname($lastname) + { + $this->lastname = $lastname; + + return $this; + } + + /** + * @return string + */ + public function getLastname() + { + return $this->lastname; + } + + /** + * @param string $locale + * + * @return $this + */ + public function setLocale($locale) + { + $this->locale = $locale; + + return $this; + } + + /** + * @return string + */ + public function getLocale() + { + return $this->locale; + } + + /** + * @param string $id + */ + public function setId($id) + { + $this->id = $id; + + return $this; + } + + /** + * @return string + */ + public function getId() + { + return $this->id; + } +} diff --git a/core/lib/Thelia/Core/Event/Order/GetStockUpdateOperationOnOrderStatusChangeEvent.php b/core/lib/Thelia/Core/Event/Order/GetStockUpdateOperationOnOrderStatusChangeEvent.php new file mode 100644 index 00000000..e2ad4adf --- /dev/null +++ b/core/lib/Thelia/Core/Event/Order/GetStockUpdateOperationOnOrderStatusChangeEvent.php @@ -0,0 +1,81 @@ +order = $order; + $this->newOrderStatus = $newOrderStatus; + } + + /** + * @return Order + */ + public function getOrder() + { + return $this->order; + } + + /** + * @return OrderStatus + */ + public function getNewOrderStatus() + { + return $this->newOrderStatus; + } + + /** + * @return int + */ + public function getOperation() + { + return $this->operation; + } + + /** + * @param int $operation + * @return $this + */ + public function setOperation($operation) + { + $this->operation = $operation; + return $this; + } +} diff --git a/core/lib/Thelia/Core/Event/Order/OrderAddressEvent.php b/core/lib/Thelia/Core/Event/Order/OrderAddressEvent.php new file mode 100644 index 00000000..4577f1f5 --- /dev/null +++ b/core/lib/Thelia/Core/Event/Order/OrderAddressEvent.php @@ -0,0 +1,260 @@ +address1 = $address1; + $this->address2 = $address2; + $this->address3 = $address3; + $this->city = $city; + $this->company = $company; + $this->country = $country; + $this->state= $state; + $this->firstname = $firstname; + $this->lastname = $lastname; + $this->phone = $phone; + $this->cellphone = $cellphone; + $this->title = $title; + $this->zipcode = $zipcode; + } + + /** + * @return string + */ + public function getAddress1() + { + return $this->address1; + } + + /** + * @return string + */ + public function getAddress2() + { + return $this->address2; + } + + /** + * @return string + */ + public function getAddress3() + { + return $this->address3; + } + + /** + * @return string + */ + public function getCity() + { + return $this->city; + } + + /** + * @return null|string + */ + public function getCompany() + { + return $this->company; + } + + /** + * @return int + */ + public function getCountry() + { + return $this->country; + } + + /** + * @return int|null + */ + public function getState() + { + return $this->state; + } + + /** + * @return string + */ + public function getFirstname() + { + return $this->firstname; + } + + /** + * @return string + */ + public function getLastname() + { + return $this->lastname; + } + + /** + * @return string + */ + public function getPhone() + { + return $this->phone; + } + + /** + * @return string + */ + public function getCellphone() + { + return $this->cellphone; + } + + /** + * @return int + */ + public function getTitle() + { + return $this->title; + } + + /** + * @return string + */ + public function getZipcode() + { + return $this->zipcode; + } + + /** + * @param \Thelia\Model\OrderAddress $orderAddress + */ + public function setOrderAddress(OrderAddress $orderAddress) + { + $this->orderAddress = $orderAddress; + } + + /** + * @param \Thelia\Model\Order $order + */ + public function setOrder(Order $order) + { + $this->order = $order; + } + + /** + * @return \Thelia\Model\OrderAddress + */ + public function getOrderAddress() + { + return $this->orderAddress; + } + + /** + * @return \Thelia\Model\Order + */ + public function getOrder() + { + return $this->order; + } +} diff --git a/core/lib/Thelia/Core/Event/Order/OrderEvent.php b/core/lib/Thelia/Core/Event/Order/OrderEvent.php new file mode 100644 index 00000000..49cf9201 --- /dev/null +++ b/core/lib/Thelia/Core/Event/Order/OrderEvent.php @@ -0,0 +1,378 @@ +setOrder($order); + } + + /** + * @param Order $order + * @return $this + */ + public function setOrder(Order $order) + { + $this->order = $order; + + return $this; + } + + /** + * @param int $cartItemId + * @return $this + */ + public function setCartItemId($cartItemId) + { + $this->cartItemId = $cartItemId; + + return $this; + } + + /** + * @return int + */ + public function getCartItemId() + { + return $this->cartItemId; + } + + /** + * @param Order $order + * @return $this + */ + public function setPlacedOrder(Order $order) + { + $this->placedOrder = $order; + + return $this; + } + + /** + * @param int $address an address ID + * @return $this + */ + public function setInvoiceAddress($address) + { + $this->invoiceAddress = $address; + + return $this; + } + + /** + * @param int $address an address ID + * @return $this + */ + public function setDeliveryAddress($address) + { + $this->deliveryAddress = $address; + + return $this; + } + + /** + * @param int $module a delivery module ID + * @return $this + */ + public function setDeliveryModule($module) + { + $this->deliveryModule = $module; + + return $this; + } + + /** + * @param int $module a payment module ID + * @return $this + */ + public function setPaymentModule($module) + { + $this->paymentModule = $module; + + return $this; + } + + /** + * @param double $postage the postage amount + * @return $this + */ + public function setPostage($postage) + { + $this->postage = $postage; + + return $this; + } + + /** + * @param string $ref the order reference + * @return $this + */ + public function setRef($ref) + { + $this->ref = $ref; + + return $this; + } + + /** + * @param int $status the order status ID + * @return $this + */ + public function setStatus($status) + { + $this->status = $status; + + return $this; + } + + /** + * @param string $deliveryRef the delivery reference + * @return $this + */ + public function setDeliveryRef($deliveryRef) + { + $this->deliveryRef = $deliveryRef; + + return $this; + } + + /** + * @return Order the order + */ + public function getOrder() + { + return $this->order; + } + + /** + * @return Order the placed order, valid only after order payment + * @throws \LogicException if the method is called before payment + */ + public function getPlacedOrder() + { + if (null === $this->placedOrder) { + throw new \LogicException("The placed order is defined only after dispatching of the ORDER_PAY event"); + } + + return $this->placedOrder; + } + + /** + * @return null|int the invoice address ID + */ + public function getInvoiceAddress() + { + return $this->invoiceAddress; + } + + /** + * @return null|int the delivery addres ID + */ + public function getDeliveryAddress() + { + return $this->deliveryAddress; + } + + /** + * @return null|int the delivery module ID + */ + public function getDeliveryModule() + { + return $this->deliveryModule; + } + + /** + * @return null|int the payment module ID + */ + public function getPaymentModule() + { + return $this->paymentModule; + } + + /** + * @return null|double the postage amount + */ + public function getPostage() + { + return $this->postage; + } + + /** + * @return null|string the order reference + */ + public function getRef() + { + return $this->ref; + } + + /** + * @return null|int the order status ID + */ + public function getStatus() + { + return $this->status; + } + + /** + * @return null|string the delivery reference + */ + public function getDeliveryRef() + { + return $this->deliveryRef; + } + + /** + * @param Response $response the payment request response + * @return $this + */ + public function setResponse(Response $response) + { + $this->response = $response; + + return $this; + } + + /** + * @return Response the payment request response + */ + public function getResponse() + { + return $this->response; + } + + /** + * @return bool true if this event has a payment request response + */ + public function hasResponse() + { + return null !== $this->response; + } + + /** + * @return null + */ + public function getPostageTax() + { + return $this->postageTax; + } + + /** + * @param null $postageTax + * @return $this + */ + public function setPostageTax($postageTax) + { + $this->postageTax = $postageTax; + + return $this; + } + + /** + * @return null + */ + public function getPostageTaxRuleTitle() + { + return $this->postageTaxRuleTitle; + } + + /** + * @param null $postageTaxRuleTitle + * @return $this + */ + public function setPostageTaxRuleTitle($postageTaxRuleTitle) + { + $this->postageTaxRuleTitle = $postageTaxRuleTitle; + + 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; + } +} diff --git a/core/lib/Thelia/Core/Event/Order/OrderManualEvent.php b/core/lib/Thelia/Core/Event/Order/OrderManualEvent.php new file mode 100644 index 00000000..e27c1228 --- /dev/null +++ b/core/lib/Thelia/Core/Event/Order/OrderManualEvent.php @@ -0,0 +1,141 @@ +setCurrency($currency) + ->setLang($lang) + ->setCart($cart) + ->setCustomer($customer) + ; + } + + public function getCurrency() + { + return $this->currency; + } + + /** + * @param Currency $currency + * @return $this + */ + public function setCurrency($currency) + { + $this->currency = $currency; + + return $this; + } + + /** + * @return Lang + */ + public function getLang() + { + return $this->lang; + } + + /** + * @param Lang $lang + * @return $this + */ + public function setLang($lang) + { + $this->lang = $lang; + + return $this; + } + + /** + * @return Cart + */ + public function getCart() + { + return $this->cart; + } + + /** + * @param Cart $cart + * @return $this + */ + public function setCart($cart) + { + $this->cart = $cart; + + return $this; + } + + /** + * @return Customer + */ + public function getCustomer() + { + return $this->customer; + } + + /** + * @param Customer $customer + * @return $this + */ + public function setCustomer($customer) + { + $this->customer = $customer; + + return $this; + } + + /** + * @return boolean + */ + public function getUseOrderDefinedAddresses() + { + return $this->useOrderDefinedAddresses; + } + + /** + * If true, the order will be created using the delivery and invoice addresses defined in $this->order instead of + * creating new OrderAdresses using the Order::getChoosenXXXAddress(). + * + * @param boolean $useOrderDefinedAddresses + * @return $this + */ + public function setUseOrderDefinedAddresses($useOrderDefinedAddresses) + { + $this->useOrderDefinedAddresses = $useOrderDefinedAddresses; + return $this; + } +} diff --git a/core/lib/Thelia/Core/Event/Order/OrderPaymentEvent.php b/core/lib/Thelia/Core/Event/Order/OrderPaymentEvent.php new file mode 100644 index 00000000..64121d2c --- /dev/null +++ b/core/lib/Thelia/Core/Event/Order/OrderPaymentEvent.php @@ -0,0 +1,73 @@ + + */ +class OrderPaymentEvent extends ActionEvent +{ + /** + * @var Order + */ + protected $order; + + /** + * @var \Thelia\Core\HttpFoundation\Response + */ + protected $response; + + public function __construct(Order $order) + { + $this->order = $order; + } + + /** + * @return \Thelia\Model\Order + */ + public function getOrder() + { + return $this->order; + } + + /** + * @param Response $response + * + * @return $this + */ + public function setResponse(Response $response) + { + $this->response = $response; + + return $this; + } + + /** + * @return \Thelia\Core\HttpFoundation\Response + */ + public function getResponse() + { + return $this->response; + } + + public function hasResponse() + { + return null !== $this->response; + } +} diff --git a/core/lib/Thelia/Core/Event/Order/OrderProductEvent.php b/core/lib/Thelia/Core/Event/Order/OrderProductEvent.php new file mode 100644 index 00000000..d1181bd0 --- /dev/null +++ b/core/lib/Thelia/Core/Event/Order/OrderProductEvent.php @@ -0,0 +1,54 @@ +setId($id); + } + + /** + * @param $id + * @return $this + */ + public function setId($id) + { + $this->id = $id; + + return $this; + } + + /** + * @return int|null + */ + public function getId() + { + return $this->id; + } +} diff --git a/core/lib/Thelia/Core/Event/OrderStatus/OrderStatusCreateEvent.php b/core/lib/Thelia/Core/Event/OrderStatus/OrderStatusCreateEvent.php new file mode 100644 index 00000000..f38d0afe --- /dev/null +++ b/core/lib/Thelia/Core/Event/OrderStatus/OrderStatusCreateEvent.php @@ -0,0 +1,22 @@ + + */ +class OrderStatusCreateEvent extends OrderStatusEvent +{ +} diff --git a/core/lib/Thelia/Core/Event/OrderStatus/OrderStatusDeleteEvent.php b/core/lib/Thelia/Core/Event/OrderStatus/OrderStatusDeleteEvent.php new file mode 100644 index 00000000..5ad4b461 --- /dev/null +++ b/core/lib/Thelia/Core/Event/OrderStatus/OrderStatusDeleteEvent.php @@ -0,0 +1,22 @@ + + */ +class OrderStatusDeleteEvent extends OrderStatusUpdateEvent +{ +} diff --git a/core/lib/Thelia/Core/Event/OrderStatus/OrderStatusEvent.php b/core/lib/Thelia/Core/Event/OrderStatus/OrderStatusEvent.php new file mode 100644 index 00000000..84fb3abc --- /dev/null +++ b/core/lib/Thelia/Core/Event/OrderStatus/OrderStatusEvent.php @@ -0,0 +1,221 @@ + + */ +class OrderStatusEvent extends ActionEvent +{ + /** @var string */ + protected $code; + + /** @var string */ + protected $title; + + /** @var string */ + protected $description; + + /** @var string */ + protected $chapo; + + /** @var string */ + protected $postscriptum; + + /** @var string */ + protected $color; + + /** @var string */ + protected $locale = 'en_US'; + + /** @var OrderStatus */ + protected $orderStatus; + + /** @var int */ + protected $position; + + /** + * @return int + */ + public function getPosition() + { + return $this->position; + } + + /** + * @param int $position + * @return OrderStatusEvent + */ + public function setPosition($position) + { + $this->position = $position; + return $this; + } + + /** + * @return bool + */ + public function hasOrderStatus() + { + return null !== $this->orderStatus; + } + + /** + * @return OrderStatus + */ + public function getOrderStatus() + { + return $this->orderStatus; + } + + /** + * @param OrderStatus $orderStatus + * @return OrderStatusEvent + */ + public function setOrderStatus($orderStatus) + { + $this->orderStatus = $orderStatus; + return $this; + } + + /** + * @return string + */ + public function getLocale() + { + return $this->locale; + } + + /** + * @param string $locale + * @return OrderStatusEvent + */ + public function setLocale($locale) + { + $this->locale = $locale; + return $this; + } + + /** + * @return string + */ + public function getCode() + { + return $this->code; + } + + /** + * @param string $code + * @return OrderStatusEvent + */ + public function setCode($code) + { + $this->code = $code; + return $this; + } + + /** + * @return string + */ + public function getColor() + { + return $this->color; + } + + /** + * @param string $color + * @return OrderStatusEvent + */ + public function setColor($color) + { + $this->color = $color; + return $this; + } + + /** + * @return string + */ + public function getTitle() + { + return $this->title; + } + + /** + * @param string $title + * @return OrderStatusEvent + */ + public function setTitle($title) + { + $this->title = $title; + return $this; + } + + /** + * @return string + */ + public function getDescription() + { + return $this->description; + } + + /** + * @param string $description + * @return OrderStatusEvent + */ + public function setDescription($description) + { + $this->description = $description; + return $this; + } + + /** + * @return string + */ + public function getChapo() + { + return $this->chapo; + } + + /** + * @param string $chapo + * @return OrderStatusEvent + */ + public function setChapo($chapo) + { + $this->chapo = $chapo; + return $this; + } + + /** + * @return string + */ + public function getPostscriptum() + { + return $this->postscriptum; + } + + /** + * @param string $postscriptum + * @return OrderStatusEvent + */ + public function setPostscriptum($postscriptum) + { + $this->postscriptum = $postscriptum; + return $this; + } +} diff --git a/core/lib/Thelia/Core/Event/OrderStatus/OrderStatusUpdateEvent.php b/core/lib/Thelia/Core/Event/OrderStatus/OrderStatusUpdateEvent.php new file mode 100644 index 00000000..58cecc46 --- /dev/null +++ b/core/lib/Thelia/Core/Event/OrderStatus/OrderStatusUpdateEvent.php @@ -0,0 +1,51 @@ + + */ +class OrderStatusUpdateEvent extends OrderStatusEvent +{ + /** @var int */ + protected $id; + + /** + * OrderStatusUpdateEvent constructor. + * @param int $id + */ + public function __construct($id) + { + $this->id = $id; + } + + /** + * @return int + */ + public function getId() + { + return $this->id; + } + + /** + * @param int $id + * @return OrderStatusUpdateEvent + */ + public function setId($id) + { + $this->id = $id; + return $this; + } +} diff --git a/core/lib/Thelia/Core/Event/Payment/BasePaymentEvent.php b/core/lib/Thelia/Core/Event/Payment/BasePaymentEvent.php new file mode 100644 index 00000000..f7272ea1 --- /dev/null +++ b/core/lib/Thelia/Core/Event/Payment/BasePaymentEvent.php @@ -0,0 +1,55 @@ + + */ +class BasePaymentEvent extends ActionEvent +{ + /** @var AbstractPaymentModule */ + protected $module = null; + + /** + * BasePaymentEvent constructor. + * @param AbstractPaymentModule $module + */ + public function __construct(AbstractPaymentModule $module) + { + $this->module = $module; + } + + /** + * @return AbstractPaymentModule + */ + public function getModule() + { + return $this->module; + } + + /** + * @param AbstractPaymentModule $module + */ + public function setModule($module) + { + $this->module = $module; + return $this; + } +} diff --git a/core/lib/Thelia/Core/Event/Payment/IsValidPaymentEvent.php b/core/lib/Thelia/Core/Event/Payment/IsValidPaymentEvent.php new file mode 100644 index 00000000..4958261b --- /dev/null +++ b/core/lib/Thelia/Core/Event/Payment/IsValidPaymentEvent.php @@ -0,0 +1,117 @@ + + */ +class IsValidPaymentEvent extends BasePaymentEvent +{ + /** @var Cart */ + protected $cart = null; + + /** @var bool */ + protected $validModule = false; + + /** @var float */ + protected $minimumAmount = null; + + /** @var float */ + protected $maximumAmount = null; + + /** + * IsValidPaymentEvent constructor. + * + * @param AbstractPaymentModule $module + * @param Cart $cart + */ + public function __construct(AbstractPaymentModule $module, Cart $cart) + { + parent::__construct($module); + $this->cart = $cart; + } + + /** + * @return Cart + */ + public function getCart() + { + return $this->cart; + } + + /** + * @param Cart $cart + */ + public function setCart($cart) + { + $this->cart = $cart; + return $this; + } + + /** + * @return boolean + */ + public function isValidModule() + { + return $this->validModule; + } + + /** + * @param boolean $validModule + */ + public function setValidModule($validModule) + { + $this->validModule = $validModule; + return $this; + } + + /** + * @return float + */ + public function getMinimumAmount() + { + return $this->minimumAmount; + } + + /** + * @param float $minimumAmount + */ + public function setMinimumAmount($minimumAmount) + { + $this->minimumAmount = $minimumAmount; + return $this; + } + + /** + * @return float + */ + public function getMaximumAmount() + { + return $this->maximumAmount; + } + + /** + * @param float $maximumAmount + */ + public function setMaximumAmount($maximumAmount) + { + $this->maximumAmount = $maximumAmount; + return $this; + } +} diff --git a/core/lib/Thelia/Core/Event/Payment/ManageStockOnCreationEvent.php b/core/lib/Thelia/Core/Event/Payment/ManageStockOnCreationEvent.php new file mode 100644 index 00000000..c43fd8f9 --- /dev/null +++ b/core/lib/Thelia/Core/Event/Payment/ManageStockOnCreationEvent.php @@ -0,0 +1,53 @@ + + */ +class ManageStockOnCreationEvent extends BasePaymentEvent +{ + /** @var bool|null */ + protected $manageStock = null; + + /** + * ManageStockOnCreationEvent constructor. + * @param bool|null $manageStock + */ + public function __construct(PaymentModuleInterface $module) + { + parent::__construct($module); + } + + /** + * @return bool|null + */ + public function getManageStock() + { + return $this->manageStock; + } + + /** + * @param bool|null $manageStock + */ + public function setManageStock($manageStock) + { + $this->manageStock = $manageStock; + return $this; + } +} diff --git a/core/lib/Thelia/Core/Event/PdfEvent.php b/core/lib/Thelia/Core/Event/PdfEvent.php new file mode 100644 index 00000000..daec7823 --- /dev/null +++ b/core/lib/Thelia/Core/Event/PdfEvent.php @@ -0,0 +1,231 @@ + + */ +class PdfEvent extends ActionEvent +{ + protected $content; + + protected $pdf; + + protected $orientation; + protected $format; + protected $lang; + protected $unicode; + protected $encoding; + protected $marges; + protected $fontName; + + /** + * @param string $content html content to transform into pdf + * @param string $orientation page orientation, same as TCPDF + * @param string $format The format used for pages, same as TCPDF + * @param string $lang Lang : fr, en, it... + * @param bool $unicode TRUE means that the input text is unicode (default = true) + * @param string $encoding charset encoding; default is UTF-8 + * @param array $marges Default marges (left, top, right, bottom) + * @param string $fontName Default font name + */ + public function __construct( + $content, + $orientation = 'P', + $format = 'A4', + $lang = 'fr', + $unicode = true, + $encoding = 'UTF-8', + array $marges = [ 0, 0, 0, 0], + $fontName = 'freesans' + ) { + $this->content = $content; + $this->orientation = $orientation; + $this->format = $format; + $this->lang = $lang; + $this->unicode = $unicode; + $this->encoding = $encoding; + $this->marges = $marges; + $this->fontName = $fontName; + } + + /** + * @param mixed $content + * @return $this + */ + public function setContent($content) + { + $this->content = $content; + + return $this; + } + + /** + * @return mixed + */ + public function getContent() + { + return $this->content; + } + + public function setPdf($pdf) + { + $this->pdf = $pdf; + + return $this; + } + + public function getPdf() + { + return $this->pdf; + } + + public function hasPdf() + { + return null !== $this->pdf; + } + + /** + * @param mixed $encoding + * @return $this + */ + public function setEncoding($encoding) + { + $this->encoding = $encoding; + + return $this; + } + + /** + * @return mixed + */ + public function getEncoding() + { + return $this->encoding; + } + + /** + * @param mixed $format + * @return $this + */ + public function setFormat($format) + { + $this->format = $format; + + return $this; + } + + /** + * @return mixed + */ + public function getFormat() + { + return $this->format; + } + + /** + * @param mixed $lang + * @return $this + */ + public function setLang($lang) + { + $this->lang = $lang; + + return $this; + } + + /** + * @return mixed + */ + public function getLang() + { + return $this->lang; + } + + /** + * @param array $marges + * @return $this + */ + public function setMarges($marges) + { + $this->marges = $marges; + + return $this; + } + + /** + * @return array + */ + public function getMarges() + { + return $this->marges; + } + + /** + * @param mixed $orientation + * @return $this + */ + public function setOrientation($orientation) + { + $this->orientation = $orientation; + + return $this; + } + + /** + * @return mixed + */ + public function getOrientation() + { + return $this->orientation; + } + + /** + * @param mixed $unicode + * @return $this + */ + public function setUnicode($unicode) + { + $this->unicode = $unicode; + + return $this; + } + + /** + * @return mixed + */ + public function getUnicode() + { + return $this->unicode; + } + + /** + * @return mixed + */ + public function getFontName() + { + return $this->fontName; + } + + /** + * @param string $fontName + * @return $this + */ + public function setFontName($fontName) + { + $this->fontName = $fontName; + return $this; + } +} diff --git a/core/lib/Thelia/Core/Event/Product/ProductAddAccessoryEvent.php b/core/lib/Thelia/Core/Event/Product/ProductAddAccessoryEvent.php new file mode 100644 index 00000000..1f9fe232 --- /dev/null +++ b/core/lib/Thelia/Core/Event/Product/ProductAddAccessoryEvent.php @@ -0,0 +1,37 @@ +accessory_id = $accessory_id; + } + + public function getAccessoryId() + { + return $this->accessory_id; + } + + public function setAccessoryId($accessory_id) + { + $this->accessory_id = $accessory_id; + } +} diff --git a/core/lib/Thelia/Core/Event/Product/ProductAddCategoryEvent.php b/core/lib/Thelia/Core/Event/Product/ProductAddCategoryEvent.php new file mode 100644 index 00000000..617913c0 --- /dev/null +++ b/core/lib/Thelia/Core/Event/Product/ProductAddCategoryEvent.php @@ -0,0 +1,37 @@ +category_id = $category_id; + } + + public function getCategoryId() + { + return $this->category_id; + } + + public function setCategoryId($category_id) + { + $this->category_id = $category_id; + } +} diff --git a/core/lib/Thelia/Core/Event/Product/ProductAddContentEvent.php b/core/lib/Thelia/Core/Event/Product/ProductAddContentEvent.php new file mode 100644 index 00000000..9dad4b41 --- /dev/null +++ b/core/lib/Thelia/Core/Event/Product/ProductAddContentEvent.php @@ -0,0 +1,37 @@ +content_id = $content_id; + } + + public function getContentId() + { + return $this->content_id; + } + + public function setContentId($content_id) + { + $this->content_id = $content_id; + } +} diff --git a/core/lib/Thelia/Core/Event/Product/ProductAssociatedContentEvent.php b/core/lib/Thelia/Core/Event/Product/ProductAssociatedContentEvent.php new file mode 100644 index 00000000..8de6896e --- /dev/null +++ b/core/lib/Thelia/Core/Event/Product/ProductAssociatedContentEvent.php @@ -0,0 +1,46 @@ +content = $content; + } + + public function hasProductAssociatedContent() + { + return ! \is_null($this->content); + } + + public function getProductAssociatedContent() + { + return $this->content; + } + + public function setProductAssociatedContent(ProductAssociatedContent $content) + { + $this->content = $content; + + return $this; + } +} diff --git a/core/lib/Thelia/Core/Event/Product/ProductCloneEvent.php b/core/lib/Thelia/Core/Event/Product/ProductCloneEvent.php new file mode 100644 index 00000000..08df07a4 --- /dev/null +++ b/core/lib/Thelia/Core/Event/Product/ProductCloneEvent.php @@ -0,0 +1,118 @@ +ref = $ref; + $this->lang = $lang; + $this->originalProduct = $originalProduct; + } + + /** + * @return string + */ + public function getRef() + { + return $this->ref; + } + + /** + * @param string $ref + */ + public function setRef($ref) + { + $this->ref = $ref; + } + + /** + * @return string the locale (such as fr_FR) + */ + public function getLang() + { + return $this->lang; + } + + /** + * @param string $lang the locale (such as fr_FR) + */ + public function setLang($lang) + { + $this->lang = $lang; + } + + /** + * @return Product + */ + public function getOriginalProduct() + { + return $this->originalProduct; + } + + /** + * @param Product $originalProduct + */ + public function setOriginalProduct($originalProduct) + { + $this->originalProduct = $originalProduct; + } + + /** + * @return Product + */ + public function getClonedProduct() + { + return $this->clonedProduct; + } + + /** + * @param Product $clonedProduct + */ + public function setClonedProduct($clonedProduct) + { + $this->clonedProduct = $clonedProduct; + } + + /** + * @return array + */ + public function getTypes() + { + return $this->types; + } +} diff --git a/core/lib/Thelia/Core/Event/Product/ProductCombinationGenerationEvent.php b/core/lib/Thelia/Core/Event/Product/ProductCombinationGenerationEvent.php new file mode 100644 index 00000000..9c199336 --- /dev/null +++ b/core/lib/Thelia/Core/Event/Product/ProductCombinationGenerationEvent.php @@ -0,0 +1,157 @@ +setCombinations($combinations); + $this->setCurrencyId($currency_id); + } + + public function getCurrencyId() + { + return $this->currency_id; + } + + public function setCurrencyId($currency_id) + { + $this->currency_id = $currency_id; + + return $this; + } + + public function getReference() + { + return $this->reference; + } + + public function setReference($reference) + { + $this->reference = $reference; + + return $this; + } + + public function getPrice() + { + return $this->price; + } + + public function setPrice($price) + { + $this->price = $price; + + return $this; + } + + public function getWeight() + { + return $this->weight; + } + + public function setWeight($weight) + { + $this->weight = $weight; + + return $this; + } + + public function getQuantity() + { + return $this->quantity; + } + + public function setQuantity($quantity) + { + $this->quantity = $quantity; + + return $this; + } + + public function getSalePrice() + { + return $this->sale_price; + } + + public function setSalePrice($sale_price) + { + $this->sale_price = $sale_price; + + return $this; + } + + public function getOnsale() + { + return $this->onsale; + } + + public function setOnsale($onsale) + { + $this->onsale = $onsale; + + return $this; + } + + public function getIsnew() + { + return $this->isnew; + } + + public function setIsnew($isnew) + { + $this->isnew = $isnew; + + return $this; + } + + public function getEanCode() + { + return $this->ean_code; + } + + public function setEanCode($ean_code) + { + $this->ean_code = $ean_code; + + return $this; + } + + public function getCombinations() + { + return $this->combinations; + } + + public function setCombinations($combinations) + { + $this->combinations = $combinations; + + return $this; + } +} diff --git a/core/lib/Thelia/Core/Event/Product/ProductCreateEvent.php b/core/lib/Thelia/Core/Event/Product/ProductCreateEvent.php new file mode 100644 index 00000000..ef6999fe --- /dev/null +++ b/core/lib/Thelia/Core/Event/Product/ProductCreateEvent.php @@ -0,0 +1,246 @@ +ref; + } + + public function setRef($ref) + { + $this->ref = $ref; + + return $this; + } + + public function getTitle() + { + return $this->title; + } + + public function setTitle($title) + { + $this->title = $title; + + return $this; + } + + public function getLocale() + { + return $this->locale; + } + + public function setLocale($locale) + { + $this->locale = $locale; + + return $this; + } + + public function getDefaultCategory() + { + return $this->default_category; + } + + public function setDefaultCategory($default_category) + { + $this->default_category = $default_category; + + return $this; + } + + public function getVisible() + { + return $this->visible; + } + + public function setVisible($visible) + { + $this->visible = $visible; + + return $this; + } + + public function setVirtual($virtual) + { + $this->virtual = $virtual; + + return $this; + } + + public function getVirtual() + { + return $this->virtual; + } + + public function getBasePrice() + { + return $this->basePrice; + } + + public function setBasePrice($basePrice) + { + $this->basePrice = $basePrice; + + return $this; + } + + public function getBaseWeight() + { + return $this->baseWeight; + } + + public function setBaseWeight($baseWeight) + { + $this->baseWeight = $baseWeight; + + return $this; + } + + public function getTaxRuleId() + { + return $this->taxRuleId; + } + + public function setTaxRuleId($taxRuleId) + { + $this->taxRuleId = $taxRuleId; + + return $this; + } + + public function getCurrencyId() + { + return $this->currencyId; + } + + public function setCurrencyId($currencyId) + { + $this->currencyId = $currencyId; + + return $this; + } + + /** + * This method is an alias of setBasePrice and used by the event when binding a form + * + * @param float $price price for this new product + * @return $this + * @see setBasePrice + */ + public function setPrice($price) + { + return $this->setBasePrice($price); + } + + /** + * This method is an alias of setBaseWeight and used by the event when binding a form + * + * @param float $weight + * @return $this + * @see setBaseWeight + */ + public function setWeight($weight) + { + return $this->setBaseWeight($weight); + } + + /** + * This method is an alias of setCurrencyId and used by the event when binding a form + * + * @param $currencyId + * @return $this + * @see setCurrencyId + */ + public function setCurrency($currencyId) + { + return $this->setCurrencyId($currencyId); + } + + /** + * This method is an alias of setTaxRuleId and used by the event when binding a form + * + * @param $taxRuleId + * @return $this + * @see setTaxRuleId + */ + public function setTaxRule($taxRuleId) + { + return $this->setTaxRuleId($taxRuleId); + } + + /** + * @return integer + */ + public function getBaseQuantity() + { + return $this->baseQuantity; + } + + /** + * @param integer $baseQuantity + * @return $this + */ + public function setBaseQuantity($baseQuantity) + { + $this->baseQuantity = $baseQuantity; + return $this; + } + + /** + * This method is an alias of setBaseQuantity and used by the event when binding a form + * + * @param integer $quantity quantity for this new product + * @return $this + * @see setBaseQuantity + */ + public function setQuantity($quantity) + { + return $this->setBaseQuantity($quantity); + } + + /** + * @return integer + */ + public function getTemplateId() + { + return $this->templateId; + } + + /** + * @param integer $templateId + * @return $this + */ + public function setTemplateId($templateId) + { + $this->templateId = $templateId; + return $this; + } +} diff --git a/core/lib/Thelia/Core/Event/Product/ProductDeleteAccessoryEvent.php b/core/lib/Thelia/Core/Event/Product/ProductDeleteAccessoryEvent.php new file mode 100644 index 00000000..4ddd2f31 --- /dev/null +++ b/core/lib/Thelia/Core/Event/Product/ProductDeleteAccessoryEvent.php @@ -0,0 +1,37 @@ +accessory_id = $accessory_id; + } + + public function getAccessoryId() + { + return $this->accessory_id; + } + + public function setAccessoryId($accessory_id) + { + $this->accessory_id = $accessory_id; + } +} diff --git a/core/lib/Thelia/Core/Event/Product/ProductDeleteCategoryEvent.php b/core/lib/Thelia/Core/Event/Product/ProductDeleteCategoryEvent.php new file mode 100644 index 00000000..cb7f2db1 --- /dev/null +++ b/core/lib/Thelia/Core/Event/Product/ProductDeleteCategoryEvent.php @@ -0,0 +1,39 @@ +category_id = $category_id; + } + + public function getCategoryId() + { + return $this->category_id; + } + + public function setCategoryId($category_id) + { + $this->category_id = $category_id; + + return $this; + } +} diff --git a/core/lib/Thelia/Core/Event/Product/ProductDeleteContentEvent.php b/core/lib/Thelia/Core/Event/Product/ProductDeleteContentEvent.php new file mode 100644 index 00000000..db7190c4 --- /dev/null +++ b/core/lib/Thelia/Core/Event/Product/ProductDeleteContentEvent.php @@ -0,0 +1,37 @@ +content_id = $content_id; + } + + public function getContentId() + { + return $this->content_id; + } + + public function setContentId($content_id) + { + $this->content_id = $content_id; + } +} diff --git a/core/lib/Thelia/Core/Event/Product/ProductDeleteEvent.php b/core/lib/Thelia/Core/Event/Product/ProductDeleteEvent.php new file mode 100644 index 00000000..c651f942 --- /dev/null +++ b/core/lib/Thelia/Core/Event/Product/ProductDeleteEvent.php @@ -0,0 +1,46 @@ +product_id = $product_id; + } + + /** + * @return int + */ + public function getProductId() + { + return $this->product_id; + } + + /** + * @param $product_id + * @return $this + */ + public function setProductId($product_id) + { + $this->product_id = $product_id; + + return $this; + } +} diff --git a/core/lib/Thelia/Core/Event/Product/ProductEvent.php b/core/lib/Thelia/Core/Event/Product/ProductEvent.php new file mode 100644 index 00000000..0b7efa84 --- /dev/null +++ b/core/lib/Thelia/Core/Event/Product/ProductEvent.php @@ -0,0 +1,46 @@ +product = $product; + } + + public function hasProduct() + { + return ! \is_null($this->product); + } + + public function getProduct() + { + return $this->product; + } + + public function setProduct(Product $product) + { + $this->product = $product; + + return $this; + } +} diff --git a/core/lib/Thelia/Core/Event/Product/ProductSetTemplateEvent.php b/core/lib/Thelia/Core/Event/Product/ProductSetTemplateEvent.php new file mode 100644 index 00000000..d74c0b11 --- /dev/null +++ b/core/lib/Thelia/Core/Event/Product/ProductSetTemplateEvent.php @@ -0,0 +1,53 @@ +template_id = $template_id; + $this->currency_id = $currency_id; + } + + public function getTemplateId() + { + return $this->template_id; + } + + public function setTemplateId($template_id) + { + $this->template_id = $template_id; + + return $this; + } + + public function getCurrencyId() + { + return $this->currency_id; + } + + public function setCurrencyId($currency_id) + { + $this->currency_id = $currency_id; + + return $this; + } +} diff --git a/core/lib/Thelia/Core/Event/Product/ProductToggleVisibilityEvent.php b/core/lib/Thelia/Core/Event/Product/ProductToggleVisibilityEvent.php new file mode 100644 index 00000000..e6f82b22 --- /dev/null +++ b/core/lib/Thelia/Core/Event/Product/ProductToggleVisibilityEvent.php @@ -0,0 +1,17 @@ +product_id = $product_id; + } + + public function getProductId() + { + return $this->product_id; + } + + public function setProductId($product_id) + { + $this->product_id = $product_id; + + return $this; + } + + public function getChapo() + { + return $this->chapo; + } + + public function setChapo($chapo) + { + $this->chapo = $chapo; + + return $this; + } + + public function getDescription() + { + return $this->description; + } + + public function setDescription($description) + { + $this->description = $description; + + return $this; + } + + public function getPostscriptum() + { + return $this->postscriptum; + } + + public function setPostscriptum($postscriptum) + { + $this->postscriptum = $postscriptum; + + return $this; + } + + /** + * @param int $brand_id + * @return $this + */ + public function setBrandId($brand_id) + { + $this->brand_id = $brand_id; + + return $this; + } + + /** + * @return int + */ + public function getBrandId() + { + return $this->brand_id; + } + + /** + * @param mixed $virtual_document_id + * + * @return $this + */ + public function setVirtualDocumentId($virtual_document_id) + { + $this->virtual_document_id = $virtual_document_id; + + return $this; + } + + /** + * @return mixed + */ + public function getVirtualDocumentId() + { + return $this->virtual_document_id; + } +} diff --git a/core/lib/Thelia/Core/Event/Product/VirtualProductOrderDownloadResponseEvent.php b/core/lib/Thelia/Core/Event/Product/VirtualProductOrderDownloadResponseEvent.php new file mode 100644 index 00000000..ebfd575a --- /dev/null +++ b/core/lib/Thelia/Core/Event/Product/VirtualProductOrderDownloadResponseEvent.php @@ -0,0 +1,78 @@ + + */ +class VirtualProductOrderDownloadResponseEvent extends ActionEvent +{ + /** @var OrderProduct */ + protected $orderProduct; + + /**@var Response */ + protected $response; + + /** + * @param OrderProduct $orderProduct + */ + public function __construct(OrderProduct $orderProduct) + { + $this->orderProduct = $orderProduct; + } + + /** + * @return OrderProduct + */ + public function getOrderProduct() + { + return $this->orderProduct; + } + + /** + * @param OrderProduct $orderProduct + * @return $this + */ + public function setOrderProduct(OrderProduct $orderProduct) + { + $this->orderProduct = $orderProduct; + + return $this; + } + + /** + * @return Response + */ + public function getResponse() + { + return $this->response; + } + + /** + * @param Response $response + * @return $this + */ + public function setResponse(Response $response) + { + $this->response = $response; + + return $this; + } +} diff --git a/core/lib/Thelia/Core/Event/Product/VirtualProductOrderHandleEvent.php b/core/lib/Thelia/Core/Event/Product/VirtualProductOrderHandleEvent.php new file mode 100644 index 00000000..d858e25f --- /dev/null +++ b/core/lib/Thelia/Core/Event/Product/VirtualProductOrderHandleEvent.php @@ -0,0 +1,144 @@ + + */ +class VirtualProductOrderHandleEvent extends ActionEvent +{ + /** @var int the product sale element id*/ + protected $pseId; + + /** @var Order the order */ + protected $order; + + /** @var string the path of the file */ + protected $path; + + /** @var bool is virtual product is really virtual */ + protected $virtual = true; + + /** @var bool use the stock for this virtual product */ + protected $useStock = false; + + public function __construct(Order $order, $pseId) + { + $this->order = $order; + $this->pseId = $pseId; + } + + /** + * @return Order + */ + public function getOrder() + { + return $this->order; + } + + /** + * @param Order $order + */ + public function setOrder($order) + { + $this->order = $order; + + return $this; + } + + /** + * @return string + */ + public function getPath() + { + return $this->path; + } + + /** + * @param string $path + */ + public function setPath($path) + { + $this->path = $path; + + return $this; + } + + + /** + * @return int + */ + public function getPseId() + { + return $this->pseId; + } + + /** + * @param int $pseId + */ + public function setPseId($pseId) + { + $this->pseId = $pseId; + + return $this; + } + + /** + * @return boolean + */ + public function isUseStock() + { + return $this->useStock; + } + + /** + * @param boolean $useStock + */ + public function setUseStock($useStock) + { + $this->useStock = $useStock; + + return $this; + } + + /** + * @return boolean + */ + public function isVirtual() + { + return $this->virtual; + } + + /** + * @param boolean $virtual + */ + public function setVirtual($virtual) + { + $this->virtual = $virtual; + + return $this; + } +} diff --git a/core/lib/Thelia/Core/Event/ProductSaleElement/ProductSaleElementCreateEvent.php b/core/lib/Thelia/Core/Event/ProductSaleElement/ProductSaleElementCreateEvent.php new file mode 100644 index 00000000..7dafaf54 --- /dev/null +++ b/core/lib/Thelia/Core/Event/ProductSaleElement/ProductSaleElementCreateEvent.php @@ -0,0 +1,70 @@ +setAttributeAvList($attribute_av_list); + $this->setCurrencyId($currency_id); + $this->setProduct($product); + } + + public function getAttributeAvList() + { + return $this->attribute_av_list; + } + + public function setAttributeAvList($attribute_av_list) + { + $this->attribute_av_list = $attribute_av_list; + + return $this; + } + + public function getCurrencyId() + { + return $this->currency_id; + } + + public function setCurrencyId($currency_id) + { + $this->currency_id = $currency_id; + + return $this; + } + + /** + * @return Product + */ + public function getProduct() + { + return $this->product; + } + + public function setProduct($product) + { + $this->product = $product; + + return $this; + } +} diff --git a/core/lib/Thelia/Core/Event/ProductSaleElement/ProductSaleElementDeleteEvent.php b/core/lib/Thelia/Core/Event/ProductSaleElement/ProductSaleElementDeleteEvent.php new file mode 100644 index 00000000..706b8ccc --- /dev/null +++ b/core/lib/Thelia/Core/Event/ProductSaleElement/ProductSaleElementDeleteEvent.php @@ -0,0 +1,72 @@ +product_sale_element_id = $product_sale_element_id; + $this->currency_id = $currency_id; + } + + /** + * @return int + */ + public function getProductSaleElementId() + { + return $this->product_sale_element_id; + } + + /** + * @param int $product_sale_element_id + * @return $this + */ + public function setProductSaleElementId($product_sale_element_id) + { + $this->product_sale_element_id = $product_sale_element_id; + + return $this; + } + + /** + * @return int + */ + public function getCurrencyId() + { + return $this->currency_id; + } + + /** + * @param int $currency_id + * @return $this + */ + public function setCurrencyId($currency_id) + { + $this->currency_id = $currency_id; + + return $this; + } +} diff --git a/core/lib/Thelia/Core/Event/ProductSaleElement/ProductSaleElementEvent.php b/core/lib/Thelia/Core/Event/ProductSaleElement/ProductSaleElementEvent.php new file mode 100644 index 00000000..c9b0a039 --- /dev/null +++ b/core/lib/Thelia/Core/Event/ProductSaleElement/ProductSaleElementEvent.php @@ -0,0 +1,43 @@ +product_sale_element = $product_sale_element; + } + + public function hasProductSaleElement() + { + return ! \is_null($this->product_sale_element); + } + + public function getProductSaleElement() + { + return $this->product_sale_element; + } + + public function setProductSaleElement(ProductSaleElements $product_sale_element) + { + $this->product_sale_element = $product_sale_element; + + return $this; + } +} diff --git a/core/lib/Thelia/Core/Event/ProductSaleElement/ProductSaleElementUpdateEvent.php b/core/lib/Thelia/Core/Event/ProductSaleElement/ProductSaleElementUpdateEvent.php new file mode 100644 index 00000000..61afb5cf --- /dev/null +++ b/core/lib/Thelia/Core/Event/ProductSaleElement/ProductSaleElementUpdateEvent.php @@ -0,0 +1,340 @@ +setProduct($product); + + $this->setProductSaleElementId($product_sale_element_id); + } + + /** + * @return int + */ + public function getProductSaleElementId() + { + return $this->product_sale_element_id; + } + + /** + * @param int $product_sale_element_id + * @return $this + */ + public function setProductSaleElementId($product_sale_element_id) + { + $this->product_sale_element_id = $product_sale_element_id; + + return $this; + } + + /** + * @return float + */ + public function getPrice() + { + return $this->price; + } + + /** + * @param float $price + * @return $this + */ + public function setPrice($price) + { + $this->price = $price; + + return $this; + } + + /** + * @return int + */ + public function getCurrencyId() + { + return $this->currency_id; + } + + /** + * @param int $currency_id + * @return $this + */ + public function setCurrencyId($currency_id) + { + $this->currency_id = $currency_id; + + return $this; + } + + /** + * @return float + */ + public function getWeight() + { + return $this->weight; + } + + /** + * @param float $weight + * @return $this + */ + public function setWeight($weight) + { + $this->weight = $weight; + + return $this; + } + + /** + * @return float + */ + public function getQuantity() + { + return $this->quantity; + } + + /** + * @param float $quantity + * @return $this + */ + public function setQuantity($quantity) + { + $this->quantity = $quantity; + + return $this; + } + + /** + * @return float + */ + public function getSalePrice() + { + return $this->sale_price; + } + + /** + * @param float $sale_price + * @return $this + */ + public function setSalePrice($sale_price) + { + $this->sale_price = $sale_price; + + return $this; + } + + /** + * @return int + */ + public function getOnsale() + { + return $this->onsale; + } + + /** + * @param int $onsale + * @return $this + */ + public function setOnsale($onsale) + { + $this->onsale = $onsale; + + return $this; + } + + /** + * @return int + */ + public function getIsnew() + { + return $this->isnew; + } + + /** + * @param int $isnew + * @return $this + */ + public function setIsnew($isnew) + { + $this->isnew = $isnew; + + return $this; + } + + /** + * @return string + */ + public function getEanCode() + { + return $this->ean_code; + } + + /** + * @param string $ean_code + * @return $this + */ + public function setEanCode($ean_code) + { + $this->ean_code = $ean_code; + + return $this; + } + + /** + * @return bool + */ + public function getIsdefault() + { + return $this->isdefault; + } + + /** + * @param bool $isdefault + * @return $this + */ + public function setIsdefault($isdefault) + { + $this->isdefault = $isdefault; + + return $this; + } + + /** + * @return string + */ + public function getReference() + { + return $this->reference; + } + + /** + * @param string $reference + * @return $this + */ + public function setReference($reference) + { + $this->reference = $reference; + + return $this; + } + + /** + * @return Product + */ + public function getProduct() + { + return $this->product; + } + + /** + * @param Product $product + * @return $this + */ + public function setProduct($product) + { + $this->product = $product; + + return $this; + } + + /** + * @return int + */ + public function getTaxRuleId() + { + return $this->tax_rule_id; + } + + /** + * @param int $tax_rule_id + * @return $this + */ + public function setTaxRuleId($tax_rule_id) + { + $this->tax_rule_id = $tax_rule_id; + + return $this; + } + + /** + * @return int + */ + public function getFromDefaultCurrency() + { + return $this->from_default_currency; + } + + /** + * @param int $from_default_currency + * @return $this + */ + public function setFromDefaultCurrency($from_default_currency) + { + $this->from_default_currency = $from_default_currency; + + return $this; + } +} diff --git a/core/lib/Thelia/Core/Event/Profile/ProfileEvent.php b/core/lib/Thelia/Core/Event/Profile/ProfileEvent.php new file mode 100644 index 00000000..2ef33081 --- /dev/null +++ b/core/lib/Thelia/Core/Event/Profile/ProfileEvent.php @@ -0,0 +1,160 @@ +profile = $profile; + } + + public function hasProfile() + { + return ! \is_null($this->profile); + } + + public function getProfile() + { + return $this->profile; + } + + public function setProfile(Profile $profile) + { + $this->profile = $profile; + + return $this; + } + + public function setId($id) + { + $this->id = $id; + + return $this; + } + + public function getId() + { + return $this->id; + } + + public function setCode($code) + { + $this->code = $code; + + return $this; + } + + public function getCode() + { + return $this->code; + } + + public function setChapo($chapo) + { + $this->chapo = $chapo; + + return $this; + } + + public function getChapo() + { + return $this->chapo; + } + + public function setDescription($description) + { + $this->description = $description; + + return $this; + } + + public function getDescription() + { + return $this->description; + } + + public function setLocale($locale) + { + $this->locale = $locale; + + return $this; + } + + public function getLocale() + { + return $this->locale; + } + + public function setPostscriptum($postscriptum) + { + $this->postscriptum = $postscriptum; + + return $this; + } + + public function getPostscriptum() + { + return $this->postscriptum; + } + + public function setTitle($title) + { + $this->title = $title; + + return $this; + } + + public function getTitle() + { + return $this->title; + } + + public function setResourceAccess($resourceAccess) + { + $this->resourceAccess = $resourceAccess; + + return $this; + } + + public function getResourceAccess() + { + return $this->resourceAccess; + } + + public function setModuleAccess($moduleAccess) + { + $this->moduleAccess = $moduleAccess; + + return $this; + } + + public function getModuleAccess() + { + return $this->moduleAccess; + } +} diff --git a/core/lib/Thelia/Core/Event/Sale/ProductSaleStatusUpdateEvent.php b/core/lib/Thelia/Core/Event/Sale/ProductSaleStatusUpdateEvent.php new file mode 100644 index 00000000..a4ef8055 --- /dev/null +++ b/core/lib/Thelia/Core/Event/Sale/ProductSaleStatusUpdateEvent.php @@ -0,0 +1,22 @@ + + */ +class ProductSaleStatusUpdateEvent extends SaleEvent +{ +} diff --git a/core/lib/Thelia/Core/Event/Sale/SaleActiveStatusCheckEvent.php b/core/lib/Thelia/Core/Event/Sale/SaleActiveStatusCheckEvent.php new file mode 100644 index 00000000..280bf9f4 --- /dev/null +++ b/core/lib/Thelia/Core/Event/Sale/SaleActiveStatusCheckEvent.php @@ -0,0 +1,23 @@ + + */ +class SaleActiveStatusCheckEvent extends SaleEvent +{ +} diff --git a/core/lib/Thelia/Core/Event/Sale/SaleClearStatusEvent.php b/core/lib/Thelia/Core/Event/Sale/SaleClearStatusEvent.php new file mode 100644 index 00000000..42cea652 --- /dev/null +++ b/core/lib/Thelia/Core/Event/Sale/SaleClearStatusEvent.php @@ -0,0 +1,22 @@ + + */ +class SaleClearStatusEvent extends SaleEvent +{ +} diff --git a/core/lib/Thelia/Core/Event/Sale/SaleCreateEvent.php b/core/lib/Thelia/Core/Event/Sale/SaleCreateEvent.php new file mode 100644 index 00000000..61ff8d55 --- /dev/null +++ b/core/lib/Thelia/Core/Event/Sale/SaleCreateEvent.php @@ -0,0 +1,84 @@ + + */ +class SaleCreateEvent extends SaleEvent +{ + protected $title; + protected $saleLabel; + protected $locale; + + /** + * @param string $locale + * + * @return SaleCreateEvent $this + */ + public function setLocale($locale) + { + $this->locale = $locale; + + return $this; + } + + /** + * @return string + */ + public function getLocale() + { + return $this->locale; + } + + /** + * @param string $title + * + * @return $this + */ + public function setTitle($title) + { + $this->title = $title; + + return $this; + } + + /** + * @return string + */ + public function getTitle() + { + return $this->title; + } + + /** + * @param string $saleLabel + * @return $this + */ + public function setSaleLabel($saleLabel) + { + $this->saleLabel = $saleLabel; + + return $this; + } + + /** + * @return string + */ + public function getSaleLabel() + { + return $this->saleLabel; + } +} diff --git a/core/lib/Thelia/Core/Event/Sale/SaleDeleteEvent.php b/core/lib/Thelia/Core/Event/Sale/SaleDeleteEvent.php new file mode 100644 index 00000000..e197606e --- /dev/null +++ b/core/lib/Thelia/Core/Event/Sale/SaleDeleteEvent.php @@ -0,0 +1,52 @@ + + */ +class SaleDeleteEvent extends SaleEvent +{ + /** @var int */ + protected $saleId; + + /** + * @param int $saleId + */ + public function __construct($saleId) + { + $this->saleId = $saleId; + } + + /** + * @param int $saleId + * + * @return SaleDeleteEvent $this + */ + public function setSaleId($saleId) + { + $this->saleId = $saleId; + + return $this; + } + + /** + * @return int + */ + public function getSaleId() + { + return $this->saleId; + } +} diff --git a/core/lib/Thelia/Core/Event/Sale/SaleEvent.php b/core/lib/Thelia/Core/Event/Sale/SaleEvent.php new file mode 100644 index 00000000..31169259 --- /dev/null +++ b/core/lib/Thelia/Core/Event/Sale/SaleEvent.php @@ -0,0 +1,64 @@ + + * @deprecated since 2.4, please use \Thelia\Model\Event\SaleEvent + */ +class SaleEvent extends ActionEvent +{ + /** + * @var \Thelia\Model\Sale + */ + protected $sale; + + public function __construct(Sale $sale = null) + { + $this->sale = $sale; + } + + /** + * @param \Thelia\Model\Sale $sale + * @return SaleEvent + */ + public function setSale(Sale $sale) + { + $this->sale = $sale; + + return $this; + } + + /** + * @return \Thelia\Model\Sale + */ + public function getSale() + { + return $this->sale; + } + + /** + * check if sale exists + * + * @return bool + */ + public function hasSale() + { + return null !== $this->sale; + } +} diff --git a/core/lib/Thelia/Core/Event/Sale/SaleToggleActivityEvent.php b/core/lib/Thelia/Core/Event/Sale/SaleToggleActivityEvent.php new file mode 100644 index 00000000..4d9bd365 --- /dev/null +++ b/core/lib/Thelia/Core/Event/Sale/SaleToggleActivityEvent.php @@ -0,0 +1,22 @@ + + */ +class SaleToggleActivityEvent extends SaleEvent +{ +} diff --git a/core/lib/Thelia/Core/Event/Sale/SaleUpdateEvent.php b/core/lib/Thelia/Core/Event/Sale/SaleUpdateEvent.php new file mode 100644 index 00000000..a0ba2ad0 --- /dev/null +++ b/core/lib/Thelia/Core/Event/Sale/SaleUpdateEvent.php @@ -0,0 +1,276 @@ + + */ +class SaleUpdateEvent extends SaleCreateEvent +{ + protected $saleId; + + protected $chapo; + protected $description; + protected $postscriptum; + protected $active; + protected $startDate; + protected $endDate; + protected $priceOffsetType; + protected $displayInitialPrice; + protected $priceOffsets; + protected $products; + protected $productAttributes; + + /** + * @param int $saleId + */ + public function __construct($saleId) + { + $this->saleId = $saleId; + } + + /** + * @param int $saleId + * + * @return SaleUpdateEvent $this + */ + public function setSaleId($saleId) + { + $this->saleId = $saleId; + + return $this; + } + + /** + * @return int + */ + public function getSaleId() + { + return $this->saleId; + } + + /** + * @param string $chapo + * + * @return SaleUpdateEvent $this + */ + public function setChapo($chapo) + { + $this->chapo = $chapo; + + return $this; + } + + /** + * @return string + */ + public function getChapo() + { + return $this->chapo; + } + /** + * @param string $description + * + * @return SaleUpdateEvent $this + */ + public function setDescription($description) + { + $this->description = $description; + + return $this; + } + + /** + * @return string + */ + public function getDescription() + { + return $this->description; + } + + /** + * @param string $postscriptum + * + * @return SaleUpdateEvent $this + */ + public function setPostscriptum($postscriptum) + { + $this->postscriptum = $postscriptum; + + return $this; + } + + /** + * @return string + */ + public function getPostscriptum() + { + return $this->postscriptum; + } + + /** + * @param bool $active + * @return SaleUpdateEvent $this + */ + public function setActive($active) + { + $this->active = $active; + + return $this; + } + + /** + * @return bool + */ + public function getActive() + { + return $this->active; + } + + /** + * @param mixed $endDate string, integer (timestamp), or \DateTime value. + * @return SaleUpdateEvent $this + */ + public function setEndDate($endDate) + { + $this->endDate = PropelDateTime::newInstance($endDate, null, '\DateTime'); + + return $this; + } + + /** + * @return null|\DateTime + */ + public function getEndDate() + { + return $this->endDate; + } + + /** + * @param int $priceOffsetType + * @return SaleUpdateEvent $this + */ + public function setPriceOffsetType($priceOffsetType) + { + $this->priceOffsetType = $priceOffsetType; + + return $this; + } + + /** + * @return int + */ + public function getPriceOffsetType() + { + return $this->priceOffsetType; + } + + /** + * @param mixed $startDate string, integer (timestamp), or \DateTime value. + * @return SaleUpdateEvent $this + */ + public function setStartDate($startDate) + { + $this->startDate = PropelDateTime::newInstance($startDate, null, '\DateTime'); + + return $this; + } + + /** + * @return null|\DateTime + */ + public function getStartDate() + { + return $this->startDate; + } + + /** + * @param bool $displayInitialPrice + * @return $this + */ + public function setDisplayInitialPrice($displayInitialPrice) + { + $this->displayInitialPrice = $displayInitialPrice; + + return $this; + } + + /** + * @return bool + */ + public function getDisplayInitialPrice() + { + return $this->displayInitialPrice; + } + + /** + * @param array $priceOffsets an array of (currency_id => price offset) couples. + * @return $this + */ + public function setPriceOffsets($priceOffsets) + { + $this->priceOffsets = $priceOffsets; + + return $this; + } + + /** + * @return array + */ + public function getPriceOffsets() + { + return $this->priceOffsets; + } + + /** + * @param array $products an array of product ID + * @return $this + */ + public function setProducts($products) + { + $this->products = $products; + + return $this; + } + + /** + * @return array + */ + public function getProducts() + { + return $this->products; + } + + /** + * @param array $productAttributes an array of (product_id => array of attribute IDs) + * @return $this + */ + public function setProductAttributes($productAttributes) + { + $this->productAttributes = $productAttributes; + + return $this; + } + + /** + * @return array $productAttributes an array of (product_id => array of attribute IDs) + */ + public function getProductAttributes() + { + return $this->productAttributes; + } +} diff --git a/core/lib/Thelia/Core/Event/SessionEvent.php b/core/lib/Thelia/Core/Event/SessionEvent.php new file mode 100644 index 00000000..64d25cf7 --- /dev/null +++ b/core/lib/Thelia/Core/Event/SessionEvent.php @@ -0,0 +1,84 @@ + + */ +class SessionEvent extends ActionEvent +{ + protected $cacheDir; + + protected $env; + + protected $debug; + + protected $session; + + /** + * @param string $cacheDir the cache directory for the current request + * @param boolean $debug debug for the current request + * @param string $env environment for the current request + */ + public function __construct($cacheDir, $debug, $env) + { + $this->cacheDir = $cacheDir; + $this->debug = $debug; + $this->env = $env; + } + + /** + * @return string the current environment + */ + public function getEnv() + { + return $this->env; + } + + /** + * @return bool the current debug mode + */ + public function getDebug() + { + return $this->debug; + } + + /** + * @return string + */ + public function getCacheDir() + { + return $this->cacheDir; + } + + /** + * @param mixed $session + */ + public function setSession(SessionInterface $session) + { + $this->session = $session; + } + + /** + * @return mixed + */ + public function getSession() + { + return $this->session; + } +} diff --git a/core/lib/Thelia/Core/Event/ShippingZone/ShippingZoneAddAreaEvent.php b/core/lib/Thelia/Core/Event/ShippingZone/ShippingZoneAddAreaEvent.php new file mode 100644 index 00000000..085c15e1 --- /dev/null +++ b/core/lib/Thelia/Core/Event/ShippingZone/ShippingZoneAddAreaEvent.php @@ -0,0 +1,72 @@ + + */ +class ShippingZoneAddAreaEvent extends ActionEvent +{ + protected $area_id; + protected $shipping_zone_id; + + public function __construct($area_id, $shipping_zone_id) + { + $this->area_id = $area_id; + $this->shipping_zone_id = $shipping_zone_id; + } + + /** + * @param mixed $area_id + * + * @return $this + */ + public function setAreaId($area_id) + { + $this->area_id = $area_id; + + return $this; + } + + /** + * @return mixed + */ + public function getAreaId() + { + return $this->area_id; + } + + /** + * @param mixed $shipping_zone_id + * + * @return $this + */ + public function setShippingZoneId($shipping_zone_id) + { + $this->shipping_zone_id = $shipping_zone_id; + + return $this; + } + + /** + * @return mixed + */ + public function getShippingZoneId() + { + return $this->shipping_zone_id; + } +} diff --git a/core/lib/Thelia/Core/Event/ShippingZone/ShippingZoneRemoveAreaEvent.php b/core/lib/Thelia/Core/Event/ShippingZone/ShippingZoneRemoveAreaEvent.php new file mode 100644 index 00000000..637c0d24 --- /dev/null +++ b/core/lib/Thelia/Core/Event/ShippingZone/ShippingZoneRemoveAreaEvent.php @@ -0,0 +1,22 @@ + + */ +class ShippingZoneRemoveAreaEvent extends ShippingZoneAddAreaEvent +{ +} diff --git a/core/lib/Thelia/Core/Event/State/StateCreateEvent.php b/core/lib/Thelia/Core/Event/State/StateCreateEvent.php new file mode 100644 index 00000000..f536ceed --- /dev/null +++ b/core/lib/Thelia/Core/Event/State/StateCreateEvent.php @@ -0,0 +1,119 @@ + + */ +class StateCreateEvent extends StateEvent +{ + protected $locale; + protected $title; + protected $isocode; + + /** @var bool is visible */ + protected $visible; + + /** @var int */ + protected $country; + + /** + * @param mixed $isocode + */ + public function setIsocode($isocode) + { + $this->isocode = $isocode; + + return $this; + } + + /** + * @return mixed + */ + public function getIsocode() + { + return $this->isocode; + } + + /** + * @param mixed $locale + */ + public function setLocale($locale) + { + $this->locale = $locale; + + return $this; + } + + /** + * @return mixed + */ + public function getLocale() + { + return $this->locale; + } + + /** + * @param mixed $title + */ + public function setTitle($title) + { + $this->title = $title; + + return $this; + } + + /** + * @return mixed + */ + public function getTitle() + { + return $this->title; + } + + /** + * @return boolean + */ + public function isVisible() + { + return $this->visible; + } + + /** + * @param boolean $visible + */ + public function setVisible($visible) + { + $this->visible = $visible; + return $this; + } + + /** + * @return int + */ + public function getCountry() + { + return $this->country; + } + + /** + * @param int $country + */ + public function setCountry($country) + { + $this->country = $country; + return $this; + } +} diff --git a/core/lib/Thelia/Core/Event/State/StateDeleteEvent.php b/core/lib/Thelia/Core/Event/State/StateDeleteEvent.php new file mode 100644 index 00000000..60f0726f --- /dev/null +++ b/core/lib/Thelia/Core/Event/State/StateDeleteEvent.php @@ -0,0 +1,50 @@ + + */ +class StateDeleteEvent extends StateEvent +{ + /** + * @var int state id + */ + protected $state_id; + + /** + * @param int $state_id + */ + public function __construct($state_id) + { + $this->state_id = $state_id; + } + + /** + * @param int $state_id + */ + public function setStateId($state_id) + { + $this->state_id = $state_id; + } + + /** + * @return int + */ + public function getStateId() + { + return $this->state_id; + } +} diff --git a/core/lib/Thelia/Core/Event/State/StateEvent.php b/core/lib/Thelia/Core/Event/State/StateEvent.php new file mode 100644 index 00000000..7ce6265c --- /dev/null +++ b/core/lib/Thelia/Core/Event/State/StateEvent.php @@ -0,0 +1,61 @@ + + * @deprecated since 2.4, please use \Thelia\Model\Event\StateEvent + */ +class StateEvent extends ActionEvent +{ + /* + * @var \Thelia\Model\State + */ + protected $state; + + public function __construct(State $state = null) + { + $this->state = $state; + } + + /** + * @param mixed $state + */ + public function setState(State $state) + { + $this->state = $state; + + return $this; + } + + /** + * @return null|\Thelia\Model\State + */ + public function getState() + { + return $this->state; + } + + /** + * @return bool + */ + public function hasState() + { + return null !== $this->state; + } +} diff --git a/core/lib/Thelia/Core/Event/State/StateToggleVisibilityEvent.php b/core/lib/Thelia/Core/Event/State/StateToggleVisibilityEvent.php new file mode 100644 index 00000000..14547786 --- /dev/null +++ b/core/lib/Thelia/Core/Event/State/StateToggleVisibilityEvent.php @@ -0,0 +1,23 @@ + + */ +class StateToggleVisibilityEvent extends StateEvent +{ +} diff --git a/core/lib/Thelia/Core/Event/State/StateUpdateEvent.php b/core/lib/Thelia/Core/Event/State/StateUpdateEvent.php new file mode 100644 index 00000000..92ff7f1f --- /dev/null +++ b/core/lib/Thelia/Core/Event/State/StateUpdateEvent.php @@ -0,0 +1,51 @@ + + */ +class StateUpdateEvent extends StateCreateEvent +{ + /** @var int */ + protected $state_id; + + /** + * @param int $state_id + */ + public function __construct($state_id) + { + $this->state_id = $state_id; + } + + /** + * @param int $state_id + * @return $this + */ + public function setStateId($state_id) + { + $this->state_id = $state_id; + + return $this; + } + + /** + * @return int + */ + public function getStateId() + { + return $this->state_id; + } +} diff --git a/core/lib/Thelia/Core/Event/Tax/TaxEvent.php b/core/lib/Thelia/Core/Event/Tax/TaxEvent.php new file mode 100644 index 00000000..41fbcc88 --- /dev/null +++ b/core/lib/Thelia/Core/Event/Tax/TaxEvent.php @@ -0,0 +1,122 @@ +tax = $tax; + } + + public function hasTax() + { + return ! \is_null($this->tax); + } + + public function getTax() + { + return $this->tax; + } + + public function setTax(Tax $tax) + { + $this->tax = $tax; + + return $this; + } + + public function setDescription($description) + { + $this->description = $description; + + return $this; + } + + public function getDescription() + { + return $this->description; + } + + public function setId($id) + { + $this->id = $id; + + return $this; + } + + public function getId() + { + return $this->id; + } + + public function setTitle($title) + { + $this->title = $title; + + return $this; + } + + public function getTitle() + { + return $this->title; + } + + public function setLocale($locale) + { + $this->locale = $locale; + + return $this; + } + + public function getLocale() + { + return $this->locale; + } + + public function setType($type) + { + $this->type = $type; + + return $this; + } + + public function getType() + { + return $this->type; + } + + public function setRequirements($requirements) + { + $this->requirements = $requirements; + + return $this; + } + + public function getRequirements() + { + return $this->requirements; + } +} diff --git a/core/lib/Thelia/Core/Event/Tax/TaxRuleEvent.php b/core/lib/Thelia/Core/Event/Tax/TaxRuleEvent.php new file mode 100644 index 00000000..3507b0fa --- /dev/null +++ b/core/lib/Thelia/Core/Event/Tax/TaxRuleEvent.php @@ -0,0 +1,134 @@ +taxRule = $taxRule; + } + + public function hasTaxRule() + { + return ! \is_null($this->taxRule); + } + + public function getTaxRule() + { + return $this->taxRule; + } + + public function setTaxRule(TaxRule $taxRule) + { + $this->taxRule = $taxRule; + + return $this; + } + + public function setDescription($description) + { + $this->description = $description; + + return $this; + } + + public function getDescription() + { + return $this->description; + } + + public function setId($id) + { + $this->id = $id; + + return $this; + } + + public function getId() + { + return $this->id; + } + + public function setTitle($title) + { + $this->title = $title; + + return $this; + } + + public function getTitle() + { + return $this->title; + } + + public function setLocale($locale) + { + $this->locale = $locale; + + return $this; + } + + public function getLocale() + { + return $this->locale; + } + + public function setCountryList($countryList) + { + $this->countryList = $countryList; + + return $this; + } + + public function getCountryList() + { + return $this->countryList; + } + + public function getCountryDeletedList() + { + return $this->countryDeletedList; + } + + public function setCountryDeletedList($countryDeletedList) + { + $this->countryDeletedList = $countryDeletedList; + return $this; + } + + public function setTaxList($taxList) + { + $this->taxList = $taxList; + + return $this; + } + + public function getTaxList() + { + return $this->taxList; + } +} diff --git a/core/lib/Thelia/Core/Event/Template/TemplateAddAttributeEvent.php b/core/lib/Thelia/Core/Event/Template/TemplateAddAttributeEvent.php new file mode 100644 index 00000000..faa6d20d --- /dev/null +++ b/core/lib/Thelia/Core/Event/Template/TemplateAddAttributeEvent.php @@ -0,0 +1,39 @@ +attribute_id = $attribute_id; + } + + public function getAttributeId() + { + return $this->attribute_id; + } + + public function setAttributeId($attribute_id) + { + $this->attribute_id = $attribute_id; + + return $this; + } +} diff --git a/core/lib/Thelia/Core/Event/Template/TemplateAddFeatureEvent.php b/core/lib/Thelia/Core/Event/Template/TemplateAddFeatureEvent.php new file mode 100644 index 00000000..e359d4e0 --- /dev/null +++ b/core/lib/Thelia/Core/Event/Template/TemplateAddFeatureEvent.php @@ -0,0 +1,39 @@ +feature_id = $feature_id; + } + + public function getFeatureId() + { + return $this->feature_id; + } + + public function setFeatureId($feature_id) + { + $this->feature_id = $feature_id; + + return $this; + } +} diff --git a/core/lib/Thelia/Core/Event/Template/TemplateCreateEvent.php b/core/lib/Thelia/Core/Event/Template/TemplateCreateEvent.php new file mode 100644 index 00000000..8ff1bfab --- /dev/null +++ b/core/lib/Thelia/Core/Event/Template/TemplateCreateEvent.php @@ -0,0 +1,43 @@ +locale; + } + + public function setLocale($locale) + { + $this->locale = $locale; + + return $this; + } + + public function getTemplateName() + { + return $this->template_name; + } + + public function setTemplateName($template_name) + { + $this->template_name = $template_name; + + return $this; + } +} diff --git a/core/lib/Thelia/Core/Event/Template/TemplateDeleteAttributeEvent.php b/core/lib/Thelia/Core/Event/Template/TemplateDeleteAttributeEvent.php new file mode 100644 index 00000000..279d569e --- /dev/null +++ b/core/lib/Thelia/Core/Event/Template/TemplateDeleteAttributeEvent.php @@ -0,0 +1,39 @@ +attribute_id = $attribute_id; + } + + public function getAttributeId() + { + return $this->attribute_id; + } + + public function setAttributeId($attribute_id) + { + $this->attribute_id = $attribute_id; + + return $this; + } +} diff --git a/core/lib/Thelia/Core/Event/Template/TemplateDeleteEvent.php b/core/lib/Thelia/Core/Event/Template/TemplateDeleteEvent.php new file mode 100644 index 00000000..6a661e26 --- /dev/null +++ b/core/lib/Thelia/Core/Event/Template/TemplateDeleteEvent.php @@ -0,0 +1,53 @@ +setTemplateId($template_id); + } + + public function getTemplateId() + { + return $this->template_id; + } + + public function setTemplateId($template_id) + { + $this->template_id = $template_id; + + return $this; + } + + public function getProductCount() + { + return $this->product_count; + } + + public function setProductCount($product_count) + { + $this->product_count = $product_count; + + return $this; + } +} diff --git a/core/lib/Thelia/Core/Event/Template/TemplateDeleteFeatureEvent.php b/core/lib/Thelia/Core/Event/Template/TemplateDeleteFeatureEvent.php new file mode 100644 index 00000000..a760026a --- /dev/null +++ b/core/lib/Thelia/Core/Event/Template/TemplateDeleteFeatureEvent.php @@ -0,0 +1,39 @@ +feature_id = $feature_id; + } + + public function getFeatureId() + { + return $this->feature_id; + } + + public function setFeatureId($feature_id) + { + $this->feature_id = $feature_id; + + return $this; + } +} diff --git a/core/lib/Thelia/Core/Event/Template/TemplateDuplicateEvent.php b/core/lib/Thelia/Core/Event/Template/TemplateDuplicateEvent.php new file mode 100644 index 00000000..b3e0348c --- /dev/null +++ b/core/lib/Thelia/Core/Event/Template/TemplateDuplicateEvent.php @@ -0,0 +1,50 @@ +sourceTemplateId = $sourceTemplateId; + $this->locale = $locale; + } + + /** + * @return int + */ + public function getSourceTemplateId() + { + return $this->sourceTemplateId; + } + + /** + * @return string + */ + public function getLocale() + { + return $this->locale; + } +} diff --git a/core/lib/Thelia/Core/Event/Template/TemplateEvent.php b/core/lib/Thelia/Core/Event/Template/TemplateEvent.php new file mode 100644 index 00000000..46f3da7b --- /dev/null +++ b/core/lib/Thelia/Core/Event/Template/TemplateEvent.php @@ -0,0 +1,59 @@ +template = $template; + } + + /** + * @return bool + */ + public function hasTemplate() + { + return ! \is_null($this->template); + } + + /** + * @return Template + */ + public function getTemplate() + { + return $this->template; + } + + /** + * @param Template $template + * @return $this + */ + public function setTemplate($template) + { + $this->template = $template; + + return $this; + } +} diff --git a/core/lib/Thelia/Core/Event/Template/TemplateUpdateEvent.php b/core/lib/Thelia/Core/Event/Template/TemplateUpdateEvent.php new file mode 100644 index 00000000..a174253c --- /dev/null +++ b/core/lib/Thelia/Core/Event/Template/TemplateUpdateEvent.php @@ -0,0 +1,62 @@ +setTemplateId($template_id); + } + + public function getTemplateId() + { + return $this->template_id; + } + + public function setTemplateId($template_id) + { + $this->template_id = $template_id; + + return $this; + } + + public function getFeatureList() + { + return $this->feature_list; + } + + public function setFeatureList($feature_list) + { + $this->feature_list = $feature_list; + + return $this; + } + + public function getAttributeList() + { + return $this->attribute_list; + } + + public function setAttributeList($attribute_list) + { + $this->attribute_list = $attribute_list; + + return $this; + } +} diff --git a/core/lib/Thelia/Core/Event/TheliaEvents.php b/core/lib/Thelia/Core/Event/TheliaEvents.php new file mode 100644 index 00000000..c1ce4c01 --- /dev/null +++ b/core/lib/Thelia/Core/Event/TheliaEvents.php @@ -0,0 +1,1187 @@ + + */ + +final class TheliaEvents +{ + // -- CORE EVENTS --------------------------------------------------------- + /** + * sent at the beginning + */ + const BOOT = "thelia.boot"; + /** + * Kernel View Check Handle + */ + const VIEW_CHECK = "thelia.view_check"; + // -- END CORE EVENTS --------------------------------------------------------- + // -- ADDRESS EVENTS --------------------------------------------------------- + + /** + * sent for address creation + */ + const ADDRESS_CREATE = "action.createAddress"; + const ADDRESS_UPDATE = "action.updateAddress"; + const ADDRESS_DELETE = "action.deleteAddress"; + + /** + * sent when an address is tag as default + */ + const ADDRESS_DEFAULT = "action.defaultAddress"; + + /** @deprecated since 2.4, \Thelia\Model\Event\AddressEvent::PRE_INSERT */ + const BEFORE_CREATEADDRESS = "action.before_createAddress"; + /** @deprecated since 2.4, \Thelia\Model\Event\AddressEvent::POST_INSERT */ + const AFTER_CREATEADDRESS = "action.after_createAddress"; + + /** @deprecated since 2.4, \Thelia\Model\Event\AddressEvent::PRE_DELETE */ + const BEFORE_DELETEADDRESS = "action.before_deleteAddress"; + /** @deprecated since 2.4, \Thelia\Model\Event\AddressEvent::POST_DELETE */ + const AFTER_DELETEADDRESS = "action.after_deleteAddress"; + + /** @deprecated since 2.4, \Thelia\Model\Event\AddressEvent::PRE_UPDATE */ + const BEFORE_UPDATEADDRESS = "action.before_updateAddress"; + /** @deprecated since 2.4, \Thelia\Model\Event\AddressEvent::POST_UPDATE */ + const AFTER_UPDATEADDRESS = "action.after_updateAddress"; + + // -- END ADDRESS EVENTS --------------------------------------------------------- + + + // -- ADMIN EVENTS --------------------------------------------------------- + /** + * Sent before the logout of the administrator. + */ + const ADMIN_LOGOUT = "action.admin_logout"; + /** + * Sent once the administrator is successfully logged in. + */ + const ADMIN_LOGIN = "action.admin_login"; + + const ADMIN_PASSWORD_RENEW = "action.admin_renew_password"; + + // -- END ADMIN EVENTS -------------------------------------------------------- + + + // -- AREA EVENTS --------------------------------------------------------- + + const AREA_CREATE = 'action.createArea'; + const AREA_UPDATE = 'action.updateArea'; + const AREA_DELETE = 'action.deleteArea'; + + const AREA_REMOVE_COUNTRY = 'action.area.removeCountry'; + const AREA_POSTAGE_UPDATE = 'action.area.postageUpdate'; + const AREA_ADD_COUNTRY = 'action.area.addCountry'; + + /** @deprecated since 2.4, \Thelia\Model\Event\AreaEvent::PRE_INSERT */ + const BEFORE_CREATEAREA = "action.before_createArea"; + /** @deprecated since 2.4, \Thelia\Model\Event\AreaEvent::POST_INSERT */ + const AFTER_CREATEAREA = "action.after_createArea"; + + /** @deprecated since 2.4, \Thelia\Model\Event\AreaEvent::PRE_DELETE */ + const BEFORE_DELETEAREA = "action.before_deleteArea"; + /** @deprecated since 2.4, \Thelia\Model\Event\AreaEvent::POST_DELETE */ + const AFTER_DELETEAREA = "action.after_deleteArea"; + + /** @deprecated since 2.4, \Thelia\Model\Event\AreaEvent::PRE_UPDATE */ + const BEFORE_UPDATEAREA = "action.before_updateArea"; + /** @deprecated since 2.4, \Thelia\Model\Event\AreaEvent::POST_UPDATE */ + const AFTER_UPDATEAREA = "action.after_updateArea"; + + // -- END AREA EVENTS --------------------------------------------------------- + + + // -- CATEGORIES EVENTS ----------------------------------------------- + + const CATEGORY_CREATE = "action.createCategory"; + const CATEGORY_UPDATE = "action.updateCategory"; + const CATEGORY_DELETE = "action.deleteCategory"; + + /** @deprecated since 2.4, \Thelia\Model\Event\CategoryEvent::PRE_INSERT */ + const BEFORE_CREATECATEGORY = "action.before_createCategory"; + /** @deprecated since 2.4, \Thelia\Model\Event\CategoryEvent::POST_INSERT */ + const AFTER_CREATECATEGORY = "action.after_createCategory"; + + /** @deprecated since 2.4, \Thelia\Model\Event\CategoryEvent::PRE_DELETE */ + const BEFORE_DELETECATEGORY = "action.before_deleteCategory"; + /** @deprecated since 2.4, \Thelia\Model\Event\CategoryEvent::POST_DELETE */ + const AFTER_DELETECATEGORY = "action.after_deleteCategory"; + + /** @deprecated since 2.4, \Thelia\Model\Event\CategoryEvent::PRE_UPDATE */ + const BEFORE_UPDATECATEGORY = "action.before_updateCategory"; + /** @deprecated since 2.4, \Thelia\Model\Event\CategoryEvent::POST_UPDATE */ + const AFTER_UPDATECATEGORY = "action.after_updateCategory"; + + const CATEGORY_TOGGLE_VISIBILITY = "action.toggleCategoryVisibility"; + const CATEGORY_UPDATE_POSITION = "action.updateCategoryPosition"; + + const CATEGORY_ADD_CONTENT = "action.categoryAddContent"; + const CATEGORY_REMOVE_CONTENT = "action.categoryRemoveContent"; + + const CATEGORY_UPDATE_SEO = "action.updateCategorySeo"; + + const VIEW_CATEGORY_ID_NOT_VISIBLE = "action.viewCategoryIdNotVisible"; + // -- END CATEGORIES EVENTS ----------------------------------------------- + + + // -- CONTENT EVENTS ----------------------------------------------- + + const CONTENT_CREATE = "action.createContent"; + const CONTENT_UPDATE = "action.updateContent"; + const CONTENT_DELETE = "action.deleteContent"; + + /** @deprecated since 2.4, \Thelia\Model\Event\ContentEvent::PRE_INSERT */ + const BEFORE_CREATECONTENT = "action.before_createContent"; + /** @deprecated since 2.4, \Thelia\Model\Event\ContentEvent::POST_INSERT */ + const AFTER_CREATECONTENT = "action.after_createContent"; + + /** @deprecated since 2.4, \Thelia\Model\Event\ContentEvent::PRE_DELETE */ + const BEFORE_DELETECONTENT = "action.before_deleteContent"; + /** @deprecated since 2.4, \Thelia\Model\Event\ContentEvent::POST_DELETE */ + const AFTER_DELETECONTENT = "action.after_deleteContent"; + + /** @deprecated since 2.4, \Thelia\Model\Event\ContentEvent::PRE_UPDATE */ + const BEFORE_UPDATECONTENT = "action.before_updateContent"; + /** @deprecated since 2.4, \Thelia\Model\Event\ContentEvent::POST_UPDATE */ + const AFTER_UPDATECONTENT = "action.after_updateContent"; + + const CONTENT_TOGGLE_VISIBILITY = "action.toggleContentVisibility"; + const CONTENT_UPDATE_POSITION = "action.updateContentPosition"; + const CONTENT_UPDATE_SEO = "action.updateContentSeo"; + + const CONTENT_ADD_FOLDER = "action.contentAddFolder"; + const CONTENT_REMOVE_FOLDER = "action.contentRemoveFolder"; + + const VIEW_CONTENT_ID_NOT_VISIBLE = "action.viewContentIdNotVisible"; + // -- END CONTENT EVENTS --------------------------------------------------------- + + + // -- COUNTRY EVENTS ----------------------------------------------- + + const COUNTRY_CREATE = "action.state.create"; + const COUNTRY_UPDATE = "action.state.update"; + const COUNTRY_DELETE = "action.state.delete"; + + /** @deprecated since 2.4, \Thelia\Model\Event\CountryEvent::PRE_INSERT */ + const BEFORE_CREATECOUNTRY = "action.before_createCountry"; + /** @deprecated since 2.4, \Thelia\Model\Event\CountryEvent::POST_INSERT */ + const AFTER_CREATECOUNTRY = "action.after_createCountry"; + + /** @deprecated since 2.4, \Thelia\Model\Event\CountryEvent::PRE_DELETE */ + const BEFORE_DELETECOUNTRY = "action.before_deleteCountry"; + /** @deprecated since 2.4, \Thelia\Model\Event\CountryEvent::POST_DELETE */ + const AFTER_DELETECOUNTRY = "action.after_deleteCountry"; + + /** @deprecated since 2.4, \Thelia\Model\Event\CountryEvent::PRE_UPDATE */ + const BEFORE_UPDATECOUNTRY = "action.before_updateCountry"; + /** @deprecated since 2.4, \Thelia\Model\Event\CountryEvent::POST_UPDATE */ + const AFTER_UPDATECOUNTRY = "action.after_updateCountry"; + + const COUNTRY_TOGGLE_DEFAULT = "action.toggleCountryDefault"; + const COUNTRY_TOGGLE_VISIBILITY = "action.state.toggleVisibility"; + // -- END COUNTRY EVENTS --------------------------------------------------------- + + + // -- STATE EVENTS ----------------------------------------------- + + const STATE_CREATE = "action.createState"; + const STATE_UPDATE = "action.updateState"; + const STATE_DELETE = "action.deleteState"; + + /** @deprecated since 2.4, \Thelia\Model\Event\CountryEvent::PRE_INSERT */ + const BEFORE_CREATESTATE = "action.before_createCountry"; + /** @deprecated since 2.4, \Thelia\Model\Event\CountryEvent::POST_INSERT */ + const AFTER_CREATESTATE = "action.after_createCountry"; + + /** @deprecated since 2.4, \Thelia\Model\Event\CountryEvent::PRE_DELETE */ + const BEFORE_DELETESTATE = "action.before_deleteCountry"; + /** @deprecated since 2.4, \Thelia\Model\Event\CountryEvent::POST_DELETE */ + const AFTER_DELETESTATE = "action.after_deleteCountry"; + + /** @deprecated since 2.4, \Thelia\Model\Event\CountryEvent::PRE_UPDATE */ + const BEFORE_UPDATESTATE = "action.before_updateCountry"; + /** @deprecated since 2.4, \Thelia\Model\Event\CountryEvent::POST_UPDATE */ + const AFTER_UPDATESTATE = "action.after_updateCountry"; + + const STATE_TOGGLE_VISIBILITY = "action.toggleCountryVisibility"; + // -- END STATE EVENTS --------------------------------------------------------- + + + + + // -- CUSTOMER EVENTS --------------------------------------------------------- + /** + * Sent before the logout of the customer. + */ + const CUSTOMER_LOGOUT = "action.customer_logout"; + /** + * Sent once the customer is successfully logged in. + */ + const CUSTOMER_LOGIN = "action.customer_login"; + /** + * sent on customer account creation + */ + const CUSTOMER_CREATEACCOUNT = "action.createCustomer"; + /** + * sent on customer account update + */ + const CUSTOMER_UPDATEACCOUNT = "action.updateCustomer"; + /** + * sent on customer account update profile + */ + const CUSTOMER_UPDATEPROFILE = "action.updateProfileCustomer"; + /** + * sent on customer removal + */ + const CUSTOMER_DELETEACCOUNT = "action.deleteCustomer"; + /** + * sent on customer address removal + */ + const CUSTOMER_ADDRESS_DELETE = "action.customer.deleteAddress"; + /** + * sent when a customer need a new password + */ + const LOST_PASSWORD = "action.lostPassword"; + + /** @deprecated since 2.4, \Thelia\Model\Event\CustomerEvent::PRE_INSERT */ + const BEFORE_CREATECUSTOMER = "action.before_createCustomer"; + /** @deprecated since 2.4, \Thelia\Model\Event\CustomerEvent::POST_INSERT */ + const AFTER_CREATECUSTOMER = "action.after_createCustomer"; + + /** @deprecated since 2.4, \Thelia\Model\Event\CustomerEvent::PRE_DELETE */ + const BEFORE_DELETECUSTOMER = "action.before_deleteCustomer"; + /** @deprecated since 2.4, \Thelia\Model\Event\CustomerEvent::POST_DELETE */ + const AFTER_DELETECUSTOMER = "action.after_deleteCustomer"; + + /** @deprecated since 2.4, \Thelia\Model\Event\CustomerEvent::PRE_UPDATE */ + const BEFORE_UPDATECUSTOMER = "action.before_updateCustomer"; + /** @deprecated since 2.4, \Thelia\Model\Event\CustomerEvent::POST_UPDATE */ + const AFTER_UPDATECUSTOMER = "action.after_updateCustomer"; + + /** + * Send the account ccreation confirmation email + */ + const SEND_ACCOUNT_CONFIRMATION_EMAIL = "action.customer.sendAccountConfirmationEmail"; + + // -- END CUSTOMER EVENTS --------------------------------------------------------- + + + // -- FOLDER EVENTS ----------------------------------------------- + + + const FOLDER_CREATE = "action.createFolder"; + const FOLDER_UPDATE = "action.updateFolder"; + const FOLDER_DELETE = "action.deleteFolder"; + + /** @deprecated since 2.4, \Thelia\Model\Event\FolderEvent::PRE_INSERT */ + const BEFORE_CREATEFOLDER = "action.before_createFolder"; + /** @deprecated since 2.4, \Thelia\Model\Event\FolderEvent::POST_INSERT */ + const AFTER_CREATEFOLDER = "action.after_createFolder"; + + /** @deprecated since 2.4, \Thelia\Model\Event\FolderEvent::PRE_DELETE */ + const BEFORE_DELETEFOLDER = "action.before_deleteFolder"; + /** @deprecated since 2.4, \Thelia\Model\Event\FolderEvent::POST_DELETE */ + const AFTER_DELETEFOLDER = "action.after_deleteFolder"; + + /** @deprecated since 2.4, \Thelia\Model\Event\FolderEvent::PRE_UPDATE */ + const BEFORE_UPDATEFOLDER = "action.before_updateFolder"; + /** @deprecated since 2.4, \Thelia\Model\Event\FolderEvent::POST_UPDATE */ + const AFTER_UPDATEFOLDER = "action.after_updateFolder"; + + const FOLDER_TOGGLE_VISIBILITY = "action.toggleFolderVisibility"; + const FOLDER_UPDATE_POSITION = "action.updateFolderPosition"; + const FOLDER_UPDATE_SEO = "action.updateFolderSeo"; + + const VIEW_FOLDER_ID_NOT_VISIBLE = "action.viewFolderIdNotVisible"; + // -- END FOLDER EVENTS --------------------------------------------------------- + + + // -- PRODUCT EVENTS ----------------------------------------------- + + const PRODUCT_CREATE = "action.createProduct"; + const PRODUCT_UPDATE = "action.updateProduct"; + const PRODUCT_DELETE = "action.deleteProduct"; + + /** @deprecated since 2.4, \Thelia\Model\Event\ProductEvent::PRE_INSERT */ + const BEFORE_CREATEPRODUCT = "action.before_createproduct"; + /** @deprecated since 2.4, \Thelia\Model\Event\ProductEvent::POST_INSERT */ + const AFTER_CREATEPRODUCT = "action.after_createproduct"; + + /** @deprecated since 2.4, \Thelia\Model\Event\ProductEvent::PRE_DELETE */ + const BEFORE_DELETEPRODUCT = "action.before_deleteProduct"; + /** @deprecated since 2.4, \Thelia\Model\Event\ProductEvent::POST_DELETE */ + const AFTER_DELETEPRODUCT = "action.after_deleteProduct"; + + /** @deprecated since 2.4, \Thelia\Model\Event\ProductEvent::PRE_UPDATE */ + const BEFORE_UPDATEPRODUCT = "action.before_deleteproduct"; + /** @deprecated since 2.4, \Thelia\Model\Event\ProductEvent::POST_UPDATE */ + const AFTER_UPDATEPRODUCT = "action.after_deleteproduct"; + + const PRODUCT_TOGGLE_VISIBILITY = "action.toggleProductVisibility"; + const PRODUCT_UPDATE_POSITION = "action.updateProductPosition"; + const PRODUCT_UPDATE_SEO = "action.updateProductSeo"; + + const PRODUCT_ADD_CONTENT = "action.productAddContent"; + const PRODUCT_REMOVE_CONTENT = "action.productRemoveContent"; + const PRODUCT_UPDATE_CONTENT_POSITION = "action.updateProductContentPosition"; + + const PRODUCT_ADD_PRODUCT_SALE_ELEMENT = "action.addProductSaleElement"; + const PRODUCT_DELETE_PRODUCT_SALE_ELEMENT = "action.deleteProductSaleElement"; + const PRODUCT_UPDATE_PRODUCT_SALE_ELEMENT = "action.updateProductSaleElement"; + + const PRODUCT_COMBINATION_GENERATION = "action.productCombinationGeneration"; + + const PRODUCT_SET_TEMPLATE = "action.productSetTemplate"; + + const PRODUCT_ADD_ACCESSORY = "action.productAddProductAccessory"; + const PRODUCT_REMOVE_ACCESSORY = "action.productRemoveProductAccessory"; + const PRODUCT_UPDATE_ACCESSORY_POSITION = "action.updateProductAccessoryPosition"; + + const PRODUCT_FEATURE_UPDATE_VALUE = "action.updateProductFeatureValue"; + const PRODUCT_FEATURE_DELETE_VALUE = "action.deleteProductFeatureValue"; + + const PRODUCT_ADD_CATEGORY = "action.addProductCategory"; + const PRODUCT_REMOVE_CATEGORY = "action.deleteProductCategory"; + + const VIRTUAL_PRODUCT_ORDER_HANDLE = "action.virtualProduct.handleOrder"; + const VIRTUAL_PRODUCT_ORDER_DOWNLOAD_RESPONSE = "action.virtualProduct.downloadResponse"; + + const VIEW_PRODUCT_ID_NOT_VISIBLE = "action.viewProductIdNotVisible"; + // -- END PRODUCT EVENTS --------------------------------------------------------- + + + // -- CLONE EVENTS ------------------------------------------------------------ + + const PRODUCT_CLONE = "action.cloneProduct"; + const FILE_CLONE = "action.cloneFile"; + const PSE_CLONE = "action.clonePSE"; + + // -- END CLONE EVENTS ------------------------------------------------------------ + + + // -- SHIPPING ZONE MANAGEMENT + + const SHIPPING_ZONE_ADD_AREA = 'action.shippingZone.addArea'; + const SHIPPING_ZONE_REMOVE_AREA = 'action.shippingZone.removeArea'; + + // -- END SHIPPING ZONE MANAGEMENT + + + + // -- Categories Associated Content ---------------------------------------- + + /** @deprecated since 2.4, \Thelia\Model\Event\CategoryAssociatedContentEvent::PRE_INSERT */ + const BEFORE_CREATECATEGORY_ASSOCIATED_CONTENT = "action.before_createCategoryAssociatedContent"; + /** @deprecated since 2.4, \Thelia\Model\Event\CategoryAssociatedContentEvent::POST_INSERT */ + const AFTER_CREATECATEGORY_ASSOCIATED_CONTENT = "action.after_createCategoryAssociatedContent"; + + /** @deprecated since 2.4, \Thelia\Model\Event\CategoryAssociatedContentEvent::PRE_DELETE */ + const BEFORE_DELETECATEGORY_ASSOCIATED_CONTENT = "action.before_deleteCategoryAssociatedContent"; + /** @deprecated since 2.4, \Thelia\Model\Event\CategoryAssociatedContentEvent::POST_DELETE */ + const AFTER_DELETECATEGORY_ASSOCIATED_CONTENT = "action.after_deleteCategoryAssociatedContent"; + + /** @deprecated since 2.4, \Thelia\Model\Event\CategoryAssociatedContentEvent::PRE_UPDATE */ + const BEFORE_UPDATECATEGORY_ASSOCIATED_CONTENT = "action.before_updateCategoryAssociatedContent"; + /** @deprecated since 2.4, \Thelia\Model\Event\CategoryAssociatedContentEvent::POST_UPDATE */ + const AFTER_UPDATECATEGORY_ASSOCIATED_CONTENT = "action.after_updateCategoryAssociatedContent"; + + // -- Product Accessories -------------------------------------------------- + + /** @deprecated since 2.4, \Thelia\Model\Event\AccessoryEvent::PRE_INSERT */ + const BEFORE_CREATEACCESSORY = "action.before_createAccessory"; + /** @deprecated since 2.4, \Thelia\Model\Event\AccessoryEvent::POST_INSERT */ + const AFTER_CREATEACCESSORY = "action.after_createAccessory"; + + /** @deprecated since 2.4, \Thelia\Model\Event\AccessoryEvent::PRE_DELETE */ + const BEFORE_DELETEACCESSORY = "action.before_deleteAccessory"; + /** @deprecated since 2.4, \Thelia\Model\Event\AccessoryEvent::POST_DELETE */ + const AFTER_DELETEACCESSORY = "action.after_deleteAccessory"; + + /** @deprecated since 2.4, \Thelia\Model\Event\AccessoryEvent::PRE_UPDATE */ + const BEFORE_UPDATEACCESSORY = "action.before_updateAccessory"; + /** @deprecated since 2.4, \Thelia\Model\Event\AccessoryEvent::POST_UPDATE */ + const AFTER_UPDATEACCESSORY = "action.after_updateAccessory"; + + // -- Product Associated Content ------------------------------------------- + + /** @deprecated since 2.4, \Thelia\Model\Event\ProductAssociatedContentEvent::PRE_INSERT */ + const BEFORE_CREATEPRODUCT_ASSOCIATED_CONTENT = "action.before_createProductAssociatedContent"; + /** @deprecated since 2.4, \Thelia\Model\Event\ProductAssociatedContentEvent::POST_INSERT */ + const AFTER_CREATEPRODUCT_ASSOCIATED_CONTENT = "action.after_createProductAssociatedContent"; + + /** @deprecated since 2.4, \Thelia\Model\Event\ProductAssociatedContentEvent::PRE_DELETE */ + const BEFORE_DELETEPRODUCT_ASSOCIATED_CONTENT = "action.before_deleteProductAssociatedContent"; + /** @deprecated since 2.4, \Thelia\Model\Event\ProductAssociatedContentEvent::POST_DELETE */ + const AFTER_DELETEPRODUCT_ASSOCIATED_CONTENT = "action.after_deleteProductAssociatedContent"; + + /** @deprecated since 2.4, \Thelia\Model\Event\ProductAssociatedContentEvent::PRE_UPDATE */ + const BEFORE_UPDATEPRODUCT_ASSOCIATED_CONTENT = "action.before_updateProductAssociatedContent"; + /** @deprecated since 2.4, \Thelia\Model\Event\ProductAssociatedContentEvent::POST_UPDATE */ + const AFTER_UPDATEPRODUCT_ASSOCIATED_CONTENT = "action.after_updateProductAssociatedContent"; + + // -- Feature product ------------------------------------------------------ + + /** @deprecated since 2.4, \Thelia\Model\Event\FeatureProductEvent::PRE_INSERT */ + const BEFORE_CREATEFEATURE_PRODUCT = "action.before_createFeatureProduct"; + /** @deprecated since 2.4, \Thelia\Model\Event\FeatureProductEvent::POST_INSERT */ + const AFTER_CREATEFEATURE_PRODUCT = "action.after_createFeatureProduct"; + + /** @deprecated since 2.4, \Thelia\Model\Event\FeatureProductEvent::PRE_DELETE */ + const BEFORE_DELETEFEATURE_PRODUCT = "action.before_deleteFeatureProduct"; + /** @deprecated since 2.4, \Thelia\Model\Event\FeatureProductEvent::POST_DELETE */ + const AFTER_DELETEFEATURE_PRODUCT = "action.after_deleteFeatureProduct"; + + /** @deprecated since 2.4, \Thelia\Model\Event\FeatureProductEvent::PRE_UPDATE */ + const BEFORE_UPDATEFEATURE_PRODUCT = "action.before_updateFeatureProduct"; + /** @deprecated since 2.4, \Thelia\Model\Event\FeatureProductEvent::POST_UPDATE */ + const AFTER_UPDATEFEATURE_PRODUCT = "action.after_updateFeatureProduct"; + + /** Persist a cart */ + const CART_PERSIST = "cart.persist"; + + /** Restore a current cart in the session, either by reloading it from the database, or creating a new one */ + const CART_RESTORE_CURRENT = "cart.restore.current"; + + /** Create a new, empty cart in the session, and attach it to the current customer, if any. */ + const CART_CREATE_NEW = "cart.create.new"; + + /** + * sent when a new existing cat id duplicated. This append when current customer is different from current cart + * The old cart is already deleted from the database when this event is dispatched. + */ + const CART_DUPLICATE = "cart.duplicate"; + + /** + * Sent when the cart is duplicated, but not yet deleted from the database. + */ + const CART_DUPLICATED = "cart.duplicated"; + + /** + * Sent when a cart item is duplicated + */ + const CART_ITEM_DUPLICATE = "cart.item.duplicate"; + + /** + * sent when a new item is added to current cart + */ + const AFTER_CARTADDITEM = "cart.after.addItem"; + + /** + * sent for searching an item in the cart + */ + const CART_FINDITEM = "cart.findItem"; + + /** + * sent when a cart item is modify + */ + const AFTER_CARTUPDATEITEM = "cart.updateItem"; + + /** + * sent for addArticle action + */ + const CART_ADDITEM = "action.addArticle"; + + /** + * sent on modify article action + */ + const CART_UPDATEITEM = "action.updateArticle"; + const CART_DELETEITEM = "action.deleteArticle"; + const CART_CLEAR = "action.clear"; + + /** before inserting a cart item in database */ + const CART_ITEM_CREATE_BEFORE = "action.cart.item.create.before"; + + /** before updating a cart item in database */ + const CART_ITEM_UPDATE_BEFORE = "action.cart.item.update.before"; + + /** + * Order linked event + */ + const ORDER_SET_DELIVERY_ADDRESS = "action.order.setDeliveryAddress"; + const ORDER_SET_DELIVERY_MODULE = "action.order.setDeliveryModule"; + const ORDER_SET_POSTAGE = "action.order.setPostage"; + const ORDER_SET_INVOICE_ADDRESS = "action.order.setInvoiceAddress"; + const ORDER_SET_PAYMENT_MODULE = "action.order.setPaymentModule"; + const ORDER_PAY = "action.order.pay"; + /** @deprecated since 2.4, \Thelia\Model\Event\OrderEvent::PRE_INSERT */ + const ORDER_BEFORE_CREATE = "action.order.beforeCreate"; + /** @deprecated since 2.4, \Thelia\Model\Event\OrderEvent::POST_INSERT */ + const ORDER_AFTER_CREATE = "action.order.afterCreate"; + const ORDER_BEFORE_PAYMENT = "action.order.beforePayment"; + const ORDER_CART_CLEAR = "action.order.cartClear"; + + const ORDER_CREATE_MANUAL = "action.order.createManual"; + + const ORDER_UPDATE_STATUS = "action.order.updateStatus"; + + const ORDER_GET_STOCK_UPDATE_OPERATION_ON_ORDER_STATUS_CHANGE = "action.order.getStockUpdateOperationOnOrderStatusChange"; + + const ORDER_SEND_CONFIRMATION_EMAIL = "action.order.sendOrderConfirmationEmail"; + + const ORDER_SEND_NOTIFICATION_EMAIL = "action.order.sendOrderNotificationEmail"; + + 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_PRODUCT_BEFORE_CREATE = "action.orderProduct.beforeCreate"; + const ORDER_PRODUCT_AFTER_CREATE = "action.orderProduct.afterCreate"; + + /** + * Sent on image processing + */ + const IMAGE_PROCESS = "action.processImage"; + + /** + * Sent just after creating the image object from the image file + */ + const IMAGE_PREPROCESSING = "action.preProcessImage"; + + /** + * Sent just before saving the processed image object on disk + */ + const IMAGE_POSTPROCESSING = "action.postProcessImage"; + + /** + * Sent on image cache clear request + */ + const IMAGE_CLEAR_CACHE = "action.clearImageCache"; + + /** + * Save given images + */ + const IMAGE_SAVE = "action.saveImages"; + + /** + * Save given images + */ + const IMAGE_UPDATE = "action.updateImages"; + const IMAGE_UPDATE_POSITION = "action.updateImagePosition"; + const IMAGE_TOGGLE_VISIBILITY = "action.toggleImageVisibility"; + + /** + * Delete given image + */ + const IMAGE_DELETE = "action.deleteImage"; + + /** + * Sent on document processing + */ + const DOCUMENT_PROCESS = "action.processDocument"; + + /** + * Sent on image cache clear request + */ + const DOCUMENT_CLEAR_CACHE = "action.clearDocumentCache"; + + /** + * Save given documents + */ + const DOCUMENT_SAVE = "action.saveDocument"; + + /** + * Save given documents + */ + const DOCUMENT_UPDATE = "action.updateDocument"; + const DOCUMENT_UPDATE_POSITION = "action.updateDocumentPosition"; + const DOCUMENT_TOGGLE_VISIBILITY = "action.toggleDocumentVisibility"; + + /** + * Delete given document + */ + const DOCUMENT_DELETE = "action.deleteDocument"; + + /** + * Sent when creating a Coupon + */ + const COUPON_CREATE = "action.create_coupon"; + + /** + * Sent just before a successful insert of a new Coupon in the database. + */ + const BEFORE_CREATE_COUPON = "action.before_create_coupon"; + + /** + * Sent just after a successful insert of a new Coupon in the database. + */ + const AFTER_CREATE_COUPON = "action.after_create_coupon"; + + /** + * Sent when editing a Coupon + */ + const COUPON_UPDATE = "action.update_coupon"; + + /** + * Sent just before a successful update of a new Coupon in the database. + */ + const BEFORE_UPDATE_COUPON = "action.before_update_coupon"; + + /** + * Sent just after a successful update of a new Coupon in the database. + */ + const AFTER_UPDATE_COUPON = "action.after_update_coupon"; + + /** + * Sent when deleting a Coupon + */ + const COUPON_DELETE = "action.delete_coupon"; + + /** + * Sent when attempting to use a Coupon + */ + const COUPON_CONSUME = "action.consume_coupon"; + + /** + * Sent when all coupons in the current session should be cleared + */ + const COUPON_CLEAR_ALL = "action.clear_all_coupon"; + + /** + * Sent just before an attempt to use a Coupon + */ + const BEFORE_CONSUME_COUPON = "action.before_consume_coupon"; + + /** + * Sent just after an attempt to use a Coupon + */ + const AFTER_CONSUME_COUPON = "action.after_consume_coupon"; + + /** + * Sent when attempting to update Coupon Condition + */ + const COUPON_CONDITION_UPDATE = "action.update_coupon_condition"; + + /** + * Sent just before an attempt to update a Coupon Condition + */ + const BEFORE_COUPON_CONDITION_UPDATE = "action.before_update_coupon_condition"; + + /** + * Sent just after an attempt to update a Coupon Condition + */ + const AFTER_COUPON_CONDITION_UPDATE = "action.after_update_coupon_condition"; + + // -- Loop --------------------------------------------- + + const LOOP_EXTENDS_ARG_DEFINITIONS = "loop.extends.arg_definitions"; + const LOOP_EXTENDS_INITIALIZE_ARGS = "loop.extends.initialize_args"; + const LOOP_EXTENDS_BUILD_MODEL_CRITERIA = "loop.extends.build_model_criteria"; + const LOOP_EXTENDS_BUILD_ARRAY = "loop.extends.build_array"; + const LOOP_EXTENDS_PARSE_RESULTS = "loop.extends.parse_results"; + + /** + * Generate the event name for a specific loop + * + * @param string $eventName the event name + * @param string $loopName the loop name + * + * @return string the event name for the loop + */ + public static function getLoopExtendsEvent($eventName, $loopName) + { + return sprintf("%s.%s", $eventName, $loopName); + } + + // -- Configuration management --------------------------------------------- + + const CONFIG_CREATE = "action.createConfig"; + const CONFIG_SETVALUE = "action.setConfigValue"; + const CONFIG_UPDATE = "action.updateConfig"; + const CONFIG_DELETE = "action.deleteConfig"; + + /** @deprecated since 2.4, \Thelia\Model\Event\ConfigEvent::PRE_INSERT */ + const BEFORE_CREATECONFIG = "action.before_createConfig"; + /** @deprecated since 2.4, \Thelia\Model\Event\ConfigEvent::POST_INSERT */ + const AFTER_CREATECONFIG = "action.after_createConfig"; + + /** @deprecated since 2.4, \Thelia\Model\Event\ConfigEvent::PRE_DELETE */ + const BEFORE_DELETECONFIG = "action.before_deleteConfig"; + /** @deprecated since 2.4, \Thelia\Model\Event\ConfigEvent::POST_DELETE */ + const AFTER_DELETECONFIG = "action.after_deleteConfig"; + + /** @deprecated since 2.4, \Thelia\Model\Event\ConfigEvent::PRE_UPDATE */ + const BEFORE_UPDATECONFIG = "action.before_updateConfig"; + /** @deprecated since 2.4, \Thelia\Model\Event\ConfigEvent::POST_UPDATE */ + const AFTER_UPDATECONFIG = "action.after_updateConfig"; + + // -- Messages management --------------------------------------------- + + const MESSAGE_CREATE = "action.createMessage"; + const MESSAGE_UPDATE = "action.updateMessage"; + const MESSAGE_DELETE = "action.deleteMessage"; + + /** @deprecated since 2.4, \Thelia\Model\Event\MessageEvent::PRE_INSERT */ + const BEFORE_CREATEMESSAGE = "action.before_createMessage"; + /** @deprecated since 2.4, \Thelia\Model\Event\MessageEvent::POST_INSERT */ + const AFTER_CREATEMESSAGE = "action.after_createMessage"; + + /** @deprecated since 2.4, \Thelia\Model\Event\MessageEvent::PRE_DELETE */ + const BEFORE_DELETEMESSAGE = "action.before_deleteMessage"; + /** @deprecated since 2.4, \Thelia\Model\Event\MessageEvent::POST_DELETE */ + const AFTER_DELETEMESSAGE = "action.after_deleteMessage"; + + /** @deprecated since 2.4, \Thelia\Model\Event\MessageEvent::PRE_UPDATE */ + const BEFORE_UPDATEMESSAGE = "action.before_updateMessage"; + /** @deprecated since 2.4, \Thelia\Model\Event\MessageEvent::POST_UPDATE */ + const AFTER_UPDATEMESSAGE = "action.after_updateMessage"; + + // -- Currencies management --------------------------------------------- + + const CURRENCY_CREATE = "action.createCurrency"; + const CURRENCY_UPDATE = "action.updateCurrency"; + const CURRENCY_DELETE = "action.deleteCurrency"; + const CURRENCY_SET_DEFAULT = "action.setDefaultCurrency"; + const CURRENCY_SET_VISIBLE = "action.setVisibleCurrency"; + const CURRENCY_UPDATE_RATES = "action.updateCurrencyRates"; + const CURRENCY_UPDATE_POSITION = "action.updateCurrencyPosition"; + + /** @deprecated since 2.4, \Thelia\Model\Event\CurrencyEvent::PRE_INSERT */ + const BEFORE_CREATECURRENCY = "action.before_createCurrency"; + /** @deprecated since 2.4, \Thelia\Model\Event\CurrencyEvent::POST_INSERT */ + const AFTER_CREATECURRENCY = "action.after_createCurrency"; + + /** @deprecated since 2.4, \Thelia\Model\Event\CurrencyEvent::PRE_DELETE */ + const BEFORE_DELETECURRENCY = "action.before_deleteCurrency"; + /** @deprecated since 2.4, \Thelia\Model\Event\CurrencyEvent::POST_DELETE */ + const AFTER_DELETECURRENCY = "action.after_deleteCurrency"; + + /** @deprecated since 2.4, \Thelia\Model\Event\CurrencyEvent::PRE_UPDATE */ + const BEFORE_UPDATECURRENCY = "action.before_updateCurrency"; + /** @deprecated since 2.4, \Thelia\Model\Event\CurrencyEvent::POST_UPDATE */ + const AFTER_UPDATECURRENCY = "action.after_updateCurrency"; + + const CHANGE_DEFAULT_CURRENCY = 'action.changeDefaultCurrency'; + + // -- Tax management --------------------------------------------- + + const TAX_CREATE = "action.createTax"; + const TAX_UPDATE = "action.updateTax"; + const TAX_DELETE = "action.deleteTax"; + + // -- Profile management --------------------------------------------- + + const PROFILE_CREATE = "action.createProfile"; + const PROFILE_UPDATE = "action.updateProfile"; + const PROFILE_DELETE = "action.deleteProfile"; + const PROFILE_RESOURCE_ACCESS_UPDATE = "action.updateProfileResourceAccess"; + const PROFILE_MODULE_ACCESS_UPDATE = "action.updateProfileModuleAccess"; + + // -- Administrator management --------------------------------------------- + + const ADMINISTRATOR_CREATE = "action.createAdministrator"; + const ADMINISTRATOR_UPDATE = "action.updateAdministrator"; + const ADMINISTRATOR_DELETE = "action.deleteAdministrator"; + const ADMINISTRATOR_UPDATEPASSWORD = 'action.generatePassword'; + const ADMINISTRATOR_CREATEPASSWORD = 'action.createPassword'; + + // -- Api management --------------------------------------------- + + const API_CREATE = 'action.createApi'; + const API_DELETE = 'action.deleteApi'; + const API_UPDATE = 'action.updateApi'; + + // -- Mailing System management --------------------------------------------- + + const MAILING_SYSTEM_UPDATE = "action.updateMailingSystem"; + + // -- Tax Rules management --------------------------------------------- + + const TAX_RULE_CREATE = "action.createTaxRule"; + const TAX_RULE_UPDATE = "action.updateTaxRule"; + const TAX_RULE_DELETE = "action.deleteTaxRule"; + const TAX_RULE_SET_DEFAULT = "action.setDefaultTaxRule"; + const TAX_RULE_TAXES_UPDATE = "action.updateTaxesTaxRule"; + + // -- Product templates management ----------------------------------------- + + const TEMPLATE_CREATE = "action.createTemplate"; + const TEMPLATE_UPDATE = "action.updateTemplate"; + const TEMPLATE_DELETE = "action.deleteTemplate"; + const TEMPLATE_DUPLICATE = "action.duplicateTemplate"; + + const TEMPLATE_ADD_ATTRIBUTE = "action.templateAddAttribute"; + const TEMPLATE_DELETE_ATTRIBUTE = "action.templateDeleteAttribute"; + + const TEMPLATE_ADD_FEATURE = "action.templateAddFeature"; + const TEMPLATE_DELETE_FEATURE = "action.templateDeleteFeature"; + + const TEMPLATE_CHANGE_FEATURE_POSITION = "action.templateChangeAttributePosition"; + const TEMPLATE_CHANGE_ATTRIBUTE_POSITION = "action.templateChangeFeaturePosition"; + + /** @deprecated since 2.4, \Thelia\Model\Event\TemplateEvent::PRE_INSERT */ + const BEFORE_CREATETEMPLATE = "action.before_createTemplate"; + /** @deprecated since 2.4, \Thelia\Model\Event\TemplateEvent::POST_INSERT */ + const AFTER_CREATETEMPLATE = "action.after_createTemplate"; + + /** @deprecated since 2.4, \Thelia\Model\Event\TemplateEvent::PRE_DELETE */ + const BEFORE_DELETETEMPLATE = "action.before_deleteTemplate"; + /** @deprecated since 2.4, \Thelia\Model\Event\TemplateEvent::POST_DELETE */ + const AFTER_DELETETEMPLATE = "action.after_deleteTemplate"; + + /** @deprecated since 2.4, \Thelia\Model\Event\TemplateEvent::PRE_UPDATE */ + const BEFORE_UPDATETEMPLATE = "action.before_updateTemplate"; + /** @deprecated since 2.4, \Thelia\Model\Event\TemplateEvent::POST_UPDATE */ + const AFTER_UPDATETEMPLATE = "action.after_updateTemplate"; + + // -- Attributes management --------------------------------------------- + + const ATTRIBUTE_CREATE = "action.createAttribute"; + const ATTRIBUTE_UPDATE = "action.updateAttribute"; + const ATTRIBUTE_DELETE = "action.deleteAttribute"; + const ATTRIBUTE_UPDATE_POSITION = "action.updateAttributePosition"; + + const ATTRIBUTE_REMOVE_FROM_ALL_TEMPLATES = "action.addAttributeToAllTemplate"; + const ATTRIBUTE_ADD_TO_ALL_TEMPLATES = "action.removeAttributeFromAllTemplate"; + + /** @deprecated since 2.4, \Thelia\Model\Event\AttributeEvent::PRE_INSERT */ + const BEFORE_CREATEATTRIBUTE = "action.before_createAttribute"; + /** @deprecated since 2.4, \Thelia\Model\Event\AttributeEvent::POST_INSERT */ + const AFTER_CREATEATTRIBUTE = "action.after_createAttribute"; + + /** @deprecated since 2.4, \Thelia\Model\Event\AttributeEvent::PRE_DELETE */ + const BEFORE_DELETEATTRIBUTE = "action.before_deleteAttribute"; + /** @deprecated since 2.4, \Thelia\Model\Event\AttributeEvent::POST_DELETE */ + const AFTER_DELETEATTRIBUTE = "action.after_deleteAttribute"; + + /** @deprecated since 2.4, \Thelia\Model\Event\AttributeEvent::PRE_UPDATE */ + const BEFORE_UPDATEATTRIBUTE = "action.before_updateAttribute"; + /** @deprecated since 2.4, \Thelia\Model\Event\AttributeEvent::POST_UPDATE */ + const AFTER_UPDATEATTRIBUTE = "action.after_updateAttribute"; + + // -- Features management --------------------------------------------- + + const FEATURE_CREATE = "action.createFeature"; + const FEATURE_UPDATE = "action.updateFeature"; + const FEATURE_DELETE = "action.deleteFeature"; + const FEATURE_UPDATE_POSITION = "action.updateFeaturePosition"; + + const FEATURE_REMOVE_FROM_ALL_TEMPLATES = "action.addFeatureToAllTemplate"; + const FEATURE_ADD_TO_ALL_TEMPLATES = "action.removeFeatureFromAllTemplate"; + + /** @deprecated since 2.4, \Thelia\Model\Event\FeatureEvent::PRE_INSERT */ + const BEFORE_CREATEFEATURE = "action.before_createFeature"; + /** @deprecated since 2.4, \Thelia\Model\Event\FeatureEvent::POST_INSERT */ + const AFTER_CREATEFEATURE = "action.after_createFeature"; + + /** @deprecated since 2.4, \Thelia\Model\Event\FeatureEvent::PRE_DELETE */ + const BEFORE_DELETEFEATURE = "action.before_deleteFeature"; + /** @deprecated since 2.4, \Thelia\Model\Event\FeatureEvent::POST_DELETE */ + const AFTER_DELETEFEATURE = "action.after_deleteFeature"; + + /** @deprecated since 2.4, \Thelia\Model\Event\FeatureEvent::PRE_UPDATE */ + const BEFORE_UPDATEFEATURE = "action.before_updateFeature"; + /** @deprecated since 2.4, \Thelia\Model\Event\FeatureEvent::POST_UPDATE */ + const AFTER_UPDATEFEATURE = "action.after_updateFeature"; + + // -- Attributes values management ---------------------------------------- + + const ATTRIBUTE_AV_CREATE = "action.createAttributeAv"; + const ATTRIBUTE_AV_UPDATE = "action.updateAttributeAv"; + const ATTRIBUTE_AV_DELETE = "action.deleteAttributeAv"; + const ATTRIBUTE_AV_UPDATE_POSITION = "action.updateAttributeAvPosition"; + + /** @deprecated since 2.4, \Thelia\Model\Event\AttributeAvEvent::PRE_INSERT */ + const BEFORE_CREATEATTRIBUTE_AV = "action.before_createAttributeAv"; + /** @deprecated since 2.4, \Thelia\Model\Event\AttributeAvEvent::POST_INSERT */ + const AFTER_CREATEATTRIBUTE_AV = "action.after_createAttributeAv"; + + /** @deprecated since 2.4, \Thelia\Model\Event\AttributeAvEvent::PRE_DELETE */ + const BEFORE_UPDATEATTRIBUTE_AV = "action.before_updateAttributeAv"; + /** @deprecated since 2.4, \Thelia\Model\Event\AttributeAvEvent::POST_DELETE */ + const AFTER_UPDATEATTRIBUTE_AV = "action.after_updateAttributeAv"; + + /** @deprecated since 2.4, \Thelia\Model\Event\AttributeAvEvent::PRE_UPDATE */ + const BEFORE_DELETEATTRIBUTE_AV = "action.before_deleteAttributeAv"; + /** @deprecated since 2.4, \Thelia\Model\Event\AttributeAvEvent::POST_UPDATE */ + const AFTER_DELETEATTRIBUTE_AV = "action.after_deleteAttributeAv"; + + // -- Features values management ---------------------------------------- + + const FEATURE_AV_CREATE = "action.createFeatureAv"; + const FEATURE_AV_UPDATE = "action.updateFeatureAv"; + const FEATURE_AV_DELETE = "action.deleteFeatureAv"; + const FEATURE_AV_UPDATE_POSITION = "action.updateFeatureAvPosition"; + + /** @deprecated since 2.4, \Thelia\Model\Event\FeatureAvEvent::PRE_INSERT */ + const BEFORE_CREATEFEATURE_AV = "action.before_createFeatureAv"; + /** @deprecated since 2.4, \Thelia\Model\Event\FeatureAvEvent::POST_INSERT */ + const AFTER_CREATEFEATURE_AV = "action.after_createFeatureAv"; + + /** @deprecated since 2.4, \Thelia\Model\Event\FeatureAvEvent::PRE_DELETE */ + const BEFORE_UPDATEFEATURE_AV = "action.before_updateFeatureAv"; + /** @deprecated since 2.4, \Thelia\Model\Event\FeatureAvEvent::POST_DELETE */ + const AFTER_UPDATEFEATURE_AV = "action.after_updateFeatureAv"; + + /** @deprecated since 2.4, \Thelia\Model\Event\FeatureAvEvent::PRE_UPDATE */ + const BEFORE_DELETEFEATURE_AV = "action.before_deleteFeatureAv"; + /** @deprecated since 2.4, \Thelia\Model\Event\FeatureAvEvent::POST_UPDATE */ + const AFTER_DELETEFEATURE_AV = "action.after_deleteFeatureAv"; + + /** + * sent when system find a mailer transporter. + */ + const MAILTRANSPORTER_CONFIG = 'action.mailertransporter.config'; + + /** + * sent when Thelia try to generate a rewritten url + */ + const GENERATE_REWRITTENURL = 'action.generate_rewritenurl'; + + const GENERATE_PDF = 'thelia.generatePdf'; + + /** + * sent when a module is activated or deactivated + */ + const MODULE_TOGGLE_ACTIVATION = 'thelia.module.toggleActivation'; + + /** + * sent when module position is changed + */ + const MODULE_UPDATE_POSITION = 'thelia.module.action.updatePosition'; + + /** + * module + */ + const MODULE_CREATE = 'thelia.module.create'; + const MODULE_UPDATE = 'thelia.module.update'; + const MODULE_DELETE = 'thelia.module.delete'; + const MODULE_INSTALL = 'thelia.module.install'; + + /** + * Generate the event name for a specific module + * + * @param string $eventName the event name + * @param string $moduleCode the module code + * + * @return string the event name for the module + */ + public static function getModuleEvent($eventName, $moduleCode) + { + return sprintf("%s.%s", $eventName, strtolower($moduleCode)); + } + + /* Payment module */ + const MODULE_PAY = 'thelia.module.pay'; + const MODULE_PAYMENT_IS_VALID = 'thelia.module.payment.is_valid'; + const MODULE_PAYMENT_MANAGE_STOCK = 'thelia.module.payment.manage_stock'; + + /* Delivery module */ + const MODULE_DELIVERY_GET_POSTAGE = 'thelia.module.delivery.postage'; + const MODULE_DELIVERY_GET_PICKUP_LOCATIONS = 'thelia.module.delivery.pickupLocations'; + + /** + * Hook + */ + const BEFORE_HOOK_RENDER = 'thelia.hook.beforeRender'; + const HOOK_PROCESS_RENDER = 'thelia.hook.processRender'; + const AFTER_HOOK_RENDER = 'thelia.hook.afterRender'; + + const HOOK_CREATE = 'thelia.hook.action.create'; + const HOOK_UPDATE = 'thelia.hook.action.update'; + const HOOK_DELETE = 'thelia.hook.action.delete'; + const HOOK_TOGGLE_NATIVE = 'thelia.hook.action.toggleNative'; + const HOOK_TOGGLE_ACTIVATION = 'thelia.hook.action.toggleActivation'; + const HOOK_CREATE_ALL = 'thelia.hook.action.createAll'; + const HOOK_DEACTIVATION = 'thelia.hook.action.deactivation'; + + const MODULE_HOOK_CREATE = 'thelia.moduleHook.action.create'; + const MODULE_HOOK_UPDATE = 'thelia.moduleHook.action.update'; + const MODULE_HOOK_DELETE = 'thelia.moduleHook.action.delete'; + const MODULE_HOOK_UPDATE_POSITION = 'thelia.moduleHook.action.updatePosition'; + const MODULE_HOOK_TOGGLE_ACTIVATION = 'thelia.moduleHook.action.toggleActivation'; + + /** + * sent for clearing cache + */ + const CACHE_CLEAR = 'thelia.cache.clear'; + + /** + * sent for subscribing to the newsletter + */ + const NEWSLETTER_SUBSCRIBE = 'thelia.newsletter.subscribe'; + const NEWSLETTER_UPDATE = 'thelia.newsletter.update'; + const NEWSLETTER_UNSUBSCRIBE = 'thelia.newsletter.unsubscribe'; + const NEWSLETTER_CONFIRM_SUBSCRIPTION = 'thelia.newsletter.confirmSubscription'; + + /** + * sent for submit contact form + * @since 2.4 + */ + const CONTACT_SUBMIT = 'thelia.contact.submit'; + + /************ LANG MANAGEMENT ****************************/ + + const LANG_UPDATE = 'action.lang.update'; + const LANG_CREATE = 'action.lang.create'; + const LANG_DELETE = 'action.lang.delete'; + + const LANG_DEFAULTBEHAVIOR = 'action.lang.defaultBehavior'; + const LANG_URL = 'action.lang.url'; + + const LANG_FIX_MISSING_FLAG = 'action.lang.fix_missing_flag'; + + const LANG_TOGGLEDEFAULT = 'action.lang.toggleDefault'; + const LANG_TOGGLEACTIVE = 'action.lang.toggleActive'; + const LANG_TOGGLEVISIBLE = 'action.lang.toggleVisible'; + + /** @deprecated since 2.4, \Thelia\Model\Event\LangEvent::PRE_INSERT */ + const BEFORE_CREATELANG = "action.before_createLang"; + /** @deprecated since 2.4, \Thelia\Model\Event\LangEvent::POST_INSERT */ + const AFTER_CREATELANG = "action.after_createLang"; + + /** @deprecated since 2.4, \Thelia\Model\Event\LangEvent::PRE_DELETE */ + const BEFORE_DELETELANG = "action.before_deleteLang"; + /** @deprecated since 2.4, \Thelia\Model\Event\LangEvent::POST_DELETE */ + const AFTER_DELETELANG = "action.after_deleteLang"; + + /** @deprecated since 2.4, \Thelia\Model\Event\LangEvent::PRE_UPDATE */ + const BEFORE_UPDATELANG = "action.before_updateLang"; + /** @deprecated since 2.4, \Thelia\Model\Event\LangEvent::POST_UPDATE */ + const AFTER_UPDATELANG = "action.after_updateLang"; + + // -- Brands management ----------------------------------------------- + + const BRAND_CREATE = "action.createBrand"; + const BRAND_UPDATE = "action.updateBrand"; + const BRAND_DELETE = "action.deleteBrand"; + + const BRAND_UPDATE_POSITION = "action.updateBrandPosition"; + const BRAND_TOGGLE_VISIBILITY = "action.toggleBrandVisibility"; + + const BRAND_UPDATE_SEO = "action.updateBrandSeo"; + + /** @deprecated since 2.4, \Thelia\Model\Event\BrandEvent::PRE_INSERT */ + const BEFORE_CREATEBRAND = "action.before_createBrand"; + /** @deprecated since 2.4, \Thelia\Model\Event\BrandEvent::POST_INSERT */ + const AFTER_CREATEBRAND = "action.after_createBrand"; + + /** @deprecated since 2.4, \Thelia\Model\Event\BrandEvent::PRE_DELETE */ + const BEFORE_DELETEBRAND = "action.before_deleteBrand"; + /** @deprecated since 2.4, \Thelia\Model\Event\BrandEvent::POST_DELETE */ + const AFTER_DELETEBRAND = "action.after_deleteBrand"; + + /** @deprecated since 2.4, \Thelia\Model\Event\BrandEvent::PRE_UPDATE */ + const BEFORE_UPDATEBRAND = "action.before_updateBrand"; + /** @deprecated since 2.4, \Thelia\Model\Event\BrandEvent::POST_UPDATE */ + const AFTER_UPDATEBRAND = "action.after_updateBrand"; + + const VIEW_BRAND_ID_NOT_VISIBLE = "action.viewBrandIdNotVisible"; + + // -- Import ---------------------------------------------- + + const IMPORT_CHANGE_POSITION = 'import.change.position'; + const IMPORT_CATEGORY_CHANGE_POSITION = 'import.category.change.position'; + + const IMPORT_BEGIN = 'import.begin'; + const IMPORT_FINISHED = 'import.finished'; + const IMPORT_SUCCESS = 'import.success'; + + // -- Export ---------------------------------------------- + + const EXPORT_CHANGE_POSITION = 'export.change.position'; + const EXPORT_CATEGORY_CHANGE_POSITION = 'export.category.change.position'; + + const EXPORT_BEGIN = 'export.begin'; + const EXPORT_FINISHED = 'export.finished'; + const EXPORT_SUCCESS = 'export.success'; + + // -- Sales management ----------------------------------------------- + + const SALE_CREATE = "action.createSale"; + const SALE_UPDATE = "action.updateSale"; + const SALE_DELETE = "action.deleteSale"; + + const SALE_TOGGLE_ACTIVITY = "action.toggleSaleActivity"; + + const SALE_CLEAR_SALE_STATUS = "action.clearSaleStatus"; + + const UPDATE_PRODUCT_SALE_STATUS = "action.updateProductSaleStatus"; + + const CHECK_SALE_ACTIVATION_EVENT = "action.checkSaleActivationEvent"; + + /** @deprecated since 2.4, \Thelia\Model\Event\SaleEvent::PRE_INSERT */ + const BEFORE_CREATESALE = "action.before_createSale"; + /** @deprecated since 2.4, \Thelia\Model\Event\SaleEvent::POST_INSERT */ + const AFTER_CREATESALE = "action.after_createSale"; + + /** @deprecated since 2.4, \Thelia\Model\Event\SaleEvent::PRE_DELETE */ + const BEFORE_DELETESALE = "action.before_deleteSale"; + /** @deprecated since 2.4, \Thelia\Model\Event\SaleEvent::POST_DELETE */ + const AFTER_DELETESALE = "action.after_deleteSale"; + + /** @deprecated since 2.4, \Thelia\Model\Event\SaleEvent::PRE_UPDATE */ + const BEFORE_UPDATESALE = "action.before_updateSale"; + /** @deprecated since 2.4, \Thelia\Model\Event\SaleEvent::POST_UPDATE */ + const AFTER_UPDATESALE = "action.after_updateSale"; + + // -- Meta Data --------------------------------------------- + + const META_DATA_CREATE = "thelia.metadata.create"; + const META_DATA_UPDATE = "thelia.metadata.update"; + const META_DATA_DELETE = "thelia.metadata.delete"; + + // -- Form events ------------------------------------------- + + const FORM_BEFORE_BUILD = "thelia.form.before_build"; + const FORM_AFTER_BUILD = "thelia.form.after_build"; + + // -- Customer Title ---------------------------------------- + + const CUSTOMER_TITLE_CREATE = "action.title.create"; + const CUSTOMER_TITLE_UPDATE = "action.title.update"; + + /** @deprecated since 2.4, \Thelia\Model\Event\CustomerTitleEvent::PRE_INSERT */ + const CUSTOMER_TITLE_BEFORE_CREATE = "action.title.before_create"; + /** @deprecated since 2.4, \Thelia\Model\Event\CustomerTitleEvent::PRE_INSERT */ + const CUSTOMER_TITLE_AFTER_CREATE = "action.title.after_create"; + /** @deprecated since 2.4, \Thelia\Model\Event\CustomerTitleEvent::PRE_INSERT */ + const CUSTOMER_TITLE_BEFORE_UPDATE = "action.title.before_update"; + /** @deprecated since 2.4, \Thelia\Model\Event\CustomerTitleEvent::PRE_INSERT */ + const CUSTOMER_TITLE_AFTER_UPDATE = "action.title.after_update"; + + const CUSTOMER_TITLE_DELETE = "action.title.delete"; + + // -- Translation ------------------------------------------- + + const TRANSLATION_GET_STRINGS = 'action.translation.get_strings'; + const TRANSLATION_WRITE_FILE = 'action.translation.write_file'; + + // -- ORDER STATUS EVENTS ----------------------------------------------- + + const ORDER_STATUS_CREATE = "action.createOrderStatus"; + const ORDER_STATUS_UPDATE = "action.updateOrderStatus"; + const ORDER_STATUS_DELETE = "action.deleteOrderStatus"; + + /** @deprecated since 2.4, \Thelia\Model\Event\OrderStatusEvent::PRE_INSERT */ + const BEFORE_CREATE_ORDER_STATUS = "action.before_createOrderStatus"; + /** @deprecated since 2.4, \Thelia\Model\Event\OrderStatusEvent::POST_INSERT */ + const AFTER_CREATE_ORDER_STATUS = "action.after_createOrderStatus"; + + /** @deprecated since 2.4, \Thelia\Model\Event\OrderStatusEvent::PRE_DELETE */ + const BEFORE_DELETE_ORDER_STATUS = "action.before_deleteOrderStatus"; + /** @deprecated since 2.4, \Thelia\Model\Event\OrderStatusEvent::POST_DELETE */ + const AFTER_DELETE_ORDER_STATUS = "action.after_deleteOrderStatus"; + + /** @deprecated since 2.4, \Thelia\Model\Event\OrderStatusEvent::PRE_UPDATE */ + const BEFORE_UPDATE_ORDER_STATUS = "action.before_updateOrderStatus"; + /** @deprecated since 2.4, \Thelia\Model\Event\OrderStatusEvent::POST_UPDATE */ + const AFTER_UPDATE_ORDER_STATUS = "action.after_updateOrderStatus"; + + const ORDER_STATUS_UPDATE_POSITION = "action.updateOrderStatusPosition"; + // -- END ORDER STATUS EVENTS ----------------------------------------------- +} diff --git a/core/lib/Thelia/Core/Event/TheliaFormEvent.php b/core/lib/Thelia/Core/Event/TheliaFormEvent.php new file mode 100644 index 00000000..6be9fc76 --- /dev/null +++ b/core/lib/Thelia/Core/Event/TheliaFormEvent.php @@ -0,0 +1,58 @@ + + */ +class TheliaFormEvent extends Event +{ + /** + * @var BaseForm + */ + protected $form; + + public function __construct(BaseForm $form) + { + $this->form = $form; + } + + /** + * @return BaseForm + */ + public function getForm() + { + return $this->form; + } + + /** + * @param BaseForm $form + * @return $this + */ + public function setForm(BaseForm $form) + { + $this->form = $form; + + return $this; + } + + public function getName() + { + return $this->form->getName(); + } +} diff --git a/core/lib/Thelia/Core/Event/ToggleVisibilityEvent.php b/core/lib/Thelia/Core/Event/ToggleVisibilityEvent.php new file mode 100644 index 00000000..66e64a2d --- /dev/null +++ b/core/lib/Thelia/Core/Event/ToggleVisibilityEvent.php @@ -0,0 +1,57 @@ +object_id = $object_id; + } + + public function getObjectId() + { + return $this->object_id; + } + + public function setObjectId($object_id) + { + $this->object_id = $object_id; + + return $this; + } + + /** + * @param mixed $object + * + * @return $this + */ + public function setObject($object) + { + $this->object = $object; + + return $this; + } + + /** + * @return mixed + */ + public function getObject() + { + return $this->object; + } +} diff --git a/core/lib/Thelia/Core/Event/Translation/TranslationEvent.php b/core/lib/Thelia/Core/Event/Translation/TranslationEvent.php new file mode 100644 index 00000000..6267950f --- /dev/null +++ b/core/lib/Thelia/Core/Event/Translation/TranslationEvent.php @@ -0,0 +1,284 @@ + + * Creation date: 26/03/2015 16:01 + */ + +namespace Thelia\Core\Event\Translation; + +use Thelia\Core\Event\ActionEvent; + +class TranslationEvent extends ActionEvent +{ + const WALK_MODE_PHP = 'php'; + const WALK_MODE_TEMPLATE = 'tpl'; + + /** @var string */ + protected $directory; + + /** @var string */ + protected $mode; + + /** @var string */ + protected $locale; + + /** @var string */ + protected $domain; + + /** @var array */ + protected $translatableStrings; + + /** @var array */ + protected $customFallbackStrings; + + /** @var array */ + protected $globalFallbackStrings; + + /** @var int */ + protected $translatableStringCount; + + /** @var string */ + protected $translationFilePath; + + /** @var array */ + protected $translatedStrings; + + /** @var bool */ + protected $createFileIfNotExists; + + public static function createGetStringsEvent($directory, $mode, $locale, $domain) + { + $event = new TranslationEvent(); + + $event->setDirectory($directory); + $event->setMode($mode); + $event->setLocale($locale); + $event->setDomain($domain); + + return $event; + } + + public static function createWriteFileEvent( + $translationFilePath, + $translatableStrings, + $translatedStrings, + $createFileIfNotExists + ) { + $event = new TranslationEvent(); + + $event->setTranslatableStrings($translatableStrings); + $event->setTranslatedStrings($translatedStrings); + $event->setCreateFileIfNotExists($createFileIfNotExists); + $event->setTranslationFilePath($translationFilePath); + + return $event; + } + + + /** + * @return string + */ + public function getDirectory() + { + return $this->directory; + } + + /** + * @param string $directory + * @return $this + */ + public function setDirectory($directory) + { + $this->directory = $directory; + return $this; + } + + /** + * @return string + */ + public function getMode() + { + return $this->mode; + } + + /** + * @param string $mode + * @return $this + */ + public function setMode($mode) + { + $this->mode = $mode; + return $this; + } + + /** + * @return string + */ + public function getLocale() + { + return $this->locale; + } + + /** + * @param string $locale + * @return $this + */ + public function setLocale($locale) + { + $this->locale = $locale; + return $this; + } + + /** + * @return string + */ + public function getDomain() + { + return $this->domain; + } + + /** + * @param string $domain + * @return $this + */ + public function setDomain($domain) + { + $this->domain = $domain; + return $this; + } + + /** + * @return array + */ + public function getTranslatableStrings() + { + return $this->translatableStrings; + } + + /** + * @param array $translatableStrings + * @return $this + */ + public function setTranslatableStrings($translatableStrings) + { + $this->translatableStrings = $translatableStrings; + return $this; + } + + /** + * @return int + */ + public function getTranslatableStringCount() + { + return $this->translatableStringCount; + } + + /** + * @param int $translatableStringCount + * @return $this + */ + public function setTranslatableStringCount($translatableStringCount) + { + $this->translatableStringCount = $translatableStringCount; + return $this; + } + + /** + * @return string + */ + public function getTranslationFilePath() + { + return $this->translationFilePath; + } + + /** + * @param string $translationFilePath + * @return $this + */ + public function setTranslationFilePath($translationFilePath) + { + $this->translationFilePath = $translationFilePath; + return $this; + } + + /** + * @return array + */ + public function getTranslatedStrings() + { + return $this->translatedStrings; + } + + /** + * @param array $translatedStrings + * @return $this + */ + public function setTranslatedStrings($translatedStrings) + { + $this->translatedStrings = $translatedStrings; + return $this; + } + + /** + * @return boolean + */ + public function isCreateFileIfNotExists() + { + return $this->createFileIfNotExists; + } + + /** + * @param boolean $createFileIfNotExists + * @return $this + */ + public function setCreateFileIfNotExists($createFileIfNotExists) + { + $this->createFileIfNotExists = $createFileIfNotExists; + return $this; + } + + /** + * @return array + */ + public function getCustomFallbackStrings() + { + return $this->customFallbackStrings; + } + + /** + * @param array $customFallbackStrings + */ + public function setCustomFallbackStrings($customFallbackStrings) + { + $this->customFallbackStrings = $customFallbackStrings; + return $this; + } + + /** + * @return array + */ + public function getGlobalFallbackStrings() + { + return $this->globalFallbackStrings; + } + + /** + * @param array $globalFallbackStrings + */ + public function setGlobalFallbackStrings($globalFallbackStrings) + { + $this->globalFallbackStrings = $globalFallbackStrings; + return $this; + } +} diff --git a/core/lib/Thelia/Core/Event/UpdateFilePositionEvent.php b/core/lib/Thelia/Core/Event/UpdateFilePositionEvent.php new file mode 100644 index 00000000..8cf2f35c --- /dev/null +++ b/core/lib/Thelia/Core/Event/UpdateFilePositionEvent.php @@ -0,0 +1,49 @@ +setQuery($query); + } + + /** + * @param ModelCriteria $query + */ + public function setQuery(ModelCriteria $query) + { + $this->query = $query; + } + + /** + * @return ModelCriteria|null + */ + public function getQuery() + { + return $this->query; + } +} diff --git a/core/lib/Thelia/Core/Event/UpdatePositionEvent.php b/core/lib/Thelia/Core/Event/UpdatePositionEvent.php new file mode 100644 index 00000000..73aab7bb --- /dev/null +++ b/core/lib/Thelia/Core/Event/UpdatePositionEvent.php @@ -0,0 +1,139 @@ +object_id = $objectId; + $this->objectId = $objectId; + $this->mode = $mode; + $this->position = $position; + $this->referrerId = $referrerId; + } + + /** + * @return int + */ + public function getMode() + { + return $this->mode; + } + + /** + * @param int $mode + * @return $this + */ + public function setMode($mode) + { + $this->mode = $mode; + + return $this; + } + + /** + * @return int|null + */ + public function getPosition() + { + return $this->position; + } + + /** + * @param int $position + * @return $this + */ + public function setPosition($position) + { + $this->position = $position; + + return $this; + } + + /** + * @return int + */ + public function getObjectId() + { + return $this->objectId; + } + + /** + * @param int $objectId + * @return $this + */ + public function setObjectId($objectId) + { + $this->object_id = $objectId; + $this->objectId = $objectId; + return $this; + } + + /** + * @return int|null + */ + public function getReferrerId() + { + return $this->referrerId; + } + + /** + * @param int|null $referrerId + */ + public function setReferrerId($referrerId) + { + $this->referrerId = $referrerId; + } +} diff --git a/core/lib/Thelia/Core/Event/UpdateSeoEvent.php b/core/lib/Thelia/Core/Event/UpdateSeoEvent.php new file mode 100644 index 00000000..f1fb6a95 --- /dev/null +++ b/core/lib/Thelia/Core/Event/UpdateSeoEvent.php @@ -0,0 +1,175 @@ +object_id = $object_id; + $this->locale = $locale; + $this->url = $url; + $this->meta_title = $meta_title; + $this->meta_description = $meta_description; + $this->meta_keywords = $meta_keywords; + } + + /** + * @return mixed + */ + public function getObjectId() + { + return $this->object_id; + } + + /** + * @param $object_id + * @return $this + */ + public function setObjectId($object_id) + { + $this->object_id = $object_id; + + return $this; + } + + /** + * @return null + */ + public function getLocale() + { + return $this->locale; + } + + /** + * @param $locale + * @return $this + */ + public function setLocale($locale) + { + $this->locale = $locale; + + return $this; + } + + /** + * @return null + */ + public function getUrl() + { + return $this->url; + } + + /** + * @param $url + * @return $this + */ + public function setUrl($url) + { + $this->url = $url; + + return $this; + } + + /** + * @return null + */ + public function getMetaTitle() + { + return $this->meta_title; + } + + /** + * @param $meta_title + * @return $this + */ + public function setMetaTitle($meta_title) + { + $this->meta_title = $meta_title; + + return $this; + } + + /** + * @return null + */ + public function getMetaDescription() + { + return $this->meta_description; + } + + /** + * @param $meta_description + * @return $this + */ + public function setMetaDescription($meta_description) + { + $this->meta_description = $meta_description; + + return $this; + } + + /** + * @return null + */ + public function getMetaKeywords() + { + return $this->meta_keywords; + } + + /** + * @param $meta_keywords + * @return $this + */ + public function setMetaKeywords($meta_keywords) + { + $this->meta_keywords = $meta_keywords; + + return $this; + } + + /** + * @param mixed $object + */ + public function setObject($object) + { + $this->object = $object; + + return $this; + } + + /** + * @return mixed + */ + public function getObject() + { + return $this->object; + } +} diff --git a/core/lib/Thelia/Core/Event/ViewCheckEvent.php b/core/lib/Thelia/Core/Event/ViewCheckEvent.php new file mode 100644 index 00000000..ce32a9f2 --- /dev/null +++ b/core/lib/Thelia/Core/Event/ViewCheckEvent.php @@ -0,0 +1,67 @@ +view = $view; + + $this->view_id = $view_id; + } + + /** + * @return mixed + */ + public function getView() + { + return $this->view; + } + + /** + * @param mixed $view + * + * @return $this + */ + public function setView($view) + { + $this->view = $view; + + return $this; + } + + /** + * @return mixed + */ + public function getViewId() + { + return $this->view_id; + } + + /** + * @param mixed $view_id + * + * @return $this + */ + public function setViewId($view_id) + { + $this->view_id = $view_id; + + return $this; + } +} \ No newline at end of file diff --git a/core/lib/Thelia/Core/EventListener/ControllerListener.php b/core/lib/Thelia/Core/EventListener/ControllerListener.php new file mode 100644 index 00000000..3a548ccd --- /dev/null +++ b/core/lib/Thelia/Core/EventListener/ControllerListener.php @@ -0,0 +1,107 @@ + + */ +class ControllerListener implements EventSubscriberInterface +{ + protected $securityContext; + + public function __construct(SecurityContext $securityContext) + { + $this->securityContext = $securityContext; + } + + public function adminFirewall(FilterControllerEvent $event) + { + $controller = $event->getController(); + //check if an admin is logged in + if ($controller[0] instanceof BaseAdminController) { + if (false === $this->securityContext->hasAdminUser() && $event->getRequest()->attributes->get('not-logged') != 1) { + throw new AdminAccessDenied( + Translator::getInstance()->trans( + "You're not currently connected to the administration panel. Please log in to access this page" + ) + ); + } + } + } + + public function apiFirewall(FilterControllerEvent $event) + { + $controller = $event->getController(); + + if ($controller[0] instanceof BaseApiController && $event->getRequest()->attributes->get('not-logged') != 1) { + $apiAccount = $this->checkApiAccess( + $event->getRequest() + ); + + $controller[0]->setApiUser($apiAccount); + } + } + + private function checkApiAccess(Request $request) + { + $key = $request->headers->get('authorization'); + if (null !== $key) { + $key = substr($key, 6); + } + + $apiAccount = ApiQuery::create()->findOneByApiKey($key); + + if (null === $apiAccount) { + throw new UnauthorizedHttpException('Token'); + } + + $secureKey = pack('H*', $apiAccount->getSecureKey()); + + $sign = hash_hmac('sha1', $request->getContent(), $secureKey); + + if ($sign != $request->query->get('sign')) { + throw new PreconditionFailedHttpException('wrong body request signature'); + } + + return $apiAccount; + } + + /** + * {@inheritdoc} + * @api + */ + public static function getSubscribedEvents() + { + return [ + KernelEvents::CONTROLLER => [ + ['adminFirewall', 128], + ['apiFirewall', 128] + ] + ]; + } +} diff --git a/core/lib/Thelia/Core/EventListener/ErrorListener.php b/core/lib/Thelia/Core/EventListener/ErrorListener.php new file mode 100644 index 00000000..806e6717 --- /dev/null +++ b/core/lib/Thelia/Core/EventListener/ErrorListener.php @@ -0,0 +1,141 @@ + + */ +class ErrorListener implements EventSubscriberInterface +{ + /** @var EventDispatcherInterface */ + protected $eventDispatcher; + + /** @var ParserInterface */ + protected $parser; + + /** @var SecurityContext */ + protected $securityContext; + + /** @var string */ + protected $env; + + public function __construct( + $env, + ParserInterface $parser, + SecurityContext $securityContext, + EventDispatcherInterface $eventDispatcher + ) { + $this->env = $env; + + $this->parser = $parser; + + $this->securityContext = $securityContext; + + $this->eventDispatcher = $eventDispatcher; + } + + public function defaultErrorFallback(GetResponseForExceptionEvent $event) + { + $this->parser->assign("status_code", 500); + $this->parser->assign("exception_message", $event->getException()->getMessage()); + + if (!$this->parser->hasTemplateDefinition()) { + $this->parser->setTemplateDefinition( + $this->securityContext->hasAdminUser() ? + $this->parser->getTemplateHelper()->getActiveAdminTemplate() : + $this->parser->getTemplateHelper()->getActiveFrontTemplate() + ); + } + + $response = new Response( + $this->parser->render(ConfigQuery::getErrorMessagePageName()), + 500 + ); + + $event->setResponse($response); + } + + public function handleException(GetResponseForExceptionEvent $event) + { + if ("prod" === $this->env && ConfigQuery::isShowingErrorMessage()) { + $this->eventDispatcher + ->dispatch( + TheliaKernelEvents::THELIA_HANDLE_ERROR, + $event + ) + ; + } + } + + 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) + { + $exception = $event->getException(); + if ($exception instanceof AuthenticationException) { + $event->setResponse( + RedirectResponse::create($exception->getLoginTemplate()) + ); + } + } + + /** + * {@inheritdoc} + * api + */ + public static function getSubscribedEvents() + { + return array( + KernelEvents::EXCEPTION => [ + ["logException", 0], + ["handleException", 0], + ['authenticationException', 100] + ], + TheliaKernelEvents::THELIA_HANDLE_ERROR => [ + ["defaultErrorFallback", 0], + ], + ); + } +} diff --git a/core/lib/Thelia/Core/EventListener/RequestListener.php b/core/lib/Thelia/Core/EventListener/RequestListener.php new file mode 100644 index 00000000..5e0631c4 --- /dev/null +++ b/core/lib/Thelia/Core/EventListener/RequestListener.php @@ -0,0 +1,319 @@ + + */ +class RequestListener implements EventSubscriberInterface +{ + use RememberMeTrait; + + /** @var EventDispatcherInterface */ + protected $eventDispatcher; + + /** @var \Thelia\Core\Translation\Translator */ + private $translator; + + public function __construct(Translator $translator, EventDispatcherInterface $eventDispatcher) + { + $this->translator = $translator; + $this->eventDispatcher = $eventDispatcher; + } + + public function registerValidatorTranslator(GetResponseEvent $event) + { + /** @var \Thelia\Core\HttpFoundation\Request $request */ + $request = $event->getRequest(); + $lang = $request->getSession()->getLang(); + + $vendorFormDir = THELIA_VENDOR . 'symfony' . DS . 'form'; + $vendorValidatorDir = THELIA_VENDOR . 'symfony' . DS . 'validator'; + + $this->translator->addResource( + 'xlf', + sprintf($vendorFormDir.DS.'Resources'.DS.'translations'.DS.'validators.%s.xlf', $lang->getCode()), + $lang->getLocale(), + 'validators' + ); + $this->translator->addResource( + 'xlf', + sprintf($vendorValidatorDir.DS.'Resources'.DS.'translations'.DS.'validators.%s.xlf', $lang->getCode()), + $lang->getLocale(), + 'validators' + ); + } + + public function rememberMeLoader(GetResponseEvent $event) + { + /** @var \Thelia\Core\HttpFoundation\Request $request */ + $request = $event->getRequest(); + + /** @var \Thelia\Core\HttpFoundation\Session\Session $session */ + $session = $request->getSession(); + + if (null === $session->getCustomerUser()) { + // Check customer remember me token + $this->getRememberMeCustomer($request, $session, $this->eventDispatcher); + } + + // Check admin remember me token + if (null === $session->getAdminUser()) { + $this->getRememberMeAdmin($request, $session); + } + } + + public function jsonBody(GetResponseEvent $event) + { + $request = $event->getRequest(); + if (!\count($request->request->all()) && \in_array($request->getMethod(), array('POST', 'PUT', 'PATCH', 'DELETE'))) { + if ('json' == $request->getFormat($request->headers->get('Content-Type'))) { + $content = $request->getContent(); + if (!empty($content)) { + $data = json_decode($content, true); + + if (null === $data) { + $event->setResponse( + new JsonResponse(["error" => "The given data is not a valid json"], 400) + ); + + $event->stopPropagation(); + + return; + } elseif (!\is_array($data)) { + // This case happens for string like: "Foo", that json_decode returns as valid json + $data = [$data]; + } + + $request->request = new ParameterBag($data); + } + } + } + } + + /** + * @param Request $request + * @param Session $session + * @param EventDispatcherInterface $dispatcher + */ + protected function getRememberMeCustomer(Request $request, Session $session, EventDispatcherInterface $dispatcher) + { + // try to get the remember me cookie + $cookieCustomerName = ConfigQuery::read('customer_remember_me_cookie_name', 'crmcn'); + $cookie = $this->getRememberMeKeyFromCookie( + $request, + $cookieCustomerName + ); + + if (null !== $cookie) { + // try to log + $authenticator = new CustomerTokenAuthenticator($cookie); + + try { + // If have found a user, store it in the security context + $user = $authenticator->getAuthentifiedUser(); + + $session->setCustomerUser($user); + + $dispatcher->dispatch( + TheliaEvents::CUSTOMER_LOGIN, + new CustomerLoginEvent($user) + ); + } catch (TokenAuthenticationException $ex) { + // Clear the cookie + $this->clearRememberMeCookie($cookieCustomerName); + } + } + } + + /** + * @param $request + * @param $session + */ + protected function getRememberMeAdmin(Request $request, Session $session) + { + // try to get the remember me cookie + $cookieAdminName = ConfigQuery::read('admin_remember_me_cookie_name', 'armcn'); + $cookie = $this->getRememberMeKeyFromCookie( + $request, + $cookieAdminName + ); + + if (null !== $cookie) { + // try to log + $authenticator = new AdminTokenAuthenticator($cookie); + + try { + // If have found a user, store it in the security context + $user = $authenticator->getAuthentifiedUser(); + + $session->setAdminUser($user); + + $this->applyUserLocale($user, $session); + + AdminLog::append("admin", "LOGIN", "Authentication successful", $request, $user, false); + } catch (TokenAuthenticationException $ex) { + AdminLog::append("admin", "LOGIN", "Token based authentication failed.", $request); + + // Clear the cookie + $this->clearRememberMeCookie($cookieAdminName); + } + } + } + + protected function applyUserLocale(UserInterface $user, Session $session) + { + // Set the current language according to locale preference + $locale = $user->getLocale(); + + if (null === $lang = LangQuery::create() + ->filterByActive(true) + ->filterByLocale($locale) + ->findOne($locale)) { + $lang = Lang::getDefaultLanguage(); + } + + $session->setLang($lang); + } + + /** + * Save the previous URL in session which is based on the referer header or the request, or + * the _previous_url request attribute, if defined. + * + * If the value of _previous_url is "dont-save", the current referrer is not saved. + * + * @param \Symfony\Component\HttpKernel\Event\PostResponseEvent $event + */ + public function registerPreviousUrl(PostResponseEvent $event) + { + $request = $event->getRequest(); + + if (!$request->isXmlHttpRequest() && $event->getResponse()->isSuccessful()) { + $referrer = $request->attributes->get('_previous_url', null); + + $catalogViews = ['category', 'product']; + + $view = $request->attributes->get('_view', null); + + if (null !== $referrer) { + // A previous URL (or the keyword 'dont-save') has been specified. + if ('dont-save' == $referrer) { + // We should not save the current URL as the previous URL + $referrer = null; + } + } else { + // The current URL will become the previous URL + $referrer = $request->getUri(); + } + + // Set previous URL, if defined + if (null !== $referrer) { + /** @var Session $session */ + $session = $request->getSession(); + + if (ConfigQuery::isMultiDomainActivated()) { + $components = parse_url($referrer); + $lang = LangQuery::create() + ->filterByUrl(sprintf("%s://%s", $components["scheme"], $components["host"]), ModelCriteria::LIKE) + ->findOne(); + + if (null !== $lang) { + $session->setReturnToUrl($referrer); + + if (\in_array($view, $catalogViews)) { + $session->setReturnToCatalogLastUrl($referrer); + } + } + } else { + if (false !== strpos($referrer, $request->getSchemeAndHttpHost())) { + $session->setReturnToUrl($referrer); + + if (\in_array($view, $catalogViews)) { + $session->setReturnToCatalogLastUrl($referrer); + } + } + } + } + } + } + + public function checkCurrency(GetResponseEvent $event) + { + /** @var Request $request */ + $request = $event->getRequest(); + + if ($request->query->has("currency")) { + if (null !== $find = CurrencyQuery::create() + ->filterById($request->getSession()->getCurrency(true)->getId(), Criteria::NOT_EQUAL) + ->filterByVisible(true) + ->filterByCode($request->query->get("currency")) + ->findOne() + ) { + $request->getSession()->setCurrency($find); + $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)); + } + } + } + + /** + * {@inheritdoc} + * api + */ + public static function getSubscribedEvents() + { + return [ + KernelEvents::REQUEST => [ + ['checkCurrency', 256], + ["registerValidatorTranslator", 128], + ["rememberMeLoader", 128], + ['jsonBody', 128] + ], + KernelEvents::TERMINATE => [ + ["registerPreviousUrl", 128] + ] + ]; + } +} diff --git a/core/lib/Thelia/Core/EventListener/ResponseListener.php b/core/lib/Thelia/Core/EventListener/ResponseListener.php new file mode 100644 index 00000000..69955364 --- /dev/null +++ b/core/lib/Thelia/Core/EventListener/ResponseListener.php @@ -0,0 +1,63 @@ + + */ +class ResponseListener implements EventSubscriberInterface +{ + public function beforeResponse(FilterResponseEvent $event) + { + $session = $event->getRequest()->getSession(); + + if (null !== $id = $session->get("cart_use_cookie")) { + $response = $event->getResponse(); + $cookieName = ConfigQuery::read("cart.cookie_name", 'thelia_cart'); + + if (empty($id)) { + $response->headers->clearCookie($cookieName, '/'); + } else { + $response->headers->setCookie( + new Cookie( + ConfigQuery::read("cart.cookie_name", 'thelia_cart'), + $id, + time()+ConfigQuery::read("cart.cookie_lifetime", 60*60*24*365), + '/' + ) + ); + } + + $session->set("cart_use_cookie", null); + } + } + + /** + * {@inheritdoc} + * api + */ + public static function getSubscribedEvents() + { + return [ + KernelEvents::RESPONSE => ['beforeResponse', 128] + ]; + } +} diff --git a/core/lib/Thelia/Core/EventListener/SessionListener.php b/core/lib/Thelia/Core/EventListener/SessionListener.php new file mode 100644 index 00000000..4d0ed675 --- /dev/null +++ b/core/lib/Thelia/Core/EventListener/SessionListener.php @@ -0,0 +1,72 @@ + + */ +class SessionListener implements EventSubscriberInterface +{ + public function prodSession(SessionEvent $event) + { + $storage = new NativeSessionStorage( + [ 'cookie_lifetime' => ConfigQuery::read('session_config.lifetime', 0) ] + ); + $storage->setSaveHandler( + new NativeFileSessionHandler( + ConfigQuery::read("session_config.save_path", THELIA_ROOT . '/local/session/') + ) + ); + $event->setSession($this->getSession($storage)); + } + + public function testSession(SessionEvent $event) + { + if ($event->getEnv() == 'test') { + $storage = new MockFileSessionStorage($event->getCacheDir() . DS . 'sessions'); + $event->setSession($this->getSession($storage)); + $event->stopPropagation(); + } + } + + public function getSession(SessionStorageInterface $storage) + { + return new Session($storage); + } + + /** + * {@inheritdoc} + * api + */ + public static function getSubscribedEvents() + { + return [ + TheliaKernelEvents::SESSION =>[ + ['prodSession', 0], + ['testSession', 128] + ] + ]; + } +} diff --git a/core/lib/Thelia/Core/EventListener/ViewListener.php b/core/lib/Thelia/Core/EventListener/ViewListener.php new file mode 100644 index 00000000..9237b2f6 --- /dev/null +++ b/core/lib/Thelia/Core/EventListener/ViewListener.php @@ -0,0 +1,156 @@ + + */ + +class ViewListener implements EventSubscriberInterface +{ + /** @var ContainerInterface */ + private $container; + + /** @var EventDispatcherInterface */ + protected $eventDispatcher; + + /** + * @param ContainerInterface $container + * @param EventDispatcherInterface $eventDispatcher + */ + public function __construct(ContainerInterface $container, EventDispatcherInterface $eventDispatcher) + { + $this->container = $container; + $this->eventDispatcher = $eventDispatcher; + } + + /** + * Launch the parser defined on the constructor and get the result. + * + * The result is transform id needed into a Response object + * + * @param \Symfony\Component\HttpKernel\Event\GetResponseForControllerResultEvent $event + */ + public function onKernelView(GetResponseForControllerResultEvent $event) + { + $parser = $this->container->get('thelia.parser'); + $templateHelper = $this->container->get('thelia.template_helper'); + $parser->setTemplateDefinition($templateHelper->getActiveFrontTemplate(), true); + $request = $this->container->get('request_stack')->getCurrentRequest(); + $response = null; + try { + $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) { + $response = $content; + } else { + $response = new Response($content, $parser->getStatus() ?: 200); + } + } catch (ResourceNotFoundException $e) { + throw new NotFoundHttpException(); + } catch (OrderException $e) { + switch ($e->getCode()) { + case OrderException::CART_EMPTY: + // Redirect to the cart template + $response = RedirectResponse::create($this->container->get('router.chainRequest')->generate($e->cartRoute, $e->arguments, Router::ABSOLUTE_URL)); + break; + case OrderException::UNDEFINED_DELIVERY: + // Redirect to the delivery choice template + $response = RedirectResponse::create($this->container->get('router.chainRequest')->generate($e->orderDeliveryRoute, $e->arguments, Router::ABSOLUTE_URL)); + break; + } + if (null === $response) { + throw $e; + } + } + + $event->setResponse($response); + } + + public function beforeKernelView(GetResponseForControllerResultEvent $event) + { + $request = $this->container->get('request_stack')->getCurrentRequest(); + + if (null === $view = $request->attributes->get('_view')) { + $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) + { + if (! $view = $request->query->get('view')) { + $view = 'index'; + if ($request->request->has('view')) { + $view = $request->request->get('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} + * api + */ + public static function getSubscribedEvents() + { + return array( + KernelEvents::VIEW =>array( + array('onKernelView', 0), + array('beforeKernelView', 5) + ) + ); + } +} diff --git a/core/lib/Thelia/Core/Form/TheliaFormFactory.php b/core/lib/Thelia/Core/Form/TheliaFormFactory.php new file mode 100644 index 00000000..8feef2da --- /dev/null +++ b/core/lib/Thelia/Core/Form/TheliaFormFactory.php @@ -0,0 +1,58 @@ + + */ +class TheliaFormFactory implements TheliaFormFactoryInterface +{ + /** @var RequestStack */ + protected $requestStack; + + /** @var ContainerInterface */ + protected $container; + + /** @var array */ + protected $formDefinition; + + public function __construct(RequestStack $requestStack, ContainerInterface $container, array $formDefinition) + { + $this->requestStack = $requestStack; + $this->container = $container; + $this->formDefinition = $formDefinition; + } + + /** + * @param string $name + * @param string $type + * @param array $data + * @param array $options + * @return \Thelia\Form\BaseForm + */ + public function createForm($name, $type = "form", array $data = array(), array $options = array()) + { + if (!isset($this->formDefinition[$name])) { + throw new \OutOfBoundsException( + sprintf("The form '%s' doesn't exist", $name) + ); + } + + return new $this->formDefinition[$name]($this->requestStack->getCurrentRequest(), $type, $data, $options, $this->container); + } +} diff --git a/core/lib/Thelia/Core/Form/TheliaFormFactoryInterface.php b/core/lib/Thelia/Core/Form/TheliaFormFactoryInterface.php new file mode 100644 index 00000000..ff64c5c2 --- /dev/null +++ b/core/lib/Thelia/Core/Form/TheliaFormFactoryInterface.php @@ -0,0 +1,29 @@ + + */ +interface TheliaFormFactoryInterface +{ + /** + * @param string $name + * @param string $type + * @param array $data + * @param array $options + * @return \Thelia\Form\BaseForm + */ + public function createForm($name, $type = "form", array $data = array(), array $options = array()); +} diff --git a/core/lib/Thelia/Core/Form/TheliaFormValidator.php b/core/lib/Thelia/Core/Form/TheliaFormValidator.php new file mode 100644 index 00000000..2588977f --- /dev/null +++ b/core/lib/Thelia/Core/Form/TheliaFormValidator.php @@ -0,0 +1,124 @@ + + */ +class TheliaFormValidator implements TheliaFormValidatorInterface +{ + /** @var TranslatorInterface */ + protected $translator; + + /** @var string */ + protected $environment; + + public function __construct(TranslatorInterface $translator, $environment) + { + $this->translator = $translator; + $this->environment = $environment; + } + + /** + * Validate a BaseForm + * + * @param BaseForm $aBaseForm the form + * @param string $expectedMethod the expected method, POST or GET, or null for any of them + * @throws FormValidationException is the form contains error, or the method is not the right one + * @return \Symfony\Component\Form\Form Form the symfony form object + */ + public function validateForm(BaseForm $aBaseForm, $expectedMethod = null) + { + $form = $aBaseForm->getForm(); + + if ($expectedMethod == null || $aBaseForm->getRequest()->isMethod($expectedMethod)) { + $form->handleRequest($aBaseForm->getRequest()); + + if ($form->isValid()) { + if ($aBaseForm instanceof FirewallForm && !$aBaseForm->isFirewallOk($this->environment)) { + throw new FormValidationException( + $this->translator->trans("You've submitted this form too many times. ") + .$this->translator->trans("Further submissions will be ignored during %time", + [ + "%time" => $aBaseForm->getWaitingTime(), + ] + ) + ); + } + + return $form; + } else { + $errorMessage = null; + if ($form->get("error_message")->getData() != null) { + $errorMessage = $form->get("error_message")->getData(); + } else { + $errorMessage = sprintf( + $this->translator->trans( + "Missing or invalid data: %s" + ), + $this->getErrorMessages($form) + ); + } + $aBaseForm->setError(true); + throw new FormValidationException($errorMessage); + } + } else { + throw new FormValidationException( + sprintf( + $this->translator->trans( + "Wrong form method, %s expected." + ), + $expectedMethod + ) + ); + } + } + + /** + * Get all errors that occurred in a form + * + * @param \Symfony\Component\Form\Form $form + * @return string the error string + */ + public function getErrorMessages(Form $form) + { + $errors = ''; + + foreach ($form->getErrors() as $key => $error) { + $errors .= $error->getMessage().', '; + } + + /** @var Form $child */ + foreach ($form->all() as $child) { + if (!$child->isValid()) { + $fieldName = $child->getConfig()->getOption('label', null); + + if (empty($fieldName)) { + $fieldName = $child->getName(); + } + + $errors .= sprintf("[%s] %s, ", $fieldName, $this->getErrorMessages($child)); + } + } + + return rtrim($errors, ', '); + } +} diff --git a/core/lib/Thelia/Core/Form/TheliaFormValidatorInterface.php b/core/lib/Thelia/Core/Form/TheliaFormValidatorInterface.php new file mode 100644 index 00000000..7ff0619e --- /dev/null +++ b/core/lib/Thelia/Core/Form/TheliaFormValidatorInterface.php @@ -0,0 +1,42 @@ + + */ +interface TheliaFormValidatorInterface +{ + /** + * Validate a BaseForm + * + * @param BaseForm $aBaseForm the form + * @param string $expectedMethod the expected method, POST or GET, or null for any of them + * @throws FormValidationException is the form contains error, or the method is not the right one + * @return \Symfony\Component\Form\Form Form the symfony form object + */ + public function validateForm(BaseForm $aBaseForm, $expectedMethod = null); + + /** + * Get all errors that occurred in a form + * + * @param \Symfony\Component\Form\Form $form + * @return string the error string + */ + public function getErrorMessages(Form $form); +} diff --git a/core/lib/Thelia/Core/Form/Type/AbstractTheliaType.php b/core/lib/Thelia/Core/Form/Type/AbstractTheliaType.php new file mode 100644 index 00000000..d6a2c998 --- /dev/null +++ b/core/lib/Thelia/Core/Form/Type/AbstractTheliaType.php @@ -0,0 +1,76 @@ + + * + * This class adds some tools for simple validation + */ +abstract class AbstractTheliaType extends AbstractType +{ + /** + * @param $groups + * @param array $constraints + * @return array + * + * Replaces validation groups in constraints + */ + protected function replaceGroups($groups, array $constraints) + { + if (!\is_array($groups)) { + $groups = [$groups]; + } + + /** @var \Symfony\Component\Validator\Constraint $constraint */ + foreach ($constraints as &$constraint) { + $constraint->groups = $groups; + } + + return $constraints; + } + + /** + * @param AbstractType $type + * @param string $groups + * @return array + * + * Get an array with the type's constraints loaded with groups + */ + protected function getConstraints(AbstractType $type, $groups = "Default") + { + /** + * Create a resolver to get the options + */ + $nullResolver = new OptionsResolver(); + $type->configureOptions($nullResolver); + + $options = $nullResolver->resolve(); + + if (!isset($options["constraints"])) { + $options["constraints"] = array(); + } + + /** + * Then replace groups + */ + $constraints = $this->replaceGroups($groups, $options["constraints"]); + + return $constraints; + } +} diff --git a/core/lib/Thelia/Core/Form/Type/CustomerTitleI18nType.php b/core/lib/Thelia/Core/Form/Type/CustomerTitleI18nType.php new file mode 100644 index 00000000..b40e1d6c --- /dev/null +++ b/core/lib/Thelia/Core/Form/Type/CustomerTitleI18nType.php @@ -0,0 +1,67 @@ + + */ +class CustomerTitleI18nType extends AbstractTheliaType +{ + public function configureOptions(OptionsResolver $resolver) + { + $resolver->setDefaults([ + "cascade_validation" => true, + ]); + } + + public function buildForm(FormBuilderInterface $builder, array $options) + { + $builder + ->add("locale", "text", array( + "required" => true, + "constraints" => array( + new NotBlank(), + ), + )) + ->add("short", "text", array( + "required" => false, + "constraints" => array( + new Length(["max" => 10]), + ), + )) + ->add("long", "text", array( + "required" => false, + "constraints" => array( + new Length(["max" => 45]), + ), + )) + ; + } + + /** + * Returns the name of this type. + * + * @return string The name of this type + */ + public function getName() + { + return "customer_title_i18n"; + } +} diff --git a/core/lib/Thelia/Core/Form/Type/CustomerTitleType.php b/core/lib/Thelia/Core/Form/Type/CustomerTitleType.php new file mode 100644 index 00000000..b9ed830c --- /dev/null +++ b/core/lib/Thelia/Core/Form/Type/CustomerTitleType.php @@ -0,0 +1,64 @@ + + */ +class CustomerTitleType extends AbstractTheliaType +{ + /** + * @var CustomerTitleIdType + */ + protected $customerTitleIdType; + + public function __construct(CustomerTitleIdType $customerTitleIdType) + { + $this->customerTitleIdType = $customerTitleIdType; + } + + public function buildForm(FormBuilderInterface $builder, array $options) + { + $builder + ->add("i18n", "collection", array( + "type" => "customer_title_i18n", + "allow_add" => true, + "required" => true, + "cascade_validation" => true, + "constraints" => array( + new Count(["min" => 1]), + ), + )) + ->add("default", "checkbox") + ->add("title_id", "customer_title_id", array( + "constraints" => $this->getConstraints($this->customerTitleIdType, "update"), + )) + ; + } + + /** + * Returns the name of this type. + * + * @return string The name of this type + */ + public function getName() + { + return "customer_title"; + } +} diff --git a/core/lib/Thelia/Core/Form/Type/Field/AbstractIdType.php b/core/lib/Thelia/Core/Form/Type/Field/AbstractIdType.php new file mode 100644 index 00000000..af20e1ed --- /dev/null +++ b/core/lib/Thelia/Core/Form/Type/Field/AbstractIdType.php @@ -0,0 +1,90 @@ + + */ +abstract class AbstractIdType extends AbstractType +{ + /** + * @var TranslatorInterface + */ + protected $translator; + + public function __construct(TranslatorInterface $translator) + { + $this->translator = $translator; + } + + public function configureOptions(OptionsResolver $resolver) + { + $resolver->setDefaults([ + "required" => true, + "constraints" => array( + new NotBlank(), + new Callback([ + "methods" => array( + [$this, "checkId"], + ), + ]), + ), + "cascade_validation" => true, + ]); + } + + public function getParent() + { + return "integer"; + } + + public function checkId($value, ExecutionContextInterface $context) + { + if (null === $this->getQuery()->findPk($value)) { + $context->addViolation( + $this->translator->trans( + "The %obj_name id '%id' doesn't exist", + [ + "%obj_name" => $this->getObjName(), + "%id" => $value, + ] + ) + ); + } + } + + protected function getObjName() + { + if (preg_match("#^(.+)_id$#i", $this->getName(), $match)) { + return $match[1]; + } + + return $this->getName(); + } + + /** + * @return \Propel\Runtime\ActiveQuery\ModelCriteria + * + * Get the model query to check + */ + abstract protected function getQuery(); +} diff --git a/core/lib/Thelia/Core/Form/Type/Field/AccessoryIdType.php b/core/lib/Thelia/Core/Form/Type/Field/AccessoryIdType.php new file mode 100644 index 00000000..3aaeac81 --- /dev/null +++ b/core/lib/Thelia/Core/Form/Type/Field/AccessoryIdType.php @@ -0,0 +1,43 @@ + + */ +class AccessoryIdType extends AbstractIdType +{ + /** + * @return \Propel\Runtime\ActiveQuery\ModelCriteria + * + * Get the model query to check + */ + protected function getQuery() + { + return new AccessoryQuery(); + } + + /** + * Returns the name of this type. + * + * @return string The name of this type + */ + public function getName() + { + return "accessory_id"; + } +} diff --git a/core/lib/Thelia/Core/Form/Type/Field/AddressIdType.php b/core/lib/Thelia/Core/Form/Type/Field/AddressIdType.php new file mode 100644 index 00000000..6b36a940 --- /dev/null +++ b/core/lib/Thelia/Core/Form/Type/Field/AddressIdType.php @@ -0,0 +1,43 @@ + + */ +class AddressIdType extends AbstractIdType +{ + /** + * @return \Propel\Runtime\ActiveQuery\ModelCriteria + * + * Get the model query to check + */ + protected function getQuery() + { + return new AddressQuery(); + } + + /** + * Returns the name of this type. + * + * @return string The name of this type + */ + public function getName() + { + return "address_id"; + } +} diff --git a/core/lib/Thelia/Core/Form/Type/Field/AdminIdType.php b/core/lib/Thelia/Core/Form/Type/Field/AdminIdType.php new file mode 100644 index 00000000..a826a9ec --- /dev/null +++ b/core/lib/Thelia/Core/Form/Type/Field/AdminIdType.php @@ -0,0 +1,43 @@ + + */ +class AdminIdType extends AbstractIdType +{ + /** + * @return \Propel\Runtime\ActiveQuery\ModelCriteria + * + * Get the model query to check + */ + protected function getQuery() + { + return new AdminQuery(); + } + + /** + * Returns the name of this type. + * + * @return string The name of this type + */ + public function getName() + { + return "admin_id"; + } +} diff --git a/core/lib/Thelia/Core/Form/Type/Field/AdminLogIdType.php b/core/lib/Thelia/Core/Form/Type/Field/AdminLogIdType.php new file mode 100644 index 00000000..0226eb44 --- /dev/null +++ b/core/lib/Thelia/Core/Form/Type/Field/AdminLogIdType.php @@ -0,0 +1,43 @@ + + */ +class AdminLogIdType extends AbstractIdType +{ + /** + * @return \Propel\Runtime\ActiveQuery\ModelCriteria + * + * Get the model query to check + */ + protected function getQuery() + { + return new AdminLogQuery(); + } + + /** + * Returns the name of this type. + * + * @return string The name of this type + */ + public function getName() + { + return "admin_log_id"; + } +} diff --git a/core/lib/Thelia/Core/Form/Type/Field/ApiIdType.php b/core/lib/Thelia/Core/Form/Type/Field/ApiIdType.php new file mode 100644 index 00000000..8887e01e --- /dev/null +++ b/core/lib/Thelia/Core/Form/Type/Field/ApiIdType.php @@ -0,0 +1,43 @@ + + */ +class ApiIdType extends AbstractIdType +{ + /** + * @return \Propel\Runtime\ActiveQuery\ModelCriteria + * + * Get the model query to check + */ + protected function getQuery() + { + return new ApiQuery(); + } + + /** + * Returns the name of this type. + * + * @return string The name of this type + */ + public function getName() + { + return "api_id"; + } +} diff --git a/core/lib/Thelia/Core/Form/Type/Field/AreaDeliveryModuleIdType.php b/core/lib/Thelia/Core/Form/Type/Field/AreaDeliveryModuleIdType.php new file mode 100644 index 00000000..2b25d833 --- /dev/null +++ b/core/lib/Thelia/Core/Form/Type/Field/AreaDeliveryModuleIdType.php @@ -0,0 +1,43 @@ + + */ +class AreaDeliveryModuleIdType extends AbstractIdType +{ + /** + * @return \Propel\Runtime\ActiveQuery\ModelCriteria + * + * Get the model query to check + */ + protected function getQuery() + { + return new AreaDeliveryModuleQuery(); + } + + /** + * Returns the name of this type. + * + * @return string The name of this type + */ + public function getName() + { + return "area_delivery_module_id"; + } +} diff --git a/core/lib/Thelia/Core/Form/Type/Field/AreaIdType.php b/core/lib/Thelia/Core/Form/Type/Field/AreaIdType.php new file mode 100644 index 00000000..6166dc35 --- /dev/null +++ b/core/lib/Thelia/Core/Form/Type/Field/AreaIdType.php @@ -0,0 +1,43 @@ + + */ +class AreaIdType extends AbstractIdType +{ + /** + * @return \Propel\Runtime\ActiveQuery\ModelCriteria + * + * Get the model query to check + */ + protected function getQuery() + { + return new AreaQuery(); + } + + /** + * Returns the name of this type. + * + * @return string The name of this type + */ + public function getName() + { + return 'area_id'; + } +} diff --git a/core/lib/Thelia/Core/Form/Type/Field/AttributeAvIdType.php b/core/lib/Thelia/Core/Form/Type/Field/AttributeAvIdType.php new file mode 100644 index 00000000..eeec14de --- /dev/null +++ b/core/lib/Thelia/Core/Form/Type/Field/AttributeAvIdType.php @@ -0,0 +1,43 @@ + + */ +class AttributeAvIdType extends AbstractIdType +{ + /** + * @return \Propel\Runtime\ActiveQuery\ModelCriteria + * + * Get the model query to check + */ + protected function getQuery() + { + return new AttributeAvQuery(); + } + + /** + * Returns the name of this type. + * + * @return string The name of this type + */ + public function getName() + { + return "attribute_av"; + } +} diff --git a/core/lib/Thelia/Core/Form/Type/Field/AttributeIdType.php b/core/lib/Thelia/Core/Form/Type/Field/AttributeIdType.php new file mode 100644 index 00000000..80aa6ee1 --- /dev/null +++ b/core/lib/Thelia/Core/Form/Type/Field/AttributeIdType.php @@ -0,0 +1,43 @@ + + */ +class AttributeIdType extends AbstractIdType +{ + /** + * @return \Propel\Runtime\ActiveQuery\ModelCriteria + * + * Get the model query to check + */ + protected function getQuery() + { + return new AttributeQuery(); + } + + /** + * Returns the name of this type. + * + * @return string The name of this type + */ + public function getName() + { + return "attribute_id"; + } +} diff --git a/core/lib/Thelia/Core/Form/Type/Field/AttributeTemplateIdType.php b/core/lib/Thelia/Core/Form/Type/Field/AttributeTemplateIdType.php new file mode 100644 index 00000000..ce530245 --- /dev/null +++ b/core/lib/Thelia/Core/Form/Type/Field/AttributeTemplateIdType.php @@ -0,0 +1,43 @@ + + */ +class AttributeTemplateIdType extends AbstractIdType +{ + /** + * @return \Propel\Runtime\ActiveQuery\ModelCriteria + * + * Get the model query to check + */ + protected function getQuery() + { + return new AttributeTemplateQuery(); + } + + /** + * Returns the name of this type. + * + * @return string The name of this type + */ + public function getName() + { + return "attribute_template_id"; + } +} diff --git a/core/lib/Thelia/Core/Form/Type/Field/BrandIdType.php b/core/lib/Thelia/Core/Form/Type/Field/BrandIdType.php new file mode 100644 index 00000000..317dae7d --- /dev/null +++ b/core/lib/Thelia/Core/Form/Type/Field/BrandIdType.php @@ -0,0 +1,43 @@ + + */ +class BrandIdType extends AbstractIdType +{ + /** + * @return \Propel\Runtime\ActiveQuery\ModelCriteria + * + * Get the model query to check + */ + protected function getQuery() + { + return new BrandQuery(); + } + + /** + * Returns the name of this type. + * + * @return string The name of this type + */ + public function getName() + { + return "brand_id"; + } +} diff --git a/core/lib/Thelia/Core/Form/Type/Field/CartIdType.php b/core/lib/Thelia/Core/Form/Type/Field/CartIdType.php new file mode 100644 index 00000000..01aad9e0 --- /dev/null +++ b/core/lib/Thelia/Core/Form/Type/Field/CartIdType.php @@ -0,0 +1,43 @@ + + */ +class CartIdType extends AbstractIdType +{ + /** + * @return \Propel\Runtime\ActiveQuery\ModelCriteria + * + * Get the model query to check + */ + protected function getQuery() + { + return new CartQuery(); + } + + /** + * Returns the name of this type. + * + * @return string The name of this type + */ + public function getName() + { + return "cart_id"; + } +} diff --git a/core/lib/Thelia/Core/Form/Type/Field/CartItemIdType.php b/core/lib/Thelia/Core/Form/Type/Field/CartItemIdType.php new file mode 100644 index 00000000..fa30a888 --- /dev/null +++ b/core/lib/Thelia/Core/Form/Type/Field/CartItemIdType.php @@ -0,0 +1,43 @@ + + */ +class CartItemIdType extends AbstractIdType +{ + /** + * @return \Propel\Runtime\ActiveQuery\ModelCriteria + * + * Get the model query to check + */ + protected function getQuery() + { + return new CartItemQuery(); + } + + /** + * Returns the name of this type. + * + * @return string The name of this type + */ + public function getName() + { + return "cart_item_id"; + } +} diff --git a/core/lib/Thelia/Core/Form/Type/Field/CategoryAssociatedContentIdType.php b/core/lib/Thelia/Core/Form/Type/Field/CategoryAssociatedContentIdType.php new file mode 100644 index 00000000..f3c4e049 --- /dev/null +++ b/core/lib/Thelia/Core/Form/Type/Field/CategoryAssociatedContentIdType.php @@ -0,0 +1,43 @@ + + */ +class CategoryAssociatedContentIdType extends AbstractIdType +{ + /** + * @return \Propel\Runtime\ActiveQuery\ModelCriteria + * + * Get the model query to check + */ + protected function getQuery() + { + return new CategoryAssociatedContentQuery(); + } + + /** + * Returns the name of this type. + * + * @return string The name of this type + */ + public function getName() + { + return "category_associated_content_id"; + } +} diff --git a/core/lib/Thelia/Core/Form/Type/Field/CategoryIdType.php b/core/lib/Thelia/Core/Form/Type/Field/CategoryIdType.php new file mode 100644 index 00000000..eea3db53 --- /dev/null +++ b/core/lib/Thelia/Core/Form/Type/Field/CategoryIdType.php @@ -0,0 +1,43 @@ + + */ +class CategoryIdType extends AbstractIdType +{ + /** + * @return \Propel\Runtime\ActiveQuery\ModelCriteria + * + * Get the model query to check + */ + protected function getQuery() + { + return new CategoryQuery(); + } + + /** + * Returns the name of this type. + * + * @return string The name of this type + */ + public function getName() + { + return "category_id"; + } +} diff --git a/core/lib/Thelia/Core/Form/Type/Field/ContentIdType.php b/core/lib/Thelia/Core/Form/Type/Field/ContentIdType.php new file mode 100644 index 00000000..29f96424 --- /dev/null +++ b/core/lib/Thelia/Core/Form/Type/Field/ContentIdType.php @@ -0,0 +1,43 @@ + + */ +class ContentIdType extends AbstractIdType +{ + /** + * @return \Propel\Runtime\ActiveQuery\ModelCriteria + * + * Get the model query to check + */ + protected function getQuery() + { + return new ContentQuery(); + } + + /** + * Returns the name of this type. + * + * @return string The name of this type + */ + public function getName() + { + return 'content_id'; + } +} diff --git a/core/lib/Thelia/Core/Form/Type/Field/CountryIdType.php b/core/lib/Thelia/Core/Form/Type/Field/CountryIdType.php new file mode 100644 index 00000000..ef25f1a6 --- /dev/null +++ b/core/lib/Thelia/Core/Form/Type/Field/CountryIdType.php @@ -0,0 +1,43 @@ + + */ +class CountryIdType extends AbstractIdType +{ + /** + * @return \Propel\Runtime\ActiveQuery\ModelCriteria + * + * Get the model query to check + */ + protected function getQuery() + { + return new CountryQuery(); + } + + /** + * Returns the name of this type. + * + * @return string The name of this type + */ + public function getName() + { + return "country_id"; + } +} diff --git a/core/lib/Thelia/Core/Form/Type/Field/CouponIdType.php b/core/lib/Thelia/Core/Form/Type/Field/CouponIdType.php new file mode 100644 index 00000000..c8e30432 --- /dev/null +++ b/core/lib/Thelia/Core/Form/Type/Field/CouponIdType.php @@ -0,0 +1,43 @@ + + */ +class CouponIdType extends AbstractIdType +{ + /** + * @return \Propel\Runtime\ActiveQuery\ModelCriteria + * + * Get the model query to check + */ + protected function getQuery() + { + return new CouponQuery(); + } + + /** + * Returns the name of this type. + * + * @return string The name of this type + */ + public function getName() + { + return "coupon_id"; + } +} diff --git a/core/lib/Thelia/Core/Form/Type/Field/CurrencyIdType.php b/core/lib/Thelia/Core/Form/Type/Field/CurrencyIdType.php new file mode 100644 index 00000000..723f361e --- /dev/null +++ b/core/lib/Thelia/Core/Form/Type/Field/CurrencyIdType.php @@ -0,0 +1,43 @@ + + */ +class CurrencyIdType extends AbstractIdType +{ + /** + * @return \Propel\Runtime\ActiveQuery\ModelCriteria + * + * Get the model query to check + */ + protected function getQuery() + { + return new CurrencyQuery(); + } + + /** + * Returns the name of this type. + * + * @return string The name of this type + */ + public function getName() + { + return "currency_id"; + } +} diff --git a/core/lib/Thelia/Core/Form/Type/Field/CustomerIdType.php b/core/lib/Thelia/Core/Form/Type/Field/CustomerIdType.php new file mode 100644 index 00000000..fe77d627 --- /dev/null +++ b/core/lib/Thelia/Core/Form/Type/Field/CustomerIdType.php @@ -0,0 +1,43 @@ + + */ +class CustomerIdType extends AbstractIdType +{ + /** + * @return \Propel\Runtime\ActiveQuery\ModelCriteria + * + * Get the model query to check + */ + protected function getQuery() + { + return new CustomerQuery(); + } + + /** + * Returns the name of this type. + * + * @return string The name of this type + */ + public function getName() + { + return "customer_id"; + } +} diff --git a/core/lib/Thelia/Core/Form/Type/Field/CustomerTitleIdType.php b/core/lib/Thelia/Core/Form/Type/Field/CustomerTitleIdType.php new file mode 100644 index 00000000..9158e31d --- /dev/null +++ b/core/lib/Thelia/Core/Form/Type/Field/CustomerTitleIdType.php @@ -0,0 +1,43 @@ + + */ +class CustomerTitleIdType extends AbstractIdType +{ + /** + * @return \Propel\Runtime\ActiveQuery\ModelCriteria + * + * Get the model query to check + */ + protected function getQuery() + { + return new CustomerTitleQuery(); + } + + /** + * Returns the name of this type. + * + * @return string The name of this type + */ + public function getName() + { + return "customer_title_id"; + } +} diff --git a/core/lib/Thelia/Core/Form/Type/Field/ExportCategoryIdType.php b/core/lib/Thelia/Core/Form/Type/Field/ExportCategoryIdType.php new file mode 100644 index 00000000..236da77f --- /dev/null +++ b/core/lib/Thelia/Core/Form/Type/Field/ExportCategoryIdType.php @@ -0,0 +1,43 @@ + + */ +class ExportCategoryIdType extends AbstractIdType +{ + /** + * @return \Propel\Runtime\ActiveQuery\ModelCriteria + * + * Get the model query to check + */ + protected function getQuery() + { + return new ExportCategoryQuery(); + } + + /** + * Returns the name of this type. + * + * @return string The name of this type + */ + public function getName() + { + return "export_category_id"; + } +} diff --git a/core/lib/Thelia/Core/Form/Type/Field/ExportIdType.php b/core/lib/Thelia/Core/Form/Type/Field/ExportIdType.php new file mode 100644 index 00000000..3b418c49 --- /dev/null +++ b/core/lib/Thelia/Core/Form/Type/Field/ExportIdType.php @@ -0,0 +1,43 @@ + + */ +class ExportIdType extends AbstractIdType +{ + /** + * @return \Propel\Runtime\ActiveQuery\ModelCriteria + * + * Get the model query to check + */ + protected function getQuery() + { + return new ExportQuery(); + } + + /** + * Returns the name of this type. + * + * @return string The name of this type + */ + public function getName() + { + return "export_id"; + } +} diff --git a/core/lib/Thelia/Core/Form/Type/Field/FeatureAvIdType.php b/core/lib/Thelia/Core/Form/Type/Field/FeatureAvIdType.php new file mode 100644 index 00000000..5b62aece --- /dev/null +++ b/core/lib/Thelia/Core/Form/Type/Field/FeatureAvIdType.php @@ -0,0 +1,43 @@ + + */ +class FeatureAvIdType extends AbstractIdType +{ + /** + * @return \Propel\Runtime\ActiveQuery\ModelCriteria + * + * Get the model query to check + */ + protected function getQuery() + { + return new FeatureAvQuery(); + } + + /** + * Returns the name of this type. + * + * @return string The name of this type + */ + public function getName() + { + return "feature_av_id"; + } +} diff --git a/core/lib/Thelia/Core/Form/Type/Field/FeatureIdType.php b/core/lib/Thelia/Core/Form/Type/Field/FeatureIdType.php new file mode 100644 index 00000000..ce12c8c8 --- /dev/null +++ b/core/lib/Thelia/Core/Form/Type/Field/FeatureIdType.php @@ -0,0 +1,43 @@ + + */ +class FeatureIdType extends AbstractIdType +{ + /** + * @return \Propel\Runtime\ActiveQuery\ModelCriteria + * + * Get the model query to check + */ + protected function getQuery() + { + return new FeatureQuery(); + } + + /** + * Returns the name of this type. + * + * @return string The name of this type + */ + public function getName() + { + return "feature_id"; + } +} diff --git a/core/lib/Thelia/Core/Form/Type/Field/FeatureProductIdType.php b/core/lib/Thelia/Core/Form/Type/Field/FeatureProductIdType.php new file mode 100644 index 00000000..69f8bb52 --- /dev/null +++ b/core/lib/Thelia/Core/Form/Type/Field/FeatureProductIdType.php @@ -0,0 +1,43 @@ + + */ +class FeatureProductIdType extends AbstractIdType +{ + /** + * @return \Propel\Runtime\ActiveQuery\ModelCriteria + * + * Get the model query to check + */ + protected function getQuery() + { + return new FeatureProductQuery(); + } + + /** + * Returns the name of this type. + * + * @return string The name of this type + */ + public function getName() + { + return "feature_product_id"; + } +} diff --git a/core/lib/Thelia/Core/Form/Type/Field/FeatureTemplateIdType.php b/core/lib/Thelia/Core/Form/Type/Field/FeatureTemplateIdType.php new file mode 100644 index 00000000..5ec1acd3 --- /dev/null +++ b/core/lib/Thelia/Core/Form/Type/Field/FeatureTemplateIdType.php @@ -0,0 +1,43 @@ + + */ +class FeatureTemplateIdType extends AbstractIdType +{ + /** + * @return \Propel\Runtime\ActiveQuery\ModelCriteria + * + * Get the model query to check + */ + protected function getQuery() + { + return new FeatureTemplateQuery(); + } + + /** + * Returns the name of this type. + * + * @return string The name of this type + */ + public function getName() + { + return "feature_template_id"; + } +} diff --git a/core/lib/Thelia/Core/Form/Type/Field/FolderIdType.php b/core/lib/Thelia/Core/Form/Type/Field/FolderIdType.php new file mode 100644 index 00000000..146b5552 --- /dev/null +++ b/core/lib/Thelia/Core/Form/Type/Field/FolderIdType.php @@ -0,0 +1,43 @@ + + */ +class FolderIdType extends AbstractIdType +{ + /** + * @return \Propel\Runtime\ActiveQuery\ModelCriteria + * + * Get the model query to check + */ + protected function getQuery() + { + return new FolderQuery(); + } + + /** + * Returns the name of this type. + * + * @return string The name of this type + */ + public function getName() + { + return 'folder_id'; + } +} diff --git a/core/lib/Thelia/Core/Form/Type/Field/FormFirewallIdType.php b/core/lib/Thelia/Core/Form/Type/Field/FormFirewallIdType.php new file mode 100644 index 00000000..d9f455c8 --- /dev/null +++ b/core/lib/Thelia/Core/Form/Type/Field/FormFirewallIdType.php @@ -0,0 +1,43 @@ + + */ +class FormFirewallIdType extends AbstractIdType +{ + /** + * @return \Propel\Runtime\ActiveQuery\ModelCriteria + * + * Get the model query to check + */ + protected function getQuery() + { + return new FormFirewallQuery(); + } + + /** + * Returns the name of this type. + * + * @return string The name of this type + */ + public function getName() + { + return "form_firewall_id"; + } +} diff --git a/core/lib/Thelia/Core/Form/Type/Field/HookIdType.php b/core/lib/Thelia/Core/Form/Type/Field/HookIdType.php new file mode 100644 index 00000000..ea09d6ef --- /dev/null +++ b/core/lib/Thelia/Core/Form/Type/Field/HookIdType.php @@ -0,0 +1,43 @@ + + */ +class HookIdType extends AbstractIdType +{ + /** + * @return \Propel\Runtime\ActiveQuery\ModelCriteria + * + * Get the model query to check + */ + protected function getQuery() + { + return new HookQuery(); + } + + /** + * Returns the name of this type. + * + * @return string The name of this type + */ + public function getName() + { + return "hook_id"; + } +} diff --git a/core/lib/Thelia/Core/Form/Type/Field/ImportCategoryIdType.php b/core/lib/Thelia/Core/Form/Type/Field/ImportCategoryIdType.php new file mode 100644 index 00000000..8ee09858 --- /dev/null +++ b/core/lib/Thelia/Core/Form/Type/Field/ImportCategoryIdType.php @@ -0,0 +1,43 @@ + + */ +class ImportCategoryIdType extends AbstractIdType +{ + /** + * @return \Propel\Runtime\ActiveQuery\ModelCriteria + * + * Get the model query to check + */ + protected function getQuery() + { + return new ImportCategoryQuery(); + } + + /** + * Returns the name of this type. + * + * @return string The name of this type + */ + public function getName() + { + return "import_category_id"; + } +} diff --git a/core/lib/Thelia/Core/Form/Type/Field/ImportIdType.php b/core/lib/Thelia/Core/Form/Type/Field/ImportIdType.php new file mode 100644 index 00000000..0c55f4f5 --- /dev/null +++ b/core/lib/Thelia/Core/Form/Type/Field/ImportIdType.php @@ -0,0 +1,43 @@ + + */ +class ImportIdType extends AbstractIdType +{ + /** + * @return \Propel\Runtime\ActiveQuery\ModelCriteria + * + * Get the model query to check + */ + protected function getQuery() + { + return new ImportQuery(); + } + + /** + * Returns the name of this type. + * + * @return string The name of this type + */ + public function getName() + { + return "import_id"; + } +} diff --git a/core/lib/Thelia/Core/Form/Type/Field/LangIdType.php b/core/lib/Thelia/Core/Form/Type/Field/LangIdType.php new file mode 100644 index 00000000..6ede5421 --- /dev/null +++ b/core/lib/Thelia/Core/Form/Type/Field/LangIdType.php @@ -0,0 +1,43 @@ + + */ +class LangIdType extends AbstractIdType +{ + /** + * @return \Propel\Runtime\ActiveQuery\ModelCriteria + * + * Get the model query to check + */ + protected function getQuery() + { + return new LangQuery(); + } + + /** + * Returns the name of this type. + * + * @return string The name of this type + */ + public function getName() + { + return "lang_id"; + } +} diff --git a/core/lib/Thelia/Core/Form/Type/Field/MessageIdType.php b/core/lib/Thelia/Core/Form/Type/Field/MessageIdType.php new file mode 100644 index 00000000..ad2262da --- /dev/null +++ b/core/lib/Thelia/Core/Form/Type/Field/MessageIdType.php @@ -0,0 +1,43 @@ + + */ +class MessageIdType extends AbstractIdType +{ + /** + * @return \Propel\Runtime\ActiveQuery\ModelCriteria + * + * Get the model query to check + */ + protected function getQuery() + { + return new MessageQuery(); + } + + /** + * Returns the name of this type. + * + * @return string The name of this type + */ + public function getName() + { + return "message_id"; + } +} diff --git a/core/lib/Thelia/Core/Form/Type/Field/MetaDataIdType.php b/core/lib/Thelia/Core/Form/Type/Field/MetaDataIdType.php new file mode 100644 index 00000000..4c10a766 --- /dev/null +++ b/core/lib/Thelia/Core/Form/Type/Field/MetaDataIdType.php @@ -0,0 +1,43 @@ + + */ +class MetaDataIdType extends AbstractIdType +{ + /** + * @return \Propel\Runtime\ActiveQuery\ModelCriteria + * + * Get the model query to check + */ + protected function getQuery() + { + return new MetaDataQuery(); + } + + /** + * Returns the name of this type. + * + * @return string The name of this type + */ + public function getName() + { + return "meta_data_id"; + } +} diff --git a/core/lib/Thelia/Core/Form/Type/Field/ModuleConfigIdType.php b/core/lib/Thelia/Core/Form/Type/Field/ModuleConfigIdType.php new file mode 100644 index 00000000..8c72e0da --- /dev/null +++ b/core/lib/Thelia/Core/Form/Type/Field/ModuleConfigIdType.php @@ -0,0 +1,43 @@ + + */ +class ModuleConfigIdType extends AbstractIdType +{ + /** + * @return \Propel\Runtime\ActiveQuery\ModelCriteria + * + * Get the model query to check + */ + protected function getQuery() + { + return new ModuleConfigQuery(); + } + + /** + * Returns the name of this type. + * + * @return string The name of this type + */ + public function getName() + { + return "module_config_id"; + } +} diff --git a/core/lib/Thelia/Core/Form/Type/Field/ModuleHookIdType.php b/core/lib/Thelia/Core/Form/Type/Field/ModuleHookIdType.php new file mode 100644 index 00000000..f6033743 --- /dev/null +++ b/core/lib/Thelia/Core/Form/Type/Field/ModuleHookIdType.php @@ -0,0 +1,43 @@ + + */ +class ModuleHookIdType extends AbstractIdType +{ + /** + * @return \Propel\Runtime\ActiveQuery\ModelCriteria + * + * Get the model query to check + */ + protected function getQuery() + { + return new ModuleHookQuery(); + } + + /** + * Returns the name of this type. + * + * @return string The name of this type + */ + public function getName() + { + return "module_hook_id"; + } +} diff --git a/core/lib/Thelia/Core/Form/Type/Field/ModuleIdType.php b/core/lib/Thelia/Core/Form/Type/Field/ModuleIdType.php new file mode 100644 index 00000000..cb7493b9 --- /dev/null +++ b/core/lib/Thelia/Core/Form/Type/Field/ModuleIdType.php @@ -0,0 +1,43 @@ + + */ +class ModuleIdType extends AbstractIdType +{ + /** + * @return \Propel\Runtime\ActiveQuery\ModelCriteria + * + * Get the model query to check + */ + protected function getQuery() + { + return new ModuleQuery(); + } + + /** + * Returns the name of this type. + * + * @return string The name of this type + */ + public function getName() + { + return "module_id"; + } +} diff --git a/core/lib/Thelia/Core/Form/Type/Field/NewsletterIdType.php b/core/lib/Thelia/Core/Form/Type/Field/NewsletterIdType.php new file mode 100644 index 00000000..424005b0 --- /dev/null +++ b/core/lib/Thelia/Core/Form/Type/Field/NewsletterIdType.php @@ -0,0 +1,43 @@ + + */ +class NewsletterIdType extends AbstractIdType +{ + /** + * @return \Propel\Runtime\ActiveQuery\ModelCriteria + * + * Get the model query to check + */ + protected function getQuery() + { + return new NewsletterQuery(); + } + + /** + * Returns the name of this type. + * + * @return string The name of this type + */ + public function getName() + { + return "newsletter_id"; + } +} diff --git a/core/lib/Thelia/Core/Form/Type/Field/OrderAddressIdType.php b/core/lib/Thelia/Core/Form/Type/Field/OrderAddressIdType.php new file mode 100644 index 00000000..80d0e5c3 --- /dev/null +++ b/core/lib/Thelia/Core/Form/Type/Field/OrderAddressIdType.php @@ -0,0 +1,43 @@ + + */ +class OrderAddressIdType extends AbstractIdType +{ + /** + * @return \Propel\Runtime\ActiveQuery\ModelCriteria + * + * Get the model query to check + */ + protected function getQuery() + { + return new OrderAddressQuery(); + } + + /** + * Returns the name of this type. + * + * @return string The name of this type + */ + public function getName() + { + return "order_address_id"; + } +} diff --git a/core/lib/Thelia/Core/Form/Type/Field/OrderCouponIdType.php b/core/lib/Thelia/Core/Form/Type/Field/OrderCouponIdType.php new file mode 100644 index 00000000..d37ea9af --- /dev/null +++ b/core/lib/Thelia/Core/Form/Type/Field/OrderCouponIdType.php @@ -0,0 +1,43 @@ + + */ +class OrderCouponIdType extends AbstractIdType +{ + /** + * @return \Propel\Runtime\ActiveQuery\ModelCriteria + * + * Get the model query to check + */ + protected function getQuery() + { + return new OrderCouponQuery(); + } + + /** + * Returns the name of this type. + * + * @return string The name of this type + */ + public function getName() + { + return "order_coupon_id"; + } +} diff --git a/core/lib/Thelia/Core/Form/Type/Field/OrderIdType.php b/core/lib/Thelia/Core/Form/Type/Field/OrderIdType.php new file mode 100644 index 00000000..38f782db --- /dev/null +++ b/core/lib/Thelia/Core/Form/Type/Field/OrderIdType.php @@ -0,0 +1,43 @@ + + */ +class OrderIdType extends AbstractIdType +{ + /** + * @return \Propel\Runtime\ActiveQuery\ModelCriteria + * + * Get the model query to check + */ + protected function getQuery() + { + return new OrderQuery(); + } + + /** + * Returns the name of this type. + * + * @return string The name of this type + */ + public function getName() + { + return "order_id"; + } +} diff --git a/core/lib/Thelia/Core/Form/Type/Field/OrderProductAttributeCombinationIdType.php b/core/lib/Thelia/Core/Form/Type/Field/OrderProductAttributeCombinationIdType.php new file mode 100644 index 00000000..95bf3fcb --- /dev/null +++ b/core/lib/Thelia/Core/Form/Type/Field/OrderProductAttributeCombinationIdType.php @@ -0,0 +1,43 @@ + + */ +class OrderProductAttributeCombinationIdType extends AbstractIdType +{ + /** + * @return \Propel\Runtime\ActiveQuery\ModelCriteria + * + * Get the model query to check + */ + protected function getQuery() + { + return new OrderProductAttributeCombinationQuery(); + } + + /** + * Returns the name of this type. + * + * @return string The name of this type + */ + public function getName() + { + return "order_product_attribute_combination_id"; + } +} diff --git a/core/lib/Thelia/Core/Form/Type/Field/OrderProductIdType.php b/core/lib/Thelia/Core/Form/Type/Field/OrderProductIdType.php new file mode 100644 index 00000000..dd893b3e --- /dev/null +++ b/core/lib/Thelia/Core/Form/Type/Field/OrderProductIdType.php @@ -0,0 +1,43 @@ + + */ +class OrderProductIdType extends AbstractIdType +{ + /** + * @return \Propel\Runtime\ActiveQuery\ModelCriteria + * + * Get the model query to check + */ + protected function getQuery() + { + return new OrderProductQuery(); + } + + /** + * Returns the name of this type. + * + * @return string The name of this type + */ + public function getName() + { + return "order_product_id"; + } +} diff --git a/core/lib/Thelia/Core/Form/Type/Field/OrderProductTaxIdType.php b/core/lib/Thelia/Core/Form/Type/Field/OrderProductTaxIdType.php new file mode 100644 index 00000000..036f85e1 --- /dev/null +++ b/core/lib/Thelia/Core/Form/Type/Field/OrderProductTaxIdType.php @@ -0,0 +1,43 @@ + + */ +class OrderProductTaxIdType extends AbstractIdType +{ + /** + * @return \Propel\Runtime\ActiveQuery\ModelCriteria + * + * Get the model query to check + */ + protected function getQuery() + { + return new OrderProductTaxQuery(); + } + + /** + * Returns the name of this type. + * + * @return string The name of this type + */ + public function getName() + { + return "order_product_tax_id"; + } +} diff --git a/core/lib/Thelia/Core/Form/Type/Field/OrderStatusIdType.php b/core/lib/Thelia/Core/Form/Type/Field/OrderStatusIdType.php new file mode 100644 index 00000000..20fce378 --- /dev/null +++ b/core/lib/Thelia/Core/Form/Type/Field/OrderStatusIdType.php @@ -0,0 +1,43 @@ + + */ +class OrderStatusIdType extends AbstractIdType +{ + /** + * @return \Propel\Runtime\ActiveQuery\ModelCriteria + * + * Get the model query to check + */ + protected function getQuery() + { + return new OrderStatusQuery(); + } + + /** + * Returns the name of this type. + * + * @return string The name of this type + */ + public function getName() + { + return "order_status_id"; + } +} diff --git a/core/lib/Thelia/Core/Form/Type/Field/ProductAssociatedContentIdType.php b/core/lib/Thelia/Core/Form/Type/Field/ProductAssociatedContentIdType.php new file mode 100644 index 00000000..6ff0fb8b --- /dev/null +++ b/core/lib/Thelia/Core/Form/Type/Field/ProductAssociatedContentIdType.php @@ -0,0 +1,43 @@ + + */ +class ProductAssociatedContentIdType extends AbstractIdType +{ + /** + * @return \Propel\Runtime\ActiveQuery\ModelCriteria + * + * Get the model query to check + */ + protected function getQuery() + { + return new ProductAssociatedContentQuery(); + } + + /** + * Returns the name of this type. + * + * @return string The name of this type + */ + public function getName() + { + return "product_associated_content_id"; + } +} diff --git a/core/lib/Thelia/Core/Form/Type/Field/ProductIdType.php b/core/lib/Thelia/Core/Form/Type/Field/ProductIdType.php new file mode 100644 index 00000000..812afa77 --- /dev/null +++ b/core/lib/Thelia/Core/Form/Type/Field/ProductIdType.php @@ -0,0 +1,42 @@ + + */ +class ProductIdType extends AbstractIdType +{ + /** + * @return \Propel\Runtime\ActiveQuery\ModelCriteria + * + * Get the model query to check + */ + protected function getQuery() + { + return new ProductQuery(); + } + + /** + * Returns the name of this type. + * + * @return string The name of this type + */ + public function getName() + { + return "product_id"; + } +} diff --git a/core/lib/Thelia/Core/Form/Type/Field/ProductSaleElementsIdType.php b/core/lib/Thelia/Core/Form/Type/Field/ProductSaleElementsIdType.php new file mode 100644 index 00000000..9f4b4601 --- /dev/null +++ b/core/lib/Thelia/Core/Form/Type/Field/ProductSaleElementsIdType.php @@ -0,0 +1,43 @@ + + */ +class ProductSaleElementsIdType extends AbstractIdType +{ + /** + * @return \Propel\Runtime\ActiveQuery\ModelCriteria + * + * Get the model query to check + */ + protected function getQuery() + { + return new ProductSaleElementsQuery(); + } + + /** + * Returns the name of this type. + * + * @return string The name of this type + */ + public function getName() + { + return "product_sale_elements_id"; + } +} diff --git a/core/lib/Thelia/Core/Form/Type/Field/ProfileIdType.php b/core/lib/Thelia/Core/Form/Type/Field/ProfileIdType.php new file mode 100644 index 00000000..8955b29d --- /dev/null +++ b/core/lib/Thelia/Core/Form/Type/Field/ProfileIdType.php @@ -0,0 +1,43 @@ + + */ +class ProfileIdType extends AbstractIdType +{ + /** + * @return \Propel\Runtime\ActiveQuery\ModelCriteria + * + * Get the model query to check + */ + protected function getQuery() + { + return new ProfileQuery(); + } + + /** + * Returns the name of this type. + * + * @return string The name of this type + */ + public function getName() + { + return "profile_id"; + } +} diff --git a/core/lib/Thelia/Core/Form/Type/Field/ResourceIdType.php b/core/lib/Thelia/Core/Form/Type/Field/ResourceIdType.php new file mode 100644 index 00000000..e35076ec --- /dev/null +++ b/core/lib/Thelia/Core/Form/Type/Field/ResourceIdType.php @@ -0,0 +1,43 @@ + + */ +class ResourceIdType extends AbstractIdType +{ + /** + * @return \Propel\Runtime\ActiveQuery\ModelCriteria + * + * Get the model query to check + */ + protected function getQuery() + { + return new ResourceQuery(); + } + + /** + * Returns the name of this type. + * + * @return string The name of this type + */ + public function getName() + { + return "resource_id"; + } +} diff --git a/core/lib/Thelia/Core/Form/Type/Field/RewritingUrlIdType.php b/core/lib/Thelia/Core/Form/Type/Field/RewritingUrlIdType.php new file mode 100644 index 00000000..38f4de4d --- /dev/null +++ b/core/lib/Thelia/Core/Form/Type/Field/RewritingUrlIdType.php @@ -0,0 +1,43 @@ + + */ +class RewritingUrlIdType extends AbstractIdType +{ + /** + * @return \Propel\Runtime\ActiveQuery\ModelCriteria + * + * Get the model query to check + */ + protected function getQuery() + { + return new RewritingUrlQuery(); + } + + /** + * Returns the name of this type. + * + * @return string The name of this type + */ + public function getName() + { + return "rewriting_url_id"; + } +} diff --git a/core/lib/Thelia/Core/Form/Type/Field/SaleIdType.php b/core/lib/Thelia/Core/Form/Type/Field/SaleIdType.php new file mode 100644 index 00000000..9ecfeb45 --- /dev/null +++ b/core/lib/Thelia/Core/Form/Type/Field/SaleIdType.php @@ -0,0 +1,43 @@ + + */ +class SaleIdType extends AbstractIdType +{ + /** + * @return \Propel\Runtime\ActiveQuery\ModelCriteria + * + * Get the model query to check + */ + protected function getQuery() + { + return new SaleQuery(); + } + + /** + * Returns the name of this type. + * + * @return string The name of this type + */ + public function getName() + { + return "sale_id"; + } +} diff --git a/core/lib/Thelia/Core/Form/Type/Field/SaleProductIdType.php b/core/lib/Thelia/Core/Form/Type/Field/SaleProductIdType.php new file mode 100644 index 00000000..fb2bd656 --- /dev/null +++ b/core/lib/Thelia/Core/Form/Type/Field/SaleProductIdType.php @@ -0,0 +1,43 @@ + + */ +class SaleProductIdType extends AbstractIdType +{ + /** + * @return \Propel\Runtime\ActiveQuery\ModelCriteria + * + * Get the model query to check + */ + protected function getQuery() + { + return new SaleProductQuery(); + } + + /** + * Returns the name of this type. + * + * @return string The name of this type + */ + public function getName() + { + return "sale_product_id"; + } +} diff --git a/core/lib/Thelia/Core/Form/Type/Field/StateIdType.php b/core/lib/Thelia/Core/Form/Type/Field/StateIdType.php new file mode 100644 index 00000000..9a1d0272 --- /dev/null +++ b/core/lib/Thelia/Core/Form/Type/Field/StateIdType.php @@ -0,0 +1,43 @@ + + */ +class StateIdType extends AbstractIdType +{ + /** + * @return \Propel\Runtime\ActiveQuery\ModelCriteria + * + * Get the model query to check + */ + protected function getQuery() + { + return new StateQuery(); + } + + /** + * Returns the name of this type. + * + * @return string The name of this type + */ + public function getName() + { + return "state_id"; + } +} diff --git a/core/lib/Thelia/Core/Form/Type/Field/TaxIdType.php b/core/lib/Thelia/Core/Form/Type/Field/TaxIdType.php new file mode 100644 index 00000000..3794a6af --- /dev/null +++ b/core/lib/Thelia/Core/Form/Type/Field/TaxIdType.php @@ -0,0 +1,43 @@ + + */ +class TaxIdType extends AbstractIdType +{ + /** + * @return \Propel\Runtime\ActiveQuery\ModelCriteria + * + * Get the model query to check + */ + protected function getQuery() + { + return new TaxQuery(); + } + + /** + * Returns the name of this type. + * + * @return string The name of this type + */ + public function getName() + { + return "tax_id"; + } +} diff --git a/core/lib/Thelia/Core/Form/Type/Field/TaxRuleIdType.php b/core/lib/Thelia/Core/Form/Type/Field/TaxRuleIdType.php new file mode 100644 index 00000000..98e70294 --- /dev/null +++ b/core/lib/Thelia/Core/Form/Type/Field/TaxRuleIdType.php @@ -0,0 +1,43 @@ + + */ +class TaxRuleIdType extends AbstractIdType +{ + /** + * @return \Propel\Runtime\ActiveQuery\ModelCriteria + * + * Get the model query to check + */ + protected function getQuery() + { + return new TaxRuleQuery(); + } + + /** + * Returns the name of this type. + * + * @return string The name of this type + */ + public function getName() + { + return "tax_rule_id"; + } +} diff --git a/core/lib/Thelia/Core/Form/Type/Field/TemplateIdType.php b/core/lib/Thelia/Core/Form/Type/Field/TemplateIdType.php new file mode 100644 index 00000000..21ffb0a4 --- /dev/null +++ b/core/lib/Thelia/Core/Form/Type/Field/TemplateIdType.php @@ -0,0 +1,43 @@ + + */ +class TemplateIdType extends AbstractIdType +{ + /** + * @return \Propel\Runtime\ActiveQuery\ModelCriteria + * + * Get the model query to check + */ + protected function getQuery() + { + return new TemplateQuery(); + } + + /** + * Returns the name of this type. + * + * @return string The name of this type + */ + public function getName() + { + return "template_id"; + } +} diff --git a/core/lib/Thelia/Core/Form/Type/ImageType.php b/core/lib/Thelia/Core/Form/Type/ImageType.php new file mode 100644 index 00000000..fe718b45 --- /dev/null +++ b/core/lib/Thelia/Core/Form/Type/ImageType.php @@ -0,0 +1,45 @@ + + */ +class ImageType extends AbstractTheliaType +{ + public function buildForm(FormBuilderInterface $builder, array $options) + { + $builder + ->add("i18n", "collection", array( + "type" => "standard_fields", + "allow_add" => true, + "allow_delete" => true, + "cascade_validation" => true, + )) + ; + } + + /** + * Returns the name of this type. + * + * @return string The name of this type + */ + public function getName() + { + return "image"; + } +} diff --git a/core/lib/Thelia/Core/Form/Type/ProductSaleElementsType.php b/core/lib/Thelia/Core/Form/Type/ProductSaleElementsType.php new file mode 100644 index 00000000..69757625 --- /dev/null +++ b/core/lib/Thelia/Core/Form/Type/ProductSaleElementsType.php @@ -0,0 +1,138 @@ + + */ +class ProductSaleElementsType extends AbstractTheliaType +{ + protected $productIdType; + protected $pseIdType; + + /** + * @param ProductIdType $productIdType + * @param ProductSaleElementsIdType $pseIdType + * + * The types are needed to load the validation groups + */ + public function __construct(ProductIdType $productIdType, ProductSaleElementsIdType $pseIdType) + { + $this->productIdType = $productIdType; + + $this->pseIdType = $pseIdType; + } + + /** + * @param OptionsResolver $resolver + * + * Always allow cascade validation for types + */ + public function configureOptions(OptionsResolver $resolver) + { + $resolver->setDefaults([ + "cascade_validation" => true, + ]); + } + + /** + * @param FormBuilderInterface $builder + * @param array $options + */ + public function buildForm(FormBuilderInterface $builder, array $options) + { + $builder + ->add("reference", "text", array( + "required" => false, + )) + ->add("price", "number", array( + "required" => false, + "constraints" => array( + new GreaterThanOrEqual(["value" => 0]), + ), + )) + ->add("price_with_tax", "number", array( + "required" => false, + "constraints" => array( + new GreaterThanOrEqual(["value" => 0]), + ), + )) + ->add("weight", "number", array( + "required" => false, + "constraints" => array( + new GreaterThanOrEqual(["value" => 0]), + ), + )) + ->add("quantity", "number", array( + "required" => false, + "constraints" => array( + new GreaterThanOrEqual(["value" => 0]), + ), + )) + ->add("sale_price", "number", array( + "required" => false, + "constraints" => array( + new GreaterThanOrEqual(["value" => 0]), + ), + )) + ->add("sale_price_with_tax", "number", array( + "required" => false, + "constraints" => array( + new GreaterThanOrEqual(["value" => 0]), + ), + )) + ->add("ean_code", "text", array( + "required" => false, + )) + ->add("attribute_av", "collection", array( + "type" => "attribute_av", + "required" => false, + "allow_add" => true, + )) + ->add("tax_rule_id", "tax_rule_id") + ->add("currency_id", "currency_id") + ->add("onsale", "checkbox") + ->add("isnew", "checkbox") + ->add("isdefault", "checkbox") + ->add("use_exchange_rate", "checkbox") + + // Only on create + ->add("product_id", "product_id", array( + "constraints" => $this->getConstraints($this->productIdType, "create"), + )) + + // Only on update + ->add("id", "product_sale_elements_id", array( + "constraints" => $this->getConstraints($this->pseIdType, "update"), + )) + ; + } + + /** + * Returns the name of this type. + * + * @return string The name of this type + */ + public function getName() + { + return "product_sale_elements"; + } +} diff --git a/core/lib/Thelia/Core/Form/Type/StandardFieldsType.php b/core/lib/Thelia/Core/Form/Type/StandardFieldsType.php new file mode 100644 index 00000000..dacab953 --- /dev/null +++ b/core/lib/Thelia/Core/Form/Type/StandardFieldsType.php @@ -0,0 +1,45 @@ + + */ +class StandardFieldsType extends AbstractType +{ + protected $formBuilder; + + use StandardDescriptionFieldsTrait; + + public function buildForm(FormBuilderInterface $builder, array $options) + { + $this->formBuilder = $builder; + $this->addStandardDescFields(); + } + + /** + * Returns the name of this type. + * + * @return string The name of this type + */ + public function getName() + { + return "standard_fields"; + } +} diff --git a/core/lib/Thelia/Core/Form/Type/TaxRuleI18nType.php b/core/lib/Thelia/Core/Form/Type/TaxRuleI18nType.php new file mode 100644 index 00000000..99abef46 --- /dev/null +++ b/core/lib/Thelia/Core/Form/Type/TaxRuleI18nType.php @@ -0,0 +1,58 @@ + + */ +class TaxRuleI18nType extends AbstractTheliaType +{ + use StandardDescriptionFieldsTrait; + + /** + * @var FormBuilderInterface + * + * This is used for compatibility with the StandardDescriptionFieldsTrait + */ + protected $formBuilder; + + public function configureOptions(OptionsResolver $resolver) + { + $resolver->setDefaults([ + "cascade_validation" => true, + ]); + } + + public function buildForm(FormBuilderInterface $builder, array $options) + { + $this->formBuilder = $builder; + + $this->addStandardDescFields(["chapo", "postscriptum"]); + } + + /** + * Returns the name of this type. + * + * @return string The name of this type + */ + public function getName() + { + return "tax_rule_i18n"; + } +} diff --git a/core/lib/Thelia/Core/Form/Type/TaxRuleType.php b/core/lib/Thelia/Core/Form/Type/TaxRuleType.php new file mode 100644 index 00000000..bb75e9e2 --- /dev/null +++ b/core/lib/Thelia/Core/Form/Type/TaxRuleType.php @@ -0,0 +1,90 @@ + + */ +class TaxRuleType extends AbstractTheliaType +{ + /** + * @var \Thelia\Core\Form\Type\Field\TaxRuleIdType + */ + protected $taxRuleIdType; + + public function __construct(TaxRuleIdType $taxRuleIdType) + { + $this->taxRuleIdType = $taxRuleIdType; + } + + public function configureOptions(OptionsResolver $resolver) + { + $resolver->setDefaults([ + "cascade_validation" => true, + ]); + } + + public function buildForm(FormBuilderInterface $builder, array $options) + { + $builder + ->add("default", "checkbox") + ->add("country", "collection", array( + "type" => "country_id", + "allow_add" => true, + "allow_delete" => true, + "cascade_validation" => "true", + "constraints" => array( + new Count(["min" => 1]), + ), + )) + ->add("tax", "collection", array( + "type" => "tax_id", + "allow_add" => true, + "allow_delete" => true, + "cascade_validation" => "true", + "constraints" => array( + new Count(["min" => 1]), + ), + )) + ->add("i18n", "collection", array( + "type" => "tax_rule_i18n", + "required" => true, + "allow_add" => true, + "cascade_validation" => true, + "constraints" => array( + new Count(["min" => 1]), + ), + )) + ->add("id", "tax_rule_id", array( + "constraints" => $this->getConstraints($this->taxRuleIdType, "update"), + )) + ; + } + + /** + * Returns the name of this type. + * + * @return string The name of this type + */ + public function getName() + { + return "tax_rule"; + } +} diff --git a/core/lib/Thelia/Core/Form/Type/TheliaType.php b/core/lib/Thelia/Core/Form/Type/TheliaType.php new file mode 100644 index 00000000..b95a4d66 --- /dev/null +++ b/core/lib/Thelia/Core/Form/Type/TheliaType.php @@ -0,0 +1,52 @@ +setDefaults(array( + 'type' => false, + 'options' => false, + )); + + $resolver->setAllowedValues('type', array('text', 'choice')); + } + + /** + * {@inheritdoc} + */ + public function buildView(FormView $view, FormInterface $form, array $options) + { + $view->vars = array_replace($view->vars, array( + 'type' => $options['type'], + 'options' => $options['options'], + )); + } + + public function getParent() + { + return 'text'; + } + + public function getName() + { + return 'thelia_type'; + } +} diff --git a/core/lib/Thelia/Core/Hook/BaseHook.php b/core/lib/Thelia/Core/Hook/BaseHook.php new file mode 100644 index 00000000..faf294c6 --- /dev/null +++ b/core/lib/Thelia/Core/Hook/BaseHook.php @@ -0,0 +1,445 @@ + + */ +abstract class BaseHook +{ + const INJECT_TEMPLATE_METHOD_NAME = "insertTemplate"; + + /** @var BaseModule */ + public $module = null; + + /** @var array list of templates automatically injected */ + protected $templates = []; + + /** @var \Thelia\Core\Template\ParserInterface */ + public $parser = null; + + /** @var TranslatorInterface $translator */ + public $translator = null; + + /** @var AssetResolverInterface $assetsResolver */ + public $assetsResolver = null; + + /** @var EventDispatcherInterface */ + public $dispatcher = null; + + /** @var Request $request */ + protected $request = null; + + /** @var Session $session */ + protected $session = null; + + /** @var Customer $customer */ + protected $customer = null; + + /** @var Cart $cart */ + protected $cart = null; + + /** @var Order $order */ + protected $order = null; + + /** @var Lang $lang */ + protected $lang = null; + + /** @var Currency $currency */ + protected $currency = null; + + /** + * This function is called when hook uses the automatic insert template. + * + * @param HookRenderEvent $event + * @param string $code + */ + public function insertTemplate(HookRenderEvent $event, $code) + { + if (array_key_exists($code, $this->templates)) { + $templates = explode(';', $this->templates[$code]); + + // Concatenate arguments and template variables, + // giving the precedence to arguments. + $allArguments = $event->getTemplateVars() + $event->getArguments(); + + foreach ($templates as $template) { + list($type, $filepath) = $this->getTemplateParams($template); + + if ("render" === $type) { + $event->add($this->render($filepath, $allArguments)); + continue; + } + + if ("dump" === $type) { + $event->add($this->render($filepath)); + continue; + } + + if ("css" === $type) { + $event->add($this->addCSS($filepath)); + continue; + } + + if ("js" === $type) { + $event->add($this->addJS($filepath)); + continue; + } + + if (method_exists($this, $type)) { + $this->{$type}($filepath, $allArguments); + } + } + } + } + + /** + * helper function allowing you to render a template using a template engine + * + * @param string $templateName the template path of the template + * @param array $parameters an array of parameters to assign to a template engine + * + * @return string the content generated by a template engine + */ + public function render($templateName, array $parameters = array()) + { + $templateDir = $this->assetsResolver->resolveAssetSourcePath($this->module->getCode(), false, $templateName, $this->parser); + + if (null !== $templateDir) { + // retrieve the template + $content = $this->parser->render($templateDir . DS . $templateName, $parameters); + } else { + $content = sprintf("ERR: Unknown template %s for module %s", $templateName, $this->module->getCode()); + } + + return $content; + } + + /** + * helper function allowing you to get the content of a file + * + * @param string $fileName the template path of the template + * + * @return string the content of the file + */ + public function dump($fileName) + { + $fileDir = $this->assetsResolver->resolveAssetSourcePath($this->module->getCode(), false, $fileName, $this->parser); + + if (null !== $fileDir) { + $content = file_get_contents($fileDir . DS . $fileName); + if (false === $content) { + $content = ""; + } + } else { + $content = sprintf("ERR: Unknown file %s for module %s", $fileName, $this->module->getCode()); + } + + return $content; + } + + /** + * helper function allowing you to generate the HTML link tag + * + * @param string $fileName the path to the css file + * @param array $attributes the attributes of the tag + * @param array $filters an array of assets processing filters (less, sass, etc.) + * + * @return string the link tag + */ + public function addCSS($fileName, $attributes = [], $filters = []) + { + $tag = ""; + + $url = $this->assetsResolver->resolveAssetURL($this->module->getCode(), $fileName, "css", $this->parser, $filters); + + if ("" !== $url) { + $tags = array(); + $tags[] = ' $val) { + if (\is_string($name) && !\in_array($name, [ "href", "rel", "type" ])) { + $tags[] = $name . '="' . $val . '" '; + } + } + $tags[] = "/>"; + $tag = implode($tags); + } + + return $tag; + } + + /** + * helper function allowing you to generate the HTML script tag + * + * @param string $fileName the path to the js file + * @param array $attributes the attributes of the tag + * @param array $filters an array of assets processing filters (cofeescript, compress, etc.) + * + * @return string the script tag + */ + public function addJS($fileName, $attributes = array(), $filters = []) + { + $tag = ""; + + $url = $this->assetsResolver->resolveAssetURL($this->module->getCode(), $fileName, "js", $this->parser, $filters); + + if ("" !== $url) { + $tags = array(); + $tags[] = '"; + $tag = implode($tags); + } + + return $tag; + } + + /** + * @param \Thelia\Module\BaseModule $module + */ + public function setModule($module) + { + $this->module = $module; + } + + /** + * @return \Thelia\Module\BaseModule + */ + public function getModule() + { + return $this->module; + } + + /** + * @param \Thelia\Core\Template\ParserInterface $parser + */ + public function setParser(ParserInterface $parser) + { + $this->parser = $parser; + } + + /** + * @return \Thelia\Core\Template\ParserInterface + */ + public function getParser() + { + return $this->parser; + } + + /** + * Translates the given message. + * + * @param string $id The message id (may also be an object that can be cast to string) + * @param array $parameters An array of parameters for the message + * @param string $domain The domain for the message + * @param string $locale The locale + * + * @return string The translated string + * + * @api + */ + protected function trans($id, array $parameters = array(), $domain = null, $locale = null) + { + return $this->translator->trans($id, $parameters, $domain, $locale); + } + + /** + * get the request + * + * @return Request + */ + protected function getRequest() + { + if (null === $this->request) { + $this->request = $this->getParser()->getRequest(); + } + + return $this->request; + } + + /** + * get the session + * + * @return Session + */ + protected function getSession() + { + if (null === $this->session) { + if (null !== $this->getRequest()) { + $this->session = $this->request->getSession(); + } + } + + return $this->session; + } + + /** + * Get the view argument for the request. + * + * It allows you to identify the page currently displayed. eg: index, category, ... + * + * @return string the current view + */ + protected function getView() + { + $ret = ""; + if (null !== $this->getRequest()) { + $ret = $this->getRequest()->attributes->get("_view", ""); + } + + return $ret; + } + + /** + * Get the cart from the session + * + * @return \Thelia\Model\Cart|null + */ + protected function getCart() + { + if (null === $this->cart) { + $this->cart = $this->getSession() ? $this->getSession()->getSessionCart($this->dispatcher) : null; + } + + return $this->cart; + } + + /** + * Get the order from the session + * + * @return \Thelia\Model\Order|null + */ + protected function getOrder() + { + if (null === $this->order) { + $this->order = $this->getSession() ? $this->getSession()->getOrder() : null; + } + + return $this->order; + } + + /** + * Get the current currency used or if not present the default currency for the shop + * + * @return \Thelia\Model\Currency + */ + protected function getCurrency() + { + if (null === $this->currency) { + $this->currency = $this->getSession() ? $this->getSession()->getCurrency(true) : Currency::getDefaultCurrency(); + } + + return $this->currency; + } + + /** + * Get the current customer logged in. If no customer is logged return null + * + * @return \Thelia\Model\Customer|null + */ + protected function getCustomer() + { + if (null === $this->customer) { + $this->customer = $this->getSession() ? $this->getSession()->getCustomerUser() : null; + } + + return $this->customer; + } + + /** + * Get the current lang used or if not present the default lang for the shop + * + * @return \Thelia\Model\Lang + */ + protected function getLang() + { + if (null === $this->lang) { + $this->lang = $this->getSession() ? $this->getSession()->getLang(true) : $this->lang = Lang::getDefaultLanguage(); + } + + return $this->lang; + } + + /** + * Add a new template for automatic render + * + * @param string $hookCode the code of the hook (the name of the event used to render) : 'hook.{type}.{hook code}' + * @param string $value list of the template to render or add. + * eg: 'render:mytemplate.html;css:assets/css/mycss.css;js:assets/js/myjs.js' + */ + public function addTemplate($hookCode, $value) + { + if (array_key_exists($hookCode, $this->templates)) { + throw new \InvalidArgumentException(sprintf("The hook '%s' is already used in this class.", $hookCode)); + } + + $this->templates[$hookCode] = $value; + } + + /** + * @return array templates + */ + public function getTemplates() + { + return $this->templates; + } + + /** + * @param $template + * @return array + */ + protected function getTemplateParams($template) + { + $templateParams = explode(':', $template); + + if (\count($templateParams) > 1) { + $type = $templateParams[0]; + $filepath = $templateParams[1]; + } else { + $type = 'render'; + $filepath = $templateParams[0]; + } + + return [$type, $filepath]; + } +} diff --git a/core/lib/Thelia/Core/Hook/DefaultHook.php b/core/lib/Thelia/Core/Hook/DefaultHook.php new file mode 100644 index 00000000..c180a28b --- /dev/null +++ b/core/lib/Thelia/Core/Hook/DefaultHook.php @@ -0,0 +1,23 @@ + + */ +class DefaultHook extends BaseHook +{ +} diff --git a/core/lib/Thelia/Core/Hook/Fragment.php b/core/lib/Thelia/Core/Hook/Fragment.php new file mode 100644 index 00000000..14baffd9 --- /dev/null +++ b/core/lib/Thelia/Core/Hook/Fragment.php @@ -0,0 +1,77 @@ + + */ +class Fragment +{ + protected $data; + + public function __construct($data = array()) + { + if (!\is_array($data)) { + throw new \InvalidArgumentException("'data' argument must be an array"); + } + $this->data = $data; + } + + public function set($key, $value) + { + $this->data[$key] = $value === null ? '' : $value; + + return $this; + } + + public function get($key) + { + if (array_key_exists($key, $this->data)) { + return $this->data[$key]; + } + + return null; + } + + public function __get($key) + { + return $this->get($key); + } + + public function getVarVal() + { + return $this->data; + } + + public function getVars() + { + return array_keys($this->data); + } + + public function filter(array $fields, $default = null) + { + if (empty($fields)) { + return; + } + + $data = []; + + foreach ($fields as $field) { + $data[$field] = (array_key_exists($field, $this->data)) ? $this->data[$field] : $default; + } + + $this->data = $data; + } +} diff --git a/core/lib/Thelia/Core/Hook/FragmentBag.php b/core/lib/Thelia/Core/Hook/FragmentBag.php new file mode 100644 index 00000000..52428c83 --- /dev/null +++ b/core/lib/Thelia/Core/Hook/FragmentBag.php @@ -0,0 +1,134 @@ + + */ +class FragmentBag implements Iterator +{ + private $position; + + /** @var array $fragments */ + protected $fragments; + + public function __construct() + { + $this->position = 0; + $this->fragments = array(); + } + + /** + * (PHP 5 >= 5.0.0)
    + * Return the current element + * @link http://php.net/manual/en/iterator.current.php + * @return mixed Can return any type. + */ + public function current() + { + return $this->fragments[$this->position]; + } + + /** + * (PHP 5 >= 5.0.0)
    + * Move forward to next element + * @link http://php.net/manual/en/iterator.next.php + * @return void Any returned value is ignored. + */ + public function next() + { + ++$this->position; + } + + /** + * (PHP 5 >= 5.0.0)
    + * Return the key of the current element + * @link http://php.net/manual/en/iterator.key.php + * @return mixed scalar on success, or null on failure. + */ + public function key() + { + return $this->position; + } + + /** + * (PHP 5 >= 5.0.0)
    + * Checks if current position is valid + * @link http://php.net/manual/en/iterator.valid.php + * @return boolean The return value will be casted to boolean and then evaluated. + * Returns true on success or false on failure. + */ + public function valid() + { + return isset($this->fragments[$this->position]); + } + + /** + * (PHP 5 >= 5.0.0)
    + * Rewind the Iterator to the first element + * @link http://php.net/manual/en/iterator.rewind.php + * @return void Any returned value is ignored. + */ + public function rewind() + { + $this->position = 0; + } + + /** + * Clears all parameters. + * + * @api + */ + public function clear() + { + $this->position = 0; + $this->fragments = array(); + } + + public function isEmpty() + { + return \count($this->fragments) == 0; + } + + public function getCount() + { + return \count($this->fragments); + } + + public function add($data) + { + $fragment = new Fragment($data); + $this->addFragment($fragment); + } + + public function addFragment(Fragment $fragment) + { + $this->fragments[] = $fragment; + } + + /** + * Gets the all keys fragment. + * + * @return array An array of parameters + * + * @api + */ + public function keys() + { + return array_keys($this->fragments); + } +} diff --git a/core/lib/Thelia/Core/Hook/HookDefinition.php b/core/lib/Thelia/Core/Hook/HookDefinition.php new file mode 100644 index 00000000..08db36ef --- /dev/null +++ b/core/lib/Thelia/Core/Hook/HookDefinition.php @@ -0,0 +1,26 @@ + + */ +class HookDefinition +{ + const BASE_CLASS = 'Thelia\Core\Hook\BaseHook'; + + const RENDER_BLOCK_EVENT = 'Thelia\Core\Event\Hook\HookRenderBlockEvent'; + const RENDER_FUNCTION_EVENT = 'Thelia\Core\Event\Hook\HookRenderEvent'; +} diff --git a/core/lib/Thelia/Core/Hook/HookHelper.php b/core/lib/Thelia/Core/Hook/HookHelper.php new file mode 100644 index 00000000..7e16e7c6 --- /dev/null +++ b/core/lib/Thelia/Core/Hook/HookHelper.php @@ -0,0 +1,539 @@ + + */ +class HookHelper +{ + /** @var array messages used to build title for hooks */ + protected $messages = array(); + + /** + * @var ParserHelperInterface + */ + protected $parserHelper; + + public function __construct(ParserHelperInterface $parserHelper) + { + $this->parserHelper = $parserHelper; + } + + /** + * @param int $templateType + * @return array + * @throws \Exception + */ + public function parseActiveTemplate($templateType = TemplateDefinition::FRONT_OFFICE) + { + switch ($templateType) { + case TemplateDefinition::FRONT_OFFICE: + $tplVar = 'active-front-template'; + break; + case TemplateDefinition::BACK_OFFICE: + $tplVar = 'active-admin-template'; + break; + case TemplateDefinition::PDF: + $tplVar = 'active-pdf-template'; + break; + case TemplateDefinition::EMAIL: + $tplVar = 'active-mail-template'; + break; + default: + throw new TheliaProcessException("Unknown template type: $templateType"); + } + + return $this->parseTemplate($templateType, ConfigQuery::read($tplVar, 'default')); + } + + /** + * @param int $templateType + * @param string $template + * @return array an array of hooks descriptors + * @throws \Exception + */ + public function parseTemplate($templateType, $template) + { + $templateDefinition = new TemplateDefinition($template, $templateType); + + $hooks = array(); + $this->walkDir($templateDefinition->getAbsolutePath(), $hooks); + + // Also parse parent templates + /** @var TemplateDefinition $parentTemplate */ + foreach ($templateDefinition->getParentList() as $parentTemplate) { + $this->walkDir($parentTemplate->getAbsolutePath(), $hooks); + } + + // load language message + $locale = Lang::getDefaultLanguage()->getLocale(); + $this->loadTrans($templateType, $locale); + + $ret = array(); + foreach ($hooks as $hook) { + try { + $ret[] = $this->prepareHook($hook); + } catch (\UnexpectedValueException $ex) { + Tlog::getInstance()->warning($ex->getMessage()); + } + } + + return $ret; + } + + /** + * Recursively examine files in a directory tree, and extract translatable strings. + * + * Returns an array of translatable strings, each item having with the following structure: + * 'files' an array of file names in which the string appears, + * 'text' the translatable text + * 'translation' => the text translation, or an empty string if none available. + * 'dollar' => true if the translatable text contains a $ + * + * @param string $directory the path to the directory to examine + * @param $hooks + * + * @internal param string $walkMode type of file scanning: WALK_MODE_PHP or WALK_MODE_TEMPLATE + * @internal param \Thelia\Core\Translation\Translator $translator the current translator + * @internal param string $currentLocale the current locale + * @internal param string $domain the translation domain (fontoffice, backoffice, module, etc...) + * @internal param array $strings the list of strings + */ + public function walkDir($directory, &$hooks) + { + $allowed_exts = array('html', 'tpl', 'xml', 'txt'); + + try { + /** @var \DirectoryIterator $fileInfo */ + foreach (new \DirectoryIterator($directory) as $fileInfo) { + if ($fileInfo->isDot()) { + continue; + } + + if ($fileInfo->isDir()) { + $this->walkDir($fileInfo->getPathName(), $hooks); + } + + if ($fileInfo->isFile()) { + $ext = $fileInfo->getExtension(); + + if (\in_array($ext, $allowed_exts)) { + if ($content = file_get_contents($fileInfo->getPathName())) { + foreach ($this->parserHelper->getFunctionsDefinition($content, array("hook", "hookblock")) as $hook) { + $hook['file'] = $fileInfo->getFilename(); + $hooks[] = $hook; + } + } + } + } + } + } catch (\UnexpectedValueException $ex) { + // Directory does not exists => ignore/ + } + } + + protected function prepareHook($hook) + { + $ret = array(); + if (!array_key_exists("attributes", $hook)) { + throw new \UnexpectedValueException("The hook should have attributes."); + } + + $attributes = $hook['attributes']; + + if (array_key_exists("name", $attributes)) { + $ret['block'] = ($hook['name'] !== 'hook'); + + $ret['code'] = $attributes['name']; + $params = explode(".", $attributes['name']); + + if (\count($params) != 2) { + // the hook does not respect the convention + if (false === strpos($attributes['name'], "$")) { + $ret['context'] = $attributes['name']; + $ret['type'] = ''; + } else { + throw new \UnexpectedValueException("skipping hook as name contains variable : " . $attributes['name']); + } + } else { + $ret['context'] = $params[0]; + $ret['type'] = $params[1]; + } + unset($attributes['name']); + + $ret['module'] = false; + if (array_key_exists("module", $attributes)) { + $ret['module'] = true; + unset($attributes['module']); + } + + // vars + if ($ret['block'] && array_key_exists("vars", $attributes)) { + unset($attributes['vars']); + $ret['vars'] = explode(",", $attributes['vars']); + } + + // get a title + $contextTitle = $this->trans("context", $ret['context']) ? : $ret['context']; + $typeTitle = $this->trans("type", $ret['type']) ? : $ret['type']; + $ret['title'] = sprintf("%s - %s", $contextTitle, $typeTitle); + $ret['file'] = $hook['file']; + $ret['attributes'] = $attributes; + } else { + throw new \UnexpectedValueException("The hook should have a name attribute."); + } + + return $ret; + } + + protected function normalizePath($path) + { + $path = str_replace( + str_replace('\\', '/', THELIA_ROOT), + '', + str_replace('\\', '/', realpath($path)) + ); + + return ltrim($path, '/'); + } + + /** + * Translate Hook labels + * + * @param $context + * @param $key + * @return string + */ + protected function trans($context, $key) + { + $message = ""; + + if (array_key_exists($context, $this->messages)) { + if (array_key_exists($key, $this->messages[$context])) { + $message = $this->messages[$context][$key]; + } + } + + return $message; + } + + protected function loadTrans($templateType, $locale) + { + switch ($templateType) { + case TemplateDefinition::FRONT_OFFICE: + $this->loadFrontOfficeTrans($locale); + break; + case TemplateDefinition::BACK_OFFICE: + $this->loadBackOfficeTrans($locale); + break; + case TemplateDefinition::PDF: + $this->loadPdfOfficeTrans($locale); + break; + case TemplateDefinition::EMAIL: + $this->loadEmailTrans($locale); + break; + } + } + + protected function loadFrontOfficeTrans($locale) + { + $t = Translator::getInstance(); + + $this->messages["context"]["404"] = $t->trans("Page 404", array(), "core", $locale); + $this->messages["context"]["account"] = $t->trans("customer account", array(), "core", $locale); + $this->messages["context"]["account-password"] = $t->trans("Change password", array(), "core", $locale); + $this->messages["context"]["account-update"] = $t->trans("Update customer account", array(), "core", $locale); + $this->messages["context"]["address-create"] = $t->trans("Address creation", array(), "core", $locale); + $this->messages["context"]["address-update"] = $t->trans("Address update", array(), "core", $locale); + $this->messages["context"]["badresponseorder"] = $t->trans("Payment failed", array(), "core", $locale); + $this->messages["context"]["cart"] = $t->trans("Cart", array(), "core", $locale); + $this->messages["context"]["category"] = $t->trans("Category page", array(), "core", $locale); + $this->messages["context"]["contact"] = $t->trans("Contact page", array(), "core", $locale); + $this->messages["context"]["content"] = $t->trans("Content page", array(), "core", $locale); + $this->messages["context"]["currency"] = $t->trans("Curency selection page", array(), "core", $locale); + $this->messages["context"]["folder"] = $t->trans("Folder page", array(), "core", $locale); + $this->messages["context"]["home"] = $t->trans("Home page", array(), "core", $locale); + $this->messages["context"]["language"] = $t->trans("language selection page", array(), "core", $locale); + $this->messages["context"]["login"] = $t->trans("Login page", array(), "core", $locale); + $this->messages["context"]["main"] = $t->trans("HTML layout", array(), "core", $locale); + $this->messages["context"]["newsletter"] = $t->trans("Newsletter page", array(), "core", $locale); + $this->messages["context"]["order-delivery"] = $t->trans("Delivery choice", array(), "core", $locale); + $this->messages["context"]["order-failed"] = $t->trans("Order failed", array(), "core", $locale); + $this->messages["context"]["order-invoice"] = $t->trans("Invoice choice", array(), "core", $locale); + $this->messages["context"]["order-payment-gateway"] = $t->trans("Payment gateway", array(), "core", $locale); + $this->messages["context"]["order-placed"] = $t->trans("Placed order", array(), "core", $locale); + $this->messages["context"]["password"] = $t->trans("Lost password", array(), "core", $locale); + $this->messages["context"]["product"] = $t->trans("Product page", array(), "core", $locale); + $this->messages["context"]["register"] = $t->trans("Register", array(), "core", $locale); + $this->messages["context"]["search"] = $t->trans("Search page", array(), "core", $locale); + $this->messages["context"]["singleproduct"] = $t->trans("Product loop", array(), "core", $locale); + $this->messages["context"]["sitemap"] = $t->trans("Sitemap", array(), "core", $locale); + $this->messages["context"]["viewall"] = $t->trans("All Products", array(), "core", $locale); + + $this->messages["type"]["additional"] = $t->trans("additional information", array(), "core", $locale); + $this->messages["type"]["after-javascript-include"] = $t->trans("after javascript include", array(), "core", $locale); + $this->messages["type"]["after-javascript-initialization"] = $t->trans("after javascript initialisation", array(), "core", $locale); + $this->messages["type"]["body"] = $t->trans("main area", array(), "core", $locale); + $this->messages["type"]["body-bottom"] = $t->trans("before the end body tag", array(), "core", $locale); + $this->messages["type"]["body-top"] = $t->trans("after the opening of the body tag", array(), "core", $locale); + $this->messages["type"]["bottom"] = $t->trans("at the bottom", array(), "core", $locale); + $this->messages["type"]["content"] = $t->trans("content area", array(), "core", $locale); + $this->messages["type"]["content-bottom"] = $t->trans("after the main content area", array(), "core", $locale); + $this->messages["type"]["content-top"] = $t->trans("before the main content area", array(), "core", $locale); + $this->messages["type"]["delivery-address"] = $t->trans("delivery address", array(), "core", $locale); + $this->messages["type"]["details-bottom"] = $t->trans("at the bottom of the detail area", array(), "core", $locale); + $this->messages["type"]["details-top"] = $t->trans("at the top of the detail", array(), "core", $locale); + $this->messages["type"]["extra"] = $t->trans("extra area", array(), "core", $locale); + $this->messages["type"]["footer-body"] = $t->trans("footer body", array(), "core", $locale); + $this->messages["type"]["footer-bottom"] = $t->trans("bottom of the footer", array(), "core", $locale); + $this->messages["type"]["footer-top"] = $t->trans("at the top of the footer", array(), "core", $locale); + $this->messages["type"]["form-bottom"] = $t->trans("at the bottom of the form", array(), "core", $locale); + $this->messages["type"]["form-top"] = $t->trans("at the top of the form", array(), "core", $locale); + $this->messages["type"]["gallery"] = $t->trans("photo gallery", array(), "core", $locale); + $this->messages["type"]["head-bottom"] = $t->trans("before the end of the head tag", array(), "core", $locale); + $this->messages["type"]["head-top"] = $t->trans("after the opening of the head tag", array(), "core", $locale); + $this->messages["type"]["header-bottom"] = $t->trans("at the bottom of the header", array(), "core", $locale); + $this->messages["type"]["header-top"] = $t->trans("at the top of the header", array(), "core", $locale); + $this->messages["type"]["javascript"] = $t->trans("javascript", array(), "core", $locale); + $this->messages["type"]["javascript-initialization"] = $t->trans("javascript initialization", array(), "core", $locale); + $this->messages["type"]["main-bottom"] = $t->trans("at the bottom of the main area", array(), "core", $locale); + $this->messages["type"]["main-top"] = $t->trans("at the top of the main area", array(), "core", $locale); + $this->messages["type"]["navbar-primary"] = $t->trans("primary navigation", array(), "core", $locale); + $this->messages["type"]["navbar-secondary"] = $t->trans("secondary navigation", array(), "core", $locale); + $this->messages["type"]["payment-extra"] = $t->trans("extra payment zone", array(), "core", $locale); + $this->messages["type"]["sidebar-body"] = $t->trans("the body of the sidebar", array(), "core", $locale); + $this->messages["type"]["sidebar-bottom"] = $t->trans("at the bottom of the sidebar", array(), "core", $locale); + $this->messages["type"]["sidebar-top"] = $t->trans("at the top of the sidebar", array(), "core", $locale); + $this->messages["type"]["stylesheet"] = $t->trans("CSS stylesheet", array(), "core", $locale); + $this->messages["type"]["success"] = $t->trans("if successful response", array(), "core", $locale); + $this->messages["type"]["top"] = $t->trans("at the top", array(), "core", $locale); + } + + protected function loadBackOfficeTrans($locale) + { + $t = Translator::getInstance(); + + $this->messages["context"]["admin-logs"] = $t->trans("Logs", array(), "core", $locale); + $this->messages["context"]["administrator"] = $t->trans("Administrator", array(), "core", $locale); + $this->messages["context"]["administrators"] = $t->trans("Administrators", array(), "core", $locale); + $this->messages["context"]["attribute"] = $t->trans("Attribut", array(), "core", $locale); + $this->messages["context"]["attribute-value"] = $t->trans("Attribute value", array(), "core", $locale); + $this->messages["context"]["attributes"] = $t->trans("Attributes", array(), "core", $locale); + $this->messages["context"]["attributes-value"] = $t->trans("Attributes value", array(), "core", $locale); + $this->messages["context"]["catalog"] = $t->trans("Catalog", array(), "core", $locale); + $this->messages["context"]["catalog-configuration"] = $t->trans("Catalog configuration", array(), "core", $locale); + $this->messages["context"]["categories"] = $t->trans("Categories", array(), "core", $locale); + $this->messages["context"]["category"] = $t->trans("Category", array(), "core", $locale); + $this->messages["context"]["config-store"] = $t->trans("Store Information", array(), "core", $locale); + $this->messages["context"]["configuration"] = $t->trans("Configuration", array(), "core", $locale); + $this->messages["context"]["content"] = $t->trans("Content", array(), "core", $locale); + $this->messages["context"]["contents"] = $t->trans("Contents", array(), "core", $locale); + $this->messages["context"]["countries"] = $t->trans("Countries", array(), "core", $locale); + $this->messages["context"]["country"] = $t->trans("Country", array(), "core", $locale); + $this->messages["context"]["coupon"] = $t->trans("Coupon", array(), "core", $locale); + $this->messages["context"]["currencies"] = $t->trans("Currencies", array(), "core", $locale); + $this->messages["context"]["currency"] = $t->trans("Currency", array(), "core", $locale); + $this->messages["context"]["customer"] = $t->trans("Customer", array(), "core", $locale); + $this->messages["context"]["customers"] = $t->trans("Customers", array(), "core", $locale); + $this->messages["context"]["document"] = $t->trans("Document", array(), "core", $locale); + $this->messages["context"]["export"] = $t->trans("Export", array(), "core", $locale); + $this->messages["context"]["feature"] = $t->trans("Feature", array(), "core", $locale); + $this->messages["context"]["features"] = $t->trans("Features", array(), "core", $locale); + $this->messages["context"]["features-value"] = $t->trans("Features value", array(), "core", $locale); + $this->messages["context"]["folder"] = $t->trans("Folder", array(), "core", $locale); + $this->messages["context"]["folders"] = $t->trans("Folder", array(), "core", $locale); + $this->messages["context"]["home"] = $t->trans("Home", array(), "core", $locale); + $this->messages["context"]["hook"] = $t->trans("Hook", array(), "core", $locale); + $this->messages["context"]["hooks"] = $t->trans("Hooks", array(), "core", $locale); + $this->messages["context"]["image"] = $t->trans("Image", array(), "core", $locale); + $this->messages["context"]["index"] = $t->trans("Dashboard", array(), "core", $locale); + $this->messages["context"]["language"] = $t->trans("Language", array(), "core", $locale); + $this->messages["context"]["languages"] = $t->trans("Languages", array(), "core", $locale); + $this->messages["context"]["mailing-system"] = $t->trans("Mailing system", array(), "core", $locale); + $this->messages["context"]["main"] = $t->trans("Layout", array(), "core", $locale); + $this->messages["context"]["message"] = $t->trans("Message", array(), "core", $locale); + $this->messages["context"]["messages"] = $t->trans("Messages", array(), "core", $locale); + $this->messages["context"]["module"] = $t->trans("Module", array(), "core", $locale); + $this->messages["context"]["module-hook"] = $t->trans("Module hook", array(), "core", $locale); + $this->messages["context"]["modules"] = $t->trans("Modules", array(), "core", $locale); + $this->messages["context"]["order"] = $t->trans("Order", array(), "core", $locale); + $this->messages["context"]["orders"] = $t->trans("Orders", array(), "core", $locale); + $this->messages["context"]["product"] = $t->trans("Product", array(), "core", $locale); + $this->messages["context"]["products"] = $t->trans("Products", array(), "core", $locale); + $this->messages["context"]["profile"] = $t->trans("Profile", array(), "core", $locale); + $this->messages["context"]["profiles"] = $t->trans("Profiles", array(), "core", $locale); + $this->messages["context"]["search"] = $t->trans("Search", array(), "core", $locale); + $this->messages["context"]["shipping-configuration"] = $t->trans("Shipping configuration", array(), "core", $locale); + $this->messages["context"]["shipping-zones"] = $t->trans("Delivery zone", array(), "core", $locale); + $this->messages["context"]["system"] = $t->trans("System", array(), "core", $locale); + $this->messages["context"]["system-configuration"] = $t->trans("System configuration", array(), "core", $locale); + $this->messages["context"]["tax"] = $t->trans("Tax", array(), "core", $locale); + $this->messages["context"]["tax-rule"] = $t->trans("tax rule", array(), "core", $locale); + $this->messages["context"]["taxes"] = $t->trans("Taxes", array(), "core", $locale); + $this->messages["context"]["taxes-rules"] = $t->trans("Taxes rules", array(), "core", $locale); + $this->messages["context"]["template"] = $t->trans("Template", array(), "core", $locale); + $this->messages["context"]["templates"] = $t->trans("Templates", array(), "core", $locale); + $this->messages["context"]["tools"] = $t->trans("Tools", array(), "core", $locale); + $this->messages["context"]["translations"] = $t->trans("Translations", array(), "core", $locale); + $this->messages["context"]["variable"] = $t->trans("Variable", array(), "core", $locale); + $this->messages["context"]["variables"] = $t->trans("Variables", array(), "core", $locale); + $this->messages["context"]["zone"] = $t->trans("Zone", array(), "core", $locale); + $this->messages["context"]["brand"] = $t->trans("Brand", array(), "core", $locale); + $this->messages["context"]["brands"] = $t->trans("Brands", array(), "core", $locale); + $this->messages["context"]["home"] = $t->trans("Home", array(), "core", $locale); + $this->messages["context"]["main"] = $t->trans("Layout", array(), "core", $locale); + $this->messages["type"]["block"] = $t->trans("block", array(), "core", $locale); + $this->messages["type"]["bottom"] = $t->trans("bottom", array(), "core", $locale); + $this->messages["type"]["create-form"] = $t->trans("create form", array(), "core", $locale); + $this->messages["type"]["delete-form"] = $t->trans("delete form", array(), "core", $locale); + $this->messages["type"]["edit-js"] = $t->trans("Edit JavaScript", array(), "core", $locale); + $this->messages["type"]["js"] = $t->trans("JavaScript", array(), "core", $locale); + $this->messages["type"]["table-header"] = $t->trans("table header", array(), "core", $locale); + $this->messages["type"]["table-row"] = $t->trans("table row", array(), "core", $locale); + $this->messages["type"]["top"] = $t->trans("at the top", array(), "core", $locale); + $this->messages["type"]["top-menu-catalog"] = $t->trans("in the menu catalog", array(), "core", $locale); + $this->messages["type"]["top-menu-configuration"] = $t->trans("in the menu configuration", array(), "core", $locale); + $this->messages["type"]["top-menu-content"] = $t->trans("in the menu folders", array(), "core", $locale); + $this->messages["type"]["top-menu-customer"] = $t->trans("in the menu customers", array(), "core", $locale); + $this->messages["type"]["top-menu-modules"] = $t->trans("in the menu modules", array(), "core", $locale); + $this->messages["type"]["top-menu-order"] = $t->trans("in the menu orders", array(), "core", $locale); + $this->messages["type"]["top-menu-tools"] = $t->trans("in the menu tools", array(), "core", $locale); + $this->messages["type"]["topbar-bottom"] = $t->trans("at the bottom of the top bar", array(), "core", $locale); + $this->messages["type"]["topbar-top"] = $t->trans("at the top of the top bar", array(), "core", $locale); + $this->messages["type"]["accessories-table-header"] = $t->trans("accessories table header", array(), "core", $locale); + $this->messages["type"]["accessories-table-row"] = $t->trans("accessories table row", array(), "core", $locale); + $this->messages["type"]["add-to-all-form"] = $t->trans("add to all form", array(), "core", $locale); + $this->messages["type"]["address-create-form"] = $t->trans("address create form", array(), "core", $locale); + $this->messages["type"]["address-delete-form"] = $t->trans("address delete form", array(), "core", $locale); + $this->messages["type"]["address-update-form"] = $t->trans("address update form", array(), "core", $locale); + $this->messages["type"]["after-combinations"] = $t->trans("after combinations", array(), "core", $locale); + $this->messages["type"]["after-footer"] = $t->trans("after footer", array(), "core", $locale); + $this->messages["type"]["after-top-menu"] = $t->trans("after top menu", array(), "core", $locale); + $this->messages["type"]["after-topbar"] = $t->trans("after top bar", array(), "core", $locale); + $this->messages["type"]["attributes-table-header"] = $t->trans("attributes table header", array(), "core", $locale); + $this->messages["type"]["attributes-table-row"] = $t->trans("attributes table row", array(), "core", $locale); + $this->messages["type"]["before-combinations"] = $t->trans("before combinations", array(), "core", $locale); + $this->messages["type"]["before-footer"] = $t->trans("before footer", array(), "core", $locale); + $this->messages["type"]["before-top-menu"] = $t->trans("before top menu", array(), "core", $locale); + $this->messages["type"]["before-topbar"] = $t->trans("before topbar", array(), "core", $locale); + $this->messages["type"]["bottom"] = $t->trans("bottom", array(), "core", $locale); + $this->messages["type"]["caption"] = $t->trans("caption", array(), "core", $locale); + $this->messages["type"]["catalog-bottom"] = $t->trans("at the bottom of the catalog", array(), "core", $locale); + $this->messages["type"]["catalog-top"] = $t->trans("at the top of the catalog area", array(), "core", $locale); + $this->messages["type"]["categories-table-header"] = $t->trans("categories table header", array(), "core", $locale); + $this->messages["type"]["categories-table-row"] = $t->trans("categories table row", array(), "core", $locale); + $this->messages["type"]["col1-bottom"] = $t->trans("at the bottom of column 1", array(), "core", $locale); + $this->messages["type"]["col1-top"] = $t->trans("at the top of the column", array(), "core", $locale); + $this->messages["type"]["combination-delete-form"] = $t->trans("combination delete form", array(), "core", $locale); + $this->messages["type"]["combinations-list-caption"] = $t->trans("combinations list caption", array(), "core", $locale); + $this->messages["type"]["config-js"] = $t->trans("configuration JavaScript", array(), "core", $locale); + $this->messages["type"]["configuration"] = $t->trans("configuration", array(), "core", $locale); + $this->messages["type"]["configuration-bottom"] = $t->trans("configuration bottom", array(), "core", $locale); + $this->messages["type"]["configuration-top"] = $t->trans("at the top of the configuration", array(), "core", $locale); + $this->messages["type"]["content-create-form"] = $t->trans(" content create form", array(), "core", $locale); + $this->messages["type"]["content-delete-form"] = $t->trans("content delete form", array(), "core", $locale); + $this->messages["type"]["content-edit-js"] = $t->trans("content edit JavaScript", array(), "core", $locale); + $this->messages["type"]["contents-table-header"] = $t->trans("contents table header", array(), "core", $locale); + $this->messages["type"]["contents-table-row"] = $t->trans("contents table row", array(), "core", $locale); + $this->messages["type"]["country-delete-form"] = $t->trans("country delete form", array(), "core", $locale); + $this->messages["type"]["create-form"] = $t->trans("create form", array(), "core", $locale); + $this->messages["type"]["create-js"] = $t->trans("create JavaScript", array(), "core", $locale); + $this->messages["type"]["delete-form"] = $t->trans("delete form", array(), "core", $locale); + $this->messages["type"]["details-details-form"] = $t->trans("stock edit form", array(), "core", $locale); + $this->messages["type"]["details-pricing-form"] = $t->trans("details pricing form", array(), "core", $locale); + $this->messages["type"]["details-promotion-form"] = $t->trans("details promotion form", array(), "core", $locale); + $this->messages["type"]["edit"] = $t->trans("Edit", array(), "core", $locale); + $this->messages["type"]["edit-js"] = $t->trans("Edit JavaScript", array(), "core", $locale); + $this->messages["type"]["features-table-header"] = $t->trans("features-table-header", array(), "core", $locale); + $this->messages["type"]["features-table-row"] = $t->trans("features table row", array(), "core", $locale); + $this->messages["type"]["folders-table-header"] = $t->trans("folders table header", array(), "core", $locale); + $this->messages["type"]["folders-table-row"] = $t->trans("folders table row", array(), "core", $locale); + $this->messages["type"]["footer-js"] = $t->trans("JavaScript", array(), "core", $locale); + $this->messages["type"]["head-css"] = $t->trans("CSS", array(), "core", $locale); + $this->messages["type"]["header"] = $t->trans("header", array(), "core", $locale); + $this->messages["type"]["hook-create-form"] = $t->trans("Hook create form", array(), "core", $locale); + $this->messages["type"]["hook-delete-form"] = $t->trans("hook delete form", array(), "core", $locale); + $this->messages["type"]["hook-edit-js"] = $t->trans("hook edit JavaScript", array(), "core", $locale); + $this->messages["type"]["id-delete-form"] = $t->trans("id delete form", array(), "core", $locale); + $this->messages["type"]["in-footer"] = $t->trans("in footer", array(), "core", $locale); + $this->messages["type"]["in-top-menu-items"] = $t->trans("in top menu items", array(), "core", $locale); + $this->messages["type"]["inside-topbar"] = $t->trans("inside top bar", array(), "core", $locale); + $this->messages["type"]["js"] = $t->trans("JavaScript", array(), "core", $locale); + $this->messages["type"]["list-caption"] = $t->trans("list caption", array(), "core", $locale); + $this->messages["type"]["list-header"] = $t->trans("list header", array(), "core", $locale); + $this->messages["type"]["list-js"] = $t->trans("list JavaScript", array(), "core", $locale); + $this->messages["type"]["list-row"] = $t->trans("list row", array(), "core", $locale); + $this->messages["type"]["logs-js"] = $t->trans("logs JavaScript", array(), "core", $locale); + $this->messages["type"]["mailing-system-js"] = $t->trans("email system JavaScript", array(), "core", $locale); + $this->messages["type"]["main"] = $t->trans("Main area", array(), "core", $locale); + $this->messages["type"]["middle"] = $t->trans("middle", array(), "core", $locale); + $this->messages["type"]["product-list"] = $t->trans("product list", array(), "core", $locale); + $this->messages["type"]["remove-to-all-form"] = $t->trans("remove to all form", array(), "core", $locale); + $this->messages["type"]["row"] = $t->trans("row", array(), "core", $locale); + $this->messages["type"]["rule-create-form"] = $t->trans("rule create form", array(), "core", $locale); + $this->messages["type"]["rule-delete-form"] = $t->trans("rule delete form", array(), "core", $locale); + $this->messages["type"]["rule-edit-js"] = $t->trans("rule edit JavaScript", array(), "core", $locale); + $this->messages["type"]["shipping-bottom"] = $t->trans("at the bottom of the shipping area", array(), "core", $locale); + $this->messages["type"]["shipping-top"] = $t->trans("at the top of the shipping area", array(), "core", $locale); + $this->messages["type"]["system-bottom"] = $t->trans("at the bottom of the system area", array(), "core", $locale); + $this->messages["type"]["system-top"] = $t->trans("at the top of the system area", array(), "core", $locale); + $this->messages["type"]["tab-content"] = $t->trans("content", array(), "core", $locale); + $this->messages["type"]["table-header"] = $t->trans("table header", array(), "core", $locale); + $this->messages["type"]["table-row"] = $t->trans("table row", array(), "core", $locale); + $this->messages["type"]["top"] = $t->trans("at the top", array(), "core", $locale); + $this->messages["type"]["update-form"] = $t->trans("update form", array(), "core", $locale); + $this->messages["type"]["update-js"] = $t->trans("update JavaScript", array(), "core", $locale); + $this->messages["type"]["value-create-form"] = $t->trans("Value create form", array(), "core", $locale); + $this->messages["type"]["value-table-header"] = $t->trans("value table header", array(), "core", $locale); + $this->messages["type"]["value-table-row"] = $t->trans("value table row", array(), "core", $locale); + } + + protected function loadPdfOfficeTrans($locale) + { + $t = Translator::getInstance(); + + $this->messages["context"]["delivery"] = $t->trans("Delivery", array(), "core", $locale); + $this->messages["context"]["invoice"] = $t->trans("Invoice", array(), "core", $locale); + $this->messages["type"]["after-addresses"] = $t->trans("after addresse area", array(), "core", $locale); + $this->messages["type"]["after-information"] = $t->trans("after the information area", array(), "core", $locale); + $this->messages["type"]["after-products"] = $t->trans("after product listing", array(), "core", $locale); + $this->messages["type"]["after-summary"] = $t->trans("after the order summary", array(), "core", $locale); + $this->messages["type"]["css"] = $t->trans("CSS", array(), "core", $locale); + $this->messages["type"]["delivery-address"] = $t->trans("delivery address", array(), "core", $locale); + $this->messages["type"]["footer-bottom"] = $t->trans("at the bottom of the footer", array(), "core", $locale); + $this->messages["type"]["footer-top"] = $t->trans("at the top of the footer", array(), "core", $locale); + $this->messages["type"]["header"] = $t->trans("in the header", array(), "core", $locale); + $this->messages["type"]["imprint"] = $t->trans("imprint", array(), "core", $locale); + $this->messages["type"]["information"] = $t->trans("at the bottom of information area", array(), "core", $locale); + } + + /** + * This method do nothing for now + * + * @param $locale + */ + protected function loadEmailTrans($locale) + { + } +} diff --git a/core/lib/Thelia/Core/HttpFoundation/JsonResponse.php b/core/lib/Thelia/Core/HttpFoundation/JsonResponse.php new file mode 100644 index 00000000..b93b81d9 --- /dev/null +++ b/core/lib/Thelia/Core/HttpFoundation/JsonResponse.php @@ -0,0 +1,67 @@ + + */ +class JsonResponse extends BaseJsonResponse +{ + public static function createError($errorMessage, $statusCode = 500) + { + return new static(["error" => $errorMessage], $statusCode); + } + + public static function createAuthError($access) + { + switch ($access) { + case AccessManager::VIEW: + $errorMessage = "You don't have the right to view this content"; + break; + + case AccessManager::UPDATE: + $errorMessage = "You don't have the right to edit this content"; + break; + + case AccessManager::CREATE: + $errorMessage = "You don't have the right to create this content"; + break; + + case AccessManager::DELETE: + $errorMessage = "You don't have the right to delete this content"; + break; + + default: + $errorMessage = "You don't have the right to do this"; + } + + $errorMessage = Translator::getInstance()->trans($errorMessage); + + return static::createError($errorMessage); + } + + public static function createNotFoundError($resource) + { + $errorMessage = Translator::getInstance() + ->trans("The resource %res has not been found", ["%res" => $resource]) + ; + + return static::createError($errorMessage, 404); + } +} diff --git a/core/lib/Thelia/Core/HttpFoundation/Request.php b/core/lib/Thelia/Core/HttpFoundation/Request.php new file mode 100644 index 00000000..e723752a --- /dev/null +++ b/core/lib/Thelia/Core/HttpFoundation/Request.php @@ -0,0 +1,182 @@ + + */ +class Request extends BaseRequest +{ + /** @var string Path info without trailing slash */ + private $resolvedPathInfo; + + /** @var string */ + protected $controllerType = null; + + /** + * @ + * {@inheritdoc} Including Thelia request properties + */ + public function initialize( + array $query = [], + array $request = [], + array $attributes = [], + array $cookies = [], + array $files = [], + array $server = [], + $content = null + ) { + parent::initialize($query, $request, $attributes, $cookies, $files, $server, $content); + + $this->resolvedPathInfo = null; + } + + /** + * Filter PathInfo to allow slash ending uri + * + * example: + * /admin will be the same as /admin/ + */ + public function getPathInfo() + { + $pathInfo = parent::getPathInfo(); + $pathLength = \strlen($pathInfo); + + if ($pathInfo !== '/' && $pathInfo[$pathLength - 1] === '/' + && (bool) ConfigQuery::read('allow_slash_ended_uri', false) + ) { + if (null === $this->resolvedPathInfo) { + $this->resolvedPathInfo = substr($pathInfo, 0, $pathLength - 1); // Remove the slash + } + + $pathInfo = $this->resolvedPathInfo; + } + + return $pathInfo; + } + + public function getRealPathInfo() + { + return parent::getPathInfo(); + } + + public function getProductId() + { + return $this->get("product_id"); + } + + public function getUriAddingParameters(array $parameters = null) + { + $uri = $this->getUri(); + + $additionalQs = ''; + + foreach ($parameters as $key => $value) { + $additionalQs .= sprintf("&%s=%s", $key, $value); + } + + if ('' == $this->getQueryString()) { + $additionalQs = '?'. ltrim($additionalQs, '&'); + } + + return $uri . $additionalQs; + } + + public function toString($withContent = true) + { + $string = + sprintf('%s %s %s', $this->getMethod(), $this->getRequestUri(), $this->server->get('SERVER_PROTOCOL')) + . "\r\n" . $this->headers . "\r\n" + ; + + if (true === $withContent) { + $string .= $this->getContent(); + } + + return $string; + } + + /** + * @param string $controllerType + */ + public function setControllerType($controllerType) + { + $this->controllerType = $controllerType; + } + + /** + * Detects where does the request + * + * + * // Detect if the request comes from the api + * if ($request->fromControllerType(BaseApiController::CONTROLLER_TYPE)) {...} + * + * + * @param $controllerType + * @return bool + */ + public function fromControllerType($controllerType) + { + return $this->controllerType === $controllerType; + } + + /** + * Detect if the request comes from the api + * + * @return bool + */ + public function fromApi() + { + return $this->controllerType === BaseApiController::CONTROLLER_TYPE; + } + + /** + * Detect if the request comes from the admin + * + * @return bool + */ + public function fromAdmin() + { + return $this->controllerType === BaseAdminController::CONTROLLER_TYPE; + } + + /** + * Detect if the request comes from the front + * + * @return bool + */ + public function fromFront() + { + return $this->controllerType === BaseFrontController::CONTROLLER_TYPE; + } + + /** + * From a Thelia request, we always return a Thelia Session object. + * + * @return null|\Thelia\Core\HttpFoundation\Session\Session + */ + public function getSession() + { + return parent::getSession(); + } +} diff --git a/core/lib/Thelia/Core/HttpFoundation/Response.php b/core/lib/Thelia/Core/HttpFoundation/Response.php new file mode 100644 index 00000000..beb8be57 --- /dev/null +++ b/core/lib/Thelia/Core/HttpFoundation/Response.php @@ -0,0 +1,43 @@ + + */ +class Response extends BaseResponse +{ + /** + * Allow Tlog to write log stuff in the fina content. + * + * @see \Thelia\Core\HttpFoundation\Response::sendContent() + */ + public function sendContent() + { + //ConfigQuery can be not already generated in cache so we must check it + if (class_exists('ConfigQuery')) { + Tlog::getInstance()->write($this->content); + } + + parent::sendContent(); + } +} diff --git a/core/lib/Thelia/Core/HttpFoundation/Session/Session.php b/core/lib/Thelia/Core/HttpFoundation/Session/Session.php new file mode 100644 index 00000000..2b57bed0 --- /dev/null +++ b/core/lib/Thelia/Core/HttpFoundation/Session/Session.php @@ -0,0 +1,411 @@ +get("thelia.current.lang"); + if (null === $lang && $forceDefault) { + $lang = Lang::getDefaultLanguage(); + } + + return $lang; + } + + public function setLang(Lang $lang) + { + $this->set("thelia.current.lang", $lang); + + return $this; + } + + public function setCurrency(Currency $currency) + { + $this->set("thelia.current.currency", $currency); + } + + /** + * Return current currency + * + * @param bool $forceDefault if true, the default currency will be returned if no current currency is defined. + * + * @return Currency + */ + public function getCurrency($forceDefault = true) + { + $currency = $this->get("thelia.current.currency"); + + if (null === $currency && $forceDefault) { + $currency = Currency::getDefaultCurrency(); + } + + return $currency; + } + + // -- Admin lang and currency ---------------------------------------------- + + public function getAdminEditionCurrency() + { + $currency = $this->get('thelia.admin.edition.currency', null); + + if (null === $currency) { + $currency = Currency::getDefaultCurrency(); + } + + return $currency; + } + + public function setAdminEditionCurrency($currencyId) + { + $this->set('thelia.admin.edition.currency', $currencyId); + + return $this; + } + + /** + * @return Lang the current edition language in the back-office + */ + public function getAdminEditionLang() + { + $lang = $this->get('thelia.admin.edition.lang'); + + if (null === $lang) { + $lang = Lang::getDefaultLanguage(); + } + + return $lang; + } + + /** + * @param Lang $lang the current edition language to set in the back-office + * @return $this + */ + public function setAdminEditionLang(Lang $lang) + { + $this->set('thelia.admin.edition.lang', $lang); + + return $this; + } + + // -- Customer user -------------------------------------------------------- + + public function setCustomerUser(UserInterface $user) + { + $this->set('thelia.customer_user', $user); + + return $this; + } + + /** + * @return UserInterface|null the current front office user, or null if none is legged in + */ + public function getCustomerUser() + { + return $this->get('thelia.customer_user'); + } + + public function clearCustomerUser() + { + return $this->remove('thelia.customer_user'); + } + + // -- Admin user ----------------------------------------------------------- + + public function setAdminUser(UserInterface $user) + { + $this->set('thelia.admin_user', $user); + + return $this; + } + + public function getAdminUser() + { + return $this->get('thelia.admin_user'); + } + + public function clearAdminUser() + { + return $this->remove('thelia.admin_user'); + } + + // -- Return page ---------------------------------------------------------- + + public function setReturnToUrl($url) + { + $this->set('thelia.return_to_url', $url); + + return $this; + } + + /** + * + * @return string the return-to URL, or the index page if none is defined. + */ + public function getReturnToUrl() + { + return $this->get('thelia.return_to_url', URL::getInstance()->getIndexPage()); + } + + // -- Return catalog last page ---------------------------------------------------------- + + public function setReturnToCatalogLastUrl($url) + { + $this->set('thelia.return_to_catalog_last_url', $url); + + return $this; + } + + /** + * + * @return string the return-to catalog last URL, or the index page if none is defined. + */ + public function getReturnToCatalogLastUrl() + { + return $this->get('thelia.return_to_catalog_last_url', URL::getInstance()->getIndexPage()); + } + + // -- Cart ------------------------------------------------------------------ + + /** + * Set the cart to store in the current session. + * + * @param Cart|null The cart to store in session + * + * @return $this + */ + public function setSessionCart(Cart $cart = null) + { + if (null === $cart || $cart->isNew()) { + self::$transientCart = $cart; + $this->remove("thelia.cart_id"); + } else { + self::$transientCart = null; + $this->set("thelia.cart_id", $cart->getId()); + } + + return $this; + } + + + /** + * Return the cart stored in the current session + * + * @param EventDispatcherInterface $dispatcher the event dispatcher, required if no cart is currently stored in the session + * + * @return Cart The cart in the current session. + */ + public function getSessionCart(EventDispatcherInterface $dispatcher = null) + { + $cart_id = $this->get("thelia.cart_id", null); + if (null !== $cart_id) { + $cart = CartQuery::create()->findPk($cart_id); + } else { + $cart = self::$transientCart; + } + + // If we do not have a cart, or if the current cart is nor valid + // restore it from the cart cookie, or create a new one + if (null === $cart || ! $this->isValidCart($cart)) { + // A dispatcher is required here. If we do not have it, throw an exception + // This is a temporary workaround to ensure backward compatibility with getCart(), + // When genCart() will be removed, this check should be removed, and $dispatcher should become + // a required parameter. + + if (null == $dispatcher) { + throw new \InvalidArgumentException( + "In this context (no cart in session), an EventDispatcher should be provided to Session::getSessionCart()." + ); + } + + $cartEvent = new CartRestoreEvent(); + + if (null !== $cart) { + $cartEvent->setCart($cart); + } + + $dispatcher->dispatch(TheliaEvents::CART_RESTORE_CURRENT, $cartEvent); + + if (null === $cart = $cartEvent->getCart()) { + throw new \LogicException( + "Unable to get a Cart." + ); + } + + // Store the cart. + $this->setSessionCart($cart); + } + + return $cart; + } + + /** + * Clear the current session cart, and store a new, empty one in the session. + * + * @param EventDispatcherInterface $dispatcher + */ + public function clearSessionCart(EventDispatcherInterface $dispatcher) + { + $event = new CartCreateEvent(); + + $dispatcher->dispatch(TheliaEvents::CART_CREATE_NEW, $event); + + if (null === $cart = $event->getCart()) { + throw new \LogicException( + "Unable to get a new empty Cart." + ); + } + + // Store the cart + $this->setSessionCart($cart); + } + + /** + * Return cart if it exists and is valid (checking customer) + * + * @return \Thelia\Model\Cart|null + * @deprecated use getSessionCart() instead + */ + public function getCart() + { + trigger_error( + 'getCart is deprecated, please use getSessionCart method instead', + E_USER_DEPRECATED + ); + + return $this->getSessionCart(null); + } + + /** + * A cart is valid if its customer ID is the same as the current logged in user + * + * @param Cart $cart The cart to check + * + * @return bool true if the cart is valid, false otherwise + */ + protected function isValidCart(Cart $cart) + { + $customer = $this->getCustomerUser(); + + return (null !== $customer && $cart->getCustomerId() == $customer->getId()) + || + (null === $customer && $cart->getCustomerId() === null); + } + + // -- Order ------------------------------------------------------------------ + + public function setOrder(Order $order) + { + $this->set("thelia.order", $order); + + return $this; + } + + /** + * @return Order + */ + public function getOrder() + { + $order = $this->get("thelia.order"); + + if (null === $order) { + $order = new Order(); + $this->setOrder($order); + } + + return $order; + } + + /** + * Set consumed coupons by the Customer + * + * @param array $couponsCode An array of Coupon code + * + * @return $this + */ + public function setConsumedCoupons(array $couponsCode) + { + $this->set('thelia.consumed_coupons', $couponsCode); + + return $this; + } + + /** + * Get Customer consumed coupons + * + * @return array $couponsCode An array of Coupon code + */ + public function getConsumedCoupons() + { + return $this->get('thelia.consumed_coupons', array()); + } + + /** + * Get saved errored forms information + * + * @return array + */ + public function getFormErrorInformation() + { + return $this->get('thelia.form-errors', []); + } + + /** + * Save errored forms information + * + * @param array $formInformation + * @return mixed + */ + public function setFormErrorInformation($formInformation) + { + $this->set('thelia.form-errors', $formInformation); + + return $this; + } +} diff --git a/core/lib/Thelia/Core/HttpKernel/Client.php b/core/lib/Thelia/Core/HttpKernel/Client.php new file mode 100644 index 00000000..efd8502b --- /dev/null +++ b/core/lib/Thelia/Core/HttpKernel/Client.php @@ -0,0 +1,41 @@ + + */ +class Client extends BaseClient +{ + /** + * Converts the BrowserKit request to a HttpKernel request. + * + * @param DomRequest $request A Request instance + * + * @return Request A Request instance + */ + protected function filterRequest(DomRequest $request) + { + $httpRequest = Request::create($request->getUri(), $request->getMethod(), $request->getParameters(), $request->getCookies(), $request->getFiles(), $request->getServer(), $request->getContent()); + + $httpRequest->files->replace($this->filterFiles($httpRequest->files->all())); + + return $httpRequest; + } +} diff --git a/core/lib/Thelia/Core/HttpKernel/Exception/NotFountHttpException.php b/core/lib/Thelia/Core/HttpKernel/Exception/NotFountHttpException.php new file mode 100644 index 00000000..8a7710e5 --- /dev/null +++ b/core/lib/Thelia/Core/HttpKernel/Exception/NotFountHttpException.php @@ -0,0 +1,36 @@ + + * @deprecated since 2.4 and will be removed in 2.6, please use Symfony\Component\HttpKernel\Exception\NotFoundHttpException + */ +class NotFountHttpException extends BaseNotFountHttpException +{ + protected $adminContext = false; + + public function __construct($message = null, \Exception $previous = null, $code = 0, $adminContext = false) + { + $this->adminContext = $adminContext; + + parent::__construct($message, $previous, $code); + } + + public function isAdminContext() + { + return $this->adminContext === true; + } +} diff --git a/core/lib/Thelia/Core/HttpKernel/Exception/RedirectException.php b/core/lib/Thelia/Core/HttpKernel/Exception/RedirectException.php new file mode 100644 index 00000000..d856bbae --- /dev/null +++ b/core/lib/Thelia/Core/HttpKernel/Exception/RedirectException.php @@ -0,0 +1,45 @@ + + */ +class RedirectException extends \RuntimeException +{ + private $url; + private $statusCode; + + public function __construct($url, $statusCode = 302, $message = "", $code = 0, \Exception $previous = null) + { + $this->url = $url; + $this->statusCode = $statusCode; + + parent::__construct($message, $code, $previous); + } + + public function getUrl() + { + return $this->url; + } + + /** + * @return int + */ + public function getStatusCode() + { + return $this->statusCode; + } +} diff --git a/core/lib/Thelia/Core/HttpKernel/Fragment/InlineFragmentRenderer.php b/core/lib/Thelia/Core/HttpKernel/Fragment/InlineFragmentRenderer.php new file mode 100644 index 00000000..d4000eb8 --- /dev/null +++ b/core/lib/Thelia/Core/HttpKernel/Fragment/InlineFragmentRenderer.php @@ -0,0 +1,60 @@ + + */ +class InlineFragmentRenderer extends SymfonyInlineFragmentRenderer +{ + /** + * @param string $uri + * @param Request $request + * @return Request + */ + protected function createSubRequest($uri, Request $request) + { + $cookies = $request->cookies->all(); + $server = $request->server->all(); + + // Override the arguments to emulate a sub-request. + // Sub-request object will point to localhost as client ip and real client ip + // will be included into trusted header for client ip + try { + if ($trustedHeaderName = Request::getTrustedHeaderName(Request::HEADER_CLIENT_IP)) { + $currentXForwardedFor = $request->headers->get($trustedHeaderName, ''); + + $server['HTTP_'.$trustedHeaderName] = ($currentXForwardedFor ? $currentXForwardedFor.', ' : '').$request->getClientIp(); + } + } catch (\InvalidArgumentException $e) { + // Do nothing + } + + $server['REMOTE_ADDR'] = '127.0.0.1'; + + $subRequest = TheliaRequest::create($uri, 'get', array(), $cookies, array(), $server); + if ($request->headers->has('Surrogate-Capability')) { + $subRequest->headers->set('Surrogate-Capability', $request->headers->get('Surrogate-Capability')); + } + + if ($session = $request->getSession()) { + $subRequest->setSession($session); + } + + return $subRequest; + } +} diff --git a/core/lib/Thelia/Core/HttpKernel/HttpCache/HttpCache.php b/core/lib/Thelia/Core/HttpKernel/HttpCache/HttpCache.php new file mode 100644 index 00000000..cdb27804 --- /dev/null +++ b/core/lib/Thelia/Core/HttpKernel/HttpCache/HttpCache.php @@ -0,0 +1,58 @@ + + */ +class HttpCache extends BaseHttpCache implements HttpKernelInterface +{ + public function __construct(HttpKernelInterface $kernel, $options = array()) + { + parent::__construct( + $kernel, + new Store($kernel->getCacheDir().'/http_cache'), + new Esi(), + array_merge( + array('debug' => $kernel->isDebug()), + $options + ) + ); + } + + public function handle(Request $request, $type = HttpKernelInterface::MASTER_REQUEST, $catch = true) + { + if (!($request instanceof \Thelia\Core\HttpFoundation\Request)) { + $request = TheliaRequest::create( + $request->getUri(), + $request->getMethod(), + $request->getMethod() == 'GET' ? $request->query->all() : $request->request->all(), + $request->cookies->all(), + $request->files->all(), + $request->server->all(), + $request->getContent() + ); + } + + return parent::handle($request, $type, $catch); + } +} diff --git a/core/lib/Thelia/Core/Propel/Generator/Builder/Om/EventBuilder.php b/core/lib/Thelia/Core/Propel/Generator/Builder/Om/EventBuilder.php new file mode 100644 index 00000000..cbad4279 --- /dev/null +++ b/core/lib/Thelia/Core/Propel/Generator/Builder/Om/EventBuilder.php @@ -0,0 +1,21 @@ +makePathRelative( + THELIA_PROPEL_BUILD_MODEL_PATH + . parent::getClassFilePath(), + THELIA_ROOT + ), '/'); + } +} diff --git a/core/lib/Thelia/Core/Propel/Generator/Builder/Om/Mixin/StubClassTrait.php b/core/lib/Thelia/Core/Propel/Generator/Builder/Om/Mixin/StubClassTrait.php new file mode 100644 index 00000000..c96b6e8c --- /dev/null +++ b/core/lib/Thelia/Core/Propel/Generator/Builder/Om/Mixin/StubClassTrait.php @@ -0,0 +1,45 @@ +getPackage() === 'Thelia.Model') { + $path = $fs->makePathRelative( + THELIA_LIB . '..' . DS . parent::getClassFilePath(), + THELIA_ROOT + ); + } else { + $path = $fs->makePathRelative( + THELIA_MODULE_DIR . parent::getClassFilePath(), + THELIA_ROOT + ); + } + + return rtrim($path, '/'); + } +} diff --git a/core/lib/Thelia/Core/Propel/Generator/Builder/Om/MultiExtendObjectBuilder.php b/core/lib/Thelia/Core/Propel/Generator/Builder/Om/MultiExtendObjectBuilder.php new file mode 100644 index 00000000..7e945bff --- /dev/null +++ b/core/lib/Thelia/Core/Propel/Generator/Builder/Om/MultiExtendObjectBuilder.php @@ -0,0 +1,21 @@ +makePathRelative( + THELIA_PROPEL_BUILD_DATABASE_PATH + . parent::getClassFilePath(), + THELIA_ROOT + ), '/'); + } +} diff --git a/core/lib/Thelia/Core/Propel/Schema/SchemaCombiner.php b/core/lib/Thelia/Core/Propel/Schema/SchemaCombiner.php new file mode 100644 index 00000000..7a1d0d42 --- /dev/null +++ b/core/lib/Thelia/Core/Propel/Schema/SchemaCombiner.php @@ -0,0 +1,412 @@ + corresponding table attribute]. + * These are attributes that can be defined either at the database or the table level. + * Since we are merging tables from various schema files that all define part of a database and can have different + * database attribute for their own tables, we have to copy these attributes to the tables themselves (if they are + * not already defined on the table). + * @var array + */ + protected static $DATABASE_INHERITABLE_ATTRIBUTES = [ + 'defaultIdMethod' => 'idMethod', + 'defaultAccessorVisibility' => 'defaultAccessorVisibility', + 'defaultMutatorVisibility' => 'defaultMutatorVisibility', + 'package' => 'package', + 'namespace' => 'namespace', + 'schema' => 'schema', + 'baseClass' => 'baseClass', + 'defaultPhpNamingMethod' => 'phpNamingMethod', + 'heavyIndexing' => 'heavyIndexing', + ]; + + /** + * Combined databases. + * @var string[] + */ + protected $databases = []; + + /** + * Map of [database name => global database \DOMElement for that database]. + * @var array + */ + protected $globalDatabaseElements = []; + + /** + * Map of [database name => [source database \DOMElement combined for this database]]. + * @var array + */ + protected $sourceDatabaseElements = []; + + /** + * Map of [database name => [external-schema database \DOMElement included for this database]]. + * @var array + */ + protected $externalSchemaDatabaseElements = []; + + /** + * @param \DOMDocument[] $schemaDocuments Schema documents to combine. + * @param \DOMDocument[] $externalSchemaDocuments Schemas documents to include as external schemas in the combined + * documents. + */ + public function __construct(array $schemaDocuments = [], array $externalSchemaDocuments = []) + { + $this->combine($schemaDocuments, $externalSchemaDocuments); + } + + /** + * @return string[] Combined databases. + */ + public function getDatabases() + { + return $this->databases; + } + + /** + * @param string $database Database + * @throws \InvalidArgumentException If the database is not in the combined databases. + */ + protected function assertDatabase($database) + { + if (!\in_array($database, $this->databases)) { + throw new \InvalidArgumentException("Database '{$database}' is not in the combined databases."); + } + } + + /** + * @param \DOMElement $element Element. + * @return \DOMDocument Element owner. + */ + protected static function getOwnerDocument(\DOMElement $element) + { + return $element->ownerDocument; + } + + /** + * @param string $database Database. + * @return \DOMDocument Combined schema document for this database. + */ + public function getCombinedDocument($database) + { + $this->assertDatabase($database); + + /** @var \DOMElement $globalDatabaseElement */ + $globalDatabaseElement = $this->globalDatabaseElements[$database]; + + return static::getOwnerDocument($globalDatabaseElement); + } + + /** + * @param string $database Database. + * @return \DOMDocument[] Source schema documents that were combined for this database. + */ + public function getSourceDocuments($database) + { + $this->assertDatabase($database); + + return array_map([$this, 'getOwnerDocument'], $this->sourceDatabaseElements[$database]); + } + + /** + * @param string $database Database. + * @return \DOMDocument[] External schema documents that were included for this database. + */ + public function getExternalSchemaDocuments($database) + { + $this->assertDatabase($database); + + return array_map([$this, 'getOwnerDocument'], $this->externalSchemaDatabaseElements[$database]); + } + + /** + * Combine multiple schemas into one schema per database. + * @param \DOMDocument[] $schemaDocuments Schema documents to combine. + * @param \DOMDocument[] $externalSchemaDocuments Schemas documents to include as external schemas in the combined + * documents. + * @return array A map of [database name => \DOMDocument schema for that database]. + */ + public function combine(array $schemaDocuments = [], array $externalSchemaDocuments = []) + { + $globalDatabaseElements = []; + + // merge schema documents, per database + foreach ($schemaDocuments as $sourceSchemaDocument) { + if (!$sourceSchemaDocument instanceof \DOMDocument) { + throw new \InvalidArgumentException('Schema file is not a \DOMDocument'); + } + + // work on document clones since we are going to edit them + $sourceSchemaDocument = clone $sourceSchemaDocument; + + // process all elements in the document + /** @var \DOMElement $sourceDatabaseElement */ + foreach ($sourceSchemaDocument->getElementsByTagName('database') as $sourceDatabaseElement) { + // pre-process the element + $this->filterExternalSchemaElements($sourceDatabaseElement); + $this->inheritDatabaseAttributes($sourceDatabaseElement); + $this->applyDatabaseTablePrefix($sourceDatabaseElement); + + // append the element + $this->mergeDatabaseElement($sourceDatabaseElement); + } + } + + // include external schema documents, per database + foreach ($externalSchemaDocuments as $externalSchemaDocument) { + if (!$externalSchemaDocument instanceof \DOMDocument) { + throw new \InvalidArgumentException('Schema file is not a \DOMDocument'); + } + + // process all elements in the document + /** @var \DOMElement $externalSchemaDatabaseElement */ + foreach ($externalSchemaDocument->getElementsByTagName('database') as $externalSchemaDatabaseElement) { + // include the document + $this->includeExternalSchema($externalSchemaDatabaseElement); + } + } + + // return the documents, not the database elements + $globalSchemaDocuments = []; + /** + * @var string $database + * @var \DOMElement $globalDatabaseElement + */ + foreach ($globalDatabaseElements as $database => $globalDatabaseElement) { + $globalSchemaDocuments[$database] = $globalDatabaseElement->ownerDocument; + } + + return $globalSchemaDocuments; + } + + /** + * Remove references from a database element. + * @param \DOMElement $databaseElement Database element to process. + */ + protected function filterExternalSchemaElements(\DOMElement $databaseElement) + { + // removing the elements in the foreach itself will break the iterator, remove them later + $externalSchemaElementsToDelete = []; + /** @var \DOMElement $externalSchemaElement */ + foreach ($databaseElement->getElementsByTagName('external-schema') as $externalSchemaElement) { + $externalSchemaElementsToDelete[] = $externalSchemaElement; + } + + foreach ($externalSchemaElementsToDelete as $externalSchemaElement) { + // add a removal notice + $externalSchemaRemovalNoticeComment = $databaseElement->ownerDocument->createComment( + "external-schema reference to '{$externalSchemaElement->getAttribute('filename')}' removed" + ); + $databaseElement->appendChild($externalSchemaRemovalNoticeComment); + + $externalSchemaElement->parentNode->removeChild($externalSchemaElement); + } + } + + /** + * Copy inheritable database attribute to the tables in the database. + * @param \DOMElement $databaseElement Database element to process. + */ + protected function inheritDatabaseAttributes(\DOMElement $databaseElement) + { + $attributesToInherit = []; + foreach (static::$DATABASE_INHERITABLE_ATTRIBUTES as $databaseAttribute => $tableAttribute) { + if (!$databaseElement->hasAttribute($databaseAttribute)) { + continue; + } + + $attributesToInherit[$tableAttribute] = $databaseElement->getAttribute($databaseAttribute); + } + + /** @var \DOMElement $tableElement */ + foreach ($databaseElement->getElementsByTagName('table') as $tableElement) { + foreach (static::$DATABASE_INHERITABLE_ATTRIBUTES as $databaseAttribute => $tableAttribute) { + if (!isset($attributesToInherit[$tableAttribute])) { + continue; + } + + if ($tableElement->hasAttribute($tableAttribute)) { + // do not inherit the attribute if the table defines its own + continue; + } + + // add an inheritance notice + $databaseAttributeInheritanceNoticeComment = $tableElement->ownerDocument->createComment( + "Attribute '{$tableAttribute}'" + . " inherited from parent database attribute '{$databaseAttribute}'" + ); + $tableElement->insertBefore( + $databaseAttributeInheritanceNoticeComment, + $tableElement->firstChild + ); + + $tableElement->setAttribute($tableAttribute, $attributesToInherit[$tableAttribute]); + } + } + } + + /** + * Prefix table names with the prefix defined on the database. + * @param \DOMElement $databaseElement Database element to process. + */ + protected function applyDatabaseTablePrefix(\DOMElement $databaseElement) + { + if (!$databaseElement->hasAttribute('tablePrefix')) { + return; + } + + $tablePrefix = $databaseElement->getAttribute('tablePrefix'); + + /** @var \DOMElement $tableElement */ + foreach ($databaseElement->getElementsByTagName('table') as $tableElement) { + if (!$tableElement->hasAttribute('name')) { + // this is probably wrong, but not our problem here - we do not validate the schema + continue; + } + + // add a prefixing notice + $tablePrefixingNoticeComment = $tableElement->ownerDocument->createComment( + "Table name prefixed with parent database 'tablePrefix'" + ); + $tableElement->appendChild($tablePrefixingNoticeComment); + + $table = $tableElement->getAttribute('name'); + $tableElement->setAttribute('name', $tablePrefix . $table); + } + } + + /** + * Get the database name from a database element. + * @param \DOMElement $databaseElement Database element. + * @return string Database name. + * @throws \LogicException If the database element is unnamed. + */ + protected function getDatabaseFromDatabaseElement(\DOMElement $databaseElement) + { + $database = $databaseElement->getAttribute('name'); + if (empty($database)) { + throw new \LogicException('Unnamed database node.'); + } + + return $database; + } + + /** + * Create a global database element in a new document. + * @param string $database Database. + */ + protected function initGlobalDatabaseElement($database) + { + if (\in_array($database, $this->databases)) { + return; + } + + $databaseDocument = new \DOMDocument(static::$GLOBAL_SCHEMA_XML_VERSION, static::$GLOBAL_SCHEMA_XML_ENCODING); + + $databaseElement = $databaseDocument->createElement('database'); + + $databaseElement->setAttribute('name', $database); + + $identifierQuotingNoticeComment = $databaseElement->ownerDocument->createComment( + "Attribute 'identifierQuoting' generated" + ); + $databaseElement->appendChild($identifierQuotingNoticeComment); + $databaseElement->setAttribute('identifierQuoting', 'true'); + + $databaseDocument->appendChild($databaseElement); + + $this->databases[] = $database; + $this->globalDatabaseElements[$database] = $databaseElement; + $this->sourceDatabaseElements[$database] = []; + $this->externalSchemaDatabaseElements[$database] = []; + } + + /** + * Merge a source database element into the corresponding global database element for this database. + * @param \DOMElement $sourceDatabaseElement Source database element to merge. + */ + protected function mergeDatabaseElement(\DOMElement $sourceDatabaseElement) + { + $database = $this->getDatabaseFromDatabaseElement($sourceDatabaseElement); + + $this->initGlobalDatabaseElement($database); + + $globalDatabaseElement = $this->globalDatabaseElements[$database]; + + // add a source schema start marker + $fileStartMarkerComment = $globalDatabaseElement->ownerDocument->createComment( + "Start of schema from '{$sourceDatabaseElement->ownerDocument->baseURI}'" + ); + $globalDatabaseElement->appendChild($fileStartMarkerComment); + + // merge the element + foreach ($sourceDatabaseElement->childNodes as $childNode) { + $importedNode = $globalDatabaseElement->ownerDocument->importNode($childNode, true); + $globalDatabaseElement->appendChild($importedNode); + } + + // and a source schema end marker + $fileEndMarkerComment = $globalDatabaseElement->ownerDocument->createComment( + "End of schema from '{$sourceDatabaseElement->ownerDocument->baseURI}'" + ); + $globalDatabaseElement->appendChild($fileEndMarkerComment); + + $this->sourceDatabaseElements[$database][] = $sourceDatabaseElement; + } + + /** + * Include an external schema into a database element. + * @param \DOMElement $externalDatabaseElement External schema database element to include. + */ + protected function includeExternalSchema(\DOMElement $externalDatabaseElement) + { + $database = $this->getDatabaseFromDatabaseElement($externalDatabaseElement); + + $this->initGlobalDatabaseElement($database); + + $globalDatabaseElement = $this->globalDatabaseElements[$database]; + + // add an inclusion notice + $externalSchemaIncludeComment = $globalDatabaseElement->ownerDocument->createComment( + "External schema included in the combining process" + ); + $globalDatabaseElement->appendChild($externalSchemaIncludeComment); + + // include the external schema + $externalSchemaInclude = $globalDatabaseElement->ownerDocument->createElement( + 'external-schema', + $externalDatabaseElement->ownerDocument->baseURI + ); + $globalDatabaseElement->appendChild($externalSchemaInclude); + + $this->externalSchemaDatabaseElements[$database][] = $externalDatabaseElement; + } +} diff --git a/core/lib/Thelia/Core/Propel/Schema/SchemaLocator.php b/core/lib/Thelia/Core/Propel/Schema/SchemaLocator.php new file mode 100644 index 00000000..bb6d0913 --- /dev/null +++ b/core/lib/Thelia/Core/Propel/Schema/SchemaLocator.php @@ -0,0 +1,273 @@ +theliaConfDir = $theliaConfDir; + $this->theliaModuleDir = $theliaModuleDir; + } + + /** + * @param ConnectionInterface $theliaDatabaseConnection Connection to the thelia database. + */ + public function setTheliaDatabaseConnection(ConnectionInterface $theliaDatabaseConnection) + { + $this->theliaDatabaseConnection = $theliaDatabaseConnection; + } + + /** + * Get schema documents for Thelia core and active modules, as well as included external schemas. + * @return \DOMDocument[] Schema documents. + */ + public function findForActiveModules() + { + $fs = new Filesystem(); + + $codes = $this->queryActiveModuleCodes(); + + foreach ($codes as $key => $code) { + // test if the module exists on the file system + if (!$fs->exists(THELIA_MODULE_DIR . $code)) { + unset($codes[$key]); + } + } + + // reset keys + $codes = array_values($codes); + + return $this->findForModules($codes); + } + + /** + * Get schema documents for specific modules and their dependencies (including Thelia), as well as included + * external schemas. + * @param string[] $modules Codes of the modules to fetch schemas for. 'Thelia' can be used to include Thelia core + * schemas. + * @param bool $withDependencies Whether to also return schemas for the specified modules dependencies. + * @return \DOMDocument[] Schema documents. + */ + public function findForModules(array $modules = [], $withDependencies = true) + { + if ($withDependencies) { + $modules = $this->addModulesDependencies($modules); + } + + $schemas = []; + + foreach ($modules as $module) { + if ($module === 'Thelia') { + $moduleSchemas = $this->getSchemaPathsForThelia(); + } else { + $moduleSchemas = $this->getSchemaPathsForModule($module); + } + + $schemaDocuments = []; + /** @var SplFileInfo $schemaFile */ + foreach ($moduleSchemas as $schemaFile) { + $schemaDocument = new \DOMDocument(); + $schemaDocument->load($schemaFile->getRealPath()); + $schemaDocuments[] = $schemaDocument; + } + + $schemaDocuments = $this->addExternalSchemaDocuments($schemaDocuments); + + $schemas = $this->mergeDOMDocumentsArrays([$schemas, $schemaDocuments]); + } + + return $schemas; + } + + /** + * Add dependencies of some modules. + * @param string[] $modules Module codes. + * @return string[] Modules codes with added dependencies. + */ + protected function addModulesDependencies(array $modules = []) + { + if (empty($modules)) { + return []; + } + + // Thelia is always a dependency + if (!\in_array('Thelia', $modules)) { + $modules[] = 'Thelia'; + } + + foreach ($modules as $module) { + // Thelia is not a real module, do not try to get its dependencies + if ($module === 'Thelia') { + continue; + } + + $moduleValidator = new ModuleValidator("{$this->theliaModuleDir}/{$module}"); + $dependencies = $moduleValidator->getCurrentModuleDependencies(true); + foreach ($dependencies as $dependency) { + if (!\in_array($dependency['code'], $modules)) { + $modules[] = $dependency['code']; + } + } + } + + return $modules; + } + + /** + * @return Finder Thelia schema files. + */ + protected function getSchemaPathsForThelia() + { + return Finder::create() + ->files() + ->name(static::$SCHEMA_FILE_PATTERN) + ->in($this->theliaConfDir); + } + + /** + * @param string $module Module code. + * @return Finder Schema files for this module. + */ + protected function getSchemaPathsForModule($module) + { + $moduleSchemas = Finder::create() + ->files() + ->name(static::$SCHEMA_FILE_PATTERN) + ->depth(0); + + try { + $moduleSchemas->in("{$this->theliaModuleDir}/{$module}/Config"); + } catch (\InvalidArgumentException $e) { + // just continue if the module has no Config directory + } + + return $moduleSchemas; + } + + /** + * Add external schema documents not already included. + * @param \DOMDocument[] $schemaDocuments Schema documents. + * @return \DOMDocument[] Schema documents. + */ + protected function addExternalSchemaDocuments(array $schemaDocuments) + { + $fs = new Filesystem(); + + $externalSchemaDocuments = []; + + foreach ($schemaDocuments as $schemaDocument) { + /** @var \DOMElement $externalSchemaElement */ + foreach ($schemaDocument->getElementsByTagName('external-schema') as $externalSchemaElement) { + if (!$externalSchemaElement->hasAttribute('filename')) { + continue; + } + + $externalSchemaPath = $externalSchemaElement->getAttribute('filename'); + + if (!$fs->exists($externalSchemaPath)) { + continue; + } + + $externalSchemaDocument = new \DOMDocument(); + if (!$externalSchemaDocument->load($externalSchemaPath)) { + continue; + } + + $externalSchemaDocuments[] = $externalSchemaDocument; + } + } + + return $this->mergeDOMDocumentsArrays([$schemaDocuments, $externalSchemaDocuments]); + } + + /** + * @param \DOMDocument[][] $documentArrays + * @return \DOMDocument[] + */ + protected function mergeDOMDocumentsArrays(array $documentArrays) + { + $result = []; + $includedDocumentURIs = []; + + foreach ($documentArrays as $documentArray) { + foreach ($documentArray as $document) { + if (\in_array($document->baseURI, $includedDocumentURIs)) { + continue; + } + + $result[] = $document; + $includedDocumentURIs[] = $document->baseURI; + } + } + + return $result; + } + + /** + * @return string[] Active module codes. + */ + protected function queryActiveModuleCodes() + { + if (!$this->theliaDatabaseConnection instanceof ConnectionInterface) { + throw new \RuntimeException("No connection to the Thelia database was provided."); + } + + $query = 'select code from module where module.activate;'; + + $statement = $this->theliaDatabaseConnection->prepare($query); + $statement->execute(); + + return $statement->fetchAll(\PDO::FETCH_COLUMN); + } +} diff --git a/core/lib/Thelia/Core/PropelInitService.php b/core/lib/Thelia/Core/PropelInitService.php new file mode 100644 index 00000000..45e95694 --- /dev/null +++ b/core/lib/Thelia/Core/PropelInitService.php @@ -0,0 +1,464 @@ +environment = $environment; + $this->debug = $debug; + $this->envParameters = $envParameters; + $this->schemaLocator = $schemaLocator; + } + + /** + * @return string Thelia database configuration file. + */ + protected function getTheliaDatabaseConfigFile() + { + $fs = new Filesystem(); + + $databaseConfigFile = THELIA_CONF_DIR . 'database_' . $this->environment . '.yml'; + if (!$fs->exists($databaseConfigFile)) { + $databaseConfigFile = THELIA_CONF_DIR . 'database.yml'; + } + + return $databaseConfigFile; + } + + /** + * @return string Propel subdirectory in the Thelia cache directory. + */ + public function getPropelCacheDir() + { + return THELIA_CACHE_DIR . $this->environment . DS . 'propel' . DS; + } + + /** + * @return string Propel configuration directory. + */ + public function getPropelConfigDir() + { + return $this->getPropelCacheDir() . 'config' . DS; + } + + /** + * @return string Propel cached configuration file. + */ + public function getPropelConfigFile() + { + return $this->getPropelConfigDir() . 'propel.yml'; + } + + /** + * @return string Propel cached initialization file. + */ + public function getPropelInitFile() + { + return $this->getPropelConfigDir() . static::$PROPEL_CONFIG_CACHE_FILENAME; + } + + /** + * @return string Generated global Propel schema(s) directory. + */ + public function getPropelSchemaDir() + { + return $this->getPropelCacheDir() . 'schema' . DS; + } + + /** + * @return string Generated Propel models directory. + */ + public function getPropelModelDir() + { + return THELIA_PROPEL_BUILD_MODEL_PATH; + } + + /** + * @return string Generated Propel models directory. + */ + public function getPropelDatabaseDir() + { + return THELIA_PROPEL_BUILD_DATABASE_PATH; + } + + /** + * @return string Generated Propel migrations directory. + */ + public function getPropelMigrationDir() + { + return $this->getPropelCacheDir() . 'migration' . DS; + } + + /** + * Run a Propel command. + * @param Command $command Command to run. + * @param array $parameters Command parameters. + * @param OutputInterface|null $output Command output. + * @return int Command exit code. + * @throws \Exception + */ + public function runCommand(Command $command, array $parameters = [], OutputInterface $output = null) + { + $parameters['command'] = $command->getName(); + $input = new ArrayInput($parameters); + + if ($output === null) { + $output = new NullOutput(); + } + + $command->setApplication(new SymfonyConsoleApplication()); + + return $command->run($input, $output); + } + + /** + * Generate the Propel configuration file. + */ + public function buildPropelConfig() + { + $propelConfigCache = new ConfigCache( + $this->getPropelConfigFile(), + $this->debug + ); + + if ($propelConfigCache->isFresh()) { + return; + } + + $configService = new DatabaseConfigurationSource( + Yaml::parse(file_get_contents($this->getTheliaDatabaseConfigFile())), + $this->envParameters + ); + + $propelConfig = $configService->getPropelConnectionsConfiguration(); + + $propelConfig['propel']['paths']['phpDir'] = THELIA_ROOT; + $propelConfig['propel']['generator']['objectModel']['builders'] = [ + 'object' + => '\Thelia\Core\Propel\Generator\Builder\Om\ObjectBuilder', + 'objectstub' + => '\Thelia\Core\Propel\Generator\Builder\Om\ExtensionObjectBuilder', + 'objectmultiextend' + => '\Thelia\Core\Propel\Generator\Builder\Om\MultiExtendObjectBuilder', + 'query' + => '\Thelia\Core\Propel\Generator\Builder\Om\QueryBuilder', + 'querystub' + => '\Thelia\Core\Propel\Generator\Builder\Om\ExtensionQueryBuilder', + 'queryinheritance' + => '\Thelia\Core\Propel\Generator\Builder\Om\QueryInheritanceBuilder', + 'queryinheritancestub' + => '\Thelia\Core\Propel\Generator\Builder\Om\ExtensionQueryInheritanceBuilder', + 'tablemap' + => '\Thelia\Core\Propel\Generator\Builder\Om\TableMapBuilder', + 'event' + => '\Thelia\Core\Propel\Generator\Builder\Om\EventBuilder' + ]; + + $propelConfig['propel']['generator']['builders'] = [ + 'resolver' + => '\Thelia\Core\Propel\Generator\Builder\ResolverBuilder' + ]; + + $configOptions['propel']['paths']['migrationDir'] = $this->getPropelConfigDir(); + + $propelConfigCache->write( + Yaml::dump($propelConfig), + [new FileResource($this->getTheliaDatabaseConfigFile())] + ); + } + + /** + * Generate the Propel initialization file. + * @throws \Exception + */ + public function buildPropelInitFile() + { + $propelInitCache = new ConfigCache( + $this->getPropelInitFile(), + $this->debug + ); + + + if ($propelInitCache->isFresh()) { + return; + } + + $this->runCommand( + new ConfigConvertCommand(), + [ + '--config-dir' => $this->getPropelConfigDir(), + '--output-dir' => $this->getPropelConfigDir(), + '--output-file' => static::$PROPEL_CONFIG_CACHE_FILENAME + ] + ); + + // rewrite the file as a cached file + $propelInitContent = file_get_contents($this->getPropelInitFile()); + $propelInitCache->write( + $propelInitContent, + [new FileResource($this->getPropelConfigFile())] + ); + } + + /** + * Generate the global Propel schema(s). + */ + public function buildPropelGlobalSchema() + { + $fs = new Filesystem(); + + // TODO: caching rules ? + if ($fs->exists($this->getPropelSchemaDir())) { + return false; + } + + $hash = ''; + + $fs->mkdir($this->getPropelSchemaDir()); + + $schemaCombiner = new SchemaCombiner( + $this->schemaLocator->findForActiveModules() + ); + + foreach ($schemaCombiner->getDatabases() as $database) { + $databaseSchemaCache = new ConfigCache( + "{$this->getPropelSchemaDir()}{$database}.schema.xml", + $this->debug + ); + + $databaseSchemaResources = []; + foreach ($schemaCombiner->getSourceDocuments($database) as $sourceDocument) { + $databaseSchemaResources[] = new FileResource($sourceDocument->baseURI); + } + + $databaseSchemaCache->write( + $schemaCombiner->getCombinedDocument($database)->saveXML(), + $databaseSchemaResources + ); + + $hash .= md5(file_get_contents($this->getPropelSchemaDir() . $database .'.schema.xml')); + } + + $fs->dumpFile($this->getPropelCacheDir() . 'hash', $hash); + + return true; + } + + /** + * Generate the base Propel models. + * @throws \Exception + */ + public function buildPropelModels() + { + $fs = new Filesystem(); + + // cache testing + if ($fs->exists($this->getPropelModelDir() . 'hash') + && file_get_contents($this->getPropelCacheDir() . 'hash') === file_get_contents($this->getPropelModelDir() . 'hash')) { + return false; + } + + $fs->remove($this->getPropelModelDir()); + + $this->runCommand( + new ModelBuildCommand(), + [ + '--config-dir' => $this->getPropelConfigDir(), + '--schema-dir' => $this->getPropelSchemaDir(), + ] + ); + + $fs->copy( + $this->getPropelCacheDir() . 'hash', + $this->getPropelModelDir() . 'hash' + ); + + return true; + } + + public function migrate() + { + $this->runCommand( + new MigrationUpCommand(), + [ + '--config-dir' => $this->getPropelConfigDir(), + '--output-dir' => THELIA_CACHE_DIR . 'propel-migrations' . DS + ] + ); + + $this->runCommand( + new MigrationDiffCommand(), + [ + '--config-dir' => $this->getPropelConfigDir(), + '--schema-dir' => $this->getPropelSchemaDir(), + '--skip-removed-table' => true, + '--output-dir' => THELIA_CACHE_DIR . 'propel-migrations' . DS + ] + ); + + $this->runCommand( + new MigrationUpCommand(), + [ + '--config-dir' => $this->getPropelConfigDir(), + '--output-dir' => THELIA_CACHE_DIR . 'propel-migrations' . DS + ] + ); + } + + /** + * Register a class loader to load the generated Propel models. + */ + public function registerPropelModelLoader() + { + $loader = new ClassLoader(); + + $loader->addPrefix( + '', // no prefix, models already define their full namespace + $this->getPropelModelDir() + ); + + $loader->addPrefix( + '', // no prefix, models already define their full namespace + $this->getPropelDatabaseDir() + ); + + $loader->register( + true // prepend the autoloader to use cached models first + ); + } + + /** + * Initialize the Propel environment and connection. + * @return bool Whether a Propel connection is available. + * @param bool $force force cache generation + * @param bool $cacheRefresh + * @throws \Throwable + * @internal + */ + public function init($force = false, &$cacheRefresh = false) + { + $flockFactory = new Factory(new FlockStore()); + + $lock = $flockFactory->createLock('propel-cache-generation'); + + // Acquire a blocking cache generation lock + $lock->acquire(true); + + try { + if ($force) { + (new Filesystem())->remove($this->getPropelCacheDir()); + } + + if (!file_exists($this->getTheliaDatabaseConfigFile())) { + return false; + } + + $this->buildPropelConfig(); + + $this->buildPropelInitFile(); + + require $this->getPropelInitFile(); + + $theliaDatabaseConnection = Propel::getConnection('thelia'); + $this->schemaLocator->setTheliaDatabaseConnection($theliaDatabaseConnection); + + $buildPropelGlobalSchema = $this->buildPropelGlobalSchema(); + $buildPropelModels = $this->buildPropelModels(); + + if ($buildPropelGlobalSchema || $buildPropelModels) { + $cacheRefresh = true; + } + + $this->registerPropelModelLoader(); + + $theliaDatabaseConnection->setAttribute(ConnectionWrapper::PROPEL_ATTR_CACHE_PREPARES, true); + + if ($this->debug) { + // In debug mode, we have to initialize Tlog at this point, as this class uses Propel + Tlog::getInstance()->setLevel(Tlog::DEBUG); + + Propel::getServiceContainer()->setLogger('defaultLogger', Tlog::getInstance()); + $theliaDatabaseConnection->useDebug(true); + } + } catch (\Throwable $th) { + $fs = new Filesystem(); + $fs->remove(THELIA_CACHE_DIR . $this->environment); + $fs->remove($this->getPropelModelDir()); + throw $th; + } finally { + // Release cache generation lock + $lock->release(); + } + + return true; + } +} diff --git a/core/lib/Thelia/Core/Routing/RewritingRouter.php b/core/lib/Thelia/Core/Routing/RewritingRouter.php new file mode 100644 index 00000000..1ffca3ce --- /dev/null +++ b/core/lib/Thelia/Core/Routing/RewritingRouter.php @@ -0,0 +1,279 @@ + + * @author Etienne Roudeix + */ +class RewritingRouter implements RouterInterface, RequestMatcherInterface +{ + /** + * @var RequestContext The context + */ + protected $context; + + /** + * @var array options, don't use for now but mandatory + */ + protected $options; + + /** + * Sets the request context. + * + * @param RequestContext $context The context + * + * @api + */ + public function setContext(RequestContext $context) + { + $this->context = $context; + } + + /** + * Gets the request context. + * + * @return RequestContext The context + * + * @api + */ + public function getContext() + { + return $this->context; + } + + public function setOption($key, $value) + { + //NOTHING TO DO FOR NOW + } + + /** + * Gets the RouteCollection instance associated with this Router. + * + * @return RouteCollection A RouteCollection instance + */ + public function getRouteCollection() + { + return new RouteCollection(); + } + + /** + * Generates a URL or path for a specific route based on the given parameters. + * + * Parameters that reference placeholders in the route pattern will substitute them in the + * path or host. Extra params are added as query string to the URL. + * + * When the passed reference type cannot be generated for the route because it requires a different + * host or scheme than the current one, the method will return a more comprehensive reference + * that includes the required params. For example, when you call this method with $referenceType = ABSOLUTE_PATH + * but the route requires the https scheme whereas the current scheme is http, it will instead return an + * ABSOLUTE_URL with the https scheme and the current host. This makes sure the generated URL matches + * the route in any case. + * + * If there is no route with the given name, the generator must throw the RouteNotFoundException. + * + * @param string $name The name of the route + * @param mixed $parameters An array of parameters + * @param Boolean|string $referenceType The type of reference to be generated (one of the constants) + * + * @return string The generated URL + * + * @throws RouteNotFoundException If the named route doesn't exist + * @throws MissingMandatoryParametersException When some parameters are missing that are mandatory for the route + * @throws InvalidParameterException When a parameter value for a placeholder is not correct because + * it does not match the requirement + * + * @api + */ + public function generate($name, $parameters = array(), $referenceType = self::ABSOLUTE_PATH) + { + throw new RouteNotFoundException(); + } + + /** + * Tries to match a URL path with a set of routes. + * + * If the matcher can not find information, it must throw one of the exceptions documented + * below. + * + * @param string $pathinfo The path info to be parsed (raw format, i.e. not urldecoded) + * + * @return array An array of parameters + * + * @throws ResourceNotFoundException If the resource could not be found + * @throws MethodNotAllowedException If the resource was found but the request method is not allowed + * + * @api + */ + public function match($pathinfo) + { + throw new ResourceNotFoundException("impossible to find route with this method, please use matchRequest method"); + } + + /** + * Tries to match a request with a set of routes. + * + * If the matcher can not find information, it must throw one of the exceptions documented + * below. + * + * @param Request $request The request to match + * + * @throws \Exception|\Thelia\Exception\UrlRewritingException + * @throws \Symfony\Component\Routing\Exception\ResourceNotFoundException + * @return array An array of parameters + * + */ + public function matchRequest(Request $request) + { + if (ConfigQuery::isRewritingEnable()) { + $urlTool = URL::getInstance(); + + $pathInfo = $request instanceof TheliaRequest ? $request->getRealPathInfo() : $request->getPathInfo(); + + try { + $rewrittenUrlData = $urlTool->resolve($pathInfo); + } catch (UrlRewritingException $e) { + switch ($e->getCode()) { + case UrlRewritingException::URL_NOT_FOUND: + throw new ResourceNotFoundException(); + break; + default: + throw $e; + } + } + + // If we have a "lang" parameter, whe have to check if the found URL has the proper locale + // If it's not the case, find the rewritten URL with the requested locale, and redirect to it. + if (null ==! $requestedLocale = $request->get('lang')) { + if (null !== $requestedLang = LangQuery::create()->findOneByLocale($requestedLocale)) { + if ($requestedLang->getLocale() != $rewrittenUrlData->locale) { + // Save one redirection if requested locale is disabled. + if (! $requestedLang->getActive()) { + $requestedLang = Lang::getDefaultLanguage(); + } + + $localizedUrl = $urlTool->retrieve( + $rewrittenUrlData->view, + $rewrittenUrlData->viewId, + $requestedLang->getLocale() + )->toString(); + + $this->redirect($urlTool->absoluteUrl($localizedUrl), 301); + } + } + } + + // 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 ? */ + if (null !== $rewrittenUrlData->redirectedToUrl) { + $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 */ + + if (null !== $rewrittenUrlData->view) { + $request->attributes->set('_view', $rewrittenUrlData->view); + if (null !== $rewrittenUrlData->viewId) { + $request->query->set($rewrittenUrlData->view . '_id', $rewrittenUrlData->viewId); + } + } + + if (null !== $rewrittenUrlData->locale) { + $this->manageLocale($rewrittenUrlData, $request); + } + + + foreach ($rewrittenUrlData->otherParameters as $parameter => $value) { + $request->query->set($parameter, $value); + } + + return array( + '_controller' => 'Thelia\\Controller\\Front\\DefaultController::noAction', + '_route' => 'rewrite', + '_rewritten' => true, + ); + } + throw new ResourceNotFoundException(); + } + + protected function manageLocale(RewritingResolver $rewrittenUrlData, TheliaRequest $request) + { + $lang = LangQuery::create() + ->findOneByLocale($rewrittenUrlData->locale); + + $langSession = $request->getSession()->getLang(); + + if ($lang != $langSession) { + if (ConfigQuery::isMultiDomainActivated()) { + $this->redirect( + sprintf("%s/%s", $lang->getUrl(), $rewrittenUrlData->rewrittenUrl), + 301 + ); + } else { + $request->getSession()->setLang($lang); + } + } + } + + protected function redirect($url, $status = 302) + { + throw new RedirectException($url, $status); + } +} diff --git a/core/lib/Thelia/Core/Security/AccessManager.php b/core/lib/Thelia/Core/Security/AccessManager.php new file mode 100644 index 00000000..c5d08941 --- /dev/null +++ b/core/lib/Thelia/Core/Security/AccessManager.php @@ -0,0 +1,94 @@ + + */ +class AccessManager +{ + const VIEW = 'VIEW'; + const CREATE = 'CREATE'; + const UPDATE = 'UPDATE'; + const DELETE = 'DELETE'; + + protected $accessGranted = array( + self::VIEW => false, + self::CREATE => false, + self::UPDATE => false, + self::DELETE => false, + ); + + protected static $accessPows = array( + self::VIEW => 3, + self::CREATE => 2, + self::UPDATE => 1, + self::DELETE => 0, + ); + + protected $accessValue; + + public function __construct($accessValue) + { + $this->accessValue = $accessValue; + + $this->fillGrantedAccess(); + } + + public function can($type) + { + if (!array_key_exists($type, $this->accessGranted)) { + return false; + } + + return $this->accessGranted[$type]; + } + + public static function getMaxAccessValue() + { + return pow(2, current(\array_slice(self::$accessPows, -1, 1, true))) - 1; + } + + public function build($accesses) + { + $this->accessValue = 0; + foreach ($accesses as $access) { + if (array_key_exists($access, self::$accessPows)) { + $this->accessValue += pow(2, self::$accessPows[$access]); + } + } + + $this->fillGrantedAccess(); + } + + protected function fillGrantedAccess() + { + $accessValue = $this->accessValue; + foreach (self::$accessPows as $type => $value) { + $pow = pow(2, $value); + if ($accessValue >= $pow) { + $accessValue -= $pow; + $this->accessGranted[$type] = true; + } else { + $this->accessGranted[$type] = false; + } + } + } + + public function getAccessValue() + { + return $this->accessValue; + } +} diff --git a/core/lib/Thelia/Core/Security/Authentication/AdminTokenAuthenticator.php b/core/lib/Thelia/Core/Security/Authentication/AdminTokenAuthenticator.php new file mode 100644 index 00000000..4db122f4 --- /dev/null +++ b/core/lib/Thelia/Core/Security/Authentication/AdminTokenAuthenticator.php @@ -0,0 +1,26 @@ + 'email' + ) + ); + } +} diff --git a/core/lib/Thelia/Core/Security/Authentication/TokenAuthenticator.php b/core/lib/Thelia/Core/Security/Authentication/TokenAuthenticator.php new file mode 100644 index 00000000..cd1206ab --- /dev/null +++ b/core/lib/Thelia/Core/Security/Authentication/TokenAuthenticator.php @@ -0,0 +1,45 @@ +key = $key; + + $this->userProvider = $userProvider; + } + + /** + * @see \Thelia\Core\Security\Authentication\AuthenticatorInterface::getAuthentifiedUser() + */ + public function getAuthentifiedUser() + { + $keyData = $this->userProvider->decodeKey($this->key); + + $user = $this->userProvider->getUser($keyData); + + if ($user === null) { + throw new TokenAuthenticationException("No user matches the provided token"); + } + return $user; + } +} diff --git a/core/lib/Thelia/Core/Security/Authentication/UsernamePasswordFormAuthenticator.php b/core/lib/Thelia/Core/Security/Authentication/UsernamePasswordFormAuthenticator.php new file mode 100644 index 00000000..65f29eb6 --- /dev/null +++ b/core/lib/Thelia/Core/Security/Authentication/UsernamePasswordFormAuthenticator.php @@ -0,0 +1,97 @@ +request = $request; + $this->baseLoginForm = $loginForm; + $this->loginForm = $this->baseLoginForm->getForm(); + $this->userProvider = $userProvider; + + $defaults = array( + 'required_method' => 'POST', + 'username_field_name' => 'username', + 'password_field_name' => 'password' + ); + + $this->options = array_merge($defaults, $options); + } + + /** + * @return string the username value + */ + public function getUsername() + { + return $this->loginForm->get($this->options['username_field_name'])->getData(); + } + + /** + * @see \Thelia\Core\Security\Authentication\AuthenticatorInterface::getAuthentifiedUser() + */ + public function getAuthentifiedUser() + { + if ($this->request->isMethod($this->options['required_method'])) { + if (! $this->loginForm->isValid()) { + throw new ValidatorException("Form is not valid."); + } + + // Retreive user + $username = $this->getUsername(); + $password = $this->loginForm->get($this->options['password_field_name'])->getData(); + + $user = $this->userProvider->getUser($username); + + if ($user === null) { + throw new UsernameNotFoundException(sprintf("Username '%s' was not found.", $username)); + } + + // Check user password + $authOk = $user->checkPassword($password) === true; + + if ($authOk !== true) { + 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; + } + + throw new \RuntimeException("Invalid method."); + } +} diff --git a/core/lib/Thelia/Core/Security/Exception/AuthenticationException.php b/core/lib/Thelia/Core/Security/Exception/AuthenticationException.php new file mode 100644 index 00000000..f316faf0 --- /dev/null +++ b/core/lib/Thelia/Core/Security/Exception/AuthenticationException.php @@ -0,0 +1,39 @@ +loginTemplate; + } + + /** + * Set the login template name + * + * @param string $loginPath the login template name + */ + public function setLoginTemplate($loginTemplate) + { + $this->loginTemplate = $loginTemplate; + } +} diff --git a/core/lib/Thelia/Core/Security/Exception/AuthorizationException.php b/core/lib/Thelia/Core/Security/Exception/AuthorizationException.php new file mode 100644 index 00000000..1f37f88a --- /dev/null +++ b/core/lib/Thelia/Core/Security/Exception/AuthorizationException.php @@ -0,0 +1,17 @@ + + */ +class CustomerNotConfirmedException extends AuthenticationException +{ + /** @var Customer */ + protected $user; + + /** + * @return Customer + */ + public function getUser() + { + return $this->user; + } + + /** + * @param Customer $user + * @return $this + */ + public function setUser(Customer $user) + { + $this->user = $user; + return $this; + } +} diff --git a/core/lib/Thelia/Core/Security/Exception/ResourceException.php b/core/lib/Thelia/Core/Security/Exception/ResourceException.php new file mode 100644 index 00000000..9f4e188d --- /dev/null +++ b/core/lib/Thelia/Core/Security/Exception/ResourceException.php @@ -0,0 +1,28 @@ + + */ +class AdminResources +{ + /** + * @deprecated 2.3 + * @removed 2.5 + */ + private static $selfReflection = null; + + /** + * @deprecated 2.3 + * @removed 2.5 + * @param $name + * @return string the constant value + */ + public static function retrieve($name) + { + $constantName = strtoupper($name); + if (null === self::$selfReflection) { + self::$selfReflection = new \ReflectionClass(__CLASS__); + } + if (self::$selfReflection->hasConstant($constantName)) { + return self::$selfReflection->getConstant($constantName); + } else { + throw new ResourceException(sprintf('Resource `%s` not found', $constantName), ResourceException::RESOURCE_NOT_FOUND); + } + } + + const SUPERADMINISTRATOR = "SUPERADMINISTRATOR"; + + const ADDRESS = "admin.address"; + + const ADMINISTRATOR = "admin.configuration.administrator"; + + const ADVANCED_CONFIGURATION = "admin.configuration.advanced"; + + const AREA = "admin.configuration.area"; + + const ATTRIBUTE = "admin.configuration.attribute"; + + const BRAND = "admin.brand"; + + const CATEGORY = "admin.category"; + + const CONFIG = "admin.configuration"; + + const CONTENT = "admin.content"; + + const COUNTRY = "admin.configuration.country"; + + const STATE = "admin.configuration.state"; + + const COUPON = "admin.coupon"; + + const CURRENCY = "admin.configuration.currency"; + + const CUSTOMER = "admin.customer"; + + const FEATURE = "admin.configuration.feature"; + + const FOLDER = "admin.folder"; + + const HOME = "admin.home"; + + const LANGUAGE = "admin.configuration.language"; + + const MAILING_SYSTEM = "admin.configuration.mailing-system"; + + const MESSAGE = "admin.configuration.message"; + + const MODULE = "admin.module"; + + const HOOK = "admin.hook"; + + const MODULE_HOOK = "admin.module-hook"; + + const ORDER = "admin.order"; + + const ORDER_STATUS = "admin.configuration.order-status"; + + const PRODUCT = "admin.product"; + + const PROFILE = "admin.configuration.profile"; + + const SHIPPING_ZONE = "admin.configuration.shipping-zone"; + + const TAX = "admin.configuration.tax"; + + const TEMPLATE = "admin.configuration.template"; + + const SYSTEM_LOG = "admin.configuration.system-logs"; + + const ADMIN_LOG = "admin.configuration.admin-logs"; + + const STORE = "admin.configuration.store"; + + const TRANSLATIONS = "admin.configuration.translations"; + + const UPDATE = "admin.configuration.update"; + + const EXPORT = "admin.export"; + + const IMPORT = "admin.import"; + + const TOOLS = "admin.tools"; + + const SALES = "admin.sales"; + + const API = "admin.configuration.api"; + + const TITLE = "admin.customer.title"; + + /** + * Stock all resources by modules + * Exemple : + * [ + * "thelia" => [ + * "ADDRESS" => "admin.address", + * ... + * ], + * "Front" => [ + * ... + * ] + * ] + * @var Array $resources + */ + protected $resources; + + /** + * Create a new AdminRessources instance. + * + * @param array $resources with format module => [ KEY => value ]. + */ + public function __construct($resources) + { + $this->resources = $resources; + } + + /** + * @param string $name + * @param string $module + * @return string + */ + public function getResource($name, $module = "thelia") + { + $constantName = strtoupper($name); + + if (isset($this->resources[$module])) { + if (isset($this->resources[$module][$constantName])) { + return $this->resources[$module][$constantName]; + } else { + throw new ResourceException(sprintf('Resource `%s` not found', $module), + ResourceException::RESOURCE_NOT_FOUND); + } + } else { + throw new ResourceException(sprintf('Module `%s` not found', $module), + ResourceException::RESOURCE_NOT_FOUND); + } + } + + /** + * @param $data with format + * [ + * "ADDRESS" => "admin.address", + * ... + * ] + * @param $module string ModuleCode + * @throws \Exception + */ + public function addModuleResources($data, $module = 'thelia') + { + if (null !== $data && \is_array($data)) { + $this->resources[$module] = $data; + } else { + throw new \Exception("Format pass to addModuleResources method is not valid"); + } + } + + /** + * @param string $name + * @param string $value + * @param string $module + */ + public function addResource($name, $value, $module = 'thelia') + { + if (null !== $name && null !== $value) { + $nameFormated = strtoupper($name); + if (!$this->resources[$module]) { + $this->resources[$module] = []; + } + $this->resources[$module][$nameFormated] = $value; + } + } +} diff --git a/core/lib/Thelia/Core/Security/Role/Role.php b/core/lib/Thelia/Core/Security/Role/Role.php new file mode 100644 index 00000000..08b5d7c6 --- /dev/null +++ b/core/lib/Thelia/Core/Security/Role/Role.php @@ -0,0 +1,46 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Thelia\Core\Security\Role; + +/** + * Role is a simple implementation of a RoleInterface where the role is a + * string. + * + * @author Fabien Potencier + */ +class Role implements RoleInterface +{ + private $role; + + /** + * Constructor. + * + * @param string $role The role name + */ + public function __construct($role) + { + $this->role = (string) $role; + } + + /** + * {@inheritdoc} + */ + public function getRole() + { + return $this->role; + } + + public function __toString() + { + return $this->role; + } +} diff --git a/core/lib/Thelia/Core/Security/Role/RoleInterface.php b/core/lib/Thelia/Core/Security/Role/RoleInterface.php new file mode 100644 index 00000000..2771d6e7 --- /dev/null +++ b/core/lib/Thelia/Core/Security/Role/RoleInterface.php @@ -0,0 +1,35 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Thelia\Core\Security\Role; + +/** + * RoleInterface represents a role granted to a user. + * + * A role must either have a string representation or it needs to be explicitly + * supported by at least one AccessDecisionManager. + * + * @author Fabien Potencier + */ +interface RoleInterface +{ + /** + * Returns the role. + * + * This method returns a string representation whenever possible. + * + * When the role cannot be represented with sufficient precision by a + * string, it should return null. + * + * @return string|null A string representation of the role, or null + */ + public function getRole(); +} diff --git a/core/lib/Thelia/Core/Security/SecurityContext.php b/core/lib/Thelia/Core/Security/SecurityContext.php new file mode 100644 index 00000000..1d78a740 --- /dev/null +++ b/core/lib/Thelia/Core/Security/SecurityContext.php @@ -0,0 +1,262 @@ + + */ +class SecurityContext +{ + /** @var RequestStack */ + private $requestStack; + + public function __construct(RequestStack $requestStack) + { + $this->requestStack = $requestStack; + } + + /** + * @return Session + */ + private function getSession() + { + $session = $this->requestStack->getCurrentRequest()->getSession(); + + if ($session === null) { + throw new \LogicException("No session found."); + } + + return $session; + } + + /** + * Gets the currently authenticated user in the admin, or null if none is defined + * + * @return UserInterface|null A UserInterface instance or null if no user is available + */ + public function getAdminUser() + { + return $this->getSession()->getAdminUser(); + } + + /** + * Check if an admin user is logged in. + * + * @return true if an admin user is logged in, false otherwise. + */ + public function hasAdminUser() + { + return $this->getSession()->getAdminUser() !== null; + } + + /** + * Gets the currently authenticated customer, or null if none is defined + * + * @return Customer|null A UserInterface instance or null if no user is available + */ + public function getCustomerUser() + { + return $this->getSession()->getCustomerUser(); + } + + /** + * Check if a customer user is logged in. + * + * @return true if a customer is logged in, false otherwise. + */ + public function hasCustomerUser() + { + return $this->getSession()->getCustomerUser() !== null; + } + + /** + * @return bool true if a user (either admin or customer) is logged in, false otherwise. + */ + final public function hasLoggedInUser() + { + return $this->hasCustomerUser() || $this->hasAdminUser(); + } + + /** + * Check if a user has at least one of the required roles + * + * @param UserInterface $user the user + * @param array $roles the roles + * @return boolean true if the user has the required role, false otherwise + */ + final public function hasRequiredRole(UserInterface $user = null, array $roles = []) + { + if ($user != null) { + // Check if user's roles matches required roles + $userRoles = $user->getRoles(); + + foreach ($userRoles as $role) { + if (\in_array($role, $roles)) { + return true; + } + } + } + + return false; + } + + final public function isUserGranted(array $roles, array $resources, array $modules, array $accesses, UserInterface $user) + { + if (! $this->hasRequiredRole($user, $roles)) { + return false; + } + + if ((empty($resources) && empty($modules)) || empty($accesses)) { + return true; + } + + if (!method_exists($user, 'getPermissions')) { + return false; + } + + $userPermissions = $user->getPermissions(); + + if ($userPermissions === AdminResources::SUPERADMINISTRATOR) { + return true; + } + + foreach ($resources as $resource) { + if ($resource === '') { + continue; + } + + $resource = strtolower($resource); + + if (!array_key_exists($resource, $userPermissions)) { + return false; + } + + foreach ($accesses as $access) { + if (!$userPermissions[$resource]->can($access)) { + return false; + } + } + } + + foreach ($modules as $module) { + if ($module === '') { + continue; + } + + if (!array_key_exists('module', $userPermissions)) { + return false; + } + + $module = strtolower($module); + + if (!array_key_exists($module, $userPermissions['module'])) { + return false; + } + + foreach ($accesses as $access) { + if (!$userPermissions['module'][$module]->can($access)) { + return false; + } + } + } + + return true; + } + + /** + * Checks if the current user is allowed + * + * @return Boolean + */ + final public function isGranted(array $roles, array $resources, array $modules, array $accesses) + { + // Find a user which matches the required roles. + $user = $this->checkRole($roles); + + if (null === $user) { + return false; + } else { + return $this->isUserGranted($roles, $resources, $modules, $accesses, $user); + } + } + + /** + * look if a user has the required role. + * + * @param array $roles + * @return null|UserInterface + */ + public function checkRole(array $roles) + { + // Find a user which matches the required roles. + $user = $this->getCustomerUser(); + + if (! $this->hasRequiredRole($user, $roles)) { + $user = $this->getAdminUser(); + + if (! $this->hasRequiredRole($user, $roles)) { + $user = null; + } + } + + return $user; + } + + /** + * Sets the authenticated admin user. + * + * @param UserInterface $user A UserInterface, or null if no further user should be stored + */ + public function setAdminUser(UserInterface $user) + { + $user->eraseCredentials(); + + $this->getSession()->setAdminUser($user); + } + + /** + * Sets the authenticated customer user. + * + * @param UserInterface $user A UserInterface, or null if no further user should be stored + */ + public function setCustomerUser(UserInterface $user) + { + $user->eraseCredentials(); + + $this->getSession()->setCustomerUser($user); + } + + /** + * Clear the customer from the security context + */ + public function clearCustomerUser() + { + $this->getSession()->clearCustomerUser(); + } + + /** + * Clear the admin from the security context + */ + public function clearAdminUser() + { + $this->getSession()->clearAdminUser(); + } +} diff --git a/core/lib/Thelia/Core/Security/Token/CookieTokenProvider.php b/core/lib/Thelia/Core/Security/Token/CookieTokenProvider.php new file mode 100644 index 00000000..ac045581 --- /dev/null +++ b/core/lib/Thelia/Core/Security/Token/CookieTokenProvider.php @@ -0,0 +1,43 @@ +cookies->has($cookieName)) { + // Create the authenticator + return $request->cookies->get($cookieName); + } + + return null; + } + + public function createCookie(UserInterface $user, $cookieName, $cookieExpires) + { + $tokenProvider = new TokenProvider(); + + $key = $tokenProvider->encodeKey($user); + + setcookie($cookieName, $key, time() + $cookieExpires, '/'); + } + + public function clearCookie($cookieName) + { + setcookie($cookieName, '', time() - 3600, '/'); + } +} diff --git a/core/lib/Thelia/Core/Security/Token/TokenProvider.php b/core/lib/Thelia/Core/Security/Token/TokenProvider.php new file mode 100644 index 00000000..39508619 --- /dev/null +++ b/core/lib/Thelia/Core/Security/Token/TokenProvider.php @@ -0,0 +1,41 @@ +setToken(uniqid()); + + return base64_encode(sprintf("%s\0%s\0%s", $user->getUsername(), $user->getToken(), $user->getSerial())); + } + + public function decodeKey($key) + { + $data = explode("\0", base64_decode($key), 3); + + if (\count($data) !== 3) { + $data = ["", "", ""]; + } + + return array( + 'username' => $data[0], + 'token' => $data[1], + 'serial' => $data[2] + ); + } +} diff --git a/core/lib/Thelia/Core/Security/User/UserInterface.php b/core/lib/Thelia/Core/Security/User/UserInterface.php new file mode 100644 index 00000000..0d63731c --- /dev/null +++ b/core/lib/Thelia/Core/Security/User/UserInterface.php @@ -0,0 +1,111 @@ + + * + */ +interface UserInterface +{ + /** + * Return the user unique ID + * @return int + */ + public function getId(); + + /** + * Return the user unique name + * @return String + */ + public function getUsername(); + + /** + * Return the user encoded password + * @return String + */ + public function getPassword(); + + /** + * Check a string against a the user password + * + * @param string $password + * @return bool + */ + public function checkPassword($password); + + /** + * Returns the roles granted to the user. + * + * + * public function getRoles() + * { + * return array('USER'); + * } + * + * + * @return Role[] The user roles + */ + public function getRoles(); + + /** + * Removes sensitive data from the user. + * + * This is important if, at any given point, sensitive information like + * the plain-text password is stored on this object. + * + * @return void + */ + public function eraseCredentials(); + + /** + * return the user token (used by remember me authnetication system) + * + * @return String + */ + public function getToken(); + + /** + * Set a token in the user data (used by remember me authnetication system) + * + * @param string $token + */ + public function setToken($token); + + /** + * return the user serial (used by remember me authnetication system) + * + * @return String + */ + public function getSerial(); + + /** + * Set a serial number int the user data (used by remember me authnetication system) + * + * @param string $serial + */ + public function setSerial($serial); + + + /** + * Get the user preferred locale + * + * @return string the locale + */ + public function getLocale(); + +} diff --git a/core/lib/Thelia/Core/Security/User/UserPermissionsTrait.php b/core/lib/Thelia/Core/Security/User/UserPermissionsTrait.php new file mode 100644 index 00000000..b296e8a7 --- /dev/null +++ b/core/lib/Thelia/Core/Security/User/UserPermissionsTrait.php @@ -0,0 +1,55 @@ +getProfileId(); + + if (null === $profileId || 0 === $profileId) { + return AdminResources::SUPERADMINISTRATOR; + } + + $userResourcePermissionsQuery = ProfileResourceQuery::create() + ->joinResource("resource", Criteria::LEFT_JOIN) + ->withColumn('resource.code', 'code') + ->filterByProfileId($profileId) + ->find(); + + $userModulePermissionsQuery = ProfileModuleQuery::create() + ->joinModule("module", Criteria::LEFT_JOIN) + ->withColumn('module.code', 'code') + ->filterByProfileId($profileId) + ->find(); + + $userPermissions = array(); + foreach ($userResourcePermissionsQuery as $userResourcePermission) { + $userPermissions[$userResourcePermission->getVirtualColumn('code')] = new AccessManager($userResourcePermission->getAccess()); + } + foreach ($userModulePermissionsQuery as $userModulePermission) { + $userPermissions['module'][strtolower($userModulePermission->getVirtualColumn('code'))] = new AccessManager($userModulePermission->getAccess()); + } + + return $userPermissions; + } +} diff --git a/core/lib/Thelia/Core/Security/UserProvider/AdminTokenUserProvider.php b/core/lib/Thelia/Core/Security/UserProvider/AdminTokenUserProvider.php new file mode 100644 index 00000000..a297cd2b --- /dev/null +++ b/core/lib/Thelia/Core/Security/UserProvider/AdminTokenUserProvider.php @@ -0,0 +1,28 @@ +filterByLogin($dataArray['username'], Criteria::EQUAL) + ->filterByRememberMeSerial($dataArray['serial'], Criteria::EQUAL) + ->filterByRememberMeToken($dataArray['token'], Criteria::EQUAL) + ->findOne(); + } +} diff --git a/core/lib/Thelia/Core/Security/UserProvider/AdminUserProvider.php b/core/lib/Thelia/Core/Security/UserProvider/AdminUserProvider.php new file mode 100644 index 00000000..d8c993a5 --- /dev/null +++ b/core/lib/Thelia/Core/Security/UserProvider/AdminUserProvider.php @@ -0,0 +1,36 @@ +filterByLogin($key, Criteria::EQUAL) + ->findOne(); + + // Try with email address + if (null == $admin && ! empty($key)) { + $admin = AdminQuery::create() + ->filterByEmail($key, Criteria::EQUAL) + ->findOne(); + } + + return $admin; + } +} diff --git a/core/lib/Thelia/Core/Security/UserProvider/CustomerTokenUserProvider.php b/core/lib/Thelia/Core/Security/UserProvider/CustomerTokenUserProvider.php new file mode 100644 index 00000000..660c66a3 --- /dev/null +++ b/core/lib/Thelia/Core/Security/UserProvider/CustomerTokenUserProvider.php @@ -0,0 +1,28 @@ +filterByEmail($dataArray['username'], Criteria::EQUAL) + ->filterByRememberMeSerial($dataArray['serial'], Criteria::EQUAL) + ->filterByRememberMeToken($dataArray['token'], Criteria::EQUAL) + ->findOne(); + } +} diff --git a/core/lib/Thelia/Core/Security/UserProvider/CustomerUserProvider.php b/core/lib/Thelia/Core/Security/UserProvider/CustomerUserProvider.php new file mode 100644 index 00000000..84256572 --- /dev/null +++ b/core/lib/Thelia/Core/Security/UserProvider/CustomerUserProvider.php @@ -0,0 +1,28 @@ +filterByEmail($key, Criteria::EQUAL) + ->findOne(); + + return $customer; + } +} diff --git a/core/lib/Thelia/Core/Security/UserProvider/TokenUserProvider.php b/core/lib/Thelia/Core/Security/UserProvider/TokenUserProvider.php new file mode 100644 index 00000000..780760ac --- /dev/null +++ b/core/lib/Thelia/Core/Security/UserProvider/TokenUserProvider.php @@ -0,0 +1,20 @@ + + */ +abstract class AbstractSerializer implements SerializerInterface +{ + public function prepareFile(\SplFileObject $fileObject) + { + } + + public function separator() + { + } + + public function finalizeFile(\SplFileObject $fileObject) + { + } +} diff --git a/core/lib/Thelia/Core/Serializer/Serializer/CSVSerializer.php b/core/lib/Thelia/Core/Serializer/Serializer/CSVSerializer.php new file mode 100644 index 00000000..1e20c908 --- /dev/null +++ b/core/lib/Thelia/Core/Serializer/Serializer/CSVSerializer.php @@ -0,0 +1,160 @@ + + */ +class CSVSerializer extends AbstractSerializer +{ + /** + * @var string CSV delimiter char + */ + protected $delimiter = ','; + + /** + * @var string CSV enclosure char + */ + protected $enclosure = '"'; + + /** + * @var null|array Headers + */ + private $headers; + + public function getId() + { + return 'thelia.csv'; + } + + public function getName() + { + return 'CSV'; + } + + public function getExtension() + { + return 'csv'; + } + + public function getMimeType() + { + return 'text/csv'; + } + + /** + * Set delimiter char + * + * @param string $delimiter Delimiter char + * + * @return $this Return $this, allow chaining + */ + public function setDelimiter($delimiter) + { + $this->delimiter = $delimiter; + + return $this; + } + + /** + * Set enclosure char + * + * @param string $enclosure Enclosure char + * + * @return $this Return $this, allow chaining + */ + public function setEnclosure($enclosure) + { + $this->enclosure = $enclosure; + + return $this; + } + + public function prepareFile(\SplFileObject $fileObject) + { + $this->headers = null; + } + + public function serialize($data) + { + if ($this->headers === null) { + $this->headers = array_keys($data); + } + + foreach ($data as &$value) { + if (\is_array($value)) { + $value = gettype($value); + } + } + + $fd = fopen('php://memory', 'w+b'); + fputcsv($fd, $data, $this->delimiter, $this->enclosure); + rewind($fd); + $csvRow = stream_get_contents($fd); + fclose($fd); + + return $csvRow; + } + + public function finalizeFile(\SplFileObject $fileObject) + { + if ($this->headers !== null) { + // Create tmp file with header + $fd = fopen('php://temp', 'w+b'); + fputcsv($fd, $this->headers, $this->delimiter, $this->enclosure); + + // Copy file content into tmp file + $fileObject->rewind(); + fwrite($fd, file_get_contents($fileObject->getPathname())); + + // Overwrite file content with tmp content + rewind($fd); + $fileObject->rewind(); + $fileObject->fwrite(stream_get_contents($fd)); + clearstatcache(true, $fileObject->getPathname()); + + fclose($fd); + } + + // Remove last line feed + $fileObject->ftruncate($fileObject->getSize() - 1); + + clearstatcache(true, $fileObject->getPathname()); + } + + public function unserialize(\SplFileObject $fileObject) + { + $data = []; + + foreach ($fileObject as $index => $row) { + if (empty($row)) { + continue; + } + + if ($index === 0) { + $this->headers = str_getcsv($row, $this->delimiter, $this->enclosure); + continue; + } + + $data[] = array_combine( + $this->headers, + str_getcsv($row, $this->delimiter, $this->enclosure) + ); + } + + return $data; + } +} diff --git a/core/lib/Thelia/Core/Serializer/Serializer/JSONSerializer.php b/core/lib/Thelia/Core/Serializer/Serializer/JSONSerializer.php new file mode 100644 index 00000000..056118dc --- /dev/null +++ b/core/lib/Thelia/Core/Serializer/Serializer/JSONSerializer.php @@ -0,0 +1,67 @@ + + */ +class JSONSerializer extends AbstractSerializer +{ + public function getId() + { + return 'thelia.json'; + } + + public function getName() + { + return 'JSON'; + } + + public function getExtension() + { + return 'json'; + } + + public function getMimeType() + { + return 'application/json'; + } + + public function prepareFile(\SplFileObject $fileObject) + { + $fileObject->fwrite('['); + } + + public function serialize($data) + { + return json_encode($data); + } + + public function separator() + { + return ',' . PHP_EOL; + } + + public function finalizeFile(\SplFileObject $fileObject) + { + $fileObject->fwrite(']'); + } + + public function unserialize(\SplFileObject $fileObject) + { + return json_decode(file_get_contents($fileObject->getPathname()), true); + } +} diff --git a/core/lib/Thelia/Core/Serializer/Serializer/XMLSerializer.php b/core/lib/Thelia/Core/Serializer/Serializer/XMLSerializer.php new file mode 100644 index 00000000..8df88b7f --- /dev/null +++ b/core/lib/Thelia/Core/Serializer/Serializer/XMLSerializer.php @@ -0,0 +1,158 @@ + + */ +class XMLSerializer extends AbstractSerializer +{ + /** + * @var \Symfony\Component\Serializer\Encoder\XmlEncoder An xml encoder instance + */ + private $xmlEncoder; + + /** + * @var integer Position of data start + */ + private $xmlDataStart; + + /** + * @var string Root node name + */ + private $rootNodeName = 'root'; + + /** + * @var string Data node name + */ + private $dataNodeName = 'data'; + + /** + * Class constructor. + */ + public function __construct() + { + $this->xmlEncoder = new XmlEncoder; + $this->xmlEncoder->setRootNodeName($this->dataNodeName); + } + + public function getId() + { + return 'thelia.xml'; + } + + public function getName() + { + return 'XML'; + } + + public function getExtension() + { + return 'xml'; + } + + public function getMimeType() + { + return 'application/xml'; + } + + /** + * Get root node name + * + * @return string Root node name + */ + public function getRootNodeName() + { + return $this->rootNodeName; + } + + /** + * Set root node name + * + * @param string $rootNodeName Root node name + * + * @return $this Return $this, allow chaining + */ + public function setRootNodeName($rootNodeName) + { + $this->rootNodeName = $rootNodeName; + + return $this; + } + + /** + * Get data node name + * + * @return string Root node name + */ + public function getDataNodeName() + { + return $this->dataNodeName; + } + + /** + * Set data node name + * + * @param string $dataNodeName Root node name + * + * @return $this Return $this, allow chaining + */ + public function setDataNodeName($dataNodeName) + { + $this->dataNodeName = $dataNodeName; + $this->xmlEncoder->setRootNodeName($this->dataNodeName); + + return $this; + } + + public function prepareFile(\SplFileObject $fileObject) + { + $this->xmlDataStart = null; + + $fileObject->fwrite( + '' . PHP_EOL . '<' . $this->rootNodeName . '>' . PHP_EOL + ); + } + + public function serialize($data) + { + $xml = $this->xmlEncoder->encode($data, 'array'); + + if ($this->xmlDataStart === null) { + $this->xmlDataStart = strpos($xml, '<' . $this->dataNodeName . '>'); + } + + return substr($xml, $this->xmlDataStart, -1); + } + + public function separator() + { + return PHP_EOL; + } + + public function finalizeFile(\SplFileObject $fileObject) + { + $fileObject->fwrite(PHP_EOL . 'rootNodeName . '>'); + } + + public function unserialize(\SplFileObject $fileObject) + { + $unserializedXml = $this->xmlEncoder->decode(file_get_contents($fileObject->getPathname()), 'null'); + + return reset($unserializedXml); + } +} diff --git a/core/lib/Thelia/Core/Serializer/Serializer/YAMLSerializer.php b/core/lib/Thelia/Core/Serializer/Serializer/YAMLSerializer.php new file mode 100644 index 00000000..1cd1d1db --- /dev/null +++ b/core/lib/Thelia/Core/Serializer/Serializer/YAMLSerializer.php @@ -0,0 +1,53 @@ + + */ +class YAMLSerializer extends AbstractSerializer +{ + public function getId() + { + return 'thelia.yml'; + } + + public function getName() + { + return 'YAML'; + } + + public function getExtension() + { + return 'yaml'; + } + + public function getMimeType() + { + return 'application/x-yaml'; + } + + public function serialize($data) + { + return Yaml::dump([$data]); + } + + public function unserialize(\SplFileObject $fileObject) + { + return Yaml::parse(file_get_contents($fileObject->getPathname())); + } +} diff --git a/core/lib/Thelia/Core/Serializer/SerializerInterface.php b/core/lib/Thelia/Core/Serializer/SerializerInterface.php new file mode 100644 index 00000000..9887102e --- /dev/null +++ b/core/lib/Thelia/Core/Serializer/SerializerInterface.php @@ -0,0 +1,89 @@ + + */ +interface SerializerInterface +{ + /** + * Get serializer identifier + * + * @return string The serializer identifier + */ + public function getId(); + + /** + * Get serializer name + * + * @return string The serializer name + */ + public function getName(); + + /** + * Get serializer extension + * + * @return string The serializer extension + */ + public function getExtension(); + + /** + * Get serializer mime type + * + * @return string The serializer mime type + */ + public function getMimeType(); + + /** + * Prepare file to receive serialized data + * + * @param \SplFileObject $fileObject A file object + */ + public function prepareFile(\SplFileObject $fileObject); + + /** + * Serialize data + * + * @param mixed $data Data to serialize + * + * @return string Serialized data + */ + public function serialize($data); + + /** + * Get string that separate serialized data + * + * @return null|string Wrap separator string + */ + public function separator(); + + /** + * Finalize file with serialized data + * + * @param \SplFileObject $fileObject A file object + */ + public function finalizeFile(\SplFileObject $fileObject); + + /** + * Unserialize data + * + * @param \SplFileObject $fileObject A file object + * + * @return array Unserialized data + */ + public function unserialize(\SplFileObject $fileObject); +} diff --git a/core/lib/Thelia/Core/Serializer/SerializerManager.php b/core/lib/Thelia/Core/Serializer/SerializerManager.php new file mode 100644 index 00000000..19c534ad --- /dev/null +++ b/core/lib/Thelia/Core/Serializer/SerializerManager.php @@ -0,0 +1,141 @@ + + */ +class SerializerManager +{ + /** + * @var array List of handled serializers + */ + protected $serializers = []; + + /** + * Reset manager + * + * @return $this Return $this, allow chaining + */ + public function reset() + { + $this->serializers = []; + + return $this; + } + + /** + * Get all serializers + * + * @return array All serializers + */ + public function getSerializers() + { + return $this->serializers; + } + + /** + * Determine if a serializer exists under the given identifier + * + * @param string $serializerId A serializer identifier + * @param boolean $throwException Throw exception if serializer doesn't exists or not + * + * @throws \InvalidArgumentException if the serializer identifier does not exist + * + * @return boolean True if the serializer exists, false otherwise + */ + public function has($serializerId, $throwException = false) + { + $exists = isset($this->serializers[$serializerId]); + + if (!$exists && $throwException) { + throw new \InvalidArgumentException( + Translator::getInstance()->trans( + 'The serializer identifier "%serializerId" doesn\’t exist', + [ + '%serializerId' => $serializerId + ] + ) + ); + } + + return $exists; + } + + /** + * Get a serializer + * + * @param string $serializerId A serializer identifier + * + * @return \Thelia\Core\Serializer\SerializerInterface Return a serializer + */ + public function get($serializerId) + { + $this->has($serializerId, true); + + return $this->serializers[$serializerId]; + } + + /** + * Set serializers + * + * @param array $serializers An array of serializer + * + * @throws \Exception + * + * @return $this Return $this, allow chaining + */ + public function setSerializers(array $serializers) + { + $this->serializers = []; + + foreach ($serializers as $serializer) { + if (!($serializer instanceof SerializerInterface)) { + throw new \Exception('SerializerManager manage only ' . __NAMESPACE__ . '\\SerializerInterface'); + } + + $this->serializers[$serializer->getId()] = $serializer; + } + + return $this; + } + + /** + * Add a serializer + * + * @param \Thelia\Core\Serializer\SerializerInterface $serializer A serializer + * + * @return $this Return $this, allow chaining + */ + public function add(SerializerInterface $serializer) + { + $this->serializers[$serializer->getId()] = $serializer; + + return $this; + } + + /** + * Remove a serializer + * + * @param string $serializerId A serializer identifier + */ + public function remove($serializerId) + { + $this->has($serializerId, true); + + unset($this->serializers[$serializerId]); + } +} diff --git a/core/lib/Thelia/Core/Stack/ParamInitMiddleware.php b/core/lib/Thelia/Core/Stack/ParamInitMiddleware.php new file mode 100644 index 00000000..12a72641 --- /dev/null +++ b/core/lib/Thelia/Core/Stack/ParamInitMiddleware.php @@ -0,0 +1,168 @@ + + */ +class ParamInitMiddleware implements HttpKernelInterface +{ + /** + * @var HttpKernelInterface + */ + protected $app; + + /** + * @var URL + */ + protected $urlManager; + + /** + * @var Translator + */ + protected $translator; + + /** + * @var EventDispatcherInterface + */ + protected $eventDispatcher; + + /** + * @param HttpKernelInterface $app + * @param URL $urlManager + * @param Translator $translator + * @param EventDispatcherInterface $eventDispatcher + */ + public function __construct(HttpKernelInterface $app, URL $urlManager, Translator $translator, EventDispatcherInterface $eventDispatcher) + { + $this->app = $app; + $this->urlManager = $urlManager; + $this->translator = $translator; + $this->eventDispatcher = $eventDispatcher; + } + + /** + * @inheritdoc + */ + public function handle(Request $request, $type = self::MASTER_REQUEST, $catch = true) + { + if ($type == HttpKernelInterface::MASTER_REQUEST) { + $response = $this->initParam($request); + + if ($response instanceof Response) { + return $response; + } + } + + return $this->app->handle($request, $type, $catch); + } + + protected function initParam(TheliaRequest $request) + { + $lang = $this->detectLang($request); + + if ($lang instanceof Response) { + return $lang; + } + + if ($lang) { + $request->getSession()->setLang($lang); + } + + return null; + } + + /** + * @param TheliaRequest $request + * @return null|\Thelia\Model\Lang + */ + protected function detectLang(TheliaRequest $request) + { + // first priority => lang parameter present in request (get or post) + $requestedLangCodeOrLocale = $request->query->get("lang"); + + // add a fallback on locale parameter + if (null === $requestedLangCodeOrLocale) { + $requestedLangCodeOrLocale = $request->query->get("locale"); + } + + // The lang parameter may contains a lang code (fr, en, ru) for Thelia < 2.2, + // or a locale (fr_FR, en_US, etc.) for Thelia > 2.2.beta1 + if (null !== $requestedLangCodeOrLocale) { + if (\strlen($requestedLangCodeOrLocale) > 2) { + $lang = LangQuery::create()->findOneByLocale($requestedLangCodeOrLocale); + } else { + $lang = LangQuery::create()->findOneByCode($requestedLangCodeOrLocale); + } + + if (\is_null($lang)) { + return Lang::getDefaultLanguage(); + } + + // if each lang has its own domain, we redirect the user to the proper one. + if (ConfigQuery::isMultiDomainActivated()) { + $domainUrl = $lang->getUrl(); + + if (! empty($domainUrl)) { + // if lang domain is different from current domain, redirect to the proper one + if (rtrim($domainUrl, "/") != $request->getSchemeAndHttpHost()) { + return new RedirectResponse($domainUrl, 301); + } else { + //the user is currently on the proper domain, nothing to change + return null; + } + } + + Tlog::getInstance()->warning("The domain URL for language ".$lang->getTitle()." (id ".$lang->getId().") is not defined."); + + return Lang::getDefaultLanguage(); + } else { + // one domain for all languages, the lang has to be set into session + return $lang; + } + } + + // Next, check if lang is defined in the current session. If not we have to set one. + if (null === $request->getSession()->getLang(false)) { + if (ConfigQuery::isMultiDomainActivated()) { + // find lang with domain + return LangQuery::create()->filterByUrl($request->getSchemeAndHttpHost(), ModelCriteria::LIKE)->findOne(); + } + + // At this point, set the lang to the default one. + return Lang::getDefaultLanguage(); + } + + return null; + } +} diff --git a/core/lib/Thelia/Core/Stack/SessionMiddleware.php b/core/lib/Thelia/Core/Stack/SessionMiddleware.php new file mode 100644 index 00000000..21279456 --- /dev/null +++ b/core/lib/Thelia/Core/Stack/SessionMiddleware.php @@ -0,0 +1,82 @@ + + */ +class SessionMiddleware implements HttpKernelInterface +{ + /** + * @var HttpKernelInterface + */ + protected $app; + + protected $eventDispatcher; + + protected $cacheDir; + + protected $env; + + protected $debug; + + protected static $session; + + /** + * @param HttpKernelInterface $app + * @param EventDispatcherInterface $eventDispatcherInterface + * @param $cacheDir + * @param $debug + * @param $env + * @internal param ContainerInterface $container + */ + public function __construct(HttpKernelInterface $app, EventDispatcherInterface $eventDispatcherInterface, $cacheDir, $debug, $env) + { + $this->app = $app; + $this->eventDispatcher = $eventDispatcherInterface; + $this->cacheDir = $cacheDir; + $this->debug = $debug; + $this->env = $env; + } + + /* + * @inherited + */ + public function handle(Request $request, $type = self::MASTER_REQUEST, $catch = true) + { + if ($type == HttpKernelInterface::MASTER_REQUEST) { + if (null === $session = self::$session) { + $event = new SessionEvent($this->cacheDir, $this->debug, $this->env); + + $this->eventDispatcher->dispatch(TheliaKernelEvents::SESSION, $event); + + self::$session = $session = $event->getSession(); + } + + $session->start(); + $request->setSession($session); + } + + return $this->app->handle($request, $type, $catch); + } +} diff --git a/core/lib/Thelia/Core/Template/Assets/AssetManagerInterface.php b/core/lib/Thelia/Core/Template/Assets/AssetManagerInterface.php new file mode 100644 index 00000000..ca319d9c --- /dev/null +++ b/core/lib/Thelia/Core/Template/Assets/AssetManagerInterface.php @@ -0,0 +1,71 @@ + + */ +class AsseticAssetManager implements AssetManagerInterface +{ + protected $debugMode; + + protected $source_file_extensions = array('less', 'js', 'coffee', 'html', 'tpl', 'htm', 'xml'); + + protected $assetFilters = []; + + public function __construct($debugMode) + { + $this->debugMode = $debugMode; + } + + /** + * Create a stamp form the modification time of the content of the given directory and all of its subdirectories + * + * @param string $directory ther directory name + * @return string the stamp of this directory + */ + protected function getStamp($directory) + { + $stamp = ''; + + $iterator = new \RecursiveIteratorIterator( + new \RecursiveDirectoryIterator($directory, \RecursiveDirectoryIterator::SKIP_DOTS), + \RecursiveIteratorIterator::LEAVES_ONLY + ); + + foreach ($iterator as $file) { + $stamp .= $file->getMTime(); + } + + return md5($stamp); + } + + /** + * Check if a file is a source asset file + * + * @param \SplFileInfo $fileInfo + * + * @return bool + */ + protected function isSourceFile(\SplFileInfo $fileInfo) + { + return \in_array($fileInfo->getExtension(), $this->source_file_extensions); + } + + /** + * Recursively copy assets from the source directory to the destination + * directory in the web space, omitting source files. + * + * @param Filesystem $fs + * @param string $from_directory the source + * @param string $to_directory the destination + * @throws \RuntimeException if a problem occurs. + */ + protected function copyAssets(Filesystem $fs, $from_directory, $to_directory) + { + Tlog::getInstance()->addDebug("Copying assets from $from_directory to $to_directory"); + + $iterator = new \RecursiveIteratorIterator( + new \RecursiveDirectoryIterator($from_directory, \RecursiveDirectoryIterator::SKIP_DOTS), + \RecursiveIteratorIterator::SELF_FIRST + ); + + $fs->mkdir($to_directory, 0777); + + /** @var \RecursiveDirectoryIterator $iterator */ + foreach ($iterator as $item) { + if ($item->isDir()) { + $dest_dir = $to_directory . DS . $iterator->getSubPathName(); + + if (! is_dir($dest_dir)) { + if ($fs->exists($dest_dir)) { + $fs->remove($dest_dir); + } + + $fs->mkdir($dest_dir, 0777); + } + } elseif (! $this->isSourceFile($item)) { + // We don't copy source files + + $dest_file = $to_directory . DS . $iterator->getSubPathName(); + + if ($fs->exists($dest_file)) { + $fs->remove($dest_file); + } + + $fs->copy($item, $dest_file); + } + } + } + + /** + * Compute the destination directory path, from the source directory and the + * base directory of the web assets + * + * @param string $webAssetsDirectoryBase Base base directory of the web assets + * @param string $webAssetsTemplate The template directory, relative to '/templates' + * @param string $webAssetsKey the assets key : module name or 0 for template assets + * + * @internal param string $source_assets_directory the source directory + * @return string the full path of the destination directory + */ + protected function getDestinationDirectory($webAssetsDirectoryBase, $webAssetsTemplate, $webAssetsKey) + { + // Compute the absolute path of the output directory + return $webAssetsDirectoryBase . DS . $webAssetsTemplate . DS . $webAssetsKey; + } + + /** + * Prepare an asset directory by checking that no changes occured in + * the source directory. If any change is detected, the whole asset directory + * is copied in the web space. + * + * @param string $sourceAssetsDirectory the full path to the source assets directory + * @param string $webAssetsDirectoryBase the base directory of the web based asset directory + * @param $webAssetsTemplate + * @param string $webAssetsKey the assets key : module name or 0 for base template + * + * @throws \RuntimeException if something goes wrong. + */ + public function prepareAssets($sourceAssetsDirectory, $webAssetsDirectoryBase, $webAssetsTemplate, $webAssetsKey) + { + // Compute the absolute path of the output directory + $to_directory = $this->getDestinationDirectory($webAssetsDirectoryBase, $webAssetsTemplate, $webAssetsKey); + + // Get a path to the stamp file + $stamp_file_path = $to_directory . DS . '.source-stamp'; + + // Get the last stamp of source assets directory + $prev_stamp = @file_get_contents($stamp_file_path); + + // Get the current stamp of the source directory + $curr_stamp = $this->getStamp($sourceAssetsDirectory); + + if ($prev_stamp !== $curr_stamp) { + $fs = new Filesystem(); + + $tmp_dir = "$to_directory.tmp"; + + $fs->remove($tmp_dir); + + // Copy the whole source dir in a temp directory + $this->copyAssets($fs, $sourceAssetsDirectory, $tmp_dir); + + // Remove existing directory + if ($fs->exists($to_directory)) { + $fs->remove($to_directory); + } + + // Put in place the new directory + $fs->rename($tmp_dir, $to_directory); + + if (false === @file_put_contents($stamp_file_path, $curr_stamp)) { + throw new \RuntimeException( + "Failed to create asset stamp file $stamp_file_path. Please check that your web server has the proper access rights to do that." + ); + } + } + } + + /** + * Decode the filters names, and initialize the Assetic FilterManager + * + * @param FilterManager $filterManager the Assetic filter manager + * @param string|array $filters a comma separated list of filter names + * @throws \InvalidArgumentException if a wrong filter is passed + * @return array an array of filter names + */ + protected function decodeAsseticFilters(FilterManager $filterManager, $filters) + { + if (! empty($filters)) { + $filter_list = \is_array($filters) ? $filters : explode(',', $filters); + + foreach ($filter_list as $filter_name) { + $filter_name = trim($filter_name); + + foreach ($this->assetFilters as $filterIdentifier => $filterInstance) { + if ($filterIdentifier == $filter_name) { + $filterManager->set($filterIdentifier, $filterInstance); + + // No, goto is not evil. + goto filterFound; + } + } + + throw new \InvalidArgumentException("Unsupported Assetic filter: '$filter_name'"); + break; + + filterFound: + } + } else { + $filter_list = array(); + } + + return $filter_list; + } + + /** + * Generates assets from $asset_path in $output_path, using $filters. + * + * @param $assetSource + * @param $assetDirectoryBase + * @param string $webAssetsDirectoryBase the full path to the asset file (or file collection, e.g. *.less) + * + * @param string $webAssetsTemplate the full disk path to the base assets output directory in the web space + * @param $webAssetsKey + * @param string $outputUrl the URL to the base assets output directory in the web space + * + * @param string $assetType the asset type: css, js, ... The generated files will have this extension. Pass an empty string to use the asset source extension. + * @param array $filters a list of filters, as defined below (see switch($filter_name) ...) + * + * @param boolean $debug true / false + * + * @return string The URL to the generated asset file. + */ + public function processAsset($assetSource, $assetDirectoryBase, $webAssetsDirectoryBase, $webAssetsTemplate, $webAssetsKey, $outputUrl, $assetType, $filters, $debug) + { + Tlog::getInstance()->addDebug( + "Processing asset: assetSource=$assetSource, assetDirectoryBase=$assetDirectoryBase, webAssetsDirectoryBase=$webAssetsDirectoryBase, webAssetsTemplate=$webAssetsTemplate, webAssetsKey=$webAssetsKey, outputUrl=$outputUrl" + ); + + $assetName = basename($assetSource); + $inputDirectory = realpath(dirname($assetSource)); + + $assetFileDirectoryInAssetDirectory = trim(str_replace(array($assetDirectoryBase, $assetName), '', $assetSource), DS); + + $am = new AssetManager(); + $fm = new FilterManager(); + + // Get the filter list + $filterList = $this->decodeAsseticFilters($fm, $filters); + + // Factory setup + $factory = new AssetFactory($inputDirectory); + + $factory->setAssetManager($am); + $factory->setFilterManager($fm); + + $factory->setDefaultOutput('*' . (!empty($assetType) ? '.' : '') . $assetType); + + $factory->setDebug($debug); + + $asset = $factory->createAsset($assetName, $filterList); + + $outputDirectory = $this->getDestinationDirectory($webAssetsDirectoryBase, $webAssetsTemplate, $webAssetsKey); + + // Get the URL part from the relative path + $outputRelativeWebPath = $webAssetsTemplate . DS . $webAssetsKey; + + $assetTargetFilename = $asset->getTargetPath(); + + /* + * This is the final name of the generated asset + * We preserve file structure intending to keep - for example - relative css links working + */ + $assetDestinationPath = $outputDirectory . DS . $assetFileDirectoryInAssetDirectory . DS . $assetTargetFilename; + + Tlog::getInstance()->addDebug("Asset destination full path: $assetDestinationPath"); + + // We generate an asset only if it does not exists, or if the asset processing is forced in development mode + if (! file_exists($assetDestinationPath) || ($this->debugMode && ConfigQuery::read('process_assets', true))) { + $writer = new AssetWriter($outputDirectory . DS . $assetFileDirectoryInAssetDirectory); + + Tlog::getInstance()->addDebug("Writing asset to $outputDirectory" . DS . "$assetFileDirectoryInAssetDirectory"); + + $writer->writeAsset($asset); + } + + // Normalize path to generate a valid URL + if (DS != '/') { + $outputRelativeWebPath = str_replace(DS, '/', $outputRelativeWebPath); + $assetFileDirectoryInAssetDirectory = str_replace(DS, '/', $assetFileDirectoryInAssetDirectory); + $assetTargetFilename = str_replace(DS, '/', $assetTargetFilename); + } + + return rtrim($outputUrl, '/') . '/' . trim($outputRelativeWebPath, '/') . '/' . trim($assetFileDirectoryInAssetDirectory, '/') . '/' . ltrim($assetTargetFilename, '/'); + } + + /** + * @inheritdoc + */ + public function isDebugMode() + { + return $this->debugMode; + } + + /** + * @inheritdoc + */ + public function registerAssetFilter($filterIdentifier, $filter) + { + $this->assetFilters[$filterIdentifier] = $filter; + } +} diff --git a/core/lib/Thelia/Core/Template/Assets/Filter/LessDotPhpFilter.php b/core/lib/Thelia/Core/Template/Assets/Filter/LessDotPhpFilter.php new file mode 100644 index 00000000..c67d2efd --- /dev/null +++ b/core/lib/Thelia/Core/Template/Assets/Filter/LessDotPhpFilter.php @@ -0,0 +1,99 @@ + + * @author Kris Wallsmith + * @author Franck Allimant + */ +class LessDotPhpFilter extends LessphpFilter implements EventSubscriberInterface +{ + /** @var string the compiler cache directory */ + private $cacheDir; + + public function __construct($environment = 'prod') + { + // Assign and create the cache directory, if required. + $this->cacheDir = THELIA_CACHE_DIR . $environment . DS . 'less.php'; + + if (! is_dir($this->cacheDir)) { + $fs = new Filesystem(); + + $fs->mkdir($this->cacheDir); + } + } + + public function filterLoad(AssetInterface $asset) + { + $filePath = $asset->getSourceRoot() . DS . $asset->getSourcePath(); + + Tlog::getInstance()->addDebug("Starting CSS processing: $filePath..."); + + $importDirs = []; + + if ($dir = $asset->getSourceDirectory()) { + $importDirs[$dir] = ''; + } + + foreach ($this->loadPaths as $loadPath) { + $importDirs[$loadPath] = ''; + } + + $options = [ + 'cache_dir' => $this->cacheDir, + 'relativeUrls' => false, // Relative paths in less files will be left unchanged. + 'compress' => true, + 'import_dirs' => $importDirs + ]; + + $css_file_name = \Less_Cache::Get([$filePath => ''], $options); + + $content = @file_get_contents($this->cacheDir . DS . $css_file_name); + + if ($content === false) { + $content = ''; + + Tlog::getInstance()->warning("Compilation of $filePath did not generate an output file."); + } + + $asset->setContent($content); + + Tlog::getInstance()->addDebug("CSS processing done."); + } + + public function clearCacheDir() + { + $fs = new Filesystem(); + + $fs->remove($this->cacheDir); + } + + public static function getSubscribedEvents() + { + return [ + TheliaEvents::CACHE_CLEAR => array("clearCacheDir", 128), + ]; + } +} diff --git a/core/lib/Thelia/Core/Template/Element/ArraySearchLoopInterface.php b/core/lib/Thelia/Core/Template/Element/ArraySearchLoopInterface.php new file mode 100644 index 00000000..d81f70b3 --- /dev/null +++ b/core/lib/Thelia/Core/Template/Element/ArraySearchLoopInterface.php @@ -0,0 +1,28 @@ + + * + */ +interface ArraySearchLoopInterface +{ + /** + * this method returns an array + * + * @return array + */ + public function buildArray(); +} diff --git a/core/lib/Thelia/Core/Template/Element/BaseI18nLoop.php b/core/lib/Thelia/Core/Template/Element/BaseI18nLoop.php new file mode 100644 index 00000000..db0969a2 --- /dev/null +++ b/core/lib/Thelia/Core/Template/Element/BaseI18nLoop.php @@ -0,0 +1,108 @@ +locale = ModelCriteriaTools::getI18n( + $this->getBackendContext(), + $this->getLang(), + $search, + $this->getCurrentRequest()->getSession()->getLang()->getLocale(), + $columns, + $foreignTable, + $foreignKey, + $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 + ); + } + } +} diff --git a/core/lib/Thelia/Core/Template/Element/BaseLoop.php b/core/lib/Thelia/Core/Template/Element/BaseLoop.php new file mode 100644 index 00000000..0f3c31e8 --- /dev/null +++ b/core/lib/Thelia/Core/Template/Element/BaseLoop.php @@ -0,0 +1,779 @@ + id) */ + protected static $loopDefinitions = null; + + /** @var ArgumentCollection[] cache for loop arguments (class => ArgumentCollection) */ + protected static $loopDefinitionsArgs = []; + + /** + * @var Request + * @deprecated since 2.3, please use getCurrentRequest() + */ + protected $request; + + /** @var RequestStack */ + protected $requestStack; + + /** @var EventDispatcherInterface */ + protected $dispatcher; + + /** @var SecurityContext */ + protected $securityContext; + + /** @var ContainerInterface Service Container */ + protected $container = null; + + /** @var ArgumentCollection */ + protected $args; + + protected $countable = true; + protected $timestampable = false; + protected $versionable = false; + + /** @var Translator */ + protected $translator = null; + + private static $cacheLoopResult = []; + private static $cacheLoopPagination = []; + private static $cacheCount = []; + + /** @var array cache of event to dispatch */ + protected static $dispatchCache = []; + + /** + * Create a new Loop + * + * @param ContainerInterface $container + */ + public function __construct(ContainerInterface $container) + { + $this->container = $container; + + $this->translator = $container->get("thelia.translator"); + + $this->checkInterface(); + + $this->requestStack = $container->get('request_stack'); + $this->request = $this->getCurrentRequest(); + $this->dispatcher = $container->get('event_dispatcher'); + $this->securityContext = $container->get('thelia.securityContext'); + + $this->initialize(); + } + + /** + * Initialize the loop + * + * First it will get the loop name according to the loop class. + * Then argument definitions is initialized + * + */ + protected function initialize() + { + $class = \get_class($this); + + if (null === self::$loopDefinitions) { + self::$loopDefinitions = \array_flip($this->container->getParameter('thelia.parser.loops')); + } + + if (isset(self::$loopDefinitions[$class])) { + $this->loopName = self::$loopDefinitions[$class]; + } + + if (!isset(self::$loopDefinitionsArgs[$class])) { + $this->args = $this->getArgDefinitions()->addArguments($this->getDefaultArgs(), false); + + $eventName = $this->getDispatchEventName(TheliaEvents::LOOP_EXTENDS_ARG_DEFINITIONS); + if (null !== $eventName) { + $this->dispatcher->dispatch( + $eventName, + new LoopExtendsArgDefinitionsEvent($this) + ); + }; + + self::$loopDefinitionsArgs[$class] = $this->args; + } + + $this->args = self::$loopDefinitionsArgs[$class]; + } + + /** + * Define common loop arguments + * + * @return Argument[] + */ + protected function getDefaultArgs() + { + $defaultArgs = [ + Argument::createBooleanTypeArgument('backend_context', false), + Argument::createBooleanTypeArgument('force_return', false), + Argument::createAnyTypeArgument('type'), + Argument::createBooleanTypeArgument('no-cache', false), + Argument::createBooleanTypeArgument('return_url', true) + ]; + + if (true === $this->countable) { + $defaultArgs[] = Argument::createIntTypeArgument('offset', 0); + $defaultArgs[] = Argument::createIntTypeArgument('page'); + $defaultArgs[] = Argument::createIntTypeArgument('limit', PHP_INT_MAX); + } + + if ($this instanceof SearchLoopInterface) { + $defaultArgs[] = Argument::createAnyTypeArgument('search_term'); + $defaultArgs[] = new Argument( + 'search_in', + new TypeCollection( + new EnumListType($this->getSearchIn()) + ) + ); + $defaultArgs[] = new Argument( + 'search_mode', + new TypeCollection( + new EnumType( + [ + SearchLoopInterface::MODE_ANY_WORD, + SearchLoopInterface::MODE_SENTENCE, + SearchLoopInterface::MODE_STRICT_SENTENCE, + ] + ) + ), + SearchLoopInterface::MODE_STRICT_SENTENCE + ); + } + + return $defaultArgs; + } + + /** + * Provides a getter to loop parameter values + * + * @param string $name the method name (only getArgname is supported) + * @param mixed $arguments this parameter is ignored + * + * @return mixed the argument value + * @throws \InvalidArgumentException if the parameter is unknown or the method name is not supported. + */ + public function __call($name, $arguments) + { + if (substr($name, 0, 3) == 'get') { + // camelCase to underscore: getNotEmpty -> not_empty + $argName = strtolower(preg_replace('/([^A-Z])([A-Z])/', "$1_$2", substr($name, 3))); + + return $this->getArgValue($argName); + } + + throw new \InvalidArgumentException( + $this->translator->trans("Unsupported magic method %name. only getArgname() is supported.", ['%name' => $name]) + ); + } + + /** + * Initialize the loop arguments. + * + * @param array $nameValuePairs a array of name => value pairs. The name is the name of the argument. + * + * @throws \InvalidArgumentException if some argument values are missing, or invalid + */ + public function initializeArgs(array $nameValuePairs) + { + $faultActor = []; + $faultDetails = []; + + if (null !== $eventName = $this->getDispatchEventName(TheliaEvents::LOOP_EXTENDS_INITIALIZE_ARGS)) { + $event = new LoopExtendsInitializeArgsEvent($this, $nameValuePairs); + $this->dispatcher->dispatch($eventName, $event); + $nameValuePairs = $event->getLoopParameters(); + } + + $loopType = isset($nameValuePairs['type']) ? $nameValuePairs['type'] : "undefined"; + $loopName = isset($nameValuePairs['name']) ? $nameValuePairs['name'] : "undefined"; + + $this->args->rewind(); + while (($argument = $this->args->current()) !== false) { + $this->args->next(); + + $value = isset($nameValuePairs[$argument->name]) ? $nameValuePairs[$argument->name] : null; + + /* check if mandatory */ + if ($value === null && $argument->mandatory) { + $faultActor[] = $argument->name; + $faultDetails[] = $this->translator->trans( + '"%param" parameter is missing in loop type: %type, name: %name', + [ + '%param' => $argument->name, + '%type' => $loopType, + '%name' => $loopName + ] + ); + } elseif ($value === '') { + if (!$argument->empty) { + /* check if empty */ + $faultActor[] = $argument->name; + $faultDetails[] = $this->translator->trans( + '"%param" parameter cannot be empty in loop type: %type, name: %name', + [ + '%param' => $argument->name, + '%type' => $loopType, + '%name' => $loopName + ] + ); + } + } elseif ($value !== null && !$argument->type->isValid($value)) { + /* check type */ + $faultActor[] = $argument->name; + $faultDetails[] = $this->translator->trans( + 'Invalid value "%value" for "%param" parameter in loop type: %type, name: %name', + [ + '%value' => $value, + '%param' => $argument->name, + '%type' => $loopType, + '%name' => $loopName + ] + ); + } else { + /* set default value */ + /* did it as last checking for we consider default value is acceptable no matter type or empty restriction */ + if ($value === null) { + $value = $argument->default; + } + + $argument->setValue($value); + } + } + + if (! empty($faultActor)) { + $complement = sprintf('[%s]', implode(', ', $faultDetails)); + + throw new \InvalidArgumentException($complement); + } + } + + /** + * Return a loop argument + * + * @param string $argumentName the argument name + * + * @return Argument the loop argument. + * @throws \InvalidArgumentException if argument is not found in loop argument list + */ + protected function getArg($argumentName) + { + $arg = $this->args->get($argumentName); + + if ($arg === null) { + throw new \InvalidArgumentException( + $this->translator->trans('Undefined loop argument "%name"', ['%name' => $argumentName]) + ); + } + + return $arg; + } + + /** + * Return a loop argument value + * + * @param string $argumentName the argument name + * + * @throws \InvalidArgumentException if argument is not found in loop argument list + * @return mixed the loop argument value + */ + protected function getArgValue($argumentName) + { + return $this->getArg($argumentName)->getValue(); + } + + /** + * @param ModelCriteria $search the search request + * @param PropelModelPager|null $pagination the pagination part + * + * @return array|PropelModelPager|ObjectCollection + * @throws \InvalidArgumentException if the search mode is undefined. + */ + protected function search(ModelCriteria $search, &$pagination = null) + { + if (false === $this->countable) { + return $search->find(); + } + + $this->setupSearchContext($search); + + if ($this->getArgValue('page') !== null) { + return $this->searchWithPagination($search, $pagination); + } else { + return $this->searchWithOffset($search); + } + } + + protected function setupSearchContext(ModelCriteria $search) + { + if ($this instanceof SearchLoopInterface) { + $searchTerm = $this->getArgValue('search_term'); + $searchIn = $this->getArgValue('search_in'); + $searchMode = $this->getArgValue('search_mode'); + + if (null !== $searchTerm && null !== $searchIn) { + switch ($searchMode) { + case SearchLoopInterface::MODE_ANY_WORD: + $searchCriteria = Criteria::IN; + $searchTerm = explode(' ', $searchTerm); + break; + case SearchLoopInterface::MODE_SENTENCE: + $searchCriteria = Criteria::LIKE; + $searchTerm = '%' . $searchTerm . '%'; + break; + case SearchLoopInterface::MODE_STRICT_SENTENCE: + $searchCriteria = Criteria::EQUAL; + break; + default: + throw new \InvalidArgumentException( + $this->translator->trans("Undefined search mode '%mode'", ['%mode' => $searchMode]) + ); + } + + $this->doSearch($search, $searchTerm, $searchIn, $searchCriteria); + } + } + } + + protected function searchArray(array $search) + { + if (false === $this->countable) { + return $search; + } + + $limit = (int) $this->getArgValue('limit'); + $offset = (int) $this->getArgValue('offset'); + + if ($this->getArgValue('page') !== null) { + $pageNum = (int) $this->getArgValue('page'); + + $totalPageCount = ceil(\count($search) / $limit); + + if ($pageNum > $totalPageCount || $pageNum <= 0) { + return []; + } + + $firstItem = ($pageNum - 1) * $limit + 1; + + return \array_slice($search, $firstItem, $firstItem + $limit, false); + } else { + return \array_slice($search, $offset, $limit, false); + } + } + + /** + * @param ModelCriteria $search + * + * @return ObjectCollection + */ + protected function searchWithOffset(ModelCriteria $search) + { + $limit = (int) $this->getArgValue('limit'); + + if ($limit >= 0) { + $search->limit($limit); + } + + $search->offset((int) $this->getArgValue('offset')); + + return $search->find(); + } + + /** + * @param ModelCriteria $search + * @param PropelModelPager|null $pagination + * + * @return array|PropelModelPager + */ + protected function searchWithPagination(ModelCriteria $search, &$pagination) + { + $page = (int) $this->getArgValue('page'); + $limit = (int) $this->getArgValue('limit'); + + $pagination = $search->paginate($page, $limit); + + if ($page > $pagination->getLastPage()) { + return []; + } else { + return $pagination; + } + } + + public function count() + { + $hash = $this->args->getHash(); + + if (($isCaching = $this->isCaching()) && isset(self::$cacheCount[$hash])) { + return self::$cacheCount[$hash]; + } + + $count = 0; + if ($this instanceof PropelSearchLoopInterface) { + $searchModelCriteria = $this->extendsBuildModelCriteria($this->buildModelCriteria()); + + if (null === $searchModelCriteria) { + $count = 0; + } else { + $this->setupSearchContext($searchModelCriteria); + + $count = $searchModelCriteria->count(); + } + } elseif ($this instanceof ArraySearchLoopInterface) { + $searchArray = $this->extendsBuildArray($this->buildArray()); + if (null === $searchArray) { + $count = 0; + } else { + $count = \count($searchArray); + } + } + + if ($isCaching) { + self::$cacheCount[$hash] = $count; + } + + return $count; + } + + /** + * @param PropelModelPager $pagination + * + * @return LoopResult + */ + public function exec(&$pagination) + { + $hash = $this->args->getHash(); + + if (($isCaching = $this->isCaching()) && isset(self::$cacheLoopResult[$hash])) { + if (isset(self::$cacheLoopPagination[$hash])) { + $pagination = self::$cacheLoopPagination[$hash]; + } + + return self::$cacheLoopResult[$hash]; + } + + $results = []; + + if ($this instanceof PropelSearchLoopInterface) { + $searchModelCriteria = $this->extendsBuildModelCriteria($this->buildModelCriteria()); + + if (null !== $searchModelCriteria) { + $results = $this->search( + $searchModelCriteria, + $pagination + ); + } + } elseif ($this instanceof ArraySearchLoopInterface) { + $searchArray = $this->extendsBuildArray($this->buildArray()); + + if (null !== $searchArray) { + $results = $this->searchArray($searchArray); + } + } + + $loopResult = new LoopResult($results); + + if (true === $this->countable) { + $loopResult->setCountable(); + } + if (true === $this->timestampable) { + $loopResult->setTimestamped(); + } + if (true === $this->versionable) { + $loopResult->setVersioned(); + } + + $parsedResults = $this->extendsParseResults($this->parseResults($loopResult)); + + $loopResult->finalizeRows(); + + if ($isCaching) { + self::$cacheLoopResult[$hash] = $parsedResults; + + if ($pagination instanceof PropelModelPager) { + self::$cacheLoopPagination[$hash] = clone $pagination; + } + } + + return $parsedResults; + } + + protected function checkInterface() + { + /* Must implement either : + * - PropelSearchLoopInterface + * - ArraySearchLoopInterface + */ + $searchInterface = false; + + if ($this instanceof PropelSearchLoopInterface) { + if (true === $searchInterface) { + throw new LoopException( + $this->translator->trans( + 'Loop cannot implements multiple Search Interfaces : `PropelSearchLoopInterface`, `ArraySearchLoopInterface`' + ), + LoopException::MULTIPLE_SEARCH_INTERFACE + ); + } + $searchInterface = true; + } + + if ($this instanceof ArraySearchLoopInterface) { + if (true === $searchInterface) { + throw new LoopException( + $this->translator->trans( + 'Loop cannot implements multiple Search Interfaces : `PropelSearchLoopInterface`, `ArraySearchLoopInterface`' + ), + LoopException::MULTIPLE_SEARCH_INTERFACE + ); + } + $searchInterface = true; + } + + if (false === $searchInterface) { + throw new LoopException( + $this->translator->trans( + 'Loop must implements one of the following interfaces : `PropelSearchLoopInterface`, `ArraySearchLoopInterface`' + ), + LoopException::SEARCH_INTERFACE_NOT_FOUND + ); + } + + /* Only PropelSearch allows timestamp and version */ + if (!$this instanceof PropelSearchLoopInterface) { + if (true === $this->timestampable) { + throw new LoopException( + $this->translator->trans("Loop must implements 'PropelSearchLoopInterface' to be timestampable"), + LoopException::NOT_TIMESTAMPED + ); + } + + if (true === $this->versionable) { + throw new LoopException( + $this->translator->trans("Loop must implements 'PropelSearchLoopInterface' to be versionable"), + LoopException::NOT_VERSIONED + ); + } + } + } + + protected function isCaching() + { + return !$this->getArg("no-cache")->getValue(); + } + + /** + * @param LoopResult $loopResult + * + * @return LoopResult + */ + abstract public function parseResults(LoopResult $loopResult); + + /** + * Definition of loop arguments + * + * example : + * + * public function getArgDefinitions() + * { + * return new ArgumentCollection( + * + * Argument::createIntListTypeArgument('id'), + * new Argument( + * 'ref', + * new TypeCollection( + * new Type\AlphaNumStringListType() + * ) + * ), + * Argument::createIntListTypeArgument('category'), + * Argument::createBooleanTypeArgument('new'), + * ... + * ); + * } + * + * @return \Thelia\Core\Template\Loop\Argument\ArgumentCollection + */ + abstract protected function getArgDefinitions(); + + /** + * Use this method in order to add fields in sub-classes + * @param LoopResultRow $loopResultRow + * @param object|array $item + * + */ + protected function addOutputFields(LoopResultRow $loopResultRow, $item) + { + } + + /** + * Get the event name for the loop depending of the event name and the loop name. + * + * This function also checks if there are services that listen to this event. + * If not the function returns null. + * + * @param string $eventName the event name (`TheliaEvents::LOOP_EXTENDS_ARG_DEFINITIONS`, + * `TheliaEvents::LOOP_EXTENDS_INITIALIZE_ARGS`, ...) + * @return null|string The event name for the loop if listeners exist, otherwise null is returned + */ + protected function getDispatchEventName($eventName) + { + $customEventName = TheliaEvents::getLoopExtendsEvent($eventName, $this->loopName); + + if (!isset(self::$dispatchCache[$customEventName])) { + self::$dispatchCache[$customEventName] = $this->dispatcher->hasListeners($customEventName); + } + + return self::$dispatchCache[$customEventName] + ? $customEventName + : null; + } + + /** + * Dispatch an event to extend the BuildModelCriteria + * + * @param ModelCriteria $search + * @return ModelCriteria + */ + protected function extendsBuildModelCriteria(ModelCriteria $search = null) + { + if (null === $search) { + return null; + } + + $eventName = $this->getDispatchEventName(TheliaEvents::LOOP_EXTENDS_BUILD_MODEL_CRITERIA); + if (null !== $eventName) { + $this->dispatcher->dispatch( + $eventName, + new LoopExtendsBuildModelCriteriaEvent($this, $search) + ); + } + + return $search; + } + + /** + * Dispatch an event to extend the BuildArray + * + * @param array $search + * @return array + */ + protected function extendsBuildArray(array $search = null) + { + if (null === $search) { + return null; + } + + $eventName = $this->getDispatchEventName(TheliaEvents::LOOP_EXTENDS_BUILD_ARRAY); + if (null !== $eventName) { + $event = new LoopExtendsBuildArrayEvent($this, $search); + + $this->dispatcher->dispatch($eventName, $event); + + $search = $event->getArray(); + } + + return $search; + } + + /** + * Dispatch an event to extend the ParseResults + * + * @param LoopResult $loopResult + * @return LoopResult + */ + protected function extendsParseResults(LoopResult $loopResult) + { + $eventName = $this->getDispatchEventName(TheliaEvents::LOOP_EXTENDS_PARSE_RESULTS); + if (null !== $eventName) { + $this->dispatcher->dispatch( + $eventName, + new LoopExtendsParseResultsEvent($this, $loopResult) + ); + } + + return $loopResult; + } + + /** + * Get the argument collection + * + * @return ArgumentCollection + */ + public function getArgumentCollection() + { + return $this->args; + } + + /** + * Get the loop name + * + * @return null|String + */ + public function getLoopName() + { + return $this->loopName; + } + + /** + * @return null|Request + * @since 2.3 + */ + protected function getCurrentRequest() + { + return $this->requestStack->getCurrentRequest(); + } +} diff --git a/core/lib/Thelia/Core/Template/Element/Exception/ElementNotFoundException.php b/core/lib/Thelia/Core/Template/Element/Exception/ElementNotFoundException.php new file mode 100644 index 00000000..a38e1bf9 --- /dev/null +++ b/core/lib/Thelia/Core/Template/Element/Exception/ElementNotFoundException.php @@ -0,0 +1,17 @@ +arguments = $arguments; + } + if ($code === null) { + $code = self::UNKNOWN_EXCEPTION; + } + parent::__construct($message, $code, $previous); + } +} diff --git a/core/lib/Thelia/Core/Template/Element/Exception/SearchLoopException.php b/core/lib/Thelia/Core/Template/Element/Exception/SearchLoopException.php new file mode 100644 index 00000000..127ab46c --- /dev/null +++ b/core/lib/Thelia/Core/Template/Element/Exception/SearchLoopException.php @@ -0,0 +1,29 @@ +arguments = $arguments; + } + if ($code === null) { + $code = self::UNKNOWN_EXCEPTION; + } + parent::__construct($message, $code, $previous); + } +} diff --git a/core/lib/Thelia/Core/Template/Element/FlashMessage.php b/core/lib/Thelia/Core/Template/Element/FlashMessage.php new file mode 100644 index 00000000..63555bab --- /dev/null +++ b/core/lib/Thelia/Core/Template/Element/FlashMessage.php @@ -0,0 +1,113 @@ + + */ +class FlashMessage implements \Iterator +{ + private $position; + protected $collection = array(); + + public function __construct() + { + $this->position = 0; + $this->collection = []; + } + + public function add($type, $messages) + { + foreach ($messages as $message) { + $this->collection[] = [ + "type" => $type, + "message" => $message + ]; + } + } + + public function addAll($all) + { + foreach ($all as $type => $messages) { + $this->add($type, $messages); + } + } + + public function isEmpty() + { + return \count($this->collection) == 0; + } + + public function getCount() + { + return \count($this->collection); + } + + /** + * (PHP 5 >= 5.0.0)
    + * Return the current element + * @link http://php.net/manual/en/iterator.current.php + * @return mixed Can return any type. + */ + public function current() + { + return $this->collection[$this->position]; + } + + /** + * (PHP 5 >= 5.0.0)
    + * Move forward to next element + * @link http://php.net/manual/en/iterator.next.php + * @return void Any returned value is ignored. + */ + public function next() + { + ++$this->position; + } + + /** + * (PHP 5 >= 5.0.0)
    + * Return the key of the current element + * @link http://php.net/manual/en/iterator.key.php + * @return mixed scalar on success, or null on failure. + */ + public function key() + { + return $this->position; + } + + /** + * (PHP 5 >= 5.0.0)
    + * Checks if current position is valid + * @link http://php.net/manual/en/iterator.valid.php + * @return boolean The return value will be casted to boolean and then evaluated. + * Returns true on success or false on failure. + */ + public function valid() + { + return isset($this->collection[$this->position]); + } + + /** + * (PHP 5 >= 5.0.0)
    + * Rewind the Iterator to the first element + * @link http://php.net/manual/en/iterator.rewind.php + * @return void Any returned value is ignored. + */ + public function rewind() + { + $this->position = 0; + } +} diff --git a/core/lib/Thelia/Core/Template/Element/LoopResult.php b/core/lib/Thelia/Core/Template/Element/LoopResult.php new file mode 100644 index 00000000..cfcb22ae --- /dev/null +++ b/core/lib/Thelia/Core/Template/Element/LoopResult.php @@ -0,0 +1,214 @@ +position = 0; + $this->resultsCollection = $resultsCollection; + } + + /** + * @param boolean $countable + */ + public function setCountable($countable = true) + { + $this->countable = true === $countable; + } + + /** + * @param boolean $timestamped + */ + public function setTimestamped($timestamped = true) + { + $this->timestamped = true === $timestamped; + } + + /** + * @param boolean $versioned + */ + public function setVersioned($versioned = true) + { + $this->versioned = true === $versioned; + } + + public function isEmpty() + { + return \count($this->collection) == 0; + } + + public function addRow(LoopResultRow $row) + { + if (true === $this->versioned) { + foreach ($this->getVersionOutputs() as $output) { + $row->set($output[0], $row->model->{$output[1]}()); + } + } + if (true === $this->timestamped) { + foreach ($this->getTimestampOutputs() as $output) { + $row->set($output[0], $row->model->{$output[1]}()); + } + } + if (true === $this->countable) { + $row->set('LOOP_COUNT', 1 + $this->getCount()); + $row->set('LOOP_TOTAL', $this->getResultDataCollectionCount()); + } + + $this->collection[] = $row; + } + + /** + * @param int $key + */ + public function remove($key) + { + if (isset($this->collection[$key])) { + unset($this->collection[$key]); + } + } + + /** + * 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() + { + return \count($this->collection); + } + + public function getResultDataCollectionCount() + { + if ($this->resultsCollection instanceof ObjectCollection || $this->resultsCollection instanceof PropelModelPager) { + return $this->resultsCollection->count(); + } elseif (\is_array($this->resultsCollection)) { + return \count($this->resultsCollection); + } else { + return 0; + } + } + + public function getResultDataCollection() + { + return $this->resultsCollection; + } + + /** + * (PHP 5 >= 5.0.0)
    + * Return the current element + * @link http://php.net/manual/en/iterator.current.php + * @return \Thelia\Core\Template\Element\LoopResultRow + */ + public function current() + { + return $this->collection[$this->position]; + } + + /** + * (PHP 5 >= 5.0.0)
    + * Move forward to next element + * @link http://php.net/manual/en/iterator.next.php + * @return void Any returned value is ignored. + */ + public function next() + { + ++$this->position; + } + + /** + * (PHP 5 >= 5.0.0)
    + * Return the key of the current element + * @link http://php.net/manual/en/iterator.key.php + * @return mixed scalar on success, or null on failure. + */ + public function key() + { + return $this->position; + } + + /** + * (PHP 5 >= 5.0.0)
    + * Checks if current position is valid + * @link http://php.net/manual/en/iterator.valid.php + * @return boolean The return value will be casted to boolean and then evaluated. + * Returns true on success or false on failure. + */ + public function valid() + { + return isset($this->collection[$this->position]); + } + + /** + * (PHP 5 >= 5.0.0)
    + * Rewind the Iterator to the first element + * @link http://php.net/manual/en/iterator.rewind.php + * @return void Any returned value is ignored. + */ + public function rewind() + { + $this->position = 0; + } + + protected function getTimestampOutputs() + { + return array( + array('CREATE_DATE', 'getCreatedAt'), + array('UPDATE_DATE', 'getUpdatedAt'), + ); + } + + protected function getVersionOutputs() + { + return array( + array('VERSION', 'getVersion'), + array('VERSION_DATE', 'getVersionCreatedAt'), + array('VERSION_AUTHOR', 'getVersionCreatedBy'), + ); + } + + /** + * @inheritdoc + */ + public function jsonSerialize() + { + $return = []; + foreach ($this->collection as $collection) { + $return[] = $collection->getVarVal(); + } + + return $return; + } +} diff --git a/core/lib/Thelia/Core/Template/Element/LoopResultRow.php b/core/lib/Thelia/Core/Template/Element/LoopResultRow.php new file mode 100644 index 00000000..5d30e460 --- /dev/null +++ b/core/lib/Thelia/Core/Template/Element/LoopResultRow.php @@ -0,0 +1,51 @@ +model = $model; + } + } + + public function set($key, $value) + { + $this->substitution[$key] = $value === null ? '' : $value; + + return $this; + } + + public function get($key) + { + return $this->substitution[$key]; + } + + public function getVarVal() + { + return $this->substitution; + } + + public function getVars() + { + return array_keys($this->substitution); + } +} diff --git a/core/lib/Thelia/Core/Template/Element/PropelSearchLoopInterface.php b/core/lib/Thelia/Core/Template/Element/PropelSearchLoopInterface.php new file mode 100644 index 00000000..5c794b68 --- /dev/null +++ b/core/lib/Thelia/Core/Template/Element/PropelSearchLoopInterface.php @@ -0,0 +1,28 @@ + + * + */ +interface PropelSearchLoopInterface +{ + /** + * this method returns a Propel ModelCriteria + * + * @return \Propel\Runtime\ActiveQuery\ModelCriteria + */ + public function buildModelCriteria(); +} diff --git a/core/lib/Thelia/Core/Template/Element/SearchLoopInterface.php b/core/lib/Thelia/Core/Template/Element/SearchLoopInterface.php new file mode 100644 index 00000000..73c9f707 --- /dev/null +++ b/core/lib/Thelia/Core/Template/Element/SearchLoopInterface.php @@ -0,0 +1,40 @@ + + * + */ +interface SearchLoopInterface +{ + const MODE_ANY_WORD = 'any_word'; + const MODE_SENTENCE = 'sentence'; + const MODE_STRICT_SENTENCE = 'strict_sentence'; + + /** + * @return array of available field to search in + */ + 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); +} diff --git a/core/lib/Thelia/Core/Template/Element/StandardI18nFieldsSearchTrait.php b/core/lib/Thelia/Core/Template/Element/StandardI18nFieldsSearchTrait.php new file mode 100644 index 00000000..be459df3 --- /dev/null +++ b/core/lib/Thelia/Core/Template/Element/StandardI18nFieldsSearchTrait.php @@ -0,0 +1,56 @@ +_or(); + } + + $this->addSearchInI18nColumn($search, strtoupper($searchInElement), $searchCriteria, $searchTerm); + $firstSearch = false; + } + } +} diff --git a/core/lib/Thelia/Core/Template/Exception/InvalidDescriptorException.php b/core/lib/Thelia/Core/Template/Exception/InvalidDescriptorException.php new file mode 100644 index 00000000..9819df45 --- /dev/null +++ b/core/lib/Thelia/Core/Template/Exception/InvalidDescriptorException.php @@ -0,0 +1,22 @@ + + */ +class InvalidDescriptorException extends \RuntimeException +{ +} diff --git a/core/lib/Thelia/Core/Template/Exception/ResourceNotFoundException.php b/core/lib/Thelia/Core/Template/Exception/ResourceNotFoundException.php new file mode 100644 index 00000000..1a733efb --- /dev/null +++ b/core/lib/Thelia/Core/Template/Exception/ResourceNotFoundException.php @@ -0,0 +1,17 @@ + + */ +class TemplateException extends \RuntimeException +{ +} diff --git a/core/lib/Thelia/Core/Template/Loop/Accessory.php b/core/lib/Thelia/Core/Template/Loop/Accessory.php new file mode 100644 index 00000000..57975515 --- /dev/null +++ b/core/lib/Thelia/Core/Template/Loop/Accessory.php @@ -0,0 +1,124 @@ + + * + * {@inheritdoc} + * @method int[] getProduct() + * @method string[] getOrder() + * + * @link http://doc.thelia.net/en/documentation/loop/accessory.html + */ +class Accessory extends Product +{ + protected $accessoryId; + protected $accessoryPosition; + + /** + * @return ArgumentCollection + */ + protected function getArgDefinitions() + { + $argumentCollection = parent::getArgDefinitions(); + + $argumentCollection->addArgument( + Argument::createIntListTypeArgument('product', null, true) + ); + + $argumentCollection->get('order')->default = "accessory"; + + $argumentCollection->get('order')->type->getKey(0)->addValue('accessory'); + $argumentCollection->get('order')->type->getKey(0)->addValue('accessory_reverse'); + + return $argumentCollection; + } + + public function buildModelCriteria() + { + $search = AccessoryQuery::create(); + + $product = $this->getProduct(); + + $search->filterByProductId($product, Criteria::IN); + + $order = $this->getOrder(); + $orderByAccessory = array_search('accessory', $order); + $orderByAccessoryReverse = array_search('accessory_reverse', $order); + if ($orderByAccessory !== false) { + $search->orderByPosition(Criteria::ASC); + $order[$orderByAccessory] = 'given_id'; + $this->args->get('order')->setValue(implode(',', $order)); + } + if ($orderByAccessoryReverse !== false) { + $search->orderByPosition(Criteria::DESC); + $order[$orderByAccessoryReverse] = 'given_id'; + $this->args->get('order')->setValue(implode(',', $order)); + } + + $accessories = $this->search($search); + + $this->accessoryIdList = array(0); + $this->accessoryPosition = $this->accessoryId = array(); + + foreach ($accessories as $accessory) { + $accessoryProductId = $accessory->getAccessory(); + + array_push($this->accessoryIdList, $accessoryProductId); + + $this->accessoryPosition[$accessoryProductId] = $accessory->getPosition(); + $this->accessoryId[$accessoryProductId] = $accessory->getId(); + } + + $receivedIdList = $this->getId(); + + /* if an Id list is receive, loop will only match accessories from this list */ + if ($receivedIdList === null) { + $this->args->get('id')->setValue(implode(',', $this->accessoryIdList)); + } else { + $this->args->get('id')->setValue(implode(',', array_intersect($receivedIdList, $this->accessoryIdList))); + } + + return parent::buildModelCriteria(); + } + + public function parseResults(LoopResult $results) + { + $results = parent::parseResults($results); + + foreach ($results as $loopResultRow) { + $accessoryProductId = $loopResultRow->get('ID'); + + $loopResultRow + ->set("ID", $this->accessoryId[$accessoryProductId]) + ->set("POSITION", $this->accessoryPosition[$accessoryProductId]) + ->set("ACCESSORY_ID", $accessoryProductId) + ; + } + + return $results; + } +} diff --git a/core/lib/Thelia/Core/Template/Loop/Address.php b/core/lib/Thelia/Core/Template/Loop/Address.php new file mode 100644 index 00000000..a2af0d6e --- /dev/null +++ b/core/lib/Thelia/Core/Template/Loop/Address.php @@ -0,0 +1,149 @@ + + * + * {@inheritdoc} + * @method int[] getId() + * @method bool|string getDefault() + * @method string getCustomer() + * @method int[] getExclude() + */ +class Address extends BaseLoop implements PropelSearchLoopInterface +{ + protected $timestampable = true; + + /** + * @return ArgumentCollection + */ + protected function getArgDefinitions() + { + return new ArgumentCollection( + new Argument( + 'id', + new TypeCollection( + new Type\IntListType(), + new Type\EnumType(array('*', 'any')) + ) + ), + new Argument( + 'customer', + new TypeCollection( + new Type\IntType(), + new Type\EnumType(array('current')) + ), + 'current' + ), + Argument::createBooleanOrBothTypeArgument('default'), + new Argument( + 'exclude', + new TypeCollection( + new Type\IntListType(), + new Type\EnumType(array('none')) + ) + ) + ); + } + + public function buildModelCriteria() + { + $search = AddressQuery::create(); + + $id = $this->getId(); + + if (null !== $id && !\in_array($id, array('*', 'any'))) { + $search->filterById($id, Criteria::IN); + } + + $customer = $this->getCustomer(); + + if ($customer === 'current') { + $currentCustomer = $this->securityContext->getCustomerUser(); + if ($currentCustomer === null) { + return null; + } else { + $search->filterByCustomerId($currentCustomer->getId(), Criteria::EQUAL); + } + } else { + $search->filterByCustomerId($customer, Criteria::EQUAL); + } + + $default = $this->getDefault(); + + if ($default === true) { + $search->filterByIsDefault(1, Criteria::EQUAL); + } elseif ($default === false) { + $search->filterByIsDefault(0, Criteria::EQUAL); + } + + $exclude = $this->getExclude(); + + if (null !== $exclude && 'none' !== $exclude) { + $search->filterById($exclude, Criteria::NOT_IN); + } + + return $search; + } + + public function parseResults(LoopResult $loopResult) + { + /** @var AddressModel $address */ + foreach ($loopResult->getResultDataCollection() as $address) { + $loopResultRow = new LoopResultRow($address); + $loopResultRow + ->set("ID", $address->getId()) + ->set("LABEL", $address->getLabel()) + ->set("CUSTOMER", $address->getCustomerId()) + ->set("TITLE", $address->getTitleId()) + ->set("COMPANY", $address->getCompany()) + ->set("FIRSTNAME", $address->getFirstname()) + ->set("LASTNAME", $address->getLastname()) + ->set("ADDRESS1", $address->getAddress1()) + ->set("ADDRESS2", $address->getAddress2()) + ->set("ADDRESS3", $address->getAddress3()) + ->set("ZIPCODE", $address->getZipcode()) + ->set("CITY", $address->getCity()) + ->set("COUNTRY", $address->getCountryId()) + ->set("STATE", $address->getStateId()) + ->set("PHONE", $address->getPhone()) + ->set("CELLPHONE", $address->getCellphone()) + ->set("DEFAULT", $address->getIsDefault()) + ; + $this->addOutputFields($loopResultRow, $address); + + $loopResult->addRow($loopResultRow); + } + + return $loopResult; + } +} diff --git a/core/lib/Thelia/Core/Template/Loop/Admin.php b/core/lib/Thelia/Core/Template/Loop/Admin.php new file mode 100644 index 00000000..45cf9ec9 --- /dev/null +++ b/core/lib/Thelia/Core/Template/Loop/Admin.php @@ -0,0 +1,94 @@ + + * + * {@inheritdoc} + * @method int[] getId() + * @method int[] getProfile() + */ +class Admin extends BaseLoop implements PropelSearchLoopInterface +{ + protected $timestampable = true; + + /** + * @return ArgumentCollection + */ + protected function getArgDefinitions() + { + return new ArgumentCollection( + Argument::createIntListTypeArgument('id'), + Argument::createIntListTypeArgument('profile') + ); + } + + public function buildModelCriteria() + { + $search = AdminQuery::create(); + + $id = $this->getId(); + + if (null !== $id) { + $search->filterById($id, Criteria::IN); + } + + $profile = $this->getProfile(); + + if (null !== $profile) { + $search->filterByProfileId($profile, Criteria::IN); + } + + $search->orderByFirstname(Criteria::ASC); + + return $search; + } + + public function parseResults(LoopResult $loopResult) + { + /** @var AdminModel $admin */ + foreach ($loopResult->getResultDataCollection() as $admin) { + $loopResultRow = new LoopResultRow($admin); + $loopResultRow->set("ID", $admin->getId()) + ->set("PROFILE", $admin->getProfileId()) + ->set("FIRSTNAME", $admin->getFirstname()) + ->set("LASTNAME", $admin->getLastname()) + ->set("LOGIN", $admin->getLogin()) + ->set("LOCALE", $admin->getLocale()) + ->set("EMAIL", $admin->getEmail()) + ; + $this->addOutputFields($loopResultRow, $admin); + + $loopResult->addRow($loopResultRow); + } + + return $loopResult; + } +} diff --git a/core/lib/Thelia/Core/Template/Loop/Archiver.php b/core/lib/Thelia/Core/Template/Loop/Archiver.php new file mode 100644 index 00000000..ef73eaa9 --- /dev/null +++ b/core/lib/Thelia/Core/Template/Loop/Archiver.php @@ -0,0 +1,96 @@ + + * @author Jérôme Billiras + */ +class Archiver extends BaseLoop implements ArraySearchLoopInterface +{ + protected function getArgDefinitions() + { + return new ArgumentCollection( + Argument::createBooleanTypeArgument('available'), + Argument::createAnyTypeArgument('archiver'), + new Argument( + 'order', + new TypeCollection( + new EnumType(['alpha', 'alpha_reverse']) + ), + 'alpha' + ) + ); + } + + public function buildArray() + { + /** @var \Thelia\Core\Archiver\ArchiverManager $archiverManager */ + $archiverManager = $this->container->get(RegisterArchiverPass::MANAGER_SERVICE_ID); + + $availability = $this->getArgValue('available'); + + $archiverId = $this->getArgValue('archiver'); + if ($archiverId === null) { + $archivers = $archiverManager->getArchivers($availability); + } else { + $archivers = []; + $archiver = $archiverManager->get($archiverId, $availability); + if ($archiver !== null) { + $archivers[] = $archiver; + } + } + + switch ($this->getArgValue('order')) { + case 'alpha': + ksort($archivers); + break; + case 'alpha_reverse': + krsort($archivers); + break; + } + + return $archivers; + } + + public function parseResults(LoopResult $loopResult) + { + /** @var \Thelia\Core\Archiver\ArchiverInterface $archiver */ + foreach ($loopResult->getResultDataCollection() as $archiver) { + $loopResultRow = new LoopResultRow; + + $loopResultRow + ->set('ID', $archiver->getId()) + ->set('NAME', $archiver->getName()) + ->set('EXTENSION', $archiver->getExtension()) + ->set('MIME_TYPE', $archiver->getMimeType()); + + $this->addOutputFields($loopResultRow, $archiver); + + $loopResult->addRow($loopResultRow); + } + + return $loopResult; + } +} diff --git a/core/lib/Thelia/Core/Template/Loop/Area.php b/core/lib/Thelia/Core/Template/Loop/Area.php new file mode 100644 index 00000000..d95db8ac --- /dev/null +++ b/core/lib/Thelia/Core/Template/Loop/Area.php @@ -0,0 +1,163 @@ + + * + * {@inheritdoc} + * @method int[] getId() + * @method int[] getCountry() + * @method int getWithZone() + * @method int getWithoutZone() + * @method bool|string getUnassigned() + * @method int[] getModuleId() + * @method string[] getOrder() + */ +class Area extends BaseI18nLoop implements PropelSearchLoopInterface +{ + protected $timestampable = true; + + /** + * @return ArgumentCollection + */ + protected function getArgDefinitions() + { + return new ArgumentCollection( + Argument::createIntListTypeArgument('id'), + Argument::createIntListTypeArgument('country'), + Argument::createIntTypeArgument('with_zone'), + Argument::createIntTypeArgument('without_zone'), + Argument::createBooleanOrBothTypeArgument('unassigned'), + Argument::createIntListTypeArgument('module_id'), + new Argument( + 'order', + new TypeCollection( + new EnumListType([ + 'id', 'id_reverse', + 'alpha', 'name', 'name_reverse' + ]) + ), + 'name' + ) + ); + } + + public function buildModelCriteria() + { + $search = AreaQuery::create(); + + $id = $this->getId(); + + if (null !== $id) { + $search->filterById($id, Criteria::IN); + } + + $withZone = $this->getWithZone(); + + if ($withZone) { + $search->joinAreaDeliveryModule('with_zone') + ->where('`with_zone`.delivery_module_id '.Criteria::EQUAL.' ?', $withZone, \PDO::PARAM_INT); + } + + $withoutZone = $this->getWithoutZone(); + + if ($withoutZone) { + $search->joinAreaDeliveryModule('without_zone', Criteria::LEFT_JOIN) + ->addJoinCondition('without_zone', 'delivery_module_id '.Criteria::EQUAL.' ?', $withoutZone, null, \PDO::PARAM_INT) + ->where('`without_zone`.delivery_module_id '.Criteria::ISNULL); + } + + $notAssigned = $this->getUnassigned(); + + if ($notAssigned) { + $search + ->joinAreaDeliveryModule('unassigned', Criteria::LEFT_JOIN) + ->where('`unassigned`.delivery_module_id ' . Criteria::ISNULL); + } + + $modules = $this->getModuleId(); + + if (null !== $modules) { + $search + ->useAreaDeliveryModuleQuery() + ->filterByDeliveryModuleId($modules, Criteria::IN) + ->endUse(); + } + + $countries = $this->getCountry(); + + if (null !== $countries) { + $search + ->useCountryAreaQuery() + ->filterByCountryId($countries, Criteria::IN) + ->endUse(); + } + + $orders = $this->getOrder(); + + foreach ($orders as $order) { + switch ($order) { + case 'id': + $search->orderById(Criteria::ASC); + break; + case 'id_reverse': + $search->orderById(Criteria::DESC); + break; + case 'alpha': + case 'name': + $search->orderByName(Criteria::ASC); + break; + case 'name_reverse': + $search->orderByName(Criteria::DESC); + break; + } + } + return $search; + } + + public function parseResults(LoopResult $loopResult) + { + /** @var AreaModel $area */ + foreach ($loopResult->getResultDataCollection() as $area) { + $loopResultRow = new LoopResultRow($area); + + $loopResultRow + ->set('ID', $area->getId()) + ->set('NAME', $area->getName()) + ->set('POSTAGE', $area->getPostage()) + ; + $this->addOutputFields($loopResultRow, $area); + + $loopResult->addRow($loopResultRow); + } + + return $loopResult; + } +} diff --git a/core/lib/Thelia/Core/Template/Loop/Argument/Argument.php b/core/lib/Thelia/Core/Template/Loop/Argument/Argument.php new file mode 100644 index 00000000..1bf004e7 --- /dev/null +++ b/core/lib/Thelia/Core/Template/Loop/Argument/Argument.php @@ -0,0 +1,220 @@ + + * + */ +class Argument +{ + public $name; + public $type; + public $default; + public $mandatory; + public $empty; + + private $value; + + public function __construct($name, \Thelia\Type\TypeCollection $type, $default = null, $mandatory = false, $empty = true, $value = null) + { + $this->name = $name; + $this->type = $type; + $this->mandatory = $mandatory ? true : false; + $this->default = $default; + $this->empty = $empty; + + $this->setValue($value); + } + + public function getValue() + { + return $this->type->getFormattedValue($this->value); + } + + public function getRawValue() + { + return $this->value; + } + + public function setValue($value) + { + if ($value === null) { + $this->value = null; + } else { + if (false === $value) { + /* (string) $value = "" */ + $this->value = 0; + } else { + $this->value = (string) $value; + } + } + } + + public static function createAnyTypeArgument($name, $default = null, $mandatory = false, $empty = true) + { + return new Argument( + $name, + new TypeCollection( + new Type\AnyType() + ), + $default, + $mandatory, + $empty + ); + } + + public static function createIntTypeArgument($name, $default = null, $mandatory = false, $empty = true) + { + return new Argument( + $name, + new TypeCollection( + new Type\IntType() + ), + $default, + $mandatory, + $empty + ); + } + + public static function createFloatTypeArgument($name, $default = null, $mandatory = false, $empty = true) + { + return new Argument( + $name, + new TypeCollection( + new Type\FloatType() + ), + $default, + $mandatory, + $empty + ); + } + + public static function createBooleanTypeArgument($name, $default = null, $mandatory = false, $empty = true) + { + return new Argument( + $name, + new TypeCollection( + new Type\BooleanType() + ), + $default, + $mandatory, + $empty + ); + } + + public static function createBooleanOrBothTypeArgument($name, $default = null, $mandatory = false, $empty = true) + { + return new Argument( + $name, + new TypeCollection( + new Type\BooleanOrBothType() + ), + $default, + $mandatory, + $empty + ); + } + + public static function createIntListTypeArgument($name, $default = null, $mandatory = false, $empty = true) + { + return new Argument( + $name, + new TypeCollection( + new Type\IntListType() + ), + $default, + $mandatory, + $empty + ); + } + + /** + * @param $name + * @param null $default + * @param bool $mandatory + * @param bool $empty + * @return Argument + * @since 2.2 + */ + public static function createAnyListTypeArgument($name, $default = null, $mandatory = false, $empty = true) + { + return new Argument( + $name, + new TypeCollection( + new Type\AnyListType() + ), + $default, + $mandatory, + $empty + ); + } + + public static function createEnumListTypeArgument($name, array $entries, $default = null, $mandatory = false, $empty = true) + { + return new Argument( + $name, + new TypeCollection( + new Type\EnumListType($entries) + ), + $default, + $mandatory, + $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 + ); + } +} diff --git a/core/lib/Thelia/Core/Template/Loop/Argument/ArgumentCollection.php b/core/lib/Thelia/Core/Template/Loop/Argument/ArgumentCollection.php new file mode 100644 index 00000000..7884ffcc --- /dev/null +++ b/core/lib/Thelia/Core/Template/Loop/Argument/ArgumentCollection.php @@ -0,0 +1,194 @@ + + * + */ + +class ArgumentCollection implements \Iterator +{ + private $arguments = array(); + + public function __construct() + { + $this->addArguments(\func_get_args(), true); + } + + /** + * @param $key + * @return bool + */ + public function hasKey($key) + { + return isset($this->arguments[$key]); + } + + /** + * @param $key + * @return Argument|null + */ + public function get($key) + { + return $this->hasKey($key) ? $this->arguments[$key] : null; + } + + /** + * @return bool + */ + public function isEmpty() + { + return \count($this->arguments) == 0; + } + + /** + * @param array $argumentList + * @param $force + * + * @return ArgumentCollection + */ + public function addArguments(array $argumentList, $force = true) + { + foreach ($argumentList as $argument) { + $this->addArgument($argument, $force); + } + + return $this; + } + + /** + * @param Argument $argument + * @param $force + * + * @return ArgumentCollection + */ + public function addArgument(Argument $argument, $force = true) + { + if (isset($this->arguments[$argument->name]) && ! $force) { + return $this; + } + + $this->arguments[$argument->name] = $argument; + + return $this; + } + + /** + * @param array $argumentNames Array with names of arguments to remove. + * + * @return ArgumentCollection + * @since 2.2.0-beta1 + */ + public function removeArguments(array $argumentNames) + { + foreach ($argumentNames as $argumentName) { + $this->removeArgument($argumentName); + } + + return $this; + } + + /** + * @param string $argumentName Name of the argument to remove. + * + * @return ArgumentCollection + * @since 2.2.0-beta1 + */ + public function removeArgument($argumentName) + { + if (isset($this->arguments[$argumentName])) { + unset($this->arguments[$argumentName]); + } + + return $this; + } + + public function getCount() + { + return \count($this->arguments); + } + + /** + * (PHP 5 >= 5.0.0)
    + * Return the current element + * @link http://php.net/manual/en/iterator.current.php + * @return Argument + */ + public function current() + { + return current($this->arguments); + } + + /** + * (PHP 5 >= 5.0.0)
    + * Move forward to next element + * @link http://php.net/manual/en/iterator.next.php + * @return void Any returned value is ignored. + */ + public function next() + { + next($this->arguments); + } + + /** + * (PHP 5 >= 5.0.0)
    + * Return the key of the current element + * @link http://php.net/manual/en/iterator.key.php + * @return mixed scalar on success, or null on failure. + */ + public function key() + { + return key($this->arguments); + } + + /** + * (PHP 5 >= 5.0.0)
    + * Checks if current position is valid + * @link http://php.net/manual/en/iterator.valid.php + * @return boolean The return value will be casted to boolean and then evaluated. + * Returns true on success or false on failure. + */ + public function valid() + { + return $this->key() !== null; + } + + /** + * (PHP 5 >= 5.0.0)
    + * Rewind the Iterator to the first element + * @link http://php.net/manual/en/iterator.rewind.php + * @return void Any returned value is ignored. + */ + public function rewind() + { + reset($this->arguments); + } + + public function getHash() + { + $arguments = $this->arguments; + + if (array_key_exists('name', $arguments)) { + unset($arguments['name']); + } + + $string = ''; + foreach ($arguments as $key => $argument) { + $string .= $key.'='.$argument->getRawValue(); + } + + return md5($string); + } +} diff --git a/core/lib/Thelia/Core/Template/Loop/AssociatedContent.php b/core/lib/Thelia/Core/Template/Loop/AssociatedContent.php new file mode 100644 index 00000000..21a4cfaf --- /dev/null +++ b/core/lib/Thelia/Core/Template/Loop/AssociatedContent.php @@ -0,0 +1,165 @@ + + * + * {@inheritdoc} + * @method int getProduct() + * @method int getCategory() + * @method int[] getExcludeProduct() + * @method int[] getExcludeCategory() + */ +class AssociatedContent extends Content +{ + protected $contentId; + protected $contentPosition; + + /** + * @return ArgumentCollection + */ + protected function getArgDefinitions() + { + $argumentCollection = parent::getArgDefinitions(); + + $argumentCollection + ->addArgument(Argument::createIntTypeArgument('product')) + ->addArgument(Argument::createIntTypeArgument('category')) + ->addArgument(Argument::createIntListTypeArgument('exclude_product')) + ->addArgument(Argument::createIntListTypeArgument('exclude_category')) + ; + + $argumentCollection->get('order')->default = "associated_content"; + + $argumentCollection->get('order')->type->getKey(0)->addValue('associated_content'); + $argumentCollection->get('order')->type->getKey(0)->addValue('associated_content_reverse'); + + return $argumentCollection; + } + + public function buildModelCriteria() + { + $product = $this->getProduct(); + $category = $this->getCategory(); + + if ($product === null && $category === null) { + throw new \InvalidArgumentException('You have to provide either `product` or `category` argument in associated_content loop'); + } + + if ($product !== null) { + /** @var ProductAssociatedContentQuery $search */ + $search = ProductAssociatedContentQuery::create(); + + $search->filterByProductId($product, Criteria::EQUAL); + } elseif ($category !== null) { + /** @var CategoryAssociatedContentQuery $search */ + $search = CategoryAssociatedContentQuery::create(); + + $search->filterByCategoryId($category, Criteria::EQUAL); + } + + $excludeProduct = $this->getExcludeProduct(); + + // If we have to filter by product, find all products assigned to this product, and filter by found IDs + if (null !== $excludeProduct) { + // Exclude all contents related to the given product + $search->filterById( + ProductAssociatedContentQuery::create()->filterByProductId($excludeProduct)->select('product_id')->find(), + Criteria::NOT_IN + ); + } + + $excludeCategory = $this->getExcludeCategory(); + + // If we have to filter by category, find all contents assigned to this category, and filter by found IDs + if (null !== $excludeCategory) { + // Exclure tous les attribut qui sont attachés aux templates indiqués + $search->filterById( + CategoryAssociatedContentQuery::create()->filterByProductId($excludeCategory)->select('category_id')->find(), + Criteria::NOT_IN + ); + } + + $order = $this->getOrder(); + $orderByAssociatedContent = array_search('associated_content', $order); + $orderByAssociatedContentReverse = array_search('associated_content_reverse', $order); + + if ($orderByAssociatedContent !== false) { + $search->orderByPosition(Criteria::ASC); + $order[$orderByAssociatedContent] = 'given_id'; + $this->args->get('order')->setValue(implode(',', $order)); + } + if ($orderByAssociatedContentReverse !== false) { + $search->orderByPosition(Criteria::DESC); + $order[$orderByAssociatedContentReverse] = 'given_id'; + $this->args->get('order')->setValue(implode(',', $order)); + } + + $associatedContents = $this->search($search); + + $associatedContentIdList = array(0); + + $this->contentPosition = $this->contentId = array(); + + foreach ($associatedContents as $associatedContent) { + $associatedContentId = $associatedContent->getContentId(); + + array_push($associatedContentIdList, $associatedContentId); + $this->contentPosition[$associatedContentId] = $associatedContent->getPosition(); + $this->contentId[$associatedContentId] = $associatedContent->getId(); + } + + $receivedIdList = $this->getId(); + + /* if an Id list is receive, loop will only match accessories from this list */ + if ($receivedIdList === null) { + $this->args->get('id')->setValue(implode(',', $associatedContentIdList)); + } else { + $this->args->get('id')->setValue(implode(',', array_intersect($receivedIdList, $associatedContentIdList))); + } + + return parent::buildModelCriteria(); + } + + public function parseResults(LoopResult $results) + { + $results = parent::parseResults($results); + + foreach ($results as $loopResultRow) { + $relatedContentId = $loopResultRow->get('ID'); + + $loopResultRow + ->set("ID", $this->contentId[$relatedContentId]) + ->set("CONTENT_ID", $relatedContentId) + ->set("POSITION", $this->contentPosition[$relatedContentId]) + + ; + } + + return $results; + } +} diff --git a/core/lib/Thelia/Core/Template/Loop/Attribute.php b/core/lib/Thelia/Core/Template/Loop/Attribute.php new file mode 100644 index 00000000..0bb8bda8 --- /dev/null +++ b/core/lib/Thelia/Core/Template/Loop/Attribute.php @@ -0,0 +1,203 @@ + + * + * {@inheritdoc} + * @method int[] getId() + * @method int[] getProduct() + * @method int[] getTemplate() + * @method int[] getExcludeTemplate() + * @method int[] getExclude() + * @method string[] getOrder() + */ +class Attribute extends BaseI18nLoop implements PropelSearchLoopInterface +{ + protected $useAttributePosistion; + + protected $timestampable = true; + + /** + * @return ArgumentCollection + */ + protected function getArgDefinitions() + { + return new ArgumentCollection( + Argument::createIntListTypeArgument('id'), + Argument::createIntListTypeArgument('product'), + Argument::createIntListTypeArgument('template'), + Argument::createIntListTypeArgument('exclude_template'), + Argument::createIntListTypeArgument('exclude'), + new Argument( + 'order', + new TypeCollection( + new Type\EnumListType(array('id', 'id_reverse', 'alpha', 'alpha_reverse', 'manual', 'manual_reverse')) + ), + 'manual' + ) + ); + } + + public function buildModelCriteria() + { + $search = AttributeQuery::create(); + + /* manage translations */ + $this->configureI18nProcessing($search); + + $id = $this->getId(); + + if (null !== $id) { + $search->filterById($id, Criteria::IN); + } + + $exclude = $this->getExclude(); + + if (null !== $exclude) { + $search->filterById($exclude, Criteria::NOT_IN); + } + + $product = $this->getProduct(); + $template = $this->getTemplate(); + $excludeTemplate = $this->getExcludeTemplate(); + + $this->useAttributePosistion = true; + + if (null !== $product) { + // Find all template assigned to the products. + $products = ProductQuery::create()->findById($product); + + // Ignore if the product cannot be found. + if ($products !== null) { + // Create template array + if ($template == null) { + $template = array(); + } + + /** @var ProductModel $product */ + foreach ($products as $product) { + $tplId = $product->getTemplateId(); + + if (! \is_null($tplId)) { + $template[] = $tplId; + } + } + } + + // franck@cqfdev.fr - 05/12/2013 : if the given product has no template + // or if the product cannot be found, do not return anything. + if (empty($template)) { + return null; + } + } + + if (! empty($template)) { + // Join with feature_template table to get position + $search + ->withColumn(AttributeTemplateTableMap::COL_POSITION, 'position') + ->filterByTemplate(TemplateQuery::create()->findById($template), Criteria::IN) + ; + + $this->useAttributePosistion = false; + } elseif (null !== $excludeTemplate) { + // Join with attribute_template table to get position + $excludeAttributes = AttributeTemplateQuery::create()->filterByTemplateId($excludeTemplate)->select('attribute_id')->find(); + + $search + ->filterById($excludeAttributes, Criteria::NOT_IN) + ; + } + + $orders = $this->getOrder(); + + foreach ($orders as $order) { + switch ($order) { + case "id": + $search->orderById(Criteria::ASC); + break; + case "id_reverse": + $search->orderById(Criteria::DESC); + break; + case "alpha": + $search->addAscendingOrderByColumn('i18n_TITLE'); + break; + case "alpha_reverse": + $search->addDescendingOrderByColumn('i18n_TITLE'); + break; + case "manual": + if ($this->useAttributePosistion) { + $search->orderByPosition(Criteria::ASC); + } else { + $search->addAscendingOrderByColumn(AttributeTemplateTableMap::COL_POSITION); + } + break; + case "manual_reverse": + if ($this->useAttributePosistion) { + $search->orderByPosition(Criteria::DESC); + } else { + $search->addDescendingOrderByColumn(AttributeTemplateTableMap::COL_POSITION); + } + break; + } + } + + return $search; + } + + public function parseResults(LoopResult $loopResult) + { + /** @var AttributeModel $attribute */ + foreach ($loopResult->getResultDataCollection() as $attribute) { + $loopResultRow = new LoopResultRow($attribute); + $loopResultRow->set("ID", $attribute->getId()) + ->set("IS_TRANSLATED", $attribute->getVirtualColumn('IS_TRANSLATED')) + ->set("LOCALE", $this->locale) + ->set("TITLE", $attribute->getVirtualColumn('i18n_TITLE')) + ->set("CHAPO", $attribute->getVirtualColumn('i18n_CHAPO')) + ->set("DESCRIPTION", $attribute->getVirtualColumn('i18n_DESCRIPTION')) + ->set("POSTSCRIPTUM", $attribute->getVirtualColumn('i18n_POSTSCRIPTUM')) + ->set("POSITION", $this->useAttributePosistion ? $attribute->getPosition() : $attribute->getVirtualColumn('position')) + ; + $this->addOutputFields($loopResultRow, $attribute); + + $loopResult->addRow($loopResultRow); + } + + return $loopResult; + } +} diff --git a/core/lib/Thelia/Core/Template/Loop/AttributeAvailability.php b/core/lib/Thelia/Core/Template/Loop/AttributeAvailability.php new file mode 100644 index 00000000..8f44e512 --- /dev/null +++ b/core/lib/Thelia/Core/Template/Loop/AttributeAvailability.php @@ -0,0 +1,174 @@ + + * + * {@inheritdoc} + * @method int[] getId() + * @method int[] getAttribute() + * @method int getProduct() + * @method int[] getExclude() + * @method string[] getOrder() + */ +class AttributeAvailability extends BaseI18nLoop implements PropelSearchLoopInterface +{ + protected $timestampable = true; + + /** + * @return ArgumentCollection + */ + protected function getArgDefinitions() + { + return new ArgumentCollection( + Argument::createIntListTypeArgument('id'), + Argument::createIntListTypeArgument('attribute'), + Argument::createIntTypeArgument('product'), + Argument::createIntListTypeArgument('exclude'), + new Argument( + 'order', + new TypeCollection( + new Type\EnumListType(array('id', 'id_reverse', 'alpha', 'alpha_reverse', 'manual', 'manual_reverse')) + ), + 'manual' + ) + ); + } + + public function buildModelCriteria() + { + $search = AttributeAvQuery::create(); + + /* manage translations */ + $this->configureI18nProcessing($search); + + $id = $this->getId(); + + if (null !== $id) { + $search->filterById($id, Criteria::IN); + } + + $exclude = $this->getExclude(); + + if (null !== $exclude) { + $search->filterById($exclude, Criteria::NOT_IN); + } + + $attribute = $this->getAttribute(); + + if (null !== $attribute) { + $search->filterByAttributeId($attribute, Criteria::IN); + } + + $product = $this->getProduct(); + + if (null !== $product) { + // Return only Attributes Av that are part on a product's combination + + /* The request is: + select * from attribute_av aav + left join attribute_combination ac on ac.attribute_av_id = aav.id + left join product_sale_elements pse on pse.id = ac.product_sale_elements_id + where aav.attribute_id=3 and pse.product_id = 279 + group by aav.id + */ + + $pseJoin = new Join(); + $pseJoin->addCondition( + AttributeCombinationTableMap::COL_PRODUCT_SALE_ELEMENTS_ID, + ProductSaleElementsTableMap::COL_ID, + Criteria::EQUAL + ); + $pseJoin->setJoinType(Criteria::LEFT_JOIN); + + $search + ->leftJoinAttributeCombination('attribute_combination') + ->groupById() + ->addJoinObject($pseJoin) + ->where(ProductSaleElementsTableMap::COL_PRODUCT_ID."=?", $product, \PDO::PARAM_INT) + ; + } + + $orders = $this->getOrder(); + + foreach ($orders as $order) { + switch ($order) { + case 'id': + $search->orderById(Criteria::ASC); + break; + case 'id_reverse': + $search->orderById(Criteria::DESC); + break; + case "alpha": + $search->addAscendingOrderByColumn('i18n_TITLE'); + break; + case "alpha_reverse": + $search->addDescendingOrderByColumn('i18n_TITLE'); + break; + case "manual": + $search->orderByPosition(Criteria::ASC); + break; + case "manual_reverse": + $search->orderByPosition(Criteria::DESC); + break; + } + } + + return $search; + } + + public function parseResults(LoopResult $loopResult) + { + /** @var AttributeAvModel $attributeAv */ + foreach ($loopResult->getResultDataCollection() as $attributeAv) { + $loopResultRow = new LoopResultRow($attributeAv); + $loopResultRow + ->set("ID", $attributeAv->getId()) + ->set("ATTRIBUTE_ID", $attributeAv->getAttributeId()) + ->set("IS_TRANSLATED", $attributeAv->getVirtualColumn('IS_TRANSLATED')) + ->set("LOCALE", $this->locale) + ->set("TITLE", $attributeAv->getVirtualColumn('i18n_TITLE')) + ->set("CHAPO", $attributeAv->getVirtualColumn('i18n_CHAPO')) + ->set("DESCRIPTION", $attributeAv->getVirtualColumn('i18n_DESCRIPTION')) + ->set("POSTSCRIPTUM", $attributeAv->getVirtualColumn('i18n_POSTSCRIPTUM')) + ->set("POSITION", $attributeAv->getPosition()) + ; + $this->addOutputFields($loopResultRow, $attributeAv); + + $loopResult->addRow($loopResultRow); + } + + return $loopResult; + } +} diff --git a/core/lib/Thelia/Core/Template/Loop/AttributeCombination.php b/core/lib/Thelia/Core/Template/Loop/AttributeCombination.php new file mode 100644 index 00000000..f09c4fb4 --- /dev/null +++ b/core/lib/Thelia/Core/Template/Loop/AttributeCombination.php @@ -0,0 +1,158 @@ + + * + * {@inheritdoc} + * @method int getProductSaleElements() + * @method string[] getOrder() + */ +class AttributeCombination extends BaseI18nLoop implements PropelSearchLoopInterface +{ + protected $timestampable = true; + + /** + * @return ArgumentCollection + */ + protected function getArgDefinitions() + { + return new ArgumentCollection( + Argument::createIntTypeArgument('product_sale_elements', null, true), + Argument::createEnumListTypeArgument( + 'order', + [ + 'alpha', 'alpha_reverse', 'manual', 'manual_reverse' + ], + 'alpha' + ) + ); + } + + public function buildModelCriteria() + { + $search = AttributeCombinationQuery::create(); + + /* manage attribute translations */ + $this->configureI18nProcessing( + $search, + array('TITLE', 'CHAPO', 'DESCRIPTION', 'POSTSCRIPTUM'), + AttributeTableMap::TABLE_NAME, + 'ATTRIBUTE_ID' + ); + + /* manage attributeAv translations */ + $this->configureI18nProcessing( + $search, + array('TITLE', 'CHAPO', 'DESCRIPTION', 'POSTSCRIPTUM'), + AttributeAvTableMap::TABLE_NAME, + 'ATTRIBUTE_AV_ID' + ); + + $productSaleElements = $this->getProductSaleElements(); + + $search->filterByProductSaleElementsId($productSaleElements, Criteria::EQUAL); + + $orders = $this->getOrder(); + + foreach ($orders as $order) { + switch ($order) { + case "alpha": + $search->addAscendingOrderByColumn(AttributeTableMap::TABLE_NAME . '_i18n_TITLE'); + break; + case "alpha_reverse": + $search->addDescendingOrderByColumn(AttributeTableMap::TABLE_NAME . '_i18n_TITLE'); + break; + case "manual": + $this->orderByTemplateAttributePosition($search, Criteria::ASC); + break; + case "manual_reverse": + $this->orderByTemplateAttributePosition($search, Criteria::DESC); + break; + } + } + + return $search; + } + + public function parseResults(LoopResult $loopResult) + { + /** @var \Thelia\Model\AttributeCombination $attributeCombination */ + foreach ($loopResult->getResultDataCollection() as $attributeCombination) { + $loopResultRow = new LoopResultRow($attributeCombination); + + $loopResultRow + ->set("LOCALE", $this->locale) + + ->set("ATTRIBUTE_ID", $attributeCombination->getAttributeId()) + ->set("ATTRIBUTE_TITLE", $attributeCombination->getVirtualColumn(AttributeTableMap::TABLE_NAME . '_i18n_TITLE')) + ->set("ATTRIBUTE_CHAPO", $attributeCombination->getVirtualColumn(AttributeTableMap::TABLE_NAME . '_i18n_CHAPO')) + ->set("ATTRIBUTE_DESCRIPTION", $attributeCombination->getVirtualColumn(AttributeTableMap::TABLE_NAME . '_i18n_DESCRIPTION')) + ->set("ATTRIBUTE_POSTSCRIPTUM", $attributeCombination->getVirtualColumn(AttributeTableMap::TABLE_NAME . '_i18n_POSTSCRIPTUM')) + + ->set("ATTRIBUTE_AVAILABILITY_ID", $attributeCombination->getAttributeAvId()) + ->set("ATTRIBUTE_AVAILABILITY_TITLE", $attributeCombination->getVirtualColumn(AttributeAvTableMap::TABLE_NAME . '_i18n_TITLE')) + ->set("ATTRIBUTE_AVAILABILITY_CHAPO", $attributeCombination->getVirtualColumn(AttributeAvTableMap::TABLE_NAME . '_i18n_CHAPO')) + ->set("ATTRIBUTE_AVAILABILITY_DESCRIPTION", $attributeCombination->getVirtualColumn(AttributeAvTableMap::TABLE_NAME . '_i18n_DESCRIPTION')) + ->set("ATTRIBUTE_AVAILABILITY_POSTSCRIPTUM", $attributeCombination->getVirtualColumn(AttributeAvTableMap::TABLE_NAME . '_i18n_POSTSCRIPTUM')); + $this->addOutputFields($loopResultRow, $attributeCombination); + $loopResult->addRow($loopResultRow); + } + + return $loopResult; + } + + /** + * @param AttributeCombinationQuery $search + * @param string $order Criteria::ASC|Criteria::DESC + * @return AttributeCombinationQuery + */ + protected function orderByTemplateAttributePosition(AttributeCombinationQuery $search, $order) + { + $search + ->useProductSaleElementsQuery() + ->joinProduct() + ->endUse() + ->useAttributeQuery() + ->joinAttributeTemplate(AttributeTemplateTableMap::TABLE_NAME) + ->addJoinCondition( + AttributeTemplateTableMap::TABLE_NAME, + AttributeTemplateTableMap::COL_TEMPLATE_ID . Criteria::EQUAL . ProductTableMap::COL_TEMPLATE_ID + ) + ->endUse() + ->orderBy(AttributeTemplateTableMap::COL_POSITION, $order); + + return $search; + } +} diff --git a/core/lib/Thelia/Core/Template/Loop/Auth.php b/core/lib/Thelia/Core/Template/Loop/Auth.php new file mode 100644 index 00000000..cec65a2c --- /dev/null +++ b/core/lib/Thelia/Core/Template/Loop/Auth.php @@ -0,0 +1,101 @@ + + * + * {@inheritdoc} + * @method string[] getRole() + * @method string[] getResource() + * @method int[] getModule() + * @method string[] getAccess() + */ +class Auth extends BaseLoop implements ArraySearchLoopInterface +{ + public function getArgDefinitions() + { + return new ArgumentCollection( + new Argument( + 'role', + new TypeCollection( + new AlphaNumStringListType() + ), + null, + true + ), + new Argument( + 'resource', + new TypeCollection( + new AlphaNumStringListType() + ) + ), + new Argument( + 'module', + new TypeCollection( + new AlphaNumStringListType() + ) + ), + new Argument( + 'access', + new TypeCollection( + new EnumListType(array(AccessManager::VIEW, AccessManager::CREATE, AccessManager::UPDATE, AccessManager::DELETE)) + ) + ) + ); + } + + public function buildArray() + { + return array(); + } + + public function parseResults(LoopResult $loopResult) + { + $roles = $this->getRole(); + $resource = $this->getResource(); + $module = $this->getModule(); + $access = $this->getAccess(); + + try { + if (true === $this->securityContext->isGranted( + $roles, + $resource === null ? array() : $resource, + $module === null ? array() : $module, + $access === null ? array() : $access + ) + ) { + // Create an empty row: loop is no longer empty :) + $loopResult->addRow(new LoopResultRow()); + } + } catch (\Exception $ex) { + // Not granted, loop is empty + } + + return $loopResult; + } +} diff --git a/core/lib/Thelia/Core/Template/Loop/BaseSpecificModule.php b/core/lib/Thelia/Core/Template/Loop/BaseSpecificModule.php new file mode 100644 index 00000000..d802af12 --- /dev/null +++ b/core/lib/Thelia/Core/Template/Loop/BaseSpecificModule.php @@ -0,0 +1,122 @@ + + * + * {@inheritdoc} + * @method int getId() + * @method int[] getExclude() + * @method string[] getExcludeCode() + * @method string getCode() + * @method string[] getOrder() + */ +abstract class BaseSpecificModule extends BaseI18nLoop implements PropelSearchLoopInterface +{ + protected $timestampable = true; + + /** + * @return \Thelia\Core\Template\Loop\Argument\ArgumentCollection + */ + protected function getArgDefinitions() + { + return new ArgumentCollection( + Argument::createIntTypeArgument('id'), + Argument::createIntListTypeArgument('exclude'), + Argument::createAnyListTypeArgument('exclude_code'), + Argument::createAnyTypeArgument('code'), + new Argument( + 'order', + new TypeCollection( + new EnumType( + [ + 'id', + 'id_reverse', + 'alpha', + 'alpha_reverse', + 'manual', + 'manual_reverse', + ] + ) + ), + 'manual' + ) + ); + } + + public function buildModelCriteria() + { + $search = ModuleQuery::create(); + + $search->filterByActivate(1); + + if (null !== $id = $this->getId()) { + $search->filterById($id); + } + + if (null !== $exclude = $this->getExclude()) { + $search->filterById($exclude, Criteria::NOT_IN); + } + + if (null !== $excludeCode = $this->getExcludeCode()) { + $search->filterByCode($excludeCode, Criteria::NOT_IN); + } + + if (null !== $code = $this->getCode()) { + $search->filterByCode($code); + } + + $this->configureI18nProcessing($search); + + $search->filterByType($this->getModuleType(), Criteria::EQUAL); + + $order = $this->getOrder(); + + switch ($order) { + case "id": + $search->orderById(Criteria::ASC); + break; + case "id_reverse": + $search->orderById(Criteria::DESC); + break; + case "alpha": + $search->addAscendingOrderByColumn('i18n_TITLE'); + break; + case "alpha_reverse": + $search->addDescendingOrderByColumn('i18n_TITLE'); + break; + case "manual_reverse": + $search->orderByPosition(Criteria::DESC); + break; + case "manual": + default: + $search->orderByPosition(Criteria::ASC); + break; + } + + return $search; + } + + abstract protected function getModuleType(); +} diff --git a/core/lib/Thelia/Core/Template/Loop/Brand.php b/core/lib/Thelia/Core/Template/Loop/Brand.php new file mode 100644 index 00000000..c1bf60ee --- /dev/null +++ b/core/lib/Thelia/Core/Template/Loop/Brand.php @@ -0,0 +1,281 @@ + + * + * {@inheritdoc} + * @method int[] getId() + * @method int getProduct() + * @method bool|string getVisible() + * @method string getTitle() + * @method bool getCurrent() + * @method int[] getExclude() + * @method string[] getOrder() + * @method bool getWithPrevNextInfo() + */ +class Brand extends BaseI18nLoop implements PropelSearchLoopInterface, SearchLoopInterface +{ + use StandardI18nFieldsSearchTrait; + + protected $timestampable = true; + + /** + * @return ArgumentCollection + */ + protected function getArgDefinitions() + { + return new ArgumentCollection( + Argument::createIntListTypeArgument('id'), + Argument::createIntTypeArgument('product'), + Argument::createBooleanOrBothTypeArgument('visible', 1), + Argument::createAnyTypeArgument('title'), + Argument::createBooleanTypeArgument('current'), + Argument::createBooleanTypeArgument('with_prev_next_info', false), + new Argument( + 'order', + new TypeCollection( + new Type\EnumListType( + array( + 'id', + 'id-reverse', + 'alpha', + 'alpha-reverse', + 'manual', + 'manual-reverse', + 'random', + 'created', + 'created-reverse', + 'updated', + 'updated-reverse', + 'visible', + 'visible-reverse' + ) + ) + ), + 'alpha' + ), + Argument::createIntListTypeArgument('exclude') + ); + } + + /** + * @return array of available field to search in + */ + public function getSearchIn() + { + return $this->getStandardI18nSearchFields(); + } + + /** + * @param BrandQuery $search + * @param string $searchTerm + * @param array $searchIn + * @param string $searchCriteria + */ + public function doSearch(&$search, $searchTerm, $searchIn, $searchCriteria) + { + $search->_and(); + + $this->addStandardI18nSearch($search, $searchTerm, $searchCriteria, $searchIn); + } + + public function buildModelCriteria() + { + $search = BrandQuery::create(); + + /* manage translations */ + $this->configureI18nProcessing( + $search, + array( + 'TITLE', + 'CHAPO', + 'DESCRIPTION', + 'POSTSCRIPTUM', + 'META_TITLE', + 'META_DESCRIPTION', + 'META_KEYWORDS' + ) + ); + + $id = $this->getId(); + + if (!\is_null($id)) { + $search->filterById($id, Criteria::IN); + } + + $product = $this->getProduct(); + + if (!\is_null($product) && null !== $productObj = ProductQuery::create()->findPk($product)) { + $search->filterByProduct($productObj); + } + + $visible = $this->getVisible(); + + if ($visible !== BooleanOrBothType::ANY) { + $search->filterByVisible($visible ? 1 : 0); + } + + $title = $this->getTitle(); + + if (!\is_null($title)) { + $this->addSearchInI18nColumn($search, 'TITLE', Criteria::LIKE, "%".$title."%"); + } + + $current = $this->getCurrent(); + + if ($current === true) { + $search->filterById($this->getCurrentRequest()->get("brand_id")); + } elseif ($current === false) { + $search->filterById($this->getCurrentRequest()->get("brand_id"), Criteria::NOT_IN); + } + + $orders = $this->getOrder(); + + foreach ($orders as $order) { + switch ($order) { + case 'id': + $search->orderById(Criteria::ASC); + break; + case 'id-reverse': + $search->orderById(Criteria::DESC); + break; + case "alpha": + $search->addAscendingOrderByColumn('i18n_TITLE'); + break; + case "alpha-reverse": + $search->addDescendingOrderByColumn('i18n_TITLE'); + break; + case "manual": + $search->orderByPosition(Criteria::ASC); + break; + case "manual-reverse": + $search->orderByPosition(Criteria::DESC); + break; + case "random": + $search->clearOrderByColumns(); + $search->addAscendingOrderByColumn('RAND()'); + break(2); + 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 "visible": + $search->orderByVisible(Criteria::ASC); + break; + case "visible-reverse": + $search->orderByVisible(Criteria::DESC); + break; + } + } + + $exclude = $this->getExclude(); + + if (!\is_null($exclude)) { + $search->filterById($exclude, Criteria::NOT_IN); + } + + return $search; + } + + public function parseResults(LoopResult $loopResult) + { + /** @var \Thelia\Model\Brand $brand */ + foreach ($loopResult->getResultDataCollection() as $brand) { + $loopResultRow = new LoopResultRow($brand); + + $loopResultRow->set("ID", $brand->getId()) + ->set("IS_TRANSLATED", $brand->getVirtualColumn('IS_TRANSLATED')) + ->set("LOCALE", $this->locale) + ->set("TITLE", $brand->getVirtualColumn('i18n_TITLE')) + ->set("CHAPO", $brand->getVirtualColumn('i18n_CHAPO')) + ->set("DESCRIPTION", $brand->getVirtualColumn('i18n_DESCRIPTION')) + ->set("POSTSCRIPTUM", $brand->getVirtualColumn('i18n_POSTSCRIPTUM')) + ->set("URL", $this->getReturnUrl() ? $brand->getUrl($this->locale) : null) + ->set("META_TITLE", $brand->getVirtualColumn('i18n_META_TITLE')) + ->set("META_DESCRIPTION", $brand->getVirtualColumn('i18n_META_DESCRIPTION')) + ->set("META_KEYWORDS", $brand->getVirtualColumn('i18n_META_KEYWORDS')) + ->set("POSITION", $brand->getPosition()) + ->set("VISIBLE", $brand->getVisible()) + ->set("LOGO_IMAGE_ID", $brand->getLogoImageId() ?: 0); + + $isBackendContext = $this->getBackendContext(); + + if ($this->getWithPrevNextInfo()) { + // Find previous and next category + $previousQuery = BrandQuery::create() + ->filterByPosition($brand->getPosition(), Criteria::LESS_THAN); + + if (! $isBackendContext) { + $previousQuery->filterByVisible(true); + } + + $previous = $previousQuery + ->orderByPosition(Criteria::DESC) + ->findOne(); + + $nextQuery = BrandQuery::create() + ->filterByPosition($brand->getPosition(), Criteria::GREATER_THAN); + + if (! $isBackendContext) { + $nextQuery->filterByVisible(true); + } + + $next = $nextQuery + ->orderByPosition(Criteria::ASC) + ->findOne(); + + $loopResultRow + ->set("HAS_PREVIOUS", $previous != null ? 1 : 0) + ->set("HAS_NEXT", $next != null ? 1 : 0) + ->set("PREVIOUS", $previous != null ? $previous->getId() : -1) + ->set("NEXT", $next != null ? $next->getId() : -1); + } + + $this->addOutputFields($loopResultRow, $brand); + + $loopResult->addRow($loopResultRow); + } + + return $loopResult; + } +} diff --git a/core/lib/Thelia/Core/Template/Loop/Cart.php b/core/lib/Thelia/Core/Template/Loop/Cart.php new file mode 100644 index 00000000..207c2409 --- /dev/null +++ b/core/lib/Thelia/Core/Template/Loop/Cart.php @@ -0,0 +1,150 @@ +getCurrentRequest()->getSession()->getSessionCart($this->getDispatcher()); + + if (null === $cart) { + return array(); + } + + $returnArray = iterator_to_array($cart->getCartItems()); + + $orders = $this->getOrder(); + + foreach ($orders as $order) { + switch ($order) { + case "reverse": + $returnArray = array_reverse($returnArray, false); + break; + } + } + + return $returnArray; + } + + /** + * @param LoopResult $loopResult + * @return LoopResult + * @throws \Propel\Runtime\Exception\PropelException + */ + public function parseResults(LoopResult $loopResult) + { + $taxCountry = $this->container->get('thelia.taxEngine')->getDeliveryCountry(); + $locale = $this->getCurrentRequest()->getSession()->getLang()->getLocale(); + $checkAvailability = ConfigQuery::checkAvailableStock(); + $defaultAvailability = \intval(ConfigQuery::read('default-available-stock', 100)); + + /** @var CartItemModel $cartItem */ + foreach ($loopResult->getResultDataCollection() as $cartItem) { + $product = $cartItem->getProduct(null, $locale); + $productSaleElement = $cartItem->getProductSaleElements(); + + $loopResultRow = new LoopResultRow($cartItem); + + $loopResultRow->set("ITEM_ID", $cartItem->getId()); + $loopResultRow->set("TITLE", $product->getTitle()); + $loopResultRow->set("REF", $product->getRef()); + $loopResultRow->set("QUANTITY", $cartItem->getQuantity()); + $loopResultRow->set("PRODUCT_ID", $product->getId()); + $loopResultRow->set("PRODUCT_URL", $product->getUrl($this->getCurrentRequest()->getSession()->getLang()->getLocale())); + if (!$checkAvailability || $product->getVirtual() === 1) { + $loopResultRow->set("STOCK", $defaultAvailability); + } else { + $loopResultRow->set("STOCK", $productSaleElement->getQuantity()); + } + $loopResultRow + ->set("PRICE", $cartItem->getPrice()) + ->set("PROMO_PRICE", $cartItem->getPromoPrice()) + ->set("TAXED_PRICE", $cartItem->getTaxedPrice($taxCountry)) + ->set("PROMO_TAXED_PRICE", $cartItem->getTaxedPromoPrice($taxCountry)) + ->set("IS_PROMO", $cartItem->getPromo() === 1 ? 1 : 0) + ; + + $loopResultRow + ->set("TOTAL_PRICE", $cartItem->getTotalPrice()) + ->set("TOTAL_PROMO_PRICE", $cartItem->getTotalPromoPrice()) + ->set("TOTAL_TAXED_PRICE", $cartItem->getTotalTaxedPrice($taxCountry)) + ->set("TOTAL_PROMO_TAXED_PRICE", $cartItem->getTotalTaxedPromoPrice($taxCountry)) + ; + + $loopResultRow + ->set("REAL_PRICE", $cartItem->getRealPrice()) + ->set("REAL_TAXED_PRICE", $cartItem->getRealTaxedPrice($taxCountry)) + ->set("REAL_TOTAL_PRICE", $cartItem->getTotalRealPrice($taxCountry)) + ->set("REAL_TOTAL_TAXED_PRICE", $cartItem->getTotalRealTaxedPrice($taxCountry)) + ; + + $loopResultRow->set("PRODUCT_SALE_ELEMENTS_ID", $productSaleElement->getId()); + $loopResultRow->set("PRODUCT_SALE_ELEMENTS_REF", $productSaleElement->getRef()); + $this->addOutputFields($loopResultRow, $cartItem); + $loopResult->addRow($loopResultRow); + } + + return $loopResult; + } + + /** + * Return the event dispatcher, + * + * @return \Symfony\Component\EventDispatcher\EventDispatcher + */ + public function getDispatcher() + { + return $this->dispatcher; + } +} diff --git a/core/lib/Thelia/Core/Template/Loop/Category.php b/core/lib/Thelia/Core/Template/Loop/Category.php new file mode 100644 index 00000000..6107a4de --- /dev/null +++ b/core/lib/Thelia/Core/Template/Loop/Category.php @@ -0,0 +1,348 @@ + + * @author Etienne Roudeix + * + * {@inheritdoc} + * @method int[] getId() + * @method int[] getParent() + * @method int[] getExcludeParent() + * @method int[] getProduct() + * @method int[] getExcludeProduct() + * @method int[] getContent() + * @method bool getCurrent() + * @method bool getNotEmpty() + * @method bool getWithPrevNextInfo() + * @method bool getNeedCountChild() + * @method bool getNeedProductCount() + * @method bool|string getVisible() + * @method int[] getExclude() + * @method string[] getOrder() + * @method int[] getTemplateId() + */ +class Category extends BaseI18nLoop implements PropelSearchLoopInterface, SearchLoopInterface +{ + use StandardI18nFieldsSearchTrait; + + protected $timestampable = true; + protected $versionable = true; + + /** + * @return ArgumentCollection + */ + protected function getArgDefinitions() + { + return new ArgumentCollection( + Argument::createIntListTypeArgument('id'), + Argument::createIntListTypeArgument('parent'), + Argument::createIntListTypeArgument('exclude_parent'), + Argument::createIntListTypeArgument('product'), + Argument::createIntListTypeArgument('exclude_product'), + Argument::createIntListTypeArgument('content'), + Argument::createBooleanTypeArgument('current'), + Argument::createBooleanTypeArgument('not_empty', 0), + Argument::createBooleanTypeArgument('with_prev_next_info', false), + Argument::createBooleanTypeArgument('need_count_child', false), + Argument::createBooleanTypeArgument('need_product_count', false), + Argument::createBooleanTypeArgument('product_count_visible_only', false), + Argument::createBooleanOrBothTypeArgument('visible', 1), + Argument::createIntListTypeArgument('template_id'), + new Argument( + 'order', + new TypeCollection( + new Type\EnumListType([ + 'id', 'id_reverse', + 'alpha', 'alpha_reverse', + 'manual', 'manual_reverse', + 'visible', 'visible_reverse', + 'created', 'created_reverse', + 'updated', 'updated_reverse', + 'random' + ]) + ), + 'manual' + ), + Argument::createIntListTypeArgument('exclude') + ); + } + + /** + * @return array of available field to search in + */ + public function getSearchIn() + { + return $this->getStandardI18nSearchFields(); + } + + /** + * @param CategoryQuery $search + * @param string $searchTerm + * @param array $searchIn + * @param string $searchCriteria + */ + public function doSearch(&$search, $searchTerm, $searchIn, $searchCriteria) + { + $search->_and(); + + $this->addStandardI18nSearch($search, $searchTerm, $searchCriteria, $searchIn); + } + + public function buildModelCriteria() + { + $search = CategoryQuery::create(); + + /* manage translations */ + $this->configureI18nProcessing($search, array('TITLE', 'CHAPO', 'DESCRIPTION', 'POSTSCRIPTUM', 'META_TITLE', 'META_DESCRIPTION', 'META_KEYWORDS')); + + $id = $this->getId(); + + if (!\is_null($id)) { + $search->filterById($id, Criteria::IN); + } + + $parent = $this->getParent(); + + if (null !== $parent) { + $search->filterByParent($parent, Criteria::IN); + $positionOrderAllowed = true; + } else { + $positionOrderAllowed = false; + } + + $excludeParent = $this->getExcludeParent(); + + if (!\is_null($excludeParent)) { + $search->filterByParent($excludeParent, Criteria::NOT_IN); + } + + $current = $this->getCurrent(); + + if ($current === true) { + $search->filterById($this->getCurrentRequest()->get("category_id")); + } elseif ($current === false) { + $search->filterById($this->getCurrentRequest()->get("category_id"), Criteria::NOT_IN); + } + + $exclude = $this->getExclude(); + + if (!\is_null($exclude)) { + $search->filterById($exclude, Criteria::NOT_IN); + } + + $visible = $this->getVisible(); + + if ($visible !== BooleanOrBothType::ANY) { + $search->filterByVisible($visible ? 1 : 0); + } + + $products = $this->getProduct(); + + if ($products != null) { + $obj = ProductQuery::create()->findPks($products); + + if ($obj != null) { + $search->filterByProduct($obj, Criteria::IN); + } + } + + $excludeProducts = $this->getExcludeProduct(); + + if ($excludeProducts != null) { + $obj = ProductQuery::create()->findPks($excludeProducts); + + if ($obj != null) { + $search->filterByProduct($obj, Criteria::NOT_IN); + } + } + + $contentId = $this->getContent(); + + if ($contentId != null) { + $search->useCategoryAssociatedContentQuery() + ->filterByContentId($contentId, Criteria::IN) + ->endUse() + ; + } + $templateIdList = $this->getTemplateId(); + + if (!\is_null($templateIdList)) { + $search->filterByDefaultTemplateId($templateIdList, Criteria::IN); + } + + $orders = $this->getOrder(); + + foreach ($orders as $order) { + switch ($order) { + case "id": + $search->orderById(Criteria::ASC); + break; + case "id_reverse": + $search->orderById(Criteria::DESC); + break; + case "alpha": + $search->addAscendingOrderByColumn('i18n_TITLE'); + break; + case "alpha_reverse": + $search->addDescendingOrderByColumn('i18n_TITLE'); + break; + case "manual_reverse": + $search->orderByPosition(Criteria::DESC); + break; + case "manual": + $search->orderByPosition(Criteria::ASC); + break; + case "visible": + $search->orderByVisible(Criteria::ASC); + break; + case "visible_reverse": + $search->orderByVisible(Criteria::DESC); + 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": + $search->clearOrderByColumns(); + $search->addAscendingOrderByColumn('RAND()'); + break(2); + break; + } + } + + return $search; + } + + public function parseResults(LoopResult $loopResult) + { + /** @var CategoryModel $category */ + foreach ($loopResult->getResultDataCollection() as $category) { + /* + * no cause pagination lost : + * if ($this->getNotEmpty() && $category->countAllProducts() == 0) continue; + */ + + $loopResultRow = new LoopResultRow($category); + + $loopResultRow + ->set("ID", $category->getId()) + ->set("IS_TRANSLATED", $category->getVirtualColumn('IS_TRANSLATED')) + ->set("LOCALE", $this->locale) + ->set("TITLE", $category->getVirtualColumn('i18n_TITLE')) + ->set("CHAPO", $category->getVirtualColumn('i18n_CHAPO')) + ->set("DESCRIPTION", $category->getVirtualColumn('i18n_DESCRIPTION')) + ->set("POSTSCRIPTUM", $category->getVirtualColumn('i18n_POSTSCRIPTUM')) + ->set("PARENT", $category->getParent()) + ->set("ROOT", $category->getRoot($category->getId())) + ->set("URL", $this->getReturnUrl() ? $category->getUrl($this->locale) : null) + ->set("META_TITLE", $category->getVirtualColumn('i18n_META_TITLE')) + ->set("META_DESCRIPTION", $category->getVirtualColumn('i18n_META_DESCRIPTION')) + ->set("META_KEYWORDS", $category->getVirtualColumn('i18n_META_KEYWORDS')) + ->set("VISIBLE", $category->getVisible() ? "1" : "0") + ->set("POSITION", $category->getPosition()) + ->set("TEMPLATE", $category->getDefaultTemplateId()); + + if ($this->getNeedCountChild()) { + $loopResultRow->set("CHILD_COUNT", $category->countChild()); + } + + if ($this->getNeedProductCount()) { + if ($this->getProductCountVisibleOnly()) { + $loopResultRow->set("PRODUCT_COUNT", $category->countAllProductsVisibleOnly()); + } else { + $loopResultRow->set("PRODUCT_COUNT", $category->countAllProducts()); + } + } + + $isBackendContext = $this->getBackendContext(); + + if ($this->getWithPrevNextInfo()) { + // Find previous and next category + $previousQuery = CategoryQuery::create() + ->filterByParent($category->getParent()) + ->filterByPosition($category->getPosition(), Criteria::LESS_THAN); + + if (! $isBackendContext) { + $previousQuery->filterByVisible(true); + } + + $previous = $previousQuery + ->orderByPosition(Criteria::DESC) + ->findOne(); + + $nextQuery = CategoryQuery::create() + ->filterByParent($category->getParent()) + ->filterByPosition($category->getPosition(), Criteria::GREATER_THAN); + + if (! $isBackendContext) { + $nextQuery->filterByVisible(true); + } + + $next = $nextQuery + ->orderByPosition(Criteria::ASC) + ->findOne(); + + $loopResultRow + ->set("HAS_PREVIOUS", $previous != null ? 1 : 0) + ->set("HAS_NEXT", $next != null ? 1 : 0) + ->set("PREVIOUS", $previous != null ? $previous->getId() : -1) + ->set("NEXT", $next != null ? $next->getId() : -1); + } + + $this->addOutputFields($loopResultRow, $category); + + $loopResult->addRow($loopResultRow); + } + + return $loopResult; + } +} diff --git a/core/lib/Thelia/Core/Template/Loop/CategoryPath.php b/core/lib/Thelia/Core/Template/Loop/CategoryPath.php new file mode 100644 index 00000000..eb87305e --- /dev/null +++ b/core/lib/Thelia/Core/Template/Loop/CategoryPath.php @@ -0,0 +1,125 @@ + c2 -> c3 -> c4, the loop will return c2 + * - visible if true or missing, only visible categories will be displayed. If false, all categories (visible or not) are returned. + * + * Class CategoryPath + * @package Thelia\Core\Template\Loop + * @author Franck Allimant + * + * {@inheritdoc} + * @method int getCategory() + * @method int getDepth() + * @method bool|string getVisible() + */ +class CategoryPath extends BaseI18nLoop implements ArraySearchLoopInterface +{ + /** + * @return ArgumentCollection + */ + protected function getArgDefinitions() + { + return new ArgumentCollection( + Argument::createIntTypeArgument('category', null, true), + Argument::createIntTypeArgument('depth', PHP_INT_MAX), + Argument::createBooleanOrBothTypeArgument('visible', true, false) + ); + } + + public function buildArray() + { + $originalId = $currentId = $this->getCategory(); + $visible = $this->getVisible(); + $depth = $this->getDepth(); + + $results = array(); + + $ids = array(); + + do { + $search = CategoryQuery::create(); + + $this->configureI18nProcessing($search, array('TITLE')); + + $search->filterById($currentId); + + if ($visible !== BooleanOrBothType::ANY) { + $search->filterByVisible($visible); + } + + $category = $search->findOne(); + + if ($category != null) { + $results[] = array( + "ID" => $category->getId(), + "TITLE" => $category->getVirtualColumn('i18n_TITLE'), + "PARENT" => $category->getParent(), + "URL" => $category->getUrl($this->locale), + "LOCALE" => $this->locale, + ); + + $currentId = $category->getParent(); + + if ($currentId > 0) { + // Prevent circular refererences + 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)", + $originalId, + $currentId + ) + ); + } + + $ids[] = $currentId; + } + } + } while ($category != null && $currentId > 0 && --$depth > 0); + + // Reverse list and build the final result + return array_reverse($results); + } + + public function parseResults(LoopResult $loopResult) + { + foreach ($loopResult->getResultDataCollection() as $result) { + $loopResultRow = new LoopResultRow($result); + foreach ($result as $output => $outputValue) { + $loopResultRow->set($output, $outputValue); + } + $this->addOutputFields($loopResultRow, $result); + $loopResult->addRow($loopResultRow); + } + + return $loopResult; + } +} diff --git a/core/lib/Thelia/Core/Template/Loop/CategoryTree.php b/core/lib/Thelia/Core/Template/Loop/CategoryTree.php new file mode 100644 index 00000000..163ec23d --- /dev/null +++ b/core/lib/Thelia/Core/Template/Loop/CategoryTree.php @@ -0,0 +1,167 @@ + + * + * {@inheritdoc} + * @method int getCategory() + * @method int getDepth() + * @method bool getNeedCountChild() + * @method bool|string getVisible() + * @method int[] getExclude() + * @method string[] getOrder() + */ +class CategoryTree extends BaseI18nLoop implements ArraySearchLoopInterface +{ + /** + * @return ArgumentCollection + */ + protected function getArgDefinitions() + { + return new ArgumentCollection( + Argument::createIntTypeArgument('category', null, true), + Argument::createIntTypeArgument('depth', PHP_INT_MAX), + Argument::createBooleanTypeArgument('need_count_child', false), + Argument::createBooleanOrBothTypeArgument('visible', true, false), + Argument::createIntListTypeArgument('exclude', array()), + new Argument( + 'order', + new TypeCollection( + new Type\EnumListType(array('position', 'position_reverse', 'id', 'id_reverse', 'alpha', 'alpha_reverse')) + ), + 'position' + ) + ); + } + + // changement de rubrique + protected function buildCategoryTree($parent, $visible, $level, $previousLevel, $maxLevel, $exclude, &$resultsList) + { + if ($level > $maxLevel) { + return; + } + + $search = CategoryQuery::create(); + $this->configureI18nProcessing($search, array('TITLE')); + + $search->filterByParent($parent); + + if ($visible !== BooleanOrBothType::ANY) { + $search->filterByVisible($visible); + } + + if ($exclude != null) { + $search->filterById($exclude, Criteria::NOT_IN); + } + + $orders = $this->getOrder(); + + foreach ($orders as $order) { + switch ($order) { + case "position": + $search->orderByPosition(Criteria::ASC); + break; + case "position_reverse": + $search->orderByPosition(Criteria::DESC); + break; + case "id": + $search->orderById(Criteria::ASC); + break; + case "id_reverse": + $search->orderById(Criteria::DESC); + break; + case "alpha": + $search->addAscendingOrderByColumn('i18n_TITLE'); + break; + case "alpha_reverse": + $search->addDescendingOrderByColumn('i18n_TITLE'); + break; + } + } + + $results = $search->find(); + + $needCountChild = $this->getNeedCountChild(); + + foreach ($results as $result) { + $row = array( + "ID" => $result->getId(), + "TITLE" => $result->getVirtualColumn('i18n_TITLE'), + "PARENT" => $result->getParent(), + "URL" => $this->getReturnUrl() ? $result->getUrl($this->locale) : null, + "VISIBLE" => $result->getVisible() ? "1" : "0", + "LEVEL" => $level, + 'PREV_LEVEL' => $previousLevel, + ); + + if ($needCountChild) { + $row['CHILD_COUNT'] = $result->countChild(); + } + + $resultsList[] = $row; + + $this->buildCategoryTree($result->getId(), $visible, 1 + $level, $level, $maxLevel, $exclude, $resultsList); + } + } + + public function parseResults(LoopResult $loopResult) + { + foreach ($loopResult->getResultDataCollection() as $result) { + $loopResultRow = new LoopResultRow($result); + foreach ($result as $output => $outputValue) { + $loopResultRow->set($output, $outputValue); + } + + $this->addOutputFields($loopResultRow, $result); + $loopResult->addRow($loopResultRow); + } + + return $loopResult; + } + + public function buildArray() + { + $id = $this->getCategory(); + $depth = $this->getDepth(); + $visible = $this->getVisible(); + $exclude = $this->getExclude(); + + $resultsList = array(); + + $this->buildCategoryTree($id, $visible, 0, 0, $depth, $exclude, $resultsList); + + return $resultsList; + } +} diff --git a/core/lib/Thelia/Core/Template/Loop/Config.php b/core/lib/Thelia/Core/Template/Loop/Config.php new file mode 100644 index 00000000..a400e222 --- /dev/null +++ b/core/lib/Thelia/Core/Template/Loop/Config.php @@ -0,0 +1,174 @@ + + * + * {@inheritdoc} + * @method int[] getId() + * @method string getVariable() + * @method bool|string getHidden() + * @method bool|string getSecured() + * @method int[] getExclude() + * @method string[] getOrder() + */ +class Config extends BaseI18nLoop implements PropelSearchLoopInterface +{ + protected $timestampable = true; + + /** + * @return ArgumentCollection + */ + protected function getArgDefinitions() + { + return new ArgumentCollection( + Argument::createIntTypeArgument('id'), + Argument::createIntListTypeArgument('exclude'), + Argument::createAnyTypeArgument('variable'), + Argument::createBooleanOrBothTypeArgument('hidden'), + Argument::createBooleanOrBothTypeArgument('secured'), + new Argument( + 'order', + new TypeCollection( + new EnumListType( + array( + 'id', 'id_reverse', + 'name', 'name_reverse', + 'title', 'title_reverse', + 'value', 'value_reverse', + ) + ) + ), + 'name' + ) + ); + } + + public function buildModelCriteria() + { + $id = $this->getId(); + $name = $this->getVariable(); + $secured = $this->getSecured(); + $exclude = $this->getExclude(); + + $search = ConfigQuery::create(); + + $this->configureI18nProcessing($search); + + if (! \is_null($id)) { + $search->filterById($id); + } + + if (! \is_null($name)) { + $search->filterByName($name); + } + + if (! \is_null($exclude)) { + $search->filterById($exclude, Criteria::NOT_IN); + } + + if ($this->getHidden() != BooleanOrBothType::ANY) { + $search->filterByHidden($this->getHidden() ? 1 : 0); + } + + if (! \is_null($secured) && $secured != BooleanOrBothType::ANY) { + $search->filterBySecured($secured ? 1 : 0); + } + + $orders = $this->getOrder(); + + foreach ($orders as $order) { + switch ($order) { + case 'id': + $search->orderById(Criteria::ASC); + break; + case 'id_reverse': + $search->orderById(Criteria::DESC); + break; + + case 'name': + $search->orderByName(Criteria::ASC); + break; + case 'name_reverse': + $search->orderByName(Criteria::DESC); + break; + + case 'title': + $search->addAscendingOrderByColumn('i18n_TITLE'); + break; + case 'title_reverse': + $search->addDescendingOrderByColumn('i18n_TITLE'); + break; + + case 'value': + $search->orderByValue(Criteria::ASC); + break; + case 'value_reverse': + $search->orderByValue(Criteria::DESC); + break; + } + } + + return $search; + } + + public function parseResults(LoopResult $loopResult) + { + /** @var ConfigModel $result */ + foreach ($loopResult->getResultDataCollection() as $result) { + $loopResultRow = new LoopResultRow($result); + + $loopResultRow + ->set("ID", $result->getId()) + ->set("NAME", $result->getName()) + ->set("VALUE", $result->getValue()) + ->set("IS_TRANSLATED", $result->getVirtualColumn('IS_TRANSLATED')) + ->set("LOCALE", $this->locale) + ->set("TITLE", $result->getVirtualColumn('i18n_TITLE')) + ->set("CHAPO", $result->getVirtualColumn('i18n_CHAPO')) + ->set("DESCRIPTION", $result->getVirtualColumn('i18n_DESCRIPTION')) + ->set("POSTSCRIPTUM", $result->getVirtualColumn('i18n_POSTSCRIPTUM')) + ->set("HIDDEN", $result->getHidden()) + ->set("SECURED", $result->getSecured()) + ; + + $this->addOutputFields($loopResultRow, $result); + $loopResult->addRow($loopResultRow); + } + + return $loopResult; + } +} diff --git a/core/lib/Thelia/Core/Template/Loop/Content.php b/core/lib/Thelia/Core/Template/Loop/Content.php new file mode 100644 index 00000000..d30e8c89 --- /dev/null +++ b/core/lib/Thelia/Core/Template/Loop/Content.php @@ -0,0 +1,381 @@ + + * + * {@inheritdoc} + * @method int[] getId() + * @method int[] getFolder() + * @method int[] getFolderDefault() + * @method bool getCurrent() + * @method bool getCurrentFolder() + * @method bool getWithPrevNextInfo() + * @method int getDepth() + * @method bool|string getVisible() + * @method string getTitle() + * @method string[] getOrder() + * @method int[] getExclude() + * @method int[] getExcludeFolder() + */ +class Content extends BaseI18nLoop implements PropelSearchLoopInterface, SearchLoopInterface +{ + use StandardI18nFieldsSearchTrait; + + protected $timestampable = true; + protected $versionable = true; + + /** + * @return ArgumentCollection + */ + protected function getArgDefinitions() + { + return new ArgumentCollection( + Argument::createIntListTypeArgument('id'), + Argument::createIntListTypeArgument('folder'), + Argument::createIntListTypeArgument('folder_default'), + Argument::createBooleanTypeArgument('current'), + Argument::createBooleanTypeArgument('current_folder'), + Argument::createBooleanTypeArgument('with_prev_next_info', false), + Argument::createIntTypeArgument('depth', 1), + Argument::createBooleanOrBothTypeArgument('visible', 1), + Argument::createAnyTypeArgument('title'), + new Argument( + 'order', + new TypeCollection( + new Type\EnumListType( + array( + 'id', 'id_reverse', + 'alpha', 'alpha-reverse', 'alpha_reverse', + 'manual', 'manual_reverse', + 'visible', 'visible_reverse', + 'random', + 'given_id', + 'created', 'created_reverse', + 'updated', 'updated_reverse', + 'position', 'position_reverse' + ) + ) + ), + 'alpha' + ), + Argument::createIntListTypeArgument('exclude'), + Argument::createIntListTypeArgument('exclude_folder') + ); + } + + /** + * @return array of available field to search in + */ + public function getSearchIn() + { + return $this->getStandardI18nSearchFields(); + } + + /** + * @param ContentQuery $search + * @param string $searchTerm + * @param array $searchIn + * @param string $searchCriteria + */ + public function doSearch(&$search, $searchTerm, $searchIn, $searchCriteria) + { + $search->_and(); + + $this->addStandardI18nSearch($search, $searchTerm, $searchCriteria, $searchIn); + } + + public function buildModelCriteria() + { + $search = ContentQuery::create(); + + /* manage translations */ + $this->configureI18nProcessing($search, array('TITLE', 'CHAPO', 'DESCRIPTION', 'POSTSCRIPTUM', 'META_TITLE', 'META_DESCRIPTION', 'META_KEYWORDS')); + + $id = $this->getId(); + + if (!\is_null($id)) { + $search->filterById($id, Criteria::IN); + } + + $manualOrderAllowed = false; + if (null !== $folderDefault = $this->getFolderDefault()) { + // Select the contents which have $folderDefault as the default folder. + $search + ->useContentFolderQuery('FolderSelect') + ->filterByDefaultFolder(true) + ->filterByFolderId($folderDefault, Criteria::IN) + ->endUse() + ; + + // We can only sort by position if we have a single folder ID + $manualOrderAllowed = (1 == \count($folderDefault)); + } elseif (null !== $folderIdList = $this->getFolder()) { + // Select all content which have one of the required folders as the default one, or an associated one + $depth = $this->getDepth(); + + $allFolderIDs = FolderQuery::getFolderTreeIds($folderIdList, $depth); + + $search + ->useContentFolderQuery('FolderSelect') + ->filterByFolderId($allFolderIDs, Criteria::IN) + ->endUse() + ; + + // We can only sort by position if we have a single folder ID, with a depth of 1 + $manualOrderAllowed = (1 == $depth && 1 == \count($folderIdList)); + } else { + $search + ->leftJoinContentFolder('FolderSelect') + ->addJoinCondition('FolderSelect', '`FolderSelect`.DEFAULT_FOLDER = 1') + ; + } + + $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(); + + if ($current === true) { + $search->filterById($this->getCurrentRequest()->get("content_id")); + } elseif ($current === false) { + $search->filterById($this->getCurrentRequest()->get("content_id"), Criteria::NOT_IN); + } + + $current_folder = $this->getCurrentFolder(); + + if ($current_folder === true) { + $current = ContentQuery::create()->findPk($this->getCurrentRequest()->get("content_id")); + + $search->filterByFolder($current->getFolders(), Criteria::IN); + } elseif ($current_folder === false) { + $current = ContentQuery::create()->findPk($this->getCurrentRequest()->get("content_id")); + + $search->filterByFolder($current->getFolders(), Criteria::NOT_IN); + } + + $visible = $this->getVisible(); + + if ($visible !== BooleanOrBothType::ANY) { + $search->filterByVisible($visible ? 1 : 0); + } + + $title = $this->getTitle(); + + if (!\is_null($title)) { + $this->addSearchInI18nColumn($search, 'TITLE', Criteria::LIKE, "%".$title."%"); + } + + $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(); + + foreach ($orders as $order) { + switch ($order) { + case "id": + $search->orderById(Criteria::ASC); + break; + case "id_reverse": + $search->orderById(Criteria::DESC); + break; + case "alpha": + $search->addAscendingOrderByColumn('i18n_TITLE'); + break; + case "alpha-reverse": + case "alpha_reverse": + $search->addDescendingOrderByColumn('i18n_TITLE'); + break; + case "manual": + if (! $manualOrderAllowed) { + throw new \InvalidArgumentException('Manual order cannot be set without single folder argument'); + } + $search->addAscendingOrderByColumn('position_delegate'); + break; + case "manual_reverse": + if (! $manualOrderAllowed) { + throw new \InvalidArgumentException('Manual order cannot be set without single folder argument'); + } + $search->addDescendingOrderByColumn('position_delegate'); + break; + case "given_id": + if (null === $id) { + throw new \InvalidArgumentException('Given_id order cannot be set without `id` argument'); + } + foreach ($id as $singleId) { + $givenIdMatched = 'given_id_matched_' . $singleId; + $search->withColumn(ContentTableMap::COL_ID . "='$singleId'", $givenIdMatched); + $search->orderBy($givenIdMatched, Criteria::DESC); + } + break; + case "visible": + $search->orderByVisible(Criteria::ASC); + break; + case "visible_reverse": + $search->orderByVisible(Criteria::DESC); + break; + case "random": + $search->clearOrderByColumns(); + $search->addAscendingOrderByColumn('RAND()'); + break(2); + 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 "position": + $search->addAscendingOrderByColumn('position_delegate'); + break; + case "position_reverse": + $search->addDescendingOrderByColumn('position_delegate'); + break; + } + } + + $search->groupById(); + + return $search; + } + + public function parseResults(LoopResult $loopResult) + { + /** @var ContentModel $content */ + foreach ($loopResult->getResultDataCollection() as $content) { + $loopResultRow = new LoopResultRow($content); + + if ((bool) $content->getVirtualColumn('is_default_folder')) { + $defaultFolderId = $content->getVirtualColumn('default_folder_id'); + } else { + $defaultFolderId = $content->getDefaultFolderId(); + } + + $loopResultRow->set("ID", $content->getId()) + ->set("IS_TRANSLATED", $content->getVirtualColumn('IS_TRANSLATED')) + ->set("LOCALE", $this->locale) + ->set("TITLE", $content->getVirtualColumn('i18n_TITLE')) + ->set("CHAPO", $content->getVirtualColumn('i18n_CHAPO')) + ->set("DESCRIPTION", $content->getVirtualColumn('i18n_DESCRIPTION')) + ->set("POSTSCRIPTUM", $content->getVirtualColumn('i18n_POSTSCRIPTUM')) + ->set("URL", $this->getReturnUrl() ? $content->getUrl($this->locale) : null) + ->set("META_TITLE", $content->getVirtualColumn('i18n_META_TITLE')) + ->set("META_DESCRIPTION", $content->getVirtualColumn('i18n_META_DESCRIPTION')) + ->set("META_KEYWORDS", $content->getVirtualColumn('i18n_META_KEYWORDS')) + ->set("POSITION", $content->getVirtualColumn('position_delegate')) + ->set("DEFAULT_FOLDER", $defaultFolderId) + ->set("VISIBLE", $content->getVisible()); + $this->addOutputFields($loopResultRow, $content); + + $this->findNextPrev($loopResultRow, $content, $defaultFolderId); + + $loopResult->addRow($loopResultRow); + } + + return $loopResult; + } + + /** + * @param LoopResultRow $loopResultRow + * @param ContentModel $content + * @param int $defaultFolderId + */ + private function findNextPrev(LoopResultRow $loopResultRow, ContentModel $content, $defaultFolderId) + { + if ($this->getWithPrevNextInfo()) { + $currentPosition = ContentFolderQuery::create() + ->filterByFolderId($defaultFolderId) + ->filterByContentId($content->getId()) + ->findOne()->getPosition(); + + // Find previous and next content + $previousQuery = ContentFolderQuery::create() + ->filterByFolderId($defaultFolderId) + ->filterByPosition($currentPosition, Criteria::LESS_THAN); + + $nextQuery = ContentFolderQuery::create() + ->filterByFolderId($defaultFolderId) + ->filterByPosition($currentPosition, Criteria::GREATER_THAN); + + if (!$this->getBackendContext()) { + $previousQuery->useContentQuery() + ->filterByVisible(true) + ->endUse(); + + $previousQuery->useContentQuery() + ->filterByVisible(true) + ->endUse(); + } + + $previous = $previousQuery + ->orderByPosition(Criteria::DESC) + ->findOne(); + + $next = $nextQuery + ->orderByPosition(Criteria::ASC) + ->findOne(); + + $loopResultRow + ->set("HAS_PREVIOUS", $previous != null ? 1 : 0) + ->set("HAS_NEXT", $next != null ? 1 : 0) + ->set("PREVIOUS", $previous != null ? $previous->getContentId() : -1) + ->set("NEXT", $next != null ? $next->getContentId() : -1); + } + } +} diff --git a/core/lib/Thelia/Core/Template/Loop/Country.php b/core/lib/Thelia/Core/Template/Loop/Country.php new file mode 100644 index 00000000..414d5a85 --- /dev/null +++ b/core/lib/Thelia/Core/Template/Loop/Country.php @@ -0,0 +1,209 @@ + + * + * {@inheritdoc} + * @method int[] getId() + * @method int[] getArea() + * @method int[] getExcludeArea() + * @method int[] getExclude() + * @method int[] getWithArea() + * @method bool|string getHasStates() + * @method bool|string getVisible() + * @method string[] getOrder() + */ +class Country extends BaseI18nLoop implements PropelSearchLoopInterface +{ + protected $timestampable = true; + + /** + * @return ArgumentCollection + */ + protected function getArgDefinitions() + { + return new ArgumentCollection( + Argument::createIntListTypeArgument('id'), + Argument::createIntListTypeArgument('area'), + Argument::createIntListTypeArgument('exclude_area'), + Argument::createBooleanTypeArgument('with_area'), + Argument::createIntListTypeArgument('exclude'), + Argument::createBooleanOrBothTypeArgument('has_states', BooleanOrBothType::ANY), + Argument::createBooleanOrBothTypeArgument('visible', 1), + new Argument( + 'order', + new TypeCollection( + new EnumListType( + [ + 'id', 'id_reverse', + 'alpha', 'alpha_reverse', + 'visible', 'visible_reverse', + 'random' + ] + ) + ), + 'id' + ) + ); + } + + public function buildModelCriteria() + { + $search = CountryQuery::create(); + + /* manage translations */ + $this->configureI18nProcessing($search); + + $id = $this->getId(); + + if (null !== $id) { + $search->filterById($id, Criteria::IN); + } + + $area = $this->getArea(); + + if (null !== $area) { + $search + ->useCountryAreaQuery('with_area') + ->filterByAreaId($area, Criteria::IN) + ->endUse(); + } + + $excludeArea = $this->getExcludeArea(); + + if (null !== $excludeArea) { + // FIXME : did not find a way to do this in a single request :( + // select * from country where id not in (select country_id from country_area where area in (...)) + $countries = CountryAreaQuery::create() + ->filterByAreaId($excludeArea, Criteria::IN) + ->select([ 'country_id' ]) + ->find() + ; + + $search->filterById($countries->toArray(), Criteria::NOT_IN); + } + + $withArea = $this->getWithArea(); + + if (true === $withArea) { + $search + ->distinct() + ->joinCountryArea('with_area', Criteria::LEFT_JOIN) + ->where('`with_area`.country_id ' . Criteria::ISNOTNULL); + } elseif (false === $withArea) { + $search + ->joinCountryArea('with_area', Criteria::LEFT_JOIN) + ->where('`with_area`.country_id ' . Criteria::ISNULL); + } + + $exclude = $this->getExclude(); + + if (!\is_null($exclude)) { + $search->filterById($exclude, Criteria::NOT_IN); + } + + $hasStates = $this->getHasStates(); + if ($hasStates !== BooleanOrBothType::ANY) { + $search->filterByHasStates($hasStates ? 1 : 0); + } + + $visible = $this->getVisible(); + if ($visible !== BooleanOrBothType::ANY) { + $search->filterByVisible($visible ? 1 : 0); + } + + $orders = $this->getOrder(); + foreach ($orders as $order) { + switch ($order) { + case "id": + $search->orderById(Criteria::ASC); + break; + case "id_reverse": + $search->orderById(Criteria::DESC); + break; + case "alpha": + $search->addAscendingOrderByColumn('i18n_TITLE'); + break; + case "alpha_reverse": + $search->addDescendingOrderByColumn('i18n_TITLE'); + break; + case "visible": + $search->orderByVisible(Criteria::ASC); + break; + case "visible_reverse": + $search->orderByVisible(Criteria::DESC); + break; + case "random": + $search->clearOrderByColumns(); + $search->addAscendingOrderByColumn('RAND()'); + break(2); + break; + } + } + + return $search; + } + + public function parseResults(LoopResult $loopResult) + { + /** @var \Thelia\Model\Country $country */ + foreach ($loopResult->getResultDataCollection() as $country) { + $loopResultRow = new LoopResultRow($country); + $loopResultRow + ->set("ID", $country->getId()) + ->set("VISIBLE", $country->getVisible()) + ->set("IS_TRANSLATED", $country->getVirtualColumn('IS_TRANSLATED')) + ->set("LOCALE", $this->locale) + ->set("TITLE", $country->getVirtualColumn('i18n_TITLE')) + ->set("CHAPO", $country->getVirtualColumn('i18n_CHAPO')) + ->set("DESCRIPTION", $country->getVirtualColumn('i18n_DESCRIPTION')) + ->set("POSTSCRIPTUM", $country->getVirtualColumn('i18n_POSTSCRIPTUM')) + ->set("ISOCODE", sprintf("%03d", $country->getIsocode())) + ->set("ISOALPHA2", $country->getIsoalpha2()) + ->set("ISOALPHA3", $country->getIsoalpha3()) + ->set("IS_DEFAULT", $country->getByDefault() ? "1" : "0") + ->set("IS_SHOP_COUNTRY", $country->getShopCountry() ? "1" : "0") + ->set("HAS_STATES", $country->getHasStates() ? "1" : "0") + ->set("NEED_ZIP_CODE", $country->getNeedZipCode() ? "1" : "0") + ->set("ZIP_CODE_FORMAT", $country->getZipCodeFormat()) + ; + + $this->addOutputFields($loopResultRow, $country); + + $loopResult->addRow($loopResultRow); + } + + return $loopResult; + } +} diff --git a/core/lib/Thelia/Core/Template/Loop/CountryArea.php b/core/lib/Thelia/Core/Template/Loop/CountryArea.php new file mode 100644 index 00000000..124c14af --- /dev/null +++ b/core/lib/Thelia/Core/Template/Loop/CountryArea.php @@ -0,0 +1,145 @@ + + * + * {@inheritdoc} + * @method int[] getId() + * @method int[] getArea() + * @method int[] getCountry() + * @method int[] getState() + * @method string[] getOrder() + */ +class CountryArea extends BaseLoop implements PropelSearchLoopInterface +{ + protected $timestampable = true; + + /** + * @return ArgumentCollection + */ + protected function getArgDefinitions() + { + return new ArgumentCollection( + Argument::createIntListTypeArgument('id'), + Argument::createIntListTypeArgument('area'), + Argument::createIntListTypeArgument('country'), + Argument::createIntListTypeArgument('state'), + new Argument( + 'order', + new TypeCollection( + new EnumListType( + [ + 'id', 'id_reverse', + 'area', 'area_reverse', + 'country', 'country_reverse', + 'state', 'state_reverse', + ] + ) + ), + 'id' + ) + ); + } + + public function buildModelCriteria() + { + $search = CountryAreaQuery::create(); + + if (null !== $id = $this->getId()) { + $search->filterById($id, Criteria::IN); + } + + if (null !== $areas = $this->getArea()) { + $search->filterByAreaId($areas, Criteria::IN); + } + + if (null !== $countries = $this->getCountry()) { + $search->filterByCountryId($countries, Criteria::IN); + } + + if (null !== $states = $this->getState()) { + $search->filterByStateId($states, Criteria::IN); + } + + $orders = $this->getOrder(); + foreach ($orders as $order) { + switch ($order) { + case "id": + $search->orderById(Criteria::ASC); + break; + case "id_reverse": + $search->orderById(Criteria::DESC); + break; + case "area": + $search->orderByAreaId(Criteria::ASC); + break; + case "area_reverse": + $search->orderByAreaId(Criteria::DESC); + break; + case "country": + $search->orderByCountryId(Criteria::ASC); + break; + case "country_reverse": + $search->orderByCountryId(Criteria::DESC); + break; + case "state": + $search->orderByStateId(Criteria::ASC); + break; + case "state_reverse": + $search->orderByStateId(Criteria::DESC); + break; + } + } + + return $search; + } + + public function parseResults(LoopResult $loopResult) + { + /** @var \Thelia\Model\CountryArea $countryArea */ + foreach ($loopResult->getResultDataCollection() as $countryArea) { + $loopResultRow = new LoopResultRow($countryArea); + $loopResultRow + ->set("ID", $countryArea->getId()) + ->set("AREA_ID", $countryArea->getAreaId()) + ->set("COUNTRY_ID", $countryArea->getCountryId()) + ->set("STATE_ID", $countryArea->getStateId()) + ; + + $this->addOutputFields($loopResultRow, $countryArea); + + $loopResult->addRow($loopResultRow); + } + + return $loopResult; + } +} diff --git a/core/lib/Thelia/Core/Template/Loop/Coupon.php b/core/lib/Thelia/Core/Template/Loop/Coupon.php new file mode 100644 index 00000000..16c4acbd --- /dev/null +++ b/core/lib/Thelia/Core/Template/Loop/Coupon.php @@ -0,0 +1,279 @@ + + * + * {@inheritdoc} + * @method int[] getId() + * @method bool|string getIsEnabled() + * @method bool getInUse() + * @method string getCode() + * @method string[] getOrder() + */ +class Coupon extends BaseI18nLoop implements PropelSearchLoopInterface +{ + /** + * Define all args used in your loop + * + * @return ArgumentCollection + */ + protected function getArgDefinitions() + { + return new ArgumentCollection( + Argument::createIntListTypeArgument('id'), + Argument::createBooleanOrBothTypeArgument('is_enabled'), + Argument::createBooleanTypeArgument('in_use'), + Argument::createAnyListTypeArgument('code'), + new Argument( + 'order', + new TypeCollection( + new EnumListType( + array( + 'id', 'id-reverse', + 'code', 'code-reverse', + 'title', 'title-reverse', + 'enabled', 'enabled-reverse', + 'start-date', 'start-date-reverse', + 'expiration-date', 'expiration-date-reverse', + 'days-left', 'days-left-reverse', + 'usages-left', 'usages-left-reverse' + ) + ) + ), + 'code' + ) + ); + } + + public function buildModelCriteria() + { + $search = CouponQuery::create(); + + /* manage translations */ + $this->configureI18nProcessing($search, array('TITLE', 'DESCRIPTION', 'SHORT_DESCRIPTION')); + + $id = $this->getId(); + $isEnabled = $this->getIsEnabled(); + + if (null !== $id) { + $search->filterById($id, Criteria::IN); + } + + if (null !== $code = $this->getCode()) { + $search->filterByCode($code, Criteria::IN); + } + + if (isset($isEnabled)) { + $search->filterByIsEnabled($isEnabled ? true : false); + } + + $inUse = $this->getInUse(); + + if ($inUse !== null) { + // Get the code of coupons currently in use + $consumedCoupons = $this->getCurrentRequest()->getSession()->getConsumedCoupons(); + + // Get only matching coupons. + $criteria = $inUse ? Criteria::IN : Criteria::NOT_IN; + + $search->filterByCode($consumedCoupons, $criteria); + } + + $search->addAsColumn('days_left', 'DATEDIFF('.CouponTableMap::COL_EXPIRATION_DATE.', CURDATE()) - 1'); + + $orders = $this->getOrder(); + + foreach ($orders as $order) { + switch ($order) { + case 'id': + $search->orderById(Criteria::ASC); + break; + case 'id-reverse': + $search->orderById(Criteria::DESC); + break; + + case 'code': + $search->orderByCode(Criteria::ASC); + break; + case 'code-reverse': + $search->orderByCode(Criteria::DESC); + break; + + case 'title': + $search->addAscendingOrderByColumn('i18n_TITLE'); + break; + case 'title-reverse': + $search->addDescendingOrderByColumn('i18n_TITLE'); + break; + + case 'enabled': + $search->orderByIsEnabled(Criteria::ASC); + break; + case 'enabled-reverse': + $search->orderByIsEnabled(Criteria::DESC); + break; + + case 'start-date': + $search->orderByStartDate(Criteria::ASC); + break; + case 'start-date-reverse': + $search->orderByStartDate(Criteria::DESC); + break; + + case 'expiration-date': + $search->orderByExpirationDate(Criteria::ASC); + break; + case 'expiration-date-reverse': + $search->orderByExpirationDate(Criteria::DESC); + break; + + case 'usages-left': + $search->orderByMaxUsage(Criteria::ASC); + break; + case 'usages-left-reverse': + $search->orderByMaxUsage(Criteria::DESC); + break; + + case 'days-left': + $search->addAscendingOrderByColumn('days_left'); + break; + case 'days-left-reverse': + $search->addDescendingOrderByColumn('days_left'); + break; + } + } + + return $search; + } + + /** + * @param LoopResult $loopResult + * @return LoopResult + * @throws \Propel\Runtime\Exception\PropelException + */ + public function parseResults(LoopResult $loopResult) + { + /** @var ConditionFactory $conditionFactory */ + $conditionFactory = $this->container->get('thelia.condition.factory'); + + /** @var MCoupon $coupon */ + foreach ($loopResult->getResultDataCollection() as $coupon) { + $loopResultRow = new LoopResultRow($coupon); + + $conditions = $conditionFactory->unserializeConditionCollection( + $coupon->getSerializedConditions() + ); + + /** @var CouponInterface $couponManager */ + $couponManager = $this->container->get($coupon->getType()); + $couponManager->set( + $this->container->get('thelia.facade'), + $coupon->getCode(), + $coupon->getTitle(), + $coupon->getShortDescription(), + $coupon->getDescription(), + $coupon->getEffects(), + $coupon->getIsCumulative(), + $coupon->getIsRemovingPostage(), + $coupon->getIsAvailableOnSpecialOffers(), + $coupon->getIsEnabled(), + $coupon->getMaxUsage(), + $coupon->getExpirationDate(), + $coupon->getFreeShippingForCountries(), + $coupon->getFreeShippingForModules(), + $coupon->getPerCustomerUsageCount() + ); + + $cleanedConditions = array(); + /** @var ConditionInterface $condition */ + foreach ($conditions as $condition) { + $temp = array( + 'toolTip' => $condition->getToolTip(), + 'summary' => $condition->getSummary() + ); + $cleanedConditions[] = $temp; + } + + $freeShippingForCountriesIds = []; + /** @var CouponCountry $couponCountry */ + foreach ($coupon->getFreeShippingForCountries() as $couponCountry) { + $freeShippingForCountriesIds[] = $couponCountry->getCountryId(); + } + + $freeShippingForModulesIds = []; + /** @var CouponModule $couponModule */ + foreach ($coupon->getFreeShippingForModules() as $couponModule) { + $freeShippingForModulesIds[] = $couponModule->getModuleId(); + } + + // If and only if the coupon is currently in use, get the coupon discount. Calling exec() on a coupon + // which is not currently in use may apply coupon on the cart. This is true for coupons such as FreeProduct, + // which adds a product to the cart. + $discount = $couponManager->isInUse() ? $couponManager->exec() : 0; + + $loopResultRow + ->set("ID", $coupon->getId()) + ->set("IS_TRANSLATED", $coupon->getVirtualColumn('IS_TRANSLATED')) + ->set("LOCALE", $this->locale) + ->set("CODE", $coupon->getCode()) + ->set("TITLE", $coupon->getVirtualColumn('i18n_TITLE')) + ->set("SHORT_DESCRIPTION", $coupon->getVirtualColumn('i18n_SHORT_DESCRIPTION')) + ->set("DESCRIPTION", $coupon->getVirtualColumn('i18n_DESCRIPTION')) + ->set("START_DATE", $coupon->getStartDate()) + ->set("EXPIRATION_DATE", $coupon->getExpirationDate()) + ->set("USAGE_LEFT", $coupon->getMaxUsage()) + ->set("PER_CUSTOMER_USAGE_COUNT", $coupon->getPerCustomerUsageCount()) + ->set("IS_CUMULATIVE", $coupon->getIsCumulative()) + ->set("IS_REMOVING_POSTAGE", $coupon->getIsRemovingPostage()) + ->set("IS_AVAILABLE_ON_SPECIAL_OFFERS", $coupon->getIsAvailableOnSpecialOffers()) + ->set("IS_ENABLED", $coupon->getIsEnabled()) + ->set("AMOUNT", $coupon->getAmount()) + ->set("APPLICATION_CONDITIONS", $cleanedConditions) + ->set("TOOLTIP", $couponManager->getToolTip()) + ->set("DAY_LEFT_BEFORE_EXPIRATION", max(0, $coupon->getVirtualColumn('days_left'))) + ->set("SERVICE_ID", $couponManager->getServiceId()) + ->set("FREE_SHIPPING_FOR_COUNTRIES_LIST", implode(',', $freeShippingForCountriesIds)) + ->set("FREE_SHIPPING_FOR_MODULES_LIST", implode(',', $freeShippingForModulesIds)) + ->set("DISCOUNT_AMOUNT", $discount) + ; + $this->addOutputFields($loopResultRow, $coupon); + + $loopResult->addRow($loopResultRow); + } + + return $loopResult; + } +} diff --git a/core/lib/Thelia/Core/Template/Loop/Currency.php b/core/lib/Thelia/Core/Template/Loop/Currency.php new file mode 100644 index 00000000..a30c7945 --- /dev/null +++ b/core/lib/Thelia/Core/Template/Loop/Currency.php @@ -0,0 +1,190 @@ + + * + * {@inheritdoc} + * @method int[] getId() + * @method int[] getExclude() + * @method bool getDefaultOnly() + * @method bool|string getVisible() + * @method string[] getOrder() + */ +class Currency extends BaseI18nLoop implements PropelSearchLoopInterface +{ + protected $timestampable = true; + + /** + * @return ArgumentCollection + */ + protected function getArgDefinitions() + { + return new ArgumentCollection( + Argument::createIntListTypeArgument('id'), + Argument::createIntListTypeArgument('exclude'), + Argument::createBooleanTypeArgument('default_only', false), + Argument::createBooleanOrBothTypeArgument('visible', true), + new Argument( + 'order', + new TypeCollection( + new EnumListType( + array( + 'id', 'id_reverse', + 'name', 'name_reverse', + 'code', 'code_reverse', + 'symbol', 'symbol_reverse', + 'rate', 'rate_reverse', + 'visible', 'visible_reverse', + 'is_default', 'is_default_reverse', + 'manual', 'manual_reverse') + ) + ), + 'manual' + ) + ); + } + + public function buildModelCriteria() + { + $search = CurrencyQuery::create(); + + /* manage translations */ + $this->configureI18nProcessing($search, array('NAME')); + + if (null !== $id = $this->getId()) { + $search->filterById($id, Criteria::IN); + } + + if (null !== $exclude = $this->getExclude()) { + $search->filterById($exclude, Criteria::NOT_IN); + } + + if ($this->getDefaultOnly() === true) { + $search->filterByByDefault(true); + } + + if ('*' !== $visible = $this->getVisible()) { + $search->filterByVisible($visible); + } + + $orders = $this->getOrder(); + + foreach ($orders as $order) { + switch ($order) { + case 'id': + $search->orderById(Criteria::ASC); + break; + case 'id_reverse': + $search->orderById(Criteria::DESC); + break; + + case 'name': + $search->addAscendingOrderByColumn('i18n_NAME'); + break; + case 'name_reverse': + $search->addDescendingOrderByColumn('i18n_NAME'); + break; + + case 'code': + $search->orderByCode(Criteria::ASC); + break; + case 'code_reverse': + $search->orderByCode(Criteria::DESC); + break; + + case 'symbol': + $search->orderBySymbol(Criteria::ASC); + break; + case 'symbol_reverse': + $search->orderBySymbol(Criteria::DESC); + break; + + case 'rate': + $search->orderByRate(Criteria::ASC); + break; + case 'rate_reverse': + $search->orderByRate(Criteria::DESC); + break; + + case 'visible': + $search->orderByVisible(Criteria::ASC); + break; + case 'visible_reverse': + $search->orderByVisible(Criteria::DESC); + break; + + case 'is_default': + $search->orderByByDefault(Criteria::ASC); + break; + case 'is_default_reverse': + $search->orderByByDefault(Criteria::DESC); + break; + + case 'manual': + $search->orderByPosition(Criteria::ASC); + break; + case 'manual_reverse': + $search->orderByPosition(Criteria::DESC); + break; + } + } + + return $search; + } + + public function parseResults(LoopResult $loopResult) + { + /** @var CurrencyModel $currency */ + foreach ($loopResult->getResultDataCollection() as $currency) { + $loopResultRow = new LoopResultRow($currency); + $loopResultRow + ->set("ID", $currency->getId()) + ->set("IS_TRANSLATED", $currency->getVirtualColumn('IS_TRANSLATED')) + ->set("LOCALE", $this->locale) + ->set("NAME", $currency->getVirtualColumn('i18n_NAME')) + ->set("ISOCODE", $currency->getCode()) + ->set("SYMBOL", $currency->getSymbol()) + ->set("FORMAT", $currency->getFormat()) + ->set("RATE", $currency->getRate()) + ->set("VISIBLE", $currency->getVisible()) + ->set("POSITION", $currency->getPosition()) + ->set("IS_DEFAULT", $currency->getByDefault()) + ; + $this->addOutputFields($loopResultRow, $currency); + + $loopResult->addRow($loopResultRow); + } + + return $loopResult; + } +} diff --git a/core/lib/Thelia/Core/Template/Loop/Customer.php b/core/lib/Thelia/Core/Template/Loop/Customer.php new file mode 100644 index 00000000..524cfef7 --- /dev/null +++ b/core/lib/Thelia/Core/Template/Loop/Customer.php @@ -0,0 +1,285 @@ + + * + * {@inheritdoc} + * @method int[] getId() + * @method bool getCurrent() + * @method string getRef() + * @method bool getReseller() + * @method int getSponsor() + * @method bool|string getNewsletter() + * @method string[] getOrder() + * @method bool getWithPrevNextInfo() + */ +class Customer extends BaseLoop implements SearchLoopInterface, PropelSearchLoopInterface +{ + protected $timestampable = true; + + /** + * @return ArgumentCollection + */ + protected function getArgDefinitions() + { + return new ArgumentCollection( + Argument::createBooleanTypeArgument('current', 1), + Argument::createIntListTypeArgument('id'), + Argument::createBooleanTypeArgument('with_prev_next_info', false), + new Argument( + 'ref', + new TypeCollection( + new Type\AlphaNumStringListType() + ) + ), + Argument::createBooleanTypeArgument('reseller'), + Argument::createIntTypeArgument('sponsor'), + new Argument( + 'order', + new TypeCollection( + new Type\EnumListType( + array( + 'id', + 'id_reverse', + 'reference', + 'reference_reverse', + 'firstname', + 'firstname_reverse', + 'lastname', + 'lastname_reverse', + 'last_order', + 'last_order_reverse', + 'order_amount', + 'order_amount_reverse', + 'registration_date', + 'registration_date_reverse' + ) + ) + ), + 'lastname' + ), + Argument::createBooleanOrBothTypeArgument("newsletter", Type\BooleanOrBothType::ANY) + ); + } + + public function getSearchIn() + { + return array( + "ref", + "firstname", + "lastname", + "email", + ); + } + + /** + * @param CustomerQuery $search + * @param $searchTerm + * @param $searchIn + * @param $searchCriteria + */ + public function doSearch(&$search, $searchTerm, $searchIn, $searchCriteria) + { + $search->_and(); + foreach ($searchIn as $index => $searchInElement) { + if ($index > 0) { + $search->_or(); + } + switch ($searchInElement) { + case "ref": + $search->filterByRef($searchTerm, $searchCriteria); + break; + case "firstname": + $search->filterByFirstname($searchTerm, $searchCriteria); + break; + case "lastname": + $search->filterByLastname($searchTerm, $searchCriteria); + break; + case "email": + $search->filterByEmail($searchTerm, $searchCriteria); + break; + } + } + } + + public function buildModelCriteria() + { + $search = CustomerQuery::create(); + + // Join newsletter + $newsletter = $this->getNewsletter(); + + // if newsletter === "*" or false, it'll be a left join + $join = new Join( + CustomerTableMap::COL_EMAIL, + NewsletterTableMap::COL_EMAIL, + true === $newsletter ? Criteria::INNER_JOIN : Criteria::LEFT_JOIN + ); + + $search + ->addJoinObject($join, 'newsletter_join') + ->addJoinCondition('newsletter_join', NewsletterTableMap::COL_UNSUBSCRIBED . ' = ?', false, null, \PDO::PARAM_BOOL) + ->withColumn("IF(ISNULL(".NewsletterTableMap::COL_EMAIL."), 0, 1)", "is_registered_to_newsletter"); + + // If "*" === $newsletter, no filter will be applied, so it won't change anything + if (false === $newsletter) { + $search->having("is_registered_to_newsletter = 0"); + } + + $current = $this->getCurrent(); + + if ($current === true) { + $currentCustomer = $this->securityContext->getCustomerUser(); + if ($currentCustomer === null) { + return null; + } else { + $search->filterById($currentCustomer->getId(), Criteria::EQUAL); + } + } + + $id = $this->getId(); + + if (null !== $id) { + $search->filterById($id, Criteria::IN); + } + + $ref = $this->getRef(); + + if (null !== $ref) { + $search->filterByRef($ref, Criteria::IN); + } + + $reseller = $this->getReseller(); + + if ($reseller === true) { + $search->filterByReseller(1, Criteria::EQUAL); + } elseif ($reseller === false) { + $search->filterByReseller(0, Criteria::EQUAL); + } + + $sponsor = $this->getSponsor(); + + if ($sponsor !== null) { + $search->filterBySponsor($sponsor, Criteria::EQUAL); + } + + $orders = $this->getOrder(); + + foreach ($orders as $order) { + switch ($order) { + case 'id': + $search->orderById(Criteria::ASC); + break; + case 'id_reverse': + $search->orderById(Criteria::DESC); + break; + case 'reference': + $search->orderByRef(Criteria::ASC); + break; + case 'reference_reverse': + $search->orderByRef(Criteria::DESC); + break; + case 'lastname': + $search->orderByLastname(Criteria::ASC); + break; + case 'lastname_reverse': + $search->orderByLastname(Criteria::DESC); + break; + case 'firstname': + $search->orderByFirstname(Criteria::ASC); + break; + case 'firstname_reverse': + $search->orderByFirstname(Criteria::DESC); + break; + case 'registration_date': + $search->orderByCreatedAt(Criteria::ASC); + break; + case 'registration_date_reverse': + $search->orderByCreatedAt(Criteria::DESC); + break; + } + } + + return $search; + } + + public function parseResults(LoopResult $loopResult) + { + /** @var \Thelia\Model\Customer $customer */ + foreach ($loopResult->getResultDataCollection() as $customer) { + $loopResultRow = new LoopResultRow($customer); + + $loopResultRow + ->set("ID", $customer->getId()) + ->set("REF", $customer->getRef()) + ->set("TITLE", $customer->getTitleId()) + ->set("FIRSTNAME", $customer->getFirstname()) + ->set("LASTNAME", $customer->getLastname()) + ->set("EMAIL", $customer->getEmail()) + ->set("RESELLER", $customer->getReseller()) + ->set("SPONSOR", $customer->getSponsor()) + ->set("DISCOUNT", $customer->getDiscount()) + ->set("NEWSLETTER", $customer->getVirtualColumn("is_registered_to_newsletter")) + ->set("CONFIRMATION_TOKEN", $customer->getConfirmationToken()) + ; + + if ($this->getWithPrevNextInfo()) { + // Find previous and next category + $previousQuery = CustomerQuery::create() + ->filterById($customer->getId(), Criteria::LESS_THAN); + $previous = $previousQuery + ->orderById(Criteria::DESC) + ->findOne(); + $nextQuery = CustomerQuery::create() + ->filterById($customer->getId(), Criteria::GREATER_THAN); + $next = $nextQuery + ->orderById(Criteria::ASC) + ->findOne(); + $loopResultRow + ->set("HAS_PREVIOUS", $previous != null ? 1 : 0) + ->set("HAS_NEXT", $next != null ? 1 : 0) + ->set("PREVIOUS", $previous != null ? $previous->getId() : -1) + ->set("NEXT", $next != null ? $next->getId() : -1); + } + + $this->addOutputFields($loopResultRow, $customer); + + $loopResult->addRow($loopResultRow); + } + + return $loopResult; + } +} diff --git a/core/lib/Thelia/Core/Template/Loop/Delivery.php b/core/lib/Thelia/Core/Template/Loop/Delivery.php new file mode 100644 index 00000000..87809b80 --- /dev/null +++ b/core/lib/Thelia/Core/Template/Loop/Delivery.php @@ -0,0 +1,208 @@ + + * @author Etienne Roudeix + * + * {@inheritdoc} + * + * @method int getAddress() + * @method int getCountry() + * @method int getState() + * + */ +class Delivery extends BaseSpecificModule +{ + public function getArgDefinitions() + { + $collection = parent::getArgDefinitions(); + + $collection + ->addArgument(Argument::createIntTypeArgument("address")) + ->addArgument(Argument::createIntTypeArgument("country")) + ->addArgument(Argument::createIntTypeArgument("state")) + ; + + return $collection; + } + + public function parseResults(LoopResult $loopResult) + { + $cart = $this->getCurrentRequest()->getSession()->getSessionCart($this->dispatcher); + $address = $this->getDeliveryAddress(); + + $country = $this->getCurrentCountry(); + if (null === $country) { + if ($address !== null) { + $country = $address->getCountry(); + } else { + $country = CountryQuery::create()->findOneByByDefault(true); + } + } + + $state = $this->getCurrentState(); + if (null === $state) { + if ($address !== null) { + $state = $address->getState(); + } + } + + $virtual = $cart->isVirtual(); + + /** @var Module $deliveryModule */ + foreach ($loopResult->getResultDataCollection() as $deliveryModule) { + $areaDeliveryModule = AreaDeliveryModuleQuery::create() + ->findByCountryAndModule($country, $deliveryModule, $state) + ; + + if (null === $areaDeliveryModule && false === $virtual) { + continue; + } + + /** @var DeliveryModuleInterface|DeliveryModuleWithStateInterface $moduleInstance */ + $moduleInstance = $deliveryModule->getDeliveryModuleInstance($this->container); + + if (true === $virtual + && false === $moduleInstance->handleVirtualProductDelivery() + && false === $this->getBackendContext() + ) { + continue; + } + + $loopResultRow = new LoopResultRow($deliveryModule); + + try { + // Check if module is valid, by calling isValidDelivery(), + // or catching a DeliveryException. + /** @var CartModel $cart */ + $cart->getAddressDeliveryId(); + $deliveryPostageEvent = new DeliveryPostageEvent($moduleInstance, $cart, $address, $country, $state); + $this->dispatcher->dispatch( + TheliaEvents::MODULE_DELIVERY_GET_POSTAGE, + $deliveryPostageEvent + ); + + if ($deliveryPostageEvent->isValidModule()) { + $postage = $deliveryPostageEvent->getPostage(); + + $loopResultRow + ->set('ID', $deliveryModule->getId()) + ->set('CODE', $deliveryModule->getCode()) + ->set('TITLE', $deliveryModule->getVirtualColumn('i18n_TITLE')) + ->set('CHAPO', $deliveryModule->getVirtualColumn('i18n_CHAPO')) + ->set('DESCRIPTION', $deliveryModule->getVirtualColumn('i18n_DESCRIPTION')) + ->set('POSTSCRIPTUM', $deliveryModule->getVirtualColumn('i18n_POSTSCRIPTUM')) + ->set('POSTAGE', $postage->getAmount()) + ->set('POSTAGE_TAX', $postage->getAmountTax()) + ->set('POSTAGE_UNTAXED', $postage->getAmount() - $postage->getAmountTax()) + ->set('POSTAGE_TAX_RULE_TITLE', $postage->getTaxRuleTitle()) + ->set('DELIVERY_DATE', $deliveryPostageEvent->getDeliveryDate()) + ; + + // add additional data if it exists + if ($deliveryPostageEvent->hasAdditionalData()) { + foreach ($deliveryPostageEvent->getAdditionalData() as $key => $value) { + $loopResultRow->set($key, $value); + } + } + + $this->addOutputFields($loopResultRow, $deliveryModule); + + $loopResult->addRow($loopResultRow); + } + } catch (DeliveryException $ex) { + // Module is not available + } + } + + return $loopResult; + } + + protected function getModuleType() + { + return BaseModule::DELIVERY_MODULE_TYPE; + } + + /** + * @return array|mixed|\Thelia\Model\Country + */ + protected function getCurrentCountry() + { + $countryId = $this->getCountry(); + if (null !== $countryId) { + $country = CountryQuery::create()->findPk($countryId); + if (null === $country) { + throw new \InvalidArgumentException('Cannot found country id: `' . $countryId . '` in delivery loop'); + } + return $country; + } + + return null; + } + + /** + * @return array|mixed|\Thelia\Model\State + */ + protected function getCurrentState() + { + $stateId = $this->getState(); + if (null !== $stateId) { + $state = StateQuery::create()->findPk($stateId); + if (null === $state) { + throw new \InvalidArgumentException('Cannot found state id: `' . $stateId . '` in delivery loop'); + } + return $state; + } + + return null; + } + + /** + * @return array|mixed|\Thelia\Model\Address + */ + protected function getDeliveryAddress() + { + $address = null; + + $addressId = $this->getAddress(); + if (empty($addressId)) { + $addressId = $this->getCurrentRequest()->getSession()->getOrder()->getChoosenDeliveryAddress(); + } + + if (!empty($addressId)) { + $address = AddressQuery::create()->findPk($addressId); + } + + return $address; + } +} diff --git a/core/lib/Thelia/Core/Template/Loop/Document.php b/core/lib/Thelia/Core/Template/Loop/Document.php new file mode 100644 index 00000000..5849b00f --- /dev/null +++ b/core/lib/Thelia/Core/Template/Loop/Document.php @@ -0,0 +1,322 @@ + + * + * {@inheritdoc} + * @method int[] getId() + * @method int[] getExclude() + * @method bool|string getVisible() + * @method int getLang() + * @method int getCategory() + * @method int getProduct() + * @method int getFolder() + * @method int getContent() + * @method string getSource() + * @method int getSourceId() + * @method bool getNewsletter() + * @method string getQueryNamespace() + * @method string[] getOrder() + */ +class Document extends BaseI18nLoop implements PropelSearchLoopInterface +{ + protected $objectType; + protected $objectId; + + protected $timestampable = true; + + /** + * @var array Possible standard document sources + */ + protected $possible_sources = array('category', 'product', 'folder', 'content', 'brand'); + + /** + * @return \Thelia\Core\Template\Loop\Argument\ArgumentCollection + */ + protected function getArgDefinitions() + { + $collection = new ArgumentCollection( + Argument::createIntListTypeArgument('id'), + Argument::createIntListTypeArgument('exclude'), + Argument::createBooleanOrBothTypeArgument('visible', 1), + new Argument( + 'order', + new TypeCollection( + new EnumListType(array('alpha', 'alpha-reverse', 'manual', 'manual-reverse', 'random')) + ), + 'manual' + ), + Argument::createIntTypeArgument('lang'), + Argument::createIntTypeArgument('category'), + Argument::createIntTypeArgument('product'), + Argument::createIntTypeArgument('folder'), + Argument::createIntTypeArgument('content'), + Argument::createAnyTypeArgument('source'), + Argument::createIntTypeArgument('source_id'), + Argument::createBooleanTypeArgument('force_return', true), + Argument::createAnyTypeArgument('query_namespace', 'Thelia\\Model'), + Argument::createBooleanTypeArgument('with_prev_next_info', false) + ); + + // Add possible document sources + foreach ($this->possible_sources as $source) { + $collection->addArgument(Argument::createIntTypeArgument($source)); + } + + return $collection; + } + + /** + * Dynamically create the search query, and set the proper filter and order + * + * @param string $source a valid source identifier (@see $possible_sources) + * @param int $object_id the source object ID + * @return ModelCriteria the propel Query object + */ + protected function createSearchQuery($source, $object_id) + { + $object = ucfirst($source); + + $ns = $this->getQueryNamespace(); + + if ('\\' !== $ns[0]) { + $ns = '\\'.$ns; + } + + $queryClass = sprintf("%s\\%sDocumentQuery", $ns, $object); + $filterMethod = sprintf("filterBy%sId", $object); + + // xxxDocumentQuery::create() + $method = new \ReflectionMethod($queryClass, 'create'); + $search = $method->invoke(null); // Static ! + + // $query->filterByXXX(id) + if (! \is_null($object_id)) { + $method = new \ReflectionMethod($queryClass, $filterMethod); + $method->invoke($search, $object_id); + } + + $orders = $this->getOrder(); + + // Results ordering + foreach ($orders as $order) { + switch ($order) { + case "alpha": + $search->addAscendingOrderByColumn('i18n_TITLE'); + break; + case "alpha-reverse": + $search->addDescendingOrderByColumn('i18n_TITLE'); + break; + case "manual-reverse": + $search->orderByPosition(Criteria::DESC); + break; + case "manual": + $search->orderByPosition(Criteria::ASC); + break; + case "random": + $search->clearOrderByColumns(); + $search->addAscendingOrderByColumn('RAND()'); + break(2); + break; + } + } + + return $search; + } + + /** + * Dynamically create the search query, and set the proper filter and order + * + * @param string $object_type (returned) the a valid source identifier (@see $possible_sources) + * @param string $object_id (returned) the ID of the source object + * @return ModelCriteria the propel Query object + */ + protected function getSearchQuery(&$object_type, &$object_id) + { + $search = null; + + // Check form source="product" source_id="123" style arguments + $source = $this->getSource(); + + if (! \is_null($source)) { + $source_id = $this->getSourceId(); + $id = $this->getId(); + + if (\is_null($source_id) && \is_null($id)) { + throw new \InvalidArgumentException("If 'source' argument is specified, 'id' or 'source_id' argument should be specified"); + } + + $search = $this->createSearchQuery($source, $source_id); + + $object_type = $source; + $object_id = $source_id; + } else { + // Check for product="id" folder="id", etc. style arguments + foreach ($this->possible_sources as $source) { + $argValue = \intval($this->getArgValue($source)); + + if ($argValue > 0) { + $search = $this->createSearchQuery($source, $argValue); + + $object_type = $source; + $object_id = $argValue; + + break; + } + } + } + + if ($search == null) { + throw new \InvalidArgumentException(sprintf("Unable to find document source. Valid sources are %s", implode(',', $this->possible_sources))); + } + + return $search; + } + + public function buildModelCriteria() + { + // Select the proper query to use, and get the object type + $this->objectType = $this->objectId = null; + + /** @var ProductDocumentQuery $search */ + $search = $this->getSearchQuery($this->objectType, $this->objectId); + + /* manage translations */ + $this->configureI18nProcessing($search); + + $id = $this->getId(); + + if (! \is_null($id)) { + $search->filterById($id, Criteria::IN); + } + + $exclude = $this->getExclude(); + if (!\is_null($exclude)) { + $search->filterById($exclude, Criteria::NOT_IN); + } + + $visible = $this->getVisible(); + if ($visible !== BooleanOrBothType::ANY) { + $search->filterByVisible($visible ? 1 : 0); + } + + return $search; + } + + public function parseResults(LoopResult $loopResult) + { + $baseSourceFilePath = ConfigQuery::read('documents_library_path'); + if ($baseSourceFilePath === null) { + $baseSourceFilePath = THELIA_LOCAL_DIR . 'media' . DS . 'documents'; + } else { + $baseSourceFilePath = THELIA_ROOT . $baseSourceFilePath; + } + + /** @var ProductDocument $result */ + foreach ($loopResult->getResultDataCollection() as $result) { + // Create document processing event + $event = new DocumentEvent(); + + // Put source document file path + $sourceFilePath = sprintf( + '%s/%s/%s', + $baseSourceFilePath, + $this->objectType, + $result->getFile() + ); + + $event->setSourceFilepath($sourceFilePath); + $event->setCacheSubdirectory($this->objectType); + + try { + // Dispatch document processing event + $this->dispatcher->dispatch(TheliaEvents::DOCUMENT_PROCESS, $event); + + $loopResultRow = new LoopResultRow($result); + + $loopResultRow + ->set("ID", $result->getId()) + ->set("LOCALE", $this->locale) + ->set("DOCUMENT_FILE", $result->getFile()) + ->set("DOCUMENT_URL", $event->getDocumentUrl()) + ->set("DOCUMENT_PATH", $event->getDocumentPath()) + ->set("ORIGINAL_DOCUMENT_PATH", $sourceFilePath) + ->set("TITLE", $result->getVirtualColumn('i18n_TITLE')) + ->set("CHAPO", $result->getVirtualColumn('i18n_CHAPO')) + ->set("DESCRIPTION", $result->getVirtualColumn('i18n_DESCRIPTION')) + ->set("POSTSCRIPTUM", $result->getVirtualColumn('i18n_POSTSCRIPTUM')) + ->set("VISIBLE", $result->getVisible()) + ->set("POSITION", $result->getPosition()) + ->set("OBJECT_TYPE", $this->objectType) + ->set("OBJECT_ID", $this->objectId) + ; + + $isBackendContext = $this->getBackendContext(); + if ($this->getWithPrevNextInfo()) { + $previousQuery = $this->getSearchQuery($this->objectType, $this->objectId) + ->filterByPosition($result->getPosition(), Criteria::LESS_THAN); + if (! $isBackendContext) { + $previousQuery->filterByVisible(true); + } + $previous = $previousQuery + ->orderByPosition(Criteria::DESC) + ->findOne(); + $nextQuery = $this->getSearchQuery($this->objectType, $this->objectId) + ->filterByPosition($result->getPosition(), Criteria::GREATER_THAN); + if (! $isBackendContext) { + $nextQuery->filterByVisible(true); + } + $next = $nextQuery + ->orderByPosition(Criteria::ASC) + ->findOne(); + $loopResultRow + ->set("HAS_PREVIOUS", $previous != null ? 1 : 0) + ->set("HAS_NEXT", $next != null ? 1 : 0) + ->set("PREVIOUS", $previous != null ? $previous->getId() : -1) + ->set("NEXT", $next != null ? $next->getId() : -1); + } + + $this->addOutputFields($loopResultRow, $result); + + $loopResult->addRow($loopResultRow); + } catch (\Exception $ex) { + // Ignore the result and log an error + Tlog::getInstance()->addError(sprintf("Failed to process document in document loop: %s", $ex->getMessage())); + } + } + + return $loopResult; + } +} diff --git a/core/lib/Thelia/Core/Template/Loop/Export.php b/core/lib/Thelia/Core/Template/Loop/Export.php new file mode 100644 index 00000000..f2639f2b --- /dev/null +++ b/core/lib/Thelia/Core/Template/Loop/Export.php @@ -0,0 +1,41 @@ + + */ +class Export extends ImportExportType +{ + protected function getBaseUrl() + { + return $this->container->getParameter("export.base_url"); + } + + /** + * @return ExportQUery + */ + protected function getQueryModel() + { + return ExportQuery::create(); + } + + protected function getCategoryName() + { + return "ExportCategoryId"; + } +} diff --git a/core/lib/Thelia/Core/Template/Loop/ExportCategory.php b/core/lib/Thelia/Core/Template/Loop/ExportCategory.php new file mode 100644 index 00000000..0877ed81 --- /dev/null +++ b/core/lib/Thelia/Core/Template/Loop/ExportCategory.php @@ -0,0 +1,31 @@ + + */ +class ExportCategory extends ImportExportCategory +{ + /** + * @return ExportCategoryQuery + */ + protected function getQueryModel() + { + return ExportCategoryQuery::create(); + } +} diff --git a/core/lib/Thelia/Core/Template/Loop/Feature.php b/core/lib/Thelia/Core/Template/Loop/Feature.php new file mode 100644 index 00000000..1a1b86ea --- /dev/null +++ b/core/lib/Thelia/Core/Template/Loop/Feature.php @@ -0,0 +1,255 @@ + + * + * {@inheritdoc} + * @method int[] getId() + * @method int[] getProduct() + * @method int[] getTemplate() + * @method int[] getExcludeTemplate() + * @method bool|string getVisible() + * @method int[] getExclude() + * @method string getTitle() + * @method string[] getOrder() + */ +class Feature extends BaseI18nLoop implements PropelSearchLoopInterface +{ + protected $useFeaturePosition; + + protected $timestampable = true; + + /** + * @return ArgumentCollection + */ + protected function getArgDefinitions() + { + return new ArgumentCollection( + Argument::createIntListTypeArgument('id'), + Argument::createIntListTypeArgument('product'), + Argument::createIntListTypeArgument('template'), + Argument::createIntListTypeArgument('exclude_template'), + Argument::createBooleanOrBothTypeArgument('visible', 1), + Argument::createIntListTypeArgument('exclude'), + new Argument( + 'order', + new TypeCollection( + new Type\EnumListType(array('id', 'id_reverse', 'alpha', 'alpha-reverse', 'manual', 'manual_reverse')) + ), + 'manual' + ), + Argument::createAnyTypeArgument('title') + ); + } + + /** + * @return \Propel\Runtime\ActiveQuery\ModelCriteria|FeatureQuery + * @throws \Propel\Runtime\Exception\PropelException + */ + public function buildModelCriteria() + { + $search = FeatureQuery::create(); + + /* manage translations */ + $this->configureI18nProcessing($search); + + $id = $this->getId(); + + if (null !== $id) { + $search->filterById($id, Criteria::IN); + } + + $exclude = $this->getExclude(); + + if (null !== $exclude) { + $search->filterById($exclude, Criteria::NOT_IN); + } + + $visible = $this->getVisible(); + + if ($visible != BooleanOrBothType::ANY) { + $search->filterByVisible($visible); + } + + $product = $this->getProduct(); + $template = $this->getTemplate(); + $excludeTemplate = $this->getExcludeTemplate(); + + $this->useFeaturePosition = true; + + if (null !== $product) { + // As we join with freature_value, we may get multiple times the same line + $search->distinct(); + + // Find all template assigned to the products. + $products = ProductQuery::create()->filterById($product, Criteria::IN)->find(); + + // Create template array + if ($template == null) { + $template = []; + } + + /** @var ProductModel $product */ + foreach ($products as $product) { + if (! $this->getBackendContext()) { + $search + ->useFeatureProductQuery() + ->filterByProduct($product) + ->endUse() + ; + } + + $tplId = $product->getTemplateId(); + + if (! empty($tplId)) { + $template[] = $tplId; + } + } + + // franck@cqfdev.fr - 05/12/2013 : if the given product has no template + // or if the product cannot be found, do not return anything. + if (empty($template)) { + return null; + } + } + + if (! empty($template)) { + // Join with feature_template table to get position, if a manual order position is required + if (\count(array_diff(['manual_reverse', 'manual'], $this->getOrder())) < 2) { + $search + ->filterByTemplate( + TemplateQuery::create()->filterById($template, Criteria::IN)->find(), + Criteria::IN + ) + ->withColumn(FeatureTemplateTableMap::COL_POSITION, 'position'); + + $this->useFeaturePosition = false; + } + } + + if (null !== $excludeTemplate) { + $search + ->filterById( + FeatureTemplateQuery::create()->filterByTemplateId($excludeTemplate)->select('feature_id')->find(), + Criteria::NOT_IN + ) + ; + } + + $title = $this->getTitle(); + + if (null !== $title) { + //find all feature that match exactly this title and find with all locales. + $features = FeatureI18nQuery::create() + ->filterByTitle($title, Criteria::LIKE) + ->select('id') + ->find(); + + if ($features) { + $search->filterById( + $features, + Criteria::IN + ); + } + } + + $orders = $this->getOrder(); + + foreach ($orders as $order) { + switch ($order) { + case "id": + $search->orderById(Criteria::ASC); + break; + case "id_reverse": + $search->orderById(Criteria::DESC); + break; + case "alpha": + $search->addAscendingOrderByColumn('i18n_TITLE'); + break; + case "alpha-reverse": + $search->addDescendingOrderByColumn('i18n_TITLE'); + break; + case "manual": + if ($this->useFeaturePosition) { + $search->orderByPosition(Criteria::ASC); + } else { + $search->addAscendingOrderByColumn(FeatureTemplateTableMap::COL_POSITION); + } + break; + case "manual_reverse": + if ($this->useFeaturePosition) { + $search->orderByPosition(Criteria::DESC); + } else { + $search->addDescendingOrderByColumn(FeatureTemplateTableMap::COL_POSITION); + } + break; + } + } + + return $search; + } + + /** + * @param LoopResult $loopResult + * @return LoopResult + * @throws \Propel\Runtime\Exception\PropelException + */ + public function parseResults(LoopResult $loopResult) + { + /** @var FeatureModel $feature */ + foreach ($loopResult->getResultDataCollection() as $feature) { + $loopResultRow = new LoopResultRow($feature); + $loopResultRow->set("ID", $feature->getId()) + ->set("IS_TRANSLATED", $feature->getVirtualColumn('IS_TRANSLATED')) + ->set("LOCALE", $this->locale) + ->set("TITLE", $feature->getVirtualColumn('i18n_TITLE')) + ->set("CHAPO", $feature->getVirtualColumn('i18n_CHAPO')) + ->set("DESCRIPTION", $feature->getVirtualColumn('i18n_DESCRIPTION')) + ->set("POSTSCRIPTUM", $feature->getVirtualColumn('i18n_POSTSCRIPTUM')) + ->set("POSITION", $this->useFeaturePosition ? $feature->getPosition() : $feature->getVirtualColumn('position')) + ; + $this->addOutputFields($loopResultRow, $feature); + + $loopResult->addRow($loopResultRow); + } + + return $loopResult; + } +} diff --git a/core/lib/Thelia/Core/Template/Loop/FeatureAvailability.php b/core/lib/Thelia/Core/Template/Loop/FeatureAvailability.php new file mode 100644 index 00000000..f145c7d0 --- /dev/null +++ b/core/lib/Thelia/Core/Template/Loop/FeatureAvailability.php @@ -0,0 +1,154 @@ + + * + * {@inheritdoc} + * @method int[] getId() + * @method int[] getFeature() + * @method int[] getExclude() + * @method string[] getOrder() + */ +class FeatureAvailability extends BaseI18nLoop implements PropelSearchLoopInterface +{ + protected $timestampable = true; + + /** + * @return ArgumentCollection + */ + protected function getArgDefinitions() + { + return new ArgumentCollection( + Argument::createIntListTypeArgument('id'), + Argument::createIntListTypeArgument('feature'), + Argument::createIntListTypeArgument('exclude'), + new Argument( + 'order', + new TypeCollection( + new Type\EnumListType(array('id', 'id_reverse', 'alpha', 'alpha-reverse', 'alpha_reverse', 'manual', 'manual_reverse')) + ), + 'manual' + ) + ); + } + + public function buildModelCriteria() + { + $search = FeatureAvQuery::create(); + + /* manage translations */ + $this->configureI18nProcessing($search); + + $id = $this->getId(); + + if (null !== $id) { + $search->filterById($id, Criteria::IN); + } + + $exclude = $this->getExclude(); + + if (null !== $exclude) { + $search->filterById($exclude, Criteria::NOT_IN); + } + + $feature = $this->getFeature(); + + if (null !== $feature) { + $search->filterByFeatureId($feature, Criteria::IN); + } + + $orders = $this->getOrder(); + + foreach ($orders as $order) { + switch ($order) { + case 'id': + $search->orderById(Criteria::ASC); + break; + case 'id_reverse': + $search->orderById(Criteria::DESC); + break; + case "alpha": + $search->addAscendingOrderByColumn('i18n_TITLE'); + break; + case "alpha_reverse": + case "alpha-reverse": + $search->addDescendingOrderByColumn('i18n_TITLE'); + break; + case "manual": + $search->orderByPosition(Criteria::ASC); + break; + case "manual_reverse": + $search->orderByPosition(Criteria::DESC); + break; + } + } + + // Search only non-freetext feature values. + $search + ->useFeatureProductQuery() + ->filterByIsFreeText(false) + ->_or() + ->filterByIsFreeText(null) //does not belong to any product + ->endUse() + ; + + // Joining with FeatureProduct may result in multiple occurences of the same FeatureAv. Juste get one. + $search->distinct(); + + return $search; + } + + public function parseResults(LoopResult $loopResult) + { + /** @var FeatureAv $featureAv */ + foreach ($loopResult->getResultDataCollection() as $featureAv) { + $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; + } +} diff --git a/core/lib/Thelia/Core/Template/Loop/FeatureValue.php b/core/lib/Thelia/Core/Template/Loop/FeatureValue.php new file mode 100644 index 00000000..23d5def7 --- /dev/null +++ b/core/lib/Thelia/Core/Template/Loop/FeatureValue.php @@ -0,0 +1,164 @@ + + * + * {@inheritdoc} + * @method int getFeature() + * @method int getProduct() + * @method string[] getFreeText() + * @method int[] getFeatureAvailability() + * @method bool getExcludeFeatureAvailability() + * @method bool getExcludeFreeText() + * @method string[] getOrder() + */ +class FeatureValue extends BaseI18nLoop implements PropelSearchLoopInterface +{ + protected $timestampable = true; + + /** + * @return ArgumentCollection + */ + protected function getArgDefinitions() + { + return new ArgumentCollection( + Argument::createIntTypeArgument('feature', null, true), + Argument::createIntTypeArgument('product'), + Argument::createIntListTypeArgument('feature_availability'), + Argument::createAnyListTypeArgument('free_text'), + Argument::createBooleanTypeArgument('exclude_feature_availability', 0), + Argument::createBooleanTypeArgument('exclude_free_text', 0), + new Argument( + 'order', + new TypeCollection( + new Type\EnumListType(array('alpha', 'alpha_reverse', 'manual', 'manual_reverse')) + ), + 'manual' + ), + Argument::createBooleanTypeArgument('force_return', true) + ); + } + + public function buildModelCriteria() + { + $search = FeatureProductQuery::create(); + + // manage featureAv translations + $this->configureI18nProcessing( + $search, + array('TITLE', 'CHAPO', 'DESCRIPTION', 'POSTSCRIPTUM'), + FeatureAvTableMap::TABLE_NAME, + 'FEATURE_AV_ID', + true + ); + + $search + ->useFeatureAvQuery('feature_av') + ->withColumn(FeatureAvTableMap::COL_POSITION, 'feature_av_position') + ->endUse(); + + $feature = $this->getFeature(); + + $search->filterByFeatureId($feature, Criteria::EQUAL); + + if (null !== $product = $this->getProduct()) { + $search->filterByProductId($product, Criteria::EQUAL); + } + + if (null !== $featureAvailability = $this->getFeatureAvailability()) { + $search->filterByFeatureAvId($featureAvailability, Criteria::IN); + } + + if (null !== $freeText = $this->getFreeText()) { + $search->filterByFreeTextValue($freeText); + } + + if (true === $excludeFeatureAvailability = $this->getExcludeFeatureAvailability()) { + $search->filterByFeatureAvId(null, Criteria::ISNULL); + } + + if (true === $excludeFreeText = $this->getExcludeFreeText()) { + $search->filterByIsFreeText(false); + } + + $orders = $this->getOrder(); + + foreach ($orders as $order) { + switch ($order) { + case "alpha": + $search->addAscendingOrderByColumn(FeatureAvTableMap::TABLE_NAME . '_i18n_TITLE'); + break; + case "alpha_reverse": + $search->addDescendingOrderByColumn(FeatureAvTableMap::TABLE_NAME . '_i18n_TITLE'); + break; + case "manual": + $search->orderBy('feature_av_position', Criteria::ASC); + break; + case "manual_reverse": + $search->orderBy('feature_av_position', Criteria::DESC); + break; + } + } + + return $search; + } + + public function parseResults(LoopResult $loopResult) + { + /** @var \Thelia\Model\FeatureProduct $featureValue */ + foreach ($loopResult->getResultDataCollection() as $featureValue) { + $loopResultRow = new LoopResultRow($featureValue); + + $loopResultRow + ->set("ID", $featureValue->getId()) + ->set("PRODUCT", $featureValue->getProductId()) + ->set("PRODUCT_ID", $featureValue->getProductId()) + ->set("FEATURE_AV_ID", $featureValue->getFeatureAvId()) + ->set("FREE_TEXT_VALUE", $featureValue->getFreeTextValue()) + ->set("IS_FREE_TEXT", \is_null($featureValue->getFeatureAvId()) ? 1 : 0) + ->set("IS_FEATURE_AV", \is_null($featureValue->getFeatureAvId()) ? 0 : 1) + ->set("LOCALE", $this->locale) + ->set("TITLE", $featureValue->getVirtualColumn(FeatureAvTableMap::TABLE_NAME . '_i18n_TITLE')) + ->set("CHAPO", $featureValue->getVirtualColumn(FeatureAvTableMap::TABLE_NAME . '_i18n_CHAPO')) + ->set("DESCRIPTION", $featureValue->getVirtualColumn(FeatureAvTableMap::TABLE_NAME . '_i18n_DESCRIPTION')) + ->set("POSTSCRIPTUM", $featureValue->getVirtualColumn(FeatureAvTableMap::TABLE_NAME . '_i18n_POSTSCRIPTUM')) + ->set("POSITION", $featureValue->getPosition()) + ; + $this->addOutputFields($loopResultRow, $featureValue); + + $loopResult->addRow($loopResultRow); + } + + return $loopResult; + } +} diff --git a/core/lib/Thelia/Core/Template/Loop/Feed.php b/core/lib/Thelia/Core/Template/Loop/Feed.php new file mode 100644 index 00000000..a3c0f61d --- /dev/null +++ b/core/lib/Thelia/Core/Template/Loop/Feed.php @@ -0,0 +1,86 @@ + + * + * {@inheritdoc} + * @method string getUrl() + * @method int getTimeout() + */ +class Feed extends BaseLoop implements ArraySearchLoopInterface +{ + public function getArgDefinitions() + { + return new ArgumentCollection( + Argument::createAnyTypeArgument('url', null, true), + Argument::createIntTypeArgument('timeout', 10) + ); + } + + public function buildArray() + { + /** @var AdapterInterface $cacheAdapter */ + $cacheAdapter = $this->container->get('thelia.cache'); + + $cacheItem = $cacheAdapter->getItem('feed_' . md5($this->getUrl())); + + 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); + } + + return $cacheItem->get(); + } + + public function parseResults(LoopResult $loopResult) + { + /** @var \SimplePie_Item $item */ + foreach ($loopResult->getResultDataCollection() as $item) { + $loopResultRow = new LoopResultRow(); + + $loopResultRow + ->set("URL", $item->get_permalink()) + ->set("TITLE", $item->get_title()) + ->set("AUTHOR", $item->get_author()) + ->set("DESCRIPTION", $item->get_description()) + ->set("DATE", $item->get_date('U')) + ; + $this->addOutputFields($loopResultRow, $item); + + $loopResult->addRow($loopResultRow); + } + + return $loopResult; + } +} diff --git a/core/lib/Thelia/Core/Template/Loop/Folder.php b/core/lib/Thelia/Core/Template/Loop/Folder.php new file mode 100644 index 00000000..3f5a730f --- /dev/null +++ b/core/lib/Thelia/Core/Template/Loop/Folder.php @@ -0,0 +1,307 @@ + + * + * {@inheritdoc} + * @method int[] getId() + * @method int getParent() + * @method int getContent() + * @method bool getCurrent() + * @method bool|string getVisible() + * @method int[] getExclude() + * @method string getTitle() + * @method string[] getOrder() + * @method bool getWithPrevNextInfo() + * @method bool getNeedCountChild() + * @method bool getNeedContentCount() + * @method bool getContentCountVisible() + */ +class Folder extends BaseI18nLoop implements PropelSearchLoopInterface, SearchLoopInterface +{ + use StandardI18nFieldsSearchTrait; + + protected $timestampable = true; + protected $versionable = true; + + /** + * @return ArgumentCollection + */ + protected function getArgDefinitions() + { + return new ArgumentCollection( + Argument::createIntListTypeArgument('id'), + Argument::createIntTypeArgument('parent'), + Argument::createIntTypeArgument('content'), + Argument::createBooleanTypeArgument('current'), + Argument::createBooleanTypeArgument('not_empty', 0), + Argument::createBooleanOrBothTypeArgument('visible', 1), + Argument::createAnyTypeArgument('title'), + Argument::createBooleanTypeArgument('need_count_child', true), + Argument::createBooleanTypeArgument('need_content_count', true), + new Argument( + 'order', + new TypeCollection( + new Type\EnumListType( + [ + 'id', 'id_reverse', + 'alpha', 'alpha_reverse', + 'manual', 'manual_reverse', + 'visible', 'visible_reverse', + 'random', + 'created', 'created_reverse', + 'updated', 'updated_reverse' + ] + ) + ), + 'manual' + ), + Argument::createIntListTypeArgument('exclude'), + Argument::createBooleanTypeArgument('with_prev_next_info', false), + Argument::createBooleanOrBothTypeArgument('content_count_visible', true) + ); + } + + /** + * @return array of available field to search in + */ + public function getSearchIn() + { + return $this->getStandardI18nSearchFields(); + } + + /** + * @param FolderQuery $search + * @param string $searchTerm + * @param array $searchIn + * @param string $searchCriteria + */ + public function doSearch(&$search, $searchTerm, $searchIn, $searchCriteria) + { + $search->_and(); + $this->addStandardI18nSearch($search, $searchTerm, $searchCriteria, $searchIn); + } + + public function buildModelCriteria() + { + $search = FolderQuery::create(); + + /* manage translations */ + $this->configureI18nProcessing( + $search, + [ 'TITLE', 'CHAPO', 'DESCRIPTION', 'POSTSCRIPTUM', 'META_TITLE', 'META_DESCRIPTION', 'META_KEYWORDS'] + ); + + $id = $this->getId(); + + if (!\is_null($id)) { + $search->filterById($id, Criteria::IN); + } + + $parent = $this->getParent(); + + if (null !== $parent) { + $search->filterByParent($parent); + } + + $current = $this->getCurrent(); + + if ($current === true) { + $search->filterById($this->getCurrentRequest()->get("folder_id")); + } elseif ($current === false) { + $search->filterById($this->getCurrentRequest()->get("folder_id"), Criteria::NOT_IN); + } + + $exclude = $this->getExclude(); + + if (!\is_null($exclude)) { + $search->filterById($exclude, Criteria::NOT_IN); + } + + $content = $this->getContent(); + + if (null !== $content) { + $obj = ContentQuery::create()->findPk($content); + + if ($obj) { + $search->filterByContent($obj, Criteria::IN); + } + } + + $title = $this->getTitle(); + + if (!\is_null($title)) { + $this->addSearchInI18nColumn($search, 'TITLE', Criteria::LIKE, "%".$title."%"); + } + + $visible = $this->getVisible(); + + if ($visible !== BooleanOrBothType::ANY) { + $search->filterByVisible($visible ? 1 : 0); + } + + $orders = $this->getOrder(); + + foreach ($orders as $order) { + switch ($order) { + case "id": + $search->orderById(Criteria::ASC); + break; + case "id_reverse": + $search->orderById(Criteria::DESC); + break; + case "alpha": + $search->addAscendingOrderByColumn('i18n_TITLE'); + break; + case "alpha_reverse": + $search->addDescendingOrderByColumn('i18n_TITLE'); + break; + case "manual_reverse": + $search->orderByPosition(Criteria::DESC); + break; + case "manual": + $search->orderByPosition(Criteria::ASC); + break; + case "visible": + $search->orderByVisible(Criteria::ASC); + break; + case "visible_reverse": + $search->orderByVisible(Criteria::DESC); + break; + case "random": + $search->clearOrderByColumns(); + $search->addAscendingOrderByColumn('RAND()'); + break(2); + 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; + } + } + + return $search; + } + + 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 */ + foreach ($loopResult->getResultDataCollection() as $folder) { + $loopResultRow = new LoopResultRow($folder); + + $loopResultRow + ->set("ID", $folder->getId()) + ->set("IS_TRANSLATED", $folder->getVirtualColumn('IS_TRANSLATED')) + ->set("LOCALE", $this->locale) + ->set("TITLE", $folder->getVirtualColumn('i18n_TITLE')) + ->set("CHAPO", $folder->getVirtualColumn('i18n_CHAPO')) + ->set("DESCRIPTION", $folder->getVirtualColumn('i18n_DESCRIPTION')) + ->set("POSTSCRIPTUM", $folder->getVirtualColumn('i18n_POSTSCRIPTUM')) + ->set("PARENT", $folder->getParent()) + ->set("ROOT", $folder->getRoot($folder->getId())) + ->set("URL", $this->getReturnUrl() ? $folder->getUrl($this->locale) : null) + ->set("META_TITLE", $folder->getVirtualColumn('i18n_META_TITLE')) + ->set("META_DESCRIPTION", $folder->getVirtualColumn('i18n_META_DESCRIPTION')) + ->set("META_KEYWORDS", $folder->getVirtualColumn('i18n_META_KEYWORDS')) + ->set("VISIBLE", $folder->getVisible() ? "1" : "0") + ->set("POSITION", $folder->getPosition()); + + + if ($needCountChild) { + $loopResultRow->set("CHILD_COUNT", $folder->countChild()); + } + + if ($needContentCount) { + $loopResultRow->set("CONTENT_COUNT", $folder->countAllContents($contentCountVisiblility)); + } + + $isBackendContext = $this->getBackendContext(); + + if ($this->getWithPrevNextInfo()) { + // Find previous and next folder + $previousQuery = FolderQuery::create() + ->filterByParent($folder->getParent()) + ->filterByPosition($folder->getPosition(), Criteria::LESS_THAN); + + if (! $isBackendContext) { + $previousQuery->filterByVisible(true); + } + + $previous = $previousQuery + ->orderByPosition(Criteria::DESC) + ->findOne(); + + $nextQuery = FolderQuery::create() + ->filterByParent($folder->getParent()) + ->filterByPosition($folder->getPosition(), Criteria::GREATER_THAN); + + if (! $isBackendContext) { + $nextQuery->filterByVisible(true); + } + + $next = $nextQuery + ->orderByPosition(Criteria::ASC) + ->findOne(); + + $loopResultRow + ->set("HAS_PREVIOUS", $previous != null ? 1 : 0) + ->set("HAS_NEXT", $next != null ? 1 : 0) + ->set("PREVIOUS", $previous != null ? $previous->getId() : -1) + ->set("NEXT", $next != null ? $next->getId() : -1); + } + + $this->addOutputFields($loopResultRow, $folder); + + $loopResult->addRow($loopResultRow); + } + + return $loopResult; + } +} diff --git a/core/lib/Thelia/Core/Template/Loop/FolderPath.php b/core/lib/Thelia/Core/Template/Loop/FolderPath.php new file mode 100644 index 00000000..fca72cd2 --- /dev/null +++ b/core/lib/Thelia/Core/Template/Loop/FolderPath.php @@ -0,0 +1,117 @@ + + * + * {@inheritdoc} + * @method int getFolder() + * @method bool|string getVisible() + * @method int getDepth() + * @method string[] getOrder() + */ +class FolderPath extends BaseI18nLoop implements ArraySearchLoopInterface +{ + /** + * @return \Thelia\Core\Template\Loop\Argument\ArgumentCollection + */ + protected function getArgDefinitions() + { + return new ArgumentCollection( + Argument::createIntTypeArgument('folder', null, true), + Argument::createIntTypeArgument('depth', PHP_INT_MAX), + Argument::createBooleanOrBothTypeArgument('visible', true, false) + ); + } + + public function buildArray() + { + $originalId = $currentId = $this->getFolder(); + $visible = $this->getVisible(); + $depth = $this->getDepth(); + + $results = array(); + + $ids = array(); + + do { + $search = FolderQuery::create(); + + $this->configureI18nProcessing($search, array('TITLE')); + + $search->filterById($currentId); + + if ($visible !== BooleanOrBothType::ANY) { + $search->filterByVisible($visible); + } + + $folder = $search->findOne(); + + if ($folder != null) { + $results[] = array( + "ID" => $folder->getId(), + "TITLE" => $folder->getVirtualColumn('i18n_TITLE'), + "URL" => $folder->getUrl($this->locale), + "LOCALE" => $this->locale, + ); + + $currentId = $folder->getParent(); + + if ($currentId > 0) { + // Prevent circular refererences + 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)", + $originalId, + $currentId + ) + ); + } + + $ids[] = $currentId; + } + } + } while ($folder != null && $currentId > 0 && --$depth > 0); + + // Reverse list and build the final result + return array_reverse($results); + } + + public function parseResults(LoopResult $loopResult) + { + foreach ($loopResult->getResultDataCollection() as $result) { + $loopResultRow = new LoopResultRow($result); + foreach ($result as $output => $outputValue) { + $loopResultRow->set($output, $outputValue); + } + + $this->addOutputFields($loopResultRow, $result); + $loopResult->addRow($loopResultRow); + } + + return $loopResult; + } +} diff --git a/core/lib/Thelia/Core/Template/Loop/FolderTree.php b/core/lib/Thelia/Core/Template/Loop/FolderTree.php new file mode 100644 index 00000000..6e388817 --- /dev/null +++ b/core/lib/Thelia/Core/Template/Loop/FolderTree.php @@ -0,0 +1,128 @@ + + * + * {@inheritdoc} + * @method int getFolder() + * @method int getDepth() + * @method bool|string getVisible() + * @method int[] getExclude() + */ +class FolderTree extends BaseI18nLoop implements ArraySearchLoopInterface +{ + /** + * @return ArgumentCollection + */ + protected function getArgDefinitions() + { + return new ArgumentCollection( + Argument::createIntTypeArgument('folder', null, true), + Argument::createIntTypeArgument('depth', PHP_INT_MAX), + Argument::createBooleanOrBothTypeArgument('visible', true, false), + Argument::createIntListTypeArgument('exclude', array()) + ); + } + + // changement de rubrique + protected function buildFolderTree($parent, $visible, $level, $maxLevel, $exclude, &$resultsList) + { + if ($level > $maxLevel) { + return; + } + + $search = FolderQuery::create(); + + $this->configureI18nProcessing($search, array( + 'TITLE' + )); + + $search->filterByParent($parent); + + if ($visible != BooleanOrBothType::ANY) { + $search->filterByVisible($visible); + } + + if ($exclude != null) { + $search->filterById($exclude, Criteria::NOT_IN); + } + + $search->orderByPosition(Criteria::ASC); + + $results = $search->find(); + + foreach ($results as $result) { + $resultsList[] = array( + "ID" => $result->getId(), + "TITLE" => $result->getVirtualColumn('i18n_TITLE'), + "PARENT" => $result->getParent(), + "URL" => $this->getReturnUrl() ? $result->getUrl($this->locale) : null, + "VISIBLE" => $result->getVisible() ? "1" : "0", + "LEVEL" => $level, + 'CHILD_COUNT' => $result->countChild(), + ); + + $this->buildFolderTree($result->getId(), $visible, 1 + $level, $maxLevel, $exclude, $resultsList); + } + } + + public function parseResults(LoopResult $loopResult) + { + foreach ($loopResult->getResultDataCollection() as $result) { + $loopResultRow = new LoopResultRow($result); + foreach ($result as $output => $outputValue) { + $loopResultRow->set($output, $outputValue); + } + + $this->addOutputFields($loopResultRow, $result); + $loopResult->addRow($loopResultRow); + } + + return $loopResult; + } + + public function buildArray() + { + $id = $this->getFolder(); + $depth = $this->getDepth(); + $visible = $this->getVisible(); + $exclude = $this->getExclude(); + + $resultsList = array(); + + $this->buildFolderTree($id, $visible, 0, $depth, $exclude, $resultsList); + + return $resultsList; + } +} diff --git a/core/lib/Thelia/Core/Template/Loop/Hook.php b/core/lib/Thelia/Core/Template/Loop/Hook.php new file mode 100644 index 00000000..c522744c --- /dev/null +++ b/core/lib/Thelia/Core/Template/Loop/Hook.php @@ -0,0 +1,197 @@ + + * + * {@inheritdoc} + * @method int[] getId() + * @method string[] getCode() + * @method string[] getHook_type() + * @method bool|string getActive() + * @method int[] getExclude() + * @method string[] getOrder() + */ +class Hook extends BaseI18nLoop implements PropelSearchLoopInterface +{ + protected $timestampable = true; + + /** + * {@inheritdoc} + */ + protected function getArgDefinitions() + { + return new ArgumentCollection( + Argument::createIntListTypeArgument('id'), + new Argument( + 'code', + new Type\TypeCollection( + new Type\AlphaNumStringListType() + ) + ), + new Argument( + 'hook_type', + new Type\TypeCollection( + new Type\EnumListType([ + TemplateDefinition::FRONT_OFFICE, + TemplateDefinition::BACK_OFFICE, + TemplateDefinition::EMAIL, + TemplateDefinition::PDF, + ]) + ) + ), + new Argument( + 'order', + new TypeCollection( + new Type\EnumListType(['id', 'id_reverse', 'code', 'code_reverse', 'alpha', 'alpha_reverse', + 'manual', 'manual_reverse', 'enabled', 'enabled_reverse', 'native', 'native_reverse' ]) + ), + 'id' + ), + Argument::createIntListTypeArgument('exclude'), + Argument::createBooleanOrBothTypeArgument('active', Type\BooleanOrBothType::ANY) + ); + } + + /** + * {@inheritdoc} + */ + public function buildModelCriteria() + { + $search = HookQuery::create(); + + /* manage translations */ + $this->configureI18nProcessing($search, ['TITLE', 'CHAPO', 'DESCRIPTION']); + + $id = $this->getId(); + + if (null !== $id) { + $search->filterById($id, Criteria::IN); + } + + $code = $this->getCode(); + if (null !== $code) { + $search->filterByCode($code, Criteria::IN); + } + + $hookType = $this->getHook_type(); + if (null !== $hookType) { + $search->filterByType($hookType, Criteria::IN); + } + + $exclude = $this->getExclude(); + if (!\is_null($exclude)) { + $search->filterById($exclude, Criteria::NOT_IN); + } + + $active = $this->getActive(); + if ($active !== Type\BooleanOrBothType::ANY) { + $search->filterByActivate($active ? 1 : 0, Criteria::EQUAL); + } + + $orders = $this->getOrder(); + + foreach ($orders as $order) { + switch ($order) { + case "id": + $search->orderById(Criteria::ASC); + break; + case "id_reverse": + $search->orderById(Criteria::DESC); + break; + case "alpha": + $search->addAscendingOrderByColumn('i18n_TITLE'); + break; + case "alpha_reverse": + $search->addDescendingOrderByColumn('i18n_TITLE'); + break; + case "code": + $search->orderByCode(Criteria::ASC); + break; + case "code_reverse": + $search->orderByCode(Criteria::DESC); + break; + case "manual": + $search->orderByPosition(Criteria::ASC); + break; + case "manual_reverse": + $search->orderByPosition(Criteria::DESC); + break; + case "enabled": + $search->orderByActivate(Criteria::ASC); + break; + case "enabled_reverse": + $search->orderByActivate(Criteria::DESC); + break; + case "native": + $search->orderByNative(Criteria::ASC); + break; + case "native_reverse": + $search->orderByNative(Criteria::DESC); + break; + } + } + + return $search; + } + + + /** + * {@inheritdoc} + */ + public function parseResults(LoopResult $loopResult) + { + /** @var \Thelia\Model\Hook $hook */ + foreach ($loopResult->getResultDataCollection() as $hook) { + if ($this->getBackendContext()) { + $loopResultRow = new LoopResultRow($hook); + + $loopResultRow + ->set("ID", $hook->getId()) + ->set("IS_TRANSLATED", $hook->getVirtualColumn('IS_TRANSLATED')) + ->set("LOCALE", $this->locale) + ->set("TITLE", $hook->getVirtualColumn('i18n_TITLE')) + ->set("CHAPO", $hook->getVirtualColumn('i18n_CHAPO')) + ->set("DESCRIPTION", $hook->getVirtualColumn('i18n_DESCRIPTION')) + ->set("CODE", $hook->getCode()) + ->set("TYPE", $hook->getType()) + ->set("NATIVE", $hook->getNative()) + ->set("ACTIVE", $hook->getActivate()) + ->set("BY_MODULE", $hook->getByModule()) + ->set("BLOCK", $hook->getBlock()) + ->set("POSITION", $hook->getPosition()) + ; + + $this->addOutputFields($loopResultRow, $hook); + $loopResult->addRow($loopResultRow); + } + } + + return $loopResult; + } +} diff --git a/core/lib/Thelia/Core/Template/Loop/Image.php b/core/lib/Thelia/Core/Template/Loop/Image.php new file mode 100644 index 00000000..480c8ddd --- /dev/null +++ b/core/lib/Thelia/Core/Template/Loop/Image.php @@ -0,0 +1,432 @@ + + * + * {@inheritdoc} + * @method int[] getId() + * @method bool|string getVisible() + * @method int[] getExclude() + * @method int getWidth() + * @method int getHeight() + * @method int getRotation() + * @method string getBackgroundColor() + * @method int getQuality() + * @method string getEffects() + * @method int getCategory() + * @method int getProduct() + * @method int getFolder() + * @method int getContent() + * @method string getSource() + * @method int getSourceId() + * @method string getQueryNamespace() + * @method bool getAllowZoom() + * @method bool getIgnoreProcessingErrors() + * @method string getResizeMode() + * @method string[] getOrder() + */ +class Image extends BaseI18nLoop implements PropelSearchLoopInterface +{ + protected $objectType; + protected $objectId; + + protected $timestampable = true; + + /** + * @var array Possible standard image sources + */ + protected $possible_sources = array('category', 'product', 'folder', 'content', 'module', 'brand'); + + /** + * @return \Thelia\Core\Template\Loop\Argument\ArgumentCollection + */ + protected function getArgDefinitions() + { + $collection = new ArgumentCollection( + Argument::createIntListTypeArgument('id'), + Argument::createIntListTypeArgument('exclude'), + Argument::createBooleanOrBothTypeArgument('visible', 1), + new Argument( + 'order', + new TypeCollection( + new EnumListType(array('alpha', 'alpha-reverse', 'manual', 'manual-reverse', 'random')) + ), + 'manual' + ), + Argument::createIntTypeArgument('width'), + Argument::createIntTypeArgument('height'), + Argument::createIntTypeArgument('rotation', 0), + Argument::createAnyTypeArgument('background_color'), + Argument::createIntTypeArgument('quality'), + new Argument( + 'resize_mode', + new TypeCollection( + new EnumType(array('crop', 'borders', 'none')) + ), + 'none' + ), + Argument::createAnyTypeArgument('effects'), + Argument::createIntTypeArgument('category'), + Argument::createIntTypeArgument('product'), + Argument::createIntTypeArgument('folder'), + Argument::createIntTypeArgument('content'), + Argument::createAnyTypeArgument('source'), + Argument::createIntTypeArgument('source_id'), + Argument::createBooleanTypeArgument('force_return', true), + Argument::createBooleanTypeArgument('ignore_processing_errors', true), + Argument::createAnyTypeArgument('query_namespace', 'Thelia\\Model'), + Argument::createBooleanTypeArgument('allow_zoom', false), + Argument::createBooleanTypeArgument('base64', false), + Argument::createBooleanTypeArgument('with_prev_next_info', false) + ); + + // Add possible image sources + foreach ($this->possible_sources as $source) { + $collection->addArgument(Argument::createIntTypeArgument($source)); + } + + return $collection; + } + + /** + * Dynamically create the search query, and set the proper filter and order + * + * @param string $source a valid source identifier (@see $possible_sources) + * @param int $object_id the source object ID + * @return ModelCriteria the propel Query object + */ + protected function createSearchQuery($source, $object_id) + { + $object = ucfirst($source); + + $ns = $this->getQueryNamespace(); + + if ('\\' !== $ns[0]) { + $ns = '\\'.$ns; + } + + $queryClass = sprintf("%s\\%sImageQuery", $ns, $object); + $filterMethod = sprintf("filterBy%sId", $object); + + // xxxImageQuery::create() + $method = new \ReflectionMethod($queryClass, 'create'); + $search = $method->invoke(null); // Static ! + + // $query->filterByXXX(id) + if (! \is_null($object_id)) { + $method = new \ReflectionMethod($queryClass, $filterMethod); + $method->invoke($search, $object_id); + } + + $orders = $this->getOrder(); + + // Results ordering + foreach ($orders as $order) { + switch ($order) { + case "alpha": + $search->addAscendingOrderByColumn('i18n_TITLE'); + break; + case "alpha-reverse": + $search->addDescendingOrderByColumn('i18n_TITLE'); + break; + case "manual-reverse": + $search->orderByPosition(Criteria::DESC); + break; + case "manual": + $search->orderByPosition(Criteria::ASC); + break; + case "random": + $search->clearOrderByColumns(); + $search->addAscendingOrderByColumn('RAND()'); + break(2); + break; + } + } + + return $search; + } + + /** + * Dynamically create the search query, and set the proper filter and order + * + * @param string $objectType (returned) the a valid source identifier (@see $possible_sources) + * @param string $objectId (returned) the ID of the source object + * @return ModelCriteria the propel Query object + */ + protected function getSearchQuery(&$objectType, &$objectId) + { + $search = null; + + // Check form source="product" source_id="123" style arguments + $source = $this->getSource(); + + if (! \is_null($source)) { + $sourceId = $this->getSourceId(); + $id = $this->getId(); + + if (\is_null($sourceId) && \is_null($id)) { + throw new \InvalidArgumentException( + "If 'source' argument is specified, 'id' or 'source_id' argument should be specified" + ); + } + + $search = $this->createSearchQuery($source, $sourceId); + + $objectType = $source; + $objectId = $sourceId; + } else { + // Check for product="id" folder="id", etc. style arguments + foreach ($this->possible_sources as $source) { + $argValue = $this->getArgValue($source); + + if (! empty($argValue)) { + $argValue = \intval($argValue); + + $search = $this->createSearchQuery($source, $argValue); + + $objectType = $source; + $objectId = $argValue; + + break; + } + } + } + + if ($search == null) { + throw new \InvalidArgumentException( + sprintf("Unable to find image source. Valid sources are %s", implode(',', $this->possible_sources)) + ); + } + + return $search; + } + + public function buildModelCriteria() + { + // Select the proper query to use, and get the object type + $this->objectType = $this->objectId = null; + + /** @var ProductDocumentQuery $search */ + $search = $this->getSearchQuery($this->objectType, $this->objectId); + + /* manage translations */ + $this->configureI18nProcessing($search); + + $id = $this->getId(); + + if (! \is_null($id)) { + $search->filterById($id, Criteria::IN); + } + + $exclude = $this->getExclude(); + if (!\is_null($exclude)) { + $search->filterById($exclude, Criteria::NOT_IN); + } + + $visible = $this->getVisible(); + if ($visible !== BooleanOrBothType::ANY) { + $search->filterByVisible($visible ? 1 : 0); + } + + return $search; + } + + public function parseResults(LoopResult $loopResult) + { + // Create image processing event + $event = new ImageEvent(); + + // Prepare tranformations + $width = $this->getWidth(); + $height = $this->getHeight(); + $rotation = $this->getRotation(); + $background_color = $this->getBackgroundColor(); + $quality = $this->getQuality(); + $effects = $this->getEffects(); + + $event->setAllowZoom($this->getAllowZoom()); + + if (! \is_null($effects)) { + $effects = explode(',', $effects); + } + + switch ($this->getResizeMode()) { + case 'crop': + $resizeMode = \Thelia\Action\Image::EXACT_RATIO_WITH_CROP; + break; + + case 'borders': + $resizeMode = \Thelia\Action\Image::EXACT_RATIO_WITH_BORDERS; + break; + + case 'none': + default: + $resizeMode = \Thelia\Action\Image::KEEP_IMAGE_RATIO; + } + + $baseSourceFilePath = ConfigQuery::read('images_library_path'); + if ($baseSourceFilePath === null) { + $baseSourceFilePath = THELIA_LOCAL_DIR . 'media' . DS . 'images'; + } else { + $baseSourceFilePath = THELIA_ROOT . $baseSourceFilePath; + } + + /** @var ProductImage $result */ + foreach ($loopResult->getResultDataCollection() as $result) { + // Setup required transformations + if (! \is_null($width)) { + $event->setWidth($width); + } + if (! \is_null($height)) { + $event->setHeight($height); + } + $event->setResizeMode($resizeMode); + if (! \is_null($rotation)) { + $event->setRotation($rotation); + } + if (! \is_null($background_color)) { + $event->setBackgroundColor($background_color); + } + if (! \is_null($quality)) { + $event->setQuality($quality); + } + if (! \is_null($effects)) { + $event->setEffects($effects); + } + + // Put source image file path + $sourceFilePath = sprintf( + '%s/%s/%s', + $baseSourceFilePath, + $this->objectType, + $result->getFile() + ); + + $event->setSourceFilepath($sourceFilePath); + $event->setCacheSubdirectory($this->objectType); + + $loopResultRow = new LoopResultRow($result); + + $loopResultRow + ->set("ID", $result->getId()) + ->set("LOCALE", $this->locale) + ->set("ORIGINAL_IMAGE_PATH", $sourceFilePath) + ->set("TITLE", $result->getVirtualColumn('i18n_TITLE')) + ->set("CHAPO", $result->getVirtualColumn('i18n_CHAPO')) + ->set("DESCRIPTION", $result->getVirtualColumn('i18n_DESCRIPTION')) + ->set("POSTSCRIPTUM", $result->getVirtualColumn('i18n_POSTSCRIPTUM')) + ->set("VISIBLE", $result->getVisible()) + ->set("POSITION", $result->getPosition()) + ->set("OBJECT_TYPE", $this->objectType) + ->set("OBJECT_ID", $this->objectId) + ; + + $addRow = true; + + $returnErroredImages = $this->getBackendContext() || ! $this->getIgnoreProcessingErrors(); + + try { + // Dispatch image processing event + $this->dispatcher->dispatch(TheliaEvents::IMAGE_PROCESS, $event); + + $loopResultRow + ->set("IMAGE_URL", $event->getFileUrl()) + ->set("ORIGINAL_IMAGE_URL", $event->getOriginalFileUrl()) + ->set("IMAGE_PATH", $event->getCacheFilepath()) + ->set("PROCESSING_ERROR", false) + ; + + + if ($this->getBase64()) { + $loopResultRow->set("IMAGE_BASE64", $this->toBase64($event->getCacheFilepath())); + } + } catch (\Exception $ex) { + // Ignore the result and log an error + Tlog::getInstance()->addError(sprintf("Failed to process image in image loop: %s", $ex->getMessage())); + + if ($returnErroredImages) { + $loopResultRow + ->set("IMAGE_URL", '') + ->set("ORIGINAL_IMAGE_URL", '') + ->set("IMAGE_PATH", '') + ->set("PROCESSING_ERROR", true) + ; + } else { + $addRow = false; + } + } + $isBackendContext = $this->getBackendContext(); + if ($this->getWithPrevNextInfo()) { + $previousQuery = $this->getSearchQuery($this->objectType, $this->objectId) + ->filterByPosition($result->getPosition(), Criteria::LESS_THAN); + if (! $isBackendContext) { + $previousQuery->filterByVisible(true); + } + $previous = $previousQuery + ->orderByPosition(Criteria::DESC) + ->findOne(); + $nextQuery = $this->getSearchQuery($this->objectType, $this->objectId) + ->filterByPosition($result->getPosition(), Criteria::GREATER_THAN); + if (! $isBackendContext) { + $nextQuery->filterByVisible(true); + } + $next = $nextQuery + ->orderByPosition(Criteria::ASC) + ->findOne(); + $loopResultRow + ->set("HAS_PREVIOUS", $previous != null ? 1 : 0) + ->set("HAS_NEXT", $next != null ? 1 : 0) + ->set("PREVIOUS", $previous != null ? $previous->getId() : -1) + ->set("NEXT", $next != null ? $next->getId() : -1); + } + + if ($addRow) { + $this->addOutputFields($loopResultRow, $result); + + $loopResult->addRow($loopResultRow); + } + } + + return $loopResult; + } + + private function toBase64($path) + { + $imgData = base64_encode(file_get_contents($path)); + return $src = 'data: '.mime_content_type($path).';base64,'.$imgData; + } +} diff --git a/core/lib/Thelia/Core/Template/Loop/Import.php b/core/lib/Thelia/Core/Template/Loop/Import.php new file mode 100644 index 00000000..4a0cb2ef --- /dev/null +++ b/core/lib/Thelia/Core/Template/Loop/Import.php @@ -0,0 +1,41 @@ + + */ +class Import extends ImportExportType +{ + protected function getBaseUrl() + { + return $this->container->getParameter("import.base_url"); + } + + /** + * @return ImportQuery + */ + protected function getQueryModel() + { + return ImportQuery::create(); + } + + protected function getCategoryName() + { + return "ImportCategoryId"; + } +} diff --git a/core/lib/Thelia/Core/Template/Loop/ImportCategory.php b/core/lib/Thelia/Core/Template/Loop/ImportCategory.php new file mode 100644 index 00000000..3a9a86fc --- /dev/null +++ b/core/lib/Thelia/Core/Template/Loop/ImportCategory.php @@ -0,0 +1,31 @@ + + */ +class ImportCategory extends ImportExportCategory +{ + /** + * @return ImportCategoryQuery + */ + protected function getQueryModel() + { + return ImportCategoryQuery::create(); + } +} diff --git a/core/lib/Thelia/Core/Template/Loop/ImportExportCategory.php b/core/lib/Thelia/Core/Template/Loop/ImportExportCategory.php new file mode 100644 index 00000000..f9a7b060 --- /dev/null +++ b/core/lib/Thelia/Core/Template/Loop/ImportExportCategory.php @@ -0,0 +1,142 @@ + + * + * {@inheritdoc} + * @method null|int[] getId() + * @method null|string[] getRef() + * @method string[] getOrder() + */ +abstract class ImportExportCategory extends BaseI18nLoop implements PropelSearchLoopInterface +{ + protected $timestampable = true; + + /** + * @param LoopResult $loopResult + * @return LoopResult + * @throws \Propel\Runtime\Exception\PropelException + */ + public function parseResults(LoopResult $loopResult) + { + /** @var \Thelia\Model\ExportCategory|\Thelia\Model\ImportCategory $category */ + foreach ($loopResult->getResultDataCollection() as $category) { + $loopResultRow = new LoopResultRow($category); + + $loopResultRow + ->set("ID", $category->getId()) + ->set("REF", $category->getRef()) + ->set("TITLE", $category->getVirtualColumn("i18n_TITLE")) + ->set("POSITION", $category->getPosition()) + ; + + $this->addOutputFields($loopResultRow, $category); + $loopResult->addRow($loopResultRow); + } + + return $loopResult; + } + + /** + * this method returns a Propel ModelCriteria + * + * @return \Propel\Runtime\ActiveQuery\ModelCriteria + */ + public function buildModelCriteria() + { + /** @var ImportCategoryQuery|ExportCategoryQuery $query */ + $query = $this->getQueryModel(); + + $this->configureI18nProcessing($query, array('TITLE')); + + if (null !== $ids = $this->getId()) { + $query->filterById($ids, Criteria::IN); + } + + if (null !== $refs = $this->getRef()) { + $query->filterByRef($refs, Criteria::IN); + } + + if (null !== $orders = $this->getOrder()) { + foreach ($orders as $order) { + switch ($order) { + case "id": + $query->orderById(); + break; + case "id_reverse": + $query->orderById(Criteria::DESC); + break; + case "ref": + $query->orderByRef(); + break; + case "ref_reverse": + $query->orderByRef(Criteria::DESC); + break; + case "alpha": + $query->addAscendingOrderByColumn("i18n_TITLE"); + break; + case "alpha_reverse": + $query->addDescendingOrderByColumn("i18n_TITLE"); + break; + case "manual": + $query->orderByPosition(); + break; + case "manual_reverse": + $query->orderByPosition(Criteria::DESC); + break; + } + } + } + + return $query; + } + + /** + * @return \Thelia\Core\Template\Loop\Argument\ArgumentCollection + */ + protected function getArgDefinitions() + { + return new ArgumentCollection( + Argument::createIntListTypeArgument('id'), + Argument::createAnyListTypeArgument('ref'), + new Argument( + "order", + new TypeCollection( + new EnumListType(["id", "id_reverse", "ref", "ref_reverse", "alpha", "alpha_reverse", "manual", "manual_reverse"]) + ), + "manual" + ) + ); + } + + /** + * @return ImportCategoryQuery|ExportCategoryQuery + */ + abstract protected function getQueryModel(); +} diff --git a/core/lib/Thelia/Core/Template/Loop/ImportExportType.php b/core/lib/Thelia/Core/Template/Loop/ImportExportType.php new file mode 100644 index 00000000..fe28897d --- /dev/null +++ b/core/lib/Thelia/Core/Template/Loop/ImportExportType.php @@ -0,0 +1,200 @@ + + * + * {@inheritdoc} + * @method null|int[] getId() + * @method null|string[] getRef() + * @method null|int[] getCategory() + * @method string[] getOrder() + */ +abstract class ImportExportType extends BaseI18nLoop implements PropelSearchLoopInterface +{ + const DEFAULT_ORDER = "manual"; + + protected $timestampable = true; + + /** + * @param LoopResult $loopResult + * @return LoopResult + * @throws \Propel\Runtime\Exception\PropelException + */ + public function parseResults(LoopResult $loopResult) + { + /** @var ImportModel|\Thelia\Model\Export $type */ + foreach ($loopResult->getResultDataCollection() as $type) { + $loopResultRow = new LoopResultRow($type); + + $url = URL::getInstance()->absoluteUrl( + $this->getBaseUrl() . "/" . $type->getId() + ); + + try { + $loopResultRow + ->set("HANDLE_CLASS", $type->getHandleClass()) + ->set("ID", $type->getId()) + ->set("REF", $type->getRef()) + ->set("TITLE", $type->getVirtualColumn("i18n_TITLE")) + ->set("DESCRIPTION", $type->getVirtualColumn("i18n_DESCRIPTION")) + ->set("URL", $url) + ->set("POSITION", $type->getPosition()) + ->set("CATEGORY_ID", $type->getByName($this->getCategoryName())) + ; + } catch (\Exception $e) { + Tlog::getInstance()->error($e->getMessage()); + } + + $this->addOutputFields($loopResultRow, $type); + $loopResult->addRow($loopResultRow); + } + + return $loopResult; + } + + /** + * this method returns a Propel ModelCriteria + * + * @return \Propel\Runtime\ActiveQuery\ModelCriteria + */ + public function buildModelCriteria() + { + /** @var \Thelia\Model\ImportQuery|\Thelia\Model\ExportQUery $query */ + $query = $this->getQueryModel(); + + $this->configureI18nProcessing($query, array('TITLE', 'DESCRIPTION')); + + if (null !== $ids = $this->getId()) { + $query->filterById($ids); + } + + if (null !== $refs = $this->getRef()) { + $query->filterByRef($refs); + } + + if (null !== $categories = $this->getCategory()) { + $query->filterBy($this->getCategoryName(), $categories, Criteria::IN); + } + + if (null !== $orders = $this->getOrder()) { + foreach ($orders as $order) { + switch ($order) { + case "id": + $query->orderById(); + break; + case "id_reverse": + $query->orderById(Criteria::DESC); + break; + case "ref": + $query->orderByRef(); + break; + case "ref_reverse": + $query->orderByRef(Criteria::DESC); + break; + case "alpha": + $query->addAscendingOrderByColumn("i18n_TITLE"); + break; + case "alpha_reverse": + $query->addDescendingOrderByColumn("i18n_TITLE"); + break; + case "manual": + $query->orderByPosition(); + break; + case "manual_reverse": + $query->orderByPosition(Criteria::DESC); + break; + } + } + } + + return $query; + } + + /** + * Definition of loop arguments + * + * example : + * + * public function getArgDefinitions() + * { + * return new ArgumentCollection( + * + * Argument::createIntListTypeArgument('id'), + * new Argument( + * 'ref', + * new TypeCollection( + * new Type\AlphaNumStringListType() + * ) + * ), + * Argument::createIntListTypeArgument('category'), + * Argument::createBooleanTypeArgument('new'), + * ... + * ); + * } + * + * @return \Thelia\Core\Template\Loop\Argument\ArgumentCollection + */ + protected function getArgDefinitions() + { + return new ArgumentCollection( + Argument::createIntListTypeArgument('id'), + Argument::createIntListTypeArgument('category'), + Argument::createAnyListTypeArgument('ref'), + new Argument( + "order", + new TypeCollection( + new EnumListType(static::getAllowedOrders()) + ), + static::DEFAULT_ORDER + ) + ); + } + + public static function getAllowedOrders() + { + return ["id", "id_reverse", "ref", "ref_reverse", "alpha", "alpha_reverse", "manual", "manual_reverse"]; + } + + /** + * @return string + */ + abstract protected function getBaseUrl(); + + /** + * @return \Thelia\Model\ImportQuery|\Thelia\Model\ExportQUery + */ + abstract protected function getQueryModel(); + + /** + * @return string + */ + abstract protected function getCategoryName(); +} diff --git a/core/lib/Thelia/Core/Template/Loop/Lang.php b/core/lib/Thelia/Core/Template/Loop/Lang.php new file mode 100644 index 00000000..41724755 --- /dev/null +++ b/core/lib/Thelia/Core/Template/Loop/Lang.php @@ -0,0 +1,172 @@ + + * + * {@inheritdoc} + * @method int[] getId() + * @method string[] getCode() + * @method string[] getLocale() + * @method int[] getExclude() + * @method bool getActive() + * @method bool getVisible() + * @method bool getDefaultOnly() + * @method bool getExcludeDefault() + * @method string[] getOrder() + */ +class Lang extends BaseLoop implements PropelSearchLoopInterface +{ + protected $timestampable = true; + + /** + * @return ArgumentCollection + */ + protected function getArgDefinitions() + { + return new ArgumentCollection( + Argument::createIntListTypeArgument('id'), + Argument::createAnyListTypeArgument('code'), + Argument::createAnyListTypeArgument('locale'), + Argument::createIntListTypeArgument('exclude'), + Argument::createBooleanOrBothTypeArgument('active', true), + Argument::createBooleanOrBothTypeArgument('visible', true), + Argument::createBooleanTypeArgument('default_only', false), + Argument::createBooleanTypeArgument('exclude_default', false), + Argument::createEnumListTypeArgument( + 'order', + [ + 'id', 'id_reverse', + 'alpha', 'alpha_reverse', + 'position', 'position_reverse' + ], + 'position' + ) + ); + } + + public function buildModelCriteria() + { + $search = LangQuery::create(); + + if (null !== $id = $this->getId()) { + $search->filterById($id, Criteria::IN); + } + + if (null !== $code = $this->getCode()) { + $search->filterByCode($code, Criteria::IN); + } + + if (null !== $locale = $this->getLocale()) { + $search->filterByLocale($locale, Criteria::IN); + } + + if (!$this->getBackendContext() && Type\BooleanOrBothType::ANY !== $visible = $this->getVisible()) { + $search->filterByVisible($visible); + } + + if (Type\BooleanOrBothType::ANY !== $active = $this->getActive()) { + $search->filterByActive($active); + } + + if ($this->getDefaultOnly()) { + $search->filterByByDefault(true); + } + + if ($this->getExcludeDefault()) { + $search->filterByByDefault(false); + } + + if (null !== $exclude = $this->getExclude()) { + $search->filterById($exclude, Criteria::NOT_IN); + } + + $orders = $this->getOrder(); + + foreach ($orders as $order) { + switch ($order) { + case "id": + $search->orderById(Criteria::ASC); + break; + case "id_reverse": + $search->orderById(Criteria::DESC); + break; + case "alpha": + $search->orderByTitle(Criteria::ASC); + break; + case "alpha_reverse": + $search->orderByTitle(Criteria::DESC); + break; + case "position": + $search->orderByPosition(Criteria::ASC); + break; + case "position_reverse": + $search->orderByPosition(Criteria::DESC); + break; + } + } + + return $search; + } + + public function parseResults(LoopResult $loopResult) + { + /** @var \Thelia\Model\Lang $result */ + foreach ($loopResult->getResultDataCollection() as $result) { + $loopResultRow = new LoopResultRow($result); + + $loopResultRow + ->set("ID", $result->getId()) + ->set("TITLE", $result->getTitle()) + ->set("CODE", $result->getCode()) + ->set("LOCALE", $result->getLocale()) + ->set("URL", $result->getUrl()) + ->set("ACTIVE", $result->getActive()) + ->set("VISIBLE", $result->getVisible()) + ->set("IS_DEFAULT", $result->getByDefault()) + ->set("DATE_FORMAT", $result->getDateFormat()) + ->set("TIME_FORMAT", $result->getTimeFormat()) + ->set("DECIMAL_SEPARATOR", $result->getDecimalSeparator()) + ->set("THOUSANDS_SEPARATOR", $result->getThousandsSeparator()) + ->set("DECIMAL_COUNT", $result->getDecimals()) + ->set("POSITION", $result->getPosition()) + ; + + $this->addOutputFields($loopResultRow, $result); + + $loopResult->addRow($loopResultRow); + } + + return $loopResult; + } +} diff --git a/core/lib/Thelia/Core/Template/Loop/Message.php b/core/lib/Thelia/Core/Template/Loop/Message.php new file mode 100644 index 00000000..11b3219f --- /dev/null +++ b/core/lib/Thelia/Core/Template/Loop/Message.php @@ -0,0 +1,127 @@ + + * + * {@inheritdoc} + * @method int getId() + * @method int[] getExclude() + * @method string getVariable() + * @method bool|string getHidden() + * @method bool|string getSecured() + */ +class Message extends BaseI18nLoop implements PropelSearchLoopInterface +{ + protected $timestampable = true; + + /** + * @return ArgumentCollection + */ + protected function getArgDefinitions() + { + return new ArgumentCollection( + Argument::createIntTypeArgument('id'), + Argument::createIntListTypeArgument('exclude'), + Argument::createAnyTypeArgument('variable'), + Argument::createBooleanOrBothTypeArgument('hidden'), + Argument::createBooleanOrBothTypeArgument('secured') + ); + } + + public function buildModelCriteria() + { + $id = $this->getId(); + $name = $this->getVariable(); + $secured = $this->getSecured(); + $exclude = $this->getExclude(); + + $search = MessageQuery::create(); + + $this->configureI18nProcessing( + $search, + array( + 'TITLE', + 'SUBJECT', + 'TEXT_MESSAGE', + 'HTML_MESSAGE' + ) + ); + + if (! \is_null($id)) { + $search->filterById($id); + } + + if (! \is_null($name)) { + $search->filterByName($name); + } + + if (! \is_null($exclude)) { + $search->filterById($exclude, Criteria::NOT_IN); + } + + if (! \is_null($secured) && $secured != BooleanOrBothType::ANY) { + $search->filterBySecured($secured ? 1 : 0); + } + + $search->orderByName(Criteria::ASC); + + return $search; + } + + public function parseResults(LoopResult $loopResult) + { + /** @var MessageModel $result */ + foreach ($loopResult->getResultDataCollection() as $result) { + $loopResultRow = new LoopResultRow($result); + + $loopResultRow + ->set("ID", $result->getId()) + ->set("NAME", $result->getName()) + ->set("IS_TRANSLATED", $result->getVirtualColumn('IS_TRANSLATED')) + ->set("LOCALE", $this->locale) + ->set("TITLE", $result->getVirtualColumn('i18n_TITLE')) + ->set("SUBJECT", $result->getVirtualColumn('i18n_SUBJECT')) + ->set("TEXT_MESSAGE", $result->getVirtualColumn('i18n_TEXT_MESSAGE')) + ->set("HTML_MESSAGE", $result->getVirtualColumn('i18n_HTML_MESSAGE')) + ->set("SECURED", $result->getSecured()) + ; + $this->addOutputFields($loopResultRow, $result); + + $loopResult->addRow($loopResultRow); + } + + return $loopResult; + } +} diff --git a/core/lib/Thelia/Core/Template/Loop/Module.php b/core/lib/Thelia/Core/Template/Loop/Module.php new file mode 100644 index 00000000..f2ecf2d7 --- /dev/null +++ b/core/lib/Thelia/Core/Template/Loop/Module.php @@ -0,0 +1,355 @@ + + * + * {@inheritdoc} + * @method int[] getId() + * @method int getProfile() + * @method int[] getArea() + * @method string[] getCode() + * @method string[] getModuleType() + * @method string[] getModuleCategory() + * @method int[] getExclude() + * @method bool|string getActive() + * @method string[] getOrder() + * @method bool|string getMandatory() + * @method bool|string getHidden() + */ +class Module extends BaseI18nLoop implements PropelSearchLoopInterface +{ + protected $timestampable = true; + + /** + * @return ArgumentCollection + */ + protected function getArgDefinitions() + { + return new ArgumentCollection( + Argument::createIntListTypeArgument('id'), + Argument::createIntTypeArgument('profile'), + Argument::createIntListTypeArgument('area'), + new Argument( + 'code', + new Type\TypeCollection( + new Type\AlphaNumStringListType() + ) + ), + new Argument( + 'module_type', + new Type\TypeCollection( + new Type\EnumListType([ + BaseModule::CLASSIC_MODULE_TYPE, + BaseModule::DELIVERY_MODULE_TYPE, + BaseModule::PAYMENT_MODULE_TYPE, + ]) + ) + ), + new Argument( + 'module_category', + new Type\TypeCollection( + new Type\EnumListType(explode(',', BaseModule::MODULE_CATEGORIES)) + ) + ), + new Argument( + 'order', + new TypeCollection( + new Type\EnumListType([ + 'id', + 'id_reverse', + 'code', + 'code_reverse', + 'title', + 'title_reverse', + 'type', + 'type_reverse', + 'manual', + 'manual_reverse', + 'enabled', + 'enabled_reverse' + ]) + ), + 'manual' + ), + Argument::createIntListTypeArgument('exclude'), + Argument::createBooleanOrBothTypeArgument('active', Type\BooleanOrBothType::ANY), + Argument::createBooleanOrBothTypeArgument('hidden', Type\BooleanOrBothType::ANY), + Argument::createBooleanOrBothTypeArgument('mandatory', Type\BooleanOrBothType::ANY) + ); + } + + public function buildModelCriteria() + { + $search = ModuleQuery::create(); + + /* manage translations */ + $this->configureI18nProcessing($search); + + $id = $this->getId(); + + if (null !== $id) { + $search->filterById($id, Criteria::IN); + } + + $profile = $this->getProfile(); + + if (null !== $profile) { + $search->leftJoinProfileModule('profile_module') + ->addJoinCondition('profile_module', 'profile_module.PROFILE_ID=?', $profile, null, \PDO::PARAM_INT) + ->withColumn('profile_module.access', 'access'); + } + + + $area = $this->getArea(); + + if (null !== $area) { + $search + ->useAreaDeliveryModuleQuery() + ->filterByAreaId($area, Criteria::IN) + ->endUse(); + } + + $code = $this->getCode(); + + if (null !== $code) { + $search->filterByCode($code, Criteria::IN); + } + + $moduleType = $this->getModuleType(); + + if (null !== $moduleType) { + $search->filterByType($moduleType, Criteria::IN); + } + + $moduleCategory = $this->getModuleCategory(); + + if (null !== $moduleCategory) { + $search->filterByCategory($moduleCategory, Criteria::IN); + } + + $exclude = $this->getExclude(); + + if (!\is_null($exclude)) { + $search->filterById($exclude, Criteria::NOT_IN); + } + + $active = $this->getActive(); + + if ($active !== Type\BooleanOrBothType::ANY) { + $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(); + + foreach ($orders as $order) { + switch ($order) { + case "id": + $search->orderById(Criteria::ASC); + break; + case "id_reverse": + $search->orderById(Criteria::DESC); + break; + case "title": + $search->addAscendingOrderByColumn('i18n_TITLE'); + break; + case "title_reverse": + $search->addDescendingOrderByColumn('i18n_TITLE'); + break; + case "code": + $search->orderByCode(Criteria::ASC); + break; + case "code_reverse": + $search->orderByCode(Criteria::DESC); + break; + case "type": + $search->orderByType(Criteria::ASC); + break; + case "type_reverse": + $search->orderByType(Criteria::DESC); + break; + case "manual": + $search->orderByPosition(Criteria::ASC); + break; + case "manual_reverse": + $search->orderByPosition(Criteria::DESC); + break; + case "enabled": + $search->orderByActivate(Criteria::ASC); + break; + case "enabled_reverse": + $search->orderByActivate(Criteria::DESC); + break; + } + } + + return $search; + } + + public function parseResults(LoopResult $loopResult) + { + /** @var \Thelia\Model\Module $module */ + foreach ($loopResult->getResultDataCollection() as $module) { + try { + new \ReflectionClass($module->getFullNamespace()); + + $exists = true; + } catch (\ReflectionException $ex) { + $exists = false; + } + + if ($exists || $this->getBackendContext()) { + $loopResultRow = new LoopResultRow($module); + + $loopResultRow + ->set("ID", $module->getId()) + ->set("IS_TRANSLATED", $module->getVirtualColumn('IS_TRANSLATED')) + ->set("LOCALE", $this->locale) + ->set("TITLE", $module->getVirtualColumn('i18n_TITLE')) + ->set("CHAPO", $module->getVirtualColumn('i18n_CHAPO')) + ->set("DESCRIPTION", $module->getVirtualColumn('i18n_DESCRIPTION')) + ->set("POSTSCRIPTUM", $module->getVirtualColumn('i18n_POSTSCRIPTUM')) + ->set("CODE", $module->getCode()) + ->set("TYPE", $module->getType()) + ->set("CATEGORY", $module->getCategory()) + ->set("ACTIVE", $module->getActivate()) + ->set("VERSION", $module->getVersion()) + ->set("CLASS", $module->getFullNamespace()) + ->set("POSITION", $module->getPosition()) + ->set("MANDATORY", $module->getMandatory()) + ->set("HIDDEN", $module->getHidden()) + ->set("EXISTS", $exists); + + $hasConfigurationInterface = false; + + /* first test if module defines it's own config route */ + if ($module->getActivate()) { + // test if a hook + $hookConfiguration = ModuleHookQuery::create() + ->filterByModuleId($module->getId()) + ->filterByActive(true) + ->useHookQuery() + ->filterByCode('module.configuration') + ->filterByType(TemplateDefinition::BACK_OFFICE) + ->endUse() + ->findOne(); + $hasConfigurationInterface = (null !== $hookConfiguration); + + if (false === $hasConfigurationInterface) { + // Works only fo activated modules - see Thelia\Core\DependencyInjection\Compiler\RegisterRouterPass + $routerId = "router." . $module->getBaseDir(); + if ($this->container->has($routerId)) { + try { + if ($this->container->get($routerId)->match('/admin/module/' . $module->getCode())) { + $hasConfigurationInterface = true; + } + } catch (ResourceNotFoundException $e) { + /* $hasConfigurationInterface stays false */ + } + } + } + + /* if not ; test if it uses admin inclusion : module_configuration.html */ + if (false === $hasConfigurationInterface) { + if (file_exists($module->getAbsoluteAdminIncludesPath() . DS . "module_configuration.html")) { + $hasConfigurationInterface = true; + } + } + } else { + // Make a quick and dirty test on the module's config.xml file + $configContent = @file_get_contents($module->getAbsoluteConfigPath() . DS . "config.xml"); + + $hasConfigurationInterface = $configContent && + preg_match('/event\s*=\s*[\'"]module.configuration[\'"]/', $configContent) === 1 + ; + + if (false === $hasConfigurationInterface) { + // Make a quick and dirty test on the module's routing.xml file + $routing = @file_get_contents($module->getAbsoluteConfigPath() . DS . "routing.xml"); + + if ($routing && strpos($routing, '/admin/module/') !== false) { + $hasConfigurationInterface = true; + } else { + if (file_exists($module->getAbsoluteAdminIncludesPath() . DS . "module_configuration.html")) { + $hasConfigurationInterface = true; + } + } + } + } + $loopResultRow->set("CONFIGURABLE", $hasConfigurationInterface ? 1 : 0); + + // Does module have hook(s) + $hookable = false; + $moduleHookCount = ModuleHookQuery::create() + ->filterByModuleId($module->getId()) + ->count() + ; + $hookable = ($moduleHookCount > 0); + + $loopResultRow->set("HOOKABLE", $hookable ? 1 : 0); + + + if (null !== $this->getProfile()) { + $accessValue = $module->getVirtualColumn('access'); + $manager = new AccessManager($accessValue); + + $loopResultRow->set("VIEWABLE", $manager->can(AccessManager::VIEW) ? 1 : 0) + ->set("CREATABLE", $manager->can(AccessManager::CREATE) ? 1 : 0) + ->set("UPDATABLE", $manager->can(AccessManager::UPDATE) ? 1 : 0) + ->set("DELETABLE", $manager->can(AccessManager::DELETE) ? 1 : 0); + } + + $this->addOutputFields($loopResultRow, $module); + + $loopResult->addRow($loopResultRow); + } + } + + return $loopResult; + } +} diff --git a/core/lib/Thelia/Core/Template/Loop/ModuleConfig.php b/core/lib/Thelia/Core/Template/Loop/ModuleConfig.php new file mode 100644 index 00000000..fed69dc2 --- /dev/null +++ b/core/lib/Thelia/Core/Template/Loop/ModuleConfig.php @@ -0,0 +1,96 @@ + + * + * {@inheritdoc} + * @method string getModule() + * @method string getVariable() + * @method string getDefaultValue() + * @method string getLocale() + */ +class ModuleConfig extends BaseLoop implements ArraySearchLoopInterface +{ + /** + * @return ArgumentCollection + */ + protected function getArgDefinitions() + { + return new ArgumentCollection( + Argument::createAnyTypeArgument('module', null, true), + Argument::createAnyTypeArgument('variable', null, true), + Argument::createAnyTypeArgument('default_value', null), + Argument::createAnyTypeArgument('locale', null) + ); + } + + /** + * @param LoopResult $loopResult + * + * @return LoopResult + */ + public function parseResults(LoopResult $loopResult) + { + $moduleCode = $this->getModule(); + + if (null === $module = ModuleQuery::create()->filterByCode($moduleCode, Criteria::LIKE)->findOne()) { + throw new \InvalidArgumentException("Module with code '$moduleCode' does not exists."); + } + + $configValue = ModuleConfigQuery::create()->getConfigValue( + $module->getId(), + $this->getVariable(), + $this->getDefaultValue(), + $this->getLocale() + ); + + $loopResultRow = new LoopResultRow(); + + $loopResultRow + ->set("VARIABLE", $this->getVariable()) + ->set("VALUE", $configValue) + ; + + $loopResult->addRow($loopResultRow); + + return $loopResult; + } + + /** + * this method returns an array + * + * @return array + */ + public function buildArray() + { + // Return an array containing one element, so that parseResults() will be called one time. + return [ 'dummy-element' ]; + } +} diff --git a/core/lib/Thelia/Core/Template/Loop/ModuleHook.php b/core/lib/Thelia/Core/Template/Loop/ModuleHook.php new file mode 100644 index 00000000..1c47763c --- /dev/null +++ b/core/lib/Thelia/Core/Template/Loop/ModuleHook.php @@ -0,0 +1,175 @@ + + * + * {@inheritdoc} + * @method int[] getId() + * @method int getHook() + * @method int getModule() + * @method int[] getExclude() + * @method bool|string getModuleActive() + * @method bool|string getHookActive() + * @method bool|string getActive() + * @method string[] getOrder() + */ +class ModuleHook extends BaseI18nLoop implements PropelSearchLoopInterface +{ + protected $timestampable = false; + + /** + * @return ArgumentCollection + */ + protected function getArgDefinitions() + { + return new ArgumentCollection( + Argument::createIntListTypeArgument('id'), + Argument::createIntTypeArgument('hook'), + Argument::createIntTypeArgument('module'), + new Argument( + 'order', + new TypeCollection( + new Type\EnumListType(array('id', 'id_reverse', 'hook', 'hook_reverse', 'manual', 'manual_reverse', 'enabled', 'enabled_reverse')) + ), + 'manual' + ), + Argument::createIntListTypeArgument('exclude'), + Argument::createBooleanOrBothTypeArgument('active', Type\BooleanOrBothType::ANY), + Argument::createBooleanOrBothTypeArgument('hook_active', Type\BooleanOrBothType::ANY), + Argument::createBooleanOrBothTypeArgument('module_active', Type\BooleanOrBothType::ANY) + ); + } + + public function buildModelCriteria() + { + $search = ModuleHookQuery::create(); + + $this->configureI18nProcessing($search, []); + + $id = $this->getId(); + if (null !== $id) { + $search->filterById($id, Criteria::IN); + } + + $hook = $this->getHook(); + if (null !== $hook) { + $search->filterByHookId($hook, Criteria::EQUAL); + } + + $module = $this->getModule(); + if (null !== $module) { + $search->filterByModuleId($module, Criteria::EQUAL); + } + + $exclude = $this->getExclude(); + if (!\is_null($exclude)) { + $search->filterById($exclude, Criteria::NOT_IN); + } + + $active = $this->getActive(); + if ($active !== Type\BooleanOrBothType::ANY) { + $search->filterByActive($active, Criteria::EQUAL); + } + + $hookActive = $this->getHookActive(); + if ($hookActive !== Type\BooleanOrBothType::ANY) { + $search->filterByHookActive($hookActive, Criteria::EQUAL); + } + + $moduleActive = $this->getModuleActive(); + if ($moduleActive !== Type\BooleanOrBothType::ANY) { + $search->filterByModuleActive($moduleActive, Criteria::EQUAL); + } + + $orders = $this->getOrder(); + + foreach ($orders as $order) { + switch ($order) { + case "id": + $search->orderById(Criteria::ASC); + break; + case "id_reverse": + $search->orderById(Criteria::DESC); + break; + case "hook": + $search->orderByHookId(Criteria::ASC); + break; + case "hook_reverse": + $search->orderByHookId(Criteria::DESC); + break; + case "manual": + $search->orderByPosition(Criteria::ASC); + break; + case "manual_reverse": + $search->orderByPosition(Criteria::DESC); + break; + case "enabled": + $search->orderByActive(Criteria::ASC); + break; + case "enabled_reverse": + $search->orderByActive(Criteria::DESC); + break; + } + } + + return $search; + } + + public function parseResults(LoopResult $loopResult) + { + /** @var \Thelia\Model\ModuleHook $moduleHook */ + foreach ($loopResult->getResultDataCollection() as $moduleHook) { + if ($this->getBackendContext()) { + $loopResultRow = new LoopResultRow($moduleHook); + + $loopResultRow + ->set("ID", $moduleHook->getId()) + ->set("HOOK_ID", $moduleHook->getHookId()) + ->set("MODULE_ID", $moduleHook->getModuleId()) + ->set("MODULE_TITLE", $moduleHook->getModule()->setLocale($this->locale)->getTitle()) + ->set("MODULE_CODE", $moduleHook->getModule()->getCode()) + ->set("CLASSNAME", $moduleHook->getClassname()) + ->set("METHOD", $moduleHook->getMethod()) + ->set("ACTIVE", $moduleHook->getActive()) + ->set("HOOK_ACTIVE", $moduleHook->getHookActive()) + ->set("MODULE_ACTIVE", $moduleHook->getModuleActive()) + ->set("POSITION", $moduleHook->getPosition()) + ->set("TEMPLATES", $moduleHook->getTemplates()) + ; + + $this->addOutputFields($loopResultRow, $moduleHook); + $loopResult->addRow($loopResultRow); + } + } + + return $loopResult; + } +} diff --git a/core/lib/Thelia/Core/Template/Loop/Order.php b/core/lib/Thelia/Core/Template/Loop/Order.php new file mode 100644 index 00000000..6218c9c9 --- /dev/null +++ b/core/lib/Thelia/Core/Template/Loop/Order.php @@ -0,0 +1,414 @@ + + * @author Etienne Roudeix + * + * {@inheritdoc} + * @method null|int[] getId() + * @method null|int[] getRef() + * @method null|int[] getInvoiceRef() + * @method null|int[] getDeliveryRef() + * @method null|int[] getTransactionRef() + * @method null|string getCustomer() + * @method null|string[] getStatus() + * @method null|int[] getExcludeStatus() + * @method null|string[] getStatusCode() + * @method null|string[] getExcludeStatusCode() + * @method null|string[] getOrder() + * @method null|bool getWithPrevNextInfo() + */ +class Order extends BaseLoop implements SearchLoopInterface, PropelSearchLoopInterface +{ + protected $countable = true; + protected $timestampable = true; + protected $versionable = false; + + public function getArgDefinitions() + { + return new ArgumentCollection( + Argument::createIntListTypeArgument('id'), + Argument::createAnyListTypeArgument('ref'), + Argument::createAnyListTypeArgument('invoice_ref'), + Argument::createAnyListTypeArgument('delivery_ref'), + Argument::createAnyListTypeArgument('transaction_ref'), + Argument::createBooleanTypeArgument('with_prev_next_info', false), + new Argument( + 'customer', + new TypeCollection( + new Type\IntType(), + new Type\EnumType(array('current', '*')) + ), + 'current' + ), + new Argument( + 'status', + new TypeCollection( + new Type\IntListType(), + new Type\EnumType(array('*')) + ) + ), + Argument::createIntListTypeArgument('exclude_status'), + new Argument( + 'status_code', + new TypeCollection( + new Type\AnyListType(), + new Type\EnumType(array('*')) + ) + ), + Argument::createAnyListTypeArgument('exclude_status_code'), + new Argument( + 'order', + new TypeCollection( + new Type\EnumListType( + array( + 'id', 'id-reverse', + 'reference', 'reference-reverse', + 'create-date', 'create-date-reverse', + 'invoice-date', 'invoice-date-reverse', + 'company', 'company-reverse', + 'customer-name', 'customer-name-reverse', + 'status', 'status-reverse' + ) + ) + ), + 'create-date-reverse' + ) + ); + } + + public function getSearchIn() + { + return array( + 'ref', + 'invoice_ref', + 'delivery_ref', + 'transaction_ref', + 'customer_ref', + 'customer_firstname', + 'customer_lastname', + 'customer_email', + ); + } + + /** + * @param OrderQuery $search + * @param $searchTerm + * @param $searchIn + * @param $searchCriteria + * @throws \Propel\Runtime\Exception\PropelException + */ + public function doSearch(&$search, $searchTerm, $searchIn, $searchCriteria) + { + $search->_and(); + foreach ($searchIn as $index => $searchInElement) { + if ($index > 0) { + $search->_or(); + } + switch ($searchInElement) { + case 'ref': + $search->filterByRef($searchTerm, $searchCriteria); + break; + case 'invoice_ref': + $search->filterByInvoiceRef($searchTerm, $searchCriteria); + break; + case 'delivery_ref': + $search->filterByDeliveryRef($searchTerm, $searchCriteria); + break; + case 'transaction_ref': + $search->filterByTransactionRef($searchTerm, $searchCriteria); + break; + case 'customer_ref': + $search->filterByCustomer( + CustomerQuery::create()->filterByRef($searchTerm, $searchCriteria)->find() + ); + break; + case 'customer_firstname': + $search->filterByOrderAddressRelatedByInvoiceOrderAddressId( + OrderAddressQuery::create()->filterByFirstname($searchTerm, $searchCriteria)->find() + ); + $search->_or(); + $search->filterByOrderAddressRelatedByDeliveryOrderAddressId( + OrderAddressQuery::create()->filterByFirstname($searchTerm, $searchCriteria)->find() + ); + break; + case 'customer_lastname': + $search->filterByOrderAddressRelatedByInvoiceOrderAddressId( + OrderAddressQuery::create()->filterByLastname($searchTerm, $searchCriteria)->find() + ); + $search->_or(); + $search->filterByOrderAddressRelatedByDeliveryOrderAddressId( + OrderAddressQuery::create()->filterByLastname($searchTerm, $searchCriteria)->find() + ); + break; + case 'customer_email': + $search->filterByCustomer( + CustomerQuery::create()->filterByEmail($searchTerm, $searchCriteria)->find() + ); + break; + } + } + } + + public function buildModelCriteria() + { + $search = OrderQuery::create(); + + if (null !== $id = $this->getId()) { + $search->filterById($id, Criteria::IN); + } + + if (null !== $ref = $this->getRef()) { + $search->filterByRef($ref, Criteria::IN); + } + + if (null !== $ref = $this->getDeliveryRef()) { + $search->filterByDeliveryRef($ref, Criteria::IN); + } + + if (null !== $ref = $this->getInvoiceRef()) { + $search->filterByInvoiceRef($ref, Criteria::IN); + } + + if (null !== $ref = $this->getTransactionRef()) { + $search->filterByTransactionRef($ref, Criteria::IN); + } + + $customer = $this->getCustomer(); + + if ($customer === 'current') { + $currentCustomer = $this->securityContext->getCustomerUser(); + if ($currentCustomer === null) { + return null; + } + + $search->filterByCustomerId($currentCustomer->getId(), Criteria::EQUAL); + } elseif ($customer !== '*') { + $search->filterByCustomerId($customer, Criteria::EQUAL); + } + + $status = $this->getStatus(); + + if (null !== $status && $status !== '*') { + $search->filterByStatusId($status, Criteria::IN); + } + + if (null !== $excludeStatus = $this->getExcludeStatus()) { + $search->filterByStatusId($excludeStatus, Criteria::NOT_IN); + } + + $statusCode = $this->getStatusCode(); + + if (null !== $statusCode && $statusCode !== '*') { + $search + ->useOrderStatusQuery() + ->filterByCode($statusCode, Criteria::IN) + ->endUse(); + } + + if (null !== $excludeStatusCode = $this->getExcludeStatusCode()) { + $search + ->useOrderStatusQuery() + ->filterByCode($excludeStatusCode, Criteria::NOT_IN) + ->endUse(); + } + + $orderers = $this->getOrder(); + + foreach ($orderers as $orderer) { + switch ($orderer) { + case 'id': + $search->orderById(Criteria::ASC); + break; + case 'id-reverse': + $search->orderById(Criteria::DESC); + break; + case 'reference': + $search->orderByRef(Criteria::ASC); + break; + case 'reference-reverse': + $search->orderByRef(Criteria::DESC); + break; + case 'create-date': + $search->orderByCreatedAt(Criteria::ASC); + break; + case 'create-date-reverse': + $search->orderByCreatedAt(Criteria::DESC); + break; + case 'invoice-date': + $search->orderByInvoiceDate(Criteria::ASC); + break; + case 'invoice-date-reverse': + $search->orderByInvoiceDate(Criteria::DESC); + break; + case 'status': + $search->orderByStatusId(Criteria::ASC); + break; + case 'status-reverse': + $search->orderByStatusId(Criteria::DESC); + break; + case 'company': + $search + ->joinOrderAddressRelatedByDeliveryOrderAddressId() + ->withColumn(OrderAddressTableMap::COL_COMPANY, 'company') + ->orderBy('company', Criteria::ASC); + break; + case 'company-reverse': + $search + ->joinOrderAddressRelatedByDeliveryOrderAddressId() + ->withColumn(OrderAddressTableMap::COL_COMPANY, 'company') + ->orderBy('company', Criteria::DESC); + break; + case 'customer-name': + $search + ->joinCustomer() + ->withColumn(CustomerTableMap::COL_FIRSTNAME, 'firstname') + ->withColumn(CustomerTableMap::COL_LASTNAME, 'lastname') + ->orderBy('lastname', Criteria::ASC) + ->orderBy('firstname', Criteria::ASC); + break; + case 'customer-name-reverse': + $search + ->joinCustomer() + ->withColumn(CustomerTableMap::COL_FIRSTNAME, 'firstname') + ->withColumn(CustomerTableMap::COL_LASTNAME, 'lastname') + ->orderBy('lastname', Criteria::DESC) + ->orderBy('firstname', Criteria::DESC); + break; + } + } + + return $search; + } + + /** + * @param LoopResult $loopResult + * @return LoopResult + * @throws \Propel\Runtime\Exception\PropelException + */ + public function parseResults(LoopResult $loopResult) + { + $lastLegacyOrderId = ConfigQuery::read('last_legacy_rounding_order_id', 0); + + /** @var \Thelia\Model\Order $order */ + foreach ($loopResult->getResultDataCollection() as $order) { + $tax = $itemsTax = 0; + + $amount = $order->getTotalAmount($tax); + $itemsAmount = $order->getTotalAmount($itemsTax, false, false); + + // Legacy orders have no discount tax calculation + if ($order->getId() <= $lastLegacyOrderId) { + $discountWithoutTax = $order->getDiscount(); + } else { + $discountWithoutTax = Calculator::getUntaxedOrderDiscount($order); + } + + $hasVirtualDownload = $order->hasVirtualProduct(); + + $loopResultRow = new LoopResultRow($order); + $loopResultRow + ->set('ID', $order->getId()) + ->set('REF', $order->getRef()) + ->set('CUSTOMER', $order->getCustomerId()) + ->set('DELIVERY_ADDRESS', $order->getDeliveryOrderAddressId()) + ->set('INVOICE_ADDRESS', $order->getInvoiceOrderAddressId()) + ->set('INVOICE_DATE', $order->getInvoiceDate()) + ->set('CURRENCY', $order->getCurrencyId()) + ->set('CURRENCY_RATE', $order->getCurrencyRate()) + ->set('TRANSACTION_REF', $order->getTransactionRef()) + ->set('DELIVERY_REF', $order->getDeliveryRef()) + ->set('INVOICE_REF', $order->getInvoiceRef()) + ->set('VIRTUAL', $hasVirtualDownload) + ->set('POSTAGE', $order->getPostage()) + ->set('POSTAGE_TAX', $order->getPostageTax()) + ->set('POSTAGE_UNTAXED', $order->getUntaxedPostage()) + ->set('POSTAGE_TAX_RULE_TITLE', $order->getPostageTaxRuleTitle()) + ->set('PAYMENT_MODULE', $order->getPaymentModuleId()) + ->set('DELIVERY_MODULE', $order->getDeliveryModuleId()) + ->set('STATUS', $order->getStatusId()) + ->set('STATUS_CODE', $order->getOrderStatus()->getCode()) + ->set('LANG', $order->getLangId()) + ->set('DISCOUNT', $order->getDiscount()) + ->set('DISCOUNT_WITHOUT_TAX', $discountWithoutTax) + ->set('DISCOUNT_TAX', $order->getDiscount() - $discountWithoutTax) + ->set('TOTAL_ITEMS_TAX', $itemsTax) + ->set('TOTAL_ITEMS_AMOUNT', $itemsAmount - $itemsTax) + ->set('TOTAL_TAXED_ITEMS_AMOUNT', $itemsAmount) + ->set('TOTAL_TAX', $tax) + ->set('TOTAL_AMOUNT', $amount - $tax) + ->set('TOTAL_TAXED_AMOUNT', $amount) + ->set('WEIGHT', $order->getWeight()) + ->set('HAS_PAID_STATUS', $order->isPaid()) + ->set('IS_PAID', $order->isPaid(false)) + ->set('IS_CANCELED', $order->isCancelled()) + ->set('IS_NOT_PAID', $order->isNotPaid()) + ->set('IS_SENT', $order->isSent()) + ->set('IS_PROCESSING', $order->isProcessing()); + + if ($this->getWithPrevNextInfo()) { + // Find previous and next category + $previousQuery = OrderQuery::create() + ->filterById($order->getId(), Criteria::LESS_THAN) + ->filterByStatusId($order->getStatusId(), Criteria::EQUAL); + + $previous = $previousQuery + ->orderById(Criteria::DESC) + ->findOne(); + + $nextQuery = OrderQuery::create() + ->filterById($order->getId(), Criteria::GREATER_THAN) + ->filterByStatusId($order->getStatusId(), Criteria::EQUAL); + + $next = $nextQuery + ->orderById(Criteria::ASC) + ->findOne(); + + $loopResultRow + ->set('HAS_PREVIOUS', $previous !== null ? 1 : 0) + ->set('HAS_NEXT', $next !== null ? 1 : 0) + ->set('PREVIOUS', $previous !== null ? $previous->getId() : -1) + ->set('NEXT', $next !== null ? $next->getId() : -1); + } + + $this->addOutputFields($loopResultRow, $order); + + $loopResult->addRow($loopResultRow); + } + + return $loopResult; + } +} diff --git a/core/lib/Thelia/Core/Template/Loop/OrderAddress.php b/core/lib/Thelia/Core/Template/Loop/OrderAddress.php new file mode 100644 index 00000000..3e8f811f --- /dev/null +++ b/core/lib/Thelia/Core/Template/Loop/OrderAddress.php @@ -0,0 +1,90 @@ + + * + * {@inheritdoc} + * @method int getId() + */ +class OrderAddress extends BaseLoop implements PropelSearchLoopInterface +{ + protected $timestampable = true; + + /** + * @return ArgumentCollection + */ + protected function getArgDefinitions() + { + return new ArgumentCollection( + Argument::createIntTypeArgument('id', null, true) + ); + } + + public function buildModelCriteria() + { + $search = OrderAddressQuery::create(); + + $id = $this->getId(); + + $search->filterById($id, Criteria::IN); + + return $search; + } + + public function parseResults(LoopResult $loopResult) + { + /** @var OrderAddressModel $orderAddress */ + foreach ($loopResult->getResultDataCollection() as $orderAddress) { + $loopResultRow = new LoopResultRow($orderAddress); + $loopResultRow + ->set("ID", $orderAddress->getId()) + ->set("TITLE", $orderAddress->getCustomerTitleId()) + ->set("COMPANY", $orderAddress->getCompany()) + ->set("FIRSTNAME", $orderAddress->getFirstname()) + ->set("LASTNAME", $orderAddress->getLastname()) + ->set("ADDRESS1", $orderAddress->getAddress1()) + ->set("ADDRESS2", $orderAddress->getAddress2()) + ->set("ADDRESS3", $orderAddress->getAddress3()) + ->set("ZIPCODE", $orderAddress->getZipcode()) + ->set("CITY", $orderAddress->getCity()) + ->set("COUNTRY", $orderAddress->getCountryId()) + ->set("STATE", $orderAddress->getStateId()) + ->set("PHONE", $orderAddress->getPhone()) + ->set("CELLPHONE", $orderAddress->getCellphone()) + ; + $this->addOutputFields($loopResultRow, $orderAddress); + + $loopResult->addRow($loopResultRow); + } + + return $loopResult; + } +} diff --git a/core/lib/Thelia/Core/Template/Loop/OrderCoupon.php b/core/lib/Thelia/Core/Template/Loop/OrderCoupon.php new file mode 100644 index 00000000..51690ec4 --- /dev/null +++ b/core/lib/Thelia/Core/Template/Loop/OrderCoupon.php @@ -0,0 +1,118 @@ + + * + * {@inheritdoc} + * @method string[] getOrder() + */ +class OrderCoupon extends BaseLoop implements PropelSearchLoopInterface +{ + /** + * Define all args used in your loop + * + * @return ArgumentCollection + */ + protected function getArgDefinitions() + { + return new ArgumentCollection( + Argument::createIntTypeArgument('order', null, true) + ); + } + + public function buildModelCriteria() + { + $search = OrderCouponQuery::create(); + + $order = $this->getOrder(); + + $search + ->filterByOrderId($order, Criteria::EQUAL) + ->orderById(Criteria::ASC) + ; + + return $search; + } + + public function parseResults(LoopResult $loopResult) + { + $this->container->get('thelia.condition.factory'); + + if (null !== $order = OrderQuery::create()->findPk($this->getOrder())) { + $oneDayInSeconds = 86400; + + /** @var \Thelia\Model\OrderCoupon $orderCoupon */ + foreach ($loopResult->getResultDataCollection() as $orderCoupon) { + $loopResultRow = new LoopResultRow($orderCoupon); + + $now = time(); + $datediff = $orderCoupon->getExpirationDate()->getTimestamp() - $now; + $daysLeftBeforeExpiration = floor($datediff/($oneDayInSeconds)); + + $freeShippingForCountriesIds = []; + /** @var OrderCouponCountry $couponCountry */ + foreach ($orderCoupon->getFreeShippingForCountries() as $couponCountry) { + $freeShippingForCountriesIds[] = $couponCountry->getCountryId(); + } + + $freeShippingForModulesIds = []; + /** @var OrderCouponModule $couponModule */ + foreach ($orderCoupon->getFreeShippingForModules() as $couponModule) { + $freeShippingForModulesIds[] = $couponModule->getModuleId(); + } + + $loopResultRow->set("ID", $orderCoupon->getId()) + ->set("CODE", $orderCoupon->getCode()) + ->set("DISCOUNT_AMOUNT", $orderCoupon->getAmount()) + ->set("TITLE", $orderCoupon->getTitle()) + ->set("SHORT_DESCRIPTION", $orderCoupon->getShortDescription()) + ->set("DESCRIPTION", $orderCoupon->getDescription()) + ->set("EXPIRATION_DATE", $orderCoupon->getExpirationDate($order->getLangId())) + ->set("IS_CUMULATIVE", $orderCoupon->getIsCumulative()) + ->set("IS_REMOVING_POSTAGE", $orderCoupon->getIsRemovingPostage()) + ->set("IS_AVAILABLE_ON_SPECIAL_OFFERS", $orderCoupon->getIsAvailableOnSpecialOffers()) + ->set("DAY_LEFT_BEFORE_EXPIRATION", $daysLeftBeforeExpiration) + ->set("FREE_SHIPPING_FOR_COUNTRIES_LIST", implode(',', $freeShippingForCountriesIds)) + ->set("FREE_SHIPPING_FOR_MODULES_LIST", implode(',', $freeShippingForModulesIds)) + ->set("PER_CUSTOMER_USAGE_COUNT", $orderCoupon->getPerCustomerUsageCount()) + ->set("IS_USAGE_CANCELED", $orderCoupon->getUsageCanceled()) + ; + $this->addOutputFields($loopResultRow, $orderCoupon); + + $loopResult->addRow($loopResultRow); + } + } + + return $loopResult; + } +} diff --git a/core/lib/Thelia/Core/Template/Loop/OrderProduct.php b/core/lib/Thelia/Core/Template/Loop/OrderProduct.php new file mode 100644 index 00000000..d6451e86 --- /dev/null +++ b/core/lib/Thelia/Core/Template/Loop/OrderProduct.php @@ -0,0 +1,202 @@ + + * + * @method int getOrder() + * @method int[] getId() + * @method bool|string getVirtual() + */ +class OrderProduct extends BaseLoop implements PropelSearchLoopInterface +{ + protected $timestampable = true; + + /** + * @return ArgumentCollection + */ + protected function getArgDefinitions() + { + return new ArgumentCollection( + Argument::createIntTypeArgument('order', null, true), + Argument::createIntListTypeArgument('id'), + Argument::createBooleanOrBothTypeArgument('virtual', BooleanOrBothType::ANY) + ); + } + + public function buildModelCriteria() + { + $search = OrderProductQuery::create(); + + $search->joinOrderProductTax('opt', Criteria::LEFT_JOIN) + ->withColumn('SUM(`opt`.AMOUNT)', 'TOTAL_TAX') + ->withColumn('SUM(`opt`.PROMO_AMOUNT)', 'TOTAL_PROMO_TAX') + ->groupById(); + + + // new join to get the product id if it exists + $pseJoin = new Join( + OrderProductTableMap::COL_PRODUCT_SALE_ELEMENTS_ID, + ProductSaleElementsTableMap::COL_ID, + Criteria::LEFT_JOIN + ); + $search + ->addJoinObject($pseJoin) + ->addAsColumn( + 'product_id', + ProductSaleElementsTableMap::COL_PRODUCT_ID + ) + ; + + $order = $this->getOrder(); + + $search->filterByOrderId($order, Criteria::EQUAL); + + $virtual = $this->getVirtual(); + if ($virtual !== BooleanOrBothType::ANY) { + if ($virtual) { + $search + ->filterByVirtual(1, Criteria::EQUAL) + ->filterByVirtualDocument(null, Criteria::NOT_EQUAL); + } else { + $search + ->filterByVirtual(0); + } + } + + if (null !== $this->getId()) { + $search->filterById($this->getId(), Criteria::IN); + } + + $search->orderById(Criteria::ASC); + + return $search; + } + + /** + * @param LoopResult $loopResult + * @return LoopResult + * @throws \Propel\Runtime\Exception\PropelException + */ + public function parseResults(LoopResult $loopResult) + { + $lastLegacyRoundingOrderId = ConfigQuery::read('last_legacy_rounding_order_id', 0); + + /** @var \Thelia\Model\OrderProduct $orderProduct */ + foreach ($loopResult->getResultDataCollection() as $orderProduct) { + $loopResultRow = new LoopResultRow($orderProduct); + + $tax = $orderProduct->getVirtualColumn('TOTAL_TAX'); + $promoTax = $orderProduct->getVirtualColumn('TOTAL_PROMO_TAX'); + + // To prevent price changes in pre-2.4 orders, use the legacy calculation method + if ($orderProduct->getOrderId() <= $lastLegacyRoundingOrderId) { + $totalTax = round($tax * $orderProduct->getQuantity(), 2); + $totalPromoTax = round($promoTax * $orderProduct->getQuantity(), 2); + + $taxedPrice = (float) $orderProduct->getPrice() + (float) $orderProduct->getVirtualColumn('TOTAL_TAX'); + $taxedPromoPrice = (float) $orderProduct->getPromoPrice() + (float) $orderProduct->getVirtualColumn('TOTAL_PROMO_TAX'); + + $totalPrice = $orderProduct->getPrice() * $orderProduct->getQuantity(); + $totalPromoPrice = $orderProduct->getPromoPrice() * $orderProduct->getQuantity(); + + $totalTaxedPrice = round($taxedPrice, 2) * $orderProduct->getQuantity(); + $totalTaxedPromoPrice = round($taxedPromoPrice, 2) * $orderProduct->getQuantity(); + } else { + $tax = round($tax, 2); + $promoTax = round($promoTax, 2); + + $totalTax = $tax * $orderProduct->getQuantity(); + $totalPromoTax = $promoTax * $orderProduct->getQuantity(); + + $taxedPrice = round((float) $orderProduct->getPrice() + $tax, 2); + $taxedPromoPrice = round((float) $orderProduct->getPromoPrice() + $promoTax, 2); + + // Price calculation should use the same rounding method as in CartItem::getTotalTaxedPromoPrice() + // For each order line, we first round the taxed price, then we multiply by the quantity. + $totalPrice = round($orderProduct->getPrice(), 2) * $orderProduct->getQuantity(); + $totalPromoPrice = round($orderProduct->getPromoPrice(), 2) * $orderProduct->getQuantity(); + + $totalTaxedPrice = $taxedPrice * $orderProduct->getQuantity(); + $totalTaxedPromoPrice = $taxedPromoPrice * $orderProduct->getQuantity(); + } + + $loopResultRow->set('ID', $orderProduct->getId()) + ->set('REF', $orderProduct->getProductRef()) + ->set('PRODUCT_ID', $orderProduct->getVirtualColumn('product_id')) + ->set('PRODUCT_SALE_ELEMENTS_ID', $orderProduct->getProductSaleElementsId()) + ->set('PRODUCT_SALE_ELEMENTS_REF', $orderProduct->getProductSaleElementsRef()) + ->set('WAS_NEW', $orderProduct->getWasNew() === 1 ? 1 : 0) + ->set('WAS_IN_PROMO', $orderProduct->getWasInPromo() === 1 ? 1 : 0) + ->set('WEIGHT', $orderProduct->getWeight()) + ->set('TITLE', $orderProduct->getTitle()) + ->set('CHAPO', $orderProduct->getChapo()) + ->set('DESCRIPTION', $orderProduct->getDescription()) + ->set('POSTSCRIPTUM', $orderProduct->getPostscriptum()) + ->set('VIRTUAL', $orderProduct->getVirtual()) + ->set('VIRTUAL_DOCUMENT', $orderProduct->getVirtualDocument()) + ->set('QUANTITY', $orderProduct->getQuantity()) + + ->set('PRICE', $orderProduct->getPrice()) + ->set('PRICE_TAX', $tax) + ->set('TAXED_PRICE', $taxedPrice) + ->set('PROMO_PRICE', $orderProduct->getPromoPrice()) + ->set('PROMO_PRICE_TAX', $promoTax) + ->set('TAXED_PROMO_PRICE', $taxedPromoPrice) + ->set('TOTAL_PRICE', $totalPrice) + ->set('TOTAL_TAXED_PRICE', $totalTaxedPrice) + ->set('TOTAL_PROMO_PRICE', $totalPromoPrice) + ->set('TOTAL_TAXED_PROMO_PRICE', $totalTaxedPromoPrice) + + ->set('TAX_RULE_TITLE', $orderProduct->getTaxRuleTitle()) + ->set('TAX_RULE_DESCRIPTION', $orderProduct->getTaxRuledescription()) + ->set('PARENT', $orderProduct->getParent()) + ->set('EAN_CODE', $orderProduct->getEanCode()) + ->set('CART_ITEM_ID', $orderProduct->getCartItemId()) + + ->set('REAL_PRICE', $orderProduct->getWasInPromo() ? $orderProduct->getPromoPrice() : $orderProduct->getPrice()) + ->set('REAL_TAXED_PRICE', $orderProduct->getWasInPromo() ? $taxedPromoPrice : $taxedPrice) + ->set('REAL_PRICE_TAX', $orderProduct->getWasInPromo() ? $promoTax : $tax) + + ->set('REAL_TOTAL_PRICE', $orderProduct->getWasInPromo() ? $totalPromoPrice : $totalPrice) + ->set('REAL_TOTAL_TAXED_PRICE', $orderProduct->getWasInPromo() ? $totalTaxedPromoPrice : $totalTaxedPrice) + ->set('REAL_TOTAL_PRICE_TAX', $orderProduct->getWasInPromo() ? $totalPromoTax : $totalTax) + + ; + $this->addOutputFields($loopResultRow, $orderProduct); + + $loopResult->addRow($loopResultRow); + } + + return $loopResult; + } +} diff --git a/core/lib/Thelia/Core/Template/Loop/OrderProductAttributeCombination.php b/core/lib/Thelia/Core/Template/Loop/OrderProductAttributeCombination.php new file mode 100644 index 00000000..940dc2eb --- /dev/null +++ b/core/lib/Thelia/Core/Template/Loop/OrderProductAttributeCombination.php @@ -0,0 +1,110 @@ + + * + * {@inheritdoc} + * @method int getOrderProduct() + * @method string[] getOrder() + * @method bool getVirtual() + */ +class OrderProductAttributeCombination extends BaseI18nLoop implements PropelSearchLoopInterface +{ + protected $timestampable = true; + + /** + * @return ArgumentCollection + */ + protected function getArgDefinitions() + { + return new ArgumentCollection( + Argument::createIntTypeArgument('order_product', null, true), + new Argument( + 'order', + new TypeCollection( + new Type\EnumListType(array('alpha', 'alpha_reverse')) + ), + 'alpha' + ) + ); + } + + public function buildModelCriteria() + { + $search = OrderProductAttributeCombinationQuery::create(); + + $orderProduct = $this->getOrderProduct(); + + $search->filterByOrderProductId($orderProduct, Criteria::EQUAL); + + $orders = $this->getOrder(); + + foreach ($orders as $order) { + switch ($order) { + case 'alpha': + $search->orderByAttributeTitle(Criteria::ASC); + break; + case 'alpha_reverse': + $search->orderByAttributeTitle(Criteria::DESC); + break; + } + } + + return $search; + } + + public function parseResults(LoopResult $loopResult) + { + /** @var OrderProductAttributeCombinationModel $orderAttributeCombination */ + foreach ($loopResult->getResultDataCollection() as $orderAttributeCombination) { + $loopResultRow = new LoopResultRow($orderAttributeCombination); + + $loopResultRow + ->set('ID', $orderAttributeCombination->getId()) + ->set('ORDER_PRODUCT_ID', $orderAttributeCombination->getOrderProductId()) + ->set('ATTRIBUTE_TITLE', $orderAttributeCombination->getAttributeTitle()) + ->set('ATTRIBUTE_CHAPO', $orderAttributeCombination->getAttributeChapo()) + ->set('ATTRIBUTE_DESCRIPTION', $orderAttributeCombination->getAttributeDescription()) + ->set('ATTRIBUTE_POSTSCRIPTUM', $orderAttributeCombination->getAttributePostscriptum()) + ->set('ATTRIBUTE_AVAILABILITY_TITLE', $orderAttributeCombination->getAttributeAvTitle()) + ->set('ATTRIBUTE_AVAILABILITY_CHAPO', $orderAttributeCombination->getAttributeAvChapo()) + ->set('ATTRIBUTE_AVAILABILITY_DESCRIPTION', $orderAttributeCombination->getAttributeAvDescription()) + ->set('ATTRIBUTE_AVAILABILITY_POSTSCRIPTUM', $orderAttributeCombination->getAttributeAvPostscriptum()) + ; + $this->addOutputFields($loopResultRow, $orderAttributeCombination); + + $loopResult->addRow($loopResultRow); + } + + return $loopResult; + } +} diff --git a/core/lib/Thelia/Core/Template/Loop/OrderProductTax.php b/core/lib/Thelia/Core/Template/Loop/OrderProductTax.php new file mode 100644 index 00000000..e52803c2 --- /dev/null +++ b/core/lib/Thelia/Core/Template/Loop/OrderProductTax.php @@ -0,0 +1,80 @@ +getOrderProduct(); + + $search->filterByOrderProductId($orderProduct, Criteria::EQUAL); + + return $search; + } + + public function parseResults(LoopResult $loopResult) + { + /** @var OrderProductTaxModel $orderProductTax */ + foreach ($loopResult->getResultDataCollection() as $orderProductTax) { + $loopResultRow = new LoopResultRow($orderProductTax); + $loopResultRow->set("ID", $orderProductTax->getId()) + ->set("TITLE", $orderProductTax->getTitle()) + ->set("DESCRIPTION", $orderProductTax->getDescription()) + ->set("AMOUNT", $orderProductTax->getAmount()) + ->set("PROMO_AMOUNT", $orderProductTax->getPromoAmount()) + ; + $this->addOutputFields($loopResultRow, $orderProductTax); + + $loopResult->addRow($loopResultRow); + } + + return $loopResult; + } +} diff --git a/core/lib/Thelia/Core/Template/Loop/OrderStatus.php b/core/lib/Thelia/Core/Template/Loop/OrderStatus.php new file mode 100644 index 00000000..9b243b9f --- /dev/null +++ b/core/lib/Thelia/Core/Template/Loop/OrderStatus.php @@ -0,0 +1,125 @@ + + * @author Gilles Bourgeat + * + * @method int[] getId() + * @method string getCode() + * @method string[] getOrder() + */ +class OrderStatus extends BaseI18nLoop implements PropelSearchLoopInterface +{ + protected $timestampable = true; + + /** + * @return ArgumentCollection + */ + protected function getArgDefinitions() + { + return new ArgumentCollection( + Argument::createIntListTypeArgument('id'), + Argument::createAnyTypeArgument('code'), + Argument::createEnumListTypeArgument( + 'order', + [ + 'alpha', + 'alpha_reverse', + 'manual', + 'manual_reverse' + ], + 'manual' + ) + ); + } + + public function buildModelCriteria() + { + $search = OrderStatusQuery::create(); + + /* manage translations */ + $this->configureI18nProcessing($search); + + if (null !== $id = $this->getId()) { + $search->filterById($id, Criteria::IN); + } + + if (null !== $code = $this->getCode()) { + $search->filterByCode($code, Criteria::EQUAL); + } + + $orders = $this->getOrder(); + + foreach ($orders as $order) { + switch ($order) { + case "alpha": + $search->addAscendingOrderByColumn('i18n_TITLE'); + break; + case "alpha_reverse": + $search->addDescendingOrderByColumn('i18n_TITLE'); + break; + case "manual": + $search->orderByPosition(Criteria::ASC); + break; + case "manual_reverse": + $search->orderByPosition(Criteria::DESC); + break; + } + } + + return $search; + } + + public function parseResults(LoopResult $loopResult) + { + /** @var OrderStatusModel $orderStatus */ + foreach ($loopResult->getResultDataCollection() as $orderStatus) { + $loopResultRow = new LoopResultRow($orderStatus); + $loopResultRow->set("ID", $orderStatus->getId()) + ->set("IS_TRANSLATED", $orderStatus->getVirtualColumn('IS_TRANSLATED')) + ->set("LOCALE", $this->locale) + ->set("CODE", $orderStatus->getCode()) + ->set("COLOR", $orderStatus->getColor()) + ->set("POSITION", $orderStatus->getPosition()) + ->set("PROTECTED_STATUS", $orderStatus->getProtectedStatus()) + ->set("TITLE", $orderStatus->getVirtualColumn('i18n_TITLE')) + ->set("CHAPO", $orderStatus->getVirtualColumn('i18n_CHAPO')) + ->set("DESCRIPTION", $orderStatus->getVirtualColumn('i18n_DESCRIPTION')) + ->set("POSTSCRIPTUM", $orderStatus->getVirtualColumn('i18n_POSTSCRIPTUM')) + ; + $this->addOutputFields($loopResultRow, $orderStatus); + + $loopResult->addRow($loopResultRow); + } + + return $loopResult; + } +} diff --git a/core/lib/Thelia/Core/Template/Loop/Payment.php b/core/lib/Thelia/Core/Template/Loop/Payment.php new file mode 100644 index 00000000..23c492c2 --- /dev/null +++ b/core/lib/Thelia/Core/Template/Loop/Payment.php @@ -0,0 +1,77 @@ + + */ +class Payment extends BaseSpecificModule implements PropelSearchLoopInterface +{ + public function getArgDefinitions() + { + $collection = parent::getArgDefinitions(); + + return $collection; + } + + public function parseResults(LoopResult $loopResult) + { + $cart = $this->getCurrentRequest()->getSession()->getSessionCart($this->dispatcher); + + /** @var \Thelia\Model\Module $paymentModule */ + foreach ($loopResult->getResultDataCollection() as $paymentModule) { + $loopResultRow = new LoopResultRow($paymentModule); + + $moduleInstance = $paymentModule->getPaymentModuleInstance($this->container); + + $isValidPaymentEvent = new IsValidPaymentEvent($moduleInstance, $cart); + $this->dispatcher->dispatch( + TheliaEvents::MODULE_PAYMENT_IS_VALID, + $isValidPaymentEvent + ); + + if (false === $isValidPaymentEvent->isValidModule()) { + continue; + } + + $loopResultRow + ->set('ID', $paymentModule->getId()) + ->set('CODE', $paymentModule->getCode()) + ->set('TITLE', $paymentModule->getVirtualColumn('i18n_TITLE')) + ->set('CHAPO', $paymentModule->getVirtualColumn('i18n_CHAPO')) + ->set('DESCRIPTION', $paymentModule->getVirtualColumn('i18n_DESCRIPTION')) + ->set('POSTSCRIPTUM', $paymentModule->getVirtualColumn('i18n_POSTSCRIPTUM')) + ; + $this->addOutputFields($loopResultRow, $paymentModule); + + $loopResult->addRow($loopResultRow); + } + + return $loopResult; + } + + protected function getModuleType() + { + return BaseModule::PAYMENT_MODULE_TYPE; + } +} diff --git a/core/lib/Thelia/Core/Template/Loop/Product.php b/core/lib/Thelia/Core/Template/Loop/Product.php new file mode 100644 index 00000000..cec4db26 --- /dev/null +++ b/core/lib/Thelia/Core/Template/Loop/Product.php @@ -0,0 +1,1228 @@ + + * + * {@inheritdoc} + * @method int[] getId() + * @method bool getComplex() + * @method string[] getRef() + * @method int[] getCategory() + * @method int[] getBrand() + * @method int[] getSale() + * @method int[] getCategoryDefault() + * @method int[] getContent() + * @method bool getNew() + * @method bool getPromo() + * @method float getMinPrice() + * @method float getMaxPrice() + * @method int getMinStock() + * @method float getMinWeight() + * @method float getMaxWeight() + * @method bool getWithPrevNextInfo() + * @method bool|string getWithPrevNextVisible() + * @method bool getCurrent() + * @method bool getCurrentCategory() + * @method bool getDepth() + * @method bool|string getVirtual() + * @method bool|string getVisible() + * @method int getCurrency() + * @method string getTitle() + * @method string[] getOrder() + * @method int[] getExclude() + * @method int[] getExcludeCategory() + * @method int[] getFeatureAvailability() + * @method string[] getFeatureValues() + * @method string[] getAttributeNonStrictMatch() + * @method int[] getTemplateId() + * @method int[] getTaxRuleId() + * @method int[] getExcludeTaxRuleId() + */ +class Product extends BaseI18nLoop implements PropelSearchLoopInterface, SearchLoopInterface +{ + protected $timestampable = true; + protected $versionable = true; + + use StandardI18nFieldsSearchTrait; + + /** + * @return ArgumentCollection + */ + protected function getArgDefinitions() + { + return new ArgumentCollection( + Argument::createBooleanTypeArgument('complex', false), + Argument::createIntListTypeArgument('id'), + Argument::createAnyListTypeArgument('ref'), + Argument::createIntListTypeArgument('category'), + Argument::createIntListTypeArgument('brand'), + Argument::createIntListTypeArgument('sale'), + Argument::createIntListTypeArgument('category_default'), + Argument::createIntListTypeArgument('content'), + Argument::createBooleanTypeArgument('new'), + Argument::createBooleanTypeArgument('promo'), + Argument::createFloatTypeArgument('min_price'), + Argument::createFloatTypeArgument('max_price'), + Argument::createIntTypeArgument('min_stock'), + Argument::createFloatTypeArgument('min_weight'), + Argument::createFloatTypeArgument('max_weight'), + Argument::createBooleanTypeArgument('with_prev_next_info', false), + Argument::createBooleanOrBothTypeArgument('with_prev_next_visible', Type\BooleanOrBothType::ANY), + Argument::createBooleanTypeArgument('current'), + Argument::createBooleanTypeArgument('current_category'), + Argument::createIntTypeArgument('depth', 1), + Argument::createBooleanOrBothTypeArgument('virtual', Type\BooleanOrBothType::ANY), + Argument::createBooleanOrBothTypeArgument('visible', 1), + Argument::createIntTypeArgument('currency'), + Argument::createAnyTypeArgument('title'), + Argument::createIntListTypeArgument('template_id'), + Argument::createIntListTypeArgument('tax_rule_id'), + Argument::createIntListTypeArgument('exclude_tax_rule_id'), + new Argument( + 'order', + new TypeCollection( + new Type\EnumListType( + [ + 'id', 'id_reverse', + 'alpha', 'alpha_reverse', + 'min_price', 'max_price', + 'manual', 'manual_reverse', + 'created', 'created_reverse', + 'updated', 'updated_reverse', + 'ref', 'ref_reverse', + 'visible', 'visible_reverse', + 'position', 'position_reverse', + 'promo', + 'new', + 'random', + 'given_id' + ] + ) + ), + 'alpha' + ), + Argument::createIntListTypeArgument('exclude'), + Argument::createIntListTypeArgument('exclude_category'), + new Argument( + 'feature_availability', + new TypeCollection( + new Type\IntToCombinedIntsListType() + ) + ), + new Argument( + 'feature_values', + new TypeCollection( + new Type\IntToCombinedStringsListType() + ) + ), + /* + * promo, new, quantity, weight or price may differ depending on the different attributes + * by default, product loop will look for at least 1 attribute which matches all the loop criteria : attribute_non_strict_match="none" + * you can also provide a list of non-strict attributes. + * ie : attribute_non_strict_match="promo,new" + * loop will return the product if he has at least an attribute in promo and at least an attribute as new ; even if it's not the same attribute. + * you can set all the attributes as non strict : attribute_non_strict_match="*" + * + * In order to allow such a process, we will have to make a LEFT JOIN foreach of the following case. + */ + new Argument( + 'attribute_non_strict_match', + new TypeCollection( + new Type\EnumListType( + ['min_stock', 'promo', 'new', 'min_weight', 'max_weight', 'min_price', 'max_price'] + ), + new Type\EnumType(['*', 'none']) + ), + 'none' + ) + ); + } + + public function getSearchIn() + { + return array_merge( + [ 'ref' ], + $this->getStandardI18nSearchFields() + ); + } + + /** + * @param ProductQuery $search + * @param $searchTerm + * @param $searchIn + * @param $searchCriteria + */ + public function doSearch(&$search, $searchTerm, $searchIn, $searchCriteria) + { + $search->_and(); + + foreach ($searchIn as $index => $searchInElement) { + if ($index > 0) { + $search->_or(); + } + switch ($searchInElement) { + case "ref": + $search->filterByRef($searchTerm, $searchCriteria); + break; + } + } + + $this->addStandardI18nSearch($search, $searchTerm, $searchCriteria, $searchIn); + } + + /** + * @param LoopResult $loopResult + * @return LoopResult + * @throws \Propel\Runtime\Exception\PropelException + */ + public function parseResults(LoopResult $loopResult) + { + $complex = $this->getComplex(); + + if (true === $complex) { + return $this->parseComplexResults($loopResult); + } else { + return $this->parseSimpleResults($loopResult); + } + } + + /** + * @param LoopResult $loopResult + * @return LoopResult + * @throws \Propel\Runtime\Exception\PropelException + */ + public function parseSimpleResults(LoopResult $loopResult) + { + /** @var TaxEngine $taxEngine */ + $taxEngine = $this->container->get('thelia.taxEngine'); + $taxCountry = $taxEngine->getDeliveryCountry(); + $taxState = $taxEngine->getDeliveryState(); + + /** @var \Thelia\Core\Security\SecurityContext $securityContext */ + $securityContext = $this->container->get('thelia.securityContext'); + + /** @var \Thelia\Model\Product $product */ + foreach ($loopResult->getResultDataCollection() as $product) { + $loopResultRow = new LoopResultRow($product); + + $price = $product->getVirtualColumn('price'); + + if (!$this->getBackendContext() + && $securityContext->hasCustomerUser() + && $securityContext->getCustomerUser()->getDiscount() > 0) { + $price = $price * (1-($securityContext->getCustomerUser()->getDiscount()/100)); + } + + try { + $taxedPrice = $product->getTaxedPrice( + $taxCountry, + $price, + $taxState + ); + } catch (TaxEngineException $e) { + $taxedPrice = null; + } + $promoPrice = $product->getVirtualColumn('promo_price'); + + if (!$this->getBackendContext() + && $securityContext->hasCustomerUser() + && $securityContext->getCustomerUser()->getDiscount() > 0) { + $promoPrice = $promoPrice * (1-($securityContext->getCustomerUser()->getDiscount()/100)); + } + try { + $taxedPromoPrice = $product->getTaxedPromoPrice( + $taxCountry, + $promoPrice, + $taxState + ); + } catch (TaxEngineException $e) { + $taxedPromoPrice = null; + } + + $defaultCategoryId = $this->getDefaultCategoryId($product); + + $loopResultRow + ->set("WEIGHT", $product->getVirtualColumn('weight')) + ->set("QUANTITY", $product->getVirtualColumn('quantity')) + ->set("EAN_CODE", $product->getVirtualColumn('ean_code')) + ->set("BEST_PRICE", $product->getVirtualColumn('is_promo') ? $promoPrice : $price) + ->set("BEST_PRICE_TAX", $taxedPrice - $product->getVirtualColumn('is_promo') ? $taxedPromoPrice - $promoPrice : $taxedPrice - $price) + ->set("BEST_TAXED_PRICE", $product->getVirtualColumn('is_promo') ? $taxedPromoPrice : $taxedPrice) + ->set("PRICE", $price) + ->set("PRICE_TAX", $taxedPrice - $price) + ->set("TAXED_PRICE", $taxedPrice) + ->set("PROMO_PRICE", $promoPrice) + ->set("PROMO_PRICE_TAX", $taxedPromoPrice - $promoPrice) + ->set("TAXED_PROMO_PRICE", $taxedPromoPrice) + ->set("IS_PROMO", $product->getVirtualColumn('is_promo')) + ->set("IS_NEW", $product->getVirtualColumn('is_new')) + ->set("PRODUCT_SALE_ELEMENT", $product->getVirtualColumn('pse_id')) + ->set("PSE_COUNT", $product->getVirtualColumn('pse_count')); + + $this->associateValues($loopResultRow, $product, $defaultCategoryId); + + $this->addOutputFields($loopResultRow, $product); + + $loopResult->addRow($loopResultRow); + } + + return $loopResult; + } + + /** + * @param LoopResult $loopResult + * @return LoopResult + * @throws \Propel\Runtime\Exception\PropelException + */ + public function parseComplexResults(LoopResult $loopResult) + { + /** @var TaxEngine $taxEngine */ + $taxEngine = $this->container->get('thelia.taxEngine'); + $taxCountry = $taxEngine->getDeliveryCountry(); + $taxState = $taxEngine->getDeliveryState(); + + /** @var \Thelia\Core\Security\SecurityContext $securityContext */ + $securityContext = $this->container->get('thelia.securityContext'); + + /** @var \Thelia\Model\Product $product */ + foreach ($loopResult->getResultDataCollection() as $product) { + $loopResultRow = new LoopResultRow($product); + + $price = $product->getRealLowestPrice(); + + if ($securityContext->hasCustomerUser() && $securityContext->getCustomerUser()->getDiscount() > 0) { + $price = $price * (1-($securityContext->getCustomerUser()->getDiscount()/100)); + } + + try { + $taxedPrice = $product->getTaxedPrice( + $taxCountry, + $price, + $taxState + ); + } catch (TaxEngineException $e) { + $taxedPrice = null; + } + + $defaultCategoryId = $this->getDefaultCategoryId($product); + + $loopResultRow + ->set("BEST_PRICE", $price) + ->set("BEST_PRICE_TAX", $taxedPrice - $price) + ->set("BEST_TAXED_PRICE", $taxedPrice) + ->set("IS_PROMO", $product->getVirtualColumn('main_product_is_promo')) + ->set("IS_NEW", $product->getVirtualColumn('main_product_is_new')); + + $this->associateValues($loopResultRow, $product, $defaultCategoryId); + + $this->addOutputFields($loopResultRow, $product); + + $loopResult->addRow($loopResultRow); + } + + return $loopResult; + } + + /** + * @param LoopResultRow $loopResultRow the current result row + * @param \Thelia\Model\Product $product + * @param $defaultCategoryId + * @return mixed + * @throws \Propel\Runtime\Exception\PropelException + */ + private function associateValues($loopResultRow, $product, $defaultCategoryId) + { + $display_initial_price = $product->getVirtualColumn('display_initial_price'); + + if (\is_null($display_initial_price)) { + $display_initial_price = 1; + } + + $loopResultRow + ->set("ID", $product->getId()) + ->set("REF", $product->getRef()) + ->set("IS_TRANSLATED", $product->getVirtualColumn('IS_TRANSLATED')) + ->set("LOCALE", $this->locale) + ->set("TITLE", $product->getVirtualColumn('i18n_TITLE')) + ->set("CHAPO", $product->getVirtualColumn('i18n_CHAPO')) + ->set("DESCRIPTION", $product->getVirtualColumn('i18n_DESCRIPTION')) + ->set("POSTSCRIPTUM", $product->getVirtualColumn('i18n_POSTSCRIPTUM')) + ->set("URL", $this->getReturnUrl() ? $product->getUrl($this->locale) : null) + ->set("META_TITLE", $product->getVirtualColumn('i18n_META_TITLE')) + ->set("META_DESCRIPTION", $product->getVirtualColumn('i18n_META_DESCRIPTION')) + ->set("META_KEYWORDS", $product->getVirtualColumn('i18n_META_KEYWORDS')) + ->set("POSITION", $product->getVirtualColumn('position_delegate')) + ->set("VIRTUAL", $product->getVirtual() ? "1" : "0") + ->set("VISIBLE", $product->getVisible() ? "1" : "0") + ->set("TEMPLATE", $product->getTemplateId()) + ->set("DEFAULT_CATEGORY", $defaultCategoryId) + ->set("TAX_RULE_ID", $product->getTaxRuleId()) + ->set("BRAND_ID", $product->getBrandId() ?: 0) + ->set("SHOW_ORIGINAL_PRICE", $display_initial_price); + + $this->findNextPrev($loopResultRow, $product, $defaultCategoryId); + + return $loopResultRow; + } + + /** + * @param LoopResultRow $loopResultRow + * @param ProductModel $product + * @param int $defaultCategoryId + */ + private function findNextPrev(LoopResultRow $loopResultRow, ProductModel $product, $defaultCategoryId) + { + if ($this->getWithPrevNextInfo()) { + $currentPosition = ProductCategoryQuery::create() + ->filterByCategoryId($defaultCategoryId) + ->filterByProductId($product->getId()) + ->findOne()->getPosition(); + + // Find previous and next product + $previousQuery = ProductCategoryQuery::create() + ->filterByCategoryId($defaultCategoryId) + ->filterByPosition($currentPosition, Criteria::LESS_THAN); + + $nextQuery = ProductCategoryQuery::create() + ->filterByCategoryId($defaultCategoryId) + ->filterByPosition($currentPosition, Criteria::GREATER_THAN); + + if (!$this->getBackendContext()) { + $previousQuery->useProductQuery() + ->filterByVisible(true) + ->endUse(); + + $previousQuery->useProductQuery() + ->filterByVisible(true) + ->endUse(); + } + + $previous = $previousQuery + ->orderByPosition(Criteria::DESC) + ->findOne(); + + $next = $nextQuery + ->orderByPosition(Criteria::ASC) + ->findOne(); + + $loopResultRow + ->set("HAS_PREVIOUS", $previous != null ? 1 : 0) + ->set("HAS_NEXT", $next != null ? 1 : 0) + ->set("PREVIOUS", $previous != null ? $previous->getProductId() : -1) + ->set("NEXT", $next != null ? $next->getProductId() : -1); + } + } + + /** + * @param ProductQuery $search + * @param array $feature_availability + * @throws \Propel\Runtime\Exception\PropelException + */ + protected function manageFeatureAv(&$search, $feature_availability) + { + if (null !== $feature_availability) { + foreach ($feature_availability as $feature => $feature_choice) { + foreach ($feature_choice['values'] as $feature_av) { + $featureAlias = 'fa_' . $feature; + if ($feature_av != '*') { + $featureAlias .= '_' . $feature_av; + } + $search->joinFeatureProduct($featureAlias, Criteria::LEFT_JOIN) + ->addJoinCondition($featureAlias, "`$featureAlias`.FEATURE_ID = ?", $feature, null, \PDO::PARAM_INT); + if ($feature_av != '*') { + $search->addJoinCondition($featureAlias, "`$featureAlias`.FEATURE_AV_ID = ?", $feature_av, null, \PDO::PARAM_INT); + } + } + + /* format for mysql */ + $sqlWhereString = $feature_choice['expression']; + if ($sqlWhereString == '*') { + $sqlWhereString = 'NOT ISNULL(`fa_' . $feature . '`.ID)'; + } else { + $sqlWhereString = preg_replace('#([0-9]+)#', 'NOT ISNULL(`fa_' . $feature . '_' . '\1`.ID)', $sqlWhereString); + $sqlWhereString = str_replace('&', ' AND ', $sqlWhereString); + $sqlWhereString = str_replace('|', ' OR ', $sqlWhereString); + } + + $search->where("(" . $sqlWhereString . ")"); + } + } + } + + /** + * @param ProductQuery $search + * @param array $feature_values + * @throws \Propel\Runtime\Exception\PropelException + */ + protected function manageFeatureValue(&$search, $feature_values) + { + if (null !== $feature_values) { + foreach ($feature_values as $feature => $feature_choice) { + $aliasMatches = []; + + foreach ($feature_choice['values'] as $feature_value) { + $featureAlias = 'fv_' . $feature; + if ($feature_value != '*') { + // Generate a unique alias for this value + $featureAlias .= '_' . hash('crc32', $feature_value) . '_' . preg_replace("/[^[:alnum:]_]/", '_', $feature_value); + } + + $search->joinFeatureProduct($featureAlias, Criteria::LEFT_JOIN) + ->addJoinCondition($featureAlias, "`$featureAlias`.FEATURE_ID = ?", $feature, null, \PDO::PARAM_INT); + + if ($feature_value != '*') { + $featureAliasI18n = $featureAlias . '_i18n'; + $featureAliasI18nJoin = $featureAlias . '_i18n_join'; + + $featureAvValueJoin = new Join(); + $featureAvValueJoin->setJoinType(Criteria::LEFT_JOIN); + $featureAvValueJoin->addExplicitCondition( + $featureAlias, + "FEATURE_AV_ID", + null, + FeatureAvI18nTableMap::TABLE_NAME, + 'ID', + $featureAliasI18n + ); + + $search + ->addJoinObject($featureAvValueJoin, $featureAliasI18nJoin) + ->addJoinCondition($featureAliasI18nJoin, "`$featureAliasI18n`.LOCALE = ?", $this->locale, null, \PDO::PARAM_STR) + ->addJoinCondition($featureAliasI18nJoin, "`$featureAliasI18n`.TITLE = ?", $feature_value, null, \PDO::PARAM_STR) + ; + + $aliasMatches[$feature_value] = $featureAliasI18n; + } + } + + /* format for mysql */ + $sqlWhereString = $feature_choice['expression']; + + if ($sqlWhereString == '*') { + $sqlWhereString = 'NOT ISNULL(`fv_' . $feature . '`.ID)'; + } else { + foreach ($aliasMatches as $value => $alias) { + $sqlWhereString = str_replace($value, 'NOT ISNULL(`'.$alias.'`.ID)', $sqlWhereString); + } + $sqlWhereString = str_replace('&', ' AND ', $sqlWhereString); + $sqlWhereString = str_replace('|', ' OR ', $sqlWhereString); + } + + $search->where("(" . $sqlWhereString . ")"); + } + } + } + + /** + * @return \Propel\Runtime\ActiveQuery\ModelCriteria|ProductQuery + * @throws \Propel\Runtime\Exception\PropelException + */ + public function buildModelCriteria() + { + Tlog::getInstance()->debug("-- Starting new product build criteria"); + + $currencyId = $this->getCurrency(); + if (null !== $currencyId) { + $currency = CurrencyQuery::create()->findOneById($currencyId); + if (null === $currency) { + throw new \InvalidArgumentException('Cannot found currency id: `' . $currency . '` in product_sale_elements loop'); + } + } else { + $currency = $this->getCurrentRequest()->getSession()->getCurrency(); + } + + $defaultCurrency = CurrencyModel::getDefaultCurrency(); + $defaultCurrencySuffix = '_default_currency'; + + $priceToCompareAsSQL = ''; + $isPSELeftJoinList = []; + $isProductPriceFirstLeftJoin = []; + + $search = ProductQuery::create(); + + $complex = $this->getComplex(); + + if (! $complex) { + $search->innerJoinProductSaleElements('pse'); + $search->addJoinCondition('pse', '`pse`.IS_DEFAULT=1'); + + $search->innerJoinProductSaleElements('pse_count'); + + $priceJoin = new Join(); + $priceJoin->addExplicitCondition(ProductSaleElementsTableMap::TABLE_NAME, 'ID', 'pse', ProductPriceTableMap::TABLE_NAME, 'PRODUCT_SALE_ELEMENTS_ID', 'price'); + $priceJoin->setJoinType(Criteria::LEFT_JOIN); + + $search->addJoinObject($priceJoin, 'price_join') + ->addJoinCondition('price_join', '`price`.`currency_id` = ?', $currency->getId(), null, \PDO::PARAM_INT); + + if ($defaultCurrency->getId() != $currency->getId()) { + $priceJoinDefaultCurrency = new Join(); + $priceJoinDefaultCurrency->addExplicitCondition(ProductSaleElementsTableMap::TABLE_NAME, 'ID', 'pse', ProductPriceTableMap::TABLE_NAME, 'PRODUCT_SALE_ELEMENTS_ID', 'price' . $defaultCurrencySuffix); + $priceJoinDefaultCurrency->setJoinType(Criteria::LEFT_JOIN); + + $search->addJoinObject($priceJoinDefaultCurrency, 'price_join' . $defaultCurrencySuffix) + ->addJoinCondition('price_join' . $defaultCurrencySuffix, '`price' . $defaultCurrencySuffix . '`.`currency_id` = ?', $defaultCurrency->getId(), null, \PDO::PARAM_INT); + + /** + * rate value is checked as a float in overloaded getRate method. + */ + $priceToCompareAsSQL = 'CASE WHEN ISNULL(`price`.PRICE) OR `price`.FROM_DEFAULT_CURRENCY = 1 THEN + CASE WHEN `pse`.PROMO=1 THEN `price' . $defaultCurrencySuffix . '`.PROMO_PRICE ELSE `price' . $defaultCurrencySuffix . '`.PRICE END * ' . $currency->getRate() . ' + ELSE + CASE WHEN `pse`.PROMO=1 THEN `price`.PROMO_PRICE ELSE `price`.PRICE END + END'; + + $search->withColumn($priceToCompareAsSQL, 'real_price'); + $search->withColumn('CASE WHEN ISNULL(`price`.PRICE) OR `price`.FROM_DEFAULT_CURRENCY = 1 THEN `price' . $defaultCurrencySuffix . '`.PRICE * ' . $currency->getRate() . ' ELSE `price`.PRICE END', 'price'); + $search->withColumn('CASE WHEN ISNULL(`price`.PRICE) OR `price`.FROM_DEFAULT_CURRENCY = 1 THEN `price' . $defaultCurrencySuffix . '`.PROMO_PRICE * ' . $currency->getRate() . ' ELSE `price`.PROMO_PRICE END', 'promo_price'); + } else { + $priceToCompareAsSQL = 'CASE WHEN `pse`.PROMO=1 THEN `price`.PROMO_PRICE ELSE `price`.PRICE END'; + + $search->withColumn($priceToCompareAsSQL, 'real_price'); + $search->withColumn('`price`.PRICE', 'price'); + $search->withColumn('`price`.PROMO_PRICE', 'promo_price'); + } + } + + /* manage translations */ + $this->configureI18nProcessing($search, ['TITLE', 'CHAPO', 'DESCRIPTION', 'POSTSCRIPTUM', 'META_TITLE', 'META_DESCRIPTION', 'META_KEYWORDS']); + + $id = $this->getId(); + + if (!\is_null($id)) { + $search->filterById($id, Criteria::IN); + } + + $ref = $this->getRef(); + + if (!\is_null($ref)) { + $search->filterByRef($ref, Criteria::IN); + } + + $title = $this->getTitle(); + + if (!\is_null($title)) { + $this->addSearchInI18nColumn($search, 'TITLE', Criteria::LIKE, "%".$title."%"); + } + + $templateIdList = $this->getTemplateId(); + + if (!\is_null($templateIdList)) { + $search->filterByTemplateId($templateIdList, Criteria::IN); + } + + $manualOrderAllowed = false; + + if (null !== $categoryDefault = $this->getCategoryDefault()) { + // Select the products which have $categoryDefault as the default category. + $search + ->useProductCategoryQuery('CategorySelect') + ->filterByDefaultCategory(true) + ->filterByCategoryId($categoryDefault, Criteria::IN) + ->endUse() + ; + + // We can only sort by position if we have a single category ID + $manualOrderAllowed = (1 == \count($categoryDefault)); + } elseif (null !== $categoryIdList = $this->getCategory()) { + // Select all products which have one of the required categories as the default one, or an associated one + $depth = $this->getDepth(); + + $allCategoryIDs = CategoryQuery::getCategoryTreeIds($categoryIdList, $depth); + + $search + ->useProductCategoryQuery('CategorySelect') + ->filterByCategoryId($allCategoryIDs, Criteria::IN) + ->endUse() + ; + + // We can only sort by position if we have a single category ID, with a depth of 1 + $manualOrderAllowed = (1 == $depth && 1 == \count($categoryIdList)); + } else { + $search + ->leftJoinProductCategory('CategorySelect') + ->addJoinCondition('CategorySelect', '`CategorySelect`.DEFAULT_CATEGORY = 1') + ; + } + + $search->withColumn( + 'CASE WHEN ISNULL(`CategorySelect`.POSITION) THEN ' . PHP_INT_MAX . ' ELSE CAST(`CategorySelect`.POSITION as SIGNED) END', + 'position_delegate' + ); + $search->withColumn('`CategorySelect`.CATEGORY_ID', 'default_category_id'); + $search->withColumn('`CategorySelect`.DEFAULT_CATEGORY', 'is_default_category'); + + $current = $this->getCurrent(); + + if ($current === true) { + $search->filterById($this->getCurrentRequest()->get("product_id"), Criteria::EQUAL); + } elseif ($current === false) { + $search->filterById($this->getCurrentRequest()->get("product_id"), Criteria::NOT_IN); + } + + $brand_id = $this->getBrand(); + + if ($brand_id !== null) { + $search->filterByBrandId($brand_id, Criteria::IN); + } + + $contentId = $this->getContent(); + + if ($contentId != null) { + $search->useProductAssociatedContentQuery() + ->filterByContentId($contentId, Criteria::IN) + ->endUse() + ; + } + + $sale_id = $this->getSale(); + + if ($sale_id !== null) { + $search->useSaleProductQuery("SaleProductSelect") + ->filterBySaleId($sale_id) + ->groupByProductId() + ->endUse() + ; + } + + $current_category = $this->getCurrentCategory(); + + if ($current_category === true) { + $search->filterByCategory( + CategoryQuery::create()->filterByProduct( + ProductCategoryQuery::create()->findPk($this->getCurrentRequest()->get("product_id")), + Criteria::IN + )->find(), + Criteria::IN + ); + } elseif ($current_category === false) { + $search->filterByCategory( + CategoryQuery::create()->filterByProduct( + ProductCategoryQuery::create()->findPk($this->getCurrentRequest()->get("product_id")), + Criteria::IN + )->find(), + Criteria::NOT_IN + ); + } + + $visible = $this->getVisible(); + + if ($visible !== Type\BooleanOrBothType::ANY) { + $search->filterByVisible($visible ? 1 : 0); + } + + $virtual = $this->getVirtual(); + + if ($virtual !== Type\BooleanOrBothType::ANY) { + $search->filterByVirtual($virtual ? 1 : 0); + } + + $exclude = $this->getExclude(); + + if (!\is_null($exclude)) { + $search->filterById($exclude, Criteria::NOT_IN); + } + + $exclude_category = $this->getExcludeCategory(); + + if (!\is_null($exclude_category)) { + $search + ->useProductCategoryQuery('ExcludeCategorySelect') + ->filterByCategoryId($exclude_category, Criteria::NOT_IN) + ->endUse() + ; + } + + if (null !== $taxRuleIdList = $this->getTaxRuleId()) { + $search->filterByTaxRuleId($taxRuleIdList, Criteria::IN); + } + + if (null !== $taxRuleIdList = $this->getExcludeTaxRuleId()) { + $search->filterByTaxRuleId($taxRuleIdList, Criteria::NOT_IN); + } + + $new = $this->getNew(); + $promo = $this->getPromo(); + $min_stock = $this->getMinStock(); + $min_weight = $this->getMinWeight(); + $max_weight = $this->getMaxWeight(); + $min_price = $this->getMinPrice(); + $max_price = $this->getMaxPrice(); + + if ($complex) { + if ($new === true) { + $isPSELeftJoinList[] = 'is_new'; + $search->joinProductSaleElements('is_new', Criteria::LEFT_JOIN) + ->where('`is_new`.NEWNESS' . Criteria::EQUAL . '1') + ->where('NOT ISNULL(`is_new`.ID)'); + } elseif ($new === false) { + $isPSELeftJoinList[] = 'is_new'; + $search->joinProductSaleElements('is_new', Criteria::LEFT_JOIN) + ->where('`is_new`.NEWNESS' . Criteria::EQUAL . '0') + ->where('NOT ISNULL(`is_new`.ID)'); + } + + if ($promo === true) { + $isPSELeftJoinList[] = 'is_promo'; + $search->joinProductSaleElements('is_promo', Criteria::LEFT_JOIN) + ->where('`is_promo`.PROMO' . Criteria::EQUAL . '1') + ->where('NOT ISNULL(`is_promo`.ID)'); + } elseif ($promo === false) { + $isPSELeftJoinList[] = 'is_promo'; + $search->joinProductSaleElements('is_promo', Criteria::LEFT_JOIN) + ->where('`is_promo`.PROMO' . Criteria::EQUAL . '0') + ->where('NOT ISNULL(`is_promo`.ID)'); + } + + if (null != $min_stock) { + $isPSELeftJoinList[] = 'is_min_stock'; + $search->joinProductSaleElements('is_min_stock', Criteria::LEFT_JOIN) + ->where('`is_min_stock`.QUANTITY' . Criteria::GREATER_EQUAL . '?', $min_stock, \PDO::PARAM_INT) + ->where('NOT ISNULL(`is_min_stock`.ID)'); + } + + if (null != $min_weight) { + $isPSELeftJoinList[] = 'is_min_weight'; + $search->joinProductSaleElements('is_min_weight', Criteria::LEFT_JOIN) + ->where('`is_min_weight`.WEIGHT' . Criteria::GREATER_EQUAL . '?', $min_weight, \PDO::PARAM_STR) + ->where('NOT ISNULL(`is_min_weight`.ID)'); + } + + if (null != $max_weight) { + $isPSELeftJoinList[] = 'is_max_weight'; + $search->joinProductSaleElements('is_max_weight', Criteria::LEFT_JOIN) + ->where('`is_max_weight`.WEIGHT' . Criteria::LESS_EQUAL . '?', $max_weight, \PDO::PARAM_STR) + ->where('NOT ISNULL(`is_max_weight`.ID)'); + } + + $attributeNonStrictMatch = $this->getAttributeNonStrictMatch(); + + if ($attributeNonStrictMatch != '*') { + if ($attributeNonStrictMatch == 'none') { + $actuallyUsedAttributeNonStrictMatchList = $isPSELeftJoinList; + } else { + $actuallyUsedAttributeNonStrictMatchList = array_values(array_intersect($isPSELeftJoinList, $attributeNonStrictMatch)); + } + + foreach ($actuallyUsedAttributeNonStrictMatchList as $key => $actuallyUsedAttributeNonStrictMatch) { + if ($key == 0) { + continue; + } + $search->where('`' . $actuallyUsedAttributeNonStrictMatch . '`.ID=' . '`' . $actuallyUsedAttributeNonStrictMatchList[$key-1] . '`.ID'); + } + } + + if (null !== $min_price) { + if (false === ConfigQuery::useTaxFreeAmounts()) { + // @todo + } + + $isPSELeftJoinList[] = 'is_min_price'; + $isProductPriceFirstLeftJoin = ['is_min_price', 'min_price_data']; + + $minPriceJoin = new Join(); + $minPriceJoin->addExplicitCondition(ProductSaleElementsTableMap::TABLE_NAME, 'ID', 'is_min_price', ProductPriceTableMap::TABLE_NAME, 'PRODUCT_SALE_ELEMENTS_ID', 'min_price_data'); + $minPriceJoin->setJoinType(Criteria::LEFT_JOIN); + + $search->joinProductSaleElements('is_min_price', Criteria::LEFT_JOIN) + ->addJoinObject($minPriceJoin, 'is_min_price_join') + ->addJoinCondition('is_min_price_join', '`min_price_data`.`currency_id` = ?', $currency->getId(), null, \PDO::PARAM_INT); + + if ($defaultCurrency->getId() != $currency->getId()) { + $minPriceJoinDefaultCurrency = new Join(); + $minPriceJoinDefaultCurrency->addExplicitCondition(ProductSaleElementsTableMap::TABLE_NAME, 'ID', 'is_min_price', ProductPriceTableMap::TABLE_NAME, 'PRODUCT_SALE_ELEMENTS_ID', 'min_price_data' . $defaultCurrencySuffix); + $minPriceJoinDefaultCurrency->setJoinType(Criteria::LEFT_JOIN); + + $search->addJoinObject($minPriceJoinDefaultCurrency, 'is_min_price_join' . $defaultCurrencySuffix) + ->addJoinCondition('is_min_price_join' . $defaultCurrencySuffix, '`min_price_data' . $defaultCurrencySuffix . '`.`currency_id` = ?', $defaultCurrency->getId(), null, \PDO::PARAM_INT); + + /** + * In propel we trust : $currency->getRate() always returns a float. + * Or maybe not : rate value is checked as a float in overloaded getRate method. + */ + $MinPriceToCompareAsSQL = 'CASE WHEN ISNULL(CASE WHEN `is_min_price`.PROMO=1 THEN `min_price_data`.PROMO_PRICE ELSE `min_price_data`.PRICE END) OR `min_price_data`.FROM_DEFAULT_CURRENCY = 1 THEN + CASE WHEN `is_min_price`.PROMO=1 THEN `min_price_data' . $defaultCurrencySuffix . '`.PROMO_PRICE ELSE `min_price_data' . $defaultCurrencySuffix . '`.PRICE END * ' . $currency->getRate() . ' + ELSE + CASE WHEN `is_min_price`.PROMO=1 THEN `min_price_data`.PROMO_PRICE ELSE `min_price_data`.PRICE END + END'; + } else { + $MinPriceToCompareAsSQL = 'CASE WHEN `is_min_price`.PROMO=1 THEN `min_price_data`.PROMO_PRICE ELSE `min_price_data`.PRICE END'; + } + + $search->where($MinPriceToCompareAsSQL . ' >= ?', $min_price, \PDO::PARAM_STR); + } + + if (null !== $max_price) { + $isPSELeftJoinList[] = 'is_max_price'; + $isProductPriceFirstLeftJoin = ['is_max_price', 'max_price_data']; + + $maxPriceJoin = new Join(); + $maxPriceJoin->addExplicitCondition(ProductSaleElementsTableMap::TABLE_NAME, 'ID', 'is_max_price', ProductPriceTableMap::TABLE_NAME, 'PRODUCT_SALE_ELEMENTS_ID', 'max_price_data'); + $maxPriceJoin->setJoinType(Criteria::LEFT_JOIN); + + $search->joinProductSaleElements('is_max_price', Criteria::LEFT_JOIN) + ->addJoinObject($maxPriceJoin, 'is_max_price_join') + ->addJoinCondition('is_max_price_join', '`max_price_data`.`currency_id` = ?', $currency->getId(), null, \PDO::PARAM_INT); + + if ($defaultCurrency->getId() != $currency->getId()) { + $maxPriceJoinDefaultCurrency = new Join(); + $maxPriceJoinDefaultCurrency->addExplicitCondition(ProductSaleElementsTableMap::TABLE_NAME, 'ID', 'is_max_price', ProductPriceTableMap::TABLE_NAME, 'PRODUCT_SALE_ELEMENTS_ID', 'max_price_data' . $defaultCurrencySuffix); + $maxPriceJoinDefaultCurrency->setJoinType(Criteria::LEFT_JOIN); + + $search->addJoinObject($maxPriceJoinDefaultCurrency, 'is_max_price_join' . $defaultCurrencySuffix) + ->addJoinCondition('is_max_price_join' . $defaultCurrencySuffix, '`max_price_data' . $defaultCurrencySuffix . '`.`currency_id` = ?', $defaultCurrency->getId(), null, \PDO::PARAM_INT); + + /** + * In propel we trust : $currency->getRate() always returns a float. + * Or maybe not : rate value is checked as a float in overloaded getRate method. + */ + $MaxPriceToCompareAsSQL = 'CASE WHEN ISNULL(CASE WHEN `is_max_price`.PROMO=1 THEN `max_price_data`.PROMO_PRICE ELSE `max_price_data`.PRICE END) OR `min_price_data`.FROM_DEFAULT_CURRENCY = 1 THEN + CASE WHEN `is_max_price`.PROMO=1 THEN `max_price_data' . $defaultCurrencySuffix . '`.PROMO_PRICE ELSE `max_price_data' . $defaultCurrencySuffix . '`.PRICE END * ' . $currency->getRate() . ' + ELSE + CASE WHEN `is_max_price`.PROMO=1 THEN `max_price_data`.PROMO_PRICE ELSE `max_price_data`.PRICE END + END'; + } else { + $MaxPriceToCompareAsSQL = 'CASE WHEN `is_max_price`.PROMO=1 THEN `max_price_data`.PROMO_PRICE ELSE `max_price_data`.PRICE END'; + } + + $search->where($MaxPriceToCompareAsSQL . '<=?', $max_price, \PDO::PARAM_STR); + } + + /* + * for ordering and outputs, the product will be : + * - new if at least one the criteria matching PSE is new + * - in promo if at least one the criteria matching PSE is in promo + */ + + /* if we don't have any join yet, let's make a global one */ + if (empty($isProductPriceFirstLeftJoin)) { + if (\count($isPSELeftJoinList) == 0) { + $joiningTable = "global"; + $isPSELeftJoinList[] = $joiningTable; + $search->joinProductSaleElements('global', Criteria::LEFT_JOIN); + } else { + $joiningTable = $isPSELeftJoinList[0]; + } + + $isProductPriceFirstLeftJoin = [$joiningTable, 'global_price_data']; + + $globalPriceJoin = new Join(); + $globalPriceJoin->addExplicitCondition(ProductSaleElementsTableMap::TABLE_NAME, 'ID', $joiningTable, ProductPriceTableMap::TABLE_NAME, 'PRODUCT_SALE_ELEMENTS_ID', 'global_price_data'); + $globalPriceJoin->setJoinType(Criteria::LEFT_JOIN); + + $search->addJoinObject($globalPriceJoin, 'global_price_join') + ->addJoinCondition('global_price_join', '`global_price_data`.`currency_id` = ?', $currency->getId(), null, \PDO::PARAM_INT); + + if ($defaultCurrency->getId() != $currency->getId()) { + $globalPriceJoinDefaultCurrency = new Join(); + $globalPriceJoinDefaultCurrency->addExplicitCondition(ProductSaleElementsTableMap::TABLE_NAME, 'ID', $joiningTable, ProductPriceTableMap::TABLE_NAME, 'PRODUCT_SALE_ELEMENTS_ID', 'global_price_data' . $defaultCurrencySuffix); + $globalPriceJoinDefaultCurrency->setJoinType(Criteria::LEFT_JOIN); + $search->addJoinObject($globalPriceJoinDefaultCurrency, 'global_price_join' . $defaultCurrencySuffix) + ->addJoinCondition('global_price_join' . $defaultCurrencySuffix, '`global_price_data' . $defaultCurrencySuffix . '`.`currency_id` = ?', $defaultCurrency->getId(), null, \PDO::PARAM_INT); + } + } + + /* + * we need to test all promo field from our previous conditions. Indeed ie: + * product P0, attributes color : red + * P0red is in promo and is the only attribute combinaton availability. + * so the product might be consider as in promo (in outputs and ordering) + * We got the following loop to display in promo AND new product but we don't care it's the same attribute which is new and in promo : + * {loop type="product" promo="1" new="1" attribute_non_strict_match="promo,new"} {/loop} + * our request will so far returns 1 line + * + * is_promo.ID | is_promo.PROMO | is_promo.NEWNESS | is_new.ID | is_new.PROMO | is_new.NEWNESS + * NULL NULL NULL red_id 1 0 + * + * So that we can say the product is in global promo only with is_promo.PROMO, we must acknowledge it with (is_promo.PROMO OR is_new.PROMO) + */ + $booleanMatchedPromoList = []; + $booleanMatchedNewnessList = []; + + foreach ($isPSELeftJoinList as $isPSELeftJoin) { + $booleanMatchedPromoList[] = '`' . $isPSELeftJoin . '`.PROMO'; + $booleanMatchedNewnessList[] = '`' . $isPSELeftJoin . '`.NEWNESS'; + } + + $search->withColumn('(' . implode(' OR ', $booleanMatchedPromoList) . ')', 'main_product_is_promo'); + $search->withColumn('(' . implode(' OR ', $booleanMatchedNewnessList) . ')', 'main_product_is_new'); + + $booleanMatchedPrice = + 'CASE WHEN `' . $isProductPriceFirstLeftJoin[0] . '`.PROMO=1 THEN `' + . $isProductPriceFirstLeftJoin[1] . '`.PROMO_PRICE ELSE `' + . $isProductPriceFirstLeftJoin[1] . '`.PRICE END'; + $booleanMatchedPriceDefaultCurrency = 'CASE WHEN `' . $isProductPriceFirstLeftJoin[0] . '`.PROMO=1 THEN `' . $isProductPriceFirstLeftJoin[1] . $defaultCurrencySuffix . '`.PROMO_PRICE ELSE `' . $isProductPriceFirstLeftJoin[1] . $defaultCurrencySuffix . '`.PRICE END'; + + if ($defaultCurrency->getId() != $currency->getId()) { + /** + * In propel we trust : $currency->getRate() always returns a float. + * Or maybe not : rate value is checked as a float in overloaded getRate method. + */ + $priceToCompareAsSQL = + 'CASE WHEN ISNULL(' . $booleanMatchedPrice .') THEN ' + . $booleanMatchedPriceDefaultCurrency . ' * ' . $currency->getRate() + . ' ELSE ' . $booleanMatchedPrice . ' END'; + } else { + $priceToCompareAsSQL = $booleanMatchedPrice; + } + + $search->withColumn('MAX(' . $priceToCompareAsSQL . ')', 'real_highest_price'); + $search->withColumn('MIN(' . $priceToCompareAsSQL . ')', 'real_lowest_price'); + } else { + if ($new === true) { + $search->where('`pse`.NEWNESS' . Criteria::EQUAL . '1'); + } elseif ($new === false) { + $search->where('`pse`.NEWNESS' . Criteria::EQUAL . '0'); + } + + if ($promo === true) { + $search->where('`pse`.PROMO' . Criteria::EQUAL . '1'); + } elseif ($promo === false) { + $search->where('`pse`.PROMO' . Criteria::EQUAL . '0'); + } + + if (null != $min_stock) { + $search->where('`pse`.QUANTITY' . Criteria::GREATER_EQUAL . '?', $min_stock, \PDO::PARAM_INT); + } + + if (null != $min_weight) { + $search->where('`pse`.WEIGHT' . Criteria::GREATER_EQUAL . '?', $min_weight, \PDO::PARAM_STR); + } + + if (null != $max_weight) { + $search->where('`is_max_weight`.WEIGHT' . Criteria::LESS_EQUAL . '?', $max_weight, \PDO::PARAM_STR); + } + + if (null !== $min_price) { + if (false === ConfigQuery::useTaxFreeAmounts()) { + // @todo + } + + $search->where($priceToCompareAsSQL . '>=?', $min_price, \PDO::PARAM_STR); + } + + if (null !== $max_price) { + if (false === ConfigQuery::useTaxFreeAmounts()) { + // @todo + } + + $search->where($priceToCompareAsSQL . '<=?', $max_price, \PDO::PARAM_STR); + } + } + + // First join sale_product table... + $search + ->leftJoinSaleProduct('SaleProductPriceDisplay') + ; + + // ... then the sale table... + $salesJoin = new Join(); + $salesJoin->addExplicitCondition( + 'SaleProductPriceDisplay', + 'SALE_ID', + null, + SaleTableMap::TABLE_NAME, + 'ID', + 'SalePriceDisplay' + ); + $salesJoin->setJoinType(Criteria::LEFT_JOIN); + + $search + ->addJoinObject($salesJoin, 'SalePriceDisplay') + ->addJoinCondition('SalePriceDisplay', '`SalePriceDisplay`.`active` = 1'); + + + // ... to get the DISPLAY_INITIAL_PRICE column ! + $search->withColumn('`SalePriceDisplay`.DISPLAY_INITIAL_PRICE', 'display_initial_price'); + + $feature_availability = $this->getFeatureAvailability(); + + $this->manageFeatureAv($search, $feature_availability); + + $feature_values = $this->getFeatureValues(); + + $this->manageFeatureValue($search, $feature_values); + + $search->groupBy(ProductTableMap::COL_ID); + + if (! $complex) { + $search->withColumn('`pse`.ID', 'pse_id'); + + $search->withColumn('`pse`.NEWNESS', 'is_new'); + $search->withColumn('`pse`.PROMO', 'is_promo'); + $search->withColumn('`pse`.QUANTITY', 'quantity'); + $search->withColumn('`pse`.WEIGHT', 'weight'); + $search->withColumn('`pse`.EAN_CODE', 'ean_code'); + + $search->withColumn('COUNT(`pse_count`.ID)', 'pse_count'); + } + + $orders = $this->getOrder(); + + foreach ($orders as $order) { + switch ($order) { + case "id": + $search->orderById(Criteria::ASC); + break; + case "id_reverse": + $search->orderById(Criteria::DESC); + break; + case "alpha": + $search->addAscendingOrderByColumn('i18n_TITLE'); + break; + case "alpha_reverse": + $search->addDescendingOrderByColumn('i18n_TITLE'); + break; + case "min_price": + if ($complex) { + $search->addAscendingOrderByColumn('real_lowest_price'); + } else { + $search->addAscendingOrderByColumn('real_price'); + } + break; + case "max_price": + if ($complex) { + $search->addDescendingOrderByColumn('real_lowest_price'); + } else { + $search->addDescendingOrderByColumn('real_price'); + } + break; + case "manual": + if (! $manualOrderAllowed) { + throw new \InvalidArgumentException('Manual order require a *single* category ID or category_default ID, and a depth <= 1'); + } + $search->addAscendingOrderByColumn('position_delegate'); + break; + case "manual_reverse": + if (! $manualOrderAllowed) { + throw new \InvalidArgumentException('Manual reverse order require a *single* category ID or category_default ID, and a depth <= 1'); + } + $search->addDescendingOrderByColumn('position_delegate'); + break; + case "ref": + $search->orderByRef(Criteria::ASC); + break; + case "ref_reverse": + $search->orderByRef(Criteria::DESC); + break; + case "visible": + $search->orderByVisible(Criteria::ASC); + break; + case "visible_reverse": + $search->orderByVisible(Criteria::DESC); + break; + case "promo": + if ($complex) { + $search->addDescendingOrderByColumn('main_product_is_promo'); + } else { + $search->addDescendingOrderByColumn('is_promo'); + } + break; + case "new": + if ($complex) { + $search->addDescendingOrderByColumn('main_product_is_new'); + } else { + $search->addDescendingOrderByColumn('is_new'); + } + 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 "position": + $search->addAscendingOrderByColumn('position_delegate'); + break; + case "position_reverse": + $search->addDescendingOrderByColumn('position_delegate'); + break; + case "given_id": + if (null === $id) { + throw new \InvalidArgumentException('Given_id order cannot be set without `id` argument'); + } + foreach ($id as $singleId) { + $givenIdMatched = 'given_id_matched_' . $singleId; + $search->withColumn(ProductTableMap::COL_ID . "='$singleId'", $givenIdMatched); + $search->orderBy($givenIdMatched, Criteria::DESC); + } + break; + case "random": + $search->clearOrderByColumns(); + $search->addAscendingOrderByColumn('RAND()'); + break(2); + } + } + + return $search; + } + + /** + * Get the default category id for a product + * + * @param \Thelia\Model\Product $product + * @return null|int + * @throws \Propel\Runtime\Exception\PropelException + */ + protected function getDefaultCategoryId($product) + { + $defaultCategoryId = null; + if ((bool) $product->getVirtualColumn('is_default_category')) { + $defaultCategoryId = $product->getVirtualColumn('default_category_id'); + } else { + $defaultCategoryId = $product->getDefaultCategoryId(); + } + return $defaultCategoryId; + } +} diff --git a/core/lib/Thelia/Core/Template/Loop/ProductSaleElements.php b/core/lib/Thelia/Core/Template/Loop/ProductSaleElements.php new file mode 100644 index 00000000..60e7958f --- /dev/null +++ b/core/lib/Thelia/Core/Template/Loop/ProductSaleElements.php @@ -0,0 +1,333 @@ + + * + * {@inheritdoc} + * @method int[] getId() + * @method int getCurrency() + * @method int getProduct() + * @method bool getPromo() + * @method bool getNew() + * @method bool getDefault() + * @method string getRef() + * @method int[] getAttributeAvailability() + * @method string[] getOrder() + * @method bool|string getVisible() + */ +class ProductSaleElements extends BaseLoop implements PropelSearchLoopInterface, SearchLoopInterface +{ + protected $timestampable = true; + + /** + * @return ArgumentCollection + */ + protected function getArgDefinitions() + { + return new ArgumentCollection( + Argument::createIntListTypeArgument('id'), + Argument::createIntTypeArgument('currency'), + Argument::createIntTypeArgument('product'), + Argument::createBooleanTypeArgument('promo'), + Argument::createBooleanTypeArgument('new'), + Argument::createBooleanTypeArgument('default'), + Argument::createBooleanOrBothTypeArgument('visible', Type\BooleanOrBothType::ANY), + Argument::createAnyTypeArgument('ref'), + new Argument( + 'attribute_availability', + new TypeCollection( + new Type\IntToCombinedIntsListType() + ) + ), + new Argument( + 'order', + new TypeCollection( + new Type\EnumListType( + array( + 'id', 'id_reverse', + 'ref', 'ref_reverse', + 'quantity', 'quantity_reverse', + 'min_price', 'max_price', + 'promo', 'new', + 'weight', 'weight_reverse', + 'created', 'created_reverse', + 'updated', 'updated_reverse', + 'random' + ) + ) + ), + 'random' + ) + ); + } + + public function buildModelCriteria() + { + $search = ProductSaleElementsQuery::create(); + + $id = $this->getId(); + $product = $this->getProduct(); + $ref = $this->getRef(); + + if (!\is_null($id)) { + $search->filterById($id, Criteria::IN); + } + + if (!\is_null($product)) { + $search->filterByProductId($product, Criteria::EQUAL); + } + + if (!\is_null($ref)) { + $search->filterByRef($ref, Criteria::EQUAL); + } + + $promo = $this->getPromo(); + + if (null !== $promo) { + $search->filterByPromo($promo); + } + + $new = $this->getNew(); + + if (null !== $new) { + $search->filterByNewness($new); + } + + $visible = $this->getVisible(); + + if (Type\BooleanOrBothType::ANY !== $visible) { + $search->useProductQuery() + ->filterByVisible($visible) + ->endUse(); + } + + $default = $this->getDefault(); + + if (null !== $default) { + $search->filterByIsDefault($default); + } + + $orders = $this->getOrder(); + + foreach ($orders as $order) { + switch ($order) { + case "id": + $search->orderById(Criteria::ASC); + break; + case "id_reverse": + $search->orderById(Criteria::DESC); + break; + case "ref": + $search->orderByRef(Criteria::ASC); + break; + case "ref_reverse": + $search->orderByRef(Criteria::DESC); + break; + case "quantity": + $search->orderByQuantity(Criteria::ASC); + break; + case "quantity_reverse": + $search->orderByQuantity(Criteria::DESC); + break; + case "min_price": + $search->addAscendingOrderByColumn('price_FINAL_PRICE'); + break; + case "max_price": + $search->addDescendingOrderByColumn('price_FINAL_PRICE'); + break; + case "promo": + $search->orderByPromo(Criteria::DESC); + break; + case "new": + $search->orderByNewness(Criteria::DESC); + break; + case "weight": + $search->orderByWeight(Criteria::ASC); + break; + case "weight_reverse": + $search->orderByWeight(Criteria::DESC); + 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": + $search->clearOrderByColumns(); + $search->addAscendingOrderByColumn('RAND()'); + break(2); + } + } + + $currencyId = $this->getCurrency(); + if (null !== $currencyId) { + $currency = CurrencyQuery::create()->findPk($currencyId); + if (null === $currency) { + throw new \InvalidArgumentException('Cannot found currency id: `' . $currency . '` in product_sale_elements loop'); + } + } else { + $currency = $this->getCurrentRequest()->getSession()->getCurrency(); + } + + $defaultCurrency = CurrencyModel::getDefaultCurrency(); + $defaultCurrencySuffix = '_default_currency'; + + $search->joinProductPrice('price', Criteria::LEFT_JOIN) + ->addJoinCondition('price', '`price`.`currency_id` = ?', $currency->getId(), null, \PDO::PARAM_INT); + + $search->joinProductPrice('price' . $defaultCurrencySuffix, Criteria::LEFT_JOIN) + ->addJoinCondition('price_default_currency', '`price' . $defaultCurrencySuffix . '`.`currency_id` = ?', $defaultCurrency->getId(), null, \PDO::PARAM_INT); + + /** + * rate value is checked as a float in overloaded getRate method. + */ + $priceSelectorAsSQL = 'CASE WHEN ISNULL(`price`.PRICE) OR `price`.FROM_DEFAULT_CURRENCY = 1 THEN `price_default_currency`.PRICE * ' . $currency->getRate() . ' ELSE `price`.PRICE END'; + $promoPriceSelectorAsSQL = 'CASE WHEN ISNULL(`price`.PRICE) OR `price`.FROM_DEFAULT_CURRENCY = 1 THEN `price_default_currency`.PROMO_PRICE * ' . $currency->getRate() . ' ELSE `price`.PROMO_PRICE END'; + $search->withColumn($priceSelectorAsSQL, 'price_PRICE') + ->withColumn($promoPriceSelectorAsSQL, 'price_PROMO_PRICE') + ->withColumn('CASE WHEN ' . ProductSaleElementsTableMap::COL_PROMO . ' = 1 THEN ' . $promoPriceSelectorAsSQL . ' ELSE ' . $priceSelectorAsSQL . ' END', 'price_FINAL_PRICE'); + + $search->groupById(); + + return $search; + } + + public function parseResults(LoopResult $loopResult) + { + $taxCountry = $this->container->get('thelia.taxEngine')->getDeliveryCountry(); + /** @var \Thelia\Core\Security\SecurityContext $securityContext */ + $securityContext = $this->container->get('thelia.securityContext'); + $discount = 0; + + if ($securityContext->hasCustomerUser() && $securityContext->getCustomerUser()->getDiscount() > 0) { + $discount = $securityContext->getCustomerUser()->getDiscount(); + } + + /** @var \Thelia\Model\ProductSaleElements $PSEValue */ + foreach ($loopResult->getResultDataCollection() as $PSEValue) { + $loopResultRow = new LoopResultRow($PSEValue); + + $price = $PSEValue->getPrice('price_PRICE', $discount); + try { + $taxedPrice = $PSEValue->getTaxedPrice( + $taxCountry, + 'price_PRICE', + $discount + ); + } catch (TaxEngineException $e) { + $taxedPrice = null; + } + + $promoPrice = $PSEValue->getPromoPrice('price_PROMO_PRICE', $discount); + try { + $taxedPromoPrice = $PSEValue->getTaxedPromoPrice( + $taxCountry, + 'price_PROMO_PRICE', + $discount + ); + } catch (TaxEngineException $e) { + $taxedPromoPrice = null; + } + + $loopResultRow + ->set("ID", $PSEValue->getId()) + ->set("QUANTITY", $PSEValue->getQuantity()) + ->set("IS_PROMO", $PSEValue->getPromo() === 1 ? 1 : 0) + ->set("IS_NEW", $PSEValue->getNewness() === 1 ? 1 : 0) + ->set("IS_DEFAULT", $PSEValue->getIsDefault() ? 1 : 0) + ->set("WEIGHT", $PSEValue->getWeight()) + ->set("REF", $PSEValue->getRef()) + ->set("EAN_CODE", $PSEValue->getEanCode()) + ->set("PRODUCT_ID", $PSEValue->getProductId()) + ->set("PRICE", $price) + ->set("PRICE_TAX", $taxedPrice - $price) + ->set("TAXED_PRICE", $taxedPrice) + ->set("PROMO_PRICE", $promoPrice) + ->set("PROMO_PRICE_TAX", $taxedPromoPrice - $promoPrice) + ->set("TAXED_PROMO_PRICE", $taxedPromoPrice); + + $this->addOutputFields($loopResultRow, $PSEValue); + $loopResult->addRow($loopResultRow); + } + + return $loopResult; + } + + /** + * @return array of available field to search in + */ + public function getSearchIn() + { + return [ + "ref", + "ean_code" + ]; + } + + /** + * @param ProductSaleElementsQuery $search + * @param $searchTerm + * @param $searchIn + * @param $searchCriteria + */ + public function doSearch(&$search, $searchTerm, $searchIn, $searchCriteria) + { + $search->_and(); + + foreach ($searchIn as $index => $searchInElement) { + if ($index > 0) { + $search->_or(); + } + switch ($searchInElement) { + case "ref": + $search->filterByRef($searchTerm, $searchCriteria); + break; + case "ean_code": + $search->filterByEanCode($searchTerm, $searchCriteria); + break; + } + } + } +} diff --git a/core/lib/Thelia/Core/Template/Loop/ProductSaleElementsDocument.php b/core/lib/Thelia/Core/Template/Loop/ProductSaleElementsDocument.php new file mode 100644 index 00000000..9a72a9b2 --- /dev/null +++ b/core/lib/Thelia/Core/Template/Loop/ProductSaleElementsDocument.php @@ -0,0 +1,145 @@ + + * + * {@inheritdoc} + * @method int[] getId() + * @method int[] getProductSaleElementsId() + * @method int[] getProductDocumentId() + * @method string[] getOrder() + */ +class ProductSaleElementsDocument extends BaseLoop implements PropelSearchLoopInterface +{ + /** + * @param LoopResult $loopResult + * + * @return LoopResult + */ + public function parseResults(LoopResult $loopResult) + { + /** @var \Thelia\Model\ProductSaleElementsProductDocument $productSaleElementDocument */ + foreach ($loopResult->getResultDataCollection() as $productSaleElementDocument) { + $row = new LoopResultRow($productSaleElementDocument); + + $row + ->set("ID", $productSaleElementDocument->getId()) + ->set("PRODUCT_SALE_ELEMENTS_ID", $productSaleElementDocument->getProductSaleElementsId()) + ->set("PRODUCT_DOCUMENT_ID", $productSaleElementDocument->getProductDocumentId()) + ; + + $this->addOutputFields($row, $productSaleElementDocument); + $loopResult->addRow($row); + } + + return $loopResult; + } + + /** + * Definition of loop arguments + * + * example : + * + * public function getArgDefinitions() + * { + * return new ArgumentCollection( + * + * Argument::createIntListTypeArgument('id'), + * new Argument( + * 'ref', + * new TypeCollection( + * new Type\AlphaNumStringListType() + * ) + * ), + * Argument::createIntListTypeArgument('category'), + * Argument::createBooleanTypeArgument('new'), + * ... + * ); + * } + * + * @return \Thelia\Core\Template\Loop\Argument\ArgumentCollection + */ + protected function getArgDefinitions() + { + return new ArgumentCollection( + Argument::createIntListTypeArgument("id"), + Argument::createIntListTypeArgument("product_sale_elements_id"), + Argument::createIntListTypeArgument("product_document_id"), + Argument::createEnumListTypeArgument( + "order", + [ + "position", + "position-reverse" + ], + "position" + ) + ); + } + + /** + * this method returns a Propel ModelCriteria + * + * @return \Propel\Runtime\ActiveQuery\ModelCriteria + */ + public function buildModelCriteria() + { + $query = ProductSaleElementsProductDocumentQuery::create(); + + if (null !== $id = $this->getId()) { + $query->filterById($id); + } + + if (null !== $pseId = $this->getProductSaleElementsId()) { + $query->filterByProductSaleElementsId($pseId); + } + + if (null !== $productDocumentId = $this->getProductDocumentId()) { + $query->filterByProductDocumentId($id); + } + + foreach ($this->getOrder() as $order) { + switch ($order) { + case "position": + $query + ->useProductDocumentQuery() + ->orderByPosition(Criteria::ASC) + ->endUse() + ; + break; + + case "position-reverse": + $query + ->useProductDocumentQuery() + ->orderByPosition(Criteria::DESC) + ->endUse() + ; + break; + } + } + + return $query; + } +} diff --git a/core/lib/Thelia/Core/Template/Loop/ProductSaleElementsImage.php b/core/lib/Thelia/Core/Template/Loop/ProductSaleElementsImage.php new file mode 100644 index 00000000..45d34667 --- /dev/null +++ b/core/lib/Thelia/Core/Template/Loop/ProductSaleElementsImage.php @@ -0,0 +1,145 @@ + + * + * {@inheritdoc} + * @method int[] getId() + * @method int[] getProductSaleElementsId() + * @method int[] getProductImageId() + * @method string[] getOrder() + */ +class ProductSaleElementsImage extends BaseLoop implements PropelSearchLoopInterface +{ + /** + * @param LoopResult $loopResult + * + * @return LoopResult + */ + public function parseResults(LoopResult $loopResult) + { + /** @var \Thelia\Model\ProductSaleElementsProductImage $productSaleElementImage */ + foreach ($loopResult->getResultDataCollection() as $productSaleElementImage) { + $row = new LoopResultRow($productSaleElementImage); + + $row + ->set("ID", $productSaleElementImage->getId()) + ->set("PRODUCT_SALE_ELEMENTS_ID", $productSaleElementImage->getProductSaleElementsId()) + ->set("PRODUCT_IMAGE_ID", $productSaleElementImage->getProductImageId()) + ; + + $this->addOutputFields($row, $productSaleElementImage); + $loopResult->addRow($row); + } + + return $loopResult; + } + + /** + * Definition of loop arguments + * + * example : + * + * public function getArgDefinitions() + * { + * return new ArgumentCollection( + * + * Argument::createIntListTypeArgument('id'), + * new Argument( + * 'ref', + * new TypeCollection( + * new Type\AlphaNumStringListType() + * ) + * ), + * Argument::createIntListTypeArgument('category'), + * Argument::createBooleanTypeArgument('new'), + * ... + * ); + * } + * + * @return \Thelia\Core\Template\Loop\Argument\ArgumentCollection + */ + protected function getArgDefinitions() + { + return new ArgumentCollection( + Argument::createIntListTypeArgument("id"), + Argument::createIntListTypeArgument("product_sale_elements_id"), + Argument::createIntListTypeArgument("product_image_id"), + Argument::createEnumListTypeArgument( + "order", + [ + "position", + "position-reverse" + ], + "position" + ) + ); + } + + /** + * this method returns a Propel ModelCriteria + * + * @return \Propel\Runtime\ActiveQuery\ModelCriteria + */ + public function buildModelCriteria() + { + $query = ProductSaleElementsProductImageQuery::create(); + + if (null !== $id = $this->getId()) { + $query->filterById($id); + } + + if (null !== $pseId = $this->getProductSaleElementsId()) { + $query->filterByProductSaleElementsId($pseId); + } + + if (null !== $productImageId = $this->getProductImageId()) { + $query->filterByProductImageId($id); + } + + foreach ($this->getOrder() as $order) { + switch ($order) { + case "position": + $query + ->useProductImageQuery() + ->orderByPosition(Criteria::ASC) + ->endUse() + ; + break; + + case "position-reverse": + $query + ->useProductImageQuery() + ->orderByPosition(Criteria::DESC) + ->endUse() + ; + break; + } + } + + return $query; + } +} diff --git a/core/lib/Thelia/Core/Template/Loop/ProductTemplate.php b/core/lib/Thelia/Core/Template/Loop/ProductTemplate.php new file mode 100644 index 00000000..ccda3481 --- /dev/null +++ b/core/lib/Thelia/Core/Template/Loop/ProductTemplate.php @@ -0,0 +1,94 @@ + + * + * {@inheritdoc} + * @method int[] getId() + * @method int[] getExclude() + */ +class ProductTemplate extends BaseI18nLoop implements PropelSearchLoopInterface +{ + protected $timestampable = true; + + /** + * @return ArgumentCollection + */ + protected function getArgDefinitions() + { + return new ArgumentCollection( + Argument::createIntListTypeArgument('id'), + Argument::createIntListTypeArgument('exclude') + ); + } + + public function buildModelCriteria() + { + $search = TemplateQuery::create(); + + /* manage translations */ + $this->configureI18nProcessing($search, array('NAME')); + + $id = $this->getId(); + + if (null !== $id) { + $search->filterById($id, Criteria::IN); + } + + $exclude = $this->getExclude(); + + if (null !== $exclude) { + $search->filterById($exclude, Criteria::NOT_IN); + } + + return $search; + } + + public function parseResults(LoopResult $loopResult) + { + /** @var TemplateModel $template */ + foreach ($loopResult->getResultDataCollection() as $template) { + $loopResultRow = new LoopResultRow($template); + + $loopResultRow + ->set("ID", $template->getId()) + ->set("IS_TRANSLATED", $template->getVirtualColumn('IS_TRANSLATED')) + ->set("LOCALE", $this->locale) + ->set("NAME", $template->getVirtualColumn('i18n_NAME')) + ; + $this->addOutputFields($loopResultRow, $template); + + $loopResult->addRow($loopResultRow); + } + + return $loopResult; + } +} diff --git a/core/lib/Thelia/Core/Template/Loop/Profile.php b/core/lib/Thelia/Core/Template/Loop/Profile.php new file mode 100644 index 00000000..74328406 --- /dev/null +++ b/core/lib/Thelia/Core/Template/Loop/Profile.php @@ -0,0 +1,90 @@ + + * + * {@inheritdoc} + * @method int[] getId() + */ +class Profile extends BaseI18nLoop implements PropelSearchLoopInterface +{ + protected $timestampable = true; + + /** + * @return ArgumentCollection + */ + protected function getArgDefinitions() + { + return new ArgumentCollection( + Argument::createIntListTypeArgument('id') + ); + } + + public function buildModelCriteria() + { + $search = ProfileQuery::create(); + + /* manage translations */ + $this->configureI18nProcessing($search); + + $id = $this->getId(); + + if (null !== $id) { + $search->filterById($id, Criteria::IN); + } + + $search->orderById(Criteria::ASC); + + return $search; + } + + public function parseResults(LoopResult $loopResult) + { + /** @var ProfileModel $profile */ + foreach ($loopResult->getResultDataCollection() as $profile) { + $loopResultRow = new LoopResultRow($profile); + $loopResultRow->set("ID", $profile->getId()) + ->set("IS_TRANSLATED", $profile->getVirtualColumn('IS_TRANSLATED')) + ->set("LOCALE", $this->locale) + ->set("CODE", $profile->getCode()) + ->set("TITLE", $profile->getVirtualColumn('i18n_TITLE')) + ->set("CHAPO", $profile->getVirtualColumn('i18n_CHAPO')) + ->set("DESCRIPTION", $profile->getVirtualColumn('i18n_DESCRIPTION')) + ->set("POSTSCRIPTUM", $profile->getVirtualColumn('i18n_POSTSCRIPTUM')) + ; + $this->addOutputFields($loopResultRow, $profile); + + $loopResult->addRow($loopResultRow); + } + + return $loopResult; + } +} diff --git a/core/lib/Thelia/Core/Template/Loop/Resource.php b/core/lib/Thelia/Core/Template/Loop/Resource.php new file mode 100644 index 00000000..0c0675ab --- /dev/null +++ b/core/lib/Thelia/Core/Template/Loop/Resource.php @@ -0,0 +1,166 @@ + + * + * {@inheritdoc} + * @method int getProfile() + * @method string[] getCode() + * @method string[] getOrder() + */ +class Resource extends BaseI18nLoop implements PropelSearchLoopInterface +{ + protected $timestampable = true; + + /** + * @return ArgumentCollection + */ + protected function getArgDefinitions() + { + return new ArgumentCollection( + Argument::createIntTypeArgument('profile'), + new Argument( + 'code', + new Type\TypeCollection( + new Type\AlphaNumStringListType() + ) + ), + new Argument( + 'order', + new TypeCollection( + new Type\EnumListType([ + 'id', + 'id_reverse', + 'code', + 'code_reverse', + 'title', + 'title_reverse', + ]) + ), + 'id' + ) + ); + } + + /** + * @return \Propel\Runtime\ActiveQuery\ModelCriteria|ResourceQuery + * @throws \Propel\Runtime\Exception\PropelException + */ + public function buildModelCriteria() + { + $search = ResourceQuery::create(); + + /* manage translations */ + $this->configureI18nProcessing($search); + + $profile = $this->getProfile(); + + if (null !== $profile) { + $search->leftJoinProfileResource('profile_resource') + ->addJoinCondition('profile_resource', 'profile_resource.PROFILE_ID=?', $profile, null, \PDO::PARAM_INT) + ->withColumn('profile_resource.access', 'access'); + } + + $code = $this->getCode(); + + if (null !== $code) { + $search->filterByCode($code, Criteria::IN); + } + + $orders = $this->getOrder(); + + foreach ($orders as $order) { + switch ($order) { + case "id": + $search->orderById(Criteria::ASC); + break; + case "id_reverse": + $search->orderById(Criteria::DESC); + break; + case "title": + $search->addAscendingOrderByColumn('i18n_TITLE'); + break; + case "title_reverse": + $search->addDescendingOrderByColumn('i18n_TITLE'); + break; + case "code": + $search->orderByCode(Criteria::ASC); + break; + case "code_reverse": + $search->orderByCode(Criteria::DESC); + break; + } + } + + return $search; + } + + /** + * @param LoopResult $loopResult + * @return LoopResult + * @throws \Propel\Runtime\Exception\PropelException + */ + public function parseResults(LoopResult $loopResult) + { + /** @var ResourceModel $resource */ + foreach ($loopResult->getResultDataCollection() as $resource) { + $loopResultRow = new LoopResultRow($resource); + $loopResultRow->set("ID", $resource->getId()) + ->set("IS_TRANSLATED", $resource->getVirtualColumn('IS_TRANSLATED')) + ->set("LOCALE", $this->locale) + ->set("CODE", $resource->getCode()) + ->set("TITLE", $resource->getVirtualColumn('i18n_TITLE')) + ->set("CHAPO", $resource->getVirtualColumn('i18n_CHAPO')) + ->set("DESCRIPTION", $resource->getVirtualColumn('i18n_DESCRIPTION')) + ->set("POSTSCRIPTUM", $resource->getVirtualColumn('i18n_POSTSCRIPTUM')) + ; + + if (null !== $this->getProfile()) { + $accessValue = $resource->getVirtualColumn('access'); + $manager = new AccessManager($accessValue); + + $loopResultRow->set("VIEWABLE", $manager->can(AccessManager::VIEW)? 1 : 0) + ->set("CREATABLE", $manager->can(AccessManager::CREATE) ? 1 : 0) + ->set("UPDATABLE", $manager->can(AccessManager::UPDATE)? 1 : 0) + ->set("DELETABLE", $manager->can(AccessManager::DELETE)? 1 : 0); + } + + $this->addOutputFields($loopResultRow, $resource); + + $loopResult->addRow($loopResultRow); + } + + return $loopResult; + } +} diff --git a/core/lib/Thelia/Core/Template/Loop/Sale.php b/core/lib/Thelia/Core/Template/Loop/Sale.php new file mode 100644 index 00000000..c596f2bb --- /dev/null +++ b/core/lib/Thelia/Core/Template/Loop/Sale.php @@ -0,0 +1,272 @@ + + * + * {@inheritdoc} + * @method int[] getId() + * @method int[] getExclude() + * @method bool|string getActive() + * @method int[] getProduct() + * @method int getCurrency() + * @method string[] getOrder() + */ +class Sale extends BaseI18nLoop implements PropelSearchLoopInterface, SearchLoopInterface +{ + use StandardI18nFieldsSearchTrait; + + protected $timestampable = true; + + /** + * @return ArgumentCollection + */ + protected function getArgDefinitions() + { + return new ArgumentCollection( + Argument::createIntListTypeArgument('id'), + Argument::createIntListTypeArgument('exclude'), + Argument::createBooleanOrBothTypeArgument('active', 1), + Argument::createIntListTypeArgument('product'), + Argument::createIntTypeArgument('currency', $this->getCurrentRequest()->getSession()->getCurrency()->getId()), + new Argument( + 'order', + new TypeCollection( + new Type\EnumListType( + array( + 'id', + 'id-reverse', + 'alpha', + 'alpha-reverse', + 'label', + 'label-reverse', + 'active', + 'active-reverse', + 'start-date', + 'start-date-reverse', + 'end-date', + 'end-date-reverse', + 'created', + 'created-reverse', + 'updated', + 'updated-reverse' + ) + ) + ), + 'start-date' + ) + ); + } + + /** + * @return array of available field to search in + */ + public function getSearchIn() + { + return array_merge( + [ "sale_label" ], + $this->getStandardI18nSearchFields() + ); + } + + /** + * @param SaleQuery $search + * @param string $searchTerm + * @param array $searchIn + * @param string $searchCriteria + */ + public function doSearch(&$search, $searchTerm, $searchIn, $searchCriteria) + { + $search->_and(); + + foreach ($searchIn as $index => $searchInElement) { + if ($index > 0) { + $search->_or(); + } + switch ($searchInElement) { + case "sale_label": + $this->addSearchInI18nColumn($search, 'SALE_LABEL', $searchCriteria, $searchTerm); + break; + } + } + + $this->addStandardI18nSearch($search, $searchTerm, $searchCriteria, $searchIn); + } + + public function buildModelCriteria() + { + $search = SaleQuery::create(); + + /* manage translations */ + $this->configureI18nProcessing($search, array('TITLE', 'SALE_LABEL', 'CHAPO', 'DESCRIPTION', 'POSTSCRIPTUM')); + + $id = $this->getId(); + + if (!\is_null($id)) { + $search->filterById($id, Criteria::IN); + } + + $active = $this->getActive(); + + if ($active !== BooleanOrBothType::ANY) { + $search->filterByActive($active ? 1 : 0); + } + + $exclude = $this->getExclude(); + + if (!\is_null($exclude)) { + $search->filterById($exclude, Criteria::NOT_IN); + } + + $productIdList = $this->getProduct(); + + if (! \is_null($productIdList)) { + $search + ->useSaleProductQuery() + ->filterByProductId($productIdList, Criteria::IN) + ->groupByProductId() + ->endUse() + ; + } + + $search + ->leftJoinSaleOffsetCurrency('SaleOffsetCurrency') + ->addJoinCondition('SaleOffsetCurrency', '`SaleOffsetCurrency`.`currency_id` = ?', $this->getCurrency(), null, \PDO::PARAM_INT) + ; + + $search->withColumn('`SaleOffsetCurrency`.PRICE_OFFSET_VALUE', 'price_offset_value'); + + $orders = $this->getOrder(); + + foreach ($orders as $order) { + switch ($order) { + case 'id': + $search->orderById(Criteria::ASC); + break; + case 'id-reverse': + $search->orderById(Criteria::DESC); + break; + case "alpha": + $search->addAscendingOrderByColumn('i18n_TITLE'); + break; + case "alpha-reverse": + $search->addDescendingOrderByColumn('i18n_TITLE'); + break; + case "label": + $search->addAscendingOrderByColumn('i18n_SALE_LABEL'); + break; + case "label-reverse": + $search->addDescendingOrderByColumn('i18n_SALE_LABEL'); + break; + case "active": + $search->orderByActive(Criteria::ASC); + break; + case "active-reverse": + $search->orderByActive(Criteria::DESC); + break; + case "start-date": + $search->orderByStartDate(Criteria::ASC); + break; + case "start-date-reverse": + $search->orderByStartDate(Criteria::DESC); + break; + case "end-date": + $search->orderByEndDate(Criteria::ASC); + break; + case "end-date-reverse": + $search->orderByEndDate(Criteria::DESC); + 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; + } + } + + return $search; + } + + public function parseResults(LoopResult $loopResult) + { + /** @var \Thelia\Model\Sale $sale */ + foreach ($loopResult->getResultDataCollection() as $sale) { + $loopResultRow = new LoopResultRow($sale); + + switch ($sale->getPriceOffsetType()) { + case \Thelia\Model\Sale::OFFSET_TYPE_AMOUNT: + $priceOffsetType = 'A'; + $priceOffsetSymbol = $this->getCurrentRequest()->getSession()->getCurrency()->getSymbol(); + break; + + case \Thelia\Model\Sale::OFFSET_TYPE_PERCENTAGE: + $priceOffsetType = 'P'; + $priceOffsetSymbol = '%'; + break; + + default: + $priceOffsetType = $priceOffsetSymbol = '?'; + } + + $loopResultRow->set("ID", $sale->getId()) + ->set("IS_TRANSLATED", $sale->getVirtualColumn('IS_TRANSLATED')) + ->set("LOCALE", $this->locale) + ->set("TITLE", $sale->getVirtualColumn('i18n_TITLE')) + ->set("SALE_LABEL", $sale->getVirtualColumn('i18n_SALE_LABEL')) + ->set("DESCRIPTION", $sale->getVirtualColumn('i18n_DESCRIPTION')) + ->set("CHAPO", $sale->getVirtualColumn('i18n_CHAPO')) + ->set("POSTSCRIPTUM", $sale->getVirtualColumn('i18n_POSTSCRIPTUM')) + ->set("ACTIVE", $sale->getActive()) + ->set("DISPLAY_INITIAL_PRICE", $sale->getDisplayInitialPrice()) + ->set("START_DATE", $sale->getStartDate()) + ->set("HAS_START_DATE", $sale->hasStartDate() ? 1 : 0) + ->set("END_DATE", $sale->getEndDate()) + ->set("HAS_END_DATE", $sale->hasEndDate() ? 1 : 0) + ->set("PRICE_OFFSET_TYPE", $priceOffsetType) + ->set("PRICE_OFFSET_SYMBOL", $priceOffsetSymbol) + ->set("PRICE_OFFSET_VALUE", $sale->getVirtualColumn('price_offset_value')) + ; + + $this->addOutputFields($loopResultRow, $sale); + $loopResult->addRow($loopResultRow); + } + + return $loopResult; + } +} diff --git a/core/lib/Thelia/Core/Template/Loop/Serializer.php b/core/lib/Thelia/Core/Template/Loop/Serializer.php new file mode 100644 index 00000000..ef790fa0 --- /dev/null +++ b/core/lib/Thelia/Core/Template/Loop/Serializer.php @@ -0,0 +1,88 @@ + + * @author Jérôme Billiras + */ +class Serializer extends BaseLoop implements ArraySearchLoopInterface +{ + protected function getArgDefinitions() + { + return new ArgumentCollection( + Argument::createAnyTypeArgument('serializer'), + new Argument( + 'order', + new TypeCollection( + new EnumType(['alpha', 'alpha_reverse']) + ), + 'alpha' + ) + ); + } + + public function buildArray() + { + /** @var \Thelia\Core\Serializer\SerializerManager $serializerManager */ + $serializerManager = $this->container->get(RegisterSerializerPass::MANAGER_SERVICE_ID); + + $serializerId = $this->getArgValue('serializer'); + if ($serializerId === null) { + $serializers = $serializerManager->getSerializers(); + } else { + $serializers = [$serializerManager->get($serializerId)]; + } + + switch ($this->getArgValue('order')) { + case 'alpha': + ksort($serializers); + break; + case 'alpha_reverse': + krsort($serializers); + break; + } + + return $serializers; + } + + public function parseResults(LoopResult $loopResult) + { + /** @var \Thelia\Core\Serializer\SerializerInterface $serializer */ + foreach ($loopResult->getResultDataCollection() as $serializer) { + $loopResultRow = new LoopResultRow; + + $loopResultRow + ->set('ID', $serializer->getId()) + ->set('NAME', $serializer->getName()) + ->set('EXTENSION', $serializer->getExtension()) + ->set('MIME_TYPE', $serializer->getMimeType()); + + $this->addOutputFields($loopResultRow, $serializer); + $loopResult->addRow($loopResultRow); + } + + return $loopResult; + } +} diff --git a/core/lib/Thelia/Core/Template/Loop/State.php b/core/lib/Thelia/Core/Template/Loop/State.php new file mode 100644 index 00000000..64b98370 --- /dev/null +++ b/core/lib/Thelia/Core/Template/Loop/State.php @@ -0,0 +1,159 @@ + + * + * {@inheritdoc} + * @method int[] getId() + * @method int[] getCountry() + * @method int[] getExclude() + * @method bool|string getVisible() + * @method string[] getOrder() + */ +class State extends BaseI18nLoop implements PropelSearchLoopInterface +{ + protected $countable = true; + protected $timestampable = false; + + /** + * @return ArgumentCollection + */ + protected function getArgDefinitions() + { + return new ArgumentCollection( + Argument::createIntListTypeArgument('id'), + Argument::createIntListTypeArgument('country'), + Argument::createIntListTypeArgument('exclude'), + Argument::createBooleanOrBothTypeArgument('visible', 1), + new Argument( + 'order', + new TypeCollection( + new EnumListType( + [ + 'id', + 'id_reverse', + 'alpha', + 'alpha_reverse', + 'visible', + 'visible_reverse', + 'random' + ] + ) + ), + 'id' + ) + ); + } + + public function buildModelCriteria() + { + $search = StateQuery::create(); + + /* manage translations */ + $this->configureI18nProcessing($search, ['TITLE']); + + $id = $this->getId(); + if (null !== $id) { + $search->filterById($id, Criteria::IN); + } + + $country = $this->getCountry(); + if (null !== $country) { + $search->filterByCountryId($country, Criteria::IN); + } + + $exclude = $this->getExclude(); + if (!\is_null($exclude)) { + $search->filterById($exclude, Criteria::NOT_IN); + } + + $visible = $this->getVisible(); + if ($visible !== BooleanOrBothType::ANY) { + $search->filterByVisible($visible ? 1 : 0); + } + + $orders = $this->getOrder(); + foreach ($orders as $order) { + switch ($order) { + case "id": + $search->orderById(Criteria::ASC); + break; + case "id_reverse": + $search->orderById(Criteria::DESC); + break; + case "alpha": + $search->addAscendingOrderByColumn('i18n_TITLE'); + break; + case "alpha_reverse": + $search->addDescendingOrderByColumn('i18n_TITLE'); + break; + case "visible": + $search->orderByVisible(Criteria::ASC); + break; + case "visible_reverse": + $search->orderByVisible(Criteria::DESC); + break; + case "random": + $search->clearOrderByColumns(); + $search->addAscendingOrderByColumn('RAND()'); + break(2); + break; + } + } + + return $search; + } + + public function parseResults(LoopResult $loopResult) + { + /** @var \Thelia\Model\State $state */ + foreach ($loopResult->getResultDataCollection() as $state) { + $loopResultRow = new LoopResultRow($state); + $loopResultRow + ->set("ID", $state->getId()) + ->set("COUNTRY", $state->getCountryId()) + ->set("VISIBLE", $state->getVisible()) + ->set("IS_TRANSLATED", $state->getVirtualColumn('IS_TRANSLATED')) + ->set("LOCALE", $this->locale) + ->set("TITLE", $state->getVirtualColumn('i18n_TITLE')) + ->set("ISOCODE", $state->getIsocode()) + ; + + $this->addOutputFields($loopResultRow, $state); + + $loopResult->addRow($loopResultRow); + } + + return $loopResult; + } +} diff --git a/core/lib/Thelia/Core/Template/Loop/Tax.php b/core/lib/Thelia/Core/Template/Loop/Tax.php new file mode 100644 index 00000000..894aa912 --- /dev/null +++ b/core/lib/Thelia/Core/Template/Loop/Tax.php @@ -0,0 +1,163 @@ + + * + * {@inheritdoc} + * @method int[] getId() + * @method int[] getExclude() + * @method int[] getTaxRule() + * @method int[] getExcludeTaxRule() + * @method int getCountry() + * @method string[] getOrder() + */ +class Tax extends BaseI18nLoop implements PropelSearchLoopInterface +{ + protected $timestampable = true; + + /** + * @return ArgumentCollection + */ + protected function getArgDefinitions() + { + return new ArgumentCollection( + Argument::createIntListTypeArgument('id'), + Argument::createIntListTypeArgument('exclude'), + Argument::createIntListTypeArgument('tax_rule'), + Argument::createIntListTypeArgument('exclude_tax_rule'), + Argument::createIntTypeArgument('country'), + new Argument( + 'order', + new TypeCollection( + new Type\EnumListType(array('id', 'id_reverse', 'alpha', 'alpha_reverse')) + ), + 'alpha' + ) + ); + } + + public function buildModelCriteria() + { + $search = TaxQuery::create(); + + /* manage translations */ + $this->configureI18nProcessing($search, array('TITLE', 'DESCRIPTION')); + + $id = $this->getId(); + + if (null !== $id) { + $search->filterById($id, Criteria::IN); + } + + $exclude = $this->getExclude(); + + if (null !== $exclude) { + $search->filterById($exclude, Criteria::NOT_IN); + } + + $country = $this->getCountry(); + + $taxRule = $this->getTaxRule(); + if (null !== $taxRule && null !== $country) { + $search->filterByTaxRuleCountry( + TaxRuleCountryQuery::create() + ->filterByCountryId($country, Criteria::EQUAL) + ->filterByTaxRuleId($taxRule, Criteria::IN) + ->find(), + Criteria::IN + ); + } + + $excludeTaxRule = $this->getExcludeTaxRule(); + if (null !== $excludeTaxRule && null !== $country) { + $excludedTaxes = TaxRuleCountryQuery::create() + ->filterByCountryId($country, Criteria::EQUAL) + ->filterByTaxRuleId($excludeTaxRule, Criteria::IN) + ->find(); + /*DOES NOT WORK + * $search->filterByTaxRuleCountry( + $excludedTaxes, + Criteria::NOT_IN + );*/ + foreach ($excludedTaxes as $excludedTax) { + $search->filterByTaxRuleCountry($excludedTax, Criteria::NOT_EQUAL); + } + } + + $orders = $this->getOrder(); + + foreach ($orders as $order) { + switch ($order) { + case "id": + $search->orderById(Criteria::ASC); + break; + case "id_reverse": + $search->orderById(Criteria::DESC); + break; + case "alpha": + $search->addAscendingOrderByColumn('i18n_TITLE'); + break; + case "alpha_reverse": + $search->addDescendingOrderByColumn('i18n_TITLE'); + break; + } + } + + return $search; + } + + public function parseResults(LoopResult $loopResult) + { + /** @var TaxModel $tax */ + foreach ($loopResult->getResultDataCollection() as $tax) { + $loopResultRow = new LoopResultRow($tax); + + $loopResultRow + ->set("ID", $tax->getId()) + ->set("TYPE", $tax->getType()) + ->set("ESCAPED_TYPE", TaxModel::escapeTypeName($tax->getType())) + ->set("REQUIREMENTS", $tax->getRequirements()) + ->set("IS_TRANSLATED", $tax->getVirtualColumn('IS_TRANSLATED')) + ->set("LOCALE", $this->locale) + ->set("TITLE", $tax->getVirtualColumn('i18n_TITLE')) + ->set("DESCRIPTION", $tax->getVirtualColumn('i18n_DESCRIPTION')) + ; + $this->addOutputFields($loopResultRow, $tax); + + $loopResult->addRow($loopResultRow); + } + + return $loopResult; + } +} diff --git a/core/lib/Thelia/Core/Template/Loop/TaxRule.php b/core/lib/Thelia/Core/Template/Loop/TaxRule.php new file mode 100644 index 00000000..1c8d63f8 --- /dev/null +++ b/core/lib/Thelia/Core/Template/Loop/TaxRule.php @@ -0,0 +1,125 @@ + + * + * {@inheritdoc} + * @method int[] getId() + * @method int[] getExclude() + * @method string[] getOrder() + */ +class TaxRule extends BaseI18nLoop implements PropelSearchLoopInterface +{ + protected $timestampable = true; + + /** + * @return ArgumentCollection + */ + protected function getArgDefinitions() + { + return new ArgumentCollection( + Argument::createIntListTypeArgument('id'), + Argument::createIntListTypeArgument('exclude'), + new Argument( + 'order', + new TypeCollection( + new Type\EnumListType(array('id', 'id_reverse', 'alpha', 'alpha_reverse')) + ), + 'alpha' + ) + ); + } + + public function buildModelCriteria() + { + $search = TaxRuleQuery::create(); + + /* manage translations */ + $this->configureI18nProcessing($search, array('TITLE', 'DESCRIPTION')); + + $id = $this->getId(); + + if (null !== $id) { + $search->filterById($id, Criteria::IN); + } + + $exclude = $this->getExclude(); + + if (null !== $exclude) { + $search->filterById($exclude, Criteria::NOT_IN); + } + + $orders = $this->getOrder(); + + foreach ($orders as $order) { + switch ($order) { + case "id": + $search->orderById(Criteria::ASC); + break; + case "id_reverse": + $search->orderById(Criteria::DESC); + break; + case "alpha": + $search->addAscendingOrderByColumn('i18n_TITLE'); + break; + case "alpha_reverse": + $search->addDescendingOrderByColumn('i18n_TITLE'); + break; + } + } + + return $search; + } + + public function parseResults(LoopResult $loopResult) + { + /** @var TaxRuleModel $taxRule */ + foreach ($loopResult->getResultDataCollection() as $taxRule) { + $loopResultRow = new LoopResultRow($taxRule); + + $loopResultRow + ->set("ID", $taxRule->getId()) + ->set("IS_TRANSLATED", $taxRule->getVirtualColumn('IS_TRANSLATED')) + ->set("LOCALE", $this->locale) + ->set("TITLE", $taxRule->getVirtualColumn('i18n_TITLE')) + ->set("DESCRIPTION", $taxRule->getVirtualColumn('i18n_DESCRIPTION')) + ->set("IS_DEFAULT", $taxRule->getIsDefault() ? '1' : '0') + ; + $this->addOutputFields($loopResultRow, $taxRule); + + $loopResult->addRow($loopResultRow); + } + + return $loopResult; + } +} diff --git a/core/lib/Thelia/Core/Template/Loop/TaxRuleCountry.php b/core/lib/Thelia/Core/Template/Loop/TaxRuleCountry.php new file mode 100644 index 00000000..2dbdda6b --- /dev/null +++ b/core/lib/Thelia/Core/Template/Loop/TaxRuleCountry.php @@ -0,0 +1,135 @@ + + * + * {@inheritdoc} + * @method int getCountry() + * @method int|null getState() + * @method int getTaxRule() + * @method string getAsk() + */ +class TaxRuleCountry extends BaseI18nLoop implements PropelSearchLoopInterface +{ + protected $taxCountForOriginCountry; + + protected $timestampable = true; + + /** + * @return ArgumentCollection + */ + protected function getArgDefinitions() + { + return new ArgumentCollection( + Argument::createIntTypeArgument('country', null, true), + new Argument( + 'ask', + new TypeCollection( + new Type\EnumType(array('taxes', 'countries')) + ), + 'taxes' + ), + Argument::createIntTypeArgument('tax_rule', null, true) + ); + } + + /** + * @inheritdoc + */ + public function buildModelCriteria() + { + $ask = $this->getAsk(); + + if ($ask === 'countries') { + return null; + } + + $country = $this->getCountry(); + $state = $this->getState(); + $taxRule = $this->getTaxRule(); + + $search = TaxRuleCountryQuery::create(); + + $search->filterByCountryId($country); + $search->filterByStateId($state); + $search->filterByTaxRuleId($taxRule); + + /* manage tax translation */ + $this->configureI18nProcessing( + $search, + array('TITLE', 'DESCRIPTION'), + TaxTableMap::TABLE_NAME, + 'TAX_ID' + ); + + $search->orderByPosition(Criteria::ASC); + + return $search; + } + + /** + * @inheritdoc + */ + public function parseResults(LoopResult $loopResult) + { + if ($this->getAsk() === 'countries') { + return $loopResult; + } + + /** @var TaxRuleCountryModel $taxRuleCountry */ + foreach ($loopResult->getResultDataCollection() as $taxRuleCountry) { + $loopResultRow = new LoopResultRow($taxRuleCountry); + $loopResultRow + ->set("TAX_RULE", $taxRuleCountry->getTaxRuleId()) + ->set("COUNTRY", $taxRuleCountry->getCountryId()) + ->set("STATE", $taxRuleCountry->getStateId()) + ->set("TAX", $taxRuleCountry->getTaxId()) + ->set("POSITION", $taxRuleCountry->getPosition()) + ->set("TAX_TITLE", $taxRuleCountry->getVirtualColumn(TaxTableMap::TABLE_NAME . '_i18n_TITLE')) + ->set( + "TAX_DESCRIPTION", + $taxRuleCountry->getVirtualColumn(TaxTableMap::TABLE_NAME . '_i18n_DESCRIPTION') + ) + ; + + $this->addOutputFields($loopResultRow, $taxRuleCountry); + $loopResult->addRow($loopResultRow); + } + + return $loopResult; + } +} diff --git a/core/lib/Thelia/Core/Template/Loop/Template.php b/core/lib/Thelia/Core/Template/Loop/Template.php new file mode 100644 index 00000000..57a4071a --- /dev/null +++ b/core/lib/Thelia/Core/Template/Loop/Template.php @@ -0,0 +1,94 @@ + + * + * {@inheritdoc} + */ +class Template extends BaseLoop implements ArraySearchLoopInterface +{ + /** + * @return ArgumentCollection + */ + protected function getArgDefinitions() + { + return new ArgumentCollection( + new Argument( + 'template-type', + new Type\TypeCollection( + new Type\EnumType(array( + 'front-office', + 'front', + 'back-office', + 'admin', + 'pdf', + 'email', + 'mail' + )) + ) + ) + ); + } + + public function buildArray() + { + $type = $this->getArg('template-type')->getValue(); + + if ($type == 'front-office' || $type == 'front') { + $templateType = TemplateDefinition::FRONT_OFFICE; + } elseif ($type == 'back-office' || $type == 'admin') { + $templateType = TemplateDefinition::BACK_OFFICE; + } elseif ($type == 'pdf') { + $templateType = TemplateDefinition::PDF; + } elseif ($type == 'email' || $type == 'mail') { + $templateType = TemplateDefinition::EMAIL; + } + + return $this->container->get('thelia.template_helper')->getList($templateType); + } + + public function parseResults(LoopResult $loopResult) + { + /** @var TemplateDefinition $template */ + foreach ($loopResult->getResultDataCollection() as $template) { + $loopResultRow = new LoopResultRow($template); + + $loopResultRow + ->set("NAME", $template->getName()) + ->set("RELATIVE_PATH", $template->getPath()) + ->set("ABSOLUTE_PATH", $template->getAbsolutePath()) + ; + $this->addOutputFields($loopResultRow, $template); + + $loopResult->addRow($loopResultRow); + } + + return $loopResult; + } +} diff --git a/core/lib/Thelia/Core/Template/Loop/Title.php b/core/lib/Thelia/Core/Template/Loop/Title.php new file mode 100644 index 00000000..7a1ddee1 --- /dev/null +++ b/core/lib/Thelia/Core/Template/Loop/Title.php @@ -0,0 +1,88 @@ + + * + * {@inheritdoc} + * @method int[] getId() + */ +class Title extends BaseI18nLoop implements PropelSearchLoopInterface +{ + protected $timestampable = true; + + /** + * @return ArgumentCollection + */ + protected function getArgDefinitions() + { + return new ArgumentCollection( + Argument::createIntListTypeArgument('id') + ); + } + + public function buildModelCriteria() + { + $search = CustomerTitleQuery::create(); + + /* manage translations */ + $this->configureI18nProcessing($search, array('SHORT', 'LONG')); + + $id = $this->getId(); + + if (null !== $id) { + $search->filterById($id, Criteria::IN); + } + + $search->orderByPosition(); + + return $search; + } + + public function parseResults(LoopResult $loopResult) + { + /** @var CustomerTitleModel $title */ + foreach ($loopResult->getResultDataCollection() as $title) { + $loopResultRow = new LoopResultRow($title); + $loopResultRow->set("ID", $title->getId()) + ->set("IS_TRANSLATED", $title->getVirtualColumn('IS_TRANSLATED')) + ->set("LOCALE", $this->locale) + ->set("DEFAULT", $title->getByDefault()) + ->set("SHORT", $title->getVirtualColumn('i18n_SHORT')) + ->set("LONG", $title->getVirtualColumn('i18n_LONG')) + ->set("POSITION", $title->getPosition()); + $this->addOutputFields($loopResultRow, $title); + + $loopResult->addRow($loopResultRow); + } + + return $loopResult; + } +} diff --git a/core/lib/Thelia/Core/Template/Parser/ParserAssetResolverFallback.php b/core/lib/Thelia/Core/Template/Parser/ParserAssetResolverFallback.php new file mode 100644 index 00000000..2d0a0b01 --- /dev/null +++ b/core/lib/Thelia/Core/Template/Parser/ParserAssetResolverFallback.php @@ -0,0 +1,99 @@ + + */ +class ParserAssetResolverFallback implements AssetResolverInterface +{ + /** + * Generate an asset URL + * + * @param string $source a module code, or ParserInterface::TEMPLATE_ASSETS_KEY + * @param string $file the file path, relative to a template base directory (e.g. assets/css/style.css) + * @param string $type the asset type, either 'css' or ' + * @param ParserInterface $parserInterface the current template parser + * @param array $filters the filters to pass to the asset manager + * @param bool $debug the debug mode + * @param string $declaredAssetsDirectory if not null, this is the assets directory declared in the {declare_assets} function of a template. + * @param mixed $sourceTemplateName A template name, of false. If provided, the assets will be searched in this template directory instead of the current one. + * @return mixed + */ + public function resolveAssetURL( + $source, + $file, + $type, + ParserInterface $parserInterface, + $filters = [], + $debug = false, + $declaredAssetsDirectory = null, + $sourceTemplateName = false + ) { + throw new \RuntimeException('if you want to use a parser, please register one'); + } + + /** + * Return an asset source file path. + * + * A system of fallback enables file overriding. It will look for the template : + * - in the current template in directory /modules/{module code}/ + * - in the module in the current template if it exists + * - in the module in the default template + * + * @param string $source a module code, or or ParserInterface::TEMPLATE_ASSETS_KEY + * @param string $templateName a template name, or false to use the current template + * @param string $fileName the filename + * @param ParserInterface $parserInterface the current template parser + * + * @return mixed the path to directory containing the file, or null if the file doesn't exists. + */ + public function resolveAssetSourcePath($source, $templateName, $fileName, ParserInterface $parserInterface) + { + throw new \RuntimeException('if you want to use a parser, please register one'); + } + + + /** + * Return an asset source file path, and the template in which it was found + * + * A system of fallback enables file overriding. It will look for the template : + * - in the current template in directory /modules/{module code}/ + * - in the module in the current template if it exists + * - in the module in the default template + * + * @param string $source a module code, or ParserInterface::TEMPLATE_ASSETS_KEY + * @param string $templateName a template name, or false to use the current template + * @param string $fileName the filename + * @param ParserInterface $parserInterface the current template parser + * @param TemplateDefinition &$templateDefinition the template where to start search. + * This parameter will contain the template where the asset was found. + * + * @return mixed the path to directory containing the file, or null if the file doesn't exists. + */ + public function resolveAssetSourcePathAndTemplate( + $source, + $templateName, + $fileName, + ParserInterface $parserInterface, + TemplateDefinition &$templateDefinition + ) { + throw new \RuntimeException('if you want to use a parser, please register one'); + } +} diff --git a/core/lib/Thelia/Core/Template/Parser/ParserFallback.php b/core/lib/Thelia/Core/Template/Parser/ParserFallback.php new file mode 100644 index 00000000..623e78b5 --- /dev/null +++ b/core/lib/Thelia/Core/Template/Parser/ParserFallback.php @@ -0,0 +1,169 @@ + + */ +class ParserFallback implements ParserInterface +{ + public function render($realTemplateName, array $parameters = array(), $compressOutput = true) + { + $this->throwException(); + } + + public function renderString($templateText, array $parameters = array(), $compressOutput = true) + { + $this->throwException(); + } + + public function getStatus() + { + $this->throwException(); + } + + public function setStatus($status) + { + $this->throwException(); + } + + /** + * Setup the parser with a template definition, which provides a template description. + * + * @param TemplateDefinition $templateDefinition + */ + public function setTemplateDefinition(TemplateDefinition $templateDefinition, $fallbackToDefaultTemplate = false) + { + $this->throwException(); + } + + /** + * Get template definition + * + * @param bool $webAssetTemplate Allow to load asset from another template + * If the name of the template if provided + * + * @return TemplateDefinition + */ + public function getTemplateDefinition($webAssetTemplate = false) + { + $this->throwException(); + } + + /** + * Check if template definition is not null + * + * @return boolean + */ + public function hasTemplateDefinition() + { + $this->throwException(); + } + + /** + * Add a template directory to the current template list + * + * @param int $templateType the template type ( + * + * @param string $templateName the template name + * @param string $templateDirectory path to the template dirtectory + * @param string $key ??? + * @param bool $unshift ??? Etienne ? + */ + public function addTemplateDirectory($templateType, $templateName, $templateDirectory, $key, $unshift = false) + { + $this->throwException(); + } + + /** + * Return the registeted template directories for a givent template type + * + * @param int $templateType + * @throws \InvalidArgumentException if the templateType is not defined + * @return array: an array of defined templates directories for the given template type + */ + public function getTemplateDirectories($templateType) + { + $this->throwException(); + } + + /** + * Create a variable that will be available in the templates + * + * @param string $variable the variable name + * @param mixed $value the value of the variable + */ + public function assign($variable, $value = null) + { + $this->throwException(); + } + + /** + * @return \Thelia\Core\Template\TemplateHelperInterface the parser template helper instance + */ + public function getTemplateHelper() + { + $this->throwException(); + } + + private function throwException() + { + throw new \RuntimeException('if you want to use a parser, please register one'); + } + + /** + * Returns the request used by the parser + * + * @return Request + */ + public function getRequest() + { + $this->throwException(); + } + + /** + * Set a new template definition, and save the current one + * + * @param TemplateDefinition $templateDefinition + * @param bool $fallbackToDefaultTemplate if true, resources will be also searched in the "default" template + * @throws \SmartyException + */ + public function pushTemplateDefinition(TemplateDefinition $templateDefinition, $fallbackToDefaultTemplate = false) + { + $this->throwException(); + } + + /** + * Restore the previous stored template definition, if one exists. + * + * @throws \SmartyException + */ + public function popTemplateDefinition() + { + $this->throwException(); + } + + /** + * Get the current status of the fallback to "default" feature + * + * @return bool + */ + public function getFallbackToDefaultTemplate() + { + $this->throwException(); + } +} diff --git a/core/lib/Thelia/Core/Template/Parser/ParserHelperFallback.php b/core/lib/Thelia/Core/Template/Parser/ParserHelperFallback.php new file mode 100644 index 00000000..ab599a06 --- /dev/null +++ b/core/lib/Thelia/Core/Template/Parser/ParserHelperFallback.php @@ -0,0 +1,38 @@ + + */ +class ParserHelperFallback implements ParserHelperInterface +{ + /** + * Parse a string and get all parser's function and block with theirs arguments. + * + * + * + * @param string $content the template content + * @param array $functions the only functions we want to parse + * + * @return array array of functions with 2 index name and attributes an array of name, value + */ + public function getFunctionsDefinition($content, array $functions = array()) + { + throw new \RuntimeException('if you want to use a parser, please register one'); + } +} diff --git a/core/lib/Thelia/Core/Template/ParserContext.php b/core/lib/Thelia/Core/Template/ParserContext.php new file mode 100644 index 00000000..03cd5d12 --- /dev/null +++ b/core/lib/Thelia/Core/Template/ParserContext.php @@ -0,0 +1,336 @@ + + */ +class ParserContext implements \IteratorAggregate +{ + // Lifetime, in seconds, of form error data + const FORM_ERROR_LIFETIME_SECONDS = 60; + + private $formStore = array(); + private $store = array(); + + /** @var TheliaFormFactoryInterface */ + private $formFactory; + + /** @var TheliaFormValidatorInterface */ + private $formValidator; + + /** @var RequestStack */ + private $requestStack; + + public function __construct( + RequestStack $requestStack, + TheliaFormFactoryInterface $formFactory, + TheliaFormValidatorInterface $formValidator + ) { + // Setup basic variables + $this->set('THELIA_VERSION', Thelia::THELIA_VERSION); + + $this->requestStack = $requestStack; + $this->formFactory = $formFactory; + $this->formValidator = $formValidator; + + // Purge outdated error form contexts + $this->cleanOutdatedFormErrorInformation(); + } + + /** + * Set the current form + * + * @param BaseForm $form + * @return $this + */ + public function pushCurrentForm(BaseForm $form) + { + array_push($this->formStore, $form); + + return $this; + } + + /** + * Set the current form. + * + * @param null|BaseForm $default + * @return BaseForm|null + */ + public function popCurrentForm($default = null) + { + $form = array_pop($this->formStore); + + if (null === $form) { + return $default; + } + + return $form; + } + + public function getCurrentForm() + { + $form = end($this->formStore); + + if (false === $form) { + throw new SmartyPluginException( + "There is currently no defined form" + ); + } + + return $form; + } + + // -- Error form ----------------------------------------------------------- + + /** + * Remove all objects in data, because they are probably not serializable + * + * @param array $data + * @return array + */ + protected function cleanFormData(array $data) + { + foreach ($data as $key => $value) { + if (\is_array($value)) { + $data[$key] = $this->cleanFormData($value); + } elseif (\is_object($value)) { + unset($data[$key]); + } + } + + return $data; + } + + /** + * Add a new form to the error form context + * + * @param BaseForm $form the errored form + * @return $this + */ + public function addForm(BaseForm $form) + { + $formErrorInformation = $this->getSession()->getFormErrorInformation(); + + // Get form field error details + $formFieldErrors = []; + + /** @var Form $field */ + foreach ($form->getForm()->getIterator() as $field) { + $errors = $field->getErrors(); + + if (\count($errors) > 0) { + $formFieldErrors[$field->getName()] = []; + + /** @var FormError $error */ + foreach ($errors as $error) { + $formFieldErrors[$field->getName()][] = [ + 'message' => $error->getMessage(), + 'template' => $error->getMessageTemplate(), + 'parameters' => $error->getMessageParameters(), + 'pluralization' => $error->getMessagePluralization() + ]; + } + } + } + + $this->set(\get_class($form) . ":" . $form->getType(), $form); + + // Set form error information + $formErrorInformation[\get_class($form) . ":" . $form->getType()] = [ + 'data' => $this->cleanFormData($form->getForm()->getData()), + 'hasError' => $form->hasError(), + 'errorMessage' => $form->getErrorMessage(), + 'method' => $this->requestStack->getCurrentRequest()->getMethod(), + 'timestamp' => time(), + 'validation_groups' => $form->getForm()->getConfig()->getOption('validation_groups'), + 'field_errors' => $formFieldErrors + ]; + + $this->getSession()->setFormErrorInformation($formErrorInformation); + + return $this; + } + + /** + * Check if the specified form has errors, and return an instance of this form if it's the case. + * + * @param string $formId the form ID, as defined in the container + * @param string $formClass the form full qualified class name + * @param string $formType the form type, something like 'form' + * @return null|BaseForm null if no error information is available + */ + public function getForm($formId, $formClass, $formType) + { + if (isset($this->store[$formClass . ":" . $formType]) && $this->store[$formClass . ":" . $formType] instanceof BaseForm) { + return $this->store[$formClass . ":" . $formType]; + } + + $formErrorInformation = $this->getSession()->getFormErrorInformation(); + + if (isset($formErrorInformation[$formClass.":".$formType])) { + $formInfo = $formErrorInformation[$formClass.":".$formType]; + + if (\is_array($formInfo['data'])) { + $form = $this->formFactory->createForm( + $formId, + $formType, + $formInfo['data'], + [ + 'validation_groups' => $formInfo['validation_groups'] + ] + ); + + // If the form has errors, perform a validation, to restore the internal error context + // A controller (as the NewsletterController) may use the parserContext to redisplay a + // validated (not errored) form. In such cases, another validation may cause unexpected + // results. + if (true === $formInfo['hasError']) { + try { + $this->formValidator->validateForm($form, $formInfo['method']); + } catch (\Exception $ex) { + // Ignore the exception. + } + + // Manually set the form fields error information, if validateForm() did not the job, + // which is the case when the user has been redirected. + foreach ($formInfo['field_errors'] as $fieldName => $errors) { + /** @var Form $field */ + $field = $form->getForm()->get($fieldName); + + if (null !== $field && \count($field->getErrors()) == 0) { + foreach ($errors as $errorData) { + $error = new FormError( + $errorData['message'], + $errorData['template'], + $errorData['parameters'], + $errorData['pluralization'] + ); + + $field->addError($error); + } + } + } + } + + $form->setError($formInfo['hasError']); + + // Check if error message is empty, as BaseForm::setErrorMessage() always set form error flag to true. + if (! empty($formInfo['errorMessage'])) { + $form->setErrorMessage($formInfo['errorMessage']); + } + + return $form; + } + } + + return null; + } + + /** + * Remove form from the saved form error information. + * + * @param BaseForm $form + * @return $this + */ + public function clearForm(BaseForm $form) + { + $formErrorInformation = $this->getSession()->getFormErrorInformation(); + + $formClass = \get_class($form) . ':' . $form->getType(); + + if (isset($formErrorInformation[$formClass])) { + unset($formErrorInformation[$formClass]); + $this->getSession()->setFormErrorInformation($formErrorInformation); + } + + return $this; + } + + /** + * Remove obsolete form error information. + */ + protected function cleanOutdatedFormErrorInformation() + { + $formErrorInformation = $this->getSession()->getFormErrorInformation(); + + if (! empty($formErrorInformation)) { + $now = time(); + + // Cleanup obsolete form information, and try to find the form data + foreach ($formErrorInformation as $name => $formData) { + if ($now - $formData['timestamp'] > self::FORM_ERROR_LIFETIME_SECONDS) { + unset($formErrorInformation[$name]); + } + } + + $this->getSession()->setFormErrorInformation($formErrorInformation); + } + + return $this; + } + + public function setGeneralError($error) + { + $this->set('general_error', $error); + + return $this; + } + + // -- Internal table manipulation ------------------------------------------ + + public function set($name, $value) + { + $this->store[$name] = $value; + + return $this; + } + + public function remove($name) + { + unset($this->store[$name]); + + return $this; + } + + public function get($name, $default = null) + { + return isset($this->store[$name]) ? $this->store[$name] : $default; + } + + public function getIterator() + { + return new \ArrayIterator($this->store); + } + + /** + * @return Session + */ + public function getSession() + { + return $this->requestStack->getCurrentRequest()->getSession(); + } +} diff --git a/core/lib/Thelia/Core/Template/ParserHelperInterface.php b/core/lib/Thelia/Core/Template/ParserHelperInterface.php new file mode 100644 index 00000000..66f7f72b --- /dev/null +++ b/core/lib/Thelia/Core/Template/ParserHelperInterface.php @@ -0,0 +1,28 @@ + + * + */ + +interface ParserInterface +{ + // A key to identify assets defined in a template. This will be the name of the directory in which the template + // assets will be copied and generated in the web cache. + const TEMPLATE_ASSETS_KEY = 'template-assets'; + + /** + * Return a rendered template file + * + * @param string $realTemplateName the template name (from the template directory) + * @param array $parameters an associative array of names / value pairs + * @return string the rendered template text + * @param bool $compressOutput if true, te output is compressed using trimWhitespaces. If false, no compression occurs + * @throws ResourceNotFoundException if the template cannot be found + * @throws \Exception + * @throws \SmartyException + */ + public function render($realTemplateName, array $parameters = array(), $compressOutput = true); + + /** + * Return a rendered template text + * + * @param string $templateText the template text + * @param array $parameters an associative array of names / value pairs + * @param bool $compressOutput if true, te output is compressed using trimWhitespaces. If false, no compression occurs + * @return string the rendered template text + * @throws \Exception + * @throws \SmartyException + */ + public function renderString($templateText, array $parameters = array(), $compressOutput = true); + + /** + * @return int the HTTP status of the response + */ + public function getStatus(); + + /** + * Sets the HTTP status of the response + * + * status An HTTP status (200, 404, ...) + * + * @param int $status + */ + public function setStatus($status); + + /** + * Returns the request used by the parser + * + * @return Request + */ + public function getRequest(); + + /** + * Set a new template definition, and save the current one + * + * @param TemplateDefinition $templateDefinition + * @param bool $fallbackToDefaultTemplate if true, resources will be also searched in the "default" template + * @throws \SmartyException + */ + public function pushTemplateDefinition(TemplateDefinition $templateDefinition, $fallbackToDefaultTemplate = false); + + /** + * Restore the previous stored template definition, if one exists. + * + * @throws \SmartyException + */ + public function popTemplateDefinition(); + + /** + * Setup the parser with a template definition, which provides a template description. + * + * @param TemplateDefinition $templateDefinition + * @param bool $fallbackToDefaultTemplate if true, also search files in hte "default" template. + */ + public function setTemplateDefinition(TemplateDefinition $templateDefinition, $fallbackToDefaultTemplate = false); + + /** + * Get template definition + * + * @param bool|string $webAssetTemplateName false to use the current template path, or a template name to + * load assets from this template instead of the current one. + * + * @return TemplateDefinition + */ + public function getTemplateDefinition($webAssetTemplateName = false); + + /** + * Check if template definition is not null + * + * @return boolean + */ + public function hasTemplateDefinition(); + + /** + * Get the current status of the fallback to "default" feature + * + * @return bool + */ + public function getFallbackToDefaultTemplate(); + + /** + * Add a template directory to the current template list + * + * @param int $templateType the template type ( + * + * @param string $templateName the template name + * @param string $templateDirectory path to the template dirtectory + * @param string $key the template directory identifier + * @param bool $unshift if true, add template at the top of the list + */ + public function addTemplateDirectory($templateType, $templateName, $templateDirectory, $key, $unshift = false); + + /** + * Return the registeted template directories for a givent template type + * + * @param int $templateType + * @throws \InvalidArgumentException if the templateType is not defined + * @return array: an array of defined templates directories for the given template type + */ + public function getTemplateDirectories($templateType); + + /** + * Create a variable that will be available in the templates + * + * @param string $variable the variable name + * @param mixed $value the value of the variable + */ + /** + * assigns a parser variable. If $variable is an array, it is supposed to contains (variable_name => variable_value) pairs + * + * @param array|string $variable the template variable name(s) + * @param mixed $value the value to assign + */ + public function assign($variable, $value = null); + + /** + * @return \Thelia\Core\Template\TemplateHelperInterface the parser template helper instance + */ + public function getTemplateHelper(); +} diff --git a/core/lib/Thelia/Core/Template/Smarty/AbstractSmartyPlugin.php b/core/lib/Thelia/Core/Template/Smarty/AbstractSmartyPlugin.php new file mode 100644 index 00000000..544819f1 --- /dev/null +++ b/core/lib/Thelia/Core/Template/Smarty/AbstractSmartyPlugin.php @@ -0,0 +1,26 @@ + + * + * @deprecated this class is now present in module TheliaSmarty and will be removed in Thelia 2.3 + */ +abstract class AbstractSmartyPlugin extends BaseAbstractSmartyPlugin +{ +} diff --git a/core/lib/Thelia/Core/Template/Smarty/SmartyPluginDescriptor.php b/core/lib/Thelia/Core/Template/Smarty/SmartyPluginDescriptor.php new file mode 100644 index 00000000..3423e066 --- /dev/null +++ b/core/lib/Thelia/Core/Template/Smarty/SmartyPluginDescriptor.php @@ -0,0 +1,26 @@ + + * + * @deprecated this class is now present in module TheliaSmarty and will be removed in Thelia 2.3 + */ +class SmartyPluginDescriptor extends BaseSmartyPluginDescriptor +{ +} diff --git a/core/lib/Thelia/Core/Template/TemplateDefinition.php b/core/lib/Thelia/Core/Template/TemplateDefinition.php new file mode 100644 index 00000000..4e92cac6 --- /dev/null +++ b/core/lib/Thelia/Core/Template/TemplateDefinition.php @@ -0,0 +1,227 @@ + self::FRONT_OFFICE_SUBDIR, + self::BACK_OFFICE => self::BACK_OFFICE_SUBDIR, + self::PDF => self::PDF_SUBDIR, + self::EMAIL => self::EMAIL_SUBDIR, + ); + + /** @var array|null the parent list cache */ + protected $parentList = null; + + /** + * TemplateDefinition constructor. + * @param string $name the template name (= directory name) + * @param int $type the remplate type (see $standardTemplatesSubdirs) + * @throws \Exception + */ + public function __construct($name, $type) + { + switch ($type) { + case TemplateDefinition::FRONT_OFFICE: + $this->path = self::FRONT_OFFICE_SUBDIR . DS . $name; + $this->translationDomainPrefix = 'fo.'; + break; + case TemplateDefinition::BACK_OFFICE: + $this->path = self::BACK_OFFICE_SUBDIR . DS . $name; + $this->translationDomainPrefix = 'bo.'; + break; + case TemplateDefinition::PDF: + $this->path = self::PDF_SUBDIR . DS . $name; + $this->translationDomainPrefix = 'pdf.'; + break; + case TemplateDefinition::EMAIL: + $this->path = self::EMAIL_SUBDIR . DS . $name; + $this->translationDomainPrefix = 'email.'; + break; + default: + $this->path = $name; + $this->translationDomainPrefix = 'generic.'; + break; + } + + // Load template descriprot, if any. + $this->templateDescriptor = (new TemplateValidator($this->getAbsolutePath()))->getTemplateDefinition($name, $type); + } + + public function getTranslationDomain() + { + return $this->translationDomainPrefix . strtolower($this->getName()); + } + + /** + * @return string + */ + public function getName() + { + return $this->templateDescriptor->getName(); + } + + public function setName($name) + { + $this->templateDescriptor->setName($name); + + return $this; + } + + public function getI18nPath() + { + return $this->getPath() . DS . 'I18n'; + } + + public function getAbsoluteI18nPath() + { + return THELIA_TEMPLATE_DIR . $this->getI18nPath(); + } + + public function getPath() + { + return $this->path; + } + + public function getAbsolutePath() + { + return THELIA_TEMPLATE_DIR . $this->getPath(); + } + + public function getConfigPath() + { + return $this->getPath() . DS . 'configs'; + } + + public function getAbsoluteConfigPath() + { + return THELIA_TEMPLATE_DIR . $this->getConfigPath(); + } + + public function setPath($path) + { + $this->path = $path; + + return $this; + } + + /** + * @return int + */ + public function getType() + { + return $this->templateDescriptor->getType(); + } + + public function setType($type) + { + $this->$this->templateDescriptor->setType($type); + + return $this; + } + + /** + * Get teh template descriptor + * + * @return TemplateDescriptor + */ + public function getDescriptor() + { + return $this->templateDescriptor; + } + + /** + * Returns an iterator on the standard templates subdir names + */ + public static function getStandardTemplatesSubdirsIterator() + { + return new \ArrayIterator(self::$standardTemplatesSubdirs); + } + + /** + * Return the template parent list + * + * @return array|null + */ + public function getParentList() + { + if (null === $this->parentList) { + $this->parentList = []; + + $parent = $this->getDescriptor()->getParent(); + + for ($index = 1; null !== $parent; $index++) { + $this->parentList[$parent->getName() . '-'] = $parent; + + $parent = $parent->getDescriptor()->getParent(); + } + } + + return $this->parentList; + } + + /** + * Find a template file path, considering the template parents, if any. + * + * @param string $templateName the template name, with path + * @return string + * @throws TemplateException + */ + public function getTemplateFilePath($templateName) + { + $templateList = array_merge( + [ $this ], + $this->getParentList() + ); + + /** @var TemplateDefinition $templateDefinition */ + foreach ($templateList as $templateDefinition) { + $templateFilePath = sprintf( + '%s%s/%s', + THELIA_TEMPLATE_DIR, + $templateDefinition->getPath(), + $templateName + ); + + if (file_exists($templateFilePath)) { + return $templateFilePath; + } + } + + throw new TemplateException("Template file not found: $templateName"); + } +} diff --git a/core/lib/Thelia/Core/Template/TemplateHelperInterface.php b/core/lib/Thelia/Core/Template/TemplateHelperInterface.php new file mode 100644 index 00000000..9eea5df7 --- /dev/null +++ b/core/lib/Thelia/Core/Template/TemplateHelperInterface.php @@ -0,0 +1,63 @@ + + * Creation date: 26/03/2015 16:36 + */ + +namespace Thelia\Core\Template; + +use Thelia\Model\ConfigQuery; + +class TheliaTemplateHelper implements TemplateHelperInterface +{ + /** + * @return TemplateDefinition + */ + public function getActiveMailTemplate() + { + return new TemplateDefinition( + ConfigQuery::read('active-mail-template', 'default'), + TemplateDefinition::EMAIL + ); + } + + /** + * Check if a template definition is the current active template + * + * @param TemplateDefinition $tplDefinition + * @return bool true is the given template is the active template + */ + public function isActive(TemplateDefinition $tplDefinition) + { + $tplVar = ''; + + switch ($tplDefinition->getType()) { + case TemplateDefinition::FRONT_OFFICE: + $tplVar = 'active-front-template'; + break; + case TemplateDefinition::BACK_OFFICE: + $tplVar = 'active-admin-template'; + break; + case TemplateDefinition::PDF: + $tplVar = 'active-pdf-template'; + break; + case TemplateDefinition::EMAIL: + $tplVar = 'active-mail-template'; + break; + } + + return $tplDefinition->getName() == ConfigQuery::read($tplVar, 'default'); + } + /** + * @return TemplateDefinition + */ + public function getActivePdfTemplate() + { + return new TemplateDefinition( + ConfigQuery::read('active-pdf-template', 'default'), + TemplateDefinition::PDF + ); + } + + /** + * @return TemplateDefinition + */ + public function getActiveAdminTemplate() + { + return new TemplateDefinition( + ConfigQuery::read('active-admin-template', 'default'), + TemplateDefinition::BACK_OFFICE + ); + } + + /** + * @return TemplateDefinition + */ + public function getActiveFrontTemplate() + { + return new TemplateDefinition( + ConfigQuery::read('active-front-template', 'default'), + TemplateDefinition::FRONT_OFFICE + ); + } + + /** + * Returns an array which contains all standard template definitions + */ + public function getStandardTemplateDefinitions() + { + return array( + $this->getActiveFrontTemplate(), + $this->getActiveAdminTemplate(), + $this->getActivePdfTemplate(), + $this->getActiveMailTemplate(), + ); + } + + /** + * Return a list of existing templates for a given template type + * + * @param int $templateType the template type + * @param string $base the template base (module or core, default to core). + * @return TemplateDefinition[] of \Thelia\Core\Template\TemplateDefinition + */ + public function getList($templateType, $base = THELIA_TEMPLATE_DIR) + { + $list = $exclude = array(); + + $tplIterator = TemplateDefinition::getStandardTemplatesSubdirsIterator(); + + foreach ($tplIterator as $type => $subdir) { + if ($templateType == $type) { + $baseDir = rtrim($base, DS).DS.$subdir; + + try { + // Every subdir of the basedir is supposed to be a template. + $di = new \DirectoryIterator($baseDir); + + /** @var \DirectoryIterator $file */ + foreach ($di as $file) { + // Ignore 'dot' elements + if ($file->isDot() || ! $file->isDir()) { + continue; + } + + // Ignore reserved directory names + if (\in_array($file->getFilename(), $exclude)) { + continue; + } + + $list[] = new TemplateDefinition($file->getFilename(), $templateType); + } + } catch (\UnexpectedValueException $ex) { + // Ignore the exception and continue + } + } + } + + return $list; + } +} diff --git a/core/lib/Thelia/Core/Template/Validator/TemplateDescriptor.php b/core/lib/Thelia/Core/Template/Validator/TemplateDescriptor.php new file mode 100644 index 00000000..a7f31716 --- /dev/null +++ b/core/lib/Thelia/Core/Template/Validator/TemplateDescriptor.php @@ -0,0 +1,249 @@ + + */ +class TemplateDescriptor +{ + /** @var string the template directory name (e.g. 'default') */ + protected $name; + + /** @var int the template type (front, back, pdf) */ + protected $type; + + /** @var array */ + protected $languages = []; + + /** @var array */ + protected $descriptives = []; + + /** @var string */ + protected $theliaVersion; + + /** @var string */ + protected $version; + + /** @var TemplateDefinition */ + protected $parent = null; + + /** @var string */ + protected $documentation; + + /** @var string */ + protected $stability; + + /** @var array */ + protected $authors = []; + + /** + * TemplateDescriptor constructor. + * @param string $name + * @param int $type + */ + public function __construct($name, $type) + { + $this->name = $name; + $this->type = $type; + } + + /** + * @return string + */ + public function getName() + { + return $this->name; + } + + /** + * @param string $name + * @return $this + */ + public function setName($name) + { + $this->name = $name; + return $this; + } + + /** + * @return int + */ + public function getType() + { + return $this->type; + } + + /** + * @param int $type + * @return $this + */ + public function setType($type) + { + $this->type = $type; + return $this; + } + + /** + * @return array + */ + public function getLanguages() + { + return $this->languages; + } + + /** + * @param array $languages + * @return $this + */ + public function setLanguages($languages) + { + $this->languages = $languages; + return $this; + } + + /** + * @return array + */ + public function getDescriptives() + { + return $this->descriptives; + } + + /** + * @param array $descriptives + * @return $this + */ + public function setDescriptives($descriptives) + { + $this->descriptives = $descriptives; + return $this; + } + + /** + * @return string + */ + public function getTheliaVersion() + { + return $this->theliaVersion; + } + + /** + * @param string $theliaVersion + * @return $this + */ + public function setTheliaVersion($theliaVersion) + { + $this->theliaVersion = $theliaVersion; + return $this; + } + + /** + * @return string + */ + public function getVersion() + { + return $this->version; + } + + /** + * @param string $version + * @return $this + */ + public function setVersion($version) + { + $this->version = $version; + return $this; + } + + /** + * @return TemplateDefinition + */ + public function getParent() + { + return $this->parent; + } + + /** + * @param TemplateDefinition $parent + * @return $this + */ + public function setParent($parent) + { + $this->parent = $parent; + return $this; + } + + public function hasParent() + { + return null !== $this->parent; + } + + /** + * @return string + */ + public function getDocumentation() + { + return $this->documentation; + } + + /** + * @param string $documentation + * @return $this + */ + public function setDocumentation($documentation) + { + $this->documentation = $documentation; + return $this; + } + + /** + * @return string + */ + public function getStability() + { + return $this->stability; + } + + /** + * @param string $stability + * @return $this + */ + public function setStability($stability) + { + $this->stability = $stability; + return $this; + } + + /** + * @return array + */ + public function getAuthors() + { + return $this->authors; + } + + /** + * @param array $authors + * @return $this + */ + public function setAuthors($authors) + { + $this->authors = $authors; + return $this; + } +} diff --git a/core/lib/Thelia/Core/Template/Validator/TemplateDescriptorValidator.php b/core/lib/Thelia/Core/Template/Validator/TemplateDescriptorValidator.php new file mode 100644 index 00000000..6dcddf6e --- /dev/null +++ b/core/lib/Thelia/Core/Template/Validator/TemplateDescriptorValidator.php @@ -0,0 +1,140 @@ + + */ +class TemplateDescriptorValidator +{ + protected static $versions = [ + '1' => 'template-1_0.xsd', + ]; + + /** @var Finder */ + protected $xsdFinder; + + protected $xmlDescriptorPath; + + /** + * TemplateDescriptorValidator constructor. + * + * @param string $xmlDescriptorPath the path to the template XML descriprot + */ + public function __construct($xmlDescriptorPath) + { + $this->xmlDescriptorPath = $xmlDescriptorPath; + + $this->xsdFinder = new Finder(); + $this->xsdFinder + ->name('*.xsd') + ->in(__DIR__ . '/schema/template/'); + } + + /** + * @param string $version the XSD version to use,, or null to use the latest version + * @return $this + * @throw InvalidDescriptorException + */ + public function validate($version = null) + { + $dom = new \DOMDocument(); + $errors = []; + + if ($dom->load($this->xmlDescriptorPath)) { + /** @var \SplFileInfo $xsdFile */ + foreach ($this->xsdFinder as $xsdFile) { + $xsdVersion = array_search($xsdFile->getBasename(), self::$versions); + + if (false === $xsdVersion || (null !== $version && $version != $xsdVersion)) { + continue; + } + + $errors = $this->schemaValidate($dom, $xsdFile); + + if (\count($errors) === 0) { + return $this; + } + } + } + + throw new InvalidDescriptorException( + sprintf( + "%s file is not a valid template descriptor : %s", + $this->xmlDescriptorPath, + implode(", ", $errors) + ) + ); + } + + /** + * Validate the schema of a XML file with a given xsd file + * + * @param \DOMDocument $dom The XML document + * @param \SplFileInfo $xsdFile The XSD file + * @return array an array of errors if validation fails, otherwise an empty array + */ + protected function schemaValidate(\DOMDocument $dom, \SplFileInfo $xsdFile) + { + $errorMessages = []; + + try { + libxml_use_internal_errors(true); + + if (!$dom->schemaValidate($xsdFile->getRealPath())) { + $errors = libxml_get_errors(); + + foreach ($errors as $error) { + $errorMessages[] = sprintf( + 'XML error "%s" [%d] (Code %d) in %s on line %d column %d' . "\n", + $error->message, + $error->level, + $error->code, + $error->file, + $error->line, + $error->column + ); + } + + libxml_clear_errors(); + } + + libxml_use_internal_errors(false); + } catch (\Exception $ex) { + libxml_use_internal_errors(false); + } + + return $errorMessages; + } + + /** + * @return \SimpleXMLElement + */ + public function getDescriptor() + { + if (file_exists($this->xmlDescriptorPath)) { + $this->validate(); + + return @simplexml_load_file($this->xmlDescriptorPath); + } + + Tlog::getInstance()->addWarning("Template descriptor $this->xmlDescriptorPath does not exists."); + } +} diff --git a/core/lib/Thelia/Core/Template/Validator/TemplateValidator.php b/core/lib/Thelia/Core/Template/Validator/TemplateValidator.php new file mode 100644 index 00000000..4ebfe8fa --- /dev/null +++ b/core/lib/Thelia/Core/Template/Validator/TemplateValidator.php @@ -0,0 +1,209 @@ + + */ +class TemplateValidator +{ + protected $templatePath; + + /** @var TemplateDescriptorValidator */ + protected $templateDescriptor; + + /** @var TemplateDefinition */ + protected $templateDefinition; + + protected $templateVersion; + + /** @var array array of errors */ + protected $errors = []; + + /** @var \SimpleXMLElement */ + protected $xmlDescriptorContent; + + /** + * TemplateValidator constructor. + * @param $templatePath + * @throws \Exception + */ + public function __construct($templatePath) + { + $templateValidator = new TemplateDescriptorValidator($templatePath . DS . 'template.xml'); + + $this->xmlDescriptorContent = $templateValidator->getDescriptor(); + } + + /** + * @return mixed + */ + public function getTemplateVersion() + { + return $this->templateVersion; + } + + + /** + * @return array + */ + public function getErrors() + { + return $this->errors; + } + + /** + * @param string $name the template directory name + * @param int $type the template type (front, back, etc.) + * @return TemplateDescriptor the template descriptor + * @throws \Exception + */ + public function getTemplateDefinition($name, $type) + { + $templateDescriptor = new TemplateDescriptor($name, $type); + + $templateDescriptor + ->setName($name) + ->setType($type) + ; + + if (! empty($this->xmlDescriptorContent)) { + $templateDescriptor + ->setVersion((string)$this->xmlDescriptorContent->version) + ->setLanguages($this->getTemplateLanguages()) + ->setDescriptives($this->getTemplateDescriptives()) + ->setAuthors($this->getTemplateAuthors()) + ->setTheliaVersion((string)$this->xmlDescriptorContent->thelia) + ->setStability((string)$this->xmlDescriptorContent->stability) + ->setDocumentation((string)$this->xmlDescriptorContent->documentation) + ; + + $this->checkVersion($templateDescriptor); + + if (! empty($this->xmlDescriptorContent->parent)) { + // Just try to instantiate template definition for the parent template + // An exception will be thrown if something goes wrong. + try { + $templateDescriptor->setParent( + new TemplateDefinition( + (string) $this->xmlDescriptorContent->parent, + $type + ) + ); + } catch (\Exception $ex) { + // The Translator could not be initialized, take care of this. + try { + $message = Translator::getInstance()->trans( + "The parent template \"%parent\" of template \"%name\" could not be found", + [ + '%parent' => $templateDescriptor->getParent()->getName(), + '%name' => $templateDescriptor->getName(), + ] + ); + } catch (\Exception $ex) { + $message = sprintf( + "The parent template \"%s\" of template \"%s\" could not be found", + $templateDescriptor->getParent()->getName(), + $templateDescriptor->getName() + ); + } + + throw new TemplateException($message); + } + } + } + + return $templateDescriptor; + } + + /** + * @param TemplateDescriptor $templateDescriptor + */ + protected function checkVersion($templateDescriptor) + { + if ($templateDescriptor->getTheliaVersion()) { + if (!Version::test(Thelia::THELIA_VERSION, $templateDescriptor->getTheliaVersion(), false, ">=")) { + // The Translator could not be initialized, take care of this. + try { + $message = Translator::getInstance()->trans( + "The template \"%name\" requires Thelia %version or newer", + [ + '%name' => $templateDescriptor->getName(), + '%version' => $templateDescriptor->getTheliaVersion() + ] + ); + } catch (\Exception $ex) { + $message = sprintf( + "The template \"%s\" requires Thelia %s or newer", + $templateDescriptor->getName(), + $templateDescriptor->getTheliaVersion() + ); + } + + throw new TemplateException($message); + } + } + } + + protected function getTemplateLanguages() + { + $languages = []; + foreach ($this->xmlDescriptorContent->languages->language as $language) { + $languages[] = (string)$language; + } + + return $languages; + } + + protected function getTemplateDescriptives() + { + $descriptives = []; + foreach ($this->xmlDescriptorContent->descriptive as $descriptive) { + $descriptives[(string)$descriptive['locale']] = [ + 'title' => (string)$descriptive->title, + 'subtitle' => (string)$descriptive->subtitle, + 'description' => (string)$descriptive->description, + 'postscriptum' => (string)$descriptive->postscriptum, + ]; + } + + return $descriptives; + } + + protected function getTemplateAuthors() + { + $authors = []; + + if (0 !== \count($this->xmlDescriptorContent->authors->author)) { + foreach ($this->xmlDescriptorContent->authors->author as $author) { + $authors[] = [ + (string)$author->name, + (string)$author->company, + (string)$author->email, + (string)$author->website + ]; + } + } + + return $authors; + } +} diff --git a/core/lib/Thelia/Core/Template/Validator/schema/template/template-1_0.xsd b/core/lib/Thelia/Core/Template/Validator/schema/template/template-1_0.xsd new file mode 100644 index 00000000..c90c003b --- /dev/null +++ b/core/lib/Thelia/Core/Template/Validator/schema/template/template-1_0.xsd @@ -0,0 +1,133 @@ + + + + + + + + + Template description, + + + + + + + + + + + An ISO 639 locale code + + + + + + + + The template extended by this template. Missing html files and assets will be searched in this template + + + + + + Languages supported by this template : fr_FR, en_US, ... + + + + + + + + + + + + + + + + + Template version + + + + + + Template authors + + + + + + + + + + + + + + + + + + + + Template tags + + + + + + + + + + + minimum required version of Thelia in 'dot' format (for example 1.2.3.4) + + + + + + current template stability: alpha, beta, rc, prod + + + + + + + + + + + + + + + The name of the directory containing te documentation, relative to this template directory. + + + + + + URL to test if a new version of the template exists. Will be called with two get parameters : template name, current version + + + + + + URL to download the new version of the template. Will be called with two get parameters : template name, current version + + + + + + diff --git a/core/lib/Thelia/Core/Thelia.php b/core/lib/Thelia/Core/Thelia.php new file mode 100644 index 00000000..15e74282 --- /dev/null +++ b/core/lib/Thelia/Core/Thelia.php @@ -0,0 +1,592 @@ + + */ + +use Propel\Runtime\Connection\ConnectionInterface; +use Propel\Runtime\DataFetcher\PDODataFetcher; +use Propel\Runtime\Propel; +use Symfony\Component\Config\FileLocator; +use Symfony\Component\Config\Loader\LoaderInterface; +use Symfony\Component\Debug\Debug; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Definition; +use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag; +use Symfony\Component\DependencyInjection\Reference; +use Symfony\Component\Finder\Finder; +use Symfony\Component\HttpKernel\Kernel; +use Thelia\Core\DependencyInjection\Loader\XmlFileLoader; +use Thelia\Core\Event\TheliaEvents; +use Thelia\Core\Propel\Schema\SchemaLocator; +use Thelia\Core\Template\TemplateDefinition; +use Thelia\Core\Template\TemplateHelperInterface; +use Thelia\Core\Translation\Translator; +use Thelia\Log\Tlog; +use Thelia\Model\Module; +use Thelia\Model\ModuleQuery; +use Thelia\Module\ModuleManagement; + +class Thelia extends Kernel +{ + const THELIA_VERSION = '2.4.3'; + + public function __construct($environment, $debug) + { + parent::__construct($environment, $debug); + + if ($debug) { + Debug::enable(); + } + } + + public static function isInstalled() + { + return file_exists(THELIA_CONF_DIR . 'database.yml'); + } + + protected function checkMySQLConfigurations(ConnectionInterface $con) + { + // TODO : add cache for this test + /** @var PDODataFetcher $result */ + $result = $con->query("SELECT VERSION() as version, @@SESSION.sql_mode as session_sql_mode"); + + if ($result && $data = $result->fetch(\PDO::FETCH_ASSOC)) { + $sessionSqlMode = explode(',', $data['session_sql_mode']); + if (empty($sessionSqlMode[0])) { + unset($sessionSqlMode[0]); + } + $canUpdate = false; + + // MariaDB is not impacted by this problem + if (false === strpos($data['version'], 'MariaDB')) { + // MySQL 5.6+ compatibility + if (version_compare($data['version'], '5.6.0', '>=')) { + // add NO_ENGINE_SUBSTITUTION + if (!\in_array('NO_ENGINE_SUBSTITUTION', $sessionSqlMode)) { + $sessionSqlMode[] = 'NO_ENGINE_SUBSTITUTION'; + $canUpdate = true; + Tlog::getInstance()->addWarning("Add sql_mode NO_ENGINE_SUBSTITUTION. Please configure your MySQL server."); + } + + // remove STRICT_TRANS_TABLES + if (($key = array_search('STRICT_TRANS_TABLES', $sessionSqlMode)) !== false) { + unset($sessionSqlMode[$key]); + $canUpdate = true; + Tlog::getInstance()->addWarning("Remove sql_mode STRICT_TRANS_TABLES. Please configure your MySQL server."); + } + + // remove ONLY_FULL_GROUP_BY + if (($key = array_search('ONLY_FULL_GROUP_BY', $sessionSqlMode)) !== false) { + unset($sessionSqlMode[$key]); + $canUpdate = true; + Tlog::getInstance()->addWarning("Remove sql_mode ONLY_FULL_GROUP_BY. Please configure your MySQL server."); + } + } + } else { + // MariaDB 10.2.4+ compatibility + if (version_compare($data['version'], '10.2.4', '>=')) { + // remove STRICT_TRANS_TABLES + if (($key = array_search('STRICT_TRANS_TABLES', $sessionSqlMode)) !== false) { + unset($sessionSqlMode[$key]); + $canUpdate = true; + Tlog::getInstance()->addWarning("Remove sql_mode STRICT_TRANS_TABLES. Please configure your MySQL server."); + } + } + + if (version_compare($data['version'], '10.1.7', '>=')) { + if (!\in_array('NO_ENGINE_SUBSTITUTION', $sessionSqlMode)) { + $sessionSqlMode[] = 'NO_ENGINE_SUBSTITUTION'; + $canUpdate = true; + Tlog::getInstance()->addWarning("Add sql_mode NO_ENGINE_SUBSTITUTION. Please configure your MySQL server."); + } + } + } + + if (! empty($canUpdate)) { + if (null === $con->query("SET SESSION sql_mode='" . implode(',', $sessionSqlMode) . "';")) { + throw new \RuntimeException('Failed to set MySQL global and session sql_mode'); + } + } + } else { + Tlog::getInstance()->addWarning("Failed to get MySQL version and sql_mode"); + } + } + + /** + * Gets the container's base class. + * + * All names except Container must be fully qualified. + * + * @return string + */ + protected function getContainerBaseClass() + { + return '\Thelia\Core\DependencyInjection\TheliaContainer'; + } + + /** + * @inheritDoc + * @throws \Exception + */ + public function boot() + { + // initialize Propel, building its cache if necessary + $propelSchemaLocator = new SchemaLocator( + THELIA_CONF_DIR, + THELIA_MODULE_DIR + ); + $propelInitService = new PropelInitService( + $this->getEnvironment(), + $this->isDebug(), + $this->getEnvParameters(), + $propelSchemaLocator + ); + + $propelConnectionAvailable = $this->initializePropelService(false, $cacheRefresh); + + if ($propelConnectionAvailable) { + $theliaDatabaseConnection = Propel::getConnection('thelia'); + $this->checkMySQLConfigurations($theliaDatabaseConnection); + } + + parent::boot(); + + $this->getContainer()->set('thelia.propel.schema.locator', $propelSchemaLocator); + $this->getContainer()->set('thelia.propel.init', $propelInitService); + + if ($cacheRefresh) { + $moduleManagement = new ModuleManagement($this->getContainer()); + $moduleManagement->updateModules($this->getContainer()); + } + + if ($propelConnectionAvailable) { + $theliaDatabaseConnection->setEventDispatcher($this->getContainer()->get('event_dispatcher')); + } + + if (self::isInstalled()) { + $this->getContainer()->get('event_dispatcher')->dispatch(TheliaEvents::BOOT); + } + } + + /** + * @param $forcePropelCacheGeneration + * @param $cacheRefresh + * @return bool + * @throws \Throwable + */ + public function initializePropelService($forcePropelCacheGeneration, &$cacheRefresh) + { + $cacheRefresh = false; + + // initialize Propel, building its cache if necessary + $propelSchemaLocator = new SchemaLocator( + THELIA_CONF_DIR, + THELIA_MODULE_DIR + ); + + $propelInitService = new PropelInitService( + $this->getEnvironment(), + $this->isDebug(), + $this->getEnvParameters(), + $propelSchemaLocator + ); + + return $propelInitService->init($forcePropelCacheGeneration, $cacheRefresh); + } + + /** + * Add all module's standard templates to the parser environment + * + * @param Definition $parser the parser + * @param Module $module the Module. + */ + protected function addStandardModuleTemplatesToParserEnvironment($parser, $module) + { + $stdTpls = TemplateDefinition::getStandardTemplatesSubdirsIterator(); + + foreach ($stdTpls as $templateType => $templateSubdirName) { + $this->addModuleTemplateToParserEnvironment($parser, $module, $templateType, $templateSubdirName); + } + } + + /** + * Add a module template directory to the parser environment + * + * @param Definition $parser the parser + * @param Module $module the Module. + * @param string $templateType the template type (one of the TemplateDefinition type constants) + * @param string $templateSubdirName the template subdirectory name (one of the TemplateDefinition::XXX_SUBDIR constants) + */ + protected function addModuleTemplateToParserEnvironment($parser, $module, $templateType, $templateSubdirName) + { + // Get template path + $templateDirectory = $module->getAbsoluteTemplateDirectoryPath($templateSubdirName); + try { + $templateDirBrowser = new \DirectoryIterator($templateDirectory); + + $code = ucfirst($module->getCode()); + + /* browse the directory */ + foreach ($templateDirBrowser as $templateDirContent) { + /* is it a directory which is not . or .. ? */ + if ($templateDirContent->isDir() && ! $templateDirContent->isDot()) { + $parser->addMethodCall( + 'addTemplateDirectory', + array( + $templateType, + $templateDirContent->getFilename(), + $templateDirContent->getPathName(), + $code + ) + ); + } + } + } catch (\UnexpectedValueException $ex) { + // The directory does not exists, ignore it. + } + } + + /** + * Load some configuration + * Initialize all plugins + * + * @param ContainerBuilder $container + * @throws \Exception + */ + protected function loadConfiguration(ContainerBuilder $container) + { + $loader = new XmlFileLoader($container, new FileLocator(__DIR__ . "/../Config/Resources")); + $finder = Finder::create() + ->name('*.xml') + ->depth(0) + ->in(__DIR__ . "/../Config/Resources"); + + /** @var \SplFileInfo $file */ + foreach ($finder as $file) { + $loader->load($file->getBaseName()); + } + + if (\defined("THELIA_INSTALL_MODE") === false) { + $modules = ModuleQuery::getActivated(); + + $translationDirs = array(); + + + + /** @var Module $module */ + foreach ($modules as $module) { + try { + $definition = new Definition(); + $definition->setClass($module->getFullNamespace()); + $definition->addMethodCall("setContainer", array(new Reference('service_container'))); + + $container->setDefinition( + "module." . $module->getCode(), + $definition + ); + + $compilers = \call_user_func(array($module->getFullNamespace(), 'getCompilers')); + + foreach ($compilers as $compiler) { + if (\is_array($compiler)) { + $container->addCompilerPass($compiler[0], $compiler[1]); + } else { + $container->addCompilerPass($compiler); + } + } + + $loader = new XmlFileLoader($container, new FileLocator($module->getAbsoluteConfigPath())); + $loader->load("config.xml", "module." . $module->getCode()); + + $envConfigFileName = sprintf("config_%s.xml", $this->environment); + $envConfigFile = sprintf('%s%s%s', $module->getAbsoluteConfigPath(), DS, $envConfigFileName); + + if (is_file($envConfigFile) && is_readable($envConfigFile)) { + $loader->load($envConfigFileName, "module." . $module->getCode()); + } + } catch (\Exception $e) { + Tlog::getInstance()->addError( + sprintf("Failed to load module %s: %s", $module->getCode(), $e->getMessage()), + $e + ); + } + } + + $parser = $container->getDefinition('thelia.parser'); + + /** @var \Thelia\Core\Template\TemplateHelperInterface $templateHelper */ + $templateHelper = $container->get('thelia.template_helper'); + + /** @var Module $module */ + foreach ($modules as $module) { + try { + $this->loadModuleTranslationDirectories($module, $translationDirs, $templateHelper); + + $this->addStandardModuleTemplatesToParserEnvironment($parser, $module); + } catch (\Exception $e) { + Tlog::getInstance()->addError( + sprintf("Failed to load module %s: %s", $module->getCode(), $e->getMessage()), + $e + ); + } + } + + // Load core translation + $translationDirs['core'] = THELIA_LIB . 'Config' . DS . 'I18n'; + + // Load core translation + $translationDirs[Translator::GLOBAL_FALLBACK_DOMAIN] = THELIA_LOCAL_DIR . 'I18n'; + + // Standard templates (front, back, pdf, mail) + /** @var TemplateDefinition $templateDefinition */ + foreach ($templateHelper->getStandardTemplateDefinitions() as $templateDefinition) { + // Load parent templates transaltions, the current template translations. + $templateList = array_merge( + $templateDefinition->getParentList(), + [ $templateDefinition ] + ); + + /** @var TemplateDefinition $tplDef */ + foreach ($templateList as $tplDef) { + if (is_dir($dir = $tplDef->getAbsoluteI18nPath())) { + $translationDirs[$tplDef->getTranslationDomain()] = $dir; + } + } + } + + if ($translationDirs) { + $this->loadTranslation($container, $translationDirs); + } + } + } + + /** + * @param Module $module + * @param array $translationDirs + * @param TemplateHelperInterface $templateHelper + */ + private function loadModuleTranslationDirectories(Module $module, array &$translationDirs, $templateHelper) + { + // Core module translation + if (is_dir($dir = $module->getAbsoluteI18nPath())) { + $translationDirs[$module->getTranslationDomain()] = $dir; + } + + // Admin includes translation + if (is_dir($dir = $module->getAbsoluteAdminIncludesI18nPath())) { + $translationDirs[$module->getAdminIncludesTranslationDomain()] = $dir; + } + + // Module back-office template, if any + $templates = + $templateHelper->getList( + TemplateDefinition::BACK_OFFICE, + $module->getAbsoluteTemplateBasePath() + ); + + foreach ($templates as $template) { + $translationDirs[$module->getBackOfficeTemplateTranslationDomain($template->getName())] = + $module->getAbsoluteBackOfficeI18nTemplatePath($template->getName()); + } + + // Module front-office template, if any + $templates = + $templateHelper->getList( + TemplateDefinition::FRONT_OFFICE, + $module->getAbsoluteTemplateBasePath() + ); + + foreach ($templates as $template) { + $translationDirs[$module->getFrontOfficeTemplateTranslationDomain($template->getName())] = + $module->getAbsoluteFrontOfficeI18nTemplatePath($template->getName()); + } + + // Module pdf template, if any + $templates = + $templateHelper->getList( + TemplateDefinition::PDF, + $module->getAbsoluteTemplateBasePath() + ); + + foreach ($templates as $template) { + $translationDirs[$module->getPdfTemplateTranslationDomain($template->getName())] = + $module->getAbsolutePdfI18nTemplatePath($template->getName()); + } + + // Module email template, if any + $templates = + $templateHelper->getList( + TemplateDefinition::EMAIL, + $module->getAbsoluteTemplateBasePath() + ); + + foreach ($templates as $template) { + $translationDirs[$module->getEmailTemplateTranslationDomain($template->getName())] = + $module->getAbsoluteEmailI18nTemplatePath($template->getName()); + } + } + + private function loadTranslation(ContainerBuilder $container, array $dirs) + { + $translator = $container->getDefinition('thelia.translator'); + + foreach ($dirs as $domain => $dir) { + try { + $finder = Finder::create() + ->files() + ->depth(0) + ->in($dir); + + /** @var \DirectoryIterator $file */ + foreach ($finder as $file) { + list($locale, $format) = explode('.', $file->getBaseName(), 2); + + $translator->addMethodCall('addResource', array($format, (string) $file, $locale, $domain)); + } + } catch (\InvalidArgumentException $ex) { + // Ignore missing I18n directories + Tlog::getInstance()->addWarning("loadTranslation: missing $dir directory"); + } + } + } + + /** + * + * initialize session in Request object + * + * All param must be change in Config table + * + * @param \Symfony\Component\HttpFoundation\Request $request + */ + + /** + * Gets a new ContainerBuilder instance used to build the service container. + * + * @return ContainerBuilder + */ + protected function getContainerBuilder() + { + return new TheliaContainerBuilder(new ParameterBag($this->getKernelParameters())); + } + + /** + * Builds the service container. + * + * @return ContainerBuilder The compiled service container + * @throws \Exception + */ + protected function buildContainer() + { + /** @var TheliaContainerBuilder $container */ + $container = parent::buildContainer(); + + $this->loadConfiguration($container); + $container->customCompile(); + + return $container; + } + + /** + * Gets the cache directory. + * + * @return string The cache directory + * + * @api + */ + public function getCacheDir() + { + if (\defined('THELIA_ROOT')) { + return THELIA_CACHE_DIR . $this->environment; + } else { + return parent::getCacheDir(); + } + } + + /** + * Gets the log directory. + * + * @return string The log directory + * + * @api + */ + public function getLogDir() + { + if (\defined('THELIA_ROOT')) { + return THELIA_LOG_DIR; + } else { + return parent::getLogDir(); + } + } + + /** + * Returns the kernel parameters. + * + * @return array An array of kernel parameters + */ + protected function getKernelParameters() + { + $parameters = parent::getKernelParameters(); + + $parameters["thelia.root_dir"] = THELIA_ROOT; + $parameters["thelia.core_dir"] = dirname(__DIR__); // This class is in core/lib/Thelia/Core. + $parameters["thelia.module_dir"] = THELIA_MODULE_DIR; + + return $parameters; + } + + /** + * return available bundle + * + * Part of Symfony\Component\HttpKernel\KernelInterface + * + * @return Bundle\TheliaBundle[] An array of bundle instances. + */ + public function registerBundles() + { + $bundles = array( + /* TheliaBundle contain all the dependency injection description */ + new Bundle\TheliaBundle(), + ); + + /** + * OTHER CORE BUNDLE CAN BE DECLARE HERE AND INITIALIZE WITH SPECIFIC CONFIGURATION + * + * HOW TO DECLARE OTHER BUNDLE ? ETC + */ + + return $bundles; + } + + /** + * Loads the container configuration + * + * part of Symfony\Component\HttpKernel\KernelInterface + * + * @param LoaderInterface $loader A LoaderInterface instance + * + * @api + */ + public function registerContainerConfiguration(LoaderInterface $loader) + { + // Nothing is load here but it's possible to load container configuration here. + // exemple in sf2 : $loader->load(__DIR__.'/config/config_'.$this->getEnvironment().'.yml'); + } +} diff --git a/core/lib/Thelia/Core/TheliaContainerBuilder.php b/core/lib/Thelia/Core/TheliaContainerBuilder.php new file mode 100644 index 00000000..eb6a9c72 --- /dev/null +++ b/core/lib/Thelia/Core/TheliaContainerBuilder.php @@ -0,0 +1,34 @@ + + */ +class TheliaContainerBuilder extends ContainerBuilder +{ + public function compile() + { + } + + public function customCompile() + { + parent::compile(); + } +} diff --git a/core/lib/Thelia/Core/TheliaHttpKernel.php b/core/lib/Thelia/Core/TheliaHttpKernel.php new file mode 100644 index 00000000..cb6e0480 --- /dev/null +++ b/core/lib/Thelia/Core/TheliaHttpKernel.php @@ -0,0 +1,80 @@ + + */ + +class TheliaHttpKernel extends HttpKernel +{ + protected static $session; + + protected $container; + + public function __construct( + EventDispatcherInterface $dispatcher, + ContainerInterface $container, + ControllerResolverInterface $controllerResolver, + RequestStack $requestStack + ) { + parent::__construct($dispatcher, $controllerResolver, $requestStack); + + $this->container = $container; + } + + public function getContainer() + { + return $this->container; + } + + /** + * Handles a Request to convert it to a Response. + * + * When $catch is true, the implementation must catch all exceptions + * and do its best to convert them to a Response instance. + * + * @param Request $request A Request instance + * @param integer $type The type of the request + * (one of HttpKernelInterface::MASTER_REQUEST or HttpKernelInterface::SUB_REQUEST) + * @param Boolean $catch Whether to catch exceptions or not + * + * @return Response A Response instance + * + * @throws \Exception When an Exception occurs during processing + * + * @api + * + */ + public function handle(Request $request, $type = HttpKernelInterface::MASTER_REQUEST, $catch = true) + { + // for backward compatibility + $this->container->set('request', $request); + $this->container->get('request.context')->fromRequest($request); + + $response = parent::handle($request, $type, $catch); + + return $response; + } +} diff --git a/core/lib/Thelia/Core/TheliaKernelEvents.php b/core/lib/Thelia/Core/TheliaKernelEvents.php new file mode 100644 index 00000000..e2d1e58b --- /dev/null +++ b/core/lib/Thelia/Core/TheliaKernelEvents.php @@ -0,0 +1,28 @@ + + */ +final class TheliaKernelEvents +{ + const SESSION = "thelia_kernel.session"; + + + // -- Kernel Error Message Handle --------------------------- + + const THELIA_HANDLE_ERROR = "thelia_kernel.handle_error"; +} diff --git a/core/lib/Thelia/Core/Translation/Translator.php b/core/lib/Thelia/Core/Translation/Translator.php new file mode 100644 index 00000000..861acef9 --- /dev/null +++ b/core/lib/Thelia/Core/Translation/Translator.php @@ -0,0 +1,117 @@ +container = $container; + // Allow singleton style calls once intanciated. + // For this to work, the Translator service has to be instanciated very early. This is done manually + // in TheliaHttpKernel, by calling $this->container->get('thelia.translator'); + parent::__construct(null); + self::$instance = $this; + } + + /** + * Return this class instance, only once instanciated. + * + * @throws \RuntimeException if the class has not been instanciated. + * @return \Thelia\Core\Translation\Translator the instance. + */ + public static function getInstance() + { + if (self::$instance == null) { + throw new \RuntimeException("Translator instance is not initialized."); + } + return self::$instance; + } + + public function getLocale() + { + if ($this->container->has('request_stack')) { + /** @var RequestStack $requestStack */ + $requestStack = $this->container->get('request_stack'); + if (null !== $request = $requestStack->getCurrentRequest()) { + return $request->getSession()->getLang()->getLocale(); + } + } + + return $this->locale; + } + + /** + * {@inheritdoc} + * + * @api + */ + public function trans( + $id, + array $parameters = array(), + $domain = 'core', + $locale = null, + $return_default_if_not_available = true, + $useFallback = true + ) { + if (null === $locale) { + $locale = $this->getLocale(); + } + + if (!isset($this->catalogues[$locale])) { + $this->loadCatalogue($locale); + } + + // global translations + if ($useFallback) { + $fallbackId = sprintf(self::GLOBAL_FALLBACK_KEY, $domain, (string) $id); + + if ($this->catalogues[$locale]->has($fallbackId, self::GLOBAL_FALLBACK_DOMAIN)) { + return parent::trans($fallbackId, $parameters, self::GLOBAL_FALLBACK_DOMAIN, $locale); + } + + if ($this->catalogues[$locale]->has($id, self::GLOBAL_FALLBACK_DOMAIN)) { + // global translations + return parent::trans($id, $parameters, self::GLOBAL_FALLBACK_DOMAIN, $locale); + } + } + + if ($this->catalogues[$locale]->has((string) $id, $domain)) { + return parent::trans($id, $parameters, $domain, $locale); + } else { + if ($return_default_if_not_available) { + return strtr($id, $parameters); + } else { + return ''; + } + } + } +} diff --git a/core/lib/Thelia/Coupon/BaseFacade.php b/core/lib/Thelia/Coupon/BaseFacade.php new file mode 100644 index 00000000..c050e0b7 --- /dev/null +++ b/core/lib/Thelia/Coupon/BaseFacade.php @@ -0,0 +1,357 @@ + + * + */ +class BaseFacade implements FacadeInterface +{ + /** @var ContainerInterface Service Container */ + protected $container = null; + + /** @var Translator Service Translator */ + protected $translator = null; + + /** @var ParserInterface The thelia parser */ + private $parser = null; + + /** + * Constructor + * + * @param ContainerInterface $container Service container + */ + public function __construct(ContainerInterface $container) + { + $this->container = $container; + } + + /** + * Return a Cart a CouponManager can process + * + * @return \Thelia\Model\Cart + */ + public function getCart() + { + return $this->getRequest()->getSession()->getSessionCart($this->getDispatcher()); + } + + /** + * Return an Address a CouponManager can process + * + * @return \Thelia\Model\Address + */ + public function getDeliveryAddress() + { + try { + return AddressQuery::create()->findPk( + $this->getRequest()->getSession()->getOrder()->getChoosenDeliveryAddress() + ); + } catch (\Exception $ex) { + throw new \LogicException("Failed to get delivery address (" . $ex->getMessage() . ")"); + } + } + + /** + * Return an Customer a CouponManager can process + * + * @return \Thelia\Model\Customer + */ + public function getCustomer() + { + return $this->container->get('thelia.securityContext')->getCustomerUser(); + } + + /** + * Return Checkout total price + * + * @return float + */ + public function getCheckoutTotalPrice() + { + return $this->getRequest()->getSession()->getOrder()->getTotalAmount(); + } + + /** + * Return Checkout total postage (only) price + * + * @return float + */ + public function getCheckoutPostagePrice() + { + return $this->getRequest()->getSession()->getOrder()->getPostage(); + } + + /** + * Return Products total price + * + * @param bool $withItemsInPromo if true, the discounted items are included in the total + * + * @return float + */ + public function getCartTotalPrice($withItemsInPromo = true) + { + $total = 0; + + $cartItems = $this->getRequest()->getSession()->getSessionCart($this->getDispatcher())->getCartItems(); + + foreach ($cartItems as $cartItem) { + if ($withItemsInPromo || ! $cartItem->getPromo()) { + $total += $cartItem->getTotalRealPrice(); + } + } + + return $total; + } + + /** + * @param bool $withItemsInPromo + * @return float|int + * @throws \Propel\Runtime\Exception\PropelException + */ + public function getCartTotalTaxPrice($withItemsInPromo = true) + { + $taxCountry = $this->getContainer()->get('thelia.taxEngine')->getDeliveryCountry(); + $cartItems = $this->getRequest()->getSession()->getSessionCart($this->getDispatcher())->getCartItems(); + + $total = 0; + + foreach ($cartItems as $cartItem) { + if ($withItemsInPromo || ! $cartItem->getPromo()) { + $total += $cartItem->getTotalRealTaxedPrice($taxCountry); + } + } + + return $total; + } + + /** + * @return Country the delivery country + */ + public function getDeliveryCountry() + { + return $this->getContainer()->get('thelia.taxEngine')->getDeliveryCountry(); + } + + /** + * Return the Checkout currency EUR|USD + * + * @return Currency + */ + public function getCheckoutCurrency() + { + return $this->getRequest()->getSession()->getCurrency()->getCode(); + } + + /** + * Return the number of Products in the Cart + * + * @return int + */ + public function getNbArticlesInCart() + { + return \count($this->getRequest()->getSession()->getSessionCart($this->getDispatcher())->getCartItems()); + } + + public function getNbArticlesInCartIncludeQuantity() + { + $cartItems = $this->getCart()->getCartItems(); + $quantity = 0; + + foreach ($cartItems as $cartItem) { + $quantity += $cartItem->getQuantity(); + } + + return $quantity; + } + + /** + * Return all Coupon given during the Checkout + * + * @return array Array of CouponInterface + */ + public function getCurrentCoupons() + { + $couponCodes = $this->getRequest()->getSession()->getConsumedCoupons(); + + if (null === $couponCodes) { + return array(); + } + /** @var CouponFactory $couponFactory */ + $couponFactory = $this->container->get('thelia.coupon.factory'); + + $coupons = []; + + foreach ($couponCodes as $couponCode) { + // Only valid coupons are returned + try { + if (false !== $couponInterface = $couponFactory->buildCouponFromCode($couponCode)) { + $coupons[] = $couponInterface; + } + } catch (\Exception $ex) { + // Just ignore the coupon and log the problem, just in case someone realize it. + Tlog::getInstance()->warning( + sprintf("Coupon %s ignored, exception occurred: %s", $couponCode, $ex->getMessage()) + ); + } + } + + return $coupons; + } + + /** + * Find one Coupon in the database from its code + * + * @param string $code Coupon code + * + * @return Coupon + */ + public function findOneCouponByCode($code) + { + $couponQuery = CouponQuery::create(); + + return $couponQuery->findOneByCode($code); + } + + /** + * Return platform Container + * + * @return Container + */ + public function getContainer() + { + return $this->container; + } + + /** + * Return platform TranslatorInterface + * + * @return TranslatorInterface + */ + public function getTranslator() + { + return $this->container->get('thelia.translator'); + } + + /** + * Return platform Parser + * + * @return ParserInterface + */ + public function getParser() + { + if ($this->parser == null) { + $this->parser = $this->container->get('thelia.parser'); + + // Define the current back-office template that should be used + $this->parser->setTemplateDefinition( + $this->parser->getTemplateHelper()->getActiveAdminTemplate() + ); + } + + return $this->parser; + } + + /** + * Return the main currency + * THe one used to set prices in BackOffice + * + * @return string + */ + public function getMainCurrency() + { + return $this->getRequest()->getSession()->getCurrency(); + } + + /** + * Return request + * + * @return Request + */ + public function getRequest() + { + return $this->container->get('request_stack')->getCurrentRequest(); + } + + /** + * Return Constraint Validator + * + * @return ConditionEvaluator + */ + public function getConditionEvaluator() + { + return $this->container->get('thelia.condition.validator'); + } + + /** + * Return all available currencies + * + * @return array of Currency + */ + public function getAvailableCurrencies() + { + $currencies = CurrencyQuery::create(); + + return $currencies->find(); + } + + /** + * Return the event dispatcher, + * + * @return \Symfony\Component\EventDispatcher\EventDispatcher + */ + public function getDispatcher() + { + return $this->container->get('event_dispatcher'); + } + + /** + * Add a coupon in session + * @param $couponCode + * @return mixed|void + */ + public function pushCouponInSession($couponCode) + { + $consumedCoupons = $this->getRequest()->getSession()->getConsumedCoupons(); + + if (!isset($consumedCoupons) || !$consumedCoupons) { + $consumedCoupons = array(); + } + + if (!isset($consumedCoupons[$couponCode])) { + // Prevent accumulation of the same Coupon on a Checkout + $consumedCoupons[$couponCode] = $couponCode; + + $this->getRequest()->getSession()->setConsumedCoupons($consumedCoupons); + } + } +} diff --git a/core/lib/Thelia/Coupon/CouponFactory.php b/core/lib/Thelia/Coupon/CouponFactory.php new file mode 100644 index 00000000..a7bde19a --- /dev/null +++ b/core/lib/Thelia/Coupon/CouponFactory.php @@ -0,0 +1,155 @@ + + * + */ +class CouponFactory +{ + /** @var ContainerInterface Service Container */ + protected $container = null; + + /** @var FacadeInterface Provide necessary value from Thelia*/ + protected $facade; + + /** + * Constructor + * + * @param ContainerInterface $container Service container + */ + public function __construct(ContainerInterface $container) + { + $this->container = $container; + $this->facade = $container->get('thelia.facade'); + } + + /** + * Build a CouponInterface from its database data + * + * @param string $couponCode Coupon code ex: XMAS + * @return CouponInterface + * @throws CouponExpiredException + * @throws CouponNoUsageLeftException + * @throws CouponNotReleaseException + */ + public function buildCouponFromCode($couponCode) + { + /** @var Coupon $couponModel */ + $couponModel = $this->facade->findOneCouponByCode($couponCode); + if ($couponModel === null) { + return false; + } + + // check if coupon is enabled + if (!$couponModel->getIsEnabled()) { + throw new InactiveCouponException($couponCode); + } + + $nowDateTime = new \DateTime(); + + // Check coupon start date + if ($couponModel->getStartDate() !== null && $couponModel->getStartDate() > $nowDateTime) { + throw new CouponNotReleaseException($couponCode); + } + + // Check coupon expiration date + if ($couponModel->getExpirationDate() < $nowDateTime) { + throw new CouponExpiredException($couponCode); + } + + // Check coupon usage count + if (! $couponModel->isUsageUnlimited()) { + if (null === $customer = $this->facade->getCustomer()) { + throw new UnmatchableConditionException($couponCode); + } + + if ($couponModel->getUsagesLeft($customer->getId()) <= 0) { + throw new CouponNoUsageLeftException($couponCode); + } + } + + /** @var CouponInterface $couponInterface */ + $couponInterface = $this->buildCouponFromModel($couponModel); + + if ($couponInterface && $couponInterface->getConditions()->count() == 0) { + throw new InvalidConditionException( + \get_class($couponInterface) + ); + } + + return $couponInterface; + } + + /** + * Build a CouponInterface from its Model data contained in the DataBase + * + * @param Coupon $model Database data + * + * @return CouponInterface ready to use CouponInterface object instance + */ + public function buildCouponFromModel(Coupon $model) + { + $isCumulative = ($model->getIsCumulative() == 1 ? true : false); + $isRemovingPostage = ($model->getIsRemovingPostage() == 1 ? true : false); + + if (!$this->container->has($model->getType())) { + return false; + } + + /** @var CouponInterface $couponManager*/ + $couponManager = $this->container->get($model->getType()); + $couponManager->set( + $this->facade, + $model->getCode(), + $model->getTitle(), + $model->getShortDescription(), + $model->getDescription(), + $model->getEffects(), + $isCumulative, + $isRemovingPostage, + $model->getIsAvailableOnSpecialOffers(), + $model->getIsEnabled(), + $model->getMaxUsage(), + $model->getExpirationDate(), + $model->getFreeShippingForCountries(), + $model->getFreeShippingForModules(), + $model->getPerCustomerUsageCount() + ); + + /** @var ConditionFactory $conditionFactory */ + $conditionFactory = $this->container->get('thelia.condition.factory'); + $conditions = $conditionFactory->unserializeConditionCollection( + $model->getSerializedConditions() + ); + + $couponManager->setConditions($conditions); + + return clone $couponManager; + } +} diff --git a/core/lib/Thelia/Coupon/CouponManager.php b/core/lib/Thelia/Coupon/CouponManager.php new file mode 100644 index 00000000..90b583fd --- /dev/null +++ b/core/lib/Thelia/Coupon/CouponManager.php @@ -0,0 +1,422 @@ + + * + */ +class CouponManager +{ + /** @var FacadeInterface Provides necessary value from Thelia */ + protected $facade = null; + + /** @var ContainerInterface Service Container */ + protected $container = null; + + /** @var array Available Coupons (Services) */ + protected $availableCoupons = array(); + + /** @var array Available Conditions (Services) */ + protected $availableConditions = array(); + + /** + * Constructor + * + * @param ContainerInterface $container Service container + */ + public function __construct(ContainerInterface $container) + { + $this->container = $container; + $this->facade = $container->get('thelia.facade'); + } + + /** + * Get Discount for the given Coupons + * @api + * @return float checkout discount + */ + public function getDiscount() + { + $discount = 0.00; + + $coupons = $this->facade->getCurrentCoupons(); + + if (\count($coupons) > 0) { + $couponsKept = $this->sortCoupons($coupons); + + $discount = $this->getEffect($couponsKept); + + // Just In Case test + $checkoutTotalPrice = $this->facade->getCartTotalTaxPrice(); + + if ($discount >= $checkoutTotalPrice) { + $discount = $checkoutTotalPrice; + } + } + + return round($discount, 2); + } + + /** + * @param $code + * @return mixed|void + */ + public function pushCouponInSession($code) + { + $this->facade->pushCouponInSession($code); + } + + /** + * Check if there is a Coupon removing Postage + * + * @param Order $order the order for which we have to check if postage is free + * + * @return bool + */ + public function isCouponRemovingPostage(Order $order) + { + $coupons = $this->facade->getCurrentCoupons(); + + if (\count($coupons) == 0) { + return false; + } + + $couponsKept = $this->sortCoupons($coupons); + + /** @var CouponInterface $coupon */ + foreach ($couponsKept as $coupon) { + if ($coupon->isRemovingPostage()) { + // Check if delivery country is on the list of countries for which delivery is free + // If the list is empty, the shipping is free for all countries. + $couponCountries = $coupon->getFreeShippingForCountries(); + + if (! $couponCountries->isEmpty()) { + if (null === $deliveryAddress = AddressQuery::create()->findPk($order->getChoosenDeliveryAddress())) { + continue; + } + + $countryValid = false; + + $deliveryCountryId = $deliveryAddress->getCountryId(); + + /** @var CouponCountry $couponCountry */ + foreach ($couponCountries as $couponCountry) { + if ($deliveryCountryId == $couponCountry->getCountryId()) { + $countryValid = true; + break; + } + } + + if (! $countryValid) { + continue; + } + } + + // Check if shipping method is on the list of methods for which delivery is free + // If the list is empty, the shipping is free for all methods. + $couponModules = $coupon->getFreeShippingForModules(); + + if (! $couponModules->isEmpty()) { + $moduleValid = false; + + $shippingModuleId = $order->getDeliveryModuleId(); + + /** @var CouponModule $couponModule */ + foreach ($couponModules as $couponModule) { + if ($shippingModuleId == $couponModule->getModuleId()) { + $moduleValid = true; + break; + } + } + + if (! $moduleValid) { + continue; + } + } + + // All conditions are met, the shipping is free ! + return true; + } + } + + return false; + } + + /** + * @return array + */ + public function getCouponsKept() + { + return $this->sortCoupons($this->facade->getCurrentCoupons()); + } + + /** + * Sort Coupon to keep + * Coupon not cumulative cancels previous + * + * @param array $coupons CouponInterface to process + * + * @return array Array of CouponInterface sorted + */ + protected function sortCoupons(array $coupons) + { + $couponsKept = array(); + + /** @var CouponInterface $coupon */ + foreach ($coupons as $coupon) { + if ($coupon && !$coupon->isExpired()) { + if ($coupon->isCumulative()) { + if (isset($couponsKept[0])) { + /** @var CouponInterface $previousCoupon */ + $previousCoupon = $couponsKept[0]; + if ($previousCoupon->isCumulative()) { + // Add Coupon + $couponsKept[] = $coupon; + } else { + // Reset Coupons, add last + $couponsKept = array($coupon); + } + } else { + // Reset Coupons, add last + $couponsKept = array($coupon); + } + } else { + // Reset Coupons, add last + $couponsKept = array($coupon); + } + } + } + + $coupons = $couponsKept; + $couponsKept = array(); + + /** @var CouponInterface $coupon */ + foreach ($coupons as $coupon) { + try { + if ($coupon->isMatching()) { + $couponsKept[] = $coupon; + } + } catch (UnmatchableConditionException $e) { + // ignore unmatchable coupon + continue; + } + } + + return $couponsKept; + } + + /** + * Process given Coupon in order to get their cumulative effects + * + * @param array $coupons CouponInterface to process + * + * @return float discount + */ + protected function getEffect(array $coupons) + { + $discount = 0.00; + /** @var CouponInterface $coupon */ + foreach ($coupons as $coupon) { + $discount += $coupon->exec($this->facade); + } + + return $discount; + } + + /** + * Add an available CouponManager (Services) + * + * @param CouponInterface $coupon CouponManager + */ + public function addAvailableCoupon(CouponInterface $coupon) + { + $this->availableCoupons[] = $coupon; + } + + /** + * Get all available CouponManagers (Services) + * + * @return array + */ + public function getAvailableCoupons() + { + return $this->availableCoupons; + } + + /** + * Add an available ConstraintManager (Services) + * + * @param ConditionInterface $condition ConditionInterface + */ + public function addAvailableCondition(ConditionInterface $condition) + { + $this->availableConditions[] = $condition; + } + + /** + * Get all available ConstraintManagers (Services) + * + * @return array + */ + public function getAvailableConditions() + { + return $this->availableConditions; + } + + /** + * Clear all data kept by coupons + */ + public function clear() + { + $coupons = $this->facade->getCurrentCoupons(); + + /** @var CouponInterface $coupon */ + foreach ($coupons as $coupon) { + $coupon->clear(); + } + } + + /** + * Decrement this coupon quantity + * + * To call when a coupon is consumed + * + * @param \Thelia\Model\Coupon $coupon Coupon consumed + * @param int|null $customerId the ID of the ordering customer + * + * @return int Usage left after decremental + */ + public function decrementQuantity(Coupon $coupon, $customerId = null) + { + if ($coupon->isUsageUnlimited()) { + return true; + } else { + try { + $usageLeft = $coupon->getUsagesLeft($customerId); + + if ($usageLeft > 0) { + // If the coupon usage is per user, add an entry to coupon customer usage count table + if ($coupon->getPerCustomerUsageCount()) { + if (null == $customerId) { + throw new \LogicException("Customer should not be null at this time."); + } + + $ccc = CouponCustomerCountQuery::create() + ->filterByCouponId($coupon->getId()) + ->filterByCustomerId($customerId) + ->findOne() + ; + + if ($ccc === null) { + $ccc = new CouponCustomerCount(); + + $ccc + ->setCustomerId($customerId) + ->setCouponId($coupon->getId()) + ->setCount(0); + } + + $newCount = 1 + $ccc->getCount(); + + $ccc + ->setCount($newCount) + ->save() + ; + + return $usageLeft - $newCount; + } else { + $coupon->setMaxUsage(--$usageLeft); + + $coupon->save(); + + return $usageLeft; + } + } + } catch (\Exception $ex) { + // Just log the problem. + Tlog::getInstance()->addError(sprintf("Failed to decrement coupon %s: %s", $coupon->getCode(), $ex->getMessage())); + } + } + + return false; + } + + /** + * Add a coupon usage, for the case the related order is canceled. + * + * @param Coupon $coupon + * @param int $customerId + */ + public function incrementQuantity(Coupon $coupon, $customerId = null) + { + if ($coupon->isUsageUnlimited()) { + return true; + } else { + try { + $usageLeft = $coupon->getUsagesLeft($customerId); + + // If the coupon usage is per user, remove an entry from coupon customer usage count table + if ($coupon->getPerCustomerUsageCount()) { + if (null == $customerId) { + throw new \LogicException("Customer should not be null at this time."); + } + + $ccc = CouponCustomerCountQuery::create() + ->filterByCouponId($coupon->getId()) + ->filterByCustomerId($customerId) + ->findOne() + ; + + if ($ccc !== null && $ccc->getCount() > 0) { + $newCount = $ccc->getCount() - 1; + + $ccc + ->setCount($newCount) + ->save(); + + return $usageLeft - $newCount; + } + } else { + // Ad one usage to coupon + $coupon->setMaxUsage(++$usageLeft); + + $coupon->save(); + + return $usageLeft; + } + } catch (\Exception $ex) { + // Just log the problem. + Tlog::getInstance()->addError(sprintf("Failed to increment coupon %s: %s", $coupon->getCode(), $ex->getMessage())); + } + } + + return false; + } +} diff --git a/core/lib/Thelia/Coupon/FacadeInterface.php b/core/lib/Thelia/Coupon/FacadeInterface.php new file mode 100644 index 00000000..4b3db0a9 --- /dev/null +++ b/core/lib/Thelia/Coupon/FacadeInterface.php @@ -0,0 +1,197 @@ + + * + */ +interface FacadeInterface +{ + /** + * Constructor + * + * @param ContainerInterface $container Service container + */ + public function __construct(ContainerInterface $container); + + /** + * Return a Cart a CouponManager can process + * + * @return \Thelia\Model\Cart + */ + public function getCart(); + + /** + * Return an Address a CouponManager can process + * + * @return \Thelia\Model\Address + */ + public function getDeliveryAddress(); + + /** + * @return Country the delivery country + */ + public function getDeliveryCountry(); + + /** + * Return an Customer a CouponManager can process + * + * @return \Thelia\Model\Customer + */ + public function getCustomer(); + + /** + * Return Checkout total price + * + * @return float + */ + public function getCheckoutTotalPrice(); + + /** + * Return Products total price + * CartTotalPrice = Checkout total - discount - postage + * @param bool $withItemsInPromo true (default) if item in promotion should be included in the total, false otherwise. + * + * @return float + */ + public function getCartTotalPrice($withItemsInPromo = true); + + /** + * Return Product total tax price + * @param bool $withItemsInPromo true (default) if item in promotion should be included in the total, false otherwise. + * + * @return float + */ + public function getCartTotalTaxPrice($withItemsInPromo = true); + + /** + * Return the Checkout currency EUR|USD + * + * @return string + */ + public function getCheckoutCurrency(); + + /** + * Return Checkout total postage (only) price + * + * @return float + */ + public function getCheckoutPostagePrice(); + + /** + * Return the number of Products in the Cart + * + * @return int + */ + public function getNbArticlesInCart(); + + /** + * Return the number of Products include quantity in the Cart + * + * @return int + */ + public function getNbArticlesInCartIncludeQuantity(); + + /** + * Return all Coupon given during the Checkout + * + * @return array Array of CouponInterface + */ + public function getCurrentCoupons(); + + /** + * Find one Coupon in the database from its code + * + * @param string $code Coupon code + * + * @return Coupon + */ + public function findOneCouponByCode($code); + + /** + * Return platform Container + * + * @return Container + */ + public function getContainer(); + + /** + * Return platform TranslatorInterface + * + * @return TranslatorInterface + */ + public function getTranslator(); + /** + * Return platform ParserInterface + * + * @return ParserInterface + */ + public function getParser(); + + /** + * Return the main currency + * THe one used to set prices in BackOffice + * + * @return string + */ + public function getMainCurrency(); + + /** + * Return request + * + * @return Request + */ + public function getRequest(); + + /** + * Return Condition Evaluator + * + * @return ConditionEvaluator + */ + public function getConditionEvaluator(); + + /** + * Return all available currencies + * + * @return array of Currency + */ + public function getAvailableCurrencies(); + + /** + * Return the event dispatcher, + * + * @return \Symfony\Component\EventDispatcher\EventDispatcher + */ + public function getDispatcher(); + + /** + * Add a coupon in session + * + * @param $couponCode + * @return mixed|void + */ + public function pushCouponInSession($couponCode); +} diff --git a/core/lib/Thelia/Coupon/Type/AbstractRemove.php b/core/lib/Thelia/Coupon/Type/AbstractRemove.php new file mode 100644 index 00000000..49f8d563 --- /dev/null +++ b/core/lib/Thelia/Coupon/Type/AbstractRemove.php @@ -0,0 +1,107 @@ + + */ +abstract class AbstractRemove extends CouponAbstract implements AmountAndPercentageCouponInterface +{ + /** + * Set the value of specific coupon fields. + * + * @param array $effects the Coupon effects params + */ + abstract public function setFieldsValue($effects); + + /** + * Get the discount for a specific cart item. + * + * @param CartItem $cartItem the cart item + * @return float the discount value + */ + abstract public function getCartItemDiscount(CartItem $cartItem); + + /** + * @inheritdoc + */ + public function set( + FacadeInterface $facade, + $code, + $title, + $shortDescription, + $description, + array $effects, + $isCumulative, + $isRemovingPostage, + $isAvailableOnSpecialOffers, + $isEnabled, + $maxUsage, + \DateTime $expirationDate, + $freeShippingForCountries, + $freeShippingForModules, + $perCustomerUsageCount + ) { + parent::set( + $facade, + $code, + $title, + $shortDescription, + $description, + $effects, + $isCumulative, + $isRemovingPostage, + $isAvailableOnSpecialOffers, + $isEnabled, + $maxUsage, + $expirationDate, + $freeShippingForCountries, + $freeShippingForModules, + $perCustomerUsageCount + ); + + $this->setFieldsValue($effects); + + return $this; + } + + /** + * @inheritdoc + */ + public function drawBaseBackOfficeInputs($templateName, $otherFields) + { + return $this->facade->getParser()->render($templateName, $otherFields); + } + + /** + * @inheritdoc + */ + public function getBaseFieldList($otherFields) + { + return array_merge($otherFields); + } + + /** + * @inheritdoc + */ + public function checkBaseCouponFieldValue($fieldName, $fieldValue) + { + return $fieldValue; + } +} diff --git a/core/lib/Thelia/Coupon/Type/AbstractRemoveOnAttributeValues.php b/core/lib/Thelia/Coupon/Type/AbstractRemoveOnAttributeValues.php new file mode 100644 index 00000000..fc723ddd --- /dev/null +++ b/core/lib/Thelia/Coupon/Type/AbstractRemoveOnAttributeValues.php @@ -0,0 +1,189 @@ + + */ +abstract class AbstractRemoveOnAttributeValues extends CouponAbstract implements AmountAndPercentageCouponInterface +{ + const ATTRIBUTES_AV_LIST = 'attribute_avs'; + const ATTRIBUTE = 'attribute_id'; + + public $attributeAvList = array(); + public $attribute = 0; + + /** + * Set the value of specific coupon fields. + * @param array $effects the Coupon effects params + */ + abstract public function setFieldsValue($effects); + + /** + * Get the discount for a specific cart item. + * + * @param CartItem $cartItem the cart item + * @return float the discount value + */ + abstract public function getCartItemDiscount(CartItem $cartItem); + + /** + * @inheritdoc + */ + public function set( + FacadeInterface $facade, + $code, + $title, + $shortDescription, + $description, + array $effects, + $isCumulative, + $isRemovingPostage, + $isAvailableOnSpecialOffers, + $isEnabled, + $maxUsage, + \DateTime $expirationDate, + $freeShippingForCountries, + $freeShippingForModules, + $perCustomerUsageCount + ) { + parent::set( + $facade, + $code, + $title, + $shortDescription, + $description, + $effects, + $isCumulative, + $isRemovingPostage, + $isAvailableOnSpecialOffers, + $isEnabled, + $maxUsage, + $expirationDate, + $freeShippingForCountries, + $freeShippingForModules, + $perCustomerUsageCount + ); + + $this->attributeAvList = isset($effects[self::ATTRIBUTES_AV_LIST]) ? $effects[self::ATTRIBUTES_AV_LIST] : array(); + + if (! \is_array($this->attributeAvList)) { + $this->attributeAvList = array($this->attributeAvList); + } + + $this->attribute = isset($effects[self::ATTRIBUTE]) ? $effects[self::ATTRIBUTE] : 0; + + $this->setFieldsValue($effects); + + return $this; + } + + /** + * @inheritdoc + */ + public function exec() + { + // This coupon subtracts the specified amount from the order total + // for each product which uses the selected attributes + $discount = 0; + + $cartItems = $this->facade->getCart()->getCartItems(); + + /** @var CartItem $cartItem */ + foreach ($cartItems as $cartItem) { + if (! $cartItem->getPromo() || $this->isAvailableOnSpecialOffers()) { + $productSaleElements = $cartItem->getProductSaleElements(); + + $combinations = $productSaleElements->getAttributeCombinations(); + + /** @var AttributeCombination $combination */ + foreach ($combinations as $combination) { + $attrValue = $combination->getAttributeAvId(); + + if (\in_array($attrValue, $this->attributeAvList)) { + $discount += $this->getCartItemDiscount($cartItem); + + break; + } + } + } + } + + return $discount; + } + + /** + * Renders the template which implements coupon specific user-input, + * using the provided template file, and a list of specific input fields. + * + * @param string $templateName the path to the template + * @param array $otherFields the list of additional fields fields + * + * @return string the rendered template. + */ + public function drawBaseBackOfficeInputs($templateName, $otherFields) + { + return $this->facade->getParser()->render($templateName, array_merge($otherFields, [ + + // The attributes list field + 'attribute_field_name' => $this->makeCouponFieldName(self::ATTRIBUTE), + 'attribute_value' => $this->attribute, + + // The attributes list field + 'attribute_av_field_name' => $this->makeCouponFieldName(self::ATTRIBUTES_AV_LIST), + 'attribute_av_values' => $this->attributeAvList + ])); + } + + /** + * @inheritdoc + */ + public function getBaseFieldList($otherFields) + { + return array_merge($otherFields, [self::ATTRIBUTE, self::ATTRIBUTES_AV_LIST]); + } + + /** + * @inheritdoc + */ + public function checkBaseCouponFieldValue($fieldName, $fieldValue) + { + if ($fieldName === self::ATTRIBUTE) { + if (empty($fieldValue)) { + throw new \InvalidArgumentException( + Translator::getInstance()->trans( + 'Please select an attribute' + ) + ); + } + } elseif ($fieldName === self::ATTRIBUTES_AV_LIST) { + if (empty($fieldValue)) { + throw new \InvalidArgumentException( + Translator::getInstance()->trans( + 'Please select at least one attribute value' + ) + ); + } + } + + return $fieldValue; + } +} diff --git a/core/lib/Thelia/Coupon/Type/AbstractRemoveOnCategories.php b/core/lib/Thelia/Coupon/Type/AbstractRemoveOnCategories.php new file mode 100644 index 00000000..8e6fecdd --- /dev/null +++ b/core/lib/Thelia/Coupon/Type/AbstractRemoveOnCategories.php @@ -0,0 +1,163 @@ + + */ +abstract class AbstractRemoveOnCategories extends CouponAbstract implements AmountAndPercentageCouponInterface +{ + const CATEGORIES_LIST = 'categories'; + + protected $category_list = array(); + + /** + * Set the value of specific coupon fields. + * + * @param array $effects the Coupon effects params + */ + abstract public function setFieldsValue($effects); + + /** + * Get the discount for a specific cart item. + * + * @param CartItem $cartItem the cart item + * @return float the discount value + */ + abstract public function getCartItemDiscount(CartItem $cartItem); + + /** + * @inheritdoc + */ + public function set( + FacadeInterface $facade, + $code, + $title, + $shortDescription, + $description, + array $effects, + $isCumulative, + $isRemovingPostage, + $isAvailableOnSpecialOffers, + $isEnabled, + $maxUsage, + \DateTime $expirationDate, + $freeShippingForCountries, + $freeShippingForModules, + $perCustomerUsageCount + ) { + parent::set( + $facade, + $code, + $title, + $shortDescription, + $description, + $effects, + $isCumulative, + $isRemovingPostage, + $isAvailableOnSpecialOffers, + $isEnabled, + $maxUsage, + $expirationDate, + $freeShippingForCountries, + $freeShippingForModules, + $perCustomerUsageCount + ); + + $this->category_list = isset($effects[self::CATEGORIES_LIST]) ? $effects[self::CATEGORIES_LIST] : array(); + + if (! \is_array($this->category_list)) { + $this->category_list = array($this->category_list); + } + + $this->setFieldsValue($effects); + + return $this; + } + /** + * @inheritdoc + */ + public function exec() + { + // This coupon subtracts the specified amount from the order total + // for each product of the selected categories. + $discount = 0; + + $cartItems = $this->facade->getCart()->getCartItems(); + + /** @var CartItem $cartItem */ + foreach ($cartItems as $cartItem) { + if (! $cartItem->getPromo() || $this->isAvailableOnSpecialOffers()) { + $categories = $cartItem->getProduct()->getCategories(); + + /** @var Category $category */ + foreach ($categories as $category) { + if (\in_array($category->getId(), $this->category_list)) { + $discount += $this->getCartItemDiscount($cartItem); + + break; + } + } + } + } + + return $discount; + } + + /** + * @inheritdoc + */ + public function drawBaseBackOfficeInputs($templateName, $otherFields) + { + return $this->facade->getParser()->render($templateName, array_merge($otherFields, [ + + // The categories list field + 'categories_field_name' => $this->makeCouponFieldName(self::CATEGORIES_LIST), + 'categories_values' => $this->category_list + ])); + } + + /** + * @inheritdoc + */ + public function getBaseFieldList($otherFields) + { + return array_merge($otherFields, [self::CATEGORIES_LIST]); + } + + /** + * @inheritdoc + */ + public function checkBaseCouponFieldValue($fieldName, $fieldValue) + { + if ($fieldName === self::CATEGORIES_LIST) { + if (empty($fieldValue)) { + throw new \InvalidArgumentException( + Translator::getInstance()->trans( + 'Please select at least one category' + ) + ); + } + } + + return $fieldValue; + } +} diff --git a/core/lib/Thelia/Coupon/Type/AbstractRemoveOnProducts.php b/core/lib/Thelia/Coupon/Type/AbstractRemoveOnProducts.php new file mode 100644 index 00000000..581e6143 --- /dev/null +++ b/core/lib/Thelia/Coupon/Type/AbstractRemoveOnProducts.php @@ -0,0 +1,173 @@ + + */ +abstract class AbstractRemoveOnProducts extends CouponAbstract implements AmountAndPercentageCouponInterface +{ + const CATEGORY_ID = 'category_id'; + const PRODUCTS_LIST = 'products'; + + public $category_id = 0; + public $product_list = array(); + + /** + * Set the value of specific coupon fields. + * + * @param array $effects the Coupon effects params + */ + abstract public function setFieldsValue($effects); + + /** + * Get the discount for a specific cart item. + * + * @param CartItem $cartItem the cart item + * @return float the discount value + */ + abstract public function getCartItemDiscount(CartItem $cartItem); + + /** + * @inheritdoc + */ + public function set( + FacadeInterface $facade, + $code, + $title, + $shortDescription, + $description, + array $effects, + $isCumulative, + $isRemovingPostage, + $isAvailableOnSpecialOffers, + $isEnabled, + $maxUsage, + \DateTime $expirationDate, + $freeShippingForCountries, + $freeShippingForModules, + $perCustomerUsageCount + ) { + parent::set( + $facade, + $code, + $title, + $shortDescription, + $description, + $effects, + $isCumulative, + $isRemovingPostage, + $isAvailableOnSpecialOffers, + $isEnabled, + $maxUsage, + $expirationDate, + $freeShippingForCountries, + $freeShippingForModules, + $perCustomerUsageCount + ); + + $this->product_list = isset($effects[self::PRODUCTS_LIST]) ? $effects[self::PRODUCTS_LIST] : array(); + + if (! \is_array($this->product_list)) { + $this->product_list = array($this->product_list); + } + + $this->category_id = isset($effects[self::CATEGORY_ID]) ? $effects[self::CATEGORY_ID] : 0; + + $this->setFieldsValue($effects); + + return $this; + } + + /** + * @inheritdoc + */ + public function exec() + { + // This coupon subtracts the specified amount from the order total + // for each product of the selected products. + $discount = 0; + + $cartItems = $this->facade->getCart()->getCartItems(); + + /** @var CartItem $cartItem */ + foreach ($cartItems as $cartItem) { + if (\in_array($cartItem->getProduct()->getId(), $this->product_list)) { + if (! $cartItem->getPromo() || $this->isAvailableOnSpecialOffers()) { + $discount += $this->getCartItemDiscount($cartItem); + } + } + } + + return $discount; + } + + /** + * @inheritdoc + */ + public function drawBaseBackOfficeInputs($templateName, $otherFields) + { + return $this->facade->getParser()->render($templateName, array_merge($otherFields, [ + + // The category ID field + 'category_id_field_name' => $this->makeCouponFieldName(self::CATEGORY_ID), + 'category_id_value' => $this->category_id, + + // The products list field + 'products_field_name' => $this->makeCouponFieldName(self::PRODUCTS_LIST), + 'products_values' => $this->product_list, + 'products_values_csv' => implode(', ', $this->product_list) + ])); + } + + /** + * @inheritdoc + */ + public function getBaseFieldList($otherFields) + { + return array_merge($otherFields, [self::CATEGORY_ID, self::PRODUCTS_LIST]); + } + + /** + * @inheritdoc + */ + public function checkBaseCouponFieldValue($fieldName, $fieldValue) + { + if ($fieldName === self::CATEGORY_ID) { + if (empty($fieldValue)) { + throw new \InvalidArgumentException( + Translator::getInstance()->trans( + 'Please select a category' + ) + ); + } + } elseif ($fieldName === self::PRODUCTS_LIST) { + if (empty($fieldValue)) { + throw new \InvalidArgumentException( + Translator::getInstance()->trans( + 'Please select at least one product' + ) + ); + } + } + + return $fieldValue; + } +} diff --git a/core/lib/Thelia/Coupon/Type/AmountAndPercentageCouponInterface.php b/core/lib/Thelia/Coupon/Type/AmountAndPercentageCouponInterface.php new file mode 100644 index 00000000..e23553bd --- /dev/null +++ b/core/lib/Thelia/Coupon/Type/AmountAndPercentageCouponInterface.php @@ -0,0 +1,66 @@ + + * + */ +interface AmountAndPercentageCouponInterface +{ + /** + * Set the value of specific coupon fields. + * @param array $effects the Coupon effects params + */ + public function setFieldsValue($effects); + + /** + * Get the discount for a specific cart item. + * + * @param CartItem $cartItem the cart item + * @return float the discount value + */ + public function getCartItemDiscount(CartItem $cartItem); + + /** + * Renders the template which implements coupon specific user-input, + * using the provided template file, and a list of specific input fields. + * + * @param string $templateName the path to the template + * @param array $otherFields the list of additional fields fields + * + * @return string the rendered template. + */ + public function drawBaseBackOfficeInputs($templateName, $otherFields); + + /** + * @inheritdoc + */ + public function getBaseFieldList($otherFields); + + /** + * Check the value of a coupon configuration field + * + * @param string $fieldName + * @param string $fieldValue + * @return string the field value + * + * @throws \InvalidArgumentException is field value is not valid. + */ + public function checkBaseCouponFieldValue($fieldName, $fieldValue); +} diff --git a/core/lib/Thelia/Coupon/Type/AmountCouponTrait.php b/core/lib/Thelia/Coupon/Type/AmountCouponTrait.php new file mode 100644 index 00000000..9fc995cd --- /dev/null +++ b/core/lib/Thelia/Coupon/Type/AmountCouponTrait.php @@ -0,0 +1,93 @@ + + * @package Thelia\Coupon\Type + */ +trait AmountCouponTrait +{ + // The amount is already defined in CouponAbstract, and should not be redefined here. + // protected $amount = 0; + + /** + * Should return the amount field name, defined in the parent class. + * + * @return string the percentage field name + */ + abstract protected function getAmountFieldName(); + + /** + * @inheritdoc + */ + public function setFieldsValue($effects) + { + $this->amount = $effects[$this->getAmountFieldName()]; + } + + /** + * @inheritdoc + */ + public function getCartItemDiscount(CartItem $cartItem) + { + return $cartItem->getQuantity() * $this->amount; + } + + /** + * @inheritdoc + */ + public function callDrawBackOfficeInputs($templateName) + { + return $this->drawBaseBackOfficeInputs($templateName, [ + 'amount_field_name' => $this->makeCouponFieldName($this->getAmountFieldName()), + 'amount_value' => $this->amount + ]); + } + + /** + * @inheritdoc + */ + protected function getFieldList() + { + return $this->getBaseFieldList([$this->getAmountFieldName()]); + } + + /** + * @inheritdoc + */ + protected function checkCouponFieldValue($fieldName, $fieldValue) + { + $this->checkBaseCouponFieldValue($fieldName, $fieldValue); + + if ($fieldName === $this->getAmountFieldName()) { + if (\floatval($fieldValue) < 0) { + throw new \InvalidArgumentException( + Translator::getInstance()->trans( + 'Value %val for Discount Amount is invalid. Please enter a positive value.', + [ '%val' => $fieldValue] + ) + ); + } + } + + return $fieldValue; + } +} diff --git a/core/lib/Thelia/Coupon/Type/CouponAbstract.php b/core/lib/Thelia/Coupon/Type/CouponAbstract.php new file mode 100644 index 00000000..b597ad1a --- /dev/null +++ b/core/lib/Thelia/Coupon/Type/CouponAbstract.php @@ -0,0 +1,521 @@ + + * + */ +abstract class CouponAbstract implements CouponInterface +{ + /** + * The dataset name for all coupon specific input fields, that do not appear in the CouPonCreationForm form. + * + * In the input form, these fields have to be created like: + * + * thelia_coupon_specific[my_field, thelia_coupon_creation_extended[my_other_field] + * + * use the makeCouponField() method to do that safely. + */ + const COUPON_DATASET_NAME = 'coupon_specific'; + + /** + * A standard 'amount' filed name, thant can be used in coupons which extends this class + */ + const AMOUNT_FIELD_NAME = 'amount'; + + /** @var FacadeInterface Provide necessary value from Thelia */ + protected $facade = null; + + /** @var Translator Service Translator */ + protected $translator = null; + + /** @var ConditionOrganizerInterface */ + protected $organizer = null; + + /** @var ConditionCollection Array of ConditionInterface */ + protected $conditions = null; + + /** @var ConditionEvaluator Condition validator */ + protected $conditionEvaluator = null; + + /** @var string Service Id */ + protected $serviceId = null; + + /** @var float Amount that will be removed from the Checkout (Coupon Effect) */ + protected $amount = 0; + + /** @var array Get the Coupon effects params */ + protected $effects = array('amount' => 0); + + /** @var string Coupon code (ex: XMAS) */ + protected $code = null; + + /** @var string Coupon title (ex: Coupon for XMAS) */ + protected $title = null; + + /** @var string Coupon short description */ + protected $shortDescription = null; + + /** @var string Coupon description */ + protected $description = null; + + /** @var bool if Coupon is enabled */ + protected $isEnabled = false; + + /** @var \DateTime Coupon start date */ + protected $startDate = null; + + /** @var \DateTime Coupon expiration date */ + protected $expirationDate = null; + + /** @var bool if Coupon is cumulative */ + protected $isCumulative = false; + + /** @var bool if Coupon is removing postage */ + protected $isRemovingPostage = false; + + /** @var int Max time a Coupon can be used (-1 = unlimited) */ + protected $maxUsage = -1; + + /** @var bool if Coupon is available for Products already on special offers */ + protected $isAvailableOnSpecialOffers = false; + + /** @var CouponCountry[] list of country IDs for which shipping is free. All if empty*/ + protected $freeShippingForCountries = []; + + /** @var CouponModule[] list of shipping module IDs for which shippiog is free. All if empty*/ + protected $freeShippingForModules = []; + + /** @var true if usage count is per customer only */ + protected $perCustomerUsageCount; + + /** + * Constructor + * + * @param FacadeInterface $facade Service facade + */ + public function __construct(FacadeInterface $facade) + { + $this->facade = $facade; + $this->translator = $facade->getTranslator(); + $this->conditionEvaluator = $facade->getConditionEvaluator(); + } + + /** + * Set Condition Organizer + * + * @param ConditionOrganizerInterface $organizer Manage Condition groups (&& and ||) + * + * @return $this + */ + public function setOrganizer($organizer) + { + $this->organizer = $organizer; + + return $this; + } + + /** + * @inheritdoc + */ + public function set( + FacadeInterface $facade, + $code, + $title, + $shortDescription, + $description, + array $effects, + $isCumulative, + $isRemovingPostage, + $isAvailableOnSpecialOffers, + $isEnabled, + $maxUsage, + \DateTime $expirationDate, + $freeShippingForCountries, + $freeShippingForModules, + $perCustomerUsageCount + ) { + $this->code = $code; + $this->title = $title; + $this->shortDescription = $shortDescription; + $this->description = $description; + + $this->isCumulative = $isCumulative; + $this->isRemovingPostage = $isRemovingPostage; + + $this->isAvailableOnSpecialOffers = $isAvailableOnSpecialOffers; + $this->isEnabled = $isEnabled; + $this->maxUsage = $maxUsage; + $this->expirationDate = $expirationDate; + $this->facade = $facade; + + $this->effects = $effects; + // Amount is now optional. + $this->amount = isset($effects[self::AMOUNT_FIELD_NAME]) ? $effects[self::AMOUNT_FIELD_NAME] : 0; + + $this->freeShippingForCountries = $freeShippingForCountries; + $this->freeShippingForModules = $freeShippingForModules; + $this->perCustomerUsageCount = $perCustomerUsageCount; + + return $this; + } + + /** + * @param true $perCustomerUsageCount + * @return $this + */ + public function setPerCustomerUsageCount($perCustomerUsageCount) + { + $this->perCustomerUsageCount = $perCustomerUsageCount; + + return $this; + } + + /** + * @return true + */ + public function getPerCustomerUsageCount() + { + return $this->perCustomerUsageCount; + } + + /** + * Return Coupon code (ex: XMAS) + * + * @return string + */ + public function getCode() + { + return $this->code; + } + + /** + * Return Coupon title (ex: Coupon for XMAS) + * + * @return string + */ + public function getTitle() + { + return $this->title; + } + + /** + * Return Coupon short description + * + * @return string + */ + public function getShortDescription() + { + return $this->shortDescription; + } + + /** + * Return Coupon description + * + * @return string + */ + public function getDescription() + { + return $this->description; + } + + /** + * If Coupon is cumulative or prevent any accumulation + * If is cumulative you can sum Coupon effects + * If not cancel all other Coupon and take the last given + * + * @return bool + */ + public function isCumulative() + { + return $this->isCumulative; + } + + /** + * If Coupon is removing Checkout Postage + * + * @return bool + */ + public function isRemovingPostage() + { + return $this->isRemovingPostage; + } + + /** + * @return array list of country IDs for which shipping is free. All if empty + */ + public function getFreeShippingForCountries() + { + return $this->freeShippingForCountries; + } + + /** + * @return array list of module IDs for which shipping is free. All if empty + */ + public function getFreeShippingForModules() + { + return $this->freeShippingForModules; + } + + /** + * @inheritdoc + */ + public function exec() + { + return $this->amount; + } + + /** + * Return condition to validate the Coupon or not + * + * @return ConditionCollection + */ + public function getConditions() + { + return clone $this->conditions; + } + + /** + * Replace the existing Conditions by those given in parameter + * If one Condition is badly implemented, no Condition will be added + * + * @param ConditionCollection $conditions ConditionInterface to add + * + * @return $this + * @throws \Thelia\Exception\InvalidConditionException + */ + public function setConditions(ConditionCollection $conditions) + { + $this->conditions = $conditions; + + return $this; + } + + /** + * Return Coupon expiration date + * + * @return \DateTime + */ + public function getExpirationDate() + { + return clone $this->expirationDate; + } + + /** + * Check if the Coupon can be used against a + * product already with a special offer price + * + * @return boolean + */ + public function isAvailableOnSpecialOffers() + { + return $this->isAvailableOnSpecialOffers; + } + + /** + * Check if Coupon has been disabled by admin + * + * @return boolean + */ + public function isEnabled() + { + return $this->isEnabled; + } + + /** + * Return how many time the Coupon can be used again + * Ex : -1 unlimited + * + * @return int + */ + public function getMaxUsage() + { + return $this->maxUsage; + } + + /** + * Check if the Coupon is already Expired + * + * @return bool + */ + public function isExpired() + { + $ret = true; + + $now = new \DateTime(); + if ($this->expirationDate > $now) { + $ret = false; + } + + return $ret; + } + + /** + * Get Coupon Manager service Id + * + * @return string + */ + public function getServiceId() + { + return $this->serviceId; + } + + /** + * Check if the current state of the application is matching this Coupon conditions + * Thelia variables are given by the FacadeInterface + * + * @return bool + */ + public function isMatching() + { + return $this->conditionEvaluator->isMatching($this->conditions); + } + + /** + * This is the field label than will be displayed in the form. + * This method should be overridden to be useful. + * + * For backward compatibility only. + * + * @return string + */ + public function getInputName() + { + return "Please override getInputName() method"; + } + + /** + * Draw the input displayed in the BackOffice + * allowing Admin to set its Coupon effect + * Override this method to do something useful + * + * @return string HTML string + */ + public function drawBackOfficeInputs() + { + return $this->facade->getParser()->render('coupon/type-fragments/remove-x.html', [ + 'label' => $this->getInputName(), + 'fieldId' => self::AMOUNT_FIELD_NAME, + 'fieldName' => $this->makeCouponFieldName(self::AMOUNT_FIELD_NAME), + 'value' => $this->amount + ]); + } + + /** + * This methods checks a field value. If the field has a correct value, this value is returned + * Otherwise, an InvalidArgumentException describing the problem should be thrown. + * + * This method should be overriden to be useful. + * + * @param string $fieldName + * @param string $fieldValue + * @return mixed + * @throws \InvalidArgumentException if the field value is not valid. + */ + protected function checkCouponFieldValue(/** @noinspection PhpUnusedParameterInspection */ $fieldName, $fieldValue) + { + return $fieldValue; + } + + /** + * A helper to get the value of a standard field name + * + * @param string $fieldName the field name + * @param array $data the input form data (e.g. $form->getData()) + * @param mixed $defaultValue the default value if the field is not found. + * + * @return mixed the input value, or the default one + * + * @throws \InvalidArgumentException if the field is not found, and no default value has been defined. + */ + protected function getCouponFieldValue($fieldName, $data, $defaultValue = null) + { + if (isset($data[self::COUPON_DATASET_NAME][$fieldName])) { + return $this->checkCouponFieldValue( + $fieldName, + $data[self::COUPON_DATASET_NAME][$fieldName] + ); + } elseif (null !== $defaultValue) { + return $defaultValue; + } else { + throw new \InvalidArgumentException(sprintf("The coupon field name %s was not found in the coupon form", $fieldName)); + } + } + + /** + * A helper to create an standard field name that will be used in the coupon form + * + * @param string $fieldName the field name + * @return string the complete name, ready to be used in a form. + */ + protected function makeCouponFieldName($fieldName) + { + return sprintf("%s[%s][%s]", CouponCreationForm::COUPON_CREATION_FORM_NAME, self::COUPON_DATASET_NAME, $fieldName); + } + + /** + * Return a list of the fields name for this coupon. + * + * @return array + */ + protected function getFieldList() + { + return [self::AMOUNT_FIELD_NAME]; + } + + /** + * Create the effect array from the list of fields + * + * @param array $data the input form data (e.g. $form->getData()) + * @return array a filedName => fieldValue array + */ + public function getEffects($data) + { + $effects = []; + + foreach ($this->getFieldList() as $fieldName) { + $effects[$fieldName] = $this->getCouponFieldValue($fieldName, $data); + } + + return $effects; + } + + /** + * @inheritdoc + */ + public function clear() + { + // Does nothing. Override this function as needed. + } + + public function isInUse() + { + return \in_array( + $this->code, + $this->facade->getRequest()->getSession()->getConsumedCoupons() + ); + } +} diff --git a/core/lib/Thelia/Coupon/Type/CouponInterface.php b/core/lib/Thelia/Coupon/Type/CouponInterface.php new file mode 100644 index 00000000..cfd645d2 --- /dev/null +++ b/core/lib/Thelia/Coupon/Type/CouponInterface.php @@ -0,0 +1,251 @@ + + * + */ +interface CouponInterface +{ + /** + * Get I18n name + * + * @return string + */ + public function getName(); + + /** + * Get I18n tooltip + * + * @return string + */ + public function getToolTip(); + + /** + * Get Coupon Manager service Id + * + * @return string + */ + public function getServiceId(); + + /** + * Set Coupon + * + * @param FacadeInterface $facade Provides necessary value from Thelia + * @param string $code Coupon code (ex: XMAS) + * @param string $title Coupon title (ex: Coupon for XMAS) + * @param string $shortDescription Coupon short description + * @param string $description Coupon description + * @param array $effects Coupon effects params + * @param bool $isCumulative If Coupon is cumulative + * @param bool $isRemovingPostage If Coupon is removing postage + * @param bool $isAvailableOnSpecialOffers If available on Product already + * on special offer price + * @param bool $isEnabled False if Coupon is disabled by admin + * @param int $maxUsage How many usage left + * @param \Datetime $expirationDate When the Code is expiring + * @param ObjectCollection $freeShippingForCountries list of countries which shipping is free. All if empty + * @param ObjectCollection $freeShippingForModules list of modules for which shipping is free. All if empty + * @param bool $perCustomerUsageCount true if usage count is per customer only + */ + public function set( + FacadeInterface $facade, + $code, + $title, + $shortDescription, + $description, + array $effects, + $isCumulative, + $isRemovingPostage, + $isAvailableOnSpecialOffers, + $isEnabled, + $maxUsage, + \DateTime $expirationDate, + $freeShippingForCountries, + $freeShippingForModules, + $perCustomerUsageCount + ); + + /** + * Return Coupon code (ex: XMAS) + * + * @return string + */ + public function getCode(); + + /** + * Return Coupon title (ex: Coupon for XMAS) + * + * @return string + */ + public function getTitle(); + + /** + * Return Coupon short description + * + * @return string + */ + public function getShortDescription(); + + /** + * Return Coupon description + * + * @return string + */ + public function getDescription(); + + /** + * If Coupon is cumulative or prevent any accumulation + * If is cumulative you can sum Coupon effects + * If not cancel all other Coupon and take the last given + * + * @return bool + */ + public function isCumulative(); + + /** + * If Coupon is removing Checkout Postage + * + * @return bool + */ + public function isRemovingPostage(); + + /** + * Return condition to validate the Coupon or not + * + * @return ConditionCollection A set of ConditionInterface + */ + public function getConditions(); + + /** + * Replace the existing Conditions by those given in parameter + * If one Condition is badly implemented, no Condition will be added + * + * @param ConditionCollection $conditions ConditionInterface to add + * + * @return $this + * @throws \Thelia\Exception\InvalidConditionException + */ + public function setConditions(ConditionCollection $conditions); + + /** + * Return Coupon expiration date + * + * @return \DateTime + */ + public function getExpirationDate(); + + /** + * Check if the Coupon can be used against a + * product already with a special offer price + * + * @return boolean + */ + public function isAvailableOnSpecialOffers(); + + /** + * Check if the Coupon can be used against a + * product already with a special offer price + * + * @return boolean + */ + public function getPerCustomerUsageCount(); + + /** + * Check if Coupon has been disabled by admin + * + * @return boolean + */ + public function isEnabled(); + + /** + * Return how many time the Coupon can be used again + * Ex : -1 unlimited + * + * @return int + */ + public function getMaxUsage(); + + /** + * Check if the Coupon is already Expired + * + * @return bool + */ + public function isExpired(); + + /** + * Return an amount thant will be subtracted to the cart total, or zero. + * + * This method could also perform something else than the calculating an amount to subtract from the cart. It may + * add a product to the cart, for example. In this case, an amount of 0 will be returned. + * + * WARNING: this method could be called several times, so perform suitable checks before performing cart + * manipulations, so that the coupon effect will not be applied several times. + * + * @return float Amount removed from the cart total + */ + public function exec(); + + /** + * Check if the current Coupon is matching its conditions + * Thelia variables are given by the FacadeInterface + * + * @return bool + */ + public function isMatching(); + + /** + * Draw the input displayed in the BackOffice + * allowing Admin to set its Coupon effect + * + * @return string HTML string + */ + public function drawBackOfficeInputs(); + + /** + * @return ObjectCollection list of country IDs for which shipping is free. All if empty + */ + public function getFreeShippingForCountries(); + + /** + * @return ObjectCollection list of module IDs for which shipping is free. All if empty + */ + public function getFreeShippingForModules(); + + /** + * Create the effect array from the list of fields + * + * @param array $data the input form data (e.g. $form->getData()) + * + * @return array a filedName => fieldValue array + */ + public function getEffects($data); + + /** + * Clear all the data the coupon may have stored, called after an order is completed. + */ + public function clear(); + + /** + * @return bool true if the coupon is currently in use in the current order process, false otherwise + */ + public function isInUse(); +} diff --git a/core/lib/Thelia/Coupon/Type/FreeProduct.php b/core/lib/Thelia/Coupon/Type/FreeProduct.php new file mode 100644 index 00000000..8eb8229c --- /dev/null +++ b/core/lib/Thelia/Coupon/Type/FreeProduct.php @@ -0,0 +1,330 @@ + + */ +class FreeProduct extends AbstractRemoveOnProducts +{ + const OFFERED_PRODUCT_ID = 'offered_product_id'; + const OFFERED_CATEGORY_ID = 'offered_category_id'; + + /** @var string Service Id */ + protected $serviceId = 'thelia.coupon.type.free_product'; + + protected $offeredProductId; + protected $offeredCategoryId; + + /** + * This constant is user to mark a free product as in the process of being added to the cart, + * but the CartItem ID is not yet been defined. + */ + const ADD_TO_CART_IN_PROCESS = -1; + + /** + * @inheritdoc + */ + public function setFieldsValue($effects) + { + $this->offeredProductId = $effects[self::OFFERED_PRODUCT_ID]; + $this->offeredCategoryId = $effects[self::OFFERED_CATEGORY_ID]; + } + + /** + * @inheritdoc + */ + public function getCartItemDiscount(CartItem $cartItem) + { + // This method is not used, we use our own implementation of exec(); + return 0; + } + + /** + * @return string The session variable where the cart item IDs for the free products are stored + */ + protected function getSessionVarName() + { + return "coupon.free_product.cart_items." . $this->getCode(); + } + /** + * Return the cart item id which contains the free product related to a given product + * + * @param Product $product the product in the cart which triggered the discount + * + * @return bool|int|CartItem the cart item which contains the free product, or false if the product is no longer in the cart, or ADD_TO_CART_IN_PROCESS if the adding process is not finished + */ + protected function getRelatedCartItem($product) + { + $cartItemIdList = $this->facade->getRequest()->getSession()->get( + $this->getSessionVarName(), + array() + ); + + if (isset($cartItemIdList[$product->getId()])) { + $cartItemId = $cartItemIdList[$product->getId()]; + + if ($cartItemId == self::ADD_TO_CART_IN_PROCESS) { + return self::ADD_TO_CART_IN_PROCESS; + } elseif (null !== $cartItem = CartItemQuery::create()->findPk($cartItemId)) { + return $cartItem; + } + } else { + // Maybe the product we're offering is already in the cart ? Search it. + $cartItems = $this->facade->getCart()->getCartItems(); + + /** @var CartItem $cartItem */ + foreach ($cartItems as $cartItem) { + if ($cartItem->getProduct()->getId() == $this->offeredProductId) { + // We found the product. Store its cart item as the free product container. + $this->setRelatedCartItem($product, $cartItem->getId()); + + return $cartItem; + } + } + } + + return false; + } + + /** + * Set the cart item id which contains the free product related to a given product + * + * @param Product $product the product in the cart which triggered the discount + * @param bool|int $cartItemId the cart item ID which contains the free product, or just true if the free product is not yet added. + */ + protected function setRelatedCartItem($product, $cartItemId) + { + $cartItemIdList = $this->facade->getRequest()->getSession()->get( + $this->getSessionVarName(), + array() + ); + + if (! \is_array($cartItemIdList)) { + $cartItemIdList = array(); + } + + $cartItemIdList[$product->getId()] = $cartItemId; + + $this->facade->getRequest()->getSession()->set( + $this->getSessionVarName(), + $cartItemIdList + ); + } + + /** + * Get the product id / cart item id list. + * + * @return array an array where the free product ID is the key, and the related cart item id the value. + */ + protected function getFreeProductsCartItemIds() + { + return $this->facade->getRequest()->getSession()->get( + $this->getSessionVarName(), + array() + ); + } + + /** + * Clear the session variable. + */ + protected function clearFreeProductsCartItemIds() + { + return $this->facade->getRequest()->getSession()->remove($this->getSessionVarName()); + } + + /** + * We overload this method here to remove the free products when the + * coupons conditions are no longer met. + * + * @inheritdoc + */ + public function isMatching() + { + $match = parent::isMatching(); + + if (! $match) { + // Cancel coupon effect (but no not remove the product) + $this->clearFreeProductsCartItemIds(); + } + + return $match; + } + + /** + * @inheritdoc + */ + public function exec() + { + $discount = 0; + + $cartItems = $this->facade->getCart()->getCartItems(); + + /** @var Product $eligibleProduct */ + $eligibleProduct = null; + + /** @var CartItem $cartItem */ + foreach ($cartItems as $cartItem) { + if (\in_array($cartItem->getProduct()->getId(), $this->product_list)) { + if (! $cartItem->getPromo() || $this->isAvailableOnSpecialOffers()) { + $eligibleProduct = $cartItem; + break; + } + } + } + + if ($eligibleProduct !== null) { + // Get the cart item for the eligible product + $freeProductCartItem = $this->getRelatedCartItem($eligibleProduct); + + // We add the free product it only if it not yet in the cart. + if ($freeProductCartItem === false) { + if (null !== $freeProduct = ProductQuery::create()->findPk($this->offeredProductId)) { + // Store in the session that the free product is added to the cart, + // so that we don't enter the following infinite loop : + // + // 1) exec() adds a product by firing a CART_ADDITEM event, + // 2) the event is processed by Action\Coupon::updateOrderDiscount(), + // 3) Action\Coupon::updateOrderDiscount() calls CouponManager::getDiscount() + // 4) CouponManager::getDiscount() calls exec() -> Infinite loop !! + + // Store a marker first, we do not have the cart item id yet. + $this->setRelatedCartItem($eligibleProduct, self::ADD_TO_CART_IN_PROCESS); + + $cartEvent = new CartEvent($this->facade->getCart()); + + $cartEvent->setNewness(true); + $cartEvent->setAppend(false); + $cartEvent->setQuantity(1); + $cartEvent->setProductSaleElementsId($freeProduct->getDefaultSaleElements()->getId()); + $cartEvent->setProduct($this->offeredProductId); + + $this->facade->getDispatcher()->dispatch(TheliaEvents::CART_ADDITEM, $cartEvent); + + // Store the final cart item ID. + $this->setRelatedCartItem($eligibleProduct, $cartEvent->getCartItem()->getId()); + + $freeProductCartItem = $cartEvent->getCartItem(); + } + } + + if ($freeProductCartItem instanceof CartItem) { + // The discount is the product price. + $discount = $freeProductCartItem->getRealTaxedPrice($this->facade->getDeliveryCountry()); + } + // No eligible product was found ! + } else { + // Remove all free products for this coupon, but no not remove the product from the cart. + $this->clearFreeProductsCartItemIds(); + } + + return $discount; + } + + /** + * @inheritdoc + */ + protected function getFieldList() + { + return $this->getBaseFieldList([self::OFFERED_CATEGORY_ID, self::OFFERED_PRODUCT_ID]); + } + + /** + * @inheritdoc + */ + protected function checkCouponFieldValue($fieldName, $fieldValue) + { + $this->checkBaseCouponFieldValue($fieldName, $fieldValue); + + if ($fieldName === self::OFFERED_PRODUCT_ID) { + if (\floatval($fieldValue) < 0) { + throw new \InvalidArgumentException( + Translator::getInstance()->trans( + 'Please select the offered product' + ) + ); + } + } elseif ($fieldName === self::OFFERED_CATEGORY_ID) { + if (empty($fieldValue)) { + throw new \InvalidArgumentException( + Translator::getInstance()->trans( + 'Please select the category of the offred product' + ) + ); + } + } + + return $fieldValue; + } + + /** + * Get I18n name + * + * @return string + */ + public function getName() + { + return $this->facade + ->getTranslator() + ->trans('Free product when buying one or more selected products', array()); + } + + /** + * @inheritdoc + */ + public function getToolTip() + { + $toolTip = $this->facade + ->getTranslator() + ->trans( + 'This coupon adds a free product to the cart if one of the selected products is in the cart.', + array() + ); + + return $toolTip; + } + + /** + * @inheritdoc + */ + public function drawBackOfficeInputs() + { + return $this->drawBaseBackOfficeInputs("coupon/type-fragments/free-product.html", [ + 'offered_category_field_name' => $this->makeCouponFieldName(self::OFFERED_CATEGORY_ID), + 'offered_category_value' => $this->offeredCategoryId, + + 'offered_product_field_name' => $this->makeCouponFieldName(self::OFFERED_PRODUCT_ID), + 'offered_product_value' => $this->offeredProductId + ]); + } + + /** + * @inheritdoc + */ + public function clear() + { + // Clear the session variable when the coupon is cleared. + $this->clearFreeProductsCartItemIds(); + } +} diff --git a/core/lib/Thelia/Coupon/Type/PercentageCouponTrait.php b/core/lib/Thelia/Coupon/Type/PercentageCouponTrait.php new file mode 100644 index 00000000..f2261809 --- /dev/null +++ b/core/lib/Thelia/Coupon/Type/PercentageCouponTrait.php @@ -0,0 +1,94 @@ + + * @package Thelia\Coupon\Type + */ +trait PercentageCouponTrait +{ + public $percentage = 0; + + /** + * Should return the percentage field name, defined in the parent class. + * + * @return string the percentage field name + */ + abstract protected function getPercentageFieldName(); + + /** + * @inheritdoc + */ + public function setFieldsValue($effects) + { + $this->percentage = $effects[$this->getPercentageFieldName()]; + } + + /** + * @inheritdoc + */ + public function getCartItemDiscount(CartItem $cartItem) + { + return $cartItem->getTotalRealTaxedPrice($this->facade->getDeliveryCountry()) * ($this->percentage / 100); + } + + /** + * @inheritdoc + */ + public function callDrawBackOfficeInputs($templateName) + { + return $this->drawBaseBackOfficeInputs($templateName, [ + 'percentage_field_name' => $this->makeCouponFieldName($this->getPercentageFieldName()), + 'percentage_value' => $this->percentage, + ]); + } + + /** + * @inheritdoc + */ + protected function getFieldList() + { + return $this->getBaseFieldList([$this->getPercentageFieldName()]); + } + + /** + * @inheritdoc + */ + protected function checkCouponFieldValue($fieldName, $fieldValue) + { + $this->checkBaseCouponFieldValue($fieldName, $fieldValue); + + if ($fieldName === $this->getPercentageFieldName()) { + $pcent = \floatval($fieldValue); + + if ($pcent <= 0 || $pcent > 100) { + throw new \InvalidArgumentException( + Translator::getInstance()->trans( + 'Value %val for Percent Discount is invalid. Please enter a positive value between 1 and 100.', + [ '%val' => $fieldValue] + ) + ); + } + } + + return $fieldValue; + } +} diff --git a/core/lib/Thelia/Coupon/Type/RemoveAmountOnAttributeValues.php b/core/lib/Thelia/Coupon/Type/RemoveAmountOnAttributeValues.php new file mode 100644 index 00000000..9b515e8b --- /dev/null +++ b/core/lib/Thelia/Coupon/Type/RemoveAmountOnAttributeValues.php @@ -0,0 +1,64 @@ + + */ +class RemoveAmountOnAttributeValues extends AbstractRemoveOnAttributeValues +{ + use AmountCouponTrait; + + /** @var string Service Id */ + protected $serviceId = 'thelia.coupon.type.remove_amount_on_attribute_av'; + + protected function getAmountFieldName() + { + return self::AMOUNT_FIELD_NAME; + } + /** + * @inheritdoc + */ + public function getName() + { + return $this->facade + ->getTranslator() + ->trans('Fixed amount discount for selected attribute values', array()); + } + + /** + * @inheritdoc + */ + public function getToolTip() + { + $toolTip = $this->facade + ->getTranslator() + ->trans( + 'This coupon subtracts the specified amount from the order total for each product which uses the selected attribute values. If the discount is greater than the total order, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.', + array() + ); + + return $toolTip; + } + + /** + * @inheritdoc + */ + public function drawBackOfficeInputs() + { + return $this->callDrawBackOfficeInputs('coupon/type-fragments/remove-amount-on-attributes.html'); + } +} diff --git a/core/lib/Thelia/Coupon/Type/RemoveAmountOnCategories.php b/core/lib/Thelia/Coupon/Type/RemoveAmountOnCategories.php new file mode 100644 index 00000000..a153aa05 --- /dev/null +++ b/core/lib/Thelia/Coupon/Type/RemoveAmountOnCategories.php @@ -0,0 +1,65 @@ + + */ +class RemoveAmountOnCategories extends AbstractRemoveOnCategories +{ + use AmountCouponTrait; + + /** @var string Service Id */ + protected $serviceId = 'thelia.coupon.type.remove_amount_on_categories'; + + protected function getAmountFieldName() + { + return self::AMOUNT_FIELD_NAME; + } + + /** + * @inheritdoc + */ + public function getName() + { + return $this->facade + ->getTranslator() + ->trans('Fixed amount discount for selected categories', array()); + } + + /** + * @inheritdoc + */ + public function getToolTip() + { + $toolTip = $this->facade + ->getTranslator() + ->trans( + 'This coupon subtracts the specified amount from the order total for each product which belongs to the selected categories. If the discount is greater than the total order, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.', + array() + ); + + return $toolTip; + } + + /** + * @inheritdoc + */ + public function drawBackOfficeInputs() + { + return $this->callDrawBackOfficeInputs('coupon/type-fragments/remove-amount-on-categories.html'); + } +} diff --git a/core/lib/Thelia/Coupon/Type/RemoveAmountOnProducts.php b/core/lib/Thelia/Coupon/Type/RemoveAmountOnProducts.php new file mode 100644 index 00000000..544cb5e8 --- /dev/null +++ b/core/lib/Thelia/Coupon/Type/RemoveAmountOnProducts.php @@ -0,0 +1,69 @@ + + */ +class RemoveAmountOnProducts extends AbstractRemoveOnProducts +{ + use AmountCouponTrait; + + /** @var string Service Id */ + protected $serviceId = 'thelia.coupon.type.remove_amount_on_products'; + + protected function getAmountFieldName() + { + return self::AMOUNT_FIELD_NAME; + } + + /** + * Get I18n name + * + * @return string + */ + public function getName() + { + return $this->facade + ->getTranslator() + ->trans('Fixed amount discount for selected products', array()); + } + + /** + * @inheritdoc + */ + public function getToolTip() + { + $toolTip = $this->facade + ->getTranslator() + ->trans( + 'This coupon subtracts the specified amount from the order total for each selected product. If the discount is greater than the total order, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.', + array() + ); + + return $toolTip; + } + + /** + * @inheritdoc + */ + public function drawBackOfficeInputs() + { + return $this->callDrawBackOfficeInputs('coupon/type-fragments/remove-amount-on-products.html'); + } +} diff --git a/core/lib/Thelia/Coupon/Type/RemovePercentageOnAttributeValues.php b/core/lib/Thelia/Coupon/Type/RemovePercentageOnAttributeValues.php new file mode 100644 index 00000000..40e216a6 --- /dev/null +++ b/core/lib/Thelia/Coupon/Type/RemovePercentageOnAttributeValues.php @@ -0,0 +1,70 @@ + + */ +class RemovePercentageOnAttributeValues extends AbstractRemoveOnAttributeValues +{ + const PERCENTAGE = 'percentage'; + + use PercentageCouponTrait; + + /** @var string Service Id */ + protected $serviceId = 'thelia.coupon.type.remove_percentage_on_attribute_av'; + + /** + * @inheritdoc + */ + protected function getPercentageFieldName() + { + return self::PERCENTAGE; + } + + /** + * @inheritdoc + */ + public function getName() + { + return $this->facade + ->getTranslator() + ->trans('Percentage discount for selected attribute values', array()); + } + + /** + * @inheritdoc + */ + public function getToolTip() + { + $toolTip = $this->facade + ->getTranslator() + ->trans( + 'This coupon subtracts from the order total the specified percentage of each product price which uses the selected attribute values. If the discount is greater than the total order, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.', + array() + ); + + return $toolTip; + } + + /** + * @inheritdoc + */ + public function drawBackOfficeInputs() + { + return $this->callDrawBackOfficeInputs('coupon/type-fragments/remove-percentage-on-attributes.html'); + } +} diff --git a/core/lib/Thelia/Coupon/Type/RemovePercentageOnCategories.php b/core/lib/Thelia/Coupon/Type/RemovePercentageOnCategories.php new file mode 100644 index 00000000..7216a326 --- /dev/null +++ b/core/lib/Thelia/Coupon/Type/RemovePercentageOnCategories.php @@ -0,0 +1,67 @@ + + */ +class RemovePercentageOnCategories extends AbstractRemoveOnCategories +{ + const PERCENTAGE = 'percentage'; + + use PercentageCouponTrait; + + /** @var string Service Id */ + protected $serviceId = 'thelia.coupon.type.remove_percentage_on_categories'; + + /** + * @inheritdoc + */ + protected function getPercentageFieldName() + { + return self::PERCENTAGE; + } + + /** + * @inheritdoc + */ + public function getName() + { + return $this->facade + ->getTranslator() + ->trans('Percentage discount for selected categories', array()); + } + + /** + * @inheritdoc + */ + public function getToolTip() + { + $toolTip = $this->facade + ->getTranslator() + ->trans( + 'This coupon subtracts from the order total a percentage of the price of each product which belongs to the selected categories. If the discount is greater than the total order, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.', + array() + ); + + return $toolTip; + } + + /** + * @inheritdoc + */ + public function drawBackOfficeInputs() + { + return $this->callDrawBackOfficeInputs('coupon/type-fragments/remove-percentage-on-categories.html'); + } +} diff --git a/core/lib/Thelia/Coupon/Type/RemovePercentageOnProducts.php b/core/lib/Thelia/Coupon/Type/RemovePercentageOnProducts.php new file mode 100644 index 00000000..d261b445 --- /dev/null +++ b/core/lib/Thelia/Coupon/Type/RemovePercentageOnProducts.php @@ -0,0 +1,74 @@ + + */ +class RemovePercentageOnProducts extends AbstractRemoveOnProducts +{ + const PERCENTAGE = 'percentage'; + + use PercentageCouponTrait; + + /** @var string Service Id */ + protected $serviceId = 'thelia.coupon.type.remove_percentage_on_products'; + + /** + * @inheritdoc + */ + protected function getPercentageFieldName() + { + return self::PERCENTAGE; + } + + /** + * Get I18n name + * + * @return string + */ + public function getName() + { + return $this->facade + ->getTranslator() + ->trans('Percentage discount for selected products', array()); + } + + /** + * @inheritdoc + */ + public function getToolTip() + { + $toolTip = $this->facade + ->getTranslator() + ->trans( + 'This coupon subtracts from the order total the specified percentage of each selected product price. If the discount is greater than the total order, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.', + array() + ); + + return $toolTip; + } + + /** + * @inheritdoc + */ + public function drawBackOfficeInputs() + { + return $this->callDrawBackOfficeInputs('coupon/type-fragments/remove-percentage-on-products.html'); + } +} diff --git a/core/lib/Thelia/Coupon/Type/RemoveXAmount.php b/core/lib/Thelia/Coupon/Type/RemoveXAmount.php new file mode 100644 index 00000000..eab6abb9 --- /dev/null +++ b/core/lib/Thelia/Coupon/Type/RemoveXAmount.php @@ -0,0 +1,80 @@ +, Franck Allimant + * + */ +class RemoveXAmount extends AbstractRemove +{ + use AmountCouponTrait; + + /** @var string Service Id */ + protected $serviceId = 'thelia.coupon.type.remove_x_amount'; + + protected function getAmountFieldName() + { + return self::AMOUNT_FIELD_NAME; + } + + /** + * @inheritdoc + */ + public function getName() + { + return $this->facade + ->getTranslator() + ->trans('Fixed Amount Discount', array()); + } + + /** + * @inheritdoc + */ + public function getToolTip() + { + $toolTip = $this->facade + ->getTranslator() + ->trans( + 'This coupon will subtracts a set amount from the total cost of an order. If the discount is greater than the total order corst, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.', + array() + ); + + return $toolTip; + } + + /** + * @inheritdoc + */ + public function exec() + { + $cartTotal = $this->facade->getCartTotalTaxPrice($this->isAvailableOnSpecialOffers()); + + if ($this->amount > $cartTotal) { + return $cartTotal; + } + + return $this->amount; + } + + /** + * @inheritdoc + */ + public function drawBackOfficeInputs() + { + return $this->callDrawBackOfficeInputs('coupon/type-fragments/remove-x-amount.html'); + } +} diff --git a/core/lib/Thelia/Coupon/Type/RemoveXPercent.php b/core/lib/Thelia/Coupon/Type/RemoveXPercent.php new file mode 100644 index 00000000..776e4b2c --- /dev/null +++ b/core/lib/Thelia/Coupon/Type/RemoveXPercent.php @@ -0,0 +1,77 @@ +, Franck Allimant + * + */ +class RemoveXPercent extends AbstractRemove +{ + const INPUT_PERCENTAGE_NAME = 'percentage'; + + use PercentageCouponTrait; + + /** @var string Service Id */ + protected $serviceId = 'thelia.coupon.type.remove_x_percent'; + + /** + * @inheritdoc + */ + protected function getPercentageFieldName() + { + return self::INPUT_PERCENTAGE_NAME; + } + + /** + * @inheritdoc + */ + public function getName() + { + return $this->facade + ->getTranslator() + ->trans('Remove X percent to total cart', array()); + } + + /** + * @inheritdoc + */ + public function getToolTip() + { + $toolTip = $this->facade + ->getTranslator() + ->trans( + 'This coupon will offert a flat percentage off a shopper\'s entire order (not applied to shipping costs or tax rates). If the discount is greater than the total order corst, the customer will only pay the shipping, or nothing if the coupon also provides free shipping.', + array() + ); + + return $toolTip; + } + + /** + * @inheritdoc + */ + public function exec() + { + return ($this->facade->getCartTotalTaxPrice($this->isAvailableOnSpecialOffers()) * $this->percentage/100); + } + + /** + * @inheritdoc + */ + public function drawBackOfficeInputs() + { + return $this->callDrawBackOfficeInputs('coupon/type-fragments/remove-x-percent.html'); + } +} diff --git a/core/lib/Thelia/Exception/AdminAccessDenied.php b/core/lib/Thelia/Exception/AdminAccessDenied.php new file mode 100644 index 00000000..0ba57f6e --- /dev/null +++ b/core/lib/Thelia/Exception/AdminAccessDenied.php @@ -0,0 +1,22 @@ + + */ +class AdminAccessDenied extends \RuntimeException +{ +} diff --git a/core/lib/Thelia/Exception/CouponExpiredException.php b/core/lib/Thelia/Exception/CouponExpiredException.php new file mode 100644 index 00000000..440de9a2 --- /dev/null +++ b/core/lib/Thelia/Exception/CouponExpiredException.php @@ -0,0 +1,40 @@ + + * + */ +class CouponExpiredException extends \Exception +{ + /** + * CouponExpiredException thrown when a Coupon is expired + * + * @param string $couponCode Coupon code + */ + public function __construct($couponCode) + { + $message = Translator::getInstance()->trans('Coupon %code is expired.', ['%code' => $couponCode ]); + + Tlog::getInstance()->addWarning($message); + + parent::__construct($message); + } +} diff --git a/core/lib/Thelia/Exception/CouponNoUsageLeftException.php b/core/lib/Thelia/Exception/CouponNoUsageLeftException.php new file mode 100644 index 00000000..6c503f76 --- /dev/null +++ b/core/lib/Thelia/Exception/CouponNoUsageLeftException.php @@ -0,0 +1,39 @@ + + */ +class CouponNoUsageLeftException extends \Exception +{ + /** + * CouponExpiredException thrown when a Coupon is expired + * + * @param string $couponCode Coupon code + */ + public function __construct($couponCode) + { + $message = Translator::getInstance()->trans('Maximum usage count reached for coupon %code', ['%code' => $couponCode ]); + + Tlog::getInstance()->addWarning($message); + + parent::__construct($message); + } +} diff --git a/core/lib/Thelia/Exception/CouponNotReleaseException.php b/core/lib/Thelia/Exception/CouponNotReleaseException.php new file mode 100644 index 00000000..bc221255 --- /dev/null +++ b/core/lib/Thelia/Exception/CouponNotReleaseException.php @@ -0,0 +1,38 @@ + + */ +class CouponNotReleaseException extends \Exception +{ + /** + * CouponNotReleaseException thrown when a Coupon is not release + * + * @param string $couponCode Coupon code + */ + public function __construct($couponCode) + { + $message = Translator::getInstance()->trans('Coupon %code is not release.', ['%code' => $couponCode]); + + Tlog::getInstance()->addWarning($message); + + parent::__construct($message); + } +} diff --git a/core/lib/Thelia/Exception/CustomerException.php b/core/lib/Thelia/Exception/CustomerException.php new file mode 100644 index 00000000..94749f0b --- /dev/null +++ b/core/lib/Thelia/Exception/CustomerException.php @@ -0,0 +1,22 @@ + + */ +class CustomerException extends \RuntimeException +{ +} diff --git a/core/lib/Thelia/Exception/DocumentException.php b/core/lib/Thelia/Exception/DocumentException.php new file mode 100644 index 00000000..80aed355 --- /dev/null +++ b/core/lib/Thelia/Exception/DocumentException.php @@ -0,0 +1,25 @@ +addError($message); + + parent::__construct($message, $code, $previous); + } +} diff --git a/core/lib/Thelia/Exception/FileException.php b/core/lib/Thelia/Exception/FileException.php new file mode 100644 index 00000000..02aff389 --- /dev/null +++ b/core/lib/Thelia/Exception/FileException.php @@ -0,0 +1,25 @@ +addError($message); + + parent::__construct($message, $code, $previous); + } +} diff --git a/core/lib/Thelia/Exception/FileNotFoundException.php b/core/lib/Thelia/Exception/FileNotFoundException.php new file mode 100644 index 00000000..0411a762 --- /dev/null +++ b/core/lib/Thelia/Exception/FileNotFoundException.php @@ -0,0 +1,22 @@ + + */ +class FileNotFoundException extends \ErrorException +{ +} diff --git a/core/lib/Thelia/Exception/FileNotReadableException.php b/core/lib/Thelia/Exception/FileNotReadableException.php new file mode 100644 index 00000000..1e525f1d --- /dev/null +++ b/core/lib/Thelia/Exception/FileNotReadableException.php @@ -0,0 +1,22 @@ + + */ +class FileNotReadableException extends \Exception +{ +} diff --git a/core/lib/Thelia/Exception/HttpUrlException.php b/core/lib/Thelia/Exception/HttpUrlException.php new file mode 100644 index 00000000..857208c1 --- /dev/null +++ b/core/lib/Thelia/Exception/HttpUrlException.php @@ -0,0 +1,22 @@ + + */ +class HttpUrlException extends \Exception +{ +} diff --git a/core/lib/Thelia/Exception/ImageException.php b/core/lib/Thelia/Exception/ImageException.php new file mode 100644 index 00000000..ec8bbb67 --- /dev/null +++ b/core/lib/Thelia/Exception/ImageException.php @@ -0,0 +1,25 @@ +addError($message); + + parent::__construct($message, $code, $previous); + } +} diff --git a/core/lib/Thelia/Exception/InactiveCouponException.php b/core/lib/Thelia/Exception/InactiveCouponException.php new file mode 100644 index 00000000..8536ffe7 --- /dev/null +++ b/core/lib/Thelia/Exception/InactiveCouponException.php @@ -0,0 +1,34 @@ + + */ +class InactiveCouponException extends \RuntimeException +{ + + public function __construct($couponCode) + { + $message = Translator::getInstance()->trans('Coupon code %code is disabled.', ['%code' => $couponCode ]); + + Tlog::getInstance()->addWarning($message); + + parent::__construct($message); + } +} diff --git a/core/lib/Thelia/Exception/InvalidCartException.php b/core/lib/Thelia/Exception/InvalidCartException.php new file mode 100644 index 00000000..a071ca90 --- /dev/null +++ b/core/lib/Thelia/Exception/InvalidCartException.php @@ -0,0 +1,17 @@ + + * + */ +class InvalidConditionException extends \RuntimeException +{ + /** + * InvalidConditionOperatorException thrown when a Condition is badly implemented + * + * @param string $className Class name + */ + public function __construct($className) + { + $message = 'Invalid Condition given to ' . $className; + Tlog::getInstance()->addError($message); + + parent::__construct($message); + } +} diff --git a/core/lib/Thelia/Exception/InvalidConditionOperatorException.php b/core/lib/Thelia/Exception/InvalidConditionOperatorException.php new file mode 100644 index 00000000..4d2dc8dc --- /dev/null +++ b/core/lib/Thelia/Exception/InvalidConditionOperatorException.php @@ -0,0 +1,39 @@ + + * + */ +class InvalidConditionOperatorException extends \RuntimeException +{ + /** + * InvalidConditionOperatorException thrown when a Condition is given a bad Operator + * + * @param string $className Class name + * @param string $parameter array key parameter + */ + public function __construct($className, $parameter) + { + $message = 'Invalid Operator for Condition ' . $className . ' on parameter ' . $parameter; + Tlog::getInstance()->addError($message); + + parent::__construct($message); + } +} diff --git a/core/lib/Thelia/Exception/InvalidConditionValueException.php b/core/lib/Thelia/Exception/InvalidConditionValueException.php new file mode 100644 index 00000000..e2808cec --- /dev/null +++ b/core/lib/Thelia/Exception/InvalidConditionValueException.php @@ -0,0 +1,39 @@ + + * + */ +class InvalidConditionValueException extends \RuntimeException +{ + /** + * InvalidConditionValueException thrown when a Condition is given a bad Parameter + * + * @param string $className Class name + * @param string $parameter array key parameter + */ + public function __construct($className, $parameter) + { + $message = 'Invalid Parameter for Condition ' . $className . ' on parameter ' . $parameter; + Tlog::getInstance()->addError($message); + + parent::__construct($message); + } +} diff --git a/core/lib/Thelia/Exception/InvalidModuleException.php b/core/lib/Thelia/Exception/InvalidModuleException.php new file mode 100644 index 00000000..fe258c40 --- /dev/null +++ b/core/lib/Thelia/Exception/InvalidModuleException.php @@ -0,0 +1,50 @@ + + */ +class InvalidModuleException extends \RuntimeException +{ + protected $errors = []; + + public function __construct(array $errors = []) + { + parent::__construct(); + + $this->errors = $errors; + } + + /** + * @return array + */ + public function getErrors() + { + return $this->errors; + } + + public function getErrorsAsString($separator = "\n") + { + $message = ''; + + /** @var \Exception $error */ + foreach ($this->errors as $error) { + $message .= $error->getMessage() . $separator; + } + + return rtrim($message, $separator); + } +} diff --git a/core/lib/Thelia/Exception/MemberAccessException.php b/core/lib/Thelia/Exception/MemberAccessException.php new file mode 100644 index 00000000..8af4e64e --- /dev/null +++ b/core/lib/Thelia/Exception/MemberAccessException.php @@ -0,0 +1,17 @@ + + * + */ +class MissingFacadeException extends \RuntimeException +{ + /** + * {@inheritdoc} + */ + public function __construct($message, $code = null, $previous = null) + { + Tlog::getInstance()->addError($message); + + parent::__construct($message, $code, $previous); + } +} diff --git a/core/lib/Thelia/Exception/ModuleException.php b/core/lib/Thelia/Exception/ModuleException.php new file mode 100644 index 00000000..be581cf5 --- /dev/null +++ b/core/lib/Thelia/Exception/ModuleException.php @@ -0,0 +1,28 @@ + + * + */ +class NotImplementedException extends BadMethodCallException +{ +} diff --git a/core/lib/Thelia/Exception/OrderException.php b/core/lib/Thelia/Exception/OrderException.php new file mode 100644 index 00000000..e00fd1c6 --- /dev/null +++ b/core/lib/Thelia/Exception/OrderException.php @@ -0,0 +1,42 @@ +arguments = $arguments; + } + if ($code === null) { + $code = self::UNKNOWN_EXCEPTION; + } + parent::__construct($message, $code, $previous); + } +} diff --git a/core/lib/Thelia/Exception/TaxEngineException.php b/core/lib/Thelia/Exception/TaxEngineException.php new file mode 100644 index 00000000..b9b2363a --- /dev/null +++ b/core/lib/Thelia/Exception/TaxEngineException.php @@ -0,0 +1,45 @@ +data = $data; + + if ($code === null) { + $code = self::UNKNOWN_EXCEPTION; + } + parent::__construct($message, $code, $previous); + } +} diff --git a/core/lib/Thelia/Exception/TypeException.php b/core/lib/Thelia/Exception/TypeException.php new file mode 100644 index 00000000..bb8e3f15 --- /dev/null +++ b/core/lib/Thelia/Exception/TypeException.php @@ -0,0 +1,28 @@ + + */ +class UnmatchableConditionException extends \RuntimeException +{ +} diff --git a/core/lib/Thelia/Exception/UrlRewritingException.php b/core/lib/Thelia/Exception/UrlRewritingException.php new file mode 100644 index 00000000..0ff0a386 --- /dev/null +++ b/core/lib/Thelia/Exception/UrlRewritingException.php @@ -0,0 +1,32 @@ + + */ +class ProcessFileException extends \RuntimeException +{ +} diff --git a/core/lib/Thelia/Files/FileConfiguration.php b/core/lib/Thelia/Files/FileConfiguration.php new file mode 100644 index 00000000..03806e4e --- /dev/null +++ b/core/lib/Thelia/Files/FileConfiguration.php @@ -0,0 +1,51 @@ + + */ +class FileConfiguration +{ + public static function getImageConfig() + { + return [ + 'objectType' => 'image', + 'validMimeTypes' => [ + 'image/jpeg' => ["jpg", "jpeg"], + 'image/png' => ["png"], + 'image/gif' => ["gif"], + ], + 'extBlackList' => [] + ]; + } + + public static function getDocumentConfig() + { + return [ + 'objectType' => 'document', + 'validMimeTypes' => [], + 'extBlackList' => [ + "php", + "php3", + "php4", + "php5", + "php6", + "asp", + "aspx", + ] + ]; + } +} diff --git a/core/lib/Thelia/Files/FileManager.php b/core/lib/Thelia/Files/FileManager.php new file mode 100644 index 00000000..1f34537e --- /dev/null +++ b/core/lib/Thelia/Files/FileManager.php @@ -0,0 +1,269 @@ +, Franck Allimant + * + */ +class FileManager +{ + protected $supportedFileModels = array(); + + /** + * Create a new FileManager instance. + * + * @param array $supportedFileModels The key should have form type.parent, where type is the file type (document or image) and parent is the parent object of the file, form example product, brand, folder, etc. + */ + public function __construct($supportedFileModels) + { + $this->supportedFileModels = $supportedFileModels; + } + + /** + * Create the file type identifier, to access the related class in the supportedFileModels table. + * + * @param string $fileType the file type, e.g. document or image. + * @param string $parentType the parent object type, e.g. product, folder, brand, etc. + * @return string + */ + protected function getFileTypeIdentifier($fileType, $parentType) + { + return strtolower("$fileType.$parentType"); + } + /** + * Create a new FileModelInterface instance, from the supportedFileModels table + * + * @param string $fileType the file type, such as document, image, etc. + * @param string $parentType the parent type, such as product, category, etc. + * + * @return FileModelInterface a file model interface instance + * + * @throws FileException if the file type is not supported, or if the class does not implements FileModelInterface + */ + public function getModelInstance($fileType, $parentType) + { + if (! isset($this->supportedFileModels[$this->getFileTypeIdentifier($fileType, $parentType)])) { + throw new FileException( + sprintf("Unsupported file type '%s' for parent type '%s'", $fileType, $parentType) + ); + } + + $className = $this->supportedFileModels[$this->getFileTypeIdentifier($fileType, $parentType)]; + + $instance = new $className; + + if (! $instance instanceof FileModelInterface) { + throw new FileException( + sprintf( + "Wrong class type for file type '%s', parent type '%s'. Class '%s' should implements FileModelInterface", + $fileType, + $parentType, + $className + ) + ); + } + + return $instance; + } + + /** + * A a new FileModelInterface class name to the supported class list. + * + * @param string $fileType the file type, such as document, image, etc. + * @param string $parentType the parent type, such as Product, Category, etc. + * @param string $fullyQualifiedClassName the fully qualified class name + */ + public function addFileModel($fileType, $parentType, $fullyQualifiedClassName) + { + $this->supportedFileModels[$this->getFileTypeIdentifier($fileType, $parentType)] = $fullyQualifiedClassName; + } + + /** + * Copy UploadedFile into the server storage directory + * + * @param FileModelInterface $model Model saved + * @param UploadedFile $uploadedFile Ready to be uploaded file + * @param ConnectionInterface $con current transaction with database + * + * @throws \Thelia\Exception\ImageException + * @return UploadedFile|null + */ + public function copyUploadedFile(FileModelInterface $model, UploadedFile $uploadedFile, ConnectionInterface $con = null) + { + $newUploadedFile = null; + + if ($uploadedFile !== null) { + $directory = $model->getUploadDir(); + + $fileName = $this->renameFile($model->getId(), $uploadedFile); + + $newUploadedFile = $uploadedFile->move($directory, $fileName); + $model->setFile($fileName); + + if (!$model->save($con)) { + throw new ImageException( + sprintf( + 'Failed to update model after copy of uploaded file %s to %s', + $uploadedFile, + $model->getFile() + ) + ); + } + } + + return $newUploadedFile; + } + /** + * Save file into the database + * + * @param int $parentId the parent object ID + * @param FileModelInterface $fileModel the file model object (image or document) to save. + * + * @return int number of modified rows in database + * + * @throws \Thelia\Exception\ImageException + */ + protected function saveFile($parentId, FileModelInterface $fileModel) + { + $nbModifiedLines = 0; + + if ($fileModel->getFile() !== null) { + $fileModel->setParentId($parentId); + + $nbModifiedLines = $fileModel->save(); + + if (!$nbModifiedLines) { + throw new ImageException( + sprintf( + 'Failed to update %s file model', + $fileModel->getFile() + ) + ); + } + } + + return $nbModifiedLines; + } + + /** + * Save file into the database + * + * @param FileCreateOrUpdateEvent $event the event + * @param FileModelInterface $imageModel the file model object (image or document) to save. + * + * @return int number of modified rows in database + */ + public function saveImage(FileCreateOrUpdateEvent $event, FileModelInterface $imageModel) + { + return $this->saveFile($event->getParentId(), $imageModel); + } + + /** + * Save file into the database + * + * @param FileCreateOrUpdateEvent $event the event + * @param FileModelInterface $documentModel the file model object (image or document) to save. + * + * @return int number of modified rows in database + */ + public function saveDocument(FileCreateOrUpdateEvent $event, FileModelInterface $documentModel) + { + return $this->saveFile($event->getParentId(), $documentModel); + } + + /** + * Sanitizes a filename replacing whitespace with dashes + * + * Removes special characters that are illegal in filenames on certain + * operating systems and special characters requiring special escaping + * to manipulate at the command line. + * + * @param string $string The filename to be sanitized + * + * @return string The sanitized filename + */ + public function sanitizeFileName($string) + { + return strtolower(preg_replace('/[^a-zA-Z0-9-_\.]/', '', $string)); + } + + /** + * Delete image from file storage and database + * + * @param FileModelInterface $model File being deleted + */ + public function deleteFile(FileModelInterface $model) + { + $url = $model->getUploadDir() . DS . $model->getFile(); + + @unlink(str_replace('..', '', $url)); + + $model->delete(); + } + + /** + * Rename file with image model id + * + * @param int $modelId Model id + * @param UploadedFile $uploadedFile File being saved + * + * @return string + */ + public function renameFile($modelId, UploadedFile $uploadedFile) + { + $extension = $uploadedFile->getClientOriginalExtension(); + if (!empty($extension)) { + $extension = '.' . strtolower($extension); + } + $fileName = $this->sanitizeFileName( + str_replace( + $extension, + '', + $uploadedFile->getClientOriginalName() + ) . '-' . $modelId . $extension + ); + + return $fileName; + } + + /** + * Check if a file is an image + * Check based on mime type + * + * @param string $mimeType File mime type + * + * @return bool + */ + public function isImage($mimeType) + { + $isValid = false; + + $allowedType = array('image/jpeg' , 'image/png' ,'image/gif'); + + if (\in_array($mimeType, $allowedType)) { + $isValid = true; + } + + return $isValid; + } +} diff --git a/core/lib/Thelia/Files/FileModelInterface.php b/core/lib/Thelia/Files/FileModelInterface.php new file mode 100644 index 00000000..4a24f92f --- /dev/null +++ b/core/lib/Thelia/Files/FileModelInterface.php @@ -0,0 +1,153 @@ + + */ +trait AddressCountryValidationTrait +{ + + public function verifyZipCode($value, ExecutionContextInterface $context) + { + $data = $context->getRoot()->getData(); + + if (null !== $country = CountryQuery::create()->findPk($data['country'])) { + if ($country->getNeedZipCode()) { + $zipCodeRegExp = $country->getZipCodeRE(); + if (null !== $zipCodeRegExp) { + if (!preg_match($zipCodeRegExp, $data['zipcode'])) { + $context->addViolation( + Translator::getInstance()->trans( + "This zip code should respect the following format : %format.", + ['%format' => $country->getZipCodeFormat()] + ) + ); + } + } + } + } + } + + public function verifyState($value, ExecutionContextInterface $context) + { + $data = $context->getRoot()->getData(); + + if (null !== $country = CountryQuery::create()->findPk($data['country'])) { + if ($country->getHasStates()) { + if (null !== $state = StateQuery::create()->findPk($data['state'])) { + if ($state->getCountryId() !== $country->getId()) { + $context->addViolation( + Translator::getInstance()->trans( + "This state doesn't belong to this country." + ) + ); + } + } else { + $context->addViolation( + Translator::getInstance()->trans( + "You should select a state for this country." + ) + ); + } + } + } + } +} diff --git a/core/lib/Thelia/Form/AddressCreateForm.php b/core/lib/Thelia/Form/AddressCreateForm.php new file mode 100644 index 00000000..064f660c --- /dev/null +++ b/core/lib/Thelia/Form/AddressCreateForm.php @@ -0,0 +1,197 @@ + + */ +class AddressCreateForm extends FirewallForm +{ + use AddressCountryValidationTrait; + + /** + * + * in this function you add all the fields you need for your Form. + * Form this you have to call add method on $this->formBuilder attribute : + * + * $this->formBuilder->add("name", "text") + * ->add("email", "email", array( + * "attr" => array( + * "class" => "field" + * ), + * "label" => "email", + * "constraints" => array( + * new \Symfony\Component\Validator\Constraints\NotBlank() + * ) + * ) + * ) + * ->add('age', 'integer'); + * + * @return null + */ + protected function buildForm() + { + $this->formBuilder + ->add("label", "text", array( + "constraints" => array( + new NotBlank(), + ), + "label" => Translator::getInstance()->trans("Address label"), + "label_attr" => array( + "for" => "address_label", + ), + )) + ->add("title", "text", array( + "constraints" => array( + new Constraints\NotBlank(), + ), + "label" => Translator::getInstance()->trans("Title"), + "label_attr" => array( + "for" => "title", + ), + )) + ->add("firstname", "text", array( + "constraints" => array( + new Constraints\NotBlank(), + ), + "label" => Translator::getInstance()->trans("First Name"), + "label_attr" => array( + "for" => "firstname", + ), + )) + ->add("lastname", "text", array( + "constraints" => array( + new Constraints\NotBlank(), + ), + "label" => Translator::getInstance()->trans("Last Name"), + "label_attr" => array( + "for" => "lastname", + ), + )) + ->add("company", "text", array( + "label" => Translator::getInstance()->trans("Company Name"), + "label_attr" => array( + "for" => "company", + ), + "required" => false, + )) + ->add("address1", "text", array( + "constraints" => array( + new Constraints\NotBlank(), + ), + "label" => Translator::getInstance()->trans("Street Address"), + "label_attr" => array( + "for" => "address1", + ), + )) + ->add("address2", "text", array( + "label" => Translator::getInstance()->trans("Address Line 2"), + "label_attr" => array( + "for" => "address2", + ), + "required" => false, + )) + ->add("address3", "text", array( + "label" => Translator::getInstance()->trans("Address Line 3"), + "label_attr" => array( + "for" => "address3", + ), + "required" => false, + )) + ->add("city", "text", array( + "constraints" => array( + new Constraints\NotBlank(), + ), + "label" => Translator::getInstance()->trans("City"), + "label_attr" => array( + "for" => "city", + ), + )) + ->add("zipcode", "text", array( + "constraints" => array( + new Constraints\NotBlank(), + new Constraints\Callback(array( + "methods" => array( + array($this, "verifyZipCode") + ), + )), + ), + "label" => Translator::getInstance()->trans("Zip code"), + "label_attr" => array( + "for" => "zipcode", + ), + )) + ->add("country", "text", array( + "constraints" => array( + new Constraints\NotBlank(), + ), + "label" => Translator::getInstance()->trans("Country"), + "label_attr" => array( + "for" => "country", + ), + )) + ->add("state", "text", array( + "required" => false, + "constraints" => array( + new Constraints\Callback(array( + "methods" => array( + array($this, "verifyState") + ), + )), + ), + + "label" => Translator::getInstance()->trans("State *"), + "label_attr" => array( + "for" => "state", + ), + )) + // Phone + ->add("phone", "text", array( + "label" => Translator::getInstance()->trans("Phone"), + "label_attr" => array( + "for" => "phone", + ), + "required" => false, + )) + ->add("cellphone", "text", array( + "label" => Translator::getInstance()->trans("Cellphone"), + "label_attr" => array( + "for" => "cellphone", + ), + "required" => false, + )) + // Default address + ->add("is_default", "checkbox", array( + "label" => Translator::getInstance()->trans("Make this address as my primary address"), + "label_attr" => array( + "for" => "default_address", + ), + "required" => false, + )) + ; + } + + /** + * @return string the name of you form. This name must be unique + */ + public function getName() + { + return "thelia_address_creation"; + } +} diff --git a/core/lib/Thelia/Form/AddressUpdateForm.php b/core/lib/Thelia/Form/AddressUpdateForm.php new file mode 100644 index 00000000..e67a259b --- /dev/null +++ b/core/lib/Thelia/Form/AddressUpdateForm.php @@ -0,0 +1,34 @@ + + */ +class AddressUpdateForm extends AddressCreateForm +{ + protected function buildForm() + { + parent::buildForm(); + } + + /** + * @return string the name of you form. This name must be unique + */ + public function getName() + { + return "thelia_address_update"; + } +} diff --git a/core/lib/Thelia/Form/AdminCreatePassword.php b/core/lib/Thelia/Form/AdminCreatePassword.php new file mode 100644 index 00000000..14417269 --- /dev/null +++ b/core/lib/Thelia/Form/AdminCreatePassword.php @@ -0,0 +1,70 @@ +formBuilder + ->add("password", "password", array( + "constraints" => array(), + "label" => $this->translator->trans("Password"), + "label_attr" => array( + "for" => "password", + ), + "attr" => [ + 'placeholder' => Translator::getInstance()->trans('Enter the new password') + ] + )) + ->add("password_confirm", "password", array( + "constraints" => array( + new Callback(array("methods" => array( + array($this, "verifyPasswordField"), + ))), + ), + "label" => $this->translator->trans('Password confirmation'), + "label_attr" => array( + "for" => "password_confirmation", + ), + "attr" => [ + 'placeholder' => Translator::getInstance()->trans('Enter the new password again') + ] + )) + ; + } + + public function verifyPasswordField($value, ExecutionContextInterface $context) + { + $data = $context->getRoot()->getData(); + + if ($data["password"] === '' && $data["password_confirm"] === '') { + $context->addViolation("password can't be empty"); + } + + if ($data["password"] != $data["password_confirm"]) { + $context->addViolation("password confirmation is not the same as password field"); + } + + $minLength = ConfigQuery::getMinimuAdminPasswordLength(); + + if (\strlen($data["password"]) < $minLength) { + $context->addViolation("password must be composed of at least $minLength characters"); + } + } +} diff --git a/core/lib/Thelia/Form/AdminLogin.php b/core/lib/Thelia/Form/AdminLogin.php new file mode 100644 index 00000000..3e1c32eb --- /dev/null +++ b/core/lib/Thelia/Form/AdminLogin.php @@ -0,0 +1,57 @@ +formBuilder + ->add("username", "text", array( + "constraints" => array( + new NotBlank(), + new Length(array("min" => 3)), + ), + "label" => Translator::getInstance()->trans("Username or e-mail address *"), + "label_attr" => array( + "for" => "username", + ), + )) + ->add("password", "password", array( + "constraints" => array( + new NotBlank(), + ), + "label" => Translator::getInstance()->trans("Password *"), + "label_attr" => array( + "for" => "password", + ), + )) + ->add("remember_me", "checkbox", array( + 'value' => 'yes', + "label" => Translator::getInstance()->trans("Remember me ?"), + "label_attr" => array( + "for" => "remember_me", + ), + )) + ; + } + + public function getName() + { + return "thelia_admin_login"; + } +} diff --git a/core/lib/Thelia/Form/AdminLostPassword.php b/core/lib/Thelia/Form/AdminLostPassword.php new file mode 100644 index 00000000..c85b2669 --- /dev/null +++ b/core/lib/Thelia/Form/AdminLostPassword.php @@ -0,0 +1,36 @@ +formBuilder + ->add("username_or_email", "text", array( + "constraints" => array( + new NotBlank(), + new Length(array("min" => 3)), + ), + "label" => Translator::getInstance()->trans("Username or e-mail address *"), + "label_attr" => array( + "for" => "username", + ), + )) + ; + } +} diff --git a/core/lib/Thelia/Form/AdministratorCreationForm.php b/core/lib/Thelia/Form/AdministratorCreationForm.php new file mode 100644 index 00000000..61a6865e --- /dev/null +++ b/core/lib/Thelia/Form/AdministratorCreationForm.php @@ -0,0 +1,181 @@ +formBuilder + ->add("login", "text", array( + "constraints" => array( + new Constraints\NotBlank(), + new Constraints\Callback(array( + "methods" => array( + array($this, "verifyExistingLogin"), + ), + )), + ), + "label" => $this->translator->trans("Login name"), + "label_attr" => array( + "for" => "login", + 'help' => $this->translator->trans("This is the name used on the login screen") + ), + )) + ->add("email", "email", array( + "constraints" => array( + new Constraints\NotBlank(), + new Constraints\Email(), + new Constraints\Callback(array( + "methods" => array( + array($this, "verifyExistingEmail"), + ), + )), + ), + "label" => $this->translator->trans("Email address"), + "label_attr" => array( + "for" => "email", + 'help' => $this->translator->trans("Please enter a valid email address") + ), + 'attr' => [ + 'placeholder' => $this->translator->trans('Administrator email address'), + ] + )) + ->add("firstname", "text", array( + "constraints" => array( + new Constraints\NotBlank(), + ), + "label" => $this->translator->trans("First Name"), + "label_attr" => array( + "for" => "firstname", + ), + )) + ->add("lastname", "text", array( + "constraints" => array( + new Constraints\NotBlank(), + ), + "label" => $this->translator->trans("Last Name"), + "label_attr" => array( + "for" => "lastname", + ), + )) + ->add("password", "password", array( + "constraints" => array(), + "label" => $this->translator->trans("Password"), + "label_attr" => array( + "for" => "password", + ), + )) + ->add("password_confirm", "password", array( + "constraints" => array( + new Constraints\Callback(array("methods" => array( + array($this, "verifyPasswordField"), + ))), + ), + "label" => $this->translator->trans('Password confirmation'), + "label_attr" => array( + "for" => "password_confirmation", + ), + )) + ->add( + 'profile', + "choice", + array( + "choices" => ProfileQuery::getProfileList(), + "constraints" => array( + new Constraints\NotBlank(), + ), + "label" => $this->translator->trans('Profile'), + "label_attr" => array( + "for" => "profile", + ), + ) + ) + ->add( + 'locale', + "choice", + array( + "choices" => $this->getLocaleList(), + "constraints" => array( + new Constraints\NotBlank(), + ), + "label" => $this->translator->trans('Preferred locale'), + "label_attr" => array( + "for" => "locale", + ), + ) + ) + ; + } + + protected function getLocaleList() + { + $locales = array(); + + $list = LangQuery::create()->find(); + + foreach ($list as $item) { + $locales[$item->getLocale()] = $item->getLocale(); + } + + return $locales; + } + + public function verifyPasswordField($value, ExecutionContextInterface $context) + { + $data = $context->getRoot()->getData(); + + if ($data["password"] === '' && $data["password_confirm"] === '') { + $context->addViolation("password can't be empty"); + } + + if ($data["password"] != $data["password_confirm"]) { + $context->addViolation("password confirmation is not the same as password field"); + } + + $minLength = ConfigQuery::getMinimuAdminPasswordLength(); + + if (\strlen($data["password"]) < $minLength) { + $context->addViolation("password must be composed of at least $minLength characters"); + } + } + + public function verifyExistingLogin($value, ExecutionContextInterface $context) + { + if (null !== $administrator = AdminQuery::create()->findOneByLogin($value)) { + $context->addViolation($this->translator->trans("This administrator login already exists")); + } + } + + public function verifyExistingEmail($value, ExecutionContextInterface $context) + { + if (null !== $administrator = AdminQuery::create()->findOneByEmail($value)) { + $context->addViolation($this->translator->trans("An administrator with thie email address already exists")); + } + } + + public function getName() + { + return "thelia_admin_administrator_creation"; + } +} diff --git a/core/lib/Thelia/Form/AdministratorModificationForm.php b/core/lib/Thelia/Form/AdministratorModificationForm.php new file mode 100644 index 00000000..864096ca --- /dev/null +++ b/core/lib/Thelia/Form/AdministratorModificationForm.php @@ -0,0 +1,103 @@ +formBuilder + ->add("id", "hidden", array( + "required" => true, + "constraints" => array( + new Constraints\NotBlank(), + new Constraints\Callback( + array( + "methods" => array( + array($this, "verifyAdministratorId"), + ), + ) + ), + ), + "attr" => array( + "id" => "administrator_update_id", + ), + )) + ; + + $this->formBuilder->get('password')->setRequired(false); + $this->formBuilder->get('password_confirm')->setRequired(false); + } + + /** + * @return string the name of you form. This name must be unique + */ + public function getName() + { + return "thelia_admin_administrator_modification"; + } + + public function verifyAdministratorId($value, ExecutionContextInterface $context) + { + $administrator = AdminQuery::create() + ->findPk($value); + + if (null === $administrator) { + $context->addViolation(Translator::getInstance()->trans("Administrator ID not found")); + } + } + + public function verifyExistingLogin($value, ExecutionContextInterface $context) + { + $data = $context->getRoot()->getData(); + + $administrator = AdminQuery::create()->findOneByLogin($value); + + if (null !== $administrator && $administrator->getId() != $data['id']) { + $context->addViolation($this->translator->trans("This administrator login already exists")); + } + } + + public function verifyExistingEmail($value, ExecutionContextInterface $context) + { + $data = $context->getRoot()->getData(); + + $administrator = AdminQuery::create()->findOneByEmail($value); + + if (null !== $administrator && $administrator->getId() != $data['id']) { + $context->addViolation($this->translator->trans("An administrator with this email address already exists")); + } + } + + public function verifyPasswordField($value, ExecutionContextInterface $context) + { + $data = $context->getRoot()->getData(); + + if (!empty($data["password"])) { + if ($data["password"] != $data["password_confirm"]) { + $context->addViolation(Translator::getInstance()->trans("password confirmation is not the same as password field")); + } + + if ($data["password"] !== '' && \strlen($data["password"]) < 4) { + $context->addViolation(Translator::getInstance()->trans("password must be composed of at least 4 characters")); + } + } + } +} diff --git a/core/lib/Thelia/Form/Api/ApiCreateForm.php b/core/lib/Thelia/Form/Api/ApiCreateForm.php new file mode 100644 index 00000000..b1cbf480 --- /dev/null +++ b/core/lib/Thelia/Form/Api/ApiCreateForm.php @@ -0,0 +1,81 @@ + + */ +class ApiCreateForm extends BaseForm +{ + /** + * + * in this function you add all the fields you need for your Form. + * Form this you have to call add method on $this->formBuilder attribute : + * + * $this->formBuilder->add("name", "text") + * ->add("email", "email", array( + * "attr" => array( + * "class" => "field" + * ), + * "label" => "email", + * "constraints" => array( + * new \Symfony\Component\Validator\Constraints\NotBlank() + * ) + * ) + * ) + * ->add('age', 'integer'); + * + * @return null + */ + protected function buildForm() + { + $this->formBuilder + ->add('label', 'text', [ + 'constraints' => [ + new NotBlank(), + ], + 'label' => Translator::getInstance()->trans('label'), + 'label_attr' => ['for' => 'api_label'] + ]) + ->add( + 'profile', + "choice", + array( + "choices" => ProfileQuery::getProfileList(), + "constraints" => array( + new NotBlank(), + ), + "label" => Translator::getInstance()->trans('Profile'), + "label_attr" => array( + "for" => "profile", + ), + ) + ) + ; + } + + /** + * @return string the name of you form. This name must be unique + */ + public function getName() + { + return 'thelia_api_create'; + } +} diff --git a/core/lib/Thelia/Form/Api/ApiEmptyForm.php b/core/lib/Thelia/Form/Api/ApiEmptyForm.php new file mode 100644 index 00000000..e92cc327 --- /dev/null +++ b/core/lib/Thelia/Form/Api/ApiEmptyForm.php @@ -0,0 +1,28 @@ + + */ +class ApiEmptyForm extends EmptyForm +{ + public function getName() + { + return ''; + } +} diff --git a/core/lib/Thelia/Form/Api/ApiUpdateForm.php b/core/lib/Thelia/Form/Api/ApiUpdateForm.php new file mode 100644 index 00000000..323507e2 --- /dev/null +++ b/core/lib/Thelia/Form/Api/ApiUpdateForm.php @@ -0,0 +1,73 @@ + + */ +class ApiUpdateForm extends BaseForm +{ + /** + * + * in this function you add all the fields you need for your Form. + * Form this you have to call add method on $this->formBuilder attribute : + * + * $this->formBuilder->add("name", "text") + * ->add("email", "email", array( + * "attr" => array( + * "class" => "field" + * ), + * "label" => "email", + * "constraints" => array( + * new \Symfony\Component\Validator\Constraints\NotBlank() + * ) + * ) + * ) + * ->add('age', 'integer'); + * + * @return null + */ + protected function buildForm() + { + $this->formBuilder + ->add( + 'profile', + "choice", + array( + "choices" => ProfileQuery::getProfileList(), + "constraints" => array( + new NotBlank(), + ), + "label" => Translator::getInstance()->trans('Profile'), + "label_attr" => array( + "for" => "profile", + ), + ) + ); + } + + /** + * @return string the name of you form. This name must be unique + */ + public function getName() + { + return 'thelia_api_create'; + } +} diff --git a/core/lib/Thelia/Form/Api/Category/CategoryCreationForm.php b/core/lib/Thelia/Form/Api/Category/CategoryCreationForm.php new file mode 100644 index 00000000..b70603bf --- /dev/null +++ b/core/lib/Thelia/Form/Api/Category/CategoryCreationForm.php @@ -0,0 +1,28 @@ + + */ +class CategoryCreationForm extends BaseCategoryCreationForm +{ + public function getName() + { + return ''; + } +} diff --git a/core/lib/Thelia/Form/Api/Category/CategoryModificationForm.php b/core/lib/Thelia/Form/Api/Category/CategoryModificationForm.php new file mode 100644 index 00000000..aaf62c80 --- /dev/null +++ b/core/lib/Thelia/Form/Api/Category/CategoryModificationForm.php @@ -0,0 +1,28 @@ + + */ +class CategoryModificationForm extends BaseCategoryModificationForm +{ + public function getName() + { + return ''; + } +} diff --git a/core/lib/Thelia/Form/Api/Customer/CustomerCreateForm.php b/core/lib/Thelia/Form/Api/Customer/CustomerCreateForm.php new file mode 100644 index 00000000..9588acc8 --- /dev/null +++ b/core/lib/Thelia/Form/Api/Customer/CustomerCreateForm.php @@ -0,0 +1,44 @@ + + */ +class CustomerCreateForm extends BaseCustomerCreateForm +{ + public function buildForm() + { + parent::buildForm(); + + $this->formBuilder + ->remove('email_confirm') + ->remove('password_confirm') + ->remove('agreed') + ->add('lang_id', 'integer', [ + 'constraints' => [ + new NotBlank(), + ] + ]); + } + + public function getName() + { + return ''; + } +} diff --git a/core/lib/Thelia/Form/Api/Customer/CustomerLogin.php b/core/lib/Thelia/Form/Api/Customer/CustomerLogin.php new file mode 100644 index 00000000..471b0f19 --- /dev/null +++ b/core/lib/Thelia/Form/Api/Customer/CustomerLogin.php @@ -0,0 +1,54 @@ + + */ +class CustomerLogin extends BaseCustomerLogin +{ + public function buildForm() + { + parent::buildForm(); + + $this->formBuilder->remove('remember_me'); + $this->formBuilder->remove('account'); + + $this->formBuilder->add("account", "text", array( + "constraints" => array( + new Constraints\Callback(array( + "methods" => array( + array($this, "verifyAccount"), + ), + )), + ), + "label_attr" => array( + "for" => "account", + ), + "empty_data" => 1, + "required" => false, + )); + } + + public function getName() + { + return ''; + } +} diff --git a/core/lib/Thelia/Form/Api/Customer/CustomerUpdateForm.php b/core/lib/Thelia/Form/Api/Customer/CustomerUpdateForm.php new file mode 100644 index 00000000..c74cf825 --- /dev/null +++ b/core/lib/Thelia/Form/Api/Customer/CustomerUpdateForm.php @@ -0,0 +1,38 @@ + + */ +class CustomerUpdateForm extends BaseCustomerUpdateForm +{ + public function buildForm() + { + parent::buildForm(); + + $this->formBuilder + ->add('lang_id', 'lang_id') + ->add('id', 'customer_id') + ; + } + + public function getName() + { + return ''; + } +} diff --git a/core/lib/Thelia/Form/Api/Product/ProductCreationForm.php b/core/lib/Thelia/Form/Api/Product/ProductCreationForm.php new file mode 100644 index 00000000..594f86ab --- /dev/null +++ b/core/lib/Thelia/Form/Api/Product/ProductCreationForm.php @@ -0,0 +1,57 @@ + + */ +class ProductCreationForm extends BaseProductCreationForm +{ + use StandardDescriptionFieldsTrait; + + /** + * @inherited + */ + protected function buildForm() + { + $translator = Translator::getInstance(); + BaseProductCreationForm::buildForm(); + + $this + ->formBuilder + ->add("brand_id", "integer", [ + 'required' => true, + 'label' => $translator->trans('Brand / Supplier'), + 'label_attr' => [ + 'for' => 'mode', + 'help' => $translator->trans("Select the product brand, or supplier."), + ], + ]); + + $this->addStandardDescFields(array('title', 'locale')); + } + + /** + * @return string the name of you form. This name must be unique + */ + public function getName() + { + return ''; + } +} diff --git a/core/lib/Thelia/Form/Api/Product/ProductModificationForm.php b/core/lib/Thelia/Form/Api/Product/ProductModificationForm.php new file mode 100644 index 00000000..97040568 --- /dev/null +++ b/core/lib/Thelia/Form/Api/Product/ProductModificationForm.php @@ -0,0 +1,28 @@ + + */ +class ProductModificationForm extends BaseProductModificationForm +{ + public function getName() + { + return ''; + } +} diff --git a/core/lib/Thelia/Form/Api/ProductSaleElements/ProductSaleElementsForm.php b/core/lib/Thelia/Form/Api/ProductSaleElements/ProductSaleElementsForm.php new file mode 100644 index 00000000..e9bf92a1 --- /dev/null +++ b/core/lib/Thelia/Form/Api/ProductSaleElements/ProductSaleElementsForm.php @@ -0,0 +1,61 @@ + + */ +class ProductSaleElementsForm extends BaseForm +{ + /** + * + * in this function you add all the fields you need for your Form. + * Form this you have to call add method on $this->formBuilder attribute : + * + * $this->formBuilder->add("name", "text") + * ->add("email", "email", array( + * "attr" => array( + * "class" => "field" + * ), + * "label" => "email", + * "constraints" => array( + * new \Symfony\Component\Validator\Constraints\NotBlank() + * ) + * ) + * ) + * ->add('age', 'integer'); + * + * @return null + */ + protected function buildForm() + { + $this->formBuilder + ->add("pse", "collection", array( + "type" => "product_sale_elements", + "allow_add" => true, + "required" => true, + )) + ; + } + + /** + * @return string the name of you form. This name must be unique + */ + public function getName() + { + return ''; + } +} diff --git a/core/lib/Thelia/Form/Area/AreaCountryForm.php b/core/lib/Thelia/Form/Area/AreaCountryForm.php new file mode 100644 index 00000000..bc88cdcd --- /dev/null +++ b/core/lib/Thelia/Form/Area/AreaCountryForm.php @@ -0,0 +1,80 @@ + + */ +class AreaCountryForm extends BaseForm +{ + use CountryListValidationTrait; + + /** + * @inheritdoc + */ + protected function buildForm() + { + $this->formBuilder + ->add( + 'area_id', + 'hidden', + [ + 'constraints' => [ + new GreaterThan(array('value' => 0)), + new NotBlank(), + ] + ] + ) + ->add( + 'country_id', + 'collection', + [ + 'type' => 'text', + 'required' => true, + 'constraints' => [ + new NotBlank(), + new Callback(["methods" => [[$this, "verifyCountryList"]]]) + ], + 'allow_add' => true, + 'allow_delete' => true, + 'label' => Translator::getInstance()->trans('Countries'), + 'label_attr' => [ + 'for' => 'countries-add', + 'help' => Translator::getInstance() + ->trans('Select the countries to include in this shipping zone'), + ], + 'attr' => [ + 'size' => 10, + 'multiple' => true, + ] + ] + ) + ; + } + + /** + * @return string the name of you form. This name must be unique + */ + public function getName() + { + return 'thelia_area_country'; + } +} diff --git a/core/lib/Thelia/Form/Area/AreaCreateForm.php b/core/lib/Thelia/Form/Area/AreaCreateForm.php new file mode 100644 index 00000000..ea95143d --- /dev/null +++ b/core/lib/Thelia/Form/Area/AreaCreateForm.php @@ -0,0 +1,55 @@ + + */ +class AreaCreateForm extends BaseForm +{ + protected function buildForm() + { + $this->formBuilder + ->add( + 'name', + 'text', + [ + 'constraints' => [ + new NotBlank(), + ], + 'label' => Translator::getInstance()->trans('Shipping zone name'), + 'label_attr' => [ + 'for' => 'shipping_name' + ], + 'attr' => [ + 'placeholder' => Translator::getInstance()->trans("A name such as Europe or Overseas"), + ], + ] + ) + ; + } + + /** + * @return string the name of you form. This name must be unique + */ + public function getName() + { + return 'thelia_area_creation'; + } +} diff --git a/core/lib/Thelia/Form/Area/AreaDeleteCountryForm.php b/core/lib/Thelia/Form/Area/AreaDeleteCountryForm.php new file mode 100644 index 00000000..df26949e --- /dev/null +++ b/core/lib/Thelia/Form/Area/AreaDeleteCountryForm.php @@ -0,0 +1,79 @@ + + */ +class AreaDeleteCountryForm extends BaseForm +{ + use CountryListValidationTrait; + + /** + * @inheritdoc + */ + protected function buildForm() + { + $this->formBuilder + ->add( + 'area_id', + 'hidden', + [ + 'required' => true, + + 'constraints' => [ + new GreaterThan(array('value' => 0)), + new NotBlank(), + ] + ] + ) + ->add( + 'country_id', + 'collection', + [ + 'type' => 'text', + 'constraints' => [ + new NotBlank(), + new Callback(["methods" => [[$this, "verifyCountryList"]]]) + ], + 'allow_add' => true, + 'allow_delete' => true, + 'label' => Translator::getInstance()->trans('Countries'), + 'label_attr' => [ + 'for' => 'country_delete_id', + 'help' => Translator::getInstance()->trans( + 'Select the countries to delete from this shipping zone' + ), + ] + ] + ) + ; + } + + + /** + * @return string the name of you form. This name must be unique + */ + public function getName() + { + return 'thelia_area_delete_country'; + } +} diff --git a/core/lib/Thelia/Form/Area/AreaModificationForm.php b/core/lib/Thelia/Form/Area/AreaModificationForm.php new file mode 100644 index 00000000..3d316acb --- /dev/null +++ b/core/lib/Thelia/Form/Area/AreaModificationForm.php @@ -0,0 +1,45 @@ + + */ +class AreaModificationForm extends AreaCreateForm +{ + public function buildForm() + { + parent::buildForm(); + + $this->formBuilder + ->add( + "area_id", + "hidden", + [ + "constraints" => [ + new GreaterThan([ 'value' => 0 ]) + ] + ] + ) + ; + } + + public function getName() + { + return 'thelia_area_modification'; + } +} diff --git a/core/lib/Thelia/Form/Area/AreaPostageForm.php b/core/lib/Thelia/Form/Area/AreaPostageForm.php new file mode 100644 index 00000000..8a8d61e6 --- /dev/null +++ b/core/lib/Thelia/Form/Area/AreaPostageForm.php @@ -0,0 +1,75 @@ + + */ +class AreaPostageForm extends BaseForm +{ + /** + * + * in this function you add all the fields you need for your Form. + * Form this you have to call add method on $this->formBuilder attribute : + * + * $this->formBuilder->add("name", "text") + * ->add("email", "email", array( + * "attr" => array( + * "class" => "field" + * ), + * "label" => "email", + * "constraints" => array( + * new \Symfony\Component\Validator\Constraints\NotBlank() + * ) + * ) + * ) + * ->add('age', 'integer'); + * + * @return null + */ + protected function buildForm() + { + $this->formBuilder + ->add('area_id', 'integer', array( + 'constraints' => array( + new GreaterThan(array('value' => 0)), + new NotBlank(), + ), + )) + ->add('postage', 'number', array( + 'constraints' => array( + new GreaterThanOrEqual(array('value' => 0)), + new NotBlank(), + ), + 'label_attr' => array('for' => 'area_postage'), + 'label' => Translator::getInstance()->trans('Postage'), + )) + ; + } + + /** + * @return string the name of you form. This name must be unique + */ + public function getName() + { + return 'thelia_area_postage'; + } +} diff --git a/core/lib/Thelia/Form/Area/CountryListValidationTrait.php b/core/lib/Thelia/Form/Area/CountryListValidationTrait.php new file mode 100644 index 00000000..d9ed6e19 --- /dev/null +++ b/core/lib/Thelia/Form/Area/CountryListValidationTrait.php @@ -0,0 +1,64 @@ + + */ +trait CountryListValidationTrait +{ + public function verifyCountryList($value, ExecutionContextInterface $context) + { + $countryList = \is_array($value) ? $value : [$value]; + + foreach ($countryList as $countryItem) { + $item = explode('-', $countryItem); + + if (\count($item) == 2) { + $country = CountryQuery::create()->findPk($item[0]); + if (null === $country) { + $context->addViolation( + Translator::getInstance()->trans( + "Country ID %id not found", + ['%id' => $item[0]] + ) + ); + } + + if ($item[1] == "0") { + continue; + } + + $state = StateQuery::create()->findPk($item[1]); + if (null === $state) { + $context->addViolation( + Translator::getInstance()->trans( + "State ID %id not found", + ['%id' => $item[1]] + ) + ); + } + } else { + $context->addViolation(Translator::getInstance()->trans("Wrong country definition")); + } + } + } +} diff --git a/core/lib/Thelia/Form/AttributeAvCreationForm.php b/core/lib/Thelia/Form/AttributeAvCreationForm.php new file mode 100644 index 00000000..24f3d7ab --- /dev/null +++ b/core/lib/Thelia/Form/AttributeAvCreationForm.php @@ -0,0 +1,49 @@ +formBuilder + ->add("title", "text", [ + "constraints" => [ + new NotBlank(), + ], + "label" => Translator::getInstance()->trans("Title *"), + "label_attr" => [ + "for" => "title", + ] + ]) + ->add("locale", "text", [ + "constraints" => [ + new NotBlank(), + ] + ]) + ->add("attribute_id", "hidden", [ + "constraints" => [ + new NotBlank(), + ] + ]); + } + + public function getName() + { + return "thelia_attributeav_creation"; + } +} diff --git a/core/lib/Thelia/Form/AttributeCreationForm.php b/core/lib/Thelia/Form/AttributeCreationForm.php new file mode 100644 index 00000000..9a27ee60 --- /dev/null +++ b/core/lib/Thelia/Form/AttributeCreationForm.php @@ -0,0 +1,50 @@ +formBuilder + ->add("title", "text", [ + "constraints" => [ + new NotBlank(), + ], + "label" => Translator::getInstance()->trans("Title *"), + "label_attr" => [ + "for" => "title", + ] + ]) + ->add("locale", "text", [ + "constraints" => [ + new NotBlank(), + ] + ]) + ->add("add_to_all", "checkbox", [ + "label" => Translator::getInstance()->trans("Add to all product templates"), + "label_attr" => [ + "for" => "add_to_all", + ] + ]); + } + + public function getName() + { + return "thelia_attribute_creation"; + } +} diff --git a/core/lib/Thelia/Form/AttributeModificationForm.php b/core/lib/Thelia/Form/AttributeModificationForm.php new file mode 100644 index 00000000..36e555fc --- /dev/null +++ b/core/lib/Thelia/Form/AttributeModificationForm.php @@ -0,0 +1,42 @@ +formBuilder + ->add("id", "hidden", array( + "constraints" => array( + new GreaterThan( + array('value' => 0) + ), + ), + )) + ; + + // Add standard description fields + $this->addStandardDescFields(); + } + + public function getName() + { + return "thelia_attribute_modification"; + } +} diff --git a/core/lib/Thelia/Form/BaseForm.php b/core/lib/Thelia/Form/BaseForm.php new file mode 100644 index 00000000..9d47e27d --- /dev/null +++ b/core/lib/Thelia/Form/BaseForm.php @@ -0,0 +1,468 @@ + + */ +abstract class BaseForm +{ + /** + * @var \Symfony\Component\Form\FormBuilderInterface + */ + protected $formBuilder; + + /** + * @var \Symfony\Component\Form\FormFactoryBuilderInterface + */ + protected $formFactoryBuilder; + + /** + * @var \Symfony\Component\Form\Form + */ + protected $form; + + /** + * @var ContainerInterface + */ + protected $container; + + /** + * @var Request + */ + protected $request; + + /** + * @var \Symfony\Component\Validator\ValidatorBuilderInterface + */ + protected $validatorBuilder; + + /** + * @var \Symfony\Component\Translation\TranslatorInterface + */ + protected $translator; + + private $view = null; + + /** + * true if the form has an error, false otherwise. + * @var boolean + */ + private $has_error = false; + + /** + * The form error message. + * @var string + */ + private $error_message = ''; + + /** + * @var \Symfony\Component\EventDispatcher\EventDispatcher + */ + protected $dispatcher; + + /** + * @var string + */ + private $type; + + /** + * @var string The form name + */ + private $formUniqueIdentifier; + + /** + * @param Request $request + * @param string $type + * @param array $data + * @param array $options + * @param ContainerInterface $container + * @deprecated Thelia forms should not be instantiated directly. Please use BaseController::createForm() instead + * @see BaseController::createForm() + */ + public function __construct( + Request $request, + $type = "form", + $data = array(), + $options = array(), + ContainerInterface $container = null + ) { + // Generate the form name from the complete class name + $this->formUniqueIdentifier = strtolower(str_replace('\\', '_', \get_class($this))); + + $this->request = $request; + $this->type = $type; + + if (null !== $container) { + $this->container = $container; + $this->dispatcher = $container->get("event_dispatcher"); + + $this->initFormWithContainer($type, $data, $options); + } else { + $this->initFormWithRequest($type, $data, $options); + } + + if (!isset($options["csrf_protection"]) || $options["csrf_protection"] !== false) { + $this->formFactoryBuilder + ->addExtension( + new CsrfExtension( + new CsrfTokenManager(null, new SessionTokenStorage( + $this->getRequest()->getSession() + )) + ) + ) + ; + } + + $this->formBuilder = $this->formFactoryBuilder + ->addExtension(new ValidatorExtension($this->validatorBuilder->getValidator())) + ->getFormFactory() + ->createNamedBuilder($this->getName(), $type, $data, $this->cleanOptions($options)) + ; + + /** + * Build the form + */ + $name = $this->getName(); + + $event = null; + + $dispatchEvents = $this->hasContainer() && $name !== null && $name !== ''; + + // We need to wrap the dispatch with a condition for backward compatibility + if ($dispatchEvents) { + $event = new TheliaFormEvent($this); + + /** + * If the form has the container, disptach the events + */ + $this->dispatcher->dispatch( + TheliaEvents::FORM_BEFORE_BUILD.".".$name, + $event + ); + } + + $this->buildForm(); + + if ($dispatchEvents) { + /** + * If the form has the container, disptach the events + */ + $this->dispatcher->dispatch( + TheliaEvents::FORM_AFTER_BUILD.".".$name, + $event + ); + } + + // If not already set, define the success_url field + // This field is not included in the standard form hidden fields + // This field is not included in the hidden fields generated by form_hidden_fields Smarty function + if (! $this->formBuilder->has('success_url')) { + $this->formBuilder->add("success_url", "hidden"); + } + + // If not already set, define the error_url field + // This field is not included in the standard form hidden fields + // This field is not included in the hidden fields generated by form_hidden_fields Smarty function + if (! $this->formBuilder->has('error_url')) { + $this->formBuilder->add("error_url", "hidden"); + } + + // The "error_message" field defines the error message displayed if + // the form could not be validated. If it is empty, a standard error message is displayed instead. + // This field is not included in the hidden fields generated by form_hidden_fields Smarty function + if (! $this->formBuilder->has('error_message')) { + $this->formBuilder->add("error_message", "hidden"); + } + + $this->form = $this->formBuilder->getForm(); + } + + public function initFormWithContainer($type, $data, $options) + { + /** @var Translator translator */ + $this->translator = $this->container->get("thelia.translator"); + + /** @var FormFactoryBuilderInterface formFactoryBuilder */ + $this->formFactoryBuilder = $this->container->get("thelia.form_factory_builder"); + + /** @var ValidationBuilder validatorBuilder */ + $this->validatorBuilder = $this->container->get("thelia.forms.validator_builder"); + } + + protected function initFormWithRequest($type, $data, $options) + { + $this->validatorBuilder = Validation::createValidatorBuilder(); + + $this->formFactoryBuilder = Forms::createFormFactoryBuilder() + ->addExtension(new HttpFoundationExtension()) + ; + + $this->translator = Translator::getInstance(); + + $this->validatorBuilder + ->setTranslationDomain('validators') + ->setTranslator($this->translator); + } + + /** + * @return \Symfony\Component\Form\FormBuilderInterface + */ + public function getFormBuilder() + { + return $this->formBuilder; + } + + /** + * @return string + */ + public function getType() + { + return $this->type; + } + + /** + * Return true if the given field value is defined only in the HTML template, and its value is defined + * in the template file, not the form builder. + * Thus, it should not be included in the form hidden fields generated by form_hidden_fields + * Smarty function, to prevent it from existing twice in the form. + * + * @param FormView $fieldView + * @return bool + */ + public function isTemplateDefinedHiddenField(FormView $fieldView) + { + return $this->isTemplateDefinedHiddenFieldName($fieldView->vars['name']); + } + + public function isTemplateDefinedHiddenFieldName($fieldName) + { + return $fieldName == 'success_url' || $fieldName == 'error_url' || $fieldName == 'error_message'; + } + + /** + * @return \Thelia\Core\HttpFoundation\Request + */ + public function getRequest() + { + return $this->request; + } + + protected function cleanOptions($options) + { + unset($options["csrf_protection"]); + + return $options; + } + + /** + * Returns the absolute URL to redirect the user to if the form is not successfully processed, + * using the 'error_url' form parameter value + * + * @param string $default the default URL. If not given, the configured base URL is used. + * @return string an absolute URL + */ + public function getErrorUrl($default = null) + { + return $this->getFormDefinedUrl('error_url', $default); + } + + /** + * @return bool true if an error URL is defined in the 'error_url' form parameter, false otherwise + */ + public function hasErrorUrl() + { + return null !== $this->form->get('error_url')->getData(); + } + + /** + * Returns the absolute URL to redirect the user to if the form is successfully processed. + * using the 'success_url' form parameter value + * + * @param string $default the default URL. If not given, the configured base URL is used. + * @return string an absolute URL + */ + public function getSuccessUrl($default = null) + { + return $this->getFormDefinedUrl('success_url', $default); + } + + /** + * @return bool true if a success URL is defined in the form, false otherwise + */ + public function hasSuccessUrl() + { + return null !== $this->form->get('success_url')->getData(); + } + + /** + * Build an absolute URL using the value of a form parameter. + * + * @param string $parameterName the form parameter name + * @param string $default a default value for the form parameter. If not defined, the configured base URL is used. + * @return string an absolute URL + */ + public function getFormDefinedUrl($parameterName, $default = null) + { + $formDefinedUrl = $this->form->get($parameterName)->getData(); + + if (empty($formDefinedUrl)) { + if ($default === null) { + $default = ConfigQuery::read('base_url', '/'); + } + + $formDefinedUrl = $default; + } + + return URL::getInstance()->absoluteUrl($formDefinedUrl); + } + + public function createView() + { + $this->view = $this->form->createView(); + + return $this; + } + + /** + * @return FormView + * @throws \LogicException + */ + public function getView() + { + if ($this->view === null) { + throw new \LogicException("View was not created. Please call BaseForm::createView() first."); + } + + return $this->view; + } + + // -- Error and errro message ---------------------------------------------- + + /** + * Set the error status of the form. + * + * @param boolean $has_error + * @return $this + */ + public function setError($has_error = true) + { + $this->has_error = $has_error; + + return $this; + } + + /** + * Get the cuirrent error status of the form. + * + * @return boolean + */ + public function hasError() + { + return $this->has_error; + } + + /** + * Set the error message related to global form error + * + * @param string $message + * @return $this + */ + public function setErrorMessage($message) + { + $this->setError(true); + $this->error_message = $message; + + return $this; + } + + /** + * Get the form error message. + * + * @return string + */ + public function getErrorMessage() + { + return $this->error_message; + } + + /** + * @return \Symfony\Component\Form\Form + */ + public function getForm() + { + return $this->form; + } + + /** + * @return bool + */ + public function hasContainer() + { + return $this->container !== null; + } + + /** + * Override this method if you don't want to use the standard name, which is created from the full class name. + * + * @return string the name of you form. This name must be unique + */ + public function getName() + { + return $this->formUniqueIdentifier; + } + + /** + * + * in this function you add all the fields you need for your Form. + * Form this you have to call add method on $this->formBuilder attribute : + * + * $this->formBuilder->add("name", "text") + * ->add("email", "email", array( + * "attr" => array( + * "class" => "field" + * ), + * "label" => "email", + * "constraints" => array( + * new \Symfony\Component\Validator\Constraints\NotBlank() + * ) + * ) + * ) + * ->add('age', 'integer'); + * + * @return null + */ + abstract protected function buildForm(); +} diff --git a/core/lib/Thelia/Form/Brand/BrandCreationForm.php b/core/lib/Thelia/Form/Brand/BrandCreationForm.php new file mode 100644 index 00000000..1346f093 --- /dev/null +++ b/core/lib/Thelia/Form/Brand/BrandCreationForm.php @@ -0,0 +1,81 @@ + + */ +class BrandCreationForm extends BaseForm +{ + protected function doBuilForm($titleFieldHelpLabel) + { + $this->formBuilder->add( + 'title', + 'text', + [ + 'constraints' => [ new NotBlank() ], + 'required' => true, + 'label' => Translator::getInstance()->trans('Brand name'), + 'label_attr' => [ + 'for' => 'title', + 'help' => $titleFieldHelpLabel, + ], + 'attr' => [ + 'placeholder' => Translator::getInstance()->trans('The brand name or title'), + ] + ] + ) + ->add( + 'locale', + 'hidden', + [ + 'constraints' => [ new NotBlank() ], + 'required' => true, + ] + ) + // Is this brand online ? + ->add( + 'visible', + 'checkbox', + [ + 'required' => false, + 'label' => Translator::getInstance()->trans('This brand is online'), + 'label_attr' => [ + 'for' => 'visible_create', + ] + ] + ); + } + + protected function buildForm() + { + $this->doBuilForm( + Translator::getInstance()->trans( + 'Enter here the brand name in the default language (%title%)', + [ '%title%' => Lang::getDefaultLanguage()->getTitle()] + ) + ); + } + + public function getName() + { + return 'thelia_brand_creation'; + } +} diff --git a/core/lib/Thelia/Form/Brand/BrandDocumentModification.php b/core/lib/Thelia/Form/Brand/BrandDocumentModification.php new file mode 100644 index 00000000..24f315d1 --- /dev/null +++ b/core/lib/Thelia/Form/Brand/BrandDocumentModification.php @@ -0,0 +1,29 @@ + + */ +class BrandDocumentModification extends DocumentModification +{ + /** + * @inheritdoc + */ + public function getName() + { + return 'thelia_brand_document_modification'; + } +} diff --git a/core/lib/Thelia/Form/Brand/BrandImageModification.php b/core/lib/Thelia/Form/Brand/BrandImageModification.php new file mode 100644 index 00000000..048229a4 --- /dev/null +++ b/core/lib/Thelia/Form/Brand/BrandImageModification.php @@ -0,0 +1,29 @@ + + */ +class BrandImageModification extends ImageModification +{ + /** + * @inheritdoc + */ + public function getName() + { + return 'thelia_brand_image_modification'; + } +} diff --git a/core/lib/Thelia/Form/Brand/BrandModificationForm.php b/core/lib/Thelia/Form/Brand/BrandModificationForm.php new file mode 100644 index 00000000..c6f051d4 --- /dev/null +++ b/core/lib/Thelia/Form/Brand/BrandModificationForm.php @@ -0,0 +1,61 @@ + + */ +class BrandModificationForm extends BrandCreationForm +{ + use StandardDescriptionFieldsTrait; + + protected function buildForm() + { + $this->doBuilForm( + Translator::getInstance()->trans('The brand name or title') + ); + + $this->formBuilder->add( + 'id', + 'hidden', + [ + 'constraints' => [ new GreaterThan(['value' => 0]) ], + 'required' => true, + ] + ) + ->add("logo_image_id", "integer", [ + 'constraints' => [ ], + 'required' => false, + 'label' => Translator::getInstance()->trans('Select the brand logo'), + 'label_attr' => [ + 'for' => 'logo_image_id', + 'help' => Translator::getInstance()->trans("Select the brand logo amongst the brand images"), + ] + ]) + ; + + // Add standard description fields, excluding title and locale, which are already defined + $this->addStandardDescFields(array('title', 'locale')); + } + + public function getName() + { + return "thelia_brand_modification"; + } +} diff --git a/core/lib/Thelia/Form/BruteforceForm.php b/core/lib/Thelia/Form/BruteforceForm.php new file mode 100644 index 00000000..88a744e5 --- /dev/null +++ b/core/lib/Thelia/Form/BruteforceForm.php @@ -0,0 +1,37 @@ + + */ +abstract class BruteforceForm extends FirewallForm +{ + const DEFAULT_TIME_TO_WAIT = 10; // 10 minutes + + const DEFAULT_ATTEMPTS = 10; + + public function getConfigTime() + { + return ConfigQuery::read("form_firewall_bruteforce_time_to_wait", static::DEFAULT_TIME_TO_WAIT); + } + + public function getConfigAttempts() + { + return ConfigQuery::read("form_firewall_bruteforce_attempts", static::DEFAULT_ATTEMPTS); + } +} diff --git a/core/lib/Thelia/Form/Cache/AssetsFlushForm.php b/core/lib/Thelia/Form/Cache/AssetsFlushForm.php new file mode 100644 index 00000000..256c4dc7 --- /dev/null +++ b/core/lib/Thelia/Form/Cache/AssetsFlushForm.php @@ -0,0 +1,39 @@ + + */ +class AssetsFlushForm extends BaseForm +{ + /** + * @inheritdoc + */ + protected function buildForm() + { + //Nothing, we just want CSRF protection + } + + /** + * @inheritdoc + */ + public function getName() + { + return "assets_flush"; + } +} diff --git a/core/lib/Thelia/Form/Cache/CacheFlushForm.php b/core/lib/Thelia/Form/Cache/CacheFlushForm.php new file mode 100644 index 00000000..d768d0ca --- /dev/null +++ b/core/lib/Thelia/Form/Cache/CacheFlushForm.php @@ -0,0 +1,39 @@ + + */ +class CacheFlushForm extends BaseForm +{ + /** + * @inheritdoc + */ + protected function buildForm() + { + //Nothing, we just want CSRF protection + } + + /** + * @inheritdoc + */ + public function getName() + { + return "cache_flush"; + } +} diff --git a/core/lib/Thelia/Form/Cache/ImagesAndDocumentsCacheFlushForm.php b/core/lib/Thelia/Form/Cache/ImagesAndDocumentsCacheFlushForm.php new file mode 100644 index 00000000..d8f70285 --- /dev/null +++ b/core/lib/Thelia/Form/Cache/ImagesAndDocumentsCacheFlushForm.php @@ -0,0 +1,39 @@ + + */ +class ImagesAndDocumentsCacheFlushForm extends BaseForm +{ + /** + * @inheritdoc + */ + protected function buildForm() + { + //Nothing, we just want CSRF protection + } + + /** + * @inheritdoc + */ + public function getName() + { + return "images_and_documents_cache_flush"; + } +} diff --git a/core/lib/Thelia/Form/CartAdd.php b/core/lib/Thelia/Form/CartAdd.php new file mode 100644 index 00000000..cb1e1c52 --- /dev/null +++ b/core/lib/Thelia/Form/CartAdd.php @@ -0,0 +1,148 @@ + + */ +class CartAdd extends BaseForm +{ + /** + * + * in this function you add all the fields you need for your Form. + * Form this you have to call add method on $this->formBuilder attribute : + * + * $this->formBuilder->add("name", "text") + * ->add("email", "email", array( + * "attr" => array( + * "class" => "field" + * ), + * "label" => "email", + * "constraints" => array( + * new \Symfony\Component\Validator\Constraints\NotBlank() + * ) + * ) + * ) + * ->add('age', 'integer'); + * + * @return null + */ + protected function buildForm() + { + $this->formBuilder + ->add("product", "text", array( + "constraints" => array( + new Constraints\NotBlank(), + new Constraints\Callback(array("methods" => array( + array($this, "checkProduct"), + ))), + ), + "label" => "product", + "label_attr" => array( + "for" => "cart_product", + ), + )) + ->add("product_sale_elements_id", "text", array( + "constraints" => array( + new Constraints\NotBlank(), + new Constraints\Callback(array("methods" => array( + array($this, "checkStockAvailability"), + ))), + ), + "required" => true, + + )) + ->add("quantity", "number", array( + "constraints" => array( + new Constraints\NotBlank(), + new Constraints\Callback(array("methods" => array( + array($this, "checkStock"), + ))), + new Constraints\GreaterThanOrEqual(array( + "value" => 0, + )), + ), + "label" => Translator::getInstance()->trans("Quantity"), + "label_attr" => array( + "for" => "quantity", + ), + )) + ->add("append", "integer") + ->add("newness", "integer") + ; + } + + public function checkProduct($value, ExecutionContextInterface $context) + { + $product = ProductQuery::create()->findPk($value); + + if (\is_null($product) || $product->getVisible() == 0) { + throw new ProductNotFoundException(sprintf(Translator::getInstance()->trans("this product id does not exists : %d"), $value)); + } + } + + public function checkStockAvailability($value, ExecutionContextInterface $context) + { + if ($value) { + $data = $context->getRoot()->getData(); + + $productSaleElements = ProductSaleElementsQuery::create() + ->filterById($value) + ->filterByProductId($data["product"]) + ->count(); + + if ($productSaleElements == 0) { + throw new StockNotFoundException(sprintf(Translator::getInstance()->trans("This product_sale_elements_id does not exists for this product : %d"), $value)); + } + } + } + + public function checkStock($value, ExecutionContextInterface $context) + { + $data = $context->getRoot()->getData(); + + if (null === $data["product_sale_elements_id"]) { + $context->buildViolation(Translator::getInstance()->trans("Invalid product_sale_elements")); + } else { + $productSaleElements = ProductSaleElementsQuery::create() + ->filterById($data["product_sale_elements_id"]) + ->filterByProductId($data["product"]) + ->findOne(); + + $product = $productSaleElements->getProduct(); + + if ($productSaleElements->getQuantity() < $value && $product->getVirtual() === 0 && ConfigQuery::checkAvailableStock()) { + $context->addViolation(Translator::getInstance()->trans("quantity value is not valid")); + } + } + } + + /** + * @return string the name of you form. This name must be unique + */ + public function getName() + { + return "thelia_cart_add"; + } +} diff --git a/core/lib/Thelia/Form/CategoryCreationForm.php b/core/lib/Thelia/Form/CategoryCreationForm.php new file mode 100644 index 00000000..412cc20e --- /dev/null +++ b/core/lib/Thelia/Form/CategoryCreationForm.php @@ -0,0 +1,77 @@ +formBuilder + ->add( + 'title', + 'text', + [ + 'constraints' => [ new NotBlank() ], + 'label' => $this->translator->trans('Category title'), + 'label_attr' => [ + 'help' => $titleHelpText + ] + ] + ) + ->add( + 'parent', + 'integer', + [ + 'label' => $this->translator->trans('Parent category'), + 'constraints' => [ new NotBlank() ], + 'label_attr' => [ + 'help' => $this->translator->trans('Select the parent category of this category.'), + ] + ] + ) + ->add( + 'locale', + 'hidden', + [ + 'constraints' => [ new NotBlank() ], + ] + ) + ->add( + 'visible', + 'integer', // Should be checkbox, but this is not API compatible, see #1199 + [ + 'required' => false, + 'label' => $this->translator->trans('This category is online') + ] + ) + ; + } + + protected function buildForm() + { + $this->doBuilForm( + $this->translator->trans( + 'Enter here the category title in the default language (%title%)', + [ '%title%' => Lang::getDefaultLanguage()->getTitle()] + ) + ); + } + + public function getName() + { + return "thelia_category_creation"; + } +} diff --git a/core/lib/Thelia/Form/CategoryDocumentModification.php b/core/lib/Thelia/Form/CategoryDocumentModification.php new file mode 100644 index 00000000..4bf035bf --- /dev/null +++ b/core/lib/Thelia/Form/CategoryDocumentModification.php @@ -0,0 +1,40 @@ + + * + */ +class CategoryDocumentModification extends DocumentModification +{ + /** + * Get form name + * This name must be unique + * + * @return string + */ + public function getName() + { + return 'thelia_category_document_modification'; + } +} diff --git a/core/lib/Thelia/Form/CategoryImageModification.php b/core/lib/Thelia/Form/CategoryImageModification.php new file mode 100644 index 00000000..c29f211f --- /dev/null +++ b/core/lib/Thelia/Form/CategoryImageModification.php @@ -0,0 +1,40 @@ + + * + */ +class CategoryImageModification extends ImageModification +{ + /** + * Get form name + * This name must be unique + * + * @return string + */ + public function getName() + { + return 'thelia_category_image_modification'; + } +} diff --git a/core/lib/Thelia/Form/CategoryModificationForm.php b/core/lib/Thelia/Form/CategoryModificationForm.php new file mode 100644 index 00000000..96204b89 --- /dev/null +++ b/core/lib/Thelia/Form/CategoryModificationForm.php @@ -0,0 +1,79 @@ +doBuilForm( + $this->translator->trans('The category title') + ); + + // Create countries and shipping modules list + $templateList = [0 => ' ']; + + $list = TemplateQuery::create()->find(); + + // Get the current edition locale + $locale = $this->getRequest()->getSession()->getAdminEditionLang()->getLocale(); + + /** @var \Thelia\Model\Template $item */ + foreach ($list as $item) { + $templateList[$item->getId()] = $item->setLocale($locale)->getName(); + } + + asort($templateList); + + $templateList[0] = $this->translator->trans("None"); + + $this->formBuilder + ->add( + 'id', + 'hidden', + [ + 'constraints' => [ new GreaterThan(array('value' => 0)) ] + ] + ) + ->add( + 'default_template_id', + 'choice', + [ + 'choices' => $templateList, + 'label' => $this->translator->trans('Default product template'), + 'label_attr' => [ + 'for' => 'price_offset_type', + 'help' => $this->translator->trans( + 'Select a default template for new products created in this category' + ) + ], + 'attr' => [ + ] + ] + ) + ; + + // Add standard description fields, excluding title which is defined in parent class + $this->addStandardDescFields([ 'title' ]); + } + + public function getName() + { + return "thelia_category_modification"; + } +} diff --git a/core/lib/Thelia/Form/ConfigCreationForm.php b/core/lib/Thelia/Form/ConfigCreationForm.php new file mode 100644 index 00000000..e2c60b63 --- /dev/null +++ b/core/lib/Thelia/Form/ConfigCreationForm.php @@ -0,0 +1,77 @@ +formBuilder + ->add("name", "text", array( + "constraints" => array( + new Constraints\NotBlank(), + new Constraints\Callback(array( + "methods" => array(array($this, "checkDuplicateName")), + )) + ), + "label" => Translator::getInstance()->trans('Name *'), + "label_attr" => array( + "for" => "name", + ), + )) + ->add("title", "text", array( + "constraints" => array( + new Constraints\NotBlank(), + ), + "label" => Translator::getInstance()->trans('Purpose *'), + "label_attr" => array( + "for" => "purpose", + ), + )) + ->add("locale", "hidden", array( + "constraints" => array( + new Constraints\NotBlank(), + ), + )) + ->add("value", "text", array( + "label" => Translator::getInstance()->trans('Value *'), + "label_attr" => array( + "for" => "value", + ), + )) + ->add("hidden", "hidden", array()) + ->add("secured", "hidden", array( + "label" => Translator::getInstance()->trans('Prevent variable modification or deletion, except for super-admin'), + )) + ; + } + + public function getName() + { + return "thelia_config_creation"; + } + + public function checkDuplicateName($value, ExecutionContextInterface $context) + { + $config = ConfigQuery::create()->findOneByName($value); + + if ($config) { + $context->addViolation(Translator::getInstance()->trans('A variable with name "%name" already exists.', array('%name' => $value))); + } + } +} diff --git a/core/lib/Thelia/Form/ConfigModificationForm.php b/core/lib/Thelia/Form/ConfigModificationForm.php new file mode 100644 index 00000000..37a9d99d --- /dev/null +++ b/core/lib/Thelia/Form/ConfigModificationForm.php @@ -0,0 +1,62 @@ +formBuilder + ->add("id", "hidden", array( + "constraints" => array( + new GreaterThan( + array('value' => 0) + ), + ), + )) + ->add("name", "text", array( + "constraints" => array( + new NotBlank(), + ), + "label" => Translator::getInstance()->trans('Name'), + "label_attr" => array( + "for" => "name", + ), + )) + ->add("value", "text", array( + "label" => Translator::getInstance()->trans('Value'), + "label_attr" => array( + "for" => "value", + ), + )) + ->add("hidden", "hidden", array()) + ->add("secured", "hidden", array( + "label" => Translator::getInstance()->trans('Prevent variable modification or deletion, except for super-admin'), + )) + ; + + // Add standard description fields + $this->addStandardDescFields(); + } + + public function getName() + { + return "thelia_config_modification"; + } +} diff --git a/core/lib/Thelia/Form/ConfigStoreForm.php b/core/lib/Thelia/Form/ConfigStoreForm.php new file mode 100644 index 00000000..f8db9391 --- /dev/null +++ b/core/lib/Thelia/Form/ConfigStoreForm.php @@ -0,0 +1,270 @@ +formBuilder + ->add( + 'store_name', + 'text', + [ + 'data' => ConfigQuery::getStoreName(), + 'constraints' => [new Constraints\NotBlank()], + 'label' => $tr->trans('Store name'), + 'attr' => [ + 'placeholder' => $tr->trans('Used in your store front'), + ] + ] + ) + ->add( + 'store_description', + 'text', + [ + 'data' => ConfigQuery::getStoreDescription(), + 'required' => false, + 'label' => $tr->trans('Store description'), + 'attr' => [ + 'placeholder' => $tr->trans('Used in your store front'), + ] + ] + ) + ->add( + 'store_email', + 'text', + [ + 'data' => ConfigQuery::getStoreEmail(), + 'constraints' => [ + new Constraints\NotBlank(), + new Constraints\Email(), + ], + 'label' => $tr->trans('Store email address'), + 'attr' => [ + 'placeholder' => $tr->trans('Contact and sender email address'), + ], + 'label_attr' => [ + 'help' => $tr->trans('This is the contact email address, and the sender email of all e-mails sent by your store.'), + ] + ] + ) + ->add( + 'store_notification_emails', + 'text', + [ + 'data' => ConfigQuery::read('store_notification_emails'), + 'constraints' => [ + new Constraints\NotBlank(), + new Constraints\Callback([ + 'methods' => [ + [$this, 'checkEmailList'], + ], + ]), + ], + 'label' => $tr->trans('Email addresses of notification recipients'), + 'attr' => [ + 'placeholder' => $tr->trans('A comma separated list of email addresses'), + ], + 'label_attr' => [ + 'help' => $tr->trans('This is a comma separated list of email addresses where store notifications (such as order placed) are sent.'), + ] + ] + ) + ->add( + 'store_business_id', + 'text', + [ + 'data' => ConfigQuery::read('store_business_id'), + 'label' => $tr->trans('Business ID'), + 'required' => false, + 'attr' => [ + 'placeholder' => $tr->trans('Store Business Identification Number (SIRET, etc).'), + ] + ] + ) + ->add( + 'store_phone', + 'text', + [ + 'data' => ConfigQuery::read('store_phone'), + 'label' => $tr->trans('Phone'), + 'required' => false, + 'attr' => [ + 'placeholder' => $tr->trans('The store phone number.'), + ] + ] + ) + ->add( + 'store_fax', + 'text', + [ + 'data' => ConfigQuery::read('store_fax'), + 'label' => $tr->trans('Fax'), + 'required' => false, + 'attr' => [ + 'placeholder' => $tr->trans('The store fax number.'), + ] + ] + ) + ->add( + 'store_address1', + 'text', + [ + 'data' => ConfigQuery::read('store_address1'), + 'constraints' => [ + new Constraints\NotBlank(), + ], + 'label' => $tr->trans('Street Address'), + 'attr' => [ + 'placeholder' => $tr->trans('Address.'), + ] + ] + ) + ->add( + 'store_address2', + 'text', + [ + 'data' => ConfigQuery::read('store_address2'), + 'required' => false, + 'attr' => [ + 'placeholder' => $tr->trans('Additional address information'), + ] + ] + ) + ->add( + 'store_address3', + 'text', + [ + 'data' => ConfigQuery::read('store_address3'), + 'required' => false, + 'attr' => [ + 'placeholder' => $tr->trans('Additional address information'), + ] + ] + ) + ->add( + 'store_zipcode', + 'text', + [ + 'data' => ConfigQuery::read('store_zipcode'), + 'constraints' => [ + new Constraints\NotBlank(), + ], + 'label' => $tr->trans('Zip code'), + 'attr' => [ + 'placeholder' => $tr->trans('Zip code'), + ] + ] + ) + ->add( + 'store_city', + 'text', + [ + 'data' => ConfigQuery::read('store_city'), + 'constraints' => [ + new Constraints\NotBlank(), + ], + 'label' => $tr->trans('City'), + 'attr' => [ + 'placeholder' => $tr->trans('City'), + ] + ] + ) + ->add( + 'store_country', + 'integer', + [ + 'data' => ConfigQuery::read('store_country'), + 'constraints' => [ + new Constraints\NotBlank(), + ], + 'label' => $tr->trans('Country'), + 'attr' => [ + 'placeholder' => $tr->trans('Country'), + ] + ] + ) + ->add( + 'favicon_file', + 'file', + [ + 'required' => false, + 'constraints' => [ + new Constraints\Image(array( + 'mimeTypes' => ['image/png', 'image/x-icon'] + )) + ], + 'label' => $tr->trans('Favicon image'), + 'label_attr' => [ + 'for' => 'favicon_file', + 'help' => $tr->trans('Icon of the website. Only PNG and ICO files are allowed.'), + ] + ] + ) + ->add( + 'logo_file', + 'file', + [ + 'required' => false, + 'constraints' => [ + new Constraints\Image() + ], + 'label' => $tr->trans('Store logo'), + 'label_attr' => [ + 'for' => 'logo_file' + ] + ] + ) + ->add( + 'banner_file', + 'file', + [ + 'required' => false, + 'constraints' => [ + new Constraints\Image() + ], + 'label' => $tr->trans('Banner'), + 'label_attr' => [ + 'for' => 'banner_file', + 'help' => $tr->trans('Banner of the website. Used in the e-mails send to the customers.'), + ] + ] + ); + } + + public function checkEmailList($value, ExecutionContextInterface $context) + { + $list = preg_split('/[,;]/', $value); + + $emailValidator = new Constraints\Email(); + + foreach ($list as $email) { + $email = trim($email); + + $context->getValidator()->validate($email, $emailValidator); + } + } + + public function getName() + { + return 'thelia_configuration_store'; + } +} diff --git a/core/lib/Thelia/Form/ContactForm.php b/core/lib/Thelia/Form/ContactForm.php new file mode 100644 index 00000000..8ae59c42 --- /dev/null +++ b/core/lib/Thelia/Form/ContactForm.php @@ -0,0 +1,97 @@ + + */ +class ContactForm extends FirewallForm +{ + /** + * + * in this function you add all the fields you need for your Form. + * Form this you have to call add method on $this->formBuilder attribute : + * + * $this->formBuilder->add("name", "text") + * ->add("email", "email", array( + * "attr" => array( + * "class" => "field" + * ), + * "label" => "email", + * "constraints" => array( + * new \Symfony\Component\Validator\Constraints\NotBlank() + * ) + * ) + * ) + * ->add('age', 'integer'); + * + * @return null + */ + protected function buildForm() + { + $this->formBuilder + ->add('name', 'text', array( + 'constraints' => array( + new NotBlank(), + ), + 'label' => Translator::getInstance()->trans('Full Name'), + 'label_attr' => array( + 'for' => 'name_contact', + ), + )) + ->add('email', 'email', array( + 'constraints' => array( + new NotBlank(), + new Email(), + ), + 'label' => Translator::getInstance()->trans('Your Email Address'), + 'label_attr' => array( + 'for' => 'email_contact', + ), + )) + ->add('subject', 'text', array( + 'constraints' => array( + new NotBlank(), + ), + 'label' => Translator::getInstance()->trans('Subject'), + 'label_attr' => array( + 'for' => 'subject_contact', + ), + )) + ->add('message', 'text', array( + 'constraints' => array( + new NotBlank(), + ), + 'label' => Translator::getInstance()->trans('Your Message'), + 'label_attr' => array( + 'for' => 'message_contact', + ), + + )) + ; + } + + /** + * @return string the name of you form. This name must be unique + */ + public function getName() + { + return 'thelia_contact'; + } +} diff --git a/core/lib/Thelia/Form/ContentCreationForm.php b/core/lib/Thelia/Form/ContentCreationForm.php new file mode 100644 index 00000000..3dd24d38 --- /dev/null +++ b/core/lib/Thelia/Form/ContentCreationForm.php @@ -0,0 +1,55 @@ +formBuilder + ->add("title", "text", array( + "constraints" => array( + new NotBlank(), + ), + "label" => Translator::getInstance()->trans('Content title *'), + "label_attr" => array( + "for" => "title", + ), + )) + ->add("default_folder", "integer", array( + "label" => Translator::getInstance()->trans("Default folder *"), + "constraints" => array( + new NotBlank(), + ), + "label_attr" => array("for" => "default_folder"), + )) + ->add("locale", "text", array( + "constraints" => array( + new NotBlank(), + ), + )) + ->add("visible", "integer", array( + "label" => Translator::getInstance()->trans("This content is online."), + "label_attr" => array("for" => "visible_create"), + )) + ; + } + + public function getName() + { + return "thelia_content_creation"; + } +} diff --git a/core/lib/Thelia/Form/ContentDocumentModification.php b/core/lib/Thelia/Form/ContentDocumentModification.php new file mode 100644 index 00000000..6ba8a2ea --- /dev/null +++ b/core/lib/Thelia/Form/ContentDocumentModification.php @@ -0,0 +1,40 @@ + + * + */ +class ContentDocumentModification extends DocumentModification +{ + /** + * Get form name + * This name must be unique + * + * @return string + */ + public function getName() + { + return 'thelia_content_document_modification'; + } +} diff --git a/core/lib/Thelia/Form/ContentImageModification.php b/core/lib/Thelia/Form/ContentImageModification.php new file mode 100644 index 00000000..6be49e42 --- /dev/null +++ b/core/lib/Thelia/Form/ContentImageModification.php @@ -0,0 +1,40 @@ + + * + */ +class ContentImageModification extends ImageModification +{ + /** + * Get form name + * This name must be unique + * + * @return string + */ + public function getName() + { + return 'thelia_content_image_modification'; + } +} diff --git a/core/lib/Thelia/Form/ContentModificationForm.php b/core/lib/Thelia/Form/ContentModificationForm.php new file mode 100644 index 00000000..66a98ea7 --- /dev/null +++ b/core/lib/Thelia/Form/ContentModificationForm.php @@ -0,0 +1,42 @@ + + */ +class ContentModificationForm extends ContentCreationForm +{ + use StandardDescriptionFieldsTrait; + + protected function buildForm() + { + parent::buildForm(); + + $this->formBuilder + ->add("id", "hidden", array("constraints" => array(new GreaterThan(array('value' => 0))))) + ; + + // Add standard description fields, excluding title and locale, which a re defined in parent class + $this->addStandardDescFields(array('title', 'locale')); + } + + public function getName() + { + return "thelia_content_modification"; + } +} diff --git a/core/lib/Thelia/Form/CountryCreationForm.php b/core/lib/Thelia/Form/CountryCreationForm.php new file mode 100644 index 00000000..4e9901d5 --- /dev/null +++ b/core/lib/Thelia/Form/CountryCreationForm.php @@ -0,0 +1,109 @@ +formBuilder + ->add( + 'title', + 'text', + [ + 'constraints' => [ + new NotBlank(), + ], + 'label' => $this->translator->trans('Country title') + ] + ) + ->add( + 'locale', + 'hidden', + [ + 'constraints' => [ + new NotBlank(), + ], + ] + ) + ->add( + 'visible', + 'checkbox', + [ + 'required' => false, + 'label' => $this->translator->trans('This country is online'), + 'label_attr' => [ + 'for' => 'visible_create', + ] + ] + ) + ->add( + 'isocode', + 'text', + [ + 'constraints' => [ + new NotBlank(), + ], + 'label' => $this->translator->trans('Numerical ISO Code'), + 'label_attr' => [ + 'help' => $this->translator->trans('Check country iso codes here.') + ], + ] + ) + ->add( + 'isoalpha2', + 'text', + [ + 'constraints' => [ + new NotBlank(), + ], + 'label' => $this->translator->trans('ISO Alpha-2 code'), + 'label_attr' => [ + 'help' => $this->translator->trans('Check country iso codes here.') + ], + ] + ) + ->add( + 'isoalpha3', + 'text', + [ + 'constraints' => [ + new NotBlank(), + ], + 'label' => $this->translator->trans('ISO Alpha-3 code'), + 'label_attr' => [ + 'help' => $this->translator->trans('Check country iso codes here.') + ], + ] + ) + ->add( + 'has_states', + 'checkbox', + [ + 'required' => false, + 'label' => $this->translator->trans('This country has states / provinces'), + 'label_attr' => [ + 'for' => 'has_states_create', + ] + ] + ) + ; + } + + public function getName() + { + return "thelia_country_creation"; + } +} diff --git a/core/lib/Thelia/Form/CountryModificationForm.php b/core/lib/Thelia/Form/CountryModificationForm.php new file mode 100644 index 00000000..40554846 --- /dev/null +++ b/core/lib/Thelia/Form/CountryModificationForm.php @@ -0,0 +1,62 @@ +formBuilder + ->add('id', 'hidden', ['constraints' => [new GreaterThan(['value' => 0])]]) + ->add( + 'need_zip_code', + 'checkbox', + [ + 'required' => false, + 'label' => $this->translator->trans('Addresses for this country need a zip code'), + 'label_attr' => [ + 'for' => 'need_zip_code', + ], + ] + ) + ->add( + 'zip_code_format', + 'text', + [ + 'required' => false, + 'constraints' => [], + 'label' => $this->translator->trans('The zip code format'), + 'label_attr' => [ + 'help' => $this->translator->trans( + 'Use a N for a number, L for Letter, C for an iso code for the state.' + ) + ], + ] + ) + ; + + // Add standard description fields, excluding title and locale, which a re defined in parent class + $this->addStandardDescFields(['title', 'locale']); + } + + public function getName() + { + return "thelia_country_modification"; + } +} diff --git a/core/lib/Thelia/Form/CouponCode.php b/core/lib/Thelia/Form/CouponCode.php new file mode 100644 index 00000000..6a8cdbc6 --- /dev/null +++ b/core/lib/Thelia/Form/CouponCode.php @@ -0,0 +1,75 @@ + + */ +class CouponCode extends BaseForm +{ + /** + * Build form + */ + protected function buildForm() + { + $this->formBuilder + ->add( + "coupon-code", + "text", + [ + "required" => true, + "constraints" => [ + new Constraints\NotBlank(), + new Constraints\Callback([ + "methods" => [ + [$this, "verifyExistingCode"], + ], + ]), + ] + ] + ) + ; + } + + public function verifyExistingCode($value, ExecutionContextInterface $context) + { + $coupon = CouponQuery::create() + ->filterByCode($value, Criteria::EQUAL) + ->findOne(); + + if (null === $coupon) { + $context->addViolation(Translator::getInstance()->trans("This coupon does not exists")); + } + } + + /** + * Form name + * + * @return string + */ + public function getName() + { + return "thelia_coupon_code"; + } +} diff --git a/core/lib/Thelia/Form/CouponCreationForm.php b/core/lib/Thelia/Form/CouponCreationForm.php new file mode 100644 index 00000000..0d18c1aa --- /dev/null +++ b/core/lib/Thelia/Form/CouponCreationForm.php @@ -0,0 +1,346 @@ + + * + */ +class CouponCreationForm extends BaseForm +{ + const COUPON_CREATION_FORM_NAME = 'thelia_coupon_creation'; + + public function __construct( + Request $request, + $type = "form", + $data = array(), + $options = array(), + ContainerInterface $container = null + ) { + $this->data = $data; + + parent::__construct($request, $type, $data, $options, $container); // TODO: Change the autogenerated stub + } + + /** + * Build Coupon form + * + * @return void + */ + protected function buildForm() + { + // Create countries and shipping modules list + $countries = [0 => ' ']; + + $list = CountryQuery::create()->find(); + + /** @var \Thelia\Model\Country $item */ + foreach ($list as $item) { + $countries[$item->getId()] = $item->getTitle(); + } + + asort($countries); + + $countries[0] = Translator::getInstance()->trans("All countries"); + + $modules = [0 => ' ']; + + $list = ModuleQuery::create()->filterByActivate(BaseModule::IS_ACTIVATED)->filterByType(BaseModule::DELIVERY_MODULE_TYPE)->find(); + + /** @var Module $item */ + foreach ($list as $item) { + $modules[$item->getId()] = $item->getTitle(); + } + + asort($modules); + + $modules[0] = Translator::getInstance()->trans("All shipping methods"); + + $this->formBuilder + ->add( + 'code', + 'text', + [ + 'constraints' => [ + new NotBlank(), + new Callback( + [ + "methods" => [ + [$this, "checkDuplicateCouponCode"], + ], + "groups" => "creation", + ] + ), + new Callback( + [ + "methods" => [ + [$this, "checkCouponCodeChangedAndDoesntExists"], + ], + "groups" => "update", + ] + ), + ] + ] + ) + ->add( + 'title', + 'text', + [ + 'constraints' => [ + new NotBlank(), + ] + ] + ) + ->add( + 'shortDescription', + 'text' + ) + ->add( + 'description', + 'textarea' + ) + ->add( + 'type', + 'text', + [ + 'constraints' => [ + new NotBlank(), + new NotEqualTo( + [ + 'value' => -1, + ] + ), + ] + ] + ) + ->add( + 'isEnabled', + 'text', + [] + ) + ->add( + 'startDate', + 'text', + [ + 'constraints' => [ + new Callback( + [ + "methods" => [ + [$this, "checkLocalizedDate"], + ], + ] + ), + ] + ] + ) + ->add( + 'expirationDate', + 'text', + [ + 'constraints' => [ + new NotBlank(), + new Callback( + [ + "methods" => [ + [$this, "checkLocalizedDate"], + [$this, "checkConsistencyDates"], + ], + ] + ), + ] + ] + ) + ->add( + 'isCumulative', + 'text', + [] + ) + ->add( + 'isRemovingPostage', + 'text', + [] + ) + ->add( + 'freeShippingForCountries', + 'choice', + [ + 'multiple' => true, + 'choices' => $countries + ] + ) + ->add( + 'freeShippingForModules', + 'choice', + [ + 'multiple' => true, + 'choices' => $modules + ] + ) + ->add( + 'isAvailableOnSpecialOffers', + 'text', + [] + ) + ->add( + 'maxUsage', + 'text', + [ + 'constraints' => [ + new NotBlank(), + new GreaterThanOrEqual(['value' => -1]), + ] + ] + ) + ->add( + 'perCustomerUsageCount', + 'choice', + [ + 'multiple' => false, + 'required' => true, + 'choices' => [ + 1 => Translator::getInstance()->trans('Per customer'), + 0 => Translator::getInstance()->trans('Overall'), + ] + ] + ) + ->add( + 'locale', + 'hidden', + [ + 'constraints' => [ + new NotBlank(), + ] + ] + ) + ->add( + 'coupon_specific', + 'collection', + [ + 'allow_add' => true, + 'allow_delete' => true, + ] + ) + ; + } + + /** + * Check coupon code unicity + * + * @param string $value + * @param ExecutionContextInterface $context + */ + public function checkDuplicateCouponCode($value, ExecutionContextInterface $context) + { + $exists = CouponQuery::create()->filterByCode($value)->count() > 0; + + if ($exists) { + $context->addViolation( + Translator::getInstance()->trans( + "The coupon code '%code' already exists. Please choose another coupon code", + ['%code' => $value] + ) + ); + } + } + + public function checkCouponCodeChangedAndDoesntExists($value, ExecutionContextInterface $context) + { + $changed = isset($this->data["code"]) && $this->data["code"] !== $value; + $exists = CouponQuery::create()->filterByCode($value)->count() > 0; + + if ($changed && $exists) { + $context->addViolation( + Translator::getInstance()->trans( + "The coupon code '%code' already exist. Please choose another coupon code", + ['%code' => $value] + ) + ); + } + } + + /** + * Validate a date entered with the default Language date format. + * + * @param string $value + * @param ExecutionContextInterface $context + */ + public function checkLocalizedDate($value, ExecutionContextInterface $context) + { + $format = LangQuery::create()->findOneByByDefault(true)->getDatetimeFormat(); + + if (false === \DateTime::createFromFormat($format, $value)) { + $context->addViolation( + Translator::getInstance()->trans( + "Date '%date' is invalid, please enter a valid date using %fmt format", + [ + '%fmt' => $format, + '%date' => $value + ] + ) + ); + } + } + + /** + * @param $value + * @param ExecutionContextInterface $context + */ + public function checkConsistencyDates($value, ExecutionContextInterface $context) + { + if (null === $startDate = $this->getForm()->get('startDate')->getData()) { + return; + } + + $format = LangQuery::create()->findOneByByDefault(true)->getDatetimeFormat(); + + $startDate = \DateTime::createFromFormat($format, $startDate); + $expirationDate = \DateTime::createFromFormat($format, $value); + + if ($startDate <= $expirationDate) { + return; + } + + $context->addViolation( + Translator::getInstance()->trans("Start date and expiration date are inconsistent") + ); + } + + /** + * Get form name + * + * @return string + */ + public function getName() + { + return self::COUPON_CREATION_FORM_NAME; + } +} diff --git a/core/lib/Thelia/Form/CurrencyCreationForm.php b/core/lib/Thelia/Form/CurrencyCreationForm.php new file mode 100644 index 00000000..14cf8d38 --- /dev/null +++ b/core/lib/Thelia/Form/CurrencyCreationForm.php @@ -0,0 +1,130 @@ +findOneByByDefault(true); + + $this->formBuilder + ->add("name", "text", [ + "required" => true, + "constraints" => [ + new NotBlank(), + ], + "label" => $this->translator->trans('Name'), + "label_attr" => [ + "for" => "name", + "help" => " " + ], + "attr" => [ + "placeholder" => $this->translator->trans('Currency name') + ] + ]) + ->add("locale", "text", [ + "required" => true, + "constraints" => [ + new NotBlank(), + ] + ]) + ->add("symbol", "text", [ + "required" => true, + "constraints" => [ + new NotBlank(), + ], + "label" => $this->translator->trans('Symbol'), + "label_attr" => [ + "for" => "symbol", + "help" => $this->translator->trans('The symbol, such as $, £, €...'), + ], + "attr" => [ + "placeholder" => $this->translator->trans('Symbol'), + ] + ]) + ->add("format", "text", [ + "required" => true, + "constraints" => [ + new NotBlank(), + ], + "label" => $this->translator->trans('Format'), + "label_attr" => [ + "for" => "format", + "help" => $this->translator->trans("%n for number, %c for the currency code, %s for the currency symbol") + ], + "attr" => [ + "placeholder" => "%n" + ] + ]) + ->add("rate", "text", [ + "required" => true, + "constraints" => [ + new NotBlank(), + ], + "label" => $this->translator->trans( + 'Rate from %currencyCode', + ['%currencyCode' => $defaultCurrency->getCode()] + ), + "label_attr" => [ + "for" => "rate", + "help" => $this->translator->trans( + "The rate from %currencyCode: Price in %currencyCode x rate = Price in this currency", + ["%currencyCode" => $defaultCurrency->getCode()] + ), + ], + "attr" => [ + "placeholder" => $this->translator->trans('Rate'), + ] + ]) + ->add("code", "text", [ + "required" => true, + "constraints" => [ + new NotBlank(), + ], + "label" => $this->translator->trans('ISO 4217 code'), + "label_attr" => [ + "for" => "iso_4217_code", + "help" => $this->translator->trans('More information about ISO 4217'), + ], + "attr" => [ + "placeholder" => $this->translator->trans('Code') + ] + ]) + ; + } + + public function getName() + { + return "thelia_currency_creation"; + } + + public function checkDuplicateCode($value, ExecutionContextInterface $context) + { + $currency = CurrencyQuery::create()->findOneByCode($value); + + if ($currency) { + $context->addViolation( + Translator::getInstance()->trans( + 'A currency with code "%name" already exists.', + ['%name' => $value] + ) + ); + } + } +} diff --git a/core/lib/Thelia/Form/CurrencyModificationForm.php b/core/lib/Thelia/Form/CurrencyModificationForm.php new file mode 100644 index 00000000..14b80cb0 --- /dev/null +++ b/core/lib/Thelia/Form/CurrencyModificationForm.php @@ -0,0 +1,32 @@ +formBuilder + ->add("id", "hidden", array("constraints" => array(new GreaterThan(array('value' => 0))))) + ; + } + + public function getName() + { + return "thelia_currency_modification"; + } +} diff --git a/core/lib/Thelia/Form/CustomerCreateForm.php b/core/lib/Thelia/Form/CustomerCreateForm.php new file mode 100644 index 00000000..9e0c6124 --- /dev/null +++ b/core/lib/Thelia/Form/CustomerCreateForm.php @@ -0,0 +1,145 @@ + + */ +class CustomerCreateForm extends AddressCreateForm +{ + protected function buildForm() + { + parent::buildForm(); + + $this->formBuilder + // Remove From Address create form + ->remove("label") + ->remove("is_default") + + // Add + ->add("auto_login", "integer") + // Add Email address + ->add("email", "email", array( + "constraints" => array( + new Constraints\NotBlank(), + new Constraints\Email(), + new Constraints\Callback(array( + "methods" => array( + array($this, + "verifyExistingEmail", ), + ), + )), + ), + "label" => Translator::getInstance()->trans("Email Address"), + "label_attr" => array( + "for" => "email", + ), + )) + // Add Login Information + ->add("password", "password", array( + "constraints" => array( + new Constraints\NotBlank(), + new Constraints\Length(array("min" => ConfigQuery::read("password.length", 4))), + ), + "label" => Translator::getInstance()->trans("Password"), + "label_attr" => array( + "for" => "password", + ), + )) + ->add("password_confirm", "password", array( + "constraints" => array( + new Constraints\NotBlank(), + new Constraints\Length(array("min" => ConfigQuery::read("password.length", 4))), + new Constraints\Callback(array("methods" => array( + array($this, "verifyPasswordField"), + ))), + ), + "label" => Translator::getInstance()->trans("Password confirmation"), + "label_attr" => array( + "for" => "password_confirmation", + ), + )) + // Add Newsletter + ->add("newsletter", "checkbox", array( + "label" => Translator::getInstance()->trans('I would like to receive the newsletter or the latest news.'), + "label_attr" => array( + "for" => "newsletter", + ), + "required" => false, + )) + ->add('lang_id', 'integer', array( + 'required' => false, + 'label' => Translator::getInstance()->trans('Preferred language'), + 'label_attr' => array( + 'for' => 'lang_id', + ), + )) + ; + + //confirm email + if (\intval(ConfigQuery::read("customer_confirm_email", 0))) { + $this->formBuilder->add("email_confirm", "email", array( + "constraints" => array( + new Constraints\NotBlank(), + new Constraints\Email(), + new Constraints\Callback(array("methods" => array( + array($this, "verifyEmailField"), + ))), + ), + "label" => Translator::getInstance()->trans("Confirm Email Address"), + "label_attr" => array( + "for" => "email_confirm", + ), + )); + } + } + + public function verifyPasswordField($value, ExecutionContextInterface $context) + { + $data = $context->getRoot()->getData(); + + if ($data["password"] != $data["password_confirm"]) { + $context->addViolation(Translator::getInstance()->trans("password confirmation is not the same as password field")); + } + } + + public function verifyEmailField($value, ExecutionContextInterface $context) + { + $data = $context->getRoot()->getData(); + + if ($data["email"] != $data["email_confirm"]) { + $context->addViolation(Translator::getInstance()->trans("email confirmation is not the same as email field")); + } + } + + public function verifyExistingEmail($value, ExecutionContextInterface $context) + { + $customer = CustomerQuery::getCustomerByEmail($value); + if ($customer) { + $context->addViolation(Translator::getInstance()->trans("This email already exists.")); + } + } + + public function getName() + { + return "thelia_customer_create"; + } +} diff --git a/core/lib/Thelia/Form/CustomerLogin.php b/core/lib/Thelia/Form/CustomerLogin.php new file mode 100644 index 00000000..1205dc21 --- /dev/null +++ b/core/lib/Thelia/Form/CustomerLogin.php @@ -0,0 +1,123 @@ + + */ +class CustomerLogin extends BruteforceForm +{ + protected function buildForm() + { + $this->formBuilder + ->add("email", "email", array( + "constraints" => array( + new Constraints\NotBlank(), + new Constraints\Email(), + new Constraints\Callback(array( + "methods" => array( + array($this, "verifyExistingEmail"), + ), + )), + ), + "label" => Translator::getInstance()->trans("Please enter your email address"), + "label_attr" => array( + "for" => "email", + ), + )) + ->add("account", "choice", array( + "constraints" => array( + new Constraints\Callback(array( + "methods" => array( + array($this, "verifyAccount"), + ), + )), + ), + "choices" => array( + 0 => Translator::getInstance()->trans("No, I am a new customer."), + 1 => Translator::getInstance()->trans("Yes, I have a password :"), + ), + "label_attr" => array( + "for" => "account", + ), + "data" => 0, + )) + ->add("password", "password", array( + "constraints" => array( + new Constraints\NotBlank(array( + 'groups' => array('existing_customer'), + )), + ), + "label" => Translator::getInstance()->trans("Please enter your password"), + "label_attr" => array( + "for" => "password", + ), + "required" => false, + )) + ->add("remember_me", "checkbox", array( + 'value' => 'yes', + "label" => Translator::getInstance()->trans("Remember me ?"), + "label_attr" => array( + "for" => "remember_me", + ), + )) + ; + } + + /** + * If the user select "Yes, I have a password", we check the password. + */ + public function verifyAccount($value, ExecutionContextInterface $context) + { + if ($value == 1) { + $data = $context->getRoot()->getData(); + if (false === $data['password'] || (empty($data['password']) && '0' != $data['password'])) { + $context->getViolations()->add(new ConstraintViolation( + Translator::getInstance()->trans('This value should not be blank.'), + 'account_password', + array(), + $context->getRoot(), + 'children[password].data', + 'propertyPath' + )); + } + } + } + + /** + * If the user select "I'am a new customer", we make sure is email address does not exit in the database. + */ + public function verifyExistingEmail($value, ExecutionContextInterface $context) + { + $data = $context->getRoot()->getData(); + if ($data["account"] == 0) { + $customer = CustomerQuery::create()->findOneByEmail($value); + if ($customer) { + $context->addViolation(Translator::getInstance()->trans("A user already exists with this email address. Please login or if you've forgotten your password, go to Reset Your Password.")); + } + } + } + + public function getName() + { + return "thelia_customer_login"; + } +} diff --git a/core/lib/Thelia/Form/CustomerLostPasswordForm.php b/core/lib/Thelia/Form/CustomerLostPasswordForm.php new file mode 100644 index 00000000..6d75c641 --- /dev/null +++ b/core/lib/Thelia/Form/CustomerLostPasswordForm.php @@ -0,0 +1,85 @@ + + */ +class CustomerLostPasswordForm extends FirewallForm +{ + /** + * + * in this function you add all the fields you need for your Form. + * Form this you have to call add method on $this->formBuilder attribute : + * + * $this->formBuilder->add("name", "text") + * ->add("email", "email", array( + * "attr" => array( + * "class" => "field" + * ), + * "label" => "email", + * "constraints" => array( + * new \Symfony\Component\Validator\Constraints\NotBlank() + * ) + * ) + * ) + * ->add('age', 'integer'); + * + * @return null + */ + protected function buildForm() + { + $this->formBuilder + ->add("email", "email", array( + "constraints" => array( + new NotBlank(), + new Email(), + new Callback(array( + "methods" => array( + array($this, + "verifyExistingEmail", ), + ), + )), + ), + "label" => Translator::getInstance()->trans("Please enter your email address"), + "label_attr" => array( + "for" => "forgot-email", + ), + )); + } + + public function verifyExistingEmail($value, ExecutionContextInterface $context) + { + $customer = CustomerQuery::create()->findOneByEmail($value); + if (null === $customer) { + $context->addViolation(Translator::getInstance()->trans("This email does not exists")); + } + } + + /** + * @return string the name of you form. This name must be unique + */ + public function getName() + { + return "thelia_customer_lost_password"; + } +} diff --git a/core/lib/Thelia/Form/CustomerPasswordUpdateForm.php b/core/lib/Thelia/Form/CustomerPasswordUpdateForm.php new file mode 100644 index 00000000..5a47b450 --- /dev/null +++ b/core/lib/Thelia/Form/CustomerPasswordUpdateForm.php @@ -0,0 +1,97 @@ + + */ +class CustomerPasswordUpdateForm extends BaseForm +{ + protected function buildForm() + { + $this->formBuilder + + // Login Information + ->add("password_old", "password", array( + "constraints" => array( + new Constraints\NotBlank(), + new Constraints\Callback(array("methods" => array( + array($this, "verifyCurrentPasswordField"), + ))), + ), + "label" => Translator::getInstance()->trans("Current Password"), + "label_attr" => array( + "for" => "password_old", + ), + )) + ->add("password", "password", array( + "constraints" => array( + new Constraints\NotBlank(), + new Constraints\Length(array("min" => ConfigQuery::read("password.length", 4))), + ), + "label" => Translator::getInstance()->trans("New Password"), + "label_attr" => array( + "for" => "password", + ), + )) + ->add("password_confirm", "password", array( + "constraints" => array( + new Constraints\NotBlank(), + new Constraints\Length(array("min" => ConfigQuery::read("password.length", 4))), + new Constraints\Callback(array("methods" => array( + array($this, "verifyPasswordField"), + ))), + ), + "label" => Translator::getInstance()->trans('Password confirmation'), + "label_attr" => array( + "for" => "password_confirmation", + ), + )); + } + + public function verifyCurrentPasswordField($value, ExecutionContextInterface $context) + { + /** + * Retrieve the user recording, because after the login action, the password is deleted in the session + */ + $userId = $this->getRequest()->getSession()->getCustomerUser()->getId(); + $user = CustomerQuery::create()->findPk($userId); + + // Check if value of the old password match the password of the current user + if (!password_verify($value, $user->getPassword())) { + $context->addViolation(Translator::getInstance()->trans("Your current password does not match.")); + } + } + + public function verifyPasswordField($value, ExecutionContextInterface $context) + { + $data = $context->getRoot()->getData(); + + if ($data["password"] != $data["password_confirm"]) { + $context->addViolation(Translator::getInstance()->trans("password confirmation is not the same as password field")); + } + } + + public function getName() + { + return "thelia_customer_password_update"; + } +} diff --git a/core/lib/Thelia/Form/CustomerProfileUpdateForm.php b/core/lib/Thelia/Form/CustomerProfileUpdateForm.php new file mode 100644 index 00000000..54700728 --- /dev/null +++ b/core/lib/Thelia/Form/CustomerProfileUpdateForm.php @@ -0,0 +1,83 @@ + + */ +class CustomerProfileUpdateForm extends CustomerCreateForm +{ + protected function buildForm() + { + parent::buildForm(); + + $this->formBuilder + ->remove("auto_login") + // Remove From Personal Informations + ->remove("phone") + ->remove("cellphone") + // Remove Delivery Informations + ->remove("company") + ->remove("address1") + ->remove("address2") + ->remove("address3") + ->remove("city") + ->remove("zipcode") + ->remove("country") + ->remove("state") + // Remove Login Information + ->remove("password") + ->remove("password_confirm") + ; + + $customerCanChangeEmail = ConfigQuery::read("customer_change_email"); + $emailConfirmation = ConfigQuery::read("customer_confirm_email"); + + if (! $customerCanChangeEmail) { + $currentOptions = $this->formBuilder->get("email")->getOptions(); + $currentOptions["constraints"] = []; + $currentOptions["required"] = false; + + $this->formBuilder->remove("email")->add("email", "text", $currentOptions); + } + + if ($this->formBuilder->has("email_confirm") && ! ($customerCanChangeEmail && $emailConfirmation)) { + $this->formBuilder->remove("email_confirm"); + } + } + + /** + * @param $value + * @param ExecutionContextInterface $context + */ + public function verifyExistingEmail($value, ExecutionContextInterface $context) + { + $customer = CustomerQuery::getCustomerByEmail($value); + // If there is already a customer for this email address and if the customer is different from the current user, do a violation + if ($customer && $customer->getId() != $this->getRequest()->getSession()->getCustomerUser()->getId()) { + $context->addViolation(Translator::getInstance()->trans("This email already exists.")); + } + } + + public function getName() + { + return "thelia_customer_profile_update"; + } +} diff --git a/core/lib/Thelia/Form/CustomerUpdateForm.php b/core/lib/Thelia/Form/CustomerUpdateForm.php new file mode 100644 index 00000000..77b8e08c --- /dev/null +++ b/core/lib/Thelia/Form/CustomerUpdateForm.php @@ -0,0 +1,229 @@ + + */ +class CustomerUpdateForm extends BaseForm +{ + use AddressCountryValidationTrait; + + /** + * @return null|void + */ + protected function buildForm() + { + $this->formBuilder + ->add( + 'update_logged_in_user', + 'integer'// In a front office context, update the in-memory logged-in user data + ) + ->add("company", "text", array( + "label" => Translator::getInstance()->trans("Company"), + "label_attr" => array( + "for" => "company", + ), + "required" => false, + )) + ->add("firstname", "text", array( + "constraints" => array( + new Constraints\NotBlank(), + ), + "label" => Translator::getInstance()->trans("First Name"), + "label_attr" => array( + "for" => "firstname", + ), + )) + ->add("lastname", "text", array( + "constraints" => array( + new Constraints\NotBlank(), + ), + "label" => Translator::getInstance()->trans("Last Name"), + "label_attr" => array( + "for" => "lastname", + ), + )) + ->add("email", "email", array( + "constraints" => array( + new Constraints\NotBlank(), + new Constraints\Email(), + ), + "label" => Translator::getInstance()->trans("Email address"), + "label_attr" => array( + "for" => "email", + ), + )) + ->add("email_confirm", "email", array( + "constraints" => array( + new Constraints\Email(), + new Constraints\Callback(array( + "methods" => array( + array($this, "verifyEmailField"), + ) + )), + ), + "label" => Translator::getInstance()->trans("Confirm Email address"), + "label_attr" => array( + "for" => "email_confirm", + ), + )) + ->add("password", "text", array( + "label" => Translator::getInstance()->trans("Password"), + "required" => false, + "label_attr" => array( + "for" => "password", + "help" => Translator::getInstance()->trans('Leave blank to keep current customer password') + ), + )) + ->add("address1", "text", array( + "constraints" => array( + new Constraints\NotBlank(), + ), + "label_attr" => array( + "for" => "address", + ), + "label" => Translator::getInstance()->trans("Street Address "), + )) + ->add("address2", "text", array( + "required" => false, + "label" => Translator::getInstance()->trans("Address Line 2"), + "label_attr" => array( + "for" => "address2", + ), + )) + ->add("address3", "text", array( + "required" => false, + "label" => Translator::getInstance()->trans("Address Line 3"), + "label_attr" => array( + "for" => "address3", + ), + )) + ->add("phone", "text", array( + "label" => Translator::getInstance()->trans("Phone"), + "label_attr" => array( + "for" => "phone", + ), + "required" => false, + )) + ->add("cellphone", "text", array( + "label" => Translator::getInstance()->trans("Cellphone"), + "label_attr" => array( + "for" => "cellphone", + ), + "required" => false, + )) + ->add("zipcode", "text", array( + "constraints" => array( + new Constraints\NotBlank(), + new Constraints\Callback(array( + "methods" => array( + array($this, "verifyZipCode") + ), + )), + ), + "label" => Translator::getInstance()->trans("Zip code"), + "label_attr" => array( + "for" => "zipcode", + ), + )) + ->add("city", "text", array( + "constraints" => array( + new Constraints\NotBlank(), + ), + "label" => Translator::getInstance()->trans("City"), + "label_attr" => array( + "for" => "city", + ), + )) + ->add("country", "text", array( + "constraints" => array( + new Constraints\NotBlank(), + ), + "label" => Translator::getInstance()->trans("Country"), + "label_attr" => array( + "for" => "country", + ), + )) + ->add("state", "text", array( + "required" => false, + "constraints" => array( + new Constraints\Callback(array( + "methods" => array( + array($this, "verifyState") + ), + )), + ), + "label" => Translator::getInstance()->trans("State *"), + "label_attr" => array( + "for" => "state", + ), + )) + ->add("title", "text", array( + "constraints" => array( + new Constraints\NotBlank(), + ), + "label" => Translator::getInstance()->trans("Title"), + "label_attr" => array( + "for" => "title", + ), + )) + ->add('discount', 'text', array( + 'required' => false, + 'label' => Translator::getInstance()->trans('permanent discount (in percent)'), + 'label_attr' => array( + 'for' => 'discount', + ), + )) + ->add('reseller', 'checkbox', array( + 'required' => false, + 'label' => Translator::getInstance()->trans('Reseller'), + 'label_attr' => array( + 'for' => 'reseller', + ), + )) + ->add('lang_id', 'integer', array( + 'required' => false, + 'label' => Translator::getInstance()->trans('Preferred language'), + 'label_attr' => array( + 'for' => 'lang_id', + ), + )) + ; + } + + public function verifyEmailField($value, ExecutionContextInterface $context) + { + $data = $context->getRoot()->getData(); + + if (isset($data["email_confirm"]) && $data["email"] != $data["email_confirm"]) { + $context->addViolation( + Translator::getInstance()->trans("email confirmation is not the same as email field") + ); + } + } + + /** + * @return string the name of you form. This name must be unique + */ + public function getName() + { + return "thelia_customer_update"; + } +} diff --git a/core/lib/Thelia/Form/Definition/AdminForm.php b/core/lib/Thelia/Form/Definition/AdminForm.php new file mode 100644 index 00000000..a9936625 --- /dev/null +++ b/core/lib/Thelia/Form/Definition/AdminForm.php @@ -0,0 +1,168 @@ + + * @package Thelia\Form\Definition + */ +final class AdminForm +{ + const ADMIN_LOGIN = 'thelia.admin.login'; + const ADMIN_LOST_PASSWORD = 'thelia.admin.lostpassword'; + const ADMIN_CREATE_PASSWORD = 'thelia.admin.createpassword'; + + const SEO = 'thelia.admin.seo'; + + const CUSTOMER_CREATE = 'thelia.admin.customer.create'; + const CUSTOMER_UPDATE = 'thelia.admin.customer.update'; + + const ADDRESS_CREATE = 'thelia.admin.address.create'; + const ADDRESS_UPDATE = 'thelia.admin.address.update'; + + const CATEGORY_CREATION = 'thelia.admin.category.creation'; + const CATEGORY_MODIFICATION = 'thelia.admin.category.modification'; + const CATEGORY_IMAGE_MODIFICATION = 'thelia.admin.category.image.modification'; + const CATEGORY_DOCUMENT_MODIFICATION = 'thelia.admin.category.document.modification'; + + const PRODUCT_CREATION = 'thelia.admin.product.creation'; + const PRODUCT_CLONE = 'thelia.admin.product.clone'; + const PRODUCT_MODIFICATION = 'thelia.admin.product.modification'; + const PRODUCT_DETAILS_MODIFICATION = 'thelia.admin.product.details.modification'; + const PRODUCT_IMAGE_MODIFICATION = 'thelia.admin.product.image.modification'; + const PRODUCT_DOCUMENT_MODIFICATION = 'thelia.admin.product.document.modification'; + + const PRODUCT_SALE_ELEMENT_UPDATE = 'thelia.admin.product_sale_element.update'; + const PRODUCT_DEFAULT_SALE_ELEMENT_UPDATE = 'thelia.admin.product_default_sale_element.update'; + const PRODUCT_COMBINATION_GENERATION = 'thelia.admin.product_combination.build'; + + const PRODUCT_DELETE = 'thelia.admin.product.deletion'; + + const FOLDER_CREATION = 'thelia.admin.folder.creation'; + const FOLDER_MODIFICATION = 'thelia.admin.folder.modification'; + const FOLDER_IMAGE_MODIFICATION = 'thelia.admin.folder.image.modification'; + const FOLDER_DOCUMENT_MODIFICATION = 'thelia.admin.folder.document.modification'; + + const CONTENT_CREATION = 'thelia.admin.content.creation'; + const CONTENT_MODIFICATION = 'thelia.admin.content.modification'; + const CONTENT_IMAGE_MODIFICATION = 'thelia.admin.content.image.modification'; + const CONTENT_DOCUMENT_MODIFICATION = 'thelia.admin.content.document.modification'; + + const BRAND_CREATION = 'thelia.admin.brand.creation'; + const BRAND_MODIFICATION = 'thelia.admin.brand.modification'; + const BRAND_IMAGE_MODIFICATION = 'thelia.admin.brand.image.modification'; + const BRAND_DOCUMENT_MODIFICATION = 'thelia.admin.brand.document.modification'; + + const CART_ADD = 'thelia.cart.add'; + + const ORDER_DELIVERY = 'thelia.order.delivery'; + const ORDER_PAYMENT = 'thelia.order.payment'; + const ORDER_UPDATE_ADDRESS = 'thelia.order.update.address'; + + const ORDER_STATUS_CREATION = 'thelia.admin.order-status.creation'; + const ORDER_STATUS_MODIFICATION = 'thelia.admin.order-status.modification'; + + const COUPON_CODE = 'thelia.order.coupon'; + + const CONFIG_CREATION = 'thelia.admin.config.creation'; + const CONFIG_MODIFICATION = 'thelia.admin.config.modification'; + + const MESSAGE_CREATION = 'thelia.admin.message.creation'; + const MESSAGE_MODIFICATION = 'thelia.admin.message.modification'; + const MESSAGE_SEND_SAMPLE = 'thelia.admin.message.send-sample'; + + const CURRENCY_CREATION = 'thelia.admin.currency.creation'; + const CURRENCY_MODIFICATION = 'thelia.admin.currency.modification'; + + const COUPON_CREATION = 'thelia.admin.coupon.creation'; + + const ATTRIBUTE_CREATION = 'thelia.admin.attribute.creation'; + const ATTRIBUTE_MODIFICATION = 'thelia.admin.attribute.modification'; + + const FEATURE_CREATION = 'thelia.admin.feature.creation'; + const FEATURE_MODIFICATION = 'thelia.admin.feature.modification'; + + const ATTRIBUTE_AV_CREATION = 'thelia.admin.attributeav.creation'; + + const FEATURE_AV_CREATION = 'thelia.admin.featureav.creation'; + + const TAX_RULE_MODIFICATION = 'thelia.admin.taxrule.modification'; + const TAX_RULE_TAX_LIST_UPDATE = 'thelia.admin.taxrule.taxlistupdate'; + const TAX_RULE_CREATION = 'thelia.admin.taxrule.add'; + + const TAX_MODIFICATION = 'thelia.admin.tax.modification'; + const TAX_TAX_LIST_UPDATE = 'thelia.admin.tax.taxlistupdate'; + const TAX_CREATION = 'thelia.admin.tax.add'; + + const PROFILE_CREATION = 'thelia.admin.profile.add'; + const PROFILE_MODIFICATION = 'thelia.admin.profile.modification'; + const PROFILE_UPDATE_RESOURCE_ACCESS = 'thelia.admin.profile.resource-access.modification'; + const PROFILE_UPDATE_MODULE_ACCESS = 'thelia.admin.profile.module-access.modification'; + + const ADMINISTRATOR_CREATION = 'thelia.admin.administrator.add'; + const ADMINISTRATOR_MODIFICATION = 'thelia.admin.administrator.update'; + + const MAILING_SYSTEM_MODIFICATION = 'thelia.admin.mailing-system.update'; + + const TEMPLATE_CREATION = 'thelia.admin.template.creation'; + const TEMPLATE_MODIFICATION = 'thelia.admin.template.modification'; + + const COUNTRY_CREATION = 'thelia.admin.country.creation'; + const COUNTRY_MODIFICATION = 'thelia.admin.country.modification'; + + const STATE_CREATION = 'thelia.admin.state.creation'; + const STATE_MODIFICATION = 'thelia.admin.state.modification'; + + const AREA_CREATE = 'thelia.admin.area.create'; + const AREA_MODIFICATION = 'thelia.admin.area.modification'; + const AREA_COUNTRY = 'thelia.admin.area.country'; + const AREA_DELETE_COUNTRY = 'thelia.admin.area.delete.country'; + const AREA_POSTAGE = 'thelia.admin.area.postage'; + + const SHIPPING_ZONE_ADD_AREA = 'thelia.shopping_zone_area'; + const SHIPPING_ZONE_REMOVE_AREA = 'thelia.shopping_zone_remove_area'; + + const LANG_UPDATE = 'thelia.lang.update'; + const LANG_CREATE = 'thelia.lang.create'; + const LANG_DEFAULT_BEHAVIOR = 'thelia.lang.defaultBehavior'; + const LANG_URL = 'thelia.lang.url'; + + const CONFIG_STORE = 'thelia.configuration.store'; + const SYSTEM_LOG_CONFIGURATION = 'thelia.system-logs.configuration'; + + const MODULE_MODIFICATION = 'thelia.admin.module.modification'; + const MODULE_INSTALL = 'thelia.admin.module.install'; + + const HOOK_CREATION = 'thelia.admin.hook.creation'; + const HOOK_MODIFICATION = 'thelia.admin.hook.modification'; + + const MODULE_HOOK_CREATION = 'thelia.admin.module-hook.creation'; + const MODULE_HOOK_MODIFICATION = 'thelia.admin.module-hook.modification'; + + const CACHE_FLUSH = 'thelia.cache.flush'; + const ASSETS_FLUSH = 'thelia.assets.flush'; + const IMAGES_AND_DOCUMENTS_CACHE_FLUSH = 'thelia.images-and-documents-cache.flush'; + + const EXPORT = 'thelia.export'; + const IMPORT = 'thelia.import'; + + const SALE_CREATION = 'thelia.admin.sale.creation'; + const SALE_MODIFICATION = 'thelia.admin.sale.modification'; + + const EMPTY_FORM = 'thelia.empty'; + + const API_CREATE = 'thelia_api_create'; + const API_UPDATE = 'thelia_api_update'; +} diff --git a/core/lib/Thelia/Form/Definition/ApiForm.php b/core/lib/Thelia/Form/Definition/ApiForm.php new file mode 100644 index 00000000..4071004f --- /dev/null +++ b/core/lib/Thelia/Form/Definition/ApiForm.php @@ -0,0 +1,36 @@ + + * @package TheliaFormDefinition + */ +final class ApiForm +{ + const EMPTY_FORM = 'thelia.api.empty'; + + const CUSTOMER_CREATE = 'thelia.api.customer.create'; + const CUSTOMER_UPDATE = 'thelia.api.customer.update'; + const CUSTOMER_LOGIN = 'thelia.api.customer.login'; + + const CATEGORY_CREATION = 'thelia.api.category.create'; + const CATEGORY_MODIFICATION = 'thelia.api.category.update'; + + const PRODUCT_SALE_ELEMENTS = 'thelia.api.product_sale_elements'; + + const PRODUCT_CREATION = 'thelia.api.product.creation'; + const PRODUCT_MODIFICATION = 'thelia.api.product.modification'; +} diff --git a/core/lib/Thelia/Form/Definition/FrontForm.php b/core/lib/Thelia/Form/Definition/FrontForm.php new file mode 100644 index 00000000..5b399bd8 --- /dev/null +++ b/core/lib/Thelia/Form/Definition/FrontForm.php @@ -0,0 +1,37 @@ + + * @package Thelia\Form\Definition + */ +final class FrontForm +{ + const ADDRESS_CREATE = 'thelia.front.address.create'; + const ADDRESS_UPDATE = 'thelia.front.address.update'; + const CART_ADD = 'thelia.cart.add'; + const CONTACT = 'thelia.front.contact'; + const COUPON_CONSUME = 'thelia.order.coupon'; + const CUSTOMER_LOGIN = 'thelia.front.customer.login'; + const CUSTOMER_LOST_PASSWORD = 'thelia.front.customer.lostpassword'; + const CUSTOMER_CREATE = 'thelia.front.customer.create'; + const CUSTOMER_PROFILE_UPDATE = 'thelia.front.customer.profile.update'; + const CUSTOMER_PASSWORD_UPDATE = 'thelia.front.customer.password.update'; + const NEWSLETTER = 'thelia.front.newsletter'; + const NEWSLETTER_UNSUBSCRIBE = 'thelia.front.newsletter.unsubscribe'; + const ORDER_DELIVER = 'thelia.order.delivery'; + const ORDER_PAYMENT = 'thelia.order.payment'; +} diff --git a/core/lib/Thelia/Form/EmptyForm.php b/core/lib/Thelia/Form/EmptyForm.php new file mode 100644 index 00000000..d0076298 --- /dev/null +++ b/core/lib/Thelia/Form/EmptyForm.php @@ -0,0 +1,53 @@ + + */ +class EmptyForm extends BaseForm +{ + /** + * + * in this function you add all the fields you need for your Form. + * Form this you have to call add method on $this->formBuilder attribute : + * + * $this->formBuilder->add("name", "text") + * ->add("email", "email", array( + * "attr" => array( + * "class" => "field" + * ), + * "label" => "email", + * "constraints" => array( + * new \Symfony\Component\Validator\Constraints\NotBlank() + * ) + * ) + * ) + * ->add('age', 'integer'); + * + * @return null + */ + protected function buildForm() + { + } + + /** + * @return string the name of you form. This name must be unique + */ + public function getName() + { + return "empty"; + } +} diff --git a/core/lib/Thelia/Form/Exception/FormValidationException.php b/core/lib/Thelia/Form/Exception/FormValidationException.php new file mode 100644 index 00000000..9547ec87 --- /dev/null +++ b/core/lib/Thelia/Form/Exception/FormValidationException.php @@ -0,0 +1,17 @@ + + */ +class ExportForm extends BaseForm +{ + public function getName() + { + return 'thelia_export'; + } + + protected function buildForm() + { + $this->formBuilder + // Todo: use list + ->add( + 'serializer', + 'text', + [ + 'required' => true, + 'label' => $this->translator->trans('File format'), + 'label_attr' => [ + 'for' => 'serializer' + ], + ] + ) + // Todo: use list + ->add( + 'language', + 'integer', + [ + 'required' => true, + 'label' => $this->translator->trans('Language'), + 'label_attr' => [ + 'for' => 'language' + ], + 'constraints' => [ + new Callback([ + 'methods' => [ + [$this, 'checkLanguage'], + ], + ]), + ], + ] + ) + ->add("do_compress", "checkbox", array( + "label" => $this->translator->trans("Do compress"), + "label_attr" => ["for" => "do_compress"], + "required" => false, + )) + // Todo: use list + ->add( + 'archiver', + 'text', + [ + 'required' => false, + 'label' => $this->translator->trans('Archive Format'), + 'label_attr' => [ + 'for' => 'archiver' + ], + ] + ) + ->add("images", "checkbox", array( + "label" => $this->translator->trans("Include images"), + "label_attr" => ["for" => "with_images"], + "required" => false, + )) + ->add("documents", "checkbox", array( + "label" => $this->translator->trans("Include documents"), + "label_attr" => ["for" => "with_documents"], + "required" => false, + )) + ->add("range_date_start", "date", array( + "label" => $this->translator->trans("Range date Start"), + "label_attr" => ["for" => "for_range_date_start"], + "required" => false, + 'years' => range(date('Y'), date('Y') - 5), + 'input' => 'array', + 'widget' => 'choice', + 'empty_value' => array('year' => 'Year', 'month' => 'Month', 'day' => 'Day'), + 'format' => 'yyyy-MM-d', + )) + ->add("range_date_end", "date", array( + "label" => $this->translator->trans("Range date End"), + "label_attr" => ["for" => "for_range_date_end"], + "required" => false, + 'years' => range(date('Y'), date('Y') - 5), + 'input' => 'array', + 'widget' => 'choice', + 'empty_value' => array('year' => 'Year', 'month' => 'Month', 'day' => 'Day'), + 'format' => 'yyyy-MM-d', + )); + } + + public function checkLanguage($value, ExecutionContextInterface $context) + { + if (null === LangQuery::create()->findPk($value)) { + $context->addViolation( + $this->translator->trans( + "The language \"%id\" doesn't exist", + [ + "%id" => $value + ] + ) + ); + } + } +} diff --git a/core/lib/Thelia/Form/FeatureAvCreationForm.php b/core/lib/Thelia/Form/FeatureAvCreationForm.php new file mode 100644 index 00000000..74842134 --- /dev/null +++ b/core/lib/Thelia/Form/FeatureAvCreationForm.php @@ -0,0 +1,50 @@ +formBuilder + ->add("title", "text", array( + "constraints" => array( + new NotBlank(), + ), + "label" => Translator::getInstance()->trans("Title *"), + "label_attr" => array( + "for" => "title", + ), + )) + ->add("locale", "text", array( + "constraints" => array( + new NotBlank(), + ), + )) + ->add("feature_id", "hidden", array( + "constraints" => array( + new NotBlank(), + ), + )) + ; + } + + public function getName() + { + return "thelia_featureav_creation"; + } +} diff --git a/core/lib/Thelia/Form/FeatureCreationForm.php b/core/lib/Thelia/Form/FeatureCreationForm.php new file mode 100644 index 00000000..cf1197ba --- /dev/null +++ b/core/lib/Thelia/Form/FeatureCreationForm.php @@ -0,0 +1,60 @@ +formBuilder + ->add( + "title", + "text", + array( + "constraints" => array( + new NotBlank(), + ), + "label" => Translator::getInstance()->trans("Title *"), + "label_attr" => array( + "for" => "title", + ), ) + ) + ->add( + "locale", + "text", + array( + "constraints" => array( + new NotBlank(), + ), ) + ) + ->add( + "add_to_all", + "checkbox", + array( + "label" => Translator::getInstance()->trans("Add to all product templates"), + "label_attr" => array( + "for" => "add_to_all", + ), ) + ) + ; + } + + public function getName() + { + return "thelia_feature_creation"; + } +} diff --git a/core/lib/Thelia/Form/FeatureModificationForm.php b/core/lib/Thelia/Form/FeatureModificationForm.php new file mode 100644 index 00000000..3c08708b --- /dev/null +++ b/core/lib/Thelia/Form/FeatureModificationForm.php @@ -0,0 +1,42 @@ +formBuilder + ->add("id", "hidden", array( + "constraints" => array( + new GreaterThan( + array('value' => 0) + ), + ), + )) + ; + + // Add standard description fields + $this->addStandardDescFields(); + } + + public function getName() + { + return "thelia_feature_modification"; + } +} diff --git a/core/lib/Thelia/Form/FirewallForm.php b/core/lib/Thelia/Form/FirewallForm.php new file mode 100644 index 00000000..f2211bfe --- /dev/null +++ b/core/lib/Thelia/Form/FirewallForm.php @@ -0,0 +1,122 @@ + + */ +abstract class FirewallForm extends BaseForm +{ + /** + * Those values are for a "normal" security policy + * + * Time is in minutes + */ + const DEFAULT_TIME_TO_WAIT = 60; // 1 hour + const DEFAULT_ATTEMPTS = 6; + + public function isFirewallOk($env) + { + if ($env === "prod" && $this->isFirewallActive()) { + /** + * Empty the firewall + */ + $deleteTime = date("Y-m-d G:i:s", time() - $this->getConfigTime() * 60); + $collection = FormFirewallQuery::create() + ->filterByFormName($this->getName()) + ->filterByUpdatedAt($deleteTime, Criteria::LESS_THAN) + ->find(); + + $collection->delete(); + + $firewallInstance = FormFirewallQuery::create() + ->filterByFormName($this->getName()) + ->filterByIpAddress($this->request->getClientIp()) + ->findOne() + ; + + if (null !== $firewallInstance) { + if ($firewallInstance->getAttempts() < $this->getConfigAttempts()) { + $firewallInstance->incrementAttempts(); + } else { + /** Set updated_at at NOW() */ + $firewallInstance->save(); + + return false; + } + } else { + $firewallInstance = (new FormFirewall()) + ->setIpAddress($this->request->getClientIp()) + ->setFormName($this->getName()) + ; + $firewallInstance->save(); + } + } + + return true; + } + + /** + * @return int + * + * The time (in hours) to wait if the attempts have been exceeded + */ + public function getConfigTime() + { + return ConfigQuery::read("form_firewall_time_to_wait", static::DEFAULT_TIME_TO_WAIT); + } + + /** + * @return int + * + * The number of allowed attempts + */ + public function getConfigAttempts() + { + return ConfigQuery::read("form_firewall_attempts", static::DEFAULT_ATTEMPTS); + } + + public function isFirewallActive() + { + return ConfigQuery::read("form_firewall_active", true); + } + + public function getWaitingTime() + { + $translator = Translator::getInstance(); + $minutes = $this->getConfigTime(); + $minutesName = $translator->trans("minute(s)"); + $text = ""; + + if ($minutes >= 60) { + $hour = floor($minutes / 60); + $minutes %= 60; + $text = $hour." ".$translator->trans("hour(s)")." "; + } + + if ($minutes !== 0) { + $text .= $minutes." ".$minutesName; + } else { + $text = rtrim($text); + } + + return $text; + } +} diff --git a/core/lib/Thelia/Form/FolderCreationForm.php b/core/lib/Thelia/Form/FolderCreationForm.php new file mode 100644 index 00000000..c7e9ccee --- /dev/null +++ b/core/lib/Thelia/Form/FolderCreationForm.php @@ -0,0 +1,56 @@ +formBuilder + ->add("title", "text", array( + "constraints" => array( + new NotBlank(), + ), + "label" => Translator::getInstance()->trans("Folder title *"), + "label_attr" => array( + "for" => "title", + ), + )) + ->add("parent", "text", array( + "label" => Translator::getInstance()->trans("Parent folder *"), + "constraints" => array( + new NotBlank(), + ), + "label_attr" => array("for" => "parent_create"), + )) + ->add("locale", "text", array( + "constraints" => array( + new NotBlank(), + ), + "label_attr" => array("for" => "locale_create"), + )) + ->add("visible", "integer", array( + "label" => Translator::getInstance()->trans("This folder is online."), + "label_attr" => array("for" => "visible_create"), + )) + ; + } + + public function getName() + { + return "thelia_folder_creation"; + } +} diff --git a/core/lib/Thelia/Form/FolderDocumentModification.php b/core/lib/Thelia/Form/FolderDocumentModification.php new file mode 100644 index 00000000..6a60bd47 --- /dev/null +++ b/core/lib/Thelia/Form/FolderDocumentModification.php @@ -0,0 +1,40 @@ + + * + */ +class FolderDocumentModification extends DocumentModification +{ + /** + * Get form name + * This name must be unique + * + * @return string + */ + public function getName() + { + return 'thelia_folder_document_modification'; + } +} diff --git a/core/lib/Thelia/Form/FolderImageModification.php b/core/lib/Thelia/Form/FolderImageModification.php new file mode 100644 index 00000000..f6316698 --- /dev/null +++ b/core/lib/Thelia/Form/FolderImageModification.php @@ -0,0 +1,40 @@ + + * + */ +class FolderImageModification extends ImageModification +{ + /** + * Get form name + * This name must be unique + * + * @return string + */ + public function getName() + { + return 'thelia_folder_image_modification'; + } +} diff --git a/core/lib/Thelia/Form/FolderModificationForm.php b/core/lib/Thelia/Form/FolderModificationForm.php new file mode 100644 index 00000000..156662bc --- /dev/null +++ b/core/lib/Thelia/Form/FolderModificationForm.php @@ -0,0 +1,36 @@ +formBuilder + ->add("id", "hidden", array("constraints" => array(new GreaterThan(array('value' => 0))))) + ; + + // Add standard description fields, excluding title and locale, which a re defined in parent class + $this->addStandardDescFields(array('title', 'locale')); + } + + public function getName() + { + return "thelia_folder_modification"; + } +} diff --git a/core/lib/Thelia/Form/HookCreationForm.php b/core/lib/Thelia/Form/HookCreationForm.php new file mode 100644 index 00000000..bca3e8cb --- /dev/null +++ b/core/lib/Thelia/Form/HookCreationForm.php @@ -0,0 +1,115 @@ + + */ +class HookCreationForm extends BaseForm +{ + protected function buildForm() + { + $this->formBuilder + ->add("code", "text", array( + "constraints" => array( + new NotBlank(), + new Callback(array( + "methods" => array(array($this, "checkCodeUnicity")) + )), + ), + "label" => Translator::getInstance()->trans("Hook code"), + "label_attr" => array( + "for" => "code", + ), + )) + ->add("locale", "hidden", array( + "constraints" => array( + new NotBlank(), + ), + )) + ->add("type", "choice", array( + "choices" => array( + TemplateDefinition::FRONT_OFFICE => Translator::getInstance()->trans("Front Office"), + TemplateDefinition::BACK_OFFICE => Translator::getInstance()->trans("Back Office"), + TemplateDefinition::EMAIL => Translator::getInstance()->trans("email"), + TemplateDefinition::PDF => Translator::getInstance()->trans("pdf"), + ), + "constraints" => array( + new NotBlank(), + ), + "label" => Translator::getInstance()->trans("Type"), + "label_attr" => array( + "for" => "type", + ), + )) + ->add("native", "hidden", array( + "label" => Translator::getInstance()->trans("Native"), + "label_attr" => array( + "for" => "native", + "help" => Translator::getInstance()->trans("Core hook of Thelia."), + ), + )) + ->add("active", "checkbox", array( + "label" => Translator::getInstance()->trans("Active"), + "required" => false, + "label_attr" => array( + "for" => "active", + ), + )) + ->add("title", "text", array( + "constraints" => array( + new NotBlank(), + ), + "label" => Translator::getInstance()->trans("Hook title"), + "label_attr" => array( + "for" => "title", + ), + )) + ; + } + + public function checkCodeUnicity($code, ExecutionContextInterface $context) + { + $type = $context->getRoot()->getData()['type']; + + $query = HookQuery::create()->filterByCode($code)->filterByType($type); + + if ($this->form->has('id')) { + $query->filterById($this->form->getRoot()->getData()['id'], Criteria::NOT_EQUAL); + } + + if ($query->count() > 0) { + $context->addViolation( + Translator::getInstance()->trans( + "A Hook with code %name already exists. Please choose another code.", + array('%name' => $code) + ) + ); + } + } + + public function getName() + { + return "thelia_hook_creation"; + } +} diff --git a/core/lib/Thelia/Form/HookModificationForm.php b/core/lib/Thelia/Form/HookModificationForm.php new file mode 100644 index 00000000..9d0c9ec3 --- /dev/null +++ b/core/lib/Thelia/Form/HookModificationForm.php @@ -0,0 +1,63 @@ + + */ +class HookModificationForm extends HookCreationForm +{ + use StandardDescriptionFieldsTrait; + + protected function buildForm() + { + parent::buildForm(); + + $this->formBuilder + ->add("id", "hidden", array("constraints" => array(new GreaterThan(array('value' => 0))))) + ->add("by_module", "checkbox", array( + "label" => Translator::getInstance()->trans("By Module"), + "required" => false, + "label_attr" => array( + "for" => "by_module", + "help" => Translator::getInstance()->trans( + "This hook is specific to a module (delivery/payment modules)." + ), + ), + )) + ->add("block", "checkbox", array( + "label" => Translator::getInstance()->trans("Hook block"), + "required" => false, + "label_attr" => array( + "for" => "block", + "help" => Translator::getInstance()->trans( + "If checked, this hook will be used by a hook block. If not, by hook function." + ), + ), + )) + ; + + // Add standard description fields, excluding title and locale, which a re defined in parent class + $this->addStandardDescFields(array('title', 'postscriptum', 'locale')); + } + + public function getName() + { + return "thelia_hook_modification"; + } +} diff --git a/core/lib/Thelia/Form/Image/DocumentModification.php b/core/lib/Thelia/Form/Image/DocumentModification.php new file mode 100644 index 00000000..43c4cea1 --- /dev/null +++ b/core/lib/Thelia/Form/Image/DocumentModification.php @@ -0,0 +1,71 @@ + + * + */ +abstract class DocumentModification extends BaseForm +{ + use StandardDescriptionFieldsTrait; + + /** + * @inheritdoc + */ + protected function buildForm() + { + $translator = Translator::getInstance(); + + $this->formBuilder + ->add( + 'file', + 'file', + [ + 'required' => false, + 'constraints' => [ ], + 'label' => $translator->trans('Replace current document by this file'), + 'label_attr' => [ + 'for' => 'file', + ] + ] + ) + // Is this document online ? + ->add( + 'visible', + 'checkbox', + [ + 'constraints' => [ ], + 'required' => false, + 'label' => $translator->trans('This document is online'), + 'label_attr' => [ + 'for' => 'visible_create', + ] + ] + ); + + // Add standard description fields + $this->addStandardDescFields(); + } +} diff --git a/core/lib/Thelia/Form/Image/ImageModification.php b/core/lib/Thelia/Form/Image/ImageModification.php new file mode 100644 index 00000000..3bca7728 --- /dev/null +++ b/core/lib/Thelia/Form/Image/ImageModification.php @@ -0,0 +1,78 @@ + + * + */ +abstract class ImageModification extends BaseForm +{ + use StandardDescriptionFieldsTrait; + + /** + * @inheritdoc + */ + protected function buildForm() + { + $translator = Translator::getInstance(); + + $this->formBuilder + ->add( + 'file', + 'file', + [ + 'required' => false, + 'constraints' => [ + new Image([ + //'minWidth' => 200, + //'minHeight' => 200 + ]), + ], + 'label' => $translator->trans('Replace current image by this file'), + 'label_attr' => [ + 'for' => 'file', + ] + ] + ) + // Is this image online ? + ->add( + 'visible', + 'checkbox', + [ + 'constraints' => [ ], + 'required' => false, + 'label' => $translator->trans('This image is online'), + 'label_attr' => [ + 'for' => 'visible_create', + ] + ] + ) + ; + + // Add standard description fields + $this->addStandardDescFields(); + } +} diff --git a/core/lib/Thelia/Form/ImportForm.php b/core/lib/Thelia/Form/ImportForm.php new file mode 100644 index 00000000..c38046b5 --- /dev/null +++ b/core/lib/Thelia/Form/ImportForm.php @@ -0,0 +1,73 @@ + + */ +class ImportForm extends BaseForm +{ + protected function buildForm() + { + $this->formBuilder + ->add("file_upload", "file", array( + "label" => $this->translator->trans("File to upload"), + "label_attr" => ["for" => "file_to_upload"], + "required" => true, + "constraints" => [ + new Assert\NotNull + ] + )) + ->add("language", "integer", array( + "label" => $this->translator->trans("Language"), + "label_attr" => ["for" => "language"], + "required" => true, + "constraints" => [ + new Assert\Callback([ + "methods" => [ + [$this, "checkLanguage"], + ], + ]), + ], + )) + ; + } + + /** + * @return string the name of you form. This name must be unique + */ + public function getName() + { + return "thelia_import"; + } + + public function checkLanguage($value, ExecutionContextInterface $context) + { + if (null === LangQuery::create()->findPk($value)) { + $context->addViolation( + $this->translator->trans( + "The language \"%id\" doesn't exist", + [ + "%id" => $value + ] + ) + ); + } + } +} diff --git a/core/lib/Thelia/Form/InstallStep3Form.php b/core/lib/Thelia/Form/InstallStep3Form.php new file mode 100644 index 00000000..e3be7b0a --- /dev/null +++ b/core/lib/Thelia/Form/InstallStep3Form.php @@ -0,0 +1,100 @@ + + * + */ +class InstallStep3Form extends BaseForm +{ + /** + * Build Coupon form + * + * @return void + */ + protected function buildForm() + { + $this->formBuilder + ->add( + 'host', + 'text', + array( + 'constraints' => array( + new NotBlank(), + ), + ) + ) + ->add( + 'user', + 'text', + array( + 'constraints' => array( + new NotBlank(), + ), + ) + ) + ->add( + 'password', + 'text', + array( + 'constraints' => array( + new NotBlank(), + ), + ) + ) + ->add( + 'port', + 'text', + array( + 'constraints' => array( + new NotBlank(), + new GreaterThan( + array( + 'value' => 0, + ) + ), + ), + ) + ) + ->add( + 'locale', + 'hidden', + array( + 'constraints' => array( + new NotBlank(), + ), + ) + ); + } + + /** + * Get form name + * + * @return string + */ + public function getName() + { + return 'thelia_install_step3'; + } +} diff --git a/core/lib/Thelia/Form/Lang/LangCreateForm.php b/core/lib/Thelia/Form/Lang/LangCreateForm.php new file mode 100644 index 00000000..ae3ac398 --- /dev/null +++ b/core/lib/Thelia/Form/Lang/LangCreateForm.php @@ -0,0 +1,138 @@ + + */ +class LangCreateForm extends BaseForm +{ + /** + * + * in this function you add all the fields you need for your Form. + * Form this you have to call add method on $this->formBuilder attribute : + * + * $this->formBuilder->add("name", "text") + * ->add("email", "email", array( + * "attr" => array( + * "class" => "field" + * ), + * "label" => "email", + * "constraints" => array( + * new \Symfony\Component\Validator\Constraints\NotBlank() + * ) + * ) + * ) + * ->add('age', 'integer'); + * + * @return null + */ + protected function buildForm() + { + $this->formBuilder + ->add('title', 'text', array( + 'constraints' => array( + new NotBlank(), + ), + 'label' => Translator::getInstance()->trans('Language name'), + 'label_attr' => array( + 'for' => 'title_lang', + ), + )) + ->add('code', 'text', array( + 'constraints' => array( + new NotBlank(), + ), + 'label' => Translator::getInstance()->trans('ISO 639-1 Code'), + 'label_attr' => array( + 'for' => 'code_lang', + ), + )) + ->add('locale', 'text', array( + 'constraints' => array( + new NotBlank(), + ), + 'label' => Translator::getInstance()->trans('language locale'), + 'label_attr' => array( + 'for' => 'locale_lang', + ), + )) + ->add('date_time_format', 'text', array( + 'constraints' => array( + new NotBlank(), + ), + 'label' => Translator::getInstance()->trans('date/time format'), + 'label_attr' => array( + 'for' => 'date_time_format', + ), + )) + ->add('date_format', 'text', array( + 'constraints' => array( + new NotBlank(), + ), + 'label' => Translator::getInstance()->trans('date format'), + 'label_attr' => array( + 'for' => 'date_lang', + ), + )) + ->add('time_format', 'text', array( + 'constraints' => array( + new NotBlank(), + ), + 'label' => Translator::getInstance()->trans('time format'), + 'label_attr' => array( + 'for' => 'time_lang', + ), + )) + ->add('decimal_separator', 'text', array( + 'constraints' => array( + new NotBlank(), + ), + 'label' => Translator::getInstance()->trans('decimal separator'), + 'label_attr' => array( + 'for' => 'decimal_separator', + ), + )) + ->add('thousands_separator', 'text', array( + 'trim' => false, + 'label' => Translator::getInstance()->trans('thousands separator'), + 'label_attr' => array( + 'for' => 'thousands_separator', + ), + )) + ->add('decimals', 'text', array( + 'constraints' => array( + new NotBlank(), + ), + 'label' => Translator::getInstance()->trans('Decimal places'), + 'label_attr' => array( + 'for' => 'decimals', + ), + )) + ; + } + + /** + * @return string the name of you form. This name must be unique + */ + public function getName() + { + return 'thelia_language_create'; + } +} diff --git a/core/lib/Thelia/Form/Lang/LangDefaultBehaviorForm.php b/core/lib/Thelia/Form/Lang/LangDefaultBehaviorForm.php new file mode 100644 index 00000000..26ffb487 --- /dev/null +++ b/core/lib/Thelia/Form/Lang/LangDefaultBehaviorForm.php @@ -0,0 +1,71 @@ + + */ +class LangDefaultBehaviorForm extends BaseForm +{ + /** + * + * in this function you add all the fields you need for your Form. + * Form this you have to call add method on $this->formBuilder attribute : + * + * $this->formBuilder->add("name", "text") + * ->add("email", "email", array( + * "attr" => array( + * "class" => "field" + * ), + * "label" => "email", + * "constraints" => array( + * new \Symfony\Component\Validator\Constraints\NotBlank() + * ) + * ) + * ) + * ->add('age', 'integer'); + * + * @return null + */ + protected function buildForm() + { + $this->formBuilder + ->add('behavior', 'choice', array( + 'choices' => array( + 0 => Translator::getInstance()->trans("Strictly use the requested language"), + 1 => Translator::getInstance()->trans("Replace by the default language"), + ), + 'constraints' => array( + new NotBlank(), + ), + 'label' => Translator::getInstance()->trans("If a translation is missing or incomplete :"), + 'label_attr' => array( + 'for' => 'defaultBehavior-form', + ), + )); + } + + /** + * @return string the name of you form. This name must be unique + */ + public function getName() + { + return 'thelia_lang_defaultBehavior'; + } +} diff --git a/core/lib/Thelia/Form/Lang/LangUpdateForm.php b/core/lib/Thelia/Form/Lang/LangUpdateForm.php new file mode 100644 index 00000000..b0bd9120 --- /dev/null +++ b/core/lib/Thelia/Form/Lang/LangUpdateForm.php @@ -0,0 +1,42 @@ + + */ +class LangUpdateForm extends LangCreateForm +{ + public function buildForm() + { + parent::buildForm(); + + $this->formBuilder + ->add('id', 'hidden', array( + 'constraints' => array( + new NotBlank(), + new GreaterThan(array('value' => 0)), + ), + )); + } + + public function getName() + { + return 'thelia_lang_update'; + } +} diff --git a/core/lib/Thelia/Form/Lang/LangUrlEvent.php b/core/lib/Thelia/Form/Lang/LangUrlEvent.php new file mode 100644 index 00000000..292af23a --- /dev/null +++ b/core/lib/Thelia/Form/Lang/LangUrlEvent.php @@ -0,0 +1,35 @@ + + */ +class LangUrlEvent extends ActionEvent +{ + protected $url = array(); + + public function addUrl($id, $url) + { + $this->url[$id] = $url; + } + + public function getUrl() + { + return $this->url; + } +} diff --git a/core/lib/Thelia/Form/Lang/LangUrlForm.php b/core/lib/Thelia/Form/Lang/LangUrlForm.php new file mode 100644 index 00000000..06c7f07a --- /dev/null +++ b/core/lib/Thelia/Form/Lang/LangUrlForm.php @@ -0,0 +1,76 @@ + + */ +class LangUrlForm extends BaseForm +{ + const LANG_PREFIX = 'url_'; + + /** + * + * in this function you add all the fields you need for your Form. + * Form this you have to call add method on $this->formBuilder attribute : + * + * $this->formBuilder->add("name", "text") + * ->add("email", "email", array( + * "attr" => array( + * "class" => "field" + * ), + * "label" => "email", + * "constraints" => array( + * new \Symfony\Component\Validator\Constraints\NotBlank() + * ) + * ) + * ) + * ->add('age', 'integer'); + * + * @return null + */ + protected function buildForm() + { + foreach (LangQuery::create()->find() as $lang) { + $this->formBuilder->add( + self::LANG_PREFIX.$lang->getId(), + 'text', + array( + 'constraints' => array( + new NotBlank(), + ), + "attr" => array( + "tag" => "url", + "url_id" => $lang->getId(), + "url_title" => $lang->getTitle(), + ), + + ) + ); + } + } + + /** + * @return string the name of you form. This name must be unique + */ + public function getName() + { + return 'thelia_language_url'; + } +} diff --git a/core/lib/Thelia/Form/MailingSystemModificationForm.php b/core/lib/Thelia/Form/MailingSystemModificationForm.php new file mode 100644 index 00000000..456afd8b --- /dev/null +++ b/core/lib/Thelia/Form/MailingSystemModificationForm.php @@ -0,0 +1,95 @@ + + */ +class MailingSystemModificationForm extends BaseForm +{ + protected function buildForm() + { + $this->formBuilder + ->add("enabled", "checkbox", array( + "required" => false, + "label" => Translator::getInstance()->trans("Enable remote SMTP use"), + "label_attr" => array("for" => "enabled_field"), + )) + ->add("host", "text", array( + "required" => false, + "label" => Translator::getInstance()->trans("Host"), + "label_attr" => array("for" => "host_field"), + )) + ->add("port", "text", array( + "required" => false, + "label" => Translator::getInstance()->trans("Port"), + "label_attr" => array("for" => "port_field"), + )) + ->add("encryption", "text", array( + "required" => false, + "label" => Translator::getInstance()->trans("Encryption"), + "label_attr" => array( + "for" => "encryption_field", + "help" => Translator::getInstance()->trans("ssl, tls or empty"), + ), + )) + ->add("username", "text", array( + "required" => false, + "label" => Translator::getInstance()->trans("Username"), + "label_attr" => array("for" => "username_field"), + )) + ->add("password", "text", array( + "required" => false, + "label" => Translator::getInstance()->trans("Password"), + "label_attr" => array("for" => "password_field"), + )) + ->add("authmode", "text", array( + "required" => false, + "label" => Translator::getInstance()->trans("Auth mode"), + "label_attr" => array( + "for" => "authmode_field", + "help" => Translator::getInstance()->trans("plain, login, cram-md5 or empty"), + ), + )) + ->add("timeout", "text", array( + "required" => false, + "label" => Translator::getInstance()->trans("Timeout"), + "label_attr" => array("for" => "timeout_field"), + )) + ->add("sourceip", "text", array( + "required" => false, + "label" => Translator::getInstance()->trans("Source IP"), + "label_attr" => array("for" => "sourceip_field"), + )) + ; + } + + public function getName() + { + return "thelia_mailing_system_modification"; + } + + /*public function verifyCode($value, ExecutionContextInterface $context) + { + $profile = ProfileQuery::create() + ->findOneByCode($value); + + if (null !== $profile) { + $context->addViolation("Profile `code` already exists"); + } + }*/ +} diff --git a/core/lib/Thelia/Form/MessageCreationForm.php b/core/lib/Thelia/Form/MessageCreationForm.php new file mode 100644 index 00000000..30eb6da1 --- /dev/null +++ b/core/lib/Thelia/Form/MessageCreationForm.php @@ -0,0 +1,80 @@ +formBuilder + ->add("name", "text", array( + "constraints" => array( + new Constraints\NotBlank(), + new Constraints\Callback(array( + "methods" => array(array($this, "checkDuplicateName")), + )) + ), + "label" => Translator::getInstance()->trans('Name'), + "label_attr" => array( + "for" => "name", + 'help' => Translator::getInstance()->trans("This is an identifier that will be used in the code to get this message"), + ), + 'attr' => [ + 'placeholder' => Translator::getInstance()->trans("Mail template name"), + ], + )) + ->add("title", "text", array( + "constraints" => array( + new Constraints\NotBlank(), + ), + "label" => Translator::getInstance()->trans('Purpose'), + "label_attr" => array( + "for" => "purpose", + 'help' => Translator::getInstance()->trans( + "Enter here the mail template purpose in the default language (%title%)", + [ '%title%' => Lang::getDefaultLanguage()->getTitle() ] + ), + ), + 'attr' => [ + 'placeholder' => Translator::getInstance()->trans("Mail template purpose"), + ], + )) + ->add("locale", "hidden", array( + "constraints" => array( + new Constraints\NotBlank(), + ), + )) + ->add("secured", "hidden", array()) + ; + } + + public function getName() + { + return "thelia_message_creation"; + } + + public function checkDuplicateName($value, ExecutionContextInterface $context) + { + $message = MessageQuery::create()->findOneByName($value); + + if ($message) { + $context->addViolation(Translator::getInstance()->trans('A message with name "%name" already exists.', array('%name' => $value))); + } + } +} diff --git a/core/lib/Thelia/Form/MessageModificationForm.php b/core/lib/Thelia/Form/MessageModificationForm.php new file mode 100644 index 00000000..f99eed87 --- /dev/null +++ b/core/lib/Thelia/Form/MessageModificationForm.php @@ -0,0 +1,138 @@ +formBuilder + ->add("id", "hidden", array( + "constraints" => array( + new GreaterThan(array('value' => 0)) + ) + )) + + ->add("name", "text", array( + "constraints" => array(new NotBlank()), + "label" => Translator::getInstance()->trans('Name'), + "label_attr" => array( + "for" => "name", + "help" => Translator::getInstance()->trans('This the unique name of this message. Do not change this value unless you understand what you do.'), + ), + 'attr' => [ + "placeholder" => Translator::getInstance()->trans('Message name'), + ], + )) + /*->add("secured" , "checkbox" , array( + "constraints" => array(new Type([ 'type' => 'bool'])), + 'required' => false, + "label" => Translator::getInstance()->trans('Prevent mailing template modification or deletion, except for super-admin') + ))*/ + + // The "secured" function is useless, as all mails are required for the system to work. + // Define all messages as not secured. + ->add("secured", "hidden", array( + "constraints" => array(new Type([ 'type' => 'bool'])), + 'required' => false, + 'data' => false, + )) + + ->add("locale", "hidden", array()) + + ->add("title", "text", array( + "constraints" => array(new NotBlank()), + "label" => Translator::getInstance()->trans('Title'), + "label_attr" => array( + "for" => "title", + "help" => Translator::getInstance()->trans("This is the message purpose, such as 'Order confirmation'."), + ), + 'attr' => [ + "placeholder" => Translator::getInstance()->trans('Title'), + ], + )) + + ->add("subject", "text", array( + "constraints" => array(new NotBlank()), + "label" => Translator::getInstance()->trans('Message subject'), + "label_attr" => array( + "for" => "subject", + "help" => Translator::getInstance()->trans("This is the subject of the e-mail, such as 'Your order is confirmed'."), + ), + 'attr' => [ + "placeholder" => Translator::getInstance()->trans('Message subject'), + ], + )) + + ->add("html_message", "text", array( + "label" => Translator::getInstance()->trans('HTML Message'), + "label_attr" => array( + "for" => "html_message", + "help" => Translator::getInstance()->trans("The mailing template in HTML format."), + ), + "required" => false, + )) + + ->add("text_message", "textarea", array( + "label" => Translator::getInstance()->trans('Text Message'), + "label_attr" => array( + "for" => "text_message", + "help" => Translator::getInstance()->trans("The mailing template in text-only format."), + ), + 'required' => false, + )) + + ->add("html_layout_file_name", "text", array( + "label" => Translator::getInstance()->trans('Name of the HTML layout file'), + "label_attr" => array( + "for" => "html_layout_file_name", + ), + "required" => false, + )) + + ->add("html_template_file_name", "text", array( + "label" => Translator::getInstance()->trans('Name of the HTML template file'), + "label_attr" => array( + "for" => "html_template_file_name", + ), + "required" => false, + )) + + ->add("text_layout_file_name", "text", array( + "label" => Translator::getInstance()->trans('Name of the text layout file'), + "label_attr" => array( + "for" => "text_layout_file_name", + ), + "required" => false, + )) + + ->add("text_template_file_name", "text", array( + "label" => Translator::getInstance()->trans('Name of the text template file'), + "label_attr" => array( + "for" => "text_template_file_name", + ), + "required" => false, + )) + ; + } +} diff --git a/core/lib/Thelia/Form/MessageSendSampleForm.php b/core/lib/Thelia/Form/MessageSendSampleForm.php new file mode 100644 index 00000000..444d6921 --- /dev/null +++ b/core/lib/Thelia/Form/MessageSendSampleForm.php @@ -0,0 +1,41 @@ +formBuilder + ->add( + "recipient_email", + "email", + [ + "constraints" => array(new NotBlank()), + "label" => Translator::getInstance()->trans('Send test e-mail to:'), + "attr" => [ + 'placeholder' => Translator::getInstance()->trans('Recipient e-mail address') + ] + ] + ); + ; + } +} diff --git a/core/lib/Thelia/Form/ModuleHookCreationForm.php b/core/lib/Thelia/Form/ModuleHookCreationForm.php new file mode 100644 index 00000000..146b3c81 --- /dev/null +++ b/core/lib/Thelia/Form/ModuleHookCreationForm.php @@ -0,0 +1,245 @@ + + */ +class ModuleHookCreationForm extends BaseForm +{ + /** @var Translator */ + protected $translator; + + protected function buildForm() + { + $this->formBuilder + ->add( + "module_id", + "choice", + array( + "choices" => $this->getModuleChoices(), + "constraints" => array( + new NotBlank(), + ), + "label" => $this->trans("Module"), + "label_attr" => array( + "for" => "module_id", + "help" => $this->trans( + "Only hookable modules are displayed in this menu." + ), + ), + ) + ) + ->add( + "hook_id", + "choice", + array( + "choices" => $this->getHookChoices(), + "constraints" => array( + new NotBlank(), + ), + "label" => $this->trans("Hook"), + "label_attr" => array("for" => "hook_id"), + ) + ) + ->add( + "classname", + "text", + array( + "constraints" => array( + new NotBlank(), + ), + "label" => $this->trans("Service ID"), + "label_attr" => array( + "for" => "classname", + "help" => $this->trans( + "The service id that will handle the hook (defined in the config.xml file of the module)." + ), + ), + ) + ) + ->add( + "method", + "text", + array( + "label" => $this->trans("Method Name"), + "constraints" => array( + new NotBlank(), + new Callback( + array( + "methods" => array( + array($this, "verifyMethod"), + ), + ) + ), + ), + "label_attr" => array( + "for" => "method", + "help" => $this->trans( + "The method name that will handle the hook event." + ), + ), + ) + ) + ->add( + "templates", + "text", + array( + "label" => $this->trans("Automatic rendered templates"), + "constraints" => array( + new Callback( + array( + "methods" => array( + array($this, "verifyTemplates"), + ), + ) + ), + ), + "label_attr" => array( + "for" => "templates", + "help" => $this->trans( + "When using the %method% method you can automatically render or dump templates or add CSS and JS files (e.g.: render:mytemplate.html;js:assets/js/myjs.js)", + ["%method%" => BaseHook::INJECT_TEMPLATE_METHOD_NAME] + ), + ), + "required" => false + ) + ) + ; + } + + protected function trans($id, $parameters = []) + { + if (null === $this->translator) { + $this->translator = Translator::getInstance(); + } + + return $this->translator->trans($id, $parameters); + } + + protected function getModuleChoices() + { + $choices = array(); + $modules = ModuleQuery::getActivated(); + + /** @var Module $module */ + foreach ($modules as $module) { + // Check if module defines a hook ID + if (ModuleHookQuery::create()->filterByModuleId($module->getId())->count() > 0 + || + IgnoredModuleHookQuery::create()->filterByModuleId($module->getId())->count() > 0 + ) { + $choices[$module->getId()] = $module->getTitle(); + } + } + + asort($choices); + + return $choices; + } + + protected function getHookChoices() + { + $choices = array(); + $hooks = HookQuery::create() + ->filterByActivate(true, Criteria::EQUAL) + ->joinWithI18n($this->translator->getLocale()) + ->orderBy('HookI18n.title', Criteria::ASC) + ->find(); + + /** @var Hook $hook */ + foreach ($hooks as $hook) { + $choices[$hook->getId()] = $hook->getTitle().' (code '.$hook->getCode().')'; + } + + return $choices; + } + + /** + * + * Check if method has a valid signature. + * See RegisterListenersPass::isValidHookMethod for implementing this verification + * + * @param $value + * @param ExecutionContextInterface $context + * @return bool + */ + public function verifyMethod($value, ExecutionContextInterface $context) + { + if (! $this->hasContainer()) { + return true; + } + + $data = $context->getRoot()->getData(); + + if (null === $service = $this->container->get($data["classname"])) { + return true; + } + + if (!method_exists($service, $data['method'])) { + $context->addViolation( + $this->trans( + "The method %method% doesn't exist in classname %classname%", + [ + '%method%' => $data['method'], + '%classname%' => $data['classname'] + ] + ) + ); + } + } + + /** + * Check if method is the right one if we want to use automatic inserted templates . + * + * @param $value + * @param ExecutionContextInterface $context + * + * @return bool + */ + public function verifyTemplates($value, ExecutionContextInterface $context) + { + $data = $context->getRoot()->getData(); + + if (!empty($data['templates']) && $data['method'] !== BaseHook::INJECT_TEMPLATE_METHOD_NAME) { + $context->addViolation( + $this->trans( + "If you use automatic insert templates, you should use the method %method%", + [ + '%method%' => BaseHook::INJECT_TEMPLATE_METHOD_NAME + ] + ) + ); + } + } + + public function getName() + { + return "thelia_module_hook_creation"; + } +} diff --git a/core/lib/Thelia/Form/ModuleHookModificationForm.php b/core/lib/Thelia/Form/ModuleHookModificationForm.php new file mode 100644 index 00000000..50337c9a --- /dev/null +++ b/core/lib/Thelia/Form/ModuleHookModificationForm.php @@ -0,0 +1,45 @@ + + */ +class ModuleHookModificationForm extends ModuleHookCreationForm +{ + protected function buildForm() + { + parent::buildForm(); + + $this->formBuilder + ->add("id", "hidden", array("constraints" => array(new GreaterThan(array('value' => 0))))) + ->add("active", "checkbox", array( + "label" => Translator::getInstance()->trans("Active"), + "required" => false, + "label_attr" => array( + "for" => "active", + ), + )) + ; + } + + public function getName() + { + return "thelia_module_hook_modification"; + } +} diff --git a/core/lib/Thelia/Form/ModuleImageModification.php b/core/lib/Thelia/Form/ModuleImageModification.php new file mode 100644 index 00000000..1c9f3ff6 --- /dev/null +++ b/core/lib/Thelia/Form/ModuleImageModification.php @@ -0,0 +1,29 @@ + + */ +class ModuleInstallForm extends BaseForm +{ + /** @var ModuleDefinition */ + protected $moduleDefinition = null; + + protected $modulePath = null; + + protected function buildForm() + { + $this->formBuilder + ->add( + 'module', + 'file', + [ + 'required' => true, + 'constraints' => [ + new Constraints\File( + [ + 'mimeTypes' => [ + 'application/zip', + ], + 'mimeTypesMessage' => Translator::getInstance()->trans('Please upload a valid Zip file'), + ] + ), + new Constraints\Callback([ + "methods" => [ + [$this, "checkModuleValidity"], + ], + ]), + ], + 'label' => Translator::getInstance()->trans('The module zip file'), + 'label_attr' => [ + 'for' => 'module', + ] + ] + ); + } + + /** + * Check module validity + * + * @param UploadedFile $file + * @param ExecutionContextInterface $context + */ + public function checkModuleValidity(UploadedFile $file, ExecutionContextInterface $context) + { + $modulePath = $this->unzipModule($file); + + if ($modulePath !== false) { + try { + // get the first directory + $moduleFiles = $this->getDirContents($modulePath); + if (\count($moduleFiles['directories']) !== 1) { + throw new Exception( + Translator::getInstance()->trans( + "Your zip must contain 1 root directory which is the root folder directory of your module" + ) + ); + } + + $moduleDirectory = $moduleFiles['directories'][0]; + + $this->modulePath = sprintf('%s/%s', $modulePath, $moduleDirectory); + + $moduleValidator = new ModuleValidator($this->modulePath); + + $moduleValidator->validate(); + + $this->moduleDefinition = $moduleValidator->getModuleDefinition(); + } catch (Exception $ex) { + $context->addViolation( + Translator::getInstance()->trans( + "The module is not valid : %message", + ['%message' => $ex->getMessage()] + ) + ); + } + } + } + + public function getModuleDefinition() + { + return $this->moduleDefinition; + } + + /** + * @return string|null + */ + public function getModulePath() + { + return $this->modulePath; + } + + /** + * Unzip a module file. + * + * @param UploadedFile $file + * + * @return string|bool the path where the module has been extracted or false if an error has occured + */ + protected function unzipModule(UploadedFile $file) + { + $extractPath = false; + $zip = new ZipArchiver(true); + if (!$zip->open($file->getRealPath())) { + throw new \Exception("unable to open zipfile"); + } + + $extractPath = $this->tempdir(); + + if ($extractPath !== false) { + if ($zip->extract($extractPath) === false) { + $extractPath = false; + } + } + + $zip->close(); + + return $extractPath; + } + + /** + * create a unique directory. + * + * @return bool|string the directory path or false if it fails + */ + protected function tempdir() + { + $tempfile = tempnam(sys_get_temp_dir(), ''); + if (file_exists($tempfile)) { + unlink($tempfile); + } + mkdir($tempfile); + if (is_dir($tempfile)) { + return $tempfile; + } + + return false; + } + + protected function getDirContents($dir) + { + $paths = array_diff(scandir($dir), ['..', '.']); + + $out = [ + 'directories' => [], + 'files' => [], + ]; + + foreach ($paths as $path) { + if (is_dir($dir.DS.$path)) { + $out['directories'][] = $path; + } else { + $out['files'][] = $path; + } + } + + return $out; + } + + public function getName() + { + return "module_install"; + } +} diff --git a/core/lib/Thelia/Form/ModuleModificationForm.php b/core/lib/Thelia/Form/ModuleModificationForm.php new file mode 100644 index 00000000..eb871921 --- /dev/null +++ b/core/lib/Thelia/Form/ModuleModificationForm.php @@ -0,0 +1,65 @@ +addStandardDescFields(); + + $this->formBuilder + ->add("id", "hidden", array( + "required" => true, + "constraints" => array( + new Constraints\NotBlank(), + new Constraints\Callback( + array( + "methods" => array( + array($this, "verifyModuleId"), + ), + ) + ), + ), + "attr" => array( + "id" => "module_update_id", + ), + )) + ; + } + + /** + * @return string the name of you form. This name must be unique + */ + public function getName() + { + return "thelia_admin_module_modification"; + } + + public function verifyModuleId($value, ExecutionContextInterface $context) + { + $module = ModuleQuery::create() + ->findPk($value); + + if (null === $module) { + $context->addViolation(Translator::getInstance()->trans("Module ID not found")); + } + } +} diff --git a/core/lib/Thelia/Form/NewsletterForm.php b/core/lib/Thelia/Form/NewsletterForm.php new file mode 100644 index 00000000..f3effb62 --- /dev/null +++ b/core/lib/Thelia/Form/NewsletterForm.php @@ -0,0 +1,97 @@ + + */ +class NewsletterForm extends BaseForm +{ + /** + * + * in this function you add all the fields you need for your Form. + * Form this you have to call add method on $this->formBuilder attribute : + * + * $this->formBuilder->add("name", "text") + * ->add("email", "email", array( + * "attr" => array( + * "class" => "field" + * ), + * "label" => "email", + * "constraints" => array( + * new \Symfony\Component\Validator\Constraints\NotBlank() + * ) + * ) + * ) + * ->add('age', 'integer'); + * + * @return null + */ + protected function buildForm() + { + $this->formBuilder + ->add('email', 'email', array( + 'constraints' => array( + new NotBlank(), + new Email(), + new Callback(array( + "methods" => array( + array($this, + "verifyExistingEmail", ), + ), + )), + ), + 'label' => Translator::getInstance()->trans('Email address'), + 'label_attr' => array( + 'for' => 'email_newsletter', + ), + )) + ->add('firstname', 'text', array( + 'label' => Translator::getInstance()->trans('Firstname'), + 'label_attr' => array( + 'for' => 'firstname_newsletter', + ), + )) + ->add('lastname', 'text', array( + 'label' => Translator::getInstance()->trans('Lastname'), + 'label_attr' => array( + 'for' => 'lastname_newsletter', + ), + )); + } + + public function verifyExistingEmail($value, ExecutionContextInterface $context) + { + $customer = NewsletterQuery::create()->filterByUnsubscribed(false)->findOneByEmail($value); + if ($customer) { + $context->addViolation(Translator::getInstance()->trans("You are already registered!")); + } + } + + /** + * @return string the name of you form. This name must be unique + */ + public function getName() + { + return 'thelia_newsletter'; + } +} diff --git a/core/lib/Thelia/Form/NewsletterUnsubscribeForm.php b/core/lib/Thelia/Form/NewsletterUnsubscribeForm.php new file mode 100644 index 00000000..2c1383f0 --- /dev/null +++ b/core/lib/Thelia/Form/NewsletterUnsubscribeForm.php @@ -0,0 +1,62 @@ + + */ +class NewsletterUnsubscribeForm extends BaseForm +{ + protected function buildForm() + { + $this->formBuilder + ->add('email', 'email', array( + 'constraints' => array( + new NotBlank(), + new Email(), + new Callback(array( + "methods" => array( + array($this, + "verifyExistingEmail", ), + ), + )), + ), + 'label' => Translator::getInstance()->trans('Email address'), + 'label_attr' => array( + 'for' => 'email_newsletter', + ), + )) + ; + } + + public function verifyExistingEmail($value, ExecutionContextInterface $context) + { + if (null === NewsletterQuery::create()->filterByUnsubscribed(false)->findOneByEmail($value)) { + $context->addViolation( + Translator::getInstance()->trans( + "The email address \"%mail\" was not found.", + [ '%mail' => $value ] + ) + ); + } + } +} diff --git a/core/lib/Thelia/Form/OrderDelivery.php b/core/lib/Thelia/Form/OrderDelivery.php new file mode 100644 index 00000000..6d0e993e --- /dev/null +++ b/core/lib/Thelia/Form/OrderDelivery.php @@ -0,0 +1,85 @@ + + */ +class OrderDelivery extends BaseForm +{ + protected function buildForm() + { + $this->formBuilder + ->add("delivery-address", "integer", array( + "required" => true, + "constraints" => array( + new Constraints\NotBlank(), + new Constraints\Callback(array( + "methods" => array( + array($this, "verifyDeliveryAddress"), + ), + )), + ), + )) + ->add("delivery-module", "integer", array( + "required" => true, + "constraints" => array( + new Constraints\NotBlank(), + new Constraints\Callback(array( + "methods" => array( + array($this, "verifyDeliveryModule"), + ), + )), + ), + )); + } + + public function verifyDeliveryAddress($value, ExecutionContextInterface $context) + { + $address = AddressQuery::create() + ->findPk($value); + + if (null === $address) { + $context->addViolation(Translator::getInstance()->trans("Address ID not found")); + } + } + + public function verifyDeliveryModule($value, ExecutionContextInterface $context) + { + $module = ModuleQuery::create() + ->filterActivatedByTypeAndId(BaseModule::DELIVERY_MODULE_TYPE, $value) + ->findOne(); + + if (null === $module) { + $context->addViolation(Translator::getInstance()->trans("Delivery module ID not found")); + } elseif (! $module->isDeliveryModule()) { + $context->addViolation( + sprintf(Translator::getInstance()->trans("delivery module %s is not a Thelia\Module\DeliveryModuleInterface"), $module->getCode()) + ); + } + } + + public function getName() + { + return "thelia_order_delivery"; + } +} diff --git a/core/lib/Thelia/Form/OrderPayment.php b/core/lib/Thelia/Form/OrderPayment.php new file mode 100644 index 00000000..5258a94a --- /dev/null +++ b/core/lib/Thelia/Form/OrderPayment.php @@ -0,0 +1,95 @@ + + */ +class OrderPayment extends FirewallForm +{ + protected function buildForm() + { + $this->formBuilder + ->add("invoice-address", "integer", array( + "required" => true, + "constraints" => array( + new Constraints\NotBlank(), + new Constraints\Callback(array( + "methods" => array( + array($this, "verifyInvoiceAddress"), + ), + )), + ), + )) + ->add("payment-module", "integer", array( + "required" => true, + "constraints" => array( + new Constraints\NotBlank(), + new Constraints\Callback(array( + "methods" => array( + array($this, "verifyPaymentModule"), + ), + )), + ), + )) + // Add terms & conditions + ->add("agreed", "checkbox", array( + "constraints" => array( + new Constraints\IsTrue(array("message" => Translator::getInstance()->trans("Please accept the Terms and conditions in order to register."))), + ), + "label" => "Agreed", + "label_attr" => array( + "for" => "agreed", + ), + )); + } + + public function verifyInvoiceAddress($value, ExecutionContextInterface $context) + { + $address = AddressQuery::create() + ->findPk($value); + + if (null === $address) { + $context->addViolation(Translator::getInstance()->trans("Address ID not found")); + } + } + + public function verifyPaymentModule($value, ExecutionContextInterface $context) + { + $module = ModuleQuery::create() + ->filterActivatedByTypeAndId(BaseModule::PAYMENT_MODULE_TYPE, $value) + ->findOne(); + + if (null === $module) { + $context->addViolation(Translator::getInstance()->trans("Payment module ID not found")); + } elseif (! $module->isPayementModule()) { + $context->addViolation( + sprintf(Translator::getInstance()->trans("payment module %s is not a Thelia\Module\PaymentModuleInterface"), $module->getCode()) + ); + } + } + + public function getName() + { + return "thelia_order_payment"; + } +} diff --git a/core/lib/Thelia/Form/OrderStatus/OrderStatusCreationForm.php b/core/lib/Thelia/Form/OrderStatus/OrderStatusCreationForm.php new file mode 100644 index 00000000..f3f4efa0 --- /dev/null +++ b/core/lib/Thelia/Form/OrderStatus/OrderStatusCreationForm.php @@ -0,0 +1,157 @@ + + * @since 2.4 + */ +class OrderStatusCreationForm extends BaseForm +{ + use StandardDescriptionFieldsTrait; + + protected function buildForm() + { + $this->formBuilder + ->add( + 'title', + 'text', + [ + 'constraints' => [ new NotBlank() ], + 'required' => true, + 'label' => Translator::getInstance()->trans('Order status name'), + 'label_attr' => [ + 'for' => 'title', + 'help' => Translator::getInstance()->trans( + 'Enter here the order status name in the default language (%title%)', + [ '%title%' => Lang::getDefaultLanguage()->getTitle()] + ), + ], + 'attr' => [ + 'placeholder' => Translator::getInstance()->trans('The order status name or title'), + ] + ] + ) + ->add( + 'code', + 'text', + [ + 'constraints' => [ + new Callback([ + 'methods' => [ + [$this, 'checkUniqueCode'], + [$this, 'checkFormatCode'], + [$this, 'checkIsRequiredCode'] + ] + ]) + ], + 'required' => true, + 'label' => Translator::getInstance()->trans('Order status code'), + 'label_attr' => [ + 'for' => 'title', + 'help' => Translator::getInstance()->trans('Enter here the order status code'), + ], + 'attr' => [ + 'placeholder' => Translator::getInstance()->trans('The order status code'), + ] + ] + ) + ->add( + 'color', + 'text', + [ + 'constraints' => [ + new NotBlank(), + new Callback([ + 'methods' => [[$this, 'checkColor']] + ]) + ], + 'required' => false, + 'label' => Translator::getInstance()->trans('Order status color'), + 'label_attr' => [ + 'for' => 'title', + 'help' => Translator::getInstance()->trans('Choice a color for this order status code'), + ], + 'attr' => [ + 'placeholder' => Translator::getInstance()->trans('#000000'), + ] + ] + ); + + $this->addStandardDescFields(['title', 'description', 'chapo', 'postscriptum']); + } + + public function getName() + { + return 'thelia_order_status_creation'; + } + + public function checkColor($value, ExecutionContextInterface $context) + { + if (!preg_match("/^#[0-9a-fA-F]{6}$/", $value)) { + $context->addViolation( + Translator::getInstance()->trans("This is not a hexadecimal color.") + ); + } + } + + public function checkUniqueCode($value, ExecutionContextInterface $context) + { + $query = OrderStatusQuery::create() + ->filterByCode($value); + + if ($this->form->has('id')) { + $query->filterById($this->form->get('id')->getData(), Criteria::NOT_EQUAL); + } + + if ($query->findOne()) { + $context->addViolation( + Translator::getInstance()->trans("This code is already used.") + ); + } + } + + public function checkFormatCode($value, ExecutionContextInterface $context) + { + if (!empty($value) && !preg_match('/^\w+$/', $value)) { + $context->addViolation( + Translator::getInstance()->trans("This is not a valid code.") + ); + } + } + + public function checkIsRequiredCode($value, ExecutionContextInterface $context) + { + if ($this->form->has('id')) { + if (null !== $orderStatus = OrderStatusQuery::create()->findOneById($this->form->get('id')->getData())) { + if (!$orderStatus->getProtectedStatus() && empty($this->form->get('code')->getData())) { + $context->addViolation( + Translator::getInstance()->trans("This value should not be blank.") + ); + } + } + } + } +} diff --git a/core/lib/Thelia/Form/OrderStatus/OrderStatusModificationForm.php b/core/lib/Thelia/Form/OrderStatus/OrderStatusModificationForm.php new file mode 100644 index 00000000..044e74d4 --- /dev/null +++ b/core/lib/Thelia/Form/OrderStatus/OrderStatusModificationForm.php @@ -0,0 +1,43 @@ + + * @since 2.4 + */ +class OrderStatusModificationForm extends OrderStatusCreationForm +{ + protected function buildForm() + { + $this->formBuilder->add("id", "hidden", [ + 'required' => true, + "constraints" => [ + new GreaterThan(['value' => 0]) + ] + ]); + + parent::buildForm(); + + $this->addStandardDescFields(); + } + + public function getName() + { + return 'thelia_order_status_modification'; + } +} diff --git a/core/lib/Thelia/Form/OrderUpdateAddress.php b/core/lib/Thelia/Form/OrderUpdateAddress.php new file mode 100644 index 00000000..c2a7bee9 --- /dev/null +++ b/core/lib/Thelia/Form/OrderUpdateAddress.php @@ -0,0 +1,213 @@ + + */ +class OrderUpdateAddress extends BaseForm +{ + use AddressCountryValidationTrait; + + protected function buildForm() + { + $this->formBuilder + ->add("id", "integer", array( + "constraints" => array( + new NotBlank(), + new Callback(array( + "methods" => array( + array($this, "verifyId"), + ), + )), + ), + "required" => true, + )) + ->add("title", "text", array( + "constraints" => array( + new NotBlank(), + new Callback(array( + "methods" => array( + array($this, "verifyTitle"), + ), + )), + ), + "label" => Translator::getInstance()->trans("Title"), + "label_attr" => array( + "for" => "title_update", + ), + )) + ->add("firstname", "text", array( + "constraints" => array( + new NotBlank(), + ), + "label" => Translator::getInstance()->trans("Firstname"), + "label_attr" => array( + "for" => "firstname_update", + ), + )) + ->add("lastname", "text", array( + "constraints" => array( + new NotBlank(), + ), + "label" => Translator::getInstance()->trans("Lastname"), + "label_attr" => array( + "for" => "lastname_update", + ), + )) + ->add("address1", "text", array( + "constraints" => array( + new NotBlank(), + ), + "label" => Translator::getInstance()->trans("Street Address"), + "label_attr" => array( + "for" => "address1_update", + ), + )) + ->add("address2", "text", array( + "required" => false, + "label" => Translator::getInstance()->trans("Additional address"), + "label_attr" => array( + "for" => "address2_update", + ), + )) + ->add("address3", "text", array( + "required" => false, + "label" => Translator::getInstance()->trans("Additional address"), + "label_attr" => array( + "for" => "address3_update", + ), + )) + ->add("zipcode", "text", array( + "constraints" => array( + new NotBlank(), + new Callback(array( + "methods" => array( + array($this, "verifyZipCode") + ), + )), + ), + "label" => Translator::getInstance()->trans("Zip code"), + "label_attr" => array( + "for" => "zipcode_update", + ), + )) + ->add("city", "text", array( + "constraints" => array( + new NotBlank(), + ), + "label" => Translator::getInstance()->trans("City"), + "label_attr" => array( + "for" => "city_update", + ), + )) + ->add("country", "text", array( + "constraints" => array( + new NotBlank(), + new Callback(array( + "methods" => array( + array($this, "verifyCountry"), + ), + )), + ), + "label" => Translator::getInstance()->trans("Country"), + "label_attr" => array( + "for" => "country_update", + ), + )) + ->add("state", "text", array( + "required" => false, + "constraints" => array( + new Callback(array( + "methods" => array( + array($this, "verifyState") + ), + )), + ), + "label" => Translator::getInstance()->trans("State *"), + "label_attr" => array( + "for" => "state", + ), + )) + ->add("phone", "text", array( + "required" => false, + "label" => Translator::getInstance()->trans("Phone"), + "label_attr" => array( + "for" => "phone_update", + ), + )) + ->add("cellphone", "text", array( + "required" => false, + "label" => Translator::getInstance()->trans("Cellphone"), + "label_attr" => array( + "for" => "cellphone_update", + ), + )) + ->add("company", "text", array( + "required" => false, + "label" => Translator::getInstance()->trans("Compagny"), + "label_attr" => array( + "for" => "company_update", + ), + )) + ; + } + + /** + * @return string the name of you form. This name must be unique + */ + public function getName() + { + return "thelia_order_address_update"; + } + + public function verifyId($value, ExecutionContextInterface $context) + { + $address = OrderAddressQuery::create() + ->findPk($value); + + if (null === $address) { + $context->addViolation(Translator::getInstance()->trans("Order address ID not found")); + } + } + + public function verifyTitle($value, ExecutionContextInterface $context) + { + $address = CustomerTitleQuery::create() + ->findPk($value); + + if (null === $address) { + $context->addViolation(Translator::getInstance()->trans("Title ID not found")); + } + } + + public function verifyCountry($value, ExecutionContextInterface $context) + { + $address = CountryQuery::create() + ->findPk($value); + + if (null === $address) { + $context->addViolation(Translator::getInstance()->trans("Country ID not found")); + } + } +} diff --git a/core/lib/Thelia/Form/ProductCloneForm.php b/core/lib/Thelia/Form/ProductCloneForm.php new file mode 100644 index 00000000..60c5fc6f --- /dev/null +++ b/core/lib/Thelia/Form/ProductCloneForm.php @@ -0,0 +1,57 @@ +formBuilder + ->add('productId', 'integer', [ + 'constraints' => [new NotBlank()] + ]) + ->add('newRef', 'text', [ + 'constraints' => [ + new NotBlank(), + new Callback([ + 'methods' => [[$this, 'checkRefDifferent']] + ]) + ], + 'label' => $this->translator->trans('Product reference (must be unique)'), + 'label_attr' => array('for' => 'newRef') + ]) + ; + } + + public function checkRefDifferent($value, ExecutionContextInterface $context) + { + $originalRef = ProductQuery::create() + ->filterByRef($value, Criteria::EQUAL) + ->count(); + + if ($originalRef !== 0) { + $context->addViolation($this->translator->trans('This product reference is already assigned to another product.')); + } + } +} diff --git a/core/lib/Thelia/Form/ProductCombinationGenerationForm.php b/core/lib/Thelia/Form/ProductCombinationGenerationForm.php new file mode 100644 index 00000000..88a924ff --- /dev/null +++ b/core/lib/Thelia/Form/ProductCombinationGenerationForm.php @@ -0,0 +1,97 @@ +formBuilder + ->add('product_id', 'integer', array( + 'label' => Translator::getInstance()->trans('Product ID'), + 'label_attr' => array('for' => 'combination_builder_id_field'), + 'constraints' => array(new GreaterThan(array('value' => 0))), + )) + ->add('currency', 'integer', array( + 'label' => Translator::getInstance()->trans('Price currency *'), + 'label_attr' => array('for' => 'combination_builder_currency_field'), + 'constraints' => array(new GreaterThan(array('value' => 0))), + )) + ->add('reference', 'text', array( + 'label' => Translator::getInstance()->trans('Reference'), + 'label_attr' => array('for' => 'combination_builder_reference_field'), + )) + ->add('price', 'number', array( + 'label' => Translator::getInstance()->trans('Product price excluding taxes'), + 'label_attr' => array('for' => 'combination_builder_price_field'), + )) + ->add('weight', 'number', array( + 'label' => Translator::getInstance()->trans('Weight'), + 'label_attr' => array('for' => 'combination_builder_weight_field'), + )) + ->add('quantity', 'number', array( + 'label' => Translator::getInstance()->trans('Available quantity'), + 'label_attr' => array('for' => 'combination_builder_quantity_field'), + )) + ->add('sale_price', 'number', array( + 'label' => Translator::getInstance()->trans('Sale price excluding taxes'), + 'label_attr' => array('for' => 'combination_builder_price_with_tax_field'), + )) + ->add('onsale', 'integer', array( + 'label' => Translator::getInstance()->trans('This product is on sale'), + 'label_attr' => array('for' => 'combination_builder_onsale_field'), + )) + ->add('isnew', 'integer', array( + 'label' => Translator::getInstance()->trans('Advertise this product as new'), + 'label_attr' => array('for' => 'combination_builder_isnew_field'), + )) + ->add('ean_code', 'text', array( + 'label' => Translator::getInstance()->trans('EAN Code'), + 'label_attr' => array('for' => 'combination_builder_ean_code_field'), + )) + ->add('attribute_av', 'collection', array( + 'type' => 'text', + 'label' => Translator::getInstance()->trans('Attribute ID:Attribute AV ID'), + 'label_attr' => array('for' => 'combination_builder_attribute_av_id'), + 'allow_add' => true, + 'allow_delete' => true, + "constraints" => array( + new Callback(array( + "methods" => array(array($this, "checkAttributeAv")), + )), + ) + )) + ; + } + + public function checkAttributeAv($value, ExecutionContextInterface $context) + { + if (empty($value)) { + $context->addViolation( + Translator::getInstance()->trans( + "You must select at least one attribute." + ) + ); + } + } + + public function getName() + { + return 'thelia_product_combination_generation_form'; + } +} diff --git a/core/lib/Thelia/Form/ProductCreationForm.php b/core/lib/Thelia/Form/ProductCreationForm.php new file mode 100644 index 00000000..6ff5dc9b --- /dev/null +++ b/core/lib/Thelia/Form/ProductCreationForm.php @@ -0,0 +1,121 @@ +doBuildForm(false); + } + + protected function doBuildForm($change_mode) + { + $this->formBuilder + ->add("ref", "text", array( + "constraints" => array( + new NotBlank(), + new Callback(array( + "methods" => array(array($this, "checkDuplicateRef")), + )), + ), + "label" => Translator::getInstance()->trans('Product reference *'), + "label_attr" => array("for" => "ref"), + )) + ->add("title", "text", array( + "constraints" => array(new NotBlank()), + "label" => Translator::getInstance()->trans('Product title'), + "label_attr" => array("for" => "title"), + )) + ->add("default_category", "integer", array( + "constraints" => array(new NotBlank()), + "label" => Translator::getInstance()->trans("Default product category *"), + "label_attr" => array("for" => "default_category_field"), + )) + ->add("locale", "text", array( + "constraints" => array(new NotBlank()), + )) + ->add("visible", "integer", array( + "label" => Translator::getInstance()->trans("This product is online"), + "label_attr" => array("for" => "visible_field"), + )) + ->add("virtual", "integer", array( + "label" => Translator::getInstance()->trans("This product does not have a physical presence"), + "label_attr" => array("for" => "virtual_field"), + )) + ; + + if (! $change_mode) { + $this->formBuilder + ->add("price", "number", array( + "constraints" => array(new NotBlank()), + "label" => Translator::getInstance()->trans("Product base price excluding taxes *"), + "label_attr" => array("for" => "price_without_tax"), + )) + ->add("tax_price", "number", array( + "label" => Translator::getInstance()->trans("Product base price with taxes"), + "label_attr" => array("for" => "price_with_tax"), + )) + ->add("currency", "integer", array( + "constraints" => array(new NotBlank()), + "label" => Translator::getInstance()->trans("Price currency *"), + "label_attr" => array("for" => "currency_field"), + )) + ->add("tax_rule", "integer", array( + "constraints" => array(new NotBlank()), + "label" => Translator::getInstance()->trans("Tax rule for this product *"), + "label_attr" => array("for" => "tax_rule_field"), + )) + ->add("weight", "number", array( + "label" => Translator::getInstance()->trans("Weight"), + "label_attr" => array("for" => "weight_field"), + )) + ->add("quantity", "number", array( + "label" => Translator::getInstance()->trans("Stock"), + "label_attr" => array("for" => "quantity_field"), + "required" => false + )) + ->add("template_id", "integer", array( + "label" => Translator::getInstance()->trans("Template"), + "label_attr" => array("for" => "template_field"), + "required" => false + )) + ; + } + } + + public function checkDuplicateRef($value, ExecutionContextInterface $context) + { + $count = ProductQuery::create()->filterByRef($value)->count(); + + if ($count > 0) { + $context->addViolation( + Translator::getInstance()->trans( + "A product with reference %ref already exists. Please choose another reference.", + array('%ref' => $value) + ) + ); + } + } + + public function getName() + { + return "thelia_product_creation"; + } +} diff --git a/core/lib/Thelia/Form/ProductDefaultSaleElementUpdateForm.php b/core/lib/Thelia/Form/ProductDefaultSaleElementUpdateForm.php new file mode 100644 index 00000000..7270f238 --- /dev/null +++ b/core/lib/Thelia/Form/ProductDefaultSaleElementUpdateForm.php @@ -0,0 +1,101 @@ +formBuilder + ->add("product_id", "integer", array( + "label" => Translator::getInstance()->trans("Product ID *"), + "label_attr" => array("for" => "product_id_field"), + "constraints" => array(new GreaterThan(array('value' => 0))), + )) + ->add("product_sale_element_id", "integer", array( + "label" => Translator::getInstance()->trans("Product sale element ID *"), + "label_attr" => array("for" => "product_sale_element_id_field"), + )) + ->add("reference", "text", array( + "label" => Translator::getInstance()->trans("Reference *"), + "label_attr" => array("for" => "reference_field"), + )) + ->add("price", "number", array( + "constraints" => array(new NotBlank()), + "label" => Translator::getInstance()->trans("Product price excluding taxes *"), + "label_attr" => array("for" => "price_field"), + )) + ->add("price_with_tax", "number", array( + "label" => Translator::getInstance()->trans("Product price including taxes"), + "label_attr" => array("for" => "price_with_tax_field"), + )) + ->add("currency", "integer", array( + "constraints" => array(new NotBlank()), + "label" => Translator::getInstance()->trans("Price currency *"), + "label_attr" => array("for" => "currency_field"), + )) + ->add("tax_rule", "integer", array( + "constraints" => array(new NotBlank()), + "label" => Translator::getInstance()->trans("Tax rule for this product *"), + "label_attr" => array("for" => "tax_rule_field"), + )) + ->add("weight", "number", array( + "label" => Translator::getInstance()->trans("Weight"), + "label_attr" => array("for" => "weight_field"), + )) + ->add("quantity", "number", array( + "constraints" => array(new NotBlank()), + "label" => Translator::getInstance()->trans("Available quantity *"), + "label_attr" => array("for" => "quantity_field"), + )) + ->add("sale_price", "number", array( + "label" => Translator::getInstance()->trans("Sale price excluding taxes"), + "label_attr" => array("for" => "price_with_tax_field"), + )) + ->add("sale_price_with_tax", "number", array( + "label" => Translator::getInstance()->trans("Sale price including taxes"), + "label_attr" => array("for" => "sale_price_with_tax_field"), + )) + ->add("onsale", "integer", array( + "label" => Translator::getInstance()->trans("This product is on sale"), + "label_attr" => array("for" => "onsale_field"), + )) + ->add("isnew", "integer", array( + "label" => Translator::getInstance()->trans("Advertise this product as new"), + "label_attr" => array("for" => "isnew_field"), + )) + ->add("isdefault", "integer", array( + "label" => Translator::getInstance()->trans("Is it the default product sale element ?"), + "label_attr" => array("for" => "isdefault_field"), + )) + ->add("ean_code", "text", array( + "label" => Translator::getInstance()->trans("EAN Code"), + "label_attr" => array("for" => "ean_code_field"), + )) + ->add("use_exchange_rate", "integer", array( + "label" => Translator::getInstance()->trans("Apply exchange rates on price in %sym", array("%sym" => Currency::getDefaultCurrency()->getSymbol())), + "label_attr" => array("for" => "use_exchange_rate_field"), + )) + ; + } + + public function getName() + { + return "thelia_product_default_sale_element_update_form"; + } +} diff --git a/core/lib/Thelia/Form/ProductDocumentModification.php b/core/lib/Thelia/Form/ProductDocumentModification.php new file mode 100644 index 00000000..f7476cf9 --- /dev/null +++ b/core/lib/Thelia/Form/ProductDocumentModification.php @@ -0,0 +1,40 @@ + + * + */ +class ProductDocumentModification extends DocumentModification +{ + /** + * Get form name + * This name must be unique + * + * @return string + */ + public function getName() + { + return 'thelia_product_document_modification'; + } +} diff --git a/core/lib/Thelia/Form/ProductImageModification.php b/core/lib/Thelia/Form/ProductImageModification.php new file mode 100644 index 00000000..25c261f7 --- /dev/null +++ b/core/lib/Thelia/Form/ProductImageModification.php @@ -0,0 +1,40 @@ + + * + */ +class ProductImageModification extends ImageModification +{ + /** + * Get form name + * This name must be unique + * + * @return string + */ + public function getName() + { + return 'thelia_product_image_modification'; + } +} diff --git a/core/lib/Thelia/Form/ProductModificationForm.php b/core/lib/Thelia/Form/ProductModificationForm.php new file mode 100644 index 00000000..2c7fa6f5 --- /dev/null +++ b/core/lib/Thelia/Form/ProductModificationForm.php @@ -0,0 +1,81 @@ +formBuilder + ->add("id", "integer", array( + "label" => Translator::getInstance()->trans("Prodcut ID *"), + "label_attr" => array("for" => "product_id_field"), + "constraints" => array(new GreaterThan(array('value' => 0))), + )) + ->add("template_id", "integer", array( + "label" => Translator::getInstance()->trans("Product template"), + "label_attr" => array("for" => "product_template_field"), + )) + ->add("brand_id", "integer", [ + 'constraints' => [ new NotBlank() ], + 'required' => true, + 'label' => Translator::getInstance()->trans('Brand / Supplier'), + 'label_attr' => [ + 'for' => 'mode', + 'help' => Translator::getInstance()->trans("Select the product brand, or supplier."), + ], + ]) + ->add("virtual_document_id", "integer", array( + "label" => Translator::getInstance()->trans("Virtual document"), + "label_attr" => array("for" => "virtual_document_id_field"), + )) + ; + + // Add standard description fields, excluding title and locale, which a re defined in parent class + $this->addStandardDescFields(array('title', 'locale')); + } + + public function checkDuplicateRef($value, ExecutionContextInterface $context) + { + $data = $context->getRoot()->getData(); + + $count = ProductQuery::create() + ->filterById($data['id'], Criteria::NOT_EQUAL) + ->filterByRef($value)->count(); + + if ($count > 0) { + $context->addViolation( + Translator::getInstance()->trans( + "A product with reference %ref already exists. Please choose another reference.", + array('%ref' => $value) + ) + ); + } + } + + public function getName() + { + return "thelia_product_modification"; + } +} diff --git a/core/lib/Thelia/Form/ProductSaleElementUpdateForm.php b/core/lib/Thelia/Form/ProductSaleElementUpdateForm.php new file mode 100644 index 00000000..e64516f5 --- /dev/null +++ b/core/lib/Thelia/Form/ProductSaleElementUpdateForm.php @@ -0,0 +1,147 @@ +formBuilder + ->add("tax_rule", "integer", array( + "constraints" => array(new NotBlank()), + "label" => Translator::getInstance()->trans("Tax rule for this product *"), + "label_attr" => array("for" => "tax_rule_field"), + )) + ->add("product_id", "integer", array( + "label" => Translator::getInstance()->trans("Product ID *"), + "label_attr" => array("for" => "product_id_field"), + "constraints" => array(new GreaterThan(array('value' => 0))), + )) + ->add("default_pse", "integer", array( + "label" => Translator::getInstance()->trans("Default product sale element"), + "label_attr" => array("for" => "default_pse_field"), + )) + ->add("currency", "integer", array( + "constraints" => array(new NotBlank()), + "label" => Translator::getInstance()->trans("Price currency *"), + "label_attr" => array("for" => "currency_field"), + )) + ->add("use_exchange_rate", "integer", array( + "label" => Translator::getInstance()->trans("Apply exchange rates on price in %sym", array("%sym" => Currency::getDefaultCurrency()->getSymbol())), + "label_attr" => array("for" => "use_exchange_rate_field"), + )) + + // -- Collections + + ->add('product_sale_element_id', 'collection', array( + 'type' => 'integer', + 'label' => Translator::getInstance()->trans('Product sale element ID *'), + 'label_attr' => array('for' => 'product_sale_element_id_field'), + 'allow_add' => true, + 'allow_delete' => true, + )) + ->add('reference', 'collection', array( + 'type' => 'text', + 'label' => Translator::getInstance()->trans('Reference *'), + 'label_attr' => array('for' => 'reference_field'), + 'allow_add' => true, + 'allow_delete' => true, + )) + ->add('price', 'collection', array( + 'type' => 'number', + 'label' => Translator::getInstance()->trans('Product price excluding taxes *'), + 'label_attr' => array('for' => 'price_field'), + 'allow_add' => true, + 'allow_delete' => true, + 'options' => array( + 'constraints' => array(new NotBlank()), + ), + )) + ->add('price_with_tax', 'collection', array( + 'type' => 'number', + 'label' => Translator::getInstance()->trans('Product price including taxes'), + 'label_attr' => array('for' => 'price_with_tax_field'), + 'allow_add' => true, + 'allow_delete' => true, + )) + ->add('weight', 'collection', array( + 'type' => 'number', + 'label' => Translator::getInstance()->trans('Weight'), + 'label_attr' => array('for' => 'weight_field'), + 'allow_add' => true, + 'allow_delete' => true, + )) + ->add('quantity', 'collection', array( + 'type' => 'number', + 'label' => Translator::getInstance()->trans('Available quantity *'), + 'label_attr' => array('for' => 'quantity_field'), + 'allow_add' => true, + 'allow_delete' => true, + 'options' => array( + 'constraints' => array(new NotBlank()), + ), + )) + ->add('sale_price', 'collection', array( + 'label' => Translator::getInstance()->trans('Sale price excluding taxes'), + 'label_attr' => array('for' => 'price_with_tax_field'), + 'allow_add' => true, + 'allow_delete' => true, + )) + ->add('sale_price_with_tax', 'collection', array( + 'type' => 'number', + 'label' => Translator::getInstance()->trans('Sale price including taxes'), + 'label_attr' => array('for' => 'sale_price_with_tax_field'), + 'allow_add' => true, + 'allow_delete' => true, + )) + ->add('onsale', 'collection', array( + 'type' => 'integer', + 'label' => Translator::getInstance()->trans('This product is on sale'), + 'label_attr' => array('for' => 'onsale_field'), + 'allow_add' => true, + 'allow_delete' => true, + )) + ->add('isnew', 'collection', array( + 'type' => 'integer', + 'label' => Translator::getInstance()->trans('Advertise this product as new'), + 'label_attr' => array('for' => 'isnew_field'), + 'allow_add' => true, + 'allow_delete' => true, + )) + ->add('isdefault', 'collection', array( + 'type' => 'integer', + 'label' => Translator::getInstance()->trans('Is it the default product sale element ?'), + 'label_attr' => array('for' => 'isdefault_field'), + 'allow_add' => true, + 'allow_delete' => true, + )) + ->add('ean_code', 'collection', array( + 'type' => 'text', + 'label' => Translator::getInstance()->trans('EAN Code'), + 'label_attr' => array('for' => 'ean_code_field'), + 'allow_add' => true, + 'allow_delete' => true, + )) + ; + } + + public function getName() + { + return "thelia_product_sale_element_update_form"; + } +} diff --git a/core/lib/Thelia/Form/ProfileCreationForm.php b/core/lib/Thelia/Form/ProfileCreationForm.php new file mode 100644 index 00000000..ae949534 --- /dev/null +++ b/core/lib/Thelia/Form/ProfileCreationForm.php @@ -0,0 +1,70 @@ + + */ +class ProfileCreationForm extends BaseForm +{ + use StandardDescriptionFieldsTrait; + + protected function buildForm() + { + $this->formBuilder + ->add("locale", "text", array( + "constraints" => array(new NotBlank()), + )) + ->add("code", "text", array( + "constraints" => array( + new NotBlank(), + new Constraints\Callback( + array( + "methods" => array( + array($this, "verifyCode"), + ), + ) + ), + ), + "label" => Translator::getInstance()->trans("Profile Code"), + "label_attr" => array("for" => "profile_code_fiels"), + )) + ; + + $this->addStandardDescFields(array('locale')); + } + + public function getName() + { + return "thelia_profile_creation"; + } + + public function verifyCode($value, ExecutionContextInterface $context) + { + /* check unicity */ + $profile = ProfileQuery::create() + ->findOneByCode($value); + + if (null !== $profile) { + $context->addViolation(Translator::getInstance()->trans("Profile `code` already exists")); + } + } +} diff --git a/core/lib/Thelia/Form/ProfileModificationForm.php b/core/lib/Thelia/Form/ProfileModificationForm.php new file mode 100644 index 00000000..8fcd0b2e --- /dev/null +++ b/core/lib/Thelia/Form/ProfileModificationForm.php @@ -0,0 +1,64 @@ + + */ +class ProfileModificationForm extends ProfileCreationForm +{ + protected function buildForm() + { + parent::buildForm(); + + $this->formBuilder + ->add("id", "hidden", array( + "required" => true, + "constraints" => array( + new Constraints\NotBlank(), + new Constraints\Callback( + array( + "methods" => array( + array($this, "verifyProfileId"), + ), + ) + ), + ), + )) + ; + + $this->formBuilder->remove("code"); + } + + public function getName() + { + return "thelia_profile_modification"; + } + + public function verifyProfileId($value, ExecutionContextInterface $context) + { + $profile = ProfileQuery::create() + ->findPk($value); + + if (null === $profile) { + $context->addViolation(Translator::getInstance()->trans("Profile ID not found")); + } + } +} diff --git a/core/lib/Thelia/Form/ProfileUpdateModuleAccessForm.php b/core/lib/Thelia/Form/ProfileUpdateModuleAccessForm.php new file mode 100644 index 00000000..1d44671e --- /dev/null +++ b/core/lib/Thelia/Form/ProfileUpdateModuleAccessForm.php @@ -0,0 +1,87 @@ + + */ +class ProfileUpdateModuleAccessForm extends BaseForm +{ + const MODULE_ACCESS_FIELD_PREFIX = "module"; + + protected function buildForm() + { + $this->formBuilder + ->add("id", "hidden", array( + "required" => true, + "constraints" => array( + new Constraints\NotBlank(), + new Constraints\Callback( + array( + "methods" => array( + array($this, "verifyProfileId"), + ), + ) + ), + ), + )) + ; + + foreach (ModuleQuery::create()->find() as $module) { + $this->formBuilder->add( + self::MODULE_ACCESS_FIELD_PREFIX.':'.str_replace(".", ":", $module->getCode()), + "choice", + array( + "choices" => array( + AccessManager::VIEW => AccessManager::VIEW, + AccessManager::CREATE => AccessManager::CREATE, + AccessManager::UPDATE => AccessManager::UPDATE, + AccessManager::DELETE => AccessManager::DELETE, + ), + "attr" => array( + "tag" => "modules", + "module_code" => $module->getCode(), + ), + "multiple" => true, + "constraints" => array( + + ), + ) + ); + } + } + + public function getName() + { + return "thelia_profile_module_access_modification"; + } + + public function verifyProfileId($value, ExecutionContextInterface $context) + { + $profile = ProfileQuery::create() + ->findPk($value); + + if (null === $profile) { + $context->addViolation(Translator::getInstance()->trans("Profile ID not found")); + } + } +} diff --git a/core/lib/Thelia/Form/ProfileUpdateResourceAccessForm.php b/core/lib/Thelia/Form/ProfileUpdateResourceAccessForm.php new file mode 100644 index 00000000..22a26f3c --- /dev/null +++ b/core/lib/Thelia/Form/ProfileUpdateResourceAccessForm.php @@ -0,0 +1,87 @@ + + */ +class ProfileUpdateResourceAccessForm extends BaseForm +{ + const RESOURCE_ACCESS_FIELD_PREFIX = "resource"; + + protected function buildForm() + { + $this->formBuilder + ->add("id", "hidden", array( + "required" => true, + "constraints" => array( + new Constraints\NotBlank(), + new Constraints\Callback( + array( + "methods" => array( + array($this, "verifyProfileId"), + ), + ) + ), + ), + )) + ; + + foreach (ResourceQuery::create()->find() as $resource) { + $this->formBuilder->add( + self::RESOURCE_ACCESS_FIELD_PREFIX.':'.str_replace(".", ":", $resource->getCode()), + "choice", + array( + "choices" => array( + AccessManager::VIEW => AccessManager::VIEW, + AccessManager::CREATE => AccessManager::CREATE, + AccessManager::UPDATE => AccessManager::UPDATE, + AccessManager::DELETE => AccessManager::DELETE, + ), + "attr" => array( + "tag" => "resources", + "resource_code" => $resource->getCode(), + ), + "multiple" => true, + "constraints" => array( + + ), + ) + ); + } + } + + public function getName() + { + return "thelia_profile_resource_access_modification"; + } + + public function verifyProfileId($value, ExecutionContextInterface $context) + { + $profile = ProfileQuery::create() + ->findPk($value); + + if (null === $profile) { + $context->addViolation(Translator::getInstance()->trans("Profile ID not found")); + } + } +} diff --git a/core/lib/Thelia/Form/Sale/SaleCreationForm.php b/core/lib/Thelia/Form/Sale/SaleCreationForm.php new file mode 100644 index 00000000..df87d8d4 --- /dev/null +++ b/core/lib/Thelia/Form/Sale/SaleCreationForm.php @@ -0,0 +1,85 @@ + + */ +class SaleCreationForm extends BaseForm +{ + protected function doBuildForm($titleFieldHelpLabel) + { + $this->formBuilder->add( + 'title', + 'text', + [ + 'constraints' => [ new NotBlank() ], + 'required' => true, + 'label' => Translator::getInstance()->trans('Sale title'), + 'label_attr' => [ + 'for' => 'title', + 'help' => $titleFieldHelpLabel, + ], + 'attr' => [ + 'placeholder' => Translator::getInstance()->trans('The sale name or descriptive title'), + ] + ] + ) + ->add( + 'label', + 'text', + [ + 'constraints' => [ new NotBlank() ], + 'required' => true, + 'label' => Translator::getInstance()->trans('Sale announce label'), + 'label_attr' => [ + 'for' => 'label', + 'help' => Translator::getInstance()->trans('The sale announce label, such as Sales ! or Flash Sales !'), + ], + 'attr' => [ + 'placeholder' => Translator::getInstance()->trans('Sale announce label'), + ] + ] + ) + ->add( + 'locale', + 'hidden', + [ + 'constraints' => [ new NotBlank() ], + 'required' => true, + ] + ); + } + + protected function buildForm() + { + $this->doBuildForm( + Translator::getInstance()->trans( + 'Enter here the sale name in the default language (%title%)', + [ '%title%' => Lang::getDefaultLanguage()->getTitle()] + ) + ); + } + + public function getName() + { + return 'thelia_sale_creation'; + } +} diff --git a/core/lib/Thelia/Form/Sale/SaleModificationForm.php b/core/lib/Thelia/Form/Sale/SaleModificationForm.php new file mode 100644 index 00000000..2f278a22 --- /dev/null +++ b/core/lib/Thelia/Form/Sale/SaleModificationForm.php @@ -0,0 +1,256 @@ + + */ +class SaleModificationForm extends SaleCreationForm +{ + // The date format for the start and end date + const PHP_DATE_FORMAT = "Y-m-d H:i:s"; + const MOMENT_JS_DATE_FORMAT = "YYYY-MM-DD HH:mm:ss"; + + use StandardDescriptionFieldsTrait; + + protected function buildForm() + { + $this->doBuildForm( + Translator::getInstance()->trans('The sale name or title') + ); + + $this->formBuilder->add( + 'id', + 'hidden', + [ + 'constraints' => [ new GreaterThan(['value' => 0]) ], + 'required' => true, + ] + ) + ->add( + 'active', + 'checkbox', + [ + 'constraints' => [ new Type([ 'type' => 'bool']) ], + 'required' => false, + 'label' => Translator::getInstance()->trans('Activate this sale'), + 'label_attr' => [ + 'for' => 'active', + ], + 'attr' => [ + ] + ] + ) + ->add( + 'display_initial_price', + 'checkbox', + [ + 'constraints' => [ new Type([ 'type' => 'bool']) ], + 'required' => false, + 'label' => Translator::getInstance()->trans('Display initial product prices on front-office'), + 'label_attr' => [ + 'for' => 'display_initial_price', + ], + 'attr' => [ + ] + ] + ) + ->add( + 'start_date', + 'text', + [ + 'constraints' => [ + new Callback([ + "methods" => [ + [ $this, "checkDate" ], + ], + ]), + ], + 'required' => false, + 'label' => Translator::getInstance()->trans('Start date of sales'), + 'label_attr' => [ + 'for' => 'start_date', + 'help' => Translator::getInstance()->trans('The date from which sales are active. Please use %fmt format.', [ '%fmt' => self::MOMENT_JS_DATE_FORMAT]), + ], + 'attr' => [ + 'data-date-format' => self::MOMENT_JS_DATE_FORMAT, + ] + ] + ) + ->add( + 'end_date', + 'text', + [ + 'constraints' => [ + new Callback([ + "methods" => [ + [ $this, "checkDate" ], + ], + ]), + ], + 'required' => false, + 'label' => Translator::getInstance()->trans('End date of sales'), + 'label_attr' => [ + 'for' => 'end_date', + 'help' => Translator::getInstance()->trans('The date after which sales are de-activated. Please use %fmt format.', [ '%fmt' => self::MOMENT_JS_DATE_FORMAT]), + ], + 'attr' => [ + 'data-date-format' => self::MOMENT_JS_DATE_FORMAT, + ] + ] + ) + ->add( + 'price_offset_type', + 'choice', + [ + 'constraints' => [ new NotBlank() ], + 'choices' => [ + Sale::OFFSET_TYPE_AMOUNT => Translator::getInstance()->trans('Constant amount'), + Sale::OFFSET_TYPE_PERCENTAGE => Translator::getInstance()->trans('Percentage'), + ], + 'required' => true, + 'label' => Translator::getInstance()->trans('Discount type'), + 'label_attr' => [ + 'for' => 'price_offset_type', + 'help' => Translator::getInstance()->trans('Select the discount type that will be applied to original product prices'), + ], + 'attr' => [ + ] + ] + ) + ->add( + 'price_offset', + 'collection', + [ + 'type' => 'number', + 'required' => true, + 'allow_add' => true, + 'allow_delete' => true, + 'options' => [ + 'constraints' => array(new NotBlank()), + ], + + 'label' => Translator::getInstance()->trans('Product price offset for each currency'), + 'label_attr' => [ + 'for' => 'price_offset', + ], + ] + ) + ->add( + 'categories', + 'choice', + [ + 'required' => true, + 'multiple' => true, + 'choices' => $this->getCategoriesIdArray(), + 'label' => Translator::getInstance()->trans('Product categories'), + 'label_attr' => [ + 'for' => 'categories', + 'help' => Translator::getInstance()->trans('Select the categories of the products covered by this operation'), + ], + 'attr' => [ + 'size' => 10, + ] + ] + ) + ->add( + 'products', + 'collection', + [ + 'type' => 'integer', + 'required' => false, + 'allow_add' => true, + 'allow_delete' => true, + 'label' => Translator::getInstance()->trans('Products'), + 'label_attr' => [ + 'for' => 'products', + 'help' => Translator::getInstance()->trans('Select the products covered by this operation'), + ], + 'attr' => [ + ] + ] + ) + ->add( + 'product_attributes', + 'collection', + [ + 'type' => 'text', + 'required' => false, + 'allow_add' => true, + 'allow_delete' => true, + 'label' => Translator::getInstance()->trans('Product attributes'), + 'label_attr' => [ + 'for' => 'product_attributes', + 'help' => Translator::getInstance()->trans('Select the product attributes included in this operation'), + ], + 'attr' => [ + ] + ] + ) + ; + // Add standard description fields, excluding title and locale, which are already defined + $this->addStandardDescFields(array('title', 'locale')); + } + + /** + * Validate a date entered with the current edition Language date format. + * + * @param string $value + * @param ExecutionContextInterface $context + */ + public function checkDate($value, ExecutionContextInterface $context) + { + $format = self::PHP_DATE_FORMAT; + + if (! empty($value) && false === \DateTime::createFromFormat($format, $value)) { + $context->addViolation(Translator::getInstance()->trans("Date '%date' is invalid, please enter a valid date using %fmt format", [ + '%fmt' => self::MOMENT_JS_DATE_FORMAT, + '%date' => $value + ])); + } + } + + public function getName() + { + return "thelia_sale_modification"; + } + + private function getCategoriesIdArray() + { + $categories = CategoryQuery::create() + ->select("id") + ->find() + ->toArray() + ; + + $ids = []; + + foreach ($categories as $category) { + $ids[$category] = $category; + } + + return $ids; + } +} diff --git a/core/lib/Thelia/Form/SeoFieldsTrait.php b/core/lib/Thelia/Form/SeoFieldsTrait.php new file mode 100644 index 00000000..82d678d6 --- /dev/null +++ b/core/lib/Thelia/Form/SeoFieldsTrait.php @@ -0,0 +1,104 @@ + + */ +trait SeoFieldsTrait +{ + /** + * Add seo meta title, meta description and meta keywords fields + * + * @param array $exclude name of the fields that should not be added to the form + */ + protected function addSeoFields($exclude = array()) + { + if (! \in_array('url', $exclude)) { + $this->formBuilder->add( + 'url', + 'text', + [ + 'required' => false, + 'label' => Translator::getInstance()->trans('Rewriten URL'), + 'label_attr' => [ + 'for' => 'rewriten_url_field', + ], + 'attr' => [ + 'placeholder' => Translator::getInstance()->trans('Use the keyword phrase in your URL.'), + ] + ] + ); + } + + if (! \in_array('meta_title', $exclude)) { + $this->formBuilder->add( + 'meta_title', + 'text', + [ + 'required' => false, + 'label' => Translator::getInstance()->trans('Page Title'), + 'label_attr' => [ + 'for' => 'meta_title', + 'help' => Translator::getInstance()->trans('The HTML TITLE element is the most important element on your web page.'), + ], + 'attr' => [ + 'placeholder' => Translator::getInstance()->trans('Make sure that your title is clear, and contains many of the keywords within the page itself.'), + ] + ] + ); + } + + if (! \in_array('meta_description', $exclude)) { + $this->formBuilder->add( + 'meta_description', + 'textarea', + [ + 'required' => false, + 'label' => Translator::getInstance()->trans('Meta Description'), + 'label_attr' => [ + 'for' => 'meta_description', + 'help' => Translator::getInstance()->trans('Keep the most important part of your description in the first 150-160 characters.'), + ], + 'attr' => [ + 'rows' => 6, + 'placeholder' => Translator::getInstance()->trans('Make sure it uses keywords found within the page itself.'), + ] + ] + ); + } + + if (! \in_array('meta_keywords', $exclude)) { + $this->formBuilder->add( + 'meta_keywords', + 'textarea', + [ + 'required' => false, + 'label' => Translator::getInstance()->trans('Meta Keywords'), + 'label_attr' => [ + 'for' => 'meta_keywords', + 'help' => Translator::getInstance()->trans('You don\'t need to use commas or other punctuations.'), + ], + 'attr' => [ + 'rows' => 3, + 'placeholder' => Translator::getInstance()->trans('Don\'t repeat keywords over and over in a row. Rather, put in keyword phrases.'), + ] + ] + ); + } + } +} diff --git a/core/lib/Thelia/Form/SeoForm.php b/core/lib/Thelia/Form/SeoForm.php new file mode 100644 index 00000000..8b01c04d --- /dev/null +++ b/core/lib/Thelia/Form/SeoForm.php @@ -0,0 +1,55 @@ + + */ +class SeoForm extends BaseForm +{ + use SeoFieldsTrait; + + /** + * @inheritdoc + */ + protected function buildForm() + { + $this->formBuilder + ->add("id", "hidden", array( + 'required' => true, + "constraints" => array( + new GreaterThan(array('value' => 0)), + ), + )) + ->add("locale", "hidden", array( + 'required' => true, + "constraints" => array( + new NotBlank(), + ), + )) + ; + + // Add SEO Fields + $this->addSeoFields(); + } + + public function getName() + { + return "thelia_seo"; + } +} diff --git a/core/lib/Thelia/Form/ShippingZone/ShippingZoneAddArea.php b/core/lib/Thelia/Form/ShippingZone/ShippingZoneAddArea.php new file mode 100644 index 00000000..f6f629ce --- /dev/null +++ b/core/lib/Thelia/Form/ShippingZone/ShippingZoneAddArea.php @@ -0,0 +1,74 @@ + + */ +class ShippingZoneAddArea extends BaseForm +{ + /** + * + * in this function you add all the fields you need for your Form. + * Form this you have to call add method on $this->formBuilder attribute : + * + * $this->formBuilder->add("name", "text") + * ->add("email", "email", array( + * "attr" => array( + * "class" => "field" + * ), + * "label" => "email", + * "constraints" => array( + * new \Symfony\Component\Validator\Constraints\NotBlank() + * ) + * ) + * ) + * ->add('age', 'integer'); + * + * @return null + */ + protected function buildForm() + { + $this->formBuilder + ->add('area_id', 'integer', array( + 'constraints' => array( + new NotBlank(), + new GreaterThan(array('value' => 0)), + ), + 'label_attr' => array('for' => 'shipping_area'), + 'label' => Translator::getInstance()->trans('Available shipping zones'), + )) + ->add('shipping_zone_id', 'integer', array( + 'constraints' => array( + new NotBlank(), + new GreaterThan(array('value' => 0)), + ), + )) + ; + } + + /** + * @return string the name of you form. This name must be unique + */ + public function getName() + { + return 'thelia_shippingzone_area'; + } +} diff --git a/core/lib/Thelia/Form/ShippingZone/ShippingZoneRemoveArea.php b/core/lib/Thelia/Form/ShippingZone/ShippingZoneRemoveArea.php new file mode 100644 index 00000000..a04a13ec --- /dev/null +++ b/core/lib/Thelia/Form/ShippingZone/ShippingZoneRemoveArea.php @@ -0,0 +1,29 @@ + + */ +class ShippingZoneRemoveArea extends ShippingZoneAddArea +{ + /** + * @return string the name of you form. This name must be unique + */ + public function getName() + { + return 'thelia_shippingzone_remove_area'; + } +} diff --git a/core/lib/Thelia/Form/StandardDescriptionFieldsTrait.php b/core/lib/Thelia/Form/StandardDescriptionFieldsTrait.php new file mode 100644 index 00000000..acfcbde8 --- /dev/null +++ b/core/lib/Thelia/Form/StandardDescriptionFieldsTrait.php @@ -0,0 +1,120 @@ + + */ +trait StandardDescriptionFieldsTrait +{ + /** + * Add standard description fields + locale tot the form + * + * @param array $exclude name of the fields that should not be added to the form + */ + protected function addStandardDescFields($exclude = array()) + { + if (! \in_array('locale', $exclude)) { + $this->formBuilder->add( + 'locale', + 'hidden', + [ + 'constraints' => [ new NotBlank() ], + 'required' => true, + ] + ); + } + + if (! \in_array('title', $exclude)) { + $this->formBuilder->add( + 'title', + 'text', + [ + 'constraints' => [ new NotBlank() ], + 'required' => true, + 'label' => Translator::getInstance()->trans('Title'), + 'label_attr' => [ + 'for' => 'title_field', + ], + 'attr' => [ + 'placeholder' => Translator::getInstance()->trans('A descriptive title'), + ] + ] + ); + } + + if (! \in_array('chapo', $exclude)) { + $this->formBuilder->add( + 'chapo', + 'textarea', + [ + 'constraints' => [ ], + 'required' => false, + 'label' => Translator::getInstance()->trans('Summary'), + 'label_attr' => [ + 'for' => 'summary_field', + 'help' => Translator::getInstance()->trans('A short description, used when a summary or an introduction is required'), + ], + 'attr' => [ + 'rows' => 3, + 'placeholder' => Translator::getInstance()->trans('Short description text'), + ] + ] + ); + } + + if (! \in_array('description', $exclude)) { + $this->formBuilder->add( + 'description', + 'textarea', + [ + 'constraints' => [ ], + 'required' => false, + 'label' => Translator::getInstance()->trans('Detailed description'), + 'label_attr' => [ + 'for' => 'detailed_description_field', + 'help' => Translator::getInstance()->trans('The detailed description.'), + ], + 'attr' => [ + 'rows' => 10, + ] + ] + ); + } + + if (! \in_array('postscriptum', $exclude)) { + $this->formBuilder->add( + 'postscriptum', + 'textarea', + [ + 'constraints' => [ ], + 'required' => false, + 'label' => Translator::getInstance()->trans('Conclusion'), + 'label_attr' => [ + 'for' => 'conclusion_field', + 'help' => Translator::getInstance()->trans('A short text, used when an additional or supplemental information is required.'), + ], + 'attr' => [ + 'placeholder' => Translator::getInstance()->trans('Short additional text'), + 'rows' => 3, + ] + ] + ); + } + } +} diff --git a/core/lib/Thelia/Form/State/StateCreationForm.php b/core/lib/Thelia/Form/State/StateCreationForm.php new file mode 100644 index 00000000..105c0df8 --- /dev/null +++ b/core/lib/Thelia/Form/State/StateCreationForm.php @@ -0,0 +1,87 @@ + + */ +class StateCreationForm extends BaseForm +{ + protected function buildForm() + { + $this->formBuilder + ->add( + 'title', + 'text', + [ + 'constraints' => [ + new NotBlank(), + ], + 'label' => $this->translator->trans('State title') + ] + ) + ->add("country_id", "country_id", array( + "constraints" => array( + new NotBlank(), + ), + "label" => $this->translator->trans("Country"), + "label_attr" => array( + "for" => "country", + ), + )) + ->add( + 'locale', + 'hidden', + [ + 'constraints' => [ + new NotBlank(), + ], + ] + ) + ->add( + 'visible', + 'checkbox', + [ + 'required' => false, + 'label' => $this->translator->trans('This state is online'), + 'label_attr' => [ + 'for' => 'visible_create', + ] + ] + ) + ->add( + 'isocode', + 'text', + [ + 'constraints' => [ + new NotBlank(), + ], + 'label' => $this->translator->trans('ISO Code'), + 'label_attr' => [ + 'help' => $this->translator->trans('Iso code for states. It depends of the country.') + ], + ] + ) + ; + } + + public function getName() + { + return "thelia_state_creation"; + } +} diff --git a/core/lib/Thelia/Form/State/StateModificationForm.php b/core/lib/Thelia/Form/State/StateModificationForm.php new file mode 100644 index 00000000..8de96dbf --- /dev/null +++ b/core/lib/Thelia/Form/State/StateModificationForm.php @@ -0,0 +1,40 @@ + + */ +class StateModificationForm extends StateCreationForm +{ + use StandardDescriptionFieldsTrait; + + protected function buildForm() + { + parent::buildForm(); + + $this->formBuilder + ->add('id', 'hidden', ['constraints' => [new GreaterThan(['value' => 0])]]) + ; + } + + public function getName() + { + return "thelia_state_modification"; + } +} diff --git a/core/lib/Thelia/Form/SystemLogConfigurationForm.php b/core/lib/Thelia/Form/SystemLogConfigurationForm.php new file mode 100644 index 00000000..6c1e97cd --- /dev/null +++ b/core/lib/Thelia/Form/SystemLogConfigurationForm.php @@ -0,0 +1,74 @@ +formBuilder + ->add("level", "choice", array( + 'choices' => array( + Tlog::MUET => Translator::getInstance()->trans("Disabled"), + Tlog::DEBUG => Translator::getInstance()->trans("Debug"), + Tlog::INFO => Translator::getInstance()->trans("Information"), + Tlog::NOTICE => Translator::getInstance()->trans("Notices"), + Tlog::WARNING => Translator::getInstance()->trans("Warnings"), + Tlog::ERROR => Translator::getInstance()->trans("Errors"), + Tlog::CRITICAL => Translator::getInstance()->trans("Critical"), + Tlog::ALERT => Translator::getInstance()->trans("Alerts"), + Tlog::EMERGENCY => Translator::getInstance()->trans("Emergency"), + ), + + "label" => Translator::getInstance()->trans('Log level *'), + "label_attr" => array( + "for" => "level_field", + ), + )) + ->add("format", "text", array( + "label" => Translator::getInstance()->trans('Log format *'), + "label_attr" => array( + "for" => "format_field", + ), + )) + ->add("show_redirections", "integer", array( + "constraints" => array(new Constraints\NotBlank()), + "label" => Translator::getInstance()->trans('Show redirections *'), + "label_attr" => array( + "for" => "show_redirections_field", + ), + )) + ->add("files", "text", array( + "label" => Translator::getInstance()->trans('Activate logs only for these files'), + "label_attr" => array( + "for" => "files_field", + ), + )) + ->add("ip_addresses", "text", array( + "label" => Translator::getInstance()->trans('Activate logs only for these IP Addresses'), + "label_attr" => array( + "for" => "files_field", + ), + )) + ; + } + + public function getName() + { + return "thelia_system_log_configuration"; + } +} diff --git a/core/lib/Thelia/Form/TaxCreationForm.php b/core/lib/Thelia/Form/TaxCreationForm.php new file mode 100644 index 00000000..e37ad906 --- /dev/null +++ b/core/lib/Thelia/Form/TaxCreationForm.php @@ -0,0 +1,160 @@ + + */ +class TaxCreationForm extends BaseForm +{ + use StandardDescriptionFieldsTrait; + + protected static $typeList = []; + + protected function buildForm() + { + if (!$this->container) { + throw new \LogicException( + Translator::getInstance()->trans( + "The container should not be null in this form. Please use the FormFactory to get an instance." + ) + ); + } + + /** @var TaxEngine $taxEngine */ + $taxEngine = $this->container->get('thelia.taxEngine'); + + $types = $taxEngine->getTaxTypeList(); + + $typeList = array(); + $requirementList = array(); + + foreach ($types as $classname) { + $instance = new $classname(); + + $typeList[Tax::escapeTypeName($classname)] = $instance->getTitle(); + + $requirementList[$classname] = $instance->getRequirementsDefinition(); + } + + $this->formBuilder + ->add( + "locale", + "hidden", + [ + "constraints" => [new NotBlank()], + ] + ) + ->add( + "type", + "choice", + [ + "choices" => $typeList, + "required" => true, + "constraints" => [ + new Constraints\NotBlank(), + ], + "label" => Translator::getInstance()->trans("Type"), + "label_attr" => ["for" => "type_field"], + ] + ) + ; + + foreach ($requirementList as $name => $requirements) { + /** @var TaxTypeRequirementDefinition $requirement */ + foreach ($requirements as $requirement) { + if (!isset(self::$typeList[$requirement->getName()])) { + self::$typeList[$requirement->getName()] = $requirement->getType(); + } + + $this->formBuilder + // Replace the '\' in the class name by hyphens + // See TaxController::getRequirements if some changes are made about this. + ->add( + Tax::escapeTypeName($name) . ':' . $requirement->getName(), + new TheliaType(), + [ + "constraints" => [ + new Constraints\Callback( + [ + "methods" => [ + [$this, "checkRequirementField"], + ], + ] + ), + ], + "attr" => [ + "tag" => "requirements", + "tax_type" => Tax::escapeTypeName($name) + ], + "label_attr" => [ + "type" => $requirement->getName() + ], + "label" => Translator::getInstance()->trans($requirement->getTitle()), + "type" => $requirement->getType()->getFormType(), + "options" => $requirement->getType()->getFormOptions(), + ] + ); + } + } + + $this->addStandardDescFields(array('postscriptum', 'chapo', 'locale')); + } + + public function checkRequirementField($value, ExecutionContextInterface $context) + { + $data = $context->getRoot()->getData(); + $type = $data["type"]; + + if (false !== strpos($context->getPropertyPath(), $type)) { + // extract requirement type + if (preg_match('@\:(.+)\]@', $context->getPropertyPath(), $matches)) { + $requirementType = $matches[1]; + if (isset(self::$typeList[$requirementType])) { + /** @var TypeInterface $typeClass */ + $typeClass = self::$typeList[$requirementType]; + $typeClass->verifyForm($value, $context); + + return; + } + } + + $context->addViolation( + Translator::getInstance()->trans( + "Impossible to check value `%value` for `%type` type", + [ + '%value' => $value, + '%type' => $type + ] + ) + ); + } + } + + public function getName() + { + return "thelia_tax_creation"; + } +} diff --git a/core/lib/Thelia/Form/TaxModificationForm.php b/core/lib/Thelia/Form/TaxModificationForm.php new file mode 100644 index 00000000..58a263ea --- /dev/null +++ b/core/lib/Thelia/Form/TaxModificationForm.php @@ -0,0 +1,61 @@ + + */ +class TaxModificationForm extends TaxCreationForm +{ + protected function buildForm() + { + parent::buildForm(); + + $this->formBuilder + ->add("id", "hidden", array( + "required" => true, + "constraints" => array( + new Constraints\NotBlank(), + new Constraints\Callback( + array( + "methods" => array( + array($this, "verifyTaxId"), + ), + ) + ), + ), + )) + ; + } + + public function getName() + { + return "thelia_tax_modification"; + } + + public function verifyTaxId($value, ExecutionContextInterface $context) + { + $tax = TaxQuery::create() + ->findPk($value); + + if (null === $tax) { + $context->addViolation("Tax ID not found"); + } + } +} diff --git a/core/lib/Thelia/Form/TaxRuleCreationForm.php b/core/lib/Thelia/Form/TaxRuleCreationForm.php new file mode 100644 index 00000000..9104d37f --- /dev/null +++ b/core/lib/Thelia/Form/TaxRuleCreationForm.php @@ -0,0 +1,36 @@ +formBuilder + ->add("locale", "hidden", array( + "constraints" => array(new NotBlank()), + )) + ; + + $this->addStandardDescFields(array('postscriptum', 'chapo', 'locale')); + } + + public function getName() + { + return "thelia_tax_rule_creation"; + } +} diff --git a/core/lib/Thelia/Form/TaxRuleModificationForm.php b/core/lib/Thelia/Form/TaxRuleModificationForm.php new file mode 100644 index 00000000..2a06484d --- /dev/null +++ b/core/lib/Thelia/Form/TaxRuleModificationForm.php @@ -0,0 +1,56 @@ +formBuilder + ->add("id", "hidden", array( + "required" => true, + "constraints" => array( + new Constraints\NotBlank(), + new Constraints\Callback( + array( + "methods" => array( + array($this, "verifyTaxRuleId"), + ), + ) + ), + ), + )) + ; + } + + public function getName() + { + return "thelia_tax_rule_modification"; + } + + public function verifyTaxRuleId($value, ExecutionContextInterface $context) + { + $taxRule = TaxRuleQuery::create() + ->findPk($value); + + if (null === $taxRule) { + $context->addViolation(Translator::getInstance()->trans("Tax rule ID not found")); + } + } +} diff --git a/core/lib/Thelia/Form/TaxRuleTaxListUpdateForm.php b/core/lib/Thelia/Form/TaxRuleTaxListUpdateForm.php new file mode 100644 index 00000000..9e2af57d --- /dev/null +++ b/core/lib/Thelia/Form/TaxRuleTaxListUpdateForm.php @@ -0,0 +1,193 @@ +formBuilder + ->add( + "id", + "hidden", + [ + "required" => true, + "constraints" => [ + new Constraints\NotBlank(), + new Constraints\Callback( + [ + "methods" => [ + [$this, "verifyTaxRuleId"], + ], + ] + ), + ], + ] + ) + ->add( + "tax_list", + "hidden", + [ + "required" => true, + "attr" => [ + "id" => 'tax_list', + ], + "constraints" => [ + new Constraints\Callback( + [ + "methods" => [ + [$this, "verifyTaxList"], + ], + ] + ), + ], + ] + ) + ->add( + "country_list", + "hidden", + [ + "required" => true, + "attr" => [ + "id" => 'country_list', + ], + "constraints" => [ + new Constraints\Callback( + [ + "methods" => [ + [$this, "verifyCountryList"], + ], + ] + ), + ], + ] + ) + ->add( + "country_deleted_list", + "hidden", + [ + "required" => true, + "attr" => [ + "id" => 'country_deleted_list', + ], + "constraints" => [ + new Constraints\Callback( + [ + "methods" => [ + [$this, "verifyCountryList"], + ], + ] + ), + ], + ] + ) + ; + } + + public function getName() + { + return "thelia_tax_rule_taxlistupdate"; + } + + public function verifyTaxRuleId($value, ExecutionContextInterface $context) + { + $taxRule = TaxRuleQuery::create() + ->findPk($value) + ; + + if (null === $taxRule) { + $context->addViolation(Translator::getInstance()->trans("Tax rule ID not found")); + } + } + + public function verifyTaxList($value, ExecutionContextInterface $context) + { + $jsonType = new JsonType(); + if (!$jsonType->isValid($value)) { + $context->addViolation(Translator::getInstance()->trans("Tax list is not valid JSON")); + } + + $taxList = json_decode($value, true); + + /* check we have 2 level max */ + + foreach ($taxList as $taxLevel1) { + if (\is_array($taxLevel1)) { + foreach ($taxLevel1 as $taxLevel2) { + if (\is_array($taxLevel2)) { + $context->addViolation(Translator::getInstance()->trans("Bad tax list JSON")); + } else { + $taxModel = TaxQuery::create()->findPk($taxLevel2); + if (null === $taxModel) { + $context->addViolation(Translator::getInstance() + ->trans("Tax ID not found in tax list JSON")); + } + } + } + } else { + $taxModel = TaxQuery::create()->findPk($taxLevel1); + if (null === $taxModel) { + $context->addViolation(Translator::getInstance()->trans("Tax ID not found in tax list JSON")); + } + } + } + } + + public function verifyCountryList($value, ExecutionContextInterface $context) + { + $jsonType = new JsonType(); + if (!$jsonType->isValid($value)) { + $context->addViolation(Translator::getInstance()->trans("Country list is not valid JSON")); + } + + $countryList = json_decode($value, true); + + foreach ($countryList as $countryItem) { + if (\is_array($countryItem)) { + $country = CountryQuery::create()->findPk($countryItem[0]); + if (null === $country) { + $context->addViolation( + Translator::getInstance()->trans( + "Country ID %id not found", + ['%id' => $countryItem[0]] + ) + ); + } + + if ($countryItem[1] == "0") { + continue; + } + + $state = StateQuery::create()->findPk($countryItem[1]); + if (null === $state) { + $context->addViolation( + Translator::getInstance()->trans( + "State ID %id not found", + ['%id' => $countryItem[1]] + ) + ); + } + } else { + $context->addViolation(Translator::getInstance()->trans("Wrong country definition")); + } + } + } +} diff --git a/core/lib/Thelia/Form/TemplateCreationForm.php b/core/lib/Thelia/Form/TemplateCreationForm.php new file mode 100644 index 00000000..7bf36d15 --- /dev/null +++ b/core/lib/Thelia/Form/TemplateCreationForm.php @@ -0,0 +1,51 @@ +formBuilder + ->add( + "name", + "text", + array( + "constraints" => array( + new NotBlank(), + ), + "label" => Translator::getInstance()->trans("Template Name *"), + "label_attr" => array( + "for" => "name", + ), ) + ) + ->add( + "locale", + "text", + array( + "constraints" => array( + new NotBlank(), + ), ) + ) + ; + } + + public function getName() + { + return "thelia_template_creation"; + } +} diff --git a/core/lib/Thelia/Form/TemplateModificationForm.php b/core/lib/Thelia/Form/TemplateModificationForm.php new file mode 100644 index 00000000..527710f2 --- /dev/null +++ b/core/lib/Thelia/Form/TemplateModificationForm.php @@ -0,0 +1,41 @@ +formBuilder + ->add("id", "hidden", array( + "constraints" => array( + new GreaterThan( + array('value' => 0) + ), + ), + )) + ; + } + + public function getName() + { + return "thelia_template_modification"; + } +} diff --git a/core/lib/Thelia/Handler/ExportHandler.php b/core/lib/Thelia/Handler/ExportHandler.php new file mode 100644 index 00000000..e2056b59 --- /dev/null +++ b/core/lib/Thelia/Handler/ExportHandler.php @@ -0,0 +1,302 @@ + + */ +class ExportHandler +{ + /** + * @var \Symfony\Component\EventDispatcher\EventDispatcherInterface An event dispatcher interface + */ + protected $eventDispatcher; + + /** @var ContainerInterface */ + protected $container; + + /** + * Class constructor + * + * @param \Symfony\Component\EventDispatcher\EventDispatcherInterface $eventDispatcher An event dispatcher interface + * @param ContainerInterface $container + */ + public function __construct(EventDispatcherInterface $eventDispatcher, ContainerInterface $container) + { + $this->eventDispatcher = $eventDispatcher; + $this->container = $container; + } + + /** + * Get export model based on given identifier + * + * @param integer $exportId An export identifier + * @param boolean $dispatchException Dispatch exception if model doesn't exist + * + * @throws \ErrorException + * + * @return null|\Thelia\Model\Export + */ + public function getExport($exportId, $dispatchException = false) + { + $export = (new ExportQuery)->findPk($exportId); + + if ($export === null && $dispatchException) { + throw new \ErrorException( + Translator::getInstance()->trans( + 'There is no id "%id" in the exports', + [ + '%id' => $exportId + ] + ) + ); + } + + return $export; + } + + /** + * Get export model based on given reference + * + * @param string $exportRef An export reference + * @param boolean $dispatchException Dispatch exception if model doesn't exist + * + * @throws \ErrorException + * + * @return null|\Thelia\Model\Export + */ + public function getExportByRef($exportRef, $dispatchException = false) + { + $export = (new ExportQuery)->findOneByRef($exportRef); + + if ($export === null && $dispatchException) { + throw new \ErrorException( + Translator::getInstance()->trans( + 'There is no ref "%ref" in the exports', + [ + '%ref' => $exportRef + ] + ) + ); + } + + return $export; + } + + /** + * Get export category model based on given identifier + * + * @param integer $exportCategoryId An export category identifier + * @param boolean $dispatchException Dispatch exception if model doesn't exist + * + * @throws \ErrorException + * + * @return null|\Thelia\Model\ExportCategory + */ + public function getCategory($exportCategoryId, $dispatchException = false) + { + $category = (new ExportCategoryQuery)->findPk($exportCategoryId); + + if ($category === null && $dispatchException) { + throw new \ErrorException( + Translator::getInstance()->trans( + 'There is no id "%id" in the export categories', + [ + '%id' => $exportCategoryId + ] + ) + ); + } + + return $category; + } + + /** + * Export + * + * @param \Thelia\Model\Export $export + * @param \Thelia\Core\Serializer\SerializerInterface $serializer + * @param null|\Thelia\Core\Archiver\ArchiverInterface $archiver + * @param null|\Thelia\Model\Lang $language + * @param boolean $includeImages + * @param boolean $includeDocuments + * @param null|array $rangeDate + * + * @return \Thelia\Core\Event\ExportEvent + */ + public function export( + Export $export, + SerializerInterface $serializer, + ArchiverInterface $archiver = null, + Lang $language = null, + $includeImages = false, + $includeDocuments = false, + $rangeDate = null + ) { + $exportHandleClass = $export->getHandleClass(); + + /** @var \Thelia\ImportExport\Export\AbstractExport $instance */ + $instance = new $exportHandleClass; + $instance->setContainer($this->container); + + // Configure handle class + $instance->setLang($language); + if ($archiver !== null) { + if ($includeImages && $instance->hasImages()) { + $instance->setExportImages(true); + } + if ($includeDocuments && $instance->hasDocuments()) { + $instance->setExportDocuments(true); + } + } + + if ($rangeDate['start'] && !($rangeDate['start'] instanceof \DateTime)) { + $rangeDate['start'] = \DateTime::createFromFormat( + 'Y-m-d H:i:s', + $rangeDate['start']['year'] . '-' . $rangeDate['start']['month'] . '-1 00:00:00' + ); + } + if ($rangeDate['end'] && !($rangeDate['end'] instanceof \DateTime)) { + $rangeDate['end'] = \DateTime::createFromFormat( + 'Y-m-d H:i:s', + $rangeDate['end']['year'] . '-' . (\intval($rangeDate['end']['month']) + 1) . '-0 23:59:59' + ); + } + $instance->setRangeDate($rangeDate); + + // Process export + $event = new ExportEvent($instance, $serializer, $archiver); + + $this->eventDispatcher->dispatch(TheliaEvents::EXPORT_BEGIN, $event); + + $filePath = $this->processExport($event->getExport(), $event->getSerializer()); + + $event->setFilePath($filePath); + + $this->eventDispatcher->dispatch(TheliaEvents::EXPORT_FINISHED, $event); + + + if ($event->getArchiver() !== null) { + // Create archive + $event->getArchiver()->create($filePath); + + // Add images + if ($includeImages && $event->getExport()->hasImages()) { + $this->processExportImages($event->getExport(), $event->getArchiver()); + } + + // Add documents + if ($includeDocuments && $event->getExport()->hasDocuments()) { + $this->processExportDocuments($event->getExport(), $event->getArchiver()); + } + + // Finalize archive + $event->getArchiver()->add($filePath)->save(); + + // Change returned file path + $event->setFilePath($event->getArchiver()->getArchivePath()); + } + + $this->eventDispatcher->dispatch(TheliaEvents::EXPORT_SUCCESS, $event); + + return $event; + } + + /** + * Process export + * + * @param \Thelia\ImportExport\Export\AbstractExport $export An export + * @param \Thelia\Core\Serializer\SerializerInterface $serializer A serializer interface + * + * @return string Export file path + */ + protected function processExport(AbstractExport $export, SerializerInterface $serializer) + { + $filename = sprintf( + '%s-%s-%s.%s', + (new \DateTime)->format('Ymd'), + uniqid(), + $export->getFileName(), + $serializer->getExtension() + ); + + $filePath = THELIA_CACHE_DIR . 'export' . DS . $filename; + + $fileSystem = new Filesystem; + $fileSystem->mkdir(dirname($filePath)); + + $file = new \SplFileObject($filePath, 'w+b'); + + $serializer->prepareFile($file); + + foreach ($export as $idx => $data) { + $data = $export->beforeSerialize($data); + $data = $export->applyOrderAndAliases($data); + $data = $serializer->serialize($data); + $data = $export->afterSerialize($data); + + if ($idx > 0) { + $data = $serializer->separator() . $data; + } + + $file->fwrite($data); + } + + $serializer->finalizeFile($file); + + unset($file); + + return $filePath; + } + + /** + * Add images to archive + * + * @param \Thelia\ImportExport\Export\AbstractExport $export An export instance + * @param \Thelia\Core\Archiver\ArchiverInterface $archiver + */ + protected function processExportImages(AbstractExport $export, ArchiverInterface $archiver) + { + foreach ($export->getImagesPaths() as $imagePath) { + $archiver->add($imagePath); + } + } + + /** + * Add documents to archive + * + * @param \Thelia\ImportExport\Export\AbstractExport $export An export instance + * @param \Thelia\Core\Archiver\ArchiverInterface $archiver + */ + protected function processExportDocuments(AbstractExport $export, ArchiverInterface $archiver) + { + foreach ($export->getDocumentsPaths() as $documentPath) { + $archiver->add($documentPath); + } + } +} diff --git a/core/lib/Thelia/Handler/ImportHandler.php b/core/lib/Thelia/Handler/ImportHandler.php new file mode 100644 index 00000000..816c5eff --- /dev/null +++ b/core/lib/Thelia/Handler/ImportHandler.php @@ -0,0 +1,310 @@ + + */ +class ImportHandler +{ + /** + * @var \Symfony\Component\EventDispatcher\EventDispatcherInterface An event dispatcher interface + */ + protected $eventDispatcher; + + /** + * @var \Thelia\Core\Serializer\SerializerManager The serializer manager service + */ + protected $serializerManager; + + /** + * @var \Thelia\Core\Archiver\ArchiverManager The archiver manager service + */ + protected $archiverManager; + + /** @var ContainerInterface */ + protected $container; + + /** + * Class constructor + * + * @param \Symfony\Component\EventDispatcher\EventDispatcherInterface $eventDispatcher + * An event dispatcher interface + * @param \Thelia\Core\Serializer\SerializerManager $serializerManager + * The serializer manager service + * @param \Thelia\Core\Archiver\ArchiverManager $archiverManager + * The archiver manager service + * @param ContainerInterface $container + */ + public function __construct( + EventDispatcherInterface $eventDispatcher, + SerializerManager $serializerManager, + ArchiverManager $archiverManager, + ContainerInterface $container + ) { + $this->eventDispatcher = $eventDispatcher; + $this->serializerManager = $serializerManager; + $this->archiverManager = $archiverManager; + $this->container = $container; + } + + /** + * Get import model based on given identifier + * + * @param integer $importId An import identifier + * @param boolean $dispatchException Dispatch exception if model doesn't exist + * + * @throws \ErrorException + * + * @return null|\Thelia\Model\Import + */ + public function getImport($importId, $dispatchException = false) + { + $import = (new ImportQuery)->findPk($importId); + + if ($import === null && $dispatchException) { + throw new \ErrorException( + Translator::getInstance()->trans( + 'There is no id "%id" in the imports', + [ + '%id' => $importId + ] + ) + ); + } + + return $import; + } + + /** + * Get import model based on given reference + * + * @param string $importRef An import reference + * @param boolean $dispatchException Dispatch exception if model doesn't exist + * + * @throws \ErrorException + * + * @return null|\Thelia\Model\Import + */ + public function getImportByRef($importRef, $dispatchException = false) + { + $import = (new ImportQuery)->findOneByRef($importRef); + + if ($import === null && $dispatchException) { + throw new \ErrorException( + Translator::getInstance()->trans( + 'There is no id "%ref" in the imports', + [ + '%ref' => $importRef + ] + ) + ); + } + + return $import; + } + + /** + * Get import category model based on given identifier + * + * @param integer $importCategoryId An import category identifier + * @param boolean $dispatchException Dispatch exception if model doesn't exist + * + * @throws \ErrorException + * + * @return null|\Thelia\Model\ImportCategory + */ + public function getCategory($importCategoryId, $dispatchException = false) + { + $category = (new ImportCategoryQuery)->findPk($importCategoryId); + + if ($category === null && $dispatchException) { + throw new \ErrorException( + Translator::getInstance()->trans( + 'There is no id "%id" in the import categories', + [ + '%id' => $importCategoryId + ] + ) + ); + } + + return $category; + } + + /** + * Import + * + * @param \Thelia\Model\Import $import + * @param \Symfony\Component\HttpFoundation\File\File $file + * @param null|\Thelia\Model\Lang $language + * + * @return \Thelia\Core\Event\ImportEvent + */ + public function import(Import $import, File $file, Lang $language = null) + { + $archiver = $this->matchArchiverByExtension($file->getFilename()); + + if ($archiver !== null) { + $file = $this->extractArchive($file, $archiver); + } + + $serializer = $this->matchSerializerByExtension($file->getFilename()); + + if ($serializer === null) { + throw new FormValidationException( + Translator::getInstance()->trans( + 'The extension "%extension" is not allowed', + [ + '%extension' => pathinfo($file->getFilename(), PATHINFO_EXTENSION) + ] + ) + ); + } + + $importHandleClass = $import->getHandleClass(); + + /** @var \Thelia\ImportExport\Import\AbstractImport $instance */ + $instance = new $importHandleClass; + $instance->setContainer($this->container); + + // Configure handle class + $instance->setLang($language); + $instance->setFile($file); + + // Process import + $event = new ImportEvent($instance, $serializer); + + $this->eventDispatcher->dispatch(TheliaEvents::IMPORT_BEGIN, $event); + + $errors = $this->processImport($event->getImport(), $event->getSerializer()); + + $event->setErrors($errors); + + $this->eventDispatcher->dispatch(TheliaEvents::IMPORT_FINISHED, $event); + + $this->eventDispatcher->dispatch(TheliaEvents::IMPORT_SUCCESS, $event); + + return $event; + } + + /** + * Match archiver relative to file name + * + * @param string $fileName File name + * + * @return null|\Thelia\Core\Archiver\AbstractArchiver + */ + public function matchArchiverByExtension($fileName) + { + /** @var \Thelia\Core\Archiver\AbstractArchiver $archiver */ + foreach ($this->archiverManager->getArchivers(true) as $archiver) { + if (stripos($fileName, '.' . $archiver->getExtension()) !== false) { + return $archiver; + } + } + + return null; + } + + /** + * Match serializer relative to file name + * + * @param string $fileName File name + * + * @return null|\Thelia\Core\Serializer\AbstractSerializer + */ + public function matchSerializerByExtension($fileName) + { + /** @var \Thelia\Core\Serializer\AbstractSerializer $serializer */ + foreach ($this->serializerManager->getSerializers() as $serializer) { + if (stripos($fileName, '.' . $serializer->getExtension()) !== false) { + return $serializer; + } + } + + return null; + } + + /** + * Extract archive + * + * @param \Symfony\Component\HttpFoundation\File\File $file + * @param \Thelia\Core\Archiver\ArchiverInterface $archiver + * + * @return \Symfony\Component\HttpFoundation\File\File First file in unarchiver + */ + public function extractArchive(File $file, ArchiverInterface $archiver) + { + $archiver->open($file->getPathname()); + + $extractpath = dirname($archiver->getArchivePath()) . DS . uniqid(); + + $archiver->extract($extractpath); + + /** @var \DirectoryIterator $item */ + foreach (new \DirectoryIterator($extractpath) as $item) { + if (!$item->isDot() && $item->isFile()) { + $file = new File($item->getPathname()); + + break; + } + } + + return $file; + } + + /** + * Process import + * + * @param \Thelia\ImportExport\Import\AbstractImport $import An import + * @param \Thelia\Core\Serializer\SerializerInterface $serializer A serializer interface + * + * @return array List of errors + */ + protected function processImport(AbstractImport $import, SerializerInterface $serializer) + { + $errors = []; + + $import->setData($serializer->unserialize($import->getFile()->openFile('r'))); + + foreach ($import as $idx => $data) { + $import->checkMandatoryColumns($data); + + $error = $import->importData($data); + if ($error !== null) { + $errors[] = $error; + } + } + + return $errors; + } +} diff --git a/core/lib/Thelia/ImportExport/AbstractHandler.php b/core/lib/Thelia/ImportExport/AbstractHandler.php new file mode 100644 index 00000000..769ae7f7 --- /dev/null +++ b/core/lib/Thelia/ImportExport/AbstractHandler.php @@ -0,0 +1,23 @@ + + * @deprecated since 2.3 + */ +abstract class AbstractHandler +{ +} diff --git a/core/lib/Thelia/ImportExport/Export/AbstractExport.php b/core/lib/Thelia/ImportExport/Export/AbstractExport.php new file mode 100644 index 00000000..35339469 --- /dev/null +++ b/core/lib/Thelia/ImportExport/Export/AbstractExport.php @@ -0,0 +1,549 @@ + + */ +abstract class AbstractExport implements \Iterator +{ + /** + * @var string Default file name + */ + const FILE_NAME = 'export'; + + /** + * @var boolean Export images with data + */ + const EXPORT_IMAGE = false; + + /** + * @var boolean Export documents with data + */ + const EXPORT_DOCUMENT = false; + + /** + * @var boolean Use range date + */ + const USE_RANGE_DATE = false; + + /** + * @var SplFileObject|\Propel\Runtime\Util\PropelModelPager Data to export + */ + private $data; + + /** + * @var boolean True if data is array, false otherwise + */ + private $dataIsArray; + + /** + * @var boolean True if data is a path to a JSON file, false otherwise + */ + private $dataIsJSONFile; + + /** + * @var ContainerInterface + */ + protected $container; + + /** + * @var \Thelia\Model\Lang A language model + */ + protected $language; + + /** + * @var null|array List of fields in order in which they must be exported and there alias name + */ + protected $orderAndAliases; + + /** + * @var null|array Keep untranslated $orderAndAliases + */ + private $originalOrderAndAliases; + + /** + * @var boolean Whether to export images or not + */ + protected $exportImages = false; + + /** + * @var array Images paths list + */ + protected $imagesPaths = []; + + /** + * @var boolean Whether to export documents or not + */ + protected $exportDocuments = false; + + /** + * @var array Documents paths list + */ + protected $documentsPaths = []; + + /** + * @var null|array Export date range + */ + protected $rangeDate; + + /** + * @return array|false|mixed|string + * @throws \Exception + */ + public function current() + { + if ($this->dataIsJSONFile) { + /** @var resource $file */ + $result = json_decode($this->data->current(), true); + + if ($result !== null) { + return $result; + } + + return []; + } + + if ($this->dataIsArray) { + return current($this->data); + } + + $data = $this->data->getIterator()->current()->toArray(TableMap::TYPE_COLNAME, true, [], true); + + foreach ($this->data->getQuery()->getWith() as $withKey => $with) { + $data = array_merge($data, $data[$withKey]); + unset($data[$withKey]); + } + + return $data; + } + + /** + * @return bool|float|int|string|null + * @throws \Exception + */ + public function key() + { + if ($this->dataIsJSONFile) { + return $this->data->key(); + } + + if ($this->dataIsArray) { + return key($this->data); + } + + if ($this->data->getIterator()->key() !== null) { + return $this->data->getIterator()->key() + ($this->data->getPage() - 1) * 1000; + } + + return null; + } + + /** + * @throws \Exception + */ + public function next() + { + if ($this->dataIsJSONFile) { + $this->data->next(); + } else if ($this->dataIsArray) { + next($this->data); + } else { + $this->data->getIterator()->next(); + if (!$this->valid() && !$this->data->isLastPage()) { + $this->data = $this->data->getQuery()->paginate($this->data->getNextPage(), 1000); + $this->data->getIterator()->rewind(); + } + } + } + + /** + * @throws \Exception + */ + public function rewind() + { + // Since it's first method call on traversable, we get raw data here + // but we do not permit to go back + + if ($this->data === null) { + $data = $this->getData(); + + // Check if $data is a path to a json file + if (\is_string($data) + && '.json' === substr($data, -5) + && file_exists($data) + ) { + $this->data = new \SplFileObject($data, 'r'); + $this->data->setFlags(SPLFileObject::READ_AHEAD); + $this->dataIsJSONFile = true; + + $this->data->rewind(); + + return; + } + + if (\is_array($data)) { + $this->data = $data; + $this->dataIsArray = true; + reset($this->data); + + return; + } + + if ($data instanceof ModelCriteria) { + $this->data = $data->setFormatter(ModelCriteria::FORMAT_ON_DEMAND)->keepQuery(false)->paginate(1, 1000); + $this->data->getIterator()->rewind(); + + return; + } + + throw new \DomainException( + 'Data must an array, an instance of \\Propel\\Runtime\\ActiveQuery\\ModelCriteria or a JSON file ending with.json' + ); + } + + throw new \LogicException('Export data can\'t be rewinded'); + } + + /** + * @return bool + * @throws \Exception + */ + public function valid() + { + if ($this->dataIsJSONFile) { + return $this->data->valid(); + } + + if ($this->dataIsArray) { + return key($this->data) !== null; + } + + return $this->data->getIterator()->valid(); + } + + + /** + * Get language + * + * @return \Thelia\Model\Lang A language model + */ + public function getLang() + { + return $this->language; + } + + /** + * Set language + * + * @param null|\Thelia\Model\Lang $language A language model + * + * @return $this Return $this, allow chaining + */ + public function setLang(Lang $language = null) + { + $this->language = $language; + + if ($this->originalOrderAndAliases === null) { + $this->originalOrderAndAliases = $this->orderAndAliases; + } + + if ($this->language !== null && $this->orderAndAliases !== null) { + $previousLocale = Translator::getInstance()->getLocale(); + + Translator::getInstance()->setLocale($this->language->getLocale()); + foreach ($this->orderAndAliases as &$alias) { + $alias = Translator::getInstance()->trans($alias); + } + + Translator::getInstance()->setLocale($previousLocale); + } + + return $this; + } + + /** + * Check if export is empty + * @return bool true if export is empty, else false. + */ + public function isEmpty() + { + return empty($this->data); + } + + + /** + * Whether images has to be exported as data + * + * @return boolean + */ + public function hasImages() + { + return static::EXPORT_IMAGE; + } + + /** + * Get export images + * + * @return boolean Whether to export images or not + */ + public function isExportImages() + { + return $this->exportImages; + } + + /** + * Set export images + * + * @param boolean $exportImages Whether to export images or not + * + * @return $this Return $this, allow chaining + */ + public function setExportImages($exportImages) + { + $this->exportImages = $exportImages; + + return $this; + } + + /** + * Get images paths + * + * @return null|array Images paths list + */ + public function getImagesPaths() + { + return $this->imagesPaths; + } + + /** + * Set images paths + * + * @param array $imagesPaths Images paths list + * + * @return $this Return $this, allow chaining + */ + public function setImagesPaths(array $imagesPaths) + { + $this->imagesPaths = $imagesPaths; + + return $this; + } + + + /** + * Whether documents has to be exported as data + * + * @return boolean + */ + public function hasDocuments() + { + return static::EXPORT_DOCUMENT; + } + + /** + * Get export documents + * + * @return boolean Whether to export documents or not + */ + public function isExportDocuments() + { + return $this->exportDocuments; + } + + /** + * Set export documents + * + * @param boolean $exportDocuments Whether to export documents or not + * + * @return $this Return $this, allow chaining + */ + public function setExportDocuments($exportDocuments) + { + $this->exportDocuments = $exportDocuments; + + return $this; + } + + /** + * Get documents paths + * + * @return null|array Documents paths list + */ + public function getDocumentsPaths() + { + return $this->documentsPaths; + } + + /** + * Set documents paths + * + * @param array $documentsPaths Documents paths list + * + * @return $this Return $this, allow chaining + */ + public function setDocumentsPaths(array $documentsPaths) + { + $this->documentsPaths = $documentsPaths; + + return $this; + } + + + /** + * Get range date + * + * @return null|array Array with date range + */ + public function getRangeDate() + { + return $this->rangeDate; + } + + /** + * Set range date + * + * @param null|array $rangeDate Array with date range + * + * @return $this Return $this, allow chaining + */ + public function setRangeDate(array $rangeDate = null) + { + $this->rangeDate = $rangeDate; + + return $this; + } + + /** + * Whether export bounded with date + * + * @return boolean + */ + public function useRangeDate() + { + return static::USE_RANGE_DATE; + } + + + /** + * Get file name + * + * @return string Export file name + */ + public function getFileName() + { + return static::FILE_NAME; + } + + /** + * Apply order and aliases on data + * + * @param array $data Raw data + * + * @return array Ordered and aliased data + */ + public function applyOrderAndAliases(array $data) + { + if ($this->orderAndAliases === null) { + return $data; + } + + $processedData = []; + + foreach ($this->orderAndAliases as $key => $value) { + if (\is_int($key)) { + $fieldName = $value; + $fieldAlias = $value; + } else { + $fieldName = $key; + $fieldAlias = $value; + } + + if ($this->dataIsJSONFile) { + $fieldName = substr($fieldName, strripos($fieldName, '.')); + $fieldName = str_replace('.', '', $fieldName); + $fieldName = strtolower($fieldName); + } + + $processedData[$fieldAlias] = null; + if (array_key_exists($fieldName, $data)) { + $processedData[$fieldAlias] = $data[$fieldName]; + } + } + + return $processedData; + } + + /** + * Process data before serialization + * + * @param array $data Data before serialization + * + * @return array Processed data before serialization + */ + public function beforeSerialize(array $data) + { + foreach ($data as $idx => &$value) { + if ($value instanceof \DateTime) { + $value = $value->format('Y-m-d H:i:s'); + } + } + + return $data; + } + + /** + * Process data after serialization + * + * @param string $data Data after serialization + * + * @return string Processed after before serialization + */ + public function afterSerialize($data) + { + return $data; + } + + /** + * @param ContainerInterface $container + */ + public function setContainer(ContainerInterface $container) + { + $this->container = $container; + } + + /** + * @return ContainerInterface + */ + protected function getContainer() + { + return $this->container; + } + + /** + * Get data to export + * + * @return string|array|\Propel\Runtime\ActiveQuery\ModelCriteria Data to export + */ + abstract protected function getData(); +} diff --git a/core/lib/Thelia/ImportExport/Export/ArrayAbstractExport.php b/core/lib/Thelia/ImportExport/Export/ArrayAbstractExport.php new file mode 100644 index 00000000..4eeb8a26 --- /dev/null +++ b/core/lib/Thelia/ImportExport/Export/ArrayAbstractExport.php @@ -0,0 +1,61 @@ +data); + } + + public function key() + { + return key($this->data); + } + + public function next() + { + next($this->data); + } + + public function rewind() + { + if ($this->data === null) { + $data = $this->getData(); + + if (\is_array($data)) { + $this->data = $data; + reset($this->data); + + return; + } + + throw new \DomainException( + 'Data must be an array.' + ); + } + + throw new \LogicException('Export data can\'t be rewinded'); + } + + public function valid() + { + return key($this->data) !== null; + } +} diff --git a/core/lib/Thelia/ImportExport/Export/ExportHandler.php b/core/lib/Thelia/ImportExport/Export/ExportHandler.php new file mode 100644 index 00000000..4f0f8dbf --- /dev/null +++ b/core/lib/Thelia/ImportExport/Export/ExportHandler.php @@ -0,0 +1,25 @@ + + * @deprecated since 2.3, fore more information http://doc.thelia.net/en/documentation/features/import_export/export.html + */ +abstract class ExportHandler extends AbstractHandler +{ +} diff --git a/core/lib/Thelia/ImportExport/Export/JsonFileAbstractExport.php b/core/lib/Thelia/ImportExport/Export/JsonFileAbstractExport.php new file mode 100644 index 00000000..621951ab --- /dev/null +++ b/core/lib/Thelia/ImportExport/Export/JsonFileAbstractExport.php @@ -0,0 +1,114 @@ + + */ +abstract class JsonFileAbstractExport extends AbstractExport +{ + /** + * @var SplFileObject Data to export + */ + private $data; + + public function current() + { + /** @var resource $file */ + $result = json_decode($this->data->current(), true); + + if ($result !== null) { + return $result; + } + + return []; + } + + public function key() + { + return $this->data->key(); + } + + public function next() + { + $this->data->next(); + } + + public function rewind() + { + if ($this->data === null) { + $data = $this->getData(); + + // Check if $data is a path to a json file + if (\is_string($data) + && '.json' === substr($data, -5) + && file_exists($data) + ) { + $this->data = new \SplFileObject($data, 'r'); + $this->data->setFlags(SPLFileObject::READ_AHEAD); + + $this->data->rewind(); + + return; + } + + throw new \DomainException( + 'Data shoul de a JSON file, ending with .json' + ); + } + + throw new \LogicException('Export data can\'t be rewinded'); + } + + public function valid() + { + return $this->data->valid(); + } + + /** + * Apply order and aliases on data + * + * @param array $data Raw data + * + * @return array Ordered and aliased data + */ + public function applyOrderAndAliases(array $data) + { + if ($this->orderAndAliases === null) { + return $data; + } + + $processedData = []; + + foreach ($this->orderAndAliases as $key => $value) { + if (\is_int($key)) { + $fieldName = $value; + $fieldAlias = $value; + } else { + $fieldName = $key; + $fieldAlias = $value; + } + + $processedData[$fieldAlias] = null; + if (array_key_exists($fieldName, $data)) { + $processedData[$fieldAlias] = $data[$fieldName]; + } + } + + return $processedData; + } +} diff --git a/core/lib/Thelia/ImportExport/Export/PropelCollectionAbstractExport.php b/core/lib/Thelia/ImportExport/Export/PropelCollectionAbstractExport.php new file mode 100644 index 00000000..7a59d9f3 --- /dev/null +++ b/core/lib/Thelia/ImportExport/Export/PropelCollectionAbstractExport.php @@ -0,0 +1,97 @@ +data->getIterator()->current()->toArray(TableMap::TYPE_COLNAME, true, [], true); + + foreach ($this->data->getQuery()->getWith() as $withKey => $with) { + $data = array_merge($data, $data[$withKey]); + unset($data[$withKey]); + } + + return $data; + } + + /** + * @return bool|float|int|string|null + * @throws \Exception + */ + public function key() + { + if ($this->data->getIterator()->key() !== null) { + return $this->data->getIterator()->key() + ($this->data->getPage() - 1) * 1000; + } + + return null; + } + + /** + * @throws \Exception + */ + public function next() + { + $this->data->getIterator()->next(); + if (!$this->valid() && !$this->data->isLastPage()) { + $this->data = $this->data->getQuery()->paginate($this->data->getNextPage(), 1000); + $this->data->getIterator()->rewind(); + } + } + + /** + * @throws \Exception + */ + public function rewind() + { + if ($this->data === null) { + $data = $this->getData(); + + if ($data instanceof ModelCriteria) { + $this->data = $data->setFormatter(ModelCriteria::FORMAT_ON_DEMAND)->keepQuery(false)->paginate(1, 1000); + $this->data->getIterator()->rewind(); + + return; + } + + throw new \DomainException( + 'Data must be an instance of \\Propel\\Runtime\\ActiveQuery\\ModelCriteria' + ); + } + + throw new \LogicException('Export data can\'t be rewinded'); + } + + /** + * @return bool + * @throws \Exception + */ + public function valid() + { + return $this->data->getIterator()->valid(); + } +} diff --git a/core/lib/Thelia/ImportExport/Export/Type/ContentExport.php b/core/lib/Thelia/ImportExport/Export/Type/ContentExport.php new file mode 100644 index 00000000..7e2be737 --- /dev/null +++ b/core/lib/Thelia/ImportExport/Export/Type/ContentExport.php @@ -0,0 +1,109 @@ + + * @author Jérôme Billiras + * @author Florian Bernard + */ +class ContentExport extends JsonFileAbstractExport +{ + const FILE_NAME = 'content'; + + const EXPORT_IMAGE = true; + + const EXPORT_DOCUMENT = true; + + const DIRECTORY_NAME = "content"; + + protected $orderAndAliases = [ + 'content_id' => 'id', + 'content_i18n_title' => 'title', + 'content_i18n_chapo' => 'chapo', + 'content_i18n_description' => 'description', + 'content_i18n_postscriptum' => 'conclusion', + 'content_visible' => 'visible', + 'content_i18n_meta_title' => 'seo_title', + 'content_i18n_meta_description' => 'seo_description', + 'content_i18n_meta_keywords' => 'seo_keywords', + 'rewriting_url_url' => 'url', + 'content_folder_folder_id' => 'folder_id', + 'content_folder_default_folder' => 'is_default_folder', + 'folder_i18n_title' => 'folder_title' + ]; + + /** + * Class constructor + */ + public function __construct() + { + $this->imagesPaths = [ + THELIA_ROOT . ConfigQuery::read('images_library_path') . DS . 'content' + ]; + + $this->documentsPaths = [ + THELIA_ROOT . ConfigQuery::read('documents_library_path') . DS . 'content' + ]; + } + + public function getData() + { + $locale = $this->language->getLocale(); + + $con = Propel::getConnection(); + $query = 'SELECT + content.id as "content_id", + content_i18n.title as "content_i18n_title", + content_i18n.chapo as "content_i18n_chapo", + content_i18n.description as "content_i18n_description", + content_i18n.postscriptum as "content_i18n_postscriptum", + content.visible as "content_visible", + content_i18n.meta_title as "content_i18n_meta_title", + content_i18n.meta_description as "content_i18n_meta_description", + content_i18n.meta_keywords as "content_i18n_meta_keywords", + rewriting_url.url as "rewriting_url_url", + content_folder.folder_id as "content_folder_folder_id", + content_folder.default_folder as "content_folder_default_folder", + folder_i18n.title as "folder_i18n_title" + FROM content + LEFT JOIN content_i18n ON content_i18n.id = content.id AND content_i18n.locale = :locale + LEFT JOIN content_folder ON content_folder.content_id = content.id + LEFT JOIN folder_i18n ON folder_i18n.id = content_folder.folder_id AND folder_i18n.locale = :locale + LEFT JOIN rewriting_url ON rewriting_url.view = "'.(new Content())->getRewrittenUrlViewName().'" AND rewriting_url.view_id = content.id + GROUP BY content.id' + ; + $stmt = $con->prepare($query); + $stmt->bindValue('locale', $locale); + $stmt->execute(); + + $filename = THELIA_CACHE_DIR . '/export/' . 'content.json'; + + if (file_exists($filename)) { + unlink($filename); + } + + while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) { + file_put_contents($filename, json_encode($row) . "\r\n", FILE_APPEND); + } + + return $filename; + } +} diff --git a/core/lib/Thelia/ImportExport/Export/Type/CustomerExport.php b/core/lib/Thelia/ImportExport/Export/Type/CustomerExport.php new file mode 100644 index 00000000..098382bf --- /dev/null +++ b/core/lib/Thelia/ImportExport/Export/Type/CustomerExport.php @@ -0,0 +1,95 @@ + + * @author Jérôme Billiras + * @author Florian Bernard + */ +class CustomerExport extends JsonFileAbstractExport +{ + const FILE_NAME = 'customer'; + + protected $orderAndAliases = [ + 'customer_ref' => 'ref', + 'customer_title_i18n_long' => 'title', + 'customer_firstname' => 'last_name', + 'customer_lastname' => 'first_name', + 'customer_email' => 'email', + 'customer_discount' => 'discount', + 'newsletter_id' => 'is_registered_to_newsletter', + 'customer_created_at' => 'sign_up_date', + 'address_company' => 'company', + 'address_address1' => 'address1', + 'address_address2' => 'address2', + 'address_address3' => 'address3', + 'address_zipcode' => 'zipcode', + 'address_city' => 'city', + 'country_i18n_title' => 'country', + 'address_phone' => 'phone', + 'address_cellphone' => 'cellphone' + ]; + + protected function getData() + { + $locale = $this->language->getLocale(); + + $con = Propel::getConnection(); + $query = 'SELECT + customer.ref as "customer_ref", + customer_title_i18n.long as "customer_title_i18n_long", + customer.firstname as "customer_firstname", + customer.lastname as "customer_lastname", + customer.email as "customer_email", + customer.discount as "customer_discount", + address.company as "address_company", + address.address1 as "address_address1", + address.address2 as "address_address2", + address.address3 as "address_address3", + address.zipcode as "address_zipcode", + address.city as "address_city", + country_i18n.title as "country_i18n_title", + newsletter.id as "newsletter_id", + address.phone as "address_phone", + address.cellphone as "address_cellphone", + customer.created_at as "customer_created_at" + FROM customer + LEFT JOIN customer_title_i18n ON customer.title_id = customer_title_i18n.id AND customer_title_i18n.locale = :locale + LEFT JOIN address ON address.customer_id = customer.id AND address.is_default = 1 + LEFT JOIN country_i18n ON address.country_id = country_i18n.id AND country_i18n.locale = :locale + LEFT JOIN newsletter ON newsletter.email = customer.email + GROUP BY customer.id' + ; + $stmt = $con->prepare($query); + $stmt->bindValue('locale', $locale); + $stmt->execute(); + + $filename = THELIA_CACHE_DIR . '/export/' . 'customer.json'; + + if (file_exists($filename)) { + unlink($filename); + } + + while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) { + file_put_contents($filename, json_encode($row) . "\r\n", FILE_APPEND); + } + + return $filename; + } +} diff --git a/core/lib/Thelia/ImportExport/Export/Type/MailingExport.php b/core/lib/Thelia/ImportExport/Export/Type/MailingExport.php new file mode 100644 index 00000000..3e4167c5 --- /dev/null +++ b/core/lib/Thelia/ImportExport/Export/Type/MailingExport.php @@ -0,0 +1,61 @@ + + * @author Florian Bernard + */ +class MailingExport extends JsonFileAbstractExport +{ + const FILE_NAME = 'mailing'; + + protected $orderAndAliases = [ + 'newsletter_id' => 'Identifier', + 'newsletter_email' => 'Email', + 'newsletter_firstname' => 'FirstName', + 'newsletter_lastname' => 'LastName' + ]; + + protected function getData() + { + $con = Propel::getConnection(); + $query = 'SELECT + newsletter.id as "newsletter_id", + newsletter.email as "newsletter_email", + newsletter.firstname as "newsletter_firstname", + newsletter.lastname as "newsletter_lastname" + FROM newsletter + WHERE newsletter.unsubscribed = 0' + ; + $stmt = $con->prepare($query); + $stmt->execute(); + + $filename = THELIA_CACHE_DIR . '/export/' . 'mailing.json'; + + if (file_exists($filename)) { + unlink($filename); + } + + while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) { + file_put_contents($filename, json_encode($row) . "\r\n", FILE_APPEND); + } + + return $filename; + } +} diff --git a/core/lib/Thelia/ImportExport/Export/Type/OrderExport.php b/core/lib/Thelia/ImportExport/Export/Type/OrderExport.php new file mode 100644 index 00000000..8f1753f2 --- /dev/null +++ b/core/lib/Thelia/ImportExport/Export/Type/OrderExport.php @@ -0,0 +1,180 @@ + + * @author Florian Bernard + */ +class OrderExport extends JsonFileAbstractExport +{ + const FILE_NAME = 'order'; + const USE_RANGE_DATE = true; + + protected $orderAndAliases = [ + 'order_ref' => 'ref', + 'order_created_at' => 'date', + 'customer_ref' => 'customer_ref', + 'order_coupon_code' => 'coupons', + 'order_total_price' => 'total_excluding_taxes', + 'order_total_tax' => 'total_taxes', + 'order_total_taxed_price' => 'total_taxed_price', + 'order_discount' => 'discount', + 'order_postage' => 'shipping_cost', + 'order_total_with_taxes_shipping_discount' => 'total_including_taxes', + 'delivery_module_title' => 'delivery_module', + 'order_delivery_ref' => 'delivery_ref', + 'payment_module_title' => 'payment_module', + 'order_invoice_ref' => 'invoice_ref', + 'order_status_i18n_title' => 'status', + 'delivery_address_customer_title_long' => 'delivery_title', + 'delivery_address_company' => 'delivery_company', + 'delivery_address_firstname' => 'delivery_first_name', + 'delivery_address_lastname' => 'delivery_last_name', + 'delivery_address_address1' => 'delivery_address_1', + 'delivery_address_address2' => 'delivery_address_2', + 'delivery_address_address3' => 'delivery_address_3', + 'delivery_address_zipcode' => 'delivery_zip_code', + 'delivery_address_city' => 'delivery_city', + 'delivery_country_i18n_title' => 'invoice_country', + 'delivery_address_phone' => 'delivery_phone', + 'invoice_address_customer_title_long' => 'invoice_title', + 'invoice_address_company' => 'invoice_company', + 'invoice_address_firstname' => 'invoice_first_name', + 'invoice_address_lastname' => 'invoice_last_name', + 'invoice_address_address1' => 'invoice_address_1', + 'invoice_address_address2' => 'invoice_address_2', + 'invoice_address_address3' => 'invoice_address_3', + 'invoice_address_zipcode' => 'invoice_zip_code', + 'invoice_address_city' => 'invoice_city', + 'invoice_country_i18n_title' => 'invoice_country', + 'invoice_address_phone' => 'invoice_phone', + 'currency_code' => 'currency', + 'order_postage_tax' => 'shipping_tax', + 'order_postage_tax_rule_title' => 'shipping_tax_rule_title', + 'order_product_tax_title' => 'tax', + ]; + + protected function getData() + { + $locale = $this->language->getLocale(); + + $con = Propel::getConnection(); + + $query = ' + SELECT + *, + (order_total_taxed_price - order_total_price) as order_total_tax, + (order_total_taxed_price + order_postage - order_discount) as order_total_with_taxes_shipping_discount + FROM ( + SELECT + `order`.ref as "order_ref", + `order`.created_at as "order_created_at", + customer.ref as "customer_ref", + ROUND(`order`.discount, 2) as order_discount, + order_coupon.code as order_coupon_code, + ROUND(`order`.postage, 2) as order_postage, + `order`.postage_tax as "order_postage_tax", + ROUND(`order`.postage_tax_rule_title,2) as "order_postage_tax_rule_title", + SUM(ROUND(order_product.quantity * IF(order_product.was_in_promo = 1, order_product.promo_price, order_product.price), 2) ) as order_total_price, + SUM( + ROUND( + order_product.quantity * ( + IF(order_product.was_in_promo = 1, order_product.promo_price, order_product.price) + + + ( + SELECT + COALESCE(SUM(IF(order_product.was_in_promo, order_product_tax.promo_amount, order_product_tax.amount)), 0) + FROM + order_product_tax + WHERE + order_product_tax.order_product_id = order_product.id + ) + ), 2 + ) + ) as order_total_taxed_price, + delivery_module.title as "delivery_module_title", + `order`.delivery_ref as "order_delivery_ref", + payment_module.title as "payment_module_title", + `order`.invoice_ref as "order_invoice_ref", + order_status_i18n.title as "order_status_i18n_title", + delivery_address_customer_title.long as "delivery_address_customer_title_long", + delivery_address.company as "delivery_address_company", + delivery_address.firstname as "delivery_address_firstname", + delivery_address.lastname as "delivery_address_lastname", + delivery_address.address1 as "delivery_address_address1", + delivery_address.address2 as "delivery_address_address2", + delivery_address.address3 as "delivery_address_address3", + delivery_address.zipcode as "delivery_address_zipcode", + delivery_address.city as "delivery_address_city", + delivery_country_i18n.title as "delivery_country_i18n_title", + delivery_address.phone as "delivery_address_phone", + invoice_address_customer_title.long as "invoice_address_customer_title_long", + invoice_address.company as "invoice_address_company", + invoice_address.firstname as "invoice_address_firstname", + invoice_address.lastname as "invoice_address_lastname", + invoice_address.address1 as "invoice_address_address1", + invoice_address.address2 as "invoice_address_address2", + invoice_address.address3 as "invoice_address_address3", + invoice_address.zipcode as "invoice_address_zipcode", + invoice_address.city as "invoice_address_city", + invoice_country_i18n.title as "invoice_country_i18n_title", + invoice_address.phone as "invoice_address_phone", + currency.code as "currency_code", + order_product_tax.title as "order_product_tax_title" + FROM `order` + LEFT JOIN customer ON customer.id = `order`.customer_id + LEFT JOIN order_product ON order_product.order_id = `order`.id + LEFT JOIN order_product_tax ON order_product_tax.order_product_id = order_product.id + LEFT JOIN order_coupon ON order_coupon.order_id = `order`.id + LEFT JOIN `module_i18n` as delivery_module ON delivery_module.id = `order`.delivery_module_id AND delivery_module.locale = :locale + LEFT JOIN `module_i18n` as payment_module ON payment_module.id = `order`.payment_module_id AND payment_module.locale = :locale + LEFT JOIN order_status_i18n ON order_status_i18n.id = `order`.status_id AND order_status_i18n.locale = :locale + LEFT JOIN order_address as delivery_address ON delivery_address.id = `order`.delivery_order_address_id + LEFT JOIN order_address as invoice_address ON invoice_address.id = `order`.invoice_order_address_id + LEFT JOIN customer_title_i18n as delivery_address_customer_title ON delivery_address_customer_title.id = delivery_address.customer_title_id AND delivery_address_customer_title.locale = :locale + LEFT JOIN customer_title_i18n as invoice_address_customer_title ON invoice_address_customer_title.id = invoice_address.customer_title_id AND invoice_address_customer_title.locale = :locale + LEFT JOIN country_i18n as delivery_country_i18n ON delivery_country_i18n.id = delivery_address.country_id AND delivery_country_i18n.locale = :locale + LEFT JOIN country_i18n as invoice_country_i18n ON invoice_country_i18n.id = invoice_address.country_id AND invoice_country_i18n.locale = :locale + LEFT JOIN currency ON currency.id = order.currency_id + WHERE `order`.created_at >= :start AND `order`.created_at <= :end + GROUP BY `order`.id + ORDER BY `order`.created_at DESC + ) as tmp + '; + + $stmt = $con->prepare($query); + $stmt->bindValue('locale', $locale); + $stmt->bindValue('start', $this->rangeDate['start']->format('Y-m-d')); + $stmt->bindValue('end', $this->rangeDate['end']->format('Y-m-d')); + $stmt->execute(); + + $filename = THELIA_CACHE_DIR . '/export/' . 'order.json'; + + if (file_exists($filename)) { + unlink($filename); + } + + while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) { + file_put_contents($filename, json_encode($row) . "\r\n", FILE_APPEND); + } + + return $filename; + } +} diff --git a/core/lib/Thelia/ImportExport/Export/Type/ProductI18nExport.php b/core/lib/Thelia/ImportExport/Export/Type/ProductI18nExport.php new file mode 100644 index 00000000..378ee0e2 --- /dev/null +++ b/core/lib/Thelia/ImportExport/Export/Type/ProductI18nExport.php @@ -0,0 +1,83 @@ + 'ref', + 'product_i18n_TITLE' => 'product_title', + 'product_i18n_CHAPO' => 'product_chapo', + 'product_i18n_DESCRIPTION' => 'product_description', + 'product_i18n_POSTSCRIPTUM' => 'product_postscriptum', + ]; + + protected $idxStripHtml = [ + 'product_i18n_CHAPO', + 'product_i18n_DESCRIPTION', + 'product_i18n_POSTSCRIPTUM', + ]; + + protected function getData() + { + $locale = $this->language->getLocale(); + + $con = Propel::getConnection(); + + $query = 'SELECT + product.ref as product_ref, + product_i18n.title as "product_i18n_TITLE", + product_i18n.chapo as "product_i18n_CHAPO", + product_i18n.description as "product_i18n_DESCRIPTION", + product_i18n.postscriptum as "product_i18n_POSTSCRIPTUM" + FROM product + LEFT JOIN product_i18n ON (product_i18n.id = product.id AND product_i18n.locale = :locale)' + ; + + $stmt = $con->prepare($query); + $stmt->bindValue('locale', $locale); + $stmt->execute(); + + $filename = THELIA_CACHE_DIR . '/export/' . 'product_i18n.json'; + + if(file_exists($filename)){ + unlink($filename); + } + + while ($row = $stmt->fetch(\PDO::FETCH_ASSOC)) { + file_put_contents($filename, json_encode($row) . "\r\n", FILE_APPEND); + } + + return $filename; + } + + /** + * @param array $data + * @return array + */ + public function beforeSerialize(array $data) + { + foreach ($data as $idx => &$value) { + if (in_array($idx, $this->idxStripHtml) && !empty($value)) { + $value = strip_tags($value); + + $value = html_entity_decode($value, ENT_QUOTES, 'UTF-8'); + } + } + + return parent::beforeSerialize($data); + } +} \ No newline at end of file diff --git a/core/lib/Thelia/ImportExport/Export/Type/ProductPricesExport.php b/core/lib/Thelia/ImportExport/Export/Type/ProductPricesExport.php new file mode 100644 index 00000000..b9793a84 --- /dev/null +++ b/core/lib/Thelia/ImportExport/Export/Type/ProductPricesExport.php @@ -0,0 +1,84 @@ + + * @author Jérôme Billiras + * @contributor Thomas Arnaud + * @author Florian Bernard + */ +class ProductPricesExport extends JsonFileAbstractExport +{ + const FILE_NAME = 'product_price'; + + protected $orderAndAliases = [ + 'product_sale_elements_id' => 'id', + 'product_i18n_id' => 'product_id', + 'product_i18n_title' => 'product_title', + 'attribute_av_i18n_title' => 'attributes', + 'product_sale_elements_ean_code' => 'ean', + 'product_price_price' => 'price', + 'product_price_promo_price' => 'promo_price', + 'currency_code' => 'currency', + 'product_sale_elements_promo' => 'promo' + ]; + + protected function getData() + { + $locale = $this->language->getLocale(); + + $con = Propel::getConnection(); + $query = 'SELECT + product_sale_elements.id as "product_sale_elements_id", + product_i18n.id as "product_i18n_id", + product_i18n.title as "product_i18n_title", + attribute_av_i18n.title as "attribute_av_i18n_title", + product_sale_elements.ean_code as "product_sale_elements_ean_code", + ROUND(product_price.price, 2) as "product_price_price", + ROUND(product_price.promo_price, 2) as "product_price_promo_price", + currency.code as "currency_code", + product_sale_elements.promo as "product_sale_elements_promo" + FROM product_sale_elements + LEFT JOIN product_i18n ON product_i18n.id = product_sale_elements.product_id + LEFT JOIN attribute_combination ON attribute_combination.product_sale_elements_id = product_sale_elements.id + LEFT JOIN attribute_av_i18n ON attribute_av_i18n.id = attribute_combination.attribute_av_id AND attribute_av_i18n.locale = :locale + LEFT JOIN product_price ON product_price.product_sale_elements_id = product_sale_elements.id + LEFT JOIN currency ON currency.id = product_price.currency_id' + ; + + $stmt = $con->prepare($query); + $stmt->bindValue('locale', $locale); + $stmt->execute(); + + $filename = THELIA_CACHE_DIR . '/export/' . 'product_price.json'; + + if (file_exists($filename)) { + unlink($filename); + } + + while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) { + file_put_contents($filename, json_encode($row) . "\r\n", FILE_APPEND); + } + + return $filename; + } +} diff --git a/core/lib/Thelia/ImportExport/Export/Type/ProductSEOExport.php b/core/lib/Thelia/ImportExport/Export/Type/ProductSEOExport.php new file mode 100644 index 00000000..5c45316e --- /dev/null +++ b/core/lib/Thelia/ImportExport/Export/Type/ProductSEOExport.php @@ -0,0 +1,76 @@ + + * @author Jérôme Billiras + * @author Florian Bernard + */ +class ProductSEOExport extends JsonFileAbstractExport +{ + const FILE_NAME = 'product_seo'; + + protected $orderAndAliases = [ + 'product_ref' => 'ref', + 'product_i18n_title' => 'product_title', + 'product_visible' => 'visible', + 'rewriting_url_url' => 'url', + 'product_i18n_meta_title' => 'page_title', + 'product_i18n_meta_description' => 'meta_description', + 'product_i18n_meta_keywords' => 'meta_keywords', + ]; + + public function getData() + { + $locale = $this->language->getLocale(); + + $con = Propel::getConnection(); + $query = 'SELECT + product.ref as "product_ref", + product_i18n.title as "product_i18n_title", + product.visible as "product_visible", + rewriting_url.url as "rewriting_url_url", + product_i18n.meta_title as "product_i18n_meta_title", + product_i18n.meta_description as "product_i18n_meta_description", + product_i18n.meta_keywords as "product_i18n_meta_keywords" + FROM product + LEFT JOIN product_i18n ON product_i18n.id = product.id AND product_i18n.locale = :locale + LEFT JOIN rewriting_url ON rewriting_url.view = "'.(new Product())->getRewrittenUrlViewName().'" AND rewriting_url.view_id = product.id + ORDER BY product.id' + ; + $stmt = $con->prepare($query); + $stmt->bindValue('locale', $locale); + $stmt->execute(); + + $filename = THELIA_CACHE_DIR . '/export/' . 'product_seo.json'; + + if (file_exists($filename)) { + unlink($filename); + } + + while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) { + file_put_contents($filename, json_encode($row) . "\r\n", FILE_APPEND); + } + + return $filename; + } +} diff --git a/core/lib/Thelia/ImportExport/Export/Type/ProductTaxedPricesExport.php b/core/lib/Thelia/ImportExport/Export/Type/ProductTaxedPricesExport.php new file mode 100644 index 00000000..2849357f --- /dev/null +++ b/core/lib/Thelia/ImportExport/Export/Type/ProductTaxedPricesExport.php @@ -0,0 +1,89 @@ + + * @author Jérôme Billiras + * @author Florian Bernard + */ +class ProductTaxedPricesExport extends JsonFileAbstractExport +{ + const FILE_NAME = 'product_taxed_price'; + + protected $orderAndAliases = [ + 'product_sale_elements_id' => 'id', + 'product_sale_elements_product_id' => 'product_id', + 'product_i18n_title' => 'title', + 'attribute_av_i18n_title' => 'attributes', + 'product_sale_elements_ean_code' => 'ean', + 'product_price_price' => 'price', + 'product_price_promo_price' => 'promo_price', + 'currency_code' => 'currency', + 'product_sale_elements_promo' => 'promo', + 'tax_rule_i18n_id' => 'tax_id', + 'tax_rule_i18n_title' => 'tax_title' + ]; + + public function getData() + { + $locale = $this->language->getLocale(); + + $con = Propel::getConnection(); + $query = 'SELECT + product_sale_elements.id as "product_sale_elements_id", + product_sale_elements.product_id as "product_sale_elements_product_id", + product_i18n.title as "product_i18n_title", + attribute_av_i18n.title as "attribute_av_i18n_title", + product_sale_elements.ean_code as "product_sale_elements_ean_code", + product_price.price as "product_price_price", + product_price.promo_price as "product_price_promo_price", + currency.code as "currency_code", + product_sale_elements.promo as "product_sale_elements_promo", + tax_rule_i18n.id as "tax_rule_i18n_id", + tax_rule_i18n.title as "tax_rule_i18n_title" + FROM product_sale_elements + LEFT JOIN product ON product.id = product_sale_elements.product_id + LEFT JOIN product_i18n ON product_i18n.id = product.id AND product_i18n.locale = :locale + LEFT JOIN attribute_combination ON attribute_combination.product_sale_elements_id = product_sale_elements.id + LEFT JOIN attribute_av_i18n ON attribute_av_i18n.id = attribute_combination.attribute_av_id AND attribute_av_i18n.locale = :locale + LEFT JOIN product_price ON product_price.product_sale_elements_id = product_sale_elements.id + LEFT JOIN currency ON currency.id = product_price.currency_id + LEFT JOIN tax_rule_i18n ON tax_rule_i18n.id = product.tax_rule_id AND tax_rule_i18n.locale = :locale + ORDER BY product.id' + ; + + $stmt = $con->prepare($query); + $stmt->bindValue('locale', $locale); + $stmt->execute(); + + $filename = THELIA_CACHE_DIR . '/export/' . 'product_seo.json'; + + if (file_exists($filename)) { + unlink($filename); + } + + while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) { + file_put_contents($filename, json_encode($row) . "\r\n", FILE_APPEND); + } + + return $filename; + } +} diff --git a/core/lib/Thelia/ImportExport/Import/AbstractImport.php b/core/lib/Thelia/ImportExport/Import/AbstractImport.php new file mode 100644 index 00000000..43b226b2 --- /dev/null +++ b/core/lib/Thelia/ImportExport/Import/AbstractImport.php @@ -0,0 +1,224 @@ + + */ +abstract class AbstractImport implements \Iterator +{ + /** + * @var array + */ + private $data; + + /** + * @var \Symfony\Component\HttpFoundation\File\File + */ + protected $file; + + /** + * @var \Thelia\Model\Lang A language model + */ + protected $language; + + /** + * @var array Mandatory columns + */ + protected $mandatoryColumns = []; + + /** + * @var ContainerInterface + */ + protected $container; + + /** + * @var integer Imported row count + */ + protected $importedRows = 0; + + public function current() + { + return current($this->data); + } + + public function key() + { + return key($this->data); + } + + public function next() + { + next($this->data); + } + + public function rewind() + { + reset($this->data); + } + + public function valid() + { + return key($this->data) !== null; + } + + /** + * Get data + * + * @return array Parsed data + */ + public function getData() + { + return $this->data; + } + + /** + * Set data + * + * @param array $data Parsed data + * + * @return $this Return $this, allow chaining + */ + public function setData(array $data) + { + $this->data = $data; + + return $this; + } + + /** + * Get file + * + * @return \Symfony\Component\HttpFoundation\File\File + */ + public function getFile() + { + return $this->file; + } + + /** + * Set file + * + * @param \Symfony\Component\HttpFoundation\File\File $file + * + * @return $this Return $this, allow chaining + */ + public function setFile(File $file) + { + $this->file = $file; + + return $this; + } + + /** + * Get language + * + * @return \Thelia\Model\Lang A language model + */ + public function getLang() + { + return $this->language; + } + + /** + * Set language + * + * @param null|\Thelia\Model\Lang $language A language model + * + * @return $this Return $this, allow chaining + */ + public function setLang(Lang $language = null) + { + $this->language = $language; + + return $this; + } + + /** + * Check mandatory columns + * + * @param array $data Data + * + * @return boolean Data contains mandatory columns or not + */ + public function checkMandatoryColumns(array $data) + { + $diff = array_diff($this->mandatoryColumns, array_keys($data)); + + if (\count($diff) > 0) { + throw new \UnexpectedValueException( + Translator::getInstance()->trans( + 'The following columns are missing: %columns', + [ + '%columns' => implode(', ', $diff) + ] + ) + ); + } + } + + /** + * Get imported rows + * + * @return int Imported rows count + */ + public function getImportedRows() + { + return $this->importedRows; + } + + /** + * Set imported rows + * + * @param int $importedRows Imported rows count + * + * @return $this Return $this, allow chaining + */ + public function setImportedRows($importedRows) + { + $this->importedRows = $importedRows; + + return $this; + } + + /** + * @param ContainerInterface $container + */ + public function setContainer(ContainerInterface $container) + { + $this->container = $container; + } + + /** + * @return ContainerInterface + */ + protected function getContainer() + { + return $this->container; + } + + /** + * Import data + * + * @param array $data Data to import + * + * @return null|String String with error, null otherwise + */ + abstract public function importData(array $data); +} diff --git a/core/lib/Thelia/ImportExport/Import/ImportHandler.php b/core/lib/Thelia/ImportExport/Import/ImportHandler.php new file mode 100644 index 00000000..df6401f3 --- /dev/null +++ b/core/lib/Thelia/ImportExport/Import/ImportHandler.php @@ -0,0 +1,25 @@ + + * @deprecated since 2.3, fore more information http://doc.thelia.net/en/documentation/features/import_export/import.html + */ +abstract class ImportHandler extends AbstractHandler +{ +} diff --git a/core/lib/Thelia/ImportExport/Import/Type/ProductPricesImport.php b/core/lib/Thelia/ImportExport/Import/Type/ProductPricesImport.php new file mode 100644 index 00000000..6c9f0698 --- /dev/null +++ b/core/lib/Thelia/ImportExport/Import/Type/ProductPricesImport.php @@ -0,0 +1,88 @@ + + */ +class ProductPricesImport extends AbstractImport +{ + protected $mandatoryColumns = [ + 'id', + 'price' + ]; + + public function importData(array $data) + { + $pse = ProductSaleElementsQuery::create()->findPk($data['id']); + + if ($pse === null) { + return Translator::getInstance()->trans( + 'The product sale element id %id doesn\'t exist', + [ + '%id' => $data['id'] + ] + ); + } else { + $currency = null; + if (isset($data['currency'])) { + $currency = CurrencyQuery::create()->findOneByCode($data['currency']); + } + if ($currency === null) { + $currency = Currency::getDefaultCurrency(); + } + + $price = ProductPriceQuery::create() + ->filterByProductSaleElementsId($pse->getId()) + ->findOneByCurrencyId($currency->getId()) + ; + + if ($price === null) { + $price = new ProductPrice; + + $price + ->setProductSaleElements($pse) + ->setCurrency($currency) + ; + } + + $price->setPrice($data['price']); + + if (isset($data['promo_price'])) { + $price->setPromoPrice($data['promo_price']); + } + + if (isset($data['promo'])) { + $price + ->getProductSaleElements() + ->setPromo((int) $data['promo']) + ->save() + ; + } + + $price->save(); + $this->importedRows++; + } + + return null; + } +} diff --git a/core/lib/Thelia/ImportExport/Import/Type/ProductStockImport.php b/core/lib/Thelia/ImportExport/Import/Type/ProductStockImport.php new file mode 100644 index 00000000..80b1b769 --- /dev/null +++ b/core/lib/Thelia/ImportExport/Import/Type/ProductStockImport.php @@ -0,0 +1,54 @@ + + */ +class ProductStockImport extends AbstractImport +{ + protected $mandatoryColumns = [ + 'id', + 'stock' + ]; + + public function importData(array $data) + { + $pse = ProductSaleElementsQuery::create()->findPk($data['id']); + + if ($pse === null) { + return Translator::getInstance()->trans( + 'The product sale element id %id doesn\'t exist', + [ + '%id' => $data['id'] + ] + ); + } else { + $pse->setQuantity($data['stock']); + + if (isset($data['ean']) && !empty($data['ean'])) { + $pse->setEanCode($data['ean']); + } + + $pse->save(); + $this->importedRows++; + } + + return null; + } +} diff --git a/core/lib/Thelia/Install/BaseInstall.php b/core/lib/Thelia/Install/BaseInstall.php new file mode 100644 index 00000000..4bef5aa6 --- /dev/null +++ b/core/lib/Thelia/Install/BaseInstall.php @@ -0,0 +1,50 @@ + + */ +abstract class BaseInstall +{ + /** @var bool If Installation wizard is launched by CLI */ + protected $isConsoleMode = true; + + /** + * Constructor + * + * @param bool $verifyInstall Verify if an installation already exists + * + * @throws Exception\AlreadyInstallException + */ + public function __construct($verifyInstall = true) + { + // Check if install wizard is launched via CLI + if (php_sapi_name() == 'cli') { + $this->isConsoleMode = true; + } else { + $this->isConsoleMode = false; + } + if (file_exists(THELIA_CONF_DIR . '/database.yml') && $verifyInstall) { + throw new AlreadyInstallException("Thelia is already installed"); + } + + $this->exec(); + } + + abstract public function exec(); +} diff --git a/core/lib/Thelia/Install/CheckDatabaseConnection.php b/core/lib/Thelia/Install/CheckDatabaseConnection.php new file mode 100644 index 00000000..474bd247 --- /dev/null +++ b/core/lib/Thelia/Install/CheckDatabaseConnection.php @@ -0,0 +1,104 @@ + + * @author Guillaume MOREL + */ +class CheckDatabaseConnection extends BaseInstall +{ + protected $validationMessages = array(); + + /** @var bool If permissions are OK */ + protected $isValid = true; + + /** @var TranslatorInterface Translator Service */ + protected $translator = null; + + /** @var string Database host information */ + protected $host = null; + + /** @var string Database user information */ + protected $user = null; + + /** @var string Database password information */ + protected $password = null; + + /** @var int Database port information */ + protected $port = null; + + /** + * @var \PDO instance + */ + protected $connection = null; + + /** + * Constructor + * + * @param string $host Database host information + * @param string $user Database user information + * @param string $password Database password information + * @param int $port Database port information + * @param bool $verifyInstall If verify install + * @param Translator $translator Translator Service + * necessary for install wizard + */ + public function __construct($host, $user, $password, $port, $verifyInstall = true, Translator $translator = null) + { + $this->host = $host; + $this->user = $user; + $this->password = $password; + $this->port = $port; + + parent::__construct($verifyInstall); + } + + /** + * Perform database connection check + * + * @return bool + */ + public function exec() + { + $dsn = "mysql:host=%s;port=%s"; + + try { + $this->connection = new \PDO( + sprintf($dsn, $this->host, $this->port), + $this->user, + $this->password + ); + } catch (\PDOException $e) { + $this->validationMessages = 'Wrong connection information'; + + $this->isValid = false; + } + + return $this->isValid; + } + + public function getConnection() + { + return $this->connection; + } +} diff --git a/core/lib/Thelia/Install/CheckPermission.php b/core/lib/Thelia/Install/CheckPermission.php new file mode 100644 index 00000000..e0424e68 --- /dev/null +++ b/core/lib/Thelia/Install/CheckPermission.php @@ -0,0 +1,395 @@ + + * @author Guillaume MOREL + */ +class CheckPermission extends BaseInstall +{ + const DIR_CONF = 'local/config'; + const DIR_LOG = 'log'; + const DIR_CACHE = 'cache'; + const DIR_WEB = 'web'; + const DIR_SESSION = 'local/session'; + const DIR_MEDIA = 'local/media'; + + /** @var array Directory needed to be writable */ + protected $directoriesToBeWritable = array( + self::DIR_CONF, + self::DIR_LOG, + self::DIR_CACHE, + self::DIR_WEB, + self::DIR_SESSION, + self::DIR_MEDIA + ); + + /** @var array Minimum server configuration necessary */ + protected $minServerConfigurationNecessary = array( + 'memory_limit' => 134217728, + 'post_max_size' => 20971520, + 'upload_max_filesize' => 2097152 + ); + + protected $phpExpectedVerions = array( + 'min' => '5.5', + 'max' => '7.4' + ); + + protected $extensions = array( + 'curl', + 'fileinfo', + 'gd', + 'intl', + 'openssl', + 'pdo_mysql', + 'dom', + 'zip' + ); + + protected $validationMessages = array(); + + /** @var bool If permissions are OK */ + protected $isValid = true; + + /** @var TranslatorInterface Translator Service */ + protected $translator = null; + + /** + * Constructor + * + * @param bool $verifyInstall If verify install + * @param Translator $translator Translator Service + * necessary for install wizard + */ + public function __construct($verifyInstall = true, Translator $translator = null) + { + $this->translator = $translator; + + $this->validationMessages['php_version'] = array( + 'text' => $this->getI18nPhpVersionText(phpversion(), true), + 'hint' => $this->getI18nPhpVersionHint(), + 'status' => true + ); + + foreach ($this->directoriesToBeWritable as $directory) { + $this->validationMessages[$directory] = array( + 'text' => '', + 'hint' => '', + 'status' => true + ); + } + foreach ($this->minServerConfigurationNecessary as $key => $value) { + $this->validationMessages[$key] = array( + 'text' => '', + 'hint' => $this->getI18nConfigHint(), + 'status' => true + ); + } + + foreach ($this->extensions as $extension) { + $this->validationMessages[$extension] = array( + 'text' => '', + 'hint' => $this->getI18nExtensionHint(), + 'status' => true, + ); + } + + parent::__construct($verifyInstall); + } + + /** + * Perform file permission check + * + * @return bool + */ + public function exec() + { + if (version_compare(phpversion(), $this->phpExpectedVerions['min'], '<') || version_compare(phpversion(), $this->phpExpectedVerions['max'], '>=')) { + $this->isValid = false; + $this->validationMessages['php_version']['text'] = $this->getI18nPhpVersionText(phpversion(), false); + $this->validationMessages['php_version']['status'] = false; + $this->validationMessages['php_version']['hint'] = $this->getI18nPhpVersionHint(); + } + + foreach ($this->directoriesToBeWritable as $directory) { + $fullDirectory = THELIA_ROOT . $directory; + $this->validationMessages[$directory]['text'] = $this->getI18nDirectoryText($fullDirectory, true); + if (is_writable($fullDirectory) === false) { + if (!$this->makeDirectoryWritable($fullDirectory)) { + $this->isValid = false; + $this->validationMessages[$directory]['status'] = false; + $this->validationMessages[$directory]['text'] = $this->getI18nDirectoryText($fullDirectory, false); + } + } + } + + foreach ($this->minServerConfigurationNecessary as $key => $value) { + $this->validationMessages[$key]['text'] = $this->getI18nConfigText($key, $this->formatBytes($value), ini_get($key), true); + if (!$this->verifyServerMemoryValues($key, $value)) { + $this->isValid = false; + $this->validationMessages[$key]['status'] = false; + $this->validationMessages[$key]['text'] = $this->getI18nConfigText($key, $this->formatBytes($value), ini_get($key), false); + ; + } + } + + foreach ($this->extensions as $extension) { + $this->validationMessages[$extension]['text'] = $this->getI18nExtensionText($extension, true); + if (false === extension_loaded($extension)) { + $this->isValid = false; + $this->validationMessages[$extension]['status'] = false; + $this->validationMessages[$extension]['text'] = $this->getI18nExtensionText($extension, false); + } + } + + return $this->isValid; + } + + /** + * Get validation messages + * + * @return array + */ + public function getValidationMessages() + { + return $this->validationMessages; + } + + /** + * Make a directory writable (recursively) + * + * @param string $directory path to directory + * + * @return bool + */ + protected function makeDirectoryWritable($directory) + { + return (is_writable(THELIA_ROOT . $directory) === true); + } + + /** + * Get Translated text about the directory state + * + * @param string $directory Directory being checked + * @param bool $isValid If directory permission is valid + * + * @return string + */ + protected function getI18nDirectoryText($directory, $isValid) + { + if ($this->translator !== null) { + if ($isValid) { + $sentence = 'The directory %directory% is writable'; + } else { + $sentence = 'The directory %directory% is not writable'; + } + + $translatedText = $this->translator->trans( + $sentence, + array( + '%directory%' => $directory + ) + ); + } else { + $translatedText = sprintf('The directory %s should be writable', $directory); + } + + return $translatedText; + } + + protected function getI18nExtensionText($extension, $isValid) + { + if ($isValid) { + $sentence = '%extension% php extension is loaded.'; + } else { + $sentence = '%extension% php extension is not loaded.'; + } + + return $this->translator->trans($sentence, array( + '%extension%' => $extension + )); + } + + /** + * Get Translated text about the directory state + * Not usable with CLI + * + * @param string $key .ini file key + * @param string $expectedValue Expected server value + * @param string $currentValue Actual server value + * @param bool $isValid If server configuration is valid + * + * @return string + */ + protected function getI18nConfigText($key, $expectedValue, $currentValue, $isValid) + { + if ($isValid) { + $sentence = 'The PHP "%key%" configuration value (currently %currentValue%) is correct (%expectedValue% required).'; + } else { + $sentence = 'The PHP "%key%" configuration value (currently %currentValue%) is below minimal requirements to run Thelia2 (%expectedValue% required).'; + } + + $translatedText = $this->translator->trans( + $sentence, + array( + '%key%' => $key, + '%expectedValue%' => $expectedValue, + '%currentValue%' => $currentValue, + ), + 'install-wizard' + ); + + return $translatedText; + } + + protected function getI18nExtensionHint() + { + return $this->translator->trans('This PHP extension should be installed and loaded.'); + } + + /** + * Get Translated hint about the config requirement issue + * + * @return string + */ + protected function getI18nConfigHint() + { + $sentence = 'Change this value in the php.ini configuration file.'; + $translatedText = $this->translator->trans( + $sentence + ); + + return $translatedText; + } + + /** + * Get Translated hint about the PHP version requirement issue + * + * @param string $expectedValue + * @param string $currentValue + * @param bool $isValid + * + * @return string + */ + protected function getI18nPhpVersionText($currentValue, $isValid) + { + if ($this->translator !== null) { + if ($isValid) { + $sentence = 'PHP version %currentValue% matches the version required (> %minExpectedValue% < %maxExpectedValue%).'; + } else { + $sentence = 'The installer detected PHP version %currentValue%, but Thelia 2 requires PHP between %minExpectedValue% and %maxExpectedValue%.'; + } + + $translatedText = $this->translator->trans( + $sentence, + array( + '%minExpectedValue%' => $this->phpExpectedVerions['min'], + '%maxExpectedValue%' => $this->phpExpectedVerions['max'], + '%currentValue%' => $currentValue, + ) + ); + } else { + $translatedText = sprintf('Thelia requires PHP between %s and %s (%s currently).', $this->phpExpectedVerions['min'], $this->phpExpectedVerions['max'], $currentValue); + } + + return $translatedText; + } + + /** + * Get Translated hint about the config requirement issue + * + * @return string + */ + protected function getI18nPhpVersionHint() + { + $sentence = 'You should change the installed PHP version to continue Thelia 2 installation.'; + $translatedText = $this->translator->trans( + $sentence, + array() + ); + + return $translatedText; + } + + /** + * Check if a server memory value is met or not + * + * @param string $key .ini file key + * @param int $necessaryValueInBytes Expected value in bytes + * + * @return bool + */ + protected function verifyServerMemoryValues($key, $necessaryValueInBytes) + { + $serverValueInBytes = $this->returnBytes(ini_get($key)); + + if ($serverValueInBytes == -1) { + return true; + } + + return ($serverValueInBytes >= $necessaryValueInBytes); + } + + /** + * Return bytes from memory .ini value + * + * @param string $val .ini value + * + * @return int + */ + protected function returnBytes($val) + { + $val = trim($val); + $last = strtolower($val[strlen($val)-1]); + // Do not add breaks in the switch below + switch ($last) { + // The 'G' modifier is available since PHP 5.1.0 + case 'g': + $val = (int)$val*1024; + // no break + case 'm': + $val = (int)$val*1024; + // no break + case 'k': + $val = (int)$val*1024; + } + + return $val; + } + + /** + * Convert bytes to readable string + * + * @param int $bytes bytes + * @param int $precision conversion precision + * + * @return string + */ + protected function formatBytes($bytes, $precision = 2) + { + $base = log($bytes) / log(1024); + $suffixes = array('', 'k', 'M', 'G', 'T'); + + return round(pow(1024, $base - floor($base)), $precision) . $suffixes[floor($base)]; + } +} diff --git a/core/lib/Thelia/Install/Database.php b/core/lib/Thelia/Install/Database.php new file mode 100644 index 00000000..945cc5b0 --- /dev/null +++ b/core/lib/Thelia/Install/Database.php @@ -0,0 +1,280 @@ + + */ +class Database +{ + /** + * @var \PDO + */ + protected $connection; + + /** + * Create a new instance, using the provided connection information, either none for + * automatically a connection, a ConnectionWrapper instance (through ConnectionInterface) or a PDO connection. + * + * @param ConnectionInterface|\PDO|null $connection the connection object + * @throws \InvalidArgumentException if $connection is not of the suitable type. + */ + public function __construct($connection = null) + { + // Get a connection from Propel if we don't have one + if (null == $connection) { + $connection = Propel::getConnection(ServiceContainerInterface::CONNECTION_WRITE); + } + + // Get the PDO connection from an + if ($connection instanceof ConnectionWrapper) { + $connection = $connection->getWrappedConnection(); + } + + if (!$connection instanceof \PDO) { + throw new \InvalidArgumentException("A PDO connection should be provided"); + } + + $this->connection = $connection; + } + + /** + * Insert all sql needed in database + * Default insert /install/thelia.sql and /install/insert.sql + * + * @param string $dbName Database name + * @param array $extraSqlFiles SQL Files uri to insert + */ + public function insertSql($dbName = null, array $extraSqlFiles = null) + { + if ($dbName) { + $this->connection->query(sprintf("use `%s`", $dbName)); + } + + $sql = array(); + + if (null === $extraSqlFiles) { + $sql = array_merge( + $sql, + $this->prepareSql(file_get_contents(THELIA_SETUP_DIRECTORY . 'thelia.sql')), + $this->prepareSql(file_get_contents(THELIA_SETUP_DIRECTORY . 'insert.sql')) + ); + } else { + foreach ($extraSqlFiles as $fileToInsert) { + $sql = array_merge( + $sql, + $this->prepareSql(file_get_contents($fileToInsert)) + ); + } + } + $size = \count($sql); + for ($i = 0; $i < $size; $i++) { + if (!empty($sql[$i])) { + $this->execute($sql[$i]); + } + } + } + + /** + * A simple wrapper around PDO::exec + * + * @param string $sql SQL query + * @param array $args SQL request parameters (PDO style) + * @throws \RuntimeException|\PDOException if something goes wrong. + * @return \PDOStatement + */ + public function execute($sql, $args = array()) + { + $stmt = $this->connection->prepare($sql); + + if ($stmt === false) { + throw new \RuntimeException("Failed to prepare statement for $sql: " . print_r($this->connection->errorInfo(), 1)); + } + + $success = $stmt->execute($args); + + if ($success === false || $stmt->errorCode() != 0) { + throw new \RuntimeException("Failed to execute SQL '$sql', arguments:" . print_r($args, 1).", error:".print_r($stmt->errorInfo(), 1)); + } + + return $stmt; + } + + /** + * Separate each sql instruction in an array + * + * @param $sql + * @return array + */ + protected function prepareSql($sql) + { + $sql = str_replace(";',", "-CODE-", $sql); + $sql = trim($sql); + preg_match_all('#DELIMITER (.+?)\n(.+?)DELIMITER ;#s', $sql, $m); + foreach ($m[0] as $k => $v) { + if ($m[1][$k] == '|') { + throw new \RuntimeException('You can not use "|" as delimiter: '.$v); + } + $stored = str_replace(';', '|', $m[2][$k]); + $stored = str_replace($m[1][$k], ";\n", $stored); + $sql = str_replace($v, $stored, $sql); + } + $query = array(); + + $tab = explode(";\n", $sql); + $size = \count($tab); + for ($i = 0; $i < $size; $i++) { + $queryTemp = str_replace("-CODE-", ";',", $tab[$i]); + $queryTemp = str_replace("|", ";", $queryTemp); + $query[] = $queryTemp; + } + + return $query; + } + + /** + * Backup the db OR just a table + * + * @param string $filename + * @param string $tables + */ + public function backupDb($filename, $tables = '*') + { + $data = []; + + // get all of the tables + if ($tables == '*') { + $tables = array(); + $result = $this->connection->prepare('SHOW TABLES'); + $result->execute(); + while ($row = $result->fetch(PDO::FETCH_NUM)) { + $tables[] = $row[0]; + } + } else { + $tables = \is_array($tables) ? $tables : explode(',', $tables); + } + + $data[] = "\n"; + $data[] = 'SET foreign_key_checks=0;'; + $data[] = "\n\n"; + + foreach ($tables as $table) { + if (!preg_match("/^[\w_\-]+$/", $table)) { + Tlog::getInstance()->alert( + sprintf( + "Attempt to backup the db with this invalid table name: '%s'", + $table + ) + ); + + continue; + } + + $result = $this->execute('SELECT * FROM `' . $table . '`'); + + $fieldCount = $result->columnCount(); + + $data[] = 'DROP TABLE `' . $table . '`;'; + + $resultStruct = $this->execute('SHOW CREATE TABLE `' . $table . '`'); + + $rowStruct = $resultStruct->fetch(PDO::FETCH_NUM); + + $data[] = "\n\n"; + $data[] = $rowStruct[1]; + $data[] = ";\n\n"; + + for ($i = 0; $i < $fieldCount; $i++) { + while ($row = $result->fetch(PDO::FETCH_NUM)) { + $data[] = 'INSERT INTO `' . $table . '` VALUES('; + for ($j = 0; $j < $fieldCount; $j++) { + $row[$j] = addslashes($row[$j]); + $row[$j] = str_replace("\n", "\\n", $row[$j]); + if (isset($row[$j])) { + $data[] = '"' . $row[$j] . '"'; + } else { + $data[] = '""'; + } + if ($j < ($fieldCount - 1)) { + $data[] = ','; + } + } + $data[] = ");\n"; + } + } + $data[] = "\n\n\n"; + } + + $data[] = 'SET foreign_key_checks=1;'; + + //save filename + $this->writeFilename($filename, $data); + } + + + /** + * Restore a file in the current db + * + * @param string $filename the file containing sql queries + */ + public function restoreDb($filename) + { + $this->insertSql(null, [$filename]); + } + + /** + * Save an array of data to a filename + * + * @param string $filename + * @param array $data + */ + private function writeFilename($filename, $data) + { + $f = fopen($filename, "w+"); + + fwrite($f, implode('', $data)); + fclose($f); + } + + /** + * create database if not exists + * + * @param $dbName + */ + public function createDatabase($dbName) + { + $this->execute( + sprintf( + "CREATE DATABASE IF NOT EXISTS `%s` CHARACTER SET utf8", + $dbName + ) + ); + } + + /** + * @return PDO + */ + public function getConnection() + { + return $this->connection; + } +} diff --git a/core/lib/Thelia/Install/Exception/AlreadyInstallException.php b/core/lib/Thelia/Install/Exception/AlreadyInstallException.php new file mode 100644 index 00000000..40a972e1 --- /dev/null +++ b/core/lib/Thelia/Install/Exception/AlreadyInstallException.php @@ -0,0 +1,22 @@ + + */ +class AlreadyInstallException extends InstallException +{ +} diff --git a/core/lib/Thelia/Install/Exception/InstallException.php b/core/lib/Thelia/Install/Exception/InstallException.php new file mode 100644 index 00000000..167a53d3 --- /dev/null +++ b/core/lib/Thelia/Install/Exception/InstallException.php @@ -0,0 +1,21 @@ + + */ +class InstallException extends \RuntimeException +{ +} diff --git a/core/lib/Thelia/Install/Exception/UpToDateException.php b/core/lib/Thelia/Install/Exception/UpToDateException.php new file mode 100644 index 00000000..5f9833a2 --- /dev/null +++ b/core/lib/Thelia/Install/Exception/UpToDateException.php @@ -0,0 +1,22 @@ + + */ +class UpToDateException extends InstallException +{ +} diff --git a/core/lib/Thelia/Install/Exception/UpdateException.php b/core/lib/Thelia/Install/Exception/UpdateException.php new file mode 100644 index 00000000..183078f6 --- /dev/null +++ b/core/lib/Thelia/Install/Exception/UpdateException.php @@ -0,0 +1,41 @@ + + */ +class UpdateException extends \RuntimeException +{ + /** @var string the version that has failed */ + protected $version = null; + + /** + * @return string + */ + public function getVersion() + { + return $this->version; + } + + /** + * @param string $version + */ + public function setVersion($version) + { + $this->version = $version; + } +} diff --git a/core/lib/Thelia/Install/Update.php b/core/lib/Thelia/Install/Update.php new file mode 100644 index 00000000..b7780dbb --- /dev/null +++ b/core/lib/Thelia/Install/Update.php @@ -0,0 +1,600 @@ + + */ +class Update +{ + const SQL_DIR = 'update/sql/'; + + const PHP_DIR = 'update/php/'; + + const INSTRUCTION_DIR = 'update/instruction/'; + + protected $version = null; + + /** @var bool */ + protected $usePropel = null; + + /** @var null|Tlog */ + protected $logger = null; + + /** @var array log messages */ + protected $logs = []; + + /** @var array post instructions */ + protected $postInstructions = []; + + /** @var array */ + protected $updatedVersions = []; + + /** @var PDO */ + protected $connection = null; + + /** @var string|null */ + protected $backupFile = null; + + /** @var string */ + protected $backupDir = 'local/backup/'; + + /** @var array */ + protected $messages = []; + + /** @var Translator */ + protected $translator; + + public function __construct($usePropel = true) + { + $this->usePropel = $usePropel; + + if ($this->usePropel) { + $this->logger = Tlog::getInstance(); + $this->logger->setLevel(Tlog::DEBUG); + } else { + $this->logs = []; + } + + $dbConfig = null; + + try { + $this->connection = $this->getDatabasePDO(); + } catch (ParseException $ex) { + throw new UpdateException("database.yml is not a valid file : " . $ex->getMessage()); + } catch (\PDOException $ex) { + throw new UpdateException('Wrong connection information' . $ex->getMessage()); + } + + $this->version = $this->getVersionList(); + } + + /** + * retrieve the database connection + * + * @return \PDO + * @throws ParseException + * @throws \PDOException + */ + protected function getDatabasePDO() + { + $configPath = THELIA_CONF_DIR . "database.yml"; + + if (!file_exists($configPath)) { + throw new UpdateException("Thelia is not installed yet"); + } + + $definePropel = new DatabaseConfigurationSource( + Yaml::parse(file_get_contents($configPath)), + $this->getEnvParameters() + ); + + return $definePropel->getTheliaConnectionPDO(); + } + + /** + * Gets the environment parameters. + * + * Only the parameters starting with "SYMFONY__" are considered. + * + * @return array An array of parameters + */ + protected function getEnvParameters() + { + $parameters = array(); + foreach ($_SERVER as $key => $value) { + if (0 === strpos($key, 'SYMFONY__')) { + $parameters[strtolower(str_replace('__', '.', substr($key, 9)))] = $value; + } + } + + return $parameters; + } + + public function isLatestVersion($version = null) + { + if (null === $version) { + $version = $this->getCurrentVersion(); + } + $lastEntry = end($this->version); + + return $lastEntry == $version; + } + + public function process() + { + $this->updatedVersions = array(); + + $currentVersion = $this->getCurrentVersion(); + $this->log('debug', "start update process"); + + if (true === $this->isLatestVersion($currentVersion)) { + $this->log('debug', "You already have the latest version. No update available"); + throw new UpToDateException('You already have the latest version. No update available'); + } + + $index = array_search($currentVersion, $this->version); + + $this->connection->beginTransaction(); + + $database = new Database($this->connection); + $version = null; + + try { + $size = \count($this->version); + + for ($i = ++$index; $i < $size; $i++) { + $version = $this->version[$i]; + $this->updateToVersion($version, $database); + $this->updatedVersions[] = $version; + } + + $currentVersion = Version::parse(); + $this->log('debug', sprintf('setting database configuration to %s', $currentVersion['version'])); + $updateConfigVersion = [ + 'thelia_version' => $currentVersion['version'], + 'thelia_major_version' => $currentVersion['major'], + 'thelia_minus_version' => $currentVersion['minus'], + 'thelia_release_version' => $currentVersion['release'], + 'thelia_extra_version' => $currentVersion['extra'], + ]; + + foreach ($updateConfigVersion as $name => $value) { + $stmt = $this->connection->prepare('SELECT * FROM `config` WHERE `name` = ?'); + $stmt->execute([$name]); + + if ($stmt->rowCount()) { + $stmt = $this->connection->prepare('UPDATE `config` SET `value` = ? WHERE `name` = ?'); + $stmt->execute([$version, $value]); + } else { + $stmt = $this->connection->prepare('INSERT INTO `config` (?) VALUES (?)'); + $stmt->execute([$version, $value]); + } + } + + $this->connection->commit(); + $this->log('debug', 'update successfully'); + } catch (\Exception $e) { + $this->connection->rollBack(); + + $this->log('error', sprintf('error during update process with message : %s', $e->getMessage())); + + $ex = new UpdateException($e->getMessage(), $e->getCode(), $e->getPrevious()); + $ex->setVersion($version); + throw $ex; + } + $this->log('debug', 'end of update processing'); + + return $this->updatedVersions; + } + + /** + * Backup current DB to file local/backup/update.sql + * @return bool if it succeeds, false otherwise + * @throws \Exception + */ + public function backupDb() + { + $database = new Database($this->connection); + + if (! $this->checkBackupIsPossible()) { + $message = 'Your database is too big for an automatic backup'; + + $this->log('error', $message); + + throw new UpdateException($message); + } + + $this->backupFile = THELIA_ROOT . $this->backupDir . 'update.sql'; + $backupDir = THELIA_ROOT . $this->backupDir; + + $fs = new Filesystem(); + + try { + $this->log('debug', sprintf('Backup database to file : %s', $this->backupFile)); + + // test if backup dir exists + if (!$fs->exists($backupDir)) { + $fs->mkdir($backupDir); + } + + if (!is_writable($backupDir)) { + throw new \RuntimeException(sprintf('impossible to write in directory : %s', $backupDir)); + } + + // test if backup file already exists + if ($fs->exists($this->backupFile)) { + // remove file + $fs->remove($this->backupFile); + } + + $database->backupDb($this->backupFile); + } catch (\Exception $ex) { + $this->log('error', sprintf('error during backup process with message : %s', $ex->getMessage())); + throw $ex; + } + } + + /** + * Restores file local/backup/update.sql to current DB + * + * @return bool if it succeeds, false otherwise + */ + public function restoreDb() + { + $database = new Database($this->connection); + + try { + $this->log('debug', sprintf('Restore database with file : %s', $this->backupFile)); + + if (!file_exists($this->backupFile)) { + return false; + } + + $database->restoreDb($this->backupFile); + } catch (\Exception $ex) { + $this->log('error', sprintf('error during restore process with message : %s', $ex->getMessage())); + print $ex->getMessage(); + return false; + } + + return true; + } + + /** + * @return null|string + */ + public function getBackupFile() + { + return $this->backupFile; + } + + public function getLogs() + { + return $this->logs; + } + + protected function log($level, $message) + { + if ($this->usePropel) { + switch ($level) { + case 'debug': + $this->logger->debug($message); + break; + case 'info': + $this->logger->info($message); + break; + case 'notice': + $this->logger->notice($message); + break; + case 'warning': + $this->logger->warning($message); + break; + case 'error': + $this->logger->error($message); + break; + case 'critical': + $this->logger->critical($message); + break; + } + } else { + $this->logs[] = [$level, $message]; + } + } + + protected function updateToVersion($version, Database $database) + { + // sql update + $filename = sprintf( + "%s%s%s", + THELIA_SETUP_DIRECTORY, + str_replace('/', DS, self::SQL_DIR), + $version . '.sql' + ); + + if (file_exists($filename)) { + $this->log('debug', sprintf('inserting file %s', $version . '.sql')); + $database->insertSql(null, [$filename]); + $this->log('debug', sprintf('end inserting file %s', $version . '.sql')); + } + + // php update + $filename = sprintf( + "%s%s%s", + THELIA_SETUP_DIRECTORY, + str_replace('/', DS, self::PHP_DIR), + $version . '.php' + ); + + if (file_exists($filename)) { + $this->log('debug', sprintf('executing file %s', $version . '.php')); + include_once($filename); + $this->log('debug', sprintf('end executing file %s', $version . '.php')); + } + + // instructions + $filename = sprintf( + "%s%s%s", + THELIA_SETUP_DIRECTORY, + str_replace('/', DS, self::INSTRUCTION_DIR), + $version . '.md' + ); + + if (file_exists($filename)) { + $this->addPostInstructions($version, file_get_contents($filename)); + } + + $this->setCurrentVersion($version); + } + + public function getCurrentVersion() + { + $stmt = $this->connection->query("SELECT `value` FROM `config` WHERE name='thelia_version'"); + + return $stmt->fetchColumn(); + } + + public function setCurrentVersion($version) + { + $currentVersion = null; + + if (null !== $this->connection) { + try { + $stmt = $this->connection->prepare('UPDATE config set value = ? where name = ?'); + $stmt->execute([$version, 'thelia_version']); + } catch (PDOException $e) { + $this->log('error', sprintf('Error setting current version : %s', $e->getMessage())); + + throw $e; + } + } + } + + /** + * Returns the database size in Mo + * @return float + * @throws \Exception + */ + public function getDataBaseSize() + { + $stmt = $this->connection->query( + "SELECT sum(data_length) / 1024 / 1024 'size' FROM information_schema.TABLES WHERE table_schema = DATABASE() GROUP BY table_schema" + ); + + if ($stmt->rowCount()) { + return \floatval($stmt->fetch(PDO::FETCH_OBJ)->size); + } + + throw new \Exception('Impossible to calculate the database size'); + } + + + /** + * Checks whether it is possible to make a data base backup + * + * @return bool + */ + public function checkBackupIsPossible() + { + $size = 0; + if (preg_match('/^(\d+)(.)$/', ini_get('memory_limit'), $matches)) { + switch (strtolower($matches[2])) { + case 'k': + $size = $matches[1] / 1024; + break; + case 'm': + $size = $matches[1]; + break; + case 'g': + $size = $matches[1] * 1024; + break; + } + } + + if ($this->getDataBaseSize() > ($size - 64) / 8) { + return false; + } + + return true; + } + + public function getLatestVersion() + { + return end($this->version); + } + + public function getVersions() + { + return $this->version; + } + + /** + * @return array + */ + public function getUpdatedVersions() + { + return $this->updatedVersions; + } + + /** + * @param array $updatedVersions + */ + public function setUpdatedVersions($updatedVersions) + { + $this->updatedVersions = $updatedVersions; + } + + /** + * Add a new post update instruction + * + * @param string $instructions content of the instruction un markdown format + */ + protected function addPostInstructions($version, $instructions) + { + if (!isset($this->postInstructions[$version])) { + $this->postInstructions[$version] = []; + } + + $this->postInstructions[$version][] = $instructions; + } + + /** + * Return the content of all instructions + * + * @param string $format the format of the export : plain (default) or html + * @return string the instructions in plain text or html + */ + public function getPostInstructions($format = 'plain') + { + $content = []; + + if (\count($this->postInstructions) == 0) { + return null; + } + + ksort($this->postInstructions); + + foreach ($this->postInstructions as $version => $instructions) { + $content[] = sprintf("## %s", $version); + foreach ($instructions as $instruction) { + $content[] = sprintf("%s", $instruction); + } + } + + $content = implode("\n\n", $content); + + if ($format === 'html') { + $content = Markdown::defaultTransform($content); + } + + return $content; + } + + public function hasPostInstructions() + { + return (\count($this->postInstructions) !== 0); + } + + public function getVersionList() + { + $list = []; + $finder = new Finder(); + $path = sprintf("%s%s", THELIA_SETUP_DIRECTORY, str_replace('/', DS, self::SQL_DIR)); + $sort = function (\SplFileInfo $a, \SplFileInfo $b) { + $a = strtolower(substr($a->getRelativePathname(), 0, -4)); + $b = strtolower(substr($b->getRelativePathname(), 0, -4)); + return version_compare($a, $b); + }; + + $files = $finder->name('*.sql')->in($path)->sort($sort); + foreach ($files as $file) { + $list[] = substr($file->getRelativePathname(), 0, -4); + } + return $list; + } + + /** + * @param string $message + * @param string $type + * @return $this + */ + public function setMessage($message, $type = 'info') + { + $this->messages[] = [$message, $type]; + + return $this; + } + + /** + * @return array + */ + public function getMessages() + { + return $this->messages; + } + + /** + * @param string $string + * @return string + */ + public function trans($string) + { + return $this->translator ? $this->translator->trans($string) : $string; + } + + /** + * @param Translator $translator + * @return $this + */ + public function setTranslator(Translator $translator) + { + $this->translator = $translator; + + return $this; + } + + public function getWebVersion() + { + $url = "http://thelia.net/version.php"; + $curl = curl_init($url); + curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); + curl_setopt($curl, CURLOPT_HEADER, false); + curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, 5); + curl_setopt($curl, CURLOPT_TIMEOUT, 5); + $res = curl_exec($curl); + + try { + if (Version::parse($res)) { + return trim($res); + } + } catch (\Exception $e) { + return null; + } + } +} diff --git a/core/lib/Thelia/Log/AbstractTlogDestination.php b/core/lib/Thelia/Log/AbstractTlogDestination.php new file mode 100644 index 00000000..0ba32a63 --- /dev/null +++ b/core/lib/Thelia/Log/AbstractTlogDestination.php @@ -0,0 +1,99 @@ +configs = $this->getConfigs(); + + // Appliquer la configuration + $this->configure(); + } + + //Affecte une valeur à une configuration de la destination + public function setConfig($name, $value, $apply_changes = true) + { + foreach ($this->configs as $config) { + if ($config->getName() == $name) { + $config->setValue($value); + + // Appliquer les changements + if ($apply_changes) { + $this->configure(); + } + return true; + } + } + + return false; + } + + //Récupère la valeur affectée à une configuration de la destination + public function getConfig($name, $default = false) + { + foreach ($this->configs as $config) { + if ($config->getName() == $name) { + return $config->getValue(); + } + } + + return $default; + } + + public function getConfigs() + { + return $this->configs; + } + + //Ajoute une ligne de logs à la destination + public function add($string) + { + $this->logs[] = $string; + } + + protected function insertAfterBody(&$res, $logdata) + { + $match = array(); + + if (preg_match("/(]*>)/i", $res, $match)) { + $res = str_replace($match[0], $match[0] . "\n" . $logdata, $res); + } + } + + // Demande à la destination de se configurer pour être prête + // a fonctionner. Si $config est != false, celà indique + // que seul le paramètre de configuration indiqué a été modifié. + protected function configure() + { + // Cette methode doit etre surchargée si nécessaire. + } + + //Lance l'écriture de tous les logs par la destination + //$res : contenu de la page html + abstract public function write(&$res); + + // Retourne le titre de cette destination, tel qu'affiché dans le menu de selection + abstract public function getTitle(); + + // Retourne une brève description de la destination + abstract public function getDescription(); +} diff --git a/core/lib/Thelia/Log/Destination/TlogDestinationFile.php b/core/lib/Thelia/Log/Destination/TlogDestinationFile.php new file mode 100644 index 00000000..07b200da --- /dev/null +++ b/core/lib/Thelia/Log/Destination/TlogDestinationFile.php @@ -0,0 +1,133 @@ +path_defaut = "log" . DS . self::TLOG_DEFAULT_NAME; + parent::__construct(); + } + + protected function getFilePath() + { + $filePath = $this->getConfig(self::VAR_PATH_FILE); + + if (preg_match('/^[a-z]:\\\|^\//i', $filePath) === 0) { + $filePath = THELIA_ROOT . $filePath; + } + + return $filePath; + } + + protected function getOpenMode() + { + return strtolower($this->getConfig(self::VAR_MODE, self::VALEUR_MODE_DEFAULT)) == 'a' ? 'a' : 'w'; + } + + public function configure() + { + $filePath = $this->getFilePath(); + $mode = $this->getOpenMode(); + + if (!empty($filePath)) { + $this->resolvePath($filePath, $mode); + } + } + + protected function resolvePath($filePath, $mode) + { + if (! empty($filePath)) { + if (! is_file($filePath)) { + $dir = dirname($filePath); + if (! is_dir($dir)) { + mkdir($dir, 0777, true); + } + + touch($filePath); + chmod($filePath, 0666); + } + + if ($this->fh) { + @fclose($this->fh); + } + + $this->fh = fopen($filePath, $mode); + return true; + } + + return false; + } + + public function getTitle() + { + return Translator::getInstance()->trans('Text File'); + } + + public function getDescription() + { + return Translator::getInstance()->trans('Store logs into text file'); + } + + public function getConfigs() + { + return array( + new TlogDestinationConfig( + self::VAR_PATH_FILE, + 'Absolute file path', + 'You should enter an abolute file path. The base directory of your Thelia installation is '.THELIA_ROOT, + $this->path_defaut, + TlogDestinationConfig::TYPE_TEXTFIELD + ), + new TlogDestinationConfig( + self::VAR_MODE, + 'File opening mode (A or E)', + 'Enter E to empty this file for each request, or A to always append logs. Consider resetting the file from time to time', + self::VALEUR_MODE_DEFAULT, + TlogDestinationConfig::TYPE_TEXTFIELD + ) + ); + } + + public function add($texte) + { + if ($this->fh) { + fwrite($this->fh, $texte."\n"); + } + } + + public function write(&$res) + { + if ($this->fh) { + @fclose($this->fh); + } + + $this->fh = false; + } +} diff --git a/core/lib/Thelia/Log/Destination/TlogDestinationHtml.php b/core/lib/Thelia/Log/Destination/TlogDestinationHtml.php new file mode 100644 index 00000000..6366bd03 --- /dev/null +++ b/core/lib/Thelia/Log/Destination/TlogDestinationHtml.php @@ -0,0 +1,66 @@ +style = $this->getConfig(self::VAR_STYLE); + } + + public function getTitle() + { + return "Direct HTML display"; + } + + public function getDescription() + { + return "Display logs in HTML format, on top of generated pages."; + } + + public function getConfigs() + { + return array( + new TlogDestinationConfig( + self::VAR_STYLE, + "CSS of each log line", + "You may also leave this field empty, and define a \"tlog-trace\" style in your CSS.", + self::VALEUR_STYLE_DEFAUT, + TlogDestinationConfig::TYPE_TEXTAREA + ) + ); + } + + public function write(&$res) + { + $block = sprintf('
    %s
    ', $this->style, htmlspecialchars(implode("\n", $this->logs))); + + $this->insertAfterBody($res, $block); + } +} diff --git a/core/lib/Thelia/Log/Destination/TlogDestinationJavascriptConsole.php b/core/lib/Thelia/Log/Destination/TlogDestinationJavascriptConsole.php new file mode 100644 index 00000000..7a570cd9 --- /dev/null +++ b/core/lib/Thelia/Log/Destination/TlogDestinationJavascriptConsole.php @@ -0,0 +1,43 @@ +try {'."\n"; + + foreach ($this->logs as $line) { + $content .= "console.log('".str_replace("'", "\\'", str_replace(array("\r\n", "\r", "\n"), '\\n', $line))."');\n"; + } + + $content .= '} catch (ex) { alert("Les logs Thelia ne peuvent être affichés dans la console javascript:" + ex); }'."\n"; + + if (preg_match("||i", $res)) { + $res = preg_replace("||i", "$content", $res); + } + } +} diff --git a/core/lib/Thelia/Log/Destination/TlogDestinationNull.php b/core/lib/Thelia/Log/Destination/TlogDestinationNull.php new file mode 100644 index 00000000..40259707 --- /dev/null +++ b/core/lib/Thelia/Log/Destination/TlogDestinationNull.php @@ -0,0 +1,38 @@ +logs as $line) { + $content .= "
    ".htmlspecialchars($line)."
    "; + } + + $tpl = $this->getConfig(self::VAR_POPUP_TPL); + + $tpl = str_replace('#LOGTEXT', $content, $tpl); + $tpl = str_replace(array("\r\n", "\r", "\n"), '\\n', $tpl); + + $wop = sprintf( + '', + $this->getConfig(self::VAR_POPUP_WIDTH), + $this->getConfig(self::VAR_POPUP_HEIGHT), + str_replace('"', '\\"', $tpl) + ); + + if (preg_match("||i", $res)) { + $res = preg_replace("||i", "$wop\n", $res); + } else { + $res .= $wop; + } + } +} diff --git a/core/lib/Thelia/Log/Destination/TlogDestinationPopup.tpl b/core/lib/Thelia/Log/Destination/TlogDestinationPopup.tpl new file mode 100644 index 00000000..0c22f005 --- /dev/null +++ b/core/lib/Thelia/Log/Destination/TlogDestinationPopup.tpl @@ -0,0 +1,52 @@ + + + + + Thelia logs + + + + + +

    Thelia Debug

    +
    #LOGTEXT
    + + diff --git a/core/lib/Thelia/Log/Destination/TlogDestinationRotatingFile.php b/core/lib/Thelia/Log/Destination/TlogDestinationRotatingFile.php new file mode 100644 index 00000000..50fe7b5d --- /dev/null +++ b/core/lib/Thelia/Log/Destination/TlogDestinationRotatingFile.php @@ -0,0 +1,119 @@ +path_defaut = "log" . DS . self::TLOG_DEFAULT_NAME; + + $this->setConfig(self::VAR_MAX_FILE_SIZE_KB, $maxFileSize, false); + + parent::__construct(); + } + + public function configure() + { + parent::configure(); + + $filePath = $this->getFilePath(); + $mode = $this->getOpenMode(); + + if ($this->fh) { + @fclose($this->fh); + } + + if (filesize($filePath) > 1024 * $this->getConfig(self::VAR_MAX_FILE_SIZE_KB, self::MAX_FILE_SIZE_KB_DEFAULT)) { + $backupFile = $filePath . '.' . strftime('%Y-%m-%d_%H-%M-%S'); + + @rename($filePath, $backupFile); + + @touch($filePath); + @chmod($filePath, 0666); + + // Keep the number of files below VAR_MAX_FILE_COUNT + $maxCount = $this->getConfig(self::VAR_MAX_FILE_COUNT, self::MAX_FILE_COUNT_DEFAULT); + + $finder = new Finder(); + + $files = $finder + ->in(dirname($filePath)) + ->files() + ->name(basename($filePath).'.*') + ->sortByModifiedTime(); + + $deleteCount = 1 + $files->count() - $maxCount; + + if ($deleteCount > 0) { + foreach ($files as $file) { + @unlink($file); + + if (--$deleteCount <= 0) { + break; + } + } + } + } + + $this->fh = fopen($filePath, $mode); + } + + public function getTitle() + { + return Translator::getInstance()->trans('Rotated Text File'); + } + + public function getDescription() + { + return Translator::getInstance()->trans('Store logs into text file, up to a certian size, then a new file is created'); + } + + public function getConfigs() + { + $arr = parent::getConfigs(); + + $arr[] = + new TlogDestinationConfig( + self::VAR_MAX_FILE_SIZE_KB, + 'Maximum log file size, in Kb', + 'When this size if exeeded, a backup copy of the file is made, and a new log file is opened. As the file size check is performed only at the beginning of a request, the file size may be bigger thant this limit. Note: 1 Mb = 1024 Kb', + self::MAX_FILE_SIZE_KB_DEFAULT, + TlogDestinationConfig::TYPE_TEXTFIELD + ); + + $arr[] = + new TlogDestinationConfig( + self::VAR_MAX_FILE_COUNT, + 'Maximum number of files to keep', + 'When this number if exeeded, the oldest files are deleted.', + self::MAX_FILE_COUNT_DEFAULT, + TlogDestinationConfig::TYPE_TEXTFIELD + ); + + return $arr; + } +} diff --git a/core/lib/Thelia/Log/Destination/TlogDestinationText.php b/core/lib/Thelia/Log/Destination/TlogDestinationText.php new file mode 100644 index 00000000..4ed30925 --- /dev/null +++ b/core/lib/Thelia/Log/Destination/TlogDestinationText.php @@ -0,0 +1,43 @@ + + * @author Manuel Raynaud + */ +class Tlog implements LoggerInterface +{ + // Nom des variables de configuration + const VAR_LEVEL = "tlog_level"; + const VAR_DESTINATIONS = "tlog_destinations"; + const VAR_PREFIXE = "tlog_prefix"; + const VAR_FILES = "tlog_files"; + const VAR_IP = "tlog_ip"; + const VAR_SHOW_REDIRECT = "tlog_show_redirect"; + + // all level of trace + const DEBUG = 100; + const INFO = 200; + const NOTICE = 300; + const WARNING = 400; + const ERROR = 500; + const CRITICAL = 600; + const ALERT = 700; + const EMERGENCY = 800; + const MUET = PHP_INT_MAX; + + protected $levels = array( + 100 => "DEBUG", + 200 => "INFO", + 300 => "NOTICE", + 400 => "WARNING", + 500 => "ERROR", + 600 => "CRITICAL", + 700 => "ALERT", + 800 => "EMERGENCY" + ); + + // default values + const DEFAULT_LEVEL = self::ERROR; + const DEFAUT_DESTINATIONS = "Thelia\Log\Destination\TlogDestinationRotatingFile"; + const DEFAUT_PREFIXE = "#INDEX: #LEVEL [#FILE:#FUNCTION()] {#LINE} #DATE #HOUR: "; + const DEFAUT_FILES = "*"; + const DEFAUT_IP = ""; + const DEFAUT_SHOW_REDIRECT = 0; + + /** + * + * @var \Thelia\Log\Tlog + */ + private static $instance = false; + + /** + * + * @var array containing class of destination handler + */ + protected $destinations = array(); + + protected $mode_back_office = false; + protected $level = self::MUET; + protected $prefix = ""; + protected $files = array(); + protected $all_files = false; + protected $show_redirect = false; + + private $linecount = 0; + + protected $done = false; + + // directories where are the Destinations Files + public $dir_destinations = array(); + + /** + * + */ + private function __construct() + { + } + + /** + * + * @return \Thelia\Log\Tlog + */ + public static function getInstance() + { + if (self::$instance == false) { + self::$instance = new Tlog(); + + // On doit placer les initialisations à ce level pour pouvoir + // utiliser la classe Tlog dans les classes de base (Cnx, BaseObj, etc.) + // Les placer dans le constructeur provoquerait une boucle + self::$instance->init(); + } + + return self::$instance; + } + + /** + * Create a new Tlog instance, that could be configured without interfering with the "main" instance + * + * @return Tlog a new Tlog instance. + */ + public static function getNewInstance() + { + $instance = new Tlog(); + + $instance->init(); + + return $instance; + } + + /** + * initialize default configuration + */ + protected function init() + { + $this->setLevel(ConfigQuery::read(self::VAR_LEVEL, self::DEFAULT_LEVEL)); + + $this->dir_destinations = array( + __DIR__.DS.'Destination', + THELIA_LOCAL_DIR.'tlog'.DS.'destinations' + ); + + $this->setPrefix(ConfigQuery::read(self::VAR_PREFIXE, self::DEFAUT_PREFIXE)); + $this->setFiles(ConfigQuery::read(self::VAR_FILES, self::DEFAUT_FILES)); + $this->setIp(ConfigQuery::read(self::VAR_IP, self::DEFAUT_IP)); + $this->setDestinations(ConfigQuery::read(self::VAR_DESTINATIONS, self::DEFAUT_DESTINATIONS)); + $this->setShowRedirect(ConfigQuery::read(self::VAR_SHOW_REDIRECT, self::DEFAUT_SHOW_REDIRECT)); + + // Au cas ou il y aurait un exit() quelque part dans le code. + register_shutdown_function(array($this, 'writeOnExit')); + } + + // Configuration + // ------------- + + /** + * + * @param string $destinations + */ + public function setDestinations($destinations) + { + if (! empty($destinations)) { + $this->destinations = array(); + + $classes_destinations = explode(';', $destinations); + + $this->loadDestinations($this->destinations, $classes_destinations); + } + + return $this; + } + + /** + * Return the directories where destinations classes should be searched. + * + * @return array of directories + */ + public function getDestinationsDirectories() + { + return $this->dir_destinations; + } + + /** + * + * change the debug level. Use Tlog constant : \Thelia\Log\Tlog::DEBUG set level to Debug + * + * @param int $level + */ + public function setLevel($level) + { + $this->level = $level; + + return $this; + } + + public function setPrefix($prefix) + { + $this->prefix = $prefix; + + return $this; + } + + public function setFiles($files) + { + $this->files = explode(";", $files); + + $this->all_files = \in_array('*', $this->files); + + return $this; + } + + public function setIp($ips) + { + // isset($_SERVER['REMOTE_ADDR']) if we are in cli mode + if (! empty($ips) && isset($_SERVER['REMOTE_ADDR']) && ! \in_array($_SERVER['REMOTE_ADDR'], explode(";", $ips))) { + $this->level = self::MUET; + } + return $this; + } + + public function setShowRedirect($bool) + { + $this->show_redirect = $bool; + + return $this; + } + + // Configuration d'une destination + public function setConfig($destination, $param, $valeur) + { + if (isset($this->destinations[$destination])) { + $this->destinations[$destination]->setConfig($param, $valeur); + } + + return $this; + } + + // Configuration d'une destination + public function getConfig($destination, $param) + { + if (isset($this->destinations[$destination])) { + return $this->destinations[$destination]->getConfig($param); + } + + return false; + } + + // Methodes d'accès aux traces + // --------------------------- + + /** + * Detailed debug information. + * + * @param string $message + * @param array $context + * @return null + */ + public function debug($message, array $context = array()) + { + $this->log(self::DEBUG, $message, $context); + } + + /** + * + * Alias of debug method. With this method you can put all parameter you want + * + * ex : Tlog::getInstance()->addDebug($arg1, $arg2, $arg3); + * + */ + public function addDebug() + { + $args = \func_get_args(); + + foreach ($args as $arg) { + $this->log(self::DEBUG, $arg); + } + } + + /** + * Interesting events. + * + * Example: User logs in, SQL logs. + * + * @param string $message + * @param array $context + * @return null + */ + public function info($message, array $context = array()) + { + $this->log(self::INFO, $message, $context); + } + + /** + * + * Alias of info method. With this method you can put all parameter you want + * + * ex : Tlog::getInstance()->addInfo($arg1, $arg2, $arg3); + * + */ + public function addInfo() + { + $args = \func_get_args(); + + foreach ($args as $arg) { + $this->log(self::INFO, $arg); + } + } + + /** + * Normal but significant events. + * + * @param string $message + * @param array $context + * @return null + */ + public function notice($message, array $context = array()) + { + $this->log(self::NOTICE, $message, $context); + } + + /** + * + * Alias of notice method. With this method you can put all parameter you want + * + * ex : Tlog::getInstance()->addNotice($arg1, $arg2, $arg3); + * + */ + public function addNotice() + { + $args = \func_get_args(); + + foreach ($args as $arg) { + $this->log(self::NOTICE, $arg); + } + } + + /** + * Exceptional occurrences that are not errors. + * + * Example: Use of deprecated APIs, poor use of an API, undesirable things + * that are not necessarily wrong. + * + * @param string $message + * @param array $context + * @return null + */ + public function warning($message, array $context = array()) + { + $this->log(self::WARNING, $message, $context); + } + + /** + * + * Alias of warning method. With this method you can put all parameter you want + * + * ex : Tlog::getInstance()->addWarning($arg1, $arg2, $arg3); + * + */ + public function addWarning() + { + $args = \func_get_args(); + + foreach ($args as $arg) { + $this->log(self::WARNING, $arg); + } + } + + /** + * Runtime errors that do not require immediate action but should typically + * be logged and monitored. + * + * @param string $message + * @param array $context + * @return null + */ + public function error($message, array $context = array()) + { + $this->log(self::ERROR, $message, $context); + } + + /** + * + * Alias of error method. With this method you can put all parameter you want + * + * ex : Tlog::getInstance()->addError($arg1, $arg2, $arg3); + * + */ + public function addError() + { + $args = \func_get_args(); + + foreach ($args as $arg) { + $this->log(self::ERROR, $arg); + } + } + + /** + * + * @see error() + */ + public function err($message, array $context = array()) + { + $this->error($message, $context); + } + + /** + * Critical conditions. + * + * Example: Application component unavailable, unexpected exception. + * + * @param string $message + * @param array $context + * @return null + */ + public function critical($message, array $context = array()) + { + $this->log(self::CRITICAL, $message, $context); + } + + /** + * + * Alias of critical method. With this method you can put all parameter you want + * + * ex : Tlog::getInstance()->addCritical($arg1, $arg2, $arg3); + * + */ + public function addCritical() + { + $args = \func_get_args(); + + foreach ($args as $arg) { + $this->log(self::CRITICAL, $arg); + } + } + + /** + * + * @see critical() + */ + public function crit($message, array $context = array()) + { + $this->critical($message, $context); + } + + /** + * Action must be taken immediately. + * + * Example: Entire website down, database unavailable, etc. This should + * trigger the SMS alerts and wake you up. + * + * @param string $message + * @param array $context + * @return null + */ + public function alert($message, array $context = array()) + { + $this->log(self::ALERT, $message, $context); + } + + /** + * + * Alias of alert method. With this method you can put all parameter you want + * + * ex : Tlog::getInstance()->addAlert($arg1, $arg2, $arg3); + * + */ + public function addAlert() + { + $args = \func_get_args(); + + foreach ($args as $arg) { + $this->log(self::ALERT, $arg); + } + } + + /** + * System is unusable. + * + * @param string $message + * @param array $context + * @return null + */ + public function emergency($message, array $context = array()) + { + $this->log(self::EMERGENCY, $message, $context); + } + + /** + * + * Alias of emergency method. With this method you can put all parameter you want + * + * ex : Tlog::getInstance()->addEmergency($arg1, $arg2, $arg3); + * + */ + public function addEmergency() + { + $args = \func_get_args(); + + foreach ($args as $arg) { + $this->log(self::EMERGENCY, $arg); + } + } + + /** + * Logs with an arbitrary level. + * + * @param mixed $level + * @param string $message + * @param array $context + * @return null + */ + public function log($level, $message, array $context = array()) + { + if ($this->level > $level || array_key_exists($level, $this->levels) === false) { + return; + } + + $this->out($this->levels[$level], $message, $context); + } + + /** + * + * final end method. Write log for each destination handler + * + * @param string $res + * @return void + */ + public function write(&$res) + { + $this->done = true; + + // Muet ? On ne fait rien + if ($this->level == self::MUET) { + return; + } + + foreach ($this->destinations as $dest) { + $dest->write($res); + } + } + + /** + * @see write() + */ + public function writeOnExit() + { + // Si les infos de debug n'ont pas été ecrites, le faire maintenant + if ($this->done === false) { + $res = ""; + + $this->write($res); + + echo $res; + } + } + + public function showRedirect($url) + { + if ($this->level != self::MUET && $this->show_redirect) { + echo " + +".Translator::getInstance()->trans('Redirecting ...')." + +".Translator::getInstance()->trans('Redirecting to %url', array('%url' => $url))." + + +"; + + return true; + } else { + return false; + } + } + + /** + * + * check if level is activated and control if current file is activated + * + * @param int $level + * @return boolean + */ + public function isActivated($level) + { + if ($this->level <= $level) { + $origin = $this->findOrigin(); + + $file = basename($origin['file']); + + if ($this->isActivedFile($file)) { + return true; + } + } + + return false; + } + + /** + * + * check if $file is in authorized files + * + * @param string $file + * @return boolean + */ + public function isActivedFile($file) + { + return ($this->all_files || \in_array($file, $this->files)) && ! \in_array("!$file", $this->files); + } + + /* -- Methodes privees ---------------------------------------- */ + + private function findOrigin() + { + $origin = array(); + + if (function_exists('debug_backtrace')) { + $trace = debug_backtrace(); + $prevHop = null; + // make a downsearch to identify the caller + $hop = array_pop($trace); + + while ($hop !== null) { + if (isset($hop['class'])) { + // we are sometimes in functions = no class available: avoid php warning here + $className = $hop['class']; + + if (! empty($className) && ($className == ltrim(__CLASS__, '\\') || strtolower(get_parent_class($className)) == ltrim(__CLASS__, '\\'))) { + $origin['line'] = $hop['line']; + $origin['file'] = $hop['file']; + break; + } + } + $prevHop = $hop; + $hop = array_pop($trace); + } + + $origin['class'] = isset($prevHop['class']) ? $prevHop['class'] : 'main'; + + if (isset($prevHop['function']) && + $prevHop['function'] !== 'include' && + $prevHop['function'] !== 'include_once' && + $prevHop['function'] !== 'require' && + $prevHop['function'] !== 'require_once') { + $origin['function'] = $prevHop['function']; + } else { + $origin['function'] = 'main'; + } + } + + return $origin; + } + + protected function interpolate($message, array $context = array()) + { + // build a replacement array with braces around the context keys + $replace = array(); + foreach ($context as $key => $val) { + $replace['{' . $key . '}'] = $val; + } + + // interpolate replacement values into the message and return + return strtr($message, $replace); + } + + private function out($level, $message, array $context = array()) + { + $text = ''; + + if ($message instanceof \Exception) { + $text = $message->getMessage()."\n".$message->getTraceAsString(); + } elseif (is_scalar($message) === false) { + $text = print_r($message, 1); + } else { + $text = $message; + } + + $text = $this->interpolate($text, $context); + + $origin = $this->findOrigin(); + + $file = basename($origin['file']); + + if ($this->isActivedFile($file)) { + $function = $origin['function']; + $line = $origin['line']; + + $prefix = str_replace( + array("#INDEX", "#LEVEL", "#FILE", "#FUNCTION", "#LINE", "#DATE", "#HOUR"), + array(1+$this->linecount, $level, $file, $function, $line, date("Y-m-d"), date("G:i:s")), + $this->prefix + ); + + $trace = $prefix . $text; + + foreach ($this->destinations as $dest) { + $dest->add($trace); + } + + $this->linecount++; + } + } + + /** + * + * @param type $destinations + * @param array $actives array containing classes instanceof AbstractTlogDestination + */ + protected function loadDestinations(&$destinations, array $actives = null) + { + foreach ($actives as $active) { + if (class_exists($active)) { + $class = new $active(); + + if (!$class instanceof AbstractTlogDestination) { + throw new \UnexpectedValueException($active." must extends Thelia\Tlog\AbstractTlogDestination"); + } + + $destinations[$active] = $class; + } + } + } +} diff --git a/core/lib/Thelia/Log/TlogDestinationConfig.php b/core/lib/Thelia/Log/TlogDestinationConfig.php new file mode 100644 index 00000000..c751171f --- /dev/null +++ b/core/lib/Thelia/Log/TlogDestinationConfig.php @@ -0,0 +1,98 @@ +name = $name; + $this->title = $title; + $this->label = $label; + $this->default = $default; + $this->type= $type; + $this->value = ConfigQuery::read($this->name, $this->default); + } + + public function getName() + { + return $this->name; + } + + public function setName($name) + { + $this->name = $name; + } + + public function getTitle() + { + return $this->title; + } + + public function setTitle($title) + { + $this->title = $title; + } + + public function getLabel() + { + return $this->label; + } + + public function setLabel($label) + { + $this->label = $label; + } + + public function getDefault() + { + return $this->default; + } + + public function setDefault($default) + { + $this->default = $default; + } + + public function getType() + { + return $this->type; + } + + public function setType($type) + { + $this->type = $type; + } + + public function getValue() + { + return $this->value; + } + + public function setValue($value) + { + $this->value = $value; + } +} diff --git a/core/lib/Thelia/Mailer/MailerFactory.php b/core/lib/Thelia/Mailer/MailerFactory.php new file mode 100644 index 00000000..a2fc2eff --- /dev/null +++ b/core/lib/Thelia/Mailer/MailerFactory.php @@ -0,0 +1,376 @@ + + * @author Franck Allimant + */ +class MailerFactory +{ + /** + * @var \Swift_Mailer + */ + protected $swiftMailer; + + /** @var EventDispatcherInterface */ + protected $dispatcher; + + /** @var ParserInterface */ + protected $parser; + + public function __construct(EventDispatcherInterface $dispatcher, ParserInterface $parser) + { + $this->dispatcher = $dispatcher; + $this->parser = $parser; + + $transporterEvent = new MailTransporterEvent(); + $this->dispatcher->dispatch(TheliaEvents::MAILTRANSPORTER_CONFIG, $transporterEvent); + + if ($transporterEvent->hasTransporter()) { + $transporter = $transporterEvent->getTransporter(); + } else { + if (ConfigQuery::isSmtpEnable()) { + $transporter = $this->configureSmtp(); + } else { + $transporter = \Swift_MailTransport::newInstance(); + } + } + + $this->swiftMailer = new \Swift_Mailer($transporter); + } + + private function configureSmtp() + { + $smtpTransporter = \Swift_SmtpTransport::newInstance(ConfigQuery::getSmtpHost(), ConfigQuery::getSmtpPort()); + + if (ConfigQuery::getSmtpEncryption()) { + $smtpTransporter->setEncryption(ConfigQuery::getSmtpEncryption()); + } + if (ConfigQuery::getSmtpUsername()) { + $smtpTransporter->setUsername(ConfigQuery::getSmtpUsername()); + } + if (ConfigQuery::getSmtpPassword()) { + $smtpTransporter->setPassword(ConfigQuery::getSmtpPassword()); + } + if (ConfigQuery::getSmtpAuthMode()) { + $smtpTransporter->setAuthMode(ConfigQuery::getSmtpAuthMode()); + } + if (ConfigQuery::getSmtpTimeout()) { + $smtpTransporter->setTimeout(ConfigQuery::getSmtpTimeout()); + } + if (ConfigQuery::getSmtpSourceIp()) { + $smtpTransporter->setSourceIp(ConfigQuery::getSmtpSourceIp()); + } + + return $smtpTransporter; + } + + /** + * @param \Swift_Mime_Message $message + * @param null $failedRecipients + * @return int number of recipients who were accepted for delivery. + */ + public function send(\Swift_Mime_Message $message, &$failedRecipients = null) + { + return $this->swiftMailer->send($message, $failedRecipients); + } + + /** + * @return \Swift_Mailer + */ + public function getSwiftMailer() + { + return $this->swiftMailer; + } + + /** + * Return a new message instance + * + * @return \Swift_Message + */ + public function getMessageInstance() + { + return \Swift_Message::newInstance(); + } + + /** + * Send a message to the customer. + * + * @param string $messageCode + * @param Customer $customer + * @param array $messageParameters an array of (name => value) parameters that will be available in the message. + */ + public function sendEmailToCustomer($messageCode, $customer, $messageParameters = []) + { + // Always add the customer ID to the parameters + $messageParameters['customer_id'] = $customer->getId(); + + $this->sendEmailMessage( + $messageCode, + [ ConfigQuery::getStoreEmail() => ConfigQuery::getStoreName() ], + [ $customer->getEmail() => $customer->getFirstname()." ".$customer->getLastname() ], + $messageParameters, + $customer->getCustomerLang()->getLocale() + ); + } + + /** + * Send a message to the shop managers. + * + * @param string $messageCode + * @param array $messageParameters an array of (name => value) parameters that will be available in the message. + * @param array $replyTo Reply to addresses. An array of (email-address => name) [optional] + */ + public function sendEmailToShopManagers($messageCode, $messageParameters = [], $replyTo = []) + { + $storeName = ConfigQuery::getStoreName(); + + // Build the list of email recipients + $recipients = ConfigQuery::getNotificationEmailsList(); + + $to = []; + + foreach ($recipients as $recipient) { + $to[$recipient] = $storeName; + } + + $this->sendEmailMessage( + $messageCode, + [ConfigQuery::getStoreEmail() => $storeName], + $to, + $messageParameters, + null, + [], + [], + $replyTo + ); + } + + /** + * Send a message to the customer. + * + * @param string $messageCode + * @param array $from From addresses. An array of (email-address => name) + * @param array $to To addresses. An array of (email-address => name) + * @param array $messageParameters an array of (name => value) parameters that will be available in the message. + * @param string $locale If null, the default store locale is used. + * @param array $cc Cc addresses. An array of (email-address => name) [optional] + * @param array $bcc Bcc addresses. An array of (email-address => name) [optional] + * @param array $replyTo Reply to addresses. An array of (email-address => name) [optional] + */ + public function sendEmailMessage($messageCode, $from, $to, $messageParameters = [], $locale = null, $cc = [], $bcc = [], $replyTo = []) + { + $store_email = ConfigQuery::getStoreEmail(); + + if (! empty($store_email)) { + if (! empty($to)) { + try { + $instance = $this->createEmailMessage($messageCode, $from, $to, $messageParameters, $locale, $cc, $bcc, $replyTo); + + $sentCount = $this->send($instance, $failedRecipients); + + if ($sentCount == 0) { + Tlog::getInstance()->addError( + Translator::getInstance()->trans( + "Failed to send message %code. Failed recipients: %failed_addresses", + [ + '%code' => $messageCode, + '%failed_addresses' => \is_array($failedRecipients) ? implode( + ',', + $failedRecipients + ) : 'none' + ] + ) + ); + } + } catch (\Exception $ex) { + Tlog::getInstance()->addError( + "Error while sending email message $messageCode: " . $ex->getMessage() + ); + } + } else { + Tlog::getInstance()->addWarning("Message $messageCode not sent: recipient list is empty."); + } + } else { + Tlog::getInstance()->addError("Can't send email message $messageCode: store email address is not defined."); + } + } + + /** + * Create a SwiftMessage instance from a given message code. + * + * @param string $messageCode + * @param array $from From addresses. An array of (email-address => name) + * @param array $to To addresses. An array of (email-address => name) + * @param array $messageParameters an array of (name => value) parameters that will be available in the message. + * @param string $locale If null, the default store locale is used. + * @param array $cc Cc addresses. An array of (email-address => name) [optional] + * @param array $bcc Bcc addresses. An array of (email-address => name) [optional] + * @param array $replyTo Reply to addresses. An array of (email-address => name) [optional] + * + * @return \Swift_Message the generated and built message. + * @throws \Exception + */ + public function createEmailMessage($messageCode, $from, $to, $messageParameters = [], $locale = null, $cc = [], $bcc = [], $replyTo = []) + { + if (null !== $message = MessageQuery::getFromName($messageCode)) { + if ($locale === null) { + $locale = Lang::getDefaultLanguage()->getLocale(); + } + + $message->setLocale($locale); + + // Assign parameters + foreach ($messageParameters as $name => $value) { + $this->parser->assign($name, $value); + } + + // As the parser uses the lang stored in the session, temporarly set the required language into the session. + // This is required in the back office when sending emails to customers, that may use a different locale than + // the current one. + $session = $this->parser->getRequest()->getSession(); + + $currentLang = $session->getLang(); + + if (null !== $requiredLang = LangQuery::create()->findOneByLocale($locale)) { + $session->setLang($requiredLang); + } + + $instance = $this->getMessageInstance(); + + $this->setupMessageHeaders($instance, $from, $to, $cc, $bcc, $replyTo); + + $message->buildMessage($this->parser, $instance); + + $session->setLang($currentLang); + + return $instance; + } + + throw new \RuntimeException( + Translator::getInstance()->trans( + "Failed to load message with code '%code%', propably because it does'nt exists.", + [ '%code%' => $messageCode ] + ) + ); + } + + /** + * Create a SwiftMessage instance from text + * + * @param array $from From addresses. An array of (email-address => name) + * @param array $to To addresses. An array of (email-address => name) + * @param string $subject the message subject + * @param string $htmlBody the HTML message body, or null + * @param string $textBody the text message body, or null + * @param array $cc Cc addresses. An array of (email-address => name) [optional] + * @param array $bcc Bcc addresses. An array of (email-address => name) [optional] + * @param array $replyTo Reply to addresses. An array of (email-address => name) [optional] + * + * @return \Swift_Message the generated and built message. + */ + public function createSimpleEmailMessage($from, $to, $subject, $htmlBody, $textBody, $cc = [], $bcc = [], $replyTo = []) + { + $instance = $this->getMessageInstance(); + + $this->setupMessageHeaders($instance, $from, $to, $cc, $bcc, $replyTo); + + $instance->setSubject($subject); + + // If we do not have an HTML message + if (empty($htmlBody)) { + // Message body is the text message + $instance->setBody($textBody, 'text/plain'); + } else { + // The main body is the HTML messahe + $instance->setBody($htmlBody, 'text/html'); + + // Use the text as a message part, if we have one. + if (! empty($textBody)) { + $instance->addPart($textBody, 'text/plain'); + } + } + + return $instance; + } + + /** + * @param array $from From addresses. An array of (email-address => name) + * @param array $to To addresses. An array of (email-address => name) + * @param string $subject the message subject + * @param string $htmlBody the HTML message body, or null + * @param string $textBody the text message body, or null + * @param array $cc Cc addresses. An array of (email-address => name) [optional] + * @param array $bcc Bcc addresses. An array of (email-address => name) [optional] + * @param array $replyTo Reply to addresses. An array of (email-address => name) [optional] + * @param null $failedRecipients The failed recipients list + * @return int number of recipients who were accepted for delivery + */ + public function sendSimpleEmailMessage($from, $to, $subject, $htmlBody, $textBody, $cc = [], $bcc = [], $replyTo = [], &$failedRecipients = null) + { + $instance = $this->createSimpleEmailMessage($from, $to, $subject, $htmlBody, $textBody, $cc, $bcc, $replyTo); + + return $this->send($instance, $failedRecipients); + } + + /** + * @param \Swift_Message $instance + * @param array $from From addresses. An array of (email-address => name) + * @param array $to To addresses. An array of (email-address => name) + * @param array $cc Cc addresses. An array of (email-address => name) [optional] + * @param array $bcc Bcc addresses. An array of (email-address => name) [optional] + * @param array $replyTo Reply to addresses. An array of (email-address => name) [optional] + */ + protected function setupMessageHeaders($instance, $from, $to, $cc = [], $bcc = [], $replyTo = []) + { + // Add from addresses + foreach ($from as $address => $name) { + $instance->addFrom($address, $name); + } + + // Add to addresses + foreach ($to as $address => $name) { + $instance->addTo($address, $name); + } + + // Add cc addresses + foreach ($cc as $address => $name) { + $instance->addCc($address, $name); + } + + // Add bcc addresses + foreach ($bcc as $address => $name) { + $instance->addBcc($address, $name); + } + + // Add reply to addresses + foreach ($replyTo as $address => $name) { + $instance->addReplyTo($address, $name); + } + } +} diff --git a/core/lib/Thelia/Model/Accessory.php b/core/lib/Thelia/Model/Accessory.php new file mode 100644 index 00000000..a480e5df --- /dev/null +++ b/core/lib/Thelia/Model/Accessory.php @@ -0,0 +1,91 @@ +filterByProductId($this->getProductId()); + } + + /** + * {@inheritDoc} + */ + public function preInsert(ConnectionInterface $con = null) + { + $this->setPosition($this->getNextPosition()); + + parent::preInsert($con); + + $this->dispatchEvent(TheliaEvents::BEFORE_CREATEACCESSORY, new AccessoryEvent($this)); + + return true; + } + + /** + * {@inheritDoc} + */ + public function postInsert(ConnectionInterface $con = null) + { + parent::postInsert($con); + + $this->dispatchEvent(TheliaEvents::AFTER_CREATEACCESSORY, new AccessoryEvent($this)); + } + + /** + * {@inheritDoc} + */ + public function preUpdate(ConnectionInterface $con = null) + { + parent::preUpdate($con); + + $this->dispatchEvent(TheliaEvents::BEFORE_UPDATEACCESSORY, new AccessoryEvent($this)); + + return true; + } + + /** + * {@inheritDoc} + */ + public function postUpdate(ConnectionInterface $con = null) + { + parent::postUpdate($con); + + $this->dispatchEvent(TheliaEvents::AFTER_UPDATEACCESSORY, new AccessoryEvent($this)); + } + + /** + * {@inheritDoc} + */ + public function preDelete(ConnectionInterface $con = null) + { + parent::preDelete($con); + + $this->dispatchEvent(TheliaEvents::BEFORE_DELETEACCESSORY, new AccessoryEvent($this)); + + return true; + } + + /** + * {@inheritDoc} + */ + public function postDelete(ConnectionInterface $con = null) + { + parent::postDelete($con); + + $this->dispatchEvent(TheliaEvents::AFTER_DELETEACCESSORY, new AccessoryEvent($this)); + } +} diff --git a/core/lib/Thelia/Model/AccessoryQuery.php b/core/lib/Thelia/Model/AccessoryQuery.php new file mode 100644 index 00000000..213f34bd --- /dev/null +++ b/core/lib/Thelia/Model/AccessoryQuery.php @@ -0,0 +1,20 @@ +filterByCustomerId($this->getCustomerId()) + ->update(array('IsDefault' => '0')); + + $this->setIsDefault(1); + $this->save(); + } + + /** + * Code to be run before inserting to database + * @param ConnectionInterface $con + * @return boolean + */ + public function preInsert(ConnectionInterface $con = null) + { + parent::preInsert($con); + + $this->dispatchEvent(TheliaEvents::BEFORE_CREATEADDRESS, new AddressEvent($this)); + + return true; + } + + /** + * Code to be run after inserting to database + * @param ConnectionInterface $con + */ + public function postInsert(ConnectionInterface $con = null) + { + parent::postInsert($con); + + $this->dispatchEvent(TheliaEvents::AFTER_CREATEADDRESS, new AddressEvent($this)); + } + + /** + * Code to be run before updating the object in database + * @param ConnectionInterface $con + * @return boolean + */ + public function preUpdate(ConnectionInterface $con = null) + { + parent::preUpdate($con); + + $this->dispatchEvent(TheliaEvents::BEFORE_UPDATEADDRESS, new AddressEvent($this)); + + return true; + } + + /** + * Code to be run after updating the object in database + * @param ConnectionInterface $con + */ + public function postUpdate(ConnectionInterface $con = null) + { + parent::postUpdate($con); + + $this->dispatchEvent(TheliaEvents::AFTER_UPDATEADDRESS, new AddressEvent($this)); + } + + /** + * Code to be run before deleting the object in database + * @param ConnectionInterface $con + * @return boolean + */ + public function preDelete(ConnectionInterface $con = null) + { + parent::preDelete($con); + + if ($this->getIsDefault()) { + return false; + } + + $this->dispatchEvent(TheliaEvents::BEFORE_DELETEADDRESS, new AddressEvent($this)); + + return true; + } + + /** + * Code to be run after deleting the object in database + * @param ConnectionInterface $con + */ + public function postDelete(ConnectionInterface $con = null) + { + parent::postDelete($con); + + $this->dispatchEvent(TheliaEvents::AFTER_DELETEADDRESS, new AddressEvent($this)); + } +} diff --git a/core/lib/Thelia/Model/AddressQuery.php b/core/lib/Thelia/Model/AddressQuery.php new file mode 100644 index 00000000..bc56477c --- /dev/null +++ b/core/lib/Thelia/Model/AddressQuery.php @@ -0,0 +1,20 @@ +setRememberMeSerial(uniqid()); + + return true; + } + + public function setPassword($password) + { + if ($this->isNew() && ($password === null || trim($password) == "")) { + throw new \InvalidArgumentException("customer password is mandatory on creation"); + } + + if ($password !== null && trim($password) != "") { + $this->setAlgo("PASSWORD_BCRYPT"); + + return parent::setPassword(password_hash($password, PASSWORD_BCRYPT)); + } + + return $this; + } + + /** + * {@inheritDoc} + */ + public function checkPassword($password) + { + return password_verify($password, $this->password); + } + + /** + * {@inheritDoc} + */ + public function getUsername() + { + return $this->getLogin(); + } + + /** + * {@inheritDoc} + */ + public function eraseCredentials() + { + parent::setPassword(null); + $this->resetModified(); + } + + /** + * {@inheritDoc} + */ + public function getRoles() + { + return array(new Role('ADMIN')); + } + + /** + * {@inheritDoc} + */ + public function getToken() + { + return $this->getRememberMeToken(); + } + + /** + * {@inheritDoc} + */ + public function setToken($token) + { + $this->setRememberMeToken($token)->save(); + } + + /** + * {@inheritDoc} + */ + public function getSerial() + { + return $this->getRememberMeSerial(); + } + + /** + * {@inheritDoc} + */ + public function setSerial($serial) + { + $this->setRememberMeSerial($serial)->save(); + } +} diff --git a/core/lib/Thelia/Model/AdminLog.php b/core/lib/Thelia/Model/AdminLog.php new file mode 100644 index 00000000..253e6c48 --- /dev/null +++ b/core/lib/Thelia/Model/AdminLog.php @@ -0,0 +1,50 @@ +setAdminLogin($adminUser !== null ? $adminUser->getUsername() : '') + ->setAdminFirstname($adminUser !== null && $adminUser instanceof Admin ? $adminUser->getFirstname() : '') + ->setAdminLastname($adminUser !== null && $adminUser instanceof Admin ? $adminUser->getLastname() : '') + ->setResource($resource) + ->setResourceId($resourceId) + ->setAction($action) + ->setMessage($message) + ->setRequest($request->toString($withRequestContent)); + + try { + $log->save(); + } catch (\Exception $ex) { + Tlog::getInstance()->err("Failed to insert new entry in AdminLog: {ex}", array('ex' => $ex)); + } + } +} diff --git a/core/lib/Thelia/Model/AdminLogQuery.php b/core/lib/Thelia/Model/AdminLogQuery.php new file mode 100644 index 00000000..02e80dd8 --- /dev/null +++ b/core/lib/Thelia/Model/AdminLogQuery.php @@ -0,0 +1,58 @@ +filterByCreatedAt($minDate, Criteria::GREATER_EQUAL); + } + + if (null !== $maxDate) { + $maxDateObject = new \DateTime($maxDate); + $maxDateObject->add(new \DateInterval('P1D')); + $search->filterByCreatedAt(date('Y-m-d', $maxDateObject->getTimestamp()), Criteria::LESS_THAN); + } + + if (null !== $resources) { + $search->filterByResource($resources); + } + + if (null !== $actions) { + $search->filterByAction($actions); + } + + if (null !== $login) { + $search->filterByAdminLogin($login); + } + + return $search->find(); + } +} +// AdminLogQuery diff --git a/core/lib/Thelia/Model/AdminQuery.php b/core/lib/Thelia/Model/AdminQuery.php new file mode 100644 index 00000000..1a4dbf9b --- /dev/null +++ b/core/lib/Thelia/Model/AdminQuery.php @@ -0,0 +1,20 @@ +getApiKey()) { + $this->setApiKey(Password::generateHexaRandom(25)); + } + + $this->generateSecureKey(); + + return true; + } + + public function postDelete(ConnectionInterface $con = null) + { + parent::postDelete($con); + + $fs = new Filesystem(); + $fs->remove($this->getKeyDir(). DS . $this->getApiKey() . '.key'); + } + + private function getKeyDir() + { + return THELIA_CONF_DIR . 'key'; + } + + private function generateSecureKey() + { + $fs = new Filesystem(); + $dir = $this->getKeyDir(); + if (!$fs->exists($dir)) { + $fs->mkdir($dir, 0700); + } + + $file = $dir . DS . $this->getApiKey().".key"; + $fs->touch($file); + file_put_contents($file, Password::generateHexaRandom(48)); + $fs->chmod($file, 0600); + } + + public function getSecureKey() + { + return file_get_contents($this->getKeyDir() . DS . $this->getApiKey() . '.key'); + } + + /** + * Returns the roles granted to the user. + * + * + * public function getRoles() + * { + * return array('USER'); + * } + * + * + * @return Role[] The user roles + */ + public function getRoles() + { + return [new Role('API')]; + } + + /** + * Return the user unique name + */ + public function getUsername() + { + throw new \RuntimeException("getUsername is not implemented"); + } + + /** + * Return the user encoded password + */ + public function getPassword() + { + throw new \RuntimeException("getPassword is not implemented"); + } + + /** + * Check a string against a the user password + */ + public function checkPassword($password) + { + throw new \RuntimeException("checkPassword is not implemented"); + } + + /** + * Removes sensitive data from the user. + * + * This is important if, at any given point, sensitive information like + * the plain-text password is stored on this object. + * + * @return void + */ + public function eraseCredentials() + { + throw new \RuntimeException("eraseCredentials is not implemented"); + } + + /** + * return the user token (used by remember me authnetication system) + */ + public function getToken() + { + throw new \RuntimeException("getToken is not implemented"); + } + + /** + * Set a token in the user data (used by remember me authnetication system) + */ + public function setToken($token) + { + throw new \RuntimeException("setToken is not implemented"); + } + + /** + * return the user serial (used by remember me authnetication system) + */ + public function getSerial() + { + throw new \RuntimeException("getSerial is not implemented"); + } + + /** + * Set a serial number int the user data (used by remember me authnetication system) + */ + public function setSerial($serial) + { + throw new \RuntimeException("setSerial is not implemented"); + } + + public function getLocale() + { + throw new \RuntimeException("getLocale is not implemented"); + } +} diff --git a/core/lib/Thelia/Model/ApiQuery.php b/core/lib/Thelia/Model/ApiQuery.php new file mode 100644 index 00000000..6cd0da61 --- /dev/null +++ b/core/lib/Thelia/Model/ApiQuery.php @@ -0,0 +1,19 @@ +dispatchEvent(TheliaEvents::BEFORE_CREATEAREA, new AreaEvent($this)); + + return true; + } + + public function postInsert(ConnectionInterface $con = null) + { + parent::postInsert($con); + + $this->dispatchEvent(TheliaEvents::AFTER_CREATEAREA, new AreaEvent($this)); + } + + public function preUpdate(ConnectionInterface $con = null) + { + parent::preUpdate($con); + + $this->dispatchEvent(TheliaEvents::BEFORE_UPDATEAREA, new AreaEvent($this)); + + return true; + } + + public function postUpdate(ConnectionInterface $con = null) + { + parent::postUpdate($con); + + $this->dispatchEvent(TheliaEvents::AFTER_UPDATEAREA, new AreaEvent($this)); + } + + public function preDelete(ConnectionInterface $con = null) + { + parent::preDelete($con); + + $this->dispatchEvent(TheliaEvents::BEFORE_DELETEAREA, new AreaEvent($this)); + + return true; + } + + public function postDelete(ConnectionInterface $con = null) + { + parent::postDelete($con); + + $this->dispatchEvent(TheliaEvents::AFTER_DELETEAREA, new AreaEvent($this)); + } +} diff --git a/core/lib/Thelia/Model/AreaDeliveryModule.php b/core/lib/Thelia/Model/AreaDeliveryModule.php new file mode 100644 index 00000000..3b08f586 --- /dev/null +++ b/core/lib/Thelia/Model/AreaDeliveryModule.php @@ -0,0 +1,9 @@ +filterByAreaId($countryInArea->getAreaId()) + ->filterByModule($module) + ->findOne() + ; + + if ($response !== null) { + break; + } + } + + return $response; + } +} +// AreaDeliveryModuleQuery diff --git a/core/lib/Thelia/Model/AreaQuery.php b/core/lib/Thelia/Model/AreaQuery.php new file mode 100644 index 00000000..b97f6144 --- /dev/null +++ b/core/lib/Thelia/Model/AreaQuery.php @@ -0,0 +1,20 @@ +dispatchEvent(TheliaEvents::BEFORE_CREATEATTRIBUTE, new AttributeEvent($this)); + + // Set the current position for the new object + $this->setPosition($this->getNextPosition()); + + parent::preInsert($con); + + return true; + } + + /** + * {@inheritDoc} + */ + public function postInsert(ConnectionInterface $con = null) + { + parent::postInsert($con); + + $this->dispatchEvent(TheliaEvents::AFTER_CREATEATTRIBUTE, new AttributeEvent($this)); + } + + /** + * {@inheritDoc} + */ + public function preUpdate(ConnectionInterface $con = null) + { + parent::preUpdate($con); + + $this->dispatchEvent(TheliaEvents::BEFORE_UPDATEATTRIBUTE, new AttributeEvent($this)); + + return true; + } + + /** + * {@inheritDoc} + */ + public function postUpdate(ConnectionInterface $con = null) + { + parent::postUpdate($con); + + $this->dispatchEvent(TheliaEvents::AFTER_UPDATEATTRIBUTE, new AttributeEvent($this)); + } + + /** + * {@inheritDoc} + */ + public function preDelete(ConnectionInterface $con = null) + { + parent::preDelete($con); + + $this->dispatchEvent(TheliaEvents::BEFORE_DELETEATTRIBUTE, new AttributeEvent($this)); + + return true; + } + + /** + * {@inheritDoc} + */ + public function postDelete(ConnectionInterface $con = null) + { + parent::postDelete($con); + + $this->dispatchEvent(TheliaEvents::AFTER_DELETEATTRIBUTE, new AttributeEvent($this)); + } +} diff --git a/core/lib/Thelia/Model/AttributeAv.php b/core/lib/Thelia/Model/AttributeAv.php new file mode 100644 index 00000000..3e1dc4c4 --- /dev/null +++ b/core/lib/Thelia/Model/AttributeAv.php @@ -0,0 +1,92 @@ +filterByAttributeId($this->getAttributeId()); + } + + /** + * {@inheritDoc} + */ + public function preInsert(ConnectionInterface $con = null) + { + parent::preInsert($con); + + // Set the current position for the new object + $this->setPosition($this->getNextPosition()); + + $this->dispatchEvent(TheliaEvents::BEFORE_CREATEATTRIBUTE_AV, new AttributeAvEvent($this)); + + return true; + } + + /** + * {@inheritDoc} + */ + public function postInsert(ConnectionInterface $con = null) + { + parent::postInsert($con); + + $this->dispatchEvent(TheliaEvents::AFTER_CREATEATTRIBUTE_AV, new AttributeAvEvent($this)); + } + + /** + * {@inheritDoc} + */ + public function preUpdate(ConnectionInterface $con = null) + { + parent::preUpdate($con); + + $this->dispatchEvent(TheliaEvents::BEFORE_UPDATEATTRIBUTE_AV, new AttributeAvEvent($this)); + + return true; + } + + /** + * {@inheritDoc} + */ + public function postUpdate(ConnectionInterface $con = null) + { + parent::postUpdate($con); + + $this->dispatchEvent(TheliaEvents::AFTER_UPDATEATTRIBUTE_AV, new AttributeAvEvent($this)); + } + + /** + * {@inheritDoc} + */ + public function preDelete(ConnectionInterface $con = null) + { + parent::preDelete($con); + + $this->dispatchEvent(TheliaEvents::BEFORE_DELETEATTRIBUTE_AV, new AttributeAvEvent($this)); + + return true; + } + + /** + * {@inheritDoc} + */ + public function postDelete(ConnectionInterface $con = null) + { + parent::postDelete($con); + + $this->dispatchEvent(TheliaEvents::AFTER_DELETEATTRIBUTE_AV, new AttributeAvEvent($this)); + } +} diff --git a/core/lib/Thelia/Model/AttributeAvI18n.php b/core/lib/Thelia/Model/AttributeAvI18n.php new file mode 100644 index 00000000..b777e315 --- /dev/null +++ b/core/lib/Thelia/Model/AttributeAvI18n.php @@ -0,0 +1,11 @@ +filterByTemplateId($this->getTemplateId()); + } + + /** + * {@inheritDoc} + */ + public function preInsert(ConnectionInterface $con = null) + { + parent::preInsert($con); + + $this->setPosition($this->getNextPosition()); + + return true; + } +} diff --git a/core/lib/Thelia/Model/AttributeTemplateQuery.php b/core/lib/Thelia/Model/AttributeTemplateQuery.php new file mode 100644 index 00000000..5f84ba13 --- /dev/null +++ b/core/lib/Thelia/Model/AttributeTemplateQuery.php @@ -0,0 +1,20 @@ +dispatchEvent(TheliaEvents::BEFORE_CREATEBRAND, new BrandEvent($this)); + + // Set the current position for the new object + $this->setPosition($this->getNextPosition()); + + return true; + } + + /** + * {@inheritDoc} + */ + public function postInsert(ConnectionInterface $con = null) + { + parent::postInsert($con); + + $this->dispatchEvent(TheliaEvents::AFTER_CREATEBRAND, new BrandEvent($this)); + } + + /** + * {@inheritDoc} + */ + public function preUpdate(ConnectionInterface $con = null) + { + parent::preUpdate($con); + + $this->dispatchEvent(TheliaEvents::BEFORE_UPDATEBRAND, new BrandEvent($this)); + + return true; + } + + /** + * {@inheritDoc} + */ + public function postUpdate(ConnectionInterface $con = null) + { + parent::postUpdate($con); + + $this->dispatchEvent(TheliaEvents::AFTER_UPDATEBRAND, new BrandEvent($this)); + } + + /** + * {@inheritDoc} + */ + public function preDelete(ConnectionInterface $con = null) + { + parent::preDelete($con); + + $this->dispatchEvent(TheliaEvents::BEFORE_DELETEBRAND, new BrandEvent($this)); + + return true; + } + + /** + * {@inheritDoc} + */ + public function postDelete(ConnectionInterface $con = null) + { + parent::postDelete($con); + + $this->markRewrittenUrlObsolete(); + + $this->dispatchEvent(TheliaEvents::AFTER_DELETEBRAND, new BrandEvent($this)); + } +} diff --git a/core/lib/Thelia/Model/BrandDocument.php b/core/lib/Thelia/Model/BrandDocument.php new file mode 100644 index 00000000..d7a22e2f --- /dev/null +++ b/core/lib/Thelia/Model/BrandDocument.php @@ -0,0 +1,130 @@ +filterByBrandId($this->getBrandId()); + } + + /** + * @inheritDoc + */ + public function preInsert(ConnectionInterface $con = null) + { + parent::preInsert($con); + + $this->setPosition($this->getNextPosition()); + + return true; + } + + public function preDelete(ConnectionInterface $con = null) + { + parent::preDelete($con); + + $this->reorderBeforeDelete( + array( + "brand_id" => $this->getBrandId(), + ) + ); + + return true; + } + + /** + * @inheritDoc + */ + public function setParentId($parentId) + { + $this->setBrandId($parentId); + + return $this; + } + + /** + * @inheritDoc + */ + public function getParentId() + { + return $this->getBrandId(); + } + + /** + * @return FileModelParentInterface the parent file model + */ + public function getParentFileModel() + { + return new Brand(); + } + + /** + * Get the ID of the form used to change this object information + * + * @return BaseForm the form + */ + public function getUpdateFormId() + { + return AdminForm::BRAND_DOCUMENT_MODIFICATION; + } + + /** + * @return string the path to the upload directory where files are stored, without final slash + */ + public function getUploadDir() + { + $uploadDir = ConfigQuery::read('documents_library_path'); + if ($uploadDir === null) { + $uploadDir = THELIA_LOCAL_DIR . 'media' . DS . 'documents'; + } else { + $uploadDir = THELIA_ROOT . $uploadDir; + } + + return $uploadDir . DS . 'brand'; + } + + /** + * @param int $objectId the ID of the object + * + * @return string the URL to redirect to after update from the back-office + */ + public function getRedirectionUrl() + { + return '/admin/brand/update/' . $this->getBrandId(); + } + + /** + * Get the Query instance for this object + * + * @return ModelCriteria + */ + public function getQueryInstance() + { + return BrandDocumentQuery::create(); + } +} diff --git a/core/lib/Thelia/Model/BrandDocumentI18n.php b/core/lib/Thelia/Model/BrandDocumentI18n.php new file mode 100644 index 00000000..162aad63 --- /dev/null +++ b/core/lib/Thelia/Model/BrandDocumentI18n.php @@ -0,0 +1,11 @@ +getBrand(); + + $brand->generateRewrittenUrl($this->getLocale()); + } +} diff --git a/core/lib/Thelia/Model/BrandI18nQuery.php b/core/lib/Thelia/Model/BrandI18nQuery.php new file mode 100644 index 00000000..ac634fe4 --- /dev/null +++ b/core/lib/Thelia/Model/BrandI18nQuery.php @@ -0,0 +1,20 @@ +filterByBrandId($this->getBrandId()); + } + + /** + * {@inheritDoc} + */ + public function preInsert(ConnectionInterface $con = null) + { + parent::preInsert($con); + + $this->setPosition($this->getNextPosition()); + + return true; + } + + public function preDelete(ConnectionInterface $con = null) + { + parent::preDelete($con); + + $this->reorderBeforeDelete( + array( + "brand_id" => $this->getBrandId(), + ) + ); + + return true; + } + + /** + * @inheritdoc + */ + public function setParentId($parentId) + { + $this->setBrandId($parentId); + + return $this; + } + + /** + * @inheritdoc + */ + public function getParentId() + { + return $this->getBrandId(); + } + + /** + * @return FileModelParentInterface the parent file model + */ + public function getParentFileModel() + { + return new Brand(); + } + + /** + * Get the ID of the form used to change this object information + * + * @return BaseForm the form + */ + public function getUpdateFormId() + { + return AdminForm::BRAND_IMAGE_MODIFICATION; + } + + /** + * @return string the path to the upload directory where files are stored, without final slash + */ + public function getUploadDir() + { + $uploadDir = ConfigQuery::read('images_library_path'); + if ($uploadDir === null) { + $uploadDir = THELIA_LOCAL_DIR . 'media' . DS . 'images'; + } else { + $uploadDir = THELIA_ROOT . $uploadDir; + } + + return $uploadDir . DS . 'brand'; + } + + /** + * @param int $objectId the ID of the object + * + * @return string the URL to redirect to after update from the back-office + */ + public function getRedirectionUrl() + { + return '/admin/brand/update/' . $this->getBrandId(); + } + + /** + * Get the Query instance for this object + * + * @return ModelCriteria + */ + public function getQueryInstance() + { + return BrandImageQuery::create(); + } +} diff --git a/core/lib/Thelia/Model/BrandImageI18n.php b/core/lib/Thelia/Model/BrandImageI18n.php new file mode 100644 index 00000000..e7426379 --- /dev/null +++ b/core/lib/Thelia/Model/BrandImageI18n.php @@ -0,0 +1,11 @@ +trans('Home') => $router->generate('admin.home.view', [], Router::ABSOLUTE_URL), + Translator::getInstance()->trans('Brand') => $router->generate('admin.brand.default', [], Router::ABSOLUTE_URL) + ]; + + if (null !== $brand = BrandQuery::create()->findPk($this->getBrandId())) { + $breadcrumb[$brand->setLocale($locale)->getTitle()] = sprintf( + "%s?current_tab=%s", + $router->generate('admin.brand.update', ['brand_id' => $brand->getId()], Router::ABSOLUTE_URL), + $tab + ); + } + + return $breadcrumb; + } +} diff --git a/core/lib/Thelia/Model/Breadcrumb/BreadcrumbInterface.php b/core/lib/Thelia/Model/Breadcrumb/BreadcrumbInterface.php new file mode 100644 index 00000000..2b114bf1 --- /dev/null +++ b/core/lib/Thelia/Model/Breadcrumb/BreadcrumbInterface.php @@ -0,0 +1,31 @@ + URL) + */ + public function getBreadcrumb(Router $router, ContainerInterface $container, $tab, $locale); +} diff --git a/core/lib/Thelia/Model/Breadcrumb/CatalogBreadcrumbTrait.php b/core/lib/Thelia/Model/Breadcrumb/CatalogBreadcrumbTrait.php new file mode 100644 index 00000000..78a20b76 --- /dev/null +++ b/core/lib/Thelia/Model/Breadcrumb/CatalogBreadcrumbTrait.php @@ -0,0 +1,86 @@ +generate('admin.catalog', [], Router::ABSOLUTE_URL); + $breadcrumb = [ + $translator->trans('Home') => $router->generate('admin.home.view', [], Router::ABSOLUTE_URL), + $translator->trans('Catalog') => $catalogUrl, + ]; + + $categoryPath = new CategoryPath($container); + $categoryPath->initializeArgs([ + 'category' => $categoryId, + 'visible' => '*' + ]); + + $results = $categoryPath->buildArray(); + + foreach ($results as $result) { + $breadcrumb[$result['TITLE']] = sprintf("%s?category_id=%d", $catalogUrl, $result['ID']); + } + + return $breadcrumb; + } + + public function getProductBreadcrumb(Router $router, ContainerInterface $container, $tab, $locale) + { + /** @var \Thelia\Model\Product $product */ + $product = $this->getProduct(); + + $breadcrumb = $this->getBaseBreadcrumb($router, $container, $product->getDefaultCategoryId(), $locale); + + $product->setLocale($locale); + + $breadcrumb[$product->getTitle()] = sprintf( + "%s?product_id=%d¤t_tab=%s", + $router->generate('admin.products.update', [], Router::ABSOLUTE_URL), + $product->getId(), + $tab + ); + + return $breadcrumb; + } + + public function getCategoryBreadcrumb(Router $router, ContainerInterface $container, $tab, $locale) + { + /** @var \Thelia\Model\Category $category */ + $category = $this->getCategory(); + $breadcrumb = $this->getBaseBreadcrumb($router, $container, $this->getParentId()); + + $category->setLocale($locale); + + $breadcrumb[$category->getTitle()] = sprintf( + "%s?category_id=%d¤t_tab=%s", + $router->generate( + 'admin.categories.update', + [], + Router::ABSOLUTE_URL + ), + $category->getId(), + $tab + ); + + return $breadcrumb; + } +} diff --git a/core/lib/Thelia/Model/Breadcrumb/FolderBreadcrumbTrait.php b/core/lib/Thelia/Model/Breadcrumb/FolderBreadcrumbTrait.php new file mode 100644 index 00000000..bc7bf707 --- /dev/null +++ b/core/lib/Thelia/Model/Breadcrumb/FolderBreadcrumbTrait.php @@ -0,0 +1,96 @@ +generate('admin.folders.default', [], Router::ABSOLUTE_URL); + $breadcrumb = [ + $translator->trans('Home') => $router->generate('admin.home.view', [], Router::ABSOLUTE_URL), + $translator->trans('Folder') => $foldersUrl, + ]; + + $folderPath = new FolderPath($container); + $folderPath->initializeArgs([ + 'folder' => $folderId, + 'visible' => '*' + ]); + + $results = $folderPath->buildArray(); + + foreach ($results as $result) { + $breadcrumb[$result['TITLE']] = sprintf( + "%s?parent=%d", + $router->generate( + 'admin.folders.default', + [], + Router::ABSOLUTE_URL + ), + $result['ID'] + ); + } + + return $breadcrumb; + } + + public function getFolderBreadcrumb(Router $router, $container, $tab, $locale) + { + /** @var \Thelia\Model\Folder $folder */ + $folder = $this->getFolder(); + $breadcrumb = $this->getBaseBreadcrumb($router, $container, $this->getParentId()); + + $folder->setLocale($locale); + + $breadcrumb[$folder->getTitle()] = sprintf( + "%s?current_tab=%s", + $router->generate( + 'admin.folders.update', + ['folder_id' => $folder->getId()], + Router::ABSOLUTE_URL + ), + $tab + ); + + return $breadcrumb; + } + + public function getContentBreadcrumb(Router $router, ContainerInterface $container, $tab, $locale) + { + /** @var \Thelia\Model\Content $content */ + $content = $this->getContent(); + + $breadcrumb = $this->getBaseBreadcrumb($router, $container, $content->getDefaultFolderId()); + + $content->setLocale($locale); + + $breadcrumb[$content->getTitle()] = sprintf( + "%s?current_tab=%s", + $router->generate( + 'admin.content.update', + ['content_id' => $content->getId()], + Router::ABSOLUTE_URL + ), + $tab + ); + + return $breadcrumb; + } +} diff --git a/core/lib/Thelia/Model/Cart.php b/core/lib/Thelia/Model/Cart.php new file mode 100644 index 00000000..40bab42d --- /dev/null +++ b/core/lib/Thelia/Model/Cart.php @@ -0,0 +1,270 @@ +getCartItems(); + + $cart = new Cart(); + $cart->setAddressDeliveryId($this->getAddressDeliveryId()); + $cart->setAddressInvoiceId($this->getAddressInvoiceId()); + $cart->setToken($token); + $discount = 0; + + if (null === $currency) { + $currencyQuery = CurrencyQuery::create(); + $currency = $currencyQuery->findPk($this->getCurrencyId()) ?: $currencyQuery->findOneByByDefault(1); + } + + $cart->setCurrency($currency); + + if ($customer) { + $cart->setCustomer($customer); + + if ($customer->getDiscount() > 0) { + $discount = $customer->getDiscount(); + } + } + + $cart->save(); + + foreach ($cartItems as $cartItem) { + $product = $cartItem->getProduct(); + $productSaleElements = $cartItem->getProductSaleElements(); + + if ($product + && + $productSaleElements + && + (int)$product->getVisible() === 1 + && + ($productSaleElements->getQuantity() >= $cartItem->getQuantity() || $product->getVirtual() === 1 || !ConfigQuery::checkAvailableStock()) + ) { + $item = new CartItem(); + $item->setCart($cart); + $item->setProductId($cartItem->getProductId()); + $item->setQuantity($cartItem->getQuantity()); + $item->setProductSaleElements($productSaleElements); + $prices = $productSaleElements->getPricesByCurrency($currency, $discount); + $item + ->setPrice($prices->getPrice()) + ->setPromoPrice($prices->getPromoPrice()) + ->setPromo($productSaleElements->getPromo()); + + $item->save(); + $dispatcher->dispatch(TheliaEvents::CART_ITEM_DUPLICATE, new CartItemDuplicationItem($item, $cartItem)); + } + } + + // Dispatche the duplication event before delting the cart from the database, + $dispatcher->dispatch(TheliaEvents::CART_DUPLICATED, new CartDuplicationEvent($cart, $this)); + + try { + $this->delete(); + } catch (\Exception $e) { + // just fail silently in some cases + } + + return $cart; + } + + /** + * Retrieve the last item added in the cart + * + * @return CartItem + */ + public function getLastCartItemAdded() + { + return CartItemQuery::create() + ->filterByCartId($this->getId()) + ->orderByCreatedAt(Criteria::DESC) + ->findOne() + ; + } + + /** + * + * Retrieve the total taxed amount. + * + * By default, the total include the discount + * + * /!\ The postage amount is not available so it's the total with or without discount an without postage + * + * @param Country $country + * @param bool $withDiscount + * @param State|null $state + * @return float + * @throws \Propel\Runtime\Exception\PropelException + */ + public function getTaxedAmount(Country $country, $withDiscount = true, State $state = null) + { + $total = 0; + + foreach ($this->getCartItems() as $cartItem) { + $total += $cartItem->getTotalRealTaxedPrice($country, $state); + } + + if ($withDiscount) { + $total -= $this->getDiscount(); + + if ($total < 0) { + $total = 0; + } + } + + return round($total, 2); + } + + /** + * @param bool $withDiscount + * @param Country|null $country + * @param State|null $state + * @return float + * @throws \Propel\Runtime\Exception\PropelException + * @see getTaxedAmount same as this method but the amount is without taxes + * + */ + public function getTotalAmount($withDiscount = true, Country $country = null, State $state = null) + { + $total = 0; + + foreach ($this->getCartItems() as $cartItem) { + $total += $cartItem->getTotalRealPrice(); + } + + if ($withDiscount) { + $total -= $this->getDiscount(false, $country, $state); + + if ($total < 0) { + $total = 0; + } + } + + return round($total, 2); + } + + /** + * Return the VAT of all items + * + * @param Country $taxCountry + * @param null $taxState + * @param bool $withDiscount + * @return float|int|string + * @throws \Propel\Runtime\Exception\PropelException + */ + public function getTotalVAT($taxCountry, $taxState = null, $withDiscount = true) + { + return $this->getTaxedAmount($taxCountry, $withDiscount, $taxState) - $this->getTotalAmount($withDiscount, $taxCountry, $taxState); + } + + /** + * @param $taxCountry + * @param null $taxState + * @return float + * @throws \Propel\Runtime\Exception\PropelException + */ + public function getDiscountVAT($taxCountry, $taxState = null) + { + return $this->getDiscount(true, $taxCountry, $taxState) - $this->getDiscount(false, $taxCountry, $taxState); + } + + /** + * Retrieve the total weight for all products in cart + * + * @return float + * @throws \Propel\Runtime\Exception\PropelException + */ + public function getWeight() + { + $weight = 0; + + foreach ($this->getCartItems() as $cartItem) { + $itemWeight = $cartItem->getProductSaleElements()->getWeight(); + $itemWeight *= $cartItem->getQuantity(); + + $weight += $itemWeight; + } + + return $weight; + } + + /** + * Tell if the cart contains only virtual products + * + * @return bool + * @throws \Propel\Runtime\Exception\PropelException + */ + public function isVirtual() + { + foreach ($this->getCartItems() as $cartItem) { + if (0 < $cartItem->getProductSaleElements()->getWeight()) { + return false; + } + + $product = $cartItem->getProductSaleElements()->getProduct(); + + if (! $product->getVirtual()) { + return false; + } + } + + // An empty cart is not virtual. + return $this->getCartItems()->count() > 0; + } + + /** + * @param string $discount + * @return BaseCart|Cart + */ + public function setDiscount($discount) + { + return parent::setDiscount(round($discount, 2)); + } + + /** + * @param bool $withTaxes + * @param \Thelia\Model\Country|null $country + * @param \Thelia\Model\State|null $state + * + * @return float|int|string + * @throws \Propel\Runtime\Exception\PropelException + */ + public function getDiscount($withTaxes = true, Country $country = null, State $state = null) + { + if ($withTaxes || null === $country) { + return parent::getDiscount(); + } + + return round(Calculator::getUntaxedCartDiscount($this, $country, $state), 2); + } +} diff --git a/core/lib/Thelia/Model/CartItem.php b/core/lib/Thelia/Model/CartItem.php new file mode 100644 index 00000000..503f627e --- /dev/null +++ b/core/lib/Thelia/Model/CartItem.php @@ -0,0 +1,268 @@ +dispatcher = $dispatcher; + } + + /** + * @param ConnectionInterface|null $con + * @return bool + */ + public function preInsert(ConnectionInterface $con = null) + { + parent::preInsert($con); + + if ($this->dispatcher) { + $cartItemEvent = new CartItemEvent($this); + $this->dispatcher->dispatch(TheliaEvents::CART_ITEM_CREATE_BEFORE, $cartItemEvent); + } + return true; + } + + /** + * @param ConnectionInterface|null $con + * @return bool + */ + public function preUpdate(ConnectionInterface $con = null) + { + parent::preUpdate($con); + + if ($this->dispatcher) { + $cartItemEvent = new CartItemEvent($this); + $this->dispatcher->dispatch(TheliaEvents::CART_ITEM_UPDATE_BEFORE, $cartItemEvent); + } + return true; + } + + /** + * @param ConnectionInterface|null $con + * @throws \Propel\Runtime\Exception\PropelException + */ + public function postInsert(ConnectionInterface $con = null) + { + parent::postInsert($con); + + if ($this->dispatcher) { + $cartEvent = new CartEvent($this->getCart()); + + $this->dispatcher->dispatch(TheliaEvents::AFTER_CARTADDITEM, $cartEvent); + } + } + + /** + * @param ConnectionInterface|null $con + * @throws \Propel\Runtime\Exception\PropelException + */ + public function postUpdate(ConnectionInterface $con = null) + { + parent::postUpdate($con); + + if ($this->dispatcher) { + $cartEvent = new CartEvent($this->getCart()); + + $this->dispatcher->dispatch(TheliaEvents::AFTER_CARTUPDATEITEM, $cartEvent); + } + } + + /** + * @param $value + * @return $this + * @throws \Propel\Runtime\Exception\PropelException + */ + public function updateQuantity($value) + { + $currentQuantity = $this->getQuantity(); + + if ($value <= 0) { + $value = $currentQuantity; + } + + if (ConfigQuery::checkAvailableStock()) { + $productSaleElements = $this->getProductSaleElements(); + $product = $productSaleElements->getProduct(); + + if ($product->getVirtual() === 0) { + if ($productSaleElements->getQuantity() < $value) { + $value = $currentQuantity; + } + } + } + + $this->setQuantity($value); + + return $this; + } + + /** + * @param $value + * @return $this + * @throws \Propel\Runtime\Exception\PropelException + */ + public function addQuantity($value) + { + $currentQuantity = $this->getQuantity(); + $newQuantity = $currentQuantity + $value; + + if (ConfigQuery::checkAvailableStock()) { + $productSaleElements = $this->getProductSaleElements(); + $product = $productSaleElements->getProduct(); + + if ($product->getVirtual() === 0) { + if ($productSaleElements->getQuantity() < $newQuantity) { + $newQuantity = $currentQuantity; + } + } + } + + $this->setQuantity($newQuantity); + + return $this; + } + + /** + * @return float + */ + public function getRealPrice() + { + return (float) ((int) $this->getPromo() === 1 ? $this->getPromoPrice() : $this->getPrice()); + } + + /** + * @param ConnectionInterface|null $con + * @param null $locale + * @return Product + * @throws \Propel\Runtime\Exception\PropelException + */ + public function getProduct(ConnectionInterface $con = null, $locale = null) + { + $product = parent::getProduct($con); + + $translation = $product->getTranslation($locale); + + if ($translation->isNew()) { + if (ConfigQuery::getDefaultLangWhenNoTranslationAvailable() == Lang::REPLACE_BY_DEFAULT_LANGUAGE) { + $locale = Lang::getDefaultLanguage()->getLocale(); + } + } + + $product->setLocale($locale); + + return $product; + } + + /** + * @param Country $country + * @param State|null $state + * @return float + * @throws \Propel\Runtime\Exception\PropelException + */ + public function getRealTaxedPrice(Country $country, State $state = null) + { + return (int) $this->getPromo() === 1 ? $this->getTaxedPromoPrice($country, $state) : $this->getTaxedPrice($country, $state); + } + + /** + * @param Country $country + * @param State|null $state + * @return float + * @throws \Propel\Runtime\Exception\PropelException + */ + public function getTaxedPrice(Country $country, State $state = null) + { + $taxCalculator = new Calculator(); + + return $taxCalculator->load($this->getProduct(), $country, $state)->getTaxedPrice($this->getPrice()); + } + + /** + * @param Country $country + * @param State|null $state + * @return float + * @throws \Propel\Runtime\Exception\PropelException + */ + public function getTaxedPromoPrice(Country $country, State $state = null) + { + $taxCalculator = new Calculator(); + + return $taxCalculator->load($this->getProduct(), $country, $state)->getTaxedPrice($this->getPromoPrice()); + } + + /** + * @since Version 2.3 + * @param Country $country + * @param State|null $state + * @return float + * @throws \Propel\Runtime\Exception\PropelException + */ + public function getTotalRealTaxedPrice(Country $country, State $state = null) + { + return (int) $this->getPromo() === 1 ? $this->getTotalTaxedPromoPrice($country, $state) : $this->getTotalTaxedPrice($country, $state); + } + + /** + * @since Version 2.3 + * @param Country $country + * @param State|null $state + * @return float + * @throws \Propel\Runtime\Exception\PropelException + */ + public function getTotalTaxedPrice(Country $country, State $state = null) + { + return round($this->getTaxedPrice($country, $state) * $this->getQuantity(), 2); + } + + /** + * @since Version 2.3 + * @throws \Propel\Runtime\Exception\PropelException + */ + public function getTotalTaxedPromoPrice(Country $country, State $state = null) + { + return round($this->getTaxedPromoPrice($country, $state) * $this->getQuantity(), 2); + } + + /** + * @since Version 2.4 + * @return float + */ + public function getTotalPrice() + { + return round($this->getPrice() * $this->getQuantity(), 2); + } + + /** + * @since Version 2.4 + * @return float + */ + public function getTotalPromoPrice() + { + return round($this->getPromoPrice() * $this->getQuantity(), 2); + } + + /** + * @since Version 2.4 + * @return float + */ + public function getTotalRealPrice() + { + return round($this->getRealPrice() * $this->getQuantity(), 2); + } +} diff --git a/core/lib/Thelia/Model/CartItemQuery.php b/core/lib/Thelia/Model/CartItemQuery.php new file mode 100644 index 00000000..7dee43cf --- /dev/null +++ b/core/lib/Thelia/Model/CartItemQuery.php @@ -0,0 +1,20 @@ +getId()); + } + + /** + * {@inheritDoc} + */ + public function getRewrittenUrlViewName() + { + return 'category'; + } + + /** + * + * count all products for current category and sub categories + * + * /!\ the number of queries is exponential, use it with caution + * + * @param bool|string $productVisibility: true (default) to count only visible products, false to count only hidden + * products, or * to count all products. + * @return int + */ + public function countAllProducts($productVisibility = true) + { + $children = CategoryQuery::findAllChild($this->getId()); + array_push($children, $this); + + $query = ProductQuery::create(); + + if ($productVisibility !== '*') { + $query->filterByVisible($productVisibility); + } + + $query + ->useProductCategoryQuery() + ->filterByCategory(new ObjectCollection($children), Criteria::IN) + ->endUse(); + + return $query->count(); + } + + /** + * + * count visible products only for current category and sub categories + * + * /!\ the number of queries is exponential, use it with caution + * + * @return int + */ + public function countAllProductsVisibleOnly() + { + return $this->countAllProducts(true); + } + + /** + * Get the root category + * @param int $categoryId + * @return mixed + */ + public function getRoot($categoryId) + { + $category = CategoryQuery::create()->findPk($categoryId); + + if (0 !== $category->getParent()) { + $parentCategory = CategoryQuery::create()->findPk($category->getParent()); + + if (null !== $parentCategory) { + $categoryId = $this->getRoot($parentCategory->getId()); + } + } + + return $categoryId; + } + + /** + * Calculate next position relative to our parent + * @param CategoryQuery $query + */ + protected function addCriteriaToPositionQuery($query) + { + $query->filterByParent($this->getParent()); + } + + public function deleteProducts(ConnectionInterface $con = null) + { + $productsCategories = ProductCategoryQuery::create() + ->filterByCategoryId($this->getId()) + ->filterByDefaultCategory(1) + ->find($con); + + if ($productsCategories) { + /** @var ProductCategory $productCategory */ + foreach ($productsCategories as $productCategory) { + if (null !== $product = $productCategory->getProduct()) { + $this->dispatchEvent(TheliaEvents::PRODUCT_DELETE, new ProductDeleteEvent($product->getId())); + } + } + } + } + + /** + * {@inheritDoc} + */ + public function preInsert(ConnectionInterface $con = null) + { + parent::preInsert($con); + + $this->setPosition($this->getNextPosition()); + + $this->dispatchEvent(TheliaEvents::BEFORE_CREATECATEGORY, new CategoryEvent($this)); + + return true; + } + + /** + * {@inheritDoc} + */ + public function postInsert(ConnectionInterface $con = null) + { + parent::postInsert($con); + + $this->dispatchEvent(TheliaEvents::AFTER_CREATECATEGORY, new CategoryEvent($this)); + } + + /** + * {@inheritDoc} + */ + public function preUpdate(ConnectionInterface $con = null) + { + parent::preUpdate($con); + + $this->dispatchEvent(TheliaEvents::BEFORE_UPDATECATEGORY, new CategoryEvent($this)); + + return true; + } + + /** + * {@inheritDoc} + */ + public function postUpdate(ConnectionInterface $con = null) + { + parent::postUpdate($con); + + $this->dispatchEvent(TheliaEvents::AFTER_UPDATECATEGORY, new CategoryEvent($this)); + } + + /** + * {@inheritDoc} + */ + public function preDelete(ConnectionInterface $con = null) + { + parent::preDelete($con); + + $this->dispatchEvent(TheliaEvents::BEFORE_DELETECATEGORY, new CategoryEvent($this)); + $this->reorderBeforeDelete( + array( + "parent" => $this->getParent(), + ) + ); + $this->deleteProducts($con); + + return true; + } + + /** + * {@inheritDoc} + */ + public function postDelete(ConnectionInterface $con = null) + { + parent::postDelete($con); + + $this->markRewrittenUrlObsolete(); + + //delete all subcategories + $subCategories = CategoryQuery::findAllChild($this->getId()); + + foreach ($subCategories as $category) { + if (!\is_null($this->dispatcher)) { + $category->setDispatcher($this->getDispatcher()); + } + + $category->delete(); + } + + $this->dispatchEvent(TheliaEvents::AFTER_DELETECATEGORY, new CategoryEvent($this)); + } + + /** + * Overload for the position management + * @param Base\ProductCategory $productCategory + * @inheritdoc + */ + protected function doAddProductCategory($productCategory) + { + parent::doAddProductCategory($productCategory); + + $productCategoryPosition = ProductCategoryQuery::create() + ->filterByCategoryId($productCategory->getCategoryId()) + ->orderByPosition(Criteria::DESC) + ->findOne(); + + $productCategory->setPosition($productCategoryPosition !== null ? $productCategoryPosition->getPosition() + 1 : 1); + } +} diff --git a/core/lib/Thelia/Model/CategoryAssociatedContent.php b/core/lib/Thelia/Model/CategoryAssociatedContent.php new file mode 100644 index 00000000..7385fb7a --- /dev/null +++ b/core/lib/Thelia/Model/CategoryAssociatedContent.php @@ -0,0 +1,79 @@ +dispatchEvent(TheliaEvents::BEFORE_CREATECATEGORY_ASSOCIATED_CONTENT, new CategoryAssociatedContentEvent($this)); + + return true; + } + + /** + * {@inheritDoc} + */ + public function postInsert(ConnectionInterface $con = null) + { + parent::postInsert($con); + + $this->dispatchEvent(TheliaEvents::AFTER_CREATECATEGORY_ASSOCIATED_CONTENT, new CategoryAssociatedContentEvent($this)); + } + + /** + * {@inheritDoc} + */ + public function preUpdate(ConnectionInterface $con = null) + { + parent::preUpdate($con); + + $this->dispatchEvent(TheliaEvents::BEFORE_UPDATECATEGORY_ASSOCIATED_CONTENT, new CategoryAssociatedContentEvent($this)); + + return true; + } + + /** + * {@inheritDoc} + */ + public function postUpdate(ConnectionInterface $con = null) + { + parent::postUpdate($con); + + $this->dispatchEvent(TheliaEvents::AFTER_UPDATECATEGORY_ASSOCIATED_CONTENT, new CategoryAssociatedContentEvent($this)); + } + + /** + * {@inheritDoc} + */ + public function preDelete(ConnectionInterface $con = null) + { + parent::preDelete($con); + + $this->dispatchEvent(TheliaEvents::BEFORE_DELETECATEGORY_ASSOCIATED_CONTENT, new CategoryAssociatedContentEvent($this)); + + return true; + } + + /** + * {@inheritDoc} + */ + public function postDelete(ConnectionInterface $con = null) + { + parent::postDelete($con); + + $this->dispatchEvent(TheliaEvents::AFTER_DELETECATEGORY_ASSOCIATED_CONTENT, new CategoryAssociatedContentEvent($this)); + } +} diff --git a/core/lib/Thelia/Model/CategoryAssociatedContentQuery.php b/core/lib/Thelia/Model/CategoryAssociatedContentQuery.php new file mode 100644 index 00000000..cf847e2d --- /dev/null +++ b/core/lib/Thelia/Model/CategoryAssociatedContentQuery.php @@ -0,0 +1,20 @@ +filterByCategory($this->getCategory()); + } + + /** + * {@inheritDoc} + */ + public function preInsert(ConnectionInterface $con = null) + { + parent::preInsert($con); + + $this->setPosition($this->getNextPosition()); + + return true; + } + + /** + * @inheritdoc + */ + public function setParentId($parentId) + { + $this->setCategoryId($parentId); + + return $this; + } + + /** + * @inheritdoc + */ + public function getParentId() + { + return $this->getCategoryId(); + } + + public function preDelete(ConnectionInterface $con = null) + { + parent::preDelete($con); + + $this->reorderBeforeDelete( + array( + "category_id" => $this->getCategoryId(), + ) + ); + + return true; + } + + /** + * @inheritdoc + */ + public function getBreadcrumb(Router $router, ContainerInterface $container, $tab, $locale) + { + return $this->getCategoryBreadcrumb($router, $container, $tab, $locale); + } + + /** + * @return FileModelParentInterface the parent file model + */ + public function getParentFileModel() + { + return new Category(); + } + + /** + * Get the ID of the form used to change this object information + * + * @return BaseForm the form + */ + public function getUpdateFormId() + { + return AdminForm::CATEGORY_DOCUMENT_MODIFICATION; + } + + /** + * @return string the path to the upload directory where files are stored, without final slash + */ + public function getUploadDir() + { + $uploadDir = ConfigQuery::read('documents_library_path'); + if ($uploadDir === null) { + $uploadDir = THELIA_LOCAL_DIR . 'media' . DS . 'documents'; + } else { + $uploadDir = THELIA_ROOT . $uploadDir; + } + + return $uploadDir . DS . 'category'; + } + + /** + * @param int $objectId the ID of the object + * + * @return string the URL to redirect to after update from the back-office + */ + public function getRedirectionUrl() + { + return '/admin/categories/update?category_id=' . $this->getCategoryId(); + } + + /** + * Get the Query instance for this object + * + * @return ModelCriteria + */ + public function getQueryInstance() + { + return CategoryDocumentQuery::create(); + } +} diff --git a/core/lib/Thelia/Model/CategoryDocumentI18n.php b/core/lib/Thelia/Model/CategoryDocumentI18n.php new file mode 100644 index 00000000..c0c84d3f --- /dev/null +++ b/core/lib/Thelia/Model/CategoryDocumentI18n.php @@ -0,0 +1,11 @@ +getCategory(); + $category->generateRewrittenUrl($this->getLocale()); + } +} diff --git a/core/lib/Thelia/Model/CategoryI18nQuery.php b/core/lib/Thelia/Model/CategoryI18nQuery.php new file mode 100644 index 00000000..9547161b --- /dev/null +++ b/core/lib/Thelia/Model/CategoryI18nQuery.php @@ -0,0 +1,20 @@ +filterByCategory($this->getCategory()); + } + + /** + * {@inheritDoc} + */ + public function preInsert(ConnectionInterface $con = null) + { + parent::preInsert($con); + + $this->setPosition($this->getNextPosition()); + + return true; + } + + /** + * @inheritdoc + */ + public function setParentId($parentId) + { + $this->setCategoryId($parentId); + + return $this; + } + + /** + * @inheritdoc + */ + public function getParentId() + { + return $this->getCategoryId(); + } + + public function preDelete(ConnectionInterface $con = null) + { + parent::preDelete($con); + + $this->reorderBeforeDelete( + array( + "category_id" => $this->getCategoryId(), + ) + ); + + return true; + } + + /** + * @inheritdoc + */ + public function getBreadcrumb(Router $router, ContainerInterface $container, $tab, $locale) + { + return $this->getCategoryBreadcrumb($router, $container, $tab, $locale); + } + + /** + * @return FileModelParentInterface the parent file model + */ + public function getParentFileModel() + { + return new Category(); + } + + /** + * Get the ID of the form used to change this object information + * + * @return BaseForm the form + */ + public function getUpdateFormId() + { + return AdminForm::CATEGORY_IMAGE_MODIFICATION; + } + + /** + * @return string the path to the upload directory where files are stored, without final slash + */ + public function getUploadDir() + { + $uploadDir = ConfigQuery::read('images_library_path'); + if ($uploadDir === null) { + $uploadDir = THELIA_LOCAL_DIR . 'media' . DS . 'images'; + } else { + $uploadDir = THELIA_ROOT . $uploadDir; + } + + return $uploadDir . DS . 'category'; + } + + /** + * @param int $objectId the ID of the object + * + * @return string the URL to redirect to after update from the back-office + */ + public function getRedirectionUrl() + { + return '/admin/categories/update?category_id=' . $this->getCategoryId(); + } + + /** + * Get the Query instance for this object + * + * @return ModelCriteria + */ + public function getQueryInstance() + { + return CategoryImageQuery::create(); + } +} diff --git a/core/lib/Thelia/Model/CategoryImageI18n.php b/core/lib/Thelia/Model/CategoryImageI18n.php new file mode 100644 index 00000000..be442493 --- /dev/null +++ b/core/lib/Thelia/Model/CategoryImageI18n.php @@ -0,0 +1,11 @@ +filterByParent($parent)->count(); + } + + /** + * + * find all category children for a given category. an array of \Thelia\Model\Category is return + * + * @param int|int[] $categoryId the category id or an array of id + * @param int $depth max depth you want to search + * @param int $currentPos don't change this param, it is used for recursion + * @return \Thelia\Model\Category[] + */ + public static function findAllChild($categoryId, $depth = 0, $currentPos = 0) + { + $result = []; + + if (\is_array($categoryId)) { + foreach ($categoryId as $categorySingleId) { + $result = array_merge($result, (array) self::findAllChild($categorySingleId, $depth, $currentPos)); + } + } else { + $currentPos++; + + if ($depth == $currentPos && $depth != 0) { + return []; + } + + $categories = self::create() + ->filterByParent($categoryId) + ->find(); + + foreach ($categories as $category) { + array_push($result, $category); + $result = array_merge($result, (array) self::findAllChild($category->getId(), $depth, $currentPos)); + } + } + + return $result; + } + + /** + * Find all IDs of child categories of a given category + * + * @param int|int[] $categoryId + * @param int $depth + * @param int $currentPos + * @return array + * @throws \Propel\Runtime\Exception\PropelException + */ + public static function findAllChildId($categoryId, $depth = 0, $currentPos = 0) + { + static $cache = []; + + $result = []; + + if (is_array($categoryId)) { + foreach ($categoryId as $categorySingleId) { + $result = array_merge($result, self::findAllChildId($categorySingleId, $depth, $currentPos)); + } + } else { + if (! isset($cache[$categoryId])) { + $currentPos++; + + if ($depth == $currentPos && $depth != 0) { + return []; + } + + $subCategories = self::create() + ->filterByParent($categoryId) + ->select(['id']) + ->find() + ->getData(); + + foreach ($subCategories as $subCategoryId) { + array_push($result, $subCategoryId); + $result = array_merge($result, self::findAllChildId($subCategoryId, $depth, $currentPos)); + } + + $cache[$categoryId] = $result; + } else { + $result = $cache[$categoryId]; + } + } + + return $result; + } + + /** + * Return all category IDs of a category tree, starting at $categoryId, up to a depth of $depth + * + * @param int|int[] $categoryId the category id or an array of category ids + * @param int $depth max tree traversal depth + * @return int[] + */ + public static function getCategoryTreeIds($categoryId, $depth = 1) + { + $result = \is_array($categoryId) ? $categoryId : [ $categoryId ]; + + if ($depth > 1) { + $categories = self::create() + ->filterByParent($categoryId, Criteria::IN) + ->withColumn('id') + ->find(); + + foreach ($categories as $category) { + $result = array_merge( + $result, + self::getCategoryTreeIds($category->getId(), $depth - 1) + ); + } + } + + return $result; + } + + /** + * Get categories from root to child + * + * @param integer $categoryId Category ID + * + * @since 2.3.0 + * + * @return array An array of \Thelia\Model\Category from root to wanted category + * or an empty array if Category ID doesn't exists + */ + public static function getPathToCategory($categoryId) + { + $path = []; + + $category = (new CategoryQuery)->findPk($categoryId); + if ($category !== null) { + $path[] = $category; + + if ($category->getParent() !== 0) { + $path = array_merge(self::getPathToCategory($category->getParent()), $path); + } + } + + return $path; + } +} +// CategoryQuery diff --git a/core/lib/Thelia/Model/CategoryVersion.php b/core/lib/Thelia/Model/CategoryVersion.php new file mode 100644 index 00000000..4a05bfdc --- /dev/null +++ b/core/lib/Thelia/Model/CategoryVersion.php @@ -0,0 +1,9 @@ +. */ +/* */ +/*************************************************************************************/ + +namespace Thelia\Model; + +use Thelia\Model\Base\Config as BaseConfig; +use Propel\Runtime\Connection\ConnectionInterface; +use Thelia\Core\Event\TheliaEvents; +use Thelia\Core\Event\Config\ConfigEvent; + +class Config extends BaseConfig +{ + use \Thelia\Model\Tools\ModelEventDispatcherTrait; + + /** + * {@inheritDoc} + */ + public function preInsert(ConnectionInterface $con = null) + { + parent::preInsert($con); + + $this->dispatchEvent(TheliaEvents::BEFORE_CREATECONFIG, new ConfigEvent($this)); + + return true; + } + + /** + * {@inheritDoc} + */ + public function postInsert(ConnectionInterface $con = null) + { + parent::postInsert($con); + + $this->dispatchEvent(TheliaEvents::AFTER_CREATECONFIG, new ConfigEvent($this)); + } + + /** + * {@inheritDoc} + */ + public function preUpdate(ConnectionInterface $con = null) + { + parent::preUpdate($con); + + $this->dispatchEvent(TheliaEvents::BEFORE_UPDATECONFIG, new ConfigEvent($this)); + + return true; + } + + /** + * {@inheritDoc} + */ + public function postUpdate(ConnectionInterface $con = null) + { + parent::postUpdate($con); + + $this->resetQueryCache(); + $this->dispatchEvent(TheliaEvents::AFTER_UPDATECONFIG, new ConfigEvent($this)); + } + + /** + * {@inheritDoc} + */ + public function preDelete(ConnectionInterface $con = null) + { + parent::preDelete($con); + + $this->dispatchEvent(TheliaEvents::BEFORE_DELETECONFIG, new ConfigEvent($this)); + + return true; + } + + /** + * {@inheritDoc} + */ + public function postDelete(ConnectionInterface $con = null) + { + parent::postDelete($con); + + $this->resetQueryCache(); + $this->dispatchEvent(TheliaEvents::AFTER_DELETECONFIG, new ConfigEvent($this)); + } + + public function resetQueryCache() + { + ConfigQuery::resetCache($this->getName()); + } +} diff --git a/core/lib/Thelia/Model/ConfigI18n.php b/core/lib/Thelia/Model/ConfigI18n.php new file mode 100644 index 00000000..8ad62029 --- /dev/null +++ b/core/lib/Thelia/Model/ConfigI18n.php @@ -0,0 +1,11 @@ +findOneByName($search); + + self::$cache[$search] = $value ? $value->getValue() : $default; + + return self::$cache[$search]; + } + + public static function write($configName, $value, $secured = null, $hidden = null) + { + $config = self::create()->findOneByName($configName); + + if (null == $config) { + $config = new Config(); + $config->setName($configName); + } + + if ($secured !== null) { + $config->setSecured($secured ? 1 : 0); + } + if ($hidden !== null) { + $config->setHidden($hidden ? 1 : 0); + } + + $config->setValue($value); + $config->save(); + + self::$cache[$configName] = $value; + } + + public static function resetCache($key = null) + { + if ($key) { + if (array_key_exists($key, self::$cache)) { + unset(self::$cache[$key]); + + return true; + } + } + self::$cache = array(); + + return true; + } + + public static function getConfiguredShopUrl() + { + return ConfigQuery::read("url_site", ''); + } + + public static function getDefaultLangWhenNoTranslationAvailable() + { + return ConfigQuery::read("default_lang_without_translation", 1); + } + + public static function isRewritingEnable() + { + return self::read("rewriting_enable") == 1; + } + + public static function getPageNotFoundView() + { + return self::read("page_not_found_view", '404.html'); + } + + public static function getObsoleteRewrittenUrlView() + { + return self::read('obsolete_rewriten_url_view', 'obsolete-rewritten-url'); + } + + public static function useTaxFreeAmounts() + { + return self::read('use_tax_free_amounts', 'default') == 1; + } + + public static function checkAvailableStock() + { + return self::read('check-available-stock', 1) != 0; + } + + public static function getUnknownFlagPath() + { + return self::read('unknown-flag-path', '/assets/img/flags/unknown.png'); + } + + public static function getStoreEmail() + { + return self::read('store_email', null); + } + + public static function getStoreName() + { + return self::read('store_name', ''); + } + + public static function getStoreDescription() + { + return self::read('store_description', ''); + } + + /** + * @since 2.3.0-alpha2 + * @return int|null the store country id + */ + public static function getStoreCountry() + { + return self::read('store_country', null); + } + + /** + * @since 2.3.0-alpha2 + * @return bool + */ + public static function getNotifyNewsletterSubscription() + { + return self::read('notify_newsletter_subscription', 0) != 0; + } + + /** + * @since 2.4 + * @return bool + */ + public static function isCustomerEmailConfirmationEnable() + { + return (bool) self::read('customer_email_confirmation', false); + } + + /** + * @return array a list of email addresses to send the shop's notifications + */ + public static function getNotificationEmailsList() + { + $contactEmail = self::getStoreEmail(); + + $list = preg_split("/[,;]/", self::read('store_notification_emails', $contactEmail)); + + $arr = []; + + foreach ($list as $item) { + $arr[] = trim($item); + } + + return $arr; + } + + /* smtp config */ + public static function isSmtpEnable() + { + return self::read('smtp.enabled') == 1; + } + + public static function getSmtpHost() + { + return self::read('smtp.host', 'localhost'); + } + + public static function getSmtpPort() + { + return self::read('smtp.port'); + } + + public static function getSmtpEncryption() + { + return self::read('smtp.encryption'); + } + + public static function getSmtpUsername() + { + return self::read('smtp.username'); + } + + public static function getSmtpPassword() + { + return self::read('smtp.password'); + } + + public static function getSmtpAuthMode() + { + return self::read('smtp.authmode'); + } + + public static function getSmtpTimeout() + { + return self::read('smtp.timeout', 30); + } + + public static function getSmtpSourceIp() + { + return self::read('smtp.sourceip'); + } + + public static function enableSmtp() + { + self::write('smtp.enabled', 1, 1, 1); + } + + public static function disableSmtp() + { + self::write('smtp.enabled', 0, 1, 1); + } + + public static function setSmtpHost($value) + { + self::write('smtp.host', $value, 1, 1); + } + + public static function setSmtpPort($value) + { + self::write('smtp.port', $value, 1, 1); + } + + public static function setSmtpEncryption($value) + { + self::write('smtp.encryption', $value, 1, 1); + } + + public static function setSmtpUsername($value) + { + self::write('smtp.username', $value, 1, 1); + } + + public static function setSmtpPassword($value) + { + self::write('smtp.password', $value, 1, 1); + } + + public static function setSmtpAuthMode($value) + { + self::write('smtp.authmode', $value, 1, 1); + } + + public static function setSmtpTimeout($value) + { + self::write('smtp.timeout', $value, 1, 1); + } + + public static function setSmtpSourceIp($value) + { + self::write('smtp.sourceip', $value, 1, 1); + } + /* end smtp config */ + + /* Thelia version */ + public static function getTheliaSimpleVersion() + { + $majorVersion = self::read('thelia_major_version'); + $minorVersion = self::read('thelia_minus_version'); + $releaseVersion = self::read('thelia_release_version'); + + return $majorVersion.'.'.$minorVersion.'.'.$releaseVersion; + } + + public static function isShowingErrorMessage() + { + return (bool) static::read("error_message.show", false); + } + + /** + * @param bool $v + */ + public static function setShowingErrorMessage($v) + { + static::write("error_message.show", (int) (@(bool) $v)); + } + + public static function getErrorMessagePageName() + { + return static::read("error_message.page_name"); + } + + public static function setErrorMessagePageName($v) + { + static::write("error_message.page_name", $v); + } + + public static function getAdminCacheHomeStatsTTL() + { + return \intval(static::read("admin_cache_home_stats_ttl", 600)); + } + + /** + * check if Thelia multi domain is activated. (Means one domain for each language) + * + * @return bool + */ + public static function isMultiDomainActivated() + { + return (bool) self::read("one_domain_foreach_lang", false); + } + + public static function getMinimuAdminPasswordLength() + { + return self::read("minimum_admin_password_length", 4); + } +} +// ConfigQuery diff --git a/core/lib/Thelia/Model/Content.php b/core/lib/Thelia/Model/Content.php new file mode 100644 index 00000000..83e2670f --- /dev/null +++ b/core/lib/Thelia/Model/Content.php @@ -0,0 +1,244 @@ +filterByFolderId($this->getDefaultFolderId()) + ->filterByDefaultFolder(true) + ->select('content_id') + ->find(); + + // Filtrer la requete sur ces produits + if ($contents != null) { + $query->filterById($contents, Criteria::IN); + } + } + + /** + * @return int + */ + public function getDefaultFolderId() + { + // Find default folder + $default_folder = ContentFolderQuery::create() + ->filterByContentId($this->getId()) + ->filterByDefaultFolder(true) + ->findOne(); + + return $default_folder == null ? 0 : $default_folder->getFolderId(); + } + + /** + * @param int $defaultFolderId + * @return $this + */ + public function setDefaultFolder($defaultFolderId) + { + // Allow uncategorized content (NULL instead of 0, to bypass delete cascade constraint) + if ($defaultFolderId <= 0) { + $defaultFolderId = null; + } + + $contentFolder = ContentFolderQuery::create() + ->filterByContentId($this->getId()) + ->filterByDefaultFolder(true) + ->findOne(); + + if ($contentFolder !== null && (int) $contentFolder->getFolderId() === (int) $defaultFolderId) { + return $this; + } + + if ($contentFolder !== null) { + $contentFolder->delete(); + } + + // checks if the content is already associated with the folder and but not default + if (null !== $contentFolder = ContentFolderQuery::create()->filterByContent($this)->filterByFolderId($defaultFolderId)->findOne()) { + $contentFolder->setDefaultFolder(true)->save(); + } else { + $position = (new ContentFolder())->setFolderId($defaultFolderId)->getNextPosition(); + + (new ContentFolder()) + ->setContent($this) + ->setFolderId($defaultFolderId) + ->setDefaultFolder(true) + ->setPosition($position) + ->save(); + + // For BC, will be removed in 2.4 + $this->setPosition($position); + } + + return $this; + } + + /** + * @deprecated since 2.3, and will be removed in 2.4, please use Content::setDefaultFolder + * @param int $defaultFolderId + * @return $this + */ + public function updateDefaultFolder($defaultFolderId) + { + return $this->setDefaultFolder($defaultFolderId); + } + + /** + * Create a new content. + * + * Here pre and post insert event are fired + * + * @param $defaultFolderId + * + * @throws \Exception + * + * @return $this Return $this, allow chaining + */ + public function create($defaultFolderId) + { + $con = Propel::getWriteConnection(ContentTableMap::DATABASE_NAME); + + $con->beginTransaction(); + + $this->dispatchEvent(TheliaEvents::BEFORE_CREATECONTENT, new ContentEvent($this)); + + try { + $this->save($con); + + $this->setDefaultFolder($defaultFolderId)->save($con); + + $con->commit(); + + $this->dispatchEvent(TheliaEvents::AFTER_CREATECONTENT, new ContentEvent($this)); + } catch (\Exception $ex) { + $con->rollback(); + + throw $ex; + } + + return $this; + } + + public function preUpdate(ConnectionInterface $con = null) + { + parent::preUpdate($con); + + $this->dispatchEvent(TheliaEvents::BEFORE_UPDATECONTENT, new ContentEvent($this)); + + return true; + } + + public function postUpdate(ConnectionInterface $con = null) + { + parent::postUpdate($con); + + $this->dispatchEvent(TheliaEvents::AFTER_UPDATECONTENT, new ContentEvent($this)); + } + + public function preDelete(ConnectionInterface $con = null) + { + parent::preDelete($con); + + $this->dispatchEvent(TheliaEvents::BEFORE_DELETECONTENT, new ContentEvent($this)); + + return true; + } + + public function postDelete(ConnectionInterface $con = null) + { + parent::postDelete($con); + + $this->markRewrittenUrlObsolete(); + + $this->dispatchEvent(TheliaEvents::AFTER_DELETECONTENT, new ContentEvent($this)); + } + + /** + * @inheritdoc + * @deprecated since 2.3, and will be removed in 2.4, please use ContentFolder::setPosition + */ + public function setPosition($v) + { + return parent::setPosition($v); + } + + /** + * @inheritdoc + * @deprecated since 2.3, and will be removed in 2.4, please use ContentFolder::getPosition + */ + public function getPosition() + { + return parent::getPosition(); + } + + public function postSave(ConnectionInterface $con = null) + { + // For BC, will be removed in 2.4 + if (!$this->isNew()) { + if (isset($this->modifiedColumns[ContentTableMap::COL_POSITION]) && $this->modifiedColumns[ContentTableMap::COL_POSITION]) { + if (null !== $productCategory = ContentFolderQuery::create() + ->filterByContent($this) + ->filterByDefaultFolder(true) + ->findOne() + ) { + $productCategory->changeAbsolutePosition($this->getPosition()); + } + } + } + + parent::postSave(); + } + + /** + * Overload for the position management + * @param ContentFolder $contentFolder + * @inheritdoc + */ + protected function doAddContentFolder($contentFolder) + { + parent::doAddContentFolder($contentFolder); + + $contentFolderPosition = ContentFolderQuery::create() + ->filterByFolderId($contentFolder->getFolderId()) + ->orderByPosition(Criteria::DESC) + ->findOne(); + + $contentFolder->setPosition($contentFolderPosition !== null ? $contentFolderPosition->getPosition() + 1 : 1); + } +} diff --git a/core/lib/Thelia/Model/ContentDocument.php b/core/lib/Thelia/Model/ContentDocument.php new file mode 100644 index 00000000..1c9e6520 --- /dev/null +++ b/core/lib/Thelia/Model/ContentDocument.php @@ -0,0 +1,140 @@ +filterByContent($this->getContent()); + } + + /** + * {@inheritDoc} + */ + public function preInsert(ConnectionInterface $con = null) + { + parent::preInsert($con); + + $this->setPosition($this->getNextPosition()); + + return true; + } + + /** + * @inheritdoc + */ + public function setParentId($parentId) + { + $this->setContentId($parentId); + + return $this; + } + + /** + * @inheritdoc + */ + public function getParentId() + { + return $this->getContentId(); + } + + public function preDelete(ConnectionInterface $con = null) + { + parent::preDelete($con); + + $this->reorderBeforeDelete( + array( + "content_id" => $this->getContentId(), + ) + ); + + return true; + } + + /** + * @inheritdoc + */ + public function getBreadcrumb(Router $router, ContainerInterface $container, $tab, $locale) + { + return $this->getContentBreadcrumb($router, $container, $tab, $locale); + } + + /** + * @return FileModelParentInterface the parent file model + */ + public function getParentFileModel() + { + return new Content(); + } + + /** + * Get the ID of the form used to change this object information + * + * @return BaseForm the form + */ + public function getUpdateFormId() + { + return AdminForm::CONTENT_DOCUMENT_MODIFICATION; + } + + /** + * @return string the path to the upload directory where files are stored, without final slash + */ + public function getUploadDir() + { + $uploadDir = ConfigQuery::read('documents_library_path'); + if ($uploadDir === null) { + $uploadDir = THELIA_LOCAL_DIR . 'media' . DS . 'documents'; + } else { + $uploadDir = THELIA_ROOT . $uploadDir; + } + + return $uploadDir . DS . 'content'; + } + + /** + * @param int $objectId the ID of the object + * + * @return string the URL to redirect to after update from the back-office + */ + public function getRedirectionUrl() + { + return '/admin/content/update/' . $this->getContentId(); + } + + /** + * Get the Query instance for this object + * + * @return ModelCriteria + */ + public function getQueryInstance() + { + return ContentDocumentQuery::create(); + } +} diff --git a/core/lib/Thelia/Model/ContentDocumentI18n.php b/core/lib/Thelia/Model/ContentDocumentI18n.php new file mode 100644 index 00000000..b9e888df --- /dev/null +++ b/core/lib/Thelia/Model/ContentDocumentI18n.php @@ -0,0 +1,11 @@ +filterByFolderId($this->getFolderId()); + } +} diff --git a/core/lib/Thelia/Model/ContentFolderQuery.php b/core/lib/Thelia/Model/ContentFolderQuery.php new file mode 100644 index 00000000..1beaadba --- /dev/null +++ b/core/lib/Thelia/Model/ContentFolderQuery.php @@ -0,0 +1,20 @@ +getContent(); + $content->generateRewrittenUrl($this->getLocale()); + } +} diff --git a/core/lib/Thelia/Model/ContentI18nQuery.php b/core/lib/Thelia/Model/ContentI18nQuery.php new file mode 100644 index 00000000..f7d21f5e --- /dev/null +++ b/core/lib/Thelia/Model/ContentI18nQuery.php @@ -0,0 +1,20 @@ +filterByContent($this->getContent()); + } + + /** + * {@inheritDoc} + */ + public function preInsert(ConnectionInterface $con = null) + { + parent::preInsert($con); + + $this->setPosition($this->getNextPosition()); + + return true; + } + + /** + * @inheritdoc + */ + public function setParentId($parentId) + { + $this->setContentId($parentId); + + return $this; + } + + /** + * @inheritdoc + */ + public function getParentId() + { + return $this->getContentId(); + } + + public function preDelete(ConnectionInterface $con = null) + { + parent::preDelete($con); + + $this->reorderBeforeDelete( + array( + "content_id" => $this->getContentId(), + ) + ); + + return true; + } + + /** + * @inheritdoc + */ + public function getBreadcrumb(Router $router, ContainerInterface $container, $tab, $locale) + { + return $this->getContentBreadcrumb($router, $container, $tab, $locale); + } + + /** + * @return FileModelParentInterface the parent file model + */ + public function getParentFileModel() + { + return new Content(); + } + + /** + * Get the ID of the form used to change this object information + * + * @return BaseForm the form + */ + public function getUpdateFormId() + { + return AdminForm::CONTENT_IMAGE_MODIFICATION; + } + + /** + * @return string the path to the upload directory where files are stored, without final slash + */ + public function getUploadDir() + { + $uploadDir = ConfigQuery::read('images_library_path'); + if ($uploadDir === null) { + $uploadDir = THELIA_LOCAL_DIR . 'media' . DS . 'images'; + } else { + $uploadDir = THELIA_ROOT . $uploadDir; + } + + return $uploadDir . DS . 'content'; + } + + /** + * @param int $objectId the ID of the object + * + * @return string the URL to redirect to after update from the back-office + */ + public function getRedirectionUrl() + { + return '/admin/content/update/' . $this->getContentId(); + } + + /** + * Get the Query instance for this object + * + * @return ModelCriteria + */ + public function getQueryInstance() + { + return ContentImageQuery::create(); + } +} diff --git a/core/lib/Thelia/Model/ContentImageI18n.php b/core/lib/Thelia/Model/ContentImageI18n.php new file mode 100644 index 00000000..18aadde6 --- /dev/null +++ b/core/lib/Thelia/Model/ContentImageI18n.php @@ -0,0 +1,11 @@ +getZipCodeFormat(); + + if (empty($zipCodeFormat)) { + return null; + } + + + $zipCodeRE = preg_replace("/\\s+/", ' ', $zipCodeFormat); + + $trans = [ + "N" => "\\d", + "L" => "[a-zA-Z]", + "C" => ".+", + " " => " +" + ]; + + $zipCodeRE = "#^" . strtr($zipCodeRE, $trans) . "$#"; + + return $zipCodeRE; + } + + /** + * This method ensure backward compatibility to Thelia 2.1, where a country belongs to one and + * only one shipping zone. + * + * @deprecated a country may belong to several Areas (shipping zones). Use CountryArea queries instead + */ + public function getAreaId() + { + $firstAreaCountry = CountryAreaQuery::create()->findOneByCountryId($this->getId()); + + if (null !== $firstAreaCountry) { + return $firstAreaCountry->getAreaId(); + } + + return null; + } + + /** + * + * Put the current country as the default one. + * + * @throws \RuntimeException + * @throws \Exception + * @throws \Propel\Runtime\Exception\PropelException + */ + public function toggleDefault() + { + if ($this->getId() === null) { + throw new \RuntimeException("impossible to just uncheck default country, choose a new one"); + } + + $con = Propel::getWriteConnection(CountryTableMap::DATABASE_NAME); + $con->beginTransaction(); + + try { + CountryQuery::create() + ->filterByByDefault(1) + ->update(array('ByDefault' => 0), $con); + + $this + ->setByDefault(1) + ->save($con); + + $con->commit(); + } catch (PropelException $e) { + $con->rollBack(); + throw $e; + } + } + + public function preInsert(ConnectionInterface $con = null) + { + parent::preInsert($con); + + $this->dispatchEvent(TheliaEvents::BEFORE_CREATECOUNTRY, new CountryEvent($this)); + + return true; + } + + public function postInsert(ConnectionInterface $con = null) + { + parent::postInsert($con); + + $this->dispatchEvent(TheliaEvents::AFTER_CREATECOUNTRY, new CountryEvent($this)); + } + + public function preUpdate(ConnectionInterface $con = null) + { + parent::preUpdate($con); + + $this->dispatchEvent(TheliaEvents::BEFORE_UPDATECOUNTRY, new CountryEvent($this)); + + return true; + } + + public function postUpdate(ConnectionInterface $con = null) + { + parent::postUpdate($con); + + $this->dispatchEvent(TheliaEvents::AFTER_UPDATECOUNTRY, new CountryEvent($this)); + } + + public function preDelete(ConnectionInterface $con = null) + { + parent::preDelete($con); + + if ($this->getByDefault()) { + return false; + } + + $this->dispatchEvent(TheliaEvents::BEFORE_DELETECOUNTRY, new CountryEvent($this)); + + return true; + } + + public function postDelete(ConnectionInterface $con = null) + { + parent::postDelete($con); + + $this->dispatchEvent(TheliaEvents::AFTER_DELETECOUNTRY, new CountryEvent($this)); + } + + /** + * Return the default country + * + * @throws \LogicException if no default country is defined + */ + public static function getDefaultCountry() + { + if (null === self::$defaultCountry) { + self::$defaultCountry = CountryQuery::create()->findOneByByDefault(true); + + if (null === self::$defaultCountry) { + throw new \LogicException(Translator::getInstance()->trans("Cannot find a default country. Please define one.")); + } + } + + return self::$defaultCountry; + } + + /** + * Return the shop country + * + * @throws LogicException if no shop country is defined + */ + public static function getShopLocation() + { + $countryId = ConfigQuery::getStoreCountry(); + + // return the default country if no shop country defined + if (empty($countryId)) { + return self::getDefaultCountry(); + } + + $shopCountry = CountryQuery::create()->findPk($countryId); + if ($shopCountry === null) { + throw new \LogicException(Translator::getInstance()->trans("Cannot find the shop country. Please select a shop country.")); + } + + return $shopCountry; + } +} diff --git a/core/lib/Thelia/Model/CountryArea.php b/core/lib/Thelia/Model/CountryArea.php new file mode 100644 index 00000000..4a5404ce --- /dev/null +++ b/core/lib/Thelia/Model/CountryArea.php @@ -0,0 +1,9 @@ +filterByCountryId($country->getId()) + ->filterByStateId($state->getId()) + ->find(); + + if (count($countryAreaList) > 0) { + return $countryAreaList; + } + } + + $countryAreaList = self::create() + ->filterByCountryId($country->getId()) + ->filterByStateId(null) + ->find() + ; + + return $countryAreaList; + } +} diff --git a/core/lib/Thelia/Model/CountryI18n.php b/core/lib/Thelia/Model/CountryI18n.php new file mode 100644 index 00000000..c861914d --- /dev/null +++ b/core/lib/Thelia/Model/CountryI18n.php @@ -0,0 +1,11 @@ +. */ +/* */ +/**********************************************************************************/ + +namespace Thelia\Model; + +use Propel\Runtime\Propel; +use Thelia\Model\Base\Coupon as BaseCoupon; +use Thelia\Model\Exception\InvalidArgumentException; +use Thelia\Model\Map\CouponTableMap; +use Thelia\Model\Tools\ModelEventDispatcherTrait; + +/** + * Used to provide an effect (mostly a discount) + * at the end of the Customer checkout tunnel + * It will be usable for a Customer only if it matches the Coupon criteria (Rules) + * + * @package Coupon + * @author Guillaume MOREL + * + */ +class Coupon extends BaseCoupon +{ + // Define the value of an unlimited coupon usage. + const UNLIMITED_COUPON_USE = -1; + + use ModelEventDispatcherTrait; + + /** + * Create or Update this Coupon + * + * @param string $code Coupon Code + * @param string $title Coupon title + * @param array $effects Ready to be serialized in JSON effect params + * @param string $type Coupon type + * @param bool $isRemovingPostage Is removing Postage + * @param string $shortDescription Coupon short description + * @param string $description Coupon description + * @param boolean $isEnabled Enable/Disable + * @param \DateTime $expirationDate Coupon expiration date + * @param boolean $isAvailableOnSpecialOffers Is available on special offers + * @param boolean $isCumulative Is cumulative + * @param int $maxUsage Coupon quantity + * @param string $defaultSerializedRule Serialized default rule added if none found + * @param string $locale Coupon Language code ISO (ex: fr_FR) + * @param array $freeShippingForCountries ID of Countries to which shipping is free + * @param array $freeShippingForMethods ID of Shipping modules for which shipping is free + * @param bool $perCustomerUsageCount True if usage coiunt is per customer + * @param $startDate + * + * @throws \Exception + */ + public function createOrUpdate( + $code, + $title, + array $effects, + $type, + $isRemovingPostage, + $shortDescription, + $description, + $isEnabled, + $expirationDate, + $isAvailableOnSpecialOffers, + $isCumulative, + $maxUsage, + $defaultSerializedRule, + $locale, + $freeShippingForCountries, + $freeShippingForMethods, + $perCustomerUsageCount, + $startDate = null + ) { + $con = Propel::getWriteConnection(CouponTableMap::DATABASE_NAME); + + $con->beginTransaction(); + + try { + $this + ->setCode($code) + ->setType($type) + ->setEffects($effects) + ->setIsRemovingPostage($isRemovingPostage) + ->setIsEnabled($isEnabled) + ->setStartDate($startDate) + ->setExpirationDate($expirationDate) + ->setIsAvailableOnSpecialOffers($isAvailableOnSpecialOffers) + ->setIsCumulative($isCumulative) + ->setMaxUsage($maxUsage) + ->setPerCustomerUsageCount($perCustomerUsageCount) + ->setLocale($locale) + ->setTitle($title) + ->setShortDescription($shortDescription) + ->setDescription($description) + ; + + // If no rule given, set default rule + if (null === $this->getSerializedConditions()) { + $this->setSerializedConditions($defaultSerializedRule); + } + + $this->save(); + + // Update countries and modules relation for free shipping + CouponCountryQuery::create()->filterByCouponId($this->id)->delete(); + CouponModuleQuery::create()->filterByCouponId($this->id)->delete(); + + foreach ($freeShippingForCountries as $countryId) { + if ($countryId <= 0) { + continue; + } + + $couponCountry = new CouponCountry(); + + $couponCountry + ->setCouponId($this->getId()) + ->setCountryId($countryId) + ->save(); + ; + } + + foreach ($freeShippingForMethods as $moduleId) { + if ($moduleId <= 0) { + continue; + } + + $couponModule = new CouponModule(); + + $couponModule + ->setCouponId($this->getId()) + ->setModuleId($moduleId) + ->save() + ; + } + + $con->commit(); + } catch (\Exception $ex) { + $con->rollback(); + + throw $ex; + } + } + + /** + * Create or Update this coupon condition + * + * @param string $serializableConditions Serialized conditions ready to be saved + * @param string $locale Coupon Language code ISO (ex: fr_FR) + * + * @throws \Exception + */ + public function createOrUpdateConditions($serializableConditions, $locale) + { + $this->setSerializedConditions($serializableConditions); + + // Set object language (i18n) + if (!\is_null($locale)) { + $this->setLocale($locale); + } + + $this->save(); + } + + /** + * Set Coupon amount + * + * @param float $amount Amount deduced from the Cart + * + * @return $this + */ + public function setAmount($amount) + { + $effects = $this->unserializeEffects($this->getSerializedEffects()); + $effects['amount'] = \floatval($amount); + $this->setEffects($effects); + + return $this; + } + + /** + * Get the amount removed from the coupon to the cart + * + * @return float + */ + public function getAmount() + { + // Amount is now optional + $amount = isset($this->getEffects()['amount']) ? $this->getEffects()['amount'] : 0; + + return \floatval($amount); + } + + /** + * Get the Coupon effects + * + * @return array + * @throws Exception\InvalidArgumentException + */ + public function getEffects() + { + $effects = $this->unserializeEffects($this->getSerializedEffects()); + + return $effects; + } + + /** + * Get the Coupon effects + * + * @param array $effects Effect ready to be serialized + * + * @throws Exception\InvalidArgumentException + * @return $this + */ + public function setEffects(array $effects) + { + $this->setSerializedEffects($this->serializeEffects($effects)); + + return $this; + } + + /** + * Return unserialized effects + * + * @param string $serializedEffects Serialized effect string to unserialize + * + * @return array + */ + public function unserializeEffects($serializedEffects) + { + $effects = json_decode($serializedEffects, true); + + return $effects; + } + + /** + * Return serialized effects + * + * @param array $unserializedEffects Unserialized array string to serialize + * + * @return string + */ + public function serializeEffects(array $unserializedEffects) + { + $effects = json_encode($unserializedEffects); + + return $effects; + } + + /** + * Return the countries for which free shipping is valid + * @return array|mixed|\Propel\Runtime\Collection\ObjectCollection + */ + public function getFreeShippingForCountries() + { + return CouponCountryQuery::create()->filterByCouponId($this->getId())->find(); + } + + /** + * Return the modules for which free shipping is valid + * + * @return array|mixed|\Propel\Runtime\Collection\ObjectCollection + */ + public function getFreeShippingForModules() + { + return CouponModuleQuery::create()->filterByCouponId($this->getId())->find(); + } + + public function isUsageUnlimited() + { + return $this->getMaxUsage() == self::UNLIMITED_COUPON_USE; + } + /** + * Get coupon usage left, either overall, or per customer. + * + * @param int|null $customerId the ID of the ordering customer + * + * @return int the usage left. + */ + public function getUsagesLeft($customerId = null) + { + $usageLeft = $this->getMaxUsage(); + + if ($this->getPerCustomerUsageCount()) { + // Get usage left for current customer. If the record is not found, + // it means that the customer has not yes used this coupon. + if (null !== $couponCustomerCount = CouponCustomerCountQuery::create() + ->filterByCouponId($this->getId()) + ->filterByCustomerId($customerId) + ->findOne()) { + // The coupon has already been used -> remove this customer's usage count + $usageLeft -= $couponCustomerCount->getCount(); + } + } + + return $usageLeft; + } +} diff --git a/core/lib/Thelia/Model/CouponCountry.php b/core/lib/Thelia/Model/CouponCountry.php new file mode 100644 index 00000000..91122e69 --- /dev/null +++ b/core/lib/Thelia/Model/CouponCountry.php @@ -0,0 +1,9 @@ +findOneByByDefault(1); + + if (null === self::$defaultCurrency) { + throw new \RuntimeException("No default currency is defined. Please define one."); + } + } + + return self::$defaultCurrency; + } + + /** + * {@inheritDoc} + */ + public function preInsert(ConnectionInterface $con = null) + { + parent::preInsert($con); + + $this->dispatchEvent(TheliaEvents::BEFORE_CREATECURRENCY, new CurrencyEvent($this)); + + // Set the current position for the new object + $this->setPosition($this->getNextPosition()); + + return true; + } + + /** + * {@inheritDoc} + */ + public function postInsert(ConnectionInterface $con = null) + { + parent::postInsert($con); + + $this->dispatchEvent(TheliaEvents::AFTER_CREATECURRENCY, new CurrencyEvent($this)); + } + + /** + * {@inheritDoc} + */ + public function preUpdate(ConnectionInterface $con = null) + { + parent::preUpdate($con); + + $this->dispatchEvent(TheliaEvents::BEFORE_UPDATECURRENCY, new CurrencyEvent($this)); + + return true; + } + + /** + * {@inheritDoc} + */ + public function postUpdate(ConnectionInterface $con = null) + { + parent::postUpdate($con); + + $this->dispatchEvent(TheliaEvents::AFTER_UPDATECURRENCY, new CurrencyEvent($this)); + } + + /** + * {@inheritDoc} + */ + public function preDelete(ConnectionInterface $con = null) + { + parent::preDelete($con); + + $this->dispatchEvent(TheliaEvents::BEFORE_DELETECURRENCY, new CurrencyEvent($this)); + + return true; + } + + /** + * {@inheritDoc} + */ + public function postDelete(ConnectionInterface $con = null) + { + parent::postDelete($con); + + $this->dispatchEvent(TheliaEvents::AFTER_DELETECURRENCY, new CurrencyEvent($this)); + } + + /** + * Get the [rate] column value. + * + * @return double + * @throws PropelException + */ + public function getRate() + { + if (false === filter_var($this->rate, FILTER_VALIDATE_FLOAT)) { + throw new PropelException('Currency::rate is not float value'); + } + + return $this->rate; + } +} diff --git a/core/lib/Thelia/Model/CurrencyI18n.php b/core/lib/Thelia/Model/CurrencyI18n.php new file mode 100644 index 00000000..561f8ba0 --- /dev/null +++ b/core/lib/Thelia/Model/CurrencyI18n.php @@ -0,0 +1,11 @@ +setTitleId($titleId) + ->setFirstname($firstname) + ->setLastname($lastname) + ->setEmail($email, $forceEmailUpdate) + ->setPassword($plainPassword) + ->setReseller($reseller) + ->setSponsor($sponsor) + ->setDiscount($discount) + ->setRef($ref) + ; + + if (!\is_null($lang)) { + $this->setLangId($lang); + } + + $con = Propel::getWriteConnection(CustomerTableMap::DATABASE_NAME); + $con->beginTransaction(); + try { + if ($this->isNew()) { + $address = new Address(); + + $address + ->setLabel(Translator::getInstance()->trans("Main address")) + ->setCompany($company) + ->setTitleId($titleId) + ->setFirstname($firstname) + ->setLastname($lastname) + ->setAddress1($address1) + ->setAddress2($address2) + ->setAddress3($address3) + ->setPhone($phone) + ->setCellphone($cellphone) + ->setZipcode($zipcode) + ->setCity($city) + ->setCountryId($countryId) + ->setStateId($stateId) + ->setIsDefault(1) + ; + + $this->addAddress($address); + + if (ConfigQuery::isCustomerEmailConfirmationEnable()) { + $this->setConfirmationToken(bin2hex(random_bytes(32))); + } + } else { + $address = $this->getDefaultAddress(); + + $address + ->setCompany($company) + ->setTitleId($titleId) + ->setFirstname($firstname) + ->setLastname($lastname) + ->setAddress1($address1) + ->setAddress2($address2) + ->setAddress3($address3) + ->setPhone($phone) + ->setCellphone($cellphone) + ->setZipcode($zipcode) + ->setCity($city) + ->setCountryId($countryId) + ->setStateId($stateId) + ->save($con) + ; + } + $this->save($con); + + $con->commit(); + } catch (PropelException $e) { + $con->rollBack(); + throw $e; + } + } + + /** + * Return the customer lang, or the default one if none is defined. + * + * @return \Thelia\Model\Lang Lang model + */ + public function getCustomerLang() + { + $lang = $this->getLangModel(); + + if ($lang === null) { + $lang = (new LangQuery) + ->filterByByDefault(1) + ->findOne() + ; + } + + return $lang; + } + + /** + * Get lang identifier + * + * @return integer Lang id + * + * @deprecated 2.3.0 It's not the good way to get lang identifier + * + * @see \Thelia\Model\Customer::getLangId() + * @see \Thelia\Model\Customer::getLangModel() + */ + public function getLang() + { + return $this->getLangId(); + } + + /** + * Set lang identifier + * + * @param integer $langId Lang identifier + * + * @return $this Return $this, allow chaining + * + * @deprecated 2.3.0 It's not the good way to set lang identifier + * + * @see \Thelia\Model\Customer::setLangId() + * @see \Thelia\Model\Customer::setLangModel() + */ + public function setLang($langId) + { + return $this->setLangId($langId); + } + + protected function generateRef() + { + $lastCustomer = CustomerQuery::create() + ->orderById(Criteria::DESC) + ->findOne() + ; + + $id = 1; + if (null !== $lastCustomer) { + $id = $lastCustomer->getId() + 1; + } + + return sprintf('CUS%s', str_pad($id, 12, 0, STR_PAD_LEFT)); + } + + /** + * @return Address + */ + public function getDefaultAddress() + { + return AddressQuery::create() + ->filterByCustomer($this) + ->filterByIsDefault(1) + ->findOne(); + } + + public function setRef($v) + { + if (null !== $v) { + parent::setRef($v); + } + + return $this; + } + + /** + * create hash for plain password and set it in Customer object + * + * @param string $password plain password before hashing + * @throws Exception\InvalidArgumentException + * @return $this|Customer + */ + public function setPassword($password) + { + if ($this->isNew() && ($password === null || trim($password) == "")) { + throw new InvalidArgumentException("customer password is mandatory on creation"); + } + + if ($password !== null && trim($password) != "") { + $this->setAlgo("PASSWORD_BCRYPT"); + + parent::setPassword(password_hash($password, PASSWORD_BCRYPT)); + } + + return $this; + } +/* + public function setRef($ref) + { + if (null === $ref && null === $this->ref) { + parent::setRef($this->generateRef()); + } elseif (null !== $ref) { + parent::setRef($ref); + } + + return $this; + }*/ + + public function setEmail($email, $force = false) + { + $email = trim($email); + + if (($this->isNew() || $force === true) && ($email === null || $email == "")) { + throw new InvalidArgumentException("customer email is mandatory"); + } + + if (!$this->isNew() && $force === false) { + return $this; + } + + return parent::setEmail($email); + } + + /** + * {@inheritDoc} + */ + public function getUsername() + { + return $this->getEmail(); + } + + /** + * {@inheritDoc} + */ + public function checkPassword($password) + { + return password_verify($password, $this->password); + } + + /** + * {@inheritDoc} + */ + public function eraseCredentials() + { + parent::setPassword(null); + $this->resetModified(); + } + + /** + * {@inheritDoc} + */ + public function getRoles() + { + return array(new Role('CUSTOMER')); + } + + /** + * {@inheritDoc} + */ + public function getToken() + { + return $this->getRememberMeToken(); + } + + /** + * {@inheritDoc} + */ + public function setToken($token) + { + $this->setRememberMeToken($token)->save(); + } + + /** + * {@inheritDoc} + */ + public function getSerial() + { + return $this->getRememberMeSerial(); + } + + /** + * @return string + * @throws PropelException + */ + public function getLocale() + { + return $this->getLangModel()->getLocale(); + } + + public function hasOrder() + { + $order = OrderQuery::create() + ->filterByCustomerId($this->getId()) + ->count(); + + return $order > 0; + } + + /** + * {@inheritDoc} + */ + public function setSerial($serial) + { + $this->setRememberMeSerial($serial)->save(); + } + + /** + * {@inheritDoc} + */ + public function preInsert(ConnectionInterface $con = null) + { + parent::preInsert($con); + + // Set the serial number (for auto-login) + $this->setRememberMeSerial(uniqid()); + + if (null === $this->getRef()) { + $this->setRef($this->generateRef()); + } + + $this->dispatchEvent(TheliaEvents::BEFORE_CREATECUSTOMER, new CustomerEvent($this)); + + return true; + } + + /** + * {@inheritDoc} + */ + public function postInsert(ConnectionInterface $con = null) + { + parent::postInsert($con); + + $this->dispatchEvent(TheliaEvents::AFTER_CREATECUSTOMER, new CustomerEvent($this)); + } + + /** + * {@inheritDoc} + */ + public function preUpdate(ConnectionInterface $con = null) + { + parent::preUpdate($con); + + $this->dispatchEvent(TheliaEvents::BEFORE_UPDATECUSTOMER, new CustomerEvent($this)); + + return true; + } + + /** + * {@inheritDoc} + */ + public function postUpdate(ConnectionInterface $con = null) + { + parent::postUpdate($con); + + $this->dispatchEvent(TheliaEvents::AFTER_UPDATECUSTOMER, new CustomerEvent($this)); + } + + /** + * {@inheritDoc} + */ + public function preDelete(ConnectionInterface $con = null) + { + parent::preDelete($con); + + $this->dispatchEvent(TheliaEvents::BEFORE_DELETECUSTOMER, new CustomerEvent($this)); + + return true; + } + + /** + * {@inheritDoc} + */ + public function postDelete(ConnectionInterface $con = null) + { + parent::postDelete($con); + + $this->dispatchEvent(TheliaEvents::AFTER_DELETECUSTOMER, new CustomerEvent($this)); + } +} diff --git a/core/lib/Thelia/Model/CustomerQuery.php b/core/lib/Thelia/Model/CustomerQuery.php new file mode 100644 index 00000000..6f518f0c --- /dev/null +++ b/core/lib/Thelia/Model/CustomerQuery.php @@ -0,0 +1,41 @@ +findOneByEmail($email); + } + + public static function getMonthlyNewCustomersStats($month, $year) + { + $numberOfDay = cal_days_in_month(CAL_GREGORIAN, $month, $year); + + $stats = array(); + for ($day=1; $day<=$numberOfDay; $day++) { + $dayCustomers = self::create() + ->filterByCreatedAt(sprintf("%s-%s-%s 00:00:00", $year, $month, $day), Criteria::GREATER_EQUAL) + ->filterByCreatedAt(sprintf("%s-%s-%s 23:59:59", $year, $month, $day), Criteria::LESS_EQUAL) + ->count(); + $stats[] = array($day-1, $dayCustomers); + } + + return $stats; + } +} +// CustomerQuery diff --git a/core/lib/Thelia/Model/CustomerTitle.php b/core/lib/Thelia/Model/CustomerTitle.php new file mode 100644 index 00000000..be40ccad --- /dev/null +++ b/core/lib/Thelia/Model/CustomerTitle.php @@ -0,0 +1,35 @@ +beginTransaction(); + + try { + CustomerTitleQuery::create() + ->update(array('ByDefault' => '0')) + ; + + $this->setByDefault(1)->save(); + + $con->commit(); + } catch (\Exception $e) { + $con->rollBack(); + + throw $e; + } + } +} diff --git a/core/lib/Thelia/Model/CustomerTitleI18n.php b/core/lib/Thelia/Model/CustomerTitleI18n.php new file mode 100644 index 00000000..4ee213d4 --- /dev/null +++ b/core/lib/Thelia/Model/CustomerTitleI18n.php @@ -0,0 +1,11 @@ +getHandleClass(); + + if ($class[0] !== '\\') { + $class = '\\' . $class; + } + + if (!class_exists($class)) { + $this->delete(); + + throw new \ErrorException( + Translator::getInstance()->trans( + 'The class "%class" doesn\'t exist', + [ + '%class' => $class + ] + ) + ); + } + + $instance = new $class(); + + if (!$instance instanceof AbstractExport) { + $this->delete(); + + throw new \ErrorException( + Translator::getInstance()->trans( + 'The class "%class" must extend %baseClass', + [ + '%class' => $class, + '%baseClass' => 'Thelia\\ImportExport\\Export\\AbstractExport', + ] + ) + ); + } + + return $instance; + } + + public function hasImages() + { + if (static::$cache === null) { + static::$cache = $this->getHandleClassInstance(); + } + + return static::$cache->hasImages(); + } + + public function hasDocuments() + { + if (static::$cache === null) { + static::$cache = $this->getHandleClassInstance(); + } + + return static::$cache->hasDocuments(); + } + + public function useRangeDate() + { + if (static::$cache === null) { + static::$cache = $this->getHandleClassInstance(); + } + + return static::$cache->useRangeDate(); + } + + /** + * {@inheritDoc} + */ + public function preInsert(ConnectionInterface $con = null) + { + parent::preInsert($con); + + $this->setPosition($this->getNextPosition()); + + return true; + } + + public function addCriteriaToPositionQuery($query) + { + $query->filterByExportCategoryId($this->getExportCategoryId()); + } +} diff --git a/core/lib/Thelia/Model/ExportCategory.php b/core/lib/Thelia/Model/ExportCategory.php new file mode 100644 index 00000000..faad1230 --- /dev/null +++ b/core/lib/Thelia/Model/ExportCategory.php @@ -0,0 +1,26 @@ +setPosition($this->getNextPosition()); + + return true; + } +} diff --git a/core/lib/Thelia/Model/ExportCategoryI18n.php b/core/lib/Thelia/Model/ExportCategoryI18n.php new file mode 100644 index 00000000..9a2d01ed --- /dev/null +++ b/core/lib/Thelia/Model/ExportCategoryI18n.php @@ -0,0 +1,11 @@ +dispatchEvent(TheliaEvents::BEFORE_CREATEFEATURE, new FeatureEvent($this)); + + // Set the current position for the new object + $this->setPosition($this->getNextPosition()); + + return true; + } + + /** + * {@inheritDoc} + */ + public function postInsert(ConnectionInterface $con = null) + { + parent::postInsert($con); + + $this->dispatchEvent(TheliaEvents::AFTER_CREATEFEATURE, new FeatureEvent($this)); + } + + /** + * {@inheritDoc} + */ + public function preUpdate(ConnectionInterface $con = null) + { + parent::preUpdate($con); + + $this->dispatchEvent(TheliaEvents::BEFORE_UPDATEFEATURE, new FeatureEvent($this)); + + return true; + } + + /** + * {@inheritDoc} + */ + public function postUpdate(ConnectionInterface $con = null) + { + parent::postUpdate($con); + + $this->dispatchEvent(TheliaEvents::AFTER_UPDATEFEATURE, new FeatureEvent($this)); + } + + /** + * {@inheritDoc} + */ + public function preDelete(ConnectionInterface $con = null) + { + parent::preDelete($con); + + $this->dispatchEvent(TheliaEvents::BEFORE_DELETEFEATURE, new FeatureEvent($this)); + + return true; + } + + /** + * {@inheritDoc} + */ + public function postDelete(ConnectionInterface $con = null) + { + parent::postDelete($con); + + $this->dispatchEvent(TheliaEvents::AFTER_DELETEFEATURE, new FeatureEvent($this)); + } +} diff --git a/core/lib/Thelia/Model/FeatureAv.php b/core/lib/Thelia/Model/FeatureAv.php new file mode 100644 index 00000000..e01cb826 --- /dev/null +++ b/core/lib/Thelia/Model/FeatureAv.php @@ -0,0 +1,92 @@ +filterByFeatureId($this->getFeatureId()); + } + + /** + * {@inheritDoc} + */ + public function preInsert(ConnectionInterface $con = null) + { + parent::preInsert($con); + + // Set the current position for the new object + $this->setPosition($this->getNextPosition()); + + $this->dispatchEvent(TheliaEvents::BEFORE_CREATEFEATURE_AV, new FeatureAvEvent($this)); + + return true; + } + + /** + * {@inheritDoc} + */ + public function postInsert(ConnectionInterface $con = null) + { + parent::postInsert($con); + + $this->dispatchEvent(TheliaEvents::AFTER_CREATEFEATURE_AV, new FeatureAvEvent($this)); + } + + /** + * {@inheritDoc} + */ + public function preUpdate(ConnectionInterface $con = null) + { + parent::preUpdate($con); + + $this->dispatchEvent(TheliaEvents::BEFORE_UPDATEFEATURE_AV, new FeatureAvEvent($this)); + + return true; + } + + /** + * {@inheritDoc} + */ + public function postUpdate(ConnectionInterface $con = null) + { + parent::postUpdate($con); + + $this->dispatchEvent(TheliaEvents::AFTER_UPDATEFEATURE_AV, new FeatureAvEvent($this)); + } + + /** + * {@inheritDoc} + */ + public function preDelete(ConnectionInterface $con = null) + { + parent::preDelete($con); + + $this->dispatchEvent(TheliaEvents::BEFORE_DELETEFEATURE_AV, new FeatureAvEvent($this)); + + return true; + } + + /** + * {@inheritDoc} + */ + public function postDelete(ConnectionInterface $con = null) + { + parent::postDelete($con); + + $this->dispatchEvent(TheliaEvents::AFTER_DELETEFEATURE_AV, new FeatureAvEvent($this)); + } +} diff --git a/core/lib/Thelia/Model/FeatureAvI18n.php b/core/lib/Thelia/Model/FeatureAvI18n.php new file mode 100644 index 00000000..1a4e768e --- /dev/null +++ b/core/lib/Thelia/Model/FeatureAvI18n.php @@ -0,0 +1,11 @@ +dispatchEvent(TheliaEvents::BEFORE_CREATEFEATURE_PRODUCT, new FeatureProductEvent($this)); + + return true; + } + + /** + * {@inheritDoc} + */ + public function postInsert(ConnectionInterface $con = null) + { + parent::postInsert($con); + + $this->dispatchEvent(TheliaEvents::AFTER_CREATEFEATURE_PRODUCT, new FeatureProductEvent($this)); + } + + /** + * {@inheritDoc} + */ + public function preUpdate(ConnectionInterface $con = null) + { + parent::preUpdate($con); + + $this->dispatchEvent(TheliaEvents::BEFORE_UPDATEFEATURE_PRODUCT, new FeatureProductEvent($this)); + + return true; + } + + /** + * {@inheritDoc} + */ + public function postUpdate(ConnectionInterface $con = null) + { + parent::postUpdate($con); + + $this->dispatchEvent(TheliaEvents::AFTER_UPDATEFEATURE_PRODUCT, new FeatureProductEvent($this)); + } + + /** + * {@inheritDoc} + */ + public function preDelete(ConnectionInterface $con = null) + { + parent::preDelete($con); + + $this->dispatchEvent(TheliaEvents::BEFORE_DELETEFEATURE_PRODUCT, new FeatureProductEvent($this)); + + return true; + } + + /** + * {@inheritDoc} + */ + public function postDelete(ConnectionInterface $con = null) + { + parent::postDelete($con); + + $this->dispatchEvent(TheliaEvents::AFTER_DELETEFEATURE_PRODUCT, new FeatureProductEvent($this)); + } + + /** + * @inheritdoc + * @deprecated since version 2.4.0, to be removed in 3.0. + * Please use getIsFreeText() instead + */ + public function getFreeTextValue() + { + $bt = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 1); + Tlog::getInstance()->warning(sprintf('Using `free_text_value` is deprecated. Use `is_free_text` instead. Used in %s:%d', $bt[0]['file'], $bt[0]['line'])); + return parent::getFreeTextValue(); + } + + /** + * @inheritdoc + * @deprecated since version 2.4.0, to be removed in 3.0. + * Please use setIsFreeText() instead + */ + public function setFreeTextValue($v) + { + $bt = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 1); + Tlog::getInstance()->warning(sprintf('Using `free_text_value` is deprecated. Use `is_free_text` instead. Used in %s:%d', $bt[0]['file'], $bt[0]['line'])); + $this->setIsFreeText($v ? true : false); + return parent::setFreeTextValue($v); + } + + /** + * {@inheritDoc} + */ + public function setIsFreeText($v) + { + parent::setFreeTextValue($v ? 1 : null); //for preventing log deprecation and infinity recursion + return parent::setIsFreeText($v); + } +} diff --git a/core/lib/Thelia/Model/FeatureProductQuery.php b/core/lib/Thelia/Model/FeatureProductQuery.php new file mode 100644 index 00000000..329d2785 --- /dev/null +++ b/core/lib/Thelia/Model/FeatureProductQuery.php @@ -0,0 +1,81 @@ +warning(sprintf('Using `free_text_value` is deprecated. Use `is_free_text` instead. Used in %s:%d', $bt[0]['file'], $bt[0]['line'])); + return parent::filterByFreeTextValue($freeTextValue, $comparison); + } + + /** + * @inheritdoc + * @deprecated since version 2.4.0, to be removed in 3.0. + * Please use orderByIsFreeText() instead + */ + public function orderByFreeTextValue($order = Criteria::ASC) + { + $bt = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 1); + Tlog::getInstance()->warning(sprintf('Using `free_text_value` is deprecated. Use `is_free_text` instead. Used in %s:%d', $bt[0]['file'], $bt[0]['line'])); + return parent::orderByFreeTextValue($order); + } + + /** + * @inheritdoc + * @deprecated since version 2.4.0, to be removed in 3.0. + * Please use groupByIsFreeText() instead + */ + public function groupByFreeTextValue() + { + $bt = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 1); + Tlog::getInstance()->warning(sprintf('Using `free_text_value` is deprecated. Use `is_free_text` instead. Used in %s:%d', $bt[0]['file'], $bt[0]['line'])); + return parent::groupByFreeTextValue(); + } + + /** + * @inheritdoc + * @deprecated since version 2.4.0, to be removed in 3.0. + * Please use findByIsFreeText() instead + */ + public function findByFreeTextValue($free_text_value) + { + $bt = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 1); + Tlog::getInstance()->warning(sprintf('Using `free_text_value` is deprecated. Use `is_free_text` instead. Used in %s:%d', $bt[0]['file'], $bt[0]['line'])); + return parent::findByFreeTextValue($free_text_value); + } + + /** + * @inheritdoc + * @deprecated since version 2.4.0, to be removed in 3.0. + * Please use findOneByIsFreeText() instead + */ + public function findOneByFreeTextValue($free_text_value) + { + $bt = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 1); + Tlog::getInstance()->warning(sprintf('Using `free_text_value` is deprecated. Use `is_free_text` instead. Used in %s:%d', $bt[0]['file'], $bt[0]['line'])); + return parent::findOneByFreeTextValue($free_text_value); + } +} +// FeatureProductQuery diff --git a/core/lib/Thelia/Model/FeatureQuery.php b/core/lib/Thelia/Model/FeatureQuery.php new file mode 100644 index 00000000..2e7d1a13 --- /dev/null +++ b/core/lib/Thelia/Model/FeatureQuery.php @@ -0,0 +1,20 @@ +filterByTemplateId($this->getTemplateId()); + } + + /** + * {@inheritDoc} + */ + public function preInsert(ConnectionInterface $con = null) + { + parent::preInsert($con); + + // Set the current position for the new object + $this->setPosition($this->getNextPosition()); + + return true; + } +} diff --git a/core/lib/Thelia/Model/FeatureTemplateQuery.php b/core/lib/Thelia/Model/FeatureTemplateQuery.php new file mode 100644 index 00000000..35dde788 --- /dev/null +++ b/core/lib/Thelia/Model/FeatureTemplateQuery.php @@ -0,0 +1,20 @@ +getId()); + } + + /** + * count all products for current category and sub categories + * + * @param bool|string $contentVisibility: true (default) to count only visible products, false to count only hidden + * products, or * to count all products. + * @return int + */ + public function countAllContents($contentVisibility = true) + { + $children = FolderQuery::findAllChild($this->getId()); + array_push($children, $this); + + + $query = ContentQuery::create()->filterByFolder(new ObjectCollection($children), Criteria::IN); + + if ($contentVisibility !== '*') { + $query->filterByVisible($contentVisibility); + } + + return $query->count(); + } + + /** + * Get the root folder + * @param int $folderId + * @return mixed + */ + public function getRoot($folderId) + { + $folder = FolderQuery::create()->findPk($folderId); + + if (0 !== $folder->getParent()) { + $parentFolder = FolderQuery::create()->findPk($folder->getParent()); + + if (null !== $parentFolder) { + $folderId = $this->getRoot($parentFolder->getId()); + } + } + + return $folderId; + } + + /** + * Calculate next position relative to our parent + + * @param FolderQuery $query + */ + protected function addCriteriaToPositionQuery($query) + { + $query->filterByParent($this->getParent()); + } + + /** + * {@inheritDoc} + */ + public function preInsert(ConnectionInterface $con = null) + { + parent::preInsert($con); + + $this->setPosition($this->getNextPosition()); + + $this->dispatchEvent(TheliaEvents::BEFORE_CREATEFOLDER, new FolderEvent($this)); + + return true; + } + + public function postInsert(ConnectionInterface $con = null) + { + parent::postInsert($con); + + $this->dispatchEvent(TheliaEvents::AFTER_CREATEFOLDER, new FolderEvent($this)); + } + + public function preUpdate(ConnectionInterface $con = null) + { + parent::preUpdate($con); + + $this->dispatchEvent(TheliaEvents::BEFORE_UPDATEFOLDER, new FolderEvent($this)); + + return true; + } + + public function postUpdate(ConnectionInterface $con = null) + { + parent::postUpdate($con); + + $this->dispatchEvent(TheliaEvents::AFTER_UPDATEFOLDER, new FolderEvent($this)); + } + + public function preDelete(ConnectionInterface $con = null) + { + parent::preDelete($con); + + $this->dispatchEvent(TheliaEvents::BEFORE_DELETEFOLDER, new FolderEvent($this)); + $this->reorderBeforeDelete( + array( + "parent" => $this->getParent(), + ) + ); + + return true; + } + + public function postDelete(ConnectionInterface $con = null) + { + parent::postDelete($con); + + $this->markRewrittenUrlObsolete(); + + $this->dispatchEvent(TheliaEvents::AFTER_DELETEFOLDER, new FolderEvent($this)); + } + + /** + * Overload for the position management + * @param Base\ContentFolder $contentFolder + * @inheritdoc + */ + protected function doAddContentFolder($contentFolder) + { + parent::doAddContentFolder($contentFolder); + + $contentFolderPosition = ContentFolderQuery::create() + ->filterByFolderId($contentFolder->getFolderId()) + ->orderByPosition(Criteria::DESC) + ->findOne(); + + $contentFolder->setPosition($contentFolderPosition !== null ? $contentFolderPosition->getPosition() + 1 : 1); + } +} diff --git a/core/lib/Thelia/Model/FolderDocument.php b/core/lib/Thelia/Model/FolderDocument.php new file mode 100644 index 00000000..cc27a535 --- /dev/null +++ b/core/lib/Thelia/Model/FolderDocument.php @@ -0,0 +1,137 @@ +filterByFolder($this->getFolder()); + } + + /** + * {@inheritDoc} + */ + public function preInsert(ConnectionInterface $con = null) + { + parent::preInsert($con); + + $this->setPosition($this->getNextPosition()); + + return true; + } + + /** + * @inheritdoc + */ + public function setParentId($parentId) + { + $this->setFolderId($parentId); + + return $this; + } + + /** + * @inheritdoc + */ + public function getParentId() + { + return $this->getFolderId(); + } + + public function preDelete(ConnectionInterface $con = null) + { + parent::preDelete($con); + + $this->reorderBeforeDelete( + array( + "folder_id" => $this->getFolderId(), + ) + ); + + return true; + } + + /** + * @inheritdoc + */ + public function getBreadcrumb(Router $router, ContainerInterface $container, $tab, $locale) + { + return $this->getFolderBreadcrumb($router, $container, $tab, $locale); + } + + /** + * @return FileModelParentInterface the parent file model + */ + public function getParentFileModel() + { + return new Folder(); + } + + /** + * Get the ID of the form used to change this object information + * + * @return BaseForm the form + */ + public function getUpdateFormId() + { + return AdminForm::FOLDER_DOCUMENT_MODIFICATION; + } + + /** + * @return string the path to the upload directory where files are stored, without final slash + */ + public function getUploadDir() + { + $uploadDir = ConfigQuery::read('documents_library_path'); + if ($uploadDir === null) { + $uploadDir = THELIA_LOCAL_DIR . 'media' . DS . 'documents'; + } else { + $uploadDir = THELIA_ROOT . $uploadDir; + } + + return $uploadDir . DS . 'folder'; + } + + /** + * @param int $objectId the ID of the parent object + * @return string the URL to redirect to after update from the back-office + */ + public function getRedirectionUrl() + { + return '/admin/folders/update/' . $this->getFolderId(); + } + + /** + * Get the Query instance for this object + * + * @return ModelCriteria + */ + public function getQueryInstance() + { + return FolderDocumentQuery::create(); + } +} diff --git a/core/lib/Thelia/Model/FolderDocumentI18n.php b/core/lib/Thelia/Model/FolderDocumentI18n.php new file mode 100644 index 00000000..e10e0104 --- /dev/null +++ b/core/lib/Thelia/Model/FolderDocumentI18n.php @@ -0,0 +1,11 @@ +getFolder(); + $folder->generateRewrittenUrl($this->getLocale()); + } +} diff --git a/core/lib/Thelia/Model/FolderI18nQuery.php b/core/lib/Thelia/Model/FolderI18nQuery.php new file mode 100644 index 00000000..fa71ca1b --- /dev/null +++ b/core/lib/Thelia/Model/FolderI18nQuery.php @@ -0,0 +1,20 @@ +filterByFolder($this->getFolder()); + } + + /** + * {@inheritDoc} + */ + public function preInsert(ConnectionInterface $con = null) + { + parent::preInsert($con); + + $this->setPosition($this->getNextPosition()); + + return true; + } + + /** + * @inheritdoc + */ + public function setParentId($parentId) + { + $this->setFolderId($parentId); + + return $this; + } + + /** + * @inheritdoc + */ + public function getParentId() + { + return $this->getFolderId(); + } + + public function preDelete(ConnectionInterface $con = null) + { + parent::preDelete($con); + + $this->reorderBeforeDelete( + array( + "folder_id" => $this->getFolderId(), + ) + ); + + return true; + } + + /** + * @inheritdoc + */ + public function getBreadcrumb(Router $router, ContainerInterface $container, $tab, $locale) + { + return $this->getFolderBreadcrumb($router, $container, $tab, $locale); + } + + /** + * @return FileModelParentInterface the parent file model + */ + public function getParentFileModel() + { + return new Folder(); + } + + /** + * Get the ID of the form used to change this object information + * + * @return BaseForm the form + */ + public function getUpdateFormId() + { + return AdminForm::FOLDER_IMAGE_MODIFICATION; + } + + /** + * @return string the path to the upload directory where files are stored, without final slash + */ + public function getUploadDir() + { + $uploadDir = ConfigQuery::read('images_library_path'); + if ($uploadDir === null) { + $uploadDir = THELIA_LOCAL_DIR . 'media' . DS . 'images'; + } else { + $uploadDir = THELIA_ROOT . $uploadDir; + } + + return $uploadDir . DS . 'folder'; + } + + /** + * @param int $objectId the ID of the parent object + * @return string the URL to redirect to after update from the back-office + */ + public function getRedirectionUrl() + { + return '/admin/folders/update/' . $this->getFolderId(); + } + + /** + * Get the Query instance for this object + * + * @return ModelCriteria + */ + public function getQueryInstance() + { + return FolderImageQuery::create(); + } +} diff --git a/core/lib/Thelia/Model/FolderImageI18n.php b/core/lib/Thelia/Model/FolderImageI18n.php new file mode 100644 index 00000000..6bc9ed38 --- /dev/null +++ b/core/lib/Thelia/Model/FolderImageI18n.php @@ -0,0 +1,11 @@ +filterByParent($parent)->count(); + } + + /** + * find all contents for a given folder. + * + * @param int $folderId the folder id or an array of id + * @param int $depth max depth you want to search + * @param int $currentPosition don't change this param, it is used for recursion + * @return \Thelia\Model\Folder[] + */ + public static function findAllChild($folderId, $depth = 0, $currentPosition = 0) + { + $result = array(); + + if (\is_array($folderId)) { + foreach ($folderId as $folderSingleId) { + $result = array_merge($result, (array) self::findAllChild($folderSingleId, $depth, $currentPosition)); + } + } else { + $currentPosition++; + + if ($depth == $currentPosition && $depth != 0) { + return[]; + } + + $categories = self::create() + ->filterByParent($folderId) + ->find(); + + foreach ($categories as $folder) { + array_push($result, $folder); + $result = array_merge($result, (array) self::findAllChild($folder->getId(), $depth, $currentPosition)); + } + } + + return $result; + } + + /** + * Return all folder IDs of a folder tree, starting at $folderId, up to a depth of $depth + * + * @param int|int[] $folderId the folder id or an array of folder ids + * @param int $depth max tree traversal depth + * @return int[] + * @since 2.3 + */ + public static function getFolderTreeIds($folderId, $depth = 1) + { + $result = \is_array($folderId) ? $folderId : [ $folderId ]; + + if ($depth > 1) { + $folders = self::create() + ->filterByParent($folderId, Criteria::IN) + ->withColumn('id') + ->find(); + + foreach ($folders as $folder) { + $result = array_merge( + $result, + self::getFolderTreeIds($folder->getId(), $depth - 1) + ); + } + } + + return $result; + } +} +// FolderQuery diff --git a/core/lib/Thelia/Model/FolderVersion.php b/core/lib/Thelia/Model/FolderVersion.php new file mode 100644 index 00000000..9dd26172 --- /dev/null +++ b/core/lib/Thelia/Model/FolderVersion.php @@ -0,0 +1,9 @@ +setAttempts(0)->save(); + + return $this; + } + + public function incrementAttempts() + { + $this->setAttempts( + $this->getAttempts() + 1 + ); + + $this->save(); + + return $this; + } +} diff --git a/core/lib/Thelia/Model/FormFirewallQuery.php b/core/lib/Thelia/Model/FormFirewallQuery.php new file mode 100644 index 00000000..f18a2518 --- /dev/null +++ b/core/lib/Thelia/Model/FormFirewallQuery.php @@ -0,0 +1,20 @@ +setPosition($this->getNextPosition()); + + return true; + } + + public function addCriteriaToPositionQuery($query) + { + $query->filterByImportCategoryId($this->getImportCategoryId()); + } +} diff --git a/core/lib/Thelia/Model/ImportCategory.php b/core/lib/Thelia/Model/ImportCategory.php new file mode 100644 index 00000000..0086a9f5 --- /dev/null +++ b/core/lib/Thelia/Model/ImportCategory.php @@ -0,0 +1,26 @@ +setPosition($this->getNextPosition()); + + return true; + } +} diff --git a/core/lib/Thelia/Model/ImportCategoryI18n.php b/core/lib/Thelia/Model/ImportCategoryI18n.php new file mode 100644 index 00000000..cdd669ac --- /dev/null +++ b/core/lib/Thelia/Model/ImportCategoryI18n.php @@ -0,0 +1,11 @@ +findOneByByDefault(1); + + if (null === self::$defaultLanguage) { + throw new \RuntimeException("No default language is defined. Please define one."); + } + } + + return self::$defaultLanguage; + } + + public function toggleDefault() + { + if ($this->getId() === null) { + throw new \RuntimeException("impossible to just uncheck default language, choose a new one"); + } + if (!$this->getByDefault()) { + $con = Propel::getWriteConnection(LangTableMap::DATABASE_NAME); + $con->beginTransaction(); + try { + LangQuery::create() + ->filterByByDefault(1) + ->update(array('ByDefault' => 0), $con); + + $this + ->setVisible(1) + ->setActive(1) + ->setByDefault(1) + ->save($con); + + $con->commit(); + } catch (PropelException $e) { + $con->rollBack(); + throw $e; + } + } + } + + public function preInsert(ConnectionInterface $con = null) + { + parent::preInsert($con); + + $this->dispatchEvent(TheliaEvents::BEFORE_CREATELANG, new LangEvent($this)); + + return true; + } + + public function postInsert(ConnectionInterface $con = null) + { + parent::postInsert($con); + + $this->dispatchEvent(TheliaEvents::AFTER_CREATELANG, new LangEvent($this)); + + $this->dispatchEvent(TheliaEvents::LANG_FIX_MISSING_FLAG, new LangEvent($this)); + } + + public function preUpdate(ConnectionInterface $con = null) + { + parent::preUpdate($con); + + $this->dispatchEvent(TheliaEvents::BEFORE_UPDATELANG, new LangEvent($this)); + + return true; + } + + public function postUpdate(ConnectionInterface $con = null) + { + parent::postUpdate($con); + + $this->dispatchEvent(TheliaEvents::AFTER_UPDATELANG, new LangEvent($this)); + + $this->dispatchEvent(TheliaEvents::LANG_FIX_MISSING_FLAG, new LangEvent($this)); + } + + public function preDelete(ConnectionInterface $con = null) + { + parent::preDelete($con); + + $this->dispatchEvent(TheliaEvents::BEFORE_DELETELANG, new LangEvent($this)); + + return true; + } + + public function postDelete(ConnectionInterface $con = null) + { + parent::postDelete($con); + + $this->dispatchEvent(TheliaEvents::AFTER_DELETELANG, new LangEvent($this)); + } + + public function preSave(ConnectionInterface $con = null) + { + // If the date/time format is not specified, generate it. + $dateTimeFormat = $this->getDateTimeFormat(); + if (empty($dateTimeFormat)) { + $this->setDatetimeFormat(sprintf("%s %s", $this->getDateFormat(), $this->getTimeFormat())); + } + + return parent::preSave($con); + } +} diff --git a/core/lib/Thelia/Model/LangQuery.php b/core/lib/Thelia/Model/LangQuery.php new file mode 100644 index 00000000..8671cff5 --- /dev/null +++ b/core/lib/Thelia/Model/LangQuery.php @@ -0,0 +1,29 @@ +findPk($search); + + if (null === $find) { + $find = $this->findOneByLocale($search); + } + + return $find; + } +} diff --git a/core/lib/Thelia/Model/Message.php b/core/lib/Thelia/Model/Message.php new file mode 100644 index 00000000..f91e84f9 --- /dev/null +++ b/core/lib/Thelia/Model/Message.php @@ -0,0 +1,205 @@ +dispatchEvent(TheliaEvents::BEFORE_CREATEMESSAGE, new MessageEvent($this)); + + return true; + } + + /** + * {@inheritDoc} + */ + public function postInsert(ConnectionInterface $con = null) + { + parent::postInsert($con); + + $this->dispatchEvent(TheliaEvents::AFTER_CREATEMESSAGE, new MessageEvent($this)); + } + + /** + * {@inheritDoc} + */ + public function preUpdate(ConnectionInterface $con = null) + { + parent::preUpdate($con); + + $this->dispatchEvent(TheliaEvents::BEFORE_UPDATEMESSAGE, new MessageEvent($this)); + + return true; + } + + /** + * {@inheritDoc} + */ + public function postUpdate(ConnectionInterface $con = null) + { + parent::postUpdate($con); + + $this->dispatchEvent(TheliaEvents::AFTER_UPDATEMESSAGE, new MessageEvent($this)); + } + + /** + * {@inheritDoc} + */ + public function preDelete(ConnectionInterface $con = null) + { + parent::preDelete($con); + + $this->dispatchEvent(TheliaEvents::BEFORE_DELETEMESSAGE, new MessageEvent($this)); + + return true; + } + + /** + * {@inheritDoc} + */ + public function postDelete(ConnectionInterface $con = null) + { + parent::postDelete($con); + + $this->dispatchEvent(TheliaEvents::AFTER_DELETEMESSAGE, new MessageEvent($this)); + } + + /** + * Calculate the message body, given the HTML entered in the back-office, the message layout, and the message template + * @param ParserInterface $parser + * @param string $message + * @param $layout + * @param $template + * @param bool $compressOutput + * @return bool|string + * @throws \SmartyException + */ + protected function getMessageBody($parser, $message, $layout, $template, $compressOutput = true) + { + $body = false; + + // Try to get the body from template file, if a file is defined + if (! empty($template)) { + try { + $body = $parser->render($template, [], $compressOutput); + } catch (ResourceNotFoundException $ex) { + Tlog::getInstance()->addError("Failed to get mail message template body $template"); + } + } + + // We did not get it ? Use the message entered in the back-office + if ($body === false) { + $body = $parser->renderString($message, [], $compressOutput); + } + + // Do we have a layout ? + if (! empty($layout)) { + // Populate the message body variable + $parser->assign('message_body', $body); + + // Render the layout file + $body = $parser->render($layout, [], $compressOutput); + } + + return $body; + } + + /** + * Get the HTML message body + * @param ParserInterface $parser + * @return bool|string + * @throws \SmartyException + */ + public function getHtmlMessageBody(ParserInterface $parser) + { + return $this->getMessageBody( + $parser, + $this->getHtmlMessage(), + $this->getHtmlLayoutFileName(), + $this->getHtmlTemplateFileName() + ); + } + + /** + * @param ParserInterface $parser + * @return string|string[]|null + * @throws \SmartyException + */ + public function getTextMessageBody(ParserInterface $parser) + { + $message = $this->getMessageBody( + $parser, + $this->getTextMessage(), + $this->getTextLayoutFileName(), + $this->getTextTemplateFileName(), + true // Do not compress the output, and keep empty lines. + ); + + // Replaced all
    by newlines. + return preg_replace("/
    /i", "\n", $message); + } + + /** + * Add a subject and a body (TEXT, HTML or both, depending on the message + * configuration. + * + * @param ParserInterface $parser + * @param \Swift_Message $messageInstance + * @param bool $useFallbackTemplate When we send mail from a module and don't use the `default` email + * template, if the file (html/txt) is not found in the template then + * the template file located in the module under + * `templates/email/default/' directory is used if + * `$useFallbackTemplate` is set to `true`. + * @return \Swift_Message + * @throws \SmartyException + */ + public function buildMessage(ParserInterface $parser, \Swift_Message $messageInstance, $useFallbackTemplate = true) + { + // Set mail template, and save the current template + $parser->pushTemplateDefinition( + $parser->getTemplateHelper()->getActiveMailTemplate(), + $useFallbackTemplate + ); + + $subject = $parser->renderString($this->getSubject()); + $htmlMessage = $this->getHtmlMessageBody($parser); + $textMessage = $this->getTextMessageBody($parser); + + $messageInstance->setSubject($subject); + + // If we do not have an HTML message + if (empty($htmlMessage)) { + // Message body is the text message + $messageInstance->setBody($textMessage, 'text/plain'); + } else { + // The main body is the HTML messahe + $messageInstance->setBody($htmlMessage, 'text/html'); + + // Use the text as a message part, if we have one. + if (! empty($textMessage)) { + $messageInstance->addPart($textMessage, 'text/plain'); + } + } + + // Restore previous template + $parser->popTemplateDefinition(); + + return $messageInstance; + } +} diff --git a/core/lib/Thelia/Model/MessageI18n.php b/core/lib/Thelia/Model/MessageI18n.php new file mode 100644 index 00000000..3dea3a5b --- /dev/null +++ b/core/lib/Thelia/Model/MessageI18n.php @@ -0,0 +1,11 @@ +filterByName($messageName)->findOne()) { + throw new \Exception("Failed to load message $messageName."); + } + + return $message; + } +} +// MessageQuery diff --git a/core/lib/Thelia/Model/MessageVersion.php b/core/lib/Thelia/Model/MessageVersion.php new file mode 100644 index 00000000..b96cd6c9 --- /dev/null +++ b/core/lib/Thelia/Model/MessageVersion.php @@ -0,0 +1,9 @@ +filterByMetaKey($metaKey) + ->filterByElementKey($elementKey) + ->filterByElementId($elementId) + ->findOne(); + + if (null !== $data) { + /** @var MetaData $data */ + $out = $data->getValue(); + } else { + $out = $default; + } + + return $out; + } + + /** + * + * @param string $elementKey the element Key : product, category, ... + * @param int $elementId the element id + * + * @return array all meta data affected to this element + */ + public static function getAllVal($elementKey, $elementId) + { + $out = array(); + + if (\is_int($elementId)) { + $datas = self::create() + ->filterByElementKey($elementKey) + ->filterByElementId($elementId) + ->find(); + if (null !== $datas) { + /** @var MetaData $data */ + foreach ($datas as $data) { + $out[$data->getMetaKey()] = $data->getValue(); + } + } + } + + return $out; + } + + /** + * Add or update the MetaData element + * + * @param string $metaKey the meta Key + * @param string $elementKey the element Key : product, category, ... + * @param int $elementId the element id + */ + public static function setVal($metaKey, $elementKey, $elementId, $value) + { + $data = self::create() + ->filterByMetaKey($metaKey) + ->filterByElementKey($elementKey) + ->filterByElementId($elementId) + ->findOne() + ; + + if (null === $data) { + $data = new MetaData(); + $data->setMetaKey($metaKey); + $data->setElementKey($elementKey); + $data->setElementId($elementId); + } + + $data->setValue($value); + + $data->save(); + } +} +// MetaDataQuery diff --git a/core/lib/Thelia/Model/Module.php b/core/lib/Thelia/Model/Module.php new file mode 100644 index 00000000..06909f0f --- /dev/null +++ b/core/lib/Thelia/Model/Module.php @@ -0,0 +1,338 @@ +getCode()); + } + + public function getAdminIncludesTranslationDomain() + { + return $this->getTranslationDomain().'.ai'; + } + + public function getAbsoluteBackOfficeTemplatePath($subdir) + { + return sprintf( + "%s".DS."%s".DS."%s", + $this->getAbsoluteTemplateBasePath(), + TemplateDefinition::BACK_OFFICE_SUBDIR, + $subdir + ); + } + + public function getAbsoluteBackOfficeI18nTemplatePath($subdir) + { + return sprintf( + "%s".DS."%s".DS."%s", + $this->getAbsoluteI18nPath(), + TemplateDefinition::BACK_OFFICE_SUBDIR, + $subdir + ); + } + + public function getBackOfficeTemplateTranslationDomain($templateName) + { + return $this->getTranslationDomain(). '.bo.' . $templateName; + } + + public function getAbsoluteFrontOfficeTemplatePath($subdir) + { + return sprintf( + "%s".DS."%s".DS."%s", + $this->getAbsoluteTemplateBasePath(), + TemplateDefinition::FRONT_OFFICE_SUBDIR, + $subdir + ); + } + + public function getAbsoluteFrontOfficeI18nTemplatePath($subdir) + { + return sprintf( + "%s".DS."%s".DS."%s", + $this->getAbsoluteI18nPath(), + TemplateDefinition::FRONT_OFFICE_SUBDIR, + $subdir + ); + } + + public function getFrontOfficeTemplateTranslationDomain($templateName) + { + return $this->getTranslationDomain(). '.fo.' . $templateName; + } + + public function getAbsolutePdfTemplatePath($subdir) + { + return sprintf( + "%s".DS."%s".DS."%s", + $this->getAbsoluteTemplateBasePath(), + TemplateDefinition::PDF_SUBDIR, + $subdir + ); + } + + public function getAbsolutePdfI18nTemplatePath($subdir) + { + return sprintf( + "%s".DS."%s".DS."%s", + $this->getAbsoluteI18nPath(), + TemplateDefinition::PDF_SUBDIR, + $subdir + ); + } + + public function getPdfTemplateTranslationDomain($templateName) + { + return $this->getTranslationDomain(). '.pdf.' . $templateName; + } + + + public function getAbsoluteEmailTemplatePath($subdir) + { + return sprintf( + "%s".DS."%s".DS."%s", + $this->getAbsoluteTemplateBasePath(), + TemplateDefinition::EMAIL_SUBDIR, + $subdir + ); + } + + public function getAbsoluteEmailI18nTemplatePath($subdir) + { + return sprintf( + "%s".DS."%s".DS."%s", + $this->getAbsoluteI18nPath(), + TemplateDefinition::EMAIL_SUBDIR, + $subdir + ); + } + + public function getEmailTemplateTranslationDomain($templateName) + { + return $this->getTranslationDomain(). '.email.' . $templateName; + } + + /** + * @return string the module's base directory path, relative to THELIA_MODULE_DIR + */ + public function getBaseDir() + { + return ucfirst($this->getCode()); + } + + /** + * @return string the module's base directory path, relative to THELIA_MODULE_DIR + */ + public function getAbsoluteBaseDir() + { + return THELIA_MODULE_DIR . $this->getBaseDir(); + } + + /** + * @return string the module's config directory path, relative to THELIA_MODULE_DIR + */ + public function getConfigPath() + { + return $this->getBaseDir() . DS . "Config"; + } + + /** + * @return string the module's config absolute directory path + */ + public function getAbsoluteConfigPath() + { + return THELIA_MODULE_DIR . $this->getConfigPath(); + } + + /** + * @return string the module's i18N directory path, relative to THELIA_MODULE_DIR + */ + public function getI18nPath() + { + return $this->getBaseDir() . DS . "I18n"; + } + + /** + * @return string the module's i18N absolute directory path + */ + public function getAbsoluteI18nPath() + { + return THELIA_MODULE_DIR . $this->getI18nPath(); + } + + /** + * @return string the module's AdminIncludes absolute directory path + */ + public function getAbsoluteAdminIncludesPath() + { + return $this->getAbsoluteBaseDir() . DS . self::ADMIN_INCLUDES_DIRECTORY_NAME; + } + + /** + * @return string the module's AdminIncludes i18N absolute directory path + */ + public function getAbsoluteAdminIncludesI18nPath() + { + return THELIA_MODULE_DIR . $this->getI18nPath() . DS . self::ADMIN_INCLUDES_DIRECTORY_NAME; + } + + /** + * Return the absolute path to the module's template directory + * + * @return string a path + */ + public function getAbsoluteTemplateBasePath() + { + return $this->getAbsoluteBaseDir() . DS . 'templates'; + } + + /** + * Return the absolute path to one of the module's template directories + * + * @param string $templateSubdirName the name of the, probably one of TemplateDefinition::xxx_SUBDIR constants + * @return string a path + */ + public function getAbsoluteTemplateDirectoryPath($templateSubdirName) + { + return $this->getAbsoluteTemplateBasePath() .DS. $templateSubdirName; + } + + /** + * @return true if this module is a delivery module + */ + public function isDeliveryModule() + { + $moduleReflection = new \ReflectionClass($this->getFullNamespace()); + + return $moduleReflection->implementsInterface("Thelia\Module\DeliveryModuleInterface") + || + $moduleReflection->implementsInterface("Thelia\Module\DeliveryModuleWithStateInterface"); + } + + /** + * @return true if this module is a payment module + */ + public function isPayementModule() + { + $moduleReflection = new \ReflectionClass($this->getFullNamespace()); + + return $moduleReflection->implementsInterface("Thelia\Module\PaymentModuleInterface"); + } + + /** + * @return bool true if the module image has been deployed, false otherwise. + */ + public function isModuleImageDeployed() + { + return ModuleImageQuery::create()->filterByModuleId($this->getId())->count() > 0; + } + + /** + * @param ContainerInterface $container the Thelia container + * @return BaseModuleInterface a module instance + * @throws \InvalidArgumentException if the module could not be found in the container/ + */ + public function getModuleInstance(ContainerInterface $container) + { + $instance = $container->get(sprintf('module.%s', $this->getCode())); + + if ($instance == null) { + throw new \InvalidArgumentException(sprintf('Undefined module in container: "%s"', $this->getCode())); + } + + return $instance; + } + + /** + * @param ContainerInterface $container the Thelia container + * @return BaseModuleInterface a module instance + * @throws \InvalidArgumentException if the module could not be found in the container/ + */ + public function getDeliveryModuleInstance(ContainerInterface $container) + { + $instance = $this->getModuleInstance($container); + + if ( + !in_array("Thelia\Module\DeliveryModuleInterface", class_implements($instance)) + && + !in_array("Thelia\Module\DeliveryModuleWithStateInterface", class_implements($instance)) + ) { + throw new \InvalidArgumentException(sprintf('Module "%s" is not a delivery module', $this->getCode())); + } + + return $instance; + } + + /** + * @param ContainerInterface $container the Thelia container + * @return PaymentModuleInterface a payment module instance + * @throws \InvalidArgumentException if the module is not found or not a payment module + */ + public function getPaymentModuleInstance(ContainerInterface $container) + { + $instance = $this->getModuleInstance($container); + + if (! $instance instanceof PaymentModuleInterface) { + throw new \InvalidArgumentException(sprintf('Module "%s" is not a payment module', $this->getCode())); + } + + return $instance; + } + /** + * @return \Thelia\Module\BaseModule a new module instance. + */ + public function createInstance() + { + $moduleClass = new \ReflectionClass($this->getFullNamespace()); + + return $moduleClass->newInstance(); + } + + /** + * Calculate next position relative to module type + * + * @param ModuleQuery $query + */ + protected function addCriteriaToPositionQuery($query) + { + $query->filterByType($this->getType()); + } + + /** + * {@inheritDoc} + */ + public function preInsert(ConnectionInterface $con = null) + { + parent::preInsert($con); + + $this->setPosition($this->getNextPosition()); + + return true; + } +} diff --git a/core/lib/Thelia/Model/ModuleConfig.php b/core/lib/Thelia/Model/ModuleConfig.php new file mode 100644 index 00000000..25bfe5d8 --- /dev/null +++ b/core/lib/Thelia/Model/ModuleConfig.php @@ -0,0 +1,9 @@ +filterByModuleId($moduleId) + ->filterByName($variableName) + ->findOne(); + ; + + if (null !== $configValue) { + if (null !== $valueLocale) { + $configValue->setLocale($valueLocale); + } + + $value = $configValue->getValue(); + } + + return $value === null ? $defaultValue : $value; + } + + /** + * Set module configuration variable, creating it if required + * + * @param int $moduleId the module id + * @param string $variableName the variable name + * @param string $variableValue the variable value + * @param null $valueLocale the locale, or null if not required + * @param bool $createIfNotExists if true, the variable will be created if not already defined + * @throws \LogicException if variable does not exists and $createIfNotExists is false + * @return $this; + */ + public function setConfigValue($moduleId, $variableName, $variableValue, $valueLocale = null, $createIfNotExists = true) + { + $configValue = self::create() + ->filterByModuleId($moduleId) + ->filterByName($variableName) + ->findOne(); + ; + + if (null === $configValue) { + if (true === $createIfNotExists) { + $configValue = new ModuleConfig(); + + $configValue + ->setModuleId($moduleId) + ->setName($variableName) + ; + } else { + throw new \LogicException("Module configuration variable $variableName does not exists. Create it first."); + } + } + + if (null !== $valueLocale) { + $configValue->setLocale($valueLocale); + } + + $configValue + ->setValue($variableValue) + ->save(); + ; + + return $this; + } + + /** + * Delete a module's configuration variable + * + * @param int $moduleId the module id + * @param string $variableName the variable name + * @return $this; + */ + public function deleteConfigValue($moduleId, $variableName) + { + if (null !== $moduleConfig = self::create() + ->filterByModuleId($moduleId) + ->filterByName($variableName) + ->findOne() + ) { + $moduleConfig->delete(); + }; + + return $this; + } +} +// ModuleConfigQuery diff --git a/core/lib/Thelia/Model/ModuleHook.php b/core/lib/Thelia/Model/ModuleHook.php new file mode 100644 index 00000000..a4276bd7 --- /dev/null +++ b/core/lib/Thelia/Model/ModuleHook.php @@ -0,0 +1,22 @@ +filterByHookId($this->getHookId()); + } +} diff --git a/core/lib/Thelia/Model/ModuleHookQuery.php b/core/lib/Thelia/Model/ModuleHookQuery.php new file mode 100644 index 00000000..717a6768 --- /dev/null +++ b/core/lib/Thelia/Model/ModuleHookQuery.php @@ -0,0 +1,20 @@ +setModuleId($parentId); + + return $this; + } + + /** + * Get file parent id + * + * @return int parent id + */ + public function getParentId() + { + return $this->getModuleId(); + } + + /** + * @return FileModelParentInterface the parent file model + */ + public function getParentFileModel() + { + return new Module(); + } + + /** + * Get the ID of the form used to change this object information + * + * @return BaseForm the form + */ + public function getUpdateFormId() + { + return 'thelia.admin.module.image.modification'; + } + + /** + * @return string the path to the upload directory where files are stored, without final slash + */ + public function getUploadDir() + { + return THELIA_LOCAL_DIR . 'media' . DS . 'images' . DS . 'module'; + } + + /** + * @return string the URL to redirect to after update from the back-office + */ + public function getRedirectionUrl() + { + return '/admin/module/update/' . $this->getModuleId(); + } + + /** + * Get the Query instance for this object + * + * @return ModelCriteria + */ + public function getQueryInstance() + { + return ModuleImageQuery::create(); + } + + /** + * @inheritdoc + */ + public function getBreadcrumb(Router $router, ContainerInterface $container, $tab, $locale) + { + $translator = Translator::getInstance(); + + /** @var \Thelia\Model\Module */ + $module = $this->getModule(); + $breadcrumb = [ + $translator->trans('Home') => $router->generate('admin.home.view', [], Router::ABSOLUTE_URL), + $translator->trans('Module') => $router->generate('admin.module', [], Router::ABSOLUTE_URL), + ]; + + $module->setLocale($locale); + + $breadcrumb[$module->getTitle()] = sprintf( + "%s?current_tab=%s", + $router->generate( + 'admin.module.update', + ['module_id' => $module->getId()], + Router::ABSOLUTE_URL + ), + $tab + ); + + return $breadcrumb; + } +} diff --git a/core/lib/Thelia/Model/ModuleImageI18n.php b/core/lib/Thelia/Model/ModuleImageI18n.php new file mode 100644 index 00000000..8f9f5f95 --- /dev/null +++ b/core/lib/Thelia/Model/ModuleImageI18n.php @@ -0,0 +1,11 @@ +filterByActivate(BaseModule::IS_ACTIVATED) + ->orderByPosition() + ->find(); + } + + return self::$activated; + } + + public static function resetActivated() + { + self::$activated = null; + } + + /** + * @param int $moduleType the module type : classic, payment or delivery. Use BaseModule constant here. + * @param int $id the module id + * @return ModuleQuery + */ + public function filterActivatedByTypeAndId($moduleType, $id) + { + return $this + ->filterByType($moduleType) + ->filterByActivate(BaseModule::IS_ACTIVATED) + ->filterById($id); + } + + + /** + * + * if the container is provided, this method will found the module in the container. Reflection is used instead. + * If it's possible use it with the container. + * + * return false if no delivery modules are found, an array of BaseModule otherwise. + * + * @param ContainerInterface $container optional + * @return false|\Thelia\Module\BaseModule[] + */ + public function retrieveVirtualProductDelivery(ContainerInterface $container = null) + { + $modules = $this + ->filterByType(BaseModule::DELIVERY_MODULE_TYPE) + ->filterByActivate(BaseModule::IS_ACTIVATED) + ->find() + ; + + $result = []; + + /** @var \Thelia\Model\Module $module */ + foreach ($modules as $module) { + try { + if (null !== $container) { + $instance = $module->getDeliveryModuleInstance($container); + } else { + $instance = $module->createInstance(); + } + + if (true === $instance->handleVirtualProductDelivery()) { + $result[] = $instance; + } + } catch (\Exception $ex) { + Tlog::getInstance()->addError("Failed to instantiate module ".$module->getCode(), $ex); + } + } + + return empty($result) ? false : $result; + } +} +// ModuleQuery diff --git a/core/lib/Thelia/Model/Newsletter.php b/core/lib/Thelia/Model/Newsletter.php new file mode 100644 index 00000000..1641ee7f --- /dev/null +++ b/core/lib/Thelia/Model/Newsletter.php @@ -0,0 +1,9 @@ +choosenDeliveryAddress = $choosenDeliveryAddress; + + return $this; + } + + /** + * @param boolean $disableVersioning + * @return $this + */ + public function setDisableVersioning($disableVersioning) + { + $this->disableVersioning = (bool) $disableVersioning; + + return $this; + } + + public function isVersioningDisable() + { + return $this->disableVersioning; + } + + public function isVersioningNecessary($con = null) + { + if ($this->isVersioningDisable()) { + return false; + } else { + return parent::isVersioningNecessary($con); + } + } + + /** + * @return int|null the choosen delivery address ID + */ + public function getChoosenDeliveryAddress() + { + return $this->choosenDeliveryAddress; + } + + /** + * @param int $choosenInvoiceAddress the choosen invoice address + * @return $this + */ + public function setChoosenInvoiceAddress($choosenInvoiceAddress) + { + $this->choosenInvoiceAddress = $choosenInvoiceAddress; + + return $this; + } + + /** + * @return int|null the choosen invoice address ID + */ + public function getChoosenInvoiceAddress() + { + return $this->choosenInvoiceAddress; + } + + /** + * {@inheritDoc} + * @throws \Propel\Runtime\Exception\PropelException + */ + public function preSave(ConnectionInterface $con = null) + { + if ($this->isPaid(false) && null === $this->getInvoiceDate()) { + $this + ->setInvoiceDate(time()); + } + + return parent::preSave($con); + } + + /** + * {@inheritDoc} + */ + public function preInsert(ConnectionInterface $con = null) + { + parent::preInsert($con); + + $this->dispatchEvent(TheliaEvents::ORDER_BEFORE_CREATE, new OrderEvent($this)); + + return true; + } + + /** + * @param ConnectionInterface|null $con + * @throws \Propel\Runtime\Exception\PropelException + */ + public function postInsert(ConnectionInterface $con = null) + { + parent::postInsert($con); + + $this->setRef($this->generateRef()) + ->setDisableVersioning(true) + ->save($con); + $this->dispatchEvent(TheliaEvents::ORDER_AFTER_CREATE, new OrderEvent($this)); + } + + public function generateRef() + { + return sprintf('ORD%s', str_pad($this->getId(), 12, 0, STR_PAD_LEFT)); + } + + /** + * Compute this order amount with taxes. The tax amount is returned in the $tax parameter. + * + * The order amount is only available once the order is persisted in database. + * During invoice process, use all cart methods instead of order methods (the order doest not exists at this moment) + * + * @param float|int $tax (output only) returns the tax amount for this order + * @param bool $includePostage if true, the postage cost is included to the total + * @param bool $includeDiscount if true, the discount will be included to the total + * @return float + * @throws \Propel\Runtime\Exception\PropelException + */ + public function getTotalAmount(&$tax = 0, $includePostage = true, $includeDiscount = true) + { + // To prevent price changes in pre-2.4 orders, use the legacy calculation method + if ($this->getId() <= ConfigQuery::read('last_legacy_rounding_order_id', 0)) { + return $this->getTotalAmountLegacy($tax, $includePostage, $includeDiscount); + } + + // Cache the query result. Wa have to une and array indexed on the order ID, as the cache ios static + // and may cache results for several orders, for example in the order list in the back-office. + static $queryResult = []; + + $id = $this->getId(); + + if (!isset($queryResult[$id]) || null === $queryResult[$id]) { + // Shoud be the same rounding method as in CartItem::getTotalTaxedPrice() + // For each order line, we round quantity x taxed price. + $query = ' + SELECT + SUM( + '.OrderProductTableMap::COL_QUANTITY.' + * + ROUND( + ( + IF('.OrderProductTableMap::COL_WAS_IN_PROMO.'=1, '.OrderProductTableMap::COL_PROMO_PRICE.', '.OrderProductTableMap::COL_PRICE.') + + + ( + SELECT COALESCE(SUM(IF('.OrderProductTableMap::COL_WAS_IN_PROMO.'=1, '.OrderProductTaxTableMap::COL_PROMO_AMOUNT.', '.OrderProductTaxTableMap::COL_AMOUNT.')), 0) + FROM '.OrderProductTaxTableMap::TABLE_NAME.' + WHERE '.OrderProductTaxTableMap::COL_ORDER_PRODUCT_ID.' = '.OrderProductTableMap::COL_ID.' + ) + ), 2 + ) + ) as total_taxed_price, + SUM( + '.OrderProductTableMap::COL_QUANTITY.' + * + ROUND( + IF( + '.OrderProductTableMap::COL_WAS_IN_PROMO.'=1, + '.OrderProductTableMap::COL_PROMO_PRICE.', + '.OrderProductTableMap::COL_PRICE.' + ), 2 + ) + ) as total_untaxed_price + from + '.OrderProductTableMap::TABLE_NAME.' + where + '.OrderProductTableMap::COL_ORDER_ID.'=:order_id + '; + + $con = Propel::getConnection(); + $stmt = $con->prepare($query); + + if (false === $stmt->execute([':order_id' => $this->getId()])) { + throw new TheliaProcessException( + sprintf( + 'Failed to get order total and order tax: %s (%s)', + $stmt->errorInfo(), + $stmt->errorCode() + ) + ); + } + + $queryResult[$id] = $stmt->fetch(\PDO::FETCH_OBJ); + } + + $total = (float) $queryResult[$id]->total_taxed_price; + $tax = $total - (float) $queryResult[$id]->total_untaxed_price; + + if (true === $includeDiscount) { + $total -= $this->getDiscount(); + $tax -= $this->getDiscount() - Calculator::getUntaxedOrderDiscount($this); + + if ($total < 0) { + $total = 0; + } + + if ($tax < 0) { + $tax = 0; + } + } + + if (false !== $includePostage) { + $total += (float)$this->getPostage(); + $tax += (float)$this->getPostageTax(); + } + + return $total; + } + + /** + * This is thge legacy way of computing this order amount with taxes. The tax amount is returned in the $tax parameter. + * + * The order amount is only available once the order is persisted in database. + * During invoice process, use all cart methods instead of order methods (the order doest not exists at this moment) + * + * @param float|int $tax (output only) returns the tax amount for this order + * @param bool $includePostage if true, the postage cost is included to the total + * @param bool $includeDiscount if true, the discount will be included to the total + * @return float + * @throws \Propel\Runtime\Exception\PropelException + */ + public function getTotalAmountLegacy(&$tax = 0, $includePostage = true, $includeDiscount = true) + { + $amount = (float)OrderProductQuery::create() + ->filterByOrderId($this->getId()) + ->withColumn('SUM( + ' . OrderProductTableMap::COL_QUANTITY . ' + * IF(' . OrderProductTableMap::COL_WAS_IN_PROMO . ' = 1, ' . OrderProductTableMap::COL_PROMO_PRICE . ', ' . OrderProductTableMap::COL_PRICE . ') + )', 'total_amount') + ->select(['total_amount']) + ->findOne(); + + $tax = (float)OrderProductTaxQuery::create() + ->useOrderProductQuery() + ->filterByOrderId($this->getId()) + ->endUse() + ->withColumn('SUM( + ' . OrderProductTableMap::COL_QUANTITY . ' + * IF(' . OrderProductTableMap::COL_WAS_IN_PROMO . ' = 1, ' . OrderProductTaxTableMap::COL_PROMO_AMOUNT . ', ' . OrderProductTaxTableMap::COL_AMOUNT . ') + )', 'total_tax') + ->select(['total_tax']) + ->findOne(); + + $total = $amount + $tax; + + // @todo : manage discount : free postage ? + if (true === $includeDiscount) { + $total -= $this->getDiscount(); + + if ($total < 0) { + $total = 0; + } + } + + if (false !== $includePostage) { + $total += \floatval($this->getPostage()); + $tax += \floatval($this->getPostageTax()); + } + + return $total; + } + + /** + * Compute this order weight. + * + * The order weight is only available once the order is persisted in database. + * During invoice process, use all cart methods instead of order methods (the order doest not exists at this moment) + * + * @return float + * @throws \Propel\Runtime\Exception\PropelException + */ + public function getWeight() + { + $weight = 0; + + /* browse all products */ + foreach ($this->getOrderProducts() as $orderProduct) { + $weight += $orderProduct->getQuantity() * (double)$orderProduct->getWeight(); + } + + return $weight; + } + + /** + * Return the postage without tax + * @return float|int + */ + public function getUntaxedPostage() + { + if (0 < $this->getPostageTax()) { + $untaxedPostage = $this->getPostage() - $this->getPostageTax(); + } else { + $untaxedPostage = $this->getPostage(); + } + + return $untaxedPostage; + } + + /** + * Check if the current order contains at less 1 virtual product with a file to download + * + * @return bool true if this order have at less 1 file to download, false otherwise. + */ + public function hasVirtualProduct() + { + $virtualProductCount = OrderProductQuery::create() + ->filterByOrderId($this->getId()) + ->filterByVirtual(1, Criteria::EQUAL) + ->count() + ; + + return ($virtualProductCount !== 0); + } + + /** + * Set the status of the current order to NOT PAID + * @throws \Propel\Runtime\Exception\PropelException + */ + public function setNotPaid() + { + $this->setStatusHelper(OrderStatus::CODE_NOT_PAID); + } + + /** + * Check if the current status of this order is NOT PAID + * + * @param bool $exact if true, the status should be the exact required status, not a derived one. + * @return bool true if this order is NOT PAID, false otherwise. + * @throws \Propel\Runtime\Exception\PropelException + */ + public function isNotPaid($exact = true) + { + return $this->getOrderStatus()->isNotPaid($exact); + } + + /** + * Set the status of the current order to PAID + * @throws \Propel\Runtime\Exception\PropelException + */ + public function setPaid() + { + $this->setStatusHelper(OrderStatus::CODE_PAID); + } + + /** + * Check if the current status of this order is PAID + * + * @param bool $exact if true, the status should be the exact required status, not a derived one. + * @return bool true if this order is PAID, false otherwise. + * @throws \Propel\Runtime\Exception\PropelException + */ + public function isPaid($exact = true) + { + return $this->getOrderStatus()->isPaid($exact); + } + + /** + * Set the status of the current order to PROCESSING + * @throws \Propel\Runtime\Exception\PropelException + */ + public function setProcessing() + { + $this->setStatusHelper(OrderStatus::CODE_PROCESSING); + } + + /** + * Check if the current status of this order is PROCESSING + * + * @param bool $exact if true, the status should be the exact required status, not a derived one. + * @return bool true if this order is PROCESSING, false otherwise. + * @throws \Propel\Runtime\Exception\PropelException + */ + public function isProcessing($exact = true) + { + return $this->getOrderStatus()->isProcessing($exact); + } + + /** + * Set the status of the current order to SENT + * @throws \Propel\Runtime\Exception\PropelException + */ + public function setSent() + { + $this->setStatusHelper(OrderStatus::CODE_SENT); + } + + /** + * Check if the current status of this order is SENT + * + * @param bool $exact if true, the status should be the exact required status, not a derived one. + * @return bool true if this order is SENT, false otherwise. + * @throws \Propel\Runtime\Exception\PropelException + */ + public function isSent($exact = true) + { + return $this->getOrderStatus()->isSent($exact); + } + + /** + * Set the status of the current order to CANCELED + * @throws \Propel\Runtime\Exception\PropelException + */ + public function setCancelled() + { + $this->setStatusHelper(OrderStatus::CODE_CANCELED); + } + + /** + * Check if the current status of this order is CANCELED + * + * @param bool $exact if true, the status should be the exact required status, not a derived one. + * @return bool true if this order is CANCELED, false otherwise. + * @throws \Propel\Runtime\Exception\PropelException + */ + public function isCancelled($exact = true) + { + return $this->getOrderStatus()->isCancelled($exact); + } + + /** + * Set the status of the current order to REFUNDED + * @throws \Propel\Runtime\Exception\PropelException + */ + public function setRefunded() + { + $this->setStatusHelper(OrderStatus::CODE_REFUNDED); + } + + /** + * Check if the current status of this order is REFUNDED + * + * @param bool $exact if true, the status should be the exact required status, not a derived one. + * @return bool true if this order is REFUNDED, false otherwise. + * @throws \Propel\Runtime\Exception\PropelException + */ + public function isRefunded($exact = true) + { + return $this->getOrderStatus()->isRefunded($exact); + } + + /** + * Set the status of the current order to the provided status + * + * @param string $statusCode the status code, one of OrderStatus::CODE_xxx constants. + * @throws \Propel\Runtime\Exception\PropelException + */ + public function setStatusHelper($statusCode) + { + if (null !== $ordeStatus = OrderStatusQuery::create()->findOneByCode($statusCode)) { + $this->setOrderStatus($ordeStatus)->save(); + } + } + + /** + * Get an instance of the payment module + * + * @return \Thelia\Module\PaymentModuleInterface + * @throws TheliaProcessException + */ + public function getPaymentModuleInstance() + { + if (null === $paymentModule = ModuleQuery::create()->findPk($this->getPaymentModuleId())) { + throw new TheliaProcessException("Payment module ID=" . $this->getPaymentModuleId() . " was not found."); + } + + return $paymentModule->createInstance(); + } + + /** + * Get an instance of the delivery module + * + * @return \Thelia\Module\BaseModuleInterface + * @throws TheliaProcessException + */ + public function getDeliveryModuleInstance() + { + if (null === $deliveryModule = ModuleQuery::create()->findPk($this->getDeliveryModuleId())) { + throw new TheliaProcessException("Delivery module ID=" . $this->getDeliveryModuleId() . " was not found."); + } + + return $deliveryModule->createInstance(); + } + + /** + * Check if stock was decreased at stock creation for this order. + * TODO : we definitely have to store modules in an order_modules table juste like order_product and other order related information. + * + * @param EventDispatcherInterface $dispatcher + * @return bool true if the stock was decreased at order creation, false otherwise + */ + public function isStockManagedOnOrderCreation(EventDispatcherInterface $dispatcher) + { + $paymentModule = $this->getPaymentModuleInstance(); + + $event = new ManageStockOnCreationEvent($paymentModule); + + $dispatcher->dispatch( + TheliaEvents::getModuleEvent( + TheliaEvents::MODULE_PAYMENT_MANAGE_STOCK, + $paymentModule->getCode() + ), + $event + ); + + return (null !== $event->getManageStock()) + ? $event->getManageStock() + : $paymentModule->manageStockOnCreation(); + } +} diff --git a/core/lib/Thelia/Model/OrderAddress.php b/core/lib/Thelia/Model/OrderAddress.php new file mode 100644 index 00000000..75565a71 --- /dev/null +++ b/core/lib/Thelia/Model/OrderAddress.php @@ -0,0 +1,9 @@ +filterByOrderCoupon($this)->find(); + } + + /** + * Return the modules for which free shipping is valid + * + * @return array|mixed|\Propel\Runtime\Collection\ObjectCollection + */ + public function getFreeShippingForModules() + { + return OrderCouponModuleQuery::create()->filterByOrderCoupon($this)->find(); + } +} diff --git a/core/lib/Thelia/Model/OrderCouponCountry.php b/core/lib/Thelia/Model/OrderCouponCountry.php new file mode 100644 index 00000000..0d19bbdc --- /dev/null +++ b/core/lib/Thelia/Model/OrderCouponCountry.php @@ -0,0 +1,9 @@ + + */ +class OrderPostage +{ + /** @var float */ + protected $amount; + + /** @var float */ + protected $amountTax; + + /** @var string */ + protected $taxRuleTitle; + + public function __construct($amount = 0.0, $amountTax = 0.0, $taxRuleTitle = '') + { + $this->amount = $amount; + $this->amountTax = $amountTax; + $this->taxRuleTitle = $taxRuleTitle; + } + + /** + * Convert a amount or OrderPostage object to an OrderPostage object + * + * @param OrderPostage|float $postage + * @return OrderPostage + */ + public static function loadFromPostage($postage) + { + if ($postage instanceof OrderPostage) { + $orderPostage = $postage; + } else { + $orderPostage = new OrderPostage($postage); + } + + return $orderPostage; + } + + /** + * @return float + */ + public function getAmount() + { + return $this->amount; + } + + /** + * @param float $amount + */ + public function setAmount($amount) + { + $this->amount = $amount; + } + + /** + * @return float + */ + public function getAmountTax() + { + return $this->amountTax; + } + + /** + * @param float $amountTax + */ + public function setAmountTax($amountTax) + { + // We have to round the postage tax to prevent small delta amounts in tax calculations. + $this->amountTax = round($amountTax, 2); + } + + /** + * @return string + */ + public function getTaxRuleTitle() + { + return $this->taxRuleTitle; + } + + /** + * @param string $taxRuleTitle + */ + public function setTaxRuleTitle($taxRuleTitle) + { + $this->taxRuleTitle = $taxRuleTitle; + } +} diff --git a/core/lib/Thelia/Model/OrderProduct.php b/core/lib/Thelia/Model/OrderProduct.php new file mode 100644 index 00000000..00293bea --- /dev/null +++ b/core/lib/Thelia/Model/OrderProduct.php @@ -0,0 +1,65 @@ +cartItemId = $cartItemId; + + return $this; + } + + /** + * @return mixed + */ + public function getCartItemId() + { + return $this->cartItemId; + } + + /** + * {@inheritDoc} + */ + public function preInsert(ConnectionInterface $con = null) + { + parent::preInsert($con); + + $this->dispatchEvent( + TheliaEvents::ORDER_PRODUCT_BEFORE_CREATE, + (new OrderProductEvent($this->getOrder(), null)) + ->setCartItemId($this->cartItemId) + ); + + return true; + } + + /** + * {@inheritDoc} + */ + public function postInsert(ConnectionInterface $con = null) + { + parent::postInsert($con); + + $this->dispatchEvent( + TheliaEvents::ORDER_PRODUCT_AFTER_CREATE, + (new OrderProductEvent($this->getOrder(), $this->getId())) + ->setCartItemId($this->cartItemId) + ); + } +} diff --git a/core/lib/Thelia/Model/OrderProductAttributeCombination.php b/core/lib/Thelia/Model/OrderProductAttributeCombination.php new file mode 100644 index 00000000..1e87cf7d --- /dev/null +++ b/core/lib/Thelia/Model/OrderProductAttributeCombination.php @@ -0,0 +1,9 @@ + 0) { + $subQuery = $query->useOrderQuery(); + + if (null !== $customerId) { + $subQuery->filterByCustomerId($customerId); + } + + if (null !== $startDate) { + $subQuery->filterByCreatedAt( + sprintf("%s 00:00:00", $startDate->format('Y-m-d')), + Criteria::GREATER_EQUAL + ); + } + + if (null !== $startDate) { + $subQuery->filterByCreatedAt( + sprintf("%s 23:59:59", $endDate->format('Y-m-d')), + Criteria::LESS_EQUAL + ); + } + + if (\count($orderStatusIdList) > 0) { + $subQuery->filterByStatusId($orderStatusIdList, Criteria::IN); + } + + $subQuery->endUse(); + } + + $query + ->filterByProductRef($productRef) + ->withColumn("SUM(`order_product`.QUANTITY)", 'TOTAL') + ->select('TOTAL') + ; + + $count = $query->findOne(); + + return null === $count ? 0 : $count; + } +} +// OrderProductQuery diff --git a/core/lib/Thelia/Model/OrderProductTax.php b/core/lib/Thelia/Model/OrderProductTax.php new file mode 100644 index 00000000..9cac9ca4 --- /dev/null +++ b/core/lib/Thelia/Model/OrderProductTax.php @@ -0,0 +1,9 @@ +filterByInvoiceDate(sprintf("%s-%s-%s 00:00:00", $year, $month, $day), Criteria::GREATER_EQUAL) + ->filterByInvoiceDate(sprintf("%s-%s-%s 23:59:59", $year, $month, $day), Criteria::LESS_EQUAL); + if (null !== $status) { + $dayOrdersQuery->filterByStatusId($status, Criteria::IN); + } + $dayOrders = $dayOrdersQuery->count(); + $stats[] = array($day-1, $dayOrders); + } + + return $stats; + } + + /** + * @param $month + * @param $year + * @return array + * @throws \Propel\Runtime\Exception\PropelException + */ + public static function getFirstOrdersStats($month, $year) + { + $numberOfDay = cal_days_in_month(CAL_GREGORIAN, $month, $year); + + $stats = array(); + for ($day=1; $day<=$numberOfDay; $day++) { + $dayOrdersQuery = self::create() + ->filterByCreatedAt(sprintf("%s-%s-%s 00:00:00", $year, $month, $day), Criteria::GREATER_EQUAL) + ->filterByCreatedAt(sprintf("%s-%s-%s 23:59:59", $year, $month, $day), Criteria::LESS_EQUAL); + + $otherOrderJoin = new Join(); + $otherOrderJoin->addExplicitCondition(OrderTableMap::TABLE_NAME, 'CUSTOMER_ID', null, OrderTableMap::TABLE_NAME, 'CUSTOMER_ID', 'other_order'); + $otherOrderJoin->setJoinType(Criteria::LEFT_JOIN); + + $dayOrdersQuery->addJoinObject($otherOrderJoin, 'other_order_join') + ->addJoinCondition('other_order_join', '`order`.`ID` <> `other_order`.`ID`') + ->addJoinCondition('other_order_join', '`order`.`CREATED_AT` > `other_order`.`CREATED_AT`'); + + $dayOrdersQuery->where('ISNULL(`other_order`.`ID`)'); + + $dayOrders = $dayOrdersQuery->count(); + $stats[] = array($day-1, $dayOrders); + } + + return $stats; + } + + /** + * @param \DateTime $startDate + * @param \DateTime $endDate + * @param bool $includeShipping + * @param bool $withTaxes + * + * @return float|int + * @throws \Propel\Runtime\Exception\PropelException + */ + public static function getSaleStats(\DateTime $startDate, \DateTime $endDate, $includeShipping, $withTaxes = true) + { + $amount = floatval( + self::baseSaleStats($startDate, $endDate, 'o') + ->innerJoinOrderProduct() + ->withColumn("SUM((`order_product`.QUANTITY * IF(`order_product`.WAS_IN_PROMO,`order_product`.PROMO_PRICE,`order_product`.PRICE)))", 'TOTAL') + ->select(['TOTAL']) + ->findOne() + ); + + if ($withTaxes) { + $amount += floatval( + self::baseSaleStats($startDate, $endDate, 'o') + ->useOrderProductQuery() + ->useOrderProductTaxQuery() + ->withColumn("SUM((`order_product`.QUANTITY * IF(`order_product`.WAS_IN_PROMO,`order_product_tax`.PROMO_AMOUNT,`order_product_tax`.AMOUNT)))", 'TAX') + ->endUse() + ->endUse() + ->select(['TAX']) + ->findOne() + ); + } + + $amount -= floatval( + self::baseSaleStats($startDate, $endDate) + ->withColumn("SUM(`order`.discount)", 'DISCOUNT') + ->select('DISCOUNT') + ->findOne() + ); + + if ($includeShipping) { + $amount += floatval( + self::baseSaleStats($startDate, $endDate) + ->withColumn("SUM(`order`.postage)", 'POSTAGE') + ->select('POSTAGE') + ->findOne() + ); + } + + return $amount; + } + + /** + * @param \DateTime $startDate + * @param \DateTime $endDate + * @param string $modelAlias + * @return OrderQuery + */ + protected static function baseSaleStats(\DateTime $startDate, \DateTime $endDate, $modelAlias = null) + { + // The sales are considered at invoice date, not order creation date + return self::create($modelAlias) + ->filterByInvoiceDate(sprintf("%s 00:00:00", $startDate->format('Y-m-d')), Criteria::GREATER_EQUAL) + ->filterByInvoiceDate(sprintf("%s 23:59:59", $endDate->format('Y-m-d')), Criteria::LESS_EQUAL) + ->filterByStatusId(OrderStatusQuery::getPaidStatusIdList(), Criteria::IN); + } + + + /** + * @param \DateTime $startDate + * @param \DateTime $endDate + * @param int[] $status + * + * @return int + */ + public static function getOrderStats(\DateTime $startDate, \DateTime $endDate, $status = null) + { + if ($status === null) { + $status = OrderStatusQuery::getPaidStatusIdList(); + } + + return self::create() + ->filterByStatusId($status, Criteria::IN) + ->filterByCreatedAt(sprintf("%s 00:00:00", $startDate->format('Y-m-d')), Criteria::GREATER_EQUAL) + ->filterByCreatedAt(sprintf("%s 23:59:59", $endDate->format('Y-m-d')), Criteria::LESS_EQUAL) + ->count(); + } +} +// OrderQuery diff --git a/core/lib/Thelia/Model/OrderStatus.php b/core/lib/Thelia/Model/OrderStatus.php new file mode 100644 index 00000000..e0d90283 --- /dev/null +++ b/core/lib/Thelia/Model/OrderStatus.php @@ -0,0 +1,123 @@ +hasStatusHelper(OrderStatus::CODE_NOT_PAID); + if ($exact) { + return $this->hasStatusHelper(OrderStatus::CODE_NOT_PAID); + } else { + return ! $this->isPaid(false); + } + } + + /** + * Check if the current status is PAID + * + * @param bool $exact if true, the method will check if the current status is exactly OrderStatus::CODE_PAID. + * if false, it will check if the order has been paid, whatever the exact status is. The default is true. + * + * @return bool true if PAID, false otherwise. + */ + public function isPaid($exact = true) + { + return $this->hasStatusHelper( + $exact ? + OrderStatus::CODE_PAID : + [ OrderStatus::CODE_PAID, OrderStatus::CODE_PROCESSING, OrderStatus::CODE_SENT ] + ); + } + + /** + * Check if the current status is PROCESSING + * + * @param bool $exact if true, the method will check if the current status is exactly OrderStatus::CODE_PROCESSING. + * if false, it will check if the order is processing, whatever the exact status is. The default is true. + * + * @return bool true if PROCESSING, false otherwise. + */ + public function isProcessing($exact = true) + { + return $this->hasStatusHelper(OrderStatus::CODE_PROCESSING); + } + + /** + * Check if the current status is SENT + * + * @param bool $exact if true, the method will check if the current status is exactly OrderStatus::CODE_SENT. + * if false, it will check if the order is send, whatever the exact status is. The default is true. + * + * @return bool true if SENT, false otherwise. + */ + public function isSent($exact = true) + { + return $this->hasStatusHelper(OrderStatus::CODE_SENT); + } + + /** + * Check if the current status is CANCELED + * + * @param bool $exact if true, the method will check if the current status is exactly OrderStatus::CODE_CANCELED. + * if false, it will check if the order is canceled, whatever the exact status is. The default is true. + * + * @return bool true if CANCELED, false otherwise. + */ + public function isCancelled($exact = true) + { + return $this->hasStatusHelper(OrderStatus::CODE_CANCELED); + } + + /** + * Check if the current status is REFUNDED + * + * @param bool $exact if true, the method will check if the current status is exactly OrderStatus::CODE_CANCELED. + * if false, it will check if the order is canceled, whatever the exact status is. The default is true. + * + * @return bool true if REFUNDED, false otherwise. + */ + public function isRefunded($exact = true) + { + return $this->hasStatusHelper(OrderStatus::CODE_REFUNDED); + } + + /** + * Check if the current status is $statusCode or, if $statusCode is an array, if the current + * status is in the $statusCode array. + * + * @param string|array $statusCode the status code, one of OrderStatus::CODE_xxx constants. + * @return bool true if the current status is in the provided status, false otherwise. + */ + public function hasStatusHelper($statusCode) + { + if (\is_array($statusCode)) { + return \in_array($this->getCode(), $statusCode); + } else { + return $this->getCode() == $statusCode; + } + } +} diff --git a/core/lib/Thelia/Model/OrderStatusI18n.php b/core/lib/Thelia/Model/OrderStatusI18n.php new file mode 100644 index 00000000..110d80af --- /dev/null +++ b/core/lib/Thelia/Model/OrderStatusI18n.php @@ -0,0 +1,11 @@ +findOneByCode($statusCode); + } + + return self::$statusModelCache[$statusCode]; + } + + /** + * Return the list of order status IDs for which an order is considered as not paid + * + * @return array + */ + public static function getNotPaidStatusIdList() + { + return self::getStatusIdList(OrderStatus::CODE_NOT_PAID); + } + + /** + * Return the list of order status IDs for which an order is considered as paid + * + * @return array + */ + public static function getPaidStatusIdList() + { + return self::getStatusIdList(OrderStatus::CODE_PAID); + } + + /** + * Return the list of order status IDs for which an order is considered as in process + * + * @return array + */ + public static function getProcessingStatusIdList() + { + return self::getStatusIdList(OrderStatus::CODE_PROCESSING); + } + + /** + * Return the list of order status IDs for which an order is considered as sent + * + * @return array + */ + public static function getSentStatusIdList() + { + return self::getStatusIdList(OrderStatus::CODE_SENT); + } + + /** + * Return the list of order status IDs for which an order is considered as canceled + * + * @return array + */ + public static function getCanceledStatusIdList() + { + return self::getStatusIdList(OrderStatus::CODE_CANCELED); + } + + /** + * Return the list of order status IDs for which an order is considered as refunded + * + * @return array + */ + public static function getRefundedStatusIdList() + { + return self::getStatusIdList(OrderStatus::CODE_REFUNDED); + } + + /** + * Return a list of status IDs which match $statusCode value. + * + * @param string $statusCode the satus code + * @return array + */ + public static function getStatusIdList($statusCode) + { + if (! isset(self::$statusIdListsCache[$statusCode])) { + $statusIdList = []; + + $statusList = OrderStatusQuery::create()->find(); + + /** @var OrderStatus $status */ + foreach ($statusList as $status) { + switch ($statusCode) { + case OrderStatus::CODE_NOT_PAID: + $match = $status->isNotPaid(false); + break; + case OrderStatus::CODE_PAID: + $match = $status->isPaid(false); + break; + + case OrderStatus::CODE_PROCESSING: + $match = $status->isProcessing(false); + break; + + case OrderStatus::CODE_SENT: + $match = $status->isSent(false); + break; + case OrderStatus::CODE_CANCELED: + $match = $status->isCancelled(false); + break; + case OrderStatus::CODE_REFUNDED: + $match = $status->isRefunded(false); + break; + + default: + throw new InvalidArgumentException("Status code '$statusCode' is not a valid value."); + } + + if ($match) { + $statusIdList[] = $status->getId(); + } + } + + self::$statusIdListsCache[$statusCode] = $statusIdList; + } + + return self::$statusIdListsCache[$statusCode]; + } +} +// OrderStatusQuery diff --git a/core/lib/Thelia/Model/OrderVersion.php b/core/lib/Thelia/Model/OrderVersion.php new file mode 100644 index 00000000..ccbf01e6 --- /dev/null +++ b/core/lib/Thelia/Model/OrderVersion.php @@ -0,0 +1,9 @@ + null, + self::TUESDAY_OPENING_HOURS_KEY => null, + self::WEDNESDAY_OPENING_HOURS_KEY => null, + self::THURSDAY_OPENING_HOURS_KEY => null, + self::FRIDAY_OPENING_HOURS_KEY => null, + self::SATURDAY_OPENING_HOURS_KEY => null, + self::SUNDAY_OPENING_HOURS_KEY => null + ]; + + /** + * @var PickupLocationAddress + */ + protected $address = null; + + public function __construct() { + $this->serializer = new Serializer([new ObjectNormalizer()], [new JsonEncoder()]); + } + + /** + * @return string + */ + public function getId() + { + return $this->id; + } + + /** + * @param string $id + * @return PickupLocation + */ + public function setId($id) + { + $this->id = $id; + return $this; + } + + /** @return float */ + public function getLatitude() + { + return $this->latitude; + } + + /** @param float + * @return $this + * */ + public function setLatitude($latitude) + { + $this->latitude = $latitude; + return $this; + } + + /** @return float */ + public function getLongitude() + { + return $this->longitude; + } + + /** @param float + * @return $this|PickupLocation + * */ + public function setLongitude($longitude) + { + $this->longitude = $longitude; + return $this; + } + + /** @return string */ + public function getTitle() + { + return $this->title; + } + + /** @param string + * @return $this|PickupLocation + * */ + public function setTitle($title) + { + $this->title = $title; + return $this; + } + + /** + * @return PickupLocationAddress + */ + public function getAddress() + { + return $this->address; + } + + /** + * @param PickupLocationAddress $address + * + * @return PickupLocation + */ + public function setAddress($address) + { + $this->address = $address; + return $this; + } + + /** + * @return int + */ + public function getModuleId() + { + return $this->moduleId; + } + + /** + * @param int $moduleId + * @return PickupLocation + */ + public function setModuleId($moduleId) + { + $this->moduleId = $moduleId; + + return $this; + } + + /** + * @return array + */ + public function getOpeningHours() + { + return $this->openingHours; + } + + /** + * @param integer $day + * @param string $hours + * + * @return $this + * @throws \Exception + */ + public function setOpeningHours($day, $hours) + { + if (!array_key_exists($day, $this->openingHours)) { + throw new \Exception(Translator::getInstance()->trans('Tried to set the opening hours for a non existant day in the array. Please use the constants defined in the PickupLocation class.')); + } + + $this->openingHours[$day] = $hours; + + return $this; + } + + /** + * @return array + * */ + public function toArray() { + return json_decode($this->serializer->serialize($this, 'json'), true); + } +} diff --git a/core/lib/Thelia/Model/PickupLocationAddress.php b/core/lib/Thelia/Model/PickupLocationAddress.php new file mode 100644 index 00000000..031b9005 --- /dev/null +++ b/core/lib/Thelia/Model/PickupLocationAddress.php @@ -0,0 +1,358 @@ +id; + } + + /** + * @param int $id + * + * @return PickupLocationAddress + */ + public function setId($id) + { + $this->id = $id; + return $this; + } + + /** + * @return bool + */ + public function isDefault() + { + return $this->isDefault; + } + + /** + * @param bool $isDefault + * + * @return PickupLocationAddress + */ + public function setIsDefault($isDefault) + { + $this->isDefault = $isDefault; + return $this; + } + + /** + * @return string + */ + public function getLabel() + { + return $this->label; + } + + /** + * @param string $label + * + * @return PickupLocationAddress + */ + public function setLabel($label) + { + $this->label = $label; + return $this; + } + + /** + * @return string + */ + public function getTitle() + { + return $this->title; + } + + /** + * @param string $title + * + * @return PickupLocationAddress + */ + public function setTitle($title) + { + $this->title = $title; + return $this; + } + + /** + * @return string + */ + public function getFirstName() + { + return $this->firstName; + } + + /** + * @param string $firstName + * + * @return PickupLocationAddress + */ + public function setFirstName($firstName) + { + $this->firstName = $firstName; + return $this; + } + + /** + * @return string + */ + public function getLastName() + { + return $this->lastName; + } + + /** + * @param string $lastName + * + * @return PickupLocationAddress + */ + public function setLastName($lastName) + { + $this->lastName = $lastName; + return $this; + } + + /** + * @return string + */ + public function getCellphoneNumber() + { + return $this->cellphoneNumber; + } + + /** + * @param string $cellphoneNumber + * + * @return PickupLocationAddress + */ + public function setCellphoneNumber($cellphoneNumber) + { + $this->cellphoneNumber = $cellphoneNumber; + return $this; + } + + /** + * @return string + */ + public function getPhoneNumber() + { + return $this->phoneNumber; + } + + /** + * @param string $phoneNumber + * + * @return PickupLocationAddress + */ + public function setPhoneNumber($phoneNumber) + { + $this->phoneNumber = $phoneNumber; + return $this; + } + + /** + * @return string + */ + public function getCompany() + { + return $this->company; + } + + /** + * @param string $company + * + * @return PickupLocationAddress + */ + public function setCompany($company) + { + $this->company = $company; + return $this; + } + + /** + * @return string + */ + public function getAddress1() + { + return $this->address1; + } + + /** + * @param string $address1 + * + * @return PickupLocationAddress + */ + public function setAddress1($address1) + { + $this->address1 = $address1; + return $this; + } + + /** + * @return string + */ + public function getAddress2() + { + return $this->address2; + } + + /** + * @param string $address2 + * + * @return PickupLocationAddress + */ + public function setAddress2($address2) + { + $this->address2 = $address2; + return $this; + } + + /** + * @return string + */ + public function getAddress3() + { + return $this->address3; + } + + /** + * @param string $address3 + * + * @return PickupLocationAddress + */ + public function setAddress3($address3) + { + $this->address3 = $address3; + return $this; + } + + /** + * @return string + */ + public function getZipCode() + { + return $this->zipCode; + } + + /** + * @param string $zipCode + * + * @return PickupLocationAddress + */ + public function setZipCode($zipCode) + { + $this->zipCode = $zipCode; + return $this; + } + + /** + * @return string + */ + public function getCity() + { + return $this->city; + } + + /** + * @param string $city + * + * @return PickupLocationAddress + */ + public function setCity($city) + { + $this->city = $city; + return $this; + } + + /** + * @return string + */ + public function getCountryCode() + { + return $this->countryCode; + } + + /** + * @param string $countryCode + * + * @return PickupLocationAddress + */ + public function setCountryCode($countryCode) + { + $this->countryCode = $countryCode; + return $this; + } + + /** + * @return array + */ + public function getAdditionalData() + { + return $this->additionalData; + } + + /** + * @param array $additionalData + * + * @return PickupLocationAddress + */ + public function setAdditionalData($additionalData) + { + $this->additionalData = $additionalData; + return $this; + } +} \ No newline at end of file diff --git a/core/lib/Thelia/Model/Product.php b/core/lib/Thelia/Model/Product.php new file mode 100644 index 00000000..96f68a05 --- /dev/null +++ b/core/lib/Thelia/Model/Product.php @@ -0,0 +1,376 @@ +getVirtualColumn($virtualColumnName); + } catch (PropelException $e) { + throw new PropelException("Virtual column `$virtualColumnName` does not exist in Product::getRealLowestPrice"); + } + + return $amount; + } + + public function getTaxedPrice(Country $country, $price, State $state = null) + { + $taxCalculator = new Calculator(); + + return $taxCalculator->load($this, $country, $state)->getTaxedPrice($price); + } + + public function getTaxedPromoPrice(Country $country, $price, State $state = null) + { + $taxCalculator = new Calculator(); + + return $taxCalculator->load($this, $country, $state)->getTaxedPrice($price); + } + + /** + * Return the default PSE for this product. + * + * @return ProductSaleElements + */ + public function getDefaultSaleElements() + { + return ProductSaleElementsQuery::create()->filterByProductId($this->id)->filterByIsDefault(true)->findOne(); + } + + /** + * Return PSE count fir this product. + * + * @param ConnectionInterface $con an optional connection object + * @return int + */ + public function countSaleElements($con = null) + { + return ProductSaleElementsQuery::create()->filterByProductId($this->id)->count($con); + } + + /** + * @return int the current default category ID for this product + */ + public function getDefaultCategoryId() + { + // Find default category + $default_category = ProductCategoryQuery::create() + ->filterByProductId($this->getId()) + ->filterByDefaultCategory(true) + ->findOne(); + + return $default_category == null ? 0 : $default_category->getCategoryId(); + } + + /** + * Set default category for this product + * + * @param int $defaultCategoryId the new default category id + * @return $this + */ + public function setDefaultCategory($defaultCategoryId) + { + // Allow uncategorized products (NULL instead of 0, to bypass delete cascade constraint) + if ($defaultCategoryId <= 0) { + $defaultCategoryId = null; + } + + /** @var ProductCategory $productCategory */ + $productCategory = ProductCategoryQuery::create() + ->filterByProductId($this->getId()) + ->filterByDefaultCategory(true) + ->findOne() + ; + + if ($productCategory !== null && (int) $productCategory->getCategoryId() === (int) $defaultCategoryId) { + return $this; + } + + if ($productCategory !== null) { + $productCategory->delete(); + } + + // checks if the product is already associated with the category and but not default + if (null !== $productCategory = ProductCategoryQuery::create()->filterByProduct($this)->filterByCategoryId($defaultCategoryId)->findOne()) { + $productCategory->setDefaultCategory(true)->save(); + } else { + $position = (new ProductCategory())->setCategoryId($defaultCategoryId)->getNextPosition(); + + (new ProductCategory()) + ->setProduct($this) + ->setCategoryId($defaultCategoryId) + ->setDefaultCategory(true) + ->setPosition($position) + ->save(); + + $this->setPosition($position); + } + + return $this; + } + + /** + * @deprecated since 2.3, and will be removed in 2.4, please use Product::setDefaultCategory + * @param int $defaultCategoryId + * @return $this + */ + public function updateDefaultCategory($defaultCategoryId) + { + return $this->setDefaultCategory($defaultCategoryId); + } + + /** + * Create a new product, along with the default category ID + * + * @param int $defaultCategoryId the default category ID of this product + * @param float $basePrice the product base price + * @param int $priceCurrencyId the price currency Id + * @param int $taxRuleId the product tax rule ID + * @param float $baseWeight base weight in Kg + * @param int $baseQuantity the product quantity (default: 0) + * @throws \Exception + */ + public function create($defaultCategoryId, $basePrice, $priceCurrencyId, $taxRuleId, $baseWeight, $baseQuantity = 0) + { + $con = Propel::getWriteConnection(ProductTableMap::DATABASE_NAME); + + $con->beginTransaction(); + $this->dispatchEvent(TheliaEvents::BEFORE_CREATEPRODUCT, new ProductEvent($this)); + + try { + // Create the product + $this->save($con); + + // Add the default category + $this->setDefaultCategory($defaultCategoryId)->save($con); + + $this->setTaxRuleId($taxRuleId); + + // Create the default product sale element of this product + $this->createProductSaleElement($con, $baseWeight, $basePrice, $basePrice, $priceCurrencyId, true, false, false, $baseQuantity); + + // Store all the stuff ! + $con->commit(); + + $this->dispatchEvent(TheliaEvents::AFTER_CREATEPRODUCT, new ProductEvent($this)); + } catch (\Exception $ex) { + $con->rollback(); + + throw $ex; + } + } + + /** + * Create a basic product sale element attached to this product. + * + * @param ConnectionInterface $con + * @param float $weight + * @param float $basePrice + * @param float $salePrice + * @param int $currencyId + * @param int $isDefault + * @param bool $isPromo + * @param bool $isNew + * @param int $quantity + * @param string $eanCode + * @param bool $ref + * @return ProductSaleElements + * @throws PropelException + * @throws \Exception + */ + public function createProductSaleElement(ConnectionInterface $con, $weight, $basePrice, $salePrice, $currencyId, $isDefault, $isPromo = false, $isNew = false, $quantity = 0, $eanCode = '', $ref = false) + { + // Create an empty product sale element + $saleElements = new ProductSaleElements(); + + $saleElements + ->setProduct($this) + ->setRef($ref == false ? $this->getRef() : $ref) + ->setPromo($isPromo) + ->setNewness($isNew) + ->setWeight($weight) + ->setIsDefault($isDefault) + ->setEanCode($eanCode) + ->setQuantity($quantity) + ->save($con) + ; + + // Create an empty product price in the provided currency + $productPrice = new ProductPrice(); + + $productPrice + ->setProductSaleElements($saleElements) + ->setPromoPrice($salePrice) + ->setPrice($basePrice) + ->setCurrencyId($currencyId) + ->setFromDefaultCurrency(false) + ->save($con) + ; + + return $saleElements; + } + + /** + * Calculate next position relative to our default category + * + * @param ProductQuery $query + * @deprecated since 2.3, and will be removed in 2.4 + */ + protected function addCriteriaToPositionQuery($query) + { + // Find products in the same category + $products = ProductCategoryQuery::create() + ->filterByCategoryId($this->getDefaultCategoryId()) + ->filterByDefaultCategory(true) + ->select('product_id') + ->find(); + + if ($products != null) { + $query->filterById($products, Criteria::IN); + } + } + + public function preUpdate(ConnectionInterface $con = null) + { + parent::preUpdate($con); + + $this->dispatchEvent(TheliaEvents::BEFORE_UPDATEPRODUCT, new ProductEvent($this)); + + return true; + } + + /** + * {@inheritDoc} + */ + public function postUpdate(ConnectionInterface $con = null) + { + parent::postUpdate($con); + + $this->dispatchEvent(TheliaEvents::AFTER_UPDATEPRODUCT, new ProductEvent($this)); + } + + /** + * {@inheritDoc} + */ + public function preDelete(ConnectionInterface $con = null) + { + parent::preDelete($con); + + // Delete free_text feature AV for this product (see issue #2061). We have to do this before + // deleting the product, as the delete is cascaded to the feature_product table. + $featureAvs = FeatureAvQuery::create() + ->useFeatureProductQuery() + ->filterByIsFreeText(true) + ->filterByProductId($this->getId()) + ->endUse() + ->find($con) + ; + + /** @var FeatureAv $featureAv */ + foreach ($featureAvs as $featureAv) { + $featureAv + ->setDispatcher($this->dispatcher) + ->delete($con) + ; + } + + $this->dispatchEvent(TheliaEvents::BEFORE_DELETEPRODUCT, new ProductEvent($this)); + + return true; + } + + /** + * {@inheritDoc} + */ + public function postDelete(ConnectionInterface $con = null) + { + parent::postDelete($con); + + $this->markRewrittenUrlObsolete(); + + $this->dispatchEvent(TheliaEvents::AFTER_DELETEPRODUCT, new ProductEvent($this)); + } + + /** + * @inheritdoc + * @deprecated since 2.3, and will be removed in 2.4, please use ProductCategory::setPosition + */ + public function setPosition($v) + { + return parent::setPosition($v); + } + + /** + * @inheritdoc + * @deprecated since 2.3, and will be removed in 2.4, please use ProductCategory::getPosition + */ + public function getPosition() + { + return parent::getPosition(); + } + + public function postSave(ConnectionInterface $con = null) + { + // For BC, will be removed in 2.4 + if (!$this->isNew()) { + if (isset($this->modifiedColumns[ProductTableMap::COL_POSITION]) && $this->modifiedColumns[ProductTableMap::COL_POSITION]) { + if (null !== $productCategory = ProductCategoryQuery::create() + ->filterByProduct($this) + ->filterByDefaultCategory(true) + ->findOne() + ) { + $productCategory->changeAbsolutePosition($this->getPosition()); + } + } + } + + parent::postSave(); + } + + /** + * Overload for the position management + * @param ProductCategory $productCategory + * @inheritdoc + */ + protected function doAddProductCategory($productCategory) + { + parent::doAddProductCategory($productCategory); + + $productCategoryPosition = ProductCategoryQuery::create() + ->filterByCategoryId($productCategory->getCategoryId()) + ->orderByPosition(Criteria::DESC) + ->findOne(); + + $productCategory->setPosition($productCategoryPosition !== null ? $productCategoryPosition->getPosition() + 1 : 1); + } +} diff --git a/core/lib/Thelia/Model/ProductAssociatedContent.php b/core/lib/Thelia/Model/ProductAssociatedContent.php new file mode 100644 index 00000000..c866d037 --- /dev/null +++ b/core/lib/Thelia/Model/ProductAssociatedContent.php @@ -0,0 +1,91 @@ +filterByProductId($this->getProductId()); + } + + /** + * {@inheritDoc} + */ + public function preInsert(ConnectionInterface $con = null) + { + parent::preInsert($con); + + $this->setPosition($this->getNextPosition()); + + $this->dispatchEvent(TheliaEvents::BEFORE_CREATEPRODUCT_ASSOCIATED_CONTENT, new ProductAssociatedContentEvent($this)); + + return true; + } + + /** + * {@inheritDoc} + */ + public function postInsert(ConnectionInterface $con = null) + { + parent::postInsert($con); + + $this->dispatchEvent(TheliaEvents::AFTER_CREATEPRODUCT_ASSOCIATED_CONTENT, new ProductAssociatedContentEvent($this)); + } + + /** + * {@inheritDoc} + */ + public function preUpdate(ConnectionInterface $con = null) + { + parent::preUpdate($con); + + $this->dispatchEvent(TheliaEvents::BEFORE_UPDATEPRODUCT_ASSOCIATED_CONTENT, new ProductAssociatedContentEvent($this)); + + return true; + } + + /** + * {@inheritDoc} + */ + public function postUpdate(ConnectionInterface $con = null) + { + parent::postUpdate($con); + + $this->dispatchEvent(TheliaEvents::AFTER_UPDATEPRODUCT_ASSOCIATED_CONTENT, new ProductAssociatedContentEvent($this)); + } + + /** + * {@inheritDoc} + */ + public function preDelete(ConnectionInterface $con = null) + { + parent::preDelete($con); + + $this->dispatchEvent(TheliaEvents::BEFORE_DELETEPRODUCT_ASSOCIATED_CONTENT, new ProductAssociatedContentEvent($this)); + + return true; + } + + /** + * {@inheritDoc} + */ + public function postDelete(ConnectionInterface $con = null) + { + parent::postDelete($con); + + $this->dispatchEvent(TheliaEvents::AFTER_DELETEPRODUCT_ASSOCIATED_CONTENT, new ProductAssociatedContentEvent($this)); + } +} diff --git a/core/lib/Thelia/Model/ProductAssociatedContentQuery.php b/core/lib/Thelia/Model/ProductAssociatedContentQuery.php new file mode 100644 index 00000000..aac06656 --- /dev/null +++ b/core/lib/Thelia/Model/ProductAssociatedContentQuery.php @@ -0,0 +1,20 @@ +filterByCategoryId($this->getCategoryId()); + } +} diff --git a/core/lib/Thelia/Model/ProductCategoryQuery.php b/core/lib/Thelia/Model/ProductCategoryQuery.php new file mode 100644 index 00000000..47fb4c00 --- /dev/null +++ b/core/lib/Thelia/Model/ProductCategoryQuery.php @@ -0,0 +1,20 @@ +filterByProduct($this->getProduct()); + } + + /** + * {@inheritDoc} + */ + public function preInsert(ConnectionInterface $con = null) + { + parent::preInsert($con); + + $this->setPosition($this->getNextPosition()); + + return true; + } + + /** + * @inheritdoc + */ + public function setParentId($parentId) + { + $this->setProductId($parentId); + + return $this; + } + + /** + * @inheritdoc + */ + public function getParentId() + { + return $this->getProductId(); + } + + public function preDelete(ConnectionInterface $con = null) + { + parent::preDelete($con); + + $this->reorderBeforeDelete( + array( + "product_id" => $this->getProductId(), + ) + ); + + return true; + } + + /** + * @inheritdoc + */ + public function getBreadcrumb(Router $router, ContainerInterface $container, $tab, $locale) + { + return $this->getProductBreadcrumb($router, $container, $tab, $locale); + } + + /** + * @return FileModelParentInterface the parent file model + */ + public function getParentFileModel() + { + return new Product(); + } + + /** + * Get the ID of the form used to change this object information + * + * @return BaseForm the form + */ + public function getUpdateFormId() + { + return AdminForm::PRODUCT_DOCUMENT_MODIFICATION; + } + + /** + * @return string the path to the upload directory where files are stored, without final slash + */ + public function getUploadDir() + { + $uploadDir = ConfigQuery::read('documents_library_path'); + if ($uploadDir === null) { + $uploadDir = THELIA_LOCAL_DIR . 'media' . DS . 'documents'; + } else { + $uploadDir = THELIA_ROOT . $uploadDir; + } + + return $uploadDir . DS . 'product'; + } + + /** + * @param int $objectId the ID of the object + * + * @return string the URL to redirect to after update from the back-office + */ + public function getRedirectionUrl() + { + return '/admin/products/update?product_id=' . $this->getProductId(); + } + + /** + * Get the Query instance for this object + * + * @return ModelCriteria + */ + public function getQueryInstance() + { + return ProductDocumentQuery::create(); + } +} diff --git a/core/lib/Thelia/Model/ProductDocumentI18n.php b/core/lib/Thelia/Model/ProductDocumentI18n.php new file mode 100644 index 00000000..4dc65583 --- /dev/null +++ b/core/lib/Thelia/Model/ProductDocumentI18n.php @@ -0,0 +1,11 @@ +getProduct(); + $product->generateRewrittenUrl($this->getLocale()); + } +} diff --git a/core/lib/Thelia/Model/ProductI18nQuery.php b/core/lib/Thelia/Model/ProductI18nQuery.php new file mode 100644 index 00000000..ecc64a29 --- /dev/null +++ b/core/lib/Thelia/Model/ProductI18nQuery.php @@ -0,0 +1,20 @@ +filterByProduct($this->getProduct()); + } + + /** + * @inheritDoc + */ + public function preInsert(ConnectionInterface $con = null) + { + parent::preInsert($con); + + $this->setPosition($this->getNextPosition()); + + return true; + } + + /** + * @inheritdoc + */ + public function setParentId($parentId) + { + $this->setProductId($parentId); + + return $this; + } + + /** + * @inheritdoc + */ + public function getParentId() + { + return $this->getProductId(); + } + + public function preDelete(ConnectionInterface $con = null) + { + parent::preDelete($con); + + $this->reorderBeforeDelete( + array( + "product_id" => $this->getProductId(), + ) + ); + + return true; + } + + /** + * @inheritdoc + */ + public function getBreadcrumb(Router $router, ContainerInterface $container, $tab, $locale) + { + return $this->getProductBreadcrumb($router, $container, $tab, $locale); + } + + /** + * @return FileModelParentInterface the parent file model + */ + public function getParentFileModel() + { + return new Product(); + } + + /** + * Get the ID of the form used to change this object information + * + * @return BaseForm the form + */ + public function getUpdateFormId() + { + return AdminForm::PRODUCT_IMAGE_MODIFICATION; + } + + /** + * @return string the path to the upload directory where files are stored, without final slash + */ + public function getUploadDir() + { + $uploadDir = ConfigQuery::read('images_library_path'); + if ($uploadDir === null) { + $uploadDir = THELIA_LOCAL_DIR . 'media' . DS . 'images'; + } else { + $uploadDir = THELIA_ROOT . $uploadDir; + } + + return $uploadDir . DS . 'product'; + } + + /** + * @param int $objectId the ID of the object + * + * @return string the URL to redirect to after update from the back-office + */ + public function getRedirectionUrl() + { + return '/admin/products/update?product_id=' . $this->getProductId(); + } + + /** + * Get the Query instance for this object + * + * @return ModelCriteria + */ + public function getQueryInstance() + { + return ProductImageQuery::create(); + } +} diff --git a/core/lib/Thelia/Model/ProductImageI18n.php b/core/lib/Thelia/Model/ProductImageI18n.php new file mode 100644 index 00000000..03b6c4cd --- /dev/null +++ b/core/lib/Thelia/Model/ProductImageI18n.php @@ -0,0 +1,11 @@ +getVirtualColumn($virtualColumnName); + + if ($discount > 0) { + $amount = $amount * (1-($discount/100)); + } + } catch (PropelException $e) { + throw new PropelException("Virtual column `$virtualColumnName` does not exist in ProductSaleElements::getPrice"); + } + + return $amount; + } + + /** + * @param string $virtualColumnName + * @param int $discount + * @return float|int|mixed + * @throws PropelException + */ + public function getPromoPrice($virtualColumnName = 'price_PROMO_PRICE', $discount = 0) + { + try { + $amount = $this->getVirtualColumn($virtualColumnName); + + if ($discount > 0) { + $amount = $amount * (1-($discount/100)); + } + } catch (PropelException $e) { + throw new PropelException("Virtual column `$virtualColumnName` does not exist in ProductSaleElements::getPromoPrice"); + } + + return $amount; + } + + /** + * @param Country $country + * @param string $virtualColumnName + * @param int $discount + * @return int + * @throws PropelException + */ + public function getTaxedPrice(Country $country, $virtualColumnName = 'price_PRICE', $discount = 0) + { + $taxCalculator = new Calculator(); + + return $taxCalculator->load($this->getProduct(), $country)->getTaxedPrice($this->getPrice($virtualColumnName, $discount)); + } + + /** + * @param Country $country + * @param string $virtualColumnName + * @param int $discount + * @return int + * @throws PropelException + */ + public function getTaxedPromoPrice(Country $country, $virtualColumnName = 'price_PROMO_PRICE', $discount = 0) + { + $taxCalculator = new Calculator(); + + return $taxCalculator->load($this->getProduct(), $country)->getTaxedPrice($this->getPromoPrice($virtualColumnName, $discount)); + } + + /** + * Get product prices for a specific currency. + * + * When the currency is not the default currency, the product prices for this currency is : + * - calculated according to the product price of the default currency. It happens when no product price exists for + * the currency or when the `from_default_currency` flag is set to `true` + * - set directly in the product price when `from_default_currency` is set to `false` + * + * @param Currency $currency + * @param int $discount + * @return ProductPriceTools + * @throws \RuntimeException + * @throws PropelException + */ + public function getPricesByCurrency(Currency $currency, $discount = 0) + { + $defaultCurrency = Currency::getDefaultCurrency(); + + $productPrice = ProductPriceQuery::create() + ->filterByProductSaleElementsId($this->getId()) + ->filterByCurrencyId($currency->getId()) + ->findOne(); + + if (null === $productPrice || $productPrice->getFromDefaultCurrency()) { + // need to calculate the prices based on the product prices for the default currency + $productPrice = ProductPriceQuery::create() + ->filterByProductSaleElementsId($this->getId()) + ->filterByCurrencyId($defaultCurrency->getId()) + ->findOne(); + if (null !== $productPrice) { + $price = $productPrice->getPrice() * $currency->getRate() / $defaultCurrency->getRate(); + $promoPrice = $productPrice->getPromoPrice() * $currency->getRate() / $defaultCurrency->getRate(); + } else { + throw new \RuntimeException('Cannot find product prices for currency id: `' . $currency->getId() . '`'); + } + } else { + $price = $productPrice->getPrice(); + $promoPrice = $productPrice->getPromoPrice(); + } + + if ($discount > 0) { + $price = $price * (1-($discount/100)); + $promoPrice = $promoPrice * (1-($discount/100)); + } + + $productPriceTools = new ProductPriceTools($price, $promoPrice); + + return $productPriceTools; + } +} diff --git a/core/lib/Thelia/Model/ProductSaleElementsProductDocument.php b/core/lib/Thelia/Model/ProductSaleElementsProductDocument.php new file mode 100644 index 00000000..a228039a --- /dev/null +++ b/core/lib/Thelia/Model/ProductSaleElementsProductDocument.php @@ -0,0 +1,9 @@ + AdminResources::SUPERADMINISTRATOR, + ); + foreach (ProfileQuery::create()->find() as $profile) { + $profileList[$profile->getId()] = $profile->getCode(); + } + + return $profileList; + } +} +// ProfileQuery diff --git a/core/lib/Thelia/Model/ProfileResource.php b/core/lib/Thelia/Model/ProfileResource.php new file mode 100644 index 00000000..3f3aecef --- /dev/null +++ b/core/lib/Thelia/Model/ProfileResource.php @@ -0,0 +1,9 @@ +getRedirected()) { + //check if rewriting url alredy exists and put redirect to the new one + RewritingUrlQuery::create() + ->filterByView($this->getView()) + ->filterByViewId($this->getViewId()) + ->filterByViewLocale($this->getViewLocale()) + ->filterByRedirected($this->getId(), Criteria::NOT_IN) + ->update(array( + "Redirected" => $this->getId() + )); + } + } +} diff --git a/core/lib/Thelia/Model/RewritingUrlQuery.php b/core/lib/Thelia/Model/RewritingUrlQuery.php new file mode 100644 index 00000000..993d2334 --- /dev/null +++ b/core/lib/Thelia/Model/RewritingUrlQuery.php @@ -0,0 +1,124 @@ +addExplicitCondition(RewritingUrlTableMap::TABLE_NAME, 'REDIRECTED', 'ru', RewritingUrlTableMap::TABLE_NAME, 'ID', 'is_redirected'); + $redirectedJoin->setJoinType(Criteria::LEFT_JOIN); + + $search = RewritingArgumentQuery::create() + ->joinRewritingUrl('ru', Criteria::RIGHT_JOIN) + ->addJoinObject($redirectedJoin) + ->where('`ru`.URL = ?', $rewrittenUrl, \PDO::PARAM_STR) + ->withColumn('`ru`.URL', 'ru_url') + ->withColumn('`ru`.VIEW', 'ru_view') + ->withColumn('`ru`.VIEW_LOCALE', 'ru_locale') + ->withColumn('`ru`.VIEW_ID', 'ru_viewId') + ->withColumn('`is_redirected`.URL', 'ru_redirected_to_url') + ->find(); + + return $search; + } + + /** + * @param $view + * @param $viewId + * @param $viewLocale + * + * @return null|RewritingUrl + */ + public function getViewUrlQuery($view, $viewLocale, $viewId) + { + return RewritingUrlQuery::create() + ->joinRewritingArgument('ra', Criteria::LEFT_JOIN) + ->where('ISNULL(`ra`.REWRITING_URL_ID)') + ->filterByView($view) + ->filterByViewLocale($this->retrieveLocale($viewLocale)) + ->filterByViewId($viewId) + ->filterByRedirected(null) + ->orderById(Criteria::DESC) + ->findOne(); + } + + /** + * @param $view + * @param $viewLocale + * @param $viewId + * @param $viewOtherParameters + * + * @return null|RewritingUrl + */ + public function getSpecificUrlQuery($view, $viewLocale, $viewId, $viewOtherParameters) + { + $urlQuery = RewritingUrlQuery::create() + ->joinRewritingArgument('ra', Criteria::LEFT_JOIN) + ->withColumn('`ra`.REWRITING_URL_ID', 'ra_REWRITING_URL_ID') + ->filterByView($view) + ->filterByViewLocale($this->retrieveLocale($viewLocale)) + ->filterByViewId($viewId) + ->filterByRedirected(null) + ->orderById(Criteria::DESC); + + $otherParametersCount = \count($viewOtherParameters); + if ($otherParametersCount > 0) { + $parameterConditions = array(); + + foreach ($viewOtherParameters as $parameter => $value) { + $conditionName = 'other_parameter_condition_' . \count($parameterConditions); + $urlQuery->condition('parameter_condition', '`ra`.PARAMETER= ?', $parameter, \PDO::PARAM_STR) + ->condition('value_condition', '`ra`.VALUE = ?', $value, \PDO::PARAM_STR) + ->combine(array('parameter_condition', 'value_condition'), Criteria::LOGICAL_AND, $conditionName); + $parameterConditions[] = $conditionName; + } + + $urlQuery->where($parameterConditions, Criteria::LOGICAL_OR); + + $urlQuery->groupBy(RewritingUrlTableMap::COL_ID); + + $urlQuery->condition('count_condition_1', 'COUNT(' . RewritingUrlTableMap::COL_ID . ') = ?', $otherParametersCount, \PDO::PARAM_INT) // ensure we got all the asked parameters (provided by the query) + ->condition('count_condition_2', 'COUNT(' . RewritingUrlTableMap::COL_ID . ') = (SELECT COUNT(*) FROM rewriting_argument WHERE rewriting_argument.REWRITING_URL_ID = ra_REWRITING_URL_ID)'); // ensure we don't miss any parameters (needed to match the rewritten url) + + $urlQuery->having(array('count_condition_1', 'count_condition_2'), Criteria::LOGICAL_AND); + } else { + $urlQuery->where('ISNULL(`ra`.REWRITING_URL_ID)'); + } + + return $urlQuery->findOne(); + } + + protected function retrieveLocale($viewLocale) + { + if (\strlen($viewLocale) == 2) { + if (null !== $lang = LangQuery::create()->findOneByCode($viewLocale)) { + $viewLocale = $lang->getLocale(); + } + } + + return $viewLocale; + } +} +// RewritingUrlQuery diff --git a/core/lib/Thelia/Model/Sale.php b/core/lib/Thelia/Model/Sale.php new file mode 100644 index 00000000..346d32e2 --- /dev/null +++ b/core/lib/Thelia/Model/Sale.php @@ -0,0 +1,160 @@ +getStartDate()); + } + + /** + * @return bool true if the sale has a begin date, false otherwise + */ + public function hasEndDate() + { + return ! \is_null($this->getEndDate()); + } + + /** + * Get the price offsets for each of the currencies. + * + * @return array an array of (currency ID => offset value) + */ + public function getPriceOffsets() + { + $currencyOffsets = SaleOffsetCurrencyQuery::create()->filterBySaleId($this->getId())->find(); + + $offsetList = []; + + /** @var SaleOffsetCurrency $currencyOffset */ + foreach ($currencyOffsets as $currencyOffset) { + $offsetList[$currencyOffset->getCurrencyId()] = $currencyOffset->getPriceOffsetValue(); + } + + return $offsetList; + } + + /** + * Return the products included in this sale. + * + * @return array an array of Products + */ + public function getSaleProductList() + { + $saleProducts = SaleProductQuery::create()->filterBySaleId($this->getId())->groupByProductId()->find(); + + return $saleProducts; + } + + /** + * Return the selected attributes values for each of the selected products. + * + * @return array an array of (product ID => array of attribute availability ID) + */ + public function getSaleProductsAttributeList() + { + $saleProducts = SaleProductQuery::create()->filterBySaleId($this->getId())->orderByProductId()->find(); + + $selectedAttributes = []; + + $currentProduct = false; + + /** @var SaleProduct $saleProduct */ + foreach ($saleProducts as $saleProduct) { + if ($currentProduct != $saleProduct->getProductId()) { + $currentProduct = $saleProduct->getProductId(); + + $selectedAttributes[$currentProduct] = []; + } + + $selectedAttributes[$currentProduct][] = $saleProduct->getAttributeAvId(); + } + + return $selectedAttributes; + } + + /** + * {@inheritDoc} + */ + public function preInsert(ConnectionInterface $con = null) + { + parent::preInsert($con); + + $this->dispatchEvent(TheliaEvents::BEFORE_CREATESALE, new SaleEvent($this)); + + return true; + } + + /** + * {@inheritDoc} + */ + public function postInsert(ConnectionInterface $con = null) + { + parent::postInsert($con); + + $this->dispatchEvent(TheliaEvents::AFTER_CREATESALE, new SaleEvent($this)); + } + + /** + * {@inheritDoc} + */ + public function preUpdate(ConnectionInterface $con = null) + { + parent::preUpdate($con); + + $this->dispatchEvent(TheliaEvents::BEFORE_UPDATESALE, new SaleEvent($this)); + + return true; + } + + /** + * {@inheritDoc} + */ + public function postUpdate(ConnectionInterface $con = null) + { + parent::postUpdate($con); + + $this->dispatchEvent(TheliaEvents::AFTER_UPDATESALE, new SaleEvent($this)); + } + + /** + * {@inheritDoc} + */ + public function preDelete(ConnectionInterface $con = null) + { + parent::preDelete($con); + + $this->dispatchEvent(TheliaEvents::BEFORE_DELETESALE, new SaleEvent($this)); + + return true; + } + + /** + * {@inheritDoc} + */ + public function postDelete(ConnectionInterface $con = null) + { + parent::postDelete($con); + + $this->dispatchEvent(TheliaEvents::AFTER_DELETESALE, new SaleEvent($this)); + } +} diff --git a/core/lib/Thelia/Model/SaleI18n.php b/core/lib/Thelia/Model/SaleI18n.php new file mode 100644 index 00000000..ba8ebbda --- /dev/null +++ b/core/lib/Thelia/Model/SaleI18n.php @@ -0,0 +1,11 @@ +dispatchEvent(TheliaEvents::BEFORE_CREATESTATE, new StateEvent($this)); + + return true; + } + + public function postInsert(ConnectionInterface $con = null) + { + parent::postInsert($con); + + $this->dispatchEvent(TheliaEvents::AFTER_CREATESTATE, new StateEvent($this)); + } + + public function preUpdate(ConnectionInterface $con = null) + { + parent::preUpdate($con); + + $this->dispatchEvent(TheliaEvents::BEFORE_UPDATESTATE, new StateEvent($this)); + + return true; + } + + public function postUpdate(ConnectionInterface $con = null) + { + parent::postUpdate($con); + + $this->dispatchEvent(TheliaEvents::AFTER_UPDATESTATE, new StateEvent($this)); + } + + public function preDelete(ConnectionInterface $con = null) + { + parent::preDelete($con); + + $this->dispatchEvent(TheliaEvents::BEFORE_DELETESTATE, new StateEvent($this)); + + return true; + } + + public function postDelete(ConnectionInterface $con = null) + { + parent::postDelete($con); + + $this->dispatchEvent(TheliaEvents::AFTER_DELETESTATE, new StateEvent($this)); + } +} diff --git a/core/lib/Thelia/Model/StateI18n.php b/core/lib/Thelia/Model/StateI18n.php new file mode 100644 index 00000000..d478c9bf --- /dev/null +++ b/core/lib/Thelia/Model/StateI18n.php @@ -0,0 +1,9 @@ +getRate(); + + if ($rate === null) { + return 0; + } + + return $amount * $rate * 0.01; + } + + public function getTaxRuleCountryPosition() + { + try { + $taxRuleCountryPosition = $this->getVirtualColumn(TaxRuleQuery::ALIAS_FOR_TAX_RULE_COUNTRY_POSITION); + } catch (PropelException $e) { + throw new PropelException("Virtual column `" . TaxRuleQuery::ALIAS_FOR_TAX_RULE_COUNTRY_POSITION . "` does not exist in Tax::getTaxRuleCountryPosition"); + } + + return $taxRuleCountryPosition; + } + + public function getTypeInstance() + { + $class = $this->getType(); + + /* test type */ + if (!class_exists($class)) { + throw new TaxEngineException('Recorded type `' . $class . '` does not exists', TaxEngineException::BAD_RECORDED_TYPE); + } + /** @var \Thelia\TaxEngine\BaseTaxType $instance */ + $instance = new $class; + + if (!$instance instanceof BaseTaxType) { + throw new TaxEngineException('Recorded type `' . $class . '` does not extends BaseTaxType', TaxEngineException::BAD_RECORDED_TYPE); + } + + $instance->loadRequirements($this->getRequirements()); + + return $instance; + } + + public function setRequirements($requirements) + { + return parent::setSerializedRequirements(base64_encode(json_encode($requirements))); + } + + public function getRequirements() + { + $requirements = json_decode(base64_decode(parent::getSerializedRequirements()), true); + + if (json_last_error() != JSON_ERROR_NONE || !\is_array($requirements)) { + throw new TaxEngineException('BAD RECORDED REQUIREMENTS', TaxEngineException::BAD_RECORDED_REQUIREMENTS); + } + + return $requirements; + } +} diff --git a/core/lib/Thelia/Model/TaxI18n.php b/core/lib/Thelia/Model/TaxI18n.php new file mode 100644 index 00000000..e0fe9f4c --- /dev/null +++ b/core/lib/Thelia/Model/TaxI18n.php @@ -0,0 +1,11 @@ +loadTaxRule($this, $country, $product)->getTaxedPrice($untaxedAmount, $taxCollection, $askedLocale); + $promoTaxCollection = new OrderProductTaxCollection(); + $taxCalculator->loadTaxRule($this, $country, $product)->getTaxedPrice($untaxedPromoAmount, $promoTaxCollection, $askedLocale); + + foreach ($taxCollection as $index => $tax) { + $tax->setPromoAmount($promoTaxCollection->getKey($index)->getAmount()); + } + + return $taxCollection; + } +} diff --git a/core/lib/Thelia/Model/TaxRuleCountry.php b/core/lib/Thelia/Model/TaxRuleCountry.php new file mode 100644 index 00000000..f90582ee --- /dev/null +++ b/core/lib/Thelia/Model/TaxRuleCountry.php @@ -0,0 +1,9 @@ +getId(), + ($country !== null) ? $country->getId() : 0, + ($state !== null) ? $state->getId() : 0 + ); + + if (array_key_exists($key, self::$caches)) { + return self::$caches[$key]; + } + + $taxRuleQuery = TaxRuleCountryQuery::create() + ->filterByTaxRuleId($taxRule->getId()); + + if (null !== $country) { + $taxRuleQuery->filterByCountry($country, Criteria::EQUAL); + } + + $synthetizedSateId = $state; + + if (null !== $state) { + $taxRuleCount = clone $taxRuleQuery; + + if (0 === $taxRuleCount->filterByStateId($state->getId(), Criteria::EQUAL)->count()) { + $synthetizedSateId = null; + } + } + + $taxRuleQuery->filterByStateId($synthetizedSateId, Criteria::EQUAL); + + $search = TaxQuery::create() + ->filterByTaxRuleCountry($taxRuleQuery->find()) + ->withColumn(TaxRuleCountryTableMap::COL_POSITION, self::ALIAS_FOR_TAX_RULE_COUNTRY_POSITION) + ->orderBy(self::ALIAS_FOR_TAX_RULE_COUNTRY_POSITION, Criteria::ASC); + ; + + return self::$caches[$key] = $search->find(); + } +} +// TaxRuleQuery diff --git a/core/lib/Thelia/Model/Template.php b/core/lib/Thelia/Model/Template.php new file mode 100644 index 00000000..209b7902 --- /dev/null +++ b/core/lib/Thelia/Model/Template.php @@ -0,0 +1,79 @@ +dispatchEvent(TheliaEvents::BEFORE_CREATETEMPLATE, new TemplateEvent($this)); + + return true; + } + + /** + * {@inheritDoc} + */ + public function postInsert(ConnectionInterface $con = null) + { + parent::postInsert($con); + + $this->dispatchEvent(TheliaEvents::AFTER_CREATETEMPLATE, new TemplateEvent($this)); + } + + /** + * {@inheritDoc} + */ + public function preUpdate(ConnectionInterface $con = null) + { + parent::preUpdate($con); + + $this->dispatchEvent(TheliaEvents::BEFORE_UPDATETEMPLATE, new TemplateEvent($this)); + + return true; + } + + /** + * {@inheritDoc} + */ + public function postUpdate(ConnectionInterface $con = null) + { + parent::postUpdate($con); + + $this->dispatchEvent(TheliaEvents::AFTER_UPDATETEMPLATE, new TemplateEvent($this)); + } + + /** + * {@inheritDoc} + */ + public function preDelete(ConnectionInterface $con = null) + { + parent::preDelete($con); + + $this->dispatchEvent(TheliaEvents::BEFORE_DELETETEMPLATE, new TemplateEvent($this)); + + return true; + } + + /** + * {@inheritDoc} + */ + public function postDelete(ConnectionInterface $con = null) + { + parent::postDelete($con); + + $this->dispatchEvent(TheliaEvents::AFTER_DELETETEMPLATE, new TemplateEvent($this)); + } +} diff --git a/core/lib/Thelia/Model/TemplateI18n.php b/core/lib/Thelia/Model/TemplateI18n.php new file mode 100644 index 00000000..9fe15a49 --- /dev/null +++ b/core/lib/Thelia/Model/TemplateI18n.php @@ -0,0 +1,11 @@ + + */ +trait I18nTimestampableTrait +{ + public function postSave(ConnectionInterface $con = null) + { + $this->getBaseQueryObject() + ->filterById($this->getId()) + ->update([$this->getUpdatedAtColumnName() => new \DateTime()], $con) + ; + + parent::postSave($con); + } + + /** + * @return \Propel\Runtime\ActiveQuery\ModelCriteria + */ + protected function getBaseQueryObject() + { + $parentClass = preg_replace("#^([\w\_\\\\]+)I18n$#", "$1Query", __CLASS__); + + return (new $parentClass()); + } + + protected function getUpdatedAtColumnName() + { + return "UpdatedAt"; + } +} diff --git a/core/lib/Thelia/Model/Tools/ModelCriteriaTools.php b/core/lib/Thelia/Model/Tools/ModelCriteriaTools.php new file mode 100644 index 00000000..77e0c157 --- /dev/null +++ b/core/lib/Thelia/Model/Tools/ModelCriteriaTools.php @@ -0,0 +1,273 @@ + + */ +class ModelCriteriaTools +{ + /** + * @param ModelCriteria $search + * @param $requestedLocale + * @param array $columns + * @param null $foreignTable + * @param string $foreignKey + * @param bool $forceReturn + * @param string $forceReturn + */ + public static function getFrontEndI18n( + ModelCriteria &$search, + $requestedLocale, + $columns, + $foreignTable, + $foreignKey, + $forceReturn = false, + $localeAlias = null + ) { + if (!empty($columns)) { + if ($foreignTable === null) { + $foreignTable = $search->getTableMap()->getName(); + $aliasPrefix = ''; + } else { + $aliasPrefix = $foreignTable . '_'; + } + + if ($localeAlias === null) { + $localeAlias = $search->getTableMap()->getName(); + } + + $defaultLangWithoutTranslation = ConfigQuery::getDefaultLangWhenNoTranslationAvailable(); + + $requestedLocaleI18nAlias = $aliasPrefix . 'requested_locale_i18n'; + $defaultLocaleI18nAlias = $aliasPrefix . 'default_locale_i18n'; + + if ($defaultLangWithoutTranslation == Lang::STRICTLY_USE_REQUESTED_LANGUAGE) { + $requestedLocaleJoin = new Join(); + $requestedLocaleJoin->addExplicitCondition( + $localeAlias, + $foreignKey, + null, + $foreignTable . '_i18n', + 'ID', + $requestedLocaleI18nAlias + ); + $requestedLocaleJoin->setJoinType($forceReturn === false ? Criteria::INNER_JOIN : Criteria::LEFT_JOIN); + + $search->addJoinObject($requestedLocaleJoin, $requestedLocaleI18nAlias) + ->addJoinCondition( + $requestedLocaleI18nAlias, + '`' . $requestedLocaleI18nAlias . '`.LOCALE = ?', + $requestedLocale, + null, + \PDO::PARAM_STR + ) + ; + + $search->withColumn( + 'NOT ISNULL(`' . $requestedLocaleI18nAlias . '`.`ID`)', + $aliasPrefix . 'IS_TRANSLATED' + ); + + foreach ($columns as $column) { + $search->withColumn( + '`' . $requestedLocaleI18nAlias . '`.`' . $column . '`', + $aliasPrefix . 'i18n_' . $column + ); + } + } else { + $defaultLocale = Lang::getDefaultLanguage()->getLocale(); + + $defaultLocaleJoin = new Join(); + $defaultLocaleJoin->addExplicitCondition( + $localeAlias, + $foreignKey, + null, + $foreignTable . '_i18n', + 'ID', + $defaultLocaleI18nAlias + ); + $defaultLocaleJoin->setJoinType(Criteria::LEFT_JOIN); + + $search->addJoinObject($defaultLocaleJoin, $defaultLocaleI18nAlias) + ->addJoinCondition( + $defaultLocaleI18nAlias, + '`' . $defaultLocaleI18nAlias . '`.LOCALE = ?', + $defaultLocale, + null, + \PDO::PARAM_STR + ) + ; + + $requestedLocaleJoin = new Join(); + $requestedLocaleJoin->addExplicitCondition( + $localeAlias, + $foreignKey, + null, + $foreignTable . '_i18n', + 'ID', + $requestedLocaleI18nAlias + ); + $requestedLocaleJoin->setJoinType(Criteria::LEFT_JOIN); + + $search->addJoinObject($requestedLocaleJoin, $requestedLocaleI18nAlias) + ->addJoinCondition( + $requestedLocaleI18nAlias, + '`' . $requestedLocaleI18nAlias . '`.LOCALE = ?', + $requestedLocale, + null, + \PDO::PARAM_STR + ) + ; + + $search->withColumn( + 'NOT ISNULL(`' . $requestedLocaleI18nAlias . '`.`ID`)', + $aliasPrefix . 'IS_TRANSLATED' + ); + + if ($forceReturn === false) { + $search->where('NOT ISNULL(`' . $requestedLocaleI18nAlias . '`.ID)')->_or()->where( + 'NOT ISNULL(`' . $defaultLocaleI18nAlias . '`.ID)' + ) + ; + } + + foreach ($columns as $column) { + $search->withColumn( + 'CASE WHEN NOT ISNULL(`' . $requestedLocaleI18nAlias . '`.`' . $column . '`) THEN `' . $requestedLocaleI18nAlias . '`.`' . $column . '` ELSE `' . $defaultLocaleI18nAlias . '`.`' . $column . '` END', + $aliasPrefix . 'i18n_' . $column + ); + } + } + } + } + + public static function getBackEndI18n( + ModelCriteria &$search, + $requestedLocale, + $columns = array('TITLE', 'CHAPO', 'DESCRIPTION', 'POSTSCRIPTUM'), + $foreignTable = null, + $foreignKey = 'ID', + $localeAlias = null + ) { + if (!empty($columns)) { + if ($foreignTable === null) { + $foreignTable = $search->getTableMap()->getName(); + $aliasPrefix = ''; + } else { + $aliasPrefix = $foreignTable . '_'; + } + + if ($localeAlias === null) { + $localeAlias = $search->getTableMap()->getName(); + } + + $requestedLocaleI18nAlias = $aliasPrefix . 'requested_locale_i18n'; + + $requestedLocaleJoin = new Join(); + $requestedLocaleJoin->addExplicitCondition( + $localeAlias, + $foreignKey, + null, + $foreignTable . '_i18n', + 'ID', + $requestedLocaleI18nAlias + ); + $requestedLocaleJoin->setJoinType(Criteria::LEFT_JOIN); + + $search->addJoinObject($requestedLocaleJoin, $requestedLocaleI18nAlias) + ->addJoinCondition( + $requestedLocaleI18nAlias, + '`' . $requestedLocaleI18nAlias . '`.LOCALE = ?', + $requestedLocale, + null, + \PDO::PARAM_STR + ) + ; + + $search->withColumn('NOT ISNULL(`' . $requestedLocaleI18nAlias . '`.`ID`)', $aliasPrefix . 'IS_TRANSLATED'); + + foreach ($columns as $column) { + $search->withColumn( + '`' . $requestedLocaleI18nAlias . '`.`' . $column . '`', + $aliasPrefix . 'i18n_' . $column + ); + } + } + } + + + /** + * Bild query to retrieve I18n + * + * @param bool $backendContext + * @param int $requestedLangId + * @param ModelCriteria $search + * @param string $currentLocale + * @param array $columns + * @param string $foreignTable + * @param string $foreignKey + * @param bool $forceReturn + * @param string|null $localeAlias le local table if different of the main query table + * + * @return string + */ + public static function getI18n( + $backendContext, + $requestedLangId, + ModelCriteria &$search, + $currentLocale, + $columns, + $foreignTable, + $foreignKey, + $forceReturn = false, + $localeAlias = null + ) { + // If a lang has been requested, find the related Lang object, and get the locale + if ($requestedLangId !== null) { + $localeSearch = LangQuery::create()->findByIdOrLocale($requestedLangId); + + if ($localeSearch === null) { + throw new \InvalidArgumentException( + sprintf( + 'Incorrect lang argument given : lang %s not found', + $requestedLangId + ) + ); + } + + $locale = $localeSearch->getLocale(); + } else { + // Use the currently defined locale + $locale = $currentLocale; + } + + // Call the proper method depending on the context: front or back + if ($backendContext) { + self::getBackEndI18n($search, $locale, $columns, $foreignTable, $foreignKey, $localeAlias); + } else { + self::getFrontEndI18n($search, $locale, $columns, $foreignTable, $foreignKey, $forceReturn, $localeAlias); + } + + return $locale; + } +} diff --git a/core/lib/Thelia/Model/Tools/ModelEventDispatcherTrait.php b/core/lib/Thelia/Model/Tools/ModelEventDispatcherTrait.php new file mode 100644 index 00000000..7f3a7fb9 --- /dev/null +++ b/core/lib/Thelia/Model/Tools/ModelEventDispatcherTrait.php @@ -0,0 +1,69 @@ +dispatcher = $dispatcher; + + return $this; + } + + public function getDispatcher() + { + return $this->dispatcher; + } + + public function clearDispatcher() + { + $this->dispatcher = null; + } + + protected function dispatchEvent($eventName, ActionEvent $event) + { + if (!\is_null($this->dispatcher)) { + $this->dispatcher->dispatch($eventName, $event); + } + } + + public function __sleep() + { + $data = parent::__sleep(); + $key = array_search("dispatcher", $data); + + if (isset($data[$key])) { + unset($data[$key]); + } + + return $data; + } +} diff --git a/core/lib/Thelia/Model/Tools/PositionManagementTrait.php b/core/lib/Thelia/Model/Tools/PositionManagementTrait.php new file mode 100644 index 00000000..bd559e8e --- /dev/null +++ b/core/lib/Thelia/Model/Tools/PositionManagementTrait.php @@ -0,0 +1,216 @@ +createQuery() + ->orderByPosition(Criteria::DESC) + ->limit(1); + + $this->addCriteriaToPositionQuery($query); + + $last = $query->findOne(); + + return $last != null ? $last->getPosition() + 1 : 1; + } + + /** + * Move up a object + */ + public function movePositionUp() + { + $this->movePositionUpOrDown(true); + } + + /** + * Move down a object + */ + public function movePositionDown() + { + $this->movePositionUpOrDown(false); + } + + /** + * Move up or down a object + * + * @param bool $up the exchange mode: go up (POSITION_UP) or go down (POSITION_DOWN) + */ + protected function movePositionUpOrDown($up = true) + { + // The current position of the object + $myPosition = $this->getPosition(); + + // Find object to exchange position with + $search = $this->createQuery(); + + $this->addCriteriaToPositionQuery($search); + + // Up or down ? + if ($up === true) { + // Find the object immediately before me + $search->filterByPosition(array('max' => $myPosition-1))->orderByPosition(Criteria::DESC); + } else { + // Find the object immediately after me + $search->filterByPosition(array('min' => $myPosition+1))->orderByPosition(Criteria::ASC); + } + + $result = $search->findOne(); + + // If we found the proper object, exchange their positions + if ($result) { + $cnx = Propel::getWriteConnection($this->getDatabaseName()); + + $cnx->beginTransaction(); + + try { + $this + ->setPosition($result->getPosition()) + ->save($cnx) + ; + + // For BC + if (method_exists($result, 'setDispatcher') && method_exists($this, 'getDispatcher')) { + $result->setDispatcher($this->getDispatcher()); + } + + $result->setPosition($myPosition)->save($cnx); + + $cnx->commit(); + } catch (\Exception $e) { + $cnx->rollback(); + } + } + } + + /** + * Simply return the database name, from the constant in the MAP class. + */ + protected function getDatabaseName() + { + // Find DATABASE_NAME constant + $mapClassName = self::TABLE_MAP; + + return $mapClassName::DATABASE_NAME; + } + + /** + * Changes object position + * + * @param newPosition + */ + public function changeAbsolutePosition($newPosition) + { + // The current position + $current_position = $this->getPosition(); + + if ($newPosition != null && $newPosition > 0 && $newPosition != $current_position) { + // Find categories to offset + $search = $this->createQuery(); + + $this->addCriteriaToPositionQuery($search); + + if ($newPosition > $current_position) { + // The new position is after the current position -> we will offset + 1 all categories located between us and the new position + $search->filterByPosition(array('min' => 1+$current_position, 'max' => $newPosition)); + + $delta = -1; + } else { + // The new position is brefore the current position -> we will offset - 1 all categories located between us and the new position + $search->filterByPosition(array('min' => $newPosition, 'max' => $current_position - 1)); + + $delta = 1; + } + + $results = $search->find(); + + $cnx = Propel::getWriteConnection($this->getDatabaseName()); + + $cnx->beginTransaction(); + + try { + foreach ($results as $result) { + $objNewPosition = $result->getPosition() + $delta; + + // For BC + if (method_exists($result, 'setDispatcher') && method_exists($this, 'getDispatcher')) { + $result->setDispatcher($this->getDispatcher()); + } + + $result->setPosition($objNewPosition)->save($cnx); + } + + $this + ->setPosition($newPosition) + ->save($cnx) + ; + + $cnx->commit(); + } catch (\Exception $e) { + $cnx->rollback(); + } + } + } + + protected function reorderBeforeDelete($fields = array()) + { + // Find DATABASE_NAME constant + $mapClassName = self::TABLE_MAP; + + $data = array(); + $whereCriteria = array(); + + foreach ($fields as $field => $value) { + $whereCriteria[] = $field . '=:' . $field; + $data[':' . $field] = $value; + } + + $data[':position'] = $this->getPosition(); + + $sql = sprintf("UPDATE `%s` SET position=(position-1) WHERE " . (\count($whereCriteria)>0 ? implode(" AND ", $whereCriteria) : '1') . " AND position>:position", $mapClassName::TABLE_NAME); + + $con = Propel::getConnection($mapClassName::DATABASE_NAME); + $statement = $con->prepare($sql); + + $statement->execute($data); + } +} diff --git a/core/lib/Thelia/Model/Tools/ProductPriceTools.php b/core/lib/Thelia/Model/Tools/ProductPriceTools.php new file mode 100644 index 00000000..344810ac --- /dev/null +++ b/core/lib/Thelia/Model/Tools/ProductPriceTools.php @@ -0,0 +1,59 @@ + + */ +class ProductPriceTools +{ + /** + * The value for the price field. + * + * @var double + */ + protected $price; + + /** + * The value for the promoPrice field. + * + * @var double + */ + protected $promoPrice; + + public function __construct($price, $promoPrice) + { + $this->price = $price; + $this->promoPrice = $promoPrice; + } + + /** + * @return float + */ + public function getPrice() + { + return $this->price; + } + + /** + * @return float + */ + public function getPromoPrice() + { + return $this->promoPrice; + } +} diff --git a/core/lib/Thelia/Model/Tools/UrlRewritingTrait.php b/core/lib/Thelia/Model/Tools/UrlRewritingTrait.php new file mode 100644 index 00000000..81e3126a --- /dev/null +++ b/core/lib/Thelia/Model/Tools/UrlRewritingTrait.php @@ -0,0 +1,223 @@ +getLocale(); + } + + return URL::getInstance()->retrieve($this->getRewrittenUrlViewName(), $this->getId(), $locale)->toString(); + } + + /** + * Generate a rewritten URL from the object title, and store it in the rewriting table + * + * @param string $locale a valid locale (e.g. en_US) + */ + public function generateRewrittenUrl($locale) + { + if ($this->isNew()) { + throw new \RuntimeException(sprintf('Object %s must be saved before generating url', $this->getRewrittenUrlViewName())); + } + // Borrowed from http://stackoverflow.com/questions/2668854/sanitizing-strings-to-make-them-url-and-filename-safe + + $this->setLocale($locale); + + $generateEvent = new GenerateRewrittenUrlEvent($this, $locale); + + $this->dispatchEvent(TheliaEvents::GENERATE_REWRITTENURL, $generateEvent); + + if ($generateEvent->isRewritten()) { + return $generateEvent->getUrl(); + } + + $title = $this->getTitle(); + + if (null == $title) { + throw new \RuntimeException('Impossible to create an url if title is null'); + } + // Replace all weird characters with dashes + $string = preg_replace('/[^\w\-~_\.]+/u', '-', $title); + + // Only allow one dash separator at a time (and make string lowercase) + $cleanString = mb_strtolower(preg_replace('/--+/u', '-', $string), 'UTF-8'); + + $urlFilePart = rtrim($cleanString, '.-~_') . ".html"; + + try { + $i=0; + while (URL::getInstance()->resolve($urlFilePart)) { + $i++; + $urlFilePart = sprintf("%s-%d.html", $cleanString, $i); + } + } catch (UrlRewritingException $e) { + $rewritingUrl = new RewritingUrl(); + $rewritingUrl->setUrl($urlFilePart) + ->setView($this->getRewrittenUrlViewName()) + ->setViewId($this->getId()) + ->setViewLocale($locale) + ->save() + ; + } + + return $urlFilePart; + } + + /** + * return the rewritten URL for the given locale + * + * @param string $locale a valid locale (e.g. en_US) + * @return null + */ + public function getRewrittenUrl($locale) + { + $rewritingUrl = RewritingUrlQuery::create() + ->filterByViewLocale($locale) + ->filterByView($this->getRewrittenUrlViewName()) + ->filterByViewId($this->getId()) + ->filterByRedirected(null) + ->findOne() + ; + + if ($rewritingUrl) { + $url = $rewritingUrl->getUrl(); + } else { + $url = null; + } + + return $url; + } + + /** + * Mark the current URL as obseolete + */ + public function markRewrittenUrlObsolete() + { + RewritingUrlQuery::create() + ->filterByView($this->getRewrittenUrlViewName()) + ->filterByViewId($this->getId()) + ->update(array( + "View" => ConfigQuery::getObsoleteRewrittenUrlView() + )); + } + + /** + * Set the rewritten URL for the given locale + * + * @param string $locale a valid locale (e.g. en_US) + * @param $url + * @return $this + * @throws UrlRewritingException + * @throws \Thelia\Exception\UrlRewritingException + */ + public function setRewrittenUrl($locale, $url) + { + $currentUrl = $this->getRewrittenUrl($locale); + if ($currentUrl == $url || null === $url) { + /* no url update */ + + return $this; + } + + try { + $resolver = new RewritingResolver($url); + + /* we can reassign old url */ + if (null === $resolver->redirectedToUrl) { + /* else ... */ + if ($resolver->view == $this->getRewrittenUrlViewName() && $resolver->viewId == $this->getId()) { + /* it's an url related to the current object */ + + if ($resolver->locale != $locale) { + /* it is an url related to this product for another locale */ + throw new UrlRewritingException(Translator::getInstance()->trans('URL_ALREADY_EXISTS'), UrlRewritingException::URL_ALREADY_EXISTS); + } + + if (\count($resolver->otherParameters) > 0) { + /* it is an url related to this product but with more arguments */ + throw new UrlRewritingException(Translator::getInstance()->trans('URL_ALREADY_EXISTS'), UrlRewritingException::URL_ALREADY_EXISTS); + } + + /* here it must be a deprecated url */ + } else { + /* already related to another object */ + throw new UrlRewritingException(Translator::getInstance()->trans('URL_ALREADY_EXISTS'), UrlRewritingException::URL_ALREADY_EXISTS); + } + } + } catch (UrlRewritingException $e) { + /* It's all good if URL is not found */ + if ($e->getCode() !== UrlRewritingException::URL_NOT_FOUND) { + throw $e; + } + } + + /* set the new URL */ + if (isset($resolver)) { + /* erase the old one */ + $rewritingUrl = RewritingUrlQuery::create()->findOneByUrl($url); + $rewritingUrl->setView($this->getRewrittenUrlViewName()) + ->setViewId($this->getId()) + ->setViewLocale($locale) + ->setRedirected(null) + ->save() + ; + + /* erase additional arguments if any : only happens in case it erases a deprecated url */ + RewritingArgumentQuery::create()->filterByRewritingUrl($rewritingUrl)->deleteAll(); + } else { + /* just create it */ + $rewritingUrl = new RewritingUrl(); + $rewritingUrl->setUrl($url) + ->setView($this->getRewrittenUrlViewName()) + ->setViewId($this->getId()) + ->setViewLocale($locale) + ->save() + ; + } + + /* deprecate the old one if needed */ + if (null !== $oldRewritingUrl = RewritingUrlQuery::create()->findOneByUrl($currentUrl)) { + $oldRewritingUrl->setRedirected($rewritingUrl->getId())->save(); + } + + return $this; + } +} diff --git a/core/lib/Thelia/Module/AbstractAdminResourcesCompiler.php b/core/lib/Thelia/Module/AbstractAdminResourcesCompiler.php new file mode 100644 index 00000000..9abedfd7 --- /dev/null +++ b/core/lib/Thelia/Module/AbstractAdminResourcesCompiler.php @@ -0,0 +1,56 @@ + + */ +abstract class AbstractAdminResourcesCompiler implements CompilerPassInterface +{ + /** + * @return Array of resources + * Exemple : + * [ + * "ADDRESS" => "admin.address", + * ... + * ] + */ + abstract public function getResources(); + + /** + * @return string ModuleCode + */ + abstract public function getModuleCode(); + + /** + * Allow module to add resources in AdminResources Service + * @param \Symfony\Component\DependencyInjection\ContainerBuilder $container + */ + public function process(\Symfony\Component\DependencyInjection\ContainerBuilder $container) + { + if (!$container->hasDefinition("thelia.admin.resources")) { + return; + } + + /** @var \Symfony\Component\DependencyInjection\Definition $adminResources */ + $adminResources = $container->getDefinition("thelia.admin.resources"); + + $adminResources->addMethodCall("addModuleResources", [$this->getResources(), $this->getModuleCode()]); + } +} diff --git a/core/lib/Thelia/Module/AbstractDeliveryModule.php b/core/lib/Thelia/Module/AbstractDeliveryModule.php new file mode 100644 index 00000000..57dc5ad6 --- /dev/null +++ b/core/lib/Thelia/Module/AbstractDeliveryModule.php @@ -0,0 +1,57 @@ +findByCountryAndModule( + $country, + $this->getModuleModel() + )) { + $area = $areaDeliveryModule->getArea(); + } + + return $area; + } + + public function getDeliveryMode() + { + return "delivery"; + } +} diff --git a/core/lib/Thelia/Module/AbstractDeliveryModuleWithState.php b/core/lib/Thelia/Module/AbstractDeliveryModuleWithState.php new file mode 100644 index 00000000..b8d6bcd8 --- /dev/null +++ b/core/lib/Thelia/Module/AbstractDeliveryModuleWithState.php @@ -0,0 +1,58 @@ +findByCountryAndModule( + $country, + $this->getModuleModel(), + $state + )) { + $area = $areaDeliveryModule->getArea(); + } + + return $area; + } + + public function getDeliveryMode() + { + return "delivery"; + } +} diff --git a/core/lib/Thelia/Module/AbstractPaymentModule.php b/core/lib/Thelia/Module/AbstractPaymentModule.php new file mode 100644 index 00000000..944429fe --- /dev/null +++ b/core/lib/Thelia/Module/AbstractPaymentModule.php @@ -0,0 +1,117 @@ +getContainer()->get("thelia.parser"); + + $parser->setTemplateDefinition( + $parser->getTemplateHelper()->getActiveFrontTemplate() + ); + + $renderedTemplate = $parser->render( + "order-payment-gateway.html", + array( + "order_id" => $order->getId(), + "cart_count" => $this->getRequest()->getSession()->getSessionCart($this->getDispatcher())->getCartItems()->count(), + "gateway_url" => $gateway_url, + "payment_form_data" => $form_data + ) + ); + + return Response::create($renderedTemplate); + } + + /** + * Return the order payment success page URL + * + * @param int $order_id the order ID + * @return string the order payment success page URL + */ + public function getPaymentSuccessPageUrl($order_id) + { + $frontOfficeRouter = $this->getContainer()->get('router.front'); + + return URL::getInstance()->absoluteUrl( + $frontOfficeRouter->generate( + "order.placed", + array("order_id" => $order_id), + Router::ABSOLUTE_URL + ) + ); + } + + /** + * Redirect the customer to the failure payment page. if $message is null, a generic message is displayed. + * + * @param int $order_id the order ID + * @param string|null $message an error message. + * + * @return string the order payment failure page URL + */ + public function getPaymentFailurePageUrl($order_id, $message) + { + $frontOfficeRouter = $this->getContainer()->get('router.front'); + + return URL::getInstance()->absoluteUrl( + $frontOfficeRouter->generate( + "order.failed", + array( + "order_id" => $order_id, + "message" => $message + ), + Router::ABSOLUTE_URL + ) + ); + } + + /** + * @inherited + */ + public function manageStockOnCreation() + { + return true; + } + + public function getMinimumAmount() + { + return null; + } + + public function getMaximumAmount() + { + return null; + } +} diff --git a/core/lib/Thelia/Module/BaseModule.php b/core/lib/Thelia/Module/BaseModule.php new file mode 100644 index 00000000..7b5e2cb5 --- /dev/null +++ b/core/lib/Thelia/Module/BaseModule.php @@ -0,0 +1,809 @@ +getModuleModel(); + } + + if ($moduleModel->getActivate() === self::IS_NOT_ACTIVATED) { + $moduleModel->setActivate(self::IS_ACTIVATED); + $moduleModel->save(); + + // Refresh propel cache to be sure that module's model is created + // when the module's initialization methods will be called. + + /** @var Thelia $theliaKernel */ + $theliaKernel = $this->container->get('kernel'); + + $theliaKernel->initializePropelService(true, $cacheRefresh); + + $con = Propel::getWriteConnection(ModuleTableMap::DATABASE_NAME); + $con->beginTransaction(); + try { + $this->initializeCoreI18n(); + if ($this->preActivation($con)) { + $this->postActivation($con); + $con->commit(); + } + } catch (\Exception $e) { + $con->rollBack(); + $moduleModel->setActivate(self::IS_NOT_ACTIVATED); + $moduleModel->save(); + throw $e; + } + + $this->registerHooks(); + } + } + + public function deActivate($moduleModel = null) + { + if (null === $moduleModel) { + $moduleModel = $this->getModuleModel(); + } + if ($moduleModel->getActivate() == self::IS_ACTIVATED) { + $con = Propel::getWriteConnection(ModuleTableMap::DATABASE_NAME); + $con->beginTransaction(); + try { + if ($this->preDeactivation($con)) { + $moduleModel->setActivate(self::IS_NOT_ACTIVATED); + $moduleModel->save($con); + $this->postDeactivation($con); + + $con->commit(); + } + } catch (\Exception $e) { + $con->rollBack(); + throw $e; + } + } + } + + public function hasContainer() + { + return null !== $this->container; + } + + public function getContainer() + { + if ($this->hasContainer() === false) { + throw new \RuntimeException("Sorry, container is not available in this context"); + } + + return $this->container; + } + + public function hasRequest() + { + return null !== $this->request; + } + + public function setRequest(Request $request) + { + $this->request = $request; + } + + /** + * @return \Thelia\Core\HttpFoundation\Request the request. + * + * @throws \RuntimeException + */ + public function getRequest() + { + if ($this->hasRequest() === false) { + // Try to get request from container. + $this->setRequest($this->getContainer()->get('request_stack')->getCurrentRequest()); + } + + if ($this->hasRequest() === false) { + throw new \RuntimeException("Sorry, the request is not available in this context"); + } + + return $this->request; + } + + public function hasDispatcher() + { + return null !== $this->dispatcher; + } + + public function setDispatcher(EventDispatcherInterface $dispatcher) + { + $this->dispatcher = $dispatcher; + } + + /** + * @return EventDispatcherInterface + * @throws \RuntimeException + */ + public function getDispatcher() + { + if ($this->hasDispatcher() === false) { + // Try to get dispatcher from container. + $this->setDispatcher($this->getContainer()->get('event_dispatcher')); + } + + if ($this->hasDispatcher() === false) { + throw new \RuntimeException("Sorry, the dispatcher is not available in this context"); + } + + return $this->dispatcher; + } + + /** + * @inheritdoc + */ + public function setTitle(Module $module, $titles) + { + if (\is_array($titles)) { + foreach ($titles as $locale => $title) { + $moduleI18n = ModuleI18nQuery::create() + ->filterById($module->getId())->filterByLocale($locale) + ->findOne(); + + if (null === $moduleI18n) { + $moduleI18n = new ModuleI18n(); + $moduleI18n + ->setId($module->getId()) + ->setLocale($locale) + ->setTitle($title) + ; + $moduleI18n->save(); + } else { + $moduleI18n->setTitle($title); + $moduleI18n->save(); + } + } + } + } + + /** + * @inheritdoc + */ + public static function getConfigValue($variableName, $defaultValue = null, $valueLocale = null) + { + return ModuleConfigQuery::create() + ->getConfigValue(self::getModuleId(), $variableName, $defaultValue, $valueLocale); + } + + /** + * @inheritdoc + */ + public static function setConfigValue($variableName, $variableValue, $valueLocale = null, $createIfNotExists = true) + { + ModuleConfigQuery::create() + ->setConfigValue(self::getModuleId(), $variableName, $variableValue, $valueLocale, $createIfNotExists); + } + + /** + * @inheritdoc + */ + public function deployImageFolder(Module $module, $folderPath, ConnectionInterface $con = null) + { + try { + $directoryBrowser = new \DirectoryIterator($folderPath); + } catch (\UnexpectedValueException $e) { + throw $e; + } + if (null === $con) { + $con = Propel::getConnection( + ModuleImageTableMap::DATABASE_NAME + ); + } + + /* browse the directory */ + $imagePosition = 1; + /** @var \DirectoryIterator $directoryContent */ + foreach ($directoryBrowser as $directoryContent) { + /* is it a file ? */ + if ($directoryContent->isFile()) { + $fileName = $directoryContent->getFilename(); + $filePath = $directoryContent->getPathName(); + + /* is it a picture ? */ + if (Image::isImage($filePath)) { + $con->beginTransaction(); + + $image = new ModuleImage(); + $image->setModuleId($module->getId()); + $image->setPosition($imagePosition); + $image->save($con); + + $imageDirectory = sprintf("%s/media/images/module", THELIA_LOCAL_DIR); + $imageFileName = sprintf("%s-%d-%s", $module->getCode(), $image->getId(), $fileName); + + $increment = 0; + while (file_exists($imageDirectory . '/' . $imageFileName)) { + $imageFileName = sprintf( + "%s-%d-%d-%s", + $module->getCode(), + $image->getId(), + $increment, + $fileName + ); + $increment++; + } + + $imagePath = sprintf('%s/%s', $imageDirectory, $imageFileName); + + if (! is_dir($imageDirectory)) { + if (! @mkdir($imageDirectory, 0777, true)) { + $con->rollBack(); + throw new ModuleException( + sprintf("Cannot create directory : %s", $imageDirectory), + ModuleException::CODE_NOT_FOUND + ); + } + } + + if (! @copy($filePath, $imagePath)) { + $con->rollBack(); + throw new ModuleException( + sprintf("Cannot copy file : %s to : %s", $filePath, $imagePath), + ModuleException::CODE_NOT_FOUND + ); + } + + $image->setFile($imageFileName); + $image->save($con); + + $con->commit(); + $imagePosition++; + } + } + } + } + + /** + * @inheritdoc + */ + public function getModuleModel() + { + if (null === $this->moduleModel) { + $this->moduleModel = ModuleQuery::create()->findOneByCode($this->getCode()); + + if (null === $this->moduleModel) { + throw new ModuleException( + sprintf("Module Code `%s` not found", $this->getCode()), + ModuleException::CODE_NOT_FOUND + ); + } + } + + return $this->moduleModel; + } + + + /** + * Module A may use static method from module B, thus we have to cache + * a couple (module code => module id). + * + * @return int The module id, in a static way, with a cache + */ + private static $moduleIds = []; + + /** + * @inheritdoc + */ + public static function getModuleId() + { + $code = self::getModuleCode(); + + if (! isset(self::$moduleIds[$code])) { + if (null === $module = ModuleQuery::create()->findOneByCode($code)) { + throw new ModuleException( + sprintf("Module Code `%s` not found", $code), + ModuleException::CODE_NOT_FOUND + ); + } + + self::$moduleIds[$code] = $module->getId(); + } + + return self::$moduleIds[$code]; + } + + /** + * @inheritdoc + */ + public static function getModuleCode() + { + $fullClassName = explode('\\', \get_called_class()); + + return end($fullClassName); + } + + /* + * The module code + */ + public function getCode() + { + return self::getModuleCode(); + } + + /** + * Check if this module is the payment module for a given order + * + * @param Order $order an order + * @return bool true if this module is the payment module for the given order. + */ + public function isPaymentModuleFor(Order $order) + { + $model = $this->getModuleModel(); + + return $order->getPaymentModuleId() == $model->getId(); + } + + /** + * Check if this module is the delivery module for a given order + * + * @param Order $order an order + * @return bool true if this module is the delivery module for the given order. + */ + public function isDeliveryModuleFor(Order $order) + { + $model = $this->getModuleModel(); + + return $order->getDeliveryModuleId() == $model->getId(); + } + + /** + * A convenient method to get the current order total, with or without tax, discount or postage. + * This method operates on the order currently in the user's session, and should not be used to + * get the total amount of an order already stored in the database. For such orders, use + * Order::getTotalAmount() method. + * + * @param bool $with_tax if true, to total price will include tax amount + * @param bool $with_discount if true, the total price will include discount, if any + * @param bool $with_postage if true, the total price will include the delivery costs, if any. + * + * @return float|int the current order amount. + */ + public function getCurrentOrderTotalAmount($with_tax = true, $with_discount = true, $with_postage = true) + { + /** @var Session $session */ + $session = $this->getRequest()->getSession(); + + /** @var Cart $cart */ + $cart = $session->getSessionCart($this->getDispatcher()); + + /** @var Order $order */ + $order = $session->getOrder(); + + /** @var TaxEngine $taxEngine */ + $taxEngine = $this->getContainer()->get("thelia.taxengine"); + + /** @var Country $country */ + $country = $taxEngine->getDeliveryCountry(); + + $state = $taxEngine->getDeliveryState(); + + $amount = $with_tax ? $cart->getTaxedAmount($country, $with_discount, $state) : $cart->getTotalAmount($with_discount, $country, $state); + + if ($with_postage) { + if ($with_tax) { + $amount += $order->getPostage(); + } else { + $amount += $order->getPostage() - $order->getPostageTax(); + } + } + + return $amount; + } + + /** + * @inheritdoc + */ + public static function getCompilers() + { + return array(); + } + + /** + * @inheritdoc + */ + public function install(ConnectionInterface $con = null) + { + // Override this method to do something useful. + } + + /** + * @inheritdoc + */ + public function update($currentVersion, $newVersion, ConnectionInterface $con = null) + { + // Override this method to do something useful. + } + + /** + * @inheritdoc + */ + public function preActivation(ConnectionInterface $con = null) + { + // Override this method to do something useful. + return true; + } + + /** + * @inheritdoc + */ + public function postActivation(ConnectionInterface $con = null) + { + // Override this method to do something useful. + } + + /** + * @inheritdoc + */ + public function preDeactivation(ConnectionInterface $con = null) + { + // Override this method to do something useful. + return true; + } + + /** + * @inheritdoc + */ + public function postDeactivation(ConnectionInterface $con = null) + { + // Override this method to do something useful. + } + + /** + * @inheritdoc + */ + public function destroy(ConnectionInterface $con = null, $deleteModuleData = false) + { + // Override this method to do something useful. + } + + /** + * @inheritdoc + */ + public function getHooks() + { + return array(); + } + + /** + * @inheritdoc + */ + public function registerHooks() + { + $moduleHooks = $this->getHooks(); + + if (\is_array($moduleHooks) && !empty($moduleHooks)) { + $allowedTypes = (array) TemplateDefinition::getStandardTemplatesSubdirsIterator(); + $defaultLang = Lang::getDefaultLanguage(); + $defaultLocale = $defaultLang->getLocale(); + + /** + * @var EventDispatcherInterface $dispatcher + */ + $dispatcher = $this->container->get("event_dispatcher"); + + foreach ($moduleHooks as $hook) { + $isValid = \is_array($hook) && + isset($hook["type"]) && + array_key_exists($hook["type"], $allowedTypes) && + isset($hook["code"]) && + \is_string($hook["code"]) && + !empty($hook["code"]) + ; + + if (!$isValid) { + Tlog::getInstance()->notice("The module ".$this->getCode()." tried to register an invalid hook"); + + continue; + } + + /** + * Create or update hook db entry. + * + * @var \Thelia\Model\Hook $hookModel + */ + list($hookModel, $updateData) = $this->createOrUpdateHook($hook, $dispatcher, $defaultLocale); + + /** + * Update translations + */ + $event = new HookUpdateEvent($hookModel->getId()); + + foreach ($updateData as $locale => $data) { + $event + ->setCode($hookModel->getCode()) + ->setNative($hookModel->getNative()) + ->setByModule($hookModel->getByModule()) + ->setActive($hookModel->getActivate()) + ->setBlock($hookModel->getBlock()) + ->setNative($hookModel->getNative()) + ->setType($hookModel->getType()) + ->setLocale($locale) + ->setChapo($data["chapo"]) + ->setTitle($data["title"]) + ->setDescription($data["description"]) + ; + + $dispatcher->dispatch(TheliaEvents::HOOK_UPDATE, $event); + } + } + } + } + + protected function createOrUpdateHook(array $hook, EventDispatcherInterface $dispatcher, $defaultLocale) + { + $hookModel = HookQuery::create()->filterByCode($hook["code"])->findOne(); + + if ($hookModel === null) { + $event = new HookCreateAllEvent(); + } else { + $event = new HookUpdateEvent($hookModel->getId()); + } + + /** + * Get used I18n variables + */ + $locale = $defaultLocale; + + list($titles, $descriptions, $chapos) = $this->getHookI18nInfo($hook, $defaultLocale); + + /** + * If the default locale exists + * extract it to save it in create action + * + * otherwise take the first + */ + if (isset($titles[$defaultLocale])) { + $title = $titles[$defaultLocale]; + + unset($titles[$defaultLocale]); + } else { + reset($titles); + + $locale = key($titles); + $title = array_shift($titles); + } + + $description = $this->arrayKeyPop($locale, $descriptions); + $chapo = $this->arrayKeyPop($locale, $chapos); + + /** + * Set data + */ + $event + ->setBlock(isset($hook["block"]) && (bool) $hook["block"]) + ->setLocale($locale) + ->setTitle($title) + ->setDescription($description) + ->setChapo($chapo) + ->setType($hook["type"]) + ->setCode($hook["code"]) + ->setNative(false) + ->setByModule(isset($hook["module"]) && (bool) $hook["module"]) + ->setActive(isset($hook["active"]) && (bool) $hook["active"]) + ; + + /** + * Dispatch the event + */ + $dispatcher->dispatch( + ( + $hookModel === null ? + TheliaEvents::HOOK_CREATE_ALL : + TheliaEvents::HOOK_UPDATE + ), + $event + ); + + return [ + $event->getHook(), + $this->formatHookDataForI18n($titles, $descriptions, $chapos) + ]; + } + + protected function formatHookDataForI18n(array $titles, array $descriptions, array $chapos) + { + $locales = array_merge( + array_keys($titles), + array_keys($descriptions), + array_keys($chapos) + ); + + $locales = array_unique($locales); + + $data = array(); + + foreach ($locales as $locale) { + $data[$locale] = [ + 'title' => !isset($titles[$locale]) ? null : $titles[$locale], + 'description' => !isset($descriptions[$locale]) ? null: $descriptions[$locale], + 'chapo' => !isset($chapos[$locale]) ? null : $chapos[$locale] + ]; + } + + return $data; + } + + protected function getHookI18nInfo(array $hook, $defaultLocale) + { + $titles = array(); + $descriptions = array(); + $chapos = array(); + + /** + * Get the defined titles + */ + if (isset($hook["title"])) { + $titles = $this->extractI18nValues($hook["title"], $defaultLocale); + } + + /** + * Then the defined descriptions + */ + if (isset($hook["description"])) { + $descriptions = $this->extractI18nValues($hook["description"], $defaultLocale); + } + + /** + * Then the short descriptions + */ + if (isset($hook["chapo"])) { + $chapos = $this->extractI18nValues($hook["chapo"], $defaultLocale); + } + + return [$titles, $descriptions, $chapos]; + } + + protected function extractI18nValues($data, $defaultLocale) + { + $returnData = array(); + + if (\is_array($data)) { + foreach ($data as $key => $value) { + if (!\is_string($key)) { + continue; + } + + $returnData[$key] = $value; + } + } elseif (is_scalar($data)) { + $returnData[$defaultLocale] = $data; + } + + return $returnData; + } + + protected function arrayKeyPop($key, array &$array) + { + $value = null; + + if (array_key_exists($key, $array)) { + $value = $array[$key]; + + unset($array[$key]); + } + + return $value; + } + + /** + * @since 2.4 + * @return string + */ + protected function getPropelSchemaDir() + { + return THELIA_MODULE_DIR . $this->getCode() . DS . 'Config' . DS . 'schema.xml'; + } + + /** + * @since 2.4 + * @return bool + */ + protected function hasPropelSchema() + { + return (new Filesystem())->exists($this->getPropelSchemaDir()); + } + + /** + * Add core translations of the module to use in `preActivation` and `postActivation` + * when the module is not yest activated and translations are not available + */ + private function initializeCoreI18n() + { + if ($this->hasContainer()) { + /** @var Translator $translator */ + $translator = $this->container->get('thelia.translator'); + + if (null !== $translator) { + $i18nPath = sprintf('%s%s/I18n/', THELIA_MODULE_DIR, $this->getCode()); + $languages = LangQuery::create()->find(); + + foreach ($languages as $language) { + $locale = $language->getLocale(); + $i18nFile = sprintf('%s%s.php', $i18nPath, $locale); + + if (is_file($i18nFile) && is_readable($i18nFile)) { + $translator->addResource('php', $i18nFile, $locale, strtolower(self::getModuleCode())); + } + } + } + } + } +} diff --git a/core/lib/Thelia/Module/BaseModuleInterface.php b/core/lib/Thelia/Module/BaseModuleInterface.php new file mode 100644 index 00000000..6248f1dc --- /dev/null +++ b/core/lib/Thelia/Module/BaseModuleInterface.php @@ -0,0 +1,250 @@ + title_string + */ + public function setTitle(Module $module, $titles); + + /** + * Get a module's configuration variable + * + * @param string $variableName the variable name + * @param string $defaultValue the default value, if variable is not defined + * @param null $valueLocale the required locale, or null to get default one + * @return string the variable value + */ + public static function getConfigValue($variableName, $defaultValue = null, $valueLocale = null); + + /** + * Set module configuration variable, creating it if required + * + * @param string $variableName the variable name + * @param string $variableValue the variable value + * @param null $valueLocale the locale, or null if not required + * @param bool $createIfNotExists if true, the variable will be created if not already defined + * @throws \LogicException if variable does not exists and $createIfNotExists is false + * @return $this; + */ + public static function setConfigValue( + $variableName, + $variableValue, + $valueLocale = null, + $createIfNotExists = true + ); + + /** + * Ensure the proper deployment of the module's images. + * + * TODO : this method does not take care of internationalization. This is a bug. + * + * @param Module $module the module + * @param string $folderPath the image folder path + * @param ConnectionInterface $con + * + * @throws \Thelia\Exception\ModuleException + * @throws \Exception + * @throws \UnexpectedValueException + */ + public function deployImageFolder(Module $module, $folderPath, ConnectionInterface $con = null); + + /** + * @return Module + * @throws \Thelia\Exception\ModuleException + */ + public function getModuleModel(); + + /** + * @return string The module id + */ + public static function getModuleId(); + + /** + * @return string The module code, in a static way + */ + public static function getModuleCode(); + + /** + * @return string The module code + */ + public function getCode(); + + /** + * + * This method adds new compilers to Thelia container + * + * You must return an array. This array can contain : + * - arrays + * - one or many instance(s) of \Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface + * + * in the first case, your array must contains 2 indexes. + * The first is the compiler instance and the second the compilerPass type. + * Example : + * return array( + * array( + * new \MyModule\DependencyInjection\Compiler\MySuperCompilerPass(), + * \Symfony\Component\DependencyInjection\Compiler\PassConfig::TYPE_BEFORE_OPTIMIZATION + * ) + * ); + * + * In the seconde case, just an instance of CompilerPassInterface. + * Example : + * return array ( + * new \MyModule\DependencyInjection\Compiler\MySuperCompilerPass() + * ); + * + * But you can combine both behaviors + * Example : + * + * return array( + * new \MyModule\DependencyInjection\Compiler\MySuperCompilerPass(), + * array( + * new \MyModule\DependencyInjection\Compiler\MyOtherSuperCompilerPass(), + * Symfony\Component\DependencyInjection\Compiler\PassConfig::TYPE_BEFORE_OPTIMIZATION + * ) + * ); + * + */ + public static function getCompilers(); + + + /** + * @return array + * + * This method must be used when your module defines hooks. + * Override this and return an array of your hooks names to register them + * + * This returned value must be like the example, only type and code are mandatory + * + * Example: + * + * return array( + * + * // Only register the title in the default language + * array( + * "type" => TemplateDefinition::BACK_OFFICE, + * "code" => "my_super_hook_name", + * "title" => "My hook", + * "description" => "My hook is really, really great", + * ), + * + * // Manage i18n + * array( + * "type" => TemplateDefinition::FRONT_OFFICE, + * "code" => "my_hook_name", + * "title" => array( + * "fr_FR" => "Mon Hook", + * "en_US" => "My hook", + * ), + * "description" => array( + * "fr_FR" => "Mon hook est vraiment super", + * "en_US" => "My hook is really, really great", + * ), + * "chapo" => array( + * "fr_FR" => "Mon hook est vraiment super", + * "en_US" => "My hook is really, really great", + * ), + * "block" => true, + * "active" => true + * ) + * ); + */ + public function getHooks(); + + /** + * Create or update module hooks returned by the `getHooks` function + */ + public function registerHooks(); +} diff --git a/core/lib/Thelia/Module/BasePaymentModuleController.php b/core/lib/Thelia/Module/BasePaymentModuleController.php new file mode 100644 index 00000000..7c2e94d4 --- /dev/null +++ b/core/lib/Thelia/Module/BasePaymentModuleController.php @@ -0,0 +1,274 @@ + + */ +abstract class BasePaymentModuleController extends BaseFrontController +{ + protected $log = null; + + /** + * Return a module identifier used to calculate the name of the log file, + * and in the log messages. + * + * @return string the module code + */ + abstract protected function getModuleCode(); + + /** + * Returns the module-specific logger, initializing it if required. + * + * @return Tlog a Tlog instance + */ + protected function getLog() + { + if ($this->log == null) { + $this->log = Tlog::getNewInstance(); + + $logFilePath = $this->getLogFilePath(); + + $this->log->setPrefix("#LEVEL: #DATE #HOUR: "); + $this->log->setDestinations("\\Thelia\\Log\\Destination\\TlogDestinationFile"); + $this->log->setConfig("\\Thelia\\Log\\Destination\\TlogDestinationFile", 0, $logFilePath); + $this->log->setLevel(Tlog::INFO); + } + + return $this->log; + } + + /** + * @return string The path to the module's log file. + */ + protected function getLogFilePath() + { + return sprintf(THELIA_ROOT . "log" . DS . "%s.log", strtolower($this->getModuleCode())); + } + + /** + * Process the confirmation of an order. This method should be called + * once the module has performed the required checks to confirm a valid payment. + * + * @param int $orderId the order ID + * @throws \Exception + */ + public function confirmPayment($orderId) + { + try { + $orderId = \intval($orderId); + + if (null !== $order = $this->getOrder($orderId)) { + $this->getLog()->addInfo( + $this->getTranslator()->trans( + "Processing confirmation of order ref. %ref, ID %id", + array('%ref' => $order->getRef(), '%id' => $order->getId()) + ) + ); + + $event = new OrderEvent($order); + + $event->setStatus(OrderStatusQuery::getPaidStatus()->getId()); + + $this->dispatch(TheliaEvents::ORDER_UPDATE_STATUS, $event); + + $this->getLog()->addInfo( + $this->getTranslator()->trans( + "Order ref. %ref, ID %id has been successfully paid.", + array('%ref' => $order->getRef(), '%id' => $order->getId()) + ) + ); + } + } catch (\Exception $ex) { + $this->getLog()->addError( + $this->getTranslator()->trans( + "Error occured while processing order ref. %ref, ID %id: %err", + array( + '%err' => $ex->getMessage(), + '%ref' => !isset($order) ? "?" : $order->getRef(), + '%id' => !isset($order) ? "?" : $order->getId() + ) + ) + ); + + throw $ex; + } + } + + /** + * Save the transaction/payment ref in the order + * + * @param int $orderId the order ID + * @param int $transactionRef the transaction reference + * + * @throws \Exception + */ + public function saveTransactionRef($orderId, $transactionRef) + { + try { + $orderId = \intval($orderId); + + if (null !== $order = $this->getOrder($orderId)) { + $event = new OrderEvent($order); + + $event->setTransactionRef($transactionRef); + + $this->dispatch(TheliaEvents::ORDER_UPDATE_TRANSACTION_REF, $event); + + $this->getLog()->addInfo( + $this->getTranslator()->trans( + "Payment transaction %transaction_ref for order ref. %ref, ID %id has been successfully saved.", + [ + '%transaction_ref' => $transactionRef, + '%ref' => $order->getRef(), + '%id' => $order->getId() + ] + ) + ); + } + } catch (\Exception $ex) { + $this->getLog()->addError( + $this->getTranslator()->trans( + "Error occurred while saving payment transaction %transaction_ref for order ID %id.", + [ + '%transaction_ref' => $transactionRef, + '%id' => $orderId + ] + ) + ); + + throw $ex; + } + } + + /** + * Process the cancellation of a payment on the payment gateway. The order will go back to the + * "not paid" status. + * + * @param int $orderId the order ID + */ + public function cancelPayment($orderId) + { + try { + $orderId = \intval($orderId); + + if (null !== $order = $this->getOrder($orderId)) { + $this->getLog()->addInfo( + $this->getTranslator()->trans( + "Processing cancelation of payment for order ref. %ref", + array('%ref' => $order->getRef()) + ) + ); + + $event = new OrderEvent($order); + + $event->setStatus(OrderStatusQuery::getNotPaidStatus()->getId()); + + $this->dispatch(TheliaEvents::ORDER_UPDATE_STATUS, $event); + + $this->getLog()->addInfo( + $this->getTranslator()->trans( + "Order ref. %ref is now unpaid.", + array('%ref' => $order->getRef()) + ) + ); + } + } catch (\Exception $ex) { + $this->getLog()->addError( + $this->getTranslator()->trans( + "Error occurred while cancelling order ref. %ref, ID %id: %err", + array( + '%err' => $ex->getMessage(), + '%ref' => !isset($order) ? "?" : $order->getRef(), + '%id' => !isset($order) ? "?" : $order->getId() + ) + ) + ); + + throw $ex; + } + } + + /** + * Get an order and issue a log message if not found. + * + * @param $orderId + * @return null|\Thelia\Model\Order + */ + protected function getOrder($orderId) + { + if (null == $order = OrderQuery::create()->findPk($orderId)) { + $this->getLog()->addError( + $this->getTranslator()->trans("Unknown order ID: %id", array('%id' => $orderId)) + ); + } + + return $order; + } + + /** + * Redirect the customer to the successful payment page. + * + * @param int $orderId the order ID + */ + public function redirectToSuccessPage($orderId) + { + $this->getLog()->addInfo("Redirecting customer to payment success page"); + + throw new RedirectException( + $this->retrieveUrlFromRouteId( + 'order.placed', + [], + [ + 'order_id' => $orderId + ], + Router::ABSOLUTE_PATH + ) + ); + } + + /** + * Redirect the customer to the failure payment page. if $message is null, a generic message is displayed. + * + * @param int $orderId the order ID + * @param string|null $message an error message. + */ + public function redirectToFailurePage($orderId, $message) + { + $this->getLog()->addInfo("Redirecting customer to payment failure page"); + + throw new RedirectException( + $this->retrieveUrlFromRouteId( + 'order.failed', + [], + [ + 'order_id' => $orderId, + 'message' => $message + ], + Router::ABSOLUTE_PATH + ) + ); + } +} diff --git a/core/lib/Thelia/Module/DeliveryModuleInterface.php b/core/lib/Thelia/Module/DeliveryModuleInterface.php new file mode 100644 index 00000000..92d5aaaa --- /dev/null +++ b/core/lib/Thelia/Module/DeliveryModuleInterface.php @@ -0,0 +1,51 @@ + + */ +class InvalidXmlDocumentException extends \RuntimeException +{ +} diff --git a/core/lib/Thelia/Module/ModuleDescriptorValidator.php b/core/lib/Thelia/Module/ModuleDescriptorValidator.php new file mode 100644 index 00000000..fcfa94b1 --- /dev/null +++ b/core/lib/Thelia/Module/ModuleDescriptorValidator.php @@ -0,0 +1,132 @@ + + */ +class ModuleDescriptorValidator +{ + protected static $versions = [ + '1' => 'module.xsd', + '2' => 'module-2_1.xsd', + '3' => 'module-2_2.xsd' + ]; + + /** @var Finder */ + protected $xsdFinder; + + protected $moduleVersion; + + public function __construct() + { + $this->xsdFinder = new Finder(); + $this->xsdFinder + ->name('*.xsd') + ->in(__DIR__ . '/schema/module/'); + } + + /** + * @return mixed + */ + public function getModuleVersion() + { + return $this->moduleVersion; + } + + public function validate($xml_file, $version = null) + { + $dom = new \DOMDocument(); + $errors = []; + + if ($dom->load($xml_file)) { + /** @var \SplFileInfo $xsdFile */ + foreach ($this->xsdFinder as $xsdFile) { + $xsdVersion = array_search($xsdFile->getBasename(), self::$versions); + + if (false === $xsdVersion || (null !== $version && $version != $xsdVersion)) { + continue; + } + + $errors = $this->schemaValidate($dom, $xsdFile); + + if (\count($errors) === 0) { + $this->moduleVersion = $xsdVersion; + + return true; + } + } + } + + throw new InvalidXmlDocumentException( + sprintf( + "%s file is not a valid file : %s", + $xml_file, + implode(", ", $errors) + ) + ); + } + + /** + * Validate the schema of a XML file with a given xsd file + * + * @param \DOMDocument $dom The XML document + * @param \SplFileInfo $xsdFile The XSD file + * @return array an array of errors if validation fails, otherwise an empty array + */ + protected function schemaValidate(\DOMDocument $dom, \SplFileInfo $xsdFile) + { + $errorMessages = []; + + try { + libxml_use_internal_errors(true); + + if (!$dom->schemaValidate($xsdFile->getRealPath())) { + $errors = libxml_get_errors(); + + foreach ($errors as $error) { + $errorMessages[] = sprintf( + 'XML error "%s" [%d] (Code %d) in %s on line %d column %d' . "\n", + $error->message, + $error->level, + $error->code, + $error->file, + $error->line, + $error->column + ); + } + + libxml_clear_errors(); + } + + libxml_use_internal_errors(false); + } catch (ErrorException $ex) { + libxml_use_internal_errors(false); + } + + return $errorMessages; + } + + public function getDescriptor($xml_file) + { + $this->validate($xml_file); + + return @simplexml_load_file($xml_file); + } +} diff --git a/core/lib/Thelia/Module/ModuleManagement.php b/core/lib/Thelia/Module/ModuleManagement.php new file mode 100644 index 00000000..2535eb4f --- /dev/null +++ b/core/lib/Thelia/Module/ModuleManagement.php @@ -0,0 +1,225 @@ + + */ +class ModuleManagement +{ + protected $baseModuleDir; + protected $reflected; + + /** @var ModuleDescriptorValidator $descriptorValidator */ + protected $descriptorValidator; + + protected $container; + + public function __construct(ContainerInterface $container) + { + $this->container = $container; + $this->baseModuleDir = THELIA_MODULE_DIR; + } + + public function updateModules(ContainerInterface $container) + { + $finder = new Finder(); + + $finder + ->name('module.xml') + ->in($this->baseModuleDir . '*' . DS . 'Config') + ; + + $errors = []; + + $modulesUpdated = []; + + foreach ($finder as $file) { + try { + $this->updateModule($file, $container); + } catch (\Exception $ex) { + // Guess module code + $moduleCode = basename(dirname(dirname($file))); + + $errors[$moduleCode] = $ex; + } + } + + if (\count($errors) > 0) { + throw new InvalidModuleException($errors); + } + + if (\count($modulesUpdated)) { + $this->cacheClear(); + } + } + + /** + * Update module information, and invoke install() for new modules (e.g. modules + * just discovered), or update() modules for which version number ha changed. + * + * @param SplFileInfo $file the module.xml file descriptor + * @param ContainerInterface $container the container + * + * @return Module + * + * @throws \Exception + * @throws \Propel\Runtime\Exception\PropelException + */ + public function updateModule($file, ContainerInterface $container) + { + $descriptorValidator = $this->getDescriptorValidator(); + + $content = $descriptorValidator->getDescriptor($file->getRealPath()); + $reflected = new \ReflectionClass((string)$content->fullnamespace); + $code = basename(dirname($reflected->getFileName())); + $version = (string)$content->version; + $mandatory = \intval($content->mandatory); + $hidden = \intval($content->hidden); + + $module = ModuleQuery::create()->filterByCode($code)->findOne(); + + if (null === $module) { + $module = new Module(); + $module->setActivate(0); + + $action = 'install'; + } elseif ($version !== $module->getVersion()) { + $currentVersion = $module->getVersion(); + $action = 'update'; + } else { + $action = 'none'; + } + + $con = Propel::getWriteConnection(ModuleTableMap::DATABASE_NAME); + $con->beginTransaction(); + + try { + $module + ->setCode($code) + ->setVersion($version) + ->setFullNamespace((string)$content->fullnamespace) + ->setType($this->getModuleType($reflected)) + ->setCategory((string)$content->type) + ->setMandatory($mandatory) + ->setHidden($hidden) + ->save($con) + ; + + // Update the module images, title and description when the module is installed, but not after + // as these data may have been modified byt the administrator + if ('install' === $action) { + $this->saveDescription($module, $content, $con); + + if (isset($content->{"images-folder"}) && !$module->isModuleImageDeployed($con)) { + /** @var \Thelia\Module\BaseModule $moduleInstance */ + $moduleInstance = $reflected->newInstance(); + $imagesFolder = THELIA_MODULE_DIR . $code . DS . (string)$content->{"images-folder"}; + $moduleInstance->deployImageFolder($module, $imagesFolder, $con); + } + } + + // Tell the module to install() or update() + $instance = $module->createInstance(); + + $instance->setContainer($container); + + if ($action == 'install') { + $instance->install($con); + } elseif ($action == 'update') { + $instance->update($currentVersion, $version, $con); + } + + if ($action !== 'none') { + $instance->registerHooks(); + } + + $con->commit(); + } catch (\Exception $ex) { + Tlog::getInstance()->addError("Failed to update module " . $module->getCode(), $ex); + + $con->rollBack(); + throw $ex; + } + + return $module; + } + + /** + * @return \Thelia\Module\ModuleDescriptorValidator + */ + public function getDescriptorValidator() + { + if (null === $this->descriptorValidator) { + $this->descriptorValidator = new ModuleDescriptorValidator(); + } + + return $this->descriptorValidator; + } + + protected function cacheClear() + { + $cacheEvent = new CacheEvent( + $this->container->getParameter('kernel.cache_dir') + ); + + $this->container->get('event_dispatcher')->dispatch(TheliaEvents::CACHE_CLEAR, $cacheEvent); + } + + private function getModuleType(\ReflectionClass $reflected) + { + if ( + $reflected->implementsInterface('Thelia\Module\DeliveryModuleInterface') + || + $reflected->implementsInterface('Thelia\Module\DeliveryModuleWithStateInterface') + ) { + return BaseModule::DELIVERY_MODULE_TYPE; + } elseif ($reflected->implementsInterface('Thelia\Module\PaymentModuleInterface')) { + return BaseModule::PAYMENT_MODULE_TYPE; + } else { + return BaseModule::CLASSIC_MODULE_TYPE; + } + } + + private function saveDescription(Module $module, \SimpleXMLElement $content, ConnectionInterface $con) + { + foreach ($content->descriptive as $description) { + $locale = (string)$description->attributes()->locale; + + $module + ->setLocale($locale) + ->setTitle($description->title) + ->setDescription(isset($description->description) ? $description->description : null) + ->setPostscriptum(isset($description->postscriptum) ? $description->postscriptum : null) + ->setChapo(isset($description->subtitle) ? $description->subtitle : null) + ->save($con) + ; + } + } +} diff --git a/core/lib/Thelia/Module/PaymentModuleInterface.php b/core/lib/Thelia/Module/PaymentModuleInterface.php new file mode 100644 index 00000000..1fa170ab --- /dev/null +++ b/core/lib/Thelia/Module/PaymentModuleInterface.php @@ -0,0 +1,53 @@ + + */ +class ModuleDefinition +{ + /** @var string */ + protected $code; + + /** @var string */ + protected $namespace; + + /** @var string */ + protected $type; + + /** @var string */ + protected $logo; + + /** @var array */ + protected $languages = []; + + /** @var array */ + protected $descriptives = []; + + /** @var string */ + protected $theliaVersion; + + /** @var string */ + protected $version; + + /** @var array */ + protected $dependencies = []; + + /** @var string */ + protected $documentation; + + /** @var string */ + protected $stability; + + /** @var array */ + protected $authors = []; + + /** + * @return array + */ + public function getAuthors() + { + return $this->authors; + } + + /** + * @param array $authors + */ + public function setAuthors($authors) + { + $this->authors = $authors; + } + + /** + * @return string + */ + public function getCode() + { + return $this->code; + } + + /** + * @param string $code + */ + public function setCode($code) + { + $this->code = $code; + } + + /** + * @return array + */ + public function getDependencies() + { + return $this->dependencies; + } + + /** + * @param array $dependencies + */ + public function setDependencies($dependencies) + { + $this->dependencies = $dependencies; + } + + /** + * @return array + */ + public function getDescriptives() + { + return $this->descriptives; + } + + /** + * @param array $descriptives + */ + public function setDescriptives($descriptives) + { + $this->descriptives = $descriptives; + } + + /** + * @return string + */ + public function getDocumentation() + { + return $this->documentation; + } + + /** + * @param string $documentation + */ + public function setDocumentation($documentation) + { + $this->documentation = $documentation; + } + + /** + * @return array + */ + public function getLanguages() + { + return $this->languages; + } + + /** + * @param array $languages + */ + public function setLanguages($languages) + { + $this->languages = $languages; + } + + /** + * @return string + */ + public function getLogo() + { + return $this->logo; + } + + /** + * @param string $logo + */ + public function setLogo($logo) + { + $this->logo = $logo; + } + + /** + * @return string + */ + public function getTheliaVersion() + { + return $this->theliaVersion; + } + + /** + * @param string $theliaVersion + */ + public function setTheliaVersion($theliaVersion) + { + $this->theliaVersion = $theliaVersion; + } + + /** + * @return string + */ + public function getNamespace() + { + return $this->namespace; + } + + /** + * @param string $namespace + */ + public function setNamespace($namespace) + { + $this->namespace = $namespace; + } + + /** + * @return string + */ + public function getStability() + { + return $this->stability; + } + + /** + * @param string $stability + */ + public function setStability($stability) + { + $this->stability = $stability; + } + + /** + * @return string + */ + public function getType() + { + return $this->type; + } + + /** + * @param string $type + */ + public function setType($type) + { + $this->type = $type; + } + + /** + * @return string + */ + public function getVersion() + { + return $this->version; + } + + /** + * @param string $version + */ + public function setVersion($version) + { + $this->version = $version; + } +} diff --git a/core/lib/Thelia/Module/Validator/ModuleValidator.php b/core/lib/Thelia/Module/Validator/ModuleValidator.php new file mode 100644 index 00000000..07c0434e --- /dev/null +++ b/core/lib/Thelia/Module/Validator/ModuleValidator.php @@ -0,0 +1,532 @@ + + */ +class ModuleValidator +{ + protected $modulePath; + + /** @var \SimpleXMLElement */ + protected $moduleDescriptor; + + /** @var ModuleDefinition */ + protected $moduleDefinition; + + protected $moduleVersion; + + /** @var Translator */ + protected $translator; + + /** @var array array of errors */ + protected $errors = []; + + protected $moduleDirName; + + /** + * @param string $modulePath the path of the module directory + * @param \Thelia\Core\Translation\Translator $translator FOR UNIT TEST PURPOSE ONLY + */ + public function __construct($modulePath = null, $translator = null) + { + $this->translator = $translator; + + $this->modulePath = $modulePath; + + $this->moduleDirName = basename($this->modulePath); + + $this->checkDirectoryStructure(); + + $this->loadModuleDescriptor(); + + $this->loadModuleDefinition(); + } + + /** + * @param mixed $modulePath + */ + public function setModulePath($modulePath) + { + $this->modulePath = $modulePath; + } + + /** + * @return mixed + */ + public function getModulePath() + { + return $this->modulePath; + } + + /** + * @return ModuleDescriptorValidator|null + */ + public function getModuleDescriptor() + { + return $this->moduleDescriptor; + } + + /** + * @return ModuleDefinition|null + */ + public function getModuleDefinition() + { + return $this->moduleDefinition; + } + + /** + * @return mixed + */ + public function getModuleVersion() + { + return $this->moduleVersion; + } + + + /** + * @return array + */ + public function getErrors() + { + return $this->errors; + } + + protected function trans($id, array $parameters = []) + { + if (null === $this->translator) { + try { + $this->translator = Translator::getInstance(); + } catch (\RuntimeException $e) { + return strtr($id, $parameters); + } + } + + return $this->translator->trans($id, $parameters); + } + + /** + * Validate a module, checks : + * + * - version of Thelia + * - modules dependencies + * + * @param bool $checkCurrentVersion if true it will also check if the module is + * already installed (not activated - present in module list) + */ + public function validate($checkCurrentVersion = true) + { + if (null === $this->moduleDescriptor) { + throw new \Exception( + $this->trans( + "The %name module definition has not been initialized.", + [ '%name' => $this->moduleDirName ] + ) + ); + } + + $this->checkVersion(); + + if (true === $checkCurrentVersion) { + $this->checkModuleVersion(); + } + + $this->checkModuleDependencies(); + $this->checkModulePropelSchema(); + } + + protected function checkDirectoryStructure() + { + if (false === file_exists($this->modulePath)) { + throw new FileNotFoundException( + $this->trans( + "Module %name directory doesn't exists.", + [ '%name' => $this->moduleDirName] + ) + ); + } + + $path = sprintf("%s/Config/module.xml", $this->modulePath); + if (false === file_exists($path)) { + throw new FileNotFoundException( + $this->trans( + "Module %name should have a module.xml in the Config directory.", + [ '%name' => $this->moduleDirName] + ) + ); + } + + $path = sprintf("%s/Config/config.xml", $this->modulePath); + if (false === file_exists($path)) { + throw new FileNotFoundException( + $this->trans( + "Module %name should have a config.xml in the Config directory.", + [ '%name' => $this->moduleDirName] + ) + ); + } + } + + protected function loadModuleDescriptor() + { + $path = sprintf("%s/Config/module.xml", $this->modulePath); + + $descriptorValidator = new ModuleDescriptorValidator(); + + try { + // validation with xsd + $this->moduleDescriptor = $descriptorValidator->getDescriptor($path); + $this->moduleVersion = $descriptorValidator->getModuleVersion(); + } catch (InvalidXmlDocumentException $ex) { + throw $ex; + } + } + + public function loadModuleDefinition() + { + if (null === $this->moduleDescriptor) { + throw new \Exception( + $this->trans( + "The %name module descriptor has not been initialized.", + [ '%name' => $this->moduleDirName ] + ) + ); + } + + $moduleDefinition = new ModuleDefinition(); + + // Try to guess the proper module name, using the descriptor information. + $fullnamespace = trim((string)$this->moduleDescriptor->fullnamespace); + + $namespaceComponents = explode("\\", $fullnamespace); + + if (! isset($namespaceComponents[0]) || empty($namespaceComponents[0])) { + throw new ModuleException( + $this->trans( + "Unable to get module code from the fullnamespace element of the module descriptor: '%val'", + [ + '%name' => $this->moduleDirName, + '%val' => $fullnamespace + ] + ) + ); + } + + // Assume the module code is the first component of the declared namespace + $moduleDefinition->setCode($namespaceComponents[0]); + $moduleDefinition->setNamespace($fullnamespace); + $moduleDefinition->setVersion((string)$this->moduleDescriptor->version); + + $this->getModuleLanguages($moduleDefinition); + + $this->getModuleDescriptives($moduleDefinition); + + $this->getModuleDependencies($moduleDefinition); + + $this->getModuleAuthors($moduleDefinition); + + $moduleDefinition->setLogo((string)$this->moduleDescriptor->logo); + $moduleDefinition->setTheliaVersion((string)$this->moduleDescriptor->thelia); + $moduleDefinition->setType((string)$this->moduleDescriptor->type); + $moduleDefinition->setStability((string)$this->moduleDescriptor->stability); + + // documentation + $moduleDefinition->setDocumentation((string)$this->moduleDescriptor->documentation); + + $this->moduleDefinition = $moduleDefinition; + } + + public function checkModulePropelSchema() + { + $schemaFile = $this->getModulePath() . DS . "Config" . DS . "schema.xml"; + $fs = new Filesystem(); + + if ($fs->exists($schemaFile) === false) { + return; + } + + if (preg_match('//s', preg_replace('//', '', file_get_contents($schemaFile)))) { + throw new ModuleException( + "On Thelia version >= 2.4.0 the behavior \"versionnable\" is not available for modules, please remove this behavior from your module schema." + ); + } + } + + protected function checkVersion() + { + if ($this->moduleDefinition->getTheliaVersion()) { + if (!Version::test(Thelia::THELIA_VERSION, $this->moduleDefinition->getTheliaVersion(), false, ">=")) { + throw new ModuleException( + $this->trans( + "The module %name requires Thelia %version or newer", + [ + '%name' => $this->moduleDirName, + '%version' => $this->moduleDefinition->getTheliaVersion() + ] + ) + ); + } + } + } + + protected function checkModuleVersion() + { + $module = ModuleQuery::create() + ->findOneByFullNamespace($this->moduleDefinition->getNamespace()); + + if (null !== $module) { + if (version_compare($module->getVersion(), $this->moduleDefinition->getVersion(), '>=')) { + throw new ModuleException( + $this->trans( + "The module %name is already installed in the same or greater version.", + [ '%name' => $this->moduleDirName] + ) + ); + } + } + } + + protected function checkModuleDependencies() + { + $errors = []; + + foreach ($this->moduleDefinition->getDependencies() as $dependency) { + $module = ModuleQuery::create() + ->findOneByCode($dependency[0]); + + $pass = false; + + if (null !== $module) { + if ($module->getActivate() === BaseModule::IS_ACTIVATED) { + if ("" == $dependency[1] || Version::test($module->getVersion(), $dependency[1], false, ">=")) { + $pass = true; + } + } + } + + if (false === $pass) { + if ('' !== $dependency[1]) { + $errors[] = $this->trans( + '%module (version: %version)', + [ + '%module' => $dependency[0], + '%version' => $dependency[1] + ] + ); + } else { + $errors[] = sprintf('%s', $dependency[0]); + } + } + } + + if (\count($errors) > 0) { + $errorsMessage = $this->trans( + 'To activate module %name, the following modules should be activated first: %modules', + ['%name' => $this->moduleDirName, '%modules' => implode(', ', $errors)] + ); + + throw new ModuleException($errorsMessage); + } + } + + /** + * Get an array of modules that depend of the current module + * + * @param bool|null $active if true only search in activated module, false only deactivated and null on all modules + * @return array array of array with `code` which is the module code that depends of this current module and + * `version` which is the required version of current module + */ + public function getModulesDependOf($active = true) + { + $code = $this->getModuleDefinition()->getCode(); + $query = ModuleQuery::create(); + $dependantModules = []; + + if (true === $active) { + $query->findByActivate(1); + } elseif (false === $active) { + $query->findByActivate(0); + } + + $modules = $query->find(); + + /** @var Module $module */ + foreach ($modules as $module) { + try { + $validator = new ModuleValidator($module->getAbsoluteBaseDir()); + + $definition = $validator->getModuleDefinition(); + $dependencies = $definition->getDependencies(); + + if (\count($dependencies) > 0) { + foreach ($dependencies as $dependency) { + if ($dependency[0] == $code) { + $dependantModules[] = [ + 'code' => $definition->getCode(), + 'version' => $dependency[1] + ]; + + break; + } + } + } + } catch (\Exception $ex) { + ; + } + } + + return $dependantModules; + } + + /** + * Get the dependencies of this module. + * @param bool $recursive Whether to also get the dependencies of dependencies, their dependencies, and so on... + * @return array Array of dependencies as ["code" => ..., "version" => ...]. No check for duplicates is made. + */ + public function getCurrentModuleDependencies($recursive = false) + { + if (empty($this->moduleDescriptor->required)) { + return []; + } + + $dependencies = []; + foreach ($this->moduleDescriptor->required->module as $dependency) { + $dependencyArray = [ + "code" => (string)$dependency, + "version" => (string)$dependency['version'], + ]; + if (!\in_array($dependencyArray, $dependencies)) { + $dependencies[] = $dependencyArray; + } + + if ($recursive) { + $recursiveModuleValidator = new ModuleValidator(THELIA_MODULE_DIR . '/' . (string)$dependency); + array_merge( + $dependencies, + $recursiveModuleValidator->getCurrentModuleDependencies(true) + ); + } + } + + return $dependencies; + } + + /** + * @param ModuleDefinition $moduleDefinition + */ + protected function getModuleLanguages(ModuleDefinition $moduleDefinition) + { + $languages = []; + if ($this->getModuleVersion() != "1") { + foreach ($this->moduleDescriptor->languages->language as $language) { + $languages[] = (string)$language; + } + } + $moduleDefinition->setLanguages($languages); + } + + /** + * @param ModuleDefinition $moduleDefinition + */ + protected function getModuleDescriptives(ModuleDefinition $moduleDefinition) + { + $descriptives = []; + foreach ($this->moduleDescriptor->descriptive as $descriptive) { + $descriptives[(string)$descriptive['locale']] = [ + 'title' => (string)$descriptive->title, + 'subtitle' => (string)$descriptive->subtitle, + 'description' => (string)$descriptive->description, + 'postscriptum' => (string)$descriptive->postscriptum, + ]; + } + $moduleDefinition->setDescriptives($descriptives); + } + + /** + * @param ModuleDefinition $moduleDefinition + */ + protected function getModuleDependencies(ModuleDefinition $moduleDefinition) + { + $dependencies = []; + if (is_countable($this->moduleDescriptor->required) && 0 !== \count($this->moduleDescriptor->required)) { + foreach ($this->moduleDescriptor->required->module as $dependency) { + $dependencies[] = [ + (string)$dependency, + (string)$dependency['version'], + ]; + } + } + $moduleDefinition->setDependencies($dependencies); + } + + /** + * @param ModuleDefinition $moduleDefinition + */ + protected function getModuleAuthors(ModuleDefinition $moduleDefinition) + { + $authors = []; + + if (is_countable($this->moduleDescriptor->author) && 0 !== \count($this->moduleDescriptor->author)) { + foreach ($this->moduleDescriptor->author as $author) { + $authors[] = [ + (string)$author->name, + (string)$author->company, + (string)$author->email, + (string)$author->website + ]; + } + } else { + $authors = $this->getModuleAuthors22($moduleDefinition); + } + $moduleDefinition->setAuthors($authors); + } + + protected function getModuleAuthors22(ModuleDefinition $moduleDefinition) + { + $authors = []; + + if (!is_countable($this->moduleDescriptor->authors->author) + || 0 === \count($this->moduleDescriptor->authors->author) + ) { + return $authors; + } + + foreach ($this->moduleDescriptor->authors->author as $author) { + $authors[] = [ + (string)$author->name, + (string)$author->company, + (string)$author->email, + (string)$author->website + ]; + } + + return $authors; + } +} diff --git a/core/lib/Thelia/Module/schema/module/module-2_1.xsd b/core/lib/Thelia/Module/schema/module/module-2_1.xsd new file mode 100644 index 00000000..8c5c6ef0 --- /dev/null +++ b/core/lib/Thelia/Module/schema/module/module-2_1.xsd @@ -0,0 +1,159 @@ + + + + + + + + + The full namespace for the main class module (for example MyModule\MyModule) + + + + + Complete description, each description must be identify by ISO CODE 639 + + + + + + + + + + + + + + The path to the logo of the module (for example myModule.png). The recommended size is 128x128. + + + + + The folder that contains the images to deploy. + + + + + Module languages supported : fr_FR, en_US, ... + + + + + + + + + + + + + + + + Module version + + + + + Module author + + + + + + + + + + + + + module type : classic, delivery, payment, ... + + + + + + + + + + + + + + + + + + Module tags + + + + + + + + + + Plugins that should be presents. Plugins are identified by their codes and an optional minimal version + + + + + + + + + + + + + + + + + + minimum required version of Thelia in 'dot' format (for example 1.2.3.4) + + + + + current module stability: alpha, beta, rc, prod + + + + + + + + + + + + + + The name of the directory containing te documentation. + + + + + URL to test if a new version of the module exists. Will be called with two get parameters : module name, current version + + + + + URL to test if a new version of the module exists. Will be called with two get parameters : module name, current version + + + + + + \ No newline at end of file diff --git a/core/lib/Thelia/Module/schema/module/module-2_2.xsd b/core/lib/Thelia/Module/schema/module/module-2_2.xsd new file mode 100644 index 00000000..1c5705c4 --- /dev/null +++ b/core/lib/Thelia/Module/schema/module/module-2_2.xsd @@ -0,0 +1,187 @@ + + + + + + + + + The full namespace for the main class module (for example MyModule\MyModule) + + + + + Complete description, each description must be identify by ISO CODE 639 + + + + + + + + + + + + + + The path to the logo of the module (for example myModule.png). The recommended size is 128x128. + + + + + The folder that contains the images to deploy. + + + + + Module languages supported : fr_FR, en_US, ... + + + + + + + + + + + + + + + + Module version + + + + + Module authors + + + + + + + + + + + + + + + + + + + module type : classic, delivery, payment, ... + + + + + + + + + + + + + + + + + + Module tags + + + + + + + + + + Plugins that should be presents. Plugins are identified by their codes and an optional minimal version + + + + + + + + + + + + + + + + + + minimum required version of Thelia in 'dot' format (for example 1.2.3.4) + + + + + current module stability: alpha, beta, rc, prod + + + + + + + + + + + + + + The name of the directory containing te documentation. + + + + + URL to test if a new version of the module exists. Will be called with two get parameters : module name, current version + + + + + URL to test if a new version of the module exists. Will be called with two get parameters : module name, current version + + + + + Flag for protected module + + + + + + + + + + + Flag for visible module + + + + + + + + + + + + \ No newline at end of file diff --git a/core/lib/Thelia/Module/schema/module/module.xsd b/core/lib/Thelia/Module/schema/module/module.xsd new file mode 100644 index 00000000..7336c751 --- /dev/null +++ b/core/lib/Thelia/Module/schema/module/module.xsd @@ -0,0 +1,110 @@ + + + + + + + + The full namespace for the main class module (for example MyModule\MyModule) + + + + + complete description, each description must be identify by ISO CODE 639 + + + + + + + + + + + + + + Module version + + + + + Module author + + + + + + + + + + + + + module type : classic, delivery, payment + + + + + + + + + + + + Les plugins qui doivent déjà être présents + + + + + + + + + + + + + + + + + + minimum required version of Thelia in 'dot' format (for example 1.2.3.4) + + + + + + + + + + current module stability: alpha, beta, rc, prod + + + + + + + + + + + + + + Le nom du fichier contenant la documentation. Ce fichier doit se trouver dans le répertoire du plugin. + + + + + L'URL a interroger pour vérifier la présence d'une nouvelle version, appellé avec le nom du plugin et sa version + + + + + + \ No newline at end of file diff --git a/core/lib/Thelia/Rewriting/RewritingResolver.php b/core/lib/Thelia/Rewriting/RewritingResolver.php new file mode 100644 index 00000000..7bc1863d --- /dev/null +++ b/core/lib/Thelia/Rewriting/RewritingResolver.php @@ -0,0 +1,83 @@ + + * + * This class provides methods to resolve rewritten URL as a query + */ +class RewritingResolver +{ + protected $search = null; + protected $rewritingUrlQuery = null; + + public $view; + public $viewId; + public $locale; + public $otherParameters; + public $redirectedToUrl; + public $rewrittenUrl; + + public function __construct($url = null) + { + $this->rewritingUrlQuery = new RewritingUrlQuery(); + + if ($url !== null) { + $this->load($url); + } + } + + public function load($rewrittenUrl) + { + $rewrittenUrl = ltrim($rewrittenUrl, '/'); + $rewrittenUrl = urldecode($rewrittenUrl); + $this->rewrittenUrl = $rewrittenUrl; + $this->search = $this->rewritingUrlQuery->getResolverSearch($rewrittenUrl); + + if ($this->search->count() == 0) { + throw new UrlRewritingException('URL NOT FOUND', UrlRewritingException::URL_NOT_FOUND); + } + + $this->view = $this->search->getFirst()->getVirtualColumn('ru_view'); + $this->viewId = $this->search->getFirst()->getVirtualColumn('ru_viewId'); + $this->locale = $this->search->getFirst()->getVirtualColumn('ru_locale'); + $this->redirectedToUrl = $this->search->getFirst()->getVirtualColumn('ru_redirected_to_url'); + + $this->otherParameters = $this->getOtherParameters(); + } + + protected function getOtherParameters() + { + if ($this->search === null) { + throw new UrlRewritingException('RESOLVER NULL SEARCH', UrlRewritingException::RESOLVER_NULL_SEARCH); + } + + $otherParameters = array(); + foreach ($this->search as $result) { + $parameter = $result->getParameter(); + $value = $result->getValue(); + + if (null !== $parameter) { + $otherParameters[$parameter] = $value; + } + } + + return $otherParameters; + } +} diff --git a/core/lib/Thelia/Rewriting/RewritingRetriever.php b/core/lib/Thelia/Rewriting/RewritingRetriever.php new file mode 100644 index 00000000..6691cfbf --- /dev/null +++ b/core/lib/Thelia/Rewriting/RewritingRetriever.php @@ -0,0 +1,104 @@ + + * + * This class provides methods to retrieve a rewritten URL from a query + */ +class RewritingRetriever +{ + protected $search = null; + protected $rewritingUrlQuery = null; + + public $url; + public $rewrittenUrl; + + public function __construct($view = null, $viewLocale = null, $viewId = null) + { + $this->rewritingUrlQuery = new RewritingUrlQuery(); + + if ($view !== null && $viewLocale !== null) { + $this->load($view, $viewLocale, $viewId); + } + } + + /** + * @param $view + * @param $viewLocale + * @param null $viewId + */ + public function loadViewUrl($view, $viewLocale = null, $viewId = null) + { + $this->search = $this->rewritingUrlQuery->getViewUrlQuery($view, $viewLocale, $viewId); + + $allParametersWithoutView = array(); + if (null !== $viewLocale) { + $allParametersWithoutView['lang'] = $viewLocale; + } + if (null !== $viewId) { + $allParametersWithoutView[$view . '_id'] = $viewId; + } + + $this->rewrittenUrl = null; + $this->url = URL::getInstance()->viewUrl($view, $allParametersWithoutView); + if ($this->search !== null) { + $this->rewrittenUrl = URL::getInstance()->absoluteUrl( + $this->search->getUrl() + ); + } + } + + /** + * @param $view + * @param $viewLocale + * @param null $viewId + * @param array $viewOtherParameters + */ + public function loadSpecificUrl($view, $viewLocale, $viewId = null, $viewOtherParameters = array()) + { + if (empty($viewOtherParameters)) { + $this->loadViewUrl($view, $viewLocale, $viewId); + + return; + } + + $this->search = $this->rewritingUrlQuery->getSpecificUrlQuery($view, $viewLocale, $viewId, $viewOtherParameters); + + $allParametersWithoutView = $viewOtherParameters; + $allParametersWithoutView['lang'] = $viewLocale; + if (null !== $viewId) { + $allParametersWithoutView[$view . '_id'] = $viewId; + } + + $this->rewrittenUrl = null; + $this->url = URL::getInstance()->viewUrl($view, $allParametersWithoutView); + if ($this->search !== null) { + $this->rewrittenUrl = $this->search->getUrl(); + } + } + + /** + * @return mixed + */ + public function toString() + { + return $this->rewrittenUrl === null ? $this->url : $this->rewrittenUrl; + } +} diff --git a/core/lib/Thelia/TaxEngine/BaseTaxType.php b/core/lib/Thelia/TaxEngine/BaseTaxType.php new file mode 100644 index 00000000..eaf20e15 --- /dev/null +++ b/core/lib/Thelia/TaxEngine/BaseTaxType.php @@ -0,0 +1,130 @@ + + * + */ +abstract class BaseTaxType +{ + /** + * A var <-> value array which contains TaxtType requirements (e.g. parameters) + * + * @var array + */ + protected $requirements = array(); + + /** + * For a price percent tax type, return the percentage (e.g. 20 for 20%) of the product price + * to use in tax calculation. + * + * For other tax types, this method shoud return 0. + * + * @return number + */ + public function pricePercentRetriever() + { + return 0; + } + + /** + * For constant amount tax type, return the absolute amount to use in tax calculation. + * + * For other tax types, this method shoud return 0. + * + * @return number + */ + public function fixAmountRetriever(Product $product) + { + return 0; + } + + /** + * Returns the requirements definition of this tax type. This is an array of + * TaxTypeRequirementDefinition, which defines the name and the type of + * the requirements. Example : + * + * array( + * 'percent' => new FloatType() + * ); + * + * @return array of TaxTypeRequirementDefinition + */ + public function getRequirementsDefinition() + { + return array(); + } + + /** + * @return the name of this tax type. + */ + abstract public function getTitle(); + + public function calculate(Product $product, $untaxedPrice) + { + return $untaxedPrice * $this->pricePercentRetriever() + $this->fixAmountRetriever($product); + } + + /** + * @throws TaxEngineException + * @return array Return the requirements array. + */ + public function getRequirements() + { + return $this->requirements; + } + + public function loadRequirements($requirementsValues) + { + $requirements = $this->getRequirementsDefinition(); + + if (!\is_array($requirements)) { + throw new TaxEngineException('getRequirementsDefinition must return an array', TaxEngineException::TAX_TYPE_BAD_ABSTRACT_METHOD); + } + + foreach ($requirements as $requirement) { + $requirementName = $requirement->getName(); + + if (! array_key_exists($requirementName, $requirementsValues)) { + throw new TaxEngineException('Cannot load requirements : requirement value for `' . $requirementName . '` not found', TaxEngineException::TAX_TYPE_REQUIREMENT_NOT_FOUND); + } + + if (! $requirement->isValueValid($requirementsValues[$requirementName])) { + throw new TaxEngineException('Requirement value for `' . $requirementName . '` does not match required type', TaxEngineException::TAX_TYPE_BAD_REQUIREMENT_VALUE); + } + + $this->requirements[$requirementName] = $requirementsValues[$requirementName]; + } + } + + public function setRequirement($key, $value) + { + $this->requirements[$key] = $value; + + return $this; + } + + public function getRequirement($key) + { + if (!array_key_exists($key, $this->requirements)) { + throw new TaxEngineException('Requirement value for `' . $key . '` does not exists in BaseTaxType::$requirements', TaxEngineException::UNDEFINED_REQUIREMENT_VALUE); + } + + return $this->requirements[$key]; + } +} diff --git a/core/lib/Thelia/TaxEngine/Calculator.php b/core/lib/Thelia/TaxEngine/Calculator.php new file mode 100644 index 00000000..ff2d5033 --- /dev/null +++ b/core/lib/Thelia/TaxEngine/Calculator.php @@ -0,0 +1,403 @@ + + * @author Franck Allimant + * @author Vincent Lopes + */ +class Calculator +{ + /** + * @var TaxRuleQuery + */ + protected $taxRuleQuery; + + /** + * @var null|\Propel\Runtime\Collection\ObjectCollection + */ + protected $taxRulesCollection; + + protected $product; + protected $country; + protected $state; + + public function __construct() + { + $this->taxRuleQuery = new TaxRuleQuery(); + } + + /** + * @param Cart $cart + * @param Country $country + * @param State|null $state + * + * @return float + * @throws \Propel\Runtime\Exception\PropelException + */ + public static function getUntaxedCartDiscount(Cart $cart, Country $country, State $state = null) + { + return $cart->getDiscount() / self::getCartTaxFactor($cart, $country, $state); + } + + /** + * @param Cart $cart + * @param Country $country + * @param State|null $state + * + * @return float|int + * @throws \Propel\Runtime\Exception\PropelException + */ + /** + * @param Order $order + * @return float + * @throws \Propel\Runtime\Exception\PropelException + */ + public static function getUntaxedOrderDiscount(Order $order) + { + return $order->getDiscount() / self::getOrderTaxFactor($order); + } + + /** + * @param Order $order + * @return float + * @throws \Propel\Runtime\Exception\PropelException + */ + public static function getOrderTaxFactor(Order $order) + { + // Cache the result in a local variable + static $orderTaxFactor; + + if (null === $orderTaxFactor) { + if ((float)$order->getDiscount() === 0.0) { + return 1; + } + + // Find the average Tax rate (see \Thelia\TaxEngine\Calculator::getCartTaxFactor()) + $orderTaxFactors = []; + + /** @var \Thelia\Model\OrderProduct $orderProduct */ + foreach ($order->getOrderProducts() as $orderProduct) { + /** @var \Thelia\Core\Template\Loop\OrderProductTax $orderProductTax */ + foreach ($orderProduct->getOrderProductTaxes() as $orderProductTax) { + $orderTaxFactors[] = 1 + $orderProductTax->getAmount() / $orderProduct->getPrice(); + } + } + + if (0 === $orderTaxfactorCount = count($orderTaxFactors)) { + return 1; + } + + $orderTaxFactor = array_sum($orderTaxFactors) / count($orderTaxFactors); + } + + return $orderTaxFactor; + } + + /** + * @param Cart $cart + * @param Country $country + * @param State|null $state + * + * @return float + * @throws \Propel\Runtime\Exception\PropelException + */ + public static function getCartTaxFactor(Cart $cart, Country $country, State $state = null) + { + // Cache the result in a local variable + static $cartFactor; + + if (null === $cartFactor) { + if ((float)$cart->getDiscount() === 0.0) { + return 1; + } + + $cartItems = $cart->getCartItems(); + + // Get the average of tax factor to apply it to the discount + $cartTaxFactors = []; + + /** @var CartItem $cartItem */ + foreach ($cartItems as $cartItem) { + $taxRulesCollection = TaxRuleQuery::create()->getTaxCalculatorCollection($cartItem->getProduct()->getTaxRule(), $country, $state); + /** @var TaxRule $taxRule */ + foreach ($taxRulesCollection as $taxRule) { + $cartTaxFactors[] = 1 + $taxRule->getTypeInstance()->pricePercentRetriever(); + } + } + + $cartFactor = array_sum($cartTaxFactors) / count($cartTaxFactors); + } + + return $cartFactor; + } + + /** + * @param Product $product + * @param Country $country + * @param State|null $state + * @return $this + * @throws \Propel\Runtime\Exception\PropelException + */ + public function load(Product $product, Country $country, State $state = null) + { + if ($product->getId() === null) { + throw new TaxEngineException('Product id is empty in Calculator::load', TaxEngineException::UNDEFINED_PRODUCT); + } + if ($country->getId() === null) { + throw new TaxEngineException('Country id is empty in Calculator::load', TaxEngineException::UNDEFINED_COUNTRY); + } + + $this->product = $product; + $this->country = $country; + $this->state = $state; + + $this->taxRulesCollection = $this->taxRuleQuery->getTaxCalculatorCollection($product->getTaxRule(), $country, $state); + + return $this; + } + + /** + * @param TaxRule $taxRule + * @param Country $country + * @param Product $product + * @param State|null $state + * @return $this + * @throws \Propel\Runtime\Exception\PropelException + */ + public function loadTaxRule(TaxRule $taxRule, Country $country, Product $product, State $state = null) + { + if ($taxRule->getId() === null) { + throw new TaxEngineException('TaxRule id is empty in Calculator::loadTaxRule', TaxEngineException::UNDEFINED_TAX_RULE); + } + if ($country->getId() === null) { + throw new TaxEngineException('Country id is empty in Calculator::loadTaxRule', TaxEngineException::UNDEFINED_COUNTRY); + } + if ($product->getId() === null) { + throw new TaxEngineException('Product id is empty in Calculator::load', TaxEngineException::UNDEFINED_PRODUCT); + } + + $this->country = $country; + $this->product = $product; + $this->state = $state; + + $this->taxRulesCollection = $this->taxRuleQuery->getTaxCalculatorCollection($taxRule, $country, $state); + + return $this; + } + + /** + * @param TaxRule $taxRule + * @param Product $product + * @return $this + * @throws \Propel\Runtime\Exception\PropelException + */ + public function loadTaxRuleWithoutCountry(TaxRule $taxRule, Product $product) + { + $this->product = null; + $this->taxRulesCollection = null; + + if ($taxRule->getId() === null) { + throw new TaxEngineException('TaxRule id is empty in Calculator::loadTaxRule', TaxEngineException::UNDEFINED_TAX_RULE); + } + if ($product->getId() === null) { + throw new TaxEngineException('Product id is empty in Calculator::load', TaxEngineException::UNDEFINED_PRODUCT); + } + + $this->product = $product; + + $this->taxRulesCollection = $this->taxRuleQuery->getTaxCalculatorCollection($taxRule); + + return $this; + } + + /** + * @param TaxRule $taxRule + * @param Country $country + * @param State|null $state + * @return $this + * @throws \Propel\Runtime\Exception\PropelException + * @since 2.4 + */ + public function loadTaxRuleWithoutProduct(TaxRule $taxRule, Country $country, State $state = null) + { + if ($taxRule->getId() === null) { + throw new TaxEngineException('TaxRule id is empty in Calculator::loadTaxRule', TaxEngineException::UNDEFINED_TAX_RULE); + } + if ($country->getId() === null) { + throw new TaxEngineException('Country id is empty in Calculator::loadTaxRule', TaxEngineException::UNDEFINED_COUNTRY); + } + + $this->country = $country; + $this->product = new Product(); + $this->state = $state; + + $this->taxRulesCollection = $this->taxRuleQuery->getTaxCalculatorCollection($taxRule, $country, $state); + + return $this; + } + + /** + * @param $untaxedPrice + * @param null $taxCollection + * @return float + * @throws \Propel\Runtime\Exception\PropelException + */ + public function getTaxAmountFromUntaxedPrice($untaxedPrice, &$taxCollection = null) + { + return $this->getTaxedPrice($untaxedPrice, $taxCollection) - $untaxedPrice; + } + + /** + * @param $taxedPrice + * @return float + */ + public function getTaxAmountFromTaxedPrice($taxedPrice) + { + return $taxedPrice - $this->getUntaxedPrice($taxedPrice); + } + + /** + * @param float $untaxedPrice + * @param OrderProductTaxCollection|null $taxCollection returns OrderProductTaxCollection + * @param string|null $askedLocale + * @return float + * @throws \Propel\Runtime\Exception\PropelException + */ + public function getTaxedPrice($untaxedPrice, &$taxCollection = null, $askedLocale = null) + { + if (null === $this->taxRulesCollection) { + throw new TaxEngineException('Tax rules collection is empty in Calculator::getTaxedPrice', TaxEngineException::UNDEFINED_TAX_RULES_COLLECTION); + } + + if (null === $this->product) { + throw new TaxEngineException('Product is empty in Calculator::getTaxedPrice', TaxEngineException::UNDEFINED_PRODUCT); + } + + if (false === filter_var($untaxedPrice, FILTER_VALIDATE_FLOAT)) { + throw new TaxEngineException('BAD AMOUNT FORMAT', TaxEngineException::BAD_AMOUNT_FORMAT); + } + + $taxedPrice = $untaxedPrice; + $currentPosition = 1; + $currentTax = 0; + + if (null !== $taxCollection) { + $taxCollection = new OrderProductTaxCollection(); + } + + /** @var Tax $taxRule */ + foreach ($this->taxRulesCollection as $taxRule) { + $position = (int) $taxRule->getTaxRuleCountryPosition(); + + /** @var BaseTaxType $taxType */ + $taxType = $taxRule->getTypeInstance(); + + if ($currentPosition !== $position) { + $taxedPrice += $currentTax; + $currentTax = 0; + $currentPosition = $position; + } + + $taxAmount = $taxType->calculate($this->product, $taxedPrice); + $currentTax += $taxAmount; + + if (null !== $taxCollection) { + /** @var TaxI18n $taxI18n */ + $taxI18n = I18n::forceI18nRetrieving($askedLocale, 'Tax', $taxRule->getId()); + + $orderProductTax = (new OrderProductTax()) + ->setTitle($taxI18n->getTitle()) + ->setDescription($taxI18n->getDescription()) + ->setAmount($taxAmount) + ; + + $taxCollection->addTax($orderProductTax); + } + } + + $taxedPrice += $currentTax; + + return $taxedPrice; + } + + /** + * @param $taxedPrice + * @return float|int|number + */ + public function getUntaxedPrice($taxedPrice) + { + if (null === $this->taxRulesCollection) { + throw new TaxEngineException('Tax rules collection is empty in Calculator::getTaxAmount', TaxEngineException::UNDEFINED_TAX_RULES_COLLECTION); + } + + if (null === $this->product) { + throw new TaxEngineException('Product is empty in Calculator::getTaxedPrice', TaxEngineException::UNDEFINED_PRODUCT); + } + + if (false === filter_var($taxedPrice, FILTER_VALIDATE_FLOAT)) { + throw new TaxEngineException('BAD AMOUNT FORMAT', TaxEngineException::BAD_AMOUNT_FORMAT); + } + + $taxRule = $this->taxRulesCollection->getLast(); + + if (null === $taxRule) { + throw new TaxEngineException('Tax rules collection got no tax ', TaxEngineException::NO_TAX_IN_TAX_RULES_COLLECTION); + } + + $untaxedPrice = $taxedPrice; + $currentPosition = (int) $taxRule->getTaxRuleCountryPosition(); + $currentFixTax = 0; + $currentTaxFactor = 0; + + do { + $position = (int) $taxRule->getTaxRuleCountryPosition(); + + /** @var BaseTaxType $taxType */ + $taxType = $taxRule->getTypeInstance(); + + if ($currentPosition !== $position) { + $untaxedPrice -= $currentFixTax; + $untaxedPrice /= (1 + $currentTaxFactor); + $currentFixTax = 0; + $currentTaxFactor = 0; + $currentPosition = $position; + } + + $currentFixTax += $taxType->fixAmountRetriever($this->product); + $currentTaxFactor += $taxType->pricePercentRetriever(); + } while ($taxRule = $this->taxRulesCollection->getPrevious()); + + $untaxedPrice -= $currentFixTax; + $untaxedPrice /= (1 + $currentTaxFactor); + + return $untaxedPrice; + } +} diff --git a/core/lib/Thelia/TaxEngine/OrderProductTaxCollection.php b/core/lib/Thelia/TaxEngine/OrderProductTaxCollection.php new file mode 100644 index 00000000..72d790b3 --- /dev/null +++ b/core/lib/Thelia/TaxEngine/OrderProductTaxCollection.php @@ -0,0 +1,116 @@ + + * + */ +class OrderProductTaxCollection implements \Iterator +{ + private $position; + protected $taxes = array(); + + public function __construct() + { + foreach (\func_get_args() as $tax) { + $this->addTax($tax); + } + } + + public function isEmpty() + { + return \count($this->taxes) == 0; + } + + /** + * @param OrderProductTax $tax + * + * @return OrderProductTaxCollection + */ + public function addTax(OrderProductTax $tax) + { + $this->taxes[] = $tax; + + return $this; + } + + public function getCount() + { + return \count($this->taxes); + } + + /** + * (PHP 5 >= 5.0.0)
    + * Return the current element + * @link http://php.net/manual/en/iterator.current.php + * @return OrderProductTax + */ + public function current() + { + return $this->taxes[$this->position]; + } + + /** + * (PHP 5 >= 5.0.0)
    + * Move forward to next element + * @link http://php.net/manual/en/iterator.next.php + * @return void Any returned value is ignored. + */ + public function next() + { + $this->position++; + } + + /** + * (PHP 5 >= 5.0.0)
    + * Return the key of the current element + * @link http://php.net/manual/en/iterator.key.php + * @return mixed scalar on success, or null on failure. + */ + public function key() + { + return $this->position; + } + + /** + * (PHP 5 >= 5.0.0)
    + * Checks if current position is valid + * @link http://php.net/manual/en/iterator.valid.php + * @return boolean The return value will be casted to boolean and then evaluated. + * Returns true on success or false on failure. + */ + public function valid() + { + return isset($this->taxes[$this->position]); + } + + /** + * (PHP 5 >= 5.0.0)
    + * Rewind the Iterator to the first element + * @link http://php.net/manual/en/iterator.rewind.php + * @return void Any returned value is ignored. + */ + public function rewind() + { + $this->position = 0; + } + + public function getKey($key) + { + return isset($this->taxes[$key]) ? $this->taxes[$key] : null; + } +} diff --git a/core/lib/Thelia/TaxEngine/TaxEngine.php b/core/lib/Thelia/TaxEngine/TaxEngine.php new file mode 100644 index 00000000..b8109c86 --- /dev/null +++ b/core/lib/Thelia/TaxEngine/TaxEngine.php @@ -0,0 +1,174 @@ + + */ +class TaxEngine +{ + protected $taxCountry = null; + protected $taxState = null; + protected $typeList = null; + + protected $taxTypesDirectories = array(); + + /** @var RequestStack */ + protected $requestStack; + + public function __construct(RequestStack $requestStack) + { + $this->requestStack = $requestStack; + + // Intialize the defaults Tax Types + $this->taxTypesDirectories['Thelia\\TaxEngine\\TaxType'] = __DIR__ . DS . "TaxType"; + } + + /** + * Add a directroy which contains tax types classes. The tax engine + * will scan this directory, and add all the tax type classes. + * + * @param string $namespace the namespace of the classes in the directory + * @param string $path_to_tax_type_classes the path to the directory + */ + public function addTaxTypeDirectory($namespace, $path_to_tax_type_classes) + { + $this->taxTypesDirectories[$namespace] = $path_to_tax_type_classes; + } + + /** + * Add a tax type to the current list. + * + * @param unknown $fullyQualifiedclassName the fully qualified classname, su chas MyTaxes\Taxes\MyTaxType + * + */ + public function addTaxType($fullyQualifiedclassName) + { + $this->typeList[] = $fullyQualifiedclassName; + } + + public function getTaxTypeList() + { + if ($this->typeList === null) { + $this->typeList = array(); + + foreach ($this->taxTypesDirectories as $namespace => $directory) { + try { + $directoryIterator = new \DirectoryIterator($directory); + + foreach ($directoryIterator as $fileinfo) { + if ($fileinfo->isFile()) { + $extension = $fileinfo->getExtension(); + if (strtolower($extension) !== 'php') { + continue; + } + $className = $fileinfo->getBaseName('.php'); + + try { + $fullyQualifiedClassName = "$namespace\\$className"; + + $instance = new $fullyQualifiedClassName; + + if ($instance instanceof BaseTaxType) { + $this->addTaxType(\get_class($instance)); + } + } catch (\Exception $ex) { + // Nothing special to do + } + } + } + } catch (\UnexpectedValueException $e) { + // Nothing special to do + } + } + } + + return $this->typeList; + } + + /** + * Find Tax Country Id + * First look for a picked delivery address country + * Then look at the current customer default address country + * Else look at the default website country + + * @return null|Country + */ + public function getDeliveryCountry() + { + if (null === $this->taxCountry) { + /* is there a logged in customer ? */ + /** @var Customer $customer */ + if (null !== $customer = $this->getSession()->getCustomerUser()) { + if (null !== $this->getSession()->getOrder() + && null !== $this->getSession()->getOrder()->getChoosenDeliveryAddress() + && null !== $currentDeliveryAddress = AddressQuery::create()->findPk($this->getSession()->getOrder()->getChoosenDeliveryAddress())) { + $this->taxCountry = $currentDeliveryAddress->getCountry(); + $this->taxState = $currentDeliveryAddress->getState(); + } else { + $customerDefaultAddress = $customer->getDefaultAddress(); + if (isset($customerDefaultAddress)) { + $this->taxCountry = $customerDefaultAddress->getCountry(); + $this->taxState = $customerDefaultAddress->getState(); + } + } + } + + if (null == $this->taxCountry) { + $this->taxCountry = CountryQuery::create()->findOneByByDefault(1); + $this->taxState = null; + } + } + + return $this->taxCountry; + } + + /** + * Find Tax State Id + * + * First look for a picked delivery address state + * Then look at the current customer default address state + * Else null + + * @return null|State + * @since 2.3.0-alpha1 + */ + public function getDeliveryState() + { + if (null === $this->taxCountry) { + /* is there a logged in customer ? */ + $this->getDeliveryCountry(); + } + + return $this->taxState; + } + + /** + * @return Session + */ + protected function getSession() + { + return $this->requestStack->getCurrentRequest()->getSession(); + } +} diff --git a/core/lib/Thelia/TaxEngine/TaxType/FeatureFixAmountTaxType.php b/core/lib/Thelia/TaxEngine/TaxType/FeatureFixAmountTaxType.php new file mode 100644 index 00000000..2c0b312c --- /dev/null +++ b/core/lib/Thelia/TaxEngine/TaxType/FeatureFixAmountTaxType.php @@ -0,0 +1,88 @@ + + * + */ +class FeatureFixAmountTaxType extends BaseTaxType +{ + public function setFeature($featureId) + { + $this->setRequirement('feature', $featureId); + + return $this; + } + + public function fixAmountRetriever(Product $product) + { + $taxAmount = 0; + $featureId = $this->getRequirement("feature"); + + $query = FeatureProductQuery::create() + ->filterByProduct($product) + ->filterByFeatureId($featureId) + ->findOne(); + + if (null !== $query) { + if (\is_null($query->getFeatureAvId())) { + $taxAmount = $query->getFreeTextValue(); //BC for old behavior + } else { + $locale = LangQuery::create()->findPk($this->getRequirement('lang'))->getLocale(); + $taxAmount = $query->getFeatureAv()->setLocale($locale)->getTitle(); + } + + $testFloat = new FloatType(); + if (!$testFloat->isValid($taxAmount)) { + //We cannot modify "bad" (consider uninitialized) feature value in backOffice if we throw exception + Tlog::getInstance()->error(Translator::getInstance()->trans('Feature value does not match FLOAT format')); + return 0; + } + } + + return $taxAmount; + } + + public function getRequirementsDefinition() + { + return array( + new TaxTypeRequirementDefinition( + 'feature', + new ModelValidIdType('Feature'), + Translator::getInstance()->trans("Feature") + ), + new TaxTypeRequirementDefinition( + 'lang', + new ModelValidIdType('Lang'), + Translator::getInstance()->trans('Language') + ), + ); + } + + public function getTitle() + { + return Translator::getInstance()->trans("Constant amount found in one of the product's feature"); + } +} diff --git a/core/lib/Thelia/TaxEngine/TaxType/FixAmountTaxType.php b/core/lib/Thelia/TaxEngine/TaxType/FixAmountTaxType.php new file mode 100644 index 00000000..31221727 --- /dev/null +++ b/core/lib/Thelia/TaxEngine/TaxType/FixAmountTaxType.php @@ -0,0 +1,54 @@ + + * + */ +class FixAmountTaxType extends BaseTaxType +{ + public function setAmount($amount) + { + $this->setRequirement('amount', $amount); + + return $this; + } + + public function fixAmountRetriever(\Thelia\Model\Product $product) + { + return $this->getRequirement("amount"); + } + + public function getRequirementsDefinition() + { + return array( + new TaxTypeRequirementDefinition( + 'amount', + new FloatType(), + Translator::getInstance()->trans("Amount") + ) + ); + } + + public function getTitle() + { + return Translator::getInstance()->trans("Constant amount"); + } +} diff --git a/core/lib/Thelia/TaxEngine/TaxType/PricePercentTaxType.php b/core/lib/Thelia/TaxEngine/TaxType/PricePercentTaxType.php new file mode 100644 index 00000000..0a855065 --- /dev/null +++ b/core/lib/Thelia/TaxEngine/TaxType/PricePercentTaxType.php @@ -0,0 +1,54 @@ + + * + */ +class PricePercentTaxType extends BaseTaxType +{ + public function setPercentage($percent) + { + $this->setRequirement('percent', $percent); + + return $this; + } + + public function pricePercentRetriever() + { + return ($this->getRequirement("percent") * 0.01); + } + + public function getRequirementsDefinition() + { + return array( + new TaxTypeRequirementDefinition( + 'percent', + new FloatType(), + Translator::getInstance()->trans("Percent") + ) + ); + } + + public function getTitle() + { + return Translator::getInstance()->trans("Percentage of the product price"); + } +} diff --git a/core/lib/Thelia/TaxEngine/TaxTypeRequirementDefinition.php b/core/lib/Thelia/TaxEngine/TaxTypeRequirementDefinition.php new file mode 100644 index 00000000..e52f6787 --- /dev/null +++ b/core/lib/Thelia/TaxEngine/TaxTypeRequirementDefinition.php @@ -0,0 +1,71 @@ + + */ +class TaxTypeRequirementDefinition +{ + /** + * @var string The requirement name + */ + protected $name; + + /** + * @var TypeInterface The requirement type + */ + protected $type; + + /** + * @var string The translated requirement title + */ + protected $title; + + /** + * Create a new Tax type requirement + * + * @param string $name the name of the requirement + * @param TypeInterface $type the type of the data + */ + public function __construct($name, TypeInterface $type, $title = null) + { + $this->name = $name; + $this->type = $type; + $this->title = $title ?: $name; + } + + public function getName() + { + return $this->name; + } + + public function getType() + { + return $this->type; + } + + public function getTitle() + { + return $this->title; + } + + public function isValueValid($value) + { + return $this->type->isValid($value); + } +} diff --git a/core/lib/Thelia/Tools/AddressFormat.php b/core/lib/Thelia/Tools/AddressFormat.php new file mode 100644 index 00000000..a8b3237e --- /dev/null +++ b/core/lib/Thelia/Tools/AddressFormat.php @@ -0,0 +1,231 @@ + + */ +class AddressFormat +{ + private static $instance; + + private function __construct() + { + } + + /** + * @return $this + */ + public static function getInstance() + { + if (!isset(self::$instance)) { + self::$instance = new AddressFormat(); + } + + return self::$instance; + } + + + /** + * Format an address + * + * @param AddressInterface $address + * @param null $locale + * @param bool $html + * @param string $htmlTag + * @param array $htmlAttributes + * @return string + */ + public function format( + AddressInterface $address, + $locale = null, + $html = true, + $htmlTag = "p", + $htmlAttributes = [] + ) { + $locale = $this->normalizeLocale($locale); + + $addressFormatRepository = new AddressFormatRepository(); + $countryRepository = new CountryRepository(); + $subdivisionRepository = new SubdivisionRepository(); + + $formatter = new DefaultFormatter( + $addressFormatRepository, + $countryRepository, + $subdivisionRepository, + $locale + ); + + $formatter->setOption('html', $html); + $formatter->setOption('html_tag', $htmlTag); + $formatter->setOption('html_attributes', $htmlAttributes); + + + $addressFormatted = $formatter->format($address); + + return $addressFormatted; + } + + /** + * Format a Thelia address (Address or OrderAddress) + * + * @param \Thelia\Model\OrderAddress|OrderAddress $address + * @param null $locale + * @param bool $html + * @param string $htmlTag + * @param array $htmlAttributes + * @return string + */ + public function formatTheliaAddress($address, $locale = null, $html = true, $htmlTag = "p", $htmlAttributes = []) + { + $address = $this->mapTheliaAddress($address, $locale); + return $this->format($address, $locale, $html, $htmlTag, $htmlAttributes); + } + + /** + * Format an address to a postal label + * + * @param AddressInterface $address + * @param null $locale + * @param null $originCountry + * @param array $options + * @return string + */ + public function postalLabelFormat(AddressInterface $address, $locale = null, $originCountry = null, $options = []) + { + $locale = $this->normalizeLocale($locale); + + $addressFormatRepository = new AddressFormatRepository(); + $countryRepository = new CountryRepository(); + $subdivisionRepository = new SubdivisionRepository(); + + if (null === $originCountry) { + $countryId = Country::getShopLocation(); + if (null === $country = CountryQuery::create()->findPk($countryId)) { + $country = Country::getDefaultCountry(); + } + + $originCountry = $country->getIsoalpha2(); + } + + $formatter = new PostalLabelFormatter( + $addressFormatRepository, + $countryRepository, + $subdivisionRepository, + $originCountry, + $locale, + $options + ); + + $addressFormatted = $formatter->format($address); + + return $addressFormatted; + } + + /** + * Format a Thelia address (Address or OrderAddress) to a postal label + * + * @param \Thelia\Model\OrderAddress|OrderAddress $address + * @param null $locale + * @param null $originCountry + * @param array $options + * @return string + */ + public function postalLabelFormatTheliaAddress($address, $locale = null, $originCountry = null, $options = []) + { + $address = $this->mapTheliaAddress($address, $locale); + return $this->postalLabelFormat($address, $locale, $originCountry, $options); + } + + /** + * Convert a Thelia address (Address or OrderAddress) to ImmutableAddressInterface + * + * @param \Thelia\Model\OrderAddress|OrderAddress $address + * @return Address|\CommerceGuys\Addressing\Model\ImmutableAddressInterface + */ + protected function mapTheliaAddress($address, $locale = null) + { + $country = $address->getCountry(); + if (null === $locale) { + $locale = Lang::getDefaultLanguage()->getLocale(); + } + $customerTitle = $address->getCustomerTitle() + ->setLocale($this->denormalizeLocale($locale)) + ->getShort() + ; + + $addressModel = new Address(); + $addressModel = $addressModel + ->withCountryCode($country->getIsoalpha2()) + ->withAddressLine1($address->getAddress1()) + ->withAddressLine2($address->getAddress2()) + ->withPostalCode($address->getZipcode()) + ->withLocality($address->getCity()) + ->withOrganization($address->getCompany()) + ->withRecipient( + sprintf( + '%s %s %s', + $customerTitle, + $address->getLastname(), + $address->getFirstname() + ) + ) + ; + + + if ($country->getHasStates() && \intval($address->getStateId()) !== 0) { + $addressModel = $addressModel->withAdministrativeArea( + sprintf( + '%s-%s', + $country->getIsoalpha2(), + $address->getState()->getIsocode() + ) + ); + } + + return $addressModel; + } + + private function normalizeLocale($locale) + { + if (null !== $locale) { + $locale = str_replace('_', '-', $locale); + } + + return $locale; + } + + private function denormalizeLocale($locale) + { + if (null !== $locale) { + $locale = str_replace('-', '_', $locale); + } + + return $locale; + } +} diff --git a/core/lib/Thelia/Tools/DateTimeFormat.php b/core/lib/Thelia/Tools/DateTimeFormat.php new file mode 100644 index 00000000..d0ef0ce1 --- /dev/null +++ b/core/lib/Thelia/Tools/DateTimeFormat.php @@ -0,0 +1,54 @@ +request = $request; + } + + public static function getInstance(Request $request) + { + return new DateTimeFormat($request); + } + + public function getFormat($output = null) + { + $lang = $this->request->getSession()->getLang(); + + $format = null; + + if ($lang) { + switch ($output) { + case "date": + $format = $lang->getDateFormat(); + break; + case "time": + $format = $lang->getTimeFormat(); + break; + default: + case "datetime": + $format = $lang->getDateTimeFormat(); + break; + } + } + + return $format; + } +} diff --git a/core/lib/Thelia/Tools/FileDownload/FileDownloader.php b/core/lib/Thelia/Tools/FileDownload/FileDownloader.php new file mode 100644 index 00000000..e8448401 --- /dev/null +++ b/core/lib/Thelia/Tools/FileDownload/FileDownloader.php @@ -0,0 +1,145 @@ + + */ +class FileDownloader implements FileDownloaderInterface +{ + /** @var LoggerInterface */ + protected $logger; + + /** @var Translator */ + protected $translator; + + public function __construct(LoggerInterface $logger, Translator $translator) + { + $this->logger = $logger; + + $this->translator = $translator; + } + + public static function getInstance() + { + return new static(Tlog::getInstance(), TheliaTranslator::getInstance()); + } + + /** + * @param string $url + * @param string $pathToStore + * @throws \Thelia\Exception\FileNotFoundException + * @throws \ErrorException + * @throws \HttpUrlException + * + * Downloads the file $url in $pathToStore + */ + public function download($url, $pathToStore) + { + if (!URL::checkUrl($url)) { + /** + * The URL is not valid + */ + throw new HttpUrlException( + $this->translator->trans( + "Tried to download a file, but the URL was not valid: %url", + [ + "%url" => $url + ] + ) + ); + } + + /** + * Try to get the file if it is online + */ + $con = curl_init($url); + curl_setopt($con, CURLOPT_RETURNTRANSFER, true); + curl_setopt($con, CURLOPT_FOLLOWLOCATION, true); + + $response = curl_exec($con); + $errno = curl_errno($con); + $curlErrorMessage = curl_error($con); + + $httpCode = curl_getinfo($con, CURLINFO_HTTP_CODE); + + curl_close($con); + + if (false === $response || $errno !== 0 || + ($httpCode != "200" && $httpCode != "204") + ) { + /** + * The server is down ? The file doesn't exist ? Anything else ? + */ + $errorMessage = $this->translator->trans( + "cURL errno %errno, http code %http_code on link \"%path\": %error", + [ + "%errno" => $errno, + "%path" => $url, + "%error" => $curlErrorMessage, + "%http_code" => $httpCode, + ] + ); + + $this->logger + ->error($errorMessage) + ; + + throw new FileNotFoundException($errorMessage); + } + + /** + * Inform that you've downloaded a file + */ + $this->logger + ->info( + $this->translator->trans( + "The file %path has been successfully downloaded", + [ + "%path" => $url + ] + ) + ) + ; + + /** + * Then try to write it on the disk + */ + $file = @fopen($pathToStore, "w"); + + if ($file === false) { + $translatedErrorMessage = $this->translator->trans( + "Failed to open a writing stream on the file: %file", + [ + "%file" => $pathToStore + ] + ); + + $this->logger->error($translatedErrorMessage); + throw new \ErrorException($translatedErrorMessage); + } + + fputs($file, $response); + fclose($file); + } +} diff --git a/core/lib/Thelia/Tools/FileDownload/FileDownloaderAwareTrait.php b/core/lib/Thelia/Tools/FileDownload/FileDownloaderAwareTrait.php new file mode 100644 index 00000000..78347bdd --- /dev/null +++ b/core/lib/Thelia/Tools/FileDownload/FileDownloaderAwareTrait.php @@ -0,0 +1,47 @@ + + */ +trait FileDownloaderAwareTrait +{ + /** @var FileDownloaderInterface */ + protected $fileDownloader; + + /** + * @return FileDownloaderInterface + */ + public function getFileDownloader() + { + if (!$this->fileDownloader instanceof FileDownloaderInterface) { + $this->fileDownloader = FileDownloader::getInstance(); + } + + return $this->fileDownloader; + } + + /** + * @param FileDownloaderInterface $fileDownloader + * @return $this + */ + public function setFileDownloader(FileDownloaderInterface $fileDownloader) + { + $this->fileDownloader = $fileDownloader; + + return $this; + } +} diff --git a/core/lib/Thelia/Tools/FileDownload/FileDownloaderInterface.php b/core/lib/Thelia/Tools/FileDownload/FileDownloaderInterface.php new file mode 100644 index 00000000..4c29daf2 --- /dev/null +++ b/core/lib/Thelia/Tools/FileDownload/FileDownloaderInterface.php @@ -0,0 +1,43 @@ + + */ +interface FileDownloaderInterface +{ + /** + * @param string $url + * @param string $pathToStore + * @throws \Thelia\Exception\FileNotFoundException + * @throws \ErrorException + * @throws \HttpUrlException + * + * Downloads the file $url in $pathToStore + */ + public function download($url, $pathToStore); + + public function __construct(LoggerInterface $logger, Translator $translator); + + /** + * @return $this + * + * Returns an hydrated instance + */ + public static function getInstance(); +} diff --git a/core/lib/Thelia/Tools/I18n.php b/core/lib/Thelia/Tools/I18n.php new file mode 100644 index 00000000..006e2436 --- /dev/null +++ b/core/lib/Thelia/Tools/I18n.php @@ -0,0 +1,142 @@ + + * + */ +class I18n +{ + protected static $defaultLocale; + + /** + * Create a \DateTime from a date picker form input + * The date format is the same as the one from the current User Session + * Ex : $lang = $session->getLang() + * + * @param Lang $lang Object containing date format + * @param string $date String to convert + * + * @return \DateTime + */ + public function getDateTimeFromForm(Lang $lang, $date) + { + $currentDateFormat = $lang->getDateFormat(); + + return \DateTime::createFromFormat($currentDateFormat, $date); + } + + public static function forceI18nRetrieving($askedLocale, $modelName, $id, $needed = array('Title')) + { + $i18nQueryClass = sprintf("\\Thelia\\Model\\%sI18nQuery", $modelName); + $i18nClass = sprintf("\\Thelia\\Model\\%sI18n", $modelName); + + /* get customer language translation */ + $i18n = $i18nQueryClass::create() + ->filterById($id) + ->filterByLocale( + $askedLocale + )->findOne(); + /* or default translation */ + if (null === $i18n) { + $i18n = $i18nQueryClass::create() + ->filterById($id) + ->filterByLocale( + Lang::getDefaultLanguage()->getLocale() + )->findOne(); + } + if (null === $i18n) { + // @todo something else ? + $i18n = new $i18nClass(); + ; + $i18n->setId($id); + foreach ($needed as $need) { + $method = sprintf('set%s', $need); + if (method_exists($i18n, $method)) { + $i18n->$method('DEFAULT ' . strtoupper($need)); + } else { + // @todo throw sg ? + } + } + } + + return $i18n; + } + + public static function addI18nCondition( + ModelCriteria $query, + $i18nTableName, + $tableIdColumn, + $i18nIdColumn, + $localeColumn, + $locale + ) { + if (null === static::$defaultLocale) { + static::$defaultLocale = Lang::getDefaultLanguage()->getLocale(); + } + + $locale = static::realEscape($locale); + $defaultLocale = static::realEscape(static::$defaultLocale); + + $query + ->_and() + ->where( + "CASE WHEN ".$tableIdColumn." IN". + "(SELECT DISTINCT ".$i18nIdColumn." ". + "FROM `".$i18nTableName."` ". + "WHERE locale=$locale) ". + "THEN ".$localeColumn." = $locale ". + "ELSE ".$localeColumn." = $defaultLocale ". + "END" + ) + ; + } + + /** + * @param $str + * @return string + * + * Really escapes a string for SQL query. + */ + public static function realEscape($str) + { + $str = trim($str, "\"'"); + + $return = "CONCAT("; + $len = \strlen($str); + + for ($i = 0; $i < $len; ++$i) { + $return .= "CHAR(".ord($str[$i])."),"; + } + + if ($i > 0) { + $return = substr($return, 0, -1); + } else { + $return = "\"\""; + } + $return .= ")"; + + return $return; + } +} diff --git a/core/lib/Thelia/Tools/Image.php b/core/lib/Thelia/Tools/Image.php new file mode 100644 index 00000000..15f934f9 --- /dev/null +++ b/core/lib/Thelia/Tools/Image.php @@ -0,0 +1,32 @@ +preFormat($number, $decimals, $decPoint, $thousandsSep, $removeZeroDecimal); + + if ($symbol !== null) { + return $number . ' ' . $symbol; + } + + return $number; + } + + /** + * @since 2.3 + * @param float $number + * @param int $decimals + * @param string $decPoint + * @param string $thousandsSep + * @param int|null $currencyId + * @param boolean $removeZeroDecimal + * @return string + */ + public function formatByCurrency( + $number, + $decimals = null, + $decPoint = null, + $thousandsSep = null, + $currencyId = null, + $removeZeroDecimal = false + ) { + $number = $this->preFormat($number, $decimals, $decPoint, $thousandsSep, $removeZeroDecimal); + + $currency = $currencyId !== null ? CurrencyQuery::create()->findPk($currencyId) : $this->request->getSession()->getCurrency(); + + if ($currency !== null && strpos($currency->getFormat(), '%n') !== false) { + return str_replace( + ['%n', '%s', '%c'], + [$number, $currency->getSymbol(), $currency->getCode()], + $currency->getFormat() + ); + } + + return $number; + } + + /** + * @param $number + * @param null $decimals + * @param null $decPoint + * @param null $thousandsSep + * @param bool $removeZeroDecimal + * + * @return string + */ + protected function preFormat( + $number, + $decimals = null, + $decPoint = null, + $thousandsSep = null, + $removeZeroDecimal = false + ) + { + $number = preg_replace('/\s+/', '', $number); + + if ($removeZeroDecimal === true) { + if($number == (int)$number) { + $number = \intval($number); + } + } + + return parent::format($number, $decimals, $decPoint, $thousandsSep); + } +} diff --git a/core/lib/Thelia/Tools/NumberFormat.php b/core/lib/Thelia/Tools/NumberFormat.php new file mode 100644 index 00000000..a54d1323 --- /dev/null +++ b/core/lib/Thelia/Tools/NumberFormat.php @@ -0,0 +1,65 @@ +request = $request; + } + + public static function getInstance(Request $request) + { + return new NumberFormat($request); + } + + /** + * Get a standard number, with '.' as decimal point and no thousands separator + * so that this number can be used to perform calculations. + * + * @param float $number the number + * @param string $decimals number of decimal figures + * @return string + */ + public function formatStandardNumber($number, $decimals = null) + { + $lang = $this->request->getSession()->getLang(); + + if ($decimals === null) { + $decimals = $lang->getDecimals(); + } + + return number_format($number, $decimals, '.', ''); + } + + public function format($number, $decimals = null, $decPoint = null, $thousandsSep = null) + { + $lang = $this->request->getSession()->getLang(); + + if ($decimals === null) { + $decimals = $lang->getDecimals(); + } + if ($decPoint === null) { + $decPoint = $lang->getDecimalSeparator(); + } + if ($thousandsSep === null) { + $thousandsSep = $lang->getThousandsSeparator(); + } + return number_format($number, $decimals, $decPoint, $thousandsSep); + } +} diff --git a/core/lib/Thelia/Tools/Password.php b/core/lib/Thelia/Tools/Password.php new file mode 100644 index 00000000..2aadb292 --- /dev/null +++ b/core/lib/Thelia/Tools/Password.php @@ -0,0 +1,54 @@ + + */ +class Password +{ + private static function randgen($letter, $length) + { + $string = ""; + do { + $string .= substr(str_shuffle($letter), 0, 1); + } while (\strlen($string) < $length); + + return $string; + } + + /** + * generate a Random password with defined length + * + * @param int $length + * @return mixed + */ + public static function generateRandom($length = 8) + { + $letter = "abcdefghijklmnopqrstuvwxyz"; + $letter .= "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + $letter .= "0123456789"; + + return self::randgen($letter, $length); + } + + public static function generateHexaRandom($length = 8) + { + $letter = "ABCDEF"; + $letter .= "0123456789"; + + return self::randgen($letter, $length); + } +} diff --git a/core/lib/Thelia/Tools/RememberMeTrait.php b/core/lib/Thelia/Tools/RememberMeTrait.php new file mode 100644 index 00000000..ec54598a --- /dev/null +++ b/core/lib/Thelia/Tools/RememberMeTrait.php @@ -0,0 +1,62 @@ + + */ +trait RememberMeTrait +{ + /** + * Get the remember me key from the cookie. + * + * @return string hte key found, or null if no key was found. + */ + protected function getRememberMeKeyFromCookie(Request $request, $cookieName) + { + $ctp = new CookieTokenProvider(); + + return $ctp->getKeyFromCookie($request, $cookieName); + } + + /** + * Create the remember me cookie for the given user. + */ + protected function createRememberMeCookie(UserInterface $user, $cookieName, $cookieExpiration) + { + $ctp = new CookieTokenProvider(); + + $ctp->createCookie( + $user, + $cookieName, + $cookieExpiration + ); + } + + /** + * Clear the remember me cookie. + */ + protected function clearRememberMeCookie($cookieName) + { + $ctp = new CookieTokenProvider(); + + $ctp->clearCookie($cookieName); + } +} diff --git a/core/lib/Thelia/Tools/Rest/ResponseRest.php b/core/lib/Thelia/Tools/Rest/ResponseRest.php new file mode 100644 index 00000000..c77f8592 --- /dev/null +++ b/core/lib/Thelia/Tools/Rest/ResponseRest.php @@ -0,0 +1,97 @@ +setContent($data); + } + + $this->headers->set('Content-Type', 'text/plain'); + } else { + $this->format = $format; + $serializer = $this->getSerializer(); + + if (isset($data)) { + $this->setContent($serializer->serialize($data, $this->format)); + } + + $this->headers->set('Content-Type', 'application/' . $this->format); + } + } + + /** + * Set Content to be serialized in the response, array or object + * + * @param array $data array or object to be serialized + * + * @return $this + */ + public function setRestContent($data) + { + $serializer = $this->getSerializer(); + + if (isset($data)) { + $this->setContent($serializer->serialize($data, $this->format)); + } + + return $this; + } + + /** + * Get Serializer + * + * @return Serializer + */ + protected function getSerializer() + { + $encoders = array(new XmlEncoder(), new JsonEncoder()); + $normalizers = array(new GetSetMethodNormalizer()); + + return new Serializer($normalizers, $encoders); + } +} diff --git a/core/lib/Thelia/Tools/TokenProvider.php b/core/lib/Thelia/Tools/TokenProvider.php new file mode 100644 index 00000000..29a40925 --- /dev/null +++ b/core/lib/Thelia/Tools/TokenProvider.php @@ -0,0 +1,156 @@ + + */ +class TokenProvider +{ + /** + * @var string The stored token for this page + */ + protected $token; + + /** + * @var SessionInterface The session where the token is stored + */ + protected $session; + + /** + * @var RequestStack + */ + protected $requestStack; + + /** + * @var TranslatorInterface The translator + */ + protected $translator; + + /** + * @var string the current name of the token + */ + protected $tokenName; + + /** + * @param RequestStack $requestStack + * @param TranslatorInterface $translator + * @param $tokenName + */ + public function __construct(RequestStack $requestStack, TranslatorInterface $translator, $tokenName) + { + /** + * Store the services + */ + $this->requestStack = $requestStack; + $this->session = $this->requestStack->getCurrentRequest()->getSession(); + $this->translator = $translator; + $this->tokenName = $tokenName; + + $this->token = $this->session->get($this->tokenName); + } + + /** + * @return string + */ + public function assignToken() + { + if (null === $this->token) { + $this->token = $this->getToken(); + + $this->session->set($this->tokenName, $this->token); + } + + return $this->token; + } + + /** + * @param string $entryValue + * @return bool + * @throws \Thelia\Core\Security\Exception\TokenAuthenticationException + */ + public function checkToken($entryValue) + { + if (null === $this->token) { + throw new TokenAuthenticationException( + "Tried to check a token without assigning it before" + ); + } elseif ($this->token !== $entryValue) { + throw new TokenAuthenticationException( + "Tried to validate an invalid token" + ); + } + + return true; + } + + protected function refreshToken() + { + $this->token = null; + $this->assignToken(); + } + + /** + * @return string + */ + public function getToken() + { + return self::generateToken(); + } + + /** + * Same method as getToken but can be called statically + * + * @alias getToken + * @return string + */ + public static function generateToken() + { + $raw = self::getOpenSSLRandom(); + if (false === $raw) { + $raw = self::getComplexRandom(); + } + return md5($raw); + } + + /** + * @param int $length + * @return string + */ + protected static function getOpenSSLRandom($length = 40) + { + if (!function_exists("openssl_random_pseudo_bytes")) { + return false; + } + + return openssl_random_pseudo_bytes($length); + } + + /** + * @return string + */ + protected static function getComplexRandom() + { + $firstValue = (float) (mt_rand(1, 0xFFFF) * rand(1, 0x10001)); + $secondValues = (float) (rand(1, 0xFFFF) * mt_rand(1, 0x10001)); + + return microtime() . ceil($firstValue / $secondValues) . uniqid(); + } +} diff --git a/core/lib/Thelia/Tools/URL.php b/core/lib/Thelia/Tools/URL.php new file mode 100644 index 00000000..b23bf92c --- /dev/null +++ b/core/lib/Thelia/Tools/URL.php @@ -0,0 +1,357 @@ +container->get('thelia.url.manager'); + self::$instance = $this; + + if ($container !== null) { + $this->requestContext = $container->get('router.admin')->getContext(); + } + + $this->retriever = new RewritingRetriever(); + $this->resolver = new RewritingResolver(); + } + + /** + * @param RequestContext $requestContext + * @since Version 2.2 + */ + public function setRequestContext(RequestContext $requestContext) + { + $this->requestContext = $requestContext; + } + + /** + * Return this class instance, only once instanciated. + * + * @throws \RuntimeException if the class has not been instanciated. + * @return \Thelia\Tools\URL the instance. + */ + public static function getInstance() + { + if (self::$instance == null) { + throw new \RuntimeException("URL instance is not initialized."); + } + return self::$instance; + } + + /** + * Return the base URL, either the base_url defined in Config, or the URL + * of the current language, if 'one_domain_foreach_lang' is enabled. + * + * @param bool $scheme_only if true, only the scheme will be returned. If false, the complete base URL, including path, is returned. + * + * @return string the base URL, with a trailing '/' + */ + public function getBaseUrl($scheme_only = false) + { + if (null === $this->baseUrlScheme) { + $scheme = "http"; + $port = 80; + + if ($host = $this->requestContext->getHost()) { + $scheme = $this->requestContext->getScheme(); + + $port = ''; + + if ('http' === $scheme && 80 != $this->requestContext->getHttpPort()) { + $port = ':'.$this->requestContext->getHttpPort(); + } elseif ('https' === $scheme && 443 != $this->requestContext->getHttpsPort()) { + $port = ':'.$this->requestContext->getHttpsPort(); + } + } + + $this->baseUrlScheme = "$scheme://$host"."$port"; + } + + return $scheme_only ? $this->baseUrlScheme : $this->baseUrlScheme . $this->requestContext->getBaseUrl(); + } + + /** + * @return string the index page, which is in fact the base URL. + */ + public function getIndexPage() + { + // The index page is the base URL :) + return $this->getBaseUrl(); + } + + /** + * Returns the Absolute URL for a given path relative to web root. By default, + * the script name (index_dev.php) is added to the URL in dev_environment, use + * $path_only = true to get a path without the index script. + * + * @param string $path the relative path + * @param array $parameters An array of parameters + * @param boolean $path_only if true (PATH_TO_FILE), getIndexPage() will not be added + * @param string $alternateBaseUrl if not null, this URL is unsed instead of the base URL. Useful for creating CDN URLs + * + * @return string The generated URL + */ + public function absoluteUrl($path, array $parameters = null, $path_only = self::WITH_INDEX_PAGE, $alternateBaseUrl = null) + { + // Already absolute ? + if (substr($path, 0, 4) != 'http') { + if (empty($alternateBaseUrl)) { + // Prevent duplication of the subdirectory name when Thelia is installed in a subdirectory. + // This happens when $path was calculated with Router::generate(), which returns an absolute URL, + // starting at web server root. For example, if Thelia is installed in /thelia2, we got something like /thelia2/my/path + // As base URL also contains /thelia2 (e.g. http://some.server.com/thelia2), we end up with + // http://some.server.com/thelia2/thelia2/my/path, instead of http://some.server.com/thelia2/my/path + // We have to compensate for this. + $rcbu = $this->requestContext->getBaseUrl(); + + $hasSubdirectory = !empty($rcbu) && (0 === strpos($path, $rcbu)); + + $base_url = $this->getBaseUrl($hasSubdirectory); + } else { + $base_url = $alternateBaseUrl; + } + + // If only a path is requested, be sure to remove the script name (index.php or index_dev.php), if any. + if ($path_only == self::PATH_TO_FILE) { + if (substr($base_url, -3) == 'php') { + $base_url = dirname($base_url); + } + } + + // Normalize the given path + $base = rtrim($base_url, '/') . '/' . ltrim($path, '/'); + } else { + $base = $path; + } + + $base = str_replace('&', '&', $base); + + $queryString = ''; + $anchor = ''; + + if (! \is_null($parameters)) { + foreach ($parameters as $name => $value) { + // Remove this parameter from base URL to prevent duplicate parameters + $base = preg_replace('`([?&])'.preg_quote($name, '`').'=(?:[^&]*)(?:&|$)`', '$1', $base); + + $queryString .= sprintf("%s=%s&", urlencode($name), urlencode($value)); + } + } + + if ('' !== $queryString = rtrim($queryString, "&")) { + // url could contain anchor + $pos = strrpos($base, '#'); + if ($pos !== false) { + $anchor = substr($base, $pos); + $base = substr($base, 0, $pos); + } + + $base = rtrim($base, "?&"); + + $sepChar = strstr($base, '?') === false ? '?' : '&'; + + $queryString = $sepChar . $queryString; + } + + return $base . $queryString . $anchor; + } + + /** + * Returns the Absolute URL to a administration view + * + * @param string $viewName the view name (e.g. login for login.html) + * @param mixed $parameters An array of parameters + * + * @return string The generated URL + */ + public function adminViewUrl($viewName, array $parameters = array()) + { + $path = sprintf("%s/admin/%s", $this->getIndexPage(), $viewName); + + return $this->absoluteUrl($path, $parameters); + } + + /** + * Returns the Absolute URL to a view + * + * @param string $viewName the view name (e.g. login for login.html) + * @param mixed $parameters An array of parameters + * + * @return string The generated URL + */ + public function viewUrl($viewName, array $parameters = array()) + { + $path = sprintf("?view=%s", $viewName); + + return $this->absoluteUrl($path, $parameters); + } + + /** + * Retrieve a rewritten URL from a view, a view id and a locale + * + * @param $view + * @param $viewId + * @param $viewLocale + * + * @return RewritingRetriever You can access $url and $rewrittenUrl properties + */ + public function retrieve($view, $viewId, $viewLocale) + { + if (ConfigQuery::isRewritingEnable()) { + $this->retriever->loadViewUrl($view, $viewLocale, $viewId); + } else { + $allParametersWithoutView = array(); + $allParametersWithoutView['lang'] = $viewLocale; + if (null !== $viewId) { + $allParametersWithoutView[$view . '_id'] = $viewId; + } + $this->retriever->rewrittenUrl = null; + $this->retriever->url = URL::getInstance()->viewUrl($view, $allParametersWithoutView); + } + + return $this->retriever; + } + + /** + * Retrieve a rewritten URL from the current GET parameters + * + * @param Request $request + * + * @return RewritingRetriever You can access $url and $rewrittenUrl properties or use toString method + */ + public function retrieveCurrent(Request $request) + { + if (ConfigQuery::isRewritingEnable()) { + $view = $request->attributes->get('_view', null); + + $viewLocale = $this->getViewLocale($request); + + $viewId = $view === null ? null : $request->query->get($view . '_id', null); + + $allOtherParameters = $request->query->all(); + if ($view !== null) { + unset($allOtherParameters['view']); + if ($viewId !== null) { + unset($allOtherParameters[$view . '_id']); + } + } + if ($viewLocale !== null) { + unset($allOtherParameters['lang']); + unset($allOtherParameters['locale']); + } + + $this->retriever->loadSpecificUrl($view, $viewLocale, $viewId, $allOtherParameters); + } else { + $allParametersWithoutView = $request->query->all(); + $view = $request->attributes->get('_view'); + if (isset($allOtherParameters['view'])) { + unset($allOtherParameters['view']); + } + $this->retriever->rewrittenUrl = null; + $this->retriever->url = URL::getInstance()->viewUrl($view, $allParametersWithoutView); + } + + return $this->retriever; + } + + /** + * Retrieve a rewritten URL from the current GET parameters or use toString method + * + * @param $url + * + * @return RewritingResolver + */ + public function resolve($url) + { + $this->resolver->load($url); + + return $this->resolver; + } + + protected function sanitize($string, $force_lowercase = true, $alphabetic_only = false) + { + static $strip = array("~", "`", "!", "@", "#", "$", "%", "^", "&", "*", "(", ")", "_", "=", "+", "[", "{", "]", + "}", "\\", "|", ";", ":", "\"", "'", "‘", "’", "“", "”", "–", "—", + "—", "–", ",", "<", ".", ">", "/", "?"); + + $clean = trim(str_replace($strip, "", strip_tags($string))); + + $clean = preg_replace('/\s+/', "-", $clean); + + $clean = ($alphabetic_only) ? preg_replace("/[^a-zA-Z0-9]/", "", $clean) : $clean ; + + return ($force_lowercase) ? + (function_exists('mb_strtolower')) ? + mb_strtolower($clean, 'UTF-8') : + strtolower($clean) : + $clean; + } + + public static function checkUrl($url, array $protocols = ["http", "https"]) + { + $pattern = sprintf(UrlValidator::PATTERN, implode('|', $protocols)); + + return (bool) preg_match($pattern, $url); + } + + /** + * Get the locale code from the lang attribute in URL. + * + * @param Request $request + * @return null|string + */ + private function getViewLocale(Request $request) + { + $viewLocale = $request->query->get('lang', null); + if (null === $viewLocale) { + // fallback for old parameter + $viewLocale = $request->query->get('locale', null); + } + if (null === $viewLocale && null !== $request->getSession()) { + // fallback to session or default language + $viewLocale = $request->getSession()->getLang()->getLocale(); + } + + return $viewLocale; + } +} diff --git a/core/lib/Thelia/Tools/Version/Constraints/BaseConstraint.php b/core/lib/Thelia/Tools/Version/Constraints/BaseConstraint.php new file mode 100644 index 00000000..4decefa8 --- /dev/null +++ b/core/lib/Thelia/Tools/Version/Constraints/BaseConstraint.php @@ -0,0 +1,73 @@ + + */ +abstract class BaseConstraint implements ConstraintInterface +{ + protected $operator = "="; + + protected $expression = null; + + public function __construct($expression) + { + $this->expression = $expression; + } + + public function test($version, $strict = false) + { + $version = $this->normalize($version, $strict); + + return version_compare($version, $this->expression, $this->operator); + } + + public function normalize($version, $strict = false) + { + return $strict ? $version : $this->normalizePrecision($version); + } + + protected function normalizePrecision($version, $changeExpression = true) + { + $expressionElements = preg_split('/[\.\-]/', $this->expression); + // cleaning alpha RC beta + $version = preg_replace('/\-.*$/', '', $version); + $versionElements = preg_split('/\./', $version); + + if (\count($expressionElements) < \count($versionElements)) { + if (true === $changeExpression) { + $this->expression = implode( + '.', + array_merge( + $expressionElements, + array_fill( + \count($expressionElements) - 1, + \count($versionElements) - \count($expressionElements), + '0' + ) + ) + ); + } else { + $version = implode( + '.', + \array_slice($versionElements, 0, \count($expressionElements)) + ); + } + } + + return $version; + } +} diff --git a/core/lib/Thelia/Tools/Version/Constraints/ConstraintEqual.php b/core/lib/Thelia/Tools/Version/Constraints/ConstraintEqual.php new file mode 100644 index 00000000..80c91f6b --- /dev/null +++ b/core/lib/Thelia/Tools/Version/Constraints/ConstraintEqual.php @@ -0,0 +1,26 @@ + + */ +class ConstraintEqual extends BaseConstraint +{ + public function __construct($expression) + { + $this->expression = str_replace('=', '', $expression); + } +} diff --git a/core/lib/Thelia/Tools/Version/Constraints/ConstraintGreater.php b/core/lib/Thelia/Tools/Version/Constraints/ConstraintGreater.php new file mode 100644 index 00000000..c65af1ee --- /dev/null +++ b/core/lib/Thelia/Tools/Version/Constraints/ConstraintGreater.php @@ -0,0 +1,30 @@ + + */ +class ConstraintGreater extends BaseConstraint +{ + public function __construct($expression, $strict = false) + { + $this->operator = $strict ? ">" : ">="; + $this->expression = substr( + $expression, + \strlen($this->operator) + ); + } +} diff --git a/core/lib/Thelia/Tools/Version/Constraints/ConstraintInterface.php b/core/lib/Thelia/Tools/Version/Constraints/ConstraintInterface.php new file mode 100644 index 00000000..22ee7eab --- /dev/null +++ b/core/lib/Thelia/Tools/Version/Constraints/ConstraintInterface.php @@ -0,0 +1,38 @@ + + */ +interface ConstraintInterface +{ + /** + * Normalize a version number in a version that will be used in `version_compare` + * + * @param string $version the version expression + * @return string the normalized expression + */ + public function normalize($version, $strict = false); + + /** + * Test if the version number is valid + * + * @param string $version the version number + * @param bool $strict if false precision will be normalized. eg: 2.1.0 > 2.1 will become 2.1.0 > 2.1.0 (default false) + * @return bool true if the version is equal, otherwise false + */ + public function test($version, $strict = false); +} diff --git a/core/lib/Thelia/Tools/Version/Constraints/ConstraintLower.php b/core/lib/Thelia/Tools/Version/Constraints/ConstraintLower.php new file mode 100644 index 00000000..bd959956 --- /dev/null +++ b/core/lib/Thelia/Tools/Version/Constraints/ConstraintLower.php @@ -0,0 +1,30 @@ + + */ +class ConstraintLower extends BaseConstraint +{ + public function __construct($expression, $strict = false) + { + $this->operator = $strict ? "<" : "<="; + $this->expression = substr( + $expression, + \strlen($this->operator) + ); + } +} diff --git a/core/lib/Thelia/Tools/Version/Constraints/ConstraintNearlyEqual.php b/core/lib/Thelia/Tools/Version/Constraints/ConstraintNearlyEqual.php new file mode 100644 index 00000000..0156cb1c --- /dev/null +++ b/core/lib/Thelia/Tools/Version/Constraints/ConstraintNearlyEqual.php @@ -0,0 +1,35 @@ + + */ +class ConstraintNearlyEqual extends BaseConstraint +{ + public function __construct($expression) + { + $this->expression = str_replace('~', '', $expression); + } + + public function normalize($version, $strict = false) + { + if (!$strict) { + $version = $this->normalizePrecision($version, false); + } + + return $version; + } +} diff --git a/core/lib/Thelia/Tools/Version/Version.php b/core/lib/Thelia/Tools/Version/Version.php new file mode 100644 index 00000000..7ce93fdc --- /dev/null +++ b/core/lib/Thelia/Tools/Version/Version.php @@ -0,0 +1,134 @@ + + */ +class Version +{ + /** + * Test if a version matched the version contraints. + * + * constraints can be simple or complex (multiple constraints separated by space) : + * + * - "~2.1" : version 2.1.* + * - "~2.1 <=2.1.4" : version 2.1.* but lower or equal to 2.1.4 + * - ">=2.1" : version 2.1.*, 2.2, ... + * - ">2.1.1 <=2.1.5" : version greater than 2.1.1 but lower or equal than 2.1.5 + * - ... + * + * @param string $version the version to test + * @param string $constraints the versions constraints + * @param bool $strict if true 2.1 is different of 2.1.0, if false version are normalized so 2.1 + * will be expended to 2.1.0 + * @param string $defaultComparison the default comparison if nothing provided + * @return bool true if version matches the constraints + */ + public static function test($version, $constraints, $strict = false, $defaultComparison = "=") + { + $constraints = self::parseConstraints($constraints, $defaultComparison); + + /** @var ConstraintInterface $constraint */ + foreach ($constraints as $constraint) { + if (!$constraint->test($version, $strict)) { + return false; + } + } + + return true; + } + + private static function parseConstraints($constraints, $defaultComparison = "=") + { + $constraintsList = []; + + foreach (explode(" ", $constraints) as $expression) { + if (1 === preg_match('/^[0-9]/', $expression)) { + $expression = $defaultComparison . $expression; + } + + if (strpos($expression, '>=') !== false) { + $constraint = new ConstraintGreater($expression); + } elseif (strpos($expression, '>') !== false) { + $constraint = new ConstraintGreater($expression, true); + } elseif (strpos($expression, '<=') !== false) { + $constraint = new ConstraintLower($expression); + } elseif (strpos($expression, '<') !== false) { + $constraint = new ConstraintLower($expression, true); + } elseif (strpos($expression, '~') !== false) { + $constraint = new ConstraintNearlyEqual($expression); + } else { + $constraint = new ConstraintEqual($expression); + } + + $constraintsList[] = $constraint; + } + + return $constraintsList; + } + + /** + * Split a version into an associative array + * [version, major, minus, release, extra] + * + * @param string $version the version to split + * @return array associative array + * [ + * 'version' => 'digit', + * 'major' => 'digit', + * 'minus' => 'digit', + * 'release' => 'digit', + * 'extra' => 'alphanumeric' + * ] + */ + public static function parse($version = null) + { + if (\is_null($version)) { + $version = \Thelia\Core\Thelia::THELIA_VERSION; + } + + $pattern = "`^(? + (?[0-9]+)\. + (?[0-9]+)\. + (?[0-9]+) + -?(?[a-zA-Z0-9]*) # extra_version will also match empty string + )$`x"; + + if (!preg_match($pattern, $version, $match)) { + throw new \InvalidArgumentException( + sprintf( + "Invalid version number provided : %s".PHP_EOL, + $version + ) + ); + } + + return [ + 'version' => $match['version'], + 'major' => $match['major'], + 'minus' => $match['minus'], + 'release' => $match['release'], + 'extra' => $match['extra'], + ]; + } +} diff --git a/core/lib/Thelia/Type/AlphaNumStringListType.php b/core/lib/Thelia/Type/AlphaNumStringListType.php new file mode 100644 index 00000000..fb26efa3 --- /dev/null +++ b/core/lib/Thelia/Type/AlphaNumStringListType.php @@ -0,0 +1,53 @@ + + * + */ + +class AlphaNumStringListType extends BaseType +{ + public function getType() + { + return 'Alphanumeric string list type'; + } + + public function isValid($values) + { + foreach (explode(',', $values) as $value) { + if (!preg_match('#^[a-zA-Z0-9\-_\.]+$#', $value)) { + return false; + } + } + + return true; + } + + public function getFormattedValue($values) + { + return $this->isValid($values) ? explode(',', $values) : null; + } + + public function getFormType() + { + return 'text'; + } + + public function getFormOptions() + { + return array(); + } +} diff --git a/core/lib/Thelia/Type/AlphaNumStringType.php b/core/lib/Thelia/Type/AlphaNumStringType.php new file mode 100644 index 00000000..039f9795 --- /dev/null +++ b/core/lib/Thelia/Type/AlphaNumStringType.php @@ -0,0 +1,47 @@ + + * + */ + +class AlphaNumStringType extends BaseType +{ + public function getType() + { + return 'Alphanumeric string type'; + } + + public function isValid($value) + { + return preg_match('#^[a-zA-Z0-9\-_\.]+$#', $value) ? true : false; + } + + public function getFormattedValue($value) + { + return $this->isValid($value) ? $value : null; + } + + public function getFormType() + { + return 'text'; + } + + public function getFormOptions() + { + return array(); + } +} diff --git a/core/lib/Thelia/Type/AnyListType.php b/core/lib/Thelia/Type/AnyListType.php new file mode 100644 index 00000000..06399b31 --- /dev/null +++ b/core/lib/Thelia/Type/AnyListType.php @@ -0,0 +1,46 @@ + + */ +class AnyListType extends BaseType +{ + public function getType() + { + return 'Any list type'; + } + + public function isValid($values) + { + return false === empty($values); + } + + public function getFormattedValue($values) + { + return $this->isValid($values) ? explode(',', $values) : null; + } + + public function getFormType() + { + return 'text'; + } + + public function getFormOptions() + { + return array(); + } +} diff --git a/core/lib/Thelia/Type/AnyType.php b/core/lib/Thelia/Type/AnyType.php new file mode 100644 index 00000000..ddf2139e --- /dev/null +++ b/core/lib/Thelia/Type/AnyType.php @@ -0,0 +1,47 @@ + + * + */ + +class AnyType extends BaseType +{ + public function getType() + { + return 'Any type'; + } + + public function isValid($value) + { + return true; + } + + public function getFormattedValue($value) + { + return $value; + } + + public function getFormType() + { + return 'text'; + } + + public function getFormOptions() + { + return array(); + } +} diff --git a/core/lib/Thelia/Type/BaseType.php b/core/lib/Thelia/Type/BaseType.php new file mode 100644 index 00000000..562f382d --- /dev/null +++ b/core/lib/Thelia/Type/BaseType.php @@ -0,0 +1,49 @@ + + * + */ +abstract class BaseType implements TypeInterface +{ + abstract public function getType(); + + abstract public function isValid($value); + + abstract public function getFormattedValue($value); + + abstract public function getFormType(); + + abstract public function getFormOptions(); + + public function verifyForm($value, ExecutionContextInterface $context) + { + if (!$this->isValid($value)) { + $context->addViolation( + Translator::getInstance()->trans( + "received value `%value` does not match `%type` type", + [ + '%value' => $value, + '%type' => $this->getType() + ] + ) + ); + } + } +} diff --git a/core/lib/Thelia/Type/BooleanOrBothType.php b/core/lib/Thelia/Type/BooleanOrBothType.php new file mode 100644 index 00000000..9738df4e --- /dev/null +++ b/core/lib/Thelia/Type/BooleanOrBothType.php @@ -0,0 +1,53 @@ + + * + */ + +class BooleanOrBothType extends BaseType +{ + const ANY = '*'; + + public function getType() + { + return 'Boolean or both type'; + } + + public function isValid($value) + { + return $value === self::ANY || filter_var($value, FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE) !== null; + } + + public function getFormattedValue($value) + { + if ($value === self::ANY) { + return $value; + } + return $value === null ? null : filter_var($value, FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE); + } + + public function getFormType() + { + return 'text'; + } + + public function getFormOptions() + { + return array(); + } +} diff --git a/core/lib/Thelia/Type/BooleanType.php b/core/lib/Thelia/Type/BooleanType.php new file mode 100644 index 00000000..05be70bb --- /dev/null +++ b/core/lib/Thelia/Type/BooleanType.php @@ -0,0 +1,47 @@ + + * + */ + +class BooleanType extends BaseType +{ + public function getType() + { + return 'Boolean type'; + } + + public function isValid($value) + { + return filter_var($value, FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE) !== null; + } + + public function getFormattedValue($value) + { + return $value === null ? null : filter_var($value, FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE); + } + + public function getFormType() + { + return 'text'; + } + + public function getFormOptions() + { + return array(); + } +} diff --git a/core/lib/Thelia/Type/EnumListType.php b/core/lib/Thelia/Type/EnumListType.php new file mode 100644 index 00000000..8ca7ebdf --- /dev/null +++ b/core/lib/Thelia/Type/EnumListType.php @@ -0,0 +1,89 @@ + + * + */ + +class EnumListType extends BaseType +{ + protected $values = array(); + + public function __construct($values = array()) + { + if (\is_array($values)) { + $this->values = $values; + } + } + + public function addValue($value) + { + if (!\in_array($value, $this->values)) { + $this->values[] = $value; + } + } + + /** + * @param array|\Traversable $values + * @since 2.3.0 + */ + public function addValues($values) + { + if (!\is_array($values) && !$values instanceof \Traversable) { + throw new \InvalidArgumentException('$values must be an array or an instance of \Traversable'); + } + + foreach ($values as $value) { + $this->addValue($value); + } + } + + public function getType() + { + return 'Enum list type'; + } + + public function isValid($values) + { + foreach (explode(',', $values) as $value) { + if (!$this->isSingleValueValid($value)) { + return false; + } + } + + return true; + } + + public function getFormattedValue($values) + { + return $this->isValid($values) ? explode(',', $values) : null; + } + + public function isSingleValueValid($value) + { + return \in_array($value, $this->values); + } + + public function getFormType() + { + return 'text'; + } + + public function getFormOptions() + { + return array(); + } +} diff --git a/core/lib/Thelia/Type/EnumType.php b/core/lib/Thelia/Type/EnumType.php new file mode 100644 index 00000000..0088d7d2 --- /dev/null +++ b/core/lib/Thelia/Type/EnumType.php @@ -0,0 +1,56 @@ + + * + */ + +class EnumType extends BaseType +{ + protected $values = array(); + + public function __construct($values = array()) + { + if (\is_array($values)) { + $this->values = $values; + } + } + + public function getType() + { + return 'Enum type'; + } + + public function isValid($value) + { + return \in_array($value, $this->values); + } + + public function getFormattedValue($value) + { + return $this->isValid($value) ? $value : null; + } + + public function getFormType() + { + return 'text'; + } + + public function getFormOptions() + { + return array(); + } +} diff --git a/core/lib/Thelia/Type/FloatToFloatArrayType.php b/core/lib/Thelia/Type/FloatToFloatArrayType.php new file mode 100644 index 00000000..b60cb0b6 --- /dev/null +++ b/core/lib/Thelia/Type/FloatToFloatArrayType.php @@ -0,0 +1,57 @@ + + * + */ + +class FloatToFloatArrayType extends BaseType +{ + public function getType() + { + return 'Float key to float value array type'; + } + + public function isValid($value) + { + if (!\is_array($value)) { + return false; + } + + foreach ($value as $key => $val) { + if (filter_var($key, FILTER_VALIDATE_FLOAT) === false || filter_var($val, FILTER_VALIDATE_FLOAT) === false) { + return false; + } + } + + return true; + } + + public function getFormattedValue($value) + { + return $this->isValid($value) ? $value : null; + } + + public function getFormType() + { + return 'text'; + } + + public function getFormOptions() + { + return array(); + } +} diff --git a/core/lib/Thelia/Type/FloatType.php b/core/lib/Thelia/Type/FloatType.php new file mode 100644 index 00000000..63473119 --- /dev/null +++ b/core/lib/Thelia/Type/FloatType.php @@ -0,0 +1,47 @@ + + * + */ + +class FloatType extends BaseType +{ + public function getType() + { + return 'Float type'; + } + + public function isValid($value) + { + return filter_var($value, FILTER_VALIDATE_FLOAT) === false ? false : true; + } + + public function getFormattedValue($value) + { + return $this->isValid($value) ? $value : null; + } + + public function getFormType() + { + return 'text'; + } + + public function getFormOptions() + { + return array(); + } +} diff --git a/core/lib/Thelia/Type/IntListType.php b/core/lib/Thelia/Type/IntListType.php new file mode 100644 index 00000000..50f1bf3c --- /dev/null +++ b/core/lib/Thelia/Type/IntListType.php @@ -0,0 +1,53 @@ + + * + */ + +class IntListType extends BaseType +{ + public function getType() + { + return 'Int list type'; + } + + public function isValid($values) + { + foreach (explode(',', $values) as $value) { + if (filter_var($value, FILTER_VALIDATE_INT) === false) { + return false; + } + } + + return true; + } + + public function getFormattedValue($values) + { + return $this->isValid($values) ? explode(',', $values) : null; + } + + public function getFormType() + { + return 'text'; + } + + public function getFormOptions() + { + return array(); + } +} diff --git a/core/lib/Thelia/Type/IntToCombinedIntsListType.php b/core/lib/Thelia/Type/IntToCombinedIntsListType.php new file mode 100644 index 00000000..a58b66e0 --- /dev/null +++ b/core/lib/Thelia/Type/IntToCombinedIntsListType.php @@ -0,0 +1,127 @@ + + * + */ + +class IntToCombinedIntsListType extends BaseType +{ + public function getType() + { + return 'Int to combined ints list type'; + } + + public function isValid($values) + { + foreach (explode(',', $values) as $intToCombinedInts) { + $parts = explode(':', $intToCombinedInts); + if (\count($parts) != 2) { + return false; + } + if (filter_var($parts[0], FILTER_VALIDATE_INT) === false) { + return false; + } + + if (false === $this->checkLogicalFormat($parts[1])) { + return false; + } + } + + return true; + } + + public function getFormattedValue($values) + { + if ($this->isValid($values)) { + $return = []; + + $values = preg_replace('#[\s]#', '', $values); + foreach (explode(',', $values) as $intToCombinedInts) { + $parts = explode(':', $intToCombinedInts); + + $return[trim($parts[0])] = array( + "values" => preg_split("#(&|\|)#", preg_replace('#[\(\)]#', '', $parts[1])), + "expression" => $parts[1], + ); + } + + return $return; + } else { + return null; + } + } + + protected function checkLogicalFormat($string) + { + /* delete all spaces and parentheses */ + $noSpaceString = preg_replace('#[\s]#', '', $string); + $noParentheseString = preg_replace('#[\(\)]#', '', $noSpaceString); + + if (!preg_match('#^([0-9]+([\&\|][0-9]+)*|\*)$#', $noParentheseString)) { + return false; + } + + /* check parenteses use */ + $openingParenthesesCount = 0; + $closingParenthesesCount = 0; + + $length = \strlen($noSpaceString); + for ($i=0; $i< $length; $i++) { + $char = $noSpaceString[$i]; + if ($char == '(') { + /* must be : + * - after a &| or () or at the begining of expression + * - before a number or () + * must not be : + * - at the end of expression + */ + if (($i!=0 && !preg_match('#[\(\)\&\|]#', $noSpaceString[$i-1])) || !isset($noSpaceString[$i+1]) || !preg_match('#[\(\)0-9]#', $noSpaceString[$i+1])) { + return false; + } + $openingParenthesesCount++; + } elseif ($char == ')') { + /* must be : + * - after a number or () + * - before a &| or () or at the end of expression + * must not be : + * - at the begining of expression + * - if no ( remain unclose + */ + if ($i == 0 || !preg_match('#[\(\)0-9]#', $noSpaceString[$i-1]) || (isset($noSpaceString[$i+1]) && !preg_match('#[\(\)\&\|]#', $noSpaceString[$i+1])) || $openingParenthesesCount-$closingParenthesesCount==0) { + return false; + } + $closingParenthesesCount++; + } + } + + if ($openingParenthesesCount != $closingParenthesesCount) { + return false; + } + + return true; + } + + public function getFormType() + { + return 'text'; + } + + public function getFormOptions() + { + return array(); + } +} diff --git a/core/lib/Thelia/Type/IntToCombinedStringsListType.php b/core/lib/Thelia/Type/IntToCombinedStringsListType.php new file mode 100644 index 00000000..20e5b147 --- /dev/null +++ b/core/lib/Thelia/Type/IntToCombinedStringsListType.php @@ -0,0 +1,173 @@ +, Franck Allimant + */ +class IntToCombinedStringsListType extends BaseType +{ + public function getType() + { + return 'Int to combined strings list type'; + } + + public function isValid($values) + { + // Explode expession parts, ignoring escaped characters, (\, and \:) + foreach (preg_split('#(?checkLogicalFormat($parts[1])) { + return false; + } + } + + return true; + } + + public function getFormattedValue($values) + { + if ($this->isValid($values)) { + $return = []; + + foreach (preg_split('/(? array_map( + function ($item) { + return trim(self::unescape($item)); + }, + preg_split( + '#(? trim(self::unescape($parts[1])), + ); + } + + return $return; + } else { + return null; + } + } + + + /** + * Escape a string to use it safely in an expression. abc:def => abc\:def. + * Escapes characters are , : ( ) | & + * + * @param $string + * @return string + */ + public static function escape($string) + { + return preg_replace('/([,\:\(\)\|\&])/', '\\\$1', $string); + } + + /** + * Unescape a string and remove avai escape symbols. abc\:def => abc:def. + * + * @param $string + * @return string + */ + public static function unescape($string) + { + return preg_replace('/\\\([,\:\(\)\|\&])/', '\1', $string); + } + + protected function checkLogicalFormat($string) + { + // Delete escaped characters + $string = preg_replace('/\\\[,\:\(\)\|\&]/', '', $string); + + /* delete all spaces and parentheses */ + $noSpaceString = preg_replace('#[\s]#', '', $string); + $noParentheseString = preg_replace('#[\(\)]#', '', $noSpaceString); + + if (!preg_match('#^([a-zA-Z0-9_\-]+([\&\|][a-zA-Z0-9_\-]+)*|\*)$#', $noParentheseString)) { + return false; + } + + /* check parenteses use */ + $openingParenthesesCount = 0; + $closingParenthesesCount = 0; + + $length = \strlen($noSpaceString); + for ($i=0; $i< $length; $i++) { + $char = $noSpaceString[$i]; + if ($char == '(') { + /* must be : + * - after a &| or () or at the begining of expression + * - before a number or () + * must not be : + * - at the end of expression + */ + if (($i!=0 && !preg_match('#[\(\)\&\|]#', $noSpaceString[$i-1])) || !isset($noSpaceString[$i+1]) || !preg_match('#[\(\)a-zA-Z0-9_\-]#', $noSpaceString[$i+1])) { + return false; + } + $openingParenthesesCount++; + } elseif ($char == ')') { + /* must be : + * - after a number or () + * - before a &| or () or at the end of expression + * must not be : + * - at the begining of expression + * - if no ( remain unclose + */ + if ($i == 0 || !preg_match('#[\(\)a-zA-Z0-9_\-]#', $noSpaceString[$i-1]) || (isset($noSpaceString[$i+1]) && !preg_match('#[\(\)\&\|]#', $noSpaceString[$i+1])) || $openingParenthesesCount-$closingParenthesesCount==0) { + return false; + } + $closingParenthesesCount++; + } + } + + if ($openingParenthesesCount != $closingParenthesesCount) { + return false; + } + + return true; + } + + public function getFormType() + { + return 'text'; + } + + public function getFormOptions() + { + return array(); + } +} diff --git a/core/lib/Thelia/Type/IntType.php b/core/lib/Thelia/Type/IntType.php new file mode 100644 index 00000000..a7e4aa04 --- /dev/null +++ b/core/lib/Thelia/Type/IntType.php @@ -0,0 +1,47 @@ + + * + */ + +class IntType extends BaseType +{ + public function getType() + { + return 'Int type'; + } + + public function isValid($value) + { + return filter_var($value, FILTER_VALIDATE_INT) === false ? false : true; + } + + public function getFormattedValue($value) + { + return $this->isValid($value) ? $value : null; + } + + public function getFormType() + { + return 'text'; + } + + public function getFormOptions() + { + return array(); + } +} diff --git a/core/lib/Thelia/Type/JsonType.php b/core/lib/Thelia/Type/JsonType.php new file mode 100644 index 00000000..c00661fb --- /dev/null +++ b/core/lib/Thelia/Type/JsonType.php @@ -0,0 +1,49 @@ + + * + */ + +class JsonType extends BaseType +{ + public function getType() + { + return 'Json type'; + } + + public function isValid($value) + { + json_decode($value, true); + + return (json_last_error() == JSON_ERROR_NONE); + } + + public function getFormattedValue($value) + { + return $this->isValid($value) ? json_decode($value, true) : null; + } + + public function getFormType() + { + return 'text'; + } + + public function getFormOptions() + { + return array(); + } +} diff --git a/core/lib/Thelia/Type/ModelType.php b/core/lib/Thelia/Type/ModelType.php new file mode 100644 index 00000000..e2bb1d89 --- /dev/null +++ b/core/lib/Thelia/Type/ModelType.php @@ -0,0 +1,66 @@ + + * + */ +class ModelType extends BaseType +{ + protected $expectedModelActiveRecord = null; + + /** + * @param $expectedModelActiveRecord + * @throws TypeException + */ + public function __construct($expectedModelActiveRecord) + { + $class = '\\Thelia\\Model\\' . $expectedModelActiveRecord; + + if (!(class_exists($class) && new $class instanceof ActiveRecordInterface)) { + throw new TypeException('MODEL NOT FOUND', TypeException::MODEL_NOT_FOUND); + } + + $this->expectedModelActiveRecord = $class; + } + + public function getType() + { + return 'Model type'; + } + + public function isValid($value) + { + return $value instanceof $this->expectedModelActiveRecord; + } + + public function getFormattedValue($value) + { + return $this->isValid($value) ? $value : null; + } + + public function getFormType() + { + return 'text'; + } + + public function getFormOptions() + { + return array(); + } +} diff --git a/core/lib/Thelia/Type/ModelValidIdType.php b/core/lib/Thelia/Type/ModelValidIdType.php new file mode 100644 index 00000000..10185fe2 --- /dev/null +++ b/core/lib/Thelia/Type/ModelValidIdType.php @@ -0,0 +1,88 @@ + + * + */ +class ModelValidIdType extends BaseType +{ + protected $expectedModelActiveRecordQuery = null; + + /** + * @param $expectedModelActiveRecord + * @throws TypeException + */ + public function __construct($expectedModelActiveRecord) + { + $class = '\\Thelia\\Model\\' . $expectedModelActiveRecord . 'Query'; + + if (!(class_exists($class) || !new $class instanceof ModelCriteria)) { + throw new TypeException('MODEL NOT FOUND', TypeException::MODEL_NOT_FOUND); + } + + $this->expectedModelActiveRecordQuery = $class; + } + + public function getType() + { + return 'Model valid Id type'; + } + + public function isValid($value) + { + $queryClass = $this->expectedModelActiveRecordQuery; + + return null !== $queryClass::create()->findPk($value); + } + + public function getFormattedValue($value) + { + $queryClass = $this->expectedModelActiveRecordQuery; + + return $this->isValid($value) ? $queryClass::create()->findPk($value) : null; + } + + public function getFormType() + { + return 'choice'; + } + + public function getFormOptions() + { + $queryClass = $this->expectedModelActiveRecordQuery; + + $query = $queryClass::create(); + + if (method_exists($query, "joinWithI18n")) { + if (null !== $locale = Translator::getInstance()->getLocale()) { + $query->joinWithI18n($locale); + } + } + + $choices = array(); + foreach ($query->find() as $item) { + $choices[$item->getId()] = method_exists($item, "getTitle") ? $item->getTitle() : $item->getId(); + } + + return array( + "choices" => $choices, + ); + } +} diff --git a/core/lib/Thelia/Type/TypeCollection.php b/core/lib/Thelia/Type/TypeCollection.php new file mode 100644 index 00000000..2700c16b --- /dev/null +++ b/core/lib/Thelia/Type/TypeCollection.php @@ -0,0 +1,142 @@ + + * + */ + +class TypeCollection implements \Iterator +{ + private $position; + protected $types = array(); + + public function __construct() + { + foreach (\func_get_args() as $type) { + $this->addType($type); + } + } + + public function isEmpty() + { + return \count($this->types) == 0; + } + + /** + * @param TypeInterface $type + * + * @return TypeCollection + */ + public function addType(TypeInterface $type) + { + $this->types[] = $type; + + return $this; + } + + public function getCount() + { + return \count($this->types); + } + + /** + * (PHP 5 >= 5.0.0)
    + * Return the current element + * @link http://php.net/manual/en/iterator.current.php + * @return \Thelia\Type\TypeInterface + */ + public function current() + { + return $this->types[$this->position]; + } + + /** + * (PHP 5 >= 5.0.0)
    + * Move forward to next element + * @link http://php.net/manual/en/iterator.next.php + * @return void Any returned value is ignored. + */ + public function next() + { + $this->position++; + } + + /** + * (PHP 5 >= 5.0.0)
    + * Return the key of the current element + * @link http://php.net/manual/en/iterator.key.php + * @return mixed scalar on success, or null on failure. + */ + public function key() + { + return $this->position; + } + + /** + * (PHP 5 >= 5.0.0)
    + * Checks if current position is valid + * @link http://php.net/manual/en/iterator.valid.php + * @return boolean The return value will be casted to boolean and then evaluated. + * Returns true on success or false on failure. + */ + public function valid() + { + return isset($this->types[$this->position]); + } + + /** + * (PHP 5 >= 5.0.0)
    + * Rewind the Iterator to the first element + * @link http://php.net/manual/en/iterator.rewind.php + * @return void Any returned value is ignored. + */ + public function rewind() + { + $this->position = 0; + } + + /** + * @param $value + * + * @return bool + */ + public function isValid($value) + { + foreach ($this as $type) { + if ($type->isValid($value)) { + return true; + } + } + + return false; + } + + public function getFormattedValue($value) + { + foreach ($this as $type) { + if ($type->isValid($value)) { + return $type->getFormattedValue($value); + } + } + + return null; + } + + public function getKey($key) + { + return isset($this->types[$key]) ? $this->types[$key] : null; + } +} diff --git a/core/lib/Thelia/Type/TypeInterface.php b/core/lib/Thelia/Type/TypeInterface.php new file mode 100644 index 00000000..416cea05 --- /dev/null +++ b/core/lib/Thelia/Type/TypeInterface.php @@ -0,0 +1,32 @@ + + * + */ +interface TypeInterface +{ + public function getType(); + + public function isValid($value); + + public function getFormattedValue($value); + + public function getFormType(); + public function getFormOptions(); + public function verifyForm($value, ExecutionContextInterface $context); +} diff --git a/core/local/modules/HookTest/Config/config.xml b/core/local/modules/HookTest/Config/config.xml new file mode 100644 index 00000000..6b26bd61 --- /dev/null +++ b/core/local/modules/HookTest/Config/config.xml @@ -0,0 +1,55 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/core/local/modules/HookTest/Config/module.xml b/core/local/modules/HookTest/Config/module.xml new file mode 100644 index 00000000..9cd16c76 --- /dev/null +++ b/core/local/modules/HookTest/Config/module.xml @@ -0,0 +1,18 @@ + + + HookTest\HookTest + + Hook module tester + + + Hook module tester + + 0.1 + + Julien Chanséaume + jchanseaume@openstudio.fr + + classic + 2.0.0 + other + diff --git a/core/local/modules/HookTest/Hook/FrontHook.php b/core/local/modules/HookTest/Hook/FrontHook.php new file mode 100644 index 00000000..ea805a63 --- /dev/null +++ b/core/local/modules/HookTest/Hook/FrontHook.php @@ -0,0 +1,170 @@ + + */ +class FrontHook extends BaseHook { + + protected $ldelim = "::"; + protected $rdelim = "::"; + + + public function onMainHeadTop(HookRenderEvent $event) + { + $event->add($this->mark("main.head-top test0")); + } + + public function onMainHeadTopTest1(HookRenderEvent $event) + { + $event->add($this->mark("main.head-top test1")); + } + + public function onMainHeadTopTest2(HookRenderEvent $event) + { + $event->add($this->mark("main.head-top test2")); + } + + public function onMainHeadTopTest3(HookRenderEvent $event) + { + $event->add($this->mark("main.head-top test3")); + } + + + // == Hook Function ===================================================== + + public function onMainBodyTop(HookRenderEvent $event){ + $event->add($this->mark("main.body-top 1-1")); + $event->add($this->mark("main.body-top 1-2")); + } + + public function onMainBodyTop2(HookRenderEvent $event) + { + $event->add($this->mark("main.body-top 2")); + } + + + // == ifhook / elsehook ================================================ + + public function onMainNavbarSecondary(HookRenderEvent $event){ + $event->add($this->mark("main.navbar-secondary 1")); + } + + /** + * empty string should be considered as empty :) and should activate the elsehook + * + * @param HookRenderEvent $event + */ + public function onMainNavbarPrimary(HookRenderEvent $event) + { + $event->add(""); + $event->add(" "); + } + + public function onProductAdditional(HookRenderEvent $event) + { + // nothing added + } + + + // == hookblock / forhook ============================================== + + public function onMainFooterBody(HookRenderBlockEvent $event) + { + $event->addFragment(new Fragment(array( + "id" => "id1", + "class" => "class1", + "content" => "content1" + ))); + $event->add(array( + "id" => "id2", + "class" => "class2", + "content" => "content2" + )); + } + + // == global objects =================================================== + + public function onMainContentTop(HookRenderEvent $event) + { + $event->add($this->mark("main.content-top")); + $event->add($this->mark("view : " . $this->getView())); + $event->add($this->mark("request : " . $this->getRequest())); + $event->add($this->mark("session : " . $this->getSession()->getId())); + $event->add($this->mark("cart : " . ($this->getCart() === null ? "null" : "not null"))); + $event->add($this->mark("order : " . ($this->getOrder() === null ? "null" : "not null"))); + $event->add($this->mark("currency : " . $this->getCurrency()->getId())); + $event->add($this->mark("customer : " . $this->getCustomer())); + $event->add($this->mark("lang : " . $this->getLang()->getId())); + } + + public function onMainContentTopRender(HookRenderEvent $event) + { + $event->add($this->render("render.html")); + } + + public function onMainContentTopDump(HookRenderEvent $event) + { + $event->add($this->dump("dump.txt")); + } + + public function onMainContentTopAddCSS(HookRenderEvent $event) + { + $event->add($this->mark($this->addCSS("assets/css/styles.css"))); + $event->add($this->mark($this->addCSS("assets/css/print.css", array("media" => "print")))); + } + + public function onMainContentTopAddJS(HookRenderEvent $event) + { + $event->add($this->mark($this->addJS("assets/js/script.js"))); + } + + public function onMainContentTopTrans(HookRenderEvent $event) + { + $event->add($this->mark($this->trans("Hodor Hodor", array(), "hooktest"))); + $event->add($this->mark($this->trans("Hello World", array(), "hooktest"))); + $event->add($this->mark($this->trans("Hello %name%", array("%name%" => "Hodor")))); + $event->add($this->mark($this->trans("Hi %name%", array("%name%" => "Hodor"), "hooktest", 'fr_FR'))); + } + + // == template overriding ==================================================== + + public function onMainContentTopOverriding(HookRenderEvent $event) + { + $event->add($this->render("override1.html")); + // redefined in template hooktest in the module + $event->add($this->render("override2.html")); + // redefined in template hooktest + $event->add($this->render("override3.html")); + + $event->add($this->render("override-assets.html")); + + } + + + + protected function mark($message, $endofline="\n") + { + return sprintf("%s %s %s%s", $this->ldelim, $message, $this->rdelim, $endofline); + } + +} \ No newline at end of file diff --git a/core/local/modules/HookTest/HookTest.php b/core/local/modules/HookTest/HookTest.php new file mode 100644 index 00000000..1a95a557 --- /dev/null +++ b/core/local/modules/HookTest/HookTest.php @@ -0,0 +1,21 @@ + 'Hodor en_US Hodor', + 'Hello World' => 'Hello en_US World', + 'Hello %name%' => 'Hello en_US %name%', + 'Hi %name%' => 'Hi en_US %name%', +); diff --git a/core/local/modules/HookTest/I18n/fr_FR.php b/core/local/modules/HookTest/I18n/fr_FR.php new file mode 100644 index 00000000..78016ce0 --- /dev/null +++ b/core/local/modules/HookTest/I18n/fr_FR.php @@ -0,0 +1,7 @@ + 'Hodor fr_FR Hodor', + 'Hello World' => 'Bonjour fr_FR monde', + 'Hello %name%' => 'Bonjour fr_FR %name%', + 'Hi %name%' => 'Salut fr_FR %name%', +); diff --git a/core/local/modules/HookTest/I18n/frontOffice/default/en_US.php b/core/local/modules/HookTest/I18n/frontOffice/default/en_US.php new file mode 100644 index 00000000..afca37ed --- /dev/null +++ b/core/local/modules/HookTest/I18n/frontOffice/default/en_US.php @@ -0,0 +1,5 @@ + + {ifloop rel="cartloop"} + + {/ifloop} + {elseloop rel="cartloop"} + + {/elseloop} + \ No newline at end of file diff --git a/core/local/modules/HookTest/templates/frontOffice/default/override-assets.html b/core/local/modules/HookTest/templates/frontOffice/default/override-assets.html new file mode 100644 index 00000000..3702db3c --- /dev/null +++ b/core/local/modules/HookTest/templates/frontOffice/default/override-assets.html @@ -0,0 +1,13 @@ + + +{stylesheets file="assets/css/style1.css" source="HookTest"} +asset file 1 : {$asset_url} +{/stylesheets} +{stylesheets file="assets/css/style2.css" source="HookTest"} +asset file 2 : {$asset_url} +{/stylesheets} +{stylesheets file="assets/css/style3.css" source="HookTest"} +asset file 3 : {$asset_url} +{/stylesheets} + + \ No newline at end of file diff --git a/core/local/modules/HookTest/templates/frontOffice/default/override1.html b/core/local/modules/HookTest/templates/frontOffice/default/override1.html new file mode 100644 index 00000000..31b1e3e4 --- /dev/null +++ b/core/local/modules/HookTest/templates/frontOffice/default/override1.html @@ -0,0 +1 @@ +:: file override1 from module/default :: diff --git a/core/local/modules/HookTest/templates/frontOffice/default/override2.html b/core/local/modules/HookTest/templates/frontOffice/default/override2.html new file mode 100644 index 00000000..d3744dba --- /dev/null +++ b/core/local/modules/HookTest/templates/frontOffice/default/override2.html @@ -0,0 +1 @@ +:: file override2 from module/default :: diff --git a/core/local/modules/HookTest/templates/frontOffice/default/override3.html b/core/local/modules/HookTest/templates/frontOffice/default/override3.html new file mode 100644 index 00000000..e178cc79 --- /dev/null +++ b/core/local/modules/HookTest/templates/frontOffice/default/override3.html @@ -0,0 +1 @@ +:: file override3 from module/default :: diff --git a/core/local/modules/HookTest/templates/frontOffice/default/render.html b/core/local/modules/HookTest/templates/frontOffice/default/render.html new file mode 100644 index 00000000..217a5f63 --- /dev/null +++ b/core/local/modules/HookTest/templates/frontOffice/default/render.html @@ -0,0 +1,2 @@ + +:: function render :: diff --git a/core/local/modules/HookTest/templates/frontOffice/hooktest/assets/css/style2.css b/core/local/modules/HookTest/templates/frontOffice/hooktest/assets/css/style2.css new file mode 100644 index 00000000..348fd427 --- /dev/null +++ b/core/local/modules/HookTest/templates/frontOffice/hooktest/assets/css/style2.css @@ -0,0 +1 @@ +/* style2 in module/hooktest */ \ No newline at end of file diff --git a/core/local/modules/HookTest/templates/frontOffice/hooktest/override2.html b/core/local/modules/HookTest/templates/frontOffice/hooktest/override2.html new file mode 100644 index 00000000..108fb477 --- /dev/null +++ b/core/local/modules/HookTest/templates/frontOffice/hooktest/override2.html @@ -0,0 +1 @@ +:: file override2 from module/hooktest :: diff --git a/core/templates/frontOffice/hooktest/composer.json b/core/templates/frontOffice/hooktest/composer.json new file mode 100644 index 00000000..4ee9e18e --- /dev/null +++ b/core/templates/frontOffice/hooktest/composer.json @@ -0,0 +1,10 @@ +{ + "name": "thelia/hooktest-template", + "type": "thelia-frontoffice-template", + "require": { + "thelia/installer": "~1.1" + }, + "extra": { + "installer-name": "hooktest" + } +} diff --git a/core/templates/frontOffice/hooktest/includes/single-product.html b/core/templates/frontOffice/hooktest/includes/single-product.html new file mode 100644 index 00000000..cd7aebd3 --- /dev/null +++ b/core/templates/frontOffice/hooktest/includes/single-product.html @@ -0,0 +1,110 @@ +
  • + {if $PSE_COUNT > 1} + {assign var="hasSubmit" value = false} + {else} + {assign var="hasSubmit" value = true} + {/if} + {assign var="productTitle" value="{$TITLE}"} + {if not $product_id} + {assign var="product_id" value=$ID} + {/if} +
    + + {hook name="singleproduct.top" product="{$product_id}"} + + + +
    +

    {$productTitle}

    + {if $hasDescription} +
    +

    {$DESCRIPTION nofilter}

    +
    + {/if} +
    + + {* Stock *} + {assign var="current_stock_content" value = "in_stock"} + {assign var="current_stock_href" value = "http://schema.org/InStock"} + {if {config key="check-available-stock"} != 0} + {if $QUANTITY == 0} + {assign var="current_stock_content" value = "out_stock"} + {assign var="current_stock_href" value = "http://schema.org/OutOfStock"} + {/if} + {/if} + +
    +
    + + {* List of condition : NewCondition, DamagedCondition, UsedCondition, RefurbishedCondition *} + + {* List of currency : The currency used to describe the product price, in three-letter ISO format. *} + + + {if $IS_PROMO } + {intl l="Special Price:"} {format_number number=$TAXED_PROMO_PRICE} {currency attr="symbol"} + {intl l="Regular Price:"} {format_number number=$TAXED_PRICE} {currency attr="symbol"} + {else} + {format_number number=$BEST_TAXED_PRICE} {currency attr="symbol"} + {/if} +
    + + {if $hasBtn == true} + {if $hasSubmit == true} + {form name="thelia.cart.add" } +
    + {form_hidden_fields form=$form} + + + + {if $form_error}
    {$form_error_message}
    {/if} + + {form_field form=$form field='product_sale_elements_id'} + + {/form_field} + {form_field form=$form field="product"} + + {/form_field} + +
    + {form_field form=$form field='quantity'} +
    + + + {if $error } + {$message} + {elseif $value != "" && !$error} + + {/if} +
    + {/form_field} +
    +
    + +
    +
    +
    +
    + {/form} + {else} + + {/if} + {/if} +
    + + {hook name="singleproduct.bottom" product="{$product_id}"} + +
    +
  • diff --git a/core/templates/frontOffice/hooktest/index.html b/core/templates/frontOffice/hooktest/index.html new file mode 100644 index 00000000..034bb83e --- /dev/null +++ b/core/templates/frontOffice/hooktest/index.html @@ -0,0 +1,24 @@ +{extends file="layout.tpl"} + +{block name="main-content"} + + {ifhook rel="home.body"} + {hook name="home.body"} + {/ifhook} + {elsehook rel="home.body"} + ::NO home.body:: + {/elsehook} + +{/block} + +{block name="stylesheet"} +{hook name="home.stylesheet"} +{/block} + +{block name="after-javascript-include"} +{hook name="home.after-javascript-include"} +{/block} + +{block name="javascript-initialization"} +{hook name="home.javascript-initialization"} +{/block} diff --git a/core/templates/frontOffice/hooktest/layout.tpl b/core/templates/frontOffice/hooktest/layout.tpl new file mode 100644 index 00000000..51134518 --- /dev/null +++ b/core/templates/frontOffice/hooktest/layout.tpl @@ -0,0 +1,110 @@ + + + + +{* Declare assets directory, relative to template base directory *} +{declare_assets directory='assets'} + +{* Set the default translation domain, that will be used by {intl} when the 'd' parameter is not set *} +{default_translation_domain domain='fo.default'} + +{hook name="main.head-top"} + +{hook name="main.stylesheet"} + +{hook name="main.body-top"} + +{hook name="main.header-top"} + +{hook name="main.navbar-secondary"} +{ifhook rel="main.navbar-secondary"} + ::main.navbar-secondary ifhook:: +{/ifhook} +{elsehook rel="main.navbar-secondary"} + ::main.navbar-secondary elsehook:: +{/elsehook} + +{hook name="main.navbar-primary"} +{ifhook rel="main.navbar-primary"} + ::main.navbar-primary ifhook:: +{/ifhook} +{elsehook rel="main.navbar-primary"} + ::main.navbar-primary elsehook:: +{/elsehook} + +{hook name="main.header-bottom"} + +{hook name="main.content-top"} + + +{block name="main-content"}{/block} + + +{hook name="main.content-bottom"} + +{ifhook rel="main.footer-top"} + {hook name="main.footer-top"} +{/ifhook} +{elsehook rel="main.footer-top"} + ::NO main.footer-top:: +{/elsehook} + +{ifhook rel="product.additional"} +{hookblock name="product.additional"} +{forhook rel="product.additional"} + ::product.additional ifhook:: +{/forhook} +{/hookblock} +{/ifhook} +{elsehook rel="product.additional"} + ::product.additional elsehook:: +{/elsehook} + + + +{ifhook rel="main.footer-body"} + ::main.footer-body ifhook:: + {hookblock name="main.footer-body"} + {forhook rel="main.footer-body"} + ::main.footer-body {$id} {$class} {$content}:: + {/forhook} + {/hookblock} +{/ifhook} +{elsehook rel="main.footer-body"} + ::main.footer-body elsehook:: +{/elsehook} + +{ifhook rel="main.footer-bottom"} + {hook name="main.footer-bottom"} +{/ifhook} +{elsehook rel="main.footer-bottom"} + ::NO main.footer-bottom:: +{/elsehook} + +{hook name="main.after-javascript-include"} + +{block name="after-javascript-include"}{/block} + +{hook name="main.javascript-initialization"} + +{block name="javascript-initialization"}{/block} + +{hook name="main.body-bottom"} diff --git a/core/templates/frontOffice/hooktest/modules/HookTest/assets/css/style3.css b/core/templates/frontOffice/hooktest/modules/HookTest/assets/css/style3.css new file mode 100644 index 00000000..ed6ae71a --- /dev/null +++ b/core/templates/frontOffice/hooktest/modules/HookTest/assets/css/style3.css @@ -0,0 +1 @@ +/* style3 in template/hooktest */ \ No newline at end of file diff --git a/core/templates/frontOffice/hooktest/modules/HookTest/override3.html b/core/templates/frontOffice/hooktest/modules/HookTest/override3.html new file mode 100644 index 00000000..a880c846 --- /dev/null +++ b/core/templates/frontOffice/hooktest/modules/HookTest/override3.html @@ -0,0 +1 @@ +:: file override3 from template/hooktest :: diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 00000000..cdf06f65 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,36 @@ +version: "3.1" + +services: + mariadb: + image: mariadb:10.3 + container_name: docker-thelia-mariadb + working_dir: /application + volumes: + - .:/application + - .docker/mysql-data:/var/lib/mysql + environment: + - MYSQL_ROOT_PASSWORD=root + - MYSQL_DATABASE=thelia + - MYSQL_USER=thelia + - MYSQL_PASSWORD=thelia + ports: + - "8086:3306" + + webserver: + image: nginx:alpine + container_name: docker-thelia-webserver + working_dir: /application + volumes: + - .:/application + - .docker/nginx/nginx.conf:/etc/nginx/conf.d/default.conf + ports: + - "8080:80" + + php-fpm: + build: .docker/php-fpm + container_name: docker-thelia-php-fpm + working_dir: /application + volumes: + - .:/application + - .docker/php-fpm/php-ini-overrides.ini:/etc/php/7.3/fpm/conf.d/99-overrides.ini + - .docker/php-fpm/php-ini-overrides.ini:/etc/php/7.3/cli/conf.d/99-overrides.ini diff --git a/index.html b/index.html new file mode 100644 index 00000000..9f1ec11f --- /dev/null +++ b/index.html @@ -0,0 +1,11 @@ + + + + + Redirecting... + + + +Redirecting... + + \ No newline at end of file diff --git a/local/.gitkeep b/local/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/local/I18n/.gitkeep b/local/I18n/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/local/backup/.gitkeep b/local/backup/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/local/config/.gitkeep b/local/config/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/local/config/.htaccess b/local/config/.htaccess new file mode 100644 index 00000000..f239fe83 --- /dev/null +++ b/local/config/.htaccess @@ -0,0 +1,2 @@ +order deny,allow +deny from all \ No newline at end of file diff --git a/local/config/Readme.md b/local/config/Readme.md new file mode 100644 index 00000000..083fcc78 --- /dev/null +++ b/local/config/Readme.md @@ -0,0 +1,35 @@ +Readme +====== + +## This is the repository of Thelia configuration. All the pull requests on this repo will be ignored. +### If you want to create a project, please take a look at [thelia/thelia-project](https://github.com/thelia/thelia-project) +### If you want to contribute to Thelia, please take a look at [thelia/thelia](https://github.com/thelia/thelia) + +Thelia +------ +[![Build Status](https://travis-ci.org/thelia/thelia.png?branch=master)](https://travis-ci.org/thelia/thelia) [![License](https://poser.pugx.org/thelia/thelia/license.png)](https://packagist.org/packages/thelia/thelia) [![Scrutinizer Quality Score](https://scrutinizer-ci.com/g/thelia/thelia/badges/quality-score.png?s=61e3e04a69bffd71c29b08e5392080317a546716)](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. + +This is the new major version of Thelia. + +You can download this version and have a try or take a look at the source code (or anything you wish, respecting LGPL). See http://thelia.net/ web site for more information. + +A repository containing all thelia modules is available at this address : https://github.com/thelia-modules + +Requirements +------------ + +* php 5.5 + * Required extensions : + * PDO_Mysql + * openssl + * intl + * gd + * curl + * safe_mode off + * memory_limit at least 128M, preferably 256. + * post_max_size 20M + * upload_max_filesize 2M +* apache 2 +* mysql diff --git a/local/config/composer.json b/local/config/composer.json new file mode 100644 index 00000000..dc793a55 --- /dev/null +++ b/local/config/composer.json @@ -0,0 +1,10 @@ +{ + "name": "thelia/config", + "type": "thelia-local", + "require": { + "thelia/installer": "~1.1" + }, + "extra": { + "installer-name": "config" + } +} diff --git a/local/config/database.yml.sample b/local/config/database.yml.sample new file mode 100644 index 00000000..e1afbf00 --- /dev/null +++ b/local/config/database.yml.sample @@ -0,0 +1,6 @@ +database: + connection: + driver: %DRIVER% + user: %USERNAME% + password: %PASSWORD% + dsn: %DSN% \ No newline at end of file diff --git a/local/config/schema.xml b/local/config/schema.xml new file mode 100644 index 00000000..df52ac60 --- /dev/null +++ b/local/config/schema.xml @@ -0,0 +1,1939 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + + + + + + + + +
    + + + + + + + + + + +
    + + + + + + + + + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + + + + + + + + +
    + + + + + + + + + + + +
    + + + + + + + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + + + + + + + + +
    + + + + + + + + + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + + + + +
    + + + + + +
    + + + + + + + + + + + + + + + + + + + + + +
    + + + + + + + + + + + + + + +
    + + + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + + + + + + + + + +
    + + + + + + + + + + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + + + + + + + + + +
    + + + + + + + + + + + +
    + + + + + + + +
    + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + + + + + + + + + + + + +
    + + + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + + + + + + + + + + +
    + + + + + + + + + + + + +
    + + + + + + + + + + + + +
    + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + + + + + + +
    + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + + + + + + + +
    + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + + +
    + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + + +
    +
    diff --git a/local/media/.gitkeep b/local/media/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/local/modules/Carousel/CHANGELOG.md b/local/modules/Carousel/CHANGELOG.md new file mode 100644 index 00000000..b4525a3b --- /dev/null +++ b/local/modules/Carousel/CHANGELOG.md @@ -0,0 +1,6 @@ +# 2.3.0-alpha1 + +- Moved the images from the directory 'media' in the module to thelia/local/media/images/carousel. +- The current images will be automatically copied in the new directory during the update of the module +- Removed AdminIncludes directory +- All html,js and css files are now in 'templates' \ No newline at end of file diff --git a/local/modules/Carousel/Carousel.php b/local/modules/Carousel/Carousel.php new file mode 100644 index 00000000..4e6f9d8e --- /dev/null +++ b/local/modules/Carousel/Carousel.php @@ -0,0 +1,109 @@ + + */ +class Carousel extends BaseModule +{ + const DOMAIN_NAME = 'carousel'; + + public function preActivation(ConnectionInterface $con = null) + { + if (! self::getConfigValue('is_initialized', false)) { + $database = new Database($con); + + $database->insertSql(null, array(__DIR__ . '/Config/thelia.sql')); + + self::setConfigValue('is_initialized', true); + } + + return true; + } + + public function destroy(ConnectionInterface $con = null, $deleteModuleData = false) + { + $database = new Database($con); + + $database->insertSql(null, array(__DIR__ . '/Config/sql/destroy.sql')); + } + + public function getUploadDir() + { + $uploadDir = ConfigQuery::read('images_library_path'); + + if ($uploadDir === null) { + $uploadDir = THELIA_LOCAL_DIR . 'media' . DS . 'images'; + } else { + $uploadDir = THELIA_ROOT . $uploadDir; + } + + return $uploadDir . DS . self::DOMAIN_NAME; + } + + /** + * @param string $currentVersion + * @param string $newVersion + * @param ConnectionInterface $con + * @author Thomas Arnaud + */ + public function update($currentVersion, $newVersion, ConnectionInterface $con = null) + { + $uploadDir = $this->getUploadDir(); + $fileSystem = new Filesystem(); + + if (!$fileSystem->exists($uploadDir) && $fileSystem->exists(__DIR__ . DS . 'media' . DS . 'carousel')) { + $finder = new Finder(); + $finder->files()->in(__DIR__ . DS . 'media' . DS . 'carousel'); + + $fileSystem->mkdir($uploadDir); + + /** @var SplFileInfo $file */ + foreach ($finder as $file) { + copy($file, $uploadDir . DS . $file->getRelativePathname()); + } + $fileSystem->remove(__DIR__ . DS . 'media'); + } + + $finder = (new Finder())->files()->name('#.*?\.sql#')->sortByName()->in(__DIR__ . DS . 'Config' . DS .'update'); + + if (0 === $finder->count()) { + return; + } + + $database = new Database($con); + + // apply update only if table exists + if ($database->execute("SHOW TABLES LIKE 'carousel'")->rowCount() === 0) { + return; + } + + /** @var SplFileInfo $updateSQLFile */ + foreach ($finder as $updateSQLFile) { + if (version_compare($currentVersion, str_replace('.sql', '', $updateSQLFile->getFilename()), '<')) { + $database->insertSql(null, [$updateSQLFile->getPathname()]); + } + } + } +} diff --git a/local/modules/Carousel/Config/config.xml b/local/modules/Carousel/Config/config.xml new file mode 100644 index 00000000..54642a77 --- /dev/null +++ b/local/modules/Carousel/Config/config.xml @@ -0,0 +1,25 @@ + + + + + + + + +
    + + + + + + + + + + + + + + diff --git a/local/modules/Carousel/Config/module.xml b/local/modules/Carousel/Config/module.xml new file mode 100644 index 00000000..2c435161 --- /dev/null +++ b/local/modules/Carousel/Config/module.xml @@ -0,0 +1,24 @@ + + + Carousel\Carousel + + An image carousel + + + Un carrousel d'images + + + en_US + fr_FR + + 2.4.3 + + Manuel Raynaud, Franck Allimant + manu@raynaud.io, franck@cqfdev.fr + + classic + 2.4.3 + alpha + diff --git a/local/modules/Carousel/Config/routing.xml b/local/modules/Carousel/Config/routing.xml new file mode 100644 index 00000000..44e95906 --- /dev/null +++ b/local/modules/Carousel/Config/routing.xml @@ -0,0 +1,42 @@ + + + + + + + Carousel\Controller\ConfigurationController::uploadImage + + + + Carousel\Controller\ConfigurationController::updateAction + + + + Carousel\Controller\ConfigurationController::deleteAction + + + diff --git a/local/modules/Carousel/Config/schema.xml b/local/modules/Carousel/Config/schema.xml new file mode 100644 index 00000000..47167283 --- /dev/null +++ b/local/modules/Carousel/Config/schema.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + + + +
    + + +
    diff --git a/local/modules/Carousel/Config/sql/destroy.sql b/local/modules/Carousel/Config/sql/destroy.sql new file mode 100644 index 00000000..e6116063 --- /dev/null +++ b/local/modules/Carousel/Config/sql/destroy.sql @@ -0,0 +1,6 @@ +SET FOREIGN_KEY_CHECKS = 0; + +DROP TABLE IF EXISTS `carousel`; +DROP TABLE IF EXISTS `carousel_i18n`; + +SET FOREIGN_KEY_CHECKS = 1; \ No newline at end of file diff --git a/local/modules/Carousel/Config/thelia.sql b/local/modules/Carousel/Config/thelia.sql new file mode 100644 index 00000000..f39cc5a8 --- /dev/null +++ b/local/modules/Carousel/Config/thelia.sql @@ -0,0 +1,51 @@ + +# This is a fix for InnoDB in MySQL >= 4.1.x +# It "suspends judgement" for fkey relationships until are tables are set. +SET FOREIGN_KEY_CHECKS = 0; + +-- --------------------------------------------------------------------- +-- carousel +-- --------------------------------------------------------------------- + +DROP TABLE IF EXISTS `carousel`; + +CREATE TABLE `carousel` +( + `id` INTEGER NOT NULL AUTO_INCREMENT, + `file` VARCHAR(255), + `position` INTEGER, + `disable` INTEGER, + `group` VARCHAR(255), + `url` VARCHAR(255), + `limited` INTEGER, + `start_date` DATETIME, + `end_date` DATETIME, + `created_at` DATETIME, + `updated_at` DATETIME, + PRIMARY KEY (`id`) +) ENGINE=InnoDB; + +-- --------------------------------------------------------------------- +-- carousel_i18n +-- --------------------------------------------------------------------- + +DROP TABLE IF EXISTS `carousel_i18n`; + +CREATE TABLE `carousel_i18n` +( + `id` INTEGER NOT NULL, + `locale` VARCHAR(5) DEFAULT 'en_US' NOT NULL, + `alt` VARCHAR(255), + `title` VARCHAR(255), + `description` LONGTEXT, + `chapo` TEXT, + `postscriptum` TEXT, + PRIMARY KEY (`id`,`locale`), + CONSTRAINT `carousel_i18n_fk_2ec1b2` + FOREIGN KEY (`id`) + REFERENCES `carousel` (`id`) + ON DELETE CASCADE +) ENGINE=InnoDB; + +# This restores the fkey checks, after having unset them earlier +SET FOREIGN_KEY_CHECKS = 1; diff --git a/local/modules/Carousel/Config/update/2.4.0.sql b/local/modules/Carousel/Config/update/2.4.0.sql new file mode 100644 index 00000000..8f95a9a9 --- /dev/null +++ b/local/modules/Carousel/Config/update/2.4.0.sql @@ -0,0 +1 @@ +ALTER TABLE `carousel` ADD (`disable` INTEGER, `group` VARCHAR(255),`limited` INTEGER, `start_date` DATETIME, `end_date` DATETIME); diff --git a/local/modules/Carousel/Controller/ConfigurationController.php b/local/modules/Carousel/Controller/ConfigurationController.php new file mode 100644 index 00000000..ad96a7a1 --- /dev/null +++ b/local/modules/Carousel/Controller/ConfigurationController.php @@ -0,0 +1,189 @@ + + */ +class ConfigurationController extends BaseAdminController +{ + + public function uploadImage() + { + if (null !== $response = $this->checkAuth(AdminResources::MODULE, ['carousel'], AccessManager::CREATE)) { + return $response; + } + + $request = $this->getRequest(); + $form = $this->createForm('carousel.image'); + $error_message = null; + try { + $this->validateForm($form); + + /** @var \Symfony\Component\HttpFoundation\File\UploadedFile $fileBeingUploaded */ + $fileBeingUploaded = $request->files->get(sprintf('%s[file]', $form->getName()), null, true); + + $fileModel = new Carousel(); + + $fileCreateOrUpdateEvent = new FileCreateOrUpdateEvent(1); + $fileCreateOrUpdateEvent->setModel($fileModel); + $fileCreateOrUpdateEvent->setUploadedFile($fileBeingUploaded); + + $this->dispatch( + TheliaEvents::IMAGE_SAVE, + $fileCreateOrUpdateEvent + ); + + // Compensate issue #1005 + $langs = LangQuery::create()->find(); + + /** @var Lang $lang */ + foreach ($langs as $lang) { + $fileCreateOrUpdateEvent->getModel()->setLocale($lang->getLocale())->setTitle('')->save(); + } + + $response = $this->redirectToConfigurationPage(); + + } catch (FormValidationException $e) { + $error_message = $this->createStandardFormValidationErrorMessage($e); + } + + if (null !== $error_message) { + $this->setupFormErrorContext( + 'carousel upload', + $error_message, + $form + ); + + $response = $this->render( + "module-configure", + [ + 'module_code' => 'Carousel' + ] + ); + } + + return $response; + } + + /** + * @param Form $form + * @param string $fieldName + * @param int $id + * @return string + */ + protected function getFormFieldValue($form, $fieldName, $id) + { + $value = $form->get(sprintf('%s%d', $fieldName, $id))->getData(); + + return $value; + } + + public function updateAction() + { + if (null !== $response = $this->checkAuth(AdminResources::MODULE, ['carousel'], AccessManager::UPDATE)) { + return $response; + } + + $form = $this->createForm('carousel.update'); + + $error_message = null; + + try { + $updateForm = $this->validateForm($form); + + $carousels = CarouselQuery::create()->findAllByPosition(); + + $locale = $this->getCurrentEditionLocale(); + + /** @var Carousel $carousel */ + foreach ($carousels as $carousel) { + $id = $carousel->getId(); + + $carousel + ->setPosition($this->getFormFieldValue($updateForm, 'position', $id)) + ->setDisable($this->getFormFieldValue($updateForm, 'disable', $id)) + ->setUrl($this->getFormFieldValue($updateForm, 'url', $id)) + ->setLocale($locale) + ->setTitle($this->getFormFieldValue($updateForm, 'title', $id)) + ->setAlt($this->getFormFieldValue($updateForm, 'alt', $id)) + ->setChapo($this->getFormFieldValue($updateForm, 'chapo', $id)) + ->setDescription($this->getFormFieldValue($updateForm, 'description', $id)) + ->setPostscriptum($this->getFormFieldValue($updateForm, 'postscriptum', $id)) + ->setGroup($this->getFormFieldValue($updateForm, 'group', $id)) + ->setLimited($this->getFormFieldValue($updateForm, 'limited', $id)) + ->setStartDate($this->getFormFieldValue($updateForm, 'start_date', $id)) + ->setEndDate($this->getFormFieldValue($updateForm, 'end_date', $id)) + ->save(); + } + + $response = $this->redirectToConfigurationPage(); + + } catch (FormValidationException $e) { + $error_message = $this->createStandardFormValidationErrorMessage($e); + } + + if (null !== $error_message) { + $this->setupFormErrorContext( + 'carousel upload', + $error_message, + $form + ); + + $response = $this->render("module-configure", [ 'module_code' => 'Carousel' ]); + } + + return $response; + + } + + public function deleteAction() + { + if (null !== $response = $this->checkAuth(AdminResources::MODULE, ['carousel'], AccessManager::DELETE)) { + return $response; + } + + $imageId = $this->getRequest()->request->get('image_id'); + + if ($imageId != "") { + $carousel = CarouselQuery::create()->findPk($imageId); + + if (null !== $carousel) { + $carousel->delete(); + } + } + + return $this->redirectToConfigurationPage(); + } + + protected function redirectToConfigurationPage() + { + return RedirectResponse::create(URL::getInstance()->absoluteUrl('/admin/module/Carousel')); + } +} \ No newline at end of file diff --git a/local/modules/Carousel/Form/CarouselImageForm.php b/local/modules/Carousel/Form/CarouselImageForm.php new file mode 100644 index 00000000..5ad985e3 --- /dev/null +++ b/local/modules/Carousel/Form/CarouselImageForm.php @@ -0,0 +1,56 @@ + + */ +class CarouselImageForm extends BaseForm +{ + /** + * @inheritdoc + */ + protected function buildForm() + { + $translator = Translator::getInstance(); + $this->formBuilder + ->add( + 'file', + 'file', + [ + 'constraints' => [ + new Image() + ], + 'label' => $translator->trans('Carousel image', [], Carousel::DOMAIN_NAME), + 'label_attr' => [ + 'for' => 'file' + ] + ] + ); + } + + /** + * @return string the name of you form. This name must be unique + */ + public function getName() + { + return 'carousel_image'; + } +} \ No newline at end of file diff --git a/local/modules/Carousel/Form/CarouselUpdateForm.php b/local/modules/Carousel/Form/CarouselUpdateForm.php new file mode 100644 index 00000000..a76470a7 --- /dev/null +++ b/local/modules/Carousel/Form/CarouselUpdateForm.php @@ -0,0 +1,228 @@ + + */ +class CarouselUpdateForm extends BaseForm +{ + /** + * @inheritdoc + */ + protected function buildForm() + { + $formBuilder = $this->formBuilder; + + $carousels = CarouselQuery::create()->orderByPosition()->find(); + + /** @var \Carousel\Model\Carousel $carousel */ + foreach ($carousels as $carousel) { + $id = $carousel->getId(); + + $formBuilder->add( + 'position' . $id, + 'text', + [ + 'label' => $this->translator->trans('Image position in carousel', [], Carousel::DOMAIN_NAME), + 'label_attr' => [ + 'for' => 'position' . $id + ], + 'required' => false, + 'attr' => [ + 'placeholder' => $this->translator->trans( + 'Image position in carousel', + [], + Carousel::DOMAIN_NAME + ) + ] + ] + )->add( + 'alt' . $id, + 'text', + [ + 'label' => $this->translator->trans('Alternative image text', [], Carousel::DOMAIN_NAME), + 'label_attr' => [ + 'for' => 'alt' . $id + ], + 'required' => false, + 'attr' => [ + 'placeholder' => $this->translator->trans( + 'Displayed when image is not visible', + [], + Carousel::DOMAIN_NAME + ) + ] + ] + )->add( + 'group' . $id, + 'text', + [ + 'label' => $this->translator->trans('Group image', [], Carousel::DOMAIN_NAME), + 'label_attr' => [ + 'for' => 'group' . $id + ], + 'required' => false, + 'attr' => [ + 'placeholder' => $this->translator->trans( + 'Group of images', + [], + Carousel::DOMAIN_NAME + ) + ] + ] + )->add( + 'url' . $id, + 'url', + [ + 'label' => $this->translator->trans('Image URL', [], Carousel::DOMAIN_NAME), + 'label_attr' => [ + 'for' => 'url' . $id + ], + 'required' => false, + 'attr' => [ + 'placeholder' => $this->translator->trans( + 'Please enter a valid URL', + [], + Carousel::DOMAIN_NAME + ) + ] + ] + )->add( + 'title' . $id, + 'text', + [ + 'constraints' => [], + 'required' => false, + 'label' => $this->translator->trans('Title', [], Carousel::DOMAIN_NAME), + 'label_attr' => [ + 'for' => 'title_field' . $id + ], + 'attr' => [ + 'placeholder' => $this->translator->trans('A descriptive title', [], Carousel::DOMAIN_NAME) + ] + ] + )->add( + 'chapo' . $id, + 'textarea', + [ + 'constraints' => [], + 'required' => false, + 'label' => $this->translator->trans('Summary', [], Carousel::DOMAIN_NAME), + 'label_attr' => [ + 'for' => 'summary_field' . $id, + 'help' => $this->translator->trans( + 'A short description, used when a summary or an introduction is required', + [], + Carousel::DOMAIN_NAME + ) + ], + 'attr' => [ + 'rows' => 3, + 'placeholder' => $this->translator->trans('Short description text', [], Carousel::DOMAIN_NAME) + ] + ] + )->add( + 'description' . $id, + 'textarea', + [ + 'constraints' => [], + 'required' => false, + 'label' => $this->translator->trans('Detailed description', [], Carousel::DOMAIN_NAME), + 'label_attr' => [ + 'for' => 'detailed_description_field' . $id, + 'help' => $this->translator->trans('The detailed description.', [], Carousel::DOMAIN_NAME) + ], + 'attr' => [ + 'rows' => 5 + ] + ] + )->add( + 'disable' . $id, + CheckboxType::class, + [ + 'required' => false, + 'label' => $this->translator->trans('Disable image', [], Carousel::DOMAIN_NAME), + 'label_attr' => [ + 'for' => 'enable' . $id, + ], + ] + )->add( + 'limited' . $id, + CheckboxType::class, + [ + 'required' => false, + 'label' => $this->translator->trans('Limited', [], Carousel::DOMAIN_NAME), + 'label_attr' => [ + 'for' => 'limited' . $id, + ], + ] + )->add( + 'start_date' . $id, + DateTimeType::class, + [ + 'label' => $this->translator->trans('Start date', [], Carousel::DOMAIN_NAME), + 'widget' => "single_text", + 'required' => false, + ] + )->add( + 'end_date' . $id, + DateTimeType::class, + [ + 'label' => $this->translator->trans('End date', [], Carousel::DOMAIN_NAME), + 'widget' => "single_text", + 'required' => false, + + ] + )->add( + 'postscriptum' . $id, + 'textarea', + [ + 'constraints' => [], + 'required' => false, + 'label' => $this->translator->trans('Conclusion', [], Carousel::DOMAIN_NAME), + 'label_attr' => [ + 'for' => 'conclusion_field' . $id, + 'help' => $this->translator->trans( + 'A short text, used when an additional or supplemental information is required.', + [], + Carousel::DOMAIN_NAME + ) + ], + 'attr' => [ + 'placeholder' => $this->translator->trans('Short additional text', [], Carousel::DOMAIN_NAME), + 'rows' => 3, + ] + ] + ); + } + } + + /** + * @inheritdoc + */ + public function getName() + { + return "carousel_update"; + } +} diff --git a/local/modules/Carousel/Hook/BackHook.php b/local/modules/Carousel/Hook/BackHook.php new file mode 100644 index 00000000..b033670d --- /dev/null +++ b/local/modules/Carousel/Hook/BackHook.php @@ -0,0 +1,48 @@ + + */ +class BackHook extends BaseHook +{ + + /** + * Add a new entry in the admin tools menu + * + * should add to event a fragment with fields : id,class,url,title + * + * @param HookRenderBlockEvent $event + */ + public function onMainTopMenuTools(HookRenderBlockEvent $event) + { + $event->add( + [ + 'id' => 'tools_menu_carousel', + 'class' => '', + 'url' => URL::getInstance()->absoluteUrl('/admin/module/Carousel'), + 'title' => $this->trans('Edit your carousel', [], Carousel::DOMAIN_NAME) + ] + ); + } +} diff --git a/local/modules/Carousel/I18n/backOffice/default/de_DE.php b/local/modules/Carousel/I18n/backOffice/default/de_DE.php new file mode 100644 index 00000000..3efa0e2d --- /dev/null +++ b/local/modules/Carousel/I18n/backOffice/default/de_DE.php @@ -0,0 +1,14 @@ + 'Ein Bild zu Karussell hinzufügen', + 'Add this image to the carousel' => 'Dieses Bild zu Karussell hinzufügen', + 'Carousel image' => 'Karussell-Bild', + 'Carousel images' => 'Karussell-Bilder', + 'Delete a carousel image' => 'Ein Karussell-Bild löschen', + 'Do you really want to remove this image from the carousel ?' => 'Wollen Sie dieses Bild wirklich aus dem Karussell entfernen?', + 'Edit your carousel.' => 'Karussell bearbeiten.', + 'Remove this image' => 'Dieses Bild entfernen', + 'Your carousel contains no image. Please add one using the form above.' => 'Das Karussell enthält kein Bild. Bitte fügen Sie mit dem Formular oben eines hinzu.', + 'Position' => 'Position', +]; diff --git a/local/modules/Carousel/I18n/backOffice/default/en_US.php b/local/modules/Carousel/I18n/backOffice/default/en_US.php new file mode 100644 index 00000000..b2765eb2 --- /dev/null +++ b/local/modules/Carousel/I18n/backOffice/default/en_US.php @@ -0,0 +1,15 @@ + 'Add an image to the carousel', + 'Add this image to the carousel' => 'Add this image to the carousel', + 'Carousel image' => 'Carousel image', + 'Carousel images' => 'Carousel images', + 'Delete a carousel image' => 'Delete a carousel image', + 'Do you really want to remove this image from the carousel ?' => 'Do you really want to remove this image from the carousel ?', + 'Edit your carousel.' => 'Edit your carousel.', + 'Remove this image' => 'Remove this image', + 'Your carousel contains no image. Please add one using the form above.' => 'Your carousel contains no image. Please add one using the form above.', + 'Position' => 'Position', + 'YYYY-MM-DD' => 'YYYY-MM-DD', +); diff --git a/local/modules/Carousel/I18n/backOffice/default/fr_FR.php b/local/modules/Carousel/I18n/backOffice/default/fr_FR.php new file mode 100644 index 00000000..93fa9c1a --- /dev/null +++ b/local/modules/Carousel/I18n/backOffice/default/fr_FR.php @@ -0,0 +1,15 @@ + 'Ajouter une image au carrousel', + 'Add this image to the carousel' => 'Ajouter l\'image au carrousel', + 'Carousel image' => 'Image du carrousel', + 'Carousel images' => 'Images du carrousel', + 'Delete a carousel image' => 'Supprimer une image du carrousel', + 'Do you really want to remove this image from the carousel ?' => 'Voulez-vous vraiment retirer cette image du carrousel ?', + 'Edit your carousel.' => 'Modifier votre carrousel', + 'Remove this image' => 'Supprimer cette image', + 'Your carousel contains no image. Please add one using the form above.' => 'Votre carrousel ne contient aucune image. Ajoutez votre première image avec le formulaire ci-dessus', + 'Position' => 'Position', + 'YYYY-MM-DD' => 'AAAA-MM-JJ', +]; diff --git a/local/modules/Carousel/I18n/backOffice/default/ru_RU.php b/local/modules/Carousel/I18n/backOffice/default/ru_RU.php new file mode 100644 index 00000000..fdc531d4 --- /dev/null +++ b/local/modules/Carousel/I18n/backOffice/default/ru_RU.php @@ -0,0 +1,14 @@ + 'Добавить изображение в карусель', + 'Add this image to the carousel' => 'Добавить это изображение в карусель', + 'Carousel image' => 'Изображение карусели', + 'Carousel images' => 'Изображения карусели', + 'Delete a carousel image' => 'Удалить изображение карусели', + 'Do you really want to remove this image from the carousel ?' => 'Вы действительно хотите удалить это изображение из карусели ?', + 'Edit your carousel.' => 'Редактировать вашу карусель.', + 'Remove this image' => 'Удалить это изображение', + 'Your carousel contains no image. Please add one using the form above.' => 'Ваша карусель не содержит изображений. Пожалуйста, добавьте одно используя форму ниже.', + 'Position' => 'Позиция', +); diff --git a/local/modules/Carousel/I18n/backOffice/default/tr_TR.php b/local/modules/Carousel/I18n/backOffice/default/tr_TR.php new file mode 100644 index 00000000..c9f9f587 --- /dev/null +++ b/local/modules/Carousel/I18n/backOffice/default/tr_TR.php @@ -0,0 +1,14 @@ + 'Slayt için bir resim ekle', + 'Add this image to the carousel' => 'slayt için bu resim ekleme', + 'Carousel image' => 'slayt görüntü', + 'Carousel images' => 'slayt görüntüleri', + 'Delete a carousel image' => 'Bir slayt resmi silme', + 'Do you really want to remove this image from the carousel ?' => 'Bu görüntüyü slayttan kaldırmak istiyor musunuz?', + 'Edit your carousel.' => 'slayt düzenleyin.', + 'Remove this image' => 'Bu resmi kaldırma', + 'Your carousel contains no image. Please add one using the form above.' => 'Senin slayt hiçbir görüntü içermiyor . Lütfen yukarıdaki formu kullanarak ekleyin.', + 'Position' => 'Pozisyon', +]; diff --git a/local/modules/Carousel/I18n/de_DE.php b/local/modules/Carousel/I18n/de_DE.php new file mode 100644 index 00000000..35b35e10 --- /dev/null +++ b/local/modules/Carousel/I18n/de_DE.php @@ -0,0 +1,20 @@ + 'Beschreibungstitel', + 'A short description, used when a summary or an introduction is required' => 'Eine kurze beschreibung, benutzt wenn eine Zusammenfassung order eine Einleitung ist nötig', + 'A short text, used when an additional or supplemental information is required.' => 'Ein kurzer Text, der verwendet wird, wenn eine zusätzliche oder ergänzende Information erforderlich ist.', + 'Alternative image text' => 'Alternativer Bildtext', + 'Carousel image' => 'Karussell-Bild', + 'Conclusion' => 'Abschluss', + 'Detailed description' => 'Detaillierte Beschreibung', + 'Displayed when image is not visible' => 'Angezeigt, wenn das Bild nicht sichtbar ist', + 'Image URL' => 'Bild-URL', + 'Image position in carousel' => 'Position des Bildes im Karussell', + 'Please enter a valid URL' => 'Bitte geben Sie eine gültige URL ein', + 'Short additional text' => 'Kurzer zusätzlicher Text', + 'Short description text' => 'Kurzes Beschreibungstext', + 'Summary' => 'Zusammenfassung', + 'The detailed description.' => 'Die detaillierte Beschreibung.', + 'Title' => 'Titel', +]; diff --git a/local/modules/Carousel/I18n/en_US.php b/local/modules/Carousel/I18n/en_US.php new file mode 100644 index 00000000..173da8ed --- /dev/null +++ b/local/modules/Carousel/I18n/en_US.php @@ -0,0 +1,22 @@ + 'A descriptive title', + 'A short description, used when a summary or an introduction is required' => 'A short description, used when a summary or an introduction is required', + 'A short text, used when an additional or supplemental information is required.' => 'A short text, used when an additional or supplemental information is required.', + 'Alternative image text' => 'Alternative image text', + 'Carousel image' => 'Carousel image', + 'Conclusion' => 'Conclusion', + 'Detailed description' => 'Detailed description', + 'Displayed when image is not visible' => 'Displayed when image is not visible', + 'Edit your carousel' => 'Edit your carousel', + 'Image URL' => 'Image URL', + 'Image position in carousel' => 'Image position in carousel', + 'Please enter a valid URL' => 'Please enter a valid URL', + 'Short additional text' => 'Short additional text', + 'Short description text' => 'Short description text', + 'Summary' => 'Summary', + 'The detailed description.' => 'The detailed description.', + 'Title' => 'Title', + 'YYYY-MM-DD' => 'AAAA-MM-JJ', +); diff --git a/local/modules/Carousel/I18n/fr_FR.php b/local/modules/Carousel/I18n/fr_FR.php new file mode 100644 index 00000000..393cf82c --- /dev/null +++ b/local/modules/Carousel/I18n/fr_FR.php @@ -0,0 +1,27 @@ + 'Un titre descriptif', + 'A short description, used when a summary or an introduction is required' => 'Une courte description, utilisée lorsqu\'un résumé ou une introduction est requise', + 'A short text, used when an additional or supplemental information is required.' => 'Un texte court, utilisé quand une conclusion ou une information complémentaire est nécessaire.', + 'Alternative image text' => 'Texte alternatif de l\'image', + 'Carousel image' => 'Image du carrousel', + 'Conclusion' => 'Conclusion', + 'Detailed description' => 'Description détaillée', + 'Disable image' => 'Désactiver l\'image', + 'Displayed when image is not visible' => 'Affiché lorsque l\'image n\'est pas visible', + 'Edit your carousel' => 'Modifier votre carousel', + 'End date' => 'Date de fin', + 'Group image' => 'Groupe de l\'image', + 'Group of images' => 'Nom du groupe auquel l\'image appartient', + 'Image URL' => 'URL de l\'image', + 'Image position in carousel' => 'Position de l\'image dans le carrousel', + 'Limited' => 'Afficher l\'image entre les dates ci-dessous', + 'Please enter a valid URL' => 'Merci d\'indiquer une URL valide', + 'Short additional text' => 'Un court texte supplémentaire', + 'Short description text' => 'Un court texte de description', + 'Start date' => 'Date de début', + 'Summary' => 'Résumé', + 'The detailed description.' => 'La description détaillée.', + 'Title' => 'Titre', +); diff --git a/local/modules/Carousel/I18n/it_IT.php b/local/modules/Carousel/I18n/it_IT.php new file mode 100644 index 00000000..3919d98b --- /dev/null +++ b/local/modules/Carousel/I18n/it_IT.php @@ -0,0 +1,11 @@ + 'Un titolo descrittivo', + 'A short description, used when a summary or an introduction is required' => 'Una breve descrizione, utilizzata quando è necessario un sommario o un\'introduzione', + 'Conclusion' => 'Conclusione', + 'Detailed description' => 'Descrizione dettagliata', + 'Summary' => 'Riassunto', + 'The detailed description.' => 'La descrizione dettagliata.', + 'Title' => 'Titolo', +]; diff --git a/local/modules/Carousel/I18n/ru_RU.php b/local/modules/Carousel/I18n/ru_RU.php new file mode 100644 index 00000000..2477c5c8 --- /dev/null +++ b/local/modules/Carousel/I18n/ru_RU.php @@ -0,0 +1,21 @@ + 'Описательный заголовок', + 'A short description, used when a summary or an introduction is required' => 'Краткое описание, используется когда необходимо', + 'A short text, used when an additional or supplemental information is required.' => 'Краткий текст используемый, когда необходима дополнительной информации.', + 'Alternative image text' => 'Альтернативный текст изображения', + 'Carousel image' => 'Изображение карусели', + 'Conclusion' => 'Заключение', + 'Detailed description' => 'Детальное описание', + 'Displayed when image is not visible' => 'Отображается когда изображения не видно', + 'Edit your carousel' => 'Редактировать вашу карусель', + 'Image URL' => 'URL изображения', + 'Image position in carousel' => 'Позиция изображения в карусели', + 'Please enter a valid URL' => 'Пожалуйста введите корректный URL', + 'Short additional text' => 'Краткий дополнительный текст', + 'Short description text' => 'Текст краткого описания', + 'Summary' => 'Краткое описание', + 'The detailed description.' => 'Детальное описание', + 'Title' => 'Заголовок', +); diff --git a/local/modules/Carousel/I18n/tr_TR.php b/local/modules/Carousel/I18n/tr_TR.php new file mode 100644 index 00000000..e8505474 --- /dev/null +++ b/local/modules/Carousel/I18n/tr_TR.php @@ -0,0 +1,20 @@ + 'Açıklayıcı bir başlık', + 'A short description, used when a summary or an introduction is required' => 'Bir Özeti veya giriş gerekli olduğunda kullanılan kısa bir açıklama', + 'A short text, used when an additional or supplemental information is required.' => 'Bir ek ya da tamamlayıcı bilgi gerekli olduğunda kullanılan kısa bir metin.', + 'Alternative image text' => 'Alternatif resim metini', + 'Carousel image' => 'slayt görüntü', + 'Conclusion' => 'Sonuç', + 'Detailed description' => 'Detaylı açıklama', + 'Displayed when image is not visible' => 'resim görünür olmadığında görüntülenen', + 'Image URL' => 'Resim Bağlantı [Link]', + 'Image position in carousel' => 'slayt bulunduğu resim', + 'Please enter a valid URL' => 'Lütfen geçerli bir URL girin', + 'Short additional text' => 'Kısa ek metin', + 'Short description text' => 'Kısa açıklama metni', + 'Summary' => 'Özet', + 'The detailed description.' => 'Ayrıntılı açıklama.', + 'Title' => 'Başlık', +]; diff --git a/local/modules/Carousel/Loop/CarouselLoop.php b/local/modules/Carousel/Loop/CarouselLoop.php new file mode 100644 index 00000000..a4b3a4f7 --- /dev/null +++ b/local/modules/Carousel/Loop/CarouselLoop.php @@ -0,0 +1,242 @@ + + */ +class CarouselLoop extends Image +{ + + + /** + * @inheritdoc + */ + protected function getArgDefinitions() + { + return new ArgumentCollection( + Argument::createIntTypeArgument('width'), + Argument::createIntTypeArgument('height'), + Argument::createIntTypeArgument('rotation', 0), + Argument::createAnyTypeArgument('background_color'), + Argument::createIntTypeArgument('quality'), + new Argument( + 'resize_mode', + new TypeCollection( + new EnumType(array('crop', 'borders', 'none')) + ), + 'none' + ), + new Argument( + 'order', + new TypeCollection( + new EnumListType(array('alpha', 'alpha-reverse', 'manual', 'manual-reverse', 'random')) + ), + 'manual' + ), + Argument::createAnyTypeArgument('effects'), + Argument::createBooleanTypeArgument('allow_zoom', false), + Argument::createBooleanTypeArgument('filter_disable_slides', true), + Argument::createAlphaNumStringTypeArgument('group') + ); + } + + /** + * @param LoopResult $loopResult + * + * @return LoopResult + * @throws \Propel\Runtime\Exception\PropelException + */ + public function parseResults(LoopResult $loopResult) + { + /** @var \Carousel\Model\Carousel $carousel */ + foreach ($loopResult->getResultDataCollection() as $carousel) { + $imgSourcePath = $carousel->getUploadDir() . DS . $carousel->getFile(); + if (!file_exists($imgSourcePath)) { + Tlog::getInstance()->error(sprintf('Carousel source image file %s does not exists.', $imgSourcePath)); + continue; + } + + $startDate = $carousel->getStartDate(); + $endDate = $carousel->getEndDate(); + + if ($carousel->getLimited()) { + $now = new \DateTime(); + if ($carousel->getDisable()) { + if ($now > $startDate && $now < $endDate) { + $carousel + ->setDisable(0) + ->save(); + } + } else { + if ($now < $startDate || $now > $endDate) { + $carousel + ->setDisable(1) + ->save(); + } + } + } + + if ($this->getFilterDisableSlides() && $carousel->getDisable()) { + continue; + } + + $loopResultRow = new LoopResultRow($carousel); + + $event = new ImageEvent(); + $event->setSourceFilepath($imgSourcePath) + ->setCacheSubdirectory('carousel'); + + switch ($this->getResizeMode()) { + case 'crop': + $resize_mode = \Thelia\Action\Image::EXACT_RATIO_WITH_CROP; + break; + + case 'borders': + $resize_mode = \Thelia\Action\Image::EXACT_RATIO_WITH_BORDERS; + break; + + case 'none': + default: + $resize_mode = \Thelia\Action\Image::KEEP_IMAGE_RATIO; + + } + + // Prepare tranformations + $width = $this->getWidth(); + $height = $this->getHeight(); + $rotation = $this->getRotation(); + $background_color = $this->getBackgroundColor(); + $quality = $this->getQuality(); + $effects = $this->getEffects(); + + if (!is_null($width)) { + $event->setWidth($width); + } + if (!is_null($height)) { + $event->setHeight($height); + } + $event->setResizeMode($resize_mode); + if (!is_null($rotation)) { + $event->setRotation($rotation); + } + if (!is_null($background_color)) { + $event->setBackgroundColor($background_color); + } + if (!is_null($quality)) { + $event->setQuality($quality); + } + if (!is_null($effects)) { + $event->setEffects($effects); + } + + $event->setAllowZoom($this->getAllowZoom()); + + // Dispatch image processing event + $this->dispatcher->dispatch(TheliaEvents::IMAGE_PROCESS, $event); + + + if ($startDate) { + $startDate = $startDate->format('Y-m-d').'T'.$startDate->format('H:i'); + } + if ($endDate) { + $endDate = $endDate->format('Y-m-d').'T'.$endDate->format('H:i'); + } + + $loopResultRow + ->set('ID', $carousel->getId()) + ->set('LOCALE', $this->locale) + ->set('IMAGE_URL', $event->getFileUrl()) + ->set('ORIGINAL_IMAGE_URL', $event->getOriginalFileUrl()) + ->set('IMAGE_PATH', $event->getCacheFilepath()) + ->set('ORIGINAL_IMAGE_PATH', $event->getSourceFilepath()) + ->set('TITLE', $carousel->getVirtualColumn('i18n_TITLE')) + ->set('CHAPO', $carousel->getVirtualColumn('i18n_CHAPO')) + ->set('DESCRIPTION', $carousel->getVirtualColumn('i18n_DESCRIPTION')) + ->set('POSTSCRIPTUM', $carousel->getVirtualColumn('i18n_POSTSCRIPTUM')) + ->set('ALT', $carousel->getVirtualColumn('i18n_ALT')) + ->set('URL', $carousel->getUrl()) + ->set('POSITION', $carousel->getPosition()) + ->set('DISABLE', $carousel->getDisable()) + ->set('GROUP', $carousel->getGroup()) + ->set('LIMITED', $carousel->getLimited()) + ->set('START_DATE', $startDate) + ->set('END_DATE', $endDate) + ; + + $loopResult->addRow($loopResultRow); + } + + return $loopResult; + } + + /** + * this method returns a Propel ModelCriteria + * + * @return \Propel\Runtime\ActiveQuery\ModelCriteria + */ + public function buildModelCriteria() + { + $search = CarouselQuery::create(); + $group = $this->getGroup(); + + $this->configureI18nProcessing($search, [ 'ALT', 'TITLE', 'CHAPO', 'DESCRIPTION', 'POSTSCRIPTUM' ]); + + $orders = $this->getOrder(); + + // Results ordering + foreach ($orders as $order) { + switch ($order) { + case "alpha": + $search->addAscendingOrderByColumn('i18n_TITLE'); + break; + case "alpha-reverse": + $search->addDescendingOrderByColumn('i18n_TITLE'); + break; + case "manual-reverse": + $search->orderByPosition(Criteria::DESC); + break; + case "manual": + $search->orderByPosition(Criteria::ASC); + break; + case "random": + $search->clearOrderByColumns(); + $search->addAscendingOrderByColumn('RAND()'); + break(2); + break; + } + } + + if ($group){ + $search->filterByGroup($group); + } + + return $search; + } +} diff --git a/local/modules/Carousel/Model/Carousel.php b/local/modules/Carousel/Model/Carousel.php new file mode 100644 index 00000000..50971104 --- /dev/null +++ b/local/modules/Carousel/Model/Carousel.php @@ -0,0 +1,113 @@ +remove($carousel->getUploadDir() . DS . $this->getFile()); + + return true; + } catch (IOException $e) { + return false; + } + } + + /** + * Set file parent id + * + * @param int $parentId parent id + * + * @return $this + */ + public function setParentId($parentId) + { + return $this; + } + + /** + * Get file parent id + * + * @return int parent id + */ + public function getParentId() + { + return $this->getId(); + } + + /** + * @return FileModelParentInterface the parent file model + */ + public function getParentFileModel() + { + return new static; + } + + /** + * Get the ID of the form used to change this object information + * + * @return BaseForm the form + */ + public function getUpdateFormId() + { + return 'carousel.image'; + } + + /** + * @return string the path to the upload directory where files are stored, without final slash + */ + public function getUploadDir() + { + $carousel = new \Carousel\Carousel(); + return $carousel->getUploadDir(); + } + + /** + * @param int $objectId the object ID + * + * @return string the URL to redirect to after update from the back-office + */ + public function getRedirectionUrl() + { + return '/admin/module/Carousel'; + } + + /** + * Get the Query instance for this object + * + * @return ModelCriteria + */ + public function getQueryInstance() + { + return CarouselQuery::create(); + } + + /** + * @param bool $visible true if the file is visible, false otherwise + * @return FileModelInterface + */ + public function setVisible($visible) + { + // Not implemented + + return $this; + } +} diff --git a/local/modules/Carousel/Model/CarouselI18n.php b/local/modules/Carousel/Model/CarouselI18n.php new file mode 100644 index 00000000..d03081e3 --- /dev/null +++ b/local/modules/Carousel/Model/CarouselI18n.php @@ -0,0 +1,10 @@ +orderByPosition() + ->find(); + } +} // CarouselQuery diff --git a/local/modules/Carousel/Readme.md b/local/modules/Carousel/Readme.md new file mode 100644 index 00000000..830f32dc --- /dev/null +++ b/local/modules/Carousel/Readme.md @@ -0,0 +1,69 @@ +# Carousel + +This module for Thelia add a customizable carousel on your home page. You can upload you own image and overload the default template in your template for using the carousel. + +## Installation + +* Copy the module into ```/local/modules/``` directory and be sure that the name of the module is Carousel. +* Activate it in your thelia administration panel + +## Usage + +In the configuration panel of this module, you can upload as many images as you want. + +## Hook + +The carousel is installed in the "Home page - main area" (home.body) hook. + +## Loop + +Customize images with the `carousel` loop, which has the same arguments as the `image` loop. You can define a width, a height, and many other parameters + +### Input arguments + +|Argument |Description | +|--- |--- | +|**width** | A width in pixels, for resizing image. If only the width is provided, the image ratio is preserved. Example : width="200" | +|**height** | A height in pixels, for resizing image. If only the height is provided, the image ratio is preserved. example : height="200" | +|**rotation** |The rotation angle in degrees (positive or negative) applied to the image. The background color of the empty areas is the one specified by 'background_color'. example : rotation="90" | +|**background_color** |The color applied to empty image parts during processing. Use $rgb or $rrggbb color format. example : background_color="$cc8000"| +|**quality** |The generated image quality, from 0(!) to 100%. The default value is 75% (you can hange this in the Administration panel). example : quality="70"| +|**resize_mode** | If 'crop', the image will have the exact specified width and height, and will be cropped if required. If 'borders', the image will have the exact specified width and height, and some borders may be added. The border color is the one specified by 'background_color'. If 'none' or missing, the image ratio is preserved, and depending od this ratio, may not have the exact width and height required. resize_mode="crop"| +|**effects** |One or more comma separated effects definitions, that will be applied to the image in the specified order. Please see below a detailed description of available effects. Expected values :
    • gamma:value : change the image Gamma to the specified value. Example: gamma:0.7.
    • grayscale or greyscale : switch image to grayscale.
    • colorize:color : apply a color mask to the image. The color format is $rgb or $rrggbb. Example: colorize:$ff2244.
    • negative : transform the image in its negative equivalent.
    • vflip or vertical_flip : flip the image vertically.
    • hflip or horizontal_flip : flip the image horizontally.
    example : effects="greyscale,gamma:0.7,vflip" | +|**group** |The name of an image group. Return only images from the specified group| +|**filter_disable_slides** |if true (the default), the disabled slides will not be displayed| + +### Ouput arguments + +|Variable |Description | +|--- |--- | +|$ID |the image ID | +|$IMAGE_URL |The absolute URL to the generated image | +|$ORIGINAL_IMAGE_URL |The absolute URL to the original image | +|$IMAGE_PATH |The absolute path to the generated image file | +|$ORIGINAL_IMAGE_PATH |The absolute path to the original image file | +|$ALT |alt text | +|$TITLE |the slide title | +|$CHAPO |the slide summary | +|$DESCRIPTION |the slide description | +|$POSTSCRIPTUM |the slide conclusion | +|$LOCALE |the textual elements locale | +|$POSITION |the slide position in the carousel | +|$URL |the related URL | +|$LIMITED| true if slide is disabled, false otherwise | +|$START_DATE| limited slide display start date | +|$END_DATE| limited slide display end date | +|$DISABLE| true if slide display is limited | +|$GROUP| name of the group the slide belong to | + +### Exemple + +``` +{loop type="carousel" name="carousel.front" width="1200" height="390" resize_mode="borders"} + {$ALT} +{/loop} +``` + +## How to override ? + +If you want your own carousel in your tempalte, create the directory ```modules/Carousel``` then create the template ```carousel.html``` in this directory. Here you can create your own carousel and the replace the default template provided in the module. diff --git a/local/modules/Carousel/composer.json b/local/modules/Carousel/composer.json new file mode 100644 index 00000000..5cfd6d37 --- /dev/null +++ b/local/modules/Carousel/composer.json @@ -0,0 +1,11 @@ +{ + "name": "thelia/carousel-module", + "license": "LGPL-3.0+", + "type": "thelia-module", + "require": { + "thelia/installer": "~1.1" + }, + "extra": { + "installer-name": "Carousel" + } +} diff --git a/local/modules/Carousel/templates/backOffice/default/assets/js/module-configuration.js b/local/modules/Carousel/templates/backOffice/default/assets/js/module-configuration.js new file mode 100644 index 00000000..54b03e5f --- /dev/null +++ b/local/modules/Carousel/templates/backOffice/default/assets/js/module-configuration.js @@ -0,0 +1,6 @@ +$(function() { + // Set proper image ID in delete from + $('a.image-delete').click(function(ev) { + $('#image_delete_id').val($(this).data('id')); + }); +}); diff --git a/local/modules/Carousel/templates/backOffice/default/module_configuration.html b/local/modules/Carousel/templates/backOffice/default/module_configuration.html new file mode 100644 index 00000000..3990a879 --- /dev/null +++ b/local/modules/Carousel/templates/backOffice/default/module_configuration.html @@ -0,0 +1,179 @@ +
    +
    +
    + {intl l='Edit your carousel.' d='carousel.bo.default'} +
    +
    + +
    +
    +
    + {form name="carousel.image"} + + + {form_hidden_fields} + + {form_field field='file'} +
    + +
    + + + + +
    +
    + {/form_field} + + {/form} +
    +
    +
    + +
    +
    + {intl l='Carousel images' d='carousel.bo.default'} +
    +
    + +
    +
    +
    + {ifloop rel="carousel.image"} + {form name="carousel.update"} +
    + + {include + file = "includes/inner-form-toolbar.html" + page_url = "{url path='/admin/module/Carousel'}" + close_url = "{url path='/admin/modules'}" + } + + {form_hidden_fields} + + {loop name="carousel.image" type="carousel" width="550" height="200" resize_mode="borders" backend_context="1" lang="$edit_language_id" filter_disable_slides=false} + +
    +
    +
    +

    + + {$ALT} + +

    + + + +
    +
    + +
    +
    + {form_field field="position{$ID}"} + + {/form_field} +
    +
    +
    +
    + {form_field field="disable{$ID}"} + + + {/form_field} +
    +
    + {form_field field="limited{$ID}"} + + + {/form_field} +
    + +
    + {form_field field="start_date{$ID}"} + +
    + +
    + {/form_field} +
    + +
    + {form_field field="end_date{$ID}"} + +
    + +
    + {/form_field} +
    +
    +
    + +
    + {* Not yet implemented + {render_form_field field="chapo{$ID} value=$CHAPO"} + *} + {render_form_field field="title{$ID}" value=$TITLE} + {render_form_field field="alt{$ID}" value=$ALT} + {render_form_field field="url{$ID}" value=$URL} + {render_form_field field="description{$ID}" extra_class="wysiwyg" value=$DESCRIPTION} + {render_form_field field="group{$ID}" value=$GROUP} + {* Not yet implemented + {render_form_field field="postscriptum{$ID}" value=$POSTSCRIPTUM} + *} +
    +
    +
    + {/loop} + + {include + file = "includes/inner-form-toolbar.html" + page_url = "{url path='/admin/module/Carousel'}" + close_url = "{url path='/admin/modules'}" + page_bottom = true + } +
    + {/form} + {/ifloop} + + {elseloop rel="carousel.image"} +
    + {intl d='carousel.bo.default' l="Your carousel contains no image. Please add one using the form above."} +
    + {/elseloop} +
    +
    +
    +
    + +{capture "delete_dialog"} + +{/capture} + +{include +file = "includes/generic-confirm-dialog.html" + +dialog_id = "delete_carousel_dialog" +dialog_title = {intl l="Delete a carousel image" d="carousel.bo.default"} +dialog_message = {intl l="Do you really want to remove this image from the carousel ?" d="carousel.bo.default"} + +form_action = {url path='/admin/module/carousel/delete'} +form_content = {$smarty.capture.delete_dialog nofilter} +} + + + + diff --git a/local/modules/Carousel/templates/frontOffice/default/carousel.html b/local/modules/Carousel/templates/frontOffice/default/carousel.html new file mode 100644 index 00000000..6a714a5e --- /dev/null +++ b/local/modules/Carousel/templates/frontOffice/default/carousel.html @@ -0,0 +1,24 @@ +{ifloop rel="carousel.front"} + +{/ifloop} \ No newline at end of file diff --git a/local/modules/Cheque/Cheque.php b/local/modules/Cheque/Cheque.php new file mode 100644 index 00000000..91cfc8cb --- /dev/null +++ b/local/modules/Cheque/Cheque.php @@ -0,0 +1,74 @@ +getCurrentOrderTotalAmount() > 0; + } + + public function postActivation(ConnectionInterface $con = null) + { + $database = new Database($con); + + // Insert email message + $database->insertSql(null, array(__DIR__ . "/Config/setup.sql")); + } + + public function destroy(ConnectionInterface $con = null, $deleteModuleData = false) + { + // Delete our message + if (null !== $message = MessageQuery::create()->findOneByName('order_confirmation_cheque')) { + $message->delete($con); + } + + parent::destroy($con, $deleteModuleData); + } + + /** + * if you want, you can manage stock in your module instead of order process. + * Return false if you want to manage yourself the stock + * + * @return bool + */ + public function manageStockOnCreation() + { + return false; + } +} diff --git a/local/modules/Cheque/Config/config.xml b/local/modules/Cheque/Config/config.xml new file mode 100644 index 00000000..b09cf496 --- /dev/null +++ b/local/modules/Cheque/Config/config.xml @@ -0,0 +1,25 @@ + + + + + +
    + + + + + + + + + + + + + + + + + diff --git a/local/modules/Cheque/Config/module.xml b/local/modules/Cheque/Config/module.xml new file mode 100644 index 00000000..723c08ad --- /dev/null +++ b/local/modules/Cheque/Config/module.xml @@ -0,0 +1,25 @@ + + + Cheque\Cheque + + Cheque + + + Cheque + + images + + en_US + fr_FR + + 2.4.3 + + Manuel Raynaud + manu@raynaud.io + + payment + 2.4.3 + alpha + diff --git a/local/modules/Cheque/Config/routing.xml b/local/modules/Cheque/Config/routing.xml new file mode 100644 index 00000000..8c741c05 --- /dev/null +++ b/local/modules/Cheque/Config/routing.xml @@ -0,0 +1,9 @@ + + + + + Cheque\Controller\ConfigureController::configure + + diff --git a/local/modules/Cheque/Config/setup.sql b/local/modules/Cheque/Config/setup.sql new file mode 100644 index 00000000..2f91a0e7 --- /dev/null +++ b/local/modules/Cheque/Config/setup.sql @@ -0,0 +1,32 @@ +-- --------------------------------------------------------------------- +-- Mail template for cheque +-- --------------------------------------------------------------------- + +-- First, delete existing entries +SET @var := 0; +SELECT @var := `id` FROM `message` WHERE name="order_confirmation_cheque"; +DELETE FROM `message` WHERE `id`=@var; + +-- Then add new entries +SELECT @max := MAX(`id`) FROM `message`; +SET @max := @max+1; + +-- insert message +INSERT INTO `message` (`id`, `name`, `secured`) VALUES + (@max, + 'order_confirmation_cheque', + '0' + ); +-- and mail templates +INSERT INTO `message_i18n` (`id`, `locale`, `title`, `subject`, `text_message`, `html_message`) VALUES + (@max, + 'en_US', + 'Confirmation of payment by cheque', + 'Payment of order {$order_ref}', 'Dear customer,\r\nThis is a confirmation of the payment by cheque of your order {$order_ref} on our shop.\r\nYour invoice is now available in your customer account at {config key="url_site"}\r\nThank you again for your purchase.\r\nThe {config key="store_name"} team.', '\r\n\r\n\r\n \r\n courriel de confirmation de commande de {config key="url_site"} \r\n \r\n\r\n\r\n
    \r\n
    \r\n

    {config key="store_name"}

    \r\n

    The payment of your order is confirmed

    \r\n

    Reference {$order_ref}

    \r\n
    \r\n

    \r\n Your invoice is now available in your customer account on\r\n {config key="store_name"}.\r\n

    \r\n

    Thank you for your order !

    \r\n

    The {config key="store_name"} team.

    \r\n
    \r\n\r\n' + ), + (@max, + 'fr_FR', + 'Confirmation de paiement par chèque', + 'Paiement de la commande : {$order_ref}', + 'Cher client,\r\nCe message confirme le paiement par chèque de votre commande numero {$order_ref} sur notre boutique.\r\nVotre facture est maintenant disponible dans votre compte client à l''adresse {config key="url_site"}\r\nMerci encore pour votre achat !\r\nL''équipe {config key="store_name"}', '\r\n\r\n\r\n \r\n Confirmation du paiement de votre commande sur {config key="url_site"} \r\n \r\n\r\n\r\n
    \r\n
    \r\n

    {config key="store_name"}

    \r\n

    Confirmation du paiement de votre commande

    \r\n

    N° {$order_ref}

    \r\n
    \r\n

    \r\n Le suivi de votre commande est disponible dans la rubrique mon compte sur\r\n {config key="url_site"}\r\n

    \r\n

    Merci pour votre achat !

    \r\n

    L''équipe {config key="store_name"}

    \r\n
    \r\n\r\n' + ); diff --git a/local/modules/Cheque/Controller/ConfigureController.php b/local/modules/Cheque/Controller/ConfigureController.php new file mode 100644 index 00000000..5aea04ed --- /dev/null +++ b/local/modules/Cheque/Controller/ConfigureController.php @@ -0,0 +1,98 @@ +. */ +/* */ +/*************************************************************************************/ + +namespace Cheque\Controller; + +use Cheque\Cheque; +use Cheque\Form\ConfigurationForm; +use Symfony\Component\HttpFoundation\RedirectResponse; +use Thelia\Controller\Admin\BaseAdminController; +use Thelia\Core\Security\AccessManager; +use Thelia\Core\Security\Resource\AdminResources; +use Thelia\Form\Exception\FormValidationException; +use Thelia\Tools\URL; + +/** + * Class SetTransferConfig + * @package WireTransfer\Controller + * @author Thelia + */ +class ConfigureController extends BaseAdminController +{ + public function configure() + { + if (null !== $response = $this->checkAuth(AdminResources::MODULE, 'Cheque', AccessManager::UPDATE)) { + return $response; + } + + // Initialize the potential exception + $ex = null; + + // Create the Form from the request + $configurationForm = $this->createForm('cheque.instructions.configure'); + + try { + // Check the form against constraints violations + $form = $this->validateForm($configurationForm, "POST"); + + // Get the form field values + $data = $form->getData(); + + Cheque::setConfigValue('instructions', $data['instructions'], $this->getCurrentEditionLocale()); + Cheque::setConfigValue('payable_to', $data['payable_to']); + + // Log configuration modification + $this->adminLogAppend( + "cheque.configuration.message", + AccessManager::UPDATE, + sprintf("Cheque instructions configuration updated") + ); + + // Everything is OK. + return new RedirectResponse(URL::getInstance()->absoluteUrl('/admin/module/Cheque')); + + } catch (FormValidationException $ex) { + // Form cannot be validated. Create the error message using + // the BaseAdminController helper method. + $error_msg = $this->createStandardFormValidationErrorMessage($ex); + } + catch (\Exception $ex) { + // Any other error + $error_msg = $ex->getMessage(); + } + + // At this point, the form has errors, and should be redisplayed. We don not redirect, + // just redisplay the same template. + // Setup the Form error context, to make error information available in the template. + $this->setupFormErrorContext( + $this->getTranslator()->trans("Cheque instructions configuration", [], Cheque::MESSAGE_DOMAIN), + $error_msg, + $configurationForm, + $ex + ); + + // Do not redirect at this point, or the error context will be lost. + // Just redisplay the current template. + return $this->render('module-configure', array('module_code' => 'Cheque')); + } +} \ No newline at end of file diff --git a/local/modules/Cheque/Form/ConfigurationForm.php b/local/modules/Cheque/Form/ConfigurationForm.php new file mode 100644 index 00000000..6ab4d5a0 --- /dev/null +++ b/local/modules/Cheque/Form/ConfigurationForm.php @@ -0,0 +1,90 @@ +. */ +/* */ +/*************************************************************************************/ + +namespace Cheque\Form; + +use Cheque\Cheque; +use Symfony\Component\Validator\Constraints\NotBlank; +use Thelia\Core\Translation\Translator; +use Thelia\Form\BaseForm; + +/** + * Class ConfigurationForm + * @package Cheque\Form + * @author Thelia + */ +class ConfigurationForm extends BaseForm +{ + protected function trans($str, $params = []) + { + return Translator::getInstance()->trans($str, $params, Cheque::MESSAGE_DOMAIN); + } + + protected function buildForm() + { + $this->formBuilder + ->add( + 'payable_to', + 'text', + [ + 'constraints' => [ new NotBlank() ], + 'label' => $this->trans('Cheque is payable to: '), + 'label_attr' => [ + 'for' => 'payable_to', + 'help' => $this->trans('The name to which the cheque shoud be payable to.') + ], + 'attr' => [ + 'rows' => 10, + 'placeholder' => $this->trans('Pay cheque to') + ] + ] + ) + ->add( + 'instructions', + 'textarea', + [ + 'constraints' => [], + 'required' => false, + 'label' => $this->trans('Cheque instructions'), + 'label_attr' => [ + 'for' => 'namefield', + 'help' => $this->trans('Please enter here the payment by cheque instructions') + ], + 'attr' => [ + 'rows' => 10, + 'placeholder' => $this->trans('Payment instruction') + ] + ] + ) + ; + } + + /** + * @return string the name of you form. This name must be unique + */ + public function getName() + { + return 'cheque_configuration_instructions'; + } +} \ No newline at end of file diff --git a/local/modules/Cheque/Hook/HookManager.php b/local/modules/Cheque/Hook/HookManager.php new file mode 100644 index 00000000..c0798886 --- /dev/null +++ b/local/modules/Cheque/Hook/HookManager.php @@ -0,0 +1,34 @@ + + */ +class HookManager extends BaseHook { + + public function onAdditionalPaymentInfo(HookRenderEvent $event) + { + $content = $this->render("order-placed.additional-payment-info.html", [ + 'placed_order_id' => $event->getArgument('placed_order_id') + ]); + + $event->add($content); + } +} \ No newline at end of file diff --git a/local/modules/Cheque/I18n/backOffice/default/de_DE.php b/local/modules/Cheque/I18n/backOffice/default/de_DE.php new file mode 100644 index 00000000..6e6d3a79 --- /dev/null +++ b/local/modules/Cheque/I18n/backOffice/default/de_DE.php @@ -0,0 +1,5 @@ + 'Scheck-Anleitungen-Konfiguration', +]; diff --git a/local/modules/Cheque/I18n/backOffice/default/en_US.php b/local/modules/Cheque/I18n/backOffice/default/en_US.php new file mode 100644 index 00000000..2219a2f7 --- /dev/null +++ b/local/modules/Cheque/I18n/backOffice/default/en_US.php @@ -0,0 +1,5 @@ + 'Cheque instructions configuration', +); diff --git a/local/modules/Cheque/I18n/backOffice/default/fr_FR.php b/local/modules/Cheque/I18n/backOffice/default/fr_FR.php new file mode 100644 index 00000000..71ae3192 --- /dev/null +++ b/local/modules/Cheque/I18n/backOffice/default/fr_FR.php @@ -0,0 +1,5 @@ + 'Instructions de paiement par chèque', +]; diff --git a/local/modules/Cheque/I18n/backOffice/default/ru_RU.php b/local/modules/Cheque/I18n/backOffice/default/ru_RU.php new file mode 100644 index 00000000..ab082b9a --- /dev/null +++ b/local/modules/Cheque/I18n/backOffice/default/ru_RU.php @@ -0,0 +1,5 @@ + 'Конфигурация инструкций для чека', +); diff --git a/local/modules/Cheque/I18n/backOffice/default/tr_TR.php b/local/modules/Cheque/I18n/backOffice/default/tr_TR.php new file mode 100644 index 00000000..9490b898 --- /dev/null +++ b/local/modules/Cheque/I18n/backOffice/default/tr_TR.php @@ -0,0 +1,5 @@ + 'Çek yönergeleri yapılandırma', +]; diff --git a/local/modules/Cheque/I18n/de_DE.php b/local/modules/Cheque/I18n/de_DE.php new file mode 100644 index 00000000..ffd4ad36 --- /dev/null +++ b/local/modules/Cheque/I18n/de_DE.php @@ -0,0 +1,11 @@ + 'Scheck-Anweisungen', + 'Cheque instructions configuration' => 'Scheck-Anleitungen-Konfiguration', + 'Cheque is payable to: ' => 'Scheck ist zahlbar an: ', + 'Pay cheque to' => 'Scheck bezahlen an', + 'Payment instruction' => 'Zahlungsanweisungen', + 'Please enter here the payment by cheque instructions' => 'Bitte geben Sie hier die Zahlung durch Scheck Anweisungen ein', + 'The name to which the cheque shoud be payable to.' => 'Der Name, an den der Scheck bezahlbar sein soll.', +]; diff --git a/local/modules/Cheque/I18n/en_US.php b/local/modules/Cheque/I18n/en_US.php new file mode 100644 index 00000000..9a0ebf14 --- /dev/null +++ b/local/modules/Cheque/I18n/en_US.php @@ -0,0 +1,11 @@ + 'Cheque instructions', + 'Cheque instructions configuration' => 'Cheque instructions configuration', + 'Cheque is payable to: ' => 'Cheque is payable to: ', + 'Pay cheque to' => 'Pay cheque to', + 'Payment instruction' => 'Payment instruction', + 'Please enter here the payment by cheque instructions' => 'Please enter here the payment by cheque instructions', + 'The name to which the cheque shoud be payable to.' => 'The name to which the cheque shoud be payable to.', +); diff --git a/local/modules/Cheque/I18n/fr_FR.php b/local/modules/Cheque/I18n/fr_FR.php new file mode 100644 index 00000000..b286ccaf --- /dev/null +++ b/local/modules/Cheque/I18n/fr_FR.php @@ -0,0 +1,11 @@ + 'Instructions de paiement', + 'Cheque instructions configuration' => 'Instructions de paiement par chèque', + 'Cheque is payable to: ' => 'Ordre du chèque', + 'Pay cheque to' => 'Ordre du chèque', + 'Payment instruction' => 'Instructions de paiement', + 'Please enter here the payment by cheque instructions' => 'Indiquez ici les instructions particulières de paiement par chèque', + 'The name to which the cheque shoud be payable to.' => 'Le nom à fare figurer sur le chèque', +]; diff --git a/local/modules/Cheque/I18n/frontOffice/default/de_DE.php b/local/modules/Cheque/I18n/frontOffice/default/de_DE.php new file mode 100644 index 00000000..b87c46ae --- /dev/null +++ b/local/modules/Cheque/I18n/frontOffice/default/de_DE.php @@ -0,0 +1,6 @@ + 'Vergessen Sie nicht, Ihren Scheck zu unterschreiben !', + 'Please make your cheque payable to %name, and send it to the following address :' => 'Bitte stellen Sie den Scheck auf %name, und senden Sie es an die folgende Adresse : ', +]; diff --git a/local/modules/Cheque/I18n/frontOffice/default/en_US.php b/local/modules/Cheque/I18n/frontOffice/default/en_US.php new file mode 100644 index 00000000..ac9f8aaa --- /dev/null +++ b/local/modules/Cheque/I18n/frontOffice/default/en_US.php @@ -0,0 +1,6 @@ + 'Be sure to sign your cheque !', + 'Please make your cheque payable to %name, and send it to the following address :' => 'Please make your cheque payable to %name, and send it to the following address :', +); diff --git a/local/modules/Cheque/I18n/frontOffice/default/fr_FR.php b/local/modules/Cheque/I18n/frontOffice/default/fr_FR.php new file mode 100644 index 00000000..b2ac1579 --- /dev/null +++ b/local/modules/Cheque/I18n/frontOffice/default/fr_FR.php @@ -0,0 +1,6 @@ + 'N\'oubliez par de signer votre chèque !', + 'Please make your cheque payable to %name, and send it to the following address :' => 'Merci de libeller votre chèque à l\'ordre de %name, et de l\'expédier à l\'adresse suivante :', +]; diff --git a/local/modules/Cheque/I18n/frontOffice/default/ru_RU.php b/local/modules/Cheque/I18n/frontOffice/default/ru_RU.php new file mode 100644 index 00000000..87fc98c9 --- /dev/null +++ b/local/modules/Cheque/I18n/frontOffice/default/ru_RU.php @@ -0,0 +1,6 @@ + 'Убедитесь в том, что подписали чек !', + 'Please make your cheque payable to %name, and send it to the following address :' => 'Пожалуйста убедитесь что ваш чек предназначен %name, и вышлите его по следующему адресу :', +); diff --git a/local/modules/Cheque/I18n/frontOffice/default/tr_TR.php b/local/modules/Cheque/I18n/frontOffice/default/tr_TR.php new file mode 100644 index 00000000..1337c364 --- /dev/null +++ b/local/modules/Cheque/I18n/frontOffice/default/tr_TR.php @@ -0,0 +1,6 @@ + 'Çekini imzalamak emin olun!', + 'Please make your cheque payable to %name, and send it to the following address :' => 'Lütfen, Çek %name için ödenecek olun ve aşağıdaki adrese gönderin:', +]; diff --git a/local/modules/Cheque/I18n/ru_RU.php b/local/modules/Cheque/I18n/ru_RU.php new file mode 100644 index 00000000..349db52b --- /dev/null +++ b/local/modules/Cheque/I18n/ru_RU.php @@ -0,0 +1,11 @@ + 'Инструкция для чека', + 'Cheque instructions configuration' => 'Конфигурация инструкций для чека', + 'Cheque is payable to: ' => 'Чек предназначен:', + 'Pay cheque to' => 'Оплата чеком для', + 'Payment instruction' => 'Инструкции для оплаты', + 'Please enter here the payment by cheque instructions' => 'Введите здесь инструкции для оплаты чеком', + 'The name to which the cheque shoud be payable to.' => 'Имя получателя чека.', +); diff --git a/local/modules/Cheque/I18n/tr_TR.php b/local/modules/Cheque/I18n/tr_TR.php new file mode 100644 index 00000000..80a9c5e3 --- /dev/null +++ b/local/modules/Cheque/I18n/tr_TR.php @@ -0,0 +1,11 @@ + 'Çek yönergeleri', + 'Cheque instructions configuration' => 'Çek yönergeleri yapılandırma', + 'Cheque is payable to: ' => 'Çek için ödenir: ', + 'Pay cheque to' => 'Çek için ödeme', + 'Payment instruction' => 'Ödeme talimatı', + 'Please enter here the payment by cheque instructions' => 'Lütfen burada ödeme çek yönergeleri tarafından girin', + 'The name to which the cheque shoud be payable to.' => 'Adı için çek shoud için ödenecek.', +]; diff --git a/local/modules/Cheque/LICENSE.txt b/local/modules/Cheque/LICENSE.txt new file mode 100644 index 00000000..65c5ca88 --- /dev/null +++ b/local/modules/Cheque/LICENSE.txt @@ -0,0 +1,165 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + + This version of the GNU Lesser General Public License incorporates +the terms and conditions of version 3 of the GNU General Public +License, supplemented by the additional permissions listed below. + + 0. Additional Definitions. + + As used herein, "this License" refers to version 3 of the GNU Lesser +General Public License, and the "GNU GPL" refers to version 3 of the GNU +General Public License. + + "The Library" refers to a covered work governed by this License, +other than an Application or a Combined Work as defined below. + + An "Application" is any work that makes use of an interface provided +by the Library, but which is not otherwise based on the Library. +Defining a subclass of a class defined by the Library is deemed a mode +of using an interface provided by the Library. + + A "Combined Work" is a work produced by combining or linking an +Application with the Library. The particular version of the Library +with which the Combined Work was made is also called the "Linked +Version". + + The "Minimal Corresponding Source" for a Combined Work means the +Corresponding Source for the Combined Work, excluding any source code +for portions of the Combined Work that, considered in isolation, are +based on the Application, and not on the Linked Version. + + The "Corresponding Application Code" for a Combined Work means the +object code and/or source code for the Application, including any data +and utility programs needed for reproducing the Combined Work from the +Application, but excluding the System Libraries of the Combined Work. + + 1. Exception to Section 3 of the GNU GPL. + + You may convey a covered work under sections 3 and 4 of this License +without being bound by section 3 of the GNU GPL. + + 2. Conveying Modified Versions. + + If you modify a copy of the Library, and, in your modifications, a +facility refers to a function or data to be supplied by an Application +that uses the facility (other than as an argument passed when the +facility is invoked), then you may convey a copy of the modified +version: + + a) under this License, provided that you make a good faith effort to + ensure that, in the event an Application does not supply the + function or data, the facility still operates, and performs + whatever part of its purpose remains meaningful, or + + b) under the GNU GPL, with none of the additional permissions of + this License applicable to that copy. + + 3. Object Code Incorporating Material from Library Header Files. + + The object code form of an Application may incorporate material from +a header file that is part of the Library. You may convey such object +code under terms of your choice, provided that, if the incorporated +material is not limited to numerical parameters, data structure +layouts and accessors, or small macros, inline functions and templates +(ten or fewer lines in length), you do both of the following: + + a) Give prominent notice with each copy of the object code that the + Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the object code with a copy of the GNU GPL and this license + document. + + 4. Combined Works. + + You may convey a Combined Work under terms of your choice that, +taken together, effectively do not restrict modification of the +portions of the Library contained in the Combined Work and reverse +engineering for debugging such modifications, if you also do each of +the following: + + a) Give prominent notice with each copy of the Combined Work that + the Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the Combined Work with a copy of the GNU GPL and this license + document. + + c) For a Combined Work that displays copyright notices during + execution, include the copyright notice for the Library among + these notices, as well as a reference directing the user to the + copies of the GNU GPL and this license document. + + d) Do one of the following: + + 0) Convey the Minimal Corresponding Source under the terms of this + License, and the Corresponding Application Code in a form + suitable for, and under terms that permit, the user to + recombine or relink the Application with a modified version of + the Linked Version to produce a modified Combined Work, in the + manner specified by section 6 of the GNU GPL for conveying + Corresponding Source. + + 1) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (a) uses at run time + a copy of the Library already present on the user's computer + system, and (b) will operate properly with a modified version + of the Library that is interface-compatible with the Linked + Version. + + e) Provide Installation Information, but only if you would otherwise + be required to provide such information under section 6 of the + GNU GPL, and only to the extent that such information is + necessary to install and execute a modified version of the + Combined Work produced by recombining or relinking the + Application with a modified version of the Linked Version. (If + you use option 4d0, the Installation Information must accompany + the Minimal Corresponding Source and Corresponding Application + Code. If you use option 4d1, you must provide the Installation + Information in the manner specified by section 6 of the GNU GPL + for conveying Corresponding Source.) + + 5. Combined Libraries. + + You may place library facilities that are a work based on the +Library side by side in a single library together with other library +facilities that are not Applications and are not covered by this +License, and convey such a combined library under terms of your +choice, if you do both of the following: + + a) Accompany the combined library with a copy of the same work based + on the Library, uncombined with any other library facilities, + conveyed under the terms of this License. + + b) Give prominent notice with the combined library that part of it + is a work based on the Library, and explaining where to find the + accompanying uncombined form of the same work. + + 6. Revised Versions of the GNU Lesser General Public License. + + The Free Software Foundation may publish revised and/or new versions +of the GNU Lesser General Public License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. + + Each version is given a distinguishing version number. If the +Library as you received it specifies that a certain numbered version +of the GNU Lesser General Public License "or any later version" +applies to it, you have the option of following the terms and +conditions either of that published version or of any later version +published by the Free Software Foundation. If the Library as you +received it does not specify a version number of the GNU Lesser +General Public License, you may choose any version of the GNU Lesser +General Public License ever published by the Free Software Foundation. + + If the Library as you received it specifies that a proxy can decide +whether future versions of the GNU Lesser General Public License shall +apply, that proxy's public statement of acceptance of any version is +permanent authorization for you to choose that version for the +Library. diff --git a/local/modules/Cheque/Listener/SendPaymentConfirmationEmail.php b/local/modules/Cheque/Listener/SendPaymentConfirmationEmail.php new file mode 100644 index 00000000..bad9482a --- /dev/null +++ b/local/modules/Cheque/Listener/SendPaymentConfirmationEmail.php @@ -0,0 +1,85 @@ +. */ +/* */ +/*************************************************************************************/ + +namespace Cheque\Listener; + +use Cheque\Cheque; +use Symfony\Component\EventDispatcher\EventSubscriberInterface; +use Thelia\Action\BaseAction; +use Thelia\Core\Event\Order\OrderEvent; +use Thelia\Core\Event\TheliaEvents; +use Thelia\Mailer\MailerFactory; + +/** + * Class SendEMail + * @package IciRelais\Listener + * @author Thelia + */ +class SendPaymentConfirmationEmail extends BaseAction implements EventSubscriberInterface +{ + /** + * @var MailerFactory + */ + protected $mailer; + + public function __construct(MailerFactory $mailer) + { + $this->mailer = $mailer; + } + + /** + * @param OrderEvent $event + * + * Check if we're the payment module, and send the payment confirmation email to the customer if it's the case. + */ + public function sendConfirmationEmail(OrderEvent $event) + { + if ($event->getOrder()->getPaymentModuleId() === Cheque::getModuleId()) { + + if ($event->getOrder()->isPaid()) { + + $order = $event->getOrder(); + + $this->mailer->sendEmailToCustomer( + 'order_confirmation_cheque', + $order->getCustomer(), + [ + 'order_id' => $order->getId(), + 'order_ref' => $order->getRef() + ] + ); + } + } + } + + /** + * @inheritdoc + */ + public static function getSubscribedEvents() + { + return array( + TheliaEvents::ORDER_UPDATE_STATUS => array("sendConfirmationEmail", 128) + ); + } + +} diff --git a/local/modules/Cheque/composer.json b/local/modules/Cheque/composer.json new file mode 100644 index 00000000..8dca2321 --- /dev/null +++ b/local/modules/Cheque/composer.json @@ -0,0 +1,11 @@ +{ + "name": "thelia/cheque-module", + "license": "LGPL-3.0+", + "type": "thelia-module", + "require": { + "thelia/installer": "~1.1" + }, + "extra": { + "installer-name": "Cheque" + } +} diff --git a/local/modules/Cheque/images/cheque.png b/local/modules/Cheque/images/cheque.png new file mode 100644 index 0000000000000000000000000000000000000000..0aad099e715aa796a29e77934cf421e7fe7b54e7 GIT binary patch literal 24812 zcmeHwbySpH*ZvTqq#_6?NDSTGB`|bIcQXS+cM1Z6G)PEGD@u17ln7FSfP{pIba%sd zk3Qkc`@F1ot?&D--#@Szm~-!Y?{m(z_rCT%w~mG?D@kKx+`#~WK-jV}5LMu}74VX} zh6enkx{ovp{6cq-(QyWWF!2yCBv8sTA`pmw%Tit2MO#rpz|7v3#RO_^3S;rGbpY-L zfrLao98AotVJ_sRFbhjNVes1P1~9oLR2Zzqt;nY6AOVA0%6K`!)V!3`&AhD5_@Q7? z5ey*@0l>;M#5Jxm-}*;&|F|49jI z_Lq)>tCP*or9sVDVKy*Zn4OC=pvV4?dJb@V7kg*8{ePJ9FY$kz81RXr;$L(B<9cmv z|8Z((7fCk&f}|t@}G9^Vrl-jbNKi4)d`5 z4{8X>FSVbc@XJF&z+MF;oM0v{_D<^d_BJBFqD=Wu2+1WRenu5JouY}Er5yrSdLh>H zN`HI&Z+kF^i3>~wh)8Z`Hg;xqZgqAp0XA*{E>1=^b^$iF-;Dga^PCMud#I(k=Res1 z0-No38^7Io-Ug6CP!kuE|H{hm_x@%FY9?TA?__J@B4TN4VgX}yu(J?i{rlo?cm5Su z0uuH%_D;aEU?QACtp9ZRH?5zsCLn9)>|$bP29t$|02f#+EujMDFmrAgmnlCpA0IzA zGZzP!8M7&rAI1#hFoT(LnwguJnDPAtQBm=C^?x%Bu{U!?7qvj`%>eU%FN@t2 z%FD*f#l{SUa=@6`*?D=HP1#^jV93MIY0k~T!NF$!=S065`?rbiJ6QtEXJYf)J&3(P zfysEx`1tuupxn%SraU~%Tu@*`CMJ9w%-oz@{QTzTP$fs^55P0-$C%p{%`94c@B3t%p<<Rhb)yZF57-}MMO zx(f7uK-8TuEM{a?QMdq@A5R?peGoa7uJ7Y{Gtx)`5x(o49`0dn#160VE! zIVZh@>l`2#4=>@m7@u>}OSsMfa`EsIu8Z+GC%uI093U4DFX6fvpL5bnxXuA`@$eF^ zi}5)py@cx=AQulW;kp=~bJ9z=&H-}q@Di?z@i`~GgzFq27Y{Gtx)`5x(o49`0dn#1 z60VE!IVZh@>l`2#4=>@m7@u>}OSsMfa`EsIu8Z+GC%uI093U4DFX6fvpL5bnxXuA` z@$eF^i}5)py@cx=AQulW;kp=~bJ9z=&H-}q@Di?z@i`~GgzFq27Y{Gtx)`5x(o49` z0dn#160VE!IVZh@>l`2#4=>@m7@u>}OSsMfa`Es&xG?_yBqz)c`1qzf@HtJQb_Fo- z8BcOE8C69P$kr7Ea?S*Sj>kcu04NCLFb@JP!$BZ65fJD`^pEA_MG%O_Sr#Iu?lHQY z=B}-7ad=ABp=>H&0Ue^EvF3t}FE1ANC3y#gP8Js1eWALU&8}yF7!|IAo_UGSQd$N^2ZGtSNaAMftVX!7yhP{=1^l){~ zbJ95oq+Jd}@_T3?dRQLKau{V45s7_*v1oBc>N>JKx%md;s|;Fb7r6MXozEFRioDp1ZF8?6`Td#Sjc}*`l zU~7H7bQ^d*r7AEI6UL|Okr4)!$NH5~fc3!Tl;8(oulF`16)+1lWz@O(dH4+Qx`l^F z$x_h>1=hR6$W^sv$w4I%uaWEK6C)K}V|JGCJZETuFWIATXk@^m0 zk)pC`&FZKEn=j7pj4qR0&wAlp@|#;*ZAIE;rt_I%0i=}Kv>|XdTx^PLlUVMjK5MeO z7Nl{0OBT62BejmxP*PG-9(Hzi9(sEEY8@RNH-`8QsTZmvGEL|S2Wr8IMkKF#Sb8^- zhziPgzv5k|S?PH;D>7co?}6(S|FUn`F&w40)lomru;f!-LBW=Y`|8-_vuDo?%PT5~ z#UQgwI$*DqkRZH1HLQs^$ad}RO6ibxyC3Z_)i^jfZaqCc)rjd4QzLUBjqL^Q_9h%w z_^Z$4U8((*);XqLotKIwWoRcjorSBIu<&RrC71t zD`6fWj@-ehJ7J&C}e&QvWW~Fw_llb^5|b>4n8Y$b~CghzERr7Lqqd{hBNM}IgTR8O%%R&8~4OX%++<{BszxE zr9cq^%_=S-)wV4h=IQqF>h#mdVQ=z9%UyA7t`t@xs`6$6mY1E;Z)}5Oh&r!6Z^QEV z*Z3iho??D#oW#&VRs;Kxh{^Eo=c#2nCeNU{P?RLE)Lw@8}o7_8C$y}b~RvEh-cteTmvV^;b4=TN-18N1E|W=F5t7tAECZ9*;=~a>S}3esppM9nM7_SAGc&6b6D_lTHaU0$wfcqWZRo}TIM738)j_7eK5o4 z_Uw8i*WSXl1`pIKgZOW?48Z&xtT=TY{k=8#>(LP}_Cyvtnk>WmM)Wa?cNpVTw5)r* z4K$5ZoOVpDtQ5X&!Z6Raj<-H3mQ`1$!_gG2o_r?XeD9Mvk|KfE$gcgR5Zi;!Sd^cx zj73&T0znD+k+)I_g9Mg>>mu96ayr?86X0xg2v-l*=$e-wO;ww}`P-E7_87_s$h64LE-sae zn57w4pF$x&W>@WWV06B|fZKvLQc2jFe1qT*CPD=ft7HnD@OzxqgP1+aTHL~!J~I#U zKnu}WMMHHA1 zdVLMrefqtN)cT`+YZl$U>~syZ=N#=G+8i!VW_WKNJ5x@S)zoCPXP)>|x2p(0Z!;-; zvZQFct6CLF%&Syw+=QGA3P(EX(fM&dSNmp?s@r6-uG9Dk8{3Gv>afU#;n(`SzUIDY*D|bmMJ<>BkgN`jO97&C&L1)n z6G$*a68p!xFRpzYh<&2u%Cc>B1^5=Y<5XKcY9rC2m6+OLXP&p|q!z0dmyNP_WmTsF z-q-wO!h5URJ>BDbXoE~<^2@eK4!8uB)q??jTS}>j(l~Kv2Zz#C>?HirCm3PVtIU>* zcuXY{dpq{wE(b(7P9)mB>UB_`8UxASSf?{=m=q zMUKn@VN3%bnxRb%D+?dX{OaO;1)srgs+ppK4f@2Mw!piQLbYzKVK2y{h|DA3YQmL`UJIV}% z$WH$*U#LR@#D2cInUz$Gan)}+#n`3*S>aC7_RhCj8kfq1teh$=YDoTBTg0HilB%bv4Wqnt($g7uVb0+p0&Mzi}PF=@q4<%=S}K-b(12 zT+H-`$haN04PQ26QG7Zv#iG&IzF}{j-l+Of4P;UG5tr@`5CFjqT6>?S%wve8aK}L( z&)5bx?wM?7Fe(LC<}{C$+-Ibso7B9qjt*;5xSC2<*NV*_=e*tE7+qxX>;EC4mWmCJ zhZieI$V@xw%-I^xL;_#iThhT>l z2H;ygFIMG+oRnJkl^@T8$XS{(L;D1yljpC_t0R^!;aCp$LEG`HRDXU?EiEc4hy-|- z`G$?OHB17|a6h=122XKj0nQLAA+Lj+B7fG&ok-<6I4-wXs7!OG0|QUDvzYoRfxetv zXgJQ~M(g3s*~96b4K*|zlJyjbEo<35QyklQAGEg5mcI6lhsCef9;xf=8V{M~qi-vX zS>9N-TghYoe)F^8a{P2JaVn$}uNf%?BTH**L9s*=q)QECAVe96ZeU9R)A{e84yijM z0bD2(wj&WE9<|x*q2G-mZ56?LCoC?j9v?|9{E?RW_!W45zvG-H_=gEg$hJ`g%DXK` zZblO9){n0=q_V2OxE~I=;Bsav1rg#!92iy_R9Zf^4SD(Nugc^+-&DysKBwYcSzm}# zK{_=|eMWe^CV0lV!h0V(6#`KWCmEF3=GD^m&Fk<2eYyK3peNT0`Mo1~+(!rm+Bc?g z@&w3Xy(_QdkaZteg(vMljnvww)iVGosYS#Rf84CdbOr5^K0g zW22Y(x?M@FF-pX=xa2c z7I#?395T#oyw>3T&Jb4o{-NhoR~F?a<!;y?n=@!O?*^-KXn{*2|#c zdqf57E*gL4aV4J-;6Wgh&=g$-24-G5a0(J>RWwsv*G2Q}<)G^i=u^Mh)?%6&_({^Q zwQOvBQ!V$khDAimqVwJE_}ksLIv|5Z%@y>0(h|H4d|p2UAzX&pTv@r1Y$&@)?{BVn z`Abf^_ji6@DrtCloN6y{llQKBuvzFQ#-7=vE$!{dcWd~mV46OnvyfvN$pLu0SE&N19drEwtp zp1dT6E`zGEmCC*NjKEChiWq`9#!*xAY_diBjKD=xzB`>t(>+BHu7orxc}tFbOt6Z< zjnLU_)QzphM=}EpIlcN%{SrPyA8I^zV7^8Ftc*RfU!5j3LQyNSJDzY5cj_x;x{vw( zWavCI*efmMR2sJ=6;8iq6;;@(KJ7|3(qL`! zij(KAdt0-zg~EDo^FjQ=Xv(ijDtt{{EW#*erA5 zG!Gfgs0Q5rO+-qp3lOV0d9#m(Sshcn9a6ki#E^*s4!vuh4rxBXDbld$1$O z-r?poMevSf7}@9V-j0p#A{?e~ZdAf})CpS<{4x?BK=<0|h9b2ioJqj{@GI?spUSgd z#iB^qOKPhgY5hP#As!}fNlmjb zt=LjnzP@{A)gIln6avS^Jqbp_!`~%PO9U-hng={7gTOx-Z{#m7$!6QH@~EbRwKQRL zXEw6iK|fngAoS1*??eJ==N^ElZbrvn4^*C%?FfkOtk(LJ7?~2#4yR_)NN`^NINTAN zrb+*h`PHkURpdLJ9bAkYPi`W3L zGjd={JyNfy9KH#)2P9+(u_6O33uh9H1PULJfdoso52j%x>uJ{$CDqCv9_XX)*Vjbc z;kF{gEuzhihg3#~oXSF?AY5r7G-D-88zjH><9P z=}AU{JJ*kUYN?T5@;Q|gGsL?iwV%#OW&$|^gc^b=(RL2(s%h`#H~8F)l%##1o>w-H z3OG{5ZH64+4uBbHgRTKA32n1)WvSt>O=)dA1)TMrE3p3uC1>AtmhjwWpFylbBN4(> z11-z8NFVOlkZRmMbFdRdHcY`l2`d2w^A0OspL5}y*CT2%LCpfDBR7^$aB_zaa|(xt z{Zh8cVr?4V6$}Uv79{2Uk2$ul&wfz2}02C7x!h45AG3M>MbJ*G(OId^-(s+vqK z!c2f8_#WTLT+qXSJa*;!vFk#$I;8@750Dpi80X~GBti*Zy&`)cr$&!SR zIsxpb?8$#)(X{T`OCeTqEIe@!<>&iZS$xUZz6WifqMI7|(Ats|B*0lyl-i&Bzg>~~GbALz{eALR$?!bVBzY zk5R=#mVoIUi{0(T(<#xeX7N-3EtEl5fmG>-%{SN72_e})PTdJt3W*N({v?1xXyUyr5Qv!y*RwgZDF~%X5v}2JR~@TE-Azf zw~xU5v3xRi4;0BvNNw;M0TXH5aE8VtP6;UCn@di8{kzeOxI5YC8wQbGG9q6VtvE~u z5;ho2IR%wkKCQXjm5g23b#;s-|KOO05j6XtG?2`2Ul;E6m|Vq>h&3uA5S0!!bfP)% zMvVqxiz85Jfoyk_$L->+7^l7QiXKbatPh@O@SCAZOTMk?20xWNZ|;Urf-(3ozEWl%PBo9PhCn2yp<+{tsR<96R}x-T$Z3oEJR+(gM+(d@K8`BfZQ#`3X0H0oRr2De`CsI*0F3y3fT#Zi91tm>ev983?WKgI`ojb2T6BwN?x zUAd*S&U4!9jFjd+XNSHi+#NTNAdxcH~YlDWwg;*{EnsH*l}u#$3nsX<8iA z2d9WZ&Lkkdrsxi}&y_afcHjAN+-XHQO+c4*e4@|Tbs#UkT=w?#p&o;Tx0XBU*lXOY zdv=fkF*2&w!zsBQbf5@@FMi|N`%E&_^CU2^ThvnK23px8pNX$;HC(LiTwQNxn+7Hs z#E>zgp}RUFR}SW}eR&z$zX9y8jP>Rth@uH!M==S+(-74vUd2>_uvu1bg&%P$0f^%+ zHb3GJFTrVKKMj8K9z@~iWbm2@*pAt1o065a^%4_Ujw0Iw90ty2GxuL*LO)F%nS{Ct z8FLk=-Iqg_oV+K?!i87dSbESutaWvDoOoTc*RJH%I(fz+%8^@Am;cQ3piH@Vrd-Mm zE?i7}FK)7iER8U^*oVyHrfceRVNGK70)utEgU~Pr#!un*%DzWmyC>tNDl;qpO1^oL zQIn*(d)b&Pkt!tr^MJWTiKbsazJw?HomFe|7FeIUjnNUy*iaXNSdq?Dq3`a91!gE+ zYRKmhy3i1%8+~Hn(UwQ8R^Y>k5E1h18Xdf2u(jXSirE_b%&y{VmC%EUpj&U+XcSYn zmwVC#Ev}%UzCSoxu@WI#4hN2;Ap-LO0S|b?%u)(;rs!BBq@7`R?48ZAi;R6I4d0w> z>`Z;_ziObETdP~plldaT-n;-4EE%q5fFFCE@XdnW}*R-Gj&)&CdcZ{btDfeWjgqwhX00Ufq53&GxssLe! zxFm(_-i+bJEuzl$#2OG}%5B(wE9N*>bF1~9a7X>3h4d5Blf~VYuUf&&U)?!9+8A1Z zJYiYYzHu|h{T}HoIA38nt4NhPJb#MoV4PAgb#7r0gJ{XQ70iN-1)Na(PJ#631sWHi zDVtnO2BL)SQ}~U5_f=TF_?!+vK>@l=ayxsv{%VScXR7V)pB{PdF##hn1E%0SNeY_o zX9G8E+|oTi?NTMwxJ)&CU0GSd44HSjo{5920+RQAls&<#_H^LT<_Jq}_zN4#&b7|t z03BR!F`Bp&$I*d2-^tg!#`YfV>5qE-Y;CXZu6&DC+B{Nn#5F`Xp$j7F$fo-|+Py{^ zP2rURGF9HVt6*)jIyK0OUjCl*$G0g|+X~_a46mJ(19O2B4{+2$9OQr!u{mCGW9r0W zW4icO4g@~3p%>#YEU6xSlz)48agj<~x4~RvE(Dj-4!2JO+(Dhab#qBj334^0-AFa( zR1$J#O!=a$F!9dmTUDd$+;ShxRZ)gTkMWmK3~91O_4M=vBW`nk_}B_d`$XDcn}~cO zG&m(Dk_J5SYPEF%YHfRqKKXTLG1aGpPO1`__4rK^1xj;AEJdn9g<$WeQjP`&QZ?)` z(d*A6i#&z%HKalni$IFW)rx_Xg$9gLCPQH=+6N0ng~u*fK)0o({u!v-!!tb6s8yB$ z;S09G9|s{%+Xh@>Lf%njb3(R_zyeZ`EXa>e)k#(GVW1-2gz+4^RJq6LzQm3S$R7WGV! z-PhO!(Nt)4GYJa5_5~j9*_|98WJr6LIZnra`*y>%^0@ZYY4#xtySatCu}zx>X(bka z9)+@Dgp}EcB~c1%_>TO%^Yds_7*I_C7P$ei__VnjTiD31Bv7h=c#tem%e6fsAUC=4 zko}67o_V+hlUrRkZqB}@7OhA9WS zGS~dR@3FS-R;}$`qlI_c08J zYgRy)cE#qaM3P)Yi~==j;sEUu8S+zg4L9LNuY{3rYa@)at^^WiAHWMF;KM?rhKD_B zxo>7(A7CbSo%ri5Ss%Q^EQ)|OqbA*s8g|XQ}g$y-{z2_rz{ zx~@&4JBu}&5N=H3spdK8%3^f%yRv^N(k(n&vCmLtm%-rdlqU!C<36rcc%qr;Bct6$4^uZi`-F3oSi{Me^`(NmorqD%+S7_``UyywD3v4;wQ;V{_(LhUr zr}lh*%1V9g{WgRVYZ>1lfQ9Z#06LPbfTGQzjUTv^32hD3E!EC)O6bR2;YkZ zfeq-}c*r^X?vI(>RLv-j1Rl(MAp2a{JsaGyY!!_t2(GTpKpeZN#eS{7k}HcxqnP#B;o-jPqt z3Y{5T1&UwBaZE(sM}m%!70k_pQM7%@uk12eZyK5!3P**|lt0~Xm~~w)Ya`X$Z8|y| zURZedefd?Hn&2! z=K7?`()i)MnKdJy4!}nT!E%Q*U+tIo;qNXqSDfJOYJA$3gs}WY%@%EKKH`<2 z2%=L|Thncv=dA}}YIr8YcPe4kaL;0EE%(#agE{-u!522NX2kLkTu9~p^0gldkhAjg za<54s>M$yfw7Qt={eG;!7`*QF`~b<=hmb8RNVrG5O^u0Kr0veER@dV2*TS`=k8V<; zRaI36eCAz5Lyx!4Zm(AOEVT*?>gS{QXj(ry`QqdJJ^I01UJhw4=ceLVBJJClyA8K) zvmg7*BWWL>zCf%Ka6kBY>PS;`a9xNiJ-}d1o3*}O`_=)EAGc~$)IX&daTcJlv>6YD z-y(j~6Z`y)sEpEG;gL=qk^fRwOw?6V+U$8vhf1s(Ao!Kji8KVnJTr`jt0@&hSUz1N z9`pUGXHq!aQ%rCF<9^tSaKXd9H7#;~sv>!De9^|;)ap|9nBHL}i`TVg$<|3P-=s6G zy+qmpVZ`M^9>^B@Mhol;6qv1*7cJ`)`k#Jk^hZfle8$)3JhKUF^Y*T$-(A^#HL_e^ z&J3(V0=i#aJWQDm5cDdV6cHzSKcZ1VBr4EcH~>|9Nt0#XYpEN321^-7O_gRTQK?L^ zNkSO1aeoBUsvO!N>*e=i?&)6Xkn{;^#d4GV*Djr*#9udr*=gEy`*Q(x<&?hdo?)HToK z0$n9glmfenc^#t2x(Z`;I(y30-Gh+iOxgAMOz^vUR?%H8(|?RjP-$8lu?b=ywfmHW z9#Z=)O01WzWJO`GW<|ZV(QG5>IxORdY?H~$cS=4HIh4(AsHK@$ z0;T%4DR|G#Kn6Vs_)}z{F)ZtLMoC~wnuJgX+NB7W| z+vh4BX2pYSy<>$&ARUFTJefFTch)qxlK$3RR>tVMt!G~&_}+`a5QGN%{X-tystc|Y)XRP>pcnXkyK zRZtz)k9clQpcN-vcTtPZ$i|Vqr?WRGx90rSc1dK{OjVC7!%IekCpgarN$_KRn9e8~ zc(k1cyV!=Qa`f}(&m$cjRw8P13TT$GP=?cG6v&2AuR+RMQ!G-cNpGPq$k?Zjrdp4=*jHZpkytW&;_wA^RYN{%KnGU-Kqp=f+BkUPf5sCF&GA^xbM zYxQ}wSH$vk zp2_r3MtO1?r`-pg?6dCfbJS4>^Cy(r%5{ci0m^R^0XwiopQiPi2GycVxItqccFhOcXnw*4}hkhUp7_mPMiW0NW;V@~kb z26lz-=?E!so`M)&Po~xhjkYYh-G2uZ{jU{A8y~&yREyBjp$E4i9WR_=gGi(~_!bsJ Sni2mWfvltwq*&be(f + {$smarty.get.errmes} + +{/if} + +
    +
    + +
    +
    + {intl d='cheque.bo.default' l="Cheque instructions configuration"} +
    +
    + +
    +
    +
    + + {form name="cheque.instructions.configure"} + + + + {include + file = "includes/inner-form-toolbar.html" + hide_submit_buttons = false + + page_url = {url path="/admin/module/Cheque"} + close_url = {url path="/admin/modules"} + } + + {form_hidden_fields} + + {if $form_error} +
    +
    +
    {$form_error_message}
    +
    +
    + {/if} + + {loop type="module-config" name="get-payable-to" module="Cheque" variable="payable_to"} + {render_form_field field="payable_to" value=$VALUE} + {/loop} + + {loop type="module-config" name="get-instruction" module="Cheque" variable="instructions" locale=$edit_language_locale} + {render_form_field field="instructions" extra_class="wysiwyg" value=$VALUE} + {/loop} + + {/form} +
    +
    +
    +
    +
    \ No newline at end of file diff --git a/local/modules/Cheque/templates/frontOffice/default/order-placed.additional-payment-info.html b/local/modules/Cheque/templates/frontOffice/default/order-placed.additional-payment-info.html new file mode 100644 index 00000000..dba86bfd --- /dev/null +++ b/local/modules/Cheque/templates/frontOffice/default/order-placed.additional-payment-info.html @@ -0,0 +1,21 @@ +{loop type="module-config" name="cheque-instructions" module="cheque" variable="payable_to"} +

    {intl d='cheque.fo.default' l="Please make your cheque payable to %name, and send it to the following address :" name={$VALUE}}

    +{/loop} + +
    + {config key="store_name"}
    + {config key="store_address1"}
    + {if ! empty({config key="store_address2"})}{config key="store_address2"}
    {/if} + {if ! empty({config key="store_address3"})}{config key="store_address3"}
    {/if} + {config key="store_zipcode"}, {config key="store_city"}
    + {if {config key="store_country"}} + {loop type="country" name="store_country" id={config key="store_country"}} + {$TITLE}
    + {/loop} + {/if} +
    +

    {intl d='cheque.fo.default' l="Be sure to sign your cheque !"}

    + +{loop type="module-config" name="cheque-instructions" module="cheque" variable="instructions"} +

    {$VALUE nofilter}

    +{/loop} \ No newline at end of file diff --git a/local/modules/Colissimo/Colissimo.php b/local/modules/Colissimo/Colissimo.php new file mode 100755 index 00000000..81b370c9 --- /dev/null +++ b/local/modules/Colissimo/Colissimo.php @@ -0,0 +1,180 @@ +insertSql(null, array(__DIR__ . '/Config/thelia.sql')); + } + + + public function isValidDelivery(Country $country, State $state = null) + { + if (0 == self::getConfigValue(ColissimoConfigValue::ENABLED, 1)) { + return false; + } + + if (null !== $area = $this->getAreaForCountry($country, $state)) { + $areaId = $area->getId(); + + $prices = self::getPrices(); + + /* Check if Colissimo delivers the area */ + if (isset($prices[$areaId]) && isset($prices[$areaId]["slices"])) { + // Yes ! Check if the cart weight is below slice limit + $areaPrices = $prices[$areaId]["slices"]; + ksort($areaPrices); + + /* Check cart weight is below the maximum weight */ + end($areaPrices); + $maxWeight = key($areaPrices); + + $cartWeight = $this->getRequest()->getSession()->getSessionCart($this->getDispatcher())->getWeight(); + + if ($cartWeight <= $maxWeight) { + return true; + } + } + } + + return false; + } + + /** + * @param $areaId + * @param $weight + * + * @return mixed + * @throws \Thelia\Exception\OrderException + */ + public static function getPostageAmount($areaId, $weight) + { + $freeshipping = Colissimo::getConfigValue(ColissimoConfigValue::FREE_SHIPPING); + $postage = 0; + if (!$freeshipping) { + $prices = self::getPrices(); + + /* check if Colissimo delivers the asked area */ + if (!isset($prices[$areaId]) || !isset($prices[$areaId]["slices"])) { + throw new DeliveryException( + Translator::getInstance()->trans( + "Colissimo delivery unavailable for the delivery country", + [], + self::DOMAIN_NAME + ) + ); + } + + $areaPrices = $prices[$areaId]["slices"]; + ksort($areaPrices); + + /* Check cart weight is below the maximum weight */ + end($areaPrices); + $maxWeight = key($areaPrices); + if ($weight > $maxWeight) { + throw new DeliveryException( + Translator::getInstance()->trans( + "Colissimo delivery unavailable for this cart weight (%weight kg)", + array("%weight" => $weight), + self::DOMAIN_NAME + ) + ); + } + + $postage = current($areaPrices); + + while (prev($areaPrices)) { + if ($weight > key($areaPrices)) { + break; + } + + $postage = current($areaPrices); + } + } + return $postage; + + } + + /** + * + * calculate and return delivery price + * + * @param Country $country + * @param State $state + * @return mixed + */ + public function getPostage(Country $country, State $state = null) + { + $cartWeight = $this->getRequest()->getSession()->getSessionCart($this->getDispatcher())->getWeight(); + + $postage = self::getPostageAmount( + $this->getAreaForCountry($country, $state)->getId(), + $cartWeight + ); + + return $postage; + } + + public function update($currentVersion, $newVersion, ConnectionInterface $con = null) + { + $uploadDir = __DIR__ . '/Config/prices.json'; + + $database = new Database($con); + + $tableExists = $database->execute("SHOW TABLES LIKE 'colissimo_freeshipping'")->rowCount(); + + if (Colissimo::getConfigValue(ColissimoConfigValue::FREE_SHIPPING, null) == null && $tableExists) { + $result = $database->execute('SELECT active FROM colissimo_freeshipping WHERE id=1')->fetch()["active"]; + Colissimo::setConfigValue(ColissimoConfigValue::FREE_SHIPPING, $result); + $database->execute("DROP TABLE `colissimo_freeshipping`"); + } + + if (is_readable($uploadDir) && Colissimo::getConfigValue(ColissimoConfigValue::PRICES, null) == null) { + Colissimo::setConfigValue(ColissimoConfigValue::PRICES, file_get_contents($uploadDir)); + } + } +} diff --git a/local/modules/Colissimo/Config/config.xml b/local/modules/Colissimo/Config/config.xml new file mode 100755 index 00000000..fb02632e --- /dev/null +++ b/local/modules/Colissimo/Config/config.xml @@ -0,0 +1,40 @@ + + + + + + + + + + + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/local/modules/Colissimo/Config/module.xml b/local/modules/Colissimo/Config/module.xml new file mode 100755 index 00000000..2fb9e2ba --- /dev/null +++ b/local/modules/Colissimo/Config/module.xml @@ -0,0 +1,18 @@ + + + Colissimo\Colissimo + + Colissimo delivery + + + Livraison par Colissimo + + 2.4.3 + + Manuel Raynaud + manu@raynaud.io + + delivery + 2.4.3 + alpha + diff --git a/local/modules/Colissimo/Config/prices.json b/local/modules/Colissimo/Config/prices.json new file mode 100755 index 00000000..53eacc3b --- /dev/null +++ b/local/modules/Colissimo/Config/prices.json @@ -0,0 +1,64 @@ +{"1": { + "_info": "area 1 : France", + "slices": { + "0.25": 5.23, + "0.5": 6.13, + "0.75": 6.89, + "1": 7.51, + "2": 8.50, + "5": 10.93, + "10": 15.68, + "30": 23.28 + } +}, "2": { + "_info": "area 2 : A Zone - Union Europ\u00e9enne et Suisse", + "slices": { + "0.5": 11.54, + "1": 14.11, + "2": 15.68, + "5": 20.14, + "10": 33.25, + "20": 55.10, + "30": 55.10 + } +}, "3": { + "_info": "area 3 : B Zone - Pays de l\u2019Europe de l\u2019Est (hors Union Europ\u00e9enne et Russie), Norv\u00e8ge, Maghreb", + "slices": { + "0.5": 15.39, + "1": 18.38, + "2": 20.00, + "5": 25.65, + "10": 42.75, + "20": 66.50 + } +}, "4": { + "_info": "area 4 : C Zone - Autres destinations", + "slices": { + "0.5": 22.52, + "1": 24.99, + "2": 34.30, + "5": 50.35, + "10": 95.00, + "20": 152.00 + } +}, "5": { + "_info": "area 5 : France OM1", + "slices": { + "0.5": 8.69, + "1": 13.16, + "2": 17.96, + "5": 26.60, + "10": 42.75, + "30": 95.95 + } +}, "6": { + "_info": "area 6 : France OM2", + "slices": { + "0.5": 10.40, + "1": 15.72, + "2": 27.74, + "5": 46.08, + "10": 90.25, + "30": 237.50 + } +}} diff --git a/local/modules/Colissimo/Config/routing.xml b/local/modules/Colissimo/Config/routing.xml new file mode 100755 index 00000000..4edcf64d --- /dev/null +++ b/local/modules/Colissimo/Config/routing.xml @@ -0,0 +1,21 @@ + + + + + Colissimo\Controller\EditPrices::editprices + + + + Colissimo\Controller\FreeShipping::set + + + + Colissimo\Controller\Export::exportAction + + + + Colissimo\Controller\Configuration::editConfiguration + + diff --git a/local/modules/Colissimo/Config/thelia.sql b/local/modules/Colissimo/Config/thelia.sql new file mode 100644 index 00000000..d44ef9fa --- /dev/null +++ b/local/modules/Colissimo/Config/thelia.sql @@ -0,0 +1,32 @@ +# This is a fix for InnoDB in MySQL >= 4.1.x +# It "suspends judgement" for fkey relationships until are tables are set. +SET FOREIGN_KEY_CHECKS = 0; + +-- --------------------------------------------------------------------- +-- Mail templates for colissimo +-- --------------------------------------------------------------------- + +-- First, delete existing entries +SET @var := 0; +SELECT @var := `id` FROM `message` WHERE name="mail_colissimo"; +DELETE FROM `message` WHERE `id`=@var; +-- Try if ON DELETE constraint isn't set +DELETE FROM `message_i18n` WHERE `id`=@var; + +-- Then add new entries +SELECT @max := MAX(`id`) FROM `message`; +SET @max := @max+1; +-- insert message +INSERT INTO `message` (`id`, `name`, `secured`) VALUES +(@max, +'mail_colissimo', +'0' +); + +-- and template fr_FR +INSERT INTO `message_i18n` (`id`, `locale`, `title`, `subject`, `text_message`, `html_message`) VALUES +(@max, 'en_US', 'Colissimo shipping message', 'Your order {$order_ref} has been shipped', '{loop type="customer" name="customer.order" current="false" id="$customer_id" backend_context="1"}\r\nDear {$FIRSTNAME} {$LASTNAME},\r\n{/loop}\r\nThank you for your order on our online store {config key="store_name"}.\r\nYour order {$order_ref} dated {format_date date=$order_date} has been shipped on {format_date date=$update_date}.\r\nThe tracking number for this delivery is {$package}. Please check the La Poste website for tracking your parcel: www.coliposte.net.\r\nYou can use this tracking number to get your parcel in your local La Poste office. If don''t get an advice in your mailbox after two working days, claim your parcel at your local La Poste office, using this tracking number.\r\nFeel free to contact us for any forther information\r\nBest Regards.', '{loop type="customer" name="customer.order" current="false" id="$customer_id" backend_context="1"}\r\n

    Dear {$FIRSTNAME} {$LASTNAME},

    \r\n{/loop}\r\n

    Thank you for your order on our online store {config key="store_name"}.

    \r\n

    Your order {$order_ref} dated {format_date date=$order_date} has been shipped on {format_date date=$update_date}.\r\nThe tracking number for this delivery is {$package}. Please check the La Poste website for tracking your parcel: www.coliposte.net.

    \r\n

    You can use this tracking number to get your parcel in your local La Poste office. If don''t get an advice in your mailbox after two working days, claim your parcel at your local La Poste office, using this tracking number.

    \r\n

    Feel free to contact us for any forther information

    \r\n

    Best Regards.

    '), +(@max, 'fr_FR', 'Message d''expédition de colissimo', 'Suivi colissimo commande : {$order_ref}', '{loop type="customer" name="customer.order" current="false" id="$customer_id" backend_context="1"}\r\n{$LASTNAME} {$FIRSTNAME},\r\n{/loop}\r\nNous vous remercions de votre commande sur notre site {config key="store_name"}\r\nUn colis concernant votre commande {$order_ref} du {format_date date=$order_date} a quitté nos entrepôts pour être pris en charge par La Poste le {format_date date=$update_date}.\r\nSon numéro de suivi est le suivant : {$package}\r\nIl vous permet de suivre votre colis en ligne sur le site de La Poste : www.coliposte.net\r\nIl vous sera, par ailleurs, très utile si vous étiez absent au moment de la livraison de votre colis : en fournissant ce numéro de Colissimo Suivi, vous pourrez retirer votre colis dans le bureau de Poste le plus proche.\r\nATTENTION ! Si vous ne trouvez pas l''avis de passage normalement déposé dans votre boîte aux lettres au bout de 48 Heures jours ouvrables, n''hésitez pas à aller le réclamer à votre bureau de Poste, muni de votre numéro de Colissimo Suivi.\r\nNous restons à votre disposition pour toute information complémentaire.\r\nCordialement', '{loop type="customer" name="customer.order" current="false" id="$customer_id" backend_context="1"}\r\n{$LASTNAME} {$FIRSTNAME},\r\n{/loop}\r\nNous vous remercions de votre commande sur notre site {config key="store_name"}\r\nUn colis concernant votre commande {$order_ref} du {format_date date=$order_date} a quitté nos entrepôts pour être pris en charge par La Poste le {format_date date=$update_date}.\r\nSon numéro de suivi est le suivant : {$package}\r\nIl vous permet de suivre votre colis en ligne sur le site de La Poste : www.coliposte.net\r\nIl vous sera, par ailleurs, très utile si vous étiez absent au moment de la livraison de votre colis : en fournissant ce numéro de Colissimo Suivi, vous pourrez retirer votre colis dans le bureau de Poste le plus proche.\r\nATTENTION ! Si vous ne trouvez pas l''avis de passage normalement déposé dans votre boîte aux lettres au bout de 48 Heures jours ouvrables, n''hésitez pas à aller le réclamer à votre bureau de Poste, muni de votre numéro de Colissimo Suivi.\r\nNous restons à votre disposition pour toute information complémentaire.\r\nCordialement'); + +# This restores the fkey checks, after having unset them earlier +SET FOREIGN_KEY_CHECKS = 1; \ No newline at end of file diff --git a/local/modules/Colissimo/Controller/Configuration.php b/local/modules/Colissimo/Controller/Configuration.php new file mode 100755 index 00000000..52f99df8 --- /dev/null +++ b/local/modules/Colissimo/Controller/Configuration.php @@ -0,0 +1,77 @@ + + */ +class Configuration extends BaseAdminController +{ + public function editConfiguration() + { + if (null !== $response = $this->checkAuth( + AdminResources::MODULE, + [Colissimo::DOMAIN_NAME], + AccessManager::UPDATE + )) { + return $response; + } + + $form = $this->createForm('colissimo.configuration'); + $error_message = null; + + try { + $validateForm = $this->validateForm($form); + $data = $validateForm->getData(); + + Colissimo::setConfigValue( + ColissimoConfigValue::ENABLED, + is_bool($data["enabled"]) ? (int) ($data["enabled"]) : $data["enabled"] + ); + + return $this->redirectToConfigurationPage(); + + } catch (FormValidationException $e) { + $error_message = $this->createStandardFormValidationErrorMessage($e); + } + + if (null !== $error_message) { + $this->setupFormErrorContext( + 'configuration', + $error_message, + $form + ); + $response = $this->render("module-configure", ['module_code' => 'Colissimo']); + } + return $response; + } + + /** + * Redirect to the configuration page + */ + protected function redirectToConfigurationPage() + { + return RedirectResponse::create(URL::getInstance()->absoluteUrl('/admin/module/Colissimo')); + } +} diff --git a/local/modules/Colissimo/Controller/EditPrices.php b/local/modules/Colissimo/Controller/EditPrices.php new file mode 100755 index 00000000..a4ed5083 --- /dev/null +++ b/local/modules/Colissimo/Controller/EditPrices.php @@ -0,0 +1,84 @@ + + */ +class EditPrices extends BaseAdminController +{ + public function editprices() + { + // Get data & treat + $post = $this->getRequest(); + $operation = $post->get('operation'); + $area = $post->get('area'); + $weight = $post->get('weight'); + $price = $post->get('price'); + + if (preg_match("#^add|delete$#", $operation) && + preg_match("#^\d+$#", $area) && + preg_match("#^\d+\.?\d*$#", $weight) + ) { + // check if area exists in db + $exists = AreaQuery::create() + ->findPK($area); + if ($exists !== null) { + + if (null !== $data = Colissimo::getConfigValue(ColissimoConfigValue::PRICES, null)) { + $json_data = json_decode( + $data, + true + ); + } + if ((float) $weight > 0 && $operation == "add" + && preg_match("#\d+\.?\d*#", $price)) { + $json_data[$area]['slices'][$weight] = $price; + } elseif ($operation == "delete") { + if (isset($json_data[$area]['slices'][$weight])) { + unset($json_data[$area]['slices'][$weight]); + } + } else { + throw new \Exception("Weight must be superior to 0"); + } + ksort($json_data[$area]['slices']); + + Colissimo::setConfigValue(ColissimoConfigValue::PRICES, json_encode($json_data)); + + } else { + throw new \Exception("Area not found"); + } + } else { + throw new \ErrorException("Arguments are missing or invalid"); + } + + return $this->redirectToConfigurationPage(); + } + + /** + * Redirect to the configuration page + */ + protected function redirectToConfigurationPage() + { + return RedirectResponse::create(URL::getInstance()->absoluteUrl('/admin/module/Colissimo')); + } +} diff --git a/local/modules/Colissimo/Controller/Export.php b/local/modules/Colissimo/Controller/Export.php new file mode 100644 index 00000000..ca82a68e --- /dev/null +++ b/local/modules/Colissimo/Controller/Export.php @@ -0,0 +1,166 @@ + + */ +class Export extends BaseAdminController +{ + const DEFAULT_PHONE = "0100000000"; + const DEFAULT_CELLPHONE = "0600000000"; + + public function exportAction() + { + if (null !== $response = $this->checkAuth(array(AdminResources::MODULE), array('Colissimo'), AccessManager::UPDATE)) { + return $response; + } + + $form = new FormExport($this->getRequest()); + + try { + $exportForm = $this->validateForm($form); + + // Get new status + $status_id = $exportForm->get('status_id')->getData(); + $status = OrderStatusQuery::create() + ->filterByCode($status_id) + ->findOne(); + + // Get Colissimo orders + $orders = ColissimoQuery::getOrders()->find(); + + $export = ""; + $store_name = ConfigQuery::getStoreName(); + + /** @var $order \Thelia\Model\Order */ + foreach ($orders as $order) { + + $value = $exportForm->get('order_'.$order->getId())->getData(); + + if ($value) { + + // Get order information + $customer = $order->getCustomer(); + $locale = $order->getLang()->getLocale(); + $address = $order->getOrderAddressRelatedByDeliveryOrderAddressId(); + $country = CountryQuery::create()->findPk($address->getCountryId()); + $country->setLocale($locale); + $customerTitle = CustomerTitleQuery::create()->findPk($address->getCustomerTitleId()); + $customerTitle->setLocale($locale); + $weight = $exportForm->get('order_weight_'.$order->getId())->getData(); + + if ($weight == 0) { + /** @var \Thelia\Model\OrderProduct $product */ + foreach ($order->getOrderProducts() as $product) { + $weight += (double)$product->getWeight(); + } + } + + /** + * Get user's phone & cellphone + * First get invoice address phone, + * If empty, try to get default address' phone. + * If still empty, set default value + */ + $phone = $address->getPhone(); + if (empty($phone)) { + $phone = $customer->getDefaultAddress()->getPhone(); + + if (empty($phone)) { + $phone = self::DEFAULT_PHONE; + } + } + + // Cellphone + $cellphone = $customer->getDefaultAddress()->getCellphone(); + + if (empty($cellphone)) { + $cellphone = $customer->getDefaultAddress()->getCellphone(); + + if (empty($cellphone)) { + $cellphone = self::DEFAULT_CELLPHONE; + } + } + + + $export .= + "\"".$order->getRef() + ."\";\"".$address->getLastname() + ."\";\"".$address->getFirstname() + ."\";\"".$address->getAddress1() + ."\";\"".$address->getAddress2() + ."\";\"".$address->getAddress3() + ."\";\"".$address->getZipcode() + ."\";\"".$address->getCity() + ."\";\"".$country->getIsoalpha2() + ."\";\"".$phone + ."\";\"".$cellphone + ."\";\"".$weight + ."\";\"".$customer->getEmail() + ."\";\"\";\"".$store_name + ."\";\"DOM\";\r\n"; + + if ($status) { + $event = new OrderEvent($order); + $event->setStatus($status->getId()); + $this->getDispatcher()->dispatch(TheliaEvents::ORDER_UPDATE_STATUS, $event); + } + } + } + + return Response::create( + utf8_decode($export), + 200, + array( + "Content-Encoding"=>"ISO-8889-1", + "Content-Type"=>"application/csv-tab-delimited-table", + "Content-disposition"=>"filename=export.csv" + ) + ); + + } catch (FormValidationException $e) { + $this->setupFormErrorContext( + Translator::getInstance()->trans("colissimo expeditor export", [], Colissimo::DOMAIN_NAME), + $e->getMessage(), + $form, + $e + ); + + return $this->render( + "module-configure", + array( + "module_code" => "Colissimo", + ) + ); + } + } +} diff --git a/local/modules/Colissimo/Controller/FreeShipping.php b/local/modules/Colissimo/Controller/FreeShipping.php new file mode 100644 index 00000000..10d46e6f --- /dev/null +++ b/local/modules/Colissimo/Controller/FreeShipping.php @@ -0,0 +1,62 @@ + + */ +class FreeShipping extends BaseAdminController +{ + public function set() + { + $response = $this->checkAuth(AdminResources::MODULE, [Colissimo::DOMAIN_NAME], AccessManager::UPDATE); + if (null !== $response) { + return $response; + } + + $form = $this->createForm('colissimo.freeshipping.form'); + + + try { + $validateForm = $this->validateForm($form); + $data = $validateForm->getData(); + + Colissimo::setConfigValue(ColissimoConfigValue::FREE_SHIPPING, (int) ($data["freeshipping"])); + return $this->redirectToConfigurationPage(); + + } catch (\Exception $e) { + $response = JsonResponse::create(array("error"=>$e->getMessage()), 500); + } + + return $response; + } + + /** + * Redirect to the configuration page + */ + protected function redirectToConfigurationPage() + { + return RedirectResponse::create(URL::getInstance()->absoluteUrl('/admin/module/Colissimo')); + } +} diff --git a/local/modules/Colissimo/EventListener/AreaDeletedListener.php b/local/modules/Colissimo/EventListener/AreaDeletedListener.php new file mode 100644 index 00000000..c1eb3e41 --- /dev/null +++ b/local/modules/Colissimo/EventListener/AreaDeletedListener.php @@ -0,0 +1,53 @@ + + */ +class AreaDeletedListener implements EventSubscriberInterface +{ + /** + * @param AreaDeleteEvent $event + */ + public function updateConfig(AreaDeleteEvent $event) + { + if (null !== $data = Colissimo::getConfigValue(ColissimoConfigValue::PRICES, null)) { + $areaId = $event->getAreaId(); + $json_data = json_decode($data, true); + unset($json_data[$areaId]); + + Colissimo::setConfigValue(ColissimoConfigValue::PRICES, json_encode($json_data, true)); + } + } + + /** + * @return array + */ + public static function getSubscribedEvents() + { + return [ + TheliaEvents::AREA_DELETE => [ + 'updateConfig', 128 + ] + ]; + } +} diff --git a/local/modules/Colissimo/Form/Configuration.php b/local/modules/Colissimo/Form/Configuration.php new file mode 100644 index 00000000..bc9c58b3 --- /dev/null +++ b/local/modules/Colissimo/Form/Configuration.php @@ -0,0 +1,59 @@ + + */ +class Configuration extends BaseForm +{ + + protected function buildForm() + { + $this->formBuilder + ->add( + "enabled", + "checkbox", + array( + "label" => "Enabled", + "label_attr" => [ + "for" => "enabled", + "help" => Translator::getInstance()->trans( + 'Check if you want to activate Colissimo', + [], + Colissimo::DOMAIN_NAME + ) + ], + "required" => false, + "constraints" => array( + ), + "value" => Colissimo::getConfigValue(ColissimoConfigValue::ENABLED, 1), + ) + ); + } + + /** + * @return string the name of you form. This name must be unique + */ + public function getName() + { + return "colissimo_enable"; + } +} diff --git a/local/modules/Colissimo/Form/Export.php b/local/modules/Colissimo/Form/Export.php new file mode 100644 index 00000000..47c8fddf --- /dev/null +++ b/local/modules/Colissimo/Form/Export.php @@ -0,0 +1,122 @@ + + */ +class Export extends BaseForm +{ + + /** + * + * in this function you add all the fields you need for your Form. + * Form this you have to call add method on $this->formBuilder attribute : + * + * $this->formBuilder->add("name", "text") + * ->add("email", "email", array( + * "attr" => array( + * "class" => "field" + * ), + * "label" => "email", + * "constraints" => array( + * new \Symfony\Component\Validator\Constraints\NotBlank() + * ) + * ) + * ) + * ->add('age', 'integer'); + * + * @return null + */ + protected function buildForm() + { + $orders = ColissimoQuery::getOrders() + ->find(); + + $this->formBuilder + ->add( + 'status_id', + 'text', + [ + 'constraints' => [ + new NotBlank(), + new Callback( + array("methods" => array(array($this, "verifyValue"))) + ) + ], + 'label' => Translator::getInstance()->trans( + 'Modify status export after export', + [], + Colissimo::DOMAIN_NAME + ), + 'label_attr' => [ + 'for' => 'status_id' + ] + ] + ); + + /** @var \Thelia\Model\Order $order */ + foreach ($orders as $order) { + $this->formBuilder + ->add( + "order_".$order->getId(), + "checkbox", + array( + 'label'=>$order->getRef(), + 'label_attr'=>array( + 'for'=>'export_'.$order->getId() + ) + ) + ) + ->add( + "order_nb_pkg_".$order->getId(), + 'number' + ) + ->add( + "order_weight_".$order->getId(), + 'number' + ); + } + } + + public function verifyValue($value, ExecutionContextInterface $context) + { + if (!preg_match("#^nochange|processing|sent$#", $value)) { + $context->addViolation( + Translator::getInstance()->trans( + 'select a valid status', + [], + Colissimo::DOMAIN_NAME + ) + ); + } + } + + /** + * @return string the name of you form. This name must be unique + */ + public function getName() + { + return "colissimo_export"; + } +} diff --git a/local/modules/Colissimo/Form/FreeShipping.php b/local/modules/Colissimo/Form/FreeShipping.php new file mode 100644 index 00000000..baea56e0 --- /dev/null +++ b/local/modules/Colissimo/Form/FreeShipping.php @@ -0,0 +1,62 @@ +formBuilder attribute : + * + * $this->formBuilder->add("name", "text") + * ->add("email", "email", array( + * "attr" => array( + * "class" => "field" + * ), + * "label" => "email", + * "constraints" => array( + * new \Symfony\Component\Validator\Constraints\NotBlank() + * ) + * ) + * ) + * ->add('age', 'integer'); + * + * @return null + */ + protected function buildForm() + { + $this->formBuilder + ->add( + "freeshipping", + "checkbox", + array( + "label" => Translator::getInstance()->trans("Activate free shipping: ", [], Colissimo::DOMAIN_NAME), + "value" => Colissimo::getConfigValue(ColissimoConfigValue::FREE_SHIPPING, false), + ) + ); + } + + /** + * @return string the name of you form. This name must be unique + */ + public function getName() + { + return "colissimofreeshipping"; + } +} diff --git a/local/modules/Colissimo/Hook/HookManager.php b/local/modules/Colissimo/Hook/HookManager.php new file mode 100644 index 00000000..7c8b15bb --- /dev/null +++ b/local/modules/Colissimo/Hook/HookManager.php @@ -0,0 +1,31 @@ + + */ +class HookManager extends BaseHook +{ + public function onModuleConfiguration(HookRenderEvent $event) + { + $module_id = self::getModule()->getModuleId(); + + $event->add($this->render("module_configuration.html", ['module_id' => $module_id])); + } +} diff --git a/local/modules/Colissimo/I18n/backOffice/default/de_DE.php b/local/modules/Colissimo/I18n/backOffice/default/de_DE.php new file mode 100644 index 00000000..10ed342f --- /dev/null +++ b/local/modules/Colissimo/I18n/backOffice/default/de_DE.php @@ -0,0 +1,25 @@ + '*Wenn Sie diese Option auswählen, sind die exportierten Bestellungen auf dieser Seite nicht mehr verfügbar', + 'Actions' => 'Aktionen', + 'An error occured' => 'Ein Fehler ist aufgetreten', + 'Area : ' => 'Bereich : ', + 'Cancel' => 'Abbrechen', + 'Change orders status after export' => 'Status der Bestellung nach dem Export ändern', + 'Colissimo Module allows to send your products all around the world with La Poste.' => 'Colissimo Modul ermöglicht, Ihre Produkte mit La Poste weltweit zu versenden.', + 'Create' => 'Erstellen', + 'Date' => 'Datum', + 'Delete' => 'Löschen', + 'Do not change' => 'Nicht ändern', + 'Edit' => 'Ändern', + 'Export' => 'Export', + 'Please change the access rights' => 'Bitte ändern Sie die Zugriffsrechte', + 'Price (€)' => 'Preis (€)', + 'Processing' => 'Bearbeitung', + 'REF' => 'REF', + 'Sent' => 'Gesendet', + 'There is currently not orders to export' => 'Es gibt derzeit keine Bestellungen, die exportiert werden können', + 'Total taxed amount' => 'Gesamter besteuerter Betrag', + 'Weight up to ... (kg)' => 'Gewicht bis zu ... (kg)', +]; diff --git a/local/modules/Colissimo/I18n/backOffice/default/en_US.php b/local/modules/Colissimo/I18n/backOffice/default/en_US.php new file mode 100644 index 00000000..0d48057a --- /dev/null +++ b/local/modules/Colissimo/I18n/backOffice/default/en_US.php @@ -0,0 +1,36 @@ + '*If you choose this option, the exported orders would not be available on this page anymore', + 'Actions' => 'Actions', + 'An error occured' => 'An error occured', + 'Area : ' => 'Area : ', + 'Cancel' => 'Cancel', + 'Change orders status after export' => 'Change orders status after export', + 'Colissimo Module allows to send your products all around the world with La Poste.' => 'Colissimo Module allows to send your products all around the world with La Poste.', + 'Create' => 'Create', + 'Create a new price slice' => 'Create a new price slice', + 'Create a price slice' => 'Create a price slice', + 'Date' => 'Date', + 'Delete' => 'Delete', + 'Delete a price slice' => 'Delete a price slice', + 'Delete this price slice' => 'Delete this price slice', + 'Do not change' => 'Do not change', + 'Do you really want to delete this slice ?' => 'Do you really want to delete this slice ?', + 'Edit' => 'Edit', + 'Edit a price slice' => 'Edit a price slice', + 'Edit this price slice' => 'Edit this price slice', + 'Export' => 'Export', + 'Export expeditor inet file' => 'Export expeditor inet file', + 'Please change the access rights' => 'Please change the access rights', + 'Price (€)' => 'Price (€)', + 'Price slices' => 'Price slices', + 'Processing' => 'Processing', + 'REF' => 'REF', + 'Sent' => 'Sent', + 'There is currently not orders to export' => 'There is currently no orders to export', + 'Total taxed amount' => 'Total taxed amount', + 'Weight up to ... (kg)' => 'Weight up to ... (kg)', + 'Number of packages' => 'Number of packages', + 'Packages weight' => 'Packages weight' +); diff --git a/local/modules/Colissimo/I18n/backOffice/default/fr_FR.php b/local/modules/Colissimo/I18n/backOffice/default/fr_FR.php new file mode 100644 index 00000000..d7237509 --- /dev/null +++ b/local/modules/Colissimo/I18n/backOffice/default/fr_FR.php @@ -0,0 +1,37 @@ + '* Si vous choisissez cette option, les commandes exportées ne seront plus affichée sur cette page.', + 'Actions' => 'Actions', + 'An error occured' => 'Une erreur est survenue', + 'Area : ' => 'Zone de livraison : ', + 'Cancel' => 'Annuler', + 'Change orders status after export' => 'Modification du statut des commande après l\'export', + 'Colissimo Module allows to send your products all around the world with La Poste.' => 'Colissimo vous permet d’expédier vos colis dans le monde entier avec La Poste', + 'Create' => 'Créer', + 'Create a new price slice' => 'Créer une nouvelle tranche de prix', + 'Create a price slice' => 'Créer une tranche de prix', + 'Customer' => 'Client', + 'Date' => 'Date', + 'Delete' => 'Supprimer', + 'Delete a price slice' => 'Supprimer une tranche de prix', + 'Delete this price slice' => 'Supprimer cette tranche de prix', + 'Do not change' => 'Ne pas modifier', + 'Do you really want to delete this slice ?' => 'Confirmez-vous la suppression de cette tranche de prix', + 'Edit' => 'Modifier', + 'Edit a price slice' => 'Modifier une tranche de prix', + 'Edit this price slice' => 'Modifier cette tranche de prix', + 'Export' => 'Export', + 'Export expeditor inet file' => 'Exporter le fichier Expeditor INET', + 'Number of packages' => 'Nombre de colis', + 'Packages weight' => 'Poids des colis', + 'Please change the access rights' => 'Merci de modifier les droits d\'accès', + 'Price (€)' => 'Prix (€)', + 'Price slices' => 'Prix et poids', + 'Processing' => 'Traitement', + 'REF' => 'REF', + 'Sent' => 'Envoyée', + 'There is currently not orders to export' => 'Il n\'y a pas de commande à exporter pour le moment', + 'Total taxed amount' => 'Total TTC', + 'Weight up to ... (kg)' => 'Jusqu\'au poids (Kg)', +]; diff --git a/local/modules/Colissimo/I18n/backOffice/default/it_IT.php b/local/modules/Colissimo/I18n/backOffice/default/it_IT.php new file mode 100644 index 00000000..58e711dc --- /dev/null +++ b/local/modules/Colissimo/I18n/backOffice/default/it_IT.php @@ -0,0 +1,13 @@ + 'Azioni', + 'Cancel' => 'Annulla', + 'Create' => 'Creare', + 'Date' => 'Data', + 'Delete' => 'Cancellare', + 'Edit' => 'Modifica', + 'Export' => 'Esporta', + 'Number of packages' => 'Numero di pacchetti', + 'Packages weight' => 'Peso pacchi', +]; diff --git a/local/modules/Colissimo/I18n/backOffice/default/ru_RU.php b/local/modules/Colissimo/I18n/backOffice/default/ru_RU.php new file mode 100644 index 00000000..dc3e7306 --- /dev/null +++ b/local/modules/Colissimo/I18n/backOffice/default/ru_RU.php @@ -0,0 +1,38 @@ + '*Если вы выберите эту опцию, экспортированные заказы больше не будут доступны на этой странице', + 'Actions' => 'Действия', + 'An error occured' => 'Произошла ошибка', + 'Area : ' => 'Зона :', + 'Cancel' => 'Отменить', + 'Change orders status after export' => 'Изменить статус заказа после экспорта', + 'Colissimo Module allows to send your products all around the world with La Poste.' => 'Модуль Colissimo позволяет отсылать ваши товары по всему миру, с помощью почтовой компании Франции La Poste.', + 'Create' => 'Создать', + 'Create a new price slice' => 'Создать новый разрез цены', + 'Create a price slice' => 'Создать разрез цены', + 'Customer' => 'Клиент', + 'Date' => 'Дата', + 'Delete' => 'Удалить', + 'Delete a price slice' => 'Удалить разрез цены', + 'Delete this price slice' => 'Удалить этот разрез цены', + 'Do not change' => 'Не изменять', + 'Do you really want to delete this slice ?' => 'Вы действительно хотите удалить этот разрез ?', + 'Edit' => 'Редактировать', + 'Edit a price slice' => 'Редактировать разрез цены', + 'Edit this price slice' => 'Редактировать этот разрез цены', + 'Export' => 'Экспорт', + 'Export expeditor inet file' => 'Экспортировать inet file экспедитора', + 'Number of packages' => 'Количество комплектов', + 'Packages weight' => 'Вес комплектов', + 'Please change the access rights' => 'Пожалуйста, измените права доступа', + 'Price (€)' => 'Цена (€)', + 'Price slices' => 'Разрезы цен', + 'Processing' => 'В обработке', + 'REF' => 'REF', + 'Save' => 'Сохранить', + 'Sent' => 'Отправлен', + 'There is currently not orders to export' => 'Сейчас нет заказов для экспорта', + 'Total taxed amount' => 'Итого', + 'Weight up to ... (kg)' => 'Вес до ... (кг)', +); diff --git a/local/modules/Colissimo/I18n/backOffice/default/tr_TR.php b/local/modules/Colissimo/I18n/backOffice/default/tr_TR.php new file mode 100644 index 00000000..a777927b --- /dev/null +++ b/local/modules/Colissimo/I18n/backOffice/default/tr_TR.php @@ -0,0 +1,34 @@ + '* Bu seçeneği seçerseniz, ihracat siparişleri artık bu sayfadaki müsait olmaz', + 'Actions' => 'Eylemler', + 'An error occured' => 'Bir hata meydana geldi', + 'Area : ' => 'Alanı: ', + 'Cancel' => 'Vazgeç', + 'Change orders status after export' => 'İhracat sonra sipariş durumunu değiştir', + 'Colissimo Module allows to send your products all around the world with La Poste.' => 'Colissimo modülü sağlar ürünlerinizi göndermek için La Poste ile dünyanın her yerinden.', + 'Create' => 'Oluştur', + 'Create a new price slice' => 'Yeni fiyat dilimi oluşturmak', + 'Create a price slice' => 'Bir fiyat dilim oluşturma', + 'Date' => 'Tarih', + 'Delete' => 'sil', + 'Delete a price slice' => 'Bir fiyat dilim silmek', + 'Delete this price slice' => 'Bu fiyat dilim silmek', + 'Do not change' => 'Değiştirme', + 'Do you really want to delete this slice ?' => 'Gerçekten bu dosyayı silmek istiyor musunuz ?', + 'Edit' => 'Düzenle', + 'Edit a price slice' => 'Bir fiyat dilim Düzenle', + 'Edit this price slice' => 'Bu fiyat dilim Düzenle', + 'Export' => 'Dışa aktarma', + 'Export expeditor inet file' => 'Expeditor inet dosyası dışa aktarma', + 'Please change the access rights' => 'Lütfen erişim haklarını Değiştir', + 'Price (€)' => 'Fiyat (TL)', + 'Price slices' => 'Fiyat dilimleri', + 'Processing' => 'İşlem devam ediyor', + 'REF' => 'ÜRÜN KODU', + 'Sent' => 'Gönder', + 'There is currently not orders to export' => 'Şu anda hiçbir emir vermek için', + 'Total taxed amount' => 'Toplam Kdvtutarı', + 'Weight up to ... (kg)' => 'Fazla kilo... (kg)', +]; diff --git a/local/modules/Colissimo/I18n/de_DE.php b/local/modules/Colissimo/I18n/de_DE.php new file mode 100644 index 00000000..5198cfbd --- /dev/null +++ b/local/modules/Colissimo/I18n/de_DE.php @@ -0,0 +1,14 @@ + 'Kostenlose Lieferung aktivieren: ', + 'Can\'t read Config directory' => 'Config-Verzeichnis kann nicht gelesen werden', + 'Can\'t read file' => 'Datei kann nicht gelesen werden', + 'Can\'t write Config directory' => 'Config-Verzeichnis kann nicht beschrieben werden', + 'Can\'t write file' => 'Datei kann nicht geschrieben werden', + 'Colissimo delivery unavailable for the delivery country' => 'Eine Lieferung mit Colissimo ist für das Land nicht verfügbar', + 'Colissimo delivery unavailable for this cart weight (%weight kg)' => 'Eine Lieferung mit Colissimo ist für Warenkörbe mit diesem Gewicht (%weight kg) nicht verfügbar', + 'Modify status export after export' => 'Status der Bestellung nach dem Export ändern', + 'colissimo expeditor export' => 'Colissimo expeditor export', + 'select a valid status' => 'Wählen Sie einen gültigen Bestellungsstatus aus', +]; diff --git a/local/modules/Colissimo/I18n/en_US.php b/local/modules/Colissimo/I18n/en_US.php new file mode 100644 index 00000000..c060ae29 --- /dev/null +++ b/local/modules/Colissimo/I18n/en_US.php @@ -0,0 +1,14 @@ + 'Activate free shipping: ', + 'Can\'t read Config directory' => 'Can\'t read Config directory', + 'Can\'t read file' => 'Can\'t read file', + 'Can\'t write Config directory' => 'Can\'t write Config directory', + 'Can\'t write file' => 'Can\'t write file', + 'Colissimo delivery unavailable for the delivery country' => 'Colissimo delivery unavailable for the delivery country', + 'Colissimo delivery unavailable for this cart weight (%weight kg)' => 'Colissimo delivery unavailable for this cart weight (%weight kg)', + 'Modify status export after export' => 'Change orders status after export', + 'colissimo expeditor export' => 'Colissimo Expeditor export', + 'select a valid status' => 'Select a valid order status', +); diff --git a/local/modules/Colissimo/I18n/fr_FR.php b/local/modules/Colissimo/I18n/fr_FR.php new file mode 100644 index 00000000..92634b2c --- /dev/null +++ b/local/modules/Colissimo/I18n/fr_FR.php @@ -0,0 +1,14 @@ + 'Activer la livraison offerte: ', + 'Can\'t read Config directory' => 'Le dossier Config ne peut être lu', + 'Can\'t read file' => 'Le fichier suivant ne peut être lu', + 'Can\'t write Config directory' => 'Le dossier Config ne peut être écrit', + 'Can\'t write file' => 'Le fichier suivant ne peut être écrit', + 'Colissimo delivery unavailable for the delivery country' => 'La livraison par Colissimo n\'est pas disponible dans ce pays', + 'Colissimo delivery unavailable for this cart weight (%weight kg)' => 'La livraison par Colissimo n\'est pas disponible pour un panier de %weight Kg', + 'Modify status export after export' => 'Modification du statut des commandes après l\'export', + 'colissimo expeditor export' => 'Export pour le logiciel Expeditor', + 'select a valid status' => 'Choisissez un statut de commande valide.', +]; diff --git a/local/modules/Colissimo/I18n/ru_RU.php b/local/modules/Colissimo/I18n/ru_RU.php new file mode 100644 index 00000000..325adc85 --- /dev/null +++ b/local/modules/Colissimo/I18n/ru_RU.php @@ -0,0 +1,15 @@ + 'Активировать бесплатную доставку:', + 'Can\'t read Config directory' => 'Невозможно прочитать директорию Config', + 'Can\'t read file' => 'Невозможно прочитать файл', + 'Can\'t write Config directory' => 'Невозможно записать в директорию Config', + 'Can\'t write file' => 'Невозможно записать файл', + 'Check if you want to activate Colissimo' => 'Выберите если хотите активировать Colissimo', + 'Colissimo delivery unavailable for the delivery country' => 'Доставка Colissimo не доступна для страны доставки', + 'Colissimo delivery unavailable for this cart weight (%weight kg)' => 'Доставка Colissimo не доступна для этого веса корзины (%weight кг)', + 'Modify status export after export' => 'Изменить статус экспорта после экспорта', + 'colissimo expeditor export' => 'Colissimo экспорт экспедитора', + 'select a valid status' => 'Выберите правильный статус', +); diff --git a/local/modules/Colissimo/I18n/tr_TR.php b/local/modules/Colissimo/I18n/tr_TR.php new file mode 100644 index 00000000..4d4ef3c5 --- /dev/null +++ b/local/modules/Colissimo/I18n/tr_TR.php @@ -0,0 +1,14 @@ + 'Ücretsiz nakliye etkinleştirmek için: ', + 'Can\'t read Config directory' => 'Yapılandırma dizini okunamıyor', + 'Can\'t read file' => 'Dosyayı okuyamıyor', + 'Can\'t write Config directory' => 'Dosyayı okuyamıyor', + 'Can\'t write file' => 'Dosyaya yazılamıyor', + 'Colissimo delivery unavailable for the delivery country' => 'Bu Teslimat Bu ülke için kullanılamaz Colissimo teslim', + 'Colissimo delivery unavailable for this cart weight (%weight kg)' => 'Colissimo teslimat için bu sepeti ağırlık (%weight kg) kullanılamaz', + 'Modify status export after export' => 'İhracat sonra sipariş durumunu değiştir', + 'colissimo expeditor export' => 'Colissimo Expeditor verme', + 'select a valid status' => 'Geçerli sipariş durumunu seçin', +]; diff --git a/local/modules/Colissimo/LICENSE.txt b/local/modules/Colissimo/LICENSE.txt new file mode 100644 index 00000000..65c5ca88 --- /dev/null +++ b/local/modules/Colissimo/LICENSE.txt @@ -0,0 +1,165 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + + This version of the GNU Lesser General Public License incorporates +the terms and conditions of version 3 of the GNU General Public +License, supplemented by the additional permissions listed below. + + 0. Additional Definitions. + + As used herein, "this License" refers to version 3 of the GNU Lesser +General Public License, and the "GNU GPL" refers to version 3 of the GNU +General Public License. + + "The Library" refers to a covered work governed by this License, +other than an Application or a Combined Work as defined below. + + An "Application" is any work that makes use of an interface provided +by the Library, but which is not otherwise based on the Library. +Defining a subclass of a class defined by the Library is deemed a mode +of using an interface provided by the Library. + + A "Combined Work" is a work produced by combining or linking an +Application with the Library. The particular version of the Library +with which the Combined Work was made is also called the "Linked +Version". + + The "Minimal Corresponding Source" for a Combined Work means the +Corresponding Source for the Combined Work, excluding any source code +for portions of the Combined Work that, considered in isolation, are +based on the Application, and not on the Linked Version. + + The "Corresponding Application Code" for a Combined Work means the +object code and/or source code for the Application, including any data +and utility programs needed for reproducing the Combined Work from the +Application, but excluding the System Libraries of the Combined Work. + + 1. Exception to Section 3 of the GNU GPL. + + You may convey a covered work under sections 3 and 4 of this License +without being bound by section 3 of the GNU GPL. + + 2. Conveying Modified Versions. + + If you modify a copy of the Library, and, in your modifications, a +facility refers to a function or data to be supplied by an Application +that uses the facility (other than as an argument passed when the +facility is invoked), then you may convey a copy of the modified +version: + + a) under this License, provided that you make a good faith effort to + ensure that, in the event an Application does not supply the + function or data, the facility still operates, and performs + whatever part of its purpose remains meaningful, or + + b) under the GNU GPL, with none of the additional permissions of + this License applicable to that copy. + + 3. Object Code Incorporating Material from Library Header Files. + + The object code form of an Application may incorporate material from +a header file that is part of the Library. You may convey such object +code under terms of your choice, provided that, if the incorporated +material is not limited to numerical parameters, data structure +layouts and accessors, or small macros, inline functions and templates +(ten or fewer lines in length), you do both of the following: + + a) Give prominent notice with each copy of the object code that the + Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the object code with a copy of the GNU GPL and this license + document. + + 4. Combined Works. + + You may convey a Combined Work under terms of your choice that, +taken together, effectively do not restrict modification of the +portions of the Library contained in the Combined Work and reverse +engineering for debugging such modifications, if you also do each of +the following: + + a) Give prominent notice with each copy of the Combined Work that + the Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the Combined Work with a copy of the GNU GPL and this license + document. + + c) For a Combined Work that displays copyright notices during + execution, include the copyright notice for the Library among + these notices, as well as a reference directing the user to the + copies of the GNU GPL and this license document. + + d) Do one of the following: + + 0) Convey the Minimal Corresponding Source under the terms of this + License, and the Corresponding Application Code in a form + suitable for, and under terms that permit, the user to + recombine or relink the Application with a modified version of + the Linked Version to produce a modified Combined Work, in the + manner specified by section 6 of the GNU GPL for conveying + Corresponding Source. + + 1) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (a) uses at run time + a copy of the Library already present on the user's computer + system, and (b) will operate properly with a modified version + of the Library that is interface-compatible with the Linked + Version. + + e) Provide Installation Information, but only if you would otherwise + be required to provide such information under section 6 of the + GNU GPL, and only to the extent that such information is + necessary to install and execute a modified version of the + Combined Work produced by recombining or relinking the + Application with a modified version of the Linked Version. (If + you use option 4d0, the Installation Information must accompany + the Minimal Corresponding Source and Corresponding Application + Code. If you use option 4d1, you must provide the Installation + Information in the manner specified by section 6 of the GNU GPL + for conveying Corresponding Source.) + + 5. Combined Libraries. + + You may place library facilities that are a work based on the +Library side by side in a single library together with other library +facilities that are not Applications and are not covered by this +License, and convey such a combined library under terms of your +choice, if you do both of the following: + + a) Accompany the combined library with a copy of the same work based + on the Library, uncombined with any other library facilities, + conveyed under the terms of this License. + + b) Give prominent notice with the combined library that part of it + is a work based on the Library, and explaining where to find the + accompanying uncombined form of the same work. + + 6. Revised Versions of the GNU Lesser General Public License. + + The Free Software Foundation may publish revised and/or new versions +of the GNU Lesser General Public License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. + + Each version is given a distinguishing version number. If the +Library as you received it specifies that a certain numbered version +of the GNU Lesser General Public License "or any later version" +applies to it, you have the option of following the terms and +conditions either of that published version or of any later version +published by the Free Software Foundation. If the Library as you +received it does not specify a version number of the GNU Lesser +General Public License, you may choose any version of the GNU Lesser +General Public License ever published by the Free Software Foundation. + + If the Library as you received it specifies that a proxy can decide +whether future versions of the GNU Lesser General Public License shall +apply, that proxy's public statement of acceptance of any version is +permanent authorization for you to choose that version for the +Library. diff --git a/local/modules/Colissimo/Listener/SendMail.php b/local/modules/Colissimo/Listener/SendMail.php new file mode 100755 index 00000000..e9db80ae --- /dev/null +++ b/local/modules/Colissimo/Listener/SendMail.php @@ -0,0 +1,104 @@ + + */ +class SendMail implements EventSubscriberInterface +{ + + protected $parser; + + protected $mailer; + + public function __construct(ParserInterface $parser, MailerFactory $mailer) + { + $this->parser = $parser; + $this->mailer = $mailer; + } + + public function updateStatus(OrderEvent $event) + { + $order = $event->getOrder(); + $colissimo = new Colissimo(); + + if ($order->isSent() && $order->getDeliveryModuleId() == $colissimo->getModuleModel()->getId()) { + $contact_email = ConfigQuery::getStoreEmail(); + + if ($contact_email) { + $order = $event->getOrder(); + $customer = $order->getCustomer(); + + $this->mailer->sendEmailToCustomer( + 'mail_colissimo', + $customer, + [ + 'customer_id' => $customer->getId(), + 'order_ref' => $order->getRef(), + 'order_date' => $order->getCreatedAt(), + 'update_date' => $order->getUpdatedAt(), + 'package' => $order->getDeliveryRef() + ] + ); + + Tlog::getInstance()->debug("Colissimo shipping message sent to customer ".$customer->getEmail()); + } else { + $customer = $order->getCustomer(); + Tlog::getInstance()->debug("Colissimo shipping message no contact email customer_id", $customer->getId()); + } + } + } + + /** + * Returns an array of event names this subscriber wants to listen to. + * + * The array keys are event names and the value can be: + * + * * The method name to call (priority defaults to 0) + * * An array composed of the method name to call and the priority + * * An array of arrays composed of the method names to call and respective + * priorities, or 0 if unset + * + * For instance: + * + * * array('eventName' => 'methodName') + * * array('eventName' => array('methodName', $priority)) + * * array('eventName' => array(array('methodName1', $priority), array('methodName2')) + * + * @return array The event names to listen to + * + * @api + */ + public static function getSubscribedEvents() + { + return array( + TheliaEvents::ORDER_UPDATE_STATUS => array("updateStatus", 128) + ); + } +} diff --git a/local/modules/Colissimo/Loop/CheckRightsLoop.php b/local/modules/Colissimo/Loop/CheckRightsLoop.php new file mode 100755 index 00000000..d655f1ad --- /dev/null +++ b/local/modules/Colissimo/Loop/CheckRightsLoop.php @@ -0,0 +1,100 @@ + + */ +class CheckRightsLoop extends BaseLoop implements ArraySearchLoopInterface +{ + protected function getArgDefinitions() + { + return new ArgumentCollection(); + } + + public function buildArray() + { + $ret = array(); + $dir = __DIR__."/../Config/"; + if (!is_readable($dir)) { + + $ret[] = array( + "ERRMES"=>Translator::getInstance()->trans( + "Can't read Config directory", + [], + Colissimo::DOMAIN_NAME + ), + "ERRFILE"=>"" + ); + } + if (!is_writable($dir)) { + $ret[] = array( + "ERRMES"=>Translator::getInstance()->trans( + "Can't write Config directory", + [], + Colissimo::DOMAIN_NAME + ), + "ERRFILE"=>"" + ); + + } + if ($handle = opendir($dir)) { + while (false !== ($file = readdir($handle))) { + if (strlen($file) > 5 && substr($file, -5) === ".json") { + if (!is_readable($dir.$file)) { + + $ret[] = array( + "ERRMES"=>Translator::getInstance()->trans( + "Can't read file", + [], + Colissimo::DOMAIN_NAME + ), + "ERRFILE"=>"Colissimo/Config/".$file + ); + } + if (!is_writable($dir.$file)) { + $ret[] = array( + "ERRMES"=>Translator::getInstance()->trans( + "Can't write file", + [], + Colissimo::DOMAIN_NAME + ), + "ERRFILE"=>"Colissimo/Config/".$file + ); + + } + } + } + } + return $ret; + } + public function parseResults(LoopResult $loopResult) + { + foreach ($loopResult->getResultDataCollection() as $arr) { + $loopResultRow = new LoopResultRow(); + $loopResultRow->set("ERRMES", $arr["ERRMES"]) + ->set("ERRFILE", $arr["ERRFILE"]); + $loopResult->addRow($loopResultRow); + } + return $loopResult; + } +} diff --git a/local/modules/Colissimo/Loop/NotSendLoop.php b/local/modules/Colissimo/Loop/NotSendLoop.php new file mode 100644 index 00000000..b504924e --- /dev/null +++ b/local/modules/Colissimo/Loop/NotSendLoop.php @@ -0,0 +1,74 @@ + + */ +class NotSendLoop extends Order +{ + /** + * + * define all args used in your loop + * + * + * example : + * + * public function getArgDefinitions() + * { + * return new ArgumentCollection( + * Argument::createIntListTypeArgument('id'), + * new Argument( + * 'ref', + * new TypeCollection( + * new Type\AlphaNumStringListType() + * ) + * ), + * Argument::createIntListTypeArgument('category'), + * Argument::createBooleanTypeArgument('new'), + * Argument::createBooleanTypeArgument('promo'), + * Argument::createFloatTypeArgument('min_price'), + * Argument::createFloatTypeArgument('max_price'), + * Argument::createIntTypeArgument('min_stock'), + * Argument::createFloatTypeArgument('min_weight'), + * Argument::createFloatTypeArgument('max_weight'), + * Argument::createBooleanTypeArgument('current'), + * + * ); + * } + * + * @return \Thelia\Core\Template\Loop\Argument\ArgumentCollection + */ + public function getArgDefinitions() + { + return new ArgumentCollection(Argument::createBooleanTypeArgument('with_prev_next_info', false)); + } + + /** + * this method returns a Propel ModelCriteria + * + * @return \Propel\Runtime\ActiveQuery\ModelCriteria + */ + public function buildModelCriteria() + { + return ColissimoQuery::getOrders(); + } +} diff --git a/local/modules/Colissimo/Loop/Price.php b/local/modules/Colissimo/Loop/Price.php new file mode 100755 index 00000000..014f5eef --- /dev/null +++ b/local/modules/Colissimo/Loop/Price.php @@ -0,0 +1,73 @@ + + */ +class Price extends BaseLoop implements ArraySearchLoopInterface +{ + /* set countable to false since we need to preserve keys */ + protected $countable = false; + + /** + * @return ArgumentCollection + */ + protected function getArgDefinitions() + { + return new ArgumentCollection( + Argument::createIntTypeArgument('area', null, true) + ); + } + + public function buildArray() + { + $area = $this->getArea(); + $prices = Colissimo::getPrices(); + + if (!isset($prices[$area]) || !isset($prices[$area]["slices"])) { + return array(); + } + + $areaPrices = $prices[$area]["slices"]; + ksort($areaPrices); + + return $areaPrices; + } + + public function parseResults(LoopResult $loopResult) + { + foreach ($loopResult->getResultDataCollection() as $maxWeight => $price) { + $loopResultRow = new LoopResultRow(); + $loopResultRow->set("MAX_WEIGHT", $maxWeight) + ->set("PRICE", $price); + + $loopResult->addRow($loopResultRow); + } + return $loopResult; + } +} diff --git a/local/modules/Colissimo/Model/ColissimoQuery.php b/local/modules/Colissimo/Model/ColissimoQuery.php new file mode 100644 index 00000000..2fb634c7 --- /dev/null +++ b/local/modules/Colissimo/Model/ColissimoQuery.php @@ -0,0 +1,66 @@ +. */ +/* */ +/*************************************************************************************/ + +namespace Colissimo\Model; + +use Colissimo\Colissimo; +use Propel\Runtime\ActiveQuery\Criteria; +use Thelia\Model\OrderQuery; +use Thelia\Model\OrderStatus; +use Thelia\Model\OrderStatusQuery; + +/** + * Class ColissimoQuery + * @package Colissimo\Model + * @author Manuel Raynaud + */ +class ColissimoQuery +{ + /** + * @return OrderQuery + */ + public static function getOrders() + { + $status = OrderStatusQuery::create() + ->filterByCode( + array( + OrderStatus::CODE_PAID, + OrderStatus::CODE_PROCESSING, + ), + Criteria::IN + ) + ->find() + ->toArray("code"); + + $query = OrderQuery::create() + ->filterByDeliveryModuleId((new Colissimo())->getModuleModel()->getId()) + ->filterByStatusId( + array( + $status[OrderStatus::CODE_PAID]['Id'], + $status[OrderStatus::CODE_PROCESSING]['Id']), + Criteria::IN + ); + + return $query; + } +} diff --git a/local/modules/Colissimo/Model/Config/Base/ColissimoConfigValue.php b/local/modules/Colissimo/Model/Config/Base/ColissimoConfigValue.php new file mode 100644 index 00000000..c481a36a --- /dev/null +++ b/local/modules/Colissimo/Model/Config/Base/ColissimoConfigValue.php @@ -0,0 +1,25 @@ + + */ +class ColissimoConfigValue +{ + const FREE_SHIPPING = "free_shipping"; + const PRICES = "prices"; + const ENABLED = "enabled"; +} diff --git a/local/modules/Colissimo/Model/Config/ColissimoConfigValue.php b/local/modules/Colissimo/Model/Config/ColissimoConfigValue.php new file mode 100644 index 00000000..d0cb0be1 --- /dev/null +++ b/local/modules/Colissimo/Model/Config/ColissimoConfigValue.php @@ -0,0 +1,24 @@ + + */ +class ColissimoConfigValue extends BaseColissimoConfigValue +{ +} diff --git a/local/modules/Colissimo/THELIA_INET.FMT b/local/modules/Colissimo/THELIA_INET.FMT new file mode 100644 index 00000000..2d3a67b6 --- /dev/null +++ b/local/modules/Colissimo/THELIA_INET.FMT @@ -0,0 +1,23 @@ +[GENERAL] +DELIMITE=O +SEPARATEUR=59 +DELIMITEUR=34 +FINDELIGNE=CRLF +Unité poids=KG +[CHAMPS] +ReferenceExpedition=1 +NomDestinataire=2 +Prenom=3 +Adresse1=4 +Adresse2=5 +Adresse3=6 +CodePostal=7 +Commune=8 +CodePays=9 +Telephone=10 +Portable=11 +Poids=12 +Mail=13 +CodePointRetrait=14 +CodeProduit=15 +NomCommercialChargeur=16 diff --git a/local/modules/Colissimo/composer.json b/local/modules/Colissimo/composer.json new file mode 100644 index 00000000..d84be8fd --- /dev/null +++ b/local/modules/Colissimo/composer.json @@ -0,0 +1,11 @@ +{ + "name": "thelia/colissimo-module", + "license": "LGPL-3.0+", + "type": "thelia-module", + "require": { + "thelia/installer": "~1.1" + }, + "extra": { + "installer-name": "Colissimo" + } +} diff --git a/local/modules/Colissimo/documentation/TarifsAvril2013.pdf b/local/modules/Colissimo/documentation/TarifsAvril2013.pdf new file mode 100755 index 0000000000000000000000000000000000000000..886a9983c8e494c318b1942a6183152586bb6922 GIT binary patch literal 184810 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 WodDM!FBboG{TKxYUa%kQ$Nvvb6JS*U literal 0 HcmV?d00001 diff --git a/local/modules/Colissimo/documentation/readme.txt b/local/modules/Colissimo/documentation/readme.txt new file mode 100755 index 00000000..b673e196 --- /dev/null +++ b/local/modules/Colissimo/documentation/readme.txt @@ -0,0 +1,3 @@ +Colissimo prices based on April 2013 pdf. +TarifsAvril2013.pdf is available in this module documentation folder. +You may update prices in Config/prices.json file. \ No newline at end of file diff --git a/local/modules/Colissimo/templates/backOffice/default/assets/js/module-configuration-js.html b/local/modules/Colissimo/templates/backOffice/default/assets/js/module-configuration-js.html new file mode 100644 index 00000000..a51dac94 --- /dev/null +++ b/local/modules/Colissimo/templates/backOffice/default/assets/js/module-configuration-js.html @@ -0,0 +1,36 @@ +{javascripts file="assets/js/bootstrap-switch/bootstrap-switch.js"} + +{/javascripts} + + \ No newline at end of file diff --git a/local/modules/Colissimo/templates/backOffice/default/module_configuration.html b/local/modules/Colissimo/templates/backOffice/default/module_configuration.html new file mode 100755 index 00000000..3c495353 --- /dev/null +++ b/local/modules/Colissimo/templates/backOffice/default/module_configuration.html @@ -0,0 +1,316 @@ +
    + + {loop name="checkrights.colissimo" type="colissimo.check.rights"} +
    +

    {$ERRMES} {$ERRFILE} | {intl d='colissimo.bo.default' l="Please change the access rights"}.

    +
    + {/loop} +
    + +{elseloop rel="checkrights.colissimo"} + +
    +

    {intl d='colissimo.bo.default' l="Colissimo Module allows to send your products all around the world with La Poste."}

    +
    + + + +
    +
    +
    + {form name="colissimo.configuration"} + + {form_hidden_fields form=$form} + + {form_field form=$form field="enabled"} +
    + + {if ! empty($label_attr.help)} + {$label_attr.help} + {/if} +
    + {/form_field} + + + + {/form} +
    +
    +
    + +
    +
    +
    + + + +
    + + +
    + {form name="colissimo.export.form"} + {if $form_error}
    {$form_error_message}
    {/if} +
    + {form_hidden_fields} +
    + +
    + {intl d='colissimo.bo.default' l="Change orders status after export"} +
    + +
    + + {form_field field="status_id"} + + + + + + + + + + + + + {/form_field} +
    +   + + +
    +   + + +
    +   + + +
    + + {intl d='colissimo.ai' l="*If you choose this option, the exported orders would not be available on this page anymore"} +
    +
    + + + + + + + + + + + + + + + {loop name="colissimo.notsend.loop" type="colissimo.notsend.loop"} + + + + + + + + + + {/loop} + {elseloop rel="colissimo.notsend.loop"} + + + + {/elseloop} + +
    + {intl d='colissimo.ai' l="REF"} + + {intl d='colissimo.ai' l="Customer"} + + {intl d='colissimo.ai' l="Date"} + + {intl d='colissimo.ai' l="Total taxed amount"} + + {intl d='colissimo.ai' l="Number of packages"} + + {intl d='colissimo.ai' l="Packages weight"} + + {intl d='colissimo.ai' l="Export"} +
    + {$REF} + + {loop type='customer' name='colissimo.customer' id=$CUSTOMER current='false'} + {$LASTNAME} {$FIRSTNAME} + {/loop} + + {$CREATE_DATE|date_format} + + {$TOTAL_TAXED_AMOUNT} {loop name="list.socolissimo.getcurrency" type="currency" id=$CURRENCY}{$SYMBOL}{/loop} + + {form_field form=$form field="order_nb_pkg_"|cat:$ID} + + {/form_field} + + {form_field form=$form field="order_weight_"|cat:$ID} + + {/form_field} + + {form_field field="order_"|cat:$ID} + + {/form_field} +
    +
    +
    {intl d='colissimo.ai' l="There is currently not orders to export"}
    +
    + + {ifloop rel="colissimo.notsend.loop"} + + {/ifloop} +
    + {/form} +
    + +
    + + {assign var="isColissimoFreeShipping" value=0} + {form name="colissimo.freeshipping.form"} +
    +
    + {form_hidden_fields} + + {form_field field="freeshipping"} + + +
    + +
    + {/form_field} +
    + {/form} + +
    +
    +
    +
    +
    +{/elseloop} diff --git a/local/modules/FreeOrder/Config/config.xml b/local/modules/FreeOrder/Config/config.xml new file mode 100644 index 00000000..42d3733f --- /dev/null +++ b/local/modules/FreeOrder/Config/config.xml @@ -0,0 +1,6 @@ + + + + diff --git a/local/modules/FreeOrder/Config/module.xml b/local/modules/FreeOrder/Config/module.xml new file mode 100644 index 00000000..d205108f --- /dev/null +++ b/local/modules/FreeOrder/Config/module.xml @@ -0,0 +1,27 @@ + + + FreeOrder\FreeOrder + + There's nothing to pay for this order + This is a pseudo-payment module for free orders. + + + Vous n'avez rien à payer pour cette commande + Un pseudo-module de paiement pour les commandes de montant nul + + + en_US + fr_FR + + 2.4.3 + + Franck Allimant + CQFDev + franck@cqfdev.fr + + payment + 2.4.3 + alpha + diff --git a/local/modules/FreeOrder/FreeOrder.php b/local/modules/FreeOrder/FreeOrder.php new file mode 100644 index 00000000..0aaae1c3 --- /dev/null +++ b/local/modules/FreeOrder/FreeOrder.php @@ -0,0 +1,41 @@ +getCurrentOrderTotalAmount(), 4) == 0; + } + + public function pay(Order $order) + { + $event = new OrderEvent($order); + $event->setStatus(OrderStatusQuery::getPaidStatus()->getId()); + $this->getDispatcher()->dispatch(TheliaEvents::ORDER_UPDATE_STATUS, $event); + } + + public function manageStockOnCreation() + { + return false; + } +} diff --git a/local/modules/FreeOrder/LICENSE.txt b/local/modules/FreeOrder/LICENSE.txt new file mode 100644 index 00000000..65c5ca88 --- /dev/null +++ b/local/modules/FreeOrder/LICENSE.txt @@ -0,0 +1,165 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + + This version of the GNU Lesser General Public License incorporates +the terms and conditions of version 3 of the GNU General Public +License, supplemented by the additional permissions listed below. + + 0. Additional Definitions. + + As used herein, "this License" refers to version 3 of the GNU Lesser +General Public License, and the "GNU GPL" refers to version 3 of the GNU +General Public License. + + "The Library" refers to a covered work governed by this License, +other than an Application or a Combined Work as defined below. + + An "Application" is any work that makes use of an interface provided +by the Library, but which is not otherwise based on the Library. +Defining a subclass of a class defined by the Library is deemed a mode +of using an interface provided by the Library. + + A "Combined Work" is a work produced by combining or linking an +Application with the Library. The particular version of the Library +with which the Combined Work was made is also called the "Linked +Version". + + The "Minimal Corresponding Source" for a Combined Work means the +Corresponding Source for the Combined Work, excluding any source code +for portions of the Combined Work that, considered in isolation, are +based on the Application, and not on the Linked Version. + + The "Corresponding Application Code" for a Combined Work means the +object code and/or source code for the Application, including any data +and utility programs needed for reproducing the Combined Work from the +Application, but excluding the System Libraries of the Combined Work. + + 1. Exception to Section 3 of the GNU GPL. + + You may convey a covered work under sections 3 and 4 of this License +without being bound by section 3 of the GNU GPL. + + 2. Conveying Modified Versions. + + If you modify a copy of the Library, and, in your modifications, a +facility refers to a function or data to be supplied by an Application +that uses the facility (other than as an argument passed when the +facility is invoked), then you may convey a copy of the modified +version: + + a) under this License, provided that you make a good faith effort to + ensure that, in the event an Application does not supply the + function or data, the facility still operates, and performs + whatever part of its purpose remains meaningful, or + + b) under the GNU GPL, with none of the additional permissions of + this License applicable to that copy. + + 3. Object Code Incorporating Material from Library Header Files. + + The object code form of an Application may incorporate material from +a header file that is part of the Library. You may convey such object +code under terms of your choice, provided that, if the incorporated +material is not limited to numerical parameters, data structure +layouts and accessors, or small macros, inline functions and templates +(ten or fewer lines in length), you do both of the following: + + a) Give prominent notice with each copy of the object code that the + Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the object code with a copy of the GNU GPL and this license + document. + + 4. Combined Works. + + You may convey a Combined Work under terms of your choice that, +taken together, effectively do not restrict modification of the +portions of the Library contained in the Combined Work and reverse +engineering for debugging such modifications, if you also do each of +the following: + + a) Give prominent notice with each copy of the Combined Work that + the Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the Combined Work with a copy of the GNU GPL and this license + document. + + c) For a Combined Work that displays copyright notices during + execution, include the copyright notice for the Library among + these notices, as well as a reference directing the user to the + copies of the GNU GPL and this license document. + + d) Do one of the following: + + 0) Convey the Minimal Corresponding Source under the terms of this + License, and the Corresponding Application Code in a form + suitable for, and under terms that permit, the user to + recombine or relink the Application with a modified version of + the Linked Version to produce a modified Combined Work, in the + manner specified by section 6 of the GNU GPL for conveying + Corresponding Source. + + 1) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (a) uses at run time + a copy of the Library already present on the user's computer + system, and (b) will operate properly with a modified version + of the Library that is interface-compatible with the Linked + Version. + + e) Provide Installation Information, but only if you would otherwise + be required to provide such information under section 6 of the + GNU GPL, and only to the extent that such information is + necessary to install and execute a modified version of the + Combined Work produced by recombining or relinking the + Application with a modified version of the Linked Version. (If + you use option 4d0, the Installation Information must accompany + the Minimal Corresponding Source and Corresponding Application + Code. If you use option 4d1, you must provide the Installation + Information in the manner specified by section 6 of the GNU GPL + for conveying Corresponding Source.) + + 5. Combined Libraries. + + You may place library facilities that are a work based on the +Library side by side in a single library together with other library +facilities that are not Applications and are not covered by this +License, and convey such a combined library under terms of your +choice, if you do both of the following: + + a) Accompany the combined library with a copy of the same work based + on the Library, uncombined with any other library facilities, + conveyed under the terms of this License. + + b) Give prominent notice with the combined library that part of it + is a work based on the Library, and explaining where to find the + accompanying uncombined form of the same work. + + 6. Revised Versions of the GNU Lesser General Public License. + + The Free Software Foundation may publish revised and/or new versions +of the GNU Lesser General Public License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. + + Each version is given a distinguishing version number. If the +Library as you received it specifies that a certain numbered version +of the GNU Lesser General Public License "or any later version" +applies to it, you have the option of following the terms and +conditions either of that published version or of any later version +published by the Free Software Foundation. If the Library as you +received it does not specify a version number of the GNU Lesser +General Public License, you may choose any version of the GNU Lesser +General Public License ever published by the Free Software Foundation. + + If the Library as you received it specifies that a proxy can decide +whether future versions of the GNU Lesser General Public License shall +apply, that proxy's public statement of acceptance of any version is +permanent authorization for you to choose that version for the +Library. diff --git a/local/modules/FreeOrder/Readme.md b/local/modules/FreeOrder/Readme.md new file mode 100644 index 00000000..63333460 --- /dev/null +++ b/local/modules/FreeOrder/Readme.md @@ -0,0 +1,25 @@ +# Free Order + +This module is used to terminate the order process when the order amount is 0,00. In this case, none of the traditional +payment modules applies. + +## Installation + +This module is bundled with Thelia standard distribution. + +### Manually + +* Copy the module into ```/local/modules/``` directory and be sure that the name of the module is FreeOrder. +* Activate it in your thelia administration panel + +### Composer + +Add it in your main thelia composer.json file + +``` +composer require thelia/free-order-module:~1.0 +``` + +## Usage + +The module is displayed as needed in the payment modules list of the order-invoice page. \ No newline at end of file diff --git a/local/modules/FreeOrder/composer.json b/local/modules/FreeOrder/composer.json new file mode 100644 index 00000000..f32437ec --- /dev/null +++ b/local/modules/FreeOrder/composer.json @@ -0,0 +1,11 @@ +{ + "name": "thelia/free-order-module", + "license": "LGPL-3.0+", + "type": "thelia-module", + "require": { + "thelia/installer": "~1.1" + }, + "extra": { + "installer-name": "FreeOrder" + } +} \ No newline at end of file diff --git a/local/modules/Front/Config/config.xml b/local/modules/Front/Config/config.xml new file mode 100644 index 00000000..dc19adf1 --- /dev/null +++ b/local/modules/Front/Config/config.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + Front/Config/front.xml + + %kernel.cache_dir% + %kernel.debug% + + + + + + diff --git a/local/modules/Front/Config/front.xml b/local/modules/Front/Config/front.xml new file mode 100644 index 00000000..20bea5d7 --- /dev/null +++ b/local/modules/Front/Config/front.xml @@ -0,0 +1,276 @@ + + + + + + Thelia\Controller\Front\DefaultController::noAction + includes/mini-cart + + + + Thelia\Controller\Front\DefaultController::noAction + includes/addedToCart + + + + + Front\Controller\CustomerController::viewRegisterAction + + + + Front\Controller\CustomerController::createAction + register + + + + + Front\Controller\CustomerController::viewLoginAction + + + + Front\Controller\CustomerController::loginAction + login + + + + + Front\Controller\CustomerController::newPasswordAction + password + + + + Front\Controller\CustomerController::newPasswordSentAction + password + + + + + Front\Controller\CustomerController::logoutAction + + + + + Front\Controller\CustomerController::confirmCustomerAction + + + + + + Thelia\Controller\Front\DefaultController::noAction + account + + + + Front\Controller\CustomerController::viewAction + account-update + + + + Front\Controller\CustomerController::updateAction + account-update + + + + + Front\Controller\CustomerController::updatePasswordAction + account-password + + + + Thelia\Controller\Front\DefaultController::noAction + account-password + + + + Front\Controller\OrderController::viewAction + \d+ + + + + Front\Controller\OrderController::generateDeliveryPdf + \d+ + + + + Front\Controller\OrderController::generateInvoicePdf + \d+ + + + + Front\Controller\OrderController::downloadVirtualProduct + \d+ + + + + + + Thelia\Controller\Front\DefaultController::noAction + address + + + + Front\Controller\AddressController::createAction + address + + + + Front\Controller\AddressController::updateViewAction + address-update + + + + Front\Controller\AddressController::processUpdateAction + address-update + + + + Front\Controller\AddressController::deleteAction + account + + + + Front\Controller\AddressController::generateModalAction + modal-address + \d+ + + + + Front:Address:makeAddressDefault + \d+ + + + + + + + Thelia\Controller\Front\DefaultController::noAction + cart + + + + Front\Controller\CartController::addItem + + + + Front\Controller\CartController::deleteItem + cart + + + + Front\Controller\CartController::changeItem + cart + + + + Front\Controller\CartController::changeCountry + cart + + + + + + Front\Controller\OrderController::deliver + order-delivery + + + + Front\Controller\OrderController::deliverView + order-delivery + + + + Front\Controller\OrderController::getDeliveryModuleListAjaxAction + + + + Front\Controller\OrderController::invoice + order-invoice + + + + Thelia\Controller\Front\DefaultController::noAction + order-invoice + + + + Front\Controller\CouponController::consumeAction + order-invoice + + + + Front\Controller\CouponController::clearAllCouponsAction + order-invoice + + + + Front\Controller\OrderController::pay + + + + Front\Controller\OrderController::orderPlaced + order-placed + + + + Front\Controller\OrderController::orderFailed + order-failed + + + + + + Front\Controller\ContactController::sendAction + contact + + + + Thelia\Controller\Front\DefaultController::noAction + contact-success + + + + + + Front\Controller\NewsletterController::subscribeAction + newsletter + + + + Front\Controller\NewsletterController::unsubscribeAction + newsletter-unsubscribe + + + + + + + Front\Controller\SitemapController::generateAction + + + Front\Controller\SitemapController::generateAction + + + + + + Front\Controller\FeedController::generateAction + catalog + + + + + + + + Thelia\Controller\Front\DefaultController::emptyRoute + + + + + Thelia\Controller\Front\DefaultController::noAction + index + ^(?!admin|api)[^/]+ + + diff --git a/local/modules/Front/Config/module.xml b/local/modules/Front/Config/module.xml new file mode 100644 index 00000000..35f38bef --- /dev/null +++ b/local/modules/Front/Config/module.xml @@ -0,0 +1,29 @@ + + + Front\Front + + Front integration + + + + Front office module + + + + en_US + fr_FR + + 2.4.3 + + + Thelia team + info@thelia.net + + + classic + 2.4.3 + alpha + 1 + diff --git a/local/modules/Front/Controller/AddressController.php b/local/modules/Front/Controller/AddressController.php new file mode 100644 index 00000000..5ef57311 --- /dev/null +++ b/local/modules/Front/Controller/AddressController.php @@ -0,0 +1,273 @@ +. */ +/* */ +/*************************************************************************************/ + +namespace Front\Controller; + +use Front\Front; +use Symfony\Component\Form\Form; +use Thelia\Controller\Front\BaseFrontController; +use Thelia\Core\Event\Address\AddressCreateOrUpdateEvent; +use Thelia\Core\Event\Address\AddressEvent; +use Thelia\Core\Event\TheliaEvents; +use Thelia\Form\Definition\FrontForm; +use Thelia\Form\Exception\FormValidationException; +use Thelia\Log\Tlog; +use Thelia\Model\AddressQuery; +use Thelia\Model\Customer; + +/** + * Class AddressController + * @package Thelia\Controller\Front + * @author Manuel Raynaud + */ +class AddressController extends BaseFrontController +{ + + /** + * Controller for generate modal containing update form + * Check if request is a XmlHttpRequest and address owner is the current customer + * + * @param $address_id + */ + public function generateModalAction($address_id) + { + + $this->checkAuth(); + $this->checkXmlHttpRequest(); + + } + + /** + * Create controller. + * Check if customer is logged in + * + * Dispatch TheliaEvents::ADDRESS_CREATE event + */ + public function createAction() + { + $this->checkAuth(); + + $addressCreate = $this->createForm(FrontForm::ADDRESS_CREATE); + + try { + /** @var Customer $customer */ + $customer = $this->getSecurityContext()->getCustomerUser(); + + $form = $this->validateForm($addressCreate, "post"); + $event = $this->createAddressEvent($form); + $event->setCustomer($customer); + + $this->dispatch(TheliaEvents::ADDRESS_CREATE, $event); + + return $this->generateSuccessRedirect($addressCreate); + } catch (FormValidationException $e) { + $message = $this->getTranslator()->trans("Please check your input: %s", ['%s' => $e->getMessage()], Front::MESSAGE_DOMAIN); + } catch (\Exception $e) { + $message = $this->getTranslator()->trans("Sorry, an error occured: %s", ['%s' => $e->getMessage()], Front::MESSAGE_DOMAIN); + } + + Tlog::getInstance()->error(sprintf("Error during address creation process : %s", $message)); + + $addressCreate->setErrorMessage($message); + + $this->getParserContext() + ->addForm($addressCreate) + ->setGeneralError($message) + ; + + // Redirect to error URL if defined + if ($addressCreate->hasErrorUrl()) { + return $this->generateErrorRedirect($addressCreate); + } + } + + protected function createAddressEvent(Form $form) + { + return new AddressCreateOrUpdateEvent( + $form->get("label")->getData(), + $form->get("title")->getData(), + $form->get("firstname")->getData(), + $form->get("lastname")->getData(), + $form->get("address1")->getData(), + $form->get("address2")->getData(), + $form->get("address3")->getData(), + $form->get("zipcode")->getData(), + $form->get("city")->getData(), + $form->get("country")->getData(), + $form->get("cellphone")->getData(), + $form->get("phone")->getData(), + $form->get("company")->getData(), + $form->get("is_default")->getData(), + $form->get("state")->getData() + ); + } + + public function updateViewAction($address_id) + { + $this->checkAuth(); + + $customer = $this->getSecurityContext()->getCustomerUser(); + $address = AddressQuery::create()->findPk($address_id); + + if (!$address || $customer->getId() != $address->getCustomerId()) { + return $this->generateRedirectFromRoute('default'); + } + + $this->getParserContext()->set("address_id", $address_id); + } + + public function processUpdateAction($address_id) + { + $this->checkAuth(); + + $addressUpdate = $this->createForm(FrontForm::ADDRESS_UPDATE); + + try { + $customer = $this->getSecurityContext()->getCustomerUser(); + + $form = $this->validateForm($addressUpdate); + + $address = AddressQuery::create()->findPk($address_id); + + if (null === $address) { + return $this->generateRedirectFromRoute('default'); + } + + if ($address->getCustomer()->getId() != $customer->getId()) { + return $this->generateRedirectFromRoute('default'); + } + + $event = $this->createAddressEvent($form); + $event->setAddress($address); + + $this->dispatch(TheliaEvents::ADDRESS_UPDATE, $event); + + return $this->generateSuccessRedirect($addressUpdate); + } catch (FormValidationException $e) { + $message = $this->getTranslator()->trans("Please check your input: %s", ['%s' => $e->getMessage()], Front::MESSAGE_DOMAIN); + } catch (\Exception $e) { + $message = $this->getTranslator()->trans("Sorry, an error occured: %s", ['%s' => $e->getMessage()], Front::MESSAGE_DOMAIN); + } + + $this->getParserContext()->set("address_id", $address_id); + + Tlog::getInstance()->error(sprintf("Error during address creation process : %s", $message)); + + $addressUpdate->setErrorMessage($message); + + $this->getParserContext() + ->addForm($addressUpdate) + ->setGeneralError($message) + ; + + if ($addressUpdate->hasErrorUrl()) { + return $this->generateErrorRedirect($addressUpdate); + } + } + + public function deleteAction($address_id) + { + $this->checkAuth(); + $error_message = false; + + $customer = $this->getSecurityContext()->getCustomerUser(); + $address = AddressQuery::create()->findPk($address_id); + + if (!$address || $customer->getId() != $address->getCustomerId()) { + // If Ajax Request + if ($this->getRequest()->isXmlHttpRequest()) { + return $this->jsonResponse( + json_encode( + array( + "success" => false, + "message" => $this->getTranslator()->trans( + "Error during address deletion process", + [], + Front::MESSAGE_DOMAIN + ) + ) + ) + ); + } else { + return $this->generateRedirectFromRoute('default'); + } + } + + try { + $this->dispatch(TheliaEvents::ADDRESS_DELETE, new AddressEvent($address)); + } catch (\Exception $e) { + $error_message = $e->getMessage(); + } + + Tlog::getInstance()->error(sprintf('Error during address deletion : %s', $error_message)); + + // If Ajax Request + if ($this->getRequest()->isXmlHttpRequest()) { + if ($error_message) { + $response = $this->jsonResponse(json_encode(array( + "success" => false, + "message" => $error_message + ))); + } else { + $response = $this->jsonResponse( + json_encode([ + "success" => true, + "message" => "" + ]) + ); + } + + return $response; + + } else { + return $this->generateRedirectFromRoute('default', array('view'=>'account')); + } + } + + public function makeAddressDefaultAction($addressId) + { + $this->checkAuth(); + + $address = AddressQuery::create() + ->filterByCustomerId($this->getSecurityContext()->getCustomerUser()->getId()) + ->findPk($addressId) + ; + + if (null === $address) { + $this->pageNotFound(); + } + + try { + $event = new AddressEvent($address); + $this->dispatch(TheliaEvents::ADDRESS_DEFAULT, $event); + } catch (\Exception $e) { + $this->getParserContext() + ->setGeneralError($e->getMessage()) + ; + + return $this->render("account"); + } + + return $this->generateRedirectFromRoute('default', array('view'=>'account')); + } +} diff --git a/local/modules/Front/Controller/CartController.php b/local/modules/Front/Controller/CartController.php new file mode 100644 index 00000000..ebb7f34e --- /dev/null +++ b/local/modules/Front/Controller/CartController.php @@ -0,0 +1,250 @@ +. */ +/* */ +/*************************************************************************************/ +namespace Front\Controller; + +use Front\Front; +use Propel\Runtime\Exception\PropelException; +use Symfony\Component\HttpFoundation\Cookie; +use Symfony\Component\HttpFoundation\Request; +use Thelia\Controller\Front\BaseFrontController; +use Thelia\Core\Event\Cart\CartEvent; +use Thelia\Core\Event\Delivery\DeliveryPostageEvent; +use Thelia\Core\Event\Order\OrderEvent; +use Thelia\Core\Event\TheliaEvents; +use Thelia\Form\CartAdd; +use Thelia\Form\Definition\FrontForm; +use Thelia\Form\Exception\FormValidationException; +use Thelia\Log\Tlog; +use Thelia\Model\AddressQuery; +use Thelia\Model\ConfigQuery; +use Thelia\Tools\URL; + +class CartController extends BaseFrontController +{ + public function addItem() + { + $request = $this->getRequest(); + + $cartAdd = $this->getAddCartForm($request); + $message = null; + + try { + $form = $this->validateForm($cartAdd); + + $cartEvent = $this->getCartEvent(); + + $cartEvent->bindForm($form); + + $this->getDispatcher()->dispatch(TheliaEvents::CART_ADDITEM, $cartEvent); + + $this->afterModifyCart(); + + if (! $this->changeViewForAjax()) { + if (null !== $response = $this->generateSuccessRedirect($cartAdd)) { + return $response; + } + } + } catch (PropelException $e) { + Tlog::getInstance()->error(sprintf("Failed to add item to cart with message : %s", $e->getMessage())); + $message = $this->getTranslator()->trans( + "Failed to add this article to your cart, please try again", + [], + Front::MESSAGE_DOMAIN + ); + } catch (FormValidationException $e) { + $message = $e->getMessage(); + } + + if ($message) { + $cartAdd->setErrorMessage($message); + $this->getParserContext()->addForm($cartAdd); + } + } + + public function changeItem() + { + $cartEvent = $this->getCartEvent(); + $cartEvent->setCartItemId($this->getRequest()->get("cart_item")); + $cartEvent->setQuantity($this->getRequest()->get("quantity")); + + try { + $this->getTokenProvider()->checkToken( + $this->getRequest()->query->get('_token') + ); + + $this->dispatch(TheliaEvents::CART_UPDATEITEM, $cartEvent); + + $this->afterModifyCart(); + + if (! $this->changeViewForAjax()) { + if (null !== $successUrl = $this->getRequest()->get("success_url")) { + return $this->generateRedirect(URL::getInstance()->absoluteUrl($successUrl)); + } + } + } catch (\Exception $e) { + Tlog::getInstance()->error(sprintf("Failed to change cart item quantity: %s", $e->getMessage())); + + $this->getParserContext()->setGeneralError($e->getMessage()); + } + } + + public function deleteItem() + { + $cartEvent = $this->getCartEvent(); + $cartEvent->setCartItemId($this->getRequest()->get("cart_item")); + + try { + $this->getTokenProvider()->checkToken( + $this->getRequest()->query->get('_token') + ); + + $this->getDispatcher()->dispatch(TheliaEvents::CART_DELETEITEM, $cartEvent); + + $this->afterModifyCart(); + } catch (\Exception $e) { + Tlog::getInstance()->error(sprintf("error during deleting cartItem with message : %s", $e->getMessage())); + $this->getParserContext()->setGeneralError($e->getMessage()); + } + + if (! $this->changeViewForAjax()) { + if (null !== $successUrl = $this->getRequest()->get("success_url")) { + return $this->generateRedirect(URL::getInstance()->absoluteUrl($successUrl)); + } + } + } + + protected function changeViewForAjax() + { + // If this is an ajax request, and if the template allow us to return an ajax result + if ($this->getRequest()->isXmlHttpRequest() && (0 === intval($this->getRequest()->get('no_ajax_check', 0)))) { + $request = $this->getRequest(); + + $view = $request->get('ajax-view', "includes/mini-cart"); + + $request->attributes->set('_view', $view); + + return true; + } + + return false; + } + + public function changeCountry() + { + $redirectUrl = URL::getInstance()->absoluteUrl("/cart"); + $deliveryId = $this->getRequest()->get("country"); + $cookieName = ConfigQuery::read('front_cart_country_cookie_name', 'fcccn'); + $cookieExpires = ConfigQuery::read('front_cart_country_cookie_expires', 2592000); + $cookieExpires = intval($cookieExpires) ?: 2592000; + + $cookie = new Cookie($cookieName, $deliveryId, time() + $cookieExpires, '/'); + + $response = $this->generateRedirect($redirectUrl); + $response->headers->setCookie($cookie); + + return $response; + } + + /** + * @return \Thelia\Core\Event\Cart\CartEvent + */ + protected function getCartEvent() + { + $cart = $this->getSession()->getSessionCart($this->getDispatcher()); + + return new CartEvent($cart); + } + + /** + * Find the good way to construct the cart form + * + * @param Request $request + * @return CartAdd + */ + private function getAddCartForm(Request $request) + { + /** @var CartAdd $cartAdd */ + if ($request->isMethod("post")) { + $cartAdd = $this->createForm(FrontForm::CART_ADD); + } else { + $cartAdd = $this->createForm( + FrontForm::CART_ADD, + "form", + array(), + array( + 'csrf_protection' => false, + ) + ); + } + + return $cartAdd; + } + + /** + * @throws PropelException + */ + protected function afterModifyCart() + { + /* recalculate postage amount */ + $order = $this->getSession()->getOrder(); + if (null !== $order) { + $deliveryModule = $order->getModuleRelatedByDeliveryModuleId(); + $deliveryAddress = AddressQuery::create()->findPk($order->getChoosenDeliveryAddress()); + + if (null !== $deliveryModule && null !== $deliveryAddress) { + $moduleInstance = $deliveryModule->getDeliveryModuleInstance($this->container); + + $orderEvent = new OrderEvent($order); + + try { + $deliveryPostageEvent = new DeliveryPostageEvent( + $moduleInstance, + $this->getSession()->getSessionCart($this->getDispatcher()), + $deliveryAddress + ); + + $this->getDispatcher()->dispatch( + TheliaEvents::MODULE_DELIVERY_GET_POSTAGE, + $deliveryPostageEvent + ); + + $postage = $deliveryPostageEvent->getPostage(); + + if (null !== $postage) { + $orderEvent->setPostage($postage->getAmount()); + $orderEvent->setPostageTax($postage->getAmountTax()); + $orderEvent->setPostageTaxRuleTitle($postage->getTaxRuleTitle()); + } + + $this->getDispatcher()->dispatch(TheliaEvents::ORDER_SET_POSTAGE, $orderEvent); + } catch (\Exception $ex) { + // The postage has been chosen, but changes in the cart causes an exception. + // Reset the postage data in the order + $orderEvent->setDeliveryModule(0); + + $this->getDispatcher()->dispatch(TheliaEvents::ORDER_SET_DELIVERY_MODULE, $orderEvent); + } + } + } + } +} diff --git a/local/modules/Front/Controller/ContactController.php b/local/modules/Front/Controller/ContactController.php new file mode 100644 index 00000000..99b08cc9 --- /dev/null +++ b/local/modules/Front/Controller/ContactController.php @@ -0,0 +1,90 @@ +. */ +/* */ +/*************************************************************************************/ + +namespace Front\Controller; + +use Thelia\Controller\Front\BaseFrontController; +use Thelia\Core\Event\Contact\ContactEvent; +use Thelia\Core\Event\TheliaEvents; +use Thelia\Form\Definition\FrontForm; +use Thelia\Form\Exception\FormValidationException; +use Thelia\Log\Tlog; +use Thelia\Model\ConfigQuery; + +/** + * Class ContactController + * @package Thelia\Controller\Front + * @author Manuel Raynaud + */ +class ContactController extends BaseFrontController +{ + /** + * send contact message + */ + public function sendAction() + { + $contactForm = $this->createForm(FrontForm::CONTACT); + + try { + $form = $this->validateForm($contactForm); + + $event = new ContactEvent($form); + + $this->dispatch(TheliaEvents::CONTACT_SUBMIT, $event); + + $this->getMailer()->sendSimpleEmailMessage( + [ ConfigQuery::getStoreEmail() => $event->getName() ], + [ ConfigQuery::getStoreEmail() => ConfigQuery::getStoreName() ], + $event->getSubject(), + '', + $event->getMessage(), + [], + [], + [ $event->getEmail() => $event->getName() ] + ); + + if ($contactForm->hasSuccessUrl()) { + return $this->generateSuccessRedirect($contactForm); + } + + return $this->generateRedirectFromRoute('contact.success'); + + } catch (FormValidationException $e) { + $error_message = $e->getMessage(); + } + + Tlog::getInstance()->error(sprintf('Error during sending contact mail : %s', $error_message)); + + $contactForm->setErrorMessage($error_message); + + $this->getParserContext() + ->addForm($contactForm) + ->setGeneralError($error_message) + ; + + // Redirect to error URL if defined + if ($contactForm->hasErrorUrl()) { + return $this->generateErrorRedirect($contactForm); + } + } +} diff --git a/local/modules/Front/Controller/CouponController.php b/local/modules/Front/Controller/CouponController.php new file mode 100644 index 00000000..d1687e49 --- /dev/null +++ b/local/modules/Front/Controller/CouponController.php @@ -0,0 +1,168 @@ +. */ +/* */ +/*************************************************************************************/ +namespace Front\Controller; + +use Front\Front; +use Propel\Runtime\Exception\PropelException; +use Thelia\Controller\Front\BaseFrontController; +use Thelia\Core\Event\Coupon\CouponConsumeEvent; +use Thelia\Core\Event\Delivery\DeliveryPostageEvent; +use Thelia\Core\Event\Order\OrderEvent; +use Thelia\Core\Event\TheliaEvents; +use Thelia\Exception\UnmatchableConditionException; +use Thelia\Form\Definition\FrontForm; +use Thelia\Form\Exception\FormValidationException; +use Thelia\Log\Tlog; +use Thelia\Model\AddressQuery; +use Thelia\Model\OrderPostage; +use Thelia\Module\Exception\DeliveryException; + +/** + * Class CouponController + * @package Thelia\Controller\Front + * @author Guillaume MOREL + */ +class CouponController extends BaseFrontController +{ + /** + * Clear all coupons. + */ + public function clearAllCouponsAction() + { + // Dispatch Event to the Action + $this->getDispatcher()->dispatch(TheliaEvents::COUPON_CLEAR_ALL); + } + + /** + * Coupon consuming + */ + public function consumeAction() + { + $this->checkCartNotEmpty(); + + $message = false; + $couponCodeForm = $this->createForm(FrontForm::COUPON_CONSUME); + + try { + $form = $this->validateForm($couponCodeForm, 'post'); + + $couponCode = $form->get('coupon-code')->getData(); + + if (null === $couponCode || empty($couponCode)) { + $message = true; + throw new \Exception( + $this->getTranslator()->trans( + 'Coupon code can\'t be empty', + [], + Front::MESSAGE_DOMAIN + ) + ); + } + + $couponConsumeEvent = new CouponConsumeEvent($couponCode); + + // Dispatch Event to the Action + $this->getDispatcher()->dispatch(TheliaEvents::COUPON_CONSUME, $couponConsumeEvent); + + /* recalculate postage amount */ + $order = $this->getSession()->getOrder(); + + if (null !== $order) { + $deliveryModule = $order->getModuleRelatedByDeliveryModuleId(); + $deliveryAddress = AddressQuery::create()->findPk($order->getChoosenDeliveryAddress()); + + if (null !== $deliveryModule && null !== $deliveryAddress) { + $moduleInstance = $deliveryModule->getDeliveryModuleInstance($this->container); + + $orderEvent = new OrderEvent($order); + + try { + $deliveryPostageEvent = new DeliveryPostageEvent( + $moduleInstance, + $this->getSession()->getSessionCart($this->getDispatcher()), + $deliveryAddress + ); + + $this->getDispatcher()->dispatch( + TheliaEvents::MODULE_DELIVERY_GET_POSTAGE, + $deliveryPostageEvent + ); + + $postage = $deliveryPostageEvent->getPostage(); + + $orderEvent->setPostage($postage->getAmount()); + $orderEvent->setPostageTax($postage->getAmountTax()); + $orderEvent->setPostageTaxRuleTitle($postage->getTaxRuleTitle()); + + $this->getDispatcher()->dispatch(TheliaEvents::ORDER_SET_POSTAGE, $orderEvent); + } catch (\Exception $ex) { + // The postage has been chosen, but changes dues to coupon causes an exception. + // Reset the postage data in the order + $orderEvent->setDeliveryModule(0); + + $this->getDispatcher()->dispatch(TheliaEvents::ORDER_SET_DELIVERY_MODULE, $orderEvent); + } + } + } + + return $this->generateSuccessRedirect($couponCodeForm); + } catch (FormValidationException $e) { + $message = $this->getTranslator()->trans( + 'Please check your coupon code: %message', + ["%message" => $e->getMessage()], + Front::MESSAGE_DOMAIN + ); + } catch (UnmatchableConditionException $e) { + $message = $this->getTranslator()->trans( + 'You should sign in or register to use this coupon', + [ + '%sign' => $this->retrieveUrlFromRouteId('customer.login.view'), + '%register' => $this->retrieveUrlFromRouteId('customer.create.view'), + ], + Front::MESSAGE_DOMAIN + ); + } catch (PropelException $e) { + $this->getParserContext()->setGeneralError($e->getMessage()); + } catch (\Exception $e) { + $message = $this->getTranslator()->trans( + 'Sorry, an error occurred: %message', + ["%message" => $e->getMessage()], + Front::MESSAGE_DOMAIN + ); + } + + if ($message !== false) { + Tlog::getInstance()->error( + sprintf("Error during order delivery process : %s. Exception was %s", $message, $e->getMessage()) + ); + + $couponCodeForm->setErrorMessage($message); + + $this->getParserContext() + ->addForm($couponCodeForm) + ->setGeneralError($message); + } + + return $this->generateErrorRedirect($couponCodeForm); + } +} diff --git a/local/modules/Front/Controller/CustomerController.php b/local/modules/Front/Controller/CustomerController.php new file mode 100644 index 00000000..aef30ad2 --- /dev/null +++ b/local/modules/Front/Controller/CustomerController.php @@ -0,0 +1,613 @@ +. */ +/* */ +/*************************************************************************************/ +namespace Front\Controller; + +use Front\Front; +use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; +use Thelia\Controller\Front\BaseFrontController; +use Thelia\Core\Event\Customer\CustomerCreateOrUpdateEvent; +use Thelia\Core\Event\Customer\CustomerEvent; +use Thelia\Core\Event\Customer\CustomerLoginEvent; +use Thelia\Core\Event\LostPasswordEvent; +use Thelia\Core\Event\Newsletter\NewsletterEvent; +use Thelia\Core\Event\TheliaEvents; +use Thelia\Core\Security\Authentication\CustomerUsernamePasswordFormAuthenticator; +use Thelia\Core\Security\Exception\AuthenticationException; +use Thelia\Core\Security\Exception\CustomerNotConfirmedException; +use Thelia\Core\Security\Exception\UsernameNotFoundException; +use Thelia\Core\Security\Exception\WrongPasswordException; +use Thelia\Form\CustomerLogin; +use Thelia\Form\Definition\FrontForm; +use Thelia\Form\Exception\FormValidationException; +use Thelia\Log\Tlog; +use Thelia\Model\ConfigQuery; +use Thelia\Model\Customer; +use Thelia\Model\CustomerQuery; +use Thelia\Model\Newsletter; +use Thelia\Model\NewsletterQuery; +use Thelia\Tools\RememberMeTrait; +use Thelia\Tools\URL; + +/** + * Class CustomerController + * @package Thelia\Controller\Front + * @author Manuel Raynaud + */ +class CustomerController extends BaseFrontController +{ + use RememberMeTrait; + + /** + * Display the register template if no customer logged + */ + public function viewLoginAction() + { + if ($this->getSecurityContext()->hasCustomerUser()) { + // Redirect to home page + return $this->generateRedirect(URL::getInstance()->getIndexPage()); + } + + return $this->render("login"); + } + + /** + * Display the register template if no customer logged + */ + public function viewRegisterAction() + { + if ($this->getSecurityContext()->hasCustomerUser()) { + // Redirect to home page + return $this->generateRedirect(URL::getInstance()->getIndexPage()); + } + + return $this->render("register"); + } + + public function newPasswordAction() + { + $passwordLost = $this->createForm(FrontForm::CUSTOMER_LOST_PASSWORD); + + if (! $this->getSecurityContext()->hasCustomerUser()) { + try { + $form = $this->validateForm($passwordLost); + + $event = new LostPasswordEvent($form->get("email")->getData()); + + $this->dispatch(TheliaEvents::LOST_PASSWORD, $event); + + return $this->generateSuccessRedirect($passwordLost); + + } catch (FormValidationException $e) { + $message = $this->getTranslator()->trans( + "Please check your input: %s", + [ + '%s' => $e->getMessage() + ], + Front::MESSAGE_DOMAIN + ); + } catch (\Exception $e) { + $message = $this->getTranslator()->trans( + "Sorry, an error occurred: %s", + [ + '%s' => $e->getMessage() + ], + Front::MESSAGE_DOMAIN + ); + } + + if ($message !== false) { + Tlog::getInstance()->error( + sprintf( + "Error during customer creation process : %s. Exception was %s", + $message, + $e->getMessage() + ) + ); + } + } else { + $message = $this->getTranslator()->trans( + "You're currently logged in. Please log out before requesting a new password.", + [], + Front::MESSAGE_DOMAIN + ); + } + + $passwordLost->setErrorMessage($message); + + $this->getParserContext() + ->addForm($passwordLost) + ->setGeneralError($message) + ; + + // Redirect to error URL if defined + if ($passwordLost->hasErrorUrl()) { + return $this->generateErrorRedirect($passwordLost); + } + } + + public function newPasswordSentAction() + { + $this->getParser()->assign('password_sent', true); + } + + /** + * Create a new customer. + * On success, redirect to success_url if exists, otherwise, display the same view again. + */ + public function createAction() + { + if (! $this->getSecurityContext()->hasCustomerUser()) { + $customerCreation = $this->createForm(FrontForm::CUSTOMER_CREATE); + + try { + $form = $this->validateForm($customerCreation, "post"); + + $customerCreateEvent = $this->createEventInstance($form->getData()); + + $this->dispatch(TheliaEvents::CUSTOMER_CREATEACCOUNT, $customerCreateEvent); + + $newCustomer = $customerCreateEvent->getCustomer(); + + // Newsletter + if (true === $form->get('newsletter')->getData()) { + $newsletterEmail = $newCustomer->getEmail(); + $nlEvent = new NewsletterEvent( + $newsletterEmail, + $this->getRequest()->getSession()->getLang()->getLocale() + ); + $nlEvent->setFirstname($newCustomer->getFirstname()); + $nlEvent->setLastname($newCustomer->getLastname()); + + // Security : Check if this new Email address already exist + if (null !== $newsletter = NewsletterQuery::create()->findOneByEmail($newsletterEmail)) { + $nlEvent->setId($newsletter->getId()); + $this->dispatch(TheliaEvents::NEWSLETTER_UPDATE, $nlEvent); + } else { + $this->dispatch(TheliaEvents::NEWSLETTER_SUBSCRIBE, $nlEvent); + } + } + + if (ConfigQuery::isCustomerEmailConfirmationEnable() && ! $newCustomer->getEnable()) { + $response = $this->generateRedirectFromRoute('customer.login.view'); + } else { + $this->processLogin($customerCreateEvent->getCustomer()); + + $cart = $this->getSession()->getSessionCart($this->getDispatcher()); + if ($cart->getCartItems()->count() > 0) { + $response = $this->generateRedirectFromRoute('cart.view'); + } else { + $response = $this->generateSuccessRedirect($customerCreation); + } + } + + return $response; + } catch (FormValidationException $e) { + $message = $this->getTranslator()->trans( + "Please check your input: %s", + [ + '%s' => $e->getMessage() + ], + Front::MESSAGE_DOMAIN + ); + } catch (\Exception $e) { + $message = $this->getTranslator()->trans( + "Sorry, an error occured: %s", + [ + '%s' => $e->getMessage() + ], + Front::MESSAGE_DOMAIN + ); + } + + Tlog::getInstance()->error( + sprintf( + "Error during customer creation process : %s. Exception was %s", + $message, + $e->getMessage() + ) + ); + + $customerCreation->setErrorMessage($message); + + $this->getParserContext() + ->addForm($customerCreation) + ->setGeneralError($message) + ; + + // Redirect to error URL if defined + if ($customerCreation->hasErrorUrl()) { + return $this->generateErrorRedirect($customerCreation); + } + } + } + + /** + * Prepare customer data update. + */ + public function viewAction() + { + $this->checkAuth(); + + /** @var Customer $customer */ + $customer = $this->getSecurityContext()->getCustomerUser(); + $newsletter = NewsletterQuery::create()->findOneByEmail($customer->getEmail()); + $data = array( + 'id' => $customer->getId(), + 'title' => $customer->getTitleId(), + 'firstname' => $customer->getFirstName(), + 'lastname' => $customer->getLastName(), + 'email' => $customer->getEmail(), + 'email_confirm' => $customer->getEmail(), + 'lang_id' => $customer->getLangId(), + 'newsletter' => $newsletter instanceof Newsletter ? !$newsletter->getUnsubscribed() : false, + ); + + $customerProfileUpdateForm = $this->createForm(FrontForm::CUSTOMER_PROFILE_UPDATE, 'form', $data); + + // Pass it to the parser + $this->getParserContext()->addForm($customerProfileUpdateForm); + } + + public function updatePasswordAction() + { + if ($this->getSecurityContext()->hasCustomerUser()) { + $customerPasswordUpdateForm = $this->createForm(FrontForm::CUSTOMER_PASSWORD_UPDATE); + + try { + /** @var Customer $customer */ + $customer = $this->getSecurityContext()->getCustomerUser(); + + $form = $this->validateForm($customerPasswordUpdateForm, "post"); + + $customerChangeEvent = $this->createEventInstance($form->getData()); + $customerChangeEvent->setCustomer($customer); + $this->dispatch(TheliaEvents::CUSTOMER_UPDATEPROFILE, $customerChangeEvent); + + return $this->generateSuccessRedirect($customerPasswordUpdateForm); + + } catch (FormValidationException $e) { + $message = $this->getTranslator()->trans( + "Please check your input: %s", + [ + '%s' => $e->getMessage() + ], + Front::MESSAGE_DOMAIN + ); + } catch (\Exception $e) { + $message = $this->getTranslator()->trans( + "Sorry, an error occured: %s", + [ + '%s' => $e->getMessage() + ], + Front::MESSAGE_DOMAIN + ); + } + + Tlog::getInstance()->error( + sprintf( + "Error during customer password modification process : %s.", + $message + ) + ); + + $customerPasswordUpdateForm->setErrorMessage($message); + + $this->getParserContext() + ->addForm($customerPasswordUpdateForm) + ->setGeneralError($message) + ; + + // Redirect to error URL if defined + if ($customerPasswordUpdateForm->hasErrorUrl()) { + return $this->generateErrorRedirect($customerPasswordUpdateForm); + } + } + } + + public function updateAction() + { + if ($this->getSecurityContext()->hasCustomerUser()) { + $customerProfileUpdateForm = $this->createForm(FrontForm::CUSTOMER_PROFILE_UPDATE); + + try { + /** @var Customer $customer */ + $customer = $this->getSecurityContext()->getCustomerUser(); + $newsletterOldEmail = $customer->getEmail(); + + $form = $this->validateForm($customerProfileUpdateForm, "post"); + + $customerChangeEvent = $this->createEventInstance($form->getData()); + $customerChangeEvent->setCustomer($customer); + + $customerChangeEvent->setEmailUpdateAllowed( + (intval(ConfigQuery::read('customer_change_email', 0))) ? true : false + ); + + $this->dispatch(TheliaEvents::CUSTOMER_UPDATEPROFILE, $customerChangeEvent); + + $updatedCustomer = $customerChangeEvent->getCustomer(); + + // Newsletter + if (true === $form->get('newsletter')->getData()) { + $nlEvent = new NewsletterEvent( + $updatedCustomer->getEmail(), + $this->getRequest()->getSession()->getLang()->getLocale() + ); + $nlEvent->setFirstname($updatedCustomer->getFirstname()); + $nlEvent->setLastname($updatedCustomer->getLastname()); + + if (null !== $newsletter = NewsletterQuery::create()->findOneByEmail($newsletterOldEmail)) { + $nlEvent->setId($newsletter->getId()); + $this->dispatch(TheliaEvents::NEWSLETTER_UPDATE, $nlEvent); + } else { + $this->dispatch(TheliaEvents::NEWSLETTER_SUBSCRIBE, $nlEvent); + } + } else { + if (null !== $newsletter = NewsletterQuery::create()->findOneByEmail($newsletterOldEmail)) { + $nlEvent = new NewsletterEvent( + $updatedCustomer->getEmail(), + $this->getRequest()->getSession()->getLang()->getLocale() + ); + $nlEvent->setId($newsletter->getId()); + $this->dispatch(TheliaEvents::NEWSLETTER_UNSUBSCRIBE, $nlEvent); + } + } + + $this->processLogin($updatedCustomer); + + return $this->generateSuccessRedirect($customerProfileUpdateForm); + + } catch (FormValidationException $e) { + $message = $this->getTranslator()->trans( + "Please check your input: %s", + [ + '%s' => $e->getMessage() + ], + Front::MESSAGE_DOMAIN + ); + } catch (\Exception $e) { + $message = $this->getTranslator()->trans( + "Sorry, an error occured: %s", + [ + '%s' => $e->getMessage() + ], + Front::MESSAGE_DOMAIN + ); + } + + Tlog::getInstance()->error(sprintf("Error during customer modification process : %s.", $message)); + + $customerProfileUpdateForm->setErrorMessage($message); + + $this->getParserContext() + ->addForm($customerProfileUpdateForm) + ->setGeneralError($message) + ; + + // Redirect to error URL if defined + if ($customerProfileUpdateForm->hasErrorUrl()) { + return $this->generateErrorRedirect($customerProfileUpdateForm); + } + } + } + + /** + * Perform user login. On a successful login, the user is redirected to the URL + * found in the success_url form parameter, or / if none was found. + * + * If login is not successfull, the same view is displayed again. + * + */ + public function loginAction() + { + if (!$this->getSecurityContext()->hasCustomerUser()) { + $request = $this->getRequest(); + $customerLoginForm = new CustomerLogin($request); + + try { + $form = $this->validateForm($customerLoginForm, "post"); + + // If User is a new customer + if ($form->get('account')->getData() == 0 && $form->get("email")->getErrors()->count() == 0) { + return $this->generateRedirectFromRoute( + "customer.create.process", + ["email" => $form->get("email")->getData()] + ); + } else { + try { + $authenticator = new CustomerUsernamePasswordFormAuthenticator($request, $customerLoginForm); + + /** @var Customer $customer */ + $customer = $authenticator->getAuthentifiedUser(); + + $this->processLogin($customer); + + if (intval($form->get('remember_me')->getData()) > 0) { + // If a remember me field if present and set in the form, create + // the cookie thant store "remember me" information + $this->createRememberMeCookie( + $customer, + $this->getRememberMeCookieName(), + $this->getRememberMeCookieExpiration() + ); + } + + return $this->generateSuccessRedirect($customerLoginForm); + + } catch (UsernameNotFoundException $e) { + $message = $this->getTranslator()->trans( + "Wrong email or password. Please try again", + [], + Front::MESSAGE_DOMAIN + ); + } catch (WrongPasswordException $e) { + $message = $this->getTranslator()->trans( + "Wrong email or password. Please try again", + [], + Front::MESSAGE_DOMAIN + ); + } catch (CustomerNotConfirmedException $e) { + if ($e->getUser() !== null) { + // Send the confirmation email again + $this->getDispatcher()->dispatch( + TheliaEvents::SEND_ACCOUNT_CONFIRMATION_EMAIL, + new CustomerEvent($e->getUser()) + ); + } + $message = $this->getTranslator()->trans( + "Your account is not yet confirmed. A confirmation email has been sent to your email address, please check your mailbox", + [], + Front::MESSAGE_DOMAIN + ); + } catch (AuthenticationException $e) { + $message = $this->getTranslator()->trans( + "Wrong email or password. Please try again", + [], + Front::MESSAGE_DOMAIN + ); + } + + } + } catch (FormValidationException $e) { + $message = $this->getTranslator()->trans( + "Please check your input: %s", + ['%s' => $e->getMessage()], + Front::MESSAGE_DOMAIN + ); + } catch (\Exception $e) { + $message = $this->getTranslator()->trans( + "Sorry, an error occured: %s", + ['%s' => $e->getMessage()], + Front::MESSAGE_DOMAIN + ); + } + + Tlog::getInstance()->error( + sprintf( + "Error during customer login process : %s. Exception was %s", + $message, + $e->getMessage() + ) + ); + + $customerLoginForm->setErrorMessage($message); + + $this->getParserContext()->addForm($customerLoginForm); + + if ($customerLoginForm->hasErrorUrl()) { + return $this->generateErrorRedirect($customerLoginForm); + } + } + } + + /** + * Perform customer logout. + */ + public function logoutAction() + { + if ($this->getSecurityContext()->hasCustomerUser()) { + $this->dispatch(TheliaEvents::CUSTOMER_LOGOUT); + } + + $this->clearRememberMeCookie($this->getRememberMeCookieName()); + + // Redirect to home page + return $this->generateRedirect(URL::getInstance()->getIndexPage()); + } + + /** + * @param $token + * @return \Symfony\Component\HttpFoundation\Response + * @throws \Exception + * @throws \Propel\Runtime\Exception\PropelException + */ + public function confirmCustomerAction($token) + { + /** @var Customer $customer */ + if (null === $customer = CustomerQuery::create()->findOneByConfirmationToken($token)) { + throw new NotFoundHttpException(); + } + + $customer + ->setEnable(true) + ->save() + ; + + // Clear form error context + + return $this->generateRedirectFromRoute('customer.login.view', [ 'validation_done' => 1 ]); + } + + /** + * Dispatch event for customer login action + * + * @param Customer $customer + */ + protected function processLogin(Customer $customer) + { + $this->dispatch(TheliaEvents::CUSTOMER_LOGIN, new CustomerLoginEvent($customer)); + } + + /** + * @param $data + * @return \Thelia\Core\Event\Customer\CustomerCreateOrUpdateEvent + */ + private function createEventInstance($data) + { + $customerCreateEvent = new CustomerCreateOrUpdateEvent( + isset($data["title"])?$data["title"]:null, + isset($data["firstname"])?$data["firstname"]:null, + isset($data["lastname"])?$data["lastname"]:null, + isset($data["address1"])?$data["address1"]:null, + isset($data["address2"])?$data["address2"]:null, + isset($data["address3"])?$data["address3"]:null, + isset($data["phone"])?$data["phone"]:null, + isset($data["cellphone"])?$data["cellphone"]:null, + isset($data["zipcode"])?$data["zipcode"]:null, + isset($data["city"])?$data["city"]:null, + isset($data["country"])?$data["country"]:null, + isset($data["email"])?$data["email"]:null, + isset($data["password"]) ? $data["password"]:null, + isset($data["lang_id"]) ? $data["lang_id"]:$this->getSession()->getLang()->getId(), + isset($data["reseller"])?$data["reseller"]:null, + isset($data["sponsor"])?$data["sponsor"]:null, + isset($data["discount"])?$data["discount"]:null, + isset($data["company"])?$data["company"]:null, + null, + isset($data["state"])?$data["state"]:null + ); + + return $customerCreateEvent; + } + + + protected function getRememberMeCookieName() + { + return ConfigQuery::read('customer_remember_me_cookie_name', 'crmcn'); + } + + protected function getRememberMeCookieExpiration() + { + return ConfigQuery::read('customer_remember_me_cookie_expiration', 2592000 /* 1 month */); + } +} diff --git a/local/modules/Front/Controller/FeedController.php b/local/modules/Front/Controller/FeedController.php new file mode 100644 index 00000000..5c3f03b6 --- /dev/null +++ b/local/modules/Front/Controller/FeedController.php @@ -0,0 +1,202 @@ + + */ +class FeedController extends BaseFrontController { + + + /** + * Folder name for feeds cache + */ + const FEED_CACHE_DIR = "feeds"; + + /** + * Key prefix for feed cache + */ + const FEED_CACHE_KEY = "feed"; + + + /** + * render the RSS feed + * + * @param $context string The context of the feed : catalog, content. default: catalog + * @param $lang string The lang of the feed : fr_FR, en_US, ... default: default language of the site + * @param $id string The id of the parent element. The id of the main parent category for catalog context. + * The id of the content folder for content context + * @return Response + * @throws \RuntimeException + */ + public function generateAction($context, $lang, $id) + { + + /** @var Request $request */ + $request = $this->getRequest(); + + // context + if ("" === $context){ + $context = "catalog"; + } else if (! in_array($context, array("catalog", "content", "brand")) ){ + $this->pageNotFound(); + } + + // the locale : fr_FR, en_US, + if ("" !== $lang) { + if (! $this->checkLang($lang)){ + $this->pageNotFound(); + } + } else { + try{ + $lang = Lang::getDefaultLanguage(); + $lang = $lang->getLocale(); + } catch (\RuntimeException $ex){ + // @todo generate error page + throw new \RuntimeException("No default language is defined. Please define one."); + } + } + if (null === $lang = LangQuery::create()->findOneByLocale($lang)){ + $this->pageNotFound(); + } + $lang = $lang->getId(); + + // check if element exists and is visible + if ("" !== $id){ + if (false === $this->checkId($context, $id)){ + $this->pageNotFound(); + } + } + + $flush = $request->query->get("flush", ""); + + // check if feed already in cache + $cacheContent = false; + + $cacheDir = $this->getCacheDir(); + $cacheKey = self::FEED_CACHE_KEY . $lang . $context . $id; + $cacheExpire = intval(ConfigQuery::read("feed_ttl", '7200')) ?: 7200; + + $cacheDriver = new FilesystemCache($cacheDir); + if (!($this->checkAdmin() && "" !== $flush)){ + $cacheContent = $cacheDriver->fetch($cacheKey); + } else { + $cacheDriver->delete($cacheKey); + } + + // if not in cache + if (false === $cacheContent){ + // render the view + $cacheContent = $this->renderRaw( + "feed", + array( + "_context_" => $context, + "_lang_" => $lang, + "_id_" => $id + ) + ); + // save cache + $cacheDriver->save($cacheKey, $cacheContent, $cacheExpire); + } + + $response = new Response(); + $response->setContent($cacheContent); + $response->headers->set('Content-Type', 'application/rss+xml'); + + return $response; + } + + + /** + * get the cache directory for feeds + * + * @return mixed|string + */ + protected function getCacheDir() + { + $cacheDir = $this->container->getParameter("kernel.cache_dir"); + $cacheDir = rtrim($cacheDir, '/'); + $cacheDir .= '/' . self::FEED_CACHE_DIR . '/'; + + return $cacheDir; + } + + /** + * Check if current user has ADMIN role + * + * @return bool + */ + protected function checkAdmin(){ + return $this->getSecurityContext()->hasAdminUser(); + } + + + /** + * Check if a lang is used + * + * @param $lang string The lang code. e.g.: fr + * @return bool true if the language is used, otherwise false + */ + private function checkLang($lang) + { + // load locals + $lang = LangQuery::create() + ->findOneByLocale($lang); + + return (null !== $lang); + } + + + /** + * Check if the element exists and is visible + * + * @param $context string catalog or content + * @param $id string id of the element + * @return bool + */ + private function checkId($context, $id) + { + $ret = false; + if (is_numeric($id)){ + if ("catalog" === $context){ + $cat = CategoryQuery::create()->findPk($id); + $ret = (null !== $cat && $cat->getVisible()); + } elseif ("brand" === $context) { + $brand = BrandQuery::create()->findPk($id); + $ret = (null !== $brand && $brand->getVisible()); + } else { + $folder = FolderQuery::create()->findPk($id); + $ret = (null !== $folder && $folder->getVisible()); + } + } + return $ret; + } +} \ No newline at end of file diff --git a/local/modules/Front/Controller/NewsletterController.php b/local/modules/Front/Controller/NewsletterController.php new file mode 100644 index 00000000..9e558141 --- /dev/null +++ b/local/modules/Front/Controller/NewsletterController.php @@ -0,0 +1,164 @@ +. */ +/* */ +/*************************************************************************************/ + +namespace Front\Controller; + +use Front\Front; +use Symfony\Component\HttpFoundation\JsonResponse; +use Thelia\Controller\Front\BaseFrontController; +use Thelia\Core\Event\Newsletter\NewsletterEvent; +use Thelia\Core\Event\TheliaEvents; +use Thelia\Form\Definition\FrontForm; +use Thelia\Log\Tlog; +use Thelia\Model\Customer; +use Thelia\Model\NewsletterQuery; + +/** + * Class NewsletterController + * @package Thelia\Controller\Front + * @author Manuel Raynaud , Franck Allimant + */ +class NewsletterController extends BaseFrontController +{ + /** + * @since 2.3.0-alpha2 + */ + public function unsubscribeAction() + { + $errorMessage = false; + + $newsletterForm = $this->createForm(FrontForm::NEWSLETTER_UNSUBSCRIBE); + + try { + $form = $this->validateForm($newsletterForm); + + $email = $form->get('email')->getData(); + + if (null !== $newsletter = NewsletterQuery::create()->findOneByEmail($email)) { + $event = new NewsletterEvent( + $email, + $this->getRequest()->getSession()->getLang()->getLocale() + ); + + $event->setId($newsletter->getId()); + + $this->dispatch(TheliaEvents::NEWSLETTER_UNSUBSCRIBE, $event); + + // If a success URL is defined in the form, redirect to it, otherwise use the defaut view + if ($newsletterForm->hasSuccessUrl() && !$this->getRequest()->isXmlHttpRequest()) { + return $this->generateSuccessRedirect($newsletterForm); + } + } + } catch (\Exception $e) { + $errorMessage = $e->getMessage(); + + Tlog::getInstance()->error(sprintf('Error during newsletter unsubscription : %s', $errorMessage)); + + $newsletterForm->setErrorMessage($errorMessage); + } + + // If Ajax Request + if ($this->getRequest()->isXmlHttpRequest()) { + return new JsonResponse([ + "success" => ($errorMessage) ? false : true, + "message" => ($errorMessage) ? $errorMessage : $this->getTranslator()->trans( + "Your subscription to our newsletter has been canceled.", + [], + Front::MESSAGE_DOMAIN + ) + ], ($errorMessage) ? 500 : 200); + } + + $this->getParserContext() + ->setGeneralError($errorMessage) + ->addForm($newsletterForm); + + // If an error URL is defined in the form, redirect to it, otherwise use the defaut view + if ($errorMessage && $newsletterForm->hasErrorUrl()) { + return $this->generateErrorRedirect($newsletterForm); + } + } + + public function subscribeAction() + { + $errorMessage = false; + + $newsletterForm = $this->createForm(FrontForm::NEWSLETTER); + + try { + $form = $this->validateForm($newsletterForm); + + $event = new NewsletterEvent( + $form->get('email')->getData(), + $this->getRequest()->getSession()->getLang()->getLocale() + ); + + /** @var Customer $customer */ + if (null !== $customer = $this->getSecurityContext()->getCustomerUser()) { + $event + ->setFirstname($customer->getFirstname()) + ->setLastname($customer->getLastname()) + ; + } else { + $event + ->setFirstname($form->get('firstname')->getData()) + ->setLastname($form->get('lastname')->getData()) + ; + } + + $this->dispatch(TheliaEvents::NEWSLETTER_SUBSCRIBE, $event); + + // If a success URL is defined in the form, redirect to it, otherwise use the defaut view + if ($newsletterForm->hasSuccessUrl() && ! $this->getRequest()->isXmlHttpRequest()) { + return $this->generateSuccessRedirect($newsletterForm); + } + } catch (\Exception $e) { + $errorMessage = $e->getMessage(); + + Tlog::getInstance()->error(sprintf('Error during newsletter subscription : %s', $errorMessage)); + + $newsletterForm->setErrorMessage($errorMessage); + } + + // If Ajax Request + if ($this->getRequest()->isXmlHttpRequest()) { + return new JsonResponse([ + "success" => ($errorMessage) ? false : true, + "message" => ($errorMessage) ? $errorMessage : $this->getTranslator()->trans( + "Thanks for signing up! We'll keep you posted whenever we have any new updates.", + [], + Front::MESSAGE_DOMAIN + ) + ], ($errorMessage) ? 500 : 200); + } + + $this->getParserContext() + ->setGeneralError($errorMessage) + ->addForm($newsletterForm); + + // If an error URL is defined in the form, redirect to it, otherwise use the defaut view + if ($errorMessage && $newsletterForm->hasErrorUrl()) { + return $this->generateErrorRedirect($newsletterForm); + } + } +} diff --git a/local/modules/Front/Controller/OrderController.php b/local/modules/Front/Controller/OrderController.php new file mode 100644 index 00000000..6b9ebd88 --- /dev/null +++ b/local/modules/Front/Controller/OrderController.php @@ -0,0 +1,605 @@ +. */ +/* */ +/*************************************************************************************/ +namespace Front\Controller; + +use Front\Front; +use Propel\Runtime\ActiveQuery\Criteria; +use Propel\Runtime\Exception\PropelException; +use Symfony\Component\HttpFoundation\Response as BaseResponse; +use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException; +use Thelia\Controller\Front\BaseFrontController; +use Thelia\Core\Event\Delivery\DeliveryPostageEvent; +use Thelia\Core\Event\Order\OrderEvent; +use Thelia\Core\Event\Product\VirtualProductOrderDownloadResponseEvent; +use Thelia\Core\Event\TheliaEvents; +use Thelia\Core\HttpFoundation\Request; +use Thelia\Exception\TheliaProcessException; +use Thelia\Form\Definition\FrontForm; +use Thelia\Form\Exception\FormValidationException; +use Thelia\Log\Tlog; +use Thelia\Model\Address; +use Thelia\Model\AddressQuery; +use Thelia\Model\AreaDeliveryModuleQuery; +use Thelia\Model\ConfigQuery; +use Thelia\Model\ModuleQuery; +use Thelia\Model\Order; +use Thelia\Model\OrderProductQuery; +use Thelia\Model\OrderQuery; +use Thelia\Module\AbstractDeliveryModule; +use Thelia\Module\Exception\DeliveryException; + +/** + * Class OrderController + * @package Thelia\Controller\Front + * @author Etienne Roudeix + */ +class OrderController extends BaseFrontController +{ + /** + * Check if the cart contains only virtual products. + */ + public function deliverView() + { + $this->checkAuth(); + $this->checkCartNotEmpty(); + + // check if the cart contains only virtual products + $cart = $this->getSession()->getSessionCart($this->getDispatcher()); + + $deliveryAddress = $this->getCustomerAddress(); + + if ($cart->isVirtual()) { + if (null !== $deliveryAddress) { + $deliveryModule = ModuleQuery::create()->retrieveVirtualProductDelivery($this->container); + + if (false === $deliveryModule) { + Tlog::getInstance()->error( + $this->getTranslator()->trans( + "To enable the virtual product feature, the VirtualProductDelivery module should be activated", + [], + Front::MESSAGE_DOMAIN + ) + ); + } elseif (count($deliveryModule) == 1) { + return $this->registerVirtualProductDelivery($deliveryModule[0], $deliveryAddress); + } + } + } + + return $this->render( + 'order-delivery', + [ + 'delivery_address_id' => (null !== $deliveryAddress) ? $deliveryAddress->getId() : null + ] + ); + } + + /** + * @param AbstractDeliveryModule $moduleInstance + * @param Address $deliveryAddress + * @return \Symfony\Component\HttpFoundation\Response + */ + private function registerVirtualProductDelivery($moduleInstance, $deliveryAddress) + { + /* get postage amount */ + $deliveryModule = $moduleInstance->getModuleModel(); + $cart = $this->getSession()->getSessionCart($this->getDispatcher()); + $deliveryPostageEvent = new DeliveryPostageEvent($moduleInstance, $cart, $deliveryAddress); + + $this->getDispatcher()->dispatch( + TheliaEvents::MODULE_DELIVERY_GET_POSTAGE, + $deliveryPostageEvent + ); + + $postage = $deliveryPostageEvent->getPostage(); + + $orderEvent = $this->getOrderEvent(); + $orderEvent->setDeliveryAddress($deliveryAddress->getId()); + $orderEvent->setDeliveryModule($deliveryModule->getId()); + $orderEvent->setPostage($postage->getAmount()); + $orderEvent->setPostageTax($postage->getAmountTax()); + $orderEvent->setPostageTaxRuleTitle($postage->getTaxRuleTitle()); + + $this->getDispatcher()->dispatch(TheliaEvents::ORDER_SET_DELIVERY_ADDRESS, $orderEvent); + $this->getDispatcher()->dispatch(TheliaEvents::ORDER_SET_DELIVERY_MODULE, $orderEvent); + $this->getDispatcher()->dispatch(TheliaEvents::ORDER_SET_POSTAGE, $orderEvent); + + return $this->generateRedirectFromRoute("order.invoice"); + } + + /** + * set delivery address + * set delivery module + */ + public function deliver() + { + $this->checkAuth(); + $this->checkCartNotEmpty(); + + $message = false; + + $orderDelivery = $this->createForm(FrontForm::ORDER_DELIVER); + + try { + $form = $this->validateForm($orderDelivery, "post"); + + $deliveryAddressId = $form->get("delivery-address")->getData(); + $deliveryModuleId = $form->get("delivery-module")->getData(); + $deliveryAddress = AddressQuery::create()->findPk($deliveryAddressId); + $deliveryModule = ModuleQuery::create()->findPk($deliveryModuleId); + + /* check that the delivery address belongs to the current customer */ + if ($deliveryAddress->getCustomerId() !== $this->getSecurityContext()->getCustomerUser()->getId()) { + throw new \Exception( + $this->getTranslator()->trans( + "Delivery address does not belong to the current customer", + [], + Front::MESSAGE_DOMAIN + ) + ); + } + + /* check that the delivery module fetches the delivery address area */ + if (null === AreaDeliveryModuleQuery::create()->findByCountryAndModule( + $deliveryAddress->getCountry(), + $deliveryModule, + $deliveryAddress->getState() + )) { + throw new \Exception( + $this->getTranslator()->trans( + "Delivery module cannot be use with selected delivery address", + [], + Front::MESSAGE_DOMAIN + ) + ); + } + + /* get postage amount */ + $moduleInstance = $deliveryModule->getDeliveryModuleInstance($this->container); + + $cart = $this->getSession()->getSessionCart($this->getDispatcher()); + $deliveryPostageEvent = new DeliveryPostageEvent($moduleInstance, $cart, $deliveryAddress); + + $this->getDispatcher()->dispatch( + TheliaEvents::MODULE_DELIVERY_GET_POSTAGE, + $deliveryPostageEvent + ); + + if (!$deliveryPostageEvent->isValidModule() || null === $deliveryPostageEvent->getPostage()) { + throw new DeliveryException( + $this->getTranslator()->trans('The delivery module is not valid.', [], Front::MESSAGE_DOMAIN) + ); + } + + $postage = $deliveryPostageEvent->getPostage(); + + $orderEvent = $this->getOrderEvent(); + $orderEvent->setDeliveryAddress($deliveryAddressId); + $orderEvent->setDeliveryModule($deliveryModuleId); + $orderEvent->setPostage($postage->getAmount()); + $orderEvent->setPostageTax($postage->getAmountTax()); + $orderEvent->setPostageTaxRuleTitle($postage->getTaxRuleTitle()); + + $this->getDispatcher()->dispatch(TheliaEvents::ORDER_SET_DELIVERY_ADDRESS, $orderEvent); + $this->getDispatcher()->dispatch(TheliaEvents::ORDER_SET_DELIVERY_MODULE, $orderEvent); + $this->getDispatcher()->dispatch(TheliaEvents::ORDER_SET_POSTAGE, $orderEvent); + + return $this->generateRedirectFromRoute("order.invoice"); + + } catch (FormValidationException $e) { + $message = $this->getTranslator()->trans( + "Please check your input: %s", + ['%s' => $e->getMessage()], + Front::MESSAGE_DOMAIN + ); + } catch (PropelException $e) { + $this->getParserContext()->setGeneralError($e->getMessage()); + } catch (\Exception $e) { + $message = $this->getTranslator()->trans( + "Sorry, an error occured: %s", + ['%s' => $e->getMessage()], + Front::MESSAGE_DOMAIN + ); + } + + if ($message !== false) { + Tlog::getInstance()->error( + sprintf("Error during order delivery process : %s. Exception was %s", $message, $e->getMessage()) + ); + + $orderDelivery->setErrorMessage($message); + + $this->getParserContext() + ->addForm($orderDelivery) + ->setGeneralError($message) + ; + } + } + + /** + * set invoice address + * set payment module + */ + public function invoice() + { + $this->checkAuth(); + $this->checkCartNotEmpty(); + $this->checkValidDelivery(); + + $message = false; + + $orderPayment = $this->createForm(FrontForm::ORDER_PAYMENT); + + try { + $form = $this->validateForm($orderPayment, "post"); + + $invoiceAddressId = $form->get("invoice-address")->getData(); + $paymentModuleId = $form->get("payment-module")->getData(); + + /* check that the invoice address belongs to the current customer */ + $invoiceAddress = AddressQuery::create()->findPk($invoiceAddressId); + if ($invoiceAddress->getCustomerId() !== $this->getSecurityContext()->getCustomerUser()->getId()) { + throw new \Exception( + $this->getTranslator()->trans( + "Invoice address does not belong to the current customer", + [], + Front::MESSAGE_DOMAIN + ) + ); + } + + $orderEvent = $this->getOrderEvent(); + $orderEvent->setInvoiceAddress($invoiceAddressId); + $orderEvent->setPaymentModule($paymentModuleId); + + $this->getDispatcher()->dispatch(TheliaEvents::ORDER_SET_INVOICE_ADDRESS, $orderEvent); + $this->getDispatcher()->dispatch(TheliaEvents::ORDER_SET_PAYMENT_MODULE, $orderEvent); + + return $this->generateRedirectFromRoute("order.payment.process"); + + } catch (FormValidationException $e) { + $message = $this->getTranslator()->trans( + "Please check your input: %s", + ['%s' => $e->getMessage()], + Front::MESSAGE_DOMAIN + ); + } catch (PropelException $e) { + $this->getParserContext()->setGeneralError($e->getMessage()); + } catch (\Exception $e) { + $message = $this->getTranslator()->trans( + "Sorry, an error occured: %s", + ['%s' => $e->getMessage()], + Front::MESSAGE_DOMAIN + ); + } + + if ($message !== false) { + Tlog::getInstance()->error( + sprintf("Error during order payment process : %s. Exception was %s", $message, $e->getMessage()) + ); + + $orderPayment->setErrorMessage($message); + + $this->getParserContext() + ->addForm($orderPayment) + ->setGeneralError($message) + ; + } + + return $this->generateErrorRedirect($orderPayment); + } + + public function pay() + { + /* check customer */ + $this->checkAuth(); + + /* check cart count */ + $this->checkCartNotEmpty(); + + /* check stock not empty */ + if (true === ConfigQuery::checkAvailableStock()) { + if (null !== $response = $this->checkStockNotEmpty()) { + return $response; + } + } + + /* check delivery address and module */ + $this->checkValidDelivery(); + + /* check invoice address and payment module */ + $this->checkValidInvoice(); + + $orderEvent = $this->getOrderEvent(); + + $this->getDispatcher()->dispatch(TheliaEvents::ORDER_PAY, $orderEvent); + + $placedOrder = $orderEvent->getPlacedOrder(); + + if (null !== $placedOrder && null !== $placedOrder->getId()) { + /* order has been placed */ + if ($orderEvent->hasResponse()) { + return $orderEvent->getResponse(); + } else { + return $this->generateRedirectFromRoute( + 'order.placed', + [], + ['order_id' => $orderEvent->getPlacedOrder()->getId()] + ); + } + } else { + /* order has not been placed */ + return $this->generateRedirectFromRoute('cart.view'); + } + } + + public function orderPlaced($order_id) + { + /* check if the placed order matched the customer */ + $placedOrder = OrderQuery::create()->findPk( + $this->getRequest()->attributes->get('order_id') + ); + + if (null === $placedOrder) { + throw new TheliaProcessException( + $this->getTranslator()->trans( + "No placed order", + [], + Front::MESSAGE_DOMAIN + ), + TheliaProcessException::NO_PLACED_ORDER, + $placedOrder + ); + } + + $customer = $this->getSecurityContext()->getCustomerUser(); + + if (null === $customer || $placedOrder->getCustomerId() !== $customer->getId()) { + throw new TheliaProcessException( + $this->getTranslator()->trans( + "Received placed order id does not belong to the current customer", + [], + Front::MESSAGE_DOMAIN + ), + TheliaProcessException::PLACED_ORDER_ID_BAD_CURRENT_CUSTOMER, + $placedOrder + ); + } + + $this->getDispatcher()->dispatch(TheliaEvents::ORDER_CART_CLEAR, $this->getOrderEvent()); + + $this->getParserContext()->set("placed_order_id", $placedOrder->getId()); + } + + + public function orderFailed($order_id, $message) + { + if (empty($order_id)) { + // Fallback to request parameter if the method parameter is empty. + $order_id = $this->getRequest()->get('order_id'); + } + + $failedOrder = OrderQuery::create()->findPk($order_id); + + if (null !== $failedOrder) { + $customer = $this->getSecurityContext()->getCustomerUser(); + + if (null === $customer || $failedOrder->getCustomerId() !== $customer->getId()) { + throw new TheliaProcessException( + $this->getTranslator()->trans( + "Received failed order id does not belong to the current customer", + [], + Front::MESSAGE_DOMAIN + ), + TheliaProcessException::PLACED_ORDER_ID_BAD_CURRENT_CUSTOMER, + $failedOrder + ); + } + } else { + Tlog::getInstance()->warning("Failed order ID '$order_id' not found."); + } + + $this->getParserContext() + ->set("failed_order_id", $order_id) + ->set("failed_order_message", $message) + ; + } + + protected function getOrderEvent() + { + $order = $this->getOrder($this->getRequest()); + + return new OrderEvent($order); + } + + public function getOrder(Request $request) + { + $session = $request->getSession(); + + if (null !== $order = $session->getOrder()) { + return $order; + } + + $order = new Order(); + + $session->setOrder($order); + + return $order; + } + + + public function viewAction($order_id) + { + $this->checkOrderCustomer($order_id); + + return $this->render('account-order', ['order_id' => $order_id]); + } + + public function generateInvoicePdf($order_id) + { + $this->checkOrderCustomer($order_id); + + + return $this->generateOrderPdf($order_id, ConfigQuery::read('pdf_invoice_file', 'invoice')); + } + + public function generateDeliveryPdf($order_id) + { + $this->checkOrderCustomer($order_id); + + return $this->generateOrderPdf($order_id, ConfigQuery::read('pdf_delivery_file', 'delivery')); + } + + public function downloadVirtualProduct($order_product_id) + { + if (null !== $orderProduct = OrderProductQuery::create()->findPk($order_product_id)) { + $order = $orderProduct->getOrder(); + + if ($order->isPaid(false)) { + // check customer + $this->checkOrderCustomer($order->getId()); + + $virtualProductEvent = new VirtualProductOrderDownloadResponseEvent($orderProduct); + $this->getDispatcher()->dispatch( + TheliaEvents::VIRTUAL_PRODUCT_ORDER_DOWNLOAD_RESPONSE, + $virtualProductEvent + ); + + $response = $virtualProductEvent->getResponse(); + + if (!$response instanceof BaseResponse) { + throw new \RuntimeException('A Response must be added in the event TheliaEvents::VIRTUAL_PRODUCT_ORDER_DOWNLOAD_RESPONSE'); + } + + return $response; + } + } + + throw new AccessDeniedHttpException(); + + } + + private function checkOrderCustomer($order_id) + { + $this->checkAuth(); + + $order = OrderQuery::create()->findPk($order_id); + $valid = true; + if ($order) { + $customerOrder = $order->getCustomer(); + $customer = $this->getSecurityContext()->getCustomerUser(); + + if ($customerOrder->getId() != $customer->getId()) { + $valid = false; + } + } else { + $valid = false; + } + + if (false === $valid) { + throw new AccessDeniedHttpException(); + } + } + + public function getDeliveryModuleListAjaxAction() + { + $this->checkXmlHttpRequest(); + + // Change the delivery address if customer has changed it + $address = null; + $session = $this->getSession(); + $addressId = $this->getRequest()->get('address_id', null); + if (null !== $addressId && $addressId !== $session->getOrder()->getChoosenDeliveryAddress()) { + $address = AddressQuery::create()->findPk($addressId); + if (null !== $address && $address->getCustomerId() === $session->getCustomerUser()->getId()) { + $session->getOrder()->setChoosenDeliveryAddress($addressId); + } + } + + $address = AddressQuery::create()->findPk($session->getOrder()->getChoosenDeliveryAddress()); + + $countryId = $address->getCountryId(); + $stateId = $address->getStateId(); + + $args = array( + 'country' => $countryId, + 'state' => $stateId, + 'address' => $session->getOrder()->getChoosenDeliveryAddress() + ); + + return $this->render('ajax/order-delivery-module-list', $args); + } + + /** + * Redirect to cart view if at least one non product is out of stock + * + * @return null|BaseResponse + */ + private function checkStockNotEmpty() + { + $cart = $this->getSession()->getSessionCart($this->getDispatcher()); + + $cartItems = $cart->getCartItems(); + + foreach ($cartItems as $cartItem) { + $pse = $cartItem->getProductSaleElements(); + + $product = $cartItem->getProduct(); + + if ($pse->getQuantity() <= 0 && $product->getVirtual() !== 1) { + return $this->generateRedirectFromRoute('cart.view'); + } + } + + return null; + } + + /** + * Retrieve the chosen delivery address for a cart or the default customer address if not exists + * + * @return null|Address + */ + protected function getCustomerAddress() + { + $deliveryAddress = null; + $addressId = $this->getSession()->getOrder()->getChoosenDeliveryAddress(); + if (null === $addressId) { + $customer = $this->getSecurityContext()->getCustomerUser(); + + $deliveryAddress = AddressQuery::create() + ->filterByCustomerId($customer->getId()) + ->orderByIsDefault(Criteria::DESC) + ->findOne(); + + if (null !== $deliveryAddress) { + $this->getSession()->getOrder()->setChoosenDeliveryAddress( + $deliveryAddress->getId() + ); + } + } else { + $deliveryAddress = AddressQuery::create()->findPk($addressId); + } + + return $deliveryAddress; + } +} diff --git a/local/modules/Front/Controller/SitemapController.php b/local/modules/Front/Controller/SitemapController.php new file mode 100644 index 00000000..360f2744 --- /dev/null +++ b/local/modules/Front/Controller/SitemapController.php @@ -0,0 +1,152 @@ + + */ +class SitemapController extends BaseFrontController { + + + /** + * Folder name for sitemap cache + */ + const SITEMAP_CACHE_DIR = "sitemap"; + + /** + * Key prefix for sitemap cache + */ + const SITEMAP_CACHE_KEY = "sitemap"; + + /** + * @return Response + */ + public function generateAction() + { + /** @var Request $request */ + $request = $this->getRequest(); + + // the locale : fr, en, + $lang = $request->query->get("lang", ""); + if ("" !== $lang) { + if (! $this->checkLang($lang)){ + $this->pageNotFound(); + } + } + // specific content : product, category, cms + $context = $request->query->get("context", ""); + if (! in_array($context, array("", "catalog", "content")) ){ + $this->pageNotFound(); + } + + $flush = $request->query->get("flush", ""); + + // check if sitemap already in cache + $cacheContent = false; + + $cacheDir = $this->getCacheDir(); + $cacheKey = self::SITEMAP_CACHE_KEY . $lang . $context; + $cacheExpire = intval(ConfigQuery::read("sitemap_ttl", '7200')) ?: 7200; + + $cacheDriver = new FilesystemCache($cacheDir); + if (!($this->checkAdmin() && "" !== $flush)) { + $cacheContent = $cacheDriver->fetch($cacheKey); + } else { + $cacheDriver->delete($cacheKey); + } + + // if not in cache + if (false === $cacheContent) { + // Render the view. Compression causes problems and is deactivated. + $cacheContent = $this->getParser(null)->render( + 'sitemap.html', + [ + "_lang_" => $lang, + "_context_" => $context + ], + false + ); + + // save cache + $cacheDriver->save($cacheKey, $cacheContent, $cacheExpire); + } + + $response = new Response(); + $response->setContent($cacheContent); + $response->headers->set('Content-Type', 'application/xml'); + + return $response; + } + + + /** + * get the cache directory for sitemap + * + * @return mixed|string + */ + protected function getCacheDir() + { + $cacheDir = $this->container->getParameter("kernel.cache_dir"); + $cacheDir = rtrim($cacheDir, '/'); + $cacheDir .= '/' . self::SITEMAP_CACHE_DIR . '/'; + + return $cacheDir; + } + + /** + * Check if current user has ADMIN role + * + * @return bool + */ + protected function checkAdmin(){ + return $this->getSecurityContext()->hasAdminUser(); + } + + + /** + * Check if a lang is used + * + * @param $lang The lang code. e.g.: fr + * @return bool true if the language is used, otherwise false + */ + private function checkLang($lang) + { + // load locals + $lang = LangQuery::create() + ->findOneByCode($lang); + + return (null !== $lang); + } + +} diff --git a/local/modules/Front/Front.php b/local/modules/Front/Front.php new file mode 100644 index 00000000..c085f27f --- /dev/null +++ b/local/modules/Front/Front.php @@ -0,0 +1,31 @@ +. */ +/* */ +/*************************************************************************************/ + +namespace Front; + +use Thelia\Module\BaseModule; + +class Front extends BaseModule +{ + const MESSAGE_DOMAIN = 'front'; +} diff --git a/local/modules/Front/I18n/de_DE.php b/local/modules/Front/I18n/de_DE.php new file mode 100644 index 00000000..bf641783 --- /dev/null +++ b/local/modules/Front/I18n/de_DE.php @@ -0,0 +1,22 @@ + 'Gutschein-Code darf nicht leer sein', + 'Delivery address does not belong to the current customer' => 'Lieferadresse gehört nicht zum aktuellen Kunden', + 'Delivery module cannot be use with selected delivery address' => 'Lieferung-Modul kann nicht mit ausgewählten Lieferadresse verwendet werden', + 'Error during address deletion process' => 'Fehler beim Löschen der Adresse', + 'Failed to add this article to your cart, please try again' => 'Der Artikel konnte nicht zum Warenkorb hinzugefügt werden, bitte versuchen Sie es erneut', + 'Invoice address does not belong to the current customer' => 'Rechnungsadresse gehört nicht zum aktuellen Kunden', + 'No placed order' => 'Keine Bestellungen', + 'Please check your coupon code: %message' => 'Bitte überprüfen Sie Ihren Gutschein-Code: %message', + 'Please check your input: %s' => 'Bitte überprüfen Sie Ihre Eingabe: %s', + 'Received failed order id does not belong to the current customer' => 'Empfangene Id einer fehlgeschlagenen Bestellung gehört nicht zum aktuellen Kunden', + 'Received placed order id does not belong to the current customer' => 'Empfangene Bestellungs-Id gehört nicht zum aktuellen Kunden', + 'Sorry, an error occured: %s' => 'Leider ist ein Fehler aufgetreten: %s', + 'Sorry, an error occurred: %message' => 'Leider ist ein Fehler aufgetreten: %message', + 'Sorry, an error occurred: %s' => 'Es tut uns Leid, aber ein Fehler ist aufgetreten: %s', + 'Thanks for signing up! We\'ll keep you posted whenever we have any new updates.' => 'Vielen Dank für Ihre Anmeldung! Wir halten Ihnen auf dem Laufenden über neuen Updates.', + 'To enable the virtual product feature, the VirtualProductDelivery module should be activated' => 'Um das virtuelle Produkt-Feature zu aktivieren, sollte das VirtualProductDelivery-Modul aktiviert werden', + 'Wrong email or password. Please try again' => 'E-Mail oder Passwort falsch. Bitte erneut versuchen', + 'You\'re currently logged in. Please log out before requesting a new password.' => 'Sie sind derzeit angemeldet. Bitte melden Sie sich ab, bevor Sie ein neues Passwort anfordern.', +]; diff --git a/local/modules/Front/I18n/en_US.php b/local/modules/Front/I18n/en_US.php new file mode 100644 index 00000000..1db05104 --- /dev/null +++ b/local/modules/Front/I18n/en_US.php @@ -0,0 +1,24 @@ + 'Coupon code can\'t be empty', + 'Delivery address does not belong to the current customer' => 'Delivery address does not belong to the current customer', + 'Delivery module cannot be use with selected delivery address' => 'Delivery module cannot be use with selected delivery address', + 'Error during address deletion process' => 'Error during address deletion process', + 'Failed to add this article to your cart, please try again' => 'Failed to add this article to your cart, please try again', + 'Invoice address does not belong to the current customer' => 'Invoice address does not belong to the current customer', + 'No placed order' => 'No placed order', + 'Please check your coupon code: %message' => 'Please check your coupon code: %message', + 'Please check your input: %s' => 'Please check your input: %s', + 'Received failed order id does not belong to the current customer' => 'Received failed order id does not belong to the current customer', + 'Received placed order id does not belong to the current customer' => 'Received placed order id does not belong to the current customer', + 'Sorry, an error occured: %s' => 'Sorry, an error occured: %s', + 'Sorry, an error occurred: %message' => 'Sorry, an error occurred: %message', + 'Sorry, an error occurred: %s' => 'Sorry, an error occurred: %s', + 'Thanks for signing up! We\'ll keep you posted whenever we have any new updates.' => 'Thanks for signing up! We\'ll keep you posted whenever we have any new updates.', + 'To enable the virtual product feature, the VirtualProductDelivery module should be activated' => 'To enable the virtual product feature, the VirtualProductDelivery module should be activated', + 'Wrong email or password. Please try again' => 'Wrong email or password. Please try again', + 'You should sign in or register to use this coupon' => 'You should sign in or register to use this coupon', + 'You\'re currently logged in. Please log out before requesting a new password.' => 'You\'re currently logged in. Please log out before requesting a new password.', + 'Your account is not yet confirmed check out your mailbox' => 'Your account is not yet confirmed check out your mailbox', +); diff --git a/local/modules/Front/I18n/fr_FR.php b/local/modules/Front/I18n/fr_FR.php new file mode 100644 index 00000000..35405e3e --- /dev/null +++ b/local/modules/Front/I18n/fr_FR.php @@ -0,0 +1,23 @@ + 'Le code promo ne peut être vide', + 'Delivery address does not belong to the current customer' => 'L\'adresse de livraison n\'appartient pas au client en cours', + 'Delivery module cannot be use with selected delivery address' => 'Le module de livraison ne peut pas être utilisé avec cette adresse de livraison', + 'Error during address deletion process' => 'Désolé. Une erreur s\'est produite lors de la suppression de l\'adresse', + 'Failed to add this article to your cart, please try again' => 'Impossible d\'ajouter cet article à votre panier. Merci de ré-essayer.', + 'Invoice address does not belong to the current customer' => 'L\'adresse de facturation n\'appartient pas au client en cours', + 'No placed order' => 'Aucune commande passée', + 'Please check your coupon code: %message' => 'Merci de vérifier votre code promo : %message', + 'Please check your input: %s' => 'Merci de vérifier les informations indiquées : %s', + 'Received failed order id does not belong to the current customer' => 'L\'id de commande refusée n\'appartient pas au client en cours', + 'Received placed order id does not belong to the current customer' => 'L\'id de commande passée n\'appartient pas au client en cours', + 'Sorry, an error occured: %s' => 'Désolé. Une erreur s\'est produite : %s', + 'Sorry, an error occurred: %message' => 'Désolé. Une erreur s\'est produite : %message', + 'Sorry, an error occurred: %s' => 'Désolé, une erreur est survenue : %s', + 'Thanks for signing up! We\'ll keep you posted whenever we have any new updates.' => 'Merci de votre inscription ! Nous vous tiendrons informé dès qu\'il y aura des nouveautés.', + 'To enable the virtual product feature, the VirtualProductDelivery module should be activated' => 'Pour activer les produits virtuels, le module VirtualProductDelivery doit être activé', + 'Wrong email or password. Please try again' => 'Adresse email ou mot de passe incorrect. Merci de ré-essayer.', + 'You should sign in or register to use this coupon' => 'Vous devez vous connecter ou vous inscrire pour utiliser ce coupon', + 'You\'re currently logged in. Please log out before requesting a new password.' => 'Vous être actuellement connecté au site. Vous devez vous déconnecter pour demander un nouveau mot de passe.', +]; diff --git a/local/modules/Front/I18n/it_IT.php b/local/modules/Front/I18n/it_IT.php new file mode 100644 index 00000000..041021bb --- /dev/null +++ b/local/modules/Front/I18n/it_IT.php @@ -0,0 +1,7 @@ + 'Il codice di sconto non può essere vuoto', + 'Thanks for signing up! We\'ll keep you posted whenever we have any new updates.' => 'Grazie per l\'inscrizione! Ti terremo aggiornato ogni volta che abbiamo eventuali nuovi aggiornamenti.', + 'You should sign in or register to use this coupon' => 'Dovresti accedere o registrarti per utilizzare questo coupon', +]; diff --git a/local/modules/Front/I18n/ru_RU.php b/local/modules/Front/I18n/ru_RU.php new file mode 100644 index 00000000..0926766c --- /dev/null +++ b/local/modules/Front/I18n/ru_RU.php @@ -0,0 +1,25 @@ + 'Код купона не может быть пустым', + 'Delivery address does not belong to the current customer' => 'Адрес доставки не пренадлежит текущему клиенту', + 'Delivery module cannot be use with selected delivery address' => 'Модуль доставки не может быть использован с текущим адресом доставки', + 'Error during address deletion process' => 'Ошибка удаления адреса', + 'Failed to add this article to your cart, please try again' => 'Ошибка при добавлении статьи в вашу корзину, попробуйте еще раз', + 'Invoice address does not belong to the current customer' => 'Адрес выставления счета не пренадлежит текущему клиенту', + 'No placed order' => 'Нет размещенного заказа', + 'Please check your coupon code: %message' => 'Пожалуйста, проверьте код купона: %message', + 'Please check your input: %s' => 'Пожалуйста, проверьте ваш ввод: %s', + 'Received failed order id does not belong to the current customer' => 'Полученный ошибочный заказ не пренадлежит текущему клиенту', + 'Received placed order id does not belong to the current customer' => 'Полученный размещенный заказ не пренадлежит текущему клиенту', + 'Sorry, an error occured: %s' => 'К сожалению произшла ошибка: %s', + 'Sorry, an error occurred: %message' => 'К сожалению произошла ошибка: %message ', + 'Sorry, an error occurred: %s' => 'К сожалению произошла ошибка: %s ', + 'Thanks for signing up! We\'ll keep you posted whenever we have any new updates.' => 'Спасибо за подписку! Мы будем держать вас в курсе обновлений.', + 'The delivery module is not valid.' => 'Некоректный модуль доставки', + 'To enable the virtual product feature, the VirtualProductDelivery module should be activated' => 'Для включения функции виртуальных продуктов, модуль VirtualProductDelivery должен быть включен', + 'Wrong email or password. Please try again' => 'Некоректный email или пароль. Пожалуйста, попробуйте еще раз', + 'You should sign in or register to use this coupon' => 'Вы должны войти или зарегистрироваться что использовать этот купон', + 'You\'re currently logged in. Please log out before requesting a new password.' => 'Вы сейчас авторизированы. Пожалуйста выйдите перед запросом нового пароля.', + 'Your subscription to our newsletter has been canceled.' => 'Ваша подписка на рассылку была отменена', +); diff --git a/local/modules/Front/I18n/tr_TR.php b/local/modules/Front/I18n/tr_TR.php new file mode 100644 index 00000000..47004a8b --- /dev/null +++ b/local/modules/Front/I18n/tr_TR.php @@ -0,0 +1,22 @@ + 'Kupon şifre boş olamaz', + 'Delivery address does not belong to the current customer' => 'Teslimat adresi geçerli müşteriye ait değil', + 'Delivery module cannot be use with selected delivery address' => 'Teslim modülü seçili teslimat adresi kullanılamaz', + 'Error during address deletion process' => 'Adres silme işlemi sırasında bir hata oluştu', + 'Failed to add this article to your cart, please try again' => 'Sepetinize Bu ürün eklenemedi, lütfen tekrar deneyin', + 'Invoice address does not belong to the current customer' => 'Fatura adresi geçerli müşteriye ait değil', + 'No placed order' => 'Yerleştirilen hiçbir sipariş', + 'Please check your coupon code: %message' => 'Kupon kodunuzu gözden geçirin: %message', + 'Please check your input: %s' => 'Lütfen girişinizi denetleyin: %s', + 'Received failed order id does not belong to the current customer' => 'Alınan başarısız sipariş kimliği geçerli müşteriye ait değil', + 'Received placed order id does not belong to the current customer' => 'Alınmış yerleştirilmiş sipariş kimliği geçerli müşteriye ait değil', + 'Sorry, an error occured: %s' => 'Üzgünüz, bir hata oluştu: %s', + 'Sorry, an error occurred: %message' => 'Üzgünüz, bir hata oluştu: %message', + 'Sorry, an error occurred: %s' => 'Üzgünüz, bir hata oluştu: %s', + 'Thanks for signing up! We\'ll keep you posted whenever we have any new updates.' => 'Teşekkürler. Yeni güncelleştirmeler olduğunda sizi haberdar edeceğiz.', + 'To enable the virtual product feature, the VirtualProductDelivery module should be activated' => 'Sanal ürün özelliği etkinleştirmek için VirtualProductDelivery modülü etkinleştirilmesi', + 'Wrong email or password. Please try again' => 'Email adresi veya şifre hatalı. Lütfen tekrar deneyiniz', + 'You\'re currently logged in. Please log out before requesting a new password.' => 'Şu anda logged içinde. Lütfen yeni bir parola istemeden önce çıkış.', +]; diff --git a/local/modules/Front/LICENSE.txt b/local/modules/Front/LICENSE.txt new file mode 100644 index 00000000..65c5ca88 --- /dev/null +++ b/local/modules/Front/LICENSE.txt @@ -0,0 +1,165 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + + This version of the GNU Lesser General Public License incorporates +the terms and conditions of version 3 of the GNU General Public +License, supplemented by the additional permissions listed below. + + 0. Additional Definitions. + + As used herein, "this License" refers to version 3 of the GNU Lesser +General Public License, and the "GNU GPL" refers to version 3 of the GNU +General Public License. + + "The Library" refers to a covered work governed by this License, +other than an Application or a Combined Work as defined below. + + An "Application" is any work that makes use of an interface provided +by the Library, but which is not otherwise based on the Library. +Defining a subclass of a class defined by the Library is deemed a mode +of using an interface provided by the Library. + + A "Combined Work" is a work produced by combining or linking an +Application with the Library. The particular version of the Library +with which the Combined Work was made is also called the "Linked +Version". + + The "Minimal Corresponding Source" for a Combined Work means the +Corresponding Source for the Combined Work, excluding any source code +for portions of the Combined Work that, considered in isolation, are +based on the Application, and not on the Linked Version. + + The "Corresponding Application Code" for a Combined Work means the +object code and/or source code for the Application, including any data +and utility programs needed for reproducing the Combined Work from the +Application, but excluding the System Libraries of the Combined Work. + + 1. Exception to Section 3 of the GNU GPL. + + You may convey a covered work under sections 3 and 4 of this License +without being bound by section 3 of the GNU GPL. + + 2. Conveying Modified Versions. + + If you modify a copy of the Library, and, in your modifications, a +facility refers to a function or data to be supplied by an Application +that uses the facility (other than as an argument passed when the +facility is invoked), then you may convey a copy of the modified +version: + + a) under this License, provided that you make a good faith effort to + ensure that, in the event an Application does not supply the + function or data, the facility still operates, and performs + whatever part of its purpose remains meaningful, or + + b) under the GNU GPL, with none of the additional permissions of + this License applicable to that copy. + + 3. Object Code Incorporating Material from Library Header Files. + + The object code form of an Application may incorporate material from +a header file that is part of the Library. You may convey such object +code under terms of your choice, provided that, if the incorporated +material is not limited to numerical parameters, data structure +layouts and accessors, or small macros, inline functions and templates +(ten or fewer lines in length), you do both of the following: + + a) Give prominent notice with each copy of the object code that the + Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the object code with a copy of the GNU GPL and this license + document. + + 4. Combined Works. + + You may convey a Combined Work under terms of your choice that, +taken together, effectively do not restrict modification of the +portions of the Library contained in the Combined Work and reverse +engineering for debugging such modifications, if you also do each of +the following: + + a) Give prominent notice with each copy of the Combined Work that + the Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the Combined Work with a copy of the GNU GPL and this license + document. + + c) For a Combined Work that displays copyright notices during + execution, include the copyright notice for the Library among + these notices, as well as a reference directing the user to the + copies of the GNU GPL and this license document. + + d) Do one of the following: + + 0) Convey the Minimal Corresponding Source under the terms of this + License, and the Corresponding Application Code in a form + suitable for, and under terms that permit, the user to + recombine or relink the Application with a modified version of + the Linked Version to produce a modified Combined Work, in the + manner specified by section 6 of the GNU GPL for conveying + Corresponding Source. + + 1) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (a) uses at run time + a copy of the Library already present on the user's computer + system, and (b) will operate properly with a modified version + of the Library that is interface-compatible with the Linked + Version. + + e) Provide Installation Information, but only if you would otherwise + be required to provide such information under section 6 of the + GNU GPL, and only to the extent that such information is + necessary to install and execute a modified version of the + Combined Work produced by recombining or relinking the + Application with a modified version of the Linked Version. (If + you use option 4d0, the Installation Information must accompany + the Minimal Corresponding Source and Corresponding Application + Code. If you use option 4d1, you must provide the Installation + Information in the manner specified by section 6 of the GNU GPL + for conveying Corresponding Source.) + + 5. Combined Libraries. + + You may place library facilities that are a work based on the +Library side by side in a single library together with other library +facilities that are not Applications and are not covered by this +License, and convey such a combined library under terms of your +choice, if you do both of the following: + + a) Accompany the combined library with a copy of the same work based + on the Library, uncombined with any other library facilities, + conveyed under the terms of this License. + + b) Give prominent notice with the combined library that part of it + is a work based on the Library, and explaining where to find the + accompanying uncombined form of the same work. + + 6. Revised Versions of the GNU Lesser General Public License. + + The Free Software Foundation may publish revised and/or new versions +of the GNU Lesser General Public License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. + + Each version is given a distinguishing version number. If the +Library as you received it specifies that a certain numbered version +of the GNU Lesser General Public License "or any later version" +applies to it, you have the option of following the terms and +conditions either of that published version or of any later version +published by the Free Software Foundation. If the Library as you +received it does not specify a version number of the GNU Lesser +General Public License, you may choose any version of the GNU Lesser +General Public License ever published by the Free Software Foundation. + + If the Library as you received it specifies that a proxy can decide +whether future versions of the GNU Lesser General Public License shall +apply, that proxy's public statement of acceptance of any version is +permanent authorization for you to choose that version for the +Library. diff --git a/local/modules/Front/composer.json b/local/modules/Front/composer.json new file mode 100644 index 00000000..b916b7bb --- /dev/null +++ b/local/modules/Front/composer.json @@ -0,0 +1,11 @@ +{ + "name": "thelia/front-module", + "license": "LGPL-3.0+", + "type": "thelia-module", + "require": { + "thelia/installer": "~1.1" + }, + "extra": { + "installer-name": "Front" + } +} diff --git a/local/modules/HookAdminHome/Config/config.xml b/local/modules/HookAdminHome/Config/config.xml new file mode 100644 index 00000000..ccf0868a --- /dev/null +++ b/local/modules/HookAdminHome/Config/config.xml @@ -0,0 +1,43 @@ + + + + + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/local/modules/HookAdminHome/Config/module.xml b/local/modules/HookAdminHome/Config/module.xml new file mode 100644 index 00000000..3d7373b0 --- /dev/null +++ b/local/modules/HookAdminHome/Config/module.xml @@ -0,0 +1,32 @@ + + + HookAdminHome\HookAdminHome + + Displays the default blocks on the homepage of the administration + + + Affiche les blocs par défaut sur la page d'accueil de l'administration + + + en_US + fr_FR + + 2.4.3 + + + Gilles Bourgeat + gilles@thelia.net + + + Franck Allimant + CQFDev + franck@cqfdev.fr + www.cqfdev.fr + + + classic + 2.3.4 + prod + diff --git a/local/modules/HookAdminHome/Config/routing.xml b/local/modules/HookAdminHome/Config/routing.xml new file mode 100644 index 00000000..251a3d4f --- /dev/null +++ b/local/modules/HookAdminHome/Config/routing.xml @@ -0,0 +1,28 @@ + + + + + + HookAdminHome\Controller\HomeController::loadStatsAjaxAction + + + + HookAdminHome\Controller\HomeController::blockMonthSalesStatistics + \d+ + \d+ + + + + HookAdminHome\Controller\HomeController::processTemplateAction + ajax/thelia_news_feed + 1 + + + + + + HookAdminHome\Controller\ConfigurationController::editConfiguration + + diff --git a/local/modules/HookAdminHome/Controller/ConfigurationController.php b/local/modules/HookAdminHome/Controller/ConfigurationController.php new file mode 100644 index 00000000..fc8ebcae --- /dev/null +++ b/local/modules/HookAdminHome/Controller/ConfigurationController.php @@ -0,0 +1,72 @@ +checkAuth( + AdminResources::MODULE, + [HookAdminHome::DOMAIN_NAME], + AccessManager::UPDATE + )) { + return $response; + } + + $form = $this->createForm('hookadminhome.config.form'); + $error_message = null; + + try { + $validateForm = $this->validateForm($form); + $data = $validateForm->getData(); + + HookAdminHome::setConfigValue(HookAdminHome::ACTIVATE_NEWS, 0); + HookAdminHome::setConfigValue(HookAdminHome::ACTIVATE_SALES, 0); + HookAdminHome::setConfigValue(HookAdminHome::ACTIVATE_INFO, 0); + HookAdminHome::setConfigValue(HookAdminHome::ACTIVATE_STATS, 0); + + if($data['enabled-news']){ + HookAdminHome::setConfigValue(HookAdminHome::ACTIVATE_NEWS, 1); + } + + if($data['enabled-sales']){ + HookAdminHome::setConfigValue(HookAdminHome::ACTIVATE_SALES, 1); + } + + if($data['enabled-info']){ + HookAdminHome::setConfigValue(HookAdminHome::ACTIVATE_INFO, 1); + } + + if($data['enabled-stats']){ + HookAdminHome::setConfigValue(HookAdminHome::ACTIVATE_STATS, 1); + } + + return RedirectResponse::create(URL::getInstance()->absoluteUrl('/admin/module/HookAdminHome')); + + } catch (FormValidationException $e) { + $error_message = $this->createStandardFormValidationErrorMessage($e); + } + + if (null !== $error_message) { + $this->setupFormErrorContext( + 'configuration', + $error_message, + $form + ); + $response = $this->render("module-configure", ['module_code' => 'HookAdminHome']); + } + return $response; + } + +} diff --git a/local/modules/HookAdminHome/Controller/HomeController.php b/local/modules/HookAdminHome/Controller/HomeController.php new file mode 100644 index 00000000..acd656cb --- /dev/null +++ b/local/modules/HookAdminHome/Controller/HomeController.php @@ -0,0 +1,156 @@ + + */ +class HomeController extends BaseAdminController +{ + /** + * Key prefix for stats cache + */ + const STATS_CACHE_KEY = "stats"; + + const RESOURCE_CODE = "admin.home"; + + public function loadStatsAjaxAction() + { + if (null !== $response = $this->checkAuth(self::RESOURCE_CODE, array(), AccessManager::VIEW)) { + return $response; + } + + $cacheExpire = ConfigQuery::getAdminCacheHomeStatsTTL(); + + /** @var AdapterInterface $cacheAdapter */ + $cacheAdapter = $this->container->get('thelia.cache'); + + $month = (int) $this->getRequest()->query->get('month', date('m')); + $year = (int) $this->getRequest()->query->get('year', date('Y')); + + $cacheKey = self::STATS_CACHE_KEY . "_" . $month . "_" . $year; + + $cacheItem = $cacheAdapter->getItem($cacheKey); + + // force flush + if ($this->getRequest()->query->get('flush', "0")) { + $cacheAdapter->deleteItem($cacheKey); + } + + if (!$cacheItem->isHit()) { + $data = $this->getStatus($month, $year); + + $cacheItem->set(json_encode($data)); + $cacheItem->expiresAfter($cacheExpire); + + if ($cacheExpire) { + $cacheAdapter->save($cacheItem); + } + } + + return $this->jsonResponse($cacheItem->get()); + } + + public function blockMonthSalesStatistics($month, $year) + { + $baseDate = sprintf("%04d-%02d", $year, $month); + + $startDate = "$baseDate-01"; + $endDate = date("Y-m-t", strtotime($startDate)); + + $prevMonthStartDate = date('Y-m-01', strtotime("$baseDate -1 month")); + $prevMonthEndDate = date("Y-m-t", strtotime($prevMonthStartDate)); + + return $this->render('block-month-sales-statistics', [ + 'startDate' => $startDate, + 'endDate' => $endDate, + 'prevMonthStartDate' => $prevMonthStartDate, + 'prevMonthEndDate' => $prevMonthEndDate, + ]); + } + + /** + * @param int $month + * @param int $year + * @return \stdClass + */ + protected function getStatus($month, $year) + { + $data = new \stdClass(); + + $data->title = $this->getTranslator()->trans( + "Stats on %month/%year", + ['%month' => $month, '%year' => $year], + HookAdminHome::DOMAIN_NAME + ); + + $data->series = []; + + /* sales */ + $data->series[] = $saleSeries = new \stdClass(); + $saleSeries->color = self::testHexColor('sales_color', '#adadad'); + $saleSeries->data = OrderQuery::getMonthlySaleStats($month, $year); + $saleSeries->valueFormat = "%1.2f " . Currency::getDefaultCurrency()->getSymbol(); + + /* new customers */ + $data->series[] = $newCustomerSeries = new \stdClass(); + $newCustomerSeries->color = self::testHexColor('customers_color', '#f39922'); + $newCustomerSeries->data = CustomerQuery::getMonthlyNewCustomersStats($month, $year); + $newCustomerSeries->valueFormat = "%d"; + + /* orders */ + $data->series[] = $orderSeries = new \stdClass(); + $orderSeries->color = self::testHexColor('orders_color', '#5cb85c'); + $orderSeries->data = OrderQuery::getMonthlyOrdersStats($month, $year); + $orderSeries->valueFormat = "%d"; + + /* first order */ + $data->series[] = $firstOrderSeries = new \stdClass(); + $firstOrderSeries->color = self::testHexColor('first_orders_color', '#5bc0de'); + $firstOrderSeries->data = OrderQuery::getFirstOrdersStats($month, $year); + $firstOrderSeries->valueFormat = "%d"; + + /* cancelled orders */ + $data->series[] = $cancelledOrderSeries = new \stdClass(); + $cancelledOrderSeries->color = self::testHexColor('cancelled_orders_color', '#d9534f'); + $cancelledOrderSeries->data = OrderQuery::getMonthlyOrdersStats($month, $year, array(5)); + $cancelledOrderSeries->valueFormat = "%d"; + + return $data; + } + + /** + * @param string $key + * @param string $default + * @return string hexadecimal color or default argument + */ + protected function testHexColor($key, $default) + { + $hexColor = $this->getRequest()->query->get($key, $default); + + return preg_match('/^#[a-f0-9]{6}$/i', $hexColor) ? $hexColor : $default; + } + + +} diff --git a/local/modules/HookAdminHome/Form/Configuration.php b/local/modules/HookAdminHome/Form/Configuration.php new file mode 100644 index 00000000..68ab6c34 --- /dev/null +++ b/local/modules/HookAdminHome/Form/Configuration.php @@ -0,0 +1,93 @@ +formBuilder->add( + "enabled-news", + "checkbox", + array( + "label" => "Enabled News", + "label_attr" => [ + "for" => "enabled-news", + "help" => Translator::getInstance()->trans( + 'Check if you want show news', + [], + HookAdminHome::DOMAIN_NAME + ) + ], + "required" => false, + "value" => HookAdminHome::getConfigValue(HookAdminHome::ACTIVATE_NEWS, 0), + ) + ); + + $this->formBuilder->add( + "enabled-info", + "checkbox", + array( + "label" => "Enabled Info", + "label_attr" => [ + "for" => "enabled-info", + "help" => Translator::getInstance()->trans( + 'Check if you want show info', + [], + HookAdminHome::DOMAIN_NAME + ) + ], + "required" => false, + "value" => HookAdminHome::getConfigValue(HookAdminHome::ACTIVATE_INFO, 0), + ) + ); + + $this->formBuilder->add( + "enabled-stats", + "checkbox", + array( + "label" => "Enabled default Home Stats", + "label_attr" => [ + "for" => "enabled-stats", + "help" => Translator::getInstance()->trans( + 'Check if you want show default Home Stats', + [], + HookAdminHome::DOMAIN_NAME + ) + ], + "required" => false, + "value" => HookAdminHome::getConfigValue(HookAdminHome::ACTIVATE_STATS, 0), + ) + ); + + + $this->formBuilder->add( + "enabled-sales", + "checkbox", + array( + "label" => "Enabled Sales Statistics", + "label_attr" => [ + "for" => "enabled-sales", + "help" => Translator::getInstance()->trans( + 'Check if you want show sales stats', + [], + HookAdminHome::DOMAIN_NAME + ) + ], + "required" => false, + "value" => HookAdminHome::getConfigValue(HookAdminHome::ACTIVATE_SALES, 0), + ) + ); + } + + public function getName() + { + return "hookadminhomeconfigform"; + } +} \ No newline at end of file diff --git a/local/modules/HookAdminHome/Hook/AdminHook.php b/local/modules/HookAdminHome/Hook/AdminHook.php new file mode 100644 index 00000000..c23377d9 --- /dev/null +++ b/local/modules/HookAdminHome/Hook/AdminHook.php @@ -0,0 +1,85 @@ + + */ +class AdminHook extends BaseHook +{ + public function blockStatistics(HookRenderEvent $event) + { + if (1 == HookAdminHome::getConfigValue(HookAdminHome::ACTIVATE_STATS, 1)) { + $event->add($this->render('block-statistics.html')); + } + + $event->add($this->render('hook-admin-home-config.html')); + + } + + public function blockStatisticsJs(HookRenderEvent $event) + { + if (1 == HookAdminHome::getConfigValue(HookAdminHome::ACTIVATE_STATS, 1)) { + $event->add($this->render('block-statistics-js.html')); + } + } + + public function blockSalesStatistics(HookRenderBlockEvent $event) + { + if (1 == HookAdminHome::getConfigValue(HookAdminHome::ACTIVATE_SALES, 1)) { + $content = trim($this->render("block-sales-statistics.html")); + if (!empty($content)) { + $event->add([ + "id" => "block-sales-statistics", + "title" => $this->trans("Sales statistics", [], HookAdminHome::DOMAIN_NAME), + "content" => $content + ]); + } + } + } + + public function blockNews(HookRenderBlockEvent $event) + { + if (1 == HookAdminHome::getConfigValue(HookAdminHome::ACTIVATE_NEWS, 1)) { + $content = trim($this->render("block-news.html")); + if (!empty($content)) { + $event->add([ + "id" => "block-news", + "title" => $this->trans("Thelia Github activity", [], HookAdminHome::DOMAIN_NAME), + "content" => $content + ]); + } + } + } + + public function blockTheliaInformation(HookRenderBlockEvent $event) + { + if (1 == HookAdminHome::getConfigValue(HookAdminHome::ACTIVATE_INFO, 1)) { + $content = trim($this->render("block-thelia-information.html")); + if (!empty($content)) { + $event->add([ + "id" => "block-thelia-information", + "title" => $this->trans("Thelia news", [], HookAdminHome::DOMAIN_NAME), + "content" => $content + ]); + } + } + } +} diff --git a/local/modules/HookAdminHome/Hook/HookAdminManager.php b/local/modules/HookAdminHome/Hook/HookAdminManager.php new file mode 100644 index 00000000..9c58a8a4 --- /dev/null +++ b/local/modules/HookAdminHome/Hook/HookAdminManager.php @@ -0,0 +1,15 @@ +add( + $this->render("admin-home-config.html") + ); + } +} \ No newline at end of file diff --git a/local/modules/HookAdminHome/HookAdminHome.php b/local/modules/HookAdminHome/HookAdminHome.php new file mode 100644 index 00000000..eb6b6754 --- /dev/null +++ b/local/modules/HookAdminHome/HookAdminHome.php @@ -0,0 +1,46 @@ + TemplateDefinition::BACK_OFFICE, + "code" => "hook_home_stats", + "title" => "Hook Home Stats", + "description" => "Hook to change default stats", + ) + ); + } +} diff --git a/local/modules/HookAdminHome/I18n/ar_SA.php b/local/modules/HookAdminHome/I18n/ar_SA.php new file mode 100644 index 00000000..26fc119c --- /dev/null +++ b/local/modules/HookAdminHome/I18n/ar_SA.php @@ -0,0 +1,5 @@ + 'إحصائيات عن الشهر و السنة %month/%year', +]; diff --git a/local/modules/HookAdminHome/I18n/backOffice/default/ar_SA.php b/local/modules/HookAdminHome/I18n/backOffice/default/ar_SA.php new file mode 100644 index 00000000..dafa0a35 --- /dev/null +++ b/local/modules/HookAdminHome/I18n/backOffice/default/ar_SA.php @@ -0,0 +1,11 @@ + 'تم إحباط الطلبات', + 'Average cart' => 'متوسط العربة', + 'Categories' => 'الفئات', + 'Click here' => 'انقر هنا', + 'Current version' => 'النسخة الحالية', + 'Customers' => 'العملاء', + 'Dashboard' => 'لوحة المعلومات', +]; diff --git a/local/modules/HookAdminHome/I18n/backOffice/default/cs_CZ.php b/local/modules/HookAdminHome/I18n/backOffice/default/cs_CZ.php new file mode 100644 index 00000000..b1fe273d --- /dev/null +++ b/local/modules/HookAdminHome/I18n/backOffice/default/cs_CZ.php @@ -0,0 +1,31 @@ + 'Aborted orders', + 'Average cart' => 'Average cart', + 'Categories' => 'Categories', + 'Click here' => 'Click here', + 'Current version' => 'Current version', + 'Customers' => 'Customers', + 'Dashboard' => 'Dashboard', + 'First orders' => 'First orders', + 'Latest version available' => 'Latest version available', + 'Lire la suite' => 'Lire la suite', + 'Loading Thelia lastest news...' => 'Loading Thelia lastest news...', + 'Loading...' => 'Loading...', + 'New customers' => 'New customers', + 'News' => 'News', + 'Offline products' => 'Offline products', + 'Online products' => 'Online products', + 'Orders' => 'Orders', + 'Overall sales' => 'Overall sales', + 'Previous month sales' => 'Previous month sales', + 'Previous year sales' => 'Previous year sales', + 'Products' => 'Products', + 'Sales' => 'Sales', + 'Sales excluding shipping' => 'Sales excluding shipping', + 'This month' => 'This month', + 'This year' => 'This year', + 'Today' => 'Today', + 'Yesterday sales' => 'Yesterday sales', +]; diff --git a/local/modules/HookAdminHome/I18n/backOffice/default/de_DE.php b/local/modules/HookAdminHome/I18n/backOffice/default/de_DE.php new file mode 100644 index 00000000..07620ee9 --- /dev/null +++ b/local/modules/HookAdminHome/I18n/backOffice/default/de_DE.php @@ -0,0 +1,30 @@ + 'Abgebrochene Bestellungen', + 'Average cart' => 'Durchschnittlichen Warenkorb', + 'Categories' => 'Kategorien', + 'Click here' => 'Hier Klicken', + 'Current version' => 'Aktuelle Version', + 'Customers' => 'Kunden', + 'Dashboard' => 'Dashboard', + 'First orders' => 'Erste Bestellungen', + 'Latest version available' => 'Neueste Version verfügbar', + 'Lire la suite' => 'Weiterlesen', + 'Loading Thelia lastest news...' => 'THELIAs neuesten Nachrichten Laden ...', + 'Loading...' => 'Laden...', + 'New customers' => 'Neue Kunde', + 'Offline products' => 'Offline Produkte', + 'Online products' => 'Online Produkte', + 'Orders' => 'Bestellungen', + 'Overall sales' => 'Gesamtverkäufe', + 'Previous month sales' => 'Vorheriger Monat Verkäufe', + 'Previous year sales' => 'Vorheriges Jahr Verkäufe', + 'Products' => 'Produkte', + 'Sales' => 'Verkäufe', + 'Sales excluding shipping' => 'Verkäufe ohne Lieferung', + 'This month' => 'Diesen Monat', + 'This year' => 'Dieses Jahr', + 'Today' => 'Heute', + 'Yesterday sales' => 'Verkäufe von Gestern', +]; diff --git a/local/modules/HookAdminHome/I18n/backOffice/default/en_US.php b/local/modules/HookAdminHome/I18n/backOffice/default/en_US.php new file mode 100644 index 00000000..5f375765 --- /dev/null +++ b/local/modules/HookAdminHome/I18n/backOffice/default/en_US.php @@ -0,0 +1,33 @@ + 'Aborted orders', + 'An error occurred while reading from JSON file' => 'An error occurred while reading from JSON file', + 'Average cart' => 'Average cart', + 'Categories' => 'Categories', + 'Click here' => 'Click here', + 'Current version' => 'Current version', + 'Customers' => 'Customers', + 'Dashboard' => 'Dashboard', + 'First orders' => 'First orders', + 'Latest version available' => 'Latest version available', + 'Loading Thelia lastest news...' => 'Loading Thelia lastest news...', + 'Loading...' => 'Loading...', + 'New customers' => 'New customers', + 'News' => 'News', + 'Offline products' => 'Offline products', + 'Online products' => 'Online products', + 'Orders' => 'Orders', + 'Overall sales' => 'Overall sales', + 'Previous month sales' => 'Previous month sales', + 'Previous year sales' => 'Previous year sales', + 'Products' => 'Products', + 'Read more' => 'Read more', + 'Sales' => 'Sales', + 'Sales excluding shipping' => 'Sales excluding shipping', + 'This month' => 'This month', + 'This year' => 'This year', + 'Today' => 'Today', + 'YYYY-MM' => 'YYYY-MM', + 'Yesterday sales' => 'Yesterday sales', +); diff --git a/local/modules/HookAdminHome/I18n/backOffice/default/es_ES.php b/local/modules/HookAdminHome/I18n/backOffice/default/es_ES.php new file mode 100644 index 00000000..6537481f --- /dev/null +++ b/local/modules/HookAdminHome/I18n/backOffice/default/es_ES.php @@ -0,0 +1,31 @@ + 'Pedidos abandonados', + 'Average cart' => 'Carrito medio', + 'Categories' => 'Categorías', + 'Click here' => 'Haz clic aquí', + 'Current version' => 'Versión actual', + 'Customers' => 'Clientes', + 'Dashboard' => 'Panel de Control', + 'First orders' => 'Primeros pedidos', + 'Latest version available' => 'Última versión disponible', + 'Lire la suite' => 'Leer más', + 'Loading Thelia lastest news...' => 'Carregant Thelia últimes notícies ...', + 'Loading...' => 'Carregant ...', + 'New customers' => 'Nuevos clientes', + 'News' => 'Noticias', + 'Offline products' => 'Productos fuera de línea', + 'Online products' => 'Productos en línea', + 'Orders' => 'Pedidos', + 'Overall sales' => 'Ventas totales', + 'Previous month sales' => 'Ventas del mes anterior', + 'Previous year sales' => 'Ventas del año anterior', + 'Products' => 'Productos', + 'Sales' => 'Ventas', + 'Sales excluding shipping' => 'Ventas sin el envio', + 'This month' => 'Este mes', + 'This year' => 'Este año', + 'Today' => 'Hoy', + 'Yesterday sales' => 'Ventas de ayer', +]; diff --git a/local/modules/HookAdminHome/I18n/backOffice/default/fr_FR.php b/local/modules/HookAdminHome/I18n/backOffice/default/fr_FR.php new file mode 100644 index 00000000..8582c93e --- /dev/null +++ b/local/modules/HookAdminHome/I18n/backOffice/default/fr_FR.php @@ -0,0 +1,34 @@ + 'Paniers abandonnés', + 'An error occurred while reading from JSON file' => 'Désolé, une erreur s\'est produite pendant la récupération des données.', + 'Average cart' => 'Panier moyen', + 'Categories' => 'Rubriques', + 'Click here' => 'Cliquez ici', + 'Current version' => 'Version en cours', + 'Customers' => 'Clients', + 'Dashboard' => 'Tableau de bord', + 'First orders' => 'Premières commandes', + 'Latest version available' => 'Dernière version disponible', + 'Loading Thelia lastest news...' => 'Chargement des dernières information Thelia...', + 'Loading...' => 'Chargement...', + 'New customers' => 'Nouveaux clients', + 'News' => 'Actualités', + 'Offline products' => 'Produits hors ligne', + 'Online products' => 'Produits en ligne', + 'Orders' => 'Commandes', + 'Overall sales' => 'Total des ventes', + 'Previous month sales' => 'Ventes du mois précédent', + 'Previous year sales' => 'Ventes de l\'année précédente', + 'Products' => 'Produits', + 'Read more' => 'Lire la suite', + 'Sales' => 'Ventes', + 'Sales excluding shipping' => 'Ventes hors frais de port', + 'This month' => 'Ce mois', + 'This year' => 'Cette année', + 'Today' => 'Aujourd\'hui', + 'YYYY-MM' => 'MM/YYYY', + 'Yesterday sales' => 'Ventes de la veille', + 'Loading Tweeter feed...' => 'Chargement du fil Tweeter...', +); diff --git a/local/modules/HookAdminHome/I18n/backOffice/default/it_IT.php b/local/modules/HookAdminHome/I18n/backOffice/default/it_IT.php new file mode 100644 index 00000000..de57bcf8 --- /dev/null +++ b/local/modules/HookAdminHome/I18n/backOffice/default/it_IT.php @@ -0,0 +1,32 @@ + 'Ordini annullati', + 'Average cart' => 'Carrello medio', + 'Categories' => 'Categorie', + 'Click here' => 'Clicca qui', + 'Current version' => 'Versione attuale', + 'Customers' => 'Clienti', + 'Dashboard' => 'Dashboard', + 'First orders' => 'Primi ordini', + 'Latest version available' => 'Ultima versione disponibile', + 'Lire la suite' => 'Per saperne di più', + 'Loading Thelia lastest news...' => 'Caricamento delle ultime notizie su Thelia...', + 'Loading...' => 'Caricamento...', + 'New customers' => 'Nuovi clienti', + 'News' => 'Notizie', + 'Offline products' => 'Prodotti non in linea', + 'Online products' => 'Prodotti online', + 'Orders' => 'Ordini', + 'Overall sales' => 'Vendite complessive', + 'Previous month sales' => 'Vendite del mese precedente', + 'Previous year sales' => 'Vendite dell\'anno precedente', + 'Products' => 'Prodotti', + 'Read more' => 'Per saperne di più', + 'Sales' => 'Vendite', + 'Sales excluding shipping' => 'Vendite escluse spese di spedizione', + 'This month' => 'Questo mese', + 'This year' => 'Quest\'anno', + 'Today' => 'Oggi', + 'Yesterday sales' => 'Vendite di ieri', +]; diff --git a/local/modules/HookAdminHome/I18n/backOffice/default/pt_BR.php b/local/modules/HookAdminHome/I18n/backOffice/default/pt_BR.php new file mode 100644 index 00000000..7daaaee4 --- /dev/null +++ b/local/modules/HookAdminHome/I18n/backOffice/default/pt_BR.php @@ -0,0 +1,6 @@ + 'Ordens abortadas', + 'Click here' => 'Clique aqui', +]; diff --git a/local/modules/HookAdminHome/I18n/backOffice/default/ru_RU.php b/local/modules/HookAdminHome/I18n/backOffice/default/ru_RU.php new file mode 100644 index 00000000..fc9b81ad --- /dev/null +++ b/local/modules/HookAdminHome/I18n/backOffice/default/ru_RU.php @@ -0,0 +1,31 @@ + 'Отмененные заказы', + 'Average cart' => 'Средняя корзина', + 'Categories' => 'Категории', + 'Click here' => 'Нажмите здесь', + 'Current version' => 'Текущая версия', + 'Customers' => 'Клиенты', + 'Dashboard' => 'Приборная панель', + 'First orders' => 'Первые заказы', + 'Latest version available' => 'Последняя доступная версия', + 'Loading Thelia lastest news...' => 'Загрузка последних новостей Thelia...', + 'Loading...' => 'Загрузка...', + 'New customers' => 'Новые клиенты', + 'News' => 'Новости', + 'Offline products' => 'Товары выкл.', + 'Online products' => 'Товары вкл.', + 'Orders' => 'Заказы', + 'Overall sales' => 'Всего продаж', + 'Previous month sales' => 'Продажи в предыдущем месяце', + 'Previous year sales' => 'Продажи в предыдущем году', + 'Products' => 'Товары', + 'Read more' => 'Читать далее', + 'Sales' => 'Продажи', + 'Sales excluding shipping' => 'Продаж без доставки', + 'This month' => 'В этом месяце', + 'This year' => 'В этом году', + 'Today' => 'Сегодня', + 'Yesterday sales' => 'Вчерашние продажи', +]; diff --git a/local/modules/HookAdminHome/I18n/backOffice/default/tr_TR.php b/local/modules/HookAdminHome/I18n/backOffice/default/tr_TR.php new file mode 100644 index 00000000..6fcb84a3 --- /dev/null +++ b/local/modules/HookAdminHome/I18n/backOffice/default/tr_TR.php @@ -0,0 +1,31 @@ + 'İptal edilen siparişler', + 'Average cart' => 'Sepet Ortalaması', + 'Categories' => 'Katogoriler', + 'Click here' => 'Buraya tıklayın', + 'Current version' => 'Güncel Sürüm', + 'Customers' => 'müşteriler', + 'Dashboard' => 'Kontrol paneli', + 'First orders' => 'İlk emir', + 'Latest version available' => 'En son yorum elde edilebilir', + 'Lire la suite' => 'Devamını okuyun', + 'Loading Thelia lastest news...' => 'Thelia yükleme son haberler...', + 'Loading...' => 'Yükleneniyor…...', + 'New customers' => 'Yeni Müşteriler', + 'News' => 'Yeni Haberler', + 'Offline products' => 'Çevrimdışı ürünler', + 'Online products' => 'Online Ürünler', + 'Orders' => 'siparişler', + 'Overall sales' => 'Genel satış', + 'Previous month sales' => 'Önceki ay satış', + 'Previous year sales' => 'Önceki yılın satış', + 'Products' => 'ürün', + 'Sales' => 'Satış', + 'Sales excluding shipping' => 'Nakliye hariç satış', + 'This month' => 'Bu Ay', + 'This year' => 'Bu yıl', + 'Today' => 'bugün', + 'Yesterday sales' => 'Dün satış', +]; diff --git a/local/modules/HookAdminHome/I18n/cs_CZ.php b/local/modules/HookAdminHome/I18n/cs_CZ.php new file mode 100644 index 00000000..2ff4e47b --- /dev/null +++ b/local/modules/HookAdminHome/I18n/cs_CZ.php @@ -0,0 +1,7 @@ + 'Sales statistics', + 'Stats on %month/%year' => 'Stats on %month/%year', + 'Thelia informations' => 'Thelia information', +]; diff --git a/local/modules/HookAdminHome/I18n/de_DE.php b/local/modules/HookAdminHome/I18n/de_DE.php new file mode 100644 index 00000000..4405c981 --- /dev/null +++ b/local/modules/HookAdminHome/I18n/de_DE.php @@ -0,0 +1,7 @@ + 'Verkaufsstatistiken', + 'Stats on %month/%year' => 'Statistiken für %month/%year', + 'Thelia informations' => 'Thelias Informationen', +]; diff --git a/local/modules/HookAdminHome/I18n/en_US.php b/local/modules/HookAdminHome/I18n/en_US.php new file mode 100644 index 00000000..a4d812ee --- /dev/null +++ b/local/modules/HookAdminHome/I18n/en_US.php @@ -0,0 +1,7 @@ + 'Stats on %month/%year', + 'Thelia informations' => 'Thelia information', + 'Sales statistics' => 'Sales statistics', +); diff --git a/local/modules/HookAdminHome/I18n/es_ES.php b/local/modules/HookAdminHome/I18n/es_ES.php new file mode 100644 index 00000000..fabace8e --- /dev/null +++ b/local/modules/HookAdminHome/I18n/es_ES.php @@ -0,0 +1,6 @@ + 'Estadísticas de ventas', + 'Thelia informations' => 'información sobre Thelia', +]; diff --git a/local/modules/HookAdminHome/I18n/fr_FR.php b/local/modules/HookAdminHome/I18n/fr_FR.php new file mode 100644 index 00000000..d39ebe1c --- /dev/null +++ b/local/modules/HookAdminHome/I18n/fr_FR.php @@ -0,0 +1,8 @@ + 'Statistiques de vente', + 'Stats on %month/%year' => 'Statistiques pour %month/%year', + 'Thelia Github activity' => 'Thelia sur Github', + 'Thelia news' => 'Actualité Thelia', +]; diff --git a/local/modules/HookAdminHome/I18n/id_ID.php b/local/modules/HookAdminHome/I18n/id_ID.php new file mode 100644 index 00000000..8cbc43ab --- /dev/null +++ b/local/modules/HookAdminHome/I18n/id_ID.php @@ -0,0 +1,5 @@ + 'Stats on %month/%year', +]; diff --git a/local/modules/HookAdminHome/I18n/it_IT.php b/local/modules/HookAdminHome/I18n/it_IT.php new file mode 100644 index 00000000..dcab80d9 --- /dev/null +++ b/local/modules/HookAdminHome/I18n/it_IT.php @@ -0,0 +1,6 @@ + 'Statistiche di vendita', + 'Thelia informations' => 'Thelia informazioni', +]; diff --git a/local/modules/HookAdminHome/I18n/ru_RU.php b/local/modules/HookAdminHome/I18n/ru_RU.php new file mode 100644 index 00000000..04f63783 --- /dev/null +++ b/local/modules/HookAdminHome/I18n/ru_RU.php @@ -0,0 +1,7 @@ + 'Статистика продаж', + 'Stats on %month/%year' => 'Статистика за %month/%year', + 'Thelia informations' => 'Информация о Thelia', +]; diff --git a/local/modules/HookAdminHome/I18n/tr_TR.php b/local/modules/HookAdminHome/I18n/tr_TR.php new file mode 100644 index 00000000..b8d17e2e --- /dev/null +++ b/local/modules/HookAdminHome/I18n/tr_TR.php @@ -0,0 +1,7 @@ + 'Satış istatistikleri', + 'Stats on %month/%year' => '%month/%year istatistikleri', + 'Thelia informations' => 'Thelia bilgi', +]; diff --git a/local/modules/HookAdminHome/LICENSE.txt b/local/modules/HookAdminHome/LICENSE.txt new file mode 100644 index 00000000..65c5ca88 --- /dev/null +++ b/local/modules/HookAdminHome/LICENSE.txt @@ -0,0 +1,165 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + + This version of the GNU Lesser General Public License incorporates +the terms and conditions of version 3 of the GNU General Public +License, supplemented by the additional permissions listed below. + + 0. Additional Definitions. + + As used herein, "this License" refers to version 3 of the GNU Lesser +General Public License, and the "GNU GPL" refers to version 3 of the GNU +General Public License. + + "The Library" refers to a covered work governed by this License, +other than an Application or a Combined Work as defined below. + + An "Application" is any work that makes use of an interface provided +by the Library, but which is not otherwise based on the Library. +Defining a subclass of a class defined by the Library is deemed a mode +of using an interface provided by the Library. + + A "Combined Work" is a work produced by combining or linking an +Application with the Library. The particular version of the Library +with which the Combined Work was made is also called the "Linked +Version". + + The "Minimal Corresponding Source" for a Combined Work means the +Corresponding Source for the Combined Work, excluding any source code +for portions of the Combined Work that, considered in isolation, are +based on the Application, and not on the Linked Version. + + The "Corresponding Application Code" for a Combined Work means the +object code and/or source code for the Application, including any data +and utility programs needed for reproducing the Combined Work from the +Application, but excluding the System Libraries of the Combined Work. + + 1. Exception to Section 3 of the GNU GPL. + + You may convey a covered work under sections 3 and 4 of this License +without being bound by section 3 of the GNU GPL. + + 2. Conveying Modified Versions. + + If you modify a copy of the Library, and, in your modifications, a +facility refers to a function or data to be supplied by an Application +that uses the facility (other than as an argument passed when the +facility is invoked), then you may convey a copy of the modified +version: + + a) under this License, provided that you make a good faith effort to + ensure that, in the event an Application does not supply the + function or data, the facility still operates, and performs + whatever part of its purpose remains meaningful, or + + b) under the GNU GPL, with none of the additional permissions of + this License applicable to that copy. + + 3. Object Code Incorporating Material from Library Header Files. + + The object code form of an Application may incorporate material from +a header file that is part of the Library. You may convey such object +code under terms of your choice, provided that, if the incorporated +material is not limited to numerical parameters, data structure +layouts and accessors, or small macros, inline functions and templates +(ten or fewer lines in length), you do both of the following: + + a) Give prominent notice with each copy of the object code that the + Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the object code with a copy of the GNU GPL and this license + document. + + 4. Combined Works. + + You may convey a Combined Work under terms of your choice that, +taken together, effectively do not restrict modification of the +portions of the Library contained in the Combined Work and reverse +engineering for debugging such modifications, if you also do each of +the following: + + a) Give prominent notice with each copy of the Combined Work that + the Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the Combined Work with a copy of the GNU GPL and this license + document. + + c) For a Combined Work that displays copyright notices during + execution, include the copyright notice for the Library among + these notices, as well as a reference directing the user to the + copies of the GNU GPL and this license document. + + d) Do one of the following: + + 0) Convey the Minimal Corresponding Source under the terms of this + License, and the Corresponding Application Code in a form + suitable for, and under terms that permit, the user to + recombine or relink the Application with a modified version of + the Linked Version to produce a modified Combined Work, in the + manner specified by section 6 of the GNU GPL for conveying + Corresponding Source. + + 1) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (a) uses at run time + a copy of the Library already present on the user's computer + system, and (b) will operate properly with a modified version + of the Library that is interface-compatible with the Linked + Version. + + e) Provide Installation Information, but only if you would otherwise + be required to provide such information under section 6 of the + GNU GPL, and only to the extent that such information is + necessary to install and execute a modified version of the + Combined Work produced by recombining or relinking the + Application with a modified version of the Linked Version. (If + you use option 4d0, the Installation Information must accompany + the Minimal Corresponding Source and Corresponding Application + Code. If you use option 4d1, you must provide the Installation + Information in the manner specified by section 6 of the GNU GPL + for conveying Corresponding Source.) + + 5. Combined Libraries. + + You may place library facilities that are a work based on the +Library side by side in a single library together with other library +facilities that are not Applications and are not covered by this +License, and convey such a combined library under terms of your +choice, if you do both of the following: + + a) Accompany the combined library with a copy of the same work based + on the Library, uncombined with any other library facilities, + conveyed under the terms of this License. + + b) Give prominent notice with the combined library that part of it + is a work based on the Library, and explaining where to find the + accompanying uncombined form of the same work. + + 6. Revised Versions of the GNU Lesser General Public License. + + The Free Software Foundation may publish revised and/or new versions +of the GNU Lesser General Public License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. + + Each version is given a distinguishing version number. If the +Library as you received it specifies that a certain numbered version +of the GNU Lesser General Public License "or any later version" +applies to it, you have the option of following the terms and +conditions either of that published version or of any later version +published by the Free Software Foundation. If the Library as you +received it does not specify a version number of the GNU Lesser +General Public License, you may choose any version of the GNU Lesser +General Public License ever published by the Free Software Foundation. + + If the Library as you received it specifies that a proxy can decide +whether future versions of the GNU Lesser General Public License shall +apply, that proxy's public statement of acceptance of any version is +permanent authorization for you to choose that version for the +Library. diff --git a/local/modules/HookAdminHome/composer.json b/local/modules/HookAdminHome/composer.json new file mode 100644 index 00000000..d5921a2c --- /dev/null +++ b/local/modules/HookAdminHome/composer.json @@ -0,0 +1,11 @@ +{ + "name": "thelia/hook-admin-home-module", + "license": "LGPL-3.0+", + "type": "thelia-module", + "require": { + "thelia/installer": "~1.1" + }, + "extra": { + "installer-name": "HookAdminHome" + } +} \ No newline at end of file diff --git a/local/modules/HookAdminHome/templates/backOffice/default/admin-home-config.html b/local/modules/HookAdminHome/templates/backOffice/default/admin-home-config.html new file mode 100644 index 00000000..a8fe8d9e --- /dev/null +++ b/local/modules/HookAdminHome/templates/backOffice/default/admin-home-config.html @@ -0,0 +1,87 @@ +
    +
    +
    + {intl l="Hook Admin Home config"} +
    +
    +
    +
    +
    + + {form name="hookadminhome.config.form"} + + + {form_hidden_fields} + + {form_field form=$form field="enabled-stats"} +
    + + {if ! empty($label_attr.help)} + {$label_attr.help} + {/if} +
    + {/form_field} + + {form_field form=$form field="enabled-news"} +
    + + {if ! empty($label_attr.help)} + {$label_attr.help} + {/if} +
    + {/form_field} + + {form_field form=$form field="enabled-sales"} +
    + + {if ! empty($label_attr.help)} + {$label_attr.help} + {/if} +
    + {/form_field} + + {form_field form=$form field="enabled-info"} +
    + + {if ! empty($label_attr.help)} + {$label_attr.help} + {/if} +
    + {/form_field} + + + + {/form} +
    +
    +
    + + \ No newline at end of file diff --git a/local/modules/HookAdminHome/templates/backOffice/default/ajax/thelia_news_feed.html b/local/modules/HookAdminHome/templates/backOffice/default/ajax/thelia_news_feed.html new file mode 100644 index 00000000..8423e59d --- /dev/null +++ b/local/modules/HookAdminHome/templates/backOffice/default/ajax/thelia_news_feed.html @@ -0,0 +1,29 @@ +{* this template is loaded via Ajax in the login page, to prevent login page slowdown *} + +{* Set the default translation domain, that will be used by intl when the 'd' parameter is not set *} +{default_translation_domain domain='hookadminhome.bo.default'} + +
    + {loop type="feed" name="thelia_feeds" url="http://thelia.net/feeds/?lang={$lang_code}" limit="6"} + +
    + +
    +
    + {* we use unescape:"htmlall" to unescape var before truncate, to prevent a cut in the middel of an HTML entity, eg &ea... *} +

    {$DESCRIPTION|strip_tags|unescape:"htmlall"|truncate:250:"...":true nofilter}

    +
    + +
    +
    + + {/loop} +
    diff --git a/local/modules/HookAdminHome/templates/backOffice/default/assets/css/home.css b/local/modules/HookAdminHome/templates/backOffice/default/assets/css/home.css new file mode 100644 index 00000000..611f6228 --- /dev/null +++ b/local/modules/HookAdminHome/templates/backOffice/default/assets/css/home.css @@ -0,0 +1 @@ +#block-information a{color:#8A8A8A}.stats{border-right:1px solid #f0f0f0;text-align:center}.stats:last-child{border-right:none}.stats h2{margin-top:0;margin-bottom:5px;font-size:30px}.stats p{margin-top:0;text-transform:uppercase;font-size:12px}@media (max-width:991px){.stats{margin-bottom:10px}.stats:nth-child(3){border-right:none}}.homepage #date-picker{text-align:center;} \ No newline at end of file diff --git a/local/modules/HookAdminHome/templates/backOffice/default/assets/less/home.less b/local/modules/HookAdminHome/templates/backOffice/default/assets/less/home.less new file mode 100644 index 00000000..a87eaab0 --- /dev/null +++ b/local/modules/HookAdminHome/templates/backOffice/default/assets/less/home.less @@ -0,0 +1,45 @@ +@import "../../../../../../../../templates/backOffice/default/assets/less/bootstrap/variables.less"; +@import "../../../../../../../../templates/backOffice/default/assets/less/thelia/variables.less"; + +#block-information { + a { + color: #8A8A8A; + } +} + +.stats { + border-right: 1px solid @table-border-color; + text-align: center; + + &:last-child { + border-right: none; + } + + h2 { + margin-top: 0; + margin-bottom: 5px; + font-size: 30px; + } + + p { + margin-top: 0; + text-transform: uppercase; + font-size: @font-size-base - 1; // 12px + } +} + +@media (max-width: @screen-sm-max) { + .stats { + margin-bottom: 10px; + + &:nth-child(3) { + border-right: none; + } + } +} + +.homepage { + #date-picker { + text-align: center; + } +} \ No newline at end of file diff --git a/local/modules/HookAdminHome/templates/backOffice/default/block-information.html b/local/modules/HookAdminHome/templates/backOffice/default/block-information.html new file mode 100644 index 00000000..25f09269 --- /dev/null +++ b/local/modules/HookAdminHome/templates/backOffice/default/block-information.html @@ -0,0 +1,59 @@ +{* Do not display shop information block if user none of the required authorizations *} + +{capture name="shop_information_block_content"} + {loop type="auth" name="can_view" role="ADMIN" resource="admin.customer" access="VIEW"} + + {/loop} + + {loop type="auth" name="can_view" role="ADMIN" resource="admin.category" access="VIEW"} + + {/loop} + + {loop type="auth" name="can_view" role="ADMIN" resource="admin.product" access="VIEW"} + + + + {/loop} + + {loop type="auth" name="can_view" role="ADMIN" resource="admin.order" access="VIEW"} + + {/loop} +{/capture} + +{if trim($smarty.capture.shop_information_block_content) ne ""} +
    +
    + {$smarty.capture.shop_information_block_content nofilter} +
    +
    +{/if} \ No newline at end of file diff --git a/local/modules/HookAdminHome/templates/backOffice/default/block-month-sales-statistics.html b/local/modules/HookAdminHome/templates/backOffice/default/block-month-sales-statistics.html new file mode 100644 index 00000000..57f72a60 --- /dev/null +++ b/local/modules/HookAdminHome/templates/backOffice/default/block-month-sales-statistics.html @@ -0,0 +1,48 @@ +{loop type="currency" name="default-currency" default_only="1"} +{$defaultCurrency = $SYMBOL} +{/loop} + +{if empty($startDate)}{$startDate = 'this_month'}{/if} +{if empty($startDate)}{$startDate = 'this_month'}{/if} + +{if empty($prevMonthStartDate)}{$prevMonthStartDate = 'last_month'}{/if} +{if empty($prevMonthEndDate)}{$prevMonthEndDate = 'last_month'}{/if} + +
    + + + + + + + + + + + + + + + + + + + + + + + +
    {intl l="Overall sales" d='hookadminhome.bo.default'}{format_money number={stats key="sales" startDate=$startDate endDate=$endDate} symbol=$defaultCurrency}
    {intl l="Sales excluding shipping" d='hookadminhome.bo.default'} + {$salesNoShipping = {stats key="sales" startDate=$startDate endDate=$endDate includeShipping="false"}} + {format_money number=$salesNoShipping symbol=$defaultCurrency} +
    {intl l="Previous month sales" d='hookadminhome.bo.default'}{format_money number={stats key="sales" startDate=$prevMonthStartDate endDate=$prevMonthEndDate} symbol=$defaultCurrency}
    {intl l="Orders" d='hookadminhome.bo.default'} + {$orderCount = {stats key="orders" startDate=$startDate endDate=$endDate}} + {$orderCount} +
    {intl l="Average cart" d='hookadminhome.bo.default'} + {if $orderCount == 0} + {format_money number=0 symbol=$defaultCurrency} + {else} + {format_money number={($salesNoShipping/$orderCount)|round:"2"} symbol=$defaultCurrency} + {/if} +
    +
    \ No newline at end of file diff --git a/local/modules/HookAdminHome/templates/backOffice/default/block-news-js.html b/local/modules/HookAdminHome/templates/backOffice/default/block-news-js.html new file mode 100644 index 00000000..d18e1f92 --- /dev/null +++ b/local/modules/HookAdminHome/templates/backOffice/default/block-news-js.html @@ -0,0 +1,7 @@ +{loop type="auth" name="can_view" role="ADMIN" module="HookAdminHome" access="VIEW"} + +{/loop} \ No newline at end of file diff --git a/local/modules/HookAdminHome/templates/backOffice/default/block-news.html b/local/modules/HookAdminHome/templates/backOffice/default/block-news.html new file mode 100644 index 00000000..97bd6f99 --- /dev/null +++ b/local/modules/HookAdminHome/templates/backOffice/default/block-news.html @@ -0,0 +1,5 @@ +{loop type="auth" name="can_view" role="ADMIN" module="HookAdminHome" access="VIEW"} +
    +
    {intl l="Loading Thelia lastest news..." d='hookadminhome.bo.default'}
    +
    +{/loop} \ No newline at end of file diff --git a/local/modules/HookAdminHome/templates/backOffice/default/block-sales-statistics.html b/local/modules/HookAdminHome/templates/backOffice/default/block-sales-statistics.html new file mode 100644 index 00000000..753173f8 --- /dev/null +++ b/local/modules/HookAdminHome/templates/backOffice/default/block-sales-statistics.html @@ -0,0 +1,100 @@ +{loop type="auth" name="can_view" role="ADMIN" resource="admin.order" access="VIEW"} + +{loop type="currency" name="default-currency" default_only="1"} +{$defaultCurrency = $SYMBOL} +{/loop} +
    +
    +
    + + + + + + + + + + + + + + + + + + + + + + + +
    {intl l="Overall sales" d='hookadminhome.bo.default'}{format_money number={stats key="sales" startDate="today" endDate="today"} symbol=$defaultCurrency}
    {intl l="Sales excluding shipping" d='hookadminhome.bo.default'} + {$salesNoShipping = {stats key="sales" startDate="today" endDate="today" includeShipping="false"}} + {format_money number=$salesNoShipping symbol=$defaultCurrency} +
    {intl l="Yesterday sales" d='hookadminhome.bo.default'}{format_money number={stats key="sales" startDate="yesterday" endDate="yesterday"} symbol=$defaultCurrency}
    {intl l="Orders" d='hookadminhome.bo.default'} + {$orderCount = {stats key="orders" startDate="today" endDate="today"}} + {$orderCount} +
    {intl l="Average cart" d='hookadminhome.bo.default'} + {if $orderCount == 0} + {format_money number=0 symbol=$defaultCurrency} + {else} + {format_money number={($salesNoShipping/$orderCount)|round:"2"} symbol=$defaultCurrency} + {/if} +
    +
    +
    + +
    + {include file="block-month-sales-statistics.html"} +
    + +
    +
    + + + + + + + + + + + + + + + + + + + + + + + +
    {intl l="Overall sales" d='hookadminhome.bo.default'}{format_money number={stats key="sales" startDate="this_year" endDate="this_year"} symbol=$defaultCurrency}
    {intl l="Sales excluding shipping" d='hookadminhome.bo.default'} + {$salesNoShipping = {stats key="sales" startDate="this_year" endDate="this_year" includeShipping="false"}} + {format_money number=$salesNoShipping symbol=$defaultCurrency} +
    {intl l="Previous year sales" d='hookadminhome.bo.default'}{format_money number={stats key="sales" startDate="last_year" endDate="last_year"} symbol=$defaultCurrency}
    {intl l="Orders" d='hookadminhome.bo.default'} + {$orderCount = {stats key="orders" startDate="this_year" endDate="this_year"}} + {$orderCount} +
    {intl l="Average cart" d='hookadminhome.bo.default'} + {if $orderCount == 0} + {format_money number=0 symbol=$defaultCurrency} + {else} + {format_money number={($salesNoShipping/$orderCount)|round:"2"} symbol=$defaultCurrency} + {/if} +
    +
    +
    +
    +{/loop} \ No newline at end of file diff --git a/local/modules/HookAdminHome/templates/backOffice/default/block-statistics-js.html b/local/modules/HookAdminHome/templates/backOffice/default/block-statistics-js.html new file mode 100644 index 00000000..b346c47d --- /dev/null +++ b/local/modules/HookAdminHome/templates/backOffice/default/block-statistics-js.html @@ -0,0 +1,207 @@ + + + + + + + \ No newline at end of file diff --git a/local/modules/HookAdminHome/templates/backOffice/default/block-statistics.html b/local/modules/HookAdminHome/templates/backOffice/default/block-statistics.html new file mode 100644 index 00000000..e29e7135 --- /dev/null +++ b/local/modules/HookAdminHome/templates/backOffice/default/block-statistics.html @@ -0,0 +1,34 @@ +{loop type="auth" name="can_view" role="ADMIN" resource="admin.order" access="VIEW"} +
    + +
    + {intl l='Dashboard' d='hookadminhome.bo.default'} +
    + + + + + + + +
    +
    + +
    +
    + + + + + +
    +
    + +
    + +
    +
    +
    + +
    +{/loop} \ No newline at end of file diff --git a/local/modules/HookAdminHome/templates/backOffice/default/block-thelia-information.html b/local/modules/HookAdminHome/templates/backOffice/default/block-thelia-information.html new file mode 100644 index 00000000..375a7815 --- /dev/null +++ b/local/modules/HookAdminHome/templates/backOffice/default/block-thelia-information.html @@ -0,0 +1,25 @@ +{loop type="auth" name="can_view" role="ADMIN" module="HookAdminHome" access="VIEW"} +
    + + + + + + + + + + + +
    {intl l="Current version" d='hookadminhome.bo.default'}{$THELIA_VERSION}
    {intl l="Latest version available" d='hookadminhome.bo.default'}{intl l="Loading..." d='hookadminhome.bo.default'}
    +
    +{/loop} + + diff --git a/local/modules/HookAdminHome/templates/backOffice/default/hook-admin-home-config.html b/local/modules/HookAdminHome/templates/backOffice/default/hook-admin-home-config.html new file mode 100644 index 00000000..2ce7e24c --- /dev/null +++ b/local/modules/HookAdminHome/templates/backOffice/default/hook-admin-home-config.html @@ -0,0 +1 @@ +{hook name="hook_home_stats" location="hook_home_stats"} \ No newline at end of file diff --git a/local/modules/HookAnalytics/Config/config.xml b/local/modules/HookAnalytics/Config/config.xml new file mode 100644 index 00000000..57a6cb0f --- /dev/null +++ b/local/modules/HookAnalytics/Config/config.xml @@ -0,0 +1,21 @@ + + + + + +
    + + + + + + + + + + + + + \ No newline at end of file diff --git a/local/modules/HookAnalytics/Config/module.xml b/local/modules/HookAnalytics/Config/module.xml new file mode 100644 index 00000000..30cef7a9 --- /dev/null +++ b/local/modules/HookAnalytics/Config/module.xml @@ -0,0 +1,24 @@ + + + HookAnalytics\HookAnalytics + + Analytics (Google) + + + Statistiques (Google) + + + en_US + fr_FR + + 2.4.3 + + Julien Chanséaume + jchanseaume@openstudio.fr + + classic + 2.4.3 + alpha + diff --git a/local/modules/HookAnalytics/Config/routing.xml b/local/modules/HookAnalytics/Config/routing.xml new file mode 100644 index 00000000..269697d7 --- /dev/null +++ b/local/modules/HookAnalytics/Config/routing.xml @@ -0,0 +1,10 @@ + + + + + HookAnalytics\Controller\Configuration::saveAction + + + diff --git a/local/modules/HookAnalytics/Controller/Configuration.php b/local/modules/HookAnalytics/Controller/Configuration.php new file mode 100644 index 00000000..dc083f55 --- /dev/null +++ b/local/modules/HookAnalytics/Controller/Configuration.php @@ -0,0 +1,57 @@ + + */ +class Configuration extends BaseAdminController { + + public function saveAction() + { + + if (null !== $response = $this->checkAuth(array(AdminResources::MODULE), array('hookanalytics'), AccessManager::UPDATE)) { + return $response; + } + + $form = new \HookAnalytics\Form\Configuration($this->getRequest()); + $resp = array( + "error" => 0, + "message" => "" + ); + $response=null; + + try { + $vform = $this->validateForm($form); + $data = $vform->getData(); + + ConfigQuery::write("hookanalytics_trackingcode", $data["trackingcode"], false, true); + + } catch (\Exception $e) { + $resp["error"] = 1; + $resp["message"] = $e->getMessage(); + } + + return JsonResponse::create($resp); + } + +} \ No newline at end of file diff --git a/local/modules/HookAnalytics/Form/Configuration.php b/local/modules/HookAnalytics/Form/Configuration.php new file mode 100644 index 00000000..01db6191 --- /dev/null +++ b/local/modules/HookAnalytics/Form/Configuration.php @@ -0,0 +1,54 @@ + + */ +class Configuration extends BaseForm { + + protected function buildForm() + { + $form = $this->formBuilder; + + $value = ConfigQuery::read("hookanalytics_trackingcode", ""); + $form->add( + "trackingcode", + "text", + array( + 'data' => $value, + 'label' => Translator::getInstance()->trans("Tracking Code"), + 'label_attr' => array( + 'for' => "trackingcode" + ), + ) + ); + + } + + /** + * @return string the name of you form. This name must be unique + */ + public function getName() + { + return "hookanalytics"; + } + + +} \ No newline at end of file diff --git a/local/modules/HookAnalytics/Hook/FrontHook.php b/local/modules/HookAnalytics/Hook/FrontHook.php new file mode 100644 index 00000000..11bd3c6c --- /dev/null +++ b/local/modules/HookAnalytics/Hook/FrontHook.php @@ -0,0 +1,33 @@ + + */ +class FrontHook extends BaseHook { + + public function onMainHeadBottom(HookRenderEvent $event) + { + $value = trim(ConfigQuery::read("hookanalytics_trackingcode", "")); + if ("" != $value){ + $event->add($value); + } + } +} \ No newline at end of file diff --git a/local/modules/HookAnalytics/HookAnalytics.php b/local/modules/HookAnalytics/HookAnalytics.php new file mode 100644 index 00000000..2636e381 --- /dev/null +++ b/local/modules/HookAnalytics/HookAnalytics.php @@ -0,0 +1,20 @@ + 'Ein Fehler ist aufgetreten', + 'Edit your analytics configuration.' => 'Analytics-Konfiguration bearbeiten.', + 'Save' => 'Speichern', +]; diff --git a/local/modules/HookAnalytics/I18n/backOffice/default/en_US.php b/local/modules/HookAnalytics/I18n/backOffice/default/en_US.php new file mode 100644 index 00000000..ef8b1f98 --- /dev/null +++ b/local/modules/HookAnalytics/I18n/backOffice/default/en_US.php @@ -0,0 +1,7 @@ + 'An error occured', + 'Edit your analytics configuration.' => 'Edit your analytics configuration.', + 'Save' => 'Save', +); diff --git a/local/modules/HookAnalytics/I18n/backOffice/default/fr_FR.php b/local/modules/HookAnalytics/I18n/backOffice/default/fr_FR.php new file mode 100644 index 00000000..56712bd3 --- /dev/null +++ b/local/modules/HookAnalytics/I18n/backOffice/default/fr_FR.php @@ -0,0 +1,7 @@ + 'Une erreur est survenue', + 'Edit your analytics configuration.' => 'Modifier la configuration des statistiques', + 'Save' => ' Enregistrer', +]; diff --git a/local/modules/HookAnalytics/I18n/backOffice/default/it_IT.php b/local/modules/HookAnalytics/I18n/backOffice/default/it_IT.php new file mode 100644 index 00000000..0c59bda5 --- /dev/null +++ b/local/modules/HookAnalytics/I18n/backOffice/default/it_IT.php @@ -0,0 +1,5 @@ + 'Salvare', +]; diff --git a/local/modules/HookAnalytics/I18n/backOffice/default/ru_RU.php b/local/modules/HookAnalytics/I18n/backOffice/default/ru_RU.php new file mode 100644 index 00000000..ed83bc56 --- /dev/null +++ b/local/modules/HookAnalytics/I18n/backOffice/default/ru_RU.php @@ -0,0 +1,7 @@ + 'Произошла ошибка', + 'Edit your analytics configuration.' => 'Редактировать вашу конфигурацию аналитики', + 'Save' => 'Сохранить', +); diff --git a/local/modules/HookAnalytics/I18n/backOffice/default/tr_TR.php b/local/modules/HookAnalytics/I18n/backOffice/default/tr_TR.php new file mode 100644 index 00000000..8e913080 --- /dev/null +++ b/local/modules/HookAnalytics/I18n/backOffice/default/tr_TR.php @@ -0,0 +1,7 @@ + 'Bir hata meydana geldi', + 'Edit your analytics configuration.' => 'Analytics yapılandırmanızı düzenleyin.', + 'Save' => 'kaydet', +]; diff --git a/local/modules/HookAnalytics/I18n/de_DE.php b/local/modules/HookAnalytics/I18n/de_DE.php new file mode 100644 index 00000000..e1b30511 --- /dev/null +++ b/local/modules/HookAnalytics/I18n/de_DE.php @@ -0,0 +1,5 @@ + 'Tracking-Code', +]; diff --git a/local/modules/HookAnalytics/I18n/en_US.php b/local/modules/HookAnalytics/I18n/en_US.php new file mode 100644 index 00000000..ba8939d7 --- /dev/null +++ b/local/modules/HookAnalytics/I18n/en_US.php @@ -0,0 +1,5 @@ + 'Tracking Code', +); diff --git a/local/modules/HookAnalytics/I18n/fr_FR.php b/local/modules/HookAnalytics/I18n/fr_FR.php new file mode 100644 index 00000000..ab7c10b8 --- /dev/null +++ b/local/modules/HookAnalytics/I18n/fr_FR.php @@ -0,0 +1,5 @@ + 'Code de suivi', +]; diff --git a/local/modules/HookAnalytics/I18n/frontOffice/default/de_DE.php b/local/modules/HookAnalytics/I18n/frontOffice/default/de_DE.php new file mode 100644 index 00000000..938a9f4a --- /dev/null +++ b/local/modules/HookAnalytics/I18n/frontOffice/default/de_DE.php @@ -0,0 +1,10 @@ + 'Facebook', + 'Google+' => 'Google+', + 'Instagram' => 'Instagram', + 'RSS' => 'RSS-Feed', + 'Twitter' => 'Twitter', + 'Youtube' => 'YouTube', +]; diff --git a/local/modules/HookAnalytics/I18n/frontOffice/default/en_US.php b/local/modules/HookAnalytics/I18n/frontOffice/default/en_US.php new file mode 100644 index 00000000..534a4d03 --- /dev/null +++ b/local/modules/HookAnalytics/I18n/frontOffice/default/en_US.php @@ -0,0 +1,10 @@ + 'Facebook', + 'Google+' => 'Google+', + 'Instagram' => 'Instagram', + 'RSS' => 'RSS Feed', + 'Twitter' => 'Twitter', + 'Youtube' => 'Youtube', +); diff --git a/local/modules/HookAnalytics/I18n/frontOffice/default/fr_FR.php b/local/modules/HookAnalytics/I18n/frontOffice/default/fr_FR.php new file mode 100644 index 00000000..7b64f075 --- /dev/null +++ b/local/modules/HookAnalytics/I18n/frontOffice/default/fr_FR.php @@ -0,0 +1,10 @@ + 'Facebook', + 'Google+' => 'Google+', + 'Instagram' => 'Instagram', + 'RSS' => 'Flux RSS', + 'Twitter' => 'Twitter', + 'Youtube' => 'Youtube', +]; diff --git a/local/modules/HookAnalytics/I18n/frontOffice/default/it_IT.php b/local/modules/HookAnalytics/I18n/frontOffice/default/it_IT.php new file mode 100644 index 00000000..15298b70 --- /dev/null +++ b/local/modules/HookAnalytics/I18n/frontOffice/default/it_IT.php @@ -0,0 +1,10 @@ + 'Facebook', + 'Google+' => 'Google +', + 'Instagram' => 'Instagram', + 'RSS' => 'RSS Feed', + 'Twitter' => 'Twitter', + 'Youtube' => 'Youtube', +]; diff --git a/local/modules/HookAnalytics/I18n/frontOffice/default/ru_RU.php b/local/modules/HookAnalytics/I18n/frontOffice/default/ru_RU.php new file mode 100644 index 00000000..385bb7a2 --- /dev/null +++ b/local/modules/HookAnalytics/I18n/frontOffice/default/ru_RU.php @@ -0,0 +1,10 @@ + 'Facebook', + 'Google+' => 'Google+', + 'Instagram' => 'Instagram', + 'RSS' => 'RSS-канал', + 'Twitter' => 'Twitter', + 'Youtube' => 'Youtube', +); diff --git a/local/modules/HookAnalytics/I18n/frontOffice/default/tr_TR.php b/local/modules/HookAnalytics/I18n/frontOffice/default/tr_TR.php new file mode 100644 index 00000000..b951272b --- /dev/null +++ b/local/modules/HookAnalytics/I18n/frontOffice/default/tr_TR.php @@ -0,0 +1,10 @@ + 'Facebook', + 'Google+' => 'Google +', + 'Instagram' => 'Instagram', + 'RSS' => 'RSS Beslemesi', + 'Twitter' => 'Twitter', + 'Youtube' => 'Youtube', +]; diff --git a/local/modules/HookAnalytics/I18n/it_IT.php b/local/modules/HookAnalytics/I18n/it_IT.php new file mode 100644 index 00000000..bcce8768 --- /dev/null +++ b/local/modules/HookAnalytics/I18n/it_IT.php @@ -0,0 +1,5 @@ + 'Codice di monitoraggio', +]; diff --git a/local/modules/HookAnalytics/I18n/ru_RU.php b/local/modules/HookAnalytics/I18n/ru_RU.php new file mode 100644 index 00000000..5d076143 --- /dev/null +++ b/local/modules/HookAnalytics/I18n/ru_RU.php @@ -0,0 +1,5 @@ + 'Код отслеживания', +); diff --git a/local/modules/HookAnalytics/I18n/tr_TR.php b/local/modules/HookAnalytics/I18n/tr_TR.php new file mode 100644 index 00000000..3e16a023 --- /dev/null +++ b/local/modules/HookAnalytics/I18n/tr_TR.php @@ -0,0 +1,5 @@ + 'İzleme Kodu', +]; diff --git a/local/modules/HookAnalytics/LICENSE.txt b/local/modules/HookAnalytics/LICENSE.txt new file mode 100644 index 00000000..65c5ca88 --- /dev/null +++ b/local/modules/HookAnalytics/LICENSE.txt @@ -0,0 +1,165 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + + This version of the GNU Lesser General Public License incorporates +the terms and conditions of version 3 of the GNU General Public +License, supplemented by the additional permissions listed below. + + 0. Additional Definitions. + + As used herein, "this License" refers to version 3 of the GNU Lesser +General Public License, and the "GNU GPL" refers to version 3 of the GNU +General Public License. + + "The Library" refers to a covered work governed by this License, +other than an Application or a Combined Work as defined below. + + An "Application" is any work that makes use of an interface provided +by the Library, but which is not otherwise based on the Library. +Defining a subclass of a class defined by the Library is deemed a mode +of using an interface provided by the Library. + + A "Combined Work" is a work produced by combining or linking an +Application with the Library. The particular version of the Library +with which the Combined Work was made is also called the "Linked +Version". + + The "Minimal Corresponding Source" for a Combined Work means the +Corresponding Source for the Combined Work, excluding any source code +for portions of the Combined Work that, considered in isolation, are +based on the Application, and not on the Linked Version. + + The "Corresponding Application Code" for a Combined Work means the +object code and/or source code for the Application, including any data +and utility programs needed for reproducing the Combined Work from the +Application, but excluding the System Libraries of the Combined Work. + + 1. Exception to Section 3 of the GNU GPL. + + You may convey a covered work under sections 3 and 4 of this License +without being bound by section 3 of the GNU GPL. + + 2. Conveying Modified Versions. + + If you modify a copy of the Library, and, in your modifications, a +facility refers to a function or data to be supplied by an Application +that uses the facility (other than as an argument passed when the +facility is invoked), then you may convey a copy of the modified +version: + + a) under this License, provided that you make a good faith effort to + ensure that, in the event an Application does not supply the + function or data, the facility still operates, and performs + whatever part of its purpose remains meaningful, or + + b) under the GNU GPL, with none of the additional permissions of + this License applicable to that copy. + + 3. Object Code Incorporating Material from Library Header Files. + + The object code form of an Application may incorporate material from +a header file that is part of the Library. You may convey such object +code under terms of your choice, provided that, if the incorporated +material is not limited to numerical parameters, data structure +layouts and accessors, or small macros, inline functions and templates +(ten or fewer lines in length), you do both of the following: + + a) Give prominent notice with each copy of the object code that the + Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the object code with a copy of the GNU GPL and this license + document. + + 4. Combined Works. + + You may convey a Combined Work under terms of your choice that, +taken together, effectively do not restrict modification of the +portions of the Library contained in the Combined Work and reverse +engineering for debugging such modifications, if you also do each of +the following: + + a) Give prominent notice with each copy of the Combined Work that + the Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the Combined Work with a copy of the GNU GPL and this license + document. + + c) For a Combined Work that displays copyright notices during + execution, include the copyright notice for the Library among + these notices, as well as a reference directing the user to the + copies of the GNU GPL and this license document. + + d) Do one of the following: + + 0) Convey the Minimal Corresponding Source under the terms of this + License, and the Corresponding Application Code in a form + suitable for, and under terms that permit, the user to + recombine or relink the Application with a modified version of + the Linked Version to produce a modified Combined Work, in the + manner specified by section 6 of the GNU GPL for conveying + Corresponding Source. + + 1) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (a) uses at run time + a copy of the Library already present on the user's computer + system, and (b) will operate properly with a modified version + of the Library that is interface-compatible with the Linked + Version. + + e) Provide Installation Information, but only if you would otherwise + be required to provide such information under section 6 of the + GNU GPL, and only to the extent that such information is + necessary to install and execute a modified version of the + Combined Work produced by recombining or relinking the + Application with a modified version of the Linked Version. (If + you use option 4d0, the Installation Information must accompany + the Minimal Corresponding Source and Corresponding Application + Code. If you use option 4d1, you must provide the Installation + Information in the manner specified by section 6 of the GNU GPL + for conveying Corresponding Source.) + + 5. Combined Libraries. + + You may place library facilities that are a work based on the +Library side by side in a single library together with other library +facilities that are not Applications and are not covered by this +License, and convey such a combined library under terms of your +choice, if you do both of the following: + + a) Accompany the combined library with a copy of the same work based + on the Library, uncombined with any other library facilities, + conveyed under the terms of this License. + + b) Give prominent notice with the combined library that part of it + is a work based on the Library, and explaining where to find the + accompanying uncombined form of the same work. + + 6. Revised Versions of the GNU Lesser General Public License. + + The Free Software Foundation may publish revised and/or new versions +of the GNU Lesser General Public License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. + + Each version is given a distinguishing version number. If the +Library as you received it specifies that a certain numbered version +of the GNU Lesser General Public License "or any later version" +applies to it, you have the option of following the terms and +conditions either of that published version or of any later version +published by the Free Software Foundation. If the Library as you +received it does not specify a version number of the GNU Lesser +General Public License, you may choose any version of the GNU Lesser +General Public License ever published by the Free Software Foundation. + + If the Library as you received it specifies that a proxy can decide +whether future versions of the GNU Lesser General Public License shall +apply, that proxy's public statement of acceptance of any version is +permanent authorization for you to choose that version for the +Library. diff --git a/local/modules/HookAnalytics/composer.json b/local/modules/HookAnalytics/composer.json new file mode 100644 index 00000000..efe5231d --- /dev/null +++ b/local/modules/HookAnalytics/composer.json @@ -0,0 +1,11 @@ +{ + "name": "thelia/hook-analytics-module", + "license": "LGPL-3.0+", + "type": "thelia-module", + "require": { + "thelia/installer": "~1.1" + }, + "extra": { + "installer-name": "HookAnalytics" + } +} diff --git a/local/modules/HookAnalytics/templates/backOffice/default/assets/js/module-configuration.js b/local/modules/HookAnalytics/templates/backOffice/default/assets/js/module-configuration.js new file mode 100644 index 00000000..fe180bb7 --- /dev/null +++ b/local/modules/HookAnalytics/templates/backOffice/default/assets/js/module-configuration.js @@ -0,0 +1,29 @@ +$(document).ready(function() { + $("#hookanalytics-form").on("submit", function(e, data){ + e.preventDefault(); + var form = $(this); + + $('body').append(''); + + $.ajax({ + url: form.attr('action'), + type: form.attr('method'), + data: form.serialize() + }).done(function(){ + $("#loading-event").remove(); + }) + .success(function(data) { + if (data.error != 0) { + $("#loading-event").remove(); + $('#hookanalytics-failed-body').html(data.message); + $("#hookanalytics-failed").modal("show"); + } + }) + .fail(function(jqXHR, textStatus, errorThrown){ + $("#loading-event").remove(); + $('#hookanalytics-failed-body').html(jqXHR.responseJSON.message); + $("#hookanalytics-failed").modal("show"); + }); + + }); +}); \ No newline at end of file diff --git a/local/modules/HookAnalytics/templates/backOffice/default/module_configuration.html b/local/modules/HookAnalytics/templates/backOffice/default/module_configuration.html new file mode 100644 index 00000000..c80b88ab --- /dev/null +++ b/local/modules/HookAnalytics/templates/backOffice/default/module_configuration.html @@ -0,0 +1,52 @@ + + + +
    +
    + +
    + {intl l='Edit your analytics configuration.'} +
    + +
    +
    + + {form name="hookanalytics.configuration.form"} + + + {form_hidden_fields} + + {form_field field='trackingcode'} +
    + + +
    + {/form_field} + + + + {/form} + +
    + +
    + +
    +
    + + + + diff --git a/local/modules/HookCart/Config/config.xml b/local/modules/HookCart/Config/config.xml new file mode 100644 index 00000000..f8c3dce8 --- /dev/null +++ b/local/modules/HookCart/Config/config.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + diff --git a/local/modules/HookCart/Config/module.xml b/local/modules/HookCart/Config/module.xml new file mode 100644 index 00000000..a217bc64 --- /dev/null +++ b/local/modules/HookCart/Config/module.xml @@ -0,0 +1,24 @@ + + + HookCart\HookCart + + Block Cart + + + Bloc Panier + + + en_US + fr_FR + + 2.4.3 + + Julien Chanséaume + jchanseaume@openstudio.fr + + classic + 2.4.3 + alpha + diff --git a/local/modules/HookCart/HookCart.php b/local/modules/HookCart/HookCart.php new file mode 100644 index 00000000..da8d0e9a --- /dev/null +++ b/local/modules/HookCart/HookCart.php @@ -0,0 +1,20 @@ + 'Warenkorb', + 'Checkout' => 'Zur Kasse', + 'Remove' => 'Entfernen', + 'View Cart' => 'Warenkorb anzeigen', + 'You have no items in your shopping cart.' => 'Sie haben keine Produkte im Warenkorb', +]; diff --git a/local/modules/HookCart/I18n/frontOffice/default/en_US.php b/local/modules/HookCart/I18n/frontOffice/default/en_US.php new file mode 100644 index 00000000..3f99d2c5 --- /dev/null +++ b/local/modules/HookCart/I18n/frontOffice/default/en_US.php @@ -0,0 +1,9 @@ + 'Cart', + 'Checkout' => 'Checkout', + 'Remove' => 'Remove', + 'View Cart' => 'View Cart', + 'You have no items in your shopping cart.' => 'You have no items in your shopping cart.', +); diff --git a/local/modules/HookCart/I18n/frontOffice/default/fr_FR.php b/local/modules/HookCart/I18n/frontOffice/default/fr_FR.php new file mode 100644 index 00000000..088f21ef --- /dev/null +++ b/local/modules/HookCart/I18n/frontOffice/default/fr_FR.php @@ -0,0 +1,9 @@ + 'Panier', + 'Checkout' => 'Commande', + 'Remove' => 'Supprimer', + 'View Cart' => 'Voir le panier', + 'You have no items in your shopping cart.' => 'Vous n\'avez pas de produit dans votre panier.', +]; diff --git a/local/modules/HookCart/I18n/frontOffice/default/it_IT.php b/local/modules/HookCart/I18n/frontOffice/default/it_IT.php new file mode 100644 index 00000000..dac05d5d --- /dev/null +++ b/local/modules/HookCart/I18n/frontOffice/default/it_IT.php @@ -0,0 +1,9 @@ + 'Carrello', + 'Checkout' => 'Procedi all\'acquisto', + 'Remove' => 'Rimuovi', + 'View Cart' => 'Visualizza il carrello', + 'You have no items in your shopping cart.' => 'Non hai nessun prodotto nel tuo carrello.', +]; diff --git a/local/modules/HookCart/I18n/frontOffice/default/ru_RU.php b/local/modules/HookCart/I18n/frontOffice/default/ru_RU.php new file mode 100644 index 00000000..7f98d017 --- /dev/null +++ b/local/modules/HookCart/I18n/frontOffice/default/ru_RU.php @@ -0,0 +1,9 @@ + 'Корзина', + 'Checkout' => 'Оформить', + 'Remove' => 'Удалить', + 'View Cart' => 'Просмотр', + 'You have no items in your shopping cart.' => 'Ваша корзина пуста', +); diff --git a/local/modules/HookCart/I18n/frontOffice/default/tr_TR.php b/local/modules/HookCart/I18n/frontOffice/default/tr_TR.php new file mode 100644 index 00000000..04f4cc85 --- /dev/null +++ b/local/modules/HookCart/I18n/frontOffice/default/tr_TR.php @@ -0,0 +1,9 @@ + 'Sepet', + 'Checkout' => 'Ödeme yap', + 'Remove' => 'Kaldır', + 'View Cart' => 'Sepeti Görüntüle', + 'You have no items in your shopping cart.' => 'Sepetinizde hiç ürün yok.', +]; diff --git a/local/modules/HookCart/LICENSE.txt b/local/modules/HookCart/LICENSE.txt new file mode 100644 index 00000000..65c5ca88 --- /dev/null +++ b/local/modules/HookCart/LICENSE.txt @@ -0,0 +1,165 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + + This version of the GNU Lesser General Public License incorporates +the terms and conditions of version 3 of the GNU General Public +License, supplemented by the additional permissions listed below. + + 0. Additional Definitions. + + As used herein, "this License" refers to version 3 of the GNU Lesser +General Public License, and the "GNU GPL" refers to version 3 of the GNU +General Public License. + + "The Library" refers to a covered work governed by this License, +other than an Application or a Combined Work as defined below. + + An "Application" is any work that makes use of an interface provided +by the Library, but which is not otherwise based on the Library. +Defining a subclass of a class defined by the Library is deemed a mode +of using an interface provided by the Library. + + A "Combined Work" is a work produced by combining or linking an +Application with the Library. The particular version of the Library +with which the Combined Work was made is also called the "Linked +Version". + + The "Minimal Corresponding Source" for a Combined Work means the +Corresponding Source for the Combined Work, excluding any source code +for portions of the Combined Work that, considered in isolation, are +based on the Application, and not on the Linked Version. + + The "Corresponding Application Code" for a Combined Work means the +object code and/or source code for the Application, including any data +and utility programs needed for reproducing the Combined Work from the +Application, but excluding the System Libraries of the Combined Work. + + 1. Exception to Section 3 of the GNU GPL. + + You may convey a covered work under sections 3 and 4 of this License +without being bound by section 3 of the GNU GPL. + + 2. Conveying Modified Versions. + + If you modify a copy of the Library, and, in your modifications, a +facility refers to a function or data to be supplied by an Application +that uses the facility (other than as an argument passed when the +facility is invoked), then you may convey a copy of the modified +version: + + a) under this License, provided that you make a good faith effort to + ensure that, in the event an Application does not supply the + function or data, the facility still operates, and performs + whatever part of its purpose remains meaningful, or + + b) under the GNU GPL, with none of the additional permissions of + this License applicable to that copy. + + 3. Object Code Incorporating Material from Library Header Files. + + The object code form of an Application may incorporate material from +a header file that is part of the Library. You may convey such object +code under terms of your choice, provided that, if the incorporated +material is not limited to numerical parameters, data structure +layouts and accessors, or small macros, inline functions and templates +(ten or fewer lines in length), you do both of the following: + + a) Give prominent notice with each copy of the object code that the + Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the object code with a copy of the GNU GPL and this license + document. + + 4. Combined Works. + + You may convey a Combined Work under terms of your choice that, +taken together, effectively do not restrict modification of the +portions of the Library contained in the Combined Work and reverse +engineering for debugging such modifications, if you also do each of +the following: + + a) Give prominent notice with each copy of the Combined Work that + the Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the Combined Work with a copy of the GNU GPL and this license + document. + + c) For a Combined Work that displays copyright notices during + execution, include the copyright notice for the Library among + these notices, as well as a reference directing the user to the + copies of the GNU GPL and this license document. + + d) Do one of the following: + + 0) Convey the Minimal Corresponding Source under the terms of this + License, and the Corresponding Application Code in a form + suitable for, and under terms that permit, the user to + recombine or relink the Application with a modified version of + the Linked Version to produce a modified Combined Work, in the + manner specified by section 6 of the GNU GPL for conveying + Corresponding Source. + + 1) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (a) uses at run time + a copy of the Library already present on the user's computer + system, and (b) will operate properly with a modified version + of the Library that is interface-compatible with the Linked + Version. + + e) Provide Installation Information, but only if you would otherwise + be required to provide such information under section 6 of the + GNU GPL, and only to the extent that such information is + necessary to install and execute a modified version of the + Combined Work produced by recombining or relinking the + Application with a modified version of the Linked Version. (If + you use option 4d0, the Installation Information must accompany + the Minimal Corresponding Source and Corresponding Application + Code. If you use option 4d1, you must provide the Installation + Information in the manner specified by section 6 of the GNU GPL + for conveying Corresponding Source.) + + 5. Combined Libraries. + + You may place library facilities that are a work based on the +Library side by side in a single library together with other library +facilities that are not Applications and are not covered by this +License, and convey such a combined library under terms of your +choice, if you do both of the following: + + a) Accompany the combined library with a copy of the same work based + on the Library, uncombined with any other library facilities, + conveyed under the terms of this License. + + b) Give prominent notice with the combined library that part of it + is a work based on the Library, and explaining where to find the + accompanying uncombined form of the same work. + + 6. Revised Versions of the GNU Lesser General Public License. + + The Free Software Foundation may publish revised and/or new versions +of the GNU Lesser General Public License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. + + Each version is given a distinguishing version number. If the +Library as you received it specifies that a certain numbered version +of the GNU Lesser General Public License "or any later version" +applies to it, you have the option of following the terms and +conditions either of that published version or of any later version +published by the Free Software Foundation. If the Library as you +received it does not specify a version number of the GNU Lesser +General Public License, you may choose any version of the GNU Lesser +General Public License ever published by the Free Software Foundation. + + If the Library as you received it specifies that a proxy can decide +whether future versions of the GNU Lesser General Public License shall +apply, that proxy's public statement of acceptance of any version is +permanent authorization for you to choose that version for the +Library. diff --git a/local/modules/HookCart/composer.json b/local/modules/HookCart/composer.json new file mode 100644 index 00000000..f56a5cb6 --- /dev/null +++ b/local/modules/HookCart/composer.json @@ -0,0 +1,11 @@ +{ + "name": "thelia/hook-cart-module", + "license": "LGPL-3.0+", + "type": "thelia-module", + "require": { + "thelia/installer": "~1.1" + }, + "extra": { + "installer-name": "HookCart" + } +} diff --git a/local/modules/HookCart/templates/frontOffice/default/assets/css/styles.css b/local/modules/HookCart/templates/frontOffice/default/assets/css/styles.css new file mode 100644 index 00000000..e69de29b diff --git a/local/modules/HookCart/templates/frontOffice/default/main-navbar-secondary.html b/local/modules/HookCart/templates/frontOffice/default/main-navbar-secondary.html new file mode 100644 index 00000000..a5df3814 --- /dev/null +++ b/local/modules/HookCart/templates/frontOffice/default/main-navbar-secondary.html @@ -0,0 +1,3 @@ + \ No newline at end of file diff --git a/local/modules/HookCart/templates/frontOffice/default/mini-cart.html b/local/modules/HookCart/templates/frontOffice/default/mini-cart.html new file mode 100644 index 00000000..72be18e5 --- /dev/null +++ b/local/modules/HookCart/templates/frontOffice/default/mini-cart.html @@ -0,0 +1,73 @@ +{ifloop rel="cartloop"} + +{/ifloop} +{elseloop rel="cartloop"} + +{/elseloop} diff --git a/local/modules/HookContact/Config/config.xml b/local/modules/HookContact/Config/config.xml new file mode 100644 index 00000000..5c54bc9c --- /dev/null +++ b/local/modules/HookContact/Config/config.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + diff --git a/local/modules/HookContact/Config/module.xml b/local/modules/HookContact/Config/module.xml new file mode 100644 index 00000000..2f9c9f63 --- /dev/null +++ b/local/modules/HookContact/Config/module.xml @@ -0,0 +1,24 @@ + + + HookContact\HookContact + + Block Contact + + + Bloc Contact + + + en_US + fr_FR + + 2.4.3 + + Julien Chanséaume + jchanseaume@openstudio.fr + + classic + 2.4.3 + alpha + diff --git a/local/modules/HookContact/Hook/FrontHook.php b/local/modules/HookContact/Hook/FrontHook.php new file mode 100644 index 00000000..8ed956f5 --- /dev/null +++ b/local/modules/HookContact/Hook/FrontHook.php @@ -0,0 +1,39 @@ + + */ +class FrontHook extends BaseHook +{ + public function onMainFooterBody(HookRenderBlockEvent $event) + { + $content = trim($this->render("main-footer-body.html")); + if ("" != $content) { + $event->add( + array( + "id" => "contact-footer-body", + "class" => "contact", + "title" => $this->trans("Contact", array(), "hookcontact"), + "content" => $content + ) + ); + } + } +} diff --git a/local/modules/HookContact/HookContact.php b/local/modules/HookContact/HookContact.php new file mode 100644 index 00000000..2b8df283 --- /dev/null +++ b/local/modules/HookContact/HookContact.php @@ -0,0 +1,20 @@ + 'Kontakt', +]; diff --git a/local/modules/HookContact/I18n/en_US.php b/local/modules/HookContact/I18n/en_US.php new file mode 100644 index 00000000..55aea96d --- /dev/null +++ b/local/modules/HookContact/I18n/en_US.php @@ -0,0 +1,5 @@ + 'Contact', +); diff --git a/local/modules/HookContact/I18n/fr_FR.php b/local/modules/HookContact/I18n/fr_FR.php new file mode 100644 index 00000000..896efb7c --- /dev/null +++ b/local/modules/HookContact/I18n/fr_FR.php @@ -0,0 +1,5 @@ + 'Contact', +]; diff --git a/local/modules/HookContact/I18n/frontOffice/default/fr_FR.php b/local/modules/HookContact/I18n/frontOffice/default/fr_FR.php new file mode 100644 index 00000000..d8eb50ed --- /dev/null +++ b/local/modules/HookContact/I18n/frontOffice/default/fr_FR.php @@ -0,0 +1,5 @@ + 'Nous trouver, Nous contacter', +]; diff --git a/local/modules/HookContact/I18n/frontOffice/default/ru_RU.php b/local/modules/HookContact/I18n/frontOffice/default/ru_RU.php new file mode 100644 index 00000000..17d5758e --- /dev/null +++ b/local/modules/HookContact/I18n/frontOffice/default/ru_RU.php @@ -0,0 +1,5 @@ + 'Найти нас, Связаться с нами', +]; diff --git a/local/modules/HookContact/I18n/it_IT.php b/local/modules/HookContact/I18n/it_IT.php new file mode 100644 index 00000000..11ee0ec2 --- /dev/null +++ b/local/modules/HookContact/I18n/it_IT.php @@ -0,0 +1,5 @@ + 'Contatta', +]; diff --git a/local/modules/HookContact/I18n/ru_RU.php b/local/modules/HookContact/I18n/ru_RU.php new file mode 100644 index 00000000..76325965 --- /dev/null +++ b/local/modules/HookContact/I18n/ru_RU.php @@ -0,0 +1,5 @@ + 'Контакты', +); diff --git a/local/modules/HookContact/I18n/tr_TR.php b/local/modules/HookContact/I18n/tr_TR.php new file mode 100644 index 00000000..31680df5 --- /dev/null +++ b/local/modules/HookContact/I18n/tr_TR.php @@ -0,0 +1,5 @@ + 'İletişim', +]; diff --git a/local/modules/HookContact/LICENSE.txt b/local/modules/HookContact/LICENSE.txt new file mode 100644 index 00000000..65c5ca88 --- /dev/null +++ b/local/modules/HookContact/LICENSE.txt @@ -0,0 +1,165 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + + This version of the GNU Lesser General Public License incorporates +the terms and conditions of version 3 of the GNU General Public +License, supplemented by the additional permissions listed below. + + 0. Additional Definitions. + + As used herein, "this License" refers to version 3 of the GNU Lesser +General Public License, and the "GNU GPL" refers to version 3 of the GNU +General Public License. + + "The Library" refers to a covered work governed by this License, +other than an Application or a Combined Work as defined below. + + An "Application" is any work that makes use of an interface provided +by the Library, but which is not otherwise based on the Library. +Defining a subclass of a class defined by the Library is deemed a mode +of using an interface provided by the Library. + + A "Combined Work" is a work produced by combining or linking an +Application with the Library. The particular version of the Library +with which the Combined Work was made is also called the "Linked +Version". + + The "Minimal Corresponding Source" for a Combined Work means the +Corresponding Source for the Combined Work, excluding any source code +for portions of the Combined Work that, considered in isolation, are +based on the Application, and not on the Linked Version. + + The "Corresponding Application Code" for a Combined Work means the +object code and/or source code for the Application, including any data +and utility programs needed for reproducing the Combined Work from the +Application, but excluding the System Libraries of the Combined Work. + + 1. Exception to Section 3 of the GNU GPL. + + You may convey a covered work under sections 3 and 4 of this License +without being bound by section 3 of the GNU GPL. + + 2. Conveying Modified Versions. + + If you modify a copy of the Library, and, in your modifications, a +facility refers to a function or data to be supplied by an Application +that uses the facility (other than as an argument passed when the +facility is invoked), then you may convey a copy of the modified +version: + + a) under this License, provided that you make a good faith effort to + ensure that, in the event an Application does not supply the + function or data, the facility still operates, and performs + whatever part of its purpose remains meaningful, or + + b) under the GNU GPL, with none of the additional permissions of + this License applicable to that copy. + + 3. Object Code Incorporating Material from Library Header Files. + + The object code form of an Application may incorporate material from +a header file that is part of the Library. You may convey such object +code under terms of your choice, provided that, if the incorporated +material is not limited to numerical parameters, data structure +layouts and accessors, or small macros, inline functions and templates +(ten or fewer lines in length), you do both of the following: + + a) Give prominent notice with each copy of the object code that the + Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the object code with a copy of the GNU GPL and this license + document. + + 4. Combined Works. + + You may convey a Combined Work under terms of your choice that, +taken together, effectively do not restrict modification of the +portions of the Library contained in the Combined Work and reverse +engineering for debugging such modifications, if you also do each of +the following: + + a) Give prominent notice with each copy of the Combined Work that + the Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the Combined Work with a copy of the GNU GPL and this license + document. + + c) For a Combined Work that displays copyright notices during + execution, include the copyright notice for the Library among + these notices, as well as a reference directing the user to the + copies of the GNU GPL and this license document. + + d) Do one of the following: + + 0) Convey the Minimal Corresponding Source under the terms of this + License, and the Corresponding Application Code in a form + suitable for, and under terms that permit, the user to + recombine or relink the Application with a modified version of + the Linked Version to produce a modified Combined Work, in the + manner specified by section 6 of the GNU GPL for conveying + Corresponding Source. + + 1) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (a) uses at run time + a copy of the Library already present on the user's computer + system, and (b) will operate properly with a modified version + of the Library that is interface-compatible with the Linked + Version. + + e) Provide Installation Information, but only if you would otherwise + be required to provide such information under section 6 of the + GNU GPL, and only to the extent that such information is + necessary to install and execute a modified version of the + Combined Work produced by recombining or relinking the + Application with a modified version of the Linked Version. (If + you use option 4d0, the Installation Information must accompany + the Minimal Corresponding Source and Corresponding Application + Code. If you use option 4d1, you must provide the Installation + Information in the manner specified by section 6 of the GNU GPL + for conveying Corresponding Source.) + + 5. Combined Libraries. + + You may place library facilities that are a work based on the +Library side by side in a single library together with other library +facilities that are not Applications and are not covered by this +License, and convey such a combined library under terms of your +choice, if you do both of the following: + + a) Accompany the combined library with a copy of the same work based + on the Library, uncombined with any other library facilities, + conveyed under the terms of this License. + + b) Give prominent notice with the combined library that part of it + is a work based on the Library, and explaining where to find the + accompanying uncombined form of the same work. + + 6. Revised Versions of the GNU Lesser General Public License. + + The Free Software Foundation may publish revised and/or new versions +of the GNU Lesser General Public License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. + + Each version is given a distinguishing version number. If the +Library as you received it specifies that a certain numbered version +of the GNU Lesser General Public License "or any later version" +applies to it, you have the option of following the terms and +conditions either of that published version or of any later version +published by the Free Software Foundation. If the Library as you +received it does not specify a version number of the GNU Lesser +General Public License, you may choose any version of the GNU Lesser +General Public License ever published by the Free Software Foundation. + + If the Library as you received it specifies that a proxy can decide +whether future versions of the GNU Lesser General Public License shall +apply, that proxy's public statement of acceptance of any version is +permanent authorization for you to choose that version for the +Library. diff --git a/local/modules/HookContact/composer.json b/local/modules/HookContact/composer.json new file mode 100644 index 00000000..2ecdb22a --- /dev/null +++ b/local/modules/HookContact/composer.json @@ -0,0 +1,11 @@ +{ + "name": "thelia/hook-contact-module", + "license": "LGPL-3.0+", + "type": "thelia-module", + "require": { + "thelia/installer": "~1.1" + }, + "extra": { + "installer-name": "HookContact" + } +} diff --git a/local/modules/HookContact/templates/frontOffice/default/main-footer-body.html b/local/modules/HookContact/templates/frontOffice/default/main-footer-body.html new file mode 100644 index 00000000..9eea38b6 --- /dev/null +++ b/local/modules/HookContact/templates/frontOffice/default/main-footer-body.html @@ -0,0 +1,25 @@ +
    + +
      +
    • +
      + {config key="store_address1"} {config key="store_address2"} {config key="store_address3"}
      + {config key="store_zipcode"} + + {config key="store_city"} + {if {config key="store_country"} } + {loop type="country" name="address.country.title" id={config key="store_country"}}, {$TITLE}{/loop} + {/if} + +
      +
    • + {if {config key="store_phone"} } +
    • + {config key="store_phone"} +
    • + {/if} +
    • + {intl l="Find us, Contact us" d="hookcontact.fo.default"} +
    • +
    +
    diff --git a/local/modules/HookCurrency/Config/config.xml b/local/modules/HookCurrency/Config/config.xml new file mode 100644 index 00000000..1b5deb78 --- /dev/null +++ b/local/modules/HookCurrency/Config/config.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + diff --git a/local/modules/HookCurrency/Config/module.xml b/local/modules/HookCurrency/Config/module.xml new file mode 100644 index 00000000..4b578553 --- /dev/null +++ b/local/modules/HookCurrency/Config/module.xml @@ -0,0 +1,24 @@ + + + HookCurrency\HookCurrency + + Block Currency + + + Bloc Devise + + + en_US + fr_FR + + 2.4.3 + + Julien Chanséaume + jchanseaume@openstudio.fr + + classic + 2.4.3 + alpha + diff --git a/local/modules/HookCurrency/HookCurrency.php b/local/modules/HookCurrency/HookCurrency.php new file mode 100644 index 00000000..63d66296 --- /dev/null +++ b/local/modules/HookCurrency/HookCurrency.php @@ -0,0 +1,20 @@ + + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + + This version of the GNU Lesser General Public License incorporates +the terms and conditions of version 3 of the GNU General Public +License, supplemented by the additional permissions listed below. + + 0. Additional Definitions. + + As used herein, "this License" refers to version 3 of the GNU Lesser +General Public License, and the "GNU GPL" refers to version 3 of the GNU +General Public License. + + "The Library" refers to a covered work governed by this License, +other than an Application or a Combined Work as defined below. + + An "Application" is any work that makes use of an interface provided +by the Library, but which is not otherwise based on the Library. +Defining a subclass of a class defined by the Library is deemed a mode +of using an interface provided by the Library. + + A "Combined Work" is a work produced by combining or linking an +Application with the Library. The particular version of the Library +with which the Combined Work was made is also called the "Linked +Version". + + The "Minimal Corresponding Source" for a Combined Work means the +Corresponding Source for the Combined Work, excluding any source code +for portions of the Combined Work that, considered in isolation, are +based on the Application, and not on the Linked Version. + + The "Corresponding Application Code" for a Combined Work means the +object code and/or source code for the Application, including any data +and utility programs needed for reproducing the Combined Work from the +Application, but excluding the System Libraries of the Combined Work. + + 1. Exception to Section 3 of the GNU GPL. + + You may convey a covered work under sections 3 and 4 of this License +without being bound by section 3 of the GNU GPL. + + 2. Conveying Modified Versions. + + If you modify a copy of the Library, and, in your modifications, a +facility refers to a function or data to be supplied by an Application +that uses the facility (other than as an argument passed when the +facility is invoked), then you may convey a copy of the modified +version: + + a) under this License, provided that you make a good faith effort to + ensure that, in the event an Application does not supply the + function or data, the facility still operates, and performs + whatever part of its purpose remains meaningful, or + + b) under the GNU GPL, with none of the additional permissions of + this License applicable to that copy. + + 3. Object Code Incorporating Material from Library Header Files. + + The object code form of an Application may incorporate material from +a header file that is part of the Library. You may convey such object +code under terms of your choice, provided that, if the incorporated +material is not limited to numerical parameters, data structure +layouts and accessors, or small macros, inline functions and templates +(ten or fewer lines in length), you do both of the following: + + a) Give prominent notice with each copy of the object code that the + Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the object code with a copy of the GNU GPL and this license + document. + + 4. Combined Works. + + You may convey a Combined Work under terms of your choice that, +taken together, effectively do not restrict modification of the +portions of the Library contained in the Combined Work and reverse +engineering for debugging such modifications, if you also do each of +the following: + + a) Give prominent notice with each copy of the Combined Work that + the Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the Combined Work with a copy of the GNU GPL and this license + document. + + c) For a Combined Work that displays copyright notices during + execution, include the copyright notice for the Library among + these notices, as well as a reference directing the user to the + copies of the GNU GPL and this license document. + + d) Do one of the following: + + 0) Convey the Minimal Corresponding Source under the terms of this + License, and the Corresponding Application Code in a form + suitable for, and under terms that permit, the user to + recombine or relink the Application with a modified version of + the Linked Version to produce a modified Combined Work, in the + manner specified by section 6 of the GNU GPL for conveying + Corresponding Source. + + 1) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (a) uses at run time + a copy of the Library already present on the user's computer + system, and (b) will operate properly with a modified version + of the Library that is interface-compatible with the Linked + Version. + + e) Provide Installation Information, but only if you would otherwise + be required to provide such information under section 6 of the + GNU GPL, and only to the extent that such information is + necessary to install and execute a modified version of the + Combined Work produced by recombining or relinking the + Application with a modified version of the Linked Version. (If + you use option 4d0, the Installation Information must accompany + the Minimal Corresponding Source and Corresponding Application + Code. If you use option 4d1, you must provide the Installation + Information in the manner specified by section 6 of the GNU GPL + for conveying Corresponding Source.) + + 5. Combined Libraries. + + You may place library facilities that are a work based on the +Library side by side in a single library together with other library +facilities that are not Applications and are not covered by this +License, and convey such a combined library under terms of your +choice, if you do both of the following: + + a) Accompany the combined library with a copy of the same work based + on the Library, uncombined with any other library facilities, + conveyed under the terms of this License. + + b) Give prominent notice with the combined library that part of it + is a work based on the Library, and explaining where to find the + accompanying uncombined form of the same work. + + 6. Revised Versions of the GNU Lesser General Public License. + + The Free Software Foundation may publish revised and/or new versions +of the GNU Lesser General Public License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. + + Each version is given a distinguishing version number. If the +Library as you received it specifies that a certain numbered version +of the GNU Lesser General Public License "or any later version" +applies to it, you have the option of following the terms and +conditions either of that published version or of any later version +published by the Free Software Foundation. If the Library as you +received it does not specify a version number of the GNU Lesser +General Public License, you may choose any version of the GNU Lesser +General Public License ever published by the Free Software Foundation. + + If the Library as you received it specifies that a proxy can decide +whether future versions of the GNU Lesser General Public License shall +apply, that proxy's public statement of acceptance of any version is +permanent authorization for you to choose that version for the +Library. diff --git a/local/modules/HookCurrency/composer.json b/local/modules/HookCurrency/composer.json new file mode 100644 index 00000000..58767943 --- /dev/null +++ b/local/modules/HookCurrency/composer.json @@ -0,0 +1,11 @@ +{ + "name": "thelia/hook-currency-module", + "license": "LGPL-3.0+", + "type": "thelia-module", + "require": { + "thelia/installer": "~1.1" + }, + "extra": { + "installer-name": "HookCurrency" + } +} diff --git a/local/modules/HookCurrency/templates/frontOffice/default/main-navbar-secondary.html b/local/modules/HookCurrency/templates/frontOffice/default/main-navbar-secondary.html new file mode 100644 index 00000000..0a8faad9 --- /dev/null +++ b/local/modules/HookCurrency/templates/frontOffice/default/main-navbar-secondary.html @@ -0,0 +1,10 @@ + \ No newline at end of file diff --git a/local/modules/HookCustomer/Config/config.xml b/local/modules/HookCustomer/Config/config.xml new file mode 100644 index 00000000..63a29ce5 --- /dev/null +++ b/local/modules/HookCustomer/Config/config.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + diff --git a/local/modules/HookCustomer/Config/module.xml b/local/modules/HookCustomer/Config/module.xml new file mode 100644 index 00000000..1d8c415e --- /dev/null +++ b/local/modules/HookCustomer/Config/module.xml @@ -0,0 +1,24 @@ + + + HookCustomer\HookCustomer + + Block Customer + + + Bloc Client + + + en_US + fr_FR + + 2.4.3 + + Julien Chanséaume + jchanseaume@openstudio.fr + + classic + 2.4.3 + alpha + diff --git a/local/modules/HookCustomer/HookCustomer.php b/local/modules/HookCustomer/HookCustomer.php new file mode 100644 index 00000000..eab3f96a --- /dev/null +++ b/local/modules/HookCustomer/HookCustomer.php @@ -0,0 +1,20 @@ + 'E-mail Adresse', + 'Forgot your Password?' => 'Haben sir Ihr Passwort vergessen ?', + 'Log In!' => 'Log In!', + 'Log out!' => 'Log out!', + 'My Account' => 'Mein Kundenkonto', + 'Password' => 'Passwort', + 'Register' => 'Registrieren', + 'Register!' => 'Registrieren!', + 'Sign In' => 'Registrieren', +]; diff --git a/local/modules/HookCustomer/I18n/frontOffice/default/en_US.php b/local/modules/HookCustomer/I18n/frontOffice/default/en_US.php new file mode 100644 index 00000000..102c3129 --- /dev/null +++ b/local/modules/HookCustomer/I18n/frontOffice/default/en_US.php @@ -0,0 +1,13 @@ + 'Email address', + 'Forgot your Password?' => 'Forgot your Password?', + 'Log In!' => 'Log In!', + 'Log out!' => 'Log out!', + 'My Account' => 'My Account', + 'Password' => 'Password', + 'Register' => 'Register', + 'Register!' => 'Register!', + 'Sign In' => 'Sign In', +); diff --git a/local/modules/HookCustomer/I18n/frontOffice/default/fr_FR.php b/local/modules/HookCustomer/I18n/frontOffice/default/fr_FR.php new file mode 100644 index 00000000..8a899390 --- /dev/null +++ b/local/modules/HookCustomer/I18n/frontOffice/default/fr_FR.php @@ -0,0 +1,13 @@ + 'Adresse e-mail', + 'Forgot your Password?' => 'Mot de passe oublié ?', + 'Log In!' => 'Se connecter', + 'Log out!' => 'Se déconnecter', + 'My Account' => 'Mon compte', + 'Password' => 'Mot de passe', + 'Register' => 'S\'inscrire', + 'Register!' => 'Enregistrez-vous !', + 'Sign In' => 'Se connecter', +]; diff --git a/local/modules/HookCustomer/I18n/frontOffice/default/it_IT.php b/local/modules/HookCustomer/I18n/frontOffice/default/it_IT.php new file mode 100644 index 00000000..aba7ec5d --- /dev/null +++ b/local/modules/HookCustomer/I18n/frontOffice/default/it_IT.php @@ -0,0 +1,13 @@ + 'Indirizzo email', + 'Forgot your Password?' => 'Hai dimenticato la password?', + 'Log In!' => 'Accedi!', + 'Log out!' => 'Esci!', + 'My Account' => 'Mio account', + 'Password' => 'Password', + 'Register' => 'Registrati', + 'Register!' => 'Registrati!', + 'Sign In' => 'Accedi', +]; diff --git a/local/modules/HookCustomer/I18n/frontOffice/default/ru_RU.php b/local/modules/HookCustomer/I18n/frontOffice/default/ru_RU.php new file mode 100644 index 00000000..8c126959 --- /dev/null +++ b/local/modules/HookCustomer/I18n/frontOffice/default/ru_RU.php @@ -0,0 +1,13 @@ + 'Адрес email', + 'Forgot your Password?' => 'Забыли пароль?', + 'Log In!' => 'Вход', + 'Log out!' => 'Выход', + 'My Account' => 'Мой аккаунт', + 'Password' => 'Пароль', + 'Register' => 'Регистрация', + 'Register!' => 'Регистрация', + 'Sign In' => 'Войти', +); diff --git a/local/modules/HookCustomer/I18n/frontOffice/default/tr_TR.php b/local/modules/HookCustomer/I18n/frontOffice/default/tr_TR.php new file mode 100644 index 00000000..83c6b6fd --- /dev/null +++ b/local/modules/HookCustomer/I18n/frontOffice/default/tr_TR.php @@ -0,0 +1,13 @@ + 'Eposta adresi', + 'Forgot your Password?' => 'Parolanızı mı unuttunuz?', + 'Log In!' => 'Oturum aç!', + 'Log out!' => 'Çıkış Yap!', + 'My Account' => 'Hesabım', + 'Password' => 'Parola', + 'Register' => 'Kaydol', + 'Register!' => 'Kayıt ol!', + 'Sign In' => 'Oturum Aç', +]; diff --git a/local/modules/HookCustomer/LICENSE.txt b/local/modules/HookCustomer/LICENSE.txt new file mode 100644 index 00000000..65c5ca88 --- /dev/null +++ b/local/modules/HookCustomer/LICENSE.txt @@ -0,0 +1,165 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + + This version of the GNU Lesser General Public License incorporates +the terms and conditions of version 3 of the GNU General Public +License, supplemented by the additional permissions listed below. + + 0. Additional Definitions. + + As used herein, "this License" refers to version 3 of the GNU Lesser +General Public License, and the "GNU GPL" refers to version 3 of the GNU +General Public License. + + "The Library" refers to a covered work governed by this License, +other than an Application or a Combined Work as defined below. + + An "Application" is any work that makes use of an interface provided +by the Library, but which is not otherwise based on the Library. +Defining a subclass of a class defined by the Library is deemed a mode +of using an interface provided by the Library. + + A "Combined Work" is a work produced by combining or linking an +Application with the Library. The particular version of the Library +with which the Combined Work was made is also called the "Linked +Version". + + The "Minimal Corresponding Source" for a Combined Work means the +Corresponding Source for the Combined Work, excluding any source code +for portions of the Combined Work that, considered in isolation, are +based on the Application, and not on the Linked Version. + + The "Corresponding Application Code" for a Combined Work means the +object code and/or source code for the Application, including any data +and utility programs needed for reproducing the Combined Work from the +Application, but excluding the System Libraries of the Combined Work. + + 1. Exception to Section 3 of the GNU GPL. + + You may convey a covered work under sections 3 and 4 of this License +without being bound by section 3 of the GNU GPL. + + 2. Conveying Modified Versions. + + If you modify a copy of the Library, and, in your modifications, a +facility refers to a function or data to be supplied by an Application +that uses the facility (other than as an argument passed when the +facility is invoked), then you may convey a copy of the modified +version: + + a) under this License, provided that you make a good faith effort to + ensure that, in the event an Application does not supply the + function or data, the facility still operates, and performs + whatever part of its purpose remains meaningful, or + + b) under the GNU GPL, with none of the additional permissions of + this License applicable to that copy. + + 3. Object Code Incorporating Material from Library Header Files. + + The object code form of an Application may incorporate material from +a header file that is part of the Library. You may convey such object +code under terms of your choice, provided that, if the incorporated +material is not limited to numerical parameters, data structure +layouts and accessors, or small macros, inline functions and templates +(ten or fewer lines in length), you do both of the following: + + a) Give prominent notice with each copy of the object code that the + Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the object code with a copy of the GNU GPL and this license + document. + + 4. Combined Works. + + You may convey a Combined Work under terms of your choice that, +taken together, effectively do not restrict modification of the +portions of the Library contained in the Combined Work and reverse +engineering for debugging such modifications, if you also do each of +the following: + + a) Give prominent notice with each copy of the Combined Work that + the Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the Combined Work with a copy of the GNU GPL and this license + document. + + c) For a Combined Work that displays copyright notices during + execution, include the copyright notice for the Library among + these notices, as well as a reference directing the user to the + copies of the GNU GPL and this license document. + + d) Do one of the following: + + 0) Convey the Minimal Corresponding Source under the terms of this + License, and the Corresponding Application Code in a form + suitable for, and under terms that permit, the user to + recombine or relink the Application with a modified version of + the Linked Version to produce a modified Combined Work, in the + manner specified by section 6 of the GNU GPL for conveying + Corresponding Source. + + 1) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (a) uses at run time + a copy of the Library already present on the user's computer + system, and (b) will operate properly with a modified version + of the Library that is interface-compatible with the Linked + Version. + + e) Provide Installation Information, but only if you would otherwise + be required to provide such information under section 6 of the + GNU GPL, and only to the extent that such information is + necessary to install and execute a modified version of the + Combined Work produced by recombining or relinking the + Application with a modified version of the Linked Version. (If + you use option 4d0, the Installation Information must accompany + the Minimal Corresponding Source and Corresponding Application + Code. If you use option 4d1, you must provide the Installation + Information in the manner specified by section 6 of the GNU GPL + for conveying Corresponding Source.) + + 5. Combined Libraries. + + You may place library facilities that are a work based on the +Library side by side in a single library together with other library +facilities that are not Applications and are not covered by this +License, and convey such a combined library under terms of your +choice, if you do both of the following: + + a) Accompany the combined library with a copy of the same work based + on the Library, uncombined with any other library facilities, + conveyed under the terms of this License. + + b) Give prominent notice with the combined library that part of it + is a work based on the Library, and explaining where to find the + accompanying uncombined form of the same work. + + 6. Revised Versions of the GNU Lesser General Public License. + + The Free Software Foundation may publish revised and/or new versions +of the GNU Lesser General Public License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. + + Each version is given a distinguishing version number. If the +Library as you received it specifies that a certain numbered version +of the GNU Lesser General Public License "or any later version" +applies to it, you have the option of following the terms and +conditions either of that published version or of any later version +published by the Free Software Foundation. If the Library as you +received it does not specify a version number of the GNU Lesser +General Public License, you may choose any version of the GNU Lesser +General Public License ever published by the Free Software Foundation. + + If the Library as you received it specifies that a proxy can decide +whether future versions of the GNU Lesser General Public License shall +apply, that proxy's public statement of acceptance of any version is +permanent authorization for you to choose that version for the +Library. diff --git a/local/modules/HookCustomer/composer.json b/local/modules/HookCustomer/composer.json new file mode 100644 index 00000000..d081b403 --- /dev/null +++ b/local/modules/HookCustomer/composer.json @@ -0,0 +1,11 @@ +{ + "name": "thelia/hook-customer-module", + "license": "LGPL-3.0+", + "type": "thelia-module", + "require": { + "thelia/installer": "~1.1" + }, + "extra": { + "installer-name": "HookCustomer" + } +} diff --git a/local/modules/HookCustomer/templates/frontOffice/default/assets/css/styles.css b/local/modules/HookCustomer/templates/frontOffice/default/assets/css/styles.css new file mode 100644 index 00000000..e69de29b diff --git a/local/modules/HookCustomer/templates/frontOffice/default/main-navbar-secondary.html b/local/modules/HookCustomer/templates/frontOffice/default/main-navbar-secondary.html new file mode 100644 index 00000000..13d84fd5 --- /dev/null +++ b/local/modules/HookCustomer/templates/frontOffice/default/main-navbar-secondary.html @@ -0,0 +1,43 @@ + \ No newline at end of file diff --git a/local/modules/HookLang/Config/config.xml b/local/modules/HookLang/Config/config.xml new file mode 100644 index 00000000..d30cb542 --- /dev/null +++ b/local/modules/HookLang/Config/config.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + diff --git a/local/modules/HookLang/Config/module.xml b/local/modules/HookLang/Config/module.xml new file mode 100644 index 00000000..f4f349f2 --- /dev/null +++ b/local/modules/HookLang/Config/module.xml @@ -0,0 +1,24 @@ + + + HookLang\HookLang + + Block Languages + + + Bloc langages + + + en_US + fr_FR + + 2.4.3 + + Julien Chanséaume + jchanseaume@openstudio.fr + + classic + 2.4.3 + alpha + diff --git a/local/modules/HookLang/HookLang.php b/local/modules/HookLang/HookLang.php new file mode 100644 index 00000000..2ab93ac2 --- /dev/null +++ b/local/modules/HookLang/HookLang.php @@ -0,0 +1,20 @@ + + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + + This version of the GNU Lesser General Public License incorporates +the terms and conditions of version 3 of the GNU General Public +License, supplemented by the additional permissions listed below. + + 0. Additional Definitions. + + As used herein, "this License" refers to version 3 of the GNU Lesser +General Public License, and the "GNU GPL" refers to version 3 of the GNU +General Public License. + + "The Library" refers to a covered work governed by this License, +other than an Application or a Combined Work as defined below. + + An "Application" is any work that makes use of an interface provided +by the Library, but which is not otherwise based on the Library. +Defining a subclass of a class defined by the Library is deemed a mode +of using an interface provided by the Library. + + A "Combined Work" is a work produced by combining or linking an +Application with the Library. The particular version of the Library +with which the Combined Work was made is also called the "Linked +Version". + + The "Minimal Corresponding Source" for a Combined Work means the +Corresponding Source for the Combined Work, excluding any source code +for portions of the Combined Work that, considered in isolation, are +based on the Application, and not on the Linked Version. + + The "Corresponding Application Code" for a Combined Work means the +object code and/or source code for the Application, including any data +and utility programs needed for reproducing the Combined Work from the +Application, but excluding the System Libraries of the Combined Work. + + 1. Exception to Section 3 of the GNU GPL. + + You may convey a covered work under sections 3 and 4 of this License +without being bound by section 3 of the GNU GPL. + + 2. Conveying Modified Versions. + + If you modify a copy of the Library, and, in your modifications, a +facility refers to a function or data to be supplied by an Application +that uses the facility (other than as an argument passed when the +facility is invoked), then you may convey a copy of the modified +version: + + a) under this License, provided that you make a good faith effort to + ensure that, in the event an Application does not supply the + function or data, the facility still operates, and performs + whatever part of its purpose remains meaningful, or + + b) under the GNU GPL, with none of the additional permissions of + this License applicable to that copy. + + 3. Object Code Incorporating Material from Library Header Files. + + The object code form of an Application may incorporate material from +a header file that is part of the Library. You may convey such object +code under terms of your choice, provided that, if the incorporated +material is not limited to numerical parameters, data structure +layouts and accessors, or small macros, inline functions and templates +(ten or fewer lines in length), you do both of the following: + + a) Give prominent notice with each copy of the object code that the + Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the object code with a copy of the GNU GPL and this license + document. + + 4. Combined Works. + + You may convey a Combined Work under terms of your choice that, +taken together, effectively do not restrict modification of the +portions of the Library contained in the Combined Work and reverse +engineering for debugging such modifications, if you also do each of +the following: + + a) Give prominent notice with each copy of the Combined Work that + the Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the Combined Work with a copy of the GNU GPL and this license + document. + + c) For a Combined Work that displays copyright notices during + execution, include the copyright notice for the Library among + these notices, as well as a reference directing the user to the + copies of the GNU GPL and this license document. + + d) Do one of the following: + + 0) Convey the Minimal Corresponding Source under the terms of this + License, and the Corresponding Application Code in a form + suitable for, and under terms that permit, the user to + recombine or relink the Application with a modified version of + the Linked Version to produce a modified Combined Work, in the + manner specified by section 6 of the GNU GPL for conveying + Corresponding Source. + + 1) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (a) uses at run time + a copy of the Library already present on the user's computer + system, and (b) will operate properly with a modified version + of the Library that is interface-compatible with the Linked + Version. + + e) Provide Installation Information, but only if you would otherwise + be required to provide such information under section 6 of the + GNU GPL, and only to the extent that such information is + necessary to install and execute a modified version of the + Combined Work produced by recombining or relinking the + Application with a modified version of the Linked Version. (If + you use option 4d0, the Installation Information must accompany + the Minimal Corresponding Source and Corresponding Application + Code. If you use option 4d1, you must provide the Installation + Information in the manner specified by section 6 of the GNU GPL + for conveying Corresponding Source.) + + 5. Combined Libraries. + + You may place library facilities that are a work based on the +Library side by side in a single library together with other library +facilities that are not Applications and are not covered by this +License, and convey such a combined library under terms of your +choice, if you do both of the following: + + a) Accompany the combined library with a copy of the same work based + on the Library, uncombined with any other library facilities, + conveyed under the terms of this License. + + b) Give prominent notice with the combined library that part of it + is a work based on the Library, and explaining where to find the + accompanying uncombined form of the same work. + + 6. Revised Versions of the GNU Lesser General Public License. + + The Free Software Foundation may publish revised and/or new versions +of the GNU Lesser General Public License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. + + Each version is given a distinguishing version number. If the +Library as you received it specifies that a certain numbered version +of the GNU Lesser General Public License "or any later version" +applies to it, you have the option of following the terms and +conditions either of that published version or of any later version +published by the Free Software Foundation. If the Library as you +received it does not specify a version number of the GNU Lesser +General Public License, you may choose any version of the GNU Lesser +General Public License ever published by the Free Software Foundation. + + If the Library as you received it specifies that a proxy can decide +whether future versions of the GNU Lesser General Public License shall +apply, that proxy's public statement of acceptance of any version is +permanent authorization for you to choose that version for the +Library. diff --git a/local/modules/HookLang/composer.json b/local/modules/HookLang/composer.json new file mode 100644 index 00000000..c5338646 --- /dev/null +++ b/local/modules/HookLang/composer.json @@ -0,0 +1,11 @@ +{ + "name": "thelia/hook-lang-module", + "license": "LGPL-3.0+", + "type": "thelia-module", + "require": { + "thelia/installer": "~1.1" + }, + "extra": { + "installer-name": "HookLang" + } +} diff --git a/local/modules/HookLang/templates/frontOffice/default/main-navbar-secondary.html b/local/modules/HookLang/templates/frontOffice/default/main-navbar-secondary.html new file mode 100644 index 00000000..a61a7a1e --- /dev/null +++ b/local/modules/HookLang/templates/frontOffice/default/main-navbar-secondary.html @@ -0,0 +1,10 @@ + \ No newline at end of file diff --git a/local/modules/HookLinks/Config/config.xml b/local/modules/HookLinks/Config/config.xml new file mode 100644 index 00000000..6036b5d0 --- /dev/null +++ b/local/modules/HookLinks/Config/config.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + diff --git a/local/modules/HookLinks/Config/module.xml b/local/modules/HookLinks/Config/module.xml new file mode 100644 index 00000000..a9a1cb82 --- /dev/null +++ b/local/modules/HookLinks/Config/module.xml @@ -0,0 +1,24 @@ + + + HookLinks\HookLinks + + Block Useful links + + + Bloc Liens utiles + + + en_US + fr_FR + + 2.4.3 + + Julien Chanséaume + jchanseaume@openstudio.fr + + classic + 2.4.3 + alpha + diff --git a/local/modules/HookLinks/Hook/FrontHook.php b/local/modules/HookLinks/Hook/FrontHook.php new file mode 100644 index 00000000..3f0a4829 --- /dev/null +++ b/local/modules/HookLinks/Hook/FrontHook.php @@ -0,0 +1,38 @@ + + */ +class FrontHook extends BaseHook { + + public function onMainFooterBody(HookRenderBlockEvent $event) + { + $content = trim($this->render("main-footer-body.html")); + if ("" != $content){ + $event->add(array( + "id" => "links-footer-body", + "class" => "default", + "title" => $this->trans("Useful links", array(), "hooklinks"), + "content" => $content + )); + } + } + +} \ No newline at end of file diff --git a/local/modules/HookLinks/HookLinks.php b/local/modules/HookLinks/HookLinks.php new file mode 100644 index 00000000..28e00f98 --- /dev/null +++ b/local/modules/HookLinks/HookLinks.php @@ -0,0 +1,20 @@ + 'Nützliche Links', +]; diff --git a/local/modules/HookLinks/I18n/en_US.php b/local/modules/HookLinks/I18n/en_US.php new file mode 100644 index 00000000..531cd8a6 --- /dev/null +++ b/local/modules/HookLinks/I18n/en_US.php @@ -0,0 +1,5 @@ + 'Useful links', +); diff --git a/local/modules/HookLinks/I18n/fr_FR.php b/local/modules/HookLinks/I18n/fr_FR.php new file mode 100644 index 00000000..95d22cf1 --- /dev/null +++ b/local/modules/HookLinks/I18n/fr_FR.php @@ -0,0 +1,5 @@ + 'Liens utiles', +]; diff --git a/local/modules/HookLinks/I18n/frontOffice/default/de_DE.php b/local/modules/HookLinks/I18n/frontOffice/default/de_DE.php new file mode 100644 index 00000000..1dc47f8d --- /dev/null +++ b/local/modules/HookLinks/I18n/frontOffice/default/de_DE.php @@ -0,0 +1,10 @@ + 'Warenkorb', + 'Checkout' => 'Zur Kasse', + 'Log out!' => 'Log out!', + 'Login' => 'Anmeldung', + 'My Account' => 'Mein Kundenkonto', + 'Register' => 'Registrieren', +]; diff --git a/local/modules/HookLinks/I18n/frontOffice/default/en_US.php b/local/modules/HookLinks/I18n/frontOffice/default/en_US.php new file mode 100644 index 00000000..33a0bb71 --- /dev/null +++ b/local/modules/HookLinks/I18n/frontOffice/default/en_US.php @@ -0,0 +1,10 @@ + 'Cart', + 'Checkout' => 'Checkout', + 'Log out!' => 'Log out!', + 'Login' => 'Login', + 'My Account' => 'My Account', + 'Register' => 'Register', +); diff --git a/local/modules/HookLinks/I18n/frontOffice/default/fr_FR.php b/local/modules/HookLinks/I18n/frontOffice/default/fr_FR.php new file mode 100644 index 00000000..8b8c6bf4 --- /dev/null +++ b/local/modules/HookLinks/I18n/frontOffice/default/fr_FR.php @@ -0,0 +1,10 @@ + 'Panier', + 'Checkout' => 'Commander', + 'Log out!' => 'Se déconnecter', + 'Login' => 'Connexion', + 'My Account' => 'Mon compte', + 'Register' => 'S\'inscrire', +]; diff --git a/local/modules/HookLinks/I18n/frontOffice/default/it_IT.php b/local/modules/HookLinks/I18n/frontOffice/default/it_IT.php new file mode 100644 index 00000000..fca67d76 --- /dev/null +++ b/local/modules/HookLinks/I18n/frontOffice/default/it_IT.php @@ -0,0 +1,10 @@ + 'Carrello', + 'Checkout' => 'Procedi all\'acquisto', + 'Log out!' => 'Esci!', + 'Login' => 'Login', + 'My Account' => 'Mio account', + 'Register' => 'Registrati', +]; diff --git a/local/modules/HookLinks/I18n/frontOffice/default/ru_RU.php b/local/modules/HookLinks/I18n/frontOffice/default/ru_RU.php new file mode 100644 index 00000000..9cbec1c8 --- /dev/null +++ b/local/modules/HookLinks/I18n/frontOffice/default/ru_RU.php @@ -0,0 +1,10 @@ + 'Корзина', + 'Checkout' => 'Оформить заказ', + 'Log out!' => 'Выход', + 'Login' => 'Вход', + 'My Account' => 'Мой аккаунт', + 'Register' => 'Регистрация', +); diff --git a/local/modules/HookLinks/I18n/frontOffice/default/tr_TR.php b/local/modules/HookLinks/I18n/frontOffice/default/tr_TR.php new file mode 100644 index 00000000..88c01521 --- /dev/null +++ b/local/modules/HookLinks/I18n/frontOffice/default/tr_TR.php @@ -0,0 +1,10 @@ + 'Sepet', + 'Checkout' => 'Ödeme yap', + 'Log out!' => 'Çıkış Yap!', + 'Login' => 'Giriş yap', + 'My Account' => 'Hesabım', + 'Register' => 'Kaydol', +]; diff --git a/local/modules/HookLinks/I18n/it_IT.php b/local/modules/HookLinks/I18n/it_IT.php new file mode 100644 index 00000000..6120aafa --- /dev/null +++ b/local/modules/HookLinks/I18n/it_IT.php @@ -0,0 +1,5 @@ + 'Link utili', +]; diff --git a/local/modules/HookLinks/I18n/ru_RU.php b/local/modules/HookLinks/I18n/ru_RU.php new file mode 100644 index 00000000..82f0c5b9 --- /dev/null +++ b/local/modules/HookLinks/I18n/ru_RU.php @@ -0,0 +1,5 @@ + 'Полезные ссылки', +); diff --git a/local/modules/HookLinks/I18n/tr_TR.php b/local/modules/HookLinks/I18n/tr_TR.php new file mode 100644 index 00000000..3f99d1ee --- /dev/null +++ b/local/modules/HookLinks/I18n/tr_TR.php @@ -0,0 +1,5 @@ + 'Faydalı Linkler', +]; diff --git a/local/modules/HookLinks/LICENSE.txt b/local/modules/HookLinks/LICENSE.txt new file mode 100644 index 00000000..65c5ca88 --- /dev/null +++ b/local/modules/HookLinks/LICENSE.txt @@ -0,0 +1,165 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + + This version of the GNU Lesser General Public License incorporates +the terms and conditions of version 3 of the GNU General Public +License, supplemented by the additional permissions listed below. + + 0. Additional Definitions. + + As used herein, "this License" refers to version 3 of the GNU Lesser +General Public License, and the "GNU GPL" refers to version 3 of the GNU +General Public License. + + "The Library" refers to a covered work governed by this License, +other than an Application or a Combined Work as defined below. + + An "Application" is any work that makes use of an interface provided +by the Library, but which is not otherwise based on the Library. +Defining a subclass of a class defined by the Library is deemed a mode +of using an interface provided by the Library. + + A "Combined Work" is a work produced by combining or linking an +Application with the Library. The particular version of the Library +with which the Combined Work was made is also called the "Linked +Version". + + The "Minimal Corresponding Source" for a Combined Work means the +Corresponding Source for the Combined Work, excluding any source code +for portions of the Combined Work that, considered in isolation, are +based on the Application, and not on the Linked Version. + + The "Corresponding Application Code" for a Combined Work means the +object code and/or source code for the Application, including any data +and utility programs needed for reproducing the Combined Work from the +Application, but excluding the System Libraries of the Combined Work. + + 1. Exception to Section 3 of the GNU GPL. + + You may convey a covered work under sections 3 and 4 of this License +without being bound by section 3 of the GNU GPL. + + 2. Conveying Modified Versions. + + If you modify a copy of the Library, and, in your modifications, a +facility refers to a function or data to be supplied by an Application +that uses the facility (other than as an argument passed when the +facility is invoked), then you may convey a copy of the modified +version: + + a) under this License, provided that you make a good faith effort to + ensure that, in the event an Application does not supply the + function or data, the facility still operates, and performs + whatever part of its purpose remains meaningful, or + + b) under the GNU GPL, with none of the additional permissions of + this License applicable to that copy. + + 3. Object Code Incorporating Material from Library Header Files. + + The object code form of an Application may incorporate material from +a header file that is part of the Library. You may convey such object +code under terms of your choice, provided that, if the incorporated +material is not limited to numerical parameters, data structure +layouts and accessors, or small macros, inline functions and templates +(ten or fewer lines in length), you do both of the following: + + a) Give prominent notice with each copy of the object code that the + Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the object code with a copy of the GNU GPL and this license + document. + + 4. Combined Works. + + You may convey a Combined Work under terms of your choice that, +taken together, effectively do not restrict modification of the +portions of the Library contained in the Combined Work and reverse +engineering for debugging such modifications, if you also do each of +the following: + + a) Give prominent notice with each copy of the Combined Work that + the Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the Combined Work with a copy of the GNU GPL and this license + document. + + c) For a Combined Work that displays copyright notices during + execution, include the copyright notice for the Library among + these notices, as well as a reference directing the user to the + copies of the GNU GPL and this license document. + + d) Do one of the following: + + 0) Convey the Minimal Corresponding Source under the terms of this + License, and the Corresponding Application Code in a form + suitable for, and under terms that permit, the user to + recombine or relink the Application with a modified version of + the Linked Version to produce a modified Combined Work, in the + manner specified by section 6 of the GNU GPL for conveying + Corresponding Source. + + 1) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (a) uses at run time + a copy of the Library already present on the user's computer + system, and (b) will operate properly with a modified version + of the Library that is interface-compatible with the Linked + Version. + + e) Provide Installation Information, but only if you would otherwise + be required to provide such information under section 6 of the + GNU GPL, and only to the extent that such information is + necessary to install and execute a modified version of the + Combined Work produced by recombining or relinking the + Application with a modified version of the Linked Version. (If + you use option 4d0, the Installation Information must accompany + the Minimal Corresponding Source and Corresponding Application + Code. If you use option 4d1, you must provide the Installation + Information in the manner specified by section 6 of the GNU GPL + for conveying Corresponding Source.) + + 5. Combined Libraries. + + You may place library facilities that are a work based on the +Library side by side in a single library together with other library +facilities that are not Applications and are not covered by this +License, and convey such a combined library under terms of your +choice, if you do both of the following: + + a) Accompany the combined library with a copy of the same work based + on the Library, uncombined with any other library facilities, + conveyed under the terms of this License. + + b) Give prominent notice with the combined library that part of it + is a work based on the Library, and explaining where to find the + accompanying uncombined form of the same work. + + 6. Revised Versions of the GNU Lesser General Public License. + + The Free Software Foundation may publish revised and/or new versions +of the GNU Lesser General Public License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. + + Each version is given a distinguishing version number. If the +Library as you received it specifies that a certain numbered version +of the GNU Lesser General Public License "or any later version" +applies to it, you have the option of following the terms and +conditions either of that published version or of any later version +published by the Free Software Foundation. If the Library as you +received it does not specify a version number of the GNU Lesser +General Public License, you may choose any version of the GNU Lesser +General Public License ever published by the Free Software Foundation. + + If the Library as you received it specifies that a proxy can decide +whether future versions of the GNU Lesser General Public License shall +apply, that proxy's public statement of acceptance of any version is +permanent authorization for you to choose that version for the +Library. diff --git a/local/modules/HookLinks/composer.json b/local/modules/HookLinks/composer.json new file mode 100644 index 00000000..23abd78e --- /dev/null +++ b/local/modules/HookLinks/composer.json @@ -0,0 +1,11 @@ +{ + "name": "thelia/hook-links-module", + "license": "LGPL-3.0+", + "type": "thelia-module", + "require": { + "thelia/installer": "~1.1" + }, + "extra": { + "installer-name": "HookLinks" + } +} diff --git a/local/modules/HookLinks/templates/frontOffice/default/main-footer-body.html b/local/modules/HookLinks/templates/frontOffice/default/main-footer-body.html new file mode 100644 index 00000000..08607f06 --- /dev/null +++ b/local/modules/HookLinks/templates/frontOffice/default/main-footer-body.html @@ -0,0 +1,15 @@ + \ No newline at end of file diff --git a/local/modules/HookNavigation/Config/config.xml b/local/modules/HookNavigation/Config/config.xml new file mode 100644 index 00000000..1da4b2b4 --- /dev/null +++ b/local/modules/HookNavigation/Config/config.xml @@ -0,0 +1,17 @@ + + + + + +
    + + + + + + + + + + + diff --git a/local/modules/HookNavigation/Config/module.xml b/local/modules/HookNavigation/Config/module.xml new file mode 100644 index 00000000..39f7f36e --- /dev/null +++ b/local/modules/HookNavigation/Config/module.xml @@ -0,0 +1,24 @@ + + + HookNavigation\HookNavigation + + Block Navigation + + + Bloc Menu + + + en_US + fr_FR + + 2.4.3 + + Julien Chanséaume + jchanseaume@openstudio.fr + + classic + 2.4.3 + alpha + diff --git a/local/modules/HookNavigation/Config/routing.xml b/local/modules/HookNavigation/Config/routing.xml new file mode 100644 index 00000000..2182aa3c --- /dev/null +++ b/local/modules/HookNavigation/Config/routing.xml @@ -0,0 +1,9 @@ + + + + HookNavigation:HookNavigationConfig:default + + + HookNavigation:HookNavigationConfig:save + + diff --git a/local/modules/HookNavigation/Controller/HookNavigationConfigController.php b/local/modules/HookNavigation/Controller/HookNavigationConfigController.php new file mode 100644 index 00000000..04b7ca5f --- /dev/null +++ b/local/modules/HookNavigation/Controller/HookNavigationConfigController.php @@ -0,0 +1,75 @@ + - OpenStudio + */ +class HookNavigationConfigController extends BaseAdminController +{ + public function defaultAction() + { + $bodyConfig = HookNavigation::getConfigValue(HookNavigationConfigValue::FOOTER_BODY_FOLDER_ID); + $bottomConfig = HookNavigation::getConfigValue(HookNavigationConfigValue::FOOTER_BOTTOM_FOLDER_ID); + + $this->getSession()->getFlashBag()->set('bodyConfig', $bodyConfig); + $this->getSession()->getFlashBag()->set('bottomConfig', $bottomConfig); + + return $this->render('hooknavigation-configuration'); + } + + public function saveAction() + { + $baseForm = $this->createForm('hooknavigation.configuration'); + + $errorMessage = null; + + try { + $form = $this->validateForm($baseForm); + $data = $form->getData(); + + HookNavigation::setConfigValue(HookNavigationConfigValue::FOOTER_BODY_FOLDER_ID, is_bool($data['footer_body_folder_id']) ? (int) ($data['footer_body_folder_id']) : $data['footer_body_folder_id']); + HookNavigation::setConfigValue(HookNavigationConfigValue::FOOTER_BOTTOM_FOLDER_ID, is_bool($data['footer_bottom_folder_id']) ? (int) ($data['footer_bottom_folder_id']) : $data['footer_bottom_folder_id']); + } catch (FormValidationException $ex) { + // Invalid data entered + $errorMessage = $this->createStandardFormValidationErrorMessage($ex); + } catch (\Exception $ex) { + // Any other error + $errorMessage = $this->getTranslator()->trans('Sorry, an error occurred: %err', ['%err' => $ex->getMessage()], [], HookNavigation::MESSAGE_DOMAIN); + } + + if (null !== $errorMessage) { + // Mark the form as with error + $baseForm->setErrorMessage($errorMessage); + + // Send the form and the error to the parser + $this->getParserContext() + ->addForm($baseForm) + ->setGeneralError($errorMessage) + ; + } else { + $this->getParserContext() + ->set('success', true) + ; + } + + return $this->defaultAction(); + } +} diff --git a/local/modules/HookNavigation/Form/HookNavigationConfigForm.php b/local/modules/HookNavigation/Form/HookNavigationConfigForm.php new file mode 100644 index 00000000..84221749 --- /dev/null +++ b/local/modules/HookNavigation/Form/HookNavigationConfigForm.php @@ -0,0 +1,55 @@ + - OpenStudio + */ +class HookNavigationConfigForm extends BaseForm +{ + public function getName() + { + return 'hooknavigation_configuration'; + } + + protected function buildForm() + { + $this->formBuilder + ->add( + 'footer_body_folder_id', + 'number', + [ + 'constraints' => [ + new NotBlank(), + ], + 'label' => $this->translator->trans('Folder in footer body', [], HookNavigation::MESSAGE_DOMAIN), + ] + ) + ->add( + 'footer_bottom_folder_id', + 'number', + [ + 'constraints' => [ + new NotBlank(), + ], + 'label' => $this->translator->trans('Folder in footer bottom', [], HookNavigation::MESSAGE_DOMAIN), + ] + ); + } +} diff --git a/local/modules/HookNavigation/Hook/FrontHook.php b/local/modules/HookNavigation/Hook/FrontHook.php new file mode 100644 index 00000000..a108f3a0 --- /dev/null +++ b/local/modules/HookNavigation/Hook/FrontHook.php @@ -0,0 +1,51 @@ +, Etienne PERRIERE - OpenStudio + */ +class FrontHook extends BaseHook +{ + public function onMainFooterBody(HookRenderBlockEvent $event) + { + $bodyConfig = HookNavigation::getConfigValue(HookNavigationConfigValue::FOOTER_BODY_FOLDER_ID); + + $content = trim($this->render('main-footer-body.html', ['bodyFolderId' => $bodyConfig])); + if ('' != $content) { + $event->add(array( + 'id' => 'navigation-footer-body', + 'class' => 'links', + 'title' => $this->trans('Latest articles', array(), HookNavigation::MESSAGE_DOMAIN), + 'content' => $content, + )); + } + } + + public function onMainFooterBottom(HookRenderEvent $event) + { + $bottomConfig = HookNavigation::getConfigValue(HookNavigationConfigValue::FOOTER_BOTTOM_FOLDER_ID); + + $content = $this->render('main-footer-bottom.html', ['bottomFolderId' => $bottomConfig]); + $event->add($content); + } +} diff --git a/local/modules/HookNavigation/HookNavigation.php b/local/modules/HookNavigation/HookNavigation.php new file mode 100644 index 00000000..a878b090 --- /dev/null +++ b/local/modules/HookNavigation/HookNavigation.php @@ -0,0 +1,24 @@ + 'Kategorien', + 'Folder in footer body' => 'Ordner in Fußzeile', + 'Folder in footer bottom' => 'Ordner in Fußzeile', + 'Home' => 'Startseite', + 'HookNavigation configuration' => 'HookNavigation Konfiguration', + 'No articles currently' => 'Zur Zeit keine Artikel', + 'Toggle navigation' => 'Navigation umschalten', +]; diff --git a/local/modules/HookNavigation/I18n/backOffice/default/en_US.php b/local/modules/HookNavigation/I18n/backOffice/default/en_US.php new file mode 100644 index 00000000..88e66b06 --- /dev/null +++ b/local/modules/HookNavigation/I18n/backOffice/default/en_US.php @@ -0,0 +1,10 @@ + 'Configuration correctly saved', + 'Configure hooknavigation' => 'Configure hooknavigation', + 'Home' => 'Home', + 'HookNavigation configuration' => 'HookNavigation configuration', + 'Modules' => 'Modules', + 'Select a folder' => 'Select a folder', +); diff --git a/local/modules/HookNavigation/I18n/backOffice/default/fr_FR.php b/local/modules/HookNavigation/I18n/backOffice/default/fr_FR.php new file mode 100644 index 00000000..04211f37 --- /dev/null +++ b/local/modules/HookNavigation/I18n/backOffice/default/fr_FR.php @@ -0,0 +1,10 @@ + 'Configuration sauvegardée correctement', + 'Configure hooknavigation' => 'Configurer Bloc Menu', + 'Home' => 'Accueil', + 'HookNavigation configuration' => 'Configuration de Block Menu', + 'Modules' => 'Modules', + 'Select a folder' => 'Sélectionner un dossier', +]; diff --git a/local/modules/HookNavigation/I18n/backOffice/default/it_IT.php b/local/modules/HookNavigation/I18n/backOffice/default/it_IT.php new file mode 100644 index 00000000..7b04d958 --- /dev/null +++ b/local/modules/HookNavigation/I18n/backOffice/default/it_IT.php @@ -0,0 +1,7 @@ + 'Home', + 'Modules' => 'Moduli', + 'Select a folder' => 'Seleziona una cartella', +]; diff --git a/local/modules/HookNavigation/I18n/backOffice/default/ru_RU.php b/local/modules/HookNavigation/I18n/backOffice/default/ru_RU.php new file mode 100644 index 00000000..5e227035 --- /dev/null +++ b/local/modules/HookNavigation/I18n/backOffice/default/ru_RU.php @@ -0,0 +1,10 @@ + 'Конфигурация успешно сохранена', + 'Configure hooknavigation' => 'Настройка HookNavigation', + 'Home' => 'Главная', + 'HookNavigation configuration' => 'Конфигурация HookNavigation', + 'Modules' => 'Модули', + 'Select a folder' => 'Выберите папку', +); diff --git a/local/modules/HookNavigation/I18n/backOffice/default/tr_TR.php b/local/modules/HookNavigation/I18n/backOffice/default/tr_TR.php new file mode 100644 index 00000000..6816d794 --- /dev/null +++ b/local/modules/HookNavigation/I18n/backOffice/default/tr_TR.php @@ -0,0 +1,11 @@ + 'Katogoriler', + 'Folder in footer body' => 'Altbilgi vücut klasöründe', + 'Folder in footer bottom' => 'Altbilgi alt klasöründe', + 'Home' => 'Ana sayfa', + 'HookNavigation configuration' => 'HookNavigation yapılandırma', + 'No articles currently' => 'Hiç makale yok', + 'Toggle navigation' => 'Navigasyonu değiştir', +]; diff --git a/local/modules/HookNavigation/I18n/en_US.php b/local/modules/HookNavigation/I18n/en_US.php new file mode 100644 index 00000000..cfcc1fe2 --- /dev/null +++ b/local/modules/HookNavigation/I18n/en_US.php @@ -0,0 +1,8 @@ + 'Folder in footer body', + 'Folder in footer bottom' => 'Folder in footer bottom', + 'Latest articles' => 'Latest articles', + 'Sorry, an error occurred: %err' => 'Sorry, an error occurred: %err', +); diff --git a/local/modules/HookNavigation/I18n/fr_FR.php b/local/modules/HookNavigation/I18n/fr_FR.php new file mode 100644 index 00000000..28b686ad --- /dev/null +++ b/local/modules/HookNavigation/I18n/fr_FR.php @@ -0,0 +1,8 @@ + 'Dossier du pied de page', + 'Folder in footer bottom' => 'Dossier sous le pied de page', + 'Latest articles' => 'Derniers articles', + 'Sorry, an error occurred: %err' => 'Désolé, une erreur est survenue: %err', +]; diff --git a/local/modules/HookNavigation/I18n/frontOffice/default/de_DE.php b/local/modules/HookNavigation/I18n/frontOffice/default/de_DE.php new file mode 100644 index 00000000..c32bbb2a --- /dev/null +++ b/local/modules/HookNavigation/I18n/frontOffice/default/de_DE.php @@ -0,0 +1,6 @@ + 'Neueste Artikel', + 'No articles currently' => 'Zur Zeit keine Artikel', +]; diff --git a/local/modules/HookNavigation/I18n/frontOffice/default/en_US.php b/local/modules/HookNavigation/I18n/frontOffice/default/en_US.php new file mode 100644 index 00000000..d63a3877 --- /dev/null +++ b/local/modules/HookNavigation/I18n/frontOffice/default/en_US.php @@ -0,0 +1,8 @@ + 'Categories', + 'Home' => 'Home', + 'No articles currently' => 'No articles currently', + 'Toggle navigation' => 'Toggle navigation', +); diff --git a/local/modules/HookNavigation/I18n/frontOffice/default/fr_FR.php b/local/modules/HookNavigation/I18n/frontOffice/default/fr_FR.php new file mode 100644 index 00000000..6d26f6f9 --- /dev/null +++ b/local/modules/HookNavigation/I18n/frontOffice/default/fr_FR.php @@ -0,0 +1,8 @@ + 'Rubriques', + 'Home' => 'Accueil', + 'No articles currently' => 'Aucun article pour le moment', + 'Toggle navigation' => 'Basculer la navigation', +]; diff --git a/local/modules/HookNavigation/I18n/frontOffice/default/it_IT.php b/local/modules/HookNavigation/I18n/frontOffice/default/it_IT.php new file mode 100644 index 00000000..c7165516 --- /dev/null +++ b/local/modules/HookNavigation/I18n/frontOffice/default/it_IT.php @@ -0,0 +1,8 @@ + 'Categorie', + 'Home' => 'Home', + 'No articles currently' => 'Attualmente non sono presenti articoli', + 'Toggle navigation' => 'Toggle navigation', +]; diff --git a/local/modules/HookNavigation/I18n/frontOffice/default/ru_RU.php b/local/modules/HookNavigation/I18n/frontOffice/default/ru_RU.php new file mode 100644 index 00000000..e6d972ed --- /dev/null +++ b/local/modules/HookNavigation/I18n/frontOffice/default/ru_RU.php @@ -0,0 +1,8 @@ + 'Категории', + 'Home' => 'Главная', + 'No articles currently' => 'Пока статей нет', + 'Toggle navigation' => 'Переключить навигацию', +); diff --git a/local/modules/HookNavigation/I18n/frontOffice/default/tr_TR.php b/local/modules/HookNavigation/I18n/frontOffice/default/tr_TR.php new file mode 100644 index 00000000..a76a2b01 --- /dev/null +++ b/local/modules/HookNavigation/I18n/frontOffice/default/tr_TR.php @@ -0,0 +1,6 @@ + 'Son Makaleler', + 'No articles currently' => 'Hiç makale yok', +]; diff --git a/local/modules/HookNavigation/I18n/it_IT.php b/local/modules/HookNavigation/I18n/it_IT.php new file mode 100644 index 00000000..8ae2a7f1 --- /dev/null +++ b/local/modules/HookNavigation/I18n/it_IT.php @@ -0,0 +1,5 @@ + 'Ultimi articoli', +]; diff --git a/local/modules/HookNavigation/I18n/ru_RU.php b/local/modules/HookNavigation/I18n/ru_RU.php new file mode 100644 index 00000000..71ed17c5 --- /dev/null +++ b/local/modules/HookNavigation/I18n/ru_RU.php @@ -0,0 +1,8 @@ + 'Папка внизу страницы', + 'Folder in footer bottom' => 'Папка в подвале страницы', + 'Latest articles' => 'Последние статьи', + 'Sorry, an error occurred: %err' => 'К сожалению произошла ошибка: %err', +); diff --git a/local/modules/HookNavigation/LICENSE.txt b/local/modules/HookNavigation/LICENSE.txt new file mode 100644 index 00000000..65c5ca88 --- /dev/null +++ b/local/modules/HookNavigation/LICENSE.txt @@ -0,0 +1,165 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + + This version of the GNU Lesser General Public License incorporates +the terms and conditions of version 3 of the GNU General Public +License, supplemented by the additional permissions listed below. + + 0. Additional Definitions. + + As used herein, "this License" refers to version 3 of the GNU Lesser +General Public License, and the "GNU GPL" refers to version 3 of the GNU +General Public License. + + "The Library" refers to a covered work governed by this License, +other than an Application or a Combined Work as defined below. + + An "Application" is any work that makes use of an interface provided +by the Library, but which is not otherwise based on the Library. +Defining a subclass of a class defined by the Library is deemed a mode +of using an interface provided by the Library. + + A "Combined Work" is a work produced by combining or linking an +Application with the Library. The particular version of the Library +with which the Combined Work was made is also called the "Linked +Version". + + The "Minimal Corresponding Source" for a Combined Work means the +Corresponding Source for the Combined Work, excluding any source code +for portions of the Combined Work that, considered in isolation, are +based on the Application, and not on the Linked Version. + + The "Corresponding Application Code" for a Combined Work means the +object code and/or source code for the Application, including any data +and utility programs needed for reproducing the Combined Work from the +Application, but excluding the System Libraries of the Combined Work. + + 1. Exception to Section 3 of the GNU GPL. + + You may convey a covered work under sections 3 and 4 of this License +without being bound by section 3 of the GNU GPL. + + 2. Conveying Modified Versions. + + If you modify a copy of the Library, and, in your modifications, a +facility refers to a function or data to be supplied by an Application +that uses the facility (other than as an argument passed when the +facility is invoked), then you may convey a copy of the modified +version: + + a) under this License, provided that you make a good faith effort to + ensure that, in the event an Application does not supply the + function or data, the facility still operates, and performs + whatever part of its purpose remains meaningful, or + + b) under the GNU GPL, with none of the additional permissions of + this License applicable to that copy. + + 3. Object Code Incorporating Material from Library Header Files. + + The object code form of an Application may incorporate material from +a header file that is part of the Library. You may convey such object +code under terms of your choice, provided that, if the incorporated +material is not limited to numerical parameters, data structure +layouts and accessors, or small macros, inline functions and templates +(ten or fewer lines in length), you do both of the following: + + a) Give prominent notice with each copy of the object code that the + Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the object code with a copy of the GNU GPL and this license + document. + + 4. Combined Works. + + You may convey a Combined Work under terms of your choice that, +taken together, effectively do not restrict modification of the +portions of the Library contained in the Combined Work and reverse +engineering for debugging such modifications, if you also do each of +the following: + + a) Give prominent notice with each copy of the Combined Work that + the Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the Combined Work with a copy of the GNU GPL and this license + document. + + c) For a Combined Work that displays copyright notices during + execution, include the copyright notice for the Library among + these notices, as well as a reference directing the user to the + copies of the GNU GPL and this license document. + + d) Do one of the following: + + 0) Convey the Minimal Corresponding Source under the terms of this + License, and the Corresponding Application Code in a form + suitable for, and under terms that permit, the user to + recombine or relink the Application with a modified version of + the Linked Version to produce a modified Combined Work, in the + manner specified by section 6 of the GNU GPL for conveying + Corresponding Source. + + 1) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (a) uses at run time + a copy of the Library already present on the user's computer + system, and (b) will operate properly with a modified version + of the Library that is interface-compatible with the Linked + Version. + + e) Provide Installation Information, but only if you would otherwise + be required to provide such information under section 6 of the + GNU GPL, and only to the extent that such information is + necessary to install and execute a modified version of the + Combined Work produced by recombining or relinking the + Application with a modified version of the Linked Version. (If + you use option 4d0, the Installation Information must accompany + the Minimal Corresponding Source and Corresponding Application + Code. If you use option 4d1, you must provide the Installation + Information in the manner specified by section 6 of the GNU GPL + for conveying Corresponding Source.) + + 5. Combined Libraries. + + You may place library facilities that are a work based on the +Library side by side in a single library together with other library +facilities that are not Applications and are not covered by this +License, and convey such a combined library under terms of your +choice, if you do both of the following: + + a) Accompany the combined library with a copy of the same work based + on the Library, uncombined with any other library facilities, + conveyed under the terms of this License. + + b) Give prominent notice with the combined library that part of it + is a work based on the Library, and explaining where to find the + accompanying uncombined form of the same work. + + 6. Revised Versions of the GNU Lesser General Public License. + + The Free Software Foundation may publish revised and/or new versions +of the GNU Lesser General Public License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. + + Each version is given a distinguishing version number. If the +Library as you received it specifies that a certain numbered version +of the GNU Lesser General Public License "or any later version" +applies to it, you have the option of following the terms and +conditions either of that published version or of any later version +published by the Free Software Foundation. If the Library as you +received it does not specify a version number of the GNU Lesser +General Public License, you may choose any version of the GNU Lesser +General Public License ever published by the Free Software Foundation. + + If the Library as you received it specifies that a proxy can decide +whether future versions of the GNU Lesser General Public License shall +apply, that proxy's public statement of acceptance of any version is +permanent authorization for you to choose that version for the +Library. diff --git a/local/modules/HookNavigation/Model/Config/Base/HookNavigationConfigValue.php b/local/modules/HookNavigation/Model/Config/Base/HookNavigationConfigValue.php new file mode 100644 index 00000000..925f6c5e --- /dev/null +++ b/local/modules/HookNavigation/Model/Config/Base/HookNavigationConfigValue.php @@ -0,0 +1,23 @@ + + + +
    +
    + {intl l="Configure hooknavigation" d="hooknavigation.bo.default"} +
    + +
    +
    + {if $success} +
    + {intl l="Configuration correctly saved" d="hooknavigation.bo.default"} +
    + {/if} + + {form name="hooknavigation.configuration"} + + {include "includes/inner-form-toolbar.html" hide_flags = 1 close_url={url path='/admin/modules'}} +
    + + {form_field form=$form field="success_url"} + + {/form_field} + + {form_hidden_fields form=$form} + + {flash type="bodyConfig"} + {assign var='bodyConfig' value=$MESSAGE} + {/flash} + {flash type="bottomConfig"} + {assign var='bottomConfig' value=$MESSAGE} + {/flash} + + {form_field form=$form field="footer_body_folder_id"} +
    + + + + + {if ! empty($label_attr.help)} + {$label_attr.help} + {/if} +
    + {/form_field} + + {form_field form=$form field="footer_bottom_folder_id"} +
    + + + + + {if ! empty($label_attr.help)} + {$label_attr.help} + {/if} +
    + {/form_field} + + {include "includes/inner-form-toolbar.html" hide_flags = 1 close_url={url path='/admin/modules'} page_bottom = 1} + + {/form} +
    +
    +
    + +{/block} + +{block name="javascript-initialization"} +{/block} \ No newline at end of file diff --git a/local/modules/HookNavigation/templates/frontOffice/default/main-footer-body.html b/local/modules/HookNavigation/templates/frontOffice/default/main-footer-body.html new file mode 100644 index 00000000..4834c61d --- /dev/null +++ b/local/modules/HookNavigation/templates/frontOffice/default/main-footer-body.html @@ -0,0 +1,17 @@ +{ifloop rel="blog.articles"} + +{/ifloop} +{elseloop rel="blog.articles"} +
      +
    • {intl l="No articles currently" d="hooknavigation.fo.default"}
    • +
    +{/elseloop} \ No newline at end of file diff --git a/local/modules/HookNavigation/templates/frontOffice/default/main-footer-bottom.html b/local/modules/HookNavigation/templates/frontOffice/default/main-footer-bottom.html new file mode 100644 index 00000000..80b298ef --- /dev/null +++ b/local/modules/HookNavigation/templates/frontOffice/default/main-footer-bottom.html @@ -0,0 +1,7 @@ + \ No newline at end of file diff --git a/local/modules/HookNavigation/templates/frontOffice/default/main-navbar-primary.html b/local/modules/HookNavigation/templates/frontOffice/default/main-navbar-primary.html new file mode 100644 index 00000000..62514618 --- /dev/null +++ b/local/modules/HookNavigation/templates/frontOffice/default/main-navbar-primary.html @@ -0,0 +1,56 @@ + + +{* classic navbar without dropdown + +*} \ No newline at end of file diff --git a/local/modules/HookNewsletter/Config/config.xml b/local/modules/HookNewsletter/Config/config.xml new file mode 100644 index 00000000..9d66a2fe --- /dev/null +++ b/local/modules/HookNewsletter/Config/config.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + diff --git a/local/modules/HookNewsletter/Config/module.xml b/local/modules/HookNewsletter/Config/module.xml new file mode 100644 index 00000000..be654f2e --- /dev/null +++ b/local/modules/HookNewsletter/Config/module.xml @@ -0,0 +1,24 @@ + + + HookNewsletter\HookNewsletter + + Block Newsletter + + + Bloc Newsletter + + + en_US + fr_FR + + 2.4.3 + + Julien Chanséaume + jchanseaume@openstudio.fr + + classic + 2.4.3 + alpha + diff --git a/local/modules/HookNewsletter/Hook/FrontHook.php b/local/modules/HookNewsletter/Hook/FrontHook.php new file mode 100644 index 00000000..0d1b9688 --- /dev/null +++ b/local/modules/HookNewsletter/Hook/FrontHook.php @@ -0,0 +1,37 @@ + + */ +class FrontHook extends BaseHook { + + public function onMainFooterBody(HookRenderBlockEvent $event) + { + $content = trim($this->render("main-footer-body.html")); + if ("" != $content){ + $event->add(array( + "id" => "newsletter-footer-body", + "class" => "newsletter", + "title" => $this->trans("Newsletter", array(), "hooknewsletter"), + "content" => $content + )); + } + } +} \ No newline at end of file diff --git a/local/modules/HookNewsletter/HookNewsletter.php b/local/modules/HookNewsletter/HookNewsletter.php new file mode 100644 index 00000000..887b4a07 --- /dev/null +++ b/local/modules/HookNewsletter/HookNewsletter.php @@ -0,0 +1,20 @@ + 'Newsletter', +]; diff --git a/local/modules/HookNewsletter/I18n/en_US.php b/local/modules/HookNewsletter/I18n/en_US.php new file mode 100644 index 00000000..eeea5e3d --- /dev/null +++ b/local/modules/HookNewsletter/I18n/en_US.php @@ -0,0 +1,5 @@ + 'Newsletter', +); diff --git a/local/modules/HookNewsletter/I18n/fr_FR.php b/local/modules/HookNewsletter/I18n/fr_FR.php new file mode 100644 index 00000000..67c6b531 --- /dev/null +++ b/local/modules/HookNewsletter/I18n/fr_FR.php @@ -0,0 +1,5 @@ + 'Lettre d\'information', +]; diff --git a/local/modules/HookNewsletter/I18n/frontOffice/default/de_DE.php b/local/modules/HookNewsletter/I18n/frontOffice/default/de_DE.php new file mode 100644 index 00000000..9de40b6a --- /dev/null +++ b/local/modules/HookNewsletter/I18n/frontOffice/default/de_DE.php @@ -0,0 +1,8 @@ + 'E-mail Adresse', + 'Sign up to receive our latest news.' => 'Abonnieren Sie unseren Newsletter.', + 'Subscribe' => 'Abonnieren', + 'Your email address' => 'Ihre E-Mail-Adresse', +]; diff --git a/local/modules/HookNewsletter/I18n/frontOffice/default/en_US.php b/local/modules/HookNewsletter/I18n/frontOffice/default/en_US.php new file mode 100644 index 00000000..68f5056a --- /dev/null +++ b/local/modules/HookNewsletter/I18n/frontOffice/default/en_US.php @@ -0,0 +1,8 @@ + 'Email address', + 'Sign up to receive our latest news.' => 'Sign up to receive our latest news.', + 'Subscribe' => 'Subscribe', + 'Your email address' => 'Your email address', +); diff --git a/local/modules/HookNewsletter/I18n/frontOffice/default/fr_FR.php b/local/modules/HookNewsletter/I18n/frontOffice/default/fr_FR.php new file mode 100644 index 00000000..17819d1f --- /dev/null +++ b/local/modules/HookNewsletter/I18n/frontOffice/default/fr_FR.php @@ -0,0 +1,8 @@ + 'Adresse e-mail', + 'Sign up to receive our latest news.' => 'Enregistrez vous pour recevoir nos dernières nouvelles.', + 'Subscribe' => 'Inscription', + 'Your email address' => 'Votre adresse email', +]; diff --git a/local/modules/HookNewsletter/I18n/frontOffice/default/it_IT.php b/local/modules/HookNewsletter/I18n/frontOffice/default/it_IT.php new file mode 100644 index 00000000..563e28bd --- /dev/null +++ b/local/modules/HookNewsletter/I18n/frontOffice/default/it_IT.php @@ -0,0 +1,6 @@ + 'Indirizzo email', + 'Subscribe' => 'Abbonati', +]; diff --git a/local/modules/HookNewsletter/I18n/frontOffice/default/ru_RU.php b/local/modules/HookNewsletter/I18n/frontOffice/default/ru_RU.php new file mode 100644 index 00000000..022c9393 --- /dev/null +++ b/local/modules/HookNewsletter/I18n/frontOffice/default/ru_RU.php @@ -0,0 +1,8 @@ + 'E-mail адрес', + 'Sign up to receive our latest news.' => 'Подпишитесь для получения новостей от нас', + 'Subscribe' => 'Подписаться', + 'Your email address' => 'Ваш email адрес', +); diff --git a/local/modules/HookNewsletter/I18n/frontOffice/default/tr_TR.php b/local/modules/HookNewsletter/I18n/frontOffice/default/tr_TR.php new file mode 100644 index 00000000..dcc2918f --- /dev/null +++ b/local/modules/HookNewsletter/I18n/frontOffice/default/tr_TR.php @@ -0,0 +1,8 @@ + 'Eposta adresi', + 'Sign up to receive our latest news.' => 'En yeni haberleri almak için kaydolun.', + 'Subscribe' => 'Abone Ol', + 'Your email address' => 'E-posta adresiniz', +]; diff --git a/local/modules/HookNewsletter/I18n/it_IT.php b/local/modules/HookNewsletter/I18n/it_IT.php new file mode 100644 index 00000000..8e9757db --- /dev/null +++ b/local/modules/HookNewsletter/I18n/it_IT.php @@ -0,0 +1,5 @@ + 'Newsletter', +]; diff --git a/local/modules/HookNewsletter/I18n/ru_RU.php b/local/modules/HookNewsletter/I18n/ru_RU.php new file mode 100644 index 00000000..147f54c6 --- /dev/null +++ b/local/modules/HookNewsletter/I18n/ru_RU.php @@ -0,0 +1,5 @@ + 'Подписка', +); diff --git a/local/modules/HookNewsletter/I18n/tr_TR.php b/local/modules/HookNewsletter/I18n/tr_TR.php new file mode 100644 index 00000000..6d9159e5 --- /dev/null +++ b/local/modules/HookNewsletter/I18n/tr_TR.php @@ -0,0 +1,5 @@ + 'E-Bülten', +]; diff --git a/local/modules/HookNewsletter/LICENSE.txt b/local/modules/HookNewsletter/LICENSE.txt new file mode 100644 index 00000000..65c5ca88 --- /dev/null +++ b/local/modules/HookNewsletter/LICENSE.txt @@ -0,0 +1,165 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + + This version of the GNU Lesser General Public License incorporates +the terms and conditions of version 3 of the GNU General Public +License, supplemented by the additional permissions listed below. + + 0. Additional Definitions. + + As used herein, "this License" refers to version 3 of the GNU Lesser +General Public License, and the "GNU GPL" refers to version 3 of the GNU +General Public License. + + "The Library" refers to a covered work governed by this License, +other than an Application or a Combined Work as defined below. + + An "Application" is any work that makes use of an interface provided +by the Library, but which is not otherwise based on the Library. +Defining a subclass of a class defined by the Library is deemed a mode +of using an interface provided by the Library. + + A "Combined Work" is a work produced by combining or linking an +Application with the Library. The particular version of the Library +with which the Combined Work was made is also called the "Linked +Version". + + The "Minimal Corresponding Source" for a Combined Work means the +Corresponding Source for the Combined Work, excluding any source code +for portions of the Combined Work that, considered in isolation, are +based on the Application, and not on the Linked Version. + + The "Corresponding Application Code" for a Combined Work means the +object code and/or source code for the Application, including any data +and utility programs needed for reproducing the Combined Work from the +Application, but excluding the System Libraries of the Combined Work. + + 1. Exception to Section 3 of the GNU GPL. + + You may convey a covered work under sections 3 and 4 of this License +without being bound by section 3 of the GNU GPL. + + 2. Conveying Modified Versions. + + If you modify a copy of the Library, and, in your modifications, a +facility refers to a function or data to be supplied by an Application +that uses the facility (other than as an argument passed when the +facility is invoked), then you may convey a copy of the modified +version: + + a) under this License, provided that you make a good faith effort to + ensure that, in the event an Application does not supply the + function or data, the facility still operates, and performs + whatever part of its purpose remains meaningful, or + + b) under the GNU GPL, with none of the additional permissions of + this License applicable to that copy. + + 3. Object Code Incorporating Material from Library Header Files. + + The object code form of an Application may incorporate material from +a header file that is part of the Library. You may convey such object +code under terms of your choice, provided that, if the incorporated +material is not limited to numerical parameters, data structure +layouts and accessors, or small macros, inline functions and templates +(ten or fewer lines in length), you do both of the following: + + a) Give prominent notice with each copy of the object code that the + Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the object code with a copy of the GNU GPL and this license + document. + + 4. Combined Works. + + You may convey a Combined Work under terms of your choice that, +taken together, effectively do not restrict modification of the +portions of the Library contained in the Combined Work and reverse +engineering for debugging such modifications, if you also do each of +the following: + + a) Give prominent notice with each copy of the Combined Work that + the Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the Combined Work with a copy of the GNU GPL and this license + document. + + c) For a Combined Work that displays copyright notices during + execution, include the copyright notice for the Library among + these notices, as well as a reference directing the user to the + copies of the GNU GPL and this license document. + + d) Do one of the following: + + 0) Convey the Minimal Corresponding Source under the terms of this + License, and the Corresponding Application Code in a form + suitable for, and under terms that permit, the user to + recombine or relink the Application with a modified version of + the Linked Version to produce a modified Combined Work, in the + manner specified by section 6 of the GNU GPL for conveying + Corresponding Source. + + 1) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (a) uses at run time + a copy of the Library already present on the user's computer + system, and (b) will operate properly with a modified version + of the Library that is interface-compatible with the Linked + Version. + + e) Provide Installation Information, but only if you would otherwise + be required to provide such information under section 6 of the + GNU GPL, and only to the extent that such information is + necessary to install and execute a modified version of the + Combined Work produced by recombining or relinking the + Application with a modified version of the Linked Version. (If + you use option 4d0, the Installation Information must accompany + the Minimal Corresponding Source and Corresponding Application + Code. If you use option 4d1, you must provide the Installation + Information in the manner specified by section 6 of the GNU GPL + for conveying Corresponding Source.) + + 5. Combined Libraries. + + You may place library facilities that are a work based on the +Library side by side in a single library together with other library +facilities that are not Applications and are not covered by this +License, and convey such a combined library under terms of your +choice, if you do both of the following: + + a) Accompany the combined library with a copy of the same work based + on the Library, uncombined with any other library facilities, + conveyed under the terms of this License. + + b) Give prominent notice with the combined library that part of it + is a work based on the Library, and explaining where to find the + accompanying uncombined form of the same work. + + 6. Revised Versions of the GNU Lesser General Public License. + + The Free Software Foundation may publish revised and/or new versions +of the GNU Lesser General Public License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. + + Each version is given a distinguishing version number. If the +Library as you received it specifies that a certain numbered version +of the GNU Lesser General Public License "or any later version" +applies to it, you have the option of following the terms and +conditions either of that published version or of any later version +published by the Free Software Foundation. If the Library as you +received it does not specify a version number of the GNU Lesser +General Public License, you may choose any version of the GNU Lesser +General Public License ever published by the Free Software Foundation. + + If the Library as you received it specifies that a proxy can decide +whether future versions of the GNU Lesser General Public License shall +apply, that proxy's public statement of acceptance of any version is +permanent authorization for you to choose that version for the +Library. diff --git a/local/modules/HookNewsletter/composer.json b/local/modules/HookNewsletter/composer.json new file mode 100644 index 00000000..230b69d6 --- /dev/null +++ b/local/modules/HookNewsletter/composer.json @@ -0,0 +1,11 @@ +{ + "name": "thelia/hook-newsletter-module", + "license": "LGPL-3.0+", + "type": "thelia-module", + "require": { + "thelia/installer": "~1.1" + }, + "extra": { + "installer-name": "HookNewsletter" + } +} diff --git a/local/modules/HookNewsletter/templates/frontOffice/default/main-footer-body.html b/local/modules/HookNewsletter/templates/frontOffice/default/main-footer-body.html new file mode 100644 index 00000000..f60e082e --- /dev/null +++ b/local/modules/HookNewsletter/templates/frontOffice/default/main-footer-body.html @@ -0,0 +1,13 @@ +

    {intl l="Sign up to receive our latest news." d="hooknewsletter.fo.default"}

    +{form name="thelia.front.newsletter"} +
    +{form_hidden_fields} +{form_field field="email"} +
    + + +
    +{/form_field} + +
    +{/form} \ No newline at end of file diff --git a/local/modules/HookProductsNew/Config/config.xml b/local/modules/HookProductsNew/Config/config.xml new file mode 100644 index 00000000..42df6539 --- /dev/null +++ b/local/modules/HookProductsNew/Config/config.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + diff --git a/local/modules/HookProductsNew/Config/module.xml b/local/modules/HookProductsNew/Config/module.xml new file mode 100644 index 00000000..f25a225d --- /dev/null +++ b/local/modules/HookProductsNew/Config/module.xml @@ -0,0 +1,24 @@ + + + HookProductsNew\HookProductsNew + + Block New Products + + + Bloc Nouveaux Produits + + + en_US + fr_FR + + 2.4.3 + + Julien Chanséaume + jchanseaume@openstudio.fr + + classic + 2.4.3 + alpha + diff --git a/local/modules/HookProductsNew/HookProductsNew.php b/local/modules/HookProductsNew/HookProductsNew.php new file mode 100644 index 00000000..16a92d08 --- /dev/null +++ b/local/modules/HookProductsNew/HookProductsNew.php @@ -0,0 +1,20 @@ + '+ Alle anzeigen', + 'Latest' => 'Neuigkeiten', +]; diff --git a/local/modules/HookProductsNew/I18n/frontOffice/default/en_US.php b/local/modules/HookProductsNew/I18n/frontOffice/default/en_US.php new file mode 100644 index 00000000..bd7cd7c7 --- /dev/null +++ b/local/modules/HookProductsNew/I18n/frontOffice/default/en_US.php @@ -0,0 +1,6 @@ + '+ View All', + 'Latest' => 'Latest', +); diff --git a/local/modules/HookProductsNew/I18n/frontOffice/default/fr_FR.php b/local/modules/HookProductsNew/I18n/frontOffice/default/fr_FR.php new file mode 100644 index 00000000..297a7334 --- /dev/null +++ b/local/modules/HookProductsNew/I18n/frontOffice/default/fr_FR.php @@ -0,0 +1,6 @@ + '+ Tout voir', + 'Latest' => 'Nouveautés', +]; diff --git a/local/modules/HookProductsNew/I18n/frontOffice/default/it_IT.php b/local/modules/HookProductsNew/I18n/frontOffice/default/it_IT.php new file mode 100644 index 00000000..f8284b5d --- /dev/null +++ b/local/modules/HookProductsNew/I18n/frontOffice/default/it_IT.php @@ -0,0 +1,6 @@ + '+ Mostra tutto', + 'Latest' => 'Ultimi', +]; diff --git a/local/modules/HookProductsNew/I18n/frontOffice/default/ru_RU.php b/local/modules/HookProductsNew/I18n/frontOffice/default/ru_RU.php new file mode 100644 index 00000000..7a74c01d --- /dev/null +++ b/local/modules/HookProductsNew/I18n/frontOffice/default/ru_RU.php @@ -0,0 +1,6 @@ + '+ Смотреть все', + 'Latest' => 'Новые', +); diff --git a/local/modules/HookProductsNew/I18n/frontOffice/default/tr_TR.php b/local/modules/HookProductsNew/I18n/frontOffice/default/tr_TR.php new file mode 100644 index 00000000..035d01d9 --- /dev/null +++ b/local/modules/HookProductsNew/I18n/frontOffice/default/tr_TR.php @@ -0,0 +1,6 @@ + '+ Hepsini gör', + 'Latest' => 'En son', +]; diff --git a/local/modules/HookProductsNew/LICENSE.txt b/local/modules/HookProductsNew/LICENSE.txt new file mode 100644 index 00000000..65c5ca88 --- /dev/null +++ b/local/modules/HookProductsNew/LICENSE.txt @@ -0,0 +1,165 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + + This version of the GNU Lesser General Public License incorporates +the terms and conditions of version 3 of the GNU General Public +License, supplemented by the additional permissions listed below. + + 0. Additional Definitions. + + As used herein, "this License" refers to version 3 of the GNU Lesser +General Public License, and the "GNU GPL" refers to version 3 of the GNU +General Public License. + + "The Library" refers to a covered work governed by this License, +other than an Application or a Combined Work as defined below. + + An "Application" is any work that makes use of an interface provided +by the Library, but which is not otherwise based on the Library. +Defining a subclass of a class defined by the Library is deemed a mode +of using an interface provided by the Library. + + A "Combined Work" is a work produced by combining or linking an +Application with the Library. The particular version of the Library +with which the Combined Work was made is also called the "Linked +Version". + + The "Minimal Corresponding Source" for a Combined Work means the +Corresponding Source for the Combined Work, excluding any source code +for portions of the Combined Work that, considered in isolation, are +based on the Application, and not on the Linked Version. + + The "Corresponding Application Code" for a Combined Work means the +object code and/or source code for the Application, including any data +and utility programs needed for reproducing the Combined Work from the +Application, but excluding the System Libraries of the Combined Work. + + 1. Exception to Section 3 of the GNU GPL. + + You may convey a covered work under sections 3 and 4 of this License +without being bound by section 3 of the GNU GPL. + + 2. Conveying Modified Versions. + + If you modify a copy of the Library, and, in your modifications, a +facility refers to a function or data to be supplied by an Application +that uses the facility (other than as an argument passed when the +facility is invoked), then you may convey a copy of the modified +version: + + a) under this License, provided that you make a good faith effort to + ensure that, in the event an Application does not supply the + function or data, the facility still operates, and performs + whatever part of its purpose remains meaningful, or + + b) under the GNU GPL, with none of the additional permissions of + this License applicable to that copy. + + 3. Object Code Incorporating Material from Library Header Files. + + The object code form of an Application may incorporate material from +a header file that is part of the Library. You may convey such object +code under terms of your choice, provided that, if the incorporated +material is not limited to numerical parameters, data structure +layouts and accessors, or small macros, inline functions and templates +(ten or fewer lines in length), you do both of the following: + + a) Give prominent notice with each copy of the object code that the + Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the object code with a copy of the GNU GPL and this license + document. + + 4. Combined Works. + + You may convey a Combined Work under terms of your choice that, +taken together, effectively do not restrict modification of the +portions of the Library contained in the Combined Work and reverse +engineering for debugging such modifications, if you also do each of +the following: + + a) Give prominent notice with each copy of the Combined Work that + the Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the Combined Work with a copy of the GNU GPL and this license + document. + + c) For a Combined Work that displays copyright notices during + execution, include the copyright notice for the Library among + these notices, as well as a reference directing the user to the + copies of the GNU GPL and this license document. + + d) Do one of the following: + + 0) Convey the Minimal Corresponding Source under the terms of this + License, and the Corresponding Application Code in a form + suitable for, and under terms that permit, the user to + recombine or relink the Application with a modified version of + the Linked Version to produce a modified Combined Work, in the + manner specified by section 6 of the GNU GPL for conveying + Corresponding Source. + + 1) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (a) uses at run time + a copy of the Library already present on the user's computer + system, and (b) will operate properly with a modified version + of the Library that is interface-compatible with the Linked + Version. + + e) Provide Installation Information, but only if you would otherwise + be required to provide such information under section 6 of the + GNU GPL, and only to the extent that such information is + necessary to install and execute a modified version of the + Combined Work produced by recombining or relinking the + Application with a modified version of the Linked Version. (If + you use option 4d0, the Installation Information must accompany + the Minimal Corresponding Source and Corresponding Application + Code. If you use option 4d1, you must provide the Installation + Information in the manner specified by section 6 of the GNU GPL + for conveying Corresponding Source.) + + 5. Combined Libraries. + + You may place library facilities that are a work based on the +Library side by side in a single library together with other library +facilities that are not Applications and are not covered by this +License, and convey such a combined library under terms of your +choice, if you do both of the following: + + a) Accompany the combined library with a copy of the same work based + on the Library, uncombined with any other library facilities, + conveyed under the terms of this License. + + b) Give prominent notice with the combined library that part of it + is a work based on the Library, and explaining where to find the + accompanying uncombined form of the same work. + + 6. Revised Versions of the GNU Lesser General Public License. + + The Free Software Foundation may publish revised and/or new versions +of the GNU Lesser General Public License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. + + Each version is given a distinguishing version number. If the +Library as you received it specifies that a certain numbered version +of the GNU Lesser General Public License "or any later version" +applies to it, you have the option of following the terms and +conditions either of that published version or of any later version +published by the Free Software Foundation. If the Library as you +received it does not specify a version number of the GNU Lesser +General Public License, you may choose any version of the GNU Lesser +General Public License ever published by the Free Software Foundation. + + If the Library as you received it specifies that a proxy can decide +whether future versions of the GNU Lesser General Public License shall +apply, that proxy's public statement of acceptance of any version is +permanent authorization for you to choose that version for the +Library. diff --git a/local/modules/HookProductsNew/composer.json b/local/modules/HookProductsNew/composer.json new file mode 100644 index 00000000..37573922 --- /dev/null +++ b/local/modules/HookProductsNew/composer.json @@ -0,0 +1,11 @@ +{ + "name": "thelia/hook-products-new-module", + "license": "LGPL-3.0+", + "type": "thelia-module", + "require": { + "thelia/installer": "~1.1" + }, + "extra": { + "installer-name": "HookProductsNew" + } +} diff --git a/local/modules/HookProductsNew/templates/frontOffice/default/home-body.html b/local/modules/HookProductsNew/templates/frontOffice/default/home-body.html new file mode 100644 index 00000000..11f6004a --- /dev/null +++ b/local/modules/HookProductsNew/templates/frontOffice/default/home-body.html @@ -0,0 +1,59 @@ +{ifloop rel="product_new"} +
    +
    +

    {intl l="Latest" d="hookproductsnew.fo.default"} {intl l="+ View All" d="hookproductsnew.fo.default"}

    +
    +
    + +
    +
    +{/ifloop} diff --git a/local/modules/HookProductsOffer/Config/config.xml b/local/modules/HookProductsOffer/Config/config.xml new file mode 100644 index 00000000..00e4ebb5 --- /dev/null +++ b/local/modules/HookProductsOffer/Config/config.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + diff --git a/local/modules/HookProductsOffer/Config/module.xml b/local/modules/HookProductsOffer/Config/module.xml new file mode 100644 index 00000000..d7a2cd04 --- /dev/null +++ b/local/modules/HookProductsOffer/Config/module.xml @@ -0,0 +1,24 @@ + + + HookProductsOffer\HookProductsOffer + + Block Promo Products + + + Bloc Produits en promo + + + en_US + fr_FR + + 2.4.3 + + Julien Chanséaume + jchanseaume@openstudio.fr + + classic + 2.4.3 + alpha + diff --git a/local/modules/HookProductsOffer/HookProductsOffer.php b/local/modules/HookProductsOffer/HookProductsOffer.php new file mode 100644 index 00000000..2b04e7f8 --- /dev/null +++ b/local/modules/HookProductsOffer/HookProductsOffer.php @@ -0,0 +1,20 @@ + '+ Alle sehen', + 'Offers' => 'Angebote', +]; diff --git a/local/modules/HookProductsOffer/I18n/frontOffice/default/en_US.php b/local/modules/HookProductsOffer/I18n/frontOffice/default/en_US.php new file mode 100644 index 00000000..9b4a1c61 --- /dev/null +++ b/local/modules/HookProductsOffer/I18n/frontOffice/default/en_US.php @@ -0,0 +1,6 @@ + '+ View All', + 'Offers' => 'Offers', +); diff --git a/local/modules/HookProductsOffer/I18n/frontOffice/default/fr_FR.php b/local/modules/HookProductsOffer/I18n/frontOffice/default/fr_FR.php new file mode 100644 index 00000000..3dbf4a11 --- /dev/null +++ b/local/modules/HookProductsOffer/I18n/frontOffice/default/fr_FR.php @@ -0,0 +1,6 @@ + '+ Tout voir', + 'Offers' => 'Promotions', +]; diff --git a/local/modules/HookProductsOffer/I18n/frontOffice/default/it_IT.php b/local/modules/HookProductsOffer/I18n/frontOffice/default/it_IT.php new file mode 100644 index 00000000..ba350c21 --- /dev/null +++ b/local/modules/HookProductsOffer/I18n/frontOffice/default/it_IT.php @@ -0,0 +1,6 @@ + '+ Mostra tutto', + 'Offers' => 'Offerte', +]; diff --git a/local/modules/HookProductsOffer/I18n/frontOffice/default/ru_RU.php b/local/modules/HookProductsOffer/I18n/frontOffice/default/ru_RU.php new file mode 100644 index 00000000..a3d352ca --- /dev/null +++ b/local/modules/HookProductsOffer/I18n/frontOffice/default/ru_RU.php @@ -0,0 +1,6 @@ + '+ Смотреть все', + 'Offers' => 'Предложения', +); diff --git a/local/modules/HookProductsOffer/I18n/frontOffice/default/tr_TR.php b/local/modules/HookProductsOffer/I18n/frontOffice/default/tr_TR.php new file mode 100644 index 00000000..bc9c3e6b --- /dev/null +++ b/local/modules/HookProductsOffer/I18n/frontOffice/default/tr_TR.php @@ -0,0 +1,6 @@ + '+ Hepsini gör', + 'Offers' => 'Teklifler', +]; diff --git a/local/modules/HookProductsOffer/LICENSE.txt b/local/modules/HookProductsOffer/LICENSE.txt new file mode 100644 index 00000000..65c5ca88 --- /dev/null +++ b/local/modules/HookProductsOffer/LICENSE.txt @@ -0,0 +1,165 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + + This version of the GNU Lesser General Public License incorporates +the terms and conditions of version 3 of the GNU General Public +License, supplemented by the additional permissions listed below. + + 0. Additional Definitions. + + As used herein, "this License" refers to version 3 of the GNU Lesser +General Public License, and the "GNU GPL" refers to version 3 of the GNU +General Public License. + + "The Library" refers to a covered work governed by this License, +other than an Application or a Combined Work as defined below. + + An "Application" is any work that makes use of an interface provided +by the Library, but which is not otherwise based on the Library. +Defining a subclass of a class defined by the Library is deemed a mode +of using an interface provided by the Library. + + A "Combined Work" is a work produced by combining or linking an +Application with the Library. The particular version of the Library +with which the Combined Work was made is also called the "Linked +Version". + + The "Minimal Corresponding Source" for a Combined Work means the +Corresponding Source for the Combined Work, excluding any source code +for portions of the Combined Work that, considered in isolation, are +based on the Application, and not on the Linked Version. + + The "Corresponding Application Code" for a Combined Work means the +object code and/or source code for the Application, including any data +and utility programs needed for reproducing the Combined Work from the +Application, but excluding the System Libraries of the Combined Work. + + 1. Exception to Section 3 of the GNU GPL. + + You may convey a covered work under sections 3 and 4 of this License +without being bound by section 3 of the GNU GPL. + + 2. Conveying Modified Versions. + + If you modify a copy of the Library, and, in your modifications, a +facility refers to a function or data to be supplied by an Application +that uses the facility (other than as an argument passed when the +facility is invoked), then you may convey a copy of the modified +version: + + a) under this License, provided that you make a good faith effort to + ensure that, in the event an Application does not supply the + function or data, the facility still operates, and performs + whatever part of its purpose remains meaningful, or + + b) under the GNU GPL, with none of the additional permissions of + this License applicable to that copy. + + 3. Object Code Incorporating Material from Library Header Files. + + The object code form of an Application may incorporate material from +a header file that is part of the Library. You may convey such object +code under terms of your choice, provided that, if the incorporated +material is not limited to numerical parameters, data structure +layouts and accessors, or small macros, inline functions and templates +(ten or fewer lines in length), you do both of the following: + + a) Give prominent notice with each copy of the object code that the + Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the object code with a copy of the GNU GPL and this license + document. + + 4. Combined Works. + + You may convey a Combined Work under terms of your choice that, +taken together, effectively do not restrict modification of the +portions of the Library contained in the Combined Work and reverse +engineering for debugging such modifications, if you also do each of +the following: + + a) Give prominent notice with each copy of the Combined Work that + the Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the Combined Work with a copy of the GNU GPL and this license + document. + + c) For a Combined Work that displays copyright notices during + execution, include the copyright notice for the Library among + these notices, as well as a reference directing the user to the + copies of the GNU GPL and this license document. + + d) Do one of the following: + + 0) Convey the Minimal Corresponding Source under the terms of this + License, and the Corresponding Application Code in a form + suitable for, and under terms that permit, the user to + recombine or relink the Application with a modified version of + the Linked Version to produce a modified Combined Work, in the + manner specified by section 6 of the GNU GPL for conveying + Corresponding Source. + + 1) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (a) uses at run time + a copy of the Library already present on the user's computer + system, and (b) will operate properly with a modified version + of the Library that is interface-compatible with the Linked + Version. + + e) Provide Installation Information, but only if you would otherwise + be required to provide such information under section 6 of the + GNU GPL, and only to the extent that such information is + necessary to install and execute a modified version of the + Combined Work produced by recombining or relinking the + Application with a modified version of the Linked Version. (If + you use option 4d0, the Installation Information must accompany + the Minimal Corresponding Source and Corresponding Application + Code. If you use option 4d1, you must provide the Installation + Information in the manner specified by section 6 of the GNU GPL + for conveying Corresponding Source.) + + 5. Combined Libraries. + + You may place library facilities that are a work based on the +Library side by side in a single library together with other library +facilities that are not Applications and are not covered by this +License, and convey such a combined library under terms of your +choice, if you do both of the following: + + a) Accompany the combined library with a copy of the same work based + on the Library, uncombined with any other library facilities, + conveyed under the terms of this License. + + b) Give prominent notice with the combined library that part of it + is a work based on the Library, and explaining where to find the + accompanying uncombined form of the same work. + + 6. Revised Versions of the GNU Lesser General Public License. + + The Free Software Foundation may publish revised and/or new versions +of the GNU Lesser General Public License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. + + Each version is given a distinguishing version number. If the +Library as you received it specifies that a certain numbered version +of the GNU Lesser General Public License "or any later version" +applies to it, you have the option of following the terms and +conditions either of that published version or of any later version +published by the Free Software Foundation. If the Library as you +received it does not specify a version number of the GNU Lesser +General Public License, you may choose any version of the GNU Lesser +General Public License ever published by the Free Software Foundation. + + If the Library as you received it specifies that a proxy can decide +whether future versions of the GNU Lesser General Public License shall +apply, that proxy's public statement of acceptance of any version is +permanent authorization for you to choose that version for the +Library. diff --git a/local/modules/HookProductsOffer/composer.json b/local/modules/HookProductsOffer/composer.json new file mode 100644 index 00000000..8329abdb --- /dev/null +++ b/local/modules/HookProductsOffer/composer.json @@ -0,0 +1,11 @@ +{ + "name": "thelia/hook-products-offer-module", + "license": "LGPL-3.0+", + "type": "thelia-module", + "require": { + "thelia/installer": "~1.1" + }, + "extra": { + "installer-name": "HookProductsOffer" + } +} diff --git a/local/modules/HookProductsOffer/templates/frontOffice/default/home-body.html b/local/modules/HookProductsOffer/templates/frontOffice/default/home-body.html new file mode 100644 index 00000000..462e775a --- /dev/null +++ b/local/modules/HookProductsOffer/templates/frontOffice/default/home-body.html @@ -0,0 +1,39 @@ +{ifloop rel="current-sales"} +
    + {loop name="current-sales" type="sale" limit="2"} +
    + + +
    +
      + {loop name="products_in_sale" type="product" limit="4" sale=$ID} + {include file="includes/single-product.html" colClass="col-md-3 col-sm-4" product_id=$ID hasBtn=false hasDescription=false width="218" height="146"} + {/loop} +
    +
    +
    + {/loop} +
    +{/ifloop} +{* Display "regular" promos, if any, only if we don't have active sales *} + +{elseloop rel="current-sales"} +{ifloop rel="product_promo"} +
    +
    +

    {intl l="Offers" d="hookproductsoffer.fo.default"} {intl l="+ View All" d="hookproductsoffer.fo.default"}

    +
    + +
    +
      + {loop name="product_promo" type="product" limit="4" promo="yes"} + {include file="includes/single-product.html" colClass="col-md-3 col-sm-4" product_id=$ID hasBtn=false hasDescription=false width="218" height="146"} + {/loop} +
    +
    +
    +{/ifloop} +{/elseloop} diff --git a/local/modules/HookSearch/Config/config.xml b/local/modules/HookSearch/Config/config.xml new file mode 100644 index 00000000..b5d60c60 --- /dev/null +++ b/local/modules/HookSearch/Config/config.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + diff --git a/local/modules/HookSearch/Config/module.xml b/local/modules/HookSearch/Config/module.xml new file mode 100644 index 00000000..49c7f1d6 --- /dev/null +++ b/local/modules/HookSearch/Config/module.xml @@ -0,0 +1,24 @@ + + + HookSearch\HookSearch + + Block Search + + + Bloc Recherche + + + en_US + fr_FR + + 2.4.3 + + Julien Chanséaume + jchanseaume@openstudio.fr + + classic + 2.4.3 + alpha + diff --git a/local/modules/HookSearch/HookSearch.php b/local/modules/HookSearch/HookSearch.php new file mode 100644 index 00000000..bbe6d752 --- /dev/null +++ b/local/modules/HookSearch/HookSearch.php @@ -0,0 +1,20 @@ + 'Mindestens 2 Zeichen.', + 'Search' => 'Suchen', + 'Search a product' => 'Ein Produkt suchen', + 'Search...' => 'Suchen ...', +]; diff --git a/local/modules/HookSearch/I18n/frontOffice/default/en_US.php b/local/modules/HookSearch/I18n/frontOffice/default/en_US.php new file mode 100644 index 00000000..5d94b36c --- /dev/null +++ b/local/modules/HookSearch/I18n/frontOffice/default/en_US.php @@ -0,0 +1,8 @@ + 'Minimum 2 characters.', + 'Search' => 'Search', + 'Search a product' => 'Search a product', + 'Search...' => 'Search...', +); diff --git a/local/modules/HookSearch/I18n/frontOffice/default/fr_FR.php b/local/modules/HookSearch/I18n/frontOffice/default/fr_FR.php new file mode 100644 index 00000000..c115fb42 --- /dev/null +++ b/local/modules/HookSearch/I18n/frontOffice/default/fr_FR.php @@ -0,0 +1,8 @@ + '2 caractères minimum.', + 'Search' => 'Recherche', + 'Search a product' => 'Rechercher un produit', + 'Search...' => 'Rechercher...', +]; diff --git a/local/modules/HookSearch/I18n/frontOffice/default/it_IT.php b/local/modules/HookSearch/I18n/frontOffice/default/it_IT.php new file mode 100644 index 00000000..65ad8706 --- /dev/null +++ b/local/modules/HookSearch/I18n/frontOffice/default/it_IT.php @@ -0,0 +1,8 @@ + 'Minimo 2 caratteri.', + 'Search' => 'Ricerca', + 'Search a product' => 'Ricerca un prodotto', + 'Search...' => 'Ricerca...', +]; diff --git a/local/modules/HookSearch/I18n/frontOffice/default/ru_RU.php b/local/modules/HookSearch/I18n/frontOffice/default/ru_RU.php new file mode 100644 index 00000000..3e3139a7 --- /dev/null +++ b/local/modules/HookSearch/I18n/frontOffice/default/ru_RU.php @@ -0,0 +1,8 @@ + 'Минимум 2 символа.', + 'Search' => 'Поиск', + 'Search a product' => 'Поиск товара', + 'Search...' => 'Поиск...', +); diff --git a/local/modules/HookSearch/I18n/frontOffice/default/tr_TR.php b/local/modules/HookSearch/I18n/frontOffice/default/tr_TR.php new file mode 100644 index 00000000..e9d75686 --- /dev/null +++ b/local/modules/HookSearch/I18n/frontOffice/default/tr_TR.php @@ -0,0 +1,8 @@ + 'En az 2 karakter.', + 'Search' => 'Arama', + 'Search a product' => 'Ürün ara', + 'Search...' => 'Arama...', +]; diff --git a/local/modules/HookSearch/LICENSE.txt b/local/modules/HookSearch/LICENSE.txt new file mode 100644 index 00000000..65c5ca88 --- /dev/null +++ b/local/modules/HookSearch/LICENSE.txt @@ -0,0 +1,165 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + + This version of the GNU Lesser General Public License incorporates +the terms and conditions of version 3 of the GNU General Public +License, supplemented by the additional permissions listed below. + + 0. Additional Definitions. + + As used herein, "this License" refers to version 3 of the GNU Lesser +General Public License, and the "GNU GPL" refers to version 3 of the GNU +General Public License. + + "The Library" refers to a covered work governed by this License, +other than an Application or a Combined Work as defined below. + + An "Application" is any work that makes use of an interface provided +by the Library, but which is not otherwise based on the Library. +Defining a subclass of a class defined by the Library is deemed a mode +of using an interface provided by the Library. + + A "Combined Work" is a work produced by combining or linking an +Application with the Library. The particular version of the Library +with which the Combined Work was made is also called the "Linked +Version". + + The "Minimal Corresponding Source" for a Combined Work means the +Corresponding Source for the Combined Work, excluding any source code +for portions of the Combined Work that, considered in isolation, are +based on the Application, and not on the Linked Version. + + The "Corresponding Application Code" for a Combined Work means the +object code and/or source code for the Application, including any data +and utility programs needed for reproducing the Combined Work from the +Application, but excluding the System Libraries of the Combined Work. + + 1. Exception to Section 3 of the GNU GPL. + + You may convey a covered work under sections 3 and 4 of this License +without being bound by section 3 of the GNU GPL. + + 2. Conveying Modified Versions. + + If you modify a copy of the Library, and, in your modifications, a +facility refers to a function or data to be supplied by an Application +that uses the facility (other than as an argument passed when the +facility is invoked), then you may convey a copy of the modified +version: + + a) under this License, provided that you make a good faith effort to + ensure that, in the event an Application does not supply the + function or data, the facility still operates, and performs + whatever part of its purpose remains meaningful, or + + b) under the GNU GPL, with none of the additional permissions of + this License applicable to that copy. + + 3. Object Code Incorporating Material from Library Header Files. + + The object code form of an Application may incorporate material from +a header file that is part of the Library. You may convey such object +code under terms of your choice, provided that, if the incorporated +material is not limited to numerical parameters, data structure +layouts and accessors, or small macros, inline functions and templates +(ten or fewer lines in length), you do both of the following: + + a) Give prominent notice with each copy of the object code that the + Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the object code with a copy of the GNU GPL and this license + document. + + 4. Combined Works. + + You may convey a Combined Work under terms of your choice that, +taken together, effectively do not restrict modification of the +portions of the Library contained in the Combined Work and reverse +engineering for debugging such modifications, if you also do each of +the following: + + a) Give prominent notice with each copy of the Combined Work that + the Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the Combined Work with a copy of the GNU GPL and this license + document. + + c) For a Combined Work that displays copyright notices during + execution, include the copyright notice for the Library among + these notices, as well as a reference directing the user to the + copies of the GNU GPL and this license document. + + d) Do one of the following: + + 0) Convey the Minimal Corresponding Source under the terms of this + License, and the Corresponding Application Code in a form + suitable for, and under terms that permit, the user to + recombine or relink the Application with a modified version of + the Linked Version to produce a modified Combined Work, in the + manner specified by section 6 of the GNU GPL for conveying + Corresponding Source. + + 1) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (a) uses at run time + a copy of the Library already present on the user's computer + system, and (b) will operate properly with a modified version + of the Library that is interface-compatible with the Linked + Version. + + e) Provide Installation Information, but only if you would otherwise + be required to provide such information under section 6 of the + GNU GPL, and only to the extent that such information is + necessary to install and execute a modified version of the + Combined Work produced by recombining or relinking the + Application with a modified version of the Linked Version. (If + you use option 4d0, the Installation Information must accompany + the Minimal Corresponding Source and Corresponding Application + Code. If you use option 4d1, you must provide the Installation + Information in the manner specified by section 6 of the GNU GPL + for conveying Corresponding Source.) + + 5. Combined Libraries. + + You may place library facilities that are a work based on the +Library side by side in a single library together with other library +facilities that are not Applications and are not covered by this +License, and convey such a combined library under terms of your +choice, if you do both of the following: + + a) Accompany the combined library with a copy of the same work based + on the Library, uncombined with any other library facilities, + conveyed under the terms of this License. + + b) Give prominent notice with the combined library that part of it + is a work based on the Library, and explaining where to find the + accompanying uncombined form of the same work. + + 6. Revised Versions of the GNU Lesser General Public License. + + The Free Software Foundation may publish revised and/or new versions +of the GNU Lesser General Public License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. + + Each version is given a distinguishing version number. If the +Library as you received it specifies that a certain numbered version +of the GNU Lesser General Public License "or any later version" +applies to it, you have the option of following the terms and +conditions either of that published version or of any later version +published by the Free Software Foundation. If the Library as you +received it does not specify a version number of the GNU Lesser +General Public License, you may choose any version of the GNU Lesser +General Public License ever published by the Free Software Foundation. + + If the Library as you received it specifies that a proxy can decide +whether future versions of the GNU Lesser General Public License shall +apply, that proxy's public statement of acceptance of any version is +permanent authorization for you to choose that version for the +Library. diff --git a/local/modules/HookSearch/composer.json b/local/modules/HookSearch/composer.json new file mode 100644 index 00000000..9dfdcaf1 --- /dev/null +++ b/local/modules/HookSearch/composer.json @@ -0,0 +1,11 @@ +{ + "name": "thelia/hook-search-module", + "license": "LGPL-3.0+", + "type": "thelia-module", + "require": { + "thelia/installer": "~1.1" + }, + "extra": { + "installer-name": "HookSearch" + } +} diff --git a/local/modules/HookSearch/templates/frontOffice/default/assets/css/styles.css b/local/modules/HookSearch/templates/frontOffice/default/assets/css/styles.css new file mode 100644 index 00000000..74b18399 --- /dev/null +++ b/local/modules/HookSearch/templates/frontOffice/default/assets/css/styles.css @@ -0,0 +1,11 @@ +.header-container .search-container label, +.header-container .search-container .btn-search>span { + position:absolute; + width:1px; + height:1px; + margin:-1px; + padding:0; + overflow:hidden; + clip:rect(0 0 0 0); + border:0 +} \ No newline at end of file diff --git a/local/modules/HookSearch/templates/frontOffice/default/main-navbar-primary.html b/local/modules/HookSearch/templates/frontOffice/default/main-navbar-primary.html new file mode 100644 index 00000000..31c6afd2 --- /dev/null +++ b/local/modules/HookSearch/templates/frontOffice/default/main-navbar-primary.html @@ -0,0 +1,11 @@ + \ No newline at end of file diff --git a/local/modules/HookSearch/templates/frontOffice/default/main-navbar-secondary.html b/local/modules/HookSearch/templates/frontOffice/default/main-navbar-secondary.html new file mode 100644 index 00000000..40ba03a6 --- /dev/null +++ b/local/modules/HookSearch/templates/frontOffice/default/main-navbar-secondary.html @@ -0,0 +1,7 @@ + \ No newline at end of file diff --git a/local/modules/HookSocial/Config/config.xml b/local/modules/HookSocial/Config/config.xml new file mode 100644 index 00000000..f151f07c --- /dev/null +++ b/local/modules/HookSocial/Config/config.xml @@ -0,0 +1,21 @@ + + + + + +
    + + + + + + + + + + + + + diff --git a/local/modules/HookSocial/Config/module.xml b/local/modules/HookSocial/Config/module.xml new file mode 100644 index 00000000..acaa72d8 --- /dev/null +++ b/local/modules/HookSocial/Config/module.xml @@ -0,0 +1,24 @@ + + + HookSocial\HookSocial + + Block Social + + + Bloc Social + + + en_US + fr_FR + + 2.4.3 + + Julien Chanséaume + jchanseaume@openstudio.fr + + classic + 2.4.3 + alpha + diff --git a/local/modules/HookSocial/Config/routing.xml b/local/modules/HookSocial/Config/routing.xml new file mode 100644 index 00000000..769a2c4a --- /dev/null +++ b/local/modules/HookSocial/Config/routing.xml @@ -0,0 +1,10 @@ + + + + + HookSocial\Controller\Configuration::saveAction + + + diff --git a/local/modules/HookSocial/Controller/Configuration.php b/local/modules/HookSocial/Controller/Configuration.php new file mode 100644 index 00000000..9fef4bfa --- /dev/null +++ b/local/modules/HookSocial/Controller/Configuration.php @@ -0,0 +1,61 @@ + + */ +class Configuration extends BaseAdminController +{ + public function saveAction() + { + + if (null !== $response = $this->checkAuth(array(AdminResources::MODULE), array('hooksocial'), AccessManager::UPDATE)) { + return $response; + } + + $form = new \HookSocial\Form\Configuration($this->getRequest()); + $resp = array( + "error" => 0, + "message" => "" + ); + $response=null; + + try { + $vform = $this->validateForm($form); + $data = $vform->getData(); + + foreach ($data as $name => $value) { + if (! $form->isTemplateDefinedHiddenFieldName($name)) { + ConfigQuery::write("hooksocial_" . $name, $value, false, true); + } + + Tlog::getInstance()->debug(sprintf("%s => %s", $name, $value)); + } + } catch (\Exception $e) { + $resp["error"] = 1; + $resp["message"] = $e->getMessage(); + } + + return JsonResponse::create($resp); + } +} \ No newline at end of file diff --git a/local/modules/HookSocial/Form/Configuration.php b/local/modules/HookSocial/Form/Configuration.php new file mode 100644 index 00000000..82d7418b --- /dev/null +++ b/local/modules/HookSocial/Form/Configuration.php @@ -0,0 +1,86 @@ + + */ +class Configuration extends BaseForm { + + protected function buildForm() + { + $form = $this->formBuilder; + + $definitions = array( + array( + "id" => "twitter", + "label" => Translator::getInstance()->trans("Twitter username", array(), 'hooksocial') + ), + array( + "id" => "facebook", + "label" => Translator::getInstance()->trans("Facebook username", array(), 'hooksocial') + ), + array( + "id" => "google", + "label" => Translator::getInstance()->trans("Google + username", array(), 'hooksocial') + ), + array( + "id" => "instagram", + "label" => Translator::getInstance()->trans("Instagram username", array(), 'hooksocial') + ), + array( + "id" => "pinterest", + "label" => Translator::getInstance()->trans("Pinterest username", array(), 'hooksocial') + ), + array( + "id" => "youtube", + "label" => Translator::getInstance()->trans("Youtube URL", array(), 'hooksocial') + ), + array( + "id" => "rss", + "label" => Translator::getInstance()->trans("RSS URL", array(), 'hooksocial') + ) + ); + + foreach ($definitions as $field){ + $value = ConfigQuery::read("hooksocial_" . $field["id"], ""); + $form->add( + $field["id"], + "text", + array( + 'data' => $value, + 'label' => $field["label"], + 'label_attr' => array( + 'for' => $field["id"] + ), + ) + ); + } + } + + /** + * @return string the name of you form. This name must be unique + */ + public function getName() + { + return "hooksocial"; + } + + +} \ No newline at end of file diff --git a/local/modules/HookSocial/Hook/FrontHook.php b/local/modules/HookSocial/Hook/FrontHook.php new file mode 100644 index 00000000..770c2178 --- /dev/null +++ b/local/modules/HookSocial/Hook/FrontHook.php @@ -0,0 +1,37 @@ + + */ +class FrontHook extends BaseHook { + + public function onMainFooterBody(HookRenderBlockEvent $event) + { + $content = trim($this->render("main-footer-body.html")); + if ("" != $content){ + $event->add(array( + "id" => "social-footer-body", + "class" => "social", + "title" => $this->trans("Follow us", array(), "hooksocial"), + "content" => $content + )); + } + } +} \ No newline at end of file diff --git a/local/modules/HookSocial/HookSocial.php b/local/modules/HookSocial/HookSocial.php new file mode 100644 index 00000000..030e814d --- /dev/null +++ b/local/modules/HookSocial/HookSocial.php @@ -0,0 +1,20 @@ + 'Ein Fehler ist aufgetreten', + 'Save' => 'Speichern', +]; diff --git a/local/modules/HookSocial/I18n/backOffice/default/en_US.php b/local/modules/HookSocial/I18n/backOffice/default/en_US.php new file mode 100644 index 00000000..4ce9a282 --- /dev/null +++ b/local/modules/HookSocial/I18n/backOffice/default/en_US.php @@ -0,0 +1,7 @@ + 'An error occured', + 'Edit your social accounts.' => 'Edit your social accounts.', + 'Save' => 'Save', +); diff --git a/local/modules/HookSocial/I18n/backOffice/default/fr_FR.php b/local/modules/HookSocial/I18n/backOffice/default/fr_FR.php new file mode 100644 index 00000000..e08beb6c --- /dev/null +++ b/local/modules/HookSocial/I18n/backOffice/default/fr_FR.php @@ -0,0 +1,7 @@ + 'Une erreur est survenue', + 'Edit your social accounts.' => 'Modifier vos paramètres de réseaux sociaux.', + 'Save' => ' Enregistrer', +]; diff --git a/local/modules/HookSocial/I18n/backOffice/default/it_IT.php b/local/modules/HookSocial/I18n/backOffice/default/it_IT.php new file mode 100644 index 00000000..3099d7ba --- /dev/null +++ b/local/modules/HookSocial/I18n/backOffice/default/it_IT.php @@ -0,0 +1,6 @@ + 'Modifica i tuoi account social.', + 'Save' => 'Salvare', +]; diff --git a/local/modules/HookSocial/I18n/backOffice/default/ru_RU.php b/local/modules/HookSocial/I18n/backOffice/default/ru_RU.php new file mode 100644 index 00000000..e49dd213 --- /dev/null +++ b/local/modules/HookSocial/I18n/backOffice/default/ru_RU.php @@ -0,0 +1,7 @@ + 'Произошла ошибка', + 'Edit your social accounts.' => 'Редактировать ваши социальные аккаунты.', + 'Save' => 'Сохранить', +); diff --git a/local/modules/HookSocial/I18n/backOffice/default/tr_TR.php b/local/modules/HookSocial/I18n/backOffice/default/tr_TR.php new file mode 100644 index 00000000..f4d5e02c --- /dev/null +++ b/local/modules/HookSocial/I18n/backOffice/default/tr_TR.php @@ -0,0 +1,7 @@ + 'Bir hata meydana geldi', + 'Edit your social accounts.' => 'Sosyal hesaplarınızı düzenleyin.', + 'Save' => 'kaydet', +]; diff --git a/local/modules/HookSocial/I18n/de_DE.php b/local/modules/HookSocial/I18n/de_DE.php new file mode 100644 index 00000000..e6c7fb51 --- /dev/null +++ b/local/modules/HookSocial/I18n/de_DE.php @@ -0,0 +1,12 @@ + 'Facebook Benutzername', + 'Follow us' => 'Folgen Sie uns', + 'Google + username' => 'Google+ Benutzername', + 'Instagram username' => 'Instagram Benutzername', + 'Pinterest username' => 'Pinterest Benutzername', + 'RSS URL' => 'RSS-URL', + 'Twitter username' => 'Twitter Benutzername', + 'Youtube URL' => 'YouTube-URL', +]; diff --git a/local/modules/HookSocial/I18n/en_US.php b/local/modules/HookSocial/I18n/en_US.php new file mode 100644 index 00000000..dfb8eff8 --- /dev/null +++ b/local/modules/HookSocial/I18n/en_US.php @@ -0,0 +1,12 @@ + 'Facebook username', + 'Follow us' => 'Follow us', + 'Google + username' => 'Google + username', + 'Instagram username' => 'Instagram username', + 'Pinterest username' => 'Pinterest username', + 'RSS URL' => 'RSS URL', + 'Twitter username' => 'Twitter username', + 'Youtube URL' => 'Youtube URL', +); diff --git a/local/modules/HookSocial/I18n/fr_FR.php b/local/modules/HookSocial/I18n/fr_FR.php new file mode 100644 index 00000000..6f08ba6f --- /dev/null +++ b/local/modules/HookSocial/I18n/fr_FR.php @@ -0,0 +1,12 @@ + 'Nom d\'utilisateur Facebook', + 'Follow us' => 'Suivez-nous', + 'Google + username' => 'Nom d\'utilisateur Google +', + 'Instagram username' => 'Nom d\'utilisateur Instagram', + 'Pinterest username' => 'Nom d\'utilisateur Pinterest', + 'RSS URL' => 'URL du flux RSS', + 'Twitter username' => 'Nom d\'utilisateur Twitter', + 'Youtube URL' => 'URL Youtube', +]; diff --git a/local/modules/HookSocial/I18n/frontOffice/default/de_DE.php b/local/modules/HookSocial/I18n/frontOffice/default/de_DE.php new file mode 100644 index 00000000..938a9f4a --- /dev/null +++ b/local/modules/HookSocial/I18n/frontOffice/default/de_DE.php @@ -0,0 +1,10 @@ + 'Facebook', + 'Google+' => 'Google+', + 'Instagram' => 'Instagram', + 'RSS' => 'RSS-Feed', + 'Twitter' => 'Twitter', + 'Youtube' => 'YouTube', +]; diff --git a/local/modules/HookSocial/I18n/frontOffice/default/en_US.php b/local/modules/HookSocial/I18n/frontOffice/default/en_US.php new file mode 100644 index 00000000..534a4d03 --- /dev/null +++ b/local/modules/HookSocial/I18n/frontOffice/default/en_US.php @@ -0,0 +1,10 @@ + 'Facebook', + 'Google+' => 'Google+', + 'Instagram' => 'Instagram', + 'RSS' => 'RSS Feed', + 'Twitter' => 'Twitter', + 'Youtube' => 'Youtube', +); diff --git a/local/modules/HookSocial/I18n/frontOffice/default/fr_FR.php b/local/modules/HookSocial/I18n/frontOffice/default/fr_FR.php new file mode 100644 index 00000000..7b64f075 --- /dev/null +++ b/local/modules/HookSocial/I18n/frontOffice/default/fr_FR.php @@ -0,0 +1,10 @@ + 'Facebook', + 'Google+' => 'Google+', + 'Instagram' => 'Instagram', + 'RSS' => 'Flux RSS', + 'Twitter' => 'Twitter', + 'Youtube' => 'Youtube', +]; diff --git a/local/modules/HookSocial/I18n/frontOffice/default/it_IT.php b/local/modules/HookSocial/I18n/frontOffice/default/it_IT.php new file mode 100644 index 00000000..15298b70 --- /dev/null +++ b/local/modules/HookSocial/I18n/frontOffice/default/it_IT.php @@ -0,0 +1,10 @@ + 'Facebook', + 'Google+' => 'Google +', + 'Instagram' => 'Instagram', + 'RSS' => 'RSS Feed', + 'Twitter' => 'Twitter', + 'Youtube' => 'Youtube', +]; diff --git a/local/modules/HookSocial/I18n/frontOffice/default/ru_RU.php b/local/modules/HookSocial/I18n/frontOffice/default/ru_RU.php new file mode 100644 index 00000000..94a66926 --- /dev/null +++ b/local/modules/HookSocial/I18n/frontOffice/default/ru_RU.php @@ -0,0 +1,11 @@ + 'Facebook', + 'Google+' => 'Google+', + 'Instagram' => 'Instagram', + 'Pinterest' => 'Pinterest', + 'RSS' => 'RSS-канал', + 'Twitter' => 'Twitter', + 'Youtube' => 'Youtube', +); diff --git a/local/modules/HookSocial/I18n/frontOffice/default/tr_TR.php b/local/modules/HookSocial/I18n/frontOffice/default/tr_TR.php new file mode 100644 index 00000000..b951272b --- /dev/null +++ b/local/modules/HookSocial/I18n/frontOffice/default/tr_TR.php @@ -0,0 +1,10 @@ + 'Facebook', + 'Google+' => 'Google +', + 'Instagram' => 'Instagram', + 'RSS' => 'RSS Beslemesi', + 'Twitter' => 'Twitter', + 'Youtube' => 'Youtube', +]; diff --git a/local/modules/HookSocial/I18n/it_IT.php b/local/modules/HookSocial/I18n/it_IT.php new file mode 100644 index 00000000..e1fd072a --- /dev/null +++ b/local/modules/HookSocial/I18n/it_IT.php @@ -0,0 +1,12 @@ + 'Nome utente Facebook', + 'Follow us' => 'Seguici', + 'Google + username' => 'Nome utente Google +', + 'Instagram username' => 'Nome utente Instagram', + 'Pinterest username' => 'Nome utente Pinterest', + 'RSS URL' => 'RSS URL', + 'Twitter username' => 'Nome utente Twitter', + 'Youtube URL' => 'Youtube URL', +]; diff --git a/local/modules/HookSocial/I18n/ru_RU.php b/local/modules/HookSocial/I18n/ru_RU.php new file mode 100644 index 00000000..a1263242 --- /dev/null +++ b/local/modules/HookSocial/I18n/ru_RU.php @@ -0,0 +1,12 @@ + 'Имя пользователя Facebook', + 'Follow us' => 'Мы в соц сетях', + 'Google + username' => 'Имя пользователя Google +', + 'Instagram username' => 'Имя пользователя Instagram', + 'Pinterest username' => 'Имя пользователя Pinterest', + 'RSS URL' => 'RSS URL', + 'Twitter username' => 'Имя пользователя Twitter', + 'Youtube URL' => 'Youtube URL', +); diff --git a/local/modules/HookSocial/I18n/tr_TR.php b/local/modules/HookSocial/I18n/tr_TR.php new file mode 100644 index 00000000..c5ea54f4 --- /dev/null +++ b/local/modules/HookSocial/I18n/tr_TR.php @@ -0,0 +1,12 @@ + 'Facebook kullanıcı adı', + 'Follow us' => 'Bizi takip edin', + 'Google + username' => 'Google + kullanıcı adı', + 'Instagram username' => 'Google + kullanıcı adı', + 'Pinterest username' => 'Pinterest kullanıcı adı', + 'RSS URL' => 'RSS URL', + 'Twitter username' => 'Twitter kullanıcı adı', + 'Youtube URL' => 'YouTube URL', +]; diff --git a/local/modules/HookSocial/LICENSE.txt b/local/modules/HookSocial/LICENSE.txt new file mode 100644 index 00000000..65c5ca88 --- /dev/null +++ b/local/modules/HookSocial/LICENSE.txt @@ -0,0 +1,165 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + + This version of the GNU Lesser General Public License incorporates +the terms and conditions of version 3 of the GNU General Public +License, supplemented by the additional permissions listed below. + + 0. Additional Definitions. + + As used herein, "this License" refers to version 3 of the GNU Lesser +General Public License, and the "GNU GPL" refers to version 3 of the GNU +General Public License. + + "The Library" refers to a covered work governed by this License, +other than an Application or a Combined Work as defined below. + + An "Application" is any work that makes use of an interface provided +by the Library, but which is not otherwise based on the Library. +Defining a subclass of a class defined by the Library is deemed a mode +of using an interface provided by the Library. + + A "Combined Work" is a work produced by combining or linking an +Application with the Library. The particular version of the Library +with which the Combined Work was made is also called the "Linked +Version". + + The "Minimal Corresponding Source" for a Combined Work means the +Corresponding Source for the Combined Work, excluding any source code +for portions of the Combined Work that, considered in isolation, are +based on the Application, and not on the Linked Version. + + The "Corresponding Application Code" for a Combined Work means the +object code and/or source code for the Application, including any data +and utility programs needed for reproducing the Combined Work from the +Application, but excluding the System Libraries of the Combined Work. + + 1. Exception to Section 3 of the GNU GPL. + + You may convey a covered work under sections 3 and 4 of this License +without being bound by section 3 of the GNU GPL. + + 2. Conveying Modified Versions. + + If you modify a copy of the Library, and, in your modifications, a +facility refers to a function or data to be supplied by an Application +that uses the facility (other than as an argument passed when the +facility is invoked), then you may convey a copy of the modified +version: + + a) under this License, provided that you make a good faith effort to + ensure that, in the event an Application does not supply the + function or data, the facility still operates, and performs + whatever part of its purpose remains meaningful, or + + b) under the GNU GPL, with none of the additional permissions of + this License applicable to that copy. + + 3. Object Code Incorporating Material from Library Header Files. + + The object code form of an Application may incorporate material from +a header file that is part of the Library. You may convey such object +code under terms of your choice, provided that, if the incorporated +material is not limited to numerical parameters, data structure +layouts and accessors, or small macros, inline functions and templates +(ten or fewer lines in length), you do both of the following: + + a) Give prominent notice with each copy of the object code that the + Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the object code with a copy of the GNU GPL and this license + document. + + 4. Combined Works. + + You may convey a Combined Work under terms of your choice that, +taken together, effectively do not restrict modification of the +portions of the Library contained in the Combined Work and reverse +engineering for debugging such modifications, if you also do each of +the following: + + a) Give prominent notice with each copy of the Combined Work that + the Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the Combined Work with a copy of the GNU GPL and this license + document. + + c) For a Combined Work that displays copyright notices during + execution, include the copyright notice for the Library among + these notices, as well as a reference directing the user to the + copies of the GNU GPL and this license document. + + d) Do one of the following: + + 0) Convey the Minimal Corresponding Source under the terms of this + License, and the Corresponding Application Code in a form + suitable for, and under terms that permit, the user to + recombine or relink the Application with a modified version of + the Linked Version to produce a modified Combined Work, in the + manner specified by section 6 of the GNU GPL for conveying + Corresponding Source. + + 1) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (a) uses at run time + a copy of the Library already present on the user's computer + system, and (b) will operate properly with a modified version + of the Library that is interface-compatible with the Linked + Version. + + e) Provide Installation Information, but only if you would otherwise + be required to provide such information under section 6 of the + GNU GPL, and only to the extent that such information is + necessary to install and execute a modified version of the + Combined Work produced by recombining or relinking the + Application with a modified version of the Linked Version. (If + you use option 4d0, the Installation Information must accompany + the Minimal Corresponding Source and Corresponding Application + Code. If you use option 4d1, you must provide the Installation + Information in the manner specified by section 6 of the GNU GPL + for conveying Corresponding Source.) + + 5. Combined Libraries. + + You may place library facilities that are a work based on the +Library side by side in a single library together with other library +facilities that are not Applications and are not covered by this +License, and convey such a combined library under terms of your +choice, if you do both of the following: + + a) Accompany the combined library with a copy of the same work based + on the Library, uncombined with any other library facilities, + conveyed under the terms of this License. + + b) Give prominent notice with the combined library that part of it + is a work based on the Library, and explaining where to find the + accompanying uncombined form of the same work. + + 6. Revised Versions of the GNU Lesser General Public License. + + The Free Software Foundation may publish revised and/or new versions +of the GNU Lesser General Public License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. + + Each version is given a distinguishing version number. If the +Library as you received it specifies that a certain numbered version +of the GNU Lesser General Public License "or any later version" +applies to it, you have the option of following the terms and +conditions either of that published version or of any later version +published by the Free Software Foundation. If the Library as you +received it does not specify a version number of the GNU Lesser +General Public License, you may choose any version of the GNU Lesser +General Public License ever published by the Free Software Foundation. + + If the Library as you received it specifies that a proxy can decide +whether future versions of the GNU Lesser General Public License shall +apply, that proxy's public statement of acceptance of any version is +permanent authorization for you to choose that version for the +Library. diff --git a/local/modules/HookSocial/composer.json b/local/modules/HookSocial/composer.json new file mode 100644 index 00000000..4a18288a --- /dev/null +++ b/local/modules/HookSocial/composer.json @@ -0,0 +1,11 @@ +{ + "name": "thelia/hook-social-module", + "license": "LGPL-3.0+", + "type": "thelia-module", + "require": { + "thelia/installer": "~1.1" + }, + "extra": { + "installer-name": "HookSocial" + } +} diff --git a/local/modules/HookSocial/templates/backOffice/default/assets/js/module-configuration.js b/local/modules/HookSocial/templates/backOffice/default/assets/js/module-configuration.js new file mode 100644 index 00000000..5bf3dfcc --- /dev/null +++ b/local/modules/HookSocial/templates/backOffice/default/assets/js/module-configuration.js @@ -0,0 +1,28 @@ +$(document).ready(function() { + $("#hooksocial-form").on("submit", function(e, data){ + e.preventDefault(); + var form = $(this); + + $('body').append(''); + + $.ajax({ + url: form.attr('action'), + type: form.attr('method'), + data: form.serialize() + }).done(function(){ + $("#loading-event").remove(); + }) + .success(function(data) { + if (data.error != 0) { + $("#loading-event").remove(); + $('#hooksocial-failed-body').html(data.message); + $("#hooksocial-failed").modal("show"); + } + }) + .fail(function(jqXHR, textStatus, errorThrown){ + $("#loading-event").remove(); + $('#hooksocial-failed-body').html(jqXHR.responseJSON.message); + $("#hooksocial-failed").modal("show"); + }); + }); +}); \ No newline at end of file diff --git a/local/modules/HookSocial/templates/backOffice/default/module_configuration.html b/local/modules/HookSocial/templates/backOffice/default/module_configuration.html new file mode 100644 index 00000000..61a48c13 --- /dev/null +++ b/local/modules/HookSocial/templates/backOffice/default/module_configuration.html @@ -0,0 +1,94 @@ + + + +
    +
    + +
    + {intl d='hooksocial.bo.default' l='Edit your social accounts.'} +
    + +
    +
    + + {form name="hooksocial.configuration.form"} + + + {form_hidden_fields} + + {form_field field='twitter'} +
    + + +
    + {/form_field} + + {form_field field='facebook'} +
    + + +
    + {/form_field} + + {form_field field='google'} +
    + + +
    + {/form_field} + + {form_field field='instagram'} +
    + + +
    + {/form_field} + + {form_field field='pinterest'} +
    + + +
    + {/form_field} + + {form_field field='youtube'} +
    + + +
    + {/form_field} + + {form_field field='rss'} +
    + + +
    + {/form_field} + + + + {/form} + +
    + +
    + +
    +
    + + + + diff --git a/local/modules/HookSocial/templates/frontOffice/default/assets/css/styles.css b/local/modules/HookSocial/templates/frontOffice/default/assets/css/styles.css new file mode 100644 index 00000000..e69de29b diff --git a/local/modules/HookSocial/templates/frontOffice/default/main-footer-body.html b/local/modules/HookSocial/templates/frontOffice/default/main-footer-body.html new file mode 100644 index 00000000..095d7832 --- /dev/null +++ b/local/modules/HookSocial/templates/frontOffice/default/main-footer-body.html @@ -0,0 +1,86 @@ + \ No newline at end of file diff --git a/local/modules/TheliaMigrateCountry/Config/config.xml b/local/modules/TheliaMigrateCountry/Config/config.xml new file mode 100644 index 00000000..9a63718e --- /dev/null +++ b/local/modules/TheliaMigrateCountry/Config/config.xml @@ -0,0 +1,27 @@ + + + + + +
    + + + + + + + + + + + + + + + + + + + diff --git a/local/modules/TheliaMigrateCountry/Config/module.xml b/local/modules/TheliaMigrateCountry/Config/module.xml new file mode 100644 index 00000000..e567af8e --- /dev/null +++ b/local/modules/TheliaMigrateCountry/Config/module.xml @@ -0,0 +1,26 @@ + + + TheliaMigrateCountry\TheliaMigrateCountry + + Countries/states migration tool + + + Utilitaire de migration des pays/états + + + en_US + fr_FR + + 2.4.3 + + + Julien Chanséaume + julien@thelia.net + + + classic + 2.3.0 + alpha + diff --git a/local/modules/TheliaMigrateCountry/Config/routing.xml b/local/modules/TheliaMigrateCountry/Config/routing.xml new file mode 100644 index 00000000..111b7cb7 --- /dev/null +++ b/local/modules/TheliaMigrateCountry/Config/routing.xml @@ -0,0 +1,15 @@ + + + + + + TheliaMigrateCountry\Controller\MigrateController::migrateSystemAction + + + + TheliaMigrateCountry\Controller\MigrateController::doMigrateSystemAction + + + diff --git a/local/modules/TheliaMigrateCountry/Controller/MigrateController.php b/local/modules/TheliaMigrateCountry/Controller/MigrateController.php new file mode 100644 index 00000000..9b582845 --- /dev/null +++ b/local/modules/TheliaMigrateCountry/Controller/MigrateController.php @@ -0,0 +1,175 @@ + + */ +class MigrateController extends BaseAdminController +{ + protected $useFallbackTemplate = true; + + public function migrateSystemAction() + { + $response = $this->checkAuth(AdminResources::COUNTRY, array(), AccessManager::UPDATE); + if (null !== $response) { + return $response; + } + + // load country not migrated + $dataForm = []; + + $migratedCountries = json_decode(ConfigQuery::read('thelia_country_state_migration', '[]'), true); + + $countries = CountryQuery::create() + ->filterByHasStates(1) + ; + + /** @var Country $country */ + foreach ($countries as $country) { + $oldCountries = CountryQuery::create() + ->filterByHasStates(0) + ->filterByIsocode($country->getIsoCode()) + ->find() + ; + /** @var Country $oldCountry */ + foreach ($oldCountries as $oldCountry) { + if (!isset($migratedCountries[$oldCountry->getId()])) { + $dataForm[] = [ + 'migrate' => false, + 'country' => $oldCountry->getId(), + 'new_country' => $country->getId(), + 'new_state' => null + ]; + } + } + } + + // prepare form + $form = $this->createForm('thelia.admin.country.state.migration', 'form', ['migrations' => $dataForm]); + $this->getParserContext()->addForm($form); + + return $this->render( + 'countries-migrate', + [ + 'countriesMigrated' => $migratedCountries, + 'showForm' => count($dataForm) != 0 + ] + ); + } + + public function doMigrateSystemAction() + { + $response = $this->checkAuth(AdminResources::COUNTRY, array(), AccessManager::UPDATE); + if (null !== $response) { + return $response; + } + + $changeForm = $this->createForm('thelia.admin.country.state.migration', 'form'); + + try { + // Check the form against constraints violations + $form = $this->validateForm($changeForm, "POST"); + + // Get the form field values + $data = $form->getData(); + + foreach ($data['migrations'] as $migration) { + + if (!$migration['migrate']) { + continue; + } + + $changeEvent = new MigrateCountryEvent( + $migration['country'], + $migration['new_country'], + $migration['new_state'] + ); + + $this->dispatch(MigrateCountryEvents::MIGRATE_COUNTRY, $changeEvent); + + // memorize the migration + $migratedCountries = json_decode(ConfigQuery::read('thelia_country_state_migration', '[]'), true); + $migratedCountries[$changeEvent->getCountry()] = [ + 'country' => $changeEvent->getNewCountry(), + 'state' => $changeEvent->getNewState(), + 'counter' => $changeEvent->getCounter() + ]; + ConfigQuery::write('thelia_country_state_migration', json_encode($migratedCountries)); + + // message + $message = $this->getTranslator()->trans( + 'Country %id migrated to country (ID %country) and state (ID %state) (address: %address, tax rules: %tax, shipping zones: %zone)', + [ + '%id' => $changeEvent->getCountry(), + '%country' => $changeEvent->getNewCountry(), + '%state' => $changeEvent->getNewState(), + '%address' => $changeEvent->getCounter()[AddressTableMap::TABLE_NAME], + '%tax' => $changeEvent->getCounter()[TaxRuleCountryTableMap::TABLE_NAME], + '%zone' => $changeEvent->getCounter()[CountryAreaTableMap::TABLE_NAME] + ] + ); + + // add flash message + $this->getSession()->getFlashBag()->add('migrate', $message); + + // Log migration + $this->adminLogAppend( + AdminResources::COUNTRY, + AccessManager::UPDATE, + $message, + $changeEvent->getCountry() + ); + + } + + return $this->generateSuccessRedirect($changeForm); + } catch (FormValidationException $ex) { + // Form cannot be validated + $error_msg = $this->createStandardFormValidationErrorMessage($ex); + } + + if (false !== $error_msg) { + $this->setupFormErrorContext( + $this->getTranslator()->trans("Country migration"), + $error_msg, + $changeForm, + $ex + ); + + return $this->render( + 'countries-migrate', + [ + 'countriesMigrated' => $migratedCountries, + 'showForm' => true + ] + ); + } + } +} diff --git a/local/modules/TheliaMigrateCountry/EventListeners/MigrateCountryListener.php b/local/modules/TheliaMigrateCountry/EventListeners/MigrateCountryListener.php new file mode 100644 index 00000000..9271e117 --- /dev/null +++ b/local/modules/TheliaMigrateCountry/EventListeners/MigrateCountryListener.php @@ -0,0 +1,155 @@ + + */ +class MigrateCountryListener implements EventSubscriberInterface +{ + + public function migrateCountry(MigrateCountryEvent $event) + { + $counter = []; + + // update address + $counter[AddressTableMap::TABLE_NAME] = $this->migrateAddress($event); + + // tax rules + $counter[TaxRuleCountryTableMap::TABLE_NAME] = $this->migrateAddress($event); + + // shipping zone + $counter[CountryAreaTableMap::TABLE_NAME] = $this->migrateAddress($event); + + // if it succeeds we toggle the visibility of old country and new + $this->setCountriesVisibility($event); + + $event->setCounter($counter); + + } + + protected function migrateAddress(MigrateCountryEvent $event) + { + $con = Propel::getWriteConnection(AddressTableMap::DATABASE_NAME); + $con->beginTransaction(); + try { + $updatedRows = AddressQuery::create() + ->filterByCountryId($event->getCountry()) + ->update( + [ + 'CountryId' => $event->getNewCountry(), + 'StateId' => $event->getNewState(), + ] + ); + + $con->commit(); + + return $updatedRows; + } catch (PropelException $e) { + $con->rollback(); + throw $e; + } + } + + protected function migrateTaxRules(MigrateCountryEvent $event) + { + $con = Propel::getWriteConnection(TaxRuleCountryTableMap::DATABASE_NAME); + $con->beginTransaction(); + try { + $updatedRows = TaxRuleCountryQuery::create() + ->filterByCountryId($event->getCountry()) + ->update( + [ + 'CountryId' => $event->getNewCountry(), + 'StateId' => $event->getNewState(), + ] + ); + + $con->commit(); + + return $updatedRows; + } catch (PropelException $e) { + $con->rollback(); + throw $e; + } + } + + protected function migrateShippingZones(MigrateCountryEvent $event) + { + $con = Propel::getWriteConnection(CountryAreaTableMap::DATABASE_NAME); + $con->beginTransaction(); + try { + $updatedRows = CountryAreaQuery::create() + ->filterByCountryId($event->getCountry()) + ->update( + [ + 'CountryId' => $event->getNewCountry(), + 'StateId' => $event->getNewState(), + ] + ); + + $con->commit(); + + return $updatedRows; + } catch (PropelException $e) { + $con->rollback(); + throw $e; + } + } + + private function setCountriesVisibility(MigrateCountryEvent $event) + { + $oldCountry = CountryQuery::create()->findPk($event->getCountry()); + + if (null !== $oldCountry) { + $oldCountry + ->setVisible(0) + ->save() + ; + } + + $newCountry = CountryQuery::create()->findPk($event->getNewCountry()); + if (null !== $newCountry) { + $newCountry + ->setVisible(1) + ->save() + ; + } + } + + /** + * @inheritdoc + */ + public static function getSubscribedEvents() + { + return [ + MigrateCountryEvents::MIGRATE_COUNTRY => 'migrateCountry' + ]; + } +} diff --git a/local/modules/TheliaMigrateCountry/Events/MigrateCountryEvent.php b/local/modules/TheliaMigrateCountry/Events/MigrateCountryEvent.php new file mode 100644 index 00000000..53613b09 --- /dev/null +++ b/local/modules/TheliaMigrateCountry/Events/MigrateCountryEvent.php @@ -0,0 +1,117 @@ + + */ +class MigrateCountryEvent extends ActionEvent +{ + /** @var int Old country Id */ + protected $country; + + /** @var int New country Id */ + protected $newCountry; + + /** @var int New state Id */ + protected $newState; + + /** @var array counter */ + protected $counter = []; + + /** + * MigrateCountryEvent constructor. + * @param $country + * @param int $newCountry + * @param int $newState + */ + public function __construct($country, $newCountry, $newState) + { + $this->country = $country; + $this->newCountry = $newCountry; + $this->newState = $newState; + } + + /** + * @return mixed + */ + public function getCountry() + { + return $this->country; + } + + /** + * @param mixed $country + */ + public function setCountry($country) + { + $this->country = $country; + return $this; + } + + /** + * @return int + */ + public function getNewCountry() + { + return $this->newCountry; + } + + /** + * @param int $newCountry + */ + public function setNewCountry($newCountry) + { + $this->newCountry = $newCountry; + return $this; + } + + /** + * @return int + */ + public function getNewState() + { + return $this->newState; + } + + /** + * @param int $newState + */ + public function setNewState($newState) + { + $this->newState = $newState; + return $this; + } + + /** + * @return array + */ + public function getCounter() + { + return $this->counter; + } + + /** + * @param array $counter + */ + public function setCounter($counter) + { + $this->counter = $counter; + return $this; + } +} diff --git a/local/modules/TheliaMigrateCountry/Events/MigrateCountryEvents.php b/local/modules/TheliaMigrateCountry/Events/MigrateCountryEvents.php new file mode 100644 index 00000000..3a1cdcb0 --- /dev/null +++ b/local/modules/TheliaMigrateCountry/Events/MigrateCountryEvents.php @@ -0,0 +1,24 @@ + + */ +class MigrateCountryEvents +{ + const MIGRATE_COUNTRY = 'action.migrate-country.migrate'; +} diff --git a/local/modules/TheliaMigrateCountry/Form/CountryStateMigrationForm.php b/local/modules/TheliaMigrateCountry/Form/CountryStateMigrationForm.php new file mode 100644 index 00000000..9a352af9 --- /dev/null +++ b/local/modules/TheliaMigrateCountry/Form/CountryStateMigrationForm.php @@ -0,0 +1,54 @@ + + */ +class CountryStateMigrationForm extends BaseForm +{ + + /** + * @inheritdocs + */ + protected function buildForm() + { + $this->formBuilder + ->add( + 'migrations', + 'collection', + [ + "type" => "country_state_migration", + "allow_add" => true, + "required" => true, + "cascade_validation" => true, + "constraints" => array( + new Count(["min" => 1]), + ), + ] + ) + ; + } + + public function getName() + { + return "thelia_country_state_migration"; + } +} diff --git a/local/modules/TheliaMigrateCountry/Form/Type/CountryStateMigrationType.php b/local/modules/TheliaMigrateCountry/Form/Type/CountryStateMigrationType.php new file mode 100644 index 00000000..acbf43fa --- /dev/null +++ b/local/modules/TheliaMigrateCountry/Form/Type/CountryStateMigrationType.php @@ -0,0 +1,114 @@ + + */ +class CountryStateMigrationType extends AbstractTheliaType +{ + public function configureOptions(OptionsResolver $resolver) + { + $resolver->setDefaults( + [ + "cascade_validation" => true, + "constraints" => array( + new Callback([ + "methods" => array( + [$this, "checkStateId"], + ), + ]), + ), + ] + ); + } + + public function buildForm(FormBuilderInterface $builder, array $options) + { + $builder + ->add("migrate", "checkbox") + ->add( + "country", + "country_id" + ) + ->add( + "new_country", + "country_id" + ) + ->add( + "new_state", + "state_id", + [ + "constraints" => [], + ] + ) + ; + } + + public function checkStateId($value, ExecutionContextInterface $context) + { + + if ($value['migrate']) { + if (null !== $state = StateQuery::create()->findPk($value['new_state'])) { + if ($state->getCountryId() !== $value['new_country']) { + $context->addViolation( + Translator::getInstance()->trans( + "The state id '%id' does not belong to country id '%id_country'", + [ + '%id' => $value['new_state'], + '%id_country' => $value['new_country'] + ] + ) + ); + } + } else { + $context->addViolation( + Translator::getInstance()->trans( + "The state id '%id' doesn't exist", + ['%id' => $value['new_state']] + ) + ); + } + } + + } + + private function getRowData(ExecutionContextInterface $context) + { + $propertyPath = $context->getPropertyPath(); + $data = $this->getRowData($context); + + + } + + /** + * Returns the name of this type. + * + * @return string The name of this type + */ + public function getName() + { + return 'country_state_migration'; + } +} diff --git a/local/modules/TheliaMigrateCountry/I18n/backOffice/default/en_US.php b/local/modules/TheliaMigrateCountry/I18n/backOffice/default/en_US.php new file mode 100644 index 00000000..35906899 --- /dev/null +++ b/local/modules/TheliaMigrateCountry/I18n/backOffice/default/en_US.php @@ -0,0 +1,31 @@ + ' country ', + ' migrated to ' => ' migrated to ', + ' state ' => ' state ', + 'After the migration the old country will be hide and the new one shown' => 'After the migration the old country will be hide and the new one shown', + 'All States' => 'All States', + 'All countries have been migrated' => 'All countries have been migrated', + 'Configuration' => 'Configuration', + 'Countries' => 'Countries', + 'Countries migrated' => 'Countries migrated', + 'Countries to migrate' => 'Countries to migrate', + 'Country ' => 'Country ', + 'Country migration' => 'Country migration', + 'For USA and Canada the states already exists as countries, so you have to select the right state.' => 'For USA and Canada the states already exists as countries, so you have to select the right state.', + 'For other countries, you should decide to use state or not. ' => 'For other countries, you should decide to use state or not. ', + 'Home' => 'Home', + 'If you want to use the new country with its states, you have to check the migrate checkbox and select a state.' => 'If you want to use the new country with its states, you have to check the migrate checkbox and select a state.', + 'In version 2.3 of Thelia, the system of country has changed.' => 'In version 2.3 of Thelia, the system of country has changed.', + 'Migrate ?' => 'Migrate ?', + 'Migrate countries' => 'Migrate countries', + 'New country' => 'New country', + 'Now, countries has been splited in countries and states.' => 'Now, countries has been splited in countries and states.', + 'Old country' => 'Old country', + 'State' => 'State', + 'The migration proccess is tricky and couldn\'t be automated.' => 'The migration proccess is tricky and couldn\'t be automated.', + 'The migration will change the address, tax rules and shipping zones to match with the new system.' => 'The migration will change the address, tax rules and shipping zones to match with the new system.', + 'The update proccess has created new countries (even if it exists) and associated states.' => 'The update proccess has created new countries (even if it exists) and associated states.', + 'We added a \'default\' state with a blank name as a fallback. Customer will have the possibility to change it later.' => 'We added a \'default\' state with a blank name as a fallback. Customer will have the possibility to change it later.', +); diff --git a/local/modules/TheliaMigrateCountry/I18n/backOffice/default/fr_FR.php b/local/modules/TheliaMigrateCountry/I18n/backOffice/default/fr_FR.php new file mode 100644 index 00000000..70b7092b --- /dev/null +++ b/local/modules/TheliaMigrateCountry/I18n/backOffice/default/fr_FR.php @@ -0,0 +1,31 @@ + ' le pays', + ' migrated to ' => 'migré vers', + ' state ' => ' état ', + 'After the migration the old country will be hide and the new one shown' => 'Après la migration l\'ancien pays sera caché et le nouveau sera activé.', + 'All States' => 'Tous les états', + 'All countries have been migrated' => 'Tous les pays ont été migré', + 'Configuration' => 'Configuration', + 'Countries' => 'Pays', + 'Countries migrated' => 'Pays migrés', + 'Countries to migrate' => 'Pays à migrer.', + 'Country ' => 'Le pays', + 'Country migration' => 'Migration pays', + 'For USA and Canada the states already exists as countries, so you have to select the right state.' => 'Pour les USA et le Canada les états étaient déjà présents mais en tant que pays. Vous devrez donc choisir l\'état correspondant.', + 'For other countries, you should decide to use state or not. ' => 'Pour les autres pays, vous devrez choisir d\'utiliser ou pas les états.', + 'Home' => 'Accueil', + 'If you want to use the new country with its states, you have to check the migrate checkbox and select a state.' => 'Si vous voulez utiliser les nouveaux pays avec les états, vous devrez cocher la boîte à cocher \'migrer\' et sélectionner un état.', + 'In version 2.3 of Thelia, the system of country has changed.' => 'En version 2.3 de Thelia, le sysème des pays a changé.', + 'Migrate ?' => 'Migrer ?', + 'Migrate countries' => 'Migrer les pays', + 'New country' => 'Nouveau pays', + 'Now, countries has been splited in countries and states.' => 'Les pays ont été séparé en pays et états.', + 'Old country' => 'Ancien pays', + 'State' => 'État/région', + 'The migration proccess is tricky and couldn\'t be automated.' => 'Le processus de migration est compliqué et ne peux pas être automatisé', + 'The migration will change the address, tax rules and shipping zones to match with the new system.' => 'La migration changera les adresses, les règles de taxe et les zones de livraisons pour fonctionner avec le nouveau système.', + 'The update proccess has created new countries (even if it exists) and associated states.' => 'Le processus de mise à jour a créé de nouveaux pays (même si il existait) et associé des états.', + 'We added a \'default\' state with a blank name as a fallback. Customer will have the possibility to change it later.' => 'Nous avons ajouté un état par \'défaut\' avec un nom vide. Par la suite, le client pourra le changer.', +]; diff --git a/local/modules/TheliaMigrateCountry/I18n/backOffice/default/it_IT.php b/local/modules/TheliaMigrateCountry/I18n/backOffice/default/it_IT.php new file mode 100644 index 00000000..8aaa7bfe --- /dev/null +++ b/local/modules/TheliaMigrateCountry/I18n/backOffice/default/it_IT.php @@ -0,0 +1,19 @@ + 'paese', + ' migrated to ' => ' migrato a ', + ' state ' => ' stato ', + 'All States' => 'Tutti gli Stati', + 'Configuration' => 'Impostazione', + 'Countries' => 'Paesi', + 'Country ' => 'Paese', + 'Country migration' => 'Migrazione del paese', + 'Home' => 'Home', + 'Migrate countries' => 'Migrazione dei paesi', + 'New country' => 'Nuovo paese', + 'Now, countries has been splited in countries and states.' => 'Ora, i paesi sono stati divisi in paesi e stati.', + 'State' => 'Stato', + 'The update proccess has created new countries (even if it exists) and associated states.' => 'Il processo di aggiornamento ha creato nuovi paesi (anche esistenti) e stati associati.', + 'We added a \'default\' state with a blank name as a fallback. Customer will have the possibility to change it later.' => 'Abbiamo aggiunto uno stato di \'default\' con un nome vuoto come fallback. Il cliente avrà la possibilità di modificarlo in seguito.', +]; diff --git a/local/modules/TheliaMigrateCountry/I18n/backOffice/default/ru_RU.php b/local/modules/TheliaMigrateCountry/I18n/backOffice/default/ru_RU.php new file mode 100644 index 00000000..acc81032 --- /dev/null +++ b/local/modules/TheliaMigrateCountry/I18n/backOffice/default/ru_RU.php @@ -0,0 +1,31 @@ + ' страну ', + ' migrated to ' => ' мигрировать в ', + ' state ' => ' штат ', + 'After the migration the old country will be hide and the new one shown' => 'После миграции старая страна будет скрыта, а новая показана', + 'All States' => 'Все штаты', + 'All countries have been migrated' => 'Все страны мигрированы', + 'Configuration' => 'Конфигурация', + 'Countries' => 'Страны', + 'Countries migrated' => 'Страны мигрированы', + 'Countries to migrate' => 'Страны для миграции', + 'Country ' => 'Страна', + 'Country migration' => 'Миграция страны', + 'For USA and Canada the states already exists as countries, so you have to select the right state.' => 'Для США и Канады штаты уже существуют как страны, поэтому вы должны выбрать правильнй штат.', + 'For other countries, you should decide to use state or not. ' => 'Для остальных стран выдолжны выбрать использовать шатыт или нет.', + 'Home' => 'Главная', + 'If you want to use the new country with its states, you have to check the migrate checkbox and select a state.' => 'Если вы хотите использовать новую страну со штатами, вы должны выбрать флаг миграции и выбрать штат.', + 'In version 2.3 of Thelia, the system of country has changed.' => 'В Thelia версии 2.3, система стран была изменена.', + 'Migrate ?' => 'Мигрировать ?', + 'Migrate countries' => 'Мигрировать страны', + 'New country' => 'Новая страна', + 'Now, countries has been split in countries and states.' => 'Сейчас страны разделены на страны и штаты', + 'Old country' => 'Старая страна', + 'State' => 'Штат', + 'The migration process is tricky and couldn\'t be automated.' => 'Процес миграции непростой и не может быть автоматизирован.', + 'The migration will change the address, tax rules and shipping zones to match with the new system.' => 'Миграция изменит адреса, налоговые правила и зоны доставки для соответствия с ново системой.', + 'The update process has created new countries (even if it exists) and associated states.' => 'Процес обновления создаст новые страны (даже если они существуют) и связаные штаты.', + 'We added a \'default\' state with a blank name as a fallback. Customer will have the possibility to change it later.' => 'Мы добавили \'стандартный\' штат с пустым именем как резерв. Клиент будет иметь возможность изменить его позже.', +); diff --git a/local/modules/TheliaMigrateCountry/I18n/en_US.php b/local/modules/TheliaMigrateCountry/I18n/en_US.php new file mode 100644 index 00000000..582bf0dc --- /dev/null +++ b/local/modules/TheliaMigrateCountry/I18n/en_US.php @@ -0,0 +1,8 @@ + 'Country %id migrated to country (ID %country) and state (ID %state) (address: %address, tax rules: %tax, shipping zones: %zone)', + 'Country migration' => 'Country migration', + 'The state id \'%id\' does not belong to country id \'%id_country\'' => 'The state id \'%id\' does not belong to country id \'%id_country\'', + 'The state id \'%id\' doesn\'t exist' => 'The state id \'%id\' doesn\'t exist', +); diff --git a/local/modules/TheliaMigrateCountry/I18n/fr_FR.php b/local/modules/TheliaMigrateCountry/I18n/fr_FR.php new file mode 100644 index 00000000..e36af4c7 --- /dev/null +++ b/local/modules/TheliaMigrateCountry/I18n/fr_FR.php @@ -0,0 +1,8 @@ + 'Le pays %id migré vers le pays (ID %country) et état (ID %state) (adresses: %address, règles de taxe: %tax, zones de livraison: %zone)', + 'Country migration' => 'Migration pays', + 'The state id \'%id\' does not belong to country id \'%id_country\'' => 'L\'état id \'%id\' n\'appartient pas au pays id \'%id_country\'', + 'The state id \'%id\' doesn\'t exist' => 'L\'état id \'%id\' n\'existe pas', +]; diff --git a/local/modules/TheliaMigrateCountry/I18n/it_IT.php b/local/modules/TheliaMigrateCountry/I18n/it_IT.php new file mode 100644 index 00000000..ebcb746f --- /dev/null +++ b/local/modules/TheliaMigrateCountry/I18n/it_IT.php @@ -0,0 +1,8 @@ + 'Paese %id migrato a paese (ID %country) e stato (ID %state) (Indirizzo: %address, norme fiscali: %tax, zone di spedizione: %zone)', + 'Country migration' => 'Migrazione del paese', + 'The state id \'%id\' does not belong to country id \'%id_country\'' => 'L\'id dello stato \'%id\' non appartiene a id paese \'%id_country\'', + 'The state id \'%id\' doesn\'t exist' => 'L\'id dello stato \'%id\' non esiste', +]; diff --git a/local/modules/TheliaMigrateCountry/I18n/ru_RU.php b/local/modules/TheliaMigrateCountry/I18n/ru_RU.php new file mode 100644 index 00000000..bfc3f20c --- /dev/null +++ b/local/modules/TheliaMigrateCountry/I18n/ru_RU.php @@ -0,0 +1,8 @@ + 'Страна %id мигрирована в страну (ID %country) и штат (ID %state) (адрес: %address, налоговые правила: %tax, зоны доставки: %zone)', + 'Country migration' => 'Миграция стран', + 'The state id \'%id\' does not belong to country id \'%id_country\'' => 'Штат с id \'%id\' не принадлежит стране с id \'%id_country\'', + 'The state id \'%id\' doesn\'t exist' => 'Штат с id \'%id\' не существует', +); diff --git a/local/modules/TheliaMigrateCountry/LICENSE.txt b/local/modules/TheliaMigrateCountry/LICENSE.txt new file mode 100644 index 00000000..65c5ca88 --- /dev/null +++ b/local/modules/TheliaMigrateCountry/LICENSE.txt @@ -0,0 +1,165 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + + This version of the GNU Lesser General Public License incorporates +the terms and conditions of version 3 of the GNU General Public +License, supplemented by the additional permissions listed below. + + 0. Additional Definitions. + + As used herein, "this License" refers to version 3 of the GNU Lesser +General Public License, and the "GNU GPL" refers to version 3 of the GNU +General Public License. + + "The Library" refers to a covered work governed by this License, +other than an Application or a Combined Work as defined below. + + An "Application" is any work that makes use of an interface provided +by the Library, but which is not otherwise based on the Library. +Defining a subclass of a class defined by the Library is deemed a mode +of using an interface provided by the Library. + + A "Combined Work" is a work produced by combining or linking an +Application with the Library. The particular version of the Library +with which the Combined Work was made is also called the "Linked +Version". + + The "Minimal Corresponding Source" for a Combined Work means the +Corresponding Source for the Combined Work, excluding any source code +for portions of the Combined Work that, considered in isolation, are +based on the Application, and not on the Linked Version. + + The "Corresponding Application Code" for a Combined Work means the +object code and/or source code for the Application, including any data +and utility programs needed for reproducing the Combined Work from the +Application, but excluding the System Libraries of the Combined Work. + + 1. Exception to Section 3 of the GNU GPL. + + You may convey a covered work under sections 3 and 4 of this License +without being bound by section 3 of the GNU GPL. + + 2. Conveying Modified Versions. + + If you modify a copy of the Library, and, in your modifications, a +facility refers to a function or data to be supplied by an Application +that uses the facility (other than as an argument passed when the +facility is invoked), then you may convey a copy of the modified +version: + + a) under this License, provided that you make a good faith effort to + ensure that, in the event an Application does not supply the + function or data, the facility still operates, and performs + whatever part of its purpose remains meaningful, or + + b) under the GNU GPL, with none of the additional permissions of + this License applicable to that copy. + + 3. Object Code Incorporating Material from Library Header Files. + + The object code form of an Application may incorporate material from +a header file that is part of the Library. You may convey such object +code under terms of your choice, provided that, if the incorporated +material is not limited to numerical parameters, data structure +layouts and accessors, or small macros, inline functions and templates +(ten or fewer lines in length), you do both of the following: + + a) Give prominent notice with each copy of the object code that the + Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the object code with a copy of the GNU GPL and this license + document. + + 4. Combined Works. + + You may convey a Combined Work under terms of your choice that, +taken together, effectively do not restrict modification of the +portions of the Library contained in the Combined Work and reverse +engineering for debugging such modifications, if you also do each of +the following: + + a) Give prominent notice with each copy of the Combined Work that + the Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the Combined Work with a copy of the GNU GPL and this license + document. + + c) For a Combined Work that displays copyright notices during + execution, include the copyright notice for the Library among + these notices, as well as a reference directing the user to the + copies of the GNU GPL and this license document. + + d) Do one of the following: + + 0) Convey the Minimal Corresponding Source under the terms of this + License, and the Corresponding Application Code in a form + suitable for, and under terms that permit, the user to + recombine or relink the Application with a modified version of + the Linked Version to produce a modified Combined Work, in the + manner specified by section 6 of the GNU GPL for conveying + Corresponding Source. + + 1) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (a) uses at run time + a copy of the Library already present on the user's computer + system, and (b) will operate properly with a modified version + of the Library that is interface-compatible with the Linked + Version. + + e) Provide Installation Information, but only if you would otherwise + be required to provide such information under section 6 of the + GNU GPL, and only to the extent that such information is + necessary to install and execute a modified version of the + Combined Work produced by recombining or relinking the + Application with a modified version of the Linked Version. (If + you use option 4d0, the Installation Information must accompany + the Minimal Corresponding Source and Corresponding Application + Code. If you use option 4d1, you must provide the Installation + Information in the manner specified by section 6 of the GNU GPL + for conveying Corresponding Source.) + + 5. Combined Libraries. + + You may place library facilities that are a work based on the +Library side by side in a single library together with other library +facilities that are not Applications and are not covered by this +License, and convey such a combined library under terms of your +choice, if you do both of the following: + + a) Accompany the combined library with a copy of the same work based + on the Library, uncombined with any other library facilities, + conveyed under the terms of this License. + + b) Give prominent notice with the combined library that part of it + is a work based on the Library, and explaining where to find the + accompanying uncombined form of the same work. + + 6. Revised Versions of the GNU Lesser General Public License. + + The Free Software Foundation may publish revised and/or new versions +of the GNU Lesser General Public License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. + + Each version is given a distinguishing version number. If the +Library as you received it specifies that a certain numbered version +of the GNU Lesser General Public License "or any later version" +applies to it, you have the option of following the terms and +conditions either of that published version or of any later version +published by the Free Software Foundation. If the Library as you +received it does not specify a version number of the GNU Lesser +General Public License, you may choose any version of the GNU Lesser +General Public License ever published by the Free Software Foundation. + + If the Library as you received it specifies that a proxy can decide +whether future versions of the GNU Lesser General Public License shall +apply, that proxy's public statement of acceptance of any version is +permanent authorization for you to choose that version for the +Library. diff --git a/local/modules/TheliaMigrateCountry/Readme.md b/local/modules/TheliaMigrateCountry/Readme.md new file mode 100644 index 00000000..ae6aee51 --- /dev/null +++ b/local/modules/TheliaMigrateCountry/Readme.md @@ -0,0 +1,18 @@ +# Thelia Migrate Country + +This module allow you to migrate the system of country from Thelia version <= 2.2.* to version >= 2.3.0-alpha1. + +## Installation + +### Manually + +* Copy the module into ```/local/modules/``` directory and be sure that the name of the module is TheliaMigrateCountry. +* Activate it in your thelia administration panel + +### Composer + +Add it in your main thelia composer.json file + +``` +composer require your-vendor/thelia-migrate-country-module:~1.0 +``` diff --git a/local/modules/TheliaMigrateCountry/TheliaMigrateCountry.php b/local/modules/TheliaMigrateCountry/TheliaMigrateCountry.php new file mode 100644 index 00000000..b8772687 --- /dev/null +++ b/local/modules/TheliaMigrateCountry/TheliaMigrateCountry.php @@ -0,0 +1,28 @@ + + {intl l='Migrate countries'} + + +{/loop} \ No newline at end of file diff --git a/local/modules/TheliaMigrateCountry/templates/backOffice/default/countries-migrate.html b/local/modules/TheliaMigrateCountry/templates/backOffice/default/countries-migrate.html new file mode 100644 index 00000000..79b068a9 --- /dev/null +++ b/local/modules/TheliaMigrateCountry/templates/backOffice/default/countries-migrate.html @@ -0,0 +1,299 @@ +{extends file="admin-layout.tpl"} + +{block name="no-return-functions"} + {$admin_current_location = 'configuration'} +{/block} + +{block name="page-title"}{intl l='Country migration'}{/block} + +{block name="check-resource"}admin.configuration.country{/block} +{block name="check-access"}update{/block} + +{block name="main-content"} +
    + +
    + + + +
    +
    +
    + +
    + {intl l='Migrate countries'} +
    + +
    +
    + {intl l='In version 2.3 of Thelia, the system of country has changed.'} + {intl l='Now, countries has been split in countries and states.'}
    + {intl l="The migration process is tricky and couldn't be automated."}

    + {intl l="The update process has created new countries (even if it exists) and associated states."}
    + {intl l="The migration will change the address, tax rules and shipping zones to match with the new system."}
    + {intl l="After the migration the old country will be hide and the new one shown"}

    + {intl l="For USA and Canada the states already exists as countries, so you have to select the right state."}
    + {intl l="For other countries, you should decide to use state or not. "} + {intl l="If you want to use the new country with its states, you have to check the migrate checkbox and select a state."} + {intl l="We added a 'default' state with a blank name as a fallback. Customer will have the possibility to change it later."} +
    +
    + + {if $showForm} +
    +
    + + {form name="thelia.admin.country.state.migration"} + + {include + file = "includes/inner-form-toolbar.html" + hide_submit_buttons = false + + page_url = {url path="/admin/configuration/countries/migrate"} + close_url = {url path="/admin/configuration/countries"} + } + + {form_hidden_fields exclude="locale"} + + {render_form_field field='success_url' value={url path="/admin/configuration/countries/migrate"}} + + {if $form_error}
    {$form_error_message}
    {/if} + + {if {hasflash type="migrate"}} +
    + {flash type="migrate"} +
    {$MESSAGE}
    + {/flash} +
    + {/if} + +
    + + + + + + + + + + + + {form_collection form=$form collection="migrations"} + {$newCountryId=0} + {$countryId=0} + + + + + + + {/form_collection} + +
    + {intl l='Countries to migrate'} +
    {intl l="Migrate ?"}{intl l="Old country"}{intl l="New country"}{intl l="State"}
    + {form_collection_field form=$form row=$row field="migrate"} + + {/form_collection_field} + + {form_collection_field form=$form row=$row field="country"} + {$countryId={$value}} + + + {/form_collection_field} + + {form_collection_field form=$form row=$row field="new_country"} + {$newCountryId={$value}} + + + {/form_collection_field} + + {form_collection_field form=$form row=$row field="new_state"} + {$ref[]={$label_attr.for}} + + + {/form_collection_field} +
    +
    + + + {/form} + +
    +
    + {else} +
    + {intl l="All countries have been migrated"} +
    + {/if} + +
    +
    + + {if count($countriesMigrated) > 0 } +
    +
    +
    + {intl l='Countries migrated'} +
    +
    + + {foreach $countriesMigrated as $country => $new} +
    +
    + {intl l='Country '} + {intl l=' migrated to '} + {intl l=' country '} + + {intl l=' state '} + +
    +
    + {/foreach} +
    + {/if} + +
    + +
    +
    +{/block} + +{block name="javascript-initialization"} + {javascripts file='assets/js/bootstrap-select/bootstrap-select.js'} + + {/javascripts} + + {javascripts file='assets/js/libs/underscore-min.js'} + + {/javascripts} + + + + +{/block} + +{block name="javascript-last-call"} + {hook name="wysiwyg.js" location="wysiwyg-country-edit-js" } +{/block} \ No newline at end of file diff --git a/local/modules/TheliaSmarty/CREDITS.md b/local/modules/TheliaSmarty/CREDITS.md new file mode 100644 index 00000000..3e89e239 --- /dev/null +++ b/local/modules/TheliaSmarty/CREDITS.md @@ -0,0 +1,40 @@ +# Credits + +## Yii framework + +TheliaSmarty module uses a function that comes from [Yii framework](http://www.yiiframework.com/) + +License : + +The Yii framework is free software. It is released under the terms of +the following BSD License. + +Copyright © 2008 by Yii Software LLC (http://www.yiisoft.com) +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + * Neither the name of Yii Software LLC nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/local/modules/TheliaSmarty/Compiler/RegisterParserPluginPass.php b/local/modules/TheliaSmarty/Compiler/RegisterParserPluginPass.php new file mode 100644 index 00000000..76514fff --- /dev/null +++ b/local/modules/TheliaSmarty/Compiler/RegisterParserPluginPass.php @@ -0,0 +1,48 @@ + + */ +class RegisterParserPluginPass implements CompilerPassInterface +{ + /** + * You can modify the container here before it is dumped to PHP code. + * + * @param ContainerBuilder $container + * + * @api + */ + public function process(ContainerBuilder $container) + { + if (!$container->hasDefinition("thelia.parser")) { + return; + } + + $smarty = $container->getDefinition("thelia.parser"); + + foreach ($container->findTaggedServiceIds("thelia.parser.register_plugin") as $id => $plugin) { + $smarty->addMethodCall("addPlugins", array(new Reference($id))); + } + + $smarty->addMethodCall("registerPlugins"); + } +} diff --git a/local/modules/TheliaSmarty/Config/config.xml b/local/modules/TheliaSmarty/Config/config.xml new file mode 100644 index 00000000..be7399d4 --- /dev/null +++ b/local/modules/TheliaSmarty/Config/config.xml @@ -0,0 +1,158 @@ + + + + + + + + + + + + + + + + + + %kernel.environment% + %kernel.debug% + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + %thelia.parser.loops% + + + + + + + + + + + + + + + + + + + + + + + + + + + + %thelia.parser.forms% + + + + + + + + + + %kernel.debug% + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + %kernel.debug% + + + + + + + + + %kernel.debug% + + + + + + %kernel.debug% + + + + diff --git a/local/modules/TheliaSmarty/Config/module.xml b/local/modules/TheliaSmarty/Config/module.xml new file mode 100644 index 00000000..801fb4a1 --- /dev/null +++ b/local/modules/TheliaSmarty/Config/module.xml @@ -0,0 +1,28 @@ + + + TheliaSmarty\TheliaSmarty + + Smarty template engine integration + + + Intégration du moteur de template Smarty + + + en_US + fr_FR + + 2.4.3 + + + Manuel Raynaud + manu@raynaud.io + + + classic + 2.4.3 + alpha + 1 + 1 + diff --git a/local/modules/TheliaSmarty/I18n/en_US.php b/local/modules/TheliaSmarty/I18n/en_US.php new file mode 100644 index 00000000..173d397f --- /dev/null +++ b/local/modules/TheliaSmarty/I18n/en_US.php @@ -0,0 +1,21 @@ + '\'%type\' loop class should extends Thelia\Core\Template\Element\BaseLoop', + 'A loop named \'%name\' already exists in the current scope.' => 'A loop named \'%name\' already exists in the current scope.', + 'Loop type \'%type\' is not defined.' => 'Loop type \'%type\' is not defined.', + 'Missing \'name\' parameter in loop arguments' => 'Missing \'name\' parameter in loop arguments', + 'Missing \'rel\' parameter in forHook arguments' => 'Missing \'rel\' parameter in forHook arguments', + 'Missing \'rel\' parameter in ifhook/elsehook arguments' => 'Missing \'rel\' parameter in ifhook/elsehook arguments', + 'Missing \'rel\' parameter in ifloop/elseloop arguments' => 'Missing \'rel\' parameter in ifloop/elseloop arguments', + 'Missing \'rel\' parameter in page loop' => 'Missing \'rel\' parameter in page loop', + 'Missing \'type\' parameter in loop arguments' => 'Missing \'type\' parameter in loop arguments', + 'Missing \'type\' parameter in {count} loop arguments' => 'Missing \'type\' parameter in {count} loop arguments', + 'Missing \'type\' parameter in {hasflash} function arguments' => 'Missing \'type\' parameter in {hasflash} function arguments', + 'No pagination currently defined for loop name \'%name\'' => 'No pagination currently defined for loop name \'%name\'', + 'Please specify either \'path\' or \'file\' parameter in {url} function.' => 'Please specify either \'path\' or \'file\' parameter in {url} function.', + 'Related hook name \'%name\' is not defined.' => 'Related hook name \'%name\' is not defined.', + 'Related loop name \'%name\'\' is not defined.' => 'Related loop name \'%name\'\' is not defined.', + 'Template file %file cannot be found.' => 'Template file %file cannot be found.', + 'The loop name \'%name\' is already defined in %className class' => 'The loop name \'%name\' is already defined in %className class', +); diff --git a/local/modules/TheliaSmarty/I18n/fr_FR.php b/local/modules/TheliaSmarty/I18n/fr_FR.php new file mode 100644 index 00000000..67b516db --- /dev/null +++ b/local/modules/TheliaSmarty/I18n/fr_FR.php @@ -0,0 +1,21 @@ + 'La loop "%type" doit étendre la class Thelia\Core\Template\Element\BaseLoop', + 'A loop named \'%name\' already exists in the current scope.' => 'une loop avec comme nom \'%name\' existe déjà dans le scope courant', + 'Loop type \'%type\' is not defined.' => 'La loop de type "%type" n\'est pas défini', + 'Missing \'name\' parameter in loop arguments' => 'Le paramètre \'name\' est manquant dans la liste des arguments', + 'Missing \'rel\' parameter in forHook arguments' => 'Le paramètre \'rel\' est manquant dans les arguments de forHook', + 'Missing \'rel\' parameter in ifhook/elsehook arguments' => 'Le paramètre \'rel\' est manquant des arguments ifhook/elsehook', + 'Missing \'rel\' parameter in ifloop/elseloop arguments' => 'Paramètre \'rel\' manquant dans la liste des arguments d\'une loop ifloop/elseloop', + 'Missing \'rel\' parameter in page loop' => 'Paramètre \'rel\' manquant dans la loop page', + 'Missing \'type\' parameter in loop arguments' => 'Le paramètre \'type\' est manquant dans la liste des arguments', + 'Missing \'type\' parameter in {count} loop arguments' => 'Le paramètre \'type\' dans la loop {count} est manquant', + 'Missing \'type\' parameter in {hasflash} function arguments' => 'Le paramètre \'type\' est manquant dans', + 'No pagination currently defined for loop name \'%name\'' => 'Il n\'y a pas de pagination définie pour la loop \'%name\'', + 'Please specify either \'path\' or \'file\' parameter in {url} function.' => 'Merci de spécifier le \'path\' ou le \'file\'.parameter dans la fonction {url}', + 'Related hook name \'%name\' is not defined.' => 'le hook ayat pour nom "%name" n\'est pas défini', + 'Related loop name \'%name\'\' is not defined.' => 'La loop ayant pour nom "%name" n\'est pas défini', + 'Template file %file cannot be found.' => 'Le fichier %s ne semble pas présent', + 'The loop name \'%name\' is already defined in %className class' => 'La loop "%name" est déjà définie dans la class %className', +]; diff --git a/local/modules/TheliaSmarty/I18n/ru_RU.php b/local/modules/TheliaSmarty/I18n/ru_RU.php new file mode 100644 index 00000000..66c82e21 --- /dev/null +++ b/local/modules/TheliaSmarty/I18n/ru_RU.php @@ -0,0 +1,20 @@ + '\'%type\' класс цикла должен расширять Thelia\Core\Template\Element\BaseLoop', + 'A loop named \'%name\' already exists in the current scope.' => 'Цикл с именем \'%name\' уже существует в текущей области видимости.', + 'Loop type \'%type\' is not defined.' => 'Тип цикла \'%type\' не определен.', + 'Missing \'name\' parameter in loop arguments' => 'Пропущен параметр \'name\' в аргументах цикла', + 'Missing \'rel\' parameter in forHook arguments' => 'Пропущен параметр \'rel\' в аргументах forHook', + 'Missing \'rel\' parameter in ifhook/elsehook arguments' => 'Пропущен параметр \'rel\' в аргументах ifhook/elsehook', + 'Missing \'rel\' parameter in ifloop/elseloop arguments' => 'Пропущен параметр \'rel\' в аргументах ifloop/elseloop', + 'Missing \'rel\' parameter in page loop' => 'Пропущен параметр \'rel\' в цикле страницы', + 'Missing \'type\' parameter in loop arguments' => 'Пропущен параметр \'type\' в аргументах цикла', + 'Missing \'type\' parameter in {count} loop arguments' => 'Пропущен параметр \'type\' в {count} аргументах цикла', + 'Missing \'type\' parameter in {hasflash} function arguments' => 'Пропущен параметр \'type\' в аргуметах функции {hasflash}', + 'No pagination currently defined for loop name \'%name\'' => 'Не определена пагинация для цикла \'%name\'', + 'Related hook name \'%name\' is not defined.' => 'Связанное имя хука \'%name\' не определено.', + 'Related loop name \'%name\'\' is not defined.' => 'Связанное имя цикла \'%name\'\' не определено.', + 'Template file %file cannot be found.' => 'Файл шаблона %file не найден.', + 'The loop name \'%name\' is already defined in %className class' => 'Имя цикла \'%name\' уже определен в классе %className', +); diff --git a/local/modules/TheliaSmarty/I18n/tr_TR.php b/local/modules/TheliaSmarty/I18n/tr_TR.php new file mode 100644 index 00000000..05f834a0 --- /dev/null +++ b/local/modules/TheliaSmarty/I18n/tr_TR.php @@ -0,0 +1,21 @@ + '\'%type\' döngü sınıfını genişleten Thelia\Core\Template\Element\BaseLoop', + 'A loop named \'%name\' already exists in the current scope.' => '\'%name\' adlı bir döngü geçerli etki alanında bulunmaktadır.', + 'Loop type \'%type\' is not defined.' => 'Döngü türü \'%type\' tanımlı değil.', + 'Missing \'name\' parameter in loop arguments' => 'Döngü değişkenlerde \'ad\' parametresi eksik', + 'Missing \'rel\' parameter in forHook arguments' => 'ForHook değişkenlerde \'rel\' parametresi eksik', + 'Missing \'rel\' parameter in ifhook/elsehook arguments' => 'İfhook/elsehook bağımsız değişkenleri \'rel\' parametresi eksik', + 'Missing \'rel\' parameter in ifloop/elseloop arguments' => 'İfloop/elseloop bağımsız değişkenleri \'rel\' parametresi eksik', + 'Missing \'rel\' parameter in page loop' => 'Sayfa döngü içinde \'rel\' parametresi eksik', + 'Missing \'type\' parameter in loop arguments' => '\'Tür\' parametresinde döngü bağımsız değişkenleri eksik', + 'Missing \'type\' parameter in {count} loop arguments' => '{count} döngü değişkenlerde \'type\' parametresi eksik', + 'Missing \'type\' parameter in {hasflash} function arguments' => '\'Tür\' parametresinde {hasflash} fonksiyon bağımsız değişkenleri eksik', + 'No pagination currently defined for loop name \'%name\'' => 'Şu anda döngü adı \'%name\' tanımlı hiçbir pagination', + 'Please specify either \'path\' or \'file\' parameter in {url} function.' => 'Lütfen \'yol\' ya da \'dosya\' parametre {url} işlevinde belirtin.', + 'Related hook name \'%name\' is not defined.' => 'İlgili kanca adı \'%name\' tanımlı değil.', + 'Related loop name \'%name\'\' is not defined.' => 'İlgili kanca adı \'%name\' tanımlı değil.', + 'Template file %file cannot be found.' => 'Şablon dosyası %file bulunamadı.', + 'The loop name \'%name\' is already defined in %className class' => 'Döngü adı \'%name\' zaten %className sınıfında tanımlanmış', +]; diff --git a/local/modules/TheliaSmarty/LICENSE.txt b/local/modules/TheliaSmarty/LICENSE.txt new file mode 100644 index 00000000..65c5ca88 --- /dev/null +++ b/local/modules/TheliaSmarty/LICENSE.txt @@ -0,0 +1,165 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + + This version of the GNU Lesser General Public License incorporates +the terms and conditions of version 3 of the GNU General Public +License, supplemented by the additional permissions listed below. + + 0. Additional Definitions. + + As used herein, "this License" refers to version 3 of the GNU Lesser +General Public License, and the "GNU GPL" refers to version 3 of the GNU +General Public License. + + "The Library" refers to a covered work governed by this License, +other than an Application or a Combined Work as defined below. + + An "Application" is any work that makes use of an interface provided +by the Library, but which is not otherwise based on the Library. +Defining a subclass of a class defined by the Library is deemed a mode +of using an interface provided by the Library. + + A "Combined Work" is a work produced by combining or linking an +Application with the Library. The particular version of the Library +with which the Combined Work was made is also called the "Linked +Version". + + The "Minimal Corresponding Source" for a Combined Work means the +Corresponding Source for the Combined Work, excluding any source code +for portions of the Combined Work that, considered in isolation, are +based on the Application, and not on the Linked Version. + + The "Corresponding Application Code" for a Combined Work means the +object code and/or source code for the Application, including any data +and utility programs needed for reproducing the Combined Work from the +Application, but excluding the System Libraries of the Combined Work. + + 1. Exception to Section 3 of the GNU GPL. + + You may convey a covered work under sections 3 and 4 of this License +without being bound by section 3 of the GNU GPL. + + 2. Conveying Modified Versions. + + If you modify a copy of the Library, and, in your modifications, a +facility refers to a function or data to be supplied by an Application +that uses the facility (other than as an argument passed when the +facility is invoked), then you may convey a copy of the modified +version: + + a) under this License, provided that you make a good faith effort to + ensure that, in the event an Application does not supply the + function or data, the facility still operates, and performs + whatever part of its purpose remains meaningful, or + + b) under the GNU GPL, with none of the additional permissions of + this License applicable to that copy. + + 3. Object Code Incorporating Material from Library Header Files. + + The object code form of an Application may incorporate material from +a header file that is part of the Library. You may convey such object +code under terms of your choice, provided that, if the incorporated +material is not limited to numerical parameters, data structure +layouts and accessors, or small macros, inline functions and templates +(ten or fewer lines in length), you do both of the following: + + a) Give prominent notice with each copy of the object code that the + Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the object code with a copy of the GNU GPL and this license + document. + + 4. Combined Works. + + You may convey a Combined Work under terms of your choice that, +taken together, effectively do not restrict modification of the +portions of the Library contained in the Combined Work and reverse +engineering for debugging such modifications, if you also do each of +the following: + + a) Give prominent notice with each copy of the Combined Work that + the Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the Combined Work with a copy of the GNU GPL and this license + document. + + c) For a Combined Work that displays copyright notices during + execution, include the copyright notice for the Library among + these notices, as well as a reference directing the user to the + copies of the GNU GPL and this license document. + + d) Do one of the following: + + 0) Convey the Minimal Corresponding Source under the terms of this + License, and the Corresponding Application Code in a form + suitable for, and under terms that permit, the user to + recombine or relink the Application with a modified version of + the Linked Version to produce a modified Combined Work, in the + manner specified by section 6 of the GNU GPL for conveying + Corresponding Source. + + 1) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (a) uses at run time + a copy of the Library already present on the user's computer + system, and (b) will operate properly with a modified version + of the Library that is interface-compatible with the Linked + Version. + + e) Provide Installation Information, but only if you would otherwise + be required to provide such information under section 6 of the + GNU GPL, and only to the extent that such information is + necessary to install and execute a modified version of the + Combined Work produced by recombining or relinking the + Application with a modified version of the Linked Version. (If + you use option 4d0, the Installation Information must accompany + the Minimal Corresponding Source and Corresponding Application + Code. If you use option 4d1, you must provide the Installation + Information in the manner specified by section 6 of the GNU GPL + for conveying Corresponding Source.) + + 5. Combined Libraries. + + You may place library facilities that are a work based on the +Library side by side in a single library together with other library +facilities that are not Applications and are not covered by this +License, and convey such a combined library under terms of your +choice, if you do both of the following: + + a) Accompany the combined library with a copy of the same work based + on the Library, uncombined with any other library facilities, + conveyed under the terms of this License. + + b) Give prominent notice with the combined library that part of it + is a work based on the Library, and explaining where to find the + accompanying uncombined form of the same work. + + 6. Revised Versions of the GNU Lesser General Public License. + + The Free Software Foundation may publish revised and/or new versions +of the GNU Lesser General Public License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. + + Each version is given a distinguishing version number. If the +Library as you received it specifies that a certain numbered version +of the GNU Lesser General Public License "or any later version" +applies to it, you have the option of following the terms and +conditions either of that published version or of any later version +published by the Free Software Foundation. If the Library as you +received it does not specify a version number of the GNU Lesser +General Public License, you may choose any version of the GNU Lesser +General Public License ever published by the Free Software Foundation. + + If the Library as you received it specifies that a proxy can decide +whether future versions of the GNU Lesser General Public License shall +apply, that proxy's public statement of acceptance of any version is +permanent authorization for you to choose that version for the +Library. diff --git a/local/modules/TheliaSmarty/Readme.md b/local/modules/TheliaSmarty/Readme.md new file mode 100644 index 00000000..96b8b328 --- /dev/null +++ b/local/modules/TheliaSmarty/Readme.md @@ -0,0 +1,2 @@ +## Smarty for Thelia + diff --git a/local/modules/TheliaSmarty/Template/AbstractSmartyPlugin.php b/local/modules/TheliaSmarty/Template/AbstractSmartyPlugin.php new file mode 100644 index 00000000..2093628a --- /dev/null +++ b/local/modules/TheliaSmarty/Template/AbstractSmartyPlugin.php @@ -0,0 +1,133 @@ +getParam($params, $name, $default); + + if (is_string($value)) { + $value = strtolower(trim($value)); + } + return $value; + } + + /** + * Get a function or block parameter value + * + * @param array $params the parameters array + * @param mixed $name as single parameter name, or an array of names. In this case, the first defined parameter is returned. Use this for aliases (context, ctx, c) + * @param mixed $default the defaut value if parameter is missing (default to null) + * @return mixed the parameter value, or the default value if it is not found. + */ + public function getParam($params, $name, $default = null) + { + if (is_array($name)) { + foreach ($name as $test) { + if (isset($params[$test])) { + return $params[$test]; + } + } + } elseif (isset($params[$name])) { + return $params[$name]; + } + + return $default; + } + + /** + * From Smarty 3.1.33, we cannot pass parameters by reference to plugin mehods, and declarations like the + * following will throw the error "Warning: Parameter 2 to expected to be a reference, value given", + * because Smarty uses call_user_func_array() to call plugins methods. + * + * public function categoryDataAccess($params, &$smarty) + * + * This method wraps the method call to prevent this error + * + * @param string $functionName the method name + * @param mixed[] $args the method arguments + * @return mixed + * + * @throws \BadMethodCallException if the method was not found in this class + */ + public function __call($functionName, $args) + { + if (false !== strpos($functionName, self::WRAPPED_METHOD_PREFIX)) { + $functionName = str_replace(self::WRAPPED_METHOD_PREFIX, '', $functionName); + + $params = isset($args[0]) ? $args[0] : []; + $smarty = isset($args[1]) ? $args[1] : null; + + return $this->$functionName($params, $smarty); + } + + throw new \BadMethodCallException("Smarty plugin method '$functionName' was not found.", $this, $functionName); + } + + protected function compatibilityFunctionCaller($params, $smarty, $functionName) + { + return $functionName($params, $smarty); + } + + /** + * @return SmartyPluginDescriptor[] an array of SmartyPluginDescriptor + */ + abstract public function getPluginDescriptors(); +} diff --git a/local/modules/TheliaSmarty/Template/Assets/SmartyAssetsManager.php b/local/modules/TheliaSmarty/Template/Assets/SmartyAssetsManager.php new file mode 100644 index 00000000..214eafc9 --- /dev/null +++ b/local/modules/TheliaSmarty/Template/Assets/SmartyAssetsManager.php @@ -0,0 +1,271 @@ +web_root = $web_root; + $this->path_relative_to_web_root = $path_relative_to_web_root; + + $this->assetsManager = $assetsManager; + $this->assetsResolver = $assetsResolver; + } + + + /** + * Prepare current template assets + * + * @param string $assets_directory the assets directory in the template + * @param \Smarty_Internal_Template $smarty the smarty parser + */ + public function prepareAssets($assets_directory, \Smarty_Internal_Template $smarty) + { + // Be sure to use the proper path separator + if (DS != '/') { + $assets_directory = str_replace('/', DS, $assets_directory); + } + + // Set the current template assets directory + self::$assetsDirectory = $assets_directory; + + /** @var SmartyParser $smartyParser */ + $smartyParser = $smarty->smarty; + + $this->prepareTemplateAssets($smartyParser->getTemplateDefinition(), $assets_directory, $smartyParser); + } + + /** + * Prepare template assets + * + * @param TemplateDefinition $templateDefinition the template to process + * @param string $assets_directory the assets directory in the template + * @param \TheliaSmarty\Template\SmartyParser $smartyParser the current parser. + */ + protected function prepareTemplateAssets( + TemplateDefinition $templateDefinition, + $assets_directory, + SmartyParser $smartyParser + ) { + // Get the registered template directories for the current template type + $templateDirectories = $smartyParser->getTemplateDirectories($templateDefinition->getType()); + + // Use the template name first + $templateDefinitionList = array_merge( + [ $templateDefinition ], + $templateDefinition->getParentList() + ); + + // Prepare assets for all template hierarchy. + // Copy current template assets and its parents assets to the web/assets directory + + /** @var TemplateDefinition $templateDefinitionItem */ + foreach ($templateDefinitionList as $templateDefinitionItem) { + // Use also the parent directories + if (isset($templateDirectories[$templateDefinitionItem->getName()])) { + /* create assets foreach registered directory : main @ modules */ + foreach ($templateDirectories[$templateDefinitionItem->getName()] as $key => $directory) { + // This is the assets directory in the template's tree + $tpl_path = $directory . DS . $assets_directory; + + if (false !== $asset_dir_absolute_path = realpath($tpl_path)) { + $this->assetsManager->prepareAssets( + $asset_dir_absolute_path, + $this->web_root . $this->path_relative_to_web_root, + $templateDefinitionItem->getPath(), + $key . DS . $assets_directory + ); + } + } + } + } + } + + /** + * Retrieve asset URL + * + * @param string $assetType js|css|image + * @param array $params Parameters + * - file File path in the default template + * - source module asset + * - filters filter to apply + * - debug + * - template if you want to load asset from another template + * @param \Smarty_Internal_Template $template Smarty Template + * + * @param bool $allowFilters if false, the 'filters' parameter is ignored + * @return string + * @throws \Exception + */ + public function computeAssetUrl($assetType, $params, \Smarty_Internal_Template $template, $allowFilters = true) + { + $file = $params['file']; + + // The 'file' parameter is mandatory + if (empty($file)) { + throw new \InvalidArgumentException( + "The 'file' parameter is missing in an asset directive (type is '$assetType')" + ); + } + + $assetOrigin = isset($params['source']) ? $params['source'] : ParserInterface::TEMPLATE_ASSETS_KEY; + $filters = $allowFilters && isset($params['filters']) ? $params['filters'] : ''; + $debug = isset($params['debug']) ? trim(strtolower($params['debug'])) == 'true' : false; + $templateName = isset($params['template']) ? $params['template'] : false; + $failsafe = isset($params['failsafe']) ? $params['failsafe'] : false; + + Tlog::getInstance()->debug("Searching asset $file in source $assetOrigin, with template $templateName"); + + /** @var \TheliaSmarty\Template\SmartyParser $smartyParser */ + $smartyParser = $template->smarty; + + if (false !== $templateName) { + // We have to be sure that this external template assets have been properly prepared. + // We will assume the following: + // 1) this template have the same type as the current template, + // 2) this template assets have the same structure as the current template + // (which is in self::$assetsDirectory) + $currentTemplate = $smartyParser->getTemplateDefinition(); + + $templateDefinition = new TemplateDefinition( + $templateName, + $currentTemplate->getType() + ); + + /* Add this templates directory to the current list */ + $smartyParser->addTemplateDirectory( + $templateDefinition->getType(), + $templateDefinition->getName(), + THELIA_TEMPLATE_DIR . $templateDefinition->getPath(), + ParserInterface::TEMPLATE_ASSETS_KEY + ); + + $this->prepareTemplateAssets($templateDefinition, self::$assetsDirectory, $smartyParser); + } + + $assetUrl = $this->assetsResolver->resolveAssetURL( + $assetOrigin, + $file, + $assetType, + $smartyParser, + $filters, + $debug, + self::$assetsDirectory, + $templateName + ); + + if (empty($assetUrl)) { + // Log the problem + if ($failsafe) { + // The asset URL will be '' + Tlog::getInstance()->addWarning("Failed to find asset source file " . $params['file']); + } else { + throw new TheliaProcessException("Failed to find asset source file " . $params['file']); + } + } + + return $assetUrl; + } + + /** + * @param $assetType + * @param $params + * @param $content + * @param \Smarty_Internal_Template $template + * @param $repeat + * @return null + * @throws \Exception + */ + public function processSmartyPluginCall( + $assetType, + $params, + $content, + \Smarty_Internal_Template $template, + &$repeat + ) { + // Opening tag (first call only) + if ($repeat) { + $isfailsafe = false; + + $url = ''; + try { + // Check if we're in failsafe mode + if (isset($params['failsafe'])) { + $isfailsafe = $params['failsafe']; + } + + $url = $this->computeAssetUrl($assetType, $params, $template); + + if (empty($url)) { + $message = sprintf("Failed to get real path of asset %s without exception", $params['file']); + + Tlog::getInstance()->addWarning($message); + + // In debug mode, throw exception + if ($this->assetsManager->isDebugMode() && ! $isfailsafe) { + throw new TheliaProcessException($message); + } + } + } catch (\Exception $ex) { + Tlog::getInstance()->addWarning( + sprintf( + "Failed to get real path of asset %s with exception: %s", + $params['file'], + $ex->getMessage() + ) + ); + + // If we're in development mode, just retrow the exception, so that it will be displayed + if ($this->assetsManager->isDebugMode() && ! $isfailsafe) { + throw $ex; + } + } + $template->assign('asset_url', $url); + } elseif (isset($content)) { + return $content; + } + + return null; + } +} diff --git a/local/modules/TheliaSmarty/Template/Assets/SmartyAssetsResolver.php b/local/modules/TheliaSmarty/Template/Assets/SmartyAssetsResolver.php new file mode 100644 index 00000000..ed6afab8 --- /dev/null +++ b/local/modules/TheliaSmarty/Template/Assets/SmartyAssetsResolver.php @@ -0,0 +1,311 @@ +path_relative_to_web_root = ConfigQuery::read('asset_dir_from_web_root', 'assets'); + + $this->assetsManager = $assetsManager; + + $this->cdnBaseUrl = ConfigQuery::read('cdn.assets-base-url', null); + } + + /** + * @param string $url the fully qualified CDN URL that will be used to create doucments URL. + */ + public function setCdnBaseUrl($url) + { + $this->cdnBaseUrl = $url; + } + + /** + * Generate an asset URL + * + * @param string $source a module code, or ParserInterface::TEMPLATE_ASSETS_KEY + * @param string $file the file path, relative to a template base directory (e.g. assets/css/style.css) + * @param string $type the asset type, either 'css' or ' + * @param ParserInterface $parserInterface the current template parser + * @param array $filters the filters to pass to the asset manager + * @param bool $debug the debug mode + * @param string $declaredAssetsDirectory if not null, this is the assets directory declared in the {declare_assets} function of a template. + * @param mixed $sourceTemplateName A template name, of false. If provided, the assets will be searched in this template directory instead of the current one. + * @return mixed + */ + public function resolveAssetURL($source, $file, $type, ParserInterface $parserInterface, $filters = [], $debug = false, $declaredAssetsDirectory = null, $sourceTemplateName = false) + { + $url = ""; + + // Normalize path separator + $file = $this->fixPathSeparator($file); + + $templateDefinition = $parserInterface->getTemplateDefinition($sourceTemplateName); + + $fileRoot = $this->resolveAssetSourcePathAndTemplate($source, $sourceTemplateName, $file, $parserInterface, $templateDefinition); + + if (null !== $fileRoot) { + $url = $this->assetsManager->processAsset( + $fileRoot . DS . $file, + $fileRoot, + THELIA_WEB_DIR . $this->path_relative_to_web_root, + $templateDefinition->getPath(), + $source, + URL::getInstance()->absoluteUrl($this->path_relative_to_web_root, null, URL::PATH_TO_FILE /* path only */, $this->cdnBaseUrl), + $type, + $filters, + $debug + ); + } else { + Tlog::getInstance()->addError("Asset $file (type $type) was not found."); + } + + return $url; + } + + + /** + * Return an asset source file path. + * + * A system of fallback enables file overriding. It will look for the template : + * - in the current template in directory /modules/{module code}/ + * - in the module in the current template if it exists + * - in the module in the default template + * + * @param string $source a module code, or or ParserInterface::TEMPLATE_ASSETS_KEY + * @param string $templateName a template name, or false to use the current template + * @param string $fileName the filename + * @param ParserInterface $parserInterface the current template parser + * + * @return mixed the path to directory containing the file, or null if the file doesn't exists. + */ + public function resolveAssetSourcePath($source, $templateName, $fileName, ParserInterface $parserInterface) + { + $tpl = $parserInterface->getTemplateDefinition(false); + + return $this->resolveAssetSourcePathAndTemplate( + $source, + $templateName, + $fileName, + $parserInterface, + $tpl + ); + } + + /** + * Return an asset source file path, and get the original template where it was found + * + * A system of fallback enables file overriding. It will look for the template : + * - in the current template in directory /modules/{module code}/ + * - in the parent templates (if any) in directory /modules/{module code}/ + * - in the module in the current template if it exists + * - in the module in the default template + * + * @param string $source a module code, or or ParserInterface::TEMPLATE_ASSETS_KEY + * @param string $templateName a template name, or false to use the current template + * @param string $fileName the filename + * @param ParserInterface $parserInterface the current template parser + * @param TemplateDefinition &$templateDefinition the template where to start search. + * This parameter will contain the template where the asset was found. + * + * @return mixed the path to directory containing the file, or null if the file doesn't exists. + */ + public function resolveAssetSourcePathAndTemplate( + $source, + $templateName, + $fileName, + ParserInterface $parserInterface, + TemplateDefinition &$templateDefinition + ) { + // A simple cache for the path list, to gain some performances + static $cache = []; + + // The path are categorized, and will be checked in the following order. (see getPossibleAssetSources) + // - template : the template directory + // - module_override : the module override directory (template/modules/module_name/...) + // - module_directory : the current template in the module directory + // - the default template in the module directory. + static $pathOrigin = ['template', 'module_override', 'module_directory', 'default_fallback']; + + $templateName = $templateName ?: $templateDefinition->getName(); + + $templateDirectories = $parserInterface->getTemplateDirectories($templateDefinition->getType()); + + $hash = "$source|$templateName"; + + if (! isset($cache[$hash])) { + // Build a list of all template names, starting with current template + $templateList = [$templateName => $templateDefinition]; + + /** @var TemplateDefinition $tplDef */ + foreach ($templateDefinition->getParentList() as $tplDef) { + $templateList[$tplDef->getName()] = $tplDef; + } + + $pathList = []; + + // Get all possible directories to search, including the parent templates ones. + // The current template is checked firts, then the parent ones. + + /** @var TemplateDefinition $templateDef */ + foreach ($templateList as $tplName => $dummy) { + $this->getPossibleAssetSources( + $templateDirectories, + $tplName, + $source, + $pathList + ); + } + + $cache[$hash] = [ $pathList, $templateList ]; + } else { + list($pathList, $templateList) = $cache[$hash]; + } + + // Normalize path separator if required (e.g., / becomes \ on windows) + $fileName = $this->fixPathSeparator($fileName); + + /* Absolute paths are not allowed. This may be a mistake, such as '/assets/...' instead of 'assets/...'. Forgive it. */ + $fileName = ltrim($fileName, DS); + + /* Navigating in the server's directory tree is not allowed :) */ + if (preg_match('!\.\.\\'.DS.'!', $fileName)) { + // This time, we will not forgive. + throw new \InvalidArgumentException("Relative paths are not allowed in assets names."); + } + + // Find the first occurrence of the file in the directory list. + foreach ($pathOrigin as $origin) { + if (isset($pathList[$origin])) { + foreach ($pathList[$origin] as $pathInfo) { + list($tplName, $path) = $pathInfo; + + if ($this->filesExist($path, $fileName)) { + // Got it ! Save the template where the asset was found and return ! + $templateDefinition = $templateList[$tplName]; + + return $path; + } + } + } + } + + // Not found ! + return null; + } + + + /** + * Be sure that the pat separator of a pathname is always the platform path separator. + * + * @param string $path the iput path + * @return string the fixed path + */ + protected function fixPathSeparator($path) + { + if (DS != '/') { + $path = str_replace('/', DS, $path); + } + + return $path; + } + + /** + * Check if a file(s) exists in a directory + * + * @param string $dir the directory path + * @param string $file the file path. It can contain wildcard. eg: /path/*.css + * @return bool true if file(s) + */ + protected function filesExist($dir, $file) + { + if (!file_exists($dir)) { + return false; + } + + $full_path = rtrim($dir, DS) . DS . ltrim($file, DS); + + try { + $files = glob($full_path); + + $files_found = ! empty($files); + } catch (\Exception $ex) { + Tlog::getInstance()->addError($ex->getMessage()); + + $files_found = false; + } + + return $files_found; + } + + /** + * Get all possible directories from which the asset can be found. + * It returns an array of directories ordered by priority. + * + * @param array $directories all directories source available for the template type + * @param string $templateName the name of the template + * @param string $source the module code or ParserInterface::TEMPLATE_ASSETS_KEY + * @param array $pathList the pathList that will be updated + */ + protected function getPossibleAssetSources($directories, $templateName, $source, &$pathList) + { + if ($source !== ParserInterface::TEMPLATE_ASSETS_KEY) { + // We're in a module. + + // First look into the current template in the right scope : frontOffice, backOffice, ... + // template should be overridden in : {template_path}/modules/{module_code}/{template_name} + if (isset($directories[$templateName][ParserInterface::TEMPLATE_ASSETS_KEY])) { + $pathList['module_override'][] = [ + $templateName, + $directories[$templateName][ParserInterface::TEMPLATE_ASSETS_KEY] + . DS + . self::MODULE_OVERRIDE_DIRECTORY_NAME . DS + . $source + ]; + } + + // then in the implementation for the current template used in the module directory + if (isset($directories[$templateName][$source])) { + $pathList['module_directory'][] = [ $templateName, $directories[$templateName][$source] ]; + } + + // then in the default theme in the module itself + if (isset($directories[self::DEFAULT_TEMPLATE_NAME][$source])) { + $pathList['default_fallback'][] = [ $templateName, $directories[self::DEFAULT_TEMPLATE_NAME][$source] ]; + } + } else { + $pathList['template'][] = [ $templateName, $directories[$templateName][$source] ]; + } + } +} diff --git a/local/modules/TheliaSmarty/Template/Exception/SmartyPluginException.php b/local/modules/TheliaSmarty/Template/Exception/SmartyPluginException.php new file mode 100644 index 00000000..41119ecf --- /dev/null +++ b/local/modules/TheliaSmarty/Template/Exception/SmartyPluginException.php @@ -0,0 +1,22 @@ + + */ +class SmartyPluginException extends \SmartyException +{ +} diff --git a/local/modules/TheliaSmarty/Template/Plugins/AdminUtilities.php b/local/modules/TheliaSmarty/Template/Plugins/AdminUtilities.php new file mode 100644 index 00000000..3623636c --- /dev/null +++ b/local/modules/TheliaSmarty/Template/Plugins/AdminUtilities.php @@ -0,0 +1,184 @@ + + */ +class AdminUtilities extends AbstractSmartyPlugin +{ + private $securityContext; + private $templateHelper; + + public function __construct(SecurityContext $securityContext, TemplateHelperInterface $templateHelper) + { + $this->securityContext = $securityContext; + $this->templateHelper = $templateHelper; + } + + /** + * @param \Smarty $smarty + * @param string $templateName + * @param array $variablesArray + * @return string + * @throws \Exception + * @throws \SmartyException + */ + protected function fetchSnippet($smarty, $templateName, $variablesArray) + { + $snippet_content = file_get_contents( + $this->templateHelper->getActiveAdminTemplate()->getTemplateFilePath( + $templateName . '.html' + ) + ); + + $smarty->assign($variablesArray); + + $data = $smarty->fetch(sprintf('string:%s', $snippet_content)); + + return $data; + } + + public function optionOffsetGenerator($params, &$smarty) + { + $label = $this->getParam($params, 'label', null); + + if (null !== $level = $this->getParam($params, [ 'l', 'level'], null)) { + $label = str_repeat(' ', 4 * $level) . $label; + } + + return $label; + } + + /** + * @param $params + * @param $smarty + * @return mixed|string + * @throws \Exception + * @throws \SmartyException + */ + public function generatePositionChangeBlock($params, &$smarty) + { + // The required permissions + $resource = $this->getParam($params, 'resource'); + $module = $this->getParam($params, 'module'); + $access = $this->getParam($params, 'access'); + + // The base position change path + $path = $this->getParam($params, 'path'); + + // The URL parameter the object ID is assigned + $url_parameter = $this->getParam($params, 'url_parameter'); + + // The current object position + $position = $this->getParam($params, 'position'); + + // The object ID + $id = $this->getParam($params, 'id'); + + // The in place dition class + $in_place_edit_class = $this->getParam($params, 'in_place_edit_class'); + + /* + + {$POSITION} + + */ + + if ($this->securityContext->isGranted( + array("ADMIN"), + $resource === null ? array() : array($resource), + $module === null ? array() : array($module), + array($access) + ) + ) { + return $this->fetchSnippet($smarty, 'includes/admin-utilities-position-block', array( + 'admin_utilities_go_up_url' => URL::getInstance()->absoluteUrl($path, array('mode' => 'up', $url_parameter => $id)), + 'admin_utilities_in_place_edit_class' => $in_place_edit_class, + 'admin_utilities_object_id' => $id, + 'admin_utilities_current_position' => $position, + 'admin_utilities_go_down_url' => URL::getInstance()->absoluteUrl($path, array('mode' => 'down', $url_parameter => $id)) + )); + } else { + return $position; + } + } + + /** + * Generates the link of a sortable column header + * + * @param array $params + * @param \Smarty $smarty + * @return string no text is returned. + * @throws \Exception + * @throws \SmartyException + */ + public function generateSortableColumnHeader($params, &$smarty) + { + // The current order of the table + $current_order = $this->getParam($params, 'current_order'); + + // The column ascending order + $order = $this->getParam($params, 'order'); + + // The column descending order label + $reverse_order = $this->getParam($params, 'reverse_order'); + + // The order change path + $path = $this->getParam($params, 'path'); + + // The column label + $label = $this->getParam($params, 'label'); + + // The request parameter + $request_parameter_name = $this->getParam($params, 'request_parameter_name', 'order'); + + if ($current_order == $order) { + $sort_direction = 'up'; + $order_change = $reverse_order; + } elseif ($current_order == $reverse_order) { + $sort_direction = 'down'; + $order_change = $order; + } else { + $order_change = $order; + } + + return $this->fetchSnippet($smarty, 'includes/admin-utilities-sortable-column-header', array( + 'admin_utilities_sort_direction' => $sort_direction, + 'admin_utilities_sorting_url' => URL::getInstance()->absoluteUrl($path, array($request_parameter_name => $order_change)), + 'admin_utilities_header_text' => $label + )); + } + + /** + * Define the various smarty plugins handled by this class + * + * @return array of smarty plugin descriptors + */ + public function getPluginDescriptors() + { + return array( + new SmartyPluginDescriptor('function', 'admin_sortable_header', $this, 'generateSortableColumnHeader'), + new SmartyPluginDescriptor('function', 'admin_position_block', $this, 'generatePositionChangeBlock'), + new SmartyPluginDescriptor('function', 'option_offset', $this, 'optionOffsetGenerator'), + ); + } +} diff --git a/local/modules/TheliaSmarty/Template/Plugins/Assets.php b/local/modules/TheliaSmarty/Template/Plugins/Assets.php new file mode 100644 index 00000000..a64578dd --- /dev/null +++ b/local/modules/TheliaSmarty/Template/Plugins/Assets.php @@ -0,0 +1,106 @@ +assetManager = new SmartyAssetsManager( + $assetsManager, + $assetsResolver, + THELIA_WEB_DIR, + $asset_dir_from_web_root + ); + } + + public function declareAssets($params, \Smarty_Internal_Template $template) + { + if (false !== $asset_dir = $this->getParam($params, 'directory', false)) { + $this->assetManager->prepareAssets($asset_dir, $template); + + return ''; + } + + throw new \InvalidArgumentException('declare_assets: parameter "directory" is required'); + } + + public function blockJavascripts($params, $content, \Smarty_Internal_Template $template, &$repeat) + { + return $this->assetManager->processSmartyPluginCall('js', $params, $content, $template, $repeat); + } + + public function blockImages($params, $content, \Smarty_Internal_Template $template, &$repeat) + { + return $this + ->assetManager + ->processSmartyPluginCall(SmartyAssetsManager::ASSET_TYPE_AUTO, $params, $content, $template, $repeat); + } + + public function blockStylesheets($params, $content, \Smarty_Internal_Template $template, &$repeat) + { + return $this->assetManager->processSmartyPluginCall('css', $params, $content, $template, $repeat); + } + + public function functionImage($params, \Smarty_Internal_Template $template) + { + return $this->assetManager->computeAssetUrl(SmartyAssetsManager::ASSET_TYPE_AUTO, $params, $template); + } + + public function functionAsset($params, \Smarty_Internal_Template $template) + { + return $this->assetManager->computeAssetUrl(SmartyAssetsManager::ASSET_TYPE_AUTO, $params, $template, false); + } + + public function functionJavascript($params, \Smarty_Internal_Template $template) + { + return $this->assetManager->computeAssetUrl(SmartyAssetsManager::ASSET_TYPE_AUTO, $params, $template); + } + + public function functionStylesheet($params, \Smarty_Internal_Template $template) + { + return $this->assetManager->computeAssetUrl('css', $params, $template); + } + + /** + * Define the various smarty plugins hendled by this class + * + * @return array an array of smarty plugin descriptors + */ + public function getPluginDescriptors() + { + return array( + new SmartyPluginDescriptor('block', 'stylesheets', $this, 'blockStylesheets'), + new SmartyPluginDescriptor('block', 'javascripts', $this, 'blockJavascripts'), + new SmartyPluginDescriptor('block', 'images', $this, 'blockImages'), + + new SmartyPluginDescriptor('function', 'asset', $this, 'functionAsset'), + new SmartyPluginDescriptor('function', 'image', $this, 'functionImage'), + new SmartyPluginDescriptor('function', 'javascript', $this, 'functionJavascript'), + new SmartyPluginDescriptor('function', 'stylesheet', $this, 'functionStylesheet'), + + new SmartyPluginDescriptor('function', 'declare_assets', $this, 'declareAssets') + ); + } +} diff --git a/local/modules/TheliaSmarty/Template/Plugins/Cache.php b/local/modules/TheliaSmarty/Template/Plugins/Cache.php new file mode 100644 index 00000000..464e5232 --- /dev/null +++ b/local/modules/TheliaSmarty/Template/Plugins/Cache.php @@ -0,0 +1,144 @@ + + */ +class Cache extends AbstractSmartyPlugin +{ + /** @var AdapterInterface */ + protected $adapter; + + /** @var RequestStack */ + protected $requestStack; + + /** @var bool */ + protected $debug; + + /** @var TaxEngine */ + protected $taxEngine; + + /** + * Cache constructor. + * @param AdapterInterface $esiFragmentRenderer + * @param RequestStack $requestStack + * @param TaxEngine $taxEngine + * @param $debug + */ + public function __construct(AdapterInterface $esiFragmentRenderer, RequestStack $requestStack, TaxEngine $taxEngine, $debug) + { + $this->adapter = $esiFragmentRenderer; + $this->requestStack = $requestStack; + $this->taxEngine = $taxEngine; + $this->debug = $debug; + } + + public function cache(array $params, $content, $template, &$repeat) + { + $key = $this->getParam($params, 'key'); + if (null === $key || empty($key)) { + throw new \InvalidArgumentException( + "Missing 'key' parameter in cache arguments" + ); + } + + $ttl = (int) $this->getParam($params, 'ttl'); + if (null === $ttl) { + throw new \InvalidArgumentException( + "Missing 'ttl' parameter in cache arguments" + ); + } + + if ($this->debug || $ttl < 1) { + if (null !== $content) { + $repeat = false; + return $content; + } + return null; + } + + /** @var CacheItemInterface $cacheItem */ + $cacheItem = $this->adapter->getItem( + $this->generateKey($params) + ); + + if ($cacheItem->isHit()) { + $repeat = false; + return $cacheItem->get(); + } + + if ($content !== null) { + $cacheItem + ->expiresAfter((int) $params['ttl']) + ->set($content); + + $this->adapter->save($cacheItem); + $repeat = false; + return $cacheItem->get(); + } + } + + /** + * @param array $params + * @return string + */ + protected function generateKey(array $params) + { + /** @var Session $session */ + if (null !== $session = $this->requestStack->getCurrentRequest()->getSession()) { + if (!isset($params['lang'])) { + $params['lang'] = $session->getLang(true)->getId(); + } + if (!isset($params['currency'])) { + $params['currency'] = $session->getCurrency(true)->getId(); + } + + if (!isset($params['country'])) { + $params['country'] = $this->taxEngine->getDeliveryCountry()->getId(); + } + + if (!isset($params['customer_discount'])) { + /** @var Customer $customer */ + if (null !== $customer = $session->getCustomerUser()) { + $params['customer_discount'] = $customer->getDiscount(); + } else { + $params['customer_discount'] = 0; + } + } + } + + return 'smarty_cache_' . md5(json_encode($params)); + } + + /** + * @return array an array of SmartyPluginDescriptor + */ + public function getPluginDescriptors() + { + return array( + new SmartyPluginDescriptor('block', 'cache', $this, 'cache') + ); + } +} diff --git a/local/modules/TheliaSmarty/Template/Plugins/CartPostage.php b/local/modules/TheliaSmarty/Template/Plugins/CartPostage.php new file mode 100644 index 00000000..1acc59e9 --- /dev/null +++ b/local/modules/TheliaSmarty/Template/Plugins/CartPostage.php @@ -0,0 +1,269 @@ +container = $container; + + $this->requestStack = $container->get('request_stack'); + + $this->request = $this->getCurrentRequest(); + + $this->dispatcher = $container->get('event_dispatcher'); + } + + /** + * Get postage amount for cart + * + * @param array $params Block parameters + * @param mixed $content Block content + * @param \Smarty_Internal_Template $template Template + * @param bool $repeat Control how many times + * the block is displayed + * + * @return mixed + */ + public function postage($params, $content, $template, &$repeat) + { + if (!$repeat) { + return (null !== $this->countryId) ? $content : ""; + } + + $customer = $this->getCurrentRequest()->getSession()->getCustomerUser(); + /** @var Address $address */ + /** @var Country $country */ + list($address, $country, $state) = $this->getDeliveryInformation($customer); + + if (null !== $country) { + $this->countryId = $country->getId(); + // try to get the cheapest delivery for this country + $this->getCheapestDelivery($address, $country, $state); + } + + $template->assign('country_id', $this->countryId); + $template->assign('delivery_id', $this->deliveryId); + $template->assign('postage', $this->postage ?: 0.0); + $template->assign('postage_tax', $this->postageTax ?: 0.0); + $template->assign('postage_title', $this->postageTaxRuleTitle ?: 0.0); + $template->assign('is_customizable', $this->isCustomizable); + } + + /** + * Retrieve the delivery country for a customer + * + * The rules : + * - the country of the delivery address of the customer related to the + * cart if it exists + * - the country saved in cookie if customer have changed + * the default country + * - the default country for the shop if it exists + * + * + * @param \Thelia\Model\Customer $customer + */ + protected function getDeliveryInformation(Customer $customer = null) + { + $address = null; + // get the selected delivery address + if (null !== $addressId = $this->getCurrentRequest()->getSession()->getOrder()->getChoosenDeliveryAddress()) { + if (null !== $address = AddressQuery::create()->findPk($addressId)) { + $this->isCustomizable = false; + return [$address, $address->getCountry(), null]; + } + } + + // get country from customer addresses + if (null !== $customer) { + $address = AddressQuery::create() + ->filterByCustomerId($customer->getId()) + ->filterByIsDefault(1) + ->findOne() + ; + + if (null !== $address) { + $this->isCustomizable = false; + + return [$address, $address->getCountry(), $address->getState()]; + } + } + + // get country from cookie + $cookieName = ConfigQuery::read('front_cart_country_cookie_name', 'fcccn'); + if ($this->getCurrentRequest()->cookies->has($cookieName)) { + $cookieVal = $this->getCurrentRequest()->cookies->getInt($cookieName, 0); + if (0 !== $cookieVal) { + $country = CountryQuery::create()->findPk($cookieVal); + if (null !== $country) { + return [null, $country, null]; + } + } + } + + // get default country for store. + try { + $country = Country::getDefaultCountry(); + + return [null, $country, null]; + } catch (\LogicException $e) { + ; + } + + return [null, null, null]; + } + + /** + * Retrieve the cheapest delivery for country + * + * @param Address $address + * @param Country $country + * @param State|null $state + * @throws PropelException + */ + protected function getCheapestDelivery(Address $address = null, Country $country = null, State $state = null) + { + $cart = $this->getCurrentRequest()->getSession()->getSessionCart(); + + $deliveryModules = ModuleQuery::create() + ->filterByActivate(1) + ->filterByType(BaseModule::DELIVERY_MODULE_TYPE, Criteria::EQUAL) + ->find() + ; + + $virtual = $cart->isVirtual(); + + /** @var \Thelia\Model\Module $deliveryModule */ + foreach ($deliveryModules as $deliveryModule) { + $areaDeliveryModule = AreaDeliveryModuleQuery::create() + ->findByCountryAndModule($country, $deliveryModule, $state); + if (null === $areaDeliveryModule && false === $virtual) { + continue; + } + + $moduleInstance = $deliveryModule->getDeliveryModuleInstance($this->container); + + if (true === $virtual + && false === $moduleInstance->handleVirtualProductDelivery() + ) { + continue; + } + + try { + $deliveryPostageEvent = new DeliveryPostageEvent($moduleInstance, $cart, $address, $country, $state); + $this->dispatcher->dispatch( + TheliaEvents::MODULE_DELIVERY_GET_POSTAGE, + $deliveryPostageEvent + ); + + if ($deliveryPostageEvent->isValidModule()) { + $postage = $deliveryPostageEvent->getPostage(); + + if (null === $this->postage || $this->postage > $postage->getAmount()) { + $this->postage = $postage->getAmount(); + $this->postageTax = $postage->getAmountTax(); + $this->postageTaxRuleTitle = $postage->getTaxRuleTitle(); + $this->deliveryId = $deliveryModule->getId(); + } + } + } catch (DeliveryException $ex) { + // Module is not available + } + } + } + + /** + * Defines the various smarty plugins handled by this class + * + * @return \TheliaSmarty\Template\SmartyPluginDescriptor[] smarty plugin descriptors + */ + public function getPluginDescriptors() + { + return array( + new SmartyPluginDescriptor('block', 'postage', $this, 'postage') + ); + } + + /** + * @return null|Request + */ + protected function getCurrentRequest() + { + return $this->requestStack->getCurrentRequest(); + } +} diff --git a/local/modules/TheliaSmarty/Template/Plugins/DataAccessFunctions.php b/local/modules/TheliaSmarty/Template/Plugins/DataAccessFunctions.php new file mode 100644 index 00000000..a6ddce92 --- /dev/null +++ b/local/modules/TheliaSmarty/Template/Plugins/DataAccessFunctions.php @@ -0,0 +1,973 @@ + + * + */ +class DataAccessFunctions extends AbstractSmartyPlugin +{ + /** @var SecurityContext */ + private $securityContext; + + /** @var ParserContext */ + protected $parserContext; + + /** @var RequestStack */ + protected $requestStack; + + /** @var EventDispatcherInterface */ + protected $dispatcher; + + /** @var TaxEngine */ + protected $taxEngine; + + /** @var CouponManager */ + protected $couponManager; + + private static $dataAccessCache = array(); + + public function __construct( + RequestStack $requestStack, + SecurityContext $securityContext, + TaxEngine $taxEngine, + ParserContext $parserContext, + EventDispatcherInterface $dispatcher, + CouponManager $couponManager + ) { + $this->securityContext = $securityContext; + $this->parserContext = $parserContext; + $this->requestStack = $requestStack; + $this->dispatcher = $dispatcher; + $this->taxEngine = $taxEngine; + $this->couponManager = $couponManager; + } + + /** + * Provides access to the current logged administrator attributes using the accessors. + * + * @param array $params + * @param \Smarty $smarty + * @return string the value of the requested attribute + */ + public function adminDataAccess($params, &$smarty) + { + return $this->dataAccess("Admin User", $params, $this->securityContext->getAdminUser()); + } + + /** + * Provides access to the current logged customer attributes thought the accessor + * + * @param array $params + * @param \Smarty $smarty + * @return string the value of the requested attribute + */ + public function customerDataAccess($params, &$smarty) + { + return $this->dataAccess("Customer User", $params, $this->securityContext->getCustomerUser()); + } + + /** + * Provides access to an attribute of the current product + * + * @param array $params + * @param \Smarty $smarty + * @return string the value of the requested attribute + */ + public function productDataAccess($params, &$smarty) + { + $productId = $this->getRequest()->get('product_id'); + + if ($productId !== null) { + return $this->dataAccessWithI18n( + "Product", + $params, + ProductQuery::create()->filterByPrimaryKey($productId) + ); + } + + return ''; + } + + /** + * Provides access to an attribute of the current category + * + * @param array $params + * @param \Smarty $smarty + * @return string the value of the requested attribute + */ + public function categoryDataAccess($params, &$smarty) + { + $categoryId = $this->getRequest()->get('category_id'); + + if ($categoryId === null) { + $productId = $this->getRequest()->get('product_id'); + + if ($productId !== null) { + if (null !== $product = ProductQuery::create()->findPk($productId)) { + $categoryId = $product->getDefaultCategoryId(); + } + } + } + + if ($categoryId !== null) { + return $this->dataAccessWithI18n( + "Category", + $params, + CategoryQuery::create()->filterByPrimaryKey($categoryId) + ); + } + + return ''; + } + + /** + * Provides access to an attribute of the current content + * + * @param array $params + * @param \Smarty $smarty + * @return string the value of the requested attribute + */ + public function contentDataAccess($params, &$smarty) + { + $contentId = $this->getRequest()->get('content_id'); + + if ($contentId !== null) { + return $this->dataAccessWithI18n( + "Content", + $params, + ContentQuery::create()->filterByPrimaryKey($contentId) + ); + } + + return ''; + } + + /** + * Provides access to an attribute of the current folder + * + * @param array $params + * @param \Smarty $smarty + * @return string the value of the requested attribute + */ + public function folderDataAccess($params, &$smarty) + { + $folderId = $this->getRequest()->get('folder_id'); + + if ($folderId === null) { + $contentId = $this->getRequest()->get('content_id'); + + if ($contentId !== null) { + if (null !== $content = ContentQuery::create()->findPk($contentId)) { + $folderId = $content->getDefaultFolderId(); + } + } + } + + if ($folderId !== null) { + return $this->dataAccessWithI18n( + "Folder", + $params, + FolderQuery::create()->filterByPrimaryKey($folderId) + ); + } + + return ''; + } + + /** + * Provides access to an attribute of the current brand + * + * @param array $params + * @param \Smarty $smarty + * @return string the value of the requested attribute + */ + public function brandDataAccess($params, &$smarty) + { + $brandId = $this->getRequest()->get('brand_id'); + + if ($brandId === null) { + $productId = $this->getRequest()->get('product_id'); + + if ($productId !== null) { + if (null !== $product = ProductQuery::create()->findPk($productId)) { + $brandId = $product->getBrandId(); + } + } + } + + if ($brandId !== null) { + return $this->dataAccessWithI18n( + "Brand", + $params, + BrandQuery::create()->filterByPrimaryKey($brandId) + ); + } + + return ''; + } + + + /** + * Provides access to an attribute of the current currency + * + * @param array $params + * @param \Smarty $smarty + * @return string the value of the requested attribute + */ + public function currencyDataAccess($params, $smarty) + { + $currency = $this->getSession()->getCurrency(); + + if ($currency) { + return $this->dataAccessWithI18n( + "Currency", + $params, + CurrencyQuery::create()->filterByPrimaryKey($currency->getId()), + array("NAME") + ); + } + + return ''; + } + + /** + * Provides access to an attribute of the default country + * + * @param array $params + * @param \Smarty $smarty + * @return string the value of the requested attribute + */ + public function countryDataAccess($params, $smarty) + { + switch ($params["ask"]) { + case "default": + return $this->dataAccessWithI18n( + "defaultCountry", + $params, + CountryQuery::create()->filterByByDefault(1)->limit(1) + ); + } + + return ''; + } + + /** + * Provides access to an attribute of the cart + * + * @param array $params + * @param \Smarty $smarty + * @return string the value of the requested attribute + * @throws \Propel\Runtime\Exception\PropelException + */ + public function cartDataAccess($params, $smarty) + { + /** @var Country $taxCountry */ + if (array_key_exists('currentCountry', self::$dataAccessCache)) { + $taxCountry = self::$dataAccessCache['currentCountry']; + } else { + $taxCountry = $this->taxEngine->getDeliveryCountry(); + self::$dataAccessCache['currentCountry'] = $taxCountry; + } + + /** @var State $taxState */ + if (array_key_exists('currentState', self::$dataAccessCache)) { + $taxState = self::$dataAccessCache['currentState']; + } else { + $taxState = $this->taxEngine->getDeliveryState(); + self::$dataAccessCache['currentState'] = $taxState; + } + + /** @var Cart $cart */ + $cart = $this->getSession()->getSessionCart($this->dispatcher); + + $result = ""; + switch ($params["attr"]) { + case "count_product": + case "product_count": + $result = $cart->getCartItems()->count(); + break; + case "count_item": + case "item_count": + $count_allitem = 0; + foreach ($cart->getCartItems() as $cartItem) { + $count_allitem += $cartItem->getQuantity(); + } + $result = $count_allitem; + break; + case "total_price": + case "total_price_with_discount": + $result = $cart->getTotalAmount(true, $taxCountry, $taxState); + break; + case "total_price_without_discount": + $result = $cart->getTotalAmount(false, $taxCountry, $taxState); + break; + case "total_taxed_price": + case "total_taxed_price_with_discount": + $result = $cart->getTaxedAmount($taxCountry, true, $taxState); + break; + case "total_taxed_price_without_discount": + $result = $cart->getTaxedAmount($taxCountry, false, $taxState); + break; + case "is_virtual": + case "contains_virtual_product": + $result = $cart->isVirtual(); + break; + case "total_vat": + case 'total_tax_amount': + $result = $cart->getTotalVAT($taxCountry, $taxState); + break; + case 'total_tax_amount_without_discount': + $result = $cart->getTotalVAT($taxCountry, $taxState, false); + break; + case 'discount_tax_amount': + $result = $cart->getDiscountVAT($taxCountry, $taxState); + break; + case "weight": + $result = $cart->getWeight(); + break; + } + + return $result; + } + + public function couponDataAccess($params, &$smarty) + { + /** @var Order $order */ + $order = $this->getSession()->getOrder(); + $attribute = $this->getNormalizedParam($params, array('attribute', 'attrib', 'attr')); + + switch ($attribute) { + case 'has_coupons': + return count($this->couponManager->getCouponsKept()) > 0; + case 'coupon_count': + return count($this->couponManager->getCouponsKept()); + case 'coupon_list': + $orderCoupons = []; + /** @var CouponInterface $coupon */ + foreach ($this->couponManager->getCouponsKept() as $coupon) { + $orderCoupons[] = $coupon->getCode(); + } + return $orderCoupons; + case 'is_delivery_free': + return $this->couponManager->isCouponRemovingPostage($order); + } + + throw new \InvalidArgumentException(sprintf("%s has no '%s' attribute", 'Order', $attribute)); + } + + /** + * Provides access to an attribute of the current order + * + * @param array $params + * @param \Smarty $smarty + * @return string the value of the requested attribute + */ + public function orderDataAccess($params, &$smarty) + { + /** @var Order $order */ + $order = $this->getSession()->getOrder(); + $attribute = $this->getNormalizedParam($params, array('attribute', 'attrib', 'attr')); + switch ($attribute) { + case 'untaxed_postage': + return $order->getUntaxedPostage(); + case 'postage': + return $order->getPostage(); + case 'postage_tax': + return $order->getPostageTax(); + case 'discount': + return $order->getDiscount(); + case 'delivery_address': + return $order->getChoosenDeliveryAddress(); + case 'invoice_address': + return $order->getChoosenInvoiceAddress(); + case 'delivery_module': + return $order->getDeliveryModuleId(); + case 'payment_module': + return $order->getPaymentModuleId(); + case 'has_virtual_product': + return $order->hasVirtualProduct(); + } + + throw new \InvalidArgumentException(sprintf("%s has no '%s' attribute", 'Order', $attribute)); + } + + /** + * Provides access to an attribute of the current language + * + * @param array $params + * @param \Smarty $smarty + * @return string the value of the requested attribute + */ + + public function langDataAccess($params, $smarty) + { + return $this->dataAccess("Lang", $params, $this->getSession()->getLang()); + } + + public function configDataAccess($params, $smarty) + { + $key = $this->getParam($params, 'key', false); + + if ($key === false) { + return null; + } + + $default = $this->getParam($params, 'default', ''); + + return ConfigQuery::read($key, $default); + } + + /** + * Provides access to a module configuration value + * + * @param array $params + * @param \Smarty $smarty + * @return string the value of the configuration value + */ + + public function moduleConfigDataAccess($params, $smarty) + { + $key = $this->getParam($params, 'key', false); + $moduleCode = $this->getParam($params, 'module', false); + $locale = $this->getParam($params, 'locale'); + + if (null === $locale) { + $locale = $this->getSession()->getLang()->getLocale(); + } + + if ($key === false || $moduleCode === false) { + return null; + } + + $default = $this->getParam($params, 'default', ''); + + if (null !== $module = ModuleQuery::create()->findOneByCode($moduleCode)) { + return ModuleConfigQuery::create() + ->getConfigValue( + $module->getId(), + $key, + $default, + $locale + ); + } else { + Tlog::getInstance()->addWarning( + sprintf( + "Module code '%s' not found in module-config Smarty function", + $moduleCode + ) + ); + + $value = $default; + } + + return $value; + } + + /** + * Provides access to sales statistics + * + * @param array $params + * @param \Smarty $smarty + * @return string the value of the requested attribute + * @throws \Exception + */ + public function statsAccess($params, $smarty) + { + if (false === array_key_exists("key", $params)) { + throw new \InvalidArgumentException(sprintf("missing key attribute in stats access function")); + } + if (false === array_key_exists("startDate", $params) || $params['startDate'] === '') { + throw new \InvalidArgumentException(sprintf("missing startDate attribute in stats access function")); + } + if (false === array_key_exists("endDate", $params) || $params['endDate'] === '') { + throw new \InvalidArgumentException(sprintf("missing endDate attribute in stats access function")); + } + + if (false !== array_key_exists("includeShipping", $params) && $params['includeShipping'] == 'false') { + $includeShipping = false; + } else { + $includeShipping = true; + } + + if (false !== array_key_exists("withTaxes", $params) && $params['withTaxes'] == 'false') { + $withTaxes = false; + } else { + $withTaxes = true; + } + + if ($params['startDate'] == 'today') { + $startDate = new \DateTime(); + $startDate->setTime(0, 0, 0); + } elseif ($params['startDate'] == 'yesterday') { + $startDate = new \DateTime(); + $startDate->setTime(0, 0, 0); + $startDate->modify('-1 day'); + } elseif ($params['startDate'] == 'this_month') { + $startDate = new \DateTime(); + $startDate->modify('first day of this month'); + $startDate->setTime(0, 0, 0); + } elseif ($params['startDate'] == 'last_month') { + $startDate = new \DateTime(); + $startDate->modify('first day of last month'); + $startDate->setTime(0, 0, 0); + } elseif ($params['startDate'] == 'this_year') { + $startDate = new \DateTime(); + $startDate->modify('first day of January this year'); + $startDate->setTime(0, 0, 0); + } elseif ($params['startDate'] == 'last_year') { + $startDate = new \DateTime(); + $startDate->modify('first day of January last year'); + $startDate->setTime(0, 0, 0); + } else { + try { + $startDate = new \DateTime($params['startDate']); + } catch (\Exception $e) { + throw new \InvalidArgumentException( + sprintf("invalid startDate attribute '%s' in stats access function", $params['startDate']) + ); + } + } + + if ($params['endDate'] == 'today') { + $endDate = new \DateTime(); + $endDate->setTime(0, 0, 0); + } elseif ($params['endDate'] == 'yesterday') { + $endDate = new \DateTime(); + $endDate->setTime(0, 0, 0); + $endDate->modify('-1 day'); + } elseif ($params['endDate'] == 'this_month') { + $endDate = new \DateTime(); + $endDate->modify('last day of this month'); + $endDate->setTime(0, 0, 0); + } elseif ($params['endDate'] == 'last_month') { + $endDate = new \DateTime(); + $endDate->modify('last day of last month'); + $endDate->setTime(0, 0, 0); + } elseif ($params['endDate'] == 'this_year') { + $endDate = new \DateTime(); + $endDate->modify('last day of December this year'); + $endDate->setTime(0, 0, 0); + } elseif ($params['endDate'] == 'last_year') { + $endDate = new \DateTime(); + $endDate->modify('last day of December last year'); + $endDate->setTime(0, 0, 0); + } else { + try { + $endDate = new \DateTime($params['endDate']); + } catch (\Exception $e) { + throw new \InvalidArgumentException( + sprintf("invalid endDate attribute '%s' in stats access function", $params['endDate']) + ); + } + } + + switch ($params['key']) { + case 'sales': + return OrderQuery::getSaleStats($startDate, $endDate, $includeShipping, $withTaxes); + break; + case 'orders': + return OrderQuery::getOrderStats($startDate, $endDate, OrderStatusQuery::getPaidStatusIdList()); + break; + } + + throw new \InvalidArgumentException( + sprintf("invalid key attribute '%s' in stats access function", $params['key']) + ); + } + + /** + * Retrieve meta data associated to an element + * + * params should contain at least key an id attributes. Thus it will return + * an array of associated data. + * + * If meta argument is specified then it will return an unique value. + * + * @param array $params + * @param \Smarty $smarty + * + * @throws \InvalidArgumentException + * + * @return string|array|null + */ + public function metaAccess($params, $smarty) + { + $meta = $this->getParam($params, 'meta', null); + $key = $this->getParam($params, 'key', null); + $id = $this->getParam($params, 'id', null); + + $cacheKey = sprintf('meta_%s_%s_%s', $meta, $key, $id); + + $out = null; + + if (array_key_exists($cacheKey, self::$dataAccessCache)) { + return self::$dataAccessCache[$cacheKey]; + } + + if ($key !== null && $id !== null) { + if ($meta === null) { + $out = MetaDataQuery::getAllVal($key, (int) $id); + } else { + $out = MetaDataQuery::getVal($meta, $key, (int) $id); + } + } else { + throw new \InvalidArgumentException("key and id arguments are required in meta access function"); + } + + self::$dataAccessCache[$cacheKey] = $out; + + if (!empty($params['out'])) { + $smarty->assign($params['out'], $out); + + return $out !== null ? true : false; + } else { + if (is_array($out)) { + throw new \InvalidArgumentException('The argument "out" is required if the meta value is an array'); + } + + return $out; + } + } + + /** + * @param $objectLabel + * @param $params + * @param ModelCriteria $search + * @param array $columns + * @param null $foreignTable + * @param string $foreignKey + * + * @return string + */ + protected function dataAccessWithI18n( + $objectLabel, + $params, + ModelCriteria $search, + $columns = array('TITLE', 'CHAPO', 'DESCRIPTION', 'POSTSCRIPTUM'), + $foreignTable = null, + $foreignKey = 'ID' + ) { + if (array_key_exists('data_' . $objectLabel, self::$dataAccessCache)) { + $data = self::$dataAccessCache['data_' . $objectLabel]; + } else { + $lang = $this->getNormalizedParam($params, array('lang')); + if ($lang === null) { + $lang = $this->getSession()->getLang()->getId(); + } + + ModelCriteriaTools::getI18n( + false, + $lang, + $search, + $this->getSession()->getLang()->getLocale(), + $columns, + $foreignTable, + $foreignKey, + true + ); + + $data = $search->findOne(); + + self::$dataAccessCache['data_' . $objectLabel] = $data; + } + + if ($data !== null) { + $noGetterData = array(); + + foreach ($columns as $column) { + $noGetterData[$column] = $data->getVirtualColumn('i18n_' . $column); + } + + return $this->dataAccess($objectLabel, $params, $data, $noGetterData); + } else { + throw new NotFoundHttpException(); + } + } + + /** + * @param $objectLabel + * @param $params + * @param $data + * @param array $noGetterData + * + * @return string + * @throws \InvalidArgumentException + */ + protected function dataAccess($objectLabel, $params, $data, $noGetterData = array()) + { + $attribute = $this->getNormalizedParam($params, array('attribute', 'attrib', 'attr')); + + if (!empty($attribute)) { + if (null != $data) { + $keyAttribute = strtoupper($attribute); + if (array_key_exists($keyAttribute, $noGetterData)) { + return $noGetterData[$keyAttribute]; + } + + $getter = sprintf("get%s", $this->underscoreToCamelcase($attribute)); + if (method_exists($data, $getter)) { + $return = $data->$getter(); + + if ($return instanceof \DateTime) { + if (array_key_exists("format", $params)) { + $format = $params["format"]; + } else { + $format = DateTimeFormat::getInstance($this->getRequest())->getFormat( + array_key_exists("output", $params) ? $params["output"] : null + ); + } + + $return = $return->format($format); + } + + return $return; + } + + throw new \InvalidArgumentException(sprintf("%s has no '%s' attribute", $objectLabel, $attribute)); + } + } + + return ''; + } + + /** + * Transcode an underscored string into a camel-cased string, eg. default_folder into DefaultFolder + * + * @param string $str the string to convert from underscore to camel-case + * + * @return string the camel cased string. + */ + private function underscoreToCamelcase($str) + { + // Split string in words. + $words = explode('_', strtolower($str)); + + $return = ''; + + foreach ($words as $word) { + $return .= ucfirst(trim($word)); + } + + return $return; + } + + /** + * Provides access to the uploaded store-related images (such as logo or favicon) + * + * @param array $params + * @param string $content + * @param \Smarty_Internal_Template $template + * @param boolean $repeat + * @return string|null + */ + public function storeMediaDataAccess($params, $content, \Smarty_Internal_Template $template, &$repeat) + { + $type = $this->getParam($params, 'type', null); + $allowedTypes = ['favicon', 'logo', 'banner']; + + + if ($type !== null && in_array($type, $allowedTypes)) { + switch ($type) { + case 'favicon': + $configKey = 'favicon_file'; + $defaultImageName = 'favicon.png'; + break; + case 'logo': + $configKey = 'logo_file'; + $defaultImageName = 'logo.png'; + break; + case 'banner': + $configKey = 'banner_file'; + $defaultImageName = 'banner.jpg'; + break; + } + + $uploadDir = ConfigQuery::read('images_library_path'); + + if ($uploadDir === null) { + $uploadDir = THELIA_LOCAL_DIR . 'media' . DS . 'images'; + } else { + $uploadDir = THELIA_ROOT . $uploadDir; + } + + $uploadDir .= DS . 'store'; + + + $imageFileName = ConfigQuery::read($configKey); + + $skipImageTransform = false; + + // If we couldn't find the image path in the config table or if it doesn't exist, we take the default image provided. + if ($imageFileName == null) { + $imageSourcePath = $uploadDir . DS . $defaultImageName; + } else { + $imageSourcePath = $uploadDir . DS . $imageFileName; + + if (!file_exists($imageSourcePath)) { + Tlog::getInstance()->error(sprintf('Source image file %s does not exists.', $imageSourcePath)); + $imageSourcePath = $uploadDir . DS . $defaultImageName; + } + + if ($type == 'favicon') { + $extension = pathinfo($imageSourcePath, PATHINFO_EXTENSION); + if ($extension == 'ico') { + $mime_type = 'image/x-icon'; + + // If the media is a .ico favicon file, we skip the image transformations, + // as transformations on .ico file are not supported by Thelia. + $skipImageTransform = true; + } else { + $mime_type = 'image/png'; + } + + $template->assign('MEDIA_MIME_TYPE', $mime_type); + } + } + + $event = new ImageEvent(); + $event->setSourceFilepath($imageSourcePath) + ->setCacheSubdirectory('store'); + + + if (!$skipImageTransform) { + switch ($this->getParam($params, 'resize_mode', null)) { + case 'crop': + $resize_mode = \Thelia\Action\Image::EXACT_RATIO_WITH_CROP; + break; + + case 'borders': + $resize_mode = \Thelia\Action\Image::EXACT_RATIO_WITH_BORDERS; + break; + + case 'none': + default: + $resize_mode = \Thelia\Action\Image::KEEP_IMAGE_RATIO; + } + + // Prepare transformations + $width = $this->getParam($params, 'width', null); + $height = $this->getParam($params, 'height', null); + $rotation = $this->getParam($params, 'rotation', null); + + if (!is_null($width)) { + $event->setWidth($width); + } + if (!is_null($height)) { + $event->setHeight($height); + } + $event->setResizeMode($resize_mode); + if (!is_null($rotation)) { + $event->setRotation($rotation); + } + } + + try { + $this->dispatcher->dispatch(TheliaEvents::IMAGE_PROCESS, $event); + $template->assign('MEDIA_URL', $event->getFileUrl()); + } catch (\Exception $ex) { + Tlog::getInstance()->error($ex->getMessage()); + $template->assign('MEDIA_URL', ''); + } + } + + if (isset($content)) { + return $content; + } else { + return null; + } + } + + /** + * @inheritdoc + */ + public function getPluginDescriptors() + { + return array( + new SmartyPluginDescriptor('function', 'admin', $this, 'adminDataAccess'), + new SmartyPluginDescriptor('function', 'customer', $this, 'customerDataAccess'), + new SmartyPluginDescriptor('function', 'product', $this, 'productDataAccess'), + new SmartyPluginDescriptor('function', 'category', $this, 'categoryDataAccess'), + new SmartyPluginDescriptor('function', 'content', $this, 'contentDataAccess'), + new SmartyPluginDescriptor('function', 'folder', $this, 'folderDataAccess'), + new SmartyPluginDescriptor('function', 'brand', $this, 'brandDataAccess'), + new SmartyPluginDescriptor('function', 'currency', $this, 'currencyDataAccess'), + new SmartyPluginDescriptor('function', 'country', $this, 'countryDataAccess'), + new SmartyPluginDescriptor('function', 'lang', $this, 'langDataAccess'), + new SmartyPluginDescriptor('function', 'cart', $this, 'cartDataAccess'), + new SmartyPluginDescriptor('function', 'order', $this, 'orderDataAccess'), + new SmartyPluginDescriptor('function', 'config', $this, 'configDataAccess'), + new SmartyPluginDescriptor('function', 'stats', $this, 'statsAccess'), + new SmartyPluginDescriptor('function', 'meta', $this, 'metaAccess'), + new SmartyPluginDescriptor('function', 'module_config', $this, 'moduleConfigDataAccess'), + new SmartyPluginDescriptor('function', 'coupon', $this, 'couponDataAccess'), + + new SmartyPluginDescriptor('block', 'local_media', $this, 'storeMediaDataAccess'), + ); + } + + /** + * @return Request + */ + protected function getRequest() + { + return $this->requestStack->getCurrentRequest(); + } + + /** + * @return Session + */ + protected function getSession() + { + return $this->getRequest()->getSession(); + } +} diff --git a/local/modules/TheliaSmarty/Template/Plugins/Esi.php b/local/modules/TheliaSmarty/Template/Plugins/Esi.php new file mode 100644 index 00000000..6bee285c --- /dev/null +++ b/local/modules/TheliaSmarty/Template/Plugins/Esi.php @@ -0,0 +1,73 @@ + + */ +class Esi extends AbstractSmartyPlugin +{ + /** @var EsiFragmentRenderer */ + protected $esiFragmentRender; + + /** @var RequestStack */ + protected $requestStack; + + public function __construct(EsiFragmentRenderer $esiFragmentRenderer, RequestStack $requestStack) + { + $this->esiFragmentRender = $esiFragmentRenderer; + $this->requestStack = $requestStack; + } + + public function renderEsi($params, $template = null) + { + $path = $this->getParam($params, 'path'); + $alt = $this->getParam($params, 'alt'); + $ignore_errors = $this->getParam($params, 'ignore_errors'); + $comment = $this->getParam($params, 'comment'); + + if (null === $path) { + return; + } + + $response = $this->esiFragmentRender->render($path, $this->requestStack->getCurrentRequest(), array( + 'alt' => $alt, + 'ignore_errors' => $ignore_errors, + 'comment' => $comment + )); + + if (!$response->isSuccessful()) { + return null; + } + + return $response->getContent(); + } + + /** + * @return array an array of SmartyPluginDescriptor + */ + public function getPluginDescriptors() + { + return array( + new SmartyPluginDescriptor('function', 'render_esi', $this, 'renderEsi') + ); + } +} diff --git a/local/modules/TheliaSmarty/Template/Plugins/FlashMessage.php b/local/modules/TheliaSmarty/Template/Plugins/FlashMessage.php new file mode 100644 index 00000000..7ad9a5a2 --- /dev/null +++ b/local/modules/TheliaSmarty/Template/Plugins/FlashMessage.php @@ -0,0 +1,155 @@ +{$MESSAGE} + * {/flash} + * ``` + * Class Form + * + * @package Thelia\Core\Template\Smarty\Plugins + * @author Guillaume MOREL + * @author Julien Chanséaume + */ +class FlashMessage extends AbstractSmartyPlugin +{ + /** @var RequestStack Request service */ + protected $requestStack; + + /** @var FlashMessageBag $results */ + protected $results; + + /** @var Translator */ + protected $translator; + + public function __construct(RequestStack $requestStack, Translator $translator) + { + $this->requestStack = $requestStack; + $this->translator = $translator; + } + + /** + * Process the count function: executes a loop and return the number of items found + * + * @param array $params parameters array + * @param \Smarty_Internal_Template $template + * + * @return int the item count + * @throws \InvalidArgumentException if a parameter is missing + * + */ + public function hasFlashMessage( + $params, + /** @noinspection PhpUnusedParameterInspection */ + $template + ) { + $type = $this->getParam($params, 'type', null); + + if (null == $type) { + throw new \InvalidArgumentException( + $this->translator->trans("Missing 'type' parameter in {hasflash} function arguments") + ); + } + + return $this->getSession()->getFlashBag()->has($type); + } + + /** + * Get FlashMessage + * And clean session from this key + * + * @param array $params Block parameters + * @param mixed $content Block content + * @param \Smarty_Internal_Template $template Template + * @param bool $repeat Control how many times + * the block is displayed + * + * @return mixed + */ + public function getFlashMessage($params, $content, \Smarty_Internal_Template $template, &$repeat) + { + $type = $this->getParam($params, 'type', false); + + if (null === $content) { + $this->results = new FlashMessageBag(); + + if (false === $type) { + $this->results->addAll($this->getSession()->getFlashBag()->all()); + } else { + $this->results->add( + $type, + $this->getSession()->getFlashBag()->get($type, []) + ); + } + + if ($this->results->isEmpty()) { + $repeat = false; + } + } else { + $this->results->next(); + } + + if ($this->results->valid()) { + $message = $this->results->current(); + $template->assign("TYPE", $message["type"]); + $template->assign("MESSAGE", $message["message"]); + + $repeat = true; + } + + if ($content !== null) { + if ($this->results->isEmpty()) { + $content = ""; + } + + return $content; + } + + return ''; + } + + /** + * @return array an array of SmartyPluginDescriptor + */ + public function getPluginDescriptors() + { + return [ + new SmartyPluginDescriptor("function", "hasflash", $this, "hasFlashMessage"), + new SmartyPluginDescriptor("block", "flash", $this, "getFlashMessage") + ]; + } + + /** + * @return Session + */ + protected function getSession() + { + return $this->requestStack->getCurrentRequest()->getSession(); + } +} diff --git a/local/modules/TheliaSmarty/Template/Plugins/Form.php b/local/modules/TheliaSmarty/Template/Plugins/Form.php new file mode 100644 index 00000000..f8b2756b --- /dev/null +++ b/local/modules/TheliaSmarty/Template/Plugins/Form.php @@ -0,0 +1,1066 @@ + find form named myForm, + * create an instance and assign this instanciation into smarty variable. Form must be declare into + * config using tag + * + * - {form_field form=$form.fieldName} {/form_field} This block find info into the Form field containing by + * the form paramter. This field must be an instance of FormView. fieldName is the name of your field. This block + * can output these info : + * * $name => name of yout input + * * $value => value for your input + * * $label => label for your input + * * $error => boolean for know if there is error for this field + * * $attr => all your attribute for your input (define when you construct programmatically you form) + * + * - {form_error form=$form.fieldName} ... {/form_error} Display this block if there are errors on this field. + * fieldName is the name of your field + * + * Class Form + * @package Thelia\Core\Template\Smarty\Plugins + */ +class Form extends AbstractSmartyPlugin +{ + const COLLECTION_TYPE_NAME = "collection"; + + private static $taggedFieldsStack = null; + private static $taggedFieldsStackPosition = null; + + /** @var ContainerInterface */ + protected $container; + + /** @var ParserContext $parserContext */ + protected $parserContext; + + /** @var ParserInterface $parser */ + protected $parser; + + protected $formDefinition = array(); + + /** @var array|TheliaFormFactoryInterface */ + protected $formFactory = array(); + + /** @var array The form collection stack */ + protected $formCollectionStack = array(); + + /** @var array Counts collection loop in page */ + protected $formCollectionCount = array(); + + public function __construct( + TheliaFormFactoryInterface $formFactory, + ParserContext $parserContext, + ParserInterface $parser + ) { + $this->formFactory = $formFactory; + $this->parserContext = $parserContext; + $this->parser = $parser; + } + + public function setFormDefinition($formDefinition) + { + foreach ($formDefinition as $name => $className) { + if (array_key_exists($name, $this->formDefinition)) { + throw new \InvalidArgumentException( + sprintf("%s form name already exists for %s class", $name, $className) + ); + } + + $this->formDefinition[$name] = $className; + } + } + + public function generateForm($params, $content, \Smarty_Internal_Template $template, &$repeat) + { + if ($repeat) { + $name = $this->getParam($params, 'name'); + $formType = $this->getParam($params, 'type', 'form'); + + if (null == $name) { + $name = "thelia.empty"; + } + + if (!isset($this->formDefinition[$name])) { + throw new ElementNotFoundException(sprintf("%s form does not exists", $name)); + } + + $formClass = $this->formDefinition[$name]; + + // Check if parser context contains our form + $instance = $this->parserContext->getForm($name, $formClass, $formType); + + if (null === $instance) { + // If not, create a new instance + $instance = $this->formFactory->createForm($name); + } + + // Set the current form + $this->parserContext->pushCurrentForm($instance); + + $instance->createView(); + + $template->assign("form", $instance); + $template->assign("form_name", $instance->getName()); + + $template->assign("form_error", $instance->hasError() ? true : false); + $template->assign("form_error_message", $instance->getErrorMessage()); + } else { + $this->parserContext->popCurrentForm(); + + return $content; + } + } + + /** + * @param \Smarty_Internal_Template $template + * @param string $fieldName + * @param string $fieldValue + * @param string $fieldType + * @param array $fieldVars + * @param int $total_value_count + */ + protected function assignFieldValues( + $template, + $fieldName, + $fieldValue, + $fieldType, + $fieldVars, + $total_value_count = 1 + ) { + $template->assign("name", $fieldName); + $template->assign("value", $fieldValue); + $template->assign("data", $fieldVars['data']); + + $template->assign("type", $fieldType); + + $template->assign("checked", isset($fieldVars['data']) ? $fieldVars['data'] : false); + $template->assign("choices", isset($fieldVars['choices']) ? $fieldVars['choices'] : false); + $template->assign("multiple", isset($fieldVars['multiple']) ? $fieldVars['multiple'] : false); + $template->assign("disabled", isset($fieldVars['disabled']) ? $fieldVars['disabled'] : false); + $template->assign("read_only", isset($fieldVars['read_only']) ? $fieldVars['read_only'] : false); + $template->assign("max_length", isset($fieldVars['max_length']) ? $fieldVars['max_length'] : false); + $template->assign('required', isset($fieldVars['required']) ? $fieldVars['required'] : false); + + $template->assign("label", $fieldVars["label"]); + $template->assign("label_attr", $fieldVars["label_attr"]); + + $template->assign('total_value_count', $total_value_count); + + /** @var FormErrorIterator $errors */ + $errors = $fieldVars["errors"]; + if ($errors) { + $template->assign("error", $errors->count() ? true : false); + $this->assignFieldErrorVars($template, $errors); + } + + $attr = array(); + + foreach ($fieldVars["attr"] as $key => $value) { + $attr[] = sprintf('%s="%s"', $key, $value); + } + + $template->assign("attr", implode(" ", $attr)); + $template->assign("attr_list", $fieldVars["attr"]); + } + + /** + * @param \Smarty_Internal_Template $template + * @param FormConfigInterface $formFieldConfig + * @param FormView $formFieldView + */ + protected function assignFormTypeValues($template, $formFieldConfig, $formFieldView) + { + $formFieldType = $formFieldConfig->getType()->getInnerType(); + + /* access to choices */ + if ($formFieldType instanceof ChoiceType) { + $template->assign("choices", $formFieldView->vars['choices']); + } + + /* access to choice collections */ + if ($formFieldType instanceof CollectionType) { + /* access to choices */ + if ($formFieldConfig->getOption('prototype', false) + && + isset($formFieldView->vars['prototype']->vars['choices']) + ) { + /* + * Get list of choices for a collection of 'choice' from this form of declaration : + * ->formBuilder->add( + * 'name', + * 'collection', [ + * 'type' => 'choice', + * 'allow_add' => true, + * 'allow_delete' => true, + * 'options' => [ + * 'choices' => PrixEtPoints::getRubriquesChoices(), + * ] + * ]) + */ + $formFieldView->vars['choices'] = $formFieldView->vars['prototype']->vars['choices']; + } else { + // FIXME : not sure if this case could exists, as "choices" is not a possible option of "collection" + if (isset($formFieldView->vars['choices'])) { + $template->assign("choices", $formFieldView->vars['choices']); + } + } + } + + /* access to date */ + if ($formFieldType instanceof DateType || $formFieldType instanceof DateTimeType || $formFieldType instanceof BirthdayType) { + if ('choice' === $formFieldConfig->getOption('widget')) { + /* access to years */ + if ($formFieldConfig->getOption('years')) { + $formFieldView->vars['years'] = $formFieldConfig->getOption('years'); + $template->assign("years", $formFieldView->vars['years']); + } + + /* access to month */ + if ($formFieldConfig->getOption('months')) { + $formFieldView->vars['months'] = $formFieldConfig->getOption('months'); + $template->assign("months", $formFieldView->vars['months']); + } + + /* access to days */ + if ($formFieldConfig->getOption('days')) { + $formFieldView->vars['days'] = $formFieldConfig->getOption('days'); + $template->assign("days", $formFieldView->vars['days']); + } + + /* access to empty_value */ + if ($formFieldConfig->getOption('empty_value')) { + $formFieldView->vars['empty_value'] = $formFieldConfig->getOption('empty_value'); + $template->assign("empty_value", $formFieldView->vars['empty_value']); + } + } + } + + /* access to thelia type */ + if ($formFieldType instanceof TheliaType) { + $template->assign("formType", $formFieldView->vars['type']); + + switch ($formFieldView->vars['type']) { + case "choice": + if (!isset($formFieldView->vars['options']['choices']) || + !is_array($formFieldView->vars['options']['choices']) + ) { + // throw new FIXME + } + $choices = array(); + foreach ($formFieldView->vars['options']['choices'] as $value => $choice) { + $choices[] = new ChoiceView($value, $value, $choice); + } + $template->assign("choices", $choices); + break; + } + } + } + + /** + * @param array $params + * @param \Smarty_Internal_Template $template + */ + protected function processFormField($params, $template) + { + $formFieldView = $this->getFormFieldView($params); + $formFieldConfig = $this->getFormFieldConfig($params); + + $formFieldType = $formFieldConfig->getType()->getName(); + + $this->assignFormTypeValues($template, $formFieldConfig, $formFieldView); + + $value = $formFieldView->vars["value"]; + + $key = $this->getParam($params, 'value_key', null); + + // We (may) have a collection + if ($key !== null) { + // Force array + if (!is_array($value)) { + $value = array(); + } + + // If the field is not found, use an empty value + $name = sprintf("%s[%s]", $formFieldView->vars["full_name"], $key); + + $val = $value[$key]; + + // For collection types, the type of field is defined in the 'type' option. + // We will use this instead of the 'collection' type + $formFieldType = $formFieldConfig->getType()->getInnerType(); + + if ($formFieldType instanceof CollectionType) { + $formFieldType = $formFieldConfig->getOption('type'); + } + + $this->assignFieldValues( + $template, + $name, + $val, + $formFieldType, + $formFieldView->vars, + count($formFieldView->children) + ); + } else { + $this->assignFieldValues( + $template, + $formFieldView->vars["full_name"], + $formFieldView->vars["value"], + $formFieldType, + $formFieldView->vars + ); + } + + $formFieldView->setRendered(); + } + + public function renderFormField($params, $content, \Smarty_Internal_Template $template, &$repeat) + { + if ($repeat) { + $this->processFormField($params, $template); + } else { + return $content; + } + } + + /** + * @param array $params + * @param string $content + * @param string $templateFile + * @param \Smarty_Internal_Template $template + * @return string + * @throws \TheliaSmarty\Template\Exception\SmartyPluginException + * @throws \Exception + * @throws \SmartyException + */ + protected function automaticFormFieldRendering($params, $content, $template, $templateFile) + { + $data = ''; + + $templateStyle = $this->getParam($params, 'template', 'standard'); + + $snippet_content = file_get_contents( + $this->parser->getTemplateDefinition()->getTemplateFilePath( + 'forms' . DS . $templateStyle . DS . $templateFile . ".html" + ) + ); + + $this->processFormField($params, $template); + + if (null === $form = $this->getParam($params, 'form', null)) { + $form = $this->parserContext->getCurrentForm(); + } + + $field_name = $this->getParam($params, 'field', false); + $field_id = $this->getParam($params, 'field_id', false); + $field_extra_class = $this->getParam($params, 'extra_class', ''); + $field_extra_class = $this->getParam($params, 'extra_classes', $field_extra_class); + $field_no_standard_classes = $this->getParam($params, 'no_standard_classes', false); + $field_value = $this->getParam($params, 'value', ''); + $show_label = $this->getParam($params, 'show_label', true); + $value_key = $this->getParam($params, 'value_key', false); + + $template->assign([ + 'content' => trim($content), + 'form' => $form, + 'field_name' => $field_name, + 'field_id' => $field_id, + 'field_extra_class' => $field_extra_class, + 'field_no_standard_classes' => $field_no_standard_classes, + 'field_value' => $field_value, + 'field_template' => $templateStyle, + 'value_key' => $value_key, + 'show_label' => $show_label, + ]); + + return $template->fetch(sprintf('string:%s', $snippet_content)); + } + + /** + * @param $params + * @param $content + * @param \Smarty_Internal_Template $template + * @param $repeat + * @return string + * @throws \Exception + * @throws \SmartyException + * @throws \TheliaSmarty\Template\Exception\SmartyPluginException + */ + public function customFormFieldRendering($params, $content, $template, &$repeat) + { + if (!$repeat) { + return $this->automaticFormFieldRendering($params, $content, $template, 'form-field-renderer'); + } + } + + /** + * @param $params + * @param \Smarty_Internal_Template $template + * @return string + * @throws \Exception + * @throws \SmartyException + * @throws \TheliaSmarty\Template\Exception\SmartyPluginException + */ + public function standardFormFieldRendering($params, \Smarty_Internal_Template $template) + { + return $this->automaticFormFieldRendering($params, '', $template, 'form-field-renderer'); + } + + /** + * @param $params + * @param \Smarty_Internal_Template $template + * @return string + * @throws \Exception + * @throws \SmartyException + * @throws \TheliaSmarty\Template\Exception\SmartyPluginException + */ + public function standardFormFieldAttributes($params, \Smarty_Internal_Template $template) + { + return $this->automaticFormFieldRendering($params, '', $template, 'form-field-attributes-renderer'); + } + + public function renderTaggedFormFields($params, $content, \Smarty_Internal_Template $template, &$repeat) + { + if (null === $content) { + self::$taggedFieldsStack = $this->getFormFieldsFromTag($params); + self::$taggedFieldsStackPosition = 0; + } else { + self::$taggedFieldsStackPosition++; + } + + if (isset(self::$taggedFieldsStack[self::$taggedFieldsStackPosition])) { + $field = self::$taggedFieldsStack[self::$taggedFieldsStackPosition]; + + $this->assignFieldValues( + $template, + $field['view']->vars["full_name"], + $field['view']->vars["value"], + $field['config']->getType()->getName(), + $field['view']->vars + ); + + $this->assignFormTypeValues($template, $field['config'], $field['view']); + + $field['view']->setRendered(); + + $repeat = true; + } + + if (!$repeat) { + self::$taggedFieldsStack = null; + self::$taggedFieldsStackPosition = null; + } + + if (null !== $content) { + return $content; + } + } + + public function renderHiddenFormField($params, \Smarty_Internal_Template $template) + { + $attrFormat = '%s="%s"'; + $field = ''; + + $baseFormInstance = $this->getInstanceFromParams($params); + + $formView = $baseFormInstance->getView(); + + $return = ""; + + $exclude = explode(',', $this->getParam($params, 'exclude', '')); + + /** @var FormView $row */ + foreach ($formView->getIterator() as $row) { + // We have to exclude the fields for which value is defined in the template. + if ($baseFormInstance->isTemplateDefinedHiddenField($row) + || + in_array($row->vars['name'], $exclude) + ) { + continue; + } + + if ($this->isHidden($row) && $row->isRendered() === false) { + $attributeList = array(); + if (isset($row->vars["attr"])) { + foreach ($row->vars["attr"] as $attrKey => $attrValue) { + $attributeList[] = sprintf($attrFormat, $attrKey, $attrValue); + } + } + $return .= sprintf($field, $row->vars["full_name"], $row->vars["value"], implode(' ', $attributeList)); + } + } + + return $return; + } + + public function formEnctype($params, \Smarty_Internal_Template $template) + { + $instance = $this->getInstanceFromParams($params); + + $formView = $instance->getView(); + + if ($formView->vars["multipart"]) { + return sprintf('%s="%s"', "enctype", "multipart/form-data"); + } + } + + public function formError($params, $content, \Smarty_Internal_Template $template, &$repeat) + { + $formFieldView = $this->getFormFieldView($params); + + /** @var FormErrorIterator $errors */ + $errors = $formFieldView->vars["errors"]; + + if (!$errors->count()) { + return ""; + } + + if ($repeat) { + $this->assignFieldErrorVars($template, $errors); + } else { + return $content; + } + } + + protected function assignFieldErrorVars(\Smarty_Internal_Template $template, FormErrorIterator $errors) + { + if ($errors->count()) { + $template->assign("message", $errors[0]->getMessage()); + $template->assign("parameters", $errors[0]->getMessageParameters()); + $template->assign("pluralization", $errors[0]->getMessagePluralization()); + } + } + + protected function isHidden(FormView $formView) + { + return array_search("hidden", $formView->vars["block_prefixes"]); + } + + /** + * @param $params + * @return FormView + * @throws \InvalidArgumentException + */ + protected function getFormFieldView($params) + { + $instance = $this->getInstanceFromParams($params); + + $fieldName = $this->getParam($params, 'field'); + + if (null == $fieldName) { + throw new \InvalidArgumentException("'field' parameter is missing"); + } + + $view = $this->retrieveField( + $fieldName, + $instance->getView(), + $instance->getName() + ); + + return $view; + } + + protected function getFormFieldsFromTag($params) + { + $instance = $this->getInstanceFromParams($params); + + $tag = $this->getParam($params, 'tag'); + + if (null == $tag) { + throw new \InvalidArgumentException("'tag' parameter is missing"); + } + + $viewList = array(); + foreach ($instance->getView() as $view) { + if (isset($view->vars['attr']['tag']) && $tag == $view->vars['attr']['tag']) { + $fieldData = $instance->getForm()->all()[$view->vars['name']]; + $viewList[] = array( + 'view' => $view, + 'config' => $fieldData->getConfig(), + ); + } + } + + return $viewList; + } + + /** + * @param $params + * @return FormConfigInterface + * @throws \InvalidArgumentException + */ + protected function getFormFieldConfig($params) + { + $instance = $this->getInstanceFromParams($params); + + $fieldName = $this->getParam($params, 'field'); + + if (null == $fieldName) { + throw new \InvalidArgumentException("'field' parameter is missing"); + } + + $fieldData = $this->retrieveField( + $fieldName, + $instance->getForm()->all(), + $instance->getName() + ); + + if (empty($fieldData)) { + throw new \InvalidArgumentException( + sprintf( + "Field name '%s' not found in form %s children", + $fieldName, + $instance->getName() + ) + ); + } + + return $fieldData->getConfig(); + } + + /** + * @param $params + * @return BaseForm + * @throws \InvalidArgumentException + */ + protected function getInstanceFromParams($params) + { + if (null === $instance = $this->getParam($params, 'form')) { + $instance = $this->parserContext->getCurrentForm(); + } + + if (null == $instance) { + throw new \InvalidArgumentException( + "Missing 'form' parameter in form arguments, and no current form was found." + ); + } + + if (!$instance instanceof BaseForm) { + throw new \InvalidArgumentException( + sprintf( + "form parameter in form_field block must be an instance of " . + "\Thelia\Form\BaseForm, instance of %s found", + get_class($instance) + ) + ); + } + + return $instance; + } + + /** + * @param $needle + * @param $haystack + * @param $formName + * @return \Symfony\Component\Form\Form + */ + protected function retrieveField($needle, $haystack, $formName) + { + $splitName = explode(".", $needle); + + foreach ($splitName as $level) { + if (empty($haystack[$level])) { + throw new \InvalidArgumentException( + sprintf("Field name '%s' not found in form %s", $needle, $formName) + ); + } + $haystack = $haystack[$level]; + } + + return $haystack; + } + + /** + * @param $params + * @param $name + * @param bool $throwException + * @return mixed|null + * + * Get a symfony form object form a function/block parameter + */ + protected function getSymfonyFormFromParams($params, $name, $throwException = false) + { + $sfForm = $this->getParam($params, $name); + + if (null === $sfForm && false === $throwException) { + return null; + } + + if (!$sfForm instanceof SymfonyForm) { + throw new \InvalidArgumentException( + sprintf( + "%s parameter must be an instance of " . + "\Symfony\Component\Form\Form, instance of %s found", + $name, + is_object($sfForm) ? get_class($sfForm) : gettype($sfForm) + ) + ); + } + + return $sfForm; + } + + /** + * @param $params + * @param $content + * @param \Smarty_Internal_Template $template + * @param $repeat + * @return mixed + * + * Loops around a form collection entries and assigns values to template + */ + public function renderFormCollection($params, $content, \Smarty_Internal_Template $template, &$repeat) + { + /** + * Get parameters + */ + $form = $this->getInstanceFromParams($params); + $row = $this->getSymfonyFormFromParams($params, "row"); + $collection = $this->resolveCollection($this->getParam($params, "collection"), $form); + + $hash = $this->initializeCollection($form, $collection, $row); + + $limit = $this->getParam($params, "limit", -1); + + /** + * Check if it has a limit + */ + if (!preg_match("#^\-?\d+$#", $limit)) { + throw new \InvalidArgumentException( + sprintf( + "Invalid value for 'limit' parameter in 'form_collection'. '%s' given, integer expected", + $limit + ) + ); + } + + /** + * Then load stack and create the stack count + */ + $limit = (int)$limit; + $hasLimit = $limit >= 0; + + /** + * If we have reached the limit, stop + */ + $collectionLimit = $this->formCollectionCount[$hash]["limit"]; + + if (($hasLimit && $limit === $collectionLimit) || + null === $row = array_shift($this->formCollectionStack[$hash]) + ) { + $repeat = false; + + /** + * Reload stack limit + */ + $this->formCollectionCount[$hash]["limit"] = 0; + + return $content; + } + + /** + * Assign variables into the template + */ + $template->assign("row", $row); + $template->assign("collection_current", $this->formCollectionCount[$hash]["count"]++); + $template->assign("collection_count", $this->formCollectionCount[$hash]["total_count"]); + + /** + * Increment the current limit state + * Force the repeat + */ + $this->formCollectionCount[$hash]["limit"]++; + $repeat = true; + + /** + * ANd return the content + */ + + return $content; + } + + /** + * @param BaseForm $form + * @param SymfonyForm $field + * @return string + * + * Get definition, return hash + */ + protected function getFormStackHash(BaseForm $form, SymfonyForm $field = null) + { + $build = get_class($form) . ":" . $form->getType(); + + if (null !== $field) { + $build .= ":" . $this->buildFieldName($field); + } + + return md5($build); + } + + /** + * @param $collection + * @param BaseForm $form + * @return SymfonyForm + * + * Extract the collection object from the form + */ + protected function resolveCollection($collection, BaseForm $form) + { + if (null === $collection) { + throw new \InvalidArgumentException( + "Missing parameter 'collection' in 'form_collection" + ); + } + + $sfForm = $form->getForm(); + + if (!$sfForm->has($collection)) { + throw new \InvalidArgumentException( + sprintf( + "Field name '%s' not found in form %s children", + $collection, + $form->getName() + ) + ); + } + + /** + * Check that the field is a "collection" type + */ + $collectionConfig = $this->retrieveField( + $collection, + $sfForm->all(), + $form->getName() + ); + + $fieldType = $collectionConfig->getConfig()->getType(); + + if ($fieldType->getName() !== static::COLLECTION_TYPE_NAME) { + $baseFieldType = $fieldType; + $resolved = false; + + while (null !== $fieldType && !$resolved) { + if ($fieldType->getName() !== static::COLLECTION_TYPE_NAME) { + $fieldType = $fieldType->getParent(); + } + } + + if (!$resolved) { + throw new \LogicException( + sprintf( + "The field '%s' is not a collection, it's a '%s'." . + "You can't use it with the function 'form_collection' in form '%s'", + $collection, + $baseFieldType->getName(), + $form->getName() + ) + ); + } + } + + return $collectionConfig; + } + + /** + * @param $params + * @param $content + * @param \Smarty_Internal_Template $template + * @param $repeat + * @return string + * + * Injects a collection field variables into the parser + */ + public function renderFormCollectionField($params, $content, \Smarty_Internal_Template $template, &$repeat) + { + if (!$repeat) { + return $content; + } + + $form = $this->getInstanceFromParams($params); + /** @var \Symfony\Component\Form\Form $row */ + $row = $this->getSymfonyFormFromParams($params, "row", true); + $field = $this->getParam($params, "field"); + + $formField = $this->retrieveField($field, $row->all(), $form->getName()); + + $formFieldConfig = $formField->getConfig(); + + $this->assignFieldValues( + $template, + $this->buildFieldName($formField), + $formField->getViewData(), + $formFieldConfig->getType(), + $this->findCollectionFieldFormView($form->getView(), $formField) + ); + + return ''; + } + + /** + * @param FormView $formView + * @param SymfonyForm $formField + * @return array + */ + protected function findCollectionFieldFormView(FormView $formView, SymfonyForm $formField) + { + $formFieldParentList = []; + + do { + // don't need to set first form name child + if (null === $formField->getParent()) { + break; + } + + $formFieldParentList[] = $formField->getConfig()->getName(); + + } while (null !== $formField = $formField->getParent()); + + $formFieldParentList = array_reverse($formFieldParentList); + + foreach ($formFieldParentList as $val) { + $formView = $formView->children[$val]; + } + + return $formView->vars; + } + + /** + * @param FormInterface $form + * @param array $tree + * @return string + * + * Tail recursive method that builds the field full name + */ + protected function buildFieldName(FormInterface $form, array &$tree = array()) + { + $config = $form->getConfig(); + $parent = $form->getParent(); + $hasParent = null !== $parent; + + if (null !== $proprietyPath = $config->getPropertyPath()) { + $name = (string)$proprietyPath; + } else { + $name = $config->getName(); + + if ($name === null) { + $name = ''; + } elseif ($name !== '' && $hasParent) { + $name = "[$name]"; + } + } + + array_unshift($tree, $name); + + if (!$hasParent) { + return implode("", $tree); + } + + return $this->buildFieldName($parent, $tree); + } + + /** + * @param $params + * @param \Smarty_Internal_Template $template + * @return mixed + * + * Counts collection entries + */ + public function formCollectionCount($params, \Smarty_Internal_Template $template) + { + /** + * Get parameters + */ + $form = $this->getInstanceFromParams($params); + $row = $this->getSymfonyFormFromParams($params, "row"); + $collection = $this->resolveCollection($this->getParam($params, "collection"), $form); + + $hash = $this->initializeCollection($form, $collection, $row); + + return $this->formCollectionCount[$hash]["total_count"]; + } + + /** + * @param BaseForm $form + * @param SymfonyForm $collection + * @param SymfonyForm $row + * @return string + * + * Initialize a collection into this class ( values stack, counting table ) + */ + protected function initializeCollection(BaseForm $form, SymfonyForm $collection, SymfonyForm $row = null) + { + $hash = $this->getFormStackHash($form, $collection); + + if (!isset($this->formCollectionStack[$hash])) { + $this->formCollectionStack[$hash] = $collection->all(); + } + + if (!isset($this->formCollectionCount[$hash])) { + $this->formCollectionCount[$hash] = [ + "count" => 0, + "limit" => 0, + "total_count" => count($this->formCollectionStack[$hash]), + ]; + } + + return $hash; + } + + /** + * @return array an array of SmartyPluginDescriptor + */ + public function getPluginDescriptors() + { + return array( + new SmartyPluginDescriptor("block", "form", $this, "generateForm"), + new SmartyPluginDescriptor("block", "form_field", $this, "renderFormField"), + new SmartyPluginDescriptor("block", "form_tagged_fields", $this, "renderTaggedFormFields"), + new SmartyPluginDescriptor("function", "form_hidden_fields", $this, "renderHiddenFormField"), + new SmartyPluginDescriptor("function", "form_enctype", $this, "formEnctype"), + new SmartyPluginDescriptor("block", "form_error", $this, "formError"), + new SmartyPluginDescriptor("function", "form_field_attributes", $this, "standardFormFieldAttributes"), + new SmartyPluginDescriptor("function", "render_form_field", $this, "standardFormFieldRendering"), + new SmartyPluginDescriptor("block", "custom_render_form_field", $this, "customFormFieldRendering"), + new SmartyPluginDescriptor("block", "form_collection", $this, "renderFormCollection"), + new SmartyPluginDescriptor("block", "form_collection_field", $this, "renderFormCollectionField"), + new SmartyPluginDescriptor("function", "form_collection_count", $this, "formCollectionCount"), + ); + } +} diff --git a/local/modules/TheliaSmarty/Template/Plugins/Format.php b/local/modules/TheliaSmarty/Template/Plugins/Format.php new file mode 100644 index 00000000..ab390193 --- /dev/null +++ b/local/modules/TheliaSmarty/Template/Plugins/Format.php @@ -0,0 +1,500 @@ + + * @author Benjamin Perche + */ +class Format extends AbstractSmartyPlugin +{ + private static $dateKeys = ["day", "month", "year"]; + private static $timeKeys = ["hour", "minute", "second"]; + + /** @var RequestStack */ + protected $requestStack; + + public function __construct(RequestStack $requestStack) + { + $this->requestStack = $requestStack; + } + + /** + * return date in expected format + * + * available parameters : + * date => DateTime object (mandatory) + * format => expected format + * output => list of default system format. Values available : + * date => date format + * time => time format + * datetime => datetime format (default) + * + * ex : + * {format_date date=$dateTimeObject format="Y-m-d H:i:s"} will output the format with specific format + * {format_date date=$dateTimeObject format="l F j" locale="fr_FR"} will output the format with specific format (see date() function) + * {format_date date=$dateTimeObject output="date"} will output the date using the default date system format + * {format_date date=$dateTimeObject} will output with the default datetime system format + * + * @param array $params + * @param null $template + * @throws \TheliaSmarty\Template\Exception\SmartyPluginException + * @return string + */ + public function formatDate($params, $template = null) + { + $date = $this->getParam($params, "date", false); + + if ($date === false) { + // Check if we have a timestamp + $timestamp = $this->getParam($params, "timestamp", false); + + if ($timestamp === false) { + // No timestamp => error + throw new SmartyPluginException("Either date or timestamp is a mandatory parameter in format_date function"); + } else { + $date = new \DateTime(); + $date->setTimestamp($timestamp); + } + } elseif (is_array($date)) { + $keys = array_keys($date); + + $isDate = $this->arrayContains(static::$dateKeys, $keys); + $isTime = $this->arrayContains(static::$timeKeys, $keys); + + // If this is not a date, fallback on today + // If this is not a time, fallback on midnight + $dateFormat = $isDate ? sprintf("%d-%d-%d", $date["year"], $date["month"], $date["day"]) : (new \DateTime())->format("Y-m-d"); + $timeFormat = $isTime ? sprintf("%d:%d:%d", $date["hour"], $date["minute"], $date["second"]) : "0:0:0"; + + $date = new \DateTime(sprintf("%s %s", $dateFormat, $timeFormat)); + } + + if (!($date instanceof \DateTime)) { + try { + $date = new \DateTime($date); + } catch (\Exception $e) { + return ""; + } + } + + $format = $this->getParam($params, "format", false); + + if ($format === false) { + $format = DateTimeFormat::getInstance($this->requestStack->getCurrentRequest())->getFormat($this->getParam($params, "output", null)); + } + + $locale = $this->getParam($params, 'locale', false); + + if (false === $locale) { + $value = $date->format($format); + } else { + $value = $this->formatDateWithLocale($date, $locale, $format); + } + + return $value; + } + + private function formatDateWithLocale(\DateTime $date, $locale, $format) + { + if (false === strpos($format, '%')) { + $formatter = new IntlDateFormatter($locale, IntlDateFormatter::FULL, IntlDateFormatter::FULL); + + $icuFormat = $this->convertDatePhpToIcu($format); + $formatter->setPattern($icuFormat); + + $localizedDate = $formatter->format($date); + } else { + // for backward compatibility + if (function_exists('setlocale')) { + // Save the current locale + $systemLocale = setlocale(LC_TIME, 0); + setlocale(LC_TIME, $locale); + $localizedDate = strftime($format, $date->getTimestamp()); + // Restore the locale + setlocale(LC_TIME, $systemLocale); + } else { + // setlocale() function not available => error + throw new SmartyPluginException("The setlocale() function is not available on your system."); + } + } + + return $localizedDate; + } + + /** + * + * display numbers in expected format + * + * available parameters : + * number => int or float number + * decimals => how many decimals format expected + * dec_point => separator for the decimal point + * thousands_sep => thousands separator + * + * ex : {format_number number="1246.12" decimals="1" dec_point="," thousands_sep=" "} will output "1 246,1" + * + * @param $params + * @param null $template + * @throws \TheliaSmarty\Template\Exception\SmartyPluginException + * @return string the expected number formatted + */ + public function formatNumber($params, $template = null) + { + $number = $this->getParam($params, "number", false); + + if ($number === false || $number === '') { + return ""; + } + + return NumberFormat::getInstance($this->requestStack->getCurrentRequest())->format( + $number, + $this->getParam($params, "decimals", null), + $this->getParam($params, "dec_point", null), + $this->getParam($params, "thousands_sep", null) + ); + } + + /** + * + * display a amount in expected format + * + * available parameters : + * number => int or float number + * decimals => how many decimals format expected + * dec_point => separator for the decimal point + * thousands_sep => thousands separator + * symbol => Currency symbol + * remove_zero_decimal => remove zero after the dec_point + * + * ex : {format_money number="1246.12" decimals="1" dec_point="," thousands_sep=" " symbol="€"} will output "1 246,1 €" + * ex : {format_money number="1246.00" decimals="2" dec_point="," thousands_sep=" " symbol="€" remove_zero_decimal=true} will output "1 246 €" + * + * @param $params + * @param null $template + * @throws \TheliaSmarty\Template\Exception\SmartyPluginException + * @return string the expected number formatted + */ + public function formatMoney($params, $template = null) + { + $number = $this->getParam($params, "number", false); + + if ($number === false || $number === '') { + return ""; + } + + if ($this->getParam($params, "symbol", null) === null) { + return MoneyFormat::getInstance($this->requestStack->getCurrentRequest())->formatByCurrency( + $number, + $this->getParam($params, "decimals", null), + $this->getParam($params, "dec_point", null), + $this->getParam($params, "thousands_sep", null), + $this->getParam($params, "currency_id", null), + $this->getParam($params, "remove_zero_decimal", false) + ); + } + + return MoneyFormat::getInstance($this->requestStack->getCurrentRequest())->format( + $number, + $this->getParam($params, "decimals", null), + $this->getParam($params, "dec_point", null), + $this->getParam($params, "thousands_sep", null), + $this->getParam($params, "symbol", null), + $this->getParam($params, "remove_zero_decimal", false) + ); + } + + + /** + * return two-dimensional arrays in string + * + * available parameters : + * values => array 2D ['key A' => ['value 1', 'value 2'], 'key B' => ['value 3', 'value 4']] + * separators => ['key value separator', 'value value separator', 'key key separator'] + * + * ex : + * {format_array_2d values=['Colors' => ['Green', 'Yellow', 'Red'], 'Material' => ['Wood']] separators=[' : ', ' / ', ' | ']} + * will output the format with specific format : "Colors : Green / Yellow / Red | Material : Wood" + * + * @param $params + * @return string + */ + public function formatTwoDimensionalArray($params) + { + $output = ''; + $values = $this->getParam($params, "values", null); + $separators = $this->getParam($params, "separators", [' : ', ' / ', ' | ']); + + if (!is_array($values)) { + return $output; + } + + foreach ($values as $key => $value) { + if ($output !== '') { + $output .= $separators[2]; + } + + $output .= $key . $separators[0]; + + if (!is_array($value)) { + $output .= $value; + continue; + } + + $output .= implode($separators[1], $value); + } + return $output; + } + + protected function arrayContains(array $expected, array $hayStack) + { + foreach ($expected as $value) { + if (!in_array($value, $hayStack)) { + return false; + } + } + + return true; + } + + /** + * This function comes from [Yii framework](http://www.yiiframework.com/) + * + * + * Converts a date format pattern from [php date() function format][] to [ICU format][]. + * + * The conversion is limited to date patterns that do not use escaped characters. + * Patterns like `jS \o\f F Y` which will result in a date like `1st of December 2014` may not be converted correctly + * because of the use of escaped characters. + * + * Pattern constructs that are not supported by the ICU format will be removed. + * + * [php date() function format]: http://php.net/manual/en/function.date.php + * [ICU format]: http://userguide.icu-project.org/formatparse/datetime#TOC-Date-Time-Format-Syntax + * + * @param string $pattern date format pattern in php date()-function format. + * @return string The converted date format pattern. + */ + protected function convertDatePhpToIcu($pattern) + { + // http://php.net/manual/en/function.date.php + return strtr( + $pattern, + [ + // Day + 'd' => 'dd', // Day of the month, 2 digits with leading zeros 01 to 31 + 'D' => 'eee', // A textual representation of a day, three letters Mon through Sun + 'j' => 'd', // Day of the month without leading zeros 1 to 31 + 'l' => 'eeee', // A full textual representation of the day of the week Sunday through Saturday + 'N' => 'e', // ISO-8601 numeric representation of the day of the week, 1 (for Monday) through 7 (for Sunday) + 'S' => '', // English ordinal suffix for the day of the month, 2 characters st, nd, rd or th. Works well with j + 'w' => '', // Numeric representation of the day of the week 0 (for Sunday) through 6 (for Saturday) + 'z' => 'D', // The day of the year (starting from 0) 0 through 365 + // Week + 'W' => 'w', // ISO-8601 week number of year, weeks starting on Monday (added in PHP 4.1.0) Example: 42 (the 42nd week in the year) + // Month + 'F' => 'MMMM', // A full textual representation of a month, January through December + 'm' => 'MM', // Numeric representation of a month, with leading zeros 01 through 12 + 'M' => 'MMM', // A short textual representation of a month, three letters Jan through Dec + 'n' => 'M', // Numeric representation of a month, without leading zeros 1 through 12, not supported by ICU but we fallback to "with leading zero" + 't' => '', // Number of days in the given month 28 through 31 + // Year + 'L' => '', // Whether it's a leap year, 1 if it is a leap year, 0 otherwise. + 'o' => 'Y', // ISO-8601 year number. This has the same value as Y, except that if the ISO week number (W) belongs to the previous or next year, that year is used instead. + 'Y' => 'yyyy', // A full numeric representation of a year, 4 digits Examples: 1999 or 2003 + 'y' => 'yy', // A two digit representation of a year Examples: 99 or 03 + // Time + 'a' => 'a', // Lowercase Ante meridiem and Post meridiem, am or pm + 'A' => 'a', // Uppercase Ante meridiem and Post meridiem, AM or PM, not supported by ICU but we fallback to lowercase + 'B' => '', // Swatch Internet time 000 through 999 + 'g' => 'h', // 12-hour format of an hour without leading zeros 1 through 12 + 'G' => 'H', // 24-hour format of an hour without leading zeros 0 to 23h + 'h' => 'hh', // 12-hour format of an hour with leading zeros, 01 to 12 h + 'H' => 'HH', // 24-hour format of an hour with leading zeros, 00 to 23 h + 'i' => 'mm', // Minutes with leading zeros 00 to 59 + 's' => 'ss', // Seconds, with leading zeros 00 through 59 + 'u' => '', // Microseconds. Example: 654321 + // Timezone + 'e' => 'VV', // Timezone identifier. Examples: UTC, GMT, Atlantic/Azores + 'I' => '', // Whether or not the date is in daylight saving time, 1 if Daylight Saving Time, 0 otherwise. + 'O' => 'xx', // Difference to Greenwich time (GMT) in hours, Example: +0200 + 'P' => 'xxx', // Difference to Greenwich time (GMT) with colon between hours and minutes, Example: +02:00 + 'T' => 'zzz', // Timezone abbreviation, Examples: EST, MDT ... + 'Z' => '', // Timezone offset in seconds. The offset for timezones west of UTC is always negative, and for those east of UTC is always positive. -43200 through 50400 + // Full Date/Time + 'c' => 'yyyy-MM-dd\'T\'HH:mm:ssxxx', // ISO 8601 date, e.g. 2004-02-12T15:19:21+00:00 + 'r' => 'eee, dd MMM yyyy HH:mm:ss xx', // RFC 2822 formatted date, Example: Thu, 21 Dec 2000 16:01:07 +0200 + 'U' => '', // Seconds since the Unix Epoch (January 1 1970 00:00:00 GMT) + ] + ); + } + + /** + * + * display an address in expected format + * + * available parameters : + * address => the id of the address to display + * order_address => the id of the order address to display + * from_country_id => the country id + * dec_point => separator for the decimal point + * thousands_sep => thousands separator + * symbol => Currency symbol + * + * ex : {format_money number="1246.12" decimals="1" dec_point="," thousands_sep=" " symbol="€"} will output "1 246,1 €" + * + * @param $params + * @param null $template + * @throws \TheliaSmarty\Template\Exception\SmartyPluginException + * @return string the expected number formatted + */ + public function formatAddress($params, $template = null) + { + $postal = filter_var( + $this->getParam($params, "postal", null), + FILTER_VALIDATE_BOOLEAN + ); + + $html = filter_var( + $this->getParam($params, "html", true), + FILTER_VALIDATE_BOOLEAN + ); + + $htmlTag = $this->getParam($params, "html_tag", "p"); + $originCountry = $this->getParam($params, "origin_country", null); + $locale = $this->getParam($params, "locale", $this->getSession()->getLang()->getLocale()); + + // extract html attributes + $htmlAttributes = []; + foreach ($params as $k => $v) { + if (strpos($k, 'html_') !== false && $k !== 'html_tag') { + $htmlAttributes[substr($k, 5)] = $v; + } + } + + // get address or order address + $address = null; + if (null !== $id = $this->getParam($params, "address", null)) { + if (null === $address = AddressQuery::create()->findPk($id)) { + return ''; + } + } elseif (null !== $id = $this->getParam($params, "order_address", null)) { + if (null === $address = OrderAddressQuery::create()->findPk($id)) { + return ''; + } + } else { + // try to parse arguments to build address + $address = $this->getAddressFormParams($params); + } + + if (null === $address) { + throw new SmartyPluginException( + "Either address, order_address or full list of address fields should be provided" + ); + } + + $addressFormat = AddressFormat::getInstance(); + if ($postal) { + if ($address instanceof Address) { + $formattedAddress = $addressFormat->postalLabelFormat($address, $locale, $originCountry); + } else { + $formattedAddress = $addressFormat->postalLabelFormatTheliaAddress($address, $locale, $originCountry); + } + } else { + if ($address instanceof Address) { + $formattedAddress = $addressFormat->format($address, $locale, $html, $htmlTag, $htmlAttributes); + } else { + $formattedAddress = $addressFormat->formatTheliaAddress($address, $locale, $html, $htmlTag, $htmlAttributes); + } + } + + return $formattedAddress; + } + + protected function getAddressFormParams($params) + { + // Check if there is arguments + $addressArgs = [ + 'country_code', + 'administrative_area', + 'locality', + 'dependent_locality', + 'postal_code', + 'sorting_code', + 'address_line1', + 'address_line2', + 'organization', + 'recipient', + 'locale' + ]; + $valid = false; + + $address = new Address(); + + foreach ($addressArgs as $arg) { + if (null !== $argVal = $this->getParam($params, $arg, null)) { + $valid = true; + $functionName = 'with' . Container::camelize($arg); + $address = $address->$functionName($argVal); + } + } + + if (false === $valid) { + return null; + } + + return $address; + } + + /** + * @return SmartyPluginDescriptor[] + */ + public function getPluginDescriptors() + { + return array( + new SmartyPluginDescriptor("function", "format_date", $this, "formatDate"), + new SmartyPluginDescriptor("function", "format_number", $this, "formatNumber"), + new SmartyPluginDescriptor("function", "format_money", $this, "formatMoney"), + new SmartyPluginDescriptor("function", "format_array_2d", $this, "formatTwoDimensionalArray"), + new SmartyPluginDescriptor("function", "format_address", $this, "formatAddress"), + ); + } + + /** + * @return Session + */ + protected function getSession() + { + return $this->requestStack->getCurrentRequest()->getSession(); + } +} diff --git a/local/modules/TheliaSmarty/Template/Plugins/Hook.php b/local/modules/TheliaSmarty/Template/Plugins/Hook.php new file mode 100644 index 00000000..b8719532 --- /dev/null +++ b/local/modules/TheliaSmarty/Template/Plugins/Hook.php @@ -0,0 +1,491 @@ + + */ +class Hook extends AbstractSmartyPlugin +{ + private $dispatcher; + + /** @var Translator */ + protected $translator; + + /** @var Module */ + protected $smartyPluginModule = null; + + /** @var array */ + protected $hookResults = array(); + + /** @var array */ + protected $varstack = array(); + + /** @var bool debug */ + protected $debug = false; + + public function __construct($debug, ContainerAwareEventDispatcher $dispatcher) + { + $this->debug = $debug; + $this->dispatcher = $dispatcher; + $this->translator = $dispatcher->getContainer()->get("thelia.translator"); + $this->hookResults = array(); + } + + /** + * Generates the content of the hook + * + * {hook name="hook_code" var1="value1" var2="value2" ... } + * + * This function create an event, feed it with the custom variables passed to the function (var1, var2, ...) and + * dispatch it to the hooks that respond to it. + * + * The name of the event is `hook.{context}.{hook_code}` where : + * * context : the id of the context of the smarty render : 1: frontoffice, 2: backoffice, 3: email, 4: pdf + * * hook_code : the code of the hook + * + * The event collects all the fragments of text rendered in each modules functions that listen to this event. + * Finally, this fragments are concatenated and injected in the template + * + * @param array $params the params passed in the smarty function + * @param \TheliaSmarty\Template\SmartyParser $smarty the smarty parser + * + * @return string the contents generated by modules + */ + public function processHookFunction($params, &$smarty) + { + $hookName = $this->getParam($params, 'name'); + $module = intval($this->getParam($params, 'module', 0)); + $moduleCode = $this->getParam($params, 'modulecode', ""); + + $type = $smarty->getTemplateDefinition()->getType(); + + $event = new HookRenderEvent($hookName, $params, $smarty->getTemplateVars()); + + $event->setArguments($this->getArgumentsFromParams($params)); + + $eventName = sprintf('hook.%s.%s', $type, $hookName); + + // this is a hook specific to a module + if (0 === $module && "" !== $moduleCode) { + if (null !== $mod = ModuleQuery::create()->findOneByCode($moduleCode)) { + $module = $mod->getId(); + } + } + if (0 !== $module) { + $eventName .= '.' . $module; + } + + $this->getDispatcher()->dispatch($eventName, $event); + + $content = trim($event->dump()); + + if ($this->debug && $smarty->getRequest()->get('SHOW_HOOK')) { + $content = self::showHook( + $hookName, + $params, + $smarty->getTemplateVars() + ) . $content; + } + + $this->hookResults[$hookName] = $content; + + // support for compatibility with module_include + if ($type === TemplateDefinition::BACK_OFFICE) { + $content .= $this->moduleIncludeCompat($params, $smarty); + } + + return $content; + } + + /** + * Call the plugin function module_include for backward compatibility. + * + * @param array $params the params passed in the smarty function + * @param \TheliaSmarty\Template\SmartyParser $smarty the smarty parser + * + * @return string the contents generated by module_include function + */ + protected function moduleIncludeCompat($params, &$smarty) + { + $plugin = $this->getSmartyPluginModule(); + $params = array( + "location" => $this->getParam($params, 'location', null), + "module" => $this->getParam($params, 'modulecode', null), + "countvar" => $this->getParam($params, 'countvar', null) + ); + + return $plugin->theliaModule($params, $smarty); + } + + /** + * get the smarty plugin Module + * + * @return Module the smarty plugin Module + */ + protected function getSmartyPluginModule() + { + if (null === $this->smartyPluginModule) { + $this->smartyPluginModule = $this->dispatcher->getContainer()->get("smarty.plugin.module"); + } + + return $this->smartyPluginModule; + } + + protected function showHook($hookName, $params, $templateVars) + { + if (!\class_exists('\Symfony\Component\VarDumper\VarDumper')) { + throw new \Exception('For use SHOW_HOOK, you can install dependency symfony/var-dumper'); + } + + ob_start(); + + \Symfony\Component\VarDumper\VarDumper::dump([ + 'hook name' => $hookName, + 'hook parameters' => $params, + 'hook external variables' => $templateVars + ]); + + $content = ob_get_clean(); + + return << +{$hookName} + Show details + + +HTML; + } + + /** + * Process the content of the hook block. + * + * {hookblock name="hook_code" var1="value1" var2="value2" ... } + * + * This function create an event, feed it with the custom variables passed to the function (var1, var2, ...) and + * dispatch it to the hooks that respond to it. + * + * The name of the event is `hook.{context}.{hook_code}` where : + * * context : the id of the context of the smarty render : 1: frontoffice, 2: backoffice, 3: email, 4: pdf + * * hook_code : the code of the hook + * + * The event collects all the fragments generated by modules that listen to this event and add it to a fragmentBag. + * This fragmentBag is not used directly. This is the forhook block that iterates over the fragmentBag to inject + * data in the template. + * + * @param array $params + * @param string $content + * @param \TheliaSmarty\Template\SmartyParser $smarty + * @param bool $repeat + * + * @return string the generated content + */ + public function processHookBlock($params, $content, $smarty, &$repeat) + { + $hookName = $this->getParam($params, 'name'); + $module = intval($this->getParam($params, 'module', 0)); + // explicit definition of variable that can be returned + $fields = preg_replace( + '|[^a-zA-Z0-9,\-_]|', + '', + $this->getParam($params, 'fields', '') + ); + $fields = ('' !== $fields) ? explode(",", $fields) : []; + + if (!$repeat) { + if ($this->debug && $smarty->getRequest()->get('SHOW_HOOK')) { + $content = self::showHook($hookName, $params, $smarty->getTemplateVars()) . $content; + } + + return $content; + } + + $type = $smarty->getTemplateDefinition()->getType(); + + $event = new HookRenderBlockEvent($hookName, $params, $fields, $smarty->getTemplateVars()); + + $event->setArguments($this->getArgumentsFromParams($params)); + + $eventName = sprintf('hook.%s.%s', $type, $hookName); + + // this is a hook specific to a module + if (0 !== $module) { + $eventName .= '.' . $module; + } + + $this->getDispatcher()->dispatch($eventName, $event); + + // save results so we can use it in forHook block + $this->hookResults[$hookName] = $event->get(); + } + + /** + * Process a {forhook rel="hookname"} ... {/forhook} + * + * The forhook iterates over the results return by a hookblock : + * + * {hookblock name="product.additional"} + * {forhook rel="product.additional"} + *
    + *

    {$title}

    + *

    {$content}

    + *
    + * {/forhook} + * {/hookblock} + * + * @param array $params + * @param string $content + * @param \TheliaSmarty\Template\SmartyParser $smarty + * @param bool $repeat + * + * @throws \InvalidArgumentException + * @return string the generated content + */ + public function processForHookBlock($params, $content, $smarty, &$repeat) + { + $rel = $this->getParam($params, 'rel'); + if (null == $rel) { + throw new \InvalidArgumentException( + $this->translator->trans("Missing 'rel' parameter in forHook arguments") + ); + } + + /** @var FragmentBag $fragments */ + $fragments = null; + + // first call + if ($content === null) { + if (!array_key_exists($rel, $this->hookResults)) { + $exception = new \InvalidArgumentException( + $this->translator->trans("Related hook name '%name' is not defined.", ['%name' => $rel]) + ); + + Tlog::getInstance()->error($exception->getMessage()); + + if ($this->debug) { + throw $exception; + } + + return ''; + } + + $fragments = $this->hookResults[$rel]; + $fragments->rewind(); + + if ($fragments->isEmpty()) { + $repeat = false; + } + } else { + $fragments = $this->hookResults[$rel]; + $fragments->next(); + } + + if ($fragments->valid()) { + /** @var Fragment $fragment */ + $fragment = $fragments->current(); + + // On first iteration, save variables that may be overwritten by this hook + if (!isset($this->varstack[$rel])) { + $saved_vars = array(); + + $varlist = $fragment->getVars(); + + foreach ($varlist as $var) { + $saved_vars[$var] = $smarty->getTemplateVars($var); + } + + $this->varstack[$rel] = $saved_vars; + } + + foreach ($fragment->getVarVal() as $var => $val) { + $smarty->assign($var, $val); + } + // continue iteration + $repeat = true; + } + + // end + if (!$repeat) { + // Restore previous variables values before terminating + if (isset($this->varstack[$rel])) { + foreach ($this->varstack[$rel] as $var => $value) { + $smarty->assign($var, $value); + } + + unset($this->varstack[$rel]); + } + } + + if ($content !== null) { + if ($fragments->isEmpty()) { + $content = ""; + } + + return $content; + } + + return ''; + } + + /** + * Process {elsehook rel="hookname"} ... {/elsehook} block + * + * @param array $params hook parameters + * @param string $content hook text content + * @param \Smarty_Internal_Template $template the Smarty object + * @param boolean $repeat repeat indicator (see Smarty doc.) + * + * @return string the hook output + */ + public function elseHook( + $params, + $content, + /** @noinspection PhpUnusedParameterInspection */ $template, + &$repeat + ) { + // When encountering close tag, check if hook has results. + if ($repeat === false) { + return $this->checkEmptyHook($params) ? $content : ''; + } + + return ''; + } + + /** + * Process {ifhook rel="hookname"} ... {/ifhook} block + * + * @param array $params hook parameters + * @param string $content hook text content + * @param \Smarty_Internal_Template $template the Smarty object + * @param boolean $repeat repeat indicator (see Smarty doc.) + * + * @return string the hook output + */ + public function ifHook($params, $content, /** @noinspection PhpUnusedParameterInspection */ $template, &$repeat) + { + // When encountering close tag, check if hook has results. + if ($repeat === false) { + return $this->checkEmptyHook($params) ? '' : $content; + } + + return ''; + } + + /** + * Check if a hook has returned results. The hook should have been executed before, or an + * InvalidArgumentException is thrown + * + * @param array $params + * + * @return boolean true if the hook is empty + * @throws \InvalidArgumentException + */ + protected function checkEmptyHook($params) + { + $hookName = $this->getParam($params, 'rel'); + + if (null == $hookName) { + throw new \InvalidArgumentException( + $this->translator->trans("Missing 'rel' parameter in ifhook/elsehook arguments") + ); + } + + if (!isset($this->hookResults[$hookName])) { + $exception = new \InvalidArgumentException( + $this->translator->trans("Related hook name '%name' is not defined.", ['%name' => $hookName]) + ); + + Tlog::getInstance()->error($exception->getMessage()); + + if ($this->debug) { + throw $exception; + } + + return true; + } + + return (is_string($this->hookResults[$hookName]) && '' === $this->hookResults[$hookName] + || !is_string($this->hookResults[$hookName]) && $this->hookResults[$hookName]->isEmpty() + ); + } + + /** + * Clean the params of the params passed to the hook function or block to feed the arguments of the event + * with relevant arguments. + * + * @param $params + * + * @return array + */ + protected function getArgumentsFromParams($params) + { + $args = array(); + $excludes = array("name", "before", "separator", "after", "fields"); + + if (is_array($params)) { + foreach ($params as $key => $value) { + if (!in_array($key, $excludes)) { + $args[$key] = $value; + } + } + } + + return $args; + } + + /** + * Define the various smarty plugins handled by this class + * + * @return array an array of smarty plugin descriptors + */ + public function getPluginDescriptors() + { + return array( + new SmartyPluginDescriptor('function', 'hook', $this, 'processHookFunction'), + new SmartyPluginDescriptor('block', 'hookblock', $this, 'processHookBlock'), + new SmartyPluginDescriptor('block', 'forhook', $this, 'processForHookBlock'), + new SmartyPluginDescriptor('block', 'elsehook', $this, 'elseHook'), + new SmartyPluginDescriptor('block', 'ifhook', $this, 'ifHook'), + ); + } + + /** + * Return the event dispatcher, + * + * @return \Symfony\Component\EventDispatcher\EventDispatcher + */ + public function getDispatcher() + { + return $this->dispatcher; + } +} diff --git a/local/modules/TheliaSmarty/Template/Plugins/Module.php b/local/modules/TheliaSmarty/Template/Plugins/Module.php new file mode 100644 index 00000000..da6e6248 --- /dev/null +++ b/local/modules/TheliaSmarty/Template/Plugins/Module.php @@ -0,0 +1,106 @@ +debug = $debug; + $this->requestStack = $requestStack; + } + /** + * Process theliaModule template inclusion function + * + * This function accepts two parameters: + * + * - location : this is the location in the admin template. Example: folder-edit'. The function will search for + * AdminIncludes/.html file, and fetch it as a Smarty template. + * - countvar : this is the name of a template variable where the number of found modules includes will be assigned. + * + * @param array $params + * @param \Smarty_Internal_Template $parser + * @internal param \Thelia\Core\Template\Smarty\Plugins\unknown $smarty + * + * @return string + * + * @throws \Exception + * @throws \SmartyException + */ + public function theliaModule($params, \Smarty_Internal_Template $parser) + { + $content = null; + $count = 0; + if (false !== $location = $this->getParam($params, 'location', false)) { + if ($this->debug === true && $this->requestStack->getCurrentRequest()->get('SHOW_INCLUDE')) { + echo sprintf('
    %s
    ', $location); + } + + $moduleLimit = $this->getParam($params, 'module', null); + + $modules = ModuleQuery::getActivated(); + + /** @var \Thelia\Model\Module $module */ + foreach ($modules as $module) { + if (null !== $moduleLimit && $moduleLimit != $module->getCode()) { + continue; + } + + $file = $module->getAbsoluteAdminIncludesPath() . DS . $location . '.html'; + + if (file_exists($file)) { + $output = trim(file_get_contents($file)); + + if (! empty($output)) { + $content .= $output; + + $count++; + } + } + } + } + + if (false !== $countvarname = $this->getParam($params, 'countvar', false)) { + $parser->assign($countvarname, $count); + } + + if (! empty($content)) { + return $parser->fetch(sprintf("string:%s", $content)); + } + + return ""; + } + + /** + * Define the various smarty plugins hendled by this class + * + * @return array of smarty plugin descriptors + */ + public function getPluginDescriptors() + { + return array( + new SmartyPluginDescriptor('function', 'module_include', $this, 'theliaModule'), + ); + } +} diff --git a/local/modules/TheliaSmarty/Template/Plugins/Render.php b/local/modules/TheliaSmarty/Template/Plugins/Render.php new file mode 100644 index 00000000..2f7abd3d --- /dev/null +++ b/local/modules/TheliaSmarty/Template/Plugins/Render.php @@ -0,0 +1,167 @@ + + */ +class Render extends AbstractSmartyPlugin +{ + /** @var ControllerResolver */ + protected $controllerResolver; + + /** @var RequestStack */ + protected $requestStack; + + /** @var Container */ + protected $container; + + /** + * @param ControllerResolver $controllerResolver + * @param RequestStack $requestStack + * @param Container $container + */ + public function __construct(ControllerResolver $controllerResolver, RequestStack $requestStack, Container $container) + { + $this->controllerResolver = $controllerResolver; + $this->requestStack = $requestStack; + $this->container = $container; + } + + /** + * @param $params + * @return mixed|string + * @throws SmartyPluginException + */ + public function processRender($params) + { + if (null === $params["action"]) { + throw new SmartyPluginException( + "You must declare the 'action' parameter in the 'render' smarty function" + ); + } + + $request = $this->prepareRequest($params); + + $this->requestStack->push($request); + + $controller = $this->controllerResolver->getController($request); + $controllerParameters = $this->controllerResolver->getArguments($request, $controller); + + $response = call_user_func_array($controller, $controllerParameters); + + $this->requestStack->pop(); + + if ($response instanceof Response) { + return $response->getContent(); + } + + return $response; + } + + protected function prepareRequest(array $params) + { + // Get action + $action = $this->popParameter($params, "action"); + + // Then get and filter query, request and method + $query = $this->popParameter($params, "query"); + $query = $this->filterArrayStrParam($query); + $request = $this->popParameter($params, "request"); + $request = $this->filterArrayStrParam($request); + $method = strtoupper($this->popParameter($params, "method", "GET")); + + // Then build the request + $requestObject = clone $this->requestStack->getCurrentRequest(); + $requestObject->query = new ParameterBag($query); + $requestObject->request = new ParameterBag($request); + $requestObject->attributes = new ParameterBag(["_controller" => $action]); + + // Apply the method + if (!empty($request) && "GET" === $method) { + $requestObject->setMethod("POST"); + } else { + $requestObject->setMethod($method); + } + + // Then all the attribute parameters + foreach ($params as $key => $attribute) { + $requestObject->attributes->set($key, $attribute); + } + + return $requestObject; + } + + /** + * @param $param + * @return array + * + * If $param is an array, return it. + * Else parser it to translate a=b&c=d&e[]=f&g[h]=i to + * ["a"=>"b","c"=>"d","e"=>["f"],"g"=>["h"=>"i"] + */ + protected function filterArrayStrParam($param) + { + if (is_array($param)) { + return $param; + } + + parse_str($param, $param); + + if (false === $param) { + return []; + } + + return $param; + } + + /** + * @param array $params + * @param $name + * @param null $default + * @return mixed + * + * Get a parameter then unset it + */ + protected function popParameter(array $params, $name, $default = null) + { + $param = $this->getParam($params, $name, $default); + + if (array_key_exists($name, $params)) { + unset($params[$name]); + } + + return $param; + } + + /** + * @return SmartyPluginDescriptor[] an array of SmartyPluginDescriptor + */ + public function getPluginDescriptors() + { + return array( + new SmartyPluginDescriptor('function', 'render', $this, 'processRender'), + ); + } +} diff --git a/local/modules/TheliaSmarty/Template/Plugins/Security.php b/local/modules/TheliaSmarty/Template/Plugins/Security.php new file mode 100644 index 00000000..bd14bfdc --- /dev/null +++ b/local/modules/TheliaSmarty/Template/Plugins/Security.php @@ -0,0 +1,146 @@ +securityContext = $securityContext; + $this->requestStack = $requestStack; + $this->dispatcher = $dispatcher; + } + + /** + * Process security check function + * + * @param array $params + * @param \Smarty $smarty + * @return string no text is returned. + * @throws \Thelia\Core\Security\Exception\AuthenticationException + * @throws AuthenticationException + * @throws AuthorizationException + */ + public function checkAuthFunction($params, &$smarty) + { + $roles = $this->explode($this->getParam($params, 'role')); + $resources = $this->explode($this->getParam($params, 'resource')); + $modules = $this->explode($this->getParam($params, 'module')); + $accesses = $this->explode($this->getParam($params, 'access')); + + if (! $this->securityContext->isGranted($roles, $resources, $modules, $accesses)) { + if (null === $this->securityContext->checkRole($roles)) { + // The current user is not logged-in. + $ex = new AuthenticationException( + sprintf( + "User not granted for roles '%s', to access resources '%s' with %s.", + implode(',', $roles), + implode(',', $resources), + implode(',', $accesses) + ) + ); + + $loginTpl = $this->getParam($params, 'login_tpl'); + + if (null != $loginTpl) { + $ex->setLoginTemplate($loginTpl); + } + } else { + // We have a logged-in user, who do not have the proper permission. Issue an AuthorizationException. + $ex = new AuthorizationException( + sprintf( + "User not granted for roles '%s', to access resources '%s' with %s.", + implode(',', $roles), + implode(',', $resources), + implode(',', $accesses) + ) + ); + } + + throw $ex; + } + + return ''; + } + + public function checkCartNotEmptyFunction($params, &$smarty) + { + $cart = $this->getSession()->getSessionCart($this->dispatcher); + if ($cart===null || $cart->countCartItems() == 0) { + throw new OrderException('Cart must not be empty', OrderException::CART_EMPTY, array('empty' => 1)); + } + + return ""; + } + + public function checkValidDeliveryFunction($params, &$smarty) + { + $order = $this->getSession()->getOrder(); + /* Does address and module still exists ? We assume address owner can't change neither module type */ + if ($order !== null) { + $checkAddress = AddressQuery::create()->findPk($order->getChoosenDeliveryAddress()); + $checkModule = ModuleQuery::create()->findPk($order->getDeliveryModuleId()); + } else { + $checkAddress = $checkModule = null; + } + + if (null === $order || null == $checkAddress || null === $checkModule) { + throw new OrderException('Delivery must be defined', OrderException::UNDEFINED_DELIVERY, array('missing' => 1)); + } + + return ""; + } + + /** + * Define the various smarty plugins handled by this class + * + * @return array an array of smarty plugin descriptors + */ + public function getPluginDescriptors() + { + return array( + new SmartyPluginDescriptor('function', 'check_auth', $this, 'checkAuthFunction'), + new SmartyPluginDescriptor('function', 'check_cart_not_empty', $this, 'checkCartNotEmptyFunction'), + new SmartyPluginDescriptor('function', 'check_valid_delivery', $this, 'checkValidDeliveryFunction'), + ); + } + + /** + * @return Session + */ + protected function getSession() + { + return $this->requestStack->getCurrentRequest()->getSession(); + } +} diff --git a/local/modules/TheliaSmarty/Template/Plugins/TheliaLoop.php b/local/modules/TheliaSmarty/Template/Plugins/TheliaLoop.php new file mode 100644 index 00000000..d3a143f2 --- /dev/null +++ b/local/modules/TheliaSmarty/Template/Plugins/TheliaLoop.php @@ -0,0 +1,496 @@ +container = $container; + $this->request = $container->get('request_stack')->getCurrentRequest(); + $this->dispatcher = $container->get('event_dispatcher'); + $this->securityContext = $container->get('thelia.securityContext'); + $this->translator = $container->get("thelia.translator"); + $this->isDebugActive = $container->getParameter("kernel.debug"); + } + + /** + * @param string $loopName + * @return PropelModelPager + * @throws \InvalidArgumentException if no pagination was found for loop + */ + public static function getPagination($loopName) + { + if (array_key_exists($loopName, self::$pagination)) { + return self::$pagination[$loopName]; + } else { + throw new \InvalidArgumentException( + Translator::getInstance()->trans("No pagination currently defined for loop name '%name'", ['%name' => $loopName ]) + ); + } + } + + /** + * Process the count function: executes a loop and return the number of items found + * + * @param array $params parameters array + * @param \Smarty_Internal_Template $template + * + * @return int the item count + * @throws \InvalidArgumentException if a parameter is missing + * + */ + public function theliaCount($params, /** @noinspection PhpUnusedParameterInspection */ $template) + { + $type = $this->getParam($params, 'type'); + + if (null == $type) { + throw new \InvalidArgumentException( + $this->translator->trans("Missing 'type' parameter in {count} loop arguments") + ); + } + + try { + $loop = $this->createLoopInstance($params); + + return $loop->count(); + } catch (ElementNotFoundException $ex) { + // If loop is not found, when in development mode, rethrow the exception to make it visible + if ($this->isDebugActive) { + throw $ex; + } + + // Otherwise, log the problem and return a count of 0 + Tlog::getInstance()->error($ex->getMessage()); + + return 0; + } + } + + /** + * Process {loop name="loop name" type="loop type" ... } ... {/loop} block + * + * @param array $params + * @param string $content + * @param \Smarty_Internal_Template $template + * @param boolean $repeat + * + * @throws \InvalidArgumentException + * + * @return void|string + */ + public function theliaLoop($params, $content, $template, &$repeat) + { + $name = $this->getParam($params, 'name'); + + if (null == $name) { + throw new \InvalidArgumentException( + $this->translator->trans("Missing 'name' parameter in loop arguments") + ); + } + + $type = $this->getParam($params, 'type'); + + if (null == $type) { + throw new \InvalidArgumentException( + $this->translator->trans("Missing 'type' parameter in loop arguments") + ); + } + + if ($content === null) { + // Check if a loop with the same name exists in the current scope, and abort if it's the case. + if (array_key_exists($name, $this->varstack)) { + throw new \InvalidArgumentException( + $this->translator->trans("A loop named '%name' already exists in the current scope.", ['%name' => $name]) + ); + } + + try { + $loop = $this->createLoopInstance($params); + + self::$pagination[$name] = null; + + // We have to clone the result, as exec() returns a cached LoopResult object, which may cause side effects + // if loops with the same argument set are nested (see https://github.com/thelia/thelia/issues/2213) + $loopResults = clone($loop->exec(self::$pagination[$name])); + + $loopResults->rewind(); + + } catch (ElementNotFoundException $ex) { + // If loop is not found, when in development mode, rethrow the exception to make it visible + if ($this->isDebugActive) { + throw $ex; + } + + // Otherwise, log the problem and simulate an empty result. + Tlog::getInstance()->error($ex->getMessage()); + + // Provide an empty result + $loopResults = new LoopResult(null); + } + + $this->loopstack[$name] = $loopResults; + + // No results ? The loop is terminated, do not evaluate loop text. + if ($loopResults->isEmpty()) { + $repeat = false; + } + } else { + $loopResults = $this->loopstack[$name]; + + $loopResults->next(); + } + + if ($loopResults->valid()) { + $loopResultRow = $loopResults->current(); + + // On first iteration, save variables that may be overwritten by this loop + if (! isset($this->varstack[$name])) { + $saved_vars = array(); + + $varlist = $loopResultRow->getVars(); + + foreach ($varlist as $var) { + $saved_vars[$var] = $template->getTemplateVars($var); + } + + $this->varstack[$name] = $saved_vars; + } + + foreach ($loopResultRow->getVarVal() as $var => $val) { + $template->assign($var, $val); + } + + $repeat = true; + } + + // Loop is terminated. Cleanup. + if (! $repeat) { + // Restore previous variables values before terminating + if (isset($this->varstack[$name])) { + foreach ($this->varstack[$name] as $var => $value) { + $template->assign($var, $value); + } + + unset($this->varstack[$name]); + } + } + + if ($content !== null) { + if ($loopResults->isEmpty()) { + $content = ""; + } + + return $content; + } + + return ''; + } + + /** + * Process {elseloop rel="loopname"} ... {/elseloop} block + * + * @param array $params loop parameters + * @param string $content loop text content + * @param \Smarty_Internal_Template $template the Smarty object + * @param boolean $repeat repeat indicator (see Smarty doc.) + * @return string the loop output + */ + public function theliaElseloop($params, $content, /** @noinspection PhpUnusedParameterInspection */ $template, &$repeat) + { + //Block the smarty interpretation in the elseloop + if ($content === null) { + if (! $this->checkEmptyLoop($params)) { + $repeat = false; + + return ''; + } + } + + return $content; + } + + /** + * Process {ifloop rel="loopname"} ... {/ifloop} block + * + * @param array $params loop parameters + * @param string $content loop text content + * @param \Smarty_Internal_Template $template the Smarty object + * @param boolean $repeat repeat indicator (see Smarty doc.) + * @return string the loop output + */ + public function theliaIfLoop($params, $content, /** @noinspection PhpUnusedParameterInspection */ $template, &$repeat) + { + // When encountering close tag, check if loop has results. + if ($repeat === false) { + return $this->checkEmptyLoop($params) ? '' : $content; + } + + return ''; + } + + /** + * Process {pageloop rel="loopname"} ... {/pageloop} block + * + * @param array $params loop parameters + * @param string $content loop text content + * @param \Smarty_Internal_Template $template the Smarty object + * @param boolean $repeat repeat indicator (see Smarty doc.) + * @return string the loop output + * @throws \InvalidArgumentException + */ + public function theliaPageLoop($params, $content, $template, &$repeat) + { + $loopName = $this->getParam($params, 'rel'); + + if (null == $loopName) { + throw new \InvalidArgumentException($this->translator->trans("Missing 'rel' parameter in page loop")); + } + + // Find pagination + $pagination = self::getPagination($loopName); + + if ($pagination === null || $pagination->getNbResults() == 0) { + // No need to paginate + return ''; + } + + $startPage = intval($this->getParam($params, 'start-page', 1)); + $displayedPageCount = intval($this->getParam($params, 'limit', 10)); + + if (intval($displayedPageCount) == 0) { + $displayedPageCount = PHP_INT_MAX; + } + + $totalPageCount = $pagination->getLastPage(); + + if ($content === null) { + // The current page + $currentPage = $pagination->getPage(); + + // Get the start page. + if ($totalPageCount > $displayedPageCount) { + $startPage = $currentPage - round($displayedPageCount / 2); + + if ($startPage <= 0) { + $startPage = 1; + } + } + + // This is the iterative page number, the one we're going to increment in this loop + $iterationPage = $startPage; + + // The last displayed page number + $endPage = $startPage + $displayedPageCount - 1; + + if ($endPage > $totalPageCount) { + $endPage = $totalPageCount; + } + + // The first displayed page number + $template->assign('START', $startPage); + // The previous page number + $template->assign('PREV', $currentPage > 1 ? $currentPage-1 : $currentPage); + // The next page number + $template->assign('NEXT', $currentPage < $totalPageCount ? $currentPage+1 : $totalPageCount); + // The last displayed page number + $template->assign('END', $endPage); + // The overall last page + $template->assign('LAST', $totalPageCount); + } else { + $iterationPage = $template->getTemplateVars('PAGE'); + + $iterationPage++; + } + + if ($iterationPage <= $template->getTemplateVars('END')) { + // The iterative page number + $template->assign('PAGE', $iterationPage); + + // The overall current page number + $template->assign('CURRENT', $pagination->getPage()); + + $repeat = true; + } + + if ($content !== null) { + return $content; + } + + return ''; + } + + /** + * Check if a loop has returned results. The loop shoud have been executed before, or an + * InvalidArgumentException is thrown + * + * @param array $params + * + * @return boolean true if the loop is empty + * @throws \InvalidArgumentException + */ + protected function checkEmptyLoop($params) + { + $loopName = $this->getParam($params, 'rel'); + + if (null == $loopName) { + throw new \InvalidArgumentException( + $this->translator->trans("Missing 'rel' parameter in ifloop/elseloop arguments") + ); + } + + if (! isset($this->loopstack[$loopName])) { + throw new \InvalidArgumentException( + $this->translator->trans("Related loop name '%name'' is not defined.", ['%name' => $loopName]) + ); + } + + return $this->loopstack[$loopName]->isEmpty(); + } + + /** + * @param $smartyParams + * + * @return BaseLoop + * @throws \Thelia\Core\Template\Element\Exception\InvalidElementException + * @throws \Thelia\Core\Template\Element\Exception\ElementNotFoundException + * @throws \ReflectionException + */ + protected function createLoopInstance($smartyParams) + { + $type = strtolower($smartyParams['type']); + + if (! isset($this->loopDefinition[$type])) { + throw new ElementNotFoundException( + $this->translator->trans("Loop type '%type' is not defined.", ['%type' => $type]) + ); + } + + $class = new \ReflectionClass($this->loopDefinition[$type]); + + if ($class->isSubclassOf("Thelia\Core\Template\Element\BaseLoop") === false) { + throw new InvalidElementException( + $this->translator->trans("'%type' loop class should extends Thelia\Core\Template\Element\BaseLoop", ['%type' => $type]) + ); + } + + /** @var BaseLoop $loop */ + $loop = $class->newInstance( + $this->container + ); + + $loop->initializeArgs($smartyParams); + + return $loop; + } + + /** + * + * Injects an associative array containing information for loop execution + * + * key is loop name + * value is the class implementing/extending base loop classes + * + * ex : + * + * $loop = array( + * "product" => "Thelia\Loop\Product", + * "category" => "Thelia\Loop\Category", + * "myLoop" => "My\Own\Loop" + * ); + * + * @param array $loopDefinition + * @throws \InvalidArgumentException if loop name already exists + */ + public function setLoopList(array $loopDefinition) + { + foreach ($loopDefinition as $name => $className) { + if (array_key_exists($name, $this->loopDefinition)) { + throw new \InvalidArgumentException( + $this->translator->trans("The loop name '%name' is already defined in %className class", [ + '%name' => $name, + '%className' => $className + ]) + ); + } + + $this->loopDefinition[$name] = $className; + } + } + + /** + * Defines the various smarty plugins hendled by this class + * + * @return \TheliaSmarty\Template\SmartyPluginDescriptor[] smarty plugin descriptors + */ + public function getPluginDescriptors() + { + return array( + + new SmartyPluginDescriptor('function', 'count', $this, 'theliaCount'), + new SmartyPluginDescriptor('block', 'loop', $this, 'theliaLoop'), + new SmartyPluginDescriptor('block', 'elseloop', $this, 'theliaElseloop'), + new SmartyPluginDescriptor('block', 'ifloop', $this, 'theliaIfLoop'), + new SmartyPluginDescriptor('block', 'pageloop', $this, 'theliaPageLoop'), + ); + } +} diff --git a/local/modules/TheliaSmarty/Template/Plugins/Translation.php b/local/modules/TheliaSmarty/Template/Plugins/Translation.php new file mode 100644 index 00000000..6eb83652 --- /dev/null +++ b/local/modules/TheliaSmarty/Template/Plugins/Translation.php @@ -0,0 +1,125 @@ +translator = $translator; + } + + /** + * Set the default translation domain + * + * @param array $params + * @param \Smarty_Internal_Template $smarty + * @return string + */ + public function setDefaultTranslationDomain($params, &$smarty) + { + $this->defaultTranslationDomain = $this->getParam($params, 'domain'); + } + + /** + * Set the default locale + * + * @param array $params + * @param \Smarty_Internal_Template $smarty + * @return string + */ + public function setDefaultLocale($params, &$smarty) + { + $this->defaultLocale = $this->getParam($params, 'locale'); + } + + /** + * Process translate function + * + * @param array $params + * @param \Smarty_Internal_Template $smarty + * @return string + */ + public function translate($params, &$smarty) + { + // All parameters other than 'l' and 'd' and 'js' are supposed to be variables. Build an array of var => value pairs + // and pass it to the translator + $vars = array(); + + foreach ($params as $name => $value) { + if (!in_array($name, $this->protectedParams)) { + $vars["%$name"] = $value; + } + } + + $str = $this->translator->trans( + $this->getParam($params, 'l'), + $vars, + $this->getParam($params, 'd', $this->defaultTranslationDomain), + $this->getParam($params, 'locale', $this->defaultLocale), + $this->getBoolean($this->getParam($params, 'default', true), true), + $this->getBoolean($this->getParam($params, 'fallback', true), true) + ); + + if ($this->getParam($params, 'js', 0)) { + $str = preg_replace("/(['\"])/", "\\\\$1", $str); + } + + return $str; + } + + protected function getBoolean($value, $default = false) + { + $val = filter_var($value, FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE); + if (null === $val) { + $val = $default; + } + + return $val; + } + + /** + * Define the various smarty plugins handled by this class + * + * @return \TheliaSmarty\Template\SmartyPluginDescriptor[] an array of smarty plugin descriptors + */ + public function getPluginDescriptors() + { + return array( + new SmartyPluginDescriptor('function', 'intl', $this, 'translate'), + new SmartyPluginDescriptor('function', 'default_translation_domain', $this, 'setDefaultTranslationDomain'), + new SmartyPluginDescriptor('function', 'default_locale', $this, 'setDefaultLocale'), + ); + } +} diff --git a/local/modules/TheliaSmarty/Template/Plugins/Type.php b/local/modules/TheliaSmarty/Template/Plugins/Type.php new file mode 100644 index 00000000..9140a13d --- /dev/null +++ b/local/modules/TheliaSmarty/Template/Plugins/Type.php @@ -0,0 +1,47 @@ +isValid($value)) { + return ''; + } + + return $value; + } + + /** + * Define the various smarty plugins handled by this class + * + * @return an array of smarty plugin descriptors + */ + public function getPluginDescriptors() + { + return array( + new SmartyPluginDescriptor('modifier', 'assertType', $this, 'assertTypeModifier'), + ); + } +} diff --git a/local/modules/TheliaSmarty/Template/Plugins/UrlGenerator.php b/local/modules/TheliaSmarty/Template/Plugins/UrlGenerator.php new file mode 100644 index 00000000..0e57fcd4 --- /dev/null +++ b/local/modules/TheliaSmarty/Template/Plugins/UrlGenerator.php @@ -0,0 +1,405 @@ +requestStack = $requestStack; + $this->tokenProvider = $tokenProvider; + $this->container = $container; + } + + /** + * Process url generator function + * + * @param array $params + * @param \Smarty $smarty + * @return string no text is returned. + */ + public function generateUrlFunction($params, &$smarty) + { + // the path to process + $current = $this->getParam($params, 'current', false); + $path = $this->getParam($params, 'path', null); + // Do not invoke index.php in URL (get a static file in web space + $file = $this->getParam($params, 'file', null); + $routeId = $this->getParam($params, 'route_id', null); + // select default router + if ($this->getRequest()->fromAdmin()) { + $defaultRouter = 'admin'; + } elseif ($this->getRequest()->fromFront()) { + $defaultRouter = 'front'; + } else { + $defaultRouter = null; + } + + $routerId = $this->getParam($params, 'router', $defaultRouter); + + $baseUrl = $this->getParam($params, 'base_url', null); + + if ($current) { + $path = $this->getRequest()->getPathInfo(); + unset($params["current"]); // Delete the current param, so it isn't included in the url + + // build the query variables + $params = array_merge( + $this->getRequest()->query->all(), + $params + ); + } + + if ($routeId !== null && $routerId !== null) { + $routerId = 'router.' . $routerId; + + // test if the router exists + if (!$this->container->has($routerId)) { + throw new \InvalidArgumentException( + 'The router "' . $routerId . '" not found.' + ); + } + // get url by router and id + /** @var Router $router */ + $router = $this->container->get($routerId); + + $url = $router->generate( + $routeId, + $this->getArgsFromParam($params, ['route_id', 'router', 'base_url']), + Router::ABSOLUTE_URL + ); + } else { + if ($file !== null) { + $path = $file; + $mode = URL::PATH_TO_FILE; + } elseif ($path !== null) { + $mode = URL::WITH_INDEX_PAGE; + } else { + throw new \InvalidArgumentException( + "Please specify either 'path', 'file' or router and route_id on parameters in {url} function." + ); + } + + $excludeParams = $this->resolvePath($params, $path, $smarty); + + $url = URL::getInstance()->absoluteUrl( + $path, + $this->getArgsFromParam($params, array_merge(['noamp', 'path', 'file', 'target', 'base_url'], $excludeParams)), + $mode, + $baseUrl + ); + + $request = $this->getRequest(); + $requestedLangCodeOrLocale = $params["lang"]; + $view = $request->attributes->get('_view', null); + $viewId = $view === null ? null : $request->query->get($view . '_id', null); + + if (null !== $requestedLangCodeOrLocale) { + if (strlen($requestedLangCodeOrLocale) > 2) { + $lang = LangQuery::create()->findOneByLocale($requestedLangCodeOrLocale); + } else { + $lang = LangQuery::create()->findOneByCode($requestedLangCodeOrLocale); + } + + if (ConfigQuery::isMultiDomainActivated()) { + $urlRewrite = RewritingUrlQuery::create() + ->filterByView($view) + ->filterByViewId($viewId) + ->filterByViewLocale($lang->getLocale()) + ->findOneByRedirected(null) + ; + + $path = ''; + if (null != $urlRewrite) { + $path = "/".$urlRewrite->getUrl(); + } + $url = rtrim($lang->getUrl(), "/").$request->getBaseUrl().$path; + } + + } + } + return $this->applyNoAmpAndTarget($params, $url); + } + + /** + * + * find placeholders in the path and replace them by the given value + * + * @param $params + * @param $path + * @param $smarty + * @return array the placeholders found + */ + protected function resolvePath(&$params, &$path, $smarty) + { + $placeholder = []; + + foreach ($params as $key => $value) { + if (false !== strpos($path, "%$key")) { + $placeholder["%$key"] = SmartyParser::theliaEscape($value, $smarty); + unset($params[$key]); + } + } + + $path = strtr($path, $placeholder); + $keys = array_keys($placeholder); + array_walk($keys, function (&$item, $key) { + $item = str_replace('%', '', $item); + }); + + return $keys; + } + + /** + * Process view url generator function + * + * @param array $params + * @param \Smarty $smarty + * @return string no text is returned. + */ + public function generateFrontViewUrlFunction($params, &$smarty) + { + return $this->generateViewUrlFunction($params, false); + } + + /** + * Process administration view url generator function + * + * @param array $params + * @param \Smarty $smarty + * @return string no text is returned. + */ + public function generateAdminViewUrlFunction($params, &$smarty) + { + return $this->generateViewUrlFunction($params, true); + } + + + public function navigateToUrlFunction($params, &$smarty) + { + $to = $this->getParam($params, 'to', null); + + $toMethod = $this->getNavigateToMethod($to); + + $url = URL::getInstance()->absoluteUrl( + $this->$toMethod(), + $this->getArgsFromParam($params, ['noamp', 'to', 'target', 'base_url']), + URL::WITH_INDEX_PAGE + ); + + return $this->applyNoAmpAndTarget($params, $url); + } + + protected function generateViewUrlFunction($params, $forAdmin) + { + // the view name (without .html) + $view = $this->getParam($params, 'view'); + + $args = $this->getArgsFromParam($params, array('view', 'noamp', 'target', 'base_url')); + + $url = $forAdmin ? URL::getInstance()->adminViewUrl($view, $args) : URL::getInstance()->viewUrl($view, $args); + + return $this->applyNoAmpAndTarget($params, $url); + } + + /** + * Get URL parameters array from parameters. + * + * @param array $params Smarty function params + * @param array $exclude Smarty function exclude params + * @return array the parameters array (either emply, of valued) + */ + private function getArgsFromParam($params, $exclude = array()) + { + $pairs = array(); + + foreach ($params as $name => $value) { + if (in_array($name, $exclude)) { + continue; + } + + $pairs[$name] = $value; + } + + return $pairs; + } + + public function generateUrlWithToken($params, &$smarty) + { + /** + * Compute the url + */ + $url = $this->generateUrlFunction($params, $smarty); + + $urlTokenParam = $this->getParam($params, "url_param", "_token"); + + /** + * Add the token + */ + $token = $this->tokenProvider->assignToken(); + + $newUrl = URL::getInstance()->absoluteUrl( + $url, + [ + $urlTokenParam => $token + ] + ); + + return $this->applyNoAmpAndTarget($params, $newUrl); + } + + protected function applyNoAmpAndTarget($params, $url) + { + $noamp = $this->getParam($params, 'noamp', null); // Do not change & in & + $target = $this->getParam($params, 'target', null); + + if (!$noamp) { + $url = str_replace('&', '&', $url); + } + + if ($target != null) { + $url .= '#'.$target; + } + + return $url; + } + + /** + * Set the _previous_url request attribute, to define the previous URL, or + * prevent saving the current URL as the previous one. + * + * @param array $params + * @param \Smarty_Internal_Template $smarty + */ + public function setPreviousUrlFunction($params, &$smarty) + { + $ignore_current = $this->getParam($params, 'ignore_current', false); + + if ($ignore_current !== false) { + $this->getRequest()->attributes->set('_previous_url', 'dont-save'); + } else { + $this->getRequest()->attributes->set('_previous_url', $this->generateUrlFunction($params, $smarty)); + } + } + + /** + * Define the various smarty plugins handled by this class + * + * @return array an array of smarty plugin descriptors + */ + public function getPluginDescriptors() + { + return array( + new SmartyPluginDescriptor('function', 'url', $this, 'generateUrlFunction'), + new SmartyPluginDescriptor('function', 'token_url', $this, 'generateUrlWithToken'), + new SmartyPluginDescriptor('function', 'viewurl', $this, 'generateFrontViewUrlFunction'), + new SmartyPluginDescriptor('function', 'admin_viewurl', $this, 'generateAdminViewUrlFunction'), + new SmartyPluginDescriptor('function', 'navigate', $this, 'navigateToUrlFunction'), + new SmartyPluginDescriptor('function', 'set_previous_url', $this, 'setPreviousUrlFunction') + ); + } + + /** + * @return array sur le format "to_value" => "method_name" + */ + protected function getNavigateToValues() + { + return array( + "current" => "getCurrentUrl", + "previous" => "getPreviousUrl", + "catalog_last" => "getCatalogLastUrl", + "index" => "getIndexUrl", + ); + } + + protected function getNavigateToMethod($to) + { + if ($to === null) { + throw new \InvalidArgumentException("Missing 'to' parameter in `navigate` substitution."); + } + + $navigateToValues = $this->getNavigateToValues(); + + if (!array_key_exists($to, $navigateToValues)) { + throw new \InvalidArgumentException( + sprintf("Incorrect value `%s` for parameter `to` in `navigate` substitution.", $to) + ); + } + + return $navigateToValues[$to]; + } + + protected function getCurrentUrl() + { + return $this->getRequest()->getUri(); + } + + protected function getPreviousUrl() + { + return URL::getInstance()->absoluteUrl($this->getSession()->getReturnToUrl()); + } + + protected function getCatalogLastUrl() + { + return URL::getInstance()->absoluteUrl($this->getSession()->getReturnToCatalogLastUrl()); + } + + protected function getIndexUrl() + { + return URL::getInstance()->getIndexPage(); + } + + /** + * @return Request + */ + protected function getRequest() + { + return $this->requestStack->getCurrentRequest(); + } + + /** + * @return Session + */ + protected function getSession() + { + return $this->getRequest()->getSession(); + } +} diff --git a/local/modules/TheliaSmarty/Template/Plugins/VarDumper.php b/local/modules/TheliaSmarty/Template/Plugins/VarDumper.php new file mode 100644 index 00000000..a62615fd --- /dev/null +++ b/local/modules/TheliaSmarty/Template/Plugins/VarDumper.php @@ -0,0 +1,72 @@ + + * @since Thelia v 2.4 + */ +class VarDumper extends AbstractSmartyPlugin +{ + /** @var bool */ + protected $debug; + + /** + * VarDumper constructor. + * @param bool $debug + */ + public function __construct($debug) + { + $this->debug = $debug; + } + + public function dump($params, $template = null) + { + if (!$this->debug) { + throw new \Exception('The smarty function "dump" is available only in debug mode.'); + } + + if (!function_exists('dump')) { + throw new \Exception('The function "dump" was no available. Check that this project has the package symfony/var-dumper in the composer.json file,' + . ' and that you have installed dev dependencies : composer.phar install --dev'); + } + + ob_start(); + foreach ($params as $name => $param) { + $type = gettype($param); + echo '
    ' + . $name + . ' : ' + . ($type === 'object' ? get_class($param) : $type) + . '
    '; + dump($param); + } + $dump = ob_get_contents(); + ob_end_clean(); + + return $dump; + } + + /** + * @return array an array of SmartyPluginDescriptor + */ + public function getPluginDescriptors() + { + return array( + new SmartyPluginDescriptor('function', 'dump', $this, 'dump') + ); + } +} diff --git a/local/modules/TheliaSmarty/Template/SmartyHelper.php b/local/modules/TheliaSmarty/Template/SmartyHelper.php new file mode 100644 index 00000000..2bed38f8 --- /dev/null +++ b/local/modules/TheliaSmarty/Template/SmartyHelper.php @@ -0,0 +1,178 @@ + + */ +class SmartyHelper implements ParserHelperInterface +{ + /** + * Parse a string and get all smarty function and block with theirs arguments. + * some smarty functions are not supported : if, for, ... + * + * + * + * @param string $content the template content + * @param array $functions the only functions we want to parse + * + * @return array array of functions with 2 index name and attributes an array of name, value + */ + public function getFunctionsDefinition($content, array $functions = array()) + { + $strlen = strlen($content); + + // init + $buffer = ''; + $name = ''; + $attributeName = ''; + $waitfor = ''; + + $inFunction = false; + $hasName = false; + $inAttribute = false; + $inInnerFunction = false; + + $ldelim = '{'; + $rdelim = '}'; + $skipFunctions = array("if", "for"); + $skipCharacters = array("\t", "\r", "\n"); + + $store = array(); + $attributes = array(); + + for ($pos = 0; $pos < $strlen; $pos++) { + $char = $content[$pos]; + + if (in_array($char, $skipCharacters)) { + continue; + } + + if (!$inFunction) { + if ($char === $ldelim) { + $inFunction = true; + $inInnerFunction = false; + } + continue; + } + + // get function name + if (!$hasName) { + if ($char === " " || $char === $rdelim) { + $name = $buffer; + // we catch this name ? + $hasName = $inFunction = (!in_array($name, $skipFunctions) && (0 === count($functions) || in_array($name, $functions))); + $buffer = ""; + continue; + } else { + // skip { + if (in_array($char, array("/", "$", "#", "'", "\""))) { + $inFunction = false; + } else { + $buffer .= $char; + } + continue; + } + } + + // inner Function ? + if ($char === $ldelim) { + $inInnerFunction = true; + $buffer .= $char; + continue; + } + + // end ? + if ($char === $rdelim) { + if ($inInnerFunction) { + $inInnerFunction = false; + $buffer .= $char; + } else { + if ($inAttribute) { + if ("" === $attributeName) { + $attributes[trim($buffer)] = ""; + } else { + $attributes[$attributeName] = $buffer; + } + $inAttribute = false; + } + $store[] = array( + "name" => $name, + "attributes" => $attributes + ); + $inFunction = false; + $inAttribute = false; + $inInnerFunction = false; + $hasName = false; + $name = ""; + $buffer = ""; + $waitfor = ""; + $attributes = array(); + } + continue; + } + + // attributes + if (!$inAttribute) { + if ($char !== " ") { + $inAttribute = true; + $buffer = $char; + $attributeName = ""; + } + } else { + if ("" === $attributeName) { + if (in_array($char, array(" ", "="))) { + $attributeName = trim($buffer); + if (" " === $char) { + $attributes[$attributeName] = ""; + $inAttribute = false; + } + $buffer = ""; + } else { + $buffer .= $char; + } + } else { + if ("" === $waitfor) { + if (in_array($char, array("'", "\""))) { + $waitfor = $char; + } else { + $waitfor = " "; + $buffer .= $char; + } + continue; + } + if ($inInnerFunction) { + $buffer .= $char; + } else { + // end of attribute ? + if ($char === $waitfor) { + $attributes[$attributeName] = $buffer; + $inAttribute = false; + $waitfor = ""; + } else { + $buffer .= $char; + } + } + } + } + } + + return $store; + } +} diff --git a/local/modules/TheliaSmarty/Template/SmartyParser.php b/local/modules/TheliaSmarty/Template/SmartyParser.php new file mode 100644 index 00000000..0f434c1b --- /dev/null +++ b/local/modules/TheliaSmarty/Template/SmartyParser.php @@ -0,0 +1,640 @@ + + * @author Etienne Roudeix + */ +class SmartyParser extends Smarty implements ParserInterface +{ + public $plugins = array(); + + /** @var EventDispatcherInterface */ + protected $dispatcher; + + /** @var ParserContext */ + protected $parserContext; + + /** @var TemplateHelperInterface */ + protected $templateHelper; + + /** @var RequestStack */ + protected $requestStack; + + protected $backOfficeTemplateDirectories = array(); + protected $frontOfficeTemplateDirectories = array(); + + protected $templateDirectories = array(); + + /** @var TemplateDefinition */ + protected $templateDefinition; + + /** @var bool if true, resources will also be searched in the default template */ + protected $fallbackToDefaultTemplate = false; + + /** @var int */ + protected $status = 200; + + /** @var string */ + protected $env; + + /** @var bool */ + protected $debug; + + /** @var array The template stack */ + protected $tplStack = []; + + /** @var bool */ + protected $useMethodCallWrapper = false; + + /** + * @param RequestStack $requestStack + * @param EventDispatcherInterface $dispatcher + * @param ParserContext $parserContext + * @param TemplateHelperInterface $templateHelper + * @param string $env + * @param bool $debug + * @throws \SmartyException + */ + public function __construct( + RequestStack $requestStack, + EventDispatcherInterface $dispatcher, + ParserContext $parserContext, + TemplateHelperInterface $templateHelper, + $env = "prod", + $debug = false + ) { + parent::__construct(); + + $this->requestStack = $requestStack; + $this->dispatcher = $dispatcher; + $this->parserContext = $parserContext; + $this->templateHelper = $templateHelper; + $this->env = $env; + $this->debug = $debug; + + // Use methos call coamptibility wrapper ? + $this->useMethodCallWrapper = version_compare(self::SMARTY_VERSION, "3.1.33", '>='); + + // Configure basic Smarty parameters + + $compile_dir = THELIA_ROOT . 'cache'. DS . $env . DS . 'smarty' . DS . 'compile'; + if (! is_dir($compile_dir)) { + @mkdir($compile_dir, 0777, true); + } + + $cache_dir = THELIA_ROOT . 'cache'. DS . $env . DS . 'smarty' . DS . 'cache'; + if (! is_dir($cache_dir)) { + @mkdir($cache_dir, 0777, true); + } + + $this->setCompileDir($compile_dir); + $this->setCacheDir($cache_dir); + + // Prevent smarty ErrorException: Notice: Undefined index bla bla bla... + $this->error_reporting = E_ALL ^ E_NOTICE; + + // The default HTTP status + $this->status = 200; + + $this->registerFilter('output', array($this, "trimWhitespaces")); + $this->registerFilter('variable', array(__CLASS__, "theliaEscape")); + } + + /** + * Return the current request or null if no request exists + * + * @return Request|null + */ + public function getRequest() + { + return $this->requestStack->getCurrentRequest(); + } + + /** + * Trim whitespaces from the HTML output, preserving required ones in pre, textarea, javascript. + * This methois uses 3 levels of trimming : + * + * - 0 : whitespaces are not trimmed, code remains as is. + * - 1 : only blank lines are trimmed, code remains indented and human-readable (the default) + * - 2 or more : all unnecessary whitespace are removed. Code is very hard to read. + * + * The trim level is defined by the configuration variable html_output_trim_level + * + * @param string $source the HTML source + * @param \Smarty_Internal_Template $template + * @return string + */ + public function trimWhitespaces($source, /** @noinspection PhpUnusedParameterInspection */ \Smarty_Internal_Template $template) + { + $compressionMode = ConfigQuery::read('html_output_trim_level', 1); + + if ($compressionMode == 0) { + return $source; + } + + $store = array(); + $_store = 0; + $_offset = 0; + + // Unify Line-Breaks to \n + $source = preg_replace("/\015\012|\015|\012/", "\n", $source); + + // capture Internet Explorer Conditional Comments + if ($compressionMode == 1) { + $expressions = array( + // remove spaces between attributes (but not in attribute values!) + '#(([a-z0-9]\s*=\s*(["\'])[^\3]*?\3)|<[a-z0-9_]+)\s+([a-z/>])#is' => '\1 \4', + '/(^[\n]*|[\n]+)[\s\t]*[\n]+/' => "\n" + ); + } elseif ($compressionMode >= 2) { + if (preg_match_all('##is', $source, $matches, PREG_OFFSET_CAPTURE | PREG_SET_ORDER)) { + foreach ($matches as $match) { + $store[] = $match[0][0]; + $_length = strlen($match[0][0]); + $replace = '@!@SMARTY:' . $_store . ':SMARTY@!@'; + $source = substr_replace($source, $replace, $match[0][1] - $_offset, $_length); + + $_offset += $_length - strlen($replace); + $_store++; + } + } + + // Strip all HTML-Comments + // yes, even the ones in + + + + + + send(); + exit; + + break; + case 'copy_cut': + if ($_POST['sub_action'] != 'copy' && $_POST['sub_action'] != 'cut') + { + response(trans('wrong sub-action').AddErrorLocation())->send(); + exit; + } + + if (strpos($_POST['path'],'../') !== FALSE + || strpos($_POST['path'],'./') !== FALSE + || strpos($_POST['path'],'..\\') !== FALSE + || strpos($_POST['path'],'.\\') !== FALSE ) + { + response(trans('wrong path'.AddErrorLocation()))->send(); + exit; + } + + if (trim($_POST['path']) == '') + { + response(trans('no path').AddErrorLocation())->send(); + exit; + } + + $msg_sub_action = ($_POST['sub_action'] == 'copy' ? trans('Copy') : trans('Cut')); + $path = $current_path . $_POST['path']; + + if (is_dir($path)) + { + // can't copy/cut dirs + if ($copy_cut_dirs === false) + { + response(sprintf(trans('Copy_Cut_Not_Allowed'), $msg_sub_action, trans('Folders')).AddErrorLocation())->send(); + exit; + } + + list($sizeFolderToCopy,$fileNum,$foldersCount) = folder_info($path,false); + // size over limit + if ($copy_cut_max_size !== false && is_int($copy_cut_max_size)) { + if (($copy_cut_max_size * 1024 * 1024) < $sizeFolderToCopy) { + response(sprintf(trans('Copy_Cut_Size_Limit'), $msg_sub_action, $copy_cut_max_size).AddErrorLocation())->send(); + exit; + } + } + + // file count over limit + if ($copy_cut_max_count !== false && is_int($copy_cut_max_count)) + { + if ($copy_cut_max_count < $fileNum) + { + response(sprintf(trans('Copy_Cut_Count_Limit'), $msg_sub_action, $copy_cut_max_count).AddErrorLocation())->send(); + exit; + } + } + + if (!checkresultingsize($sizeFolderToCopy)) { + response(sprintf(trans('max_size_reached'),$MaxSizeTotal).AddErrorLocation())->send(); + exit; + } + } else { + // can't copy/cut files + if ($copy_cut_files === false) + { + response(sprintf(trans('Copy_Cut_Not_Allowed'), $msg_sub_action, trans('Files')).AddErrorLocation())->send(); + exit; + } + } + + $_SESSION['RF']['clipboard']['path'] = $_POST['path']; + $_SESSION['RF']['clipboard_action'] = $_POST['sub_action']; + break; + case 'clear_clipboard': + $_SESSION['RF']['clipboard'] = null; + $_SESSION['RF']['clipboard_action'] = null; + break; + case 'chmod': + if($ftp){ + $path = $ftp_base_url . $upload_dir . $_POST['path']; + if ( + ($_POST['folder']==1 && $chmod_dirs === false) + || ($_POST['folder']==0 && $chmod_files === false) + || (is_function_callable("chmod") === false) ) + { + response(sprintf(trans('File_Permission_Not_Allowed'), (is_dir($path) ? trans('Folders') : trans('Files')), 403).AddErrorLocation())->send(); + exit; + } + $info = $_POST['permissions']; + }else{ + $path = $current_path . $_POST['path']; + if ( + (is_dir($path) && $chmod_dirs === false) + || (is_file($path) && $chmod_files === false) + || (is_function_callable("chmod") === false) ) + { + response(sprintf(trans('File_Permission_Not_Allowed'), (is_dir($path) ? trans('Folders') : trans('Files')), 403).AddErrorLocation())->send(); + exit; + } + + $perms = fileperms($path) & 0777; + + $info = '-'; + + // Owner + $info .= (($perms & 0x0100) ? 'r' : '-'); + $info .= (($perms & 0x0080) ? 'w' : '-'); + $info .= (($perms & 0x0040) ? + (($perms & 0x0800) ? 's' : 'x' ) : + (($perms & 0x0800) ? 'S' : '-')); + + // Group + $info .= (($perms & 0x0020) ? 'r' : '-'); + $info .= (($perms & 0x0010) ? 'w' : '-'); + $info .= (($perms & 0x0008) ? + (($perms & 0x0400) ? 's' : 'x' ) : + (($perms & 0x0400) ? 'S' : '-')); + + // World + $info .= (($perms & 0x0004) ? 'r' : '-'); + $info .= (($perms & 0x0002) ? 'w' : '-'); + $info .= (($perms & 0x0001) ? + (($perms & 0x0200) ? 't' : 'x' ) : + (($perms & 0x0200) ? 'T' : '-')); + + } + + + $ret = '
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    r  w  x  
    '.trans('User').'
    '.trans('Group').'
    '.trans('All').'
    '; + + if ((!$ftp && is_dir($path)) ) + { + $ret .= '
    '.trans('File_Permission_Recursive').'

    +
      +
    • +
    • +
    • +
    • +
    +
    '; + } + + $ret .= '
    '; + + response($ret)->send(); + exit; + + break; + case 'get_lang': + if ( ! file_exists('lang/languages.php')) + { + response(trans('Lang_Not_Found').AddErrorLocation())->send(); + exit; + } + + $languages = include 'lang/languages.php'; + if ( ! isset($languages) || ! is_array($languages)) + { + response(trans('Lang_Not_Found').AddErrorLocation())->send(); + exit; + } + + $curr = $_SESSION['RF']['language']; + + $ret = ''; + + response($ret)->send(); + exit; + + break; + case 'change_lang': + $choosen_lang = (!empty($_POST['choosen_lang']))? $_POST['choosen_lang']:"en_EN"; + + if(array_key_exists($choosen_lang,$languages)){ + if ( ! file_exists('lang/' . $choosen_lang . '.php')) + { + response(trans('Lang_Not_Found').AddErrorLocation())->send(); + exit; + }else{ + $_SESSION['RF']['language'] = $choosen_lang; + } + } + + break; + case 'cad_preview': + if($ftp){ + $selected_file = $ftp_base_url.$upload_dir . $_GET['file']; + }else{ + $selected_file = $current_path . $_GET['file']; + + if ( ! file_exists($selected_file)) + { + response(trans('File_Not_Found').AddErrorLocation())->send(); + exit; + } + } + if($ftp){ + $url_file = $selected_file; + }else{ + $url_file = $base_url . $upload_dir . str_replace($current_path, '', $_GET["file"]); + } + + $cad_url = urlencode($url_file); + $cad_html = ""; + $ret = $cad_html; + response($ret)->send(); + break; + case 'get_file': // preview or edit + $sub_action = $_GET['sub_action']; + $preview_mode = $_GET["preview_mode"]; + + if ($sub_action != 'preview' && $sub_action != 'edit') + { + response(trans('wrong action').AddErrorLocation())->send(); + exit; + } + + if($ftp){ + $selected_file = ($sub_action == 'preview' ? $ftp_base_url.$upload_dir . $_GET['file'] : $ftp_base_url.$upload_dir . $_POST['path']); + }else{ + $selected_file = ($sub_action == 'preview' ? $current_path . $_GET['file'] : $current_path . $_POST['path']); + + if ( ! file_exists($selected_file)) + { + response(trans('File_Not_Found').AddErrorLocation())->send(); + exit; + } + } + + $info = pathinfo($selected_file); + + if ($preview_mode == 'text') + { + $is_allowed = ($sub_action == 'preview' ? $preview_text_files : $edit_text_files); + $allowed_file_exts = ($sub_action == 'preview' ? $previewable_text_file_exts : $editable_text_file_exts); + } elseif ($preview_mode == 'viewerjs') { + $is_allowed = $viewerjs_enabled; + $allowed_file_exts = $viewerjs_file_exts; + } elseif ($preview_mode == 'google') { + $is_allowed = $googledoc_enabled; + $allowed_file_exts = $googledoc_file_exts; + } + + if ( ! isset($allowed_file_exts) || ! is_array($allowed_file_exts)) + { + $allowed_file_exts = array(); + } + + if ( ! in_array($info['extension'], $allowed_file_exts) + || ! isset($is_allowed) + || $is_allowed === false + || (!$ftp && ! is_readable($selected_file)) + ) + { + response(sprintf(trans('File_Open_Edit_Not_Allowed'), ($sub_action == 'preview' ? strtolower(trans('Open')) : strtolower(trans('Edit')))).AddErrorLocation())->send(); + exit; + } + if ($sub_action == 'preview') + { + if ($preview_mode == 'text') + { + // get and sanities + $data = file_get_contents($selected_file); + $data = htmlspecialchars(htmlspecialchars_decode($data)); + $ret = ''; + + if ( ! in_array($info['extension'],$previewable_text_file_exts_no_prettify)) + { + $ret .= ''; + $ret .= '
    '.$data.'
    '; + } else { + $ret .= '
    '.$data.'
    '; + } + + } + elseif ($preview_mode == 'google' || $preview_mode == 'viewerjs') { + if($ftp){ + $url_file = $selected_file; + }else{ + $url_file = $base_url . $upload_dir . str_replace($current_path, '', $_GET["file"]); + } + + $googledoc_url = urlencode($url_file); + $googledoc_html = ""; + $ret = $googledoc_html; + } + } else { + $data = stripslashes(htmlspecialchars(file_get_contents($selected_file))); + $ret = ''; + } + + response($ret)->send(); + exit; + + break; + default: + response(trans('no action passed').AddErrorLocation())->send(); + exit; + } +} else { + response(trans('no action passed').AddErrorLocation())->send(); + exit; +} +?> \ No newline at end of file diff --git a/local/modules/Tinymce/Resources/js/tinymce/filemanager/config/.htaccess b/local/modules/Tinymce/Resources/js/tinymce/filemanager/config/.htaccess new file mode 100644 index 00000000..14249c50 --- /dev/null +++ b/local/modules/Tinymce/Resources/js/tinymce/filemanager/config/.htaccess @@ -0,0 +1 @@ +Deny from all \ No newline at end of file diff --git a/local/modules/Tinymce/Resources/js/tinymce/filemanager/config/config.php b/local/modules/Tinymce/Resources/js/tinymce/filemanager/config/config.php new file mode 100644 index 00000000..0e3a7568 --- /dev/null +++ b/local/modules/Tinymce/Resources/js/tinymce/filemanager/config/config.php @@ -0,0 +1,602 @@ +exists($webMediaEnvPath)) { + $fileSystem->mkdir($webMediaEnvPath.DS.'upload'); + $fileSystem->mkdir($webMediaEnvPath.DS.'thumbs'); + } + } else { + if (false === $fileSystem->exists($webMediaPath)) { + $fileSystem->mkdir($webMediaPath.DS.'upload'); + $fileSystem->mkdir($webMediaPath.DS.'thumbs'); + } + } +} + +$env = getenv('THELIA_ENV') ?: 'prod'; + +if (file_exists(__DIR__.'/../../../../../../../../core/vendor/autoload.php')) { + // Symlinked with std install + require_once __DIR__.'/../../../../../../../../core/vendor/autoload.php'; +} elseif (file_exists(__DIR__.'/../../../../core/vendor/autoload.php')) { + // Hard copy with std install + require_once __DIR__.'/../../../../core/vendor/autoload.php'; +} elseif (file_exists(__DIR__.'/../../../../../../../../bootstrap.php')) { + // Symlinked with thelia-project + require_once __DIR__.'/../../../../../../../../bootstrap.php'; +} elseif (file_exists(__DIR__.'/../../../../bootstrap.php')) { + // Hard copy with thelia-project + require_once __DIR__.'/../../../../bootstrap.php'; +} + +/** @var Request $request */ +$request = Request::createFromGlobals(); + +$thelia = new Thelia($env, false); + +$thelia->boot(); + +/** @var \Symfony\Component\DependencyInjection\ContainerInterface $container */ +$container = $thelia->getContainer(); + +$eventDispatcher = $container->get('event_dispatcher'); +$container->get('thelia.translator'); +$container->get('thelia.url.manager'); +$container->set('request', $request); +$container->get('request_stack')->push($request); +$event = new \Thelia\Core\Event\SessionEvent(THELIA_CACHE_DIR.$env, false, $env); + +$eventDispatcher->dispatch(\Thelia\Core\TheliaKernelEvents::SESSION, $event); +$session = $event->getSession(); +$session->start(); +$request->setSession($session); + +/** @var \Thelia\Core\Security\SecurityContext $securityContext */ +$securityContext = $container->get('thelia.securityContext'); + +// We just check the current user has the ADMIN role. +$isGranted = $securityContext->isGranted(['ADMIN'], [], [], []); + +if (false === $isGranted) { + echo "Sorry, it seems that you're not allowed to use this function. ADMIN role is required."; + + exit; +} + +//------------------------------------------------------------------------------ +// DO NOT COPY THESE VARIABLES IN FOLDERS config.php FILES +//------------------------------------------------------------------------------ + +//********************** +//Path configuration +//********************** + +// In this configuration the media folder is located in the /web directory. + +// base url of site (without final /). if you prefer relative urls leave empty. +$base_url = rtrim(ConfigQuery::getConfiguredShopUrl(), '/'); + +// Argh, url_site is not defined ?! +if (empty($base_url)) { + // A we did not used the router to access this dialog, we cannot use the URL class. Use the good old method. + $base_url = $request->getSchemeAndHttpHost().preg_replace('!/tinymce/filemanager/dialog.php.*$!', '', $_SERVER['REQUEST_URI']); +} + +//Check for backward compatibility +if ($env !== "prod") { + // path from base_url to base of upload folder for current env (with start and final /) + $upload_dir = '/media/'.$env.'/upload/'; + + // path from base_url to base of upload folder for current env (with start and final /) + $thumbs_dir = '/media/'.$env.'/thumbs/'; + + // path to file manager folder to upload folder for current env (with final /) + $current_path = THELIA_WEB_DIR.'media'.DS.$env.DS.'upload'.DS; + + // path to file manager folder to thumbs folder for current env (with final /) + // WARNING: thumbs folder should not be inside the upload folder + $thumbs_base_path = THELIA_WEB_DIR.'media'.DS.$env.DS.'thumbs'.DS; +} else { + // path from base_url to base of upload folder (with start and final /) + $upload_dir = '/media/upload/'; + + // path from base_url to base of upload folder (with start and final /) + $thumbs_dir = '/media/thumbs/'; + + // path to file manager folder to upload folder (with final /) + $current_path = THELIA_WEB_DIR.'media'.DS.'upload'.DS; + + // path to file manager folder to thumbs folder (with final /) + // WARNING: thumbs folder should not be inside the upload folder + $thumbs_base_path = THELIA_WEB_DIR.'media'.DS.'thumbs'.DS; +} + +generateFolder($env); + +// path from base_url to filemanager folder (with start and final /) +$filemanager_dir = '/tinymce/filemanager/'; + +// Set the language to the back-office current language, if it is available +$current_locale = $request->getSession()->getLang()->getLocale(); + +if (file_exists(__DIR__.DS.'..'.DS.'lang.'.DS.$current_locale.'.php')) { + $default_language = $current_locale; +} else { + $default_language = 'en_EN'; +} + + +/* +|-------------------------------------------------------------------------- +| Optional security +|-------------------------------------------------------------------------- +| +| if set to true only those will access RF whose url contains the access key(akey) like: +| +| in tinymce a new parameter added: filemanager_access_key:"myPrivateKey" +| example tinymce config: +| +| tiny init ... +| external_filemanager_path:"../filemanager/", +| filemanager_title:"Filemanager" , +| filemanager_access_key:"myPrivateKey" , +| ... +| +*/ + +define('USE_ACCESS_KEYS', false); // TRUE or FALSE + +/* +|-------------------------------------------------------------------------- +| DON'T COPY THIS VARIABLES IN FOLDERS config.php FILES +|-------------------------------------------------------------------------- +*/ + +define('DEBUG_ERROR_MESSAGE', false); // TRUE or FALSE + +/* +|-------------------------------------------------------------------------- +| Path configuration +|-------------------------------------------------------------------------- +| In this configuration the folder tree is +| root +| |- source <- upload folder +| |- thumbs <- thumbnail folder [must have write permission (755)] +| |- filemanager +| |- js +| | |- tinymce +| | | |- plugins +| | | | |- responsivefilemanager +| | | | | |- plugin.min.js +*/ + +$config = array( + + /* + |-------------------------------------------------------------------------- + | DON'T TOUCH (base url (only domain) of site). + |-------------------------------------------------------------------------- + | + | without final / (DON'T TOUCH) + | + */ + 'base_url' => $base_url, + + /* + |-------------------------------------------------------------------------- + | path from base_url to base of upload folder + |-------------------------------------------------------------------------- + | + | with start and final / + | + */ + 'upload_dir' => $upload_dir, + /* + |-------------------------------------------------------------------------- + | relative path from filemanager folder to upload folder + |-------------------------------------------------------------------------- + | + | with final / + | + */ + 'current_path' => $current_path, + + /* + |-------------------------------------------------------------------------- + | relative path from filemanager folder to thumbs folder + |-------------------------------------------------------------------------- + | + | with final / + | DO NOT put inside upload folder + | + */ + 'thumbs_base_path' => $thumbs_base_path, + + + /* + |-------------------------------------------------------------------------- + | FTP configuration BETA VERSION + |-------------------------------------------------------------------------- + | + | If you want enable ftp use write these parametres otherwise leave empty + | Remember to set base_url properly to point in the ftp server domain and + | upload dir will be ftp_base_folder + upload_dir so without final / + | + */ + 'ftp_host' => false, + 'ftp_user' => "user", + 'ftp_pass' => "pass", + 'ftp_base_folder' => "base_folder", + 'ftp_base_url' => "http://site to ftp root", + /* -------------------------------------------------------------------------- + | path from ftp_base_folder to base of thumbs folder with start and final | + |--------------------------------------------------------------------------*/ + 'ftp_thumbs_dir' => '/thumbs/', + 'ftp_ssl' => false, + 'ftp_port' => 21, + + + // 'ftp_host' => "s108707.gridserver.com", + // 'ftp_user' => "test@responsivefilemanager.com", + // 'ftp_pass' => "Test.1234", + // 'ftp_base_folder' => "/domains/responsivefilemanager.com/html", + + + /* + |-------------------------------------------------------------------------- + | Access keys + |-------------------------------------------------------------------------- + | + | add access keys eg: array('myPrivateKey', 'someoneElseKey'); + | keys should only containt (a-z A-Z 0-9 \ . _ -) characters + | if you are integrating lets say to a cms for admins, i recommend making keys randomized something like this: + | $username = 'Admin'; + | $salt = 'dsflFWR9u2xQa' (a hard coded string) + | $akey = md5($username.$salt); + | DO NOT use 'key' as access key! + | Keys are CASE SENSITIVE! + | + */ + + 'access_keys' => array(), + + //-------------------------------------------------------------------------------------------------------- + // YOU CAN COPY AND CHANGE THESE VARIABLES INTO FOLDERS config.php FILES TO CUSTOMIZE EACH FOLDER OPTIONS + //-------------------------------------------------------------------------------------------------------- + + /* + |-------------------------------------------------------------------------- + | Maximum size of all files in source folder + |-------------------------------------------------------------------------- + | + | in Megabytes + | + */ + 'MaxSizeTotal' => false, + + /* + |-------------------------------------------------------------------------- + | Maximum upload size + |-------------------------------------------------------------------------- + | + | in Megabytes + | + */ + 'MaxSizeUpload' => 100, + + /* + |-------------------------------------------------------------------------- + | File and Folder permission + |-------------------------------------------------------------------------- + | + */ + 'fileFolderPermission' => 0755, + + + /* + |-------------------------------------------------------------------------- + | default language file name + |-------------------------------------------------------------------------- + */ + 'default_language' => $default_language, + + /* + |-------------------------------------------------------------------------- + | Icon theme + |-------------------------------------------------------------------------- + | + | Default available: ico and ico_dark + | Can be set to custom icon inside filemanager/img + | + */ + 'icon_theme' => "ico", + + + //Show or not total size in filemanager (is possible to greatly increase the calculations) + 'show_total_size' => false, + //Show or not show folder size in list view feature in filemanager (is possible, if there is a large folder, to greatly increase the calculations) + 'show_folder_size' => false, + //Show or not show sorting feature in filemanager + 'show_sorting_bar' => true, + //Show or not show filters button in filemanager + 'show_filter_buttons' => true, + //Show or not language selection feature in filemanager + 'show_language_selection' => true, + //active or deactive the transliteration (mean convert all strange characters in A..Za..z0..9 characters) + 'transliteration' => false, + //convert all spaces on files name and folders name with $replace_with variable + 'convert_spaces' => false, + //convert all spaces on files name and folders name this value + 'replace_with' => "_", + //convert to lowercase the files and folders name + 'lower_case' => false, + + //Add ?484899493349 (time value) to returned images to prevent cache + 'add_time_to_img' => false, + + // -1: There is no lazy loading at all, 0: Always lazy-load images, 0+: The minimum number of the files in a directory + // when lazy loading should be turned on. + 'lazy_loading_file_number_threshold' => -1, + + + //******************************************* + //Images limit and resizing configuration + //******************************************* + + // set maximum pixel width and/or maximum pixel height for all images + // If you set a maximum width or height, oversized images are converted to those limits. Images smaller than the limit(s) are unaffected + // if you don't need a limit set both to 0 + 'image_max_width' => 0, + 'image_max_height' => 0, + 'image_max_mode' => 'auto', + /* + # $option: 0 / exact = defined size; + # 1 / portrait = keep aspect set height; + # 2 / landscape = keep aspect set width; + # 3 / auto = auto; + # 4 / crop= resize and crop; + */ + + //Automatic resizing // + // If you set $image_resizing to TRUE the script converts all uploaded images exactly to image_resizing_width x image_resizing_height dimension + // If you set width or height to 0 the script automatically calculates the other dimension + // Is possible that if you upload very big images the script not work to overcome this increase the php configuration of memory and time limit + 'image_resizing' => false, + 'image_resizing_width' => 0, + 'image_resizing_height' => 0, + 'image_resizing_mode' => 'auto', // same as $image_max_mode + 'image_resizing_override' => false, + // If set to TRUE then you can specify bigger images than $image_max_width & height otherwise if image_resizing is + // bigger than $image_max_width or height then it will be converted to those values + + + //****************** + // + // WATERMARK IMAGE + // + //Watermark url or false + 'image_watermark' => false, + # Could be a pre-determined position such as: + # tl = top left, + # t = top (middle), + # tr = top right, + # l = left, + # m = middle, + # r = right, + # bl = bottom left, + # b = bottom (middle), + # br = bottom right + # Or, it could be a co-ordinate position such as: 50x100 + 'image_watermark_position' => 'br', + # padding: If using a pre-determined position you can + # adjust the padding from the edges by passing an amount + # in pixels. If using co-ordinates, this value is ignored. + 'image_watermark_padding' => 0, + + //****************** + // Default layout setting + // + // 0 => boxes + // 1 => detailed list (1 column) + // 2 => columns list (multiple columns depending on the width of the page) + // YOU CAN ALSO PASS THIS PARAMETERS USING SESSION VAR => $_SESSION['RF']["VIEW"]= + // + //****************** + 'default_view' => 0, + + //set if the filename is truncated when overflow first row + 'ellipsis_title_after_first_row' => true, + + //************************* + //Permissions configuration + //****************** + 'delete_files' => true, + 'create_folders' => true, + 'delete_folders' => true, + 'upload_files' => true, + 'rename_files' => true, + 'rename_folders' => true, + 'duplicate_files' => true, + 'copy_cut_files' => true, // for copy/cut files + 'copy_cut_dirs' => true, // for copy/cut directories + 'chmod_files' => true, // change file permissions + 'chmod_dirs' => true, // change folder permissions + 'preview_text_files' => true, // eg.: txt, log etc. + 'edit_text_files' => true, // eg.: txt, log etc. + 'create_text_files' => true, // only create files with exts. defined in $editable_text_file_exts + + // you can preview these type of files if $preview_text_files is true + 'previewable_text_file_exts' => array( "bsh", "c","css", "cc", "cpp", "cs", "csh", "cyc", "cv", "htm", "html", "java", "js", "m", "mxml", "perl", "pl", "pm", "py", "rb", "sh", "xhtml", "xml","xsl" ), + 'previewable_text_file_exts_no_prettify' => array( 'txt', 'log' ), + + // you can edit these type of files if $edit_text_files is true (only text based files) + // you can create these type of files if $create_text_files is true (only text based files) + // if you want you can add html,css etc. + // but for security reasons it's NOT RECOMMENDED! + 'editable_text_file_exts' => array( 'txt', 'log', 'xml', 'html', 'css', 'htm', 'js' ), + + // Preview with Google Documents + 'googledoc_enabled' => true, + 'googledoc_file_exts' => array( 'doc', 'docx', 'xls', 'xlsx', 'ppt', 'pptx' ), + + // Preview with Viewer.js + 'viewerjs_enabled' => true, + 'viewerjs_file_exts' => array( 'pdf', 'odt', 'odp', 'ods' ), + + // defines size limit for paste in MB / operation + // set 'FALSE' for no limit + 'copy_cut_max_size' => 100, + // defines file count limit for paste / operation + // set 'FALSE' for no limit + 'copy_cut_max_count' => 200, + //IF any of these limits reached, operation won't start and generate warning + + //********************** + //Allowed extensions (lowercase insert) + //********************** + 'ext_img' => array( 'jpg', 'jpeg', 'png', 'gif', 'bmp', 'tiff', 'svg' ), //Images + 'ext_file' => array( 'doc', 'docx', 'rtf', 'pdf', 'xls', 'xlsx', 'txt', 'csv', 'html', 'xhtml', 'psd', 'sql', 'log', 'fla', 'xml', 'ade', 'adp', 'mdb', 'accdb', 'ppt', 'pptx', 'odt', 'ots', 'ott', 'odb', 'odg', 'otp', 'otg', 'odf', 'ods', 'odp', 'css', 'ai', 'kmz','dwg', 'dxf', 'hpgl', 'plt', 'spl', 'step', 'stp', 'iges', 'igs', 'sat', 'cgm'), //Files + 'ext_video' => array( 'mov', 'mpeg', 'm4v', 'mp4', 'avi', 'mpg', 'wma', "flv", "webm" ), //Video + 'ext_music' => array( 'mp3', 'mpga', 'm4a', 'ac3', 'aiff', 'mid', 'ogg', 'wav' ), //Audio + 'ext_misc' => array( 'zip', 'rar', 'gz', 'tar', 'iso', 'dmg' ), //Archives + + /****************** + * AVIARY config + *******************/ + 'aviary_active' => true, + 'aviary_apiKey' => "2444282ef4344e3dacdedc7a78f8877d", + 'aviary_language' => "en", + 'aviary_theme' => "light", + 'aviary_tools' => "all", + 'aviary_maxSize' => "1400", + // Add or modify the Aviary options below as needed - they will be json encoded when added to the configuration so arrays can be utilized as needed + + //The filter and sorter are managed through both javascript and php scripts because if you have a lot of + //file in a folder the javascript script can't sort all or filter all, so the filemanager switch to php script. + //The plugin automatic swich javascript to php when the current folder exceeds the below limit of files number + 'file_number_limit_js' => 500, + + //********************** + // Hidden files and folders + //********************** + // set the names of any folders you want hidden (eg "hidden_folder1", "hidden_folder2" ) Remember all folders with these names will be hidden (you can set any exceptions in config.php files on folders) + 'hidden_folders' => array(), + // set the names of any files you want hidden. Remember these names will be hidden in all folders (eg "this_document.pdf", "that_image.jpg" ) + 'hidden_files' => array( 'config.php' ), + + /******************* + * URL upload + *******************/ + 'url_upload' => true, + + /******************* + * JAVA upload + *******************/ + 'java_upload' => true, + 'JAVAMaxSizeUpload' => 200, //Gb + + + //************************************ + //Thumbnail for external use creation + //************************************ + + + // New image resized creation with fixed path from filemanager folder after uploading (thumbnails in fixed mode) + // If you want create images resized out of upload folder for use with external script you can choose this method, + // You can create also more than one image at a time just simply add a value in the array + // Remember than the image creation respect the folder hierarchy so if you are inside source/test/test1/ the new image will create at + // path_from_filemanager/test/test1/ + // PS if there isn't write permission in your destination folder you must set it + // + 'fixed_image_creation' => false, //activate or not the creation of one or more image resized with fixed path from filemanager folder + 'fixed_path_from_filemanager' => array( '../test/', '../test1/' ), //fixed path of the image folder from the current position on upload folder + 'fixed_image_creation_name_to_prepend' => array( '', 'test_' ), //name to prepend on filename + 'fixed_image_creation_to_append' => array( '_test', '' ), //name to appendon filename + 'fixed_image_creation_width' => array( 300, 400 ), //width of image (you can leave empty if you set height) + 'fixed_image_creation_height' => array( 200, '' ), //height of image (you can leave empty if you set width) + /* + # $option: 0 / exact = defined size; + # 1 / portrait = keep aspect set height; + # 2 / landscape = keep aspect set width; + # 3 / auto = auto; + # 4 / crop= resize and crop; + */ + 'fixed_image_creation_option' => array( 'crop', 'auto' ), //set the type of the crop + + + // New image resized creation with relative path inside to upload folder after uploading (thumbnails in relative mode) + // With Responsive filemanager you can create automatically resized image inside the upload folder, also more than one at a time + // just simply add a value in the array + // The image creation path is always relative so if i'm inside source/test/test1 and I upload an image, the path start from here + // + 'relative_image_creation' => false, //activate or not the creation of one or more image resized with relative path from upload folder + 'relative_path_from_current_pos' => array( './', './' ), //relative path of the image folder from the current position on upload folder + 'relative_image_creation_name_to_prepend' => array( '', '' ), //name to prepend on filename + 'relative_image_creation_name_to_append' => array( '_thumb', '_thumb1' ), //name to append on filename + 'relative_image_creation_width' => array( 300, 400 ), //width of image (you can leave empty if you set height) + 'relative_image_creation_height' => array( 200, '' ), //height of image (you can leave empty if you set width) + /* + # $option: 0 / exact = defined size; + # 1 / portrait = keep aspect set height; + # 2 / landscape = keep aspect set width; + # 3 / auto = auto; + # 4 / crop= resize and crop; + */ + 'relative_image_creation_option' => array( 'crop', 'crop' ), //set the type of the crop + + + // Remember text filter after close filemanager for future session + 'remember_text_filter' => false, + +); + +return array_merge( + $config, + array( + 'MaxSizeUpload' => ((int)(ini_get('post_max_size')) < $config['MaxSizeUpload']) + ? (int)(ini_get('post_max_size')) : $config['MaxSizeUpload'], + 'ext'=> array_merge( + $config['ext_img'], + $config['ext_file'], + $config['ext_misc'], + $config['ext_video'], + $config['ext_music'] + ), + // For a list of options see: https://developers.aviary.com/docs/web/setup-guide#constructor-config + 'aviary_defaults_config' => array( + 'apiKey' => $config['aviary_apiKey'], + 'language' => $config['aviary_language'], + 'theme' => $config['aviary_theme'], + 'tools' => $config['aviary_tools'], + 'maxSize' => $config['aviary_maxSize'] + ), + ) +); +?> diff --git a/local/modules/Tinymce/Resources/js/tinymce/filemanager/css/style.css b/local/modules/Tinymce/Resources/js/tinymce/filemanager/css/style.css new file mode 100644 index 00000000..bdda797d --- /dev/null +++ b/local/modules/Tinymce/Resources/js/tinymce/filemanager/css/style.css @@ -0,0 +1,36 @@ +/*! + * Bootstrap v2.3.1 + * + * Copyright 2012 Twitter, Inc + * Licensed under the Apache License v2.0 + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Designed and built with all the love in the world @twitter by @mdo and @fat. + */article,aside,details,figcaption,figure,footer,header,hgroup,nav,section{display:block}audio,canvas,video{display:inline-block}audio:not([controls]){display:none}html{-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}a:focus{outline:#333 dotted thin;outline:-webkit-focus-ring-color auto;outline-offset:-2px}a:active,a:hover{outline:0}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}img{max-width:100%;height:auto;vertical-align:middle;border:0;-ms-interpolation-mode:bicubic}#map_canvas img,.google-maps img{max-width:none}button,input,select,textarea{margin:0;font-size:100%;vertical-align:middle}button::-moz-focus-inner,input::-moz-focus-inner{padding:0;border:0}button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}button,input[type=button],input[type=checkbox],input[type=radio],input[type=reset],input[type=submit],label,select{cursor:pointer}input[type=search]{box-sizing:content-box;-webkit-appearance:textfield}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}textarea{overflow:auto}@media print{*{text-shadow:none!important;color:#000!important;background:0 0!important;box-shadow:none!important}a,a:visited{text-decoration:underline}a[href]:after{content:" (" attr(href) ")"}abbr[title]:after{content:" (" attr(title) ")"}.ir a:after,a[href^="#"]:after,a[href^="javascript:"]:after{content:""}blockquote,pre{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}img,tr{page-break-inside:avoid}img{max-width:100%!important}@page{margin:.5cm}h2,h3,p{orphans:3;widows:3}h2,h3{page-break-after:avoid}}body{line-height:20px;color:#333;background-color:#fff}a:focus,a:hover{color:#005580;text-decoration:underline}.img-rounded{border-radius:6px}.img-polaroid{padding:4px;background-color:#fff;border:1px solid #ccc;border:1px solid rgba(0,0,0,.2);box-shadow:0 1px 3px rgba(0,0,0,.1)}.img-circle{border-radius:500px}.row{margin-left:-20px}.row:after,.row:before{display:table;content:"";line-height:0}.row:after{clear:both}[class*=span]{float:left;min-height:1px;margin-left:20px}.container,.navbar-fixed-bottom .container,.navbar-fixed-top .container,.navbar-static-top .container,.span12{width:940px}.span11{width:860px}.span10{width:780px}.span9{width:700px}.span8{width:620px}.span7{width:540px}.span6{width:460px}.span5{width:380px}.span4{width:300px}.span3{width:220px}.span2{width:140px}.span1{width:60px}.offset12{margin-left:980px}.offset11{margin-left:900px}.offset10{margin-left:820px}.offset9{margin-left:740px}.offset8{margin-left:660px}.offset7{margin-left:580px}.offset6{margin-left:500px}.offset5{margin-left:420px}.offset4{margin-left:340px}.offset3{margin-left:260px}.offset2{margin-left:180px}.offset1{margin-left:100px}.row-fluid{width:100%}.row-fluid:after,.row-fluid:before{display:table;content:"";line-height:0}.row-fluid:after{clear:both}.row-fluid [class*=span]{display:block;width:100%;min-height:30px;box-sizing:border-box;float:left;margin-left:2.12765957%}.row-fluid [class*=span]:first-child{margin-left:0}.row-fluid .controls-row [class*=span]+[class*=span]{margin-left:2.12765957%}.row-fluid .span12{width:100%}.row-fluid .span11{width:91.4893617%}.row-fluid .span10{width:82.9787234%}.row-fluid .span9{width:74.46808511%}.row-fluid .span8{width:65.95744681%}.row-fluid .span7{width:57.44680851%}.row-fluid .span6{width:48.93617021%}.row-fluid .span5{width:40.42553191%}.row-fluid .span4{width:31.91489362%}.row-fluid .span3{width:23.40425532%}.row-fluid .span2{width:14.89361702%}.row-fluid .span1{width:6.38297872%}.row-fluid .offset12{margin-left:104.25531915%}.row-fluid .offset12:first-child{margin-left:102.12765957%}.row-fluid .offset11{margin-left:95.74468085%}.row-fluid .offset11:first-child{margin-left:93.61702128%}.row-fluid .offset10{margin-left:87.23404255%}.row-fluid .offset10:first-child{margin-left:85.10638298%}.row-fluid .offset9{margin-left:78.72340426%}.row-fluid .offset9:first-child{margin-left:76.59574468%}.row-fluid .offset8{margin-left:70.21276596%}.row-fluid .offset8:first-child{margin-left:68.08510638%}.row-fluid .offset7{margin-left:61.70212766%}.row-fluid .offset7:first-child{margin-left:59.57446809%}.row-fluid .offset6{margin-left:53.19148936%}.row-fluid .offset6:first-child{margin-left:51.06382979%}.row-fluid .offset5{margin-left:44.68085106%}.row-fluid .offset5:first-child{margin-left:42.55319149%}.row-fluid .offset4{margin-left:36.17021277%}.row-fluid .offset4:first-child{margin-left:34.04255319%}.row-fluid .offset3{margin-left:27.65957447%}.row-fluid .offset3:first-child{margin-left:25.53191489%}.row-fluid .offset2{margin-left:19.14893617%}.row-fluid .offset2:first-child{margin-left:17.0212766%}.row-fluid .offset1{margin-left:10.63829787%}.row-fluid .offset1:first-child{margin-left:8.5106383%}.row-fluid [class*=span].hide,[class*=span].hide{display:none}.row-fluid [class*=span].pull-right,[class*=span].pull-right{float:right}.container{margin-right:auto;margin-left:auto}.container:after,.container:before{display:table;content:"";line-height:0}.container:after{clear:both}.container-fluid:after,.container-fluid:before{display:table;content:"";line-height:0}.container-fluid:after{clear:both}p{margin:0 0 10px}.lead{margin-bottom:20px;font-size:21px;font-weight:200;line-height:30px}small{font-size:85%}strong{font-weight:700}em{font-style:italic}cite{font-style:normal}.muted{color:#999}a.muted:focus,a.muted:hover{color:grey}.text-warning{color:#c09853}a.text-warning:focus,a.text-warning:hover{color:#a47e3c}.text-error{color:#b94a48}a.text-error:focus,a.text-error:hover{color:#953b39}.text-info{color:#3a87ad}a.text-info:focus,a.text-info:hover{color:#2d6987}.text-success{color:#468847}a.text-success:focus,a.text-success:hover{color:#356635}.text-left{text-align:left}.text-right{text-align:right}h1,h2,h3,h4,h5,h6{margin:10px 0;font-family:inherit;font-weight:700;line-height:20px;color:inherit;text-rendering:optimizelegibility}h1 small,h2 small,h3 small,h4 small,h5 small,h6 small{font-weight:400;line-height:1;color:#999}h1,h2,h3{line-height:40px}h1{font-size:38.5px}h2{font-size:31.5px}h5{font-size:14px}h6{font-size:11.9px}h1 small{font-size:24.5px}h2 small{font-size:17.5px}h3 small,h4 small{font-size:14px}.page-header{padding-bottom:9px;margin:20px 0 30px;border-bottom:1px solid #eee}ol,ul{padding:0;margin:0 0 10px 25px}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}li{line-height:20px}ol.inline,ol.unstyled,ul.inline,ul.unstyled{margin-left:0;list-style:none}ol.inline>li,ul.inline>li{display:inline-block;padding-left:5px;padding-right:5px}dl{margin-bottom:20px}dd,dt{line-height:20px}dt{font-weight:700}dd{margin-left:10px}.dl-horizontal:after,.dl-horizontal:before{display:table;content:"";line-height:0}.dl-horizontal:after{clear:both}.dl-horizontal dt{float:left;width:160px;clear:left;text-align:right;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.dl-horizontal dd{margin-left:180px}hr{margin:20px 0;border:0;border-top:1px solid #eee;border-bottom:1px solid #fff}abbr[data-original-title],abbr[title]{cursor:help;border-bottom:1px dotted #999}abbr.initialism{font-size:90%;text-transform:uppercase}blockquote{padding:0 0 0 15px;margin:0 0 20px;border-left:5px solid #eee}blockquote p{margin-bottom:0;font-size:17.5px;font-weight:300;line-height:1.25}blockquote small{display:block;line-height:20px;color:#999}blockquote small:before{content:'\2014 \00A0'}blockquote.pull-right{float:right;padding-right:15px;padding-left:0;border-right:5px solid #eee;border-left:0}blockquote.pull-right p,blockquote.pull-right small{text-align:right}blockquote.pull-right small:before{content:''}blockquote.pull-right small:after{content:'\00A0 \2014'}blockquote:after,blockquote:before,q:after,q:before{content:""}address{display:block;margin-bottom:20px;font-style:normal;line-height:20px}code,pre{padding:0 3px 2px;font-family:Monaco,Menlo,Consolas,"Courier New",monospace;font-size:12px;color:#333;border-radius:3px}code{padding:2px 4px;color:#d14;background-color:#f7f7f9;border:1px solid #e1e1e8;white-space:nowrap}pre{display:block;padding:9.5px;margin:0 0 10px;font-size:13px;line-height:20px;word-break:break-all;word-wrap:break-word;white-space:pre;white-space:pre-wrap;background-color:#f5f5f5;border:1px solid #ccc;border:1px solid rgba(0,0,0,.15);border-radius:4px}pre code{padding:0;color:inherit;white-space:pre;white-space:pre-wrap;background-color:transparent;border:0}.pre-scrollable{max-height:340px;overflow-y:scroll}fieldset{padding:0;margin:0;border:0}legend{display:block;width:100%;padding:0;margin-bottom:20px;font-size:21px;line-height:40px;color:#333;border:0;border-bottom:1px solid #e5e5e5}legend small{font-size:15px;color:#999}button,input,label,select,textarea{font-size:14px;font-weight:400;line-height:20px}button,input,select,textarea{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif}label{display:block;margin-bottom:5px}.uneditable-input,input[type=color],input[type=date],input[type=datetime-local],input[type=datetime],input[type=email],input[type=month],input[type=number],input[type=password],input[type=search],input[type=tel],input[type=text],input[type=time],input[type=url],input[type=week],select,textarea{display:inline-block;height:20px;padding:4px 6px;margin-bottom:10px;font-size:14px;line-height:20px;color:#555;border-radius:4px;vertical-align:middle}.uneditable-input,input,textarea{width:206px}textarea{height:auto}.uneditable-input,input[type=color],input[type=date],input[type=datetime-local],input[type=datetime],input[type=email],input[type=month],input[type=number],input[type=password],input[type=search],input[type=tel],input[type=text],input[type=time],input[type=url],input[type=week],textarea{background-color:#fff;border:1px solid #ccc;box-shadow:inset 0 1px 1px rgba(0,0,0,.075);transition:border linear .2s,box-shadow linear .2s}.uneditable-input:focus,input[type=color]:focus,input[type=date]:focus,input[type=datetime-local]:focus,input[type=datetime]:focus,input[type=email]:focus,input[type=month]:focus,input[type=number]:focus,input[type=password]:focus,input[type=search]:focus,input[type=tel]:focus,input[type=text]:focus,input[type=time]:focus,input[type=url]:focus,input[type=week]:focus,textarea:focus{border-color:rgba(82,168,236,.8);outline:0;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(82,168,236,.6)}input[type=checkbox],input[type=radio]{margin:4px 0 0;line-height:normal}input[type=button],input[type=checkbox],input[type=file],input[type=image],input[type=radio],input[type=reset],input[type=submit]{width:auto}input[type=file],select{height:30px;line-height:30px}select{width:220px;border:1px solid #ccc;background-color:#fff}select[multiple],select[size]{height:auto}input[type=checkbox]:focus,input[type=file]:focus,input[type=radio]:focus,select:focus{outline:#333 dotted thin;outline:-webkit-focus-ring-color auto;outline-offset:-2px}.uneditable-input,.uneditable-textarea{color:#999;background-color:#fcfcfc;border-color:#ccc;box-shadow:inset 0 1px 2px rgba(0,0,0,.025);cursor:not-allowed}.uneditable-input{overflow:hidden;white-space:nowrap}.uneditable-textarea{width:auto;height:auto}input:-moz-placeholder,textarea:-moz-placeholder{color:#999}input:-ms-input-placeholder,textarea:-ms-input-placeholder{color:#999}input::-webkit-input-placeholder,textarea::-webkit-input-placeholder{color:#999}.checkbox,.radio{min-height:20px;padding-left:20px}.checkbox input[type=checkbox],.radio input[type=radio]{float:left;margin-left:-20px}.controls>.checkbox:first-child,.controls>.radio:first-child{padding-top:5px}.checkbox.inline,.radio.inline{display:inline-block;padding-top:5px;margin-bottom:0;vertical-align:middle}.checkbox.inline+.checkbox.inline,.radio.inline+.radio.inline{margin-left:10px}.input-mini{width:60px}.input-small{width:90px}.input-medium{width:150px}.input-large{width:210px}.input-xlarge{width:270px}.input-xxlarge{width:530px}.row-fluid .uneditable-input[class*=span],.row-fluid input[class*=span],.row-fluid select[class*=span],.row-fluid textarea[class*=span],.uneditable-input[class*=span],input[class*=span],select[class*=span],textarea[class*=span]{float:none;margin-left:0}.input-append .uneditable-input[class*=span],.input-append input[class*=span],.input-prepend .uneditable-input[class*=span],.input-prepend input[class*=span],.row-fluid .input-append [class*=span],.row-fluid .input-prepend [class*=span],.row-fluid .uneditable-input[class*=span],.row-fluid input[class*=span],.row-fluid select[class*=span],.row-fluid textarea[class*=span]{display:inline-block}.uneditable-input,input,textarea{margin-left:0}.controls-row [class*=span]+[class*=span]{margin-left:20px}.uneditable-input.span12,input.span12,textarea.span12{width:926px}.uneditable-input.span11,input.span11,textarea.span11{width:846px}.uneditable-input.span10,input.span10,textarea.span10{width:766px}.uneditable-input.span9,input.span9,textarea.span9{width:686px}.uneditable-input.span8,input.span8,textarea.span8{width:606px}.uneditable-input.span7,input.span7,textarea.span7{width:526px}.uneditable-input.span6,input.span6,textarea.span6{width:446px}.uneditable-input.span5,input.span5,textarea.span5{width:366px}.uneditable-input.span4,input.span4,textarea.span4{width:286px}.uneditable-input.span3,input.span3,textarea.span3{width:206px}.uneditable-input.span2,input.span2,textarea.span2{width:126px}.uneditable-input.span1,input.span1,textarea.span1{width:46px}.controls-row:after,.controls-row:before{display:table;content:"";line-height:0}.controls-row:after{clear:both}.controls-row [class*=span],.row-fluid .controls-row [class*=span]{float:left}.controls-row .checkbox[class*=span],.controls-row .radio[class*=span]{padding-top:5px}input[disabled],input[readonly],select[disabled],select[readonly],textarea[disabled],textarea[readonly]{cursor:not-allowed;background-color:#eee}input[type=checkbox][disabled],input[type=checkbox][readonly],input[type=radio][disabled],input[type=radio][readonly]{background-color:transparent}.control-group.warning .checkbox,.control-group.warning .control-label,.control-group.warning .help-block,.control-group.warning .help-inline,.control-group.warning .radio,.control-group.warning input,.control-group.warning select,.control-group.warning textarea{color:#c09853}.control-group.warning input,.control-group.warning select,.control-group.warning textarea{border-color:#c09853;box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.control-group.warning input:focus,.control-group.warning select:focus,.control-group.warning textarea:focus{border-color:#a47e3c;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #dbc59e}.control-group.warning .input-append .add-on,.control-group.warning .input-prepend .add-on{color:#c09853;background-color:#fcf8e3;border-color:#c09853}.control-group.error .checkbox,.control-group.error .control-label,.control-group.error .help-block,.control-group.error .help-inline,.control-group.error .radio,.control-group.error input,.control-group.error select,.control-group.error textarea{color:#b94a48}.control-group.error input,.control-group.error select,.control-group.error textarea{border-color:#b94a48;box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.control-group.error input:focus,.control-group.error select:focus,.control-group.error textarea:focus{border-color:#953b39;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #d59392}.control-group.error .input-append .add-on,.control-group.error .input-prepend .add-on{color:#b94a48;background-color:#f2dede;border-color:#b94a48}.control-group.success .checkbox,.control-group.success .control-label,.control-group.success .help-block,.control-group.success .help-inline,.control-group.success .radio,.control-group.success input,.control-group.success select,.control-group.success textarea{color:#468847}.control-group.success input,.control-group.success select,.control-group.success textarea{border-color:#468847;box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.control-group.success input:focus,.control-group.success select:focus,.control-group.success textarea:focus{border-color:#356635;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #7aba7b}.control-group.success .input-append .add-on,.control-group.success .input-prepend .add-on{color:#468847;background-color:#dff0d8;border-color:#468847}.control-group.info .checkbox,.control-group.info .control-label,.control-group.info .help-block,.control-group.info .help-inline,.control-group.info .radio,.control-group.info input,.control-group.info select,.control-group.info textarea{color:#3a87ad}.control-group.info input,.control-group.info select,.control-group.info textarea{border-color:#3a87ad;box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.control-group.info input:focus,.control-group.info select:focus,.control-group.info textarea:focus{border-color:#2d6987;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #7ab5d3}.control-group.info .input-append .add-on,.control-group.info .input-prepend .add-on{color:#3a87ad;background-color:#d9edf7;border-color:#3a87ad}input:focus:invalid,select:focus:invalid,textarea:focus:invalid{color:#b94a48;border-color:#ee5f5b}input:focus:invalid:focus,select:focus:invalid:focus,textarea:focus:invalid:focus{border-color:#e9322d;box-shadow:0 0 6px #f8b9b7}.form-actions{padding:19px 20px 20px;margin-top:20px;margin-bottom:20px;background-color:#f5f5f5;border-top:1px solid #e5e5e5}.form-actions:after,.form-actions:before{display:table;content:"";line-height:0}.form-actions:after{clear:both}.help-block,.help-inline{color:#595959}.help-block{display:block;margin-bottom:10px}.help-inline{display:inline-block;vertical-align:middle;padding-left:5px}.input-append,.input-prepend{display:inline-block;margin-bottom:10px;vertical-align:middle;font-size:0;white-space:nowrap}.input-append .dropdown-menu,.input-append .popover,.input-append .uneditable-input,.input-append input,.input-append select,.input-prepend .dropdown-menu,.input-prepend .popover,.input-prepend .uneditable-input,.input-prepend input,.input-prepend select{font-size:14px}.input-append .uneditable-input,.input-append input,.input-append select,.input-prepend .uneditable-input,.input-prepend input,.input-prepend select{position:relative;margin-bottom:0;vertical-align:top;border-radius:0 4px 4px 0}.input-append .uneditable-input:focus,.input-append input:focus,.input-append select:focus,.input-prepend .uneditable-input:focus,.input-prepend input:focus,.input-prepend select:focus{z-index:2}.input-append .add-on,.input-prepend .add-on{display:inline-block;width:auto;height:20px;min-width:16px;padding:4px 5px;font-size:14px;font-weight:400;line-height:20px;text-align:center;text-shadow:0 1px 0 #fff;background-color:#eee;border:1px solid #ccc}.input-append .add-on,.input-append .btn,.input-append .btn-group>.dropdown-toggle,.input-prepend .add-on,.input-prepend .btn,.input-prepend .btn-group>.dropdown-toggle{vertical-align:top;border-radius:0}.input-append .active,.input-prepend .active{background-color:#a9dba9;border-color:#46a546}.input-prepend .add-on,.input-prepend .btn{margin-right:-1px}.input-append .uneditable-input,.input-append input,.input-append select,.input-prepend .add-on:first-child,.input-prepend .btn:first-child{border-radius:4px 0 0 4px}.input-append .uneditable-input+.btn-group .btn:last-child,.input-append input+.btn-group .btn:last-child,.input-append select+.btn-group .btn:last-child{border-radius:0 4px 4px 0}.input-append .add-on,.input-append .btn,.input-append .btn-group{margin-left:-1px}.input-prepend.input-append .uneditable-input,.input-prepend.input-append input,.input-prepend.input-append select{border-radius:0}.input-prepend.input-append .uneditable-input+.btn-group .btn,.input-prepend.input-append input+.btn-group .btn,.input-prepend.input-append select+.btn-group .btn{border-radius:0 4px 4px 0}.input-prepend.input-append .add-on:first-child,.input-prepend.input-append .btn:first-child{margin-right:-1px;border-radius:4px 0 0 4px}.input-prepend.input-append .add-on:last-child,.input-prepend.input-append .btn:last-child{margin-left:-1px;border-radius:0 4px 4px 0}.input-prepend.input-append .btn-group:first-child{margin-left:0}input.search-query{padding-right:14px;padding-left:14px;margin-bottom:0;border-radius:15px}.form-search .input-append .search-query{border-radius:14px 0 0 14px}.form-search .input-append .btn,.form-search .input-prepend .search-query{border-radius:0 14px 14px 0}.form-search .input-prepend .btn{border-radius:14px 0 0 14px}.form-horizontal .help-inline,.form-horizontal .input-append,.form-horizontal .input-prepend,.form-horizontal .uneditable-input,.form-horizontal input,.form-horizontal select,.form-horizontal textarea,.form-inline .help-inline,.form-inline .input-append,.form-inline .input-prepend,.form-inline .uneditable-input,.form-inline input,.form-inline select,.form-inline textarea,.form-search .help-inline,.form-search .input-append,.form-search .input-prepend,.form-search .uneditable-input,.form-search input,.form-search select,.form-search textarea{display:inline-block;margin-bottom:0;vertical-align:middle}.form-horizontal .hide,.form-inline .hide,.form-search .hide{display:none}.form-inline .btn-group,.form-inline label,.form-search .btn-group,.form-search label{display:inline-block}.form-inline .input-append,.form-inline .input-prepend,.form-search .input-append,.form-search .input-prepend{margin-bottom:0}.form-inline .checkbox,.form-inline .radio,.form-search .checkbox,.form-search .radio{padding-left:0;margin-bottom:0;vertical-align:middle}.form-inline .checkbox input[type=checkbox],.form-inline .radio input[type=radio],.form-search .checkbox input[type=checkbox],.form-search .radio input[type=radio]{float:left;margin-right:3px;margin-left:0}.control-group{margin-bottom:10px}legend+.control-group{margin-top:20px;-webkit-margin-top-collapse:separate}.form-horizontal .control-group{margin-bottom:20px}.form-horizontal .control-group:after,.form-horizontal .control-group:before{display:table;content:"";line-height:0}.form-horizontal .control-group:after{clear:both}.form-horizontal .control-label{float:left;width:160px;padding-top:5px;text-align:right}.form-horizontal .controls{margin-left:180px}.form-horizontal .help-block{margin-bottom:0}.form-horizontal .input-append+.help-block,.form-horizontal .input-prepend+.help-block,.form-horizontal .uneditable-input+.help-block,.form-horizontal input+.help-block,.form-horizontal select+.help-block,.form-horizontal textarea+.help-block{margin-top:10px}.form-horizontal .form-actions{padding-left:180px}table{max-width:100%;background-color:transparent;border-collapse:collapse;border-spacing:0}.table{width:100%;margin-bottom:20px}.table td,.table th{padding:8px;line-height:20px;text-align:left;vertical-align:top;border-top:1px solid #ddd}.table th{font-weight:700}.table thead th{vertical-align:bottom}.table caption+thead tr:first-child td,.table caption+thead tr:first-child th,.table colgroup+thead tr:first-child td,.table colgroup+thead tr:first-child th,.table thead:first-child tr:first-child td,.table thead:first-child tr:first-child th{border-top:0}.table tbody+tbody{border-top:2px solid #ddd}.table .table{background-color:#fff}.table-condensed td,.table-condensed th{padding:4px 5px}.table-bordered{border:1px solid #ddd;border-collapse:separate;border-left:0;border-radius:4px}.table-bordered td,.table-bordered th{border-left:1px solid #ddd}.table-bordered caption+tbody tr:first-child td,.table-bordered caption+tbody tr:first-child th,.table-bordered caption+thead tr:first-child th,.table-bordered colgroup+tbody tr:first-child td,.table-bordered colgroup+tbody tr:first-child th,.table-bordered colgroup+thead tr:first-child th,.table-bordered tbody:first-child tr:first-child td,.table-bordered tbody:first-child tr:first-child th,.table-bordered thead:first-child tr:first-child th{border-top:0}.table-bordered tbody:first-child tr:first-child>td:first-child,.table-bordered tbody:first-child tr:first-child>th:first-child,.table-bordered thead:first-child tr:first-child>th:first-child{border-top-left-radius:4px}.table-bordered tbody:first-child tr:first-child>td:last-child,.table-bordered tbody:first-child tr:first-child>th:last-child,.table-bordered thead:first-child tr:first-child>th:last-child{border-top-right-radius:4px}.table-bordered tbody:last-child tr:last-child>td:first-child,.table-bordered tbody:last-child tr:last-child>th:first-child,.table-bordered tfoot:last-child tr:last-child>td:first-child,.table-bordered tfoot:last-child tr:last-child>th:first-child,.table-bordered thead:last-child tr:last-child>th:first-child{border-bottom-left-radius:4px}.table-bordered tbody:last-child tr:last-child>td:last-child,.table-bordered tbody:last-child tr:last-child>th:last-child,.table-bordered tfoot:last-child tr:last-child>td:last-child,.table-bordered tfoot:last-child tr:last-child>th:last-child,.table-bordered thead:last-child tr:last-child>th:last-child{border-bottom-right-radius:4px}.table-bordered tfoot+tbody:last-child tr:last-child td:first-child{border-bottom-left-radius:0}.table-bordered tfoot+tbody:last-child tr:last-child td:last-child{border-bottom-right-radius:0}.table-bordered caption+tbody tr:first-child td:first-child,.table-bordered caption+thead tr:first-child th:first-child,.table-bordered colgroup+tbody tr:first-child td:first-child,.table-bordered colgroup+thead tr:first-child th:first-child{border-top-left-radius:4px}.table-bordered caption+tbody tr:first-child td:last-child,.table-bordered caption+thead tr:first-child th:last-child,.table-bordered colgroup+tbody tr:first-child td:last-child,.table-bordered colgroup+thead tr:first-child th:last-child{border-top-right-radius:4px}.table-striped tbody>tr:nth-child(odd)>td,.table-striped tbody>tr:nth-child(odd)>th{background-color:#f9f9f9}.table-hover tbody tr:hover>td,.table-hover tbody tr:hover>th{background-color:#f5f5f5}.row-fluid table td[class*=span],.row-fluid table th[class*=span],table td[class*=span],table th[class*=span]{display:table-cell;float:none;margin-left:0}.table td.span1,.table th.span1{float:none;width:44px;margin-left:0}.table td.span2,.table th.span2{float:none;width:124px;margin-left:0}.table td.span3,.table th.span3{float:none;width:204px;margin-left:0}.table td.span4,.table th.span4{float:none;width:284px;margin-left:0}.table td.span5,.table th.span5{float:none;width:364px;margin-left:0}.table td.span6,.table th.span6{float:none;width:444px;margin-left:0}.table td.span7,.table th.span7{float:none;width:524px;margin-left:0}.table td.span8,.table th.span8{float:none;width:604px;margin-left:0}.table td.span9,.table th.span9{float:none;width:684px;margin-left:0}.table td.span10,.table th.span10{float:none;width:764px;margin-left:0}.table td.span11,.table th.span11{float:none;width:844px;margin-left:0}.table td.span12,.table th.span12{float:none;width:924px;margin-left:0}.table tbody tr.success>td{background-color:#dff0d8}.table tbody tr.error>td{background-color:#f2dede}.table tbody tr.warning>td{background-color:#fcf8e3}.table tbody tr.info>td{background-color:#d9edf7}.table-hover tbody tr.success:hover>td{background-color:#d0e9c6}.table-hover tbody tr.error:hover>td{background-color:#ebcccc}.table-hover tbody tr.warning:hover>td{background-color:#faf2cc}.table-hover tbody tr.info:hover>td{background-color:#c4e3f3}[class*=" icon-"],[class^=icon-]{display:inline-block;width:14px;height:14px;line-height:14px;vertical-align:text-top;background-image:url(../img/glyphicons-halflings.png);background-position:14px 14px;background-repeat:no-repeat;margin-top:1px}.dropdown-menu>.active>a>[class*=" icon-"],.dropdown-menu>.active>a>[class^=icon-],.dropdown-menu>li>a:focus>[class*=" icon-"],.dropdown-menu>li>a:focus>[class^=icon-],.dropdown-menu>li>a:hover>[class*=" icon-"],.dropdown-menu>li>a:hover>[class^=icon-],.dropdown-submenu:focus>a>[class*=" icon-"],.dropdown-submenu:focus>a>[class^=icon-],.dropdown-submenu:hover>a>[class*=" icon-"],.dropdown-submenu:hover>a>[class^=icon-],.icon-white,.nav-list>.active>a>[class*=" icon-"],.nav-list>.active>a>[class^=icon-],.nav-pills>.active>a>[class*=" icon-"],.nav-pills>.active>a>[class^=icon-],.navbar-inverse .nav>.active>a>[class*=" icon-"],.navbar-inverse .nav>.active>a>[class^=icon-]{background-image:url(../img/glyphicons-halflings-white.png)}.icon-glass{background-position:0 0}.icon-music{background-position:-24px 0}.icon-search{background-position:-48px 0}.icon-envelope{background-position:-72px 0}.icon-heart{background-position:-96px 0}.icon-star{background-position:-120px 0}.icon-star-empty{background-position:-144px 0}.icon-user{background-position:-168px 0}.icon-film{background-position:-192px 0}.icon-th-large{background-position:-216px 0}.icon-th{background-position:-240px 0}.icon-th-list{background-position:-264px 0}.icon-ok{background-position:-288px 0}.icon-remove{background-position:-312px 0}.icon-zoom-in{background-position:-336px 0}.icon-zoom-out{background-position:-360px 0}.icon-off{background-position:-384px 0}.icon-signal{background-position:-408px 0}.icon-cog{background-position:-432px 0}.icon-trash{background-position:-456px 0}.icon-home{background-position:0 -24px}.icon-file{background-position:-24px -24px}.icon-time{background-position:-48px -24px}.icon-road{background-position:-72px -24px}.icon-download-alt{background-position:-96px -24px}.icon-download{background-position:-120px -24px}.icon-upload{background-position:-144px -24px}.icon-inbox{background-position:-168px -24px}.icon-play-circle{background-position:-192px -24px}.icon-repeat{background-position:-216px -24px}.icon-refresh{background-position:-240px -24px}.icon-list-alt{background-position:-264px -24px}.icon-lock{background-position:-287px -24px}.icon-flag{background-position:-312px -24px}.icon-headphones{background-position:-336px -24px}.icon-volume-off{background-position:-360px -24px}.icon-volume-down{background-position:-384px -24px}.icon-volume-up{background-position:-408px -24px}.icon-qrcode{background-position:-432px -24px}.icon-barcode{background-position:-456px -24px}.icon-tag{background-position:0 -48px}.icon-tags{background-position:-25px -48px}.icon-book{background-position:-48px -48px}.icon-bookmark{background-position:-72px -48px}.icon-print{background-position:-96px -48px}.icon-camera{background-position:-120px -48px}.icon-font{background-position:-144px -48px}.icon-bold{background-position:-167px -48px}.icon-italic{background-position:-192px -48px}.icon-text-height{background-position:-216px -48px}.icon-text-width{background-position:-240px -48px}.icon-align-left{background-position:-264px -48px}.icon-align-center{background-position:-288px -48px}.icon-align-right{background-position:-312px -48px}.icon-align-justify{background-position:-336px -48px}.icon-list{background-position:-360px -48px}.icon-indent-left{background-position:-384px -48px}.icon-indent-right{background-position:-408px -48px}.icon-facetime-video{background-position:-432px -48px}.icon-picture{background-position:-456px -48px}.icon-pencil{background-position:0 -72px}.icon-map-marker{background-position:-24px -72px}.icon-adjust{background-position:-48px -72px}.icon-tint{background-position:-72px -72px}.icon-edit{background-position:-96px -72px}.icon-share{background-position:-120px -72px}.icon-check{background-position:-144px -72px}.icon-move{background-position:-168px -72px}.icon-step-backward{background-position:-192px -72px}.icon-fast-backward{background-position:-216px -72px}.icon-backward{background-position:-240px -72px}.icon-play{background-position:-264px -72px}.icon-pause{background-position:-288px -72px}.icon-stop{background-position:-312px -72px}.icon-forward{background-position:-336px -72px}.icon-fast-forward{background-position:-360px -72px}.icon-step-forward{background-position:-384px -72px}.icon-eject{background-position:-408px -72px}.icon-chevron-left{background-position:-432px -72px}.icon-chevron-right{background-position:-456px -72px}.icon-plus-sign{background-position:0 -96px}.icon-minus-sign{background-position:-24px -96px}.icon-remove-sign{background-position:-48px -96px}.icon-ok-sign{background-position:-72px -96px}.icon-question-sign{background-position:-96px -96px}.icon-info-sign{background-position:-120px -96px}.icon-screenshot{background-position:-144px -96px}.icon-remove-circle{background-position:-168px -96px}.icon-ok-circle{background-position:-192px -96px}.icon-ban-circle{background-position:-216px -96px}.icon-arrow-left{background-position:-240px -96px}.icon-arrow-right{background-position:-264px -96px}.icon-arrow-up{background-position:-289px -96px}.icon-arrow-down{background-position:-312px -96px}.icon-share-alt{background-position:-336px -96px}.icon-resize-full{background-position:-360px -96px}.icon-resize-small{background-position:-384px -96px}.icon-plus{background-position:-408px -96px}.icon-minus{background-position:-433px -96px}.icon-asterisk{background-position:-456px -96px}.icon-exclamation-sign{background-position:0 -120px}.icon-gift{background-position:-24px -120px}.icon-leaf{background-position:-48px -120px}.icon-fire{background-position:-72px -120px}.icon-eye-open{background-position:-96px -120px}.icon-eye-close{background-position:-120px -120px}.icon-warning-sign{background-position:-144px -120px}.icon-plane{background-position:-168px -120px}.icon-calendar{background-position:-192px -120px}.icon-random{background-position:-216px -120px;width:16px}.icon-comment{background-position:-240px -120px}.icon-magnet{background-position:-264px -120px}.icon-chevron-up{background-position:-288px -120px}.icon-chevron-down{background-position:-313px -119px}.icon-retweet{background-position:-336px -120px}.icon-shopping-cart{background-position:-360px -120px}.icon-folder-close{background-position:-384px -120px;width:16px}.icon-folder-open{background-position:-408px -120px;width:16px}.icon-resize-vertical{background-position:-432px -119px}.icon-resize-horizontal{background-position:-456px -118px}.icon-hdd{background-position:0 -144px}.icon-bullhorn{background-position:-24px -144px}.icon-bell{background-position:-48px -144px}.icon-certificate{background-position:-72px -144px}.icon-thumbs-up{background-position:-96px -144px}.icon-thumbs-down{background-position:-120px -144px}.icon-hand-right{background-position:-144px -144px}.icon-hand-left{background-position:-168px -144px}.icon-hand-up{background-position:-192px -144px}.icon-hand-down{background-position:-216px -144px}.icon-circle-arrow-right{background-position:-240px -144px}.icon-circle-arrow-left{background-position:-264px -144px}.icon-circle-arrow-up{background-position:-288px -144px}.icon-circle-arrow-down{background-position:-312px -144px}.icon-globe{background-position:-336px -144px}.icon-wrench{background-position:-360px -144px}.icon-tasks{background-position:-384px -144px}.icon-filter{background-position:-408px -144px}.icon-briefcase{background-position:-432px -144px}.icon-fullscreen{background-position:-456px -144px}.dropdown,.dropup{position:relative}.dropdown-toggle:active,.open .dropdown-toggle{outline:0}.caret{display:inline-block;width:0;height:0;vertical-align:top;border-top:4px solid #000;border-right:4px solid transparent;border-left:4px solid transparent;content:""}.dropdown .caret{margin-top:8px;margin-left:2px}.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:160px;padding:5px 0;margin:2px 0 0;list-style:none;background-color:#fff;border:1px solid #ccc;border:1px solid rgba(0,0,0,.2);border-radius:6px;box-shadow:0 5px 10px rgba(0,0,0,.2);background-clip:padding-box}.dropdown-menu.pull-right{right:0;left:auto}.dropdown-menu .divider{height:1px;margin:9px 1px;overflow:hidden;background-color:#e5e5e5;border-bottom:1px solid #fff}.dropdown-menu>li>a{display:block;padding:3px 20px;clear:both;font-weight:400;line-height:20px;color:#333;white-space:nowrap}.dropdown-menu>li>a:focus,.dropdown-menu>li>a:hover,.dropdown-submenu:focus>a,.dropdown-submenu:hover>a{text-decoration:none;color:#fff;background-color:#0081c2;background-image:linear-gradient(to bottom,#08c,#0077b3);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0077b3', GradientType=0)}.dropdown-menu>.active>a,.dropdown-menu>.active>a:focus,.dropdown-menu>.active>a:hover{color:#fff;text-decoration:none;outline:0;background-color:#0081c2;background-image:linear-gradient(to bottom,#08c,#0077b3);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0077b3', GradientType=0)}.dropdown-menu>.disabled>a,.dropdown-menu>.disabled>a:focus,.dropdown-menu>.disabled>a:hover{color:#999}.dropdown-menu>.disabled>a:focus,.dropdown-menu>.disabled>a:hover{text-decoration:none;background-color:transparent;background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);cursor:default}.open>.dropdown-menu{display:block}.pull-right>.dropdown-menu{right:0;left:auto}.dropup .caret,.navbar-fixed-bottom .dropdown .caret{border-top:0;border-bottom:4px solid #000;content:""}.dropup .dropdown-menu,.navbar-fixed-bottom .dropdown .dropdown-menu{top:auto;bottom:100%;margin-bottom:1px}.dropdown-submenu{position:relative}.dropdown-submenu>.dropdown-menu{top:0;left:100%;margin-top:-6px;margin-left:-1px;border-radius:0 6px 6px}.dropdown-submenu:hover>.dropdown-menu{display:block}.dropup .dropdown-submenu>.dropdown-menu{top:auto;bottom:0;margin-top:0;margin-bottom:-2px;border-radius:5px 5px 5px 0}.dropdown-submenu>a:after{display:block;content:" ";float:right;width:0;height:0;border-color:transparent;border-style:solid;border-width:5px 0 5px 5px;border-left-color:#ccc;margin-top:5px;margin-right:-10px}.dropdown-submenu:hover>a:after{border-left-color:#fff}.dropdown-submenu.pull-left{float:none}.dropdown-submenu.pull-left>.dropdown-menu{left:-100%;margin-left:10px;border-radius:6px 0 6px 6px}.dropdown .dropdown-menu .nav-header{padding-left:20px;padding-right:20px}.typeahead{z-index:1051;margin-top:2px;border-radius:4px}.well{min-height:20px;padding:19px;margin-bottom:20px;background-color:#f5f5f5;border:1px solid #e3e3e3;border-radius:4px;box-shadow:inset 0 1px 1px rgba(0,0,0,.05)}.well blockquote{border-color:#ddd;border-color:rgba(0,0,0,.15)}.well-large{padding:24px;border-radius:6px}.well-small{padding:9px;border-radius:3px}.fade{opacity:0;transition:opacity .15s linear}.fade.in{opacity:1}.collapse{position:relative;height:0;overflow:hidden;transition:height .35s ease}.collapse.in{height:auto}.close{float:right;font-size:20px;font-weight:700;line-height:20px;color:#000;text-shadow:0 1px 0 #fff;opacity:.2;filter:alpha(opacity=20)}.close:focus,.close:hover{color:#000;text-decoration:none;cursor:pointer;opacity:.4;filter:alpha(opacity=40)}button.close{padding:0;cursor:pointer;background:0 0;border:0;-webkit-appearance:none}.btn{display:inline-block;padding:4px 12px;margin-bottom:0;font-size:14px;line-height:20px;text-align:center;vertical-align:middle;cursor:pointer;color:#333;background-color:#f5f5f5;background-image:linear-gradient(to bottom,#fff,#e6e6e6);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);border:1px solid #ccc}.btn.active,.btn.disabled,.btn:active,.btn:focus,.btn:hover,.btn[disabled]{color:#333;background-color:#e6e6e6}.btn:focus,.btn:hover{color:#333;text-decoration:none;background-position:0 -15px;transition:background-position .1s linear}.btn:focus{outline-offset:-2px}.btn.active,.btn:active{background-image:none;outline:0;box-shadow:inset 0 2px 4px rgba(0,0,0,.15),0 1px 2px rgba(0,0,0,.05)}.btn.disabled,.btn[disabled]{cursor:default;background-image:none;opacity:.65;filter:alpha(opacity=65);box-shadow:none}.btn-large{padding:11px 19px;font-size:17.5px;border-radius:6px}.btn-large [class*=" icon-"],.btn-large [class^=icon-]{margin-top:4px}.btn-small{padding:2px 10px;font-size:11.9px;border-radius:3px}.btn-small [class*=" icon-"],.btn-small [class^=icon-]{margin-top:0}.btn-mini [class*=" icon-"],.btn-mini [class^=icon-]{margin-top:-1px}.btn-mini{padding:0 6px;font-size:10.5px;border-radius:3px}.btn-block{display:block;width:100%;padding-left:0;padding-right:0;box-sizing:border-box}.btn-block+.btn-block{margin-top:5px}input[type=button].btn-block,input[type=reset].btn-block,input[type=submit].btn-block{width:100%}.btn-primary{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,.25);background-image:linear-gradient(to bottom,#08c,#04c);background-repeat:repeat-x;border-color:#04c #04c #002a80;border-color:rgba(0,0,0,.1) rgba(0,0,0,.1) rgba(0,0,0,.25);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.btn-primary.active,.btn-primary.disabled,.btn-primary:active,.btn-primary:focus,.btn-primary:hover,.btn-primary[disabled]{color:#fff}.btn-warning{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,.25);background-color:#faa732;background-image:linear-gradient(to bottom,#fbb450,#f89406);background-repeat:repeat-x;border-color:#f89406 #f89406 #ad6704;border-color:rgba(0,0,0,.1) rgba(0,0,0,.1) rgba(0,0,0,.25);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.btn-warning.active,.btn-warning.disabled,.btn-warning:active,.btn-warning:focus,.btn-warning:hover,.btn-warning[disabled]{color:#fff;background-color:#f89406}.btn-danger{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,.25);background-color:#da4f49;background-image:linear-gradient(to bottom,#ee5f5b,#bd362f);background-repeat:repeat-x;border-color:#bd362f #bd362f #802420;border-color:rgba(0,0,0,.1) rgba(0,0,0,.1) rgba(0,0,0,.25);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.btn-danger.active,.btn-danger.disabled,.btn-danger:active,.btn-danger:focus,.btn-danger:hover,.btn-danger[disabled]{color:#fff;background-color:#bd362f}.btn-success{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,.25);background-color:#5bb75b;background-image:linear-gradient(to bottom,#62c462,#51a351);background-repeat:repeat-x;border-color:#51a351 #51a351 #387038;border-color:rgba(0,0,0,.1) rgba(0,0,0,.1) rgba(0,0,0,.25);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.btn-success.active,.btn-success.disabled,.btn-success:active,.btn-success:focus,.btn-success:hover,.btn-success[disabled]{color:#fff;background-color:#51a351}.btn-info{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,.25);background-color:#49afcd;background-image:linear-gradient(to bottom,#5bc0de,#2f96b4);background-repeat:repeat-x;border-color:#2f96b4 #2f96b4 #1f6377;border-color:rgba(0,0,0,.1) rgba(0,0,0,.1) rgba(0,0,0,.25);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.btn-info.active,.btn-info.disabled,.btn-info:active,.btn-info:focus,.btn-info:hover,.btn-info[disabled]{color:#fff;background-color:#2f96b4}.btn-inverse{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,.25);background-color:#363636;background-image:linear-gradient(to bottom,#444,#222);background-repeat:repeat-x;border-color:#222 #222 #000;border-color:rgba(0,0,0,.1) rgba(0,0,0,.1) rgba(0,0,0,.25);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.btn-inverse.active,.btn-inverse.disabled,.btn-inverse:active,.btn-inverse:focus,.btn-inverse:hover,.btn-inverse[disabled]{color:#fff;background-color:#222}button.btn::-moz-focus-inner,input[type=submit].btn::-moz-focus-inner{padding:0;border:0}.btn-link,.btn-link:active,.btn-link[disabled]{background-color:transparent;background-image:none;box-shadow:none}.btn-link{border-color:transparent;cursor:pointer;color:#08c;border-radius:0}.btn-link:focus,.btn-link:hover{color:#005580;text-decoration:underline;background-color:transparent}.btn-link[disabled]:focus,.btn-link[disabled]:hover{color:#333;text-decoration:none}.btn-group{position:relative;display:inline-block;font-size:0;vertical-align:middle;white-space:nowrap}.btn-group+.btn-group{margin-left:5px}.btn-toolbar{font-size:0;margin-top:10px;margin-bottom:10px}.btn-toolbar>.btn+.btn,.btn-toolbar>.btn+.btn-group,.btn-toolbar>.btn-group+.btn{margin-left:5px}.btn-group>.btn{position:relative;border-radius:0}.btn-group>.btn+.btn{margin-left:-1px}.btn-group>.btn,.btn-group>.dropdown-menu,.btn-group>.popover{font-size:14px}.btn-group>.btn-mini{font-size:10.5px}.btn-group>.btn-small{font-size:11.9px}.btn-group>.btn-large{font-size:17.5px}.btn-group>.btn:first-child{margin-left:0;border-top-left-radius:4px;border-bottom-left-radius:4px}.btn-group>.btn:last-child,.btn-group>.dropdown-toggle{border-top-right-radius:4px;border-bottom-right-radius:4px}.btn-group>.btn.large:first-child{margin-left:0;border-top-left-radius:6px;border-bottom-left-radius:6px}.btn-group>.btn.large:last-child,.btn-group>.large.dropdown-toggle{border-top-right-radius:6px;border-bottom-right-radius:6px}.btn-group>.btn.active,.btn-group>.btn:active,.btn-group>.btn:focus,.btn-group>.btn:hover{z-index:2}.btn-group .dropdown-toggle:active,.btn-group.open .dropdown-toggle{outline:0}.btn-group>.btn+.dropdown-toggle{padding-left:8px;padding-right:8px;box-shadow:inset 1px 0 0 rgba(255,255,255,.125),inset 0 1px 0 rgba(255,255,255,.2),0 1px 2px rgba(0,0,0,.05)}.btn-group>.btn-mini+.dropdown-toggle{padding-left:5px;padding-right:5px}.btn-group>.btn-large+.dropdown-toggle{padding-left:12px;padding-right:12px}.btn-group.open .dropdown-toggle{background-image:none;box-shadow:inset 0 2px 4px rgba(0,0,0,.15),0 1px 2px rgba(0,0,0,.05)}.btn-group.open .btn.dropdown-toggle{background-color:#e6e6e6}.btn-group.open .btn-primary.dropdown-toggle{background-color:#04c}.btn-group.open .btn-warning.dropdown-toggle{background-color:#f89406}.btn-group.open .btn-danger.dropdown-toggle{background-color:#bd362f}.btn-group.open .btn-success.dropdown-toggle{background-color:#51a351}.btn-group.open .btn-info.dropdown-toggle{background-color:#2f96b4}.btn-group.open .btn-inverse.dropdown-toggle{background-color:#222}.btn .caret{margin-top:8px;margin-left:0}.btn-large .caret{margin-top:6px;border-left-width:5px;border-right-width:5px;border-top-width:5px}.btn-mini .caret,.btn-small .caret{margin-top:8px}.dropup .btn-large .caret{border-bottom-width:5px}.btn-danger .caret,.btn-info .caret,.btn-inverse .caret,.btn-primary .caret,.btn-success .caret,.btn-warning .caret{border-top-color:#fff;border-bottom-color:#fff}.btn-group-vertical{display:inline-block}.btn-group-vertical>.btn{display:block;float:none;max-width:100%;border-radius:0}.btn-group-vertical>.btn+.btn{margin-left:0;margin-top:-1px}.btn-group-vertical>.btn:first-child{border-radius:4px 4px 0 0}.btn-group-vertical>.btn:last-child{border-radius:0 0 4px 4px}.btn-group-vertical>.btn-large:first-child{border-radius:6px 6px 0 0}.btn-group-vertical>.btn-large:last-child{border-radius:0 0 6px 6px}.alert{text-shadow:0 1px 0 rgba(255,255,255,.5);background-color:#fcf8e3}.alert,.alert h4{color:#c09853}.alert h4{margin:0}.alert .close{position:relative;top:-2px;right:-21px;line-height:20px}.alert-success{background-color:#dff0d8;border-color:#d6e9c6;color:#468847}.alert-success h4{color:#468847}.alert-danger,.alert-error{background-color:#f2dede;border-color:#eed3d7;color:#b94a48}.alert-danger h4,.alert-error h4{color:#b94a48}.alert-info{background-color:#d9edf7;border-color:#bce8f1;color:#3a87ad}.alert-info h4{color:#3a87ad}.alert-block{padding-top:14px;padding-bottom:14px}.alert-block>p,.alert-block>ul{margin-bottom:0}.alert-block p+p{margin-top:5px}.nav{margin-left:0;margin-bottom:20px;list-style:none}.nav>li>a{display:block}.nav>li>a:focus,.nav>li>a:hover{text-decoration:none;background-color:#eee}.nav>li>a>img{max-width:none}.nav>.pull-right{float:right}.nav-header{display:block;padding:3px 15px;font-size:11px;font-weight:700;line-height:20px;color:#999;text-shadow:0 1px 0 rgba(255,255,255,.5);text-transform:uppercase}.nav li+.nav-header{margin-top:9px}.nav-list{padding-left:15px;padding-right:15px;margin-bottom:0}.nav-list .nav-header,.nav-list>li>a{margin-left:-15px;margin-right:-15px;text-shadow:0 1px 0 rgba(255,255,255,.5)}.nav-list>li>a{padding:3px 15px}.nav-list>.active>a,.nav-list>.active>a:focus,.nav-list>.active>a:hover{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,.2);background-color:#08c}.nav-list [class*=" icon-"],.nav-list [class^=icon-]{margin-right:2px}.nav-list .divider{height:1px;margin:9px 1px;overflow:hidden;background-color:#e5e5e5;border-bottom:1px solid #fff}.nav-pills:after,.nav-pills:before,.nav-tabs:after,.nav-tabs:before{display:table;content:"";line-height:0}.nav-pills:after,.nav-tabs:after{clear:both}.nav-pills>li,.nav-tabs>li{float:left}.nav-pills>li>a,.nav-tabs>li>a{padding-right:12px;padding-left:12px;margin-right:2px;line-height:14px}.nav-tabs{border-bottom:1px solid #ddd}.nav-tabs>li{margin-bottom:-1px}.nav-tabs>li>a{padding-top:8px;padding-bottom:8px;line-height:20px;border:1px solid transparent;border-radius:4px 4px 0 0}.nav-tabs>li>a:focus,.nav-tabs>li>a:hover{border-color:#eee #eee #ddd}.nav-tabs>.active>a,.nav-tabs>.active>a:focus,.nav-tabs>.active>a:hover{color:#555;background-color:#fff;border:1px solid #ddd;border-bottom-color:transparent;cursor:default}.nav-pills>li>a{padding-top:8px;padding-bottom:8px;margin-top:2px;margin-bottom:2px;border-radius:5px}.nav-pills>.active>a,.nav-pills>.active>a:focus,.nav-pills>.active>a:hover{color:#fff;background-color:#08c}.nav-stacked>li{float:none}.nav-stacked>li>a{margin-right:0}.nav-tabs.nav-stacked{border-bottom:0}.nav-tabs.nav-stacked>li>a{border:1px solid #ddd;border-radius:0}.nav-tabs.nav-stacked>li:first-child>a{border-top-right-radius:4px;border-top-left-radius:4px}.nav-tabs.nav-stacked>li:last-child>a{border-bottom-right-radius:4px;border-bottom-left-radius:4px}.nav-tabs.nav-stacked>li>a:focus,.nav-tabs.nav-stacked>li>a:hover{border-color:#ddd;z-index:2}.nav-pills.nav-stacked>li>a{margin-bottom:3px}.nav-pills.nav-stacked>li:last-child>a{margin-bottom:1px}.nav-tabs .dropdown-menu{border-radius:0 0 6px 6px}.nav-pills .dropdown-menu{border-radius:6px}.nav .dropdown-toggle .caret{border-top-color:#08c;border-bottom-color:#08c;margin-top:6px}.nav .dropdown-toggle:focus .caret,.nav .dropdown-toggle:hover .caret{border-top-color:#005580;border-bottom-color:#005580}.nav-tabs .dropdown-toggle .caret{margin-top:8px}.nav .active .dropdown-toggle .caret{border-top-color:#fff;border-bottom-color:#fff}.nav-tabs .active .dropdown-toggle .caret{border-top-color:#555;border-bottom-color:#555}.nav>.dropdown.active>a:focus,.nav>.dropdown.active>a:hover{cursor:pointer}.nav-pills .open .dropdown-toggle,.nav-tabs .open .dropdown-toggle,.nav>li.dropdown.open.active>a:focus,.nav>li.dropdown.open.active>a:hover{color:#fff;background-color:#999;border-color:#999}.nav li.dropdown.open .caret,.nav li.dropdown.open a:focus .caret,.nav li.dropdown.open a:hover .caret,.nav li.dropdown.open.active .caret{border-top-color:#fff;border-bottom-color:#fff;opacity:1;filter:alpha(opacity=100)}.tabs-stacked .open>a:focus,.tabs-stacked .open>a:hover{border-color:#999}.tabbable:after,.tabbable:before{display:table;content:"";line-height:0}.tabbable:after{clear:both}.tab-content{overflow:auto}.tabs-below>.nav-tabs,.tabs-left>.nav-tabs,.tabs-right>.nav-tabs{border-bottom:0}.pill-content>.pill-pane,.tab-content>.tab-pane{display:none}.pill-content>.active,.tab-content>.active{display:block}.tabs-below>.nav-tabs{border-top:1px solid #ddd}.tabs-below>.nav-tabs>li{margin-top:-1px;margin-bottom:0}.tabs-below>.nav-tabs>li>a{border-radius:0 0 4px 4px}.tabs-below>.nav-tabs>li>a:focus,.tabs-below>.nav-tabs>li>a:hover{border-bottom-color:transparent;border-top-color:#ddd}.tabs-below>.nav-tabs>.active>a,.tabs-below>.nav-tabs>.active>a:focus,.tabs-below>.nav-tabs>.active>a:hover{border-color:transparent #ddd #ddd}.tabs-left>.nav-tabs>li,.tabs-right>.nav-tabs>li{float:none}.tabs-left>.nav-tabs>li>a,.tabs-right>.nav-tabs>li>a{min-width:74px;margin-right:0;margin-bottom:3px}.tabs-left>.nav-tabs{float:left;margin-right:19px;border-right:1px solid #ddd}.tabs-left>.nav-tabs>li>a{margin-right:-1px;border-radius:4px 0 0 4px}.tabs-left>.nav-tabs>li>a:focus,.tabs-left>.nav-tabs>li>a:hover{border-color:#eee #ddd #eee #eee}.tabs-left>.nav-tabs .active>a,.tabs-left>.nav-tabs .active>a:focus,.tabs-left>.nav-tabs .active>a:hover{border-color:#ddd transparent #ddd #ddd}.tabs-right>.nav-tabs{float:right;margin-left:19px;border-left:1px solid #ddd}.tabs-right>.nav-tabs>li>a{margin-left:-1px;border-radius:0 4px 4px 0}.tabs-right>.nav-tabs>li>a:focus,.tabs-right>.nav-tabs>li>a:hover{border-color:#eee #eee #eee #ddd}.tabs-right>.nav-tabs .active>a,.tabs-right>.nav-tabs .active>a:focus,.tabs-right>.nav-tabs .active>a:hover{border-color:#ddd #ddd #ddd transparent}.nav>.disabled>a{color:#999}.nav>.disabled>a:focus,.nav>.disabled>a:hover{text-decoration:none;background-color:transparent;cursor:default}.navbar{overflow:visible}.navbar-inner{min-height:40px;padding-left:20px;padding-right:20px;background-color:#fafafa;background-image:linear-gradient(to bottom,#fff,#f2f2f2);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff2f2f2', GradientType=0);border:1px solid #d4d4d4;border-radius:4px;box-shadow:0 1px 4px rgba(0,0,0,.065)}.navbar-inner:after,.navbar-inner:before{display:table;content:"";line-height:0}.navbar-inner:after{clear:both}.navbar .container{width:auto}.nav-collapse.collapse{height:auto;overflow:visible}.navbar .brand{float:left;display:block;padding:10px 20px;margin-left:-20px;font-size:20px;font-weight:200;color:#777;text-shadow:0 1px 0 #fff}.navbar .brand:focus,.navbar .brand:hover{text-decoration:none}.navbar-text{margin-bottom:0;line-height:40px;color:#777}.navbar-link{color:#777}.navbar-link:focus,.navbar-link:hover{color:#333}.navbar .divider-vertical{height:40px;margin:0 9px;border-left:1px solid #f2f2f2;border-right:1px solid #fff}.navbar .btn,.navbar .btn-group{margin-top:5px}.navbar .btn-group .btn,.navbar .input-append .btn,.navbar .input-append .btn-group,.navbar .input-prepend .btn,.navbar .input-prepend .btn-group{margin-top:0}.navbar-form{margin-bottom:0}.navbar-form:after,.navbar-form:before{display:table;content:"";line-height:0}.navbar-form:after{clear:both}.navbar-form .checkbox,.navbar-form .radio,.navbar-form input,.navbar-form select{margin-top:5px}.navbar-form .btn,.navbar-form input,.navbar-form select{display:inline-block;margin-bottom:0}.navbar-form input[type=checkbox],.navbar-form input[type=image],.navbar-form input[type=radio]{margin-top:3px}.navbar-form .input-append,.navbar-form .input-prepend{margin-top:5px;white-space:nowrap}.navbar-form .input-append input,.navbar-form .input-prepend input{margin-top:0}.navbar-search{position:relative;float:left;margin-top:5px;margin-bottom:0}.navbar-search .search-query{margin-bottom:0;padding:4px 14px;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:13px;font-weight:400;line-height:1;border-radius:15px}.navbar-static-top{position:static;margin-bottom:0}.navbar-static-top .navbar-inner{border-radius:0}.navbar-fixed-bottom,.navbar-fixed-top{position:fixed;right:0;left:0;z-index:1030;margin-bottom:0}.navbar-fixed-top .navbar-inner,.navbar-static-top .navbar-inner{border-width:0 0 1px}.navbar-fixed-bottom .navbar-inner{border-width:1px 0 0}.navbar-fixed-bottom .navbar-inner,.navbar-fixed-top .navbar-inner{padding-left:0;padding-right:0;border-radius:0}.navbar-fixed-bottom .container,.navbar-fixed-top .container,.navbar-static-top .container{width:940px}.navbar-fixed-top{top:0}.navbar-fixed-top .navbar-inner,.navbar-static-top .navbar-inner{box-shadow:0 1px 10px rgba(0,0,0,.1)}.navbar-fixed-bottom{bottom:0}.navbar-fixed-bottom .navbar-inner{box-shadow:0 -1px 10px rgba(0,0,0,.1)}.navbar .nav{position:relative;left:0;display:block;float:left;margin:0 10px 0 0}.navbar .nav.pull-right{float:right;margin-right:0}.navbar .nav>li{float:left}.navbar .nav>li>a{float:none;padding:10px 15px;color:#777;text-decoration:none;text-shadow:0 1px 0 #fff}.navbar .nav .dropdown-toggle .caret{margin-top:8px}.navbar .nav>li>a:focus,.navbar .nav>li>a:hover{background-color:transparent;color:#333;text-decoration:none}.navbar .nav>.active>a,.navbar .nav>.active>a:focus,.navbar .nav>.active>a:hover{color:#555;text-decoration:none;background-color:#e5e5e5;box-shadow:inset 0 3px 8px rgba(0,0,0,.125)}.navbar .btn-navbar{display:none;float:right;padding:7px 10px;margin-left:5px;margin-right:5px;color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,.25);background-color:#ededed;background-image:linear-gradient(to bottom,#f2f2f2,#e5e5e5);background-repeat:repeat-x;border-color:#e5e5e5 #e5e5e5 #bfbfbf;border-color:rgba(0,0,0,.1) rgba(0,0,0,.1) rgba(0,0,0,.25);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);box-shadow:inset 0 1px 0 rgba(255,255,255,.1),0 1px 0 rgba(255,255,255,.075)}.navbar .btn-navbar.active,.navbar .btn-navbar.disabled,.navbar .btn-navbar:active,.navbar .btn-navbar:focus,.navbar .btn-navbar:hover,.navbar .btn-navbar[disabled]{color:#fff;background-color:#e5e5e5}.navbar .btn-navbar .icon-bar{display:block;width:18px;height:2px;background-color:#f5f5f5;border-radius:1px;box-shadow:0 1px 0 rgba(0,0,0,.25)}.btn-navbar .icon-bar+.icon-bar{margin-top:3px}.navbar .nav>li>.dropdown-menu:before{content:'';display:inline-block;border-left:7px solid transparent;border-right:7px solid transparent;border-bottom:7px solid #ccc;border-bottom-color:rgba(0,0,0,.2);position:absolute;top:-7px;left:9px}.navbar .nav>li>.dropdown-menu:after{content:'';display:inline-block;border-left:6px solid transparent;border-right:6px solid transparent;border-bottom:6px solid #fff;position:absolute;top:-6px;left:10px}.navbar-fixed-bottom .nav>li>.dropdown-menu:before{border-top:7px solid #ccc;border-top-color:rgba(0,0,0,.2);border-bottom:0;bottom:-7px;top:auto}.navbar-fixed-bottom .nav>li>.dropdown-menu:after{border-top:6px solid #fff;border-bottom:0;bottom:-6px;top:auto}.navbar .nav li.dropdown>a:focus .caret,.navbar .nav li.dropdown>a:hover .caret{border-top-color:#333;border-bottom-color:#333}.navbar .nav li.dropdown.active>.dropdown-toggle,.navbar .nav li.dropdown.open.active>.dropdown-toggle,.navbar .nav li.dropdown.open>.dropdown-toggle{background-color:#e5e5e5;color:#555}.navbar .nav li.dropdown>.dropdown-toggle .caret{border-top-color:#777;border-bottom-color:#777}.navbar .nav li.dropdown.active>.dropdown-toggle .caret,.navbar .nav li.dropdown.open.active>.dropdown-toggle .caret,.navbar .nav li.dropdown.open>.dropdown-toggle .caret{border-top-color:#555;border-bottom-color:#555}.navbar .nav>li>.dropdown-menu.pull-right,.navbar .pull-right>li>.dropdown-menu{left:auto;right:0}.navbar .nav>li>.dropdown-menu.pull-right:before,.navbar .pull-right>li>.dropdown-menu:before{left:auto;right:12px}.navbar .nav>li>.dropdown-menu.pull-right:after,.navbar .pull-right>li>.dropdown-menu:after{left:auto;right:13px}.navbar .nav>li>.dropdown-menu.pull-right .dropdown-menu,.navbar .pull-right>li>.dropdown-menu .dropdown-menu{left:auto;right:100%;margin-left:0;margin-right:-1px;border-radius:6px 0 6px 6px}.navbar-inverse .navbar-inner{background-color:#1b1b1b;background-image:linear-gradient(to bottom,#222,#111);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff222222', endColorstr='#ff111111', GradientType=0);border-color:#252525}.navbar-inverse .brand,.navbar-inverse .nav>li>a{color:#999;text-shadow:0 -1px 0 rgba(0,0,0,.25)}.navbar-inverse .brand:focus,.navbar-inverse .brand:hover,.navbar-inverse .nav>li>a:focus,.navbar-inverse .nav>li>a:hover{color:#fff}.navbar-inverse .brand,.navbar-inverse .navbar-text{color:#999}.navbar-inverse .nav>li>a:focus,.navbar-inverse .nav>li>a:hover{background-color:transparent;color:#fff}.navbar-inverse .nav .active>a,.navbar-inverse .nav .active>a:focus,.navbar-inverse .nav .active>a:hover{color:#fff;background-color:#111}.navbar-inverse .navbar-link{color:#999}.navbar-inverse .navbar-link:focus,.navbar-inverse .navbar-link:hover{color:#fff}.navbar-inverse .divider-vertical{border-left-color:#111;border-right-color:#222}.navbar-inverse .nav li.dropdown.active>.dropdown-toggle,.navbar-inverse .nav li.dropdown.open.active>.dropdown-toggle,.navbar-inverse .nav li.dropdown.open>.dropdown-toggle{background-color:#111;color:#fff}.navbar-inverse .nav li.dropdown>a:focus .caret,.navbar-inverse .nav li.dropdown>a:hover .caret{border-top-color:#fff;border-bottom-color:#fff}.navbar-inverse .nav li.dropdown>.dropdown-toggle .caret{border-top-color:#999;border-bottom-color:#999}.navbar-inverse .nav li.dropdown.active>.dropdown-toggle .caret,.navbar-inverse .nav li.dropdown.open.active>.dropdown-toggle .caret,.navbar-inverse .nav li.dropdown.open>.dropdown-toggle .caret{border-top-color:#fff;border-bottom-color:#fff}.navbar-inverse .navbar-search .search-query{color:#fff;background-color:#515151;border-color:#111;box-shadow:inset 0 1px 2px rgba(0,0,0,.1),0 1px 0 rgba(255,255,255,.15);transition:none}.navbar-inverse .navbar-search .search-query:-moz-placeholder{color:#ccc}.navbar-inverse .navbar-search .search-query:-ms-input-placeholder{color:#ccc}.navbar-inverse .navbar-search .search-query::-webkit-input-placeholder{color:#ccc}.navbar-inverse .navbar-search .search-query.focused,.navbar-inverse .navbar-search .search-query:focus{padding:5px 15px;color:#333;text-shadow:0 1px 0 #fff;background-color:#fff;border:0;box-shadow:0 0 3px rgba(0,0,0,.15);outline:0}.navbar-inverse .btn-navbar{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,.25);background-color:#0e0e0e;background-image:linear-gradient(to bottom,#151515,#040404);background-repeat:repeat-x;border-color:#040404 #040404 #000;border-color:rgba(0,0,0,.1) rgba(0,0,0,.1) rgba(0,0,0,.25);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.navbar-inverse .btn-navbar.active,.navbar-inverse .btn-navbar.disabled,.navbar-inverse .btn-navbar:active,.navbar-inverse .btn-navbar:focus,.navbar-inverse .btn-navbar:hover,.navbar-inverse .btn-navbar[disabled]{color:#fff;background-color:#040404}.breadcrumb{padding:8px 15px;margin:0 0 20px;list-style:none;background-color:#f5f5f5;border-radius:4px}.breadcrumb>li{display:inline-block;text-shadow:0 1px 0 #fff}.breadcrumb>li>.divider{padding:0 5px;color:#ccc}.breadcrumb>.active{color:#999}.pagination{margin:20px 0}.pagination ul{display:inline-block;margin-left:0;margin-bottom:0;border-radius:4px;box-shadow:0 1px 2px rgba(0,0,0,.05)}.pagination ul>li{display:inline}.pagination ul>li>a,.pagination ul>li>span{float:left;padding:4px 12px;line-height:20px;text-decoration:none;background-color:#fff;border:1px solid #ddd;border-left-width:0}.pagination ul>.active>a,.pagination ul>.active>span,.pagination ul>li>a:focus,.pagination ul>li>a:hover{background-color:#f5f5f5}.pagination ul>.active>a,.pagination ul>.active>span{color:#999;cursor:default}.pagination ul>.disabled>a,.pagination ul>.disabled>a:focus,.pagination ul>.disabled>a:hover,.pagination ul>.disabled>span{color:#999;background-color:transparent;cursor:default}.pagination ul>li:first-child>a,.pagination ul>li:first-child>span{border-left-width:1px;border-top-left-radius:4px;border-bottom-left-radius:4px}.pagination ul>li:last-child>a,.pagination ul>li:last-child>span{border-top-right-radius:4px;border-bottom-right-radius:4px}.pagination-centered{text-align:center}.pagination-right{text-align:right}.pagination-large ul>li>a,.pagination-large ul>li>span{padding:11px 19px;font-size:17.5px}.pagination-large ul>li:first-child>a,.pagination-large ul>li:first-child>span{border-top-left-radius:6px;border-bottom-left-radius:6px}.pagination-large ul>li:last-child>a,.pagination-large ul>li:last-child>span{border-top-right-radius:6px;border-bottom-right-radius:6px}.pagination-mini ul>li:first-child>a,.pagination-mini ul>li:first-child>span,.pagination-small ul>li:first-child>a,.pagination-small ul>li:first-child>span{border-top-left-radius:3px;border-bottom-left-radius:3px}.pagination-mini ul>li:last-child>a,.pagination-mini ul>li:last-child>span,.pagination-small ul>li:last-child>a,.pagination-small ul>li:last-child>span{border-top-right-radius:3px;border-bottom-right-radius:3px}.pagination-small ul>li>a,.pagination-small ul>li>span{padding:2px 10px;font-size:11.9px}.pagination-mini ul>li>a,.pagination-mini ul>li>span{padding:0 6px;font-size:10.5px}.pager{margin:20px 0;list-style:none;text-align:center}.pager:after,.pager:before{display:table;content:"";line-height:0}.pager:after{clear:both}.pager li{display:inline}.pager li>a,.pager li>span{display:inline-block;padding:5px 14px;background-color:#fff;border:1px solid #ddd;border-radius:15px}.pager li>a:focus,.pager li>a:hover{text-decoration:none;background-color:#f5f5f5}.pager .next>a,.pager .next>span{float:right}.pager .previous>a,.pager .previous>span{float:left}.pager .disabled>a,.pager .disabled>a:focus,.pager .disabled>a:hover,.pager .disabled>span{color:#999;background-color:#fff;cursor:default}.modal-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040;background-color:#000}.modal-backdrop.fade{opacity:0}.modal{left:50%;z-index:1050;background-color:#fff;border:1px solid #999;border:1px solid rgba(0,0,0,.3);border-radius:6px;box-shadow:0 3px 7px rgba(0,0,0,.3);background-clip:padding-box}.modal-header{border-bottom:1px solid #eee}.modal-header .close{margin-top:2px}.modal-header h3{margin:0;line-height:30px}.modal-body{position:relative;overflow-y:auto}.modal-form{margin-bottom:0}.modal-footer{margin-bottom:0;text-align:right;background-color:#f5f5f5;border-top:1px solid #ddd;border-radius:0 0 6px 6px;box-shadow:inset 0 1px 0 #fff}.modal-footer:after,.modal-footer:before{display:table;content:"";line-height:0}.modal-footer:after{clear:both}.modal-footer .btn+.btn{margin-left:5px;margin-bottom:0}.modal-footer .btn-group .btn+.btn{margin-left:-1px}.modal-footer .btn-block+.btn-block{margin-left:0}.tooltip{position:absolute;display:block;visibility:visible;font-size:11px;line-height:1.4;opacity:0;filter:alpha(opacity=0)}.tooltip.top{margin-top:-3px;padding:5px 0}.tooltip.right{margin-left:3px;padding:0 5px}.tooltip.bottom{margin-top:3px;padding:5px 0}.tooltip.left{margin-left:-3px;padding:0 5px}.tooltip-inner{max-width:200px;padding:8px;color:#fff;text-align:center;text-decoration:none;background-color:#000;border-radius:4px}.tooltip-arrow{position:absolute;width:0;height:0;border-color:transparent;border-style:solid}.tooltip.top .tooltip-arrow{bottom:0;left:50%;margin-left:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.right .tooltip-arrow{top:50%;left:0;margin-top:-5px;border-width:5px 5px 5px 0;border-right-color:#000}.tooltip.left .tooltip-arrow{top:50%;right:0;margin-top:-5px;border-width:5px 0 5px 5px;border-left-color:#000}.tooltip.bottom .tooltip-arrow{top:0;left:50%;margin-left:-5px;border-width:0 5px 5px;border-bottom-color:#000}.popover{position:absolute;top:0;left:0;z-index:1010;display:none;max-width:276px;padding:1px;text-align:left;background-color:#fff;background-clip:padding-box;border:1px solid #ccc;border:1px solid rgba(0,0,0,.2);border-radius:6px;box-shadow:0 5px 10px rgba(0,0,0,.2);white-space:normal}.popover.top{margin-top:-10px}.popover.right{margin-left:10px}.popover.bottom{margin-top:10px}.popover.left{margin-left:-10px}.popover-title{margin:0;padding:8px 14px;font-size:14px;font-weight:400;line-height:18px;background-color:#f7f7f7;border-bottom:1px solid #ebebeb;border-radius:5px 5px 0 0}.popover-title:empty{display:none}.popover-content{padding:9px 14px}.popover .arrow,.popover .arrow:after{position:absolute;display:block;width:0;height:0;border-color:transparent;border-style:solid}.popover .arrow{border-width:11px}.popover .arrow:after{border-width:10px;content:""}.popover.top .arrow{left:50%;margin-left:-11px;border-bottom-width:0;border-top-color:#999;border-top-color:rgba(0,0,0,.25);bottom:-11px}.popover.top .arrow:after{bottom:1px;margin-left:-10px;border-bottom-width:0;border-top-color:#fff}.popover.right .arrow{top:50%;left:-11px;margin-top:-11px;border-left-width:0;border-right-color:#999;border-right-color:rgba(0,0,0,.25)}.popover.right .arrow:after{left:1px;bottom:-10px;border-left-width:0;border-right-color:#fff}.popover.bottom .arrow{left:50%;margin-left:-11px;border-top-width:0;border-bottom-color:#999;border-bottom-color:rgba(0,0,0,.25);top:-11px}.popover.bottom .arrow:after{top:1px;margin-left:-10px;border-top-width:0;border-bottom-color:#fff}.popover.left .arrow{top:50%;right:-11px;margin-top:-11px;border-right-width:0;border-left-color:#999;border-left-color:rgba(0,0,0,.25)}.popover.left .arrow:after{right:1px;border-right-width:0;border-left-color:#fff;bottom:-10px}.thumbnails{margin-left:-20px;list-style:none}.thumbnails:after,.thumbnails:before{display:table;content:"";line-height:0}.thumbnails:after{clear:both}.row-fluid .thumbnails{margin-left:0}.thumbnails>li{float:left;margin-bottom:20px;margin-left:20px}.thumbnail{display:block;padding:4px;line-height:20px;border:1px solid #ddd;border-radius:4px;box-shadow:0 1px 3px rgba(0,0,0,.055);transition:all .2s ease-in-out}a.thumbnail:focus,a.thumbnail:hover{border-color:#08c;box-shadow:0 1px 4px rgba(0,105,214,.25)}.thumbnail>img{display:block;max-width:100%;margin-left:auto;margin-right:auto}.thumbnail .caption{padding:9px;color:#555}.media,.media-body{overflow:hidden;zoom:1}.media,.media .media{margin-top:15px}.media:first-child{margin-top:0}.media-object{display:block}.media-heading{margin:0 0 5px}.media>.pull-left{margin-right:10px}.media>.pull-right{margin-left:10px}.media-list{margin-left:0;list-style:none}.badge,.label{display:inline-block;padding:2px 4px;font-size:11.84px;font-weight:700;line-height:14px;color:#fff;vertical-align:baseline;white-space:nowrap;text-shadow:0 -1px 0 rgba(0,0,0,.25);background-color:#999}.label{border-radius:3px}.badge{padding-left:9px;padding-right:9px;border-radius:9px}.badge:empty,.label:empty{display:none}a.badge:focus,a.badge:hover,a.label:focus,a.label:hover{color:#fff;text-decoration:none;cursor:pointer}.badge-important,.label-important{background-color:#b94a48}.badge-important[href],.label-important[href]{background-color:#953b39}.badge-warning,.label-warning{background-color:#f89406}.badge-warning[href],.label-warning[href]{background-color:#c67605}.badge-success,.label-success{background-color:#468847}.badge-success[href],.label-success[href]{background-color:#356635}.badge-info,.label-info{background-color:#3a87ad}.badge-info[href],.label-info[href]{background-color:#2d6987}.badge-inverse,.label-inverse{background-color:#333}.badge-inverse[href],.label-inverse[href]{background-color:#1a1a1a}.btn .badge,.btn .label{position:relative;top:-1px}.btn-mini .badge,.btn-mini .label{top:0}@-webkit-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@-ms-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}.progress{overflow:hidden;height:20px;margin-bottom:20px;background-color:#f7f7f7;background-image:linear-gradient(to bottom,#f5f5f5,#f9f9f9);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#fff9f9f9', GradientType=0);box-shadow:inset 0 1px 2px rgba(0,0,0,.1);border-radius:4px}.progress .bar{width:0;height:100%;color:#fff;float:left;font-size:12px;text-align:center;text-shadow:0 -1px 0 rgba(0,0,0,.25);background-color:#0e90d2;background-image:linear-gradient(to bottom,#149bdf,#0480be);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff149bdf', endColorstr='#ff0480be', GradientType=0);box-shadow:inset 0 -1px 0 rgba(0,0,0,.15);box-sizing:border-box;transition:width .6s ease}.progress .bar+.bar{box-shadow:inset 1px 0 0 rgba(0,0,0,.15),inset 0 -1px 0 rgba(0,0,0,.15)}.progress-striped .bar{background-color:#149bdf;background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-size:40px 40px}.progress.active .bar{-webkit-animation:progress-bar-stripes 2s linear infinite;-ms-animation:progress-bar-stripes 2s linear infinite;animation:progress-bar-stripes 2s linear infinite}.progress .bar-danger,.progress-danger .bar{background-color:#dd514c;background-image:linear-gradient(to bottom,#ee5f5b,#c43c35);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b', endColorstr='#ffc43c35', GradientType=0)}.progress-danger.progress-striped .bar,.progress-striped .bar-danger{background-color:#ee5f5b;background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress .bar-success,.progress-success .bar{background-color:#5eb95e;background-image:linear-gradient(to bottom,#62c462,#57a957);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462', endColorstr='#ff57a957', GradientType=0)}.progress-striped .bar-success,.progress-success.progress-striped .bar{background-color:#62c462;background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress .bar-info,.progress-info .bar{background-color:#4bb1cf;background-image:linear-gradient(to bottom,#5bc0de,#339bb9);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff339bb9', GradientType=0)}.progress-info.progress-striped .bar,.progress-striped .bar-info{background-color:#5bc0de;background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress .bar-warning,.progress-warning .bar{background-color:#faa732;background-image:linear-gradient(to bottom,#fbb450,#f89406);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450', endColorstr='#fff89406', GradientType=0)}.progress-striped .bar-warning,.progress-warning.progress-striped .bar{background-color:#fbb450;background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.accordion{margin-bottom:20px}.accordion-group{margin-bottom:2px;border:1px solid #e5e5e5;border-radius:4px}.accordion-heading{border-bottom:0}.accordion-heading .accordion-toggle{display:block;padding:8px 15px}.accordion-toggle{cursor:pointer}.accordion-inner{padding:9px 15px;border-top:1px solid #e5e5e5}.carousel{position:relative;margin-bottom:20px;line-height:1}.carousel-inner{overflow:hidden;width:100%;position:relative}.carousel-inner>.item{display:none;position:relative;transition:.6s ease-in-out left}.carousel-inner>.item>a>img,.carousel-inner>.item>img{display:block;line-height:1}.carousel-inner>.active,.carousel-inner>.next,.carousel-inner>.prev{display:block}.carousel-inner>.active{left:0}.carousel-inner>.next,.carousel-inner>.prev{position:absolute;top:0;width:100%}.carousel-inner>.next{left:100%}.carousel-inner>.prev{left:-100%}.carousel-inner>.next.left,.carousel-inner>.prev.right{left:0}.carousel-inner>.active.left{left:-100%}.carousel-inner>.active.right{left:100%}.carousel-control{position:absolute;top:40%;left:15px;width:40px;height:40px;margin-top:-20px;font-size:60px;font-weight:100;line-height:30px;color:#fff;text-align:center;background:#222;border:3px solid #fff;border-radius:23px;opacity:.5;filter:alpha(opacity=50)}.carousel-control.right{left:auto;right:15px}.carousel-control:focus,.carousel-control:hover{color:#fff;text-decoration:none;opacity:.9;filter:alpha(opacity=90)}.carousel-indicators{position:absolute;top:15px;right:15px;z-index:5;margin:0;list-style:none}.carousel-indicators li{display:block;float:left;width:10px;height:10px;margin-left:5px;text-indent:-999px;background-color:#ccc;background-color:rgba(255,255,255,.25);border-radius:5px}.carousel-indicators .active{background-color:#fff}.carousel-caption{position:absolute;left:0;right:0;bottom:0;padding:15px;background:#333;background:rgba(0,0,0,.75)}.carousel-caption h4,.carousel-caption p{color:#fff;line-height:20px}.carousel-caption h4{margin:0 0 5px}.carousel-caption p{margin-bottom:0}.hero-unit{padding:60px;margin-bottom:30px;font-size:18px;font-weight:200;line-height:30px;color:inherit;background-color:#eee;border-radius:6px}.hero-unit h1{margin-bottom:0;font-size:60px;line-height:1;color:inherit;letter-spacing:-1px}.hero-unit li{line-height:30px}.pull-right{float:right}.pull-left{float:left}.hide{display:none}.show{display:block}.invisible{visibility:hidden}.affix{position:fixed}/*! + * Bootstrap Responsive v2.3.1 + * + * Copyright 2012 Twitter, Inc + * Licensed under the Apache License v2.0 + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Designed and built with all the love in the world @twitter by @mdo and @fat. + */.clearfix:after,.clearfix:before{display:table;content:"";line-height:0}.clearfix:after{clear:both}.hide-text{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.input-block-level{display:block;width:100%;min-height:30px;box-sizing:border-box}@-ms-viewport{width:device-width}.hidden{display:none;visibility:hidden}.hidden-desktop,.visible-phone,.visible-tablet{display:none!important}.visible-desktop{display:inherit!important}@media (min-width:768px) and (max-width:839px){.hidden-desktop{display:inherit!important}.visible-desktop{display:none!important}.visible-tablet{display:inherit!important}.hidden-tablet{display:none!important}}@media (max-width:767px){.hidden-desktop{display:inherit!important}.visible-desktop{display:none!important}.visible-phone{display:inherit!important}.hidden-phone{display:none!important}}.visible-print{display:none!important}@media print{.visible-print{display:inherit!important}.hidden-print{display:none!important}}@media (min-width:1200px){.row{margin-left:-30px}.row:after,.row:before{display:table;content:"";line-height:0}.row:after{clear:both}[class*=span]{float:left;min-height:1px;margin-left:30px}.container,.navbar-fixed-bottom .container,.navbar-fixed-top .container,.navbar-static-top .container,.span12{width:1170px}.span11{width:1070px}.span10{width:970px}.span9{width:870px}.span8{width:770px}.span7{width:670px}.span6{width:570px}.span5{width:470px}.span4{width:370px}.span3{width:270px}.span2{width:170px}.span1{width:70px}.offset12{margin-left:1230px}.offset11{margin-left:1130px}.offset10{margin-left:1030px}.offset9{margin-left:930px}.offset8{margin-left:830px}.offset7{margin-left:730px}.offset6{margin-left:630px}.offset5{margin-left:530px}.offset4{margin-left:430px}.offset3{margin-left:330px}.offset2{margin-left:230px}.offset1{margin-left:130px}.row-fluid{width:100%}.row-fluid:after,.row-fluid:before{display:table;content:"";line-height:0}.row-fluid:after{clear:both}.row-fluid [class*=span]{display:block;width:100%;min-height:30px;box-sizing:border-box;float:left;margin-left:2.56410256%}.row-fluid [class*=span]:first-child{margin-left:0}.row-fluid .controls-row [class*=span]+[class*=span]{margin-left:2.56410256%}.row-fluid .span12{width:100%}.row-fluid .span11{width:91.45299145%}.row-fluid .span10{width:82.90598291%}.row-fluid .span9{width:74.35897436%}.row-fluid .span8{width:65.81196581%}.row-fluid .span7{width:57.26495726%}.row-fluid .span6{width:48.71794872%}.row-fluid .span5{width:40.17094017%}.row-fluid .span4{width:31.62393162%}.row-fluid .span3{width:23.07692308%}.row-fluid .span2{width:14.52991453%}.row-fluid .span1{width:5.98290598%}.row-fluid .offset12{margin-left:105.12820513%}.row-fluid .offset12:first-child{margin-left:102.56410256%}.row-fluid .offset11{margin-left:96.58119658%}.row-fluid .offset11:first-child{margin-left:94.01709402%}.row-fluid .offset10{margin-left:88.03418803%}.row-fluid .offset10:first-child{margin-left:85.47008547%}.row-fluid .offset9{margin-left:79.48717949%}.row-fluid .offset9:first-child{margin-left:76.92307692%}.row-fluid .offset8{margin-left:70.94017094%}.row-fluid .offset8:first-child{margin-left:68.37606838%}.row-fluid .offset7{margin-left:62.39316239%}.row-fluid .offset7:first-child{margin-left:59.82905983%}.row-fluid .offset6{margin-left:53.84615385%}.row-fluid .offset6:first-child{margin-left:51.28205128%}.row-fluid .offset5{margin-left:45.2991453%}.row-fluid .offset5:first-child{margin-left:42.73504274%}.row-fluid .offset4{margin-left:36.75213675%}.row-fluid .offset4:first-child{margin-left:34.18803419%}.row-fluid .offset3{margin-left:28.20512821%}.row-fluid .offset3:first-child{margin-left:25.64102564%}.row-fluid .offset2{margin-left:19.65811966%}.row-fluid .offset2:first-child{margin-left:17.09401709%}.row-fluid .offset1{margin-left:11.11111111%}.row-fluid .offset1:first-child{margin-left:8.54700855%}.uneditable-input,input,textarea{margin-left:0}.controls-row [class*=span]+[class*=span]{margin-left:30px}.uneditable-input.span12,input.span12,textarea.span12{width:1156px}.uneditable-input.span11,input.span11,textarea.span11{width:1056px}.uneditable-input.span10,input.span10,textarea.span10{width:956px}.uneditable-input.span9,input.span9,textarea.span9{width:856px}.uneditable-input.span8,input.span8,textarea.span8{width:756px}.uneditable-input.span7,input.span7,textarea.span7{width:656px}.uneditable-input.span6,input.span6,textarea.span6{width:556px}.uneditable-input.span5,input.span5,textarea.span5{width:456px}.uneditable-input.span4,input.span4,textarea.span4{width:356px}.uneditable-input.span3,input.span3,textarea.span3{width:256px}.uneditable-input.span2,input.span2,textarea.span2{width:156px}.uneditable-input.span1,input.span1,textarea.span1{width:56px}.thumbnails{margin-left:-30px}.thumbnails>li{margin-left:30px}.row-fluid .thumbnails{margin-left:0}}@media (min-width:768px) and (max-width:839px){.row{margin-left:-20px}.row:after,.row:before{display:table;content:"";line-height:0}.row:after{clear:both}[class*=span]{float:left;min-height:1px;margin-left:20px}.container,.navbar-fixed-bottom .container,.navbar-fixed-top .container,.navbar-static-top .container,.span12{width:724px}.span11{width:662px}.span10{width:600px}.span9{width:538px}.span8{width:476px}.span7{width:414px}.span6{width:352px}.span5{width:290px}.span4{width:228px}.span3{width:166px}.span2{width:104px}.span1{width:42px}.offset12{margin-left:764px}.offset11{margin-left:702px}.offset10{margin-left:640px}.offset9{margin-left:578px}.offset8{margin-left:516px}.offset7{margin-left:454px}.offset6{margin-left:392px}.offset5{margin-left:330px}.offset4{margin-left:268px}.offset3{margin-left:206px}.offset2{margin-left:144px}.offset1{margin-left:82px}.row-fluid{width:100%}.row-fluid:after,.row-fluid:before{display:table;content:"";line-height:0}.row-fluid:after{clear:both}.row-fluid [class*=span]{display:block;width:100%;min-height:30px;box-sizing:border-box;float:left;margin-left:2.76243094%}.row-fluid [class*=span]:first-child{margin-left:0}.row-fluid .controls-row [class*=span]+[class*=span]{margin-left:2.76243094%}.row-fluid .span12{width:100%}.row-fluid .span11{width:91.43646409%}.row-fluid .span10{width:82.87292818%}.row-fluid .span9{width:74.30939227%}.row-fluid .span8{width:65.74585635%}.row-fluid .span7{width:57.18232044%}.row-fluid .span6{width:48.61878453%}.row-fluid .span5{width:40.05524862%}.row-fluid .span4{width:31.49171271%}.row-fluid .span3{width:22.9281768%}.row-fluid .span2{width:14.36464088%}.row-fluid .span1{width:5.80110497%}.row-fluid .offset12{margin-left:105.52486188%}.row-fluid .offset12:first-child{margin-left:102.76243094%}.row-fluid .offset11{margin-left:96.96132597%}.row-fluid .offset11:first-child{margin-left:94.19889503%}.row-fluid .offset10{margin-left:88.39779006%}.row-fluid .offset10:first-child{margin-left:85.63535912%}.row-fluid .offset9{margin-left:79.83425414%}.row-fluid .offset9:first-child{margin-left:77.0718232%}.row-fluid .offset8{margin-left:71.27071823%}.row-fluid .offset8:first-child{margin-left:68.50828729%}.row-fluid .offset7{margin-left:62.70718232%}.row-fluid .offset7:first-child{margin-left:59.94475138%}.row-fluid .offset6{margin-left:54.14364641%}.row-fluid .offset6:first-child{margin-left:51.38121547%}.row-fluid .offset5{margin-left:45.5801105%}.row-fluid .offset5:first-child{margin-left:42.81767956%}.row-fluid .offset4{margin-left:37.01657459%}.row-fluid .offset4:first-child{margin-left:34.25414365%}.row-fluid .offset3{margin-left:28.45303867%}.row-fluid .offset3:first-child{margin-left:25.69060773%}.row-fluid .offset2{margin-left:19.88950276%}.row-fluid .offset2:first-child{margin-left:17.12707182%}.row-fluid .offset1{margin-left:11.32596685%}.row-fluid .offset1:first-child{margin-left:8.56353591%}.uneditable-input,input,textarea{margin-left:0}.controls-row [class*=span]+[class*=span]{margin-left:20px}.uneditable-input.span12,input.span12,textarea.span12{width:710px}.uneditable-input.span11,input.span11,textarea.span11{width:648px}.uneditable-input.span10,input.span10,textarea.span10{width:586px}.uneditable-input.span9,input.span9,textarea.span9{width:524px}.uneditable-input.span8,input.span8,textarea.span8{width:462px}.uneditable-input.span7,input.span7,textarea.span7{width:400px}.uneditable-input.span6,input.span6,textarea.span6{width:338px}.uneditable-input.span5,input.span5,textarea.span5{width:276px}.uneditable-input.span4,input.span4,textarea.span4{width:214px}.uneditable-input.span3,input.span3,textarea.span3{width:152px}.uneditable-input.span2,input.span2,textarea.span2{width:90px}.uneditable-input.span1,input.span1,textarea.span1{width:28px}}@media (max-width:767px){body{padding-left:20px;padding-right:20px}.navbar-fixed-bottom,.navbar-fixed-top,.navbar-static-top{margin-left:-20px;margin-right:-20px}.container-fluid{padding:0}.dl-horizontal dt{float:none;clear:none;width:auto;text-align:left}.dl-horizontal dd{margin-left:0}.container{width:auto}.row-fluid{width:100%}.row,.thumbnails{margin-left:0}.thumbnails>li{float:none;margin-left:0}.row-fluid [class*=span],.uneditable-input[class*=span],[class*=span]{float:none;display:block;width:100%;margin-left:0;box-sizing:border-box}.row-fluid .span12,.span12{width:100%;box-sizing:border-box}.row-fluid [class*=offset]:first-child{margin-left:0}.input-large,.input-xlarge,.input-xxlarge,.uneditable-input,input[class*=span],select[class*=span],textarea[class*=span]{display:block;width:100%;min-height:30px;box-sizing:border-box}.input-append input,.input-append input[class*=span],.input-prepend input,.input-prepend input[class*=span]{display:inline-block;width:auto}.controls-row [class*=span]+[class*=span]{margin-left:0}.modal{position:fixed;top:20px;left:20px;right:20px;width:auto;margin:0}.modal.fade{top:-100px}.modal.fade.in{top:20px}}@media (max-width:480px){.nav-collapse{-webkit-transform:translate3d(0,0,0)}.page-header h1 small{display:block;line-height:20px}input[type=checkbox],input[type=radio]{border:1px solid #ccc}.form-horizontal .control-label{float:none;width:auto;padding-top:0;text-align:left}.form-horizontal .controls{margin-left:0}.form-horizontal .control-list{padding-top:0}.form-horizontal .form-actions{padding-left:10px;padding-right:10px}.media .pull-left,.media .pull-right{float:none;display:block;margin-bottom:10px}.media-object{margin-right:0;margin-left:0}.modal{top:10px;left:10px;right:10px}.modal-header .close{padding:10px;margin:-10px}.carousel-caption{position:static}}@media (max-width:839px){body{padding-top:0}.navbar-fixed-bottom,.navbar-fixed-top{position:static}.navbar-fixed-top{margin-bottom:20px}.navbar-fixed-bottom{margin-top:20px}.navbar-fixed-bottom .navbar-inner,.navbar-fixed-top .navbar-inner{padding:5px}.navbar .container{width:auto;padding:0}.navbar .brand{padding-left:10px;padding-right:10px;margin:0 0 0 -5px}.nav-collapse{clear:both}.nav-collapse .nav{float:none;margin:0 0 10px}.nav-collapse .nav>li{float:none}.nav-collapse .nav>li>a{margin-bottom:2px}.nav-collapse .nav>.divider-vertical{display:none}.nav-collapse .nav .nav-header{color:#777;text-shadow:none}.nav-collapse .dropdown-menu a,.nav-collapse .nav>li>a{padding:9px 15px;font-weight:700;color:#777;border-radius:3px}.nav-collapse .btn{padding:4px 10px;font-weight:400;border-radius:4px}.nav-collapse .dropdown-menu li+li a{margin-bottom:2px}.nav-collapse .dropdown-menu a:focus,.nav-collapse .dropdown-menu a:hover,.nav-collapse .nav>li>a:focus,.nav-collapse .nav>li>a:hover{background-color:#f2f2f2}.navbar-inverse .nav-collapse .dropdown-menu a,.navbar-inverse .nav-collapse .nav>li>a{color:#999}.navbar-inverse .nav-collapse .dropdown-menu a:focus,.navbar-inverse .nav-collapse .dropdown-menu a:hover,.navbar-inverse .nav-collapse .nav>li>a:focus,.navbar-inverse .nav-collapse .nav>li>a:hover{background-color:#111}.nav-collapse.in .btn-group{margin-top:5px;padding:0}.nav-collapse .dropdown-menu{position:static;top:auto;left:auto;float:none;display:none;max-width:none;margin:0 15px;padding:0;background-color:transparent;border:none;border-radius:0;box-shadow:none}.nav-collapse .open>.dropdown-menu{display:block}.nav-collapse .dropdown-menu .divider,.nav-collapse .dropdown-menu:after,.nav-collapse .dropdown-menu:before,.nav-collapse .nav>li>.dropdown-menu:after,.nav-collapse .nav>li>.dropdown-menu:before{display:none}.nav-collapse .navbar-form,.nav-collapse .navbar-search{float:none;padding:10px 15px;margin:10px 0;border-top:1px solid #f2f2f2;border-bottom:1px solid #f2f2f2;box-shadow:inset 0 1px 0 rgba(255,255,255,.1),0 1px 0 rgba(255,255,255,.1)}.navbar-inverse .nav-collapse .navbar-form,.navbar-inverse .nav-collapse .navbar-search{border-top-color:#111;border-bottom-color:#111}.navbar .nav-collapse .nav.pull-right{float:none;margin-left:0}.nav-collapse,.nav-collapse.collapse{overflow:hidden;height:0}.navbar .btn-navbar{display:block}.navbar-static .navbar-inner{padding-left:10px;padding-right:10px}}@media (min-width:839px + 1){.nav-collapse.collapse{height:auto!important;overflow:visible!important}}.lightbox{background-color:transparent;text-align:center;line-height:0;z-index:1050;position:relative;top:70px;outline:0}.lightbox .hide{display:none}.lightbox .in{display:block}.lightbox-content{display:inline-block;background-color:#fff}.lightbox-content .lightbox-caption{padding:2%;position:absolute;left:11px;right:12px;bottom:11px;background:#000;background:rgba(0,0,0,.6);color:#fff;text-align:center;text-shadow:0 -1px 0 #000;text-shadow:0 -1px 0 rgba(0,0,0,.3);font-size:14px;line-height:18px}.lightbox-header .close{color:#fff;margin-right:-16px;margin-top:-16px;font-size:2em;opacity:.8;filter:alpha(opacity=80)}.lightbox-header .close :hover{opacity:.4;filter:alpha(opacity=40)}/*! + * Bootstrap Modal + * + * Copyright Jordan Schroter + * Licensed under the Apache License v2.0 + * http://www.apache.org/licenses/LICENSE-2.0 + * + */.modal-open{overflow:hidden}.modal-open.page-overflow .modal-scrollable,.modal-open.page-overflow .page-container,.modal-open.page-overflow .page-container .navbar-fixed-bottom,.modal-open.page-overflow .page-container .navbar-fixed-top{overflow-y:scroll}@media (max-width:979px){.modal-open.page-overflow .page-container .navbar-fixed-bottom,.modal-open.page-overflow .page-container .navbar-fixed-top{overflow-y:visible}}.modal-scrollable{position:fixed;top:0;bottom:0;left:0;right:0;overflow:auto}.modal{outline:0;position:absolute;margin-top:0;top:50%;overflow:visible}.modal.fade{top:-100%;-webkit-transition:opacity .3s linear,top .3s ease-out,bottom .3s ease-out,margin-top .3s ease-out;-moz-transition:opacity .3s linear,top .3s ease-out,bottom .3s ease-out,margin-top .3s ease-out;-o-transition:opacity .3s linear,top .3s ease-out,bottom .3s ease-out,margin-top .3s ease-out;transition:opacity .3s linear,top .3s ease-out,bottom .3s ease-out,margin-top .3s ease-out}.modal.fade.in{top:50%}.modal-body{max-height:none;overflow:visible}.modal.modal-absolute{position:absolute;z-index:950}.modal .loading-mask{position:absolute;top:0;bottom:0;left:0;right:0;background:#fff;border-radius:6px}.modal-backdrop.modal-absolute{position:absolute;z-index:940}.modal-backdrop,.modal-backdrop.fade.in{opacity:.7;filter:alpha(opacity=70);background:#fff}.modal.container{width:940px;margin-left:-470px}.modal-overflow.modal{top:1%}.modal-overflow.modal.fade{top:-100%}.modal-overflow.modal.fade.in{top:1%}.modal-overflow .modal-body{overflow:auto;-webkit-overflow-scrolling:touch}@media (min-width:1200px){.modal.container{width:1170px;margin-left:-585px}}@media (max-width:979px){.modal,.modal.container,.modal.modal-overflow{top:1%;right:1%;left:1%;bottom:auto;width:auto!important;height:auto!important;margin:0!important;padding:0!important}.modal.container.fade.in,.modal.fade.in,.modal.modal-overflow.fade.in{top:1%;bottom:auto}.modal-body,.modal-overflow .modal-body{position:static;margin:0;height:auto!important;max-height:none!important;overflow:visible!important}.modal-footer,.modal-overflow .modal-footer{position:static}}.loading-spinner{position:absolute;top:50%;left:50%;margin:-12px 0 0 -12px}.animated{-webkit-animation-duration:1s;-moz-animation-duration:1s;-o-animation-duration:1s;animation-duration:1s;-webkit-animation-fill-mode:both;-moz-animation-fill-mode:both;-o-animation-fill-mode:both;animation-fill-mode:both}@-webkit-keyframes shake{0%,100%{-webkit-transform:translateX(0)}10%,30%,50%,70%,90%{-webkit-transform:translateX(-10px)}20%,40%,60%,80%{-webkit-transform:translateX(10px)}}@-moz-keyframes shake{0%,100%{-moz-transform:translateX(0)}10%,30%,50%,70%,90%{-moz-transform:translateX(-10px)}20%,40%,60%,80%{-moz-transform:translateX(10px)}}@-o-keyframes shake{0%,100%{-o-transform:translateX(0)}10%,30%,50%,70%,90%{-o-transform:translateX(-10px)}20%,40%,60%,80%{-o-transform:translateX(10px)}}@keyframes shake{0%,100%{transform:translateX(0)}10%,30%,50%,70%,90%{transform:translateX(-10px)}20%,40%,60%,80%{transform:translateX(10px)}}.shake{-webkit-animation-name:shake;-moz-animation-name:shake;-o-animation-name:shake;animation-name:shake}@-webkit-keyframes passing-through{0%{opacity:0;-webkit-transform:translateY(40px);-moz-transform:translateY(40px);-ms-transform:translateY(40px);-o-transform:translateY(40px);transform:translateY(40px)}30%,70%{opacity:1;-webkit-transform:translateY(0);-moz-transform:translateY(0);-ms-transform:translateY(0);-o-transform:translateY(0);transform:translateY(0)}100%{opacity:0;-webkit-transform:translateY(-40px);-moz-transform:translateY(-40px);-ms-transform:translateY(-40px);-o-transform:translateY(-40px);transform:translateY(-40px)}}@-moz-keyframes passing-through{0%{opacity:0;-webkit-transform:translateY(40px);-moz-transform:translateY(40px);-ms-transform:translateY(40px);-o-transform:translateY(40px);transform:translateY(40px)}30%,70%{opacity:1;-webkit-transform:translateY(0);-moz-transform:translateY(0);-ms-transform:translateY(0);-o-transform:translateY(0);transform:translateY(0)}100%{opacity:0;-webkit-transform:translateY(-40px);-moz-transform:translateY(-40px);-ms-transform:translateY(-40px);-o-transform:translateY(-40px);transform:translateY(-40px)}}@keyframes passing-through{0%{opacity:0;-webkit-transform:translateY(40px);-moz-transform:translateY(40px);-ms-transform:translateY(40px);-o-transform:translateY(40px);transform:translateY(40px)}30%,70%{opacity:1;-webkit-transform:translateY(0);-moz-transform:translateY(0);-ms-transform:translateY(0);-o-transform:translateY(0);transform:translateY(0)}100%{opacity:0;-webkit-transform:translateY(-40px);-moz-transform:translateY(-40px);-ms-transform:translateY(-40px);-o-transform:translateY(-40px);transform:translateY(-40px)}}@-webkit-keyframes slide-in{0%{opacity:0;-webkit-transform:translateY(40px);-moz-transform:translateY(40px);-ms-transform:translateY(40px);-o-transform:translateY(40px);transform:translateY(40px)}30%{opacity:1;-webkit-transform:translateY(0);-moz-transform:translateY(0);-ms-transform:translateY(0);-o-transform:translateY(0);transform:translateY(0)}}@-moz-keyframes slide-in{0%{opacity:0;-webkit-transform:translateY(40px);-moz-transform:translateY(40px);-ms-transform:translateY(40px);-o-transform:translateY(40px);transform:translateY(40px)}30%{opacity:1;-webkit-transform:translateY(0);-moz-transform:translateY(0);-ms-transform:translateY(0);-o-transform:translateY(0);transform:translateY(0)}}@keyframes slide-in{0%{opacity:0;-webkit-transform:translateY(40px);-moz-transform:translateY(40px);-ms-transform:translateY(40px);-o-transform:translateY(40px);transform:translateY(40px)}30%{opacity:1;-webkit-transform:translateY(0);-moz-transform:translateY(0);-ms-transform:translateY(0);-o-transform:translateY(0);transform:translateY(0)}}@-webkit-keyframes pulse{0%{-webkit-transform:scale(1);-moz-transform:scale(1);-ms-transform:scale(1);-o-transform:scale(1);transform:scale(1)}10%{-webkit-transform:scale(1.1);-moz-transform:scale(1.1);-ms-transform:scale(1.1);-o-transform:scale(1.1);transform:scale(1.1)}20%{-webkit-transform:scale(1);-moz-transform:scale(1);-ms-transform:scale(1);-o-transform:scale(1);transform:scale(1)}}@-moz-keyframes pulse{0%{-webkit-transform:scale(1);-moz-transform:scale(1);-ms-transform:scale(1);-o-transform:scale(1);transform:scale(1)}10%{-webkit-transform:scale(1.1);-moz-transform:scale(1.1);-ms-transform:scale(1.1);-o-transform:scale(1.1);transform:scale(1.1)}20%{-webkit-transform:scale(1);-moz-transform:scale(1);-ms-transform:scale(1);-o-transform:scale(1);transform:scale(1)}}@keyframes pulse{0%{-webkit-transform:scale(1);-moz-transform:scale(1);-ms-transform:scale(1);-o-transform:scale(1);transform:scale(1)}10%{-webkit-transform:scale(1.1);-moz-transform:scale(1.1);-ms-transform:scale(1.1);-o-transform:scale(1.1);transform:scale(1.1)}20%{-webkit-transform:scale(1);-moz-transform:scale(1);-ms-transform:scale(1);-o-transform:scale(1);transform:scale(1)}}.dropzone,.dropzone *{box-sizing:border-box}.dropzone.dz-clickable{cursor:pointer}.dropzone.dz-clickable *{cursor:default}.dropzone.dz-clickable .dz-message,.dropzone.dz-clickable .dz-message *{cursor:pointer}.dropzone.dz-started .dz-message{display:none}.dropzone.dz-drag-hover{border-style:solid}.dropzone.dz-drag-hover .dz-message{opacity:.5}.dropzone .dz-message{text-align:center;margin:2em 0}.dropzone .dz-preview{position:relative;display:inline-block;vertical-align:top;margin:16px;min-height:100px}.dropzone .dz-preview:hover{z-index:1000}.dropzone .dz-preview.dz-file-preview .dz-image{border-radius:20px;background:#999;background:linear-gradient(to bottom,#eee,#ddd)}.dropzone .dz-preview.dz-file-preview .dz-details{opacity:1}.dropzone .dz-preview.dz-image-preview{background:#fff}.dropzone .dz-preview.dz-image-preview .dz-details{-webkit-transition:opacity .2s linear;-moz-transition:opacity .2s linear;-ms-transition:opacity .2s linear;-o-transition:opacity .2s linear;transition:opacity .2s linear}.dropzone .dz-preview .dz-remove{font-size:14px;text-align:center;display:block;cursor:pointer;border:none}.dropzone .dz-preview .dz-remove:hover{text-decoration:underline}.dropzone .dz-preview:hover .dz-details{opacity:1}.dropzone .dz-preview .dz-details{z-index:20;position:absolute;top:0;left:0;opacity:0;font-size:13px;min-width:100%;max-width:100%;padding:2em 1em;text-align:center;color:rgba(0,0,0,.9);line-height:150%}.dropzone .dz-preview .dz-details .dz-size{margin-bottom:1em;font-size:16px}.dropzone .dz-preview .dz-details .dz-filename{white-space:nowrap}.dropzone .dz-preview .dz-details .dz-filename:hover span{border:1px solid rgba(200,200,200,.8);background-color:rgba(255,255,255,.8)}.dropzone .dz-preview .dz-details .dz-filename:not(:hover){overflow:hidden;text-overflow:ellipsis}.dropzone .dz-preview .dz-details .dz-filename:not(:hover) span{border:1px solid transparent}.dropzone .dz-preview .dz-details .dz-filename span,.dropzone .dz-preview .dz-details .dz-size span{background-color:rgba(255,255,255,.4);padding:0 .4em;border-radius:3px}.dropzone .dz-preview:hover .dz-image img{-webkit-transform:scale(1.05,1.05);-moz-transform:scale(1.05,1.05);-ms-transform:scale(1.05,1.05);-o-transform:scale(1.05,1.05);transform:scale(1.05,1.05);-webkit-filter:blur(8px);filter:blur(8px)}.dropzone .dz-preview .dz-image{border-radius:20px;overflow:hidden;width:120px;height:120px;position:relative;display:block;z-index:10}.dropzone .dz-preview .dz-image img{display:block}.dropzone .dz-preview.dz-success .dz-success-mark{-webkit-animation:passing-through 3s cubic-bezier(.77,0,.175,1);-moz-animation:passing-through 3s cubic-bezier(.77,0,.175,1);-ms-animation:passing-through 3s cubic-bezier(.77,0,.175,1);-o-animation:passing-through 3s cubic-bezier(.77,0,.175,1);animation:passing-through 3s cubic-bezier(.77,0,.175,1)}.dropzone .dz-preview.dz-error .dz-error-mark{opacity:1;-webkit-animation:slide-in 3s cubic-bezier(.77,0,.175,1);-moz-animation:slide-in 3s cubic-bezier(.77,0,.175,1);-ms-animation:slide-in 3s cubic-bezier(.77,0,.175,1);-o-animation:slide-in 3s cubic-bezier(.77,0,.175,1);animation:slide-in 3s cubic-bezier(.77,0,.175,1)}.dropzone .dz-preview .dz-error-mark,.dropzone .dz-preview .dz-success-mark{pointer-events:none;opacity:0;z-index:500;position:absolute;display:block;top:50%;left:50%;margin-left:-27px;margin-top:-27px}.dropzone .dz-preview .dz-error-mark svg,.dropzone .dz-preview .dz-success-mark svg{display:block;width:54px;height:54px}.dropzone .dz-preview.dz-processing .dz-progress{opacity:1;-webkit-transition:all .2s linear;-moz-transition:all .2s linear;-ms-transition:all .2s linear;-o-transition:all .2s linear;transition:all .2s linear}.dropzone .dz-preview.dz-complete .dz-progress{opacity:0;-webkit-transition:opacity .4s ease-in;-moz-transition:opacity .4s ease-in;-ms-transition:opacity .4s ease-in;-o-transition:opacity .4s ease-in;transition:opacity .4s ease-in}.dropzone .dz-preview:not(.dz-processing) .dz-progress{-webkit-animation:pulse 6s ease infinite;-moz-animation:pulse 6s ease infinite;-ms-animation:pulse 6s ease infinite;-o-animation:pulse 6s ease infinite;animation:pulse 6s ease infinite}.dropzone .dz-preview .dz-progress{opacity:1;z-index:1000;pointer-events:none;position:absolute;height:16px;left:50%;top:50%;margin-top:-8px;width:80px;margin-left:-40px;background:rgba(255,255,255,.9);-webkit-transform:scale(1);border-radius:8px;overflow:hidden}.dropzone .dz-preview .dz-progress .dz-upload{background:#333;background:linear-gradient(to bottom,#666,#444);position:absolute;top:0;left:0;bottom:0;width:0;-webkit-transition:width 300ms ease-in-out;-moz-transition:width 300ms ease-in-out;-ms-transition:width 300ms ease-in-out;-o-transition:width 300ms ease-in-out;transition:width 300ms ease-in-out}.dropzone .dz-preview.dz-error .dz-error-message{display:block}.dropzone .dz-preview.dz-error:hover .dz-error-message{opacity:1;pointer-events:auto}.dropzone .dz-preview .dz-error-message{pointer-events:none;z-index:1000;position:absolute;display:block;display:none;opacity:0;-webkit-transition:opacity .3s ease;-moz-transition:opacity .3s ease;-ms-transition:opacity .3s ease;-o-transition:opacity .3s ease;transition:opacity .3s ease;border-radius:8px;font-size:13px;top:130px;left:-10px;width:140px;background:#be2626;background:linear-gradient(to bottom,#be2626,#a92222);padding:.5em 1.2em;color:#fff}.dropzone .dz-preview .dz-error-message:after{content:'';position:absolute;top:-6px;left:64px;width:0;height:0;border-left:6px solid transparent;border-right:6px solid transparent;border-bottom:6px solid #be2626}/*! + * jQuery contextMenu - Plugin for simple contextMenu handling + * + * Version: 1.6.6 + * + * Authors: Rodney Rehm, Addy Osmani (patches for FF) + * Web: http://medialize.github.com/jQuery-contextMenu/ + * + * Licensed under + * MIT License http://www.opensource.org/licenses/mit-license + * GPL v3 http://opensource.org/licenses/GPL-3.0 + * + */.context-menu-list{min-width:120px;max-width:250px;display:inline-block;position:absolute;list-style-type:none;border:1px solid #DDD;-webkit-box-shadow:0 2px 5px rgba(0,0,0,.5);-moz-box-shadow:0 2px 5px rgba(0,0,0,.5);-ms-box-shadow:0 2px 5px rgba(0,0,0,.5);-o-box-shadow:0 2px 5px rgba(0,0,0,.5);box-shadow:0 2px 5px rgba(0,0,0,.5)}.context-menu-item>label>input,.context-menu-item>label>textarea{-webkit-user-select:text;-moz-user-select:text;-ms-user-select:text;user-select:text}.context-menu-item.hover{cursor:pointer}.context-menu-item.disabled{color:#666}.context-menu-submenu:after{content:">";color:#666;position:absolute;top:0;right:3px;z-index:1}.context-menu-item.icon{min-height:18px;background-repeat:no-repeat}.context-menu-input>label>*{vertical-align:top}.context-menu-input>label>input[type=checkbox],.context-menu-input>label>input[type=radio]{margin-left:-17px}.context-menu-input>label>span{margin-left:5px}.context-menu-input>label,.context-menu-input>label>input[type=text],.context-menu-input>label>select,.context-menu-input>label>textarea{display:block;width:100%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;-ms-box-sizing:border-box;-o-box-sizing:border-box;box-sizing:border-box}.context-menu-input>label>textarea{height:100px}.context-menu-item>.context-menu-list{display:none;right:-5px;top:5px}.context-menu-item.hover>.context-menu-list{display:block}.context-menu-accesskey{text-decoration:underline}*,:after,:before{box-sizing:border-box}body,html{font-family:'Open Sans',sans-serif;font-size:100%;padding:0;margin:0}body{padding-top:32px;font-weight:200;background:#ececec;overflow:-moz-scrollbars-vertical}.btn{background-image:none!important;text-shadow:none!important;border-color:none!important;box-shadow:none!important}.btn:focus{outline:0}.btn-inverse{background-image:none!important;background:#333}pre.no-prettify,pre.prettyprint{height:300px;margin:0!important;width:100%!important;overflow:scroll;border-radius:0!important}.input-append .add-on:last-child,.input-append .btn-group:last-child>.dropdown-toggle,.input-append .btn:last-child{border-radius:0!important}[class*=" rficon-"],[class^=rficon-]{display:inline-block;width:16px;height:16px;margin-top:1px;line-height:16px;vertical-align:text-top;background-position:0 0;background-repeat:no-repeat}.rficon-clipboard-apply{background-image:url(../img/clipboard_apply.png)}.rficon-clipboard-clear{background-image:url(../img/clipboard_clear.png)}.rficon-upload{background-image:url(../img/upload.png)}.btn{border-radius:0}.container-fluid{margin-top:10px!important}.img-precontainer{margin:auto;width:100%;text-align:center;background:#fff;border:none}.img-container{height:91px;width:122px;padding:0;border:none;overflow:hidden;display:table-cell;text-align:center;vertical-align:middle;margin:auto;background-image:url(../img/trans.jpg);background-size:13px}.img-container img{max-width:122px;max-height:91px}ul.breadcrumb{margin-bottom:5px;border-radius:0;padding-bottom:4px;padding-top:6px;background:#f0f0f0;box-shadow:0 1px 4px rgba(0,0,0,.065);border-bottom:1px solid #bbb}ul.breadcrumb .pull-left i{margin-top:2px}.alert{padding:8px 35px 8px 14px;margin-bottom:2px;border:1px solid #aaa;color:#666;font-weight:200;font-size:13px;border-radius:0;background:#fff}.img-container *,.img-container-mini *{vertical-align:middle}#help{display:none}.text-center{text-align:center}iframe{overflow:auto;-webkit-overflow-scrolling:touch}.upload-help{font-size:11px;font-weight:200;color:#777;text-shadow:0 1px 0 #fff;text-align:center}.upload-tabbable{margin-left:5px;margin-right:5px}.upload-tabbable .nav{margin:0}.upload-tabbable .nav li a{font-size:13px;font-weight:200;color:#777;text-shadow:0 1px 0 #fff}.upload-tabbable .tab-content{padding:5px;border-bottom:1px solid #ddd;border-left:1px solid #ddd;border-right:1px solid #ddd;background:#fff;margin-bottom:5px;height:400px;overflow-y:scroll}input#filter-input{margin:0 0 2px;width:84px;height:26px;vertical-align:bottom;border-radius:0;font-size:12px;font-weight:200;position:relative;left:1px}.qq-uploader .span9{margin-left:14px!important;width:690px!important}.space10{clear:both;height:10px}h4{font-size:12px;font-weight:200;margin:6px 0 0;text-align:center;padding:0;line-height:18px}h3{font-size:14px;font-weight:200}.boxes{border:1px solid #CCC;word-wrap:break-word;background:#fff;box-shadow:1px 1px 2px 0 rgba(0,0,0,.2);min-height:115px;text-align:center}.container-fluid{padding:0 10px!important}body .avpw .avpw_primary_button,body .avpw .avpw_primary_button:active,body .avpw .avpw_primary_button:link,body .avpw .avpw_primary_button:visited{color:#fff;background:#999;border:none}body .avpw .avpw_primary_button:hover{border:none;background:#666}.uploader{position:fixed;top:50px;left:14px;margin:auto;width:100%;z-index:9999;overflow:hidden;background:#eee;padding-top:20px;border:1px solid #ccc;display:none;box-shadow:0 0 10px 0 rgba(1,1,1,.5)}.download-form{margin-bottom:25px}.grid li i{margin-left:2px;margin-right:2px;z-index:0}.box,.boxx{word-wrap:break-word;vertical-align:top;text-align:left;position:relative;border:none;box-shadow:none;z-index:100;padding:4px}.box .btn{width:100%;background:0 0;box-shadow:none;border:none;z-index:200}.navbar{margin-bottom:0;border-bottom:1px solid #bbb}.navbar .navbar-inner{border:none;min-height:35px;border-radius:0;padding-bottom:2px;margin:0;padding-right:8px;padding-left:8px}.navbar .navbar-inner .container-fluid{margin:0;margin-top:0!important;padding:0}.navbar .navbar-inner .container-fluid .brand{display:none}.navbar .navbar-inner .container-fluid .filters span{margin-top:0;font-size:13px;font-weight:200;color:#777;text-shadow:0 1px 0 #fff}ul.sorting{position:absolute;left:-25px;top:20px;min-width:0;background:#eee}ul.sorting li a:hover{background:#aaa}.btn-group .dropdown-toggle.sorting-btn{background:0 0;border:none;box-shadow:none;position:relative;-webkit-box-shadow:none;top:-5px;font-size:13px}.btn-group .dropdown-toggle.sorting-btn:hover{background:0 0;border:none;box-shadow:none;-webkit-box-shadow:none}ul.sorting.dropdown-menu>li>a{font-size:12px;text-shadow:none}ul.sorting.dropdown-menu>li>a.descending{background-image:url(../img/down.png);background-repeat:no-repeat;background-position:6px 8px}ul.sorting.dropdown-menu>li>a.ascending{background-image:url(../img/up.png);background-repeat:no-repeat;background-position:6px 8px}.sorter-container{margin-top:5px;margin-bottom:0;border-radius:0;padding-bottom:4px;padding-top:6px;box-shadow:0 1px 4px rgba(0,0,0,.065);background-color:#f5f5f5;position:relative;border-bottom:1px solid #bbb;height:24px}.sorter-container a.sorter{color:#000}.sorter-container a.descending{padding-left:9px;background-image:url(../img/down.png);background-repeat:no-repeat;background-position:0 3px}.sorter-container a.ascending{padding-left:9px;background-image:url(../img/up.png);background-repeat:no-repeat;background-position:0 4px}.sorter-container .file-date,.sorter-container .file-extension,.sorter-container .file-name,.sorter-container .file-operations,.sorter-container .file-size,.sorter-container .img-dimension{display:block;position:absolute;top:0;z-index:100;box-shadow:none;text-align:left;font-size:13px;margin-top:1px;color:#999}.sorter-container .file-operations{width:110px;right:0}.sorter-container .img-dimension{width:65px;right:123px}.sorter-container .file-date{width:70px;right:188px}.sorter-container .file-size{width:55px;right:258px}.sorter-container .file-extension{width:40px;right:313px}.sorter-container .file-name{width:50px;left:52px}.file-date,.file-extension,.file-name,.file-operations,.file-size,.img-dimension{font-size:12px;font-weight:200;color:#777;text-shadow:0 1px 0 #fff;display:none}.view-controller{text-align:left}.view-controller .btn-group>.btn:first-child,.view-controller .btn-group>.btn:last-child{border-radius:0}.navbar .filters .btn{margin-bottom:2px;padding:2px 8px;margin-top:5px}.filters .types{text-align:right}@media (max-width:780px){#view2{display:none}}@media (min-width:840px){.mobile-inline-visible{display:none!important}}@media (max-width:839px){body{padding-top:0}.mobile-inline-visible{display:inline!important}.filters .types{text-align:left}.navbar .navbar-inner .container-fluid .brand{display:block}.navbar .navbar-inner{padding-bottom:4px}.filters div.span2.half,.filters div.span3.half,.filters div.span4.half{float:left;width:auto;margin-right:10px}.filters div.entire{float:none;width:100%;clear:both}.container-fluid{margin:0!important;padding:0}#qLbar{height:50px!important}}@media (min-width:400px) and (max-width:839px){.filters .row-fluid .half{width:48.61878453038674%;float:left}}.tooltip.in{z-index:10000;opacity:1;filter:alpha(opacity=1);font-weight:700}.tooltip{font-weight:700;z-index:10000}.grid{padding:0;margin:0 auto;list-style:none;-webkit-overflow-scrolling:touch}.ui-draggable-helper{z-index:10}.grid li{display:inline-block;width:124px;border:none;margin:4px 4px 8px;padding:0;vertical-align:top}.grid figure{position:relative;display:block;width:122px;margin:auto}.grid figure:hover{background:#e0e0e0!important}.list-view1.grid li,.list-view1.grid li figure{width:100%}.grid figcaption{text-align:center;padding:8px 2px 2px;color:#fff;height:30px;width:122px;margin-left:0;margin-right:0;position:absolute;top:auto;bottom:0;box-shadow:inset 0 0 8px 0 rgba(41,41,41,.5)}.grid figcaption a{margin:0;padding:3px}.grid figcaption h3{margin:0;padding:0;color:#fff}.grid h4{text-align:center;color:#000;padding:0;margin-bottom:4px;margin-top:4px}.grid figure .box{box-sizing:content-box;cursor:pointer}.list-view0.grid figure .box,.list-view1.grid figure .box,.list-view2.grid figure .box{max-width:100%;display:block;position:relative;overflow:hidden;z-index:1}.list-view0.grid figure .box h4.ellipsis,.list-view1.grid figure .box h4.ellipsis,.list-view2.grid figure .box h4.ellipsis{height:18px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.list-view0.grid figure .box h4,.list-view0.grid figure .box h4 a,.list-view1.grid figure .box h4,.list-view1.grid figure .box h4 a,.list-view2.grid figure .box h4,.list-view2.grid figure .box h4 a{z-index:1}.no-touch .list-view0 figure .box{z-index:1;transition:-webkit-transform .3s;transition:transform .3s}.list-view0.grid .ui-state-highlight .img-precontainer{background:grey!important}.list-view0.grid .ui-state-highlight .img-precontainer .img-container{background:repeating-linear-gradient(45deg,transparent,transparent 5px,rgba(255,255,255,.4) 5px,rgba(255,255,255,.3) 10px);border:none;overflow:hidden}.list-view0.grid .ui-state-hover .img-precontainer .img-container{background:#666}.list-view1.grid .ui-state-highlight:nth-child(odd) figure,.list-view2.grid .ui-state-highlight:nth-child(odd) figure{background:#ddd!important;border-bottom-color:#444!important}.list-view1.grid .ui-state-highlight:nth-child(even) figure,.list-view2.grid .ui-state-highlight:nth-child(even) figure{background:#ccc!important;border-bottom-color:#aaa!important}.list-view1.grid .ui-state-highlight.ui-state-hover figure,.list-view2.grid .ui-state-highlight.ui-state-hover figure{background-color:#aaa!important}.no-touch .list-view0 figure.cs-hover .box,.no-touch .list-view0 figure:hover .box{box-shadow:0 0 4px 0 rgba(1,1,1,.5);-webkit-transform:translateY(-26px);transform:translateY(-26px)}.list-view0 figure.cs-hover .box.no-effect,.list-view0 figure:hover .box.no-effect,.no-effect{box-shadow:none;-webkit-transform:none;transform:none}.list-view0 .img-precontainer-mini{display:none;background:0 0}a,a:hover{color:#000;text-decoration:none}.back-directory .box,.back-directory .img-precontainer,.back-directory .img-precontainer-mini{background:0 0}form{margin:0;padding:0}.google-iframe,.viewer-iframe{width:100%;height:500px;border:none}.modal{width:60%;margin-left:-30%}.modal-body{padding:6px}.modal-body form,.modal-body input,.modal-body textarea{margin:0;border-radius:0}.modal-body .text-center{padding-bottom:6px}.modal-footer{padding:7px}.modal-header{padding:7px 8px!important}.modal-header h3{font-weight:300;font-size:20px}.list-view1.sorter-container{display:block}.list-view0.sorter-container,.list-view2.sorter-container{display:none}.list-view0.grid .img-precontainer .img-container img{max-width:122px!important;max-height:91px!important}.list-view0.grid .img-precontainer .img-container img.icon{width:122px;margin-top:0}.list-view0.grid .img-precontainer .filetype{position:absolute;top:0;width:122px;text-align:center;color:#fff;font-size:13px;line-height:22px}.list-view0.grid .cover{background:rgba(255,255,255,.25);width:122px;position:absolute;top:22px;right:0;height:69px}.list-view0.grid .box{background:#fff}.list-view0.grid .directory{background:#ddd}.list-view0.grid figure.back-directory .directory{background:#bbb}.list-view0.grid figcaption{background:#fff}.list-view0.grid .selected figure{border:none;height:126px}.list-view0.grid .selected figure .box,.list-view0.grid .selected figure figcaption,.list-view0.grid .selected figure>a{display:none}.list-view1.grid li,.list-view2.grid li{margin:0}.list-view1.grid li.back figure.back-directory,.list-view2.grid li.back figure.back-directory{height:34px}.list-view1.grid li:nth-child(odd) figure,.list-view2.grid li:nth-child(odd) figure{background:#f9f9f9}.list-view1.grid li:nth-child(odd) figure.directory,.list-view2.grid li:nth-child(odd) figure.directory{background:#eaeaea}.list-view1.grid li figure,.list-view2.grid li figure{border-bottom:1px solid #aaa;background:#fff}.list-view1.grid li figure.back-directory,.list-view2.grid li figure.back-directory{background:#bbb}.list-view1.grid li figure.back-directory .box,.list-view2.grid li figure.back-directory .box{background:0 0}.list-view1.grid li figure.directory,.list-view2.grid li figure.directory{background:#efefef}.list-view1.grid li figure.directory box,.list-view2.grid li figure.directory box{padding:0;min-height:10px}.list-view1.grid li figure .box,.list-view2.grid li figure .box{margin-left:50px;transition:none}.list-view1.grid li figure .box h4,.list-view2.grid li figure .box h4{padding-top:1px;font-size:13px;text-align:left}.list-view1.grid .img-precontainer-mini,.list-view2.grid .img-precontainer-mini{display:block;position:absolute;width:45px;height:34px;overflow:hidden;text-align:center}.list-view1.grid .img-precontainer-mini img,.list-view2.grid .img-precontainer-mini img{max-width:45px}.list-view1.grid .img-precontainer-mini .filetype,.list-view2.grid .img-precontainer-mini .filetype{position:absolute;top:1px;text-align:center;left:0;padding:1px 2px;font-size:13px;line-height:32px;width:45px;height:32px;color:#fff;background:#333}.list-view1.grid .cover,.list-view2.grid .cover{display:none}.list-view1.grid .img-container-mini,.list-view2.grid .img-container-mini{width:45px;height:34px;border:none;overflow:hidden;display:table-cell;text-align:center;vertical-align:middle;margin:auto}.list-view1.grid .img-precontainer-mini.original-thumb,.list-view2.grid .img-precontainer-mini.original-thumb{padding:0}.list-view1.grid .img-precontainer-mini.original-thumb img,.list-view2.grid .img-precontainer-mini.original-thumb img{width:auto;max-height:32px}.list-view1.grid .img-precontainer-mini.original-thumb img.original,.list-view2.grid .img-precontainer-mini.original-thumb img.original{width:auto;height:auto}.list-view1.grid .img-precontainer,.list-view2.grid .img-precontainer{display:none}.list-view1.grid figcaption,.list-view2.grid figcaption{background:0 0;width:120px;position:absolute;right:0;top:0;z-index:1;bottom:0;box-shadow:none;text-align:right}.list-view1.grid .selected figure,.list-view2.grid .selected figure{background:#ccc!important}.list-view1.grid .file-date,.list-view1.grid .file-extension,.list-view1.grid .file-size,.list-view1.grid .img-dimension{overflow:hidden;display:block;position:absolute;top:0;z-index:1;box-shadow:none;text-align:left;margin-top:7px}.list-view1.grid .img-dimension{width:65px;right:120px}.list-view1.grid .file-date{width:70px;right:185px}.list-view1.grid .file-size{width:55px;right:255px}.list-view1.grid .file-extension{width:40px;right:310px}.list-view1.grid figure .box{padding-right:352px}.list-view2.grid figure .box{padding-right:115px}@media (max-width:610px){.list-view1.grid figure .box{padding-right:312px}.list-view1.grid figure .file-extension,.sorter-container .file-extension{display:none}}@media (max-width:565px){.list-view1.grid figure .box{padding-right:257px}.list-view1.grid figure .file-size,.sorter-container .file-size{display:none}}@media (max-width:495px){.list-view1.grid figure .box{padding-right:187px}.list-view1.grid figure .file-date,.sorter-container .file-date{display:none}}@media (max-width:430px){.list-view1.grid figure .box{padding-right:115px}.list-view1.grid figure .img-dimension,.sorter-container .img-dimension{display:none}.breadcrumb{margin-left:0;margin-right:0}}.list-view1.grid .img-precontainer-mini .filetype.pdf,.list-view2.grid .img-precontainer-mini .filetype.pdf{background:#CB0011}.list-view1.grid .img-precontainer-mini .filetype.ai,.list-view2.grid .img-precontainer-mini .filetype.ai{background:#D6772F}.list-view1.grid .img-precontainer-mini .filetype.psd,.list-view2.grid .img-precontainer-mini .filetype.psd{background:#0960A4}.list-view1.grid .img-precontainer-mini .filetype.html,.list-view1.grid .img-precontainer-mini .filetype.xhtml,.list-view2.grid .img-precontainer-mini .filetype.html,.list-view2.grid .img-precontainer-mini .filetype.xhtml{background:#035BC4}.list-view1.grid .img-precontainer-mini .filetype.fla,.list-view1.grid .img-precontainer-mini .filetype.flv,.list-view2.grid .img-precontainer-mini .filetype.fla,.list-view2.grid .img-precontainer-mini .filetype.flv{background:#CF302E}.list-view1.grid .img-precontainer-mini .filetype.ppt,.list-view1.grid .img-precontainer-mini .filetype.pptx,.list-view2.grid .img-precontainer-mini .filetype.ppt,.list-view2.grid .img-precontainer-mini .filetype.pptx{background:#DA5B00}.list-view1.grid .img-precontainer-mini .filetype.css,.list-view1.grid .img-precontainer-mini .filetype.xls,.list-view1.grid .img-precontainer-mini .filetype.xlsx,.list-view2.grid .img-precontainer-mini .filetype.css,.list-view2.grid .img-precontainer-mini .filetype.xls,.list-view2.grid .img-precontainer-mini .filetype.xlsx{background:#1A712C}.list-view1.grid .img-precontainer-mini .filetype.doc,.list-view1.grid .img-precontainer-mini .filetype.docx,.list-view1.grid .img-precontainer-mini .filetype.rts,.list-view2.grid .img-precontainer-mini .filetype.doc,.list-view2.grid .img-precontainer-mini .filetype.docx,.list-view2.grid .img-precontainer-mini .filetype.rts{background:#002093}.list-view1.grid .img-precontainer-mini .filetype.gzip,.list-view1.grid .img-precontainer-mini .filetype.rar,.list-view1.grid .img-precontainer-mini .filetype.zip,.list-view2.grid .img-precontainer-mini .filetype.gzip,.list-view2.grid .img-precontainer-mini .filetype.rar,.list-view2.grid .img-precontainer-mini .filetype.zip{background:#FE9221}.list-view1.grid .img-precontainer-mini .filetype.avi,.list-view1.grid .img-precontainer-mini .filetype.mov,.list-view1.grid .img-precontainer-mini .filetype.mp4,.list-view1.grid .img-precontainer-mini .filetype.mpeg,.list-view1.grid .img-precontainer-mini .filetype.mpg,.list-view1.grid .img-precontainer-mini .filetype.webm,.list-view1.grid .img-precontainer-mini .filetype.wma,.list-view2.grid .img-precontainer-mini .filetype.avi,.list-view2.grid .img-precontainer-mini .filetype.mov,.list-view2.grid .img-precontainer-mini .filetype.mp4,.list-view2.grid .img-precontainer-mini .filetype.mpeg,.list-view2.grid .img-precontainer-mini .filetype.mpg,.list-view2.grid .img-precontainer-mini .filetype.webm,.list-view2.grid .img-precontainer-mini .filetype.wma{background:#31231E}.list-view1.grid .img-precontainer-mini .filetype.ac3,.list-view1.grid .img-precontainer-mini .filetype.aiff,.list-view1.grid .img-precontainer-mini .filetype.m4a,.list-view1.grid .img-precontainer-mini .filetype.mid,.list-view1.grid .img-precontainer-mini .filetype.mp3,.list-view1.grid .img-precontainer-mini .filetype.ogg,.list-view1.grid .img-precontainer-mini .filetype.wav,.list-view2.grid .img-precontainer-mini .filetype.ac3,.list-view2.grid .img-precontainer-mini .filetype.aiff,.list-view2.grid .img-precontainer-mini .filetype.m4a,.list-view2.grid .img-precontainer-mini .filetype.mid,.list-view2.grid .img-precontainer-mini .filetype.mp3,.list-view2.grid .img-precontainer-mini .filetype.ogg,.list-view2.grid .img-precontainer-mini .filetype.wav{background:#9F008B}.list-view1.grid .img-precontainer-mini .filetype.odb,.list-view1.grid .img-precontainer-mini .filetype.odf,.list-view1.grid .img-precontainer-mini .filetype.odg,.list-view1.grid .img-precontainer-mini .filetype.odp,.list-view1.grid .img-precontainer-mini .filetype.ods,.list-view1.grid .img-precontainer-mini .filetype.odt,.list-view1.grid .img-precontainer-mini .filetype.otg,.list-view1.grid .img-precontainer-mini .filetype.otp,.list-view1.grid .img-precontainer-mini .filetype.ots,.list-view1.grid .img-precontainer-mini .filetype.ott,.list-view2.grid .img-precontainer-mini .filetype.odb,.list-view2.grid .img-precontainer-mini .filetype.odf,.list-view2.grid .img-precontainer-mini .filetype.odg,.list-view2.grid .img-precontainer-mini .filetype.odp,.list-view2.grid .img-precontainer-mini .filetype.ods,.list-view2.grid .img-precontainer-mini .filetype.odt,.list-view2.grid .img-precontainer-mini .filetype.otg,.list-view2.grid .img-precontainer-mini .filetype.otp,.list-view2.grid .img-precontainer-mini .filetype.ots,.list-view2.grid .img-precontainer-mini .filetype.ott{background:#367BBE}.list-view1.grid .img-precontainer-mini .filetype.bmp,.list-view1.grid .img-precontainer-mini .filetype.gif,.list-view1.grid .img-precontainer-mini .filetype.jpeg,.list-view1.grid .img-precontainer-mini .filetype.jpg,.list-view1.grid .img-precontainer-mini .filetype.png,.list-view1.grid .img-precontainer-mini .filetype.svg,.list-view1.grid .img-precontainer-mini .filetype.tiff,.list-view2.grid .img-precontainer-mini .filetype.bmp,.list-view2.grid .img-precontainer-mini .filetype.gif,.list-view2.grid .img-precontainer-mini .filetype.jpeg,.list-view2.grid .img-precontainer-mini .filetype.jpg,.list-view2.grid .img-precontainer-mini .filetype.png,.list-view2.grid .img-precontainer-mini .filetype.svg,.list-view2.grid .img-precontainer-mini .filetype.tiff{background:#CFA554}.list-view1.grid .img-precontainer-mini .filetype.dmg,.list-view1.grid .img-precontainer-mini .filetype.iso,.list-view1.grid .img-precontainer-mini .filetype.log,.list-view1.grid .img-precontainer-mini .filetype.sql,.list-view1.grid .img-precontainer-mini .filetype.txt,.list-view1.grid .img-precontainer-mini .filetype.xml,.list-view2.grid .img-precontainer-mini .filetype.dmg,.list-view2.grid .img-precontainer-mini .filetype.iso,.list-view2.grid .img-precontainer-mini .filetype.log,.list-view2.grid .img-precontainer-mini .filetype.sql,.list-view2.grid .img-precontainer-mini .filetype.txt,.list-view2.grid .img-precontainer-mini .filetype.xml{background:#CACACA}.list-view1.grid .img-precontainer-mini .filetype.accdb,.list-view1.grid .img-precontainer-mini .filetype.ade,.list-view1.grid .img-precontainer-mini .filetype.adp,.list-view1.grid .img-precontainer-mini .filetype.mdb,.list-view2.grid .img-precontainer-mini .filetype.accdb,.list-view2.grid .img-precontainer-mini .filetype.ade,.list-view2.grid .img-precontainer-mini .filetype.adp,.list-view2.grid .img-precontainer-mini .filetype.mdb{background:#B61C19}.lightbox-content{overflow:hidden;padding:0;background:0 0;box-shadow:none;border-radius:0;border:0}.context-menu-list{font-family:'Open Sans',sans-serif;width:200px;background:#fff;font-size:12px;margin:0;padding:5px}.context-menu-item{background-color:#fff;position:relative;height:auto;word-wrap:break-word;-webkit-user-select:none;-moz-user-select:0;-ms-user-select:none;user-select:none;padding:5px 5px 5px 30px}.context-menu-item:last-child{border:none}.context-menu-separator{padding-bottom:0;border-bottom:1px solid #ddd}.context-menu-item.hover{background-color:#ddd}.context-menu-input.hover,.context-menu-item.disabled.hover{cursor:default;background-color:#eee}.context-menu-item.icon{vertical-align:middle;background-position:4px 5px;width:auto;display:list-item}.context-menu-item.icon-edit{background-image:url(../img/file_edit.png)}.context-menu-item.icon-cut{background-image:url(../img/cut.png)}.context-menu-item.icon-copy{background-image:url(../img/copy.png)}.context-menu-item.icon-rename{background-image:url(../img/rename.png)}.context-menu-item.icon-preview{background-image:url(../img/preview.png)}.context-menu-item.icon-dimension{background-image:url(../img/dimension.png)}.context-menu-item.icon-date{background-image:url(../img/date.png)}.context-menu-item.icon-label{background-image:url(../img/label.png)}.context-menu-item.icon-size{background-image:url(../img/size.png)}.context-menu-item.icon-download{background-image:url(../img/download.png)}.context-menu-item.icon-paste{background-image:url(../img/page_white_paste.png)}.context-menu-item.icon-clipboard-apply{background-image:url(../img/clipboard_apply.png)}.context-menu-item.icon-delete{background-image:url(../img/page_white_delete.png)}.context-menu-item.icon-add{background-image:url(../img/page_white_add.png)}.context-menu-item.icon-quit{background-image:url(../img/door.png)}.context-menu-item.icon-info{background-image:url(../img/info.png)}.context-menu-item.icon-extract{background-image:url(../img/zip.png)}.context-menu-item.icon-url{background-image:url(../img/url.png)}.context-menu-item.icon-edit_img{background-image:url(../img/edit_img.png)}.context-menu-item.icon-duplicate{background-image:url(../img/duplicate.png)}.context-menu-item.icon-key{background-image:url(../img/key.png)}.dropzone{border:1px solid rgba(0,0,0,.03);min-height:360px;border-radius:3px;background:rgba(0,0,0,.03);padding:23px}.dropzone .dz-success *{cursor:pointer!important}.dropzone .dz-default.dz-message{opacity:1;-ms-filter:none;-webkit-filter:none;filter:none;transition:opacity .3s ease-in-out;background-repeat:no-repeat;background-position:0 0;position:absolute;width:428px;height:123px;margin-left:-214px;margin-top:-61.5px;top:50%;left:50%}.btn-primary,.btn-primary.disabled,.btn-primary[disabled]{background-color:#333}.btn-primary.active,.btn-primary:active,.btn-primary:focus,.btn-primary:hover{background-color:#222} \ No newline at end of file diff --git a/local/modules/Tinymce/Resources/js/tinymce/filemanager/dialog.php b/local/modules/Tinymce/Resources/js/tinymce/filemanager/dialog.php new file mode 100644 index 00000000..9b2a1e7e --- /dev/null +++ b/local/modules/Tinymce/Resources/js/tinymce/filemanager/dialog.php @@ -0,0 +1,1161 @@ +isDir($ftp_base_folder.$upload_dir.$rfm_subfolder.$subdir)) || (!$ftp && !file_exists($current_path.$rfm_subfolder.$subdir))) +{ + $subdir = ''; + $rfm_subfolder = ""; +} + + +if (trim($rfm_subfolder) == "") +{ + $cur_dir = $upload_dir.$subdir; + $cur_path = $current_path.$subdir; + $thumbs_path = $thumbs_base_path; + $parent = $subdir; +} +else +{ + $cur_dir = $upload_dir.$rfm_subfolder.$subdir; + $cur_path = $current_path.$rfm_subfolder.$subdir; + $thumbs_path = $thumbs_base_path.$rfm_subfolder; + $parent = $rfm_subfolder.$subdir; +} + +if($ftp){ + $cur_dir = $ftp_base_folder.$cur_dir; + $cur_path = str_replace(array('/..','..'),'',$cur_dir); + $thumbs_path = str_replace(array('/..','..'),'',$ftp_base_folder.$ftp_thumbs_dir.$rfm_subfolder); + $parent = $ftp_base_folder.$parent; +} + +if(!$ftp){ + $cycle = TRUE; + $max_cycles = 50; + $i = 0; + while($cycle && $i < $max_cycles){ + $i++; + if ($parent=="./") $parent=""; + + if (file_exists($current_path.$parent."config.php")) + { + require_once $current_path.$parent."config.php"; + $cycle = FALSE; + } + + if ($parent == "") $cycle = FALSE; + else $parent = fix_dirname($parent)."/"; + } + + if (!is_dir($thumbs_path.$subdir)) + { + create_folder(FALSE, $thumbs_path.$subdir); + } +} +if (isset($_GET['callback'])) +{ + $callback = strip_tags($_GET['callback']); +} +else $callback=0; +if (isset($_GET['popup'])) +{ + $popup = strip_tags($_GET['popup']); +} else $popup=0; +//Sanitize popup +$popup=!!$popup; + +if (isset($_GET['crossdomain'])) +{ + $crossdomain = strip_tags($_GET['crossdomain']); +} else $crossdomain=0; + +//Sanitize crossdomain +$crossdomain=!!$crossdomain; + +//view type +if(!isset($_SESSION['RF']["view_type"])) +{ + $view = $default_view; + $_SESSION['RF']["view_type"] = $view; +} + +if (isset($_GET['view'])) +{ + $view = fix_get_params($_GET['view']); + $_SESSION['RF']["view_type"] = $view; +} + +$view = $_SESSION['RF']["view_type"]; + +//filter +$filter = ""; +if(isset($_SESSION['RF']["filter"])) +{ + $filter = $_SESSION['RF']["filter"]; +} + +if(isset($_GET["filter"])) +{ + $filter = fix_get_params($_GET["filter"]); +} + +if (!isset($_SESSION['RF']['sort_by'])) +{ + $_SESSION['RF']['sort_by'] = 'name'; +} + +if (isset($_GET["sort_by"])) +{ + $sort_by = $_SESSION['RF']['sort_by'] = fix_get_params($_GET["sort_by"]); +} else $sort_by = $_SESSION['RF']['sort_by']; + + +if (!isset($_SESSION['RF']['descending'])) +{ + $_SESSION['RF']['descending'] = TRUE; +} + +if (isset($_GET["descending"])) +{ + $descending = $_SESSION['RF']['descending'] = fix_get_params($_GET["descending"])==1; +} else { + $descending = $_SESSION['RF']['descending']; +} + +$boolarray = Array(false => 'false', true => 'true'); + +$return_relative_url = isset($_GET['relative_url']) && $_GET['relative_url'] == "1" ? true : false; + +if (!isset($_GET['type'])){ + $_GET['type'] = 0; +} + +if($_GET['type']==1 || $_GET['type']==3){ + $filter=''; +} + +$extensions=null; +if (isset($_GET['extensions'])){ + $extensions = json_decode(urldecode($_GET['extensions'])); + if($extensions){ + $ext = $extensions; + $show_filter_buttons = false; + } +} + +if (isset($_GET['editor'])) +{ + $editor = strip_tags($_GET['editor']); +} else { + if($_GET['type']==0){ + $editor=false; + } else { + $editor='tinymce'; + } +} + +if (!isset($_GET['field_id'])) $_GET['field_id'] = ''; + +$field_id = isset($_GET['field_id']) ? fix_get_params($_GET['field_id']) : ''; +$type_param = fix_get_params($_GET['type']); + +if ($type_param==1) $apply = 'apply_img'; +elseif($type_param==2) $apply = 'apply_link'; +elseif($type_param==0 && $_GET['field_id']=='') $apply = 'apply_none'; +elseif($type_param==3) $apply = 'apply_video'; +else $apply = 'apply'; + +$get_params = array( + 'editor' => $editor, + 'type' => $type_param, + 'lang' => $lang, + 'popup' => $popup, + 'crossdomain' => $crossdomain, + 'extensions' => ($extensions) ? urlencode(json_encode($extensions)) : null , + 'field_id' => $field_id, + 'relative_url' => $return_relative_url, + 'akey' => (isset($_GET['akey']) && $_GET['akey'] != '' ? $_GET['akey'] : 'key') +); +if(isset($_GET['CKEditorFuncNum'])){ + $get_params['CKEditorFuncNum'] = $_GET['CKEditorFuncNum']; + $get_params['CKEditor'] = (isset($_GET['CKEditor'])? $_GET['CKEditor'] : ''); +} +$get_params['fldr'] =''; + +$get_params = http_build_query($get_params); +?> + + + + + + + + Responsive FileManager + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + " /> + " /> + " /> + " /> + + + + +
    +
    + +
    +
    +
    +
    + +
    +
    +
    + + +
    +

    :


    + + + + + + + + + + +
    +
    +
    +
    + +
    +
    +
    +
    + +
    + +
    +
    +
    +
    + +
    +
    +
    +
    + + +
    +
    +
    +
    + +
    +
    + +
    + + + +
    + +scanDir("/".$ftp_base_folder.$upload_dir.$rfm_subfolder.$subdir); + if (!$ftp->isDir("/".$ftp_base_folder.$ftp_thumbs_dir.$rfm_subfolder.$subdir)){ + create_folder(false,"/".$ftp_base_folder.$ftp_thumbs_dir.$rfm_subfolder.$subdir,$ftp,$config); + } + }catch(FtpClient\FtpException $e){ + echo "Error: "; + echo $e->getMessage(); + echo "
    Please check configurations"; + die(); + } +}else{ + $files = scandir($current_path.$rfm_subfolder.$subdir); +} + +$n_files= count($files); + +//php sorting +$sorted=array(); +//$current_folder=array(); +//$prev_folder=array(); +$current_files_number = 0; +$current_folders_number = 0; + +foreach($files as $k=>$file){ + if($ftp){ + $date = strtotime($file['day']." ".$file['month']." ".date('Y')." ".$file['time']); + $size = $file['size']; + if($file['type']=='file'){ + $current_files_number++; + $file_ext = substr(strrchr($file['name'],'.'),1); + }else{ + $current_folders_number++; + $file_ext=trans('Type_dir'); + } + $sorted[$k]=array( + 'file'=>$file['name'], + 'file_lcase'=>strtolower($file['name']), + 'date'=>$date, + 'size'=>$size, + 'permissions' => $file['permissions'], + 'extension'=>strtolower($file_ext) + ); + }else{ + + + if($file!="." && $file!=".."){ + if(is_dir($current_path.$rfm_subfolder.$subdir.$file)){ + $date=filemtime($current_path.$rfm_subfolder.$subdir. $file); + $current_folders_number++; + if($show_folder_size){ + list($size,$nfiles,$nfolders) = folder_info($current_path.$rfm_subfolder.$subdir.$file,false); + } else { + $size=0; + } + $file_ext=trans('Type_dir'); + $sorted[$k]=array( + 'file'=>$file, + 'file_lcase'=>strtolower($file), + 'date'=>$date, + 'size'=>$size, + 'permissions' =>'', + 'extension'=>strtolower($file_ext) + ); + if($show_folder_size){ + $sorted[$k]['nfiles'] = $nfiles; + $sorted[$k]['nfolders'] = $nfolders; + } + }else{ + $current_files_number++; + $file_path=$current_path.$rfm_subfolder.$subdir.$file; + $date=filemtime($file_path); + $size=filesize($file_path); + $file_ext = substr(strrchr($file,'.'),1); + $sorted[$k]=array( + 'file'=>$file, + 'file_lcase'=>strtolower($file), + 'date'=>$date, + 'size'=>$size, + 'permissions' =>'', + 'extension'=>strtolower($file_ext) + ); + } + } + } +} + + +// Should lazy loading be enabled +$lazy_loading_enabled= ($lazy_loading_file_number_threshold == 0 || $lazy_loading_file_number_threshold != -1 && $n_files > $lazy_loading_file_number_threshold) ? true : false; + +function filenameSort($x, $y) { + return $x['file_lcase'] < $y['file_lcase']; +} +function dateSort($x, $y) { + return $x['date'] < $y['date']; +} +function sizeSort($x, $y) { + return $x['size'] < $y['size']; +} +function extensionSort($x, $y) { + return $x['extension'] < $y['extension']; +} + +switch($sort_by){ + case 'date': + usort($sorted, 'dateSort'); + break; + case 'size': + usort($sorted, 'sizeSort'); + break; + case 'extension': + usort($sorted, 'extensionSort'); + break; + default: + usort($sorted, 'filenameSort'); + break; +} + +if(!$descending){ + $sorted=array_reverse($sorted); +} + +if($subdir!=""){ + $sorted = array_merge(array(array('file'=>'..')),$sorted); +} +$files=$sorted; + +?> + + + + + + + +
    + + +
    + +
    +
    + isDir($ftp_base_folder.$upload_dir.$rfm_subfolder.$subdir)) || (!$ftp && @opendir($current_path.$rfm_subfolder.$subdir)===FALSE)){ ?> +
    +
    There is an error! The upload folder there isn't. Check your config.php file.
    + +

    + +
    + + + + + + + + +
      " id="main-item-container"> + $file_number_limit_js && $file!=".." && stripos($file,$filter)===false)){ + continue; + } + $new_name=fix_filename($file,$config); + if($ftp && $file!='..' && $file!=$new_name){ + //rename + rename_folder($current_path.$subdir.$file,$new_name,$ftp,$config); + $file=$new_name; + } + //add in thumbs folder if not exist + if($file!='..'){ + if(!$ftp && !file_exists($thumbs_path.$subdir.$file)){ + create_folder(false,$thumbs_path.$subdir.$file,$ftp,$config); + } + } + + $class_ext = 3; + if($file=='..' && trim($subdir) != '' ){ + $src = explode("/",$subdir); + unset($src[count($src)-2]); + $src=implode("/",$src); + if($src=='') $src="/"; + } + elseif ($file!='..') { + $src = $subdir . $file."/"; + } + + ?> + + $file_array) { + $file=$file_array['file']; + + if($file == '.' || $file == '..' || $file_array['extension']==trans('Type_dir') || in_array($file, $hidden_files) || !in_array(fix_strtolower($file_array['extension']), $ext) || ($filter!='' && $n_files>$file_number_limit_js && stripos($file,$filter)===false)) + continue; + + $filename=substr($file, 0, '-' . (strlen($file_array['extension']) + 1)); + if(!$ftp){ + $file_path=$current_path.$rfm_subfolder.$subdir.$file; + //check if file have illegal caracter + + if($file!=fix_filename($file,$config)){ + $file1=fix_filename($file,$config); + $file_path1=($current_path.$rfm_subfolder.$subdir.$file1); + if(file_exists($file_path1)){ + $i = 1; + $info=pathinfo($file1); + while(file_exists($current_path.$rfm_subfolder.$subdir.$info['filename'].".[".$i."].".$info['extension'])) { + $i++; + } + $file1=$info['filename'].".[".$i."].".$info['extension']; + $file_path1=($current_path.$rfm_subfolder.$subdir.$file1); + } + + $filename=substr($file1, 0, '-' . (strlen($file_array['extension']) + 1)); + rename_file($file_path,fix_filename($filename,$config),$ftp,$config); + $file=$file1; + $file_array['extension']=fix_filename($file_array['extension'],$config); + $file_path=$file_path1; + } + }else{ + $file_path = $config['ftp_base_url'].$upload_dir.$rfm_subfolder.$subdir.$file; + } + + $is_img=false; + $is_video=false; + $is_audio=false; + $show_original=false; + $show_original_mini=false; + $mini_src=""; + $src_thumb=""; + if(in_array($file_array['extension'], $ext_img)){ + $src = $base_url.$cur_dir.$file; + $is_img=true; + + $img_width = $img_height = ""; + if($ftp){ + $mini_src = $src_thumb = $config['ftp_base_url'].$ftp_thumbs_dir.$subdir. $file; + $creation_thumb_path = "/".$config['ftp_base_folder'].$ftp_thumbs_dir.$subdir. $file; + }else{ + + $creation_thumb_path = $mini_src = $src_thumb = $thumbs_path.$subdir. $file; + + if(!file_exists($src_thumb) ){ + if(!create_img($file_path, $creation_thumb_path, 122, 91,'crop',$ftp,$config)){ + $src_thumb=$mini_src=""; + }else{ + new_thumbnails_creation($current_path.$rfm_subfolder.$subdir,$file_path,$file,$current_path,'','','','','','','',$fixed_image_creation,$fixed_path_from_filemanager,$fixed_image_creation_name_to_prepend,$fixed_image_creation_to_append,$fixed_image_creation_width,$fixed_image_creation_height,$fixed_image_creation_option); + } + } + //check if is smaller than thumb + list($img_width, $img_height, $img_type, $attr)=@getimagesize($file_path); + if($img_width<122 && $img_height<91){ + $src_thumb=$file_path; + $show_original=true; + } + + if($img_width<45 && $img_height<38){ + $mini_src=$current_path.$rfm_subfolder.$subdir.$file; + $show_original_mini=true; + } + } + } + $is_icon_thumb=false; + $is_icon_thumb_mini=false; + $no_thumb=false; + if($src_thumb==""){ + $no_thumb=true; + if(file_exists('img/'.$icon_theme.'/'.$file_array['extension'].".jpg")){ + $src_thumb ='img/'.$icon_theme.'/'.$file_array['extension'].".jpg"; + }else{ + $src_thumb = "img/".$icon_theme."/default.jpg"; + } + $is_icon_thumb=true; + } else { + $src_thumb = $base_url.$thumbs_dir.$subdir.$file; + } + if($mini_src==""){ + $is_icon_thumb_mini=false; + } else { + $mini_src = $src_thumb; + } + + $class_ext=0; + if (in_array($file_array['extension'], $ext_video)) { + $class_ext = 4; + $is_video=true; + }elseif (in_array($file_array['extension'], $ext_img)) { + $class_ext = 2; + }elseif (in_array($file_array['extension'], $ext_music)) { + $class_ext = 5; + $is_audio=true; + }elseif (in_array($file_array['extension'], $ext_misc)) { + $class_ext = 3; + }else{ + $class_ext = 1; + } + if((!($_GET['type']==1 && !$is_img) && !(($_GET['type']==3 && !$is_video) && ($_GET['type']==3 && !$is_audio))) && $class_ext>0){ +?> + +
    + + +
    +
    + + + + + + + + + + + + + + + + + + + + + + diff --git a/local/modules/Tinymce/Resources/js/tinymce/filemanager/execute.php b/local/modules/Tinymce/Resources/js/tinymce/filemanager/execute.php new file mode 100644 index 00000000..3229d55a --- /dev/null +++ b/local/modules/Tinymce/Resources/js/tinymce/filemanager/execute.php @@ -0,0 +1,524 @@ +send(); + exit; +} + +if (strpos($_POST['path'],'/')===0 + || strpos($_POST['path'],'../')!==FALSE + || strpos($_POST['path'],'./')===0 + || strpos($_POST['path'],'..\\')!==FALSE + || strpos($_POST['path'],'.\\')===0) +{ + response(trans('wrong path'.AddErrorLocation()))->send(); + exit; +} + +if (isset($_SESSION['RF']['language']) && file_exists('lang/' . basename($_SESSION['RF']['language']) . '.php')) +{ + $languages = include 'lang/languages.php'; + if(array_key_exists($_SESSION['RF']['language'],$languages)){ + include 'lang/' . basename($_SESSION['RF']['language']) . '.php'; + }else{ + response(trans('Lang_Not_Found').AddErrorLocation())->send(); + exit; + } +} +else +{ + response(trans('Lang_Not_Found').AddErrorLocation())->send(); + exit; +} + +$ftp = ftp_con($config); + +$base = $current_path; +$path = $base.$_POST['path']; +$cycle = TRUE; +$max_cycles = 50; +$i = 0; +while($cycle && $i<$max_cycles) +{ + $i++; + if ($path == $base) $cycle=FALSE; + + if (file_exists($path."config.php")) + { + require_once $path."config.php"; + $cycle = FALSE; + } + $path = fix_dirname($path)."/"; +} + +$path = $current_path.$_POST['path']; +$path_thumb = $thumbs_base_path.$_POST['path']; + +if($ftp){ + $path = $ftp_base_folder.$upload_dir.$_POST['path']; + $path_thumb = $ftp_base_folder.$ftp_thumbs_dir.$_POST['path']; +} + +if (isset($_POST['name'])) +{ + $name = fix_filename($_POST['name'],$config); + if (strpos($name,'../') !== FALSE || strpos($name,'..\\') !== FALSE) + { + response(trans('wrong name').AddErrorLocation())->send(); + exit; + } +} + +$info = pathinfo($path); +if (isset($info['extension']) && !(isset($_GET['action']) && $_GET['action']=='delete_folder') && !in_array(strtolower($info['extension']), $ext) && $_GET['action'] != 'create_file') +{ + response(trans('wrong extension').AddErrorLocation())->send(); + exit; +} + +if (isset($_GET['action'])) +{ + switch($_GET['action']) + { + case 'delete_file': + if ($delete_files){ + if($ftp){ + try{ + $ftp->delete("/".$path); + @$ftp->delete("/".$path_thumb); + }catch(FtpClient\FtpException $e){ + return; + } + }else{ + + unlink($path); + if (file_exists($path_thumb)){ + unlink($path_thumb); + } + } + + $info=pathinfo($path); + if (!$ftp && $relative_image_creation){ + foreach($relative_path_from_current_pos as $k=>$path) + { + if ($path!="" && $path[strlen($path)-1]!="/") $path.="/"; + + if (file_exists($info['dirname']."/".$path.$relative_image_creation_name_to_prepend[$k].$info['filename'].$relative_image_creation_name_to_append[$k].".".$info['extension'])) + { + unlink($info['dirname']."/".$path.$relative_image_creation_name_to_prepend[$k].$info['filename'].$relative_image_creation_name_to_append[$k].".".$info['extension']); + } + } + } + + if (!$ftp && $fixed_image_creation) + { + foreach($fixed_path_from_filemanager as $k=>$path) + { + if ($path!="" && $path[strlen($path)-1] != "/") $path.="/"; + + $base_dir=$path.substr_replace($info['dirname']."/", '', 0, strlen($current_path)); + if (file_exists($base_dir.$fixed_image_creation_name_to_prepend[$k].$info['filename'].$fixed_image_creation_to_append[$k].".".$info['extension'])) + { + unlink($base_dir.$fixed_image_creation_name_to_prepend[$k].$info['filename'].$fixed_image_creation_to_append[$k].".".$info['extension']); + } + } + } + } + break; + case 'delete_folder': + if ($delete_folders){ + + if($ftp){ + deleteDir($path,$ftp,$config); + deleteDir($path_thumb,$ftp,$config); + }else{ + if (is_dir($path_thumb)) + { + deleteDir($path_thumb); + } + + if (is_dir($path)) + { + deleteDir($path); + if ($fixed_image_creation) + { + foreach($fixed_path_from_filemanager as $k=>$paths){ + if ($paths!="" && $paths[strlen($paths)-1] != "/") $paths.="/"; + + $base_dir=$paths.substr_replace($path, '', 0, strlen($current_path)); + if (is_dir($base_dir)) deleteDir($base_dir); + } + } + } + } + } + break; + case 'create_folder': + if ($create_folders) + { + + $name = fix_filename($_POST['name'],$config); + $path .= $name; + $path_thumb .= $name; + create_folder(fix_path($path,$config),fix_path($path_thumb,$config),$ftp,$config); + } + break; + case 'rename_folder': + if ($rename_folders){ + $name=fix_filename($name,$config); + $name=str_replace('.','',$name); + + if (!empty($name)){ + if (!rename_folder($path,$name,$ftp,$config)) + { + response(trans('Rename_existing_folder').AddErrorLocation())->send(); + exit; + } + rename_folder($path_thumb,$name,$ftp,$config); + if (!$ftp && $fixed_image_creation){ + foreach($fixed_path_from_filemanager as $k=>$paths){ + if ($paths!="" && $paths[strlen($paths)-1] != "/") $paths.="/"; + + $base_dir=$paths.substr_replace($path, '', 0, strlen($current_path)); + rename_folder($base_dir,$name,$ftp,$config); + } + } + } else { + response(trans('Empty_name').AddErrorLocation())->send(); + exit; + } + } + break; + case 'create_file': + if ($create_text_files === FALSE) { + response(sprintf(trans('File_Open_Edit_Not_Allowed'), strtolower(trans('Edit'))).AddErrorLocation())->send(); + exit; + } + + if (!isset($editable_text_file_exts) || !is_array($editable_text_file_exts)){ + $editable_text_file_exts = array(); + } + + // check if user supplied extension + if (strpos($name, '.') === FALSE){ + response(trans('No_Extension').' '.sprintf(trans('Valid_Extensions'), implode(', ', $editable_text_file_exts)).AddErrorLocation())->send(); + exit; + } + + // correct name + $old_name = $name; + $name=fix_filename($name,$config); + if (empty($name)) + { + response(trans('Empty_name').AddErrorLocation())->send(); + exit; + } + + // check extension + $parts = explode('.', $name); + if (!in_array(end($parts), $editable_text_file_exts)) { + response(trans('Error_extension').' '.sprintf(trans('Valid_Extensions'), implode(', ', $editable_text_file_exts)), 400)->send(); + exit; + } + + $content = $_POST['new_content']; + + if($ftp){ + $tmp = time().$name; + file_put_contents($tmp, $content); + $ftp->put("/".$path.$name, $tmp, FTP_BINARY); + unlink($tmp); + response(trans('File_Save_OK'))->send(); + }else{ + if (!checkresultingsize(strlen($content))) { + response(sprintf(trans('max_size_reached'),$MaxSizeTotal).AddErrorLocation())->send(); + exit; + } + // file already exists + if (file_exists($path.$name)) { + response(trans('Rename_existing_file').AddErrorLocation())->send(); + exit; + } + + if (@file_put_contents($path.$name, $content) === FALSE) { + response(trans('File_Save_Error').AddErrorLocation())->send(); + exit; + } else { + if (is_function_callable('chmod') !== FALSE){ + chmod($path.$name, 0644); + } + response(trans('File_Save_OK'))->send(); + exit; + } + } + + break; + case 'rename_file': + if ($rename_files){ + $name=fix_filename($name,$config); + if (!empty($name)) + { + if (!rename_file($path,$name,$ftp,$config)) + { + response(trans('Rename_existing_file').AddErrorLocation())->send(); + exit; + } + + rename_file($path_thumb,$name,$ftp,$config); + + if ($fixed_image_creation) + { + $info=pathinfo($path); + + foreach($fixed_path_from_filemanager as $k=>$paths) + { + if ($paths!="" && $paths[strlen($paths)-1] != "/") $paths.="/"; + + $base_dir = $paths.substr_replace($info['dirname']."/", '', 0, strlen($current_path)); + if (file_exists($base_dir.$fixed_image_creation_name_to_prepend[$k].$info['filename'].$fixed_image_creation_to_append[$k].".".$info['extension'])) + { + rename_file($base_dir.$fixed_image_creation_name_to_prepend[$k].$info['filename'].$fixed_image_creation_to_append[$k].".".$info['extension'],$fixed_image_creation_name_to_prepend[$k].$name.$fixed_image_creation_to_append[$k],$ftp,$config); + } + } + } + } else { + response(trans('Empty_name').AddErrorLocation())->send(); + exit; + } + } + break; + case 'duplicate_file': + if ($duplicate_files) + { + $name=fix_filename($name,$config); + if (!empty($name)) + { + if (!$ftp && !checkresultingsize(filesize($path))) { + response(sprintf(trans('max_size_reached'),$MaxSizeTotal).AddErrorLocation())->send(); + exit; + } + if (!duplicate_file($path,$name,$ftp,$config)) + { + response(trans('Rename_existing_file').AddErrorLocation())->send(); + exit; + } + + duplicate_file($path_thumb,$name,$ftp,$config); + + if (!$ftp && $fixed_image_creation) + { + $info=pathinfo($path); + foreach($fixed_path_from_filemanager as $k=>$paths) + { + if ($paths!="" && $paths[strlen($paths)-1] != "/") $paths.= "/"; + + $base_dir=$paths.substr_replace($info['dirname']."/", '', 0, strlen($current_path)); + + if (file_exists($base_dir.$fixed_image_creation_name_to_prepend[$k].$info['filename'].$fixed_image_creation_to_append[$k].".".$info['extension'])) + { + duplicate_file($base_dir.$fixed_image_creation_name_to_prepend[$k].$info['filename'].$fixed_image_creation_to_append[$k].".".$info['extension'],$fixed_image_creation_name_to_prepend[$k].$name.$fixed_image_creation_to_append[$k]); + } + } + } + } else { + response(trans('Empty_name').AddErrorLocation())->send(); + exit; + } + } + break; + + case 'paste_clipboard': + if ( ! isset($_SESSION['RF']['clipboard_action'], $_SESSION['RF']['clipboard']['path']) + || $_SESSION['RF']['clipboard_action'] == '' + || $_SESSION['RF']['clipboard']['path'] == '') + { + response()->send(); + exit; + } + + $action = $_SESSION['RF']['clipboard_action']; + $data = $_SESSION['RF']['clipboard']; + + + if($ftp){ + if($_POST['path']!=""){ + $path.=DIRECTORY_SEPARATOR; + $path_thumb.=DIRECTORY_SEPARATOR; + } + $path_thumb .= basename($data['path']); + $path .= basename($data['path']) ; + $data['path_thumb'] = DIRECTORY_SEPARATOR.$config['ftp_base_folder'].$config['ftp_thumbs_dir'].$data['path']; + $data['path'] = DIRECTORY_SEPARATOR.$config['ftp_base_folder'].$config['upload_dir'].$data['path']; + }else{ + $data['path_thumb'] = $thumbs_base_path.$data['path']; + $data['path'] = $current_path.$data['path']; + } + + $pinfo = pathinfo($data['path']); + + // user wants to paste to the same dir. nothing to do here... + if ($pinfo['dirname'] == rtrim($path, DIRECTORY_SEPARATOR)) { + response()->send(); + exit; + } + + // user wants to paste folder to it's own sub folder.. baaaah. + if (is_dir($data['path']) && strpos($path, $data['path']) !== FALSE){ + response()->send(); + exit; + } + + // something terribly gone wrong + if ($action != 'copy' && $action != 'cut'){ + response(trans('wrong action').AddErrorLocation())->send(); + exit; + } + if($ftp){ + if ($action == 'copy') + { + $tmp = time().basename($data['path']); + $ftp->get($tmp, $data['path'], FTP_BINARY); + $ftp->put(DIRECTORY_SEPARATOR.$path, $tmp, FTP_BINARY); + unlink($tmp); + + if(url_exists($data['path_thumb'])){ + $tmp = time().basename($data['path_thumb']); + @$ftp->get($tmp, $data['path_thumb'], FTP_BINARY); + @$ftp->put(DIRECTORY_SEPARATOR.$path_thumb, $tmp, FTP_BINARY); + unlink($tmp); + } + + } elseif ($action == 'cut') { + $ftp->rename($data['path'], DIRECTORY_SEPARATOR.$path); + if(url_exists($data['path_thumb'])){ + @$ftp->rename($data['path_thumb'], DIRECTORY_SEPARATOR.$path_thumb); + } + } + }else{ + // check for writability + if (is_really_writable($path) === FALSE || is_really_writable($path_thumb) === FALSE){ + response(trans('Dir_No_Write').'
    '.str_replace('../','',$path).'
    '.str_replace('../','',$path_thumb).AddErrorLocation())->send(); + exit; + } + + // check if server disables copy or rename + if (is_function_callable(($action == 'copy' ? 'copy' : 'rename')) === FALSE){ + response(sprintf(trans('Function_Disabled'), ($action == 'copy' ? (trans('Copy')) : (trans('Cut')))).AddErrorLocation())->send(); + exit; + } + if ($action == 'copy') + { + list($sizeFolderToCopy,$fileNum,$foldersCount) = folder_info($path,false); + if (!checkresultingsize($sizeFolderToCopy)) { + response(sprintf(trans('max_size_reached'),$MaxSizeTotal).AddErrorLocation())->send(); + exit; + } + rcopy($data['path'], $path); + rcopy($data['path_thumb'], $path_thumb); + } elseif ($action == 'cut') { + rrename($data['path'], $path); + rrename($data['path_thumb'], $path_thumb); + + // cleanup + if (is_dir($data['path']) === TRUE){ + rrename_after_cleaner($data['path']); + rrename_after_cleaner($data['path_thumb']); + } + } + } + + // cleanup + $_SESSION['RF']['clipboard']['path'] = NULL; + $_SESSION['RF']['clipboard_action'] = NULL; + + break; + case 'chmod': + $mode = $_POST['new_mode']; + $rec_option = $_POST['is_recursive']; + $valid_options = array('none', 'files', 'folders', 'both'); + $chmod_perm = ($_POST['folder'] ? $chmod_dirs : $chmod_files); + + // check perm + if ($chmod_perm === FALSE) { + response(sprintf(trans('File_Permission_Not_Allowed'), (is_dir($path) ? (trans('Folders')) : (trans('Files')) )).AddErrorLocation())->send(); + exit; + } + // check mode + if (!preg_match("/^[0-7]{3}$/", $mode)){ + response(trans('File_Permission_Wrong_Mode').AddErrorLocation())->send(); + exit; + } + // check recursive option + if (!in_array($rec_option, $valid_options)){ + response(trans("wrong option").AddErrorLocation())->send(); + exit; + } + // check if server disabled chmod + if (!$ftp && is_function_callable('chmod') === FALSE){ + response(sprintf(trans('Function_Disabled'), 'chmod').AddErrorLocation())->send(); + exit; + } + + $mode = "0".$mode; + $mode = octdec($mode); + if($ftp){ + $ftp->chmod($mode, "/".$path); + }else{ + rchmod($path, $mode, $rec_option); + } + + break; + case 'save_text_file': + $content = $_POST['new_content']; + // $content = htmlspecialchars($content); not needed + // $content = stripslashes($content); + + if($ftp){ + $tmp = time(); + file_put_contents($tmp, $content); + try{ + $ftp->put("/".$path, $tmp, FTP_BINARY); + }catch(FtpClient\FtpException $e){ + echo $e->getMessage(); + } + unlink($tmp); + response(trans('File_Save_OK'))->send(); + }else{ + // no file + if (!file_exists($path)) { + response(trans('File_Not_Found').AddErrorLocation())->send(); + exit; + } + + // not writable or edit not allowed + if (!is_writable($path) || $edit_text_files === FALSE) { + response(sprintf(trans('File_Open_Edit_Not_Allowed'), strtolower(trans('Edit'))).AddErrorLocation())->send(); + exit; + } + + if (!checkresultingsize(strlen($content))) { + response(sprintf(trans('max_size_reached'),$MaxSizeTotal).AddErrorLocation())->send(); + exit; + } + if (@file_put_contents($path, $content) === FALSE) { + response(trans('File_Save_Error').AddErrorLocation())->send(); + exit; + } else { + response(trans('File_Save_OK'))->send(); + exit; + } + } + + break; + default: + response(trans('wrong action').AddErrorLocation())->send(); + exit; + } +} +?> \ No newline at end of file diff --git a/local/modules/Tinymce/Resources/js/tinymce/filemanager/force_download.php b/local/modules/Tinymce/Resources/js/tinymce/filemanager/force_download.php new file mode 100644 index 00000000..111c53eb --- /dev/null +++ b/local/modules/Tinymce/Resources/js/tinymce/filemanager/force_download.php @@ -0,0 +1,151 @@ +send(); + exit; +} + +include 'include/mime_type_lib.php'; + + +if ( + strpos($_POST['path'], '/') === 0 + || strpos($_POST['path'], '../') !== false + || strpos($_POST['path'], './') === 0 + || strpos($_POST['path'], '..\\') !== false + || strpos($_POST['path'], '.\\') === 0 +) +{ + response(trans('wrong path'.AddErrorLocation()), 400)->send(); + exit; +} + + +if (strpos($_POST['name'], '/') !== false) +{ + response(trans('wrong path'.AddErrorLocation()), 400)->send(); + exit; +} +if($ftp){ + $path = $ftp_base_url . $upload_dir . $_POST['path']; +}else{ + $path = $current_path . $_POST['path']; +} + +$name = $_POST['name']; + +$info = pathinfo($name); + +if ( ! in_array(fix_strtolower($info['extension']), $ext)) +{ + response(trans('wrong extension'.AddErrorLocation()), 400)->send(); + exit; +} + + + +$file_name = $info['basename']; +$file_ext = $info['extension']; +$file_path = $path . $name; + +// make sure the file exists +if($ftp){ + $file_url = 'http://www.myremoteserver.com/file.exe'; + header('Content-Type: application/octet-stream'); + header("Content-Transfer-Encoding: Binary"); + header("Content-disposition: attachment; filename=\"" . $file_name . "\""); + readfile($file_path); +}elseif (is_file($file_path) && is_readable($file_path)) +{ + if ( ! file_exists($path . $name)) + { + response(trans('File_Not_Found'.AddErrorLocation()), 404)->send(); + exit; + } + + $size = filesize($file_path); + $file_name = rawurldecode($file_name); + if (function_exists('mime_content_type')){ + $mime_type = mime_content_type($file_path); + }elseif(function_exists('finfo_open')){ + $finfo = finfo_open(FILEINFO_MIME_TYPE); + $mime_type = finfo_file($finfo, $file_path); + }else{ + include 'include/mime_type_lib.php'; + $mime_type = get_file_mime_type($file_path); + } + + @ob_end_clean(); + if(ini_get('zlib.output_compression')){ + ini_set('zlib.output_compression', 'Off'); + } + header('Content-Type: ' . $mime_type); + header('Content-Disposition: attachment; filename="'.$file_name.'"'); + header("Content-Transfer-Encoding: binary"); + header('Accept-Ranges: bytes'); + + if(isset($_SERVER['HTTP_RANGE'])) + { + list($a, $range) = explode("=",$_SERVER['HTTP_RANGE'],2); + list($range) = explode(",",$range,2); + list($range, $range_end) = explode("-", $range); + $range=intval($range); + if(!$range_end) { + $range_end=$size-1; + } else { + $range_end=intval($range_end); + } + + $new_length = $range_end-$range+1; + header("HTTP/1.1 206 Partial Content"); + header("Content-Length: $new_length"); + header("Content-Range: bytes $range-$range_end/$size"); + } else { + $new_length=$size; + header("Content-Length: ".$size); + } + + $chunksize = 1*(1024*1024); + $bytes_send = 0; + if ($file = fopen($file_path, 'r')) + { + if(isset($_SERVER['HTTP_RANGE'])) + fseek($file, $range); + + while(!feof($file) && + (!connection_aborted()) && + ($bytes_send<$new_length) + ) + { + $buffer = fread($file, $chunksize); + echo($buffer); + flush(); + $bytes_send += strlen($buffer); + } + fclose($file); + } else { + die('Error - can not open file.'); + } + + die(); + +} +else +{ + // file does not exist + header("HTTP/1.0 404 Not Found"); + exit; +} + +exit; \ No newline at end of file diff --git a/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/clipboard_apply.png b/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/clipboard_apply.png new file mode 100644 index 0000000000000000000000000000000000000000..d470c4434ba88711588dbca8762cfc42e1781759 GIT binary patch literal 189 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPHV5AX?bRZ~;@|NlRbgn;N1pN{~g zSW1HYf*BZQo@qRE6QnfK)5S5QBF^;WL*51jo|cQs77YuyCm1kzS~py}U9T2><-Pmo zB3I3)5_K}{mQ1zE>t_a-{!ZdmfB3P?#r{dNBlDq+2?8m43{nq1Bp#f!Z-GI;)On_F cYz;0mA2Akl@XGwZ31|s}r>mdKI;Vst00Uz{t^fc4 literal 0 HcmV?d00001 diff --git a/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/clipboard_clear.png b/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/clipboard_clear.png new file mode 100644 index 0000000000000000000000000000000000000000..e7fb9031bbaae2e99b053798a1a674cac64bf0b6 GIT binary patch literal 195 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPE^3h)VW6&4m&Q&ao@|38p~fZcD7 zumELQOM?7@f%MEXAFOs(0vXYsE{-7;alU5{avm_?V7;(r!41Z&ORQWwuQz|c^y1&@ zD=r#;*(*CfaT}X=3TC{!?sEUm`^KeOM~|H=vT*ssc}8c(EIkfRRR$rp1)NV>6fT$l ksbBwU;))x;j~o#Hxm@;>+u}8OKx-I0UHx3vIVCg!0Ckf|LI3~& literal 0 HcmV?d00001 diff --git a/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/copy.png b/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/copy.png new file mode 100644 index 0000000000000000000000000000000000000000..e1d89116d3fb4a7fb0874d9ab6d5f5b502d44f3b GIT binary patch literal 238 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPFP2=EDURZ~+lHa7kb0}>Jvl9G}T zQd3h?OH0eh$OxzaC<0O0o?5R3)XQ5EiYG43ltY(aU2^428 z3GxeOn0e-edbJpk>+9*_7*Y|(du$_bgMx_bMQx+R8w2xS*Dn3Pe^z z1Ef+_RTanpiU0wS0n`NnKyg(KRj@FSR0RqG1t3yDE)W2vAc7ECAP>R-3c?v`AVD|+ zYJsqU=0J>sGJxVh7iw#3ZROYc2lTLiNswPK10xd)D;ql}7Z)#|kg$lTgrtmuqLQ+T zimIBrhM|e6rInq%qmyrHc1~_?US57tSwmw}OG{gS|CBlN<}X-!{^G@pmu}v=cmLs| zM=xHz{w*nQ`Uq(B1y2{pkcv3p?(2L_0U|8o(p?2>6}tA8vx>gqU3%mH|Lm6E33E~= zO+G1C(R1A1HcR_)ir(~P?{7wg7T#U`Ebw~&zGb`i9}qNn#b|qBIn}b0!^kX$^H;i)T>p_Li=96;b^Ka$rfhdkWmvn1b8=wf@4peL7Z*4- zeUlTqu6lU8Tl^-EsU905cqRpLMedrh&+5;^1LbkSyCz(`XS(yJ&AmI@6mM^s^g}uG w;XN;HFS~G!C!e||<=x#_X|-McT=8Gl&qtMB9C>mi3zSeiUHx3vIVCg!0Ev;nq5uE@ literal 0 HcmV?d00001 diff --git a/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/dimension.png b/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/dimension.png new file mode 100644 index 0000000000000000000000000000000000000000..43dcc10155703666c47b845df93feebcf8b7d21d GIT binary patch literal 489 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!63?wyl`GbMfx&WUL*Z=?j1DQhw>^s?#0(7fo zNswPK1EUCwa_H~-z48IayIMMa-ae;rEB4m~Pw69uPd=)>z03OLp0WQ2lkmrvF5Wry zprN%b#9TNk@|aoo>K98yfQD@Jba4!+hzsq%I_anZkMq?fo~O=KOiYyg^xuBl<9mD7 z#OutJ?9I6lap3joO$mQaUA*|H3Gcx%1wQ2QuH%bW2&>r(gcV@;M}nonz|r-6DniZAF9D zTEvunv$(bU^ux1P;?8gX{kLpi(A&=&$~WHcmUollww$-bMz%LTh<~m8|9eOC6aL80 XKF#xG&C|*bP;7a+`njxgN@xNAsIHRv literal 0 HcmV?d00001 diff --git a/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/down.png b/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/down.png new file mode 100644 index 0000000000000000000000000000000000000000..76511223d957dd488561ac4eefda6f5ef835ba26 GIT binary patch literal 163 zcmeAS@N?(olHy`uVBq!ia0vp^93afX3?$7I7w-U4asfUeuK)l42QqPiwjPVMKsnBm zAirP+rY>g1X2!~vUXj&uKtXL!7srr_xa0(55x)cmX7#HIqHGIi8jDIwXe~E3kSH)Q hFg7qU;9w9`W@gA?V!2g*uIVJm9#2<4mvv4FO#u5cAhQ4f literal 0 HcmV?d00001 diff --git a/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/download.png b/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/download.png new file mode 100644 index 0000000000000000000000000000000000000000..76125f22a6e94ecc3c4b53e6b6d009ee4793fb44 GIT binary patch literal 674 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!63?wyl`GXl47gs@Y0R@59Nl8foy#SFiGBN_{va+)B z_xHEAw+Gtm=;#P^2GB-i0CXzQVX6<(dw{{0R1)MD%wW!cc_L@c=~rA+_-b1ouddEN z^SE2J_Q{?8rRJJbZ@Bg=?n!3uyW@Z5lQvLu@S#mub?^WrjHws??gV1OwTZ} zE}f;U>FZy*9ljOG>wG<+;qO8DgiiY=-XFWQ8yxiyDr;J|e&~G6qcFW+#JkWsPRs3+ zWy9MI0jnRI#jO`TC*JVSNXmGp`?((1`STc!ZmznOwQjcV)>&s65=8s2hucl9jq_)9 zUXY+sQ(RsCUx1Hw?(&m^S3j3^P6&1*lQb>=It(xb?# zTVA{5J9AqnAHNxz_)cDCQk95(=h2{7KV4Y@%VzH0x083ryJG&9<6nyJRDP_!7gQuw i@&Ci$pTGVcblM-YNUrbm`%77%F!pryb6Mw<&;$T*ORLua literal 0 HcmV?d00001 diff --git a/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/file_edit.png b/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/file_edit.png new file mode 100644 index 0000000000000000000000000000000000000000..4bcd072e9f7e228d3452973b7c0e9e76a9543a96 GIT binary patch literal 764 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|I14-?iy0WW zg+Z8+Vb&Z8pn}NEkcg59UmvUF{9L`nl>DSry^7odplSvNn+hu+GdHy)QK2F?C$HG5 z!d3~a!V1U+3F|8Y3;nDA{o-C@9zzrKDK}xwt{K19`Se z86_nJR{Hwo<>h+i#(Mch>H3D2mX`VkM*2oZx=P7{9O-#x!EwNQn0$BtH5O0c3d|4@L;p!@;Rg)2@GT#PZ!4!3&E+A z_j?_25NO~0Gx@dXJPt9ju8yXtj*g{ME8ahteWyAmb9vlT;~O__{bXo*oA_|Cz(HTWyN0mrWR^{QFrF_gkVo!0^< zI|{#HT*AGwX7cl&mLELBZ#WpPjAFkNP@!p-xypwBJj1uy3DxsI&VBxH45svE7W|_kWesGo$TRwW@yq=frGs zNiXHr+VXXl0e^Lx^eo~%eJ1(tHrpVj!>G%r%)HX(!N*-{w;D`i?#LWaweR{P^F1}v kZt|xlHID~Ee|Oa}%-oR7{dOvA5hzJ|y85}Sb4q9e0O7eBumAu6 literal 0 HcmV?d00001 diff --git a/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/glyphicons-halflings-white.png b/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/glyphicons-halflings-white.png new file mode 100644 index 0000000000000000000000000000000000000000..a92969a174c8ed385127cbdf5f836b539cc88170 GIT binary patch literal 8583 zcmZu$byQSe*B(Lz1cwk5kd#J2kdRKLq=%M9Q4~SC8FJ{(p`@7s1Vlh-r38eL7`nTM z9%`8HzVGi_?^<7+KlXa=*?T|x*=OBz){RIVEfoqf1~L!`M4_gttOo)SpaGmmLIl{1 zky>96h;U5jCFD6Cj|XP{8UHVqmzM{;|G54Wu(-GgOm=s71Gcud7O+SpGB-CjIyxG_ z2?+^+jf#o_;={ti0PO4Q>*C_#dAkCBm4OH0f2^fVfc*4Nk9 z)z$6j=+M&A`tjq(w{PEm{`^^8U0qO6ke8PS#Ajq=q^70cPfrgJyt=x2b#(;*fTy{+`S9=%xNK}}JUu+VK()8G2UuVd5CC96Cy)#11Ugz?UIx;Eihu=zfm}cUKmrK+rv$J* z|BwK=fEUOGXaNB94#WVQ$H&M2iP_!V1zG^S00ZCxssLV~FM#16VL;0D^))G?$XlI(%rjv|Neb?21X`k7FISk zHui@PA98SVadGqT^71`;EGYQoiI9-c)2AXLVq#+A&m^U!q@`u$P-%-r14($dPx+SXVq#geq3>K;J-9U2}P9UY&XnVp-TUszaNTHV6z9~>T^-(df62m&!V zt0^l$yexKe;sZI>{m0vK1}Y|$tVK#`gh^6mW5w6Kf}W)(xzT)a7vKw{Y`(|O$I(fU zD54OqcTewh$3k7-nW?{9V4!kV{)4*1qnK(TtBS-}7n5^S!L6a_AFolKL^`8Nw`-No z_gOyMzbRf9MPW0usLIRDo?>e20$SFGJlAtkgYl_tK528Zcb^eJS*c}qMxK(tdbO+I z8auFSRjUB|wWiQqd*g$|u@t?m++;4CSSNWHl!0U{#q)$xMko*TP`15Lvn!x>WT9N- zw7V!TY>c!@H6;)$?<}*`jeHqM1rl(eCVOJ}8XjKna4KZ?>ma*m->2!pQ4SY%=7CcCf5nNs{$j|s~DWfRe7ysV=TRV9Bw ztEaP?5`RCiHR%}V`irhV|Cn^iweM#fdZ?=WL{lZaPeAu@xT`Xo1%bY@JO9f?9sK)_ z=V8&*carQ!sc}U2wx|A_kQj?g z2oDXBMg$yFEO-y$l&=JX%gn9cNvqBW-%H;NIn; z10mIb;P3ctv%rA`QV{vx%g_U6ujB2l_ccrTk}}H255(jY%g%e@4gF<31s@yr4k3=- zDUyTF7rf5#5(e6NsWqqjT-G|;XR|s%C+=3_h8_h=wd~#m8$?w}KQXL!tyJ?`;&+_Q zAIAom`+H99VT)23ecv4=_v0T3=yg87dX)?5-C{3zKlD@Id?t>gE$K(U>|aY#s!^J$ z4oVa!T{$mg>Sx~{3Gzd4ds-#KoGgFyfx64};#5Xd>7X{Vw@6g;q-*PZ>aA=^Ei5E z)^oba!_#(pAR~|5@+gQ^2RodJ7}Uzy@X&raF!#*hs7Zw7nTj%vezI6*^|})NKJTlV zcn!6RWLz?x(4Jpa#fR|#o^%-Di@=e&D$}}p^3+8wjOqKS;+XT^{jp;g@g2{!(#jYJ z?U;D&P}=oX zF9!x+8mcOhoWyHQat&5QWESi4m_QOl<(%-|{5=12yd9p7BLp+2CnQ9!jd@g~?WPD! zAGZso^&yjY?+Mun1?E`!)~e;cyLvOSS?p;6?3&?%84>Y@da*1wS7_*2K(IV9<=YJz zkcB#OMoPwtG8kKReRqFUzg_!vQQ!8;k)X}*^7HLbB37ukbb_D(toOc7AsX4gx!khR zzIak-l+3=j67Kii8p+I&D`BwbyCLvrP{7Ruzm?VQk0o$=^KTLujgc zF{=0*HFoNvpz0R1?TOJ^Xoi_WyxW%gW-ENH{B2S$vuY=J6X6qa5Q7k&SN80?IjL{H zyNSH7r>U7bt^k3ZqYc)|_j!M*-dZv%HUEGHjbAsZF zOZv8<=)_h65jXsV1$VEv^x)Riyl>X$1?%p|cUE$rp4CF46gSaOC?>?e^uUsp(}%bH^k#03 zRMXh*OwOpGG-b7wB$1#XBdQ%=Ky!O<`;6yEaYfaDBr(y!1HW|#+DhpUlH#rXwKc)d zUym%5Ca91F`Q>bEgW9{>8Y;SvaDF;@0@}NHk{+a}s3C*xtk35b2&t*%D47nt9I~c9 zGqS+U`+fd=nBPCEt(NUKfw-1IUks%7!ss5Xt;C%kL`U&DEv-U_z^d zWCFE6RYrl@Ssxl$a8D}*&A4A!r=OqhxTwUUVgzRztiM3iihZ7?kk?SArNvMT5EJ$t zkouj8l5T%}jVrI9ch7$N3ZqIJCGGxw-CcQ4@@cL9pC(AANbEhb(|b=(CXu=o2^T(R zB&3lplM{bm28);jk6QnGfFjekWJdZ*eL0%HN-~>yaYoZ^{b937B^RM!5@FUIJ7jg* zhD`Gr?#)v8>pNAm+8mZhT2;bKb{1}|r9q2pWlcK~*-G}32*VnmYRE|Pi>;Eaps^H$ z3k#7=)F~|w<8|{!qd9Z=A)jHI#UNz6=Gvt%j?(@Ulpy)_XKBNZEV~8ECFX&bR>4=C zY#_EYKfNbXipXN3VpGW!h<gu~zW9a%J&=a0%_ zvW}Q$3iv5C)0dt2wE1)1sC81R*nPC=+laip|2wwX?G4i6S2Aqux?!e_DWk_{9};xC zCVL$9)`Q0XQpn)e9lgrJKO0ehUvR6KRwI-27#0Q)2|vD=qx zu{xA?PHA;Ysw1V?ZD6I1eupc<_&YuoPJt{sqNq!mPDG(b+bkk2g?X2}8J@c3&^J_q zE)~n=EQPfbBxX^UXT`XOLTKUGd2sXmI>G|)u}mWykf_48HnCD|UFvgG2UnFjiuLEv2~K3RE7X?<^}j)7F9+&T+~ zfuHxsy?(z|i-RyqSNV>+U8p5$p)X6VM8#9Y@WN74$?T{5#Iw%~;Hs0_4LSQKjtk>d z`AfF>>Q#yZ$w*6nv|ldr{xAKmRDQqK2htp+6(L4mNc0-0O`UuJ_Em57XaGK>@G>D^zBM>fMbH~w22CYkL zQU>S>Ygf^C6YK?wKknbN8H;OsH@4sW^brJ}1~>79H00~P(0F;9AuA;S|1|dasJp8 z-aeW`f%^7E5FcaJOZ#fw&-TL>sG)FkiOtIj+s{qI1n}?^_vOzbrl4GL!JoV1*@f#kGZB{D zEOzN%J%SA#-qT9)Fo!7G1X8xHL(O;06BS7WpwJl^p#*w`u0FrWRK2vYQnGi<%;U@} z`zzJ_-0v?;t7Z`gy>|rY$Hs58FMYf}uH6<#%hq{3WPurbr*TxP0%xw?+*sz{tJtjp zvz@*oAW82c`yHBKb6z3>W_=r*izFxHqu3)j;?nm*ChUnv)KF1q-)ZuQdCY(Eawgfz z*m8Wd!JjE9sL+T$K5ubKcP;0!>X>_*DYrIe&{>S?`SS@o6e|rOeZ?nzIIL*=zNi6x zsCvhO3GZufFBcjtqLTl>Sv01KjA2PHrN9ZG`+H+T`BoBl%((bjUEv=&g0|b=oX}T% z!J75+z>AZuO3*jEZ+^*z%|e_gdQpR82*XX3I&Z(yYM57<^w_Zug6KnCJ@m-W-zwNH zK{{f3Uc^qb-J(op4Zk~c4Eere3dbAY-}ThLbUyPRWE^2FT+JF2Md?j3OQ18{YuAfK z`YpO;>hZX5W2pgG&71kdG7;wit+G$ls;a6kHMH4+OE1bQ=829zMs7fg5x%~%Dfxb0(YfLQ8n$;*``#y1 zq>yhDDJ8wK6!$wKvQ|gV8-Fn&ej>>0Ju`juUVxyei@|ABiSzRs(G#=QUcI@5q_!2) z!ji4=&m}3ohJ0OoM@Fb0+LGCz%nN~_KNxBfDTSAxmqEiD^DPWtscc@O5}= ze^h*Ir?)repF}Dl4cS~4d?fcqLfX((|9b9-IV(%nMwj6d@-Rjb~EVmw`tF_wFCeASCgBF z8w0iL1{L76pehP@=S2dBqtO)^U9#uMKE1O|WRXWl^jBfn*seAq(P5biRL+|pe%sNu z*m;hb7d?HG1PTh7E*R7SDOa=^`H*6*2VBg{>EPX$81tJ)*Aoxjr%@((52Rla#Q8bO z`>?n$<-#t^zkfd8IP>@(&;7~7+kHistV9G!q zq%0Vx*UZyOsjT=`CU02dd%X6G?U_rBS@=l@+fn<8wj>DqwQ&zCOKe_n!Zz*r*>QR? zZf!Hs0lYnB~JQ7p<>4uQeVeyti-DhF0F^HFGu~CM?3++cEeb^uwDb}vo ztMF0AnY>5ZCMQteh3iAfm$@X3u%cJt${3}&h+L@$Z?6-}ER)WkLClV(f2-3@SA@|( z=i1d|jvN(;e9t@?_guKW$}Aw}-(i_st7nNPSarcg*%$_MCkl5#49&K}wdC45Ew{5F zNMl!rq!Roi&ciIArQ#fO@cJIz(ZDmv!2GU#QQycDmK1I!)nCbKIEIV&Lx>Xd+NXOi zljaAih^R1~zU$xwT+4yS*gU^KF;=GMD4Q9(Axh}V#1>;gNjjU1W)=x*lkv(pmbLT! z>3(k~+9xO4u+qFX!dp3iYwk-OK~W`R+3@d|b;lqMa7q#b|5KV(;n6CN>ZTb#&#sOZ zsvmOBtqh$Q&0vR_d49E1?3*(X$zd!CL)#F**uJnxhEYnxwwpB%j)A`$&Mq8OYyL@I z6@Y!d3t`Aa3{NmX>x2fr#Aqy{jK1!w$R94k($S;6uhyYS^e6yl&D|lQ2L==)}VIy!grp!sv5)v zu5C4cct_)*ua7oXJBgluSs;CuHa?fngp)d0-Ov=+UfU+FJB#D?3icl;*OCWGT4mJQc z<_AS;?Z;R_Bc@^Jo9*pvTALt*%~@n#(5X=fp|`%fG&c@jjYPs@K)Pg$`li>4N<5TjyJf@!(2$T94Pttj0-PaI8L$2imgp_fE(rJpx- zbN^)=#B6^)Hr@^7*A`EQ#iQW~vYA-2>VmItMzW3?9r7;vKc(lBiFzW}y3)@bf~QTR zXwtHuDvhZdn4eC)EIvYIr-IY9a|8`)?+mJhH zeBin~I)1ZP-^epcuVF$(mVK!XZ7xhv_D}U^+hrLyagA;m*_4IkMI{1`S-m)0_vYxa z0}N<(`LSCM&0O;J$O@;l1d-q1mRkkNdSN5q1LOv&pzm=o5BK3LEB9T%?d zd*e~U$Vz?CQK#+eeCh<3LP>u1UruWpb%zXhcd4~gdl;hY`!8H-_1%3svht)J^|^vS zpd}|P%x7PezTxy|Y!9p`$l0d|Wr@OGD6ugVeI7*ANJ1|r5L$f|_b;3@j`BUg()=KN zXu_YQno68P{UE|emAWB4OYd+vt)+5#(F$lHdZNH4XHI|;0>VTP=i7_^&{PO%q zoWWPFbPN2Tr-dbaR7z^L7!Pd=Y^wJ-rS06GH-bOXy=rY1$y_&1MNBH6J~A7Tk!*dI zD!|@I+dBB}s=elwAt~Qj{rjlRG(UtaILva;lv|<@CH55kzK%N4G5Mypfo^U#9R7%= z@QV5x!n?Vx3VhhW-KhC1cZNz!%9s39mc9I*jq(dqX(FYNfG<-Dv4>1(svw%+F8FmN za1@{ncZ9{d=LBkag>r&ih1os~Ot1&ldv|mBa=q_;AJ;#2Q_M#551EjZ_0WJKIey?o zKf)y6YVx}PlK@?d|Ns1~_OC1BSqsgmU_Ki{*x?eW`)7HaZSEW$VPoXN!!o#AC;~5G zg+sx%#2XsKi`So-$w#{c`M-3`Z~6A3Wl`LZN-1FU!No%ZrDTHO#&_OR7GTI~kW`4P zs^jyIi9v=|@JiO#iaLtCo=EY)+2!qdpVRB~qV-qGf$v^L?Od-giWZU*ghYo%G_*vp z2~u~w`?x3`uTVQ4`(AXe9&5eRkT^)Qh*j`xZzC9te)>MVqoM}K4~E|NS}>|-v;!T_ zHyC+muCsr=%&Tp|u-IL#&u9qlsiK^r>HR4Yj3|nsWYf-su2)rrlz&~bndQF@8j%0! z;~KxTY&(~`=6+Od9+DqcyV5gf57T6_yewct2a+!iTV5UD|G-JbLoT^39cc=2TPwJq zB_Ff)vK{!IV9_e!aVvLJ3mH<&_*w4E{J7I*0tthX9R5qYFPoRc=a_CVw`Ku934UXTwtr&PC`GHa zA9^FA77?<{+db#7&pl_D;rQNV5w^}e86qX*{E5o-7Q+#pfgP)>lsZP4%Ha2}5mO|} z!a04jX=nbjC*Pc#xw^=?_{}zRzX9fns?U$997@7Ql_o{V<`X9iQqNmXltY5*ZMJ)p zyK_0)jp}3fimnu2U_uKFj|kcflb5z9*0+oHb4DTaF(+AS{PDPq_bT4%%5CdMf{NHX zRH@f1@ma$G>-K>}UM8FALGx!jQjrnGlC8DIi3KU6mE%2d<>NRkhiF(tSI#&k7p_i9 zjc}m+*lnIlxuEh~R>#p%#dTCXbjl(l>+89@fvUV(-}`pcOfO{9ysfH1ZosOVaZchy zru~$V&^@5 z_J8~5H|OpjV9u_pT3#{;;-}Wi>{^eO6_m<~ets$UOC4;sU)VU_CK8vfvh2>w%gB`)AJW6^xz3*P&BIS-^7I6ojUtlh`r*FRb^o5)NX|}ClsqEqtvbuISI6j z!PnD+8m{_9z`5}7g5T&5vnAVh@Zr1sujk`K!To{Y7&b!tBub=soMsp)+;tdCr0tK=D(~is zr0r4O{ja*`8KU5v>IzaxlI24Q6&2+tE%hyFV|ZyPgCCIrF5y@sqfp+_m~&6C$gN9P k1t)v1H(VQdjcdUezUD=qhqa!-e`k=|b1mgBidMn@1#+3J@c;k- literal 0 HcmV?d00001 diff --git a/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/glyphicons-halflings.png b/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/glyphicons-halflings.png new file mode 100644 index 0000000000000000000000000000000000000000..f43139a488fa35166c45f8f760fa6842cc82826c GIT binary patch literal 15602 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 literal 0 HcmV?d00001 diff --git a/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/ade.jpg b/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/ade.jpg new file mode 100644 index 0000000000000000000000000000000000000000..b653b3d1375113626f327305808833c8cf96fc58 GIT binary patch literal 2290 zcmb7Fc|4Ts9)I3>XR*&>X^e&$lMbRgW5!h|Gs!wR8H6mA-H>IZ#W)>_CgpIAx^XHZ zrMW0{>PlH6MQP!b6Cl_y}x(){GR9c{@&;N{VmU<=vRyYg1fVu zGk_ofAmjpyQNVTDCyWHZ!vmND08{{USP0OFhFAdwc>q9_pq6IDCGe6Ss5B}T0cUe! zvM^34jtHlPrqJ9yom}FC@j@DV_1e`|tF1TD+~SiXlHx;l(wO_K!XucRu+T`wAaDd2 z7)HS`1_h%qh~U(5I2guhsi~=`6SRm#f)*Z6(xK>)w8`3dyq=LBnPNbtQi*y-#zxDH zDa)w_%AY_=Pb^Lohto9B#%mk=-=b&*L=_MS#4uzGP(%nOLW(wEfY3+5$}lYn8UtZ* zFbXkJka@(oWI+^Uh{j+Q13&|rM-gBG62BhYcTXkCkFdN08^K*kA^@An=)m>zqDN^D zyoR`S%|-1acP_mUSD!IF^e8NP!*n52<$6Qb%%6+9o>ho)8_nyJ&AP76ADfAra;n~8 zKBSrfvMc36yE&ImcG#)<&nI+b0fr|B9qVM(J6H81)+~H#(SGxV2G@Q7*&sky5C957 zBRBjFD;fg>2!&-@>k^1MdUUQQ0$By217T2$jg4=&pGx|UXBS=icuSb))b$~2a?35} z(tcIDb-N;3e{J2UKRr?O!}|^PG#lSX<_Ttg5jy2z|D29@*P^nk2i+R@+}w#h6uZy_ z)#j+(F%;+LveC!33leXQJ->V8Z)!V(lB}D#W-x0el4-_>ixD3x6RwGD(hIG^wX38? z^xE97$UPgHim|utJfwc-P{juGzB`MDjjDf;Gpa_NtvUDCJfmGp(7JWm(VI`#{;?Th zXhsAO3}Ml@Zv+u`FcF|h+B7;3!(d6RxFMqS(XlTyk$gHp?|cX2O6&u97mm*iC;$AR zJYx=$4!$W&)r*R=lDz!`qumu7-)UH{4=ci>!y zh-zentiVxb6{$BIM)hkABAfx5h#}FLAy|U8F>6-~!-^;H($VF5hKZ8WrQKh%jCDYL zmV>CgD&m46BUt@*&X#}g{psXv-{oeL;lL|hL*r|!9HWnnUosyXv(uV#ZL_PI&lf|DBBAHrSH=MLScSDOS^xhvyReQ+(V6j^^ zJbcf8r!2VN(BX^sh2EZ_&XxP$U(do^zV)fYjt)pnPZm^3EXIK}C z%~d}QxqGO`9Y0DOjory?*mOI2;xnZ#CZgV>sd#d8%ERvVF$W|+D+x%(As9w4)c^#D zbQVv*6qORBwJjm(T+iumedj=59I_lA&MH7p>OEufO@AC;HQ;E~nbeecy#T`dF=@@6 zRvKw#teOJWukVuTd_-BhOOn|WKKr~%8cQ1MeLuUr;w7`s^zrX@QW(C^{`RCYWBmF0 z;%wqmAMDEVYZ;i*Ovcufo-uwTQ^NB* z*dgHKV($>1MxD)?TD>=*m$W>+Tz(>(!YcQHBSl*mOEiERqgAA!;(8r&ghm?-WdT~(Z^1U?Z;p5I$-O>2aB0ik!@tnKE~RD3z|o{zo#t# zn{$GL?8LVQ^XmjJkE`a#d2DO0u~dopBah~PkZe6#+mp;LyBDDSvFuIwDv|y+mj~`Q zO`|(bS^50K@T_aljTqZ?Q7Nl@rlULbCI=<$;JA<#B7w&a-J9g)iQO9gpX^)Vzf7&? z)4!l|CHG#q3&E}MvJXG4G{ZTxtDe@H`si38%Tbvockli_dWJ#wfh~-Kx`Hkf`nO%2 j>&fMIzK~?woIOmQ4-EEX4<32%-F{!n#~xZ}SN!%L0k>Q) literal 0 HcmV?d00001 diff --git a/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/adp.jpg b/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/adp.jpg new file mode 100644 index 0000000000000000000000000000000000000000..b653b3d1375113626f327305808833c8cf96fc58 GIT binary patch literal 2290 zcmb7Fc|4Ts9)I3>XR*&>X^e&$lMbRgW5!h|Gs!wR8H6mA-H>IZ#W)>_CgpIAx^XHZ zrMW0{>PlH6MQP!b6Cl_y}x(){GR9c{@&;N{VmU<=vRyYg1fVu zGk_ofAmjpyQNVTDCyWHZ!vmND08{{USP0OFhFAdwc>q9_pq6IDCGe6Ss5B}T0cUe! zvM^34jtHlPrqJ9yom}FC@j@DV_1e`|tF1TD+~SiXlHx;l(wO_K!XucRu+T`wAaDd2 z7)HS`1_h%qh~U(5I2guhsi~=`6SRm#f)*Z6(xK>)w8`3dyq=LBnPNbtQi*y-#zxDH zDa)w_%AY_=Pb^Lohto9B#%mk=-=b&*L=_MS#4uzGP(%nOLW(wEfY3+5$}lYn8UtZ* zFbXkJka@(oWI+^Uh{j+Q13&|rM-gBG62BhYcTXkCkFdN08^K*kA^@An=)m>zqDN^D zyoR`S%|-1acP_mUSD!IF^e8NP!*n52<$6Qb%%6+9o>ho)8_nyJ&AP76ADfAra;n~8 zKBSrfvMc36yE&ImcG#)<&nI+b0fr|B9qVM(J6H81)+~H#(SGxV2G@Q7*&sky5C957 zBRBjFD;fg>2!&-@>k^1MdUUQQ0$By217T2$jg4=&pGx|UXBS=icuSb))b$~2a?35} z(tcIDb-N;3e{J2UKRr?O!}|^PG#lSX<_Ttg5jy2z|D29@*P^nk2i+R@+}w#h6uZy_ z)#j+(F%;+LveC!33leXQJ->V8Z)!V(lB}D#W-x0el4-_>ixD3x6RwGD(hIG^wX38? z^xE97$UPgHim|utJfwc-P{juGzB`MDjjDf;Gpa_NtvUDCJfmGp(7JWm(VI`#{;?Th zXhsAO3}Ml@Zv+u`FcF|h+B7;3!(d6RxFMqS(XlTyk$gHp?|cX2O6&u97mm*iC;$AR zJYx=$4!$W&)r*R=lDz!`qumu7-)UH{4=ci>!y zh-zentiVxb6{$BIM)hkABAfx5h#}FLAy|U8F>6-~!-^;H($VF5hKZ8WrQKh%jCDYL zmV>CgD&m46BUt@*&X#}g{psXv-{oeL;lL|hL*r|!9HWnnUosyXv(uV#ZL_PI&lf|DBBAHrSH=MLScSDOS^xhvyReQ+(V6j^^ zJbcf8r!2VN(BX^sh2EZ_&XxP$U(do^zV)fYjt)pnPZm^3EXIK}C z%~d}QxqGO`9Y0DOjory?*mOI2;xnZ#CZgV>sd#d8%ERvVF$W|+D+x%(As9w4)c^#D zbQVv*6qORBwJjm(T+iumedj=59I_lA&MH7p>OEufO@AC;HQ;E~nbeecy#T`dF=@@6 zRvKw#teOJWukVuTd_-BhOOn|WKKr~%8cQ1MeLuUr;w7`s^zrX@QW(C^{`RCYWBmF0 z;%wqmAMDEVYZ;i*Ovcufo-uwTQ^NB* z*dgHKV($>1MxD)?TD>=*m$W>+Tz(>(!YcQHBSl*mOEiERqgAA!;(8r&ghm?-WdT~(Z^1U?Z;p5I$-O>2aB0ik!@tnKE~RD3z|o{zo#t# zn{$GL?8LVQ^XmjJkE`a#d2DO0u~dopBah~PkZe6#+mp;LyBDDSvFuIwDv|y+mj~`Q zO`|(bS^50K@T_aljTqZ?Q7Nl@rlULbCI=<$;JA<#B7w&a-J9g)iQO9gpX^)Vzf7&? z)4!l|CHG#q3&E}MvJXG4G{ZTxtDe@H`si38%Tbvockli_dWJ#wfh~-Kx`Hkf`nO%2 j>&fMIzK~?woIOmQ4-EEX4<32%-F{!n#~xZ}SN!%L0k>Q) literal 0 HcmV?d00001 diff --git a/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/ai.jpg b/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/ai.jpg new file mode 100644 index 0000000000000000000000000000000000000000..e469be3df8781b9a24e84ec22c5e6433dfd2feb7 GIT binary patch literal 1776 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 literal 0 HcmV?d00001 diff --git a/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/c4d.jpg b/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/c4d.jpg new file mode 100644 index 0000000000000000000000000000000000000000..62994da7a372dd446ff991e89eb2b1f38f863865 GIT binary patch literal 6241 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 literal 0 HcmV?d00001 diff --git a/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/css.jpg b/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/css.jpg new file mode 100644 index 0000000000000000000000000000000000000000..e1673b0743b8c26007a9828f0d61ff3ff8b4e8d1 GIT binary patch literal 1722 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 T4edi=31f=DPE=aUT^Rf?WJ=VB literal 0 HcmV?d00001 diff --git a/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/default.jpg b/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/default.jpg new file mode 100644 index 0000000000000000000000000000000000000000..94ca6691a6257d6e13d45455484f99d08fb8b88c GIT binary patch literal 1723 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 literal 0 HcmV?d00001 diff --git a/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/doc.jpg b/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/doc.jpg new file mode 100644 index 0000000000000000000000000000000000000000..c0e14b3f4b883770eb061827cc9eb8497a75805f GIT binary patch literal 2511 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

    ~yju=_>uu*lZ*+Of!ulMa&( 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 I;$e>dH<`FnivR!s literal 0 HcmV?d00001 diff --git a/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/dxf.jpg b/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/dxf.jpg new file mode 100644 index 0000000000000000000000000000000000000000..7041cbe6f750106d9461dce3648976613f6cef82 GIT binary patch literal 5419 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 R2Z9KsF=E#Y5-ahq@dHtmFyR0I literal 0 HcmV?d00001 diff --git a/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/fla.jpg b/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/fla.jpg new file mode 100644 index 0000000000000000000000000000000000000000..41bd2ec10832000d145e32e4652a41a932b64cc2 GIT binary patch literal 1859 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 literal 0 HcmV?d00001 diff --git a/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/folder_back.png b/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/folder_back.png new file mode 100644 index 0000000000000000000000000000000000000000..dc0786ec6cea1394a7bd1c394727ce9604c9141b GIT binary patch literal 1128 zcmeAS@N?(olHy`uVBq!ia0vp^RX`lg!3-q3%M)E07#M2L^NvAv_Sw|~OKsWav-ShQ@-+I8zUZQinN`;MKvcJJMP;NX#? zr_Y={cj5AtYu9hzx&QFV(`PT2FPYU7|t)Hku3cJ}G-&`8KU6hAq87==kjTKgss` z3im7Prq4Y3|MX{@^I+sJ+563aVM>$D(hVQ4ggNY6+j#l@iR@3gyfG@Wm8?>Wc&ze_ zi%Ql!NxjWz#Gk2bl(bYlYRjHQA^OHCo?nusOZqNuiu<>VF{4JNat;cS?{w6kwl+^nZGMyT_}1@~(|4b`Rj$vmG!~4%eUWdGvtt+AyJJr~xZ4FB zH20p+@m5sjlIUFTd;0W=1(s89X;)4)OUn87^~;sbpPn4~@#Dsg7efA7a(8zd7yUhS zbKxSdm1_(8^fcXbj`o(6N#|@X@p0Lv_D48-ZE>Fs&*W1te)Iec*O7NvzUdc_ZnW@K zi*#)nztpWvUTgIJR+@b+w14~dIW4^Kd-mDcpKMT#?^!cAwpZUXC<(25)zVb5ySm9# zJyAio!Oq^ais@}a14BRtdn!Y-+0W_a7ooAaCw|FmjY&OoIxYiKEQ6=3pUXO@geCwO CHQzk| literal 0 HcmV?d00001 diff --git a/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/gif.jpg b/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/gif.jpg new file mode 100644 index 0000000000000000000000000000000000000000..8c771ca3c3e3c87d3eb8409538ccc6187ddd717c GIT binary patch literal 1979 zcmb7Ed010d7QgSkY%GEI0*Gvx5D=BNOcIcQm4OI?AdG-4Wvc`T$|^x%6qk|@6gTBQ}GN)XB1Fc$jnocHeg?z`tZzq8%nQ4Op9 z18^^QPj`SI03h%Iswv>I?Lb^C06spz8UR28NKPCe!5!2BW4Hi7tI?H{%xY|9AEs8S zmVn*Pl(e{{xJ*$DE9xN2%XgbcQe1Kz%htxxhG(&w1S1gD4VX9rFhpIZ6(LioBpL>F zCh!=>{bwCULQtqzDS$Qxl{kjO`jz~}U^;8X9DvQr4{T#aLx#g;wN>?TQd_yyZ+d~( zq;oV2Tz=4GpHX%CMC;__=9ct@za4(O)}#IK&F_n(^1JfKkxiP$038gvAiF$NKl_z) z!oH8*OzU);k@>vLHV=qzt$Kv8U1bd`{%BPXHBr* zSoX%l6GpSOMoia@hVT3Wj)gvT+(XVwHypA0Fu3jSBNoG~ri!L^w+X53Gbe-Ga|zQK zi-EI8ilSQ&9h)hy4Y5zgvvNyA`i@p~TU0arYbx$!G>fCO{VmNxUdb=K`!X^L;?+Hw1MG%z0^jPK$HfJlB=dzp$?1nS4$PKTwZfq+fYJ;x0J`2AP z#r+{U{Os%@i@}(q-f4Mm@$9%@rZdF+D*+G`!)RK6f`qr4OfVp1K z3ZwRk;&By#0rJ)TLr_f`iTW-?RNYX5LDn3Rhorg;C$+AmP*_r*c^6VX^Uz)7_aAcv;)*I|?w`BmI&rapy8n}+F; zp^?FLTe349Lwf^CdX)i~B*|pFVcEdL?s$g7w6ZeLlVVy^(B$>P;FsX_p|0Ed+P^op z@p<^EJT>|9iPOdDpV@_<|J?K6Jte8>o}q$kUO%XSD1>A1^K?n>?w(h>VcD(JWk)Fp zd4<{tAk4V}j-OC0e~zqq9&q;i?>x=7&)-3!hS^psW*<&>pB|qO zC5K9s`rbgdXR>fXPHd`~}tVwP*?UKj} zBR18Q?o)xKrS!>xMu)^fn{=aQR3<^my$E9OXKF48XfDy8r_egQ4jikEOh)MKM7^BNzO)QszL-nJP3BZvLf zLP;Gaeo1|lr{C{(@O)!LxlYuq%^B0%_nvVA7^NCdmbqey!+{IQfvosLV9$WS4`*?n z`$h`IlCG7O;R||i&r7|xvhSw(ZPRzr!_kTSc;%@=hm((b+J^0dQa6;Y8K&RgE7qLq z+rjChj}v3-hf<%g z8?8S31scpI-8s7*FW`HkPuh$k(0hJoSmI4719}19bt-y4`PDHLJw}+Dz2_8@u}99A q-P?KT$Db74$!(m0MXjF0?PqdN?AKGi%o@JMxpl>DuG@&L8u>4o$F|J? literal 0 HcmV?d00001 diff --git a/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/gz.jpg b/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/gz.jpg new file mode 100644 index 0000000000000000000000000000000000000000..36d159166e47d37b44fd4ed6dd800c2eca16f903 GIT binary patch literal 1718 zcmb7EdpuNG96$Hod3lWH65}z}jFeQXnPG}z8A+&Nrc$J0@-Bvv3aQ3!QlgDYeaPlf z5?fw9cGvcx6urIrc&iqxQh9$$W%gV)yZh&U&*z@cx#xGz{eFM1t87+22Mkvy7bk!q z03dJxP$MFPF2;Ip+TRaPNy@8kHG81 zO*ITtW76m}=KqGW3g9&04Pr6G7@#$i3;`$uW558`CqAma(JCAD43`Eeao)5>W%2iS>b!Ts@wZteVlM_ zj9DQZ(mQ{0q!;_M=QIAto^Q))oAvrg=}w*RqGi3S7w)MYP0qZs-7tvNJowO>UpcG< zK3Bb#VzwZyrmf=%y}8!ui(1AQO9>)+vYuI=?U7`*+eFOY@xZG5}fwnuTW zifL1vjuu=hd1WMm8ccBj=@3L^S_6z3Mj}%fI7gGs$2CthC5H1u4O)>=Lu*J`(^dwAg9 zn`=-a7iNhlDeAOD*ermAGc>h0v$#A6Wy=^F^^kKQUFZ??j$B zD?9haWcHZz!f*6r2jZ*!Gq0E5+hEHtlVi@oy+=1UAF8$s7U}+GDPeo$uVk)uF|er` z75vaJ-$?s?a9fkk?FEA2aWB*RKKhlfPW)(A9E9yn$=of9EBa98e*6Y;aH%zRm>a%W z9%ptUE$-aU%jCC0&2{`Qrwnh-|7G8ZL>(IQ|R9vS7&@~R> z8Wq4c`3eN*00x&Qkq(G`D|5cqo*idIoa^j-RCmShF|=6IIr>Ns&$uY(f;AG3-PH~3 z?@R1sFPjiK(0^AA zVBkECu$0Y}#t%s3sX29%;)$ANbSo0b5J83aTTpR!V#TPR&&iz?O?zHqhZ`Q>G;r+< z-SFNcBiF@YJVFufR?}_omZi4o&F!6#$YiQLNQAg4AOL4@ctVMk&6TGP1dt?EX*!=IdZXNJaxP1_c3b6))-Gab04 zf|IJEwrG3Lz$$Knd7`Tkq@2Y7@E=e4Pf`G6WN_^zQn?s%PN#)2AY)lYj8+|@B*}P literal 0 HcmV?d00001 diff --git a/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/html.jpg b/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/html.jpg new file mode 100644 index 0000000000000000000000000000000000000000..a1af20d076fc5c79e6db7996e79bfefe2f241a7b GIT binary patch literal 2152 zcmb7_dpK0<9>?Fc)?68yam%GN!xlPdh^?_>u;nf@qlC~5%{ikQxr@Ck_XvqI)seJK zbcS3qDzwEGC6}JLuBk}sq)z9-oHbL~XP^JhZ>{yL_g%mDeV@;cILWB_0agis*aZJ;L)5sb)V@YV2G9E=b!sB@jd z2avBG^o?L(EDpjGWRCy|-35~oG8)0W0&%N6sQ+bJfks|TlcoRw^zL!^wypj5f`^^5 zUa{=#vC4XtFLj02lefI|31S!+Rtx~JZf=n8wO*7|ZgqEESa*0I85jEHEEL0#3?K{) zA=uU9aR>&B2N0~TMc1HiWN}d%0?G3*nIL@=Yg7#9hXOT zFL;WMa@|j8rxl&r_i*P8s-&%Dqu`qz0ey+O>XT~le8Uy3`G0!3l(+Z<)Q9?X^N$!1 ztBcz6ZR5v0LfuWFgl=m=lf6lOU@vX*)A}fjt+vLSo=5!lNCr?sGYWtZ7y~PhzZT-=CL|LjsI36oLm}@pdBEx>lY=XZm!09 zD&e0>UE2k=|2UP|6ZK83$;vD5C&dgQsHosd*S5ACGY&cno$5-?;PbL|pcyqe<{dIiO!%kdzD@JBofP@`ehsa8(x=t2zxl+l@! znzrC49#kNr1l z5@(hIhtq}EF9rHzl#DdH*O2V`bZcmjYg`i5eZBj=e&8Ik?qM8xYApHC@IaJ-)g9oE zT8NBWbQu0kn$Oi6QkH%pUbDu|rv=xUiv+jh9A@lyJN=TqO<4PMcVKCIX;m=e^2_;| z-bRxoBV`XUhE)Jn_B_yU?sd`@5S^AfZj97TJu|oHEk3Z)`%~je{G^byLV3ZT&OW#s zX?{1Ckri*l!+XoX8O(BmYC>+#!G~GDX8sh-43U%;-MfA^Oy7U%+oDVQ&K>+@N!Yyf zX5;D1t#AImq2Xwx)^RoMcz^xoi8Cpu?N{#K@*HJ55A7#d8$2qV;}=g6N7!oL$$-|6 zvwYKQV;(ldch{aaCxmR#Nl(^#hGAFC3`@f4wyv-mG%h;AF*R zCG}*c+-kvhozE4Wx4dn4V#D`Q2doMPSazg|l62nB;WZ(do%mY73UnOb#|*2KSle>< z7792)qUK^s*I3%#p+fwA!{YNpSWGo8g?CSfMm`FO}F^dB-tpnq|pp`lUa5`;lz`s;FtVhLz$ zo>Me6mF_5A?R@gGdtFMBd)w&`ZUy=A-6r+Ho%wp{6C08_6VJ}UbNKzU;faHibUILu zdoDK2e}7BI)#2;{t-mYh%9b@A86O0lpt6&%mPJe$@2c@O%2XAN&Yip<4h$K7{4a$Z zDM$dS;;XW*NRktqM~$XC7Jep?H#qs?wl;!%QQ;?XhBfoH)tmPN}=* z*@jyKJL=;=Hz|Gat%Ai+UN9Jd`(G9^oz3N;6(jvDH|QcJ`E_cR!w-ASj=e6|j)Pnr zh1w?rz4k}l-(TMqT5Xm{x}EpeSW9Kmk@CaV-u^bTDF?eQ3Xi||WKIeh;X1JDCHC90 zr%Me^xyyh literal 0 HcmV?d00001 diff --git a/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/iso.jpg b/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/iso.jpg new file mode 100644 index 0000000000000000000000000000000000000000..379f50667f68117eeaa2ced50fcc0ace9c45a143 GIT binary patch literal 1496 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 IMcNzx1#lOing9R* literal 0 HcmV?d00001 diff --git a/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/jpg.jpg b/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/jpg.jpg new file mode 100644 index 0000000000000000000000000000000000000000..8c771ca3c3e3c87d3eb8409538ccc6187ddd717c GIT binary patch literal 1979 zcmb7Ed010d7QgSkY%GEI0*Gvx5D=BNOcIcQm4OI?AdG-4Wvc`T$|^x%6qk|@6gTBQ}GN)XB1Fc$jnocHeg?z`tZzq8%nQ4Op9 z18^^QPj`SI03h%Iswv>I?Lb^C06spz8UR28NKPCe!5!2BW4Hi7tI?H{%xY|9AEs8S zmVn*Pl(e{{xJ*$DE9xN2%XgbcQe1Kz%htxxhG(&w1S1gD4VX9rFhpIZ6(LioBpL>F zCh!=>{bwCULQtqzDS$Qxl{kjO`jz~}U^;8X9DvQr4{T#aLx#g;wN>?TQd_yyZ+d~( zq;oV2Tz=4GpHX%CMC;__=9ct@za4(O)}#IK&F_n(^1JfKkxiP$038gvAiF$NKl_z) z!oH8*OzU);k@>vLHV=qzt$Kv8U1bd`{%BPXHBr* zSoX%l6GpSOMoia@hVT3Wj)gvT+(XVwHypA0Fu3jSBNoG~ri!L^w+X53Gbe-Ga|zQK zi-EI8ilSQ&9h)hy4Y5zgvvNyA`i@p~TU0arYbx$!G>fCO{VmNxUdb=K`!X^L;?+Hw1MG%z0^jPK$HfJlB=dzp$?1nS4$PKTwZfq+fYJ;x0J`2AP z#r+{U{Os%@i@}(q-f4Mm@$9%@rZdF+D*+G`!)RK6f`qr4OfVp1K z3ZwRk;&By#0rJ)TLr_f`iTW-?RNYX5LDn3Rhorg;C$+AmP*_r*c^6VX^Uz)7_aAcv;)*I|?w`BmI&rapy8n}+F; zp^?FLTe349Lwf^CdX)i~B*|pFVcEdL?s$g7w6ZeLlVVy^(B$>P;FsX_p|0Ed+P^op z@p<^EJT>|9iPOdDpV@_<|J?K6Jte8>o}q$kUO%XSD1>A1^K?n>?w(h>VcD(JWk)Fp zd4<{tAk4V}j-OC0e~zqq9&q;i?>x=7&)-3!hS^psW*<&>pB|qO zC5K9s`rbgdXR>fXPHd`~}tVwP*?UKj} zBR18Q?o)xKrS!>xMu)^fn{=aQR3<^my$E9OXKF48XfDy8r_egQ4jikEOh)MKM7^BNzO)QszL-nJP3BZvLf zLP;Gaeo1|lr{C{(@O)!LxlYuq%^B0%_nvVA7^NCdmbqey!+{IQfvosLV9$WS4`*?n z`$h`IlCG7O;R||i&r7|xvhSw(ZPRzr!_kTSc;%@=hm((b+J^0dQa6;Y8K&RgE7qLq z+rjChj}v3-hf<%g z8?8S31scpI-8s7*FW`HkPuh$k(0hJoSmI4719}19bt-y4`PDHLJw}+Dz2_8@u}99A q-P?KT$Db74$!(m0MXjF0?PqdN?AKGi%o@JMxpl>DuG@&L8u>4o$F|J? literal 0 HcmV?d00001 diff --git a/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/log.jpg b/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/log.jpg new file mode 100644 index 0000000000000000000000000000000000000000..ec6d3e3f5f5b5ea808a90bb21ba75007d3802a95 GIT binary patch literal 1765 zcmb7EdpJ~S82`>W=HfEzj7yVC84N|ca+{J%lyNJ=P>B>vshN#RROmu-Yh82MbYX`? zs8FNwL=>XvGL(|gkdlYUsKsNt9|x&p7WjWy?pO^-{1FspZKNt4M5k~JJ|yW z0sz7uAQk`{yD-j90GLdm4*(znD4qkPuo-3rs@Mwv%!R*eBDl!+xwph9o&~0^`$9QE zoQQxORR3`5I+mS75N8jEYGSa;z}SH9Om*558nAzlUm(>mj7~Q(_4D@&5O)Dv07D3j zKroEJ5+FE40=$$o0Y|_S2n0NdBu|!;ktfO$NhHOe6lLWoBo&gpjM}1~Nb+(d5=9aO zTP|5Ciy*QTB8f=(-w@veWFqhe5eTFOU^0Y|A#npx$I3?_2_!Xs1%W7yL!=-)W>xx^ zdd@0-1>_J2z$k)Z)IAxSQ`6dvnf^-5$Qb?UW4~eso>>i#ak*ICe=x%RwrYT!+s}+Q z03hs&L+pf*{DKKA^xtQm_+k;zT`!i}DG zzlsUgSTZ`;52f&s6oSd$Aceyd0E{d!TnV9M1&XE(3(Jm(8eGmIJ>z!3=q+&niBj9~PTHA58?m9z}$Yxt;<@u~F8EN$8fH~+hR zHmu;|d2?*xtzpq~MSs?KK|@ISzysbMX&=)Nwdl>s>i6Gd^*b2d(h1|Yn$;&?DLUhp z$M*8v5zygnUK8UuQdE7A-($fZrKl{t?D>3n=nGjZ^k#7t(#^~hhQ?G0O9o)$b9-<9ET?xD{X+OE$ZZ+!BsDD8Ycti>2;Ihd?Bbaa<)XUb{b z!;XHTDs6?pIU{}dqnk$kw`wb@WLs-m*@oMd9IJM|vv(`?oa|Y)fPPq#d&GL4(h}da z>%om@77dy3S~+Qh+2wEFo;69(9$J02G1=#FnV(|Y^*)A4Vu-cX_+RXf&mxD3lN)1V z-_u(6bq9NRg%1n(%ks{i;})%mUuVB}b3CF!TJq$WwxD2YwBZ+>&1jaME@Rh<-tvgF z%ulsC!s^-HrVnC(ZKp1ZbtsITvG1J>k%610q0yQ#)bBVo@9rmTcji0UT2oXqptO)% zuaM3xpEx-3Qo8*bU)i*SmD995<+klwy)Iw7vixUH)skLlAGs4T;<&|c&mGSz~t+C@%A3y8MOuUXAGQO(0GNoFg5VvC*OLTzw6@8X<-?`t zD^+XUokpK>^-dJY(=~7Dfm(xzqA(4x!7kY! zp9b{5PQzCR3BNGFNdbZ+xC9Vc6QG7hZZ>QD#;B~|yb8YHJHO~uNqox8(WOqqN8nhQ z2(DKhHMJ1G;YRjxl;WX;pb5SznVWvkjt#U8wBEqtTsL=n8O^{Mbvw_BE^{mYSlX9x zF1)E$aEU%dQFc&`*VG&Fs*iW|++anvke=!99ebv#;y%uxT0}7(ExeT5G;s7R>sg0;Tf8-%H+AQ{bIqHKT*OJTGTVly_in$NlplnuaV~1Dof7W5*X6#M Rx=kP#X|PH7&OB1w`8S?lY>xl{ literal 0 HcmV?d00001 diff --git a/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/m4a.jpg b/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/m4a.jpg new file mode 100644 index 0000000000000000000000000000000000000000..5c6417c870d36a1433acfa810ec20ac75026b1d5 GIT binary patch literal 1529 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 literal 0 HcmV?d00001 diff --git a/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/mid.jpg b/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/mid.jpg new file mode 100644 index 0000000000000000000000000000000000000000..176cd71a923a95c591c6e0c5da3e88377952ed24 GIT binary patch literal 1630 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 Hp3V9%0{PkZ literal 0 HcmV?d00001 diff --git a/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/mpeg.jpg b/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/mpeg.jpg new file mode 100644 index 0000000000000000000000000000000000000000..50f99ff0a74487f5478ecf274344071a182ac813 GIT binary patch literal 1589 zcmb7DeK=HU6o2o%Gk3-`!@WMr(?&C95zYGWpqM2xRe)@DQ*8=4l$R?0>n?35C_ z;aRFFNs7VRNs(0Bl2E(JN5xYlTRuu{J=N@c$Flz2bD#IQ=f3Bj-}`%i=NwI&<_REH zt#Drf5Ci}OK0wnAM9ULon*dn78dw1Um;l)?12pKtD3}fx0BAlsv6GmOP541nQ1cns zd2fxCMadGw!?>Y4xT_?~-J)dCGVTIvCu>`4drz)=bZq#xXz3QNAR#ndDzFm@9W))l z6`%-)VhD<2C}kKOqYS6fFggQgFc>(FGni}^gE@tX<1Ag)6gHc~;V@Xbdb%7v=&~sg zm`-KFTsoVHGui*!G*GXQM?S*;qd#PQWxqce}P0tbr=i({+HBQnkRjG;mvvj~7d$!OTb zIdqhUV+>eC0YNTw(3gZjPE1&BgpPhZy^`1CpCf+yq9b8en(Dd#Ih`X5cGsuSF2pJG z8#(mrimSN;yHeCP@llNlqC}@}yQ>`s`kPK0?t5xp)^|NYK2*CXe)vlKdGFiPcMioF zhRLVeYHVWEG{O*<^x zr?*8IZI!0BxCpadC}9wc#v;cNsQQqAt`C!ihFmjSv5$0HYzAS(UtqUX;_DX@D*wJz zRoA*V`Pj9Ve>KBh&{022{lU22xt>J_Tz72_Ru%oVIrshNV=*js(($B}gC3I8BM$r# zW#zo8lKS1p>q?8|ip8_bd0vjHWlA&Uisrt?aJGYepniIA3x2#ymt%By`0C{xkD^!7 zsLGND&!$$qSn8U3Haj@^L`+x{f4gPN4(wIb`fj6?^nOB$-F

    eCZ0wrm-f@}a>ynvifXXp@H=;Q@l= z3Pj=p?d_;0CHi%zHaIt@pZIjA)KqvW@>C>R$e0PUO-V|i@&3|cA|zKRCIlj>T$@hy zC(&)O&LoWU<-Ko~HCR>7$~5&5FV3R`=8g&cpT1yBU@@g`#@P9go(u8P!!#o!-^PgV z>VBxYtIuwxVtUwG#yd{?+;lBBjZ92Wb@i}wz5;}9O-KbPgcc` zGP?1zGQ^~1j+etVcIQ*_nGqiMTS%5=_OvHv-Bo|`e^TKfu=}myjf;DDdd0b^7do0Y QFchgdje#Jm3(ETNA2~qyvH$=8 literal 0 HcmV?d00001 diff --git a/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/mpg.jpg b/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/mpg.jpg new file mode 100644 index 0000000000000000000000000000000000000000..daa2bc4633d71a8205d00348edea30d4a8ed9345 GIT binary patch literal 1532 zcmb7Dc~BE)6#sTN7a>b_MUG)m7EnQ@Gzm}yWdJEhFqq(xQaniH7{Vn;Vi9Uk6Q1Xuw8-~c2~1sKqSQD6sO08kw|x00>H=KL*m z&}aaj(sZ>dRh1ndNA1`{h0B6NQ&njy%ER5qUF7a1p~PwG_+4qr6iSfgB@)Fem7-YV zeGmjt1Vb?dMKP2%jET|4Vwka+Y!;i%X5l!W!L!1CgA{dDn^}rss4-?ZI%o>ZsHbYP*14eBT zlg&oxFM={KV;|r_2uffCT&Sdk;Pu*KqwMWg`4M57@9wV7wOBek*9jzHjP~AFGP_j-FDPEiSUrs(O!xWIE28jo`>g=ZQ;ye6xdGdwhv>VC_8*iX- z&zua)FL^91TsNGe)F5}C$WtyDbhitBJPT{0NPu7%a~^S!5E5HJ5tag>D8N(@h9LgP z^f~TCW!Ejg6`y5z%CEVRW;KiqBY+tkNGJ@HJ=YU-kOe4((FpA1jBz@kKv8JQYw(}gZ#p_Q}HQ?_BFV#ogW zHzcwA(SKx1LR%cFe2%t`I46Ez)!h7Y`}^D%XTuHM<0l=9?c@%@Q-;Cy!H0fos`Dys z9vF=1ROZEnY0|Cl+smtqt|W4kv)cpw+*Wm0#4G;ndEGPSUbMg6ZjJn?OaInMnZ)<6 z&DOrjV!znOl~z$NPv?Zb+2t+oJ6fB!*eU;!-n^vj=bNkhR}nK@7nU7Tlq$2U(QE^F_79N1k?hCvfk<%A%UYXP$`Ja(3UpI6zyHJit%@xsguQ7 z`W)t}T|GQ%e^{~f;4o8CqFz@$ZLd8xQ=j3?>rP0s6|@E=$E-={FqBs^@J*|uYr;_f zsL7t@2U(*hh9-v&jk+8zu%8l&hhUQTM_`9!&0)R&{W`nS|MI=43^JW1~Fi8ax zLP3Di)D*2cV(ReIz41>uU&Y=ptORY;ZvDsSo%|u%9*XXNV1SSW1t9pX;)oHx8OPV_ z4&zB!X?~{d!)cS`D4J8oe5{F6r67=slqoXi_#|ekMKddT{RcO`&^LrjqB?SwJ>?Pj z!hO%{)XWoA`QJLZ-quIwW}7L-bmalMwd?IyE$$ViT)iyxtk!(d{3$9k+iLZ>OZ_jM zE?SFwk0}Xf$+&`7Qzpz=bHK5;qh=?!@%1*HbA5w;dcX*_?M&20p0$o`YPoKwh%xs5 E3(f1;z5oCK literal 0 HcmV?d00001 diff --git a/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/odb.jpg b/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/odb.jpg new file mode 100644 index 0000000000000000000000000000000000000000..1a4157e4570faf5b2e20efaff272e816ae735290 GIT binary patch literal 1748 zcmb7EYfw{16yAGpZW8h!2>~OBlAuMzS3*Rwib+6-APAz>QHllvlvqXN9mHCSJQWZX zOMDGMsE=4HXrVz-p^Ohi6tpTbMU*O5r3Mg85l#1kqW#ey{qF4S&Ys=xeCOPA)^yL* z0oXoX-d+Gf06^deOb>z7Gf5QzfS(_50sv3}lBohDxPn$-0|x+TF*>@FT#Svbg9xMP z9hl`G9jDr$N)8X>hpPEL0iN;=swfp-JY((*=NT@(eDA2Z@R+EO^?YHHQZy&jRTS!C zY6BhsMKBaYP!vN6U^qsAOd?Tm3YkKokeN&tl|f@s=~O0@X3nKEcuXdfLNjNXGg%BK zlSh!i>%>huhS7OcCYATUVX6ZhDhL9}7-A1l4uWwIQ#}|5!^aQ^BE%8kWC{sEsnBRm z>|>vp03bmT6w`gcfZHe=W5e|6^4Iji`4jAK?lFPv$ky1V;Ju%p&YRaQnWkFf=l)8| zC?7e6L}&hd)$hgyyTYzuh2AHj?_^c;)_ESQrVplf>aQ@XFOD385+5|Lx1uU*>&DYv7yNmv zYmg_e29(*Ah37KGiDhl{#IKBTK5aoZnh3Y-$J3HF9*n1kpB}%5|NT6M`Ic?A$#c*D z{h;gFV%L>b>dsbI-=Klzwl!J3$&pQdmvY9MT|Zm-#JH8v$RPw`B}>XPmY~ z6I#@CI3?KxAp0Z^K}VvDk^=TSIm1MgKw71ClkiB1n6P1!E~{l+hC`to=Ft-6g2a%D$`|R;hqb;*kxwgPb#LE%(KN*|rF3$gUPUkHcX?wwr6_7le*4T2 zs|MeUy9(M`+HcvX{J)-@Yb9VbE*i4h5Ey)5aR2!lEXV{7S!n_^4F{jA!;CGvN-sIR zogK6FxWl9!er20aR*cDe(`Tc!%3kb$bb?;$7C-Q)Az35!T-#EV{;v9XCud93Wwp#Z zBGy}RaCO96pXHIO=gy2f7hmamM{N46M~IXSzz7J)7bs}&7bu3XHdMhkqMaBfhvPnyo{ z$kC$WG`F-cOZJ|7-JaPAofBW(JIPmaNqM#W;<)Xv`+diz@Ix22=Uvra6qdIL3|W>7 ztr?3V$c~1U3!Xm4w+%U3o^9xJaoW+!8|Ntbs_wKpDdR9hF`?y#{;41d6agbr-@Q~?tH zu|J_c$W$N@ic+=G07H+We1sFeA`pwU^Ky3g3 literal 0 HcmV?d00001 diff --git a/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/odf.jpg b/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/odf.jpg new file mode 100644 index 0000000000000000000000000000000000000000..da290dc7bb3c8b1bcc85a9d1dc48743d221b9517 GIT binary patch literal 1760 zcmb7Ddo+}37=OR-o0~FY#-%YX?F=d`nn7~utYM~U5r#I}!&=w25sJ*ZER~aJw-l1( zQsYt~vB+iH)RJtZGDo{zs9X|TZ4Fi}soD1{)SmropYOcqd(Zp4&-47=-}8Hvca#Hw z?kaK-0R#a6fgex~0{+@~$z}lD-GM0pfC7+o2_V27^a35Y06=Bv!bzeGTiE;IPUTx* z?YTWx5-CXx3uOlEoDLZvYOw<+5Ig97|OB8C_Ml!0IjMA;5>;qxIjoP&8Ik`Mx!f zfe!3rA0R*wWaT}e3Xf4bMu+sBITSDn{~y`ii@i3>O0J2{ORrW=-e{8j@#S#W262nA zz>NR?mTR)TFlX$AuxqlqvVZ3JsQp;8hqKyz~uRI0QpF4i6wG`F$h+ z1R{!&5C-6?vw3_caUcXkfiMvw`c~WZdE+?4v5r)h?5nc(NFRUXhLQ7~xO$Aq%8mUsBB+-_lyB)$VCFrfvt}|nd6@RZKSQ-~`-FtaJ@N zt#awlQ`6bq_FeVDE^C*!d#>uN+kV{B`NA2S7Z|ywugT);6LFVzK%hnp0J}_BfQjo0 z#Rv=y4wt8{Wyu#rr@TW7xpqXJ4gE5)Tp*gwk58`Pl<8YsY9CmcTgbb7;Z$c~Q;1Zb z2((9TFAAS=FA2^XC`gHPgaww(75LB&1jQJT4i48+T~mv}7ER#j|!$ad}h zbt1pH#jb+!+GV*_Z*%mUs_#!u1q_+=yJ?t?v<3ERM?N1dJe4Wqh+>rh*0H7I4?&2k zi?BJ$p?nE|p-$A`7zAk=a(R}{VlVHI=vpl&fp9}$aLkUBV)@`)8%U1mG)qTvdTDfg zDp@PIf04=qTSH&}!okzuI!jYJt{?W09MoxEn>{4mFKnppJ)1mG+FIUV^7oK`LcQ0S z8E2^y*m;|VF$+De^^N!$UnWS;vIkZl@_gl!0SL*$>3}1e#j={!-2J|`iqzNcyn>0b zBs0-Y*H=M_=Q|_?v+EAOsfk%hu5h_Z8}Qii-N@pb`TWpxCB{Rhw_~=_PqyonTM>30UN$<0(4RNv3Z5M`j4VJAImD*53yl5@lF)@4s@6w~6m z2{RV4m}f5E6@Ya*sYL7TZ%Znd!zJ`=)EJ1=Y*cv@=;QsLH+x zC#vUJdo8uny$yx>2&wL+~|2= z$Uoa<(h;J2H`@U3{=df>*qM9JPhn2E>+ZQdd^#J~CPw@qO(=c_ha0Wndj(~+$`^!B zm*e!>^nH?5-GM4>jTC-=nhoXE-%$WA$DYHv36$hq5iT_QNrQkbxwaVWQ5iW7M zJb%*_k0kdo=BCmJvYzJFy(iOl)^evvucVs0j5B`Fym92E`7J!<3S7|$i8QZgd^BNW zxIC|*lwx{xR;^+jc4nb1^x0KU5ATvWkq?qTXR)Ei3_)BbXr z4X;0cpw@wAl^0GQ9Ij8Vj0vc~^p+6{6nz~I5yeGmDE;80T7tjZsnGZ+!ISGphYhuc Z4$#L_PgjO4k@_VX812q>-|4Bm`w!SQM)d#y literal 0 HcmV?d00001 diff --git a/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/odg.jpg b/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/odg.jpg new file mode 100644 index 0000000000000000000000000000000000000000..1a4157e4570faf5b2e20efaff272e816ae735290 GIT binary patch literal 1748 zcmb7EYfw{16yAGpZW8h!2>~OBlAuMzS3*Rwib+6-APAz>QHllvlvqXN9mHCSJQWZX zOMDGMsE=4HXrVz-p^Ohi6tpTbMU*O5r3Mg85l#1kqW#ey{qF4S&Ys=xeCOPA)^yL* z0oXoX-d+Gf06^deOb>z7Gf5QzfS(_50sv3}lBohDxPn$-0|x+TF*>@FT#Svbg9xMP z9hl`G9jDr$N)8X>hpPEL0iN;=swfp-JY((*=NT@(eDA2Z@R+EO^?YHHQZy&jRTS!C zY6BhsMKBaYP!vN6U^qsAOd?Tm3YkKokeN&tl|f@s=~O0@X3nKEcuXdfLNjNXGg%BK zlSh!i>%>huhS7OcCYATUVX6ZhDhL9}7-A1l4uWwIQ#}|5!^aQ^BE%8kWC{sEsnBRm z>|>vp03bmT6w`gcfZHe=W5e|6^4Iji`4jAK?lFPv$ky1V;Ju%p&YRaQnWkFf=l)8| zC?7e6L}&hd)$hgyyTYzuh2AHj?_^c;)_ESQrVplf>aQ@XFOD385+5|Lx1uU*>&DYv7yNmv zYmg_e29(*Ah37KGiDhl{#IKBTK5aoZnh3Y-$J3HF9*n1kpB}%5|NT6M`Ic?A$#c*D z{h;gFV%L>b>dsbI-=Klzwl!J3$&pQdmvY9MT|Zm-#JH8v$RPw`B}>XPmY~ z6I#@CI3?KxAp0Z^K}VvDk^=TSIm1MgKw71ClkiB1n6P1!E~{l+hC`to=Ft-6g2a%D$`|R;hqb;*kxwgPb#LE%(KN*|rF3$gUPUkHcX?wwr6_7le*4T2 zs|MeUy9(M`+HcvX{J)-@Yb9VbE*i4h5Ey)5aR2!lEXV{7S!n_^4F{jA!;CGvN-sIR zogK6FxWl9!er20aR*cDe(`Tc!%3kb$bb?;$7C-Q)Az35!T-#EV{;v9XCud93Wwp#Z zBGy}RaCO96pXHIO=gy2f7hmamM{N46M~IXSzz7J)7bs}&7bu3XHdMhkqMaBfhvPnyo{ z$kC$WG`F-cOZJ|7-JaPAofBW(JIPmaNqM#W;<)Xv`+diz@Ix22=Uvra6qdIL3|W>7 ztr?3V$c~1U3!Xm4w+%U3o^9xJaoW+!8|Ntbs_wKpDdR9hF`?y#{;41d6agbr-@Q~?tH zu|J_c$W$N@ic+=G07H+We1sFeA`pwU^Ky3g3 literal 0 HcmV?d00001 diff --git a/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/odp.jpg b/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/odp.jpg new file mode 100644 index 0000000000000000000000000000000000000000..da290dc7bb3c8b1bcc85a9d1dc48743d221b9517 GIT binary patch literal 1760 zcmb7Ddo+}37=OR-o0~FY#-%YX?F=d`nn7~utYM~U5r#I}!&=w25sJ*ZER~aJw-l1( zQsYt~vB+iH)RJtZGDo{zs9X|TZ4Fi}soD1{)SmropYOcqd(Zp4&-47=-}8Hvca#Hw z?kaK-0R#a6fgex~0{+@~$z}lD-GM0pfC7+o2_V27^a35Y06=Bv!bzeGTiE;IPUTx* z?YTWx5-CXx3uOlEoDLZvYOw<+5Ig97|OB8C_Ml!0IjMA;5>;qxIjoP&8Ik`Mx!f zfe!3rA0R*wWaT}e3Xf4bMu+sBITSDn{~y`ii@i3>O0J2{ORrW=-e{8j@#S#W262nA zz>NR?mTR)TFlX$AuxqlqvVZ3JsQp;8hqKyz~uRI0QpF4i6wG`F$h+ z1R{!&5C-6?vw3_caUcXkfiMvw`c~WZdE+?4v5r)h?5nc(NFRUXhLQ7~xO$Aq%8mUsBB+-_lyB)$VCFrfvt}|nd6@RZKSQ-~`-FtaJ@N zt#awlQ`6bq_FeVDE^C*!d#>uN+kV{B`NA2S7Z|ywugT);6LFVzK%hnp0J}_BfQjo0 z#Rv=y4wt8{Wyu#rr@TW7xpqXJ4gE5)Tp*gwk58`Pl<8YsY9CmcTgbb7;Z$c~Q;1Zb z2((9TFAAS=FA2^XC`gHPgaww(75LB&1jQJT4i48+T~mv}7ER#j|!$ad}h zbt1pH#jb+!+GV*_Z*%mUs_#!u1q_+=yJ?t?v<3ERM?N1dJe4Wqh+>rh*0H7I4?&2k zi?BJ$p?nE|p-$A`7zAk=a(R}{VlVHI=vpl&fp9}$aLkUBV)@`)8%U1mG)qTvdTDfg zDp@PIf04=qTSH&}!okzuI!jYJt{?W09MoxEn>{4mFKnppJ)1mG+FIUV^7oK`LcQ0S z8E2^y*m;|VF$+De^^N!$UnWS;vIkZl@_gl!0SL*$>3}1e#j={!-2J|`iqzNcyn>0b zBs0-Y*H=M_=Q|_?v+EAOsfk%hu5h_Z8}Qii-N@pb`TWpxCB{Rhw_~=_PqyonTM>30UN$<0(4RNv3Z5M`j4VJAImD*53yl5@lF)@4s@6w~6m z2{RV4m}f5E6@Ya*sYL7TZ%Znd!zJ`=)EJ1=Y*cv@=;QsLH+x zC#vUJdo8uny$yx>2&wL+~|2= z$Uoa<(h;J2H`@U3{=df>*qM9JPhn2E>+ZQdd^#J~CPw@qO(=c_ha0Wndj(~+$`^!B zm*e!>^nH?5-GM4>jTC-=nhoXE-%$WA$DYHv36$hq5iT_QNrQkbxwaVWQ5iW7M zJb%*_k0kdo=BCmJvYzJFy(iOl)^evvucVs0j5B`Fym92E`7J!<3S7|$i8QZgd^BNW zxIC|*lwx{xR;^+jc4nb1^x0KU5ATvWkq?qTXR)Ei3_)BbXr z4X;0cpw@wAl^0GQ9Ij8Vj0vc~^p+6{6nz~I5yeGmDE;80T7tjZsnGZ+!ISGphYhuc Z4$#L_PgjO4k@_VX812q>-|4Bm`w!SQM)d#y literal 0 HcmV?d00001 diff --git a/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/ods.jpg b/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/ods.jpg new file mode 100644 index 0000000000000000000000000000000000000000..1a4157e4570faf5b2e20efaff272e816ae735290 GIT binary patch literal 1748 zcmb7EYfw{16yAGpZW8h!2>~OBlAuMzS3*Rwib+6-APAz>QHllvlvqXN9mHCSJQWZX zOMDGMsE=4HXrVz-p^Ohi6tpTbMU*O5r3Mg85l#1kqW#ey{qF4S&Ys=xeCOPA)^yL* z0oXoX-d+Gf06^deOb>z7Gf5QzfS(_50sv3}lBohDxPn$-0|x+TF*>@FT#Svbg9xMP z9hl`G9jDr$N)8X>hpPEL0iN;=swfp-JY((*=NT@(eDA2Z@R+EO^?YHHQZy&jRTS!C zY6BhsMKBaYP!vN6U^qsAOd?Tm3YkKokeN&tl|f@s=~O0@X3nKEcuXdfLNjNXGg%BK zlSh!i>%>huhS7OcCYATUVX6ZhDhL9}7-A1l4uWwIQ#}|5!^aQ^BE%8kWC{sEsnBRm z>|>vp03bmT6w`gcfZHe=W5e|6^4Iji`4jAK?lFPv$ky1V;Ju%p&YRaQnWkFf=l)8| zC?7e6L}&hd)$hgyyTYzuh2AHj?_^c;)_ESQrVplf>aQ@XFOD385+5|Lx1uU*>&DYv7yNmv zYmg_e29(*Ah37KGiDhl{#IKBTK5aoZnh3Y-$J3HF9*n1kpB}%5|NT6M`Ic?A$#c*D z{h;gFV%L>b>dsbI-=Klzwl!J3$&pQdmvY9MT|Zm-#JH8v$RPw`B}>XPmY~ z6I#@CI3?KxAp0Z^K}VvDk^=TSIm1MgKw71ClkiB1n6P1!E~{l+hC`to=Ft-6g2a%D$`|R;hqb;*kxwgPb#LE%(KN*|rF3$gUPUkHcX?wwr6_7le*4T2 zs|MeUy9(M`+HcvX{J)-@Yb9VbE*i4h5Ey)5aR2!lEXV{7S!n_^4F{jA!;CGvN-sIR zogK6FxWl9!er20aR*cDe(`Tc!%3kb$bb?;$7C-Q)Az35!T-#EV{;v9XCud93Wwp#Z zBGy}RaCO96pXHIO=gy2f7hmamM{N46M~IXSzz7J)7bs}&7bu3XHdMhkqMaBfhvPnyo{ z$kC$WG`F-cOZJ|7-JaPAofBW(JIPmaNqM#W;<)Xv`+diz@Ix22=Uvra6qdIL3|W>7 ztr?3V$c~1U3!Xm4w+%U3o^9xJaoW+!8|Ntbs_wKpDdR9hF`?y#{;41d6agbr-@Q~?tH zu|J_c$W$N@ic+=G07H+We1sFeA`pwU^Ky3g3 literal 0 HcmV?d00001 diff --git a/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/odt.jpg b/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/odt.jpg new file mode 100644 index 0000000000000000000000000000000000000000..1a4157e4570faf5b2e20efaff272e816ae735290 GIT binary patch literal 1748 zcmb7EYfw{16yAGpZW8h!2>~OBlAuMzS3*Rwib+6-APAz>QHllvlvqXN9mHCSJQWZX zOMDGMsE=4HXrVz-p^Ohi6tpTbMU*O5r3Mg85l#1kqW#ey{qF4S&Ys=xeCOPA)^yL* z0oXoX-d+Gf06^deOb>z7Gf5QzfS(_50sv3}lBohDxPn$-0|x+TF*>@FT#Svbg9xMP z9hl`G9jDr$N)8X>hpPEL0iN;=swfp-JY((*=NT@(eDA2Z@R+EO^?YHHQZy&jRTS!C zY6BhsMKBaYP!vN6U^qsAOd?Tm3YkKokeN&tl|f@s=~O0@X3nKEcuXdfLNjNXGg%BK zlSh!i>%>huhS7OcCYATUVX6ZhDhL9}7-A1l4uWwIQ#}|5!^aQ^BE%8kWC{sEsnBRm z>|>vp03bmT6w`gcfZHe=W5e|6^4Iji`4jAK?lFPv$ky1V;Ju%p&YRaQnWkFf=l)8| zC?7e6L}&hd)$hgyyTYzuh2AHj?_^c;)_ESQrVplf>aQ@XFOD385+5|Lx1uU*>&DYv7yNmv zYmg_e29(*Ah37KGiDhl{#IKBTK5aoZnh3Y-$J3HF9*n1kpB}%5|NT6M`Ic?A$#c*D z{h;gFV%L>b>dsbI-=Klzwl!J3$&pQdmvY9MT|Zm-#JH8v$RPw`B}>XPmY~ z6I#@CI3?KxAp0Z^K}VvDk^=TSIm1MgKw71ClkiB1n6P1!E~{l+hC`to=Ft-6g2a%D$`|R;hqb;*kxwgPb#LE%(KN*|rF3$gUPUkHcX?wwr6_7le*4T2 zs|MeUy9(M`+HcvX{J)-@Yb9VbE*i4h5Ey)5aR2!lEXV{7S!n_^4F{jA!;CGvN-sIR zogK6FxWl9!er20aR*cDe(`Tc!%3kb$bb?;$7C-Q)Az35!T-#EV{;v9XCud93Wwp#Z zBGy}RaCO96pXHIO=gy2f7hmamM{N46M~IXSzz7J)7bs}&7bu3XHdMhkqMaBfhvPnyo{ z$kC$WG`F-cOZJ|7-JaPAofBW(JIPmaNqM#W;<)Xv`+diz@Ix22=Uvra6qdIL3|W>7 ztr?3V$c~1U3!Xm4w+%U3o^9xJaoW+!8|Ntbs_wKpDdR9hF`?y#{;41d6agbr-@Q~?tH zu|J_c$W$N@ic+=G07H+We1sFeA`pwU^Ky3g3 literal 0 HcmV?d00001 diff --git a/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/ogg.jpg b/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/ogg.jpg new file mode 100644 index 0000000000000000000000000000000000000000..e20ab2fcba8688bc85b520c7c8e54c8cb0870f52 GIT binary patch literal 1557 zcmb7EYfuwc7`?lj$0EdJNkUK=yP=|tA|{bXd1yc-0)h<#MFhnpfEalUp%f9Vg<{3l zN~N@lDWVh~o$81+GNK?l7%a6Y4l)6;f)BtNCfWQY>9)WU@DWSA zJbWzo!AgK47>Xe%ilJ0sbc_lH&4x*5GMG#zgT-PKb~D(xEzV+bXL4=r1S~i;V-9;J zi*3hZ38*HpoT{|NFk1o6!Ug|3EDeCbK^(}%5NCiA2u2_lJ(vTxj{%I*U^*B~93t6J zNhlvA{%(@SMCl9+w{!wKScGyg4ivEEN5dF7T|V{Yx~A36b=ZF^wz8`9p;;2?(C;R1 zxdWG`o9jLOdlQakIqVoY^nMXHyW*e%pr+%CgSFi!Hk=-NU4K&7OaJq4gG-zJ{Jb|k znUIQ*0}zY`$yj0ND2;(&OcCx42)P0h!XZ(Fj!rC>CVp%G)O^mUI{>)+jWtVjnfm>z zul0$}cHY_xk+WpYf_rt}4bTi1qQ38KKRc|iEPSscFQ}>L(DTT1UJ9jQ)9-hUU%n_d zhMu3_EQ|g;vGUfhCNJ$xef8G($&q>WQb=b$0qH;jn3WES(dYoN=aPYh&{-t*3|OI= z;soWBBBPlLIn^#$O4QEXt?KoiSCqLSfn+mlI4n$}%Umf~&PVzSo|lBJ%3vJU#1AyZ zZ9lGxpM6;6>1253#al8w_!)$pM*wI6Kx0}V5r_%w>C=!N0aJh|1vruY$KEyWA64u5 zJ|?4M(TssBV^!T%H@8gee6i=#phh|4^xd4`lw!f{)w1hec}c-pyJb6e9EB*0IFwrv zI+H#P15p5tfG|Q)1jkt%nDzO2o?M~)<*nijDLOH?C0SSchCO%CyZPT|!N5q~PjLhl%fj2H0PiBbARksh|i@O^_)@pTEQ%4yUF%(zJm&0ZRb)Au zhkGrar2Cq)heAG4=Mi?0xHJ{;cfxF4M4{l|^2Uv58JuX7Z2qzasr=H@+1l zytL_W-}6PP|j1@i(f0xGP=;=Fvhvw%%Edp!}hrY`L%8+9Bx;^zK%uP&c{F@&qC$+EAPi6!= z9#s6)A?_m_Ug%52TpkwddURN~k>7jS^}wvTH?&)lTo&|%^kog^@vrf2G$nKuE)Ez^ lY%te7Rb@%$qsyo0)s(es`YYfuavE z)~s?}1rP)P1U^8~5BSczq#*#fxd9^p00kfkQb2$sm<0=90|3oK=f1?`VRK`VGO3sX z%iJTjOSed4B%9blyV+|zoL#m^!=-F<6B`pV6N`0h*YNFj6hoDP5iw%F+YIVgFgYuDdr`_;d7;yq6grgrY}>O>TJQL# zib0D{SoP&ec~C>|vU--A-P>A`?FT;->7aFoC~53&h;bJGc2SD|8F_O0<_etx`^|jg zQ`-A<>RWdkw_C@Lsc8n}_Bei9@>R7od}BJKw+IJ-1PCN-mK^L56eHjqF3*gp&eY%w z93y4ZETM`kk&$j|1z5yUbqwf;noM9NihTCPz3dbjSNV>{M?a)DvPUM0&lOawxhEH_ zrW>Zbs%(ZB1~VAs&#EwuK~(3O&DY@Q@%Xb4s1jo0(GsifeCiP!?e^1slJ~`R79Z5V z^WQ#TqdQh9*xMub2+%up*3Xuibz`q($Y2gF@3#_{n0*k&k^!Je5h88gCmCAX;Lkp#xH9Yhe~|*w_a$udve$E_HFvry^@P6VR+VJ>|KZB52X%!Op_I$ zCO4aEWsz~IO7ls-i_89I*X|cdlSUm{67q>)qEAy|YS~cD$rrJ&=}u`A#XeyncJ@0H z-qujUhSfai4H@NqDntc%Y9Mz{44eqn)LHY8m3FG=55ofzFMQ9k_|ikE$Aa!G%sgNj zYmJV#ro3Yg_jvy4{;XWe$hXYZztCxscKU-bpo1qV&Yr(Pa4OOu_t5oU``4zjmK*?G4%Z?a5?C*8ro3ZPggiCk1>`lD# zD9%$Hf*dc9FaKie8DB=(~6BVgEp9^N_SL=86XiWB_u>{ho> zc(Faf3iaXYMVVw}HZ8>e_Q+=EJYFidFl5uFct> z(G|yD!I~c|X=F4t4*9jMEfgU#JHbmQ+Y|3wN`7osy70etBfCjH_fb3Vdxu!n_;>; z3|J8x?$_n*uRB1l9q999vYM_uDR-I3AIUMUO)z0;^{Bt{?)0N-pZB!(Z1}(~w3!?z YzC{g4`O>ny8r+H literal 0 HcmV?d00001 diff --git a/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/otp.jpg b/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/otp.jpg new file mode 100644 index 0000000000000000000000000000000000000000..802e78ccdd971db4d8429b0bd900befb86351b75 GIT binary patch literal 1870 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 literal 0 HcmV?d00001 diff --git a/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/ott.jpg b/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/ott.jpg new file mode 100644 index 0000000000000000000000000000000000000000..1a4157e4570faf5b2e20efaff272e816ae735290 GIT binary patch literal 1748 zcmb7EYfw{16yAGpZW8h!2>~OBlAuMzS3*Rwib+6-APAz>QHllvlvqXN9mHCSJQWZX zOMDGMsE=4HXrVz-p^Ohi6tpTbMU*O5r3Mg85l#1kqW#ey{qF4S&Ys=xeCOPA)^yL* z0oXoX-d+Gf06^deOb>z7Gf5QzfS(_50sv3}lBohDxPn$-0|x+TF*>@FT#Svbg9xMP z9hl`G9jDr$N)8X>hpPEL0iN;=swfp-JY((*=NT@(eDA2Z@R+EO^?YHHQZy&jRTS!C zY6BhsMKBaYP!vN6U^qsAOd?Tm3YkKokeN&tl|f@s=~O0@X3nKEcuXdfLNjNXGg%BK zlSh!i>%>huhS7OcCYATUVX6ZhDhL9}7-A1l4uWwIQ#}|5!^aQ^BE%8kWC{sEsnBRm z>|>vp03bmT6w`gcfZHe=W5e|6^4Iji`4jAK?lFPv$ky1V;Ju%p&YRaQnWkFf=l)8| zC?7e6L}&hd)$hgyyTYzuh2AHj?_^c;)_ESQrVplf>aQ@XFOD385+5|Lx1uU*>&DYv7yNmv zYmg_e29(*Ah37KGiDhl{#IKBTK5aoZnh3Y-$J3HF9*n1kpB}%5|NT6M`Ic?A$#c*D z{h;gFV%L>b>dsbI-=Klzwl!J3$&pQdmvY9MT|Zm-#JH8v$RPw`B}>XPmY~ z6I#@CI3?KxAp0Z^K}VvDk^=TSIm1MgKw71ClkiB1n6P1!E~{l+hC`to=Ft-6g2a%D$`|R;hqb;*kxwgPb#LE%(KN*|rF3$gUPUkHcX?wwr6_7le*4T2 zs|MeUy9(M`+HcvX{J)-@Yb9VbE*i4h5Ey)5aR2!lEXV{7S!n_^4F{jA!;CGvN-sIR zogK6FxWl9!er20aR*cDe(`Tc!%3kb$bb?;$7C-Q)Az35!T-#EV{;v9XCud93Wwp#Z zBGy}RaCO96pXHIO=gy2f7hmamM{N46M~IXSzz7J)7bs}&7bu3XHdMhkqMaBfhvPnyo{ z$kC$WG`F-cOZJ|7-JaPAofBW(JIPmaNqM#W;<)Xv`+diz@Ix22=Uvra6qdIL3|W>7 ztr?3V$c~1U3!Xm4w+%U3o^9xJaoW+!8|Ntbs_wKpDdR9hF`?y#{;41d6agbr-@Q~?tH zu|J_c$W$N@ic+=G07H+We1sFeA`pwU^Ky3g3 literal 0 HcmV?d00001 diff --git a/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/pdf.jpg b/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/pdf.jpg new file mode 100644 index 0000000000000000000000000000000000000000..2080921c1ddef54ff2d192666250b86b47707fa4 GIT binary patch literal 2050 zcmb7FdpJ~U7k~HObHmUKMsi9sZXu=_m*VSU-0zo(N)bkeCPTnwV%D8wcquu{r-Nxwbr}E{o-LjaLW9>Aa;8U-ro4FFsWudW;~Mpk_X&E9>R#p}-Ew@Hab`9zhB_Bc4 zC7Eb0mPo)6i2t{Vn*o^syufh;QUfpu~zdX&dGfqo1VqF9O{@(HB8AEr@ih*7dOZzPuQ!* zGva*Gj?`H0HjGvsR4RP{@HMk9tvY`*PG}SxGb;&vtN`B3?$79SIkb8^jH6xJ3pkkl88m0H0C!3Y_H1vr|# zB2|rvH@Dz~D^Ltr>{D4K)ypVR!Ofum?CJ@n@TVrYeY71za+jO826c20DN4Qjo*R#K zjSsHBai_L8cin#W%;_Y|!WAa}>743A|N5}mNGe=xH*N2fW^#8>N4JpPOJ{X|#B8*D zc-he6--RK>GH>suotQ+|ZvS5|)?HkD{6%`u_w+k3bwORUaCr|m*u63(&*cK%?zQ^V zrALBJdxwG0EQVChO^vJW&7~Tx-J>WcH3=sS+HotCfP@pk$WyU2HKsZ%e3=F;p|Nlx z_^_#6!M=vNYLRs8lKcJme8)qAsNB-#*4pTwvt3JE2M>w7=CE4h-2u8+;(`t8gN~v* zn2;o@!8kl3`)v<&N-$V5kXN8Fmg`R*`-UQKSTLtYKfYW!h&BY9f0 zL-(_7!Gf>i8H!Fm=FcsgKb_Nc7&!2t$Uf2A_S0!s?(+jKHz)MUU)|q4kTF}{)*F4z zPHMtBRS+iNu>Bct!}xiR3;QTa9k+X|&y}gSjvonWq_h;Y{9Ldvx%|8QPdynatI_zfHoAekG@{evGS`1S%4pI2)4bNu zkCE*MDLcDzBNAQ?d7)*{BB3*mU?6mkzLfzY0~(WIjy5YNyqe`#($q7vGFfJ{MHP+o z7!tk{(yJ|2-@NJeqO;u{Wse5q3vKoz8uJzXMS9m?8`d^{myQzA(NE*`!>u4DYr#r z%H-XA%9eYpB5%PrOi5PjKi$SBLuOfHcW%AUXy41##=WR$9$~6k{?6<4D}FV3roXYo z_C?&Jnot=dpx-$x%BxfL>`mIZDRn3Y1+qgq&^&s`2PBEty_?-MTND|?`Cepj+OrNInQEV#+=<&QO*PV zNo$SHx)bnxd7shz(UFpE*DOsPmpq)L+BLI%nC8iTGkiv9&H2rKCMF(o^%;6|-d3vA c@aHkR&OiOwlJa4%n;AAy)jzAKAVNIwUy^9o$^ZZW literal 0 HcmV?d00001 diff --git a/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/png.jpg b/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/png.jpg new file mode 100644 index 0000000000000000000000000000000000000000..8c771ca3c3e3c87d3eb8409538ccc6187ddd717c GIT binary patch literal 1979 zcmb7Ed010d7QgSkY%GEI0*Gvx5D=BNOcIcQm4OI?AdG-4Wvc`T$|^x%6qk|@6gTBQ}GN)XB1Fc$jnocHeg?z`tZzq8%nQ4Op9 z18^^QPj`SI03h%Iswv>I?Lb^C06spz8UR28NKPCe!5!2BW4Hi7tI?H{%xY|9AEs8S zmVn*Pl(e{{xJ*$DE9xN2%XgbcQe1Kz%htxxhG(&w1S1gD4VX9rFhpIZ6(LioBpL>F zCh!=>{bwCULQtqzDS$Qxl{kjO`jz~}U^;8X9DvQr4{T#aLx#g;wN>?TQd_yyZ+d~( zq;oV2Tz=4GpHX%CMC;__=9ct@za4(O)}#IK&F_n(^1JfKkxiP$038gvAiF$NKl_z) z!oH8*OzU);k@>vLHV=qzt$Kv8U1bd`{%BPXHBr* zSoX%l6GpSOMoia@hVT3Wj)gvT+(XVwHypA0Fu3jSBNoG~ri!L^w+X53Gbe-Ga|zQK zi-EI8ilSQ&9h)hy4Y5zgvvNyA`i@p~TU0arYbx$!G>fCO{VmNxUdb=K`!X^L;?+Hw1MG%z0^jPK$HfJlB=dzp$?1nS4$PKTwZfq+fYJ;x0J`2AP z#r+{U{Os%@i@}(q-f4Mm@$9%@rZdF+D*+G`!)RK6f`qr4OfVp1K z3ZwRk;&By#0rJ)TLr_f`iTW-?RNYX5LDn3Rhorg;C$+AmP*_r*c^6VX^Uz)7_aAcv;)*I|?w`BmI&rapy8n}+F; zp^?FLTe349Lwf^CdX)i~B*|pFVcEdL?s$g7w6ZeLlVVy^(B$>P;FsX_p|0Ed+P^op z@p<^EJT>|9iPOdDpV@_<|J?K6Jte8>o}q$kUO%XSD1>A1^K?n>?w(h>VcD(JWk)Fp zd4<{tAk4V}j-OC0e~zqq9&q;i?>x=7&)-3!hS^psW*<&>pB|qO zC5K9s`rbgdXR>fXPHd`~}tVwP*?UKj} zBR18Q?o)xKrS!>xMu)^fn{=aQR3<^my$E9OXKF48XfDy8r_egQ4jikEOh)MKM7^BNzO)QszL-nJP3BZvLf zLP;Gaeo1|lr{C{(@O)!LxlYuq%^B0%_nvVA7^NCdmbqey!+{IQfvosLV9$WS4`*?n z`$h`IlCG7O;R||i&r7|xvhSw(ZPRzr!_kTSc;%@=hm((b+J^0dQa6;Y8K&RgE7qLq z+rjChj}v3-hf<%g z8?8S31scpI-8s7*FW`HkPuh$k(0hJoSmI4719}19bt-y4`PDHLJw}+Dz2_8@u}99A q-P?KT$Db74$!(m0MXjF0?PqdN?AKGi%o@JMxpl>DuG@&L8u>4o$F|J? literal 0 HcmV?d00001 diff --git a/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/ppt.jpg b/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/ppt.jpg new file mode 100644 index 0000000000000000000000000000000000000000..aa13f733428128a02fb020ae18a70c8511142c39 GIT binary patch literal 2386 zcmb7FdpK0<8voW>Gh+ooD}f-nG{Ae9wBn_j`Z8_x4GiNCp7vXwS9> z5Ci~(JwP%DZ0wE&_yVwP8!!d{5CIeu0C3m}(*jNG0|3s2fBcEeMSiS3q)N#GFxwsy z77!c|>2rX}i=aAk?6w34915VWGg)t9YQl7)vJZv%gdXw^qSBA;_x9zn=nMAgtb~0{7kgTJ`4dfPKKz{( zVp}&pg`vOuH4eNNkF;i;Y8q0H5Uh-f&CI|E>7vqP;1GZ;vBlvLm>>fnItx`+U1r0< zh!HWu5FTEr>fF9+N3eVMR9|c%gYNzz(u_3B8A-U-pF#1k-q(F_B*e8jBSs~R)o7yW z?V+E1f^#ML@YX`O*0gbSuf=bo;pTvn*=FM?virJZc2Gh1d8^r!-CHcTYTpQXl^BzG z;&PVr)gg;~PQB%jBS}3}V|L}|Z-y`9&*@K04wxOU3^mQ{eKH>yqglR-d|gAQWw@?m z`oZ=Ec2*v>fPoXL?2+D#^R8>ch zzRrwk>n%(wdo{U87R#?S^eL#8>^yhX&+swVD*dO85v~smwJm$ad0O&ymd`CE;Gf0I z_wGGza;)mO_|=I832^h%FNp8at>M=8+6QUJY72^MmwzDvcZsZ&LpylcapA@8%Pyqu z(IYgrkGZ-e|E}p?)=)?8yS7cY+684BDD$;3%;qS-x*5jFBeLH^jA6zB3Lb+@XAn>o zny#&jcbKrO+>{@x%4FGac>7aC->ZsX4bOYEmX8*Erd~9n=CfJUagB?2&IFsh%#1#w zwadaGY5LB=cLVn9@utX9NVhs)wY`4FAK`my152i75)I~=EGMJ#OQEDq@mpJ;x;Lv` ze&NrW6KC$x5V}Sdva)T@Hil30ozJ|wqnVcDD63JD{k4!aiC_I?x%1Fo+T?FtW1@)p zH>Gd7C#$0M=FYUP)3@;OarW;LUVrW;8@S35Pkr{+>zLzeeO#O34{TLfPjz`-Qp@;{I*?Fx4ffe{7uzv-N?9-MAxGyGoYc=Tj#uQq*dqbh^&~nS#ROVYnpY} z>-96!+^EqX_K$q?=U13FKEKp{^rXOxMT+q8eJ%l+Sk4TkT@T~%Sl=(@i~@8RbXymZ zH(!uchIUR)*>D~#wZ65^e3{U`g{XJZ=8@2Zq42Vcpmo$CGe;Zdbm&}&n(+;J93{HK zKSi~Q-_w5MxNT^m(5d8$N7DqY%GBaff?03Rc`ikrDpoQc9+{jS?0VsB8mBERw3nkf z)C%oJh5~Z3*79T(4xtJcjyN9z%?B*DI(~ z3Jnm$9 zZ7q!mdsIBL(_ApHR5cKRfQ_X8RSiQ2s~T?sYQs+wm32;1zeB(-3~O{)#l?<-!PwAe z+&;Le6TSKALNc{D{9e!a!FX-l@Fi2Ou8QrZBl@;amRNu&3wdj4Tp9G}n zltou^Ns&S#N-Yy8;{@Z5goXjX3x+msK6z7bvz!t{WB#Jo1lKSXm3sLN^0LM0owxil zUi5}G7i$YDV+S+hBO+hHJ+i( z)$t0#t_l8g!}H#sU&CWB*IxE4?;gX6<7V2Q**?3y%iJ@Y{Yk^2YTws@w{VX~4MWoR EU*kK4SO5S3 literal 0 HcmV?d00001 diff --git a/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/pptx.jpg b/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/pptx.jpg new file mode 100644 index 0000000000000000000000000000000000000000..85049696aed2ab58dda7b0adccd5fd70624528f9 GIT binary patch literal 2479 zcmb7FdpuNI8(uSeW{k^Zk4wT-gK<5{U|i>5hQyEuF^C!8dJgOW z8U>*t6dDbo#Rg#^vEeY15?BeGgoFf+K#(QM$jjmt@dSeWDtSdEC1qu0St-@Es)V&N z1Z5?05@fn~rZfaeE8z)vrT^QO?gJtoc!4+wr4GnrGJ17gaT+7f{_Z=o%!pP)6ZK=(^$S8;2UNiHNPF} zKF-+YVRSAvQT3a3*W%m;ug8lSe)YWg;*i+~5#BLW;d49B{+%biZ=EmC>D~f9+=(0a zi5AwxnY~GWs~j93mM|02)>Scgs;Y;_xK{f!)!P1&nANVeqNF3Nu7;z6zKnPE-g}#P zVf^`%_JW^z<~q3&^`}H#jeM?4!oT$=f~%@Ve_cddA_)*;6d0f|C#bh*k2aeyXm?|5D_wN!Us2-&C?eCtu8n*^- zbWT(jU--tMdMbh#dbjxDYL}tjbpe={RooW0FV5c_kLZn-6~1a~tFm0QZnyLGqc0S& zJ(@f|mA<8O~U&$abQ9T5W+gW*DJ_a_!XT~^w!{MTk@r zF(5ZrZmr>2R#tZZDmCN!`?dErLDIHJ0XSUTe{Qf(gVn(XKV9sk@b2 zN}g@r{AG-OEOu9`)2}ya&O>i&NH<{DAe$Ex(4&GD)3b}_K4~2@(FU%s5VSAWK{FGgdTy%XiHxeT}wB z_HFB719#_pN?mqq6Qb!HjsfN1;}C<^{10{WM=O$F9iDB^xR_$ns<$V$liobmrKmBI z)j!RN;f=PR`dvQFSMajj*}8o13%$sV>gw=#8(q3qO&H7LZkaYM%5Zw5J1;pHQ1;g$ zMFg@L(oYZsa5&sD<{yxWa#%I0Au~!|U4zZ3fhk5NzGoE3G={C4`~HY*{(oBxXMtwubP+^oDb`adX3ygLPbGBYEk?!w;d z_s?xgc|&)(II$VTJ|z<0Q47Mp_fisZGl3<$+_));vu%nh7dk9zdYdYavDp+YRQMI3jA_6r-DhFm~O_3SQLVm9s zH)(oV6>QWNP@}SIWN6po^DSXN;W}zbqT7XDN}lmcJt_ThhwFGiI<8x$YauC0b4fV! z^|In{W;efdU=mcRJt%Jo0h*$t_e}Wf`^bA{LW~zHmq6Vmzv$}ldn)cK3Mr21<=|{i zchXzOu#Vu4iU4=3w!WA}-Zz)cV~OzOjw^AKzeT!N<`{VPUro8vsV)rOlY4D| z^`_!$bLpzK?8bNJiQC%Z2E>W8SUYj?sK{GGE~Ng$3xWoXJl}u3Dr$>jA2W{#0~_V% ziupav*&_4_9b1y}mZUT5ybzW@)cuD%!aC&Rcyb~h;AH?Bj~h4zqw#t)2I9-y8$o

    Pt^fOKD(e?!4mursha)Xj-HjME6lG= zhx;#0Mbm$*Z^&kHv&fvn8%g}1`X&|&n48k-Yq%!OVbx5&ITO2{@e#Ga zTnO)SA{hw1iZc56@{L?&){>7^jP17XDYJq6)oyuptaE?GX^l|CK z3{~m(xBun5CS(K#irPG@;4tL|25P=lJhV^LdpG=gTB9kJ_I{nSuQ}m!Z{gcD&FyCe p+N)06^2|@9do&N!oa8e_@A8e}wUV3|JzC%Lx-9 literal 0 HcmV?d00001 diff --git a/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/psd.jpg b/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/psd.jpg new file mode 100644 index 0000000000000000000000000000000000000000..53028c560d07ba15c963e5136a5ca6d4246ff4e6 GIT binary patch literal 2110 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 literal 0 HcmV?d00001 diff --git a/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/rtf.jpg b/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/rtf.jpg new file mode 100644 index 0000000000000000000000000000000000000000..c0e14b3f4b883770eb061827cc9eb8497a75805f GIT binary patch literal 2511 zcmb7FdpuNI8(w?wx$H3PVM3HJya^&U|}1r@sFE*8c7NTfhD6^}g$U_OqT>{z%>jFlR?6 zM*u+pK==jZ{lJ#DGc*_gH#e{V0DuB0DHIU!8IA%S{00CnhQGgwDMr4}Hz+{)-@wWv zLL3?v8nY>gF5E?T_T;S!3k?sYTbeC3voN!Er8|X-H*F6O*h)9w8604-SjY;tmOlpe z0EQ44fnXSc6$2q6ia{a}$V4)UOeT{k6g8@fk{YUvQYcEQ8pPmVVTK$IbeuRUh6rfd75}SK~((HDb3@;YcxOm zu*9c;&IEwu+SqlspZAG<-@rf)JpLmGPM?eHE2P&~i9V^knv#Q{(eT28iQPzC2*;Wz z3%cVLJET~yFWmNpdyZrM!q=~~P9EMyFML(tCG*N2iYG_fKbBL2AZK9V+NG7*NSe zIai3+Yls&^Adr46877i&LZ}cnlWxIAHOyHwTfBA@=L90cazNr9`SDlWnTmToFvgwT zb0<2lx+6a>-&1lgq)x3vx<=4CLpx-3{Z#f$v(2I7FOyGBEBOyMs|u|yF-0_SZpZD% zZuWKW2If7ymQp>nz0s?Qba=q+=e)EM*CRAekzpV@SZ(ONR&8Q%B2lTfoqg<(PvUBA zw>4^WrnA~4k67+wdvapmwLLFyD0AU3*rI0+J#kAP3?&|67Mfa9jJ1D{DRc6v9&-&$ zip>(iybZDfk6X)P2St5d&Yn(rMyJz@9Z%+)Yz;YE>0==9Fs`2ZCE!bXSMvvpw9ow4bC4I+A?EM7}GeK@>ZkM@QjC4 zXQHS>r~R1D@{K21IsMo}`s-A^4xRgUZ%6I7n;oS{3Oqj-ccw+5?#SB)hEt82h$7N^ z?@O-1lP;hF7!Yyck-ueyV1N)Xbt09;NFZrsRMO3@R@y%w{+b+CBnLMQSge#ZS7D$= z(7+2r%`+p8(qP)!9%g5!&1h(vhfmHZukuM!fR6a}u34^^Bg5GKAMzuon8$`j&Lrjx z&X4;j;pgvJ5_q`$pyA-v-9txzx{z6J!1h1*Jbz2g$|E)omnD>pUpUu&?n_d`uPzEO+chLyX5%! z`g!v$trpv^bl?m8h1>UKWL33)_*Z5mE%_mdJct|7&%F6Sa?DR< z$jc~mX#9`f9vgdyj=!i#wXnNRaB)pnvnG3E@-tsiuGzNRE|dG6y1L!Veb6|Kb>oRt z!lSb3;56lCFZT)8tqlzKsn|I!v1_IN6+yX9f<~j4XqAP*`?U)fvkznKmOJL=V@kcq4uQC)eFw>6;K7$k&={vP6*R#@{Ym zZ?(+IJ7WH1$S%Cc2KhN-O%b^*aQuSA;jBLPjXG%KR+))<1*G^&`A3X^UvZ zNN;Lw9xKYPVq{j23-R2X&{; zlGSTDTqXGM(`M%0e&p)w2=YR0GO{?EPum27Av5>&Mu&}p2n}gl&ozxi)kdZ!`Pdj2 zPu=rm!`y14QQ|C~t2WJh+p~(;>5WG=e2jmRjzxGT8x;rrP309CrWT>0&pq(czjm6h z3}Gl{N5GtbOt0Zm%0liFE!dyOQW99wdu;Ih!OmY7v{1U<6e&g`4@u=PHj^5g2pCim3hHA zi}A=zJTmS^2=SX4;gK=?m)Qkm(D^0ikqMRc-+c)4Zu66a*Ouj0hY~a))6u8*Oucrb z9q_)?kQrsPuXn01DM7ozZ?9zfz?FR29pTs{^Huah@9re4j%_Z3Mf5qkQl9apjb-jJ z^mxZx_PKa=yhA~-qDB3Xor*h(9TpIoV9RgsA0F|~_-6xnhvH)6^lWeBR!c$7d`Qdv z%aiqXC%TPztNRFo18BlE8+onC@aOEb3~0Kikomejzu1(a|^q7+f&7X8S4Ou>DEP|4AMnmrk3>1nSw=?{Gi;Q%lD+V}N7(*7MNY>nG@hGBL{v;%LS8{p zNm)f#@2tLoq0zpRAn*UNem7@`}cJ|nf=Glb`?7E2cZ6mkYnuXHa!a408^RM^YqhY#h zz6Fd+m=Cfsm4OzH%WgGBXX2OkjuP^9)2D`OnVL(0#&>bu zP5J)7q>6^^lR#U*+7C|R@gh-yZA>5{qM#&04p`}S?4^MTdO=i|c^psSx+BgraGB?L zBE1u9y<^1$j9TvPqT%wn+xSzYkmK;A>X0ErVrWni=h>!%T}1l_p4;YD!7fbVM{K#cjqlavj`w-Ld?CA5n#sn71BxGQNx{mn~h$4^=-$6D~2M7^hA zRC+an=2FVvHxn?n#}X|Wiv;rWDo*jW+rX+`oZo8lysf?&9*QXo%o~idt8tboq#i9< z#J`Py1rOo>@T-~hazyka+~+JNz@|mB=%#uyCM0qR`Bg!wkAscn<9bbwzPq>bdlOBc z#MWj_5NHfptYy1b1Kzpai*7&o3a-e=MkozPZ;r*bhQ3j|*5!bRE#>cL0<(JkUm056 z9A{$WO`9o|&LqX`aja-Vj_0{yMN=oIy+R4mbz$!gias7nJ2kv%u28YBPnXQFWuY+v z!mU6iz!j1iB11lT5BK3y(+Z^VUhj`7Li=34I@DgRXN6K*e4U3DKa+M#WZUz%tl0?C z8Drtqg)#Xd(Fv`bCC1y-+$n#j90&q(q0GoeSaBg?X@6~9thJx=y-Sw7IIBvWzll(T zeI^k)v~rx|=IDCJOr8~2pQBAUxhlxJGg7iirO7Wz_Ni$))#{NQ_0^74VQ*xGfivCZ zps|}+v?vwl1r3nS%?;i@H#rTR7bSd|Ahp-kX6 zL}s`7Fkjb$R?TM8yz{P^FwxJnEVjqBAi&aKsHk0>To>x`;O!RD-a@wlBqyq=X9WLj z%qe6*TBdZy6dy>O04}rq#txidVUGXRzPM{v^CsaMH6Q)3O?igI96kxdVwha0^3u_a z%9pFUj{$J*i|h5dUQjj{v!Yzka#3NBef3~V%XQm;5Zn?+bLmY9IQ z%#09(3B)JUwGZ;>uoA{dp*~IXnG6!eP?!n=$+9yrflKZo$wr(B5mhYFft)G2(#F50 zOV{Ao^qo;{m=hBU>8BH9@5fa(bV*nA!=Z4LT-vb)NvCX=LXV0~&nQhF|7ea;x( zvE`gnJ^R66xvnYt2HbingLCb9A4C1-mtT9ooLr*!!K^(n>V(yZo6{EaVE4pr(6(k@ ztY@cHu1=o~%FyZQhF!5cM{8a9vhv#&3or<7%iub;ujD_PIxIyuqmh>OSA3!~b)b|f zWc3XhTH3=IxYw%V>;V%Xhh7sW+uaH5!_zL}M`ETsZUm+lxlb0Gs{goJF zFve^pp5F{NxSa_4l~iqHql*rmU(zLvX3i`Z${OH_`I!fIl)9cf?;-L>z{E@$ift^b zRmWH^@$#fXXG2Rv7G#PJTiUdBNbtbRsfYQF!gGSEznMt%PbWU{MyXdpBB}L5;Ui;le1y& zO;u#g1Y?zP-xiuXRYb|v=T`dLL7F>3dsd|nOB*&#Q$8&pFC8$dI~iVjS+hF4yT<^Z zpoLb>v^YFgyMVqLhn{+P%%XGklFw0yd~hqo1s7PP_sZF^<-5#rxC)YY z5>KWWAk{dGYcARMPPF3^E4V5KdCDpqdCfy@JQ}?zjw^wM(9y*U!==8kZ}$cpYNg2Z zJOhLdah`)!`0?sYxbo=hZTd;=8Y}gqR+Iqqa)j~J z%IeE1D} zz8U-i%mIJ5N7^l|v_8mZJb@h`%Uosxnnl+2>KJcRR!Fr1e+pgkcluu0`H0 z4k}9;vV;|y)R0DTVwGo;Ptiv)giuJAf_W4Gt3qzH>K2>2R zS>T&pb-6|ff|1znjW!y;wxnc%lD1FDR>*@jX1QUXAGr4{n#o{HWfWhocqo&ckxw!l z&^|A;ToL~6%Dq&<0iP!s5_*1KH)l|=1I+yjGvTBviR@1oI+wXCD$2gfY=kkm)0qG} zKpEcbrVPq(#$3804))VbLZQOo4VT)Q8jjPtZ5!vVds8*>x9m;5Q_M@A1jm^BUl(Ko zS3l{qkVJm?J})zYc2P9NE|aTy@ZJ!4^dH`w$yj+wud6b*#5RscDc-_(YFW-eawdwM zc)&~GQ6{i9kbfXe>ne-w4LOsWNWbFQ3CfZ-tvxk-y3c6^cb_CRC%~=z?o7I&(_kQ3 zfeE~*JAwB7X6hPrCWx-yc$-GP~hHV0y=7HdEJ4tYmC4^s?dS|KQnDGbMoIT=(#5C7i30I zhwHvHe3*2w)N>m~ISf2slWXM1uv@E;5fJp5U(|;z>!AIC8JwOeRVqLl)atoFx;f|B zUD6@jXC{DmK}+Rj*F~noTh0ZW30dU0cxrwg#5QjQTQ-1uWoED7Thg)yV(#5vyHLsl zvVA!N@$*{W9t(Z51;T3$QB{P!#&)M;1P8BucgvP_%4$12ixzn?xrh%T<&ruq4PWg+ zu#I_Ts)muf1=kSb4VNCm=QL`feYhZYFCEfuvb;R@!&g=^zQ-(IG_{xX3yPNVt=x2| zp~67Dg9%)uNy?EtRmmNe#dx$KLCQQ8-B|i)Sv(^oIs4!zA%A+VB7PlWItMZAQsxWm7rtH!|aokxnE zM1BJL#%Mk|bNx;JI`kWg0!>tc>m|Iw_VOou@~V4ZTtImzffeyN@jUCt#$Y8A2pJ(% z8%y$01*`62L2Y6wCty5i)eha8Bc(goUhs_NZZPdwXf6}rWN^{-DSWl4(V5KSeh9I# zEW+DBqlCg)sL(tfM&>RqfH=XI$7d9Ho{vXVfiVHaeWG+~Xq)^zBIvuX8w|QB3TaR$qyNc8gLEliPd!CH#BsyZ#?j)qfbT z7-Ep>Hm9kq;QorarQ*9oTOQ8}iXaj+DT~kfx$Z^x^}fRxiHGUu&n#4iIrVP}f0GFi z@5M=(;lIwdLuqCeSCYfQ8C~2Rbq(?6w=OVrDcV=yxfeqvmAk9~TJNA1e(2mpM_^}4 zDWZa;5x8UgOHHn0PKEEZ>jkZ7kduH#r(&CPIHKWXO{+=7bH**kXb4~TWF~v)JA>ZK z5jrx*Xh{APoc);iZRtKU<{@^ zw7rjjvir*%)#!*LTNbg?hRLECUv|_j_IsvgOZ&bg+vHX^-2G^(TYUu9h7!QT}!pEh69>1mS3RxVJtCfe&pWeM-{Il6$2GY zHF*z%rr+(mXmwI9huxbqG3PUuctASYqvWIa5?gL032`S4*U^kzV*1oPjhk#y(Nd-= zIaVfyL~Kf$KP189#FCQP-T;I9!~Ut5^9L!6qXA%UkUuqQh>R-Gzpnu@BMqGc1I7#+<>fA+a!V#%&HPjMCva_?5u8| zxy(rkIaE?#Y8ZTo!Na|8;>rE{1HZ0cD0>OPlu%hHH%$lMCj92&BbF-{2DfjDeSiJx zwH`f}EF${}bhW@@&#}r5kJGFo`Pn`CZX*a@|8>psVKs6MPrAa%XYnM-Iq!N-ctifX zZTgfpM!)fUT}#@zqOH=vFNmi%r=BDY_0>U9pcLc^DT`!+A@(Mmp@C`FoyzAL8AUv28y2S$#*{ zX#LEkIoS2EqgC;yGVxJUyQMtiR9z*q(okVel;bD+ynV-w9vi{${pLkmS!f@ZnM zYFoWatD8aDK3)o~#`B+(zbKhY4j^ec`a~NCK-S*zeS&`j9Y&&}f#LW#Hr?F`V-30! zMHJs|CzCHo!x4TsWkuiWfMM5fi&|D}*f&dF9oy7U2)pyV$pp3{-sPNgan{!`Nr+wY zikeAO_^KwwA=IIK(NDE2x8Atu9!Q7EOR%!kyxtBpktvB zH~Vg-SJfz1dRbL*==*spmccu)FG~mSUqSYMkQ^wI(o42_*b`RjkL>Y0{^<8tCw*JV za+P-dWF{~vwR=1#|K?D=>yXBZT~u#ZBogiOWl+L0 zcT020nJyZ(+f7T>_-rh`&fuU)Vr)(tl#S??QsYwX6&3HtoF`9z`G(U~=4n`85E)&u z*T<;-fm@Blrh?4USCTlytSYnGY|_EiWWm@^UZ>X=_eYAYcbiuCM3IXP(JyO7!eO8* z_sL)Z*tdBfqsT(NkFIjqlXXMd=9l|J4HZ79d4{E7<-ZJ4gXkgDkW`TQ(y-7chAuUu zF^&utreU4BreZGQ05twAc4i4gjjKr${B=PrD| z%7~U`Vm?vhhFK}F$hzTxE^=1*vir?lW+76+Je#s$i@GMx2TdBR_sC~W8Vc=b=Cro& zCEhf!u)`$vj+DJfSJ5pNGYQy~Y?^Bwc2X?=X9XgT`M(N<`!}F8rGd>SGQHg#F=8VO zLwHpW6X2)wlJYgV*79!0r(+X$uD=hbrFWtwkSQ-7t9LlSgFo-Onj&2@KB%8c5^k2% zUbLr;-AAz=L)pKDi3Ob$OgQtcIB~hyVdlJ>3Oogt9vRyI9@^QgW?x?qE-d~Aq433A zFQPKMN$)HRsbGN>TH3Z&AM8jCnuxlZl2?^nk@))gM8LK2b2W&d-#^v~R;lc$I7VDs z_M-<^1xj>vmwRl?eyOSmbgTKCNU7H64%r;cD%wV=DCZs|tT9I^{+9jfg zjmo8F5q2da)mBoR%p?~fU&dUeQ!xW9 z{bCb@F~a1iNIE}>?&a_15hD}{>1?Jg(}HQ`L-!OVM8%7E(RA}fOE!;hX(O;!^aB?F zLkNsOFpR)TL$HX_a2ORl7LQZM<8dUCIz>%WouEx2ku>LNYE!8+8ckhQS6`Q;uSTL# zm5ZS1%1k1H5UB(bf%?Bq(F!O8zy-+&WC&migis(w8_-3|M z)1RD*KA?s`045`3l-!BAoY{WfjJor2>5-6#iS9Cw1Hn4u=t2r~G|eH*t`ge={jVb-fW92n+6VsCKz+04zk`Y)l3a28J*Yc6Md7!9p;C z0XTC!MN?Z#V?Ny}9Nh{5-5`X8XSAZ(J$3AjV(tQ{u<~WsPu8IOrN^z#`}oQ!>t_5w z%6hDzN7}?0osjkAy?WKW62}ybiR*<=I(ZGLd=^o!wfK)^r{;A{L@`JDbq#ucy__Xm zOLG5E!7}3CHS_rs|NtJqId1LPs(x`rSv>#W|Kmc1;goO9SB zO5=8fy651cXVcr1^eA6Joh`$EcFQPkN66(H0q|Ua6-ois3?7SB`HTTo5(ZE-G_hI+ z<}41+&^dq~M_*)N8Sms09S8mz#JQ_f6fYimlamCyaL* zd&ZZ^3i#eV7-5x7eYRV(D zo6BXJFEWUeR)PekIBp-yJgC%$Y`DDbI&sIw+_LaKRqI~5s;O(8%=9`-ifzTy9B_`Z zsP-%d(l};wLLyo5@#oT%I}J@hwKi8{Nz2i&D2IZEz;n1!vvT9^M@Qw{J4@_rZ)t7d zJYf`$R(pm^26jd9yNan{Rh1$1oAvetsYK0twa=>ksizsM?UIf?xpH76uwkqNd3MC$ zjLE&kv-WqPa zND394Ixi**ecA`CM!fgcC;<977SGbgA{b;&a}b~yuma3Eytr|3OD8J1siO~mgn=Tcf^=w?Be3+u!~hv zxwGA9;QY$t`GZ7Tl)74&Mpx7{-#p59k&O{l(^@VovqE<^r{&vAE|Rj-bKC{ zciOb(xpqy<=HK}$F{kZJI^MRqM>1`KdeUCV&|*IyVxX)PJ;z@eL{~mwj4YHL*;(0| zr=mZEsHObBx zNr>jkcQOpgQ;U-sdg``06%O6$hUKe8`YF?xR23s&=;?}^@7n2CKB*)Bv8iZC$9sTq zaPc_tZqq%CdARX(tZDdFTG5SK-vW4Azqd9=B${meLE8Gfx2(+dX1eQmeb2|s%PWFS z#NYtrYs}8}d9Zn}^Mm7EVTEITVY>F5g1yU*=|+_J@j|aiQuH4l(JR%+1`E1G3XtdP uZPc_7pRGRDY0i1P;Zmi}$T2GaG_LV=%?y$4JW;d;DJ#vzz4!}d-}?`~I4T_g literal 0 HcmV?d00001 diff --git a/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/stp.jpg b/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/stp.jpg new file mode 100644 index 0000000000000000000000000000000000000000..cab6077ed3a0644c1e190818b2de3a45a662dd23 GIT binary patch literal 5539 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 GBK;R3t(Um~ literal 0 HcmV?d00001 diff --git a/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/svg.jpg b/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/svg.jpg new file mode 100644 index 0000000000000000000000000000000000000000..8c771ca3c3e3c87d3eb8409538ccc6187ddd717c GIT binary patch literal 1979 zcmb7Ed010d7QgSkY%GEI0*Gvx5D=BNOcIcQm4OI?AdG-4Wvc`T$|^x%6qk|@6gTBQ}GN)XB1Fc$jnocHeg?z`tZzq8%nQ4Op9 z18^^QPj`SI03h%Iswv>I?Lb^C06spz8UR28NKPCe!5!2BW4Hi7tI?H{%xY|9AEs8S zmVn*Pl(e{{xJ*$DE9xN2%XgbcQe1Kz%htxxhG(&w1S1gD4VX9rFhpIZ6(LioBpL>F zCh!=>{bwCULQtqzDS$Qxl{kjO`jz~}U^;8X9DvQr4{T#aLx#g;wN>?TQd_yyZ+d~( zq;oV2Tz=4GpHX%CMC;__=9ct@za4(O)}#IK&F_n(^1JfKkxiP$038gvAiF$NKl_z) z!oH8*OzU);k@>vLHV=qzt$Kv8U1bd`{%BPXHBr* zSoX%l6GpSOMoia@hVT3Wj)gvT+(XVwHypA0Fu3jSBNoG~ri!L^w+X53Gbe-Ga|zQK zi-EI8ilSQ&9h)hy4Y5zgvvNyA`i@p~TU0arYbx$!G>fCO{VmNxUdb=K`!X^L;?+Hw1MG%z0^jPK$HfJlB=dzp$?1nS4$PKTwZfq+fYJ;x0J`2AP z#r+{U{Os%@i@}(q-f4Mm@$9%@rZdF+D*+G`!)RK6f`qr4OfVp1K z3ZwRk;&By#0rJ)TLr_f`iTW-?RNYX5LDn3Rhorg;C$+AmP*_r*c^6VX^Uz)7_aAcv;)*I|?w`BmI&rapy8n}+F; zp^?FLTe349Lwf^CdX)i~B*|pFVcEdL?s$g7w6ZeLlVVy^(B$>P;FsX_p|0Ed+P^op z@p<^EJT>|9iPOdDpV@_<|J?K6Jte8>o}q$kUO%XSD1>A1^K?n>?w(h>VcD(JWk)Fp zd4<{tAk4V}j-OC0e~zqq9&q;i?>x=7&)-3!hS^psW*<&>pB|qO zC5K9s`rbgdXR>fXPHd`~}tVwP*?UKj} zBR18Q?o)xKrS!>xMu)^fn{=aQR3<^my$E9OXKF48XfDy8r_egQ4jikEOh)MKM7^BNzO)QszL-nJP3BZvLf zLP;Gaeo1|lr{C{(@O)!LxlYuq%^B0%_nvVA7^NCdmbqey!+{IQfvosLV9$WS4`*?n z`$h`IlCG7O;R||i&r7|xvhSw(ZPRzr!_kTSc;%@=hm((b+J^0dQa6;Y8K&RgE7qLq z+rjChj}v3-hf<%g z8?8S31scpI-8s7*FW`HkPuh$k(0hJoSmI4719}19bt-y4`PDHLJw}+Dz2_8@u}99A q-P?KT$Db74$!(m0MXjF0?PqdN?AKGi%o@JMxpl>DuG@&L8u>4o$F|J? literal 0 HcmV?d00001 diff --git a/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/tar.jpg b/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/tar.jpg new file mode 100644 index 0000000000000000000000000000000000000000..665cd0364930df93b3fd32d88df6b235796d26ca GIT binary patch literal 1747 zcmb7EdpJ~S82`>Wb8{JHObDqNvM!++W|WnTT#7DhkSi}v@U`W&Y^yEtqO;f3<3=BAdWW~QtiRHx8L|L{<5FqM9c#WH7deYpP8L0|`9 z2!Rm@h7nk12o{kU4kL%h;&FI99!Df9lNIHa2?_)vk)lLVP*f*s5S8V%w3Ud;ibSHi z>?i1U*-ixnQBWrk3F`mbq^*EV0G=Qkfph>&h7d9&y@@6cEtxFEC4=w;EDnRlv{3aB zS@cr`RS1j2BM?D402C1jz$Ao(>enM2{dr;W8%QrBO_>g$;JUMN@#i{Ao6<&SzweAo zpK8>#e*7Xl$Gq^kgjTSiYnWT-8Arb$XIz$bxZNT)G|av`a?@nllgKw=<4R%qwezAs zqGM|Y=M!%@`MVEpW)zK=SX}NNltkAd_M`vCsonE>=PR1t?q4rigb|*<58(cgh1M{X zwJr%jFb)-KnKcH%0vLyszPUyX$+Pve~|{NuMO01@}uf_7ejG4 z=t)w<4o`XhA*_7EMT4G7y<~;@-V4QiHRDvDW(F;y>e=|H;ABZM&Uvp}s71gLwHOVP zPS&Pu>uO^uKv7LlR15~j%Pr>)P*4aWup0x;EPHsPbz_-ImOn6X>^X4JhspIZdf4KS)=%Tz~7Q`H}ZC|4j4N zpFcl5!Q9nZaja#R>#ifa)l=_o5K1f#hhHi+-pjuJ-3=Zbc+W#mH-bGlmYuQxLuZs5 zN|Y`u5`rOM@Sm8XuKon%lYhMtE{m$DR5umGTuczpOF%mKhQlm6+sZ zH!obd+r)ww)e}@=CahYOzmF&B&s$CFGI}V?Oup_VSX@84D(|HCZ%nP>N@RBw$=iXFZq>|-Tq933`O)U23JND(M#Ej;>ne!-x4h%nT+J0}qx*^A6UAv;;0mFE!#L$(44_iZ;KcXQRfcru) zKxU9=wp1xlnYFFC7BV3y4 cl~nYexN1^UKBZm$LwC;87hgqY#!37C1NakCm;e9( literal 0 HcmV?d00001 diff --git a/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/tiff.jpg b/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/tiff.jpg new file mode 100644 index 0000000000000000000000000000000000000000..afe2cde90e7aeed960ce94fc279d0e22919144ae GIT binary patch literal 1953 zcmb7EdpMN&9{;`XJGYo&h7l(^`;HAANi&1kRAypEg*A-m(1nr9=pwR+k|;GwE{9d& zK@B_7<}9{2rHsdAg>6N0iA-)?WVKE9Ji?rJEO!4rpZ9s6_xF3h&-eTNe6Olr)i9v$ z=I`PI2m%1Y9-vYH4lh<541k*(Fb4pT0CYhNaM%fxf;HF+09*vG{D~_1vYoDHIA(LrYtWqD`hy z^wmZ%b+x7@f@tcKC?x&=8>$9CBLP1Uhd{;vra=e|QZ)iYb&3#3ou_3G5j=qe!D``> z>@PwXherqyQPmH~2n1j%Ld6o;uiX^MSysoshHm>cy3>c!`SIDGzP4Vc6nr=M#K519 z0uB1i`GnZ&7h}SEeLg2DK5cu`82E7Px1*Af5&P{{+E<_*02I5&yHtLDM~Z&g>vuaO z!)De;X*H_b_kM_?D0^ivm-vStjGY-3KroH~;aBM45IlehM2N13T5o1hbyl+k{uomd z76yce7byAPwA%Aer2Xw@>kzxn{E@{YGbl>(!0lmQ^!1H*0;T0i`TE`trzq zH*{QPw})VH__Cl#bU3H!up3U)|2wnuFTuu0766Bn{j{O_l94uC;%ym$BnU(B25gC(Q{~9||we8P|M) z9(=3<5-cDF4L~>uhvjt{ScVar4$3fQ>oPez7DK^m7fs^`$qar4TDFw{!;m3_knM( z=6a31sn2_CEa3~&`)3ZdT$CxQ&Q)D)P%>stiiBRcr@L=lsf}Lq?+N>sy`Q2TXgx+{ zZDree?}oNCaixrme)ibbx# zlot*NpIdCcb$oS}X!!P)^QBVDHs)t`Lb&+CR%f)}={%!nDtWRdtaO0#LqhdAT&m!# z?3?KCb#A{>r~uQT)HPsbw*Ub%eX~kaQ+Lz4o%%(b`3%pELxvl4i z))m`Uclr2^n4D|2#?hp; zIioc)LdxEEEsc>i+U}xE9<(xlJ9c)hM3ls(R>=zG>J~8lV^FXawA=#_pfNlGrm0L8 zH=;AM7!~--m*>QRF=vq1`Abn*xtniTm-qGRXX~o-|Gr~q%9lphhHE6r6~ku)foSNJ za0ioLyIKo<9;H=3oT0~5S=ww>AbH8jZJA2l4fUR(Uk@1hJaRWZo!}+>lo2`QJrqzg zOXH*(-do#k=A?C;+s*KQ8+C7di#%TW@w=~XN@b#)G-t6vNBK}iR|m-;Mg>&hOx?j> zooqj60X}&9)9gWv;^NW)2o?vncm4vX9vKEe+qJ450NaiBoFx$!{1-HAh#+h+tN;t1 zi?RZ!3?|28F>3WlQI)&yv!??u<8upTT)Pdc3rW?sZI}}is(M$!_&@nVGzMT%xmdNBSfMxq|FbKVqR#(g zD&Yf3eGI zOa-HeBXUvDUdVcCI{Iw9TOm()HwpZ^b5EBzOAPo1#a_$qEe1;}N&@gbKh b9hK$e}}|o`bza literal 0 HcmV?d00001 diff --git a/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/txt.jpg b/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/txt.jpg new file mode 100644 index 0000000000000000000000000000000000000000..ec6d3e3f5f5b5ea808a90bb21ba75007d3802a95 GIT binary patch literal 1765 zcmb7EdpJ~S82`>W=HfEzj7yVC84N|ca+{J%lyNJ=P>B>vshN#RROmu-Yh82MbYX`? zs8FNwL=>XvGL(|gkdlYUsKsNt9|x&p7WjWy?pO^-{1FspZKNt4M5k~JJ|yW z0sz7uAQk`{yD-j90GLdm4*(znD4qkPuo-3rs@Mwv%!R*eBDl!+xwph9o&~0^`$9QE zoQQxORR3`5I+mS75N8jEYGSa;z}SH9Om*558nAzlUm(>mj7~Q(_4D@&5O)Dv07D3j zKroEJ5+FE40=$$o0Y|_S2n0NdBu|!;ktfO$NhHOe6lLWoBo&gpjM}1~Nb+(d5=9aO zTP|5Ciy*QTB8f=(-w@veWFqhe5eTFOU^0Y|A#npx$I3?_2_!Xs1%W7yL!=-)W>xx^ zdd@0-1>_J2z$k)Z)IAxSQ`6dvnf^-5$Qb?UW4~eso>>i#ak*ICe=x%RwrYT!+s}+Q z03hs&L+pf*{DKKA^xtQm_+k;zT`!i}DG zzlsUgSTZ`;52f&s6oSd$Aceyd0E{d!TnV9M1&XE(3(Jm(8eGmIJ>z!3=q+&niBj9~PTHA58?m9z}$Yxt;<@u~F8EN$8fH~+hR zHmu;|d2?*xtzpq~MSs?KK|@ISzysbMX&=)Nwdl>s>i6Gd^*b2d(h1|Yn$;&?DLUhp z$M*8v5zygnUK8UuQdE7A-($fZrKl{t?D>3n=nGjZ^k#7t(#^~hhQ?G0O9o)$b9-<9ET?xD{X+OE$ZZ+!BsDD8Ycti>2;Ihd?Bbaa<)XUb{b z!;XHTDs6?pIU{}dqnk$kw`wb@WLs-m*@oMd9IJM|vv(`?oa|Y)fPPq#d&GL4(h}da z>%om@77dy3S~+Qh+2wEFo;69(9$J02G1=#FnV(|Y^*)A4Vu-cX_+RXf&mxD3lN)1V z-_u(6bq9NRg%1n(%ks{i;})%mUuVB}b3CF!TJq$WwxD2YwBZ+>&1jaME@Rh<-tvgF z%ulsC!s^-HrVnC(ZKp1ZbtsITvG1J>k%610q0yQ#)bBVo@9rmTcji0UT2oXqptO)% zuaM3xpEx-3Qo8*bU)i*SmD995<+klwy)Iw7vixUH)skLlAGs4T;<&|c&mGSz~t+C@%A3y8MOuUXAGQO(0GNoFg5VvC*OLTzw6@8X<-?`t zD^+XUokpK>^-dJY(=~7Dfm(xzqA(4x!7kY! zp9b{5PQzCR3BNGFNdbZ+xC9Vc6QG7hZZ>QD#;B~|yb8YHJHO~uNqox8(WOqqN8nhQ z2(DKhHMJ1G;YRjxl;WX;pb5SznVWvkjt#U8wBEqtTsL=n8O^{Mbvw_BE^{mYSlX9x zF1)E$aEU%dQFc&`*VG&Fs*iW|++anvke=!99ebv#;y%uxT0}7(ExeT5G;s7R>sg0;Tf8-%H+AQ{bIqHKT*OJTGTVly_in$NlplnuaV~1Dof7W5*X6#M Rx=kP#X|PH7&OB1w`8S?lY>xl{ literal 0 HcmV?d00001 diff --git a/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/vwx.jpg b/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/vwx.jpg new file mode 100644 index 0000000000000000000000000000000000000000..c56cad7ec6b5fc5ef19911d191292e0b99afe5ec GIT binary patch literal 5463 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 literal 0 HcmV?d00001 diff --git a/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/xls.jpg b/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/xls.jpg new file mode 100644 index 0000000000000000000000000000000000000000..4f656f73dc2dc53e6ee67b95bf8ef0b08365f3da GIT binary patch literal 2691 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 literal 0 HcmV?d00001 diff --git a/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/zip.jpg b/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico/zip.jpg new file mode 100644 index 0000000000000000000000000000000000000000..36d159166e47d37b44fd4ed6dd800c2eca16f903 GIT binary patch literal 1718 zcmb7EdpuNG96$Hod3lWH65}z}jFeQXnPG}z8A+&Nrc$J0@-Bvv3aQ3!QlgDYeaPlf z5?fw9cGvcx6urIrc&iqxQh9$$W%gV)yZh&U&*z@cx#xGz{eFM1t87+22Mkvy7bk!q z03dJxP$MFPF2;Ip+TRaPNy@8kHG81 zO*ITtW76m}=KqGW3g9&04Pr6G7@#$i3;`$uW558`CqAma(JCAD43`Eeao)5>W%2iS>b!Ts@wZteVlM_ zj9DQZ(mQ{0q!;_M=QIAto^Q))oAvrg=}w*RqGi3S7w)MYP0qZs-7tvNJowO>UpcG< zK3Bb#VzwZyrmf=%y}8!ui(1AQO9>)+vYuI=?U7`*+eFOY@xZG5}fwnuTW zifL1vjuu=hd1WMm8ccBj=@3L^S_6z3Mj}%fI7gGs$2CthC5H1u4O)>=Lu*J`(^dwAg9 zn`=-a7iNhlDeAOD*ermAGc>h0v$#A6Wy=^F^^kKQUFZ??j$B zD?9haWcHZz!f*6r2jZ*!Gq0E5+hEHtlVi@oy+=1UAF8$s7U}+GDPeo$uVk)uF|er` z75vaJ-$?s?a9fkk?FEA2aWB*RKKhlfPW)(A9E9yn$=of9EBa98e*6Y;aH%zRm>a%W z9%ptUE$-aU%jCC0&2{`Qrwnh-|7G8ZL>(IQ|R9vS7&@~R> z8Wq4c`3eN*00x&Qkq(G`D|5cqo*idIoa^j-RCmShF|=6IIr>Ns&$uY(f;AG3-PH~3 z?@R1sFPjiK(0^AA zVBkECu$0Y}#t%s3sX29%;)$ANbSo0b5J83aTTpR!V#TPR&&iz?O?zHqhZ`Q>G;r+< z-SFNcBiF@YJVFufR?}_omZi4o&F!6#$YiQLNQAg4AOL4@ctVMk&6TGP1dt?EX*!=IdZXNJaxP1_c3b6))-Gab04 zf|IJEwrG3Lz$$Knd7`Tkq@2Y7@E=e4Pf`G6WN_^zQn?s%PN#)2AY)lYj8+|@B*}P literal 0 HcmV?d00001 diff --git a/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/ac3.jpg b/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/ac3.jpg new file mode 100644 index 0000000000000000000000000000000000000000..0530f2800a2882ca5aebdb09e9bbda8031849ff4 GIT binary patch literal 3462 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 literal 0 HcmV?d00001 diff --git a/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/accdb.jpg b/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/accdb.jpg new file mode 100644 index 0000000000000000000000000000000000000000..13607b106309e9ef258633eb883fe7ce779fa780 GIT binary patch literal 4130 zcmb7G30PCd7Cygo;Vgu0 z<(bKGpZ8NwYBB9N>x@&|)>VwNw$wg{U_(gXVKV?m0g z;iOz`CsX1RiZHT+$rp=)1PB`y#XeJ1ON6{bTW%1gT$OKR+u~re2H4H@r-qE+l+}9sr zWCwpqBuA2YLzp%$UNno$tsTNMVGczE1f)P5>cx-@y}$t>_=7ikrh*)45l6x;yk;ST8MiihCtxHIko9NYu< z#Ao8Okkkct)p#Hn;wJ|Zp&NPHXD1EP(afYDbHID6VY;iO5T&SgQ^zvY*9pZ17$1NCjR+k@k2 zw`jM~rwzPN1!QWEl8{$YbtM!U9(Py_wTP(%5$f+EUJCMcz|&zBO-SBqIH(~rL97pb z6AC%DgHqnFyr;Yyyb@j+@A0rX1}zTD61ELHhW(5k$9}>t0S7yc)nYYR19k*Ep|Sbt z+V@$})LtDgDI=pLt1vL%&|DKBV|lZTSmvx*tO+bjR)~hhVHvROSph67q%qReO*W_> z7K;?3QLYBE`sumI9Uz5BQzUsRdV!F(I>!rLWdtWMS!`#^5y@m6wMxN}6AD7Ul!&(j@*X6| z0lX5b?>EZWtAjG-YykHjbY?XT%3{(1$`t?xj)O95bS94Z8lc)qoGxG5XAfPxmjM(B z4t({0ik3Gzn>tjgSLnQA6ae(*t5hFKRjS_o$o_4B(=ydv$o5?(O#qlZn>_V_2{eix zI;hcQK>9{81ezKH1W}AMSV*z%=THIGO9AiakY_&G$g>uW?tfB?sTxLRF{Z)uNUG{D za12XTN|U6SL_8<%b54-J*FQ;`Eaf=Zx!CdTriGwfDhYYANXFqU<2#At;>CQi>K6C_ zm24Q<(P&hRLB|;w#$eEBIGxF0vzZJgbL1$N)=2&FqnJ#C2?pbhbWBW4MryImIXZeQ z6B8ZM2!%$YF))TUj%(}aGxc@;@208)HWTJSCPpy>Dw~3_DXOzzM7{%IPV>UQJ2__;kVTh{SM*p3yhN$Ayk-`>J7%}{~C(=)$z?OWF+ZaSmLvN%Jr%()&gqJ>OUBQ3iX$=Kukb4%oK*6c#ORfTS zqfs!N4pbh4J!YET*wLN>o~zF z2io|O0&(@BeUB~Yd;9GCDr~9W?pN~%ksUCUwAl0iybOP<;M@Kph~sp_EZ^45Mj}=r=_{*~4jU zy@~evW}orA(n>1nx}(i4_(G9fu{!_mSVvDmocL&M^Nape(mkjj@65$FZ<)*u6)l?a zX70}7i`{S~a!cifq!w{Q<&Qc&)+!LVneJ$EOU+rC7U;_lC^wg8IZh6>S~!Hzhrjlhhr92*)`??-BF9qT&>QUx9FRXX8YUqPTuQ1a{Wj&d!p-#2W1Oy z8osXQ1#+DioKseBEl!eD?W8A3zurmY?{fJ ztXpZ^EBJPv&7R zQNQEH;jW~o}7i70J#{?X^0Wt;>&wI z@|iI+G#awV+t?!LQu>UfS19@AqAo`MP>g;$O#5sAZR1MRGaWgn(OdesMd(`j=WVU~ zZ`)c;n52t}NTm%q34wyD$n*M4l%|_s@|?5U^JufCh`Jy1TE9TwqcQp6h8Lz*MjW#( zIqAGUy*+OJqJ>)UredTi-agT7v1|A3=Zp+6(=&`|`~6Vku8LFf^R8&`EY0QW_~BvR z0qZ7B=;^soSfBHkb8}tv<=qFuRupjbtBK1l-er7B? t9y_i!*gp46^@7H{=z(O30}QV|tgaK+k6#kDHw+ynyj^J~91fw_Oq`RB}k&MX(So!VP~ z5fd352@nJUT=)Un9%^HBc=%$zfEO7Z$AJz2sNV>cN*M_UAWN=M38KRAdGi=S{cgc#{t*~F7X`QUUUE$34nIb_xne)|Mtx|O{^9HfY6{_k){@9L7WQ! zSte4dGyqWULVMscjS^z2J;W9&C=g;6fz$Okg21VIJWt1&EeMAkLMvUAAxwjK1;iey zBkbuTuwDaXz&KH2xmYC?;Y2O?DuqNU6YCuM?qA#^nEwQ`WH~TrU2}xJi8^yuEPT2V zxo4=jfeR;|hr5ZYjTtWBum zL_rMWU{A&JM51mGldaQ)5kzghAf5r{AVMGp3XlqW5s-s-00#mP1;XG{2~^M{0a74? z7BTdSp+$;(05YNN{XD*oqaQQONY{;iNQ{QFyq}|=p?8p@z^pJ9<^zAHVR6`WED#F< zI2MAju^Ctdv<6|*3<~%obmAZ#^g^ZjIN2Zv&P?c-1H#H|bKDGL@YSltQqhIdKB#6m zOU1As#xZ0JH7iC|0H|RFhO+YpT#eaUyp56PEdf0f)d zJf3`=+yy^ZK`2}SnNCp_R3+7|gxbLK9F;>0WNLsA_O~HV0ksY(9krqod7167hp2>j zUBZh5u-aqT%DTe(jdhu|lU2?7b<`Zg5l2-CEk_&Bqv#Ll5%e6u(Pp#-J&v}b`_Uf_ zG2g%T`Y49A*X2vth-`^f7@BWnt;Ik_52M@BUFZ??arE)@I0Fl(ThYDgT>3=lu`{fj zY}h|47b%zzYc*8W_s>O~04Yd>N~B;Jp*i3-a>9*jEjoD3?(95HV!`fs~7kl4#Z zDkvOE1SJ&U6n9Dx#hVgC;GvU8nFxJBu;&=m>rak>F)9P`2o|i0A&#eR*AaV_7`+tg zmO_QU&%x)FeP8?@Rtm0In)Dj2^DfM%KYHdw{Ul}Z4Jk0)+@ zKm%mN3|`dmWk6^{Yynw^0f<5D3|N4;4RS~Ttdjz4kVD-0L?iB6IC}6&+Ceff@^_#H zoJ3Hy1HhN3)JU_W`QkJ@H4l&BbE2}Oaw+cP734L=%P$VrQX^K$g)*F#>+kO!5SZrY zqrDEo0f}fR(UHj{luE&zyYRDLg61s zL>2T6A(5#x3N{9XZi^B2LAUlAFhSuU2Fif7yI5VeVGKk6L;f}e&{j7Cqk<)!XqF;L z6IAC~Qi;6By(KKFHg?6zn!yFrFr%d?j^&5+-F+xtZQ87ru3Ot0@mw)!>xjb-hs zX|dw|;|X7E7ry(P+I(L*vHro$g?DwsK<&CKPyD`nGlN}*@K-`@E)1fu2u30{fv#a> zlmbWy)sp3F;mu_8p;Q`703nkGj^FqwZ&Hr4EW4zA?6s6<`E9SJwqdtR1kLjg%zB)i z?Q33gc-?Nt4QraQ4{LtDsVKegB4M2mUY=zv;^*cIdvoxCsO0VO`(BtxvlYy*9zRH? zOLp(=dv@Z|4`oRKOQU6K?swhuC>`xyyI;!cZ`Ew|PrTi`u5#==P%+Oe>}`a*Ki6*V z*#U*JrU+Lp7ca8)+#EBHa$u*AUwQni))L0s8%c9Tt@LxkJw<=ChJ~U}{f?dSVg`SD z_D?M!mVr6EJo;4ixxs}CLBjumKpG+hG5~^-Pz*Dn4u(SDH^3yDIZ@16GrdFAEsU|w zEI!y{&p*t*v>6<4^3G_!r9lACf+2G;G@4GjQa5&!wmz1&N$5P4?1DuidJ@ojQHL za?kzf#EJ}w`<`p78`77wp0&~Rr53#0QdI;zz9K)geo`~J+dTi2>z&74^_%0G21@BG zJfa$Yx9D=sk6uE$aiM#keU$08kKAN$ProyzxY#6ZKGDhSjVA-9c)J1icF4tZfl~T}Yr&AHh5qVvC_snejbkpv@n`K+T*^d+Hs;Q3L#8i`z zPa~AR4OKq1uM=}SU0o-=8Gkf$$vs}~-lp2|)48_KmGzES8fO=0(Hr+FBo|L;O4qm> z*NJ~|3-rU=bF()$#V$K==FsNC!;>XdH9Jr3$=$Xy=GEn%$2BR(FFCUpZ>B(n`Ue({Fx><^J9ukN^TxszcqNxjyDH5^Q|ij@BX%Bp#7=iv$~Dn%U6B_ z_rwHvJ`fZ|F~j*ln83+9lvS{Erf>rzyZ$!L?;AQIAx`fa>$HFq$>0`{nLBMu$dhc? zZTtoHrpv7UTf~lf*3Vr}eO_4Qygp;AZN-d+TUI`^KD;xP*YrvB^QVq&{VgA6b>3@P z%Qr4aDfo@m>Plx+Tv>DKb)tQ*dZUM>*IoC#2UZzkQM^QyvLZl2HgK0lu{iSC{#YjU>S@xMw+#l{{gN!?e^T|90)|4VAOQ{CD> zFSJQg238K;b-H&5yzXG5!GBhWCmF0>1^+oSX@=O;t%rC7!|or>B5_z5|8`h)1UKSl zL*VhGj95A+AbV(55w9q{^Yh;yI?8B%+;(&-|o*E(nBbhx<7AQ z-|uKqe=$jR==7AYYI(FG5j$<_o_i~oJX(3wcgruI?%3ZkCi0VyB=17AEJf`~!8SjK zXO;VGvm@e?>n!$8F#dXLP*kDS;(A3v)5}R$?Oqurww7NH=o(u(dCS-kFwh)Xe5xdd z%5hT)R>%S}PbPEY=kJ=n-B~o*ZlOg`*qT#ktimhq@hn`;7WmD1?7&{Wyt>ON`0$ez z?%{Vhjss_GeXRxk*wUr0rSVffK50IM7rcCx`P%-n%Rg2hK67PG%f{TOs$zPsOU1(F zwAF79E_hDzK~5+suASTOIaO`4F3(IU{*RUaFRxS0zD<}jyR4|t`(#o;p67`>yEl^- m=S=9rC&$jc@x^je>lpJR%QncS#o8Wt6#HmV9Q&9;d-X4{{9~~I literal 0 HcmV?d00001 diff --git a/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/adp.jpg b/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/adp.jpg new file mode 100644 index 0000000000000000000000000000000000000000..92d67d93e94f02deda3cce2f8c27016af09a6799 GIT binary patch literal 4126 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 literal 0 HcmV?d00001 diff --git a/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/ai.jpg b/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/ai.jpg new file mode 100644 index 0000000000000000000000000000000000000000..b7c353b410632b2c9226647d236ad3b8ef887e40 GIT binary patch literal 3416 zcmb7G3s6&M7Ctxk<{^X_5Jkbq6P%_7_1X2++U)t0kbvXp?4QYhznt^^ z=l{<6A2;qx?jDe9Gc*}MQ54L@54is=Zq=w%@91)KGBjCgbO4B3^me;NzyefQoqTR) z8e6!qh!uB(07gJCL_)CM;IJ!ox-7s(xa2voJ^ThR62RA!U+f>qe(qPWk#iUTC<)qa zMu(vSaW#O@VzBd00MRY9CsjG^h{Yojhw~^9v4Y?-FHR@8#ET0(ocvrBa)?%$!K61L zUXD1fq@TU4ANFcM2FA(ctQ>DPu%s3`-d1Y1a2|)Zdxg6n^JTEY;=-IgZ8Y{$M|s{n ze8!U8P5j(kA8s<})p>|tL;G2~GmY5CBmR%8yg-R~B7h*Ql+P&e@&ze1ru?@M4@0}r z?9}A@>^0Vs>>R{6R?u8-n@8dh&RK&)g|&oe#MexmhO9B_p~1+ds}aW`9&K{X^~I;P zj>0|z!J!QKE?cm^!wLMEi)(+)g(O2G^kv~cL<&|;=S zpd4*4=IJ~f@0b9i%rm-|jK*1B%<<0fosVNt6wIUKi#0j z6|i^|RiG-fXC)kd-sAx}oIs`%^w{4(o(;A3DIKt)rPeKx0S~DJw=Vl(Hmr#YSQQr) zKPtKu+Z8(%KMa^75OF}2==bTv^v84?eT+T_EZsq$pg*Bc)BEVZ`(wU%?Y&X_YwyXI z*hscy75e7uUuzC5vNTzgY@94zHb(ZkEX&VgWf8Ij*<4u+dZPU6W(oKQ`{H>5Ydk-Y)u71c&XVzM#GV02#r6$nV9Nhic7En;YFVxf=`NyMQN ziC7{D3YJNOhJ*x5BvQFFL^c>(kTf)G%-}GBNf1gP6ym55h6x!QBncvn|F5}ELZ}25 zK@CksgCLZmLn-$uh$8=iXitqulB7`rk(g$L=nN$*ZZ+O3-K$Lre;7IF-I&v~iCQLEKJLzcj~`M#*tDvC z^n}KVRYwk7ZZ16f^m@^eqZ77W%-S&R;K|lJKI`OD8_7EK`K)!G32BO&L#bXu5cCnI z%7LPB!Gj0&MWO_BC=&+4u|pK{@aTjo$~67b+55A8EKk?O#yS|J>a|BNo{#kQ4 zsLSZ0)_!l^mbd$O*Y!yI_`^dTe<~bQz9jkEx04^WZL&U64>~-%sPXjFi81rLC~frb zo~Z8B%^W#n>+kniTW*~_x-06ktLQ++yL(G^gUULp zImHbJ*RT4`;`{XtuTyXB>(GB*6tO1K%ud=O-81C0@^*L3h?SOan%T#b7W{grb4<>@ z>YL{h|2XW>l}Xz~qgHfITFPmA9%{GF``}*0h}QC??A%2;5jo|H+P>{^1J-CfE+IuT z0uc8tAr(3n5^5F71$y~*UGdWT{U^TaTgN$LpG3PhS}wJ{ccHg*BR^3+mSJZE&mI}G z>{jil&H2GO2|aVRhTpDii(0XEg1lqHrr5_0+0E@&KF)Dfv}?-Sw*Oet*C6e9B)9<1VgVFsQhG|LR@$c6~bi z)cFs8`J#GjY7_h3vBo%=>2i7F;#0=Q4GkN9a4G)s=^qYRRwjr4vm>JC=adaS@26Ir z-F+!YrWt?p?u|k>II^$r2(fIOwzCm>JIiKoo>0=1sz_+sTvt#vde`7dDs|Ah40`9G L{Np2x?(Y8q`&$$H literal 0 HcmV?d00001 diff --git a/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/aiff.jpg b/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/aiff.jpg new file mode 100644 index 0000000000000000000000000000000000000000..f0422da52b1777393733719c441478a6a9209db7 GIT binary patch literal 3454 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 literal 0 HcmV?d00001 diff --git a/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/bmp.jpg b/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/bmp.jpg new file mode 100644 index 0000000000000000000000000000000000000000..f479380fb0db7d03a6580c674582f7f2fa9acc84 GIT binary patch literal 3754 zcmb7G3s_WT8vf3lb7m$kb3p`UL=T9~{v3fgYcF_8<7qJKz8Q-~aya ze>vm$%yAhc8L8>1KoA6^;RhU71c%a-lb5RVRH^A%3Tyxn?A4gfdL9E{Fxo76$|R;} zaWNz41s+TWPY3`{jn-;TRI9T93&-W2 z_zdIbUTI0o8^MiQjbb6<5R7-4ZAn~wCgQK{RRxKNX94hh$}On{!+hSub(Q&x5c^@g zOlM2aABoo)OLJ6+u`h3Tl_`_U!*M#b)@1Y&f)QV=WYf7dMm;2yu_+3~vk_0Nw5N^a zCo`-y3%R&6PhDkl4r0thT9#=t)QAHRueX@;xUo<(xtrB1xv?-m*LQFMtu%9 z7S5Lvu~z3CF()}-tIWrJ%JrpUZI=9zzEp9!E;W6Gzsjt4?nTr_?XlSNIBl4p>e5&g zO2n9ly2Tm`INuP{lgczHoVO8(AAv$b11y-J6l*OQ;Vv+c2TDl7rx`5RQVu%MV}!+4 z79%>s8>%pNf1cXO8Sdj|R5*JNaJ_Mq`*VgzxIV%$QT~*iipKx>R2CIa&7d>!@@%Pc_(aWKKsRBy9??hq?MNYb{H4+K)HhL^bYNn%wP} z$2DWrY#QqTSkZye*@chw>4Q~AC%IafZtBpZpLl(+3RJ)6FWpZM(A`+~(ihzQ=|1`b zetIDhS3vJnWI$Cq=So;zyzp^zXh)_EG+2LuJQHdiRXT1(%Z-}?+%23F>@zt( zqgSJ@-hV9a1n8gumFQqOaxLg8=dclKG3(fKGNP24N<~uXzuL9)xV=28g0JAG@DqXI z&*I1NBl#H|9zA*dP;86CTH#VZd~#fjaWi1Yu+SA(o^a=`7v8&9o|=h%>Z{B9F9A?9ge$AnEwL6alPXUSgly0D+kEV=5Bou0!{efMU5{5P8$&b zv=akl5Hc6eBf>^FJb-6(K#g#?JD)4uU5mX(p1ek$i&57|y6_T?>bM6nDzi;z(ABYJ zOld8Xp;jmjI-`z>j);qhig+jsy|l3wqejojS43)}*oPwL#X0&Q8F*YFxr(NFq<~Ke zNKzo6X^JltNTou7Q0U<)^75GA?I{#`P4oAbi30-zJ-nno)5Ja^aiEw>LeMlVAO+qO zhZ}t}8Xka?8&h^Yc08H%&a_hP4p{s#CYAUml&Czi5Zw`Ev?G%H6(O zL!B#E+?g@}WMD$%!&!G#nHhf9x}zeB{?k%$Hg-oE{&0bgL#wZ1I(Y^Dot}W1fqaUHhr|BkhYD z{9d=0?tWkPhpqKRp`D)$eYtqsrMYJ!mS3K@Wmfn5>XlE&-+A}-!invM#)6iL_Y;WZ-yrZt3G*aC z;2siq(A-|<3W26XQnb{^5+sk!-Mre z*B(3g;khE!hi&&JzBbDNky8g+BKMzVgPrRJH&21?MiUWfbA01REhYWA-F&H;a zIv4wn@_C(XNmEBm{p)A12Bh{33_UCR^vLaIn_WQnJgd6WSGw)H)SjMZiG5=)w`QTZ z_Xv{5Cq@kiLJC2VxrrJHBVW_dUacwRXu$@D;xYOf%;;b`)eOP?L|w#EAOeEZ(joSoTW;(^w{ z?<1a5nW`JJp6^uTp8Lz9)qn30{&@78!o>rk4YGxhd#mtpcC2{Q(A6{lJiq_IB;Tq- z3m^a2-pVJQL-EcN?Yt-PP`eAy(}~wkVel4yfk{4&w=RR#Z){a=FH3%JFFOh7EE-Ew z?o&;G6rGhPYS!G8FxBk~N*Z>(>2g-`v+stm%=(}O4IYw{UIkO%p7+bN&oAHWVx(au zr8(=TzM%J%0@HcwXx!|*zMkzj3%ddieJ1(3{Z6rBk4o*=06k5mD-BP*t&@=-9_!zi z@xo1U$K|*DTkS=J_~lEXf4*UWq4iU;!~xf4bS+qW=#;#*_pSG;jCS7qn zN*&zKK3O(7yJFM7L%h$QnV8vMFrhI-)}JuB-0!71GsE}YI?~^68Bizs&}V7$t6|L( s93WA~MXQ$!D&}N$h9zznl*EKBIp+Cd1JAd-bB$CxC3kX^sov51KS1K1&;S4c literal 0 HcmV?d00001 diff --git a/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/css.jpg b/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/css.jpg new file mode 100644 index 0000000000000000000000000000000000000000..8c80e1571791a5144ae7af5c824fe8e3b7bb5153 GIT binary patch literal 3444 zcmb7G3sh5A7CkTTB}51zLDY&Co+y<%h~XnbQISu8AYu&Q54DEm0g;fzmjs2TVWn{dq*38aQM9Yh1P~f^7TyLR`UdSuD{L0TexnhG@F)tCce%fM7C-yfGKd@I6r6HaGAP6qyvx;1N!PJ`a!g+{? zqg`*XsS4fp8dFLBY{WQL&{$!fN#YRBX`M9#YY7pEd&)T#S!2{ggPzM&B92BJR&LL6 z$ES0xRRzTEj8jvdk&hVT(EKuOt{QPD;Jx{)(xlUx{|K4r0~-5TgVlQEy< z!uc{%&gz^a#-#gf<%PIU$yg@Q#uvKBG7C!$St>Wb)?#$-MbySL@pcW-hVhy6T3(rr z7~?PxIa3j-8)D&WdTl1DZ4Bb+FqhH-2WBY2UI!+44lHOO8`AM<0UkZ2U;rapIP`L8 zF;Ia}fwmX()J~3TjF(a79NkAoW0n_lTp8}VIc8=AqhR9ko5JKV)0iYC8CWKjnZZnF zGSQmMq<9pleRQ%=26s`ZE6#GTV`idbE~M9o+M_&U*gF1ggYMjKzDG6QS(?3mjN_Rx zYBu{;0IXPnf!R&;ty5?1vDZ8v_A=A9=%S>v7G}SyzQS*WeZtGwcL{HJ#|y6uZ{Vj3 z(r^WgPDPcd%HUiHtA{sn&>T)6(*|1XZzIo)S_hO4TG3KdeW=$%D#5ME@6U(2Xs=aq zRq?IjvZ6uJq_{sQhd1J&D$!f$Pw960DE%k;46t+ueS$ttpP~=YpLt@wct^)&2hGI*3$RuL zRefL*PG*E44MJw!@{a~;!JezIN;|C-|@$i+|$ zH8d3g0y#y?DaYq{Vc~xu0V$)W`3Xc6BSc>a`Fk|DIl4hY;{X{g!@_M{ zp$HVit?pJ?JsXxy*Fv;2cy)t!F;8>{Qr zZ%9<=5*MZq@k=;s-4;0M%1*9+mlf7rsrrzFrqC~9Cc_P1fKkLGV+Tw(g zcaP-!HpKzqfs*mRpboe1T-M$Hm&d!<&RKb3ms3Nl^vWE5BfG%jlYJ-6xcHi>7DH*yMk;R z*{imVlMo>zFC2wc8`yw8RU<|7)J*o{$dI_U_`g5xpaOb~BX54#eBnkwUBDJWL&?=+ z?<+nY-t%~IQPPwp$^IWFeibLHmd{8mfcE4)f4kN(NxtyxHBr-|iL1L~U%&f($L>G; z`=7Ajlj4G>?>xSvi>6yA)%Z2tT^qUlZ0Zxc_3_BI4J8s@+btX-YO0i)9>f=qC=)?z zp*i5$3e_#^>9PCwt$~zXQT7Fj%=?jT(SL5P5Z}Ie>r~{7C~D6S;~xHNXh`z79pR3y F{{feV5BLB8 literal 0 HcmV?d00001 diff --git a/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/csv.jpg b/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/csv.jpg new file mode 100644 index 0000000000000000000000000000000000000000..b81a32b0fd8e7127b883b7a59e63532e41f6720b GIT binary patch literal 4189 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 literal 0 HcmV?d00001 diff --git a/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/default.jpg b/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/default.jpg new file mode 100644 index 0000000000000000000000000000000000000000..433adcfbaa07a89b1a9decbccabd571d48dd70d6 GIT binary patch literal 3783 zcmb7G3s_S}7Ctxk<^h2aC`_m(+&QiIJrDcku)tjExw%@76d+q?)F;J6NN1)h zrTk040S^#@1cWNJAvav1hzD$hOP>AP3GnK?4oD*t;9CHbth_7a`ab%BC4-FY?WEA2th=*k5#aiRj zQw$4d5W6`}L6$rbF~*_wZ>gpz5K9ohqt8hqbD?Isg4M>5xiCI`JlCkOYM^iHw25Rc zTrVSH4dyjsO!~GlD;duz8OuyG>XWTw8D*v>I?l>3%+;FDB5GrH>hqF_HjK}lRq3N* z5MvzXcUG4|@`jk}o}r2)xgCo*1YW09z(NkBW3L7sbb}OB3m^|?COTe+h;@=YZ`&B@a($Xc-MY35)%311r`L~h zY%501Iejw#2FyUu>U{d<>FdJ7?lzCKojEl7oWs|JFzxU1%e~3H&27j261SswJogH> z1OF~TIPQSftSB2*Y0NueuCfL%%$BD3f zOs`dTL3U5pF54m7DZATmj^2p@csTZ_6`BfA*i z9RTv2+Z$GsXgW50Y^J50cF9 zH)>#Oug#bMF!@)kS!a7~$~=HQ1^~C$dTriV69;SqI5bh6r(bA^hcDh107ItVc=LD4 zAp&dDRg>uf)+_!7fbR7s)3XYbsk;*6cK|eMP1m6)YOy90AR&QNeGmYba=}84F9V{D zk^t9?0j5xcY&ePXwsJTCr5a$Y98&X1BefPsTc4cm92=uxJ8i?W2-S223C{+GX_)=Y%G3-0;8Pc^I17J1W}SS_*4AQuCHhnija(1j=8wYSAHS_&`~|)Zgv0 zVb_+xKlC2u1NNOf--wZF>Y{3PRz0l>D_m~xF)L_D0FsrG!{aV57e1O6Pz10P^$ZsS zMKdH7=ruPUaQQUj=FgE);+F=7g)2~>098|5&hr|@(Py32!G1HlTGU4;taWJb{P2ol zQ?h(l@ORgLY&{iM`1z(av-3x(^BzS`$}M&e>^LfkIVFiX5s+P6aCPSQZ%-F}G}L3w z{nH^^T=rHU`y}wAlHUt{#gj55?8}v7bpQUOG%@WT?@bCy zEfMl#>4ifzv|>!mVIvN@&mUt!W|q2V7@gmzRcm$|f3&>-T-@I^J)>^bH?;*mi>_ z4qqT07N$_`Y_evH7s~1W?(R2Lx;Yi{*=08!l#f;K{gD6pVYUC&>~Zcb|JgG2xZm5i z+I}lZ4bj!S5$7l>Ul#6AuDrbMrXo@C%3)*i{g~Lqhv{XGkKLEKKS z^~%o3gWoOtIit#+np>h3objKNzP8$L^@Xy^JEfiL;|DBBIX$auYm;kTm8Qk%rs{c# zPvgm|e}3vT_{^=Q}o} z_hXVwph-&(7{0m8Z*((f?=ANW$@{)7ed>CU996#_loE2 z-|$6vTXcOw#QCbhNBpgG-^_Gn?nKUx|uZKh?I*zSpcjT}(BuDLvp@DSmHk znAf7)ryrf^7*Q`CJYmc?@wLv-Ltxy)ai8Jg0pc zR~lA?CEOu`^kNS7q|(A)oOp62#D8}s%!J`$QUoxmwn{-c4+YxZ`H|2p6zb@YicF?M(SNM-wu&F;RQseT)dU1>Pbuvy6|&kkBOa_pYXblHs6 zqecz%b4vX6@`J;}uHA4M!S(DsTQulF3H7e<-nS7Uqm|OnnPVP{7GCiASJAy|GQ%L= zyYFvo94@X~{Cm*+Lm!t%Wji_A`PSy#5U-r*yTV`YHuBXY+TE8M?EPf!t0Zx4-B0ai U)s)3AZ5UPi%|T&En(5O20Ih7m)c^nh literal 0 HcmV?d00001 diff --git a/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/dmg.jpg b/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/dmg.jpg new file mode 100644 index 0000000000000000000000000000000000000000..509039ef7c0c6ed1a1c0fa5a661330d0eef53204 GIT binary patch literal 3619 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 literal 0 HcmV?d00001 diff --git a/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/docx.jpg b/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/docx.jpg new file mode 100644 index 0000000000000000000000000000000000000000..9b0bc4b3940e66cdc5ebce60cbc4008af13c41c6 GIT binary patch literal 4075 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 S&G)qb@Qz#3g}fEI*8c$n9ZWy~ literal 0 HcmV?d00001 diff --git a/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/favicon.ico b/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..73837074b18ff48735fcf5a33cc8c6a09498853c GIT binary patch literal 1150 zcmbu-O(;ZB6u|NO=J|@vNGT~7>yF5rQH494Viy&5I&Gh8V}RNt4k7#Ky=XkK>*W2- zO72CiAJ>p`7qO02Ea1U$oT%-W-*A8$w4oi%*u;)^PtB=^>5tj|M&_4z#U9qM4cW8L z)8jBtJa=M*{xi?KoBRnCcF$b$Ki`|I)f!Rz^<8&TyGM!b*K;zdWh2W*egE?*&X@1c zulJiSvMxlwe5-m+5BW1%QG^PVB`LS{eBuT!p!eTE{(=Ww;Rf>Vyrd@NS$|>+dVUUh R2Z9KsF=E#Y5-ahq@dHtmFyR0I literal 0 HcmV?d00001 diff --git a/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/fla.jpg b/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/fla.jpg new file mode 100644 index 0000000000000000000000000000000000000000..e8757e637d54d25ea9463e59e533792973abb335 GIT binary patch literal 3608 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 literal 0 HcmV?d00001 diff --git a/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/flv.jpg b/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/flv.jpg new file mode 100644 index 0000000000000000000000000000000000000000..c53f1357d26860de8075242a2f0abe6e14754d10 GIT binary patch literal 3572 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 Uj$G~U_K%LB)Y~C%Y_zrfADhWeZ2$lO literal 0 HcmV?d00001 diff --git a/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/folder.png b/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/folder.png new file mode 100644 index 0000000000000000000000000000000000000000..a5fac96d05b3ba566375d81fa94f660acf7bcb5a GIT binary patch literal 535 zcmeAS@N?(olHy`uVBq!ia0vp^RX`lg!3-q3%M)FJ)an4A5D*On4h{~+#>RSjdfM9B z*4EbM=H@`Ifq{Xpt}al-$jC@vU*E*U1jsNnGz5wR0gw&h0!4rTs2)Nhi^CPb1>p>^ zCPPdGKykPrL=9BL$gt+g^AkX~T9gF&1v4;maB=hS^6?7@3TbK^8k<;I2Zm?l=H(Zc zl$KT0O`W!M?fQ*-_w7G&?D(nEXV0C#`RMVhcRzmqS~IV32GESho-U3d6>&)l+&xW! z23&3jH6&OUCx{e${xq4VV&{qk!)~31SgTu#5*O23ZhQWB{+X@2 zFVD3tH2%+Bb26nyvsb&jRC?-ecg{B#7+)@BF+ct!PR!3b=To7qU$}F}J+2FE6Qjdh z${ObQ*mL}yw{(B6&{~_5*_}~Sms?eSnDSz8$@SZvj@6>In-_44zSVuv-nB3K!aS4A zOG~6(W`QWr$!fkZ#@qky@j5Rycg00q&=$RGe{}l(;D;#+TpK*HBmzV;JT@BesKY$N Zz`zmUek&^CzCO^q44$rjF6*2UngHF~w6g#J literal 0 HcmV?d00001 diff --git a/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/folder_back.png b/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/folder_back.png new file mode 100644 index 0000000000000000000000000000000000000000..dc0786ec6cea1394a7bd1c394727ce9604c9141b GIT binary patch literal 1128 zcmeAS@N?(olHy`uVBq!ia0vp^RX`lg!3-q3%M)E07#M2L^NvAv_Sw|~OKsWav-ShQ@-+I8zUZQinN`;MKvcJJMP;NX#? zr_Y={cj5AtYu9hzx&QFV(`PT2FPYU7|t)Hku3cJ}G-&`8KU6hAq87==kjTKgss` z3im7Prq4Y3|MX{@^I+sJ+563aVM>$D(hVQ4ggNY6+j#l@iR@3gyfG@Wm8?>Wc&ze_ zi%Ql!NxjWz#Gk2bl(bYlYRjHQA^OHCo?nusOZqNuiu<>VF{4JNat;cS?{w6kwl+^nZGMyT_}1@~(|4b`Rj$vmG!~4%eUWdGvtt+AyJJr~xZ4FB zH20p+@m5sjlIUFTd;0W=1(s89X;)4)OUn87^~;sbpPn4~@#Dsg7efA7a(8zd7yUhS zbKxSdm1_(8^fcXbj`o(6N#|@X@p0Lv_D48-ZE>Fs&*W1te)Iec*O7NvzUdc_ZnW@K zi*#)nztpWvUTgIJR+@b+w14~dIW4^Kd-mDcpKMT#?^!cAwpZUXC<(25)zVb5ySm9# zJyAio!Oq^ais@}a14BRtdn!Y-+0W_a7ooAaCw|FmjY&OoIxYiKEQ6=3pUXO@geCwO CHQzk| literal 0 HcmV?d00001 diff --git a/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/gif.jpg b/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/gif.jpg new file mode 100644 index 0000000000000000000000000000000000000000..f479380fb0db7d03a6580c674582f7f2fa9acc84 GIT binary patch literal 3754 zcmb7G3s_WT8vf3lb7m$kb3p`UL=T9~{v3fgYcF_8<7qJKz8Q-~aya ze>vm$%yAhc8L8>1KoA6^;RhU71c%a-lb5RVRH^A%3Tyxn?A4gfdL9E{Fxo76$|R;} zaWNz41s+TWPY3`{jn-;TRI9T93&-W2 z_zdIbUTI0o8^MiQjbb6<5R7-4ZAn~wCgQK{RRxKNX94hh$}On{!+hSub(Q&x5c^@g zOlM2aABoo)OLJ6+u`h3Tl_`_U!*M#b)@1Y&f)QV=WYf7dMm;2yu_+3~vk_0Nw5N^a zCo`-y3%R&6PhDkl4r0thT9#=t)QAHRueX@;xUo<(xtrB1xv?-m*LQFMtu%9 z7S5Lvu~z3CF()}-tIWrJ%JrpUZI=9zzEp9!E;W6Gzsjt4?nTr_?XlSNIBl4p>e5&g zO2n9ly2Tm`INuP{lgczHoVO8(AAv$b11y-J6l*OQ;Vv+c2TDl7rx`5RQVu%MV}!+4 z79%>s8>%pNf1cXO8Sdj|R5*JNaJ_Mq`*VgzxIV%$QT~*iipKx>R2CIa&7d>!@@%Pc_(aWKKsRBy9??hq?MNYb{H4+K)HhL^bYNn%wP} z$2DWrY#QqTSkZye*@chw>4Q~AC%IafZtBpZpLl(+3RJ)6FWpZM(A`+~(ihzQ=|1`b zetIDhS3vJnWI$Cq=So;zyzp^zXh)_EG+2LuJQHdiRXT1(%Z-}?+%23F>@zt( zqgSJ@-hV9a1n8gumFQqOaxLg8=dclKG3(fKGNP24N<~uXzuL9)xV=28g0JAG@DqXI z&*I1NBl#H|9zA*dP;86CTH#VZd~#fjaWi1Yu+SA(o^a=`7v8&9o|=h%>Z{B9F9A?9ge$AnEwL6alPXUSgly0D+kEV=5Bou0!{efMU5{5P8$&b zv=akl5Hc6eBf>^FJb-6(K#g#?JD)4uU5mX(p1ek$i&57|y6_T?>bM6nDzi;z(ABYJ zOld8Xp;jmjI-`z>j);qhig+jsy|l3wqejojS43)}*oPwL#X0&Q8F*YFxr(NFq<~Ke zNKzo6X^JltNTou7Q0U<)^75GA?I{#`P4oAbi30-zJ-nno)5Ja^aiEw>LeMlVAO+qO zhZ}t}8Xka?8&h^Yc08H%&a_hP4p{s#CYAUml&Czi5Zw`Ev?G%H6(O zL!B#E+?g@}WMD$%!&!G#nHhf9x}zeB{?k%$Hg-oE{&0bgL#wZ1I(Y^Dot}W1fqaUHhr|BkhYD z{9d=0?tWkPhpqKRp`D)$eYtqsrMYJ!mS3K@Wmfn5>XlE&-+A}-!invM#)6iL_Y;WZ-yrZt3G*aC z;2siq(A-|<3W26XQnb{^5+sk!-Mre z*B(3g;khE!hi&&JzBbDNky8g+BKMzVgPrRJH&21?MiUWfbA01REhYWA-F&H;a zIv4wn@_C(XNmEBm{p)A12Bh{33_UCR^vLaIn_WQnJgd6WSGw)H)SjMZiG5=)w`QTZ z_Xv{5Cq@kiLJC2VxrrJHBVW_dUacwRXu$@D;xYOf%;;b`)eOP?L|w#EAOeEZ(joSoTW;(^w{ z?<1a5nW`JJp6^uTp8Lz9)qn30{&@78!o>rk4YGxhd#mtpcC2{Q(A6{lJiq_IB;Tq- z3m^a2-pVJQL-EcN?Yt-PP`eAy(}~wkVel4yfk{4&w=RR#Z){a=FH3%JFFOh7EE-Ew z?o&;G6rGhPYS!G8FxBk~N*Z>(>2g-`v+stm%=(}O4IYw{UIkO%p7+bN&oAHWVx(au zr8(=TzM%J%0@HcwXx!|*zMkzj3%ddieJ1(3{Z6rBk4o*=06k5mD-BP*t&@=-9_!zi z@xo1U$K|*DTkS=J_~lEXf4*UWq4iU;!~xf4bS+qW=#;#*_pSG;jCS7qn zN*&zKK3O(7yJFM7L%h$QnV8vMFrhI-)}JuB-0!71GsE}YI?~^68Bizs&}V7$t6|L( s93WA~MXQ$!D&}N$h9zznl*EKBIp+Cd1JAd-bB$CxC3kX^sov51KS1K1&;S4c literal 0 HcmV?d00001 diff --git a/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/gz.jpg b/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/gz.jpg new file mode 100644 index 0000000000000000000000000000000000000000..414d5da6fc4e3c926d0d2c3fad61ded968eef4a0 GIT binary patch literal 3372 zcmb7G3se(V8vZ9UlSBw1AiluLfEtli41ywyRzi5oBZfzPZ8eVpQj!oR!3WD$+Ox-& zszRVppvmZELNH?yC5}t*-92wxznh+EU%tF1xz+tX<9icM_7&aOa!< z|L%Xk|G#(cjOPo_4Nw*47UTj&QIL;6@Z6FeD$wZ`>J6p21w}dN0Fdo8I-NEN2Vi%& z1w&pIH)rlVPSyhw7y+RW4WUM}%c<4tivSzplIy_s;4{ET0G~{JvVS1^XLq3%-em@$ zw1^V{B#~7@ZiSaGnci4a{sQ8m zXt!A11?4__qr+5EiWtXA+H31(kvN3YZFcFfmJpBlS`A-7))@8BVBxcK5Kllns-_{| z7oRS4EiNN=F-~KRt^_g0p@o->g?hx%h+h}#3}i0UOtCJ z=E8g#CGQe*#F+GLcTG9&Q!K4j87J{>3{gNZk;#!!5>aQrjfN&qF0;1RmQ6s=x|1wD9QV z(PE{-pcZXU=IKR_cT9j$EsnlTM&m3`=6GkgjhK z8KdU9;0k~XE6|_a#NaxeZ8|#K@8K>phZcOIINJoJ&#Eu`HG7-AjC~J#H87sN!d}H+ z4`^`(Y@#ANs%O-`Cpgtc_@g2QOzG)q&aO-(lO$rjHQ(1CMVK-?{JHQDMMPw5cqHO*5`-VqayPAtWZKf(xsTH{+0O4{JGgbu@ zsT)~lZ)4CPRcY8Esgn4VC@wBjkLu*8nPMf6)TbWz9;MHhR-W6vD_hNE<_v1tS8}i1 z11YVOcG)vWQ0wUz+j`r7>aAFasI_-{MwJh>cgJ*mQ}G|ol>6h`M;`mU*kDU3J#uIF z_Ax?ZU)m+xbyAp!pn8d7yi;Q#XHvSS5G4JCi7NcQq?tj1bSS)!U{sNV<3?+eC#MRo zby4xN^@c^JdS6!3nUenwOU$a|)AH0!zg6^PSM-Jd`>nb}B?z&RD_wb9~UifUn z4^gq>2feE}kl0}``>m`$HP4x*GE4{oBPX{nzn;S>Nh(_mv(&g z*6GwodmGkoJJ@oic6HmOhb!79Q6srunQzqqV&h^IG_th@w(?;Ko9^F=& zJhZHO^Kf>`$=ds5VaBL%KLAU!{+dt_5vNJk&Q{g;W$KNuym_;KU1r8Th<{=KnnPjV zuif_hWnVNcS^3=J!Ldgw(ps{Yk2^DeRBP{olPj0o)d{~iaN}jw2KRgQ>sM^(nsR>1 zTcP#MW507u*IBvg#?o1%ZWX~b`suD|a1ljiMD73!Xlj*Z2gJGYE~`}p>aO+~GXR{z~z IzQxn?KLAko>;M1& literal 0 HcmV?d00001 diff --git a/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/html.jpg b/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/html.jpg new file mode 100644 index 0000000000000000000000000000000000000000..6bb674362029da0c86910b8b32cc3a6b1ce55c32 GIT binary patch literal 3719 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 U==pE^vdV2`T8G0Y*I4fS5AsT9EdT%j literal 0 HcmV?d00001 diff --git a/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/jpeg.jpg b/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/jpeg.jpg new file mode 100644 index 0000000000000000000000000000000000000000..b4f258a742e86858281211ae7605b69cae66e2f8 GIT binary patch literal 3700 zcmb7G2~<;O7QQd9KmyR;yK+3RtynWja*5=(Ig>Mmt(tJ5p%ozLyZ7$79d@f%m@L`~CO- z?)|s8{^|M#B-t5R89)#OEW;1Dt_wfNQYxQNYw|L(a#ZL55dKwbwHkRefXVEzX)@F3 z;*wRgupf9Z4g4Sk{Ioi|RiRer05+D(z9+W3{{V~xaCyP~{S(>0`{t)->^cBKgm#PG zt}`L71K=BVR+|Gr@GaVt*Ep<*g<*&TZ72}2oW+%HoX+BMH!kKlg&HMtSgm4Rl~#|q z0daKsID6$d?ACw`jFZWj8Jj^zv$as$EENVL!#UiKKX8v@J_wqOPRyBW5%~1CR~IbD zcNCj@m2H{EgWGgkRRQ8zXz#T;(pdW(#5bJPMGD080Co_Ih)9ZXROn%iB|JSc9*mK!XM{Ar0SFu%V{{3}8eHgI)$L z24WIaqwW4YHOF!H8Dms(y$9IdILiGw?hyt(919gp$*Fk!e}u}R7E{So3eZ$4wUk;y zrK2^4dc>dXI@Kfv$9XFvbySbzQ%{#E?+ zg92y3$SE?RDg!qYb}w(igd9#H(*at1UPGP*wT>#CFryXb=8!QDTM4Eq_iipUMvqzL zpUZE``{eENH|77HFveKK2~{Fn$b;lD@-TUXJPR~=f;>qcC%egg5mEOrMNpa_*1U=4C@SXH*dW>||+$L|x5QYwOqrLumvYLnTuJgP#V5~K?hKnvyx zQUtMrY!;91Ji%P_rQlQLRqx(8UdDtBm~kwuiZ{*zZq>1CmF-=Nx{autaWHjwcK|3Y z*0nZ6WtD@DlgpE61zu$gon_X=MAKTMk>*@>+Q!%!TP>rH0rnnb`vKh1aQ7P#bbid{ zSOKv32RySbjM-K>0Xpme!3krwC_EEoy8%8()H!Xn?s$0do&&H~#K&>p3I8-ao4#_n z?%;VP+yyYQ)8+bgkIOak2FAY%aKh-i2J2OIh6;ccE7(&XM8GE|<3Wv=0jrG&0X~NT zvWZYH)(}x14iBKo0F;Nrp80HJ&syy5dGp$MUPgTz>BWz+RM&5ikY{xmOon6hlfi7D<6}}{;$jx&U@aYt&8#)j^18&t*ra6r!g$vePy&x_B>Uj=d8AN42}x2Y zd1Ff1nh(P}d*3;g+A<hp!AS6C{zF&#u zuHT#*eoJ!W>AxuSpV9{^B_;7&=3XxJn{9dF;VnstPPus{4H z{gupeZ{WGC885$d_*&exn7u7?!)~rBY3g3S`*y_RJ)MJBe)#fEXWjG!S;qH{&lE@J zZL113?prWj6`oK!?ZZ2PU(O_sSk{#akKOLQQhYlDQxwgPTAwfr4@DQCSSwg?)sUI(&1pN z@*K8^6#lX22iFLY=10aVZk?3KwRBDUes$T-(Iu4{IpUvoc)d^5vm43fpC?{19Xb(n zwz(`+7BRAO$9u1DyrfI=*%4i|eesP~eA@7@(XT++}~mvrG- z_u!Q(`J(rJW{A(ws>xn^inz~1!Zt?6eJy9W-=xoA==tl7?A{5SUx6bVm$man+^ zv!*oT`5?y&=Q<=$J0(B9d^-AE>m(mqBTCp>@l996*#JS>z)!`iV-+nw%}zTr_dmzq zd1LFpUb}FhX%V!yg%HudHrKA3S{iWvy}u{=S=qT@Nq7{ig nfrouJ%HD=b{lS=9v(h$%o^4A?m28|9)t_Ge=a-YZUH$(916_s= literal 0 HcmV?d00001 diff --git a/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/jpg.jpg b/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/jpg.jpg new file mode 100644 index 0000000000000000000000000000000000000000..f479380fb0db7d03a6580c674582f7f2fa9acc84 GIT binary patch literal 3754 zcmb7G3s_WT8vf3lb7m$kb3p`UL=T9~{v3fgYcF_8<7qJKz8Q-~aya ze>vm$%yAhc8L8>1KoA6^;RhU71c%a-lb5RVRH^A%3Tyxn?A4gfdL9E{Fxo76$|R;} zaWNz41s+TWPY3`{jn-;TRI9T93&-W2 z_zdIbUTI0o8^MiQjbb6<5R7-4ZAn~wCgQK{RRxKNX94hh$}On{!+hSub(Q&x5c^@g zOlM2aABoo)OLJ6+u`h3Tl_`_U!*M#b)@1Y&f)QV=WYf7dMm;2yu_+3~vk_0Nw5N^a zCo`-y3%R&6PhDkl4r0thT9#=t)QAHRueX@;xUo<(xtrB1xv?-m*LQFMtu%9 z7S5Lvu~z3CF()}-tIWrJ%JrpUZI=9zzEp9!E;W6Gzsjt4?nTr_?XlSNIBl4p>e5&g zO2n9ly2Tm`INuP{lgczHoVO8(AAv$b11y-J6l*OQ;Vv+c2TDl7rx`5RQVu%MV}!+4 z79%>s8>%pNf1cXO8Sdj|R5*JNaJ_Mq`*VgzxIV%$QT~*iipKx>R2CIa&7d>!@@%Pc_(aWKKsRBy9??hq?MNYb{H4+K)HhL^bYNn%wP} z$2DWrY#QqTSkZye*@chw>4Q~AC%IafZtBpZpLl(+3RJ)6FWpZM(A`+~(ihzQ=|1`b zetIDhS3vJnWI$Cq=So;zyzp^zXh)_EG+2LuJQHdiRXT1(%Z-}?+%23F>@zt( zqgSJ@-hV9a1n8gumFQqOaxLg8=dclKG3(fKGNP24N<~uXzuL9)xV=28g0JAG@DqXI z&*I1NBl#H|9zA*dP;86CTH#VZd~#fjaWi1Yu+SA(o^a=`7v8&9o|=h%>Z{B9F9A?9ge$AnEwL6alPXUSgly0D+kEV=5Bou0!{efMU5{5P8$&b zv=akl5Hc6eBf>^FJb-6(K#g#?JD)4uU5mX(p1ek$i&57|y6_T?>bM6nDzi;z(ABYJ zOld8Xp;jmjI-`z>j);qhig+jsy|l3wqejojS43)}*oPwL#X0&Q8F*YFxr(NFq<~Ke zNKzo6X^JltNTou7Q0U<)^75GA?I{#`P4oAbi30-zJ-nno)5Ja^aiEw>LeMlVAO+qO zhZ}t}8Xka?8&h^Yc08H%&a_hP4p{s#CYAUml&Czi5Zw`Ev?G%H6(O zL!B#E+?g@}WMD$%!&!G#nHhf9x}zeB{?k%$Hg-oE{&0bgL#wZ1I(Y^Dot}W1fqaUHhr|BkhYD z{9d=0?tWkPhpqKRp`D)$eYtqsrMYJ!mS3K@Wmfn5>XlE&-+A}-!invM#)6iL_Y;WZ-yrZt3G*aC z;2siq(A-|<3W26XQnb{^5+sk!-Mre z*B(3g;khE!hi&&JzBbDNky8g+BKMzVgPrRJH&21?MiUWfbA01REhYWA-F&H;a zIv4wn@_C(XNmEBm{p)A12Bh{33_UCR^vLaIn_WQnJgd6WSGw)H)SjMZiG5=)w`QTZ z_Xv{5Cq@kiLJC2VxrrJHBVW_dUacwRXu$@D;xYOf%;;b`)eOP?L|w#EAOeEZ(joSoTW;(^w{ z?<1a5nW`JJp6^uTp8Lz9)qn30{&@78!o>rk4YGxhd#mtpcC2{Q(A6{lJiq_IB;Tq- z3m^a2-pVJQL-EcN?Yt-PP`eAy(}~wkVel4yfk{4&w=RR#Z){a=FH3%JFFOh7EE-Ew z?o&;G6rGhPYS!G8FxBk~N*Z>(>2g-`v+stm%=(}O4IYw{UIkO%p7+bN&oAHWVx(au zr8(=TzM%J%0@HcwXx!|*zMkzj3%ddieJ1(3{Z6rBk4o*=06k5mD-BP*t&@=-9_!zi z@xo1U$K|*DTkS=J_~lEXf4*UWq4iU;!~xf4bS+qW=#;#*_pSG;jCS7qn zN*&zKK3O(7yJFM7L%h$QnV8vMFrhI-)}JuB-0!71GsE}YI?~^68Bizs&}V7$t6|L( s93WA~MXQ$!D&}N$h9zznl*EKBIp+Cd1JAd-bB$CxC3kX^sov51KS1K1&;S4c literal 0 HcmV?d00001 diff --git a/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/log.jpg b/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/log.jpg new file mode 100644 index 0000000000000000000000000000000000000000..c2fe0e7c6934d35614774e055b9079361c736c03 GIT binary patch literal 3804 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 Nx-%|O*PHC@`X45_7oGqB literal 0 HcmV?d00001 diff --git a/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/mp3.jpg b/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/mp3.jpg new file mode 100644 index 0000000000000000000000000000000000000000..fd66149082a8a8484c4ccf579445183f5810140d GIT binary patch literal 3335 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 literal 0 HcmV?d00001 diff --git a/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/mpg.jpg b/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/mpg.jpg new file mode 100644 index 0000000000000000000000000000000000000000..0da2aadb1a51c1bbbd4d392a0f697be2b4a5848e GIT binary patch literal 3459 zcmb7G3s6&M7CtxkCWKcYh+?tDtJp%V(tu!L6_ocIVgN<0N=Pn}8X(*RL`16AT~X0h z*}ALlC?Zz7wRRPkVr$1owYZM2^?^kwJ_ZM>*ln@PSRc)v|K>sHI6D0^`R|u=zW@B+ zIsfCv{H^&Gc%~#ICjdoJkc1yF-*IY5j*VTQRAnY4r^TZKz-gb_V9<+LfTCg(uS$$z zb7#+Co!UVJuYfD~f~#6%G(;N=20MG1;Gm~IF8_a3(gfd*{WFN5Unyzp<0W$ z3h{(|2m3+?Y|(%WjFZR}bG%N&l3FPFk^-Hc6C9TAC2j}ii(rwy409HmANFp>MOmr% z3?#W1@<}QyuGgsJvk;F%`x%2NhS=Xg+*h_JCmQj10FhS#pO9nWi>6iV#Uq}8*sriG$r_(d zF_vc$yAY?cFg61*#-aK5)G12DzKCo15*3*XHPa28K9S6Y@#$|2CZ$ya-CL~BAah~9 zjEpl1Ibuw@*HoB|`;?4jCY$(d>sV$^fi5B0%C9o$g}sQ{m`1)#MYLgj=8~F^PehDy zn0~G}htv(Rc%)VxM`{~{I0|M`YT%#*^0C)IF+2knRFDWU_%r~Io&wN;9xWVtIke~~ zcUXkB=kt^T$1-M+u}~P@OGe`?&*xZX_} ztr5%=y8@+yP8Jrz_o&norxeO?W};&z#BB5}3$%}6SMm#Vnu~w_5!DQ4Su*IyIQEQD zbBSXGz=##FWjE2WPOVi(N7_B?HKyg=D{ie-komIuio3RiLRsnMSn#fp}(Nd0ZSjJPteEcZ|KkHFYPg(zxI|W_O%!C zB{q^RSq0mCjy8*62& z>htF!CqM@|s6+>gk;`LMNrj7H2}X51Csw759}~Qlf7(HA&Hm7Nuq(3jF&`6 zf+Z;g+fJS&0DTeI$J^CgPL7>1Bm>TYg;lY~nJDZ!vRBFIa@4Iy-JFT5z;_2gY>8nB zuUlAXVnY;)ci3orm2qrxu_kB&tJdpT!DVE5&dBlQoHhu^dytF+c&HNIZ`6p3gEmt- zK;#d2XI&b!%_#%eZv^lO9kd1Foj80aK+9xJ8DDORhcDjq0LFqzA;NFUEe7wVF0=U| z-d9eW0iJC#o1Zk8&ChmY{7!)5dh=~q9$%p=07y?Kw?0TgOnKo&jV}YDjq(MtfB{md zQFg4N0<9boz-k>ZRt~xINh5bHjLiuAxXRpIhPk^+rEZ>X?lKRL*F0R@DJPL^i{$PO?BMHp|ryT1E6wP3@tTz1rLo;HaL{6TH&@j0&4+Th379|!vZB(kqU2wj~ z*WPViugzG0R(7*dbLC-FVDG-hs`=xJB3rvnwUyQR-kDx& zJF63uHs$vJr{xd&Pv>QSno+Q;{oAv;fVzebRdYx4fwud<9J}^D$zSeJ7D13wm>vr@ zjf#B%L1ZIDkaQ?oBK5FE5@C9B5RZ{~4O0Z4VEsd)jb#U$JiUi2RatrJ{8E0!=DI_d ztyxN@i3XI~m@i#VuiJdTars;Q2RgDhgg?tX(B15%slIH6$*Pgd??$Grx|td=Lc@5) zZt3_SKJ^`6e};E2bZ-vJIjlI^5f|a!v(~vMtMiNfJMOhjIecsWxsZOQe6Dt<>0m>k zF(C5r;;QP1tlEtgE$=UDYkBN5B`c@yyE(1pe|I}jlpgv=zmS^i!|OF2w=6DGT>mGU z@lz+?DBXK8;mFC*o{slEXNN}(i*F7JxXaC+wR=ov#`HaVx~_+wK9_cW*n_Jx8$wT> zKY2F0HSYrT>y^qmcft=br!`y0HZS>i{JUY>tFB=o{XKC{Q8X>Kl?f>M7zmEuq?n;r z=9RA4bz2QEZ{zIh$l!FpkY%%?K13zL5fCmG+upTp zSMpm5q$k&rwY^}ckgeqTvaKW#NQtmQ44yt~qvS9qSP?zLQ(gL_GH=Budx<=KF z?au29o&9&XaU*cP{$yRLb!ghF@m6 z)+BAsjp+)@^#9-AN+&9U^HTr0YU<9BU>{+IqS%_3p>*H))npD lu*Q4q@cM literal 0 HcmV?d00001 diff --git a/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/odb.jpg b/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/odb.jpg new file mode 100644 index 0000000000000000000000000000000000000000..eb6522c84b5ddfc8dfb785525b64adea20581b95 GIT binary patch literal 3581 zcmb7G2~bm67QKHSPPk&Kfl=o-E9nfwxInwi7 z_Hv6pI|nh2rPmf)hmbggbJAc>#9BgU#Mg_2bh5^%hXJFIl#DnWai^lvG*^5k!(KLw z*rhn-MTyynF%Bb6&}C>5cSQV+Xw4;ap=M^SU`{1-VSMJe&7pN^VD4GW*<>!vmsJXO zDMyUS+;bG=;XWl}*=UED=NilA7noAgUHqvwv$Pjc8@paC%_Z6}KKqkSOio3Nao8t< zWjLuDVlKd_OCq(6Ks*RWP&yF63VQ4fV1akQLoTF30zPdZqNe~%U`C68UI8s8$_t9o z_FG7Q za4XQZ(8)s~)T7eII1`~1XC^vEK*EBKrD5(d{0woN$#Cx522|6WrM20QaoicBW^2m| zfE_E)lwGfubviNiV1V1h*RlJ?T=YCK6>>gRU+xZfkE_G}GIzCkJa>h=il566k1Jr7 z6qTSVle7|cH?LQ#9BPs203G%>k!MA%O-fs>Xn|!x$7Tv0sUNEA z)RpS>>IbdnXpY#bO3Y$r5AzRZKXZUN4LnoB)G~*eB$Z6PHr96RTm<|FCOg$X;$zAxoAe$>M>R^^nENG_nkW zn@*mrJNja=Pj;(sJUMPgs|J}WrWPEo3BwB4#L{njr zgYTnO_v7R7RVMK17DGfhuQQu@$z|t7!7hkpf-wTfdytF+c$zD{->44fnr)6OfPs(j z&ibj@mR}06%?{un)ocsHJF)$0fPK-1Qn9Qt9=>?b0N4v6`$)ej&jh@it~;Gi@xGET z0(iI3>3p-+>3p{i<6i}+F*|RyE+F6TH_rjV;t z3b{hj)_EmZZd6OU%$8mB-?!~fR-fb0az5nm# zJOU~OjD~WC>I}4sVpNp#CHXS-H*iQxP{%1G;Wf-*1~3E0zbIY*^~W-0y#}zO;Wo zrtm@CtN+xTR(corK34nVq`i@khIFY{&yp>Bc7wN_>-_jZ_O7o6^z>Z+g?~m-;Nn%o zdnPnk4pwvsK34pFT(bE2;w!=D{_eOvdEly-S8^)mk3Cd#X~` z3&!*i4sGqd(r1y4EEA zGGYF-`bX+r6Q}%YZ3ul3RCpmWbM2UQ&(G?op6;`=^6Oi72Whi|hHAH;Sy{R4?EBlZ zqqb;{R}T6$@8RC?(N|9Oj!tXiAG7<76Uydp>~`02J?8Pug>z3Sa!xFL^<`>k-v~d` z;@9>K{#(tqrF$~(8YTp-I5ZS1+|37f1IJRFdnG7PVeJ-H#_J|d*YfJ|wGHQ+w#nd- zmm1C0GvWv~z;}C^nm<@Ko({QWEU?(ZnAz!ij`ogPP%VZW&FsH%;AU0TsOVan4(m|X zBOq>h%3q(I+T?vU?nuP(=M2oQs#t1xX|l~~*FN%b(3Vzp%<(Q=hjT=XCO$F{B}j-JBgfH_-Z9 zvia#o>V<{&e3sNTcgLhP%fCCLT;#iNdj1+V&tvztx2heFerKqlCzZA}-B*+_<&WEW z=qqNl?=VvH!`x6-Ngdvnecn{(w@F>69a&L6R}(dXy7=Jzu&8%ypTxvb`nYvhr#;iW zYF~Y};z)jI^%9k3Ov3M-^aGENf7114(AtKsQOV`J6D(5`A@BCxuq8*jZ`$bu=jHza DNg__S literal 0 HcmV?d00001 diff --git a/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/odf.jpg b/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/odf.jpg new file mode 100644 index 0000000000000000000000000000000000000000..8f40c746036378c31397e2a0cc49a743daebd865 GIT binary patch literal 3590 zcmb7G2~bm67QH|J|0Kl{0w~ZR^3hfq6$~HG-F6v8 zQCoYe1VpiIm%`H4aT&K(anJ#^U2y4c8B1|m9m{p5)Xv=Z69RNuTJutQ|K#5D?mO?k z``(Z3rtKGyrzNK*14U6V20vhHl^jk@Oq`)qjZaQZPeKQPWT)C_)QdQPqGF3lm6E_s znmmP*w15ac16S||SGC4$j8`ht0UP0xXV>=nI$$J#tDztEcV++Xmuntx)&Njav>Wow znj*w=09d`oXtDr^@1s5DON$Y)qzB?|CKQNRL2!W`k0vj#yGTTmO4#|*dOt7lR-u1Ld|pyuTLR!VSM_W(V}!{pxcV|8DuV8 zFC*j4!WuCq-Dc5dW1W(*Oti(6?HJ2U$=4;PI{0Nqy-FbagxZDcgg@?nmBhDQ#Lf$?P&OeB7XG3m?*CWeUxj)`MNF(aAL zXpLotITa{7>ExgQ9-&fuoD#6&%tXfoNLcG{4RMa)7Mf=0G)-%sp_-0W8an(K$GKwE zZ0MW;Fk=SVR~OnjPv^^y`8hq@HRkXaSKZE+!T3+*m%Y!nvDdI~VefQ|XK%B2@Y4eE zxC44YQ4y-r2|HnS@WbMJ-q z5*t}9*@gD`I_H`Py(~c%AnPp~Een$Mk)=CXoXl4iE*m53hn@iEzUe#sUDl$5$(XD5 ztbTYdasqUagGzMpC2~!eRg&Rin2S+6pA&~trY955r2ejIV@NHxs}LuNM~mZu6ZaR# zio?Ze1h=0&aX<9MVxQzxZ$CLsMwb=vomiL^XPi)>>PW4U(X&yv9(D5;eh$7n01^$x zxh7qK*1|<76hpXpe3kKBYOyA4Ag9*rIl*P-OuU&l&F1sMfV>CEIDi)_;r&MWGAhVkzJoYdRyL3z>~T|U6LapcwqDX^3mUex$9AlfK@U-(@MIez$+9TmlU_4oGuU-kNit76A!MzoU%1pJU z#I)e@z3_CED8BCo6Vc$_(7#yWiCit*T#l zEUWvh%(Jq}?a46{D!2OeUa8`DTrb~uAg!=wz>z@{&+TM=*8MoN=Xw9ujrW%yH(8SkavEo*$#W5C{>uXcUI$Y1T4GGpq(BW~WohVLJ? zwPvs1QQ11EAHQ;WkL5AJ(;mbSKV`>r=fnBO$- zi<^{vwAb@_in5*mRu~>iwa?RA`~AEn4wD=r#}W`REKSb3&?xW>4v$wa$SkR-ex|6u z%#Bjcyw_eVal!8cq<^oT%^e!@++7)3I&J&p)s0KsH*c$cs9ce`rf==}xUoTWz;}a_ zSF2x~TpCmKbkSS)=EKJhm`0qs@cPJU$QyQf#mLmfL1&t^C6E5Igqj}sh}v1`|7Mjw zyr%5wj%U`}-`3@~WldbrCih-CKEQRLPyUczo3yv;4&7MuV8gsU8LAs=LRUZOcCwja ztS(2dD(-si+AE&E{FQ%G-I7h(`ioDz7man|P0}djicQy=Z=DV{f0j7iJd`E3G+D-lt!}m7((T z!4V?=a_`+^j*N%{uj++Ex1#5p{yA;_OY!N@Wy#>bnl zHZ5)#(DHRuQlV$aP|6VCJt83ci(jV{)KOGa;qd)0Q%Vg_znLtG7+mtVioQN~pnH|P Sck`w#)b@*CMP58%Yxy7chgaAD literal 0 HcmV?d00001 diff --git a/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/odg.jpg b/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/odg.jpg new file mode 100644 index 0000000000000000000000000000000000000000..eb6522c84b5ddfc8dfb785525b64adea20581b95 GIT binary patch literal 3581 zcmb7G2~bm67QKHSPPk&Kfl=o-E9nfwxInwi7 z_Hv6pI|nh2rPmf)hmbggbJAc>#9BgU#Mg_2bh5^%hXJFIl#DnWai^lvG*^5k!(KLw z*rhn-MTyynF%Bb6&}C>5cSQV+Xw4;ap=M^SU`{1-VSMJe&7pN^VD4GW*<>!vmsJXO zDMyUS+;bG=;XWl}*=UED=NilA7noAgUHqvwv$Pjc8@paC%_Z6}KKqkSOio3Nao8t< zWjLuDVlKd_OCq(6Ks*RWP&yF63VQ4fV1akQLoTF30zPdZqNe~%U`C68UI8s8$_t9o z_FG7Q za4XQZ(8)s~)T7eII1`~1XC^vEK*EBKrD5(d{0woN$#Cx522|6WrM20QaoicBW^2m| zfE_E)lwGfubviNiV1V1h*RlJ?T=YCK6>>gRU+xZfkE_G}GIzCkJa>h=il566k1Jr7 z6qTSVle7|cH?LQ#9BPs203G%>k!MA%O-fs>Xn|!x$7Tv0sUNEA z)RpS>>IbdnXpY#bO3Y$r5AzRZKXZUN4LnoB)G~*eB$Z6PHr96RTm<|FCOg$X;$zAxoAe$>M>R^^nENG_nkW zn@*mrJNja=Pj;(sJUMPgs|J}WrWPEo3BwB4#L{njr zgYTnO_v7R7RVMK17DGfhuQQu@$z|t7!7hkpf-wTfdytF+c$zD{->44fnr)6OfPs(j z&ibj@mR}06%?{un)ocsHJF)$0fPK-1Qn9Qt9=>?b0N4v6`$)ej&jh@it~;Gi@xGET z0(iI3>3p-+>3p{i<6i}+F*|RyE+F6TH_rjV;t z3b{hj)_EmZZd6OU%$8mB-?!~fR-fb0az5nm# zJOU~OjD~WC>I}4sVpNp#CHXS-H*iQxP{%1G;Wf-*1~3E0zbIY*^~W-0y#}zO;Wo zrtm@CtN+xTR(corK34nVq`i@khIFY{&yp>Bc7wN_>-_jZ_O7o6^z>Z+g?~m-;Nn%o zdnPnk4pwvsK34pFT(bE2;w!=D{_eOvdEly-S8^)mk3Cd#X~` z3&!*i4sGqd(r1y4EEA zGGYF-`bX+r6Q}%YZ3ul3RCpmWbM2UQ&(G?op6;`=^6Oi72Whi|hHAH;Sy{R4?EBlZ zqqb;{R}T6$@8RC?(N|9Oj!tXiAG7<76Uydp>~`02J?8Pug>z3Sa!xFL^<`>k-v~d` z;@9>K{#(tqrF$~(8YTp-I5ZS1+|37f1IJRFdnG7PVeJ-H#_J|d*YfJ|wGHQ+w#nd- zmm1C0GvWv~z;}C^nm<@Ko({QWEU?(ZnAz!ij`ogPP%VZW&FsH%;AU0TsOVan4(m|X zBOq>h%3q(I+T?vU?nuP(=M2oQs#t1xX|l~~*FN%b(3Vzp%<(Q=hjT=XCO$F{B}j-JBgfH_-Z9 zvia#o>V<{&e3sNTcgLhP%fCCLT;#iNdj1+V&tvztx2heFerKqlCzZA}-B*+_<&WEW z=qqNl?=VvH!`x6-Ngdvnecn{(w@F>69a&L6R}(dXy7=Jzu&8%ypTxvb`nYvhr#;iW zYF~Y};z)jI^%9k3Ov3M-^aGENf7114(AtKsQOV`J6D(5`A@BCxuq8*jZ`$bu=jHza DNg__S literal 0 HcmV?d00001 diff --git a/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/odp.jpg b/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/odp.jpg new file mode 100644 index 0000000000000000000000000000000000000000..8f40c746036378c31397e2a0cc49a743daebd865 GIT binary patch literal 3590 zcmb7G2~bm67QH|J|0Kl{0w~ZR^3hfq6$~HG-F6v8 zQCoYe1VpiIm%`H4aT&K(anJ#^U2y4c8B1|m9m{p5)Xv=Z69RNuTJutQ|K#5D?mO?k z``(Z3rtKGyrzNK*14U6V20vhHl^jk@Oq`)qjZaQZPeKQPWT)C_)QdQPqGF3lm6E_s znmmP*w15ac16S||SGC4$j8`ht0UP0xXV>=nI$$J#tDztEcV++Xmuntx)&Njav>Wow znj*w=09d`oXtDr^@1s5DON$Y)qzB?|CKQNRL2!W`k0vj#yGTTmO4#|*dOt7lR-u1Ld|pyuTLR!VSM_W(V}!{pxcV|8DuV8 zFC*j4!WuCq-Dc5dW1W(*Oti(6?HJ2U$=4;PI{0Nqy-FbagxZDcgg@?nmBhDQ#Lf$?P&OeB7XG3m?*CWeUxj)`MNF(aAL zXpLotITa{7>ExgQ9-&fuoD#6&%tXfoNLcG{4RMa)7Mf=0G)-%sp_-0W8an(K$GKwE zZ0MW;Fk=SVR~OnjPv^^y`8hq@HRkXaSKZE+!T3+*m%Y!nvDdI~VefQ|XK%B2@Y4eE zxC44YQ4y-r2|HnS@WbMJ-q z5*t}9*@gD`I_H`Py(~c%AnPp~Een$Mk)=CXoXl4iE*m53hn@iEzUe#sUDl$5$(XD5 ztbTYdasqUagGzMpC2~!eRg&Rin2S+6pA&~trY955r2ejIV@NHxs}LuNM~mZu6ZaR# zio?Ze1h=0&aX<9MVxQzxZ$CLsMwb=vomiL^XPi)>>PW4U(X&yv9(D5;eh$7n01^$x zxh7qK*1|<76hpXpe3kKBYOyA4Ag9*rIl*P-OuU&l&F1sMfV>CEIDi)_;r&MWGAhVkzJoYdRyL3z>~T|U6LapcwqDX^3mUex$9AlfK@U-(@MIez$+9TmlU_4oGuU-kNit76A!MzoU%1pJU z#I)e@z3_CED8BCo6Vc$_(7#yWiCit*T#l zEUWvh%(Jq}?a46{D!2OeUa8`DTrb~uAg!=wz>z@{&+TM=*8MoN=Xw9ujrW%yH(8SkavEo*$#W5C{>uXcUI$Y1T4GGpq(BW~WohVLJ? zwPvs1QQ11EAHQ;WkL5AJ(;mbSKV`>r=fnBO$- zi<^{vwAb@_in5*mRu~>iwa?RA`~AEn4wD=r#}W`REKSb3&?xW>4v$wa$SkR-ex|6u z%#Bjcyw_eVal!8cq<^oT%^e!@++7)3I&J&p)s0KsH*c$cs9ce`rf==}xUoTWz;}a_ zSF2x~TpCmKbkSS)=EKJhm`0qs@cPJU$QyQf#mLmfL1&t^C6E5Igqj}sh}v1`|7Mjw zyr%5wj%U`}-`3@~WldbrCih-CKEQRLPyUczo3yv;4&7MuV8gsU8LAs=LRUZOcCwja ztS(2dD(-si+AE&E{FQ%G-I7h(`ioDz7man|P0}djicQy=Z=DV{f0j7iJd`E3G+D-lt!}m7((T z!4V?=a_`+^j*N%{uj++Ex1#5p{yA;_OY!N@Wy#>bnl zHZ5)#(DHRuQlV$aP|6VCJt83ci(jV{)KOGa;qd)0Q%Vg_znLtG7+mtVioQN~pnH|P Sck`w#)b@*CMP58%Yxy7chgaAD literal 0 HcmV?d00001 diff --git a/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/ods.jpg b/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/ods.jpg new file mode 100644 index 0000000000000000000000000000000000000000..eb6522c84b5ddfc8dfb785525b64adea20581b95 GIT binary patch literal 3581 zcmb7G2~bm67QKHSPPk&Kfl=o-E9nfwxInwi7 z_Hv6pI|nh2rPmf)hmbggbJAc>#9BgU#Mg_2bh5^%hXJFIl#DnWai^lvG*^5k!(KLw z*rhn-MTyynF%Bb6&}C>5cSQV+Xw4;ap=M^SU`{1-VSMJe&7pN^VD4GW*<>!vmsJXO zDMyUS+;bG=;XWl}*=UED=NilA7noAgUHqvwv$Pjc8@paC%_Z6}KKqkSOio3Nao8t< zWjLuDVlKd_OCq(6Ks*RWP&yF63VQ4fV1akQLoTF30zPdZqNe~%U`C68UI8s8$_t9o z_FG7Q za4XQZ(8)s~)T7eII1`~1XC^vEK*EBKrD5(d{0woN$#Cx522|6WrM20QaoicBW^2m| zfE_E)lwGfubviNiV1V1h*RlJ?T=YCK6>>gRU+xZfkE_G}GIzCkJa>h=il566k1Jr7 z6qTSVle7|cH?LQ#9BPs203G%>k!MA%O-fs>Xn|!x$7Tv0sUNEA z)RpS>>IbdnXpY#bO3Y$r5AzRZKXZUN4LnoB)G~*eB$Z6PHr96RTm<|FCOg$X;$zAxoAe$>M>R^^nENG_nkW zn@*mrJNja=Pj;(sJUMPgs|J}WrWPEo3BwB4#L{njr zgYTnO_v7R7RVMK17DGfhuQQu@$z|t7!7hkpf-wTfdytF+c$zD{->44fnr)6OfPs(j z&ibj@mR}06%?{un)ocsHJF)$0fPK-1Qn9Qt9=>?b0N4v6`$)ej&jh@it~;Gi@xGET z0(iI3>3p-+>3p{i<6i}+F*|RyE+F6TH_rjV;t z3b{hj)_EmZZd6OU%$8mB-?!~fR-fb0az5nm# zJOU~OjD~WC>I}4sVpNp#CHXS-H*iQxP{%1G;Wf-*1~3E0zbIY*^~W-0y#}zO;Wo zrtm@CtN+xTR(corK34nVq`i@khIFY{&yp>Bc7wN_>-_jZ_O7o6^z>Z+g?~m-;Nn%o zdnPnk4pwvsK34pFT(bE2;w!=D{_eOvdEly-S8^)mk3Cd#X~` z3&!*i4sGqd(r1y4EEA zGGYF-`bX+r6Q}%YZ3ul3RCpmWbM2UQ&(G?op6;`=^6Oi72Whi|hHAH;Sy{R4?EBlZ zqqb;{R}T6$@8RC?(N|9Oj!tXiAG7<76Uydp>~`02J?8Pug>z3Sa!xFL^<`>k-v~d` z;@9>K{#(tqrF$~(8YTp-I5ZS1+|37f1IJRFdnG7PVeJ-H#_J|d*YfJ|wGHQ+w#nd- zmm1C0GvWv~z;}C^nm<@Ko({QWEU?(ZnAz!ij`ogPP%VZW&FsH%;AU0TsOVan4(m|X zBOq>h%3q(I+T?vU?nuP(=M2oQs#t1xX|l~~*FN%b(3Vzp%<(Q=hjT=XCO$F{B}j-JBgfH_-Z9 zvia#o>V<{&e3sNTcgLhP%fCCLT;#iNdj1+V&tvztx2heFerKqlCzZA}-B*+_<&WEW z=qqNl?=VvH!`x6-Ngdvnecn{(w@F>69a&L6R}(dXy7=Jzu&8%ypTxvb`nYvhr#;iW zYF~Y};z)jI^%9k3Ov3M-^aGENf7114(AtKsQOV`J6D(5`A@BCxuq8*jZ`$bu=jHza DNg__S literal 0 HcmV?d00001 diff --git a/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/odt.jpg b/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/odt.jpg new file mode 100644 index 0000000000000000000000000000000000000000..eb6522c84b5ddfc8dfb785525b64adea20581b95 GIT binary patch literal 3581 zcmb7G2~bm67QKHSPPk&Kfl=o-E9nfwxInwi7 z_Hv6pI|nh2rPmf)hmbggbJAc>#9BgU#Mg_2bh5^%hXJFIl#DnWai^lvG*^5k!(KLw z*rhn-MTyynF%Bb6&}C>5cSQV+Xw4;ap=M^SU`{1-VSMJe&7pN^VD4GW*<>!vmsJXO zDMyUS+;bG=;XWl}*=UED=NilA7noAgUHqvwv$Pjc8@paC%_Z6}KKqkSOio3Nao8t< zWjLuDVlKd_OCq(6Ks*RWP&yF63VQ4fV1akQLoTF30zPdZqNe~%U`C68UI8s8$_t9o z_FG7Q za4XQZ(8)s~)T7eII1`~1XC^vEK*EBKrD5(d{0woN$#Cx522|6WrM20QaoicBW^2m| zfE_E)lwGfubviNiV1V1h*RlJ?T=YCK6>>gRU+xZfkE_G}GIzCkJa>h=il566k1Jr7 z6qTSVle7|cH?LQ#9BPs203G%>k!MA%O-fs>Xn|!x$7Tv0sUNEA z)RpS>>IbdnXpY#bO3Y$r5AzRZKXZUN4LnoB)G~*eB$Z6PHr96RTm<|FCOg$X;$zAxoAe$>M>R^^nENG_nkW zn@*mrJNja=Pj;(sJUMPgs|J}WrWPEo3BwB4#L{njr zgYTnO_v7R7RVMK17DGfhuQQu@$z|t7!7hkpf-wTfdytF+c$zD{->44fnr)6OfPs(j z&ibj@mR}06%?{un)ocsHJF)$0fPK-1Qn9Qt9=>?b0N4v6`$)ej&jh@it~;Gi@xGET z0(iI3>3p-+>3p{i<6i}+F*|RyE+F6TH_rjV;t z3b{hj)_EmZZd6OU%$8mB-?!~fR-fb0az5nm# zJOU~OjD~WC>I}4sVpNp#CHXS-H*iQxP{%1G;Wf-*1~3E0zbIY*^~W-0y#}zO;Wo zrtm@CtN+xTR(corK34nVq`i@khIFY{&yp>Bc7wN_>-_jZ_O7o6^z>Z+g?~m-;Nn%o zdnPnk4pwvsK34pFT(bE2;w!=D{_eOvdEly-S8^)mk3Cd#X~` z3&!*i4sGqd(r1y4EEA zGGYF-`bX+r6Q}%YZ3ul3RCpmWbM2UQ&(G?op6;`=^6Oi72Whi|hHAH;Sy{R4?EBlZ zqqb;{R}T6$@8RC?(N|9Oj!tXiAG7<76Uydp>~`02J?8Pug>z3Sa!xFL^<`>k-v~d` z;@9>K{#(tqrF$~(8YTp-I5ZS1+|37f1IJRFdnG7PVeJ-H#_J|d*YfJ|wGHQ+w#nd- zmm1C0GvWv~z;}C^nm<@Ko({QWEU?(ZnAz!ij`ogPP%VZW&FsH%;AU0TsOVan4(m|X zBOq>h%3q(I+T?vU?nuP(=M2oQs#t1xX|l~~*FN%b(3Vzp%<(Q=hjT=XCO$F{B}j-JBgfH_-Z9 zvia#o>V<{&e3sNTcgLhP%fCCLT;#iNdj1+V&tvztx2heFerKqlCzZA}-B*+_<&WEW z=qqNl?=VvH!`x6-Ngdvnecn{(w@F>69a&L6R}(dXy7=Jzu&8%ypTxvb`nYvhr#;iW zYF~Y};z)jI^%9k3Ov3M-^aGENf7114(AtKsQOV`J6D(5`A@BCxuq8*jZ`$bu=jHza DNg__S literal 0 HcmV?d00001 diff --git a/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/ogg.jpg b/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/ogg.jpg new file mode 100644 index 0000000000000000000000000000000000000000..23ed22b8925ceff4621392d15a022715ca9dc0ba GIT binary patch literal 3440 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 ADF6Tf literal 0 HcmV?d00001 diff --git a/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/ots.jpg b/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/ots.jpg new file mode 100644 index 0000000000000000000000000000000000000000..eb6522c84b5ddfc8dfb785525b64adea20581b95 GIT binary patch literal 3581 zcmb7G2~bm67QKHSPPk&Kfl=o-E9nfwxInwi7 z_Hv6pI|nh2rPmf)hmbggbJAc>#9BgU#Mg_2bh5^%hXJFIl#DnWai^lvG*^5k!(KLw z*rhn-MTyynF%Bb6&}C>5cSQV+Xw4;ap=M^SU`{1-VSMJe&7pN^VD4GW*<>!vmsJXO zDMyUS+;bG=;XWl}*=UED=NilA7noAgUHqvwv$Pjc8@paC%_Z6}KKqkSOio3Nao8t< zWjLuDVlKd_OCq(6Ks*RWP&yF63VQ4fV1akQLoTF30zPdZqNe~%U`C68UI8s8$_t9o z_FG7Q za4XQZ(8)s~)T7eII1`~1XC^vEK*EBKrD5(d{0woN$#Cx522|6WrM20QaoicBW^2m| zfE_E)lwGfubviNiV1V1h*RlJ?T=YCK6>>gRU+xZfkE_G}GIzCkJa>h=il566k1Jr7 z6qTSVle7|cH?LQ#9BPs203G%>k!MA%O-fs>Xn|!x$7Tv0sUNEA z)RpS>>IbdnXpY#bO3Y$r5AzRZKXZUN4LnoB)G~*eB$Z6PHr96RTm<|FCOg$X;$zAxoAe$>M>R^^nENG_nkW zn@*mrJNja=Pj;(sJUMPgs|J}WrWPEo3BwB4#L{njr zgYTnO_v7R7RVMK17DGfhuQQu@$z|t7!7hkpf-wTfdytF+c$zD{->44fnr)6OfPs(j z&ibj@mR}06%?{un)ocsHJF)$0fPK-1Qn9Qt9=>?b0N4v6`$)ej&jh@it~;Gi@xGET z0(iI3>3p-+>3p{i<6i}+F*|RyE+F6TH_rjV;t z3b{hj)_EmZZd6OU%$8mB-?!~fR-fb0az5nm# zJOU~OjD~WC>I}4sVpNp#CHXS-H*iQxP{%1G;Wf-*1~3E0zbIY*^~W-0y#}zO;Wo zrtm@CtN+xTR(corK34nVq`i@khIFY{&yp>Bc7wN_>-_jZ_O7o6^z>Z+g?~m-;Nn%o zdnPnk4pwvsK34pFT(bE2;w!=D{_eOvdEly-S8^)mk3Cd#X~` z3&!*i4sGqd(r1y4EEA zGGYF-`bX+r6Q}%YZ3ul3RCpmWbM2UQ&(G?op6;`=^6Oi72Whi|hHAH;Sy{R4?EBlZ zqqb;{R}T6$@8RC?(N|9Oj!tXiAG7<76Uydp>~`02J?8Pug>z3Sa!xFL^<`>k-v~d` z;@9>K{#(tqrF$~(8YTp-I5ZS1+|37f1IJRFdnG7PVeJ-H#_J|d*YfJ|wGHQ+w#nd- zmm1C0GvWv~z;}C^nm<@Ko({QWEU?(ZnAz!ij`ogPP%VZW&FsH%;AU0TsOVan4(m|X zBOq>h%3q(I+T?vU?nuP(=M2oQs#t1xX|l~~*FN%b(3Vzp%<(Q=hjT=XCO$F{B}j-JBgfH_-Z9 zvia#o>V<{&e3sNTcgLhP%fCCLT;#iNdj1+V&tvztx2heFerKqlCzZA}-B*+_<&WEW z=qqNl?=VvH!`x6-Ngdvnecn{(w@F>69a&L6R}(dXy7=Jzu&8%ypTxvb`nYvhr#;iW zYF~Y};z)jI^%9k3Ov3M-^aGENf7114(AtKsQOV`J6D(5`A@BCxuq8*jZ`$bu=jHza DNg__S literal 0 HcmV?d00001 diff --git a/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/ott.jpg b/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/ott.jpg new file mode 100644 index 0000000000000000000000000000000000000000..eb6522c84b5ddfc8dfb785525b64adea20581b95 GIT binary patch literal 3581 zcmb7G2~bm67QKHSPPk&Kfl=o-E9nfwxInwi7 z_Hv6pI|nh2rPmf)hmbggbJAc>#9BgU#Mg_2bh5^%hXJFIl#DnWai^lvG*^5k!(KLw z*rhn-MTyynF%Bb6&}C>5cSQV+Xw4;ap=M^SU`{1-VSMJe&7pN^VD4GW*<>!vmsJXO zDMyUS+;bG=;XWl}*=UED=NilA7noAgUHqvwv$Pjc8@paC%_Z6}KKqkSOio3Nao8t< zWjLuDVlKd_OCq(6Ks*RWP&yF63VQ4fV1akQLoTF30zPdZqNe~%U`C68UI8s8$_t9o z_FG7Q za4XQZ(8)s~)T7eII1`~1XC^vEK*EBKrD5(d{0woN$#Cx522|6WrM20QaoicBW^2m| zfE_E)lwGfubviNiV1V1h*RlJ?T=YCK6>>gRU+xZfkE_G}GIzCkJa>h=il566k1Jr7 z6qTSVle7|cH?LQ#9BPs203G%>k!MA%O-fs>Xn|!x$7Tv0sUNEA z)RpS>>IbdnXpY#bO3Y$r5AzRZKXZUN4LnoB)G~*eB$Z6PHr96RTm<|FCOg$X;$zAxoAe$>M>R^^nENG_nkW zn@*mrJNja=Pj;(sJUMPgs|J}WrWPEo3BwB4#L{njr zgYTnO_v7R7RVMK17DGfhuQQu@$z|t7!7hkpf-wTfdytF+c$zD{->44fnr)6OfPs(j z&ibj@mR}06%?{un)ocsHJF)$0fPK-1Qn9Qt9=>?b0N4v6`$)ej&jh@it~;Gi@xGET z0(iI3>3p-+>3p{i<6i}+F*|RyE+F6TH_rjV;t z3b{hj)_EmZZd6OU%$8mB-?!~fR-fb0az5nm# zJOU~OjD~WC>I}4sVpNp#CHXS-H*iQxP{%1G;Wf-*1~3E0zbIY*^~W-0y#}zO;Wo zrtm@CtN+xTR(corK34nVq`i@khIFY{&yp>Bc7wN_>-_jZ_O7o6^z>Z+g?~m-;Nn%o zdnPnk4pwvsK34pFT(bE2;w!=D{_eOvdEly-S8^)mk3Cd#X~` z3&!*i4sGqd(r1y4EEA zGGYF-`bX+r6Q}%YZ3ul3RCpmWbM2UQ&(G?op6;`=^6Oi72Whi|hHAH;Sy{R4?EBlZ zqqb;{R}T6$@8RC?(N|9Oj!tXiAG7<76Uydp>~`02J?8Pug>z3Sa!xFL^<`>k-v~d` z;@9>K{#(tqrF$~(8YTp-I5ZS1+|37f1IJRFdnG7PVeJ-H#_J|d*YfJ|wGHQ+w#nd- zmm1C0GvWv~z;}C^nm<@Ko({QWEU?(ZnAz!ij`ogPP%VZW&FsH%;AU0TsOVan4(m|X zBOq>h%3q(I+T?vU?nuP(=M2oQs#t1xX|l~~*FN%b(3Vzp%<(Q=hjT=XCO$F{B}j-JBgfH_-Z9 zvia#o>V<{&e3sNTcgLhP%fCCLT;#iNdj1+V&tvztx2heFerKqlCzZA}-B*+_<&WEW z=qqNl?=VvH!`x6-Ngdvnecn{(w@F>69a&L6R}(dXy7=Jzu&8%ypTxvb`nYvhr#;iW zYF~Y};z)jI^%9k3Ov3M-^aGENf7114(AtKsQOV`J6D(5`A@BCxuq8*jZ`$bu=jHza DNg__S literal 0 HcmV?d00001 diff --git a/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/pdf.jpg b/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/pdf.jpg new file mode 100644 index 0000000000000000000000000000000000000000..809b5e605e76730d02b0e17dbafebe7db8bc1a87 GIT binary patch literal 3705 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 literal 0 HcmV?d00001 diff --git a/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/png.jpg b/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/png.jpg new file mode 100644 index 0000000000000000000000000000000000000000..f479380fb0db7d03a6580c674582f7f2fa9acc84 GIT binary patch literal 3754 zcmb7G3s_WT8vf3lb7m$kb3p`UL=T9~{v3fgYcF_8<7qJKz8Q-~aya ze>vm$%yAhc8L8>1KoA6^;RhU71c%a-lb5RVRH^A%3Tyxn?A4gfdL9E{Fxo76$|R;} zaWNz41s+TWPY3`{jn-;TRI9T93&-W2 z_zdIbUTI0o8^MiQjbb6<5R7-4ZAn~wCgQK{RRxKNX94hh$}On{!+hSub(Q&x5c^@g zOlM2aABoo)OLJ6+u`h3Tl_`_U!*M#b)@1Y&f)QV=WYf7dMm;2yu_+3~vk_0Nw5N^a zCo`-y3%R&6PhDkl4r0thT9#=t)QAHRueX@;xUo<(xtrB1xv?-m*LQFMtu%9 z7S5Lvu~z3CF()}-tIWrJ%JrpUZI=9zzEp9!E;W6Gzsjt4?nTr_?XlSNIBl4p>e5&g zO2n9ly2Tm`INuP{lgczHoVO8(AAv$b11y-J6l*OQ;Vv+c2TDl7rx`5RQVu%MV}!+4 z79%>s8>%pNf1cXO8Sdj|R5*JNaJ_Mq`*VgzxIV%$QT~*iipKx>R2CIa&7d>!@@%Pc_(aWKKsRBy9??hq?MNYb{H4+K)HhL^bYNn%wP} z$2DWrY#QqTSkZye*@chw>4Q~AC%IafZtBpZpLl(+3RJ)6FWpZM(A`+~(ihzQ=|1`b zetIDhS3vJnWI$Cq=So;zyzp^zXh)_EG+2LuJQHdiRXT1(%Z-}?+%23F>@zt( zqgSJ@-hV9a1n8gumFQqOaxLg8=dclKG3(fKGNP24N<~uXzuL9)xV=28g0JAG@DqXI z&*I1NBl#H|9zA*dP;86CTH#VZd~#fjaWi1Yu+SA(o^a=`7v8&9o|=h%>Z{B9F9A?9ge$AnEwL6alPXUSgly0D+kEV=5Bou0!{efMU5{5P8$&b zv=akl5Hc6eBf>^FJb-6(K#g#?JD)4uU5mX(p1ek$i&57|y6_T?>bM6nDzi;z(ABYJ zOld8Xp;jmjI-`z>j);qhig+jsy|l3wqejojS43)}*oPwL#X0&Q8F*YFxr(NFq<~Ke zNKzo6X^JltNTou7Q0U<)^75GA?I{#`P4oAbi30-zJ-nno)5Ja^aiEw>LeMlVAO+qO zhZ}t}8Xka?8&h^Yc08H%&a_hP4p{s#CYAUml&Czi5Zw`Ev?G%H6(O zL!B#E+?g@}WMD$%!&!G#nHhf9x}zeB{?k%$Hg-oE{&0bgL#wZ1I(Y^Dot}W1fqaUHhr|BkhYD z{9d=0?tWkPhpqKRp`D)$eYtqsrMYJ!mS3K@Wmfn5>XlE&-+A}-!invM#)6iL_Y;WZ-yrZt3G*aC z;2siq(A-|<3W26XQnb{^5+sk!-Mre z*B(3g;khE!hi&&JzBbDNky8g+BKMzVgPrRJH&21?MiUWfbA01REhYWA-F&H;a zIv4wn@_C(XNmEBm{p)A12Bh{33_UCR^vLaIn_WQnJgd6WSGw)H)SjMZiG5=)w`QTZ z_Xv{5Cq@kiLJC2VxrrJHBVW_dUacwRXu$@D;xYOf%;;b`)eOP?L|w#EAOeEZ(joSoTW;(^w{ z?<1a5nW`JJp6^uTp8Lz9)qn30{&@78!o>rk4YGxhd#mtpcC2{Q(A6{lJiq_IB;Tq- z3m^a2-pVJQL-EcN?Yt-PP`eAy(}~wkVel4yfk{4&w=RR#Z){a=FH3%JFFOh7EE-Ew z?o&;G6rGhPYS!G8FxBk~N*Z>(>2g-`v+stm%=(}O4IYw{UIkO%p7+bN&oAHWVx(au zr8(=TzM%J%0@HcwXx!|*zMkzj3%ddieJ1(3{Z6rBk4o*=06k5mD-BP*t&@=-9_!zi z@xo1U$K|*DTkS=J_~lEXf4*UWq4iU;!~xf4bS+qW=#;#*_pSG;jCS7qn zN*&zKK3O(7yJFM7L%h$QnV8vMFrhI-)}JuB-0!71GsE}YI?~^68Bizs&}V7$t6|L( s93WA~MXQ$!D&}N$h9zznl*EKBIp+Cd1JAd-bB$CxC3kX^sov51KS1K1&;S4c literal 0 HcmV?d00001 diff --git a/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/ppt.jpg b/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/ppt.jpg new file mode 100644 index 0000000000000000000000000000000000000000..b87590a2b8d7796fff1aec41d704d499337364ee GIT binary patch literal 4035 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 literal 0 HcmV?d00001 diff --git a/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/pptx.jpg b/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/pptx.jpg new file mode 100644 index 0000000000000000000000000000000000000000..62cbe2faf4eb2ad4ea9d5ae0fdfa114d31048ef9 GIT binary patch literal 4089 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 literal 0 HcmV?d00001 diff --git a/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/psd.jpg b/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/psd.jpg new file mode 100644 index 0000000000000000000000000000000000000000..312af5c8b938e172c7c61b6c461e6999bf027619 GIT binary patch literal 3859 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 KZjXZWSN;#Qw(cPS literal 0 HcmV?d00001 diff --git a/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/rar.jpg b/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/rar.jpg new file mode 100644 index 0000000000000000000000000000000000000000..6057cbc5447e64c29d3c4017f7464d7229973ca7 GIT binary patch literal 3387 zcmb7G2~+^_;jw zt!Tocsi)P%Eiv(g*4EQl>vEKcL~E@Jbs;WQYjdzt>vBTVMl=2In_++)PjYhS%zfYd z_q+f7{{O%CzHwc1-3C=&wmusuih^AHfa|X8kY1}@WH1(G>+^Lu03iF=R9|nSIe=Qb zQ!wUaa%J=8bFx05VLbRk2>6;Tj`|FPAs?_2E_se_gI54O0rbYbcziVbJHLD@c!vdm zlB2z@!eOaJ+yo%8S?UERfb<^PQyQK1h-E)P94Meb#2SLD+&GJ1vm2L*oD!oJIYg_{ zQf;b0yaI8od4#=c1a@mc2Kve2?Yv;Ma3mK7p{~+u6~qG#HKiGdV*u!YN+G+{&8KHHSC`C1 zJQnR0R;RwiV{f*b3yTorTzYp+-7MmVa86qsTFfOxAih=2>q(7K4+9l^mJV?&;?U}b zT#tVy&#`Pav5S71tF?uQ(GMdmG36N$hampBP-i4-p=M?`Z_6QTp?{{Q-f8e?VEXO0 zLb4Xd%PM(?7$f>*`kmD!xKGJkcA8Tt@yuoCS6Z|69{!4Yo46NI8~cIKU?kemKYPI> z=yDLFANC1vFC}?HEE!i}$|AXqNBla>p-jL-9hkAVfE}I#2S&(&OnlaZfFqS)1shs; z9OcnsrTm}sTFr!MG-A`uYDlg`^SGe!t)Um;=hE2lnYivF{lTBe$fn(Fy zboO;N3$3Z_YhDG05jr`jg8Qh{?Pn=8;L1eD9LQ`7X^8gD;Z_Tatd{ewk5J8Uly$@7 z=*Jr|YOWiZ0dQajhN6obnWxWJ93AH!;V!d>7W67UUjaowlwZj`Nx$SW_I;8Y!}BHA zB{%TX2N_rao2aN3RawPKIJ~^LQ89EO(+MW*?;x)ZwGJsARnba&TgdPT$ppW?aIg?o z#|~RHS2h3AT-NN;e4u$SYK>u!qq4+oW$C(~xKXb(E^ToAy zd-2v@jF;F*w4@3{>y6Ac4>o0{a)L5anWYRgmz5C>N8KWZLN3bv}UO#c-t|NPu%wC4NZK#`f@=f^e z0MOReFBhy;)lM!^qj{Cfz*ia1>Ft*ISk7d#apI7J6L<$NEaNNUfxHLFJbjG~S6pI{*$%vor|H-2U*zdk(-+nUpC0rWBcY zH{Ei%p5lEa>i~G(?s9#z+vR$`2mRjwIAL?$ft9)@Yb8KI0lD=-4iYK=FKT=l5N%Wl zNJI>fM@{fzBNgr8&;aYLzlSpVrCS_#| zBa=xatW+*jtK~Ae+{ag`@EPOhE0-%&3O}X)#EBDq6zYI5{{Y1P#0e#lNMwx6k7fP* zedIp=Kf1X-1GOC9fM$k@09s8kYRc6O6UcuchWtVDHky*kk6D{VMGJ)^%ge_ds!D z-rEm!w_39vmtXDfJ-9UfdiN(=HdHQ2hjXVkAM4+?;eKJk(VCxL{JOQ^-ue{ZBqK=e zv5aCV5B8?5f|t7qsZW*^ct8r`oND&zid1j%GiIYuVI(<|=#CPRBc@n3I6Pi~LDjr!JZe_BOz4^jxNFAP_$xxXdr57*u=1TP}mU_PGYna)^ zc8*ic=(tvyyUJO5l6!Rc_NCKZjoWnx-a1&eSsH!m({k19sQg@+-{PL%g_OU#pnYX) z^>-ieNE2fl%DbC<|DZa Mf3yBi@TRNp|7IcnbpQYW literal 0 HcmV?d00001 diff --git a/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/rtf.jpg b/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/rtf.jpg new file mode 100644 index 0000000000000000000000000000000000000000..122d3825b90e6a38dc8f628296c3a45ffe78941e GIT binary patch literal 4081 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 literal 0 HcmV?d00001 diff --git a/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/sql.jpg b/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/sql.jpg new file mode 100644 index 0000000000000000000000000000000000000000..73485f1521ba06efc0e66d441cb1b9994c245580 GIT binary patch literal 3766 zcmb7G30M=?7Cw`iEG!M62#6vhs4M~viXejQ0oh~3Em|dnfkXm{lR$-H>-MzR`YLMs zs#c4LU6Izh6t`DV6t&_;tp%5-wED!YwN|WE%sUf8fPQ}M_bzbfpL70u?z#Ux_YS5X zOxM6MB{4Y>2!en~_yeYPVSRFZ{9KtlGch?$iVgtbCrZ6u%cB7bi;S#1DUO~oQ$Y(` zfd_-Z4&1>`sWRweWwJED#&Nl4|JM0EU?hN+z!&@bv;XvFm&+Jb0E7tbx?F>*5b**4 zzE-7YjR1n5&_4cEqaLwvC}L+86GSZGaDF#V;BZbio?+%>$>Wj3nzk-F@VqCMi4a45vP%tGGpT6AM z)$Am>1y`w*(kX~Xp#8Ys7{}R1A--E&Ff|sjKLBq)9-BC|o6n0ZQ)f*_?1J`OjWIdP zVlOMo$;d>EV|mpDx>PO>$2qPt#G{trh4`wPN#^z#^C2OZNsuBAKs-!cJjoKDOfi&9 z;q2x(W$O40#2ANU=P6TUh}{vt$?D|XT$nRi&1jRjxiCI?OmCD~av*ONX*0OFaJ`h6 zF__ngG09s-br#ksH$T=u#N4PFwph;PhViMhN>-YL7~@dC zGDTB4-4OHLa+L|3wn2!aU>czW26T{vy$Xt;3uur-62#$C4=j4}Km%H|Fz98_q9I;_ z0<^uDCo^-p$MiDt&7*H|qj8oObGm2fuyAygDuGf!otSiQx zb$t~811iw7y1>3VHI*N5vwG+YRQ>E0`=)Zp{5yU5Kk;wzFJRxwzuY^Xe~Et?e_A0H zcR*{-s1UQ#n0LZp!>wBk7N5V5y7LF_3WDNeJpXtAp}SUgGWgPtMQebe^(`>jO-Gf}G^ zRbM<8cLFpp6*JMmtH@HA_=2o@l(do$wjK509vWl(q@-|W*Gy+mN2T=K%L!i#hX=4i1C)is-T7SO?phpedGe}wRz_JBX~nZRs_8j|Wa^EYLQNTyOXrl* zDKcqNp{7Vfj|~bB8WS`w4Yf2fY>`q+OBRHN28WH$9XHl=3F3jrHInQ2d>$zjP(qRv z3i*6W;N;-sBytdmYzK+$Z3hmv6Ny|sT?Y?w@bK`kwRiHSJqCz9JRGLrJPqJa+ocQYLZClSnoGLrBDo)bYj5vE2MipwX>zuX$ljV}<22$HfvuQT@#QvYUZ z1A836b0i&6y0`i{ZQSm!r|(_zJ@VE4!=9V&jLSu@(KYI4LB)?3BjcVt%{g86ahv}& z+|z=iVFuMx<-D5}vL}H)Bc^|(T!dVo!qWPK=MT~-b|ZK@0>K9!L2-L*ZWQoHzJQQ8 zI}IGTm6H)ef%Xq2g>{BvW_mS8o$Kb=JO^)_OXmpYXiRZyl|@UV`IYQ{rOV2 zta}p%iA@3 z-@W?&_N=s9A>)C8)`U4t&iYc6kA zbfu-8c5d-6NN+oH_;jG(AF)SHhW`-dmnJ*2I$~XBo9z|-r}?$DnKw*a^^M}B=VR?* zt#>y9oQ4O-Dz```FRq-wqXFyhK~Dij4}b2ub@bzqB!O?lP6xHY<;sU|CjU6AeG~Do zSqGj!vRRrxp|I`^s&f7N?M%tS@GBd(&@t*ICWxsON4*ylw|QCuE1mOuKxoa<3jtLS zrD>~MyXsnF=Ti9c<&6#NW7eOUDbl|3)Mt;KDrD7CAK#5ON51w>SbO8Q6UXAS&oy`q zS9N+S-5#y3cssICx9&fpI)zR?Pt@QQ+j^p9NQ$yqVzZh-&j}D6Dcz<5ZUf$4*wxUtH<9rQsL)K}_}ztL~0nE~gJT zjIPrvsvXMSHx70^mH9*EK61%2idZ=7_geR9XVcn#e&%eu%ei@<-Fzl&TSDzush>TO zX&T@ADZTXE!cTX3PWE>5`9v1*?7L;QBR>yQ#Ee{?TitQqarL>p=GhMl6hoW*SFNZL zjY_Ldok3UZtvFRloVi(3FaJZjvfy_8nr-{1XS;T&ls<3I`SkUBO7TLS$;b!&|k2jxF|@tsNO|aaXRr J9x=t#`ai+~z0Uvu literal 0 HcmV?d00001 diff --git a/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/svg.jpg b/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/svg.jpg new file mode 100644 index 0000000000000000000000000000000000000000..f479380fb0db7d03a6580c674582f7f2fa9acc84 GIT binary patch literal 3754 zcmb7G3s_WT8vf3lb7m$kb3p`UL=T9~{v3fgYcF_8<7qJKz8Q-~aya ze>vm$%yAhc8L8>1KoA6^;RhU71c%a-lb5RVRH^A%3Tyxn?A4gfdL9E{Fxo76$|R;} zaWNz41s+TWPY3`{jn-;TRI9T93&-W2 z_zdIbUTI0o8^MiQjbb6<5R7-4ZAn~wCgQK{RRxKNX94hh$}On{!+hSub(Q&x5c^@g zOlM2aABoo)OLJ6+u`h3Tl_`_U!*M#b)@1Y&f)QV=WYf7dMm;2yu_+3~vk_0Nw5N^a zCo`-y3%R&6PhDkl4r0thT9#=t)QAHRueX@;xUo<(xtrB1xv?-m*LQFMtu%9 z7S5Lvu~z3CF()}-tIWrJ%JrpUZI=9zzEp9!E;W6Gzsjt4?nTr_?XlSNIBl4p>e5&g zO2n9ly2Tm`INuP{lgczHoVO8(AAv$b11y-J6l*OQ;Vv+c2TDl7rx`5RQVu%MV}!+4 z79%>s8>%pNf1cXO8Sdj|R5*JNaJ_Mq`*VgzxIV%$QT~*iipKx>R2CIa&7d>!@@%Pc_(aWKKsRBy9??hq?MNYb{H4+K)HhL^bYNn%wP} z$2DWrY#QqTSkZye*@chw>4Q~AC%IafZtBpZpLl(+3RJ)6FWpZM(A`+~(ihzQ=|1`b zetIDhS3vJnWI$Cq=So;zyzp^zXh)_EG+2LuJQHdiRXT1(%Z-}?+%23F>@zt( zqgSJ@-hV9a1n8gumFQqOaxLg8=dclKG3(fKGNP24N<~uXzuL9)xV=28g0JAG@DqXI z&*I1NBl#H|9zA*dP;86CTH#VZd~#fjaWi1Yu+SA(o^a=`7v8&9o|=h%>Z{B9F9A?9ge$AnEwL6alPXUSgly0D+kEV=5Bou0!{efMU5{5P8$&b zv=akl5Hc6eBf>^FJb-6(K#g#?JD)4uU5mX(p1ek$i&57|y6_T?>bM6nDzi;z(ABYJ zOld8Xp;jmjI-`z>j);qhig+jsy|l3wqejojS43)}*oPwL#X0&Q8F*YFxr(NFq<~Ke zNKzo6X^JltNTou7Q0U<)^75GA?I{#`P4oAbi30-zJ-nno)5Ja^aiEw>LeMlVAO+qO zhZ}t}8Xka?8&h^Yc08H%&a_hP4p{s#CYAUml&Czi5Zw`Ev?G%H6(O zL!B#E+?g@}WMD$%!&!G#nHhf9x}zeB{?k%$Hg-oE{&0bgL#wZ1I(Y^Dot}W1fqaUHhr|BkhYD z{9d=0?tWkPhpqKRp`D)$eYtqsrMYJ!mS3K@Wmfn5>XlE&-+A}-!invM#)6iL_Y;WZ-yrZt3G*aC z;2siq(A-|<3W26XQnb{^5+sk!-Mre z*B(3g;khE!hi&&JzBbDNky8g+BKMzVgPrRJH&21?MiUWfbA01REhYWA-F&H;a zIv4wn@_C(XNmEBm{p)A12Bh{33_UCR^vLaIn_WQnJgd6WSGw)H)SjMZiG5=)w`QTZ z_Xv{5Cq@kiLJC2VxrrJHBVW_dUacwRXu$@D;xYOf%;;b`)eOP?L|w#EAOeEZ(joSoTW;(^w{ z?<1a5nW`JJp6^uTp8Lz9)qn30{&@78!o>rk4YGxhd#mtpcC2{Q(A6{lJiq_IB;Tq- z3m^a2-pVJQL-EcN?Yt-PP`eAy(}~wkVel4yfk{4&w=RR#Z){a=FH3%JFFOh7EE-Ew z?o&;G6rGhPYS!G8FxBk~N*Z>(>2g-`v+stm%=(}O4IYw{UIkO%p7+bN&oAHWVx(au zr8(=TzM%J%0@HcwXx!|*zMkzj3%ddieJ1(3{Z6rBk4o*=06k5mD-BP*t&@=-9_!zi z@xo1U$K|*DTkS=J_~lEXf4*UWq4iU;!~xf4bS+qW=#;#*_pSG;jCS7qn zN*&zKK3O(7yJFM7L%h$QnV8vMFrhI-)}JuB-0!71GsE}YI?~^68Bizs&}V7$t6|L( s93WA~MXQ$!D&}N$h9zznl*EKBIp+Cd1JAd-bB$CxC3kX^sov51KS1K1&;S4c literal 0 HcmV?d00001 diff --git a/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/tar.jpg b/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/tar.jpg new file mode 100644 index 0000000000000000000000000000000000000000..bb5adaf98c1aa16496d445a1fd43cb78bf126f33 GIT binary patch literal 3346 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 literal 0 HcmV?d00001 diff --git a/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/txt.jpg b/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/txt.jpg new file mode 100644 index 0000000000000000000000000000000000000000..c2fe0e7c6934d35614774e055b9079361c736c03 GIT binary patch literal 3804 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 literal 0 HcmV?d00001 diff --git a/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/wma.jpg b/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/wma.jpg new file mode 100644 index 0000000000000000000000000000000000000000..9dfa9fee6dd23939e537b615a6c28e09734df3e6 GIT binary patch literal 3461 zcmb7G3se(l7QU02JP?S9pdwftMSQTphUdajOCbad0)}UWq7ae+0wIJXC{R4Us?@r^ zYt^bf&DNae8VdbY6D7PVS;mCfEiFTmr`vv&?NU+(?>`+xWT z|NMjXy7eYVQj(NOKv5J-#|x~tg@=`Ld7&zEW|A^hfdK$vv)X9X^H_jNgT<7YoWRb? z%V&ihz=KiX4!+>7)|id)Dpe|=5iWTSw#U~1GXY!;d2xI&`?+84TF$HiphW1e(wa4u zh-(4(dX3R!0TA3lf6P3K5wUPIVs8@)L@Xn?)Q%GgF1F)YHcob?963a*SW~9fB5pt& zTs**EIsn@>AOrIxa|X_&)3Br$DpOU7PS4o__S-AM1DG#^mHHa2*=GKD_b^vv&A{g* zQhS+cdZq(!*Qga)h{vP6}3r`j2QDU z4>&^(=^J9ck5-*XdK-%Pb;zaEz(Exh<6Q#==mQoqAsG_zX#^8SNrt@t%TXd3mH_yNn~0;jrUu~t3s_#rGr+q#IVMO;GAz@uQ||*6U2Vv0CA#tj5tu7>SD3tk>W7%bn!%t__@|i-ya`Tiw^RzSI(}! zcrNk==pYA`=wKdlP1se^VFT1*)`9PdLn-6WgfYtJc5MvV%T5&ng&ei!f&cfB=w*x?4Wvnyl zO3N&4xJ>p3HXc7^9IG^FLW5bgUeDS>X4b@+In!KD8w%t*NX7v?%(Q*qs1cX@eU>zU zX+Ptcb*0~zUjy)&8DL~&zi$$riNpT{a5!31W14HvhacW=0n8;4;kMtDM*^NrT~_Nu zJg8Tqa9D)cAkq-znymBw+PkxUx=J(wCE~z^_-S1u47YF zisVY2LB~df#)gK6Mx|meEu6`q*0Zu&tt>KD8>7)$Z-5+l#AtHk98?FhY?JYP&_^#M|m=g=g=XdA%yY&ne}Us zir_7%r>SwklTx&lvYvv`SUzeZJ#d=HO(4YCXpDN3e~<>7^#|}kI!{7Nuyu{>py;J} zl;66I7Xsc6I=#y8_oT@qB7$!3`V`*nID2Eh^uhjny!|Ht+)jq~sAm7NIi*ke_Nt_e z;wW5Vn-N6;5}+8o$a30^541qYP!d@bPwF*NRfG~mD2(Fso^9Xs@AV(HQEW4o{Zk+-DN7w-F9a8zUxK$#;&@_7b1N;9w%-*(=lgBd(20V4nA1j z6}|al)c37vKL$S1b(Rk|1V?XM^JLG;FvF7k(%|+PiqN}XPW;$=cWUU)qodz%_FlBg zf90N2*Sh>4cL};w^Y7((eONRiP-8?IFxKKRL`c3!9aw=!w?=&dOw%yPHolZS7G4FwCY{aJf|+U~?dq1VH< z_!S(SkR?c1d~O6ggU^dumS0d8@RNQ?`pM7z3cgz%c-=iu&>Xe9z5K49@yO1}S!=H> k&Y-7EOUd6U?tV|?Kff$##R5f0{m`YS=~3GnCR#iG2ah8hu>b%7 literal 0 HcmV?d00001 diff --git a/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/xhtml.jpg b/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/xhtml.jpg new file mode 100644 index 0000000000000000000000000000000000000000..3420b3359ce45ce5defb7c0ebccaf9eee669ce9b GIT binary patch literal 3653 zcmb7G2~bn#7CtxkCZrHTK&uEY*9D=B&;YSQwIWM^AWPWXXsaQ)KqLvtO+et`dy3Yj zIx5;eowh3A?%4W7u`aEORrI~Oj$0A6ZgjL&Yt?7#Li5g_ga93yUR;jjFqeEPc zctk-rdr>#+)PM|(lgyboUaw_IE!2Ezq29nb9M0}9+})Ue291U?%-PWfVlT0l z2+6&ePsw)SI;}>TgLoL)kDG1r#6BGHy|R+LIK-g<0>45&DbL9ljHxQlort&(+I4!H zD%WMNG8JTGBF3?ThLY0pBo5&m*IE;>mM{eIwPH?1))@8BpyLvih({nESX`FkichCn z%X5g`5vQs+AptCu&S-dLGGdIw zJmO4wq;80X{yI$}scksou`q$s00*T|fV~z>&;cxDLo&qU(+oU%3PBGBv~cL<(4wcj zp#*KO=BXVV=a?==kz@27G8$)jHOD!_T^Fa6>C4EODEy9Q(wKLcXeI_&CYBk;jAath z8pDisD^PdS$wCp_MWxO-7AV7+iH->nzbv3E#65oR zSIf9lt3_Jl;*$?Dofa zUwJGC=%}^ZUo_b59qTau6@Wtq`wf_-tk4$%q^FZxAH*P}{P3d2mjTg61%S|j0aB?z zH_oO)TpR(wd_6EO4!QG5BX=#1c0C1k0ym?oj&|dGLbd-6icGUjZ`4bM9Pl>PJARj-1Nf1gP6yhjvhVl0C6nhfJ|JUq?!B-6V zP(@QiK;TQ!zLfn4^e6v;P!!3~)jTL#C>Agx^!6ryka{-zWsuM~L`KW7bPH$o^cI}! zgG)*a)!(1!D9S$-TlB%)_VQz2^Yh=huUPyka=*`CvN&r~LZ9M`-p^^)Ihe+o2FgG{ z!gdLv8G%p)l)R668qO(3C6rL`vZZq5#O?pRc+0qE(ePvEyw>&0Jhd5S>Hbi&)zrIk6U7RCkC@3Zzuj3rulCFl<85J3#-RG&5B{uQ z_>u4|cy4+2x3|AKsMz^ST_a!fFrV{Z`FFq9ZjS9}T|PHhHC>U?-)PnC5ABGWsn}{U zzZlzavMFfAiWy6mEKR%AJaMg0(+)}9`^z$R9qd&yapgY>_V&7Q({KH(`F>Q+)GRK2 zZ{wUVJ_(!@oEw-^-Q=Slp*^u=^LC%wBj+Nwzc!`*y^}WwWIfn?_2r{o`Y?6W%$F<{$!VuZ7ln%ZR{Wn#Tp9)6hn3HVyy9Ch=`NP zvuauOG>v7pyS}m)?E2N$m#n$Hrs~2jI_aMOtjs&NWC!*=DcKqRFHc2SCI52Blk%-8 zx~y70`bO>w^VyK|9u*;Ni&|37)gSKjpIMdG>_;J!*681UviO=YPY#J~n&pd*)_t`n z??AdaVPk#k``5&hek4`Y7~+{ku`YSCld(+#W%xf2$ z>O@atn)BKOFJB(2_~7j2$-8CBpi^o6UT*oPW!dS_lBgqT+cvzxi<8-e{4G&JTu_=oA%cK0giBoivR!s literal 0 HcmV?d00001 diff --git a/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/xls.jpg b/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/xls.jpg new file mode 100644 index 0000000000000000000000000000000000000000..62e21ddf236050f1c0d9ae46b96d2bda00c2b735 GIT binary patch literal 4183 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 literal 0 HcmV?d00001 diff --git a/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/xml.jpg b/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/xml.jpg new file mode 100644 index 0000000000000000000000000000000000000000..7b2d75b9ece1ca16ca87b4be2b2ce76566ffd7af GIT binary patch literal 3774 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 literal 0 HcmV?d00001 diff --git a/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/zip.jpg b/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/ico_dark/zip.jpg new file mode 100644 index 0000000000000000000000000000000000000000..414d5da6fc4e3c926d0d2c3fad61ded968eef4a0 GIT binary patch literal 3372 zcmb7G3se(V8vZ9UlSBw1AiluLfEtli41ywyRzi5oBZfzPZ8eVpQj!oR!3WD$+Ox-& zszRVppvmZELNH?yC5}t*-92wxznh+EU%tF1xz+tX<9icM_7&aOa!< z|L%Xk|G#(cjOPo_4Nw*47UTj&QIL;6@Z6FeD$wZ`>J6p21w}dN0Fdo8I-NEN2Vi%& z1w&pIH)rlVPSyhw7y+RW4WUM}%c<4tivSzplIy_s;4{ET0G~{JvVS1^XLq3%-em@$ zw1^V{B#~7@ZiSaGnci4a{sQ8m zXt!A11?4__qr+5EiWtXA+H31(kvN3YZFcFfmJpBlS`A-7))@8BVBxcK5Kllns-_{| z7oRS4EiNN=F-~KRt^_g0p@o->g?hx%h+h}#3}i0UOtCJ z=E8g#CGQe*#F+GLcTG9&Q!K4j87J{>3{gNZk;#!!5>aQrjfN&qF0;1RmQ6s=x|1wD9QV z(PE{-pcZXU=IKR_cT9j$EsnlTM&m3`=6GkgjhK z8KdU9;0k~XE6|_a#NaxeZ8|#K@8K>phZcOIINJoJ&#Eu`HG7-AjC~J#H87sN!d}H+ z4`^`(Y@#ANs%O-`Cpgtc_@g2QOzG)q&aO-(lO$rjHQ(1CMVK-?{JHQDMMPw5cqHO*5`-VqayPAtWZKf(xsTH{+0O4{JGgbu@ zsT)~lZ)4CPRcY8Esgn4VC@wBjkLu*8nPMf6)TbWz9;MHhR-W6vD_hNE<_v1tS8}i1 z11YVOcG)vWQ0wUz+j`r7>aAFasI_-{MwJh>cgJ*mQ}G|ol>6h`M;`mU*kDU3J#uIF z_Ax?ZU)m+xbyAp!pn8d7yi;Q#XHvSS5G4JCi7NcQq?tj1bSS)!U{sNV<3?+eC#MRo zby4xN^@c^JdS6!3nUenwOU$a|)AH0!zg6^PSM-Jd`>nb}B?z&RD_wb9~UifUn z4^gq>2feE}kl0}``>m`$HP4x*GE4{oBPX{nzn;S>Nh(_mv(&g z*6GwodmGkoJJ@oic6HmOhb!79Q6srunQzqqV&h^IG_th@w(?;Ko9^F=& zJhZHO^Kf>`$=ds5VaBL%KLAU!{+dt_5vNJk&Q{g;W$KNuym_;KU1r8Th<{=KnnPjV zuif_hWnVNcS^3=J!Ldgw(ps{Yk2^DeRBP{olPj0o)d{~iaN}jw2KRgQ>sM^(nsR>1 zTcP#MW507u*IBvg#?o1%ZWX~b`suD|a1ljiMD73!Xlj*Z2gJGYE~`}p>aO+~GXR{z~z IzQxn?KLAko>;M1& literal 0 HcmV?d00001 diff --git a/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/info.png b/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/info.png new file mode 100644 index 0000000000000000000000000000000000000000..6baffc3307de0704eb7a515da29edaeb2285a9aa GIT binary patch literal 345 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!63?wyl`GbK}W`IwK>;M1%flNApZDpIffYvCL z1o;IsFbc9U3w(b6*6+pN=feL!+-2uya=-t^$CZ`k9p6I{4xz{VNA|e^Ro8mDIEGZj z<@Ry%H9K&)9*mqLS-M5(SCp4pC=vRg^dro%TLIC+vyZ=a0{oyPt94M=4aF?JzVB} smLt)m%=R{;CG%Y6IG2Zkj#)pSaF&L#uQ=J&=>-ZMPgg&ebxsLQ0GQ@qmH+?% literal 0 HcmV?d00001 diff --git a/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/key.png b/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/key.png new file mode 100644 index 0000000000000000000000000000000000000000..463d08262dc74d741461f60e6643339e03b5f6f2 GIT binary patch literal 185 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPGa4)6(aH8wW>|NlRb#00EYOb-B+ zag+r41v4-(GO;&oKBK<4X)jRB)zif>q#`a^poM8q&xQ~;HUWXxFFY8!T}n!}w6?Xe z8KiKOG&oq#xOguxkYO4ZM`~(90#HF}Vp3W{0*5ziW}3<|J%)flF=6i3f;6Ck44$rj JF6*2UngD%zHDUk& literal 0 HcmV?d00001 diff --git a/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/label.png b/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/label.png new file mode 100644 index 0000000000000000000000000000000000000000..fa65317110b69e3e174d9c885e191cf79aaec208 GIT binary patch literal 479 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

    j18u&F);XYTzQ4ESARIc40xcFMNx;gYyfz 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 literal 0 HcmV?d00001 diff --git a/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/processing.gif b/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/processing.gif new file mode 100644 index 0000000000000000000000000000000000000000..7c99504e10b085b4d083e7473df26e4e1f4ecf18 GIT binary patch literal 3209 zcmcK6eN4z}Q2rbDSRQTqiegkVMdcOh*)yl$90>MUHO; z$`puTM1;T!MiGo+m3fqAYLQvxXtjzut!L|YXxFvO(^-ylmi4qdoVq8Ac4uw>ME>Hx zocsO!zR&Zxvt0|GTSFoe9Yl!B<~B4nTzL0_!{wN~HyJw=vs$d>FO`q~c|5u=8u&$E z`rp$d!y^Wr0TW~4*6`T%v8gYo7Cpac;**Ks+TexJ3tT?e=kZNFn2Ha@)1OMOsjC_P zXgt;*3#<-Ie=|LDb|lgsxqa*Q!-o&i6ZkVfl;k+`^X!>Ro%83;zjs-6o^)Wvce| zZqW)6eWXI%a||6<_iJLECXwi6I=XNFG6NgG=#Yq4NL#MZ@>*%3MR=0z)YW;K6q>plt6OP!bKnhyus2S=!ILt)->zn-N}q+ zGe8?u0Syen(?A(O@=4I~f4jK7GAmuT%f$-Oix-9rsQwGX^R^x=-(%crz4R;MJ}y>l zKeUvUQop1B#KpJUwuV`6zW6EkX(G#{saf9Gt9M%9;sk*8foPYtGYPQrszc3jFH3UMy z10i6WSr7in#T`kBoH?VJ3qz?W<$=Ls>$@?}akN)(zrWgu+foz7K zr7WgvqXtKoTvk)m*p#MLhg=lWtlPn;D^W`$o82DiDtf~%)*$h2M{{gIrKa7a*sRZy zDG)|DRo2SmF4bF=0*57HW@x?OXh($aAp86WNS>d^rEmD#3i}jf8Y{vot`u=ya!Z*m zqGR-Y;?8o;4Gm{NIg72#eN18d4#n06$She3h!$c74M;9o4H!i*z<>zC1{Me#Vopr8 zD`Nl%sRKoF96}=i6B<P!NEHc7Pi&&J+lLcyZ*v6z(Og_pC1| zn_pPJf?R%h>EGjRsB$~+=_8|?4Q^CF@aBn{ofE9myQg#h@zwPG;5)qMZmrK8MrO6PEVU!6Gi5$LgB2Rt3I@0tB_!$zU!vV!e75p*n_mf zA-hbeyynY%Ja&JW19r>Z$;6oIkHKyM3xI%rz*Y+|VeIen~i2W>60 z+|K$D;&i}^PqD0R9ekZ)o=aI23sNg7k%8u=)n$td8nex$#mtBmip^fLFd%GI1Qd$QM2i&~%O*oUNC zMoth~rXLBn+r^l2_O5lvR3v^)D6cbK3K;FGL60CHIORyetslF$KK4lcPCc3$AYypU zurMHH7)nqE2r)6EWEg~-NE~)RX%I#hJa$D+BOuwEbifLD8Nee#mi~TETclLyNabIlb4}{ZBp$rtyd_QztL)1 zX-XAp#QmX||IonEkbV!^+vaPJoH`TY;be}~${`AP#%0(N(K1ef&Tm}Oi>!8)Ojbqu z)j1SS+v8e0W>i;&))tO1IHH5PmRzT$; zN^!BzRE-24V+F$N@=Pq@O0S92Qq;TOOOg&{PoG()Qpp%4n?2A=u0^Vt@%T_tJogl1 zJkv`YB@X8uxOC+TFXmGa`|_lSzpgEZRm2NOy-Lc^$#DK?Ch^>Ny~bN+eXiclkrJc6 z5c>QoL#Cu$|7wne{r&SWaZAC$1gXN>fSC@XD!DcwcHl^?U^t;Z8i#nH3s4*&fbd~= z0}3F5AoK!?1Eol;7FZ9%BcK4RfC5(mutI}ich7huk}mvs;=G+Ie^%6AmF+7=^_lG} zGq~ialo;-l{WQ1!;L#5^xcQj-Kt?&Md$;N-P^o&s0cyFiqhWpNO-T z@72qM0(>=PT9NU@zwl49tL`UDj%F~VXY=uL%^JyFY2%dra0(CRokd8j$Y92u+< zNF;*1^H;~Njp6JVn^X?lrRe7BHNWx7rR7DGLy3gyt2(Xrue6Hz>?*dl`?_8H%P+5I HqM!T+FLlTe literal 0 HcmV?d00001 diff --git a/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/rename.png b/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/rename.png new file mode 100644 index 0000000000000000000000000000000000000000..a425ee7529301df781a5c3f21f23263a7c3e3c81 GIT binary patch literal 262 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!63?wyl`GbL!Uw}`D>wg#!6cmh%j0Exo1O!x6 zRK&!@fb7GE56_u1XZiBw;^N}&?(U+ZqCkecyu6l{mY$xTfq?-~8Bjz?Nl8sjO;uHu zwVY`O&}8wFAirP+77l)K8F^)W69?b$!k!BkuiU(K`@@HKla&jBN&-Ax978JNde2&m zH7E!;UtGY!RVQ%q;NSd^Q$4N6OTI6u_!0F!?%uh;o6mm-)ptEj=w2dmV{2OW6z?DT v^QUgyA}3w_dgI(FS0^Pt&rCR6qGJH{an^LB{Ts5hht&W literal 0 HcmV?d00001 diff --git a/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/size.png b/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/size.png new file mode 100644 index 0000000000000000000000000000000000000000..fcc302f200c97c361acf473d0d8f9bd4a868b47d GIT binary patch literal 660 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 literal 0 HcmV?d00001 diff --git a/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/trans.jpg b/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/trans.jpg new file mode 100644 index 0000000000000000000000000000000000000000..147175ee8e65cf8d678b66368995de1b70123c06 GIT binary patch literal 4024 zcmbtX2Uru!+MdlOfh4qq4uV0t^xl*zRl0xzg7l{JZleiOM2d|nh#&~k5mB*$fC}dT zQUvrM%}x^w!2`+Nz`6Q7xBcbLKC}Dox9@y2@06WyXk)Y~z-DG-Y6Kt%02AZ_v}th0 zFvi~p01FGS69B*nun-o&2!a3#xsm?DNCAisU^eXlI6(YAu`49;i+|c5p#S0^J~tCm z3*w7j-=@z})K3Pf6#j+jT-pLqxAqH;2oCoP4k0Va$^&(MQwucRBa$|;=q6+v7C1AW z1)9(w;&FNN6#bL58N!&Ufx#hbTPq_|bHh!6geUGHAx97qATTH*%+^?+e8AC(%rK6$ z76-V2BoK1<3=h$>wl?4N`7dwZM>pFJhGgiz{w3w#8=1q93K7v{gu>ywg_Y^pV++%J zgd;j4Bm&_aq+?G%cP|8oAXqxg&ej0IMF?i`-NHBM*kcQ~({YriFTHFZ09aCxmwyld z3{wEWEMDH>o&eyN5l*mYNEpH)xFJ|KFfbVLPbfvO1ideiCz3)R0ibyb0MyH0HkU~N z8Uq2~k^E&7S3{bJrVl|XaZ2J>lqmqwaG;qkMaiKe|q22`Bw=TnN0LSWdUZO6G}#jp-NzN_yal!gU7UE zZLnV$su+zKS8z3WYXVHT%jCl>z&yfohSh=%%hp9qBN?$XvG;MD<#gcU=9=cd&J)h7 z&xhw5=P%zDE?^+YCOEgfnVc%*yhBbHBRnqBEP7hZLtI0GBrz}9z4NNnNoiLZ4Ou?f zRk;`Pw-hcZ#ws}}Ypak|8B{;0^{Y2)^8C+X6u;^gv_n$yjx?P*=<{TX9tW;5r{ zu4Y3ygj~*Z+s{i}kiV#TNiWYd->SgA(6Pw1*zK}siASl&6}K{%s|U*WRqVZ{U#V6l zb)CN&U;VXa@c0O>;*}@y*!QeYa%W7~AG3{zT!a)HAVOp+14%_${KME&XUk^=vpW&Z1oQrrxNxs$Y#`F9KeO+h4BvvUQ8TJx0yXzcvv2>2C<2<4H1(`x}-1cwH!w{g*j)q%D7#5 zgm|WT%lQ2HrTAC2wF@K(T5spwK1Xg5O4zYaSVZ`{NT29su_$qK2~kNPIll9jRJL@m zjD@VU9E;qd{IJ4J#R8=`Wp5R8RYf&^by$5-V^p(4t9Dnx?o{n)9Y0+sJxhIk1C2eh zhT=wo#yln@Q&uzlUIuft1#AgfK~^+tnhnjCwvTE@wcl`9-~Z=cj`Rug5pJ& zODTB``QwFfk#w>B<+zf{(*7&ouL_hKRQO%XtZb|rx&FO|=Z0#neO*|6Rzr2;Vx1%(kJNC=lNF)J&W~A7nWl`JFRFT5A&f>1!F7?r|~FI6$%wf0_{#}(iT9FvPW2}br;MB) zNgYZXOz+EhdZr`u-r1X3wb>Opg}J%sQqRX-2*2om$tBM=->5*VP`*gGnD;Vs30y)c zUAQt^Hhy)Wyr<&fwYJKpsvFlUtFP9S-YBUpsVl87Yq-`})70GD-qLe(xOMi{%5C@# z`(4p?)q7_5T^@uzJdLdFmd?J%vt1iKT*%5cf9Btt(pUal=kGHEs6mnEMnnF?nIlc3 zV=rjq;uBUckG?AZqkrujGx4)^bFbbK-f6xM_)z%q_j$0OvKX*bx;(Z*{9^t! z^;_2}hGM*y{$pUBXTyWqK%)V$wcpYA1Q-jz)lLBHHUKbv2tYoP#qt0kA$yIr9%9!4 zD0MA>lAi!5Oc}EK$87E&Xut+UfG+R?*`N!8AVVkzdW$kZRl*!_8kzxp2E&JGz*=Iz zF_bepm3i7*ORYt8(tt-aE9zD^jSDV zR8H)*M8VEO(sHsmxdnv@r2&lMTU%D1irlRx_x%~J!)QXS>dZDMRi@6-d{+(#tGzsJvasK zLnz1wszx!PVvs*)5WI>`!-!&@Vxt(O89p*L;u7$V1P!Jg%ItVA{eq5{dBJ&5BX zXEzs>XBTf0-{3Y0fmFfIWN)Ea;lm;uV)+uIna%B`w}>Zdhhb_Htt z=z8dT?C~>-FiAEmHos#zX@lFRX&<`3(Q);lk!z9Lx~G@-sGm*1SfGChHmo7iCuZl- zjT5iq2b20!CeoHO*|YV}#a(<_AXJ=Mx>253#a+{0AJ(jKi~TORPwOQ1$o4w+pC6hX zGk(=I?fRDM-q$-&HJmXP{>pvIcFy>{_PpA%+*fgmz&aaU?^eu*j587h`uO|$ zl2tY_{T28Cf8dK;WUy)chwp#q{okGu-Z4mA34lRxNNkwDuU`aN4~dYy$)-V`veINl zd3lZh>~AX;rE{=s0OW2*ZBY5zY0v(t5bYr#G6E7H!4MIkh!9MKXpg~mByz+cixx?L zF9D%oGzQDSh{F>Q!c8`Sf?ybhhA|lW0RlRKdJ9~%yNa%~qSs!0N z|A6p_$f)R;*rQ3Ol2cBnrlseeJAdKgrM&!tva974*D9;7S2s1c+-$wocKc38=i{#K zo+nSAJs%n#8GSJ}J~2HrJNM@8yZ0YHeqQ0Vz%U137TQvJ1#+q%}+4aQNt5m(G;`eth!kxqI$8 aK4MRt&fO?7DRw&0ZU#?RKbLh*2~7aatZW|u literal 0 HcmV?d00001 diff --git a/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/url.png b/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/url.png new file mode 100644 index 0000000000000000000000000000000000000000..f18499afb62d9ce8961936ccd9a358d2da20362b GIT binary patch literal 593 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!63?wyl`GbMfw*a3I*Z=?j1DW&zy1Kgbu?Wo; zV`F19kuwuz4+Dh)OM?7@8JJlcz|j;hs_CjCY1%U^9+?9iMqY4gVR;b%?h zUT#6H2O4MYU6vCNeZN`l&Lid7&!Y~e@APzW45^6oJ)7Eh*g>G>;-UDf^!NQfYXX&i{{Fe-RU4DBeu=b} z-%d79UEZf0eXj4<%%3nJj6ZhnO|c*$mf`~?*U~sAPT^Udc6`P3?{*5|j?IS;&RG2H z$bS9P@vWBPr$w*N)-9hJ5pv~RW#H;hpI*%}XH}SXdw0_3g9&{7IV{J$k8W7>@#W9f z^&Q@>8Xw>OeJpIny5xcO=`-eabwAl>Hf=ffYrp$xM<R#a>3ve0!aO@p;+@f! RR|cR!^K|udS?83{1OP*>n)?6% literal 0 HcmV?d00001 diff --git a/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/zip.png b/local/modules/Tinymce/Resources/js/tinymce/filemanager/img/zip.png new file mode 100644 index 0000000000000000000000000000000000000000..9ef55c7b72fd530e37881c36f0bfd697250e297a GIT binary patch literal 819 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!63?wyl`GXl47<&SILR|m<{|^*F2BD#$wzl>_ z5eSJa1z|flIM~>L6aWDm8yk?cu&}kYwPR&v<>26e=<@aTwXv}SN*NoQ0!g42paMNT zJzHA`AlJ?gXo4LN4-b&d!omX7%*n~gzy!3>PFh+p8)7w3pP896kd%^=1_}b*1|)55?7_C% z0PO;DK_XzIfTX>hqk(}DPz0h9$glw#WCwD&jI1m(Gbreg0mK$pcfz_ z5H&zo0rfgLxwyKz0}Xd{bOxH>;NT1lFpDBTy%fED z3#hrMB*-tAp_1`;MHTZ-rr&in5#Rp&tY-<8ydOBtddsEOPiwfo1%7Yhc_?<|(vL%z zA}6FoP2Bk7QV+L_vn+?*=aX)exBiF~`F1w%pIOM?qG;iUuZ9kP=Y~(M+M?dZRzK7-e%HH|>t5YnpvX}Za!6iO#MbeqG;^}k^F=%Yp0__-wUu-` zl6mX%Pu|dvX*@HcUAa#&yj?ga?!R#DX)}{W9YQL>?`N91e|;YAn=8vHdu27VgNbO= znf@4?r*mcJ#@;+CxCZ3|_WMQ88~L + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + * + * @copyright Nicolas Tallefourtane http://nicolab.net + */ +namespace FtpClient; + +use \Countable; + +/** + * The FTP and SSL-FTP client for PHP. + * + * @method bool alloc() alloc(int $filesize, string &$result = null) Allocates space for a file to be uploaded + * @method bool cdup() cdup() Changes to the parent directory + * @method bool chdir() chdir(string $directory) Changes the current directory on a FTP server + * @method int chmod() chmod(int $mode, string $filename) Set permissions on a file via FTP + * @method bool delete() delete(string $path) Deletes a file on the FTP server + * @method bool exec() exec(string $command) Requests execution of a command on the FTP server + * @method bool fget() fget(resource $handle, string $remote_file, int $mode, int $resumepos = 0) Downloads a file from the FTP server and saves to an open file + * @method bool fput() fput(string $remote_file, resource $handle, int $mode, int $startpos = 0) Uploads from an open file to the FTP server + * @method mixed get_option() get_option(int $option) Retrieves various runtime behaviours of the current FTP stream + * @method bool get() get(string $local_file, string $remote_file, int $mode, int $resumepos = 0) Downloads a file from the FTP server + * @method int mdtm() mdtm(string $remote_file) Returns the last modified time of the given file + * @method int nb_continue() nb_continue() Continues retrieving/sending a file (non-blocking) + * @method int nb_fget() nb_fget(resource $handle, string $remote_file, int $mode, int $resumepos = 0) Retrieves a file from the FTP server and writes it to an open file (non-blocking) + * @method int nb_fput() nb_fput(string $remote_file, resource $handle, int $mode, int $startpos = 0) Stores a file from an open file to the FTP server (non-blocking) + * @method int nb_get() nb_get(string $local_file, string $remote_file, int $mode, int $resumepos = 0) Retrieves a file from the FTP server and writes it to a local file (non-blocking) + * @method int nb_put() nb_put(string $remote_file, string $local_file, int $mode, int $startpos = 0) Stores a file on the FTP server (non-blocking) + * @method bool pasv() pasv(bool $pasv) Turns passive mode on or off + * @method bool put() put(string $remote_file, string $local_file, int $mode, int $startpos = 0) Uploads a file to the FTP server + * @method string pwd() pwd() Returns the current directory name + * @method bool quit() quit() Closes an FTP connection + * @method array raw() raw(string $command) Sends an arbitrary command to an FTP server + * @method bool rename() rename(string $oldname, string $newname) Renames a file or a directory on the FTP server + * @method bool set_option() set_option(int $option, mixed $value) Set miscellaneous runtime FTP options + * @method bool site() site(string $command) Sends a SITE command to the server + * @method int size() size(string $remote_file) Returns the size of the given file + * @method string systype() systype() Returns the system type identifier of the remote FTP server + * + * @author Nicolas Tallefourtane + */ +class FtpClient implements Countable +{ + /** + * The connection with the server. + * + * @var resource + */ + protected $conn; + + /** + * PHP FTP functions wrapper. + * + * @var FtpWrapper + */ + private $ftp; + + /** + * Constructor. + * + * @param resource|null $connection + * @throws FtpException If FTP extension is not loaded. + */ + public function __construct($connection = null) + { + if (!extension_loaded('ftp')) { + throw new FtpException('FTP extension is not loaded!'); + } + + if ($connection) { + $this->conn = $connection; + } + + $this->setWrapper(new FtpWrapper($this->conn)); + } + + /** + * Close the connection when the object is destroyed. + */ + public function __destruct() + { + if ($this->conn) { + $this->ftp->close(); + } + } + + /** + * Call an internal method or a FTP method handled by the wrapper. + * + * Wrap the FTP PHP functions to call as method of FtpClient object. + * The connection is automaticaly passed to the FTP PHP functions. + * + * @param string $method + * @param array $arguments + * @return mixed + * @throws FtpException When the function is not valid + */ + public function __call($method, array $arguments) + { + return $this->ftp->__call($method, $arguments); + } + + /** + * Overwrites the PHP limit + * + * @param string|null $memory The memory limit, if null is not modified + * @param int $time_limit The max execution time, unlimited by default + * @param bool $ignore_user_abort Ignore user abort, true by default + * @return FtpClient + */ + public function setPhpLimit($memory = null, $time_limit = 0, $ignore_user_abort = true) + { + if (null !== $memory) { + ini_set('memory_limit', $memory); + } + + ignore_user_abort(true); + set_time_limit($time_limit); + + return $this; + } + + /** + * Get the help information of the remote FTP server. + * + * @return array + */ + public function help() + { + return $this->ftp->raw('help'); + } + + /** + * Open a FTP connection. + * + * @param string $host + * @param bool $ssl + * @param int $port + * @param int $timeout + * + * @return FTPClient + * @throws FtpException If unable to connect + */ + public function connect($host, $ssl = false, $port = 21, $timeout = 90) + { + if ($ssl) { + $this->conn = @$this->ftp->ssl_connect($host, $port, $timeout); + } else { + $this->conn = @$this->ftp->connect($host, $port, $timeout); + } + + if (!$this->conn) { + throw new FtpException('Unable to connect'); + } + + return $this; + } + + /** + * Closes the current FTP connection. + * + * @return bool + */ + public function close() + { + if ($this->conn) { + $this->ftp->close(); + $this->conn = null; + } + } + + /** + * Get the connection with the server. + * + * @return resource + */ + public function getConnection() + { + return $this->conn; + } + + /** + * Get the wrapper. + * + * @return FtpWrapper + */ + public function getWrapper() + { + return $this->ftp; + } + + /** + * Logs in to an FTP connection. + * + * @param string $username + * @param string $password + * + * @return FtpClient + * @throws FtpException If the login is incorrect + */ + public function login($username = 'anonymous', $password = '') + { + $result = $this->ftp->login($username, $password); + + if ($result === false) { + throw new FtpException('Login incorrect'); + } + + return $this; + } + + /** + * Returns the last modified time of the given file. + * Return -1 on error + * + * @param string $remoteFile + * @param string|null $format + * + * @return int + */ + public function modifiedTime($remoteFile, $format = null) + { + $time = $this->ftp->mdtm($remoteFile); + + if ($time !== -1 && $format !== null) { + return date($format, $time); + } + + return $time; + } + + /** + * Changes to the parent directory. + * + * @throws FtpException + * @return FtpClient + */ + public function up() + { + $result = @$this->ftp->cdup(); + + if ($result === false) { + throw new FtpException('Unable to get parent folder'); + } + + return $this; + } + + /** + * Returns a list of files in the given directory. + * + * @param string $directory The directory, by default is "." the current directory + * @param bool $recursive + * @param callable $filter A callable to filter the result, by default is asort() PHP function. + * The result is passed in array argument, + * must take the argument by reference ! + * The callable should proceed with the reference array + * because is the behavior of several PHP sorting + * functions (by reference ensure directly the compatibility + * with all PHP sorting functions). + * + * @return array + * @throws FtpException If unable to list the directory + */ + public function nlist($directory = '.', $recursive = false, $filter = 'sort') + { + if (!$this->isDir($directory)) { + throw new FtpException('"'.$directory.'" is not a directory'); + } + + $files = $this->ftp->nlist($directory); + + if ($files === false) { + throw new FtpException('Unable to list directory'); + } + + $result = array(); + $dir_len = strlen($directory); + + // if it's the current + if (false !== ($kdot = array_search('.', $files))) { + unset($files[$kdot]); + } + + // if it's the parent + if(false !== ($kdot = array_search('..', $files))) { + unset($files[$kdot]); + } + + if (!$recursive) { + foreach ($files as $file) { + $result[] = $directory.'/'.$file; + } + + // working with the reference (behavior of several PHP sorting functions) + $filter($result); + + return $result; + } + + // utils for recursion + $flatten = function (array $arr) use (&$flatten) { + + $flat = []; + + foreach ($arr as $k => $v) { + if (is_array($v)) { + $flat = array_merge($flat, $flatten($v)); + } else { + $flat[] = $v; + } + } + + return $flat; + }; + + foreach ($files as $file) { + $file = $directory.'/'.$file; + + // if contains the root path (behavior of the recursivity) + if (0 === strpos($file, $directory, $dir_len)) { + $file = substr($file, $dir_len); + } + + if ($this->isDir($file)) { + $result[] = $file; + $items = $flatten($this->nlist($file, true, $filter)); + + foreach ($items as $item) { + $result[] = $item; + } + + } else { + $result[] = $file; + } + } + + $result = array_unique($result); + + $filter($result); + + return $result; + } + + /** + * Creates a directory. + * + * @see FtpClient::rmdir() + * @see FtpClient::remove() + * @see FtpClient::put() + * @see FtpClient::putAll() + * + * @param string $directory The directory + * @param bool $recursive + * @return array + */ + public function mkdir($directory, $recursive = false) + { + if (!$recursive or $this->isDir($directory)) { + return $this->ftp->mkdir($directory); + } + + $result = false; + $pwd = $this->ftp->pwd(); + $parts = explode('/', $directory); + + foreach ($parts as $part) { + + if (!@$this->ftp->chdir($part)) { + $result = $this->ftp->mkdir($part); + $this->ftp->chdir($part); + } + } + + $this->ftp->chdir($pwd); + + return $result; + } + + /** + * Remove a directory. + * + * @see FtpClient::mkdir() + * @see FtpClient::cleanDir() + * @see FtpClient::remove() + * @see FtpClient::delete() + * @param string $directory + * @param bool $recursive Forces deletion if the directory is not empty + * @return bool + * @throws FtpException If unable to list the directory to remove + */ + public function rmdir($directory, $recursive = true) + { + if ($recursive) { + $files = $this->nlist($directory, false, 'rsort'); + + // remove children + foreach ($files as $file) { + $this->remove($file, true); + } + } + + // remove the directory + return $this->ftp->rmdir($directory); + } + + /** + * Empty directory. + * + * @see FtpClient::remove() + * @see FtpClient::delete() + * @see FtpClient::rmdir() + * + * @param string $directory + * @return bool + */ + public function cleanDir($directory) + { + if(!$files = $this->nlist($directory)) { + return $this->isEmpty($directory); + } + + // remove children + foreach ($files as $file) { + $this->remove($file, true); + } + + return $this->isEmpty($directory); + } + + /** + * Remove a file or a directory. + * + * @see FtpClient::rmdir() + * @see FtpClient::cleanDir() + * @see FtpClient::delete() + * @param string $path The path of the file or directory to remove + * @param bool $recursive Is effective only if $path is a directory, {@see FtpClient::rmdir()} + * @return bool + */ + public function remove($path, $recursive = false) + { + try { + if (@$this->ftp->delete($path) + or ($this->isDir($path) and @$this->rmdir($path, $recursive))) { + return true; + } + + return false; + } catch (\Exception $e) { + return false; + } + } + + /** + * Check if a directory exist. + * + * @param string $directory + * @return bool + * @throws FtpException + */ + public function isDir($directory) + { + $pwd = $this->ftp->pwd(); + + if ($pwd === false) { + throw new FtpException('Unable to resolve the current directory'); + } + + if (@$this->ftp->chdir($directory)) { + $this->ftp->chdir($pwd); + return true; + } + + $this->ftp->chdir($pwd); + + return false; + } + + /** + * Check if a directory is empty. + * + * @param string $directory + * @return bool + */ + public function isEmpty($directory) + { + return $this->count($directory, null, false) === 0 ? true : false; + } + + /** + * Scan a directory and returns the details of each item. + * + * @see FtpClient::nlist() + * @see FtpClient::rawlist() + * @see FtpClient::parseRawList() + * @see FtpClient::dirSize() + * @param string $directory + * @param bool $recursive + * @return array + */ + public function scanDir($directory = '.', $recursive = false) + { + return $this->parseRawList($this->rawlist($directory, $recursive)); + } + + /** + * Returns the total size of the given directory in bytes. + * + * @param string $directory The directory, by default is the current directory. + * @param bool $recursive true by default + * @return int The size in bytes. + */ + public function dirSize($directory = '.', $recursive = true) + { + $items = $this->scanDir($directory, $recursive); + $size = 0; + + foreach ($items as $item) { + $size += (int) $item['size']; + } + + return $size; + } + + /** + * Count the items (file, directory, link, unknown). + * + * @param string $directory The directory, by default is the current directory. + * @param string|null $type The type of item to count (file, directory, link, unknown) + * @param bool $recursive true by default + * @return int + */ + public function count($directory = '.', $type = null, $recursive = true) + { + $items = (null === $type ? $this->nlist($directory, $recursive) + : $this->scanDir($directory, $recursive)); + + $count = 0; + foreach ($items as $item) { + if (null === $type or $item['type'] == $type) { + $count++; + } + } + + return $count; + } + + /** + * Uploads a file to the server from a string. + * + * @param string $remote_file + * @param string $content + * @return FtpClient + * @throws FtpException When the transfer fails + */ + public function putFromString($remote_file, $content) + { + $handle = fopen('php://temp', 'w'); + + fwrite($handle, $content); + rewind($handle); + + if ($this->ftp->fput($remote_file, $handle, FTP_BINARY)) { + return $this; + } + + throw new FtpException('Unable to put the file "'.$remote_file.'"'); + } + + /** + * Uploads a file to the server. + * + * @param string $local_file + * @return FtpClient + * @throws FtpException When the transfer fails + */ + public function putFromPath($local_file) + { + $remote_file = basename($local_file); + $handle = fopen($local_file, 'r'); + + if ($this->ftp->fput($remote_file, $handle, FTP_BINARY)) { + rewind($handle); + return $this; + } + + throw new FtpException( + 'Unable to put the remote file from the local file "'.$local_file.'"' + ); + } + + /** + * Upload files. + * + * @param string $source_directory + * @param string $target_directory + * @param int $mode + * @return FtpClient + */ + public function putAll($source_directory, $target_directory, $mode = FTP_BINARY) + { + $d = dir($source_directory); + + // do this for each file in the directory + while ($file = $d->read()) { + + // to prevent an infinite loop + if ($file != "." && $file != "..") { + + // do the following if it is a directory + if (is_dir($source_directory.'/'.$file)) { + + if (!$this->isDir($target_directory.'/'.$file)) { + + // create directories that do not yet exist + $this->ftp->mkdir($target_directory.'/'.$file); + } + + // recursive part + $this->putAll( + $source_directory.'/'.$file, $target_directory.'/'.$file, + $mode + ); + } else { + + // put the files + $this->ftp->put( + $target_directory.'/'.$file, $source_directory.'/'.$file, + $mode + ); + } + } + } + + return $this; + } + + /** + * Returns a detailed list of files in the given directory. + * + * @see FtpClient::nlist() + * @see FtpClient::scanDir() + * @see FtpClient::dirSize() + * @param string $directory The directory, by default is the current directory + * @param bool $recursive + * @return array + * @throws FtpException + */ + public function rawlist($directory = '.', $recursive = false) + { + if (!$this->isDir($directory)) { + throw new FtpException('"'.$directory.'" is not a directory.'); + } + + $list = $this->ftp->rawlist($directory); + $items = array(); + + if (!$list) { + return $items; + } + + if (false == $recursive) { + + foreach ($list as $path => $item) { + $chunks = preg_split("/\s+/", $item); + + // if not "name" + if (empty($chunks[8]) || $chunks[8] == '.' || $chunks[8] == '..') { + continue; + } + + $path = $directory.'/'.$chunks[8]; + + if (isset($chunks[9])) { + $nbChunks = count($chunks); + + for ($i = 9; $i < $nbChunks; $i++) { + $path .= ' '.$chunks[$i]; + } + } + + + if (substr($path, 0, 2) == './') { + $path = substr($path, 2); + } + + $items[ $this->rawToType($item).'#'.$path ] = $item; + } + + return $items; + } + + $path = ''; + + foreach ($list as $item) { + $len = strlen($item); + + if (!$len + + // "." + || ($item[$len-1] == '.' && $item[$len-2] == ' ' + + // ".." + or $item[$len-1] == '.' && $item[$len-2] == '.' && $item[$len-3] == ' ') + ){ + + continue; + } + + $chunks = preg_split("/\s+/", $item); + + // if not "name" + if (empty($chunks[8]) || $chunks[8] == '.' || $chunks[8] == '..') { + continue; + } + + $path = $directory.'/'.$chunks[8]; + + if (isset($chunks[9])) { + $nbChunks = count($chunks); + + for ($i = 9; $i < $nbChunks; $i++) { + $path .= ' '.$chunks[$i]; + } + } + + if (substr($path, 0, 2) == './') { + $path = substr($path, 2); + } + + $items[$this->rawToType($item).'#'.$path] = $item; + + if ($item[0] == 'd') { + $sublist = $this->rawlist($path, true); + + foreach ($sublist as $subpath => $subitem) { + $items[$subpath] = $subitem; + } + } + } + + return $items; + } + + /** + * Parse raw list. + * + * @see FtpClient::rawlist() + * @see FtpClient::scanDir() + * @see FtpClient::dirSize() + * @param array $rawlist + * @return array + */ + public function parseRawList(array $rawlist) + { + $items = array(); + $path = ''; + + foreach ($rawlist as $key => $child) { + $chunks = preg_split("/\s+/", $child); + + if (isset($chunks[8]) && ($chunks[8] == '.' or $chunks[8] == '..')) { + continue; + } + + if (count($chunks) === 1) { + $len = strlen($chunks[0]); + + if ($len && $chunks[0][$len-1] == ':') { + $path = substr($chunks[0], 0, -1); + } + + continue; + } + + $item = [ + 'permissions' => $chunks[0], + 'number' => $chunks[1], + 'owner' => $chunks[2], + 'group' => $chunks[3], + 'size' => $chunks[4], + 'month' => $chunks[5], + 'day' => $chunks[6], + 'time' => $chunks[7], + 'name' => $chunks[8], + 'type' => $this->rawToType($chunks[0]), + ]; + + unset($chunks[0]); + unset($chunks[1]); + unset($chunks[2]); + unset($chunks[3]); + unset($chunks[4]); + unset($chunks[5]); + unset($chunks[6]); + unset($chunks[7]); + $item['name'] = implode(' ', $chunks); + + if ($item['type'] == 'link') { + $item['target'] = $chunks[10]; // 9 is "->" + } + + // if the key is not the path, behavior of ftp_rawlist() PHP function + if (is_int($key) || false === strpos($key, $item['name'])) { + array_splice($chunks, 0, 8); + + $key = $item['type'].'#' + .($path ? $path.'/' : '') + .implode(" ", $chunks); + + if ($item['type'] == 'link') { + + // get the first part of 'link#the-link.ext -> /path/of/the/source.ext' + $exp = explode(' ->', $key); + $key = rtrim($exp[0]); + } + + $items[$key] = $item; + + } else { + + // the key is the path, behavior of FtpClient::rawlist() method() + $items[$key] = $item; + } + } + + return $items; + } + + /** + * Convert raw info (drwx---r-x ...) to type (file, directory, link, unknown). + * Only the first char is used for resolving. + * + * @param string $permission Example : drwx---r-x + * + * @return string The file type (file, directory, link, unknown) + * @throws FtpException + */ + public function rawToType($permission) + { + if (!is_string($permission)) { + throw new FtpException('The "$permission" argument must be a string, "' + .gettype($permission).'" given.'); + } + + if (empty($permission[0])) { + return 'unknown'; + } + + switch ($permission[0]) { + case '-': + return 'file'; + + case 'd': + return 'directory'; + + case 'l': + return 'link'; + + default: + return 'unknown'; + } + } + + /** + * Set the wrapper which forward the PHP FTP functions to use in FtpClient instance. + * + * @param FtpWrapper $wrapper + * @return FtpClient + */ + protected function setWrapper(FtpWrapper $wrapper) + { + $this->ftp = $wrapper; + + return $this; + } +} diff --git a/local/modules/Tinymce/Resources/js/tinymce/filemanager/include/FtpException.php b/local/modules/Tinymce/Resources/js/tinymce/filemanager/include/FtpException.php new file mode 100644 index 00000000..f17ed7f8 --- /dev/null +++ b/local/modules/Tinymce/Resources/js/tinymce/filemanager/include/FtpException.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + * + * @copyright Nicolas Tallefourtane http://nicolab.net + */ +namespace FtpClient; + +/** + * The FtpException class. + * Exception thrown if an error on runtime of the FTP client occurs. + * @inheritDoc + * @author Nicolas Tallefourtane + */ +class FtpException extends \Exception {} diff --git a/local/modules/Tinymce/Resources/js/tinymce/filemanager/include/FtpWrapper.php b/local/modules/Tinymce/Resources/js/tinymce/filemanager/include/FtpWrapper.php new file mode 100644 index 00000000..cd12de03 --- /dev/null +++ b/local/modules/Tinymce/Resources/js/tinymce/filemanager/include/FtpWrapper.php @@ -0,0 +1,115 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + * + * @copyright Nicolas Tallefourtane http://nicolab.net + */ +namespace FtpClient; + +/** + * Wrap the PHP FTP functions + * + * @method bool alloc() alloc(int $filesize, string &$result = null) Allocates space for a file to be uploaded + * @method bool cdup() cdup() Changes to the parent directory + * @method bool chdir() chdir(string $directory) Changes the current directory on a FTP server + * @method int chmod() chmod(int $mode, string $filename) Set permissions on a file via FTP + * @method bool close() close() Closes an FTP connection + * @method bool delete() delete(string $path) Deletes a file on the FTP server + * @method bool exec() exec(string $command) Requests execution of a command on the FTP server + * @method bool fget() fget(resource $handle, string $remote_file, int $mode, int $resumepos = 0) Downloads a file from the FTP server and saves to an open file + * @method bool fput() fput(string $remote_file, resource $handle, int $mode, int $startpos = 0) Uploads from an open file to the FTP server + * @method mixed get_option() get_option(int $option) Retrieves various runtime behaviours of the current FTP stream + * @method bool get() get(string $local_file, string $remote_file, int $mode, int $resumepos = 0) Downloads a file from the FTP server + * @method bool login() login(string $username, string $password) Logs in to an FTP connection + * @method int mdtm() mdtm(string $remote_file) Returns the last modified time of the given file + * @method string mkdir() mkdir(string $directory) Creates a directory + * @method int nb_continue() nb_continue() Continues retrieving/sending a file (non-blocking) + * @method int nb_fget() nb_fget(resource $handle, string $remote_file, int $mode, int $resumepos = 0) Retrieves a file from the FTP server and writes it to an open file (non-blocking) + * @method int nb_fput() nb_fput(string $remote_file, resource $handle, int $mode, int $startpos = 0) Stores a file from an open file to the FTP server (non-blocking) + * @method int nb_get() nb_get(string $local_file, string $remote_file, int $mode, int $resumepos = 0) Retrieves a file from the FTP server and writes it to a local file (non-blocking) + * @method int nb_put() nb_put(string $remote_file, string $local_file, int $mode, int $startpos = 0) Stores a file on the FTP server (non-blocking) + * @method array nlist() nlist(string $directory) Returns a list of files in the given directory + * @method bool pasv() pasv(bool $pasv) Turns passive mode on or off + * @method bool put() put(string $remote_file, string $local_file, int $mode, int $startpos = 0) Uploads a file to the FTP server + * @method string pwd() pwd() Returns the current directory name + * @method bool quit() quit() Closes an FTP connection + * @method array raw() raw(string $command) Sends an arbitrary command to an FTP server + * @method array rawlist() rawlist(string $directory, bool $recursive = false) Returns a detailed list of files in the given directory + * @method bool rename() rename(string $oldname, string $newname) Renames a file or a directory on the FTP server + * @method bool rmdir() rmdir(string $directory) Removes a directory + * @method bool set_option() set_option(int $option, mixed $value) Set miscellaneous runtime FTP options + * @method bool site() site(string $command) Sends a SITE command to the server + * @method int size() size(string $remote_file) Returns the size of the given file + * @method string systype() systype() Returns the system type identifier of the remote FTP server + * + * @author Nicolas Tallefourtane + */ +class FtpWrapper +{ + /** + * The connection with the server + * + * @var resource + */ + protected $conn; + + /** + * Constructor. + * + * @param resource &$connection The FTP (or SSL-FTP) connection (takes by reference). + */ + public function __construct(&$connection) + { + $this->conn = &$connection; + } + + /** + * Forward the method call to FTP functions + * + * @param string $function + * @param array $arguments + * @return mixed + * @throws FtpException When the function is not valid + */ + public function __call($function, array $arguments) + { + $function = 'ftp_' . $function; + + if (function_exists($function)) { + array_unshift($arguments, $this->conn); + return call_user_func_array($function, $arguments); + } + + throw new FtpException("{$function} is not a valid FTP function"); + } + + /** + * Opens a FTP connection + * + * @param string $host + * @param int $port + * @param int $timeout + * @return resource + */ + public function connect($host, $port = 21, $timeout = 90) + { + return ftp_connect($host, $port, $timeout); + } + + /** + * Opens a Secure SSL-FTP connection + * @param string $host + * @param int $port + * @param int $timeout + * @return resource + */ + public function ssl_connect($host, $port = 21, $timeout = 90) + { + return ftp_ssl_connect($host, $port, $timeout); + } +} diff --git a/local/modules/Tinymce/Resources/js/tinymce/filemanager/include/Response.php b/local/modules/Tinymce/Resources/js/tinymce/filemanager/include/Response.php new file mode 100644 index 00000000..ae9f10c9 --- /dev/null +++ b/local/modules/Tinymce/Resources/js/tinymce/filemanager/include/Response.php @@ -0,0 +1,365 @@ + 'Continue', + 101 => 'Switching Protocols', + 102 => 'Processing', // RFC2518 + 200 => 'OK', + 201 => 'Created', + 202 => 'Accepted', + 203 => 'Non-Authoritative Information', + 204 => 'No Content', + 205 => 'Reset Content', + 206 => 'Partial Content', + 207 => 'Multi-Status', // RFC4918 + 208 => 'Already Reported', // RFC5842 + 226 => 'IM Used', // RFC3229 + 300 => 'Multiple Choices', + 301 => 'Moved Permanently', + 302 => 'Found', + 303 => 'See Other', + 304 => 'Not Modified', + 305 => 'Use Proxy', + 306 => 'Reserved', + 307 => 'Temporary Redirect', + 308 => 'Permanent Redirect', // RFC7238 + 400 => 'Bad Request', + 401 => 'Unauthorized', + 402 => 'Payment Required', + 403 => 'Forbidden', + 404 => 'Not Found', + 405 => 'Method Not Allowed', + 406 => 'Not Acceptable', + 407 => 'Proxy Authentication Required', + 408 => 'Request Timeout', + 409 => 'Conflict', + 410 => 'Gone', + 411 => 'Length Required', + 412 => 'Precondition Failed', + 413 => 'Request Entity Too Large', + 414 => 'Request-URI Too Long', + 415 => 'Unsupported Media Type', + 416 => 'Requested Range Not Satisfiable', + 417 => 'Expectation Failed', + 418 => 'I\'m a teapot', // RFC2324 + 422 => 'Unprocessable Entity', // RFC4918 + 423 => 'Locked', // RFC4918 + 424 => 'Failed Dependency', // RFC4918 + 425 => 'Reserved for WebDAV advanced collections expired proposal', // RFC2817 + 426 => 'Upgrade Required', // RFC2817 + 428 => 'Precondition Required', // RFC6585 + 429 => 'Too Many Requests', // RFC6585 + 431 => 'Request Header Fields Too Large', // RFC6585 + 500 => 'Internal Server Error', + 501 => 'Not Implemented', + 502 => 'Bad Gateway', + 503 => 'Service Unavailable', + 504 => 'Gateway Timeout', + 505 => 'HTTP Version Not Supported', + 506 => 'Variant Also Negotiates (Experimental)', // RFC2295 + 507 => 'Insufficient Storage', // RFC4918 + 508 => 'Loop Detected', // RFC5842 + 510 => 'Not Extended', // RFC2774 + 511 => 'Network Authentication Required', // RFC6585 + ); + + /** + * @var string + */ + protected $content; + + /** + * @var int + */ + protected $statusCode; + + /** + * @var string + */ + protected $statusText; + + /** + * @var array + */ + public $headers; + + /** + * @var string + */ + protected $version; + + /** + * Construct the response + * + * @param mixed $content + * @param int $statusCode + * @param array $headers + */ + public function __construct($content = '', $statusCode = 200, $headers = array()) + { + $this->setContent($content); + $this->setStatusCode($statusCode); + $this->headers = $headers; + $this->version = '1.1'; + } + + /** + * Set the content on the response. + * + * @param mixed $content + * @return $this + */ + public function setContent($content) + { + if ($content instanceof ArrayObject || is_array($content)) + { + $this->headers['Content-Type'] = array('application/json'); + + $content = json_encode($content); + } + + $this->content = $content; + } + + /** + * Returns the Response as an HTTP string. + * + * The string representation of the Response is the same as the + * one that will be sent to the client only if the prepare() method + * has been called before. + * + * @return string The Response as an HTTP string + * + * @see prepare() + */ + public function __toString() + { + return + sprintf('HTTP/%s %s %s', $this->version, $this->statusCode, $this->statusText)."\r\n". + $this->headers."\r\n". + $this->getContent(); + } + + /** + * Sets the response status code. + * + * @param int $code HTTP status code + * @param mixed $text HTTP status text + * + * If the status text is null it will be automatically populated for the known + * status codes and left empty otherwise. + * + * @return Response + * + * @throws \InvalidArgumentException When the HTTP status code is not valid + * + * @api + */ + public function setStatusCode($code, $text = null) + { + $this->statusCode = $code = (int) $code; + if ($this->isInvalid()) { + throw new InvalidArgumentException(sprintf('The HTTP status code "%s" is not valid.', $code)); + } + + if (null === $text) { + $this->statusText = isset(self::$statusTexts[$code]) ? self::$statusTexts[$code] : ''; + + return $this; + } + + if (false === $text) { + $this->statusText = ''; + + return $this; + } + + $this->statusText = $text; + + return $this; + } + + // http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html + /** + * Is response invalid? + * + * @return bool + * + * @api + */ + public function isInvalid() + { + return $this->statusCode < 100 || $this->statusCode >= 600; + } + + /** + * Set a header on the Response. + * + * @param string $key + * @param string $value + * @param bool $replace + * @return $this + */ + public function header($key, $value, $replace = true) + { + if (empty($this->headers[$key])) + { + $this->headers[$key] = array(); + } + if ($replace) + { + $this->headers[$key] = array($value); + } + else + { + $this->headers[$key][] = $value; + } + + return $this; + } + + /** + * Sends HTTP headers and content. + * + * @return Response + * + * @api + */ + public function send() + { + $this->sendHeaders(); + $this->sendContent(); + + if (function_exists('fastcgi_finish_request')) { + fastcgi_finish_request(); + } + + return $this; + } + + /** + * Sends content for the current web response. + * + * @return Response + */ + public function sendContent() + { + echo $this->content; + + return $this; + } + + /** + * Sends HTTP headers. + * + * @return Response + */ + public function sendHeaders() + { + // headers have already been sent by the developer + if (headers_sent()) { + return $this; + } + + // status + header(sprintf('HTTP/%s %s %s', $this->version, $this->statusCode, $this->statusText), true, $this->statusCode); + + // headers + foreach ($this->headers as $name => $values) { + if (is_array($values)) + { + foreach ($values as $value) + { + header($name . ': ' . $value, false, $this->statusCode); + } + } + else + { + header($name . ': ' . $values, false, $this->statusCode); + } + } + + return $this; + } +} \ No newline at end of file diff --git a/local/modules/Tinymce/Resources/js/tinymce/filemanager/include/ftp_class.php b/local/modules/Tinymce/Resources/js/tinymce/filemanager/include/ftp_class.php new file mode 100644 index 00000000..9c2ae228 --- /dev/null +++ b/local/modules/Tinymce/Resources/js/tinymce/filemanager/include/ftp_class.php @@ -0,0 +1,82 @@ +messageArray[] = $message; + } + + public function getMessages() + { + return $this->messageArray; + } + + public function connect ($server, $ftpUser, $ftpPassword, $isPassive = false) + { + + // *** Set up basic connection + $this->connectionId = ftp_connect($server); + + // *** Login with username and password + $loginResult = ftp_login($this->connectionId, $ftpUser, $ftpPassword); + + // *** Sets passive mode on/off (default off) + ftp_pasv($this->connectionId, $isPassive); + + // *** Check connection + if ((!$this->connectionId) || (!$loginResult)) { + $this->logMessage('FTP connection has failed!'); + $this->logMessage('Attempted to connect to ' . $server . ' for user ' . $ftpUser, true); + return false; + } else { + $this->logMessage('Connected to ' . $server . ', for user ' . $ftpUser); + $this->loginOk = true; + return true; + } + } + public function makeDir($directory) + { + // *** If creating a directory is successful... + if (ftp_mkdir($this->connectionId, $directory)) { + + $this->logMessage('Directory "' . $directory . '" created successfully'); + return true; + + } else { + + // *** ...Else, FAIL. + $this->logMessage('Failed creating directory "' . $directory . '"'); + return false; + } + } + + public function changeDir($directory) + { + if (ftp_chdir($this->connectionId, $directory)) { + $this->logMessage('Current directory is now: ' . ftp_pwd($this->connectionId)); + return true; + } else { + $this->logMessage('Couldn\'t change directory'); + return false; + } + } + + public function getDirListing($directory = '.', $parameters = '-la') + { + echo shell_exec('whoami')." is who i am
    "; + echo "Current directory is now: " . ftp_pwd($this->connectionId) . "
    "; + + // get contents of the current directory + $contentsArray = ftp_rawlist($this->connectionId, $parameters . ' ' . $directory); + echo error_get_last(); + return $contentsArray; + } +} \ No newline at end of file diff --git a/local/modules/Tinymce/Resources/js/tinymce/filemanager/include/mime_type_lib.php b/local/modules/Tinymce/Resources/js/tinymce/filemanager/include/mime_type_lib.php new file mode 100644 index 00000000..f8981b5c --- /dev/null +++ b/local/modules/Tinymce/Resources/js/tinymce/filemanager/include/mime_type_lib.php @@ -0,0 +1,340 @@ + 'application/postscript', + 'aif' => 'audio/x-aiff', + 'aifc' => 'audio/x-aiff', + 'aiff' => 'audio/x-aiff', + 'asc' => 'text/plain', + 'asf' => 'video/x-ms-asf', + 'asx' => 'video/x-ms-asf', + 'au' => 'audio/basic', + 'avi' => 'video/x-msvideo', + 'bcpio' => 'application/x-bcpio', + 'bin' => 'application/octet-stream', + 'bmp' => 'image/bmp', + 'bz2' => 'application/x-bzip2', + 'cdf' => 'application/x-netcdf', + 'chrt' => 'application/x-kchart', + 'class' => 'application/octet-stream', + 'cpio' => 'application/x-cpio', + 'cpt' => 'application/mac-compactpro', + 'csh' => 'application/x-csh', + 'css' => 'text/css', + 'dcr' => 'application/x-director', + 'dir' => 'application/x-director', + 'djv' => 'image/vnd.djvu', + 'djvu' => 'image/vnd.djvu', + 'dll' => 'application/octet-stream', + 'dms' => 'application/octet-stream', + 'dvi' => 'application/x-dvi', + 'dwg' => 'image/vnd.dwg', + 'dxr' => 'application/x-director', + 'eps' => 'application/postscript', + 'etx' => 'text/x-setext', + 'exe' => 'application/octet-stream', + 'ez' => 'application/andrew-inset', + 'flv' => 'video/x-flv', + 'gif' => 'image/gif', + 'gtar' => 'application/x-gtar', + 'gz' => 'application/x-gzip', + 'hdf' => 'application/x-hdf', + 'hqx' => 'application/mac-binhex40', + 'htm' => 'text/html', + 'html' => 'text/html', + 'ice' => 'x-conference/x-cooltalk', + 'ief' => 'image/ief', + 'iges' => 'model/iges', + 'igs' => 'model/iges', + 'img' => 'application/octet-stream', + 'iso' => 'application/octet-stream', + 'jad' => 'text/vnd.sun.j2me.app-descriptor', + 'jar' => 'application/x-java-archive', + 'jnlp' => 'application/x-java-jnlp-file', + 'jpe' => 'image/jpeg', + 'jpeg' => 'image/jpeg', + 'jpg' => 'image/jpeg', + 'js' => 'application/x-javascript', + 'kar' => 'audio/midi', + 'kil' => 'application/x-killustrator', + 'kpr' => 'application/x-kpresenter', + 'kpt' => 'application/x-kpresenter', + 'ksp' => 'application/x-kspread', + 'kwd' => 'application/x-kword', + 'kwt' => 'application/x-kword', + 'kml' => 'application/vnd.google-earth.kml+xml', + 'kmz' => 'application/vnd.google-earth.kmz', + 'latex' => 'application/x-latex', + 'lha' => 'application/octet-stream', + 'lzh' => 'application/octet-stream', + 'm3u' => 'audio/x-mpegurl', + 'man' => 'application/x-troff-man', + 'me' => 'application/x-troff-me', + 'mesh' => 'model/mesh', + 'mid' => 'audio/midi', + 'midi' => 'audio/midi', + 'mif' => 'application/vnd.mif', + 'mov' => 'video/quicktime', + 'movie' => 'video/x-sgi-movie', + 'mp2' => 'audio/mpeg', + 'mp3' => 'audio/mpeg', + 'mp4' => 'video/mp4', + 'mpe' => 'video/mpeg', + 'mpg' => 'video/mpeg', + 'mpeg' => 'video/mpeg', + 'ms' => 'application/x-troff-ms', + 'msh' => 'model/mesh', + 'mxu' => 'video/vnd.mpegurl', + 'nc' => 'application/x-netcdf', + 'odb' => 'application/vnd.oasis.opendocument.database', + 'odc' => 'application/vnd.oasis.opendocument.chart', + 'odf' => 'application/vnd.oasis.opendocument.formula', + 'odg' => 'application/vnd.oasis.opendocument.graphics', + 'odi' => 'application/vnd.oasis.opendocument.image', + 'odm' => 'application/vnd.oasis.opendocument.text-master', + 'odp' => 'application/vnd.oasis.opendocument.presentation', + 'ods' => 'application/vnd.oasis.opendocument.spreadsheet', + 'odt' => 'application/vnd.oasis.opendocument.text', + 'ogg' => 'application/ogg', + 'otg' => 'application/vnd.oasis.opendocument.graphics-template', + 'oth' => 'application/vnd.oasis.opendocument.text-web', + 'otp' => 'application/vnd.oasis.opendocument.presentation-template', + 'ots' => 'application/vnd.oasis.opendocument.spreadsheet-template', + 'ott' => 'application/vnd.oasis.opendocument.text-template', + 'pbm' => 'image/x-portable-bitmap', + 'pdb' => 'chemical/x-pdb', + 'pdf' => 'application/pdf', + 'pgm' => 'image/x-portable-graymap', + 'pgn' => 'application/x-chess-pgn', + 'php' => 'text/x-php', + 'png' => 'image/png', + 'pnm' => 'image/x-portable-anymap', + 'ppm' => 'image/x-portable-pixmap', + 'ppt' => 'application/vnd.ms-powerpoint', + 'ps' => 'application/postscript', + 'qt' => 'video/quicktime', + 'ra' => 'audio/x-realaudio', + 'ram' => 'audio/x-pn-realaudio', + 'ras' => 'image/x-cmu-raster', + 'rgb' => 'image/x-rgb', + 'rm' => 'audio/x-pn-realaudio', + 'roff' => 'application/x-troff', + 'rpm' => 'application/x-rpm', + 'rtf' => 'text/rtf', + 'rtx' => 'text/richtext', + 'sgm' => 'text/sgml', + 'sgml' => 'text/sgml', + 'sh' => 'application/x-sh', + 'shar' => 'application/x-shar', + 'silo' => 'model/mesh', + 'sis' => 'application/vnd.symbian.install', + 'sit' => 'application/x-stuffit', + 'skd' => 'application/x-koan', + 'skm' => 'application/x-koan', + 'skp' => 'application/x-koan', + 'skt' => 'application/x-koan', + 'smi' => 'application/smil', + 'smil' => 'application/smil', + 'snd' => 'audio/basic', + 'svg' => 'image/svg+xml', + 'so' => 'application/octet-stream', + 'spl' => 'application/x-futuresplash', + 'src' => 'application/x-wais-source', + 'stc' => 'application/vnd.sun.xml.calc.template', + 'std' => 'application/vnd.sun.xml.draw.template', + 'sti' => 'application/vnd.sun.xml.impress.template', + 'stw' => 'application/vnd.sun.xml.writer.template', + 'sv4cpio' => 'application/x-sv4cpio', + 'sv4crc' => 'application/x-sv4crc', + 'swf' => 'application/x-shockwave-flash', + 'sxc' => 'application/vnd.sun.xml.calc', + 'sxd' => 'application/vnd.sun.xml.draw', + 'sxg' => 'application/vnd.sun.xml.writer.global', + 'sxi' => 'application/vnd.sun.xml.impress', + 'sxm' => 'application/vnd.sun.xml.math', + 'sxw' => 'application/vnd.sun.xml.writer', + 't' => 'application/x-troff', + 'tar' => 'application/x-tar', + 'tcl' => 'application/x-tcl', + 'tex' => 'application/x-tex', + 'texi' => 'application/x-texinfo', + 'texinfo' => 'application/x-texinfo', + 'tgz' => 'application/x-gzip', + 'tif' => 'image/tiff', + 'tiff' => 'image/tiff', + 'torrent' => 'application/x-bittorrent', + 'tr' => 'application/x-troff', + 'tsv' => 'text/tab-separated-values', + 'txt' => 'text/plain', + 'ustar' => 'application/x-ustar', + 'vcd' => 'application/x-cdlink', + 'vrml' => 'model/vrml', + 'wav' => 'audio/x-wav', + 'wax' => 'audio/x-ms-wax', + 'wbmp' => 'image/vnd.wap.wbmp', + 'wbxml' => 'application/vnd.wap.wbxml', + 'wm' => 'video/x-ms-wm', + 'wma' => 'audio/x-ms-wma', + 'wml' => 'text/vnd.wap.wml', + 'wmlc' => 'application/vnd.wap.wmlc', + 'wmls' => 'text/vnd.wap.wmlscript', + 'wmlsc' => 'application/vnd.wap.wmlscriptc', + 'wmv' => 'video/x-ms-wmv', + 'wmx' => 'video/x-ms-wmx', + 'wrl' => 'model/vrml', + 'wvx' => 'video/x-ms-wvx', + 'xbm' => 'image/x-xbitmap', + 'xht' => 'application/xhtml+xml', + 'xhtml' => 'application/xhtml+xml', + 'xml' => 'text/xml', + 'xml' => 'application/xml', + 'xpm' => 'image/x-xpixmap', + 'xsl' => 'text/xsl', + 'xwd' => 'image/x-xwindowdump', + 'xyz' => 'chemical/x-xyz', + 'zip' => 'application/zip', + 'doc' => 'application/msword', + 'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', + 'dotx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.template', + 'docm' => 'application/vnd.ms-word.document.macroEnabled.12', + 'xls' => 'application/vnd.ms-excel', + 'xlsx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', + 'xltx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.template', + 'xlsm' => 'application/vnd.ms-excel.sheet.macroEnabled.12', + 'xltm' => 'application/vnd.ms-excel.template.macroEnabled.12', + 'xlam' => 'application/vnd.ms-excel.addin.macroEnabled.12', + 'xlsb' => 'application/vnd.ms-excel.sheet.binary.macroEnabled.12', + 'ppt' => 'application/vnd.ms-powerpoint', + 'pptx' => 'application/vnd.openxmlformats-officedocument.presentationml.presentation', + 'potx' => 'application/vnd.openxmlformats-officedocument.presentationml.template', + 'ppsx' => 'application/vnd.openxmlformats-officedocument.presentationml.slideshow', + 'ppam' => 'application/vnd.ms-powerpoint.addin.macroEnabled.12', + 'pptm' => 'application/vnd.ms-powerpoint.presentation.macroEnabled.12', + 'potm' => 'application/vnd.ms-powerpoint.template.macroEnabled.12', + 'ppsm' => 'application/vnd.ms-powerpoint.slideshow.macroEnabled.12', +); + +if ( ! function_exists('get_extension_from_mime')) +{ + function get_extension_from_mime($mime){ + global $mime_types; + if(strpos($mime, ';')!==FALSE){ + $mime = substr($mime, 0,strpos($mime, ';')); + } + $mime_types_conv = array_flip($mime_types); + if(isset($mime_types_conv[$mime])){ + return $mime_types_conv[$mime]; + } + return ''; + } +} + +if ( ! function_exists('get_file_mime_type')) +{ + function get_file_mime_type($filename, $debug = false) + { + if (function_exists('finfo_open') && function_exists('finfo_file') && function_exists('finfo_close')) + { + $fileinfo = finfo_open(FILEINFO_MIME_TYPE); + $mime_type = finfo_file($fileinfo, $filename); + finfo_close($fileinfo); + + if ( ! empty($mime_type)) + { + if (true === $debug) + { + return array( 'mime_type' => $mime_type, 'method' => 'fileinfo' ); + } + + return $mime_type; + } + } + + if (function_exists('mime_content_type')) + { + $mime_type = mime_content_type($filename); + + if ( ! empty($mime_type)) + { + if (true === $debug) + { + return array( 'mime_type' => $mime_type, 'method' => 'mime_content_type' ); + } + + return $mime_type; + } + } + + global $mime_types; + + $tmp_array = explode('.', $filename); + $ext = strtolower(array_pop($tmp_array)); + + if ( ! empty($mime_types[ $ext ])) + { + if (true === $debug) + { + return array( 'mime_type' => $mime_types[ $ext ], 'method' => 'from_array' ); + } + + return $mime_types[ $ext ]; + } + + if (true === $debug) + { + return array( 'mime_type' => 'application/octet-stream', 'method' => 'last_resort' ); + } + + return 'application/octet-stream'; + } +} + + +/******************** + * The following code can be used to test the function. + * First put a plain text file named "test.txt" and a + * JPEG image file named "image.jpg" in the same folder + * as this file. + * + * Simply remove the "REMOVE ME TO TEST" lines below to have + * the code run when this file runs. + * + * Run the code with this command: + * php mime_type_lib.php + ********************/ + + +/* REMOVE ME TO TEST +echo get_file_mime_type( 'test.txt' ) . "\n"; +echo print_r( get_file_mime_type( 'image.jpg', true ), true ) . "\n"; +REMOVE ME TO TEST */ diff --git a/local/modules/Tinymce/Resources/js/tinymce/filemanager/include/php_image_magician.php b/local/modules/Tinymce/Resources/js/tinymce/filemanager/include/php_image_magician.php new file mode 100644 index 00000000..a16ac96a --- /dev/null +++ b/local/modules/Tinymce/Resources/js/tinymce/filemanager/include/php_image_magician.php @@ -0,0 +1,3783 @@ + resizeImage(150, 100, 0); +# $magicianObj -> saveImage('images/car_small.jpg', 100); +# +# - See end of doc for more examples - +# +# Supported file types include: jpg, png, gif, bmp, psd (read) +# +# +# +# The following functions are taken from phpThumb() [available from +# http://phpthumb.sourceforge.net], and are used with written permission +# from James Heinrich. +# - GD2BMPstring +# - GetPixelColor +# - LittleEndian2String +# +# The following functions are from Marc Hibbins and are used with written +# permission (are also under the Attribution-ShareAlike +# [http://creativecommons.org/licenses/by-sa/3.0/] license. +# - +# +# PhpPsdReader is used with written permission from Tim de Koning. +# [http://www.kingsquare.nl/phppsdreader] +# +# +# +# Modificatoin history +# Date Initials Ver Description +# 10-05-11 J.C.O 0.0 Initial build +# 01-06-11 J.C.O 0.1.1 * Added reflections +# * Added Rounded corners +# * You can now use PNG interlacing +# * Added shadow +# * Added caption box +# * Added vintage filter +# * Added dynamic image resizing (resize on the fly) +# * minor bug fixes +# 05-06-11 J.C.O 0.1.1.1 * Fixed undefined variables +# 17-06-11 J.C.O 0.1.2 * Added image_batch_class.php class +# * Minor bug fixes +# 26-07-11 J.C.O 0.1.4 * Added support for external images +# * Can now set the crop poisition +# 03-08-11 J.C.O 0.1.5 * Added reset() method to reset resource to +# original input file. +# * Added method addTextToCaptionBox() to +# simplify adding text to a caption box. +# * Added experimental writeIPTC. (not finished) +# * Added experimental readIPTC. (not finished) +# 11-08-11 J.C.O * Added initial border presets. +# 30-08-11 J.C.O * Added 'auto' crop option to crop portrait +# images near the top. +# 08-09-11 J.C.O * Added cropImage() method to allow standalone +# cropping. +# 17-09-11 J.C.O * Added setCropFromTop() set method - set the +# percentage to crop from the top when using +# crop 'auto' option. +# * Added setTransparency() set method - allows you +# to turn transparency off (like when saving +# as a jpg). +# * Added setFillColor() set method - set the +# background color to use instead of transparency. +# 05-11-11 J.C.O 0.1.5.1 * Fixed interlacing option +# 0-07-12 J.C.O 1.0 +# +# Known issues & Limitations: +# ------------------------------- +# Not so much an issue, the image is destroyed on the deconstruct rather than +# when we have finished with it. The reason for this is that we don't know +# when we're finished with it as you can both save the image and display +# it directly to the screen (imagedestroy($this->imageResized)) +# +# Opening BMP files is slow. A test with 884 bmp files processed in a loop +# takes forever - over 5 min. This test inlcuded opening the file, then +# getting and displaying its width and height. +# +# $forceStretch: +# ------------------------------- +# On by default. +# $forceStretch can be disabled by calling method setForceStretch with false +# parameter. If disabled, if an images original size is smaller than the size +# specified by the user, the original size will be used. This is useful when +# dealing with small images. +# +# If enabled, images smaller than the size specified will be stretched to +# that size. +# +# Tips: +# ------------------------------- +# * If you're resizing a transparent png and saving it as a jpg, set +# $keepTransparency to false with: $magicianObj->setTransparency(false); +# +# FEATURES: +# * EASY TO USE +# * BMP SUPPORT (read & write) +# * PSD (photoshop) support (read) +# * RESIZE IMAGES +# - Preserve transparency (png, gif) +# - Apply sharpening (jpg) (requires PHP >= 5.1.0) +# - Set image quality (jpg, png) +# - Resize modes: +# - exact size +# - resize by width (auto height) +# - resize by height (auto width) +# - auto (automatically determine the best of the above modes to use) +# - crop - resize as best as it can then crop the rest +# - Force stretching of smaller images (upscale) +# * APPLY FILTERS +# - Convert to grey scale +# - Convert to black and white +# - Convert to sepia +# - Convert to negative +# * ROTATE IMAGES +# - Rotate using predefined "left", "right", or "180"; or any custom degree amount +# * EXTRACT EXIF DATA (requires exif module) +# - make +# - model +# - date +# - exposure +# - aperture +# - f-stop +# - iso +# - focal length +# - exposure program +# - metering mode +# - flash status +# - creator +# - copyright +# * ADD WATERMARK +# - Specify exact x, y placement +# - Or, specify using one of the 9 pre-defined placements such as "tl" +# (for top left), "m" (for middle), "br" (for bottom right) +# - also specify padding from edge amount (optional). +# - Set opacity of watermark (png). +# * ADD BORDER +# * USE HEX WHEN SPECIFYING COLORS (eg: #ffffff) +# * SAVE IMAGE OR OUTPUT TO SCREEN +# +# +# ========================================================================# + + +class imageLib { + + private $fileName; + private $image; + protected $imageResized; + private $widthOriginal; # Always be the original width + private $heightOriginal; + private $width; # Current width (width after resize) + private $height; + private $imageSize; + private $fileExtension; + + private $debug = true; + private $errorArray = array(); + + private $forceStretch = true; + private $aggresiveSharpening = false; + + private $transparentArray = array( '.png', '.gif' ); + private $keepTransparency = true; + private $fillColorArray = array( 'r' => 255, 'g' => 255, 'b' => 255 ); + + private $sharpenArray = array( 'jpg' ); + + private $psdReaderPath; + private $filterOverlayPath; + + private $isInterlace; + + private $captionBoxPositionArray = array(); + + private $fontDir = 'fonts'; + + private $cropFromTopPercent = 10; + + +## -------------------------------------------------------- + + function __construct($fileName) + # Author: Jarrod Oberto + # Date: 27-02-08 + # Purpose: Constructor + # Param in: $fileName: File name and path. + # Param out: n/a + # Reference: + # Notes: + # + { + if ( ! $this->testGDInstalled()) + { + if ($this->debug) + { + throw new Exception('The GD Library is not installed.'); + } + else + { + throw new Exception(); + } + }; + + $this->initialise(); + + // *** Save the image file name. Only store this incase you want to display it + $this->fileName = $fileName; + $this->fileExtension = fix_strtolower(strrchr($fileName, '.')); + + // *** Open up the file + $this->image = $this->openImage($fileName); + + + // *** Assign here so we don't modify the original + $this->imageResized = $this->image; + + // *** If file is an image + if ($this->testIsImage($this->image)) + { + // *** Get width and height + $this->width = imagesx($this->image); + $this->widthOriginal = imagesx($this->image); + $this->height = imagesy($this->image); + $this->heightOriginal = imagesy($this->image); + + + /* Added 15-09-08 + * Get the filesize using this build in method. + * Stores an array of size + * + * $this->imageSize[1] = width + * $this->imageSize[2] = height + * $this->imageSize[3] = width x height + * + */ + $this->imageSize = getimagesize($this->fileName); + + } + else + { + $this->errorArray[] = 'File is not an image'; + } + } + +## -------------------------------------------------------- + + private function initialise() + { + + $this->psdReaderPath = dirname(__FILE__) . '/classPhpPsdReader.php'; + $this->filterOverlayPath = dirname(__FILE__) . '/filters'; + + // *** Set if image should be interlaced or not. + $this->isInterlace = false; + } + + + /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*- + Resize +*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*/ + + + public function resizeImage($newWidth, $newHeight, $option = 0, $sharpen = false, $autoRotate = false) + # Author: Jarrod Oberto + # Date: 27-02-08 + # Purpose: Resizes the image + # Param in: $newWidth: + # $newHeight: + # $option: 0 / exact = defined size; + # 1 / portrait = keep aspect set height; + # 2 / landscape = keep aspect set width; + # 3 / auto = auto; + # 4 / crop= resize and crop; + # + # $option can also be an array containing options for + # cropping. E.G., array('crop', 'r') + # + # This array only applies to 'crop' and the 'r' refers to + # "crop right". Other value include; tl, t, tr, l, m (default), + # r, bl, b, br, or you can specify your own co-ords (which + # isn't recommended. + # + # $sharpen: true: sharpen (jpg only); + # false: don't sharpen + # Param out: n/a + # Reference: + # Notes: To clarify the $option input: + # 0 = The exact height and width dimensions you set. + # 1 = Whatever height is passed in will be the height that + # is set. The width will be calculated and set automatically + # to a the value that keeps the original aspect ratio. + # 2 = The same but based on the width. We try make the image the + # biggest size we can while stil fitting inside the box size + # 3 = Depending whether the image is landscape or portrait, this + # will automatically determine whether to resize via + # dimension 1,2 or 0 + # 4 = Will resize and then crop the image for best fit + # + # forceStretch can be applied to options 1,2,3 and 4 + # + { + + // *** We can pass in an array of options to change the crop position + $cropPos = 'm'; + if (is_array($option) && fix_strtolower($option[0]) == 'crop') + { + $cropPos = $option[1]; # get the crop option + } + else + { + if (strpos($option, '-') !== false) + { + // *** Or pass in a hyphen seperated option + $optionPiecesArray = explode('-', $option); + $cropPos = end($optionPiecesArray); + } + } + + // *** Check the option is valid + $option = $this->prepOption($option); + + // *** Make sure the file passed in is valid + if ( ! $this->image) + { + if ($this->debug) + { + throw new Exception('file ' . $this->getFileName() . ' is missing or invalid'); + } + else + { + throw new Exception(); + } + }; + + // *** Get optimal width and height - based on $option + $dimensionsArray = $this->getDimensions($newWidth, $newHeight, $option); + + $optimalWidth = $dimensionsArray['optimalWidth']; + $optimalHeight = $dimensionsArray['optimalHeight']; + + // *** Resample - create image canvas of x, y size + $this->imageResized = imagecreatetruecolor($optimalWidth, $optimalHeight); + $this->keepTransparancy($optimalWidth, $optimalHeight, $this->imageResized); + imagecopyresampled($this->imageResized, $this->image, 0, 0, 0, 0, $optimalWidth, $optimalHeight, $this->width, $this->height); + + + // *** If '4', then crop too + if ($option == 4 || $option == 'crop') + { + + if (($optimalWidth >= $newWidth && $optimalHeight >= $newHeight)) + { + $this->crop($optimalWidth, $optimalHeight, $newWidth, $newHeight, $cropPos); + } + } + + // *** If Rotate. + if ($autoRotate) + { + + $exifData = $this->getExif(false); + if (count($exifData) > 0) + { + + switch ($exifData['orientation']) + { + case 8: + $this->imageResized = imagerotate($this->imageResized, 90, 0); + break; + case 3: + $this->imageResized = imagerotate($this->imageResized, 180, 0); + break; + case 6: + $this->imageResized = imagerotate($this->imageResized, -90, 0); + break; + } + } + } + + // *** Sharpen image (if jpg and the user wishes to do so) + if ($sharpen && in_array($this->fileExtension, $this->sharpenArray)) + { + + // *** Sharpen + $this->sharpen(); + } + } + +## -------------------------------------------------------- + + public function cropImage($newWidth, $newHeight, $cropPos = 'm') + # Author: Jarrod Oberto + # Date: 08-09-11 + # Purpose: Crops the image + # Param in: $newWidth: crop with + # $newHeight: crop height + # $cropPos: Can be any of the following: + # tl, t, tr, l, m, r, bl, b, br, auto + # Or: + # a custom position such as '30x50' + # Param out: n/a + # Reference: + # Notes: + # + { + + // *** Make sure the file passed in is valid + if ( ! $this->image) + { + if ($this->debug) + { + throw new Exception('file ' . $this->getFileName() . ' is missing or invalid'); + } + else + { + throw new Exception(); + } + }; + + $this->imageResized = $this->image; + $this->crop($this->width, $this->height, $newWidth, $newHeight, $cropPos); + + } + +## -------------------------------------------------------- + + private function keepTransparancy($width, $height, $im) + # Author: Jarrod Oberto + # Date: 08-04-11 + # Purpose: Keep transparency for png and gif image + # Param in: + # Param out: n/a + # Reference: + # Notes: + # + { + // *** If PNG, perform some transparency retention actions (gif untested) + if (in_array($this->fileExtension, $this->transparentArray) && $this->keepTransparency) + { + imagealphablending($im, false); + imagesavealpha($im, true); + $transparent = imagecolorallocatealpha($im, 255, 255, 255, 127); + imagefilledrectangle($im, 0, 0, $width, $height, $transparent); + } + else + { + $color = imagecolorallocate($im, $this->fillColorArray['r'], $this->fillColorArray['g'], $this->fillColorArray['b']); + imagefilledrectangle($im, 0, 0, $width, $height, $color); + } + } + +## -------------------------------------------------------- + + private function crop($optimalWidth, $optimalHeight, $newWidth, $newHeight, $cropPos) + # Author: Jarrod Oberto + # Date: 15-09-08 + # Purpose: Crops the image + # Param in: $newWidth: + # $newHeight: + # Param out: n/a + # Reference: + # Notes: + # + { + + // *** Get cropping co-ordinates + $cropArray = $this->getCropPlacing($optimalWidth, $optimalHeight, $newWidth, $newHeight, $cropPos); + $cropStartX = $cropArray['x']; + $cropStartY = $cropArray['y']; + + // *** Crop this bad boy + $crop = imagecreatetruecolor($newWidth, $newHeight); + $this->keepTransparancy($optimalWidth, $optimalHeight, $crop); + imagecopyresampled($crop, $this->imageResized, 0, 0, $cropStartX, $cropStartY, $newWidth, $newHeight, $newWidth, $newHeight); + + $this->imageResized = $crop; + + // *** Set new width and height to our variables + $this->width = $newWidth; + $this->height = $newHeight; + + } + +## -------------------------------------------------------- + + private function getCropPlacing($optimalWidth, $optimalHeight, $newWidth, $newHeight, $pos = 'm') + # + # Author: Jarrod Oberto + # Date: July 11 + # Purpose: Set the cropping area. + # Params in: + # Params out: (array) the crop x and y co-ordinates. + # Notes: When specifying the exact pixel crop position (eg 10x15), be + # very careful as it's easy to crop out of the image leaving + # black borders. + # + { + $pos = fix_strtolower($pos); + + // *** If co-ords have been entered + if (strstr($pos, 'x')) + { + $pos = str_replace(' ', '', $pos); + + $xyArray = explode('x', $pos); + list($cropStartX, $cropStartY) = $xyArray; + + } + else + { + + switch ($pos) + { + case 'tl': + $cropStartX = 0; + $cropStartY = 0; + break; + + case 't': + $cropStartX = ($optimalWidth / 2) - ($newWidth / 2); + $cropStartY = 0; + break; + + case 'tr': + $cropStartX = $optimalWidth - $newWidth; + $cropStartY = 0; + break; + + case 'l': + $cropStartX = 0; + $cropStartY = ($optimalHeight / 2) - ($newHeight / 2); + break; + + case 'm': + $cropStartX = ($optimalWidth / 2) - ($newWidth / 2); + $cropStartY = ($optimalHeight / 2) - ($newHeight / 2); + break; + + case 'r': + $cropStartX = $optimalWidth - $newWidth; + $cropStartY = ($optimalHeight / 2) - ($newHeight / 2); + break; + + case 'bl': + $cropStartX = 0; + $cropStartY = $optimalHeight - $newHeight; + break; + + case 'b': + $cropStartX = ($optimalWidth / 2) - ($newWidth / 2); + $cropStartY = $optimalHeight - $newHeight; + break; + + case 'br': + $cropStartX = $optimalWidth - $newWidth; + $cropStartY = $optimalHeight - $newHeight; + break; + + case 'auto': + // *** If image is a portrait crop from top, not center. v1.5 + if ($optimalHeight > $optimalWidth) + { + $cropStartX = ($optimalWidth / 2) - ($newWidth / 2); + $cropStartY = ($this->cropFromTopPercent / 100) * $optimalHeight; + } + else + { + + // *** Else crop from the center + $cropStartX = ($optimalWidth / 2) - ($newWidth / 2); + $cropStartY = ($optimalHeight / 2) - ($newHeight / 2); + } + break; + + default: + // *** Default to center + $cropStartX = ($optimalWidth / 2) - ($newWidth / 2); + $cropStartY = ($optimalHeight / 2) - ($newHeight / 2); + break; + } + } + + return array( 'x' => $cropStartX, 'y' => $cropStartY ); + } + +## -------------------------------------------------------- + + private function getDimensions($newWidth, $newHeight, $option) + # Author: Jarrod Oberto + # Date: 17-11-09 + # Purpose: Get new image dimensions based on user specificaions + # Param in: $newWidth: + # $newHeight: + # Param out: Array of new width and height values + # Reference: + # Notes: If $option = 3 then this function is call recursivly + # + # To clarify the $option input: + # 0 = The exact height and width dimensions you set. + # 1 = Whatever height is passed in will be the height that + # is set. The width will be calculated and set automatically + # to a the value that keeps the original aspect ratio. + # 2 = The same but based on the width. + # 3 = Depending whether the image is landscape or portrait, this + # will automatically determine whether to resize via + # dimension 1,2 or 0. + # 4 = Resize the image as much as possible, then crop the + # remainder. + { + + switch (strval($option)) + { + case '0': + case 'exact': + $optimalWidth = $newWidth; + $optimalHeight = $newHeight; + break; + case '1': + case 'portrait': + $dimensionsArray = $this->getSizeByFixedHeight($newWidth, $newHeight); + $optimalWidth = $dimensionsArray['optimalWidth']; + $optimalHeight = $dimensionsArray['optimalHeight']; + break; + case '2': + case 'landscape': + $dimensionsArray = $this->getSizeByFixedWidth($newWidth, $newHeight); + $optimalWidth = $dimensionsArray['optimalWidth']; + $optimalHeight = $dimensionsArray['optimalHeight']; + break; + case '3': + case 'auto': + $dimensionsArray = $this->getSizeByAuto($newWidth, $newHeight); + $optimalWidth = $dimensionsArray['optimalWidth']; + $optimalHeight = $dimensionsArray['optimalHeight']; + break; + case '4': + case 'crop': + $dimensionsArray = $this->getOptimalCrop($newWidth, $newHeight); + $optimalWidth = $dimensionsArray['optimalWidth']; + $optimalHeight = $dimensionsArray['optimalHeight']; + break; + } + + return array( 'optimalWidth' => $optimalWidth, 'optimalHeight' => $optimalHeight ); + } + +## -------------------------------------------------------- + + private function getSizeByFixedHeight($newWidth, $newHeight) + { + // *** If forcing is off... + if ( ! $this->forceStretch) + { + + // *** ...check if actual height is less than target height + if ($this->height < $newHeight) + { + return array( 'optimalWidth' => $this->width, 'optimalHeight' => $this->height ); + } + } + + $ratio = $this->width / $this->height; + + $newWidth = $newHeight * $ratio; + + //return $newWidth; + return array( 'optimalWidth' => $newWidth, 'optimalHeight' => $newHeight ); + } + +## -------------------------------------------------------- + + private function getSizeByFixedWidth($newWidth, $newHeight) + { + // *** If forcing is off... + if ( ! $this->forceStretch) + { + + // *** ...check if actual width is less than target width + if ($this->width < $newWidth) + { + return array( 'optimalWidth' => $this->width, 'optimalHeight' => $this->height ); + } + } + + $ratio = $this->height / $this->width; + + $newHeight = $newWidth * $ratio; + + //return $newHeight; + return array( 'optimalWidth' => $newWidth, 'optimalHeight' => $newHeight ); + } + +## -------------------------------------------------------- + + private function getSizeByAuto($newWidth, $newHeight) + # Author: Jarrod Oberto + # Date: 19-08-08 + # Purpose: Depending on the height, choose to resize by 0, 1, or 2 + # Param in: The new height and new width + # Notes: + # + { + // *** If forcing is off... + if ( ! $this->forceStretch) + { + + // *** ...check if actual size is less than target size + if ($this->width < $newWidth && $this->height < $newHeight) + { + return array( 'optimalWidth' => $this->width, 'optimalHeight' => $this->height ); + } + } + + if ($this->height < $this->width) + // *** Image to be resized is wider (landscape) + { + //$optimalWidth = $newWidth; + //$optimalHeight= $this->getSizeByFixedWidth($newWidth); + + $dimensionsArray = $this->getSizeByFixedWidth($newWidth, $newHeight); + $optimalWidth = $dimensionsArray['optimalWidth']; + $optimalHeight = $dimensionsArray['optimalHeight']; + } + elseif ($this->height > $this->width) + // *** Image to be resized is taller (portrait) + { + //$optimalWidth = $this->getSizeByFixedHeight($newHeight); + //$optimalHeight= $newHeight; + + $dimensionsArray = $this->getSizeByFixedHeight($newWidth, $newHeight); + $optimalWidth = $dimensionsArray['optimalWidth']; + $optimalHeight = $dimensionsArray['optimalHeight']; + } + else + // *** Image to be resizerd is a square + { + + if ($newHeight < $newWidth) + { + //$optimalWidth = $newWidth; + //$optimalHeight= $this->getSizeByFixedWidth($newWidth); + $dimensionsArray = $this->getSizeByFixedWidth($newWidth, $newHeight); + $optimalWidth = $dimensionsArray['optimalWidth']; + $optimalHeight = $dimensionsArray['optimalHeight']; + } + else + { + if ($newHeight > $newWidth) + { + //$optimalWidth = $this->getSizeByFixedHeight($newHeight); + //$optimalHeight= $newHeight; + $dimensionsArray = $this->getSizeByFixedHeight($newWidth, $newHeight); + $optimalWidth = $dimensionsArray['optimalWidth']; + $optimalHeight = $dimensionsArray['optimalHeight']; + } + else + { + // *** Sqaure being resized to a square + $optimalWidth = $newWidth; + $optimalHeight = $newHeight; + } + } + } + + return array( 'optimalWidth' => $optimalWidth, 'optimalHeight' => $optimalHeight ); + } + +## -------------------------------------------------------- + + private function getOptimalCrop($newWidth, $newHeight) + # Author: Jarrod Oberto + # Date: 17-11-09 + # Purpose: Get optimal crop dimensions + # Param in: width and height as requested by user (fig 3) + # Param out: Array of optimal width and height (fig 2) + # Reference: + # Notes: The optimal width and height return are not the same as the + # same as the width and height passed in. For example: + # + # + # |-----------------| |------------| |-------| + # | | => |**| |**| => | | + # | | |**| |**| | | + # | | |------------| |-------| + # |-----------------| + # original optimal crop + # size size size + # Fig 1 2 3 + # + # 300 x 250 150 x 125 150 x 100 + # + # The optimal size is the smallest size (that is closest to the crop size) + # while retaining proportion/ratio. + # + # The crop size is the optimal size that has been cropped on one axis to + # make the image the exact size specified by the user. + # + # * represent cropped area + # + { + + // *** If forcing is off... + if ( ! $this->forceStretch) + { + + // *** ...check if actual size is less than target size + if ($this->width < $newWidth && $this->height < $newHeight) + { + return array( 'optimalWidth' => $this->width, 'optimalHeight' => $this->height ); + } + } + + $heightRatio = $this->height / $newHeight; + $widthRatio = $this->width / $newWidth; + + if ($heightRatio < $widthRatio) + { + $optimalRatio = $heightRatio; + } + else + { + $optimalRatio = $widthRatio; + } + + $optimalHeight = round($this->height / $optimalRatio); + $optimalWidth = round($this->width / $optimalRatio); + + return array( 'optimalWidth' => $optimalWidth, 'optimalHeight' => $optimalHeight ); + } + +## -------------------------------------------------------- + + private function sharpen() + # Author: Jarrod Oberto + # Date: 08 04 2011 + # Purpose: Sharpen image + # Param in: n/a + # Param out: n/a + # Reference: + # Notes: + # Credit: Incorporates Joe Lencioni (August 6, 2008) code + { + + if (version_compare(PHP_VERSION, '5.1.0') >= 0) + { + + // *** + if ($this->aggresiveSharpening) + { # A more aggressive sharpening solution + + $sharpenMatrix = array( array( -1, -1, -1 ), + array( -1, 16, -1 ), + array( -1, -1, -1 ) ); + $divisor = 8; + $offset = 0; + + imageconvolution($this->imageResized, $sharpenMatrix, $divisor, $offset); + } + else # More subtle and personally more desirable + { + $sharpness = $this->findSharp($this->widthOriginal, $this->width); + + $sharpenMatrix = array( + array( -1, -2, -1 ), + array( -2, $sharpness + 12, -2 ), //Lessen the effect of a filter by increasing the value in the center cell + array( -1, -2, -1 ) + ); + $divisor = $sharpness; // adjusts brightness + $offset = 0; + imageconvolution($this->imageResized, $sharpenMatrix, $divisor, $offset); + } + } + else + { + if ($this->debug) + { + throw new Exception('Sharpening required PHP 5.1.0 or greater.'); + } + } + } + + ## -------------------------------------------------------- + + private function sharpen2($level) + { + $sharpenMatrix = array( + array( $level, $level, $level ), + array( $level, (8 * $level) + 1, $level ), //Lessen the effect of a filter by increasing the value in the center cell + array( $level, $level, $level ) + ); + + } + +## -------------------------------------------------------- + + private function findSharp($orig, $final) + # Author: Ryan Rud (http://adryrun.com) + # Purpose: Find optimal sharpness + # Param in: n/a + # Param out: n/a + # Reference: + # Notes: + # + { + $final = $final * (750.0 / $orig); + $a = 52; + $b = -0.27810650887573124; + $c = .00047337278106508946; + + $result = $a + $b * $final + $c * $final * $final; + + return max(round($result), 0); + } + +## -------------------------------------------------------- + + private function prepOption($option) + # Author: Jarrod Oberto + # Purpose: Prep option like change the passed in option to lowercase + # Param in: (str/int) $option: eg. 'exact', 'crop'. 0, 4 + # Param out: lowercase string + # Reference: + # Notes: + # + { + if (is_array($option)) + { + if (fix_strtolower($option[0]) == 'crop' && count($option) == 2) + { + return 'crop'; + } + else + { + throw new Exception('Crop resize option array is badly formatted.'); + } + } + else + { + if (strpos($option, 'crop') !== false) + { + return 'crop'; + } + } + + if (is_string($option)) + { + return fix_strtolower($option); + } + + return $option; + } + + + /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*- + Presets +*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*/ + +# +# Preset are pre-defined templates you can apply to your image. +# +# These are inteded to be applied to thumbnail images. +# + + + public function borderPreset($preset) + { + switch ($preset) + { + + case 'simple': + $this->addBorder(7, '#fff'); + $this->addBorder(6, '#f2f1f0'); + $this->addBorder(2, '#fff'); + $this->addBorder(1, '#ccc'); + break; + default: + break; + } + + } + + + /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*- + Draw border +*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*/ + + public function addBorder($thickness = 1, $rgbArray = array( 255, 255, 255 )) + # Author: Jarrod Oberto + # Date: 05-05-11 + # Purpose: Add a border to the image + # Param in: + # Param out: + # Reference: + # Notes: This border is added to the INSIDE of the image + # + { + if ($this->imageResized) + { + + $rgbArray = $this->formatColor($rgbArray); + $r = $rgbArray['r']; + $g = $rgbArray['g']; + $b = $rgbArray['b']; + + + $x1 = 0; + $y1 = 0; + $x2 = ImageSX($this->imageResized) - 1; + $y2 = ImageSY($this->imageResized) - 1; + + $rgbArray = ImageColorAllocate($this->imageResized, $r, $g, $b); + + + for ($i = 0; $i < $thickness; $i++) + { + ImageRectangle($this->imageResized, $x1++, $y1++, $x2--, $y2--, $rgbArray); + } + } + } + + + /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*- + Gray Scale +*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*/ + + public function greyScale() + # Author: Jarrod Oberto + # Date: 07-05-2011 + # Purpose: Make image greyscale + # Param in: n/a + # Param out: + # Reference: + # Notes: + # + { + if ($this->imageResized) + { + imagefilter($this->imageResized, IMG_FILTER_GRAYSCALE); + } + + } + + ## -------------------------------------------------------- + + public function greyScaleEnhanced() + # Author: Jarrod Oberto + # Date: 07-05-2011 + # Purpose: Make image greyscale + # Param in: n/a + # Param out: + # Reference: + # Notes: + # + { + if ($this->imageResized) + { + imagefilter($this->imageResized, IMG_FILTER_GRAYSCALE); + imagefilter($this->imageResized, IMG_FILTER_CONTRAST, -15); + imagefilter($this->imageResized, IMG_FILTER_BRIGHTNESS, 2); + $this->sharpen($this->width); + } + } + + ## -------------------------------------------------------- + + public function greyScaleDramatic() + # Alias of gd_filter_monopin + { + $this->gd_filter_monopin(); + } + + + /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*- + Black 'n White +*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*/ + + public function blackAndWhite() + # Author: Jarrod Oberto + # Date: 07-05-2011 + # Purpose: Make image black and white + # Param in: n/a + # Param out: + # Reference: + # Notes: + # + { + if ($this->imageResized) + { + + imagefilter($this->imageResized, IMG_FILTER_GRAYSCALE); + imagefilter($this->imageResized, IMG_FILTER_CONTRAST, -1000); + } + + } + + + /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*- + Negative +*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*/ + + public function negative() + # Author: Jarrod Oberto + # Date: 07-05-2011 + # Purpose: Make image negative + # Param in: n/a + # Param out: + # Reference: + # Notes: + # + { + if ($this->imageResized) + { + + imagefilter($this->imageResized, IMG_FILTER_NEGATE); + } + + } + + + /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*- + Sepia +*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*/ + + public function sepia() + # Author: Jarrod Oberto + # Date: 07-05-2011 + # Purpose: Make image sepia + # Param in: n/a + # Param out: + # Reference: + # Notes: + # + { + if ($this->imageResized) + { + imagefilter($this->imageResized, IMG_FILTER_GRAYSCALE); + imagefilter($this->imageResized, IMG_FILTER_BRIGHTNESS, -10); + imagefilter($this->imageResized, IMG_FILTER_CONTRAST, -20); + imagefilter($this->imageResized, IMG_FILTER_COLORIZE, 60, 30, -15); + } + } + + ## -------------------------------------------------------- + + public function sepia2() + + { + if ($this->imageResized) + { + + $total = imagecolorstotal($this->imageResized); + for ($i = 0; $i < $total; $i++) + { + $index = imagecolorsforindex($this->imageResized, $i); + $red = ($index["red"] * 0.393 + $index["green"] * 0.769 + $index["blue"] * 0.189) / 1.351; + $green = ($index["red"] * 0.349 + $index["green"] * 0.686 + $index["blue"] * 0.168) / 1.203; + $blue = ($index["red"] * 0.272 + $index["green"] * 0.534 + $index["blue"] * 0.131) / 2.140; + imagecolorset($this->imageResized, $i, $red, $green, $blue); + } + + + } + } + + + /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*- + Vintage +*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*/ + + public function vintage() + # Alias of gd_filter_monopin + { + $this->gd_filter_vintage(); + } + + /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*- + Presets By Marc Hibbins +*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*/ + + + /** Apply 'Monopin' preset */ + public function gd_filter_monopin() + { + + if ($this->imageResized) + { + imagefilter($this->imageResized, IMG_FILTER_GRAYSCALE); + imagefilter($this->imageResized, IMG_FILTER_BRIGHTNESS, -15); + imagefilter($this->imageResized, IMG_FILTER_CONTRAST, -15); + $this->imageResized = $this->gd_apply_overlay($this->imageResized, 'vignette', 100); + } + } + + ## -------------------------------------------------------- + + public function gd_filter_vintage() + { + if ($this->imageResized) + { + $this->imageResized = $this->gd_apply_overlay($this->imageResized, 'vignette', 45); + imagefilter($this->imageResized, IMG_FILTER_BRIGHTNESS, 20); + imagefilter($this->imageResized, IMG_FILTER_CONTRAST, -35); + imagefilter($this->imageResized, IMG_FILTER_COLORIZE, 60, -10, 35); + imagefilter($this->imageResized, IMG_FILTER_SMOOTH, 7); + $this->imageResized = $this->gd_apply_overlay($this->imageResized, 'scratch', 10); + } + } + + ## -------------------------------------------------------- + + /** Apply a PNG overlay */ + private function gd_apply_overlay($im, $type, $amount) + # + # Original Author: Marc Hibbins + # License: Attribution-ShareAlike 3.0 + # Purpose: + # Params in: + # Params out: + # Notes: + # + { + $width = imagesx($im); + $height = imagesy($im); + $filter = imagecreatetruecolor($width, $height); + + imagealphablending($filter, false); + imagesavealpha($filter, true); + + $transparent = imagecolorallocatealpha($filter, 255, 255, 255, 127); + imagefilledrectangle($filter, 0, 0, $width, $height, $transparent); + + // *** Resize overlay + $overlay = $this->filterOverlayPath . '/' . $type . '.png'; + $png = imagecreatefrompng($overlay); + imagecopyresampled($filter, $png, 0, 0, 0, 0, $width, $height, imagesx($png), imagesy($png)); + + $comp = imagecreatetruecolor($width, $height); + imagecopy($comp, $im, 0, 0, 0, 0, $width, $height); + imagecopy($comp, $filter, 0, 0, 0, 0, $width, $height); + imagecopymerge($im, $comp, 0, 0, 0, 0, $width, $height, $amount); + + imagedestroy($comp); + + return $im; + } + + + /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*- + Colorise +*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*/ + + public function image_colorize($rgb) + { + imageTrueColorToPalette($this->imageResized, true, 256); + $numColors = imageColorsTotal($this->imageResized); + + for ($x = 0; $x < $numColors; $x++) + { + list($r, $g, $b) = array_values(imageColorsForIndex($this->imageResized, $x)); + + // calculate grayscale in percent + $grayscale = ($r + $g + $b) / 3 / 0xff; + + imageColorSet($this->imageResized, $x, + $grayscale * $rgb[0], + $grayscale * $rgb[1], + $grayscale * $rgb[2] + ); + + } + + return true; + } + + + /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*- + Reflection +*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*/ + + public function addReflection($reflectionHeight = 50, $startingTransparency = 30, $inside = false, $bgColor = '#fff', $stretch = false, $divider = 0) + { + + // *** Convert color + $rgbArray = $this->formatColor($bgColor); + $r = $rgbArray['r']; + $g = $rgbArray['g']; + $b = $rgbArray['b']; + + $im = $this->imageResized; + $li = imagecreatetruecolor($this->width, 1); + + $bgc = imagecolorallocate($li, $r, $g, $b); + imagefilledrectangle($li, 0, 0, $this->width, 1, $bgc); + + $bg = imagecreatetruecolor($this->width, $reflectionHeight); + $wh = imagecolorallocate($im, 255, 255, 255); + + $im = imagerotate($im, -180, $wh); + imagecopyresampled($bg, $im, 0, 0, 0, 0, $this->width, $this->height, $this->width, $this->height); + + $im = $bg; + + $bg = imagecreatetruecolor($this->width, $reflectionHeight); + + for ($x = 0; $x < $this->width; $x++) + { + imagecopy($bg, $im, $x, 0, $this->width - $x - 1, 0, 1, $reflectionHeight); + } + $im = $bg; + + $transaprencyAmount = $this->invertTransparency($startingTransparency, 100); + + + // *** Fade + if ($stretch) + { + $step = 100 / ($reflectionHeight + $startingTransparency); + } + else + { + $step = 100 / $reflectionHeight; + } + for ($i = 0; $i <= $reflectionHeight; $i++) + { + + if ($startingTransparency > 100) + { + $startingTransparency = 100; + } + if ($startingTransparency < 1) + { + $startingTransparency = 1; + } + imagecopymerge($bg, $li, 0, $i, 0, 0, $this->width, 1, $startingTransparency); + $startingTransparency += $step; + } + + // *** Apply fade + imagecopymerge($im, $li, 0, 0, 0, 0, $this->width, $divider, 100); // Divider + + + // *** width, height of reflection. + $x = imagesx($im); + $y = imagesy($im); + + + // *** Determines if the reflection should be displayed inside or outside the image + if ($inside) + { + + // Create new blank image with sizes. + $final = imagecreatetruecolor($this->width, $this->height); + + imagecopymerge($final, $this->imageResized, 0, 0, 0, $reflectionHeight, $this->width, $this->height - $reflectionHeight, 100); + imagecopymerge($final, $im, 0, $this->height - $reflectionHeight, 0, 0, $x, $y, 100); + + } + else + { + + // Create new blank image with sizes. + $final = imagecreatetruecolor($this->width, $this->height + $y); + + imagecopymerge($final, $this->imageResized, 0, 0, 0, 0, $this->width, $this->height, 100); + imagecopymerge($final, $im, 0, $this->height, 0, 0, $x, $y, 100); + } + + $this->imageResized = $final; + + imagedestroy($li); + imagedestroy($im); + } + + + /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*- + Rotate +*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*/ + + public function rotate($value = 90, $bgColor = 'transparent') + # Author: Jarrod Oberto + # Date: 07-05-2011 + # Purpose: Rotate image + # Param in: (mixed) $degrees: (int) number of degress to rotate image + # (str) param "left": rotate left + # (str) param "right": rotate right + # (str) param "upside": upside-down image + # Param out: + # Reference: + # Notes: The default direction of imageRotate() is counter clockwise. + # + { + if ($this->imageResized) + { + + if (is_integer($value)) + { + $degrees = $value; + } + + // *** Convert color + $rgbArray = $this->formatColor($bgColor); + $r = $rgbArray['r']; + $g = $rgbArray['g']; + $b = $rgbArray['b']; + if (isset($rgbArray['a'])) + { + $a = $rgbArray['a']; + } + + if (is_string($value)) + { + + $value = fix_strtolower($value); + + switch ($value) + { + case 'left': + $degrees = 90; + break; + case 'right': + $degrees = 270; + break; + case 'upside': + $degrees = 180; + break; + default: + break; + } + + } + + // *** The default direction of imageRotate() is counter clockwise + // * This makes it clockwise + $degrees = 360 - $degrees; + + // *** Create background color + $bg = ImageColorAllocateAlpha($this->imageResized, $r, $g, $b, $a); + + // *** Fill with background + ImageFill($this->imageResized, 0, 0, $bg); + + // *** Rotate + $this->imageResized = imagerotate($this->imageResized, $degrees, $bg); // Rotate 45 degrees and allocated the transparent colour as the one to make transparent (obviously) + + // Ensure alpha transparency + ImageSaveAlpha($this->imageResized, true); + + } + } + + + /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*- + Round corners +*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*/ + + public function roundCorners($radius = 5, $bgColor = 'transparent') + # Author: Jarrod Oberto + # Date: 19-05-2011 + # Purpose: Create rounded corners on your image + # Param in: (int) radius = the amount of curvature + # (mixed) $bgColor = the corner background color + # Param out: n/a + # Reference: + # Notes: + # + { + + // *** Check if the user wants transparency + $isTransparent = false; + if ( ! is_array($bgColor)) + { + if (fix_strtolower($bgColor) == 'transparent') + { + $isTransparent = true; + } + } + + + // *** If we use transparency, we need to color our curved mask with a unique color + if ($isTransparent) + { + $bgColor = $this->findUnusedGreen(); + } + + // *** Convert color + $rgbArray = $this->formatColor($bgColor); + $r = $rgbArray['r']; + $g = $rgbArray['g']; + $b = $rgbArray['b']; + if (isset($rgbArray['a'])) + { + $a = $rgbArray['a']; + } + + + // *** Create top-left corner mask (square) + $cornerImg = imagecreatetruecolor($radius, $radius); + //$cornerImg = imagecreate($radius, $radius); + + //imagealphablending($cornerImg, true); + //imagesavealpha($cornerImg, true); + + //imagealphablending($this->imageResized, false); + //imagesavealpha($this->imageResized, true); + + // *** Give it a color + $maskColor = imagecolorallocate($cornerImg, 0, 0, 0); + + + // *** Replace the mask color (black) to transparent + imagecolortransparent($cornerImg, $maskColor); + + + // *** Create the image background color + $imagebgColor = imagecolorallocate($cornerImg, $r, $g, $b); + + + // *** Fill the corner area to the user defined color + imagefill($cornerImg, 0, 0, $imagebgColor); + + + imagefilledellipse($cornerImg, $radius, $radius, $radius * 2, $radius * 2, $maskColor); + + + // *** Map to top left corner + imagecopymerge($this->imageResized, $cornerImg, 0, 0, 0, 0, $radius, $radius, 100); #tl + + // *** Map rounded corner to other corners by rotating and applying the mask + $cornerImg = imagerotate($cornerImg, 90, 0); + imagecopymerge($this->imageResized, $cornerImg, 0, $this->height - $radius, 0, 0, $radius, $radius, 100); #bl + + $cornerImg = imagerotate($cornerImg, 90, 0); + imagecopymerge($this->imageResized, $cornerImg, $this->width - $radius, $this->height - $radius, 0, 0, $radius, $radius, 100); #br + + $cornerImg = imagerotate($cornerImg, 90, 0); + imagecopymerge($this->imageResized, $cornerImg, $this->width - $radius, 0, 0, 0, $radius, $radius, 100); #tr + + + // *** If corners are to be transparent, we fill our chromakey color as transparent. + if ($isTransparent) + { + //imagecolortransparent($this->imageResized, $imagebgColor); + $this->imageResized = $this->transparentImage($this->imageResized); + imagesavealpha($this->imageResized, true); + } + + } + + + /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*- + Shadow +*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*/ + + public function addShadow($shadowAngle = 45, $blur = 15, $bgColor = 'transparent') + # + # Author: Jarrod Oberto (Adapted from Pascal Naidon) + # Ref: http://www.les-stooges.org/pascal/webdesign/vignettes/index.php?la=en + # Purpose: Add a drop shadow to your image + # Params in: (int) $angle: the angle of the shadow + # (int) $blur: the blur distance + # (mixed) $bgColor: the color of the background + # Params out: + # Notes: + # + { + // *** A higher number results in a smoother shadow + define('STEPS', $blur * 2); + + // *** Set the shadow distance + $shadowDistance = $blur * 0.25; + + // *** Set blur width and height + $blurWidth = $blurHeight = $blur; + + + if ($shadowAngle == 0) + { + $distWidth = 0; + $distHeight = 0; + } + else + { + $distWidth = $shadowDistance * cos(deg2rad($shadowAngle)); + $distHeight = $shadowDistance * sin(deg2rad($shadowAngle)); + } + + + // *** Convert color + if (fix_strtolower($bgColor) != 'transparent') + { + $rgbArray = $this->formatColor($bgColor); + $r0 = $rgbArray['r']; + $g0 = $rgbArray['g']; + $b0 = $rgbArray['b']; + } + + + $image = $this->imageResized; + $width = $this->width; + $height = $this->height; + + + $newImage = imagecreatetruecolor($width, $height); + imagecopyresampled($newImage, $image, 0, 0, 0, 0, $width, $height, $width, $height); + + + // *** RGB + $rgb = imagecreatetruecolor($width + $blurWidth, $height + $blurHeight); + $colour = imagecolorallocate($rgb, 0, 0, 0); + imagefilledrectangle($rgb, 0, 0, $width + $blurWidth, $height + $blurHeight, $colour); + $colour = imagecolorallocate($rgb, 255, 255, 255); + //imagefilledrectangle($rgb, $blurWidth*0.5-$distWidth, $blurHeight*0.5-$distHeight, $width+$blurWidth*0.5-$distWidth, $height+$blurWidth*0.5-$distHeight, $colour); + imagefilledrectangle($rgb, $blurWidth * 0.5 - $distWidth, $blurHeight * 0.5 - $distHeight, $width + $blurWidth * 0.5 - $distWidth, $height + $blurWidth * 0.5 - $distHeight, $colour); + //imagecopymerge($rgb, $newImage, 1+$blurWidth*0.5-$distWidth, 1+$blurHeight*0.5-$distHeight, 0,0, $width, $height, 100); + imagecopymerge($rgb, $newImage, $blurWidth * 0.5 - $distWidth, $blurHeight * 0.5 - $distHeight, 0, 0, $width + $blurWidth, $height + $blurHeight, 100); + + + // *** Shadow (alpha) + $shadow = imagecreatetruecolor($width + $blurWidth, $height + $blurHeight); + imagealphablending($shadow, false); + $colour = imagecolorallocate($shadow, 0, 0, 0); + imagefilledrectangle($shadow, 0, 0, $width + $blurWidth, $height + $blurHeight, $colour); + + + for ($i = 0; $i <= STEPS; $i++) + { + + $t = ((1.0 * $i) / STEPS); + $intensity = 255 * $t * $t; + + $colour = imagecolorallocate($shadow, $intensity, $intensity, $intensity); + $points = array( + $blurWidth * $t, $blurHeight, // Point 1 (x, y) + $blurWidth, $blurHeight * $t, // Point 2 (x, y) + $width, $blurHeight * $t, // Point 3 (x, y) + $width + $blurWidth * (1 - $t), $blurHeight, // Point 4 (x, y) + $width + $blurWidth * (1 - $t), $height, // Point 5 (x, y) + $width, $height + $blurHeight * (1 - $t), // Point 6 (x, y) + $blurWidth, $height + $blurHeight * (1 - $t), // Point 7 (x, y) + $blurWidth * $t, $height // Point 8 (x, y) + ); + imagepolygon($shadow, $points, 8, $colour); + } + + for ($i = 0; $i <= STEPS; $i++) + { + + $t = ((1.0 * $i) / STEPS); + $intensity = 255 * $t * $t; + + $colour = imagecolorallocate($shadow, $intensity, $intensity, $intensity); + imagefilledarc($shadow, $blurWidth - 1, $blurHeight - 1, 2 * (1 - $t) * $blurWidth, 2 * (1 - $t) * $blurHeight, 180, 268, $colour, IMG_ARC_PIE); + imagefilledarc($shadow, $width, $blurHeight - 1, 2 * (1 - $t) * $blurWidth, 2 * (1 - $t) * $blurHeight, 270, 358, $colour, IMG_ARC_PIE); + imagefilledarc($shadow, $width, $height, 2 * (1 - $t) * $blurWidth, 2 * (1 - $t) * $blurHeight, 0, 90, $colour, IMG_ARC_PIE); + imagefilledarc($shadow, $blurWidth - 1, $height, 2 * (1 - $t) * $blurWidth, 2 * (1 - $t) * $blurHeight, 90, 180, $colour, IMG_ARC_PIE); + } + + + $colour = imagecolorallocate($shadow, 255, 255, 255); + imagefilledrectangle($shadow, $blurWidth, $blurHeight, $width, $height, $colour); + imagefilledrectangle($shadow, $blurWidth * 0.5 - $distWidth, $blurHeight * 0.5 - $distHeight, $width + $blurWidth * 0.5 - 1 - $distWidth, $height + $blurHeight * 0.5 - 1 - $distHeight, $colour); + + + // *** The magic + imagealphablending($rgb, false); + + for ($theX = 0; $theX < imagesx($rgb); $theX++) + { + for ($theY = 0; $theY < imagesy($rgb); $theY++) + { + + // *** Get the RGB values for every pixel of the RGB image + $colArray = imagecolorat($rgb, $theX, $theY); + $r = ($colArray >> 16) & 0xFF; + $g = ($colArray >> 8) & 0xFF; + $b = $colArray & 0xFF; + + // *** Get the alpha value for every pixel of the shadow image + $colArray = imagecolorat($shadow, $theX, $theY); + $a = $colArray & 0xFF; + $a = 127 - floor($a / 2); + $t = $a / 128.0; + + // *** Create color + if (fix_strtolower($bgColor) == 'transparent') + { + $myColour = imagecolorallocatealpha($rgb, $r, $g, $b, $a); + } + else + { + $myColour = imagecolorallocate($rgb, $r * (1.0 - $t) + $r0 * $t, $g * (1.0 - $t) + $g0 * $t, $b * (1.0 - $t) + $b0 * $t); + } + + // *** Add color to new rgb image + imagesetpixel($rgb, $theX, $theY, $myColour); + } + } + + imagealphablending($rgb, true); + imagesavealpha($rgb, true); + + $this->imageResized = $rgb; + + imagedestroy($image); + imagedestroy($newImage); + imagedestroy($shadow); + } + + + /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*- + Add Caption Box +*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*/ + + public function addCaptionBox($side = 'b', $thickness = 50, $padding = 0, $bgColor = '#000', $transaprencyAmount = 30) + # + # Author: Jarrod Oberto + # Date: 26 May 2011 + # Purpose: Add a caption box + # Params in: (str) $side: the side to add the caption box (t, r, b, or l). + # (int) $thickness: how thick you want the caption box to be. + # (mixed) $bgColor: The color of the caption box. + # (int) $transaprencyAmount: The amount of transparency to be + # applied. + # Params out: n/a + # Notes: + # + { + $side = fix_strtolower($side); + + // *** Convert color + $rgbArray = $this->formatColor($bgColor); + $r = $rgbArray['r']; + $g = $rgbArray['g']; + $b = $rgbArray['b']; + + $positionArray = $this->calculateCaptionBoxPosition($side, $thickness, $padding); + + // *** Store incase we want to use method addTextToCaptionBox() + $this->captionBoxPositionArray = $positionArray; + + + $transaprencyAmount = $this->invertTransparency($transaprencyAmount, 127, false); + $transparent = imagecolorallocatealpha($this->imageResized, $r, $g, $b, $transaprencyAmount); + imagefilledrectangle($this->imageResized, $positionArray['x1'], $positionArray['y1'], $positionArray['x2'], $positionArray['y2'], $transparent); + } + + ## -------------------------------------------------------- + + public function addTextToCaptionBox($text, $fontColor = '#fff', $fontSize = 12, $angle = 0, $font = null) + # + # Author: Jarrod Oberto + # Date: 03 Aug 11 + # Purpose: Simplify adding text to a caption box by automatically + # locating the center of the caption box + # Params in: The usually text paams (less a couple) + # Params out: n/a + # Notes: + # + { + + // *** Get the caption box measurements + if (count($this->captionBoxPositionArray) == 4) + { + $x1 = $this->captionBoxPositionArray['x1']; + $x2 = $this->captionBoxPositionArray['x2']; + $y1 = $this->captionBoxPositionArray['y1']; + $y2 = $this->captionBoxPositionArray['y2']; + } + else + { + if ($this->debug) + { + throw new Exception('No caption box found.'); + } + else + { + return false; + } + } + + + // *** Get text font + $font = $this->getTextFont($font); + + // *** Get text size + $textSizeArray = $this->getTextSize($fontSize, $angle, $font, $text); + $textWidth = $textSizeArray['width']; + $textHeight = $textSizeArray['height']; + + // *** Find the width/height middle points + $boxXMiddle = (($x2 - $x1) / 2); + $boxYMiddle = (($y2 - $y1) / 2); + + // *** Box middle - half the text width/height + $xPos = ($x1 + $boxXMiddle) - ($textWidth / 2); + $yPos = ($y1 + $boxYMiddle) - ($textHeight / 2); + + $pos = $xPos . 'x' . $yPos; + + $this->addText($text, $pos, $padding = 0, $fontColor, $fontSize, $angle, $font); + + } + + ## -------------------------------------------------------- + + private function calculateCaptionBoxPosition($side, $thickness, $padding) + { + $positionArray = array(); + + switch ($side) + { + case 't': + $positionArray['x1'] = 0; + $positionArray['y1'] = $padding; + $positionArray['x2'] = $this->width; + $positionArray['y2'] = $thickness + $padding; + break; + case 'r': + $positionArray['x1'] = $this->width - $thickness - $padding; + $positionArray['y1'] = 0; + $positionArray['x2'] = $this->width - $padding; + $positionArray['y2'] = $this->height; + break; + case 'b': + $positionArray['x1'] = 0; + $positionArray['y1'] = $this->height - $thickness - $padding; + $positionArray['x2'] = $this->width; + $positionArray['y2'] = $this->height - $padding; + break; + case 'l': + $positionArray['x1'] = $padding; + $positionArray['y1'] = 0; + $positionArray['x2'] = $thickness + $padding; + $positionArray['y2'] = $this->height; + break; + + default: + break; + } + + return $positionArray; + + } + + /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*- + Get EXIF Data +*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*/ + + public function getExif($debug = false) + # Author: Jarrod Oberto + # Date: 07-05-2011 + # Purpose: Get image EXIF data + # Param in: n/a + # Param out: An associate array of EXIF data + # Reference: + # Notes: + # 23 May 13 : added orientation flag -jco + # + { + + if ( ! $this->debug || ! $debug) + { + $debug = false; + } + + // *** Check all is good - check the EXIF library exists and the file exists, too. + if ( ! $this->testEXIFInstalled()) + { + if ($debug) + { + throw new Exception('The EXIF Library is not installed.'); + } + else + { + return array(); + } + }; + if ( ! file_exists($this->fileName)) + { + if ($debug) + { + throw new Exception('Image not found.'); + } + else + { + return array(); + } + }; + if ($this->fileExtension != '.jpg') + { + if ($debug) + { + throw new Exception('Metadata not supported for this image type.'); + } + else + { + return array(); + } + }; + $exifData = exif_read_data($this->fileName, 'IFD0'); + + // *** Format the apperture value + $ev = $exifData['ApertureValue']; + $apPeicesArray = explode('/', $ev); + if (count($apPeicesArray) == 2) + { + $apertureValue = round($apPeicesArray[0] / $apPeicesArray[1], 2, PHP_ROUND_HALF_DOWN) . ' EV'; + } + else + { + $apertureValue = ''; + } + + // *** Format the focal length + $focalLength = $exifData['FocalLength']; + $flPeicesArray = explode('/', $focalLength); + if (count($flPeicesArray) == 2) + { + $focalLength = $flPeicesArray[0] / $flPeicesArray[1] . '.0 mm'; + } + else + { + $focalLength = ''; + } + + // *** Format fNumber + $fNumber = $exifData['FNumber']; + $fnPeicesArray = explode('/', $fNumber); + if (count($fnPeicesArray) == 2) + { + $fNumber = $fnPeicesArray[0] / $fnPeicesArray[1]; + } + else + { + $fNumber = ''; + } + + // *** Resolve ExposureProgram + if (isset($exifData['ExposureProgram'])) + { + $ep = $exifData['ExposureProgram']; + } + if (isset($ep)) + { + $ep = $this->resolveExposureProgram($ep); + } + + + // *** Resolve MeteringMode + $mm = $exifData['MeteringMode']; + $mm = $this->resolveMeteringMode($mm); + + // *** Resolve Flash + $flash = $exifData['Flash']; + $flash = $this->resolveFlash($flash); + + + if (isset($exifData['Make'])) + { + $exifDataArray['make'] = $exifData['Make']; + } + else + { + $exifDataArray['make'] = ''; + } + + if (isset($exifData['Model'])) + { + $exifDataArray['model'] = $exifData['Model']; + } + else + { + $exifDataArray['model'] = ''; + } + + if (isset($exifData['DateTime'])) + { + $exifDataArray['date'] = $exifData['DateTime']; + } + else + { + $exifDataArray['date'] = ''; + } + + if (isset($exifData['ExposureTime'])) + { + $exifDataArray['exposure time'] = $exifData['ExposureTime'] . ' sec.'; + } + else + { + $exifDataArray['exposure time'] = ''; + } + + if ($apertureValue != '') + { + $exifDataArray['aperture value'] = $apertureValue; + } + else + { + $exifDataArray['aperture value'] = ''; + } + + if (isset($exifData['COMPUTED']['ApertureFNumber'])) + { + $exifDataArray['f-stop'] = $exifData['COMPUTED']['ApertureFNumber']; + } + else + { + $exifDataArray['f-stop'] = ''; + } + + if (isset($exifData['FNumber'])) + { + $exifDataArray['fnumber'] = $exifData['FNumber']; + } + else + { + $exifDataArray['fnumber'] = ''; + } + + if ($fNumber != '') + { + $exifDataArray['fnumber value'] = $fNumber; + } + else + { + $exifDataArray['fnumber value'] = ''; + } + + if (isset($exifData['ISOSpeedRatings'])) + { + $exifDataArray['iso'] = $exifData['ISOSpeedRatings']; + } + else + { + $exifDataArray['iso'] = ''; + } + + if ($focalLength != '') + { + $exifDataArray['focal length'] = $focalLength; + } + else + { + $exifDataArray['focal length'] = ''; + } + + if (isset($ep)) + { + $exifDataArray['exposure program'] = $ep; + } + else + { + $exifDataArray['exposure program'] = ''; + } + + if ($mm != '') + { + $exifDataArray['metering mode'] = $mm; + } + else + { + $exifDataArray['metering mode'] = ''; + } + + if ($flash != '') + { + $exifDataArray['flash status'] = $flash; + } + else + { + $exifDataArray['flash status'] = ''; + } + + if (isset($exifData['Artist'])) + { + $exifDataArray['creator'] = $exifData['Artist']; + } + else + { + $exifDataArray['creator'] = ''; + } + + if (isset($exifData['Copyright'])) + { + $exifDataArray['copyright'] = $exifData['Copyright']; + } + else + { + $exifDataArray['copyright'] = ''; + } + + // *** Orientation + if (isset($exifData['Orientation'])) + { + $exifDataArray['orientation'] = $exifData['Orientation']; + } + else + { + $exifDataArray['orientation'] = ''; + } + + return $exifDataArray; + } + + ## -------------------------------------------------------- + + private function resolveExposureProgram($ep) + { + switch ($ep) + { + case 0: + $ep = ''; + break; + case 1: + $ep = 'manual'; + break; + case 2: + $ep = 'normal program'; + break; + case 3: + $ep = 'aperture priority'; + break; + case 4: + $ep = 'shutter priority'; + break; + case 5: + $ep = 'creative program'; + break; + case 6: + $ep = 'action program'; + break; + case 7: + $ep = 'portrait mode'; + break; + case 8: + $ep = 'landscape mode'; + break; + + default: + break; + } + + return $ep; + } + + ## -------------------------------------------------------- + + private function resolveMeteringMode($mm) + { + switch ($mm) + { + case 0: + $mm = 'unknown'; + break; + case 1: + $mm = 'average'; + break; + case 2: + $mm = 'center weighted average'; + break; + case 3: + $mm = 'spot'; + break; + case 4: + $mm = 'multi spot'; + break; + case 5: + $mm = 'pattern'; + break; + case 6: + $mm = 'partial'; + break; + case 255: + $mm = 'other'; + break; + + default: + break; + } + + return $mm; + } + + ## -------------------------------------------------------- + + private function resolveFlash($flash) + { + switch ($flash) + { + case 0: + $flash = 'flash did not fire'; + break; + case 1: + $flash = 'flash fired'; + break; + case 5: + $flash = 'strobe return light not detected'; + break; + case 7: + $flash = 'strobe return light detected'; + break; + case 9: + $flash = 'flash fired, compulsory flash mode'; + break; + case 13: + $flash = 'flash fired, compulsory flash mode, return light not detected'; + break; + case 15: + $flash = 'flash fired, compulsory flash mode, return light detected'; + break; + case 16: + $flash = 'flash did not fire, compulsory flash mode'; + break; + case 24: + $flash = 'flash did not fire, auto mode'; + break; + case 25: + $flash = 'flash fired, auto mode'; + break; + case 29: + $flash = 'flash fired, auto mode, return light not detected'; + break; + case 31: + $flash = 'flash fired, auto mode, return light detected'; + break; + case 32: + $flash = 'no flash function'; + break; + case 65: + $flash = 'flash fired, red-eye reduction mode'; + break; + case 69: + $flash = 'flash fired, red-eye reduction mode, return light not detected'; + break; + case 71: + $flash = 'flash fired, red-eye reduction mode, return light detected'; + break; + case 73: + $flash = 'flash fired, compulsory flash mode, red-eye reduction mode'; + break; + case 77: + $flash = 'flash fired, compulsory flash mode, red-eye reduction mode, return light not detected'; + break; + case 79: + $flash = 'flash fired, compulsory flash mode, red-eye reduction mode, return light detected'; + break; + case 89: + $flash = 'flash fired, auto mode, red-eye reduction mode'; + break; + case 93: + $flash = 'flash fired, auto mode, return light not detected, red-eye reduction mode'; + break; + case 95: + $flash = 'flash fired, auto mode, return light detected, red-eye reduction mode'; + break; + + default: + break; + } + + return $flash; + + } + + + /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*- + Get IPTC Data +*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*/ + + + /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*- + Write IPTC Data +*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*/ + + public function writeIPTCcaption($value) + # Caption + { + $this->writeIPTC(120, $value); + } + + ## -------------------------------------------------------- + + public function writeIPTCwriter($value) + { + //$this->writeIPTC(65, $value); + } + + ## -------------------------------------------------------- + + private function writeIPTC($dat, $value) + { + + # LIMIT TO JPG + + $caption_block = $this->iptc_maketag(2, $dat, $value); + $image_string = iptcembed($caption_block, $this->fileName); + file_put_contents('iptc.jpg', $image_string); + } + +## -------------------------------------------------------- + + private function iptc_maketag($rec, $dat, $val) + # Author: Thies C. Arntzen + # Purpose: Function to format the new IPTC text + # Param in: $rec: Application record. (We’re working with #2) + # $dat: Index. (120 for caption, 118 for contact. See the IPTC IIM + # specification: + # http://www.iptc.org/std/IIM/4.1/specification/IIMV4.1.pdf + # $val: Value/data/text. Make sure this is within the length + # constraints of the IPTC IIM specification + # Ref: http://blog.peterhaza.no/working-with-image-meta-data-in-exif-and-iptc-headers-from-php/ + # http://php.net/manual/en/function.iptcembed.php + # + { + $len = strlen($val); + if ($len < 0x8000) + { + return chr(0x1c) . chr($rec) . chr($dat) . + chr($len >> 8) . + chr($len & 0xff) . + $val; + } + else + { + return chr(0x1c) . chr($rec) . chr($dat) . + chr(0x80) . chr(0x04) . + chr(($len >> 24) & 0xff) . + chr(($len >> 16) & 0xff) . + chr(($len >> 8) & 0xff) . + chr(($len) & 0xff) . + $val; + } + } + + + + /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*- + Write XMP Data +*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*/ + + //http://xmpphptoolkit.sourceforge.net/ + + + /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*- + Add Text +*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*/ + + public function addText($text, $pos = '20x20', $padding = 0, $fontColor = '#fff', $fontSize = 12, $angle = 0, $font = null) + # Author: Jarrod Oberto + # Date: 18-11-09 + # Purpose: Add text to an image + # Param in: + # Param out: + # Reference: http://php.net/manual/en/function.imagettftext.php + # Notes: Make sure you supply the font. + # + { + + // *** Convert color + $rgbArray = $this->formatColor($fontColor); + $r = $rgbArray['r']; + $g = $rgbArray['g']; + $b = $rgbArray['b']; + + // *** Get text font + $font = $this->getTextFont($font); + + // *** Get text size + $textSizeArray = $this->getTextSize($fontSize, $angle, $font, $text); + $textWidth = $textSizeArray['width']; + $textHeight = $textSizeArray['height']; + + // *** Find co-ords to place text + $posArray = $this->calculatePosition($pos, $padding, $textWidth, $textHeight, false); + $x = $posArray['width']; + $y = $posArray['height']; + + $fontColor = imagecolorallocate($this->imageResized, $r, $g, $b); + + // *** Add text + imagettftext($this->imageResized, $fontSize, $angle, $x, $y, $fontColor, $font, $text); + } + + ## -------------------------------------------------------- + + private function getTextFont($font) + { + // *** Font path (shou + $fontPath = dirname(__FILE__) . '/' . $this->fontDir; + + + // *** The below is/may be needed depending on your version (see ref) + putenv('GDFONTPATH=' . realpath('.')); + + // *** Check if the passed in font exsits... + if ($font == null || ! file_exists($font)) + { + + // *** ...If not, default to this font. + $font = $fontPath . '/arimo.ttf'; + + // *** Check our default font exists... + if ( ! file_exists($font)) + { + + // *** If not, return false + if ($this->debug) + { + throw new Exception('Font not found'); + } + else + { + return false; + } + } + } + + return $font; + + } + + ## -------------------------------------------------------- + + private function getTextSize($fontSize, $angle, $font, $text) + { + + // *** Define box (so we can get the width) + $box = @imageTTFBbox($fontSize, $angle, $font, $text); + + // *** Get width of text from dimensions + $textWidth = abs($box[4] - $box[0]); + + // *** Get height of text from dimensions (should also be same as $fontSize) + $textHeight = abs($box[5] - $box[1]); + + return array( 'height' => $textHeight, 'width' => $textWidth ); + } + + + /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*- + Add Watermark +*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*/ + + public function addWatermark($watermarkImage, $pos, $padding = 0, $opacity = 0) + # Author: Jarrod Oberto + # Date: 18-11-09 + # Purpose: Add watermark image + # Param in: (str) $watermark: The watermark image + # (str) $pos: Could be a pre-determined position such as: + # tl = top left, + # t = top (middle), + # tr = top right, + # l = left, + # m = middle, + # r = right, + # bl = bottom left, + # b = bottom (middle), + # br = bottom right + # Or, it could be a co-ordinate position such as: 50x100 + # + # (int) $padding: If using a pre-determined position you can + # adjust the padding from the edges by passing an amount + # in pixels. If using co-ordinates, this value is ignored. + # Param out: + # Reference: http://www.php.net/manual/en/image.examples-watermark.php + # Notes: Based on example in reference. + # + # + { + + // Load the stamp and the photo to apply the watermark to + $stamp = $this->openImage($watermarkImage); # stamp + $im = $this->imageResized; # photo + + // *** Get stamps width and height + $sx = imagesx($stamp); + $sy = imagesy($stamp); + + // *** Find co-ords to place image + $posArray = $this->calculatePosition($pos, $padding, $sx, $sy); + $x = $posArray['width']; + $y = $posArray['height']; + + // *** Set watermark opacity + if (fix_strtolower(strrchr($watermarkImage, '.')) == '.png') + { + + $opacity = $this->invertTransparency($opacity, 100); + $this->filterOpacity($stamp, $opacity); + } + + // Copy the watermark image onto our photo + imagecopy($im, $stamp, $x, $y, 0, 0, imagesx($stamp), imagesy($stamp)); + + } + + ## -------------------------------------------------------- + + private function calculatePosition($pos, $padding, $assetWidth, $assetHeight, $upperLeft = true) + # + # Author: Jarrod Oberto + # Date: 08-05-11 + # Purpose: Calculate the x, y pixel cordinates of the asset to place + # Params in: (str) $pos: Either something like: "tl", "l", "br" or an + # exact position like: "100x50" + # (int) $padding: The amount of padding from the edge. Only + # used for the predefined $pos. + # (int) $assetWidth: The width of the asset to add to the image + # (int) $assetHeight: The height of the asset to add to the image + # (bol) $upperLeft: if true, the asset will be positioned based + # on the upper left x, y coords. If false, it means you're + # using the lower left as the basepoint and this will + # convert it to the upper left position + # Params out: + # NOTE: this is done from the UPPER left corner!! But will convert lower + # left basepoints to upper left if $upperleft is set to false + # + # + { + $pos = fix_strtolower($pos); + + // *** If co-ords have been entered + if (strstr($pos, 'x')) + { + $pos = str_replace(' ', '', $pos); + + $xyArray = explode('x', $pos); + list($width, $height) = $xyArray; + + } + else + { + + switch ($pos) + { + case 'tl': + $width = 0 + $padding; + $height = 0 + $padding; + break; + + case 't': + $width = ($this->width / 2) - ($assetWidth / 2); + $height = 0 + $padding; + break; + + case 'tr': + $width = $this->width - $assetWidth - $padding; + $height = 0 + $padding;; + break; + + case 'l': + $width = 0 + $padding; + $height = ($this->height / 2) - ($assetHeight / 2); + break; + + case 'm': + $width = ($this->width / 2) - ($assetWidth / 2); + $height = ($this->height / 2) - ($assetHeight / 2); + break; + + case 'r': + $width = $this->width - $assetWidth - $padding; + $height = ($this->height / 2) - ($assetHeight / 2); + break; + + case 'bl': + $width = 0 + $padding; + $height = $this->height - $assetHeight - $padding; + break; + + case 'b': + $width = ($this->width / 2) - ($assetWidth / 2); + $height = $this->height - $assetHeight - $padding; + break; + + case 'br': + $width = $this->width - $assetWidth - $padding; + $height = $this->height - $assetHeight - $padding; + break; + + default: + $width = 0; + $height = 0; + break; + } + } + + if ( ! $upperLeft) + { + $height = $height + $assetHeight; + } + + return array( 'width' => $width, 'height' => $height ); + } + + + ## -------------------------------------------------------- + + private function filterOpacity(&$img, $opacity = 75) + # + # Author: aiden dot mail at freemail dot hu + # Author date: 29-03-08 08:16 + # Date added: 08-05-11 + # Purpose: Change opacity of image + # Params in: $img: Image resource id + # (int) $opacity: the opacity amount: 0-100, 100 being not opaque. + # Params out: (bool) true on success, else false + # Ref: http://www.php.net/manual/en/function.imagefilter.php#82162 + # Notes: png only + # + { + + if ( ! isset($opacity)) + { + return false; + } + + if ($opacity == 100) + { + return true; + } + + $opacity /= 100; + + //get image width and height + $w = imagesx($img); + $h = imagesy($img); + + //turn alpha blending off + imagealphablending($img, false); + + //find the most opaque pixel in the image (the one with the smallest alpha value) + $minalpha = 127; + for ($x = 0; $x < $w; $x++) + { + for ($y = 0; $y < $h; $y++) + { + $alpha = (imagecolorat($img, $x, $y) >> 24) & 0xFF; + if ($alpha < $minalpha) + { + $minalpha = $alpha; + } + } + } + + //loop through image pixels and modify alpha for each + for ($x = 0; $x < $w; $x++) + { + for ($y = 0; $y < $h; $y++) + { + //get current alpha value (represents the TANSPARENCY!) + $colorxy = imagecolorat($img, $x, $y); + $alpha = ($colorxy >> 24) & 0xFF; + //calculate new alpha + if ($minalpha !== 127) + { + $alpha = 127 + 127 * $opacity * ($alpha - 127) / (127 - $minalpha); + } + else + { + $alpha += 127 * $opacity; + } + //get the color index with new alpha + $alphacolorxy = imagecolorallocatealpha($img, ($colorxy >> 16) & 0xFF, ($colorxy >> 8) & 0xFF, $colorxy & 0xFF, $alpha); + //set pixel with the new color + opacity + if ( ! imagesetpixel($img, $x, $y, $alphacolorxy)) + { + + return false; + } + } + } + + return true; + } + +## -------------------------------------------------------- + + private function openImage($file) + # Author: Jarrod Oberto + # Date: 27-02-08 + # Purpose: + # Param in: + # Param out: n/a + # Reference: + # Notes: + # + { + + if ( ! file_exists($file) && ! $this->checkStringStartsWith('http://', $file) && ! $this->checkStringStartsWith('https://', $file) ) + { + if ($this->debug) + { + throw new Exception('Image not found.'); + } + else + { + throw new Exception(); + } + }; + + // *** Get extension + $extension = strrchr($file, '.'); + $extension = fix_strtolower($extension); + switch ($extension) + { + case '.jpg': + case '.jpeg': + $img = @imagecreatefromjpeg($file); + break; + case '.gif': + $img = @imagecreatefromgif($file); + break; + case '.png': + $img = @imagecreatefrompng($file); + break; + case '.bmp': + $img = @$this->imagecreatefrombmp($file); + break; + case '.psd': + $img = @$this->imagecreatefrompsd($file); + break; + + + // ... etc + + default: + $img = false; + break; + } + + return $img; + } + +## -------------------------------------------------------- + + public function reset() + # + # Author: Jarrod Oberto + # Date: 30-08-11 + # Purpose: Reset the resource (allow further editing) + # Params in: + # Params out: + # Notes: + # + { + $this->__construct($this->fileName); + } + +## -------------------------------------------------------- + + public function saveImage($savePath, $imageQuality = "100") + # Author: Jarrod Oberto + # Date: 27-02-08 + # Purpose: Saves the image + # Param in: $savePath: Where to save the image including filename: + # $imageQuality: image quality you want the image saved at 0-100 + # Param out: n/a + # Reference: + # Notes: * gif doesn't have a quality parameter + # * jpg has a quality setting 0-100 (100 being the best) + # * png has a quality setting 0-9 (0 being the best) + # + # * bmp files have no native support for bmp files. We use a + # third party class to save as bmp. + { + + // *** Perform a check or two. + if ( ! is_resource($this->imageResized)) + { + if ($this->debug) + { + throw new Exception('saveImage: This is not a resource.'); + } + else + { + throw new Exception(); + } + } + $fileInfoArray = pathInfo($savePath); + clearstatcache(); + if ( ! is_writable($fileInfoArray['dirname'])) + { + if ($this->debug) + { + throw new Exception('The path is not writable. Please check your permissions.'); + } + else + { + throw new Exception(); + } + } + + // *** Get extension + $extension = strrchr($savePath, '.'); + $extension = fix_strtolower($extension); + + $error = ''; + + switch ($extension) + { + case '.jpg': + case '.jpeg': + $this->checkInterlaceImage($this->isInterlace); + if (imagetypes() & IMG_JPG) + { + imagejpeg($this->imageResized, $savePath, $imageQuality); + } + else + { + $error = 'jpg'; + } + break; + + case '.gif': + $this->checkInterlaceImage($this->isInterlace); + if (imagetypes() & IMG_GIF) + { + imagegif($this->imageResized, $savePath); + } + else + { + $error = 'gif'; + } + break; + + case '.png': + // *** Scale quality from 0-100 to 0-9 + $scaleQuality = round(($imageQuality / 100) * 9); + + // *** Invert qualit setting as 0 is best, not 9 + $invertScaleQuality = 9 - $scaleQuality; + + $this->checkInterlaceImage($this->isInterlace); + if (imagetypes() & IMG_PNG) + { + imagepng($this->imageResized, $savePath, $invertScaleQuality); + } + else + { + $error = 'png'; + } + break; + + case '.bmp': + file_put_contents($savePath, $this->GD2BMPstring($this->imageResized)); + break; + + + // ... etc + + default: + // *** No extension - No save. + $this->errorArray[] = 'This file type (' . $extension . ') is not supported. File not saved.'; + break; + } + + //imagedestroy($this->imageResized); + + // *** Display error if a file type is not supported. + if ($error != '') + { + $this->errorArray[] = $error . ' support is NOT enabled. File not saved.'; + } + } + +## -------------------------------------------------------- + + public function displayImage($fileType = 'jpg', $imageQuality = "100") + # Author: Jarrod Oberto + # Date: 18-11-09 + # Purpose: Display images directly to the browser + # Param in: The image type you want to display + # Param out: + # Reference: + # Notes: + # + { + + if ( ! is_resource($this->imageResized)) + { + if ($this->debug) + { + throw new Exception('saveImage: This is not a resource.'); + } + else + { + throw new Exception(); + } + } + + switch ($fileType) + { + case 'jpg': + case 'jpeg': + header('Content-type: image/jpeg'); + imagejpeg($this->imageResized, '', $imageQuality); + break; + case 'gif': + header('Content-type: image/gif'); + imagegif($this->imageResized); + break; + case 'png': + header('Content-type: image/png'); + + // *** Scale quality from 0-100 to 0-9 + $scaleQuality = round(($imageQuality / 100) * 9); + + // *** Invert qualit setting as 0 is best, not 9 + $invertScaleQuality = 9 - $scaleQuality; + + imagepng($this->imageResized, '', $invertScaleQuality); + break; + case 'bmp': + echo 'bmp file format is not supported.'; + break; + + // ... etc + + default: + // *** No extension - No save. + break; + } + + + //imagedestroy($this->imageResized); + } + +## -------------------------------------------------------- + + public function setTransparency($bool) + # Sep 2011 + { + $this->keepTransparency = $bool; + } + +## -------------------------------------------------------- + + public function setFillColor($value) + # Sep 2011 + # Param in: (mixed) $value: (array) Could be an array of RGB + # (str) Could be hex #ffffff or #fff, fff, ffffff + # + # If the keepTransparency is set to false, then no transparency is to be used. + # This is ideal when you want to save as jpg. + # + # this method allows you to set the background color to use instead of + # transparency. + # + { + $colorArray = $this->formatColor($value); + $this->fillColorArray = $colorArray; + } + +## -------------------------------------------------------- + + public function setCropFromTop($value) + # Sep 2011 + { + $this->cropFromTopPercent = $value; + } + +## -------------------------------------------------------- + + public function testGDInstalled() + # Author: Jarrod Oberto + # Date: 27-02-08 + # Purpose: Test to see if GD is installed + # Param in: n/a + # Param out: (bool) True is gd extension loaded otherwise false + # Reference: + # Notes: + # + { + if (extension_loaded('gd') && function_exists('gd_info')) + { + $gdInstalled = true; + } + else + { + $gdInstalled = false; + } + + return $gdInstalled; + } + +## -------------------------------------------------------- + + public function testEXIFInstalled() + # Author: Jarrod Oberto + # Date: 08-05-11 + # Purpose: Test to see if EXIF is installed + # Param in: n/a + # Param out: (bool) True is exif extension loaded otherwise false + # Reference: + # Notes: + # + { + if (extension_loaded('exif')) + { + $exifInstalled = true; + } + else + { + $exifInstalled = false; + } + + return $exifInstalled; + } + +## -------------------------------------------------------- + + public function testIsImage($image) + # Author: Jarrod Oberto + # Date: 27-02-08 + # Purpose: Test if file is an image + # Param in: n/a + # Param out: n/a + # Reference: + # Notes: + # + { + if ($image) + { + $fileIsImage = true; + } + else + { + $fileIsImage = false; + } + + return $fileIsImage; + } + +## -------------------------------------------------------- + + public function testFunct() + # Author: Jarrod Oberto + # Date: 27-02-08 + # Purpose: Test Function + # Param in: n/a + # Param out: n/a + # Reference: + # Notes: + # + { + echo $this->height; + } + +## -------------------------------------------------------- + + public function setForceStretch($value) + # Author: Jarrod Oberto + # Date: 23-12-10 + # Purpose: + # Param in: (bool) $value + # Param out: n/a + # Reference: + # Notes: + # + { + $this->forceStretch = $value; + } + +## -------------------------------------------------------- + + public function setFile($fileName) + # Author: Jarrod Oberto + # Date: 28-02-08 + # Purpose: + # Param in: n/a + # Param out: n/a + # Reference: + # Notes: + # + { + self::__construct($fileName); + } + +## -------------------------------------------------------- + + public function getFileName() + # Author: Jarrod Oberto + # Date: 10-09-08 + # Purpose: + # Param in: n/a + # Param out: n/a + # Reference: + # Notes: + # + { + return $this->fileName; + } + +## -------------------------------------------------------- + + public function getHeight() + { + return $this->height; + } + +## -------------------------------------------------------- + + public function getWidth() + { + return $this->width; + } + +## -------------------------------------------------------- + + public function getOriginalHeight() + { + return $this->heightOriginal; + } + +## -------------------------------------------------------- + + public function getOriginalWidth() + { + return $this->widthOriginal; + } + +## -------------------------------------------------------- + + public function getErrors() + # Author: Jarrod Oberto + # Date: 19-11-09 + # Purpose: Returns the error array + # Param in: n/a + # Param out: Array of errors + # Reference: + # Notes: + # + { + return $this->errorArray; + } + +## -------------------------------------------------------- + + private function checkInterlaceImage($isEnabled) + # jpg will use progressive (they don't use interace) + { + if ($isEnabled) + { + imageinterlace($this->imageResized, $isEnabled); + } + } + +## -------------------------------------------------------- + + protected function formatColor($value) + # Author: Jarrod Oberto + # Date: 09-05-11 + # Purpose: Determine color method passed in and return color as RGB + # Param in: (mixed) $value: (array) Could be an array of RGB + # (str) Could be hex #ffffff or #fff, fff, ffffff + # Param out: + # Reference: + # Notes: + # + { + $rgbArray = array(); + + // *** If it's an array it should be R, G, B + if (is_array($value)) + { + + if (key($value) == 0 && count($value) == 3) + { + + $rgbArray['r'] = $value[0]; + $rgbArray['g'] = $value[1]; + $rgbArray['b'] = $value[2]; + + } + else + { + $rgbArray = $value; + } + } + else + { + if (fix_strtolower($value) == 'transparent') + { + + $rgbArray = array( + 'r' => 255, + 'g' => 255, + 'b' => 255, + 'a' => 127 + ); + + } + else + { + + // *** ...Else it should be hex. Let's make it RGB + $rgbArray = $this->hex2dec($value); + } + } + + return $rgbArray; + } + + ## -------------------------------------------------------- + + function hex2dec($hex) + # Purpose: Convert #hex color to RGB + { + $color = str_replace('#', '', $hex); + + if (strlen($color) == 3) + { + $color = $color . $color; + } + + $rgb = array( + 'r' => hexdec(substr($color, 0, 2)), + 'g' => hexdec(substr($color, 2, 2)), + 'b' => hexdec(substr($color, 4, 2)), + 'a' => 0 + ); + + return $rgb; + } + + ## -------------------------------------------------------- + + private function createImageColor($colorArray) + { + $r = $colorArray['r']; + $g = $colorArray['g']; + $b = $colorArray['b']; + + return imagecolorallocate($this->imageResized, $r, $g, $b); + } + + ## -------------------------------------------------------- + + private function testColorExists($colorArray) + { + $r = $colorArray['r']; + $g = $colorArray['g']; + $b = $colorArray['b']; + + if (imagecolorexact($this->imageResized, $r, $g, $b) == -1) + { + return false; + } + else + { + return true; + } + } + + ## -------------------------------------------------------- + + private function findUnusedGreen() + # Purpose: We find a green color suitable to use like green-screen effect. + # Therefore, the color must not exist in the image. + { + $green = 255; + + do + { + + $greenChroma = array( 0, $green, 0 ); + $colorArray = $this->formatColor($greenChroma); + $match = $this->testColorExists($colorArray); + $green--; + + } while ($match == false && $green > 0); + + // *** If no match, just bite the bullet and use green value of 255 + if ( ! $match) + { + $greenChroma = array( 0, $green, 0 ); + } + + return $greenChroma; + } + + ## -------------------------------------------------------- + + private function findUnusedBlue() + # Purpose: We find a green color suitable to use like green-screen effect. + # Therefore, the color must not exist in the image. + { + $blue = 255; + + do + { + + $blueChroma = array( 0, 0, $blue ); + $colorArray = $this->formatColor($blueChroma); + $match = $this->testColorExists($colorArray); + $blue--; + + } while ($match == false && $blue > 0); + + // *** If no match, just bite the bullet and use blue value of 255 + if ( ! $match) + { + $blueChroma = array( 0, 0, $blue ); + } + + return $blueChroma; + } + + ## -------------------------------------------------------- + + private function invertTransparency($value, $originalMax, $invert = true) + # Purpose: This does two things: + # 1) Convert the range from 0-127 to 0-100 + # 2) Inverts value to 100 is not transparent while 0 is fully + # transparent (like Photoshop) + { + // *** Test max range + if ($value > $originalMax) + { + $value = $originalMax; + } + + // *** Test min range + if ($value < 0) + { + $value = 0; + } + + if ($invert) + { + return $originalMax - (($value / 100) * $originalMax); + } + else + { + return ($value / 100) * $originalMax; + } + } + + ## -------------------------------------------------------- + + private function transparentImage($src) + { + // *** making images with white bg transparent + $r1 = 0; + $g1 = 255; + $b1 = 0; + for ($x = 0; $x < imagesx($src); ++$x) + { + for ($y = 0; $y < imagesy($src); ++$y) + { + $color = imagecolorat($src, $x, $y); + $r = ($color >> 16) & 0xFF; + $g = ($color >> 8) & 0xFF; + $b = $color & 0xFF; + for ($i = 0; $i < 270; $i++) + { + //if ($r . $g . $b == ($r1 + $i) . ($g1 + $i) . ($b1 + $i)) { + if ($r == 0 && $g == 255 && $b == 0) + { + //if ($g == 255) { + $trans_colour = imagecolorallocatealpha($src, 0, 0, 0, 127); + imagefill($src, $x, $y, $trans_colour); + } + } + } + } + + return $src; + } + + ## -------------------------------------------------------- + + function checkStringStartsWith($needle, $haystack) + # Check if a string starts with a specific pattern + { + return (substr($haystack, 0, strlen($needle)) == $needle); + } + + + /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*- + BMP SUPPORT (SAVING) - James Heinrich +*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*/ + + private function GD2BMPstring(&$gd_image) + # Author: James Heinrich + # Purpose: Save file as type bmp + # Param in: The image canvas (passed as ref) + # Param out: + # Reference: + # Notes: This code was stripped out of two external files + # (phpthumb.bmp.php,phpthumb.functions.php) and added below to + # avoid dependancies. + # + { + $imageX = ImageSX($gd_image); + $imageY = ImageSY($gd_image); + + $BMP = ''; + for ($y = ($imageY - 1); $y >= 0; $y--) + { + $thisline = ''; + for ($x = 0; $x < $imageX; $x++) + { + $argb = $this->GetPixelColor($gd_image, $x, $y); + $thisline .= chr($argb['blue']) . chr($argb['green']) . chr($argb['red']); + } + while (strlen($thisline) % 4) + { + $thisline .= "\x00"; + } + $BMP .= $thisline; + } + + $bmpSize = strlen($BMP) + 14 + 40; + // BITMAPFILEHEADER [14 bytes] - http://msdn.microsoft.com/library/en-us/gdi/bitmaps_62uq.asp + $BITMAPFILEHEADER = 'BM'; // WORD bfType; + $BITMAPFILEHEADER .= $this->LittleEndian2String($bmpSize, 4); // DWORD bfSize; + $BITMAPFILEHEADER .= $this->LittleEndian2String(0, 2); // WORD bfReserved1; + $BITMAPFILEHEADER .= $this->LittleEndian2String(0, 2); // WORD bfReserved2; + $BITMAPFILEHEADER .= $this->LittleEndian2String(54, 4); // DWORD bfOffBits; + + // BITMAPINFOHEADER - [40 bytes] http://msdn.microsoft.com/library/en-us/gdi/bitmaps_1rw2.asp + $BITMAPINFOHEADER = $this->LittleEndian2String(40, 4); // DWORD biSize; + $BITMAPINFOHEADER .= $this->LittleEndian2String($imageX, 4); // LONG biWidth; + $BITMAPINFOHEADER .= $this->LittleEndian2String($imageY, 4); // LONG biHeight; + $BITMAPINFOHEADER .= $this->LittleEndian2String(1, 2); // WORD biPlanes; + $BITMAPINFOHEADER .= $this->LittleEndian2String(24, 2); // WORD biBitCount; + $BITMAPINFOHEADER .= $this->LittleEndian2String(0, 4); // DWORD biCompression; + $BITMAPINFOHEADER .= $this->LittleEndian2String(0, 4); // DWORD biSizeImage; + $BITMAPINFOHEADER .= $this->LittleEndian2String(2835, 4); // LONG biXPelsPerMeter; + $BITMAPINFOHEADER .= $this->LittleEndian2String(2835, 4); // LONG biYPelsPerMeter; + $BITMAPINFOHEADER .= $this->LittleEndian2String(0, 4); // DWORD biClrUsed; + $BITMAPINFOHEADER .= $this->LittleEndian2String(0, 4); // DWORD biClrImportant; + + return $BITMAPFILEHEADER . $BITMAPINFOHEADER . $BMP; + } + +## -------------------------------------------------------- + + private function GetPixelColor(&$img, $x, $y) + # Author: James Heinrich + # Purpose: + # Param in: + # Param out: + # Reference: + # Notes: + # + { + if ( ! is_resource($img)) + { + return false; + } + + return @ImageColorsForIndex($img, @ImageColorAt($img, $x, $y)); + } + +## -------------------------------------------------------- + + private function LittleEndian2String($number, $minbytes = 1) + # Author: James Heinrich + # Purpose: BMP SUPPORT (SAVING) + # Param in: + # Param out: + # Reference: + # Notes: + # + { + $intstring = ''; + while ($number > 0) + { + $intstring = $intstring . chr($number & 255); + $number >>= 8; + } + + return str_pad($intstring, $minbytes, "\x00", STR_PAD_RIGHT); + } + + + /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*- + BMP SUPPORT (READING) +*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*/ + + private function ImageCreateFromBMP($filename) + # Author: DHKold + # Date: The 15th of June 2005 + # Version: 2.0B + # Purpose: To create an image from a BMP file. + # Param in: BMP file to open. + # Param out: Return a resource like the other ImageCreateFrom functions + # Reference: http://us3.php.net/manual/en/function.imagecreate.php#53879 + # Bug fix: Author: domelca at terra dot es + # Date: 06 March 2008 + # Fix: Correct 16bit BMP support + # Notes: + # + { + + //Ouverture du fichier en mode binaire + if ( ! $f1 = fopen($filename, "rb")) + { + return false; + } + + //1 : Chargement des ent�tes FICHIER + $FILE = unpack("vfile_type/Vfile_size/Vreserved/Vbitmap_offset", fread($f1, 14)); + if ($FILE['file_type'] != 19778) + { + return false; + } + + //2 : Chargement des ent�tes BMP + $BMP = unpack('Vheader_size/Vwidth/Vheight/vplanes/vbits_per_pixel' . + '/Vcompression/Vsize_bitmap/Vhoriz_resolution' . + '/Vvert_resolution/Vcolors_used/Vcolors_important', fread($f1, 40)); + $BMP['colors'] = pow(2, $BMP['bits_per_pixel']); + + if ($BMP['size_bitmap'] == 0) + { + $BMP['size_bitmap'] = $FILE['file_size'] - $FILE['bitmap_offset']; + } + + $BMP['bytes_per_pixel'] = $BMP['bits_per_pixel'] / 8; + $BMP['bytes_per_pixel2'] = ceil($BMP['bytes_per_pixel']); + $BMP['decal'] = ($BMP['width'] * $BMP['bytes_per_pixel'] / 4); + $BMP['decal'] -= floor($BMP['width'] * $BMP['bytes_per_pixel'] / 4); + $BMP['decal'] = 4 - (4 * $BMP['decal']); + + if ($BMP['decal'] == 4) + { + $BMP['decal'] = 0; + } + + //3 : Chargement des couleurs de la palette + $PALETTE = array(); + if ($BMP['colors'] < 16777216) + { + $PALETTE = unpack('V' . $BMP['colors'], fread($f1, $BMP['colors'] * 4)); + } + + //4 : Cr�ation de l'image + $IMG = fread($f1, $BMP['size_bitmap']); + $VIDE = chr(0); + + $res = imagecreatetruecolor($BMP['width'], $BMP['height']); + $P = 0; + $Y = $BMP['height'] - 1; + while ($Y >= 0) + { + $X = 0; + while ($X < $BMP['width']) + { + if ($BMP['bits_per_pixel'] == 24) + { + $COLOR = unpack("V", substr($IMG, $P, 3) . $VIDE); + } + elseif ($BMP['bits_per_pixel'] == 16) + { + + /* + * BMP 16bit fix + * ================= + * + * Ref: http://us3.php.net/manual/en/function.imagecreate.php#81604 + * + * Notes: + * "don't work with bmp 16 bits_per_pixel. change pixel + * generator for this." + * + */ + + // *** Original code (don't work) + //$COLOR = unpack("n",substr($IMG,$P,2)); + //$COLOR[1] = $PALETTE[$COLOR[1]+1]; + + $COLOR = unpack("v", substr($IMG, $P, 2)); + $blue = ($COLOR[1] & 0x001f) << 3; + $green = ($COLOR[1] & 0x07e0) >> 3; + $red = ($COLOR[1] & 0xf800) >> 8; + $COLOR[1] = $red * 65536 + $green * 256 + $blue; + + } + elseif ($BMP['bits_per_pixel'] == 8) + { + $COLOR = unpack("n", $VIDE . substr($IMG, $P, 1)); + $COLOR[1] = $PALETTE[ $COLOR[1] + 1 ]; + } + elseif ($BMP['bits_per_pixel'] == 4) + { + $COLOR = unpack("n", $VIDE . substr($IMG, floor($P), 1)); + if (($P * 2) % 2 == 0) + { + $COLOR[1] = ($COLOR[1] >> 4); + } + else + { + $COLOR[1] = ($COLOR[1] & 0x0F); + } + $COLOR[1] = $PALETTE[ $COLOR[1] + 1 ]; + } + elseif ($BMP['bits_per_pixel'] == 1) + { + $COLOR = unpack("n", $VIDE . substr($IMG, floor($P), 1)); + if (($P * 8) % 8 == 0) + { + $COLOR[1] = $COLOR[1] >> 7; + } + elseif (($P * 8) % 8 == 1) + { + $COLOR[1] = ($COLOR[1] & 0x40) >> 6; + } + elseif (($P * 8) % 8 == 2) + { + $COLOR[1] = ($COLOR[1] & 0x20) >> 5; + } + elseif (($P * 8) % 8 == 3) + { + $COLOR[1] = ($COLOR[1] & 0x10) >> 4; + } + elseif (($P * 8) % 8 == 4) + { + $COLOR[1] = ($COLOR[1] & 0x8) >> 3; + } + elseif (($P * 8) % 8 == 5) + { + $COLOR[1] = ($COLOR[1] & 0x4) >> 2; + } + elseif (($P * 8) % 8 == 6) + { + $COLOR[1] = ($COLOR[1] & 0x2) >> 1; + } + elseif (($P * 8) % 8 == 7) + { + $COLOR[1] = ($COLOR[1] & 0x1); + } + $COLOR[1] = $PALETTE[ $COLOR[1] + 1 ]; + } + else + { + return false; + } + + imagesetpixel($res, $X, $Y, $COLOR[1]); + $X++; + $P += $BMP['bytes_per_pixel']; + } + + $Y--; + $P += $BMP['decal']; + } + //Fermeture du fichier + fclose($f1); + + return $res; + } + + + /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*- + PSD SUPPORT (READING) +*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*/ + + private function imagecreatefrompsd($fileName) + # Author: Tim de Koning + # Version: 1.3 + # Purpose: To create an image from a PSD file. + # Param in: PSD file to open. + # Param out: Return a resource like the other ImageCreateFrom functions + # Reference: http://www.kingsquare.nl/phppsdreader + # Notes: + # + { + if (file_exists($this->psdReaderPath)) + { + + + include_once($this->psdReaderPath); + + $psdReader = new PhpPsdReader($fileName); + + if (isset($psdReader->infoArray['error'])) + { + return ''; + } + else + { + return $psdReader->getImage(); + } + } + else + { + return false; + } + } + +## -------------------------------------------------------- + + public function __destruct() + { + if (is_resource($this->imageResized)) + { + imagedestroy($this->imageResized); + } + } + +## -------------------------------------------------------- + +} + + +/* + * Example with some API calls (outdated): + * + * + * =============================== + * Compulsary + * =============================== + * + * include("classes/resize_class.php"); + * + * // *** Initialise object + * $magicianObj = new resize('images/cars/large/a.jpg'); + * + * // *** Turn off stretching (optional) + * $magicianObj -> setForceStretch(false); + * + * // *** Resize object + * $magicianObj -> resizeImage(150, 100, 0); + * + * =============================== + * Image options - can run none, one, or all. + * =============================== + * + * // *** Add watermark + * $magicianObj -> addWatermark('stamp.png'); + * + * // *** Add text + * $magicianObj -> addText('testing...'); + * + * =============================== + * Output options - can run one, or the other, or both. + * =============================== + * + * // *** Save image to disk + * $magicianObj -> saveImage('images/cars/large/b.jpg', 100); + * + * // *** Or output to screen (params in can be jpg, gif, png) + * $magicianObj -> displayImage('png'); + * + * =============================== + * Return options - return errors. nice for debuggin. + * =============================== + * + * // *** Return error array + * $errorArray = $magicianObj -> getErrors(); + * + * + * =============================== + * Cleanup options - not really neccessary, but good practice + * =============================== + * + * // *** Free used memory + * $magicianObj -> __destruct(); + */ diff --git a/local/modules/Tinymce/Resources/js/tinymce/filemanager/include/utils.php b/local/modules/Tinymce/Resources/js/tinymce/filemanager/include/utils.php new file mode 100644 index 00000000..18916924 --- /dev/null +++ b/local/modules/Tinymce/Resources/js/tinymce/filemanager/include/utils.php @@ -0,0 +1,1164 @@ +send(); + exit; + } + + } + if(file_exists('lang/' . $lang . '.php')){ + $lang_vars = include 'lang/' . $lang . '.php'; + }else{ + $lang_vars = include '../lang/' . $lang . '.php'; + } + + if ( ! is_array($lang_vars)) + { + $lang_vars = array(); + } + /** + * Translate language variable + * + * @param $var string name + * + * @return string translated variable + */ + function trans($var) + { + global $lang_vars; + + return (array_key_exists($var, $lang_vars)) ? $lang_vars[ $var ] : $var; + } +} + +/** +* Delete directory +* +* @param string $dir +* +* @return bool +*/ +function deleteDir($dir,$ftp = null, $config = null) +{ + if($ftp){ + + try{ + $ftp->rmdir($dir); + return true; + + }catch(FtpClient\FtpException $e){ + return null; + } + + }else{ + if ( ! file_exists($dir)) + { + return false; + } + if ( ! is_dir($dir)) + { + return unlink($dir); + } + foreach (scandir($dir) as $item) + { + if ($item == '.' || $item == '..') + { + continue; + } + if ( ! deleteDir($dir . DIRECTORY_SEPARATOR . $item)) + { + return false; + } + } + } + + return rmdir($dir); +} + +/** +* Make a file copy +* +* @param string $old_path +* @param string $name New file name without extension +* +* @return bool +*/ +function duplicate_file( $old_path, $name, $ftp = null, $config = null ) +{ + $info = pathinfo($old_path); + $new_path = $info['dirname'] . "/" . $name . "." . $info['extension']; + if($ftp){ + try{ + $tmp = time().$name . "." . $info['extension']; + $ftp->get($tmp, "/".$old_path, FTP_BINARY); + $ftp->put("/".$new_path, $tmp, FTP_BINARY); + unlink($tmp); + return true; + + }catch(FtpClient\FtpException $e){ + return null; + } + }else{ + if (file_exists($old_path)) + { + if (file_exists($new_path) && $old_path == $new_path) + { + return false; + } + + return copy($old_path, $new_path); + } + } +} + + +/** +* Rename file +* +* @param string $old_path File to rename +* @param string $name New file name without extension +* @param bool $transliteration +* +* @return bool +*/ +function rename_file($old_path, $name, $ftp = null, $config = null) +{ + $name = fix_filename($name, $config); + $info = pathinfo($old_path); + $new_path = $info['dirname'] . "/" . $name . "." . $info['extension']; + if($ftp){ + try{ + return $ftp->rename("/".$old_path, "/".$new_path); + }catch(FtpClient\FtpException $e){ + return false; + } + }else{ + if (file_exists($old_path)) + { + $new_path = $info['dirname'] . "/" . $name . "." . $info['extension']; + if (file_exists($new_path) && $old_path == $new_path) + { + return false; + } + + return rename($old_path, $new_path); + } + } +} + + +function url_exists($url){ + if (!$fp = curl_init($url)) return false; + return true; +} + + +function tempdir() { + $tempfile=tempnam(sys_get_temp_dir(),''); + if (file_exists($tempfile)) { unlink($tempfile); } + mkdir($tempfile); + if (is_dir($tempfile)) { return $tempfile; } +} + + +/** +* Rename directory +* +* @param string $old_path Directory to rename +* @param string $name New directory name +* @param bool $transliteration +* +* @return bool +*/ +function rename_folder($old_path, $name, $ftp = null, $config = null) +{ + $name = fix_filename($name, $config, true); + $new_path = fix_dirname($old_path) . "/" . $name; + if($ftp){ + if($ftp->chdir("/".$old_path)){ + if(@$ftp->chdir($new_path)){ + return false; + } + return $ftp->rename("/".$old_path, "/".$new_path); + } + }else{ + if (file_exists($old_path)) + { + if (file_exists($new_path) && $old_path == $new_path) + { + return false; + } + + return rename($old_path, $new_path); + } + } +} + +function ftp_con($config){ + if(isset($config['ftp_host']) && $config['ftp_host']){ + // *** Include the class + include('include/FtpClient.php'); + include('include/FtpException.php'); + include('include/FtpWrapper.php'); + + $ftp = new \FtpClient\FtpClient(); + try{ + $ftp->connect($config['ftp_host'],$config['ftp_ssl'],$config['ftp_port']); + $ftp->login($config['ftp_user'], $config['ftp_pass']); + $ftp->pasv(true); + return $ftp; + }catch(FtpClient\FtpException $e){ + echo "Error: "; + echo $e->getMessage(); + echo " to server "; + $tmp = $e->getTrace(); + echo $tmp[0]['args'][0]; + echo "
    Please check configurations"; + die(); + } + }else{ + return false; + } +} + +/** +* Create new image from existing file +* +* @param string $imgfile Source image file name +* @param string $imgthumb Thumbnail file name +* @param int $newwidth Thumbnail width +* @param int $newheight Optional thumbnail height +* @param string $option Type of resize +* +* @return bool +* @throws \Exception +*/ +function create_img($imgfile, $imgthumb, $newwidth, $newheight = null, $option = "crop", $ftp=false,$config = array()) +{ + $result = false; + if($ftp ){ + if(url_exists($imgfile)){ + $temp = tempnam('/tmp','RF'); + unlink($temp); + $temp .=".".substr(strrchr($imgfile,'.'),1); + $handle = fopen($temp, "w"); + fwrite($handle, file_get_contents($imgfile)); + fclose($handle); + $imgfile= $temp; + $save_ftp = $imgthumb; + $imgthumb = $temp; + } + } + if(file_exists($imgfile) || strpos($imgfile,'http')===0){ + if (strpos($imgfile,'http')===0 || image_check_memory_usage($imgfile, $newwidth, $newheight)) + { + require_once('php_image_magician.php'); + try{ + $magicianObj = new imageLib($imgfile); + $magicianObj->resizeImage($newwidth, $newheight, $option); + $magicianObj->saveImage($imgthumb, 80); + }catch (Exception $e){ + return false; + } + $result = true; + } + } + if($result && $ftp ){ + $ftp->put($save_ftp, $imgthumb, FTP_BINARY); + unlink($imgthumb); + } + + return $result; +} + +/** +* Convert convert size in bytes to human readable +* +* @param int $size +* +* @return string +*/ +function makeSize($size) +{ + $units = array( 'B', 'KB', 'MB', 'GB', 'TB' ); + $u = 0; + while ((round($size / 1024) > 0) && ($u < 4)) + { + $size = $size / 1024; + $u++; + } + + return (number_format($size, 0) . " " . trans($units[ $u ])); +} + +/** +* Determine directory size +* +* @param string $path +* +* @return int +*/ +function folder_info($path,$count_hidden=true) +{ + global $hidden_folders,$hidden_files; + $total_size = 0; + $files = scandir($path); + $cleanPath = rtrim($path, '/') . '/'; + $files_count = 0; + $folders_count = 0; + foreach ($files as $t) + { + if ($t != "." && $t != "..") + { + if ($count_hidden or !(in_array($t,$hidden_folders) or in_array($t,$hidden_files))) + { + $currentFile = $cleanPath . $t; + if (is_dir($currentFile)) + { + list($size,$tmp,$tmp1) = folder_info($currentFile); + $total_size += $size; + $folders_count ++; + } + else + { + $size = filesize($currentFile); + $total_size += $size; + $files_count++; + } + } + } + } + + return array($total_size,$files_count,$folders_count); +} +/** +* Get number of files in a directory +* +* @param string $path +* +* @return int +*/ +function filescount($path,$count_hidden=true) +{ + global $hidden_folders,$hidden_files; + $total_count = 0; + $files = scandir($path); + $cleanPath = rtrim($path, '/') . '/'; + + foreach ($files as $t) + { + if ($t != "." && $t != "..") + { + if ($count_hidden or !(in_array($t,$hidden_folders) or in_array($t,$hidden_files))) + { + $currentFile = $cleanPath . $t; + if (is_dir($currentFile)) + { + $size = filescount($currentFile); + $total_count += $size; + } + else + { + $total_count += 1; + } + } + } + } + + return $total_count; +} +/** +* check if the current folder size plus the added size is over the overall size limite +* +* @param int $sizeAdded +* +* @return bool +*/ +function checkresultingsize($sizeAdded) +{ + global $MaxSizeTotal,$current_path; + if ($MaxSizeTotal !== false && is_int($MaxSizeTotal)) { + list($sizeCurrentFolder,$fileCurrentNum,$foldersCurrentCount) = folder_info($current_path,false); + // overall size over limit + if (($MaxSizeTotal * 1024 * 1024) < ($sizeCurrentFolder + $sizeAdded)) { + return false; + } + } + return true; +} + +/** +* Create directory for images and/or thumbnails +* +* @param string $path +* @param string $path_thumbs +*/ +function create_folder($path = null, $path_thumbs = null,$ftp = null,$config = null) +{ + if($ftp){ + $ftp->mkdir($path); + $ftp->mkdir($path_thumbs); + }else{ + $oldumask = umask(0); + if ($path && ! file_exists($path)) + { + mkdir($path, 0755, true); + } // or even 01777 so you get the sticky bit set + if ($path_thumbs && ! file_exists($path_thumbs)) + { + mkdir($path_thumbs, 0755, true) or die("$path_thumbs cannot be found"); + } // or even 01777 so you get the sticky bit set + umask($oldumask); + } +} + +/** +* Get file extension present in directory +* +* @param string $path +* @param string $ext +*/ +function check_files_extensions_on_path($path, $ext) +{ + if ( ! is_dir($path)) + { + $fileinfo = pathinfo($path); + if ( ! in_array(mb_strtolower($fileinfo['extension']), $ext)) + { + unlink($path); + } + } + else + { + $files = scandir($path); + foreach ($files as $file) + { + check_files_extensions_on_path(trim($path, '/') . "/" . $file, $ext); + } + } +} + +/** +* Get file extension present in PHAR file +* +* @param string $phar +* @param array $files +* @param string $basepath +* @param string $ext +*/ +function check_files_extensions_on_phar($phar, &$files, $basepath, $ext) +{ + foreach ($phar as $file) + { + if ($file->isFile()) + { + if (in_array(mb_strtolower($file->getExtension()), $ext)) + { + $files[] = $basepath . $file->getFileName(); + } + } + else + { + if ($file->isDir()) + { + $iterator = new DirectoryIterator($file); + check_files_extensions_on_phar($iterator, $files, $basepath . $file->getFileName() . '/', $ext); + } + } + } +} + +/** +* Cleanup input +* +* @param string $str +* +* @return string +*/ +function fix_get_params($str) +{ + return strip_tags(preg_replace("/[^a-zA-Z0-9\.\[\]_| -]/", '', $str)); +} + +/** +* Cleanup filename +* +* @param string $str +* @param bool $transliteration +* @param bool $convert_spaces +* @param string $replace_with +* @param bool $is_folder +* +* @return string +*/ +function fix_filename($str, $config, $is_folder = false) +{ + if ($config['convert_spaces']) + { + $str = str_replace(' ', $config['replace_with'], $str); + } + + if ($config['transliteration']) + { + if (!mb_detect_encoding($str, 'UTF-8', true)) + { + $str = utf8_encode($str); + } + if (function_exists('transliterator_transliterate')) + { + $str = transliterator_transliterate('Any-Latin; Latin-ASCII', $str); + } + else + { + $str = iconv('UTF-8', 'ASCII//TRANSLIT//IGNORE', $str); + } + + $str = preg_replace("/[^a-zA-Z0-9\.\[\]_| -]/", '', $str); + } + + $str = str_replace(array( '"', "'", "/", "\\" ), "", $str); + $str = strip_tags($str); + + // Empty or incorrectly transliterated filename. + // Here is a point: a good file UNKNOWN_LANGUAGE.jpg could become .jpg in previous code. + // So we add that default 'file' name to fix that issue. + if (strpos($str, '.') === 0 && $is_folder === false) + { + $str = 'file' . $str; + } + + return trim($str); +} + +/** +* Cleanup directory name +* +* @param string $str +* +* @return string +*/ +function fix_dirname($str) +{ + return str_replace('~', ' ', dirname(str_replace(' ', '~', $str))); +} + +/** +* Correct strtoupper handling +* +* @param string $str +* +* @return string +*/ +function fix_strtoupper($str) +{ + if (function_exists('mb_strtoupper')) + { + return mb_strtoupper($str); + } + else + { + return strtoupper($str); + } +} + +/** +* Correct strtolower handling +* +* @param string $str +* +* @return string +*/ +function fix_strtolower($str) +{ + if (function_exists('mb_strtoupper')) + { + return mb_strtolower($str); + } + else + { + return strtolower($str); + } +} + +function fix_path($path, $config) +{ + $info = pathinfo($path); + $tmp_path = $info['dirname']; + $str = fix_filename($info['filename'], $config); + if ($tmp_path != "") + { + return $tmp_path . DIRECTORY_SEPARATOR . $str; + } + else + { + return $str; + } +} + +/** +* @param $current_path +* @param $fld +* +* @return bool +*/ +function config_loading($current_path, $fld) +{ + if (file_exists($current_path . $fld . ".config")) + { + require_once($current_path . $fld . ".config"); + + return true; + } + echo "!!!!" . $parent = fix_dirname($fld); + if ($parent != "." && ! empty($parent)) + { + config_loading($current_path, $parent); + } + + return false; +} + +/** +* Check if memory is enough to process image +* +* @param string $img +* @param int $max_breedte +* @param int $max_hoogte +* +* @return bool +*/ +function image_check_memory_usage($img, $max_breedte, $max_hoogte) +{ + if (file_exists($img)) + { + $K64 = 65536; // number of bytes in 64K + $memory_usage = memory_get_usage(); + $memory_limit = abs(intval(str_replace('M', '', ini_get('memory_limit')) * 1024 * 1024)); + $image_properties = getimagesize($img); + $image_width = $image_properties[0]; + $image_height = $image_properties[1]; + if (isset($image_properties['bits'])) + $image_bits = $image_properties['bits']; + else + $image_bits = 0; + $image_memory_usage = $K64 + ($image_width * $image_height * ($image_bits) * 2); + $thumb_memory_usage = $K64 + ($max_breedte * $max_hoogte * ($image_bits) * 2); + $memory_needed = abs(intval($memory_usage + $image_memory_usage + $thumb_memory_usage)); + + if ($memory_needed > $memory_limit) + { + return false; + } + else + { + return true; + } + } + else + { + return false; + } +} + +/** +* Check is string is ended with needle +* +* @param string $haystack +* @param string $needle +* +* @return bool +*/ +function endsWith($haystack, $needle) +{ + return $needle === "" || substr($haystack, -strlen($needle)) === $needle; +} + +/** +* TODO REFACTOR THIS! +* +* @param $targetPath +* @param $targetFile +* @param $name +* @param $current_path +* @param $relative_image_creation +* @param $relative_path_from_current_pos +* @param $relative_image_creation_name_to_prepend +* @param $relative_image_creation_name_to_append +* @param $relative_image_creation_width +* @param $relative_image_creation_height +* @param $relative_image_creation_option +* @param $fixed_image_creation +* @param $fixed_path_from_filemanager +* @param $fixed_image_creation_name_to_prepend +* @param $fixed_image_creation_to_append +* @param $fixed_image_creation_width +* @param $fixed_image_creation_height +* @param $fixed_image_creation_option +* +* @return bool +*/ +function new_thumbnails_creation($targetPath, $targetFile, $name, $current_path, $relative_image_creation, $relative_path_from_current_pos, $relative_image_creation_name_to_prepend, $relative_image_creation_name_to_append, $relative_image_creation_width, $relative_image_creation_height, $relative_image_creation_option, $fixed_image_creation, $fixed_path_from_filemanager, $fixed_image_creation_name_to_prepend, $fixed_image_creation_to_append, $fixed_image_creation_width, $fixed_image_creation_height, $fixed_image_creation_option) +{ + //create relative thumbs + $all_ok = true; + if ($relative_image_creation) + { + foreach ($relative_path_from_current_pos as $k => $path) + { + if ($path != "" && $path[ strlen($path) - 1 ] != "/") + { + $path .= "/"; + } + if ( ! file_exists($targetPath . $path)) + { + create_folder($targetPath . $path, false); + } + $info = pathinfo($name); + if ( ! endsWith($targetPath, $path)) + { + if ( ! create_img($targetFile, $targetPath . $path . $relative_image_creation_name_to_prepend[ $k ] . $info['filename'] . $relative_image_creation_name_to_append[ $k ] . "." . $info['extension'], $relative_image_creation_width[ $k ], $relative_image_creation_height[ $k ], $relative_image_creation_option[ $k ])) + { + $all_ok = false; + } + } + } + } + + //create fixed thumbs + if ($fixed_image_creation) + { + foreach ($fixed_path_from_filemanager as $k => $path) + { + if ($path != "" && $path[ strlen($path) - 1 ] != "/") + { + $path .= "/"; + } + $base_dir = $path . substr_replace($targetPath, '', 0, strlen($current_path)); + if ( ! file_exists($base_dir)) + { + create_folder($base_dir, false); + } + $info = pathinfo($name); + if ( ! create_img($targetFile, $base_dir . $fixed_image_creation_name_to_prepend[ $k ] . $info['filename'] . $fixed_image_creation_to_append[ $k ] . "." . $info['extension'], $fixed_image_creation_width[ $k ], $fixed_image_creation_height[ $k ], $fixed_image_creation_option[ $k ])) + { + $all_ok = false; + } + } + } + + return $all_ok; +} + + +/** +* Get a remote file, using whichever mechanism is enabled +* +* @param string $url +* +* @return bool|mixed|string +*/ +function get_file_by_url($url) +{ + if (ini_get('allow_url_fopen')) + { + $arrContextOptions=array( + "ssl"=>array( + "verify_peer"=>false, + "verify_peer_name"=>false, + ), + ); + return file_get_contents($url, false, stream_context_create($arrContextOptions)); + } + if ( ! function_exists('curl_version')) + { + return false; + } + + $ch = curl_init(); + + curl_setopt($ch, CURLOPT_HEADER, 0); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); + curl_setopt($ch, CURLOPT_URL, $url); + + $data = curl_exec($ch); + curl_close($ch); + + return $data; +} + +/** +* test for dir/file writability properly +* +* @param string $dir +* +* @return bool +*/ +function is_really_writable($dir) +{ + $dir = rtrim($dir, '/'); + // linux, safe off + if (DIRECTORY_SEPARATOR == '/' && @ini_get("safe_mode") == false) + { + return is_writable($dir); + } + + // Windows, safe ON. (have to write a file :S) + if (is_dir($dir)) + { + $dir = $dir . '/' . md5(mt_rand(1, 1000) . mt_rand(1, 1000)); + + if (($fp = @fopen($dir, 'ab')) === false) + { + return false; + } + + fclose($fp); + @chmod($dir, 0755); + @unlink($dir); + + return true; + } + elseif ( ! is_file($dir) || ($fp = @fopen($dir, 'ab')) === false) + { + return false; + } + + fclose($fp); + + return true; +} + +/** +* Check if a function is callable. +* Some servers disable copy,rename etc. +* +* @parm string $name +* +* @return bool +*/ +function is_function_callable($name) +{ + if (function_exists($name) === false) + { + return false; + } + $disabled = explode(',', ini_get('disable_functions')); + + return ! in_array($name, $disabled); +} + +/** +* recursivly copies everything +* +* @param string $source +* @param string $destination +* @param bool $is_rec +*/ +function rcopy($source, $destination, $is_rec = false) +{ + if (is_dir($source)) + { + if ($is_rec === false) + { + $pinfo = pathinfo($source); + $destination = rtrim($destination, '/') . DIRECTORY_SEPARATOR . $pinfo['basename']; + } + if (is_dir($destination) === false) + { + mkdir($destination, 0755, true); + } + + $files = scandir($source); + foreach ($files as $file) + { + if ($file != "." && $file != "..") + { + rcopy($source . DIRECTORY_SEPARATOR . $file, rtrim($destination, '/') . DIRECTORY_SEPARATOR . $file, true); + } + } + } + else + { + if (file_exists($source)) + { + if (is_dir($destination) === true) + { + $pinfo = pathinfo($source); + $dest2 = rtrim($destination, '/') . DIRECTORY_SEPARATOR . $pinfo['basename']; + } + else + { + $dest2 = $destination; + } + + copy($source, $dest2); + } + } +} + + + + +/** +* recursivly renames everything +* +* I know copy and rename could be done with just one function +* but i split the 2 because sometimes rename fails on windows +* Need more feedback from users and refactor if needed +* +* @param string $source +* @param string $destination +* @param bool $is_rec +*/ +function rrename($source, $destination, $is_rec = false) +{ + if (is_dir($source)) + { + if ($is_rec === false) + { + $pinfo = pathinfo($source); + $destination = rtrim($destination, '/') . DIRECTORY_SEPARATOR . $pinfo['basename']; + } + if (is_dir($destination) === false) + { + mkdir($destination, 0755, true); + } + + $files = scandir($source); + foreach ($files as $file) + { + if ($file != "." && $file != "..") + { + rrename($source . DIRECTORY_SEPARATOR . $file, rtrim($destination, '/') . DIRECTORY_SEPARATOR . $file, true); + } + } + } + else + { + if (file_exists($source)) + { + if (is_dir($destination) === true) + { + $pinfo = pathinfo($source); + $dest2 = rtrim($destination, '/') . DIRECTORY_SEPARATOR . $pinfo['basename']; + } + else + { + $dest2 = $destination; + } + + rename($source, $dest2); + } + } +} + +// On windows rename leaves folders sometime +// This will clear leftover folders +// After more feedback will merge it with rrename +function rrename_after_cleaner($source) +{ + $files = scandir($source); + + foreach ($files as $file) + { + if ($file != "." && $file != "..") + { + if (is_dir($source . DIRECTORY_SEPARATOR . $file)) + { + rrename_after_cleaner($source . DIRECTORY_SEPARATOR . $file); + } + else + { + unlink($source . DIRECTORY_SEPARATOR . $file); + } + } + } + + return rmdir($source); +} + +/** +* Recursive chmod +* @param string $source +* @param int $mode +* @param string $rec_option +* @param bool $is_rec +*/ +function rchmod($source, $mode, $rec_option = "none", $is_rec = false) +{ + if ($rec_option == "none") + { + chmod($source, $mode); + } + else + { + if ($is_rec === false) + { + chmod($source, $mode); + } + + $files = scandir($source); + + foreach ($files as $file) + { + if ($file != "." && $file != "..") + { + if (is_dir($source . DIRECTORY_SEPARATOR . $file)) + { + if ($rec_option == "folders" || $rec_option == "both") + { + chmod($source . DIRECTORY_SEPARATOR . $file, $mode); + } + rchmod($source . DIRECTORY_SEPARATOR . $file, $mode, $rec_option, true); + } + else + { + if ($rec_option == "files" || $rec_option == "both") + { + chmod($source . DIRECTORY_SEPARATOR . $file, $mode); + } + } + } + } + } +} + +/** +* @param string $input +* @param bool $trace +* @param bool $halt +*/ +function debugger($input, $trace = false, $halt = false) +{ + ob_start(); + + echo "
    ----- DEBUG DUMP -----"; + echo "

    ";
    +	var_dump($input);
    +	echo "
    "; + + if ($trace) + { + if (is_php('5.3.6')) + { + $debug = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS); + } + else + { + $debug = debug_backtrace(false); + } + + echo "
    -----STACK TRACE-----"; + echo "
    ";
    +		var_dump($debug);
    +		echo "
    "; + } + + echo ""; + echo "---------------------------
    "; + + $ret = ob_get_contents(); + ob_end_clean(); + + echo $ret; + + if ($halt == true) + { + exit(); + } +} + +/** +* @param string $version +* +* @return bool +*/ +function is_php($version = '5.0.0') +{ + static $phpVer; + $version = (string) $version; + + if ( ! isset($phpVer[ $version ])) + { + $phpVer[ $version ] = (version_compare(PHP_VERSION, $version) < 0) ? false : true; + } + + return $phpVer[ $version ]; +} + +/** +* Return the caller location if set in config.php +* @param string $version +* +* @return bool +*/ +function AddErrorLocation() +{ + if (defined('DEBUG_ERROR_MESSAGE') and DEBUG_ERROR_MESSAGE) { + $pile=debug_backtrace(); + return " (@".$pile[0]["file"]."#".$pile[0]["line"].")"; + } + return ""; +} +?> diff --git a/local/modules/Tinymce/Resources/js/tinymce/filemanager/js/ZeroClipboard.swf b/local/modules/Tinymce/Resources/js/tinymce/filemanager/js/ZeroClipboard.swf new file mode 100644 index 0000000000000000000000000000000000000000..d4e2561b366e131d3bae303acce90a137a4956e1 GIT binary patch literal 4036 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 literal 0 HcmV?d00001 diff --git a/local/modules/Tinymce/Resources/js/tinymce/filemanager/js/include.js b/local/modules/Tinymce/Resources/js/tinymce/filemanager/js/include.js new file mode 100644 index 00000000..989b3abb --- /dev/null +++ b/local/modules/Tinymce/Resources/js/tinymce/filemanager/js/include.js @@ -0,0 +1,2 @@ +var encodeURL,show_animation,hide_animation,apply,apply_none,apply_img,apply_any,apply_video,apply_link,apply_file_rename,apply_file_duplicate,apply_folder_rename;!function(e,a,r){"use strict";function t(e){show_animation();var a=new Image;a.src=e,jQuery(a).on("load",function(){hide_animation()})}function n(){jQuery("#textfile_create_area").parent().parent().remove(),e.ajax({type:"GET",url:"ajax_calls.php?action=new_file_form"}).done(function(a){bootbox.dialog(a,[{label:jQuery("#cancel").val(),"class":"btn"},{label:jQuery("#ok").val(),"class":"btn-inverse",callback:function(){var a=jQuery("#create_text_file_name").val()+jQuery("#create_text_file_extension").val(),r=jQuery("#textfile_create_area").val();if(null!==a){a=_(a);var t=jQuery("#sub_folder").val()+jQuery("#fldr_value").val();e.ajax({type:"POST",url:"execute.php?action=create_file",data:{path:t,name:a,new_content:r}}).done(function(e){""!=e&&bootbox.alert(e,function(){setTimeout(function(){window.location.href=jQuery("#refresh").attr("href")+"&"+(new Date).getTime()},500)})})}}}],{header:jQuery("#lang_new_file").val()})})}function i(a){jQuery("#textfile_edit_area").parent().parent().remove();var r=a.find(".rename-file-paths").attr("data-path");e.ajax({type:"POST",url:"ajax_calls.php?action=get_file&sub_action=edit&preview_mode=text",data:{path:r}}).done(function(t){bootbox.dialog(t,[{label:jQuery("#cancel").val(),"class":"btn"},{label:jQuery("#ok").val(),"class":"btn-inverse",callback:function(){var a=jQuery("#textfile_edit_area").val();e.ajax({type:"POST",url:"execute.php?action=save_text_file",data:{path:r,new_content:a}}).done(function(e){""!=e&&bootbox.alert(e)})}}],{header:a.find(".name_download").val()})})}function l(){e.ajax({type:"POST",url:"ajax_calls.php?action=get_lang",data:{}}).done(function(a){bootbox.dialog(a,[{label:jQuery("#cancel").val(),"class":"btn"},{label:jQuery("#ok").val(),"class":"btn-inverse",callback:function(){var a=jQuery("#new_lang_select").val();e.ajax({type:"POST",url:"ajax_calls.php?action=change_lang",data:{choosen_lang:a}}).done(function(e){""!=e?bootbox.alert(e):setTimeout(function(){window.location.href=jQuery("#refresh").attr("href").replace(/lang=[\w]*&/i,"lang="+a+"&")+"&"+(new Date).getTime()},100)})}}],{header:jQuery("#lang_lang_change").val()})})}function o(a){jQuery("#files_permission_start").parent().parent().remove();var r=a.find(".rename-file-paths"),t=r.attr("data-path"),n=r.attr("data-permissions"),i=r.attr("data-folder");e.ajax({type:"POST",url:"ajax_calls.php?action=chmod",data:{path:t,permissions:n,folder:i}}).done(function(a){bootbox.dialog(a,[{label:jQuery("#cancel").val(),"class":"btn"},{label:jQuery("#ok").val(),"class":"btn-inverse",callback:function(){var a="-";a+=jQuery("#u_4").is(":checked")?"r":"-",a+=jQuery("#u_2").is(":checked")?"w":"-",a+=jQuery("#u_1").is(":checked")?"x":"-",a+=jQuery("#g_4").is(":checked")?"r":"-",a+=jQuery("#g_2").is(":checked")?"w":"-",a+=jQuery("#g_1").is(":checked")?"x":"-",a+=jQuery("#a_4").is(":checked")?"r":"-",a+=jQuery("#a_2").is(":checked")?"w":"-",a+=jQuery("#a_1").is(":checked")?"x":"-";var n=jQuery("#chmod_form #chmod_value").val();if(""!=n&&"undefined"!=typeof n){var l=jQuery("#chmod_form input[name=apply_recursive]:checked").val();""!=l&&"undefined"!=typeof l||(l="none"),e.ajax({type:"POST",url:"execute.php?action=chmod",data:{path:t,new_mode:n,is_recursive:l,folder:i}}).done(function(e){""!=e?bootbox.alert(e):r.attr("data-permissions",a)})}}}],{header:jQuery("#lang_file_permission").val()}),setTimeout(function(){u(!1)},100)})}function u(a){var r=[];if(r.user=0,r.group=0,r.all=0,"undefined"!=typeof a&&1==a){var t=jQuery("#chmod_form #chmod_value").val();r.user=t.substr(0,1),r.group=t.substr(1,1),r.all=t.substr(2,1),e.each(r,function(a){(""==r[a]||0==e.isNumeric(r[a])||parseInt(r[a])<0||parseInt(r[a])>7)&&(r[a]="0")}),jQuery("#chmod_form input:checkbox").each(function(){var e=jQuery(this).attr("data-group"),a=jQuery(this).attr("data-value");c(r[e],a)?jQuery(this).prop("checked",!0):jQuery(this).prop("checked",!1)})}else jQuery("#chmod_form input:checkbox:checked").each(function(){var e=jQuery(this).attr("data-group"),a=jQuery(this).attr("data-value");r[e]=parseInt(r[e])+parseInt(a)}),jQuery("#chmod_form #chmod_value").val(r.user.toString()+r.group.toString()+r.all.toString())}function c(a,r){var t=[];return t[1]=[1,3,5,7],t[2]=[2,3,6,7],t[4]=[4,5,6,7],a=parseInt(a),r=parseInt(r),e.inArray(a,t[r])!=-1}function s(){bootbox.confirm(jQuery("#lang_clear_clipboard_confirm").val(),jQuery("#cancel").val(),jQuery("#ok").val(),function(a){1==a&&e.ajax({type:"POST",url:"ajax_calls.php?action=clear_clipboard",data:{}}).done(function(e){""!=e?bootbox.alert(e):jQuery("#clipboard").val("0"),y(!1)})})}function d(a,r){if("copy"==r||"cut"==r){var t;t=a.hasClass("directory")?a.find(".rename-file-paths").attr("data-path"):a.find(".rename-file-paths").attr("data-path"),e.ajax({type:"POST",url:"ajax_calls.php?action=copy_cut",data:{path:t,sub_action:r}}).done(function(e){""!=e?bootbox.alert(e):(jQuery("#clipboard").val("1"),y(!0))})}}function f(a){bootbox.confirm(jQuery("#lang_paste_confirm").val(),jQuery("#cancel").val(),jQuery("#ok").val(),function(r){if(1==r){var t;t="undefined"!=typeof a?a.find(".rename-folder").attr("data-path"):jQuery("#sub_folder").val()+jQuery("#fldr_value").val(),e.ajax({type:"POST",url:"execute.php?action=paste_clipboard",data:{path:t}}).done(function(e){""!=e?bootbox.alert(e):(jQuery("#clipboard").val("0"),y(!1),setTimeout(function(){window.location.href=jQuery("#refresh").attr("href")+"&"+(new Date).getTime()},300))})}})}function p(a,r){var t;t=a.hasClass("directory")?a.find(".rename-folder"):a.find(".rename-file");var n=t.attr("data-path");a.parent().hide(100),e.ajax({type:"POST",url:"ajax_calls.php?action=copy_cut",data:{path:n,sub_action:"cut"}}).done(function(t){if(""!=t)bootbox.alert(t);else{var n;n="undefined"!=typeof r?r.hasClass("back-directory")?r.find(".path").val():r.find(".rename-folder").attr("data-path"):jQuery("#sub_folder").val()+jQuery("#fldr_value").val(),e.ajax({type:"POST",url:"execute.php?action=paste_clipboard",data:{path:n}}).done(function(e){""!=e?(bootbox.alert(e),a.parent().show(100)):(jQuery("#clipboard").val("0"),y(!1),a.parent().remove())})}}).error(function(){a.parent().show(100)})}function y(e){1==e?jQuery(".paste-here-btn, .clear-clipboard-btn").removeClass("disabled"):jQuery(".paste-here-btn, .clear-clipboard-btn").addClass("disabled")}function v(e){var r=jQuery(".breadcrumb").width()+e,t=jQuery("#view"),n=jQuery("#help");if(jQuery(".uploader").css("width",r),t.val()>0){if(1==t.val())jQuery("ul.grid li, ul.grid figure").css("width","100%");else{var i=Math.floor(r/380);0==i&&(i=1,jQuery("h4").css("font-size",12)),r=Math.floor(r/i-3),jQuery("ul.grid li, ul.grid figure").css("width",r)}n.hide()}else a.touch&&n.show()}function m(){var e=jQuery(this);0==jQuery("#view").val()&&(1==e.attr("toggle")?(e.attr("toggle",0),e.animate({top:"0px"},{queue:!1,duration:300})):(e.attr("toggle",1),e.animate({top:"-30px"},{queue:!1,duration:300})))}function j(e){var a=new RegExp("(?:[?&]|&)"+e+"=([^&]+)","i"),r=window.location.search.match(a);return r&&r.length>1?r[1]:null}function Q(){1==jQuery("#popup").val()?window.close():("function"==typeof parent.jQuery(".modal").modal&&parent.jQuery(".modal").modal("hide"),"undefined"!=typeof parent.jQuery&&parent.jQuery?"function"==typeof parent.jQuery.fancybox&&parent.jQuery.fancybox.close():"function"==typeof parent.$.fancybox&&parent.$.fancybox.close())}function Q(){1==jQuery("#popup").val()?window.close():("function"==typeof parent.jQuery(".modal:has(iframe[src*=filemanager])").modal&&parent.jQuery(".modal:has(iframe[src*=filemanager])").modal("hide"),"undefined"!=typeof parent.jQuery&&parent.jQuery?"function"==typeof parent.jQuery.fancybox&&parent.jQuery.fancybox.close():"function"==typeof parent.$.fancybox&&parent.$.fancybox.close())}function h(e){for(var e,a=[/[\300-\306]/g,/[\340-\346]/g,/[\310-\313]/g,/[\350-\353]/g,/[\314-\317]/g,/[\354-\357]/g,/[\322-\330]/g,/[\362-\370]/g,/[\331-\334]/g,/[\371-\374]/g,/[\321]/g,/[\361]/g,/[\307]/g,/[\347]/g],r=["A","a","E","e","I","i","O","o","U","u","N","n","C","c"],t=0;t]+(>|$)/g,""),e.trim(a)):null}function g(a,r,t,n,i){null!==t&&(t=_(t),e.ajax({type:"POST",url:"execute.php?action="+a,data:{path:r,name:t.replace("/","")}}).done(function(e){return""!=e?(bootbox.alert(e),!1):(""!=i&&window[i](n,t),!0)}))}function b(a,r){var t=jQuery("li.dir","ul.grid").filter(":visible"),n=jQuery("li.file","ul.grid").filter(":visible"),i=[],l=[],o=[],u=[];t.each(function(){var a=jQuery(this),t=a.find(r).val();if(e.isNumeric(t))for(t=parseFloat(t);"undefined"!=typeof i[t]&&i[t];)t=parseFloat(parseFloat(t)+parseFloat(.001));else t=t+"a"+a.find("h4 a").attr("data-file");i[t]=a.html(),l.push(t)}),n.each(function(){var a=jQuery(this),t=a.find(r).val();if(e.isNumeric(t))for(t=parseFloat(t);"undefined"!=typeof o[t]&&o[t];)t=parseFloat(parseFloat(t)+parseFloat(.001));else t=t+"a"+a.find("h4 a").attr("data-file");o[t]=a.html(),u.push(t)}),e.isNumeric(l[0])?l.sort(function(e,a){return parseFloat(e)-parseFloat(a)}):l.sort(),e.isNumeric(u[0])?u.sort(function(e,a){return parseFloat(e)-parseFloat(a)}):u.sort(),a&&(l.reverse(),u.reverse()),t.each(function(e){var a=jQuery(this);a.html(i[l[e]])}),n.each(function(e){var a=jQuery(this);a.html(o[u[e]])})}function w(e,a){return featherEditor.launch({image:e,url:a}),!1}function x(){jQuery(".lazy-loaded").lazyload()}var k="9.11.3",C=!0,T=0,I=function(){var e=0;return function(a,r){clearTimeout(e),e=setTimeout(a,r)}}(),S=function(e){if(1==jQuery("#ftp").val())var a=jQuery("#ftp_base_url").val()+jQuery("#upload_dir").val()+jQuery("#fldr_value").val();else var a=jQuery("#base_url").val()+jQuery("#cur_dir").val();var r=e.find("a.link").attr("data-file");return""!=r&&null!=r&&(a+=r),r=e.find("h4 a.folder-link").attr("data-file"),""!=r&&null!=r&&(a+=r),a},U={contextActions:{copy_url:function(e){var a=S(e);bootbox.alert('URL:
    '),jQuery("#copy-button"+T).html(' '+jQuery("#lang_copy").val());var r=new ZeroClipboard(jQuery("#copy-button"+T));r.on("ready",function(e){r.on("wrongFlash noFlash",function(){ZeroClipboard.destroy()}),r.on("aftercopy",function(e){jQuery("#copy-button"+T).html(' '+jQuery("#ok").val()),jQuery("#copy-button"+T).attr("class","btn disabled"),T++}),r.on("error",function(e){})})},unzip:function(a){var r=jQuery("#sub_folder").val()+jQuery("#fldr_value").val()+a.find("a.link").attr("data-file");show_animation(),e.ajax({type:"POST",url:"ajax_calls.php?action=extract",data:{path:r}}).done(function(e){hide_animation(),""!=e?bootbox.alert(e):window.location.href=jQuery("#refresh").attr("href")+"&"+(new Date).getTime()})},edit_img:function(e){var a=e.attr("data-name");if(1==jQuery("#ftp").val())var r=jQuery("#ftp_base_url").val()+jQuery("#upload_dir").val()+jQuery("#fldr_value").val()+a;else var r=jQuery("#base_url").val()+jQuery("#cur_dir").val()+a;var t=jQuery("#aviary_img");t.attr("data-name",a),show_animation(),t.attr("src",r).load(w(t.attr("id"),r))},duplicate:function(e){var a=e.find("h4").text().trim();bootbox.prompt(jQuery("#lang_duplicate").val(),jQuery("#cancel").val(),jQuery("#ok").val(),function(r){if(null!==r&&(r=_(r),r!=a)){var t=e.find(".rename-file");g("duplicate_file",t.attr("data-path"),r,t,"apply_file_duplicate")}},a)},select:function(e){var a,r=S(e),t=jQuery("#field_id").val(),n=jQuery("#return_relative_url").val();if(1==n&&(r=r.replace(jQuery("#base_url").val(),""),r=r.replace(jQuery("#cur_dir").val(),"")),a=1==jQuery("#popup").val()?window.opener:window.parent,""!=t)if(1==jQuery("#crossdomain").val())a.postMessage({sender:"responsivefilemanager",url:r,field_id:t},"*");else{var i=jQuery("#"+t,a.document);i.val(r).trigger("change"),"function"==typeof a.responsive_filemanager_callback&&a.responsive_filemanager_callback(t),Q()}else apply_any(r)},copy:function(e){d(e,"copy")},cut:function(e){d(e,"cut")},paste:function(){f()},chmod:function(e){o(e)},edit_text_file:function(e){i(e)}},makeContextMenu:function(){var a=this;e.contextMenu({selector:"figure:not(.back-directory), .list-view2 figure:not(.back-directory)",autoHide:!0,build:function(e){e.addClass("selected");var t={callback:function(r,t){a.contextActions[r](e)},items:{}};return(e.find(".img-precontainer-mini .filetype").hasClass("png")||e.find(".img-precontainer-mini .filetype").hasClass("jpg")||e.find(".img-precontainer-mini .filetype").hasClass("jpeg"))&&r&&(t.items.edit_img={name:jQuery("#lang_edit_image").val(),icon:"edit_img",disabled:!1}),e.hasClass("directory")&&0!=jQuery("#type_param").val()&&(t.items.select={name:jQuery("#lang_select").val(),icon:"",disabled:!1}),t.items.copy_url={name:jQuery("#lang_show_url").val(),icon:"url",disabled:!1},(e.find(".img-precontainer-mini .filetype").hasClass("zip")||e.find(".img-precontainer-mini .filetype").hasClass("tar")||e.find(".img-precontainer-mini .filetype").hasClass("gz"))&&(t.items.unzip={name:jQuery("#lang_extract").val(),icon:"extract",disabled:!1}),e.find(".img-precontainer-mini .filetype").hasClass("edit-text-file-allowed")&&(t.items.edit_text_file={name:jQuery("#lang_edit_file").val(),icon:"edit",disabled:!1}),e.hasClass("directory")||1!=jQuery("#duplicate").val()||(t.items.duplicate={name:jQuery("#lang_duplicate").val(),icon:"duplicate",disabled:!1}),e.hasClass("directory")||1!=jQuery("#copy_cut_files_allowed").val()?e.hasClass("directory")&&1==jQuery("#copy_cut_dirs_allowed").val()&&(t.items.copy={name:jQuery("#lang_copy").val(),icon:"copy",disabled:!1},t.items.cut={name:jQuery("#lang_cut").val(),icon:"cut",disabled:!1}):(t.items.copy={name:jQuery("#lang_copy").val(),icon:"copy",disabled:!1},t.items.cut={name:jQuery("#lang_cut").val(),icon:"cut",disabled:!1}),0==jQuery("#clipboard").val()||e.hasClass("directory")||(t.items.paste={name:jQuery("#lang_paste_here").val(),icon:"clipboard-apply",disabled:!1}),e.hasClass("directory")||1!=jQuery("#chmod_files_allowed").val()?e.hasClass("directory")&&1==jQuery("#chmod_dirs_allowed").val()&&(t.items.chmod={name:jQuery("#lang_file_permission").val(),icon:"key",disabled:!1}):t.items.chmod={name:jQuery("#lang_file_permission").val(),icon:"key",disabled:!1},t.items.sep="----",t.items.info={name:""+jQuery("#lang_file_info").val()+"",disabled:!0},t.items.name={name:e.attr("data-name"),icon:"label",disabled:!0},"img"==e.attr("data-type")&&(t.items.dimension={name:e.find(".img-dimension").html(),icon:"dimension",disabled:!0}),"true"!==jQuery("#show_folder_size").val()&&"true"!==jQuery("#show_folder_size").val()||(e.hasClass("directory")?t.items.size={name:e.find(".file-size").html()+" - "+e.find(".nfiles").val()+" "+jQuery("#lang_files").val()+" - "+e.find(".nfolders").val()+" "+jQuery("#lang_folders").val(),icon:"size",disabled:!0}:t.items.size={name:e.find(".file-size").html(),icon:"size",disabled:!0}),t.items.date={name:e.find(".file-date").html(),icon:"date",disabled:!0},t},events:{hide:function(){jQuery("figure").removeClass("selected")}}}),jQuery(document).on("contextmenu",function(e){if(!jQuery(e.target).is("figure"))return!1})},bindGridEvents:function(){function a(e){window[e.attr("data-function")](e.attr("data-file"),jQuery("#field_id").val())}var r=jQuery("ul.grid");r.on("click",".modalAV",function(a){var r=jQuery(this);a.preventDefault();var t=jQuery("#previewAV"),n=jQuery(".body-preview");t.removeData("modal"),t.modal({backdrop:"static",keyboard:!1}),r.hasClass("audio")?n.css("height","80px"):n.css("height","345px"),e.ajax({url:r.attr("data-url"),success:function(e){n.html(e)}})}),r.on("click",".file-preview-btn",function(a){var r=jQuery(this);a.preventDefault(),e.ajax({url:r.attr("data-url"),success:function(e){bootbox.modal(e," "+r.parent().parent().parent().find(".name").val())}})}),r.on("click",".preview",function(){var e=jQuery(this);return 0==e.hasClass("disabled")&&jQuery("#full-img").attr("src",decodeURIComponent(e.attr("data-url"))),!0}),r.on("click",".rename-file",function(){var a=jQuery(this),r=a.parent().parent().parent(),t=r.find("h4"),n=e.trim(t.text());bootbox.prompt(jQuery("#rename").val(),jQuery("#cancel").val(),jQuery("#ok").val(),function(e){null!==e&&(e=_(e),e!=n&&g("rename_file",a.attr("data-path"),e,r,"apply_file_rename"))},n)}),r.on("click",".rename-folder",function(){var a=jQuery(this),r=a.parent().parent().parent(),t=r.find("h4"),n=e.trim(t.text());bootbox.prompt(jQuery("#rename").val(),jQuery("#cancel").val(),jQuery("#ok").val(),function(e){null!==e&&(e=_(e).replace(".",""),e!=n&&g("rename_folder",a.attr("data-path"),e,r,"apply_folder_rename"))},n)}),r.on("click",".delete-file",function(){var e=jQuery(this);bootbox.confirm(e.attr("data-confirm"),jQuery("#cancel").val(),jQuery("#ok").val(),function(a){if(1==a){g("delete_file",e.attr("data-path"),"","","");var r=jQuery("#files_number");r.text(parseInt(r.text())-1),e.parent().parent().parent().parent().remove()}})}),r.on("click",".delete-folder",function(){var e=jQuery(this);bootbox.confirm(e.attr("data-confirm"),jQuery("#cancel").val(),jQuery("#ok").val(),function(a){if(1==a){g("delete_folder",e.attr("data-path"),"","","");var r=jQuery("#folders_number");r.text(parseInt(r.text())-1),e.parent().parent().parent().remove()}})}),jQuery("ul.grid").on("click",".link",function(){a(jQuery(this))}),jQuery("ul.grid").on("click","div.box",function(e){var r=jQuery(this).find(".link");if(0!==r.length)a(r);else{var t=jQuery(this).find(".folder-link");0!==t.length&&(document.location=jQuery(t).prop("href"))}})},makeFilters:function(a){jQuery("#filter-input").on("keyup",function(){jQuery(".filters label").removeClass("btn-inverse"),jQuery(".filters label").find("i").removeClass("icon-white"),jQuery("#ff-item-type-all").addClass("btn-inverse"),jQuery("#ff-item-type-all").find("i").addClass("icon-white");var r=_(jQuery(this).val()).toLowerCase();jQuery(this).val(r),a&&I(function(){jQuery("li","ul.grid ").each(function(){var e=jQuery(this);""!=r&&e.attr("data-name").toLowerCase().indexOf(r)==-1?e.hide(100):e.show(100)}),e.ajax({url:"ajax_calls.php?action=filter&type="+r}).done(function(e){""!=e&&bootbox.alert(e)}),I(function(){var e=0!=jQuery("#descending").val();b(e,"."+jQuery("#sort_by").val()),x()},500)},300)}).keypress(function(e){13==e.which&&jQuery("#filter").trigger("click")}),jQuery("#filter").on("click",function(){var e=_(jQuery("#filter-input").val());window.location.href=jQuery("#current_url").val()+"&filter="+e})},makeUploader:function(){jQuery("#uploader-btn").on("click",function(){var e=jQuery("#sub_folder").val()+jQuery("#fldr_value").val()+"/";e=e.substring(0,e.length-1),jQuery("#iframe-container").html(jQuery(""}else"application/x-shockwave-flash"==i.source1mime?(o+='',i.poster&&(o+=''),o+=""):-1!=i.source1mime.indexOf("audio")?e.settings.audio_template_callback?o=e.settings.audio_template_callback(i):o+='":"script"==i.type?o+='':o=e.settings.video_template_callback?e.settings.video_template_callback(i):'"}return o}function s(e){var t={};return new tinymce.html.SaxParser({validate:!1,allow_conditional_comments:!0,special:"script,noscript",start:function(e,n){if(t.source1||"param"!=e||(t.source1=n.map.movie),("iframe"==e||"object"==e||"embed"==e||"video"==e||"audio"==e)&&(t.type||(t.type=e),t=tinymce.extend(n.map,t)),"script"==e){var i=r(n.map.src);if(!i)return;t={type:"script",source1:n.map.src,width:i.width,height:i.height}}"source"==e&&(t.source1?t.source2||(t.source2=n.map.src):t.source1=n.map.src),"img"!=e||t.poster||(t.poster=n.map.src)}}).parse(e),t.source1=t.source1||t.src||t.data,t.source2=t.source2||"",t.poster=t.poster||"",t}function l(t){return t.getAttribute("data-mce-object")?s(e.serializer.serialize(t,{selection:!0})):{}}function c(t){if(e.settings.media_filter_html===!1)return t;var n,r=new tinymce.html.Writer;return new tinymce.html.SaxParser({validate:!1,allow_conditional_comments:!1,special:"script,noscript",comment:function(e){r.comment(e)},cdata:function(e){r.cdata(e)},text:function(e,t){r.text(e,t)},start:function(t,i,o){if(n=!0,"script"!=t&&"noscript"!=t){for(var a=0;a=a&&(r(s,{src:t["source"+a],type:t["source"+a+"mime"]}),!t["source"+a]))return;break;case"img":if(!t.poster)return;i=!0}o.start(e,s,l)},end:function(e){if("video"==e&&n)for(var s=1;2>=s;s++)if(t["source"+s]){var l=[];l.map={},s>a&&(r(l,{src:t["source"+s],type:t["source"+s+"mime"]}),o.start("source",l,!0))}if(t.poster&&"object"==e&&n&&!i){var c=[];c.map={},r(c,{src:t.poster,width:t.width,height:t.height}),o.start("img",c,!0)}o.end(e)}},new tinymce.html.Schema({})).parse(e),o.getContent()}function d(t,n){var r,i,o,a,s;for(o=t.attributes,a=o.length;a--;)r=o[a].name,i=o[a].value,"width"!==r&&"height"!==r&&"style"!==r&&(("data"==r||"src"==r)&&(i=e.convertURL(i,r)),n.attr("data-mce-p-"+r,i));s=t.firstChild&&t.firstChild.value,s&&(n.attr("data-mce-html",escape(s)),n.firstChild=null)}function f(e){var t,n=e.name;return t=new tinymce.html.Node("img",1),t.shortEnded=!0,d(e,t),t.attr({width:e.attr("width")||"300",height:e.attr("height")||("audio"==n?"30":"150"),style:e.attr("style"),src:tinymce.Env.transparentSrc,"data-mce-object":n,"class":"mce-object mce-object-"+n}),t}function p(e){var t,n,r,i=e.name;return t=new tinymce.html.Node("span",1),t.attr({contentEditable:"false",style:e.attr("style"),"data-mce-object":i,"class":"mce-preview-object mce-object-"+i}),d(e,t),n=new tinymce.html.Node(i,1),n.attr({src:e.attr("src"),allowfullscreen:e.attr("allowfullscreen"),width:e.attr("width")||"300",height:e.attr("height")||("audio"==i?"30":"150"),frameborder:"0"}),r=new tinymce.html.Node("span",1),r.attr("class","mce-shim"),t.append(n),t.append(r),t}var m=[{regex:/youtu\.be\/([\w\-.]+)/,type:"iframe",w:560,h:314,url:"//www.youtube.com/embed/$1",allowFullscreen:!0},{regex:/youtube\.com(.+)v=([^&]+)/,type:"iframe",w:560,h:314,url:"//www.youtube.com/embed/$2",allowFullscreen:!0},{regex:/youtube.com\/embed\/([a-z0-9\-]+)/i,type:"iframe",w:560,h:314,url:"//www.youtube.com/embed/$1",allowFullscreen:!0},{regex:/vimeo\.com\/([0-9]+)/,type:"iframe",w:425,h:350,url:"//player.vimeo.com/video/$1?title=0&byline=0&portrait=0&color=8dc7dc",allowfullscreen:!0},{regex:/vimeo\.com\/(.*)\/([0-9]+)/,type:"iframe",w:425,h:350,url:"//player.vimeo.com/video/$2?title=0&byline=0",allowfullscreen:!0},{regex:/maps\.google\.([a-z]{2,3})\/maps\/(.+)msid=(.+)/,type:"iframe",w:425,h:350,url:'//maps.google.com/maps/ms?msid=$2&output=embed"',allowFullscreen:!1}],h=tinymce.Env.ie&&tinymce.Env.ie<=8?"onChange":"onInput";e.on("ResolveName",function(e){var t;1==e.target.nodeType&&(t=e.target.getAttribute("data-mce-object"))&&(e.name=t)}),e.on("preInit",function(){var t=e.schema.getSpecialElements();tinymce.each("video audio iframe object".split(" "),function(e){t[e]=new RegExp("]*>","gi")});var n=e.schema.getBoolAttrs();tinymce.each("webkitallowfullscreen mozallowfullscreen allowfullscreen".split(" "),function(e){n[e]={}}),e.parser.addNodeFilter("iframe,video,audio,object,embed,script",function(t){for(var n,i,o,a=t.length;a--;)n=t[a],n.parent&&(n.parent.attr("data-mce-object")||("script"!=n.name||(o=r(n.attr("src"))))&&(o&&(o.width&&n.attr("width",o.width.toString()),o.height&&n.attr("height",o.height.toString())),i="iframe"==n.name&&e.settings.media_live_embeds!==!1&&tinymce.Env.ceFalse?p(n):f(n),n.replace(i)))}),e.serializer.addAttributeFilter("data-mce-object",function(e,t){for(var n,r,i,o,a,s,l,u,d=e.length;d--;)if(n=e[d],n.parent){for(l=n.attr(t),r=new tinymce.html.Node(l,1),"audio"!=l&&"script"!=l&&(u=n.attr("class"),u&&-1!==u.indexOf("mce-preview-object")?r.attr({width:n.firstChild.attr("width"),height:n.firstChild.attr("height")}):r.attr({width:n.attr("width"),height:n.attr("height")})),r.attr({style:n.attr("style")}),o=n.attributes,i=o.length;i--;){var f=o[i].name;0===f.indexOf("data-mce-p-")&&r.attr(f.substr(11),o[i].value)}"script"==l&&r.attr("type","text/javascript"),a=n.attr("data-mce-html"),a&&(s=new tinymce.html.Node("#text",3),s.raw=!0,s.value=c(unescape(a)),r.append(s)),n.replace(r)}})}),e.on("ObjectSelected",function(e){var t=e.target.getAttribute("data-mce-object");("audio"==t||"script"==t)&&e.preventDefault()}),e.on("objectResized",function(e){var t,n=e.target;n.getAttribute("data-mce-object")&&(t=n.getAttribute("data-mce-html"),t&&(t=unescape(t),n.setAttribute("data-mce-html",escape(u(t,{width:e.width,height:e.height})))))}),e.addButton("media",{tooltip:"Insert/edit video",onclick:i,stateSelector:["img[data-mce-object]","span[data-mce-object]"]}),e.addMenuItem("media",{icon:"media",text:"Insert/edit video",onclick:i,context:"insert",prependToContext:!0}),e.addCommand("mceMedia",i),this.showDialog=i}); \ No newline at end of file diff --git a/local/modules/Tinymce/Resources/js/tinymce/plugins/nonbreaking/plugin.min.js b/local/modules/Tinymce/Resources/js/tinymce/plugins/nonbreaking/plugin.min.js new file mode 100644 index 00000000..1e4f3343 --- /dev/null +++ b/local/modules/Tinymce/Resources/js/tinymce/plugins/nonbreaking/plugin.min.js @@ -0,0 +1 @@ +tinymce.PluginManager.add("nonbreaking",function(e){var t=e.getParam("nonbreaking_force_tab");if(e.addCommand("mceNonBreaking",function(){e.insertContent(e.plugins.visualchars&&e.plugins.visualchars.state?' ':" "),e.dom.setAttrib(e.dom.select("span.mce-nbsp"),"data-mce-bogus","1")}),e.addButton("nonbreaking",{title:"Nonbreaking space",cmd:"mceNonBreaking"}),e.addMenuItem("nonbreaking",{text:"Nonbreaking space",cmd:"mceNonBreaking",context:"insert"}),t){var n=+t>1?+t:3;e.on("keydown",function(t){if(9==t.keyCode){if(t.shiftKey)return;t.preventDefault();for(var r=0;n>r;r++)e.execCommand("mceNonBreaking")}})}}); \ No newline at end of file diff --git a/local/modules/Tinymce/Resources/js/tinymce/plugins/noneditable/plugin.min.js b/local/modules/Tinymce/Resources/js/tinymce/plugins/noneditable/plugin.min.js new file mode 100644 index 00000000..b3d2add6 --- /dev/null +++ b/local/modules/Tinymce/Resources/js/tinymce/plugins/noneditable/plugin.min.js @@ -0,0 +1 @@ +tinymce.PluginManager.add("noneditable",function(e){function t(e){return function(t){return-1!==(" "+t.attr("class")+" ").indexOf(e)}}function n(t){function n(t){var n=arguments,r=n[n.length-2];return r>0&&'"'==a.charAt(r-1)?t:''+e.dom.encode("string"==typeof n[1]?n[1]:n[0])+""}var r=o.length,a=t.content,s=tinymce.trim(i);if("raw"!=t.format){for(;r--;)a=a.replace(o[r],n);t.content=a}}var r,i,o,a="contenteditable";r=" "+tinymce.trim(e.getParam("noneditable_editable_class","mceEditable"))+" ",i=" "+tinymce.trim(e.getParam("noneditable_noneditable_class","mceNonEditable"))+" ";var s=t(r),l=t(i);o=e.getParam("noneditable_regexp"),o&&!o.length&&(o=[o]),e.on("PreInit",function(){o&&e.on("BeforeSetContent",n),e.parser.addAttributeFilter("class",function(e){for(var t,n=e.length;n--;)t=e[n],s(t)?t.attr(a,"true"):l(t)&&t.attr(a,"false")}),e.serializer.addAttributeFilter(a,function(e){for(var t,n=e.length;n--;)t=e[n],(s(t)||l(t))&&(o&&t.attr("data-mce-content")?(t.name="#text",t.type=3,t.raw=!0,t.value=t.attr("data-mce-content")):t.attr(a,null))})})}); \ No newline at end of file diff --git a/local/modules/Tinymce/Resources/js/tinymce/plugins/pagebreak/plugin.min.js b/local/modules/Tinymce/Resources/js/tinymce/plugins/pagebreak/plugin.min.js new file mode 100644 index 00000000..b76e5845 --- /dev/null +++ b/local/modules/Tinymce/Resources/js/tinymce/plugins/pagebreak/plugin.min.js @@ -0,0 +1 @@ +tinymce.PluginManager.add("pagebreak",function(e){var t="mce-pagebreak",n=e.getParam("pagebreak_separator",""),r=new RegExp(n.replace(/[\?\.\*\[\]\(\)\{\}\+\^\$\:]/g,function(e){return"\\"+e}),"gi"),i='';e.addCommand("mcePageBreak",function(){e.settings.pagebreak_split_block?e.insertContent("

    "+i+"

    "):e.insertContent(i)}),e.addButton("pagebreak",{title:"Page break",cmd:"mcePageBreak"}),e.addMenuItem("pagebreak",{text:"Page break",icon:"pagebreak",cmd:"mcePageBreak",context:"insert"}),e.on("ResolveName",function(n){"IMG"==n.target.nodeName&&e.dom.hasClass(n.target,t)&&(n.name="pagebreak")}),e.on("click",function(n){n=n.target,"IMG"===n.nodeName&&e.dom.hasClass(n,t)&&e.selection.select(n)}),e.on("BeforeSetContent",function(e){e.content=e.content.replace(r,i)}),e.on("PreInit",function(){e.serializer.addNodeFilter("img",function(t){for(var r,i,o=t.length;o--;)if(r=t[o],i=r.attr("class"),i&&-1!==i.indexOf("mce-pagebreak")){var a=r.parent;if(e.schema.getBlockElements()[a.name]&&e.settings.pagebreak_split_block){a.type=3,a.value=n,a.raw=!0,r.remove();continue}r.type=3,r.value=n,r.raw=!0}})})}); \ No newline at end of file diff --git a/local/modules/Tinymce/Resources/js/tinymce/plugins/paste/plugin.min.js b/local/modules/Tinymce/Resources/js/tinymce/plugins/paste/plugin.min.js new file mode 100644 index 00000000..a81b7921 --- /dev/null +++ b/local/modules/Tinymce/Resources/js/tinymce/plugins/paste/plugin.min.js @@ -0,0 +1 @@ +!function(e,t){"use strict";function n(e,t){for(var n,r=[],o=0;o/g]),o(s.parse(i)),l}function o(e){function t(e,t,n){return t||n?"\xa0":" "}return e=r(e,[/^[\s\S]*]*>\s*|\s*<\/body[^>]*>[\s\S]*$/g,/|/g,[/( ?)\u00a0<\/span>( ?)/g,t],/
    /g,/
    $/i])}return{filter:r,innerText:i,trimHtml:o}}),r("tinymce/pasteplugin/Clipboard",["tinymce/Env","tinymce/dom/RangeUtils","tinymce/util/VK","tinymce/pasteplugin/Utils","tinymce/util/Delay"],function(e,t,n,r,i){return function(o){function a(e){var t,n=o.dom;if(t=o.fire("BeforePastePreProcess",{content:e}),t=o.fire("PastePreProcess",t),e=t.content,!t.isDefaultPrevented()){if(o.hasEventListeners("PastePostProcess")&&!t.isDefaultPrevented()){var r=n.add(o.getBody(),"div",{style:"display:none"},e);t=o.fire("PastePostProcess",{node:r}),n.remove(r),e=t.node.innerHTML}t.isDefaultPrevented()||o.insertContent(e,{merge:o.settings.paste_merge_formats!==!1,data:{paste:!0}})}}function s(e){e=o.dom.encode(e).replace(/\r\n/g,"\n");var t,n=o.dom.getParent(o.selection.getStart(),o.dom.isBlock),i=o.settings.forced_root_block;i&&(t=o.dom.createHTML(i,o.settings.forced_root_block_attrs),t=t.substr(0,t.length-3)+">"),n&&/^(PRE|DIV)$/.test(n.nodeName)||!i?e=r.filter(e,[[/\n/g,"
    "]]):(e=r.filter(e,[[/\n\n/g,"

    "+t],[/^(.*<\/p>)(

    )$/,t+"$1"],[/\n/g,"
    "]]),-1!=e.indexOf("

    ")&&(e=t+e)),a(e)}function l(){function t(e){var t,n,i,o=e.startContainer;if(t=e.getClientRects(),t.length)return t[0];if(e.collapsed&&1==o.nodeType){for(i=o.childNodes[w.startOffset];i&&3==i.nodeType&&!i.data.length;)i=i.nextSibling;if(i)return"BR"==i.tagName&&(n=r.doc.createTextNode("\ufeff"),i.parentNode.insertBefore(n,i),e=r.createRng(),e.setStartBefore(n),e.setEndAfter(n),t=e.getClientRects(),r.remove(n)),t.length?t[0]:void 0}}var n,r=o.dom,i=o.getBody(),a=o.dom.getViewPort(o.getWin()),s=a.y,l=20;if(w=o.selection.getRng(),o.inline&&(n=o.selection.getScrollContainer(),n&&n.scrollTop>0&&(s=n.scrollTop)),w.getClientRects){var c=t(w);if(c)l=s+(c.top-r.getPos(i).y);else{l=s;var u=w.startContainer;u&&(3==u.nodeType&&u.parentNode!=i&&(u=u.parentNode),1==u.nodeType&&(l=r.getPos(u,n||i).y))}}C=r.add(o.getBody(),"div",{id:"mcepastebin",contentEditable:!0,"data-mce-bogus":"all",style:"position: absolute; top: "+l+"px;width: 10px; height: 10px; overflow: hidden; opacity: 0"},S),(e.ie||e.gecko)&&r.setStyle(C,"left","rtl"==r.getStyle(i,"direction",!0)?65535:-65535),r.bind(C,"beforedeactivate focusin focusout",function(e){e.stopPropagation()}),C.focus(),o.selection.select(C,!0)}function c(){if(C){for(var e;e=o.dom.get("mcepastebin");)o.dom.remove(e),o.dom.unbind(e);w&&o.selection.setRng(w)}C=w=null}function u(){var e,t,n,r,i="";for(e=o.dom.select("div[id=mcepastebin]"),t=0;t>8);return decodeURIComponent(escape(n))}function f(e){var t,n,r;return n="",t=e.indexOf(n),-1!==t&&(e=e.substr(t+n.length)),r="",t=e.indexOf(r),-1!==t&&(e=e.substr(0,t)),e}function p(e){var t={};if(e){if(e.getData){var n=e.getData("Text");n&&n.length>0&&-1==n.indexOf(T)&&(t["text/plain"]=n)}if(e.types)for(var r=0;r')}var i,s,l,c=!1;if(n)for(i=0;i0}function b(e){return n.metaKeyPressed(e)&&86==e.keyCode||e.shiftKey&&45==e.keyCode}function x(){function t(e,t,n){var i;return y(e,"text/html")?i=e["text/html"]:(i=u(),i==S&&(n=!0)),i=r.trimHtml(i),C&&C.firstChild&&"mcepastebin"===C.firstChild.id&&(n=!0),c(),i.length||(n=!0),n&&(i=y(e,"text/plain")&&-1==i.indexOf("

    ")?e["text/plain"]:r.innerText(i)),i==S?void(t||o.windowManager.alert("Please use Ctrl+V/Cmd+V keyboard shortcuts to paste contents.")):void(n?s(i):a(i))}o.on("keydown",function(t){function n(e){b(e)&&!e.isDefaultPrevented()&&c()}if(b(t)&&!t.isDefaultPrevented()){if(N=t.shiftKey&&86==t.keyCode,N&&e.webkit&&-1!=navigator.userAgent.indexOf("Version/"))return;if(t.stopImmediatePropagation(),E=(new Date).getTime(),e.ie&&N)return t.preventDefault(),void o.fire("paste",{ieFake:!0});c(),l(),o.once("keyup",n),o.once("paste",function(){o.off("keyup",n)})}}),o.on("paste",function(n){var r=(new Date).getTime(),a=m(n),s=(new Date).getTime()-r,d=(new Date).getTime()-E-s<1e3,f="text"==_.pasteFormat||N;return N=!1,n.isDefaultPrevented()||g(n)?void c():h(n)?void c():(d||n.preventDefault(),!e.ie||d&&!n.ieFake||(l(),o.dom.bind(C,"paste",function(e){e.stopPropagation()}),o.getDoc().execCommand("Paste",!1,null),a["text/html"]=u()),void(y(a,"text/html")?(n.preventDefault(),t(a,d,f)):i.setEditorTimeout(o,function(){t(a,d,f)},0)))}),o.on("dragstart dragend",function(e){k="dragstart"==e.type}),o.on("drop",function(e){var t=v(e);if(!e.isDefaultPrevented()&&!k&&!h(e,t)&&t&&o.settings.paste_filter_drop!==!1){var n=p(e.dataTransfer),i=n["mce-internal"]||n["text/html"]||n["text/plain"];i&&(e.preventDefault(),o.undoManager.transact(function(){n["mce-internal"]&&o.execCommand("Delete"),o.selection.setRng(t),i=r.trimHtml(i),n["text/html"]?a(i):s(i)}))}}),o.on("dragover dragend",function(e){o.settings.paste_data_images&&e.preventDefault()})}var C,w,N,_=this,E=0,k=!1,S="%MCEPASTEBIN%",T="data:text/mce-internal,";_.pasteHtml=a,_.pasteText=s,o.on("preInit",function(){x(),o.parser.addNodeFilter("img",function(t,n,r){function i(e){return e.data&&e.data.paste===!0}function a(t){t.attr("data-mce-object")||u===e.transparentSrc||t.remove()}function s(e){return 0===e.indexOf("webkit-fake-url")}function l(e){return 0===e.indexOf("data:")}if(!o.settings.paste_data_images&&i(r))for(var c=t.length;c--;){var u=t[c].attributes.map.src;u&&(s(u)?a(t[c]):!o.settings.allow_html_data_urls&&l(u)&&a(t[c]))}})})}}),r("tinymce/pasteplugin/WordFilter",["tinymce/util/Tools","tinymce/html/DomParser","tinymce/html/Schema","tinymce/html/Serializer","tinymce/html/Node","tinymce/pasteplugin/Utils"],function(e,t,n,r,i,o){function a(e){return/s?a&&(a=a.parent.parent):(c=a,a=null)),a&&a.name==t?a.append(e):(c=c||a,a=new i(t,1),o>1&&a.attr("start",""+o),e.wrap(a)),e.name="li",s>u&&c&&c.lastChild.append(a),u=s,r(e),n(e,/^\u00a0+/),n(e,/^\s*([\u2022\u00b7\u00a7\u25CF]|\w+\.)/),n(e,/^\u00a0+/)}for(var a,c,u=1,d=[],f=e.firstChild;"undefined"!=typeof f&&null!==f;)if(d.push(f),f=f.walk(),null!==f)for(;"undefined"!=typeof f&&f.parent!==e;)f=f.walk();for(var p=0;p]+id="?docs-internal-[^>]*>/gi,""),g=g.replace(/
    /gi,""),m=u.paste_retain_style_properties,m&&(h=e.makeMap(m.split(/[, ]/))),u.paste_enable_default_filters!==!1&&a(d.content)){d.wordContent=!0,g=o.filter(g,[//gi,/<(!|script[^>]*>.*?<\/script(?=[>\s])|\/?(\?xml(:\w+)?|img|meta|link|style|\w:\w+)(?=[\s\/>]))[^>]*>/gi,[/<(\/?)s>/gi,"<$1strike>"],[/ /gi,"\xa0"],[/([\s\u00a0]*)<\/span>/gi,function(e,t){return t.length>0?t.replace(/./," ").slice(Math.floor(t.length/2)).split("").join("\xa0"):""}]]);var v=u.paste_word_valid_elements;v||(v="-strong/b,-em/i,-u,-span,-p,-ol,-ul,-li,-h1,-h2,-h3,-h4,-h5,-h6,-p/div,-a[href|name],sub,sup,strike,br,del,table[width],tr,td[colspan|rowspan|width],th[colspan|rowspan|width],thead,tfoot,tbody");var y=new n({valid_elements:v,valid_children:"-li[p]"});e.each(y.elements,function(e){e.attributes["class"]||(e.attributes["class"]={},e.attributesOrder.push("class")),e.attributes.style||(e.attributes.style={},e.attributesOrder.push("style"))});var b=new t({},y);b.addAttributeFilter("style",function(e){for(var t,n=e.length;n--;)t=e[n],t.attr("style",p(t,t.attr("style"))),"span"==t.name&&t.parent&&!t.attributes.length&&t.unwrap()}),b.addAttributeFilter("class",function(e){for(var t,n,r=e.length;r--;)t=e[r],n=t.attr("class"),/^(MsoCommentReference|MsoCommentText|msoDel)$/i.test(n)&&t.remove(),t.attr("class",null)}),b.addNodeFilter("del",function(e){for(var t=e.length;t--;)e[t].remove()}),b.addNodeFilter("a",function(e){for(var t,n,r,i=e.length;i--;)if(t=e[i],n=t.attr("href"),r=t.attr("name"),n&&-1!=n.indexOf("#_msocom_"))t.remove();else if(n&&0===n.indexOf("file://")&&(n=n.split("#")[1],n&&(n="#"+n)),n||r){if(r&&!/^_?(?:toc|edn|ftn)/i.test(r)){t.unwrap();continue}t.attr({href:n,name:r})}else t.unwrap()});var x=b.parse(g);u.paste_convert_word_fake_lists!==!1&&f(x),d.content=new r({validate:u.validate},y).serialize(x)}})}return c.isWordContent=a,c}),r("tinymce/pasteplugin/Quirks",["tinymce/Env","tinymce/util/Tools","tinymce/pasteplugin/WordFilter","tinymce/pasteplugin/Utils"],function(e,t,n,r){return function(i){function o(e){i.on("BeforePastePreProcess",function(t){t.content=e(t.content)})}function a(e){if(!n.isWordContent(e))return e;var o=[];t.each(i.schema.getBlockElements(),function(e,t){o.push(t)});var a=new RegExp("(?:
     [\\s\\r\\n]+|
    )*(<\\/?("+o.join("|")+")[^>]*>)(?:
     [\\s\\r\\n]+|
    )*","g");return e=r.filter(e,[[a,"$1"]]),e=r.filter(e,[[/

    /g,"

    "],[/
    /g," "],[/

    /g,"
    "]])}function s(e){if(n.isWordContent(e))return e;var t=i.settings.paste_webkit_styles;if(i.settings.paste_remove_styles_if_webkit===!1||"all"==t)return e;if(t&&(t=t.split(/[, ]/)),t){var r=i.dom,o=i.selection.getNode();e=e.replace(/(<[^>]+) style="([^"]*)"([^>]*>)/gi,function(e,n,i,a){var s=r.parseStyle(i,"span"),l={};if("none"===t)return n+a;for(var c=0;c]+) style="([^"]*)"([^>]*>)/gi,"$1$3");return e=e.replace(/(<[^>]+) data-mce-style="([^"]+)"([^>]*>)/gi,function(e,t,n,r){return t+' style="'+n+'"'+r})}e.webkit&&o(s),e.ie&&o(a)}}),r("tinymce/pasteplugin/Plugin",["tinymce/PluginManager","tinymce/pasteplugin/Clipboard","tinymce/pasteplugin/WordFilter","tinymce/pasteplugin/Quirks"],function(e,t,n,r){var i;e.add("paste",function(e){function o(){if("text"==a.pasteFormat)this.active(!1),a.pasteFormat="html";else if(a.pasteFormat="text",this.active(!0),!i){var t=e.translate("Paste is now in plain text mode. Contents will now be pasted as plain text until you toggle this option off.");e.notificationManager.open({text:t,type:"info"}),i=!0}}var a,s=this,l=e.settings;s.clipboard=a=new t(e),s.quirks=new r(e),s.wordFilter=new n(e),e.settings.paste_as_text&&(s.clipboard.pasteFormat="text"),l.paste_preprocess&&e.on("PastePreProcess",function(e){l.paste_preprocess.call(s,s,e)}),l.paste_postprocess&&e.on("PastePostProcess",function(e){l.paste_postprocess.call(s,s,e)}),e.addCommand("mceInsertClipboardContent",function(e,t){t.content&&s.clipboard.pasteHtml(t.content),t.text&&s.clipboard.pasteText(t.text)}),e.paste_block_drop&&e.on("dragend dragover draggesture dragdrop drop drag",function(e){e.preventDefault(),e.stopPropagation()}),e.settings.paste_data_images||e.on("drop",function(e){var t=e.dataTransfer;t&&t.files&&t.files.length>0&&e.preventDefault()}),e.addButton("pastetext",{icon:"pastetext",tooltip:"Paste as text",onclick:o,active:"text"==s.clipboard.pasteFormat}),e.addMenuItem("pastetext",{text:"Paste as text",selectable:!0,active:a.pasteFormat,onclick:o})})}),o(["tinymce/pasteplugin/Utils"])}(this); \ No newline at end of file diff --git a/local/modules/Tinymce/Resources/js/tinymce/plugins/preview/plugin.min.js b/local/modules/Tinymce/Resources/js/tinymce/plugins/preview/plugin.min.js new file mode 100644 index 00000000..7d5e0478 --- /dev/null +++ b/local/modules/Tinymce/Resources/js/tinymce/plugins/preview/plugin.min.js @@ -0,0 +1 @@ +tinymce.PluginManager.add("preview",function(e){var t=e.settings,n=!tinymce.Env.ie;e.addCommand("mcePreview",function(){e.windowManager.open({title:"Preview",width:parseInt(e.getParam("plugin_preview_width","650"),10),height:parseInt(e.getParam("plugin_preview_height","500"),10),html:'",buttons:{text:"Close",onclick:function(){this.parent().parent().close()}},onPostRender:function(){var r,i="";i+='',tinymce.each(e.contentCSS,function(t){i+=''});var o=t.body_id||"tinymce";-1!=o.indexOf("=")&&(o=e.getParam("body_id","","hash"),o=o[e.id]||o);var a=t.body_class||"";-1!=a.indexOf("=")&&(a=e.getParam("body_class","","hash"),a=a[e.id]||"");var s=e.settings.directionality?' dir="'+e.settings.directionality+'"':"";if(r=""+i+'"+e.getContent()+"",n)this.getEl("body").firstChild.src="data:text/html;charset=utf-8,"+encodeURIComponent(r);else{var l=this.getEl("body").firstChild.contentWindow.document;l.open(),l.write(r),l.close()}}})}),e.addButton("preview",{title:"Preview",cmd:"mcePreview"}),e.addMenuItem("preview",{text:"Preview",cmd:"mcePreview",context:"view"})}); \ No newline at end of file diff --git a/local/modules/Tinymce/Resources/js/tinymce/plugins/print/plugin.min.js b/local/modules/Tinymce/Resources/js/tinymce/plugins/print/plugin.min.js new file mode 100644 index 00000000..9f58535b --- /dev/null +++ b/local/modules/Tinymce/Resources/js/tinymce/plugins/print/plugin.min.js @@ -0,0 +1 @@ +tinymce.PluginManager.add("print",function(e){e.addCommand("mcePrint",function(){e.getWin().print()}),e.addButton("print",{title:"Print",cmd:"mcePrint"}),e.addShortcut("Meta+P","","mcePrint"),e.addMenuItem("print",{text:"Print",cmd:"mcePrint",icon:"print",shortcut:"Meta+P",context:"file"})}); \ No newline at end of file diff --git a/local/modules/Tinymce/Resources/js/tinymce/plugins/responsivefilemanager/editor_plugin.js b/local/modules/Tinymce/Resources/js/tinymce/plugins/responsivefilemanager/editor_plugin.js new file mode 100644 index 00000000..fd420092 --- /dev/null +++ b/local/modules/Tinymce/Resources/js/tinymce/plugins/responsivefilemanager/editor_plugin.js @@ -0,0 +1,126 @@ +(function() { + + tinymce.create('tinymce.plugins.ResponsiveFileManager', + { + + init : function(editor, url) + { + + // File manager callback + function openmanager() + { + editor.focus(true); + var title="RESPONSIVE FileManager"; + if (typeof editor.settings.filemanager_title !== "undefined" && editor.settings.filemanager_title) { + title=editor.settings.filemanager_title; + } + var akey="key"; + if (typeof editor.settings.filemanager_access_key !== "undefined" && editor.settings.filemanager_access_key) { + akey=editor.settings.filemanager_access_key; + } + var sort_by=""; + if (typeof editor.settings.filemanager_sort_by !== "undefined" && editor.settings.filemanager_sort_by) { + sort_by="&sort_by="+editor.settings.filemanager_sort_by; + } + var descending="false"; + if (typeof editor.settings.filemanager_descending !== "undefined" && editor.settings.filemanager_descending) { + descending=editor.settings.filemanager_descending; + } + var fldr=""; + if (typeof editor.settings.filemanager_subfolder !== "undefined" && editor.settings.filemanager_subfolder) { + fldr="&fldr="+editor.settings.filemanager_subfolder; + } + // Disabled because of bug + var type=2; + if (typeof editor.settings.filemanager_type !== "undefined" && editor.settings.filemanager_type) { + if ($.isNumeric(editor.settings.filemanager_type) === true && editor.settings.filemanager_type > 0 && editor.settings.filemanager_type <= 3) { + type=editor.settings.filemanager_type; + } + else if (editor.settings.filemanager_type == 'image'){ + type = 1; + } + else if (editor.settings.filemanager_type == 'media'){ + type = 3; + } + else { + type = 2; + } + } + + win = editor.windowManager.open({ + title: title, + file: editor.settings.external_filemanager_path+'dialog.php?type=4&descending='+descending+sort_by+fldr+'&lang='+editor.settings.language+'&akey='+akey, + width: 860, + height: 570, + inline: 1, + resizable: true, + maximizable: true + }); + } + + editor.settings.file_browser_callback = filemanager; + + function filemanager (id, value, type, win) { + // DEFAULT AS FILE + urltype=2; + if (type=='image') { urltype=1; } + if (type=='media') { urltype=3; } + var title="RESPONSIVE FileManager"; + if (typeof editor.settings.filemanager_title !== "undefined" && editor.settings.filemanager_title) { + title=editor.settings.filemanager_title; + } + var akey="key"; + if (typeof editor.settings.filemanager_access_key !== "undefined" && editor.settings.filemanager_access_key) { + akey=editor.settings.filemanager_access_key; + } + var sort_by=""; + if (typeof editor.settings.filemanager_sort_by !== "undefined" && editor.settings.filemanager_sort_by) { + sort_by="&sort_by="+editor.settings.filemanager_sort_by; + } + var descending="false"; + if (typeof editor.settings.filemanager_descending !== "undefined" && editor.settings.filemanager_descending) { + descending=editor.settings.filemanager_descending; + } + var fldr=""; + if (typeof editor.settings.filemanager_subfolder !== "undefined" && editor.settings.filemanager_subfolder) { + fldr="&fldr="+editor.settings.filemanager_subfolder; + } + + tinymce.activeEditor.windowManager.open({ + title: title, + file: editor.settings.external_filemanager_path+'dialog.php?type='+urltype+'&descending='+descending+sort_by+fldr+'&lang='+editor.settings.language+'&akey='+akey, + width: 860, + height: 570, + resizable: true, + maximizable: true, + inline: 1 + }, { + setUrl: function (url) { + var fieldElm = win.document.getElementById(id); + fieldElm.value = editor.convertURL(url); + if ("fireEvent" in fieldElm) { + fieldElm.fireEvent("onchange") + } else { + var evt = document.createEvent("HTMLEvents"); + evt.initEvent("change", false, true); + fieldElm.dispatchEvent(evt); + } + } + }); + }; + + // Register buttons + editor.addButton('responsivefilemanager', + { + title : 'Browse files', + image : url + '/img/insertfile.gif', + shortcut: 'Ctrl+E', + onclick: openmanager + }); + } + + }); + + // Register plugin + tinymce.PluginManager.add('responsivefilemanager', tinymce.plugins.ResponsiveFileManager); +})(); diff --git a/local/modules/Tinymce/Resources/js/tinymce/plugins/responsivefilemanager/img/insertfile.gif b/local/modules/Tinymce/Resources/js/tinymce/plugins/responsivefilemanager/img/insertfile.gif new file mode 100644 index 0000000000000000000000000000000000000000..93689cb34950fb518b02f808ba64cbc3a06df224 GIT binary patch literal 3325 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 0 && editor.settings.filemanager_type <= 3) { + type=editor.settings.filemanager_type; + } + else if (editor.settings.filemanager_type == 'image'){ + type = 1; + } + else if (editor.settings.filemanager_type == 'media'){ + type = 3; + } + else { + type = 2; + } + } + + win = editor.windowManager.open({ + title: title, + file: editor.settings.external_filemanager_path+'dialog.php?type=4&descending='+descending+sort_by+fldr+'&lang='+editor.settings.language+'&akey='+akey, + width: 860, + height: 570, + inline: 1, + resizable: true, + maximizable: true + }); + } + + editor.addButton('responsivefilemanager', { + icon: 'browse', + tooltip: 'Insert file', + shortcut: 'Ctrl+E', + onclick:openmanager + }); + + editor.addShortcut('Ctrl+E', '', openmanager); + + editor.addMenuItem('responsivefilemanager', { + icon: 'browse', + text: 'Insert file', + shortcut: 'Ctrl+E', + onclick: openmanager, + context: 'insert' + }); + +}); \ No newline at end of file diff --git a/local/modules/Tinymce/Resources/js/tinymce/plugins/responsivefilemanager/plugin.min.js b/local/modules/Tinymce/Resources/js/tinymce/plugins/responsivefilemanager/plugin.min.js new file mode 100644 index 00000000..d5db47ea --- /dev/null +++ b/local/modules/Tinymce/Resources/js/tinymce/plugins/responsivefilemanager/plugin.min.js @@ -0,0 +1,9 @@ +/** + * plugin.js + * + * Copyright, Alberto Peripolli + * Released under Creative Commons Attribution-NonCommercial 3.0 Unported License. + * + * Contributing: https://github.com/trippo/ResponsiveFilemanager + */ +tinymce.PluginManager.add("responsivefilemanager",function(e){function t(){e.focus(true);var t="RESPONSIVE FileManager";if(typeof e.settings.filemanager_title!=="undefined"&&e.settings.filemanager_title){t=e.settings.filemanager_title}var n="key";if(typeof e.settings.filemanager_access_key!=="undefined"&&e.settings.filemanager_access_key){n=e.settings.filemanager_access_key}var r="";if(typeof e.settings.filemanager_sort_by!=="undefined"&&e.settings.filemanager_sort_by){r="&sort_by="+e.settings.filemanager_sort_by}var i="false";if(typeof e.settings.filemanager_descending!=="undefined"&&e.settings.filemanager_descending){i=e.settings.filemanager_descending}var s="";if(typeof e.settings.filemanager_subfolder!=="undefined"&&e.settings.filemanager_subfolder){s="&fldr="+e.settings.filemanager_subfolder}var o=2;if(typeof e.settings.filemanager_type!=="undefined"&&e.settings.filemanager_type){if($.isNumeric(e.settings.filemanager_type)===true&&e.settings.filemanager_type>0&&e.settings.filemanager_type<=3){o=e.settings.filemanager_type}else if(e.settings.filemanager_type=="image"){o=1}else if(e.settings.filemanager_type=="media"){o=3}else{o=2}}win=e.windowManager.open({title:t,file:e.settings.external_filemanager_path+"dialog.php?type=4&descending="+i+r+s+"&lang="+e.settings.language+"&akey="+n,width:860,height:570,inline:1,resizable:true,maximizable:true})}e.addButton("responsivefilemanager",{icon:"browse",tooltip:"Insert file",shortcut:"Ctrl+E",onclick:t});e.addShortcut("Ctrl+E","",t);e.addMenuItem("responsivefilemanager",{icon:"browse",text:"Insert file",shortcut:"Ctrl+E",onclick:t,context:"insert"})}) \ No newline at end of file diff --git a/local/modules/Tinymce/Resources/js/tinymce/plugins/save/plugin.min.js b/local/modules/Tinymce/Resources/js/tinymce/plugins/save/plugin.min.js new file mode 100644 index 00000000..ff35bb45 --- /dev/null +++ b/local/modules/Tinymce/Resources/js/tinymce/plugins/save/plugin.min.js @@ -0,0 +1 @@ +tinymce.PluginManager.add("save",function(e){function t(){var t;return t=tinymce.DOM.getParent(e.id,"form"),!e.getParam("save_enablewhendirty",!0)||e.isDirty()?(tinymce.triggerSave(),e.getParam("save_onsavecallback")?(e.execCallback("save_onsavecallback",e),void e.nodeChanged()):void(t?(e.setDirty(!1),(!t.onsubmit||t.onsubmit())&&("function"==typeof t.submit?t.submit():n(e.translate("Error: Form submit field collision."))),e.nodeChanged()):n(e.translate("Error: No form element found.")))):void 0}function n(t){e.notificationManager.open({text:t,type:"error"})}function r(){var t=tinymce.trim(e.startContent);return e.getParam("save_oncancelcallback")?void e.execCallback("save_oncancelcallback",e):(e.setContent(t),e.undoManager.clear(),void e.nodeChanged())}function i(){var t=this;e.on("nodeChange dirty",function(){t.disabled(e.getParam("save_enablewhendirty",!0)&&!e.isDirty())})}e.addCommand("mceSave",t),e.addCommand("mceCancel",r),e.addButton("save",{icon:"save",text:"Save",cmd:"mceSave",disabled:!0,onPostRender:i}),e.addButton("cancel",{text:"Cancel",icon:!1,cmd:"mceCancel",disabled:!0,onPostRender:i}),e.addShortcut("Meta+S","","mceSave")}); \ No newline at end of file diff --git a/local/modules/Tinymce/Resources/js/tinymce/plugins/searchreplace/plugin.min.js b/local/modules/Tinymce/Resources/js/tinymce/plugins/searchreplace/plugin.min.js new file mode 100644 index 00000000..811e3e63 --- /dev/null +++ b/local/modules/Tinymce/Resources/js/tinymce/plugins/searchreplace/plugin.min.js @@ -0,0 +1 @@ +!function(){function e(e){return e&&1==e.nodeType&&"false"===e.contentEditable}function t(t,n,r,i,o){function a(e,t){if(t=t||0,!e[0])throw"findAndReplaceDOMText cannot handle zero-length matches";var n=e.index;if(t>0){var r=e[t];if(!r)throw"Invalid capture group";n+=e[0].indexOf(r),e[0]=r}return[n,n+e[0].length,[e[0]]]}function s(t){var n;if(3===t.nodeType)return t.data;if(m[t.nodeName]&&!p[t.nodeName])return"";if(n="",e(t))return"\n";if((p[t.nodeName]||h[t.nodeName])&&(n+="\n"),t=t.firstChild)do n+=s(t);while(t=t.nextSibling);return n}function l(t,n,r){var i,o,a,s,l=[],c=0,u=t,d=n.shift(),f=0;e:for(;;){if((p[u.nodeName]||h[u.nodeName]||e(u))&&c++,3===u.nodeType&&(!o&&u.length+c>=d[1]?(o=u,s=d[1]-c):i&&l.push(u),!i&&u.length+c>d[0]&&(i=u,a=d[0]-c),c+=u.length),i&&o){if(u=r({startNode:i,startNodeIndex:a,endNode:o,endNodeIndex:s,innerNodes:l,match:d[2],matchIndex:f}),c-=o.length-s,i=null,o=null,l=[],d=n.shift(),f++,!d)break}else if(m[u.nodeName]&&!p[u.nodeName]||!u.firstChild){if(u.nextSibling){u=u.nextSibling;continue}}else if(!e(u)){u=u.firstChild;continue}for(;;){if(u.nextSibling){u=u.nextSibling;break}if(u.parentNode===t)break e;u=u.parentNode}}}function c(e){var t;if("function"!=typeof e){var n=e.nodeType?e:f.createElement(e);t=function(e,t){var r=n.cloneNode(!1);return r.setAttribute("data-mce-index",t),e&&r.appendChild(f.createTextNode(e)),r}}else t=e;return function(e){var n,r,i,o=e.startNode,a=e.endNode,s=e.matchIndex;if(o===a){var l=o;i=l.parentNode,e.startNodeIndex>0&&(n=f.createTextNode(l.data.substring(0,e.startNodeIndex)),i.insertBefore(n,l));var c=t(e.match[0],s);return i.insertBefore(c,l),e.endNodeIndexp;++p){var h=e.innerNodes[p],g=t(h.data,s);h.parentNode.replaceChild(g,h),d.push(g)}var v=t(a.data.substring(0,e.endNodeIndex),s);return i=o.parentNode,i.insertBefore(n,o),i.insertBefore(u,o),i.removeChild(o),i=a.parentNode,i.insertBefore(v,a),i.insertBefore(r,a),i.removeChild(a),v}}var u,d,f,p,m,h,g=[],v=0;if(f=n.ownerDocument,p=o.getBlockElements(),m=o.getWhiteSpaceElements(),h=o.getShortEndedElements(),d=s(n)){if(t.global)for(;u=t.exec(d);)g.push(a(u,i));else u=d.match(t),g.push(a(u,i));return g.length&&(v=g.length,l(n,g,c(r))),v}}function n(e){function n(){function t(){o.statusbar.find("#next").disabled(!a(d+1).length),o.statusbar.find("#prev").disabled(!a(d-1).length)}function n(){tinymce.ui.MessageBox.alert("Could not find the specified string.",function(){o.find("#find")[0].focus()})}var r,i={};r=tinymce.trim(e.selection.getContent({format:"text"}));var o=tinymce.ui.Factory.create({type:"window",layout:"flex",pack:"center",align:"center",onClose:function(){e.focus(),u.done()},onSubmit:function(e){var r,s,l,c;return e.preventDefault(),s=o.find("#case").checked(),c=o.find("#words").checked(),l=o.find("#find").value(),l.length?i.text==l&&i.caseState==s&&i.wholeWord==c?0===a(d+1).length?void n():(u.next(),void t()):(r=u.find(l,s,c),r||n(),o.statusbar.items().slice(1).disabled(0===r),t(),void(i={text:l,caseState:s,wholeWord:c})):(u.done(!1),void o.statusbar.items().slice(1).disabled(!0))},buttons:[{text:"Find",subtype:"primary",onclick:function(){o.submit()}},{text:"Replace",disabled:!0,onclick:function(){u.replace(o.find("#replace").value())||(o.statusbar.items().slice(1).disabled(!0),d=-1,i={})}},{text:"Replace all",disabled:!0,onclick:function(){u.replace(o.find("#replace").value(),!0,!0),o.statusbar.items().slice(1).disabled(!0),i={}}},{type:"spacer",flex:1},{text:"Prev",name:"prev",disabled:!0,onclick:function(){u.prev(),t()}},{text:"Next",name:"next",disabled:!0,onclick:function(){u.next(),t()}}],title:"Find and replace",items:{type:"form",padding:20,labelGap:30,spacing:10,items:[{type:"textbox",name:"find",size:40,label:"Find",value:r},{type:"textbox",name:"replace",size:40,label:"Replace with"},{type:"checkbox",name:"case",text:"Match case",label:" "},{type:"checkbox",name:"words",text:"Whole words",label:" "}]}}).renderTo().reflow()}function r(e){var t=e.getAttribute("data-mce-index");return"number"==typeof t?""+t:t}function i(n){var r,i;return i=e.dom.create("span",{"data-mce-bogus":1}),i.className="mce-match-marker",r=e.getBody(),u.done(!1),t(n,r,i,!1,e.schema)}function o(e){var t=e.parentNode;e.firstChild&&t.insertBefore(e.firstChild,e),e.parentNode.removeChild(e)}function a(t){var n,i=[];if(n=tinymce.toArray(e.getBody().getElementsByTagName("span")),n.length)for(var o=0;o0}var u=this,d=-1;u.init=function(e){e.addMenuItem("searchreplace",{text:"Find and replace",shortcut:"Meta+F",onclick:n,separator:"before",context:"edit"}),e.addButton("searchreplace",{tooltip:"Find and replace",shortcut:"Meta+F",onclick:n}),e.addCommand("SearchReplace",n),e.shortcuts.add("Meta+F","",n)},u.find=function(e,t,n){e=e.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g,"\\$&"),e=n?"\\b"+e+"\\b":e;var r=i(new RegExp(e,t?"g":"gi"));return r&&(d=-1,d=s(!0)),r},u.next=function(){var e=s(!0);-1!==e&&(d=e)},u.prev=function(){var e=s(!1);-1!==e&&(d=e)},u.replace=function(t,n,i){var s,f,p,m,h,g,v=d;for(n=n!==!1,p=e.getBody(),f=tinymce.grep(tinymce.toArray(p.getElementsByTagName("span")),c),s=0;sd&&f[s].setAttribute("data-mce-index",h-1)}return e.undoManager.add(),d=v,n?(g=a(v+1).length>0,u.next()):(g=a(v-1).length>0,u.prev()),!i&&g},u.done=function(t){var n,i,a,s;for(i=tinymce.toArray(e.getBody().getElementsByTagName("span")),n=0;n=l.end?(o=d,s=l.end-u):i&&c.push(d),!i&&d.length+u>l.start&&(i=d,a=l.start-u),u+=d.length),i&&o){if(d=r({startNode:i,startNodeIndex:a,endNode:o,endNodeIndex:s,innerNodes:c,match:l.text,matchIndex:f}),u-=o.length-s,i=null,o=null,c=[],l=n.shift(),f++,!l)break}else if(_[d.nodeName]&&!N[d.nodeName]||!d.firstChild){if(d.nextSibling){d=d.nextSibling;continue}}else if(!e(d)){d=d.firstChild;continue}for(;;){if(d.nextSibling){d=d.nextSibling;break}if(d.parentNode===t)break e;d=d.parentNode}}}function a(e){function t(t,n){var r=k[n];r.stencil||(r.stencil=e(r));var i=r.stencil.cloneNode(!1);return i.setAttribute("data-mce-index",n),t&&i.appendChild(S.doc.createTextNode(t)),i}return function(e){var n,r,i,o=e.startNode,a=e.endNode,s=e.matchIndex,l=S.doc;if(o===a){var c=o;i=c.parentNode,e.startNodeIndex>0&&(n=l.createTextNode(c.data.substring(0,e.startNodeIndex)),i.insertBefore(n,c));var u=t(e.match,s);return i.insertBefore(u,c),e.endNodeIndexp;++p){var h=e.innerNodes[p],g=t(h.data,s);h.parentNode.replaceChild(g,h),f.push(g)}var v=t(a.data.substring(0,e.endNodeIndex),s);return i=o.parentNode,i.insertBefore(n,o),i.insertBefore(d,o),i.removeChild(o),i=a.parentNode,i.insertBefore(v,a),i.insertBefore(r,a),i.removeChild(a),v}}function s(e){var t=e.parentNode;t.insertBefore(e.firstChild,e),e.parentNode.removeChild(e)}function l(e){var n=t.getElementsByTagName("*"),r=[];e="number"==typeof e?""+e:null;for(var i=0;it&&e(k[t],t)!==!1;t++);return this}function f(e){return k.length&&o(t,k,a(e)),this}function p(e,t){if(w&&e.global)for(;C=e.exec(w);)k.push(r(C,t));return this}function m(e){var t,n=l(e?c(e):null);for(t=n.length;t--;)s(n[t]);return this}function h(e){return k[e.getAttribute("data-mce-index")]}function g(e){return l(c(e))[0]}function v(e,t,n){return k.push({start:e,end:e+t,text:w.substr(e,t),data:n}),this}function y(e){var t=l(c(e)),r=n.dom.createRng();return r.setStartBefore(t[0]),r.setEndAfter(t[t.length-1]),r}function b(e,t){var r=y(e);return r.deleteContents(),t.length>0&&r.insertNode(n.dom.doc.createTextNode(t)),r}function x(){return k.splice(0,k.length),m(),this}var C,w,N,_,E,k=[],S=n.dom;return N=n.schema.getBlockElements(),_=n.schema.getWhiteSpaceElements(),E=n.schema.getShortEndedElements(),w=i(t),{text:w,matches:k,each:d,filter:u,reset:x,matchFromElement:h,elementFromMatch:g,find:p,add:v,wrap:f,unwrap:m,replace:b,rangeFromMatch:y,indexOf:c}}}),r("tinymce/spellcheckerplugin/Plugin",["tinymce/spellcheckerplugin/DomTextMatcher","tinymce/PluginManager","tinymce/util/Tools","tinymce/ui/Menu","tinymce/dom/DOMUtils","tinymce/util/XHR","tinymce/util/URI","tinymce/util/JSON"],function(e,t,n,r,i,o,a,s){t.add("spellchecker",function(t,l){function c(){return A.textMatcher||(A.textMatcher=new e(t.getBody(),t)),A.textMatcher}function u(e,t){var r=[];return n.each(t,function(e){r.push({selectable:!0,text:e.name,data:e.value})}),r}function d(e){for(var t in e)return!1;return!0}function f(e,o){var a=[],s=k[e];n.each(s,function(e){a.push({text:e,onclick:function(){t.insertContent(t.dom.encode(e)),t.dom.remove(o),v()}})}),a.push({text:"-"}),R&&a.push({text:"Add to Dictionary",onclick:function(){y(e,o)}}),a.push.apply(a,[{text:"Ignore",onclick:function(){b(e,o)}},{text:"Ignore all",onclick:function(){b(e,o,!0)}}]),T=new r({items:a,context:"contextmenu",onautohide:function(e){-1!=e.target.className.indexOf("spellchecker")&&e.preventDefault()},onhide:function(){T.remove(),T=null}}),T.renderTo(document.body);var l=i.DOM.getPos(t.getContentAreaContainer()),c=t.dom.getPos(o[0]),u=t.dom.getRoot();"BODY"==u.nodeName?(c.x-=u.ownerDocument.documentElement.scrollLeft||u.scrollLeft,c.y-=u.ownerDocument.documentElement.scrollTop||u.scrollTop):(c.x-=u.scrollLeft,c.y-=u.scrollTop),l.x+=c.x,l.y+=c.y,T.moveTo(l.x,l.y+o[0].offsetHeight)}function p(){return t.getParam("spellchecker_wordchar_pattern")||new RegExp('[^\\s!"#$%&()*+,-./:;<=>?@[\\]^_{|}`\xa7\xa9\xab\xae\xb1\xb6\xb7\xb8\xbb\xbc\xbd\xbe\xbf\xd7\xf7\xa4\u201d\u201c\u201e\xa0\u2002\u2003\u2009]+',"g")}function m(e,r,i,c){var u={method:e},d="";"spellcheck"==e&&(u.text=r,u.lang=B.spellchecker_language),"addToDictionary"==e&&(u.word=r),n.each(u,function(e,t){d&&(d+="&"),d+=t+"="+encodeURIComponent(e)}),o.send({url:new a(l).toAbsolute(B.spellchecker_rpc_url),type:"post",content_type:"application/x-www-form-urlencoded",data:d,success:function(e){if(e=s.parse(e))e.error?c(e.error):i(e);else{var n=t.translate("Server response wasn't proper JSON.");c(n)}},error:function(){var e=t.translate("The spelling service was not found: (")+B.spellchecker_rpc_url+t.translate(")");c(e)}})}function h(e,t,n,r){var i=B.spellchecker_callback||m;i.call(A,e,t,n,r)}function g(){function e(e){t.notificationManager.open({text:e,type:"error"}),t.setProgressState(!1),x()}x()||(t.setProgressState(!0),h("spellcheck",c().text,_,e),t.focus())}function v(){t.dom.select("span.mce-spellchecker-word").length||x()}function y(e,n){t.setProgressState(!0),h("addToDictionary",e,function(){t.setProgressState(!1),t.dom.remove(n,!0),v()},function(e){t.notificationManager.open({text:e,type:"error"}),t.setProgressState(!1)})}function b(e,r,i){t.selection.collapse(),i?n.each(t.dom.select("span.mce-spellchecker-word"),function(n){n.getAttribute("data-mce-word")==e&&t.dom.remove(n,!0)}):t.dom.remove(r,!0),v()}function x(){return c().reset(),A.textMatcher=null,S?(S=!1,t.fire("SpellcheckEnd"),!0):void 0}function C(e){var t=e.getAttribute("data-mce-index");return"number"==typeof t?""+t:t}function w(e){var r,i=[];if(r=n.toArray(t.getBody().getElementsByTagName("span")),r.length)for(var o=0;o0){var i=t.dom.createRng();i.setStartBefore(r[0]),i.setEndAfter(r[r.length-1]),t.selection.setRng(i),f(n.getAttribute("data-mce-word"),r)}}}),t.addMenuItem("spellchecker",{text:"Spellcheck",context:"tools",onclick:g,selectable:!0,onPostRender:function(){var e=this;e.active(S),t.on("SpellcheckStart SpellcheckEnd",function(){e.active(S)})}});var M={tooltip:"Spellcheck",onclick:g,onPostRender:function(){var e=this;t.on("SpellcheckStart SpellcheckEnd",function(){e.active(S)})}};E.length>1&&(M.type="splitbutton",M.menu=E,M.onshow=N,M.onselect=function(e){B.spellchecker_language=e.control.settings.data}),t.addButton("spellchecker",M),t.addCommand("mceSpellCheck",g),t.on("remove",function(){T&&(T.remove(),T=null)}),t.on("change",v),this.getTextMatcher=c,this.getWordCharPattern=p,this.markErrors=_,this.getLanguage=function(){return B.spellchecker_language},B.spellchecker_language=B.spellchecker_language||B.language||"en"})}),o(["tinymce/spellcheckerplugin/DomTextMatcher"])}(this); \ No newline at end of file diff --git a/local/modules/Tinymce/Resources/js/tinymce/plugins/tabfocus/plugin.min.js b/local/modules/Tinymce/Resources/js/tinymce/plugins/tabfocus/plugin.min.js new file mode 100644 index 00000000..25a990ff --- /dev/null +++ b/local/modules/Tinymce/Resources/js/tinymce/plugins/tabfocus/plugin.min.js @@ -0,0 +1 @@ +tinymce.PluginManager.add("tabfocus",function(e){function t(e){9!==e.keyCode||e.ctrlKey||e.altKey||e.metaKey||e.preventDefault()}function n(t){function n(n){function o(e){return"BODY"===e.nodeName||"hidden"!=e.type&&"none"!=e.style.display&&"hidden"!=e.style.visibility&&o(e.parentNode)}function l(e){return/INPUT|TEXTAREA|BUTTON/.test(e.tagName)&&tinymce.get(t.id)&&-1!=e.tabIndex&&o(e)}if(s=r.select(":input:enabled,*[tabindex]:not(iframe)"),i(s,function(t,n){return t.id==e.id?(a=n,!1):void 0}),n>0){for(c=a+1;c=0;c--)if(l(s[c]))return s[c];return null}var a,s,l,c;if(!(9!==t.keyCode||t.ctrlKey||t.altKey||t.metaKey||t.isDefaultPrevented())&&(l=o(e.getParam("tab_focus",e.getParam("tabfocus_elements",":prev,:next"))),1==l.length&&(l[1]=l[0],l[0]=":prev"),s=t.shiftKey?":prev"==l[0]?n(-1):r.get(l[0]):":next"==l[1]?n(1):r.get(l[1]))){var u=tinymce.get(s.id||s.name);s.id&&u?u.focus():tinymce.util.Delay.setTimeout(function(){tinymce.Env.webkit||window.focus(),s.focus()},10),t.preventDefault()}}var r=tinymce.DOM,i=tinymce.each,o=tinymce.explode;e.on("init",function(){e.inline&&tinymce.DOM.setAttrib(e.getBody(),"tabIndex",null),e.on("keyup",t),tinymce.Env.gecko?e.on("keypress keydown",n):e.on("keydown",n)})}); \ No newline at end of file diff --git a/local/modules/Tinymce/Resources/js/tinymce/plugins/table/plugin.min.js b/local/modules/Tinymce/Resources/js/tinymce/plugins/table/plugin.min.js new file mode 100644 index 00000000..d9f89ca1 --- /dev/null +++ b/local/modules/Tinymce/Resources/js/tinymce/plugins/table/plugin.min.js @@ -0,0 +1,2 @@ +!function(e,t){"use strict";function n(e,t){for(var n,r=[],a=0;a10)&&(t.innerHTML='
    ')}return{getSpanVal:t,paddCell:n}}),r("tinymce/tableplugin/TableGrid",["tinymce/util/Tools","tinymce/Env","tinymce/tableplugin/Utils"],function(e,n,r){var i=e.each,o=r.getSpanVal;return function(a,s){function l(e){return e===a.getBody()}function c(){var e=0;L=[],H=0,i(["thead","tbody","tfoot"],function(t){var n=W.select("> "+t+" tr",s);i(n,function(n,r){r+=e,i(W.select("> td, > th",n),function(e,n){var i,a,s,l;if(L[r])for(;L[r][n];)n++;for(s=o(e,"rowspan"),l=o(e,"colspan"),a=r;r+s>a;a++)for(L[a]||(L[a]=[]),i=n;n+l>i;i++)L[a][i]={part:t,real:a==r&&i==n,elm:e,rowspan:s,colspan:l};H=Math.max(H,n+1)})}),e+=n.length})}function u(e,t){return e=e.cloneNode(t),e.removeAttribute("id"),e}function d(e,t){var n;return n=L[t],n?n[e]:void 0}function f(e,t,n){e&&(n=parseInt(n,10),1===n?e.removeAttribute(t,1):e.setAttribute(t,n,1))}function p(e){return e&&(W.hasClass(e.elm,"mce-item-selected")||e==F)}function m(){var e=[];return i(s.rows,function(t){i(t.cells,function(n){return W.hasClass(n,"mce-item-selected")||F&&n==F.elm?(e.push(t),!1):void 0})}),e}function h(){var e=W.createRng();l(s)||(e.setStartAfter(s),e.setEndAfter(s),z.setRng(e),W.remove(s))}function g(t){var o,s={};return a.settings.table_clone_elements!==!1&&(s=e.makeMap((a.settings.table_clone_elements||"strong em b i span font h1 h2 h3 h4 h5 h6 p div").toUpperCase(),/[ ,]/)),e.walk(t,function(e){var r;return 3==e.nodeType?(i(W.getParents(e.parentNode,null,t).reverse(),function(e){s[e.nodeName]&&(e=u(e,!1),o?r&&r.appendChild(e):o=r=e,r=e)}),r&&(r.innerHTML=n.ie?" ":'
    '),!1):void 0},"childNodes"),t=u(t,!1),f(t,"rowSpan",1),f(t,"colSpan",1),o?t.appendChild(o):r.paddCell(t),t}function v(){var e,t=W.createRng();return i(W.select("tr",s),function(e){0===e.cells.length&&W.remove(e)}),0===W.select("tr",s).length?(t.setStartBefore(s),t.setEndBefore(s),z.setRng(t),void W.remove(s)):(i(W.select("thead,tbody,tfoot",s),function(e){0===e.rows.length&&W.remove(e)}),c(),void(I&&(e=L[Math.min(L.length-1,I.y)],e&&(z.select(e[Math.min(e.length-1,I.x)].elm,!0),z.collapse(!0)))))}function y(e,t,n,r){var i,o,a,s,l;for(i=L[t][e].elm.parentNode,a=1;n>=a;a++)if(i=W.getNext(i,"tr")){for(o=e;o>=0;o--)if(l=L[t+a][o].elm,l.parentNode==i){for(s=1;r>=s;s++)W.insertAfter(g(l),l);break}if(-1==o)for(s=1;r>=s;s++)i.insertBefore(g(i.cells[0]),i.cells[0])}}function b(){i(L,function(e,t){i(e,function(e,n){var r,i,a;if(p(e)&&(e=e.elm,r=o(e,"colspan"),i=o(e,"rowspan"),r>1||i>1)){for(f(e,"rowSpan",1),f(e,"colSpan",1),a=0;r-1>a;a++)W.insertAfter(g(e),e);y(n,t,i-1,r)}})})}function x(t,n,r){var o,a,s,l,u,m,h,g,y,x,C;if(t?(o=A(t),a=o.x,s=o.y,l=a+(n-1),u=s+(r-1)):(I=O=null,i(L,function(e,t){i(e,function(e,n){p(e)&&(I||(I={x:n,y:t}),O={x:n,y:t})})}),I&&(a=I.x,s=I.y,l=O.x,u=O.y)),g=d(a,s),y=d(l,u),g&&y&&g.part==y.part){for(b(),c(),g=d(a,s).elm,f(g,"colSpan",l-a+1),f(g,"rowSpan",u-s+1),h=s;u>=h;h++)for(m=a;l>=m;m++)L[h]&&L[h][m]&&(t=L[h][m].elm,t!=g&&(x=e.grep(t.childNodes),i(x,function(e){g.appendChild(e)}),x.length&&(x=e.grep(g.childNodes),C=0,i(x,function(e){"BR"==e.nodeName&&W.getAttrib(e,"data-mce-bogus")&&C++0&&L[n-1][s]&&(m=L[n-1][s].elm,h=o(m,"rowSpan"),h>1)){f(m,"rowSpan",h+1);continue}}else if(h=o(r,"rowspan"),h>1){f(r,"rowSpan",h+1);continue}d=g(r),f(d,"colSpan",r.colSpan),c.appendChild(d),a=r}c.hasChildNodes()&&(e?l.parentNode.insertBefore(c,l):W.insertAfter(c,l))}}function w(e){var t,n;i(L,function(n){return i(n,function(n,r){return p(n)&&(t=r,e)?!1:void 0}),e?!t:void 0}),i(L,function(r,i){var a,s,l;r[t]&&(a=r[t].elm,a!=n&&(l=o(a,"colspan"),s=o(a,"rowspan"),1==l?e?(a.parentNode.insertBefore(g(a),a),y(t,i,s-1,l)):(W.insertAfter(g(a),a),y(t,i,s-1,l)):f(a,"colSpan",a.colSpan+1),n=a))})}function N(t){return e.grep(_(t),p)}function _(e){var t=[];return i(e,function(e){i(e,function(e){t.push(e)})}),t}function E(){var t=[];if(l(s)){if(1==L[0].length)return;if(N(L).length==_(L).length)return}i(L,function(n){i(n,function(n,r){p(n)&&-1===e.inArray(t,r)&&(i(L,function(e){var t,n=e[r].elm;t=o(n,"colSpan"),t>1?f(n,"colSpan",t-1):W.remove(n)}),t.push(r))})}),v()}function k(){function e(e){var t,n;i(e.cells,function(e){var n=o(e,"rowSpan");n>1&&(f(e,"rowSpan",n-1),t=A(e),y(t.x,t.y,1,1))}),t=A(e.cells[0]),i(L[t.y],function(e){var t;e=e.elm,e!=n&&(t=o(e,"rowSpan"),1>=t?W.remove(e):f(e,"rowSpan",t-1),n=e)})}var t;t=m(),l(s)&&t.length==s.rows.length||(i(t.reverse(),function(t){e(t)}),v())}function S(){var e=m();if(!l(s)||e.length!=s.rows.length)return W.remove(e),v(),e}function T(){var e=m();return i(e,function(t,n){e[n]=u(t,!0)}),e}function R(e,t){var n=m(),r=n[t?0:n.length-1],o=r.cells.length;e&&(i(L,function(e){var t;return o=0,i(e,function(e){e.real&&(o+=e.colspan),e.elm.parentNode==r&&(t=1)}),t?!1:void 0}),t||e.reverse(),i(e,function(e){var n,i,a=e.cells.length;for(n=0;a>n;n++)i=e.cells[n],f(i,"colSpan",1),f(i,"rowSpan",1);for(n=a;o>n;n++)e.appendChild(g(e.cells[a-1]));for(n=o;a>n;n++)W.remove(e.cells[n]);t?r.parentNode.insertBefore(e,r):W.insertAfter(e,r)}),W.removeClass(W.select("td.mce-item-selected,th.mce-item-selected"),"mce-item-selected"))}function A(e){var t;return i(L,function(n,r){return i(n,function(n,i){return n.elm==e?(t={x:i,y:r},!1):void 0}),!t}),t}function B(e){I=A(e)}function D(){var e,t;return e=t=0,i(L,function(n,r){i(n,function(n,i){var o,a;p(n)&&(n=L[r][i],i>e&&(e=i),r>t&&(t=r),n.real&&(o=n.colspan-1,a=n.rowspan-1,o&&i+o>e&&(e=i+o),a&&r+a>t&&(t=r+a)))})}),{x:e,y:t}}function M(e){var t,n,r,i,o,a,s,l,c,u;if(O=A(e),I&&O){for(t=Math.min(I.x,O.x),n=Math.min(I.y,O.y),r=Math.max(I.x,O.x),i=Math.max(I.y,O.y),o=r,a=i,u=n;a>=u;u++)e=L[u][t],e.real||t-(e.colspan-1)=c;c++)e=L[n][c],e.real||n-(e.rowspan-1)=u;u++)for(c=t;r>=c;c++)e=L[u][c],e.real&&(s=e.colspan-1,l=e.rowspan-1,s&&c+s>o&&(o=c+s),l&&u+l>a&&(a=u+l));for(W.removeClass(W.select("td.mce-item-selected,th.mce-item-selected"),"mce-item-selected"),u=n;a>=u;u++)for(c=t;o>=c;c++)L[u][c]&&W.addClass(L[u][c].elm,"mce-item-selected")}}function P(e,t){var n,r,i;n=A(e),r=n.y*H+n.x;do{if(r+=t,i=d(r%H,Math.floor(r/H)),!i)break;if(i.elm!=e)return z.select(i.elm,!0),W.isEmpty(i.elm)&&z.collapse(!0),!0}while(i.elm==e);return!1}var L,H,I,O,F,z=a.selection,W=z.dom;s=s||W.getParent(z.getStart(!0),"table"),c(),F=W.getParent(z.getStart(!0),"th,td"),F&&(I=A(F),O=D(),F=d(I.x,I.y)),e.extend(this,{deleteTable:h,split:b,merge:x,insertRow:C,insertCol:w,deleteCols:E,deleteRows:k,cutRows:S,copyRows:T,pasteRows:R,getPos:A,setStartCell:B,setEndCell:M,moveRelIdx:P,refresh:c})}}),r("tinymce/tableplugin/Quirks",["tinymce/util/VK","tinymce/util/Delay","tinymce/Env","tinymce/util/Tools","tinymce/tableplugin/Utils"],function(e,t,n,r,i){var o=r.each,a=i.getSpanVal;return function(s){function l(){function n(n){function r(e,t){var r=e?"previousSibling":"nextSibling",o=s.dom.getParent(t,"tr"),a=o[r];if(a)return v(s,t,a,e),n.preventDefault(),!0;var l=s.dom.getParent(o,"table"),d=o.parentNode,f=d.nodeName.toLowerCase();if("tbody"===f||f===(e?"tfoot":"thead")){var p=i(e,l,d,"tbody");if(null!==p)return c(e,p,t)}return u(e,o,r,l)}function i(e,t,n,r){var i=s.dom.select(">"+r,t),o=i.indexOf(n);if(e&&0===o||!e&&o===i.length-1)return l(e,t);if(-1===o){var a="thead"===n.tagName.toLowerCase()?0:i.length-1;return i[a]}return i[o+(e?-1:1)]}function l(e,t){var n=e?"thead":"tfoot",r=s.dom.select(">"+n,t);return 0!==r.length?r[0]:null}function c(e,t,r){var i=d(t,e);return i&&v(s,r,i,e),n.preventDefault(),!0}function u(e,t,i,o){var a=o[i];if(a)return f(a),!0;var l=s.dom.getParent(o,"td,th");if(l)return r(e,l,n);var c=d(t,!e);return f(c),n.preventDefault(),!1}function d(e,t){var n=e&&e[t?"lastChild":"firstChild"];return n&&"BR"===n.nodeName?s.dom.getParent(n,"td,th"):n}function f(e){s.selection.setCursorLocation(e,0)}function p(){return x==e.UP||x==e.DOWN}function m(e){var t=e.selection.getNode(),n=e.dom.getParent(t,"tr");return null!==n}function h(e){for(var t=0,n=e;n.previousSibling;)n=n.previousSibling,t+=a(n,"colspan");return t}function g(e,t){var n=0,r=0;return o(e.children,function(e,i){return n+=a(e,"colspan"),r=i,n>t?!1:void 0}),r}function v(e,t,n,r){var i=h(s.dom.getParent(t,"td,th")),o=g(n,i),a=n.childNodes[o],l=d(a,r);f(l||a)}function y(e){var t=s.selection.getNode(),n=s.dom.getParent(t,"td,th"),r=s.dom.getParent(e,"td,th");return n&&n!==r&&b(n,r)}function b(e,t){return s.dom.getParent(e,"TABLE")===s.dom.getParent(t,"TABLE")}var x=n.keyCode;if(p()&&m(s)){var C=s.selection.getNode();t.setEditorTimeout(s,function(){y(C)&&r(!n.shiftKey&&x===e.UP,C,n)},0)}}s.on("KeyDown",function(e){n(e)})}function c(){function e(e,t){var n,r=t.ownerDocument,i=r.createRange();return i.setStartBefore(t),i.setEnd(e.endContainer,e.endOffset),n=r.createElement("body"),n.appendChild(i.cloneContents()),0===n.innerHTML.replace(/<(br|img|object|embed|input|textarea)[^>]*>/gi,"-").replace(/<[^>]+>/g,"").length}s.on("KeyDown",function(t){var n,r,i=s.dom;(37==t.keyCode||38==t.keyCode)&&(n=s.selection.getRng(),r=i.getParent(n.startContainer,"table"),r&&s.getBody().firstChild==r&&e(n,r)&&(n=i.createRng(),n.setStartBefore(r),n.setEndBefore(r),s.selection.setRng(n),t.preventDefault()))})}function u(){s.on("KeyDown SetContent VisualAid",function(){var e;for(e=s.getBody().lastChild;e;e=e.previousSibling)if(3==e.nodeType){if(e.nodeValue.length>0)break}else if(1==e.nodeType&&("BR"==e.tagName||!e.getAttribute("data-mce-bogus")))break;e&&"TABLE"==e.nodeName&&(s.settings.forced_root_block?s.dom.add(s.getBody(),s.settings.forced_root_block,s.settings.forced_root_block_attrs,n.ie&&n.ie<11?" ":'
    '):s.dom.add(s.getBody(),"br",{"data-mce-bogus":"1"}))}),s.on("PreProcess",function(e){var t=e.node.lastChild;t&&("BR"==t.nodeName||1==t.childNodes.length&&("BR"==t.firstChild.nodeName||"\xa0"==t.firstChild.nodeValue))&&t.previousSibling&&"TABLE"==t.previousSibling.nodeName&&s.dom.remove(t)})}function d(){function e(e,t,n,r){var i,o,a,s=3,l=e.dom.getParent(t.startContainer,"TABLE");return l&&(i=l.parentNode),o=t.startContainer.nodeType==s&&0===t.startOffset&&0===t.endOffset&&r&&("TR"==n.nodeName||n==i),a=("TD"==n.nodeName||"TH"==n.nodeName)&&!r,o||a}function t(){var t=s.selection.getRng(),n=s.selection.getNode(),r=s.dom.getParent(t.startContainer,"TD,TH");if(e(s,t,n,r)){r||(r=n);for(var i=r.lastChild;i.lastChild;)i=i.lastChild;3==i.nodeType&&(t.setEnd(i,i.data.length),s.selection.setRng(t))}}s.on("KeyDown",function(){t()}),s.on("MouseDown",function(e){2!=e.button&&t()})}function f(){function t(e){s.selection.select(e,!0),s.selection.collapse(!0)}function n(e){s.$(e).empty(),i.paddCell(e)}s.on("keydown",function(i){if((i.keyCode==e.DELETE||i.keyCode==e.BACKSPACE)&&!i.isDefaultPrevented()){var o,a,l,c;if(o=s.dom.getParent(s.selection.getStart(),"table")){if(a=s.dom.select("td,th",o),l=r.grep(a,function(e){return s.dom.hasClass(e,"mce-item-selected")}),0===l.length)return c=s.dom.getParent(s.selection.getStart(),"td,th"),void(s.selection.isCollapsed()&&c&&s.dom.isEmpty(c)&&(i.preventDefault(),n(c),t(c)));i.preventDefault(),s.undoManager.transact(function(){a.length==l.length?s.execCommand("mceTableDelete"):(r.each(l,n),t(l[0]))})}}})}f(),n.webkit&&(l(),d()),n.gecko&&(c(),u()),n.ie>10&&(c(),u())}}),r("tinymce/tableplugin/CellSelection",["tinymce/tableplugin/TableGrid","tinymce/dom/TreeWalker","tinymce/util/Tools"],function(e,t,n){return function(r){function i(e){r.getBody().style.webkitUserSelect="",(e||d)&&(r.dom.removeClass(r.dom.select("td.mce-item-selected,th.mce-item-selected"),"mce-item-selected"),d=!1)}function o(t){var n,i,o=t.target;if(!c&&s&&(a||o!=s)&&("TD"==o.nodeName||"TH"==o.nodeName)){i=u.getParent(o,"table"),i==l&&(a||(a=new e(r,i),a.setStartCell(s),r.getBody().style.webkitUserSelect="none"),a.setEndCell(o),d=!0),n=r.selection.getSel();try{n.removeAllRanges?n.removeAllRanges():n.empty()}catch(f){}t.preventDefault()}}var a,s,l,c,u=r.dom,d=!0;return r.on("MouseDown",function(e){2==e.button||c||(i(),s=u.getParent(e.target,"td,th"),l=u.getParent(s,"table"))}),r.on("mouseover",o),r.on("remove",function(){u.unbind(r.getDoc(),"mouseover",o)}),r.on("MouseUp",function(){function e(e,r){var o=new t(e,e);do{if(3==e.nodeType&&0!==n.trim(e.nodeValue).length)return void(r?i.setStart(e,0):i.setEnd(e,e.nodeValue.length));if("BR"==e.nodeName)return void(r?i.setStartBefore(e):i.setEndBefore(e))}while(e=r?o.next():o.prev())}var i,o,c,d,f,p=r.selection;if(s){if(a&&(r.getBody().style.webkitUserSelect=""),o=u.select("td.mce-item-selected,th.mce-item-selected"),o.length>0){i=u.createRng(),d=o[0],i.setStartBefore(d),i.setEndAfter(d),e(d,1),c=new t(d,u.getParent(o[0],"table"));do if("TD"==d.nodeName||"TH"==d.nodeName){if(!u.hasClass(d,"mce-item-selected"))break;f=d}while(d=c.next());e(f),p.setRng(i)}r.nodeChanged(),s=a=l=null}}),r.on("KeyUp Drop SetContent",function(e){i("setcontent"==e.type),s=a=l=null,c=!1}),r.on("ObjectResizeStart ObjectResized",function(e){c="objectresized"!=e.type}),{clear:i}}}),r("tinymce/tableplugin/Dialogs",["tinymce/util/Tools","tinymce/Env"],function(e,t){var n=e.each;return function(r){function i(){var e=r.settings.color_picker_callback;return e?function(){var t=this;e.call(r,function(e){t.value(e).fire("change")},t.value())}:void 0}function o(e){return{title:"Advanced",type:"form",defaults:{onchange:function(){d(e,this.parents().reverse()[0],"style"==this.name())}},items:[{label:"Style",name:"style",type:"textbox"},{type:"form",padding:0,formItemDefaults:{layout:"grid",alignH:["start","right"]},defaults:{size:7},items:[{label:"Border color",type:"colorbox",name:"borderColor",onaction:i()},{label:"Background color",type:"colorbox",name:"backgroundColor",onaction:i()}]}]}}function a(e){return e?e.replace(/px$/,""):""}function s(e){return/^[0-9]+$/.test(e)&&(e+="px"),e}function l(e){n("left center right".split(" "),function(t){r.formatter.remove("align"+t,{},e)})}function c(e){n("top middle bottom".split(" "),function(t){r.formatter.remove("valign"+t,{},e)})}function u(t,n,r){function i(t,r){return r=r||[],e.each(t,function(e){var t={text:e.text||e.title};e.menu?t.menu=i(e.menu):(t.value=e.value,n&&n(t)),r.push(t)}),r}return i(t,r||[])}function d(e,t,n){var r=t.toJSON(),i=e.parseStyle(r.style);n?(t.find("#borderColor").value(i["border-color"]||"")[0].fire("change"),t.find("#backgroundColor").value(i["background-color"]||"")[0].fire("change")):(i["border-color"]=r.borderColor,i["background-color"]=r.backgroundColor),t.find("#style").value(e.serializeStyle(e.parseStyle(e.serializeStyle(i))))}function f(e,t,n){var r=e.parseStyle(e.getAttrib(n,"style"));r["border-color"]&&(t.borderColor=r["border-color"]),r["background-color"]&&(t.backgroundColor=r["background-color"]),t.style=e.serializeStyle(r)}function p(e,t,r){var i=e.parseStyle(e.getAttrib(t,"style"));n(r,function(e){i[e.name]=e.value}),e.setAttrib(t,"style",e.serializeStyle(e.parseStyle(e.serializeStyle(i))))}var m=this;m.tableProps=function(){m.table(!0)},m.table=function(i){function c(){function n(e,t,r){if("TD"===e.tagName||"TH"===e.tagName)C.setStyle(e,t,r);else if(e.children)for(var i=0;i',h.insertBefore(i,h.firstChild)),l(h),w.align&&r.formatter.apply("align"+w.align,{},h),r.focus(),r.addVisual()})}function m(e,t){function n(e,n){for(var r=0;rr;r++)n.push(r);return n}function S(e,t,n){for(var r,i=e(),o=0;o0?y(i,o,a):[],u=s.length>0?y(d,f,s):[];w(c,e.offsetWidth,l),N(u,e.offsetHeight,l)}function B(e,t,n,r){if(0>t||t>=e.length-1)return"";var i=e[t];if(i)i={value:i,delta:0};else for(var o=e.slice(0,t).reverse(),a=0;a0?i:o}function P(t,n,r){for(var i=T(t),o=e.map(i,function(e){return d(e.colIndex,e.element).x}),a=[],s=0;s1?B(o,s):M(i[s].element,n,r);c=c?c:Ce,a.push(c)}return a}function L(e){var t=D(e,"height"),n=parseInt(t,10);return V(t)&&(n=0),!isNaN(n)&&n>0?n:m(e,"height")}function H(t){for(var n=R(t),r=e.map(n,function(e){return i(e.rowIndex,e.element).y}),o=[],a=0;a1?B(r,a):L(n[a].element);l=l?l:we,o.push(l)}return o}function I(t,n,r,i,o){function a(t){return e.map(t,function(){return 0})}function s(){var e;if(o)e=[100-d[0]];else{var t=Math.max(i,d[0]+r);e=[t-d[0]]}return e}function l(e,t){var n,o=a(d.slice(0,e)),s=a(d.slice(t+1));if(r>=0){var l=Math.max(i,d[t]-r);n=o.concat([r,l-d[t]]).concat(s)}else{var c=Math.max(i,d[e]+r),u=d[e]-c;n=o.concat([c-d[e],u]).concat(s)}return n}function c(e,t){var n,o=a(d.slice(0,t));if(r>=0)n=o.concat([r]);else{var s=Math.max(i,d[t]+r);n=o.concat([s-d[t]])}return n}var u,d=t.slice(0);return u=0===t.length?[]:1===t.length?s():0===n?l(0,1):n>0&&ni;i++)r+=n[i];return r}function F(t,n){var r=t.getAllCells();return e.map(r,function(e){var t=O(e.colIndex,e.colIndex+e.colspan,n);return{element:e.element,width:t,colspan:e.colspan}})}function z(t,n){var r=t.getAllCells();return e.map(r,function(e){var t=O(e.rowIndex,e.rowIndex+e.rowspan,n);return{element:e.element,height:t,rowspan:e.rowspan}})}function W(t,n){var r=t.getAllRows();return e.map(r,function(e,t){return{element:e.element,height:n[t]}})}function V(e){return _e.test(e)}function U(e){return Ee.test(e)}function $(t,n,i){function o(t,n){e.each(t,function(e){r.dom.setStyle(e.element,"width",e.width+n),r.dom.setAttrib(e.element,"width",null)})}function a(){return in;n++){for(i+="",r=0;e>r;r++)i+=""+(s.ie?" ":"
    ")+"";i+=""}return i+="",o.undoManager.transact(function(){o.insertContent(i),a=o.dom.get("__mce"),o.dom.setAttrib(a,"id",null),o.dom.setAttribs(a,o.settings.table_default_attributes||{}),o.dom.setStyles(a,o.settings.table_default_styles||{})}),a}function c(e,t){function n(){e.disabled(!o.dom.getParent(o.selection.getStart(),t)),o.selection.selectorChanged(t,function(t){e.disabled(!t)})}o.initialized?n():o.on("init",n)}function d(){c(this,"table")}function f(){c(this,"td,th")}function p(){var e="";e='';for(var t=0;10>t;t++){e+="";for(var n=0;10>n;n++)e+='';e+=""}return e+="
    ",e+=''}function m(e,t,n){var r,i,a,s,l,c=n.getEl().getElementsByTagName("table")[0],u=n.isRtl()||"tl-tr"==n.parent().rel;for(c.nextSibling.innerHTML=e+1+" x "+(t+1),u&&(e=9-e),i=0;10>i;i++)for(r=0;10>r;r++)s=c.rows[i].childNodes[r].firstChild,l=(u?r>=e:e>=r)&&t>=i,o.dom.toggleClass(s,"mce-active",l),l&&(a=s);return a.parentNode}function h(){o.addButton("tableprops",{title:"Table properties",onclick:C.tableProps,icon:"table"}),o.addButton("tabledelete",{title:"Delete table",onclick:a("mceTableDelete")}),o.addButton("tablecellprops",{title:"Cell properties",onclick:a("mceTableCellProps")}),o.addButton("tablemergecells",{title:"Merge cells",onclick:a("mceTableMergeCells")}),o.addButton("tablesplitcells",{title:"Split cell",onclick:a("mceTableSplitCells")}),o.addButton("tableinsertrowbefore",{title:"Insert row before",onclick:a("mceTableInsertRowBefore")}),o.addButton("tableinsertrowafter",{title:"Insert row after",onclick:a("mceTableInsertRowAfter")}),o.addButton("tabledeleterow",{title:"Delete row",onclick:a("mceTableDeleteRow")}),o.addButton("tablerowprops",{title:"Row properties",onclick:a("mceTableRowProps")}),o.addButton("tablecutrow",{title:"Cut row",onclick:a("mceTableCutRow")}),o.addButton("tablecopyrow",{title:"Copy row",onclick:a("mceTableCopyRow")}),o.addButton("tablepasterowbefore",{title:"Paste row before",onclick:a("mceTablePasteRowBefore")}),o.addButton("tablepasterowafter",{title:"Paste row after",onclick:a("mceTablePasteRowAfter")}),o.addButton("tableinsertcolbefore",{title:"Insert column before",onclick:a("mceTableInsertColBefore")}),o.addButton("tableinsertcolafter",{title:"Insert column after",onclick:a("mceTableInsertColAfter")}),o.addButton("tabledeletecol",{title:"Delete column",onclick:a("mceTableDeleteCol")})}function g(e){var t=o.dom.is(e,"table")&&o.getBody().contains(e);return t}function v(){var e=o.settings.table_toolbar;""!==e&&e!==!1&&(e||(e="tableprops tabledelete | tableinsertrowbefore tableinsertrowafter tabledeleterow | tableinsertcolbefore tableinsertcolafter tabledeletecol"),o.addContextToolbar(g,e))}var y,b,x=this,C=new r(o);!o.settings.object_resizing||o.settings.object_resizing!==!0&&"table"!==o.settings.object_resizing||(b=i(o)),o.settings.table_grid===!1?o.addMenuItem("inserttable",{text:"Insert table",icon:"table",context:"table",onclick:C.table}):o.addMenuItem("inserttable",{text:"Insert table",icon:"table",context:"table",ariaHideMenu:!0,onclick:function(e){e.aria&&(this.parent().hideAll(),e.stopImmediatePropagation(),C.table())},onshow:function(){m(0,0,this.menu.items()[0])},onhide:function(){var e=this.menu.items()[0].getEl().getElementsByTagName("a");o.dom.removeClass(e,"mce-active"),o.dom.addClass(e[0],"mce-active")},menu:[{type:"container",html:p(),onPostRender:function(){this.lastX=this.lastY=0},onmousemove:function(e){var t,n,r=e.target;"A"==r.tagName.toUpperCase()&&(t=parseInt(r.getAttribute("data-mce-x"),10),n=parseInt(r.getAttribute("data-mce-y"),10),(this.isRtl()||"tl-tr"==this.parent().rel)&&(t=9-t),(t!==this.lastX||n!==this.lastY)&&(m(t,n,e.control),this.lastX=t,this.lastY=n))},onclick:function(e){var t=this;"A"==e.target.tagName.toUpperCase()&&(e.preventDefault(),e.stopPropagation(),t.parent().cancel(),o.undoManager.transact(function(){l(t.lastX+1,t.lastY+1)}),o.addVisual())}}]}),o.addMenuItem("tableprops",{text:"Table properties",context:"table",onPostRender:d,onclick:C.tableProps}),o.addMenuItem("deletetable",{text:"Delete table",context:"table",onPostRender:d,cmd:"mceTableDelete"}),o.addMenuItem("cell",{separator:"before",text:"Cell",context:"table",menu:[{text:"Cell properties",onclick:a("mceTableCellProps"),onPostRender:f},{text:"Merge cells",onclick:a("mceTableMergeCells"),onPostRender:f},{text:"Split cell",onclick:a("mceTableSplitCells"),onPostRender:f}]}),o.addMenuItem("row",{text:"Row",context:"table",menu:[{text:"Insert row before",onclick:a("mceTableInsertRowBefore"),onPostRender:f},{text:"Insert row after",onclick:a("mceTableInsertRowAfter"),onPostRender:f},{text:"Delete row",onclick:a("mceTableDeleteRow"),onPostRender:f},{text:"Row properties",onclick:a("mceTableRowProps"),onPostRender:f},{text:"-"},{text:"Cut row",onclick:a("mceTableCutRow"),onPostRender:f},{text:"Copy row",onclick:a("mceTableCopyRow"),onPostRender:f},{text:"Paste row before",onclick:a("mceTablePasteRowBefore"),onPostRender:f},{text:"Paste row after",onclick:a("mceTablePasteRowAfter"),onPostRender:f}]}),o.addMenuItem("column",{text:"Column",context:"table",menu:[{text:"Insert column before",onclick:a("mceTableInsertColBefore"),onPostRender:f},{text:"Insert column after",onclick:a("mceTableInsertColAfter"),onPostRender:f},{text:"Delete column",onclick:a("mceTableDeleteCol"),onPostRender:f}]});var w=[];u("inserttable tableprops deletetable | cell row column".split(" "),function(e){"|"==e?w.push({text:"-"}):w.push(o.menuItems[e])}),o.addButton("table",{type:"menubutton",title:"Table",menu:w}),s.isIE||o.on("click",function(e){e=e.target,"TABLE"===e.nodeName&&(o.selection.select(e),o.nodeChanged())}),x.quirks=new t(o),o.on("Init",function(){x.cellSelection=new n(o),x.resizeBars=b}),o.on("PreInit",function(){o.serializer.addAttributeFilter("data-mce-cell-padding,data-mce-border,data-mce-border-color",function(e,t){for(var n=e.length;n--;)e[n].attr(t,null)})}),u({mceTableSplitCells:function(e){e.split()},mceTableMergeCells:function(e){var t;t=o.dom.getParent(o.selection.getStart(),"th,td"),o.dom.select("td.mce-item-selected,th.mce-item-selected").length?e.merge():C.merge(e,t)},mceTableInsertRowBefore:function(e){e.insertRow(!0)},mceTableInsertRowAfter:function(e){e.insertRow()},mceTableInsertColBefore:function(e){e.insertCol(!0)},mceTableInsertColAfter:function(e){e.insertCol()},mceTableDeleteCol:function(e){e.deleteCols()},mceTableDeleteRow:function(e){e.deleteRows()},mceTableCutRow:function(e){y=e.cutRows()},mceTableCopyRow:function(e){y=e.copyRows()},mceTablePasteRowBefore:function(e){e.pasteRows(y,!0)},mceTablePasteRowAfter:function(e){e.pasteRows(y)},mceTableDelete:function(e){b&&b.clearBars(),e.deleteTable()}},function(t,n){o.addCommand(n,function(){var n=new e(o);n&&(t(n),o.execCommand("mceRepaint"),x.cellSelection.clear())})}),u({mceInsertTable:C.table,mceTableProps:function(){C.table(!0)},mceTableRowProps:C.row,mceTableCellProps:C.cell},function(e,t){o.addCommand(t,function(t,n){e(n)})}),h(),v(),o.settings.table_tab_navigation!==!1&&o.on("keydown",function(t){var n,r,i;9==t.keyCode&&(n=o.dom.getParent(o.selection.getStart(),"th,td"),n&&(t.preventDefault(),r=new e(o),i=t.shiftKey?-1:1,o.undoManager.transact(function(){!r.moveRelIdx(n,i)&&i>0&&(r.insertRow(),r.refresh(),r.moveRelIdx(n,i))})))}),x.insertTable=l}var u=o.each;l.add("table",c)})}(this); \ No newline at end of file diff --git a/local/modules/Tinymce/Resources/js/tinymce/plugins/template/plugin.min.js b/local/modules/Tinymce/Resources/js/tinymce/plugins/template/plugin.min.js new file mode 100644 index 00000000..53cc04c1 --- /dev/null +++ b/local/modules/Tinymce/Resources/js/tinymce/plugins/template/plugin.min.js @@ -0,0 +1 @@ +tinymce.PluginManager.add("template",function(e){function t(t){return function(){var n=e.settings.templates;"string"==typeof n?tinymce.util.XHR.send({url:n,success:function(e){t(tinymce.util.JSON.parse(e))}}):t(n)}}function n(t){function n(t){function n(t){if(-1==t.indexOf("")){var n="";tinymce.each(e.contentCSS,function(t){n+=''}),t=""+n+""+t+""}t=o(t,"template_preview_replace_values");var i=r.find("iframe")[0].getEl().contentWindow.document;i.open(),i.write(t),i.close()}var a=t.control.value();a.url?tinymce.util.XHR.send({url:a.url,success:function(e){i=e,n(i)}}):(i=a.content,n(i)),r.find("#description")[0].text(t.control.value().description)}var r,i,s=[];if(!t||0===t.length){var l=e.translate("No templates defined.");return void e.notificationManager.open({text:l,type:"info"})}tinymce.each(t,function(e){s.push({selected:!s.length,text:e.title,value:{url:e.url,content:e.content,description:e.description}})}),r=e.windowManager.open({title:"Insert template",layout:"flex",direction:"column",align:"stretch",padding:15,spacing:10,items:[{type:"form",flex:0,padding:0,items:[{type:"container",label:"Templates",items:{type:"listbox",label:"Templates",name:"template",values:s,onselect:n}}]},{type:"label",name:"description",label:"Description",text:"\xa0"},{type:"iframe",flex:1,border:1}],onsubmit:function(){a(!1,i)},width:e.getParam("template_popup_width",600),height:e.getParam("template_popup_height",500)}),r.find("listbox")[0].fire("select")}function r(t,n){function r(e,t){if(e=""+e,e.length0&&(l=u.create("div",null),l.appendChild(c[0].cloneNode(!0))),s(u.select("*",l),function(t){a(t,e.getParam("template_cdate_classes","cdate").replace(/\s+/g,"|"))&&(t.innerHTML=r(e.getParam("template_cdate_format",e.getLang("template.cdate_format")))),a(t,e.getParam("template_mdate_classes","mdate").replace(/\s+/g,"|"))&&(t.innerHTML=r(e.getParam("template_mdate_format",e.getLang("template.mdate_format")))),a(t,e.getParam("template_selected_content_classes","selcontent").replace(/\s+/g,"|"))&&(t.innerHTML=d)}),i(l),e.execCommand("mceInsertContent",!1,l.innerHTML),e.addVisual()}var s=tinymce.each;e.addCommand("mceInsertTemplate",a),e.addButton("template",{title:"Insert template",onclick:t(n)}),e.addMenuItem("template",{text:"Insert template",onclick:t(n),context:"insert"}),e.on("PreProcess",function(t){var n=e.dom;s(n.select("div",t.node),function(t){n.hasClass(t,"mceTmpl")&&(s(n.select("*",t),function(t){n.hasClass(t,e.getParam("template_mdate_classes","mdate").replace(/\s+/g,"|"))&&(t.innerHTML=r(e.getParam("template_mdate_format",e.getLang("template.mdate_format"))))}),i(t))})})}); \ No newline at end of file diff --git a/local/modules/Tinymce/Resources/js/tinymce/plugins/textcolor/plugin.min.js b/local/modules/Tinymce/Resources/js/tinymce/plugins/textcolor/plugin.min.js new file mode 100644 index 00000000..c762f75c --- /dev/null +++ b/local/modules/Tinymce/Resources/js/tinymce/plugins/textcolor/plugin.min.js @@ -0,0 +1 @@ +tinymce.PluginManager.add("textcolor",function(e){function t(t){var n;return e.dom.getParents(e.selection.getStart(),function(e){var r;(r=e.style["forecolor"==t?"color":"background-color"])&&(n=r)}),n}function n(){var t,n,r=[];for(n=e.settings.textcolor_map||["000000","Black","993300","Burnt orange","333300","Dark olive","003300","Dark green","003366","Dark azure","000080","Navy Blue","333399","Indigo","333333","Very dark gray","800000","Maroon","FF6600","Orange","808000","Olive","008000","Green","008080","Teal","0000FF","Blue","666699","Grayish blue","808080","Gray","FF0000","Red","FF9900","Amber","99CC00","Yellow green","339966","Sea green","33CCCC","Turquoise","3366FF","Royal blue","800080","Purple","999999","Medium gray","FF00FF","Magenta","FFCC00","Gold","FFFF00","Yellow","00FF00","Lime","00FFFF","Aqua","00CCFF","Sky blue","993366","Red violet","FFFFFF","White","FF99CC","Pink","FFCC99","Peach","FFFF99","Light yellow","CCFFCC","Pale green","CCFFFF","Pale cyan","99CCFF","Light sky blue","CC99FF","Plum"],t=0;t
    '+(n?"×":"")+"
    "}var r,i,o,a,s,u,d,f=this,p=f._id,m=0;for(r=n(),r.push({text:tinymce.translate("No color"),color:"transparent"}),o='',a=r.length-1,u=0;c>u;u++){for(o+="",s=0;l>s;s++)d=u*l+s,d>a?o+="":(i=r[d],o+=t(i.color,i.text));o+=""}if(e.settings.color_picker_callback){for(o+='",o+="",s=0;l>s;s++)o+=t("","Custom color");o+=""}return o+="
    "}function i(t,n){e.undoManager.transact(function(){e.focus(),e.formatter.apply(t,{value:n}),e.nodeChanged()})}function o(t){e.undoManager.transact(function(){e.focus(),e.formatter.remove(t,{value:null},null,!0),e.nodeChanged()})}function a(n){function r(e){u.hidePanel(),u.color(e),i(u.settings.format,e)}function a(){u.hidePanel(),u.resetColor(),o(u.settings.format)}function s(e,t){e.style.background=t,e.setAttribute("data-mce-color",t)}var c,u=this.parent();tinymce.DOM.getParent(n.target,".mce-custom-color-btn")&&(u.hidePanel(),e.settings.color_picker_callback.call(e,function(e){var t,n,i,o=u.panel.getEl().getElementsByTagName("table")[0];for(t=tinymce.map(o.rows[o.rows.length-1].childNodes,function(e){return e.firstChild}),i=0;ii;i++)s(t[i],t[i+1].getAttribute("data-mce-color"));s(n,e),r(e)},t(u.settings.format))),c=n.target.getAttribute("data-mce-color"),c?(this.lastId&&document.getElementById(this.lastId).setAttribute("aria-selected",!1),n.target.setAttribute("aria-selected",!0),this.lastId=n.target.id,"transparent"==c?a():r(c)):null!==c&&u.hidePanel()}function s(){var e=this;e._color?i(e.settings.format,e._color):o(e.settings.format)}var l,c;c=e.settings.textcolor_rows||5,l=e.settings.textcolor_cols||8,e.addButton("forecolor",{type:"colorbutton",tooltip:"Text color",format:"forecolor",panel:{role:"application",ariaRemember:!0,html:r,onclick:a},onclick:s}),e.addButton("backcolor",{type:"colorbutton",tooltip:"Background color",format:"hilitecolor",panel:{role:"application",ariaRemember:!0,html:r,onclick:a},onclick:s})}); \ No newline at end of file diff --git a/local/modules/Tinymce/Resources/js/tinymce/plugins/textpattern/plugin.min.js b/local/modules/Tinymce/Resources/js/tinymce/plugins/textpattern/plugin.min.js new file mode 100644 index 00000000..5f2f45c3 --- /dev/null +++ b/local/modules/Tinymce/Resources/js/tinymce/plugins/textpattern/plugin.min.js @@ -0,0 +1 @@ +tinymce.PluginManager.add("textpattern",function(e){function t(){return c&&(l.sort(function(e,t){return e.start.length>t.start.length?-1:e.start.length'+e+"
    "}function o(){var e,t="";for(e in p)t+=e;return new RegExp("["+t+"]","g")}function a(){var e,t="";for(e in p)t&&(t+=","),t+="span.mce-"+p[e];return t}var s,l,c,u,d,f,p,m,h=e.getBody(),g=e.selection;if(p={"\xa0":"nbsp","\xad":"shy"},r=!r,i.state=r,e.fire("VisualChars",{state:r}),m=o(),t&&(f=g.getBookmark()),r)for(l=[],tinymce.walk(h,function(e){3==e.nodeType&&e.nodeValue&&m.test(e.nodeValue)&&l.push(e)},"childNodes"),c=0;c=0;c--)e.dom.remove(l[c],1);g.moveToBookmark(f)}function n(){var t=this;e.on("VisualChars",function(e){t.active(e.state)})}var r,i=this;e.addCommand("mceVisualChars",t),e.addButton("visualchars",{title:"Show invisible characters",cmd:"mceVisualChars",onPostRender:n}),e.addMenuItem("visualchars",{text:"Show invisible characters",cmd:"mceVisualChars",onPostRender:n,selectable:!0,context:"view",prependToContext:!0}),e.on("beforegetcontent",function(e){r&&"raw"!=e.format&&!e.draft&&(r=!0,t(!1))})}); \ No newline at end of file diff --git a/local/modules/Tinymce/Resources/js/tinymce/plugins/wordcount/plugin.min.js b/local/modules/Tinymce/Resources/js/tinymce/plugins/wordcount/plugin.min.js new file mode 100644 index 00000000..d31b9260 --- /dev/null +++ b/local/modules/Tinymce/Resources/js/tinymce/plugins/wordcount/plugin.min.js @@ -0,0 +1 @@ +tinymce.PluginManager.add("wordcount",function(e){function t(){e.theme.panel.find("#wordcount").text(["Words: {0}",i.getCount()])}var n,r,i=this;n=e.getParam("wordcount_countregex",/[\w\u2019\x27\-\u00C0-\u1FFF]+/g),r=e.getParam("wordcount_cleanregex",/[0-9.(),;:!?%#$?\x27\x22_+=\\\/\-]*/g),e.on("init",function(){var n=e.theme.panel&&e.theme.panel.find("#statusbar")[0];n&&tinymce.util.Delay.setEditorTimeout(e,function(){n.insert({type:"label",name:"wordcount",text:["Words: {0}",i.getCount()],classes:"wordcount",disabled:e.settings.readonly},0),e.on("setcontent beforeaddundo",t),e.on("keyup",function(e){32==e.keyCode&&t()})},0)}),i.getCount=function(){var t=e.getContent({format:"raw"}),i=0;if(t){t=t.replace(/\.\.\./g," "),t=t.replace(/<.[^<>]*?>/g," ").replace(/ | /gi," "),t=t.replace(/(\w+)(&#?[a-z0-9]+;)+(\w+)/i,"$1$3").replace(/&.+?;/g," "),t=t.replace(r,"");var o=t.match(n);o&&(i=o.length)}return i}}); \ No newline at end of file diff --git a/local/modules/Tinymce/Resources/js/tinymce/plugins/youtube/README.md b/local/modules/Tinymce/Resources/js/tinymce/plugins/youtube/README.md new file mode 100644 index 00000000..951fbcea --- /dev/null +++ b/local/modules/Tinymce/Resources/js/tinymce/plugins/youtube/README.md @@ -0,0 +1,78 @@ +Plugin youtube for TinyMCE 4 +====================== + +Insert YouTube video W3C valid with optionnals (HD, similar vidéos) + + +Authors +------- + + * Gerits Aurelien (Author-Developer) contact[at]aurelien-gerits[point]be + +Official link in french : + +###Screenshot + +![tinyMCE plugin YouTube](http://blog.aurelien-gerits.be/wp-content/uploads/2013/09/youtube-tinymce-2.0.png "tinyMCE plugin YouTube") + +###Installation + * Download the dist/youtube.zip archive + * Unzip archive in tinyMCE plugin directory (tiny_mce/plugins/) + +###Configuration + ```html + +``` + +###Languages + * English + * French + * Russian + * Spanish + * German + * Italian + * Brazilian + * Hungarian + * Polish + + You can send me translations in other languages + +### Old Version + +[Plugin YouTube for tinyMCE 3](http://magix-cjquery.com/post/2012/05/11/plugin-youtube-v1.4-pour-tinyMCE) + +
    +This file is part of tinyMCE.
    +YouTube for tinyMCE
    +Copyright (C) 2011 - 2013  Gerits Aurelien aurelien[at]magix-dev[dot]be - contact[at]aurelien-gerits[dot]be
    +
    +Redistributions of files must retain the above copyright notice.
    +This program is free software: you can redistribute it and/or modify
    +it under the terms of the GNU General Public License as published by
    +the Free Software Foundation, either version 3 of the License, or
    +(at your option) any later version.
    +
    +This program is distributed in the hope that it will be useful,
    +but WITHOUT ANY WARRANTY; without even the implied warranty of
    +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    +GNU General Public License for more details.
    +
    +You should have received a copy of the GNU General Public License
    +along with this program.  If not, see .
    +
    +####DISCLAIMER
    +
    +Do not edit or add to this file if you wish to upgrade jimagine to newer
    +versions in the future. If you wish to customize jimagine for your
    +needs please refer to magix-dev.be for more information.
    +
    diff --git a/local/modules/Tinymce/Resources/js/tinymce/plugins/youtube/css/styles.css b/local/modules/Tinymce/Resources/js/tinymce/plugins/youtube/css/styles.css new file mode 100644 index 00000000..fa6367a0 --- /dev/null +++ b/local/modules/Tinymce/Resources/js/tinymce/plugins/youtube/css/styles.css @@ -0,0 +1,9 @@ +/*! + * Bootstrap v3.0.0 + * + * Copyright 2013 Twitter, Inc + * Licensed under the Apache License v2.0 + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Designed and built with all the love in the world by @mdo and @fat. + *//*! normalize.css v2.1.0 | MIT License | git.io/normalize */article,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section,summary{display:block}audio,canvas,video{display:inline-block}audio:not([controls]){display:none;height:0}[hidden]{display:none}html{font-family:sans-serif;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}body{margin:0}a:active,a:hover{outline:0}h1{margin:.67em 0}b,strong{font-weight:700}dfn{font-style:italic}hr{height:0;-moz-box-sizing:content-box;box-sizing:content-box}mark{color:#000;background:#ff0}code,kbd,pre,samp{font-family:monospace,serif;font-size:1em}pre{white-space:pre-wrap}q{quotes:"\201C" "\201D" "\2018" "\2019"}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:0}button,input,select,textarea{margin:0}button,select{text-transform:none}button,html input[type=button],input[type=reset],input[type=submit]{cursor:pointer;-webkit-appearance:button}button[disabled],html input[disabled]{cursor:default}input[type=checkbox],input[type=radio]{padding:0;box-sizing:border-box}input[type=search]{-webkit-appearance:textfield}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}button::-moz-focus-inner,input::-moz-focus-inner{padding:0;border:0}textarea{overflow:auto;vertical-align:top}table{border-collapse:collapse;border-spacing:0}@media print{*{color:#000!important;text-shadow:none!important;background:transparent!important;box-shadow:none!important}a,a:visited{text-decoration:underline}a[href]:after{content:" (" attr(href) ")"}abbr[title]:after{content:" (" attr(title) ")"}.ir a:after,a[href^="javascript:"]:after,a[href^="#"]:after{content:""}blockquote,pre{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}img,tr{page-break-inside:avoid}img{max-width:100%!important}@page{margin:2cm .5cm}h2,h3,p{orphans:3;widows:3}h2,h3{page-break-after:avoid}.navbar{display:none}.table td,.table th{background-color:#fff!important}.btn>.caret,.dropup>.btn>.caret{border-top-color:#000!important}.label{border:1px solid #000}.table{border-collapse:collapse!important}.table-bordered td,.table-bordered th{border:1px solid #ddd!important}}*,:after,:before{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}html{font-size:62.5%;-webkit-tap-highlight-color:rgba(0,0,0,0)}body{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;line-height:1.428571429;color:#333;background-color:#fff}button,input,select,textarea{font-family:inherit;font-size:inherit;line-height:inherit}button,input,select[multiple],textarea{background-image:none}a{color:#428bca;text-decoration:none}a:focus,a:hover{color:#2a6496;text-decoration:underline}a:focus{outline-offset:-2px}img{vertical-align:middle}.img-responsive{display:block;height:auto;max-width:100%}.img-rounded{border-radius:6px}.img-thumbnail{display:inline-block;height:auto;max-width:100%;padding:4px;line-height:1.428571429;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:all .2s ease-in-out;transition:all .2s ease-in-out}.img-circle{border-radius:50%}hr{margin-top:20px;margin-bottom:20px;border:0;border-top:1px solid #eee}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);border:0}p{margin:0 0 10px}.lead{margin-bottom:20px;font-size:16.1px;font-weight:200;line-height:1.4}@media(min-width:768px){.lead{font-size:21px}}small{font-size:85%}cite{font-style:normal}.text-muted{color:#999}.text-primary{color:#428bca}.text-warning{color:#c09853}.text-danger{color:#b94a48}.text-success{color:#468847}.text-info{color:#3a87ad}.text-left{text-align:left}.text-right{text-align:right}.text-center{text-align:center}.h1,.h2,.h3,.h4,.h5,.h6,h1,h2,h3,h4,h5,h6{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-weight:500;line-height:1.1}.h1 small,.h2 small,.h3 small,.h4 small,.h5 small,.h6 small,h1 small,h2 small,h3 small,h4 small,h5 small,h6 small{font-weight:400;line-height:1;color:#999}h1,h2,h3{margin-top:20px;margin-bottom:10px}h4,h5,h6{margin-top:10px;margin-bottom:10px}.h1,h1{font-size:36px}.h2,h2{font-size:30px}.h3,h3{font-size:24px}.h4,h4{font-size:18px}.h5,h5{font-size:14px}.h6,h6{font-size:12px}.h1 small,h1 small{font-size:24px}.h2 small,h2 small{font-size:18px}.h3 small,.h4 small,h3 small,h4 small{font-size:14px}.page-header{padding-bottom:9px;margin:40px 0 20px;border-bottom:1px solid #eee}ol,ul{margin-top:0;margin-bottom:10px}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}.list-inline,.list-unstyled{padding-left:0;list-style:none}.list-inline>li{display:inline-block;padding-right:5px;padding-left:5px}dl{margin-bottom:20px}dd,dt{line-height:1.428571429}dt{font-weight:700}dd{margin-left:0}@media(min-width:768px){.dl-horizontal dt{float:left;width:160px;overflow:hidden;clear:left;text-align:right;text-overflow:ellipsis;white-space:nowrap}.dl-horizontal dd{margin-left:180px}.dl-horizontal dd:after,.dl-horizontal dd:before{display:table;content:" "}.dl-horizontal dd:after{clear:both}}abbr[data-original-title],abbr[title]{cursor:help;border-bottom:1px dotted #999}abbr.initialism{font-size:90%;text-transform:uppercase}blockquote{padding:10px 20px;margin:0 0 20px;border-left:5px solid #eee}blockquote p{font-size:17.5px;font-weight:300;line-height:1.25}blockquote p:last-child{margin-bottom:0}blockquote small{display:block;line-height:1.428571429;color:#999}blockquote small:before{content:'\2014 \00A0'}blockquote.pull-right{padding-right:15px;padding-left:0;border-right:5px solid #eee;border-left:0}blockquote.pull-right p,blockquote.pull-right small{text-align:right}blockquote.pull-right small:before{content:''}blockquote.pull-right small:after{content:'\00A0 \2014'}blockquote:after,blockquote:before,q:after,q:before{content:""}address{display:block;margin-bottom:20px;font-style:normal;line-height:1.428571429}code,pre{font-family:Monaco,Menlo,Consolas,"Courier New",monospace}code{padding:2px 4px;font-size:90%;color:#c7254e;white-space:nowrap;background-color:#f9f2f4;border-radius:4px}pre{display:block;padding:9.5px;margin:0 0 10px;font-size:13px;line-height:1.428571429;color:#333;word-break:break-all;word-wrap:break-word;background-color:#f5f5f5;border:1px solid #ccc;border-radius:4px}pre.prettyprint{margin-bottom:20px}pre code{padding:0;font-size:inherit;color:inherit;white-space:pre-wrap;background-color:transparent;border:0}.pre-scrollable{max-height:340px;overflow-y:scroll}.container{padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}.container:after,.container:before{display:table;content:" "}.container:after{clear:both}.row{margin-right:-15px;margin-left:-15px}.row:after,.row:before{display:table;content:" "}.row:after{clear:both}.col-lg-1,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-md-1,.col-md-10,.col-md-11,.col-md-12,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-sm-1,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-xs-1,.col-xs-10,.col-xs-11,.col-xs-12,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9{position:relative;min-height:1px;padding-right:15px;padding-left:15px}.col-xs-1,.col-xs-10,.col-xs-11,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9{float:left}.col-xs-1{width:8.333333333333332%}.col-xs-2{width:16.666666666666664%}.col-xs-3{width:25%}.col-xs-4{width:33.33333333333333%}.col-xs-5{width:41.66666666666667%}.col-xs-6{width:50%}.col-xs-7{width:58.333333333333336%}.col-xs-8{width:66.66666666666666%}.col-xs-9{width:75%}.col-xs-10{width:83.33333333333334%}.col-xs-11{width:91.66666666666666%}.col-xs-12{width:100%}@media(min-width:768px){.container{max-width:750px}.col-sm-1,.col-sm-10,.col-sm-11,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9{float:left}.col-sm-1{width:8.333333333333332%}.col-sm-2{width:16.666666666666664%}.col-sm-3{width:25%}.col-sm-4{width:33.33333333333333%}.col-sm-5{width:41.66666666666667%}.col-sm-6{width:50%}.col-sm-7{width:58.333333333333336%}.col-sm-8{width:66.66666666666666%}.col-sm-9{width:75%}.col-sm-10{width:83.33333333333334%}.col-sm-11{width:91.66666666666666%}.col-sm-12{width:100%}.col-sm-push-1{left:8.333333333333332%}.col-sm-push-2{left:16.666666666666664%}.col-sm-push-3{left:25%}.col-sm-push-4{left:33.33333333333333%}.col-sm-push-5{left:41.66666666666667%}.col-sm-push-6{left:50%}.col-sm-push-7{left:58.333333333333336%}.col-sm-push-8{left:66.66666666666666%}.col-sm-push-9{left:75%}.col-sm-push-10{left:83.33333333333334%}.col-sm-push-11{left:91.66666666666666%}.col-sm-pull-1{right:8.333333333333332%}.col-sm-pull-2{right:16.666666666666664%}.col-sm-pull-3{right:25%}.col-sm-pull-4{right:33.33333333333333%}.col-sm-pull-5{right:41.66666666666667%}.col-sm-pull-6{right:50%}.col-sm-pull-7{right:58.333333333333336%}.col-sm-pull-8{right:66.66666666666666%}.col-sm-pull-9{right:75%}.col-sm-pull-10{right:83.33333333333334%}.col-sm-pull-11{right:91.66666666666666%}.col-sm-offset-1{margin-left:8.333333333333332%}.col-sm-offset-2{margin-left:16.666666666666664%}.col-sm-offset-3{margin-left:25%}.col-sm-offset-4{margin-left:33.33333333333333%}.col-sm-offset-5{margin-left:41.66666666666667%}.col-sm-offset-6{margin-left:50%}.col-sm-offset-7{margin-left:58.333333333333336%}.col-sm-offset-8{margin-left:66.66666666666666%}.col-sm-offset-9{margin-left:75%}.col-sm-offset-10{margin-left:83.33333333333334%}.col-sm-offset-11{margin-left:91.66666666666666%}}@media(min-width:992px){.container{max-width:970px}.col-md-1,.col-md-10,.col-md-11,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9{float:left}.col-md-1{width:8.333333333333332%}.col-md-2{width:16.666666666666664%}.col-md-3{width:25%}.col-md-4{width:33.33333333333333%}.col-md-5{width:41.66666666666667%}.col-md-6{width:50%}.col-md-7{width:58.333333333333336%}.col-md-8{width:66.66666666666666%}.col-md-9{width:75%}.col-md-10{width:83.33333333333334%}.col-md-11{width:91.66666666666666%}.col-md-12{width:100%}.col-md-push-0{left:auto}.col-md-push-1{left:8.333333333333332%}.col-md-push-2{left:16.666666666666664%}.col-md-push-3{left:25%}.col-md-push-4{left:33.33333333333333%}.col-md-push-5{left:41.66666666666667%}.col-md-push-6{left:50%}.col-md-push-7{left:58.333333333333336%}.col-md-push-8{left:66.66666666666666%}.col-md-push-9{left:75%}.col-md-push-10{left:83.33333333333334%}.col-md-push-11{left:91.66666666666666%}.col-md-pull-0{right:auto}.col-md-pull-1{right:8.333333333333332%}.col-md-pull-2{right:16.666666666666664%}.col-md-pull-3{right:25%}.col-md-pull-4{right:33.33333333333333%}.col-md-pull-5{right:41.66666666666667%}.col-md-pull-6{right:50%}.col-md-pull-7{right:58.333333333333336%}.col-md-pull-8{right:66.66666666666666%}.col-md-pull-9{right:75%}.col-md-pull-10{right:83.33333333333334%}.col-md-pull-11{right:91.66666666666666%}.col-md-offset-0{margin-left:0}.col-md-offset-1{margin-left:8.333333333333332%}.col-md-offset-2{margin-left:16.666666666666664%}.col-md-offset-3{margin-left:25%}.col-md-offset-4{margin-left:33.33333333333333%}.col-md-offset-5{margin-left:41.66666666666667%}.col-md-offset-6{margin-left:50%}.col-md-offset-7{margin-left:58.333333333333336%}.col-md-offset-8{margin-left:66.66666666666666%}.col-md-offset-9{margin-left:75%}.col-md-offset-10{margin-left:83.33333333333334%}.col-md-offset-11{margin-left:91.66666666666666%}}@media(min-width:1200px){.container{max-width:1170px}.col-lg-1,.col-lg-10,.col-lg-11,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9{float:left}.col-lg-1{width:8.333333333333332%}.col-lg-2{width:16.666666666666664%}.col-lg-3{width:25%}.col-lg-4{width:33.33333333333333%}.col-lg-5{width:41.66666666666667%}.col-lg-6{width:50%}.col-lg-7{width:58.333333333333336%}.col-lg-8{width:66.66666666666666%}.col-lg-9{width:75%}.col-lg-10{width:83.33333333333334%}.col-lg-11{width:91.66666666666666%}.col-lg-12{width:100%}.col-lg-push-0{left:auto}.col-lg-push-1{left:8.333333333333332%}.col-lg-push-2{left:16.666666666666664%}.col-lg-push-3{left:25%}.col-lg-push-4{left:33.33333333333333%}.col-lg-push-5{left:41.66666666666667%}.col-lg-push-6{left:50%}.col-lg-push-7{left:58.333333333333336%}.col-lg-push-8{left:66.66666666666666%}.col-lg-push-9{left:75%}.col-lg-push-10{left:83.33333333333334%}.col-lg-push-11{left:91.66666666666666%}.col-lg-pull-0{right:auto}.col-lg-pull-1{right:8.333333333333332%}.col-lg-pull-2{right:16.666666666666664%}.col-lg-pull-3{right:25%}.col-lg-pull-4{right:33.33333333333333%}.col-lg-pull-5{right:41.66666666666667%}.col-lg-pull-6{right:50%}.col-lg-pull-7{right:58.333333333333336%}.col-lg-pull-8{right:66.66666666666666%}.col-lg-pull-9{right:75%}.col-lg-pull-10{right:83.33333333333334%}.col-lg-pull-11{right:91.66666666666666%}.col-lg-offset-0{margin-left:0}.col-lg-offset-1{margin-left:8.333333333333332%}.col-lg-offset-2{margin-left:16.666666666666664%}.col-lg-offset-3{margin-left:25%}.col-lg-offset-4{margin-left:33.33333333333333%}.col-lg-offset-5{margin-left:41.66666666666667%}.col-lg-offset-6{margin-left:50%}.col-lg-offset-7{margin-left:58.333333333333336%}.col-lg-offset-8{margin-left:66.66666666666666%}.col-lg-offset-9{margin-left:75%}.col-lg-offset-10{margin-left:83.33333333333334%}.col-lg-offset-11{margin-left:91.66666666666666%}}table{max-width:100%;background-color:transparent}th{text-align:left}.table{width:100%;margin-bottom:20px}.table tbody>tr>td,.table tbody>tr>th,.table tfoot>tr>td,.table tfoot>tr>th,.table thead>tr>td,.table thead>tr>th{padding:8px;line-height:1.428571429;vertical-align:top;border-top:1px solid #ddd}.table thead>tr>th{vertical-align:bottom;border-bottom:2px solid #ddd}.table caption+thead tr:first-child td,.table caption+thead tr:first-child th,.table colgroup+thead tr:first-child td,.table colgroup+thead tr:first-child th,.table thead:first-child tr:first-child td,.table thead:first-child tr:first-child th{border-top:0}.table tbody+tbody{border-top:2px solid #ddd}.table .table{background-color:#fff}.table-condensed tbody>tr>td,.table-condensed tbody>tr>th,.table-condensed tfoot>tr>td,.table-condensed tfoot>tr>th,.table-condensed thead>tr>td,.table-condensed thead>tr>th{padding:5px}.table-bordered,.table-bordered>tbody>tr>td,.table-bordered>tbody>tr>th,.table-bordered>tfoot>tr>td,.table-bordered>tfoot>tr>th,.table-bordered>thead>tr>td,.table-bordered>thead>tr>th{border:1px solid #ddd}.table-bordered>thead>tr>td,.table-bordered>thead>tr>th{border-bottom-width:2px}.table-striped>tbody>tr:nth-child(odd)>td,.table-striped>tbody>tr:nth-child(odd)>th{background-color:#f9f9f9}.table-hover>tbody>tr:hover>td,.table-hover>tbody>tr:hover>th{background-color:#f5f5f5}table col[class*=col-]{display:table-column;float:none}table td[class*=col-],table th[class*=col-]{display:table-cell;float:none}.table>tbody>tr.active>td,.table>tbody>tr.active>th,.table>tbody>tr>td.active,.table>tbody>tr>th.active,.table>tfoot>tr.active>td,.table>tfoot>tr.active>th,.table>tfoot>tr>td.active,.table>tfoot>tr>th.active,.table>thead>tr.active>td,.table>thead>tr.active>th,.table>thead>tr>td.active,.table>thead>tr>th.active{background-color:#f5f5f5}.table>tbody>tr.success>td,.table>tbody>tr.success>th,.table>tbody>tr>td.success,.table>tbody>tr>th.success,.table>tfoot>tr.success>td,.table>tfoot>tr.success>th,.table>tfoot>tr>td.success,.table>tfoot>tr>th.success,.table>thead>tr.success>td,.table>thead>tr.success>th,.table>thead>tr>td.success,.table>thead>tr>th.success{background-color:#dff0d8;border-color:#d6e9c6}.table-hover>tbody>tr.success:hover>td,.table-hover>tbody>tr>td.success:hover,.table-hover>tbody>tr>th.success:hover{background-color:#d0e9c6;border-color:#c9e2b3}.table>tbody>tr.danger>td,.table>tbody>tr.danger>th,.table>tbody>tr>td.danger,.table>tbody>tr>th.danger,.table>tfoot>tr.danger>td,.table>tfoot>tr.danger>th,.table>tfoot>tr>td.danger,.table>tfoot>tr>th.danger,.table>thead>tr.danger>td,.table>thead>tr.danger>th,.table>thead>tr>td.danger,.table>thead>tr>th.danger{background-color:#f2dede;border-color:#eed3d7}.table-hover>tbody>tr.danger:hover>td,.table-hover>tbody>tr>td.danger:hover,.table-hover>tbody>tr>th.danger:hover{background-color:#ebcccc;border-color:#e6c1c7}.table>tbody>tr.warning>td,.table>tbody>tr.warning>th,.table>tbody>tr>td.warning,.table>tbody>tr>th.warning,.table>tfoot>tr.warning>td,.table>tfoot>tr.warning>th,.table>tfoot>tr>td.warning,.table>tfoot>tr>th.warning,.table>thead>tr.warning>td,.table>thead>tr.warning>th,.table>thead>tr>td.warning,.table>thead>tr>th.warning{background-color:#fcf8e3;border-color:#fbeed5}.table-hover>tbody>tr.warning:hover>td,.table-hover>tbody>tr>td.warning:hover,.table-hover>tbody>tr>th.warning:hover{background-color:#faf2cc;border-color:#f8e5be}@media(max-width:768px){.table-responsive{width:100%;margin-bottom:15px;overflow-x:scroll;overflow-y:hidden;border:1px solid #ddd}.table-responsive>.table{margin-bottom:0;background-color:#fff}.table-responsive>.table>tbody>tr>td,.table-responsive>.table>tbody>tr>th,.table-responsive>.table>tfoot>tr>td,.table-responsive>.table>tfoot>tr>th,.table-responsive>.table>thead>tr>td,.table-responsive>.table>thead>tr>th{white-space:nowrap}.table-responsive>.table-bordered{border:0}.table-responsive>.table-bordered>tbody>tr>td:first-child,.table-responsive>.table-bordered>tbody>tr>th:first-child,.table-responsive>.table-bordered>tfoot>tr>td:first-child,.table-responsive>.table-bordered>tfoot>tr>th:first-child,.table-responsive>.table-bordered>thead>tr>td:first-child,.table-responsive>.table-bordered>thead>tr>th:first-child{border-left:0}.table-responsive>.table-bordered>tbody>tr>td:last-child,.table-responsive>.table-bordered>tbody>tr>th:last-child,.table-responsive>.table-bordered>tfoot>tr>td:last-child,.table-responsive>.table-bordered>tfoot>tr>th:last-child,.table-responsive>.table-bordered>thead>tr>td:last-child,.table-responsive>.table-bordered>thead>tr>th:last-child{border-right:0}.table-responsive>.table-bordered>tbody>tr:last-child>td,.table-responsive>.table-bordered>tbody>tr:last-child>th,.table-responsive>.table-bordered>tfoot>tr:last-child>td,.table-responsive>.table-bordered>tfoot>tr:last-child>th,.table-responsive>.table-bordered>thead>tr:last-child>td,.table-responsive>.table-bordered>thead>tr:last-child>th{border-bottom:0}}fieldset{padding:0;margin:0;border:0}legend{display:block;width:100%;padding:0;margin-bottom:20px;font-size:21px;line-height:inherit;color:#333;border:0;border-bottom:1px solid #e5e5e5}label{display:inline-block;margin-bottom:5px;font-weight:700}input[type=search]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}input[type=checkbox],input[type=radio]{margin:4px 0 0;line-height:normal}input[type=file]{display:block}select[multiple],select[size]{height:auto}select optgroup{font-family:inherit;font-size:inherit;font-style:inherit}input[type=checkbox]:focus,input[type=file]:focus,input[type=radio]:focus{outline:thin dotted #333;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}input[type=number]::-webkit-inner-spin-button,input[type=number]::-webkit-outer-spin-button{height:auto}.form-control:-moz-placeholder{color:#999}.form-control::-moz-placeholder{color:#999}.form-control:-ms-input-placeholder{color:#999}.form-control::-webkit-input-placeholder{color:#999}.form-control{display:block;width:100%;height:34px;padding:6px 12px;font-size:14px;line-height:1.428571429;color:#555;vertical-align:middle;background-color:#fff;border:1px solid #ccc;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075);-webkit-transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s}.form-control:focus{border-color:#66afe9;outline:0;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6);box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6)}.form-control[disabled],.form-control[readonly],fieldset[disabled] .form-control{cursor:not-allowed;background-color:#eee}textarea.form-control{height:auto}.checkbox,.radio{display:block;min-height:20px;padding-left:20px;margin-top:10px;margin-bottom:10px;vertical-align:middle}.checkbox label,.radio label{display:inline;margin-bottom:0;font-weight:400;cursor:pointer}.checkbox input[type=checkbox],.checkbox-inline input[type=checkbox],.radio input[type=radio],.radio-inline input[type=radio]{float:left;margin-left:-20px}.checkbox+.checkbox,.radio+.radio{margin-top:-5px}.checkbox-inline,.radio-inline{display:inline-block;padding-left:20px;margin-bottom:0;font-weight:400;vertical-align:middle;cursor:pointer}.checkbox-inline+.checkbox-inline,.radio-inline+.radio-inline{margin-top:0;margin-left:10px}.checkbox-inline[disabled],.checkbox[disabled],.radio-inline[disabled],.radio[disabled],fieldset[disabled] .checkbox,fieldset[disabled] .checkbox-inline,fieldset[disabled] .radio,fieldset[disabled] .radio-inline,fieldset[disabled] input[type=checkbox],fieldset[disabled] input[type=radio],input[type=checkbox][disabled],input[type=radio][disabled]{cursor:not-allowed}.input-sm{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-sm{height:30px;line-height:30px}textarea.input-sm{height:auto}.input-lg{height:45px;padding:10px 16px;font-size:18px;line-height:1.33;border-radius:6px}select.input-lg{height:45px;line-height:45px}textarea.input-lg{height:auto}.has-warning .control-label,.has-warning .help-block{color:#c09853}.has-warning .form-control{border-color:#c09853;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-warning .form-control:focus{border-color:#a47e3c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #dbc59e;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #dbc59e}.has-warning .input-group-addon{color:#c09853;background-color:#fcf8e3;border-color:#c09853}.has-error .control-label,.has-error .help-block{color:#b94a48}.has-error .form-control{border-color:#b94a48;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-error .form-control:focus{border-color:#953b39;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #d59392;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #d59392}.has-error .input-group-addon{color:#b94a48;background-color:#f2dede;border-color:#b94a48}.has-success .control-label,.has-success .help-block{color:#468847}.has-success .form-control{border-color:#468847;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-success .form-control:focus{border-color:#356635;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #7aba7b;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #7aba7b}.has-success .input-group-addon{color:#468847;background-color:#dff0d8;border-color:#468847}.form-control-static{padding-top:7px;margin-bottom:0}.help-block{display:block;margin-top:5px;margin-bottom:10px;color:#737373}@media(min-width:768px){.form-inline .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.form-inline .form-control{display:inline-block}.form-inline .checkbox,.form-inline .radio{display:inline-block;padding-left:0;margin-top:0;margin-bottom:0}.form-inline .checkbox input[type=checkbox],.form-inline .radio input[type=radio]{float:none;margin-left:0}}.form-horizontal .checkbox,.form-horizontal .checkbox-inline,.form-horizontal .control-label,.form-horizontal .radio,.form-horizontal .radio-inline{padding-top:7px;margin-top:0;margin-bottom:0}.form-horizontal .form-group{margin-right:-15px;margin-left:-15px}.form-horizontal .form-group:after,.form-horizontal .form-group:before{display:table;content:" "}.form-horizontal .form-group:after{clear:both}@media(min-width:768px){.form-horizontal .control-label{text-align:right}}.btn{display:inline-block;padding:6px 12px;margin-bottom:0;font-size:14px;font-weight:400;line-height:1.428571429;text-align:center;white-space:nowrap;vertical-align:middle;cursor:pointer;border:1px solid transparent;border-radius:4px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;-o-user-select:none;user-select:none}.btn:focus{outline:thin dotted #333;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.btn:focus,.btn:hover{color:#333;text-decoration:none}.btn.active,.btn:active{outline:0;-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn.disabled,.btn[disabled],fieldset[disabled] .btn{pointer-events:none;cursor:not-allowed;opacity:.65;filter:alpha(opacity=65);-webkit-box-shadow:none;box-shadow:none}.btn-default{color:#333;background-color:#fff}.btn-default.active,.btn-default:active,.btn-default:focus,.btn-default:hover,.open .dropdown-toggle.btn-default{color:#333;background-color:#ebebeb;border-color:#adadad}.btn-default.active,.btn-default:active,.open .dropdown-toggle.btn-default{background-image:none}.btn-default.disabled,.btn-default.disabled.active,.btn-default.disabled:active,.btn-default.disabled:focus,.btn-default.disabled:hover,.btn-default[disabled],.btn-default[disabled].active,.btn-default[disabled]:active,.btn-default[disabled]:focus,.btn-default[disabled]:hover,fieldset[disabled] .btn-default,fieldset[disabled] .btn-default.active,fieldset[disabled] .btn-default:active,fieldset[disabled] .btn-default:focus,fieldset[disabled] .btn-default:hover{background-color:#fff;border-color:#ccc}.btn-primary{color:#fff;background-color:#428bca}.btn-primary.active,.btn-primary:active,.btn-primary:focus,.btn-primary:hover,.open .dropdown-toggle.btn-primary{color:#fff;background-color:#3276b1;border-color:#285e8e}.btn-primary.active,.btn-primary:active,.open .dropdown-toggle.btn-primary{background-image:none}.btn-primary.disabled,.btn-primary.disabled.active,.btn-primary.disabled:active,.btn-primary.disabled:focus,.btn-primary.disabled:hover,.btn-primary[disabled],.btn-primary[disabled].active,.btn-primary[disabled]:active,.btn-primary[disabled]:focus,.btn-primary[disabled]:hover,fieldset[disabled] .btn-primary,fieldset[disabled] .btn-primary.active,fieldset[disabled] .btn-primary:active,fieldset[disabled] .btn-primary:focus,fieldset[disabled] .btn-primary:hover{background-color:#428bca;border-color:#357ebd}.btn-warning{color:#fff;background-color:#f0ad4e}.btn-warning.active,.btn-warning:active,.btn-warning:focus,.btn-warning:hover,.open .dropdown-toggle.btn-warning{color:#fff;background-color:#ed9c28;border-color:#d58512}.btn-warning.active,.btn-warning:active,.open .dropdown-toggle.btn-warning{background-image:none}.btn-warning.disabled,.btn-warning.disabled.active,.btn-warning.disabled:active,.btn-warning.disabled:focus,.btn-warning.disabled:hover,.btn-warning[disabled],.btn-warning[disabled].active,.btn-warning[disabled]:active,.btn-warning[disabled]:focus,.btn-warning[disabled]:hover,fieldset[disabled] .btn-warning,fieldset[disabled] .btn-warning.active,fieldset[disabled] .btn-warning:active,fieldset[disabled] .btn-warning:focus,fieldset[disabled] .btn-warning:hover{background-color:#f0ad4e;border-color:#eea236}.btn-danger{color:#fff;background-color:#d9534f}.btn-danger.active,.btn-danger:active,.btn-danger:focus,.btn-danger:hover,.open .dropdown-toggle.btn-danger{color:#fff;background-color:#d2322d;border-color:#ac2925}.btn-danger.active,.btn-danger:active,.open .dropdown-toggle.btn-danger{background-image:none}.btn-danger.disabled,.btn-danger.disabled.active,.btn-danger.disabled:active,.btn-danger.disabled:focus,.btn-danger.disabled:hover,.btn-danger[disabled],.btn-danger[disabled].active,.btn-danger[disabled]:active,.btn-danger[disabled]:focus,.btn-danger[disabled]:hover,fieldset[disabled] .btn-danger,fieldset[disabled] .btn-danger.active,fieldset[disabled] .btn-danger:active,fieldset[disabled] .btn-danger:focus,fieldset[disabled] .btn-danger:hover{background-color:#d9534f;border-color:#d43f3a}.btn-success{color:#fff;background-color:#5cb85c}.btn-success.active,.btn-success:active,.btn-success:focus,.btn-success:hover,.open .dropdown-toggle.btn-success{color:#fff;background-color:#47a447;border-color:#398439}.btn-success.active,.btn-success:active,.open .dropdown-toggle.btn-success{background-image:none}.btn-success.disabled,.btn-success.disabled.active,.btn-success.disabled:active,.btn-success.disabled:focus,.btn-success.disabled:hover,.btn-success[disabled],.btn-success[disabled].active,.btn-success[disabled]:active,.btn-success[disabled]:focus,.btn-success[disabled]:hover,fieldset[disabled] .btn-success,fieldset[disabled] .btn-success.active,fieldset[disabled] .btn-success:active,fieldset[disabled] .btn-success:focus,fieldset[disabled] .btn-success:hover{background-color:#5cb85c;border-color:#4cae4c}.btn-info{color:#fff;background-color:#5bc0de}.btn-info.active,.btn-info:active,.btn-info:focus,.btn-info:hover,.open .dropdown-toggle.btn-info{color:#fff;background-color:#39b3d7;border-color:#269abc}.btn-info.active,.btn-info:active,.open .dropdown-toggle.btn-info{background-image:none}.btn-info.disabled,.btn-info.disabled.active,.btn-info.disabled:active,.btn-info.disabled:focus,.btn-info.disabled:hover,.btn-info[disabled],.btn-info[disabled].active,.btn-info[disabled]:active,.btn-info[disabled]:focus,.btn-info[disabled]:hover,fieldset[disabled] .btn-info,fieldset[disabled] .btn-info.active,fieldset[disabled] .btn-info:active,fieldset[disabled] .btn-info:focus,fieldset[disabled] .btn-info:hover{background-color:#5bc0de;border-color:#46b8da}.btn-link{font-weight:400;color:#428bca;cursor:pointer;border-radius:0}.btn-link,.btn-link:active,.btn-link[disabled],fieldset[disabled] .btn-link{background-color:transparent;-webkit-box-shadow:none;box-shadow:none}.btn-link,.btn-link:active,.btn-link:focus,.btn-link:hover{border-color:transparent}.btn-link:focus,.btn-link:hover{color:#2a6496;text-decoration:underline;background-color:transparent}.btn-link[disabled]:focus,.btn-link[disabled]:hover,fieldset[disabled] .btn-link:focus,fieldset[disabled] .btn-link:hover{color:#999;text-decoration:none}.btn-lg{padding:10px 16px;font-size:18px;line-height:1.33;border-radius:6px}.btn-sm,.btn-xs{padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.btn-xs{padding:1px 5px}.btn-block{display:block;width:100%;padding-right:0;padding-left:0}.btn-block+.btn-block{margin-top:5px}input[type=button].btn-block,input[type=reset].btn-block,input[type=submit].btn-block{width:100%}.fade{opacity:0;-webkit-transition:opacity .15s linear;transition:opacity .15s linear}.fade.in{opacity:1}.collapse{display:none}.collapse.in{display:block}.collapsing{position:relative;height:0;overflow:hidden;-webkit-transition:height .35s ease;transition:height .35s ease}@font-face{font-family:'Glyphicons Halflings';src:url(../fonts/glyphicons-halflings-regular.eot);src:url(../fonts/glyphicons-halflings-regular.eot?#iefix) format('embedded-opentype'),url(../fonts/glyphicons-halflings-regular.woff) format('woff'),url(../fonts/glyphicons-halflings-regular.ttf) format('truetype'),url(../fonts/glyphicons-halflings-regular.svg#glyphicons-halflingsregular) format('svg')}.glyphicon{position:relative;top:1px;display:inline-block;font-family:'Glyphicons Halflings';-webkit-font-smoothing:antialiased;font-style:normal;font-weight:400;line-height:1}.glyphicon-asterisk:before{content:"\2a"}.glyphicon-plus:before{content:"\2b"}.glyphicon-euro:before{content:"\20ac"}.glyphicon-minus:before{content:"\2212"}.glyphicon-cloud:before{content:"\2601"}.glyphicon-envelope:before{content:"\2709"}.glyphicon-pencil:before{content:"\270f"}.glyphicon-glass:before{content:"\e001"}.glyphicon-music:before{content:"\e002"}.glyphicon-search:before{content:"\e003"}.glyphicon-heart:before{content:"\e005"}.glyphicon-star:before{content:"\e006"}.glyphicon-star-empty:before{content:"\e007"}.glyphicon-user:before{content:"\e008"}.glyphicon-film:before{content:"\e009"}.glyphicon-th-large:before{content:"\e010"}.glyphicon-th:before{content:"\e011"}.glyphicon-th-list:before{content:"\e012"}.glyphicon-ok:before{content:"\e013"}.glyphicon-remove:before{content:"\e014"}.glyphicon-zoom-in:before{content:"\e015"}.glyphicon-zoom-out:before{content:"\e016"}.glyphicon-off:before{content:"\e017"}.glyphicon-signal:before{content:"\e018"}.glyphicon-cog:before{content:"\e019"}.glyphicon-trash:before{content:"\e020"}.glyphicon-home:before{content:"\e021"}.glyphicon-file:before{content:"\e022"}.glyphicon-time:before{content:"\e023"}.glyphicon-road:before{content:"\e024"}.glyphicon-download-alt:before{content:"\e025"}.glyphicon-download:before{content:"\e026"}.glyphicon-upload:before{content:"\e027"}.glyphicon-inbox:before{content:"\e028"}.glyphicon-play-circle:before{content:"\e029"}.glyphicon-repeat:before{content:"\e030"}.glyphicon-refresh:before{content:"\e031"}.glyphicon-list-alt:before{content:"\e032"}.glyphicon-flag:before{content:"\e034"}.glyphicon-headphones:before{content:"\e035"}.glyphicon-volume-off:before{content:"\e036"}.glyphicon-volume-down:before{content:"\e037"}.glyphicon-volume-up:before{content:"\e038"}.glyphicon-qrcode:before{content:"\e039"}.glyphicon-barcode:before{content:"\e040"}.glyphicon-tag:before{content:"\e041"}.glyphicon-tags:before{content:"\e042"}.glyphicon-book:before{content:"\e043"}.glyphicon-print:before{content:"\e045"}.glyphicon-font:before{content:"\e047"}.glyphicon-bold:before{content:"\e048"}.glyphicon-italic:before{content:"\e049"}.glyphicon-text-height:before{content:"\e050"}.glyphicon-text-width:before{content:"\e051"}.glyphicon-align-left:before{content:"\e052"}.glyphicon-align-center:before{content:"\e053"}.glyphicon-align-right:before{content:"\e054"}.glyphicon-align-justify:before{content:"\e055"}.glyphicon-list:before{content:"\e056"}.glyphicon-indent-left:before{content:"\e057"}.glyphicon-indent-right:before{content:"\e058"}.glyphicon-facetime-video:before{content:"\e059"}.glyphicon-picture:before{content:"\e060"}.glyphicon-map-marker:before{content:"\e062"}.glyphicon-adjust:before{content:"\e063"}.glyphicon-tint:before{content:"\e064"}.glyphicon-edit:before{content:"\e065"}.glyphicon-share:before{content:"\e066"}.glyphicon-check:before{content:"\e067"}.glyphicon-move:before{content:"\e068"}.glyphicon-step-backward:before{content:"\e069"}.glyphicon-fast-backward:before{content:"\e070"}.glyphicon-backward:before{content:"\e071"}.glyphicon-play:before{content:"\e072"}.glyphicon-pause:before{content:"\e073"}.glyphicon-stop:before{content:"\e074"}.glyphicon-forward:before{content:"\e075"}.glyphicon-fast-forward:before{content:"\e076"}.glyphicon-step-forward:before{content:"\e077"}.glyphicon-eject:before{content:"\e078"}.glyphicon-chevron-left:before{content:"\e079"}.glyphicon-chevron-right:before{content:"\e080"}.glyphicon-plus-sign:before{content:"\e081"}.glyphicon-minus-sign:before{content:"\e082"}.glyphicon-remove-sign:before{content:"\e083"}.glyphicon-ok-sign:before{content:"\e084"}.glyphicon-question-sign:before{content:"\e085"}.glyphicon-info-sign:before{content:"\e086"}.glyphicon-screenshot:before{content:"\e087"}.glyphicon-remove-circle:before{content:"\e088"}.glyphicon-ok-circle:before{content:"\e089"}.glyphicon-ban-circle:before{content:"\e090"}.glyphicon-arrow-left:before{content:"\e091"}.glyphicon-arrow-right:before{content:"\e092"}.glyphicon-arrow-up:before{content:"\e093"}.glyphicon-arrow-down:before{content:"\e094"}.glyphicon-share-alt:before{content:"\e095"}.glyphicon-resize-full:before{content:"\e096"}.glyphicon-resize-small:before{content:"\e097"}.glyphicon-exclamation-sign:before{content:"\e101"}.glyphicon-gift:before{content:"\e102"}.glyphicon-leaf:before{content:"\e103"}.glyphicon-eye-open:before{content:"\e105"}.glyphicon-eye-close:before{content:"\e106"}.glyphicon-warning-sign:before{content:"\e107"}.glyphicon-plane:before{content:"\e108"}.glyphicon-random:before{content:"\e110"}.glyphicon-comment:before{content:"\e111"}.glyphicon-magnet:before{content:"\e112"}.glyphicon-chevron-up:before{content:"\e113"}.glyphicon-chevron-down:before{content:"\e114"}.glyphicon-retweet:before{content:"\e115"}.glyphicon-shopping-cart:before{content:"\e116"}.glyphicon-folder-close:before{content:"\e117"}.glyphicon-folder-open:before{content:"\e118"}.glyphicon-resize-vertical:before{content:"\e119"}.glyphicon-resize-horizontal:before{content:"\e120"}.glyphicon-hdd:before{content:"\e121"}.glyphicon-bullhorn:before{content:"\e122"}.glyphicon-certificate:before{content:"\e124"}.glyphicon-thumbs-up:before{content:"\e125"}.glyphicon-thumbs-down:before{content:"\e126"}.glyphicon-hand-right:before{content:"\e127"}.glyphicon-hand-left:before{content:"\e128"}.glyphicon-hand-up:before{content:"\e129"}.glyphicon-hand-down:before{content:"\e130"}.glyphicon-circle-arrow-right:before{content:"\e131"}.glyphicon-circle-arrow-left:before{content:"\e132"}.glyphicon-circle-arrow-up:before{content:"\e133"}.glyphicon-circle-arrow-down:before{content:"\e134"}.glyphicon-globe:before{content:"\e135"}.glyphicon-tasks:before{content:"\e137"}.glyphicon-filter:before{content:"\e138"}.glyphicon-fullscreen:before{content:"\e140"}.glyphicon-dashboard:before{content:"\e141"}.glyphicon-heart-empty:before{content:"\e143"}.glyphicon-link:before{content:"\e144"}.glyphicon-phone:before{content:"\e145"}.glyphicon-usd:before{content:"\e148"}.glyphicon-gbp:before{content:"\e149"}.glyphicon-sort:before{content:"\e150"}.glyphicon-sort-by-alphabet:before{content:"\e151"}.glyphicon-sort-by-alphabet-alt:before{content:"\e152"}.glyphicon-sort-by-order:before{content:"\e153"}.glyphicon-sort-by-order-alt:before{content:"\e154"}.glyphicon-sort-by-attributes:before{content:"\e155"}.glyphicon-sort-by-attributes-alt:before{content:"\e156"}.glyphicon-unchecked:before{content:"\e157"}.glyphicon-expand:before{content:"\e158"}.glyphicon-collapse-down:before{content:"\e159"}.glyphicon-collapse-up:before{content:"\e160"}.glyphicon-log-in:before{content:"\e161"}.glyphicon-flash:before{content:"\e162"}.glyphicon-log-out:before{content:"\e163"}.glyphicon-new-window:before{content:"\e164"}.glyphicon-record:before{content:"\e165"}.glyphicon-save:before{content:"\e166"}.glyphicon-open:before{content:"\e167"}.glyphicon-saved:before{content:"\e168"}.glyphicon-import:before{content:"\e169"}.glyphicon-export:before{content:"\e170"}.glyphicon-send:before{content:"\e171"}.glyphicon-floppy-disk:before{content:"\e172"}.glyphicon-floppy-saved:before{content:"\e173"}.glyphicon-floppy-remove:before{content:"\e174"}.glyphicon-floppy-save:before{content:"\e175"}.glyphicon-floppy-open:before{content:"\e176"}.glyphicon-credit-card:before{content:"\e177"}.glyphicon-transfer:before{content:"\e178"}.glyphicon-cutlery:before{content:"\e179"}.glyphicon-header:before{content:"\e180"}.glyphicon-compressed:before{content:"\e181"}.glyphicon-earphone:before{content:"\e182"}.glyphicon-phone-alt:before{content:"\e183"}.glyphicon-tower:before{content:"\e184"}.glyphicon-stats:before{content:"\e185"}.glyphicon-sd-video:before{content:"\e186"}.glyphicon-hd-video:before{content:"\e187"}.glyphicon-subtitles:before{content:"\e188"}.glyphicon-sound-stereo:before{content:"\e189"}.glyphicon-sound-dolby:before{content:"\e190"}.glyphicon-sound-5-1:before{content:"\e191"}.glyphicon-sound-6-1:before{content:"\e192"}.glyphicon-sound-7-1:before{content:"\e193"}.glyphicon-copyright-mark:before{content:"\e194"}.glyphicon-registration-mark:before{content:"\e195"}.glyphicon-cloud-download:before{content:"\e197"}.glyphicon-cloud-upload:before{content:"\e198"}.glyphicon-tree-conifer:before{content:"\e199"}.glyphicon-tree-deciduous:before{content:"\e200"}.glyphicon-briefcase:before{content:"\1f4bc"}.glyphicon-calendar:before{content:"\1f4c5"}.glyphicon-pushpin:before{content:"\1f4cc"}.glyphicon-paperclip:before{content:"\1f4ce"}.glyphicon-camera:before{content:"\1f4f7"}.glyphicon-lock:before{content:"\1f512"}.glyphicon-bell:before{content:"\1f514"}.glyphicon-bookmark:before{content:"\1f516"}.glyphicon-fire:before{content:"\1f525"}.glyphicon-wrench:before{content:"\1f527"}.caret{display:inline-block;width:0;height:0;margin-left:2px;vertical-align:middle;border-top:4px solid #000;border-right:4px solid transparent;border-bottom:0 dotted;border-left:4px solid transparent;content:""}.dropdown{position:relative}.dropdown-toggle:focus{outline:0}.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:160px;padding:5px 0;margin:2px 0 0;font-size:14px;list-style:none;background-color:#fff;border:1px solid #ccc;border:1px solid rgba(0,0,0,.15);border-radius:4px;-webkit-box-shadow:0 6px 12px rgba(0,0,0,.175);box-shadow:0 6px 12px rgba(0,0,0,.175);background-clip:padding-box}.dropdown-menu.pull-right{right:0;left:auto}.dropdown-menu .divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.dropdown-menu>li>a{display:block;padding:3px 20px;clear:both;font-weight:400;line-height:1.428571429;color:#333;white-space:nowrap}.dropdown-menu>li>a:focus,.dropdown-menu>li>a:hover{color:#fff;text-decoration:none}.dropdown-menu>.active>a,.dropdown-menu>.active>a:focus,.dropdown-menu>.active>a:hover{color:#fff;text-decoration:none;outline:0}.dropdown-menu>.disabled>a,.dropdown-menu>.disabled>a:focus,.dropdown-menu>.disabled>a:hover{color:#999}.dropdown-menu>.disabled>a:focus,.dropdown-menu>.disabled>a:hover{text-decoration:none;cursor:not-allowed;background-color:transparent;background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.open>.dropdown-menu{display:block}.open>a{outline:0}.dropdown-header{display:block;padding:3px 20px;font-size:12px;line-height:1.428571429;color:#999}.dropdown-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:990}.pull-right>.dropdown-menu{right:0;left:auto}.dropup .caret,.navbar-fixed-bottom .dropdown .caret{border-top:0 dotted;border-bottom:4px solid #000;content:""}.dropup .dropdown-menu,.navbar-fixed-bottom .dropdown .dropdown-menu{top:auto;bottom:100%;margin-bottom:1px}@media(min-width:768px){.navbar-right .dropdown-menu{right:0;left:auto}}.btn-default .caret{border-top-color:#333}.btn-danger .caret,.btn-info .caret,.btn-primary .caret,.btn-success .caret,.btn-warning .caret{border-top-color:#fff}.dropup .btn-default .caret{border-bottom-color:#333}.dropup .btn-danger .caret,.dropup .btn-info .caret,.dropup .btn-primary .caret,.dropup .btn-success .caret,.dropup .btn-warning .caret{border-bottom-color:#fff}.btn-group,.btn-group-vertical{position:relative;display:inline-block;vertical-align:middle}.btn-group-vertical>.btn,.btn-group>.btn{position:relative;float:left}.btn-group-vertical>.btn.active,.btn-group-vertical>.btn:active,.btn-group-vertical>.btn:focus,.btn-group-vertical>.btn:hover,.btn-group>.btn.active,.btn-group>.btn:active,.btn-group>.btn:focus,.btn-group>.btn:hover{z-index:2}.btn-group-vertical>.btn:focus,.btn-group>.btn:focus{outline:0}.btn-group .btn+.btn,.btn-group .btn+.btn-group,.btn-group .btn-group+.btn,.btn-group .btn-group+.btn-group{margin-left:-1px}.btn-toolbar:after,.btn-toolbar:before{display:table;content:" "}.btn-toolbar:after{clear:both}.btn-toolbar .btn-group{float:left}.btn-toolbar>.btn+.btn,.btn-toolbar>.btn+.btn-group,.btn-toolbar>.btn-group+.btn,.btn-toolbar>.btn-group+.btn-group{margin-left:5px}.btn-group>.btn:not(:first-child):not(:last-child):not(.dropdown-toggle){border-radius:0}.btn-group>.btn:first-child{margin-left:0}.btn-group>.btn:first-child:not(:last-child):not(.dropdown-toggle){border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn:last-child:not(:first-child),.btn-group>.dropdown-toggle:not(:first-child){border-bottom-left-radius:0;border-top-left-radius:0}.btn-group>.btn-group{float:left}.btn-group>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group>.btn-group:first-child>.btn:last-child,.btn-group>.btn-group:first-child>.dropdown-toggle{border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn-group:last-child>.btn:first-child{border-bottom-left-radius:0;border-top-left-radius:0}.btn-group .dropdown-toggle:active,.btn-group.open .dropdown-toggle{outline:0}.btn-group-xs>.btn{padding:5px 10px;padding:1px 5px;font-size:12px;line-height:1.5;border-radius:3px}.btn-group-sm>.btn{padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.btn-group-lg>.btn{padding:10px 16px;font-size:18px;line-height:1.33;border-radius:6px}.btn-group>.btn+.dropdown-toggle{padding-right:8px;padding-left:8px}.btn-group>.btn-lg+.dropdown-toggle{padding-right:12px;padding-left:12px}.btn-group.open .dropdown-toggle{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn .caret{margin-left:0}.btn-lg .caret{border-width:5px 5px 0;border-bottom-width:0}.dropup .btn-lg .caret{border-width:0 5px 5px}.btn-group-vertical>.btn,.btn-group-vertical>.btn-group{display:block;float:none;width:100%;max-width:100%}.btn-group-vertical>.btn-group:after,.btn-group-vertical>.btn-group:before{display:table;content:" "}.btn-group-vertical>.btn-group:after{clear:both}.btn-group-vertical>.btn-group>.btn{float:none}.btn-group-vertical>.btn+.btn,.btn-group-vertical>.btn+.btn-group,.btn-group-vertical>.btn-group+.btn,.btn-group-vertical>.btn-group+.btn-group{margin-top:-1px;margin-left:0}.btn-group-vertical>.btn:not(:first-child):not(:last-child){border-radius:0}.btn-group-vertical>.btn:first-child:not(:last-child){border-top-right-radius:4px;border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn:last-child:not(:first-child){border-top-right-radius:0;border-bottom-left-radius:4px;border-top-left-radius:0}.btn-group-vertical>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group-vertical>.btn-group:first-child>.btn:last-child,.btn-group-vertical>.btn-group:first-child>.dropdown-toggle{border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn-group:last-child>.btn:first-child{border-top-right-radius:0;border-top-left-radius:0}.btn-group-justified{display:table;width:100%;border-collapse:separate;table-layout:fixed}.btn-group-justified .btn{display:table-cell;float:none;width:1%}[data-toggle=buttons]>.btn>input[type=checkbox],[data-toggle=buttons]>.btn>input[type=radio]{display:none}.input-group{position:relative;display:table;border-collapse:separate}.input-group.col{float:none;padding-right:0;padding-left:0}.input-group .form-control{width:100%;margin-bottom:0}.input-group-lg>.form-control,.input-group-lg>.input-group-addon,.input-group-lg>.input-group-btn>.btn{height:45px;padding:10px 16px;font-size:18px;line-height:1.33;border-radius:6px}select.input-group-lg>.form-control,select.input-group-lg>.input-group-addon,select.input-group-lg>.input-group-btn>.btn{height:45px;line-height:45px}textarea.input-group-lg>.form-control,textarea.input-group-lg>.input-group-addon,textarea.input-group-lg>.input-group-btn>.btn{height:auto}.input-group-sm>.form-control,.input-group-sm>.input-group-addon,.input-group-sm>.input-group-btn>.btn{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-group-sm>.form-control,select.input-group-sm>.input-group-addon,select.input-group-sm>.input-group-btn>.btn{height:30px;line-height:30px}textarea.input-group-sm>.form-control,textarea.input-group-sm>.input-group-addon,textarea.input-group-sm>.input-group-btn>.btn{height:auto}.input-group .form-control,.input-group-addon,.input-group-btn{display:table-cell}.input-group .form-control:not(:first-child):not(:last-child),.input-group-addon:not(:first-child):not(:last-child),.input-group-btn:not(:first-child):not(:last-child){border-radius:0}.input-group-addon,.input-group-btn{width:1%;white-space:nowrap;vertical-align:middle}.input-group-addon{padding:6px 12px;font-size:14px;font-weight:400;line-height:1;text-align:center;background-color:#eee;border:1px solid #ccc;border-radius:4px}.input-group-addon.input-sm{padding:5px 10px;font-size:12px;border-radius:3px}.input-group-addon.input-lg{padding:10px 16px;font-size:18px;border-radius:6px}.input-group-addon input[type=checkbox],.input-group-addon input[type=radio]{margin-top:0}.input-group .form-control:first-child,.input-group-addon:first-child,.input-group-btn:first-child>.btn,.input-group-btn:first-child>.dropdown-toggle,.input-group-btn:last-child>.btn:not(:last-child):not(.dropdown-toggle){border-top-right-radius:0;border-bottom-right-radius:0}.input-group-addon:first-child{border-right:0}.input-group .form-control:last-child,.input-group-addon:last-child,.input-group-btn:first-child>.btn:not(:first-child),.input-group-btn:last-child>.btn,.input-group-btn:last-child>.dropdown-toggle{border-bottom-left-radius:0;border-top-left-radius:0}.input-group-addon:last-child{border-left:0}.input-group-btn{position:relative;white-space:nowrap}.input-group-btn>.btn{position:relative}.input-group-btn>.btn+.btn{margin-left:-4px}.input-group-btn>.btn:active,.input-group-btn>.btn:hover{z-index:2}.nav{padding-left:0;margin-bottom:0;list-style:none}.nav:after,.nav:before{display:table;content:" "}.nav:after{clear:both}.nav>li{position:relative;display:block}.nav>li>a{position:relative;display:block;padding:10px 15px}.nav>li>a:focus,.nav>li>a:hover{text-decoration:none;background-color:#eee}.nav>li.disabled>a{color:#999}.nav>li.disabled>a:focus,.nav>li.disabled>a:hover{color:#999;text-decoration:none;cursor:not-allowed;background-color:transparent}.nav .open>a,.nav .open>a:focus,.nav .open>a:hover{background-color:#eee;border-color:#428bca}.nav .nav-divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.nav>li>a>img{max-width:none}.nav-tabs{border-bottom:1px solid #ddd}.nav-tabs>li{float:left;margin-bottom:-1px}.nav-tabs>li>a{margin-right:2px;line-height:1.428571429;border:1px solid transparent;border-radius:4px 4px 0 0}.nav-tabs>li>a:hover{border-color:#eee #eee #ddd}.nav-tabs>li.active>a,.nav-tabs>li.active>a:focus,.nav-tabs>li.active>a:hover{color:#555;cursor:default;background-color:#fff;border:1px solid #ddd;border-bottom-color:transparent}.nav-tabs.nav-justified{width:100%;border-bottom:0}.nav-tabs.nav-justified>li{float:none}.nav-tabs.nav-justified>li>a{text-align:center;margin-right:0;border-bottom:1px solid #ddd}@media(min-width:768px){.nav-tabs.nav-justified>li{display:table-cell;width:1%}}.nav-tabs.nav-justified>.active>a{border-bottom-color:#fff}.nav-pills>li{float:left}.nav-pills>li>a{border-radius:5px}.nav-pills>li+li{margin-left:2px}.nav-pills>li.active>a,.nav-pills>li.active>a:focus,.nav-pills>li.active>a:hover{color:#fff;background-color:#428bca}.nav-stacked>li{float:none}.nav-stacked>li+li{margin-top:2px;margin-left:0}.nav-justified{width:100%}.nav-justified>li{float:none}.nav-justified>li>a{text-align:center}@media(min-width:768px){.nav-justified>li{display:table-cell;width:1%}}.nav-tabs-justified{border-bottom:0}.nav-tabs-justified>li>a{margin-right:0;border-bottom:1px solid #ddd}.nav-tabs-justified>.active>a{border-bottom-color:#fff}.tabbable:after,.tabbable:before{display:table;content:" "}.tabbable:after{clear:both}.pill-content>.pill-pane,.tab-content>.tab-pane{display:none}.pill-content>.active,.tab-content>.active{display:block}.nav .caret{border-top-color:#428bca;border-bottom-color:#428bca}.nav a:hover .caret{border-top-color:#2a6496;border-bottom-color:#2a6496}.nav-tabs .dropdown-menu{margin-top:-1px;border-top-right-radius:0;border-top-left-radius:0}.navbar{position:relative;z-index:1000;min-height:50px;margin-bottom:20px;border:1px solid transparent}.navbar:after,.navbar:before{display:table;content:" "}.navbar:after{clear:both}@media(min-width:768px){.navbar{border-radius:4px}}.navbar-header:after,.navbar-header:before{display:table;content:" "}.navbar-header:after{clear:both}@media(min-width:768px){.navbar-header{float:left}}.navbar-collapse{max-height:340px;padding-right:15px;padding-left:15px;overflow-x:visible;border-top:1px solid transparent;box-shadow:inset 0 1px 0 rgba(255,255,255,.1);-webkit-overflow-scrolling:touch}.navbar-collapse:after,.navbar-collapse:before{display:table;content:" "}.navbar-collapse:after{clear:both}.navbar-collapse.in{overflow-y:auto}@media(min-width:768px){.navbar-collapse{width:auto;border-top:0;box-shadow:none}.navbar-collapse.collapse{display:block!important;height:auto!important;padding-bottom:0;overflow:visible!important}.navbar-collapse.in{overflow-y:visible}.navbar-collapse .navbar-nav.navbar-left:first-child{margin-left:-15px}.navbar-collapse .navbar-nav.navbar-right:last-child{margin-right:-15px}.navbar-collapse .navbar-text:last-child{margin-right:0}}.container>.navbar-collapse,.container>.navbar-header{margin-right:-15px;margin-left:-15px}@media(min-width:768px){.container>.navbar-collapse,.container>.navbar-header{margin-right:0;margin-left:0}}.navbar-static-top{border-width:0 0 1px}@media(min-width:768px){.navbar-static-top{border-radius:0}}.navbar-fixed-bottom,.navbar-fixed-top{position:fixed;right:0;left:0;border-width:0 0 1px}@media(min-width:768px){.navbar-fixed-bottom,.navbar-fixed-top{border-radius:0}}.navbar-fixed-top{top:0;z-index:1030}.navbar-fixed-bottom{bottom:0;margin-bottom:0}.navbar-brand{float:left;padding:15px;font-size:18px;line-height:20px}.navbar-brand:focus,.navbar-brand:hover{text-decoration:none}@media(min-width:768px){.navbar>.container .navbar-brand{margin-left:-15px}}.navbar-toggle{position:relative;float:right;padding:9px 10px;margin-top:8px;margin-right:15px;margin-bottom:8px;background-color:transparent;border:1px solid transparent;border-radius:4px}.navbar-toggle .icon-bar{display:block;width:22px;height:2px;border-radius:1px}.navbar-toggle .icon-bar+.icon-bar{margin-top:4px}@media(min-width:768px){.navbar-toggle{display:none}}.navbar-nav{margin:7.5px -15px}.navbar-nav>li>a{padding-top:10px;padding-bottom:10px;line-height:20px}@media(max-width:767px){.navbar-nav .open .dropdown-menu{position:static;float:none;width:auto;margin-top:0;background-color:transparent;border:0;box-shadow:none}.navbar-nav .open .dropdown-menu .dropdown-header,.navbar-nav .open .dropdown-menu>li>a{padding:5px 15px 5px 25px}.navbar-nav .open .dropdown-menu>li>a{line-height:20px}.navbar-nav .open .dropdown-menu>li>a:focus,.navbar-nav .open .dropdown-menu>li>a:hover{background-image:none}}@media(min-width:768px){.navbar-nav{float:left;margin:0}.navbar-nav>li{float:left}.navbar-nav>li>a{padding-top:15px;padding-bottom:15px}}@media(min-width:768px){.navbar-left{float:left!important}.navbar-right{float:right!important}}.navbar-form{padding:10px 15px;margin-top:8px;margin-right:-15px;margin-bottom:8px;margin-left:-15px;border-top:1px solid transparent;border-bottom:1px solid transparent;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.1),0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 0 rgba(255,255,255,.1),0 1px 0 rgba(255,255,255,.1)}@media(min-width:768px){.navbar-form .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.navbar-form .form-control{display:inline-block}.navbar-form .checkbox,.navbar-form .radio{display:inline-block;padding-left:0;margin-top:0;margin-bottom:0}.navbar-form .checkbox input[type=checkbox],.navbar-form .radio input[type=radio]{float:none;margin-left:0}}@media(max-width:767px){.navbar-form .form-group{margin-bottom:5px}}@media(min-width:768px){.navbar-form{width:auto;padding-top:0;padding-bottom:0;margin-right:0;margin-left:0;border:0;-webkit-box-shadow:none;box-shadow:none}}.navbar-nav>li>.dropdown-menu{margin-top:0;border-top-right-radius:0;border-top-left-radius:0}.navbar-fixed-bottom .navbar-nav>li>.dropdown-menu{border-bottom-right-radius:0;border-bottom-left-radius:0}.navbar-nav.pull-right>li>.dropdown-menu,.navbar-nav>li>.dropdown-menu.pull-right{right:0;left:auto}.navbar-btn{margin-top:8px;margin-bottom:8px}.navbar-text{float:left;margin-top:15px;margin-bottom:15px}@media(min-width:768px){.navbar-text{margin-right:15px;margin-left:15px}}.navbar-default{background-color:#f8f8f8;border-color:#e7e7e7}.navbar-default .navbar-brand{color:#777}.navbar-default .navbar-brand:focus,.navbar-default .navbar-brand:hover{color:#5e5e5e;background-color:transparent}.navbar-default .navbar-nav>li>a,.navbar-default .navbar-text{color:#777}.navbar-default .navbar-nav>li>a:focus,.navbar-default .navbar-nav>li>a:hover{color:#333;background-color:transparent}.navbar-default .navbar-nav>.active>a,.navbar-default .navbar-nav>.active>a:focus,.navbar-default .navbar-nav>.active>a:hover{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav>.disabled>a,.navbar-default .navbar-nav>.disabled>a:focus,.navbar-default .navbar-nav>.disabled>a:hover{color:#ccc;background-color:transparent}.navbar-default .navbar-toggle{border-color:#ddd}.navbar-default .navbar-toggle:focus,.navbar-default .navbar-toggle:hover{background-color:#ddd}.navbar-default .navbar-toggle .icon-bar{background-color:#ccc}.navbar-default .navbar-collapse,.navbar-default .navbar-form{border-color:#e6e6e6}.navbar-default .navbar-nav>.dropdown>a:focus .caret,.navbar-default .navbar-nav>.dropdown>a:hover .caret{border-top-color:#333;border-bottom-color:#333}.navbar-default .navbar-nav>.open>a,.navbar-default .navbar-nav>.open>a:focus,.navbar-default .navbar-nav>.open>a:hover{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav>.open>a .caret,.navbar-default .navbar-nav>.open>a:focus .caret,.navbar-default .navbar-nav>.open>a:hover .caret{border-top-color:#555;border-bottom-color:#555}.navbar-default .navbar-nav>.dropdown>a .caret{border-top-color:#777;border-bottom-color:#777}@media(max-width:767px){.navbar-default .navbar-nav .open .dropdown-menu>li>a{color:#777}.navbar-default .navbar-nav .open .dropdown-menu>li>a:focus,.navbar-default .navbar-nav .open .dropdown-menu>li>a:hover{color:#333;background-color:transparent}.navbar-default .navbar-nav .open .dropdown-menu>.active>a,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:focus,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:hover{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:focus,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:hover{color:#ccc;background-color:transparent}}.navbar-default .navbar-link{color:#777}.navbar-default .navbar-link:hover{color:#333}.navbar-inverse{background-color:#222;border-color:#080808}.navbar-inverse .navbar-brand{color:#999}.navbar-inverse .navbar-brand:focus,.navbar-inverse .navbar-brand:hover{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav>li>a,.navbar-inverse .navbar-text{color:#999}.navbar-inverse .navbar-nav>li>a:focus,.navbar-inverse .navbar-nav>li>a:hover{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav>.active>a,.navbar-inverse .navbar-nav>.active>a:focus,.navbar-inverse .navbar-nav>.active>a:hover{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav>.disabled>a,.navbar-inverse .navbar-nav>.disabled>a:focus,.navbar-inverse .navbar-nav>.disabled>a:hover{color:#444;background-color:transparent}.navbar-inverse .navbar-toggle{border-color:#333}.navbar-inverse .navbar-toggle:focus,.navbar-inverse .navbar-toggle:hover{background-color:#333}.navbar-inverse .navbar-toggle .icon-bar{background-color:#fff}.navbar-inverse .navbar-collapse,.navbar-inverse .navbar-form{border-color:#101010}.navbar-inverse .navbar-nav>.open>a,.navbar-inverse .navbar-nav>.open>a:focus,.navbar-inverse .navbar-nav>.open>a:hover{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav>.dropdown>a:hover .caret{border-top-color:#fff;border-bottom-color:#fff}.navbar-inverse .navbar-nav>.dropdown>a .caret{border-top-color:#999;border-bottom-color:#999}.navbar-inverse .navbar-nav>.open>a .caret,.navbar-inverse .navbar-nav>.open>a:focus .caret,.navbar-inverse .navbar-nav>.open>a:hover .caret{border-top-color:#fff;border-bottom-color:#fff}@media(max-width:767px){.navbar-inverse .navbar-nav .open .dropdown-menu>.dropdown-header{border-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a{color:#999}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:focus,.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:hover{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:focus,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:hover{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:focus,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:hover{color:#444;background-color:transparent}}.navbar-inverse .navbar-link{color:#999}.navbar-inverse .navbar-link:hover{color:#fff}.breadcrumb{padding:8px 15px;margin-bottom:20px;list-style:none;background-color:#f5f5f5;border-radius:4px}.breadcrumb>li{display:inline-block}.breadcrumb>li+li:before{padding:0 5px;color:#ccc;content:"/\00a0"}.breadcrumb>.active{color:#999}.pagination{display:inline-block;padding-left:0;margin:20px 0;border-radius:4px}.pagination>li{display:inline}.pagination>li>a,.pagination>li>span{position:relative;float:left;padding:6px 12px;margin-left:-1px;line-height:1.428571429;text-decoration:none;background-color:#fff;border:1px solid #ddd}.pagination>li:first-child>a,.pagination>li:first-child>span{margin-left:0;border-bottom-left-radius:4px;border-top-left-radius:4px}.pagination>li:last-child>a,.pagination>li:last-child>span{border-top-right-radius:4px;border-bottom-right-radius:4px}.pagination>li>a:focus,.pagination>li>a:hover,.pagination>li>span:focus,.pagination>li>span:hover{background-color:#eee}.pagination>.active>a,.pagination>.active>a:focus,.pagination>.active>a:hover,.pagination>.active>span,.pagination>.active>span:focus,.pagination>.active>span:hover{z-index:2;color:#fff;cursor:default;background-color:#428bca;border-color:#428bca}.pagination>.disabled>a,.pagination>.disabled>a:focus,.pagination>.disabled>a:hover,.pagination>.disabled>span{color:#999;cursor:not-allowed;background-color:#fff;border-color:#ddd}.pagination-lg>li>a,.pagination-lg>li>span{padding:10px 16px;font-size:18px}.pagination-lg>li:first-child>a,.pagination-lg>li:first-child>span{border-bottom-left-radius:6px;border-top-left-radius:6px}.pagination-lg>li:last-child>a,.pagination-lg>li:last-child>span{border-top-right-radius:6px;border-bottom-right-radius:6px}.pagination-sm>li>a,.pagination-sm>li>span{padding:5px 10px;font-size:12px}.pagination-sm>li:first-child>a,.pagination-sm>li:first-child>span{border-bottom-left-radius:3px;border-top-left-radius:3px}.pagination-sm>li:last-child>a,.pagination-sm>li:last-child>span{border-top-right-radius:3px;border-bottom-right-radius:3px}.pager{padding-left:0;margin:20px 0;text-align:center;list-style:none}.pager:after,.pager:before{display:table;content:" "}.pager:after{clear:both}.pager li{display:inline}.pager li>a,.pager li>span{display:inline-block;padding:5px 14px;background-color:#fff;border:1px solid #ddd;border-radius:15px}.pager li>a:focus,.pager li>a:hover{text-decoration:none;background-color:#eee}.pager .next>a,.pager .next>span{float:right}.pager .previous>a,.pager .previous>span{float:left}.pager .disabled>a,.pager .disabled>a:focus,.pager .disabled>a:hover,.pager .disabled>span{color:#999;cursor:not-allowed;background-color:#fff}.label{display:inline;padding:.2em .6em .3em;font-size:75%;font-weight:700;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25em}.label[href]:focus,.label[href]:hover{color:#fff;text-decoration:none;cursor:pointer}.label:empty{display:none}.label-default{background-color:#999}.label-default[href]:focus,.label-default[href]:hover{background-color:gray}.label-primary{background-color:#428bca}.label-primary[href]:focus,.label-primary[href]:hover{background-color:#3071a9}.label-success{background-color:#5cb85c}.label-success[href]:focus,.label-success[href]:hover{background-color:#449d44}.label-info{background-color:#5bc0de}.label-info[href]:focus,.label-info[href]:hover{background-color:#31b0d5}.label-warning{background-color:#f0ad4e}.label-warning[href]:focus,.label-warning[href]:hover{background-color:#ec971f}.label-danger{background-color:#d9534f}.label-danger[href]:focus,.label-danger[href]:hover{background-color:#c9302c}.badge{display:inline-block;min-width:10px;padding:3px 7px;font-size:12px;font-weight:700;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:baseline;background-color:#999;border-radius:10px}.badge:empty{display:none}a.badge:focus,a.badge:hover{color:#fff;text-decoration:none;cursor:pointer}.btn .badge{position:relative;top:-1px}.nav-pills>.active>a>.badge,a.list-group-item.active>.badge{color:#428bca;background-color:#fff}.nav-pills>li>a>.badge{margin-left:3px}.jumbotron{padding:30px;margin-bottom:30px;font-size:21px;font-weight:200;line-height:2.1428571435;color:inherit;background-color:#eee}.jumbotron h1{line-height:1;color:inherit}.jumbotron p{line-height:1.4}.container .jumbotron{border-radius:6px}@media screen and (min-width:768px){.jumbotron{padding-top:48px;padding-bottom:48px}.container .jumbotron{padding-right:60px;padding-left:60px}.jumbotron h1{font-size:63px}}.thumbnail{display:inline-block;display:block;height:auto;max-width:100%;padding:4px;line-height:1.428571429;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:all .2s ease-in-out;transition:all .2s ease-in-out}.thumbnail>img{display:block;height:auto;max-width:100%}a.thumbnail:focus,a.thumbnail:hover{border-color:#428bca}.thumbnail>img{margin-right:auto;margin-left:auto}.thumbnail .caption{padding:9px;color:#333}.alert{border:1px solid transparent;border-radius:4px}.alert h4{margin-top:0;color:inherit}.alert .alert-link{font-weight:700}.alert>p,.alert>ul{margin-bottom:0}.alert>p+p{margin-top:5px}.alert-dismissable{padding-right:35px}.alert-dismissable .close{position:relative;top:-2px;right:-21px;color:inherit}.alert-success{color:#468847;background-color:#dff0d8}.alert-success hr{border-top-color:#c9e2b3}.alert-success .alert-link{color:#356635}.alert-info{color:#3a87ad;background-color:#d9edf7}.alert-info hr{border-top-color:#a6e1ec}.alert-info .alert-link{color:#2d6987}.alert-warning{color:#c09853;background-color:#fcf8e3}.alert-warning hr{border-top-color:#f8e5be}.alert-warning .alert-link{color:#a47e3c}.alert-danger{color:#b94a48;background-color:#f2dede}.alert-danger hr{border-top-color:#e6c1c7}.alert-danger .alert-link{color:#953b39}@-webkit-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@-moz-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@-o-keyframes progress-bar-stripes{from{background-position:0 0}to{background-position:40px 0}}@keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}.progress{height:20px;margin-bottom:20px;overflow:hidden;background-color:#f5f5f5;border-radius:4px;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,.1);box-shadow:inset 0 1px 2px rgba(0,0,0,.1)}.progress-bar{float:left;width:0;height:100%;font-size:12px;color:#fff;text-align:center;background-color:#428bca;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,.15);box-shadow:inset 0 -1px 0 rgba(0,0,0,.15);-webkit-transition:width .6s ease;transition:width .6s ease}.progress-striped .progress-bar{background-image:-webkit-gradient(linear,0 100%,100% 0,color-stop(0.25,rgba(255,255,255,.15)),color-stop(0.25,transparent),color-stop(0.5,transparent),color-stop(0.5,rgba(255,255,255,.15)),color-stop(0.75,rgba(255,255,255,.15)),color-stop(0.75,transparent),to(transparent));background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15)25%,transparent 25%,transparent 50%,rgba(255,255,255,.15)50%,rgba(255,255,255,.15)75%,transparent 75%,transparent);background-image:-moz-linear-gradient(45deg,rgba(255,255,255,.15)25%,transparent 25%,transparent 50%,rgba(255,255,255,.15)50%,rgba(255,255,255,.15)75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15)25%,transparent 25%,transparent 50%,rgba(255,255,255,.15)50%,rgba(255,255,255,.15)75%,transparent 75%,transparent);background-size:40px 40px}.progress.active .progress-bar{-webkit-animation:progress-bar-stripes 2s linear infinite;-moz-animation:progress-bar-stripes 2s linear infinite;-ms-animation:progress-bar-stripes 2s linear infinite;-o-animation:progress-bar-stripes 2s linear infinite;animation:progress-bar-stripes 2s linear infinite}.progress-bar-success{background-color:#5cb85c}.progress-striped .progress-bar-success{background-image:-webkit-gradient(linear,0 100%,100% 0,color-stop(0.25,rgba(255,255,255,.15)),color-stop(0.25,transparent),color-stop(0.5,transparent),color-stop(0.5,rgba(255,255,255,.15)),color-stop(0.75,rgba(255,255,255,.15)),color-stop(0.75,transparent),to(transparent));background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15)25%,transparent 25%,transparent 50%,rgba(255,255,255,.15)50%,rgba(255,255,255,.15)75%,transparent 75%,transparent);background-image:-moz-linear-gradient(45deg,rgba(255,255,255,.15)25%,transparent 25%,transparent 50%,rgba(255,255,255,.15)50%,rgba(255,255,255,.15)75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15)25%,transparent 25%,transparent 50%,rgba(255,255,255,.15)50%,rgba(255,255,255,.15)75%,transparent 75%,transparent)}.progress-bar-info{background-color:#5bc0de}.progress-striped .progress-bar-info{background-image:-webkit-gradient(linear,0 100%,100% 0,color-stop(0.25,rgba(255,255,255,.15)),color-stop(0.25,transparent),color-stop(0.5,transparent),color-stop(0.5,rgba(255,255,255,.15)),color-stop(0.75,rgba(255,255,255,.15)),color-stop(0.75,transparent),to(transparent));background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15)25%,transparent 25%,transparent 50%,rgba(255,255,255,.15)50%,rgba(255,255,255,.15)75%,transparent 75%,transparent);background-image:-moz-linear-gradient(45deg,rgba(255,255,255,.15)25%,transparent 25%,transparent 50%,rgba(255,255,255,.15)50%,rgba(255,255,255,.15)75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15)25%,transparent 25%,transparent 50%,rgba(255,255,255,.15)50%,rgba(255,255,255,.15)75%,transparent 75%,transparent)}.progress-bar-warning{background-color:#f0ad4e}.progress-striped .progress-bar-warning{background-image:-webkit-gradient(linear,0 100%,100% 0,color-stop(0.25,rgba(255,255,255,.15)),color-stop(0.25,transparent),color-stop(0.5,transparent),color-stop(0.5,rgba(255,255,255,.15)),color-stop(0.75,rgba(255,255,255,.15)),color-stop(0.75,transparent),to(transparent));background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15)25%,transparent 25%,transparent 50%,rgba(255,255,255,.15)50%,rgba(255,255,255,.15)75%,transparent 75%,transparent);background-image:-moz-linear-gradient(45deg,rgba(255,255,255,.15)25%,transparent 25%,transparent 50%,rgba(255,255,255,.15)50%,rgba(255,255,255,.15)75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15)25%,transparent 25%,transparent 50%,rgba(255,255,255,.15)50%,rgba(255,255,255,.15)75%,transparent 75%,transparent)}.progress-bar-danger{background-color:#d9534f}.progress-striped .progress-bar-danger{background-image:-webkit-gradient(linear,0 100%,100% 0,color-stop(0.25,rgba(255,255,255,.15)),color-stop(0.25,transparent),color-stop(0.5,transparent),color-stop(0.5,rgba(255,255,255,.15)),color-stop(0.75,rgba(255,255,255,.15)),color-stop(0.75,transparent),to(transparent));background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15)25%,transparent 25%,transparent 50%,rgba(255,255,255,.15)50%,rgba(255,255,255,.15)75%,transparent 75%,transparent);background-image:-moz-linear-gradient(45deg,rgba(255,255,255,.15)25%,transparent 25%,transparent 50%,rgba(255,255,255,.15)50%,rgba(255,255,255,.15)75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15)25%,transparent 25%,transparent 50%,rgba(255,255,255,.15)50%,rgba(255,255,255,.15)75%,transparent 75%,transparent)}.media,.media-body{overflow:hidden;zoom:1}.media,.media .media{margin-top:15px}.media:first-child{margin-top:0}.media-object{display:block}.media-heading{margin:0 0 5px}.media>.pull-left{margin-right:10px}.media>.pull-right{margin-left:10px}.media-list{padding-left:0;list-style:none}.list-group{padding-left:0;margin-bottom:20px}.list-group-item{position:relative;display:block;padding:10px 15px;margin-bottom:-1px;background-color:#fff;border:1px solid #ddd}.list-group-item:first-child{border-top-right-radius:4px;border-top-left-radius:4px}.list-group-item:last-child{margin-bottom:0;border-bottom-right-radius:4px;border-bottom-left-radius:4px}.list-group-item>.badge{float:right}.list-group-item>.badge+.badge{margin-right:5px}a.list-group-item{color:#555}a.list-group-item .list-group-item-heading{color:#333}a.list-group-item:focus,a.list-group-item:hover{text-decoration:none;background-color:#f5f5f5}.list-group-item.active,.list-group-item.active:focus,.list-group-item.active:hover{z-index:2;color:#fff;background-color:#428bca}.list-group-item.active .list-group-item-heading,.list-group-item.active:focus .list-group-item-heading,.list-group-item.active:hover .list-group-item-heading{color:inherit}.list-group-item.active .list-group-item-text,.list-group-item.active:focus .list-group-item-text,.list-group-item.active:hover .list-group-item-text{color:#e1edf7}.list-group-item-heading{margin-top:0;margin-bottom:5px}.list-group-item-text{margin-bottom:0;line-height:1.3}.panel{margin-bottom:20px;background-color:#fff;border:1px solid transparent;border-radius:4px}.panel-body{padding:15px}.panel-body:after,.panel-body:before{display:table;content:" "}.panel-body:after{clear:both}.panel>.list-group{margin-bottom:0}.panel>.list-group .list-group-item{border-width:1px 0}.panel>.list-group .list-group-item:first-child{border-top-right-radius:0;border-top-left-radius:0}.panel>.list-group .list-group-item:last-child{border-bottom:0}.panel-heading+.list-group .list-group-item:first-child{border-top-width:0}.panel>.table{margin-bottom:0}.panel>.panel-body+.table{border-top:1px solid #ddd}.panel-heading{padding:10px 15px;border-bottom:1px solid transparent;border-top-right-radius:3px;border-top-left-radius:3px}.panel-title{margin-top:0;margin-bottom:0;font-size:16px}.panel-title>a{color:inherit}.panel-footer{padding:10px 15px;background-color:#f5f5f5;border-top:1px solid #ddd;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel-group .panel{margin-bottom:0;overflow:hidden;border-radius:4px}.panel-group .panel+.panel{margin-top:5px}.panel-group .panel-heading{border-bottom:0}.panel-group .panel-heading+.panel-collapse .panel-body{border-top:1px solid #ddd}.panel-group .panel-footer{border-top:0}.panel-group .panel-footer+.panel-collapse .panel-body{border-bottom:1px solid #ddd}.panel-default{border-color:#ddd}.panel-default>.panel-heading{color:#333;background-color:#f5f5f5;border-color:#ddd}.panel-default>.panel-heading+.panel-collapse .panel-body{border-top-color:#ddd}.panel-default>.panel-footer+.panel-collapse .panel-body{border-bottom-color:#ddd}.panel-primary{border-color:#428bca}.panel-primary>.panel-heading{color:#fff;background-color:#428bca;border-color:#428bca}.panel-primary>.panel-heading+.panel-collapse .panel-body{border-top-color:#428bca}.panel-primary>.panel-footer+.panel-collapse .panel-body{border-bottom-color:#428bca}.panel-success{border-color:#d6e9c6}.panel-success>.panel-heading{color:#468847;background-color:#dff0d8;border-color:#d6e9c6}.panel-success>.panel-heading+.panel-collapse .panel-body{border-top-color:#d6e9c6}.panel-success>.panel-footer+.panel-collapse .panel-body{border-bottom-color:#d6e9c6}.panel-warning{border-color:#fbeed5}.panel-warning>.panel-heading{color:#c09853;background-color:#fcf8e3;border-color:#fbeed5}.panel-warning>.panel-heading+.panel-collapse .panel-body{border-top-color:#fbeed5}.panel-warning>.panel-footer+.panel-collapse .panel-body{border-bottom-color:#fbeed5}.panel-danger{border-color:#eed3d7}.panel-danger>.panel-heading{color:#b94a48;background-color:#f2dede;border-color:#eed3d7}.panel-danger>.panel-heading+.panel-collapse .panel-body{border-top-color:#eed3d7}.panel-danger>.panel-footer+.panel-collapse .panel-body{border-bottom-color:#eed3d7}.panel-info{border-color:#bce8f1}.panel-info>.panel-heading{color:#3a87ad;background-color:#d9edf7;border-color:#bce8f1}.panel-info>.panel-heading+.panel-collapse .panel-body{border-top-color:#bce8f1}.panel-info>.panel-footer+.panel-collapse .panel-body{border-bottom-color:#bce8f1}.well{min-height:20px;padding:19px;margin-bottom:20px;background-color:#f5f5f5;border:1px solid #e3e3e3;border-radius:4px}.well blockquote{border-color:#ddd;border-color:rgba(0,0,0,.15)}.well-lg{padding:24px;border-radius:6px}.well-sm{padding:9px;border-radius:3px}.close{float:right;font-size:21px;font-weight:700;line-height:1;color:#000;text-shadow:0 1px 0 #fff;opacity:.2;filter:alpha(opacity=20)}.close:focus,.close:hover{color:#000;text-decoration:none;cursor:pointer;opacity:.5;filter:alpha(opacity=50)}button.close{padding:0;cursor:pointer;background:0 0;border:0;-webkit-appearance:none}.modal-open{overflow:hidden}.modal-open .navbar-fixed-bottom,.modal-open .navbar-fixed-top,body.modal-open{margin-right:15px}.modal{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040;display:none;overflow:auto;overflow-y:scroll}.modal.fade .modal-dialog{-webkit-transform:translate(0,-25%);-ms-transform:translate(0,-25%);transform:translate(0,-25%);-webkit-transition:-webkit-transform .3s ease-out;-moz-transition:-moz-transform .3s ease-out;-o-transition:-o-transform .3s ease-out;transition:transform .3s ease-out}.modal.in .modal-dialog{-webkit-transform:translate(0,0);-ms-transform:translate(0,0);transform:translate(0,0)}.modal-dialog{z-index:1050;width:auto;padding:10px;margin-right:auto;margin-left:auto}.modal-content{position:relative;background-color:#fff;border:1px solid #999;border:1px solid rgba(0,0,0,.2);border-radius:6px;outline:0;-webkit-box-shadow:0 3px 9px rgba(0,0,0,.5);box-shadow:0 3px 9px rgba(0,0,0,.5);background-clip:padding-box}.modal-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1030;background-color:#000}.modal-backdrop.fade{opacity:0;filter:alpha(opacity=0)}.modal-backdrop.in{opacity:.5;filter:alpha(opacity=50)}.modal-header{min-height:16.43px;padding:15px;border-bottom:1px solid #e5e5e5}.modal-header .close{margin-top:-2px}.modal-title{margin:0;line-height:1.428571429}.modal-body{position:relative;padding:20px}.modal-footer{padding:19px 20px 20px;margin-top:15px;text-align:right;border-top:1px solid #e5e5e5}.modal-footer:after,.modal-footer:before{display:table;content:" "}.modal-footer:after{clear:both}.modal-footer .btn+.btn{margin-bottom:0;margin-left:5px}.modal-footer .btn-group .btn+.btn{margin-left:-1px}.modal-footer .btn-block+.btn-block{margin-left:0}@media screen and (min-width:768px){.modal-dialog{right:auto;left:50%;width:600px;padding-top:30px;padding-bottom:30px}.modal-content{-webkit-box-shadow:0 5px 15px rgba(0,0,0,.5);box-shadow:0 5px 15px rgba(0,0,0,.5)}}.tooltip{position:absolute;z-index:1030;display:block;font-size:12px;line-height:1.4;opacity:0;filter:alpha(opacity=0);visibility:visible}.tooltip.in{opacity:.9;filter:alpha(opacity=90)}.tooltip.top{padding:5px 0;margin-top:-3px}.tooltip.right{padding:0 5px;margin-left:3px}.tooltip.bottom{padding:5px 0;margin-top:3px}.tooltip.left{padding:0 5px;margin-left:-3px}.tooltip-inner{max-width:200px;padding:3px 8px;color:#fff;text-align:center;text-decoration:none;background-color:#000;border-radius:4px}.tooltip-arrow{position:absolute;width:0;height:0;border-color:transparent;border-style:solid}.tooltip.top .tooltip-arrow{bottom:0;left:50%;margin-left:-5px;border-top-color:#000;border-width:5px 5px 0}.tooltip.top-left .tooltip-arrow{bottom:0;left:5px;border-top-color:#000;border-width:5px 5px 0}.tooltip.top-right .tooltip-arrow{right:5px;bottom:0;border-top-color:#000;border-width:5px 5px 0}.tooltip.right .tooltip-arrow{top:50%;left:0;margin-top:-5px;border-right-color:#000;border-width:5px 5px 5px 0}.tooltip.left .tooltip-arrow{top:50%;right:0;margin-top:-5px;border-left-color:#000;border-width:5px 0 5px 5px}.tooltip.bottom .tooltip-arrow{top:0;left:50%;margin-left:-5px;border-bottom-color:#000;border-width:0 5px 5px}.tooltip.bottom-left .tooltip-arrow{top:0;left:5px;border-bottom-color:#000;border-width:0 5px 5px}.tooltip.bottom-right .tooltip-arrow{top:0;right:5px;border-bottom-color:#000;border-width:0 5px 5px}.popover{position:absolute;top:0;left:0;z-index:1010;display:none;max-width:276px;padding:1px;text-align:left;white-space:normal;background-color:#fff;border:1px solid #ccc;border:1px solid rgba(0,0,0,.2);border-radius:6px;-webkit-box-shadow:0 5px 10px rgba(0,0,0,.2);box-shadow:0 5px 10px rgba(0,0,0,.2);background-clip:padding-box}.popover.top{margin-top:-10px}.popover.right{margin-left:10px}.popover.bottom{margin-top:10px}.popover.left{margin-left:-10px}.popover-title{padding:8px 14px;margin:0;font-size:14px;font-weight:400;line-height:18px;background-color:#f7f7f7;border-bottom:1px solid #ebebeb;border-radius:5px 5px 0 0}.popover-content{padding:9px 14px}.popover .arrow,.popover .arrow:after{position:absolute;display:block;width:0;height:0;border-color:transparent;border-style:solid}.popover .arrow{border-width:11px}.popover .arrow:after{border-width:10px;content:""}.popover.top .arrow{bottom:-11px;left:50%;margin-left:-11px;border-top-color:#999;border-top-color:rgba(0,0,0,.25);border-bottom-width:0}.popover.top .arrow:after{bottom:1px;margin-left:-10px;border-top-color:#fff;border-bottom-width:0;content:" "}.popover.right .arrow{top:50%;left:-11px;margin-top:-11px;border-right-color:#999;border-right-color:rgba(0,0,0,.25);border-left-width:0}.popover.right .arrow:after{bottom:-10px;left:1px;border-right-color:#fff;border-left-width:0;content:" "}.popover.bottom .arrow{top:-11px;left:50%;margin-left:-11px;border-bottom-color:#999;border-bottom-color:rgba(0,0,0,.25);border-top-width:0}.popover.bottom .arrow:after{top:1px;margin-left:-10px;border-bottom-color:#fff;border-top-width:0;content:" "}.popover.left .arrow{top:50%;right:-11px;margin-top:-11px;border-left-color:#999;border-left-color:rgba(0,0,0,.25);border-right-width:0}.popover.left .arrow:after{right:1px;bottom:-10px;border-left-color:#fff;border-right-width:0;content:" "}.carousel{position:relative}.carousel-inner{position:relative;width:100%;overflow:hidden}.carousel-inner>.item{position:relative;display:none;-webkit-transition:.6s ease-in-out left;transition:.6s ease-in-out left}.carousel-inner>.item>a>img,.carousel-inner>.item>img{display:block;height:auto;max-width:100%;line-height:1}.carousel-inner>.active,.carousel-inner>.next,.carousel-inner>.prev{display:block}.carousel-inner>.active{left:0}.carousel-inner>.next,.carousel-inner>.prev{position:absolute;top:0;width:100%}.carousel-inner>.next{left:100%}.carousel-inner>.prev{left:-100%}.carousel-inner>.next.left,.carousel-inner>.prev.right{left:0}.carousel-inner>.active.left{left:-100%}.carousel-inner>.active.right{left:100%}.carousel-control{position:absolute;top:0;bottom:0;left:0;width:15%;font-size:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,.6);opacity:.5;filter:alpha(opacity=50)}.carousel-control.left{background-image:-webkit-gradient(linear,0 top,100% top,from(rgba(0,0,0,.5)),to(rgba(0,0,0,.0001)));background-image:-webkit-linear-gradient(left,color-stop(rgba(0,0,0,.5)0),color-stop(rgba(0,0,0,.0001)100%));background-image:-moz-linear-gradient(left,rgba(0,0,0,.5)0,rgba(0,0,0,.0001)100%);background-image:linear-gradient(to right,rgba(0,0,0,.5)0,rgba(0,0,0,.0001)100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1)}.carousel-control.right{right:0;left:auto;background-image:-webkit-gradient(linear,0 top,100% top,from(rgba(0,0,0,.0001)),to(rgba(0,0,0,.5)));background-image:-webkit-linear-gradient(left,color-stop(rgba(0,0,0,.0001)0),color-stop(rgba(0,0,0,.5)100%));background-image:-moz-linear-gradient(left,rgba(0,0,0,.0001)0,rgba(0,0,0,.5)100%);background-image:linear-gradient(to right,rgba(0,0,0,.0001)0,rgba(0,0,0,.5)100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1)}.carousel-control:focus,.carousel-control:hover{color:#fff;text-decoration:none;opacity:.9;filter:alpha(opacity=90)}.carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next,.carousel-control .icon-prev{position:absolute;top:50%;left:50%;z-index:5;display:inline-block}.carousel-control .icon-next,.carousel-control .icon-prev{width:20px;height:20px;margin-top:-10px;margin-left:-10px;font-family:serif}.carousel-control .icon-prev:before{content:'\2039'}.carousel-control .icon-next:before{content:'\203a'}.carousel-indicators{position:absolute;bottom:10px;left:50%;z-index:15;width:60%;padding-left:0;margin-left:-30%;text-align:center;list-style:none}.carousel-indicators li{display:inline-block;width:10px;height:10px;margin:1px;text-indent:-999px;cursor:pointer;border:1px solid #fff;border-radius:10px}.carousel-indicators .active{width:12px;height:12px;margin:0;background-color:#fff}.carousel-caption{position:absolute;right:15%;bottom:20px;left:15%;z-index:10;padding-top:20px;padding-bottom:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,.6)}.carousel-caption .btn{text-shadow:none}@media screen and (min-width:768px){.carousel-control .icon-next,.carousel-control .icon-prev{width:30px;height:30px;margin-top:-15px;margin-left:-15px;font-size:30px}.carousel-caption{right:20%;left:20%;padding-bottom:30px}.carousel-indicators{bottom:20px}}.clearfix:after,.clearfix:before{display:table;content:" "}.clearfix:after{clear:both}.pull-right{float:right!important}.pull-left{float:left!important}.hide{display:none!important}.show{display:block!important}.invisible{visibility:hidden}.text-hide{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.affix{position:fixed}@-ms-viewport{width:device-width}@media screen and (max-width:400px){@-ms-viewport{width:320px}}.hidden{display:none!important;visibility:hidden!important}.visible-lg,.visible-md,.visible-sm,.visible-xs,td.visible-lg,td.visible-md,td.visible-sm,td.visible-xs,th.visible-lg,th.visible-md,th.visible-sm,th.visible-xs,tr.visible-lg,tr.visible-md,tr.visible-sm,tr.visible-xs{display:none!important}@media(max-width:767px){.visible-xs{display:block!important}tr.visible-xs{display:table-row!important}td.visible-xs,th.visible-xs{display:table-cell!important}}@media(min-width:768px) and (max-width:991px){.visible-xs.visible-sm{display:block!important}tr.visible-xs.visible-sm{display:table-row!important}td.visible-xs.visible-sm,th.visible-xs.visible-sm{display:table-cell!important}}@media(min-width:992px) and (max-width:1199px){.visible-xs.visible-md{display:block!important}tr.visible-xs.visible-md{display:table-row!important}td.visible-xs.visible-md,th.visible-xs.visible-md{display:table-cell!important}}@media(min-width:1200px){.visible-xs.visible-lg{display:block!important}tr.visible-xs.visible-lg{display:table-row!important}td.visible-xs.visible-lg,th.visible-xs.visible-lg{display:table-cell!important}}@media(max-width:767px){.visible-sm.visible-xs{display:block!important}tr.visible-sm.visible-xs{display:table-row!important}td.visible-sm.visible-xs,th.visible-sm.visible-xs{display:table-cell!important}}@media(min-width:768px) and (max-width:991px){.visible-sm{display:block!important}tr.visible-sm{display:table-row!important}td.visible-sm,th.visible-sm{display:table-cell!important}}@media(min-width:992px) and (max-width:1199px){.visible-sm.visible-md{display:block!important}tr.visible-sm.visible-md{display:table-row!important}td.visible-sm.visible-md,th.visible-sm.visible-md{display:table-cell!important}}@media(min-width:1200px){.visible-sm.visible-lg{display:block!important}tr.visible-sm.visible-lg{display:table-row!important}td.visible-sm.visible-lg,th.visible-sm.visible-lg{display:table-cell!important}}@media(max-width:767px){.visible-md.visible-xs{display:block!important}tr.visible-md.visible-xs{display:table-row!important}td.visible-md.visible-xs,th.visible-md.visible-xs{display:table-cell!important}}@media(min-width:768px) and (max-width:991px){.visible-md.visible-sm{display:block!important}tr.visible-md.visible-sm{display:table-row!important}td.visible-md.visible-sm,th.visible-md.visible-sm{display:table-cell!important}}@media(min-width:992px) and (max-width:1199px){.visible-md{display:block!important}tr.visible-md{display:table-row!important}td.visible-md,th.visible-md{display:table-cell!important}}@media(min-width:1200px){.visible-md.visible-lg{display:block!important}tr.visible-md.visible-lg{display:table-row!important}td.visible-md.visible-lg,th.visible-md.visible-lg{display:table-cell!important}}@media(max-width:767px){.visible-lg.visible-xs{display:block!important}tr.visible-lg.visible-xs{display:table-row!important}td.visible-lg.visible-xs,th.visible-lg.visible-xs{display:table-cell!important}}@media(min-width:768px) and (max-width:991px){.visible-lg.visible-sm{display:block!important}tr.visible-lg.visible-sm{display:table-row!important}td.visible-lg.visible-sm,th.visible-lg.visible-sm{display:table-cell!important}}@media(min-width:992px) and (max-width:1199px){.visible-lg.visible-md{display:block!important}tr.visible-lg.visible-md{display:table-row!important}td.visible-lg.visible-md,th.visible-lg.visible-md{display:table-cell!important}}@media(min-width:1200px){.visible-lg{display:block!important}tr.visible-lg{display:table-row!important}td.visible-lg,th.visible-lg{display:table-cell!important}}.hidden-xs{display:block!important}tr.hidden-xs{display:table-row!important}td.hidden-xs,th.hidden-xs{display:table-cell!important}@media(max-width:767px){.hidden-xs,td.hidden-xs,th.hidden-xs,tr.hidden-xs{display:none!important}}@media(min-width:768px) and (max-width:991px){.hidden-xs.hidden-sm,td.hidden-xs.hidden-sm,th.hidden-xs.hidden-sm,tr.hidden-xs.hidden-sm{display:none!important}}@media(min-width:992px) and (max-width:1199px){.hidden-xs.hidden-md,td.hidden-xs.hidden-md,th.hidden-xs.hidden-md,tr.hidden-xs.hidden-md{display:none!important}}@media(min-width:1200px){.hidden-xs.hidden-lg,td.hidden-xs.hidden-lg,th.hidden-xs.hidden-lg,tr.hidden-xs.hidden-lg{display:none!important}}.hidden-sm{display:block!important}tr.hidden-sm{display:table-row!important}td.hidden-sm,th.hidden-sm{display:table-cell!important}@media(max-width:767px){.hidden-sm.hidden-xs,td.hidden-sm.hidden-xs,th.hidden-sm.hidden-xs,tr.hidden-sm.hidden-xs{display:none!important}}@media(min-width:768px) and (max-width:991px){.hidden-sm,td.hidden-sm,th.hidden-sm,tr.hidden-sm{display:none!important}}@media(min-width:992px) and (max-width:1199px){.hidden-sm.hidden-md,td.hidden-sm.hidden-md,th.hidden-sm.hidden-md,tr.hidden-sm.hidden-md{display:none!important}}@media(min-width:1200px){.hidden-sm.hidden-lg,td.hidden-sm.hidden-lg,th.hidden-sm.hidden-lg,tr.hidden-sm.hidden-lg{display:none!important}}.hidden-md{display:block!important}tr.hidden-md{display:table-row!important}td.hidden-md,th.hidden-md{display:table-cell!important}@media(max-width:767px){.hidden-md.hidden-xs,td.hidden-md.hidden-xs,th.hidden-md.hidden-xs,tr.hidden-md.hidden-xs{display:none!important}}@media(min-width:768px) and (max-width:991px){.hidden-md.hidden-sm,td.hidden-md.hidden-sm,th.hidden-md.hidden-sm,tr.hidden-md.hidden-sm{display:none!important}}@media(min-width:992px) and (max-width:1199px){.hidden-md,td.hidden-md,th.hidden-md,tr.hidden-md{display:none!important}}@media(min-width:1200px){.hidden-md.hidden-lg,td.hidden-md.hidden-lg,th.hidden-md.hidden-lg,tr.hidden-md.hidden-lg{display:none!important}}.hidden-lg{display:block!important}tr.hidden-lg{display:table-row!important}td.hidden-lg,th.hidden-lg{display:table-cell!important}@media(max-width:767px){.hidden-lg.hidden-xs,td.hidden-lg.hidden-xs,th.hidden-lg.hidden-xs,tr.hidden-lg.hidden-xs{display:none!important}}@media(min-width:768px) and (max-width:991px){.hidden-lg.hidden-sm,td.hidden-lg.hidden-sm,th.hidden-lg.hidden-sm,tr.hidden-lg.hidden-sm{display:none!important}}@media(min-width:992px) and (max-width:1199px){.hidden-lg.hidden-md,td.hidden-lg.hidden-md,th.hidden-lg.hidden-md,tr.hidden-lg.hidden-md{display:none!important}}@media(min-width:1200px){.hidden-lg,td.hidden-lg,th.hidden-lg,tr.hidden-lg{display:none!important}}.visible-print,td.visible-print,th.visible-print,tr.visible-print{display:none!important}@media print{.visible-print{display:block!important}tr.visible-print{display:table-row!important}td.visible-print,th.visible-print{display:table-cell!important}.hidden-print,td.hidden-print,th.hidden-print,tr.hidden-print{display:none!important}}.btn-danger,.btn-default,.btn-info,.btn-primary,.btn-success,.btn-warning{text-shadow:0 -1px 0 rgba(0,0,0,.2);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075)}.btn-danger.active,.btn-danger:active,.btn-default.active,.btn-default:active,.btn-info.active,.btn-info:active,.btn-primary.active,.btn-primary:active,.btn-success.active,.btn-success:active,.btn-warning.active,.btn-warning:active{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn.active,.btn:active{background-image:none}.btn-default{text-shadow:0 1px 0 #fff;background-image:-webkit-gradient(linear,left 0,left 100%,from(#fff),to(#e6e6e6));background-image:-webkit-linear-gradient(top,#fff,0,#e6e6e6,100%);background-image:-moz-linear-gradient(top,#fff 0,#e6e6e6 100%);background-image:linear-gradient(to bottom,#fff 0,#e6e6e6 100%);background-repeat:repeat-x;border-color:#e0e0e0;border-color:#ccc;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe6e6e6', GradientType=0)}.btn-default.active,.btn-default:active{background-color:#e6e6e6;border-color:#e0e0e0}.btn-primary{background-image:-webkit-gradient(linear,left 0,left 100%,from(#428bca),to(#3071a9));background-image:-webkit-linear-gradient(top,#428bca,0,#3071a9,100%);background-image:-moz-linear-gradient(top,#428bca 0,#3071a9 100%);background-image:linear-gradient(to bottom,#428bca 0,#3071a9 100%);background-repeat:repeat-x;border-color:#2d6ca2;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff3071a9', GradientType=0)}.btn-primary.active,.btn-primary:active{background-color:#3071a9;border-color:#2d6ca2}.btn-success{background-image:-webkit-gradient(linear,left 0,left 100%,from(#5cb85c),to(#449d44));background-image:-webkit-linear-gradient(top,#5cb85c,0,#449d44,100%);background-image:-moz-linear-gradient(top,#5cb85c 0,#449d44 100%);background-image:linear-gradient(to bottom,#5cb85c 0,#449d44 100%);background-repeat:repeat-x;border-color:#419641;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0)}.btn-success.active,.btn-success:active{background-color:#449d44;border-color:#419641}.btn-warning{background-image:-webkit-gradient(linear,left 0,left 100%,from(#f0ad4e),to(#ec971f));background-image:-webkit-linear-gradient(top,#f0ad4e,0,#ec971f,100%);background-image:-moz-linear-gradient(top,#f0ad4e 0,#ec971f 100%);background-image:linear-gradient(to bottom,#f0ad4e 0,#ec971f 100%);background-repeat:repeat-x;border-color:#eb9316;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0)}.btn-warning.active,.btn-warning:active{background-color:#ec971f;border-color:#eb9316}.btn-danger{background-image:-webkit-gradient(linear,left 0,left 100%,from(#d9534f),to(#c9302c));background-image:-webkit-linear-gradient(top,#d9534f,0,#c9302c,100%);background-image:-moz-linear-gradient(top,#d9534f 0,#c9302c 100%);background-image:linear-gradient(to bottom,#d9534f 0,#c9302c 100%);background-repeat:repeat-x;border-color:#c12e2a;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0)}.btn-danger.active,.btn-danger:active{background-color:#c9302c;border-color:#c12e2a}.btn-info{background-image:-webkit-gradient(linear,left 0,left 100%,from(#5bc0de),to(#31b0d5));background-image:-webkit-linear-gradient(top,#5bc0de,0,#31b0d5,100%);background-image:-moz-linear-gradient(top,#5bc0de 0,#31b0d5 100%);background-image:linear-gradient(to bottom,#5bc0de 0,#31b0d5 100%);background-repeat:repeat-x;border-color:#2aabd2;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0)}.btn-info.active,.btn-info:active{background-color:#31b0d5;border-color:#2aabd2}.img-thumbnail,.thumbnail{-webkit-box-shadow:0 1px 2px rgba(0,0,0,.075);box-shadow:0 1px 2px rgba(0,0,0,.075)}.dropdown-menu>.active>a,.dropdown-menu>.active>a:focus,.dropdown-menu>.active>a:hover,.dropdown-menu>li>a:focus,.dropdown-menu>li>a:hover{background-color:#357ebd;background-image:-webkit-gradient(linear,left 0,left 100%,from(#428bca),to(#357ebd));background-image:-webkit-linear-gradient(top,#428bca,0,#357ebd,100%);background-image:-moz-linear-gradient(top,#428bca 0,#357ebd 100%);background-image:linear-gradient(to bottom,#428bca 0,#357ebd 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff357ebd', GradientType=0)}.navbar{background-image:-webkit-gradient(linear,left 0,left 100%,from(#fff),to(#f8f8f8));background-image:-webkit-linear-gradient(top,#fff,0,#f8f8f8,100%);background-image:-moz-linear-gradient(top,#fff 0,#f8f8f8 100%);background-image:linear-gradient(to bottom,#fff 0,#f8f8f8 100%);background-repeat:repeat-x;border-radius:4px;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff8f8f8', GradientType=0);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 5px rgba(0,0,0,.075);box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 5px rgba(0,0,0,.075)}.navbar .navbar-nav>.active>a{background-color:#f8f8f8}.navbar-brand,.navbar-nav>li>a{text-shadow:0 1px 0 rgba(255,255,255,.25)}.navbar-inverse{background-image:-webkit-gradient(linear,left 0,left 100%,from(#3c3c3c),to(#222));background-image:-webkit-linear-gradient(top,#3c3c3c,0,#222,100%);background-image:-moz-linear-gradient(top,#3c3c3c 0,#222 100%);background-image:linear-gradient(to bottom,#3c3c3c 0,#222 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c', endColorstr='#ff222222', GradientType=0)}.navbar-inverse .navbar-nav>.active>a{background-color:#222}.navbar-inverse .navbar-brand,.navbar-inverse .navbar-nav>li>a{text-shadow:0 -1px 0 rgba(0,0,0,.25)}.navbar-fixed-bottom,.navbar-fixed-top,.navbar-static-top{border-radius:0}.alert{text-shadow:0 1px 0 rgba(255,255,255,.2);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.25),0 1px 2px rgba(0,0,0,.05);box-shadow:inset 0 1px 0 rgba(255,255,255,.25),0 1px 2px rgba(0,0,0,.05)}.alert-success{background-image:-webkit-gradient(linear,left 0,left 100%,from(#dff0d8),to(#c8e5bc));background-image:-webkit-linear-gradient(top,#dff0d8,0,#c8e5bc,100%);background-image:-moz-linear-gradient(top,#dff0d8 0,#c8e5bc 100%);background-image:linear-gradient(to bottom,#dff0d8 0,#c8e5bc 100%);background-repeat:repeat-x;border-color:#b2dba1;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffc8e5bc', GradientType=0)}.alert-info{background-image:-webkit-gradient(linear,left 0,left 100%,from(#d9edf7),to(#b9def0));background-image:-webkit-linear-gradient(top,#d9edf7,0,#b9def0,100%);background-image:-moz-linear-gradient(top,#d9edf7 0,#b9def0 100%);background-image:linear-gradient(to bottom,#d9edf7 0,#b9def0 100%);background-repeat:repeat-x;border-color:#9acfea;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffb9def0', GradientType=0)}.alert-warning{background-image:-webkit-gradient(linear,left 0,left 100%,from(#fcf8e3),to(#f8efc0));background-image:-webkit-linear-gradient(top,#fcf8e3,0,#f8efc0,100%);background-image:-moz-linear-gradient(top,#fcf8e3 0,#f8efc0 100%);background-image:linear-gradient(to bottom,#fcf8e3 0,#f8efc0 100%);background-repeat:repeat-x;border-color:#f5e79e;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fff8efc0', GradientType=0)}.alert-danger{background-image:-webkit-gradient(linear,left 0,left 100%,from(#f2dede),to(#e7c3c3));background-image:-webkit-linear-gradient(top,#f2dede,0,#e7c3c3,100%);background-image:-moz-linear-gradient(top,#f2dede 0,#e7c3c3 100%);background-image:linear-gradient(to bottom,#f2dede 0,#e7c3c3 100%);background-repeat:repeat-x;border-color:#dca7a7;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffe7c3c3', GradientType=0)}.progress{background-image:-webkit-gradient(linear,left 0,left 100%,from(#ebebeb),to(#f5f5f5));background-image:-webkit-linear-gradient(top,#ebebeb,0,#f5f5f5,100%);background-image:-moz-linear-gradient(top,#ebebeb 0,#f5f5f5 100%);background-image:linear-gradient(to bottom,#ebebeb 0,#f5f5f5 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff5f5f5', GradientType=0)}.progress-bar{background-image:-webkit-gradient(linear,left 0,left 100%,from(#428bca),to(#3071a9));background-image:-webkit-linear-gradient(top,#428bca,0,#3071a9,100%);background-image:-moz-linear-gradient(top,#428bca 0,#3071a9 100%);background-image:linear-gradient(to bottom,#428bca 0,#3071a9 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff3071a9', GradientType=0)}.progress-bar-success{background-image:-webkit-gradient(linear,left 0,left 100%,from(#5cb85c),to(#449d44));background-image:-webkit-linear-gradient(top,#5cb85c,0,#449d44,100%);background-image:-moz-linear-gradient(top,#5cb85c 0,#449d44 100%);background-image:linear-gradient(to bottom,#5cb85c 0,#449d44 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0)}.progress-bar-info{background-image:-webkit-gradient(linear,left 0,left 100%,from(#5bc0de),to(#31b0d5));background-image:-webkit-linear-gradient(top,#5bc0de,0,#31b0d5,100%);background-image:-moz-linear-gradient(top,#5bc0de 0,#31b0d5 100%);background-image:linear-gradient(to bottom,#5bc0de 0,#31b0d5 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0)}.progress-bar-warning{background-image:-webkit-gradient(linear,left 0,left 100%,from(#f0ad4e),to(#ec971f));background-image:-webkit-linear-gradient(top,#f0ad4e,0,#ec971f,100%);background-image:-moz-linear-gradient(top,#f0ad4e 0,#ec971f 100%);background-image:linear-gradient(to bottom,#f0ad4e 0,#ec971f 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0)}.progress-bar-danger{background-image:-webkit-gradient(linear,left 0,left 100%,from(#d9534f),to(#c9302c));background-image:-webkit-linear-gradient(top,#d9534f,0,#c9302c,100%);background-image:-moz-linear-gradient(top,#d9534f 0,#c9302c 100%);background-image:linear-gradient(to bottom,#d9534f 0,#c9302c 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0)}.list-group{border-radius:4px;-webkit-box-shadow:0 1px 2px rgba(0,0,0,.075);box-shadow:0 1px 2px rgba(0,0,0,.075)}.list-group-item.active,.list-group-item.active:focus,.list-group-item.active:hover{text-shadow:0 -1px 0 #3071a9;background-image:-webkit-gradient(linear,left 0,left 100%,from(#428bca),to(#3278b3));background-image:-webkit-linear-gradient(top,#428bca,0,#3278b3,100%);background-image:-moz-linear-gradient(top,#428bca 0,#3278b3 100%);background-image:linear-gradient(to bottom,#428bca 0,#3278b3 100%);background-repeat:repeat-x;border-color:#3278b3;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff3278b3', GradientType=0)}.panel{-webkit-box-shadow:0 1px 2px rgba(0,0,0,.05);box-shadow:0 1px 2px rgba(0,0,0,.05)}.panel-default>.panel-heading{background-image:-webkit-gradient(linear,left 0,left 100%,from(#f5f5f5),to(#e8e8e8));background-image:-webkit-linear-gradient(top,#f5f5f5,0,#e8e8e8,100%);background-image:-moz-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:linear-gradient(to bottom,#f5f5f5 0,#e8e8e8 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0)}.panel-primary>.panel-heading{background-image:-webkit-gradient(linear,left 0,left 100%,from(#428bca),to(#357ebd));background-image:-webkit-linear-gradient(top,#428bca,0,#357ebd,100%);background-image:-moz-linear-gradient(top,#428bca 0,#357ebd 100%);background-image:linear-gradient(to bottom,#428bca 0,#357ebd 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff357ebd', GradientType=0)}.panel-success>.panel-heading{background-image:-webkit-gradient(linear,left 0,left 100%,from(#dff0d8),to(#d0e9c6));background-image:-webkit-linear-gradient(top,#dff0d8,0,#d0e9c6,100%);background-image:-moz-linear-gradient(top,#dff0d8 0,#d0e9c6 100%);background-image:linear-gradient(to bottom,#dff0d8 0,#d0e9c6 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffd0e9c6', GradientType=0)}.panel-info>.panel-heading{background-image:-webkit-gradient(linear,left 0,left 100%,from(#d9edf7),to(#c4e3f3));background-image:-webkit-linear-gradient(top,#d9edf7,0,#c4e3f3,100%);background-image:-moz-linear-gradient(top,#d9edf7 0,#c4e3f3 100%);background-image:linear-gradient(to bottom,#d9edf7 0,#c4e3f3 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffc4e3f3', GradientType=0)}.panel-warning>.panel-heading{background-image:-webkit-gradient(linear,left 0,left 100%,from(#fcf8e3),to(#faf2cc));background-image:-webkit-linear-gradient(top,#fcf8e3,0,#faf2cc,100%);background-image:-moz-linear-gradient(top,#fcf8e3 0,#faf2cc 100%);background-image:linear-gradient(to bottom,#fcf8e3 0,#faf2cc 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fffaf2cc', GradientType=0)}.panel-danger>.panel-heading{background-image:-webkit-gradient(linear,left 0,left 100%,from(#f2dede),to(#ebcccc));background-image:-webkit-linear-gradient(top,#f2dede,0,#ebcccc,100%);background-image:-moz-linear-gradient(top,#f2dede 0,#ebcccc 100%);background-image:linear-gradient(to bottom,#f2dede 0,#ebcccc 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffebcccc', GradientType=0)}.well{background-image:-webkit-gradient(linear,left 0,left 100%,from(#e8e8e8),to(#f5f5f5));background-image:-webkit-linear-gradient(top,#e8e8e8,0,#f5f5f5,100%);background-image:-moz-linear-gradient(top,#e8e8e8 0,#f5f5f5 100%);background-image:linear-gradient(to bottom,#e8e8e8 0,#f5f5f5 100%);background-repeat:repeat-x;border-color:#dcdcdc;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8', endColorstr='#fff5f5f5', GradientType=0);-webkit-box-shadow:inset 0 1px 3px rgba(0,0,0,.05),0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 3px rgba(0,0,0,.05),0 1px 0 rgba(255,255,255,.1)}body{padding:10px}a:active,a:focus{outline:0}a img{border:none}#preview{background-image:url(../img/Google-YouTube-128.png);background-repeat:no-repeat;background-position:center center;height:325px;width:430px}#insert-btn{margin-left:5px}.alert{margin-bottom:5px;padding:5px}.form-group{margin-bottom:0}.alert-info{font-size:12px} \ No newline at end of file diff --git a/local/modules/Tinymce/Resources/js/tinymce/plugins/youtube/img/Google-YouTube-128.png b/local/modules/Tinymce/Resources/js/tinymce/plugins/youtube/img/Google-YouTube-128.png new file mode 100644 index 0000000000000000000000000000000000000000..ef60bd04b08c8a4e8c262b9df0e87661d32dc8e1 GIT binary patch literal 11800 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 GH#s%4|H~Bs literal 0 HcmV?d00001 diff --git a/local/modules/Tinymce/Resources/js/tinymce/plugins/youtube/img/youtube.gif b/local/modules/Tinymce/Resources/js/tinymce/plugins/youtube/img/youtube.gif new file mode 100644 index 0000000000000000000000000000000000000000..6d673d1d6781d47552da8ced38acb3f844c88e88 GIT binary patch literal 212 zcmZ?wbhEHb6k!ly*v!fB9|+Ez`9E{!|FpFK#>W2{7|xtIV{B~9zyOj0l4wBjCkrD3 z11EzHNE~Da152a9Nzc`LZ!k6d`1in#kxfa#O``8Wqs-gWQ{}C<8{g`@-2P}+@Y?M^ zcP6ZpJ+LgRkEMkv(My(tiSgj3aE_cstPUkw5;>}mK9o3|a9h|?tfb2pvo$iOLPRv3 uH8s4ds3bQmHG(;(r8c)LE|r0?+BPR7G%zPkC$($d{HP+y#Y-dv8LR;@J4?a< literal 0 HcmV?d00001 diff --git a/local/modules/Tinymce/Resources/js/tinymce/plugins/youtube/js/main.js b/local/modules/Tinymce/Resources/js/tinymce/plugins/youtube/js/main.js new file mode 100644 index 00000000..3f55be0e --- /dev/null +++ b/local/modules/Tinymce/Resources/js/tinymce/plugins/youtube/js/main.js @@ -0,0 +1,807 @@ +/*! + * bootstrap.js v3.0.0 by @fat and @mdo + * Copyright 2013 Twitter Inc. + * http://www.apache.org/licenses/LICENSE-2.0 + */ +if (!jQuery)throw new Error("Bootstrap requires jQuery"); ++function(t) { + "use strict"; + function e() { + var t = document.createElement("bootstrap"), e = {WebkitTransition: "webkitTransitionEnd", MozTransition: "transitionend", OTransition: "oTransitionEnd otransitionend", transition: "transitionend"}; + for (var i in e)if (void 0 !== t.style[i])return{end: e[i]} + } + + t.fn.emulateTransitionEnd = function(e) { + var i = !1, n = this; + t(this).one(t.support.transition.end, function() { + i = !0 + }); + var o = function() { + i || t(n).trigger(t.support.transition.end) + }; + return setTimeout(o, e), this + }, t(function() { + t.support.transition = e() + }) +}(window.jQuery), +function(t) { + "use strict"; + var e = '[data-dismiss="alert"]', i = function(i) { + t(i).on("click", e, this.close) + }; + i.prototype.close = function(e) { + function i() { + s.trigger("closed.bs.alert").remove() + } + + var n = t(this), o = n.attr("data-target"); + o || (o = n.attr("href"), o = o && o.replace(/.*(?=#[^\s]*$)/, "")); + var s = t(o); + e && e.preventDefault(), s.length || (s = n.hasClass("alert") ? n : n.parent()), s.trigger(e = t.Event("close.bs.alert")), e.isDefaultPrevented() || (s.removeClass("in"), t.support.transition && s.hasClass("fade") ? s.one(t.support.transition.end, i).emulateTransitionEnd(150) : i()) + }; + var n = t.fn.alert; + t.fn.alert = function(e) { + return this.each(function() { + var n = t(this), o = n.data("bs.alert"); + o || n.data("bs.alert", o = new i(this)), "string" == typeof e && o[e].call(n) + }) + }, t.fn.alert.Constructor = i, t.fn.alert.noConflict = function() { + return t.fn.alert = n, this + }, t(document).on("click.bs.alert.data-api", e, i.prototype.close) +}(window.jQuery), +function(t) { + "use strict"; + var e = function(i, n) { + this.$element = t(i), this.options = t.extend({}, e.DEFAULTS, n) + }; + e.DEFAULTS = {loadingText: "loading..."}, e.prototype.setState = function(t) { + var e = "disabled", i = this.$element, n = i.is("input") ? "val" : "html", o = i.data(); + t += "Text", o.resetText || i.data("resetText", i[n]()), i[n](o[t] || this.options[t]), setTimeout(function() { + "loadingText" == t ? i.addClass(e).attr(e, e) : i.removeClass(e).removeAttr(e) + }, 0) + }, e.prototype.toggle = function() { + var t = this.$element.closest('[data-toggle="buttons"]'); + if (t.length) { + var e = this.$element.find("input").prop("checked", !this.$element.hasClass("active")).trigger("change"); + "radio" === e.prop("type") && t.find(".active").removeClass("active") + } + this.$element.toggleClass("active") + }; + var i = t.fn.button; + t.fn.button = function(i) { + return this.each(function() { + var n = t(this), o = n.data("bs.button"), s = "object" == typeof i && i; + o || n.data("bs.button", o = new e(this, s)), "toggle" == i ? o.toggle() : i && o.setState(i) + }) + }, t.fn.button.Constructor = e, t.fn.button.noConflict = function() { + return t.fn.button = i, this + }, t(document).on("click.bs.button.data-api", "[data-toggle^=button]", function(e) { + var i = t(e.target); + i.hasClass("btn") || (i = i.closest(".btn")), i.button("toggle"), e.preventDefault() + }) +}(window.jQuery), +function(t) { + "use strict"; + var e = function(e, i) { + this.$element = t(e), this.$indicators = this.$element.find(".carousel-indicators"), this.options = i, this.paused = this.sliding = this.interval = this.$active = this.$items = null, "hover" == this.options.pause && this.$element.on("mouseenter", t.proxy(this.pause, this)).on("mouseleave", t.proxy(this.cycle, this)) + }; + e.DEFAULTS = {interval: 5e3, pause: "hover", wrap: !0}, e.prototype.cycle = function(e) { + return e || (this.paused = !1), this.interval && clearInterval(this.interval), this.options.interval && !this.paused && (this.interval = setInterval(t.proxy(this.next, this), this.options.interval)), this + }, e.prototype.getActiveIndex = function() { + return this.$active = this.$element.find(".item.active"), this.$items = this.$active.parent().children(), this.$items.index(this.$active) + }, e.prototype.to = function(e) { + var i = this, n = this.getActiveIndex(); + return e > this.$items.length - 1 || 0 > e ? void 0 : this.sliding ? this.$element.one("slid", function() { + i.to(e) + }) : n == e ? this.pause().cycle() : this.slide(e > n ? "next" : "prev", t(this.$items[e])) + }, e.prototype.pause = function(e) { + return e || (this.paused = !0), this.$element.find(".next, .prev").length && t.support.transition.end && (this.$element.trigger(t.support.transition.end), this.cycle(!0)), this.interval = clearInterval(this.interval), this + }, e.prototype.next = function() { + return this.sliding ? void 0 : this.slide("next") + }, e.prototype.prev = function() { + return this.sliding ? void 0 : this.slide("prev") + }, e.prototype.slide = function(e, i) { + var n = this.$element.find(".item.active"), o = i || n[e](), s = this.interval, a = "next" == e ? "left" : "right", r = "next" == e ? "first" : "last", l = this; + if (!o.length) { + if (!this.options.wrap)return; + o = this.$element.find(".item")[r]() + } + this.sliding = !0, s && this.pause(); + var h = t.Event("slide.bs.carousel", {relatedTarget: o[0], direction: a}); + if (!o.hasClass("active")) { + if (this.$indicators.length && (this.$indicators.find(".active").removeClass("active"), this.$element.one("slid", function() { + var e = t(l.$indicators.children()[l.getActiveIndex()]); + e && e.addClass("active") + })), t.support.transition && this.$element.hasClass("slide")) { + if (this.$element.trigger(h), h.isDefaultPrevented())return; + o.addClass(e), o[0].offsetWidth, n.addClass(a), o.addClass(a), n.one(t.support.transition.end,function() { + o.removeClass([e, a].join(" ")).addClass("active"), n.removeClass(["active", a].join(" ")), l.sliding = !1, setTimeout(function() { + l.$element.trigger("slid") + }, 0) + }).emulateTransitionEnd(600) + } else { + if (this.$element.trigger(h), h.isDefaultPrevented())return; + n.removeClass("active"), o.addClass("active"), this.sliding = !1, this.$element.trigger("slid") + } + return s && this.cycle(), this + } + }; + var i = t.fn.carousel; + t.fn.carousel = function(i) { + return this.each(function() { + var n = t(this), o = n.data("bs.carousel"), s = t.extend({}, e.DEFAULTS, n.data(), "object" == typeof i && i), a = "string" == typeof i ? i : s.slide; + o || n.data("bs.carousel", o = new e(this, s)), "number" == typeof i ? o.to(i) : a ? o[a]() : s.interval && o.pause().cycle() + }) + }, t.fn.carousel.Constructor = e, t.fn.carousel.noConflict = function() { + return t.fn.carousel = i, this + }, t(document).on("click.bs.carousel.data-api", "[data-slide], [data-slide-to]", function(e) { + var i, n = t(this), o = t(n.attr("data-target") || (i = n.attr("href")) && i.replace(/.*(?=#[^\s]+$)/, "")), s = t.extend({}, o.data(), n.data()), a = n.attr("data-slide-to"); + a && (s.interval = !1), o.carousel(s), (a = n.attr("data-slide-to")) && o.data("bs.carousel").to(a), e.preventDefault() + }), t(window).on("load", function() { + t('[data-ride="carousel"]').each(function() { + var e = t(this); + e.carousel(e.data()) + }) + }) +}(window.jQuery), +function(t) { + "use strict"; + var e = function(i, n) { + this.$element = t(i), this.options = t.extend({}, e.DEFAULTS, n), this.transitioning = null, this.options.parent && (this.$parent = t(this.options.parent)), this.options.toggle && this.toggle() + }; + e.DEFAULTS = {toggle: !0}, e.prototype.dimension = function() { + var t = this.$element.hasClass("width"); + return t ? "width" : "height" + }, e.prototype.show = function() { + if (!this.transitioning && !this.$element.hasClass("in")) { + var e = t.Event("show.bs.collapse"); + if (this.$element.trigger(e), !e.isDefaultPrevented()) { + var i = this.$parent && this.$parent.find("> .panel > .in"); + if (i && i.length) { + var n = i.data("bs.collapse"); + if (n && n.transitioning)return; + i.collapse("hide"), n || i.data("bs.collapse", null) + } + var o = this.dimension(); + this.$element.removeClass("collapse").addClass("collapsing")[o](0), this.transitioning = 1; + var s = function() { + this.$element.removeClass("collapsing").addClass("in")[o]("auto"), this.transitioning = 0, this.$element.trigger("shown.bs.collapse") + }; + if (!t.support.transition)return s.call(this); + var a = t.camelCase(["scroll", o].join("-")); + this.$element.one(t.support.transition.end, t.proxy(s, this)).emulateTransitionEnd(350)[o](this.$element[0][a]) + } + } + }, e.prototype.hide = function() { + if (!this.transitioning && this.$element.hasClass("in")) { + var e = t.Event("hide.bs.collapse"); + if (this.$element.trigger(e), !e.isDefaultPrevented()) { + var i = this.dimension(); + this.$element[i](this.$element[i]())[0].offsetHeight, this.$element.addClass("collapsing").removeClass("collapse").removeClass("in"), this.transitioning = 1; + var n = function() { + this.transitioning = 0, this.$element.trigger("hidden.bs.collapse").removeClass("collapsing").addClass("collapse") + }; + return t.support.transition ? void this.$element[i](0).one(t.support.transition.end, t.proxy(n, this)).emulateTransitionEnd(350) : n.call(this) + } + } + }, e.prototype.toggle = function() { + this[this.$element.hasClass("in") ? "hide" : "show"]() + }; + var i = t.fn.collapse; + t.fn.collapse = function(i) { + return this.each(function() { + var n = t(this), o = n.data("bs.collapse"), s = t.extend({}, e.DEFAULTS, n.data(), "object" == typeof i && i); + o || n.data("bs.collapse", o = new e(this, s)), "string" == typeof i && o[i]() + }) + }, t.fn.collapse.Constructor = e, t.fn.collapse.noConflict = function() { + return t.fn.collapse = i, this + }, t(document).on("click.bs.collapse.data-api", "[data-toggle=collapse]", function(e) { + var i, n = t(this), o = n.attr("data-target") || e.preventDefault() || (i = n.attr("href")) && i.replace(/.*(?=#[^\s]+$)/, ""), s = t(o), a = s.data("bs.collapse"), r = a ? "toggle" : n.data(), l = n.attr("data-parent"), h = l && t(l); + a && a.transitioning || (h && h.find('[data-toggle=collapse][data-parent="' + l + '"]').not(n).addClass("collapsed"), n[s.hasClass("in") ? "addClass" : "removeClass"]("collapsed")), s.collapse(r) + }) +}(window.jQuery), +function(t) { + "use strict"; + function e() { + t(n).remove(), t(o).each(function(e) { + var n = i(t(this)); + n.hasClass("open") && (n.trigger(e = t.Event("hide.bs.dropdown")), e.isDefaultPrevented() || n.removeClass("open").trigger("hidden.bs.dropdown")) + }) + } + + function i(e) { + var i = e.attr("data-target"); + i || (i = e.attr("href"), i = i && /#/.test(i) && i.replace(/.*(?=#[^\s]*$)/, "")); + var n = i && t(i); + return n && n.length ? n : e.parent() + } + + var n = ".dropdown-backdrop", o = "[data-toggle=dropdown]", s = function(e) { + t(e).on("click.bs.dropdown", this.toggle) + }; + s.prototype.toggle = function(n) { + var o = t(this); + if (!o.is(".disabled, :disabled")) { + var s = i(o), a = s.hasClass("open"); + if (e(), !a) { + if ("ontouchstart"in document.documentElement && !s.closest(".navbar-nav").length && t(' + +
    +
    +
    + {intl l='List of the text area where the wysiwyg editor will be used' d='tinymce.bo.default'} +
    +
    +

    + {intl l='This is a critical data, to update it you have to inform the ids (#timymce_configuration-id-test_zone for example) or the classes (.wysiwyg for example) , separated with comas, of the text areas you want to have the wysiwyg editor directly in the data base.' d='tinymce.bo.default'} +

    +
    + +
    + {render_form_field form=$form field="available_text_areas"} +
    +
    +
    + +
    +
    + {if $form_error} +
    {$form_error_message}
    + {/if} + +
    + {render_form_field form=$form field="editor_height"} + + {render_form_field form=$form field="force_pasting_as_text"} + {render_form_field form=$form field="set_images_as_responsive"} + {render_form_field form=$form field="show_menu_bar"} + {render_form_field form=$form field="custom_css"} +
    + +
    + {render_form_field form=$form field="test_zone" extra_class="wysiwyg"} +
    +
    +
    + + {/form} + + + + + \ No newline at end of file diff --git a/local/modules/Tinymce/templates/backOffice/default/tinymce_init.tpl b/local/modules/Tinymce/templates/backOffice/default/tinymce_init.tpl new file mode 100644 index 00000000..1b03d0d7 --- /dev/null +++ b/local/modules/Tinymce/templates/backOffice/default/tinymce_init.tpl @@ -0,0 +1,123 @@ + + + diff --git a/local/modules/VirtualProductControl/Config/config.xml b/local/modules/VirtualProductControl/Config/config.xml new file mode 100644 index 00000000..689f7901 --- /dev/null +++ b/local/modules/VirtualProductControl/Config/config.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + diff --git a/local/modules/VirtualProductControl/Config/module.xml b/local/modules/VirtualProductControl/Config/module.xml new file mode 100644 index 00000000..42c051d7 --- /dev/null +++ b/local/modules/VirtualProductControl/Config/module.xml @@ -0,0 +1,20 @@ + + + VirtualProductControl\VirtualProductControl + + Virtual Product Controller + Check if a virtual product delivery module is enabled if at least one product is virtual + + + Contrôle de produit virtuel + Vérifie qu'un module de livraison pour produit virtuel soit activé si des produits virtuels existent + + 2.4.3 + + Manuel Raynaud + manu@raynaud.io + + classic + 2.4.3 + alpha + diff --git a/local/modules/VirtualProductControl/Hook/VirtualProductHook.php b/local/modules/VirtualProductControl/Hook/VirtualProductHook.php new file mode 100644 index 00000000..8ded689a --- /dev/null +++ b/local/modules/VirtualProductControl/Hook/VirtualProductHook.php @@ -0,0 +1,62 @@ + + */ +class VirtualProductHook extends BaseHook +{ + /** + * @var SecurityContext + */ + protected $securityContext; + + public function __construct(SecurityContext $securityContext) + { + $this->securityContext = $securityContext; + } + + public function onMainBeforeContent(HookRenderEvent $event) + { + if ($this->securityContext->isGranted( + ["ADMIN"], + [AdminResources::PRODUCT], + [], + [AccessManager::VIEW] + )) { + $products = ProductQuery::create() + ->filterByVirtual(1) + ->filterByVisible(1) + ->count(); + + if ($products > 0) { + $deliveryModule = ModuleQuery::create()->retrieveVirtualProductDelivery(); + + if (false === $deliveryModule) { + $event->add($this->render('virtual-delivery-warning.html')); + } + } + } + } +} diff --git a/local/modules/VirtualProductControl/I18n/backOffice/default/de_DE.php b/local/modules/VirtualProductControl/I18n/backOffice/default/de_DE.php new file mode 100644 index 00000000..aaa4698a --- /dev/null +++ b/local/modules/VirtualProductControl/I18n/backOffice/default/de_DE.php @@ -0,0 +1,5 @@ + 'Mindestens ein virtuelles Produkt ist verfügbar, aber kein Liefermodul für virtuellen Produkte ist aktiviert', +]; diff --git a/local/modules/VirtualProductControl/I18n/backOffice/default/en_US.php b/local/modules/VirtualProductControl/I18n/backOffice/default/en_US.php new file mode 100644 index 00000000..2b71ceb9 --- /dev/null +++ b/local/modules/VirtualProductControl/I18n/backOffice/default/en_US.php @@ -0,0 +1,5 @@ + 'At least one virtual product is online but no virtual product delivery module enabled', +); diff --git a/local/modules/VirtualProductControl/I18n/backOffice/default/fr_FR.php b/local/modules/VirtualProductControl/I18n/backOffice/default/fr_FR.php new file mode 100644 index 00000000..b04c5963 --- /dev/null +++ b/local/modules/VirtualProductControl/I18n/backOffice/default/fr_FR.php @@ -0,0 +1,5 @@ + 'Au moins un produit virtuel est en vente mais aucun module de livraison pour produit virtuel n\'est activé', +]; diff --git a/local/modules/VirtualProductControl/I18n/backOffice/default/it_IT.php b/local/modules/VirtualProductControl/I18n/backOffice/default/it_IT.php new file mode 100644 index 00000000..1a42252f --- /dev/null +++ b/local/modules/VirtualProductControl/I18n/backOffice/default/it_IT.php @@ -0,0 +1,5 @@ + 'Almeno un prodotto virtuale è online, ma nessun modulo di consegna del prodotto virtuale è abilitato', +]; diff --git a/local/modules/VirtualProductControl/I18n/backOffice/default/tr_TR.php b/local/modules/VirtualProductControl/I18n/backOffice/default/tr_TR.php new file mode 100644 index 00000000..b2fd7a5e --- /dev/null +++ b/local/modules/VirtualProductControl/I18n/backOffice/default/tr_TR.php @@ -0,0 +1,5 @@ + 'En az bir sanal ürün hiç sanal ürün teslim modülü etkin yayında', +]; diff --git a/local/modules/VirtualProductControl/I18n/de_DE.php b/local/modules/VirtualProductControl/I18n/de_DE.php new file mode 100644 index 00000000..aaa4698a --- /dev/null +++ b/local/modules/VirtualProductControl/I18n/de_DE.php @@ -0,0 +1,5 @@ + 'Mindestens ein virtuelles Produkt ist verfügbar, aber kein Liefermodul für virtuellen Produkte ist aktiviert', +]; diff --git a/local/modules/VirtualProductControl/I18n/en_US.php b/local/modules/VirtualProductControl/I18n/en_US.php new file mode 100644 index 00000000..ecd80759 --- /dev/null +++ b/local/modules/VirtualProductControl/I18n/en_US.php @@ -0,0 +1,4 @@ + 'At least one virtual product is online but no virtual product delivery module enabled', +); diff --git a/local/modules/VirtualProductControl/I18n/fr_FR.php b/local/modules/VirtualProductControl/I18n/fr_FR.php new file mode 100644 index 00000000..b04c5963 --- /dev/null +++ b/local/modules/VirtualProductControl/I18n/fr_FR.php @@ -0,0 +1,5 @@ + 'Au moins un produit virtuel est en vente mais aucun module de livraison pour produit virtuel n\'est activé', +]; diff --git a/local/modules/VirtualProductControl/I18n/it_IT.php b/local/modules/VirtualProductControl/I18n/it_IT.php new file mode 100644 index 00000000..1a42252f --- /dev/null +++ b/local/modules/VirtualProductControl/I18n/it_IT.php @@ -0,0 +1,5 @@ + 'Almeno un prodotto virtuale è online, ma nessun modulo di consegna del prodotto virtuale è abilitato', +]; diff --git a/local/modules/VirtualProductControl/I18n/ru_RU.php b/local/modules/VirtualProductControl/I18n/ru_RU.php new file mode 100644 index 00000000..2b7b7727 --- /dev/null +++ b/local/modules/VirtualProductControl/I18n/ru_RU.php @@ -0,0 +1,4 @@ + 'Включен по крайне мере один виртуальный товар, но модуль доставки виртуальных товаров не активирован', +); diff --git a/local/modules/VirtualProductControl/I18n/tr_TR.php b/local/modules/VirtualProductControl/I18n/tr_TR.php new file mode 100644 index 00000000..b2fd7a5e --- /dev/null +++ b/local/modules/VirtualProductControl/I18n/tr_TR.php @@ -0,0 +1,5 @@ + 'En az bir sanal ürün hiç sanal ürün teslim modülü etkin yayında', +]; diff --git a/local/modules/VirtualProductControl/LICENSE.txt b/local/modules/VirtualProductControl/LICENSE.txt new file mode 100644 index 00000000..65c5ca88 --- /dev/null +++ b/local/modules/VirtualProductControl/LICENSE.txt @@ -0,0 +1,165 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + + This version of the GNU Lesser General Public License incorporates +the terms and conditions of version 3 of the GNU General Public +License, supplemented by the additional permissions listed below. + + 0. Additional Definitions. + + As used herein, "this License" refers to version 3 of the GNU Lesser +General Public License, and the "GNU GPL" refers to version 3 of the GNU +General Public License. + + "The Library" refers to a covered work governed by this License, +other than an Application or a Combined Work as defined below. + + An "Application" is any work that makes use of an interface provided +by the Library, but which is not otherwise based on the Library. +Defining a subclass of a class defined by the Library is deemed a mode +of using an interface provided by the Library. + + A "Combined Work" is a work produced by combining or linking an +Application with the Library. The particular version of the Library +with which the Combined Work was made is also called the "Linked +Version". + + The "Minimal Corresponding Source" for a Combined Work means the +Corresponding Source for the Combined Work, excluding any source code +for portions of the Combined Work that, considered in isolation, are +based on the Application, and not on the Linked Version. + + The "Corresponding Application Code" for a Combined Work means the +object code and/or source code for the Application, including any data +and utility programs needed for reproducing the Combined Work from the +Application, but excluding the System Libraries of the Combined Work. + + 1. Exception to Section 3 of the GNU GPL. + + You may convey a covered work under sections 3 and 4 of this License +without being bound by section 3 of the GNU GPL. + + 2. Conveying Modified Versions. + + If you modify a copy of the Library, and, in your modifications, a +facility refers to a function or data to be supplied by an Application +that uses the facility (other than as an argument passed when the +facility is invoked), then you may convey a copy of the modified +version: + + a) under this License, provided that you make a good faith effort to + ensure that, in the event an Application does not supply the + function or data, the facility still operates, and performs + whatever part of its purpose remains meaningful, or + + b) under the GNU GPL, with none of the additional permissions of + this License applicable to that copy. + + 3. Object Code Incorporating Material from Library Header Files. + + The object code form of an Application may incorporate material from +a header file that is part of the Library. You may convey such object +code under terms of your choice, provided that, if the incorporated +material is not limited to numerical parameters, data structure +layouts and accessors, or small macros, inline functions and templates +(ten or fewer lines in length), you do both of the following: + + a) Give prominent notice with each copy of the object code that the + Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the object code with a copy of the GNU GPL and this license + document. + + 4. Combined Works. + + You may convey a Combined Work under terms of your choice that, +taken together, effectively do not restrict modification of the +portions of the Library contained in the Combined Work and reverse +engineering for debugging such modifications, if you also do each of +the following: + + a) Give prominent notice with each copy of the Combined Work that + the Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the Combined Work with a copy of the GNU GPL and this license + document. + + c) For a Combined Work that displays copyright notices during + execution, include the copyright notice for the Library among + these notices, as well as a reference directing the user to the + copies of the GNU GPL and this license document. + + d) Do one of the following: + + 0) Convey the Minimal Corresponding Source under the terms of this + License, and the Corresponding Application Code in a form + suitable for, and under terms that permit, the user to + recombine or relink the Application with a modified version of + the Linked Version to produce a modified Combined Work, in the + manner specified by section 6 of the GNU GPL for conveying + Corresponding Source. + + 1) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (a) uses at run time + a copy of the Library already present on the user's computer + system, and (b) will operate properly with a modified version + of the Library that is interface-compatible with the Linked + Version. + + e) Provide Installation Information, but only if you would otherwise + be required to provide such information under section 6 of the + GNU GPL, and only to the extent that such information is + necessary to install and execute a modified version of the + Combined Work produced by recombining or relinking the + Application with a modified version of the Linked Version. (If + you use option 4d0, the Installation Information must accompany + the Minimal Corresponding Source and Corresponding Application + Code. If you use option 4d1, you must provide the Installation + Information in the manner specified by section 6 of the GNU GPL + for conveying Corresponding Source.) + + 5. Combined Libraries. + + You may place library facilities that are a work based on the +Library side by side in a single library together with other library +facilities that are not Applications and are not covered by this +License, and convey such a combined library under terms of your +choice, if you do both of the following: + + a) Accompany the combined library with a copy of the same work based + on the Library, uncombined with any other library facilities, + conveyed under the terms of this License. + + b) Give prominent notice with the combined library that part of it + is a work based on the Library, and explaining where to find the + accompanying uncombined form of the same work. + + 6. Revised Versions of the GNU Lesser General Public License. + + The Free Software Foundation may publish revised and/or new versions +of the GNU Lesser General Public License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. + + Each version is given a distinguishing version number. If the +Library as you received it specifies that a certain numbered version +of the GNU Lesser General Public License "or any later version" +applies to it, you have the option of following the terms and +conditions either of that published version or of any later version +published by the Free Software Foundation. If the Library as you +received it does not specify a version number of the GNU Lesser +General Public License, you may choose any version of the GNU Lesser +General Public License ever published by the Free Software Foundation. + + If the Library as you received it specifies that a proxy can decide +whether future versions of the GNU Lesser General Public License shall +apply, that proxy's public statement of acceptance of any version is +permanent authorization for you to choose that version for the +Library. diff --git a/local/modules/VirtualProductControl/VirtualProductControl.php b/local/modules/VirtualProductControl/VirtualProductControl.php new file mode 100644 index 00000000..e3211039 --- /dev/null +++ b/local/modules/VirtualProductControl/VirtualProductControl.php @@ -0,0 +1,20 @@ + +
    + +
    + \ No newline at end of file diff --git a/local/modules/VirtualProductDelivery/Config/config.xml b/local/modules/VirtualProductDelivery/Config/config.xml new file mode 100644 index 00000000..1b16d36c --- /dev/null +++ b/local/modules/VirtualProductDelivery/Config/config.xml @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/local/modules/VirtualProductDelivery/Config/module.xml b/local/modules/VirtualProductDelivery/Config/module.xml new file mode 100644 index 00000000..7175d41f --- /dev/null +++ b/local/modules/VirtualProductDelivery/Config/module.xml @@ -0,0 +1,24 @@ + + + VirtualProductDelivery\VirtualProductDelivery + + Virtual Products Delivery + + + Livraison Produits Virtuels + + + en_US + fr_FR + + 2.4.3 + + Julien Chanséaume + jchanseaume@openstudio.fr + + delivery + 2.4.3 + alpha + diff --git a/local/modules/VirtualProductDelivery/EventListeners/SendMail.php b/local/modules/VirtualProductDelivery/EventListeners/SendMail.php new file mode 100644 index 00000000..2eea49e5 --- /dev/null +++ b/local/modules/VirtualProductDelivery/EventListeners/SendMail.php @@ -0,0 +1,122 @@ + + */ +class SendMail implements EventSubscriberInterface +{ + /** @var MailerFactory */ + protected $mailer; + + /** @var EventDispatcherInterface */ + protected $eventDispatcher; + + public function __construct(MailerFactory $mailer, EventDispatcherInterface $eventDispatcher) + { + $this->mailer = $mailer; + $this->eventDispatcher = $eventDispatcher; + } + + public function updateStatus(OrderEvent $event) + { + $order = $event->getOrder(); + + if ($order->hasVirtualProduct() && $order->isPaid(true)) { + $this->eventDispatcher->dispatch( + VirtualProductDeliveryEvents::ORDER_VIRTUAL_FILES_AVAILABLE, + $event + ); + } + } + + /** + * Send email to notify customer that files for virtual products are available + * + * @param OrderEvent $event + * @throws \Exception + */ + public function sendEmail(OrderEvent $event) + { + $order = $event->getOrder(); + + // Be sure that we have a document to download + $virtualProductCount = OrderProductQuery::create() + ->filterByOrderId($order->getId()) + ->filterByVirtual(true) + ->filterByVirtualDocument(null, Criteria::NOT_EQUAL) + ->count(); + + if ($virtualProductCount > 0) { + $customer = $order->getCustomer(); + + $this->mailer->sendEmailToCustomer( + 'mail_virtualproduct', + $customer, + [ + 'customer_id' => $customer->getId(), + 'order_id' => $order->getId(), + 'order_ref' => $order->getRef(), + 'order_date' => $order->getCreatedAt(), + 'update_date' => $order->getUpdatedAt() + ] + ); + } else { + Tlog::getInstance()->warning( + "Virtual product download message not sent to customer: there's nothing to downnload" + ); + } + } + + + /** + * Returns an array of event names this subscriber wants to listen to. + * + * The array keys are event names and the value can be: + * + * * The method name to call (priority defaults to 0) + * * An array composed of the method name to call and the priority + * * An array of arrays composed of the method names to call and respective + * priorities, or 0 if unset + * + * For instance: + * + * * array('eventName' => 'methodName') + * * array('eventName' => array('methodName', $priority)) + * * array('eventName' => array(array('methodName1', $priority), array('methodName2')) + * + * @return array The event names to listen to + * + * @api + */ + public static function getSubscribedEvents() + { + return array( + TheliaEvents::ORDER_UPDATE_STATUS => array("updateStatus", 128), + VirtualProductDeliveryEvents::ORDER_VIRTUAL_FILES_AVAILABLE => array("sendEmail", 128) + ); + } +} diff --git a/local/modules/VirtualProductDelivery/EventListeners/VirtualProductEvents.php b/local/modules/VirtualProductDelivery/EventListeners/VirtualProductEvents.php new file mode 100644 index 00000000..8b398ea6 --- /dev/null +++ b/local/modules/VirtualProductDelivery/EventListeners/VirtualProductEvents.php @@ -0,0 +1,119 @@ + + */ +class VirtualProductEvents implements EventSubscriberInterface +{ + + public function handleOrder(VirtualProductOrderHandleEvent $event) + { + $documentId = MetaDataQuery::getVal( + 'virtual', + MetaDataModel::PSE_KEY, + $event->getPseId() + ); + + if (null !== $documentId) { + $productDocument = ProductDocumentQuery::create()->findPk($documentId); + if (null !== $productDocument) { + $event->setPath($productDocument->getFile()); + } + } + + } + + public function download(VirtualProductOrderDownloadResponseEvent $event) + { + $orderProduct = $event->getOrderProduct(); + + if ($orderProduct->getVirtualDocument()) { + $baseSourceFilePath = ConfigQuery::read('documents_library_path'); + if ($baseSourceFilePath === null) { + $baseSourceFilePath = THELIA_LOCAL_DIR . 'media' . DS . 'documents'; + } else { + $baseSourceFilePath = THELIA_ROOT . $baseSourceFilePath; + } + + // try to get the file + $path = $baseSourceFilePath . DS . 'product' . DS . $orderProduct->getVirtualDocument(); + + if (!is_file($path) || !is_readable($path)) { + throw new \ErrorException( + Translator::getInstance()->trans( + "The file [%file] does not exist", + [ + "%file" => $orderProduct->getId() + ], + VirtualProductDelivery::MESSAGE_DOMAIN + ) + ); + } + + $response = new BinaryFileResponse($path); + $response->setContentDisposition(ResponseHeaderBag::DISPOSITION_ATTACHMENT); + $event->setResponse($response); + + } + } + + + + /** + * Returns an array of event names this subscriber wants to listen to. + * + * The array keys are event names and the value can be: + * + * * The method name to call (priority defaults to 0) + * * An array composed of the method name to call and the priority + * * An array of arrays composed of the method names to call and respective + * priorities, or 0 if unset + * + * For instance: + * + * * array('eventName' => 'methodName') + * * array('eventName' => array('methodName', $priority)) + * * array('eventName' => array(array('methodName1', $priority), array('methodName2')) + * + * @return array The event names to listen to + * + * @api + */ + public static function getSubscribedEvents() + { + return [ + TheliaEvents::VIRTUAL_PRODUCT_ORDER_HANDLE => ['handleOrder', 128], + TheliaEvents::VIRTUAL_PRODUCT_ORDER_DOWNLOAD_RESPONSE => ['download', 128] + ]; + } +} diff --git a/local/modules/VirtualProductDelivery/Events/VirtualProductDeliveryEvents.php b/local/modules/VirtualProductDelivery/Events/VirtualProductDeliveryEvents.php new file mode 100644 index 00000000..4850aa69 --- /dev/null +++ b/local/modules/VirtualProductDelivery/Events/VirtualProductDeliveryEvents.php @@ -0,0 +1,26 @@ + + */ +class VirtualProductDeliveryEvents extends ActionEvent +{ + const ORDER_VIRTUAL_FILES_AVAILABLE = 'virtual_product_delivery.virtual_files_available'; +} diff --git a/local/modules/VirtualProductDelivery/Hook/HookManager.php b/local/modules/VirtualProductDelivery/Hook/HookManager.php new file mode 100644 index 00000000..8dab669f --- /dev/null +++ b/local/modules/VirtualProductDelivery/Hook/HookManager.php @@ -0,0 +1,39 @@ + + */ +class HookManager extends BaseHook +{ + public function onAccountOrderAfterProducts(HookRenderEvent $event) + { + $orderId = $event->getArgument('order'); + + if (null !== $orderId) { + $render = $this->render( + 'account-order-after-products.html', + [ + "order_id" => $orderId + ] + ); + $event->add($render); + } + } +} diff --git a/local/modules/VirtualProductDelivery/I18n/de_DE.php b/local/modules/VirtualProductDelivery/I18n/de_DE.php new file mode 100644 index 00000000..774ee9be --- /dev/null +++ b/local/modules/VirtualProductDelivery/I18n/de_DE.php @@ -0,0 +1,8 @@ + 'Bestellung {$order_ref} validiert. Laden Sie Ihre Dateien herunter.', + 'The file [%file] does not exist' => 'Die Datei [%file] existiert nicht', + 'This module cannot be used on the current cart.' => 'Dieses Modul kann nicht für diesen Warenkorb benutzt werden. ', + 'Virtual product download message' => 'Virtuelles Produkt Herunterladung Nachricht', +]; diff --git a/local/modules/VirtualProductDelivery/I18n/email/default/en_US.php b/local/modules/VirtualProductDelivery/I18n/email/default/en_US.php new file mode 100644 index 00000000..6f40b67a --- /dev/null +++ b/local/modules/VirtualProductDelivery/I18n/email/default/en_US.php @@ -0,0 +1,10 @@ + 'Best Regards.', + 'Feel free to contact us for any further information.' => 'Feel free to contact us for any further information.', + 'Products:' => 'Products:', + 'You have to be logged in to your account to download this files.' => 'You have to be logged in to your account to download this files.', + 'Your order %ref has been validated. You can download your files.' => 'Your order %ref has been validated. You can download your files.', + 'have to be logged in to your account to download this files.' => 'have to be logged in to your account to download this files.', +); diff --git a/local/modules/VirtualProductDelivery/I18n/email/default/fr_FR.php b/local/modules/VirtualProductDelivery/I18n/email/default/fr_FR.php new file mode 100644 index 00000000..4a751a8f --- /dev/null +++ b/local/modules/VirtualProductDelivery/I18n/email/default/fr_FR.php @@ -0,0 +1,10 @@ + 'Cordialement', + 'Feel free to contact us for any further information.' => 'N\'hésitez pas à nous contacter pour toute information complémentaire.', + 'Products:' => 'Articles à télécharger:', + 'You have to be logged in to your account to download this files.' => 'Vous devez être connecté à votre compte pour pouvoir télécharger le fichier.', + 'Your order %ref has been validated. You can download your files.' => 'Votre commande %ref a été validé. Vous pouvez désormais télécharger vos fichiers.', + 'have to be logged in to your account to download this files.' => 'Vous devez être connecté à votre compte pour pouvoir télécharger les fichiers.', +]; diff --git a/local/modules/VirtualProductDelivery/I18n/email/default/it_IT.php b/local/modules/VirtualProductDelivery/I18n/email/default/it_IT.php new file mode 100644 index 00000000..97ea8be1 --- /dev/null +++ b/local/modules/VirtualProductDelivery/I18n/email/default/it_IT.php @@ -0,0 +1,10 @@ + 'Distinti saluti.', + 'Feel free to contact us for any further information.' => 'Non esitate a contattarci per qualsiasi ulteriore informazione.', + 'Products:' => 'Prodotti:', + 'You have to be logged in to your account to download this files.' => 'Devi essere loggato al tuo account per poter scaricare questi file.', + 'Your order %ref has been validated. You can download your files.' => 'Il vostro ordine %ref è stato convalidato. È possibile scaricare i file.', + 'have to be logged in to your account to download this files.' => 'devi essere loggato al tuo account per poter scaricare questi file.', +]; diff --git a/local/modules/VirtualProductDelivery/I18n/email/default/ru_RU.php b/local/modules/VirtualProductDelivery/I18n/email/default/ru_RU.php new file mode 100644 index 00000000..e30d2eb2 --- /dev/null +++ b/local/modules/VirtualProductDelivery/I18n/email/default/ru_RU.php @@ -0,0 +1,9 @@ + 'С наилучшими пожеланиями.', + 'Feel free to contact us for any further information.' => 'Не стесняйтесь обращаться к нам за любой дополнительной информацией.', + 'Products:' => 'Товары:', + 'You have to be logged in to your account to download this files.' => 'Вы должны войти в ваш аккаунт, чтобы скачать эти файлы', + 'Your order %ref has been validated. You can download your files.' => 'Ваш заказ %ref подтвержден. Можете скачивать ваши файлы.', +); diff --git a/local/modules/VirtualProductDelivery/I18n/email/default/tr_TR.php b/local/modules/VirtualProductDelivery/I18n/email/default/tr_TR.php new file mode 100644 index 00000000..f814b8fe --- /dev/null +++ b/local/modules/VirtualProductDelivery/I18n/email/default/tr_TR.php @@ -0,0 +1,10 @@ + 'Saygılarımızla,.', + 'Feel free to contact us for any further information.' => 'Daha fazla bilgi için bizimle temas kurmaktan çekinmeyin.', + 'Products:' => 'ürün:', + 'You have to be logged in to your account to download this files.' => 'Bu dosyaları karşıdan yüklemek için hesabınıza oturum açmış olmanız gerekir.', + 'Your order %ref has been validated. You can download your files.' => 'Sipariş %ref doğrulandı. Sen-ebilmek download senin eğe.', + 'have to be logged in to your account to download this files.' => 'Bu dosyaları karşıdan yüklemek için hesabınıza oturum açmış olmanız gerekir.', +]; diff --git a/local/modules/VirtualProductDelivery/I18n/en_US.php b/local/modules/VirtualProductDelivery/I18n/en_US.php new file mode 100644 index 00000000..f197297f --- /dev/null +++ b/local/modules/VirtualProductDelivery/I18n/en_US.php @@ -0,0 +1,8 @@ + 'Order {$order_ref} validated. Download your files.', + 'The file [%file] does not exist' => 'The file [%file] does not exist', + 'This module cannot be used on the current cart.' => 'This module cannot be used on the current cart.', + 'Virtual product download message' => 'Virtual product download message', +); diff --git a/local/modules/VirtualProductDelivery/I18n/fr_FR.php b/local/modules/VirtualProductDelivery/I18n/fr_FR.php new file mode 100644 index 00000000..4d258b83 --- /dev/null +++ b/local/modules/VirtualProductDelivery/I18n/fr_FR.php @@ -0,0 +1,8 @@ + 'Commande {$order_ref} validée. Téléchargez vos fichiers.', + 'The file [%file] does not exist' => 'le fichier [%file] n\'existe pas', + 'This module cannot be used on the current cart.' => 'Ce module ne peut pas être utilisé avec le panier actuel.', + 'Virtual product download message' => 'Message pour le téléchargement des produits virtuels', +]; diff --git a/local/modules/VirtualProductDelivery/I18n/frontOffice/default/de_DE.php b/local/modules/VirtualProductDelivery/I18n/frontOffice/default/de_DE.php new file mode 100644 index 00000000..07fa0462 --- /dev/null +++ b/local/modules/VirtualProductDelivery/I18n/frontOffice/default/de_DE.php @@ -0,0 +1,9 @@ + 'Lieferadresse', + 'Download' => 'Herunterladen', + 'File' => 'Datei', + 'List of downloadable files' => 'Liste der herunterladbaren Dateien', + 'No delivery address for this delivery method' => 'Keine Lieferadresse für diese Liefermethode', +]; diff --git a/local/modules/VirtualProductDelivery/I18n/frontOffice/default/en_US.php b/local/modules/VirtualProductDelivery/I18n/frontOffice/default/en_US.php new file mode 100644 index 00000000..8d11f5e0 --- /dev/null +++ b/local/modules/VirtualProductDelivery/I18n/frontOffice/default/en_US.php @@ -0,0 +1,9 @@ + 'Delivery address', + 'Download' => 'Download', + 'File' => 'File', + 'List of downloadable files' => 'List of downloadable files', + 'No delivery address for this delivery method' => 'No delivery address for this delivery method', +); diff --git a/local/modules/VirtualProductDelivery/I18n/frontOffice/default/fr_FR.php b/local/modules/VirtualProductDelivery/I18n/frontOffice/default/fr_FR.php new file mode 100644 index 00000000..d12b648f --- /dev/null +++ b/local/modules/VirtualProductDelivery/I18n/frontOffice/default/fr_FR.php @@ -0,0 +1,9 @@ + 'Adresse de livraison', + 'Download' => 'Télécharger', + 'File' => 'Fichier', + 'List of downloadable files' => 'Liste des fichiers téléchargeables', + 'No delivery address for this delivery method' => 'L\'adresse de livraison n\'est pas nécessaire pour cette méthode de livraison', +]; diff --git a/local/modules/VirtualProductDelivery/I18n/frontOffice/default/it_IT.php b/local/modules/VirtualProductDelivery/I18n/frontOffice/default/it_IT.php new file mode 100644 index 00000000..7abc77b8 --- /dev/null +++ b/local/modules/VirtualProductDelivery/I18n/frontOffice/default/it_IT.php @@ -0,0 +1,8 @@ + 'Indirizzo di consegna', + 'File' => 'File', + 'List of downloadable files' => 'Elenco dei file scaricabili', + 'No delivery address for this delivery method' => 'Nessun indirizzo di consegna per questo metodo di consegna', +]; diff --git a/local/modules/VirtualProductDelivery/I18n/frontOffice/default/ru_RU.php b/local/modules/VirtualProductDelivery/I18n/frontOffice/default/ru_RU.php new file mode 100644 index 00000000..8aaa497a --- /dev/null +++ b/local/modules/VirtualProductDelivery/I18n/frontOffice/default/ru_RU.php @@ -0,0 +1,9 @@ + 'Адрес доставки', + 'Download' => 'Скачать', + 'File' => 'Файл', + 'List of downloadable files' => 'Список скачиваемых файлов', + 'No delivery address for this delivery method' => 'Нет адреса доставки для этого метода доставки', +); diff --git a/local/modules/VirtualProductDelivery/I18n/frontOffice/default/tr_TR.php b/local/modules/VirtualProductDelivery/I18n/frontOffice/default/tr_TR.php new file mode 100644 index 00000000..040103d3 --- /dev/null +++ b/local/modules/VirtualProductDelivery/I18n/frontOffice/default/tr_TR.php @@ -0,0 +1,9 @@ + 'Teslimat adresi', + 'Download' => 'İndir', + 'File' => 'Dosya', + 'List of downloadable files' => 'İndirilebilir dosyalar', + 'No delivery address for this delivery method' => 'Bu teslim yöntemi için hiçbir teslimat adresi', +]; diff --git a/local/modules/VirtualProductDelivery/I18n/it_IT.php b/local/modules/VirtualProductDelivery/I18n/it_IT.php new file mode 100644 index 00000000..b286eca2 --- /dev/null +++ b/local/modules/VirtualProductDelivery/I18n/it_IT.php @@ -0,0 +1,7 @@ + 'Ordine {$order_ref} convalidato. Scarica i tuoi file.', + 'The file [%file] does not exist' => 'Il file [%file] non esiste', + 'This module cannot be used on the current cart.' => 'Questo modulo non può essere utilizzato sul carrello attuale.', +]; diff --git a/local/modules/VirtualProductDelivery/I18n/pdf/default/de_DE.php b/local/modules/VirtualProductDelivery/I18n/pdf/default/de_DE.php new file mode 100644 index 00000000..c3097e65 --- /dev/null +++ b/local/modules/VirtualProductDelivery/I18n/pdf/default/de_DE.php @@ -0,0 +1,5 @@ + 'Keine Lieferadresse für diese Liefermethode', +]; diff --git a/local/modules/VirtualProductDelivery/I18n/pdf/default/en_US.php b/local/modules/VirtualProductDelivery/I18n/pdf/default/en_US.php new file mode 100644 index 00000000..205aa3f4 --- /dev/null +++ b/local/modules/VirtualProductDelivery/I18n/pdf/default/en_US.php @@ -0,0 +1,5 @@ + 'No delivery address for this delivery method', +); diff --git a/local/modules/VirtualProductDelivery/I18n/pdf/default/fr_FR.php b/local/modules/VirtualProductDelivery/I18n/pdf/default/fr_FR.php new file mode 100644 index 00000000..b2088c85 --- /dev/null +++ b/local/modules/VirtualProductDelivery/I18n/pdf/default/fr_FR.php @@ -0,0 +1,5 @@ + 'L\'adresse de livraison n\'est pas nécessaire pour cette méthode de livraison', +]; diff --git a/local/modules/VirtualProductDelivery/I18n/pdf/default/it_IT.php b/local/modules/VirtualProductDelivery/I18n/pdf/default/it_IT.php new file mode 100644 index 00000000..c36c7201 --- /dev/null +++ b/local/modules/VirtualProductDelivery/I18n/pdf/default/it_IT.php @@ -0,0 +1,5 @@ + 'Nessun indirizzo di consegna per questo metodo di consegna', +]; diff --git a/local/modules/VirtualProductDelivery/I18n/pdf/default/ru_RU.php b/local/modules/VirtualProductDelivery/I18n/pdf/default/ru_RU.php new file mode 100644 index 00000000..75399158 --- /dev/null +++ b/local/modules/VirtualProductDelivery/I18n/pdf/default/ru_RU.php @@ -0,0 +1,5 @@ + 'Нет адреса доставки для этого метода доставки', +); diff --git a/local/modules/VirtualProductDelivery/I18n/pdf/default/tr_TR.php b/local/modules/VirtualProductDelivery/I18n/pdf/default/tr_TR.php new file mode 100644 index 00000000..bbef2c98 --- /dev/null +++ b/local/modules/VirtualProductDelivery/I18n/pdf/default/tr_TR.php @@ -0,0 +1,5 @@ + 'Bu teslim yöntemi için hiçbir teslimat adresi', +]; diff --git a/local/modules/VirtualProductDelivery/I18n/ru_RU.php b/local/modules/VirtualProductDelivery/I18n/ru_RU.php new file mode 100644 index 00000000..57686cd3 --- /dev/null +++ b/local/modules/VirtualProductDelivery/I18n/ru_RU.php @@ -0,0 +1,8 @@ + 'Заказ {$order_ref} подтвержден. Можете скачивать ваши файлы.', + 'The file [%file] does not exist' => 'Файл [%file] не найден', + 'This module cannot be used on the current cart.' => 'Этот модуль не может быть использован с текущей корзиной', + 'Virtual product download message' => 'Сообщения при скачивании виртуального товара', +); diff --git a/local/modules/VirtualProductDelivery/I18n/tr_TR.php b/local/modules/VirtualProductDelivery/I18n/tr_TR.php new file mode 100644 index 00000000..978854a2 --- /dev/null +++ b/local/modules/VirtualProductDelivery/I18n/tr_TR.php @@ -0,0 +1,8 @@ + 'Doğrulanmış {$order_ref} sipariş. Download senin eğe.', + 'The file [%file] does not exist' => '[%file] dosyası yok', + 'This module cannot be used on the current cart.' => 'Bu modül geçerli arabaya kullanılamaz.', + 'Virtual product download message' => 'Sanal ürün indir mesaj', +]; diff --git a/local/modules/VirtualProductDelivery/LICENSE.txt b/local/modules/VirtualProductDelivery/LICENSE.txt new file mode 100644 index 00000000..65c5ca88 --- /dev/null +++ b/local/modules/VirtualProductDelivery/LICENSE.txt @@ -0,0 +1,165 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + + This version of the GNU Lesser General Public License incorporates +the terms and conditions of version 3 of the GNU General Public +License, supplemented by the additional permissions listed below. + + 0. Additional Definitions. + + As used herein, "this License" refers to version 3 of the GNU Lesser +General Public License, and the "GNU GPL" refers to version 3 of the GNU +General Public License. + + "The Library" refers to a covered work governed by this License, +other than an Application or a Combined Work as defined below. + + An "Application" is any work that makes use of an interface provided +by the Library, but which is not otherwise based on the Library. +Defining a subclass of a class defined by the Library is deemed a mode +of using an interface provided by the Library. + + A "Combined Work" is a work produced by combining or linking an +Application with the Library. The particular version of the Library +with which the Combined Work was made is also called the "Linked +Version". + + The "Minimal Corresponding Source" for a Combined Work means the +Corresponding Source for the Combined Work, excluding any source code +for portions of the Combined Work that, considered in isolation, are +based on the Application, and not on the Linked Version. + + The "Corresponding Application Code" for a Combined Work means the +object code and/or source code for the Application, including any data +and utility programs needed for reproducing the Combined Work from the +Application, but excluding the System Libraries of the Combined Work. + + 1. Exception to Section 3 of the GNU GPL. + + You may convey a covered work under sections 3 and 4 of this License +without being bound by section 3 of the GNU GPL. + + 2. Conveying Modified Versions. + + If you modify a copy of the Library, and, in your modifications, a +facility refers to a function or data to be supplied by an Application +that uses the facility (other than as an argument passed when the +facility is invoked), then you may convey a copy of the modified +version: + + a) under this License, provided that you make a good faith effort to + ensure that, in the event an Application does not supply the + function or data, the facility still operates, and performs + whatever part of its purpose remains meaningful, or + + b) under the GNU GPL, with none of the additional permissions of + this License applicable to that copy. + + 3. Object Code Incorporating Material from Library Header Files. + + The object code form of an Application may incorporate material from +a header file that is part of the Library. You may convey such object +code under terms of your choice, provided that, if the incorporated +material is not limited to numerical parameters, data structure +layouts and accessors, or small macros, inline functions and templates +(ten or fewer lines in length), you do both of the following: + + a) Give prominent notice with each copy of the object code that the + Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the object code with a copy of the GNU GPL and this license + document. + + 4. Combined Works. + + You may convey a Combined Work under terms of your choice that, +taken together, effectively do not restrict modification of the +portions of the Library contained in the Combined Work and reverse +engineering for debugging such modifications, if you also do each of +the following: + + a) Give prominent notice with each copy of the Combined Work that + the Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the Combined Work with a copy of the GNU GPL and this license + document. + + c) For a Combined Work that displays copyright notices during + execution, include the copyright notice for the Library among + these notices, as well as a reference directing the user to the + copies of the GNU GPL and this license document. + + d) Do one of the following: + + 0) Convey the Minimal Corresponding Source under the terms of this + License, and the Corresponding Application Code in a form + suitable for, and under terms that permit, the user to + recombine or relink the Application with a modified version of + the Linked Version to produce a modified Combined Work, in the + manner specified by section 6 of the GNU GPL for conveying + Corresponding Source. + + 1) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (a) uses at run time + a copy of the Library already present on the user's computer + system, and (b) will operate properly with a modified version + of the Library that is interface-compatible with the Linked + Version. + + e) Provide Installation Information, but only if you would otherwise + be required to provide such information under section 6 of the + GNU GPL, and only to the extent that such information is + necessary to install and execute a modified version of the + Combined Work produced by recombining or relinking the + Application with a modified version of the Linked Version. (If + you use option 4d0, the Installation Information must accompany + the Minimal Corresponding Source and Corresponding Application + Code. If you use option 4d1, you must provide the Installation + Information in the manner specified by section 6 of the GNU GPL + for conveying Corresponding Source.) + + 5. Combined Libraries. + + You may place library facilities that are a work based on the +Library side by side in a single library together with other library +facilities that are not Applications and are not covered by this +License, and convey such a combined library under terms of your +choice, if you do both of the following: + + a) Accompany the combined library with a copy of the same work based + on the Library, uncombined with any other library facilities, + conveyed under the terms of this License. + + b) Give prominent notice with the combined library that part of it + is a work based on the Library, and explaining where to find the + accompanying uncombined form of the same work. + + 6. Revised Versions of the GNU Lesser General Public License. + + The Free Software Foundation may publish revised and/or new versions +of the GNU Lesser General Public License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. + + Each version is given a distinguishing version number. If the +Library as you received it specifies that a certain numbered version +of the GNU Lesser General Public License "or any later version" +applies to it, you have the option of following the terms and +conditions either of that published version or of any later version +published by the Free Software Foundation. If the Library as you +received it does not specify a version number of the GNU Lesser +General Public License, you may choose any version of the GNU Lesser +General Public License ever published by the Free Software Foundation. + + If the Library as you received it specifies that a proxy can decide +whether future versions of the GNU Lesser General Public License shall +apply, that proxy's public statement of acceptance of any version is +permanent authorization for you to choose that version for the +Library. diff --git a/local/modules/VirtualProductDelivery/VirtualProductDelivery.php b/local/modules/VirtualProductDelivery/VirtualProductDelivery.php new file mode 100644 index 00000000..b96226a6 --- /dev/null +++ b/local/modules/VirtualProductDelivery/VirtualProductDelivery.php @@ -0,0 +1,109 @@ +getRequest()->getSession()->getSessionCart($this->getDispatcher())->isVirtual(); + } + + public function getPostage(Country $country, State $state = null) + { + if (!$this->isValidDelivery($country, $state)) { + throw new DeliveryException( + $this->trans("This module cannot be used on the current cart.") + ); + } + + return 0.0; + } + + /** + * This module manages virtual product delivery + * + * @return bool + */ + public function handleVirtualProductDelivery() + { + return true; + } + + + public function postActivation(ConnectionInterface $con = null) + { + // create new message + if (null === MessageQuery::create()->findOneByName('mail_virtualproduct')) { + $message = new Message(); + $message + ->setName('mail_virtualproduct') + ->setHtmlTemplateFileName('virtual-product-download.html') + ->setHtmlLayoutFileName('') + ->setTextTemplateFileName('virtual-product-download.txt') + ->setTextLayoutFileName('') + ->setSecured(0); + + $languages = LangQuery::create()->find(); + + foreach ($languages as $language) { + $locale = $language->getLocale(); + + $message->setLocale($locale); + + $message->setSubject( + $this->trans('Order {$order_ref} validated. Download your files.', [], $locale) + ); + $message->setTitle( + $this->trans('Virtual product download message', [], $locale) + ); + } + + $message->save(); + } + } + + protected function trans($id, $parameters = [], $locale = null) + { + if (null === $this->translator) { + $this->translator = Translator::getInstance(); + } + + return $this->translator->trans($id, $parameters, self::MESSAGE_DOMAIN, $locale); + } +} diff --git a/local/modules/VirtualProductDelivery/composer.json b/local/modules/VirtualProductDelivery/composer.json new file mode 100644 index 00000000..77460d83 --- /dev/null +++ b/local/modules/VirtualProductDelivery/composer.json @@ -0,0 +1,11 @@ +{ + "name": "thelia/virtual-product-delivery-module", + "license": "LGPL-3.0+", + "type": "thelia-module", + "require": { + "thelia/installer": "~1.1" + }, + "extra": { + "installer-name": "VirtualProductDelivery" + } +} diff --git a/local/modules/VirtualProductDelivery/templates/email/default/virtual-product-download.html b/local/modules/VirtualProductDelivery/templates/email/default/virtual-product-download.html new file mode 100644 index 00000000..f7069b3b --- /dev/null +++ b/local/modules/VirtualProductDelivery/templates/email/default/virtual-product-download.html @@ -0,0 +1,29 @@ +{default_translation_domain domain="virtualproductdelivery.email.default"} +{default_locale locale={$locale}} + +{loop name="order.invoice" type="order" id=$order_id customer="*" limit="1" backend_context="1"} +

    + {intl l="Your order %ref has been validated. You can download your files." ref={$REF}}

    + +

    {intl l="Products:"}

    + +
      + {loop type="order_product" name="order-products" order=$ID virtual="1" backend_context="1"} +
    • + {$TITLE} : {url path="/account/download/$ID"} + {ifloop rel="combinations"} +
      + {loop type="order_product_attribute_combination" name="combinations" order_product=$ID} + {$ATTRIBUTE_TITLE} - {$ATTRIBUTE_AVAILABILITY_TITLE} + {/loop} + {/ifloop} +
    • + {/loop} +
    +{/loop} + +

    {intl l="You have to be logged in to your account to download this files."}

    + +

    {intl l="Feel free to contact us for any further information."}

    + +

    {intl l="Best Regards."}

    \ No newline at end of file diff --git a/local/modules/VirtualProductDelivery/templates/email/default/virtual-product-download.txt b/local/modules/VirtualProductDelivery/templates/email/default/virtual-product-download.txt new file mode 100644 index 00000000..9fc5592b --- /dev/null +++ b/local/modules/VirtualProductDelivery/templates/email/default/virtual-product-download.txt @@ -0,0 +1,26 @@ +{default_translation_domain domain="virtualproductdelivery.email.default"} +{default_locale locale={$locale}} + +{loop name="order.invoice" type="order" id=$order_id customer="*" limit="1" backend_context="1"} + +{intl l="Your order %ref has been validated. You can download your files." ref={$REF}} + +---------------------------------------------------------------------- +{intl l="Products:"} +---------------------------------------------------------------------- +{loop type="order_product" name="order-products" order=$ID virtual="1" backend_context="1"} +{$TITLE} : {url path="/account/download/$ID"} +{ifloop rel="combinations"} +{loop type="order_product_attribute_combination" name="combinations" order_product=$ID} +{$ATTRIBUTE_TITLE} - {$ATTRIBUTE_AVAILABILITY_TITLE} +{/loop} +{/ifloop} +---------------------------------------------------------------------- +{/loop} +{/loop} + +{intl l="You have to be logged in to your account to download this files."} + +{intl l="Feel free to contact us for any further information."} + +{intl l="Best Regards."} \ No newline at end of file diff --git a/local/modules/VirtualProductDelivery/templates/frontOffice/default/account-order-after-products.html b/local/modules/VirtualProductDelivery/templates/frontOffice/default/account-order-after-products.html new file mode 100644 index 00000000..c4384e7a --- /dev/null +++ b/local/modules/VirtualProductDelivery/templates/frontOffice/default/account-order-after-products.html @@ -0,0 +1,24 @@ +{loop type="order" name="virtual.order" id="$order_id" limit="1"} +{if $STATUS >=2 && $VIRTUAL} + + + + + + + + + {loop name="virtual.order.products" type="order_product" virtual="1" order={$ID}} + + + + + {/loop} + +
    {intl l="File" d='virtualproductdelivery.fo.default'}{intl l="Download" d='virtualproductdelivery.fo.default'}
    {$TITLE} + + {intl l="Download" d='virtualproductdelivery.fo.default'} + +
    +{/if} +{/loop} diff --git a/local/modules/VirtualProductDelivery/templates/frontOffice/default/delivery-address.html b/local/modules/VirtualProductDelivery/templates/frontOffice/default/delivery-address.html new file mode 100644 index 00000000..ceb1e750 --- /dev/null +++ b/local/modules/VirtualProductDelivery/templates/frontOffice/default/delivery-address.html @@ -0,0 +1,6 @@ +
    +
    {intl l="Delivery address" d="virtualproductdelivery.fo.default"}
    +
    + {intl l="No delivery address for this delivery method" d="virtualproductdelivery.fo.default"} +
    +
    \ No newline at end of file diff --git a/local/modules/VirtualProductDelivery/templates/pdf/default/delivery-address.html b/local/modules/VirtualProductDelivery/templates/pdf/default/delivery-address.html new file mode 100644 index 00000000..6a5a1f92 --- /dev/null +++ b/local/modules/VirtualProductDelivery/templates/pdf/default/delivery-address.html @@ -0,0 +1,3 @@ +

    + {intl l="No delivery address for this delivery method" d="virtualproductdelivery.pdf.default"} +

    \ No newline at end of file diff --git a/php-cs b/php-cs new file mode 100644 index 00000000..a7928901 --- /dev/null +++ b/php-cs @@ -0,0 +1,26 @@ +#!/bin/bash + +php-cs-fixer fix core/lib/Thelia/Action/ --level=psr2 +php-cs-fixer fix core/lib/Thelia/Command/ --level=psr2 +php-cs-fixer fix core/lib/Thelia/Condition/ --level=psr2 +php-cs-fixer fix core/lib/Thelia/Config/ --level=psr2 +php-cs-fixer fix core/lib/Thelia/Controller/ --level=psr2 +php-cs-fixer fix core/lib/Thelia/Core/ --level=psr2 +php-cs-fixer fix core/lib/Thelia/Coupon/ --level=psr2 +php-cs-fixer fix core/lib/Thelia/Exception/ --level=psr2 +php-cs-fixer fix core/lib/Thelia/Files/ --level=psr2 +php-cs-fixer fix core/lib/Thelia/Form/ --level=psr2 +php-cs-fixer fix core/lib/Thelia/ImportExport/ --level=psr2 +php-cs-fixer fix core/lib/Thelia/Install/ --level=psr2 +php-cs-fixer fix core/lib/Thelia/Log/ --level=psr2 +php-cs-fixer fix core/lib/Thelia/Mailer/ --level=psr2 +find core/lib/Thelia/Model/ -maxdepth 1 -name *.php -exec php-cs-fixer fix '{}' --level=psr2 \; +php-cs-fixer fix core/lib/Thelia/Model/Breadcrumb --level=psr2 +php-cs-fixer fix core/lib/Thelia/Model/Exception --level=psr2 +php-cs-fixer fix core/lib/Thelia/Model/Tools --level=psr2 +php-cs-fixer fix core/lib/Thelia/Module/ --level=psr2 +php-cs-fixer fix core/lib/Thelia/Rewriting/ --level=psr2 +php-cs-fixer fix core/lib/Thelia/TaxEngine/ --level=psr2 +php-cs-fixer fix tests/phpunit/Thelia/Tests/ --level=psr2 +php-cs-fixer fix core/lib/Thelia/Tools/ --level=psr2 +php-cs-fixer fix core/lib/Thelia/Type/ --level=psr2 \ No newline at end of file diff --git a/php-cs.bat b/php-cs.bat new file mode 100644 index 00000000..f58558fb --- /dev/null +++ b/php-cs.bat @@ -0,0 +1,27 @@ +@echo off +echo Running php-cs-fixer... +call php-cs-fixer fix core\lib\Thelia\Action --level=psr2 +call php-cs-fixer fix core\lib\Thelia\Command --level=psr2 +call php-cs-fixer fix core\lib\Thelia\Condition --level=psr2 +call php-cs-fixer fix core\lib\Thelia\Config --level=psr2 +call php-cs-fixer fix core\lib\Thelia\Controller --level=psr2 +call php-cs-fixer fix core\lib\Thelia\Core --level=psr2 +call php-cs-fixer fix core\lib\Thelia\Coupon --level=psr2 +call php-cs-fixer fix core\lib\Thelia\Exception --level=psr2 +call php-cs-fixer fix core\lib\Thelia\Files --level=psr2 +call php-cs-fixer fix core\lib\Thelia\Form --level=psr2 +call php-cs-fixer fix core\lib\Thelia\ImportExport --level=psr2 +call php-cs-fixer fix core\lib\Thelia\Install --level=psr2 +call php-cs-fixer fix core\lib\Thelia\Log --level=psr2 +call php-cs-fixer fix core\lib\Thelia\Mailer --level=psr2 +for %%F in (core\lib\Thelia\Model\*.php) DO call php-cs-fixer fix %%F --level=psr2 +call php-cs-fixer fix core\lib\Thelia\Model\Breadcrumb --level=psr2 +call php-cs-fixer fix core\lib\Thelia\Model\Exception --level=psr2 +call php-cs-fixer fix core\lib\Thelia\Model\Tools --level=psr2 +call php-cs-fixer fix core\lib\Thelia\Module --level=psr2 +call php-cs-fixer fix core\lib\Thelia\Rewriting --level=psr2 +call php-cs-fixer fix core\lib\Thelia\TaxEngine --level=psr2 +call php-cs-fixer fix tests\phpunit\Thelia\Tests --level=psr2 +call php-cs-fixer fix core\lib\Thelia\Tools --level=psr2 +call php-cs-fixer fix core\lib\Thelia\Type --level=psr2 +echo Done. \ No newline at end of file diff --git a/phpunit.xml b/phpunit.xml new file mode 100644 index 00000000..f7a3fe22 --- /dev/null +++ b/phpunit.xml @@ -0,0 +1,28 @@ + + + + + + tests/phpunit/Thelia/Tests + local/modules/*/Tests + + + + + core/lib + + core/lib/Thelia/Model/map + core/lib/Thelia/Model/om + core/lib/Thelia/Tests + + + + diff --git a/reset_install.bat b/reset_install.bat new file mode 100644 index 00000000..48534b51 --- /dev/null +++ b/reset_install.bat @@ -0,0 +1,53 @@ +echo off +REM @author Guillaume MOREL +REM v0.1 + +echo [WARN] This script will reset this Thelia2 install, all data will be cleared. +pause + +if exist local\config\database.yml ( + + echo [INFO] Clearing caches + php Thelia cache:clear + + echo [INFO] Self-updating Composer + composer self-update + + echo [INFO] Downloading vendors + composer install --prefer-dist --optimize-autoloader + + cd local\config\ + + echo [INFO] Building Models file + ..\..\bin\propel build -v --output-dir=../../core/lib/ --enable-identifier-quoting + + echo [INFO] Building SQL CREATE file + ..\..\bin\propel sql:build -v --output-dir=..\..\setup + + echo [INFO] Reloading Thelia2 database + cd ..\.. + del setup\sqldb.map + php Thelia thelia:dev:reloadDB + + echo [INFO] Installing fixtures + php setup\faker.php + + echo [INFO] Clearing caches + php Thelia cache:clear + + echo [INFO] Adding admin + php Thelia admin:create --login_name thelia2 --password thelia2 --last_name thelia2 --first_name thelia2 --email thelia2@example.com + + echo [INFO] Admin user thelia2 with password thelia2 and email admin@example.com successfully created. + + echo [INFO] Activating Delivery Module + php Thelia module:activate Colissimo + + echo [INFO] Activating Payment Module + php Thelia module:activate Cheque + + echo [SUCCESS] Reset done +) +) else ( + echo [FAILED] Please add your database informations in local\config\database.yml and start this script again. +) diff --git a/reset_install.sh b/reset_install.sh new file mode 100644 index 00000000..610f403e --- /dev/null +++ b/reset_install.sh @@ -0,0 +1,46 @@ +#!/bin/bash +# @author Guillaume MOREL +# v0.2 + +echo -e "\033[47m\033[1;31m\n[WARNING] This script will reset this Thelia2 install\nPress ENTER to continue or ^C to cancel\033[0m" + +read test + +echo -e "\n\033[01;34m[INFO] Clearing caches\033[00m\n" +php Thelia cache:clear + +echo -e "\n\033[01;34m[INFO] Self-updating Composer\033[00m\n" +composer self-update + +echo -e "\n\033[01;34m[INFO] Downloading vendors\033[00m\n" +composer install --prefer-dist --optimize-autoloader + +cd local/config/ + +echo -e "\n\033[01;34m[INFO] Building Models file\033[00m\n" +../../bin/propel build -v --output-dir=../../core/lib/ --enable-identifier-quoting + +echo -e "\n\033[01;34m[INFO] Building SQL CREATE file\033[00m\n" +../../bin/propel sql:build -v --output-dir=../../setup/ + +echo -e "\n\033[01;34m[INFO] Reloading Thelia2 database\033[00m\n" +cd ../.. +rm setup/sqldb.map +php Thelia thelia:dev:reloadDB + +echo -e "\n\033[01;34m[INFO] Installing fixtures\033[00m\n" +php setup/faker.php + +echo -e "\n\033[01;34m[INFO] Adding admin\033[00m\n" +php Thelia admin:create --login_name thelia2 --password thelia2 --last_name thelia2 --first_name thelia2 --email thelia2@example.com + +echo -e "\n\033[01;34m[INFO] Clearing caches\033[00m\n" +php Thelia cache:clear + +echo -e "\n\033[01;34m[INFO] Activating Delivery Module(s)\033[00m\n" +php Thelia module:activate Colissimo + +echo -e "\n\033[01;34m[INFO] Activating Payment Module(s)\033[00m\n" +php Thelia module:activate Cheque + +echo -e "\n\033[00;32m[SUCCESS] Reset done\033[00m\n" diff --git a/run-tests.sh b/run-tests.sh new file mode 100644 index 00000000..1880025a --- /dev/null +++ b/run-tests.sh @@ -0,0 +1,36 @@ +#!/bin/bash +# -------------------------------------------------------------- +# This script is started by Travis to perform all Thelia 2 tests +# -------------------------------------------------------------- + +# will exit with non-zero error code if any of the command fails +set -e + +echo "backup DB" +mysqldump -h $DB_HOST -u $DB_USER thelia >../thelia.sql + +echo "phpunit" +./bin/phpunit + +echo "restore DB" +mysql -h $DB_HOST -u $DB_USER thelia <../thelia.sql + +echo "deactivate modules only needed by phpunit tests" +php Thelia module:refresh +php Thelia module:deactivate HookTest + +echo "Clearing cache" +php Thelia cache:clear --env=prod +rm -rf local/session/sess_* + +echo "CasperJS" +echo "casperjs : $(which casperjs) $(casperjs --version)" +echo "phantomjs : ${PHANTOMJS_EXECUTABLE} $(${PHANTOMJS_EXECUTABLE} --version)" + +export DISPLAY=:99.0 + +# echo "Front tests" +# casperjs test --local-to-remote-url-access=true --ignore-ssl-errors=true --ssl-protocol=any --pre=tests/functionnal/casperjs/conf/local.js --verbose tests/functionnal/casperjs/exe/front/ --thelia2_base_url="http://127.0.0.1:8000/index.php/" --thelia2_screenshot_path="tests/functionnal/casperjs/screenshot/" --thelia2_screenshot_disabled + +# echo "Back tests" +# casperjs test --local-to-remote-url-access=true --ignore-ssl-errors=true --ssl-protocol=any --pre=tests/functionnal/casperjs/conf/local.js --verbose tests/functionnal/casperjs/exe/back/ --thelia2_base_url="http://127.0.0.1:8000/index_dev.php/" --thelia2_screenshot_path="tests/functionnal/casperjs/screenshot/" --thelia2_screenshot_disabled diff --git a/setup/.gitkeep b/setup/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/setup/.htaccess b/setup/.htaccess new file mode 100644 index 00000000..ff2beb84 --- /dev/null +++ b/setup/.htaccess @@ -0,0 +1,2 @@ +order deny,allow +deny from all diff --git a/setup/I18n/ar_SA.php b/setup/I18n/ar_SA.php new file mode 100644 index 00000000..e713c0a9 --- /dev/null +++ b/setup/I18n/ar_SA.php @@ -0,0 +1,14 @@ + 'عنوان', + 'Advanced configuration' => 'التكوين المتقدم', + 'Category' => 'الفئة', + 'Configuration' => 'لوحة التحكم', + 'Coupon' => 'قسيمة خصم', + 'Customer' => 'العميل', + 'Folder' => 'مجلّد', + 'Hooks' => 'روابط', + 'New York' => 'نيويورك', + 'Search' => 'بحث', +]; diff --git a/setup/I18n/cs_CZ.php b/setup/I18n/cs_CZ.php new file mode 100644 index 00000000..7644134b --- /dev/null +++ b/setup/I18n/cs_CZ.php @@ -0,0 +1,9 @@ + 'Adresa', + 'Category' => 'Kategorie', + 'Content' => 'Obsah', + 'New York' => 'New York', + 'Search' => 'Vyhledávání', +]; diff --git a/setup/I18n/de_DE.php b/setup/I18n/de_DE.php new file mode 100644 index 00000000..2970c223 --- /dev/null +++ b/setup/I18n/de_DE.php @@ -0,0 +1,1037 @@ + 'Ablaufzeit in Sekunden des Cookies "Remember me" für die Administratoren', + '"Remember me" cookie expiration time, in seconds, for customer users' => 'Ablaufzeit in Sekunden des Cookies "Remember me" für die Kunden', + '"Remember me" cookie name for administration users' => 'Name des Cookies "Remember me" für die Administratoren', + '"Remember me" cookie name for customer users' => 'Name des Cookies "Remember me" für die Kunden', + '72h delivery' => '72Std Lieferung ', + 'A {config key="store_name"} account has been created for you' => 'Ein Konto {config key="store_name"} wurde für Sie erstellt.', + 'API Configuration' => 'API-Konfiguration', + 'Address' => 'Adresse', + 'Address creation - CSS stylesheet' => 'Adresse Erstellung - CSS-Stylesheet', + 'Address creation - after javascript include' => 'Adresse Erstellung - nach der Integration von Javascript', + 'Address creation - after javascript initialisation' => 'Adresse Erstellung - nach der Initialisierung von Javascript', + 'Address creation - at the bottom' => 'Adresse Erstellung - unten', + 'Address creation - at the bottom of the form' => 'Adresse Erstellung - unten im Formular', + 'Address creation - at the top' => 'Adresse Erstellung - oben', + 'Address creation - at the top of the form' => 'Adresse Erstellung - oben im Formular', + 'Address update - CSS stylesheet' => 'Adresseänderung - CSS-Stylesheet', + 'Address update - after javascript include' => 'Adresseänderung - nach der Integration von Javascript', + 'Address update - after javascript initialisation' => 'Adresseänderung - nach der Initialisierung von Javascript', + 'Address update - at the bottom' => 'Adresseänderung - unten', + 'Address update - at the bottom of the form' => 'Adresseänderung - unten im Formular', + 'Address update - at the top' => 'Adresseänderung - oben', + 'Address update - at the top of the form' => 'Adressänderung - oben im Formular', + 'Admin layout - After the main content' => 'Admin layout - Nach dem Hauptinhalt', + 'Administatros list' => 'Administratorenliste', + 'Administration profiles management' => 'Administration-Profilverwaltung', + 'Administrator - create form' => 'Administrator - Erstellungsformular', + 'Administrator - delete form' => 'Administrator - Löschungsformular', + 'Administrator - update form' => 'Administrator - Änderungsformular', + 'Administrator list' => 'Administratorenliste', + 'Administrators - JavaScript' => 'Administratoren - JavaScript', + 'Administrators - at the top' => 'Administratoren - oben', + 'Administrators - bottom' => 'Administratoren - unten', + 'Administrators - header' => 'Administratoren - Header', + 'Administrators - row' => 'Administratoren - Zeile', + 'Advanced Configuration' => 'Erweiterte Konfiguration', + 'Advanced Configuration - Javascript' => 'Erweiterte Konfiguration - JavaScript', + 'Advanced configuration' => 'Erweiterte Konfiguration', + 'Afghanistan' => 'Afghanistan', + 'Albania' => 'Albanien', + 'Algeria' => 'Algerien', + 'All Products - CSS stylesheet' => 'Alle Produkte - CSS-Stylesheet', + 'All Products - after javascript include' => 'Alle Produkte - nach der Integration von Javascript', + 'All Products - after javascript initialisation' => 'Alle Produkte - nach der Initialisierung von Javascript', + 'All Products - at the bottom' => 'Alle Produkte - unten', + 'All Products - at the top' => 'Alle Produkte - oben', + 'Allow customers to change their email. 1 for yes, 0 for no' => 'Den Kunden erlauben ihre E-Mail-Adresse zu ändern. 1 für Ja, 0 für Nein', + 'Allow negative product stock (1) or not (0)' => 'Negativen Lagerbestand erlauben (1) oder nicht (0)', + 'Allow negative product stock (1) or not (0, default)' => 'Negativen Lagerbestand erlauben (1) oder nicht (0)(Standartwert 0)', + 'Allow slash ended uri' => 'URI mit Slash beendet erlauben', + 'An image carousel on your home page' => 'Ein Bilder-Karussel auf Ihre Startseite', + 'Andorra' => 'Andorra', + 'Angola' => 'Angola', + 'Antigua and Barbuda' => 'Antigua und Barbuda', + 'Api page - at bottom' => 'API Seite - unten', + 'Api page - at top' => 'API Seite - oben', + 'Api page - in deletion form' => 'API Seite - Löschungsformular', + 'Argentina' => 'Argentinien', + 'Armenia' => 'Armenien', + 'Ask the customers to confirm their email, 1 for yes, 0 for no' => 'Den Kunden fragen, ihre E-Mail-Adresse zu bestätigen. 1 für Jan, 0 für Nein', + 'Attribut - Edit JavaScript' => 'Deklination - JavaScript Änderung', + 'Attribut - add to all form' => 'Deklination - zu allen hinzufügen Formular', + 'Attribut - create form' => 'Deklination - Erstellungsformular', + 'Attribut - delete form' => 'Deklination - Löschungsformular', + 'Attribut - id delete form' => 'Deklination - ID Löschungsformular', + 'Attribut - remove to all form' => 'Deklination - multipel Löschungsformular', + 'Attribute edit - bottom' => 'Deklination Bearbeitung - unten', + 'Attribute edit - top' => 'Deklination Bearbeitung - oben', + 'Attribute value - create form' => 'Deklinationsangabe - Erstellungsformular', + 'Attributes - JavaScript' => 'Deklinationen - JavaScript', + 'Attributes - at the top' => 'Deklinationen - oben', + 'Attributes - bottom' => 'Deklinationen - unten', + 'Attributes - table header' => 'Deklinationen - Tabellenkopf', + 'Attributes - table row' => 'Deklinationen - Tabellenzeile', + 'Attributes value - table header' => 'Deklinationenangaben - Tabellenkopf', + 'Attributes value - table row' => 'Deklinationenangaben - Tabellenzeile', + 'Allow module installation from ZIP files.' => 'Modulinstallation aus ZIP-Dateien zulassen.' , + 'Australia' => 'Australien', + 'Austria' => 'Österreich', + 'Azerbaijan' => 'Aserbaidschan', + 'Back-office export management' => 'Exporten-Verwaltung', + 'Back-office home page' => 'Back-Office Startseite', + 'Back-office search function' => 'Back-Office Suchfunktion', + 'Bahamas' => 'Bahamas', + 'Bahrain' => 'Bahrein', + 'Bangladesh' => 'Bangladesch', + 'Barbados' => 'Barbados', + 'Base URL of the shop (e.g. http://www.yourshopdomain.com)' => 'Shops Basis-URL (zum Beispiel http://www.yourshopdomain.com)', + 'Belarus' => 'Weißrussland', + 'Belgium' => 'Belgien', + 'Belize' => 'Belize', + 'Benin' => 'Bénin', + 'Bhutan' => 'Bhutan', + 'Bielorussia' => 'Weißrussland', + 'Bolivia' => 'Bolivien', + 'Bosnia and Herzegovina' => 'Bosnien Herzegovina', + 'Botswana' => 'Botswana', + 'Brand - Edit JavaScript' => 'Marke - JavaScript Änderung', + 'Brand - JavaScript' => 'Marke - JavaScript', + 'Brand - Tab' => 'Marke - Tab', + 'Brand - content' => 'Marke - Inhalt', + 'Brand - create form' => 'Marke - Erstellungsformular', + 'Brand - delete form' => 'Marke - Löschungsformular', + 'Brand edit - bottom' => 'Marke Bearbeitung - unten', + 'Brand edit - right column bottom' => 'Marke bearbeiten - Rechte Spalte unten', + 'Brand edit - right column top' => 'Marke bearbeiten - Rechte Spalte oben', + 'Brand edit - top' => 'Marke Bearbeitung - oben', + 'Brand edit page - in the form' => 'Brand edit Seite - im Formular', + 'Brands - at the top' => 'Marken - oben', + 'Brands - bottom' => 'Marken - unten', + 'Brands - table header' => 'Marken - Tabellenkopf', + 'Brands - table row' => 'Marken - Tabellzeilen', + 'Brands management' => 'Marken-Verwaltung', + 'Brands page - CSS stylesheet' => 'Marken Seite - CSS-Stylesheet', + 'Brands page - after javascript include' => 'Marken Seite - Nach der Integration von Javascript', + 'Brands page - after the main content area' => 'Marken Seite - Nach dem Hauptinhalt Bereich', + 'Brands page - at the bottom' => 'Marken Seite - unten', + 'Brands page - at the bottom of the main area' => 'Marken Seite - unten des Hauptbereichs', + 'Brands page - at the bottom of the sidebar' => 'Marken Seite - unten der Sidebar', + 'Brands page - at the top' => 'Marken Seite - oben', + 'Brands page - at the top of the main area' => 'Marken Seite - oben des Hauptbereichs', + 'Brands page - at the top of the sidebar' => 'Marken Seite - oben der Sidebar', + 'Brands page - before the main content area' => 'Marken Seite - vor dem Hauptinhaltsbereich', + 'Brands page - javascript initialization' => 'Marken Seite - Javascript Initialisation', + 'Brands page - the body of the sidebar' => 'Marken Seite - Sidebars Body', + 'Brazil' => 'Brasilien', + 'Brunei' => 'Brunei', + 'Bulgaria' => 'Bulgarien', + 'Burkina' => 'Burkina Faso', + 'Burma' => 'Birma', + 'Burundi' => 'Burundi', + 'Cambodia' => 'Kambodscha', + 'Cameroon' => 'Kamerun', + 'Canceled' => 'Storniert', + 'Cape Verde' => 'Kap Verde', + 'Cart - CSS stylesheet' => 'Warenkorb - CSS-Stylesheet', + 'Cart - after javascript include' => 'Warenkorb - Nach Integration von JavaScript', + 'Cart - at the bottom' => 'Warenkorb - unten', + 'Cart - at the top' => 'Warenkorb - oben ', + 'Cart - javascript initialization' => 'Warenkorb - Initialisierung von Javascript', + 'Cart block' => 'Warenkorb Block', + 'Categories - JavaScript' => 'Kategorien - JavaScript', + 'Categories - at the bottom of the catalog' => 'Kategorien - unten an dem Katalog', + 'Categories - at the top' => 'Kategorien - oben', + 'Categories - bottom' => 'Kategorien - unten', + 'Categories - caption' => 'Kategorien - Bildunterschrift', + 'Categories - header' => 'Kategorien - Kopfzeile', + 'Categories - row' => 'Kategorien - Zeile', + 'Category' => 'Kategorie', + 'Category - Edit JavaScript' => 'Kategorie - JavaScript Änderung', + 'Category - Tab' => 'Kategorie - Tab', + 'Category - content' => 'Kategorie - Inhalt', + 'Category - contents table header' => 'Kategorie - Inhalts Tabellenkopf', + 'Category - contents table row' => 'Kategorie - Inhalts Tabellenzeile', + 'Category - create form' => 'Kategorie - Erstellungsformular', + 'Category - delete form' => 'Kategorie - Löschungsformular', + 'Category configuration' => 'Kategorie-Konfiguration', + 'Category edit - bottom' => 'Kategorie Bearbeitung - unten', + 'Category edit - top' => 'Kategorie Bearbeitung - oben', + 'Category page - CSS stylesheet' => 'Kategorieseite - CSS-Stylesheet', + 'Category page - after javascript include' => 'Kategorieseite - Nach Integration von JavaScript', + 'Category page - after javascript initialisation' => 'Kategorieseite - nach der Initialisierung von Javascript', + 'Category page - after the main content area' => 'Kategorieseite - nach dem Hauptinhaltsbereich', + 'Category page - at the bottom' => 'Kategorieseite - unten', + 'Category page - at the bottom of the main area' => 'Kategorieseite - unten an dem Hauptbereich', + 'Category page - at the bottom of the sidebar' => 'Kategorieseite - unten an der Sidebar', + 'Category page - at the top' => 'Kategorieseite - oben', + 'Category page - at the top of the main area' => 'Kategorieseite - oben an dem Hauptbereich', + 'Category page - at the top of the sidebar' => 'Kategorieseite - oben an der Sidebar', + 'Category page - before the main content area' => 'Kategorieseite - vor dem Hauptinhaltsbereich', + 'Category page - the body of the sidebar' => 'Kategorieseite - Sidebars Body', + 'Central African Republic' => 'Zentralafrikanische Republik', + 'Chad' => 'Tschad', + 'Change password - CSS stylesheet' => 'Passwort Änderung - CSS-Stylesheet', + 'Change password - after javascript include' => 'Passwort Änderung - Nach Integration von JavaScript', + 'Change password - after javascript initialisation' => 'Passwort Änderung - nach der Initialisierung von Javascript', + 'Change password - at the bottom' => 'Passwort Änderung - unten', + 'Change password - at the top' => 'Passwort Änderung - oben', + 'Check available product stock (1) or ignore it (0) when displaying and changing ordered quantity' => 'Verfügbaren Lagerbestand prüfen (1) oder ignorieren (0) beim Anzeigen und Änderung der bestellte Menge', + 'Check if a virtual product delivery module is enabled if at least one product is virtual' => 'Prüfen ob ein Liefermodul für virtuellen Produkte aktiviert ist, wenn es mindestens ein virtuelles Produkt gibt', + 'Chile' => 'Chile', + 'China' => 'China', + 'Client edit - bottom' => 'Kunde Bearbeitung - unten', + 'Client edit - top' => 'Kunde Bearbeitung - oben', + 'Colombia' => 'Kolumbien', + 'Comoros' => 'Komoren', + 'Compile templates assets automatically upon asset source change (1 = yes, 0 = no)' => 'Template Assets automatisch bei Codeänderungen kompilieren? (1 = ja, 0 = nein)', + 'Configuration' => 'Einstellungen', + 'Configuration - JavaScript' => 'Konfiguration - JavaScript', + 'Configuration - at the bottom of the catalog' => 'Konfiguration - unten an dem katalog', + 'Configuration - at the bottom of the shipping area' => 'Konfiguration - unten an der Lieferzone', + 'Configuration - at the bottom of the system area' => 'Konfiguration - unten an dem Systembereich', + 'Configuration - at the top' => 'Konfiguration - oben', + 'Configuration - at the top of the catalog area' => 'Konfiguration - oben an dem Katalogsbereich', + 'Configuration - at the top of the shipping area' => 'Konfiguration - oben an der Lieferzone', + 'Configuration - at the top of the system area' => 'Konfiguration - oben an dem Systembereich', + 'Configuration - bottom' => 'Konfiguration - unten', + 'Configuration / Administrator' => 'Konfiguration / Administrator', + 'Configuration / Area' => 'Konfiguration / Zone', + 'Configuration / Attribute' => 'Konfiguration / Deklination', + 'Configuration / Cache' => 'Konfiguration / Cache', + 'Configuration / Country' => 'Konfiguration / Land', + 'Configuration / Currency' => 'Konfiguration / Währung', + 'Configuration / Feature' => 'Konfiguration / Charakteristik', + 'Configuration / Language' => 'Konfiguration / Sprache', + 'Configuration / Mailing-system' => 'Konfiguration / Mailing-System', + 'Configuration / Message' => 'Konfiguration / Nachricht', + 'Configuration / Module' => 'Konfiguration / Modul', + 'Configuration / Profile' => 'Konfiguration / Profil', + 'Configuration / Shipping-zone' => 'Konfiguration / Lieferzone', + 'Configuration / System Log' => 'Konfiguration / Logs System', + 'Configuration / Tax' => 'Konfiguration / Tax', + 'Configuration / Template' => 'Konfiguration / Template', + 'Configuration variables' => 'Konfigurations Variablen', + 'Congo' => 'Kongo', + 'Contact block' => 'Kontakt-Block', + 'Contact page - CSS stylesheet' => 'Kontaktseite - CSS-Stylesheet', + 'Contact page - after javascript include' => 'Kontaktseite - Nach Integration von JavaScript', + 'Contact page - after javascript initialisation' => 'Kontaktseite - nach der Initialisierung von Javascript', + 'Contact page - at the bottom' => 'Kontaktseite - unten', + 'Contact page - at the bottom of the form' => 'Kontaktseite - unten an dem Formular', + 'Contact page - at the top' => 'Kontaktseite - oben', + 'Contact page - at the top of the form' => 'Kontaktseite - oben an dem Formular', + 'Contact page - if successful response' => 'Kontaktseite - wenn erfolgreich', + 'Content' => 'Inhalt', + 'Content - Edit JavaScript' => 'Inhalt - JavaScript Änderung', + 'Content - Tab' => 'Inhalt - Tab', + 'Content - content' => 'Inhalt - Inhalt', + 'Content - create form' => 'Inhalt - Erstellungsformular', + 'Content - delete form' => 'Inhalt - Löschungsformular', + 'Content edit - bottom' => 'Inhalt Bearbeitung - unten', + 'Content edit - right column bottom' => 'Inhalt bearbeiten - Rechte Spalte unten', + 'Content edit - right column top' => 'Inhalt bearbeiten - Rechte Spalte oben', + 'Content edit - top' => 'Inhalt Bearbeitung - oben', + 'Content page - CSS stylesheet' => 'Inhaltseite - CSS-Stylesheet', + 'Content page - after javascript include' => 'Inhaltseite - Nach Integration von JavaScript', + 'Content page - after javascript initialisation' => 'Inhaltseite - nach der Initialisierung von Javascript', + 'Content page - after the main content area' => 'Inhaltseite - nach dem Hauptinhaltsbereich', + 'Content page - at the bottom' => 'Inhaltseite - unten', + 'Content page - at the bottom of the main area' => 'Inhaltseite - unten an dem Hauptbereich', + 'Content page - at the bottom of the sidebar' => 'Inhaltseite - unten an der Sidebar', + 'Content page - at the top' => 'Inhaltseite - oben', + 'Content page - at the top of the main area' => 'Inhaltseite - oben an dem Hauptbereich', + 'Content page - at the top of the sidebar' => 'Inhaltseite - oben an der Sidebar', + 'Content page - before the main content area' => 'Inhaltseite- vor dem Hauptinhaltsbereich', + 'Content page - the body of the sidebar' => 'Inhaltseite - Sidebars Body', + 'Contents - caption' => 'Inhalte - Bildunterschrift', + 'Contents - header' => 'Inhalte - Kopfzeile', + 'Contents - row' => 'Inhalte - Zeile', + 'Cook Islands' => 'Cookinseln', + 'Costa Rica' => 'Costa Rica', + 'Countries - JavaScript' => 'Länder - JavaScript', + 'Countries - at the top' => 'Länder - oben', + 'Countries - bottom' => 'Länder - unten', + 'Countries - table header' => 'Länder - Tabellenkopf', + 'Countries - table row' => 'Länder - Tabellenzeile', + 'Country - Edit JavaScript' => 'Land - JavaScript Änderung', + 'Country - create form' => 'Land - Erstellungsformular', + 'Country - delete form' => 'Land - Löschungsformular', + 'Country edit - bottom' => 'Währung Bearbeitung - unten', + 'Country edit - top' => 'Währung Bearbeitung - oben', + 'Coupon' => 'Gutschein', + 'Coupon - at the top' => 'Gutschein - oben', + 'Coupon - bottom' => 'Gutschein - unten', + 'Coupon - create JavaScript' => 'Gutschein - JavaScript erstellen', + 'Coupon - list JavaScript' => 'Gutschein - JavaScript den Listen', + 'Coupon - list caption' => 'Gutschein - Bildunterschrift', + 'Coupon - table header' => 'Gutschein - Tabellenkopf', + 'Coupon - table row' => 'Gutschein - Tabellenzeile', + 'Coupon - update JavaScript' => 'Gutschein - JavaScript Änderung', + 'Coupon page - in deletion form' => 'Gutschein-Seite - Löschungsformular', + 'Croatia' => 'Kroatien', + 'Cuba' => 'Kuba', + 'Curency selection page - CSS stylesheet' => 'Währungswahl-Seite - CSS-Stylesheet', + 'Curency selection page - after javascript include' => 'Währungswahl-Seite - Nach Integration von JavaScript', + 'Curency selection page - after javascript initialisation' => 'Währungswahl-Seite - nach der Initialisierung von Javascript', + 'Curency selection page - at the bottom' => 'Währungswahl-Seite - unten', + 'Curency selection page - at the top' => 'Währungswahl-Seite - oben', + 'Currencies - JavaScript' => 'Währungen - JavaScript', + 'Currencies - at the top' => 'Währungen - oben', + 'Currencies - bottom' => 'Währungen - unten', + 'Currencies - table header' => 'Währungen - Tabellenkopf', + 'Currencies - table row' => 'Währungen - Tabellenzeile', + 'Currency - Edit JavaScript' => 'Währung - JavaScript Änderung', + 'Currency - create form' => 'Währung - Erstellungsformular', + 'Currency - delete form' => 'Währung - Löschungsformular', + 'Currency block' => 'Währungensblock', + 'Currency edit - bottom' => 'Währung Bearbeitung - unten', + 'Currency edit - top' => 'Währung Bearbeitung - oben', + 'Customer' => 'Kunde', + 'Customer - Edit' => 'Kunde - Modification', + 'Customer - Edit JavaScript' => 'Kunde - JavaScript Änderung', + 'Customer - address create form' => 'Kunde - Adresse-Erstellungsformular', + 'Customer - address delete form' => 'Kunde - Adresse-Löschungsformular', + 'Customer - address update form' => 'Kunde - Adresse-Änderungsformular', + 'Customer - at the top' => 'Kunde - oben', + 'Customer - bottom' => 'Kunde - unten', + 'Customer - create form' => 'Kunde - Erstellungsformular', + 'Customer - delete form' => 'Kunde - Löschungsformular', + 'Customer - order table header' => 'Kunde - Bestellungs-Tabellenkopf', + 'Customer - order table row' => 'Kunde - Bestellungs-Tabellenzeile', + 'Customer account - additional information' => 'Kundenkonto - Erweitere Informationen', + 'Customer account block' => 'Kundenkonto-Block', + 'Customer title' => 'Kunde-Andere', + 'Customers - JavaScript' => 'Kunden - JavaScript', + 'Customers - caption' => 'Kunden - Bildunterschrift', + 'Customers - header' => 'Kunden - Tabellenkopf', + 'Customers - row' => 'Kunden - Zeile', + 'Cyprus' => 'Zypern', + 'Czech Republic' => 'Tschechische Republik', + 'Danish krone' => 'Dänische Kronen', + 'Dashboard - at the top' => 'Dashboard - oben', + 'Dashboard - bottom' => 'Dashboard - unten', + 'Dashboard - middle' => 'Dashboard - in der Mitte', + 'Data import / export' => 'Importation / Exportation von Daten', + 'Default available stock when check-available-stock is set to 0.' => 'Standart verfügbaren Bestand wenn check-available-stock gleich 0.', + 'Default lang without translation' => 'Standartsprache ohne Übersetzung', + 'Delivery - After delivery module' => 'Lieferung - Nach dem Liefermodul', + 'Delivery - CSS' => 'Lieferung - CSS', + 'Delivery - additional product information' => 'Lieferung - Weitere Produktinformationen', + 'Delivery - after addresse area' => 'Lieferung - Nach dem Adresse-Bereich', + 'Delivery - after the information area' => 'Lieferung - Nach dem Informationsbereich', + 'Delivery - after the order summary' => 'Lieferung - Nach der Zusammenfassung der Bestellung', + 'Delivery - at the bottom of information area' => 'Lieferung - unten an dem Informationsbereich', + 'Delivery - at the bottom of the footer' => 'Lieferung - unten an dem Footer', + 'Delivery - at the top of the footer' => 'Lieferung - oben an dem Footer', + 'Delivery - delivery address' => 'Lieferung - Lieferadresse', + 'Delivery - imprint' => 'Lieferung - Impressum', + 'Delivery - in the header' => 'Lieferung - im Header', + 'Delivery choice - CSS stylesheet' => 'Lieferwahl - CSS-Stylesheet', + 'Delivery choice - after javascript include' => 'Lieferwahl - Nach Integration von JavaScript', + 'Delivery choice - after javascript initialisation' => 'Lieferwahl - nach der Initialisierung von Javascript', + 'Delivery choice - at the bottom' => 'Lieferwahl - unten', + 'Delivery choice - at the bottom of the form' => 'Lieferwahl - unten an dem Formular', + 'Delivery choice - at the top' => 'Lieferwahl - oben', + 'Delivery choice - at the top of the form' => 'Lieferwahl - oben an dem Formular', + 'Delivery choice - extra area' => 'Lieferwahl - Erweiteren Bereich', + 'Delivery choice - javascript' => 'Lieferwahl - Javascript', + 'Delivery zone - Edit JavaScript' => 'Lieferzone - JavaScript Änderung', + 'Delivery zone - JavaScript' => 'Lieferzone - JavaScript', + 'Delivery zone - at the top' => 'Lieferzone - oben', + 'Delivery zone - bottom' => 'Lieferzone - unten', + 'Delivery zone - table header' => 'Lieferzone - Tabellenkopf', + 'Delivery zone - table row' => 'Lieferzone - Tabellenzeile', + 'Denmark' => 'Dänemark', + 'Display and process prices with (0) or without (1) taxes.' => 'Anzeigt und verwendet Preise mit (0) oder ohne (1) Taxen', + 'Djibouti' => 'Djibuti', + 'Document - Edit JavaScript' => 'Dokument - JavaScript Änderung', + 'Document edit - bottom' => 'Dokument Bearbeitung - unten', + 'Document edit - top' => 'Dokument Bearbeitung - oben', + 'Dollar' => 'Dollar', + 'Dollar (CAD)' => 'Dollar (CAD)', + 'Dominica' => 'Dominikanische Republik', + 'Dominican Republic' => 'Dominikanische Republik', + 'Ecuador' => 'Ecuador', + 'Egypt' => 'Ägypten', + 'El Salvador' => 'El Salvador', + 'Email html - layout - CSS' => 'E-Mail html - Layout - CSS', + 'Email html - layout - footer' => 'E-Mail html - Layout - Fußzeile', + 'Email html - order confirmation - after address' => 'E-Mail html - Bestellbestätigung - nach Adresse', + 'Email html - order confirmation - after products' => 'E-Mail html - Bestellbestätigung - nach Produkten', + 'Email html - order confirmation - before address' => 'E-Mail html - Bestellbestätigung - vor Adresse', + 'Email html - order confirmation - before products' => 'E-Mail html - Bestellbestätigung - vor Produkten', + 'Enable (1) or disable (0) URL rewriting' => 'Aktivieren (1) oder deaktivieren (0) URL Überschreibung', + 'Equatorial Guinea' => 'Äquatorialguinea', + 'Eritrea' => 'Eritrea', + 'Estonia' => 'Estland', + 'Ethiopia' => 'Äthiopien', + 'Euro' => 'Euro', + 'Export - JavaScript' => 'Export - JavaScript', + 'Export - table header' => 'Export - Tabellenkopf', + 'Export - table row' => 'Export - Tabellenzeile', + 'Export modal or page - bottom' => 'Export modal or page - unten', + 'Export modal or page - top' => 'Export modal or page - oben', + 'Exports - JavaScript' => 'Exporte - JavaScript', + 'Exports - at the bottom of a category' => 'Exporte - unten einer Kategorie', + 'Exports - at the bottom of column 1' => 'Exporte - unten der Spalte 1', + 'Exports - at the top' => 'Exporte - oben', + 'Feature - Edit JavaScript' => 'Karakteristik - JavaScript Änderung', + 'Feature - Value create form' => 'Karakteristik - Angabe-Erstellungsformular', + 'Feature - add to all form' => 'Karakteristik - zu allen hinzufügen Formular', + 'Feature - create form' => 'Karakteristik - Erstellungsformular', + 'Feature - delete form' => 'Karakteristik - Löschungsformular', + 'Feature - remove to all form' => 'Karakteristik - multipel Löschungsformular', + 'Feature edit - bottom' => 'Charakteristik Bearbeitung - unten', + 'Feature edit - top' => 'Charakteristik Bearbeitung - oben', + 'Features - JavaScript' => 'Karakteristiken - JavaScript', + 'Features - at the top' => 'Karakteristiken - oben', + 'Features - bottom' => 'Karakteristiken - unten', + 'Features - table header' => 'Karakteristiken - Tabellenkopf', + 'Features - table row' => 'Karakteristiken - Tabellenzeile', + 'Features value - table header' => 'Karakteristiken-Angaben - Tabellenkopf', + 'Features value - table row' => 'Karakteristiken-Angaben - Tabellenzeile', + 'Fiji' => 'Fiji', + 'File name of the 404 (not found) view in the current template (with extension, e.g. 404.html)' => 'Name der Seite 404 (unauffindbar) in dem aktuellen Modell (mit der Dateinamenerweiterung 404.html zum Beispiel)', + 'Filename of the error page' => 'Dateiname der Fehlerseite', + 'Finland' => 'Finnland', + 'Folder' => 'Ordner', + 'Folder - Edit JavaScript' => 'Ordner - JavaScript Änderung', + 'Folder - JavaScript' => 'Ordner - JavaScript', + 'Folder - Tab' => 'Ordner - Tab', + 'Folder - at the top' => 'Ordner - oben', + 'Folder - bottom' => 'Ordner - unten', + 'Folder - caption' => 'Ordner - Bildunterschrift', + 'Folder - content' => 'Ordner - Inhalt', + 'Folder - create form' => 'Ordner - Erstellungsformular', + 'Folder - delete form' => 'Ordner - Löschungsformular', + 'Folder - header' => 'Ordner - Header', + 'Folder - row' => 'Ordner - Zeile', + 'Folder edit - bottom' => 'Ordner Bearbeitung - unten', + 'Folder edit - right column bottom' => 'Ordner bearbeiten - Rechte Spalte unten', + 'Folder edit - right column top' => 'Ordner bearbeiten - Rechte Spalte oben', + 'Folder edit - top' => 'Ordner Bearbeitung - oben', + 'Folder page - CSS stylesheet' => 'Ordnerseite - CSS-Stylesheet', + 'Folder page - after javascript include' => 'Ordnerseite - Nach Integration von JavaScript', + 'Folder page - after javascript initialisation' => 'Ordnerseite - nach der Initialisierung von Javascript', + 'Folder page - after the main content area' => 'Ordnerseite - nach dem Hauptinhaltsbereich', + 'Folder page - at the bottom' => 'Ordnerseite - unten', + 'Folder page - at the bottom of the main area' => 'Ordnerseite - unten an dem Hauptbereich', + 'Folder page - at the top' => 'Ordnerseite - oben', + 'Folder page - at the top of the main area' => 'Ordnerseite - oben an dem Hauptbereich', + 'Folder page - before the main content area' => 'Ordnerseite - vor dem Hauptinhaltsbereich', + 'France metropolitan' => 'Frankreich', + 'French 10% VAT' => '10% Französische MwSt.', + 'French 20% VAT' => '20% Französische MwSt.', + 'French Southern Territories' => 'Französische Süd- und Antarktisgebiete', + 'Front office integration' => 'Front office Modul ', + 'Gabon' => 'Gabun', + 'Gambia' => 'Gambie', + 'Georgia' => 'Georgien', + 'Germany' => 'Deutschland', + 'Ghana' => 'Ghana', + 'Google Analytics block' => 'Google Analytics Block', + 'Greece' => 'Griechenland', + 'Grenada' => 'Grenada', + 'Guadeloupe' => 'Guadeloupe', + 'Guatemala' => 'Guatemala', + 'Guinea' => 'Guinea', + 'Guinea-Bissau' => 'Guinea-Bissau', + 'Guyana' => 'Guyana', + 'Guyane Française' => 'Französisch-Guayana', + 'HTML layout - CSS stylesheet' => 'HTML Struktur - CSS-Stylesheet', + 'HTML layout - after javascript include' => 'HTML Struktur - Nach Integration von JavaScript', + 'HTML layout - after the main content area' => 'HTML Struktur - nach dem Hauptinhaltsbereich', + 'HTML layout - after the opening of the body tag' => 'HTML Struktur - nach der Eröffnung des Body-Tag', + 'HTML layout - after the opening of the head tag' => 'HTML Struktur - nach der Eröffnung des Head-Tag', + 'HTML layout - at the bottom of the header' => 'HTML Struktur - unten an dem Header', + 'HTML layout - at the top of the footer' => 'HTML Struktur - oben an dem Footer', + 'HTML layout - at the top of the header' => 'HTML Struktur - oben an dem Header', + 'HTML layout - before the end body tag' => 'HTML Struktur - vor dem Ende des Body-Tag', + 'HTML layout - before the end of the head tag' => 'HTML Struktur - vor dem Ende des Head-Tag', + 'HTML layout - before the main content area' => 'HTML Struktur - vor dem Hauptinhaltsbereich', + 'HTML layout - bottom of the footer' => 'HTML Struktur - unten an dem Footer', + 'HTML layout - footer body' => 'HTML Struktur - Footer Body', + 'HTML layout - javascript initialization' => 'HTML Struktur - Initialisierung von Javascript', + 'HTML layout - primary navigation' => 'HTML Struktur - Hauptnavigation', + 'HTML layout - secondary navigation' => 'HTML Struktur - Sekundärenavigation', + 'Haiti' => 'Haiti', + 'Home - JavaScript' => 'Accueil - JavaScript', + 'Home - at the top' => 'Accueil - oben', + 'Home - block' => 'Accueil - Block', + 'Home - bottom' => 'Accueil - unten', + 'Home page - CSS stylesheet' => 'Startseite - CSS-Stylesheet', + 'Home page - after javascript include' => 'Startseite - Nach Integration von JavaScript', + 'Home page - after javascript initialisation' => 'Startseite - nach der Initialisierung von Javascript', + 'Home page - main area' => 'Startseite - Hauptbereich', + 'Honduras' => 'Honduras', + 'Hong Kong' => 'Hong Kong', + 'Hook - Edit JavaScript' => 'Hook - JavaScript Änderung', + 'Hook - create form' => 'Hook - Erstellungsformular', + 'Hook - delete form' => 'Hook - Löschungsformular', + 'Hook edit - bottom' => 'Hook Bearbeitung - unten', + 'Hook edit - top' => 'Hook Bearbeitung - oben', + 'Hook positions' => 'Hook Positionen', + 'Hooks' => 'Andockpunkte', + 'Hooks - JavaScript' => 'Hooks - JavaScript', + 'Hooks - at the top' => 'Hooks - oben', + 'Hooks - bottom' => 'Hooks - unten', + 'Hooks - table header' => 'Hooks - Tabellenkopf', + 'Hooks - table row' => 'Hooks - Tabellenzeile', + 'Hooks management' => 'Hooks Verwendung', + 'How document files are delivered in the web space (symlink or copy)' => 'Wie werden Dokumentdateien im Webspace (Symlink oder Kopie) ausgeliefert', + 'How original (full resolution) images are delivered in the web space (symlink or copy)' => 'Wie werden die Originalbilder (volle Auflösung) im Webspace ausgeliefert (symlink or copy)', + 'Hungary' => 'Ungarn', + 'Iceland' => 'Island', + 'Image - Edit JavaScript' => 'Bild - JavaScript Änderung', + 'Image edit - bottom' => 'Bild Bearbeitung - unten', + 'Image edit - top' => 'Bild Bearbeitung - oben', + 'Import - table header' => 'Import - Tabellenkopf', + 'Import - table row' => 'Import - Tabellenzeile', + 'India' => 'Indien', + 'Indonesia' => 'Indonesien', + 'Invoice - After delivery module' => 'Rechnung - Nach dem Liefermodul', + 'Invoice - After payment module' => 'Rechnung - Nach dem Zahlungsmodul', + 'Invoice - CSS' => 'Rechnung - CSS', + 'Invoice - additional product information' => 'Rechnung - Weitere Produktinformationen', + 'Invoice - after addresse area' => 'Rechnung - nach dem Adressebereich', + 'Invoice - after product listing' => 'Rechnung - nach der Produktliste', + 'Invoice - after the information area' => 'Rechnung - nach dem Informationsbereich', + 'Invoice - after the order summary' => 'Rechnung - nach der Bestellungs-Zusammenfassung', + 'Invoice - at the bottom of information area' => 'Rechnung - unten an dem Informationsbereich', + 'Invoice - at the bottom of the footer' => 'Rechnung - unten an dem Footer', + 'Invoice - at the top of the footer' => 'Rechnung - oben an dem Footer', + 'Invoice - delivery address' => 'Rechnung - Bestellungsadresse', + 'Invoice - imprint' => 'Rechnung - Impressum', + 'Invoice - in the header' => 'Rechnung - im Header', + 'Invoice choice - CSS stylesheet' => 'Bezahlungsmethode - CSS-Stylesheet', + 'Invoice choice - after javascript include' => 'Bezahlungsmethode - Nach Integration von JavaScript', + 'Invoice choice - after javascript initialisation' => 'Bezahlungsmethode - nach der Initialisierung von Javascript', + 'Invoice choice - at the bottom' => 'Bezahlungsmethode - unten', + 'Invoice choice - at the top' => 'Bezahlungsmethode - oben', + 'Invoice choice - delivery address' => 'Bezahlungsmethode - Lieferadresse', + 'Invoice choice - extra payment zone' => 'Bezahlungsmethode - extra payment zone', + 'Iran' => 'Iran', + 'Iraq' => 'Irak', + 'Ireland' => 'Irland', + 'Israel' => 'Israel', + 'Italy' => 'Italien', + 'Ivory Coast' => 'Elfenbeinküste', + 'Jamaica' => 'Jamaika', + 'Japan' => 'Japan', + 'Jordan' => 'Jordanien', + 'Kazakhstan' => 'Kasachstan', + 'Kenya' => 'Kenia', + 'Kiribati' => 'Kiribati', + 'Kuwait' => 'Kuwait', + 'Kyrgyzstan' => 'Kirgisistan', + 'Language - create form' => 'Sprache - Erstellungsformular', + 'Languages - JavaScript' => 'Sprachen - JavaScript', + 'Languages - at the top' => 'Sprachen - oben', + 'Languages - bottom' => 'Sprachen - unten', + 'Languages - delete form' => 'Sprachen - Löschungsformular', + 'Languages block' => 'Sprachen Block', + 'Laos' => 'Laos', + 'Latvia' => 'Lettland', + 'Layout - Before the main content' => 'Layout - vor dem Hauptinhaltsbereich', + 'Layout - CSS' => 'Layout - CSS', + 'Layout - JavaScript' => 'Layout - JavaScript', + 'Layout - after footer' => 'Layout - nach dem Footer', + 'Layout - after top bar' => 'Layout - nach der Titelleiste', + 'Layout - after top menu' => 'Layout - nach dem Top Menü', + 'Layout - at the bottom of the top bar' => 'Layout - unten an der Titelleiste', + 'Layout - at the top of the top bar' => 'Layout - oben an der Titelleiste', + 'Layout - before footer' => 'Layout - vor dem Footer', + 'Layout - before top menu' => 'Layout - vor dem Top Menü', + 'Layout - before topbar' => 'Layout - vor der Titelleiste', + 'Layout - in footer' => 'Layout - Im Footer', + 'Layout - in the menu catalog' => 'Layout - im Katalogs-Menü', + 'Layout - in the menu configuration' => 'Layout - im konfigurations-Menü', + 'Layout - in the menu customers' => 'Layout - im Kundes-Menü', + 'Layout - in the menu folders' => 'Layout - im Ordners-Menü', + 'Layout - in the menu modules' => 'Layout - im Moduls-Menü', + 'Layout - in the menu orders' => 'Layout - im Bestellungsmenü', + 'Layout - in the menu tools' => 'Layout - im Tools-Menü', + 'Layout - in top menu items' => 'Layout - in Top-Menü Elementen', + 'Layout - inside top bar' => 'Layout - in der Titelleiste', + 'Leave the default configuration of session' => 'Die Session Standartkonfiguration lassen', + 'Lebanon' => 'Libanon', + 'Lesotho' => 'Lesotho', + 'Liberia' => 'Liberia', + 'Libya' => 'Libyen', + 'Liechtenstein' => 'Liechtenstein', + 'Life time of the cart cookie in the customer browser, in seconds' => 'Dauer der Warenkorb-Cookie in dem Kunden-Browser, in Sekunden', + 'Life time of the session cookie in the customer browser, in seconds' => 'Dauer der Session-Cookie in dem Kunden-Browser, in Sekunden', + 'Links block' => 'Links Block', + 'Lithuania' => 'Litauen', + 'Logging system configuration' => 'Logs System Konfiguration', + 'Login page - CSS stylesheet' => 'Anmeldeseite - CSS-Stylesheet', + 'Login page - after javascript include' => 'Anmeldeseite - Nach Integration von JavaScript', + 'Login page - after javascript initialisation' => 'Anmeldeseite - nach der Initialisierung von Javascript', + 'Login page - at the bottom' => 'Anmeldeseite - unten', + 'Login page - at the bottom of the form' => 'Anmeldeseite - unten an dem Formular', + 'Login page - at the bottom of the main area' => 'Anmeldeseite - unten an dem Hauptbereich', + 'Login page - at the top' => 'Anmeldeseite - oben', + 'Login page - at the top of the form' => 'Anmeldeseite - oben im Formular', + 'Login page - at the top of the main area' => 'Anmeldeseite - oben an dem Hauptbereich', + 'Logs - JavaScript' => 'Protokolle - JavaScript', + 'Logs - at the top' => 'Logs - oben', + 'Logs - bottom' => 'Logs - unten', + 'Lost password - CSS stylesheet' => 'Passwort verloren - CSS-Stylesheet', + 'Lost password - after javascript include' => 'Passwort verloren - Nach Integration von JavaScript', + 'Lost password - at the bottom' => 'Passwort verloren - unten', + 'Lost password - at the bottom of the form' => 'Passwort verloren - unten an dem Formular', + 'Lost password - at the top' => 'Passwort verloren - oben', + 'Lost password - at the top of the form' => 'Passwort verloren - oben im Formular', + 'Lost password - javascript initialization' => 'Passwort verloren - Initialisierung von Javascript', + 'Luxembourg' => 'Luxemburg', + 'Macedonia' => 'Mazedonien', + 'Madagascar' => 'Madagaskar', + 'Mail sent to the customer when its account is created by an administrator in the back-office' => 'Mail an den Kunden geschickt, wenn sein Konto von einem Administrator im Back-Office erstellt wird', + 'Mail sent to the customer when its password or email is changed in the back-office' => 'Mail an den Kunden geschickt, wenn sein Passwort oder E-Mail von einem Administrator im Back-Office geändert werden', + 'Mailing system - JavaScript' => 'E-Mail Sendung - JavaScript', + 'Mailing system - at the top' => 'E-Mail Sendung - oben', + 'Mailing system - bottom' => 'E-Mail Sendung - unten', + 'Malawi' => 'Malawi', + 'Malaysia' => 'Malaysien', + 'Maldives' => 'Malediven', + 'Mali' => 'Mali', + 'Malta' => 'Malta', + 'Marshall Islands' => 'Marshallinseln', + 'Martinique' => 'Martinique', + 'Mauritania' => 'Mauretanien', + 'Mauritius' => 'Mauritius', + 'Mayotte' => 'Mayotte', + 'Message - Edit JavaScript' => 'Nachricht - JavaScript Änderung', + 'Message - create form' => 'Nachricht - Erstellungsformular', + 'Message - delete form' => 'Nachricht - Löschungsformular', + 'Message edit - bottom' => 'Nachricht Bearbeitung - unten', + 'Message edit - top' => 'Nachricht Bearbeitung - oben', + 'Message sent to the shop owner when a new order is placed' => 'Gesendete Nachricht wenn eine neue Bestellung erteilt wird.', + 'Messages - JavaScript' => 'Nachrichten - JavaScript', + 'Messages - at the top' => 'Nachrichten - oben', + 'Messages - bottom' => 'Nachrichten - unten', + 'Messages - table header' => 'Nachrichten - Tabellenkopf', + 'Messages - table row' => 'Nachrichten - Tabellenzeile', + 'Mexico' => 'Mexiko', + 'Micronesia' => 'Mikronesien', + 'Mini cart' => 'Mini-Warenkorb', + 'Miss' => 'Fräulein', + 'Miss_short' => 'Fr.', + 'Misses' => 'Frau', + 'Mister' => 'Herr', + 'Module - Edit JavaScript' => 'Modul - JavaScript Änderung', + 'Module - configuration' => 'Modul - Konfiguration', + 'Module - configuration JavaScript' => 'Modul - JavaScript Konfiguration', + 'Module edit - bottom' => 'Modul Bearbeitung - unten', + 'Module edit - top' => 'Modul Bearbeitung - oben', + 'Module hook - Edit JavaScript' => 'Modul Hook - JavaScript Änderung', + 'Module hook - JavaScript' => 'Modul Hook - JavaScript', + 'Module hook - create form' => 'Modul Hook - Erstellungsformular', + 'Module hook - delete form' => 'Modul Hook - Löschungsformular', + 'Module hook edit - bottom' => 'Modul-Hook Bearbeitung - unten', + 'Module hook edit - top' => 'Modul-Hook Bearbeitung - oben', + 'Modules - JavaScript' => 'Modulen - JavaScript', + 'Modules - at the top' => 'Modulen - oben', + 'Modules - bottom' => 'Modulen - unten', + 'Modules - table header' => 'Modulen - Tabellenkopf', + 'Modules - table row' => 'Modulen - Tabellenzeile', + 'Modules maagement' => 'Modul Verwendung', + 'Modules management' => 'Modul Verwendung', + 'Moldova' => 'Moldau', + 'Monaco' => 'Monaco', + 'Mongolia' => 'Mongolei', + 'Morocco' => 'Marokko', + 'Mozambique' => 'Mosambik', + 'Mr.' => 'Hr.', + 'Mrs' => 'Fr.', + 'Name of the active PDF template' => 'Name der aktiven PDF Template', + 'Name of the active back-office template' => 'Name der aktiven Back Office Template', + 'Name of the active front-office template' => 'Name der aktiven Front Office Template', + 'Name of the active mailing template' => 'Name der aktiven E-Mail Template', + 'Name of the cart cookie' => 'Name der Warenkorb-Cookie', + 'Name of the delivery view in the current PDF template (without extension)' => 'Name der Lieferung Sicht in der aktuellen PDF-Vorlage (ohne Erweiterung)', + 'Name of the graphic driver used by the Imagine library (see https://imagine.readthedocs.org)' => 'Name des Grafik-Treibers, der von der Imagine-Bibliothek verwendet wird (siehe https://imagine.readthedocs.org)', + 'Name of the invoice view in the current PDF template (without extension)' => 'Name der Rechnungsansicht in der aktuellen PDF-Vorlage (ohne Erweiterung)', + 'Name of the template view returned when an obsolete (or inactive) product URL is invoked' => 'Name des Templates zurückgegeben, wenn eine veraltete (oder inaktive) Produkt-URL aufgerufen wird', + 'Name the cart cookie' => 'Name der Warenkorb-Cookie', + 'Namibia' => 'Namibia', + 'Nauru' => 'Nauru', + 'Navigation block' => 'Menü Block', + 'Nepal' => 'Nepal', + 'Netherlands' => 'Niederlande', + 'New Products block' => 'Neue Produkte Block', + 'New York' => 'New York', + 'New Zealand' => 'Neuseeland', + 'New order {$order_ref} placed on {config key="store_name"}' => 'Neue Bestellung {$order_ref} für {config key="store_name"}', + 'Newsletter block' => 'Newsletter Block', + 'Newsletter page - CSS stylesheet' => 'Newletter-Seite - CSS-Stylesheet', + 'Newsletter page - after javascript include' => 'Newletter-Seite - Nach Integration von JavaScript', + 'Newsletter page - after javascript initialisation' => 'Newletter-Seite - nach der Initialisierung von Javascript', + 'Newsletter page - at the bottom' => 'Newletter-Seite - unten', + 'Newsletter page - at the top' => 'Newletter-Seite - oben', + 'Nicaragua' => 'Nicaragua', + 'Niger' => 'Niger', + 'Nigeria' => 'Nigeria', + 'Niue' => 'Niue', + 'North Korea' => 'Nordkorea', + 'Norway' => 'Norwegen', + 'Not paid' => 'Nicht bezahlt', + 'Nouvelle-Calédonie' => 'Neu-Kaledonien', + 'Oman' => 'Oman', + 'Order' => 'Bestellung', + 'Order - After closing product row' => 'Bestellung - Nach Sperrung der Produkt Zeile', + 'Order - After product list' => 'Bestellung - Nach der Produktliste', + 'Order - Before product list' => 'Bestellung - Vor der Produktliste', + 'Order - Before starting product row' => 'Bestellung - Vor der Öffnung der Produktzeile', + 'Order - Edit JavaScript' => 'Bestellung - JavaScript Änderung', + 'Order - Tab' => 'Bestellung - Tab', + 'Order - bill bottom' => 'Bestellung - Rechnung unten', + 'Order - bill top' => 'Bestellung - Rechnung oben', + 'Order - cart bottom' => 'Bestellung - Warenkorb unten', + 'Order - cart top' => 'Bestellung - Warenkorb oben', + 'Order - content' => 'Bestellung - Inhalt', + 'Order - customer information bottom' => 'Bestellung - Kunde Informationen unten', + 'Order - delivery module bottom' => 'Bestellung - Liefermodul unten', + 'Order - payment module bottom' => 'Bestellung - Zahlungsmodul unten', + 'Order - product list' => 'Bestellung - Produktliste', + 'Order - table header' => 'Bestellung - Tabellenkopf', + 'Order - table row' => 'Bestellung - Tabellenzeile', + 'Order confirmation - after the order summary' => 'Bestellbestätigung - nach den Bestellungszusammenfassungen', + 'Order confirmation sent to the customer' => 'Bestellbestätigung den Kunden gesendet', + 'Order details - CSS stylesheet' => 'Bestellungsdetails - CSS-Stylesheet', + 'Order details - additional delivery information' => 'Bestellungsdetails - weitere Informationen für den Versand', + 'Order details - additional information' => 'Bestellungsdetails - weitere Informationen', + 'Order details - additional invoice information' => 'Bestellungsdetails - weitere Informationen für die Rechnung', + 'Order details - additional product information' => 'Bestellungsdetails - weitere Informationen für ein Produkt', + 'Order details - after addresses' => 'Bestellungsdetails - Nach den Adressen', + 'Order details - after global information' => 'Bestellungsdetails - nach den allgemeinen Informationen', + 'Order details - after javascript include' => 'Bestellungsdetails - nach Integration von JavaScript', + 'Order details - after product' => 'Bestelldaten - nach einem Produkt', + 'Order details - after products' => 'Bestellungsdetails - nach den Produkten', + 'Order details - after products list' => 'Bestellungsdetails - nach der Produktliste', + 'Order details - at the bottom' => 'Bestellungsdetails - unten', + 'Order details - at the top' => 'Bestellungsdetails - oben', + 'Order details - before products list' => 'Bestellungsdetails - vor der Produktliste', + 'Order details - delivery address' => 'Bestellungsdetails - Lieferadresse', + 'Order details - invoice address' => 'Bestellungsdetails - Rechnungsadresse', + 'Order details - javascript initialization' => 'Bestellungsdetails - Initialisierung von Javascript', + 'Order edit - bottom' => 'Bestellung Bearbeitung - unten', + 'Order edit - delivery address' => 'Bestellungs-Änderung - Lieferadresse', + 'Order edit - displayed after product information' => 'Bestellungs Bearbeitung - unter die Produktdaten', + 'Order edit - order product table header' => 'Bestellung bearbeiten - Produkttabelle Header', + 'Order edit - order product table row' => 'Bestellung bearbeiten - Produkttabelle Zeile', + 'Order edit - top' => 'Bestellung Bearbeitung - oben', + 'Order failed - CSS stylesheet' => 'Fehlschlag der Bestellung - CSS-Stylesheet', + 'Order failed - after javascript include' => 'Fehlschlag der Bestellung - Nach Integration von JavaScript', + 'Order failed - after javascript initialisation' => 'Fehlschlag der Bestellung - nach der Initialisierung von Javascript', + 'Order failed - at the bottom' => 'Fehlschlag der Bestellung - unten', + 'Order failed - at the top' => 'Fehlschlag der Bestellung - oben', + 'Orders - JavaScript' => 'Bestellungen - JavaScript', + 'Orders - at the top' => 'Bestellungen - oben', + 'Orders - bottom' => 'Bestellungen - unten', + 'Orders - table header' => 'Bestellungen - Tabellenkopf', + 'Orders - table row' => 'Bestellungen - Tabellenzeile', + 'Page 404 - CSS stylesheet' => 'Seite nicht gefunden - CSS-Stylesheet', + 'Page 404 - after javascript include' => 'Seite nicht gefunden - Nach Integration von JavaScript', + 'Page 404 - after javascript initialisation' => 'Seite nicht gefunden - nach der Initialisierung von Javascript', + 'Page 404 - content area' => 'Seite nicht gefunden - Inhalts-Bereich', + 'Paid' => 'Bezahlt', + 'Pakistan' => 'Pakistan', + 'Panama' => 'Panama', + 'Papua Nueva Guinea' => 'Papua-Neuguinea', + 'Paraguay' => 'Paraguay', + 'Path to the directory where documents are stored' => 'Pfad zu dem Verzeichnis, in dem Dokumente gespeichert sind', + 'Path to the directory where images are stored' => 'Pfad zu dem Verzeichnis, in dem Bilder gespeichert sind', + 'Pay by cheque' => 'Per Cheque bezahlen', + 'Payment failed - CSS stylesheet' => 'Bezahlungs-Fehlschlagen - CSS-Stylesheet', + 'Payment failed - after javascript include' => 'Bezahlungs-Fehlschlagen - Nach Integration von JavaScript', + 'Payment failed - javascript initialization' => 'Bezahlungs-Fehlschlagen - Initialisierung von Javascript', + 'Payment gateway - CSS stylesheet' => 'Zahlung-Gateway - CSS-Stylesheet', + 'Payment gateway - after javascript include' => 'Zahlung-Gateway - Nach Integration von JavaScript', + 'Payment gateway - after javascript initialisation' => 'Zahlung-Gateway - nach der Initialisierung von Javascript', + 'Payment gateway - javascript' => 'Zahlung-Gateway - Javascript', + 'Payment gateway - main area' => 'Zahlung-Gateway - Hauptbereich', + 'Peru' => 'Peru', + 'Philippines' => 'Philippinen', + 'Placed order - CSS stylesheet' => 'Erteilten Auftrag - CSS-Stylesheet', + 'Placed order - after javascript include' => 'Erteilten Auftrag - nach Integration von JavaScript', + 'Placed order - after javascript initialisation' => 'Erteilten Auftrag - nach der Initialisierung von Javascript', + 'Placed order - main area' => 'Erteilten Auftrag - Hauptbereich', + 'Poland' => 'Polen', + 'Polynésie française' => 'Französisch-Polynesien', + 'Portugal' => 'Portugal', + 'Processing' => 'Bearbeitung', + 'Product' => 'Produkt', + 'Product - Edit JavaScript' => 'Produkt - JavaScript Änderung', + 'Product - Tab' => 'Produkt - Tab', + 'Product - accessories table header' => 'Produkt - Zubehör Tabellenkopf', + 'Product - accessories table row' => 'Produkt - Zubehör Tabellenzeile', + 'Product - after combinations' => 'Produkt - nach den Kombinationen', + 'Product - at the bottom of a product combination' => 'Produkt - unten einer Produkt-Kombination', + 'Product - attributes table header' => 'Produkt - Deklination Tabellenkopf', + 'Product - attributes table row' => 'Produkt - Deklination Tabellenzeile', + 'Product - before combinations' => 'Produkt - vor den Kombinationen', + 'Product - categories table header' => 'Produkt - Kategorien Tabellenkopf', + 'Product - categories table row' => 'Produkt - Kategorien Tabellenzeile', + 'Product - combination delete form' => 'Produkt - Kombinations-Löschungsformular', + 'Product - combinations list caption' => 'Produkt - Kombinationsliste-Bildunterschrift', + 'Product - content' => 'Produkt - Inhalt', + 'Product - contents table header' => 'Produkt - Inhalte Tabellenkopf', + 'Product - contents table row' => 'Produkt - Inhalte Tabellenzeile', + 'Product - create form' => 'Produkt - Erstellungsformular', + 'Product - delete form' => 'Produkt - Löschungsformular', + 'Product - details pricing form' => 'Produkt - Preisedetails Formular', + 'Product - details promotion form' => 'Produkt - Sonderangebotdetails Formular', + 'Product - features table row' => 'Produkt - Charakteristiken Tabellenzeile', + 'Product - features-table-header' => 'Produkt - Charakteristiken Tabellenkopf', + 'Product - folders table header' => 'Produkt - Ordner Tabellenkopf', + 'Product - folders table row' => 'Produkt - Ordner Tabellenzeile', + 'Product - stock edit form' => 'Produkt - Bestandänderung Formular', + 'Product edit - bottom' => 'Produkt Bearbeitung - unten', + 'Product edit - top' => 'Produkt Bearbeitung - oben', + 'Product loop - at the bottom' => 'Produkt-Loop - unten', + 'Product loop - at the top' => 'Produkt-Loop - oben', + 'Product page - CSS stylesheet' => 'Produktseite - CSS-Stylesheet', + 'Product page - On the bottom of the form' => 'Produktseite - unten an dem Formular', + 'Product page - On the top of the form' => 'Produktseite - oben im Formular', + 'Product page - additional information' => 'Produktseite - erweitere Informationen', + 'Product page - after javascript include' => 'Produktseite - Nach Integration von JavaScript', + 'Product page - after javascript initialisation' => 'Produktseite - nach der Initialisierung von Javascript', + 'Product page - at the bottom' => 'Produktseite - unten', + 'Product page - at the bottom of the detail area' => 'Produktseite - unten dem Details-Bereich', + 'Product page - at the top' => 'Produktseite - oben', + 'Product page - at the top of the detail' => 'Produktseite - oben dem Details-Bereich', + 'Product page - photo gallery' => 'Produktseite - Bilder-Gallerie', + 'Products - caption' => 'Produkte - Bildunterschrift', + 'Products - header' => 'Produkte - Header', + 'Products - row' => 'Produkte - Zeile', + 'Products offer block' => 'Sonderangebot-Block', + 'Profile - Edit JavaScript' => 'Profil - JavaScript Änderung', + 'Profile - create form' => 'Profil - Erstellungsformular', + 'Profile - delete form' => 'Profil - Löschungsformular', + 'Profile - table header' => 'Profil - Tabellenkopf', + 'Profile - table row' => 'Profil - Tabellenzeile', + 'Profile edit - bottom' => 'Profil Bearbeitung - unten', + 'Profile edit - top' => 'Profil Bearbeitung - oben', + 'Profiles - JavaScript' => 'Profile - JavaScript', + 'Profiles - at the top' => 'Profile - oben', + 'Profiles - bottom' => 'Profile - unten', + 'Qatar' => 'Katar', + 'Refunded' => 'Zrückerstattet', + 'Register - CSS stylesheet' => 'Konto-Erstellung - CSS-Stylesheet', + 'Register - after javascript include' => 'Konto-Erstellung - Nach Integration von JavaScript', + 'Register - after javascript initialisation' => 'Konto-Erstellung - nach der Initialisierung von Javascript', + 'Register - at the bottom' => 'Konto-Erstellung - unten', + 'Register - at the bottom of the form' => 'Konto-Erstellung - unten an dem Formular', + 'Register - at the top' => 'Konto-Erstellung - oben', + 'Register - at the top of the form' => 'Konto-Erstellung - oben im Formular', + 'Romania' => 'Rumänien', + 'Russia' => 'Russland', + 'Rwanda' => 'Ruanda', + 'Réunion(La)' => 'La Réunion', + 'Saint Barthélemy' => 'Saint-Barthélemy', + 'Saint Kitts and Nevis' => 'St. Kitts und Nevis', + 'Saint Lucia' => 'St. Lucia', + 'Saint Martin (French part)' => 'Saint-Martin (franz. Teil)', + 'Saint Vincent and the Grenadines' => 'St. Vincent und die Grenadinen', + 'Sale - create form' => 'Sonderangebot - Erstellungsformular', + 'Sale - delete form' => 'Sonderangebot - Löschungsformular', + 'Sale edit - bottom' => 'Sonderangebot Bearbeitung - unten', + 'Sale edit - top' => 'Sonderangebot Bearbeitung - oben', + 'Sale edit page - javascript last call block' => 'Sonderangebot Änderungsseite - javascript last call block', + 'Sales - JavaScript' => 'Sonderangebote - JavaScript', + 'Sales - at the bottom' => 'Sonderangebote - unten', + 'Sales - at the top' => 'Sonderangebote - oben', + 'Sales - table header' => 'Sonderangebote - Tabellenkopf', + 'Sales - table row' => 'Sonderangebote - Tabellenzeile', + 'Sales management' => 'Sonderangebotsmanagement', + 'San Marino' => 'Saint-Marin', + 'Sao Tome and Principe' => 'São Tomé und Príncipe', + 'Saudi Arabia' => 'Saudi-Arabien', + 'Search' => 'Suchen', + 'Search - JavaScript' => 'Suche - JavaScript', + 'Search - at the top' => 'Suche - oben', + 'Search - bottom' => 'Suche - unten', + 'Search block' => 'Suche-Block', + 'Search page - CSS stylesheet' => 'Suche-Seite - CSS-Stylesheet', + 'Search page - after javascript include' => 'Suche-Seite - Nach Integration von JavaScript', + 'Search page - after javascript initialisation' => 'Suche-Seite - nach der Initialisierung von Javascript', + 'Secret key for form CSRF token' => 'Geheimer Schlüssel für Formular CSRF-token', + 'Senegal' => 'Senegal', + 'Sent' => 'Gesendet', + 'Seychelles' => 'Seychellen', + 'Shipping configuration' => 'Lieferungskonfiguration', + 'Shipping configuration - Edit' => 'Versandkonfiguration - Änderung', + 'Shipping configuration - Edit JavaScript' => 'Versandkonfiguration - JavaScript Änderung', + 'Shipping configuration - JavaScript' => 'Versandkonfiguration - JavaScript', + 'Shipping configuration - at the top' => 'Versandkonfiguration - oben', + 'Shipping configuration - bottom' => 'Versandkonfiguration - unten', + 'Shipping configuration - country delete form' => 'Versandkonfiguration - Länder Löschungsfomular', + 'Shipping configuration - create form' => 'Versandkonfiguration - Erstellungsformular', + 'Shipping configuration - delete form' => 'Versandkonfiguration - Löschungsformular', + 'Shipping configuration - table header' => 'Versandkonfiguration - Tabellenkopf', + 'Shipping configuration - table row' => 'Versandkonfiguration - Tabellenzeile', + 'Shipping configuration edit - bottom' => 'Lieferzone Bearbeitung - unten', + 'Shipping configuration edit - top' => 'Lieferzone Bearbeitung - oben', + 'Shipping zones edit - bottom' => 'Transporteur Lieferzonen Bearbeitung - unten', + 'Shipping zones edit - top' => 'Transporteur Lieferzonen Bearbeitung - oben', + 'Show error message instead of a white page on a server error' => 'Fehlermeldung zeigen anstatt einer weißen Seite im Falle eines eines Serverfehlers', + 'Sierra Leone' => 'Sierra Leone', + 'Singapore' => 'Singapur', + 'Sitemap - at the bottom' => 'Sitemap - unten', + 'Slovakia' => 'Slowakei', + 'Slovenia' => 'Slowenien', + 'Smarty template engine integration' => 'Smarty Template Engine Integration', + 'Social Networks block' => 'Social Networks Block', + 'Solomon Islands' => 'Salomon-Inseln', + 'Somalia' => 'Somalia', + 'South Africa' => 'Südafrika', + 'South Korea' => 'Südkorea', + 'Spain' => 'Spanien', + 'Sri Lanka' => 'Sri Lanka', + 'St Pierre et Miquelon' => 'Saint-Pierre und Miquelon', + 'Store Information - JavaScript' => 'Shop Informationen - JavaScript', + 'Store information configuration' => 'Shop Informationen', + 'Sudan' => 'Sudan', + 'Suriname' => 'Suriname', + 'Swaziland' => 'Swaziland', + 'Sweden' => 'Schweden', + 'Switzerland' => 'Schweiz', + 'Syria' => 'Syrien', + 'System - logs JavaScript' => 'System - JavaScript Logs', + 'Tab SEO - bottom' => 'SEO Tab - unten', + 'Tab SEO - top' => 'SEO Tab - oben', + 'Tab SEO - update form' => 'Registerkarte SEO - Update-Formular', + 'Tab document - bottom' => 'Dokument Tab - unten', + 'Tab document - top' => 'Dokument Tab - oben', + 'Tab image - bottom' => 'Bild Tab - unten', + 'Tab image - top' => 'Bild Tab - oben', + 'Tajikistan' => 'Tadschikistan', + 'Tanzania' => 'Tansania', + 'Tax - Edit JavaScript' => 'Taxe - JavaScript Änderung', + 'Tax - create form' => 'Taxe - Erstellungsformular', + 'Tax - delete form' => 'Taxe - Löschungsformular', + 'Tax edit - bottom' => 'Taxe Bearbeitung - unten', + 'Tax edit - top' => 'Taxe Bearbeitung - oben', + 'Tax rule edit - bottom' => 'Taxregel Bearbeitung - unten', + 'Tax rule edit - top' => 'Taxregel Bearbeitung - oben', + 'Tax rules configuration' => 'Taxeregelung-Konfiguration', + 'Taxes - update form' => 'Taxes - Änderungs-Formular', + 'Taxes rules - JavaScript' => 'Taxeregeln - JavaScript', + 'Taxes rules - at the top' => 'Taxeregeln - oben', + 'Taxes rules - bottom' => 'Taxeregeln - unten', + 'Template - Edit JavaScript' => 'Template - JavaScript Änderung', + 'Template - attributes table header' => 'Template - Tabellenkopf attributs', + 'Template - attributes table row' => 'Template - Tabellenzeile attributs', + 'Template - create form' => 'Template - Erstellungsformular', + 'Template - delete form' => 'Template - Löschungsformular', + 'Template - features table row' => 'Template - Charakteristiken Tabellenzeile', + 'Template - features-table-header' => 'Template - Charakteristiken Tabellenkopf', + 'Template edit - bottom' => 'Template Bearbeitung - unten', + 'Template edit - top' => 'Template Bearbeitung - oben', + 'Templates - JavaScript' => 'Templates - JavaScript', + 'Templates - at the top' => 'Templates - oben', + 'Templates - bottom' => 'Templates - unten', + 'Templates - table header' => 'Templates - Tabellenkopf', + 'Templates - table row' => 'Templates - Tabellenzeile', + 'Thailand' => 'Thailand', + 'The ID of the \'Terms & Conditions\' content.' => 'Ihr \'Allgemeine Geschäftsbedingungen \' ID.', + 'The ID of the folder containing your information pages : terms, imprint, ...' => 'Die ID des Ordners mit Ihren Informations-Seiten: AGB, Impressum, ...', + 'The Vatican' => 'der Vatikan', + 'The default quality (in %) of the generated images' => 'Die Standardqualität (in%) der erzeugten Bilder', + 'The path (relative to the default back-office template) to the image used when no flag image can be found for a country' => 'Der Pfad (relativ zu der Standard-Backoffice-Vorlage) zu dem verwendetes Bild wenn kein Flagge-Bild für ein Land gefunden werden kann', + 'The path to the document cache directory in the web space' => 'Der Pfad zum Dokument-Cache-Verzeichnis in dem Web-Space', + 'The path to the image cache directory in the web space' => 'Der Pfad zum Bild-Cache-Verzeichnis in dem Web-Space', + 'TinyMCE WYSIWYG editor' => 'TinyMCE WYSIWYG Editor', + 'Togo' => 'Togo', + 'Tonga' => 'Tonga', + 'Tools - JavaScript' => 'Tools - JavaScript', + 'Tools - at the bottom of column 1' => 'Tools - unten der Spalte 1', + 'Tools - at the top' => 'Tools - oben', + 'Tools - at the top of the column' => 'Tools - oben der Spalte', + 'Tools - bottom' => 'Tools - unten', + 'Tools panel' => 'Tools', + 'Translations' => 'Übersetzungen', + 'Translations - JavaScript' => 'Übersetzungen - JavaScript', + 'Trinidad and Tobago' => 'Trinidad und Tobago', + 'Tunisia' => 'Tunesien', + 'Turkey' => 'Türkei', + 'Turkmenistan' => 'Turkménistan', + 'Tuvalu' => 'Tuvalu', + 'UK Pound' => 'Britische Pfund', + 'Uganda' => 'Uganda', + 'Ukraine' => 'Ukraine', + 'United Arab Emirates' => 'Vereinigte Arabische Emirate', + 'United Kingdom' => 'Vereinigtes Königreich', + 'United States Dollar' => 'US Dollar', + 'Update customer account - CSS stylesheet' => 'Kundenkonto Änderung - CSS-Stylesheet', + 'Update customer account - after javascript include' => 'Kundenkonto Änderung - Nach Integration von JavaScript', + 'Update customer account - after javascript initialisation' => 'Kundenkonto Änderung - nach der Initialisierung von Javascript', + 'Update customer account - at the bottom' => 'Kundenkonto Änderung - unten', + 'Update customer account - at the bottom of the form' => 'Kundenkonto Änderung - unten an dem Formular', + 'Update customer account - at the top' => 'Kundenkonto Änderung - oben', + 'Update customer account - at the top of the form' => 'Kundenkonto Änderung - oben im Formular', + 'Uruguay' => 'Uruguay', + 'Use a persistent cookie to keep track of customer cart' => 'Ein dauerhaftes Cookie verwenden, um den Kundes-Warenkorb zu merken', + 'Uzbekistan' => 'Usbekistan', + 'Vanuatu' => 'Vanuatu', + 'Variable - Edit JavaScript' => 'Variable - JavaScript Änderung', + 'Variable - create form' => 'Variable - Erstellungsformular', + 'Variable - delete form' => 'Variable - Löschungsformular', + 'Variable edit - bottom' => 'Variable Bearbeitung - unten', + 'Variable edit - top' => 'Variable Bearbeitung - oben', + 'Variables - JavaScript' => 'Variablen - JavaScript', + 'Variables - at the top' => 'Variablen - oben', + 'Variables - bottom' => 'Variablen - unten', + 'Variables - table header' => 'Variablen - Tabellenkopf', + 'Variables - table row' => 'Variablen - Tabellenzeile', + 'Venezuela' => 'Venezuela', + 'Vietnam' => 'Vietnam', + 'View administration logs' => 'Administration Logs ansehen', + 'Virtual Product Controller' => 'Steuerung für virtuelle Produkte', + 'Wallis-et-Futuna' => 'Wallis und Futuna', + 'Western Samoa' => 'West-Samoa', + 'Where the WYSIWYG editor is required' => 'Überall wo WYSIWYG editor ist nötig', + 'Whitespace trim level of the generated HTML code (0 = none, 1 = medium, 2 = maximum)' => 'Whitespace trim Ebene des generierten HTML-Codes (0 = aus, 1 = Mittel, 2 = Maximum)', + 'Yemen' => 'Jemen', + 'You can now login at' => 'Sie können Ihnen anmelden bei', + 'You have lost your password
    \r\nPlease, change this password after your first connection' => 'Sie haben Ihr Passwort vergessen br />\r\nBitte ändern Sie das Passwort nach Ihre erste Anmeldung', + 'You have lost your password
    \r\nYour new password is' => 'Sie haben Ihr Passwort vergessen
    \r\nIhr neues Passwort ist ', + 'Your account information on {config key="store_name"} has been changed.' => 'Ihre Konto-Zugriff für {config key="store_name"} wurde geändert', + 'Your new passord is : {$password}' => 'Ihr neues Passwort ist : {$password}', + 'Your new password' => 'Ihr neues Passwort', + 'Your new password for {config key="store_name"}' => 'Ihr neues Passwort für {config key="store_name"}', + 'Your order {$order_ref} at {config key="store_name"}' => 'Ihre Bestellung {$order_ref} bei {config key="store_name"}', + 'Zaire' => 'Zaire', + 'Zambia' => 'Sambia', + 'Zimbabwe' => 'Zimbabwe', + 'Zone - delete form' => 'Zone - Löschungsformular', + '[Firewall/Bruteforce] Number of allowed attemps' => '[Firewall/Bruteforce] Anzahl der erlaubten Versuche', + '[Firewall/Bruteforce] Time to wait between X attempts' => '[Firewall/Bruteforce] Wartezeit zwischen X Versuche', + '[Firewall] Activate the firewall' => '[Firewall] Firewall aktivieren', + '[Firewall] Number of allowed attemps' => '[Firewall] Anzahl der erlaubten Versuche', + '[Firewall] Time to wait between X attempts' => '[Firewall] Wartezeit zwischen X Versuche', + 'changing password email for' => 'Passwort Änderung für', + 'customer account - CSS stylesheet' => 'Kundenkonto - CSS-Stylesheet', + 'customer account - after javascript include' => 'Kundenkonto - Nach Integration von JavaScript', + 'customer account - after javascript initialisation' => 'Kundenkonto - nach der Initialisierung von Javascript', + 'customer account - at the bottom' => 'Kundenkonto - unten', + 'customer account - at the top' => 'Kundenkonto - oben', + 'export of newsletter subscribers' => 'Export für die Newsletter Angemeldeten', + 'language selection page - CSS stylesheet' => 'Sprachwahl Seite - CSS-Stylesheet', + 'language selection page - after javascript include' => 'Sprachwahl Seite - Nach Integration von JavaScript', + 'language selection page - after javascript initialisation' => 'Sprachwahl Seite - nach der Initialisierung von Javascript', + 'language selection page - at the bottom' => 'Sprachwahl Seite - unten', + 'language selection page - at the top' => 'Sprachwahl Seite - oben', + 'tax rule - Edit JavaScript' => 'Taxregel - JavaScript Änderung', + 'tax rule - create form' => 'Taxregel - Erstellungsformular', + 'tax rule - delete form' => 'Taxregel - Löschungsformular', + 'tinymce wysiwyg editor' => 'Tinymce Wysiwyg Editor', + 'Default Tax Rule' => 'Standardsteuerregel', + 'French 10% VAT (France only)' => '10% französische Mehrwertsteuer (nur Metropolitan France)', + 'French 20% VAT for all European countries (metropolitan only)' => 'Französische Mehrwertsteuer von 20% für alle Länder in Europa (nur Metropolregion)', + 'French 10% VAT (for metropolitan France only)' => 'Französische Mehrwertsteuer von 10% nur für die französische Metropole', +]; diff --git a/setup/I18n/el_GR.php b/setup/I18n/el_GR.php new file mode 100644 index 00000000..f766ef2a --- /dev/null +++ b/setup/I18n/el_GR.php @@ -0,0 +1,7 @@ + 'Διεύθυνση', + 'New York' => 'Νέα Υόρκη', + 'Search' => 'Αναζήτηση', +]; diff --git a/setup/I18n/en_US.php b/setup/I18n/en_US.php new file mode 100644 index 00000000..51110933 --- /dev/null +++ b/setup/I18n/en_US.php @@ -0,0 +1,1476 @@ + '"Remember me" cookie expiration time, in seconds, for administration users', + '"Remember me" cookie expiration time, in seconds, for customer users' => '"Remember me" cookie expiration time, in seconds, for customer users', + '"Remember me" cookie name for administration users' => '"Remember me" cookie name for administration users', + '"Remember me" cookie name for customer users' => '"Remember me" cookie name for customer users', + '72h delivery' => '72h delivery', + 'A {config key="store_name"} account has been created for you' => 'A {config key="store_name"} account has been created for you', + 'API Configuration' => 'API Configuration', + 'Account order - after product information' => 'Account order - after product information', + 'Aceh' => 'Aceh', + 'Address' => 'Address', + 'Address creation - CSS stylesheet' => 'Address creation - CSS stylesheet', + 'Address creation - after javascript include' => 'Address creation - after javascript include', + 'Address creation - after javascript initialisation' => 'Address creation - after javascript initialisation', + 'Address creation - at the bottom' => 'Address creation - at the bottom', + 'Address creation - at the bottom of the form' => 'Address creation - at the bottom of the form', + 'Address creation - at the top' => 'Address creation - at the top', + 'Address creation - at the top of the form' => 'Address creation - at the top of the form', + 'Address update - CSS stylesheet' => 'Address update - CSS stylesheet', + 'Address update - after javascript include' => 'Address update - after javascript include', + 'Address update - after javascript initialisation' => 'Address update - after javascript initialisation', + 'Address update - at the bottom' => 'Address update - at the bottom', + 'Address update - at the bottom of the form' => 'Address update - at the bottom of the form', + 'Address update - at the top' => 'Address update - at the top', + 'Address update - at the top of the form' => 'Address update - at the top of the form', + 'Admin layout - After the main content' => 'Admin layout - After the main content', + 'Administatros list' => 'Administatros list', + 'Administration profiles management' => 'Administration profiles management', + 'Administrator - create form' => 'Administrator - create form', + 'Administrator - delete form' => 'Administrator - delete form', + 'Administrator - update form' => 'Administrator - update form', + 'Administrator list' => 'Administrator list', + 'Administrators - JavaScript' => 'Administrators - JavaScript', + 'Administrators - at the top' => 'Administrators - at the top', + 'Administrators - bottom' => 'Administrators - bottom', + 'Administrators - header' => 'Administrators - header', + 'Administrators - row' => 'Administrators - row', + 'Advanced Configuration' => 'Advanced Configuration', + 'Advanced Configuration - Javascript' => 'Advanced Configuration - Javascript', + 'Advanced configuration' => 'Advanced configuration', + 'Afghanistan' => 'Afghanistan', + 'Agrigento' => 'Agrigento', + 'Aguascalientes' => 'Aguascalientes', + 'Aichi' => 'Aichi', + 'Akita' => 'Akita', + 'Alabama' => 'Alabama', + 'Alaska' => 'Alaska', + 'Albania' => 'Albania', + 'Alberta' => 'Alberta', + 'Alessandria' => 'Alessandria', + 'Algeria' => 'Algeria', + 'All Products - CSS stylesheet' => 'All Products - CSS stylesheet', + 'All Products - after javascript include' => 'All Products - after javascript include', + 'All Products - after javascript initialisation' => 'All Products - after javascript initialisation', + 'All Products - at the bottom' => 'All Products - at the bottom', + 'All Products - at the top' => 'All Products - at the top', + 'Allow an administrator to recreate a lost password (1 = yes, 0 = no)' => 'Allow an administrator to recreate a lost password (1 = yes, 0 = no)', + 'Allow customers to change their email. 1 for yes, 0 for no' => 'Allow customers to change their email. 1 for yes, 0 for no', + 'Allow negative product stock (1) or not (0)' => 'Allow negative product stock (1) or not (0)', + 'Allow negative product stock (1) or not (0, default)' => 'Allow negative product stock (1) or not (0, default)', + 'Allow slash ended uri' => 'Allow slash ended uri', + 'Allow module installation from ZIP files.' => 'Allow module installation from ZIP files.' , + 'An image carousel on your home page' => 'An image carousel on your home page', + 'Ancona' => 'Ancona', + 'Andorra' => 'Andorra', + 'Angola' => 'Angola', + 'Antigua and Barbuda' => 'Antigua and Barbuda', + 'Aomori' => 'Aomori', + 'Aosta' => 'Aosta', + 'Api page - at bottom' => 'Api page - at bottom', + 'Api page - at top' => 'Api page - at top', + 'Api page - in deletion form' => 'Api page - in deletion form', + 'Arezzo' => 'Arezzo', + 'Argentina' => 'Argentina', + 'Arizona' => 'Arizona', + 'Arkansas' => 'Arkansas', + 'Armenia' => 'Armenia', + 'Ascoli Piceno' => 'Ascoli Piceno', + 'Ask the customers to confirm their email in customer creation form, 1 for yes, 0 for no' => 'Ask the customers to confirm their email in customer creation form (1: yes, 0: no)', + 'Asti' => 'Asti', + 'Attribut - Edit JavaScript' => 'Attribut - Edit JavaScript', + 'Attribut - add to all form' => 'Attribut - add to all form', + 'Attribut - create form' => 'Attribut - create form', + 'Attribut - delete form' => 'Attribut - delete form', + 'Attribut - id delete form' => 'Attribut - id delete form', + 'Attribut - remove to all form' => 'Attribut - remove to all form', + 'Attribute edit - bottom' => 'Attribute edit - bottom', + 'Attribute edit - top' => 'Attribute edit - top', + 'Attribute value - create form' => 'Attribute value - create form', + 'Attributes - JavaScript' => 'Attributes - JavaScript', + 'Attributes - at the top' => 'Attributes - at the top', + 'Attributes - bottom' => 'Attributes - bottom', + 'Attributes - table header' => 'Attributes - table header', + 'Attributes - table row' => 'Attributes - table row', + 'Attributes value - table header' => 'Attributes value - table header', + 'Attributes value - table row' => 'Attributes value - table row', + 'Australia' => 'Australia', + 'Austria' => 'Austria', + 'Avellino' => 'Avellino', + 'Azerbaijan' => 'Azerbaijan', + 'Back-office Home page content' => 'Back-office Home page content', + 'Back-office export management' => 'Back-office export management', + 'Back-office home page' => 'Back-office home page', + 'Back-office search function' => 'Back-office search function', + 'Bahamas' => 'Bahamas', + 'Bahrain' => 'Bahrain', + 'Baht' => 'Baht', + 'Baja California' => 'Baja California', + 'Baja California Sur' => 'Baja California Sur', + 'Bali' => 'Bali', + 'Bangka' => 'Bangka', + 'Bangladesh' => 'Bangladesh', + 'Banten' => 'Banten', + 'Barbados' => 'Barbados', + 'Bari' => 'Bari', + 'Barletta-Andria-Trani' => 'Barletta-Andria-Trani', + 'Base URL of the shop (e.g. http://www.yourshopdomain.com)' => 'Base URL of the shop (e.g. http://www.yourshopdomain.com)', + 'Belarus' => 'Belarus', + 'Belarusian ruble' => 'Belarusian ruble', + 'Belgium' => 'Belgium', + 'Belize' => 'Belize', + 'Belluno' => 'Belluno', + 'Benevento' => 'Benevento', + 'Bengkulu' => 'Bengkulu', + 'Benin' => 'Benin', + 'Bergamo' => 'Bergamo', + 'Bhutan' => 'Bhutan', + 'Biella' => 'Biella', + 'Bielorussia' => 'Bielorussia', + 'Bolivia' => 'Bolivia', + 'Boliviano' => 'Boliviano', + 'Bologna' => 'Bologna', + 'Bolzano' => 'Bolzano', + 'Bolívar fuerte' => 'Bolívar fuerte', + 'Bosnia and Herzegovina' => 'Bosnia and Herzegovina', + 'Botswana' => 'Botswana', + 'Brand - Edit JavaScript' => 'Brand - Edit JavaScript', + 'Brand - JavaScript' => 'Brand - JavaScript', + 'Brand - Tab' => 'Brand - Tab', + 'Brand - content' => 'Brand - content', + 'Brand - create form' => 'Brand - create form', + 'Brand - delete form' => 'Brand - delete form', + 'Brand edit - bottom' => 'Brand edit - bottom', + 'Brand edit - right column bottom' => 'Brand edit - right column bottom', + 'Brand edit - right column top' => 'Brand edit - right column top', + 'Brand edit - top' => 'Brand edit - top', + 'Brand edit page - in the form' => 'Brand edit page - in the form', + 'Brands - at the top' => 'Brands - at the top', + 'Brands - bottom' => 'Brands - bottom', + 'Brands - table header' => 'Brands - table header', + 'Brands - table row' => 'Brands - table row', + 'Brands management' => 'Brands management', + 'Brands page - CSS stylesheet' => 'Brands page - CSS stylesheet', + 'Brands page - after javascript include' => 'Brands page - after javascript include', + 'Brands page - after the main content area' => 'Brands page - after the main content area', + 'Brands page - at the bottom' => 'Brands page - at the bottom', + 'Brands page - at the bottom of the main area' => 'Brands page - at the bottom of the main area', + 'Brands page - at the bottom of the sidebar' => 'Brands page - at the bottom of the sidebar', + 'Brands page - at the top' => 'Brands page - at the top', + 'Brands page - at the top of the main area' => 'Brands page - at the top of the main area', + 'Brands page - at the top of the sidebar' => 'Brands page - at the top of the sidebar', + 'Brands page - before the main content area' => 'Brands page - before the main content area', + 'Brands page - javascript initialization' => 'Brands page - javascript initialization', + 'Brands page - the body of the sidebar' => 'Brands page - the body of the sidebar', + 'Brazil' => 'Brazil', + 'Brescia' => 'Brescia', + 'Brindisi' => 'Brindisi', + 'British Columbia' => 'British Columbia', + 'Brunei' => 'Brunei', + 'Buenos Aires' => 'Buenos Aires', + 'Bulgaria' => 'Bulgaria', + 'Burkina' => 'Burkina', + 'Burma' => 'Burma', + 'Burundi' => 'Burundi', + 'Cagliari' => 'Cagliari', + 'California' => 'California', + 'Caltanissetta' => 'Caltanissetta', + 'Cambodia' => 'Cambodia', + 'Cameroon' => 'Cameroon', + 'Campeche' => 'Campeche', + 'Campobasso' => 'Campobasso', + 'Canada' => 'Canada', + 'Canceled' => 'Canceled', + 'Cape Verde' => 'Cape Verde', + 'Carbonia-Iglesias' => 'Carbonia-Iglesias', + 'Cart - CSS stylesheet' => 'Cart - CSS stylesheet', + 'Cart - after javascript include' => 'Cart - after javascript include', + 'Cart - at the bottom' => 'Cart - at the bottom', + 'Cart - at the top' => 'Cart - at the top', + 'Cart - javascript initialization' => 'Cart - javascript initialization', + 'Cart block' => 'Cart block', + 'Caserta' => 'Caserta', + 'Catamarca' => 'Catamarca', + 'Catania' => 'Catania', + 'Catanzaro' => 'Catanzaro', + 'Categories - JavaScript' => 'Categories - JavaScript', + 'Categories - at the bottom of the catalog' => 'Categories - at the bottom of the catalog', + 'Categories - at the top' => 'Categories - at the top', + 'Categories - bottom' => 'Categories - bottom', + 'Categories - caption' => 'Categories - caption', + 'Categories - header' => 'Categories - header', + 'Categories - row' => 'Categories - row', + 'Category' => 'Category', + 'Category - Edit JavaScript' => 'Category - Edit JavaScript', + 'Category - Tab' => 'Category - Tab', + 'Category - content' => 'Category - content', + 'Category - contents table header' => 'Category - contents table header', + 'Category - contents table row' => 'Category - contents table row', + 'Category - create form' => 'Category - create form', + 'Category - delete form' => 'Category - delete form', + 'Category configuration' => 'Category configuration', + 'Category edit - bottom' => 'Category edit - bottom', + 'Category edit - right column bottom' => 'Category edit - right column bottom', + 'Category edit - right column top' => 'Category edit - right column top', + 'Category edit - top' => 'Category edit - top', + 'Category page - CSS stylesheet' => 'Category page - CSS stylesheet', + 'Category page - after javascript include' => 'Category page - after javascript include', + 'Category page - after javascript initialisation' => 'Category page - after javascript initialisation', + 'Category page - after the main content area' => 'Category page - after the main content area', + 'Category page - at the bottom' => 'Category page - at the bottom', + 'Category page - at the bottom of the main area' => 'Category page - at the bottom of the main area', + 'Category page - at the bottom of the sidebar' => 'Category page - at the bottom of the sidebar', + 'Category page - at the top' => 'Category page - at the top', + 'Category page - at the top of the main area' => 'Category page - at the top of the main area', + 'Category page - at the top of the sidebar' => 'Category page - at the top of the sidebar', + 'Category page - before the main content area' => 'Category page - before the main content area', + 'Category page - the body of the sidebar' => 'Category page - the body of the sidebar', + 'Central African Republic' => 'Central African Republic', + 'Central Java' => 'Central Java', + 'Central Kalimantan' => 'Central Kalimantan', + 'Central Sulawesi' => 'Central Sulawesi', + 'Chaco' => 'Chaco', + 'Chad' => 'Chad', + 'Change password - CSS stylesheet' => 'Change password - CSS stylesheet', + 'Change password - after javascript include' => 'Change password - after javascript include', + 'Change password - after javascript initialisation' => 'Change password - after javascript initialisation', + 'Change password - at the bottom' => 'Change password - at the bottom', + 'Change password - at the top' => 'Change password - at the top', + 'Check available product stock (1) or ignore it (0) when displaying and changing ordered quantity' => 'Check available product stock (1) or ignore it (0) when displaying and changing ordered quantity', + 'Check if a virtual product delivery module is enabled if at least one product is virtual' => 'Check if a virtual product delivery module is enabled if at least one product is virtual', + 'Chiapas' => 'Chiapas', + 'Chiba' => 'Chiba', + 'Chieti' => 'Chieti', + 'Chihuahua' => 'Chihuahua', + 'Chile' => 'Chile', + 'China' => 'China', + 'Chubut' => 'Chubut', + 'Ciudad de Buenos Aires' => 'Ciudad de Buenos Aires', + 'Client edit - bottom' => 'Client edit - bottom', + 'Client edit - top' => 'Client edit - top', + 'Coahuila' => 'Coahuila', + 'Coat of arms of East Java' => 'Coat of arms of East Java', + 'Colima' => 'Colima', + 'Colombia' => 'Colombia', + 'Colorado' => 'Colorado', + 'Colón' => 'Colón', + 'Como' => 'Como', + 'Comoros' => 'Comoros', + 'Compile templates assets automatically upon asset source change (1 = yes, 0 = no)' => 'Compile templates assets automatically upon asset source change (1 = yes, 0 = no)', + 'Configuration' => 'Configuration', + 'Configuration - JavaScript' => 'Configuration - JavaScript', + 'Configuration - Order path - bottom' => 'Configuration - Order path - bottom', + 'Configuration - Order path - top' => 'Configuration - Order path - top', + 'Configuration - at the bottom of the catalog' => 'Configuration - at the bottom of the catalog', + 'Configuration - at the bottom of the shipping area' => 'Configuration - at the bottom of the shipping area', + 'Configuration - at the bottom of the system area' => 'Configuration - at the bottom of the system area', + 'Configuration - at the top' => 'Configuration - at the top', + 'Configuration - at the top of the catalog area' => 'Configuration - at the top of the catalog area', + 'Configuration - at the top of the shipping area' => 'Configuration - at the top of the shipping area', + 'Configuration - at the top of the system area' => 'Configuration - at the top of the system area', + 'Configuration - bottom' => 'Configuration - bottom', + 'Configuration / Administrator' => 'Configuration / Administrator', + 'Configuration / Area' => 'Configuration / Area', + 'Configuration / Attribute' => 'Configuration / Attribute', + 'Configuration / Cache' => 'Configuration / Cache', + 'Configuration / Country' => 'Configuration / Country', + 'Configuration / Currency' => 'Configuration / Currency', + 'Configuration / Feature' => 'Configuration / Feature', + 'Configuration / Language' => 'Configuration / Language', + 'Configuration / Mailing-system' => 'Configuration / Mailing-system', + 'Configuration / Message' => 'Configuration / Message', + 'Configuration / Module' => 'Configuration / Module', + 'Configuration / Profile' => 'Configuration / Profile', + 'Configuration / Shipping-zone' => 'Configuration / Shipping-zone', + 'Configuration / System Log' => 'Configuration / System Log', + 'Configuration / Tax' => 'Configuration / Tax', + 'Configuration / Template' => 'Configuration / Template', + 'Configuration order status' => 'Configuration order status', + 'Configuration variables' => 'Configuration variables', + 'Confirm your %store account' => 'Confirm your {config key="store_name"} account', + 'Congo' => 'Congo', + 'Connecticut' => 'Connecticut', + 'Contact block' => 'Contact block', + 'Contact page - CSS stylesheet' => 'Contact page - CSS stylesheet', + 'Contact page - after javascript include' => 'Contact page - after javascript include', + 'Contact page - after javascript initialisation' => 'Contact page - after javascript initialisation', + 'Contact page - at the bottom' => 'Contact page - at the bottom', + 'Contact page - at the bottom of the form' => 'Contact page - at the bottom of the form', + 'Contact page - at the top' => 'Contact page - at the top', + 'Contact page - at the top of the form' => 'Contact page - at the top of the form', + 'Contact page - if successful response' => 'Contact page - if successful response', + 'Content' => 'Content', + 'Content - Edit JavaScript' => 'Content - Edit JavaScript', + 'Content - Tab' => 'Content - Tab', + 'Content - content' => 'Content - content', + 'Content - create form' => 'Content - create form', + 'Content - delete form' => 'Content - delete form', + 'Content edit - bottom' => 'Content edit - bottom', + 'Content edit - right column bottom' => 'Content edit - right column bottom', + 'Content edit - right column top' => 'Content edit - right column top', + 'Content edit - top' => 'Content edit - top', + 'Content page - CSS stylesheet' => 'Content page - CSS stylesheet', + 'Content page - after javascript include' => 'Content page - after javascript include', + 'Content page - after javascript initialisation' => 'Content page - after javascript initialisation', + 'Content page - after the main content area' => 'Content page - after the main content area', + 'Content page - at the bottom' => 'Content page - at the bottom', + 'Content page - at the bottom of the main area' => 'Content page - at the bottom of the main area', + 'Content page - at the bottom of the sidebar' => 'Content page - at the bottom of the sidebar', + 'Content page - at the top' => 'Content page - at the top', + 'Content page - at the top of the main area' => 'Content page - at the top of the main area', + 'Content page - at the top of the sidebar' => 'Content page - at the top of the sidebar', + 'Content page - before the main content area' => 'Content page - before the main content area', + 'Content page - the body of the sidebar' => 'Content page - the body of the sidebar', + 'Contents - caption' => 'Contents - caption', + 'Contents - header' => 'Contents - header', + 'Contents - row' => 'Contents - row', + 'Cook Islands' => 'Cook Islands', + 'Corrientes' => 'Corrientes', + 'Cosenza' => 'Cosenza', + 'Costa Rica' => 'Costa Rica', + 'Countries - JavaScript' => 'Countries - JavaScript', + 'Countries - at the top' => 'Countries - at the top', + 'Countries - bottom' => 'Countries - bottom', + 'Countries - table header' => 'Countries - table header', + 'Countries - table row' => 'Countries - table row', + 'Country - Edit JavaScript' => 'Country - Edit JavaScript', + 'Country - create form' => 'Country - create form', + 'Country - delete form' => 'Country - delete form', + 'Country edit - bottom' => 'Country edit - bottom', + 'Country edit - top' => 'Country edit - top', + 'Coupon' => 'Coupon', + 'Coupon - at the top' => 'Coupon - at the top', + 'Coupon - bottom' => 'Coupon - bottom', + 'Coupon - create JavaScript' => 'Coupon - create JavaScript', + 'Coupon - list JavaScript' => 'Coupon - list JavaScript', + 'Coupon - list caption' => 'Coupon - list caption', + 'Coupon - table header' => 'Coupon - table header', + 'Coupon - table row' => 'Coupon - table row', + 'Coupon - update JavaScript' => 'Coupon - update JavaScript', + 'Coupon page - in deletion form' => 'Coupon page - in deletion form', + 'Cremona' => 'Cremona', + 'Croatia' => 'Croatia', + 'Croatian Kuna' => 'Croatian Kuna', + 'Crotone' => 'Crotone', + 'Cuba' => 'Cuba', + 'Cuneo' => 'Cuneo', + 'Curency selection page - CSS stylesheet' => 'Curency selection page - CSS stylesheet', + 'Curency selection page - after javascript include' => 'Curency selection page - after javascript include', + 'Curency selection page - after javascript initialisation' => 'Curency selection page - after javascript initialisation', + 'Curency selection page - at the bottom' => 'Curency selection page - at the bottom', + 'Curency selection page - at the top' => 'Curency selection page - at the top', + 'Currencies - JavaScript' => 'Currencies - JavaScript', + 'Currencies - at the top' => 'Currencies - at the top', + 'Currencies - bottom' => 'Currencies - bottom', + 'Currencies - table header' => 'Currencies - table header', + 'Currencies - table row' => 'Currencies - table row', + 'Currency - Edit JavaScript' => 'Currency - Edit JavaScript', + 'Currency - create form' => 'Currency - create form', + 'Currency - delete form' => 'Currency - delete form', + 'Currency block' => 'Currency block', + 'Currency edit - bottom' => 'Currency edit - bottom', + 'Currency edit - top' => 'Currency edit - top', + 'Customer' => 'Customer', + 'Customer - Edit' => 'Customer - Edit', + 'Customer - Edit JavaScript' => 'Customer - Edit JavaScript', + 'Customer - address create form' => 'Customer - address create form', + 'Customer - address delete form' => 'Customer - address delete form', + 'Customer - address update form' => 'Customer - address update form', + 'Customer - at the top' => 'Customer - at the top', + 'Customer - bottom' => 'Customer - bottom', + 'Customer - create form' => 'Customer - create form', + 'Customer - delete form' => 'Customer - delete form', + 'Customer - order table header' => 'Customer - order table header', + 'Customer - order table row' => 'Customer - order table row', + 'Customer account - additional information' => 'Customer account - additional information', + 'Customer account block' => 'Customer account block', + 'Customer account creation should be confirmed by email (1: yes, 0: no)' => 'Customer account creation should be confirmed by email (1: yes, 0: no)', + 'Customer title' => 'Customer title', + 'Customers - JavaScript' => 'Customers - JavaScript', + 'Customers - caption' => 'Customers - caption', + 'Customers - header' => 'Customers - header', + 'Customers - row' => 'Customers - row', + 'Cyprus' => 'Cyprus', + 'Czech Republic' => 'Czech Republic', + 'Czech koruna' => 'Czech koruna', + 'Córdoba' => 'Córdoba', + 'Danish krone' => 'Danish krone', + 'Dashboard - at the top' => 'Dashboard - at the top', + 'Dashboard - bottom' => 'Dashboard - bottom', + 'Dashboard - middle' => 'Dashboard - middle', + 'Data import / export' => 'Data import / export', + 'Default available stock when check-available-stock is set to 0.' => 'Default available stock when check-available-stock is set to 0.', + 'Default lang without translation' => 'Default lang without translation', + 'Default number of coupons per page on coupon list' => 'Default number of coupons per page on coupon list', + 'Delaware' => 'Delaware', + 'Delivery - After delivery module' => 'Delivery - After delivery module', + 'Delivery - CSS' => 'Delivery - CSS', + 'Delivery - additional product information' => 'Delivery - additional product information', + 'Delivery - after addresse area' => 'Delivery - after addresse area', + 'Delivery - after product information' => 'Delivery - after product information', + 'Delivery - after the information area' => 'Delivery - after the information area', + 'Delivery - after the order summary' => 'Delivery - after the order summary', + 'Delivery - at the bottom of information area' => 'Delivery - at the bottom of information area', + 'Delivery - at the bottom of the footer' => 'Delivery - at the bottom of the footer', + 'Delivery - at the top of the footer' => 'Delivery - at the top of the footer', + 'Delivery - delivery address' => 'Delivery - delivery address', + 'Delivery - imprint' => 'Delivery - imprint', + 'Delivery - in the header' => 'Delivery - in the header', + 'Delivery choice - CSS stylesheet' => 'Delivery choice - CSS stylesheet', + 'Delivery choice - after javascript include' => 'Delivery choice - after javascript include', + 'Delivery choice - after javascript initialisation' => 'Delivery choice - after javascript initialisation', + 'Delivery choice - at the bottom' => 'Delivery choice - at the bottom', + 'Delivery choice - at the bottom of the form' => 'Delivery choice - at the bottom of the form', + 'Delivery choice - at the top' => 'Delivery choice - at the top', + 'Delivery choice - at the top of the form' => 'Delivery choice - at the top of the form', + 'Delivery choice - extra area' => 'Delivery choice - extra area', + 'Delivery choice - javascript' => 'Delivery choice - javascript', + 'Delivery zone - Edit JavaScript' => 'Delivery zone - Edit JavaScript', + 'Delivery zone - JavaScript' => 'Delivery zone - JavaScript', + 'Delivery zone - at the top' => 'Delivery zone - at the top', + 'Delivery zone - bottom' => 'Delivery zone - bottom', + 'Delivery zone - table header' => 'Delivery zone - table header', + 'Delivery zone - table row' => 'Delivery zone - table row', + 'Denmark' => 'Denmark', + 'Dinar' => 'Dinar', + 'Display and process prices with (0) or without (1) taxes.' => 'Display and process prices with (0) or without (1) taxes.', + 'Displays the default blocks on the homepage of the administration' => 'Displays the default blocks on the homepage of the administration', + 'District of Columbia' => 'District of Columbia', + 'Distrito Federal' => 'Distrito Federal', + 'Djibouti' => 'Djibouti', + 'Document - Edit JavaScript' => 'Document - Edit JavaScript', + 'Document edit - bottom' => 'Document edit - bottom', + 'Document edit - top' => 'Document edit - top', + 'Dollar' => 'Dollar', + 'Dollar (CAD)' => 'Dollar (CAD)', + 'Dominica' => 'Dominica', + 'Dominican Republic' => 'Dominican Republic', + 'Durango' => 'Durango', + 'East Nusa Tenggara' => 'East Nusa Tenggara', + 'East kalimantan' => 'East kalimantan', + 'Ecuador' => 'Ecuador', + 'Egypt' => 'Egypt', + 'Ehime' => 'Ehime', + 'El Salvador' => 'El Salvador', + 'Email html - layout - CSS' => 'Email html - layout - CSS', + 'Email html - layout - footer' => 'Email html - layout - footer', + 'Email html - order confirmation - after address' => 'Email html - order confirmation - after address', + 'Email html - order confirmation - after products' => 'Email html - order confirmation - after products', + 'Email html - order confirmation - before address' => 'Email html - order confirmation - before address', + 'Email html - order confirmation - before products' => 'Email html - order confirmation - before products', + 'Email html - order confirmation - delivery address' => 'Email html - order confirmation - delivery address', + 'Email html - order confirmation - footer' => 'Email html - order confirmation - footer', + 'Email html - order confirmation - order product' => 'Email html - order confirmation - order product', + 'Email html - order notification - after address' => 'Email html - order notification - after address', + 'Email html - order notification - after product information' => 'Email html - order notification - after product information', + 'Email html - order notification - after products' => 'Email html - order notification - after products', + 'Email html - order notification - before address' => 'Email html - order notification - before address', + 'Email html - order notification - before products' => 'Email html - order notification - before products', + 'Email html - order notification - delivery address' => 'Email html - order notification - delivery address', + 'Email html - order notification - order product' => 'Email html - order notification - order product', + 'Email txt - order confirmation - after address' => 'Email txt - order confirmation - after address', + 'Email txt - order confirmation - after products' => 'Email txt - order confirmation - after products', + 'Email txt - order confirmation - before address' => 'Email txt - order confirmation - before address', + 'Email txt - order confirmation - before products' => 'Email txt - order confirmation - before products', + 'Email txt - order confirmation - delivery address' => 'Email txt - order confirmation - delivery address', + 'Email txt - order confirmation - order product' => 'Email txt - order confirmation - order product', + 'Email txt - order notification - after address' => 'Email txt - order notification - after address', + 'Email txt - order notification - after product information' => 'Email txt - order notification - after product information', + 'Email txt - order notification - after products' => 'Email txt - order notification - after products', + 'Email txt - order notification - before address' => 'Email txt - order notification - before address', + 'Email txt - order notification - before products' => 'Email txt - order notification - before products', + 'Email txt - order notification - delivery address' => 'Email txt - order notification - delivery address', + 'Email txt - order notification - order product' => 'Email txt - order notification - order product', + 'Enable (1) or disable (0) URL rewriting' => 'Enable (1) or disable (0) URL rewriting', + 'Enna' => 'Enna', + 'Entre Ríos' => 'Entre Ríos', + 'Equatorial Guinea' => 'Equatorial Guinea', + 'Eritrea' => 'Eritrea', + 'Estado de México' => 'Estado de México', + 'Estonia' => 'Estonia', + 'Ethiopia' => 'Ethiopia', + 'Euro' => 'Euro', + 'Export - JavaScript' => 'Export - JavaScript', + 'Export - table header' => 'Export - table header', + 'Export - table row' => 'Export - table row', + 'Export modal or page - bottom' => 'Export modal or page - bottom', + 'Export modal or page - top' => 'Export modal or page - top', + 'Exports - JavaScript' => 'Exports - JavaScript', + 'Exports - at the bottom of a category' => 'Exports - at the bottom of a category', + 'Exports - at the bottom of column 1' => 'Exports - at the bottom of column 1', + 'Exports - at the top' => 'Exports - at the top', + 'Feature - Edit JavaScript' => 'Feature - Edit JavaScript', + 'Feature - Value create form' => 'Feature - Value create form', + 'Feature - add to all form' => 'Feature - add to all form', + 'Feature - create form' => 'Feature - create form', + 'Feature - delete form' => 'Feature - delete form', + 'Feature - remove to all form' => 'Feature - remove to all form', + 'Feature edit - bottom' => 'Feature edit - bottom', + 'Feature edit - top' => 'Feature edit - top', + 'Features - JavaScript' => 'Features - JavaScript', + 'Features - at the top' => 'Features - at the top', + 'Features - bottom' => 'Features - bottom', + 'Features - table header' => 'Features - table header', + 'Features - table row' => 'Features - table row', + 'Features value - table header' => 'Features value - table header', + 'Features value - table row' => 'Features value - table row', + 'Fermo' => 'Fermo', + 'Ferrara' => 'Ferrara', + 'Fiji' => 'Fiji', + 'File name of the 404 (not found) view in the current template (with extension, e.g. 404.html)' => 'File name of the 404 (not found) view in the current template (with extension, e.g. 404.html)', + 'Filename of the error page' => 'Filename of the error page', + 'Finland' => 'Finland', + 'Firenze' => 'Firenze', + 'Florida' => 'Florida', + 'Foggia' => 'Foggia', + 'Folder' => 'Folder', + 'Folder - Edit JavaScript' => 'Folder - Edit JavaScript', + 'Folder - JavaScript' => 'Folder - JavaScript', + 'Folder - Tab' => 'Folder - Tab', + 'Folder - at the top' => 'Folder - at the top', + 'Folder - bottom' => 'Folder - bottom', + 'Folder - caption' => 'Folder - caption', + 'Folder - content' => 'Folder - content', + 'Folder - create form' => 'Folder - create form', + 'Folder - delete form' => 'Folder - delete form', + 'Folder - header' => 'Folder - header', + 'Folder - row' => 'Folder - row', + 'Folder edit - bottom' => 'Folder edit - bottom', + 'Folder edit - right column bottom' => 'Folder edit - right column bottom', + 'Folder edit - right column top' => 'Folder edit - right column top', + 'Folder edit - top' => 'Folder edit - top', + 'Folder page - CSS stylesheet' => 'Folder page - CSS stylesheet', + 'Folder page - after javascript include' => 'Folder page - after javascript include', + 'Folder page - after javascript initialisation' => 'Folder page - after javascript initialisation', + 'Folder page - after the main content area' => 'Folder page - after the main content area', + 'Folder page - at the bottom' => 'Folder page - at the bottom', + 'Folder page - at the bottom of the main area' => 'Folder page - at the bottom of the main area', + 'Folder page - at the top' => 'Folder page - at the top', + 'Folder page - at the top of the main area' => 'Folder page - at the top of the main area', + 'Folder page - before the main content area' => 'Folder page - before the main content area', + 'Forint' => 'Forint', + 'Forlì-Cesena' => 'Forlì-Cesena', + 'Formosa' => 'Formosa', + 'Franc' => 'Franc', + 'France metropolitan' => 'France metropolitan', + 'French 10% VAT' => 'French 10% VAT', + 'French 20% VAT' => 'French 20% VAT', + 'French Southern Territories' => 'French Southern Territories', + 'Front office integration' => 'Front office integration', + 'Frosinone' => 'Frosinone', + 'Fukui' => 'Fukui', + 'Fukuoka' => 'Fukuoka', + 'Fukushima' => 'Fukushima', + 'Gabon' => 'Gabon', + 'Gambia' => 'Gambia', + 'Genova' => 'Genova', + 'Georgia' => 'Georgia', + 'Germany' => 'Germany', + 'Ghana' => 'Ghana', + 'Gifu' => 'Gifu', + 'Google Analytics block' => 'Google Analytics block', + 'Gorizia' => 'Gorizia', + 'Greece' => 'Greece', + 'Grenada' => 'Grenada', + 'Grosseto' => 'Grosseto', + 'Guadeloupe' => 'Guadeloupe', + 'Guanajuato' => 'Guanajuato', + 'Guaraní' => 'Guaraní', + 'Guatemala' => 'Guatemala', + 'Guerrero' => 'Guerrero', + 'Guinea' => 'Guinea', + 'Guinea-Bissau' => 'Guinea-Bissau', + 'Gunma' => 'Gunma', + 'Guyana' => 'Guyana', + 'Guyane Française' => 'Guyane Française', + 'HTML layout - CSS stylesheet' => 'HTML layout - CSS stylesheet', + 'HTML layout - after javascript include' => 'HTML layout - after javascript include', + 'HTML layout - after the main content area' => 'HTML layout - after the main content area', + 'HTML layout - after the opening of the body tag' => 'HTML layout - after the opening of the body tag', + 'HTML layout - after the opening of the head tag' => 'HTML layout - after the opening of the head tag', + 'HTML layout - at the bottom of the header' => 'HTML layout - at the bottom of the header', + 'HTML layout - at the top of the footer' => 'HTML layout - at the top of the footer', + 'HTML layout - at the top of the header' => 'HTML layout - at the top of the header', + 'HTML layout - before the end body tag' => 'HTML layout - before the end body tag', + 'HTML layout - before the end of the head tag' => 'HTML layout - before the end of the head tag', + 'HTML layout - before the main content area' => 'HTML layout - before the main content area', + 'HTML layout - bottom of the footer' => 'HTML layout - bottom of the footer', + 'HTML layout - footer body' => 'HTML layout - footer body', + 'HTML layout - javascript initialization' => 'HTML layout - javascript initialization', + 'HTML layout - primary navigation' => 'HTML layout - primary navigation', + 'HTML layout - secondary navigation' => 'HTML layout - secondary navigation', + 'Haiti' => 'Haiti', + 'Hawaii' => 'Hawaii', + 'Hidalgo' => 'Hidalgo', + 'Hiroshima' => 'Hiroshima', + 'Hokkaido' => 'Hokkaido', + 'Home - JavaScript' => 'Home - JavaScript', + 'Home - at the top' => 'Home - at the top', + 'Home - block' => 'Home - block', + 'Home - bottom' => 'Home - bottom', + 'Home page - CSS stylesheet' => 'Home page - CSS stylesheet', + 'Home page - after javascript include' => 'Home page - after javascript include', + 'Home page - after javascript initialisation' => 'Home page - after javascript initialisation', + 'Home page - main area' => 'Home page - main area', + 'Honduras' => 'Honduras', + 'Hong Kong' => 'Hong Kong', + 'Hong Kong Dollar' => 'Hong Kong Dollar', + 'Hook - Edit JavaScript' => 'Hook - Edit JavaScript', + 'Hook - create form' => 'Hook - create form', + 'Hook - delete form' => 'Hook - delete form', + 'Hook edit - bottom' => 'Hook edit - bottom', + 'Hook edit - top' => 'Hook edit - top', + 'Hook positions' => 'Hook positions', + 'Hooks' => 'Hooks', + 'Hooks - JavaScript' => 'Hooks - JavaScript', + 'Hooks - at the top' => 'Hooks - at the top', + 'Hooks - bottom' => 'Hooks - bottom', + 'Hooks - table header' => 'Hooks - table header', + 'Hooks - table row' => 'Hooks - table row', + 'Hooks management' => 'Hooks management', + 'How document files are delivered in the web space (symlink or copy)' => 'How document files are delivered in the web space (symlink or copy)', + 'How original (full resolution) images are delivered in the web space (symlink or copy)' => 'How original (full resolution) images are delivered in the web space (symlink or copy)', + 'Hungary' => 'Hungary', + 'Hyogo' => 'Hyogo', + 'Ibaraki' => 'Ibaraki', + 'Iceland' => 'Iceland', + 'Idaho' => 'Idaho', + 'Illinois' => 'Illinois', + 'Image - Edit JavaScript' => 'Image - Edit JavaScript', + 'Image edit - bottom' => 'Image edit - bottom', + 'Image edit - top' => 'Image edit - top', + 'Imperia' => 'Imperia', + 'Import - table header' => 'Import - table header', + 'Import - table row' => 'Import - table row', + 'India' => 'India', + 'Indian Rupee' => 'Indian Rupee', + 'Indiana' => 'Indiana', + 'Indonesia' => 'Indonesia', + 'Invoice - After delivery module' => 'Invoice - After delivery module', + 'Invoice - After payment module' => 'Invoice - After payment module', + 'Invoice - CSS' => 'Invoice - CSS', + 'Invoice - additional product information' => 'Invoice - additional product information', + 'Invoice - after addresse area' => 'Invoice - after addresse area', + 'Invoice - after product information' => 'Invoice - after product information', + 'Invoice - after product listing' => 'Invoice - after product listing', + 'Invoice - after the information area' => 'Invoice - after the information area', + 'Invoice - after the order summary' => 'Invoice - after the order summary', + 'Invoice - at the bottom of information area' => 'Invoice - at the bottom of information area', + 'Invoice - at the bottom of the footer' => 'Invoice - at the bottom of the footer', + 'Invoice - at the top of the footer' => 'Invoice - at the top of the footer', + 'Invoice - delivery address' => 'Invoice - delivery address', + 'Invoice - imprint' => 'Invoice - imprint', + 'Invoice - in the header' => 'Invoice - in the header', + 'Invoice choice - CSS stylesheet' => 'Invoice choice - CSS stylesheet', + 'Invoice choice - after javascript include' => 'Invoice choice - after javascript include', + 'Invoice choice - after javascript initialisation' => 'Invoice choice - after javascript initialisation', + 'Invoice choice - at the bottom' => 'Invoice choice - at the bottom', + 'Invoice choice - at the top' => 'Invoice choice - at the top', + 'Invoice choice - delivery address' => 'Invoice choice - delivery address', + 'Invoice choice - extra payment zone' => 'Invoice choice - extra payment zone', + 'Iowa' => 'Iowa', + 'Iran' => 'Iran', + 'Iraq' => 'Iraq', + 'Ireland' => 'Ireland', + 'Isernia' => 'Isernia', + 'Ishikawa' => 'Ishikawa', + 'Israel' => 'Israel', + 'Italy' => 'Italy', + 'Ivory Coast' => 'Ivory Coast', + 'Iwate' => 'Iwate', + 'Jakarta' => 'Jakarta', + 'Jalisco' => 'Jalisco', + 'Jamaica' => 'Jamaica', + 'Jambi' => 'Jambi', + 'Japan' => 'Japan', + 'Jordan' => 'Jordan', + 'Jujuy' => 'Jujuy', + 'Kagawa' => 'Kagawa', + 'Kagoshima' => 'Kagoshima', + 'Kanagawa' => 'Kanagawa', + 'Kansas' => 'Kansas', + 'Kazakhstan' => 'Kazakhstan', + 'Kentucky' => 'Kentucky', + 'Kenya' => 'Kenya', + 'Kenyan shilling' => 'Kenyan shilling', + 'Kiribati' => 'Kiribati', + 'Kochi' => 'Kochi', + 'Krona' => 'Krona', + 'Krone' => 'Krone', + 'Kumamoto' => 'Kumamoto', + 'Kuwait' => 'Kuwait', + 'Kyoto' => 'Kyoto', + 'Kyrgyzstan' => 'Kyrgyzstan', + 'L\'Aquila' => 'L\'Aquila', + 'La Pampa' => 'La Pampa', + 'La Rioja' => 'La Rioja', + 'La Spezia' => 'La Spezia', + 'Lambang Provinsi Papua Barat' => 'Lambang Provinsi Papua Barat', + 'Lambang Riau' => 'Lambang Riau', + 'Lambang propinsi' => 'Lambang propinsi', + 'Lampung' => 'Lampung', + 'Language - create form' => 'Language - create form', + 'Languages - JavaScript' => 'Languages - JavaScript', + 'Languages - at the top' => 'Languages - at the top', + 'Languages - bottom' => 'Languages - bottom', + 'Languages - delete form' => 'Languages - delete form', + 'Languages block' => 'Languages block', + 'Laos' => 'Laos', + 'Lari' => 'Lari', + 'Latina' => 'Latina', + 'Latvia' => 'Latvia', + 'Layout - Before the main content' => 'Layout - Before the main content', + 'Layout - CSS' => 'Layout - CSS', + 'Layout - JavaScript' => 'Layout - JavaScript', + 'Layout - after footer' => 'Layout - after footer', + 'Layout - after top bar' => 'Layout - after top bar', + 'Layout - after top menu' => 'Layout - after top menu', + 'Layout - at the bottom of the top bar' => 'Layout - at the bottom of the top bar', + 'Layout - at the top of the top bar' => 'Layout - at the top of the top bar', + 'Layout - before footer' => 'Layout - before footer', + 'Layout - before top menu' => 'Layout - before top menu', + 'Layout - before topbar' => 'Layout - before topbar', + 'Layout - in footer' => 'Layout - in footer', + 'Layout - in the menu catalog' => 'Layout - in the menu catalog', + 'Layout - in the menu configuration' => 'Layout - in the menu configuration', + 'Layout - in the menu customers' => 'Layout - in the menu customers', + 'Layout - in the menu folders' => 'Layout - in the menu folders', + 'Layout - in the menu modules' => 'Layout - in the menu modules', + 'Layout - in the menu orders' => 'Layout - in the menu orders', + 'Layout - in the menu tools' => 'Layout - in the menu tools', + 'Layout - in top menu items' => 'Layout - in top menu items', + 'Layout - inside top bar' => 'Layout - inside top bar', + 'Leave the default configuration of session' => 'Leave the default configuration of session', + 'Lebanon' => 'Lebanon', + 'Lecce' => 'Lecce', + 'Lecco' => 'Lecco', + 'Lei' => 'Lei', + 'Lesotho' => 'Lesotho', + 'Lev' => 'Lev', + 'Liberia' => 'Liberia', + 'Libya' => 'Libya', + 'Liechtenstein' => 'Liechtenstein', + 'Life time of the cart cookie in the customer browser, in seconds' => 'Life time of the cart cookie in the customer browser, in seconds', + 'Life time of the session cookie in the customer browser, in seconds' => 'Life time of the session cookie in the customer browser, in seconds', + 'Links block' => 'Links block', + 'Lira' => 'Lira', + 'Lithuania' => 'Lithuania', + 'Livorno' => 'Livorno', + 'Lodi' => 'Lodi', + 'Logging system configuration' => 'Logging system configuration', + 'Login page - CSS stylesheet' => 'Login page - CSS stylesheet', + 'Login page - after javascript include' => 'Login page - after javascript include', + 'Login page - after javascript initialisation' => 'Login page - after javascript initialisation', + 'Login page - at the bottom' => 'Login page - at the bottom', + 'Login page - at the bottom of the form' => 'Login page - at the bottom of the form', + 'Login page - at the bottom of the main area' => 'Login page - at the bottom of the main area', + 'Login page - at the top' => 'Login page - at the top', + 'Login page - at the top of the form' => 'Login page - at the top of the form', + 'Login page - at the top of the main area' => 'Login page - at the top of the main area', + 'Logs - JavaScript' => 'Logs - JavaScript', + 'Logs - at the top' => 'Logs - at the top', + 'Logs - bottom' => 'Logs - bottom', + 'Lost password - CSS stylesheet' => 'Lost password - CSS stylesheet', + 'Lost password - after javascript include' => 'Lost password - after javascript include', + 'Lost password - at the bottom' => 'Lost password - at the bottom', + 'Lost password - at the bottom of the form' => 'Lost password - at the bottom of the form', + 'Lost password - at the top' => 'Lost password - at the top', + 'Lost password - at the top of the form' => 'Lost password - at the top of the form', + 'Lost password - javascript initialization' => 'Lost password - javascript initialization', + 'Louisiana' => 'Louisiana', + 'Lucca' => 'Lucca', + 'Luxembourg' => 'Luxembourg', + 'Macedonia' => 'Macedonia', + 'Macerata' => 'Macerata', + 'Madagascar' => 'Madagascar', + 'Mail sent after a subscription to newsletter' => 'Mail sent after a subscription to newsletter', + 'Mail sent to an administrator who requested a new password' => 'Mail sent to an administrator who requested a new password', + 'Mail sent to the customer to confirm its account' => 'Mail sent to the customer to confirm its account', + 'Mail sent to the customer when its account is created by an administrator in the back-office' => 'Mail sent to the customer when its account is created by an administrator in the back-office', + 'Mail sent to the customer when its password or email is changed in the back-office' => 'Mail sent to the customer when its password or email is changed in the back-office', + 'Mailing system - JavaScript' => 'Mailing system - JavaScript', + 'Mailing system - at the top' => 'Mailing system - at the top', + 'Mailing system - bottom' => 'Mailing system - bottom', + 'Maine' => 'Maine', + 'Malawi' => 'Malawi', + 'Malaysia' => 'Malaysia', + 'Maldives' => 'Maldives', + 'Mali' => 'Mali', + 'Malta' => 'Malta', + 'Maluku' => 'Maluku', + 'Manat' => 'Manat', + 'Manitoba' => 'Manitoba', + 'Mantova' => 'Mantova', + 'Marshall Islands' => 'Marshall Islands', + 'Martinique' => 'Martinique', + 'Maryland' => 'Maryland', + 'Massa' => 'Massa', + 'Massachusetts' => 'Massachusetts', + 'Matera' => 'Matera', + 'Mauritania' => 'Mauritania', + 'Mauritius' => 'Mauritius', + 'Mayotte' => 'Mayotte', + 'Medio Campidano' => 'Medio Campidano', + 'Mendoza' => 'Mendoza', + 'Message - Edit JavaScript' => 'Message - Edit JavaScript', + 'Message - create form' => 'Message - create form', + 'Message - delete form' => 'Message - delete form', + 'Message edit - bottom' => 'Message edit - bottom', + 'Message edit - top' => 'Message edit - top', + 'Message sent to the shop owner when a new order is placed' => 'Message sent to the shop owner when a new order is placed', + 'Messages - JavaScript' => 'Messages - JavaScript', + 'Messages - at the top' => 'Messages - at the top', + 'Messages - bottom' => 'Messages - bottom', + 'Messages - table header' => 'Messages - table header', + 'Messages - table row' => 'Messages - table row', + 'Messina' => 'Messina', + 'Mexico' => 'Mexico', + 'Michigan' => 'Michigan', + 'Michoacán' => 'Michoacán', + 'Micronesia' => 'Micronesia', + 'Mie' => 'Mie', + 'Milano' => 'Milano', + 'Mini cart' => 'Mini cart', + 'Minnesota' => 'Minnesota', + 'Misiones' => 'Misiones', + 'Miss' => 'Miss', + 'Miss_short' => 'Miss_short', + 'Misses' => 'Misses', + 'Mississippi' => 'Mississippi', + 'Missouri' => 'Missouri', + 'Mister' => 'Mister', + 'Miyagi' => 'Miyagi', + 'Miyazaki' => 'Miyazaki', + 'Modena' => 'Modena', + 'Module - Edit JavaScript' => 'Module - Edit JavaScript', + 'Module - configuration' => 'Module - configuration', + 'Module - configuration JavaScript' => 'Module - configuration JavaScript', + 'Module edit - bottom' => 'Module edit - bottom', + 'Module edit - top' => 'Module edit - top', + 'Module hook - Edit JavaScript' => 'Module hook - Edit JavaScript', + 'Module hook - JavaScript' => 'Module hook - JavaScript', + 'Module hook - create form' => 'Module hook - create form', + 'Module hook - delete form' => 'Module hook - delete form', + 'Module hook edit - bottom' => 'Module hook edit - bottom', + 'Module hook edit - top' => 'Module hook edit - top', + 'Modules - JavaScript' => 'Modules - JavaScript', + 'Modules - at the top' => 'Modules - at the top', + 'Modules - bottom' => 'Modules - bottom', + 'Modules - table header' => 'Modules - table header', + 'Modules - table row' => 'Modules - table row', + 'Modules maagement' => 'Modules maagement', + 'Modules management' => 'Modules management', + 'Moldova' => 'Moldova', + 'Monaco' => 'Monaco', + 'Mongolia' => 'Mongolia', + 'Montana' => 'Montana', + 'Monza e della Brianza' => 'Monza e della Brianza', + 'Morelos' => 'Morelos', + 'Morocco' => 'Morocco', + 'Mozambique' => 'Mozambique', + 'Mr.' => 'Mr.', + 'Mrs' => 'Mrs', + 'Nagano' => 'Nagano', + 'Nagasaki' => 'Nagasaki', + 'Name of the active PDF template' => 'Name of the active PDF template', + 'Name of the active back-office template' => 'Name of the active back-office template', + 'Name of the active front-office template' => 'Name of the active front-office template', + 'Name of the active mailing template' => 'Name of the active mailing template', + 'Name of the cart cookie' => 'Name of the cart cookie', + 'Name of the delivery view in the current PDF template (without extension)' => 'Name of the delivery view in the current PDF template (without extension)', + 'Name of the graphic driver used by the Imagine library (see https://imagine.readthedocs.org)' => 'Name of the graphic driver used by the Imagine library (see https://imagine.readthedocs.org)', + 'Name of the invoice view in the current PDF template (without extension)' => 'Name of the invoice view in the current PDF template (without extension)', + 'Name of the template view returned when an obsolete (or inactive) product URL is invoked' => 'Name of the template view returned when an obsolete (or inactive) product URL is invoked', + 'Name the cart cookie' => 'Name the cart cookie', + 'Namibia' => 'Namibia', + 'Napoli' => 'Napoli', + 'Nara' => 'Nara', + 'Nauru' => 'Nauru', + 'Navigation block' => 'Navigation block', + 'Nayarit' => 'Nayarit', + 'Nebraska' => 'Nebraska', + 'Nepal' => 'Nepal', + 'Netherlands' => 'Netherlands', + 'Neuquén' => 'Neuquén', + 'Nevada' => 'Nevada', + 'New Brunswick' => 'New Brunswick', + 'New Hampshire' => 'New Hampshire', + 'New Jersey' => 'New Jersey', + 'New Mexico' => 'New Mexico', + 'New Products block' => 'New Products block', + 'New York' => 'New York', + 'New Zealand' => 'New Zealand', + 'New order {$order_ref} placed on {config key="store_name"}' => 'New order {$order_ref} placed on {config key="store_name"}', + 'New password request on %store' => 'New password request on {config key="store_name"}', + 'Newfoundland and Labrador' => 'Newfoundland and Labrador', + 'Newsletter block' => 'Newsletter block', + 'Newsletter page - CSS stylesheet' => 'Newsletter page - CSS stylesheet', + 'Newsletter page - after javascript include' => 'Newsletter page - after javascript include', + 'Newsletter page - after javascript initialisation' => 'Newsletter page - after javascript initialisation', + 'Newsletter page - at the bottom' => 'Newsletter page - at the bottom', + 'Newsletter page - at the top' => 'Newsletter page - at the top', + 'Newsletter subscription confirmation mail' => 'Newsletter subscription confirmation mail', + 'Newsletter unsubscribe page - CSS stylesheet' => 'Newsletter unsubscribe page - CSS stylesheet', + 'Newsletter unsubscribe page - after javascript include' => 'Newsletter unsubscribe page - after javascript include', + 'Newsletter unsubscribe page - after javascript initialisation' => 'Newsletter unsubscribe page - after javascript initialisation', + 'Newsletter unsubscribe page - at the bottom' => 'Newsletter unsubscribe page - at the bottom', + 'Newsletter unsubscribe page - at the top' => 'Newsletter unsubscribe page - at the top', + 'Nicaragua' => 'Nicaragua', + 'Niger' => 'Niger', + 'Nigeria' => 'Nigeria', + 'Nigerian naira' => 'Nigerian naira', + 'Niigata' => 'Niigata', + 'Niue' => 'Niue', + 'North Carolina' => 'North Carolina', + 'North Dakota' => 'North Dakota', + 'North Korea' => 'North Korea', + 'North Maluku' => 'North Maluku', + 'North Sulawesi' => 'North Sulawesi', + 'North Sumatra' => 'North Sumatra', + 'Northwest Territories' => 'Northwest Territories', + 'Norway' => 'Norway', + 'Not paid' => 'Not paid', + 'Nouvelle-Calédonie' => 'Nouvelle-Calédonie', + 'Nova Scotia' => 'Nova Scotia', + 'Novara' => 'Novara', + 'Nuevo León' => 'Nuevo León', + 'Nuevo Sol' => 'Nuevo Sol', + 'Number by default of results per page for customer list' => 'Default number of customers on customer list', + 'Number by default of results per page for order list' => 'Default number of orders on order list', + 'Number by default of results per page for product list' => 'Default number of products on product list', + 'Nunavut' => 'Nunavut', + 'Nuoro' => 'Nuoro', + 'Oaxaca' => 'Oaxaca', + 'Ogliastra' => 'Ogliastra', + 'Ohio' => 'Ohio', + 'Oita' => 'Oita', + 'Okayama' => 'Okayama', + 'Okinawa' => 'Okinawa', + 'Oklahoma' => 'Oklahoma', + 'Olbia-Tempio' => 'Olbia-Tempio', + 'Oman' => 'Oman', + 'Ontario' => 'Ontario', + 'Order' => 'Order', + 'Order - After closing product row' => 'Order - After closing product row', + 'Order - After product list' => 'Order - After product list', + 'Order - Before product list' => 'Order - Before product list', + 'Order - Before starting product row' => 'Order - Before starting product row', + 'Order - Edit JavaScript' => 'Order - Edit JavaScript', + 'Order - Tab' => 'Order - Tab', + 'Order - bill bottom' => 'Order - bill bottom', + 'Order - bill top' => 'Order - bill top', + 'Order - cart bottom' => 'Order - cart bottom', + 'Order - cart top' => 'Order - cart top', + 'Order - content' => 'Order - content', + 'Order - customer information bottom' => 'Order - customer information bottom', + 'Order - delivery module bottom' => 'Order - delivery module bottom', + 'Order - payment module bottom' => 'Order - payment module bottom', + 'Order - product list' => 'Order - product list', + 'Order - table header' => 'Order - table header', + 'Order - table row' => 'Order - table row', + 'Order confirmation - after the order summary' => 'Order confirmation - after the order summary', + 'Order confirmation sent to the customer' => 'Order confirmation sent to the customer', + 'Order details - CSS stylesheet' => 'Order details - CSS stylesheet', + 'Order details - additional delivery information' => 'Order details - additional delivery information', + 'Order details - additional information' => 'Order details - additional information', + 'Order details - additional invoice information' => 'Order details - additional invoice information', + 'Order details - additional product information' => 'Order details - additional product information', + 'Order details - after addresses' => 'Order details - after addresses', + 'Order details - after delivery address' => 'Order details - after delivery address', + 'Order details - after global information' => 'Order details - after global information', + 'Order details - after invoice address' => 'Order details - after invoice address', + 'Order details - after javascript include' => 'Order details - after javascript include', + 'Order details - after product' => 'Order details - after product', + 'Order details - after products' => 'Order details - after products', + 'Order details - after products list' => 'Order details - after products list', + 'Order details - at the bottom' => 'Order details - at the bottom', + 'Order details - at the top' => 'Order details - at the top', + 'Order details - before products list' => 'Order details - before products list', + 'Order details - delivery address' => 'Order details - delivery address', + 'Order details - invoice address' => 'Order details - invoice address', + 'Order details - javascript initialization' => 'Order details - javascript initialization', + 'Order edit - bottom' => 'Order edit - bottom', + 'Order edit - delivery address' => 'Order edit - delivery address', + 'Order edit - displayed after product information' => 'Order edit - displayed after product information', + 'Order edit - order product table header' => 'Order edit - order product table header', + 'Order edit - order product table row' => 'Order edit - order product table row', + 'Order edit - top' => 'Order edit - top', + 'Order failed - CSS stylesheet' => 'Order failed - CSS stylesheet', + 'Order failed - after javascript include' => 'Order failed - after javascript include', + 'Order failed - after javascript initialisation' => 'Order failed - after javascript initialisation', + 'Order failed - at the bottom' => 'Order failed - at the bottom', + 'Order failed - at the top' => 'Order failed - at the top', + 'Order invoice page - bottom of coupon form' => 'Order invoice page - bottom of coupon form', + 'Order invoice page - bottom of payment form' => 'Order invoice page - bottom of payment form', + 'Order status - JavaScript' => 'Order status - JavaScript', + 'Order status - bottom' => 'Order status - bottom', + 'Order status - form creation' => 'Order status - form creation', + 'Order status - form modification' => 'Order status - form modification', + 'Order status - table header' => 'Order status - table header', + 'Order status - table row' => 'Order status - table row', + 'Order status - top' => 'Order status - top', + 'Orders - JavaScript' => 'Orders - JavaScript', + 'Orders - at the top' => 'Orders - at the top', + 'Orders - bottom' => 'Orders - bottom', + 'Orders - table header' => 'Orders - table header', + 'Orders - table row' => 'Orders - table row', + 'Oregon' => 'Oregon', + 'Oristano' => 'Oristano', + 'Osaka' => 'Osaka', + 'Padova' => 'Padova', + 'Page 404 - CSS stylesheet' => 'Page 404 - CSS stylesheet', + 'Page 404 - after javascript include' => 'Page 404 - after javascript include', + 'Page 404 - after javascript initialisation' => 'Page 404 - after javascript initialisation', + 'Page 404 - content area' => 'Page 404 - content area', + 'Paid' => 'Paid', + 'Pakistan' => 'Pakistan', + 'Palermo' => 'Palermo', + 'Panama' => 'Panama', + 'Papua' => 'Papua', + 'Papua Nueva Guinea' => 'Papua Nueva Guinea', + 'Paraguay' => 'Paraguay', + 'Parma' => 'Parma', + 'Path to the directory where documents are stored' => 'Path to the directory where documents are stored', + 'Path to the directory where images are stored' => 'Path to the directory where images are stored', + 'Pavia' => 'Pavia', + 'Pay by cheque' => 'Pay by cheque', + 'Payment failed - CSS stylesheet' => 'Payment failed - CSS stylesheet', + 'Payment failed - after javascript include' => 'Payment failed - after javascript include', + 'Payment failed - javascript initialization' => 'Payment failed - javascript initialization', + 'Payment gateway - CSS stylesheet' => 'Payment gateway - CSS stylesheet', + 'Payment gateway - after javascript include' => 'Payment gateway - after javascript include', + 'Payment gateway - after javascript initialisation' => 'Payment gateway - after javascript initialisation', + 'Payment gateway - javascript' => 'Payment gateway - javascript', + 'Payment gateway - main area' => 'Payment gateway - main area', + 'Pennsylvania' => 'Pennsylvania', + 'Peru' => 'Peru', + 'Perugia' => 'Perugia', + 'Pesaro-Urbino' => 'Pesaro-Urbino', + 'Pescara' => 'Pescara', + 'Peso' => 'Peso', + 'Peso Argentino' => 'Peso Argentino', + 'Philippine Peso' => 'Philippine Peso', + 'Philippines' => 'Philippines', + 'Piacenza' => 'Piacenza', + 'Pisa' => 'Pisa', + 'Pistoia' => 'Pistoia', + 'Placed order - CSS stylesheet' => 'Placed order - CSS stylesheet', + 'Placed order - after javascript include' => 'Placed order - after javascript include', + 'Placed order - after javascript initialisation' => 'Placed order - after javascript initialisation', + 'Placed order - main area' => 'Placed order - main area', + 'Poland' => 'Poland', + 'Polynésie française' => 'Polynésie française', + 'Pordenone' => 'Pordenone', + 'Portugal' => 'Portugal', + 'Potenza' => 'Potenza', + 'Pound' => 'Pound', + 'Prato' => 'Prato', + 'Prince Edward Island' => 'Prince Edward Island', + 'Processing' => 'Processing', + 'Product' => 'Product', + 'Product - Edit JavaScript' => 'Product - Edit JavaScript', + 'Product - Tab' => 'Product - Tab', + 'Product - accessories table header' => 'Product - accessories table header', + 'Product - accessories table row' => 'Product - accessories table row', + 'Product - after combinations' => 'Product - after combinations', + 'Product - at the bottom of a product combination' => 'Product - at the bottom of a product combination', + 'Product - attributes table header' => 'Product - attributes table header', + 'Product - attributes table row' => 'Product - attributes table row', + 'Product - before combinations' => 'Product - before combinations', + 'Product - categories table header' => 'Product - categories table header', + 'Product - categories table row' => 'Product - categories table row', + 'Product - combination delete form' => 'Product - combination delete form', + 'Product - combinations list caption' => 'Product - combinations list caption', + 'Product - content' => 'Product - content', + 'Product - contents table header' => 'Product - contents table header', + 'Product - contents table row' => 'Product - contents table row', + 'Product - create form' => 'Product - create form', + 'Product - delete form' => 'Product - delete form', + 'Product - details pricing form' => 'Product - details pricing form', + 'Product - details promotion form' => 'Product - details promotion form', + 'Product - features table row' => 'Product - features table row', + 'Product - features-table-header' => 'Product - features-table-header', + 'Product - folders table header' => 'Product - folders table header', + 'Product - folders table row' => 'Product - folders table row', + 'Product - stock edit form' => 'Product - stock edit form', + 'Product edit - bottom' => 'Product edit - bottom', + 'Product edit - right column bottom' => 'Product edit - right column bottom', + 'Product edit - right column top' => 'Product edit - right column top', + 'Product edit - top' => 'Product edit - top', + 'Product loop - at the bottom' => 'Product loop - at the bottom', + 'Product loop - at the top' => 'Product loop - at the top', + 'Product page - CSS stylesheet' => 'Product page - CSS stylesheet', + 'Product page - On the bottom of the form' => 'Product page - On the bottom of the form', + 'Product page - On the top of the form' => 'Product page - On the top of the form', + 'Product page - additional information' => 'Product page - additional information', + 'Product page - after javascript include' => 'Product page - after javascript include', + 'Product page - after javascript initialisation' => 'Product page - after javascript initialisation', + 'Product page - at the bottom' => 'Product page - at the bottom', + 'Product page - at the bottom of the detail area' => 'Product page - at the bottom of the detail area', + 'Product page - at the top' => 'Product page - at the top', + 'Product page - at the top of the detail' => 'Product page - at the top of the detail', + 'Product page - photo gallery' => 'Product page - photo gallery', + 'Products - caption' => 'Products - caption', + 'Products - header' => 'Products - header', + 'Products - row' => 'Products - row', + 'Products offer block' => 'Products offer block', + 'Profile - Edit JavaScript' => 'Profile - Edit JavaScript', + 'Profile - create form' => 'Profile - create form', + 'Profile - delete form' => 'Profile - delete form', + 'Profile - table header' => 'Profile - table header', + 'Profile - table row' => 'Profile - table row', + 'Profile edit - bottom' => 'Profile edit - bottom', + 'Profile edit - top' => 'Profile edit - top', + 'Profiles - JavaScript' => 'Profiles - JavaScript', + 'Profiles - at the top' => 'Profiles - at the top', + 'Profiles - bottom' => 'Profiles - bottom', + 'Puebla' => 'Puebla', + 'Puerto Rico' => 'Puerto Rico', + 'Qatar' => 'Qatar', + 'Quebec' => 'Quebec', + 'Querétaro' => 'Querétaro', + 'Quetzal' => 'Quetzal', + 'Quintana Roo' => 'Quintana Roo', + 'Ragusa' => 'Ragusa', + 'Ravenna' => 'Ravenna', + 'Real' => 'Real', + 'Refunded' => 'Refunded', + 'Reggio Calabria' => 'Reggio Calabria', + 'Reggio Emilia' => 'Reggio Emilia', + 'Register - CSS stylesheet' => 'Register - CSS stylesheet', + 'Register - after javascript include' => 'Register - after javascript include', + 'Register - after javascript initialisation' => 'Register - after javascript initialisation', + 'Register - at the bottom' => 'Register - at the bottom', + 'Register - at the bottom of the form' => 'Register - at the bottom of the form', + 'Register - at the top' => 'Register - at the top', + 'Register - at the top of the form' => 'Register - at the top of the form', + 'Rhode Island' => 'Rhode Island', + 'Riau' => 'Riau', + 'Rieti' => 'Rieti', + 'Rimini' => 'Rimini', + 'Ringgit' => 'Ringgit', + 'Riyal' => 'Riyal', + 'Roma' => 'Roma', + 'Romania' => 'Romania', + 'Rovigo' => 'Rovigo', + 'Ruble' => 'Ruble', + 'Rupee' => 'Rupee', + 'Rupiah' => 'Rupiah', + 'Russia' => 'Russia', + 'Rwanda' => 'Rwanda', + 'Réunion(La)' => 'Réunion(La)', + 'Río Negro' => 'Río Negro', + 'Saga' => 'Saga', + 'Saint Barthélemy' => 'Saint Barthélemy', + 'Saint Kitts and Nevis' => 'Saint Kitts and Nevis', + 'Saint Lucia' => 'Saint Lucia', + 'Saint Martin (French part)' => 'Saint Martin (French part)', + 'Saint Vincent and the Grenadines' => 'Saint Vincent and the Grenadines', + 'Saitama' => 'Saitama', + 'Sale - CSS stylesheet' => 'Sale - CSS stylesheet', + 'Sale - after javascript include' => 'Sale - after javascript include', + 'Sale - after the main content area' => 'Sale - after the main content area', + 'Sale - at the bottom' => 'Sale - at the bottom', + 'Sale - at the bottom of the main area' => 'Sale - at the bottom of the main area', + 'Sale - at the top' => 'Sale - at the top', + 'Sale - at the top of the main area' => 'Sale - at the top of the main area', + 'Sale - before the main content area' => 'Sale - before the main content area', + 'Sale - create form' => 'Sale - create form', + 'Sale - delete form' => 'Sale - delete form', + 'Sale - javascript initialization' => 'Sale - javascript initialization', + 'Sale edit - bottom' => 'Sale edit - bottom', + 'Sale edit - top' => 'Sale edit - top', + 'Sale edit page - javascript last call block' => 'Sale edit page - javascript last call block', + 'Salerno' => 'Salerno', + 'Sales - JavaScript' => 'Sales - JavaScript', + 'Sales - at the bottom' => 'Sales - at the bottom', + 'Sales - at the top' => 'Sales - at the top', + 'Sales - table header' => 'Sales - table header', + 'Sales - table row' => 'Sales - table row', + 'Sales management' => 'Sales management', + 'Salta' => 'Salta', + 'San Juan' => 'San Juan', + 'San Luis' => 'San Luis', + 'San Luis Potosí' => 'San Luis Potosí', + 'San Marino' => 'San Marino', + 'Santa Cruz' => 'Santa Cruz', + 'Santa Fe' => 'Santa Fe', + 'Santiago del Estero' => 'Santiago del Estero', + 'Sao Tome and Principe' => 'Sao Tome and Principe', + 'Saskatchewan' => 'Saskatchewan', + 'Sassari' => 'Sassari', + 'Saudi Arabia' => 'Saudi Arabia', + 'Savona' => 'Savona', + 'Search' => 'Search', + 'Search - JavaScript' => 'Search - JavaScript', + 'Search - at the top' => 'Search - at the top', + 'Search - bottom' => 'Search - bottom', + 'Search block' => 'Search block', + 'Search page - CSS stylesheet' => 'Search page - CSS stylesheet', + 'Search page - after javascript include' => 'Search page - after javascript include', + 'Search page - after javascript initialisation' => 'Search page - after javascript initialisation', + 'Secret key for form CSRF token' => 'Secret key for form CSRF token', + 'Send a confirmation email to newsletter subscribers (1 = yes, 0 = no)' => 'Send a confirmation email to newsletter subscribers (1 = yes, 0 = no)', + 'Senegal' => 'Senegal', + 'Sent' => 'Sent', + 'Seychelles' => 'Seychelles', + 'Shekel' => 'Shekel', + 'Shiga' => 'Shiga', + 'Shimane' => 'Shimane', + 'Shipping configuration' => 'Shipping configuration', + 'Shipping configuration - Edit' => 'Shipping configuration - Edit', + 'Shipping configuration - Edit JavaScript' => 'Shipping configuration - Edit JavaScript', + 'Shipping configuration - JavaScript' => 'Shipping configuration - JavaScript', + 'Shipping configuration - at the top' => 'Shipping configuration - at the top', + 'Shipping configuration - bottom' => 'Shipping configuration - bottom', + 'Shipping configuration - country delete form' => 'Shipping configuration - country delete form', + 'Shipping configuration - create form' => 'Shipping configuration - create form', + 'Shipping configuration - delete form' => 'Shipping configuration - delete form', + 'Shipping configuration - table header' => 'Shipping configuration - table header', + 'Shipping configuration - table row' => 'Shipping configuration - table row', + 'Shipping configuration edit - bottom' => 'Shipping configuration edit - bottom', + 'Shipping configuration edit - top' => 'Shipping configuration edit - top', + 'Shipping zones edit - bottom' => 'Shipping zones edit - bottom', + 'Shipping zones edit - top' => 'Shipping zones edit - top', + 'Shizuoka' => 'Shizuoka', + 'Show error message instead of a white page on a server error' => 'Show error message instead of a white page on a server error', + 'Siena' => 'Siena', + 'Sierra Leone' => 'Sierra Leone', + 'Sinaloa' => 'Sinaloa', + 'Singapore' => 'Singapore', + 'Siracusa' => 'Siracusa', + 'Sitemap - at the bottom' => 'Sitemap - at the bottom', + 'Slovakia' => 'Slovakia', + 'Slovenia' => 'Slovenia', + 'Smarty template engine integration' => 'Smarty template engine integration', + 'Social Networks block' => 'Social Networks block', + 'Solomon Islands' => 'Solomon Islands', + 'Somalia' => 'Somalia', + 'Sondrio' => 'Sondrio', + 'Sonora' => 'Sonora', + 'South Africa' => 'South Africa', + 'South Carolina' => 'South Carolina', + 'South Dakota' => 'South Dakota', + 'South Kalimantan' => 'South Kalimantan', + 'South Korea' => 'South Korea', + 'South Sulawesi' => 'South Sulawesi', + 'South Sumatra' => 'South Sumatra', + 'Southeast Sulawesi' => 'Southeast Sulawesi', + 'Spain' => 'Spain', + 'Sri Lanka' => 'Sri Lanka', + 'St Pierre et Miquelon' => 'St Pierre et Miquelon', + 'Store Information - JavaScript' => 'Store Information - JavaScript', + 'Store information configuration' => 'Store information configuration', + 'Sudan' => 'Sudan', + 'Suriname' => 'Suriname', + 'Swaziland' => 'Swaziland', + 'Sweden' => 'Sweden', + 'Switzerland' => 'Switzerland', + 'Syria' => 'Syria', + 'System - logs JavaScript' => 'System - logs JavaScript', + 'Tab SEO - bottom' => 'Tab SEO - bottom', + 'Tab SEO - top' => 'Tab SEO - top', + 'Tab SEO - update form' => 'Tab SEO - update form', + 'Tab document - bottom' => 'Tab document - bottom', + 'Tab document - top' => 'Tab document - top', + 'Tab image - bottom' => 'Tab image - bottom', + 'Tab image - top' => 'Tab image - top', + 'Tabasco' => 'Tabasco', + 'Tajikistan' => 'Tajikistan', + 'Tamaulipas' => 'Tamaulipas', + 'Tanzania' => 'Tanzania', + 'Taranto' => 'Taranto', + 'Tax - Edit JavaScript' => 'Tax - Edit JavaScript', + 'Tax - create form' => 'Tax - create form', + 'Tax - delete form' => 'Tax - delete form', + 'Tax edit - bottom' => 'Tax edit - bottom', + 'Tax edit - top' => 'Tax edit - top', + 'Tax rule edit - bottom' => 'Tax rule edit - bottom', + 'Tax rule edit - top' => 'Tax rule edit - top', + 'Tax rules configuration' => 'Tax rules configuration', + 'Taxes - update form' => 'Taxes - update form', + 'Taxes rules - JavaScript' => 'Taxes rules - JavaScript', + 'Taxes rules - at the top' => 'Taxes rules - at the top', + 'Taxes rules - bottom' => 'Taxes rules - bottom', + 'Template - Edit JavaScript' => 'Template - Edit JavaScript', + 'Template - attributes table header' => 'Template - attributes table header', + 'Template - attributes table row' => 'Template - attributes table row', + 'Template - create form' => 'Template - create form', + 'Template - delete form' => 'Template - delete form', + 'Template - features table row' => 'Template - features table row', + 'Template - features-table-header' => 'Template - features-table-header', + 'Template edit - bottom' => 'Template edit - bottom', + 'Template edit - top' => 'Template edit - top', + 'Templates - JavaScript' => 'Templates - JavaScript', + 'Templates - at the top' => 'Templates - at the top', + 'Templates - bottom' => 'Templates - bottom', + 'Templates - table header' => 'Templates - table header', + 'Templates - table row' => 'Templates - table row', + 'Tennessee' => 'Tennessee', + 'Teramo' => 'Teramo', + 'Terni' => 'Terni', + 'Texas' => 'Texas', + 'Thailand' => 'Thailand', + 'The ID of the \'Terms & Conditions\' content.' => 'The ID of the \'Terms & Conditions\' content.', + 'The ID of the folder containing your information pages : terms, imprint, ...' => 'The ID of the folder containing your information pages : terms, imprint, ...', + 'The Vatican' => 'The Vatican', + 'The default quality (in %) of the generated images' => 'The default quality (in %) of the generated images', + 'The minimum length required for an administrator password' => 'The minimum length required for an administrator password', + 'The path (relative to the default back-office template) to the image used when no flag image can be found for a country' => 'The path (relative to the default back-office template) to the image used when no flag image can be found for a country', + 'The path to the document cache directory in the web space' => 'The path to the document cache directory in the web space', + 'The path to the image cache directory in the web space' => 'The path to the image cache directory in the web space', + 'Tierra del Fuego' => 'Tierra del Fuego', + 'TinyMCE WYSIWYG editor' => 'TinyMCE WYSIWYG editor', + 'Tlaxcala' => 'Tlaxcala', + 'Tochigi' => 'Tochigi', + 'Togo' => 'Togo', + 'Tokushima' => 'Tokushima', + 'Tokyo' => 'Tokyo', + 'Tonga' => 'Tonga', + 'Tools - JavaScript' => 'Tools - JavaScript', + 'Tools - at the bottom of column 1' => 'Tools - at the bottom of column 1', + 'Tools - at the top' => 'Tools - at the top', + 'Tools - at the top of the column' => 'Tools - at the top of the column', + 'Tools - bottom' => 'Tools - bottom', + 'Tools panel' => 'Tools panel', + 'Torino' => 'Torino', + 'Tottori' => 'Tottori', + 'Toyama' => 'Toyama', + 'Translations' => 'Translations', + 'Translations - JavaScript' => 'Translations - JavaScript', + 'Trapani' => 'Trapani', + 'Trento' => 'Trento', + 'Treviso' => 'Treviso', + 'Trieste' => 'Trieste', + 'Trinidad and Tobago' => 'Trinidad and Tobago', + 'Tucumán' => 'Tucumán', + 'Tunisia' => 'Tunisia', + 'Tunisian Dinar' => 'Tunisian Dinar', + 'Turkey' => 'Turkey', + 'Turkmenistan' => 'Turkmenistan', + 'Tuvalu' => 'Tuvalu', + 'UK Pound' => 'UK Pound', + 'US Virgin Islands' => 'US Virgin Islands', + 'USA' => 'USA', + 'Udine' => 'Udine', + 'Uganda' => 'Uganda', + 'Ukraine' => 'Ukraine', + 'United Arab Emirates' => 'United Arab Emirates', + 'United Arab Emirates dirham' => 'United Arab Emirates dirham', + 'United Kingdom' => 'United Kingdom', + 'United States Dollar' => 'United States Dollar', + 'Update customer account - CSS stylesheet' => 'Update customer account - CSS stylesheet', + 'Update customer account - after javascript include' => 'Update customer account - after javascript include', + 'Update customer account - after javascript initialisation' => 'Update customer account - after javascript initialisation', + 'Update customer account - at the bottom' => 'Update customer account - at the bottom', + 'Update customer account - at the bottom of the form' => 'Update customer account - at the bottom of the form', + 'Update customer account - at the top' => 'Update customer account - at the top', + 'Update customer account - at the top of the form' => 'Update customer account - at the top of the form', + 'Uruguay' => 'Uruguay', + 'Use a persistent cookie to keep track of customer cart' => 'Use a persistent cookie to keep track of customer cart', + 'Utah' => 'Utah', + 'Uzbekistan' => 'Uzbekistan', + 'Vanuatu' => 'Vanuatu', + 'Varese' => 'Varese', + 'Variable - Edit JavaScript' => 'Variable - Edit JavaScript', + 'Variable - create form' => 'Variable - create form', + 'Variable - delete form' => 'Variable - delete form', + 'Variable edit - bottom' => 'Variable edit - bottom', + 'Variable edit - top' => 'Variable edit - top', + 'Variables - JavaScript' => 'Variables - JavaScript', + 'Variables - at the top' => 'Variables - at the top', + 'Variables - bottom' => 'Variables - bottom', + 'Variables - table header' => 'Variables - table header', + 'Variables - table row' => 'Variables - table row', + 'Venezia' => 'Venezia', + 'Venezuela' => 'Venezuela', + 'Veracruz' => 'Veracruz', + 'Verbano-Cusio-Ossola' => 'Verbano-Cusio-Ossola', + 'Vercelli' => 'Vercelli', + 'Vermont' => 'Vermont', + 'Verona' => 'Verona', + 'Vibo Valentia' => 'Vibo Valentia', + 'Vicenza' => 'Vicenza', + 'Vietnam' => 'Vietnam', + 'View administration logs' => 'View administration logs', + 'Virginia' => 'Virginia', + 'Virtual Product Controller' => 'Virtual Product Controller', + 'Viterbo' => 'Viterbo', + 'Wakayama' => 'Wakayama', + 'Wallis-et-Futuna' => 'Wallis-et-Futuna', + 'Washington' => 'Washington', + 'West Java' => 'West Java', + 'West Kalimantan' => 'West Kalimantan', + 'West Nusa Tenggara' => 'West Nusa Tenggara', + 'West Sulawesi' => 'West Sulawesi', + 'West Sumatra' => 'West Sumatra', + 'West Virginia' => 'West Virginia', + 'Western Samoa' => 'Western Samoa', + 'Where the WYSIWYG editor is required' => 'Where the WYSIWYG editor is required', + 'Whitespace trim level of the generated HTML code (0 = none, 1 = medium, 2 = maximum)' => 'Whitespace trim level of the generated HTML code (0 = none, 1 = medium, 2 = maximum)', + 'Wisconsin' => 'Wisconsin', + 'Wyoming' => 'Wyoming', + 'Yamagata' => 'Yamagata', + 'Yamaguchi' => 'Yamaguchi', + 'Yamanashi' => 'Yamanashi', + 'Yemen' => 'Yemen', + 'Yen' => 'Yen', + 'Yogyakarta' => 'Yogyakarta', + 'You can now login at' => 'You can now login at', + 'You have lost your password
    \r\nPlease, change this password after your first connection' => 'You have lost your password
    \r\nPlease, change this password after your first connection', + 'You have lost your password
    \r\nYour new password is' => 'You have lost your password
    \r\nYour new password is', + 'Your account information on {config key="store_name"} has been changed.' => 'Your account information on {config key="store_name"} has been changed.', + 'Your new passord is : {$password}' => 'Your new passord is : {$password}', + 'Your new password' => 'Your new password', + 'Your new password for {config key="store_name"}' => 'Your new password for {config key="store_name"}', + 'Your order {$order_ref} at {config key="store_name"}' => 'Your order {$order_ref} at {config key="store_name"}', + 'Your subscription to %store newsletter' => 'Your subscription to {config key="store_name"} newsletter', + 'Yuan' => 'Yuan', + 'Yucatán' => 'Yucatán', + 'Yukon' => 'Yukon', + 'Zacatecas' => 'Zacatecas', + 'Zaire' => 'Zaire', + 'Zambia' => 'Zambia', + 'Zimbabwe' => 'Zimbabwe', + 'Zone - delete form' => 'Zone - delete form', + 'Złoty' => 'Złoty', + '[Firewall/Bruteforce] Number of allowed attemps' => '[Firewall/Bruteforce] Number of allowed attemps', + '[Firewall/Bruteforce] Time to wait between X attempts' => '[Firewall/Bruteforce] Time to wait between X attempts', + '[Firewall] Activate the firewall' => '[Firewall] Activate the firewall', + '[Firewall] Number of allowed attemps' => '[Firewall] Number of allowed attemps', + '[Firewall] Time to wait between X attempts' => '[Firewall] Time to wait between X attempts', + 'changing password email for' => 'changing password email for', + 'customer account - CSS stylesheet' => 'customer account - CSS stylesheet', + 'customer account - after javascript include' => 'customer account - after javascript include', + 'customer account - after javascript initialisation' => 'customer account - after javascript initialisation', + 'customer account - at the bottom' => 'customer account - at the bottom', + 'customer account - at the top' => 'customer account - at the top', + 'export of newsletter subscribers' => 'export of newsletter subscribers', + 'language selection page - CSS stylesheet' => 'language selection page - CSS stylesheet', + 'language selection page - after javascript include' => 'language selection page - after javascript include', + 'language selection page - after javascript initialisation' => 'language selection page - after javascript initialisation', + 'language selection page - at the bottom' => 'language selection page - at the bottom', + 'language selection page - at the top' => 'language selection page - at the top', + 'state - Edit JavaScript' => 'state - Edit JavaScript', + 'state - creation form' => 'state - creation form', + 'state - delete form' => 'state - delete form', + 'state-edit - at the top' => 'state-edit - at the top', + 'state-edit - bottom' => 'state-edit - bottom', + 'states - JavaScript' => 'states - JavaScript', + 'states - at the top' => 'states - at the top', + 'states - bottom' => 'states - bottom', + 'states - table header' => 'states - table header', + 'states - table row' => 'states - table row', + 'tax rule - Edit JavaScript' => 'tax rule - Edit JavaScript', + 'tax rule - create form' => 'tax rule - create form', + 'tax rule - delete form' => 'tax rule - delete form', + 'tinymce wysiwyg editor' => 'tinymce wysiwyg editor', + 'Đồng' => 'Đồng', + 'Гривна' => 'Гривна', + 'Default Tax Rule' => 'Default Tax Rule', + 'French 10% VAT (France only)' => 'French 10% VAT (France only)', + 'French 20% VAT for all European countries (metropolitan only)' => 'French 20% VAT for all European countries (metropolitan only)', + 'French 10% VAT (for metropolitan France only)' => 'French 10% VAT (for metropolitan France only)', +); diff --git a/setup/I18n/es_ES.php b/setup/I18n/es_ES.php new file mode 100644 index 00000000..7715cbbb --- /dev/null +++ b/setup/I18n/es_ES.php @@ -0,0 +1,1071 @@ + 'Fecha de caducidad de cookie "recuerdame", en segundos, para los usuarios de la administración', + '"Remember me" cookie expiration time, in seconds, for customer users' => 'Fecha de caducidad de cookie "Acuérdate de mi", en segundos, para los usuarios cliente', + '"Remember me" cookie name for administration users' => 'Nombre de la cookie "Recordarme" para los usuarios de administración', + '"Remember me" cookie name for customer users' => 'Nombre de la cookie "Recordarme" para los usuarios cliente', + '72h delivery' => 'entrega 72h', + 'A {config key="store_name"} account has been created for you' => 'Una {config key="store_name"} cuenta ha sido creada para ti', + 'API Configuration' => 'Configuración de API', + 'Address' => 'Dirección', + 'Address creation - CSS stylesheet' => 'Creación de dirección - hoja de estilos CSS', + 'Address creation - after javascript include' => 'Creación de dirección- después del include javascript', + 'Address creation - after javascript initialisation' => 'Creación de dirección - después de la inicialización de javascript', + 'Address creation - at the bottom' => 'Creación de dirección - en la parte inferior', + 'Address creation - at the bottom of the form' => 'Creación de dirección - en la parte inferior del formulario', + 'Address creation - at the top' => 'Creación de dirección - en la parte superior', + 'Address creation - at the top of the form' => 'Creación de dirección - en la parte superior del formulario', + 'Address update - CSS stylesheet' => 'Actualización de dirección - hoja de estilos CSS', + 'Address update - after javascript include' => 'Actualización de dirección - tras el include javascript', + 'Address update - after javascript initialisation' => 'Actualización de dirección - después de la inicialización de javascript', + 'Address update - at the bottom' => 'Actualización de dirección - en la parte inferior', + 'Address update - at the bottom of the form' => 'Actualización de dirección - en la parte inferior del formulario', + 'Address update - at the top' => 'Actualizar dirección - en la parte superior', + 'Address update - at the top of the form' => 'Actualizar dirección - en la parte superior del formulario', + 'Admin layout - After the main content' => 'Diseño de administración - Después del contenido principal', + 'Administatros list' => 'Lista de Administradores', + 'Administration profiles management' => 'Gestión de perfiles de administración', + 'Administrator - create form' => 'Administrador - formulario de creación', + 'Administrator - delete form' => 'Administrador - formulario de eliminación', + 'Administrator - update form' => 'Administrador - formulario de actualización', + 'Administrator list' => 'Lista de administrador', + 'Administrators - JavaScript' => 'Administradores - JavaScript', + 'Administrators - at the top' => 'Administradores - en la parte superior', + 'Administrators - bottom' => 'Administradores - inferior', + 'Administrators - header' => 'Administradores - cabecera', + 'Administrators - row' => 'Administradores - fila', + 'Advanced Configuration' => 'Configuración avanzada', + 'Advanced Configuration - Javascript' => 'Configuración avanzada - JavaScript', + 'Advanced configuration' => 'Configuración avanzada', + 'Afghanistan' => 'Afganistán', + 'Albania' => 'Albania', + 'Algeria' => 'Argelia', + 'All Products - CSS stylesheet' => 'Todos los productos - hoja de estilos CSS', + 'All Products - after javascript include' => 'Todos los productos - después de include javascript', + 'All Products - after javascript initialisation' => 'Todos los productos - después de la inicialización de javascript', + 'All Products - at the bottom' => 'Todos los productos - en la parte inferior', + 'All Products - at the top' => 'Todos los productos - en la parte superior', + 'Allow an administrator to recreate a lost password (1 = yes, 0 = no)' => 'Permite a un administrador recrear una contraseña perdida (1 = sí, 0 = no)', + 'Allow customers to change their email. 1 for yes, 0 for no' => 'Permitir a los clientes cambiar su correo electrónico. 1 para sí, 0 para no', + 'Allow negative product stock (1) or not (0)' => 'Permitir valores negativos producto (1) o no (0)', + 'Allow negative product stock (1) or not (0, default)' => 'Permite valores negativos producto (1) o no (valor por defecto 0,)', + 'Allow module installation from ZIP files.' => 'Permitir la instalación del módulo desde archivos ZIP.' , + 'Allow slash ended uri' => 'Permitir barra de fín de url', + 'An image carousel on your home page' => 'Un carrusel de imágenes en la página de inicio', + 'Andorra' => 'Andorra', + 'Angola' => 'Angola', + 'Antigua and Barbuda' => 'Antigua y Barbuda', + 'Api page - at bottom' => 'Página de la API - en la parte inferior', + 'Api page - at top' => 'Página de la API - en la parte superior', + 'Api page - in deletion form' => 'Página de Api - en formulario de eliminación', + 'Argentina' => 'Argentina', + 'Armenia' => 'Armenia', + 'Ask the customers to confirm their email, 1 for yes, 0 for no' => 'Preguntar al cliente para confirmar su correo electrónico, 1 para sí, 0 no', + 'Attribut - Edit JavaScript' => 'Atributo - editar JavaScript', + 'Attribut - add to all form' => 'Atributo - agregar a todos los formularios', + 'Attribut - create form' => 'Atributo - formulario de creación', + 'Attribut - delete form' => 'Atributo - formulario de eliminación', + 'Attribut - id delete form' => 'Atributo - Formulario de eliminación de id', + 'Attribut - remove to all form' => 'Atributo - quitar a todos', + 'Attribute edit - bottom' => 'Edición de atributos - inferior', + 'Attribute edit - top' => 'Editar atributo - superior', + 'Attribute value - create form' => 'Valor de atributo - formulario de creación', + 'Attributes - JavaScript' => 'Atributos - JavaScript', + 'Attributes - at the top' => 'Atributos - en la parte superior', + 'Attributes - bottom' => 'Atributos - inferior', + 'Attributes - table header' => 'Atributos - encabezado de tabla', + 'Attributes - table row' => 'Atributos - fila de la tabla', + 'Attributes value - table header' => 'Valor de atributos - encabezado de tabla', + 'Attributes value - table row' => 'Valor de atributos - fila de la tabla', + 'Australia' => 'Australia', + 'Austria' => 'Austria', + 'Azerbaijan' => 'Azerbaiyán', + 'Back-office export management' => 'Gestor de exportación de Back Office', + 'Back-office home page' => 'Página de inicio de back office', + 'Back-office search function' => 'Función de búsqueda de back office', + 'Bahamas' => 'Bahamas', + 'Bahrain' => 'Bahrein', + 'Bangladesh' => 'Bangladesh', + 'Barbados' => 'Barbados', + 'Base URL of the shop (e.g. http://www.yourshopdomain.com)' => 'Base URL de la tienda (por ejemplo http://www.yourshopdomain.com)', + 'Belarus' => 'Belarús', + 'Belgium' => 'Bélgica', + 'Belize' => 'Belice', + 'Benin' => 'Benin', + 'Bhutan' => 'Bhután', + 'Bielorussia' => 'Bielorusia', + 'Bolivia' => 'Bolivia', + 'Bosnia and Herzegovina' => 'Bosnia y Herzegovina', + 'Botswana' => 'Botswana', + 'Brand - Edit JavaScript' => 'Marca - editar JavaScript', + 'Brand - JavaScript' => 'Marca - JavaScript', + 'Brand - Tab' => 'Marca - Tab', + 'Brand - content' => 'Marca - contenido', + 'Brand - create form' => 'Marca - formulario de creación', + 'Brand - delete form' => 'Marca - formulario de eliminación', + 'Brand edit - bottom' => 'Editar marca - inferior', + 'Brand edit - right column bottom' => 'Edición de marca - al pie de la columna derecha', + 'Brand edit - right column top' => 'Edición de marca - encabezado de la columna derecha', + 'Brand edit - top' => 'Editar marca - superior', + 'Brand edit page - in the form' => 'Página de edición de marca - en formulario', + 'Brands - at the top' => 'Marcas - en parte superior', + 'Brands - bottom' => 'Marcas - inferior', + 'Brands - table header' => 'Marcas - encabezado de tabla', + 'Brands - table row' => 'Marcas - file de la tabla', + 'Brands management' => 'Gestión de marcas', + 'Brands page - CSS stylesheet' => 'Página de marcas - hoja de estilos CSS', + 'Brands page - after javascript include' => 'Página de marcas - después de inclusión de javascript', + 'Brands page - after the main content area' => 'Página de marcas - después el área de contenido principal', + 'Brands page - at the bottom' => 'Página de las marcas - en la parte inferior', + 'Brands page - at the bottom of the main area' => 'Página de las marcas - en la parte inferior del área principal', + 'Brands page - at the bottom of the sidebar' => 'Página de las marcas - en la parte inferior de la barra lateral', + 'Brands page - at the top' => 'Página de las marcas - en la parte superior', + 'Brands page - at the top of the main area' => 'Página de las marcas - en la parte inferior del área principal', + 'Brands page - at the top of the sidebar' => 'Página de las marcas - en la parte inferior de la barra lateral', + 'Brands page - before the main content area' => 'Página de marcas - antes del área de contenido principal', + 'Brands page - javascript initialization' => 'Página de marcas - inicialización de javascript', + 'Brands page - the body of the sidebar' => 'Página de marcas - el cuerpo de la barra lateral', + 'Brazil' => 'Brasil', + 'Brunei' => 'Brunei', + 'Bulgaria' => 'Bulgaria', + 'Burkina' => 'Burkina', + 'Burma' => 'Birmania', + 'Burundi' => 'Burundi', + 'Cambodia' => 'Camboya', + 'Cameroon' => 'Camerún', + 'Canceled' => 'Cancelado', + 'Cape Verde' => 'Cabo Verde', + 'Cart - CSS stylesheet' => 'Carrito - hoja de estilos CSS', + 'Cart - after javascript include' => 'Carro - después de inclusión javascript', + 'Cart - at the bottom' => 'Carrito - En la parte inferior', + 'Cart - at the top' => 'Carrito - En la parte superior', + 'Cart - javascript initialization' => 'Carro - inicialización de javascript', + 'Cart block' => 'Bloque de carrito', + 'Categories - JavaScript' => 'Categorías - JavaScript', + 'Categories - at the bottom of the catalog' => 'Categorías - en la parte inferior del catálogo', + 'Categories - at the top' => 'Categorías - en la parte superior', + 'Categories - bottom' => 'Categorías - inferior', + 'Categories - caption' => 'Categorías - título', + 'Categories - header' => 'Categorías - header', + 'Categories - row' => 'Categorías - fila', + 'Category' => 'Categoria', + 'Category - Edit JavaScript' => 'Categoría - edición JavaScript', + 'Category - Tab' => 'Categoría - Tab', + 'Category - content' => 'Categoría - contenido', + 'Category - contents table header' => 'Categoría - encabezado de tabla de contenido', + 'Category - contents table row' => 'Categoría - fila de la tabla de contenido', + 'Category - create form' => 'Formulario de creación de la categoría-', + 'Category - delete form' => 'Categoría - formulario de eliminación', + 'Category configuration' => 'Configuración de la categoría', + 'Category edit - bottom' => 'Editar categoría - inferior', + 'Category edit - right column bottom' => 'Edición de categoría - al pie de la columna derecha', + 'Category edit - right column top' => 'Edición de categoría - al tope de la columna derecha', + 'Category edit - top' => 'Categoría edición - superior', + 'Category page - CSS stylesheet' => 'Página de la categoría - hoja de estilos CSS', + 'Category page - after javascript include' => 'Página de la categoría - después de inclusión javascript', + 'Category page - after javascript initialisation' => 'Página de la categoría - después de la inicialización de javascript', + 'Category page - after the main content area' => 'Página de la categoría - después el área de contenido principal', + 'Category page - at the bottom' => 'Página de la categoría - en la parte inferior', + 'Category page - at the bottom of the main area' => 'Página de la categoría - en la parte inferior de la zona principal', + 'Category page - at the bottom of the sidebar' => 'Página de la categoría - en la parte inferior de la barra lateral', + 'Category page - at the top' => 'Página de la categoría - en la parte superior', + 'Category page - at the top of the main area' => 'Página de categoría - en la parte superior de la zona principal', + 'Category page - at the top of the sidebar' => 'Página de categoría - en la parte inferior de la barra lateral', + 'Category page - before the main content area' => 'Página de categoría - antes el área de contenido principal', + 'Category page - the body of the sidebar' => 'Página de categoría - el cuerpo de la barra lateral', + 'Central African Republic' => 'República Centroafricana', + 'Chad' => 'Chad', + 'Change password - CSS stylesheet' => 'Cambiar contraseña - hoja de estilos CSS', + 'Change password - after javascript include' => 'Cambiar contraseña - después de inclusión javascript', + 'Change password - after javascript initialisation' => 'Cambiar contraseña - después de la inicialización de javascript', + 'Change password - at the bottom' => 'Cambiar contraseña - en la parte inferior', + 'Change password - at the top' => 'Cambiar contraseña - en la parte superior', + 'Check available product stock (1) or ignore it (0) when displaying and changing ordered quantity' => 'Comprobar disponibilidad de stock de producto (1) o ignorar (0) cuando se muestra o cambia cantidad en pedido', + 'Check if a virtual product delivery module is enabled if at least one product is virtual' => 'Compruebe si un módulo de entrega de producto virtual está habilitado si es virtual por lo menos un producto', + 'Chile' => 'Chile', + 'China' => 'China', + 'Client edit - bottom' => 'Editar cliente - parte inferior', + 'Client edit - top' => 'Editar cliente - superior', + 'Colombia' => 'Colombia', + 'Comoros' => 'Comoras', + 'Compile templates assets automatically upon asset source change (1 = yes, 0 = no)' => 'Compilar las plantillas automáticamente en cada cambio de código fuente (1 = sí, 2 = no)', + 'Configuration' => 'Configuración', + 'Configuration - JavaScript' => 'Configuración - JavaScript', + 'Configuration - at the bottom of the catalog' => 'Configuración - en la parte inferior del catálogo', + 'Configuration - at the bottom of the shipping area' => 'Configuración - en la parte inferior de la zona de envío', + 'Configuration - at the bottom of the system area' => 'Configuración - en la parte inferior de la zona del sistema', + 'Configuration - at the top' => 'Configuración - en la parte superior', + 'Configuration - at the top of the catalog area' => 'Configuración - en la parte superior de la zona de catálogo', + 'Configuration - at the top of the shipping area' => 'Configuración - en la parte superior del área de envío', + 'Configuration - at the top of the system area' => 'Configuración - en la parte superior del área del sistema', + 'Configuration - bottom' => 'Configuración - parte inferior', + 'Configuration / Administrator' => 'Configuración / administrador', + 'Configuration / Area' => 'Configuración / área', + 'Configuration / Attribute' => 'Configuración / atributo', + 'Configuration / Cache' => 'Configuración / caché', + 'Configuration / Country' => 'Configuración / país', + 'Configuration / Currency' => 'Configuración / Moneda', + 'Configuration / Feature' => 'Configuración / Característica', + 'Configuration / Language' => 'Configuración / Idioma', + 'Configuration / Mailing-system' => 'Configuración / Sistema de correo', + 'Configuration / Message' => 'Configuración / Mensaje', + 'Configuration / Module' => 'Configuración / Módulo', + 'Configuration / Profile' => 'Configuración / Perfil', + 'Configuration / Shipping-zone' => 'Configuración / Zona de envío', + 'Configuration / System Log' => 'Configuración / Sistema de log', + 'Configuration / Tax' => 'Configuración / Impuestos', + 'Configuration / Template' => 'Configuración / Plantilla', + 'Configuration variables' => 'Variables de configuración', + 'Congo' => 'Congo', + 'Contact block' => 'Bloque de contacto', + 'Contact page - CSS stylesheet' => 'Página de contacto - hoja de estilos CSS', + 'Contact page - after javascript include' => 'Página de contacto - después del include de javascript', + 'Contact page - after javascript initialisation' => 'Página de contacto - después de la inicialización de javascript', + 'Contact page - at the bottom' => 'Página de contacto - en la parte inferior', + 'Contact page - at the bottom of the form' => 'Página de contacto - en la parte inferior del formulario', + 'Contact page - at the top' => 'Página de contacto - en la parte superior', + 'Contact page - at the top of the form' => 'Página de contacto - en la parte superior del formulario', + 'Contact page - if successful response' => 'Página de contacto - si la respuesta es exitosa', + 'Content' => 'Contenido', + 'Content - Edit JavaScript' => 'Contenido - Editar JavaScript', + 'Content - Tab' => 'Contenido - Pestaña', + 'Content - content' => 'Contenido - contenido', + 'Content - create form' => 'Contenido - formulario de creación', + 'Content - delete form' => 'Contenido - Formulario para eliminar', + 'Content edit - bottom' => 'Editar Contenido - inferior', + 'Content edit - right column bottom' => 'Edición de Contenido - al pie de la columna derecha', + 'Content edit - right column top' => 'Edición de Contenido - al tope de la columna derecha', + 'Content edit - top' => 'Editar contenido - superior', + 'Content page - CSS stylesheet' => 'Página de contacto - hoja de estilos CSS', + 'Content page - after javascript include' => 'Página de contacto - después del include de javascript', + 'Content page - after javascript initialisation' => 'Página de contacto - después de la inicialización de javascript', + 'Content page - after the main content area' => 'Página de contenido - después del área de contenido principal', + 'Content page - at the bottom' => 'Página de contacto - en la parte inferior', + 'Content page - at the bottom of the main area' => 'Página de contenido - en la parte inferior de la zona principal', + 'Content page - at the bottom of the sidebar' => 'Página de contenido - en la parte inferior de la barra lateral', + 'Content page - at the top' => 'Página de contacto - en la parte superior', + 'Content page - at the top of the main area' => 'Página de contenido - en la parte superior de la zona principal', + 'Content page - at the top of the sidebar' => 'Página de contenido - en la parte superior de la barra lateral', + 'Content page - before the main content area' => 'Página de contenido - antes del área de contenido principal', + 'Content page - the body of the sidebar' => 'Página de contenido - cuerpo de la barra lateral', + 'Contents - caption' => 'Contenido - leyenda', + 'Contents - header' => 'Contenido - encabezado', + 'Contents - row' => 'Contenido - fila', + 'Cook Islands' => 'Cook', + 'Costa Rica' => 'Costa Rica', + 'Countries - JavaScript' => 'Países - JavaScript', + 'Countries - at the top' => 'Países - en la parte superior', + 'Countries - bottom' => 'Países - parte inferior', + 'Countries - table header' => 'Países - encabezado de la tabla', + 'Countries - table row' => 'Países - fila de la tabla', + 'Country - Edit JavaScript' => 'País - editar JavaScript', + 'Country - create form' => 'País - formulario de creación', + 'Country - delete form' => 'País - formulario para eliminar', + 'Country edit - bottom' => 'Edición de pais - parte inferior', + 'Country edit - top' => 'Edición de país - parte superior', + 'Coupon' => 'Cupón', + 'Coupon - at the top' => 'Cupón - en la parte superior', + 'Coupon - bottom' => 'Cupón - parte inferior', + 'Coupon - create JavaScript' => 'Cupón - crear JavaScript', + 'Coupon - list JavaScript' => 'Cupón - enlistar JavaScript', + 'Coupon - list caption' => 'Cupón - titulo de la lista', + 'Coupon - table header' => 'Cupón - encabezado de tabla', + 'Coupon - table row' => 'Cupón - fila de la tabla', + 'Coupon - update JavaScript' => 'Cupón - actualizar JavaScript', + 'Coupon page - in deletion form' => 'Página de cupón - en formulario de eliminación', + 'Croatia' => 'Croacia', + 'Cuba' => 'Cuba', + 'Curency selection page - CSS stylesheet' => 'Página de selección de divisa - hoja de estilos CSS', + 'Curency selection page - after javascript include' => 'Página de selección de divisa - después de inclusión javascript', + 'Curency selection page - after javascript initialisation' => 'Página de selección de divisa - después de la inicialización de javascript', + 'Curency selection page - at the bottom' => 'Página de selección de divisa - en la parte inferior', + 'Curency selection page - at the top' => 'Página de selección de divisa - en la parte superior', + 'Currencies - JavaScript' => 'Divisas - JavaScript', + 'Currencies - at the top' => 'Divisas - en la parte superior', + 'Currencies - bottom' => 'Divisas - inferior', + 'Currencies - table header' => 'Divisas - encabezado de tabla', + 'Currencies - table row' => 'Divisas - fila de tabla', + 'Currency - Edit JavaScript' => 'Divisas - Editar javaScript', + 'Currency - create form' => 'Divisas - formulario de creación', + 'Currency - delete form' => 'Moneda - Formulario de eliminación', + 'Currency block' => 'Bloque de monedas', + 'Currency edit - bottom' => 'Editar Monedas - Pie', + 'Currency edit - top' => 'Editar Monedas - Cabecera', + 'Customer' => 'Cliente', + 'Customer - Edit' => 'Cliente - Editar', + 'Customer - Edit JavaScript' => 'Cliente - Editar JavaScript', + 'Customer - address create form' => 'Cliente - formulario crear dirección', + 'Customer - address delete form' => 'Cliente - Formulario borrar dirección', + 'Customer - address update form' => 'Cliente - formulario de actualización de dirección', + 'Customer - at the top' => 'Cliente - en la cabecera', + 'Customer - bottom' => 'Cliente - pie', + 'Customer - create form' => 'Cliente - formulario creación', + 'Customer - delete form' => 'Cliente - formulario eliminación', + 'Customer - order table header' => 'Cliente - cabecera tabla de pedidos', + 'Customer - order table row' => 'Cliente - celda tabla pedidos', + 'Customer account - additional information' => 'Cuenta de cliente - información adicional', + 'Customer account block' => 'Bloque de cuenta de cliente', + 'Customer title' => 'Estado civil cliente', + 'Customers - JavaScript' => 'Clientes - JavaScript', + 'Customers - caption' => 'Clientes - texto', + 'Customers - header' => 'Clientes - encabezado', + 'Customers - row' => 'Clientes - fila', + 'Cyprus' => 'Chipre', + 'Czech Republic' => 'República Checa', + 'Dashboard - at the top' => 'Dashboard - en la parte superior', + 'Dashboard - bottom' => 'Dashboard - fondo', + 'Dashboard - middle' => 'Dashboard - medio', + 'Data import / export' => 'Importación/ exportación de datos', + 'Default available stock when check-available-stock is set to 0.' => 'Cuando check-available-stock es 0 stock disponible por defecto.', + 'Default lang without translation' => 'Lenguaje por defecto sin traducción', + 'Delivery - After delivery module' => 'Entrega - después del módulo de entrega', + 'Delivery - CSS' => 'Entrega - CSS', + 'Delivery - additional product information' => 'Entrega - información adicional del producto', + 'Delivery - after addresse area' => 'Entrega - tras el área de dirección', + 'Delivery - after the information area' => 'Entrega - después del área de información', + 'Delivery - after the order summary' => 'Envío - después del resumen de pedido', + 'Delivery - at the bottom of information area' => 'Envío - en el pié del área de información', + 'Delivery - at the bottom of the footer' => 'Envío - En el pie del footer', + 'Delivery - at the top of the footer' => 'Envío - en la parte superior del footer', + 'Delivery - delivery address' => 'Envío - dirección de entrega', + 'Delivery - imprint' => 'Envío - imprimir', + 'Delivery - in the header' => 'Envío - en la cabecera', + 'Delivery choice - CSS stylesheet' => 'Opción de entrega - CSS', + 'Delivery choice - after javascript include' => 'Opción de entrega - después de incluir el javascript', + 'Delivery choice - after javascript initialisation' => 'Opción de entrega - despues de inicializar el javascript', + 'Delivery choice - at the bottom' => 'Elección de entrega - en el pie', + 'Delivery choice - at the bottom of the form' => 'Opción de entrega - en el pie del formulario', + 'Delivery choice - at the top' => 'Opción de entrega - en la cabecera', + 'Delivery choice - at the top of the form' => 'Opción de entrega - en la cabecera del formulario', + 'Delivery choice - extra area' => 'Opción de entrega - área extra', + 'Delivery choice - javascript' => 'Opción de entrega - javascript', + 'Delivery zone - Edit JavaScript' => 'Zona de entrega - Editar JavasCript', + 'Delivery zone - JavaScript' => 'Zona de entrega - JavaScript', + 'Delivery zone - at the top' => 'Zona de entrega - En la cabecera', + 'Delivery zone - bottom' => 'Zona de entrega - en el pie', + 'Delivery zone - table header' => 'Zona de entrega - en el encabezado de tabla', + 'Delivery zone - table row' => 'Zona de entrega - en la fila de la tabla', + 'Denmark' => 'Dinamarca', + 'Display and process prices with (0) or without (1) taxes.' => 'Mostrar y procesar precios con (0) o sin (1) impuestos.', + 'Distrito Federal' => 'Ciudad de México', + 'Djibouti' => 'Djibouti', + 'Document - Edit JavaScript' => 'Documento - edición JavaScript', + 'Document edit - bottom' => 'Edición de documentos - pie', + 'Document edit - top' => 'Edición de documentos - cabecera', + 'Dominica' => 'Dominica', + 'Dominican Republic' => 'República Dominicana', + 'Ecuador' => 'Ecuador', + 'Egypt' => 'Egipto', + 'El Salvador' => 'El Salvador', + 'Email html - layout - CSS' => 'Email HTML - Interfaz - CSS', + 'Email html - layout - footer' => 'Email HTML - Interfaz - pie', + 'Email html - order confirmation - after address' => 'Email HTML - confirmación de orden - después de la dirección', + 'Email html - order notification - order product' => 'Email HTML - notificación de orden - pedir producto', + 'Email txt - order confirmation - after address' => 'Email texto - confirmación de pedido - después de la dirección', + 'Email txt - order confirmation - after products' => 'Email texto - confirmación de pedido - después de los productos', + 'Email txt - order confirmation - before address' => 'Email texto - confirmación de pedido - antes de la dirección', + 'Email txt - order confirmation - before products' => 'Email texto - confirmación de pedido - antes de los productos', + 'Email txt - order confirmation - delivery address' => 'Email texto - confirmación de pedido - dirección de entrega', + 'Email txt - order confirmation - order product' => 'Email texto - confirmación de pedido - pedido de producto', + 'Email txt - order notification - after address' => 'Email texto - notificación de pedido - después de la dirección', + 'Enable (1) or disable (0) URL rewriting' => 'Activar(1) o desactivar(0) reescritura de URL', + 'Equatorial Guinea' => 'Guinea Ecuatorial', + 'Eritrea' => 'Eritrea', + 'Estonia' => 'Estonia', + 'Ethiopia' => 'Etiopía', + 'Euro' => 'Euro', + 'Export - JavaScript' => 'Exportación - JavaScript', + 'Export - table header' => 'Exportación - encabezado de tabla', + 'Export - table row' => 'Exportación - fila de la tabla', + 'Export modal or page - bottom' => 'Modal o página de exportación - inferior', + 'Export modal or page - top' => 'Modal o página de exportación - superior', + 'Exports - JavaScript' => 'Exportar JavaScript', + 'Exports - at the bottom of a category' => 'Exportar - en la parte inferior de una categoría', + 'Exports - at the bottom of column 1' => 'Exportar - en la parte inferior de la columna 1', + 'Exports - at the top' => 'Exportar - en la parte superior', + 'Feature - Edit JavaScript' => 'Característica - Editar JavaScript', + 'Feature - Value create form' => 'Característica - Formulario para crear valor', + 'Feature - add to all form' => 'Característica - Agregar a todos los formularios', + 'Feature - create form' => 'Característica - formulario crear', + 'Feature - delete form' => 'Característica - formulario borrar', + 'Feature - remove to all form' => 'Característica - eliminar todos los formularios', + 'Feature edit - bottom' => 'Editar Característica - inferior', + 'Feature edit - top' => 'Editar Característica - superior', + 'Features - JavaScript' => 'Característica - JavaScript', + 'Features - at the top' => 'Característica - ir arriba', + 'Features - bottom' => 'Característica - inferior', + 'Features - table header' => 'Característica - Encabezado de tabla', + 'Features - table row' => 'Característica - Fila de tabla', + 'Features value - table header' => 'Valor Característica - encabezado de tabla', + 'Features value - table row' => 'Valor Característica - fila de tabla', + 'Fiji' => 'Fiji', + 'File name of the 404 (not found) view in the current template (with extension, e.g. 404.html)' => 'Nombre de archivo de la vista 404 (no encontrado) en la plantilla actual (con la extensión, ej: 404.html)', + 'Filename of the error page' => 'Nombre de archivo de la página de error', + 'Finland' => 'Finlandia', + 'Folder' => 'Carpeta', + 'Folder - Edit JavaScript' => 'Carpeta - Editar JavaScript', + 'Folder - JavaScript' => 'Carpeta - JavaScript', + 'Folder - Tab' => 'Carpeta - Pestaña', + 'Folder - at the top' => 'Carpeta - ir arriba', + 'Folder - bottom' => 'Carpeta - abajo', + 'Folder - caption' => 'Carpeta - título', + 'Folder - content' => 'Carpeta - contenido', + 'Folder - header' => 'Carpeta - encabezado', + 'Folder - row' => 'Carpeta - fila', + 'Folder edit - bottom' => 'Editar carpeta - parte inferior', + 'Folder edit - right column bottom' => 'Edición de carpeta - al pie de la columna derecha', + 'Folder edit - right column top' => 'Edición de carpeta - al tope de la columna derecha', + 'Folder edit - top' => 'Edición de carpeta - superior', + 'Folder page - CSS stylesheet' => 'Página de la carpeta - hoja de estilos CSS', + 'Folder page - after javascript include' => 'Carpeta de página - después de incluir JavaScript', + 'Folder page - after javascript initialisation' => 'Carpeta de página - después de inicialización de JavaScript', + 'Folder page - after the main content area' => 'Carpeta de página - después del área de contenido principal', + 'Folder page - at the bottom' => 'Carpeta de página - al final', + 'Folder page - at the bottom of the main area' => 'Carpeta de página - al final del área principal', + 'Folder page - at the top' => 'Carpeta de página - en la parte superior', + 'Folder page - at the top of the main area' => 'Carpeta de página - en la parte superior del área principal', + 'Folder page - before the main content area' => 'Carpeta de página - antes del área de contenido principal', + 'France metropolitan' => 'Francia', + 'French 10% VAT' => 'Francés 10% de IVA', + 'French 20% VAT' => 'Francés 20% de IVA', + 'French Southern Territories' => 'Tierras Australes y Antárticas Francesas', + 'Front office integration' => 'Front office integración', + 'Gabon' => 'Gabón', + 'Gambia' => 'Gambia', + 'Georgia' => 'Georgia', + 'Germany' => 'Alemania', + 'Ghana' => 'Ghana', + 'Google Analytics block' => 'Bloque Google Analytics', + 'Greece' => 'Grecia', + 'Grenada' => 'Granada', + 'Guadeloupe' => 'Guadalupe', + 'Guatemala' => 'Guatemala', + 'Guinea' => 'Guinea', + 'Guinea-Bissau' => 'Guinea-Bissau', + 'Guyana' => 'Guyana', + 'Guyane Française' => 'Guayana Francesa', + 'HTML layout - CSS stylesheet' => 'Diseño HTML - hojas de estilo CSS', + 'HTML layout - after javascript include' => 'Diseño HTML - después de incluir javascript', + 'HTML layout - after the main content area' => 'Diseño HTML - después del área de contenido principal', + 'HTML layout - after the opening of the body tag' => 'Diseño HTML - después de la etiqueta body de apertura', + 'HTML layout - after the opening of the head tag' => 'Diseño HTML - después de la etiqueta head de apertura', + 'HTML layout - at the bottom of the header' => 'Diseño HTML - en la parte inferior de la cabecera', + 'HTML layout - at the top of the footer' => 'Diseño HTML - en la parte superior del pie de página', + 'HTML layout - at the top of the header' => 'Diseño HTML - en la parte superior de la cabecera', + 'HTML layout - before the end body tag' => 'Diseño HTML - antes de la etiqueta body de cierre', + 'HTML layout - before the end of the head tag' => 'Diseño HTML - antes de la etiqueta head de cierre', + 'HTML layout - before the main content area' => 'Diseño HTML - antes el área de contenido principal', + 'HTML layout - bottom of the footer' => 'Diseño HTML - parte inferior del pie de página', + 'HTML layout - footer body' => 'Diseño HTML - cuerpo del pie de página', + 'HTML layout - javascript initialization' => 'Diseño HTML - inicialización de JavaScript', + 'HTML layout - primary navigation' => 'Diseño HTML - navegación principal', + 'HTML layout - secondary navigation' => 'Diseño HTML - navegación secundaria', + 'Haiti' => 'Haití', + 'Home - JavaScript' => 'Inicio - JavaScript', + 'Home - at the top' => 'Inicio - en la parte superior', + 'Home - block' => 'Inicio - bloque', + 'Home - bottom' => 'Inicio - fondo', + 'Home page - CSS stylesheet' => 'Página de inicio - hoja de estilos CSS', + 'Home page - after javascript include' => 'Página de inicio - después de incluir JavaScript', + 'Home page - after javascript initialisation' => 'Página de inicio - después de la inicialización de JavaScript', + 'Home page - main area' => 'Página de inicio - Área Principal', + 'Honduras' => 'Honduras', + 'Hong Kong' => 'Hong Kong', + 'Hong Kong Dollar' => 'Dólar de Hong Kong', + 'Hook - Edit JavaScript' => 'Hook - editar JavaScript', + 'Hook edit - bottom' => 'Edición de Hook - inferior', + 'Hook edit - top' => 'Edición de Hook - superior', + 'Hook positions' => 'Posiciones de hook', + 'Hooks' => 'Hooks', + 'Hooks - JavaScript' => 'Hooks - JavaScript', + 'Hooks - at the top' => 'Hooks - en la parte superior', + 'Hooks - bottom' => 'Hooks - inferior', + 'Hooks - table header' => 'Hooks - encabezado de tabla', + 'Hooks - table row' => 'Hooks - fila de la tabla', + 'Hooks management' => 'Gestión de Hooks', + 'How document files are delivered in the web space (symlink or copy)' => 'Cómo los documento son enviados en el espacio de la web (enlace o copia)', + 'How original (full resolution) images are delivered in the web space (symlink or copy)' => 'Cómo se entregan imágenes originales (resolución completa) en el espacio de la web (enlace o copia)', + 'Hungary' => 'Hungría', + 'Iceland' => 'Islandia', + 'Image - Edit JavaScript' => 'Imagen - Editar JavaScript', + 'Image edit - bottom' => 'Edición de imagen - parte inferior', + 'Image edit - top' => 'Edición de imagen - parte superior', + 'Import - table header' => 'Importar - encabezado de tabla', + 'Import - table row' => 'Importar - fila de la tabla', + 'India' => 'India', + 'Indonesia' => 'Indonesia', + 'Invoice - After delivery module' => 'Factura - Después de módulo de entrega de factura', + 'Invoice - After payment module' => 'Factura - Después de módulo de pago de factura', + 'Invoice - CSS' => 'Factura - CSS', + 'Invoice - additional product information' => 'Factura - información adicional del producto', + 'Invoice - after addresse area' => 'Factura - después del área de dirección', + 'Invoice - after product listing' => 'Factura - después de listado de productos', + 'Invoice - after the information area' => 'Factura - después del área de información', + 'Invoice - after the order summary' => 'Factura - después del resumen de la orden', + 'Invoice - at the bottom of information area' => 'Factura - en la parte inferior del área de la información', + 'Invoice - at the bottom of the footer' => 'Factura - en la parte inferior del pie de página', + 'Invoice - at the top of the footer' => 'Factura - en la parte superior del pie de página', + 'Invoice - delivery address' => 'Factura - dirección de envío', + 'Invoice - imprint' => 'Factura - pie de imprenta', + 'Invoice - in the header' => 'Factura - en la cabecera', + 'Invoice choice - CSS stylesheet' => 'Opción de factura - hoja de estilos CSS', + 'Invoice choice - after javascript include' => 'Opción de factura - después de incluir javascript', + 'Invoice choice - after javascript initialisation' => 'Opción de factura - después de la inicialización de javascript', + 'Invoice choice - at the bottom' => 'Opción de factura - en la parte inferior de la factura', + 'Invoice choice - at the top' => 'Opción de factura - en la parte superior', + 'Invoice choice - delivery address' => 'Opción de factura - dirección de envío', + 'Invoice choice - extra payment zone' => 'Opción de factura - zona de pago extra', + 'Iran' => 'Irán', + 'Iraq' => 'Iraq', + 'Ireland' => 'Irlanda', + 'Israel' => 'Israel', + 'Italy' => 'Italia', + 'Ivory Coast' => 'Costa de Marfil', + 'Jamaica' => 'Jamaica', + 'Japan' => 'Japón', + 'Jordan' => 'Jordania', + 'Kazakhstan' => 'Kazajstán', + 'Kenya' => 'Kenia', + 'Kiribati' => 'Kiribati', + 'Kuwait' => 'Kuwait', + 'Kyrgyzstan' => 'Kirguistán', + 'Language - create form' => 'Idioma - formulario de creación', + 'Languages - JavaScript' => 'Idiomas - JavaScript', + 'Languages - at the top' => 'Idiomas - en la parte superior', + 'Languages - bottom' => 'Idiomas - parte inferior', + 'Languages - delete form' => 'Idiomas - Formulario de borrar', + 'Languages block' => 'Bloque de idiomas', + 'Laos' => 'Laos', + 'Latvia' => 'Letonia', + 'Layout - Before the main content' => 'Diseño - antes el contenido principal', + 'Layout - CSS' => 'Diseño - CSS', + 'Layout - JavaScript' => 'Diseño - JavaScript', + 'Layout - after footer' => 'Diseño - después de pie de página', + 'Layout - after top bar' => 'Diseño - después de la barra superior', + 'Layout - after top menu' => 'Diseño - después del menú principal', + 'Layout - at the bottom of the top bar' => 'Diseño - en la parte inferior de la barra superior', + 'Layout - at the top of the top bar' => 'Diseño - en la parte superior de la barra superior', + 'Layout - before footer' => 'Diseño - antes del pie de página', + 'Layout - before top menu' => 'Diseño - antes del menú principal', + 'Layout - before topbar' => 'Diseño - antes de la barra superior', + 'Layout - in footer' => 'Diseño - en el pie de página', + 'Layout - in the menu catalog' => 'Diseño - en el menú de catálogo', + 'Layout - in the menu configuration' => 'Diseño - en el menú de configuración', + 'Layout - in the menu customers' => 'Diseño - en el menú de cliente', + 'Layout - in the menu folders' => 'Diseño - en el menú de carpetas', + 'Layout - in the menu modules' => 'Diseño - en el menú de módulos', + 'Layout - in the menu orders' => 'Diseño - en el menú de pedidos', + 'Layout - in the menu tools' => 'Diseño - en el menú de herramientas', + 'Layout - in top menu items' => 'Diseño - en la parte superior del menú artículos', + 'Layout - inside top bar' => 'Diseño - en la barra superior', + 'Leave the default configuration of session' => 'Abandonde la configuración predeterminada de la sesión', + 'Lebanon' => 'Líbano', + 'Lesotho' => 'Lesoto', + 'Liberia' => 'Liberia', + 'Libya' => 'Libia', + 'Liechtenstein' => 'Liechtenstein', + 'Life time of the cart cookie in the customer browser, in seconds' => 'Tiempo de vida de la cookie del carro en el navegador del cliente, en segundos', + 'Life time of the session cookie in the customer browser, in seconds' => 'Tiempo de vida de la cookie de la sesión en el navegador del cliente, en segundos', + 'Links block' => 'Bloque de enlaces', + 'Lithuania' => 'Lituania', + 'Logging system configuration' => 'Configuración de sistema de registro', + 'Login page - CSS stylesheet' => 'Página de inicio de sesión - hoja de estilos CSS', + 'Login page - after javascript include' => 'Página de inicio de sesión - después de incluir JavaScript', + 'Login page - after javascript initialisation' => 'Página de inicio de sesión - después de la inicialización de JavaScript', + 'Login page - at the bottom' => 'Página de inicio de sesión - en la parte inferior', + 'Login page - at the bottom of the form' => 'Página de inicio de sesión - en la parte inferior del formulario', + 'Login page - at the bottom of the main area' => 'Página de inicio de sesión - en la parte inferior del área principal', + 'Login page - at the top' => 'Página de inicio de sesión - en la parte superior', + 'Login page - at the top of the form' => 'Página de inicio de sesión - en la parte superior del formulario', + 'Login page - at the top of the main area' => 'Página de inicio de sesión - en la parte superior del área principal', + 'Logs - JavaScript' => 'Registros - JavaScript', + 'Logs - at the top' => 'Registros - en la parte superior', + 'Logs - bottom' => 'Registros - inferior', + 'Lost password - CSS stylesheet' => 'Contraseña perdida - hoja de estilos CSS', + 'Lost password - after javascript include' => 'Contraseña perdida - después de incluir javascript', + 'Lost password - at the bottom' => 'Contraseña perdida - en la parte inferior', + 'Lost password - at the bottom of the form' => 'Contraseña perdida - en la parte inferior del formulario', + 'Lost password - at the top' => 'Contraseña perdida - en la parte superior', + 'Lost password - at the top of the form' => 'Contraseña perdida - en la parte superior del formulario', + 'Lost password - javascript initialization' => 'Contraseña perdida - inicialización de JavaScript', + 'Luxembourg' => 'Luxemburgo', + 'Macedonia' => 'Macedonia', + 'Madagascar' => 'Madagascar', + 'Mail sent after a subscription to newsletter' => 'Correo enviado después de la suscripción al boletín de noticias', + 'Mail sent to an administrator who requested a new password' => 'Correo enviado a un administrador que ha solicitado una nueva contraseña', + 'Mail sent to the customer when its account is created by an administrator in the back-office' => 'Correo enviado al cliente cuando se crea su cuenta por un administrador en el back-office', + 'Mail sent to the customer when its password or email is changed in the back-office' => 'Correo enviado al cliente cuando se cambia su contraseña o correo electrónico en el back-office', + 'Mailing system - JavaScript' => 'Sistema de correo - JavaScript', + 'Mailing system - at the top' => 'Sistema de correo - en la parte superior', + 'Mailing system - bottom' => 'Sistema de correo - fondo', + 'Malawi' => 'Malawi', + 'Malaysia' => 'Malasia', + 'Maldives' => 'Maldivas', + 'Mali' => 'Malí', + 'Malta' => 'Malta', + 'Marshall Islands' => 'Marshall', + 'Martinique' => 'Martinica', + 'Mauritania' => 'Mauritania', + 'Mauritius' => 'Mauricio', + 'Mayotte' => 'Mayotte', + 'Message - Edit JavaScript' => 'Mensaje - Editar JavaScript', + 'Message - create form' => 'Mensaje - formulario de creación', + 'Message - delete form' => 'Mensaje - formulario de borrado', + 'Message edit - bottom' => 'Editar mensaje - base', + 'Message edit - top' => 'Editar mensaje - tope', + 'Message sent to the shop owner when a new order is placed' => 'Mensaje enviado al propietario de la tienda cuando se envía una nueva orden', + 'Messages - JavaScript' => 'Mensajes - JavaScript', + 'Messages - at the top' => 'Mensajes - al tope', + 'Messages - bottom' => 'Mensajes - base', + 'Messages - table header' => 'Mensajes - encabezado de la tabla', + 'Messages - table row' => 'Mensajes - fila de la tabla', + 'Mexico' => 'Méjico', + 'Micronesia' => 'Micronesia', + 'Mini cart' => 'Mini tarjeta', + 'Miss' => 'Señorita', + 'Miss_short' => 'Señorita', + 'Misses' => 'Señora', + 'Mister' => 'Señor', + 'Module - Edit JavaScript' => 'Módulo - Editar JavaScript', + 'Module - configuration' => 'Módulo - configuración', + 'Module - configuration JavaScript' => 'Módulo - configuración de JavaScript', + 'Module edit - bottom' => 'Edición de módulo - base', + 'Module edit - top' => 'Edición de módulo - tope', + 'Modules - JavaScript' => 'Módulos - JavaScript', + 'Modules - at the top' => 'Módulos - al inicio', + 'Modules - bottom' => 'Módulos - base', + 'Modules - table header' => 'Módulos - encabezado de la tabla', + 'Modules - table row' => 'Módulos - fila de la tabla', + 'Modules maagement' => 'Administración de módulos', + 'Modules management' => 'Administración de módulos', + 'Moldova' => 'Moldova', + 'Monaco' => 'Mónaco', + 'Mongolia' => 'Mongolia', + 'Morocco' => 'Marruecos', + 'Mozambique' => 'Mozambique', + 'Mr.' => 'Sr.', + 'Mrs' => 'Sra', + 'Name of the active PDF template' => 'Nombre de la plantilla PDF activa', + 'Name of the active back-office template' => 'Nombe de la plantilla del administrador activo', + 'Name of the active front-office template' => 'Nombre de la plantilla activa de recepción', + 'Name of the active mailing template' => 'Nombre de la plantilla de correo activa', + 'Name of the cart cookie' => 'Nombre de la cookie del carrito', + 'Name of the delivery view in the current PDF template (without extension)' => 'Nombre de la vista de entrega en la plantilla PDF actual (sin extensión)', + 'Name of the graphic driver used by the Imagine library (see https://imagine.readthedocs.org)' => 'Nombre del controlador gráfico usado por la Librería Imagine (ver https://imagine.readthedocs.org)', + 'Name of the invoice view in the current PDF template (without extension)' => 'Nombre de la vista para la factura en la plantilla PDF actual (sin extensión)', + 'Name of the template view returned when an obsolete (or inactive) product URL is invoked' => 'Nombre de la plantilla regresada cuando se llama una URL obsoleta (o inactiva) de un producto', + 'Name the cart cookie' => 'Nombre la cookie de carrito', + 'Namibia' => 'Namibia', + 'Nauru' => 'Nauru', + 'Navigation block' => 'Bloque de navegación', + 'Nepal' => 'Nepal', + 'Netherlands' => 'Países Bajos', + 'New Products block' => 'Bloque de nuevos productos', + 'New York' => 'Nueva York', + 'New Zealand' => 'Nueva Zelandia', + 'New order {$order_ref} placed on {config key="store_name"}' => 'Nueva orden {$order_ref} ubicada en {tecla config = "store_name"}', + 'New password request on %store' => 'Nueva contraseña solicitada en {config key="store_name"}', + 'Newsletter block' => 'Bloque del boletín de noticias', + 'Newsletter page - CSS stylesheet' => 'Página del boletín de noticias - hoja de estilos CSS', + 'Newsletter page - after javascript include' => 'Página del boletín de noticias - después de incluir JavaScript', + 'Newsletter page - after javascript initialisation' => 'Página del boletín de noticias - después de la inicialización de JavaScript', + 'Newsletter page - at the bottom' => 'Página del boletín de noticias - en la parte inferior', + 'Newsletter page - at the top' => 'Página del boletín de noticias - en la parte superior', + 'Newsletter subscription confirmation mail' => 'Confirmación de suscripción por correo al boletín', + 'Newsletter unsubscribe page - CSS stylesheet' => 'Página de baja del boletín - Hoja de estilos CSS', + 'Newsletter unsubscribe page - after javascript include' => 'Página de baja del boletín - después de incluir JavaScript', + 'Newsletter unsubscribe page - after javascript initialisation' => 'Página de baja del boletín - después de la inicialización de JavaScript', + 'Newsletter unsubscribe page - at the bottom' => 'Página de baja del boletín - al pie', + 'Newsletter unsubscribe page - at the top' => 'Página de baja del boletín - en la parte superior', + 'Nicaragua' => 'Nicaragua', + 'Niger' => 'Níger', + 'Nigeria' => 'Nigeria', + 'Niue' => 'Niue', + 'North Korea' => 'Corea del Norte', + 'Norway' => 'Noruega', + 'Not paid' => 'No pagados', + 'Nouvelle-Calédonie' => 'Nouvelle-Calédonie', + 'Number by default of results per page for customer list' => 'Número predeterminado de resultados por página para la lista de clientes', + 'Number by default of results per page for order list' => 'Número predeterminado de resultados por página para la lista de pedidos', + 'Number by default of results per page for product list' => 'Número predeterminado de resultados por página para la lista de productos', + 'Oman' => 'Omán', + 'Order' => 'Pedido', + 'Order - After closing product row' => 'Orden - después de cerrar la fila de producto', + 'Order - After product list' => 'Orden - después de la lista de productos', + 'Order - Before product list' => 'Orden - antes de la lista de productos', + 'Order - Before starting product row' => 'Orden - antes de comenzar la fila de producto', + 'Order - Edit JavaScript' => 'Orden - editar JavaScript', + 'Order - Tab' => 'Orden - Pestaña', + 'Order - bill bottom' => 'Orden - parte inferior de la cuenta', + 'Order - bill top' => 'Orden - parte superior de la cuenta', + 'Order - cart bottom' => 'Orden - parte inferior del carro', + 'Order - cart top' => 'Orden - parte superior del carro', + 'Order - content' => 'Orden - contenido', + 'Order - customer information bottom' => 'Orden - parte inferior de información del cliente', + 'Order - delivery module bottom' => 'Orden - parte inferior del módulo de entrega', + 'Order - payment module bottom' => 'Orden - parte inferior del módulo de pago', + 'Order - product list' => 'Orden - lista de productos', + 'Order - table header' => 'Orden - encabezado de tabla', + 'Order - table row' => 'Orden - fila de la tabla', + 'Order confirmation - after the order summary' => 'Confirmación de la orden - después del Resumen de la orden', + 'Order confirmation sent to the customer' => 'Confirmación de la orden enviada al cliente', + 'Order details - CSS stylesheet' => 'Detalles de la Orden - hoja de estilos CSS', + 'Order details - additional delivery information' => 'Detalles de la Orden - información adicional del envío', + 'Order details - additional information' => 'Detalles de la Orden - información adicional', + 'Order details - additional invoice information' => 'Detalles de la Orden - información adicional de la factura', + 'Order details - additional product information' => 'Detalles de la Orden - información adicional del producto', + 'Order details - after addresses' => 'Detalles de la Orden - después de direcciones', + 'Order details - after delivery address' => 'Detalles de pedido - después de la dirección de entrega', + 'Order details - after global information' => 'Detalles de la orden - después de la información global', + 'Order details - after invoice address' => 'Detalles de pedido - después de la dirección de facturación', + 'Order details - after javascript include' => 'Detalles de la orden - después de incluir JavaScript', + 'Order details - after product' => 'Detalles de la orden - después del producto', + 'Order details - after products' => 'Detalles de la orden - después de los productos', + 'Order details - after products list' => 'Detalles de la orden - después de la lista de productos', + 'Order details - at the bottom' => 'Detalles de la orden - en la parte inferior', + 'Order details - at the top' => 'Detalles de la orden - en la parte superior', + 'Order details - before products list' => 'Detalles de la orden - antes de lista de productos', + 'Order details - delivery address' => 'Pedir detalles - dirección de envío', + 'Order details - invoice address' => 'Detalles de la orden - dirección de factura', + 'Order details - javascript initialization' => 'Detalles de la Orden - inicialización de JavaScript', + 'Order edit - bottom' => 'Editar Orden - parte inferior', + 'Order edit - delivery address' => 'Editar Orden - dirección de envío', + 'Order edit - displayed after product information' => 'Edición de Pedido - se muestra después de la información de producto', + 'Order edit - order product table header' => 'Edición de Pedido - encabezado de la tabla de pedido de producto', + 'Order edit - order product table row' => 'Edición de Pedido - fila de la tabla del pedido de producto', + 'Order edit - top' => 'Edición de Pedido - al tope', + 'Order failed - CSS stylesheet' => 'Pedido erróneo - Hoja de Estilos CSS', + 'Order failed - after javascript include' => 'Pedido erróneo - después de incluir JavaScript', + 'Order failed - after javascript initialisation' => 'Pedido erróneo - después de la inicialización de JavaScript', + 'Order failed - at the bottom' => 'Pedido erróneo - al pie', + 'Order failed - at the top' => 'Pedido erróneo - al tope', + 'Orders - JavaScript' => 'Pedidos - JavaScript', + 'Orders - at the top' => 'Pedidos - encabezado', + 'Orders - bottom' => 'Pedidos - pie de página', + 'Orders - table header' => 'Pedidos - encabezado de tabla', + 'Orders - table row' => 'Pedidos - fila de tabla', + 'Page 404 - CSS stylesheet' => 'Página 404 - CSS Hoja de estilos', + 'Page 404 - after javascript include' => 'Página 404 - después de incluir JavaScript', + 'Page 404 - after javascript initialisation' => 'Página 404 - después de inicializar JavaScript', + 'Page 404 - content area' => 'Página 404 - área de contenido', + 'Paid' => 'Pagado', + 'Pakistan' => 'Pakistán', + 'Panama' => 'Panamá', + 'Papua Nueva Guinea' => 'Papua Nueva Guinea', + 'Paraguay' => 'Paraguay', + 'Path to the directory where documents are stored' => 'Ruta al directorio donde los documentos estén guardados', + 'Path to the directory where images are stored' => 'Ruta al directorio donde las imágenes estén guardadas', + 'Pay by cheque' => 'Pagar con Cheque', + 'Payment failed - CSS stylesheet' => 'Pago erróneo - Hoja de Estilos CSS', + 'Payment failed - after javascript include' => 'Pago erróneo - después de incluir JavaScript', + 'Payment failed - javascript initialization' => 'Pago erróneo - inicialización de JavaScript', + 'Payment gateway - CSS stylesheet' => 'Pasarela de pago - Hoja de estilos CSS', + 'Payment gateway - after javascript include' => 'Pasarela de pago - después de incluir JavaScript', + 'Payment gateway - after javascript initialisation' => 'Pasarela de pago - después de inicializar JavaScript', + 'Payment gateway - javascript' => 'Pasarela de pago - JavaScript', + 'Payment gateway - main area' => 'Pasarela de pago - área principal', + 'Peru' => 'Perú', + 'Philippines' => 'Filipinas', + 'Placed order - CSS stylesheet' => 'Orden registrada - Hoja de estilo CSS', + 'Placed order - after javascript include' => 'Orden registrada - después del javascript include', + 'Placed order - after javascript initialisation' => 'Orden registrada - después de la inicialización de Javascript', + 'Placed order - main area' => 'Orden registrada - área principal', + 'Poland' => 'Polonia', + 'Polynésie française' => 'Polinesia Francesa', + 'Portugal' => 'Portugal', + 'Processing' => 'Procesando', + 'Product' => 'Producto', + 'Product - Edit JavaScript' => 'Producto - Editar JavaScript', + 'Product - Tab' => 'Producto - Pestaña', + 'Product - accessories table header' => 'Producto - encabezado de la tabla accesoria', + 'Product - accessories table row' => 'Producto - fila de la tabla de accesorios', + 'Product - after combinations' => 'Producto - después de las combinaciones', + 'Product - at the bottom of a product combination' => 'Producto - al pie de la combinación de un producto', + 'Product - attributes table header' => 'Producto - encabezado de la tabla de atributos', + 'Product - attributes table row' => 'Producto - fila de la tabla de atributos', + 'Product - before combinations' => 'Producto - después de las combinaciones', + 'Product - categories table header' => 'Producto - encabezado de la tabla de categorías', + 'Product - categories table row' => 'Producto - fila de la tabla de categorías', + 'Product - combination delete form' => 'Producto - Formulario para borrar combinaciones', + 'Product - combinations list caption' => 'Producto - título de la lista de combinaciones', + 'Product - content' => 'Producto - contenido', + 'Product - contents table header' => 'Producto - contenidos del encabezado de tabla', + 'Product - contents table row' => 'Producto - contenidos de la fila de la tabla', + 'Product - create form' => 'Producto - formulario de creación', + 'Product - delete form' => 'Producto - formulario de borrado', + 'Product - details pricing form' => 'Producto - formato de detalles del precio', + 'Product - details promotion form' => 'Producto - formulario de detalles de la promoción', + 'Product - features table row' => 'Producto - fila de la tabla de características', + 'Product - features-table-header' => 'Producto - encabezado de la tabla de características', + 'Product - folders table header' => 'Producto - encabezado de la tabla de carpetas', + 'Product - folders table row' => 'Producto - fila de la tabla de carpetas', + 'Product - stock edit form' => 'Producto - Editar formulario de stock', + 'Product edit - bottom' => 'Editar producto - parte inferior', + 'Product edit - right column bottom' => 'Edición de producto - al pie de la columna derecha', + 'Product edit - right column top' => 'Edición de producto - encabezado de la columna derecha', + 'Product edit - top' => 'Editar producto - parte superior', + 'Product loop - at the bottom' => 'Ciclo del producto - en la parte inferior', + 'Product loop - at the top' => 'Ciclo del producto - en la parte superior', + 'Product page - CSS stylesheet' => 'Página de producto - hoja de estilos CSS', + 'Product page - On the bottom of the form' => 'Página del producto - en la parte inferior del formulario', + 'Product page - On the top of the form' => 'Página de producto - en la parte superior del formulario', + 'Product page - additional information' => 'Página de producto - información adicional', + 'Product page - after javascript include' => 'Página de producto - después de incluir JavaScript', + 'Product page - after javascript initialisation' => 'Página de producto - después de la inicialización de Javascript', + 'Product page - at the bottom' => 'Página de producto - en la parte inferior', + 'Product page - at the bottom of the detail area' => 'Página de producto - en la parte inferior del área de detalle', + 'Product page - at the top' => 'Página de producto - en la parte superior', + 'Product page - at the top of the detail' => 'Página de producto - en la parte superior del detalle', + 'Product page - photo gallery' => 'Página de producto - Galería de fotos', + 'Products - caption' => 'Productos - leyenda', + 'Products - header' => 'Productos - encabezado', + 'Products - row' => 'Productos - fila', + 'Products offer block' => 'Bloque de oferta de productos', + 'Profile - Edit JavaScript' => 'Perfil - editar JavaScript', + 'Profile - create form' => 'Perfil - formulario de alta', + 'Profile - delete form' => 'Perfil - formulario de borrado', + 'Profile - table header' => 'Perfil - encabezado de tabla', + 'Profile - table row' => 'Perfil - fila de la tabla', + 'Profile edit - bottom' => 'Editar Perfil - parte inferior', + 'Profile edit - top' => 'Editar Perfil - parte superior', + 'Profiles - JavaScript' => 'Perfiles - JavaScript', + 'Profiles - at the top' => 'Perfiles - en la parte superior', + 'Profiles - bottom' => 'Perfiles - parte inferior', + 'Qatar' => 'Qatar', + 'Refunded' => 'Reembolsado', + 'Register - CSS stylesheet' => 'Registro - hoja de estilos CSS', + 'Register - after javascript include' => 'Registro - después de incluir JavaScript', + 'Register - after javascript initialisation' => 'Registro - después de la inicialización de JavaScript', + 'Register - at the bottom' => 'Registro - en la parte inferior', + 'Register - at the bottom of the form' => 'Registro - en la parte inferior del formulario', + 'Register - at the top' => 'Registro - en la parte superior', + 'Register - at the top of the form' => 'Registro - en la parte superior del formulario', + 'Romania' => 'Rumania', + 'Russia' => 'Rusia', + 'Rwanda' => 'Ruanda', + 'Réunion(La)' => 'Réunion(la)', + 'Saint Barthélemy' => 'San Bartolomé', + 'Saint Kitts and Nevis' => 'San Cristóbal', + 'Saint Lucia' => 'Santa Lucía', + 'Saint Martin (French part)' => 'San Martín (parte francesa)', + 'Saint Vincent and the Grenadines' => 'San Vicente y las Granadinas', + 'Sale - CSS stylesheet' => 'Venta - Hoja de estilos CSS', + 'Sale - after javascript include' => 'Venta - después de incluir JavaScript', + 'Sale - after the main content area' => 'Venta - después del área de contenido principal', + 'Sale - at the bottom' => 'Venta - al pie', + 'Sale - at the bottom of the main area' => 'Venta - al pie del área principal', + 'Sale - at the top' => 'Venta - encabezado', + 'Sale - at the top of the main area' => 'Venta - encabezado del área principal', + 'Sale - before the main content area' => 'Venta - antes del área de contenido principal', + 'Sale - create form' => 'Venta - formulario de creación', + 'Sale - delete form' => 'Venta - formulario de borrado', + 'Sale - javascript initialization' => 'Venta - inicialización de JavaScript', + 'Sale edit - bottom' => 'Editar Venta - parte inferior', + 'Sale edit - top' => 'Editar Venta - parte superior', + 'Sale edit page - javascript last call block' => 'Página de edición de Venta - última bloque de llamada JavaScript', + 'Sales - JavaScript' => 'Ventas - JavaScript', + 'Sales - at the bottom' => 'Ventas - en la parte inferior', + 'Sales - at the top' => 'Ventas - en la parte superior', + 'Sales - table header' => 'Ventas - encabezado de tabla', + 'Sales - table row' => 'Ventas - fila de la tabla', + 'Sales management' => 'Administración de ventas', + 'San Marino' => 'San Marino', + 'Sao Tome and Principe' => 'Santo Tomé y Príncipe', + 'Saudi Arabia' => 'Arabia Saudita', + 'Search' => 'Buscar', + 'Search - JavaScript' => 'Búsqueda - JavaScript', + 'Search - at the top' => 'Búsqueda - al inicio', + 'Search - bottom' => 'Búsqueda - base', + 'Search block' => 'Bloque de búsqueda', + 'Search page - CSS stylesheet' => 'Página de búsqueda - Hoja de Estilos en Cascada', + 'Search page - after javascript include' => 'Página de búsqueda - después de incluir JavaScript', + 'Search page - after javascript initialisation' => 'Página de búsqueda - después de inicializar JavaScript', + 'Secret key for form CSRF token' => 'Clave secreta para el token CSRF del formulario', + 'Send a confirmation email to newsletter subscribers (1 = yes, 0 = no)' => 'Enviar un correo de confirmación a los suscriptores del boletín (1 = sí, 0 = no)', + 'Senegal' => 'Senegal', + 'Sent' => 'Enviado', + 'Seychelles' => 'Seychelles', + 'Shipping configuration' => 'Configuración de envío', + 'Shipping configuration - Edit' => 'Configuración de envío - Editar', + 'Shipping configuration - Edit JavaScript' => 'Configuración de envío - Editar JavaScript', + 'Shipping configuration - JavaScript' => 'Configuración de envío - JavaScript', + 'Shipping configuration - at the top' => 'Configuración de envío - al inicio', + 'Shipping configuration - bottom' => 'Configuración de envío - base', + 'Shipping configuration - country delete form' => 'Configuración de envío - formulario de borrado de país', + 'Shipping configuration - create form' => 'Configuración de envío - formulario de creación', + 'Shipping configuration - delete form' => 'Configuración de envío - formulario de borrado', + 'Shipping configuration - table header' => 'Configuración de envío - encabezado de tabla', + 'Shipping configuration - table row' => 'Configuración de envío - fila de tabla', + 'Shipping configuration edit - bottom' => 'Configuración de envío - base', + 'Shipping configuration edit - top' => 'Configuración de envío - inicio', + 'Shipping zones edit - bottom' => 'Edición zonas de envío - base', + 'Shipping zones edit - top' => 'Edición zonas de envío - inicio', + 'Show error message instead of a white page on a server error' => 'Mostrar mensaje de error en lugar de una página en blanco cuando ocurre un error de servidor', + 'Sierra Leone' => 'Sierra Leona', + 'Singapore' => 'Singapur', + 'Sitemap - at the bottom' => 'Mapa de sitio - en la base', + 'Slovakia' => 'Eslovaquia', + 'Slovenia' => 'Eslovenia', + 'Smarty template engine integration' => 'Integración del motor de plantillas Smarty', + 'Social Networks block' => 'Bloque de Redes Sociales', + 'Solomon Islands' => 'Salomón', + 'Somalia' => 'Somalia', + 'South Africa' => 'Sudáfrica', + 'South Korea' => 'Corea del Sur', + 'Spain' => 'España', + 'Sri Lanka' => 'Sri Lanka', + 'St Pierre et Miquelon' => 'San Pedro y Miquelón', + 'Store Information - JavaScript' => 'Información de tienda - JavaScript', + 'Store information configuration' => 'Configuración de la información de tienda', + 'Sudan' => 'Sudán', + 'Suriname' => 'Suriname', + 'Swaziland' => 'Swazilandia', + 'Sweden' => 'Suecia', + 'Switzerland' => 'Suiza', + 'Syria' => 'Siria', + 'System - logs JavaScript' => 'Sistema - registros de JavaScript', + 'Tab SEO - bottom' => 'Ficha SEO - abajo', + 'Tab SEO - top' => 'Ficha SEO - arriba', + 'Tab SEO - update form' => 'Ficha SEO - formato de actualización', + 'Tab document - bottom' => 'Ficha de documento - abajo', + 'Tab document - top' => 'Ficha de documento - arriba', + 'Tab image - bottom' => 'Pestaña de imagen - abajo', + 'Tab image - top' => 'Pestaña de imagen - arriba', + 'Tajikistan' => 'Tayikistán', + 'Tanzania' => 'Tanzanía', + 'Tax - Edit JavaScript' => 'Editar JavaScript', + 'Tax - create form' => 'Impuesto - formulario de creación', + 'Tax - delete form' => 'Impuesto - formulario de borrado', + 'Tax edit - bottom' => 'Editar Impuesto - base', + 'Tax edit - top' => 'Editar Impuesto - parte superior', + 'Tax rule edit - bottom' => 'Editar regla de Impuesto - base', + 'Tax rule edit - top' => 'Edición de regla de impuesto - parte superior', + 'Tax rules configuration' => 'Configuración de las reglas de impuestos', + 'Taxes - update form' => 'Impuestos - formulario de actualización', + 'Taxes rules - JavaScript' => 'Reglas de impuestos - JavaScript', + 'Taxes rules - at the top' => 'Reglas de impuestos - en la parte superior', + 'Taxes rules - bottom' => 'Reglas de impuestos - parte inferior', + 'Template - Edit JavaScript' => 'Plantilla - editar JavaScript', + 'Template - attributes table header' => 'Plantilla - cabecera de la tabla de atributos', + 'Template - attributes table row' => 'Plantilla - fila de la tabla de atributos', + 'Template - create form' => 'Plantilla - formulario de creación', + 'Template - delete form' => 'Plantilla - formulario de borrado', + 'Template - features table row' => 'Plantilla - fila de la tabla de características', + 'Template - features-table-header' => 'Plantilla - encabezado de tabla de características', + 'Template edit - bottom' => 'Editar plantilla - parte inferior', + 'Template edit - top' => 'Editar plantilla - parte superior', + 'Templates - JavaScript' => 'Plantillas - JavaScript', + 'Templates - at the top' => 'Plantillas - en la parte superior', + 'Templates - bottom' => 'Plantillas - parte inferior', + 'Templates - table header' => 'Plantillas - encabezado de tabla', + 'Templates - table row' => 'Plantillas - fila de la tabla', + 'Thailand' => 'Tailandia', + 'The ID of the \'Terms & Conditions\' content.' => 'El ID de los contenidos de \'Términos y condiciones\'.', + 'The ID of the folder containing your information pages : terms, imprint, ...' => 'El ID de la carpeta que contiene sus páginas de información: términos, impresión,...', + 'The Vatican' => 'El Vatican', + 'The default quality (in %) of the generated images' => 'La calidad por defecto (en %) de las imágenes generadas', + 'The minimum length required for an administrator password' => 'La longitud mínima de la contraseña de administrador', + 'The path (relative to the default back-office template) to the image used when no flag image can be found for a country' => 'La ruta (relativa a la plantilla de back office por defecto) a la imagen que se utiliza cuando no se puede encontrar ninguna imagen de la bandera para un país', + 'The path to the document cache directory in the web space' => 'La ruta al directorio de caché de documentos en el espacio web', + 'The path to the image cache directory in the web space' => 'La ruta de acceso para el directorio de caché de imagen en el espacio web', + 'TinyMCE WYSIWYG editor' => 'Editor TinyMCE WYSIWYG', + 'Togo' => 'Togo', + 'Tonga' => 'Tonga', + 'Tools - JavaScript' => 'Herramientas - JavaScript', + 'Tools - at the bottom of column 1' => 'Herramientas - en la parte inferior de la columna 1', + 'Tools - at the top' => 'Herramientas - en la parte superior', + 'Tools - at the top of the column' => 'Herramientas - en la parte superior de la columna', + 'Tools - bottom' => 'Herramientas - parte inferior', + 'Tools panel' => 'Panel de herramientas', + 'Translations' => 'Traducciones', + 'Translations - JavaScript' => 'Traducciones - JavaScript', + 'Trinidad and Tobago' => 'Trinidad y Tabago', + 'Tunisia' => 'Túnez', + 'Turkey' => 'Turquía', + 'Turkmenistan' => 'Turkmenistán', + 'Tuvalu' => 'Tuvalu', + 'UK Pound' => 'Libra Reino Unido', + 'Ukraine' => 'Ucrania', + 'United Arab Emirates' => 'Emiratos Árabes Unidos', + 'United Kingdom' => 'Reino Unido', + 'United States Dollar' => 'Dólar Estadunidense', + 'Update customer account - CSS stylesheet' => 'Actualización de cuenta del cliente - Hoja de estilos CSS', + 'Update customer account - after javascript include' => 'Actualización de cuenta del cliente - después de incluir JavaScript', + 'Update customer account - after javascript initialisation' => 'Actualización de cuenta de cliente - después de inicializar JavaScript', + 'Update customer account - at the bottom' => 'Actualización de cuenta de cliente - al pie', + 'Update customer account - at the bottom of the form' => 'Actualización de cuenta de cliente - al pie del formulario', + 'Update customer account - at the top' => 'Actualización de cuenta de cliente - encabezado', + 'Update customer account - at the top of the form' => 'Actualización de cuenta de cliente - encabezado del formulario', + 'Uruguay' => 'Uruguay', + 'Use a persistent cookie to keep track of customer cart' => 'Usa una \'cookie\' persistente para mantener el trayecto del carrito del cliente', + 'Uzbekistan' => 'Uzbekistán', + 'Vanuatu' => 'Vanuatu', + 'Variable - Edit JavaScript' => 'Variable - Editar JavaScript', + 'Variable - create form' => 'Variable - formulario de creación', + 'Variable - delete form' => 'Variable - formulario de borrado', + 'Variable edit - bottom' => 'Editar variable - parte inferior', + 'Variable edit - top' => 'Editar variable - parte superior', + 'Variables - JavaScript' => 'Variables - JavaScript', + 'Variables - at the top' => 'Variables - en la parte superior', + 'Variables - bottom' => 'Variables - parte inferior', + 'Variables - table header' => 'Variables - encabezado de tabla', + 'Variables - table row' => 'Variables - fila de la tabla', + 'Venezuela' => 'Venezuela', + 'Vietnam' => 'Viet Nam', + 'View administration logs' => 'Ver logs de administración', + 'Virtual Product Controller' => 'Controlador de producto virtual', + 'Wallis-et-Futuna' => 'Wallis-et-Futuna', + 'Western Samoa' => 'Samoa', + 'Where the WYSIWYG editor is required' => 'Donde se requiere el editor WYSIWYG', + 'Whitespace trim level of the generated HTML code (0 = none, 1 = medium, 2 = maximum)' => 'Espacio en blanco del ajuste nivel del código HTML generado (0 = ninguna, 1 = medio, 2 = máximo)', + 'Yemen' => 'Yemen', + 'You can now login at' => 'Ahora puede entrar', + 'You have lost your password
    \r\nPlease, change this password after your first connection' => 'Ha perdido su contraseña < br / > \r\nPor favor, cambiar esta contraseña después de su primera conexión', + 'You have lost your password
    \r\nYour new password is' => 'Ha perdido su contraseña < br / > \r\nSu nueva contraseña es', + 'Your account information on {config key="store_name"} has been changed.' => 'La información de su cuenta en {tecla config = "store_name"} ha sido cambiada.', + 'Your new passord is : {$password}' => 'Su nueva contraseña es: {$password}', + 'Your new password' => 'Su nueva contraseña', + 'Your new password for {config key="store_name"}' => 'Su nueva contraseña para {tecla config = "store_name"}', + 'Your order {$order_ref} at {config key="store_name"}' => 'Su orden {$order_ref} en {tecla config = "store_name"}', + 'Your subscription to %store newsletter' => 'Tu suscripción al boletín de {config key="store_name"}', + 'Zaire' => 'Zaire', + 'Zambia' => 'Zambia', + 'Zimbabwe' => 'Zimbabue', + 'Zone - delete form' => 'Zona - formulario de borrado', + '[Firewall/Bruteforce] Number of allowed attemps' => '[Firewall/Bruteforce] Número de intentos permitidos', + '[Firewall/Bruteforce] Time to wait between X attempts' => '[Firewall/Bruteforce] Tiempo de espera entre X intentos', + '[Firewall] Activate the firewall' => '[Firewall] Activar el firewall', + '[Firewall] Number of allowed attemps' => '[Firewall] Número de intentos permitidos', + '[Firewall] Time to wait between X attempts' => '[Firewall] Tiempo de espera entre X intentos', + 'changing password email for' => 'cambio de correo electrónico contraseña para', + 'customer account - CSS stylesheet' => 'cuenta de cliente - hoja de estilos CSS', + 'customer account - after javascript include' => 'cuenta de cliente - después de incluir JavaScript', + 'customer account - after javascript initialisation' => 'cuenta de cliente - después de la inicialización de JavaScript', + 'customer account - at the bottom' => 'cuenta de cliente - en la parte inferior', + 'customer account - at the top' => 'cuenta de cliente - en la parte superior', + 'export of newsletter subscribers' => 'exportación de los suscriptores del boletín de noticias', + 'language selection page - CSS stylesheet' => 'página de selección de idioma - hoja de estilos CSS', + 'language selection page - after javascript include' => 'página de selección de idioma - después de incluir JavaScript', + 'language selection page - after javascript initialisation' => 'página de selección de idioma - después de la inicialización de JavaScript', + 'language selection page - at the bottom' => 'página de selección de idioma - en la parte inferior', + 'language selection page - at the top' => 'página de selección de idioma - en la parte superior', + 'state - Edit JavaScript' => 'estado - Editar JavaScript', + 'state - creation form' => 'estado - formulario de creación', + 'state - delete form' => 'estado - formulario de borrado', + 'state-edit - at the top' => 'estado - editar - encabezado', + 'state-edit - bottom' => 'estado - al pie', + 'states - JavaScript' => 'estados - JavaScript', + 'states - at the top' => 'estados - encabezado', + 'states - bottom' => 'estados - al pie', + 'states - table header' => 'estados - encabezado de tabla', + 'states - table row' => 'estados - fila de tabla', + 'tax rule - Edit JavaScript' => 'regla de impuesto - Editar JavaScript', + 'tax rule - create form' => 'regla de impuesto - formulario de creación', + 'tax rule - delete form' => 'regla de impuesto - formulario de borrado', + 'tinymce wysiwyg editor' => 'editor tinymce wysiwyg', + 'Default Tax Rule' => 'Regla impositiva predeterminada', + 'French 10% VAT (France only)' => '10% de IVA francés (solo Francia metropolitana)', + 'French 20% VAT for all European countries (metropolitan only)' => 'IVA francés al 20% para todos los países de Europa (solo países metropolitanos)', + 'French 10% VAT (for metropolitan France only)' => 'IVA francés al 10% (solo para Francia metropolitana)', +]; diff --git a/setup/I18n/fa_IR.php b/setup/I18n/fa_IR.php new file mode 100644 index 00000000..fa2d7e17 --- /dev/null +++ b/setup/I18n/fa_IR.php @@ -0,0 +1,311 @@ + 'تحویل 72 ساعته', + 'API Configuration' => 'تنظیمات API', + 'Address' => 'نشانی', + 'Address creation - CSS stylesheet' => 'ایجاد آدرس - فایل CSS', + 'Address creation - after javascript include' => 'ایجاد آدرس - پس از include جاوا اسکریپت', + 'Address creation - after javascript initialisation' => 'ایجاد آدرس - پس از initial جاوا اسکریپت', + 'Address creation - at the bottom' => 'ایجاد آدرس - در پایین', + 'Address creation - at the bottom of the form' => 'ایجاد آدرس - در پایین فرم', + 'Address creation - at the top' => 'ایجاد آدرس - در بالای', + 'Address creation - at the top of the form' => 'ایجاد آدرس - در بالای فرم', + 'Administrator - create form' => 'مدیر - فرم ایجاد', + 'Administrator - delete form' => 'مدیر - فرم حذف', + 'Administrator - update form' => 'مدیر - فرم به روز رسانی', + 'Administrator list' => 'لیست مدیر', + 'Administrators - JavaScript' => 'مدیران - جاوا اسکریپت', + 'Administrators - at the top' => 'مدیران - در بالا', + 'Administrators - bottom' => 'مدیران - پایین', + 'Administrators - header' => 'مدیران - هدر', + 'Administrators - row' => 'مدیران - ردیف', + 'Advanced Configuration' => 'پیکربندی پیشرفته', + 'Advanced Configuration - Javascript' => 'پیکربندی پیشرفته - جاوا اسکریپت', + 'Advanced configuration' => 'پیکربندی پیشرفته', + 'Afghanistan' => 'افغانستان', + 'Albania' => 'آلبانی', + 'Algeria' => 'الجزایر', + 'Andorra' => 'آندورا', + 'Angola' => 'آنگولا', + 'Antigua and Barbuda' => 'آنتیگوا و باربودا', + 'Argentina' => 'آرژانتین', + 'Armenia' => 'ارمنستان', + 'Attributes - table row' => 'ویژگی های - ردیف جدول', + 'Australia' => 'استراليا', + 'Austria' => 'اتریش', + 'Azerbaijan' => 'آذربایجان', + 'Bahamas' => 'باهاما', + 'Bahrain' => 'بحرین', + 'Bangladesh' => 'بنگلادش', + 'Barbados' => 'باربادوس', + 'Belarus' => 'بلاروس', + 'Belgium' => 'بلژیک', + 'Belize' => 'بلیز', + 'Benin' => 'بنین', + 'Bhutan' => 'بوتان', + 'Bolivia' => 'بولیوی', + 'Bosnia and Herzegovina' => 'بوسنی و هرزگوین', + 'Botswana' => 'بوتسوانا', + 'Brazil' => 'برزيل', + 'Brunei' => 'برونئی', + 'Bulgaria' => 'بلغارستان', + 'Burkina' => 'بورکینا', + 'Burma' => 'برمه', + 'Burundi' => 'بوروندی', + 'Cambodia' => 'کامبوج', + 'Cameroon' => 'کامرون', + 'Canceled' => 'لغو شده', + 'Category' => 'دسته‌بندی', + 'Category - contents table row' => 'دسته بندی - ردیف جدول محتویات', + 'Chad' => 'چاد', + 'Chile' => 'شیلی', + 'China' => 'چین', + 'Colombia' => 'کلمبیا', + 'Comoros' => 'کومور', + 'Configuration' => 'پیکربندی', + 'Configuration / Administrator' => 'پیکربندی / مدیران', + 'Configuration / Area' => 'پیکربندی / منطقه', + 'Configuration / Attribute' => 'پیکربندی / خصوصیت', + 'Configuration / Cache' => 'پیکربندی / حافظه موقت', + 'Configuration / Country' => 'پیکربندی / کشور', + 'Configuration / Currency' => 'پیکربندی / ارز', + 'Configuration / Feature' => 'پیکربندی / ویژگی', + 'Configuration / Language' => 'پیکربندی / زبان', + 'Configuration / Mailing-system' => 'پیکربندی / سیستم ایمیل', + 'Configuration / Message' => 'پیکربندی / پیام', + 'Configuration / Module' => 'پیکربندی / ماژول', + 'Configuration / Profile' => 'پیکربندی / حساب کاربری', + 'Configuration / Shipping-zone' => 'پیکربندی / نواحی حمل و نقل', + 'Configuration / System Log' => 'پیکربندی / گزارش سیستم', + 'Configuration / Tax' => 'پیکربندی / مالیات', + 'Configuration / Template' => 'پیکربندی / قالب', + 'Configuration variables' => 'پیکربندی متغییرها', + 'Congo' => 'کنگو', + 'Contact block' => 'بلوک تماس با ما', + 'Content' => 'محتوا', + 'Content edit - bottom' => 'ویرایش محتوا - پایین', + 'Cook Islands' => 'جزایر کوک', + 'Costa Rica' => 'کاستاریکا', + 'Coupon' => 'کوپن', + 'Croatia' => 'کرواسی', + 'Cuba' => 'کوبا', + 'Currency edit - top' => 'ویرایش واحد پول - بالا', + 'Customer' => 'مشتری', + 'Customer title' => 'عنوان مشتری', + 'Cyprus' => 'قبرس', + 'Czech Republic' => 'جمهوری چک', + 'Dashboard - at the top' => 'پیشخوان - در بالا', + 'Dashboard - bottom' => 'پیشخوان - پایین', + 'Dashboard - middle' => 'پیشخوان - وسط', + 'Data import / export' => 'ورود/خروج اطلاعات', + 'Delivery zone - table row' => 'منطقه تحویل - ردیف جدول', + 'Denmark' => 'دانمارک', + 'Djibouti' => 'جیبوتی', + 'Document - Edit JavaScript' => 'سند - ویرایش جاوا اسکریپت', + 'Document edit - bottom' => 'ویرایش نوشتار - پایین', + 'Document edit - top' => 'ویرایش نوشتار - بالا', + 'Dominica' => 'دومینیکا', + 'Dominican Republic' => 'جمهوری دومینیکن', + 'Ecuador' => 'اکوادور', + 'Egypt' => 'مصر', + 'El Salvador' => 'السالوادور', + 'Equatorial Guinea' => 'گینه استوایی', + 'Eritrea' => 'اریتره', + 'Estonia' => 'استونی', + 'Ethiopia' => 'اتیوپی', + 'Euro' => 'یورو', + 'Fiji' => 'فیجی', + 'Finland' => 'فنلاند', + 'Folder' => 'پوشه', + 'Gabon' => 'گابن', + 'Gambia' => 'گامبیا', + 'Georgia' => 'گرجستان', + 'Germany' => 'آلمان', + 'Ghana' => 'غنا', + 'Greece' => 'یونان', + 'Grenada' => 'گراندا', + 'Guadeloupe' => 'گوادلوپ', + 'Guatemala' => 'گواتمالا', + 'Guinea' => 'گینه', + 'Guinea-Bissau' => 'گینه بیسائو', + 'Guyana' => 'گویان', + 'Haiti' => 'هائیتی', + 'Honduras' => 'هندوراس', + 'Hong Kong' => 'هنگ کنگ', + 'Hook - Edit JavaScript' => 'قلاب - ویرایش جاوا اسکریپت', + 'Hook - create form' => 'قلاب - فرم ایجاد', + 'Hook - delete form' => 'قلاب - فرم حذف', + 'Hook edit - bottom' => 'قلاب ویرایش - پایین', + 'Hook edit - top' => 'قلاب ویرایش - بالا', + 'Hook positions' => 'موقعیت‌های قلاب', + 'Hooks' => 'قلاب‌ها', + 'Hooks - JavaScript' => 'قلاب‌ها - جاوا اسکریپت', + 'Hungary' => 'مجارستان', + 'Iceland' => 'ایسلند', + 'Image - Edit JavaScript' => 'تصویر - ویرایش جاوا اسکریپت', + 'India' => 'هند', + 'Indonesia' => 'اندونزی', + 'Iran' => 'ایران', + 'Iraq' => 'عراق', + 'Ireland' => 'ایرلند', + 'Israel' => 'اسرائیل', + 'Italy' => 'ايتاليا', + 'Ivory Coast' => 'ساحل عاج', + 'Jamaica' => 'جامائیکا', + 'Japan' => 'ژاپن', + 'Jordan' => 'اردن', + 'Kazakhstan' => 'قزاقستان', + 'Kenya' => 'کنیا', + 'Kiribati' => 'کیریباتی', + 'Kuwait' => 'کویت', + 'Kyrgyzstan' => 'قرقیزستان', + 'Laos' => 'لائوس', + 'Latvia' => 'لتونی', + 'Lebanon' => 'لبنان', + 'Lesotho' => 'لسوتو', + 'Liberia' => 'لیبریا', + 'Libya' => 'لیبی', + 'Liechtenstein' => 'لیختن اشتاین', + 'Lithuania' => 'لیتوانی', + 'Luxembourg' => 'لوکزامبورگ', + 'Macedonia' => 'مقدونیه', + 'Madagascar' => 'ماداگاسکار', + 'Malawi' => 'مالاوی', + 'Malaysia' => 'مالزی', + 'Maldives' => 'مالدیو', + 'Mali' => 'مالی', + 'Malta' => 'مالت', + 'Marshall Islands' => 'جزایر مارشال', + 'Martinique' => 'مارتینیک', + 'Mauritania' => 'موریتانی', + 'Mauritius' => 'موریس', + 'Mayotte' => 'مایوت', + 'Mexico' => 'مکزیک', + 'Micronesia' => 'میکرونزی', + 'Miss' => 'خانم', + 'Miss_short' => 'خانم', + 'Mister' => 'آقا', + 'Moldova' => 'مولداوی', + 'Monaco' => 'موناکو', + 'Mongolia' => 'مغولستان', + 'Morocco' => 'مراکش', + 'Mozambique' => 'موزامبیک', + 'Mr.' => 'آقای', + 'Mrs' => 'خانم', + 'Namibia' => 'نامیبیا', + 'Nauru' => 'نائورو', + 'Nepal' => 'نپال', + 'Netherlands' => 'هلند', + 'New York' => 'تالش', + 'New Zealand' => 'نيوزلند', + 'Nicaragua' => 'نیکاراگوئه', + 'Niger' => 'نیجر', + 'Nigeria' => 'نیجریه', + 'Niue' => 'نیو', + 'North Korea' => 'کره شمالی', + 'Norway' => 'نروژ', + 'Not paid' => 'پرداخت نشده', + 'Oman' => 'عمان', + 'Order' => 'سفارش', + 'Paid' => 'پرداخت شده', + 'Pakistan' => 'پاکستان', + 'Panama' => 'پاناما', + 'Paraguay' => 'پاراگوئه', + 'Pay by cheque' => 'پرداخت با چک', + 'Peru' => 'پرو', + 'Philippines' => 'فیلیپین', + 'Poland' => 'لهستان', + 'Portugal' => 'پرتغال', + 'Processing' => 'پردازش', + 'Product' => 'محصول', + 'Qatar' => 'قطر', + 'Refunded' => 'برگشت وجه شده', + 'Romania' => 'رومانی', + 'Russia' => 'روسیه', + 'Rwanda' => 'رواندا', + 'Saint Kitts and Nevis' => 'سنت کیتس و نویس', + 'Saint Lucia' => 'سنت لوسیا', + 'Sales management' => 'مدیریت حراج', + 'San Marino' => 'سن مارینو', + 'Saudi Arabia' => 'عربستان سعودی', + 'Search' => 'جستجو', + 'Senegal' => 'سنگال', + 'Sent' => 'ارسال', + 'Seychelles' => 'سیشل', + 'Shipping configuration' => 'پیکربندی حمل و نقل', + 'Shipping configuration - Edit' => 'پیکربندی حمل و نقل - ویرایش', + 'Sierra Leone' => 'سیرالئون', + 'Singapore' => 'سنگاپور', + 'Sitemap - at the bottom' => 'نقشه سایت - در پایین', + 'Slovakia' => 'اسلواکی', + 'Slovenia' => 'اسلوونی', + 'Solomon Islands' => 'جزایر سلیمان', + 'Somalia' => 'سومالی', + 'South Africa' => 'آفریقای جنوبی', + 'South Korea' => 'کره جنوبی', + 'Spain' => 'اسپانیا', + 'Sri Lanka' => 'سریلانکا', + 'Sudan' => 'سودان', + 'Suriname' => 'سورینام', + 'Swaziland' => 'سوازیلند', + 'Sweden' => 'سوئد', + 'Switzerland' => 'سوئیس', + 'Syria' => 'سوریه', + 'Tajikistan' => 'تاجیکستان', + 'Tanzania' => 'تانزانیا', + 'Togo' => 'توگو', + 'Tonga' => 'تونگا', + 'Tools - JavaScript' => 'ابزارها - جاوا اسکریپت', + 'Translations' => 'ترجمه‌ها', + 'Tunisia' => 'تونس', + 'Turkey' => 'ترکیه', + 'Turkmenistan' => 'ترکمنستان', + 'Tuvalu' => 'تووالو', + 'UK Pound' => 'پوند انگلستان', + 'Uganda' => 'اوگاندا', + 'Ukraine' => 'اکراین', + 'United Arab Emirates' => 'امارات متحده عربی', + 'United Kingdom' => 'انگلستان', + 'United States Dollar' => 'دلار آمریکا', + 'Update customer account - CSS stylesheet' => 'به روز رسانی حساب مشتری - CSS', + 'Update customer account - after javascript include' => 'به روز رسانی حساب مشتری - پس از include شدن جاوا اسکریپت', + 'Update customer account - after javascript initialisation' => 'به روز رسانی حساب مشتری - پس از intial شدن جاوا اسکریپت', + 'Update customer account - at the bottom' => 'به روز رسانی حساب مشتری - در قسمت پایین', + 'Update customer account - at the bottom of the form' => 'به روز رسانی حساب مشتری - در قسمت پایین فرم', + 'Update customer account - at the top' => 'به روز رسانی حساب مشتری - در قسمت بالا', + 'Update customer account - at the top of the form' => 'به روز رسانی حساب مشتری - در قسمت بالای فرم', + 'Uruguay' => 'اروگوئه', + 'Use a persistent cookie to keep track of customer cart' => 'استفاده از کوکی ماندگار برای پیگیری سبد خرید مشتریان', + 'Uzbekistan' => 'ازبکستان', + 'Vanuatu' => 'وانواتو', + 'Variable - Edit JavaScript' => 'متغیر - ویرایش جاوا اسکریپت', + 'Variable - create form' => 'متغیر - ایجاد فرم', + 'Variable - delete form' => 'متغير - حذف فرم', + 'Variable edit - bottom' => 'ویرایش متغیر - پایین', + 'Variable edit - top' => 'ویرایش متغیر - بالا', + 'Variables - JavaScript' => 'متغیرهای - جاوا اسکریپت', + 'Variables - at the top' => 'متغیرهای - در بالای', + 'Variables - bottom' => 'متغیرهای - پایین', + 'Variables - table header' => 'متغیرهای - عنوان جدول', + 'Variables - table row' => 'متغیرهای - ردیف جدول', + 'Venezuela' => 'ونزوئلا', + 'Vietnam' => 'ویتنام', + 'View administration logs' => 'مشاهده لاگ مدیریت', + 'Virtual Product Controller' => 'کنترل کننده محصولات مجازی', + 'Wallis-et-Futuna' => 'والیس و فوتونا', + 'Western Samoa' => 'ساموآ غربی', + 'Where the WYSIWYG editor is required' => 'جایی که ویرایشگر دیداری لازم است', + 'Yemen' => 'یمن', + 'You can now login at' => 'شما می‌توانید وارد شوید در', + 'You have lost your password
    \r\nPlease, change this password after your first connection' => 'رمزعبور شما از دست رفته است
    \r\nلطفا پس از اولین ارتباط رمزعبور را تغییر دهید', + 'You have lost your password
    \r\nYour new password is' => 'روزعبور شما از دست رفته است
    \r\nرمزعبور جدید شما هست:', + 'Your account information on {config key="store_name"} has been changed.' => 'اطلاعات حساب شما در {config key="store_name"} تغییر کرد.', + 'Your new passord is : {$password}' => 'رمزعبور جدید شما: {$password}', + 'Your new password' => 'رمز عبور جدید شما', + 'Your new password for {config key="store_name"}' => 'رمزعبور جدید شما برای {config key="store_name"}', + 'Your order {$order_ref} at {config key="store_name"}' => 'سفارش شما {$order_ref} در {config key="store_name"}', + 'Zaire' => 'زئیر', + 'Zambia' => 'زامبیا', + 'Zimbabwe' => 'زیمباوه', +]; diff --git a/setup/I18n/fr_FR.php b/setup/I18n/fr_FR.php new file mode 100644 index 00000000..62e235ca --- /dev/null +++ b/setup/I18n/fr_FR.php @@ -0,0 +1,1460 @@ + 'Délai d\'expiration du cookie "Remember me", en secondes, pour les utilisateurs d\'administration', + '"Remember me" cookie expiration time, in seconds, for customer users' => 'Délai d\'expiration du cookie "Remember me", en secondes, pour les clients', + '"Remember me" cookie name for administration users' => 'Nom du cookie "Remember me" pour les utilisateurs d\'administration', + '"Remember me" cookie name for customer users' => 'Nom du cookie "Remember me" pour les clients', + '72h delivery' => 'Livraison par colissimo en 72h', + 'A {config key="store_name"} account has been created for you' => 'Un compte {config key="store_name"} vient d\'être créé pour vous.', + 'API Configuration' => 'Configuration de l\'API', + 'Aceh' => 'Aceh', + 'Address' => 'Adresse', + 'Address creation - CSS stylesheet' => 'Création d\'adresse - feuille de style CSS', + 'Address creation - after javascript include' => 'Création d\'adresse - après l\'inclusion du JavaScript', + 'Address creation - after javascript initialisation' => 'Création d\'adresse - après l\'initialisation du JavaScript', + 'Address creation - at the bottom' => 'Création d\'adresse - en bas', + 'Address creation - at the bottom of the form' => 'Création d\'adresse - en bas du formulaire', + 'Address creation - at the top' => 'Création d\'adresse - en haut', + 'Address creation - at the top of the form' => 'Création d\'adresse - en haut du formulaire', + 'Address update - CSS stylesheet' => 'Modification d\'adresse - feuille de style CSS', + 'Address update - after javascript include' => 'Modification d\'adresse - après l\'inclusion du JavaScript', + 'Address update - after javascript initialisation' => 'Modification d\'adresse - après l\'initialisation du JavaScript', + 'Address update - at the bottom' => 'Modification d\'adresse - en bas', + 'Address update - at the bottom of the form' => 'Modification d\'adresse - en bas du formulaire', + 'Address update - at the top' => 'Modification d\'adresse - en haut', + 'Address update - at the top of the form' => 'Modification d\'adresse - en haut du formulaire', + 'Admin layout - After the main content' => 'Admin layout - Après le contenu principal', + 'Administatros list' => 'Liste des administrateurs', + 'Administration profiles management' => 'Gestion des profils d\'administration', + 'Administrator - create form' => 'Administateur - formulaire de création', + 'Administrator - delete form' => 'Administateur - formulaire de suppression', + 'Administrator - update form' => 'Administateur - formulaire de modification', + 'Administrator list' => 'Liste des administrateurs', + 'Administrators - JavaScript' => 'Administateurs - JavaScript', + 'Administrators - at the top' => 'Administateurs - en haut', + 'Administrators - bottom' => 'Administateurs - bas', + 'Administrators - header' => 'Administrateurs - en-tête', + 'Administrators - row' => 'Administrateurs - ligne', + 'Advanced Configuration' => 'Configuration avancée', + 'Advanced Configuration - Javascript' => 'Configuration avancée - JavaScript', + 'Advanced configuration' => 'Configuration avancée', + 'Afghanistan' => 'Afghanistan', + 'Agrigento' => 'Agrigento', + 'Aguascalientes' => 'Aguascalientes', + 'Aichi' => 'Aichi', + 'Akita' => 'Akita', + 'Alabama' => 'Alabama', + 'Alaska' => 'Alaska', + 'Albania' => 'Albanie', + 'Alberta' => 'Alberta', + 'Alessandria' => 'Alessandria', + 'Algeria' => 'Algérie', + 'All Products - CSS stylesheet' => 'Tous les produits - feuille de style CSS', + 'All Products - after javascript include' => 'Tous les produits - après l\'inclusion du JavaScript', + 'All Products - after javascript initialisation' => 'Tous les produits - après l\'initialisation du JavaScript', + 'All Products - at the bottom' => 'Tous les produits - en bas', + 'All Products - at the top' => 'Tous les produits - en haut', + 'Allow an administrator to recreate a lost password (1 = yes, 0 = no)' => 'Permettre à un administrateur de recréer un mot de passe perdu (1 = Oui, 0 = non)', + 'Allow customers to change their email. 1 for yes, 0 for no' => 'Permettre aux utilisateurs de changer leur email. 1 pour oui, 0 pour non', + 'Allow negative product stock (1) or not (0)' => 'Autoriser un stock négatif sur les produits (1) ou pas (0, défaut)', + 'Allow negative product stock (1) or not (0, default)' => 'Autoriser le stock négatif (1) ou pas (0) (0 par défaut)', + 'Allow module installation from ZIP files.' => 'Autoriser l\'installation des modules par fichier ZIP.' , + 'Allow slash ended uri' => 'Autoriser les URI terminées par un slash', + 'An image carousel on your home page' => 'Un carrousel d\'images sur votre page d\'accueil', + 'Ancona' => 'Ancona', + 'Andorra' => 'Andorre', + 'Angola' => 'Angola', + 'Antigua and Barbuda' => 'Antigua-et-Barbuda', + 'Aomori' => 'Aomori', + 'Aosta' => 'Aosta', + 'Api page - at bottom' => 'Page api - en bas', + 'Api page - at top' => 'Page api - en haut', + 'Api page - in deletion form' => 'Page api - formulaire de suppression', + 'Arezzo' => 'Arezzo', + 'Argentina' => 'Argentine', + 'Arizona' => 'Arizona', + 'Arkansas' => 'Arkansas', + 'Armenia' => 'Arménie', + 'Ascoli Piceno' => 'Ascoli Piceno', + 'Ask the customers to confirm their email in customer creation form, 1 for yes, 0 for no' => 'Demander aux clients de confirmer leur adresse email dans le formulaire de création de compte (1: oui, 0: non)', + 'Ask the customers to confirm their email, 1 for yes, 0 for no' => 'Demander aux clients de confirmer leur email. 1 pour oui, 0 pour non', + 'Asti' => 'Asti', + 'Attribut - Edit JavaScript' => 'Attribut - JavaScript modification', + 'Attribut - add to all form' => 'Attribut - formulaire ajouter à tous', + 'Attribut - create form' => 'Attribut - formulaire de création', + 'Attribut - delete form' => 'Attribut - formulaire de suppression', + 'Attribut - id delete form' => 'Attribut - formulaire de suppression ID', + 'Attribut - remove to all form' => 'Attribut - formulaire de suppression multiple', + 'Attribute edit - bottom' => 'Édition d\'une déclinaison - en bas', + 'Attribute edit - top' => 'Édition d\'une déclinaison - en haut', + 'Attribute value - create form' => 'Valeur d\'attribut - formulaire de création', + 'Attributes - JavaScript' => 'Attributs - JavaScript', + 'Attributes - at the top' => 'Attributs - en haut', + 'Attributes - bottom' => 'Attributs - bas', + 'Attributes - table header' => 'Attributs - colonne tableau', + 'Attributes - table row' => 'Attributs - ligne tableau', + 'Attributes value - table header' => 'Valeurs des attributs - colonne tableau', + 'Attributes value - table row' => 'Valeurs des attributs - ligne tableau', + 'Australia' => 'Australie', + 'Austria' => 'Autriche', + 'Avellino' => 'Avellino', + 'Azerbaijan' => 'Azerbaïdjan', + 'Back-office Home page content' => 'Contenu de la page d\'accueil de l\'administration', + 'Back-office export management' => 'gestion des exports', + 'Back-office home page' => 'Page d\'acceuil de l\'administration', + 'Back-office search function' => 'Fonction de recherche dans l\'administration', + 'Bahamas' => 'Bahamas', + 'Bahrain' => 'Bahreïn', + 'Baht' => 'Baht', + 'Baja California' => 'Baja California', + 'Baja California Sur' => 'Baja California Sur', + 'Bali' => 'Bali', + 'Bangka' => 'Bangka', + 'Bangladesh' => 'Bangladesh', + 'Banten' => 'Banten', + 'Barbados' => 'Barbade', + 'Bari' => 'Bari', + 'Barletta-Andria-Trani' => 'Barletta-Andria-Trani', + 'Base URL of the shop (e.g. http://www.yourshopdomain.com)' => 'URL de base pour la boutique (par exemple http://www.yourshopdomain.com)', + 'Belarus' => 'Belarus', + 'Belarusian ruble' => 'Rouble Biélorusse', + 'Belgium' => 'Belgique', + 'Belize' => 'Belize', + 'Belluno' => 'Belluno', + 'Benevento' => 'Benevento', + 'Bengkulu' => 'Bengkulu', + 'Benin' => 'Bénin', + 'Bergamo' => 'Bergamo', + 'Bhutan' => 'Bhoutan', + 'Biella' => 'Biella', + 'Bielorussia' => 'Biélorussie', + 'Bolivia' => 'Bolivie', + 'Boliviano' => 'Bolivie', + 'Bologna' => 'Bologne', + 'Bolzano' => 'Bolzano', + 'Bolívar fuerte' => 'Bolivar Vénézuélien', + 'Bosnia and Herzegovina' => 'Bosnie-Herzégovine', + 'Botswana' => 'Botswana', + 'Brand - Edit JavaScript' => 'Marque - Modification du JavaScript', + 'Brand - JavaScript' => 'Marque - JavaScript', + 'Brand - Tab' => 'Marque - Onglet', + 'Brand - content' => 'Marque - contenu', + 'Brand - create form' => 'Marque - formulaire de création', + 'Brand - delete form' => 'Marque - formulaire de suppression', + 'Brand edit - bottom' => 'Édition d\'une marque - en bas', + 'Brand edit - right column bottom' => 'Édition d\'une marque - en bas de la colonne de droite', + 'Brand edit - right column top' => 'Édition d\'une marque - en haut de la colonne de droite', + 'Brand edit - top' => 'Édition d\'une marque - en haut', + 'Brand edit page - in the form' => 'Page brand edit - dans formulaire', + 'Brands - at the top' => 'Marques - en haut', + 'Brands - bottom' => 'Marques - bas', + 'Brands - table header' => 'Marques - colonne tableau', + 'Brands - table row' => 'Marques - ligne tableau', + 'Brands management' => 'Gestion des marques', + 'Brands page - CSS stylesheet' => 'Page des marques - feuille de style CSS', + 'Brands page - after javascript include' => 'Page des marques - après l\'inclusion du JavaScript', + 'Brands page - after the main content area' => 'Page des marques - en dessous de la zone de contenu principale', + 'Brands page - at the bottom' => 'Page des marques - en bas', + 'Brands page - at the bottom of the main area' => 'Page des marques - en bas de la zone principal', + 'Brands page - at the bottom of the sidebar' => 'Page des marques - en bas de la sidebar', + 'Brands page - at the top' => 'Page des marques - en haut', + 'Brands page - at the top of the main area' => 'Page des marques - en haut de la zone principal', + 'Brands page - at the top of the sidebar' => 'Page des marques - en haut de la sidebar', + 'Brands page - before the main content area' => 'Page des marques - au dessus de la zone de contenu principale', + 'Brands page - javascript initialization' => 'Page des marques - initialisation du JavaScript', + 'Brands page - the body of the sidebar' => 'Page des marques - le corps de la sidebar', + 'Brazil' => 'Brésil', + 'Brescia' => 'Brescia', + 'Brindisi' => 'Brindisi', + 'British Columbia' => 'Colombie-Britannique', + 'Brunei' => 'Brunei', + 'Buenos Aires' => 'Buenos Aires', + 'Bulgaria' => 'Bulgarie', + 'Burkina' => 'Burkina', + 'Burma' => 'Birmanie', + 'Burundi' => 'Burundi', + 'Cagliari' => 'Cagliari', + 'California' => 'Californie', + 'Caltanissetta' => 'Caltanissetta', + 'Cambodia' => 'Cambodge', + 'Cameroon' => 'Cameroun', + 'Campeche' => 'Campeche', + 'Campobasso' => 'Campobasso', + 'Canada' => 'Canada', + 'Canceled' => 'Annulée', + 'Cape Verde' => 'Cap-Vert', + 'Carbonia-Iglesias' => 'Carbonia-Iglesias', + 'Cart - CSS stylesheet' => 'Panier - feuille de style CSS', + 'Cart - after javascript include' => 'Panier - après l\'inclusion du JavaScript', + 'Cart - at the bottom' => 'Panier - en bas', + 'Cart - at the top' => 'Panier - en haut', + 'Cart - javascript initialization' => 'Panier - initialisation du JavaScript', + 'Cart block' => 'Bloc panier', + 'Caserta' => 'Caserta', + 'Catamarca' => 'Catamarca', + 'Catania' => 'Catane', + 'Catanzaro' => 'Catanzaro', + 'Categories - JavaScript' => 'Catégories - JavaScript', + 'Categories - at the bottom of the catalog' => 'Catégories - en bas du catalogue', + 'Categories - at the top' => 'Catégories - en haut', + 'Categories - bottom' => 'Catégories - bas', + 'Categories - caption' => 'Catégories - légende', + 'Categories - header' => 'Catégories - en-tête', + 'Categories - row' => 'Catégories - ligne', + 'Category' => 'Catégorie', + 'Category - Edit JavaScript' => 'Catégorie - JavaScript modification', + 'Category - Tab' => 'Catégorie - Onglet', + 'Category - content' => 'Catégorie - contenu', + 'Category - contents table header' => 'Catégorie - colonne tableau contenus', + 'Category - contents table row' => 'Catégorie - ligne tableau contenus', + 'Category - create form' => 'Catégorie - formulaire de création', + 'Category - delete form' => 'Catégorie - formulaire de suppression', + 'Category configuration' => 'Configuration d\'une catégorie', + 'Category edit - bottom' => 'Édition d\'une categorie - en bas', + 'Category edit - right column bottom' => 'Édition d\'une catégorie - en bas de la colonne de droite', + 'Category edit - right column top' => 'Édition d\'une catégorie - en haut de la colonne de droite', + 'Category edit - top' => 'Édition d\'une categorie - en haut', + 'Category page - CSS stylesheet' => 'Page catégorie - feuille de style CSS', + 'Category page - after javascript include' => 'Page catégorie - après l\'inclusion du JavaScript', + 'Category page - after javascript initialisation' => 'Page catégorie - après l\'initialisation du JavaScript', + 'Category page - after the main content area' => 'Page catégorie - en dessous de la zone de contenu principale', + 'Category page - at the bottom' => 'Page catégorie - en bas', + 'Category page - at the bottom of the main area' => 'Page catégorie - en bas de la zone principal', + 'Category page - at the bottom of the sidebar' => 'Page catégorie - en bas de la sidebar', + 'Category page - at the top' => 'Page catégorie - en haut', + 'Category page - at the top of the main area' => 'Page catégorie - en haut de la zone principal', + 'Category page - at the top of the sidebar' => 'Page catégorie - en haut de la sidebar', + 'Category page - before the main content area' => 'Page catégorie - au dessus de la zone de contenu principale', + 'Category page - the body of the sidebar' => 'Page catégorie - le corps de la sidebar', + 'Central African Republic' => 'République centrafricaine', + 'Central Java' => 'Central Java', + 'Central Kalimantan' => 'Kalimantan occidental', + 'Central Sulawesi' => 'Sulawesi central', + 'Chaco' => 'Chaco', + 'Chad' => 'Tchad', + 'Change password - CSS stylesheet' => 'Changement de mot de passe - feuille de style CSS', + 'Change password - after javascript include' => 'Changement de mot de passe - après l\'inclusion du JavaScript', + 'Change password - after javascript initialisation' => 'Changement de mot de passe - après l\'initialisation du JavaScript', + 'Change password - at the bottom' => 'Changement de mot de passe - en bas', + 'Change password - at the top' => 'Changement de mot de passe - en haut', + 'Check available product stock (1) or ignore it (0) when displaying and changing ordered quantity' => 'Vérifier la présence de produits en stock (1) ou l\'ignorer (0) lors de l\'affichage et la modification des quantités commandées', + 'Check if a virtual product delivery module is enabled if at least one product is virtual' => 'Vérifie qu\'un module de livraison pour produit virtuel soit activé si des produits virtuels existent', + 'Chiapas' => 'Chiapas', + 'Chiba' => 'Chiba', + 'Chieti' => 'Chieti', + 'Chihuahua' => 'Chihuahua', + 'Chile' => 'Chili', + 'China' => 'Chine', + 'Chubut' => 'Chubut', + 'Ciudad de Buenos Aires' => 'Ciudad de Buenos Aires', + 'Client edit - bottom' => 'Édition d\'un client - en bas', + 'Client edit - top' => 'Édition d\'un client - en haut', + 'Coahuila' => 'Coahuila', + 'Coat of arms of East Java' => 'Coat of arms of East Java', + 'Colima' => 'Colima', + 'Colombia' => 'Colombie', + 'Colorado' => 'Colorado', + 'Colón' => 'Colón', + 'Como' => 'Como', + 'Comoros' => 'Comores', + 'Compile templates assets automatically upon asset source change (1 = yes, 0 = no)' => 'Compiler les resources du modèle actif à chaque changement (1 = oui, 2 = non)', + 'Configuration' => 'Configuration', + 'Configuration - JavaScript' => 'Configuration - JavaScript', + 'Configuration - at the bottom of the catalog' => 'Configuration - en bas du catlogue', + 'Configuration - at the bottom of the shipping area' => 'Configuration - en bas de la zone livraison', + 'Configuration - at the bottom of the system area' => 'Configuration - en bas de la zone système', + 'Configuration - at the top' => 'Configuration - en haut', + 'Configuration - at the top of the catalog area' => 'Configuration - en haut de la zone catalogue', + 'Configuration - at the top of the shipping area' => 'Configuration - en haut de la zone livraison', + 'Configuration - at the top of the system area' => 'Configuration - en haut de la zone système', + 'Configuration - bottom' => 'Configuration - bas', + 'Configuration / Administrator' => 'Configuration / Administrateur', + 'Configuration / Area' => 'Configuration / Zone', + 'Configuration / Attribute' => 'Configuration / Attribut', + 'Configuration / Cache' => 'Configuration / Cache', + 'Configuration / Country' => 'Configuration / Pays', + 'Configuration / Currency' => 'Configuration / Devise', + 'Configuration / Feature' => 'Configuration / Caractéristique', + 'Configuration / Language' => 'Configuration / Langue', + 'Configuration / Mailing-system' => 'Configuration / Système de mails', + 'Configuration / Message' => 'Configuration / Message', + 'Configuration / Module' => 'Configuration / Module', + 'Configuration / Profile' => 'Configuration / Profil', + 'Configuration / Shipping-zone' => 'Configuration / Zone de livraison', + 'Configuration / System Log' => 'Configuration / Logs système', + 'Configuration / Tax' => 'Configuration / Taxe', + 'Configuration / Template' => 'Configuration / Modèle', + 'Configuration variables' => 'Variables de configuration', + 'Confirm your %store account' => 'Confirmez la création de votre compte {config key="store_name"}', + 'Congo' => 'Congo', + 'Connecticut' => 'Connecticut', + 'Contact block' => 'Bloc contact', + 'Contact page - CSS stylesheet' => 'Page contact - feuille de style CSS', + 'Contact page - after javascript include' => 'Page contact - après l\'inclusion du JavaScript', + 'Contact page - after javascript initialisation' => 'Page contact - après l\'initialisation du JavaScript', + 'Contact page - at the bottom' => 'Page contact - en bas', + 'Contact page - at the bottom of the form' => 'Page contact - en bas du formulaire', + 'Contact page - at the top' => 'Page contact - en haut', + 'Contact page - at the top of the form' => 'Page contact - en haut du formulaire', + 'Contact page - if successful response' => 'Page contact - en cas de succès', + 'Content' => 'Contenu', + 'Content - Edit JavaScript' => 'Contenu - JavaScript modification', + 'Content - Tab' => 'Contenu - Onglet', + 'Content - content' => 'Contenu - contenu', + 'Content - create form' => 'Contenu - formulaire de création', + 'Content - delete form' => 'Contenu - formulaire de suppression', + 'Content edit - bottom' => 'Édition d\'un contenu - en bas', + 'Content edit - right column bottom' => 'Édition d\'un contenu - en bas de la colonne de droite', + 'Content edit - right column top' => 'Édition d\'un contenu - en haut de la colonne de droite', + 'Content edit - top' => 'Édition d\'un contenu - en haut', + 'Content page - CSS stylesheet' => 'Page de contenu - feuille de style CSS', + 'Content page - after javascript include' => 'Page de contenu - après l\'inclusion du JavaScript', + 'Content page - after javascript initialisation' => 'Page de contenu - après l\'initialisation du JavaScript', + 'Content page - after the main content area' => 'Page de contenu - en dessous de la zone de contenu principale', + 'Content page - at the bottom' => 'Page de contenu - en bas', + 'Content page - at the bottom of the main area' => 'Page de contenu - en bas de la zone principal', + 'Content page - at the bottom of the sidebar' => 'Page de contenu - en bas de la sidebar', + 'Content page - at the top' => 'Page de contenu - en haut', + 'Content page - at the top of the main area' => 'Page de contenu - en haut de la zone principal', + 'Content page - at the top of the sidebar' => 'Page de contenu - en haut de la sidebar', + 'Content page - before the main content area' => 'Page de contenu - au dessus de la zone de contenu principale', + 'Content page - the body of the sidebar' => 'Page de contenu - le corps de la sidebar', + 'Contents - caption' => 'Contenus - légende', + 'Contents - header' => 'Contenus - en-tête', + 'Contents - row' => 'Contenus - ligne', + 'Cook Islands' => 'Cook', + 'Corrientes' => 'Corrientes', + 'Cosenza' => 'Cosenza', + 'Costa Rica' => 'Costa Rica', + 'Countries - JavaScript' => 'Pays - JavaScript', + 'Countries - at the top' => 'Pays - en haut', + 'Countries - bottom' => 'Pays - bas', + 'Countries - table header' => 'Pays - colonne tableau', + 'Countries - table row' => 'Pays - ligne tableau', + 'Country - Edit JavaScript' => 'Pays - JavaScript modification', + 'Country - create form' => 'Pays - formulaire de création', + 'Country - delete form' => 'Pays - formulaire de suppression', + 'Country edit - bottom' => 'Édition d\'un pays - en bas', + 'Country edit - top' => 'Édition d\'un pays - en haut', + 'Coupon' => 'Code promo', + 'Coupon - at the top' => 'Code promo - en haut', + 'Coupon - bottom' => 'Code promo - bas', + 'Coupon - create JavaScript' => 'Code promo - JavaScript création', + 'Coupon - list JavaScript' => 'Code promo - JavaScript des listes', + 'Coupon - list caption' => 'Code promo - légende liste', + 'Coupon - table header' => 'Code promo - colonne tableau', + 'Coupon - table row' => 'Code promo - ligne tableau', + 'Coupon - update JavaScript' => 'Code promo - JavaScript modification', + 'Coupon page - in deletion form' => 'Page coupon - formulaire de suppression', + 'Cremona' => 'Cremona', + 'Croatia' => 'Croatie', + 'Croatian Kuna' => 'Kuna Croate', + 'Crotone' => 'Crotone', + 'Cuba' => 'Cuba', + 'Cuneo' => 'Cuneo', + 'Curency selection page - CSS stylesheet' => 'Page du choix de la device - feuille de style CSS', + 'Curency selection page - after javascript include' => 'Page du choix de la device - après l\'inclusion du JavaScript', + 'Curency selection page - after javascript initialisation' => 'Page du choix de la device - après l\'initialisation du JavaScript', + 'Curency selection page - at the bottom' => 'Page du choix de la device - en bas', + 'Curency selection page - at the top' => 'Page du choix de la device - en haut', + 'Currencies - JavaScript' => 'Devises - JavaScript', + 'Currencies - at the top' => 'Devises - en haut', + 'Currencies - bottom' => 'Devises - bas', + 'Currencies - table header' => 'Devises - colonne tableau', + 'Currencies - table row' => 'Devises - ligne tableau', + 'Currency - Edit JavaScript' => 'Devise - JavaScript modification', + 'Currency - create form' => 'Devise - formulaire de création', + 'Currency - delete form' => 'Devise - formulaire de suppression', + 'Currency block' => 'Bloc des devises', + 'Currency edit - bottom' => 'Édition d\'une devise - en bas', + 'Currency edit - top' => 'Édition d\'une devise - en haut', + 'Customer' => 'Client', + 'Customer - Edit' => 'Client - Modification', + 'Customer - Edit JavaScript' => 'Client - JavaScript modification', + 'Customer - address create form' => 'Client - formulaire de création d\'adresse', + 'Customer - address delete form' => 'Client - formulaire de suppression adresse', + 'Customer - address update form' => 'Client - formulaire de Modification d\'adresse', + 'Customer - at the top' => 'Client - en haut', + 'Customer - bottom' => 'Client - bas', + 'Customer - create form' => 'Client - formulaire de création', + 'Customer - delete form' => 'Client - formulaire de suppression', + 'Customer - order table header' => 'Client - colonne tableau commande', + 'Customer - order table row' => 'Client - ligne tableau commande', + 'Customer account - additional information' => 'Compte client - informations additionnelles', + 'Customer account block' => 'Bloc compte client', + 'Customer account creation should be confirmed by email (1: yes, 0: no)' => 'La création d\'un compte client doit être confirmée par email (1: oui, 0: non)', + 'Customer title' => 'civilité client', + 'Customers - JavaScript' => 'Clients - JavaScript', + 'Customers - caption' => 'Clients - légende', + 'Customers - header' => 'Clients - en-tête', + 'Customers - row' => 'Clients - ligne', + 'Cyprus' => 'Chypre', + 'Czech Republic' => 'République tchèque', + 'Czech koruna' => 'Couronne Tchèque', + 'Córdoba' => 'Cordoba', + 'Danish krone' => 'Couronne Danoise', + 'Dashboard - at the top' => 'Tableau de bord - en haut', + 'Dashboard - bottom' => 'Tableau de bord - bas', + 'Dashboard - middle' => 'Tableau de bord - au milieu', + 'Data import / export' => 'Importation / exportation de données', + 'Default available stock when check-available-stock is set to 0.' => 'Stock disponible par défaut quand check-available-stock est à 0.', + 'Default lang without translation' => 'Langue par défaut sans traduction', + 'Default number of coupons per page on coupon list' => 'Nombre de coupons par page dans la liste des coupons', + 'Delaware' => 'Delaware', + 'Delivery - After delivery module' => 'Commande - après le module de livraison', + 'Delivery - CSS' => 'Bon de livraison - CSS', + 'Delivery - additional product information' => 'Bon de livraison - informations additionnelles pour un produit', + 'Delivery - after addresse area' => 'Bon de livraison - après la zone d\'adresses', + 'Delivery - after the information area' => 'Bon de livraison - après la zone d\'informations', + 'Delivery - after the order summary' => 'Bon de livraison - après le résumé de la commande', + 'Delivery - at the bottom of information area' => 'Bon de livraison - en bas de la zone d\'informations', + 'Delivery - at the bottom of the footer' => 'Bon de livraison - en bas du pied de page', + 'Delivery - at the top of the footer' => 'Bon de livraison - en haut du pied de page', + 'Delivery - delivery address' => 'Bon de livraison - adresse de livraison', + 'Delivery - imprint' => 'Bon de livraison - mentions légales', + 'Delivery - in the header' => 'Bon de livraison - dans l\'en-tête', + 'Delivery choice - CSS stylesheet' => 'Choix du transporteur - feuille de style CSS', + 'Delivery choice - after javascript include' => 'Choix du transporteur - après l\'inclusion du JavaScript', + 'Delivery choice - after javascript initialisation' => 'Choix du transporteur - après l\'initialisation du JavaScript', + 'Delivery choice - at the bottom' => 'Choix du transporteur - en bas', + 'Delivery choice - at the bottom of the form' => 'Choix du transporteur - en bas du formulaire', + 'Delivery choice - at the top' => 'Choix du transporteur - en haut', + 'Delivery choice - at the top of the form' => 'Choix du transporteur - en haut du formulaire', + 'Delivery choice - extra area' => 'Choix du transporteur - zone supplémentaire', + 'Delivery choice - javascript' => 'Choix du transporteur - javascript', + 'Delivery zone - Edit JavaScript' => 'Zone de livraison - JavaScript modification', + 'Delivery zone - JavaScript' => 'Zone de livraison - JavaScript', + 'Delivery zone - at the top' => 'Zone de livraison - en haut', + 'Delivery zone - bottom' => 'Zone de livraison - bas', + 'Delivery zone - table header' => 'Zone de livraison - colonne tableau', + 'Delivery zone - table row' => 'Zone de livraison - ligne tableau', + 'Denmark' => 'Danemark', + 'Dinar' => 'Dinar', + 'Display and process prices with (0) or without (1) taxes.' => 'Affiche et traite les prix avec(0) ou sans (1) les taxes', + 'Displays the default blocks on the homepage of the administration' => 'Affiche les blocs par défaut sur la page d\'accueil de l\'administration', + 'District of Columbia' => 'District de Columbia', + 'Distrito Federal' => 'Distrito Federal', + 'Djibouti' => 'Djibouti', + 'Document - Edit JavaScript' => 'Document - JavaScript modification', + 'Document edit - bottom' => 'Édition d\'un document - en bas', + 'Document edit - top' => 'Édition d\'un document - en haut', + 'Dollar' => 'Dollar', + 'Dollar (CAD)' => 'Dollar Canadien', + 'Dominica' => 'Dominique', + 'Dominican Republic' => 'République dominicaine', + 'Durango' => 'Durango', + 'East Nusa Tenggara' => 'Nusa Tenggara oriental', + 'East kalimantan' => 'Kalimantan oriental', + 'Ecuador' => 'Équateur', + 'Egypt' => 'Égypte', + 'Ehime' => 'Ehime', + 'El Salvador' => 'Salvador', + 'Email html - layout - CSS' => 'Email html - layout - CSS', + 'Email html - layout - footer' => 'Email html - layout - pied de page', + 'Email html - order confirmation - after address' => 'Email html - confirmation commande - après adresses', + 'Email html - order confirmation - after products' => 'Email html - confirmation commande - après produits', + 'Email html - order confirmation - before address' => 'Email html - confirmation commande - avant adresses', + 'Email html - order confirmation - before products' => 'Email html - confirmation commande - avant produits', + 'Email html - order confirmation - delivery address' => 'Email html - confirmation commande - adresse de livraison', + 'Email html - order confirmation - footer' => 'Email html - confirmation commande - pied de page', + 'Email html - order confirmation - order product' => 'Email html - confirmation commande - produit de la commande', + 'Email html - order notification - after address' => 'Email html - notification commande - après adresses', + 'Email html - order notification - after products' => 'Email html - notification commande - après produits', + 'Email html - order notification - before address' => 'Email html - notification commande - avant adresses', + 'Email html - order notification - before products' => 'Email html - notification commande - avant produits', + 'Email html - order notification - delivery address' => 'Email html - notification commande - adresse de livraison', + 'Email html - order notification - order product' => 'Email html - notification commande - produit de la commande', + 'Email txt - order confirmation - after address' => 'Email txt - confirmation commande - après adresses', + 'Email txt - order confirmation - after products' => 'Email txt - confirmation commande - après produits', + 'Email txt - order confirmation - before address' => 'Email txt - confirmation commande - avant adresses', + 'Email txt - order confirmation - before products' => 'Email txt - confirmation commande - avant produits', + 'Email txt - order confirmation - delivery address' => 'Email txt - confirmation commande - adresse de livraison', + 'Email txt - order confirmation - order product' => 'Email txt - confirmation commande - produit de la commande', + 'Email txt - order notification - after address' => 'Email txt - notification commande - après adresses', + 'Email txt - order notification - after products' => 'Email txt - notification commande - après produits', + 'Email txt - order notification - before address' => 'Email txt - notification commande - avant adresses', + 'Email txt - order notification - before products' => 'Email txt - notification commande - avant produits', + 'Email txt - order notification - delivery address' => 'Email txt - notification commande - adresse de livraison', + 'Email txt - order notification - order product' => 'Email txt - notification commande - produit de la commande', + 'Enable (1) or disable (0) URL rewriting' => 'Activer (1) ou désactiver (0) la réécriture d\'URL', + 'Enna' => 'Enna', + 'Entre Ríos' => 'Entre Ríos', + 'Equatorial Guinea' => 'Guinée équatoriale', + 'Eritrea' => 'Érythrée', + 'Estado de México' => 'Estado de México', + 'Estonia' => 'Estonie', + 'Ethiopia' => 'Éthiopie', + 'Euro' => 'Euro', + 'Export - JavaScript' => 'Export - JavaScript', + 'Export - table header' => 'Export - colonne tableau', + 'Export - table row' => 'Export - ligne du tableau', + 'Export modal or page - bottom' => 'Modal ou page d\'export - en bas', + 'Export modal or page - top' => 'Modal ou page d\'export - en haut', + 'Exports - JavaScript' => 'Exports - JavaScript', + 'Exports - at the bottom of a category' => 'Exports - en bas d\'une catégorie', + 'Exports - at the bottom of column 1' => 'Exports - en bas de la colonne 1', + 'Exports - at the top' => 'Exports - en haut', + 'Feature - Edit JavaScript' => 'Caractéristique - JavaScript modification', + 'Feature - Value create form' => 'Caractéristique - Formulaire de création de valeur', + 'Feature - add to all form' => 'Caractéristique - formulaire ajouter à tous', + 'Feature - create form' => 'Caractéristique - formulaire de création', + 'Feature - delete form' => 'Caractéristique - formulaire de suppression', + 'Feature - remove to all form' => 'Caractéristique - formulaire de suppression multiple', + 'Feature edit - bottom' => 'Édition d\'une caractéristique - en bas', + 'Feature edit - top' => 'Édition d\'une caractéristique - en haut', + 'Features - JavaScript' => 'Caractéristiques - JavaScript', + 'Features - at the top' => 'Caractéristiques - en haut', + 'Features - bottom' => 'Caractéristiques - bas', + 'Features - table header' => 'Caractéristiques - colonne tableau', + 'Features - table row' => 'Caractéristiques - ligne tableau', + 'Features value - table header' => 'Valeur de caractéristiques - colonne tableau', + 'Features value - table row' => 'Valeur de caractéristiques - ligne tableau', + 'Fermo' => 'Fermo', + 'Ferrara' => 'Ferrara', + 'Fiji' => 'Fidji', + 'File name of the 404 (not found) view in the current template (with extension, e.g. 404.html)' => 'Nom de la page 404 (introuvable) dans le modèle actuel (avec l\'extension, par exemple, 404.html)', + 'Filename of the error page' => 'Nom du fichier de la page d\'erreur', + 'Finland' => 'Finlande', + 'Firenze' => 'Firenze', + 'Florida' => 'Floride', + 'Foggia' => 'Foggia', + 'Folder' => 'Dossier', + 'Folder - Edit JavaScript' => 'Dossier - JavaScript modification', + 'Folder - JavaScript' => 'Dossiers - JavaScript', + 'Folder - Tab' => 'Dossier - Onglet', + 'Folder - at the top' => 'Dossiers - en haut', + 'Folder - bottom' => 'Dossiers - bas', + 'Folder - caption' => 'Dossiers - légende', + 'Folder - content' => 'Dossier - contenu', + 'Folder - create form' => 'Dossier - formulaire de création', + 'Folder - delete form' => 'Dossier - formulaire de suppression', + 'Folder - header' => 'Dossiers - en-tête', + 'Folder - row' => 'Dossiers - ligne', + 'Folder edit - bottom' => 'Édition d\'un dossier - en bas', + 'Folder edit - right column bottom' => 'Édition d\'un dossier - en bas de la colonne de droite', + 'Folder edit - right column top' => 'Édition d\'un dossier - en haut de la colonne de droite', + 'Folder edit - top' => 'Édition d\'un dossier - en haut', + 'Folder page - CSS stylesheet' => 'Page dossier - feuille de style CSS', + 'Folder page - after javascript include' => 'Page dossier - après l\'inclusion du JavaScript', + 'Folder page - after javascript initialisation' => 'Page dossier - après l\'initialisation du JavaScript', + 'Folder page - after the main content area' => 'Page dossier - en dessous de la zone de contenu principale', + 'Folder page - at the bottom' => 'Page dossier - en bas', + 'Folder page - at the bottom of the main area' => 'Page dossier - en bas de la zone principale', + 'Folder page - at the top' => 'Page dossier - en haut', + 'Folder page - at the top of the main area' => 'Page dossier - en haut de la zone principale', + 'Folder page - before the main content area' => 'Page dossier - au dessus de la zone de contenu principale', + 'Forint' => 'Forint', + 'Forlì-Cesena' => 'Forlì-Cesena', + 'Formosa' => 'Formosa', + 'Franc' => 'Franc', + 'France metropolitan' => 'France métropolitaine', + 'French 10% VAT' => 'TVA française à 10%', + 'French 20% VAT' => 'TVA française à 20%', + 'French Southern Territories' => 'Terres australes et antarctiques françaises', + 'Front office integration' => 'Module Front office', + 'Frosinone' => 'Frosinone', + 'Fukui' => 'Fukui', + 'Fukuoka' => 'Fukuoka', + 'Fukushima' => 'Fukushima', + 'Gabon' => 'Gabon', + 'Gambia' => 'Gambie', + 'Genova' => 'Genova', + 'Georgia' => 'Géorgie', + 'Germany' => 'Allemagne', + 'Ghana' => 'Ghana', + 'Gifu' => 'Gifu', + 'Google Analytics block' => 'Bloc Google Analytics', + 'Gorizia' => 'Gorizia', + 'Greece' => 'Grèce', + 'Grenada' => 'Grenade', + 'Grosseto' => 'Grosseto', + 'Guadeloupe' => 'Guadeloupe', + 'Guanajuato' => 'Guanajuato', + 'Guaraní' => 'Guaraní', + 'Guatemala' => 'Guatemala', + 'Guerrero' => 'Guerrero', + 'Guinea' => 'Guinée', + 'Guinea-Bissau' => 'Guinée-Bissao', + 'Gunma' => 'Gunma', + 'Guyana' => 'Guyane', + 'Guyane Française' => 'Guyane Française', + 'HTML layout - CSS stylesheet' => 'Structure HTML - feuille de style CSS', + 'HTML layout - after javascript include' => 'Structure HTML - après l\'inclusion du JavaScript', + 'HTML layout - after the main content area' => 'Structure HTML - en dessous de la zone de contenu principale', + 'HTML layout - after the opening of the body tag' => 'Structure HTML - après l\'ouverture de la balise body', + 'HTML layout - after the opening of the head tag' => 'Structure HTML - après l\'ouverture de la balise head', + 'HTML layout - at the bottom of the header' => 'Structure HTML - en bas du header', + 'HTML layout - at the top of the footer' => 'Structure HTML - en haut du pied de page', + 'HTML layout - at the top of the header' => 'Structure HTML - en haut du header', + 'HTML layout - before the end body tag' => 'Structure HTML - avant la fin de la balise body', + 'HTML layout - before the end of the head tag' => 'Structure HTML - avant la fin de la balise head', + 'HTML layout - before the main content area' => 'Structure HTML - au dessus de la zone de contenu principale', + 'HTML layout - bottom of the footer' => 'Structure HTML - en bas du pied de page', + 'HTML layout - footer body' => 'Structure HTML - corps du pied de page', + 'HTML layout - javascript initialization' => 'Structure HTML - initialisation du JavaScript', + 'HTML layout - primary navigation' => 'Structure HTML - navigation principale', + 'HTML layout - secondary navigation' => 'Structure HTML - navigation secondaire', + 'Haiti' => 'Haïti', + 'Hawaii' => 'Hawaii', + 'Hidalgo' => 'Hidalgo', + 'Hiroshima' => 'Hiroshima', + 'Hokkaido' => 'Hokkaido', + 'Home - JavaScript' => 'Accueil - JavaScript', + 'Home - at the top' => 'Accueil - en haut', + 'Home - block' => 'Accueil - bloc', + 'Home - bottom' => 'Accueil - bas', + 'Home page - CSS stylesheet' => 'Page d\'accueil - feuille de style CSS', + 'Home page - after javascript include' => 'Page d\'accueil - après l\'inclusion du JavaScript', + 'Home page - after javascript initialisation' => 'Page d\'accueil - après l\'initialisation du JavaScript', + 'Home page - main area' => 'Page d\'accueil - zone principale', + 'Honduras' => 'Honduras', + 'Hong Kong' => 'Hong Kong', + 'Hong Kong Dollar' => 'Dollar de Honk-Kong', + 'Hook - Edit JavaScript' => 'Point d\'accroche - JavaScript modification', + 'Hook - create form' => 'Point d\'accroche - formulaire de création', + 'Hook - delete form' => 'Point d\'accroche - formulaire de suppression', + 'Hook edit - bottom' => 'Édition d\'hook - en bas', + 'Hook edit - top' => 'Édition d\'hook - en haut', + 'Hook positions' => 'Positions des points d\'accroche', + 'Hooks' => 'Points d\'accroche', + 'Hooks - JavaScript' => 'Points d\'accroche - Javascript', + 'Hooks - at the top' => 'Point d\'accroches - en haut', + 'Hooks - bottom' => 'Point d\'accroches - bas', + 'Hooks - table header' => 'Point d\'accroches - colonne tableau', + 'Hooks - table row' => 'Point d\'accroches - ligne tableau', + 'Hooks management' => 'Gestion des hooks', + 'How document files are delivered in the web space (symlink or copy)' => 'Comment les documents sont-ils fournis dans l\'espace web (lien symbolique ou copie)', + 'How original (full resolution) images are delivered in the web space (symlink or copy)' => 'Comment les images originales (pleine résolution) sont-elles fournises dans l\'espace web (lien symbolique ou copie)', + 'Hungary' => 'Hongrie', + 'Hyogo' => 'Hyogo', + 'Ibaraki' => 'Ibaraki', + 'Iceland' => 'Islande', + 'Idaho' => 'Idaho', + 'Illinois' => 'Illinois', + 'Image - Edit JavaScript' => 'Image - Modification de JavaScript', + 'Image edit - bottom' => 'Édition d\'image - en bas', + 'Image edit - top' => 'Édition d\'image - en haut', + 'Imperia' => 'Imperia', + 'Import - table header' => 'Import - colonne tableau', + 'Import - table row' => 'Import - ligne du tableau', + 'India' => 'Inde', + 'Indian Rupee' => 'Roupie Hindoue', + 'Indiana' => 'Indiana', + 'Indonesia' => 'Indonésie', + 'Invoice - After delivery module' => 'Commande - après le module de livraison', + 'Invoice - After payment module' => 'Commande - après le module de paiement', + 'Invoice - CSS' => 'Facture - CSS', + 'Invoice - additional product information' => 'Facture - informations additionnelles pour un produit', + 'Invoice - after addresse area' => 'Facture - après la zone d\'adresses', + 'Invoice - after product listing' => 'Facture - après la liste des produits', + 'Invoice - after the information area' => 'Facture - après la zone d\'informations', + 'Invoice - after the order summary' => 'Facture - après le résumé de la commande', + 'Invoice - at the bottom of information area' => 'Facture - en bas de la zone d\'informations', + 'Invoice - at the bottom of the footer' => 'Facture - en bas du pied de page', + 'Invoice - at the top of the footer' => 'Facture - en haut du pied de page', + 'Invoice - delivery address' => 'Facture - adresse de livraison', + 'Invoice - imprint' => 'Facture - mentions légales', + 'Invoice - in the header' => 'Facture - dans l\'en-tête', + 'Invoice choice - CSS stylesheet' => 'Choix du mode de paiement - feuille de style CSS', + 'Invoice choice - after javascript include' => 'Choix du mode de paiement - après l\'inclusion du JavaScript', + 'Invoice choice - after javascript initialisation' => 'Choix du mode de paiement - après l\'initialisation du JavaScript', + 'Invoice choice - at the bottom' => 'Choix du mode de paiement - en bas', + 'Invoice choice - at the top' => 'Choix du mode de paiement - en haut', + 'Invoice choice - delivery address' => 'Choix du mode de paiement - adresse de livraison', + 'Invoice choice - extra payment zone' => 'Choix du mode de paiement - zone de paiement supplémentaire', + 'Iowa' => 'Iowa', + 'Iran' => 'Iran', + 'Iraq' => 'Iraq', + 'Ireland' => 'Irlande', + 'Isernia' => 'Isernia', + 'Ishikawa' => 'Ishikawa', + 'Israel' => 'Israël', + 'Italy' => 'Italie', + 'Ivory Coast' => 'Côte dIvoire', + 'Iwate' => 'Iwate', + 'Jakarta' => 'Jakarta', + 'Jalisco' => 'Jalisco', + 'Jamaica' => 'Jamaïque', + 'Jambi' => 'Jambi', + 'Japan' => 'Japon', + 'Jordan' => 'Jordanie', + 'Jujuy' => 'Jujuy', + 'Kagawa' => 'Kagawa', + 'Kagoshima' => 'Kagoshima', + 'Kanagawa' => 'Kanagawa', + 'Kansas' => 'Kansas', + 'Kazakhstan' => 'Kazakhstan', + 'Kentucky' => 'Kentucky', + 'Kenya' => 'Kenya', + 'Kenyan shilling' => 'Shilling Kenyan', + 'Kiribati' => 'Kiribati', + 'Kochi' => 'Kochi', + 'Krona' => 'Couronne Suédoise', + 'Krone' => 'Couronne Norvégienne', + 'Kumamoto' => 'Kumamoto', + 'Kuwait' => 'Koweït', + 'Kyoto' => 'Kyoto', + 'Kyrgyzstan' => 'Kirghizistan', + 'L\'Aquila' => 'L\'Aquila', + 'La Pampa' => 'La Pampa', + 'La Rioja' => 'La Rioja', + 'La Spezia' => 'La Spezia', + 'Lambang Provinsi Papua Barat' => 'Lambang Provinsi Papua Barat', + 'Lambang Riau' => 'Lambang Riau', + 'Lambang propinsi' => 'Lambang propinsi', + 'Lampung' => 'Lampung', + 'Language - create form' => 'Langage - formulaire de création', + 'Languages - JavaScript' => 'Langages - JavaScript', + 'Languages - at the top' => 'Langages - en haut', + 'Languages - bottom' => 'Langages - bas', + 'Languages - delete form' => 'Langages - formulaire de suppression', + 'Languages block' => 'Bloc des langues', + 'Laos' => 'Laos', + 'Lari' => 'Lari', + 'Latina' => 'Latina', + 'Latvia' => 'Lettonie', + 'Layout - Before the main content' => 'Layout - Avant le contenu principal', + 'Layout - CSS' => 'Mise en page - CSS', + 'Layout - JavaScript' => 'Mise en page - JavaScript', + 'Layout - after footer' => 'Mise en page - après le pied de page', + 'Layout - after top bar' => 'Mise en page - après la barre de titre', + 'Layout - after top menu' => 'Mise en page - après le menu haut', + 'Layout - at the bottom of the top bar' => 'Mise en page - en bas de la barre supérieure', + 'Layout - at the top of the top bar' => 'Mise en page - en haut de la barre supérieure', + 'Layout - before footer' => 'Mise en page - avant le pied de page', + 'Layout - before top menu' => 'Mise en page - avant le menu haut', + 'Layout - before topbar' => 'Mise en page - avant la barre de titre', + 'Layout - in footer' => 'Mise en page - dans le pied de page', + 'Layout - in the menu catalog' => 'Mise en page - dans le menu catalogue', + 'Layout - in the menu configuration' => 'Mise en page - dans le menu configuration', + 'Layout - in the menu customers' => 'Mise en page - dans le menu clients', + 'Layout - in the menu folders' => 'Mise en page - dans le menu dossiers', + 'Layout - in the menu modules' => 'Mise en page - dans le menu modules', + 'Layout - in the menu orders' => 'Mise en page - dans le menu commandes', + 'Layout - in the menu tools' => 'Mise en page - dans le menu outils', + 'Layout - in top menu items' => 'Mise en page - éléments du menu haut', + 'Layout - inside top bar' => 'Mise en page - dans la barre de titre', + 'Leave the default configuration of session' => 'Laisser la configuration par défaut de la session', + 'Lebanon' => 'Liban', + 'Lecce' => 'Lecce', + 'Lecco' => 'Lecco', + 'Lei' => 'Lei', + 'Lesotho' => 'Lesotho', + 'Lev' => 'Lev', + 'Liberia' => 'Liberia', + 'Libya' => 'Libye', + 'Liechtenstein' => 'Liechtenstein', + 'Life time of the cart cookie in the customer browser, in seconds' => 'Durée de vie du cookie du panier dans le navigateur du client, en secondes', + 'Life time of the session cookie in the customer browser, in seconds' => 'Durée de vie du cookie de la session dans le navigateur du client, en secondes', + 'Links block' => 'Bloc liens', + 'Lira' => 'Lire', + 'Lithuania' => 'Lituanie', + 'Livorno' => 'Livourne', + 'Lodi' => 'Lodi', + 'Logging system configuration' => 'Configuration du système de log', + 'Login page - CSS stylesheet' => 'Page de connexion - feuille de style CSS', + 'Login page - after javascript include' => 'Page de connexion - après l\'inclusion du JavaScript', + 'Login page - after javascript initialisation' => 'Page de connexion - après l\'initialisation du JavaScript', + 'Login page - at the bottom' => 'Page de connexion - en bas', + 'Login page - at the bottom of the form' => 'Page de connexion - en bas du formulaire', + 'Login page - at the bottom of the main area' => 'Page de connexion - en bas de la zone principal', + 'Login page - at the top' => 'Page de connexion - en haut', + 'Login page - at the top of the form' => 'Page de connexion - en haut du formulaire', + 'Login page - at the top of the main area' => 'Page de connexion - en haut de la zone principal', + 'Logs - JavaScript' => 'Journaux - JavaScript', + 'Logs - at the top' => 'Logs - en haut', + 'Logs - bottom' => 'Logs - bas', + 'Lost password - CSS stylesheet' => 'Mot de passe perdu - feuille de style CSS', + 'Lost password - after javascript include' => 'Mot de passe perdu - après l\'inclusion du JavaScript', + 'Lost password - at the bottom' => 'Mot de passe perdu - en bas', + 'Lost password - at the bottom of the form' => 'Mot de passe perdu - en bas du formulaire', + 'Lost password - at the top' => 'Mot de passe perdu - en haut', + 'Lost password - at the top of the form' => 'Mot de passe perdu - en haut du formulaire', + 'Lost password - javascript initialization' => 'Mot de passe perdu - initialisation du JavaScript', + 'Louisiana' => 'Louisiane', + 'Lucca' => 'Lucca', + 'Luxembourg' => 'Luxembourg', + 'Macedonia' => 'Macédoine', + 'Macerata' => 'Macerata', + 'Madagascar' => 'Madagascar', + 'Mail sent after a subscription to newsletter' => 'Email envoyé après l\'inscription à la newsletter', + 'Mail sent to an administrator who requested a new password' => 'Courrier envoyé à un administrateur qui a demandé un nouveau mot de passe', + 'Mail sent to the customer to confirm its account' => 'E-mail de confirmation de création de compte client', + 'Mail sent to the customer when its account is created by an administrator in the back-office' => 'Mail envoyé au client lorsque son compte est créé depuis le back-office par un administrateur', + 'Mail sent to the customer when its password or email is changed in the back-office' => 'Message envoyé au client lorsque son mot de passe ou son email est changé dans le back-office', + 'Mailing system - JavaScript' => 'Envoi des e-mails - JavaScript', + 'Mailing system - at the top' => 'Envoi des e-mails - en haut', + 'Mailing system - bottom' => 'Envoi des e-mails - en bas', + 'Maine' => 'Maine', + 'Malawi' => 'Malawi', + 'Malaysia' => 'Malaisie', + 'Maldives' => 'Maldives', + 'Mali' => 'Mali', + 'Malta' => 'Malte', + 'Maluku' => 'Maluku', + 'Manat' => 'Manat', + 'Manitoba' => 'Manitoba', + 'Mantova' => 'Mantova', + 'Marshall Islands' => 'Marshall', + 'Martinique' => 'Martinique', + 'Maryland' => 'Maryland', + 'Massa' => 'Massa', + 'Massachusetts' => 'Massachusetts', + 'Matera' => 'Matera', + 'Mauritania' => 'Mauritanie', + 'Mauritius' => 'Maurice', + 'Mayotte' => 'Mayotte', + 'Medio Campidano' => 'Medio Campidano', + 'Mendoza' => 'Mendoza', + 'Message - Edit JavaScript' => 'Message - Modification de JavaScript', + 'Message - create form' => 'Message - formulaire de création', + 'Message - delete form' => 'Message - formulaire de suppression', + 'Message edit - bottom' => 'Édition d\'un message - en bas', + 'Message edit - top' => 'Édition d\'un message - en haut', + 'Message sent to the shop owner when a new order is placed' => 'Message envoyé au gestionnaire de la boutique lors d\'une nouvelle commande.', + 'Messages - JavaScript' => 'Messages - JavaScript', + 'Messages - at the top' => 'Messages - en haut', + 'Messages - bottom' => 'Messages - bas', + 'Messages - table header' => 'Messages - colonne tableau', + 'Messages - table row' => 'Messages - ligne tableau', + 'Messina' => 'Messina', + 'Mexico' => 'Mexique', + 'Michigan' => 'Michigan', + 'Michoacán' => 'Michoacán', + 'Micronesia' => 'Micronésie', + 'Mie' => 'Mie', + 'Milano' => 'Milano', + 'Mini cart' => 'Mini panier', + 'Minnesota' => 'Minnesota', + 'Misiones' => 'Misiones', + 'Miss' => 'Mademoiselle', + 'Miss_short' => 'Mlle', + 'Misses' => 'Madame', + 'Mississippi' => 'Mississippi', + 'Missouri' => 'Missouri', + 'Mister' => 'Monsieur', + 'Miyagi' => 'Miyagi', + 'Miyazaki' => 'Miyazaki', + 'Modena' => 'Modena', + 'Module - Edit JavaScript' => 'Module - Modification de JavaScript', + 'Module - configuration' => 'Module - configuration', + 'Module - configuration JavaScript' => 'Module - JavaScript configuration', + 'Module edit - bottom' => 'Édition d\'un module - en bas', + 'Module edit - top' => 'Édition d\'un module - en haut', + 'Module hook - Edit JavaScript' => 'Module hook - Modification de JavaScript', + 'Module hook - JavaScript' => 'Point d\'accroche des modules - Javascript', + 'Module hook - create form' => 'Module hook - formulaire de création', + 'Module hook - delete form' => 'Module hook - formulaire de suppression', + 'Module hook edit - bottom' => 'Édition d\'un hook de module - en bas', + 'Module hook edit - top' => 'Édition d\'un hook de module - en haut', + 'Modules - JavaScript' => 'Modules - JavaScript', + 'Modules - at the top' => 'Modules - en haut', + 'Modules - bottom' => 'Modules - bas', + 'Modules - table header' => 'Modules - colonne tableau', + 'Modules - table row' => 'Modules - ligne tableau', + 'Modules maagement' => 'Gestion des modules', + 'Modules management' => 'Gestion des modules', + 'Moldova' => 'Moldavie', + 'Monaco' => 'Principauté de Monaco', + 'Mongolia' => 'Mongolie', + 'Montana' => 'Montana', + 'Monza e della Brianza' => 'Monza e della Brianza', + 'Morelos' => 'Morelos', + 'Morocco' => 'Maroc', + 'Mozambique' => 'Mozambique', + 'Mr.' => 'M.', + 'Mrs' => 'Mme', + 'Nagano' => 'Nagano', + 'Nagasaki' => 'Nagasaki', + 'Name of the active PDF template' => 'Nom du modèle PDF actif', + 'Name of the active back-office template' => 'Nom du modèle de back-office actif', + 'Name of the active front-office template' => 'Nom du modèle de front-office actif', + 'Name of the active mailing template' => 'Nom du modèle d\'e-mail actif', + 'Name of the cart cookie' => 'Nom du cookie de stockage du panier', + 'Name of the delivery view in the current PDF template (without extension)' => 'Nom de la vue de la livraison dans le modèle PDF en cours (sans extension)', + 'Name of the graphic driver used by the Imagine library (see https://imagine.readthedocs.org)' => 'Nom du pilote graphique utilisé par la bibliothèque Imagine (voir https://imagine.readthedocs.org)', + 'Name of the invoice view in the current PDF template (without extension)' => 'Nom de la vue de la facture dans le modèle PDF en cours (sans extension)', + 'Name of the template view returned when an obsolete (or inactive) product URL is invoked' => 'Nom de la page du modèle retournée lorsqu\'une URL obsolète (ou inactive) est invoquée', + 'Name the cart cookie' => 'Nom du cookie pour le panier', + 'Namibia' => 'Namibie', + 'Napoli' => 'Napoli', + 'Nara' => 'Nara', + 'Nauru' => 'Nauru', + 'Navigation block' => 'Bloc menu', + 'Nayarit' => 'Nayarit', + 'Nebraska' => 'Nebraska', + 'Nepal' => 'Népal', + 'Netherlands' => 'Pays-Bas', + 'Neuquén' => 'Neuquén', + 'Nevada' => 'Nevada', + 'New Brunswick' => 'Nouveau-Brunswick', + 'New Hampshire' => 'New Hampshire', + 'New Jersey' => 'New Jersey', + 'New Mexico' => 'Nouveau-Mexique', + 'New Products block' => 'Bloc nouveaux produits', + 'New York' => 'New York', + 'New Zealand' => 'Nouvelle-Zélande', + 'New order {$order_ref} placed on {config key="store_name"}' => 'Nouvelle commande {$order_ref} reçue sur {config key="store_name"}', + 'New password request on %store' => 'Votre demande de mot de passe {config key="store_name"}', + 'Newfoundland and Labrador' => 'Terre Neuve et Labrador', + 'Newsletter block' => 'Bloc newsletter', + 'Newsletter page - CSS stylesheet' => 'Page newsletter - feuille de style CSS', + 'Newsletter page - after javascript include' => 'Page newsletter - après l\'inclusion du JavaScript', + 'Newsletter page - after javascript initialisation' => 'Page newsletter - après l\'initialisation du JavaScript', + 'Newsletter page - at the bottom' => 'Page newsletter - en bas', + 'Newsletter page - at the top' => 'Page newsletter - en haut', + 'Newsletter subscription confirmation mail' => 'Mail de confirmation d\'inscription à la newsletter', + 'Newsletter unsubscribe page - CSS stylesheet' => 'Désabonnement newsletter - feuille de style CSS', + 'Newsletter unsubscribe page - after javascript include' => 'Désabonnement newsletter - après l\'inclusion du JavaScript', + 'Newsletter unsubscribe page - after javascript initialisation' => 'Désabonnement newsletter - après l\'initialisation du JavaScript', + 'Newsletter unsubscribe page - at the bottom' => 'Désabonnement newsletter - en bas', + 'Newsletter unsubscribe page - at the top' => 'Désabonnement newsletter - en haut', + 'Nicaragua' => 'Nicaragua', + 'Niger' => 'Niger', + 'Nigeria' => 'Nigeria', + 'Nigerian naira' => 'Naira Nigérien', + 'Niigata' => 'Niigata', + 'Niue' => 'Niue', + 'North Carolina' => 'Caroline du Nord', + 'North Dakota' => 'Dakota du Nord', + 'North Korea' => 'Corée du Nord', + 'North Maluku' => 'Maluku du Nord', + 'North Sulawesi' => 'Sulawesi du Nord', + 'North Sumatra' => 'Sumatra-Nord', + 'Northwest Territories' => 'Territoires du Nord-Ouest', + 'Norway' => 'Norvège', + 'Not paid' => 'Non payée', + 'Nouvelle-Calédonie' => 'Nouvelle-Calédonie', + 'Nova Scotia' => 'Nouvelle-Écosse', + 'Novara' => 'Novara', + 'Nuevo León' => 'Nuevo León', + 'Nuevo Sol' => 'Nuevo Sol', + 'Number by default of results per page for customer list' => 'Nombre par défaut de résultats par page pour la liste des clients', + 'Number by default of results per page for order list' => 'Nombre par défaut de résultats par page pour la liste des commandes', + 'Number by default of results per page for product list' => 'Nombre par défaut de résultats par page pour la liste des produits', + 'Nunavut' => 'Nunavut', + 'Nuoro' => 'Nuoro', + 'Oaxaca' => 'Oaxaca', + 'Ogliastra' => 'Ogliastra', + 'Ohio' => 'Ohio', + 'Oita' => 'Oita', + 'Okayama' => 'Okayama', + 'Okinawa' => 'Okinawa', + 'Oklahoma' => 'Oklahoma', + 'Olbia-Tempio' => 'Olbia-Tempio', + 'Oman' => 'Oman', + 'Ontario' => 'Ontario', + 'Order' => 'Commande', + 'Order - After closing product row' => 'Commande - Après avoir fermé la ligne produit', + 'Order - After product list' => 'Commande - Après la liste des produits', + 'Order - Before product list' => 'Commande - Avant la liste des produits', + 'Order - Before starting product row' => 'Commande - Avant d\'ouvrir la ligne produit', + 'Order - Edit JavaScript' => 'Commande - Modification de JavaScript', + 'Order - Tab' => 'Commande- Onglet', + 'Order - bill bottom' => 'Commande - facture bas', + 'Order - bill top' => 'Commande - facture haut', + 'Order - cart bottom' => 'Commande - panier bas', + 'Order - cart top' => 'Commande - panier haut', + 'Order - content' => 'Commande - contenu', + 'Order - customer information bottom' => 'Commande - en bas des informations client', + 'Order - delivery module bottom' => 'Commande - en bas du module de livraison', + 'Order - payment module bottom' => 'Commande - en bas du module de paiement', + 'Order - product list' => 'Commande - liste produit', + 'Order - table header' => 'Commande - colonne tableau', + 'Order - table row' => 'Commande - ligne tableau', + 'Order confirmation - after the order summary' => 'Confirmation de commande - après les récapitulatif de commande', + 'Order confirmation sent to the customer' => 'Confirmation de commande envoyée au client', + 'Order details - CSS stylesheet' => 'Détail d\'une commande - feuille de style CSS', + 'Order details - additional delivery information' => 'Détail d\'une commande - informations additionnelles pour l\'expédition', + 'Order details - additional information' => 'Détail d\'une commande - informations additionnelles', + 'Order details - additional invoice information' => 'Détail d\'une commande - informations additionnelles pour la facturation', + 'Order details - additional product information' => 'Détail d\'une commande - informations additionnelles pour un produit', + 'Order details - after addresses' => 'Détail d\'une commande - Après les adresses', + 'Order details - after delivery address' => 'Détails d\'une commande - après l\'adresse de livraison', + 'Order details - after global information' => 'Détail d\'une commande - après les informations générales', + 'Order details - after invoice address' => 'Détail d\'une commande - après l\'adresse de facturation', + 'Order details - after javascript include' => 'Détail d\'une commande - après l\'inclusion du JavaScript', + 'Order details - after product' => 'Détail d\'une commande - Après un produit', + 'Order details - after products' => 'Détail d\'une commande - Après les produits', + 'Order details - after products list' => 'Détail d\'une commande - après la liste des produits', + 'Order details - at the bottom' => 'Détail d\'une commande - en bas', + 'Order details - at the top' => 'Détail d\'une commande - en haut', + 'Order details - before products list' => 'Détail d\'une commande - avant la liste des produits', + 'Order details - delivery address' => 'Détail d\'une commande - adresse de livraison', + 'Order details - invoice address' => 'Détail d\'une commande - adresse de facturation', + 'Order details - javascript initialization' => 'Détail d\'une commande - initialisation du JavaScript', + 'Order edit - bottom' => 'Édition d\'une commande - en bas', + 'Order edit - delivery address' => 'Modification commande - adresse de livraison', + 'Order edit - displayed after product information' => 'Édition d\'une commande - sous les informations du produit', + 'Order edit - order product table header' => 'Modification commande - en-tête des produits', + 'Order edit - order product table row' => 'Modification commande - ligne du tableau des produits', + 'Order edit - top' => 'Édition d\'une commande - en haut', + 'Order failed - CSS stylesheet' => 'Échec de la commande - feuille de style CSS', + 'Order failed - after javascript include' => 'Echec de la commande - après l\'inclusion du JavaScript', + 'Order failed - after javascript initialisation' => 'Echec de la commande - après l\'initialisation du JavaScript', + 'Order failed - at the bottom' => 'Échec de la commande - en bas', + 'Order failed - at the top' => 'Échec de la commande - en haut', + 'Orders - JavaScript' => 'Commandes - JavaScript', + 'Orders - at the top' => 'Commandes - en haut', + 'Orders - bottom' => 'Commandes - en bas', + 'Orders - table header' => 'Commandes - colonne tableau', + 'Orders - table row' => 'Commandes - ligne tableau', + 'Oregon' => 'Oregon', + 'Oristano' => 'Oristano', + 'Osaka' => 'Osaka', + 'Padova' => 'Padova', + 'Page 404 - CSS stylesheet' => 'Page introuvable - feuille de style CSS', + 'Page 404 - after javascript include' => 'Page introuvable - après l\'inclusion du JavaScript', + 'Page 404 - after javascript initialisation' => 'Page introuvable - après l\'initialisation du JavaScript', + 'Page 404 - content area' => 'Page introuvable - zone de contenu', + 'Paid' => 'Payée', + 'Pakistan' => 'Pakistan', + 'Palermo' => 'Palerme', + 'Panama' => 'Panama', + 'Papua' => 'Papouasie', + 'Papua Nueva Guinea' => 'Papouasie', + 'Paraguay' => 'Paraguay', + 'Parma' => 'Parma', + 'Path to the directory where documents are stored' => 'Chemin vers le répertoire où sont stockés les documents', + 'Path to the directory where images are stored' => 'Chemin vers le répertoire où les images sont stockées', + 'Pavia' => 'Pavie', + 'Pay by cheque' => 'Payer par chèque', + 'Payment failed - CSS stylesheet' => 'Échec du paiement - feuille de style CSS', + 'Payment failed - after javascript include' => 'Echec du paiement - après l\'inclusion du JavaScript', + 'Payment failed - javascript initialization' => 'Echec du paiement - initialisation du JavaScript', + 'Payment gateway - CSS stylesheet' => 'Passerelle de paiement - feuille de style CSS', + 'Payment gateway - after javascript include' => 'Passerelle de paiement - après l\'inclusion du JavaScript', + 'Payment gateway - after javascript initialisation' => 'Passerelle de paiement - après l\'initialisation du JavaScript', + 'Payment gateway - javascript' => 'Passerelle de paiement - javascript', + 'Payment gateway - main area' => 'Passerelle de paiement - zone principale', + 'Pennsylvania' => 'Pennsylvanie', + 'Peru' => 'Pérou', + 'Perugia' => 'Pérouse', + 'Pesaro-Urbino' => 'Pesaro-Urbino', + 'Pescara' => 'Pescara', + 'Peso' => 'Peso', + 'Peso Argentino' => 'Peso Argentin', + 'Philippine Peso' => 'Peso Philippin', + 'Philippines' => 'Philippines', + 'Piacenza' => 'Piacenza', + 'Pisa' => 'Pise', + 'Pistoia' => 'Pistoia', + 'Placed order - CSS stylesheet' => 'Commande terminée - feuille de style CSS', + 'Placed order - after javascript include' => 'Commande terminée - après l\'inclusion du JavaScript', + 'Placed order - after javascript initialisation' => 'Commande terminée - après l\'initialisation du JavaScript', + 'Placed order - main area' => 'Commande terminée - zone principale', + 'Poland' => 'Pologne', + 'Polynésie française' => 'Polynésie française', + 'Pordenone' => 'Pordenone', + 'Portugal' => 'Portugal', + 'Potenza' => 'Potenza', + 'Pound' => 'Livre', + 'Prato' => 'Prato', + 'Prince Edward Island' => 'Île-du-Prince-Édouard', + 'Processing' => 'Traitement', + 'Product' => 'Produit', + 'Product - Edit JavaScript' => 'Produit - Modification de JavaScript', + 'Product - Tab' => 'Produit - Onglet', + 'Product - accessories table header' => 'Produit - colonne tableau accessoires', + 'Product - accessories table row' => 'Produit - ligne tableau accessoires', + 'Product - after combinations' => 'Produit - après les déclinaisons', + 'Product - at the bottom of a product combination' => 'Produit - en bas d\'une combinaison de déclinaisons', + 'Product - attributes table header' => 'Produit - colonne tableau attributs', + 'Product - attributes table row' => 'Produit - ligne tableau attributs', + 'Product - before combinations' => 'Produit - avant les déclinaisons', + 'Product - categories table header' => 'Produit - colonne tableau catégories', + 'Product - categories table row' => 'Produit - ligne tableau catégories', + 'Product - combination delete form' => 'Produit - formulaire de suppression de combinaison', + 'Product - combinations list caption' => 'Produit - légende liste des déclinaisons', + 'Product - content' => 'Produit - contenu', + 'Product - contents table header' => 'Produit - colonne tableau contenus', + 'Product - contents table row' => 'Produit - ligne tableau contenus', + 'Product - create form' => 'Produit - formulaire de création', + 'Product - delete form' => 'Produit - formulaire de suppression', + 'Product - details pricing form' => 'Produit - Formulaire détail des prix', + 'Product - details promotion form' => 'Produit - Formulaire détail des promotions', + 'Product - features table row' => 'Produit - ligne tableau caractéristiques', + 'Product - features-table-header' => 'Produit - colonne tableau caractéristiques', + 'Product - folders table header' => 'Produit - colonne tableau dossiers', + 'Product - folders table row' => 'Produit - ligne tableau dossiers', + 'Product - stock edit form' => 'Produit - formulaire de modification du stock', + 'Product edit - bottom' => 'Édition d\'un produit - en bas', + 'Product edit - right column bottom' => 'Édition d\'un produit - en bas de la colonne de droite', + 'Product edit - right column top' => 'Édition d\'un produit - en haut de la colonne de droite', + 'Product edit - top' => 'Édition d\'un produit - en haut', + 'Product loop - at the bottom' => 'Boucle produit - en bas', + 'Product loop - at the top' => 'Boucle produit - en haut', + 'Product page - CSS stylesheet' => 'Page produit - feuille de style CSS', + 'Product page - On the bottom of the form' => 'Page produit - En bas du formulaire', + 'Product page - On the top of the form' => 'Page produit - En haut du formulaire', + 'Product page - additional information' => 'Page produit - informations additionnelles', + 'Product page - after javascript include' => 'Page produit - après l\'inclusion du JavaScript', + 'Product page - after javascript initialisation' => 'Page produit - après l\'initialisation du JavaScript', + 'Product page - at the bottom' => 'Page produit - en bas', + 'Product page - at the bottom of the detail area' => 'Page produit - en dessous de la zone de détail', + 'Product page - at the top' => 'Page produit - en haut', + 'Product page - at the top of the detail' => 'Page produit - en haut de la zone détail', + 'Product page - photo gallery' => 'Page produit - galerie photos', + 'Products - caption' => 'Produits - légende', + 'Products - header' => 'Produits - en-tête', + 'Products - row' => 'Produits - ligne', + 'Products offer block' => 'Bloc promotions', + 'Profile - Edit JavaScript' => 'Profil - Modification de JavaScript', + 'Profile - create form' => 'Profil - formulaire de création', + 'Profile - delete form' => 'Profil - formulaire de suppression', + 'Profile - table header' => 'Profil - colonne tableau', + 'Profile - table row' => 'Profil - ligne du tableau', + 'Profile edit - bottom' => 'Édition d\'un profil - en bas', + 'Profile edit - top' => 'Édition d\'un profil - en haut', + 'Profiles - JavaScript' => 'Profils - JavaScript', + 'Profiles - at the top' => 'Profils - en haut', + 'Profiles - bottom' => 'Profils - en bas', + 'Puebla' => 'Puebla', + 'Puerto Rico' => 'Porto Rico', + 'Qatar' => 'Qatar', + 'Quebec' => 'Québec', + 'Querétaro' => 'Querétaro', + 'Quetzal' => 'Quetzal', + 'Quintana Roo' => 'Quintana Roo', + 'Ragusa' => 'Ragusa', + 'Ravenna' => 'Ravenne', + 'Real' => 'Real', + 'Refunded' => 'Remboursé', + 'Reggio Calabria' => 'Reggio de Calabre', + 'Reggio Emilia' => 'Reggio d\'Émilie', + 'Register - CSS stylesheet' => 'Création de compte - feuille de style CSS', + 'Register - after javascript include' => 'Création de compte - après l\'inclusion du JavaScript', + 'Register - after javascript initialisation' => 'Création de compte - après l\'initialisation du JavaScript', + 'Register - at the bottom' => 'Création de compte - en bas', + 'Register - at the bottom of the form' => 'Création de compte - en bas du formulaire', + 'Register - at the top' => 'Création de compte - en haut', + 'Register - at the top of the form' => 'Création de compte - en haut du formulaire', + 'Rhode Island' => 'Rhode Island', + 'Riau' => 'Riau', + 'Rieti' => 'Rieti', + 'Rimini' => 'Rimini', + 'Ringgit' => 'Ringgit', + 'Riyal' => 'Riyal', + 'Roma' => 'Rome', + 'Romania' => 'Roumanie', + 'Rovigo' => 'Rovigo', + 'Ruble' => 'Rouble', + 'Rupee' => 'Roupie Pakistanaise', + 'Rupiah' => 'Roupie Indonésienne', + 'Russia' => 'Russie', + 'Rwanda' => 'Rwanda', + 'Réunion(La)' => 'Réunion(La)', + 'Río Negro' => 'Rio Negro', + 'Saga' => 'Saga', + 'Saint Barthélemy' => 'Saint-Barthélemy', + 'Saint Kitts and Nevis' => 'Saint-Christophe-et-Niévès', + 'Saint Lucia' => 'Sainte-Lucie', + 'Saint Martin (French part)' => 'Saint-Martin (Antilles françaises)', + 'Saint Vincent and the Grenadines' => 'Saint-Vincent-et-les Grenadines', + 'Saitama' => 'Saitama', + 'Sale - CSS stylesheet' => 'Promotion - feuille de style CSS', + 'Sale - after javascript include' => 'Promotion - après l\'inclusion du JavaScript', + 'Sale - after the main content area' => 'Promotion - en dessous de la zone de contenu principale', + 'Sale - at the bottom' => 'Promotion - en bas', + 'Sale - at the bottom of the main area' => 'Promotion - en bas de la zone principal', + 'Sale - at the top' => 'Promotion - en haut', + 'Sale - at the top of the main area' => 'Promotion - en haut de la zone principal', + 'Sale - before the main content area' => 'Promotion - au dessous de la zone de contenu principale', + 'Sale - create form' => 'Promotion - formulaire de création', + 'Sale - delete form' => 'Promotion - formulaire de suppression', + 'Sale - javascript initialization' => 'Promotion - initialisation du JavaScript', + 'Sale edit - bottom' => 'Édition d\'une promotion - en bas', + 'Sale edit - top' => 'Édition d\'une promotion - en haut', + 'Sale edit page - javascript last call block' => 'Page sale edit - appel javascript', + 'Salerno' => 'Salerno', + 'Sales - JavaScript' => 'Promotions - JavaScript', + 'Sales - at the bottom' => 'Promotions - en bas', + 'Sales - at the top' => 'Promotions - en haut', + 'Sales - table header' => 'Promotions - colonne tableau', + 'Sales - table row' => 'Promotions - ligne du tableau', + 'Sales management' => 'Gestion des promotions', + 'Salta' => 'Salta', + 'San Juan' => 'San Juan', + 'San Luis' => 'San Luis', + 'San Luis Potosí' => 'San Luis Potosí', + 'San Marino' => 'Saint-Marin', + 'Santa Cruz' => 'Santa Cruz', + 'Santa Fe' => 'Santa Fe', + 'Santiago del Estero' => 'Santiago del Estero', + 'Sao Tome and Principe' => 'Sao Tomé-et-Principe', + 'Saskatchewan' => 'Saskatchewan', + 'Sassari' => 'Sassari', + 'Saudi Arabia' => 'Arabie saoudite', + 'Savona' => 'Savona', + 'Search' => 'Recherche', + 'Search - JavaScript' => 'Recherche - JavaScript', + 'Search - at the top' => 'Recherche - en haut', + 'Search - bottom' => 'Recherche - en bas', + 'Search block' => 'Bloc de recherche', + 'Search page - CSS stylesheet' => 'Page de recherche - feuille de style CSS', + 'Search page - after javascript include' => 'Page de recherche - après l\'inclusion du JavaScript', + 'Search page - after javascript initialisation' => 'Page de recherche - après l\'initialisation du JavaScript', + 'Secret key for form CSRF token' => 'Clé secrète pour le jeton CSRF des formulaires', + 'Send a confirmation email to newsletter subscribers (1 = yes, 0 = no)' => 'Envoyer un email de confirmation aux abonnés de la newsletter (1 = Oui, 0 = non)', + 'Senegal' => 'Sénégal', + 'Sent' => 'Envoyée', + 'Seychelles' => 'Seychelles', + 'Shekel' => 'Shekel', + 'Shiga' => 'Shiga', + 'Shimane' => 'Shimane', + 'Shipping configuration' => 'Configuration du transport', + 'Shipping configuration - Edit' => 'Configuration du transport - Modification', + 'Shipping configuration - Edit JavaScript' => 'Configuration du transport - Modification de JavaScript', + 'Shipping configuration - JavaScript' => 'Configuration du transport - JavaScript', + 'Shipping configuration - at the top' => 'Configuration du transport - en haut', + 'Shipping configuration - bottom' => 'Configuration du transport - en bas', + 'Shipping configuration - country delete form' => 'Configuration du transport - formulaire de suppression de pays', + 'Shipping configuration - create form' => 'Configuration du transport - formulaire de création', + 'Shipping configuration - delete form' => 'Configuration du transport - formulaire de suppression', + 'Shipping configuration - table header' => 'Configuration du transport - colonne tableau', + 'Shipping configuration - table row' => 'Configuration du transport - ligne tableau', + 'Shipping configuration edit - bottom' => 'Édition d\'une zone de livraiso - en bas', + 'Shipping configuration edit - top' => 'Édition d\'une zone de livraison - en haut', + 'Shipping zones edit - bottom' => 'Édition des zones de livraison d\'un transporteur - en bas', + 'Shipping zones edit - top' => 'Édition des zones de livraison d\'un transporteur - en haut', + 'Shizuoka' => 'Shizuoka', + 'Show error message instead of a white page on a server error' => 'Afficher un message d\'erreur à la place d\'une page blanche lors d\'une erreur serveur', + 'Siena' => 'Siena', + 'Sierra Leone' => 'Sierra Léone', + 'Sinaloa' => 'Sinaloa', + 'Singapore' => 'Singapour', + 'Siracusa' => 'Siracusa', + 'Sitemap - at the bottom' => 'Sitemap - en bas', + 'Slovakia' => 'Slovaquie', + 'Slovenia' => 'Slovénie', + 'Smarty template engine integration' => 'Intégration du moteur de template Smarty', + 'Social Networks block' => 'Bloc réseaux sociaux', + 'Solomon Islands' => 'Salomon', + 'Somalia' => 'Somalie', + 'Sondrio' => 'Sondrio', + 'Sonora' => 'Sonora', + 'South Africa' => 'Afrique du Sud', + 'South Carolina' => 'Caroline du Sud', + 'South Dakota' => 'Dakota du Sud', + 'South Kalimantan' => 'Kalimantan du Sud', + 'South Korea' => 'Corée du Sud', + 'South Sulawesi' => 'Sulawesi du Sud', + 'South Sumatra' => 'Sumatra du Sud', + 'Southeast Sulawesi' => 'Sulawesi du sud-est', + 'Spain' => 'Espagne', + 'Sri Lanka' => 'Sri Lanka', + 'St Pierre et Miquelon' => 'St Pierre et Miquelon', + 'Store Information - JavaScript' => 'Information boutique - JavaScript', + 'Store information configuration' => 'Configuration des informations sur la boutique', + 'Sudan' => 'Soudan', + 'Suriname' => 'Suriname', + 'Swaziland' => 'Swaziland', + 'Sweden' => 'Suède', + 'Switzerland' => 'Suisse', + 'Syria' => 'Syrie', + 'System - logs JavaScript' => 'Système - logs JavaScript', + 'Tab SEO - bottom' => 'Onglet SEO - en bas', + 'Tab SEO - top' => 'Onglet SEO - en haut', + 'Tab SEO - update form' => 'Onglet SEO - formulaire de mise à jour', + 'Tab document - bottom' => 'Onglet document - en bas', + 'Tab document - top' => 'Onglet document - en haut', + 'Tab image - bottom' => 'Onglet image - en bas', + 'Tab image - top' => 'Onglet image - en haut', + 'Tabasco' => 'Tabasco', + 'Tajikistan' => 'Tadjikistan', + 'Tamaulipas' => 'Tamaulipas', + 'Tanzania' => 'Tanzanie', + 'Taranto' => 'Taranto', + 'Tax - Edit JavaScript' => 'Taxe - Modification de JavaScript', + 'Tax - create form' => 'Taxe - formulaire de création', + 'Tax - delete form' => 'Taxe - formulaire de suppression', + 'Tax edit - bottom' => 'Édition d\'une taxe - en bas', + 'Tax edit - top' => 'Édition d\'une taxe - en haut', + 'Tax rule edit - bottom' => 'Édition d\'une règle de taxe - en bas', + 'Tax rule edit - top' => 'Édition d\'une règle de taxe - en haut', + 'Tax rules configuration' => 'Configuration des règles de taxes', + 'Taxes - update form' => 'Taxes - formulaire de modification', + 'Taxes rules - JavaScript' => 'Règles de taxes - JavaScript', + 'Taxes rules - at the top' => 'Règles de taxes - en haut', + 'Taxes rules - bottom' => 'Règles de taxes - en bas', + 'Template - Edit JavaScript' => 'Gabarit - Modification de JavaScript', + 'Template - attributes table header' => 'Gabarit - colonne tableau attributs', + 'Template - attributes table row' => 'Gabarit - ligne tableau attributs', + 'Template - create form' => 'Gabarit - formulaire de création', + 'Template - delete form' => 'Gabarit - formulaire de suppression', + 'Template - features table row' => 'Gabarit - ligne tableau caractéristiques', + 'Template - features-table-header' => 'Gabarit - colonne tableau caractéristiques', + 'Template edit - bottom' => 'Édition d\'un gabarit - en bas', + 'Template edit - top' => 'Édition d\'un gabarit - en haut', + 'Templates - JavaScript' => 'Gabarits - JavaScript', + 'Templates - at the top' => 'Gabarits - en haut', + 'Templates - bottom' => 'Gabarits - en bas', + 'Templates - table header' => 'Gabarits - colonne tableau', + 'Templates - table row' => 'Gabarits - ligne tableau', + 'Tennessee' => 'Tennessee', + 'Teramo' => 'Teramo', + 'Terni' => 'Terni', + 'Texas' => 'Texas', + 'Thailand' => 'Thaïlande', + 'The ID of the \'Terms & Conditions\' content.' => 'L\'ID du contenu de vos \'CGV\'.', + 'The ID of the folder containing your information pages : terms, imprint, ...' => 'L\'ID du dossier contenant vos pages d\'informations : CGV, mentions légales, ...', + 'The Vatican' => 'Vatican', + 'The default quality (in %) of the generated images' => 'La qualité par défaut (en %) dans les images générées', + 'The minimum length required for an administrator password' => 'La longueur minimale requise pour un mot de passe administrateur', + 'The path (relative to the default back-office template) to the image used when no flag image can be found for a country' => 'Le chemin (par rapport au modèle de back-office par défaut) vers l\'image utilisée lorsque aucune image de drapeau ne peut être trouvée pour un pays', + 'The path to the document cache directory in the web space' => 'Chemin d\'accès au répertoire de cache de documents dans l\'espace web', + 'The path to the image cache directory in the web space' => 'Chemin vers le répertoire de cache d\'images dans l\'espace web', + 'Tierra del Fuego' => 'Tierra del Fuego', + 'TinyMCE WYSIWYG editor' => 'Editeur visuel TinyMCE', + 'Tlaxcala' => 'Tlaxcala', + 'Tochigi' => 'Tochigi', + 'Togo' => 'Togo', + 'Tokushima' => 'Tokushima', + 'Tokyo' => 'Tokyo', + 'Tonga' => 'Îles Tonga', + 'Tools - JavaScript' => 'Outils - JavaScript', + 'Tools - at the bottom of column 1' => 'Outils - en bas de la colonne 1', + 'Tools - at the top' => 'Outils - en haut', + 'Tools - at the top of the column' => 'Outils - en haut de la colonne', + 'Tools - bottom' => 'Outils - en bas', + 'Tools panel' => 'Outils', + 'Torino' => 'Torino', + 'Tottori' => 'Tottori', + 'Toyama' => 'Toyama', + 'Translations' => 'Traductions', + 'Translations - JavaScript' => 'Traductions - JavaScript', + 'Trapani' => 'Trapani', + 'Trento' => 'Trento', + 'Treviso' => 'Treviso', + 'Trieste' => 'Trieste', + 'Trinidad and Tobago' => 'Trinité-et-Tobago', + 'Tucumán' => 'Tucuman', + 'Tunisia' => 'Tunisie', + 'Tunisian Dinar' => 'Dinar Tunisien', + 'Turkey' => 'Turquie', + 'Turkmenistan' => 'Turkménistan', + 'Tuvalu' => 'Tuvalu', + 'UK Pound' => 'Livre anglaise', + 'US Virgin Islands' => 'Îles Vierges américaines', + 'USA' => 'États-Unis', + 'Udine' => 'Udine', + 'Uganda' => 'Ouganda', + 'Ukraine' => 'Ukraine', + 'United Arab Emirates' => 'Émirats arabes unis', + 'United Arab Emirates dirham' => 'Dirham des Émirats Arabes Unis', + 'United Kingdom' => 'Royaume-Uni', + 'United States Dollar' => 'Dollar Américain', + 'Update customer account - CSS stylesheet' => 'Modification compte client - feuille de style CSS', + 'Update customer account - after javascript include' => 'Modification compte client - après l\'inclusion du JavaScript', + 'Update customer account - after javascript initialisation' => 'Modification compte client - après l\'initialisation du JavaScript', + 'Update customer account - at the bottom' => 'Modification compte client - en bas', + 'Update customer account - at the bottom of the form' => 'Modification compte client - en bas du formulaire', + 'Update customer account - at the top' => 'Modification compte client - en haut', + 'Update customer account - at the top of the form' => 'Modification compte client - en haut du formulaire', + 'Uruguay' => 'Uruguay', + 'Use a persistent cookie to keep track of customer cart' => 'Utiliser un cookie persistant pour mémoriser le panier du client', + 'Utah' => 'Utah', + 'Uzbekistan' => 'Ouzbékistan', + 'Vanuatu' => 'Vanuatu', + 'Varese' => 'Varese', + 'Variable - Edit JavaScript' => 'Variable - Modification de JavaScript', + 'Variable - create form' => 'Variable - formulaire de création', + 'Variable - delete form' => 'Variable - formulaire de suppression', + 'Variable edit - bottom' => 'Édition d\'une variable - en bas', + 'Variable edit - top' => 'Édition d\'une variable - en haut', + 'Variables - JavaScript' => 'Variables - JavaScript', + 'Variables - at the top' => 'Variables - en haut', + 'Variables - bottom' => 'Variables - en bas', + 'Variables - table header' => 'Variables - colonne tableau', + 'Variables - table row' => 'Variables - ligne tableau', + 'Venezia' => 'Venezia', + 'Venezuela' => 'Vénézuela', + 'Veracruz' => 'Veracruz', + 'Verbano-Cusio-Ossola' => 'Verbano-Cusio-Ossola', + 'Vercelli' => 'Vercelli', + 'Vermont' => 'Vermont', + 'Verona' => 'Vérone', + 'Vibo Valentia' => 'Vibo Valentia', + 'Vicenza' => 'Vicenza', + 'Vietnam' => 'Viêt Nam', + 'View administration logs' => 'Consulter les logs d\'administration', + 'Virginia' => 'Virginie', + 'Virtual Product Controller' => 'Contôle de produit virtuel', + 'Viterbo' => 'Viterbo', + 'Wakayama' => 'Wakayama', + 'Wallis-et-Futuna' => 'Wallis-et-Futuna', + 'Washington' => 'Washington', + 'West Java' => 'Java-Ouest', + 'West Kalimantan' => 'Kalimantan occidental', + 'West Nusa Tenggara' => 'Nusa Tenggara occidental', + 'West Sulawesi' => 'Sulawesi occidental', + 'West Sumatra' => 'Sumatra occidental', + 'West Virginia' => 'Virginie-occidentale', + 'Western Samoa' => 'Samoa occidentales', + 'Where the WYSIWYG editor is required' => 'Partout ou l\'éditeur WYSIWYG est nécessaire', + 'Whitespace trim level of the generated HTML code (0 = none, 1 = medium, 2 = maximum)' => 'Niveau de découpe des espaces dans le code HTML généré (0 = aucun, 1 = moyen, 2 = maximum)', + 'Wisconsin' => 'Wisconsin', + 'Wyoming' => 'Wyoming', + 'Yamagata' => 'Yamagata', + 'Yamaguchi' => 'Yamaguchi', + 'Yamanashi' => 'Yamanashi', + 'Yemen' => 'Yémen', + 'Yen' => 'Yen', + 'Yogyakarta' => 'Yogyakarta', + 'You can now login at' => 'Vous pouvez maintenant vous connecter sur ', + 'You have lost your password
    \r\nPlease, change this password after your first connection' => 'Vous avez oublié votre mot de passe
    \r\nVeuillez modifier ce mot de passe après votre première connexion', + 'You have lost your password
    \r\nYour new password is' => 'Vous avez oublié votre mot de passe
    \r\nVotre nouveau mot de passe est ', + 'Your account information on {config key="store_name"} has been changed.' => 'L\'accès à votre compte {config key="store_name"} a changé', + 'Your new passord is : {$password}' => 'Votre nouveau mot de passe est : {$password}', + 'Your new password' => 'Votre nouveau mot de passe', + 'Your new password for {config key="store_name"}' => 'Votre nouveau mot de passe {config key="store_name"}', + 'Your order {$order_ref} at {config key="store_name"}' => 'Votre commande {$order_ref} chez {config key="store_name"}', + 'Your subscription to %store newsletter' => 'Votre abonnement à {config key="store_name"} newsletter', + 'Yuan' => 'Yuan', + 'Yucatán' => 'Yucatán', + 'Yukon' => 'Yukon', + 'Zacatecas' => 'Zacatecas', + 'Zaire' => 'Zaïre', + 'Zambia' => 'Zambie', + 'Zimbabwe' => 'Zimbabwe', + 'Zone - delete form' => 'Zone - formulaire de suppression', + 'Złoty' => 'Złoty', + '[Firewall/Bruteforce] Number of allowed attemps' => '[Pare-feu/Bruteforce] Nombre de tentatives autorisées', + '[Firewall/Bruteforce] Time to wait between X attempts' => '[Pare-feu/Bruteforce] Temps à attendre entre X essais', + '[Firewall] Activate the firewall' => '[Pare-feu] Activer le pare-feu', + '[Firewall] Number of allowed attemps' => '[Pare-feu] Nombre de tentatives autorisées', + '[Firewall] Time to wait between X attempts' => '[Pare-feu] Temps à attendre entre X essais', + 'changing password email for' => 'Changement du mot de passe pour', + 'customer account - CSS stylesheet' => 'Compte client - feuille de style CSS', + 'customer account - after javascript include' => 'Compte client - après l\'inclusion du JavaScript', + 'customer account - after javascript initialisation' => 'Compte client - après l\'initialisation du JavaScript', + 'customer account - at the bottom' => 'Compte client - en bas', + 'customer account - at the top' => 'Compte client - en haut', + 'export of newsletter subscribers' => 'Export des inscrits à la newsletter', + 'language selection page - CSS stylesheet' => 'Page du choix du langage - feuille de style CSS', + 'language selection page - after javascript include' => 'Page du choix du langage - après l\'inclusion du JavaScript', + 'language selection page - after javascript initialisation' => 'Page du choix du langage - après l\'initialisation du JavaScript', + 'language selection page - at the bottom' => 'Page du choix du langage - en bas', + 'language selection page - at the top' => 'Page du choix du langage - en haut', + 'state - Edit JavaScript' => 'Etat - JavaScript modification', + 'state - creation form' => 'état - formulaire de création', + 'state - delete form' => 'état - formulaire de suppression', + 'state-edit - at the top' => 'édition d\'un état - en haut', + 'state-edit - bottom' => 'édition d\'un état - en bas', + 'states - JavaScript' => 'états - JavaScript', + 'states - at the top' => 'états - en haut', + 'states - bottom' => 'états - bas', + 'states - table header' => 'états - colonne tableau', + 'states - table row' => 'états - ligne du tableau', + 'tax rule - Edit JavaScript' => 'Règle de taxe - Modification de JavaScript', + 'tax rule - create form' => 'Règle de taxe - formulaire de création', + 'tax rule - delete form' => 'Règle de taxe - formulaire de suppression', + 'tinymce wysiwyg editor' => 'Editeur TinyMCE', + 'Đồng' => 'Đồng', + 'Гривна' => 'Hryvnia Ukrainien', + 'Default Tax Rule' => 'Règle de taxes par défaut', + 'French 10% VAT (France only)' => 'TVA française à 10% (France métropolitaine seulement)', + 'French 20% VAT for all European countries (metropolitan only)' => 'TVA Française a 20% pour tous les pays en Europe (hors DOM TOM)', + 'French 10% VAT (for metropolitan France only)' => 'TVA Française à 10% (France métropolitaine seulement)', +); diff --git a/setup/I18n/hu_HU.php b/setup/I18n/hu_HU.php new file mode 100644 index 00000000..b09b55fe --- /dev/null +++ b/setup/I18n/hu_HU.php @@ -0,0 +1,17 @@ + 'Cím', + 'Advanced configuration' => 'Speciális beállítások', + 'Category' => 'Kategória', + 'Configuration' => 'Beállítások', + 'Content' => 'Tartalom', + 'Coupon' => 'Kupon', + 'Customer' => 'Ügyfél', + 'New York' => 'New York', + 'Product' => 'Termék', + 'Sales management' => 'Kampányok kezelése', + 'Search' => 'Keresés', + 'Shipping configuration' => 'Szállítási beállítások', + 'Translations' => 'Fordítások', +]; diff --git a/setup/I18n/id_ID.php b/setup/I18n/id_ID.php new file mode 100644 index 00000000..c37c8e05 --- /dev/null +++ b/setup/I18n/id_ID.php @@ -0,0 +1,49 @@ + '"Ingatkan saya" waktu kedaluwarsa kuki, secepatnya, untuk pengguna bagian administrasi', + '"Remember me" cookie expiration time, in seconds, for customer users' => '"Ingatkan saya" waktu kedaluwarsa kuki, secepatnya, untuk pelanggan', + '"Remember me" cookie name for administration users' => '"Ingatkan saya" nama kuki untuk administrator', + '"Remember me" cookie name for customer users' => '"Ingatkan saya" nama kuki untuk pelanggan', + '72h delivery' => 'Pengiriman 72 jam', + 'A {config key="store_name"} account has been created for you' => 'Sebuah akun {config key="store_name"} telah dibuat', + 'API Configuration' => 'Konfigurasi API', + 'Aceh' => 'Aceh', + 'Address' => 'Alamat', + 'Address creation - CSS stylesheet' => 'Kreasi alamat - CSS stylesheet', + 'Address creation - after javascript include' => 'Kreasi alamat - setelah mencakup javascript', + 'Address creation - after javascript initialisation' => 'Kreasi alamat - setelah inisiasi javascript', + 'Address creation - at the bottom' => 'Kreasi alamat - di bagian bawah', + 'Address creation - at the bottom of the form' => 'Kreasi alamat - di bawah formulir', + 'Address creation - at the top' => 'Kreasi alamat - di atas', + 'Address creation - at the top of the form' => 'Kreasi alamat - di atas formulir', + 'Address update - CSS stylesheet' => 'Alamat diperbarui - CSS stylesheet', + 'Address update - after javascript include' => 'Alamat diperbarui - setelah mencakup javascript', + 'Address update - after javascript initialisation' => 'Alamat diperbarui - setelah mencakup javascript', + 'Address update - at the bottom' => 'Alamat diubah - di bagian bawah', + 'Address update - at the bottom of the form' => 'Alamat diubah - di bawah formulir', + 'Address update - at the top' => 'Alamat diperbarui - di atas', + 'Address update - at the top of the form' => 'Alamat diubah - di atas formulir', + 'Admin layout - After the main content' => 'Tata letak admin - setelah konten utama', + 'Administatros list' => 'Daftar administrator', + 'Administration profiles management' => 'Manajemen profil administrasi', + 'Administrator - create form' => 'Administrator - buat formulir', + 'Administrator - delete form' => 'Administrator - hapus formulir', + 'Administrator - update form' => 'Administrator - Perbarui formulir', + 'Administrator list' => 'Daftar administrator', + 'Administrators - JavaScript' => 'Administrator - JavaScript', + 'Administrators - at the top' => 'Administrator - di atas', + 'Administrators - bottom' => 'Administrator - bawah', + 'Administrators - header' => 'Administrator - header', + 'Administrators - row' => 'Administrator - baris', + 'Alabama' => 'Alabama', + 'Alaska' => 'Alaska', + 'All Products - at the top' => 'Semua produk - di atas', + 'Allow customers to change their email. 1 for yes, 0 for no' => 'Memungkinkan pelanggan untuk mengubah email mereka. 1 untuk ya, 0 untuk tidak', + 'Category' => 'Kategori', + 'Content' => 'Konten', + 'Folder' => 'Folder', + 'Hooks' => 'Kaitan', + 'Order' => 'Pesan', + 'Translations' => 'Alih Bahasa', +]; diff --git a/setup/I18n/it_IT.php b/setup/I18n/it_IT.php new file mode 100644 index 00000000..bce278c0 --- /dev/null +++ b/setup/I18n/it_IT.php @@ -0,0 +1,165 @@ + 'Configurazione API', + 'Address' => 'Indirizzo', + 'Advanced configuration' => 'Configurazione avanzata', + 'Agrigento' => 'Agrigento', + 'Akita' => 'Akita', + 'Alabama' => 'Alabama', + 'Alaska' => 'Alaska', + 'Alberta' => 'Alberta', + 'Alessandria' => 'Alessandria', + 'Ancona' => 'Ancona', + 'Aosta' => 'Aosta', + 'Arezzo' => 'Arezzo', + 'Arizona' => 'Arizona', + 'Arkansas' => 'Arkansas', + 'Ascoli Piceno' => 'Ascoli Piceno', + 'Asti' => 'Asti', + 'Avellino' => 'Avellino', + 'Bali' => 'Bali', + 'Bari' => 'Bari', + 'Belluno' => 'Belluno', + 'Benevento' => 'Benevento', + 'Bergamo' => 'Bergamo', + 'Biella' => 'Biella', + 'Bologna' => 'Bologna', + 'Brescia' => 'Brescia', + 'Brindisi' => 'Brindisi', + 'Buenos Aires' => 'Buenos Aires', + 'Cagliari' => 'Cagliari', + 'California' => 'California', + 'Caltanissetta' => 'Caltanissetta', + 'Campobasso' => 'Campobasso', + 'Canada' => 'Canada', + 'Caserta' => 'Caserta', + 'Catania' => 'Catania', + 'Catanzaro' => 'Catanzaro', + 'Category' => 'Categoria', + 'Chieti' => 'Chieti', + 'Colorado' => 'Colorado', + 'Como' => 'Como', + 'Configuration' => 'Impostazioni', + 'Content' => 'Contenuto', + 'Cosenza' => 'Cosenza', + 'Coupon' => 'Promozione', + 'Cremona' => 'Cremona', + 'Crotone' => 'Crotone', + 'Cuneo' => 'Cuneo', + 'Customer' => 'Cliente', + 'Ferrara' => 'Ferrara', + 'Firenze' => 'Firenze', + 'Florida' => 'Florida', + 'Foggia' => 'Foggia', + 'Folder' => 'Cartella', + 'Forlì-Cesena' => 'Forlì-Cesena', + 'French Southern Territories' => 'Terre australi e antartiche francesi', + 'Genova' => 'Genova', + 'Gorizia' => 'Gorizia', + 'Hook positions' => 'Posizioni dell\'hook', + 'Idaho' => 'Idaho', + 'Illinois' => 'Illinois', + 'Imperia' => 'Imperia', + 'Jakarta' => 'Jakarta', + 'Kansas' => 'Kansas', + 'Kentucky' => 'Kentucky', + 'L\'Aquila' => 'L\'Aquila', + 'La Spezia' => 'La Spezia', + 'Lari' => 'Lari', + 'Latina' => 'Latina', + 'Lecce' => 'Lecce', + 'Lecco' => 'Lecco', + 'Livorno' => 'Livorno', + 'Lodi' => 'Lodi', + 'Louisiana' => 'Louisiana', + 'Lucca' => 'Lucca', + 'Macerata' => 'Macerata', + 'Maine' => 'Maine', + 'Mantova' => 'Mantova', + 'Maryland' => 'Maryland', + 'Massa' => 'Massa', + 'Massachusetts' => 'Massachusetts', + 'Matera' => 'Matera', + 'Medio Campidano' => 'Medio Campidano', + 'Messina' => 'Messina', + 'Michigan' => 'Michigan', + 'Milano' => 'Milano', + 'Minnesota' => 'Minnesota', + 'Mississippi' => 'Mississippi', + 'Missouri' => 'Missouri', + 'Modena' => 'Modena', + 'Montana' => 'Montana', + 'Napoli' => 'Napoli', + 'Nevada' => 'Nevada', + 'New Hampshire' => 'New Hampshire', + 'New Jersey' => 'New Jersey', + 'New York' => 'Roma', + 'North Carolina' => 'North Carolina', + 'North Dakota' => 'North Dakota', + 'Novara' => 'Novara', + 'Ohio' => 'Ohio', + 'Oklahoma' => 'Oklahoma', + 'Olbia-Tempio' => 'Olbia-Tempio', + 'Ontario' => 'Ontario', + 'Oregon' => 'Oregon', + 'Oristano' => 'Oristano', + 'Padova' => 'Padova', + 'Palermo' => 'Palermo', + 'Parma' => 'Parma', + 'Pavia' => 'Pavia', + 'Pennsylvania' => 'Pennsylvania', + 'Perugia' => 'Perugia', + 'Pesaro-Urbino' => 'Pesaro-Urbino', + 'Pescara' => 'Pescara', + 'Piacenza' => 'Piacenza', + 'Pisa' => 'Pisa', + 'Pistoia' => 'Pistoia', + 'Pordenone' => 'Pordenone', + 'Potenza' => 'Potenza', + 'Prato' => 'Prato', + 'Product' => 'Prodotto', + 'Puerto Rico' => 'Puerto Rico', + 'Quebec' => 'Quebec', + 'Ragusa' => 'Ragusa', + 'Ravenna' => 'Ravenna', + 'Reggio Calabria' => 'Reggio Calabria', + 'Reggio Emilia' => 'Reggio Emilia', + 'Rieti' => 'Rieti', + 'Rimini' => 'Rimini', + 'Saint Barthélemy' => 'Saint-Barthélemy', + 'Saint Martin (French part)' => 'Saint-Martin', + 'Salerno' => 'Salerno', + 'Sales management' => 'Gestione vendite', + 'Santa Cruz' => 'Santa Cruz', + 'Sassari' => 'Sassari', + 'Savona' => 'Savona', + 'Search' => 'Ricerca', + 'Shipping configuration' => 'Configurazione di spedizione', + 'Siena' => 'Siena', + 'Siracusa' => 'Siracusa', + 'Sondrio' => 'Sondrio', + 'Taranto' => 'Taranto', + 'Teramo' => 'Teramo', + 'Terni' => 'Terni', + 'Tokyo' => 'Tokyo', + 'Torino' => 'Torino', + 'Trapani' => 'Trapani', + 'Trento' => 'Trento', + 'Treviso' => 'Treviso', + 'Trieste' => 'Trieste', + 'USA' => 'USA', + 'Udine' => 'Udine', + 'Varese' => 'Varese', + 'Venezia' => 'Venezia', + 'Vercelli' => 'Vercelli', + 'Vermont' => 'Vermont', + 'Verona' => 'Verona', + 'Vibo Valentia' => 'Vibo Valentia', + 'Vicenza' => 'Vicenza', + 'Viterbo' => 'Viterbo', + 'Yucatán' => 'Yucatán', + 'language selection page - at the top' => 'pagina selezione lingua - nella parte superiore', + 'tax rule - Edit JavaScript' => 'regola fiscale - Modificare JavaScript', + 'tinymce wysiwyg editor' => 'tinymce wysiwyg editor', +]; diff --git a/setup/I18n/pl_PL.php b/setup/I18n/pl_PL.php new file mode 100644 index 00000000..be8f6b17 --- /dev/null +++ b/setup/I18n/pl_PL.php @@ -0,0 +1,479 @@ + '"Zapamiętaj mnie" czas ważności ciastka (cookie) w sekundach dla administratorów', + '"Remember me" cookie expiration time, in seconds, for customer users' => '"Zapamiętaj mnie" czas ważności ciastka (cookie) w sekundach, dla zalogowanych klientów', + '"Remember me" cookie name for administration users' => '"Zapamiętaj mnie" nazwa ciastka (cookie) dla administratorów', + '"Remember me" cookie name for customer users' => '"Zapamiętaj mnie" nazwa ciastka (cookie) dla zalogowanych klientów', + '72h delivery' => 'Dostawa w 72h', + 'A {config key="store_name"} account has been created for you' => '{config key="store_name"} konto zostało utworzone dla Ciebie', + 'API Configuration' => 'Konfiguracja interfejsu API', + 'Aceh' => 'Aceh', + 'Address creation - CSS stylesheet' => 'Tworzenie adresu - style CSS', + 'Address creation - after javascript include' => 'Tworzenie adresu - po załadowaniu javascript', + 'Address creation - after javascript initialisation' => 'Tworzenie adresu - po inicjalizacji javascript', + 'Address creation - at the bottom' => 'Tworzenie adresu - na dole', + 'Address creation - at the bottom of the form' => 'Tworzenie adresu - w dolnej części formularza', + 'Address creation - at the top' => 'Tworzenie adresu - na górze', + 'Address creation - at the top of the form' => 'Tworzenie adresu - w górnej części formularza', + 'Address update - CSS stylesheet' => 'Aktualizacja adresu - style CSS', + 'Address update - after javascript include' => 'Aktualizacja adresu - po załadowaniu javascript', + 'Address update - after javascript initialisation' => 'Aktualizacja adresu - po inicjalizacji javascript', + 'Address update - at the bottom' => 'Aktualizacja adresu - na dole', + 'Address update - at the bottom of the form' => 'Aktualizacja adresu - w dolnej części formularza', + 'Address update - at the top' => 'Aktualizacja adresu - na górze', + 'Address update - at the top of the form' => 'Aktualizacja adresu - w górnej części formularza', + 'Admin layout - After the main content' => 'Układ admin - Pod główną zawartością', + 'Administatros list' => 'Lista administratorów', + 'Administration profiles management' => 'Zarządzanie profilami administratorów', + 'Administrator - create form' => 'Administrator - formularz dodawania', + 'Administrator - delete form' => 'Administrator - formularz usuwania', + 'Administrator - update form' => 'Administrator - formularz modyfikacji', + 'Administrator list' => 'Lista administratorów', + 'Administrators - JavaScript' => 'Administratorzy - JavaScript', + 'Administrators - at the top' => 'Administratorzy - u góry', + 'Administrators - bottom' => 'Administratorzy - Dolny', + 'Administrators - header' => 'Administratorzy - nagłówek', + 'Administrators - row' => 'Administratorzy - wiersz', + 'Advanced Configuration' => 'Zaawansowana konfiguracja', + 'Advanced Configuration - Javascript' => 'Zaawansowana konfiguracja - po załadowaniu javascript', + 'Advanced configuration' => 'Zaawansowana konfiguracja', + 'Afghanistan' => 'Afganistan', + 'Albania' => 'Albania', + 'Algeria' => 'Algieria', + 'All Products - CSS stylesheet' => 'Wszystkie produkty -style CSS', + 'All Products - after javascript include' => 'Wszystkie produkty - po załadowaniu javascript', + 'All Products - after javascript initialisation' => 'Wszystkie produkty - po inicjalizacji javascript', + 'All Products - at the bottom' => 'Wszystkie produkty - na dole', + 'All Products - at the top' => 'Wszystkie produkty - na górze', + 'Allow an administrator to recreate a lost password (1 = yes, 0 = no)' => 'Pozwól administratorom na ponowne utworzenie hasła (1 = tak, 0 = nie)', + 'Allow customers to change their email. 1 for yes, 0 for no' => 'Zezwalaj klientom na zmianę adresu email. 1 - zezwalaj, 0 - nie zezwalaj', + 'Allow negative product stock (1) or not (0)' => 'Zezwalaj na ujemną liczbę produktów w magazynie, 1 - zezwalaj, 0 - nie zezwalaj', + 'Allow negative product stock (1) or not (0, default)' => 'Zezwalaj na ujemną liczbę produktów w magazynie, 1 - zezwalaj, 0 - nie zezwalaj (domyślnie)', + 'Allow slash ended uri' => 'Ukośnik na końcu adresu uri', + 'Ancona' => 'Ancona', + 'Andorra' => 'Andora', + 'Angola' => 'Angola', + 'Antigua and Barbuda' => 'Antigua i Barbuda', + 'Aomori' => 'Aomori', + 'Aosta' => 'Aosta', + 'Api page - at bottom' => 'Strona Api - na dole', + 'Api page - at top' => 'Strona Api - u góry', + 'Api page - in deletion form' => 'Api - formularz usuwania', + 'Argentina' => 'Argentyna', + 'Armenia' => 'Armenia', + 'Ask the customers to confirm their email, 1 for yes, 0 for no' => 'Poprosić klientów o potwierdzenie adresu email? 1 - tak, 0 - nie', + 'Attribut - Edit JavaScript' => 'Atrybut - edycja javascript', + 'Attribut - add to all form' => 'Atrybut - dodaj do wszystkich formularzy', + 'Attribut - create form' => 'Atrybuty - formularz dodawania', + 'Attribut - delete form' => 'Atrybuty - formularz usuwania', + 'Attribut - id delete form' => 'Atrybuty - Formularz usuwania (id)', + 'Attribut - remove to all form' => 'Atrybuty - formularz usuwania wielu atrybutów', + 'Attribute edit - bottom' => 'Edycja atrybutu - dół', + 'Attribute edit - top' => 'Edycja atrybutu - góra', + 'Australia' => 'Australia', + 'Austria' => 'Austria', + 'Avellino' => 'Avellino', + 'Azerbaijan' => 'Azerbejdżan', + 'Back-office home page' => 'Back-office strona główna', + 'Bahamas' => 'Bahamy', + 'Bahrain' => 'Bahrajn', + 'Baht' => 'Baht', + 'Baja California' => 'Baja California', + 'Bangladesh' => 'Bangladesz', + 'Barbados' => 'Barbados', + 'Base URL of the shop (e.g. http://www.yourshopdomain.com)' => 'Podstawowy URL sklepu (np. http://www.yourshopdomain.com)', + 'Belarus' => 'Białoruś', + 'Belgium' => 'Belgia', + 'Belize' => 'Belize', + 'Benin' => 'Benin', + 'Bergamo' => 'Bergamo', + 'Bhutan' => 'Bhutan', + 'Biella' => 'Biella', + 'Bielorussia' => 'Białoruś', + 'Bolivia' => 'Boliwia', + 'Boliviano' => 'Boliwijski', + 'Bologna' => 'Bolonia', + 'Bolzano' => 'Bolzano', + 'Bolívar fuerte' => 'Bolivar fuerte', + 'Bosnia and Herzegovina' => 'Bośnia i Hercegowina', + 'Botswana' => 'Botswana', + 'Brand - Edit JavaScript' => 'Marka - edycja javascript', + 'Brand - JavaScript' => 'Marka - JavaScript', + 'Brand - Tab' => 'Marka - zakładka', + 'Brand - content' => 'Marka - treść', + 'Brand - create form' => 'Marka - formularz dodawania', + 'Brand - delete form' => 'Marka - formularz usuwania', + 'Brand edit - bottom' => 'Edycja marki - dół', + 'Brand edit - right column bottom' => 'Edycja marki - prawa kolumna, dół', + 'Brand edit - right column top' => 'Edycja marki - prawa kolumna, góra', + 'Brand edit - top' => 'Edycja marki - góra', + 'Brand edit page - in the form' => 'Strona edycji marki - w formularzu', + 'Brands - at the top' => 'Marki - na górze', + 'Brands - bottom' => 'Marki - dół', + 'Brands - table header' => 'Marki - nagłówek tabeli', + 'Brands - table row' => 'Marki - wiersz tabeli', + 'Brands management' => 'Zarządzanie markami', + 'Brands page - CSS stylesheet' => 'Strona marek - style CSS', + 'Brazil' => 'Brazylia', + 'Brunei' => 'Brunei', + 'Bulgaria' => 'Bułgaria', + 'Burkina' => 'Burkina', + 'Burma' => 'Birma', + 'Burundi' => 'Burundi', + 'Cagliari' => 'Cagliari', + 'California' => 'Kalifornia', + 'Caltanissetta' => 'Caltanissetta', + 'Cambodia' => 'Kambodża', + 'Cameroon' => 'Kamerun', + 'Campeche' => 'Campeche', + 'Campobasso' => 'Campobasso', + 'Canada' => 'Kanada', + 'Canceled' => 'Anulowany', + 'Cape Verde' => 'Wyspy Zielonego Przylądka', + 'Carbonia-Iglesias' => 'Carbonia-Iglesias', + 'Cart - CSS stylesheet' => 'Koszyk - style CSS', + 'Cart - after javascript include' => 'Koszyk - po dołączeniu javascript', + 'Cart - at the bottom' => 'Koszyk - na dole', + 'Cart - at the top' => 'Koszyk - na górze', + 'Cart - javascript initialization' => 'Koszyk - inicjalizacja javascript', + 'Cart block' => 'Blok koszyka', + 'Categories - JavaScript' => 'Kategorie - JavaScript', + 'Categories - at the bottom of the catalog' => 'Kategorie - w dolnej części katalogu', + 'Categories - at the top' => 'Kategorie - na górze', + 'Categories - bottom' => 'Kategorie - dół', + 'Categories - caption' => 'Kategorie - podpis', + 'Categories - header' => 'Kategorie - nagłówek', + 'Categories - row' => 'Kategorii - wiersz', + 'Category' => 'Kategoria', + 'Category - Edit JavaScript' => 'Kategoria - edycja JavaScript', + 'Category - Tab' => 'Kategoria - Zakładka', + 'Category - content' => 'Kategoria - treść', + 'Category - contents table header' => 'Kategoria - zawartość nagłówka tabeli', + 'Category - contents table row' => 'Kategoria - zawartość wiersza tabeli', + 'Category configuration' => 'Konfiguracja kategorii', + 'Category edit - bottom' => 'Edycja kategorii - dół', + 'Category edit - top' => 'Edycja kategorii - góra', + 'Category page - CSS stylesheet' => 'Strona kategorii - style CSS', + 'Category page - after javascript include' => 'Strona kategorii - po dołączeniu javascript', + 'Category page - after javascript initialisation' => 'Strona kategorii - po inicjalizacji javascript', + 'Category page - after the main content area' => 'Strona kategorii - pod obszarem głównej treści', + 'Category page - at the bottom' => 'Strona kategorii - na dole', + 'Category page - at the bottom of the main area' => 'Strona kategorii - w dolnej części głównego obszaru', + 'Category page - at the bottom of the sidebar' => 'Strona kategorii - na dole paska bocznego', + 'Category page - at the top' => 'Strona kategorii - na górze', + 'Category page - at the top of the main area' => 'Strona kategorii - w górnej części obszaru głównego', + 'Category page - at the top of the sidebar' => 'Strona kategorii - w górnej części paska bocznego', + 'Category page - before the main content area' => 'Strona kategorii - przed obszarem głównej treści', + 'Category page - the body of the sidebar' => 'Strona kategorii - body paska bocznego', + 'Central African Republic' => 'Republika Środkowej Afryki', + 'Chad' => 'Czad', + 'Change password - CSS stylesheet' => 'Zmiana hasła - CSS', + 'Change password - after javascript include' => 'Zmiana hasła - po dołączeniu plików javascript', + 'Change password - after javascript initialisation' => 'Zmiana hasła - po inicjalizacji javascript', + 'Change password - at the bottom' => 'Zmiana hasła - na dole', + 'Configuration' => 'Konfiguracja', + 'Configuration - at the top' => 'Konfiguracja - na górze', + 'Configuration - at the top of the catalog area' => 'Konfiguracja - w górnej części obszaru katalog', + 'Configuration - at the top of the shipping area' => 'Konfiguracja - w górnej części obszaru dostawy', + 'Configuration - at the top of the system area' => 'Konfiguracja - w górnej części obszaru systemu', + 'Configuration - bottom' => 'Konfiguracja - góra', + 'Configuration / Administrator' => 'Konfiguracja / Administrator', + 'Configuration / Area' => 'Konfiguracja / Obszar', + 'Configuration / Attribute' => 'Konfiguracja / Atrybut', + 'Configuration / Cache' => 'Konfiguracja / Cache', + 'Configuration / Country' => 'Konfiguracja / Kraj', + 'Configuration / Currency' => 'Konfiguracja / Waluty', + 'Configuration / Feature' => 'Konfiguracja / Cecha', + 'Configuration / Language' => 'Konfiguracja / Język', + 'Configuration / Mailing-system' => 'Konfiguracja / Mailing-system', + 'Configuration / Message' => 'Konfiguracja / Wiadomości', + 'Configuration / Module' => 'Konfiguracja / Moduł', + 'Configuration / Profile' => 'Konfiguracja / Profil', + 'Configuration / Shipping-zone' => 'Konfiguracja / strefy dostawy', + 'Configuration / System Log' => 'Konfiguracja / System Logowania', + 'Configuration / Tax' => 'Konfiguracja / Podatek', + 'Configuration / Template' => 'Konfiguracja / Szablon', + 'Configuration variables' => 'Zmienne konfiguracyjne', + 'Congo' => 'Kongo', + 'Contact block' => 'Blok kontakt', + 'Contact page - CSS stylesheet' => 'Strona kontaktowa - style CSS', + 'Contact page - after javascript include' => 'Strona kontaktowa - po dołączeniu plików javascript', + 'Contact page - after javascript initialisation' => 'Strona kontaktowa - po inicjalizacji javascript', + 'Contact page - at the bottom' => 'Kontakt - na dole', + 'Contact page - at the bottom of the form' => 'Kontakt - w dolnej części formularza', + 'Contact page - at the top' => 'Kontakt - na górze', + 'Contact page - at the top of the form' => 'Kontakt - w górnej części formularza', + 'Contact page - if successful response' => 'Kontakt strona - jeśli udana odpowiedź', + 'Content' => 'Zawartość', + 'Content - Edit JavaScript' => 'Treść - edycja JavaScript', + 'Content - Tab' => 'Treść - Zakładka', + 'Content - content' => 'Zawartość - treści', + 'Costa Rica' => 'Kostaryka', + 'Countries - JavaScript' => 'Kraje - JavaScript', + 'Countries - at the top' => 'Krajach - na górze', + 'Countries - bottom' => 'Kraje - dół', + 'Countries - table header' => 'Kraje - nagłówek tabeli', + 'Countries - table row' => 'Kraje - wiersz tabeli', + 'Country - Edit JavaScript' => 'Kraj - edycja JavaScript', + 'Croatia' => 'Chorwacja', + 'Cuba' => 'Kuba', + 'Customer - Edit' => 'Klient - Edycja', + 'Customer - Edit JavaScript' => 'Klient - edycja JavaScript', + 'Customer - address create form' => 'Klient - formularz tworzenia adresu', + 'Customer - address update form' => 'Klient - formularz aktualizacji adresu', + 'Customer - at the top' => 'Klient - na górze', + 'Customer - bottom' => 'Klient - dół', + 'Customer - create form' => 'Klient - formularz tworzenia', + 'Customer - delete form' => 'Klient - formularz usuwania', + 'Customer - order table header' => 'Klient - nagłówek tabeli zamówienia', + 'Customer - order table row' => 'Klient - wiersz tabeli zamówienia', + 'Customer account - additional information' => 'Konto klienta - dodatkowe informacje', + 'Customer account block' => 'Blok konta klienta', + 'Customer title' => 'Tytuł klienta', + 'Customers - JavaScript' => 'Klienci - JavaScript', + 'Customers - header' => 'Klienci - nagłówek', + 'Customers - row' => 'Klienci - wiersz', + 'Cyprus' => 'Cypr', + 'Czech Republic' => 'Republika Czeska', + 'Dashboard - at the top' => 'Panel główny - u góry', + 'Dashboard - bottom' => 'Panel główny - dół', + 'Dashboard - middle' => 'Panel główny - środek', + 'Data import / export' => 'Import / export danych', + 'Default lang without translation' => 'Domyślny język bez tłumaczenia', + 'Delivery - After delivery module' => 'Dostawa - po module dostawy', + 'Delivery - CSS' => 'Dostawa - CSS', + 'Delivery - additional product information' => 'Dostawa - dodatkowe informacje o produkcie', + 'Delivery - after addresse area' => 'Dostawa - pod obszarem adresu', + 'Delivery - after the information area' => 'Dostawa - pod obszarem informacji', + 'Delivery - after the order summary' => 'Dostawa - po podsumowaniu zamówienia', + 'Delivery - at the bottom of information area' => 'Dostawa - w dolnej części obszaru informacyjnego', + 'Delivery - at the bottom of the footer' => 'Dostawa - na dole stopki', + 'Delivery - at the top of the footer' => 'Dostawa - na górze stopki', + 'Delivery - delivery address' => 'Dostawa - adres dostawy', + 'Delivery - in the header' => 'Dostawa - w nagłówku', + 'Delivery choice - CSS stylesheet' => 'Wybór dostawcy - style CSS', + 'Delivery choice - after javascript include' => 'Wybór dostawcy - po dołączeniu javascript', + 'Denmark' => 'Dania', + 'Djibouti' => 'Dżibuti', + 'Dominica' => 'Dominika', + 'Dominican Republic' => 'Dominikana', + 'Ecuador' => 'Ekwador', + 'Egypt' => 'Egipt', + 'El Salvador' => 'Salwador', + 'Enable (1) or disable (0) URL rewriting' => 'Włącz (1) lub wyłącz (0) nadpisywanie URLi', + 'Equatorial Guinea' => 'Gwinea Równikowa', + 'Eritrea' => 'Erytrea', + 'Estonia' => 'Estonia', + 'Ethiopia' => 'Etiopia', + 'Euro' => 'Euro', + 'Export - JavaScript' => 'Eksport - JavaScript', + 'Export - table header' => 'Eksport - nagłówek tabeli', + 'Export - table row' => 'Eksport - wiersz tabeli', + 'Export modal or page - bottom' => 'Eksport modal lub strona - dół', + 'Export modal or page - top' => 'Eksport modal lub strona - góra', + 'Exports - JavaScript' => 'Eksport - JavaScript', + 'Exports - at the bottom of a category' => 'Eksportu - na dole kategorii', + 'Exports - at the bottom of column 1' => 'Export - w dolnej części kolumny 1', + 'Exports - at the top' => 'Eksportu - na górze', + 'Fiji' => 'Fidżi', + 'Filename of the error page' => 'Nazwa pliku strony błędu', + 'Finland' => 'Finlandia', + 'Folder' => 'Katalog', + 'Gabon' => 'Gabon', + 'Gambia' => 'Gambia', + 'Georgia' => 'Gruzja', + 'Germany' => 'Niemcy', + 'Ghana' => 'Ghana', + 'Google Analytics block' => 'Blok Google Analytics', + 'Greece' => 'Grecja', + 'Grenada' => 'Grenada', + 'Guadeloupe' => 'Gwadelupa', + 'Guatemala' => 'Gwatemala', + 'Guinea' => 'Gwinea', + 'Guinea-Bissau' => 'Gwinea Bissau', + 'Guyana' => 'Gujana', + 'Guyane Française' => 'Guyane Française', + 'HTML layout - CSS stylesheet' => 'Układ HTML - styl CSS', + 'HTML layout - after javascript include' => 'Układ HTML - po dołączeniu plików javascript', + 'HTML layout - after the main content area' => 'Układ HTML - pod głównym obszarem zawartości', + 'HTML layout - after the opening of the body tag' => 'Układ HTML - po otwarciu znacznika body', + 'HTML layout - after the opening of the head tag' => 'Układ HTML - po otwarciu znacznika head', + 'HTML layout - at the bottom of the header' => 'Układ HTML - na dole nagłówka', + 'HTML layout - at the top of the footer' => 'Układ HTML - na górze stopki', + 'HTML layout - at the top of the header' => 'Układ HTML - na górze nagłówka', + 'HTML layout - before the end body tag' => 'Układ HTML - przed zamknięciem znacznika body', + 'HTML layout - before the end of the head tag' => 'Układ HTML - przed zamknięciem znacznika head', + 'HTML layout - before the main content area' => 'Układ HTML - nad obszarem głównej treści', + 'HTML layout - bottom of the footer' => 'Układ HTML - na dole stopki', + 'HTML layout - footer body' => 'Układ HTML - stopka', + 'HTML layout - javascript initialization' => 'Układ HTML - inicjalizacja javascript', + 'HTML layout - primary navigation' => 'Układ HTML - podstawowa nawigacja', + 'HTML layout - secondary navigation' => 'Układ HTML - drugorzędna nawigacja', + 'Haiti' => 'Haiti', + 'Home - JavaScript' => 'Strona główna - JavaScript', + 'Home - at the top' => 'Strona główna - na górze', + 'Home - block' => 'Strona główna - blok', + 'Home - bottom' => 'Strona główna - dół', + 'Home page - CSS stylesheet' => 'Strona główna - style CSS', + 'Home page - after javascript include' => 'Strona główna - po dołączeniu plików javascript', + 'Home page - after javascript initialisation' => 'Strona główna - po inicjalizacji javascript', + 'Home page - main area' => 'Strona główna - główny obszar', + 'Honduras' => 'Honduras', + 'Hong Kong' => 'Hong Kong', + 'Hook - Edit JavaScript' => 'Hook - edycja javascript', + 'Hungary' => 'Węgry', + 'Iceland' => 'Islandia', + 'India' => 'Indie', + 'Indonesia' => 'Indonezja', + 'Iran' => 'Iran', + 'Iraq' => 'Irak', + 'Ireland' => 'Irlandia', + 'Israel' => 'Izrael', + 'Italy' => 'Włochy', + 'Ivory Coast' => 'Wybrzeże Kości Słoniowej', + 'Jamaica' => 'Jamajka', + 'Japan' => 'Japonia', + 'Jordan' => 'Jordania', + 'Kazakhstan' => 'Kazachstan', + 'Kenya' => 'Kenia', + 'Kiribati' => 'Kiribati', + 'Kuwait' => 'Kuwejt', + 'Kyrgyzstan' => 'Kirgistan', + 'Laos' => 'Laotański', + 'Latvia' => 'Łotwa', + 'Layout - Before the main content' => 'Układ - przed główną treścią', + 'Layout - CSS' => 'Układ - CSS', + 'Layout - JavaScript' => 'Układ - JavaScript', + 'Layout - after footer' => 'Układ - pod stopką', + 'Layout - after top bar' => 'Układ - pod górnym paskiem', + 'Lebanon' => 'Liban', + 'Liberia' => 'Liberia', + 'Libya' => 'Libia', + 'Liechtenstein' => 'Liechtenstein', + 'Lithuania' => 'Litwa', + 'Luxembourg' => 'Luxemburg', + 'Macedonia' => 'Macedonia', + 'Madagascar' => 'Madagaskar', + 'Malawi' => 'Malawi', + 'Malaysia' => 'Malezja', + 'Maldives' => 'Malediwy', + 'Mali' => 'Mali', + 'Malta' => 'Malta', + 'Marshall Islands' => 'Wyspy Marshalla', + 'Martinique' => 'Martynika', + 'Mauritania' => 'Mauretania', + 'Mauritius' => 'Mauritius', + 'Mayotte' => 'Majotta', + 'Mexico' => 'Meksyk', + 'Micronesia' => 'Mikronezja', + 'Miss' => 'Pani', + 'Miss_short' => 'Pani', + 'Misses' => 'Pani', + 'Mister' => 'Pan', + 'Moldova' => 'Mołdawia', + 'Monaco' => 'Monako', + 'Mongolia' => 'Mongolia', + 'Morocco' => 'Maroko', + 'Mozambique' => 'Mozambik', + 'Mr.' => 'Pan', + 'Mrs' => 'Pani', + 'Name of the active PDF template' => 'Nazwa aktywnego szablonu PDF', + 'Name of the active back-office template' => 'Nazwa aktywnego szablonu back-office', + 'Name of the active front-office template' => 'Nazwa aktywnego szablonu front-office', + 'Name of the active mailing template' => 'Nazwa aktywnego szablonu korespondencji email', + 'Name of the cart cookie' => 'Nazwa ciastka koszyka', + 'Name of the delivery view in the current PDF template (without extension)' => 'Nazwa widoku dostawy w bieżącym szablonie PDF (bez rozszerzenia)', + 'Name the cart cookie' => 'Nazwa ciastka koszyka', + 'Namibia' => 'Namibia', + 'Nauru' => 'Nauru', + 'Navigation block' => 'Blok nawigacji', + 'Nepal' => 'Nepal', + 'Netherlands' => 'Holandia', + 'New Products block' => 'Blok nowych produktów', + 'New York' => 'New York', + 'New Zealand' => 'Nowa Zelandia', + 'New order {$order_ref} placed on {config key="store_name"}' => 'Nowe zamówienie {$order_ref} złożone w {config key="store_name"}', + 'Nicaragua' => 'Nikaragua', + 'Niger' => 'Niger', + 'Nigeria' => 'Nigeria', + 'Niue' => 'Niue', + 'North Korea' => 'Korea Północna', + 'Norway' => 'Norwegia', + 'Not paid' => 'Nie zapłacono', + 'Nouvelle-Calédonie' => 'Nowa Kaledonia', + 'Oman' => 'Oman', + 'Order' => 'Zamówienie', + 'Page 404 - CSS stylesheet' => 'Strona 404 - style CSS', + 'Page 404 - content area' => 'Strona 404 - treść', + 'Paid' => 'Zapłacone', + 'Pakistan' => 'Pakistan', + 'Panama' => 'Panama', + 'Papua Nueva Guinea' => 'Papua-Nowa Gwinea', + 'Paraguay' => 'Paragwaj', + 'Pay by cheque' => 'Zapłać czekiem', + 'Peru' => 'Peru', + 'Philippines' => 'Filipiny', + 'Poland' => 'Polska', + 'Portugal' => 'Portugalia', + 'Processing' => 'Przetwarzanie', + 'Qatar' => 'Katar', + 'Romania' => 'Rumunia', + 'Russia' => 'Rosja', + 'Rwanda' => 'Rwanda', + 'San Marino' => 'San Marino', + 'Sao Tome and Principe' => 'Wyspy Świętego Tomasza i Książęca', + 'Saudi Arabia' => 'Arabia Saudyjska', + 'Search' => 'Szukaj', + 'Senegal' => 'Senegal', + 'Sent' => 'Wysłano', + 'Seychelles' => 'Seszele', + 'Sierra Leone' => 'Sierra Leone', + 'Singapore' => 'Singapur', + 'Slovakia' => 'Słowacja', + 'Slovenia' => 'Słowenia', + 'Social Networks block' => 'Blok Sieci Społecznościowych', + 'Solomon Islands' => 'Wyspy Salomona', + 'Somalia' => 'Somalia', + 'South Africa' => 'Afryka Południowa', + 'South Korea' => 'Korea Południowa', + 'Spain' => 'Hiszpania', + 'Sri Lanka' => 'Sri Lanka', + 'Sudan' => 'Sudan', + 'Suriname' => 'Surinam', + 'Swaziland' => 'Suazi', + 'Sweden' => 'Szwecja', + 'Switzerland' => 'Szwajcaria', + 'Syria' => 'Syria', + 'Tajikistan' => 'Tadżykistan', + 'Tanzania' => 'Tanzania', + 'Thailand' => 'Tajlandia', + 'The Vatican' => 'Watykan', + 'Togo' => 'Togo', + 'Tonga' => 'Tonga', + 'Translations' => 'Tłumaczenia', + 'Tunisia' => 'Tunezja', + 'Turkey' => 'Turcja', + 'Turkmenistan' => 'Turkmenistan', + 'Tuvalu' => 'Tuwalu', + 'UK Pound' => 'Funt Wielkiej Brytanii', + 'Uganda' => 'Uganda', + 'Ukraine' => 'Ukraina', + 'United Arab Emirates' => 'Zjednoczone Emiraty Arabskie', + 'United Kingdom' => 'Wielka Brytania', + 'United States Dollar' => 'Dolar amerykański', + 'Venezuela' => 'Wenezuela', + 'Vietnam' => 'Wietnam', + 'Yemen' => 'Jemen', + 'You can now login at' => 'Możesz teraz zalogować się na', + 'You have lost your password
    \r\nPlease, change this password after your first connection' => 'Straciłeś hasło
    \r\nProszę zmienić hasło po pierwszym logowaniu', + 'You have lost your password
    \r\nYour new password is' => 'Straciłeś hasło < br / > \r\nTwoje nowe hasło', + 'Your account information on {config key="store_name"} has been changed.' => 'Informacje o twoim koncie na {config key="store_name"} zostały zmienione.', + 'Your new passord is : {$password}' => 'Twoje nowe hasło: {$password}', + 'Your new password' => 'Twoje nowe hasło', + 'Your new password for {config key="store_name"}' => 'Twoje nowe hasło dla {config key="store_name"}', + 'Your order {$order_ref} at {config key="store_name"}' => 'Twoje zamówienie {$order_ref} w {config key="store_name"}', + 'Zaire' => 'Zair', + 'Zambia' => 'Zambia', + 'Zimbabwe' => 'Zimbabwe', +]; diff --git a/setup/I18n/pt_BR.php b/setup/I18n/pt_BR.php new file mode 100644 index 00000000..6cd03e4f --- /dev/null +++ b/setup/I18n/pt_BR.php @@ -0,0 +1,72 @@ + '"Lembrar-me" cookie de expiração tempo, em segundos, para usuários de administração', + '"Remember me" cookie expiration time, in seconds, for customer users' => '"Lembrar-me" cookie expiração tempo, em segundos, para os usuários do cliente', + 'Address' => 'Endereço', + 'Address creation - CSS stylesheet' => 'Criação de endereço - folha de estilos CSS', + 'Advanced configuration' => 'Configuração avançada', + 'Afghanistan' => 'Afeganistão', + 'Albania' => 'Albânia', + 'Algeria' => 'Argélia', + 'All Products - CSS stylesheet' => 'Todos os produtos - folha de estilos CSS', + 'All Products - after javascript include' => 'Todos os produtos - após incluir javascript', + 'All Products - after javascript initialisation' => 'Todos os produtos - após a inicialização do javascript', + 'All Products - at the bottom' => 'Todos os produtos - na parte inferior', + 'All Products - at the top' => 'Todos os produtos - no topo', + 'Allow customers to change their email. 1 for yes, 0 for no' => 'Permitir que clientes mudem seu e-mail. 1 Sim, 0 não', + 'Allow negative product stock (1) or not (0)' => 'Permitir o estoque de produto negativo (1) ou não (0)', + 'Ask the customers to confirm their email, 1 for yes, 0 for no' => 'Pergunte aos clientes para confirmar seu e-mail, 1 para Sim, 0 não', + 'Australia' => 'Austrália', + 'Austria' => 'Áustria', + 'Azerbaijan' => 'Azerbeijão', + 'Bahamas' => 'Bahamas', + 'Bahrain' => 'Bahrein', + 'Bangladesh' => 'Bangladesh', + 'Barbados' => 'Barbados', + 'Belarus' => 'Bielorrússia', + 'Belgium' => 'Bélgica', + 'Belize' => 'Belize', + 'Benin' => 'República do Benim', + 'Bhutan' => 'Butão', + 'Bielorussia' => 'Bielorussia', + 'Bolivia' => 'Bolívia', + 'Bosnia and Herzegovina' => 'Bósnia e Herzegovina', + 'Botswana' => 'Botsuana', + 'Brand - JavaScript' => 'Marca - JavaScript', + 'Brand - Tab' => 'Marca - guia', + 'Brand - content' => 'Marca - conteúdo', + 'Brand - create form' => 'Marca - formulário de criação', + 'Brand - delete form' => 'Marca - formulário de exclusão', + 'Brazil' => 'Brasil', + 'Brunei' => 'Brunei', + 'Bulgaria' => 'Bulgária', + 'Burma' => 'Birmânia', + 'Burundi' => 'Burundi', + 'Cambodia' => 'Camboja', + 'Cameroon' => 'Camarões', + 'Canceled' => 'Cancelado', + 'Cape Verde' => 'Cabo Verde', + 'Cart - CSS stylesheet' => 'Carrinho - folha de estilos CSS', + 'Cart - after javascript include' => 'Carrinho - após incluir javascript', + 'Cart - at the bottom' => 'Carrinho - na parte inferior', + 'Cart - javascript initialization' => 'Carrinho - inicialização de javascript', + 'Cart block' => 'Bloco do carrinho', + 'Categories - JavaScript' => 'Categorias - JavaScript', + 'Categories - at the bottom of the catalog' => 'Categorias - na parte inferior do catálogo', + 'Categories - at the top' => 'Categorias - no topo', + 'Categories - caption' => 'Categorias - legenda', + 'Categories - header' => 'Categorias - cabeçalho', + 'Category' => 'Categoria', + 'Category - Edit JavaScript' => 'Categoria - editar JavaScript', + 'Category - Tab' => 'Categoria - guia', + 'Category - content' => 'Categoria - conteúdo', + 'Configuration' => 'Configuração', + 'Content' => 'Conteúdo', + 'Coupon' => 'Cupom', + 'Customer' => 'Cliente', + 'Hooks' => 'Ganchos', + 'Modules maagement' => 'Módulos', + 'New York' => 'Cidade', + 'Search' => 'Procurar', +]; diff --git a/setup/I18n/pt_PT.php b/setup/I18n/pt_PT.php new file mode 100644 index 00000000..ba155fb7 --- /dev/null +++ b/setup/I18n/pt_PT.php @@ -0,0 +1,5 @@ + 'Endereço', +]; diff --git a/setup/I18n/ru_RU.php b/setup/I18n/ru_RU.php new file mode 100644 index 00000000..c0992a17 --- /dev/null +++ b/setup/I18n/ru_RU.php @@ -0,0 +1,1449 @@ + 'Время жизни cookie "Запомнить меня" в секундах, для админов', + '"Remember me" cookie expiration time, in seconds, for customer users' => 'Время жизни cookie "Запомнить меня" в секундах, для клиентов', + '"Remember me" cookie name for administration users' => 'Имя cookie "Запомнить меня" для админов', + '"Remember me" cookie name for customer users' => 'Имя cookie "Запомнить меня" для клинтов', + '72h delivery' => '72h delivery', + 'A {config key="store_name"} account has been created for you' => 'Аккаунт в {config key="store_name"} был создан для вас', + 'API Configuration' => 'Конфигурация API', + 'Aceh' => 'Ачех', + 'Address' => 'Адрес', + 'Address creation - CSS stylesheet' => 'Создание адреса - CSS стили', + 'Address creation - after javascript include' => 'Создание адреса - после включения javascript', + 'Address creation - after javascript initialisation' => 'Создание адреса - после инициализации javascript', + 'Address creation - at the bottom' => 'Создание адреса - внизу', + 'Address creation - at the bottom of the form' => 'Создание адреса - внизу формы', + 'Address creation - at the top' => 'Создание адреса - вверху', + 'Address creation - at the top of the form' => 'Создание адреса - вверху формы', + 'Address update - CSS stylesheet' => 'Обновление адреса - CSS стили', + 'Address update - after javascript include' => 'Обновление адреса - после включения javascript', + 'Address update - after javascript initialisation' => 'Обновление адреса - после инициализации javascript', + 'Address update - at the bottom' => 'Обновление адреса - внизу', + 'Address update - at the bottom of the form' => 'Обновление адреса - внизу формы', + 'Address update - at the top' => 'Обновление адреса - вверху', + 'Address update - at the top of the form' => 'Обновление адреса - вверху формы', + 'Admin layout - After the main content' => 'Каркас админки - После основного контента', + 'Administatros list' => 'Список администраторов', + 'Administration profiles management' => 'Управление административными модулями', + 'Administrator - create form' => 'Администратор - форма создания', + 'Administrator - delete form' => 'Администратор - форма удаления', + 'Administrator - update form' => 'Администратор - форма обновления', + 'Administrator list' => 'Список администраторов', + 'Administrators - JavaScript' => 'Администраторы - JavaScript', + 'Administrators - at the top' => 'Администраторы - вверху', + 'Administrators - bottom' => 'Администраторы - внизу', + 'Administrators - header' => 'Администраторы - заголовок', + 'Administrators - row' => 'Администраторы - строка', + 'Advanced Configuration' => 'Расширенная конфигурация', + 'Advanced Configuration - Javascript' => 'Расширенная конфигурация - Javascript', + 'Advanced configuration' => 'Расширенная конфигурация', + 'Afghanistan' => 'Афганистан', + 'Agrigento' => 'Агридженто', + 'Aguascalientes' => 'Агуаскальентес', + 'Aichi' => 'Айти', + 'Akita' => 'Акита', + 'Alabama' => 'Алабама', + 'Alaska' => 'Аляска', + 'Albania' => 'Албания', + 'Alberta' => 'Альберта', + 'Alessandria' => 'Алессандрия', + 'Algeria' => 'Алжир', + 'All Products - CSS stylesheet' => 'Все товары - CSS стили', + 'All Products - after javascript include' => 'Все товары - после включения javascript', + 'All Products - after javascript initialisation' => 'Все товары - после инициализации javascript', + 'All Products - at the bottom' => 'Все товары - внизу', + 'All Products - at the top' => 'Все товары - вверху', + 'Allow an administrator to recreate a lost password (1 = yes, 0 = no)' => 'Позволять восстановление утеряного пароля админа (1 - Да, 0 - Нет)', + 'Allow customers to change their email. 1 for yes, 0 for no' => 'Позволять клиентам менять email. 1 - Да, 0 - Нет', + 'Allow negative product stock (1) or not (0)' => 'Разрешить отрицательные остатки товара (1) или нет (0)', + 'Allow negative product stock (1) or not (0, default)' => 'Разрешить отрицательные остатки товара (1) или нет (0, по умолчанию)', + 'Allow slash ended uri' => 'Разрешить URI закрывающим слешем', + 'An image carousel on your home page' => 'Слайдер на главной', + 'Ancona' => 'Анконы', + 'Andorra' => 'Андорра', + 'Angola' => 'Ангола', + 'Antigua and Barbuda' => 'Антигуа и Барбуда', + 'Aomori' => 'Аомори', + 'Aosta' => 'Аоста', + 'Api page - at bottom' => 'Страница API - внизу', + 'Api page - at top' => 'Страница API - вверху', + 'Api page - in deletion form' => 'Страница API - в форме удаления', + 'Arezzo' => 'Ареццо', + 'Argentina' => 'Аргентина', + 'Arizona' => 'Аризона', + 'Arkansas' => 'Арканзас', + 'Armenia' => 'Армения', + 'Ascoli Piceno' => 'Асколи-Пичено', + 'Ask the customers to confirm their email, 1 for yes, 0 for no' => 'Просить клиентов подтверждения email. 1 - Да, 0 - Нет', + 'Asti' => 'Асти', + 'Attribut - Edit JavaScript' => 'Атрибут - Редактирование JavaScript', + 'Attribut - add to all form' => 'Атрибут - форма добавить все', + 'Attribut - create form' => 'Атрибут - форма создания', + 'Attribut - delete form' => 'Атрибут - форма удаления', + 'Attribut - id delete form' => 'Атрибут - форма удаления id', + 'Attribut - remove to all form' => 'Атрибут - форма удалить все', + 'Attribute edit - bottom' => 'Редактирование атрибута - внизу', + 'Attribute edit - top' => 'Редактирование атрибута - вверху', + 'Attribute value - create form' => 'Значение атрибута - форма создания', + 'Attributes - JavaScript' => 'Атрибуты - JavaScript', + 'Attributes - at the top' => 'Атрибуты - вверху', + 'Attributes - bottom' => 'Атрибуты - внизу', + 'Attributes - table header' => 'Атрибуты - заголовок таблицы', + 'Attributes - table row' => 'Атрибуты - строка таблицы', + 'Attributes value - table header' => 'Значение атрибутов - заголовок таблицы', + 'Attributes value - table row' => 'Значение атрибутов - строка таблицы', + 'Australia' => 'Австралия', + 'Austria' => 'Австрия', + 'Avellino' => 'Авеллино', + 'Azerbaijan' => 'Азербайджан', + 'Back-office export management' => 'Управление экспортом в админке', + 'Back-office home page' => 'Главная админки', + 'Back-office search function' => 'Поиск по админке', + 'Bahamas' => 'Багамские о-ва', + 'Bahrain' => 'Бахрейн', + 'Baht' => 'Бат', + 'Baja California' => 'Южная Калифорния', + 'Baja California Sur' => 'Южная Нижняя Калифорния', + 'Bali' => 'Бали', + 'Bangka' => 'Bangka', + 'Bangladesh' => 'Бангладеш', + 'Banten' => 'Бантен', + 'Barbados' => 'Barbados', + 'Bari' => 'Бари', + 'Barletta-Andria-Trani' => 'Барлетта-Андрия-Трани', + 'Base URL of the shop (e.g. http://www.yourshopdomain.com)' => 'Базовый URL магазина (например http://www.yourshopdomain.com)', + 'Belarus' => 'Беларусь', + 'Belarusian ruble' => 'Белорусский рубль', + 'Belgium' => 'Бельгия', + 'Belize' => 'Белиз', + 'Belluno' => 'Беллуно', + 'Benevento' => 'Беневенто', + 'Bengkulu' => 'Бенгкулу', + 'Benin' => 'Бенин', + 'Bergamo' => 'Бергамо', + 'Bhutan' => 'Бутан', + 'Biella' => 'Биэлла', + 'Bielorussia' => 'Белорусь', + 'Bolivia' => 'Боливия', + 'Boliviano' => 'Боливиано', + 'Bologna' => 'Болонья', + 'Bolzano' => 'Больцано', + 'Bolívar fuerte' => 'Боливар', + 'Bosnia and Herzegovina' => 'Босния и Герцеговина', + 'Botswana' => 'Ботсвана', + 'Brand - Edit JavaScript' => 'Бренд - Редактирование JavaScript', + 'Brand - JavaScript' => 'Бренд - JavaScript', + 'Brand - Tab' => 'Бренд - Вкладка', + 'Brand - content' => 'Бренд - содержимое', + 'Brand - create form' => 'Бренд - форма создания', + 'Brand - delete form' => 'Бренд - форма удаления', + 'Brand edit - bottom' => 'Редактирование бренда - внизу', + 'Brand edit - right column bottom' => 'Редактирование бренда - внизу правой колонки', + 'Brand edit - right column top' => 'Редактирование бренда - вверху правой колонки', + 'Brand edit - top' => 'Редактирование бренда - вверху', + 'Brand edit page - in the form' => 'Страница редактирования бренда - в форме', + 'Brands - at the top' => 'Бренды - вверху', + 'Brands - bottom' => 'Бренды - внизу', + 'Brands - table header' => 'Бренды - заголовок таблицы', + 'Brands - table row' => 'Бренды - строка таблицы', + 'Brands management' => 'Управление брендами', + 'Brands page - CSS stylesheet' => 'Страница брендов - CSS стили', + 'Brands page - after javascript include' => 'Страница брендов - после включения javascript', + 'Brands page - after the main content area' => 'Страница брендов - после основной зоны контента', + 'Brands page - at the bottom' => 'Страница брендов - внизу', + 'Brands page - at the bottom of the main area' => 'Страница брендов - внизу основной зоны', + 'Brands page - at the bottom of the sidebar' => 'Страница брендов - внизу боковой панели', + 'Brands page - at the top' => 'Страница брендов - вверху', + 'Brands page - at the top of the main area' => 'Страница брендов - вверху основной зоны', + 'Brands page - at the top of the sidebar' => 'Страница брендов - вверху боковой панели', + 'Brands page - before the main content area' => 'Страница брендов - перед основной зоной контента', + 'Brands page - javascript initialization' => 'Страница брендов - после инициализации javascript', + 'Brands page - the body of the sidebar' => 'Страница брендов - содержимое боковой панели', + 'Brazil' => 'Бразилия', + 'Brescia' => 'Брешиа', + 'Brindisi' => 'Бриндиси', + 'British Columbia' => 'Британская Колумбия', + 'Brunei' => 'Бруней', + 'Buenos Aires' => 'Буэнос айрес', + 'Bulgaria' => 'Болгария', + 'Burkina' => 'Буркина', + 'Burma' => 'Бирма', + 'Burundi' => 'Бурунди', + 'Cagliari' => 'Кальяри', + 'California' => 'Калифорния', + 'Caltanissetta' => 'Кальтаниссетта', + 'Cambodia' => 'Камбоджа', + 'Cameroon' => 'Камерун', + 'Campeche' => 'Кампече', + 'Campobasso' => 'Кампобассо', + 'Canada' => 'Канада', + 'Canceled' => 'Отменен', + 'Cape Verde' => 'Кабо-Верде', + 'Carbonia-Iglesias' => 'Карбония-Иглесиас', + 'Cart - CSS stylesheet' => 'Корзина - CSS стили', + 'Cart - after javascript include' => 'Корзина - после включения javascript', + 'Cart - at the bottom' => 'Корзина - внизу', + 'Cart - at the top' => 'Корзина - вверху', + 'Cart - javascript initialization' => 'Корзина - после инициализации javascript', + 'Cart block' => 'Блок корзины', + 'Caserta' => 'Казерта', + 'Catamarca' => 'Катамарка', + 'Catania' => 'Катания', + 'Catanzaro' => 'Катандзаро', + 'Categories - JavaScript' => 'Категории - JavaScript', + 'Categories - at the bottom of the catalog' => 'Категории - внизу каталога', + 'Categories - at the top' => 'Категории - вверху', + 'Categories - bottom' => 'Категории - внизу', + 'Categories - caption' => 'Категории - заглавие', + 'Categories - header' => 'Категории - заголовок', + 'Categories - row' => 'Категории - строка', + 'Category' => 'Категория', + 'Category - Edit JavaScript' => 'Категория - Редактирование JavaScript', + 'Category - Tab' => 'Категория - Вкладка', + 'Category - content' => 'Категория - содержимое', + 'Category - contents table header' => 'Категория - заголовок таблицы содержимого', + 'Category - contents table row' => 'Категория - строка таблицы содержимого', + 'Category - create form' => 'Категория - форма создания', + 'Category - delete form' => 'Категория - форма удаления', + 'Category configuration' => 'Конфигурация категорий', + 'Category edit - bottom' => 'Редактирование категории - внизу', + 'Category edit - right column bottom' => 'Редактирование категории - внизу правой колонки', + 'Category edit - right column top' => 'Редактирование категории - вверху правой колонки', + 'Category edit - top' => 'Редактирование категории - вверху', + 'Category page - CSS stylesheet' => 'Страница категории - CSS стили', + 'Category page - after javascript include' => 'Страница категории - после включения javascript', + 'Category page - after javascript initialisation' => 'Страница категории - после инициализации javascript', + 'Category page - after the main content area' => 'Страница категории - после основной зоны контента', + 'Category page - at the bottom' => 'Страница категории - внизу', + 'Category page - at the bottom of the main area' => 'Страница категории - внизу основной зоны', + 'Category page - at the bottom of the sidebar' => 'Страница категории - внизу боковой панели', + 'Category page - at the top' => 'Страница категории - вверху', + 'Category page - at the top of the main area' => 'Страница категории - вверху основной зоны', + 'Category page - at the top of the sidebar' => 'Страница категории - вверху боковой панели', + 'Category page - before the main content area' => 'Страница категории - перед основной зоной контента', + 'Category page - the body of the sidebar' => 'Страница категории - содержимое боковой панели', + 'Central African Republic' => 'Центрально-Африканская Республика', + 'Central Java' => 'Центральная Ява', + 'Central Kalimantan' => 'Центральный Калимантан', + 'Central Sulawesi' => 'Центральный Сулавеси', + 'Chaco' => 'Чако', + 'Chad' => 'Чад', + 'Change password - CSS stylesheet' => 'Смена пароля - CSS стили', + 'Change password - after javascript include' => 'Смена пароля - после включения javascript', + 'Change password - after javascript initialisation' => 'Смена пароля - после инициализации javascript', + 'Change password - at the bottom' => 'Смена пароля - внизу', + 'Change password - at the top' => 'Смена пароля - вверху', + 'Check available product stock (1) or ignore it (0) when displaying and changing ordered quantity' => 'Проверять доступный запас товара (1) или игнорировать его (0) при отображении и изменении количества в заказе', + 'Check if a virtual product delivery module is enabled if at least one product is virtual' => 'Проверять вкоючен ли модуль доставки виртуальных товаров, если хотя бы однин товар виртуальный', + 'Chiapas' => 'Чьяпас', + 'Chiba' => 'Тиба', + 'Chieti' => 'Кьети', + 'Chihuahua' => 'Чихуахуа', + 'Chile' => 'Чили', + 'China' => 'Китай', + 'Chubut' => 'Чубут', + 'Ciudad de Buenos Aires' => 'Сьюдад-де-Буэнос-Айрес', + 'Client edit - bottom' => 'Редактирование клиента - внизу', + 'Client edit - top' => 'Редактирование клиента - вверху', + 'Coahuila' => 'Коауила', + 'Coat of arms of East Java' => 'Герб Восточная Ява', + 'Colima' => 'Колима', + 'Colombia' => 'Колумбия', + 'Colorado' => 'Колорадо', + 'Colón' => 'Колон', + 'Como' => 'Комо', + 'Comoros' => 'Коморские', + 'Compile templates assets automatically upon asset source change (1 = yes, 0 = no)' => 'Компилировать assets автоматически при изменении источника asset (1 - Да, 0 - Нет)', + 'Configuration' => 'Конфигурация', + 'Configuration - JavaScript' => 'Конфигурация - JavaScript', + 'Configuration - at the bottom of the catalog' => 'Конфигурация - внизу каталога', + 'Configuration - at the bottom of the shipping area' => 'Конфигурация - внизу зоны доставки', + 'Configuration - at the bottom of the system area' => 'Конфигурация - внизу системной зоны', + 'Configuration - at the top' => 'Конфигурация - вверху', + 'Configuration - at the top of the catalog area' => 'Конфигурация - вверху зоны каталога', + 'Configuration - at the top of the shipping area' => 'Конфигурация - вверху зоны доставки', + 'Configuration - at the top of the system area' => 'Конфигурация - вверху системной зоны', + 'Configuration - bottom' => 'Конфигурация - внизу', + 'Configuration / Administrator' => 'Конфигурация / Администратор', + 'Configuration / Area' => 'Конфигурация / Зона', + 'Configuration / Attribute' => 'Конфигурация / Атрибут', + 'Configuration / Cache' => 'Конфигурация / Кеш', + 'Configuration / Country' => 'Конфигурация / Страна', + 'Configuration / Currency' => 'Конфигурация / Валюта', + 'Configuration / Feature' => 'Конфигурация / Характеристика', + 'Configuration / Language' => 'Конфигурация / Язык', + 'Configuration / Mailing-system' => 'Конфигурация / Система отправки почты', + 'Configuration / Message' => 'Конфигурация / Сообщение', + 'Configuration / Module' => 'Конфигурация / Модуль', + 'Configuration / Profile' => 'Конфигурация / Профиль', + 'Configuration / Shipping-zone' => 'Конфигурация / Зона доставки', + 'Configuration / System Log' => 'Конфигурация / Системный лог', + 'Configuration / Tax' => 'Конфигурация / Налог', + 'Configuration / Template' => 'Конфигурация / Шаблон', + 'Configuration variables' => 'Конфигурация переменных', + 'Congo' => 'Конго', + 'Connecticut' => 'Коннектикут', + 'Contact block' => 'Блок контактов', + 'Contact page - CSS stylesheet' => 'Страница контактов - CSS стили', + 'Contact page - after javascript include' => 'Страница контактов - после включения javascript', + 'Contact page - after javascript initialisation' => 'Страница контактов - после инициализации javascript', + 'Contact page - at the bottom' => 'Страница контактов - внизу', + 'Contact page - at the bottom of the form' => 'Страница контактов - внизу формы', + 'Contact page - at the top' => 'Страница контактов - вверху', + 'Contact page - at the top of the form' => 'Страница контактов - вверху формы', + 'Contact page - if successful response' => 'Страница контактов - при успешном ответе', + 'Content' => 'Содержимое', + 'Content - Edit JavaScript' => 'Контент - Редактирование JavaScript', + 'Content - Tab' => 'Контент - Вкладка', + 'Content - content' => 'Контент - содержимое', + 'Content - create form' => 'Контент - форма создания', + 'Content - delete form' => 'Контент - форма удаления', + 'Content edit - bottom' => 'Редактирование контента - внизу', + 'Content edit - right column bottom' => 'Редактирование контента - внизу правой колонки', + 'Content edit - right column top' => 'Редактирование контента - вверху правой колонки', + 'Content edit - top' => 'Редактирование контента - вверху', + 'Content page - CSS stylesheet' => 'Страница контента - CSS стили', + 'Content page - after javascript include' => 'Страница контента - после включения javascript', + 'Content page - after javascript initialisation' => 'Страница контента - после инициализации javascript', + 'Content page - after the main content area' => 'Страница контента - после основной зоны контента', + 'Content page - at the bottom' => 'Страница контента - внизу', + 'Content page - at the bottom of the main area' => 'Страница контента - внизу основной зоны', + 'Content page - at the bottom of the sidebar' => 'Страница контента - внизу боковой панели', + 'Content page - at the top' => 'Страница контента - вверху', + 'Content page - at the top of the main area' => 'Страница контента - вверху основной зоны', + 'Content page - at the top of the sidebar' => 'Страница контента - вверху боковой панели', + 'Content page - before the main content area' => 'Страница контента - перед основной зоной контента', + 'Content page - the body of the sidebar' => 'Страница контента - содержимое боковой панели', + 'Contents - caption' => 'Контенты - заглавие', + 'Contents - header' => 'Контенты - заголовок', + 'Contents - row' => 'Контенты - строка', + 'Cook Islands' => 'Острова Кука', + 'Corrientes' => 'Корриентес', + 'Cosenza' => 'Козенца', + 'Costa Rica' => 'Коста-Рика', + 'Countries - JavaScript' => 'Страны - JavaScript', + 'Countries - at the top' => 'Страны - вверху', + 'Countries - bottom' => 'Страны - внизу', + 'Countries - table header' => 'Страны - заголовок таблицы', + 'Countries - table row' => 'Страны - строка таблицы', + 'Country - Edit JavaScript' => 'Страна - Редактирование JavaScript', + 'Country - create form' => 'Страна - форма создания', + 'Country - delete form' => 'Страна - форма удаления', + 'Country edit - bottom' => 'Редактирование страны - внизу', + 'Country edit - top' => 'Редактирование страны - вверху', + 'Coupon' => 'Купон', + 'Coupon - at the top' => 'Купон - вверху', + 'Coupon - bottom' => 'Купон - внизу', + 'Coupon - create JavaScript' => 'Купон - Создание JavaScript', + 'Coupon - list JavaScript' => 'Купон - список JavaScript', + 'Coupon - list caption' => 'Купон - заголовок списка', + 'Coupon - table header' => 'Купон - заголовок таблицы', + 'Coupon - table row' => 'Купон - строка таблицы', + 'Coupon - update JavaScript' => 'Купон - обновить JavaScript', + 'Coupon page - in deletion form' => 'Страница купона - в форме удаления', + 'Cremona' => 'Кремона', + 'Croatia' => 'Хорватия', + 'Croatian Kuna' => 'Хорватская куна', + 'Crotone' => 'Кротоне', + 'Cuba' => 'Куба', + 'Cuneo' => 'Кунео', + 'Curency selection page - CSS stylesheet' => 'Страница выбора валюты - CSS стили', + 'Curency selection page - after javascript include' => 'Страница выбора валюты - послк включения javascript', + 'Curency selection page - after javascript initialisation' => 'Страница выбора валюты - после инициализации javascript', + 'Curency selection page - at the bottom' => 'Страница выбора валюты - внизу', + 'Curency selection page - at the top' => 'Страница выбора валюты - вверху', + 'Currencies - JavaScript' => 'Валюты - JavaScript', + 'Currencies - at the top' => 'Валюты - вверху', + 'Currencies - bottom' => 'Валюты - внизу', + 'Currencies - table header' => 'Валюты - заголовок таблицы', + 'Currencies - table row' => 'Валюты - строка таблицы', + 'Currency - Edit JavaScript' => 'Валюта - Редактирование JavaScript', + 'Currency - create form' => 'Валюта - форма создания', + 'Currency - delete form' => 'Валюта - форма удаления', + 'Currency block' => 'Переключатель валют', + 'Currency edit - bottom' => 'Редактирование валюты - внизу', + 'Currency edit - top' => 'Редактирование валюты - вверху', + 'Customer' => 'Клиент', + 'Customer - Edit' => 'Клиент - Edit', + 'Customer - Edit JavaScript' => 'Клиент - Редактирование JavaScript', + 'Customer - address create form' => 'Клиент - форма создания адреса', + 'Customer - address delete form' => 'Клиент - форма удаления адреса', + 'Customer - address update form' => 'Клиент - форма обновления адреса', + 'Customer - at the top' => 'Клиент - вверху', + 'Customer - bottom' => 'Клиент - внизу', + 'Customer - create form' => 'Клиент - форма создания', + 'Customer - delete form' => 'Клиент - форма удаления', + 'Customer - order table header' => 'Клиент - заголовок таблицы заказа', + 'Customer - order table row' => 'Клиент - строка таблицы заказа', + 'Customer account - additional information' => 'Аккаунт клиента - дополнительная информация', + 'Customer account block' => 'Блок для клиентов', + 'Customer title' => 'Заголовок клиента', + 'Customers - JavaScript' => 'Клиенты - JavaScript', + 'Customers - caption' => 'Клиенты - заглавие', + 'Customers - header' => 'Клиенты - заголовок', + 'Customers - row' => 'Клиенты - строка', + 'Cyprus' => 'Кипр', + 'Czech Republic' => 'Чешская Республика', + 'Czech koruna' => 'Чешская крона', + 'Córdoba' => 'Кордова', + 'Danish krone' => 'Датская крона', + 'Dashboard - at the top' => 'Приборная панель - вверху', + 'Dashboard - bottom' => 'Приборная панель - внизу', + 'Dashboard - middle' => 'Приборная панель - середина', + 'Data import / export' => 'Импорт / экспорт', + 'Default available stock when check-available-stock is set to 0.' => 'Доступный остаток когда check-available-stock выставлен в 0', + 'Default lang without translation' => 'Язык по умолчанию без перевода', + 'Delaware' => 'Делавэр', + 'Delivery - After delivery module' => 'Доставка - После модуля доставки', + 'Delivery - CSS' => 'Доставка - CSS', + 'Delivery - additional product information' => 'Доставка - дополнительная информация о товаре', + 'Delivery - after addresse area' => 'Доставка - после зоны адреса', + 'Delivery - after the information area' => 'Доставка - после информационной зоны', + 'Delivery - after the order summary' => 'Доставка - после общей суммы заказа', + 'Delivery - at the bottom of information area' => 'Доставка - внизу информационной зоны', + 'Delivery - at the bottom of the footer' => 'Доставка - внизу подвала', + 'Delivery - at the top of the footer' => 'Доставка - вверху подвала', + 'Delivery - delivery address' => 'Доставка - адрес доставки', + 'Delivery - imprint' => 'Доставка - штамп', + 'Delivery - in the header' => 'Доставка - в заголовке', + 'Delivery choice - CSS stylesheet' => 'Выбор доставки - CSS стили', + 'Delivery choice - after javascript include' => 'Выбор доставки- после включения javascript', + 'Delivery choice - after javascript initialisation' => 'Выбор доставки - после инициализации javascript', + 'Delivery choice - at the bottom' => 'Выбор доставки - внизу', + 'Delivery choice - at the bottom of the form' => 'Выбор доставки - внизу формы', + 'Delivery choice - at the top' => 'Выбор доставки - вверху', + 'Delivery choice - at the top of the form' => 'Выбор доставки - вверху формы', + 'Delivery choice - extra area' => 'Выбор доставки - доп. зона', + 'Delivery choice - javascript' => 'Выбор доставки - javascript', + 'Delivery zone - Edit JavaScript' => 'Зона доставки - Редактирование JavaScript', + 'Delivery zone - JavaScript' => 'Зона доставки - JavaScript', + 'Delivery zone - at the top' => 'Зона доставки - вверху', + 'Delivery zone - bottom' => 'Зона доставки - внизу', + 'Delivery zone - table header' => 'Зона доставки - заголовок таблицы', + 'Delivery zone - table row' => 'Зона доставки - строка таблицы', + 'Denmark' => 'Дания', + 'Dinar' => 'Динар', + 'Display and process prices with (0) or without (1) taxes.' => 'Отображать и обрабатывать цены с (0) или без (1) налогов.', + 'Displays the default blocks on the homepage of the administration' => 'Отображение стандартных блоков на главной админки', + 'District of Columbia' => 'Округ Колумбия', + 'Distrito Federal' => 'Федеральный округ', + 'Djibouti' => 'Джибути', + 'Document - Edit JavaScript' => 'Документ - Редактирование JavaScript', + 'Document edit - bottom' => 'Редактирование документа - внизу', + 'Document edit - top' => 'Редактирование документа - вверху', + 'Dollar' => 'Фиджийский доллар', + 'Dollar (CAD)' => 'Канадский доллар', + 'Dominica' => 'Доминика', + 'Dominican Republic' => 'Доминиканская Республика', + 'Durango' => 'Дюранго', + 'East Nusa Tenggara' => 'Восточной долготы Малые Зондские', + 'East kalimantan' => 'Восточный Калимантан', + 'Ecuador' => 'Эквадор', + 'Egypt' => 'Египет', + 'Ehime' => 'Эхимэ', + 'El Salvador' => 'Сальвадор', + 'Email html - layout - CSS' => 'Email html - каркас - CSS', + 'Email html - layout - footer' => 'Email html - каркас - footer', + 'Email html - order confirmation - after address' => 'Email html - подтверждение заказа - после адреса', + 'Email html - order confirmation - after products' => 'Email html - подтверждение заказа - после товаров', + 'Email html - order confirmation - before address' => 'Email html - подтверждение заказа - до адреса', + 'Email html - order confirmation - before products' => 'Email html - подтверждение заказа - до товаров', + 'Email html - order confirmation - delivery address' => 'Email html - подтверждение заказа - адрес доставки', + 'Email html - order confirmation - footer' => 'Email html - подтверждение заказа - footer', + 'Email html - order confirmation - order product' => 'Email html - подтверждение заказа - заказ товара', + 'Email html - order notification - after address' => 'Email html - уведомление о заказе - после адреса', + 'Email html - order notification - after products' => 'Email html - уведомление о заказе - после товаров', + 'Email html - order notification - before address' => 'Email html - уведомление о заказе - до адреса', + 'Email html - order notification - before products' => 'Email html - уведомление о заказе - до товаров', + 'Email html - order notification - delivery address' => 'Email html - уведомление о заказе - адрес доставки', + 'Email html - order notification - order product' => 'Email html - уведомление о заказе - заказ товара', + 'Email txt - order confirmation - after address' => 'Email текст - подтверждение заказа - после адреса', + 'Email txt - order confirmation - after products' => 'Email текст - подтверждение заказа - после товаров', + 'Email txt - order confirmation - before address' => 'Email текст - подтверждение заказа - до адреса', + 'Email txt - order confirmation - before products' => 'Email текст - подтверждение заказа - до товаров', + 'Email txt - order confirmation - delivery address' => 'Email текст - подтверждение заказа - адрес доставки', + 'Email txt - order confirmation - order product' => 'Email текст - подтверждение заказа - заказ товара', + 'Email txt - order notification - after address' => 'Email текст - уведомление о заказе - после адреса', + 'Email txt - order notification - after products' => 'Email текст - уведомление о заказе - после товаров', + 'Email txt - order notification - before address' => 'Email текст - уведомление о заказе - до адреса', + 'Email txt - order notification - before products' => 'Email текст - уведомление о заказе - до товаров', + 'Email txt - order notification - delivery address' => 'Email текст - уведомление о заказе - адрес доставки', + 'Email txt - order notification - order product' => 'Email текст - уведомление о заказе - заказ товара', + 'Enable (1) or disable (0) URL rewriting' => 'Вкл (1) или Выкл (0) URL rewriting', + 'Enna' => 'Энна', + 'Entre Ríos' => 'Энтре-Риос', + 'Equatorial Guinea' => 'Экваториальная Гвинея', + 'Eritrea' => 'Эритрея', + 'Estado de México' => 'Мехико', + 'Estonia' => 'Эстония', + 'Ethiopia' => 'Эфиопия', + 'Euro' => 'Евро', + 'Export - JavaScript' => 'Экспорт - JavaScript', + 'Export - table header' => 'Экспорт - заголовок таблицы', + 'Export - table row' => 'Экспорт - строка таблицы', + 'Export modal or page - bottom' => 'Страница или модальное окно экспорта - внизу', + 'Export modal or page - top' => 'Страница или модальное окно экспорта - вверху', + 'Exports - JavaScript' => 'Экспорты - JavaScript', + 'Exports - at the bottom of a category' => 'Экспорты - внизу категории', + 'Exports - at the bottom of column 1' => 'Экспорты - внизу колонки 1', + 'Exports - at the top' => 'Экспорты - вверху', + 'Feature - Edit JavaScript' => 'Характеристика - Редактирование JavaScript', + 'Feature - Value create form' => 'Характеристика - Форма создания значения', + 'Feature - add to all form' => 'Характеристика - форма добавить все', + 'Feature - create form' => 'Характеристика - форма создания', + 'Feature - delete form' => 'Характеристика - форма удаления', + 'Feature - remove to all form' => 'Характеристика - форма удалить все', + 'Feature edit - bottom' => 'Редактирование характеристики - внизу', + 'Feature edit - top' => 'Редактирование характеристики - вверху', + 'Features - JavaScript' => 'Характеристики - JavaScript', + 'Features - at the top' => 'Характеристики - вверху', + 'Features - bottom' => 'Характеристики - внизу', + 'Features - table header' => 'Характеристики - заголовок таблицы', + 'Features - table row' => 'Характеристики - строка таблицы', + 'Features value - table header' => 'Значение характеристик - заголовок таблицы', + 'Features value - table row' => 'Значение характеристик - строка таблицы', + 'Fermo' => 'Фермо', + 'Ferrara' => 'Феррара', + 'Fiji' => 'Фиджи', + 'File name of the 404 (not found) view in the current template (with extension, e.g. 404.html)' => 'Имя файла страницы 404 (не найден) в текущем шаблоне (с расширением, например 404.html)', + 'Filename of the error page' => 'Имя файла для страницы ошибок', + 'Finland' => 'Финляндия', + 'Firenze' => 'Флоренция', + 'Florida' => 'Флорида', + 'Foggia' => 'Фоджа', + 'Folder' => 'Папка', + 'Folder - Edit JavaScript' => 'Папка - Редактирование JavaScript', + 'Folder - JavaScript' => 'Папка - JavaScript', + 'Folder - Tab' => 'Папка - Вкладка', + 'Folder - at the top' => 'Папка - вверху', + 'Folder - bottom' => 'Папка - внизу', + 'Folder - caption' => 'Папка - заглавие', + 'Folder - content' => 'Папка - содержимое', + 'Folder - create form' => 'Папка - форма создания', + 'Folder - delete form' => 'Папка - форма удаления', + 'Folder - header' => 'Папка - заголовок', + 'Folder - row' => 'Папка - строка', + 'Folder edit - bottom' => 'Редактирование папки - внизу', + 'Folder edit - right column bottom' => 'Редактирование папки - внизу правой колонки', + 'Folder edit - right column top' => 'Редактирование папки - вверху правой колонки', + 'Folder edit - top' => 'Редактирование папки - вверху', + 'Folder page - CSS stylesheet' => 'Страница папки - CSS стили', + 'Folder page - after javascript include' => 'Страница папки - после включения javascript', + 'Folder page - after javascript initialisation' => 'Страница папки - после инициализации javascript', + 'Folder page - after the main content area' => 'Страница папки - после основной зоны контента', + 'Folder page - at the bottom' => 'Страница папки - внизу', + 'Folder page - at the bottom of the main area' => 'Страница папки - внизу основной зоны', + 'Folder page - at the top' => 'Страница папки - вверху', + 'Folder page - at the top of the main area' => 'Страница папки - вверху основной зоны', + 'Folder page - before the main content area' => 'Страница папки - перед основной зоной контента', + 'Forint' => 'Форинт', + 'Forlì-Cesena' => 'Форли-Чезена', + 'Formosa' => 'Формоза', + 'Franc' => 'Франк', + 'France metropolitan' => 'Франция столичная', + 'French 10% VAT' => 'Французский 10% НДС', + 'French 20% VAT' => 'Французский 20% НДС', + 'French Southern Territories' => 'Французские Южные Территории', + 'Front office integration' => 'Отображение магазина', + 'Frosinone' => 'Фрозиноне', + 'Fukui' => 'Фукуи', + 'Fukuoka' => 'Фукуока', + 'Fukushima' => 'Фукусима', + 'Gabon' => 'Габон', + 'Gambia' => 'Гамбия', + 'Genova' => 'Генуя', + 'Georgia' => 'Джорджия', + 'Germany' => 'Германия', + 'Ghana' => 'Гана', + 'Gifu' => 'Гифу', + 'Google Analytics block' => 'Блок Google Analytics', + 'Gorizia' => 'Гориция', + 'Greece' => 'Греция', + 'Grenada' => 'Гренада', + 'Grosseto' => 'Гроссето', + 'Guadeloupe' => 'Гваделупа', + 'Guanajuato' => 'Гуанахуато', + 'Guaraní' => 'Гуарани', + 'Guatemala' => 'Гватемала', + 'Guerrero' => 'Герреро', + 'Guinea' => 'Гвинея', + 'Guinea-Bissau' => 'Гвинея-Бисау', + 'Gunma' => 'Гумма', + 'Guyana' => 'Гайана', + 'Guyane Française' => 'Французская Гвиана', + 'HTML layout - CSS stylesheet' => 'HTML каркас - CSS стили', + 'HTML layout - after javascript include' => 'HTML каркас - после включения javascript', + 'HTML layout - after the main content area' => 'HTML каркас - после зоны основного контента', + 'HTML layout - after the opening of the body tag' => 'HTML каркас - после открытия тега body ', + 'HTML layout - after the opening of the head tag' => 'HTML каркас - после открытия тега head', + 'HTML layout - at the bottom of the header' => 'HTML каркас - внизу шапки', + 'HTML layout - at the top of the footer' => 'HTML каркас - вверху подвала', + 'HTML layout - at the top of the header' => 'HTML каркас - вверху шапки', + 'HTML layout - before the end body tag' => 'HTML каркас - перед закрытием тега body', + 'HTML layout - before the end of the head tag' => 'HTML каркас - перед закрытием тега head', + 'HTML layout - before the main content area' => 'HTML каркас - перед зоной основного контента', + 'HTML layout - bottom of the footer' => 'HTML каркас - внизу подвала', + 'HTML layout - footer body' => 'HTML каркас - тело подвала', + 'HTML layout - javascript initialization' => 'HTML каркас - после инициализации javascript', + 'HTML layout - primary navigation' => 'HTML каркас - первичная навигация', + 'HTML layout - secondary navigation' => 'HTML каркас - вторичная навигация', + 'Haiti' => 'Гаити', + 'Hawaii' => 'Гавайи', + 'Hidalgo' => 'Идальго', + 'Hiroshima' => 'Хиросима', + 'Hokkaido' => 'Хоккайдо', + 'Home - JavaScript' => 'Главная - JavaScript', + 'Home - at the top' => 'Главная - вверху', + 'Home - block' => 'Главная - блок', + 'Home - bottom' => 'Главная - внизу', + 'Home page - CSS stylesheet' => 'Домашнаяя страница - CSS стили', + 'Home page - after javascript include' => 'Домашнаяя страница - после включения javascript', + 'Home page - after javascript initialisation' => 'Домашнаяя страница - после инициализации javascript', + 'Home page - main area' => 'Домашняя страница - основная зона', + 'Honduras' => 'Гондурас', + 'Hong Kong' => 'Гонконг', + 'Hong Kong Dollar' => 'Гонконгский доллар', + 'Hook - Edit JavaScript' => 'Хук - Редактирование JavaScript', + 'Hook - create form' => 'Хук - форма создания', + 'Hook - delete form' => 'Хук - форма удаления', + 'Hook edit - bottom' => 'Редактирование хука - внизу', + 'Hook edit - top' => 'Редактирование хука - вверху', + 'Hook positions' => 'Позиции хуков', + 'Hooks' => 'Хуки', + 'Hooks - JavaScript' => 'Хуки - JavaScript', + 'Hooks - at the top' => 'Хуки - вверху', + 'Hooks - bottom' => 'Хуки - внизу', + 'Hooks - table header' => 'Хуки - заголовок таблицы', + 'Hooks - table row' => 'Хуки - строка таблицы', + 'Hooks management' => 'Управление хуками', + 'How document files are delivered in the web space (symlink or copy)' => 'Способ доставки документов в web директорию (symlink или copy)', + 'How original (full resolution) images are delivered in the web space (symlink or copy)' => 'Способ доставки оригинальных изображений в web директорию (symlink или copy)', + 'Hungary' => 'Венгрия', + 'Hyogo' => 'Хего', + 'Ibaraki' => 'Ибараки', + 'Iceland' => 'Исландия', + 'Idaho' => 'Айдахо', + 'Illinois' => 'Иллинойс', + 'Image - Edit JavaScript' => 'Изображение - Редактирование JavaScript', + 'Image edit - bottom' => 'Редактирование изображения - внизу', + 'Image edit - top' => 'Редактирование изображения - вверху', + 'Imperia' => 'Империя', + 'Import - table header' => 'Импорт - заголовок таблицы', + 'Import - table row' => 'Импорт - строка таблицы', + 'India' => 'Индия', + 'Indian Rupee' => 'Индийская рупия', + 'Indiana' => 'Индиана', + 'Indonesia' => 'Индонезия', + 'Invoice - After delivery module' => 'Счет-фактура - После модуля доставки', + 'Invoice - After payment module' => 'Счет-фактура - После модуля оплаты', + 'Invoice - CSS' => 'Счет-фактура - CSS', + 'Invoice - additional product information' => 'Счет-фактура - дополнительная информация о товаре', + 'Invoice - after addresse area' => 'Счет-фактура - после зоны адреса', + 'Invoice - after product listing' => 'Счет-фактура - после списка товаров', + 'Invoice - after the information area' => 'Счет-фактура - после информационной зоны', + 'Invoice - after the order summary' => 'Счет-фактура - после общей суммы заказа', + 'Invoice - at the bottom of information area' => 'Счет-фактура - внизу информационной зоны', + 'Invoice - at the bottom of the footer' => 'Счет-фактура - внизу подвала', + 'Invoice - at the top of the footer' => 'Счет-фактура - вверху подвала', + 'Invoice - delivery address' => 'Счет-фактура - адрес доставки', + 'Invoice - imprint' => 'Счет-фактура - штамп', + 'Invoice - in the header' => 'Счет-фактура - в заголовке', + 'Invoice choice - CSS stylesheet' => 'Выбор счет-фактуры - CSS стили', + 'Invoice choice - after javascript include' => 'Выбор счет-фактуры - после включения javascript', + 'Invoice choice - after javascript initialisation' => 'Выбор счет-фактуры - после инициализации javascript ', + 'Invoice choice - at the bottom' => 'Выбор счет-фактуры - внизу', + 'Invoice choice - at the top' => 'Выбор счет-фактуры - вверху', + 'Invoice choice - delivery address' => 'Выбор счет-фактуры - адрес доставки', + 'Invoice choice - extra payment zone' => 'Выбор счет-фактуры - доп. зона оплаты', + 'Iowa' => 'Айова', + 'Iran' => 'Иран', + 'Iraq' => 'Ирак', + 'Ireland' => 'Ирландия', + 'Isernia' => 'Изерния', + 'Ishikawa' => 'Исикава', + 'Israel' => 'Израиль', + 'Italy' => 'Италия', + 'Ivory Coast' => 'Кот-д\'Ивуар', + 'Iwate' => 'Ивате', + 'Jakarta' => 'Джакарта', + 'Jalisco' => 'Халиско', + 'Jamaica' => 'Ямайка', + 'Jambi' => 'Джамби', + 'Japan' => 'Япония', + 'Jordan' => 'Иордания', + 'Jujuy' => 'Жужуй', + 'Kagawa' => 'Кагава', + 'Kagoshima' => 'Кагосима', + 'Kanagawa' => 'Канагава', + 'Kansas' => 'Канзас', + 'Kazakhstan' => 'Казахстан', + 'Kentucky' => 'Кентукки', + 'Kenya' => 'Кения', + 'Kenyan shilling' => 'Кенийский шиллинг', + 'Kiribati' => 'Кирибати', + 'Kochi' => 'Коти', + 'Krona' => 'Шведская крона', + 'Krone' => 'Норвежская крона', + 'Kumamoto' => 'Кумамото', + 'Kuwait' => 'Кувейт', + 'Kyoto' => 'Киото', + 'Kyrgyzstan' => 'Кыргызстан', + 'L\'Aquila' => 'Аквила', + 'La Pampa' => 'Ла-Пампа', + 'La Rioja' => 'Ла-Риоха', + 'La Spezia' => 'Ла Специя', + 'Lambang Provinsi Papua Barat' => 'Lambang Provinsi Папуа Барат', + 'Lambang Riau' => 'Lambang Риау', + 'Lambang propinsi' => 'Lambang Пропинси', + 'Lampung' => 'Лампунг', + 'Language - create form' => 'Язык - форма создания', + 'Languages - JavaScript' => 'Языки - JavaScript', + 'Languages - at the top' => 'Языки - вверху', + 'Languages - bottom' => 'Языки - внизу', + 'Languages - delete form' => 'Языки - форма удаления', + 'Languages block' => 'Переключатель языков', + 'Laos' => 'Лаос', + 'Lari' => 'Лари', + 'Latina' => 'Латина', + 'Latvia' => 'Латвия', + 'Layout - Before the main content' => 'Каркас - Перед основным контентом', + 'Layout - CSS' => 'Каркас - CSS', + 'Layout - JavaScript' => 'Каркас - JavaScript', + 'Layout - after footer' => 'Каркас - после подвала', + 'Layout - after top bar' => 'Каркас - после верхней панели', + 'Layout - after top menu' => 'Каркас - после верхнего меню', + 'Layout - at the bottom of the top bar' => 'Каркас - внизу верхней панели', + 'Layout - at the top of the top bar' => 'Каркас - вверху верхней панели', + 'Layout - before footer' => 'Каркас - перед подвалом', + 'Layout - before top menu' => 'Каркас - перед верхним меню', + 'Layout - before topbar' => 'Каркас - перед верхней панелью', + 'Layout - in footer' => 'Каркас - в подвале', + 'Layout - in the menu catalog' => 'Каркас - в меню каталог', + 'Layout - in the menu configuration' => 'Каркас - в меню конфигурация', + 'Layout - in the menu customers' => 'Каркас - в меню клиенты', + 'Layout - in the menu folders' => 'Каркас - в меню папки', + 'Layout - in the menu modules' => 'Каркас - в меню модули', + 'Layout - in the menu orders' => 'Каркас - в меню заказы', + 'Layout - in the menu tools' => 'Каркас - в меню инструменты', + 'Layout - in top menu items' => 'Каркас - в элементрах верхнего меню', + 'Layout - inside top bar' => 'Каркас - внутри верхней панели', + 'Leave the default configuration of session' => 'Оставить настройки по умолчанию для сессии', + 'Lebanon' => 'Ливан', + 'Lecce' => 'Лечче', + 'Lecco' => 'Лекко', + 'Lei' => 'Румынский лей', + 'Lesotho' => 'Лесото', + 'Lev' => 'Лев', + 'Liberia' => 'Либерия', + 'Libya' => 'Ливия', + 'Liechtenstein' => 'Лихтенштейн', + 'Life time of the cart cookie in the customer browser, in seconds' => 'Время жизни cookie корзины в секундах', + 'Life time of the session cookie in the customer browser, in seconds' => 'Время жизни cookie сессии клиента в секундах', + 'Links block' => 'Блок ссылок', + 'Lira' => 'Лира', + 'Lithuania' => 'Литва', + 'Livorno' => 'Ливорно', + 'Lodi' => 'Лоди', + 'Logging system configuration' => 'Конфигурация системы логов', + 'Login page - CSS stylesheet' => 'Страница логина - CSS стили', + 'Login page - after javascript include' => 'Страница логина - после включения javascript', + 'Login page - after javascript initialisation' => 'Страница логина - после инициализации javascript', + 'Login page - at the bottom' => 'Страница логина - внизу', + 'Login page - at the bottom of the form' => 'Страница логина - внизу формы', + 'Login page - at the bottom of the main area' => 'Страница логина - внизу основной зоны', + 'Login page - at the top' => 'Страница логина - вверху', + 'Login page - at the top of the form' => 'Страница логина - вверху формы', + 'Login page - at the top of the main area' => 'Страница логина - вверху основной зоны', + 'Logs - JavaScript' => 'Логи - JavaScript', + 'Logs - at the top' => 'Логи - вверху', + 'Logs - bottom' => 'Логи - внизу', + 'Lost password - CSS stylesheet' => 'Восстановление пароля - CSS стили', + 'Lost password - after javascript include' => 'Восстановление пароля - после включения javascript', + 'Lost password - at the bottom' => 'Восстановление пароля - внизу', + 'Lost password - at the bottom of the form' => 'Восстановление пароля - внизу формы', + 'Lost password - at the top' => 'Восстановление пароля - вверху', + 'Lost password - at the top of the form' => 'Восстановление пароля - вверху формы', + 'Lost password - javascript initialization' => 'Восстановление пароля - после инициализации javascript', + 'Louisiana' => 'Луизиана', + 'Lucca' => 'Лукка', + 'Luxembourg' => 'Люксембург', + 'Macedonia' => 'Македония', + 'Macerata' => 'Мачерата', + 'Madagascar' => 'Мадагаскар', + 'Mail sent after a subscription to newsletter' => 'Выслано письмо после подписки на рассылку', + 'Mail sent to an administrator who requested a new password' => 'Письмо отсылаемое администратору при запросе нового пароля', + 'Mail sent to the customer when its account is created by an administrator in the back-office' => 'Письмо отсылаемое клиенту когда аккаунт был создан администратором в админке', + 'Mail sent to the customer when its password or email is changed in the back-office' => 'Письмо отылаемое клиенту когда его пароль или email изменен из админки', + 'Mailing system - JavaScript' => 'Система отправки почты - JavaScript', + 'Mailing system - at the top' => 'Система отправки почты - вверху', + 'Mailing system - bottom' => 'Система отправки почты - внизу', + 'Maine' => 'Мейн', + 'Malawi' => 'Малави', + 'Malaysia' => 'Малайзия', + 'Maldives' => 'Мальдивы', + 'Mali' => 'Мали', + 'Malta' => 'Мальта', + 'Maluku' => 'Малуку', + 'Manat' => 'Манат', + 'Manitoba' => 'Манитоба', + 'Mantova' => 'Мантуя', + 'Marshall Islands' => 'Маршалловы острова', + 'Martinique' => 'Мартиника', + 'Maryland' => 'Мэриленд', + 'Massa' => 'Масса', + 'Massachusetts' => 'Массачусетс', + 'Matera' => 'Матера', + 'Mauritania' => 'Мавритания', + 'Mauritius' => 'Маврикий', + 'Mayotte' => 'Майотта', + 'Medio Campidano' => 'Медио Кампидано', + 'Mendoza' => 'Мендоса', + 'Message - Edit JavaScript' => 'Сообщение - Редактирование JavaScript', + 'Message - create form' => 'Сообщения - форма создания', + 'Message - delete form' => 'Сообщения - форма удаления', + 'Message edit - bottom' => 'Редактирование сообщения - внизу', + 'Message edit - top' => 'Редактирование сообщения - вверху', + 'Message sent to the shop owner when a new order is placed' => 'Сообщение отсылаемое владельцу магазина при новом заказе', + 'Messages - JavaScript' => 'Сообщения - JavaScript', + 'Messages - at the top' => 'Сообщения - вверху', + 'Messages - bottom' => 'Сообщения - низ', + 'Messages - table header' => 'Сообщения - заголовок таблицы', + 'Messages - table row' => 'Сообщения - строка таблицы', + 'Messina' => 'Мессина', + 'Mexico' => 'Мексика', + 'Michigan' => 'Мичиган', + 'Michoacán' => 'Мичоакан', + 'Micronesia' => 'Микронезия', + 'Mie' => 'Мие', + 'Milano' => 'Милан', + 'Mini cart' => 'Мини корзина', + 'Minnesota' => 'Миннесота', + 'Misiones' => 'Мисьонес', + 'Miss' => 'Уважаемая', + 'Miss_short' => 'Ув.', + 'Misses' => 'Уважаемая', + 'Mississippi' => 'Миссисипи', + 'Missouri' => 'Миссури', + 'Mister' => 'Уважаемый', + 'Miyagi' => 'Мияги', + 'Miyazaki' => 'Миядзаки', + 'Modena' => 'Модена', + 'Module - Edit JavaScript' => 'Модуль - Редактирование JavaScript', + 'Module - configuration' => 'Модуль - конфигурация', + 'Module - configuration JavaScript' => 'Модуль - конфигурация JavaScript', + 'Module edit - bottom' => 'Редактирование модуля - внизу', + 'Module edit - top' => 'Редактирование модуля - вверху', + 'Module hook - Edit JavaScript' => 'Хук модуля - Редактирование JavaScript', + 'Module hook - JavaScript' => 'Хук модуля - JavaScript', + 'Module hook - create form' => 'Хук модуля - форма создания', + 'Module hook - delete form' => 'Хук модуля - форма удаления', + 'Module hook edit - bottom' => 'Редактирование хука модуля - внизу', + 'Module hook edit - top' => 'Редактирование хука модуля - вверху', + 'Modules - JavaScript' => 'Модули - JavaScript', + 'Modules - at the top' => 'Модули - вверху', + 'Modules - bottom' => 'Модули - внизу', + 'Modules - table header' => 'Модули - заголовок таблицы', + 'Modules - table row' => 'Модули - строка таблицы', + 'Modules maagement' => 'Управление модулями', + 'Modules management' => 'Управление модулями', + 'Moldova' => 'Молдова', + 'Monaco' => 'Монако', + 'Mongolia' => 'Монголия', + 'Montana' => 'Монтана', + 'Monza e della Brianza' => 'Монца э делла Брианца', + 'Morelos' => 'Морелос', + 'Morocco' => 'Марокко', + 'Mozambique' => 'Мозамбик', + 'Mr.' => 'Ув.', + 'Mrs' => 'Ув.', + 'Nagano' => 'Нагано', + 'Nagasaki' => 'Нагасаки', + 'Name of the active PDF template' => 'Имя активного шаблона для PDF', + 'Name of the active back-office template' => 'Имя активного шаблона админки', + 'Name of the active front-office template' => 'Имя активного шаблона магазина', + 'Name of the active mailing template' => 'Имя активного шаблона рассылок', + 'Name of the cart cookie' => 'Имя cookie корзины', + 'Name of the delivery view in the current PDF template (without extension)' => 'Имя страницы текущего PDF шаблона для доставки (без расширения)', + 'Name of the graphic driver used by the Imagine library (see https://imagine.readthedocs.org)' => 'Имя графического драйвера используемого библиотекой Imagine (см. https://imagine.readthedocs.org)', + 'Name of the invoice view in the current PDF template (without extension)' => 'Имя страницы текущего PDF шаблона для счет-фактуры (без расширения)', + 'Name of the template view returned when an obsolete (or inactive) product URL is invoked' => 'Имя страницы шаблона возвращаемой при вызове заброшеного (или не активного) URL товара', + 'Name the cart cookie' => 'Имя cookie корзины', + 'Namibia' => 'Намибия', + 'Napoli' => 'Наполи', + 'Nara' => 'Нара', + 'Nauru' => 'Науру', + 'Navigation block' => 'Блок навигации', + 'Nayarit' => 'Наярит', + 'Nebraska' => 'Небраска', + 'Nepal' => 'Непал', + 'Netherlands' => 'Нидерланды', + 'Neuquén' => 'Неукен', + 'Nevada' => 'Невада', + 'New Brunswick' => 'Новый Брансвик', + 'New Hampshire' => 'Нью-Гемпшир', + 'New Jersey' => 'Нью-Джерси', + 'New Mexico' => 'Нью-Мексико', + 'New Products block' => 'Блок новых товаров', + 'New York' => 'Нью-Йорк', + 'New Zealand' => 'Новая Зеландия', + 'New order {$order_ref} placed on {config key="store_name"}' => 'Новый заказ {$order_ref} размещен в {config key="store_name"}', + 'New password request on %store' => 'Ваш новый пароль для %store', + 'Newfoundland and Labrador' => 'Ньюфаундленд и Лабрадор', + 'Newsletter block' => 'Блок подписки', + 'Newsletter page - CSS stylesheet' => 'Страница рассылки - CSS стили', + 'Newsletter page - after javascript include' => 'Страница рассылки - после включения javascript', + 'Newsletter page - after javascript initialisation' => 'Страница рассылки - после инициализации javascript', + 'Newsletter page - at the bottom' => 'Страница рассылки - внизу', + 'Newsletter page - at the top' => 'Страница рассылки - вверху', + 'Newsletter subscription confirmation mail' => 'Письмо подтверждения подписки на рассылку новостей', + 'Newsletter unsubscribe page - CSS stylesheet' => 'Страница отписки от рассылки - CSS стили', + 'Newsletter unsubscribe page - after javascript include' => 'Страница отписки от рассылки - после включения javascript', + 'Newsletter unsubscribe page - after javascript initialisation' => 'Страница отписки от рассылки - после инициализации javascript', + 'Newsletter unsubscribe page - at the bottom' => 'Страница отписки от рассылки - внизу', + 'Newsletter unsubscribe page - at the top' => 'Страница отписки от рассылки - вверху', + 'Nicaragua' => 'Никарагуа', + 'Niger' => 'Нигер', + 'Nigeria' => 'Нигерия', + 'Nigerian naira' => 'Нигерийская найра', + 'Niigata' => 'Ниигата', + 'Niue' => 'Ниуэ', + 'North Carolina' => 'Северная Каролина', + 'North Dakota' => 'Северная Дакота', + 'North Korea' => 'Северная Корея', + 'North Maluku' => 'Северное Малуку', + 'North Sulawesi' => 'Северный Сулавеси', + 'North Sumatra' => 'Северная Суматра', + 'Northwest Territories' => 'Северо-западные территории', + 'Norway' => 'Норвегия', + 'Not paid' => 'Не оплачен', + 'Nouvelle-Calédonie' => 'Новая Каледония', + 'Nova Scotia' => 'Новая Шотландия', + 'Novara' => 'Новара', + 'Nuevo León' => 'Нуэво-Леон', + 'Nuevo Sol' => 'Перуанский соль', + 'Number by default of results per page for customer list' => 'Количество результатов по умолчанию для списка клиентов', + 'Number by default of results per page for order list' => 'Количество результатов по умолчанию для списка заказов', + 'Number by default of results per page for product list' => 'Количество результатов по умолчанию для списка товаров', + 'Nunavut' => 'Нунавут', + 'Nuoro' => 'Нуоро', + 'Oaxaca' => 'Оахака', + 'Ogliastra' => 'Ольястра', + 'Ohio' => 'Огайо', + 'Oita' => 'Оита', + 'Okayama' => 'Окаяма', + 'Okinawa' => 'Окинава', + 'Oklahoma' => 'Оклахома', + 'Olbia-Tempio' => 'Ольвия-Темпио', + 'Oman' => 'Оман', + 'Ontario' => 'Онтарио', + 'Order' => 'Заказ', + 'Order - After closing product row' => 'Заказ - После строки товара', + 'Order - After product list' => 'Заказ - После списка товаров', + 'Order - Before product list' => 'Заказ - Перед списком товаров', + 'Order - Before starting product row' => 'Заказ - Перед строкой товара', + 'Order - Edit JavaScript' => 'Заказ - Редактирование JavaScript', + 'Order - Tab' => 'Заказ - Вкладка', + 'Order - bill bottom' => 'Заказ - низ оплаты', + 'Order - bill top' => 'Заказ - верх оплаты', + 'Order - cart bottom' => 'Заказ - низ корзины', + 'Order - cart top' => 'Заказ - верх корзины', + 'Order - content' => 'Заказ - содержимое', + 'Order - customer information bottom' => 'Заказ - внизу информации о клиенте', + 'Order - delivery module bottom' => 'Заказ - внизу модуля доставки', + 'Order - payment module bottom' => 'Заказ - внизу модуля оплаты', + 'Order - product list' => 'Заказ - список товаров', + 'Order - table header' => 'Заказ - заголовок таблицы', + 'Order - table row' => 'Заказ - строка таблицы', + 'Order confirmation - after the order summary' => 'Подтверждение заказа - после общей суммы заказа', + 'Order confirmation sent to the customer' => 'Подтверждение заказа отосланное клиенту', + 'Order details - CSS stylesheet' => 'Детали заказа - CSS стили', + 'Order details - additional delivery information' => 'Детали заказа - дополнительная информация доставки', + 'Order details - additional information' => 'Детали заказа - дополнительная информация', + 'Order details - additional invoice information' => 'Детали заказа - дополнительная информация счет-фактуры', + 'Order details - additional product information' => 'Детали заказа - дополнительная информация товара', + 'Order details - after addresses' => 'Детали заказа - после адресов', + 'Order details - after delivery address' => 'Детали заказа - после адреса доставки', + 'Order details - after global information' => 'Детали заказа - после общей информации', + 'Order details - after invoice address' => 'Детали заказа - после адреса счет-фактуры', + 'Order details - after javascript include' => 'Детали заказа - после включения javascript', + 'Order details - after product' => 'Детали заказа - после товара', + 'Order details - after products' => 'Детали заказа - после товаров', + 'Order details - after products list' => 'Детали заказа - после списка товаров', + 'Order details - at the bottom' => 'Детали заказа - внизу', + 'Order details - at the top' => 'Детали заказа - вверху', + 'Order details - before products list' => 'Детали заказа - перед списком товаров', + 'Order details - delivery address' => 'Детали заказа - адрес доставки', + 'Order details - invoice address' => 'Детали заказа - адрес счет-фактуры', + 'Order details - javascript initialization' => 'Детали заказа - после инициализщации javascript', + 'Order edit - bottom' => 'Редактирование заказа - внизу', + 'Order edit - delivery address' => 'Редактирование заказа - адрес доставки', + 'Order edit - displayed after product information' => 'Редактирование заказа - отображается после информации о товаре', + 'Order edit - order product table header' => 'Редактирование заказа - заголовок таблицы заказ товара', + 'Order edit - order product table row' => 'Редактирование заказа - строка таблицы заказ товара', + 'Order edit - top' => 'Редактирование заказа - вверху', + 'Order failed - CSS stylesheet' => 'Ошибка заказа - CSS стили', + 'Order failed - after javascript include' => 'Ошибка заказа - после включения javascript', + 'Order failed - after javascript initialisation' => 'Ошибка заказа - после инициализации javascript', + 'Order failed - at the bottom' => 'Ошибка заказа - внизу', + 'Order failed - at the top' => 'Ошибка заказа - вверху', + 'Orders - JavaScript' => 'Заказы - JavaScript', + 'Orders - at the top' => 'Заказы - вверху', + 'Orders - bottom' => 'Заказы - внизу', + 'Orders - table header' => 'Заказы - заголовок таблицы', + 'Orders - table row' => 'Заказы - строка таблицы', + 'Oregon' => 'Oregon', + 'Oristano' => 'Ористано', + 'Osaka' => 'Осака', + 'Padova' => 'Падуя', + 'Page 404 - CSS stylesheet' => 'Страница 404 - CSS стили', + 'Page 404 - after javascript include' => 'Страница 404 - после включения javascript', + 'Page 404 - after javascript initialisation' => 'Страница 404 - после инициализации javascript', + 'Page 404 - content area' => 'Страница 404 - зона контента', + 'Paid' => 'Оплачен', + 'Pakistan' => 'Пакистан', + 'Palermo' => 'Палермо', + 'Panama' => 'Панама', + 'Papua' => 'Папуа', + 'Papua Nueva Guinea' => 'Папуа Новая Гвинея', + 'Paraguay' => 'Парагвай', + 'Parma' => 'Парма', + 'Path to the directory where documents are stored' => 'Путь до дериктории где хранятся документы', + 'Path to the directory where images are stored' => 'Путь до директории где хранятся изображения', + 'Pavia' => 'Павия', + 'Pay by cheque' => 'Оплата чеком', + 'Payment failed - CSS stylesheet' => 'Платеж отклонен - CSS стили', + 'Payment failed - after javascript include' => 'Платеж отклонен - после включения javascript', + 'Payment failed - javascript initialization' => 'Платеж отклонен - после инициализации javascript', + 'Payment gateway - CSS stylesheet' => 'Платежный шлюз - CSS стили', + 'Payment gateway - after javascript include' => 'Платежный шлюз - после включения javascript', + 'Payment gateway - after javascript initialisation' => 'Платежный шлюз - после инициализации javascript', + 'Payment gateway - javascript' => 'Платежный шлюз - javascript', + 'Payment gateway - main area' => 'Платежный шлюз - основная зона', + 'Pennsylvania' => 'Пенсильвания', + 'Peru' => 'Перу', + 'Perugia' => 'Перуджа', + 'Pesaro-Urbino' => 'Пезаро-Урбино', + 'Pescara' => 'Пескара', + 'Peso' => 'Песо', + 'Peso Argentino' => 'Аргентинский песо', + 'Philippine Peso' => 'Филиппинское песо', + 'Philippines' => 'Филиппины', + 'Piacenza' => 'Пьяченца', + 'Pisa' => 'Пиза', + 'Pistoia' => 'Пистойя', + 'Placed order - CSS stylesheet' => 'Размещенный заказ - CSS стили', + 'Placed order - after javascript include' => 'Размещенный заказ - после включения javascript', + 'Placed order - after javascript initialisation' => 'Размещенный заказ - после инициализации javascript', + 'Placed order - main area' => 'Размещенный заказ - основная зона', + 'Poland' => 'Польша', + 'Polynésie française' => 'Французская полинезия', + 'Pordenone' => 'Порденоне', + 'Portugal' => 'Португалия', + 'Potenza' => 'Потенца', + 'Pound' => 'Египетский фунт', + 'Prato' => 'Прато', + 'Prince Edward Island' => 'Остров Принца Эдуарда', + 'Processing' => 'В обработке', + 'Product' => 'Товар', + 'Product - Edit JavaScript' => 'Товар - Редактирование JavaScript', + 'Product - Tab' => 'Товар - Вкладка', + 'Product - accessories table header' => 'Товар - заголовок таблицы аксессуаров', + 'Product - accessories table row' => 'Товар - строка таблицы аксессуаров', + 'Product - after combinations' => 'Товар - после комбинаций', + 'Product - at the bottom of a product combination' => 'Товар - внизу комбинации товара', + 'Product - attributes table header' => 'Товар - заголовок таблицы атрибутов', + 'Product - attributes table row' => 'Товар - строка таблицы атрибутов', + 'Product - before combinations' => 'Товар - перед комбинациями', + 'Product - categories table header' => 'Товар - заголовок таблицы категорий', + 'Product - categories table row' => 'Товар - строка таблицы категорий', + 'Product - combination delete form' => 'Товар - форма удаления комбинации', + 'Product - combinations list caption' => 'Товар - заголовок списка комбинаций', + 'Product - content' => 'Товар - содержимое', + 'Product - contents table header' => 'Товар - заголовок таблицы содержимого', + 'Product - contents table row' => 'Товар - строка таблицы содержимого', + 'Product - create form' => 'Товар - форма создания', + 'Product - delete form' => 'Товар - форма удаления', + 'Product - details pricing form' => 'Товар - форма деталей ценообразования', + 'Product - details promotion form' => 'Товар - форма деталей продвижения', + 'Product - features table row' => 'Товар - строка таблицы характеристик', + 'Product - features-table-header' => 'Товар - заголовок таблицы характеристик', + 'Product - folders table header' => 'Товар - заголовок таблицы папок', + 'Product - folders table row' => 'Товар - строка таблицы папок', + 'Product - stock edit form' => 'Товар - форма редактирования остатков на складе', + 'Product edit - bottom' => 'Редактирование товара - внизу', + 'Product edit - right column bottom' => 'Редактирование товара - внизу правой колонки', + 'Product edit - right column top' => 'Редактирование товара - вверху правой колонки', + 'Product edit - top' => 'Редактирование товара - вверху', + 'Product loop - at the bottom' => 'Цикл товара - внизу', + 'Product loop - at the top' => 'Цикл товара - вверху', + 'Product page - CSS stylesheet' => 'Страница товара - CSS стили', + 'Product page - On the bottom of the form' => 'Страница товара - Внизу формы', + 'Product page - On the top of the form' => 'Страница товара - Вверху формы', + 'Product page - additional information' => 'Страница товара - дополнительная информация', + 'Product page - after javascript include' => 'Страница товара - после включения javascript', + 'Product page - after javascript initialisation' => 'Страница товара - после инициализации javascript', + 'Product page - at the bottom' => 'Страница товара - внизу', + 'Product page - at the bottom of the detail area' => 'Страница товара - внизу зоны деталей', + 'Product page - at the top' => 'Страница товара - вверху', + 'Product page - at the top of the detail' => 'Страница товара - вверху деталей', + 'Product page - photo gallery' => 'Страница товара - фото галерея', + 'Products - caption' => 'Товары - заглавие', + 'Products - header' => 'Товары - заголовок', + 'Products - row' => 'Товары - строка', + 'Products offer block' => 'Блок предлагаемых товаров', + 'Profile - Edit JavaScript' => 'Профиль - Редактирование JavaScript', + 'Profile - create form' => 'Профиль - форма создания', + 'Profile - delete form' => 'Профиль - форма удаления', + 'Profile - table header' => 'Профиль - заголовок таблицы', + 'Profile - table row' => 'Профиль - строка таблицы', + 'Profile edit - bottom' => 'Редактирование профиля - внизу', + 'Profile edit - top' => 'Редактирование профиля - вверху', + 'Profiles - JavaScript' => 'Профили - JavaScript', + 'Profiles - at the top' => 'Профили - вверху', + 'Profiles - bottom' => 'Профили - внизу', + 'Puebla' => 'Пуэбла', + 'Puerto Rico' => 'Пуэрто-Рико', + 'Qatar' => 'Катар', + 'Quebec' => 'Квебек', + 'Querétaro' => 'Керетаро', + 'Quetzal' => 'Кетцаль', + 'Quintana Roo' => 'Кинтана-РОО', + 'Ragusa' => 'Рагуза', + 'Ravenna' => 'Равенна', + 'Real' => 'Бразильский Реал', + 'Refunded' => 'Возвращен', + 'Reggio Calabria' => 'Реджо-ди-Калабрии', + 'Reggio Emilia' => 'Реджио Эмилия', + 'Register - CSS stylesheet' => 'Регистрация - CSS стили', + 'Register - after javascript include' => 'Регистрация - после включения javascript', + 'Register - after javascript initialisation' => 'Регистрация - после инициализации javascript', + 'Register - at the bottom' => 'Регистрация - внизу', + 'Register - at the bottom of the form' => 'Регистрация - внизу формы', + 'Register - at the top' => 'Регистрация - вверху', + 'Register - at the top of the form' => 'Регистрация - вверху формы', + 'Rhode Island' => 'Род-Айленд', + 'Riau' => 'Риау', + 'Rieti' => 'Риети', + 'Rimini' => 'Римини', + 'Ringgit' => 'Ринггит', + 'Riyal' => 'Риал', + 'Roma' => 'Рома', + 'Romania' => 'Румыния', + 'Rovigo' => 'Ровиго', + 'Ruble' => 'Рубль', + 'Rupee' => 'Пакистанская рупия', + 'Rupiah' => 'Индонезийская рупия', + 'Russia' => 'Россия', + 'Rwanda' => 'Руанда', + 'Réunion(La)' => 'Реюньон (La)', + 'Río Negro' => 'Рио-Негро', + 'Saga' => 'Сага', + 'Saint Barthélemy' => 'Сен-Бартельми', + 'Saint Kitts and Nevis' => 'Сент-Китс и Невис', + 'Saint Lucia' => 'Сент-Люсия', + 'Saint Martin (French part)' => 'Сен-Мартен (французская часть)', + 'Saint Vincent and the Grenadines' => 'Святой Винсент и Гренадины', + 'Saitama' => 'Сайтама', + 'Sale - CSS stylesheet' => 'Распродажа - CSS стили', + 'Sale - after javascript include' => 'Распродажа - после включения javascript', + 'Sale - after the main content area' => 'Распродажа - после зоной основного контента', + 'Sale - at the bottom' => 'Распродажа - внизу', + 'Sale - at the bottom of the main area' => 'Распродажа - внизу основной зоны', + 'Sale - at the top' => 'Распродажа - вверху', + 'Sale - at the top of the main area' => 'Распродажа - вверху основной зоны', + 'Sale - before the main content area' => 'Распродажа - перед зоной основного контента', + 'Sale - create form' => 'Распродажа - форма создания', + 'Sale - delete form' => 'Распродажа - форма удаления', + 'Sale - javascript initialization' => 'Распродажа - после инициализации javascript ', + 'Sale edit - bottom' => 'Редактирование распродажи - внизу', + 'Sale edit - top' => 'Редактирование распродажи - вверху', + 'Sale edit page - javascript last call block' => 'Страница редактирования распродажи - блок последнего вызова javascript', + 'Salerno' => 'Салерно', + 'Sales - JavaScript' => 'Распродажи - JavaScript', + 'Sales - at the bottom' => 'Распродажи - внизу', + 'Sales - at the top' => 'Распродажи - вверху', + 'Sales - table header' => 'Распродажи - заголовок таблицы', + 'Sales - table row' => 'Распродажи - строка таблицы', + 'Sales management' => 'Управление распродажами', + 'Salta' => 'Сальта', + 'San Juan' => 'Сан-Хуан', + 'San Luis' => 'Сан-Луис', + 'San Luis Potosí' => 'Сан-Луис-Потоси', + 'San Marino' => 'Сан-Марино', + 'Santa Cruz' => 'Санта Круз', + 'Santa Fe' => 'Санта-Фе', + 'Santiago del Estero' => 'Сантьяго', + 'Sao Tome and Principe' => 'Сан-Томе и Принсипи', + 'Saskatchewan' => 'Саскачеван', + 'Sassari' => 'Сассари', + 'Saudi Arabia' => 'Саудовская Аравия', + 'Savona' => 'Савона', + 'Search' => 'Поиск', + 'Search - JavaScript' => 'Поиск - JavaScript', + 'Search - at the top' => 'Поиск - вверху', + 'Search - bottom' => 'Поиск - внизу', + 'Search block' => 'Блок поиска', + 'Search page - CSS stylesheet' => 'Страница поиска - CSS стили', + 'Search page - after javascript include' => 'Страница поиска - после включения javascript', + 'Search page - after javascript initialisation' => 'Страница поиска - после инициализации javascript', + 'Secret key for form CSRF token' => 'Секретный ключ для CSRF токена', + 'Send a confirmation email to newsletter subscribers (1 = yes, 0 = no)' => 'Посылать email подтверждения подписчикам рассылки', + 'Senegal' => 'Сенегал', + 'Sent' => 'Выслан', + 'Seychelles' => 'Сейшелы', + 'Shekel' => 'Шекель', + 'Shiga' => 'Сига', + 'Shimane' => 'Симанэ', + 'Shipping configuration' => 'Конфигурация доставки', + 'Shipping configuration - Edit' => 'Конфигурация доставки - Edit', + 'Shipping configuration - Edit JavaScript' => 'Конфигурация доставки - Редактирование JavaScript', + 'Shipping configuration - JavaScript' => 'Конфигурация доставки - JavaScript', + 'Shipping configuration - at the top' => 'Конфигурация доставки - вверху', + 'Shipping configuration - bottom' => 'Конфигурация доставки - внизу', + 'Shipping configuration - country delete form' => 'Конфигурация доставки - форма удаления страны', + 'Shipping configuration - create form' => 'Конфигурация доставки - форма создания', + 'Shipping configuration - delete form' => 'Конфигурация доставки - форма удаления', + 'Shipping configuration - table header' => 'Конфигурация доставки - заголовок таблицы', + 'Shipping configuration - table row' => 'Конфигурация доставки - строка таблицы', + 'Shipping configuration edit - bottom' => 'Редактирование конфигурации доставки - внизу', + 'Shipping configuration edit - top' => 'Редактирование конфигурации доставки - вверху', + 'Shipping zones edit - bottom' => 'Редактирование зон доставки - внизу', + 'Shipping zones edit - top' => 'Редактирование зон доставки - вверху', + 'Shizuoka' => 'Сидзуока', + 'Show error message instead of a white page on a server error' => 'Показывать страницу ошибок вместо белой страницы при ошибке сервера', + 'Siena' => 'Сиена', + 'Sierra Leone' => 'Сьерра-Леоне', + 'Sinaloa' => 'Синалоа', + 'Singapore' => 'Сингапур', + 'Siracusa' => 'Сиракузы', + 'Sitemap - at the bottom' => 'Карта сайта - внизу', + 'Slovakia' => 'Словакия', + 'Slovenia' => 'Словения', + 'Smarty template engine integration' => 'Интеграция шаблонизатора Smarty', + 'Social Networks block' => 'Блок социалок', + 'Solomon Islands' => 'Соломоновы острова', + 'Somalia' => 'Сомали', + 'Sondrio' => 'Сондрио', + 'Sonora' => 'Сонора', + 'South Africa' => 'Южная Африка', + 'South Carolina' => 'Южная Каролина', + 'South Dakota' => 'Северная Дакота', + 'South Kalimantan' => 'Южный Калимантан', + 'South Korea' => 'Южная Корея', + 'South Sulawesi' => 'Южный Сулавеси', + 'South Sumatra' => 'Южная Суматра', + 'Southeast Sulawesi' => 'Юго-Восточный Сулавеси', + 'Spain' => 'Испания', + 'Sri Lanka' => 'Шри-Ланка', + 'St Pierre et Miquelon' => 'Сен-Пьер и Микелон', + 'Store Information - JavaScript' => 'Информация о магазине - JavaScript', + 'Store information configuration' => 'Конфигурация информации магазина', + 'Sudan' => 'Судан', + 'Suriname' => 'Суринам', + 'Swaziland' => 'Свазиленд', + 'Sweden' => 'Швеция', + 'Switzerland' => 'Швейцария', + 'Syria' => 'Сирия', + 'System - logs JavaScript' => 'Система - логи JavaScript', + 'Tab SEO - bottom' => 'Вкладка SEO - внизу', + 'Tab SEO - top' => 'Вкладка SEO - вверху', + 'Tab SEO - update form' => 'Вкладка SEO - форма обновления', + 'Tab document - bottom' => 'Вкладка документов - внизу', + 'Tab document - top' => 'Вкладка документов - вверху', + 'Tab image - bottom' => 'Вкладка изображений - внизу', + 'Tab image - top' => 'Вкладка изображений - вверху', + 'Tabasco' => 'Табаско', + 'Tajikistan' => 'Таджикистан', + 'Tamaulipas' => 'Тамаулипас', + 'Tanzania' => 'Танзания', + 'Taranto' => 'Таранто', + 'Tax - Edit JavaScript' => 'Налог - Редактирование JavaScript', + 'Tax - create form' => 'Налог - форма создания', + 'Tax - delete form' => 'Налог - форма удаления', + 'Tax edit - bottom' => 'Редактирование налога - внизу', + 'Tax edit - top' => 'Редактирование налога - вверху', + 'Tax rule edit - bottom' => 'Редактирование налогового правила - внизу', + 'Tax rule edit - top' => 'Редактирование налогового правила - вверху', + 'Tax rules configuration' => 'Конфигурация налоговых правил', + 'Taxes - update form' => 'Налоги - форма обновления', + 'Taxes rules - JavaScript' => 'Налоговые правила - JavaScript', + 'Taxes rules - at the top' => 'Налоговые правила - вверху', + 'Taxes rules - bottom' => 'Налоговые правила - внизу', + 'Template - Edit JavaScript' => 'Шаблон - Редактирование JavaScript', + 'Template - attributes table header' => 'Шаблон - заголовок таблицы атрибутов', + 'Template - attributes table row' => 'Шаблон - строка таблицы атрибутов', + 'Template - create form' => 'Шаблон - форма создания', + 'Template - delete form' => 'Шаблон - форма удаления', + 'Template - features table row' => 'Шаблон - строка таблицы характеристик', + 'Template - features-table-header' => 'Шаблон - заголовок таблицы характеристик', + 'Template edit - bottom' => 'Редактирование шаблона - внизу', + 'Template edit - top' => 'Редактирование шаблона - вверху', + 'Templates - JavaScript' => 'Шаблоны - JavaScript', + 'Templates - at the top' => 'Шаблоны - вверху', + 'Templates - bottom' => 'Шаблоны - внизу', + 'Templates - table header' => 'Шаблоны - заголовок таблицы', + 'Templates - table row' => 'Шаблоны - строка таблицы', + 'Tennessee' => 'Теннесси', + 'Teramo' => 'Терамо', + 'Terni' => 'Терни', + 'Texas' => 'Техас', + 'Thailand' => 'Таиланд', + 'The ID of the \'Terms & Conditions\' content.' => 'ID контента \'Условия использования\'', + 'The ID of the folder containing your information pages : terms, imprint, ...' => 'ID папки содержащей информационные страницы : условия, выходные сведения, ...', + 'The Vatican' => 'Ватикан', + 'The default quality (in %) of the generated images' => 'Качество (в %) генерируемых изображений', + 'The minimum length required for an administrator password' => 'Минимальная длина пароля для админа', + 'The path (relative to the default back-office template) to the image used when no flag image can be found for a country' => 'Путь (относительно стандартного шаблона админки) к изображению для флага страны, если изображение флага не найдено', + 'The path to the document cache directory in the web space' => 'Путь до кеша документов относительно web директории', + 'The path to the image cache directory in the web space' => 'Путь до кеша изобрежений относительно web директории', + 'Tierra del Fuego' => 'Огненной Земли', + 'TinyMCE WYSIWYG editor' => 'Редактор TinyMCE', + 'Tlaxcala' => 'Тлашкала', + 'Tochigi' => 'Тотиги', + 'Togo' => 'Того', + 'Tokushima' => 'Токусима', + 'Tokyo' => 'Токио', + 'Tonga' => 'Тонга', + 'Tools - JavaScript' => 'Инструменты - JavaScript', + 'Tools - at the bottom of column 1' => 'Инструменты - внизу колонки 1', + 'Tools - at the top' => 'Инструменты - вверху', + 'Tools - at the top of the column' => 'Инструменты - вверху колонки', + 'Tools - bottom' => 'Инструменты - внизу', + 'Tools panel' => 'Панель инструментов', + 'Torino' => 'Торино', + 'Tottori' => 'Тоттори', + 'Toyama' => 'Тояма', + 'Translations' => 'Переводы', + 'Translations - JavaScript' => 'Переводы - JavaScript', + 'Trapani' => 'Трапани', + 'Trento' => 'Тренто', + 'Treviso' => 'Тревизо', + 'Trieste' => 'Триест', + 'Trinidad and Tobago' => 'Тринидад и Тобаго', + 'Tucumán' => 'Тукуман', + 'Tunisia' => 'Тунис', + 'Tunisian Dinar' => 'Тунисский динар', + 'Turkey' => 'Турция', + 'Turkmenistan' => 'Туркменистан', + 'Tuvalu' => 'Тувалу', + 'UK Pound' => 'Английский фунт', + 'US Virgin Islands' => 'Виргинские острова США', + 'USA' => 'США', + 'Udine' => 'Удине', + 'Uganda' => 'Уганда', + 'Ukraine' => 'Украина', + 'United Arab Emirates' => 'Объединенные Арабские Эмираты', + 'United Arab Emirates dirham' => 'ОАЭ дирхам', + 'United Kingdom' => 'Великобритания', + 'United States Dollar' => 'Доллар США', + 'Update customer account - CSS stylesheet' => 'Обновление аккаунта клиента - CSS стили', + 'Update customer account - after javascript include' => 'Обновление аккаунта клиента - после включения javascript', + 'Update customer account - after javascript initialisation' => 'Обновление аккаунта клиента - после инициализации javascript', + 'Update customer account - at the bottom' => 'Обновление аккаунта клиента - внизу', + 'Update customer account - at the bottom of the form' => 'Обновление аккаунта клиента - внизу формы', + 'Update customer account - at the top' => 'Обновление аккаунта клиента - вверху', + 'Update customer account - at the top of the form' => 'Обновление аккаунта клиента - вверху формы', + 'Uruguay' => 'Уругвай', + 'Use a persistent cookie to keep track of customer cart' => 'Использовать cookie для отслеживания корзины клиента', + 'Utah' => 'Юта', + 'Uzbekistan' => 'Узбекистан', + 'Vanuatu' => 'Вануату', + 'Varese' => 'Варезе', + 'Variable - Edit JavaScript' => 'Переменная - Редактирование JavaScript', + 'Variable - create form' => 'Переменная - форма создания', + 'Variable - delete form' => 'Переменная - форма удаления', + 'Variable edit - bottom' => 'Редактирование переменной - внизу', + 'Variable edit - top' => 'Редактирование переменной - вверху', + 'Variables - JavaScript' => 'Переменные - JavaScript', + 'Variables - at the top' => 'Переменные - вверху', + 'Variables - bottom' => 'Переменные - внизу', + 'Variables - table header' => 'Переменные - заголовок таблицы', + 'Variables - table row' => 'Переменные - строка таблицы', + 'Venezia' => 'Венеция', + 'Venezuela' => 'Венесуэла', + 'Veracruz' => 'Веракрус', + 'Verbano-Cusio-Ossola' => 'Вербано-Кузьо-Оссола', + 'Vercelli' => 'Верчелли', + 'Vermont' => 'Вермонт', + 'Verona' => 'Верона', + 'Vibo Valentia' => 'Вибо Валентия', + 'Vicenza' => 'Виченца', + 'Vietnam' => 'Вьетнам', + 'View administration logs' => 'Просмотр административных логов', + 'Virginia' => 'Вирджиния', + 'Virtual Product Controller' => 'Поддержка виртуальных товаров', + 'Viterbo' => 'Витербо', + 'Wakayama' => 'Вакаяма', + 'Wallis-et-Futuna' => 'Уоллис и Футуна', + 'Washington' => 'Вашингтон', + 'West Java' => 'Западная Ява', + 'West Kalimantan' => 'Западный Калимантан', + 'West Nusa Tenggara' => 'Западные Малые Зондские острова', + 'West Sulawesi' => 'Западный Сулавеси', + 'West Sumatra' => 'Западная Суматра', + 'West Virginia' => 'Западная Виргиния', + 'Western Samoa' => 'Западное Самоа', + 'Where the WYSIWYG editor is required' => 'Где требуется редактор WYSIWYG', + 'Whitespace trim level of the generated HTML code (0 = none, 1 = medium, 2 = maximum)' => 'Обрезание пробелов в генерируемом HTML (0 - нет, 1 - среднее, 2 - максимальное). Сильно влияет на производительность !', + 'Wisconsin' => 'Висконсин', + 'Wyoming' => 'Вайоминг', + 'Yamagata' => 'Ямагата', + 'Yamaguchi' => 'Ямагути', + 'Yamanashi' => 'Яманаси', + 'Yemen' => 'Йемен', + 'Yen' => 'Иена', + 'Yogyakarta' => 'Джокьякарта', + 'You can now login at' => 'Сейчас вы можете войти', + 'You have lost your password
    \r\nPlease, change this password after your first connection' => 'Вы потеряли свой пароль
    \r\nПожалуйста смените его после первого подключения', + 'You have lost your password
    \r\nYour new password is' => 'Вы потеряли свой пароль
    \r\nВаш новый пароль', + 'Your account information on {config key="store_name"} has been changed.' => 'Данные аккаунта в {config key="store_name"} были изменены.', + 'Your new passord is : {$password}' => 'Ваш новый пароль : {$password}', + 'Your new password' => 'Ваш новый пароль', + 'Your new password for {config key="store_name"}' => 'Ваш новый пароль для {config key="store_name"}', + 'Your order {$order_ref} at {config key="store_name"}' => 'Ваш заказ {$order_ref} в {config key="store_name"}', + 'Your subscription to %store newsletter' => 'Подписка на рассылку новостей %store', + 'Yuan' => 'Юань', + 'Yucatán' => 'Юкатан', + 'Yukon' => 'Юкон', + 'Zacatecas' => 'Сакатекас', + 'Zaire' => 'Заир', + 'Zambia' => 'Замбия', + 'Zimbabwe' => 'Зимбабве', + 'Zone - delete form' => 'Зона - форма удаления', + 'Złoty' => 'Польский злотый', + '[Firewall/Bruteforce] Number of allowed attemps' => '[Firewall/Bruteforce] Количество возможных попыток перебора', + '[Firewall/Bruteforce] Time to wait between X attempts' => '[Firewall/Bruteforce] Время между Х попыток перебора', + '[Firewall] Activate the firewall' => '[Firewall] Активация firewall', + '[Firewall] Number of allowed attemps' => '[Firewall] Количествно возможных попыток', + '[Firewall] Time to wait between X attempts' => '[Firewall] Время между Х попытками', + 'changing password email for' => 'смена пароля для email', + 'customer account - CSS stylesheet' => 'Аккаунт клиента - CSS стили', + 'customer account - after javascript include' => 'Аккаунт клиента - после включения javascript', + 'customer account - after javascript initialisation' => 'Аккаунт клиента - после инициализации javascript', + 'customer account - at the bottom' => 'Аккаунт клиента - внизу', + 'customer account - at the top' => 'Аккаунт клиента - вверху', + 'export of newsletter subscribers' => 'экспорт подписчиков рассылки', + 'language selection page - CSS stylesheet' => 'Страница выбора языка - CSS стили', + 'language selection page - after javascript include' => 'Страница выбора языка - после включения javascript', + 'language selection page - after javascript initialisation' => 'Страница выбора языка - после инициализации javascript', + 'language selection page - at the bottom' => 'Страница выбора языка - внизу', + 'language selection page - at the top' => 'Страница выбора языка - вверху', + 'state - Edit JavaScript' => 'Штат - Редактирование JavaScript', + 'state - creation form' => 'Штат - форма создания', + 'state - delete form' => 'Штат - форма удаления', + 'state-edit - at the top' => 'Редактирование штата - вверху', + 'state-edit - bottom' => 'Редактирование штата - внизу', + 'states - JavaScript' => 'Штаты - JavaScript', + 'states - at the top' => 'Штаты - вверху', + 'states - bottom' => 'Штаты - внизу', + 'states - table header' => 'Штаты - заголовок таблицы', + 'states - table row' => 'Штаты - строка таблицы', + 'tax rule - Edit JavaScript' => 'Налоговое правило - Редактирование JavaScript', + 'tax rule - create form' => 'Налоговое правило - форма создания', + 'tax rule - delete form' => 'Налоговое правило - форма удаления', + 'tinymce wysiwyg editor' => 'WYSIWYG редактор TinyMCE', + 'Đồng' => 'Донг', + 'Гривна' => 'Гривна', +); diff --git a/setup/I18n/sk_SK.php b/setup/I18n/sk_SK.php new file mode 100644 index 00000000..ab6f15e7 --- /dev/null +++ b/setup/I18n/sk_SK.php @@ -0,0 +1,527 @@ + '"Pamätaj si ma" cookie čas vypršania, v sekundách, pre adminov', + '"Remember me" cookie expiration time, in seconds, for customer users' => '"Pamätaj si ma" cookie čas vypršania, v sekundách, pre zákazníkov', + '"Remember me" cookie name for administration users' => '"Pamätaj si ma" cookie meno pre adminov', + '"Remember me" cookie name for customer users' => '"Pamätaj si ma" cookie meno pre zákazníckych užívateľov', + '72h delivery' => 'dodanie do 72hodín', + 'A {config key="store_name"} account has been created for you' => '{kľúč config = "store_name"} účet bol vytvorený pre vás', + 'API Configuration' => 'API konfigurácia', + 'Aceh' => 'Aceh', + 'Address' => 'Adresa', + 'Address creation - CSS stylesheet' => 'Vytvorenie adresy - CSS štýlov', + 'Address update - at the bottom' => 'Aktualizovať adresu - naspodku', + 'Address update - at the bottom of the form' => 'Aktualizovať adresu - v spodnej časti formulára', + 'Address update - at the top' => 'Adresa update - hore', + 'Administatros list' => 'Zoznam administrátorov', + 'Administrator - create form' => 'Administrátor - vytvorenie formulára', + 'Administrator - delete form' => 'Správca - Vymazať formulár', + 'Administrator list' => 'Zoznam administrátorov', + 'Administrators - JavaScript' => 'Správcovia - JavaScript', + 'Administrators - at the top' => 'Správcovia - hore', + 'Administrators - bottom' => 'Správcovia - spodné', + 'Administrators - header' => 'Správcovia - hlavička', + 'Advanced Configuration' => 'Pokročilá konfigurácia', + 'Advanced Configuration - Javascript' => 'Pokročilá konfigurácia - Javascript', + 'Advanced configuration' => 'Pokročilá konfigurácia', + 'Afghanistan' => 'Afganistan', + 'Agrigento' => 'Agrigento', + 'Aguascalientes' => 'Aguascalientes', + 'Aichi' => 'Aiči', + 'Akita' => 'Akita', + 'Alabama' => 'Alabama', + 'Alaska' => 'Aljaška', + 'Albania' => 'Albánsko', + 'Alberta' => 'Alberta', + 'Alessandria' => 'Alessandria', + 'Algeria' => 'Alžírsko', + 'All Products - CSS stylesheet' => 'Všetky produkty - CSS štýlov', + 'All Products - at the bottom' => 'Všetky produkty - na spodu', + 'All Products - at the top' => 'Všetky produkty - hore', + 'Allow an administrator to recreate a lost password (1 = yes, 0 = no)' => 'Povoliť správcom obnoviť stratené heslo (1 = áno, 0 = nie)', + 'Allow customers to change their email. 1 for yes, 0 for no' => 'Umožniť zákazníkom zmeniť ich e-mail. 1 áno, 0 pre nie', + 'An image carousel on your home page' => 'Kolotočový obrázok na vašu hlavnú stránku', + 'Ancona' => 'Ancona', + 'Andorra' => 'Andorra', + 'Aomori' => 'Aomori', + 'Aosta' => 'Aosta', + 'Arezzo' => 'Arezzo', + 'Arizona' => 'Arizona', + 'Arkansas' => 'Arkansas', + 'Ascoli Piceno' => 'Ascoli Piceno', + 'Asti' => 'Asti', + 'Attribut - create form' => 'Attribut - vytvoriť formulár', + 'Attribut - delete form' => 'Attribut - Vymazať formulár', + 'Attribut - id delete form' => 'Attribut - id Vymazať formulár', + 'Attribute value - create form' => 'Atribút hodnoty - vytvorenie formulára', + 'Australia' => 'Austrália', + 'Austria' => 'Rakúsko', + 'Avellino' => 'Avellino', + 'Azerbaijan' => 'Azerbajdžan', + 'Back-office export management' => 'Riadenie vývozov back-office', + 'Back-office home page' => 'Back-office – Domovská stránka', + 'Bahamas' => 'Bahamy', + 'Bahrain' => 'Bahrajn', + 'Baht' => 'Baht', + 'Baja California' => 'Baja California', + 'Baja California Sur' => 'Baja California Sur', + 'Bali' => 'Bali', + 'Bangka' => 'Bangka', + 'Bangladesh' => 'Bangladéš', + 'Banten' => 'Banten', + 'Barbados' => 'Barbados', + 'Bari' => 'Bari', + 'Barletta-Andria-Trani' => 'Barletta-Andria-Trani', + 'Belarus' => 'Bielorusko', + 'Belarusian ruble' => 'Bieloruský rubeľ', + 'Belgium' => 'Belgicko', + 'Belize' => 'Belize', + 'Belluno' => 'Belluno', + 'Benevento' => 'Benevento', + 'Bengkulu' => 'Bengkulu', + 'Benin' => 'Benin', + 'Bergamo' => 'Bergamo', + 'Bhutan' => 'Bhután', + 'Biella' => 'Biella', + 'Bielorussia' => 'Bielorusko', + 'Bolivia' => 'Bolívia', + 'Boliviano' => 'Bolívijské Boliviano', + 'Bologna' => 'Bologna', + 'Bolzano' => 'Bolzano', + 'Bolívar fuerte' => 'Bolivar fuerte', + 'Bosnia and Herzegovina' => 'Bosna a Hercegovina', + 'Botswana' => 'Botswana', + 'Brand - Edit JavaScript' => 'Značka - upraviť JavaScript', + 'Brand - JavaScript' => 'Značka - JavaScript', + 'Brand - content' => 'Značka - obsah', + 'Brand - create form' => 'Značka - vytvoriť formulár', + 'Brand - delete form' => 'Značka - Vymazať formulár', + 'Brand edit - right column bottom' => 'Upraviť značky - dolnej časti pravého stĺpca', + 'Brand edit - right column top' => 'Upraviť značky - pravý stĺpec hore', + 'Brescia' => 'Brescia', + 'Brindisi' => 'Brindisi', + 'British Columbia' => 'Britská Kolumbia', + 'Brunei' => 'Brunej', + 'Buenos Aires' => 'Buenos Aires', + 'Bulgaria' => 'Bulharsko', + 'Burkina' => 'Burkina', + 'Burma' => 'Barma', + 'Burundi' => 'Burundi', + 'Cagliari' => 'Cagliari', + 'California' => 'Kalifornia', + 'Caltanissetta' => 'Caltanissetta', + 'Cambodia' => 'Kambodža', + 'Cameroon' => 'Kamerun', + 'Campeche' => 'Campeche', + 'Campobasso' => 'Campobasso', + 'Canada' => 'Kanada', + 'Canceled' => 'Zrušené', + 'Cape Verde' => 'Kapverdy', + 'Carbonia-Iglesias' => 'Athina-Iglesias', + 'Cart - CSS stylesheet' => 'Nákupný košík - CSS štýlov', + 'Cart - after javascript include' => 'Nákupný košík - po javascript obsahovať', + 'Cart - at the bottom' => 'Nákupný košík - na dne', + 'Cart - at the top' => 'Nákupný košík - hore', + 'Cart - javascript initialization' => 'Nákupný košík - javascript Inicializácia', + 'Cart block' => 'Blok košík', + 'Caserta' => 'Caserta', + 'Catamarca' => 'Catamarca', + 'Catania' => 'Catania', + 'Catanzaro' => 'Catanzaro', + 'Categories - JavaScript' => 'Kategórie - JavaScript', + 'Categories - at the bottom of the catalog' => 'Kategórie - v spodnej časti katalógu', + 'Categories - at the top' => 'Kategórie - v hornej časti', + 'Categories - bottom' => 'Kategórie - spodné', + 'Categories - caption' => 'Kategórie - Popis', + 'Categories - header' => 'Kategórie - hlavička', + 'Categories - row' => 'Kategórie - riadok', + 'Category' => 'Kategória', + 'Category - Edit JavaScript' => 'Kategória - upraviť JavaScript', + 'Category - content' => 'Kategória - obsah', + 'Category - create form' => 'Kategória - vytvoriť formulár', + 'Category - delete form' => 'Kategória - Vymazať formulár', + 'Category edit - right column bottom' => 'Upraviť kategóriu - dolnej časti pravého stĺpca', + 'Category edit - right column top' => 'Upraviť kategóriu - pravý stĺpec hore', + 'Central African Republic' => 'Stredoafrická republika', + 'Central Java' => 'Centrálna Java', + 'Central Kalimantan' => 'Centrálnej Kalimantan', + 'Central Sulawesi' => 'Centrálnej Sulawesi', + 'Chaco' => 'Chaco', + 'Chad' => 'Čad', + 'Change password - CSS stylesheet' => 'Zmena hesla - CSS štýlov', + 'Change password - at the bottom' => 'Zmena hesla - na dne', + 'Change password - at the top' => 'Zmena hesla - hore', + 'Chiapas' => 'Chiapas', + 'Chiba' => 'Chiba', + 'Chieti' => 'Chieti', + 'Chihuahua' => 'Čivava', + 'Chile' => 'Čile', + 'China' => 'Čína', + 'Chubut' => 'Chubut', + 'Ciudad de Buenos Aires' => 'Ciudad de Buenos Aires', + 'Coahuila' => 'Coahuila', + 'Colima' => 'Colima', + 'Colombia' => 'Kolumbia', + 'Colorado' => 'Colorado', + 'Colón' => 'Colón', + 'Configuration' => 'Konfigurácia', + 'Configuration - JavaScript' => 'Konfigurácia - JavaScript', + 'Configuration - at the bottom of the catalog' => 'Konfigurácia - v spodnej časti katalógu', + 'Configuration - at the bottom of the shipping area' => 'Konfigurácia - v dolnej časti oblasti pre odoslanie', + 'Configuration - at the bottom of the system area' => 'Konfigurácia - v spodnej časti oblasti systému', + 'Configuration / Module' => 'Konfigurácia / modul', + 'Configuration / Profile' => 'Nastavenia / profil', + 'Configuration / Shipping-zone' => 'Konfigurácia / zóna doručenia', + 'Configuration / System Log' => 'Konfigurácia / systém Log', + 'Configuration / Tax' => 'Konfigurácia / daň', + 'Congo' => 'Kongo', + 'Connecticut' => 'Connecticut', + 'Content' => 'Obsah', + 'Content - create form' => 'Obsah - vytvoriť formulár', + 'Content - delete form' => 'Obsah - Vymazať formulár', + 'Content edit - right column bottom' => 'Upraviť obsah - dolnej časti pravého stĺpca', + 'Content edit - right column top' => 'Upraviť obsah - pravý stĺpec hore', + 'Corrientes' => 'Corrientes', + 'Cosenza' => 'Cosenza', + 'Country - create form' => 'Krajina - vytvoriť formulár', + 'Country - delete form' => 'Krajina - Vymazať formulár', + 'Coupon' => 'Kupón', + 'Cremona' => 'Cremona', + 'Croatia' => 'Chorvátsko', + 'Croatian Kuna' => 'Chorvátska Kuna', + 'Crotone' => 'Crotone', + 'Cuba' => 'Kuba', + 'Cuneo' => 'Cuneo', + 'Currencies - at the top' => 'Meny - hore', + 'Currencies - bottom' => 'Meny - spodné', + 'Currencies - table header' => 'Meny - hlavička tabuľky', + 'Currencies - table row' => 'Meny - riadok tabuľky', + 'Currency - create form' => 'Mena - vytvoriť formulár', + 'Currency - delete form' => 'Mena - Vymazať formulár', + 'Customer' => 'Zákazník', + 'Customer - Edit' => 'Zákazník - upraviť', + 'Customer - address create form' => 'Zákazník – formulár vytvorenia adresy', + 'Customer - address delete form' => 'Zákazník – formulár odstránenia adresy', + 'Customer - address update form' => 'Zákazník – formulár aktualizovania adresy', + 'Customer - at the top' => 'Zákazník - hore', + 'Customer - bottom' => 'Zákazník - dole', + 'Customer - create form' => 'Zákazník - vytvoriť formulár', + 'Customer - delete form' => 'Zákazník - Vymazať formulár', + 'Cyprus' => 'Cyprus', + 'Czech Republic' => 'Česká republika', + 'Czech koruna' => 'Česká koruna', + 'Córdoba' => 'Córdoba', + 'Danish krone' => 'Dánska koruna', + 'Delaware' => 'Delaware', + 'Delivery - CSS' => 'Dodanie - CSS', + 'Dinar' => 'Dinár', + 'Displays the default blocks on the homepage of the administration' => 'Zobrazuje predvolené bloky na domovskú stránku správy', + 'District of Columbia' => 'District of Columbia', + 'Distrito Federal' => 'Distrito Federal', + 'Dollar' => 'Dolár', + 'Dollar (CAD)' => 'Dolár (CAD)', + 'Durango' => 'Durango', + 'East Nusa Tenggara' => 'East Nusa Tenggara', + 'East kalimantan' => 'East kalimantan', + 'Ehime' => 'Ehime', + 'Email html - layout - CSS' => 'Html email - usporiadanie - CSS', + 'Email html - layout - footer' => 'E-mail - štruktúra - html päta', + 'Email html - order confirmation - after address' => 'E-mail Html - potvrdenie objednávky - po adrese', + 'Email html - order confirmation - after products' => 'E-mail html - potvrdenieobjednávky - po produktoch', + 'Email html - order confirmation - before address' => 'E-mail html - potvrdenie objednávky - pred adresu', + 'Email html - order confirmation - before products' => 'E-mail html- potvrdenie objednávky - pred produkty', + 'Email html - order confirmation - delivery address' => 'E-mail Html - potvrdenie objednávky - dodacia adresa', + 'Email html - order confirmation - footer' => 'E-mail html - potvrdenie objednávky - päta', + 'Email html - order confirmation - order product' => 'E-mail html - potvrdenie objednávky -objednaný produkt', + 'Email html - order notification - after address' => 'E-mail Html - potvrdenie objednávky - po adrese', + 'Email html - order notification - after products' => 'E-mail html - potvrdenie objednávky - po produktoch', + 'Email html - order notification - before address' => 'E-mail html - potvrdenie objednávky - pred adresu', + 'Email html - order notification - before products' => 'E-mail html - potvrdenie objednávky - po produktoch', + 'Email html - order notification - delivery address' => 'E-mail Html - potvrdenie objednávky - dodacia adresa', + 'Email html - order notification - order product' => 'E-mail html - potvrdenie objednávky -objednaný produkt', + 'Email txt - order confirmation - after address' => 'E-mail txt - potvrdenie objednávky - po adrese', + 'Email txt - order confirmation - after products' => 'E-mail txt - potvrdenie objednávky - po produktov', + 'Email txt - order confirmation - before address' => 'E-mail txt - potvrdenie objednávky - pred adresu', + 'Email txt - order confirmation - before products' => 'E-mail txt - potvrdenie objednávky - pred produktami', + 'Email txt - order confirmation - delivery address' => 'E-mail txt - potvrdenie objednávky - dodacia adresa', + 'Email txt - order confirmation - order product' => 'E-mail txt - potvrdenie objednávky - objednaný produkt', + 'Email txt - order notification - after address' => 'E-mail txt - potvrdenie objednávky - po adrese', + 'Email txt - order notification - after products' => 'E-mail txt - potvrdenie objednávky - po produktoch', + 'Email txt - order notification - before address' => 'E-mail txt - potvrdenie objednávky - pred adresu', + 'Email txt - order notification - before products' => 'E-mail txt - potvrdenie objednávky - pred produktami', + 'Email txt - order notification - delivery address' => 'E-mail txt - potvrdenie objednávky - dodacia adresa', + 'Email txt - order notification - order product' => 'E-mail txt - potvrdenie objednávky -objednaný produkt', + 'Enna' => 'Enna', + 'Entre Ríos' => 'Entre Ríos', + 'Estado de México' => 'Estado de México', + 'Feature - Value create form' => 'Funkcia - hodnota vytvoriť formulár', + 'Feature - create form' => 'Charakteristika - vytvoriť formulár', + 'Feature - delete form' => 'Charakteristika - Vymazať formulár', + 'Fermo' => 'Fermo', + 'Ferrara' => 'Ferrara', + 'Firenze' => 'Firenze', + 'Florida' => 'Florida', + 'Foggia' => 'Foggia', + 'Folder' => 'Priečinok', + 'Folder - create form' => 'Zložky - vytvorenie formulára', + 'Folder - delete form' => 'Zložku - Vymazať formulár', + 'Folder edit - right column bottom' => 'Upraviť zložky - dolná časť pravého stĺpca', + 'Folder edit - right column top' => 'Upraviť zložky - pravý stĺpec hore', + 'Forint' => 'Maďarský forint', + 'Forlì-Cesena' => 'Forlì-Cesena', + 'Formosa' => 'Formosa', + 'Franc' => 'Frank', + 'French Southern Territories' => 'Francúzske južné územia', + 'Frosinone' => 'Frosinone', + 'Fukui' => 'Fukui', + 'Fukuoka' => 'Fukuoka', + 'Fukushima' => 'Fukushima', + 'Genova' => 'Genova', + 'Gifu' => 'Gifu', + 'Gorizia' => 'Gorizia', + 'Grosseto' => 'Grosseto', + 'Guanajuato' => 'Guanajuato', + 'Guaraní' => 'Guaraní', + 'Guerrero' => 'Guerrero', + 'Gunma' => 'Gunma', + 'Hawaii' => 'Havaj', + 'Invoice - After delivery module' => 'Faktúra - po dodanie modul', + 'Invoice - After payment module' => 'Faktúra - po platobný modul', + 'Invoice - CSS' => 'Faktúra - CSS', + 'Invoice - additional product information' => 'Faktúra - ďalšie informácie o produkte', + 'Invoice - after addresse area' => 'Faktúra - po Address oblasť', + 'Invoice - after product listing' => 'Faktúra - po výpis produktov', + 'Invoice - after the information area' => 'Faktúra - po informácie', + 'Invoice - after the order summary' => 'Faktúra - po súhrne objednávky', + 'Invoice - delivery address' => 'Faktúra - adresa doručenia', + 'Invoice - imprint' => 'Faktúra -pečiatka', + 'Invoice - in the header' => 'Faktúra - v hlavičke', + 'Invoice choice - at the bottom' => 'Výber faktúry - naspodku', + 'Invoice choice - at the top' => 'Výber faktúry - hore', + 'Jakarta' => 'Jakarta', + 'Kuwait' => 'Kuvajt', + 'Kyrgyzstan' => 'Kirgizsko', + 'Language - create form' => 'Jazyk - vytvoriť formulár', + 'Languages - JavaScript' => 'Jazyky - JavaScript', + 'Languages - at the top' => 'Jazyky - hore', + 'Languages - bottom' => 'Jazyky - spodné', + 'Languages - delete form' => 'Jazyky - Vymazať formulár', + 'Laos' => 'Laos', + 'Lecco' => 'Lecco', + 'Lei' => 'Lei', + 'Lev' => 'Lev', + 'Lira' => 'Líra', + 'Livorno' => 'Livorno', + 'Lodi' => 'Lodi', + 'Louisiana' => 'Louisiana', + 'Lucca' => 'Lucca', + 'Macerata' => 'Macerata', + 'Mail sent after a subscription to newsletter' => 'E-mail zaslaný po prihlásení sa na odber noviniek', + 'Mail sent to an administrator who requested a new password' => 'E-mail, ktorý je odoslaný adminovi po žiadosti o nové heslo', + 'Maine' => 'Maine', + 'Maluku' => 'Maluku', + 'Manat' => 'Turkménsky manat', + 'Manitoba' => 'Manitoba', + 'Mantova' => 'Mantova', + 'Maryland' => 'Maryland', + 'Massa' => 'Massa', + 'Massachusetts' => 'Massachusetts', + 'Matera' => 'Matera', + 'Medio Campidano' => 'Medio Campidano', + 'Mendoza' => 'Mendoza', + 'Messina' => 'Messina', + 'Michigan' => 'Michigan', + 'Michoacán' => 'Michoacán', + 'Mie' => 'Mie', + 'Milano' => 'Milano', + 'Mini cart' => 'Mini nákupný košík', + 'Minnesota' => 'Minnesota', + 'Misiones' => 'Misiones', + 'Mississippi' => 'Mississippi', + 'Missouri' => 'Missouri', + 'Miyagi' => 'Miyagi', + 'Miyazaki' => 'Miyazaki', + 'Modena' => 'Modena', + 'New York' => 'New York', + 'Nunavut' => 'Nunavut', + 'Nuoro' => 'Nuoro', + 'Oaxaca' => 'Oaxaca', + 'Ogliastra' => 'Ogliastra', + 'Ohio' => 'Ohio', + 'Oita' => 'Oita', + 'Okayama' => 'Okayama', + 'Okinawa' => 'Okinawa', + 'Oklahoma' => 'Oklahoma', + 'Olbia-Tempio' => 'Olbia Tempio', + 'Ontario' => 'Ontario', + 'Order' => 'Objednávka', + 'Order - cart bottom' => 'Objednávka - dno košíka', + 'Order - cart top' => 'Objednávka - košík top', + 'Order details - after delivery address' => 'Podrobnosti objednávky - po adresu doručenia', + 'Order details - after invoice address' => 'Podrobnosti objednávky - po fakturačnej adrese', + 'Oregon' => 'Oregon', + 'Oristano' => 'Oristano', + 'Osaka' => 'Osaka', + 'Padova' => 'Padova', + 'Palermo' => 'Palermo', + 'Papua' => 'Papua', + 'Parma' => 'Parma', + 'Pavia' => 'Pavia', + 'Pennsylvania' => 'Pennsylvania', + 'Perugia' => 'Perugia', + 'Pesaro-Urbino' => 'Pesaro-Urbino', + 'Potenza' => 'Potenza', + 'Pound' => 'Libra', + 'Prato' => 'Prato', + 'Prince Edward Island' => 'Ostrov princa Eduarda', + 'Product - create form' => 'Produkt - vytvoriť formulár', + 'Product - delete form' => 'Produkt - Vymazať formulár', + 'Puebla' => 'Puebla', + 'Puerto Rico' => 'Portoriko', + 'Quebec' => 'Quebec', + 'Querétaro' => 'Querétaro', + 'Quetzal' => 'Guatemalský quetzal', + 'Quintana Roo' => 'Quintana Roo', + 'Ragusa' => 'Ragusa', + 'Ravenna' => 'Ravenna', + 'Real' => 'Reálne', + 'Reggio Calabria' => 'Reggio Calabria', + 'Reggio Emilia' => 'Reggio Emilia', + 'Rhode Island' => 'Rhode Island', + 'Riau' => 'Riau', + 'Rieti' => 'Rieti', + 'Rimini' => 'Rimini', + 'Ringgit' => 'Ringgit', + 'Riyal' => 'Riál', + 'Roma' => 'Rím', + 'Rovigo' => 'Rovigo', + 'Ruble' => 'Rubeľ', + 'Rupee' => 'Rupia', + 'Rupiah' => 'Rupia', + 'Río Negro' => 'Río Negro', + 'Saga' => 'Sága', + 'Saint Barthélemy' => 'Svätý Bartolomej', + 'Saint Martin (French part)' => 'Svätý Martin (Francúzska časť)', + 'Saitama' => 'Saitama', + 'Sale - CSS stylesheet' => 'Predaj - CSS štýlov', + 'Sale - at the top' => 'Výpredaj - hore', + 'Sale - at the top of the main area' => 'Výpredaj - v hornej časti hlavnej oblasti', + 'Salerno' => 'Salerno', + 'Salta' => 'Salta', + 'San Juan' => 'San Juan', + 'San Luis' => 'San Luis', + 'San Luis Potosí' => 'San Luis Potosí', + 'Santa Cruz' => 'Santa Cruz', + 'Santa Fe' => 'Santa Fe', + 'Santiago del Estero' => 'Santiago del Estero', + 'Saskatchewan' => 'Saskatchewan', + 'Sassari' => 'Sassari', + 'Savona' => 'Savona', + 'Search' => 'Hľadať', + 'Send a confirmation email to newsletter subscribers (1 = yes, 0 = no)' => 'Poslať potvrdzovací e-mail pre záujemcov o newsletter (1 = áno, 0 = nie)', + 'Shekel' => 'Shekel', + 'Shiga' => 'Šiga', + 'Shimane' => 'Šimane', + 'Shizuoka' => 'Shizuoka', + 'Siena' => 'Siena', + 'Sinaloa' => 'Sinaloa', + 'Siracusa' => 'Siracusa', + 'Sondrio' => 'Sondrio', + 'Sonora' => 'Sonora', + 'South Carolina' => 'Južná Karolína', + 'South Dakota' => 'Južná Dakota', + 'South Kalimantan' => 'Južná Kalimantan', + 'South Sulawesi' => 'Južná Sulawesi', + 'South Sumatra' => 'Južná Sumatra', + 'Southeast Sulawesi' => 'Juhovýchodný Sulawesi', + 'Tabasco' => 'Tabasco', + 'Tamaulipas' => 'Tamaulipas', + 'Taranto' => 'Taranto', + 'Tennessee' => 'Tennessee', + 'Teramo' => 'Teramo', + 'Terni' => 'Terni', + 'Texas' => 'Texas', + 'The minimum length required for an administrator password' => 'Minimálna požadovaná dĺžka hesla administrátora', + 'Tierra del Fuego' => 'Tierra del Fuego', + 'Tlaxcala' => 'Tlaxcala', + 'Tochigi' => 'Točigi', + 'Tokushima' => 'Tokushima', + 'Tokyo' => 'Tokio', + 'Torino' => 'Torino', + 'Tottori' => 'Tottori', + 'Toyama' => 'Toyama', + 'Translations' => 'Preklady', + 'Trapani' => 'Trapani', + 'Trento' => 'Trento', + 'Treviso' => 'Treviso', + 'Trieste' => 'Trieste', + 'Tucumán' => 'Tucumán', + 'Tunisian Dinar' => 'Tuniský dinár', + 'US Virgin Islands' => 'AMERICKÉ Panenské ostrovy', + 'USA' => 'USA', + 'Udine' => 'Udine', + 'Uganda' => 'Uganda', + 'Ukraine' => 'Ukrajina', + 'United Arab Emirates' => 'Spojené Arabské Emiráty', + 'United Arab Emirates dirham' => 'Spojené Arabské Emiráty dirham', + 'Utah' => 'Utah', + 'Uzbekistan' => 'Uzbekistan', + 'Vanuatu' => 'Vanuatu', + 'Varese' => 'Varese', + 'Venezia' => 'Venezia', + 'Veracruz' => 'Veracruz', + 'Verbano-Cusio-Ossola' => 'Verbano-Cusio-Ossola', + 'Vercelli' => 'Vercelli', + 'Vermont' => 'Vermont', + 'Verona' => 'Verona', + 'Vibo Valentia' => 'Vibo Valentia', + 'Vicenza' => 'Vicenza', + 'Virginia' => 'Virginia', + 'Viterbo' => 'Viterbo', + 'Wakayama' => 'Wakayama', + 'Washington' => 'Washington', + 'West Java' => 'Západná Jáva', + 'West Kalimantan' => 'West Kalimantan', + 'West Nusa Tenggara' => 'West Nusa Tenggara', + 'West Sulawesi' => 'Západ Sulawesi', + 'West Sumatra' => 'Západná Sumatra', + 'West Virginia' => 'Západná Virgínia', + 'Western Samoa' => 'Západná Samoa', + 'Wisconsin' => 'Wisconsin', + 'Wyoming' => 'Wyoming', + 'Yamagata' => 'Yamagata', + 'Yamaguchi' => 'Yamaguchi', + 'Yamanashi' => 'Jamanaši', + 'Yemen' => 'Jemen', + 'Yen' => 'Yen', + 'Yogyakarta' => 'Yogyakarta', + 'You can now login at' => 'Teraz sa môžete prihlásiť na', + 'You have lost your password
    \r\nPlease, change this password after your first connection' => 'Stratili ste heslo < br / > \r\n Prosím, zmeňte si heslo po prvom prihlásení', + 'You have lost your password
    \r\nYour new password is' => 'Stratili ste heslo
    \r\n Vaše nové heslo je', + 'Your new passord is : {$password}' => 'Nové heslo je: {$password}', + 'Your subscription to %store newsletter' => 'Odoberanie noviniek %store', + 'Yuan' => 'Yuan', + 'Yucatán' => 'Yucatán', + 'Yukon' => 'Yukon', + 'Zacatecas' => 'Zacatecas', + 'Zimbabwe' => 'Zimbabwe', + 'Złoty' => 'Złoty', + 'changing password email for' => 'zmena hesla e-mailom na', + 'customer account - CSS stylesheet' => 'zákaznícky účet - CSS štýlov', + 'customer account - after javascript initialisation' => 'zákaznícky účet - po javascript inicializáciu', + 'customer account - at the top' => 'zákaznícky účet - hore', + 'language selection page - at the top' => 'jazyk výber stránky - hore', + 'state - Edit JavaScript' => 'štát - úprava JavaScript', + 'state - creation form' => 'štát - vytvorenie formulára', + 'state - delete form' => 'štát - Vymazať formulár', + 'state-edit - at the top' => 'štát-edit - hore', + 'state-edit - bottom' => 'štát-edit - spodné', + 'states - JavaScript' => 'štáty - JavaScript', + 'states - at the top' => 'štáty - hore', + 'states - bottom' => 'štáty - spodné', + 'states - table header' => 'štáty - hlavička tabuľky', + 'states - table row' => 'štáty - riadok tabuľky', + 'Đồng' => 'Đồng', + 'Гривна' => 'ГРИВНА', +]; diff --git a/setup/I18n/tr_TR.php b/setup/I18n/tr_TR.php new file mode 100644 index 00000000..99b51a4f --- /dev/null +++ b/setup/I18n/tr_TR.php @@ -0,0 +1,1020 @@ + '"Beni hatırla" tanımlama bilgisi zaman aşımı süresi, saniye cinsinden için yönetim kullanıcı', + '"Remember me" cookie expiration time, in seconds, for customer users' => '"Beni hatırla" tanımlama bilgisi zaman aşımı süresi, saniye cinsinden müşteri kullanıcılar için', + '"Remember me" cookie name for administration users' => '"Beni hatırla" tanımlama bilgisi adı yönetim kullanıcılar için', + '"Remember me" cookie name for customer users' => '"Beni hatırla" tanımlama bilgisi adı Müşteri kullanıcılar için', + '72h delivery' => '72h teslim', + 'A {config key="store_name"} account has been created for you' => 'A {config anahtarı "store_name" =} hesabı sizin için oluşturuldu', + 'API Configuration' => 'API yapılandırma', + 'Address' => 'Adres', + 'Address creation - CSS stylesheet' => 'Adres oluşturma - CSS stil sayfası', + 'Address creation - after javascript include' => 'JavaScript içerme sonra oluşturma - adres', + 'Address creation - after javascript initialisation' => 'Adres oluşturma - javascript başlatma sonra', + 'Address creation - at the bottom' => 'Adres oluşturma - alt', + 'Address creation - at the bottom of the form' => 'Adres oluşturma - alt formu', + 'Address creation - at the top' => 'Adres oluşturma - üst', + 'Address creation - at the top of the form' => 'Adres oluşturma - alt formu', + 'Address update - CSS stylesheet' => 'Güncelleştirme - CSS stil sayfası', + 'Address update - after javascript include' => 'JavaScript içerme sonra güncelleme - adres', + 'Address update - after javascript initialisation' => 'Adres güncelleme - javascript başlatma sonra', + 'Address update - at the bottom' => 'Güncelleştirme - alt', + 'Address update - at the bottom of the form' => 'Güncelleştirme - alt formu', + 'Address update - at the top' => 'Güncelleştirme - üst', + 'Address update - at the top of the form' => 'Güncelleştirme - alt formu', + 'Admin layout - After the main content' => 'Admin düzeni - sonra ana içerik', + 'Administatros list' => 'Administatros listesi', + 'Administration profiles management' => 'Yönetim profilleri yönetim', + 'Administrator - create form' => 'Yönetici - oluşturma formu', + 'Administrator - delete form' => 'Yönetici - silme formu', + 'Administrator - update form' => 'Yönetici - güncelleştirme formu', + 'Administrator list' => 'Yönetici listesi', + 'Administrators - JavaScript' => 'Yöneticiler - JavaScript', + 'Administrators - at the top' => 'Yöneticiler - üst', + 'Administrators - bottom' => 'Yöneticiler - alt', + 'Administrators - header' => 'Yöneticiler - başlık', + 'Administrators - row' => 'Yöneticiler - kürek', + 'Advanced Configuration' => 'Gelişmiş yapılandırma', + 'Advanced Configuration - Javascript' => 'Gelişmiş yapılandırma - JavaScript', + 'Advanced configuration' => 'Gelişmiş yapılandırma', + 'Afghanistan' => 'Afganistan', + 'Albania' => 'Albania', + 'Algeria' => 'Algeria', + 'All Products - CSS stylesheet' => 'Tüm ürünler - CSS stil sayfası', + 'All Products - after javascript include' => 'Tüm ürünler - sonra JavaScript içerme', + 'All Products - after javascript initialisation' => 'Tüm ürünler - javascript başlatma sonra', + 'All Products - at the bottom' => 'Tüm ürünler - alt', + 'All Products - at the top' => 'Tüm ürünler - üst', + 'Allow customers to change their email. 1 for yes, 0 for no' => 'Müşterilerin kendi e-posta değiştirmek izin. Evet için 1, hayır için 0', + 'Allow negative product stock (1) or not (0)' => 'Negatif ürün stok (1) izin (0)', + 'Allow negative product stock (1) or not (0, default)' => 'Negatif ürün stok (1) izin (0, varsayılan)', + 'Allow slash ended uri' => 'Eğik çizgi sona erdi URI izin', + 'An image carousel on your home page' => 'Giriş sayfanızdaki bir görüntü slayt', + 'Andorra' => 'Andorra', + 'Angola' => 'Angola', + 'Antigua and Barbuda' => 'Antigua and Barbuda', + 'Api page - at bottom' => 'API sayfa - alt', + 'Api page - at top' => 'API sayfa - üst', + 'Api page - in deletion form' => 'API sayfa - silme formu', + 'Argentina' => 'Arjantin', + 'Armenia' => 'Ermenistan', + 'Ask the customers to confirm their email, 1 for yes, 0 for no' => 'Onların 1 e-posta, "Evet," için onaylamak için müşteriler sormak 0 hayır için', + 'Attribut - Edit JavaScript' => 'Attribut - düzen JavaScript', + 'Attribut - add to all form' => 'Attribut - tüm forma ekleme', + 'Attribut - create form' => 'Attribut - oluşturma formu', + 'Attribut - delete form' => 'Attribut - silme formu', + 'Attribut - id delete form' => 'Attribut - kimliği silme formu', + 'Attribut - remove to all form' => 'Attribut - tüm form için Kaldır', + 'Attribute edit - bottom' => 'Öznitelik Düzenle - alt', + 'Attribute edit - top' => 'Öznitelik Düzenle - üst', + 'Attribute value - create form' => 'Öznitelik değeri - oluşturma formu', + 'Attributes - JavaScript' => 'Öznitelikleri - JavaScript', + 'Attributes - at the top' => 'Öznitelikleri - üst', + 'Attributes - bottom' => 'Öznitelikleri - alt', + 'Attributes - table header' => 'Öznitelikleri - Tablo üstbilgisi', + 'Attributes - table row' => 'Öznitelikleri - tablo satırı', + 'Attributes value - table header' => 'Öznitelikleri değeri - Tablo üstbilgisi', + 'Attributes value - table row' => 'Öznitelikleri değeri - tablo satırı', + 'Australia' => 'Avusturalya', + 'Austria' => 'Avusturya', + 'Azerbaijan' => 'Azerbaycan', + 'Back-office export management' => 'Arka ofis ihracat yönetimi', + 'Back-office home page' => 'Arka ofis ana sayfa', + 'Back-office search function' => 'Arka ofis arama fonksiyonu', + 'Bahamas' => 'Bahamalar', + 'Bahrain' => 'Bahrain', + 'Bangladesh' => 'Bangladeş', + 'Barbados' => 'Barbados', + 'Base URL of the shop (e.g. http://www.yourshopdomain.com)' => 'Shop (örneğin http://www.yourshopdomain.com) temel URL', + 'Belarus' => 'Beyaz Rusya (Belarus)', + 'Belgium' => 'Belgium', + 'Belize' => 'Belize', + 'Benin' => 'Benin', + 'Bhutan' => 'Butan', + 'Bielorussia' => 'Bielorussia', + 'Bolivia' => 'Bolivia', + 'Bosnia and Herzegovina' => 'Bosnia and Herzegovina', + 'Botswana' => 'Botsvana', + 'Brand - Edit JavaScript' => 'Marka - düzenleme JavaScript', + 'Brand - JavaScript' => 'Marka - JavaScript', + 'Brand - Tab' => 'Marka - sekmesi', + 'Brand - content' => 'Marka - içerik', + 'Brand - create form' => 'Marka - oluşturma formu', + 'Brand - delete form' => 'Marka - silme formu', + 'Brand edit - bottom' => 'Düzenle marka - alt', + 'Brand edit - top' => 'Marka Düzenle - üst', + 'Brand edit page - in the form' => 'Marka Düzenle sayfa - formu', + 'Brands - at the top' => 'Marka - üst', + 'Brands - bottom' => 'Marka - alt', + 'Brands - table header' => 'Marka - Tablo üstbilgisi', + 'Brands - table row' => 'Marka - tablo satırı', + 'Brands management' => 'Marka yönetimi', + 'Brands page - CSS stylesheet' => 'Markalar sayfa - CSS stil sayfası', + 'Brands page - after javascript include' => 'Markalar - JavaScript içerme sonra sayfa', + 'Brands page - after the main content area' => 'Markalar sayfa - ana içerik alanına sonra', + 'Brands page - at the bottom' => 'Markalar sayfa - alt', + 'Brands page - at the bottom of the main area' => 'Markalar sayfa - ana alanının altındaki', + 'Brands page - at the bottom of the sidebar' => 'Markalar sayfa - alt kenar çubuğu', + 'Brands page - at the top' => 'Markalar sayfa - üst', + 'Brands page - at the top of the main area' => 'Markalar sayfa - ana alanının altındaki', + 'Brands page - at the top of the sidebar' => 'Markalar sayfa - alt kenar çubuğu', + 'Brands page - before the main content area' => '-Ana içerik alanına önce markalar sayfa', + 'Brands page - javascript initialization' => 'Markalar sayfa - javascript başlatma', + 'Brands page - the body of the sidebar' => 'Markalar sayfa - kenar gövdesi', + 'Brazil' => 'Brazilya', + 'Brunei' => 'Brunei', + 'Bulgaria' => 'Bulgaria', + 'Burkina' => 'Burkina', + 'Burma' => 'Burma', + 'Burundi' => 'Burundi', + 'Cambodia' => 'Cambodia', + 'Cameroon' => 'Kamerun', + 'Canceled' => 'İptal', + 'Cape Verde' => 'Yeşil Burun Adaları', + 'Cart - CSS stylesheet' => 'Sepeti - CSS stil sayfası', + 'Cart - after javascript include' => 'Cart - sonra JavaScript içerme', + 'Cart - at the bottom' => 'Sepeti - alt', + 'Cart - at the top' => 'Sepeti - üst', + 'Cart - javascript initialization' => 'Sepeti - javascript başlatma', + 'Cart block' => 'Alışveriş Sepeti', + 'Categories - JavaScript' => 'Kategoriler - JavaScript', + 'Categories - at the bottom of the catalog' => 'Kategoriler - katalog alt', + 'Categories - at the top' => 'Kategoriler - üst', + 'Categories - bottom' => 'Alt Kategoriler-', + 'Categories - caption' => 'Kategoriler - resim yazısı', + 'Categories - header' => 'Kategoriler - başlık', + 'Categories - row' => 'Kategoriler - kürek', + 'Category' => 'kategori', + 'Category - Edit JavaScript' => 'Kategori - düzenleme JavaScript', + 'Category - Tab' => 'Kategori - sekmesi', + 'Category - content' => 'Kategori - içerik', + 'Category - contents table header' => 'Kategori - içindekiler tablosu başlığı', + 'Category - contents table row' => 'Kategori - içeriği tablo satırı', + 'Category - create form' => 'Kategori - oluşturma formu', + 'Category - delete form' => 'Kategori - silme formu', + 'Category configuration' => 'Kategori yapılandırma', + 'Category edit - bottom' => 'Kategori Düzenle - alt', + 'Category edit - top' => 'Kategori Düzenle - üst', + 'Category page - CSS stylesheet' => 'Kategori sayfası - CSS stil sayfası', + 'Category page - after javascript include' => 'Kategori sayfası - sonra JavaScript içerme', + 'Category page - after javascript initialisation' => 'Kategori sayfası - javascript başlatma sonra', + 'Category page - after the main content area' => 'Kategori sayfası - ana içerik alanına sonra', + 'Category page - at the bottom' => 'Kategori sayfası - alt', + 'Category page - at the bottom of the main area' => 'Kategori sayfası - ana alanının altındaki', + 'Category page - at the bottom of the sidebar' => 'Kategori sayfası - alt kenar çubuğu', + 'Category page - at the top' => 'Kategori sayfası - üst', + 'Category page - at the top of the main area' => 'Kategori sayfası - ana alanının altındaki', + 'Category page - at the top of the sidebar' => 'Kategori sayfası - alt kenar çubuğu', + 'Category page - before the main content area' => 'Kategori sayfası - ana içerik alanına önce', + 'Category page - the body of the sidebar' => 'Kategori sayfası - kenar gövdesi', + 'Central African Republic' => 'Orta Afrika Cumhuriyeti', + 'Chad' => 'Chad', + 'Change password - CSS stylesheet' => 'Şifre Değiştir - CSS stil sayfası', + 'Change password - after javascript include' => 'JavaScript içerme sonra Parola Değiştir-', + 'Change password - after javascript initialisation' => 'Şifre Değiştir - javascript başlatma sonra', + 'Change password - at the bottom' => 'Şifre Değiştir - alt', + 'Change password - at the top' => 'Şifre Değiştir - üst', + 'Check available product stock (1) or ignore it (0) when displaying and changing ordered quantity' => 'Mevcut ürün stok (1) kontrol veya sipariş edilen miktar görüntüleme ve değiştirmeye ne zaman (0) aldırmamak', + 'Check if a virtual product delivery module is enabled if at least one product is virtual' => 'En az bir ürün sanal ise bir sanal ürün teslim modülü etkin olup olmadığını denetleyin', + 'Chile' => 'Chile', + 'China' => 'Çin Halk Cumhuriyeti', + 'Client edit - bottom' => 'İstemci Düzenle - alt', + 'Client edit - top' => 'İstemci Düzenle - üst', + 'Colombia' => 'Colombia', + 'Comoros' => 'Komor Adaları', + 'Compile templates assets automatically upon asset source change (1 = yes, 0 = no)' => 'Şablonları kıymetler kıymet kaynak değişikliği üzerine otomatik olarak derlemek (1 = yes, 0 = Hayır)', + 'Configuration' => 'Ayarlar', + 'Configuration - JavaScript' => 'Yapılandırma - JavaScript', + 'Configuration - at the bottom of the catalog' => 'Yapılandırma - katalog alt', + 'Configuration - at the bottom of the shipping area' => 'Yapılandırma - sevkiyat alanına alt', + 'Configuration - at the bottom of the system area' => 'Yapılandırma - başta-in belgili tanımlık sistem alan', + 'Configuration - at the top' => 'Yapılandırma - üst', + 'Configuration - at the top of the catalog area' => 'Yapılandırma - katalog alanının üstündeki', + 'Configuration - at the top of the shipping area' => 'Yapılandırma - sevkiyat alanına alt', + 'Configuration - at the top of the system area' => 'Yapılandırma - başta-in belgili tanımlık sistem alan', + 'Configuration - bottom' => 'Yapılandırma - alt', + 'Configuration / Administrator' => 'Yapılandırma / Yönetici', + 'Configuration / Area' => 'Yapılandırma / alan', + 'Configuration / Attribute' => 'Yapılandırma / özniteliği', + 'Configuration / Cache' => 'Yapılandırma / Cache', + 'Configuration / Country' => 'Yapılandırma ülke', + 'Configuration / Currency' => 'Yapılandırma / para birimi', + 'Configuration / Feature' => 'Yapılandırma / özellik', + 'Configuration / Language' => 'Yapılandırma / dil', + 'Configuration / Mailing-system' => 'Yapılandırma / posta sistemi', + 'Configuration / Message' => 'Yapılandırma / mesaj', + 'Configuration / Module' => 'Yapılandırma / modülü', + 'Configuration / Profile' => 'Yapılandırma / profil', + 'Configuration / Shipping-zone' => 'Yapılandırma / nakliye bölgesi', + 'Configuration / System Log' => 'Yapılandırma / sistem günlüğü', + 'Configuration / Tax' => 'Yapılandırma /Kdv', + 'Configuration / Template' => 'Yapılandırma / şablon', + 'Configuration variables' => 'Yapılandırma değişkenleri', + 'Congo' => 'Congo', + 'Contact block' => 'İletişim bilgileri', + 'Contact page - CSS stylesheet' => 'İletişim sayfası - CSS stil sayfası', + 'Contact page - after javascript include' => 'JavaScript içerme sonra sayfa - iletişim', + 'Contact page - after javascript initialisation' => '-Sonra javascript başlatma iletişim sayfası', + 'Contact page - at the bottom' => '-Alt iletişim sayfası', + 'Contact page - at the bottom of the form' => '-Formun altındaki iletişim sayfası', + 'Contact page - at the top' => '-Üst iletişim sayfası', + 'Contact page - at the top of the form' => '-Formun altındaki iletişim sayfası', + 'Contact page - if successful response' => 'İletişim sayfası - başarılı olursa yanıt', + 'Content' => 'Içerik', + 'Content - Edit JavaScript' => 'İçerik - düzenleme JavaScript', + 'Content - Tab' => 'İçerik - sekmesi', + 'Content - content' => 'İçerik - içerik', + 'Content - create form' => 'İçerik - oluşturma formu', + 'Content - delete form' => 'İçerik - silme formu', + 'Content edit - bottom' => 'Düzenleme içerik - alt', + 'Content edit - top' => 'İçerik düzenleme - üst', + 'Content page - CSS stylesheet' => 'İletişim sayfası - CSS stil sayfası', + 'Content page - after javascript include' => 'JavaScript içerme sonra sayfa - iletişim', + 'Content page - after javascript initialisation' => '-Sonra javascript başlatma iletişim sayfası', + 'Content page - after the main content area' => 'İçerik sayfası - ana içerik alanına sonra', + 'Content page - at the bottom' => '-Alt iletişim sayfası', + 'Content page - at the bottom of the main area' => 'İçerik sayfası - ana alanının altındaki', + 'Content page - at the bottom of the sidebar' => 'İçerik sayfası - alt kenar çubuğu', + 'Content page - at the top' => '-Üst iletişim sayfası', + 'Content page - at the top of the main area' => 'İçerik sayfası - ana alanının altındaki', + 'Content page - at the top of the sidebar' => 'İçerik sayfası - alt kenar çubuğu', + 'Content page - before the main content area' => '-Daha önce ana içerik alanına içerik sayfası', + 'Content page - the body of the sidebar' => 'İçerik sayfası - kenar gövdesi', + 'Contents - caption' => 'İçindekiler - resim yazısı', + 'Contents - header' => 'İçindekiler - başlık', + 'Contents - row' => 'İçindekiler - kürek', + 'Cook Islands' => 'Cook Adaları', + 'Costa Rica' => 'Kosta Rica', + 'Countries - JavaScript' => 'Ülkeler - JavaScript', + 'Countries - at the top' => 'Ülkeler - üst', + 'Countries - bottom' => 'Ülkeler - alt', + 'Countries - table header' => 'Ülkeler - Tablo üstbilgisi', + 'Countries - table row' => 'Ülkeler - tablo satırı', + 'Country - Edit JavaScript' => 'Ülke - düzenleme JavaScript', + 'Country - create form' => 'Ülke - oluşturma formu', + 'Country - delete form' => 'Ülke - silme formu', + 'Country edit - bottom' => 'Ülke düzenleme - alt', + 'Country edit - top' => 'Ülke Düzenle - üst', + 'Coupon' => 'Kupon', + 'Coupon - at the top' => 'Kupon - üst', + 'Coupon - bottom' => 'Kupon - alt', + 'Coupon - create JavaScript' => 'Kupon - JavaScript oluşturmak', + 'Coupon - list JavaScript' => 'Kupon - JavaScript listesi', + 'Coupon - list caption' => 'Kupon - liste resim yazısı', + 'Coupon - table header' => 'Kupon - Tablo üstbilgisi', + 'Coupon - table row' => 'Kupon - tablo satırı', + 'Coupon - update JavaScript' => 'Kupon - JavaScript güncelleştirmek', + 'Coupon page - in deletion form' => 'Kupon sayfasında - silme formu', + 'Croatia' => 'Hırvatistan', + 'Cuba' => 'Cuba', + 'Curency selection page - CSS stylesheet' => 'Curency seçim sayfası - CSS stil sayfası', + 'Curency selection page - after javascript include' => 'Curency seçimi sayfa JavaScript içerme-', + 'Curency selection page - after javascript initialisation' => 'Curency seçim sayfası - javascript başlatma sonra', + 'Curency selection page - at the bottom' => 'Curency seçim sayfası - alt', + 'Curency selection page - at the top' => 'Curency seçim sayfası - üst', + 'Currencies - JavaScript' => 'Para birimleri - JavaScript', + 'Currencies - at the top' => 'Para birimleri - üst', + 'Currencies - bottom' => 'Para birimleri - alt', + 'Currencies - table header' => 'Para birimleri - Tablo üstbilgisi', + 'Currencies - table row' => 'Para birimleri - tablo satırı', + 'Currency - Edit JavaScript' => 'Döviz Alım - düzenleme JavaScript', + 'Currency - create form' => 'Döviz Alım - oluşturma formu', + 'Currency - delete form' => 'Döviz Alım - silme formu', + 'Currency block' => 'Kur kutusu', + 'Currency edit - bottom' => 'Para birimi Düzenle - alt', + 'Currency edit - top' => 'Para birimi Düzenle - üst', + 'Customer' => 'Customer', + 'Customer - Edit' => 'Müşteri - Düzenle', + 'Customer - Edit JavaScript' => 'Müşteri - düzenleme JavaScript', + 'Customer - address create form' => 'Müşteri - adres oluşturma formu', + 'Customer - address delete form' => 'Müşteri - adresi silme formu', + 'Customer - address update form' => 'Müşteri - adres güncelleştirme formu', + 'Customer - at the top' => 'Müşteri - üst', + 'Customer - bottom' => 'Müşteri - alt', + 'Customer - create form' => 'Müşteri - oluşturma formu', + 'Customer - delete form' => 'Müşteri - silme formu', + 'Customer - order table header' => 'Müşteri - sipariş tablo başlığı', + 'Customer - order table row' => 'Müşteri - sipariş tablo satırı', + 'Customer account - additional information' => 'Müşteri hesabı - ek bilgi', + 'Customer account block' => 'Müşteri hesap blok', + 'Customer title' => 'Müşteri adı', + 'Customers - JavaScript' => 'Müşteriler - JavaScript', + 'Customers - caption' => 'Müşteriler - resim yazısı', + 'Customers - header' => 'Müşteriler - başlık', + 'Customers - row' => 'Müşteriler - kürek', + 'Cyprus' => 'Kıbrıs Cumhuriyeti', + 'Czech Republic' => 'Çek Cumhuriyeti', + 'Dashboard - at the top' => 'Pano - üst', + 'Dashboard - bottom' => 'Pano - alt', + 'Dashboard - middle' => 'Pano - orta', + 'Data import / export' => 'Veri ithalat / ihracat', + 'Default available stock when check-available-stock is set to 0.' => 'Kullanılabilir stok onay mevcut stok 0 olarak ayarlandığında varsayılan.', + 'Default lang without translation' => 'Varsayılan lang çeviri olmadan', + 'Delivery - After delivery module' => 'Dağıtım - sonra teslim modülü', + 'Delivery - CSS' => 'Dağıtım - CSS', + 'Delivery - additional product information' => 'Dağıtım - daha fazla ürün bilgisi', + 'Delivery - after addresse area' => 'Dağıtım - adres alanı sonra', + 'Delivery - after the information area' => 'Dağıtım - bilgi alan sonra', + 'Delivery - after the order summary' => 'Dağıtım - Özet sipariş sonrası', + 'Delivery - at the bottom of information area' => 'Dağıtım - bilgi alanının altındaki', + 'Delivery - at the bottom of the footer' => 'Dağıtım - altbilgi alt', + 'Delivery - at the top of the footer' => 'Dağıtım - altbilgi üstündeki', + 'Delivery - delivery address' => 'Dağıtım - teslimat adresi', + 'Delivery - imprint' => 'Dağıtım - Künye', + 'Delivery - in the header' => 'Dağıtım - başlıktaki', + 'Delivery choice - CSS stylesheet' => 'Teslimat seçim - CSS stil sayfası', + 'Delivery choice - after javascript include' => 'JavaScript içerme sonra teslim seçim-', + 'Delivery choice - after javascript initialisation' => 'Teslimat seçim - javascript başlatma sonra', + 'Delivery choice - at the bottom' => 'Teslimat seçim - alt', + 'Delivery choice - at the bottom of the form' => 'Teslimat seçim - alt formu', + 'Delivery choice - at the top' => 'Teslimat seçim - üst', + 'Delivery choice - at the top of the form' => 'Teslimat seçim - alt formu', + 'Delivery choice - extra area' => 'Teslimat seçim - ilave alan', + 'Delivery choice - javascript' => 'Teslimat seçim - javascript', + 'Delivery zone - Edit JavaScript' => 'Teslimat bölgesi - JavaScript Düzenle', + 'Delivery zone - JavaScript' => 'Teslimat bölgesi - JavaScript', + 'Delivery zone - at the top' => 'Teslimat bölgesi - üst', + 'Delivery zone - bottom' => 'Teslimat bölgesi - alt', + 'Delivery zone - table header' => 'Teslimat bölgesi - Tablo üstbilgisi', + 'Delivery zone - table row' => 'Teslimat bölgesi - tablo satırı', + 'Denmark' => 'Danimarka', + 'Display and process prices with (0) or without (1) taxes.' => 'Görüntü ve işlem fiyatları (0) ile veya olmadan (1) vergi.', + 'Djibouti' => 'Cibuti', + 'Document - Edit JavaScript' => 'Belge - düzenleme JavaScript', + 'Document edit - bottom' => 'Belge düzenleme - alt', + 'Document edit - top' => 'Belge düzenleme - üst', + 'Dominica' => 'Dominika', + 'Dominican Republic' => 'Dominican Republic', + 'Ecuador' => 'Ecuador', + 'Egypt' => 'Mısır', + 'El Salvador' => 'El Salvador', + 'Enable (1) or disable (0) URL rewriting' => 'Etkinleştir (1) veya devre dışı bırak (0) URL yeniden yazma', + 'Equatorial Guinea' => 'Ekvator Ginesi', + 'Eritrea' => 'Eritrea', + 'Estonia' => 'Estonya', + 'Ethiopia' => 'Ethiopia', + 'Euro' => 'Euro', + 'Export - JavaScript' => 'İhracat - JavaScript', + 'Export - table header' => 'İthalat - Tablo üstbilgisi', + 'Export - table row' => 'İhracat - tablo satırı', + 'Export modal or page - bottom' => 'Kalıcı ihracat veya sayfa - alt', + 'Export modal or page - top' => 'İhracat kalıcı veya sayfa - üst', + 'Exports - JavaScript' => 'İhracat - JavaScript', + 'Exports - at the bottom of a category' => 'İhracat - kategorisi altındaki', + 'Exports - at the bottom of column 1' => 'İhracat - 1 sütunun altındaki', + 'Exports - at the top' => 'İhracat - üst', + 'Feature - Edit JavaScript' => 'Özellik - düzenleme JavaScript', + 'Feature - Value create form' => 'Özellik - değer oluşturma formu', + 'Feature - add to all form' => 'Özellik - tüm forma ekleme', + 'Feature - create form' => 'Özellik - oluşturma formu', + 'Feature - delete form' => 'Özellik - silme formu', + 'Feature - remove to all form' => 'Özellik - tüm forma çıkarmak', + 'Feature edit - bottom' => 'Düzenleme özelliği - alt', + 'Feature edit - top' => 'Özelliği Düzenle - üst', + 'Features - JavaScript' => 'Özellikler - JavaScript', + 'Features - at the top' => 'Özellikler - üst', + 'Features - bottom' => 'Özellikler - alt', + 'Features - table header' => 'Özellikler - Tablo üstbilgisi', + 'Features - table row' => 'Özellikler - tablo satırı', + 'Features value - table header' => 'Özellik değeri - Tablo üstbilgisi', + 'Features value - table row' => 'Özellik değeri - tablo satırı', + 'Fiji' => 'Fiji', + 'File name of the 404 (not found) view in the current template (with extension, e.g. 404.html)' => 'Dosya adı (uzantısı, örneğin 404.html) geçerli şablonunda 404 (bulunamadı) görünümü', + 'Filename of the error page' => 'Hata sayfasının dosya adı', + 'Finland' => 'Finland', + 'Folder' => 'Klasör', + 'Folder - Edit JavaScript' => 'Klasör - düzenleme JavaScript', + 'Folder - JavaScript' => 'Klasör - JavaScript', + 'Folder - Tab' => 'Klasör - sekmesi', + 'Folder - at the top' => 'Klasör - üst', + 'Folder - bottom' => 'Klasör - alt', + 'Folder - caption' => 'Klasör - resim yazısı', + 'Folder - content' => 'Klasör - içerik', + 'Folder - create form' => 'Klasör - oluşturma formu', + 'Folder - delete form' => 'Klasör - silme formu', + 'Folder - header' => 'Klasör - başlık', + 'Folder - row' => 'Klasör - satır', + 'Folder edit - bottom' => 'Klasörünü düzenlemek - alt', + 'Folder edit - top' => 'Klasörü Düzenle - üst', + 'Folder page - CSS stylesheet' => 'Klasör sayfası - CSS stil sayfası', + 'Folder page - after javascript include' => 'Klasör sayfa JavaScript içerme-', + 'Folder page - after javascript initialisation' => 'Klasör sayfası - javascript başlatma sonra', + 'Folder page - after the main content area' => 'Klasör sayfası - ana içerik alanına sonra', + 'Folder page - at the bottom' => '-Alt klasörü sayfası', + 'Folder page - at the bottom of the main area' => '-Ana alanının alt klasörü sayfası', + 'Folder page - at the top' => 'Klasör sayfası - üst', + 'Folder page - at the top of the main area' => '-Ana alanının alt klasörü sayfası', + 'Folder page - before the main content area' => '-Ana içerik alanına önce klasörü sayfası', + 'France metropolitan' => 'Fransa metropolitan', + 'French 10% VAT' => 'Fransız % 10 KDV', + 'French 20% VAT' => 'Fransız % 10 KDV', + 'Front office integration' => 'Açık ofis entegrasyonu', + 'Gabon' => 'Gabon', + 'Gambia' => 'Gambiya', + 'Georgia' => 'Gürcistan', + 'Germany' => 'Germany', + 'Ghana' => 'Gana', + 'Google Analytics block' => 'Google Analytics blok', + 'Greece' => 'Greece', + 'Grenada' => 'Grenada', + 'Guadeloupe' => 'Guadeloupe', + 'Guatemala' => 'Guatemala', + 'Guinea' => 'Guinea', + 'Guinea-Bissau' => 'Gine Bissau', + 'Guyana' => 'Guyana', + 'Guyane Française' => 'Guyane Française', + 'HTML layout - CSS stylesheet' => 'HTML Düzeni - CSS stil sayfası', + 'HTML layout - after javascript include' => 'HTML Düzeni - sonra JavaScript içerme', + 'HTML layout - after the main content area' => 'HTML Düzeni - ana içerik alanına sonra', + 'HTML layout - after the opening of the body tag' => 'HTML Düzeni - ten etiket açtıktan sonra', + 'HTML layout - after the opening of the head tag' => 'HTML Düzeni - ten etiket açtıktan sonra', + 'HTML layout - at the bottom of the header' => 'HTML Düzeni - başlığının altındaki', + 'HTML layout - at the top of the footer' => 'HTML Düzeni - altbilgi üstündeki', + 'HTML layout - at the top of the header' => 'HTML Düzeni - başlığının altındaki', + 'HTML layout - before the end body tag' => 'HTML Düzeni - son beden etiketinden önce', + 'HTML layout - before the end of the head tag' => 'HTML Düzeni - baş etiketi sonundan önce', + 'HTML layout - before the main content area' => 'HTML Düzeni - ana içerik alanına önce', + 'HTML layout - bottom of the footer' => 'HTML Düzeni - altbilginin alt kısmı', + 'HTML layout - footer body' => 'HTML Düzeni - altbilgi vücut', + 'HTML layout - javascript initialization' => 'HTML Düzeni - javascript başlatma', + 'HTML layout - primary navigation' => 'HTML Düzeni - birincil gezinti', + 'HTML layout - secondary navigation' => 'HTML Düzeni - ikincil gezinti', + 'Haiti' => 'Haiti', + 'Home - JavaScript' => 'Ana sayfa - JavaScript', + 'Home - at the top' => 'Ana sayfa - üst', + 'Home - block' => 'Ana sayfa - blok', + 'Home - bottom' => 'Ana sayfa - alt', + 'Home page - CSS stylesheet' => 'Ana sayfa - CSS stil sayfası', + 'Home page - after javascript include' => 'Ana sayfa - sonra javascript içerme', + 'Home page - after javascript initialisation' => 'Klasör sayfası - javascript başlatma sonra', + 'Home page - main area' => 'Ana sayfa - ana alan', + 'Honduras' => 'Honduras', + 'Hong Kong' => 'Hong Kong', + 'Hook - Edit JavaScript' => 'Hook - düzenleme JavaScript', + 'Hook - create form' => 'Kanca oluşturma formu', + 'Hook - delete form' => 'Hook - silme formu', + 'Hook edit - bottom' => 'Düzenle kanca - alt', + 'Hook edit - top' => 'Kanca Düzenle - üst', + 'Hook positions' => 'Kanca pozisyonlar', + 'Hooks' => 'Kanca (modül)', + 'Hooks - JavaScript' => 'Kanca - JavaScript', + 'Hooks - at the top' => 'Kanca - üst', + 'Hooks - bottom' => 'Kanca - alt', + 'Hooks - table header' => 'Kanca - Tablo üstbilgisi', + 'Hooks - table row' => 'Kanca - tablo satırı', + 'Hooks management' => 'Kanca yönetimi', + 'How document files are delivered in the web space (symlink or copy)' => 'Nasıl belge dosyaları web alanı (sembolik link veya kopya) teslim edilir', + 'How original (full resolution) images are delivered in the web space (symlink or copy)' => 'Nasıl orijinal (tam çözünürlükte) görüntüler web alanı (sembolik link veya kopya) teslim edilir', + 'Hungary' => 'Hungary', + 'Iceland' => 'İzlanda', + 'Image - Edit JavaScript' => 'Resim - düzenleme JavaScript', + 'Image edit - bottom' => 'Görüntü Düzenle - alt', + 'Image edit - top' => 'Görüntü Düzenle - üst', + 'Import - table header' => 'İthalat - Tablo üstbilgisi', + 'Import - table row' => 'İthalat - tablo satırı', + 'India' => 'Hindistan', + 'Indonesia' => 'Indonesia', + 'Invoice - After delivery module' => 'Fatura - sonra teslim modülü', + 'Invoice - After payment module' => '-Fatura ödeme modülü sonra', + 'Invoice - CSS' => 'Fatura - CSS', + 'Invoice - additional product information' => 'Fatura - daha fazla ürün bilgisi', + 'Invoice - after addresse area' => '-Adres alanı sonrası fatura', + 'Invoice - after product listing' => 'Fatura - sonra ürün listesi', + 'Invoice - after the information area' => '-Bilgi alan sonrası fatura', + 'Invoice - after the order summary' => '-Fatura Özet sipariş sonra', + 'Invoice - at the bottom of information area' => 'Fatura - bilgi alanının altındaki', + 'Invoice - at the bottom of the footer' => 'Fatura - altbilgi alt', + 'Invoice - at the top of the footer' => 'Fatura - altbilgi üstündeki', + 'Invoice - delivery address' => 'Fatura - teslimat adresi', + 'Invoice - imprint' => 'Fatura - Künye', + 'Invoice - in the header' => 'Fatura - başlıktaki', + 'Invoice choice - CSS stylesheet' => 'Fatura seçim - CSS stil sayfası', + 'Invoice choice - after javascript include' => 'JavaScript içerme sonra seçim - fatura', + 'Invoice choice - after javascript initialisation' => 'Fatura seçim - javascript başlatma sonra', + 'Invoice choice - at the bottom' => 'Fatura seçim - alt', + 'Invoice choice - at the top' => 'Fatura seçim - üst', + 'Invoice choice - delivery address' => 'Fatura seçim - teslimat adresi', + 'Invoice choice - extra payment zone' => 'Fatura seçim - ilave ödeme bölge', + 'Iran' => 'Iran', + 'Iraq' => 'Iraq', + 'Ireland' => 'İrlanda', + 'Israel' => 'Israel', + 'Italy' => 'Italy', + 'Ivory Coast' => 'Ivory Coast', + 'Jamaica' => 'Jameika', + 'Japan' => 'Japonya', + 'Jordan' => 'Ürdün', + 'Kazakhstan' => 'Kazakistan', + 'Kenya' => 'Kenya', + 'Kiribati' => 'Kiribati', + 'Kuwait' => 'Kuwait', + 'Kyrgyzstan' => 'Kırgızistan', + 'Language - create form' => 'Dil - oluşturma formu', + 'Languages - JavaScript' => 'Diller - JavaScript', + 'Languages - at the top' => 'Diller - üst', + 'Languages - bottom' => 'Diller - alt', + 'Languages - delete form' => 'Diller - silme formu', + 'Languages block' => 'Dil paketi', + 'Laos' => 'Laos', + 'Latvia' => 'Latviya', + 'Layout - Before the main content' => 'Düzen - daha önce ana içerik', + 'Layout - CSS' => 'Düzen - CSS', + 'Layout - JavaScript' => 'Düzen - JavaScript', + 'Layout - after footer' => 'Düzen - altbilgi sonra', + 'Layout - after top bar' => 'Düzen - en iyi bar sonra', + 'Layout - after top menu' => 'Düzen - üst menü sonra', + 'Layout - at the bottom of the top bar' => 'Düzen - üst çubuğu altındaki', + 'Layout - at the top of the top bar' => 'Düzen - üst çubuğu üstündeki', + 'Layout - before footer' => 'Düzen - altbilgi önce', + 'Layout - before top menu' => 'Düzen - üst menü önce', + 'Layout - before topbar' => 'Düzen - topbar önce', + 'Layout - in footer' => 'Düzen - altbilgi', + 'Layout - in the menu catalog' => 'Düzen - menü Kataloğu', + 'Layout - in the menu configuration' => 'Düzen - menü yapılandırma', + 'Layout - in the menu customers' => 'Düzen - menü müşterilerinde', + 'Layout - in the menu folders' => 'Düzen - menü klasörlerde', + 'Layout - in the menu modules' => 'Düzen - menü modülleri', + 'Layout - in the menu orders' => 'Düzen - menü klasörlerde', + 'Layout - in the menu tools' => 'Düzen - menü Araçlar', + 'Layout - in top menu items' => 'Düzen - üst menü öğeleri', + 'Layout - inside top bar' => 'Düzen - en iyi bar içinde', + 'Leave the default configuration of session' => 'Oturum varsayılan yapılandırmasını bırakın', + 'Lebanon' => 'Lübnan', + 'Lesotho' => 'Lesoto', + 'Liberia' => 'Liberia', + 'Libya' => 'Libya', + 'Liechtenstein' => 'Liechtenstein', + 'Life time of the cart cookie in the customer browser, in seconds' => 'Müşteri tarayıcı sepeti çerezde yaşam süresi saniye içinde', + 'Life time of the session cookie in the customer browser, in seconds' => 'Müşteri tarayıcı oturum çerezinin yaşam süresi saniye içinde', + 'Links block' => 'Bağlantı kutusu', + 'Lithuania' => 'Letonya', + 'Logging system configuration' => 'Günlük sistem yapılandırmasını', + 'Login page - CSS stylesheet' => 'Giriş sayfası - CSS stil sayfası', + 'Login page - after javascript include' => 'Giriş sayfası - sonra JavaScript içerme', + 'Login page - after javascript initialisation' => 'Klasör sayfası - javascript başlatma sonra', + 'Login page - at the bottom' => 'Giriş sayfası - alt', + 'Login page - at the bottom of the form' => 'Giriş sayfası - alt formu', + 'Login page - at the bottom of the main area' => 'Giriş sayfası - ana alanının altındaki', + 'Login page - at the top' => 'Giriş sayfası - üst', + 'Login page - at the top of the form' => 'Giriş sayfası - formun üstündeki', + 'Login page - at the top of the main area' => 'Giriş sayfası - ana alanının altındaki', + 'Logs - JavaScript' => 'Günlükleri - JavaScript', + 'Logs - at the top' => 'Günlükleri - üst', + 'Logs - bottom' => 'Günlükleri - alt', + 'Lost password - CSS stylesheet' => 'Parolayı unuttum - CSS stil sayfası', + 'Lost password - after javascript include' => 'Kayıp parola - sonra javascript içerme', + 'Lost password - at the bottom' => 'Parolayı unuttum - alt', + 'Lost password - at the bottom of the form' => 'Parolayı unuttum - alt formu', + 'Lost password - at the top' => 'Parolayı unuttum - üst', + 'Lost password - at the top of the form' => 'Parolayı unuttum - alt formu', + 'Lost password - javascript initialization' => 'Parolayı unuttum - javascript başlatma', + 'Luxembourg' => 'Luxembourg', + 'Macedonia' => 'Macedonia', + 'Madagascar' => 'Madagascar', + 'Mail sent to the customer when its account is created by an administrator in the back-office' => 'Arka ofiste bir yönetici tarafından kendi hesabınızı oluştururken müşteriye gönderilen posta', + 'Mail sent to the customer when its password or email is changed in the back-office' => 'Onun parola veya e-posta arka ofis değiştiğinde müşteriye gönderilen posta', + 'Mailing system - JavaScript' => 'JavaScript sistemi - posta', + 'Mailing system - at the top' => 'Posta sistemi - üst', + 'Mailing system - bottom' => 'Sistem - posta alt', + 'Malawi' => 'Malavi', + 'Malaysia' => 'Malezya', + 'Maldives' => 'Maldives', + 'Mali' => 'Mali', + 'Malta' => 'Malta', + 'Marshall Islands' => 'Marshall Islands', + 'Martinique' => 'Martinique', + 'Mauritania' => 'Mauritania', + 'Mauritius' => 'Morityus', + 'Mayotte' => 'Mayotte', + 'Message - Edit JavaScript' => 'Mesaj - düzenleme JavaScript', + 'Message - create form' => 'Mesaj - oluşturma formu', + 'Message - delete form' => 'Mesaj - silme formu', + 'Message edit - bottom' => 'Düzenle mesaj - alt', + 'Message edit - top' => 'İleti düzenleme - üst', + 'Message sent to the shop owner when a new order is placed' => 'Yeni bir sipariş verildiğinde dükkan sahibine gönderilen ileti', + 'Messages - JavaScript' => 'Mesaj - JavaScript', + 'Messages - at the top' => 'Mesaj - üst', + 'Messages - bottom' => 'Mesaj - alt', + 'Messages - table header' => 'Mesaj - Tablo üstbilgisi', + 'Messages - table row' => 'Mesaj - tablo satırı', + 'Mexico' => 'Meksika', + 'Micronesia' => 'Micronesia', + 'Mini cart' => 'Mini arabası', + 'Miss' => 'Miss', + 'Miss_short' => 'Miss', + 'Misses' => 'Eksikler', + 'Mister' => 'Bay', + 'Module - Edit JavaScript' => 'Modül - düzenleme JavaScript', + 'Module - configuration' => 'Modül - yapılandırma', + 'Module - configuration JavaScript' => 'Modül - yapılandırma JavaScript', + 'Module edit - bottom' => 'Modülü Düzenle - alt', + 'Module edit - top' => 'Modülü Düzenle - üst', + 'Module hook - Edit JavaScript' => 'Modülü kanca - JavaScript Düzenle', + 'Module hook - JavaScript' => 'Modülü kanca - JavaScript', + 'Module hook - create form' => 'Modülü kanca - oluşturma formu', + 'Module hook - delete form' => 'Modülü kanca - silme formu', + 'Module hook edit - bottom' => 'Modülü kanca Düzenle - alt', + 'Module hook edit - top' => 'Modülü kanca Düzenle - üst', + 'Modules - JavaScript' => 'Modüller - JavaScript', + 'Modules - at the top' => 'Modüller - üst', + 'Modules - bottom' => 'Modüller - alt', + 'Modules - table header' => 'Modüller - Tablo üstbilgisi', + 'Modules - table row' => 'Modüller - tablo satırı', + 'Modules maagement' => 'Modülleri maagement', + 'Modules management' => 'Modülleri maagement', + 'Moldova' => 'Moldova', + 'Monaco' => 'Monaco', + 'Mongolia' => 'Mongolia', + 'Morocco' => 'Morocco', + 'Mozambique' => 'Mozambique', + 'Mr.' => 'Bay.', + 'Mrs' => 'Bayan', + 'Name of the active PDF template' => 'Adı active PDF şablonu', + 'Name of the active back-office template' => 'Etkin arka ofis şablonunun adı', + 'Name of the active front-office template' => 'Aktif ön büro şablonunun adı', + 'Name of the active mailing template' => 'Etkin posta şablonunun adı', + 'Name of the cart cookie' => 'Sepeti tanımlama bilgisinin adını', + 'Name of the delivery view in the current PDF template (without extension)' => 'Geçerli PDF şablonu (uzantısı olmadan) teslim görünümün adı', + 'Name of the graphic driver used by the Imagine library (see https://imagine.readthedocs.org)' => 'Hayal Kitaplığı tarafından kullanılan grafik sürücüsünün adı (bkz: https://imagine.readthedocs.org)', + 'Name of the invoice view in the current PDF template (without extension)' => 'Geçerli PDF şablonu (uzantısı olmadan) teslim görünümün adı', + 'Name of the template view returned when an obsolete (or inactive) product URL is invoked' => 'Bir kullanılmayan (veya etkin) ürün URL\'si çağrıldığında döndürülen şablon görünümün adı', + 'Name the cart cookie' => 'Adı sepeti tanımlama bilgisi', + 'Namibia' => 'Nambiya', + 'Nauru' => 'Nauru', + 'Navigation block' => 'Gezinti blok', + 'Nepal' => 'Nepal', + 'Netherlands' => 'Netherlands', + 'New Products block' => 'Yeni Ürünler Bloğu', + 'New York' => 'Adresinizi yazınız', + 'New Zealand' => 'Yeni Zelanda', + 'New order {$order_ref} placed on {config key="store_name"}' => 'Yeni sipariş {$order_ref} yerleştirilir {config anahtarı "store_name" =}', + 'Newfoundland and Labrador' => 'Newfoundland ve Labrador', + 'Newsletter block' => 'Haber bülteni kutusu', + 'Newsletter page - CSS stylesheet' => 'Bülten sayfa - CSS stil sayfası', + 'Newsletter page - after javascript include' => 'Bülten sayfa JavaScript içerme-', + 'Newsletter page - after javascript initialisation' => 'Bülten sayfa - javascript başlatma sonra', + 'Newsletter page - at the bottom' => 'Bülten sayfa - alt', + 'Newsletter page - at the top' => 'Bülten sayfa - üst', + 'Nicaragua' => 'Nicaragua', + 'Niger' => 'Nijer', + 'Nigeria' => 'Nijerya', + 'Niue' => 'Norveç', + 'North Carolina' => 'Güney Carolina', + 'North Dakota' => 'Kuzey Dakota', + 'North Korea' => 'Kuzey Kore', + 'Northwest Territories' => 'Kuzeybatı Toprakları', + 'Norway' => 'Norway', + 'Not paid' => 'Ödenmeyen', + 'Nouvelle-Calédonie' => 'Yeni Kaledonya', + 'Oman' => 'Oman', + 'Order' => 'Sipariş', + 'Order - After closing product row' => 'Sipariş ürün satır kapattıktan sonra-', + 'Order - After product list' => 'Sipariş - sonra ürün listesi', + 'Order - Before product list' => 'Sipariş - önce ürün listesi', + 'Order - Before starting product row' => 'Sipariş ürün satır başlamadan önce-', + 'Order - Edit JavaScript' => 'Sipariş - düzenleme JavaScript', + 'Order - Tab' => 'Sipariş - sekmesi', + 'Order - bill bottom' => 'Sipariş - bill alt', + 'Order - bill top' => 'Sipariş - bill üst', + 'Order - cart bottom' => 'Sipariş - sepeti alt', + 'Order - cart top' => 'Sipariş - sepeti üst', + 'Order - content' => 'Sipariş - içerik', + 'Order - customer information bottom' => 'Sipariş - müşteri bilgi alt', + 'Order - delivery module bottom' => 'Sipariş - teslimat modülü alt', + 'Order - payment module bottom' => 'Sipariş - ödeme modülü alt', + 'Order - product list' => 'Sipariş - ürün listesi', + 'Order - table header' => 'Siparişler - Tablo üstbilgisi', + 'Order - table row' => 'Siparişler - tablo satırı', + 'Order confirmation - after the order summary' => 'Sipariş teyidi - sonra sipariş Özeti', + 'Order confirmation sent to the customer' => 'Müşteriye gönderilen sipariş teyidi', + 'Order details - CSS stylesheet' => 'Detaylar - CSS stil sayfası sipariş', + 'Order details - additional delivery information' => 'Ek teslimat bilgilerini detaylar - sipariş', + 'Order details - additional information' => 'Daha fazla bilgi ayrıntılı bilgi - sipariş', + 'Order details - additional invoice information' => 'Detaylar - ek fatura bilgileri sipariş', + 'Order details - additional product information' => 'Daha fazla ürün bilgisi detaylar - sipariş', + 'Order details - after addresses' => 'Sipariş ayrıntıları - adresleri sonra', + 'Order details - after global information' => 'Sipariş ayrıntıları - küresel bilgi sonra', + 'Order details - after javascript include' => 'JavaScript içerme sonra detaylar - siparişi', + 'Order details - after product' => 'Sipariş ayrıntıları - ürün sonra', + 'Order details - after products' => 'Sipariş ayrıntıları - ürün sonra', + 'Order details - after products list' => 'Sipariş ayrıntıları - ürünler listesinden sonra', + 'Order details - at the bottom' => 'Sipariş ayrıntıları - alt', + 'Order details - at the top' => 'Sipariş ayrıntıları - üst', + 'Order details - before products list' => 'Sipariş ayrıntıları - önce ürün listesi', + 'Order details - delivery address' => 'Teslimat adresi detaylar - sipariş', + 'Order details - invoice address' => 'Sipariş ayrıntıları - fatura adresi', + 'Order details - javascript initialization' => 'Detaylar - javascript başlatma sipariş', + 'Order edit - bottom' => 'Düzenleme sipariş - alt', + 'Order edit - delivery address' => 'Siparişi gir - teslimat adresi', + 'Order edit - displayed after product information' => 'Sonra ürün bilgileri görüntülenen sipariş Düzenle-', + 'Order edit - order product table header' => 'Siparişi gir - sipariş ürün tablo başlığı', + 'Order edit - order product table row' => 'Siparişi gir - sipariş ürün tablo satırı', + 'Order edit - top' => 'Sipariş Düzenle - üst', + 'Order failed - CSS stylesheet' => 'Başarısız - sipariş CSS stil sayfası', + 'Order failed - after javascript include' => 'Başarısız - sipariş sonra javascript içerme', + 'Order failed - after javascript initialisation' => 'Başarısız - sipariş sonra javascript başlatma', + 'Order failed - at the bottom' => 'Başarısız - sipariş alt', + 'Order failed - at the top' => 'Sipariş başarısız - üst', + 'Orders - JavaScript' => 'Siparişler - JavaScript', + 'Orders - at the top' => 'Siparişler - üst', + 'Orders - bottom' => 'Siparişler - Alt', + 'Orders - table header' => 'Siparişler - Tablo üstbilgisi', + 'Orders - table row' => 'Siparişler - tablo satırı', + 'Page 404 - CSS stylesheet' => 'Sayfa 404 - CSS stil sayfası', + 'Page 404 - after javascript include' => 'Sayfa javascript içerme sonra 404-', + 'Page 404 - after javascript initialisation' => 'Sayfa 404 - javascript başlatma sonra', + 'Page 404 - content area' => 'Sayfa 404 - içerik alanı', + 'Paid' => 'Ödendi', + 'Pakistan' => 'Pakistan', + 'Panama' => 'Panama', + 'Papua Nueva Guinea' => 'Papua Nueva Gine', + 'Paraguay' => 'Paraguay', + 'Path to the directory where documents are stored' => 'Belgeleri depolandığı dizinin yolunu', + 'Path to the directory where images are stored' => 'Görüntüleri depolandığı dizinin yolunu', + 'Pay by cheque' => 'Çekle Ödeme', + 'Payment failed - CSS stylesheet' => 'Ödeme başarısız oldu - CSS stil sayfası', + 'Payment failed - after javascript include' => 'JavaScript içerme sonra ödeme - başarısız oldu', + 'Payment failed - javascript initialization' => 'Ödeme başlatma başarısız oldu - javascript', + 'Payment gateway - CSS stylesheet' => 'Ödeme ağ geçidi - CSS stil sayfası', + 'Payment gateway - after javascript include' => 'JavaScript içerme sonra ödeme ağ geçidi-', + 'Payment gateway - after javascript initialisation' => 'Ödeme ağ geçidi - javascript başlatma sonra', + 'Payment gateway - javascript' => 'Ödeme ağ geçidi - javascript', + 'Payment gateway - main area' => 'Ödeme ağ geçidi - ana alan', + 'Peru' => 'Peru', + 'Philippines' => 'Filipinler', + 'Placed order - CSS stylesheet' => 'Yerleştirilmiş sipariş - CSS stil sayfası', + 'Placed order - after javascript include' => 'Sipariş - sonra javascript içerme', + 'Placed order - after javascript initialisation' => 'Yerleştirilmiş sipariş - javascript başlatma sonra', + 'Placed order - main area' => 'Yerleştirilmiş sipariş - ana alan', + 'Poland' => 'Polonya', + 'Polynésie française' => 'Polynésie française', + 'Portugal' => 'Portekiz', + 'Processing' => 'İşlem devam ediyor', + 'Product' => 'ürün', + 'Product - Edit JavaScript' => 'Ürün - düzenleme JavaScript', + 'Product - Tab' => 'Ürün - sekmesi', + 'Product - accessories table header' => 'Ürün - Aksesuar Tablo üstbilgisi', + 'Product - accessories table row' => 'Ürün - Aksesuar tablo satırı', + 'Product - after combinations' => 'Ürün - sonra kombinasyonları', + 'Product - at the bottom of a product combination' => 'Ürünler - ürün birleşimi dibinde', + 'Product - attributes table header' => 'Ürün - öznitelikleri üstbilgi masa.', + 'Product - attributes table row' => 'Ürün - öznitelikleri satır tablo.', + 'Product - before combinations' => 'Ürün - önce kombinasyonları', + 'Product - categories table header' => 'Ürün - Kategoriler tablosu başlığı', + 'Product - categories table row' => 'Ürün - kategoriler tablo satırı', + 'Product - combination delete form' => 'Ürün - birleşimi silme formu', + 'Product - combinations list caption' => 'Ürün - kombinasyon listesi başlığı', + 'Product - content' => 'Ürün - içerik', + 'Product - contents table header' => 'Ürün - içindekiler tablosu başlığı', + 'Product - contents table row' => 'Ürün - içeriği tablo satırı', + 'Product - create form' => 'Ürün - oluşturma formu', + 'Product - delete form' => 'Ürün - silme formu', + 'Product - details pricing form' => 'Ürün - form fiyat tafsilât', + 'Product - details promotion form' => 'Ürün - ayrıntıları tanıtım formu', + 'Product - features table row' => 'Ürün - özellikleri tablo satırı', + 'Product - features-table-header' => 'Ürün - özellikleri Tablo başlık', + 'Product - folders table header' => 'Ürün - klasörler Tablo üstbilgisi', + 'Product - folders table row' => 'Ürün - klasörler tablo satırı', + 'Product - stock edit form' => 'Ürün - stok düzenleme formu', + 'Product edit - bottom' => 'Ürün Düzenle - alt', + 'Product edit - top' => 'Ürün Düzenle - üst', + 'Product loop - at the bottom' => 'Ürün döngüsü - alt', + 'Product loop - at the top' => 'Ürün döngüsü - üst', + 'Product page - CSS stylesheet' => 'Ürün sayfası - CSS stil sayfası', + 'Product page - On the bottom of the form' => 'Ürün sayfasında - formun altı', + 'Product page - On the top of the form' => 'Ürün sayfasında - formun altı', + 'Product page - additional information' => 'Ürün sayfası - ek bilgi', + 'Product page - after javascript include' => 'Ürün sayfa JavaScript içerme-', + 'Product page - after javascript initialisation' => 'Ürün sayfası - javascript başlatma sonra', + 'Product page - at the bottom' => 'Alt - ürün sayfası', + 'Product page - at the bottom of the detail area' => 'Ayrıntı alanının alt - ürün sayfası', + 'Product page - at the top' => 'Ürün sayfası - üst', + 'Product page - at the top of the detail' => 'Ürün sayfası - detay üstündeki', + 'Product page - photo gallery' => 'Ürün sayfası - Fotoğraf Galerisi', + 'Products - caption' => 'Ürünler - resim yazısı', + 'Products - header' => 'Ürünler - başlık', + 'Products - row' => 'Ürünler - kürek', + 'Products offer block' => 'Blok ürünler sunmak', + 'Profile - Edit JavaScript' => 'Profil - düzenleme JavaScript', + 'Profile - create form' => 'Profil - oluşturma formu', + 'Profile - delete form' => 'Profili - silme form', + 'Profile - table header' => 'Profil - Tablo üstbilgisi', + 'Profile - table row' => 'Profil - tablo satırı', + 'Profile edit - bottom' => 'Düzenle Profil - alt', + 'Profile edit - top' => 'Profil Düzenle - üst', + 'Profiles - JavaScript' => 'Profiller - JavaScript', + 'Profiles - at the top' => 'Profiller - üst', + 'Profiles - bottom' => 'Profiller - alt', + 'Qatar' => 'Katar', + 'Refunded' => 'Geri ödeme', + 'Register - CSS stylesheet' => 'Kayıt - CSS stil sayfası', + 'Register - after javascript include' => 'Sonra JavaScript içerme - kayıt', + 'Register - after javascript initialisation' => '-Javascript başlatma sonra kayıt', + 'Register - at the bottom' => 'Kayıt - alt', + 'Register - at the bottom of the form' => '-Kayıt formu alt kısmında', + 'Register - at the top' => 'Kayıt - üst', + 'Register - at the top of the form' => '-Kayıt formu üst kısmında', + 'Romania' => 'Romanya', + 'Russia' => 'Rusya', + 'Rwanda' => 'Ruanda', + 'Réunion(La)' => 'Réunion(La)', + 'Saint Kitts and Nevis' => 'Saint Kitts ve Nevis', + 'Saint Lucia' => 'Saint Lucia', + 'Saint Vincent and the Grenadines' => 'Saint Vincent and the Grenadines', + 'Sale - create form' => 'Satılık - oluşturma formu', + 'Sale - delete form' => 'Satılık - silme formu', + 'Sale edit - bottom' => 'Satılık Düzenle - alt', + 'Sale edit - top' => 'Satılık düzen - en iyi', + 'Sale edit page - javascript last call block' => 'Satış sayfa - javascript son çağrı blok Düzenle', + 'Sales - JavaScript' => 'Satış - JavaScript', + 'Sales - at the bottom' => 'Satış - alt', + 'Sales - at the top' => 'Satış - üst', + 'Sales - table header' => 'Satış - Tablo üstbilgisi', + 'Sales - table row' => 'Satış - tablo satırı', + 'Sales management' => 'Satış Yönetimi', + 'San Marino' => 'San Marino', + 'Sao Tome and Principe' => 'Sao Tome ve Principe', + 'Saudi Arabia' => 'Saudi Arabia', + 'Search' => 'Arama', + 'Search - JavaScript' => 'Arama - JavaScript', + 'Search - at the top' => 'Arama - üst', + 'Search - bottom' => 'Arama - alt', + 'Search block' => 'Arama engelleme', + 'Search page - CSS stylesheet' => 'Arama sayfası - CSS stil sayfası', + 'Search page - after javascript include' => 'Arama sayfası - sonra JavaScript içerme', + 'Search page - after javascript initialisation' => 'Arama sayfası - javascript başlatma sonra', + 'Secret key for form CSRF token' => 'Form CSRF belirteci için gizli anahtar', + 'Senegal' => 'Senegal', + 'Sent' => 'Gönder', + 'Seychelles' => 'Seyşel Adaları', + 'Shipping configuration' => 'Aktarma yapılandırması', + 'Shipping configuration - Edit' => 'Aktarma yapılandırması - Düzenle', + 'Shipping configuration - Edit JavaScript' => 'Aktarma yapılandırması - JavaScript Düzenle', + 'Shipping configuration - JavaScript' => 'Aktarma yapılandırması - JavaScript', + 'Shipping configuration - at the top' => 'Aktarma yapılandırması - üst', + 'Shipping configuration - bottom' => 'Aktarma yapılandırması - alt', + 'Shipping configuration - country delete form' => 'Aktarma yapılandırması - ülke silme formu', + 'Shipping configuration - create form' => 'Aktarma yapılandırması - oluşturma formu', + 'Shipping configuration - delete form' => 'Aktarma yapılandırması - silme formu', + 'Shipping configuration - table header' => 'Aktarma yapılandırması - Tablo üstbilgisi', + 'Shipping configuration - table row' => 'Aktarma yapılandırması - tablo satırı', + 'Shipping configuration edit - bottom' => 'Aktarma yapılandırması Düzenle - alt', + 'Shipping configuration edit - top' => 'Sevkiyat yapılandırma Düzenle - üst', + 'Shipping zones edit - bottom' => 'Nakliye bölgeleri düzenlemek - alt', + 'Shipping zones edit - top' => 'Nakliye bölgeleri Düzenle - üst', + 'Show error message instead of a white page on a server error' => 'Bir sunucu hatası üzerinde beyaz bir sayfa yerine hata iletisi göster', + 'Sierra Leone' => 'Sierra Leone', + 'Singapore' => 'Singapore', + 'Sitemap - at the bottom' => 'Site Haritası - alt', + 'Slovakia' => 'Slovakya', + 'Slovenia' => 'Slovenya', + 'Smarty template engine integration' => 'Smarty şablon motoru entegrasyonu', + 'Social Networks block' => 'Sosyal ağlar blok', + 'Solomon Islands' => 'Solomon Islands', + 'Somalia' => 'Somali', + 'South Africa' => 'Güney Afrika', + 'South Carolina' => 'Güney Carolina', + 'South Dakota' => 'Güney Dakota', + 'South Korea' => 'South Korea', + 'Spain' => 'Spain', + 'Sri Lanka' => 'Sri Lanka', + 'St Pierre et Miquelon' => 'St Pierre et Miquelon', + 'Store Information - JavaScript' => 'Mağaza bilgileri - JavaScript', + 'Store information configuration' => 'Mağaza bilgileri yapılandırma', + 'Sudan' => 'Sudan', + 'Suriname' => 'Suriname', + 'Swaziland' => 'Svaziland', + 'Sweden' => 'İsveç', + 'Switzerland' => 'Switzerland', + 'Syria' => 'Suriye', + 'System - logs JavaScript' => 'Sistem - günlükleri JavaScript', + 'Tab SEO - bottom' => 'SEO sekme - alt', + 'Tab SEO - top' => 'Sekme SEO - üst', + 'Tab SEO - update form' => 'Sekme SEO - güncelleştirme formu', + 'Tab document - bottom' => 'Belge sekmesi - alt', + 'Tab document - top' => 'Sekmesini belge - üst', + 'Tab image - bottom' => 'Resim sekmesi - alt', + 'Tab image - top' => 'Sekme resmi - üst', + 'Tajikistan' => 'Tajikistan', + 'Tanzania' => 'Tanzanya', + 'Tax - Edit JavaScript' => 'Kdv- düzenleme JavaScript', + 'Tax - create form' => 'Kdv - oluşturma formu', + 'Tax - delete form' => 'Kdv - silme formu', + 'Tax edit - bottom' => 'Düzenleme Kdvi - alt', + 'Tax edit - top' => 'Kdv Düzenle - üst', + 'Tax rule edit - bottom' => 'Kural düzenleme Kdv - alt', + 'Tax rule edit - top' => 'Kdv Kural Düzenle - üst', + 'Tax rules configuration' => 'Kdv kuralları yapılandırma', + 'Taxes - update form' => 'Kdv - güncelleştirme formu', + 'Taxes rules - JavaScript' => 'Kdv kuralları - JavaScript', + 'Taxes rules - at the top' => 'Kdv kuralları - üst', + 'Taxes rules - bottom' => 'Kdv kuralları - alt', + 'Template - Edit JavaScript' => 'Şablon - düzenleme JavaScript', + 'Template - attributes table header' => 'Şablon - öznitelikleri üstbilgi masa.', + 'Template - attributes table row' => 'Şablon - öznitelikleri satır tablo.', + 'Template - create form' => 'Şablon - oluşturma formu', + 'Template - delete form' => 'Şablon - silme formu', + 'Template - features table row' => 'Şablon - Özellikleri tablo satırı', + 'Template - features-table-header' => 'Şablon - Özellikleri tablo başlık', + 'Template edit - bottom' => 'Şablonu Düzenle - alt', + 'Template edit - top' => 'Şablonu Düzenle - üst', + 'Templates - JavaScript' => 'Şablonlar - JavaScript', + 'Templates - at the top' => 'Şablonlar - üst', + 'Templates - bottom' => 'Şablonlar - alt', + 'Templates - table header' => 'Şablonlar - Tablo üstbilgisi', + 'Templates - table row' => 'Şablonlar - tablo satırı', + 'Thailand' => 'Tayland', + 'The ID of the \'Terms & Conditions\' content.' => '\'Şartlar ve koşullar\' içerik Kımlığı.', + 'The ID of the folder containing your information pages : terms, imprint, ...' => 'Bilgi sayfaları içeren klasörü Kımlığı: şartları, Künye,...', + 'The Vatican' => 'Vatikan', + 'The default quality (in %) of the generated images' => 'Oluşturulan görüntülerin varsayılan kalitesini (% olarak)', + 'The path (relative to the default back-office template) to the image used when no flag image can be found for a country' => '(Göre varsayılan arka ofis şablon) yolu hiçbir bayrak resmi bir ülke için bulduğunda kullanılan görüntüsüne', + 'The path to the document cache directory in the web space' => 'Web alanı belge önbellek dizininde yolunu', + 'The path to the image cache directory in the web space' => 'Web alanı resim önbellek dizininde yolunu', + 'TinyMCE WYSIWYG editor' => 'TinyMCE WYSIWYG editörü', + 'Togo' => 'Togo', + 'Tonga' => 'Tonga', + 'Tools - JavaScript' => 'Araçlar - JavaScript', + 'Tools - at the bottom of column 1' => 'Araçlar - 1 sütunun altındaki', + 'Tools - at the top' => 'Araçlar - üst', + 'Tools - at the top of the column' => 'Üst sütun - Araçlar', + 'Tools - bottom' => 'Araçlar - alt', + 'Tools panel' => 'Araçlar paneli', + 'Translations' => 'Çeviri', + 'Translations - JavaScript' => 'Çeviriler - JavaScript', + 'Trinidad and Tobago' => 'Trinidad and Tobago', + 'Tunisia' => 'Tunisia', + 'Turkey' => 'Türkiye', + 'Turkmenistan' => 'Türkmenistan', + 'Tuvalu' => 'Tuvalu', + 'UK Pound' => 'İngiliz Lirası', + 'Uganda' => 'Uganda', + 'Ukraine' => 'Ukrayna', + 'United Arab Emirates' => 'United Arab Emirates', + 'United Kingdom' => 'Birleşik Krallık', + 'United States Dollar' => 'ABD doları', + 'Update customer account - CSS stylesheet' => 'Müşteri hesabını güncelle - CSS stil sayfası', + 'Update customer account - after javascript include' => 'JavaScript içerme sonra müşteri hesabı - güncelleme', + 'Update customer account - after javascript initialisation' => 'Javascript başlatma sonra - müşteri hesabını güncelle', + 'Update customer account - at the bottom' => 'Alt - müşteri hesabını güncelle', + 'Update customer account - at the bottom of the form' => 'Formun alt - müşteri hesabını güncelle', + 'Update customer account - at the top' => 'Üst - müşteri hesabını güncelle', + 'Update customer account - at the top of the form' => 'Formun alt - müşteri hesabını güncelle', + 'Uruguay' => 'Uruguay', + 'Use a persistent cookie to keep track of customer cart' => 'Müşteri sepeti izlemek için kalıcı bir tanımlama bilgisi kullanın', + 'Uzbekistan' => 'Özbekistan', + 'Vanuatu' => 'Vanuatu Cumhuriyeti', + 'Variable - Edit JavaScript' => 'Değişken - düzenleme JavaScript', + 'Variable - create form' => 'Değişken - oluşturma formu', + 'Variable - delete form' => 'Değişken - silme formu', + 'Variable edit - bottom' => 'Değişkenini Düzenle - alt', + 'Variable edit - top' => 'Değişken Düzenle - üst', + 'Variables - JavaScript' => 'Değişkenleri - JavaScript', + 'Variables - at the top' => 'Değişkenleri - üst', + 'Variables - bottom' => 'Değişkenleri - alt', + 'Variables - table header' => 'Değişkenleri - Tablo üstbilgisi', + 'Variables - table row' => 'Değişkenleri - tablo satırı', + 'Venezuela' => 'Venezuela', + 'Vietnam' => 'Vietnam', + 'View administration logs' => 'Yönetim günlüklerini görüntüleme', + 'Virtual Product Controller' => 'Sanal ürün denetleyicisi', + 'Wallis-et-Futuna' => 'Wallis-et-Futuna', + 'Western Samoa' => 'Batı Samoa', + 'Where the WYSIWYG editor is required' => 'WYSIWYG editörü gerekli olduğu', + 'Whitespace trim level of the generated HTML code (0 = none, 1 = medium, 2 = maximum)' => 'Boşluk kırpmak oluşturulan HTML kodunun düzeyi (0 = yok, 1 = orta, 2 = maksimum)', + 'Yemen' => 'Yemen', + 'You can now login at' => 'Şimdi giriş yapınız', + 'You have lost your password
    \r\nPlease, change this password after your first connection' => 'Şifrenizi kaybetti < br / > \r\nPlease, ilk bağlantıdan sonra bu parolayı değiştirme', + 'You have lost your password
    \r\nYour new password is' => 'Şifrenizi kaybetti < br / > \r\nYour yeni şifre', + 'Your account information on {config key="store_name"} has been changed.' => 'Hesap bilgilerinizi {config anahtarı "store_name" =} değiştirildi.', + 'Your new passord is : {$password}' => 'Senin yeni geçmek mi: {$password}', + 'Your new password' => 'Yeni parola', + 'Your new password for {config key="store_name"}' => 'Yeni parolanızı {config anahtarı "store_name" =}', + 'Your order {$order_ref} at {config key="store_name"}' => 'Sipariş {$order_ref}, {config anahtarı "store_name" =}', + 'Zaire' => 'Zaire', + 'Zambia' => 'Zambia', + 'Zimbabwe' => 'Zimbabwe', + 'Zone - delete form' => 'Bölge - silme formu', + '[Firewall/Bruteforce] Number of allowed attemps' => '[Güvenlik duvarı/Bruteforce] İzin verilen kalkışmak sayısı', + '[Firewall/Bruteforce] Time to wait between X attempts' => '[Güvenlik duvarı/Bruteforce] X arasında beklenecek süre çalışır', + '[Firewall] Activate the firewall' => '[Firewall] Güvenlik Duvarı\'nı etkinleştirme', + '[Firewall] Number of allowed attemps' => '[Firewall] sayısı izin verilen kalkışmak', + '[Firewall] Time to wait between X attempts' => '[Firewall] X arasında beklenecek süre çalışır', + 'changing password email for' => 'şifre e-posta için değiştirme', + 'customer account - CSS stylesheet' => 'Müşteri hesabı - CSS stil sayfası', + 'customer account - after javascript include' => 'Müşteri hesabı - sonra JavaScript içerme', + 'customer account - after javascript initialisation' => 'Müşteri hesabı - javascript başlatma sonra', + 'customer account - at the bottom' => 'Müşteri hesabı - alt', + 'customer account - at the top' => 'Müşteri hesabı - üst', + 'export of newsletter subscribers' => 'bülten abonesi ihracat', + 'language selection page - CSS stylesheet' => 'Dil seçimi sayfası - CSS stil sayfası', + 'language selection page - after javascript include' => 'Dil seçimi sayfa JavaScript içerme-', + 'language selection page - after javascript initialisation' => 'Dil seçimi sayfası - javascript başlatma sonra', + 'language selection page - at the bottom' => 'Dil seçimi sayfası - alt', + 'language selection page - at the top' => 'Dil seçimi sayfası - üst', + 'tax rule - Edit JavaScript' => 'Kdv kural - JavaScript Düzenle', + 'tax rule - create form' => 'Kdv kural - oluşturma formu', + 'tax rule - delete form' => 'Kdv kural - silme formu', + 'tinymce wysiwyg editor' => 'TinyMCE WYSIWYG editörü', +]; diff --git a/setup/I18n/uk_UA.php b/setup/I18n/uk_UA.php new file mode 100644 index 00000000..64971cb8 --- /dev/null +++ b/setup/I18n/uk_UA.php @@ -0,0 +1,8 @@ + 'Категорія', + 'Content' => 'Контент', + 'Folder' => 'Каталог', + 'Hooks' => 'Хуки', +]; diff --git a/setup/Readme.md b/setup/Readme.md new file mode 100644 index 00000000..aa8dc438 --- /dev/null +++ b/setup/Readme.md @@ -0,0 +1,35 @@ +Readme +====== + +## This is the repository of Thelia setup/update scripts. All the pull requests on this repo will be ignored. +### If you want to create a project, please take a look at [thelia/thelia-project](https://github.com/thelia/thelia-project) +### If you want to contribute to Thelia, please take a look at [thelia/thelia](https://github.com/thelia/thelia) + +Thelia +------ +[![Build Status](https://travis-ci.org/thelia/thelia.png?branch=master)](https://travis-ci.org/thelia/thelia) [![License](https://poser.pugx.org/thelia/thelia/license.png)](https://packagist.org/packages/thelia/thelia) [![Scrutinizer Quality Score](https://scrutinizer-ci.com/g/thelia/thelia/badges/quality-score.png?s=61e3e04a69bffd71c29b08e5392080317a546716)](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. + +This is the new major version of Thelia. + +You can download this version and have a try or take a look at the source code (or anything you wish, respecting LGPL). See http://thelia.net/ web site for more information. + +A repository containing all thelia modules is available at this address : https://github.com/thelia-modules + +Requirements +------------ + +* php 5.5 + * Required extensions : + * PDO_Mysql + * openssl + * intl + * gd + * curl + * safe_mode off + * memory_limit at least 128M, preferably 256. + * post_max_size 20M + * upload_max_filesize 2M +* apache 2 +* mysql diff --git a/setup/composer.json b/setup/composer.json new file mode 100644 index 00000000..f1b0d121 --- /dev/null +++ b/setup/composer.json @@ -0,0 +1,11 @@ +{ + "name": "thelia/setup", + "type": "thelia-local", + "require": { + "thelia/installer": "~1.1", + "fzaninotto/faker": "1.5.*" + }, + "extra": { + "installer-name": "setup" + } +} diff --git a/setup/faker-assets/FreeSans.ttf b/setup/faker-assets/FreeSans.ttf new file mode 100644 index 0000000000000000000000000000000000000000..9db958532c12ef7f4aa22fab57a0f71e82acdd38 GIT binary patch literal 714456 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

    YoY{Tps(}N873!pmd$-^|tLKtcQ|SKo^_N|G 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 )r+_%USi1dhK+UkOZ?7=*O+WA-{?*j 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 +$thelia->getContainer()->get('thelia.translator'); +// The default faker is en_US +$faker = Faker\Factory::create('en_US'); + +// Create localized version for content generation +$localizedFaker = []; + +foreach ($localeList as $locale) { + $localizedFaker[$locale] = Faker\Factory::create($locale); +} + +$con = \Propel\Runtime\Propel::getConnection( + Thelia\Model\Map\ProductTableMap::DATABASE_NAME +); +$con->beginTransaction(); + +// Intialize URL management +$url = new Thelia\Tools\URL(); + +$currency = \Thelia\Model\CurrencyQuery::create()->filterByCode('EUR')->findOne(); + +//\Thelia\Log\Tlog::getInstance()->setLevel(\Thelia\Log\Tlog::ERROR); + +try { + $stmt = $con->prepare("SET foreign_key_checks = 0"); + $stmt->execute(); + + echo "Clearing tables\n"; + + Model\ProductAssociatedContentQuery::create()->deleteAll(); + Model\CategoryAssociatedContentQuery::create()->deleteAll(); + Model\FeatureProductQuery::create()->deleteAll(); + Model\AttributeCombinationQuery::create()->deleteAll(); + Model\FeatureQuery::create()->deleteAll(); + Model\FeatureI18nQuery::create()->deleteAll(); + Model\FeatureAvQuery::create()->deleteAll(); + Model\FeatureAvI18nQuery::create()->deleteAll(); + Model\AttributeQuery::create()->deleteAll(); + Model\AttributeI18nQuery::create()->deleteAll(); + Model\AttributeAvQuery::create()->deleteAll(); + Model\AttributeAvI18nQuery::create()->deleteAll(); + Model\CategoryQuery::create()->deleteAll(); + Model\CategoryI18nQuery::create()->deleteAll(); + Model\ProductQuery::create()->deleteAll(); + Model\ProductI18nQuery::create()->deleteAll(); + Model\CustomerQuery::create()->deleteAll(); + Model\AdminQuery::create()->deleteAll(); + Model\FolderQuery::create()->deleteAll(); + Model\FolderI18nQuery::create()->deleteAll(); + Model\ContentQuery::create()->deleteAll(); + Model\ContentI18nQuery::create()->deleteAll(); + Model\AccessoryQuery::create()->deleteAll(); + Model\ProductSaleElementsQuery::create()->deleteAll(); + Model\ProductPriceQuery::create()->deleteAll(); + Model\BrandQuery::create()->deleteAll(); + Model\BrandI18nQuery::create()->deleteAll(); + Model\ProductImageQuery::create()->deleteAll(); + Model\CategoryImageQuery::create()->deleteAll(); + Model\FolderImageQuery::create()->deleteAll(); + Model\ContentImageQuery::create()->deleteAll(); + Model\BrandImageQuery::create()->deleteAll(); + Model\ProductDocumentQuery::create()->deleteAll(); + Model\CategoryDocumentQuery::create()->deleteAll(); + Model\FolderDocumentQuery::create()->deleteAll(); + Model\ContentDocumentQuery::create()->deleteAll(); + Model\BrandDocumentQuery::create()->deleteAll(); + Model\CouponQuery::create()->deleteAll(); + Model\OrderQuery::create()->deleteAll(); + Model\SaleQuery::create()->deleteAll(); + Model\SaleProductQuery::create()->deleteAll(); + Model\MetaDataQuery::create()->deleteAll(); + + $stmt = $con->prepare("SET foreign_key_checks = 1"); + + $stmt->execute(); + + // default country (France) + $defaultCountry = [64, null]; + + // Store info + + echo "Creating Store information \n"; + + Model\ConfigQuery::write('store_name', 'Thelia V2'); + Model\ConfigQuery::write('store_email', 'test@thelia.net'); + Model\ConfigQuery::write('store_notification_emails', 'test@thelia.net'); + Model\ConfigQuery::write('store_address1', "5 rue Rochon"); + Model\ConfigQuery::write('store_zipcode', "63000"); + Model\ConfigQuery::write('store_city', "Clermont-Ferrand"); + Model\ConfigQuery::write('store_country', $defaultCountry[0]); + + $api = new Thelia\Model\Api(); + + $api + ->setProfileId(null) + ->setApiKey('79E95BD784CADA0C9A578282E') + ->setLabel("test") + ->save(); + + // API + echo "Creating API key\n"; + + $api = new Thelia\Model\Api(); + + $api + ->setProfileId(null) + ->setApiKey('79E95BD784CADA0C9A578282E') + ->setLabel("test") + ->save(); + + // Customer + echo "Creating customers\n"; + $customer = new Thelia\Model\Customer(); + + $customer->createOrUpdate( + 1, + "thelia", + "thelia", + "5 rue rochon", + "", + "", + "0102030405", + "0601020304", + "63000", + "clermont-ferrand", + $defaultCountry[0], + "test@thelia.net", + "azerty", + null, + 0, + null, + 0, + null, + null, + false, + $defaultCountry[1] + ); + for ($j = 0; $j <= 3; $j++) { + $address = new Thelia\Model\Address(); + $country = getRandomCountry(); + $address->setLabel(getRealText(20)) + ->setTitleId(rand(1, 3)) + ->setFirstname($faker->firstname) + ->setLastname($faker->lastname) + ->setAddress1($faker->streetAddress) + ->setAddress2($faker->streetAddress) + ->setAddress3($faker->streetAddress) + ->setCellphone($faker->phoneNumber) + ->setPhone($faker->phoneNumber) + ->setZipcode($faker->postcode) + ->setCity($faker->city) + ->setCountryId($country[0]) + ->setStateId($country[1]) + ->setCustomer($customer) + ->save() + ; + } + + $admin = new Thelia\Model\Admin(); + $admin + ->setFirstname($faker->firstname) + ->setLastname($faker->lastname) + ->setLogin('thelia') + ->setPassword('thelia') + ->setLocale('en_US') + ->setEmail('') + ->save(); + + for ($i=0; $i<3; $i++) { + $admin = new Thelia\Model\Admin(); + $admin + ->setFirstname($faker->firstname) + ->setLastname($faker->lastname) + ->setLogin($faker->firstname) + ->setPassword('azerty') + ->setLocale('en_US') + ->setEmail($faker->email) + ->save(); + } + + for ($i = 0; $i < 50; $i++) { + $customer = new Thelia\Model\Customer(); + $country = getRandomCountry(); + $customer->createOrUpdate( + rand(1, 3), + $faker->firstname, + $faker->lastname, + $faker->streetAddress, + $faker->streetAddress, + $faker->streetAddress, + $faker->phoneNumber, + $faker->phoneNumber, + $faker->postcode, + $faker->city, + $country[0], + $faker->email, + "azerty".$i, + null, + 0, + null, + 0, + null, + null, + false, + $country[1] + ); + + for ($j = 0; $j <= 3; $j++) { + $address = new Thelia\Model\Address(); + $address->setLabel(getRealText(20)) + ->setTitleId(rand(1, 3)) + ->setFirstname($faker->firstname) + ->setLastname($faker->lastname) + ->setAddress1($faker->streetAddress) + ->setAddress2($faker->streetAddress) + ->setAddress3($faker->streetAddress) + ->setCellphone($faker->phoneNumber) + ->setPhone($faker->phoneNumber) + ->setZipcode($faker->postcode) + ->setCity($faker->city) + ->setCountryId($country[0]) + ->setStateId($country[1]) + ->setCustomer($customer) + ->save() + ; + + } + } + + echo "Creating features\n"; + + //features and features_av + $featureList = array(); + for ($i=0; $i<4; $i++) { + $feature = new Thelia\Model\Feature(); + $feature->setVisible(1); + $feature->setPosition($i); + setI18n($feature); + + $feature->save(); + $featureId = $feature->getId(); + $featureList[$featureId] = array(); + + //hardcode chance to have no av + if ($i === 1 || $i === 3) { + for ($j = 0; $j < rand(1, 5); $j++) { + $featureAv = new Thelia\Model\FeatureAv(); + $featureAv->setFeature($feature); + $featureAv->setPosition($j); + setI18n($featureAv); + + $featureAv->save(); + $featureList[$featureId][] = $featureAv->getId(); + } + } + } + + echo "Creating attributes\n"; + + //attributes and attributes_av + $attributeList = array(); + for ($i=0; $i<4; $i++) { + $attribute = new Thelia\Model\Attribute(); + $attribute->setPosition($i); + setI18n($attribute); + + $attribute->save(); + $attributeId = $attribute->getId(); + $attributeList[$attributeId] = array(); + + for ($j=0; $jsetAttribute($attribute); + $attributeAv->setPosition($j); + setI18n($attributeAv); + + $attributeAv->save(); + $attributeList[$attributeId][] = $attributeAv->getId(); + } + } + + echo "Creating templates\n"; + + $template = new Thelia\Model\Template(); + setI18n($template, array("Name" => 20)); + $template->save(); + + foreach ($attributeList as $attributeId => $attributeAvId) { + $at = new Thelia\Model\AttributeTemplate(); + + $at + ->setTemplate($template) + ->setAttributeId($attributeId) + ->save(); + } + + foreach ($featureList as $featureId => $featureAvId) { + $ft = new Thelia\Model\FeatureTemplate(); + + $ft + ->setTemplate($template) + ->setFeatureId($featureId) + ->save(); + } + + echo "Creating folders and contents\n"; + + //folders and contents + $contentIdList = array(); + for ($i=0; $i<4; $i++) { + $folder = new Thelia\Model\Folder(); + $folder->setParent(0); + $folder->setVisible(1); + $folder->setPosition($i+1); + setI18n($folder); + + $folder->save(); + + $image = new \Thelia\Model\FolderImage(); + $image->setFolderId($folder->getId()); + generate_image($image, 'folder', $folder->getId()); + + $document = new \Thelia\Model\FolderDocument(); + $document->setFolderId($folder->getId()); + generate_document($document, 'folder', $folder->getId()); + + for ($j=0; $j<3; $j++) { + $subfolder = new Thelia\Model\Folder(); + $subfolder->setParent($folder->getId()); + $subfolder->setVisible(1); + $subfolder->setPosition($j+1); + setI18n($subfolder); + + $subfolder->save(); + + $image = new \Thelia\Model\FolderImage(); + $image->setFolderId($subfolder->getId()); + generate_image($image, 'folder', $subfolder->getId()); + + $document = new \Thelia\Model\FolderDocument(); + $document->setFolderId($folder->getId()); + generate_document($document, 'folder', $subfolder->getId()); + + for ($k=0; $k<4; $k++) { + $content = new Thelia\Model\Content(); + $content->addFolder($subfolder); + + $contentFolders = $content->getContentFolders(); + $collection = new \Propel\Runtime\Collection\Collection(); + $collection->prepend($contentFolders[0]->setDefaultFolder(1)); + $content->setContentFolders($collection); + + $content->setVisible(1); + $content->setPosition($k+1); + setI18n($content); + + $content->save(); + $contentId = $content->getId(); + $contentIdList[] = $contentId; + + $image = new \Thelia\Model\ContentImage(); + $image->setContentId($contentId); + generate_image($image, 'content', $contentId); + + $document = new \Thelia\Model\ContentDocument(); + $document->setContentId($contentId); + generate_document($document, 'content', $contentId); + } + } + } + + echo "Creating brands\n"; + + $brandIdList = []; + + for ($k=0; $k<10; $k++) { + $brand = new Thelia\Model\Brand(); + + $brand->setVisible(1); + $brand->setPosition($k+1); + setI18n($brand); + + $brand->save(); + $brandId = $brand->getId(); + $brandIdList[] = $brandId; + + $image = new \Thelia\Model\BrandImage(); + $image->setBrandId($brandId); + generate_image($image, 'brand', $brandId); + + $document = new \Thelia\Model\BrandDocument(); + $document->setBrandId($brandId); + generate_document($document, 'brand', $brandId); + } + + echo "Creating categories and products\n"; + + //categories and products + $productIdList = array(); + $virtualProductList = array(); + $categoryIdList = array(); + for ($i=1; $i<$numberCategories; $i++) { + $category = createCategory($faker, 0, $i, $categoryIdList, $contentIdList); + + for ($j=1; $jgetId(), $j, $categoryIdList, $contentIdList); + + for ($k=0; $ksetAccessory($productIdList[$pick]) + ->setProductId($productId) + ->setPosition($i) + ->save(); + } + + //add random associated content + $alreadyPicked = array(); + for ($i=1; $isetContentId($contentIdList[$pick]) + ->setProductId($productId) + ->setPosition($i) + ->save(); + } + + //associate PSE and stocks to products + $pse_count = rand(1, 7); + for ($pse_idx=0; $pse_idx<$pse_count; $pse_idx++) { + $stock = new \Thelia\Model\ProductSaleElements(); + $stock->setProductId($productId); + $stock->setRef($productId . '_' . $pse_idx . '_' . $faker->randomNumber(8)); + $stock->setQuantity($faker->numberBetween(1, 50)); + $stock->setPromo($faker->numberBetween(0, 1)); + $stock->setNewness($faker->numberBetween(0, 1)); + $stock->setWeight($faker->randomFloat(2, 1, 5)); + $stock->setIsDefault($pse_idx == 0 ? true : false); + $stock->setEanCode(substr(str_shuffle("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"), 0, 13)); + $stock->save(); + + // associate document to virtual product + if (array_key_exists($productId, $virtualProductList)) { + $virtualDocument = new \Thelia\Model\MetaData(); + $virtualDocument + ->setMetaKey('virtual') + ->setElementKey(\Thelia\Model\MetaData::PSE_KEY) + ->setElementId($stock->getId()) + ->setValue($virtualProductList[$productId]) + ->save(); + } + + $price = $faker->randomFloat(2, 20, 250); + $promoPrice = $price * $faker->randomFloat(2, 0, 1); + + $productPrice = new \Thelia\Model\ProductPrice(); + $productPrice->setProductSaleElements($stock); + $productPrice->setCurrency($currency); + $productPrice->setPrice($price); + $productPrice->setPromoPrice($promoPrice); + $productPrice->save(); + + //associate attributes - or not - to PSE + + $alreadyPicked = array(); + $minAttrCount = $pse_count == 1 ? 0 : 1; + + for ($attrIdx=0; $attrIdxsetAttributeId($pick) + ->setAttributeAvId($attributeList[$pick][array_rand($attributeList[$pick], 1)]) + ->setProductSaleElements($stock) + ->save(); + } + } + + //associate features to products + $freeTextCreated = false; + foreach ($featureList as $featureId => $featureAvId) { + $featureProduct = new Thelia\Model\FeatureProduct(); + $featureProduct->setProductId($productId) + ->setFeatureId($featureId); + + if ($freeTextCreated === false && count($featureAvId) === 0) { //set one feature as free text + $featureAv = new Thelia\Model\FeatureAv(); + $featureAv->setFeatureId($featureId); + $featureAv->setPosition(1); + setI18n($featureAv); + $featureAv->save(); + + $featureProduct->setFeatureAvId($featureAv->getId()); + $featureProduct->setIsFreeText(true); + $freeTextCreated = true; + } elseif (count($featureAvId) > 0) { //got some av + $featureProduct->setFeatureAvId( + $featureAvId[array_rand($featureAvId, 1)] + ); + } else { //no av : no featureProduct + continue; + } + + $featureProduct->save(); + } + } + + echo "Creating orders\n"; + + $colissimo_id = ModuleQuery::create()-> + filterByCode("Colissimo") + ->findOne() + ->getId(); + + $cheque_id = ModuleQuery::create() + ->filterByCode("Cheque") + ->findOne() + ->getId(); + + for ($i=0; $i < 50; ++$i) { + $placedOrder = new \Thelia\Model\Order(); + $country = getRandomCountry(); + + $deliveryOrderAddress = new OrderAddress(); + $deliveryOrderAddress + ->setCustomerTitleId(mt_rand(1, 3)) + ->setCompany(getRealText(15)) + ->setFirstname($faker->firstname) + ->setLastname($faker->lastname) + ->setAddress1($faker->streetAddress) + ->setAddress2($faker->streetAddress) + ->setAddress3($faker->streetAddress) + ->setPhone($faker->phoneNumber) + ->setZipcode($faker->postcode) + ->setCity($faker->city) + ->setCountryId($country[0]) + ->setStateId($country[1]) + ->save($con) + ; + + $invoiceOrderAddress = new OrderAddress(); + $invoiceOrderAddress + ->setCustomerTitleId(mt_rand(1, 3)) + ->setCompany(getRealText(15)) + ->setFirstname($faker->firstname) + ->setLastname($faker->lastname) + ->setAddress1($faker->streetAddress) + ->setAddress2($faker->streetAddress) + ->setAddress3($faker->streetAddress) + ->setPhone($faker->phoneNumber) + ->setZipcode($faker->postcode) + ->setCity($faker->city) + ->setCountryId($country[0]) + ->setStateId($country[1]) + ->save($con) + ; + + /** + * Create a cart for the order + */ + $cart = new \Thelia\Model\Cart(); + $cart->save(); + + $currency = \Thelia\Model\CurrencyQuery::create() + ->addAscendingOrderByColumn('RAND()') + ->findOne(); + + $placedOrder + ->setDeliveryOrderAddressId($deliveryOrderAddress->getId()) + ->setInvoiceOrderAddressId($invoiceOrderAddress->getId()) + ->setDeliveryModuleId($colissimo_id) + ->setPaymentModuleId($cheque_id) + ->setStatusId(mt_rand(1, 5)) + ->setCurrencyRate($currency->getRate()) + ->setCurrencyId($currency->getId()) + ->setCustomer( + \Thelia\Model\CustomerQuery::create() + ->addAscendingOrderByColumn('RAND()') + ->findOne() + ) + ->setDiscount(mt_rand(0, 10)) + ->setLang( + \Thelia\Model\LangQuery::create() + ->addAscendingOrderByColumn('RAND()') + ->findOne() + ) + ->setPostage(mt_rand(1, 50)) + ->setCartId($cart->getId()) + ; + + $placedOrder->save($con); + + for ($j=0; $j < mt_rand(1, 10); ++$j) { + $pse = \Thelia\Model\ProductSaleElementsQuery::create() + ->addAscendingOrderByColumn('RAND()') + ->findOne(); + + $product = $pse->getProduct(); + + $orderProduct = new \Thelia\Model\OrderProduct(); + + $orderProduct + ->setOrderId($placedOrder->getId()) + ->setProductRef($product->getRef()) + ->setProductSaleElementsRef($pse->getRef()) + ->setProductSaleElementsId($pse->getId()) + ->setTitle($product->getTitle()) + ->setChapo($product->getChapo()) + ->setDescription($product->getDescription()) + ->setPostscriptum($product->getPostscriptum()) + ->setQuantity(mt_rand(1, 10)) + ->setPrice($price=mt_rand(1, 100)) + ->setPromoPrice(mt_rand(1, $price)) + ->setWasNew($pse->getNewness()) + ->setWasInPromo(rand(0, 1) == 1) + ->setWeight($pse->getWeight()) + ->setTaxRuleTitle(getRealText(20)) + ->setTaxRuleDescription(getRealText(50)) + ->setEanCode($pse->getEanCode()) + ->save($con); + } + + } + + echo "Generating coupons fixtures\n"; + + generateCouponFixtures($thelia); + + echo "Generating sales\n"; + + for($idx = 1; $idx <= 5; $idx++) { + + $sale = new \Thelia\Model\Sale(); + + $start = new \DateTime(); + $end = new \DateTime(); + + $sale + ->setActive(0) + ->setStartDate($start->setTimestamp(strtotime("today - 1 month"))) + ->setEndDate($end->setTimestamp(strtotime("today + 1 month"))) + ->setPriceOffsetType(\Thelia\Model\Sale::OFFSET_TYPE_PERCENTAGE) + ->setDisplayInitialPrice(true) + ; + + setI18n($sale, [ + 'SaleLabel' => 20, 'Title' => 20, 'Chapo' => 30, 'Postscriptum' => 30, 'Description' => 50 + ]); + + $sale->save(); + + $currencies = \Thelia\Model\CurrencyQuery::create()->find(); + + foreach($currencies as $currency) { + $saleOffset = new \Thelia\Model\SaleOffsetCurrency(); + + $saleOffset + ->setCurrencyId($currency->getId()) + ->setSaleId($sale->getId()) + ->setPriceOffsetValue($faker->numberBetween(10, 70)) + ->save() + ; + } + + $products = \Thelia\Model\ProductQuery::create()->addAscendingOrderByColumn('RAND()')->find(); + + $count = $faker->numberBetween(5, 20); + + foreach ($products as $product) { + + if ( --$count < 0) break; + + $saleProduct = new \Thelia\Model\SaleProduct(); + + $saleProduct + ->setSaleId($sale->getId()) + ->setProductId($product->getId()) + ->setAttributeAvId(null) + ->save(); + ; + } + } + + $con->commit(); + + echo "Successfully terminated.\n"; + +} catch (Exception $e) { + echo "error : ".$e->getMessage()."\n"; + if ($e->getPrevious()) echo "Cause: ".$e->getPrevious()->getMessage()."\n"; + echo $e->getTraceAsString(); + + $con->rollBack(); +} + +function createProduct($faker, Thelia\Model\Category $category, $position, $template, $brandIdList, &$productIdList, &$virtualProductList) +{ + $product = new Thelia\Model\Product(); + $product->setRef($category->getId() . '_' . $position . '_' . $faker->randomNumber(8)); + $product->addCategory($category); + $product->setVisible(1); + $productCategories = $product->getProductCategories(); + $collection = new \Propel\Runtime\Collection\Collection(); + $collection->prepend($productCategories[0]->setDefaultCategory(1)); + $product->setProductCategories($collection); + $product->setVirtual((mt_rand(1, 5) > 1) ? 0 : 1); + $product->setVisible(1); + $product->setPosition($position); + $product->setTaxRuleId(1); + $product->setTemplate($template); + $product->setBrandId($brandIdList[array_rand($brandIdList, 1)]); + + setI18n($product); + + $product->save(); + $productId = $product->getId(); + $productIdList[] = $productId; + + $image = new \Thelia\Model\ProductImage(); + $image->setProductId($productId); + generate_image($image, 'product', $productId); + + $document = new \Thelia\Model\ProductDocument(); + $document->setProductId($productId); + generate_document($document, 'product', $productId); + + if ($product->getVirtual() == 1){ + $virtualProductList[$productId] = $document->getId(); + } + + return $product; +} + +function createCategory($faker, $parent, $position, &$categoryIdList, $contentIdList) +{ + $category = new Thelia\Model\Category(); + $category->setParent($parent); + $category->setVisible(1); + $category->setPosition($position); + setI18n($category); + + $category->save(); + $categoryId = $category->getId(); + $categoryIdList[] = $categoryId; + + //add random associated content + $alreadyPicked = array(); + for ($i=1; $isetContentId($contentIdList[$pick]) + ->setCategoryId($categoryId) + ->setPosition($i) + ->save(); + } + + $image = new \Thelia\Model\CategoryImage(); + $image->setCategoryId($categoryId); + generate_image($image, 'category', $categoryId); + + $document = new \Thelia\Model\CategoryDocument(); + $document->setCategoryId($categoryId); + generate_document($document, 'category', $categoryId); + + return $category; +} + +function generate_image($image, $typeobj, $id) +{ + global $faker; + + $image + ->setTitle(getRealText(20)) + ->setDescription(getRealText(250)) + ->setChapo(getRealText(40)) + ->setPostscriptum(getRealText(40)) + ->setFile(sprintf("sample-image-%s.png", $id)) + ->save() + ; + + $palette = new \Imagine\Image\Palette\RGB(); + + // Generate images + $imagine = new Imagine\Gd\Imagine(); + $image = $imagine->create(new Imagine\Image\Box(320, 240), $palette->color('#E9730F')); + + $white = $palette->color('#FFF'); + + $font = $imagine->font(__DIR__.'/faker-assets/FreeSans.ttf', 14, $white); + + $tbox = $font->box("THELIA"); + $image->draw()->text("THELIA", $font, new Imagine\Image\Point((320 - $tbox->getWidth()) / 2, 30)); + + $str = sprintf("%s sample image", ucfirst($typeobj)); + $tbox = $font->box($str); + $image->draw()->text($str, $font, new Imagine\Image\Point((320 - $tbox->getWidth()) / 2, 80)); + + $font = $imagine->font(__DIR__.'/faker-assets/FreeSans.ttf', 18, $white); + + $str = sprintf("%s ID %d", strtoupper($typeobj), $id); + $tbox = $font->box($str); + $image->draw()->text($str, $font, new Imagine\Image\Point((320 - $tbox->getWidth()) / 2, 180)); + + $image->draw() + ->line(new Imagine\Image\Point(0, 0), new Imagine\Image\Point(319, 0), $white) + ->line(new Imagine\Image\Point(319, 0), new Imagine\Image\Point(319, 239), $white) + ->line(new Imagine\Image\Point(319, 239), new Imagine\Image\Point(0,239), $white) + ->line(new Imagine\Image\Point(0, 239), new Imagine\Image\Point(0, 0), $white) + ; + + $image_file = sprintf("%smedia/images/%s/sample-image-%s.png", THELIA_LOCAL_DIR, $typeobj, $id); + + if (! is_dir(dirname($image_file))) mkdir(dirname($image_file), 0777, true); + + $image->save($image_file); +} + +function generate_document($document, $typeobj, $id) +{ + global $faker; + + $document + ->setTitle(getRealText(20)) + ->setDescription(getRealText(250)) + ->setChapo(getRealText(40)) + ->setPostscriptum(getRealText(40)) + ->setFile(sprintf("sample-document-%s.txt", $id)) + ->save() + ; + + $document_file = sprintf("%smedia/documents/%s/sample-document-%s.txt", THELIA_LOCAL_DIR, $typeobj, $id); + + if (! is_dir(dirname($document_file))) mkdir(dirname($document_file), 0777, true); + + file_put_contents($document_file, getRealText(256)); +} + +function getRealText($length, $locale = 'en_US') { + global $localizedFaker, $realTextMode; + + if ($realTextMode) { + $text = $localizedFaker[$locale]->realText($length); + + // Below 20 chars, generate a simple text, without ponctuation nor newlines. + if ($length <= 20) + $text = ucfirst(strtolower(preg_replace("/[^\pL\pM\pN\ ]/", '', $text))); + } else { + $text = $localizedFaker[$locale]->text($length); + } + + // echo "Generated $locale text ($length) : $locale:$text\n"; + + return "$locale:$text"; +} + +function setI18n(&$object, $fields = array('Title' => 20, 'Chapo' => 30, 'Postscriptum' => 30, 'Description' => 50) ) +{ + global $localeList, $localizedFaker; + + foreach ($localeList as $locale) { + + $object->setLocale($locale); + + foreach ($fields as $name => $length) { + $func = "set".ucfirst(strtolower($name)); + + $object->$func(getRealText($length, $locale)); + } + } +} +/** + * Generate Coupon fixtures + */ +function generateCouponFixtures(\Thelia\Core\Thelia $thelia) +{ + /** @var $container ContainerInterface Service Container */ + $container = $thelia->getContainer(); + /** @var FacadeInterface $adapter */ + $adapter = $container->get('thelia.facade'); + + // Coupons + $coupon1 = new Thelia\Model\Coupon(); + $coupon1->setCode('XMAS'); + $coupon1->setType('thelia.coupon.type.remove_x_amount'); + $coupon1->setTitle('Christmas coupon'); + $coupon1->setShortDescription('Coupon for Christmas removing 10€ if your total checkout is more than 40€'); + $coupon1->setDescription('Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras at luctus tellus. Integer turpis mauris, aliquet vitae risus tristique, pellentesque vestibulum urna. Vestibulum sodales laoreet lectus dictum suscipit. Praesent vulputate, sem id varius condimentum, quam magna tempor elit, quis venenatis ligula nulla eget libero. Cras egestas euismod tellus, id pharetra leo suscipit quis. Donec lacinia ac lacus et ultricies. Nunc in porttitor neque. Proin at quam congue, consectetur orci sed, congue nulla. Nulla eleifend nunc ligula, nec pharetra elit tempus quis. Vivamus vel mauris sed est dictum blandit. Maecenas blandit dapibus velit ut sollicitudin. In in euismod mauris, consequat viverra magna. Cras velit velit, sollicitudin commodo tortor gravida, tempus varius nulla. + +Donec rhoncus leo mauris, id porttitor ante luctus tempus. Curabitur quis augue feugiat, ullamcorper mauris ac, interdum mi. Quisque aliquam lorem vitae felis lobortis, id interdum turpis mattis. Vestibulum diam massa, ornare congue blandit quis, facilisis at nisl. In tortor metus, venenatis non arcu nec, sollicitudin ornare nisl. Nunc erat risus, varius nec urna at, iaculis lacinia elit. Aenean ut felis tempus, tincidunt odio non, sagittis nisl. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Donec vitae hendrerit elit. Nunc sit amet gravida risus, euismod lobortis massa. Nam a erat mauris. Nam a malesuada lorem. Nulla id accumsan dolor, sed rhoncus tellus. Quisque dictum felis sed leo auctor, at volutpat lectus viverra. Morbi rutrum, est ac aliquam imperdiet, nibh sem sagittis justo, ac mattis magna lacus eu nulla. + +Duis interdum lectus nulla, nec pellentesque sapien condimentum at. Suspendisse potenti. Sed eu purus tellus. Nunc quis rhoncus metus. Fusce vitae tellus enim. Interdum et malesuada fames ac ante ipsum primis in faucibus. Etiam tempor porttitor erat vitae iaculis. Sed est elit, consequat non ornare vitae, vehicula eget lectus. Etiam consequat sapien mauris, eget consectetur magna imperdiet eget. Nunc sollicitudin luctus velit, in commodo nulla adipiscing fermentum. Fusce nisi sapien, posuere vitae metus sit amet, facilisis sollicitudin dui. Fusce ultricies auctor enim sit amet iaculis. Morbi at vestibulum enim, eget adipiscing eros. + +Praesent ligula lorem, faucibus ut metus quis, fermentum iaculis erat. Pellentesque elit erat, lacinia sed semper ac, sagittis vel elit. Nam eu convallis est. Curabitur rhoncus odio vitae consectetur pellentesque. Nam vitae arcu nec ante scelerisque dignissim vel nec neque. Suspendisse augue nulla, mollis eget dui et, tempor facilisis erat. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi ac diam ipsum. Donec convallis dui ultricies velit auctor, non lobortis nulla ultrices. Morbi vitae dignissim ante, sit amet lobortis tortor. Nunc dapibus condimentum augue, in molestie neque congue non. + +Sed facilisis pellentesque nisl, eu tincidunt erat scelerisque a. Nullam malesuada tortor vel erat volutpat tincidunt. In vehicula diam est, a convallis eros scelerisque ut. Donec aliquet venenatis iaculis. Ut a arcu gravida, placerat dui eu, iaculis nisl. Quisque adipiscing orci sit amet dui dignissim lacinia. Sed vulputate lorem non dolor adipiscing ornare. Morbi ornare id nisl id aliquam. Ut fringilla elit ante, nec lacinia enim fermentum sit amet. Aenean rutrum lorem eu convallis pharetra. Cras malesuada varius metus, vitae gravida velit. Nam a varius ipsum, ac commodo dolor. Phasellus nec elementum elit. Etiam vel adipiscing leo.'); + $coupon1->setEffects(array( + RemoveXAmount::AMOUNT_FIELD_NAME => 10.00, + )); + $coupon1->setIsUsed(true); + $coupon1->setIsEnabled(true); + $date = new \DateTime(); + $coupon1->setExpirationDate($date->setTimestamp(strtotime("today + 3 months"))); + + $condition1 = new MatchForTotalAmount($adapter); + $operators = array( + MatchForTotalAmount::CART_TOTAL => Operators::SUPERIOR, + MatchForTotalAmount::CART_CURRENCY => Operators::EQUAL + ); + $values = array( + MatchForTotalAmount::CART_TOTAL => 40.00, + MatchForTotalAmount::CART_CURRENCY => 'EUR' + ); + $condition1->setValidatorsFromForm($operators, $values); + + $condition2 = new MatchForTotalAmount($adapter); + $operators = array( + MatchForTotalAmount::CART_TOTAL => Operators::INFERIOR, + MatchForTotalAmount::CART_CURRENCY => Operators::EQUAL + ); + $values = array( + MatchForTotalAmount::CART_TOTAL => 400.00, + MatchForTotalAmount::CART_CURRENCY => 'EUR' + ); + $condition2->setValidatorsFromForm($operators, $values); + + $conditions = new ConditionCollection(); + $conditions[] = $condition1; + $conditions[] = $condition2; + /** @var ConditionFactory $conditionFactory */ + $conditionFactory = $container->get('thelia.condition.factory'); + + $serializedConditions = $conditionFactory->serializeConditionCollection($conditions); + $coupon1->setSerializedConditions($serializedConditions); + $coupon1->setMaxUsage(40); + $coupon1->setIsCumulative(true); + $coupon1->setIsRemovingPostage(false); + $coupon1->setIsAvailableOnSpecialOffers(true); + $coupon1->setPerCustomerUsageCount(false); + $coupon1->save(); + + // Coupons + $coupon2 = new Thelia\Model\Coupon(); + $coupon2->setCode('SPRINGBREAK'); + $coupon2->setType('thelia.coupon.type.remove_x_percent'); + $coupon2->setTitle('Springbreak coupon'); + $coupon2->setShortDescription('Coupon for Springbreak removing 10% if you have more than 4 articles in your cart'); + $coupon2->setDescription('Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras at luctus tellus. Integer turpis mauris, aliquet vitae risus tristique, pellentesque vestibulum urna. Vestibulum sodales laoreet lectus dictum suscipit. Praesent vulputate, sem id varius condimentum, quam magna tempor elit, quis venenatis ligula nulla eget libero. Cras egestas euismod tellus, id pharetra leo suscipit quis. Donec lacinia ac lacus et ultricies. Nunc in porttitor neque. Proin at quam congue, consectetur orci sed, congue nulla. Nulla eleifend nunc ligula, nec pharetra elit tempus quis. Vivamus vel mauris sed est dictum blandit. Maecenas blandit dapibus velit ut sollicitudin. In in euismod mauris, consequat viverra magna. Cras velit velit, sollicitudin commodo tortor gravida, tempus varius nulla. + +Donec rhoncus leo mauris, id porttitor ante luctus tempus. Curabitur quis augue feugiat, ullamcorper mauris ac, interdum mi. Quisque aliquam lorem vitae felis lobortis, id interdum turpis mattis. Vestibulum diam massa, ornare congue blandit quis, facilisis at nisl. In tortor metus, venenatis non arcu nec, sollicitudin ornare nisl. Nunc erat risus, varius nec urna at, iaculis lacinia elit. Aenean ut felis tempus, tincidunt odio non, sagittis nisl. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Donec vitae hendrerit elit. Nunc sit amet gravida risus, euismod lobortis massa. Nam a erat mauris. Nam a malesuada lorem. Nulla id accumsan dolor, sed rhoncus tellus. Quisque dictum felis sed leo auctor, at volutpat lectus viverra. Morbi rutrum, est ac aliquam imperdiet, nibh sem sagittis justo, ac mattis magna lacus eu nulla. + +Duis interdum lectus nulla, nec pellentesque sapien condimentum at. Suspendisse potenti. Sed eu purus tellus. Nunc quis rhoncus metus. Fusce vitae tellus enim. Interdum et malesuada fames ac ante ipsum primis in faucibus. Etiam tempor porttitor erat vitae iaculis. Sed est elit, consequat non ornare vitae, vehicula eget lectus. Etiam consequat sapien mauris, eget consectetur magna imperdiet eget. Nunc sollicitudin luctus velit, in commodo nulla adipiscing fermentum. Fusce nisi sapien, posuere vitae metus sit amet, facilisis sollicitudin dui. Fusce ultricies auctor enim sit amet iaculis. Morbi at vestibulum enim, eget adipiscing eros. + +Praesent ligula lorem, faucibus ut metus quis, fermentum iaculis erat. Pellentesque elit erat, lacinia sed semper ac, sagittis vel elit. Nam eu convallis est. Curabitur rhoncus odio vitae consectetur pellentesque. Nam vitae arcu nec ante scelerisque dignissim vel nec neque. Suspendisse augue nulla, mollis eget dui et, tempor facilisis erat. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi ac diam ipsum. Donec convallis dui ultricies velit auctor, non lobortis nulla ultrices. Morbi vitae dignissim ante, sit amet lobortis tortor. Nunc dapibus condimentum augue, in molestie neque congue non. + +Sed facilisis pellentesque nisl, eu tincidunt erat scelerisque a. Nullam malesuada tortor vel erat volutpat tincidunt. In vehicula diam est, a convallis eros scelerisque ut. Donec aliquet venenatis iaculis. Ut a arcu gravida, placerat dui eu, iaculis nisl. Quisque adipiscing orci sit amet dui dignissim lacinia. Sed vulputate lorem non dolor adipiscing ornare. Morbi ornare id nisl id aliquam. Ut fringilla elit ante, nec lacinia enim fermentum sit amet. Aenean rutrum lorem eu convallis pharetra. Cras malesuada varius metus, vitae gravida velit. Nam a varius ipsum, ac commodo dolor. Phasellus nec elementum elit. Etiam vel adipiscing leo.'); + $coupon2->setEffects(array( + RemoveXPercent::INPUT_PERCENTAGE_NAME => 10.00 + )); + $coupon2->setIsUsed(true); + $coupon2->setIsEnabled(true); + $date = new \DateTime(); + $coupon2->setExpirationDate($date->setTimestamp(strtotime("today + 1 months"))); + + $condition1 = new MatchForXArticles($adapter); + $operators = array( + MatchForXArticles::CART_QUANTITY => Operators::SUPERIOR, + ); + $values = array( + MatchForXArticles::CART_QUANTITY => 4, + ); + $condition1->setValidatorsFromForm($operators, $values); + $conditions = new ConditionCollection(); + $conditions[] = $condition1; + + /** @var ConditionFactory $conditionFactory */ + $conditionFactory = $container->get('thelia.condition.factory'); + + $serializedConditions = $conditionFactory->serializeConditionCollection($conditions); + $coupon2->setSerializedConditions($serializedConditions); + $coupon2->setMaxUsage(-1); + $coupon2->setIsCumulative(false); + $coupon2->setIsRemovingPostage(true); + $coupon2->setIsAvailableOnSpecialOffers(true); + $coupon2->setPerCustomerUsageCount(false); + $coupon2->save(); + + // Coupons + $coupon3 = new Thelia\Model\Coupon(); + $coupon3->setCode('OLD'); + $coupon3->setType('thelia.coupon.type.remove_x_percent'); + $coupon3->setTitle('Old coupon'); + $coupon3->setShortDescription('Coupon for Springbreak removing 10% if you have more than 4 articles in your cart'); + $coupon3->setDescription('Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras at luctus tellus. Integer turpis mauris, aliquet vitae risus tristique, pellentesque vestibulum urna. Vestibulum sodales laoreet lectus dictum suscipit. Praesent vulputate, sem id varius condimentum, quam magna tempor elit, quis venenatis ligula nulla eget libero. Cras egestas euismod tellus, id pharetra leo suscipit quis. Donec lacinia ac lacus et ultricies. Nunc in porttitor neque. Proin at quam congue, consectetur orci sed, congue nulla. Nulla eleifend nunc ligula, nec pharetra elit tempus quis. Vivamus vel mauris sed est dictum blandit. Maecenas blandit dapibus velit ut sollicitudin. In in euismod mauris, consequat viverra magna. Cras velit velit, sollicitudin commodo tortor gravida, tempus varius nulla. + +Donec rhoncus leo mauris, id porttitor ante luctus tempus. Curabitur quis augue feugiat, ullamcorper mauris ac, interdum mi. Quisque aliquam lorem vitae felis lobortis, id interdum turpis mattis. Vestibulum diam massa, ornare congue blandit quis, facilisis at nisl. In tortor metus, venenatis non arcu nec, sollicitudin ornare nisl. Nunc erat risus, varius nec urna at, iaculis lacinia elit. Aenean ut felis tempus, tincidunt odio non, sagittis nisl. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Donec vitae hendrerit elit. Nunc sit amet gravida risus, euismod lobortis massa. Nam a erat mauris. Nam a malesuada lorem. Nulla id accumsan dolor, sed rhoncus tellus. Quisque dictum felis sed leo auctor, at volutpat lectus viverra. Morbi rutrum, est ac aliquam imperdiet, nibh sem sagittis justo, ac mattis magna lacus eu nulla. + +Duis interdum lectus nulla, nec pellentesque sapien condimentum at. Suspendisse potenti. Sed eu purus tellus. Nunc quis rhoncus metus. Fusce vitae tellus enim. Interdum et malesuada fames ac ante ipsum primis in faucibus. Etiam tempor porttitor erat vitae iaculis. Sed est elit, consequat non ornare vitae, vehicula eget lectus. Etiam consequat sapien mauris, eget consectetur magna imperdiet eget. Nunc sollicitudin luctus velit, in commodo nulla adipiscing fermentum. Fusce nisi sapien, posuere vitae metus sit amet, facilisis sollicitudin dui. Fusce ultricies auctor enim sit amet iaculis. Morbi at vestibulum enim, eget adipiscing eros. + +Praesent ligula lorem, faucibus ut metus quis, fermentum iaculis erat. Pellentesque elit erat, lacinia sed semper ac, sagittis vel elit. Nam eu convallis est. Curabitur rhoncus odio vitae consectetur pellentesque. Nam vitae arcu nec ante scelerisque dignissim vel nec neque. Suspendisse augue nulla, mollis eget dui et, tempor facilisis erat. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi ac diam ipsum. Donec convallis dui ultricies velit auctor, non lobortis nulla ultrices. Morbi vitae dignissim ante, sit amet lobortis tortor. Nunc dapibus condimentum augue, in molestie neque congue non. + +Sed facilisis pellentesque nisl, eu tincidunt erat scelerisque a. Nullam malesuada tortor vel erat volutpat tincidunt. In vehicula diam est, a convallis eros scelerisque ut. Donec aliquet venenatis iaculis. Ut a arcu gravida, placerat dui eu, iaculis nisl. Quisque adipiscing orci sit amet dui dignissim lacinia. Sed vulputate lorem non dolor adipiscing ornare. Morbi ornare id nisl id aliquam. Ut fringilla elit ante, nec lacinia enim fermentum sit amet. Aenean rutrum lorem eu convallis pharetra. Cras malesuada varius metus, vitae gravida velit. Nam a varius ipsum, ac commodo dolor. Phasellus nec elementum elit. Etiam vel adipiscing leo.'); + $coupon3->setEffects(array( + RemoveXPercent::INPUT_PERCENTAGE_NAME => 10.00, + )); + $coupon3->setIsUsed(false); + $coupon3->setIsEnabled(false); + $date = new \DateTime(); + $coupon3->setExpirationDate($date->setTimestamp(strtotime("today + 2 months"))); + + $condition1 = new MatchForEveryone($adapter); + $operators = array(); + $values = array(); + $condition1->setValidatorsFromForm($operators, $values); + $conditions = new ConditionCollection(); + $conditions[] = $condition1; + + /** @var ConditionFactory $constraintCondition */ + $constraintCondition = $container->get('thelia.condition.factory'); + + $serializedConditions = $constraintCondition->serializeConditionCollection($conditions); + $coupon3->setSerializedConditions($serializedConditions); + $coupon3->setMaxUsage(-1); + $coupon3->setIsCumulative(true); + $coupon3->setIsRemovingPostage(false); + $coupon3->setIsAvailableOnSpecialOffers(false); + $coupon3->setPerCustomerUsageCount(false); + $coupon3->save(); +} + +/** + * get a random country and state + * + * @return array first row is the country id, second row is the state id or null + */ +function getRandomCountry() +{ + global $countryStateList; + + if (count($countryStateList) === 0) { + $countryStateList = CountryQuery::create() + ->joinState('State', \Propel\Runtime\ActiveQuery\Criteria::LEFT_JOIN) + ->select(['Id', 'State.Id']) + ->find() + ->toArray() + ; + $countryStateList = array_map( + function ($item) { + return [$item['Id'], $item['State.Id']]; + }, + $countryStateList + ); + } + + return $countryStateList[mt_rand(0, count($countryStateList) - 1)]; +} + +function usage() +{ + $usage = << + +Options: + + -h + Display this message and exit + + -b + Use this bootstrap file + + -c + Maximum number of categories and sub categories to create (default: 20) + + -p + Maximum number of products to create in a category (default: 20) + + -l + The list of locales (separated with a ,) for which to generate content (default: fr_FR, en_US, es_ES, it_IT, de_DE) + + -r + Use real text or not. real text mode is much more slower than false text mode. + 0 : false text mode + 1 : real text mode (default) + +Examples: + + Generate content in english and french with false text for 5 categories and 10 products + + php faker.php -r 0 -c 5 -p 10 -l 'fr_FR, en_US' + +USAGE; + + echo $usage; +} diff --git a/setup/faker_100categories_1000products_4locales.php b/setup/faker_100categories_1000products_4locales.php new file mode 100644 index 00000000..96a21198 --- /dev/null +++ b/setup/faker_100categories_1000products_4locales.php @@ -0,0 +1,200 @@ +beginTransaction(); + +$currency = \Thelia\Model\CurrencyQuery::create()->filterByCode('EUR')->findOne(); + +try { + $stmt = $con->prepare("SET foreign_key_checks = 0"); + $stmt->execute(); + + $productAssociatedContent = Thelia\Model\ProductAssociatedContentQuery::create() + ->find(); + $productAssociatedContent->delete(); + + $categoryAssociatedContent = Thelia\Model\CategoryAssociatedContentQuery::create() + ->find(); + $categoryAssociatedContent->delete(); + + $attributeCategory = Thelia\Model\AttributeCategoryQuery::create() + ->find(); + $attributeCategory->delete(); + + $featureCategory = Thelia\Model\FeatureCategoryQuery::create() + ->find(); + $featureCategory->delete(); + + $featureProduct = Thelia\Model\FeatureProductQuery::create() + ->find(); + $featureProduct->delete(); + + $attributeCombination = Thelia\Model\AttributeCombinationQuery::create() + ->find(); + $attributeCombination->delete(); + + $feature = Thelia\Model\FeatureQuery::create() + ->find(); + $feature->delete(); + + $feature = Thelia\Model\FeatureI18nQuery::create() + ->find(); + $feature->delete(); + + $featureAv = Thelia\Model\FeatureAvQuery::create() + ->find(); + $featureAv->delete(); + + $featureAv = Thelia\Model\FeatureAvI18nQuery::create() + ->find(); + $featureAv->delete(); + + $attribute = Thelia\Model\AttributeQuery::create() + ->find(); + $attribute->delete(); + + $attribute = Thelia\Model\AttributeI18nQuery::create() + ->find(); + $attribute->delete(); + + $attributeAv = Thelia\Model\AttributeAvQuery::create() + ->find(); + $attributeAv->delete(); + + $attributeAv = Thelia\Model\AttributeAvI18nQuery::create() + ->find(); + $attributeAv->delete(); + + $category = Thelia\Model\CategoryQuery::create() + ->find(); + $category->delete(); + + $category = Thelia\Model\CategoryI18nQuery::create() + ->find(); + $category->delete(); + + $product = Thelia\Model\ProductQuery::create() + ->find(); + $product->delete(); + + $product = Thelia\Model\ProductI18nQuery::create() + ->find(); + $product->delete(); + + $customer = Thelia\Model\CustomerQuery::create() + ->find(); + $customer->delete(); + + $folder = Thelia\Model\FolderQuery::create() + ->find(); + $folder->delete(); + + $folder = Thelia\Model\FolderI18nQuery::create() + ->find(); + $folder->delete(); + + $content = Thelia\Model\ContentQuery::create() + ->find(); + $content->delete(); + + $content = Thelia\Model\ContentI18nQuery::create() + ->find(); + $content->delete(); + + $accessory = Thelia\Model\AccessoryQuery::create() + ->find(); + $accessory->delete(); + + $stock = \Thelia\Model\ProductSaleElementsQuery::create() + ->find(); + $stock->delete(); + + $productPrice = \Thelia\Model\ProductPriceQuery::create() + ->find(); + $productPrice->delete(); + + $stmt = $con->prepare("SET foreign_key_checks = 1"); + $stmt->execute(); + + //categories and products + for ($i=0; $i<100; $i++) { + $category = new Thelia\Model\Category(); + $category->setParent(0); + $category->setVisible(1); + $category->setPosition($i); + setI18n($faker, $category); + + $category->save(); + + for ($j=0; $j<10; $j++) { + $product = new Thelia\Model\Product(); + $product->setRef($category->getId() . '_' . $j . '_' . $faker->randomNumber(8)); + $product->addCategory($category); + $product->setVisible(1); + $product->setPosition($j); + setI18n($faker, $product); + + $product->save(); + } + } + + $con->commit(); +} catch (Exception $e) { + echo "error : ".$e->getMessage()."\n"; + $con->rollBack(); +} + +function setI18n($faker, &$object, $fields = array('Title' => 20, 'Description' => 50) ) +{ + $localeList = array('fr_FR', 'en_US', 'es_ES', 'it_IT', 'de_DE'); + + foreach ($localeList as $locale) { + $object->setLocale($locale); + + foreach ($fields as $name => $length) { + $func = "set$name"; + + $object->$func($locale . ' : ' . $faker->text($length)); + } + } +} diff --git a/setup/faker_add_ecotax.php b/setup/faker_add_ecotax.php new file mode 100644 index 00000000..f46ae956 --- /dev/null +++ b/setup/faker_add_ecotax.php @@ -0,0 +1,153 @@ +boot(); + +$faker = Faker\Factory::create(); + +$con = \Propel\Runtime\Propel::getConnection( + Thelia\Model\Map\ProductTableMap::DATABASE_NAME +); +$con->beginTransaction(); + +// Intialize URL management + +try { + $options = getopt('f::e::'); + + $forceEcotaxFeatureId = $options['f']; + if (null !== $forceEcotaxFeatureId && !filter_var($forceEcotaxFeatureId, FILTER_VALIDATE_INT)) { + exit('[ERROR] bad value for f option\n'); + } + + $forceEcotaxId = $options['e']; + if (null !== $forceEcotaxId && !filter_var($forceEcotaxId, FILTER_VALIDATE_INT)) { + exit('[ERROR] bad value for e option\n'); + } + + echo "Adding Ecotax feature\n"; + $feature = null; + if (null !== $forceEcotaxFeatureId) { + $feature = \Thelia\Model\FeatureQuery::create()->findPk($forceEcotaxFeatureId); + if (null === $feature) { + echo "Feature `$forceEcotaxFeatureId` not found\n"; + } + } + if (null === $feature) { + $feature = new \Thelia\Model\Feature(); + $feature->setVisible(1); + $feature->save(); + echo sprintf("Ecotax feature added with ID \n", $feature->getId()); + } + + $fr = \Thelia\Model\Base\FeatureI18nQuery::create() + ->filterByLocale('fr_FR') + ->filterByFeature($feature) + ->findOne(); + if (null === $fr) { + $fr = new \Thelia\Model\FeatureI18n(); + $fr->setLocale('fr_FR') + ->setFeature($feature); + } + $fr->setTitle('Ecotaxe'); + $fr->save($con); + + $us = \Thelia\Model\Base\FeatureI18nQuery::create() + ->filterByLocale('en_US') + ->filterByFeature($feature) + ->findOne(); + if (null === $us) { + $us = new \Thelia\Model\FeatureI18n(); + $us->setLocale('en_US') + ->setFeature($feature); + } + $us->setTitle('Ecotax'); + $us->save($con); + + echo "Adding ecotax\n"; + + $tax = null; + if (null !== $forceEcotaxId) { + $tax = \Thelia\Model\TaxQuery::create()->findPk($forceEcotaxId); + if (null === $tax) { + echo "Tax `$forceEcotaxId` not found\n"; + } + } + if (null === $tax) { + $tax = new \Thelia\Model\Tax(); + $tax->setType('FeatureFixAmountTaxType') + ->setSerializedRequirements( + base64_encode(sprintf('{"feature":%s}', $feature->getId())) + ); + $tax->save(); + echo sprintf("Ecotax added with ID \n", $tax->getId()); + } + + $fr = \Thelia\Model\Base\TaxI18nQuery::create() + ->filterByLocale('fr_FR') + ->filterByTax($tax) + ->findOne(); + if (null === $fr) { + $fr = new \Thelia\Model\TaxI18n(); + $fr->setLocale('fr_FR') + ->setTax($tax); + } + $fr->setTitle('Ecotaxe'); + $fr->save($con); + + $us = \Thelia\Model\Base\TaxI18nQuery::create() + ->filterByLocale('en_US') + ->filterByTax($tax) + ->findOne(); + if (null === $us) { + $us = new \Thelia\Model\TaxI18n(); + $us->setLocale('en_US') + ->setTax($tax); + } + $us->setTitle('Ecotax'); + $us->save($con); + + $con->commit(); + + echo "Successfully terminated.\n"; + +} catch (Exception $e) { + echo "error : ".$e->getMessage()."\n"; + $con->rollBack(); +} diff --git a/setup/import.php b/setup/import.php new file mode 100644 index 00000000..dea33622 --- /dev/null +++ b/setup/import.php @@ -0,0 +1,736 @@ +. */ +/* */ +/*************************************************************************************/ +use Thelia\Model\ContentFolderQuery; +use Thelia\Model\ProductAssociatedContent; + +if (php_sapi_name() != 'cli') { + throw new \Exception('this script can only be launched with cli sapi'); +} + +$bootstrapToggle = false; +$bootstraped = false; + +// Autoload bootstrap + +foreach ($argv as $arg) { + if ($arg === '-b') { + $bootstrapToggle = true; + + continue; + } + + if ($bootstrapToggle) { + require __DIR__ . DIRECTORY_SEPARATOR . $arg; + + $bootstraped = true; + } +} + +if (!$bootstraped) { + if (isset($bootstrapFile)) { + require $bootstrapFile; + } elseif (is_file($file = __DIR__ . '/../core/vendor/autoload.php')) { + require $file; + } elseif (is_file($file = __DIR__ . '/../../bootstrap.php')) { + // Here we are on a thelia/thelia-project + require $file; + } else { + echo "No autoload file found. Please use the -b argument to include yours"; + exit(1); + } +} + +$thelia = new Thelia\Core\Thelia("dev", true); +$thelia->boot(); + +// Load the translator +$thelia->getContainer()->get("thelia.translator"); + +$faker = Faker\Factory::create(); +// Intialize URL management +$url = new Thelia\Tools\URL(); +$con = \Propel\Runtime\Propel::getConnection( + Thelia\Model\Map\ProductTableMap::DATABASE_NAME +); +$con->beginTransaction(); + +try { + $stmt = $con->prepare("SET foreign_key_checks = 0"); + $stmt->execute(); + clearTables($con); + $stmt = $con->prepare("SET foreign_key_checks = 1"); + $stmt->execute(); + + $material = createMaterials($con); + + $color = createColors($con); + $brands = createBrands($faker, $con); + + $folders = createFolders($faker, $con); + $contents = createContents($faker, $folders, $con); + + $categories = createCategories($faker, $con); + + echo "creating templates\n"; + $template = new \Thelia\Model\Template(); + $template + ->setLocale('fr_FR') + ->setName('template de démo') + ->setLocale('en_US') + ->setName('demo template') + ->save($con); + + $at = new Thelia\Model\AttributeTemplate(); + + $at + ->setTemplate($template) + ->setAttribute($color) + ->save($con); + + $ft = new Thelia\Model\FeatureTemplate(); + + $ft + ->setTemplate($template) + ->setFeature($material) + ->save($con); + echo "end creating templates\n"; + + createProduct($faker, $categories, $brands, $contents, $template, $color, $material, $con); + + createCustomer($faker, $con); + + // set some config key + createConfig($faker, $folders, $contents, $con); + + + $con->commit(); +} catch (Exception $e) { + echo "error : ".$e->getMessage()."\n"; + $con->rollBack(); +} + +function createProduct($faker, $categories, $brands, $contents, $template, $attribute, $feature, $con) +{ + echo "start creating products\n"; + $fileSystem = new \Symfony\Component\Filesystem\Filesystem(); + if (($handle = fopen(THELIA_SETUP_DIRECTORY . 'import/products.csv', "r")) !== FALSE) { + $row=0; + while (($data = fgetcsv($handle, 100000, ";")) !== FALSE) { + $row++; + if($row == 1) continue; + $product = new \Thelia\Model\Product(); + + $product + ->setRef($data[0]) + ->setVisible(1) + ->setTaxRuleId(1) + ->setTemplate($template) + ; + + $productCategories = explode(';', $data[15]); + foreach ($productCategories as $productCategory) { + $productCategory = trim($productCategory); + if (array_key_exists($productCategory, $categories)) { + $product->addCategory($categories[$productCategory]); + } + } + + $brand = $data[11]; + if (array_key_exists($brand, $brands)) { + $product->setBrand($brands[$brand]); + } + + $product + ->setLocale('en_US') + ->setTitle($data[1]) + ->setChapo($data[2]) + ->setDescription($data[4]) + ->setPostscriptum($data[6]) + ->setLocale('fr_FR') + ->setTitle($data[1]) + ->setChapo($data[3]) + ->setDescription($data[5]) + ->setPostscriptum($data[7]) + ->save($con); + + $productCategories = $product->getProductCategories()->getFirst(); + $productCategories->setDefaultCategory(true) + ->save($con); + + // Set the position + $product->setPosition($product->getNextPosition())->save($con); + + $images = explode(';', $data[10]); + + foreach ($images as $image) { + $image = trim($image); + if(empty($image)) continue; + $productImage = new \Thelia\Model\ProductImage(); + $productImage + ->setProduct($product) + ->setFile($image) + ->save($con); + $fileSystem->copy(THELIA_SETUP_DIRECTORY . 'import/images/'.$image, THELIA_LOCAL_DIR . 'media/images/product/'.$image, true); + } + + $pses = explode(";", $data[12]); + + foreach ($pses as $pse) { + if(empty($pse)) continue; + $stock = new \Thelia\Model\ProductSaleElements(); + $stock->setProduct($product); + $stock->setRef($product->getId() . '_' . uniqid('', true)); + $stock->setQuantity($faker->numberBetween(1,50)); + if (!empty($data[9])) { + $stock->setPromo(1); + } else { + $stock->setPromo(0); + } + + $stock->setNewness($faker->numberBetween(0,1)); + $stock->setWeight($faker->randomFloat(2, 1,30)); + $stock->save($con); + + $productPrice = new \Thelia\Model\ProductPrice(); + $productPrice->setProductSaleElements($stock); + $productPrice->setCurrencyId(1); + $productPrice->setPrice($data[8]); + $productPrice->setPromoPrice($data[9]); + $productPrice->save($con); + + $attributeAv = \Thelia\Model\AttributeAvI18nQuery::create() + ->filterByLocale('en_US') + ->filterByTitle($pse) + ->findOne($con); + + $attributeCombination = new \Thelia\Model\AttributeCombination(); + $attributeCombination + ->setAttributeId($attribute->getId()) + ->setAttributeAvId($attributeAv->getId()) + ->setProductSaleElements($stock) + ->save($con); + } + + $productSaleElements = $product->getProductSaleElementss()->getFirst(); + $productSaleElements->setIsDefault(1)->save($con); + + // associated content + $associatedContents = explode(";", $data[14]); + foreach ($associatedContents as $associatedContent) { + $content = new ProductAssociatedContent(); + if ( ! array_key_exists($associatedContent, $contents)){ + continue; + } + + $content + ->setProduct($product) + ->setContent($contents[$associatedContent]) + ->save($con) + ; + } + + // feature + $features = explode(";", $data[13]); + + foreach ($features as $aFeature) { + $featurAv = \Thelia\Model\FeatureAvI18nQuery::create() + ->filterByLocale('en_US') + ->filterByTitle($aFeature) + ->findOne($con); + + $featureProduct = new Thelia\Model\FeatureProduct(); + $featureProduct->setProduct($product) + ->setFeatureId($feature->getId()) + ->setFeatureAvId($featurAv->getId()) + ->save($con) + ; + } + } + } + echo "end creating products\n"; +} + +function createConfig($faker, $folders, $contents, $con){ + + // Store + \Thelia\Model\ConfigQuery::write("store_name", "Thelia"); + \Thelia\Model\ConfigQuery::write("store_description", "E-commerce solution based on Symfony 2"); + \Thelia\Model\ConfigQuery::write("store_email", "Thelia"); + \Thelia\Model\ConfigQuery::write("store_address1", "5 rue Rochon"); + \Thelia\Model\ConfigQuery::write("store_city", "Clermont-Ferrrand"); + \Thelia\Model\ConfigQuery::write("store_phone", "+(33)444053102"); + \Thelia\Model\ConfigQuery::write("store_email", "contact@thelia.net"); + // Contents + \Thelia\Model\ConfigQuery::write("information_folder_id", $folders['Information']->getId()); + \Thelia\Model\ConfigQuery::write("terms_conditions_content_id", $contents["Terms and Conditions"]->getId()); +} + +function createCustomer($faker, $con){ + + echo "Creating customer\n"; + + //customer + $customer = new Thelia\Model\Customer(); + $customer->createOrUpdate( + 1, + "thelia", + "thelia", + "5 rue rochon", + "", + "", + "0102030405", + "0601020304", + "63000", + "Clermont-Ferrand", + 64, + "test@thelia.net", + "thelia" + ); + for ($j = 0; $j <= 2; $j++) { + $address = new Thelia\Model\Address(); + $address->setLabel($faker->text(20)) + ->setTitleId(rand(1,3)) + ->setFirstname($faker->firstname) + ->setLastname($faker->lastname) + ->setAddress1($faker->streetAddress) + ->setAddress2($faker->streetAddress) + ->setAddress3($faker->streetAddress) + ->setCellphone($faker->phoneNumber) + ->setPhone($faker->phoneNumber) + ->setZipcode($faker->postcode) + ->setCity($faker->city) + ->setCountryId(64) + ->setCustomer($customer) + ->save($con) + ; + } + + echo "End creating customer\n"; +} + +function createMaterials($con) +{ + echo "start creating materials feature\n"; + + $feature = null; + $features = array(); + + if (($handle = fopen(THELIA_SETUP_DIRECTORY . 'import/materials.csv', "r")) !== FALSE) { + $row=0; + $feature = new \Thelia\Model\Feature(); + $feature + ->setPosition(1) + ->setLocale('fr_FR') + ->setTitle('Matière') + ->setLocale('en_US') + ->setTitle('Material'); + + while (($data = fgetcsv($handle, 1000, ";")) !== FALSE) { + $row++; + $featureAv = new \Thelia\Model\FeatureAv(); + $featureAv + ->setPosition($row) + ->setLocale('fr_FR') + ->setTitle($data[0]) + ->setLocale('en_US') + ->setTitle($data[1]); + //$featureAv->setFeature($feature); + + $feature->addFeatureAv($featureAv); + } + + $feature->save($con); + + fclose($handle); + } + echo "materials feature created successfully\n"; + + return $feature; +} + + +function createBrands($faker, $con) +{ + echo "start creating brands\n"; + + $fileSystem = new \Symfony\Component\Filesystem\Filesystem(); + + $brands = array(); + if (($handle = fopen(THELIA_SETUP_DIRECTORY . 'import/brand.csv', "r")) !== FALSE) { + $row=0; + while (($data = fgetcsv($handle, 1000, ";")) !== FALSE) { + $row++; + if ($row == 1) continue; + + $brand = new \Thelia\Model\Brand(); + + $brand + ->setVisible(1) + ->setPosition($row-1) + ->setLocale('fr_FR') + ->setTitle(trim($data[0])) + ->setChapo($faker->text(20)) + ->setDescription($faker->text(100)) + ->setLocale('en_US') + ->setTitle(trim($data[0])) + ->setChapo($faker->text(20)) + ->setDescription($faker->text(100)) + ->save($con); + + $brands[trim($data[0])] = $brand; + + $images = explode(';', $data[1]); + $logoId = null; + foreach ($images as $image) { + $image = trim($image); + if(empty($image)) continue; + $brandImage = new \Thelia\Model\BrandImage(); + $brandImage + ->setBrandId($brand->getId()) + ->setFile($image) + ->save($con); + if ($logoId === null) { + $logoId = $brandImage->getId(); + } + $fileSystem->copy(THELIA_SETUP_DIRECTORY . 'import/images/'.$image, THELIA_LOCAL_DIR . 'media/images/brand/'.$image, true); + } + + if ($logoId !== null){ + $brand->setLogoImageId($logoId); + $brand->save($con); + } + + } + fclose($handle); + } + echo "brands created successfully\n"; + + return $brands; +} + + +function createCategories($faker, $con) +{ + echo "start creating categories\n"; + $categories = array(); + if (($handle = fopen(THELIA_SETUP_DIRECTORY . 'import/categories.csv', "r")) !== FALSE) { + $row=0; + while (($data = fgetcsv($handle, 1000, ";")) !== FALSE) { + $row++; + if($row==1) continue; + $category = new \Thelia\Model\Category(); + $category + ->setVisible(1) + ->setPosition($row-1) + ->setParent(0) + ->setLocale('fr_FR') + ->setTitle(trim($data[0])) + ->setChapo($faker->text(20)) + ->setDescription($faker->text(100)) + ->setLocale('en_US') + ->setTitle(trim($data[1])) + ->setChapo($faker->text(20)) + ->setDescription($faker->text(100)) + ->save($con); + $categories[trim($data[1])] = $category; + } + fclose($handle); + } + echo "categories created successfully\n"; + + return $categories; +} + +function createFolders($faker, $con) +{ + echo "start creating folders\n"; + + $fileSystem = new \Symfony\Component\Filesystem\Filesystem(); + + $folders = array(); + if (($handle = fopen(THELIA_SETUP_DIRECTORY . 'import/folders.csv', "r")) !== FALSE) { + $row=0; + while (($data = fgetcsv($handle, 1000, ";")) !== FALSE) { + $row++; + if ($row == 1) continue; + + $folder = new \Thelia\Model\Folder(); + + $folder + ->setVisible(1) + ->setPosition($row-1) + ->setLocale('fr_FR') + ->setTitle(trim($data[0])) + ->setChapo($faker->text(20)) + ->setDescription($faker->text(100)) + ->setLocale('en_US') + ->setTitle(trim($data[1])) + ->setChapo($faker->text(20)) + ->setDescription($faker->text(100)) + ->save($con); + + $folders[trim($data[1])] = $folder; + + $images = explode(';', $data[6]); + foreach ($images as $image) { + $image = trim($image); + if(empty($image)) continue; + $folderImage = new \Thelia\Model\FolderImage(); + $folderImage + ->setFolderId($folder->getId()) + ->setFile($image) + ->save($con); + $fileSystem->copy(THELIA_SETUP_DIRECTORY . 'import/images/'.$image, THELIA_LOCAL_DIR . 'media/images/folder/'.$image, true); + } + } + fclose($handle); + } + echo "Folders created successfully\n"; + + return $folders; +} + + +function createContents($faker, $folders, $con) +{ + echo "start creating contents\n"; + + $fileSystem = new \Symfony\Component\Filesystem\Filesystem(); + + $contents = array(); + if (($handle = fopen(THELIA_SETUP_DIRECTORY . 'import/contents.csv', "r")) !== FALSE) { + $row=0; + while (($data = fgetcsv($handle, 1000, ";")) !== FALSE) { + $row++; + if ($row == 1) continue; + + $content = new \Thelia\Model\Content(); + + $content + ->setVisible(1) + ->setPosition($row-1) + ->setLocale('fr_FR') + ->setTitle(trim($data[0])) + ->setChapo($faker->text(20)) + ->setDescription($faker->text(200)) + ->setLocale('en_US') + ->setTitle(trim($data[1])) + ->setChapo($faker->text(20)) + ->setDescription($faker->text(200)); + + // folder + $contentFolders = explode(';', $data[7]); + $defaultFolder = null; + foreach ($contentFolders as $contentFolder) { + $contentFolder = trim($contentFolder); + if (array_key_exists($contentFolder, $folders)) { + $content->addFolder($folders[$contentFolder]); + if (null === $defaultFolder) { + $defaultFolder = $folders[$contentFolder]->getId(); + } + } + } + + $content + ->getContentFolders() + ->getFirst() + ->setDefaultFolder(true) + ->save($con) + ; + + $content->save($con); + + $images = explode(';', $data[6]); + foreach ($images as $image) { + $image = trim($image); + if(empty($image)) continue; + $contentImage = new \Thelia\Model\ContentImage(); + $contentImage + ->setContentId($content->getId()) + ->setFile($image) + ->save($con); + $fileSystem->copy(THELIA_SETUP_DIRECTORY . 'import/images/'.$image, THELIA_LOCAL_DIR . 'media/images/content/'.$image, true); + } + + $contents[trim($data[1])] = $content; + } + fclose($handle); + } + echo "Contents created successfully\n"; + + return $contents; +} + + +function createColors($con) +{ + echo "start creating colors attributes\n"; + if (($handle = fopen(THELIA_SETUP_DIRECTORY . 'import/colors.csv', "r")) !== FALSE) { + $row=0; + $attribute = new \Thelia\Model\Attribute(); + $attribute + ->setPosition(1) + ->setLocale('fr_FR') + ->setTitle('Couleur') + ->setLocale('en_US') + ->setTitle('Colors'); + + while (($data = fgetcsv($handle, 1000, ";")) !== FALSE) { + $row++; + $attributeAv = new \Thelia\Model\AttributeAv(); + $attributeAv + ->setPosition($row) + ->setLocale('fr_FR') + ->setTitle($data[0]) + ->setLocale('en_US') + ->setTitle($data[1]); + + $attribute->addAttributeAv($attributeAv); + } + $attribute->save($con); + fclose($handle); + } + echo "colors attributes created with success\n"; + + return $attribute; +} + +function clearTables($con) +{ + echo "Clearing tables\n"; + + $productAssociatedContent = Thelia\Model\ProductAssociatedContentQuery::create() + ->find($con); + $productAssociatedContent->delete($con); + + $categoryAssociatedContent = Thelia\Model\CategoryAssociatedContentQuery::create() + ->find($con); + $categoryAssociatedContent->delete($con); + + $featureProduct = Thelia\Model\FeatureProductQuery::create() + ->find($con); + $featureProduct->delete($con); + + $attributeCombination = Thelia\Model\AttributeCombinationQuery::create() + ->find($con); + $attributeCombination->delete($con); + + $feature = Thelia\Model\FeatureQuery::create() + ->find($con); + $feature->delete($con); + + $feature = Thelia\Model\FeatureI18nQuery::create() + ->find($con); + $feature->delete($con); + + $featureAv = Thelia\Model\FeatureAvQuery::create() + ->find($con); + $featureAv->delete($con); + + $featureAv = Thelia\Model\FeatureAvI18nQuery::create() + ->find($con); + $featureAv->delete($con); + + $attribute = Thelia\Model\AttributeQuery::create() + ->find($con); + $attribute->delete($con); + + $attribute = Thelia\Model\AttributeI18nQuery::create() + ->find($con); + $attribute->delete($con); + + $attributeAv = Thelia\Model\AttributeAvQuery::create() + ->find($con); + $attributeAv->delete($con); + + $attributeAv = Thelia\Model\AttributeAvI18nQuery::create() + ->find($con); + $attributeAv->delete($con); + + $brand = Thelia\Model\BrandQuery::create() + ->find($con); + $brand->delete($con); + + $brand = Thelia\Model\BrandI18nQuery::create() + ->find($con); + $brand->delete($con); + + $category = Thelia\Model\CategoryQuery::create() + ->find($con); + $category->delete($con); + + $category = Thelia\Model\CategoryI18nQuery::create() + ->find($con); + $category->delete($con); + + $product = Thelia\Model\ProductQuery::create() + ->find($con); + $product->delete($con); + + $product = Thelia\Model\ProductI18nQuery::create() + ->find($con); + $product->delete($con); + + $folder = Thelia\Model\FolderQuery::create() + ->find($con); + $folder->delete($con); + + $folder = Thelia\Model\FolderI18nQuery::create() + ->find($con); + $folder->delete($con); + + $content = Thelia\Model\ContentQuery::create() + ->find($con); + $content->delete($con); + + $content = Thelia\Model\ContentI18nQuery::create() + ->find($con); + $content->delete($con); + + $accessory = Thelia\Model\AccessoryQuery::create() + ->find($con); + $accessory->delete($con); + + $stock = \Thelia\Model\ProductSaleElementsQuery::create() + ->find($con); + $stock->delete($con); + + $productPrice = \Thelia\Model\ProductPriceQuery::create() + ->find($con); + $productPrice->delete($con); + + \Thelia\Model\ProductImageQuery::create()->find($con)->delete($con); + + $customer = \Thelia\Model\CustomerQuery::create() + ->find($con); + $customer->delete($con); + + $sale = \Thelia\Model\SaleQuery::create()->find($con); + $sale->delete($con); + + $saleProduct = \Thelia\Model\SaleProductQuery::create()->find($con); + $saleProduct->delete($con); + + echo "Tables cleared with success\n"; + +} diff --git a/setup/import/brand.csv b/setup/import/brand.csv new file mode 100644 index 00000000..ed94aaaf --- /dev/null +++ b/setup/import/brand.csv @@ -0,0 +1,8 @@ +"NAME";"LOGO" +"MILAN";"BRAND-1.png" +"MAGIS";"BRAND-2.png" +"OXYO";"BRAND-3.png" +"OFFUS";"BRAND-4.png" +"PLINK";"BRAND-5.png" +"PARRY";"BRAND-6.png" +"TOKO";"BRAND-7.png" diff --git a/setup/import/categories.csv b/setup/import/categories.csv new file mode 100644 index 00000000..d5a1d81c --- /dev/null +++ b/setup/import/categories.csv @@ -0,0 +1,5 @@ +"CATEGORIES FR";"CATEGORIES UK";"CHAPO FR";"CHAPO UK";"DESCRIPTIF FR";"DESCRIPTIF UK";"PHOTO" +"Chaises";"Chairs";"";"";"";"";"" +"Tabourets";"Stools";"";"";"";"";"" +"Fauteuils";"Armchairs";"";"";"";"";"" +"Canapés";"Sofas";"";"";"";"";"" diff --git a/setup/import/colors.csv b/setup/import/colors.csv new file mode 100644 index 00000000..9b5ebcb6 --- /dev/null +++ b/setup/import/colors.csv @@ -0,0 +1,13 @@ +"Bleu";"Blue" +"Jaune";"Yellow" +"Orange";"Orange" +"Rose";"Pink" +"Vert";"Green" +"Violet";"Purple" +"Rouge";"Red" +"Gris";"Gray" +"Noir";"Black" +"Beige";"Beige" +"Turquoise";"Turquoise" +"Marron";"Brown" +"Blanc";"White" diff --git a/setup/import/contents.csv b/setup/import/contents.csv new file mode 100644 index 00000000..4ae5a018 --- /dev/null +++ b/setup/import/contents.csv @@ -0,0 +1,12 @@ +"TITLE FR";"TITLE UK";"CHAPO FR";"CHAPO UK";"DESCRIPTIF FR";"DESCRIPTIF UK";"PHOTO","FOLDERS UK" +"A propos";"About us";"";"";"";"";"";"Information" +"Conditions générales de vente";"Terms and Conditions";"";"";"";"";"";"Information" +"Mentions légales";"Imprint";"";"";"";"";"";"Information" +"Livraison";"Delivery";"";"";"";"";"";"Information" +"Garantie";"Warranty";"";"";"";"";"";"Information" +"Nouveau horaire d''ouverture";"New opening times";"";"";"";"";"";"Blog" +"Nouveauté : Scarlett";"New product : Scarlett";"";"";"";"";"";"Blog" +"Obtenez votre bon de réduction";"Claim your voucher";"";"";"";"";"";"Blog" +"Nettoyage du tissu";"Cleaning Tissue";"";"";"";"";"";"Advice" +"Entretien du bois";"Maintenance of wood";"";"";"";"";"";"Advice" +"Entretien du cuir";"Maintenance of leather";"";"";"";"";"";"Advice" \ No newline at end of file diff --git a/setup/import/folders.csv b/setup/import/folders.csv new file mode 100644 index 00000000..1c37d64c --- /dev/null +++ b/setup/import/folders.csv @@ -0,0 +1,4 @@ +"TITLE FR";"TITLE UK";"CHAPO FR";"CHAPO UK";"DESCRIPTIF FR";"DESCRIPTIF UK";"PHOTO" +"Informations";"Information";"";"";"";"";"" +"Blog";"Blog";"";"";"";"";"" +"Conseils";"Advice";"";"";"";"";"" diff --git a/setup/import/images/BRAND-1.png b/setup/import/images/BRAND-1.png new file mode 100644 index 0000000000000000000000000000000000000000..dfde5d5499e4104532393756df048f4fedd1fa78 GIT binary patch literal 2971 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 literal 0 HcmV?d00001 diff --git a/setup/import/images/BRAND-2.png b/setup/import/images/BRAND-2.png new file mode 100644 index 0000000000000000000000000000000000000000..cbedcf2fe8bb85f5000fb14ccb205d1aeb3ed70d GIT binary patch literal 4475 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 literal 0 HcmV?d00001 diff --git a/setup/import/images/BRAND-4.png b/setup/import/images/BRAND-4.png new file mode 100644 index 0000000000000000000000000000000000000000..931b72a266af2b1cb5270f30b78485d777f3847f GIT binary patch literal 3385 zcmeHK`#Teg8y{ViQn}V4t%F)4x8q3e_gEr^qma9lW$rc&E20p^=6+{>tDSgd-`*V`t=$FN$pavE)*i_6rK!k=$KzEg+!4{l)Fi2E`{~j(pTEUHd$JT= zy?e>e?pa}_`j2ed?U92#P-Nb&$#8c2(@}bhmJ{ z#cvYUwDgm+o`6VrCxyUjO_eN7ao!jSlgTG~hDCEJIM!52MTsgNj|a&Cjxj4a`vKi- z8-PTy{eSkaVZf^5>_0ix*`rEbv(OT+l*Qb)$oH|(zxzO--k>i<|0`HZA-;)a=v2-OcvKZcm1{ zomcsmy6Av18pF?cEYLniA@us0vuEA(!Wu7zU2AG?MA-<}h5nw50upn#t-P|A3GcQH znnTZ^?E26Pjygc)pj`xwhpF1@mCYaXm{=ieo&SCr?cA>VD4e-CY4}R?BN&EB957!< zV(HvW<>qU&#?&ylRtB=&N*M9?z&BlD5{6FSuSJbSJG!u%v+6lDWHBPeq815(7MD$~ zAfJ@9Nz-g%NL8h-qIa-K!Ii0z+0LHB1?)+)+ASw&{JXk;cIlT5$X>}pVW-!#GuHE_ z*PT4)u03mWXDrgmpxmb6E;}4f#iJrI*9M)zJReinx0-Pq%SKtljRgus`bGd9huOkO z815|fd7U1~y2r{`XUHt&qXV*2+hMS#Wwd(2t``PGBVu3QmHffzqV`%9ZsVET$YXM#786B?))x&OZj@Sl>lDO;k~RFa_ygdE=Yt4*TIwiP1`Bd9xhptqCeet!e2Vt7kZNhHu=~0*>AF!c?+2 zhW-2VGnH*h2Q;~+E-&^G4(u7g#p)o z5a=<)^P;HDx!q~OX&|L^u3A$gm+L-QtK^BiSzQhlKj$-4lip++^s=o0?gS2EL9q0u zh{Scc;&MeN!X0jBBx=<#I<>A20UBtKx zn6KZ`;s-ojWbpurOQc{2n0|R1=&YRN`Gf^;zo;DQ0fI5{JUF0lek!^5)dkAsQ%xVo zcr(;V5AWy}H6v5_O^v2;EwuP_C|`6{T?<|@Y86}~wRO1RoN=W$M?tC*#BGPZK#H7V5!xVH1s~&)uHCBj#Yg=9 zdY;Q}y`>;{tnum7ac-l|RQDwL)j0iEtLHoy%B4*M?bE-apAah^)#eG6_04xKtmpUJ z(L94djP;UFjsVuCa>t51K-1HXJ>_olyzzS+fPW>%?G!6$d)c4Aq{dSr)I@ z?{7RE(^5TcX23}qINv^Xxo+hfUyh8H-H}&!9ctWZ0wOqftvp;mrK)|Si5hO7Hw(M* zAz4#<+j}a)KxkAun}fPU(+rW2xYT~eR4Xx!`nfb)-rp7bQqc;MKYMeda~byhW4bJa zx|sZjK$UE{2h;1Jeg}M%HMcXGdOx@jv|G=ToCn4gSI^Wf*KCyJ#JAp>RtHZj=_teW-^H-?B{RD3Q{={q<%920vjlUNW{*I?|fvnQ}5pxhH@G?qF$T`pw%T(n5>030x z*Dat})bsY{rx{l6P``9jl2-wz{(^t3@vN`CK#)ayNLvjQNVT3JZ+#u&&9sdEseVWM zN#}|;Yg+8QRTlfBzsdW`i-iVW+4+{angqf_nE*8j%6Qdov)&_S3J* zrS3a4c=NN2%+fCW^qTNXE(A>Iu+5v+XLEaK*`9vL2>Gx-%~`Q+6Pl^5QCrXFQ`u<%;$tc;UfGxbpe{WWWcfnqqbx=v)PJn}F+V+hGrCzN!jAGAH zk0Y&1l1GMsNH6$H#G3XEx0*qi*LX@{>IBTgf~O^Yy>fD8q~Uj@{`U}yR|nx!cfnDu zFT%s2o9EsGll(c3RSE~4a!og3upiLzcHf?cvAW@_rt2Q>GaZOyy}!x$Zew4es@z^g zwsckl2Y+F!Y!#ND$rmN0x3^16zxObomGtarf{tydr#23<*=z<3E>YYM)&sQcJNcje dn;2{#cKLQUgdAZD-g$`t5PKIpf=xi`{{Z>;1AG7g literal 0 HcmV?d00001 diff --git a/setup/import/images/BRAND-5.png b/setup/import/images/BRAND-5.png new file mode 100644 index 0000000000000000000000000000000000000000..6f6023a923d8a3db716afca7f7d638228288a7dd GIT binary patch literal 2537 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 L&b;NOPs;xQ6wpSi literal 0 HcmV?d00001 diff --git a/setup/import/images/BRAND-7.png b/setup/import/images/BRAND-7.png new file mode 100644 index 0000000000000000000000000000000000000000..ba4c5b4f2193e5b103a1487c14e1472c7a2e9c5c GIT binary patch literal 2493 zcmeHJ`8OMA7mjL6JB%8NLCeu^S{-9FR8us92JKjisjYUgHfkAaZKP*>)!NN;qDsUx zT563XLW2mkHi)JYJ_kvyp>`sX1o<-U{0Z~p{PI5UIrqNLz4y82z2|1RINK|p)I13Q z02FWDfVu$yGFH<2ru=c~8D~g=0{|!fdlPDXI~lz;?U3tt|4io=hb*Aij)K$*AK!*H z76MN0z1{mM7sxoJX6LN|Y&B`Pkr3{sq23qa2+gC}IVrRP124q|UGAH;sW|n*>rwO9 z3+@*Yj@^cA@5`fwFD?o9 zJS&8s=Bk==Wau_$*+)!NHSNnadGi06KmF0RGH%u?ij9a-Et})+rf`$kDkg2~7Pt|z z7Xu#9$j$uTU&cS=&ZwB4w*N8syN6bHj>y0K38RMnyQs#C;mOD_bn^QHYPz_QsA19-@lYY%^7o59eV_Qy9eye9pr27o{34}}0tO%aZ9L+KLbTmIP4PL6M}?YuH4v*PH3ji{W?PH?e+;Ad!4J8 z)^S>k|6r%iI_rskD-l1FC5Ek%AH#JbS39pG=G2v4d1}Gi?{M}#KS?mubRwZcUKei6 zpE?I@mT*Zrpe-f{3lwZ0E7r#XDUg!U5zN+35E?b3`;h6;RM6XliNUSmr^y-|0deOV zBXU^fXNLk%579XJ$c=k*5@F~9SZ)w|y3DW*t3B-|++%Qc^7Px(Lz)TW-URT_XFsRV zTu1l)=(>m=UfS8*xs8KJZDHp*MrnK4!n9gGbY%(Su7d~hGmAS8EaK)X+Fc;3oPxhhQMq<$ z{bJGji!-M1z&Sm_aaPB?~ltR9ZDZ4wj+l?(s$F`6j4J0E3@`pp4Ve1jvri#_wNV=nY zgJHo9GeY$*oZxkrgA9Q=Fm;nbTM*W6_!GeIy}i|?*=xodN!_UMgb8ijR7=FTWU+NC z{A_MtmaKu4Q5>59;xx{OXP{BLU8GK?+Yj2+z6L&8MTdU^Jr1swsnkLuCi1qB2ba!c zQW|I9Xu%fyOsK?UT_T}DUUxSktY%#EoWqqtTWW#D^*kdR4)1>yRuxt??`quOxU_(Y z=Wto661_fwcQ1<2s=hx;IMs~Rooi(@(t-%{*prV<;l1-(*8FHaL=)*fWHPyn*1ZHz zSBj;liz=(D8a~T`WN(Ed32$ke!?ajst51lBn^UKSBv=XZUpyu34pk8*Ah6~~XKU&&8jVq6t<+1G3cJQHET8?v(HpSu$-tg6b{ zRV#|(AMlz+Qj!LT*_*GPdZswG1H+;_AlO;ioZqguRp9rgs4`#jb88l%FSV~4ldy=U zUpT$b>R61jH+tqiY!9-f=)=aXgOv9~<9(^@sW27?h2L*)vnw~yZ&mTEOUYbc`~+zB zH$(VHf{IZy=N~dZ2udc%>P1l?=T+QPl4(HT?N{g}lWyz^@^O$yW+}kUA!d$FBlR(= zo<$XCAEqsIOy6s%Lu7_N!y7&iI&@LR9i+!-goVC2p-W1*vQgu!l{VAj+MdXQ!uY)r zXGC+^VpN4s1#wwKQgY4Z1z?ch>1Bp^WR|F)U%w)*73t@UWqaCR4yz0vg_Y;fi?m?# z@5`N!g^?c(LOw{eDa4B+Nt<6ncxJftjfB8-Yd&8=nWJkUgh~btpaSrjVc0F)8#QHR zTa(4abkS7i)kzW==f?u75{;Sd$10o2a0rp#zusQ8Ee3hiTZ|(qW~rj&3=HapwED5> zMEDSO`6)?foIKAjZad83KG?Twk*rnI7ME52lmi=d4@-wkNZ2?+*;W}QmyWMF;Nm(g z!jh)dLn|b58nv!X1-pI$>BLcMIxSYElbNlb6V@}(7ZF1tv#)E_7n8RJ|N5uE#LaQW zwf&X|x+QY^cLG5@6mFdQ)YCRxd=H3RxNsNaAdryH-$KSu&axIj=7yRV1Tkg%Y3R5l z?pNjpE8aj;Qx+Fv4Ny0t${zjjjg_vU%)juDNg&c;U1(rF-|SYDu4RCmw$9K7o4{ZH E4@!w}P5=M^ literal 0 HcmV?d00001 diff --git a/setup/import/images/PROD001-1.jpg b/setup/import/images/PROD001-1.jpg new file mode 100644 index 0000000000000000000000000000000000000000..c340872f76ed5aaf825f9e0827a0193b63b6a4b8 GIT binary patch literal 51530 zcmeFZcU)7;)-W7Y!~!Z(RhlA2I)q-rQG`erLO`if0)!5sNz1X(%b|BrS|Bv(Qlo;P zROub0_YMgy$s6#TbIWs|@AsVdx$pPao&4B)&CJ?styyc$?3r1!Ar29L0IsPhDJucU z$jAVXNIw8^>QaWHC)^SMP*(@=004jsfD2^T0cS}N8R-Wgy9ppag#iEuvRi+`?quA* zNm?sqyxq$ik2Fp2vKhoATR7LH~xw#U|v zu8s(6M<+G~2%8?2pFNB0|5N z`-3alg-EiW_ZOP8tXu2NE7rDLR_p`)Q;q^3Mgzu$gl z{`pEqb@?*Y6{>4ju3V$Na^(u`$>j>|&qt{LCj^Ke0n`@&o+J&D-2t4TCOb<_MjR(K z^%Aj(Or9hqImydT9PMX13m`jlj{H2ug^QOilU(Z`E6D(7&i+w(4M28|?ChCyXUHke zUm!nA2_#igpFMZ`x-j{DEmN91&M!pH(?-54dBA>`PWzJ?P}JpRw*m!66l8O1%N!v_ zpHcdX^I^1(h2rN-S8;|O=rnA*>~&+W+suv1lFa2|Sx|Z(#aXFRE z1M^r3u%4AiKs>6dWpDvU4LEa#B<;CVnJCVai=B#aTlo4pk_66oXvjrgMADu}@JYLS z6L{Bb%H?I00));SA-ctJ{zL!@PO;BDBq1^xEEJ*QuCVDpMfmR};QE^g#1R1H*;Ag> z0C~WkPLwjoy}MD$D#~}Gw4;>o#$^3>1)9X~|9}nYa?6?9UAYyhWHgs3E(xmoAXRwx z){Vs@58;Nvg0jBD7Ylc~b|P?v8wGput^;+*mlfgiz(pcpvA^wld9{9;(4%v&45SR_ z8t(yqyKp^UV|5JW%UdANAanG+V}Qj_vnfUda=qX}_=^H%nR@wtTMx6zr}7VmSt-OY zxcO@PBHQKI%z?K2YI_G(c5{^_T`N&u(T0GvD^=W%=VbYOqqLRpzP0;@wh;lu?tf~- z-g-&!a_OP@u(^Y^!{9G`0$Ae?g(`{T{s7~vIv9PSwGxzW!_DT%qYmF<%lS;aX>Xy$ z!J!r56~(5J#DnKZaFg@K<6}|%Gk(pCt!yly>z)`dEkr12D@`kr{Z-%<*749Z%i{c0 zugPq6orrx^HzMHUQKc zT_r6(gsgODAfHppPCT7^{pgGc8_P8e7gsRjtX&kv5(C3>zE`-PQCD-@5mkX@vMqgi zrNNrFgM9r#hs&}!9*$DNT;|WLO@>{SpHB%MlpqLB7^KDwRwBP+ zmdKB(p!loD>vw}@ah)u3lAa#|BN*^)rBTW}VHG4Fyhrju6(q6eA5GNmmY$E-KlRl^5VkzxeGcAI_c#@FxNaGhN4$oZgpgBKX|s`+9npE81=AJ3UGkc9E$^ZSSc15gUB^;FQ47M?Hs0eHEZz`&WY2CMq9$i_}wyGRIFp-D?;-MJd)s~Q!{$D z#)le}+jX>EZKd!@K-@fF`Uz5o`Ahn)d=e4xHg|5#8ruM_q8{+Ww}8~feqXCu zfW`xvGmFzALP7EEim@c)|Nr52@PbhqakaN`I>hdWDNAcHJ;2qZ+Y zJq5URpZk7yw|`!sYT#?lQY0*#{qXH-G2xXC?X5Ly$7i=ybW?R-Wk$Q(?OD>U6b{r^ zNGv^30Jnd>#;ckES)TU_2-Y{kqr7hs0Z8?f4`#3-f!Cf{>|?dS+=Bk3mbG*taJdrF^a^@pL2;R#Y=F=e>?QA0d+ev=8q1oqS=PHJHUieQ#BYR)1N9 zO|*7N_@giVs48Z8xb#cB+n^b9_1@u~XBHwx%7n?@OhO&%OZfE_7yLM8*RsJdk-aDL zXi|a@y!fh0o*xzxU5L>`s1fS^-f;&<=!Q));M>`E5c>m5A+(>K8TLW}(%?=<3^HlY;#cx$V|(kM zM}7A}8XAtnPD`?;;nKR;uQa`MH|i2;XpBlH z_Mhr2?_~5>OT8P@^oBy{+WqTSUb9?ys6q`1Ln=^mcBT;lr5~1U*xjzkZ<+kS6soj* zU93m&-u|+hPZwR7JyC$gQ;Dq-0iV{23Hn`qNqg#p1AC(JtxIh2%dbhdyQqJ z{2|#%=DeMor<=?36Oh~mW@qYoTId3EAT{c=@Kp2@=+ZxmPi_G-|4EM|hN~&u?gZxo z%noK{>R^5<#YLE>6U+etcR$ThSehcNe;0?s4rc0V{gc6YM>89kx$7wh7nr3T3H}}H z(y2Uuw&9!$3~`Ef&IN96eS&`uK_YVkkdr7oklFwPP(W>6OyLeBjt&4?HB+zW?j(AS zE^Pd4N~9^j9o&@Z3<7WgC@dl*DlQ_zbjJ0+!#Xwcsr@gV&MQe)Kh05{=1zQqRRL>PS0`yfK?j6@>B&k%fMhX2Pg5sBVF4jQfULZy6UhZ&u54y7E4YIk*G4Ud ziw$le$E7ExE~M_H0JDZa@^XPeyfk#oy=={;EV$%Bmt;MqJ?)+BNjhfpw6}9WNPEh0 zof4NO!6(InTx_Q(uC{Vq%J!yKFlp(NrIwDPqaB;1fUp=BiH3`XrL^`#rQa!#a&lb1 zi|XOwA>aWNaCET}6qb^b5)={<6cOPkVeliKJGh#9@;e~dNfa)zozi#+Lzuh3olZ=| zc0$wC%+bwNj*IIO+wY_;%>Sh9o zwRf_Eoe1}{u@IQ^Y366n4i1w1DG>=e#W@x4cO+TCe@#jDv{=E>-ihSC2$I@B;=iN* zec6dVP7zP-rv`JdaW_GGOxPui)nC%bz|5Ek0hyFE# zr+-)czp_55zx?Ti|6u$-y5djUlhC9UTu5VxqsvKW0i7;=|K;X@tl&T6p0wqpOr6vL zElgcaACiW8(8-#fUkJ!ABB}Go4g#-`i1dkV{tNE^wt?#E|KCltxBtDLkvOZXOFwip zcRT5U$`3(52M-HJbGU`H(;qt_(n4l1OG#5vDSk02pe4VsFieQw6ewoF53>-p1X@~1 zh`_{1?*Cti{jZwwC-;Bdls~KguD||SCjAJGAQ|qtAgM3@i-F>25oyRH4Ss@uj-Wrg zGpT?7KTRax_iSC>_)EzD@vi@<>n~~GFCqW` z<6VDS`;xX63N5m$;lWQd5Ndl9fBd4IaKtX=-w3?b!PYNO3ryvDzURA+lHWi^s0 zGo3`UNRg}4t%aYLKNyp0Rj5goXUWLVQILKY&ym89Ct{uOy?$HxzE1BX>KrU(LNl6WEr=+t;c~Uc2mCBXA!Vz?T678N69KWZ!~Hrz@P#%T7fA1hMH72 zc@*!~Z9F*9Vf4=O^1U9TlGzU_IvI16Vk+C2+Hgd=M9Z&H^kX&+6>moT%Vli z)0&>y0)5AaPa$Il6BzJMtM+dNdwAFl_Ow@4Y`CwFuHhhyZ;p zlcq7q2d{$_7uiu2JlE>iqe`1}3g%!e_SA}LuJ=Xhyfe5hK^%Rdi)b1s8 zruhM{NHDD70wt%IR$h#-8 z|Cn($9>o{v9wo+INhJc_1rPx=2#wiQFRxzUmc8w6NS&B#QNq4tyIv*Ojt)x%@bt;& zDRGZ=SC7)C@B7(jdmq%1!sN{@HB1hIBV`pSn%hY$v_(XK!W-mSgwl$gm)BF0j<+Um zrMl5cwwsh&!5Nc}#t{iJIK8SL4%XxNM6jyxj}g7PWQPSKMPmU8no)?7Gkhr`t z(Uw|iF3M$pLlzY}^~v%>F6Y*8Wno?*j(ZU*SH_n4Zk!@Ym4RYG_eUx%G*aI z>^J+QqFk_FI^yf-QSxT9U+BP=JaaUgDViZ0O`gCdr~kfp{*P<6i|spv(`^M|sirx* z&C0>;&ikQMT>hV)<*F3wmxkYoSz~No*XVX=`>=W|->);-QxxaWPuoi)m6-C-l2f{7 z9tYpBsq)aW=?6j~)PaHRojgH{$DcZn#McST}H{BbC7&*#Y7YGro^UzoIn>(%jP;>pvy8mK{M$kQ7YqwgMbw_2=UY{HS9(Qcu} zxFh@MmnJKHBvnMyH}53{|Aw}W!sNY$WqU47YT0Do#GC>Nu6!PY1I=Ies6hA3(+ctj zP;ql16tpEe{ZNyo$-WXx#w}IaJw;WLm%)}zC1c`p^6Hn5Tk_sao26wZ6WkKL5?*(S z-&Jt*VOplmIcD&$>nIVYTG z9_MIss5teeHL8QR0vAAe<3YQvTcY#D7}Z4rivs1$kq2ket& ztV_EaQ){YHwtwNJZuquSRMau0fI&#ye9&4@1Y@I&2WNk)ZTPpK%@oX2mtz=TBN>?W z{si5UQWop$DBCTNVNqg6b&fadv(X{}gW$}poh?gY(($_gb)trOZ)}}i=*mhjONrJx z5?r{M2z%ld{@b%$|{lI&VV;=JnCkuMs2f@DUXrtC1 zRUi9c-|se$MI6LmyT=nXntLN0&A8kbP0EnoN(wmJBLTIn;KBLq;wkkWS;chE@$#5k<|&I43^Q z{)?1EEq6l4sJjr8yH6YSP|$S4+L+o6-@RQcE7lm_)RnoOyyvjP2nJS zD$5pB?0KhnA|r9L-Iw+Lp-}ybgo8DHG!`7rbJ!3deYyMBe}mS}sSMOEUi4GN9!0i1 zI#Rc#45!^URnVPbmK@#Xfx5A8=SE~=sfd6cae<`SF8zDkp}wrbj-2Vcz9r}i=GguP zsl)QokpZcA-Bu2PN?tmh${GQ-2T_&}B;!4=kJx;Kwzgktb)TGvUE`jg=!pN#yUmmG zl9bUSR|Fw8$|uTt z*E5crVXvE-NfQ)h6(>i$wk)#eO@U4Mp!X75mXm84+x2j8zq}^js2>6n7RCz}YVvw* z{u}fIkn8{TxaIJn2nVXZSnND!ssy9?;t%KVThs3@C=>SXvFubc7F4NR{yfSoJZntX3F4e@7?K>(~OA zT7F8GtK?9+UTiggU;%5}6$+l+(o}Z$6t7P%Inpsd7So*HSt@~h8G(~aSUf9 z*UBa)0MO3CGo`u3PLVOrsQS<71>fTLbTPGwX5>~foHmNw5ngp#F-q5sal7^lrER`> zPLkxjVBv4hL+-^Lxy@)Iz_l}MiN4)v9G#CJSxisyHQMPW&D@~%qTNTkdMsLc-G?GR zhli5?7LD!CEO~sTQ5=+e^PG@7>TF~0=H9Gd)QjF$3z2?NW>+(ApG)&{bN zcqcxz&_##@etHAb?jE+Yq4e9UC!DUykt8;knB|FyHV$o+lKcA-kPV6*i~ z?Tne=dNVq089}%abST3)H;HHUa*g%qkJx(H(tns%%|8Eh`7lZP-=Z~ENj&!f#T?R7 zzBMu{xwV4+^0hhpK8poKBA_1ZF?M+(-*K~RO-siIwYZoT$=5MHF%vOVl(^L)ulG^k z9Yt@vgz3&D0?v8I(tO()$Pq^Hf2*~#HLZe#P0Z276xV+&NR3^8GS42iyPxFCB*x)ZFuO-0q}b?GvLvU+XcO8JIKKI^PRlA_7!~ zJyvIAb@W(7+aiZ0Fp4AYf_`hRnr|NC!wu^-qvrNj|1H{Mfvh$DrmF4DZRFG<*#>Y8P0JFF5H)v5`er+H*UxmRCPkn^taVux30w^E zeSeUwN1YIVTU$?TRMFn*>jf7+B}EQ?BA~95{aSFV(MG#)nvHa%fw-ZCR^J<(b)5(T z+8;bIucgeRQKy!1+f3)l>vWN6%Fj_v`Mw)>e#{nZsb(@p2j2zz>((s60q#9Uyt>;slnqVwS0M$WT)hDF;$Ry@ovmJc|7=QO(BQ4 z7~M#kp%|2fM(7ZynvcdNg+z7*Cs{S$F)Rlr`lXT|iHP@_*BB&VeVx`?W9-e?Q8QDLVwmCm)Lc7-F!u<q z%SeZ9RX3gew7)q&F}{Vs#aOXUJCsXczyqVTM->nd&Gix6RYLT;T3cKmTGq_;fDC0N zE#}E1SiYFeFj4K78DsA(Cho zciXU)JL8%eMaI^A37Kla(Mjjb!g2B_|#@e9s?vBM_O;X4~cW z8*+@Zzs7IxaVu}V-gpKqj*(wcZyk0$cq8vFh92JGrSCP+pVM5~5I4;J+p^SX$Z{X) z1h+O3@TQ$hD+|@2U%n`|=b>=dwbKGyobov0^}VY7p~l@d>YkwV5aZO?y!3iQ@TVwg z-I(!wt9}!L5qIW|fv(k2{{lN7{7UqXq#6h>N^?T5y##&FQ3@KW*W4^zR1XY>M^IK| znhmW$p`J~?%`c#l#zMZ~O-cMIzErHq(U3-i#D_DVAI!c>=& zm=hf&J?E`zxI}isq>}Xp8SQklX1@5TL!3VK6w9cT5@N>eD{2J%3=a--LuhDSrq>b< zC5@o8BgHReC(7P7#Iic@Q$V(LjYjZH?i3gLnFLIdXBky?^R!=Th2H6x?BJk{Is!un zyhO*=JVx_1Mf+vv;YGQLi3`9^OCV^$xyNyRcQG#~Sn!KZlhPeDJfX$oQMyFcqF~O> z2rJe4(n>>9d66R>Zuv*Pnae@j3{S}cv#Qaew`qT3ugyy4u&}x_USw6;M5WecY?_c1 zJkubVM+B^0HSb2M>sdTc3KiQh8;RzQKH3vm^}EG?K(pYbn>LF$bur{#JQ^;Tbu?53Tlc*R2=9F&!BZY)pti+6=?m`Vzj zk%olx{44? z7ZI$v(H*tzA(Tur%r|}P-gp-%%R~gE*mm+Y+v`zIuU&7W)MY`96*C+u0oAnzZYa8T zDI1C6)V`2D4Ew)KRMIzJv47Dk^#5$dXw&bs$1JPJBQ_%iiCVaEcU0X2sBJeM7?fm{ zuA$D2u|((G$xRHe>(+ZbN1Lq4;9jG|U&h@#k=B%|n7j5Yt)LB}^+vjAjdNd{!0DV_ zy=r=>-q14ZP}j;5yCx&o+sSnKY}$;_5-3; zy)DiLEz1)Zv&DO8ayDTqo;<>Zf(B&bumXZL zjm6e&m`7)Vg*BM$Jv`BgajEuhN-4!sO5b+9llm6XaV(`WkSl{ii7t+pW1o!`;#R74 zke9O>&WqV4t>c#$SlSg3wola~svUrnQgM~MBNUR2ljAy{x{WqJfAQmVUEfQpnfDXv zPc1|T&IRs^%9CE%y7OXw#qpLEwte0_p0cu5g0IbnKM(=EhrC)zOM$pfkV~_8&i7i$ zjJ$ML@a#gVTG_~`VFdw#M?A2O+}k!B=JLM+pLT?q~<%>mwG z$h9 zsXn!5a&&A)(?xDSBBe3geGrAumrHarz6Hj1C_NQ`2Ypmv2A?&d12cSi07+rzTxxaJ zi@96qz3PZH?jEPA&p~4Y)_Q3~=kKA@oP*Yyu;mrW?9VI3Gx%*5{PRMmNgIo@wZO5R z)yYai&(_7yMJ3Jm<-0$Brq#njJM|}`EqXhXg+T;+c}RJY@6kR^iCJE5z$-+owq-t{ zK*86UF|TV&BF3o7M%W=3j(gDDT45qn(XZEF$Z|_vyYIu-g066#zG!D{xJZ8?hPuBY z43w_yNI!G^(7Oar^IQLFc#17-D|g&$BU~K?vxx1l99kY(v)>=YCpMWeSuG}cWmx96 z;~IYSU><-=TdaNKEpB2i=exyeCRPpb9!UXB{n(Le;t2=5`3Rd*1wm@x~+ z`Re+{LiU0VWgB(z*ZhV@v=PT)kxS!>8n^Q1ZtR-g6I`A)S4Bcf;d1xZb28-1(Y449 zC7-3FR7btV!RH0-hc(vK#}($SxdE}ZS1sgi9J+LtZ7^1A2L9O^$DYAb54UJBegRDO z%kK7^Sciey*i@tHv?cVt^h@to^b3b3_*rFY^k+tC+grkfv zXT<6udYlstmQ&Oj%M@P_UQKChrLpGJV?E~9=PcksRqFufG^Xb-WRID-#=*)4QmR95948KTLyL!1#V8OL6 znuN{m&&!nbtaMFv9NG-Xy2Jr7@1UCa9Wl74Z@Ie8!NZwv!>-9ob=XW=8_QytmfG>m z^6t3U?q_d>SztJ;p}SS~j!whwQcu&f9K5+y%Mq7xpBLXye5SPRUhl>f8l(ksaPP`0 ztTK=`5@ZRC74NGPZeCe!5(?}%vG zGIieECn+VpT}dkAjkR$~E3NEmHE-*D7Gatzj;eJsmyIM#&{aA|JfZt)O|=cTZYWiV znUIIPc?5!FLRAC@WSA6n%$#+kyljI)d-=9nrl)MpvRA5Kk7jt^jCA?12J?3ej+l5H zpH%XC7*!HqTy*0$DYTN+NLUTEY;i3M!Eb(}oVh4rnUlV!#@XT2D%j0C*ikyh!C-PD z45f6@QF{A_$&DwGHgk}`(4*=?y+X(hwDZQ?j>V@Lq38bejAQ3{QoY2?vNZ~C25Tj4 zsM~di>GUf?)U|^AUG)@O&Cp!Ja__&Ief{fizjK=F7&cAtoJmE6VT;DmQ`m5LH?Jvx?zA7&%P9MD*5^EvgxmUcxfqUI-st~0kpC(dFE4d9N|IS)YB7JoY)z-D z@=ord>U+5FZQHdjT!`o(%eN$}m8*cYvrp!k-(p`R+qPC4@py(Vh~%2o^2-&CMqH550>Gr=ZZTb;RE3@Y+4}m6NJB5^bq81GyMfA+;nc9`=L2CLX}X zTqnykE6>+y#l>J92PA_LM-?`+z3;A0C1jfwoUEXTFZ66MUWT!i!w zZa_3%`INJ3(%=>D_B1DAz9=0<^L@AFJ8X?PDOYE}w+gOSB)HN0amtyox;Qu|{48Xt z%%iYV^iVbSXg#Oa>FWbsu3TKW zaV4`0Mu)}lEK8$B@JXOGW(0I8#MkY{kD?G{+e4q_>3Gv#FYfWnj58TEL_kvY0VL4N zJ@QZ%A5<90;Fm zP80kRp97!h+&%wWP99wDYV@3Q#CW(#oOVY1x+1fqR?)!n!DKBI*`d?bX^0PFiB@MU zb4c>-rrr(!I__6jIA}Gp`0)M!a^5}=-d(*fXfqb2jNHF`*@Lu=GToJdzurX{Ck492 ziyIXh@$4;!gop#@eY6j6IDFlkJa2Zjb`OuI=A_#em$CeVGU$Z~ z@w}Z20=6|Wi0qH9Gv6C|Qlqt-uNiV=W!dAUKXFSk1iLmC;o2*Y?UYURfG$=&8xKmB z;LY&e(s|zOGl9qh`3v;A47E{Z%6NR+@ez%UrNnU;zDY6~b46((t$rXX<@go_G#rbBeUzoO?dU zpv(IS>YB~5I6NlG5`~j_sv&5E?l<|OHba=;lMcspPhc09JCdE<(_vcaAg1Gq`vu;Y zu&-8^MdGb}U##%OQDf-YsZlGP5kvre3hb6wDoVA|{YnGrK!|>k_lKpR&BP$LdX3gm zFK)t4b~U)tIx&JVD1dI*GPbv7@=1+X^2};CD8(r*zIwx>lTo82 zR0@u@^{`betcA9919f&1Nh#f~(`Zz&UdBMdfqx{Qw&hXt9a*7Wd-=7gyrs<+;m?l? z;$<|t<`X}ejQKK~xL7g=s4rcGkK$p%0-qvC=LP&}_#2Ee26!0>t2To_vRUb8+>fL7 zzzi}WELC(yP2TLl`33&Nht<%OFDYG>&MX?Ksow7H<4ML+P|A3|khygcoUZCXK~@8p z-O2^4*x=Ry^e*Jul*Akf==q(nw?0DqSiI zhRYbM)W9`&KpHG-M>v#(O;Y_1aK|s;NN!5^>iZ7%2lwuluTy7LJE{oor(LY#nI4r6 zB1kv59LjjWgT=4J$>Uv*-;HV9Yyb7Hzk*exx6fhteQP&WFRs}anl?=@L^Sr*AbUPP zw)%eSouOW>7t*!mjrPGHX=W;s4A~$B6Ds2)^*u^skMD+mUEWr5(VZrJYmfe{DsZv& z$*N3@zE<)1;{LJvD}!(0R5zlqVfm#EU2b<*8U?x#JU9HLJ@r%Q%#|u0^(MbA*oVPo zWMqJj=mF#5LxZGz$(bs({u>K7a)39mE{?9!2KsAmg<@lygHX{<>FK<{6wij{9{Go? z?;GNr(*(=Z{M@(+X&&ijHj|ygG3MK{D7_^U-wG2CEm|Z8ZA*_;$Lffq(ydg~ikU5G zL{BdONB4;al*E_%zjBU?#d`Kg!WGv0;*?bi2G?}7k-$P5T&t_{O$oX7l%ifYK1k8t4hECE@2&JE$Erit64R5D zt1SC-ztotq4>LMEy{Z1-o69dh%_7g)keXym1XO4|+^8$3ztwxZLGMem7>C5}bsd!L z!#yLi{0zJ%k3SqkLD!o(JUj;L_Sz6~Mwgj}ta~)zwV>U^;+C(8O;UD+oBA^LZ3y+s z;*_?3ravl_r6w zA(B-ubE*EOVVcLDBthS=OdkBamk0n4nmyGI-AQSbX`gS{E)3Usi@&ENIPWxwTd^B& zHwdyCq=YYC!3{JKaZKy!ZdKl@Qkm+S&5{^;qm|2V8lS!I+a&EN+|$Y?zoe6QUr8uf zSDB+!*;Ud8jjqW-qksbLN$`w>oP?$avlf57g99k$<$JjNpE%kUKAx`3S0#hYyw1YB z*pP{q8qWtEVrUzDCUd7ILI}(9l(Nd4mA);uZs$fe9G>Bd{imKJsUx85`)^Z=RaZ-E z8nJmfwi9DFqX8R8d`@D?NO^~Wz%h~>>2DaU z=t+$Z@%p^oqp0CUJ`jF#A)#y$`LK)#s9GliI?@|en|#@c01WBOMO(xd$d6<17?^wI zx=~BvXqrZlKaUt60S9~nAJ=0pds{1W4{vtcAKWu!5l~G zLnBod`cF;bQa%y^+nbL!N`@3wcag*w4@)O>W zSxG&?SyxWh-Vlahs~+P3(jswG57n?rxWp=P_$)DXwv2fob8Fz>e3)freWjef>Fhxx zk~?n$Aesd6ySjEXsf2aw6hD5$9_surjZ*Z;LsFXgf~a-zblt*6}E0PI)Gz zKf_T7VO0{iF+r8JEJy?hpHq3s$ciHXR>SWZ;-b!g%8)(G5whXZ-I znmwyRgZag7rlifLyMqeOnv%-?YnN~piTY4TJjR{FSbkUU!8QRwLl~9DHpn+D{)cb>9RQJ<0ylz*7^%oT#RruY!y`!03vtN~wkk+PiyzCRNQLE}! zz0A1r+`~4urxaHcA&?P2(atTn7b!kcT!t$0jo!8y3Z2Z6D>->xUx(n*dJaTCxWA#a zD<%Rq)sZxxBtARW;@C$urvoY+)U2M{d*>gE9DUsKsQW`@fAP+mf>fcW`;L7}`g+$u z?FVcDJ{YknhjHTR{Mh2==9A|spQYklC$*80o~oG&!R#~lcheg*xbxh}aQ}cpYbx8$ zK1t7CmaVBN{n75Ut?mg8k;1E4sk+Gf7su3K<5!mpyS5ijH(6Ddf!ko^nwk7m z%XHqsQNoX%aLzbrkY?ec>QThgjJ3LLw5$;)-=JLB6YciQ^3qkMF7NO0xLbj>jt#Qf z_E6@qI{CqSE#aQ}-;K7jdiIC*O!St25#FfWlE#jM_DBnt=@-87>o##YfmD0N&kaM z*raJwZg1{AnqcEs>@fDEa|?1@foFA16Tz|lspG!{oZabNGH8^QFV}zsE}1-fOz7mg z7GbsPCN)&WUNcL$Y0SLDBV5Jb<$E%pFsskT{P0+n-4Z}iR%*J;+%YUF5Ry!oHll>_ z&ES*Yc3{=Lq2D3MHNd-!irNlp>{H zeo9K^qhuRrO5>UGIh4N#dL5Y4-&*tVJ$kOji!_X{bO7II9v}4CX7iB7^%un&5n6iY zN`*#&Yko$)67|`-@s1|4YnRrnTRt`Ry>4sI-`tj%@dOs1`2U2bB3`hIuPtq{8T+4?Rn;n-~qg zH>dVcvaL@~Zz83BvLw|cYN}S^UA!5>MzrMGVWTTrU2)@{So;rbcpBcTx+uxgJZh-c zGQ^NZ=i!bY)?JGO)V4dDdAIkglfBsB&NYze2(_qs4fu@mmVWSR_^fe zr}9`MCRHcy>0lST@=(Wd3bBg&ex_|ifYzQ>MzE!X$QW)Au|U1+Q@y0(S@n6LG#K>s zu)*f_e%yw4T9|Nr>fDfwNPPX;S&p2UF0pspNmk6|ew{B#|80lzI60NpO3!ifYPV+Q zd~)IFD%!xt3rWX&&>2kNdg0iwrO_0)QIsB2-{N#{dbC%r54w|$qn>fJ|0&mBzRJrJ z;`Y%-l}n)taPJOYZo)bbiqwu(zp&-bwt7uBq_p|ACn{?MIWWLOxEc#NXwZsv^RvpR z8;0qMYi^xcb|3d?+GR!vH=+Hu;rM{MsHAlALD5+RR(I6~5;GX@GQ6M88|9UPgKqzZ7T< zEw=|hN+i{)H-D>m)3*4@qfwn`%y&77&i>}Yde6+3^v2_9fjF5LpqQoXoq5~d zj9$oaT$ujoo;zvaL)10W69Jvh6{yJ;t#Vt4O+WKJ|1iBG=m4xxddD_tGBNL41g)@! zw)wRZL(rMSC*`wcexs$Ag45~BV<4nWqmg_f;Q2ZzWL@zV3l@1GpTlx*Nnp0OvY;Kg zMFi+HD7Ls8X zm&F^3Rvs_zbGae8oDbEnb>aCDRmtxy{JJ2YU@o6$fHga>P37Kc2)o1g#!3ppxtk>M zN;S5L2?1*nmc3u*q#5osKHCzz=Uos@PX0*?Wj(c26!0}^#JW1aT1?5W-z3;Xdy%&& zjJZGq)Ioar=3guX9*cL;qqBR;X%6y%;l+xm{4$mW4y7tBO$Xm~)ypHIaYJJzpaZS+ zP2_}q{xGIiF9e~{gJ1SxieoT@A8YhBwT7(cpKq{P9EHB?gAAu55E`|bdJb~ys#Fo5 z%o#|b9*yEX&csS|@ZwRo|8&w~@p|V|wWq%V0B5(VmK>VUX%mN^lj65Mnb4Pr077## zfos4o#Qaud4z{DKMKBi62~FMY1D8(z28FQz+#jLVMBPU%GGAnA;0j``lFTa;I6daoNuvAR(?1ZlN;LFmJ;yN7dKe#AIasRgq)~cC6K> z3iTO7ds!;C1tpU)b0FCJMg^kA=Y}btV!>uV6tg+Z#k}gt+XdF?axMwuQ**R@2XRz# zAD07)_HMeVmIR~sF>p~mcr~A>fU0D7u|DG4W|@zWvQhV|`N^PdmSW2Zy!fh1;B@|i z;QL)~rFLt3O{uh-NJ^kttxl8N`{xhYXLR$CFO_Ilzv9t}{pAZ-_>S{_TDKeLo#j+7 zSICk^6hVUY83tZX&Rm}Uje&xe9Ovzp=?Z$cP|N_(@L}}QhQ7%;hkLyvsP$f|OBD?0 z6`cxZc*mA)9D(mgDVr3GP)5a`)~l z6Ri9^?(1lRZG07r&SsNobW)8bVrB%6~=l6_@w$hmGQ zsMNKq?#`%w$9b9XzQi+?QDXXkISA3xbrT~3#7v}o;h7QZaVIZ_Myfpu1XyT{NoL4` z?~wMvbm)hS5#L3Zgr>;W=Mq9S5ptgl#w=s)FiI}dCNfEMOXYie*~LmZcxE0KN#kyy zjrfx~{+n&}#{2~CQD|AA=6It2bXcZ4X!qfPl&qk2wW0x^@y!Z`Nf^iWFc)G92C~lLvni}0IPEV>5<)XOhcRR%aaSH=S^3s zMmW;cPrEGkUKt!B+}12FNM3Vkc1EnfPHeGvFc9CUU7oNT>THvMSx z4&+2KkA{Mgc&;wLNUK{S9ddiedFdVN6XAD|Jyochh~6pDk8aS^gR=U^Ny}Jsg!#9yh0?Wo4TZ0lp3wqm_cp5UPlL0 z?O^UMy-%zv>2?Q>aMyB&tktw48WDebe^4542=(2iEtOZnNm_L*T^ss@fcJ-TLmuTj zxmD;irp=jnllorFk8NiB1V6`8?^p?w7B<654z%%P)dx%pNF=RjPV4t2381RAM{?-Z zv+8h|!U&CG(_wUaiHW@JJN;26L?`=H+x%*h;|Nf3fj%1|o<{FzMX6?2JYN(pjcw^4 zS)iSlOOHk>)vB93ZK)sI#=~B<-$U;+`AWa{&g;$1YT%whmq2NPGpX9u#gyRl+w}$s z#YHot>C&;78!WFfP)D~AtEk1DLOV13S8V@I{E8JUF|;H#VW~iIV?%WQjNVQo1Y|NI zYHn>DF;l#yx`a;!>UNgNe;93KUmqKtU79h9< zhZ+u{#e=pD5J(^t2^OrlQzSruKye7}&U^Eo@7`~%d%k=BoO2>;#U@$VGxN;ev-k51 z7DFqN6kNY8T;+Hoq1Cu~y1yHWXL-E6d`7%NYA)#}naNwU7| z`TE|;J%8pvL+Wi}MTNef1-jXVD2p{jd&Tw_KevzORqgq(08m6+PQVjmJ?J7Q)cri* zR88WBS<7TrEbKO`mi;Ym2H)CQ}ejc8h}kB!EY7L|Pxe=un;SP2z$wkk=4 zR>=CH0EeiPSHyZ2ymFuGPZXGUeRz0Aq&A*4@V_>dD0XL@UFZuXmaSx9s=2%BC*d;I z+t@-Y(Jq<3mlbA38HN?E8v{1KT>DY&@lJ!D2WH}P1-)lhW4>s$g3)!z#&|viE#A*n z!XJC0c&C3?en!UznG9h=(0**~fTTG?S@e---?w#nVaIgTbsXb> z(;QY9X4*|P8jzD7gr6q%im~Ws){Oi(sR^}riJBs-(w+rd`jrlcN;7}FKYKEi=E^Ijq4oaJ zvanmkeXY=IOU1?dp?MOV|88FmvvSmw*g7sB^PP)sc(j;0W%{zoa5%L`n{`R3S~qu- z)i|eYT7M=;fT=-_s)`n_d{)!V+RFV{qV{fceX%B`NuseOH%O4q`C=xIz= z;|_@fQJrjKZ*l2&F1iz{=0S@sTK^4-3k`#;@HmvzfP(gmu;Qwhyk+n>+*oTt~4+xJOJyqs>U z_aF2ICzUztdG-*4xZF-qRT@Kvav(VaRKT9QIGGccX@^V=^nRvWBC|dV`0^K|=zMTzS!+30OLI&M103^XAozq{mG^5%0<;1GCju z%|7(XL*eScS19cP&AlfwjXk(9m*>$jty+?`g~Y(s+{8tr1<(Vbe0 zf=T>OoQ}3jAM49Lb1$kXMgPRP{K7xI1>HJH!E;)tz?W#o0y4S0ijL%LD4k#6!lL#5 zzc7cTH&k;gDt|TAm4jBNsO=&Wd=aqb=Aw{?+U?jl6@->0J8B8O71h!8BUB?FulqY7 z5+#@aB*cw#EW61(5|Ssc0uPtdp5v~wu(X`kZHyC0Rr6DBU7t|coj46rCd7Q(fQ10! zQLO^^7|yTYaWkKrmBpW1Rf<9YuG7d{p7(sd zswf%*-o)4m?A&>nkvBpk$XjjkSZ?=Dn;^gVryXwf^PDv4#Lx#G+;Z3CXT;B3^p5Jk zFKm(N)w($2e<RIFZ`jfwS_vjfWs(E)mz5n4aAUGY zX@y-r^!})&)Rqh2ABsY({{^|qN!Hdg+7Optxh>O$6UMbrRy${BpzX92gHk_+8QO;> zi?@5-{}~*$8-2q5>_yi6uf!i;+FnuV+_&(kfM^RN5@JFF#tf?jv)vjQ9qY|AytN@P z{PzMQpaSDwWelRNg>J6+sxZ9PD_51Cgr zu|}A2k-4d#Q5f?>n+VZ=vmoTGafD3Ltj^Njb#zuWijT>+zZ`~Z3G-QbB%;m=eoxM= z!|Zi%jP_Z&@qs0fs_qfbe6LOK%%ce%$u=oAYHH#Tn!IQ9)XPB1vyU?%h&@!dJ|H8< zGl$t%$==ObbMIb}=!8^7khh?nahTDc=DFpHUm)9!dtLRbRkmA4rrL+K($D6JR0<~Q zSXt>d?{=_KfSkW?hoxIRK}shCtM9Zr3D1USPuL?BGm!|=eE0N!jU~q9 zapG#3KFj-|PgLAPTtHACVUdve6qji}EcUZ@1K*}O7aS{CrQ8ipp9d%;>=p;FYph>j z>X)9RB&BFX7fkxa!b++Q$r+$>a&@@(y6m&HNfRN}qInpp=Hy_{ryjcEtl(;o-_{A1 zudDT!SGBxgP2UpIYdiER{v}f^Ucx49r!|ZA=U0t>7!t(mI_S2PQm0pl6+d%a=Aex_ zsSUxoOQh_{nwDCYm6R(2(oW=c%nu(=%z)n|j$Y(|{qDX^&K4nE?tb1y>qK(`D;*Bo zdnT9;7#-o8{k+W{!as_~&-Cndj$$PA*pGYt+O5VsgXSeVOEttgfo3YyWuf4Pdo%)` z$8G40v&v!%WcVTgKm_DuSh;TWfILi5)`4>#y8(*d4sjc)ngzPO?aQ|ciN)~HEP%L9nZKX5Rlj3ZBE)DBq-z#R7i{zJfc^2t@9%qxY>H*We&_iJ z?3&d^6e3hZON3y5rI4s)*8qh?Bbq}+q!jX}>$!tUbj1hCGebgjbcYo34udh@^KyMs zEMbY4VAx{;bbn^C#5TFGEy6fA)1pfJY(6z!RVjaLd!73zSum0d| z+p93ipUFv8@x4327G0y`DAchRb9Ux=Z9_EStfkyXd{C8<$|$l;7uJ6X>&+dmyhPGR zLMe-CXcIa_;d&#{F785!%kJFDywIzjVSGCy39$j)+MTL0txtRPm{TqA3K*ydVnrL{ zi~5D~Ftu9I2SK`y_*Ay$Z9Pr2zExncuT8LuCyN|nv)HqiQm6~9)YfqJN;dy?M7Kg7 zctq~`#(gO~A>?5(i%d9R1flX%+avyNbbTcbd!b`SfIR zL+#N?Ml5tSEt=H(`k?)Z%>2~6!)l=jHZuAXnfMadXHpv|pCK!5XkX;F>uGGRnezly zdY>w+Ro^TbLY=F(>%vP)m-Hp!3Xn8Fn)S>Oui1#ldF5_ehIDNbI+Z*@HL5VPCBZ5x zLl#J~eD`3i%k8sj6@Ym+K<%kV#kx6%m-zYKys#(qaxk)klkey?xys~m6PTDsGV3O9 zclM(z{-IEjkT&d`G5Opj~U z=$n8^^!yh*nSYzmNWb)O&(za0&abrLk4()bS6$c%{|P0qklVnSC14d*X9kr(qe)0%GLgEvFuI z!@2*quTZo&O*nrK?IZhcI(&G-@vxHGIq{YG%30B>NRVJWDZXpYcQu2jX_IF&MNw(9s;f`d+Un$2IC;sV`Xz-z!@@(+*r zd+kK}@6N>qPUHD|y5ELI+e>w$f?@ZoCN=|JO>kCf(f(HDA7ert`vp(&*g0!G#U&K_ zi>Sav^hzbc=q!Ud-iB3{sKe?O1FF^|IN%7`uzErzK=!VcLid1nnX zgpdR>_Kf2+G~k%2Uf&Ms-KFJpj5ISU zFay*c?VeyHQ|yj*Px3Ar%bYz?>zZdW=UJg*haWl%re(BMqgy4qK}Z&-tTLu)s-#(STeRS|Jg?=(iWXSm1>CS*g-`z$PZ z?}r9T#tq^$C6)E;AU`epT_(?WvJ7)rouW>N(rd%-yY;`tuB z3LI6*21c)49QQ++5QS5*W@HaJ#P!G;BS$w7q}nw_)}lG7%=p{1q;6FAuIh*ZU3$7b05@Y^@u0?^R9KZ5gGTw%J@N6(iEu>Gv4c<^*T2Zb9sYP9ycq{|=Jp$qu z##)18ymdJ{EbN=pPHUl|lVD$6b?Jr?ki=+;T5`M6WQOxn#Tl&*r>{=VGAcwj!W{3$ zQ`y*9)KNyH;qXd*HDYpfC0$#G5pM4vb~;}!C-TK`M`lAYdNJ*cykyko^x+QzCIjGo zK2s$p=+jq4*5yGZQFV%jDmg{DGicXkZY`i7zfd(zo2rq}hxh zkok`zntKXhnRkC$?TS${bS!JhumKNMkBrQLw>;L*1e-{Uxn!pDv2IZTg z#7B!e_(DD$(j-`WFWUsz^S0}`qg8o+Y&|+@*A~zUFxw_#10+}t4mwvQbO!GKsHDy= z7H%J&Ko{xi^azi8z|8)O082g&p_4kV1b25mqT;w~4K}blv+{MB;3^yEdc@@*I33x@l*80|Ql~@4)Kd|FUK`X610a~Il(6yG zX;~M{)Tp`l3%1p;mn%1>_XJ@j=c>2j%ax2yWW%clFB6s^L&S96+7c{>JaTD=J#<}b z*%YH^mXWGi9Gm^NAN!`Nj7&+INz)InA8i{QkAKiFGk0lZd@y}$fP_OAc z?37p04B55lcYagqS)0zYK2eZ6epXPwWzL~H>rDfhc{kRy4qf}X$mXr7Nd~r^2$LFD zw2!+XQ}$}C&X-ED;uqNq2@QG~b9~&V4+@Sg*XtWzqP-1AS^T1)nkAK*XH*b>%*}8C z1^fGb1B>35H{(no_J})3>W<_?bZ$B8D_RQ-wHvrp^h~LqwInW%rN}G~#$AlrVG?q~ z1Jc;+1P0yH=kjzloRGu43s5&YWnIA3+8Kl^I_ju);d}O2O}DfPOU3%3=~QPozxwcO z=tCXlC{MrJwH0_KB)^P_Xf!TF%}er#hd*;b#X}P>4J$DkBrBn`Ii9o223P_-<8Cn5 zrWva9my8xR<6wD3_?49r5YRKbJ~1c7d<(o%8P>;5!vI;GWQu3`wY=g`w9yg69{Jmf z5v2Ekq!#c(Vo!SFFbtkNRVun^Xq`fw8N!PJ}1*Sj(!y6g2&pvgqojRy{_mn5n;c-uqe+UC|=O0 z!5Uczk~;IO>Ld~frY{4nBM)Dzb_16P5XtuLen0TSKNNI*mNFfQU)rG?am~MnhEEh} zZ%}7%-c{nubt@P*AY~F!5OVRCt0~J7?0_bQPMLp<8A-pG)R_xFLI9C6P%phBA_u;L{lKVWvnAyg90-x8H>R;I64` z>}ZTGIQZXrO1fFE7?S)6{Nuv&rQg(qc?$#{$a(=CgB|@fNn3e!@ibw#Ham6Va z2}DtgDA^u^3@N8os&p0`u~xUJ;=4}2&C}_fo(&&a)gWF#F?AUu;;_5f2g|bYZ3NZ; zEOtPJ6qnsg5oRV6s}E^kEsq7Gwx#OS+K6(v{1MQ2w)CUgXU`MDf3y%Cui zxSZtQlQ2HPKOy&SG^Y%OP+VD7e0w%W6Z-_gl$%hd=BXN`vBDSo^5uvBGHj3=QnMOC zeSgS3|6O;pa)=q~q!Hd_^Xpr|{DlF2ekonb#KpBl)sj9YQS*$)ssisIZbFjwVVJ8v zY}IHxI2s%q-~8#-x{^5z7{)Gav3R3`?Wr5B5px!as*pjqc6@2~xpF6&!^U);rD0kf z$a87012R}993qGyBKiJGFtFUI*d<+(uyu|g?93NCF0w;5W()CP z^l}X@P1}htdWBr8;&fj1k}UO9NQ~Of$?fUD3MY?D06BL1%#j`hi^oa}UX(&BJ;PCg zr)C>0!3G(Is_fBo1&5j%D2RA%7JCrm3K^@cZI=FgA-&CEmyyZySdc144mA3HMbJU0o}Tcmq%)mdp<#9miGRMZe(t7;a`$?!|jD)hl)eQ z`tXA}5vK#Gh6^tx#`}>YcmAP}X*BN}G2L|WTQULdo$Y3w$Gxc%^3tzBFApb9sCc+i zN;rWJxN(Jhz-TT7%2y`&;HC8pw;E>mc~m}AP!IEY_`|>hNN2OF38Dz=SPsQ}ooHDN zYRBo&Scs2#64ND|_~LO?eJrfWK5nxW;Ws%U^=cy_!kv?2#WjSkTEq)i*{T9NX-YBO zyzo!K=R6bWF@d#bcorvb@9@_5H7au6qHwrV8_hlU1_P3&SnJE~)Q_M9e(qX8w)M7| zW@7hEb@$nzIGH31K>fOM%XDy9h5Z;7?1BM^mryp|V-sf43Y7uvsFl#)&O5VLBWqXQ zOrK8Y-O{!vvLX6|vOiawa43Mtgh~OMa0PNdA^P@DmPPdbJG1WJwpR+XY?&Eyn|cIC zWF#3m!*ga@=0$hVcl_Jc5byA7m4fqC`oju4(m6cIYYaYg?&kRdu+_-4J%8%@!+Y!3 zj0)$(f--24J7QWWxFlD2*14ljG{bgu6rsX&zOsTGnE*BxjFC`lQNxf->zF;ne^=GzTZ`3|JBOH~or1L~=#bY_u zc2l*-0+c2Uykwn{reLdQz=L>cKTOSfNkw*_ph`GykU7NwsmS8vVFWJJ4<0OJZPw|^ zDp9RC4EYngy4hyYnH|C&lqF|cb{O8Dvn7c_Oai(?6yzrYLgkB7t3G9^tZMk7F9@Mg zox1(*e-Bd1RoQ&P4}vbR6@=;-&$*g^W80K5u^4yvmUj&j-4X8)|Af;H+b!>>$FBkwfFf)qY`Lu>lr-y8G5XlL6s_xpJ!27xG zy5%J@BUOQAk_S%0WWNs2a+j+_@{p6SX*PAq{ZBl!eHwj$mtU+!=(xhZ4zPICr%b;Y zo=d5^{<2#@pcf9edte&luMo~`#c!GV17w@AIDO-Lj^LFPQ8%!S!Hr}=W79v)5N0cl zFi!v+t|@YR(i7PFjEP8WlvK+UYgOz&G#D&VJp`uI?wbLakqk-?(r5Nk{*t-v-~Bmu zNo2K=i6ek~;Td3iZ8^2lH9y+h^x?EkRw#sQxL^A=AE3|wyQ7cXerUwR>j@st!>bL^ zM1@OTi^*M`bFYr{c$sUd(s-*+VGs>I*iaa+ffPm~GBtf1W`+qP1QdS48fBl^zVz#(-kF$5yx_Fe_dszG^ z*(2ZA9by&DV|8)DM6m$PB&?&Y0=(x3gEYZ~wzyeSU)r?rsFx>#H=7GHYrwWn)%F{1)+zA0XB;K}UQ6jKqnC+Pm!^4Cy0rB~}Z{zve1i80WBS9b#UIH{~`C?E@T$gTmh?&y(f1tas zYwO0E-qRsH<( zCQ$5|oef)z1U6y!QN8pe*qHmF8g8Fyp?WDwvPKCgBo@gDGg^nS%)|H? zJa$z|mFKsFwgJJQ*stUZ-6ika8Fow5A3bZ?F-6^h*$fvwAwM8e8p_?iCEN##b(YSk~V3))^Zq%%}_|xCodw) z-E7)K{AE~~$TYc_cYa15(QldI#|A8pLVQtQ?NUDBH~>b2EfsC3@wUmAHzz;<$YJT1 z&g`2rTo3*_9#cSrvOdk)w`LEVYdm;ut5#uTA1VFLSByc;H2kjxO)Ya%&keiMaOIzq z6YUR0v-EFgH>knm+M-SQYpn*nd43k&?dtDcsE@l`3eBM&4}F z^sKQ)D`efT(P6iE4d0J|^wG!{z&PWL_i}j4T){E>=5bnGFkc?Xv3ES*KpP2Z0&V&q zFyEEEPzg9irW{MT4SK!MJf-LU#{MtXFOIMFYFBQ}M<4N&&JJdVxDArk+q!2qcYuA~ z>q8pu-HciX_n1ZO-3wiMY(Gp5pKt)*EmuEN`0&|h=eX7{z`!g|h7Y+Kc*-Ihv+r00 zf;J?z4t%!MvaUDy86)n4vgVqX4n9k;lh%yjZMOBh?f&QY?2nhRfr#4$B?~T&)y9eqA-@X`P+$7(NU65_g~1HXV zRIfDwQq|hR{sOGqqx;cP6Io{nP3N8SrG4DR(!j5O#9&+&O)tRJFnL&*{IFh!1L_!H?@Q3cHtLyxJX;p#q1}v<+7*w z^*pF$BZBtBV27c)#}_4j7doOdRF;?tU9hY!)A4}Jse+fsz6HXr?*v9ZB!1->(7FK?lvWFE{Q+wt5FG0~PGizx0xSCM;MFM;QU< zK1zyq%fK!uD$FZuV*hFc)AzdbNEtY{2Nd!UtJs-e`s#f1v~$3T2!DKcGJQs8F88eF z_#?!nD$on8c;Kw(;ZX~wP5UNqXzKlBKm1LbsTY0h5A{jqpih;*nB*<2V)9b|I@XM} zg5m@oX!vVusR+&uhIOx2y&f}s6FX4LJXvKv`AwM}?7?xec)y_noYCyC!JF!6_RwNY z_>%q~f1rD-&u~ISOP?55(HMR&Cvm5wJo$ySc5HtW3U{dD5q`OvJ>TjH>I!zI!N+tnj`#*U? z6u6dFCwEX6oK}6+**bJ>Beotws5Bklb4BYMsU$EneHVDsYKi1WhfLzA~vbrC<} zB?bU$Qi1CR9tx31sew1$>uf7+(?E%4ll#27{4;PK#!@F|0_;jpRPImFU*Qur4}O&; zIvw8zZKetbAMqtO9G!ejjLPfmxJOwUYG>|m)N&7>BHSf-%GBMwQ*PE-qJF45xMc|K zO9d5c#N1DMX>>{)3q$CfdB$8MVzyK;;z!9@J%UFa%z?0*C2?3y(eH zWp;y8`~@dI{Qn!XMeN!mi$}~?zA|5Fz0ph2dqw(##}zLMvFn|TkAM_B&uwp#Z}0E4 zUVB7-gJSMV>-F9b|6V&OKlFYCKKkEZ+(|(`M>Z&8{~Khcn6x4DlOJRzEp)@o#Q}Nh zWB>c!WuHvQ&gx`D{_L>Dh>mj`d6WL6rTgMBq#7&fJ*WibDLn4y>gL|V=+WQqN1G87 z6|QoLNEKI-q-qLV9t<1nS8*?>A)nX?5~dQFn7N#sV|kdB^^(v&U}=c*+q9m%nO1ai zBGEjt)F5fnz*IPQmgbggZnC*TXQ{Nhi(KCJlUWLYmt||8KGJnYG(%C9H zBfVREXDG7wZ27!&?!dftFrc2kPxAod!9fb`xBtC~)bMTk--h`=9*8&ne~O$le>mWI zfuoF^iWIBmY(ppoH-huQ8~BL%wIQSdcoX}Ou! z18{8CQJ}X9kjVgIv5PqJe!nau{^NR;%X%tWd^wy;toun}rmEo#dy3<22jKy+U@oQ! zBO%Ji#u%*0T)_o+VSsAFq-Jz&)AC|9GY}`A^L)LS&G{nBNr$ss^Yz(T(C%^{%*tW_w(j|o2AFxe}9hOzIos8B-!Iy;Z&p*TcFpk z4N;FuQR`b$UB9epS{c7}gfu|eX&-nX`(lg!)v;dEc@;(386lqB)&DB)i18s;Jej*j zgIATBw%~XZ*t2PbOpEu&ZdyF>GQf7+`63X-@Q7~gahSs2R`tjF%B_5)D;#^pO@RY+ z*QU{XSGL^n6i1b$YtzRcIS!6K990FnZggE~CSCs7?~m@<@vrpAe4D?W21(B1^vj%~ zG%IedTD9@d{R6?K^8X|PWzu2~y*y4g@(_O}Q0U|iK6tzT?xB+8&hfc{TiR$JV92v1 zrbHH>v9v5Bqp?KTGT0b)jjYmn)9U9Lv%7MV0r9SWCskmV~yq);hTkqC| z-{luq8x;Z){-L1o5JI|UU2R?Pd7AP&#l7O`=*C9K>$HV#fn>b0Q&*Z6)f*IdfM@Oa za9S(+sdMc|d+vvtwqJ(Q>ldN`U3N}8>OFIsp1oyZm@zS%^s=FxyV}}k)PsInif1%d zD~f%xGEO0cGUwW2VR^-eo~#=@p8o|1j`cxb_zAtCk z68pMCz&<*7Wbb75h|;#$6&c-IKlboj(tnH-Gcu_D2V#;jle{cli@fud`RdM<{{_2O zZEunRw(hy+zj)e78Ox>__j>0SwcGa_lGoynK6p_qeULeJr4d%6co$T3-D5KSuE+kH zJDyd5iO9LYj{>IVVXB;1I$g1gAC3W~A?t}Dz*m-O0SWy2H` z=VTVx4td=kbL^zNXPbHPk=p#C-H2K-FETUVpDW&aPV}*k(_)*$tjl9*j%vH!08_}j+ z^{Is(12?U?gzw92NU7SUhV#lH4Sp_b+&k$CwYMYnUBsngMuH~*?0Y>+^AfC<_Nz4@ z3;SA`^BVtJjK?Hiqt>5V1wk}qez$dGbFmDt@wF)?UDBKkEX?|__5i#4IGN88dp^$d z73Nmiyp*oKWWx2HJ|`}$4lyvg{LCJ_Ql#yG$O+oZk-Akdk$#~wQzN|z(_PrZOnDt8 zLmkuj`U>aSLjkc5HXW0lwe&=2%vPum_|E)dUC-30wwD#XIPU-S!^bP71*q!p2G?YIJeGH>W0Fq$ z((L-Rn{n%^8}?r>=|6)Q`8id{ivkKFS<#u+Nl@weqiYm1ezav~9|ByjVHVb@YAEWb zFV3Uc4o|+(xEI=dSD0S8&2+2BohxI9&k`waqwv~ua)~!B=J;Hlb+@|pHqP#v&~3Nk zo-ePGoOP+D9(?%zV8)%^#dVls`~mSpgrLGW4ZnC3>{(IcgC~bq*}l00=1QwI=@}#2 z=L!e&Yevu#boItr3?z()CYW4}SEG#bL#IU^?)nrhS3aXpMrwzP`4Nh%-M`j_`V&HU z`E9J7w!G5)Y$i{9+$ZAx5=Q;?4C&646k&y#ha1_}C6uYpetd~plr5RoS+;GUTyl0j zi1sJv+>Sis`k!x?J`04R4`LrEkcPbV<`*FT;@_Ce@lV)P@@JhlygPh ze^B#I;U4-O20DQZHRn_^NU@Pc(F&g7`d)A*C91?2NN*RWu@(5en^)*p^5{Zy%ainI zuLKwFKrZI6;N@|HxPV(_&hc8HycP>4zR`A<^8=lJ?MrQgeR(+-CnfEPR5w+%Ox0Q$ z)vm3x#vf!2lJ!7Idkj$VWLeR3<4AMv*OF+ma1Jfo8xP^vO=T%la2TbRdgIfG7ks&y zRhqm{^Ks`9YMPon8=FPfryjk1ME9SE;Waaf8&lVE9#ODtURk)-Me$tz4Rtfcji%&~ z=gN~SZ)XZdBjaJdPY!JLg$PBrFLExlu+bF&-dQ$)sB!09W;O(p5Ax>k;?JDn17uW++IG^Ww)bD3(w-KHSal_-J1QD2B#tIqhw|dRT5Ku8zZE z%+%WWd}czXxx)Ou?oi8BElEF`YiT)iBzwUE(9h9GW(y{D_m+;|dHz8Qm$&Q*mGu@0 z3N@*^6JrYC%7V>S+05L;r9&B0k7%4Js)XHxO?iXZy-#=o&r+z^z*DAPS$Aw1nIkXFxg|J5!a;ALKSPdCEkaCbTG5< z&K)`5w6ds$T2wLgWRG&rE_>{UE7a%)Nvz4v8*8?Ay71<9T zF9!$M12~iV75q zT0Op^Fw+#P_cvNSU>x3kqx1h9tmgGCZx^n7r{MfR9>+e9Oy<8E{S3PEgwg+%C-hUp zUrxD?ccgxis3v{)c>E)Tb7(#UA5HnJJjOly3VVM@JY|rHB<$HW#ZZWSr0$}BKs=>; ze5G^+i=?XXP(eZWxl*7R?h}-qQ{IS1#<#c#OGkZZ8xyoVw@7cUF(9ZaC^)a&~sP z0Sl7X+gM&4{0)&@8XVb8KenmOwg?U)x>gGKplb0bb+4dhDSsscPmkAnO!)w6oJLaGX>tvz21XBvvCKN^GFpt^>}6J6`HqUaLta=TXe=NZBU zveVifOoxs^s!(GM9bO8*!>uIGbk@=GOAOP%gSOJa^gy!#S~xy&u5~QS*zzEEW=Adz z7lN76BQkl%RPii!qq7Nc$J&%cU#V|25wt*fH@EIl$`jfYT>(@kQ~*qO)M(fB%T5jC z`40u$Bg}A`yK57`pZ2Pt1bQfPM=Z*kem$L+60Z0wM>3|lhT-vywY7?o^+aH$TE20c zpU&u(ASPTMAT(EyVl>B=P!Y?M35;riz#c1ew>82)OQ!_*_^oehVhb}{HJ1A1{7^ z8s-Kl{@F3FN26q||Bds76ydS8h`#CEI$K;*8T7fa`r62y8rT&%h1$eBc-sx^Ipu5Q zbaWw)9{)}?wXidjv4l&6B=8%6@7n;y+bjQ%kkJ1Px;GmY$qT;4``e7lS8Z8mT$M#B zh#w`-0}`bl98G;M9@}~37MS$R&dHm{|I=1u>yLqyg$L(MH1!h>sxL%*Yk*hTi^0Gr z?5U!R!HXYRE8jMTiXF(kwWHw+-x~g_ONB|j^;GWQuHth8^P}S{)EmT)CdrT0sq@qd z+68u#vJ&>}BH@`YHCt8e#(@2JZ^<`{+LbQeFsGL zJY=(K%DwCI>ju2N$eAxG@-Pi;)1N~kclq?p1?G8M&yQ{F_Ut8WpsO%n^gx-C%y}j? zGGHy+;Mx47p%Ndt;8kwpmLcR`2VekQ>$$8FbL4)kG9#Bcodb5Lm|FP>oRMGdYl1*A zfAG6Co*v}nb~Bq0a&)v&i8i!(ek56S+U$95{#L1>kn7JAGO-eK-cDI48|UWPs+sw& zLm*}8s9{Xx?&Fb}kgV(P1eSfh&ov_HeS|kcwRis-fTZk}o`6hNd+L1HI2{Nr-TMYM zQE?jD-U_{(rhNsMR2jwW4GJKD;y)BOhb_JEj)FO0c?))#yqgJ&W!rKfK>Cki5m1Y( zkv@JsE=aR_H39U_v>{)A2yR_y8f|tc@g$9j1ZpHSHdV()*PaXXovS?39aA&!qO||o zA*6j&{TEJ`49x-Z{bZD0LASX%rG|^zIm`{2cI^TF8W)PNA-Z4xP3~fA&RSor;fYR8 z&sGpr)@*i+TDPOu1gZix3X!17A`tCh&F9|7!HZt%D3cLT)Y5{3K`nXHP;~0GT}^mF zaT~9l%gjfFp@I41Bb{>LxB#wF=hQ2ah|L}8?)&U9IyrSk$3r1+|5`*uZSj=v6HB4h ztF$c~B>$j25kI2K{S{VfJS`gu#(#t#=my+>9)mNK=C!ho8)wk|Yix0L#i`Bns_Sd5 z!&2Cj>%~V7pY(!zKS6`lzVVmkMic)oVK+veyos=|d1Ucj?8g7gv7ibS9ij057o@2^ zxL*77v3kXmJx7#6X*M=e%lG3mmtU>7Yu#MFL`0IfT;m5HzL(Ci)a`r~toZ!Zw(zw= z|7&8fS*nRM<|o_(+jrwRBWV_{-~>M!Y>fWZzkl=aas-Y^ULWS__tYG%WT=o}iAm<4 zjFML{&#h5&=_0ZZdpy*(%hWbr{0X}dnIRgVfyN9s16s{3v@{S-q8*k>a8KqqN6V?m`- zL?B=OO_t;t16u*~Od4HDbhN>{J84$g{Kdn^DNppGV8&q?oSa>n zo+uHqSm!Kd*PR$eHqZX}P^ck@Gy(ROmdB5WJ>BBNoT!;|&xgEOlXG%$tOTbQ_B*AW z0XEJNMLp%~=AY3M=_s2BI{OVBZ|J#wuHxp8+b{2Cu|Q~|)gQ$3<&|mt*)i_zx7$pb z5k47kbC>U=&|8Ot=`F8b9uJ3;1KL!F5 ze+d`=x)ta$t?>7(DWaU1M87d+?RjHL=8d^<;Ee@~zA~SrR}eDe`(>~a#goZBKFgoN z*Im!$Vy?1ZD!-O9IpV)dEJVSv!E?f?u2g4Xx6p$MeFs*7EsZm%fl zY2KzF@{p&*u`NH-7PIkmcxpjhmZ&|@$XIcpC86pZglteqn8%(z6CNy;^buFqAFw^2 zuMPfnJYSjfKFdEB4H}Sp+?SVOMeFIWsEC5`+^fyfLg;myiL_;Bl}XL(gfblLZx3v} z_B`$|ItDAm3s15}6qEzK?D1`!I77=X`#CU$EtcVnA5Pi5SbDQt^&Pe+ad%AVKeZ0I zrzWlTnP{|?@c7CWtsI6$V&KuM*@TSz~k$1fPR#&g^-mo0q#bmInY7c81ThbH4Pt`=>l) zT5n`lufJPbFE9e(Z`Sx-3~$CO>*HJWtFkR$sD?h(w zL1fs%ZvQw?2}5f861&C5!y$@2QMYuwghu*JwXHN<8U?4QUo9AyGL&r`Z ziA8GmP?q)!X3sx}1p&qgW%FEYJ3Ekb72P+#OFfZNl`sQbBZA4o78h4yG zT-VK??4%(buP6fNdFlwR9T4ae^#QVt0e^(I3>l(L>g{g7@U7xW0HEpGA&cR~I7U}| zwACVftFk`|o!0Yc9m(B$kZsr2!s5?&8yE4EB^dglAx^Ze%3@Fx;VTyyV9!-cH71)G@->TBOd zDl5r86d1*qO?l+Alanh4>mg=wq%RnPzk(iUkoF%T zv_*bDjTang^YVni`vdJ()BS%wYZGq=5U6KW+#TIn)!g_G#R`Q(fp@@V2~Huq_ndG1 zynb@Uc5>y$*XuNZEkJ9G$jUL(9i4)2d~Zx9%?d|p%ZQ@fa=F@(**~s&cGAh;rMUBz zEJyg9eE;|2gbx2sH}ier0|kZDCeIZD-EFoHrgedz&c@$MvHuwO4sU{)b-a-O5LZK^ zT3c=wu6y4XTFHK05gIHbN_DUxcU|FxS@rRK-@sEk;o=&bpA6+<^r>?7AHwOW_RX5m zzVF|ecV9lYNf)A|Uuk#pwtv`O&?~(THCC@Pv%d!)Hk3@(KdPIl6tRc(2U_$f@j7V% zU(pJ9INgtqA8&mdyiZcyQ0+e4(p)@rC5)}(>H-3mvX9qug1l2{Dh?$FCMv5XBIsQa6Iz#vFNE9gw4XXXV`mr=Uf}j&z5HQHk&my{Na{rN^=K0Y1_mMwG8P z?%RccLp=j(~oSDiqbVg z9{|)1#Uh(qd-?g%#&Bkvq=lOO6-LoqlpwkRcTDZ{aQi|TUN@%D4%Q+XwD#+|ok~qE ze47v&ByH&Fc*{!WFJndwErWW(lI`EQx*U)^^@k%{qT#*0zeX{Wm1}kQ$Vltal1N9d z1O9Byhphz|vNLT1Ou3sjQW+cb#c8BXP^rRJ0&P9yQfWsQ=Q!_txs!6U-r1*^?9TG# zgPC9Z{xa;%1Xah-dGUzh3)9=Bf*g9n615vVF&lym)^f&rS|ABM9g&sTdAxbCbLv2{{U8uZ3Xc4I*zw( z-qcU_l}%p$o*f;(N3yi~N^xq4r`^}btL#q2y^A{_?571o38r*@5}Jm}e&tqbXr`5rh@3;%qK`rt;k4 zUArvDO+_h6{$|RkZz-9^Van0O#;2*LG__)=mUy+)!J6xJa3(I_+y&L1;7o0BESM4k z`|LzoJ8yq85j}29auT_aPVI<6O5FMb30>$ScE2`2Ta^+3M<6Hw06-`J0000000e*< z{$Zo&ozVlW z`YvObj(tFmm;4NapD{T(BX5t1ln8cxH!_6ehSz<_y)O!KCGA6Ue=Ev>uzH*3+2 zMH#EIsO40Aev_DdmD>LRv4?BDl+LbcrQ&3-}h(TJ)Y_Dd1lz$t*5i*ZfU=@quKYP-yOdX2S@Dx0Je==p=)qtd90yH zPSvnDg~ds=%{V{0{8gFRH5wf@s+`vx`{S>V{{ZW&>GiseC0L?;@jW~q=b(M0v}UV~ zJRYEu%5jsjPOVGOoA96L`Ag!?y{g#yiy51LYCQZuCt=d3TGzu;V9Smz}!YtMdWQOIMHNp8w8 z&P^*emv9_jtfWGPI$Fp98Q#l=&xcgY_Dji97k%p@}{23YklmePsQQl;{O0fRWHXazgaH>sq43w zSAQ`z;ybD3=hx01!$Z584J<^{MrXdReqA3;`#yaZU4r&YN}eiudX_U7pA|~=p~Wdn zy~*y`*6!=8pS#J}DAUs&dA^&{U6*OyIfsrDCdsJbp%|o*(bcb)t zwA3Ki4LjP)XzXascxuHNmto5?NJT~az0C^imbElu9fK;%VNKtMevgr%RZUoP*a|!< zGPlIhs#^Bp%i$d2lU)t9U0aG=mKv+tS1_1l-l1OhZSHBzHDad3CavGxV9j{js{-rH z02f<6zW^ix+)6B+`Lh`knk4%I<}(qMO1D7Au|0R(306SrmEUlN%aRD2kN^}1Xmzjv z1povBfC2$PfKVm|za&qU_<9}hLTg2{7Qw}-7So}1T^jyStj~{ zUYvl2mmn)8)8GYPkQ9X>6H_ZB@lb?$ypd9kK9row2(cFKfirc8pj1)bgK?Wc++zA$Gm&yW0<9m8#>a zWzx>_YIkci%P7gZaqp{3c|*-{N5u5)lf7FnYGR6~)!d%Sx=*^UlkS{L%Qn8~?M;`O z=#N=$J86z_@29MMGY%WGp566si*Tot=E}AWySxr3?a^z)d%^g{uTz=T?Cn0MopFip zj=$&ea5`;%r%OL(a~;#u{GR8a{h@S5v{1q0@e3-)OK)?En)h>mt5ap^D?c->>b6d& zPtKpUPqVLsv1zuppHYfx`!#!dc)QG%qv^57Vai11j&9pBvWa4!6W-yLSfsc6yZM7G zHF4#B6V?M%9z`o7DHuZ&Btnm3URq{~AQjOL=zoFh)IF}|iz7#el4+}oE! zIE>1)>*fm9;`y49LnwxhD>X@3OVZ|17$P~i{9biVoE+y>MMYjxZ)N5tVj7g&uD+1+ z-FNM8*+!GbOC`%QYT5p1rNXkzf|u53#mdr@e#AXwaT?9Jv-FcR%~`9uInU)E8FSh# z+uAz3Rl|tyo>BSF!W?#-$^ExIqVX}p=sgunMdfw*V)0P=#xce9-EcwqC+2lscJ*JX zF>WG=_Vb_0Jl(@Vx>`Ft?o8J{5&6%P+q)h5A94!$jV)W-rlZE{EXmqatD0gRXBXg` zv{m{m9ZOZUZeOp8shX$0XFvJycFjJ5)rvT1h^9NDG5-Lc7uS85docE4*~SK*7ffj^ zB`@Z@oqH8(C#Id3VoMI9mOd3KklO-2fYQnIz9vA3F1RDynCzRw=`k!e#M;QcK{CIjNLG zlfvPYQcW&I6wUS^fZ5rr<-f+W!C+1sD~QyXU(Ct#vF4Nq3_mNx@5U zq{dh(Qb}*zSe!Jb8r5i~p2l%GW6`IH!KuOQWfe>$#7l|HavC-M{1e-2BU+mB(W;Jo zo)6n^u-9firc|w+WcYWGXB96ekIN|~3bOC3NAAzfaLdH)dn0=Gp38`$XVzQ&+Pgi| z);#0b>RV%UwqDiEd_Jz^{?$Fc_~|}V?R=fu&$G{K{f1Vlh}8Kf*K(-J(av(^DwHkL z-YaoZf7VvcDC$oO_7?br;3l>r<{CatbBQU zQ`yh74zJOXr-s90Zv%a**}8pCIgC}`A71wvrP^AZFDRVT z-9Jv}xM*J7^ftLr!bcnVKOH^3r;M6hPxUAFW#zN*I_9TlYINN3ntS8x4#}k2nr&Cv z&kbGE^p|gyHy3MK-0qG&$f)SHxA}#LmN!T}fETSA{H#l7-z0CPTD2bj>>Aj(L*V*T0_+PDSeP4pW zU4CwjTDPlH`n1*MFGOv1I^8ako-4J*G41~V%*&9`?7e2Pt{YTL{62k<^HuE++P7;M z$CLX#_BEJel%1oS=al6_gm2YTUv6HmCtKEUO{yYd#X0uRDDdk(PT8W|`ll19uO7(f zK0PDN-?SIeqwO2py;x>`(7mPO9txzCo=t$4)v&35MZzC@_PCCruHFq!rZIB4nC^~I z<=5jf?m8`rqtZl8t8o+GJm=4+!XfpKVP8i-VLguEsYff)IBJ!t+wJ?6&(E2_*R8Iu zQOX>}HYkpB&R+YFXgseep$tA-meHXUzRYRD#?GqdscS@Iqp@Ie2tv(Mwch&}OtOk* zT$U3gj9N-7n%N^6sgzMJQwfyr{>85QxteuW)TW0chRWcq_!8-|=xI$;El8#zzlO`x zvQhO$o>{pZHV!ei+c&v{)UgfP7;E!hcQBcTaZJm14~J2EuZe`tTC~%KcGvZlHLc)Njg?yLp5tAGfU z`;j^cTVBQzEWBUH#0O}VXZ!{`PGWX4I-XYML`rV<>JdBcI|S|j05OyYFafaS00000 zP$wYfP#_5a0Be=2H~25O_5w~~{{{Z5{A{%^)BL4vMG6t>cWQzJ1sR(Q+(@YArZeUgSuqy9uz=p52 zz@)syausP_@>nfp=htLZs(y|KA_H)!U&G3u-D zi2F0|r|TGetJ-&CU95H;jQ1M*PR_63-i#;=C?Y)_{DgN(Y z+U=%!RpHz3jJ&&Q>i*u3v)NR0rhYx1>BE@p>)I<>X#W6rg2ZB$Wr2;C)p3(; z!G5Iq$I0Dz8S3_4pHt2whOYSf!$V26H9A~VGsRDI{Uz>N6Sgf2+7w}j%X1&9A!*2^;$=O9m zcKeNo79%p`sitOMJZsG5XL{Q-$En^A7bsJA{TO|P{>j_)w*6L`i1vK>x<%*wAV5GfdY$-cjKnS(nhAgZ&U) zmgxLtJw>m5?sJ*R@mIxTYD&FHzZprsr&YbQDz2%ktj}!opBHAgq^62uo{`-gq4kD> z><>cdd@VdSL8b8YR28FWCjLhqa{bEZoVQfbO)<(H<1f=nnu_;o&DpzJ#+1uEOO?W8 zONP;o-TmGs6I3&bGUPCsGfRhot@@bFaLOoh6f(F*HgH$zv86TlHDZSTA1&o*_2pwu zYs$n!a)w{}yO_;Pq9wbBz*}o_Fq)ZRwMPqYyAv6eh|6w{8Mv>KF`2_sDdgLuhqL0h zQwg5-tW$=~Dps+jHD{A7Gt-5P8ALWI(s#P=44LW0EznJCIK&eaB*U7rV0fj)Hl; zgr{N^x^o1r=0qQnKz0XE0zd!()CXt)03-)!0k71pP$2JM3zpyj000AE1d!>uL%@N_ zavbsvx78pay|)3&bomadb5>JxmXIg-+AP~ui<*E7sYHLKxxw&B>ZGX%z37`(C* zi?ZC+rssP~sxuA`J<_-w(+5{C%y3kz(60vyv};pSgyQ;2Ei~7euWsbiR8>skVYj(z zDv64tF+LOTeBIke(e0!&*;UT_CC05kkCSrzpET!zs{53F^&9@JWe8I0fJ?$s4+}&kepy`}O0#lu^ z_^-c*uWq#J$L!0?X?LW0PS4t#KWf_J($^Jt$4aB$9e$qInC&f*w02F-4NbYHx_Z+- z>FM?MIn1NC{?u^UEVT9;UE`sJsSXJxH0p5L+$y77X?Q6Z*Rr$~-Sw4QjQMzU@?%ET z+BWTas%}m^{CfGgrJ6#H8dW&?M{hHC!J3<1EYr#49jyCOc0bu&Nno`uvY{+{`q8Re@OA3Pcp-HyX`~U-Y@ch zVO@|^%5YU3qnzp(IaJ|p+)<++vcGCi$m`n8=$c|;#W?oW{{YrLvhDgE(6vq{QC4TV zpU!@e^p4GbiGI*~QpeHMp3)tlW?9^uQdm4qM;Z`+t4cPC^hZ$E?W?+({?@sx<>4Hi z!$-2LX=4^>ihh1G&Gq+V9>P71_DzJNhsiXa8t{r-PKsClCk=O7cH@$_V%th+ITNJReR{J}2*v4gImd!jX=GFX}j$x@3cD8BZxNUP8si_o0 zVx1e?@i3aA8DW~0E%r3#sg_Y0XQvBtF=Y{kYIONG5UkLGT>fJtEF#S@nv_%KgE)q0 z#@ixGIEF~87&2sz{D87xU2o6}M%?}&Tf`!HEzD#&a{NqWSzYrnnK`B@%YO3v4uIw- znksTm>t`FXLE0yFP)^(b01%10WRTl?GGPw zfma@Pet=c3`}hG@9qqYtD&fDWlt`qbf3@IP=9tSI=--kICYBk{ZEfAu%ZZN*4NNke zTim(kjcVC?nzG-x$|hkZB3yniD1@Tl0`jq`P05a}Ikywh*R@83$@M;0UnA5RHXj>< z#7Bm{7ZpKNr#0glCZC@(b7NC-#mKpCsivsuF*ugi_LklIb8h7^RWsHmGZXN9zuPy_ z(JWJ|oOU0cQOdDWyrY!n>ZM#8ebA{F?Vs zwr--it4~zh_H~bjdB=>tSnU_+(e~`^GdGq;uX{nGk>oewcpWD>Q;lfyyz4*CO8wVM zz};WpAJVD&HO(>I9K8Cm(e8GiK~{J;=f19fT^@zlKhX);{{Ur*7`)3(Q^n$(l&aOQ z6*^u`@gzoraACQ4z%Yb4PX&rgV-P7;K*)p+|#g$`sOT#^)V#RaJA& zTe>vyOmc^9!f6Onv-dogD;g7bEnigRaQbmYaQl_E#y+)T+&5`tZZ@aEcGo)?&B>Ng zL_=zZOKT}ZpHm5~lv3HFl{EhEoyj#|!)}&e6q1tgMm%eVdUzN{&xI!XcbM@?;#uK@ z>%-)&$eEU0EcCFO?H#(3Wt39brG$K?w|2%nOyY@VjukFuIcLKR)adWJ^e~#ClQlXk zn_mM7s#g-r8c9A&!5FgPW`#G=1?bBPR`>yy6w+M3z{X@{gdO)@Mk>n)E}@h|EMkmi zS;R6$UEIZz>%a@f>zEc-0^m$<%`hyvbQu%S#%Cz9c19;?pF1NSXEm32<{oB2)N(SE z?7@WjE}Mi(R!uZc)RVg52XXCQLcdT-LIWT<1KdCWLm9Y6p80|Q>=YR(T3g}g!9 z09zoZAcvR$r-(p-&6GAo&O*xfu|#*1ppn!@;|g@M_>PE+^Jy`Fd-7dI4yfktF%V#B zbYrNE$PIE}8tyJ&!mjPxpNI|Ze)A}vVmto;iF3^nZxV=->DQrEULEYv5pNJ7^SBV= zoxrO~`!FMi$9{lAir5Ocx40E*?_mP24fN_<;6$l!boTBpMI}is%MvRpZqLh|hFIZ_ zrX4*NWDF+IkO#%QpnQZfqj*= z*2Z487<#FNza=E@)wy3|D6c1~U1h89ZMTNwjXhklM*yO?-u%ZB`n98gT_f@*5$f>C z3<_M(;$K(Inw}9QzV_%&CQ(Fovd0e;?3byG)e98EEO6T>MO{`W@TcTWQ{BDZ!#_+k`!Mna|+7}E3ABg%NSYmB+LwvhWi-IUjpgDms z1seAmY5)KL001e_A>tJA2w8wv?_Z-mXw;ARe zJ(kYoksDiY`IaCp;3JasA9c)e-iWjBDxynkTgYV)ljrb7$cDNn=wEnsyE4ykhi+_T z5oES9$L{3<|n? zZEzw~(_8w1R~Ify-Q^gkOWh&{U=!W1k#b@bmI3iyE``jdAb3X}Ys_X&7))^1=rbw8vcoUv zav76_b%(RHyvV#OtSz@u_yZ8UaP2-`A$c-Ji?>brfp}21{lH|6D|1Adz{whIeu+4w zT~c=>&Q}bPrM1x)61-`?R`d%H$r!Fy@+M)H7mQOenP$3;xgrZi0c5%)1=2_hB-;YX za_{c~R_|af8~6b`@+8a&Mj_^6E}r|53w0TRCFudoK`FJ~#ZHI{mCv1mN`Io-MNC^Ul$N(DQs6Ih?fe$bMEpQ%a00nCRegGfC zZeShO(EDEU4o&-A(TVqvMxh*S;UBIz-O>6Zoe}qoQSexC^h~!E^?~NovvJ`L^!s# z^$Ixe`0NBVeb5zZ&!`R-pCBWJ_ihAmu3rWL#{2vLtBV4%irs-(C&}&xIYRqK)CxL% zK&0ti^7$ELRnkc}Z;@hC5TvLl*26HyX;8gG*#iCB&?wYhS;aGRh+hMlYEKqaKL?c*nd6OSu7P z$Grh=PnZ@zgsms#h*#61I2c-ecH_R<)4rJ5rtcj)oFY zR!YegLP8vhVK@H(gb5Xr-R;~Hs(NjIfJCO)3)^5DT%8~`T=yx>J90q~w(0|xe7~oWNLy+uP9iK51D6OAA5ts*ln}H2(udq~G zYhRafb0{@uX$*+BOPOTAGZ+zNZxZK{A@a5Q2%bg}=jdFJHPJs(gJ0qm7Ebm8B(Lk< z1zPR`B)kBtjh{V$i7uM~R|n7vxOemdt{qeI0wqnpUVv58ihpzn_jh}jG9l7Wnh`Q1 z-M)p-BMEfxvR~pNQxJQew&pmKhB7)Up>lA+?o(E1W)p|GDw;zuaINmwI}EQ3B|+Zr zry_AIQxKI+C;Tipj4c>jlCa5zl{L+iGOKX@szer1@$&+BP!>^dpcYEpz_Ly31gP)3 z0?8%N35rk53q>`|3twQFE#gU3uJ00M7EgXgDl6Y&bVZl=vI0-50(^_u8}j*qB?19M zt$?3EC0~+$K?e5b19y8Q5if3A0tD=p*b#nhcY!OsB6)!e#3{dUM3dSVC~e*Y$&hQ6 zssSAOg9!+FfC_X7dH_Hf1E%EyD7NSV$N&(MPnbci#4liyweRX)sBD$KBgYE#~Zb%2aR{_GifR#;m+rSA_?a2V(+r$ar?_Qud z0F@NF0c9KQU?oD&kQPx^{LM1odxqC!_ejw}$KmZ)gm=Xac z-|+amU<&L9m^%^a z3oG}4>#z}Z)p>+2t+-O#?n9yRz1Cck5xEN`|?X5e;ue1KZ_ zcKCq}H?RJi0WSb0E~@^47PY!=IVx7> zISVeVWfHtuj#WGQ4#8x)GaTSIw;>`{-ANNDo_nS0UV(O(kwmT@;W>a?pl1RCSwm(6 zm;e`i&=b#abQ|8_HcN1cTPxfWpFZ%2x_k8T0#i-w!OZXoSv{@DDid85fR}rKcj^PJ z-=G*g5Nh*;J21r|Kpufj?h~}?2`$h901*#maH)2%I}cDJ!L|`M3WsL4Io)@40c4%N1O>My2}e&raxH$HJBl3k0c5|tkRSu(0i|uh*o2pG z>JQ>MWWp`u=wb=GbnqR5I@r9<(}%yI5f8{wTqCm@-BH2j;&u|kqvb&L|Jqw zS+eISTYKy>BZaOfuO1dOp560V;jLQLkY-~d0WKwEy#`cibY;v4;a0Nca2zds21AD2(8?S!?io_t zgveU&a;8on4nR+?{v#@jUuC#VmI|Nv<^b>xZK3OjxynkLToe1=z=cU-;%$bs6O zi&%$ZcBZHt_uZDSaf5`3?*Gm$BE{sLqY*a^D7B2Ifmq@Ov*D8z*MKE3QP57QXDE zeu)4{^`=36 z%`uR(?n5vRJ8Uvw;kPHub^=W+CWOpn99rEq@fq(08?ltaZ2bgEmg?*QEy$$6z7WLhS)Jw@*>jN@;Q&(HFbh@EruFz5DtIg-doE(C5pLT%{EN0YHEN000FQ zuet~T1{3N5F17)>+#HMl0K*B6@wqM1usI3d$P6K=%OmBuI}>%#09087m`(eFWD0no zPb7MTO9wOs!ElMb;6qE8F(%3F_=7#iO{@-M@d`UP%$=#$M`ybEl}EQgod;__;s`pn z?c@nVzc3HI{J?D1&!`5S_dqSR-rhh!6TR%dU`J0-9S9pfK*?_l6vj|a(0dM29X3NG zAuk^>j=*;Bw{Ycw4K7LZCoG|BEtxtftiH?Z+&P0*cm4yYTI;{iU=mzbvcHLW%w#Qn zyh)gW4K}>Xo@k480l@9dXEI>7fCm)T-AkMTi(H5fF59x?I8u)2XP8@VexwGs?kq@I zu1nBlPYs_gUL?**8c%B!6l|?)lOk@Z{A$sEz5C{D(`1&5F)S0c8Obw2Z!(2DZ6GtKRLDPTa0QTW*9vo|_Z^TmBH}3Eyi0FMZkp&zkrET=|Z~ zO_F{cL@If6Wewjjh5EY%I`|WoQ7ZjP00Mvk06-`ZwZfLaAe{gl!O=I{kOjC8CILG= zfrw&ZpF+Uud4)Cx4!nXM00JIhm_uDbIY?OM1ObG40umS8TcA#$Se|DsfP|lTLe|~< zfN}x9%m;I5FDOS_6QU=3Z|imy4Q+N*!TLYm$aBEgf5fVemR$&mv*aW#w*3K)NZoA8 z9)!p?t+ObH=1f3Y-}nHvhaj_E09c&zVHWTCiR2dR*Tiz@4*d%O&whq66CrJ`%j^)= z_ut4woRe;sVqy#uSL#TV>W&+}WK)IT)UbuEyZMmp8c&ikz*+LSG7Vkbu4DwZ@wsP^ zaNlm=7U{#}f{xwW1Q$E)VKOBow(tSC##Biqb+8iE!WP^GmF~b7q$*ba0~tXspMfF{ zWw-DzAbUO0dO(-9?40r@*5vG7vZeeAgR?{vZxVqp9QPRj08RJXZH6FBZQKI=-QyM5-q&$-TZpL3nI7tS#B zadmbwJDRcfk^{co(dvtbwJbvYM=!J<1isg+S`6 zY8pDK+jLa5WYyGkwrK09YeW0&{d~RAC;}EIt0Zd#-gI}h2PHv}&`t0IPeE06b=8}K zv-I)>hVsq8`S=B(2eUY8s;UpZwI7EAK@a$6=@pQDATS%|wk*V@LQO|iLq~n9teTdN zhMJDXHZFKBpTM`e&jmI7-ky9NKiZS8|L6AP=bO!!Z;bzYdGqtQnSpB$_;LG#_vF-Z z2BC$#_OUZCgZMc^kO(gZIiBI-aT=iu(8781=FOkCaQ^&-V!{iA#Uw-*E)%uHY z+DB1%&1H|$&#&JdZslnBDu$r7{PV#M^w{$Y#Z|=4aU+FWu@^ILzpn0@h|7Fa(@j0( z%w(^Le3(U;iTthD{|bQQeEJi%a_M z@G{anFqnJi0Lrw{F3$4ldRt$rR0BJNd2}K|?*`pmpu<{?t-3j-B58zT-gMPRkcM-T zx$IneM{KRy^;o|4D;y}V!%AITcHUCca@K*ECts+F=5tT-q7~(GG$vAxqGf^h&=bS4@svcYvHL9wNEEy3UBXcoNwkp0mk%ma{YtOwCK*M zE$gKY2lj6}9~@Wm^5sg?^K4iOj2I;~DJf!YLhpr}^FK`~n5^4*W41dym%C`Y0 z=$W;+yc>nPLJz*|;IZ#Jvp0X1H*_TtOp@M9 zFg0itv2QOwCpsB9c*O4Lz15Y+9&)^|js^!wov&G71? zWMa~a9i=PFZ|-<@N8fnpoSi9oWSxSFuI<-#L!Kj{Du>$}nJ!Pn{Bt>wm7<&9jV_$m zJ83xf2?v@}!UCiz1%T0>?LdB)%!Mdul6Jt(pDq zB?ltw*?jSos^8kV=GBgB4%Cz)8;%L0__@F9rCRjd9L`897qaAwFejPj!AYx;;<1Fi zY0s6gi4@(hF6$bdCmhrACx@`Zn+*?Hl7cr98? z8L_9mMzgPd`|(1GX@6amMSSDc;}Qr|!>Hg2k=4zE_+u$gLy}fJijM4mEfo~GHN=Ir z8lE^pX1E=9bh?fTI}r4Kk+8$|Uch*aE&@)pkyAyr3YQOyFi|(zNC@9+0YY2iHgbc> z)ni4aRq42$LDn|c5Xmwz9O&`&ouLrMY-0y*Ous5JJXBpNvpfDxvi@zmsns64=DAO* zCCl7{7`I;D&M)4<_iU;D^@$G~)3fWo)Yw&}y}Uk^^A+1|Fy|!ecnOsrDZM*;_2Xg| zimtRFez_-^qydCz3CY2jhOKIP+hL|0R{ zgqa9#1mV4A8>^OvtvEs?Y7MgH!iFd^1*Vm0f2Kp1UEutM{kH>di7zU3Re9^hfkMvoujW8Px8B!0-Rkv0 z)Osly-;JQlOeuCQK5pYzWIEy05Hz-%G*03`H;?E!Zyb6Pl#^SlJKsyeh*5!fzi_v* z?wH7fNx64VQ_@cLDW=kn9t%`POrOg=zjXH-X!)5{k)3&7Cld!wFZE(q-Ro%DM7p)} zoSXCuIO1l<2XDAB@oSEQ^6uTIbX4LE?+Bf?K0>vYaS|TeLvz$Ep(?T@;SuCPd?BJg zix})Sj+?XSrrB0DO{R;y_EW7kJJXou>pfMTl6d5xyNCOUMQ*EPA>C!z?H_jSZ+nZW zcrx+ejryi@gmA%uZQLonhs&W!oSN_LxoKaN`rgAAh0;=8-Oea^25q?_DE;x|S{FkV zL^##)kXh8)mzO&nI|`O}ZskC40(9*LI^jk|QMvx%+J#N=`VA+GozB$t&|`K;(pMz} zkwZo%9a4tGmnALk(b$c3#;jF_PqwQ|BgOjz=j{Lb;A`XD=coNna3FEu_do5 zNi5mzD6|N3!{rlSTW!dr)UWgB&XIb)*Qm=xe}lRLVRNjYcb52>xcL_z?gWGOiDGQn zo`+oK1aoSsyCdG0%EtHK0uTB4{tFTB`?!y??h9cCRGs}rhfUBp|uYSPDpb zKm`0A1%fs=%8!AT{z|}=;>SbtG}P2pw`i%WOYzTvw(W8!qGdg>j%XZ4*3;b{PjE%a z+T%P>F7~cCSyw#P-JXDUl*M9XPr0}f(6SEpC^u&umWXkb;zvV52i?s zL>w<+p{u()5l_I`6I`*pi^oP$HV+xzfyfFJ#nDXkVJwf zkpQAxr42H0$62B=M331p_i16g%Yged0WCb6#tm~}0H23z=DEw=0gH9#<}Av~*V5I8 zi@wX1z=d;hXUaq4%$qzh#?rsS-5k1;`_DB z-BI>ea0|RUfd}93EudpMmekp>`aZDVE!N0)xEp;%|B;|Ll|3v+H?jA~V?BJL1f@K3~Lxak-Z? z4|C<8;{xNn_-bO84qpzm|91+yIj@$=}R@}PSl6(=W<;tuXWj|Lat zH^{@g_r62adGMp)K8vHtgDCxg@ba7jaR~B+AkHr@fnIL%FOxX`H)*_<;bzU{;(WXq z*Kz`E5!@RuuF4HT{CqR1T)Me+;SNz=YY5KcLB7o^{v7}ee&61e=7xUCYZW&t;0$gv zt-*~#Tw8^JEC{TGj36vT06%xg6|#ryAPqs zig$5`{m=1T1gytQe1;4QXP0m3yh_i-ySt*$_(SgdxRZzPPvy+vr2#OPD+%!;CcA&i zTZp?bdj1JC7mIUs1`Fg2lU-AX0RyMRF06Ybnv0%I}#413H8p(N6Y69?P8Xjm8mvfqrNf{AYAw z2WJDUI~Mm-7$6~l`J)eN}1Pdh|{qw+C;0^}TU!V&eummum{sI>U zUF`CY=)C#6fm;x?5d8QNBfRj;ycXkyfhm@UwUig*4rl>hoQn_5uLU>mTzUY0J|Nfz zLG2(2EPpG2CGWST@3*Dzx25m5rSG?;@3*Dzx25m5rSG?;?{8x1<4JgHfFK7!Ts<4e zfWWK*?SveGTIB%LDp_bhGH z9^-0aVFZi`e2cm8otWKRb%!gD{#EVb89a6xS^g{yLq<3g%rBLsS!Ip)7Qo^uNDiXi zG;Ya8xZUnE3e$|1Y=kog&S+pp(dVYlT%e#|t6#G@^VB>e{GaqJXr~eGn_BlR7rYT} zmOgHYvlQ$zz|7VIG&8sE7FeEgIioj&mwD~;hZD{fgt&_5Pwm2!!Dr<38NFEu z>`37C8>fBwEf)g8Q%6MwgIBia?n+PwMotwUdruWLWmOeO7vbXxEU0LLtOFY8g?ej; z^T}&vT^;q-T5FoAnt2+aU0nD0;n0?T=2j>_H`F%AwFrG#T^}7E4^IzZmX!7JaL3?v zeDv1xGS>lNE?8x)EDwd?rni>o-IqOVwqMo&i$lw5Dyu4?RJGJ(wYDg$ZBgB}W!q+1 zun|F3MNM5rRa;3-RYy}>M^#Ps+qD*yhI4e%vDj_&tt=4JTl=k2r%s(xKBb|I#W|~} zZQHg@MO9rzU0n%aDB*oE1bZJP3|?+FhuvsA3g^nRBZ6>H72Q0R8*Rp0j&ZeqH|eWZtluEfIyo{~8?y zjI20&C7k^!C7`tuTrtkv22}lCQ!sigxC-fi@%rrWo(>_O|ede}Ro zRZe=Mow-za>KNdFks9dIz~neP)_!;?{$bzE%o}E4fI0#zC9qVY_11E?;wY(ZQ&QEk zn%#<{sH(1`s`?EX>*(s_``<$4QG))Cs-~o>p`^amYIbYQPq~_z>Fma$h}?l?vU_&w zIAT$*jym5PT1V9Z?X=Z?%Qhv=Z5mEWYHDazC3_7`McWW5#Qa9MO+i>>X8S9U| z`@f2!A2rwqd=)5Pll@i(yIq}ub3t#dnyRMZRzvkIs#|wyXc`!*X&LU`s&1gJwN+#H zHUqVtpgup|HUNe-0?t=&?Khv!pVDw>M^}*FuUtw$<5}{iiQd{-57W+Ey~W69BXr>Cd8D;lssD;yEcYo(d7s$*u4bK}B|?A`HbE?WV^lHf{kM}Ol{ zJKYK2Lhi0yPNCy&k8uVaqV&yDv{wKBvvW&Vh0C(sT|xf5&`eP(KM??ecp}f$^NogG z_Rim_(Vy{!{glhM>}DNfe@)?f$^Ht}aQrKb=Rf-e_=hv?uZc6BwZFo@yV?Gl^s~?H z7pdPIaKA|T<}>_j%8YC7uW+7U>{no})9$Zuo(J!*;2-Y1zozkgd%ps69esa=&wBlS zkuvK7{AVw0p;GUj{P449zBlVlo;l#IfZy(M#e+4+_gi6>Xs_=x zO_sNa>)7+Wta@wl_TFg6wcmiQzv9vc|BOq|WO&L24WzTbELLjUW|x&2G(6UcaLOKs z-sue1mjA|jIP(^m!5C*QXH!|L@?X^ig~f2K+&^mLX^#V|JaBu1McfI8^^pCsGRqRM zvi4jqisFq76>p5=H{tU;d;hNs0&@(ww7)mn&&7PFLH1u+;6Lx9-G7rl`sXz<{J*M+ zy7s@%X!|GQi#r5=49I`QX!{ox_|N<3pUQ3jTaNJmq>p%fcZSWW{38dPiSM47wMJY< zz*9tYe#!0r8{-dXB|1PB{+CF{GnCBuJpW}9E|*2}8ssO9aux*CRBrIQeyl&M$Nql) zZh_w|@Vf-hkU5thoZI?-3C){3M{vHt0&w;Z zoOy%h3V`yzCxRpaA^v%M^PvU8i^1MN0dVR~fJ+ho-1$UsT2WAJ&XT!ngv8fE^VF8^ zRF{*Oe_+=#dwGrJ7G7spIE1bT^%& z2@1>+6cn60ca8@jSqz-go1-=tS}VTufRMWVQm=Wt&dP;KSUhxCrZGQF{$-^BZe)4; zxh>$Z-U`(2(MRd)HCI|`89FK~z@HB{B5>(Fh$bG=zHpI8@c716w_-E6$MtT{oY&i6 zZ0)r5`;omL=k@j+cJaCV$CI3Qb-h#DOpdtvUb&l)TUy^Yy-8>9(UX2x?Jj@lK%UW3ekiqkF@wOu)7{g_hGzDB0--WvlBq@-@; z1t-6}?;oJWnAR7bPwtT#T74a?y3q8jGmha$d+pekx>UoZRyJjEuAlD$;jM)CAz`Y(E9cDl!q*tNga<)pSsOy>A9T;js_Ge7lu<)xHV7pr`Zm) zuqb&n@=R0w4FUi2TI45%)&R=$qU}Vj-l5ej5sXLN^S3L<4-9^AK#wafbJn~5qIjLM zTKr>)g_(DK3eLRSQsTXQ?Q3LdL0sNAMZ@EMa@rqryNMk>ft#bH;5ezUZuUD4ghd`b zTIP?Jh+TEsI(d_es<0AnW?j$$ur7HvT``+3{5`X^X+N#BrN zAtTwp#Px|``cCj+oGnAi_n9X&@k?M2xnoMw)rG|gphGY2K|X~ zd}wvWq*P=MX*$EtY$8Hw@2=M8u|&8Wd421+D+6{F=RjJC=!gN)kcGsptj^zv*)Bp~Frb$j;d_po!H;3Q}CkfsmWw zp8jHwf~_OOfD4516t-u;)fV>DYYdZfD;D?OgE zdOPFZ#PkMc#h#}@SM*DB^?{R1SNj(X3{JUvjRq@KXut+v`&)-jl@BQ*)EbPC%<6s)l;f4xw`W|OU?rw{{n_9o*M)fK%ys*6r%R-L!UzVReKk39&F!(S7= zZpa%)?{B_xKntm)^nxiKGk{_RMA-zC=N?C7eX%LwKrT_owFI~D?+tWjHm?E1MOyoo zz7bJL9i=Cq$Pj-YNH)!Urvum7)qk}k$Y84&{>^XgrgN*3o;6-Q6&BbMS}*$L;h0f8 zv$m~a3wqFg*&27UUBw?E@tp%-`$h92GAmb^WHpy@AZ;C(w)(+Kh#jz2k$e|f`ktZa zz4c*d=(V?>g9YHrbT|YtSQu@?sxN$Uo=q%-`?~vH*L_W^Th7|pCt)+*(-mxj)y51x zDb@^XOx`5SfzFPQDtcH0_1)xW`jkcoee;aI?)pJhL4{a-gD;}~U7Ei6ct4Y*zL<@j zvLU6TklEnZvDO9|Y;vH88Tbaw{Q#YOEB<>YQoBDZ=XcqiwDvk)*O**p7u0;a20_ z`1xU9OULt!MfXIf-z+y*I_J9-f5NmdhOl-#xiGI?(V(f1k^|p{s?Gt!M4z z)T4~YuqlZmhHVWD@WHOD0|E6{m+)N;7b{SdEoo0zmx(8dMc%oSw-KRwms~^6aUPyC zI2gZ`ah#l571Gj3SkhvH=%fhso5(PmuDwA{zp2CwW<8x$&)m=(`+&Kn!}v=k;(2mG zz?d-jI@RBBCHUncM&|sF8?Gvsvr#tMcyG~HAEz25w_}`6+4huqe3fjUWVgIM=&W(% z$f!TX!^!b#kc5fU?StXQi^NMGE}KM_nhO#jqVDeLxo zl|(HbTd9i@nQ>c+h#5GL<_R- zX8i>Nv34U`;%#?Kn*?Zr)1sY}K`X7^fu{uNd#~j#n#UFOCh)Tla3EPw^5T|O`nrj} z)L3lC0AI7F?D&SXB9e_A`x3ioa&t8ioq58i^9eTB85?^Y%UWQ=RvdhJGRo)ZxvkL; z^gG-Dl~`H`jWjwrTy?s{mhQzgPKm^s^cU{oK<VsD zp|S>(J16>HF7gY~0$;01sGvHSaLa)F(_h`!soGhqRrYa@mcqcaj3o=>F+>-qBwa2v zKG3S7*q`Rc@6!{>4lMA0c3mU`C4C&_{+f)Ox(WA&58JNjZ?LX#F2W#5YNaN_aUu3sKUVks5FNU_i9_JyN-~eF8B!MH^J? zqdd`RJ1LJigyKMJ;MXDk1I=4e8kY9yhp)d@eznisbY;Yi+qp+n>sO?EN{R?gU-L(v za>>q$@WzeanePCYVyMq?-%q*@8eigImw210_OYe8`)m+>F1Q>YeKCZT8gGY(nz7c%z8~@)B$o7xFx4GBjjT?zd1Z=2};kz zT5Pq6`D(sX&gJe zv5Ny01i&REjHPB@UPqMYxCuLn)ed(=vts>-gT|DU_14)+Y_P^I&7}>>Ri#?dsgy8N z&o2198W5(b+4-&|BFRSa$M{b8AcnygC<_@`B$7?#_&_Kbd`+=X8qpY1LUzFvwr9s5 z7l$8YGsK7ejN@%S7e#sRWeYLAr$-o9i!XzqkZV$k%qt(PaIRd8F`8OZ*r#W= zb6`GVfJAHU9Bx3y9|g!bDF{}YkQucbm7Wy3+yB1EIVFy|`_&}`T-c`FW9825RWPM7j$B>yma;k_TlZpN^eF^J?s*ZKDJ(5FJqk?1JS&? zIY-s=AzA;PpA`qP9}c$jEicS!^`Gt&o$q`Vp04m%O78Ag{30QS)sCqNVtPtH6>bu) zMEpmrUjIIB3e_I9rFXyT+sr>Eu-_@|;MBc1#F33-x2g`9>yt;{W3lxgYEK=a0ddf6 z=_@4dI<;$%X#YYJ#@gw(-ymUzq_XBF@Kf575+}d*?wK&T^ug@!eMTuLHrM>?x8r;NeAphre)@u^Xj5+gMxeI?!-2 z6@1V&poGq*)zZf$MdMgtD^Q5_<67>vpdEq8J`QBV)*fmI46rksHJ?u>Ztx448uk!@ha(#dfo0c>22ZhaJ`sF>%z*2&$C{*F2M6|E=KAcTy z&dWYl!_Es~3{Oe}>)fD8%>%nVJ$>)A=ppgdB!7VsD%x^{She?z-8(z>PHma?2^vaL zRJq`Via>By7TeV3On2a#u90C`SFLy)_QOe)ZrKl(ZQ3}233@5X-@n_q6@jHAPCdvI z$Qp3Y3}<^yJ%ekNV{EY@#mzhAL|4hw+l>>kwxbFU$o~XS4zca~Y=7 zu9+0a(^=C(S!>qGmYlL>opgEC6mX}lqLlQAE?igDQ{77U|4Pg7PaU?yu!@@EPM2ji z!ZjP1D)cwi#aZv28oX)h%>D6WOTp)DcRV*O=_NB{rYN~EvLasdblwY_J}@W`hq9?d z&6cSfWcDK&B}~i4d&cIytG!pqOtt0{F@?!+Dg%65`YP8BTw>DENg4&?xmLa9kujs4 zYZ*^{{K1!fi75caK5FQNZ}fdIqEX86=d4*6z2WTcT1Mb;e~VzHc;+@BWKGXXLundz zEUb5bGroomgu?Yet4FESiEwP^)WVNTjz9{%<{u9X-?s}a%zxFYSI~SqE?b6DM~61^`Ek)4lS&LQ^<0C|f8c?|n`jrTYB2L_x1 zHceNqh+Z@tVKX#MeDhB3{4@=dOc4(4Lk!Cd4zoPqQ;#=RWemn2!ww$}46rt?NZoQ~ z)Qe4Hj}Ni7QH1<)d&pqmBY8ad6)@999b#YNK*NDtmRv%yX24VNWU(&4aV1s1aYY*z zvZo)>c$7xVlTLnEsMGU6v>L7zXn95TTAnbl(n_H^FQ_vNQO9T&vi?*QMK~;go#a66 z!vQua+QLs-tr^20H{wv*U8Tg0)J10!hX zNr6$%Uw0MlZl0)m)hr*v#y9$qsOKNpZGUy><9np&h1c*~#oCI%>D$#_{}~#@zn7cx z=rdS%@EOoY<^1Bki}~0NmDUe$*U6s%k>%;bY*+&f6JQJ zXMB?wJ*l1D&q8z#wj@)49*U&RSP{~~$rf5oUS~>^%puYwko!Xb`$wsG*tG*8NOSHGW^pu@8X@v2|3xxsRQ; zY
    y98|QKWyNaf&|<*|1*{-6}Sy(rv4B68ziezPD&W}vq_Nwh`QG1Gx5kxeJOr# z%TNw_!%0N38xNmhbd6a-@vNR^vP@4cS+u*>v&k>0FPn*EV2J|(_RdF^QF81On3rTo zV7Ef!9?j>n2FR9_%qxh)r1+^0@(~fC)?I zuBe&anQ%xID~M^?eA}(2#*MPC0e(&L=8rnIfcPb>>;;%pMI1;nFd(-oYRB!eTZoYp z*$Shm!FO*=296qtReoR}w}~CZ-bbt)ThM(d|5;~aI=|4yf{~T145+Pc<@iQ+b`Cte zGHVf~UK9sR7_Eo&RaoIBKx(@7DBAG~x{fB1TD%%=nTO~a@QGt7vY!FUXs=PPsq??@ zr}#U|QvdVbqCZWGgDaVR-eu1ElJ~zJNHR(Dw@bwju8&N&?0)>g-F1*E7gbj@c53K$ zV3zFwYx8{-t^7a8ExJG!A6ULC(BfuEzVpZRGFhZA1D1IPE|Eu;Uwvdb-8S!`6dRz} zv>wu;)XY6weM4C~J|TF{AV!EWOiOk8X7#imlWb+t=rnfGU`<}zQD!)s!PEoG!RzsN zZo+mU?*Q)(T-pCFFGPy?9*8k)z^YFNw49I6P>Dax9AVoq4y`X|zYfrAHSi-A8c?2i zSWlrjkW4D`KtN;hG&R{yIXz$O1yCyni;^h@hdWvafek5;25eCtN`1A9&)zuK$TZMq zRA|#YD+X%Moz8ntV0o}oYbt$!*@w-h?lsGULLNB}aM+&R(APNBQ8{ zdzRF>>?L67v=8)aLPW8Z}IfF{ID0Py4LoUQ>eW6ix{5fNW48XE2 zSZ-~LQkqtR>AoCDZ20K%?wSdNZRpMIi?I_xS;|P29$ZyvY%W+Tmr|Rc6c;j)S;7$6 z)8#)d+YuAL>{cg*&t?UJL_5oY4DDJ9G{*X?SD!ffhZ4Pr6i;Pj_rr-%*wtQPMVeA` zpV7Ta5LJC8`mFZcv4JMtykMMe9T2gA!1h@vpS9hOns=JsHoaI#poWzesKjn)p|)us z?JL?_ujFA5Z`xcCxV5vfh@Vc)Bd+dI7v9#xIMi7+k(2$oWhmkC*{wvP#2cL(-B(pl zKWwDC+9h+KmgJ%KbttP6q`_)4q)7v_5f!#Kbbn>(u62o5*=M`1(H_#T)m>Jp$n-p% zSvs;0ZkWhgK@^uHzoAqL*<(v-=B4#E_txItn45*EXbQcvOt5EU#r<4F@Zm$@)EwIQ zbdkH7NB-NvY(!tATjL+(o~7x=Z1c3Dj(YohF5n;dtO$H77uV!}X_u1brrk-$&LN;tyeSpuS13|;%+?}G-&Pc4{Rj_TS*k)347~bhI!?SvlGob2_UV zOdJRz_g9D1^4xh>Wt{2ALnDpVMCrX3FWk^g>w+`DGVqC%n!Q9d@MD&k#jTYCe5sq~ z35>E+`(c^$EWNz7sU3YU+-m2QtReMpJHU=-1_qI6ss1PL3k0X6Nh_qN>v~-ih-Z21 zmZ4UMvnTb7hAt*mJ<^muZg{fyk-X7X`4OS2NZ93?f1MFFJNe0hk>D78^R56<=5jjx zblzmY&2ysX{Pt?050-D2AK#Vwg>B$wGeFJEolMy5j9E;478@uM+0}HoT1!)o-XcH7 zfwE=A2KV_NZ|6We`b#B@gv`>1R(WF^9>0GtI=OonjTwr1*)srmj|X0XzB%CVuHtiK z3%R7STA493^6hs=3Jur%arl}IiBIS}J3CJ^?mA+~sGFaN;t#oUw(sLYY1-2crL@gE zY-%hwZ}4S5IvK3Q(l4qsh0B03qXE16WTvAdB)tB5=G5NUV6Jo2!eAcBJ-FWs% zV&;a8^v$sT{i=i|hZHUI##DesX8o%wg$dnrN?2MXV^7mpV@62&PByLP$?Hj*R7PoE z2}|^Z#BS={sJ76=GvlQ zMzEK}Pv}%9;ZjxHomGS5VM!?$iSVMA&VBeJati!!S3Fock}5M)>cAYIn3QjzN&7T8 znpmRGDghZe{Z0Fu%Aw}xn23;7h7M1QV)qjcetzKGP?V?rbgR{!qbKK-mUljR_jV@- z+LU-NWRQGfhv*|Y26?Q4T6$-5%c||YK-d=tzC!&8e}7CQA?*mCObuJxZhAb10aWpi ziqjXViJ#g=nmcbaHJ%bSz83Rpu#iS+_RsNrcA~fK(gwAqL?Mhle&p7JD{>bCXgLBf zBZeXTA*{*n_?Y8l{`K_jrb?O3A1pGGn?A3$FqN=jyZTO;o*K;F&~iD}BQwm&5Lc>k zuA5Ou3)3XmS5gOBr}mTI7vM{T?3w<3$7#kg(@l?C!UL!uszj4Z?vVo=e6pE1uAsFL zFVrO0D0$m;8{DK<`^t`1ea*ugF?iJWER9{|A#t-FYiSho?$JKdczf@pyUf&ng}vQx zR!v%$1UJ@&sm?XY%Id5uys{v>7F&1Aecwx64pgE-EquusZnC-WvC6K$2jOAe$(EET ze-1Z%2$+Lmr8LVaPT1U1_d9q*k`1qxDi3A0>+@mPERvx(zpZrfz#ujI&h}8Y zzlMmo=2uIHXKVz0?Cl|Cc8 z_rnp!a`w!7Q+@UQL8l624LbTuijm9wpcWQF1lZa(r6}FI{Mo0 z;h}NcxO1XajmP~{xNfdl8SCH06=cWxxA1Nf!eg3kPG&vM3qFsy_>SW6*zZ`flCpW& zBfkZg&yHKxSQc*{->IwHf8$js96w>bzBNF~vs~#G@Icg)7Jj09;y`x_U6Qbt?Lx%o1X#!}|~M#XE+Y8u#G>5p@ld(#+2`Ygi_EIl#ZV zGNyF*X{xZqk^rTM=v8j#QTAW%A0D43SG8VzlXP&cz6#wu<$8=9qA$-SI$L625=}CH z&Ppv2afQ{!6w22i0_N>k_93U;E~-Xd+FBJikgay8TE``z9di3HnwS(V5fX7NVDlb2<8c15 zAmPuq8tU0=%%h+9W3CA#q(wSIC$}`AaY1qsUN3ZCE5yeKQQ;DmlJv$DE0UK?r_BeT z6Eel74iI|lS3ge%V#MMH19_>Tkty@)c1353cJD$_mCUJ1eH%9HsX>wM;eO$J#|H`35mH2#|BW#`hX1hVhn}xNl3DS4r z%G2vP(C*$==bUb($rk^pgaQ`>U82~#yQ@T_WGWt5uBi{mwT&P4-@ax~^4sgm%IC2U z$y1dtY2d#BkFv?ndnsYby`1z()`&wYnFT#+f zlg5z+`Pc4nAnzuyc~xxi@RutdJFdAmJWVElxfLK~;EbNPX3Y(ucf z-rKfHGwg5-1}UYj|K72McKoe}wdKIIn7KuFKCV{Hy3^ZAO|>078l6Kqcq2FqrFD>e z_5J4(m0-E0s&Bf_55lDrFM$z%&+znlVhHYr(&Lfj2^Hr9%SL?_h9l5^Dwm>~-Cfgx z1qOi-WtcwJA^TZigD2}EJAH`3@0xtC2MZBAKBS0^Z)0WOD05sFg25b5jvRUNG^t%K z>F^5~(&@owHmhX_N7lg`Rj#i|Z*|Y|kNcojBEQ5~AxJ8HH#tc#El@`5M$yMd`61rE zciyvy>WZ=Qi$9E>L2V)=NtpM(Vj8RkbarmIJ)@to zF83*1ppt$3Ior=e*N&dxA>So0R4^G)DTj5@)DMtMoPTZsA+>3iB? zXx}~p8>w$6nWmombyNQwa>sBQ*lT#W`)p7ZP45F^d69I*_=?I5Mo7k9;QY%~cDRI` zF2T1G0^B|@$^O>@I%?u3l;sd6>1H;ov9t+8%Q&hsa0k_7KkCBCW zEyzqc#Asz|OfCg3SL`WjIv6B6rs0VxUOCa8FNt-J`dDQQKUMD;aehCqhduX=N{$`O z$nakiSfSLKUD-gQb;o9_!fzcSkSvQ{1itjxb5D6xMmp*6HPC4*gp8TaG1yFQo4-#^ zDK)DrG^xseElSaD#A1p{x9Pym8M%cemt_MH?+V}elbYfikH1^#i;p~IW64r^oEySU zE>U1v^`7f#Jf3K%gw8P!qN9(&XJmRRGwXmj-kCJOG_51aY!`5UmJ=Nio;TStaWOFF zy{krbBT|J*ZiADDR9cEUk5yveW>Gy4iUHf!;a(#<*{5>C#B1qV41JIXgWYVQU8V%xTo=5p&fRUt=xIjUq4We|>WfxjDMy#=ubIa9|B9 zLg{57qPyYCN<{zt=%rC&$ae*m%a)Wn+V$!>vR?s?s(j;d@pR~@LBOzSnF-zTcgqlz#zoo3R2J(zyixF+vgtZo`syFmj!Au^`!~@amu-9VR*0EV znha)^U3^yOvx2)B27I?T&@15lV{fyKoHrPh;??nF}`3tT z!TqliTfzT*{vSV?JRe~ICl8}|TR``aqb$3%;y)t7YWz>FyVY1P-l(aWaOCX!niGoi zl3xzei`hpmKY5&(Htq$#q)|xdwu~lLx< zAMEcRnTDI4Enio=w+l}V~7<0ejh4$!+UX57I>RB@#RGkbTXj?Anj%70WZm_}7R z=uw(Wd)<*V_W8u*B`saU)kd}+MD^}|T|%gDJYwwjK1k+lg?`t-MlH$wB)0g9!ePmr^r@E zC4bTq%Gdt6>hbuY`Z-#ZM&IUUYq{eNjg7EoPIIib6g)Rb1%srwhMZJ>TayugEgy3y ztG0Ed9(9eKl1_Lwm^BiIak?l@-z_?lPq5E|Uxh^J1z%AvpSs)PtFzMmz?hBD#`ABk zwe*xnu@{-mVUxZhD74jBX_~)S89Zh~v$nt5IpvTW?22fyAN5m-^zPm+W>Yx!L8eVa z9x*INiLuUr!xY9fT29`UV3}lSNg+EIHg;xAUKdZ!QPR|Jj3DkYmTC|m+T6@$z}``R zTyFbP)=1+(5pI&CsR{DF!ewR^O(9Nj*F*U*4zx=f$gWZID^u%RMsoe1>T!l?9(Q@I5e-Q6wW z7nd^`SF}mP8@}{W#E$9mqy|=yyes3p-(+n^aJ2D$_z=Qn(eoWv!GZVTkeqNo1}mVQhLr5hKAwsN zi>TWQa({P4h{8Bn5t{?CB)f}SR7HD@5U<#4dOO{*-2u#^yuJ(hs1D=3zF{w{FiLSE z6A5hrft@}Tq(8)|G*K+cHx>51azq>Ht(^zIN-@i3#mviFlh+fC$rtU!&nf9@Ky+sG zHVvkv4Fud+@+RGnhVs~2HDR1JnI(#Sd!M!Ab!WmY8879&52s%iM)?DKQvlFEH6P!x zqvx*a)x-Py5;Tw7nyS!GIe|Wrz98e+tVUTa%#MS*Lc#VeS{})=wm-nHN`<|2!@VMB zcNt{=RA;8iiNHHwrQc*%ky06yqQ|WFl5BhZuW+B9HY?^R@n*|s63qZd9-CHR;-sHA zdC%dK834IYf!*mJa*$Zd(?ZXs{H~_mz4HlgH#SPAHKH>oyJYCP9aT@SR*scb@`BNh&9NIR8Yi=qQsKe%=4latQ-$3DR#eSc zt{QbI=DmGvzD-2J$mxl%>? z&-d6lHQIv1C0{Lk@|8!4u3pUjrkm}k9wp{B&Bu@aFXrAmsHr|$7siUdidaEu@f874 z5fuTc5m5mVB2A=5nurjJbVArFDpDgNpi&~e6F?#KsFa9+NH2jP9YQY&kh1-Lo|${* z-Z|g7=bZVzd(ZoaGfapRcJ}_QwVr1^>sjPbjQ3d-$Ka#v2LCm35a0&eCb)eo#$ET- zFM2b@%I@v@HYd^QU3%>inlmSU?>=*GOGrnf3O1gJtftf^mj4~rJcyma^m6x2)m0*x zo+3%RWc-`o6<=WRsz#tUaxM_)@3{@H8ig5Ik& zS@;ge#4Zfi(`u?~ih)8Q$lQ{07QGsF7u5ZENg`BsitRkCSki>}A-FxLaT`a?l;HfE zN1|==Sg*XdJQi8FB>Lq^WbzHX3-cT`u;oH98;~z- z6JAI2oh=}^|Kexg5jji0dB&3dI$QH)LifY9-j5nmoD2I1tgKwZ$aIt&If{IW zRj7pQz&9o{XS>mV2R1@^iUO!D@M*bHdQs-g|putd; zLo5WyRv(lr7l@m6{Wx@RI^;Bxt#}&OAWR-Yy;;!U4*RNVrB*2UBX=0DDK&BWr^0s=5k1cD ze<-bG>Yn!SyIWBn=j3rCHPtO^vwU=nYmSX_RiF8(Rqp5MiF^*EBzy1;@o=tJl9E&Z zj6}ns@zcX?AI?02E}>s<7I^%UR<5&65yOwDoO9{EiVpWDiJ5vB1^?zT4r-|K9SWx= zpt}a828q0!i({a)%rnU1Kp8X5ac2x$DDyx%5cLB5TSKqQwh-P_Rot9ZsSDgS@$1X8 z*6U@`8_1VsG$}qeI_{gWn@{2I|>tKgnsipM_mzc zba$2ca>m3pkmmfT1?Q&ztHr_7SBfJi*A)ZVv1LdYYD^u~J9R%Z5&a|(6UhE1%Q)+)H;q|zcw=zMi+eZiS2vLfHAth!XAezSKigMOl{(P!wIY^ zDFdHh8sw_Ai;5el8=8YqhxLDxG=TgM&<<-&Lp{hvYYU9CUpKsS0+?PhA%BR{5t_uZAl`tla*Cs%*-G}f@6 z!dBQ|7M_y!;wA-B*95r7iwB3*@R#qSDt*Mjr@jMogSG(J|6x{xl_}H z7@i~=7AMcmeOJle@wUL)zf4mJ^(McxZB&>2(swZkH#MoLw>ZSNV6;*dcL82LbVGUH zkSFTG(Cc%))Thv79{>1JuLtL`j&AecJ#j>&!twsmhlHHzj!*FQ0dz$Z6UiSKx``cB@VI=m9u6vFeh}4Low0el zeUowSRivjxZ>KvSXu+k;TUzBEn66l{7Znl9wt*wsluNrEC^MiUeG-enFEK?1DeO{o zX#k!C1Wi65xqg}j$s2!SXm>|2%UjS4&!nE&viLk1D0IIwen4Q{9=zpUK%-hGeA6O? z(-Q-$1_-G=Q`Y)llwSW!bH(cl(f|l!iB1AVfad+;_h%?0`8Ur}N(;-T*1#)DGAb@P z5&H0*Gk@!6=e5_}cP4$|fY6NmI9Xcu36a0{=yBPe72@;!A@XR(*Vs_wWrCF1+i$JgkI3usoxQ9T!%U4cL{+1w&N)*zb!}*y zRo*(S&xv$$NGMdg^y#|!mgUX0zpBf_diEq_hE`wt-ia47foK7wp)}6>RYRwk!1aus zYLBaoTx#CQfb^0LOA%T-a7g+dn)t$Spsulyg8H>{NMJ<`7lSD6FnylWmA3zGCs*z_ z&nrMJ-e<GKT;zzMAA(``b-GfI>hac4w;w6~o99UT z`;-sq4egzF#a%ytj!oM{CC5d*zdVwenHj3;(Xjmi?efTTB;v}Bkd4OI&1YAdRaf3g zy&7Lb8{Lt}Md{a4>Hopm`u~d-`8Ox{pJKk8Nm#YdI1H&`^K;=LeZ}0<8>M8Zkl7-| z!s!7573dz}xu}y&(>FDN*fzFKe2!_{QPDVRrvW&`VtMIX&+>PofD$rz0XwbLbH);$ z>Y))f2%Rtq(2D6Ze{$-%>=&qsUD>?JHW&iXO9VECOq zTq~Wdc6I2{df|V?Y}^TyB7X@Ok}t5jU#^iTGR5@YJO-}c=0=)GwW-|i{G6{tY&gCH z8jvTM?U)xgva3d}Y(Qh7-CK+Ulsdf;&!sr+EPmn!w&g+Mldd*bYyd^%gVM*KydbEK zz*O&!5|ySKB81)jfCeWL58~R(4qR?z>Av?TLel)ZDe#4Hm!o%0?zgdb=Dwv(;d7W8 z6{Wt1507PK15v2CYb4>1wz_{-xPvnJ_NKQw~}mO z(EpMU{>`&lAj=6{JCFU#EBrs!5*M5W&5!FQjaidfcMWO7b?_xjF@>pzc3=jtdbB>T zVal>=Y`68-K76$l^A>!-r!(iWP|joBMYPh(LyBAreD1+02(f)ypr}ZS1Er9v7p3#c zlC&eFgFC|aT*z*=`E`fU{I)?d@|x$RpI?G_OPV*X`E+XYvbK|#X|I1|)kz?qf%K-_ z@3!e}ph}ht@Y0Uk-{TfQn1uxD2jiz+xq%RFvzUnV^Z&-gCKyA_ByM^`mrU(LZs((2 z6gQ5acj;8Eg}3NGrqBKl84buHtwNb>WFnR3dc>KjXw>c5guAO8;fqX0f?^+q(_`oT zaA0~mqt?6Ue{o-fNv4<_t=PMfaet4WL@t9P5T8q_U|0_?k}1oJCjt&JcAb~}%!bmr z_Ad!1rFv(;-~bgQ*)+ahDt=GcTvTOtf=tAX@S?IksfnL7VLKNM-f$Qa`(6=@sjZy& zVH=nKhId+E)97FsNa)YIe$|g2cek6u+xC(K{71^KHzb1RuecQe zYOpgB9Obj@yjNIjV_39unLl%#oz&SElRz63$XOrYFF#U@ zvRmIB&lP-I2+>Q37rK) zb}aUt_#(wUARPtFxWC@N;}*1t)81{ie+3tdQKr5Ka57X^C)e7LdsnX4ysh)xwnQk1 z$A_sYD{#$j&-XsQ_Weu752eXEc)Q6ktblv7uvgIi_HUl{X}%gdrpFsS?Y(w<=H8(! z<+N#;o+=)wSjF@(FVGBrO?F+FEObDwZ~+iAwVyq-zLz!(IFKMD$8YU4mftJ>KXLR0 z$%Kpt*|5#KFb4*-Z+amm<3!`scj_pRHdyRCqsE+C5Zy<(cRYs6t_9T-$xLwmHJ)A) z{do|G*wh)iIu7@Qqb^$v!&+_ClzRcf%F&dJDKuqjSooaU*^G5bDjyd)x~gT<)=}55 z!0~cX0mWQ%KAGW`Zt)m2<}1ayOQ531AUH&uRSuc@L+ij?a%&uiHjIgQTEEO##ZC&+ zT&9`HOu|YMNCRfd!4+?vsP2tgSi9=;hgB}=4Q(Ul>`8bG8z=o!);Ozx&iZTs%?=O7rjesk4g z^8pViyuXv?&)kqghq>M@HJUSExD8HTzd2RVQ88QMDzmvx_nt?pKiN2~-Yc!Cq=;;g zmLN~I+y9;1qsZ4{JsBT?a#Y1^fRK=Hg?MI|t~iEX@m@>Ih;K!SkS6a&gOMb<49uQg zoLn$&KO5SkShVoUTW(1CKe6xUR<~Kc$u7w}aXpj`R@Xp?%6(kH6Kex_e&_bM4%AlUZ;}TA!j0@~1LR#?kFdPx^2hv3xXSyv?*$ z+-)N7>YCnm7l#Xmc{j0wzI{|qUbAyJ)S$K&yZ|)`lB{W-XYrmO6;_UU$la&vC>jRfYBF4s>kMftX3>WhQPr% z#=~-5{m!LkC6hkL<)~=+nxvW%n_ySVh%=rK9@HCb1*lqKra=o-{bO@IotVB4}6v}Fp;_TbnuB&R_O+iFV0!mNK{`YJwGw?<>0;s z?Jh6(fM7oiOT99)-gxT5r(>6)>IJ9MQenII=o(pEI=)H#R{9)N(Hz_>H>%H=N2UDS z9iwJ97H*p_)@gvHBYs0Vsy0&eq6U3mf%iQ+*R$A68~!P5dKgK=EIu9Va&AfZ&BIx@ zgu45c>ykbjt}Mb2$s4GvAtmQx82>TiO(Crg=E);kf=gl{J;A$-y?c?TZuA`!#+yX` z&>i-G$1c3BT@*f6=rH8V&nhnldL{J|B-PlBo>aAu?-IZt8nAxuUX{xeHKr%(_dq04 zFU|TeZwfWXl{aJ2$lAKG&nauRvTT{eDb9Xs<7^oN*}zV2{PDhHAP<#5lmO|$2MM@Y ze?KW$sizC@MnMORRx#`j35S|CsTzf66>bp6n|1x!tC42ZLnN+p*dJwJuZFm786aDw;s) zfD>WAZMD8ONrgs+Ao|27G=rEU7_&=3@g}r=7~ELb?By&$)-V`=&*!hMo3`rFINc9T z6PW^}wLi4nJs@NQovKm~K;5h_eDd?!GBK-qu}5Zc?8shFc<&gGVbrvVO$lG(UPhz{ z{Q`*ijxx)5UOC0I%xB1ifot5uXOP=NCWxZc=G~ZNNHO6}kl08dVQCXdADI_P1i{A4RF9d2NPqTTQ z4CyNlBX6=R%(W+S#JSMHWPhfkpzOj*gjsU3g>%RlLMOL&@Qa3rp607O=Y95fb6!E# zW&{F*`>yW0B9Z%PiPG6@CpG3EDw(Geew?DW@AT^f->N%WZ_~9;CLFl61JCaLc&g&+ zkf$fEGqr(7XkzAqDHzjAFR~07$Pw>Ep+v6WkV9$fU$*rps**~t$MA-B&N{hdRz3{4 zWwKzI;Url|`df*V-D-3;I((1C3}s_^uJO#CQ^=2H&%EgAI!pC63TkHJ^nJwc&wzGN z?{-pC$@YF}!l%%YIgI+i8U!dC^GRNQ)+T;K%N&$YDlMKpfw6S@8@!oyc$QY>G6?X@ zWdWo$(w9rFjl(q`;U%edltAr^aCa)*nz=G(F~1(+$JOF&D5r0h{fri7BGE$EOp5^Y zQD5QC+dv<4E+~2%bUO7P_%X+K$;F6`#)v$EbocRW8`$j=zFW)7F+;j#%Ra=W_kQn^ z3r5HCBeotG*v*Na1^RBIu*Vo^oq&PIOAojA1&|nT_a?4Q@muPM?pRbXzU??!Za)t)}U6o=5#n(t<^CJ6KNx<`m7nW7R}0*RCcMvf$W2 zxtsX0^!~d?{g!cBwFf+}*Oc~fTlg-i%Wg2*xarM3XD#y|q2wy*Tp-y4&FkEKUxy9{ z;^@7n1kOZ(1hK?_Qw264UPq23U1X|WYQht4($&8WFl<}RH`Ylr#HV*b0H4U$Qx(B8 ziS`{UJ@dQax_ZP?^;+V9et9SQV}|!WBT?(;*?CU%E{JmMH7aZSvJHcYlBs5Hls}_% zJUXV)QyJjNY_s^c6}Sds3U5y2v{sGA-`(M}sAI$f@p2DiDudmaa_j}lV5%CzhjtxO zAb_EiPyGQ+kgJ}Ou8Yye0Gd@EkkdClI@X08hKe}s@1LE2Qd1PO><;>n(0{Waznt{a zkgb28Ws+3+ZD<}ikz%qAY9nIk$il2%EodBnMHdtzV>o+ER*Za2aH>{+C%sw)(2r0j z#s6pffB%fZ3GaN~)w#y;5Ddq!>8D+8ULe<-ES+)br>=BFyDN^YdS%0(yy>{Xo;Dr) zx-g(_Huci=oa%A60+8*JbP}Iu6ew<;Gi4ltl><^VwBmUL>hA9+(Yu55gk;=ib|DD< z$>-+zg{P4;mQb}pSWs#&SJn`2mi%TsCij7RuJ2~ibzoQ(q)`j~j6d&~viz zni^ZHnfO4zvIo;p0Q0b!uT?7n{q+77FX&Ew8iX2aSRn<>K-N446oxpso{OW0EW^u)!d2{s;PKq+c!7ma9l5m2Si4fK2v0PAZ9)rF| zs`~SC2IDsm?^Vz+MWM$7#>-FhY25+>$p}T{+9?iuJyfc#fNLK_rgM`XSswO5A33rn zj6*6^FrXq}MeP791*BO;{rymR;@pmbsPvN$kxdi7{$_1tl0+;AL5wAhCfs_}wU)H- zw&W+Hdf%5|{f52|P-U5QD~jvoUcJ1r{2>SRtG3J;N?ZV8&De zx(nR@9M89XYze}H!TD8*h&nF%+*?0M{R^a#odsi?&(v!iZMS<)%JSH2jTV%iJl7T?~7C1Ls)h1B?TX`xF9wAS*p)2 z$wEuoZFp4^E?Kjv48!!kfe|Z=GQ^6#q%~(=%RziT;HffpxRagGxxJ1XdY7!eX|?{@ zT}eE43^ARM0nsqv+xk%XRO#n*N$JZdIf%0VH_uO;OZZ|kPD}LP^v3?1Uib${mw(C) zS@o8%gzt;8$?4y(lMcy+eAQDBKc;>s_jE+}mCW?Gn|EcD(k~`x{~Gce>m$6W(Dj+J zqOOa5vjMnss}5v{+G~g;pvhu1 zmw3*#c!iBLpzRxSY1=@*^p`lt?e_#Lk7HPz^wGI(JHvF4MgpT62Iw=Q5cKDIihd0)*{-AD( z7Oe`Hm3*`b=i}RHqw2BSADJmzk;MZQF%MOb&oA^uiju+zOJo*r`k^^r_w|>~{LS#= zX$Okydy!|lCQ*4=#3u`1@17RV*4@H5Sl7hz;Nn6uNO6Kog@?XQ=M)IZ-G~a#Wezh^ zJcSF)HXhEmVV~{-DdOFUT^#E%7PdLc!hF8!BzY;^ZDZVO&%AA_hP99>N4#K$WnOC; za*M%dFy6&bG;Paef+D)OX!{d8E`P0rXP_=Z(eoC1?G4cE0TIJvqAk+Qr#9#kVR`ju z+ALi8n+Hs76fs2{vb1RzlN@gYk-{HayJgLVB*h++$OPbH_s2*w|LGwLCkbY=&|t3L zEb#cU+d6SQ4^0cDr!)E<^S2=u$)B-A^V#=}c`%#%$Aq%$ISN$J`=L>pMPpHHAs~f- zJ=h<;DScl}j{)~8R1Jic`~jV-z)SM4D`mu)4Y75N-pbz2O;V@eVo;U)ow00j1q5n? zBR39JW2Zv~=gH%{ThILF(IK$!gr`7fn=)z3&SB96ldh-xd zY-J?rH;>>|o8v2@k8bW#s+7ssmeA^)#X_~}j8PpFa;m4=nsy>dC+z)>Nv07it_9h{ z;t$HhpQ~XA$>kO5;WhDjJU}YHGmgVA^4TIvD;poAv)0Pn-*KaSJJBM+rQ3KwMdR)x z1=qG;zj-vCH4bwwlWYH8+-AK9F09S+HxI+dI&G)CzdAJK`sUv7bTD^}JBN2*1>uZL zn+w|_qM%Zkm&@Sx>a5Lri`6{3O*SOY?jg8tUzN%-_K!|37d|HAilh)IWT%C(ZfDjT zK+WzeE;1%>w_qVQvez-k_o-Q@Xf+o~TaS!OW%e9=5Hsif+E8MS5E9c^!3$ z2u7OQs@acj2l89T??Pdl^&c}?RImKul9Omb>p3A6cNu35a7PzQ2tL{$sN4`{&n{@< zFZ4$DP@9?DxAt9|nzlxDb;#uki(Iapma5|Uf%*`S2D|_ZrzD<$O>X!K6y5}%7fpKg{m%94I@b*nl65k{Mscui=T@S^*sP~4yRGD$YuM;|oUa8|JJ4(b z)D5P#(=m@C-+wpRb4Qu{Rhf$26tlmuS=hbklEmjDRv{fQ=6F5tkkQ^>xXGDT9s07R z2NPPf1}UJetm5NDq1MyU-9W2>r~nnskS38$pT zk^`V}KliU@+plaMB?^uWmd?Fkmp)o7x41J>GpvQN`DIyeA2T9$QvVRF*q+&>dWZe& zqMrE40JDdF<9`7rt@OoUf}2|DMenP*#7{x*me_bcljr#rf&yPBon~?+x5BIo zBv%EM#QoOurbSj3;5j-GQx9Yf4PBuk#ov#NM4RC>h#Y$_epmIB*?G$NLvG>SfFIe$c2XkPL^X21+(PgjcNnvgL^ngzk$z@~qR^Crh(f#+|v~7@)2w-~#C7H7tw96JTt76UZ3ByG^PuPU9i6?* zgX66c1SHR0y6?@B**}M;AXJ_Oo;n~9;Dzif3i#12ihQ11hPi&aRQ)E%l`ay z{sZn0hG^LrlneE;gh93d|BD_BC7d)Mc{65jeV}Ils(L_14xi=DY4CvG<7=OCe^;Bzuc?ohB>H>X?k8yRQ$9l*Lmj@tiK*dHfm>P*95dN-4A6;17+Yr zsBftrR@)d%E^9jmfMUy=T>f4Ah(BUEP~>wiX{>yeo_vC6m>ew>=9y6_o~^L+mj@sp z?_B}+Z@$!XOryg|e+*c#OYK|_ig;K_B=udJm4Cu8+?%aFtN%v1gs}eNJa|4MAqI2&( zmTf+rkr;zrs*vDYB4>TU!up$9VV?9aa7D2oA1=QPN@zc3857J*}eN3;8 zJsjP1GH9=)kgz}b*A?*wkWZr7bFxK;v;<3N)T=kh>)_;>IneJ+Bu!fAWw}Kut%0iH z&DvGE^6B>}cRT8=_Q)+sKfD%A!Gh7(hw#)>B(0`-k}hwB4+@eewFfH)I8~Z#6whF2^|d06Nir z0Uv!#vZ=b$6jMu#Og>d@&>$-2=C7TK7?$73>GNFNR?Eh|w!$P2naB2otF1zUtRo}? zyxO9{f^=zp^h~I^7L1gbwHx5;tyrGT+*`kr8-64k+3=dP%B}~if)*E(;#DL&J(kTJ zxntQwzn(nb?$50`o1>yAeGqIqYV3aMx|d%@F4}|p`k~P*jKJH+tYoCXUnjM}(*Sxj zI?3HU^Y66gX3TW@@1A}okSY?nhmif6@I4%^F17-80dMrav!6*uzj=kLxpdF_(h)W3 z9N!zX0`C_w^7uH@?fJGTM+Sy1w8U?qN^;5yz7Kh~*_}r?>RmECo+s{=&I~U2?~)q* z{zv%ndW8>F3EMBWIFGE?c2E;2N0*CSe8#_ye)OtW?8;ZVEOiaE1%hGq7N43a-+n1p zYnoSb&lq>}aO5#=adgi}+yjgHu=_W}?mdC`y;O9B&XA)lhU{|(4zuyOC9U*GCQWBm zIIw&?)Q2_#OKramwN@%+KUr5;S*NKC@)2%f)0bR*hL`%*biiPwEg%``A7av~f*b}@ zeo8pJgVIk!wCBjAfWoLY*aUgpC%Yhjmebfff9v5pRpXy6RJlhFSi>9Vg3>njK7+mN zfAdh;1SQYK3r)f)VQS1qT;Uk}-S*E)CzuEZxS7;<`B^>Z#2;92r-RxF6WzGQLgHLd zQU1{%jeS(Yz44cyG(AR67hn1aYxUbt1aIi;xePDlIB>9uOnrw5*dE{5r}$0w1Q?BI z8il%L=WVB9+T@;$bivc;ac53BexvYdb@Cy>XvJ?vo%#jNMHa8N@#_#dT$xR#9CaPj z?3UGzMjZep*RL79T@N?%d0AvZt*PuFU$-BXRJPrHM`qB_5L?$}^uk+J<2NzJ^Mh-5 z6V)&7bv-D1;aJ2@eUH89g>R`We)kZ0tV*e;z(j>x95tUwE$v!ql4YH>K1&=Wvu8%9 zfL8F_o*7J?mmaqA8;{vI;Y z2!|3w36^91n2t#b#f7xeLhc@ah6{|crfR-pH zcXG34xIty>HENXs3{UIqw9Q<+;v+_6=^pR1@4e&~F}<>CJ_PwAEmxho7I^{JRIQt?(e^ABPqRqwn07I1Unwj zWu8@~nvj3>lGfnbH63~eUjJZ2W>h}^{K=eq0ROnLu<2S1u*0Rb)Adn*n}t8XNMkhW zEcbjlnu%Oc*{`0wQCAK%X#u+b{R*h1DAT*8Mgg85UY?kl&anUnz1ZtFz00nCTARg_ zz5nf0O@*`DEW8AE%W#dlOG!k_7inL}>?3537TK6lgPH9;@toMYP=;J2i!pZ-t?$^@ zsXZ)SMI9x~^#wjz$rZ)nRV+P0!I>z_sMsF7m=8A&B3VDNetExnZVa=UWHr?a4Heja zZQyLbS-bl~lE>9f5Ir3Z(|UNgYTp|d^dqbvU0$Y}NS@wy+%H<2JKUj8_}GT%!n-tk z{*Bl4nEB{ooULYsT*>*`GyfKw=RNu0e&apTVXUHXSkr`^bZFD$g$~EeriO_3Adeos z{N#3BQZKlc?jl^fXwh}74NRs zr%!L@z3p>q)R2uNQVupVyN2gv7YzGx!8K49i!+s?ndhyxuv~ffkrR_f9%X61FL$m%B70tgT!_1O%+pgKa@Q`{|iG9gkWS6;o zTdMO0(dv%1~r!JK|Te?7Yea*#O9?-DjrchAlSSNXuk9arEBc!^=sk zp7pnvXKhe{tJ5<7{`|)OF}e@^57FlS&ytExFEU!5<$NK^i(}9wmiw$g`;y(bvV>>`r=s?(kK<6cRxyEC z!q};UIMZu_9_nKhRk#7gN?4wYPUf)Yb;kPnN4@0aiItHTpp$3y5czWfGJ;`)&JWLc@|t zNi6Hwoo9Ek-_Dt{yB~3TgZbrF=9uWEW~dhrd+3aS^4v7wfcdJ|EdiChJBF&gA#*1Y zOAITk_~qtmmaCo>zFWA>>9&S!=xXrci)^n~G7o$uw{863asRw5!)>dsTHrsq`Y3B* z-~Hm`G4A@PpCNGaQwo$;-cNP4z>S1|E{{;mcmUa?OiO=tT($5ieMEIsivKdcpLMYc zd%+|WGJz^4o?t3#&}m65NZQT0rYv#eQUlZ^mniNZPI9JgF2Ra$S3I->`Df z70iw>f=p7K&px%CFG7Mw#}2C6@3C;VAwP2<(;edn9jmeOO)3Ps#Q@62<2TQ)7!vH! zG^*9E*Z9Tm)O@!vg5Wr(9HJ!*YKIF^W#2b)NRust2^Wj2ul3vu#1gj=XWE`=5?&;3 z0h7vxT$zP4G+fx^p4;~Q>!;3PfW(+(2=x%b-8jps@jcqT#ngy%899MyOG_xO3eKw% zHFg1SD)T*4q?i^iE8_nNi5~iF@|PtCY2hI#Hd-?kyBT70iRPm-4|Qs>pw$?*dYG$> zD@H$bzMprk5$U$?*_iiQY{xMD<}wT#7U7uz|ASL0v}9p`aG&k@2MQ95;7)E_Hy5nj z{L@S-;`w8nP7eop!VYS*p2Z#ko7}v}2^L(g8CcinKfA7bX?(#EH2+e;48kQG!lfW{ zPZ&gwfiElP-?s?g1Jzq_fD=Njl_(?PTMD^!<~PqacohhX!Adm~Vq5++U5l6dYn8&H zaWg6zK{%!Bh}S#C9~)}WIl=&CMd5yiA@yRrerCWcv%`Usjk=z+7A~g|rv~>X-0^yvs-gdy%dG1iv>r z4x?^w7`w7I)*f;2yh4?yTesUrRynl}rC$n`A-+e7#P_xqxMi0vLK)<&N`=_W}D;ta>&eil=0-=r&Hj$6gEB(?c8R#im1_@$jQ2{lusN|GTHJ578|UpE@~Q z=h$JDl7tEsVlh^BcW8@Uwqo*pj6`Ik!!<+uRKU{kr8Zu5CO_xrA2j((#uro{>zzn9 z1t)(*w31^iv2ZkQ@<(Ug>uYcuI`kwViwHmTk}m7UV7A{nTK+}q#rv2r$F_7mv4#S7 z>)hDCb@3*F#dcShgLq&PoZL1wdBy~pCB+$CoEei7+s#%9*sstaCiu`;#iDvmYUxF_h2e#BX2lzu;BnSFVB9b#TTQce+yB-sd0~&+hH;J{$BiKY%I_e=trFc+ zbv~R>#Bw5`U;o8-!W+?;!&i3<3Z0s^YyT_E^3I76LB!97&_=rpm%|>|2#8p~@?wJY$(R*q8uVVT_PFllIdrKR)bTp+r%loVZj~TdF!b*JcKGEK+g=gW zJ|%9ONYw0{p51qqeM9K1{tq)QKE+{&O{UKm3?9-Jj`P_HmO3|yL-gNEeO{x$Y+mT%g@ZTLYYll=2%p3H>-vPdT_$(rdO*rPy58#O80bHv#(s4_@Wu43 zXi`jbb^0az`#_0HW}$oqP2cPO=3qzB6$yJ)KQ8bpy9f*~s1;6lia@Kn4eEkiqb!3v zBU`^j z_Dmshu*(4JxCu;HRvA`mgeBtmqCwcZb)=!=qob!iPL?c)z7Y)k6$lQtlImOjie?HQ zO!n8jzJQx(^TUxQ@jKPX?|y}?bJsm#8Ck9g7lfn)L*!Lqt3^y@$BA--m7qEfD7mAp z!#+=@uJ18JNo`y=(F2FEud7Zy1+J-Sdi#Jp(VJ$e3~8qP=CS2uF8-)KVDt+sC>PVv z06Xs}j}z^EZVZO!_L_~D81R56Irju8L7plSFcq?a`SIA32P`4-ajrCy9`D9Any$sA zehr9mO{uY~gBr2G>qyS_H_ye~=k2KeB=?g@lE}Ls!a{Xy#rhF9 z^{@Q%O4vZ;>di@6RO?TOV15#S6W;g|@Lhzj zM~8g_BHSEY{8pIw7wJhYjy0nxyM(axk$1$HC^k{_u`q&N3|a;SPElT^!G$Bc?Oxmuh2S2D4aviI%1&j|~DVsf;eONYeB#_R8z zba~Utb7FWUi@{W;*1Vo@wu9AteZAq~Iur{aN{zLZ`DG6t9YFwYV*lMYuRp zH>>Sn)^Yr@2!SZZyxWO4Ic^l9ALjMBM^UUC1XK|mFOq->))JNS>6pqBp_bmLa{Ws>TA%kTUPC7z+-t;W{Kjj3PiBd|NO`QfC7Jlq$A$HK@pCFEo()T6yR zOH7wD&wpGZ6j+TPfWFHyy=|!~0l*zPB(oJ0k!%0p?e^ES&}Fsn%0*Bow zx@te*@STfRWtG!^>IM=S@x#gHiq5BWUrCT*EiZmr4}-C>{mlokINCzoK1n zZ_eci*Wt-TA;ZTr(-&LU6^$|dx0DL&2fU6v+yx&ILkq?P?x}q-n^mNSOhQ9r^ zfk~6>X|(1V82Fs-leU+P)R@uB8oq zTXw;uAD7t&cv=r!`7;0Vg5YZ;*AQPfV{3LsXxBsNc_?~Zx?Pi2lN3Jqy6GIs-KTM3 zFMpmN^FX9}HDcuQHzX3hnl?x&c{D`pdM~3e^qvAgFas^$m9-if5#KE$c5^_ygt`)m z@fq3?aa6=%zW~p}mWg*SS=KIP=2>l!ogd`?M8{VL{Ox|IjZv=x+k51kGY9@KIuyKK z#{zD4rO{Mv~Y&T+6`1vWTFEd|+1peaHyEvtT%!kU5BhIVy-7l(@ z4Wo_lw^k-mT`DBbu{O4ttIiZP6=7XiY}A$+dT~p*XF7pd20!DvLSi%?7Q_C@?hlrX zW3!2+&z`@l%}tEin3`6PUoZMJqy2a@(fi!qJC2f2Q?^3|&kONuNPIm#3;$q}T>O~- zpo{mNCGw%$YZ+&2o`-{l=VDJANjPYeWgX&g-W8mp+jq zE}iS2XH6@O{&WKv>+eVQa!DmBQO=bCeo#iYn6LbYlo>0{Qun^{-a5_g_a)A?@EqI| z<-2`jLVP-TFT^raCN~PbQz9b2FbmO8=$UeZ+X<+nMxd zzj-3~RiyvSP)g%|3<>(J^Cpr`X-zj*pirAlY1v~QubTYb*M!V+I5X|fnLB0_{};c8 z|6_RnUq9s^GSc(!mLmW9hyIUuTnBoQpo?Czk0|0kDC4>L2DG9~VxZ$v!FQ2_7_rGZ z`JKN)q0h!#T!g>xpt|?O>3!Cd&Q%YP!?t=J&<|<(24MZeG6E|a9W*iOv1>Wom_qy$ z-CjO!D^L5B3`}3q)q(rf#mZ~lV*LJ{l$xa*`db@NaW6+mqKB1HvS&-@cCjEGcDyLvtwd6^@b!_YXXt{rxoP?3bA_m*4aH`v zk$*|;-1RWyQU}z%ckByT@>)~-oxeUwQKtG(puyV5l)1Tyb8kz$jLohocAr(CbQ5M_ zdt;*(-nC_H&J*;A=-)9I%_Xt8jRgwTd%!T)JW;h^+M($hA98YR@f18tScd18v1yto zHrK**g29qJVs<|!fv4PD$WkF)T(GS;;#36 z*jE|cF!S@|H-1DO5dXM6;@1tp#0P&3D233(sbsZbR9h~6(|g*X>WJzAXVL})x`}oR z`O>|4w*w41t}uk0#`ZE~{=W8H@Y@P{cH~7O?K%lLhf7H|e(CobXgY>Y68N$?NIGnF zmtZo#@5?urn$o>${#7*XWrI37(-DWSwg*O~2xAsSHuuT_L)m~ELo0alpS5tqCN#Cg zA*oPG6KEJTkVD&b+YVLDluW6=LJ$3(}lIHAo}5z}kg@N}pFqyQWO(zXAKfR!Z$UB>_FDsg>4~ z&34XtY5N@n9h;&C9@*Qm{5Im{&|eflFZO{e6trsWuEEuMYT>n^o>ouL;+o?N{0#Mt zxfe@FV!)jW~S5jPEzr)+Ryo@`~8msg`$Ih`|h?)^drL0@1E^wdwcSDR+>l=^%93C=q{WxHP5d+mbJAWn9q zQ8P-FeaHfQLk4H|4LkIfO46MrbWS8Yo#{{XiYnDmbNKUf!7rYJax zi%=dnq_iyT#(1oK8Iz3q%`+eLWsuvV`#tepi^aT?T1|SbAg3#SEfqY%C2LVDc5Y6- zvZJl)oliJz7S`8=8pFbJb90Xv?{T_vmX|e%orso~rz4Nf%GP-Q-_cw ze_^KuJBQU=dVwO?FUVeRM zwmEu5mDZ*?=Uty|KuyLz>b%P>gYVNmwYNs(V3jRws;38+9Ovo5_VVsd2Z*!m%A+=# z1$AilGv0fdSw+}z2?7p|ak8u?5s*wP2yO{CTXO|B3$)ljfAgFY-LE!O;u~UZpKzeo zCv&v#-4)%v3X@+a+)eh%c>Ho1yhL-?;yjWAUFL#C$KiRHXg74Pngm}?k3wxsX%$&& zDEq~&N~1@%BR1BxH&0w05R!bYApV|AWdUuZ?iRbbg=3k|OTS2lLMffkHGN{c2pu!; zE!7Ug(L!IJ?URmQ-$6d3&tEJ`R9FarqXq79CUD0WUQzNvE$gV zqbOw5QA7u#0@8^J7C?vyQ6VNvMMXu4ii(O51tHW#PzWtVMFd4eYLJr9AqgRr6i8X~ zJ#l8vcXqkXbKths*ijf+-5bv|2p|?Y}F#yxhwd^gHwfi>azEUA@ea! z3BkZB)vf+fNsIANf_Fn}QwGcqx=Vp7bo*ZrnXPgWDWXR_-9fe)`#E8B^5teinbix? zZdY1LK4-?oWfu)s1&*9Q=5mAjJTIL!c)sv8=*tDb44dxWH|RA@*os z(zX0&FXE0&8hUxYIfc+rXFTt$dAUhhMaVcy%0lC0@_swl1i_JCvWE0b-feMu_2i`& zZt72qF%n~|2UD0GJ7BnO?}X3toZiphpJeouADlRp5q%$|NVnn{=^;SWN4<_Wm5wl4 z#v)>igAWE5v@V5;-|Fu?%4+z(gdb>lvB=qd%IitnHtKzC$Z=Q@M!z$=$Y9l@C7&Jl zoI8X((}|?8s;#kNcFK?O($*W>t!;z6>!@5!fw|fNb7q2dyMRB&(jsheK+@Pmm5uWoG6Ps6Xl5 zi@ek41AoNU>!_?(YVPS4QBt=q8fi*gIk~v};EdtIQ}eUybnZydjjh9#O5Vp~-Fr_A zPk^#dymV7$bv~65_#)QPV4ZnqRL8Y}kga#I?Rr^$amNb?eX3BOes7Gy@jZ`MzP$OY z`o)3m)DeR5g}GBVcapKm^1W7~vsigl@aL4t6N8^d-kJV&%<|7M1J)f%nu2!1o!Q}18D`svQpI%$5c-H# zYAcTM8ss&mk02@4O=bDYKJ27^fr*13zKw-F`B+-Kf$}+PnJ45>;n5BKY^O8_)QNn0 zISU+ApE7q$LSwEk`O%eQJCJr&B);8c_95)H4Xccdrec^gXdRN7R>RFDQkBUY;O$D* zx^qKF#U_rOnKETQ>~*qU$W>(W_>AH+FOT=R8+0SlPS+(9loS6GWz~Ojf&bV>{ujv8 zzexSsKjFTDqnq8F{QLX7ANqe~ohpc#wkdm;>8T@Y9u=N^&v!X-+97*-C84A=JBHGe z>+ghd%E4FqoyJxzywedSe{b!2tMi)Z*4Mcqm&TwTKYp%6ooR+FWv$~OIqH{|6`8fx zp>IV>Qpu~FytU%=k6kZ*vNKRI9?w}rC}ZWZ9-xCoohO$pm6#oB76aqy#zM;Elgx9c zQU0`q@&NCamA#9IkE{o8qE$OkleCzZoO}2){`~xOk#SF!YKzI!=_N<&{jcZpI$|bV z&r1S8eGIFFaS!&<&-7UvT+8XgjxW4~LgY3~ zK(9L`ciMf1Z&$mB9LwF(b0j@#{QR=+)k8_s)~z-l*xz#km5gyYpr;N>R@|Oj@VPmq zqRc3I^Ns3ZbjDm-Ds7mc!Yk=jEo|BSE>B)RXWnUkG^Xo|cXrKzUp{8d{E@b3htufe zyPIBc)QJX6C9hLIsXfZ*IQl_ZI4By+e9vBA{wSH1Sl@$AqC|sb6Cg)8lg@)MWOG+< z)^w)r0jIFTDUe4Aa-A_(TdO1ZuaY}zil!!cTiS-req1(9E?pN^niBai<8^krz9#X3^5cYaQL>(a zRGahC`1pp+H`vfVVeSsqHoLsdn7S34SoLzb6Lw9bHU9fa#2pq>*RKq9tddns(DC(j zZ86j-7)u>|Z4Ul~DMO0@bNWT2mC}6g<~`@U5{WaLOZGL1liTgc77l?R(7xhYeK^(< zK*y$-+dguB!op45bLX}mU8HmjnM*$RJ+JCqf1QwiK(=_=KACIraHZ-nYW4NF=oRaj)8f)Nf9Juz> zB)bbF$k$aX-Ch|l9O_Vusy-;DNIm}1h|zz;(Bc0Drc1EldHoY?+FyJ}^}4hED_<7L zdB=VFo0piK7JsTU>Nq{}>#OA(EpqPeUH4}FIA`Cy@6BhPd-DDE@$v%yW`%wnS`*Y{ zc8tZjJaXs5?B^HMRApNIU7Pub26z7waogJDRa<|{6+LG;-$%w?!Mv03)lC%W-?+Jx z&_bJSbN|8I^;t2(4Z1VEhDjo1u_SBQVA)XV8qU#@x|@)DQNcHmA+XWA(#1i?$Gz!4 zeiQTg5lS{}I5nD@G^M7hBEaVUy<$xD+wu+JaJ29v&)=$I@A;(KD1%3K=ey)1&l^TV znB6H9QbnK4T_%~0(!vlr22WQR5GO4!O&hnNjaz6l;)!qxBh36-sRB;)-di>p z30ABTrO7JpErm1fDY{FSVMGSdruUemo`xmJR6;6!29&2}ja#;<6{XO`mF%h3lPx!X z=7%#R$rrGOvLIySVr9+;=C9K{pUk^}hk~as6l+*Un7l0x4{bdq@+~@^vSw$(#Sa_j z8qh}!D!IHz+2q)h6Nt2*kHY)jvssrco z>TW9j>5>>jMRg#dsxRuXd3INkC*OQ@Q{$TzoZ%qNL^Sn;z_Rx3_*JIZD>i^fyVNpb zcFxADQAXQ#-gZ4nEO~o;6My;f2QJ-@Lx9}ezKd8T+;~u1 zF=!HN$*NcWnOpKdSitiy(1QE_g(0Z_$$0<7sn516AIA8&O+#Qh_PLIX)msWeO})?R zf%3WihJF)=#S3^y9j(Vbe%OW z8{YZ%J-w!$I2#kYPOS{zyKCyQ(|SyCN}pabBuzv_1WHXRy&w7ESH*aHxT=+puNlhL zWM@b*;=C8ESAG3F^2YRSA4=UrmMHVELPDtu^IEYTXPaqi%5YMo#--WUZ{PF+GvJ1> ztYr21pCY`xD#BHj>^RGlgQA?9GgsBIBG+hc`loTZm;u5d#H{(e z>rVwa6rS{g3=PpK&!m1I!inZaG4pRFCM6T)JzW;!0;Uw`Vg2HQm99~8bv z9#B23TKjEFIKmY74kdrgqH`(hFHSwqdL4IBAH>dkCygynK+%V$gUYjixHEjIST*)E z1V{qbDZq>_#oD8ca~^u;qc_jA>uhPsM5EgwGsmLH;GFrFz5j#f<s1pb0d_Jh(zeo4l(5#H>vEefo`2NL-Z-?|+b9CR82h&)?xtVyr7f94Cbx78CgVWy*#v%i1({Cnp^``p)+==!R6 z%9J|#Y*}Djvbgqz-L-DS>hhWI;5obDREI$$GKqj@`GI3S>)9ZMy0zE{vO+~WrhzZ= zhYBDdnha?Wijm}M)5cbg)mUP=x3TR%D>8O~oUbI_pYkwf1L*q`MQpJ~uY-S`?)FQa zyKMfCM#^nUikSu}ZW&|6wzzQIIOqjiT*(RUak=0&gZ-gLdsZ9*NeyJZ9^M=JWVY+^ z^s2jhdKy6EfKEjZ-wY)$eO$P%by^!?gL42_q)G>{oQ#Cxb$7 z-(UUEIz(|5i<4WyA(6HZ7$0|7h?|QPDOJpaB6Gm3d1ks7IDK$GGfZSnLqaxZRTd1t zrICa!Cx1{E<||Y&gQ97)xG9rySwWjE+t#ghbu2MN^;zx5)aea{C(`GVeXnt(JrbV5 z!^y+_`gNC2qgR{0gDi!LO7T(6-QD)6zw|p^j}J5WC-Kit!|li;W>=L=p(l0uXY7#w z&UgF^CK3O4ZsV`LRoy;-_u`R_itYX@skomaSuYB7XLsM4^Y-Mb%0wF0A$?Qpu^1C9 z1|PCc;ri98AnxqSZk)p8{d)-U1}X6}LP@X9$1i>ypAX{5bt*ijmFcQzt@+?yL!LR_ zo1hFa@7s>m8$gG72TOOvgo_2PcQEP0?fE?X1~E&)hhh zF`Q059k$rZUsldL2C-|AhCm`*mJXfYk^bR%cK<3)LnmfXIXo)=s^3$0$B9aFDWB*( z8C%NB4`ME@4Z#j_v=|HySN+aqdR#S5PkS)NjCG&rPU1S$q~)^%dvI7GRV9(5!e)!3 zBg6_!Jx_|TR9R2Il4V4*y!N{7V_K-`r(^Tq z7Mqz0Y`cdrBc>xHGoJZ!afz6ssF(n8GZFwdCcd*_?y&$1rP8aUdgiGe|_VX z!{EL4e{x`aW(>(7;*Hlc)@V9qYUEs^#h~Un{X)>F;$!SbCAsocQFDK#sM&T=7Ls&3 zTDaj(_J>8`k@2_&UkiJZ_5VueB(1agS5F80Z?I48N9uvzS8&L&Z+J254!=3*8OD@P za&b-GHsMY;i*e93g;@cqCA!7?gOCJOB_Y55|P82~iA>lod1Kr)|)_iEfU!v)~K|JtN{Z2N6jP0mY+fzeD9!IMQ zLZt>2m}#S+E&R&ck+|&DhmLx;-hCYSLIPkO|NdCF2^L++W6JUBV94^OeCwp+6-FW{ z+(er=oe;TKYiUkAqANhtgnBBG_WvxDh~9829}iB(fRbTRb;zQ3O?yuSHB^xBPWCBt z#q2Ab&V!0wLju;2;Jw+fA6klDwW{X43mpQV;<5JqW`K4OjK8)}qcG9j!&(8M5j(jd z&^UuEH4)V-@76nD`>+i|mV#W9RQ?aW3S?DLff1*3(w4{Z_cofRzsP%{+CmrqrZfAa z`M{*gsltNiDVPCX4-Y2Mpcd6!*NF!ibT($j7|E5l26 zPrjozI`;5Pl1a09{R(W<@F7&0CO%WDahFT($(g!4-@5EvL>oSU)J3BV*%I+>jpdc} zImC6lo@)wmBcb|%B@5#(ZPD!G2>e2pXe0u}i#-`P`GIikV5R+>_D+l(gtkz5l?i#h zpd{R7x-;IXUBMc;ZAHV=^Y7Rti=J1r&rKoG6s7!pru(Dt+MxdD!~3o{{PSjq7gstFtO+M+XECzHeF<#SxZ zrl2gXp!dBFfGkr3CX~j3A6ssa0#RuMGl&Dnbb2XPk2+`~vr9?nso&?98FH?Zs0x#UY18%s zX(6TP-rtB3bF^4Z+HBxRxGX!5DfeR<`Uf+t&pXu25*3&Qez<*O`?flkyedZjdOmBR zr*mg2Rv;;yt||*MkgPfr?j4C6BnwW3w+eyT3W9S2_=qovBvV;M`ws zrI5-U*WU?w9;EDi-0pKt?_xJs*1>n5;b1TUt1wDAe9bXlZM^*1U191bT`E&g6W-DE z-2VA%F5MuHszy5b$}LS+(}KIRMQe=@O(~K1K>;&V`9M8IPJ>UfrSow{1tj9&q16zJ z>twf0iLTUy06xl8*yAdb@Ybq;+^CV42t!Zp)Dr5)JiR^&RhG8k9JhwvetyN10HSr_ zG*ltZd1Gn8PPHO?55?1%SP}G8;OvtTrdYze#{H&qNn@?#54w?Hm)}vwodZVzzge$! zxra_}f*%7p`o`~F8`@Xctbjr&h>MuW+#uW#w=4I7%M-=AX{u09m8p>ZcX!Z#&I13VGy(tr zMFi1!uLj|1MEhjIeCPn^si^zbD>PS#7oiG?YdF)fwupUNQIzp*HR>Q%EY=7UxET(i zGCo`Om+hZ32;EUdpKC@6+*oZX&S_iBLi}O&?zpZf!|B!iH`(dq&FM|=*J-xCCecuF z!O|A;hfB)cBK<4RUuyYlUk9YC)5;SVp5Z0U_a7B_F~zOe;`;1+-`gyyPB7A(8HXiGDs}SVY6Ag z64%uE)-f#ZMY)e`lg6C3?y0s)P?K|<2IFG&24qWS2SoSD%^dGEf^nj(JkdOlaBZY^_93Eu7Vi!8Xc>rN@C?sy@&?ket}BSMRFIFz-6?;PpJ5-*8awMLbWTi}OE8?z1+E73la};d+stjfq7t-)SaD^4lKA$h= zM0;{UV!{qGDRo1lMwrluhcUt5#x**XGyO)1;y*tv#;;<-r$eK`w6aw>&qVbyGp1)P zhpUnBvkg4iDdbSmpP%JAm1q2epXDXOJy68Sp)&Sf5jWdRrj3V+cW{{yC@HKU$TTC+ zO~;qaCPDBCui#K>Ekosr+NPf0E>HeU`=+HT#>7=L(?( zf=uE{1#`kc}?NEi-8g855 znV*N!H5|5sQkF{d%vbbh{}(sPUpRq%XNM{L15N}=qR2b#*5M`+VO`PM7YRWMqv&P1 zzdAj1$7@PjmxF*`*s4l7dC8deIOJ9ble+cH2ati{2fbk__8RU8IC%B8r~5j}yo}Ka zv`%YB-JP?(b2&-g>9qsZp81fFfNZ^Idsn3f_Z*h7Ii-;Z*R-)>Ua;hHgq-+w?f|xx z!&QQh-nqQab_0KHNm5hZj4RDFs*^Y9c)+vmT)ySQuq3Q#MbLadN&A ziP`>}ERT&dJ2eg6#!?enNJV7)%dYyL)u*sv5t$lGZU*zMMfa?@F<-PrzU)9r3n9g3 z#pNc)5v4N)dSx)KNJV6u>+!6WXAf*5lvbA@82i$mmbvC#HNU1>@m@ajNxv|@oDwF} z_R+e6#t9F^)|Ck_JJ_e}qi%1ilc5Pi6b|kr_FZWFfU(DKIzz>x$~I$C(Uv8Ql^aOh zQ}(TEA_Zk{`^t_^wH>o{mha0)zRw8EQEcI2RYlO0f^N&0=!Jx;7hxq)sBh(OI_`JZ zK^r84pHZ*el|jb2n{N41n!&PDo9Yr(?>(>mTjBTr7R7}~U1^iY8ZHA1FpD5@G-3ND zaG50j-)UU_&tes_fA8h%znKZyA7>x?|O_ zD4MCHD)@bt{TcPWzv;ZQ=%V-s!XQP^E@f4^L;ey6(~N7f9!B;=lz~m;ba;w)(GLz( z`0VF0W<{*gn!9?4V{?9BTYCsGTum#a^IM7vxXg35LW@4P0RsAtrr^*yXG3KYc#nI) z4;ps_M^{yvD0b0ZfBzm@8`=bUb*^sAbH{6mqKqO=TL8jiE3d|q-ik$^&doH(eq~{) zDbVCu*NHi+Y}nZM;xLDdJ#;>;f6^0!)Cm7$DQ8x#4pZ68EZx1j?t6n&nqsrQceFB; zEz|pIeEXzl!|B+U2qDm*7VOUcl@JT7V@^z2e)RI2?8fAgOCo|?f*ssXUl@vP5Mxr`yQ3mD?cx)US$By zQNNLf4X0eW@U)VV5;K{?cA}uha{}?vEM3jMrpQeY2q|UHs+DC`HQW1&%M=vz(QV%nb4ZF*r;N4V)0v+7fnG9oqncX5(K_O-7HM4TN``CE;}H&b7$QJ;BAsa~ zcqS1#-8YJL;*0y3^_WFr+VT~7dGl0-($+}q$CptK<%gx5 zBIlqYwYsXJu=tbyTVcO76@^pr3@v+0`JAvNPfbcWrrVK>IUYTv_blj}FFb5(%}v^1 z&UDZI1C8)x=ks&^292CeL6|Cj0oZZE0YEd~kozCKy8#Gj0efROc+h_b*#Fs?Hh=45 zAsAXr6Jnb%Bg~u)=kt#lalnW!bO0NDm@e5v`h>U{3ma)zgPf4#DI+9*bxp`DT!wM7mWoj02fZs=nv@i5u?Vui`s<7d3{O!Sd?yKTUyGMHr`C+Fbkl@$TZm^* z!LZecA<=_7C=0^f9FA8F(+6)?Xx*CGqk&!+Y@wwaGZblrUU@346`PB(E#hqRq65a9 z!D0J89VNOi6+IQnR{ijsjw^rAMCxv$1&0C{p$&^B0^v*FaY$5(FK5VTT2Q4(Wzk*J zl*D%*0uku04n507E9FE+x5`4!0wV=kw^Ay*iXGa5;WDx>#Y4G;Yzn|v-hlPN;>qkF zKfI_N7^~^{UOl{wQy#S201e^EWoi)hZ2n@LNOZyz4iSYFRNdyj>B zvoo`s$OEX+-r^4-JUcjya7K zYx+>+-4yZW>6YuA_D<`mC%!53k5)Est(Z@YtcZA%Cs*S^e z(k611qvY5ZtM{cN%j+v1r;kI6MjtpEu##JDS@H7z!d9N`Zz22*xMMgSh7E0{IAD?O zOcdLKM8a0>*K!pt_0Uq8Mk*NE{|c4q`h!6!(z@#Y6AX%B@jET5PY~4+|C$#4)pvEI zaF{AC+t-TiWDjia-(M}m^-p3JTIAvOj}WuJc1`ZY-`QA(H8)jA0Jf&R1`b>U>94Qh zKUy)!4oGwRvr$k?QmDk`cizd=Za*`Po(gi8T1YPHi(m*i@LGO7?AV@fjd&U5P=NwX z6o1mT50X(|Lj%1gt!2qT+Js7^2*zx9iXI*M-DdQzS<>kLhgk`%x2_FBo4|B3$g!UZdWu4M*hZ3P5NiS7<~3#dvcJ9QzOs+#_6tK3xUUBl)Y6q;Z&0e5~3wZyY^2_p)M5@Drz~!Rh~pJU@WwER_KoU69j0n zMxr4Qhx&y@9xZ{#dg5^GD7zdtTod=ZPqv(iC@2x)5i8ka@M~w7(e4u?S~hDP05HiS z6WK^XD7T|e^ywXBNdKk-uFgo2wY>hTpIp{%-HNa{YA60HsvR3Va38DojwS}&bHNvB z|5d5z&0_^L%p6f1qB~kNF4uMSVpy=Tc$|{of$~L?TI0>nei{4(Y55Yv#61>Rt4n+6Cae&1R`M(ysqm%W8 zrr_73TKgUyGYlSIg4YIh&Xpr@<$u`q_M;eDEz+b7k6gcpzXUEyQKXFn~kfn@5S#Wpx3inA|CB{i5;z2M<;j&eDqk2vCk3V`e$@jSlk11nR@~g)O)cGw- zeZDy5k;)lo%2prjxA1Lb&wm^?9*MBCy;7UAMf1KU3h3W5>&&a%vhy_sck5O7a6Q!! zz6Qid@RWmbw8+oh`+tepqkMvdvqq)k0?h7bZD?;SIJ&@4%I!HmY$Mf)y7?X>f(A`k zoZ|X4UpdiQNZ3MGH$|X1uti<-*G3#q&UnWMv2Y6#6R*kJf@GTSop!e+B>4HgKxzr} zX^{MgZHzENEN@lzKO&c@@Qa7u*Th)HVKJIfGoj6II*t|&4-RJLBzO3G(oILD`>kyH zr(6_>Kc_AH;bn#mYu~fN$kQ^Xbltn#rmwE(x9{|ue-^5b2bkcupLoo6-JTRYqmA~p z&c6IelshHT_BWlaz8xaT!t@%4LFs(meTQqur~c~yI(Mt`RyvZrKyFnzX93US#P=p1 zyJz^v%iWq}zPg&osL|hat}F0kxfxZ0V#b0HGZMqQV zs8aBD=>|-fj)zgF_#!gWWJ0c`F08vaY`n$3HYDJAkZdfF#0Ync&*ICIWWLK~_g*dq zu2wh*gvP*UcCfU3NnHN$v`TdpS_)}bwz5Y@+qoPFjcC!u?Z^q9YG~MrVjG%xFRUGl zsnPcPuTKPKU8F|Bt(um_?MSmvXPL&3vHa6eWK}iY(jhq`^z$4(4X1KMX@ht;${v^@ zhA3h3@|P-4#$x?@ACH__HF^8g_UMUoT{7M*eii3?+Qnk`n+{YL$tlLLtyf1Ec11c~ z?q164#*G#z_ak+iKrej~tGhX#d|;dJ)<@3hIZPQw!N?fMx>Er$8?_cWwa*?q$K=w< z>^CCbGua^^#u@$h2%c%yGSO`~0N6oYHMX=xMx+$&NFovKtd0fm#)5Pa~YK|F=`XcTN+6+(JA%4kCf!5DIw)dHM6!`gEMCFU+OJH@em$WZ63*4IsX0wlTaHOS z_5!w^>qibztG@QP)i>qe6BP{0Iy7lu@Csy3#C9tmKO6dq6-Kkw7?M`p?u^2 z5m5P6Xw4|La58Bjnw<@QW`%T*1dwqe$8By zlJzDq0%DjJW!4QEY9ifFTGcd{d zVXnpF`)3I@Sjo)HR?QDAZqw1F>`im%DK8w$XVT2fF?Vq)FVLTT5)O`p<{q(HmGp9_ zg~pbuq$Q)Y+7v_iwG@LI+gZoxF5|x3b**RBHxHvT|u*$A9&R=$*P z|Llq7Et#1NGgw5fdJubZj%=CHbX~O>THLbd#uMVxrxV81-rA0Mp9H36K#QG3h7In1NweS)~-Y1@a~t z+oa+a*Q1m3%mt8f#na?&l2P)<=>c3~t9ay4g~ymg2nxaM2tsJGe%)Fo5cqJ0lb5uH zAOj8Wnu(+?zY7lS-!PDW>I;w~^=}sVKeqXQXfRF}glPkj1&V;*f(04>?x^oz2qVUv9J;UULMbLjONCDdH*5*TX1lgv4zZ;i-&k zh+`#P6KhRpxIW%25WI0+mMaT4^5t1oCn$uUn=;N7u&8Yw* zwLV_>VN&Goo93MsW(Cn*XNupOhY|L7v34Fhnx*p(^kV@iafuH$xYuxPHsaP?#T&*!=R}4jD1#RCwcznjo6q}`-xACec z4;L!EvuH%v%8~nb_U~=nmxx^>r~Jj~W7K(Qw~D6(iaMyWysawcg;~cl&YiHxKjcHg^F6ww@5`o;4drq_~wF1VY0VwVBU z{;usjqqI<@0qn~+RqpFDYsV8`LvJsuHIs2vM$OGZr8(Cu@&`5veQS;IjxtJG1dz^3 zZj<+9#t(w}2QM#i8d~q_a~dLsN90Y3p}89buYJDbyCJv|P^nay6CWoKcWt9HY?ivs z2w4A{jvd_60dkIju9q}E$$B!q#5`)x7(Wg0MZACYBaz1}NrdJs`k-JqO@6X!_Fz{3 zg!Avoww(6joZ{odRtaS@_H~@cM4@i|R*D@DIjMzVpPD`){ni)TN`KSY;H_E85lXJ3 zHP77=D{EYEn?^2uA!l5KSu=HLQwBZTz4(#E{I((p!bRH5QIeJ1q({5rgVlTtXv)1&A}yd zinWkZd;U2jt=xwi}< z`bX`xc7Qoui;|gOZNA~)Kh3PX79zT{=G`MRc1sZyZ*1UBPw#svp94t3*n!o~q`Pva ze;&?9v$Lrv3F)9gL2wp?OkEteC;z1~=~4D) z#YV%&`_Z|oxz^JIt=mfUuJ~8KocUzeE6>dJNouMh3^3?nsl3a8Zudn=yzn8}eTJ8Y zK#*PGl=5B)g-MnnqOiT?6x!%=uw9uP!1og1FpzB&I0SE#e_x6&Qt^N{y<*bc=Xe}6 z9R@3T9&{n%g}S5|J^1o;q&-do^WvYQd^yE&)T}# z>F>{)ACPpFA6@6-vjGb5{oRKm&7>MhWg+$DOSipS_CoY;`^5#lqx%z*U^SKUg%?X=JP$ft1}l?_9mIt$h;_N0vAh;pYfufAYA-}0 z3q}Y6?kk!dd&Q-7WLE~Z-HPKDM;3e4^+cw7(P{3kNn08$5UrN~W09;4OLzT3wsx8H zRO5kDhe2X8LWHmk3VgA5@8S^*UIafpP2yl_zauob%lQ1AIHDUwW6VZ2vfr3Ao+A>E z7}caqynW-~qComE1&fLKZnHc#eqj&y!Y<+IUw@uSV5%m)@AC4K9YafGo_T7H4%uI$ZtLrrjNcF#y+l%trVTU)&z`h*>!`rS`P)SI9D1 z@JDR~NNrHKymxW^sd5d{1o5Uh+7rL}o#!{n(OW+deP8@7FqB7P&}hGo;HyQ<0SrI} zf)s;ea`s7HQHwYa`u(L{_qEl9g* zeyPcr30>SIBoX->LRG!dCToEW<-t2Uq!zn7aL^OjzQyk`(N$s3D3zJ21NcK)NPR9y z+M@~h-R{20gk`T^%t@XC0gwuI-MPuB5SYDl6uS@VWn?fmTI5>lT;8CAJXPW~1R0yV zU*uZpxc~-%a+_i|bNATY0g4lVF!PyX>YUn)!Ed@TJpsZqVX-Atj(1!}G(=4MTTSA2 z9u6yJjO9m6)$6haVI2a8vbU|2yVfeg2$j@7D)Zz=dl*6c$3c+EzTNG6zAzgJe~x6L zMQ}&$gm08R@PWe>6PLwPN@sCb+%>|X1bIS%^jj*L+sJAmuyUoepxA*dY1={0aq$U9;bv|6g~KnC>8%A(LTAW7T|j^DC8 zMgN!e_;&E4$I%T{K`mIbv@VxJjYfMW%*d;`(=yElznFP=X-WH>xW&2H$B#l3rv4^n zO^J(m3aTMGL+`l8F&fPdK5SC^{jpGWky$s=YZAfe6{DrRMWr#k*}D>=sBI6qvu^ri zS8hrtG~LzzO{b*@fBI_Whq=tm`n|@Fwdj*#1EmJ+@~WE~4-OvPPYiuRQ$&3^(Hx{C zQW#jgl3&yC5?7fRYDGQ*gP69BE`k{1pXS;#^g02;oiK`sR>Ol(t`lJMNMF3hNzRE! zk%eKBM#CB=L~y)(Q_SEAb=H|`sCs;OqbIzvy>4pUt_Z{vhy8MzJo1ad1Q~Hsv)+EA z8W|~vxqBgME^dJ`q&8$P150y~BQLNWULwhx(1D0r**n3K4%9#f6HSyFa(`G_FWxSH zt@|C=rtk!ufPvf1o)-jAO zB9leMmZUd9++(Onep>3CV1oohah#s1NXo+O5KkKPwWp`v*-i}3rr&p;mPW0( zf^xWnBXal8dX*WqCQsUKFP-$hJfW7q_dUckNb>txEv8Xpp)bei0G)xYihkc;@ZRyj z4fppQB{_=EDa)#FG6rHsKCQ+PIjV@arvPz9EI6kIhEu z{z_ypZ>vq{EmjB`k9NKFI(SjO1lzHMp5U6)1+nl2XqbkRn-<^yeCZ-+_X7~$Wm}zA zDm|irKnPHY==~+7Dg#J&g|MI2Ocr0H52C~U_jI2tr>w@g7}kBz3humox_dVAiUn3l z8z0XV0d~+P$>u|ntSz#t;KUAG$hp_1@cc7K1_yGX|Gp>Dx&f`j_zUr0bOj^HQ>2fn zf04i_(-VPA{*Bc9h1Y?L6k>TCo~9{{Shas-uC|KBV_{9I0M7KWu|Ha3+e(2{7^#L& zS%wr%vuid*sIOp8cobM+;dqe^AwzZe##7w#58TC^cc2!{#AiLyyA86P+p zoSY`-i$@g{CRcwsG`Y}#{3*vMQDKhyQ8QYbVGMJtQEuY^NyZmYswsQOw-Hxbo!@|cZ#@DX_bGtZS`EKW4P~hQb zKjiQ%emvdmXDR)#eohqlSX!xAn7&c3{G-xl8Alw+^j$ zx#{@xf(eZi9@6QQO`4H&AWcMiDafVKGg&iVk~h3FnNhiuYP8U2d1C&l71&Oun8b7v zO~ZE5a2*YrV4u)J$j+Np$QLLN3>t{WSS1)>8-D1{6PlAcuXLgfPaqN7ILF2OtvcY=!Ibj0q6;&Dro7w{rjEU{isK z33e=o#*BL@&`fK-D3(3CE0+&{Ub-InY)4}qtXrsD#cZlFs@N;Iu_f#Sp%=TU93r)8kz86 zvzj()sJ4g9D*-R}2Z;U2e6k%wSKoaU!lPbb{KD7**xOyh5#vXak z>_=zI07TLEH!a;}6^Gpl@)5^G(?;`Tr-QL^c3VPs3E^7@kRZV+NVq6r|zf$K{m;`oU_wgl$aD@>VIj{GKeOG;ooiTQQ zze9b|E?9MD&xM^C0lSr|Z5y6q#|RT=-k2#vS)Pi zVrAoZ4;DpEzY#li{Qd>I=TX(o``?~FRWbwQAzjI%yLx8_7oj!Dyj!lUH??)!0<2XA z^jG3{vZN8J%l&Qbax@M)>XfJLYlXlIb)%L*9MX)3gm0~Vzk6H15)1$|-_ZR%fdq=b zW!AQMf~Nxd+NNk>%--IO3pK2fVYIYm=@>zLzKu+j`IPz;FULweWspATv0T7)f{=e2 z@{U68`@TIiWe{6umvyRGTavve(ilIX|y}u=-;Rg`-_YW_G?NIS|hCi z_YU$nk6W3xa|D>cZ#qkY5Cu(c1%Bbwiy9JD#un$srEZ#>ujLNc)Kk#cTKk_MWwY`4 zQnh`Ic0Y{4)$D)Rk>%^anqY&&XGFQM`G1dxOG5y4W8{{%_5s&Tvc3 z97)4(I&G(=jC!Hl<_DxRKP?@`v|1%}hCapL!GGjt<{Y)9bb<|eLY7>%UnF_KiYl2b zN{ZwTw3>gX$uYG$iB!~U?r>Cjnr<$OAF59ebOs82YDLk59`wK=d^IE>-a-5f)s2Hr z=!`FtfbMHc7OZ@`a;5s{n$gIGL#gNUGx`h<$*pk#`OOa0+?<($_vLhRR+coY!*><7 z#pUMY*048D<1zhT7pN&sst;#hb@iWYn$OOOnqs2zR67d;B`7MIx#&y`D#|= zi4n}p_1MmuiKIv#@5ExI-?gpFFZU)^WzQfcn7drQtiMP@DKsd9U7#clJ*7`h|KYp) zrOw1#wul@mW$*%V7k*t`-T6xQIokqk&_brFvKp1tDX9yG!T7iVu!HTpzp=g*c~is@ zk7)5s24wi=`*hBIfRk&Hs#K_ig7%fmr<`(*sH)lL9haWgY0+Ns z1K2>|7`H8J^+t&Sm9$^1I|KYiq7Nl)#ygPwX4w9^i*X>HdC>QWC7x!1WGdF5HfCLX zX+#~}O+zmWf;VC2@%yCCSqD;*PuUcn_z~G_g0x$H+;Z9{JaNCy7@6RHH|78WyoLwe zhq*!%_GU;vZv7lznWl6bmcrflZc-e|tE)*d-c5P79tsgJLbOs*kM@nTAUfFw)!Hn( zp%!f zWZP1IVW1Jx#wlCk#+|p)^&!m#Xl<2Y`G9gvRkki|wh{tNZ>=VEjKN`56F<>|GSgvy zR09X#?^?^jNwM7YrShb0ybqbjgsn?SWHsn|T&&vn{h{_}nK>VSny*;cH#unU4cc(O z=PBHj>*3dHySI$P9ncS zhHL+;=Je7LbMu{sPN4auqN+&4e1)UFew8Rd#T=^Evo21)`NjoSBk0tQ@_WVAE<oUkI@tYwZfx^e z17#{YW&0Dqn;Sk|JjVOIUYnI?%@z!-pDHQsNnwNM!#R3cZ<_C5&M1VvUj$`q_18=dsBY7eJ;!h21FsD# z`##+U!X70@c;JwwKstWS4n#Jw`=e=6laq%)m8vfKfM{S5nOJXkOr|0R@?t>c{FC4O zlf>XscwDp=rw{!9^;!P)4&XWb%eDS_uha~h_|NU%Nsl86aWv& zAYtc4QeFGHl*!gz0W6@Tz+1ttD1}`Ju%H}Kt#Gjbe)63Kz~pT9mHv7O_<#*!L8CeU zvIX$3`BE>A1TzNnhhKd&*^yHMnt-br3B1VNK)<{;aBEX8XOP&*O6+6mo0Kv$4|cUk z4>YG{p`>0X+Vh2(u0>ZhuEX(Iw`_>WJn!s=_D3^I!?$_YWq85q~QB+^TWrbo^ z^^u`uQ4fdD8(~t%;BTj0E8shF5+PK{#(n2CQiu+|6L5Xt#q{YAUuEHi!YSBAH^Wq* zG~nUD&Q{`jtO$ZDzhYXZHgw15Ym^I)LX{8HR;e2+ms_m#*c}wZD=FHY@*)mN%~{Pt z;#%F&mYVF(VygSNJ>3?QE%n;eO3$Gy*o05h7fydjKXiNb_G7Dd2Ao^OA={dfoUqU7 zS*8YAB&>wRYzBjPlA4__eWQ8Ze_!)^Dk6i*^`ouOV?2nx^}2DKzbg5M)mzX0uq>jL z_2E_SBjGJ#*}@!p(iRAux9_PuUHxJ0oT6iu!OzZM3!)|>V<#YY4%%IVp?sGer~?U_ zD8off)aRI?nYBX|gnCA(9%f zhaW##lnQf&Hf~N=d1YPi?u~Q0xGd{M&s*P`$Atd$_N?kHrp@l5F&HTL#DS$X%et3D| z#eME5#WUrs=NBIT+_T%I%wogp5B>TyF=1%+A4LWm>H)j(P0>XW_UjAZXVJT&fNTbh zHiWK-@%D=)Rbo6S{_<#-%O+A4BpIQ@0bWemm>Hf*>T)ySz!%7KRxQ71;y~%5^ew|p z#IepS{uDtfMsi^h1iofh<*g&m>540Q&O*uFTNPyCp5naJELw-W#I$Sc1PMk8!2b(pT`azNgFxQu50?mK#cqyrQz4EJ+k##U0Fia zvx!fZPZ~|S>>ii;d6~nur?ScwR!YS;mTUO$p~}$dKZE|=Pq}-a*AzYL+v-zz7;1}H zubOXJX<}x6Z^42dkQ{tGy9yCW(VN2O&F%Hi>$eM%`EJg)UA<)6&021gE1^J1katz> zr>)ysaWP?NL17aG0^k`?6g-{i3eB6b_tw3m0c!^uVk7qzF4`xoHpOPMHSE)4B#&)e zDyOEVqkEtM!Go4(<>`mF;%{c|WgqI<-0R;teDm*hyWY4P#65Lq>b@r!GJ7|465csB^@$hTTxRC3 z;geLnE?AU@J6XKlv3`E*Hz(|-Znqj7J0Q(y8FFZ#jsFk?t=+PWrI}9a0?K=TNPhDG z`FxCRwwctU-Cc{;K@?g>Ize8>7&`qrcyKFmw2kJo7(Et-z1aN0`VVxH_obyDP>P|* zkoZJa$$3j~$WQXMBfJr)q8rrqPo8@$KYTpmAWYDhwt6zL)+cVH0h4Km913TYbdQt^ zN|R63CFX+as_+x?r%h+>xO!E9_VjN=N8-y+H|q-F=-kkxXFvJcCX^LRQixgej;)|2 z4rDAsNSp)isojdkGvW`w)LyFK`313Tuaw1!M%^F1cG?1+Pxva|FDAndEE<7cS*)@M z=QxJVxhq}MQQCFh_xc>4?VLB%autd^)|-2BGenyF43w|50b|qA}ynU7r93nN6HW?_v#@7yqBZn z!=MXHO~oDa*Gs`O!rYySr~vI4O^csKS2gHl{~*2oQz8tQbQ!4=^h$rrAyw7`P2&6Pug?Xm207Ico+go)d(&QpGgszn;7OBgcJzK=!EuHx+H z3qLFzBJ}X$3)buqYFd0#qN7%HxzGUhp5o_UVsSi5%_LX^4Cv3i1Z=Pqh()N;z+s@Y7dj#*|eR0DejlECf zkhL9Hv!|-IzSh6Dy_Q`CPhu5i2sXxk-Q4Wjd7*BXXuN)u)7Bwo7W;qqHvGkgS!ZY8 zx9!{5%hup!t~8dz`JnMZ5{IdK!nU+^q|$*10oI z7nB97nIu?VSzUX{mUIUYG*gMO4)x#VthRq?cS|0-U*M!50b_F|X?@pw`{U-(@y`~O zi}9==N2gDlEHBw5N+@0MOFs+PT%qqjGCq27XQ>@F-cL_u?lIn`V7#%-w2~wa@Dq0= zJhOZ}2Pne`TdmXg=dWV)}V@}K_MRG;mf$3Dkx5&N9jt94bo1`slfKGYOruc8=alA)H3wtTW} z5q2?tT~Gni+@h@z-IO$nW)3-x*}C|*%7O-Lm{fgB$@Ej2H1Fqw8FMZ&&kgD`-@X% z?VE>qnGSN;eHK4(voQ*B(W)k2Mc%5jyN_G&+^|!}JBuU7nM%t2Bzq1OG#*kSK5XrD z=c$HTVYcb-g61~Qri5^&RbRGu%T9-hL^0doZ=cCwBX7&% zbm0r=Px!tsb1qYtJJSwX(tl5E?kjh*8~XJnQo@RDUX|K+1_P!sp*%YWE3?=aTcNZN z^5?h2zixcio6#$pwxB}d^nI^PF={koSvn{CKDp~R@doi~_Wk2QKl_|cS+_xA88RJP3In=HrzoW)X^`BZGGwUw7ZKO zxo+Nqkl7~kylA!e zCa10O+&o)vkJQ!+?vxh?m7Q~nUv0kqzCcJ+LXYy*WW|k4J^kE;1Jwtrse`i45$MyS z%036%QIJ`+U$*fjp_2&X)HoOV*O0clLM${mBBwO67Szo1Lgd zUI}Eqw1O9U9*5_pj9aT?WSQ+(7U}Au;i1P-YykpkirIS{(dL8uZrmmP?P)y`zpu;~ z3g}$$;0MaE|5n@jyM+56e$;p%_3z%9a=)8|_dgjp|M9v1Px2}Q3yot3^?(~>z|UDB zJV?wTOG+Q0ExDFApgSZa?av8Y&#bi5bZws2nhb%tL<1(=e z5cPkc(jLsy4SpCGvJ5}LvWX02;X%&g%-Y1yQmCfuI_koK&B7{ma9_+~p2(hybnwIm zDmx%3k*i+XN+1ukaPWRF_nYY-aoICi@K+(TFXE+T$X|&fNk4eZt9Tqn@xpgN_7Ve< znuvC=akq`XW#sT`VxKF71A?yL@GRkY<#g0B5*jlMiepMF)BDiaCu}HGPwY}R+V?io zsZrC%M0f}6L|{C)PgmtJAD$`sWx`qcWHsFQ!ruxK}4SS%KcwnkbU>lcvaVfh-SMPJn+=) zqNeX}mJR!cRexw#nW(GMDkrj5MPDhs{hGa`g$wUL(*$rWsKawAGicdWg z&73l&cP1(11<7XV5F((hvp{>O1(<`g``ysVR)=Wn3HR=t?yQ@;``+Gb*NWZ#IgA)b5si-W1ayKgpA-Cw*U=iZyfYv#3##p8~Qcx*TILe3EfUy7p?2 z@3iKjKs4rux&B+2wm$~v2rI|0Y*A7VB&^Ah&s?s2tXn(^T7If22ECDLpR#MkYDEj` zV{F1f+Y`j_Cj7oxM;A&-U2IGAsg9;#d!Su}DV&fJtw1I|V6sA>hJo3+94gVFh}5!sggtZOcCz!yJ;xSpMSkl+8n_N0M@I!IZf=a( zK)>}w?a6L;?Hb4y5~cMSZt?wgNp*afb#g*fz4h2awv}p4VCB83{Gn%2P!L?% zJ*F1^(0ji;nO z@1j)!f9#c&ZOjta#alKVwnD2WNv_lFk?hQt;Wmlc(}Uae<$ty-7PrU3P8gaKYo!ym zN!KQ)eu_U)@_Te;6!3@p6b*D?3t=xPA~@JeKRw8$@_Qeb4o$nv@V?jSqxoAINY~Q+#4ugmTo1Ccb+@^SJzav0jgMA**q=h_{)J0#{%Upo3|c_ zx)&VaG=N=VE4x++POPALIV^hS-Rtxe;|$Zf27^7Y@&V2iVIW!r!GbNz6VNR6x`7+h-2LbnAeQp?$`H8P0-iW}P-4-KiC z6R$Q^#{2akaK9+Eo_^1Nyqq%&PmtTeSf{)S`HN)4f+M*5${XI!9-1ofNn&xzxM%W+ zVjag-*dXNP9*X_FjKlGScE>Xi6oDdDlDcuXxr1_t6&u&F40>y_8YvJ8M@(*#Ugsrx zp-2-IB&7yrl6uTCRf>GH15SmVP_1c;H!1?lrnKmQekfCs*ookN^U_Q?LqGflkZ}}( zUX)jNvP?P`j5SYnK$^VJtqV%ON+u2E4Vgg=6`A_ES~wMVOw~I1UtV-iBVA(jqW>=i z=>JCBGDZnfScHEH&>*P+ZIj$VLoN@}P24|!)$GE1zMdfMcUowxVF_=~Z9<9(dY6ig}4jh*b5) zBcv8&a2hyL$JjbK#mhcJ=B6J8Wj89L)WOe$#%{=!c{sn?VWulbNyH}nk{?X>T@961 zj;0W=Iumj4Je_HSy?Tge-*99q97#{h(dn*%3x`q(o?8Fqr4_48Sx!=v&$mCr9kI4e z3h@le?3_k>ys&cftkK^ZGmc>c2Grr%o&@`6zwn%2{QAS*5XiFJQI(DnG;N@9xjZ)M z^5KnhCYEp)1rr+stg)inu-R7TDc^@j{NSH6Zd>TOh2tIUN0fIvUUHAXG@Wm!NAVEz zhvS|#{+9G%$il$4ch9vHo;VoDuF`)oncEt}_bN-czF=F1p~h2`Ij(mlCvoUa!P`8H z%7|q`dLENAbL}B1l0S5o)Vy4*11@8vey>pRl+shc&g#N+g^P}_cHd(d_ZhouSU<#$ z-0cRNo{-nxa{L~R!K027y?7G&D?@*D^uw&WZ%Z#~)x_F|f7Hf`l%S#UlFvjR>KsYblrRC1F6TB&>BoEBQ1VF z=ePc8P*x^BeOkKVVXZe0t*;}@8Hf;_qBd4V_BRy@^}InR9s3}vx|79JspnjLT}P5d zAk`F&id?t1Xvy>aTNR`-Wz|(R=M9$E88~v~&&2w1qU93pNP6&-{!)O2PB|`Gp?eir zjAYsvYBdDv!+ZJ1IVs+{n?h7S6+ImGc;E5guEYrA6{NTJ7Qc^Pg!#pZI9A`f327?#SG} z+SnlNEb=KL|8#;wQg;`$L7{J#%>2G)eou&{KW2WdpgDD8%I?bJ5gj@&*=EPMXiJB( z>BkTIs|N}uCz)0(-k)&VJE;tD#yDMqs9|1r7ue1s@&(-oz`Pdo)p1OQ!ZSFg~&}8O!+Tab&+eGY?Kqm9Dru)Qaj1s1> z^Q<1_gWZAPf%M^!g4^qU(`8%w26Q>Z6=!2Fj`c#j9IKyuIBisKY%F^k`#|H^o0weO z+%$2bKCR_|>5nsYr{<&)2eBsegPOjYA6GNXYaw+nnuD$owi5?mK;^^ndbiz!*?aa* z5iSeSui$+CAXJh*`^y}}gDV4uWM?N8S8kpmI(G2T_ttqcz%8AB>GPZ<-fuX28-N+X zL+=VYsI{_dQ`+;%)_lFfrXmb`4m>X~y@w;?KDVKB-h|X&*Nr877WG>tpXp$Kmb@1@ zIBi*)=Vaj?k=RSH`{ab3>D5>3!>tE2)5-aDBzcK$4?4lIQ5bi4y7U}yVIk_-}a=cmA{vGzI-^yLq z!ypCuu&YPkxNbFBIdZTnP^@Jf?jANtk@@G(^gTP8LX)=~9b4@lujZ8JK+td#@Q2JN zQOz;774#Ew=dIVSZMmIv$&0kbM6u7Uf0BTD#_ey&At`aqb^z4l6xx?bx7J^ zl)!}oBTA2L*mXUbc0^6-AU)S?M3zZ5C_`d7^Pi1PX!V_{RH%+x*GiSnQYNY1#?5VLDD>C%9TJUzbZ z>W>AH21}|M5V{NRQ5QeUv{<$Amq$b;0p+ zyJeGZ3}A57=k2-UffX9am9e!l9VV{`ctPm3!^_rS((&pW6LpaE(#RrdDhd*p2H2u` zzQif?>N~yachmbEYG)3#L-l(|r|~eIUaP0H;9L+^ru1^BOtOh@xFgQR08E7em}-9{ z`09KjE`8eo(zgvp8V3s~9Nnr&Pd(pV`M>?7)aWPwiwBk_qKRlrJ%i=x$N%cL@o*!T zT7f`Oy~?;&Mh}mdz9~T1OU;1r0I+~W)oNMIT8d-TFMZ0;JR0{O-;7reK9>>m&wQQCntWNVx$i=Tsj@htLt zb8@?m0ly39X%q60^h|)_GI&eU)38qv3_$W+8?#VJ6!0fjISrFuGx5+%_b7|UBSn39 z-Q>~*ql`%N@s%VzMfSGOhFxVV)EoO3*QQRvQ|2i;l!`eTmR3h*-Bn(RU|>vrs`}df zI$3{LNuxatB(G;Zk)!UFfJ5<>UghmPeD&u3U>yR>+SJukOncmUPIt9Ob`hczCMM)B z=K%%NfgTX`0EUyR1+wIzn4}V?Sse>sq5IE6jz;F0AUyS8{Nk7uH0EzlEq#tls-AvW zJ!@0jKJTEwR_Tn_{Z8|RLt$f1Iz(+axxzf=n~5LkQ2Yl7R{yiS4azfSo-T>oRR<6K zu2}NDIQwJH^^i9!nK7d-#In1|hWM8FL?{PSRkIxm^naWR{Yh)Ps*+P+O9R%~eM;|x zFD7j=jn7@+L z_PMV_+%cHPYQ4!}^d1Q(#Di~6N2)jFrv4$DRP$5rTs85t#a{9LGcxzn*Ne7Zdy9;$ z3rL?*d$uh+dQo4jztfW8oF)EWOlAOD1rd=>R1cNvtBZ7z^T8Z6UC#`-|e$ut)xm%vTj}*DCs>%6~!>|ed zd`~s@_fK-)Qa=vANH&2m07haC7TaeR=}$V->Fz=5Ve9gAF+`^y_BJ~vV>1RkmQ6mm zKPks-TFijl@8ZD7*XC+)&dVhHfTFYckE^Km2MI zx%v40Be%nECuHRoL{4WXtm~H^I`-(v;|oi^?JNI9=1>0CmY*SYtG@5o41!LgX(2n> zAM5WAP0dV7CQguMGfQgrp&KX1*G{@!npN?X{q6GT+i6TbaiF|SGogQ~z#~25T4Ndq z8bhCJo1l>jt;(u~2hk^AoVUHwJ6%UK>uSO*FI!yeWwdeL?2~VO>bW)}sk|oCbW&>U z?OPPX;OQ5WV`q`t-jGiamocR8qS@iMWUqXn<24%HjI=M}sISlIxYGY%PWOa2>4{}l zgPgvRigNpjLyl^%vZQ#iN|sZvzy9p^%5oGvNsOjPCOR>!AF4@#COa<4W?Dkq%}^pnF8jHGO6sIjh^MiwWo@EyatH(b`F zZq+}r8%tY9W5$pq?>VEV_nrOK;Eszcv3VIh>*=9xl6a@*^0nlRvu5&jyhOF_@IlB3 z3=U6jJ5#25#XHWHTo{9wy9z*I*0;>f;%8OzOL3z8(O*8*D%BmLGwdJp zewR0_xYeWcBjn`5{==J=5MH%`V@nea{Eg3rw~S)6VI~3T3FW)+y9E zsMYK#fO=H3YyAt=-o>=rKRa?bzO~mBslAr*KU!W;QQr;j$BXlPccgDNxm;p#F zp8R+Sz(Chz7H~Qd8A73-x^1@Y<@+6h%G-4a+;<)|NY2fJz5Q=m8rq%Gtf4DAOBV8oTX+KDreodkq z@C5qrB>F#{v8?9b#cJc3zWkr~lejm=&+(6Y{!ivSzGzY~J-!g4fR_1k=qQ8Kf6h|j zXBUG%B*WY}=OJfeVwP~KmRBYhbx5-rAWPVS1L2uhEKX*Yuwj}k5NA%QF{$1S&y$;- z2JDfd5YUW-QpVK9RK^65E5&McjKq>EN5`BAfz&e!^u!TwkkNDO*sQow?v>N8#lX3z z;yq(XqzT)j=8&DPKU(%zcDfDSln5`ieNVnT(rLIWySVYQL373}zl}342 z$>El&2bPaZr!UDh2Y4(+KENk!XJ(I5T$)g6bv3cM5R0LNO;lqXO2EQEk^9J)jkm|Q zbWC-dgO?4MNC42po~^b&{``s5JE2HHXvGhEBWLz32&`5(ncs2MUXGed@LwmZSv}Dk zRE$tFc;0=wj@#{bcUUp!*^_}80TwarvJX<9zHHsL`=q&JBvtRLUX3_Hv?i}KEs1&( zH7)n-BkS{^Jm^~Kt?y)XdsH)T=n64cEq$BBp)O}@uUFig9{1-^;h_T1E)98 z!)TktOKK;6d(y$}-pLi=V~?8J@JEo_0fI#uC{z8k(o|*lE{}MTf9eKNkVVy~2G2ly z6egNLtN;TuU|?;Bn|Jw{9lI8O2Eps$B**VqXNS~VVp1gzMZJ342iwJ;eqg?w^YUnM zTlde=TW!7P{Jvz>{X1xJb&pvWdotA!blIUT^rutp^H0@ts{8)zA0gKF*>rLb0u%-y z-(O7jLaZbhXKiC`(=0taOZcp@sA~pN+AsIKG-Ox5dllU|-s#iyD>F81n-#lz;>IB) zYy1Pp>KTUjV+WQHwe6G72e#yYFD5I5P|Hj5{JEByOu9O#${Y{*K4I)XX1Pxd*g{Wk#?lF1bC*O1PH~!;1A;>Ha&ZyY=o87NtqDXD0 z2PYpX4_J^mvf-x_+7CNjhG7MiNnUS510@AF-dX;`3seKY9S<+e*K-zzJ z<3KZVK)m)(Q&8l|Pr4nNXn+5SUrW-cU+WpwKOFnn^4r5pqM{tqNBuHh#_4}q`o&}s z`l_x}RsLb3C~aTxPDB`hD7OJV!Rt0T-)WThH~T47pf3XpG{2)=P3pVU5EJU@l?lCHo8&K^}R8A7`~Lb$;A_s3Lc zmrdKcjHD$UY)QTi*Z#%uAYdo!-=oY8N@#VDVj9 z_Ezh_l@S7&p7(Ry#tXBZtqV&HWYOCrKMGT>XeV+w$4je zy7u0laP9(GbQj(9#l#Ey$cS5jRAIcbgrww(E0H6VOMO%A%r$(@P>&)pWQB?os$@5^qF-ONU_&B6gdVzVmt znTL==-uQ0@#n9z_NysmS$AFdLts0aKF~g8<>bisZf?LgZt(BUh1nf*EKL)S z%FmCH&!t%B=Mw|v>Z}M_szNV=gG_%N0*jiXtkYCx>h){ z4xFA)TZ2_(G@cGmnarA1@8Gn4+R;jDts&N5ZPyHrm7o^H`(07TDUV$IEV;feHg@q! zwFfRH@lk)Ml=&#Q92ue0){J_NZ!cyCiWb^PVA z1pA&z^4BZinFjgjUQw>PAYqof5*ZrvRhjg~tXSkZwDr1TAIM*SUpON?SeQG}i(mPt z*;C{Vl*5qFteCVl%0s7b)88d0qNloIpI2U<84mNT!A{pz zlqT&Moxk@LAEE$mBYpvZ>x!^*2S1_HC!cWe1@fhZX|x@rjZLckET&6QOKc8LPE-jU z2lLI`036o+7d6wX$UG0n7vr9<`W{e&SxR6xr2@MtdncynFbXXgqwO_D$(fI)Jdm7; z#vFw$|Byrf)o1=o1|4$eJeKD_Uj4tZQ2(=x{U6Tx?*n;8pM?(N8!jNNUf@x?n+FZJ zYS+O$F9VXv^anqk_qmEu;OVpVlxTp+p%`2mBE_jz91k|E&Us?*3`Q>o`VFtDNltib zO7-egTKxqMPdTD#M+?G0{K0_x!E5t0d^rX)9bBr^e4dy4cWb9s0qXidd-81P#Zf&c z`1s&jH3T<9G)7Fu-DR*TXBS9r4jMh{be%udC}WOm+<0ucDAr41Poxt?mS9uqL=}GZ zjbJ_92HK!O1}}=;)E>0}?AFOH;^Dy|rcE+bAR2p^a5HZ3Y@zDne@aDX^V~se`rv%A z8ib+STIpG_ zSAM%(y|?wytrIif^YvcOB?Y9r0Tbt22mBVtpRtNC|Hs=$2Lrl168sM3XA$|KWgC{% zX-9qg#e`PoxE})28i!W#B2;;n@0WE!`k*rotPRNBLS$}t&PH+vZL*(KbLvpf`Vs9?YlknJb&4)gLZ#t*#4d8v8l!Cy3E}fL(>@FU&>i+5OyET*o~J^ z7wu${s5Mxy`^{BymMcmt9loW1FM7C$2RhfU;Z=efl|dOq%+)TD!Q@ ze|~s+A#x1==uyMWrzh7tkKMI#ZBFF7l{)>nI@NdEzL-2GZFo_i@xc1MaO;a=I&xI! zHqZg&Ifk`eW}p1Z-8A{y%~=yRvd0fw^l&j%4g* zA&F9*{`u`#PuK9+n1hdQj2J({-Wn zdQk1Aj6|33V%L{$MP7YR?7^~H8OPrcIL`M^eXgu}dV{E&9Q?)P31V5(JN-Q^b#~&M z8`!Y+KBgp@HvdPcBVu}X57?RN6LDjP!LZ$xG9B@iW+U~-svq)0_eG2wf`Vz90F@-@ zPF$Z!nAfhWMH>+^&*(UAnR=L;V4P^Yo_bjJhW6NZQ2qM`NN#Z*-^}XVa{S3IOM;hw zpzv6~q4XkymhkLHz;SNn#J3!6J@mmG;8*up9QM%H1|9l7YM`iqo3qeeiH;(|=4+sE zoYf`UVjr97WaJ>RcqmA!FyxlP0yC*}a1rP!JXiRu2+DY*tUql+T&t>bz+pvwAaZts z|D3zn8irlqpoR2{pq&e#qB7JO;}g3&nZSqXCb?;iP^4~Qg@qq+s;B9Dq z^~ZC)6rcJdfK&JyCpyR?y#R9i**LaC7I|J-W|WNNf4vG&*M+HQ_}H-l;~+Y4k<>EY zX+y4NEJ+rq3Z4y|I8R)@tO3@-nAuebC8(-Ch`l`%WXpld`u|j2{Z~Hs_o?s%k9*Nn zwMLpcvT9IWe_0j41d34MCs(7%OCMm<3oZO$Y;zF-xa@dANNDx0a1h$m#oGwvUi8m7*yEX4k#pF(7=X_=SB!b0|LF; zL|M60I%`t+IFTNLieOFtgzBCm9zM3|v12I8Km<4vm}Z>kk_)UnH<;&ASbsA+0C9tv zS|A17CN<>n^^97WaCR}4dvoLSekD&$A;Z|}Asukhr6jQ9LLF3-17ej4#I-0-BsJi< ze7bL2F%zFw0BJ0|%;nn|YVcM0W48sO5>6!n=blF^tTCL#_gfKJ8$*FI?{x&PH0LgG zm@Nl4flt-g+v(2;M1Y)ypK?iM9g^PO479Yb1RgzGm0W?m zq^6=Ox3XlAvX{VnPnkk# zx`yUclswrqg}mhkX|vj#W@A_bMV5MlkGv{Lwm3RLG~e(eSlaUZ*zUPzWvNqUmn96P zr~gF#WMCzjax_H^hPC)WI{(-UKa9LH9`K?a5bW7GsZE_e zd@^-fjD6)IO6Ll@L9KAl4Ew>{vmnfyqP&pj5kqWyl?$D9HH(}V_8MYz(RQ0N9FIRB znRb;*Fw-(j-7VWIBz>xWR=>q#!B6RPGg(|Sl-SML4dk!OL(pRES4K5mI60|zNP=j> z{i$?a3?($xH!*V89dpw<9#M6U88CuN&@!Y|({}x?q;K%s{?Io);xa0870&o#vcBY= z(5luS(*H}e!lCpf|cvek+YCmBn>y=WO%av zH`@?i9Ki!f0l#8b5N(D}y=n6K^0+}lr zJQ#q3bdZVr@p_miZb;j~QVGx)zz>G;fcjsjPiwT7dM*_{B|uSuE)>8lh(LIPT(N$* zxyF$zq3Ri=l6A3iujMJFbD4Gg5Qdx2o zO#w1v1fK&A)~7HnkxpHlfq4ccnY4h{Wnso%xMB_AMyF ztBsmue>hcIGGTX?M24BzAnH{74P&341nYrUXFZSprOW{Puqlr7hzdhHVSFStks=q#RxZVYNcU4yeCDWqOM9dz^vaD0q+il)bn0f~V#wFWI-mSLq zOPMzeXTu$L(zig~An+jZ_Ilm74HS1^6*5$f!cr<~A^|>h^G4rJL^KGchtL6jo`UL9 z-Qi$g`0+zh6Y>&u23;VPJ19-4i(3ZJtpqhC5xc1oPJqz_j)JpCN5N#FC?P-;`Jn3H zDJ!X7yT)JpH8{8|XcJ)OU6%EW-6n-tLFXO{?I;bUg{?xaWJ%tHK)4upv>Q|Gwajonm-}Z%TipcFfGs3p zqFjZA+w-MG0R$m(>36eA@U!3nJMjeVwQ5MS=T7C8q>3aBI=<&AYGQLuFsPCl=Zl?U z?d=DFsZdZStggML46URy^;f$Tk5g9JxA-k14o26)csH4lWmA?4KircZFT)8>B+q+ZkqQ zY}ZFe|71XT-6@rdluG5bcGwZ=d`K_I^p+kq_m>Y+8<=GwAoW61N0zL>yXT2U^F#sMk+nfV>y#vT=$&~qLt+xishfTZ(ci_Jv0Ul zU~xJfl&R`ZUPuQO`ZbBT#hbtwf7XCUuRgOx{jkaK|1!2Rjjq|=8K;1Q8Ni=E(Iy=s z4z(UK7FJ5AV3Hakz()o#JREfm1xOK$r@&hc=`Ywj+YLYjfC9{PQwFH;i}gU?g7Z2Z z5{>~RI8uNm!Y$pq1z8URpBBPqOR*UzmV{uEZkRVrf!TTUevab|Vj*fBBl{%1@BPqk zDbAzq6w^qF?WnT;(nV?NG`jkRL^Om|K(EHIK_DyU`c?ORQcicdz+9es&BhdK972Df^{T6}_6$ z`+XRH?3a)dKa(2B_%Ds6QDQS(XNwQqD31&5G9bSw#Yrqu8FyWany8T}^{HfMh#K=W z+~?ADg%r3R${>&~QAv-Q{7Sm?U@@VCB~-ct0<<4?d}$T(0a}Fv>_OgOa|61ofEf@% za(tl&ErLdqM*Q#nYf^zA9!b=fYUr`4(%<9|dwHuhO(NKWS7!8>RZ>uuTqNk}hke?y zqLS1)9@1S}sdGse6}}3+as1cPE_V`g6$BK7DmM++H1*tUE_N}RGiV9zOykU&Vcvdt zRO@-$%n{b*zeZBVw&MSlYV-HUxE>HM5;Ye{&9UkW_6=*5U}paf8p7Y1-8(c**a}wG zI1NYoKb4w#R)4ni82$od41EATf8TG>yHS5RQcl5u;I6Y=)dq1A+&vUe9EC8Qr6$VO)^}iT&32e^Z zFD6b}8467w07t7rdFLz+g(=`}H#4ign7kk<`jvh?;pxN4-*_MbMw(UX!sYaqXUwxW zzB-i$;%W_Qb3qF29T;abqSDj{hJNGc;``6S&)rufbLcrEV<-+?nH~U61cQn2Z1Fvyc7=^$nTQ7^#gU zh7$%1cxdJ`A0-&4*TH|BAd_6N?R+I!;|VF6qQ(|8Ud zQLSS^BI58@$CW#8JmM<+h!mp^+KJUgmf6~?x-m$)8QQ6DNI9o#;L122pT3=93iLUE z@afY|wb3gg3e~C!=>9!jETn}ZZ7{fOaY@}xr?reXz^zS(>2M7O3TIE3T6w$psc!}R zX%oD(fjJ9Q#l)-Xl(UvOmv^GbM-x&rSr{B9O^0}k6@+uI&)E!UcvIV}^-OwuJWo3e zaTb!4{X-g;`Hr4Pmson98nqif=WB^VvF{l|*f)7E3r1&+VQ8+>2Ok+6PEKGyhxk0y z;HK=3V)OPxS^Ka=ydVjYof12Oo=kfpnv5Bx*>a9jK)MXq{sI2oB#sDH?8UP*K17Mo zh505L_YSAN6AgmD`kS~Av7Tx~nxAQwwIGZNrhTdt&npdk z0`mjscPEDKM=q(~1d0X_IwTIUHUspsZozWtddYxL4|1JG70i^2y<)vPk`MCbO6KXw z!bMJ6yg1^4H%DjU4OYcMk_i&D8GPP@X$13{I^# zvIZOeuci&Rx_`eT`?5*TSw7s9oM-ty21|%8&FZIK)!SDXOuLllhf9S9yuNW(n5Qnt z9k|Dzf=SggK!>|}lyWbW+SolPNkx)2=wzO^jt@sk5DMZk+uk>P!wsS)94}<$+U4rp zdJvM5!8=oy1nFdlt{~xyNhd2-0~YgpT63@v9c`vB!KHty1a9!~Ac?t><%*1Mp4X@m zDWqz6kQu{cjxXl$Q$`k}Nb7W{3pMKf66j(eg({9a2qdU?pgc~jgDyZjeIo~csu4BJL; z^w$dD`)8iZ)r6szxter}BRBVp2~=QZZpv%JWm}Oq5akEstDUw)2SI2$zS%Wx2GkMi z#keg=zuO)*%!n}I+E3RZ`E271#@zJPF%%_ikmBk1t-BJUZo@e@Qhe`x$8jeP!sv9^ z9JH1+h;{G?e$Iqf`0qxNJFKxn+=vConaah@8vI}e0pEu(0T_1rSyC?rehUwC{M&wi zQkRhE#e|(!_J`AZBp*km!i$D*8yt>IHY&w5uoa|2lD-^If_cHvR6$#e4=&exjRC*3 z2fN@P7146=vwrI%2AK@pF7Er~yyHXs_qTSjIL69l>26uXS0qg={=84RLp6qzWeJ54 zoEb^9BCS#0^){EMHpVR>q883uTsMi^HAL#0h$|<<`DWPZL8OeM;nApze~;`@7c*Ir zUrfxQ+@tCt@RK+pNR_gB$J-TVa!i<&N$`pS_Ry&*hG-;B2(_AQyZ2*0oD)Pb;$P{AZN(0K&p11!n+WxJz){@gj!JM=j)1baqD&Q! zrX&_tARjGp>mgI8>CADT1OIPCswDvgy($jhWu4<$_)2TQC{=4xASMZGD2ADHXeeIm z8pCqr;M^SEmr5B=KLbf>LHR_oFKOy$2_>{&Db}%Jl^?0f3TZ9HYVi5E#p2`fJg8xT z)s!_GbWQ)w^nf<(AWy@=^*jnx952)#wZTWFHOFdt!Ub@q2Avcz;a##~AP^8#7iLw+=o8pRi}B7{9GS z$qq|xZ&JRv5e%{@5aG+8VufVdsr+Q_i zwvs)%0vuyOkFcdfhZKXEDq;RD@jrI>$8c*TQ46EO86Ucus-poyU2`1jo(IhU39tiX zmygj(BFJ{F{e_U#au~;0%zYUc^Mqgc$YgYLJIWWFIj7^D5p#bFCq2STX0Mme8zf5V zr;3xTI9`jaU%^I#g@L{CwN%Evwri0!HUs8Z2w})P1DXJcy42yE}d;c#_?uend<3*V#QyW@tZu68YdNany~KU83Nb?#^xD_AH)psXYmI- zg-*~KjSRk3+sHjtATl-^KH)JsmfSo@?KLnFNBmCgJOywL0lcScbq@(Bu7Hp?TC_)* z;mL>#ZV%qxUO7^xB;qE=)k=B7_!zJa2#lj;;U^#~jdE+;wXoboqZKQ2GEB$Dl&8W# zdieNZ#6%}-aO5b#SAe;@LfO&Q0H0Gik-R`C01k;anac67CC`KthnvnNp~_@V53Y^2 z&l;=6zdC+&E>?iE1&v8v$ZdGC-hd{5mgZAB)J@dVG#pC8LBGWn zij53>8F`98*vgW7u24i}G{>BUYlW~JCXwa#578>}Ou;W*)5MWo$I{COK5tMB_|?iW z=cFoyVC0AcM+0`M>JA`naaf zvyHlnt#3`OTiL1-E3UrPx3aYpE0Y|%&e3f@jm}vuAvu1mABq?)Mlmcoe!P}etFhW@ zI|`|_69tolEf5HXSQX;OENTd$L=wIf$pHe$A&}(6_j-c#U4PsD$R9>N!a2{m@9Vzq z>%MOCLCLiwSmJwRL$1=jL-YOTurx#4za))phdb*u_a?+hI$uHp$DL*ha1$?S$m4Tk z8thR9SWa0L0lB|Gh?*WJ_<(v8{z{8;@^dYo{P0YH)LN;ph(5>n>9BiKAlETR*Ae+1 z@(a2984>Jtb_zlX`B)De9#h?(p5)+W%B?HTRGLoqNxnV%gvi+#V87>zX1kJpT_@^- z3pL#Yg6<|7v!&N$f9Xk2w)fA(aM)0R0%9^Wyx7l6pi)tN&CgvmjMJ!acRE@ zZDx!gh9zG8I4=DXZyPX#I|cL&7Sl+|K8(9~^sBl+(K5AAfg&m(?8>90vAA}9J8_h0 z9)`cVhlaoYk;cQD)v?++YAueJk6^`T_zxw*J|pTUp@7PrX0-aa%s(8Ls{f zj~y2wf@m&{*6zVu@+Zc%^Na=M7bxU6{Wk|+Ew*_%YZ@c)C(-ADG4W5vmOl>=mW#yS1VNJ@6F{p2j9 zUI?$SUX17lR*zq$fjK_Dxc;fgSI%D5VaaY2lF4t4zu^@moXbxAJzT&aaTlnKr9AgV zCJq^d%l*<%y&pKPa8?rd`aL10HiPNl{qk3^$DLN3bAJ@qZ)!FWDID#|*~MM&$ph>1 z8Ye1MuRCLY&C^TuS~o3Sp1;+Q*!SF@9v%B2YM1X1m2Vkl4ds=O_ZFE#Pw1+wt}yIF zR6d(i@^TTy1=70(+F0}WH{)%C3{A523cOPHo^QKNe)4V5QxK7V&n*AvO2p?WBPhsG zmFQ26xu4|$^Pga<5Th&CCKB6`BZ{!i!7~TpNVwPuV7q3m;d4w)GnSQ~jWlXR zNK5|I9Sc1C=FBiK-+Qrsr}=I*D*RRw)sHr1@cx2>mPirDK)F_eqW3b@49zwg??nR# zwuUtcXmWQ@UqdDm=K*;>?^r6$15Eo~aXWW%$zYOE)|Fd_g9{;-YbH6111c=x!KO5e z5Gc=AoSf~n&?iE0qT#I)LARfMD?610$?xOq*bqrp86&3;c!1j~$=z{GI=IJo9vv;X z5;_Wzt0elaE?;d`BA=o7fw#B$uD{HV1@lT4=fV8!CH;UNyGuu|{LV4hxF$0u?r>-* zXLxobxK7@g&hRddXwFe?{?4R3#L&W|aCBsfJrWUKNO77@kahN;ySMizETx>o&5a8- z-GGsDlaptjrX#;F(#u@%3*1)QurB^pW&Lu&K=(aftRI+X5sE#hL?0)9z3nt7G6578 zYX|oCD*ZaPKj3ny&m!BM4tzAEY8|65z{AAiLEQh`eXjZiw|r6h%9!@0*qPkt)!lJE znZ07SZeXSWVSI`-e+9gkRpErN?X>lRr!yMSh<*JJhvK`s_1yUVvi)Lk%EMKjr7%c$ zqWWdDYzxaPLoF~!+gQDG}O2e_9YwJZUu8dWE*Ga8i@o0I5S+I8$B z$WHrZ$l0pv>QbX1-?|VnT1nCQAgxbx4KAmVYPiMJHWqsVC^5E0mu5Q)_D z-_Cd}XDa-42Uj$AJeZeh44(Oiyu3}?L=uPFzs$k2tbF}brh&OclOxVY+%n%v<^!UE zi}%B^{4xgy;p8qUsL^H466^rjXuZLd`n?A&aG&;h-p^NT$MUD{B-ih;I~Yh#I;e#~ zp3S1#RPG9G^mNfuKZ^slrG#woDDqoo+6!vcyibiz_Zop}!ocUu4?lOBP#0fBaC%6N24De0h&MQ2zgMMpKu zje%-PQi2~4->15^|Cbc*tIz86r{t9wEb6;oT-q}f6>Lm9Xegx9pHo!GWI7d0ac-5o zkl12cK-&e;VDQFV?&T7V<(+45@2bIIjmI)+N%3{5DPnhU=}6XBy-a@Tw``R?o$cjo zmL`;i&m;Js3%c23GWg?uwmJ%78cjJZEjgE`$r$Yh-XTy!F>&{t=wOYxBQ|#>)H^rn z6}to4LR1L>t<QlD2p{;%ftH{K{gDpwP@TsqD>xW>8m0<;zopiXdGdU7LOwErCI2mx$f zyAXpB?QR?Vj^ov*N3fUAM3C6&W}qRV)y>gglk%{aXuKX-Xo_V~rz3MvDuddes(~>m z^Y?6fW3SDidf@c1GKTi=!rwP=O`;VZH?6(u$m8EJY5VHgz;4%PRZUP>U4K1Et)@E*P=5`F4ZAkGA zaK%V7l0IgM4X@qzzVJVbaxT+3x}Lz8>O91y^xqEjbR7S(RNb=tK9e7k z#`+e|=hWB$yY*N3c2raVI#!BNBg=Ez{_orGi*G z=mf5;u&=8D?@fm&*Dz9g-4ch*t)z*Py7v>WUD<05MRG>W^h@*LIX~0wRaXM1REY2C zyL8rV0hQSnnkmqF`Hx$5EK0^d^Q7;elHN}h>VS@XFwCYT=jJ3$V?)xQ)AHo(y4;V7 zxT;rq`NEJIRw7syXAbZd+V}0$%$ZO!4QmtR$xh=os!wD`@0aEMpRad(*e~R&l-Jgy z&Ho_kNex$^@;vr?NH|hdT`3s~uqR>+yx|8e4kfdqQzh(R*h>2ggZ`8VgvyX7YG^>_ zyrhRkJ3D^;w478F)!-`x9P%z$uzW)6PetO7dIN0iO0@FK`pqvoG{SrC;>wU5}m%_avKFE=fE|Cba7Fl3RC+f?|{#1|0W0!<>`HD#BzP zUNp`xj7~gdCI#3_ElQA{IO!O!9|9H6ec!4$!}(Is}T?}o{+jJ`i5v| zh5|=lGOUlhvJhDCPoD3_xOe8K5RPN|D$+6C;m7irU|_pacK2t7c3H(n`L&Y}dMs@Wo~AZVqpEH)Zr& z2Pcy{#lIaSkwrZLW#SEwX#fDwo)zI{MQ;aB+chQJ31ti=4gAq#jZuV>-bCn&l(~Cb zrxc9|EwZ}w+n3*QjJwYn(osuAW2~Sby3gfY9h2VQzAEQt`T~VNBv4K?#kMrs3Z`u4 zVk&sp;2=a;-5R2M2v%y|>BVdfdI;45I<|(6A%6czWg0i}Sws);O^qs%!UVqQ#v5aA z){o)uw(0Z7IDEC?ITm_Jg+yA-4kTLPQ)s%Hn^n#r6G7d^S_gL~;f8dNYZ7Q7Qi?uP@{TDa8)k01 zs$9321_q<0h^fRI&-v?|dip~l5@N%)(B2186A7Ru_w=Ky{w6(t#@Z|0dZRK|i9y2S zKg+6rWVEM%B|P@7?o!I zwPpxiz5=f;#ZmZU?$fBA7-834T#E=x)HLD4^hDd>ywK8-#&Do{7Z7U!#id6 zA*DYjXaXfnUR`^2WM%h~a~HDVxUA2bJE-n;^zc`mOUcCNzF_ZQvW$x2zL^uB1-*@T zttCymiJkM6YbV2+VDhwjvUi=*@A1VVeze=5`S2|uv?`9`fhR;uL-oifW5QN5YSvSQ zchy&r`656J5&)pBqUe+h2O}d5Yv zaTsAb7W)BFGe86Xl_naSGl}9z5o1cgLq{T*$h#G#vbZ-wJ(fAbPc!vQrODi4l@z)P z+nv8;YMh}YW^%+g`mn5@{IKF2XrkR)@+vf48v&5S)7m3aGub^`}Uuy>;MOSoCqn%B`(FSd^;%- zS}_^9INo@ZInB7y%v=(y##%P+Q`yIsJrDjLdGsZ#^>K+j(^+Fo<0_5mX<7+%9DxX7 zU7Z;Tcd7mJ0EBjkdubKSI~qm#3TZ7>523tRyD6HT5ND+OY6M*<+3RQf8imo_ z<%@!F))l2XbHq7!txRD2`!z|m`zDl5K&LjBKDBcqKMz6=;sLdn*{+%G_S}V` zsOa(9W_cF0`P zQqLOUUdnT1yK#BZXh9SChszH;L6=Tc`iXzJs^j7K#ltOIS1)N65isW2mrm#F_$ou# z!*vQTn{i!v z;XAFhg^Bh4EYwlwIJRr1aq*J#GN^2(X$Fh6mK}#i)y4bStg*SvQuJ@F>QB|LM7~qA z@`Bve!+DY3rid$yzm(`DsD%wD^L|C4^TnS|=b&e>x-a`Rl;kt4o@Z%0E%qe@pp(Nk zTH{Hcdp{j2rkPoIUQ+LM%O*)X0b?xR#*OU7f;kkWmgeeE%6 zYE;w~T>JO1SI(in!#9zGMPdWLx0~^ZkOluD%!Z6QJn?=<&0ei$Tg>YY%@n4((&YDU zs8QGp=W_c#pRp%P#4iZm_=&fmB$#;TZQqbx*r@TD3b&~|_X4{7)(#wq_pBA0r^=eA zzVpnU4TxJi(a;TRxDhJ?SKfp}=fa|y0;6qdRJLp?PbHNGK*mqVu{rPwlN}KUXz|JZ zNgz(v(li{y({2euQscx}j+}6B`@E_qvX19w`JGqsr%(}V v3c`g()KP>~AipzG-8N^F)d$l^vlH;)-^Mx;{I>gUC;H{&I|;U69(?zIxXf52 literal 0 HcmV?d00001 diff --git a/setup/import/images/PROD001-3.jpg b/setup/import/images/PROD001-3.jpg new file mode 100644 index 0000000000000000000000000000000000000000..89f69a766935aed31b7e15e97a055f392b1da8e8 GIT binary patch literal 102141 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

    G)|Jf|PnBi#` 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%0Alm$b}X3wWJ4eYsRqtf?6bj+vr zybCS(mk`l6u!c!$l)gPIHoZk=AG&D{(!o@V)B%EY3;P575>|%6gR5rI4Kz2-6|{h-bbBm@I#`ul@oQ zrkLp6#7}r^|NCLuLj}W5oFaGv*{{O(&3kD~{8Y?Df*nEii@Yjoq|Gc^6 zkDI^OA}?8LX0L-jgZvo!{qS2za;yi!HHH+voyx?&&l(>FB0dawH#Kg=UzbDw;pL+L z8VTBeWF-9ipj8Jv-B+X6e4S$j*Nq#2)F5I67HLwuC{0w1b`cfCUM{pzlUK^4uY#UW z2j~y1#0{_#=JdbKnQp6=Dx1J>LEzbm__H(YRR3xUxe)|>C`>eL^bpyFzfM%lgn2NA z7E4dKZ2x=mEN7g{^BmOcq@u!R1>?UJ8M2mG^^ZFFUi^IYHbLyYG;Vr~54OGU*GJEP z#PX7pAW>b?+ek- z`|XoYpS8>w6HRZ0Lr+^{n#;9}L)Ix%PqhsYM6rm-x@OT4TH0~@z(y8wVTkD{W08(rs;1NyR0kE33i;j$*X1o=u#lWCX zRrASYmf z5e$dqky|~}B0XI7ZpoVA_r4lse>I{tivi+ZxfY~qmSVgjImJICnMVEnr|gkjwjt73 z*NmaO?>P3f{6#F6$LY&HUz&{xz$kJUo%ZxYQB{@F74oYV9D8z?pt)Z;pgn1sfxe_I zy}RgQPr%ZG3)?J39*$ck|D@6^2_Y`}@Zf$)Vn3_9;O(A@n>^0`8;Cd7{G5p$ z0x6=%^9oX){ps!A87tf_2tFTT))3>@^NJt*ag^lWIivsmS>V4TrI1{DTx%e6I7C>q zP$BPdm*RwsmZOn!zrWI}|KoPm&lhpUB$8Byo%kj;S>zo*WLoI=7j=x=qzxREdftsWi1Ol^{dA62#Ifl+-TTeOjGvks+GAnDq?R z5a=KM^U}Sa$g?6@>;Z(UfgB1gRFH)cD>(Y{2e9hEh(>7XAJ>kjeRf~EJzvh9jW%P} z1|I)AV{ZeI)hE9YS4HUpYkL8VmO~etuo%j8234=_Nct84hGf!Zn2nOwnog2I+qKX1 zDr4_V@^e~yCa8hIntO^<7YH6|dpsh8jkLbKO1)R;pt|W771#8Iz&BGO6B%H2CNYHD zMd{&ZZro@4e|op^HnI{1;Ufx+(WZhMeyM||N-%hXS0^edd>Pp#x5;F^Xg8tf4e~h- z8(5|8a*~RQ*LBcj@4~B5k<8IB$zHx)l%>J1=NpDV+nfr6nSv&Q@x(63Z!(?X^gUce zA=eGu_cy1%?&kK(A9_xEJP%s@2C@XA4n{|gUigDKwQEJ`sxs#og92dvmSkTG zq6DT2%8m~=3<6>hL;svY>jU(~Rf=9=XacK8tII{AGejC% z^V?7r%2U|@v8T8cS%Db+tI@7us7}IH`9DrNwJ;B)lo0FP;xn~!9nS(_(zVeed}C~t zT%iBDqV#vU(!zKL;%Q%n`;-z@ZoS!86qa}KWJ6RL_Tai zA3ee@l-j#-a+#$>1zJm2nfSVEe*WR3L z0!vh_uc8gWCHYdh-*K|mWB|MyDN@)kuMb#E(U3`635(5_3M{x_gT5NYaqujKL9LNU zPzQb!k?X%O@;3ugtjB-CG-+hk$y*)`jR^!LDv$V_Qz~&>;2^Q(BUUR{skxI|tJaV^ zR4?!4=JsOWfcV-`oNLl37vpAk`o#V+YyHS9gF}h3Jfl;V3Hp%YX_kg-L=oN_tfp4P z4W#%NI#{2@qjQF;yKt#lh(Ofe{p`FfWqpVoeNe~R9N4jjv6v|4^Jiv`x2wJ~p2YH< zK`dJ{gvh{~UetNSWl$9p+(_FjvjXz zhyEs(FEa^DkdSP7B0WQ#&-Lcm#Z8uu@sa@p1=o8L&%fQCiR1#0-Hr8jOM54z*O@rI zFL{Yft_K`R@qus?KCA=W4667s23EV53?6>SR%5Vt1|AO%2W*AFYt+9mAnbj=+eBa@ z&^K)gZWL&O27+4BWq`F;je@F}D1lz*Tx#hf@G$Vj@FhRi1i`MP!2d(49VcK*THM;UgncV6H%B15-Ajm5nrmQR<^usA<{ z26t-38j}i8(+VZ1$q5hWVS{m1C$-XBEGeQwnz3Ce4BXAR=Y}34Kwzv2!h<(-GV% zj5WP%Xg={N2(z-jO2H8ZjBGwc5Ku93D9qK|!utTDREAk$hj}jGJl7W^96@g7m9fcV3Iz_RNzp3wHi| zlf-UM9BFv1;}v%zqO-?pu{&1bPFF|37>b{+W>UU{+n(~=RwSR!TPg9{^W%-`I~K)MD& zJ}p(uppZ9A3QL5u85yd>jmYP0i&Bq$Jq-^dK&fRDtBPj!}-FKwLe5>o+%f6=nEz`d+2pL zr@RXhI&Pn7@o33j0$H87h)!l6uF4IQZAtwQn?HD=9oqsaH3OrTO?#Kq8z?bQG((iY zanx!FldX~TVz0&OD>U&A)s=&@k*0^$?RvzaejIk-VVQ+rn3Hb;gD7T#&peOvPN&Lu zHD}(>8U){!O9m{3H;MgtS-SA&?^^qF1SxIl$uB=STp^YR)6I>^~Sqbu>3T7%}nXQn(g|Dm#@1az?P|{||*e zKn-%D<{z~QTySU_ktu}aD82z5@C}Y{Yf=kq08fzm)%i#(RH)t&UW8T(yQpM*(;^lb zhM$3mVxVndkb5x(U0lfaRfJY(xk60G1WQ7F)~tsRMb)*HYW9&X1Lbn{n;##_QNnG}SnDfBd%wpPRe zxJYHaz^X7HIc7r@+gwwvedx#UO?d=4*tp-9*P-S-m!1RNNlt00I zC#dTD)qmiXLR;QUd?oL(qMax97WDz`0ME4HS}^{!B4HfzyjUv}N44{mygjhV2qw*u#!7*5}2uj?{_Q z9h!KjJG==9$GHJjj??io4JUPld(-N|JJuiUcb|Xi?7UfhYlDexJt=WaEnSeWKCbq; zzEUDQ16A4_q>&8AS1;yenU1K`qZKb6&X4)Hb0s&A?G->tmOXbuDkXW>CXn=@x9Bk^ zC=t9%X9B)-26Z8ATzs#17an{w>G~Auxd$cbDOs+|<3_FQsaQ1wdHzA{>qJw(xfd(*vs>0|e2aso?_ zfX3y7+>fdrr6&xi@ik{m5137T5#WmM$Z45xN+#x-p1WjVDxAA#skaWK$Mccfy&sKQ zfC+6@?7I3QYde4c&fT4ummFnQT zvR^i@vaJM;=1}KRRrM`<`$YGWq=exrq7ywQ`(B0rp2M`3>hq>SE~lMNvB1rCRUJ0) z!)GW@un7hn0dK$w6pB~QV{^z!r(tM6Gl;c1iAAn~{pN0{ z+U>=|Ld9taV;I+mKn|hr3Kymc$O;)6Yo{I(vZf$Qun9SSOrbLhjCU4Yv_l>b8|!~> z|O8r3krAiToWz=No7*LbPO?97010z&Fhqc5t^4``KKbRKc9U>l+> z47DQE$>1)(G?r`JHw;eRQ>nYii}{dOcjQEwk@X0P7=_h}Aw2+BmtV|6!9fLz?y4Af zk3r+`%Ja=a8D(I&7P$Z>DQH>5gxe=L#uIYlC}Gl)?C7dz(1eV{AMT&|_Tg=Lj6zkQ zF3Aw#5U=BEkT1g_5ATR5k6NK2bmE5YW!z9F^Zd9$Yr_RFfz`A0bx>^^GIWAR;g1-6 zuVFKRjQfaCfhLjz{eWskeR6l1{YLjiRwq)^&)xP^`t4y~tuXCfAK+@Mq1)7{`56aY z7fTDC0hL&>PxkWiF5C7`G&XgcWAl{WvYktFt2Zi#1t7nkQ%w%R9GdNG#lgOhMbkth z)Z3BwAP46f4$Ce#QZL_vmMU6wahz&(lI7ehujL!OJ4)u3H1rUy3>8FX%|)A#*sgBH zif%&6-dQaN8fV=+Hs{*?!@~*Hy>HjV7l48fA`6i$g+p^f z*NdZdZM|x;A~MO^5dG=3_@m4&e^A9=z>Q}4!C-fg zVOiJGtN$=gnfo_c_m>gUObAS=Qk@r9bYA)>-P77WB011o4ac!WDa7+satT}ScXYAZ zu%4uI1q^2r*=zbiSx;*S&t4=L$Om3_eDaM|@<_{{DmJQ-DnoU9)<(O=dk>d~)L<88 zM_2e%7&dqi^;f%xwHH-nwmH27e;4i=_JwvmIPUth?LRG6lLZ|SU2Eb>SQvD#b`a*@@^3xHh z5>)d9R-`p|vgn%z!#cPP@VRta70K6sk3&?y0dn!&9jbC)qof3;x=vScmAPX~x`W^G zz3ZixDg+`k4D3byO;Eq{lZ2d`f*5aPl%)3;hs4TcZOptXuNzbC_ivg%Y$RET2@JV7 z(?clH##y6`qkUu6j*J32%GcXqY zDkGy6l^@9W&B`gmnl;!$w12BjRXmmzPVUmyjZS->IF;M73bX^PF4`J9PB4-yr{Kg? zg(OWV7=;?Mwn2u^&<-YM=Q`sKe5XC%Sm=cuxQac6T>BT&iQ1|UYEMz7OQDh7ttbOa zij5FUNWlvZ>u4c9p0%O`AvGYwa2EX>rPw91g!8cW*&idbKS>%D3_8aEmwT%N&{9h5 z8dP%u${x@WI}t~{VB)Ib+J6=i6Ei13aNV%(Hu z{EsKfa1q--#;yO{h7K8B-?^}6D$u=&S@A@NB6W9$Xc`DfqQMNu+WR@o9x}rr5R?K7 zJ6RFwNA3Y6YT6E2`w;vEKer(uett%^AfZt)yNW#%xM)BL!7p4#`zBn4}A#Tu!`uTQ=44kPN>na+U4hM3DCXu zlL&Z(EL`0jYaUTFk3Cg>#VUc7)fuG+(CVYrr3rQ%{jOKwyOCL0YdGy-sG`a7d2Yl+ zIui{msH|1E9kY0B20ze5+EsE#K0V0yP`iPT55dc8Bx}%1{OMFaqD`=5;N_=@Gt>@T zwM2p2X#xKBts05^Gak%U?JCNEg@ zVa$aG7qBw}J%;Dbp@ub)O$Lcr{;hFzcF;0_l;h)-@mR=@1xWMV6>001d*ki#0uDh6 zyU?ZTK+X-j3mG5gG(U4BTm+mhSRFbWL)-0NoAC;Y>x;02V6u~Oj}MfYx?>{DR=D4T z@a;Xq1++qdEfZShOe&wXWt*++&he!??7Oh;Ta0im68*^PTG{eME0M*D3hxQuW?1Au zc?c=5&k)#Q*z;WF)wwpk6CRmXE*_JO@p#(jfZJ$KRLwtLrant)MM?S_2IRAZrDldz z^+{164Aj<{VoB$Crhbb$JuwaVLc=FnwrzVarqKZcIep{FX97uQLIu)I2GafU(7IXR z`m)LD3?26pp%;lx|DaM>GSgPNF>DFKD9SUnVwzpAywX14hSKuw?6D)3lr2B|JG1s2 zak)f}m8v%to*l)L@A@fde(1+t>36oixl>qXuD`JxCtHw6db7fbZ;&IOMd_x0wHGE+kK z)HWS3mO&a9d8y;mC<2VxFMoalC9vcbdJ?)LtowByWDOD&=u=&J z_jT&6rMM5#Lq`zUv{#mx@`eoja9^a<;}1A>>2IvH9r}z(U=apGsEc)PeKUIOH$(Tg}5`&v>xS^zw!cqCS zLS7UmKL)b*(978>7Q!aQx{vI;G*qhBc3#xJ~tqjNUR649l(ak*$dDeQwqV~AI{qj!ssS5ue^t2}*FsIM|HqhgP=W^L7XZ$5e*en1GF%}47$U@b)XAmhvl=CQ%m`wTyypiBd- zXA1Fek&Q;;S$SO}V*pBlJv3cF0pd;ll4+a{kEuKv_0 zw|Mn9oZM3jAX%FN9o%Jihgx)f2y2az|$Z5YBUEIbCE+l z`YTR~NZWQpxLYLv$d$Hb7x+gmI}0itgY+qwB)u5sdBSJdWLZe z)Y431h}>v!kY9FDsFKhOOP`@s^MmA7%Wc@MZ@K!rn0gSHN41zwheI%8l1*Vfzhn&% z|LLXN$ww*JXE569RO;p>GY?gbdC+T}86?&6Ydw=E;<2M@ZoCK3m6(ETtm30_vmsyI zWC%yue&$wn$TKWC3L}tdl?)o^p-O(?TFWJt#zu=mrFJL6`zM^H9BrFRQVt5*?H*l{r!o|S7Q-M+45}HIx}#Fqa_Arj>CZ> zt$kGJ6%!?KEOtyO&f1z1K7HN?qu-Wo`UXo#4}I>7L@RCafQC7DUr!dtc*kY;!gj=Z z%y^VL90IH_er-0NYn_?4YviC^KE&{?YhAt?Jx-r2O4yWfxR50U^FZz&94Nbzn7&0m z!U@I;eTIf4Ee87m&zHD%s2D`I-Wl!lkEC}ym6)z2)b z@}wpH>k&SKD5~nJNF|X~k?(UeINv14j-G+CAw|qQG0ECz=cIzEgvXgpS#2f^y`PDP4lnwV7pg8hw@u+63qQuf72Hptc;*8o<8!$l20l2&TyJX zH&QDWS1mSWCzTQ@j-H$lW0S|d6P-+Jt38u%&rjK%PF}PZ4H@T##H?5hm~<9hb|71y zYw#GTxY^ml)bD9BNsq@4`(j-E9^#nAG53dU|7mZ-{74~7^WmN}@?k5Og&!anfEEOB zsk7HvL&6B4-kb6Gt}pf14`s@3%2wsWcElC50N`!FE;!D=8e9G-!F2KwVcKX&D|h`Qz1`yI*LYuM=A%2Ln*ZGnn=d#M#L$TXW7BX6Z@?Yog&0h z229o6K=8M()v~B^#t9r{&iFIu_SY9UzCXb(6cn~tq+KUE6#l^%>P`Irhxh^+1jqkD zdVsql(HJPAP<*k@*jG`(DK&=hyXO$rwd$j0 zp1elXXG5uiW$Pm;DpZ3NO}~5GS))asfG35_Xhoq?Tblcq|4@ermgq`a0t1Tz^PS6!u|>SC z!$(cca@_vbWN?AbAF^35D+aBF8UQ(Z9Pdn|JR^2`V)Gd=+2^D6HaasV1oy))fSgBk z@l>AGNNtbAe_>Ep+~V-C+V9MmUf!G5m(7O`)*#N?rmKGBI3f4mPtCE}fuV-GF(PYDW30|bXjD!yWyO70ym;*2=6D8tY$h67hQXuOvnR7tX4-zE0h zRPYbm(|5|JA2qgvspdqYT?V-;d?i7|`7v~Vdlk46FdTrNb|0#hjgKd_8#<9+;Hkqb zj!z9p898!BZq1?jhm)Os51z3ZK_I0(gsgg;y&$nke7-aDNO1~_tZ$MBu3sk$Q%>J- zZ}8`QTSV1mSfynhJuY7|b_CFOolIB-lCnk6@$%HRH=Rh`?iUXUg&urPPL7CHz&Rm0X|av|gBWQmLjiEJ@`BuMpi*^aUEVCNg`O3m_h$;jpVCo*c`TcE@} zzF^Fyo2D>QT+kBbPRJDznnq0UFX^!-Vx%tyEEUzgfsAjbwz5I32lsh$voAZ{2^_lk@7LuSq9p z)}c>8yO7nvVhz&T{|c*!!8PG|#s6-A9<!~WhfD7ec`K7CD>8iQo(sZ8KC;;9(x!0 zVz5J6@Fpa3>-Zh{mcc3SuV%Z2!?mLON5$?>H)}=(Q-s1M=tf6S1fGf=E*G z`D8L2cn$sb{pG`maBZFgj6c&V-hy=>Hj}T9_?A>IFrQ`n@XP)BTV+dj9-hNZ?%U`P zy%R0V_+eT2-o6(rmN%wdu4oKhxLs@bt$=+q&*5lI+n0!hBWL8n@rE&EZIP)?M%Enh z^Vs|{)iuV`;A?NPAwEJGEPYnKBC;wyZuQzMtBP}_nL7qA?rk497`VvE{KQO+M1WT( zKVyZ!$xS6S!fppK+2GF8Kd7?>*I1s0?b9)3d+uDaBsFCIh6r}fh6?^;^w%Sb+Z?vlTjvy()tDF-xOZhn<{uaOUvk*uFL!l z5Ukrmau4ZP;;U}Im@iI2-IAvT&<316Kvum?xhme&^phb*CXor&&z!nk)$`1LdF7{P zZWe{!Z{{^+Cfy#!>wG&ttrab>Sbgh2v@D3-8^lVv`21AbbJcC=cO9DQYY5uo!0O^l zf0sRz*Q_g>F0XmIAJtJ*CGl9|7wgh6As_k$JWHO|!jiv%RbjAE_}NxQ5E4zalE$GD z)2G$E;X`Rlihy6K3JQ`}|G4MpImFNOfh2j=Tzk9c)ju?oU^p3gD`$93lxlAm+l5r< zO}Fbx?!!kIcCo%OoAisaa9Cn!7C&-ymdy9@sYt>Y^4m-sJHr;RFGR&&B>Kq=A7R!uRm|OuiTd6E zl@<<0Z=l~la!AUfxgV-rnTmdl2H}>3O#P9+ygdDuYzeCu(J%*13*%g#jHJa_)p;eZ znsXk7pF*KfMWn^Ntr4mTTZ_yjP!Qu;KX!6;cIC>fPYxwqRfV1zrEs?oW~cUf1g_L# zM~KsSx(N)~6S@0CT0_<0jVeaaF0@&h&9mt6NjFu>rrby!f3`x^ih>}xzG@AL<(imj z!nKrZ(a(`)P}kl|C4Wy-#mK)Jc|7E?flKnSkp@k^`BL8rcaq;2%seu%^^?Jn`jW-Z z%#Zvejke_<)kU65nwRhf6tGLmI1h6QbLQLG9fV@SOrZzKnKYiCnU_;o6!#+U(zf7K z^+ZR11Fg`~?CoHzYR-?F{0b^p@yjK(+|t>xEbiQWafhC{B3b)YFcXmt&6qoSo*uu_ zWPbrK%&Wa5s$bnByyYKPu0-;a+w zb!j%qd*yFEZ?DJZu-*_UORi=l-g)?#sc9bP8sVm-mnN~o{&C(%q;uE@i=F=I#?E_kU@aS9jVf5 zp)7aB-#k;uU*yN*zeaxWV|@SK`GJEP%6#C|Mz9rd>EB6d{^_k=DNm=+u;~32o_ar( zyv74gKqptAJ5*gkauJ#f+!Nv;I(581_$UAUJQP}3WuzC#U;gGFPEZ^W=a9VLvRJ-+ z5bTK9u%3&N5~>*^sj{$vVKr&A8?+QJx&g)O zdBiVxThggmqFm?~V0ADbt^yGx!hl7WrtpNp)Zl+Nbp5?EL_8o91H2k5>7Zx$-wD== zIMz2ohSNgOh;#%xl$89&G_L?D;v@SfdfI-{dB)v+V}|9cT@vJz8Nm!92>?{j9{Wu@&k6H*S@RRjEjrIq7WXrE+c-6|W0V1Ih zIZ{};O_iH+khU-5-o<-M?M7*9L|={kC32>`Yx&i0mQ{CrGmv=3zPFlwB79xL+olg? zB(r4dMC5Agyky%^-t*r$ZBY{2^d+;g&KQHBSl-2(+h2bnr!DB_SgyJf?Z`&T=OMY5 zlKY-s%bM|<(D)rA@$TgEdZF3dgSY1&rMMMjPn^DA=e>K%?NaHzH7~|lcio3w&OQ+* z?@&i2HW)-dC+&(*TWn^jIklK3Uded?yU~-}b#flk=r^@|-w*Cd3c{;4VkuH1?3B*V zv&ATs9am$xH*X@ub4g}alNm)j)?qZeca*4s{QwDKU7aZE1H~t@CA^ZIMfrIoi|Qua zd15)QY<}IiV8iCL5g~wUlNRKyW{tkl^X%@qg&TbzSYfkroLw)b!CSUy!$woXn!Z<< zsN3fY<5ewJ5LE~v960X5M%()7RlzSMW&^C&4=>|3E_5v)kxd%;i|M%siC*dR+Ad*s zFP2+&wOP>#$yeVLHpj77UHnbpw~Q=XL{TZa4V279p#m+dYDhrvs9;YJ(DO!vF-+it z((3FgwjmvGnHt4|8~Y#aGR`n$V4HCM_kDlxB1+^q#|gJXxlFIy)dI|#2{H=^&ZWTd z2Dd+3Add~KQ&b2_rO z7lJxJkizSW>KT#k1;F*tU_#26x%X%{Wb?0y#syOeTpis2!nMV-7FXSh>H{yT()ZupuJ(jAVIUzEFr=bTW zWHp8--rusrcnq9s23p$+r8-^3CohJV779GUvC+8O_TBo%$yQ@TYy$oeuKuNd8_M41 zpC?fHz$Pj|3zZUAtF-;@voLNiPy6DU1KP>Z-kV|TTzqQAga=!^+@W5`OixTHAB2x* ztJ#M+cBwbdL`QG4Dm_$5WmikwuzrCOnA*cYp|ijLlFXtTP}4qhxUzwD;_SZT-^{N1 z_4G9UR8Hey+(*Weg}3S@XfIj3Hd>I=GxkThIBqjVw?3%rvFmk^{k|nn@fZAF&{eU# ze?fSj*^aJ2%z(YI8GLIa4J*BxJaywj;(`8-6jEP&EA!-gjfClE{o{*g?&hOWdhjyO zD@#lUwe@}Z&QB_$Z_3y~U2v|#!^uLFM5tyS_-M$hJ=Xxy6B})WV)h`V zmY)%D$wid6E)bd-;db$Nv_@ID;G5UE_c4Zd^tO|mW$$zD-A}Gv?Kauv5mxi=&<~>T z+n#PXvZ#|Dm|atwSZe2Io*BYB+R+-+mAhr_?9B&X9?p=)uIjpn5o=Aj+3t6*&0W;` zsq(VhPV;e^Tg6LWU;Pq>QITK530;N@3v1W6rz|X-;+bL?A9&V%e--5gvL1UbA@A|3 zyP6uII=a@*ry^zCc4L^aKtllJCK>h_JJ&(o8o|;(InA_XDAQJJ2+Vw1Hzd=%UW zW#DY_F(bkPd}2#pCEoBEfz7gS#KaKXRT^NcDB$mnWH};-t)#H149m#8V{eBNlJt=P zN>#qX3hrUWV6R-P78Oc^*XrYt$W<~$Z(_mWT&^Kuhy(8KE{tTjan>S-km_u;KTotE zR7FuIAbcNiQhre(_#KA=gxA40`m5E=iJ4ug)py~gKO%7d1%e252`6gaSis5G@_!+} z!u=uslm3>Q`WJev$TSdSL20z_X0qlBUNH4f`cq#95h~>^)QMb4zx=*(L>z>~1CAk| zS&?gK{ZJ;?`LZtvlxTVu2g@4)=sS?r%+Ax_296! zYqG;CA8lM|emHSM2!S=YDr~!&?5eQ8x%bZ1Id$PjEhvi?Su+=mCz>wX-JoOH)S7e& z2ay(&aGP#Iea78_E$wv?frk1cZ!y>r#~{#nCmR7r`0x@)yge6XUhr^fA-h<1!8wM} zztWv@maRT2G576x@Xj(ru-T#Qc1yHgdF-68+&Q|h>DkltbTh-#5j&}BA#}HIVhW+S$RX27{-|OfXQf3xm87|O0 zK?Gj*rQVe>?gEz^bJ878c-__HgFTCMgdfI)w7c5X?}F82152HR*V4#h`PIXb9xaVn z3;JZ$y_yp7qsODN^-;%FPzlg{wVQ3f{53nZbL~u>+FfRr{mo0**J+USsci`fD$=Ep>9r7{vxn=((v?Jbq^r708Z+K|VaAK-bvFmQ_)O8Qi|;Uv*evjH zJ(CpmS>7B)dmrHxb!r2Tz5@8kD+P|M! zppKN-jGLt3jXn^BX|ZbZ;49M?@YX(A)6aKLJIoC9pGoS|AQb0(lu7v6!8toVk8YQg zbv$U7q5Nv4ba5q{wliPnU0>F2cI{C(c>U8*cV3Q0jDLf@?R)*^(Uws{sDeR*QBN!l z*#`;Q;Om0DPCG8L+#tuZE2j$=&N5YiR22_?9|7!oLvaQqrGat@R;WNULUp3F|{UDfmaN4yybAfA14GwVZvH25M zC@LRi=bimSLrBN=drz%4E`P{(SY=oe3H!U2uz&Os^TMN}EN9Yox;8zXC?>kYs-A!l zn@EpWEjq&q59>>p4JseM{$Lf9npKD0B=SlLEGcFGxB0`_H{h7gH(|s)ZDcVGH3|Wj z?4w)uWb1)+^c9JuLRjoO$7D~LopG2Ld%wE@S)A!GQK+Bb}~QTw}H zldLc%MgWBnE&iRO*%N;EWUR64@UHWgGK zID5TT42}UWuYf*HUMBZoM-5fm`r%LVm#c)K48+z!hXyseI7>rxD4>hn|Mup;A85^& zlBHN5qnn)prNa23$p2ApspvvViM3x}SC74t zWJo4JX!VaUuV`eD#uXFbsK1;hi9}g`I+3%gRDQiDg2;MG=p9~vG%3B&_-&f$2(Do& zc>0*$uEaQ1*RK)7g@#q_T70xmj{<$b5W6_KYcpWQ*En9f1T8HLNRvJMS0swU-R==0 zK@P}XH z*;7fB_fihF<@SzBk)0*I<`2^;QU*#o``i~$f^F0l3at-s4HiZ^WXFOq0B=`F`+P)4WrV8}rcC7#7 z>U#R{h$HioX@y&se&*Kgd%x|I`xa7z5p%K2?~HekSUtO~KK(>|2qj+F?m|=7QAia(j$otM|5cP$Y)wV z0cK{1*SAW;JSXPmtwLBPwI8nao+S&UE3FM6Z^i_pe@t)Au)F?{7GwR*%VUhX8DSr% z$`+nx5}7AJ?UrT2cKzNLgJo?7^4Ed?RoR=zHFb7t!#K3mTBTZtR)tut#cGk-I#M87 z2hI)RYXZd?y#n6;gAFQ|=pR-vB>Z>%`M0{i}wh zgJ+L=_0cZ3rfRCLUA=t#LVfv}h1-L!d>>4$sW|WPI<{x*9wA)(!3#Az~RgU}XtBPKH)_F2XU4d&qz+Z;m z{xmBqwYcUsWDAef-)WkMfBsH}4O(4$Zr%)cX6ups?iEWCTOM3G08lpHBI$!NB8uK?`f@_@P&P`KBTZa>t1uuh?+8dcF?Q#z$(ob*B%*v zXsS80WV5Gm#5X}-q}Rctkn4OgMhx}jVP0r>zN$L(P9(VO6W)Uz%$|Lz?`7Tmd9sT~ z7#*f2n-%I~`R&^$d7`mcw*cJcJMzqe*fZo1=J{>4eRc6U{!Mjyg@Ts(U5tk8qwHUv?rzxIO*jwWd7+CI_+JB@7;ijJ?)y@imGvm0rq5v8wiz@2pFXA zM*#j!&@#Gc2HWyqce}0r5f`qnltCFF)PePC^EslGhX?Q3|2IUt^#eEP@Pt7^^aAp; z_uhNh7+_CQ7VWcJajYyWczc**5LK3W+s#b-UR(3q3RS`UZi84$jzk_1FJkX18b}kt zcdR@tZpDJ+<#drvix1yU{30+A-t1nvD6F6hmRJr%C`!fq73?@_I^pl7B&jF32BR^c z-p;u_6l>b5z0Oz*m}WQ!M*LvD6FMFtQQIrQNJr}lc5onltJ7I2ZA>T{G8BDm)*WZj zP!<;Y#@(6ckelDQJMv!=O>|NJ_QLR$yzz|g%o{Dl@YQ=l%k%6si_olbEFf;q7KJ^D2U~{vl8FKc6*i&_ zd^f#18w>8mPKxWl4IrZvprPRZsmN)Er z{~%q>LP{iVa00QnYnHayX8>d{069wM8mQ4><`1AP4!wYma_2}H0fcF9$W1@C+QbJu zB_8gZHn2*;tmT;@$Qe7?x4Ok)Y0(^$tzD}MW4oUkKYO$sbn~oOwtw{&DJS-XD&2ed z^_>3Dqy-{bR_?YFu`fpGu5%(&KZLnr+gNT?YH$OP0sSzt;8t{;FX18RjmRzZS9;>C%^340M$?i|B+XDkl+jC4g0gFjm7vXs{|HLkO?diBCi-4-P z^(%d8+U31gWnoUo?aKf;TI5Vdw|F~NUZlpBZ_lbfcSdq;Q4g(ooLetv%D18|M)$*0 zu}_qar_;We5s>s}NXGPP*FNE`-|jR&C}WY)Oe%zXCy{Svq$qA#6OwGS%okYm6oP~# zHz@~;g#6jz-OF0^%>v&cnTs+xzY2hu&Y}1sPY~Ji)fa&uteL)f@_?{Lam2C{GX&NJ z>tDO{|CH8UX2xG>vv=Kpn)Fm@jV^0wM;_HM+GY?3eB(8FM@qb7U8^!ms;uD(O8P&I z9(g0&|IzhrsUIz4*sijA^VM#B`8Ig$Pw*K3lCrV0dVPn{RULHn9U~M|x>jUrKjP53 zJudupBv2w^=qmsa+~hA)e>7;KP-YAEZ|i4Rn3(!8rX7IhrTIy%$?KOUx}WZS-r5Ug`P(CbHx{4wy%cwwE3N2Ios zVGk%sh&eU0ES~st$8et?FJvVDw&S{11&|DD%R<$)L88D_6`6ucv7Js!!166u881|U zligDZILT%53i%yU}s*&NQcOZr_2 z5NF$e)dyX=LQQ<(emHOMuS0)X^?b{Y$IVmevKJfcN6x)fh}&Zls$?6QG#g)i!B5&= zy)}i=3fYC@{b|2_ec|qv{q)P)F72n!M?N{w+E)BLLpZ2Qkb1**a%9&^=93rER7*sttvKw_hO@uThGx%^PGQ}-*!2V|lZ;Ia-mpaU7;<)s zH)jJi#GcwWrjxLrZLfW}DnD~l;!jnfA&d_G<0W|W+MT-wQ{L~scIn1vEzm65qs$F` z_kR83+_qW_PY_FTVv(&yh>*p zD$~mt&z8Fdr_TGyo@S3nIazgSl*31U#UB1`$pW6|cOs9k*X-}A0V*^~SzU4DBhfrj zKb2ypi_bh}R|Q_*zQ!j{AY^2(y1KnV|3nY{k*s~|%KE9~+onXT&P7k607zSt9)nrV z%r#$~6K=H}|8v!G{eczXN7P^|);xKb|LQj1Pjs8Y=Rv>;D>y8TXKX3269^jA3*%_c(rW)@wup65FJ!1nzf8f6&Fn~KN&CvRohw*Y zH^D1#HJp45>ZAXO=%-QVq;ideu9{s?y+PjA=}4nlt-XSX&-%p} zdBM_Bc#iQ+=+XBZ=qjB)5MEJ<;cd2UDF>;kM>xY9~RHc3#_sU4a4rmWc^|`KBnHp{AaCwgg zs1A+T?Y=RtqLV>4K=3-!tUhYe%Ne5OpI;mGW2%G2);U~nd4}zcW5siGgm#r>IBBIe)nv--K;rr7TY*xVg5Dn zrzgC-wqvg(GRKyLySj1a=?{aCo4)0jm=jNQ)YW`@W7F!m*`NEzZU2Mi+O^{++okY* z4dCxw+sY`_iV=HkcZv^~#mNqN618wF!v+ubJ9z>b#iU^IU4c^UfoTb!Cvsz~;u`(e zqwU(qX%AHGiaWo2wd(r`n_DM#Db3`K?>{?NI_K6m!tN76SnZxZ8R< z8|Z+LCGlTL;xC!~H#olCZue3;NN+Pv5^3L$KQLgi$rpQ}Tm5|QmXiyQ2K$VfDNuJ~ zN^i5~!Ss9ObJl!f*fo0XxmH=nvMy%9*W?N76;7cpqbA(QaBC~!^087!WAN7z{4T9! zJzoFXg^V=Gw|!L}+(HdK_2T_g>uPK({gb`8Nj#LNYKfJ@vmj8GyXZcy4 zr(shsUU@v9sGdFXPu3Tnf+gX~Te}P1A9E>@IeqC#rAjH~v>o|j^|{@P-?85aq}Qw} z!FELLWO;{{{H(n;>FmBRaT+ZVhndCXV#1a&-PV6M+Xp;kx$W-td8-^Afx4ea<%wWQC^gjN)vLAo65FIw|J zYDQ^2<=4h}aASE}>$QhQ*VNDJ0*iXGdG~y=M@J@k-a6cj!NA*2>;BKPQ>YedtaSyN z0XKXpD?gU?!|%J-QDvRjMaJUPH0(Tmebmkq9mzJ!x5j;IXa7;OdsoN_$@8QPKEt?0 z>u-Le>uROdw=X|= zOBn>Th+lk>-TKbyptBBHZwuhTytU>uugAM(AsruI;~YqPux|T%w~x}&qoEYo#biw? z>^5-5b-B+~E*j%?eszvxHo#Mn*GHQI6uKN9XbNX8`s3JgU&9De}9nl+T%@wA@x-`0sMmVs2 z3ma1;ojgV0l9Lw`w5D|5!I;3mQaL18@WaIlr7Gj$kYn5Fl_B6dkD2r4nCyPRi2>`M zF~55m{RH>y!ZPgKm7{*wRfg&X0B_jq}BWF z{WDAe?BO+r&cvi~K4*T(2fBnJcJYl*?M@;>H3RJaPphKQWk<2#XJ_Zo=jUW;eEcjZ z>AQsaO0nlX zpJtFPbdD@YKgNn1wb$L&K7yW7>>nUl@!x^q|M_8y8HY|9A-~(8J=|k}BolDo|83$9 zrDp%)MgM)68kJYW_T#|c?xv%(24kG4Ol;Os7sGzjc4tttfLVfAcyKPt+>!5UyyJ4% ziZ!@`j}+jWJtQzNQ5e#o>><&lb|I|4NQYPmPbhk#)tz1s_mG2HcLraaT{sZSL788p zU~eyHpN*c(X*u~AjUO;!Sgzvom#pbXKcBhp^Y7lDa*SWS`lCgk30aL_ zomdy?dDyt|=N9|RJzNRy-@}s#I*NF}`GAt6o{Ki7Rjj)E)8G}Ks(=FQT7Bra=vzk_ zs$tLgqIE6$s7r&uI>231(%LLcQxt$5SY`W4V%B zmr8gIP!k6qD(QyO^JMwvfG=-;St)3S+NJ4gHTL-X8(iVUfI|NjdoLKIFbqF~8>s0l`MOQoS^OH`F=aoNo~k*{5Xv6e4!ae3>`b^G2K;D`{3 z7wG9nY6I0HZl2mW>%vzvRy;^qoO=9&U);KK19F;E9&U|dD9cSZS6`8)oP0(5seIFw zb=$XX5{cHC7H5}?+uoGl%kxipy3%EM3eRuRszVVlK)?Cqxvapn16#|B10lw0*x83emHtoj%H(5%tjMH=}&!j6;cOncGz9I;0b1n&y`o z$~I-_uNEtoF7im?6zA{4?$Hb}R9AbKJEv-89Q*vR-yD45_u!sbJBEK18FZ<9bW24+ zxt39eSlSzF9?2t9ZUu6FABX*U9!y+sW38N6HOvc$+KvGGI!fTKrhxawB<&iZe)BS~ zQcBoO-`77mGGn333;|eyV?d6OzkJ`&B(Fa}K5mVQDg?$={jyU5aJ#|smkuA|>>5JG zY(fn*20^N%fDvG4Zi*7sqq`R;{Y($G2joxe(N*E2*YSlx^rlb2jInmb8pCou=GQ?| zfxE;tidOV{yxVZbT42wo8wWUE!O+SFWQ4KZAJg0A7BRqyEt)Q($RC<|gESe$q&kB!WS)Uv`1T=&9xjGtaIohz}a;?KcXp|mVFrt3+ zkp4yt*wO(&tPk^8F%Rl%h?#GQm~aojS%~?l7&%SNb+-uQG@&=bSuSl%1IXy1MV=x7 zLI>j!nz7K5b(Xl^(n9=ATE_*_y1lGka6$l_MmSS(pI|F?O9fd@NQ8-#%EqTXQjH{2ddy9lVa z_&oH;A5Su3Do2txG{nYwi`G0VPL4TFE}1`$K8p4t`?C;A|ENE?c=<uq?>$|2WkujVc3NfCs!7aCTq&U#x^q?any#C3P%r3{~|}hddaD1=z~K zvR-`)$hueAQh~SUCJ-F`nLo9UQT8kvMsxIww-dRouBt4r4_PXzs>adM)p3Lq_m!{D z?bapr(Da!Kkr*Ks6Z-cXnk5oZQkfZU*Jvj4In^WO0}<}XZd z?8ZD=OC|T%^W20Uzw0OOlt@-5_6wx9AGC9qPP(*<&X5dy<+k+82QM!FwQ}|Hrq?XcxFo6rqf=V zntQNARPjA^(Tv@mx;y3f@&_l+X@Mg%lfw=Se7bLWMrGM@i<@|=&$SQ~Rb z^{!o`(X2aYxmrMXE=N3(302GH8z$69*AW{Uq zrV4bg4XIRmDB?Qckrw>4zENQnz7M)_}KEScSWtn&qcB=H(z%u0~LJJ~PZFF71db<;I|pnZUJW{rHkB2I7x?zq+%0A@do?G4W+&fl`2(gc;s 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 literal 0 HcmV?d00001 diff --git a/setup/import/images/PROD001-4.jpg b/setup/import/images/PROD001-4.jpg new file mode 100644 index 0000000000000000000000000000000000000000..94eb80ce9a988f9dd20c588720387db7208681e6 GIT binary patch literal 110433 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

    ZsaNuUN>l6?%D(uf;n{jajNJtv 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ΜA1B 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 literal 0 HcmV?d00001 diff --git a/setup/import/images/PROD001-5.jpg b/setup/import/images/PROD001-5.jpg new file mode 100644 index 0000000000000000000000000000000000000000..3036b219663d76419c49e2c4368256d7803a9821 GIT binary patch literal 104065 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

    o%)DkZV(XSaK*P1GzQ{ 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 literal 0 HcmV?d00001 diff --git a/setup/import/images/PROD002-1.jpg b/setup/import/images/PROD002-1.jpg new file mode 100644 index 0000000000000000000000000000000000000000..f38d005e0b1ab8946690fc858e30f7f1da63ae44 GIT binary patch literal 141375 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%0A$%hx^BbwiTy!XD@v+|dI9Am0QA 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 HGxk3KpnSw^ literal 0 HcmV?d00001 diff --git a/setup/import/images/PROD002-2.jpg b/setup/import/images/PROD002-2.jpg new file mode 100644 index 0000000000000000000000000000000000000000..61a57c5ade4f176bfc687d47baed7a121a3d0f34 GIT binary patch literal 126842 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 Dp&~RA literal 0 HcmV?d00001 diff --git a/setup/import/images/PROD002-3.jpg b/setup/import/images/PROD002-3.jpg new file mode 100644 index 0000000000000000000000000000000000000000..845a260315cbdeefe152e681d2d4fc0ff827c22f GIT binary patch literal 74860 zcmeFa2VB$1wm2R|KrAR06huH#5ouCF6Ua)H8l`uZ5+FbbB=nYD8;U?ysuYPz69JKq zR2w2)x^(H%dk@L~n^1&Z^xl2<-QRof^S{v~GpEg&GwsazP6px^;#bgNML7jI(5_v( zK-YkOAYwOdtgI{C0t8Y}xCGh@0)Y;KXm{-f2?D7X!21x8J_3Aq0`J2>dOz?z3A~T& zq5$mzzDaM!U6kZ+Jdi%Mp56l>F0Rw;2H<=EFB9;60D$uY>0?0pB9OiUqz?jVaUgwk z_jj3(Zteyh2H=VS9PYD+EME^u$5MbmP?U+CC5)BT-qr-|2sdLzJ0g*`tZ+2a*2EEJ z&Wf~Sb+Ljw!dOjB%xo-CNGCgUR*%B{8me|3s&-XF0jjzVkrBRp8ALJ!xrB}H ztL8{k80&Q_q$3h-g|ugtRu^Q|hTEAVUC(c z2B6=wp4I`>^n$a35KJTL8X0aIGvy68$>d6G&68!*2s=>cF*fDSP%Usb2mpZufG+ZIOFD2%8uVmcf4<9?cRl%D$KC7c!$3Ep zSWiCzn)$@DH5yV+0mV?0>q07H*LoUgc+hSjP3oV)0Ad%=4M;H3YxjDZl&9DN-xIrL zhbVxaavd%X&`@omq27|-yPhWLK(htDZ%g{XmNY;{*1-$-re9BQ_6;FczRP0#0%Bm1 z@BL*94DuEPDmn!Mg=v65o-`y$YqB_uf%aepM#Fj@v>W)hYu9d4-AHdL5XJhKq5^Uo z<8B(L;l{XI2GU!{-LBnhEeCvocCV+y_W{hnYooVsd=t0K4}cZc=7%xR0rF@tmR14n zB94P-$vKeuZ-9VZ#5T}v(1E>s_tNY=KtpqYZvVdhbjJ@JIB@9r$)iV)A3b`K?g06< z{( z5j%kKLrwg!3j%0K3Cwn+32*HM^qk#$D5(9ttpxqQ3$itvrdv;Om-m{yM znrbg4#Q^~TNk_5g%n?4yt2a!Jo^|-0pX%7dr)g4b=Z>qrH5Cv<-K>?SJ|Cz)**#^3 z2Gc)FzjZ+-NW)zAU5um9i8{?5*mTD2_w`P_Gji;~v3D{_RncqINuG8 z&;HmnFfS~xZRz3@mXK50Jh(syv>Bl79;W`zID3?m|M!Q-NE*CV ztDO`$XWEUr87QrO+zc%^b)Jf(0QCj%yE;ILm=or*nnI4So=p{gtO5IX6^N~%0~F*k z=|B+BoJOF+d5&{|3W^Hn0@VT)&IQMA0jLu{uMwQrXM6tD^wFnJFA@$_q2E9Ts{7?? zQoLv)yq@F|K^O85t#U`I!$jl<{=kOEO}!7qaGmEJ{}5(){^rC>!*gErMiaL{L{Ji1 z9aAG2Nw~#^Z^8^|G7Q*brys(YaC`)7W3!^bH$+ghm%u9RFN6xn?291pT*sISB(fxk z2vQq7zYxVT$Tpue?peB&=oK)mbh=n?nXM?K+Hx)_gRor6dEANM@AA3wImWOJGBfaD zDvT*R3L1Q~47C(9WA;A z#AQW8Ldl@YsJCbTeZr-}mznkpyQXgRJ!DlpM(KRSRt_ASj1xnQC45-z8dGJ!c2pBV z!bFgOZa_X;*2|Up?Dl(2rCvjiD*G_h2OMUVimNCH_$YesA;|II5yU|r zAxY|KUqj*efw`!G?z%yx!lo}hN;Z~*I^B@@Hi(2GTjV`CetLH~E|f^`Q4Zq+F6Rml zU3HeutG>c_a^RI1%HQmls#I1ZZ){<2OQFjpoZ^s*?H=y3))^z3!~48-pcGxs~Ue%~sOC>Av=yejh5z zRzJW}$Wr%UAg0wb;Er5V5`zx*Ls>rU`_~O384mqb%bJiCC((dkaP$Pe+ubL?1;c)a`RQX&Zp&FbTdfq@;XZhiQR|FK+xC*v~Gmn%zdP zYedvtzOnjVHMYJ)?sSMP@LwlVlya>9y_!^A__4|a9 z3MnE;=8>1beAX|M;vo4~ta^uH7Y7bpN|U&fv%hOq?fnX`)RTvY%A$OTpk{C?5wvSI zw47N&<(cmgvNqBG*F`~uj3Lumwv!*c?@^4p*#-$j#bd68d%aLN7ZggGLZHNkOm0cm<8Inl+d4KV@N0-yLy&2Psm5`Vc%XYqonpa8`lXc$xF9Y4tt30(eb)* zj!WsI9JeUNgCxYQm0v`UJEmTcWxTX8nGr$6#&w-Syq`W+r8*z3?Zx=fe|+#XgFYsB zf%O_F=m}#i#aR%&!V_l85u@w*&zt?~xl7FRm*=HpR=|9?`JSq@d@B~v?bCL$)!Ds5 zozp9OryR!cp{w*sy8dm~7w`CUtOQntJ^k$F=q|4F@uF$TN{sP@cNl(9;*;v$YAIBF ziwE?Ds2N*~_6-4xGlKbFB^ohbRZZIrPBgxZ7jsc>gZp{D;(Qg&*o|-W!H)$P4tMtR zuRJn!|6pHH%_~~dEs{~OU^#+a)K5GYsKp4_8<@75$kn=>H~c)Y+2CvWm-E%mzfr!Q z3rMxpDx*wq7lVG&acm!#uq1*w7a$IX%iSSP;aT0vHw;aig%_fG=I;|?bkg+Bz-HQO z&voDZ&2w;}_{AvxN)X+>8VT5$Z!EbGkCm!q#+)`umXcG6?{z*d@CZ!qf`V*QUC=L5 zqsK~$1*@594Hm?*lPiR8>&XW%H0VF?<{2KFU2$SUJ$a7};6G4@qhaPzYCGeE(~?Zf zZW2fs$m6l)kAx0-k0FVm+eDB&A&elrRINL9Q_th%ReRP?gVRfF73d>xA;XW)om_gU zC))kakxi!}V>pou^P*5{ln}_`#*-eF7r0<;aEjLEF+K&`noZwsexB}3<{h7?G76gV zBb^s~fpx4umDo%+k$7{{%jgB2%7Od8TEPNVznse~UZU+-z4Kdn`yf?mi8}-6=H5RX zS(9yRl1_%^w%nWXoq75BLUE8p5pESRj1?%Gs%gI)i?1CYMqv*7vGSSM`}9W>LA@ex z?xydK2_3RuN>R!?VUQ$8WiGtLbCd|WxokXVBRT%KalvD9?BPlZ56dF+9F>CrEi=ub z7!O)ynJ;A&gu}&Y@q2O)9ii^YW~TIGFJ8VAIZqqEmu=q?%OsQt`jq6MTaxw2>`Ep@>@=ym)9ycBOe)`AC_m7tXAx^~# z@YuixKbc?dec4BQZora5RsT~s%L~BtTE!b~!;k%n77%f4kLvf`m;ldZkcgCm${x}d z3AE=3(=I&_#i{f1On{5G8?=WB@LhLDTQTjX1RdPAMP%B|0HP#s7Rf0yD-$@1l%igz zBBiO;HkYL2-i;k48E%S#TUt4ilKWt`Fa*rb(FEm2#-QN{ds`SONr8rwDfXaYCgcPa z($pGeMov;7?Z`BgD44B@D~Wm!3Wg@5DA5QLTU!!{(hO;fBq_Y^?vm7P<~Pur=htv>OIGqUMA~!%gg1 zp?OS5(HIdLtO2F=n>43)f8q4x07I>$S-DRg_}#TYlBrTtJq7! ztl-z&Q80CPRSh$D8#7UJc8KIYaaS={1Ta1wO;}wKwsvSSR|$5qa4{fF0`s!7l1UtG zB-j-YCYCTUF;ehN0|~^hM0ohX?0^iExrLaTjNG~eASc1TuBwZR3y+Hc4-#d`%O@%- z%6plgm!F>-px{Qk0n?Eyw;h@dkg$)HEJFr{HbcSfNh6V!B-6wc>EtNE&c2UzU9<|^ z4247^EgZ=+>t-o{K@b}lvQg|wVK9({1$co zc@<5Z01NKaP%yx1BV`s3lj&jz}mCXb-v5LYU{X7KB*Up*#ePR33gX*bC`vRldU7WlsCDmTXXKi_cgAfjggax`9GabR-#wh2@oO&6k8qAZKmZ+f zXUv+H^aGq7Y-a@7qxlgE{ezOop4QGxWY=qF6wn0$Uun(Na!+?gk=)3gF+Vfu7DsbuW-`IfsC8F# zXXJO^bZ7jUv-$(vy7#&>cHM>jDU#&h?o2>-cz=WfJm77pwaoh5LZ0}xOgyA{$Pw;n z3;R9`{d4p7wvEybOOhV6a94Kwt%PR!TmqN*xCHn_fVU_Y zm>+lx@B=VFj__sR4bTdc@?ZcDyafaW_^(I{U6qm+6%v#Zmf{nY;+K}aDkUo@B*iBr zEhr!?A^=`jbem@XlG{Y~Pf3qyckWP|XtKY!)~hyQV$!4yH`(+8;=DV7Nv8Y`SCE#z zjzU_%fdPhAlb2#ukd+qV6BQET=I7zt%D;tfy8v~#In2xiC5J@Gx;g^hD&U<;f3 z<=u(oUowy*+~Nm=jfB}^7E)GB3hs!$4nwJ%kfIvjr;)$7mw@|A^6Pi@DR-76P6kUO z5%xgngIskXao)ecNCqPV$vY&#rMGmnk`x3w?>g;P@OD~lxH&)ybY1?fq-)Sk%55F* zf6I^{*LRy{oBERGC0i%bHck_W=SXf;?N8uMa-Hu8Nnw6opjVP*Zv}7C>PnkRqtu;D z$!$&A#qqIj(EkPXooVL+bhm*2rQQncpm!d~8=LdBAqQ-IGT`FmhX#+u*SxTj*XS%FSHv1zHfU;BzSC}ZqvmMRO2tbuG-;udbp`@~Y~T0uXh${J561b<0s!(Y>_9zKRDNDQ z0Q6;j4n8QZmva zvcQ@yA}GfvE6pdzF9^OYAjl8&#=o!vEx;*bwsk7*xTE}&B%d4US~V=^)TG#TDzg_ z79rb&lOk6xCMeidOQ1_hl24`Vd}3=u&~}DxvRtfScH5?b%fQJUG4Q5Cxn^536`60_ z(zmgP|9h=whO~2rp@8#h8|tmM<~F@H8tU)2ob*2)SN~+oZ7Rz8pEe{-JX=N?5Z5M6 zfd7^j1oQvniR_xPw-!BzwK+xfAgZmCk6(_hQR;LfdT$sY*_L!ZodDchW#fT-k+@# z|JEM6em?&HW{(yA-`-;d!2c75{dfDm{|)kg;+Oq5NdKYtuub+_X7eHI+IDcu&W{v^ z0QQ0kJ8WV9VaNLmE3j!;mj?x&Ny6<+Y-RrId)6I9{7ZoiGZcE~u!0$|IYgOoqfA`5 z(J=A}BGNPN%j+=)fKBYGEfC=`ce_g3DFPc<4U`iQhu;A~sy_)VW$OgH=0py(Z_RE+ ztD683bMmH>6hz;k+5+7qCO_S^0|J$jocx08q~Bp1WYXkHYy^d+fVk2c>2~;z)azk+ z>B~}rU{MhuL@viCCmA?xkF z3EH5MgWK9Fla9A-RO>rngG3$$gV}BAVVn7F1Y3I3dRb(;E#M9EYbI!E;CEwNYq7iye8^Fgr4-07pH5Gfq3QZQyofTst7KBi}k|N4D!u zDAMDP_2%1VjCItGY(RJ4k%t7|kwF(`Ym0Q*k!KyX!KUnl048=I+WDtuSy%B#=%27} zZMz-Vx3%C7_-*a@L;O$5-)OfV*IH1nU76mtxF+tg&H~QS4!G9&+oITWm zW!O$|*d z=)ZESTLH&4UDlX4TJt;eR_u>>chGf>ZA^m3V0ooGV0RCBEpvidB_itNv*#XyU77F-?Cr<9g&pVg50tyt(yy=*#g`k z{SMlB0{S8TX9BiPK|2Z9HV5rQux%3hF~QGt*qCJ2Yrm6_4U(UUS)XUPfoE2vrr1f$ zpQfUnNVd;KKcV=UDx}%wC$-r+8SPZU_Sxts6q`Dbhm8jOdoNz=^JK_&qRsK~=TQOV zQT8x98Nh*t+X6>b)~&b=xWIot_w>4A;Lwj$Qy zo7AMKP6KHN$d)nzPPv+G`U2$HVLN6Arp;Mx%h=n(xefg@_V3o;Y|-zUZA#ffwS%xV zQ}3+Eciaydw+P=b*>@Gz__vU3h|vHJMv{*GlYDNl;D*n=6}m}D>Nnhc>n*;m&j4nI zNjssOe|8S#G8ZeL)|R6v8_(k;ful;m6%9M%gao-*NheBn;^X5N;bH|oet;DP!~$o2 zcE<99!9by4pfXz|uVpr40i@|+Tg}Le-X?@Rx2wQ_Zi--)M%p=|fLkusy6Se44f|;U z&sRyuh`<{?dIPXY05=7WMSSnUS{wQA1Us!ne_Ee*i~+3G4EVVM@WTb(&0jx|pKOz# zK>s^G0PX+%um2SCw`}|$bN$C$f6D@Yi}*ji>p$lDTNe0R#Q*7C|1sC!vcTUW{(sZE zzW;6&W(WLO)dl!fDsV@WG-x;Z1|-twZqjQH1?iKLbg>W>B^4F9ON%Qfg^$YXwYEH=lLWO9!S;o;W9{Zic?~?tR^Pji8vR3t%Cc z`W`^&X`nRnwNT`r1d~62Le?&R0?-O{fJ#6q6f~5;YcEN+^)mUWj$EZadKS2R>Gy|E zkMRSg9hXw;o@5h{HVu?P-F#O^PbxC#*_6hubhDoA*C#EI?#=tp>pvFwj|Ki?f&X_F zpwfPHAXQNK_fl~P-0K(g`}wd2>Mcn@&(A_(qDEF!>fhe{9i>_gb(mm0#kmJh9CnTA zPNf-K<(Q(Du6J`!TGjJsS%`h0E6`oCFh)1==&sg5`V95e>MQyky0~|z+4N_-W)-`K zM23wZ_H7QsDXE1XM9>(=Nl}rSeI*MS+Jh`X4!6<`;~Q41Et zlmD>1Q01IfYiEhO6?_EzI^Vcu^l0Yb{RJ6<|3_R|j%^kbp(>}S5nI&=#%8nBT9k+k zxeL=9mvI*wg{VegL>rBBo6V(X7u?~CZA(JAo<8P8&%Mr6RIIH2@Ti6K~@h_U&y%N168oRzNF33G4f}GxKKxWK876%vA)+jYWzG550 zplpSH*g~ZmJbLM(!D^gQWSARfxR0L|W9AE4on)FvTUt|Bk2EaFj%g4<*xA%?`OHdJ=vYP{5|W6Zh5(~z$?!lO??3YD zYC=u{w?cioy(B%RO(?D_euh~v{DLKdj!3!?LC=jI8-<@Xa`S0FU>2R0+6eKEh2mcPL*k`%NA)mmPi=`Hud`|Whq4?9wLsC(!0`{zm2;jG zz?FhkESX2^6|qp}iT>3>$tvKkz98(yjwI|9A!L<)uuR)zj8MTcT)e8JQB;dni4d{* zxE$CuH>=N11U)mrau~kAPQ|Q(SLsvw!d}%AsvsjIQt!G6m2z%*f;PA1z_5LP1gb?Oh_2fECciW6v*QXqF z?)qwZJSIh736j-T7vDw*d0%kKK5PuGeR#F8GQv%_*JMilbCS-zBI$fC7oEVkP%Yw3OM zgjRfh9^)JhVNs@{wBPtn+r+O0o~9T%TId;1y<)Vs!a`H+a*n%Y8~ay(xARG^x+U42 zcEN}jakJ0;@A7i2Mi+Oc^mZRz%6eUJe?A(A<`G?Nh4edf3y(R>LW|xN_#A5yZl3n1 z4(BCA^;z^z-*1VmuJ@2H%2={%>Ys+RiFwbHOXSey&b=B}EtC5qWL)>#RaEV*sv~2s+q5t2t4q z1laYQE#LgDo3NEUU(5@LP^z%$igp4PDjT#a0J%Hf66@Oi^<&YqStxz3^;pHToMyy8 zR~htzvxFU%x4levL63dL8Z{ZfnLt>8x~~jb;U5Ro+<4UhUmn@t3hrIeuukNC8_vha zS8$nIU&}euHjk1y&$Ne_Lw4=N-oEPoS@M6saf~WAy)U zbRZ+^H9kJi+vp`$Flh1X$BN{-uUOTogC8IK<`8`*=h0jE{i!yqrRvX%VN6~x345&q zLzwq|HDYaMXAa?%diVG_*t(0 zd4pc(H($b)ihjKIyr288Q>G!pJxTTO;yHK8NU6J$NBU8C6&~;UDVy1%&Tl@NvD4@l zgQErA6PQ9cE`EwdzRES}BaR_=KrQT~Yw8C*oUl&E2)LhR-YspBQ5mm&Z(wB!0by_w zQ>~tqV8WQi$9XkkOA#FqwfgbYphVT_>o1z>;6eoMEF`R)l7Jl8;ry4OkpCAerNYfZ)oIhNfqZ8(0HaRKR9y+tnI@2k_ale zU8mMj%{YR4U~b{N5bikkIOEQjgh=he-Pf?_@chT~Y+!9S)O43rkgN+Tdhw&YeY?J+ zj#sIZ(M(wMqoHQXvk9)KwuSL4K5pfR(XbxvT$j6jp~v(&JAw-O6~=Wi@yF`a;{JB6B-N3DWtOkhI#bkN7GSoJ#PSVb`l<6UfIpi>=%*bz@fLk5qem zaY8C6yHf8~>vcn=%&cxZ8x3TGJa;+AeEX;P7;d+ccu7v@5+$cQNs^bEX5k#)+ON7H z!3&rRdBKdBlbM#Ly-d=F+AAPJw06gz)UdRgCa?6cPdQhgn2nkZ?rwdEJ+%0?>f8(@8#~O zGc}`kE?Zf`w_jt0eP?8Vg=Z$=3pU_546$AAz zpbNyL>MJytz@)*5!h_&S*?xPIvp z;uJo?vT;$MPW=t<;b3j*#lj~>s>aT~4Nv!_c9aRlEuON~OA*41PaK^>Ef*asafB@S z(WhqHT=87Kl6grg_P8Qil^doY9{*s>=8v7`3EIcM;A@AV^L~@Ox5N=nUlZ=mj%AJW zXJlz+DXK@}BNhDu`~9_9iZv72ho9BofR~kWNFWwp27=LXaXDpl1*J({%VO1ZEfOw= z>po_1sn}PJ9qmQBWVB6t3r^jtqbQwVuxUstjXpCBPO-eu8{gXKJfCKy_*k5MD%7~( zT|<|8s2Kh+5wx$nfW@a~-nF-IBpN-3#|b9IXx@UW_tzM3F*3E<28nmX<1`=GDNfg) zr}jB9^){s}KD3!WzUWARo`+Yui7}L`)%wisvE`(EPjFNJsC%IZomV_t+kG*A{oNvn`XHW&3VBU8`>HYSv6rUJ!J!BCPex^}1Qr__vL{~-2~ClnXq`zFDac@4 z=GGKzb{ZZmu?sA1DnF%>lX%Ea7b}u#TzGW`#xt z@C&FkPS}=(#OE6Tk+hS;3;*CfZ|r zLp<6TblMXlfpM(Jjh0WyO^EDEbt{ij|1^Gj2=yuyo$c}#Dg;23a*Cgfb94$Jd24KG zyE}s{((6yZFR&2x5K`pWXUAoEva}%COx=|!5MEf2u9WNY)bB<8^#Qb@OIM;!EJvq2 zXC6xum;bYa{qJ+5qB-i2R~*Yk;s%`W$suxdE%zI0brXDBZ|IJk$99^l%O@7Bc7%>a zp7zwTnw+a_vU?fFG=H-!5__kzGy(Qt_?eiLt9=J{Brk~2P}yoTJ@9~w%I z2vzp$yL=?L@iwbw*iM!U6-_+!&U1>iyn7=HVUlp`QiPkC@r?sRttv>$TLR4c<>i=_ zXCJAkHYLHI&u~qI1i^fm^{OYEEX(fJX685FjTT;P?1p`?o@BY_o{igE21f3Gt$Mq# zI(UYvNDjEkG^yFd|5dy7k%(}z(NsNtb|t>Jn_&uAYU&rprCbU0?VifvZq*B%I z-Tilij30ojJNu3C&w4-k&)C5bh1DypNrI#I9YKOPDNOT;t{Ek-Lp9!sSU z@9J5J@tNddSz)8y8|zloZ-%t^Jm$PSNUvMxUx?>0l7ft!E!0%@n0LU)IJUA}a!Zp@ z*ACzwdDIU{_&S&st(vKe5U%TsSYeOyPSnb`Q8UQVa^irj=!uqAGpv@XCrsaIDTHNb z4FnOa@V(9tcuf`uB7|dQi6G!wXlL`6f)8+}0=iy&=KvQ9_Z8tV^^!V?FafsgJ-})I zQaEm9F@=T3O#RwZP4BzUycI^xRk;|<+?5r<4a0n>LW|=s1r^>IH40@<^Q8}+Wq6d; z(Qln+p5vMCd^t7FQeDf}`RLHaM>%yBJbAI`jCbBOl_l9B4^@=eLef8ud^KxR;qo0m zneXOwqs60wzMfb62JPt#uju_k^{H~MremFaD;4VTIJG`YtUmU7*HY+M{5(5D_wCV( zWh;)Rlldj|h?wL>9=T^`B}|zfjM&!9`1z4f4}`iG5lye6tW!tKmL8~t9!q{YU1sNM z6yaWXbj8A0A6v=jVxy7K*EPc?&aQ$#oNU8idT)0B0Sm#1MHM25U*Mf1;7ldkpxnQ_ zJe~C|P8ZX2copl@8f=sLnh6Sk-QR>2V4Z_q!^__1FlIGVUdLAu zUaFYdmC#qIQ~mc2eVM@f>Zo5tzBZbsZ_o-)ff-B#MAt8A> zmb*V>?-W{BOhJSFa(T6%tYD0@;jJ1!WZ-*)CMx!+e$CgWa=F!TL8LB`BkFZ7tA zMZbo2=!RqEwWtg|$I2|C!=!MX@4M2=!VN^yKF-^WCDsHwCtnE8tPmlBs*`HtLW+~0 zXUyt{rcXuhe@0jVoAuW8rHII%YO0ynNr4=U8NB44!>H4$U(P6m(;9fmS0y-9zg*Z= z#?)C{PQ9=6s0z2mJl6Q)sy>0`3lF>71M8IISWD4W7WWl4ar3FO6QxBLCxf(`I-2gd zy-#l((kXmu=Ac-3NjE;9<73jmjJ7_yzFIw=?gz)3I>>`l> z``7!N({&#+dDNfJ6077MbDc7uT@_31yh)gq(aN6=zf~B>go#;pQVsN76!-4srAKIq zc814G@@KiG#MH$?-<=0@Q{{9##oXW_f)Wtk7n-3Zxdh(vIUyoQgJ8>*$9y7ar4oo9 zD0?e8M^Svp!)C#x;_S+%<&58S!Ci9@sAf;M3$P1F#V%Q;_}=?||YJ%V)U4yHnHZ z^YpGmfs)BAv`u651*_N@&eN~D)tf?>j1>@44YKNCzxu36Vxi~k2`4r_G_In%NIF{h+UDaGV zzG^l{?~nEm_D13#q_xu00KuT#nrN9?}P!HkS30a71>X{p7fZHsf`S^Ho)!J z(8{@9LZWBKvg7RFK#Mn=C-9$DuHH6RL@Xj z^@T2Bntes-HgvIZ=^ezPnF!j0k9Aiu=vG^pllAU+mw>m%fAtglwpzBN#8M@Ekhd1{ zf^EKtL4v<|kVcN%(x1JbeIV)feC+Z(n^^Q|NRRd)jSCp_7IFa+F&+UFtdz*mU{3_C zD&o5@zD!uO?B~INJ22CAXXgD65n?^NdB$TFE&IBMTp&)ZO5L~R$HZ7xuPwd1p&~z7 zQx2`tmVhB7Rx3<#@XwfG`Rd~{?$~bJADNLrfTgxCyQBM1<~L!&bg_tdCrLIJ5hU1Q zW_>8t^Y~-qL)a;snL8u|dq0m>kYn~7H^vRaH{W@hrKfq2I=oTY3#e2`oFQb+xYxMS ztN3o|V%E~TXftj6(P_)27yaER+4FqS3*HkkOEeot2XB?s}p1T(| zW^|mT=bb=IbIrISv@(lvJ`M_L1%hYA*&?!-5^U->>=%*SguYdXmXchMccaeiN4+*m6Yw9mt#n4L=TI|bL+qH3F!+!G~hIX$x zSs=B7g3E{JA7@z>&)qoXJfWmBD>%Pc$#MEo4YDvol8&oe(O-CUXqqsmiGM&peJ8Nk zMP(*uTJZ{7K$nLgo^2^(t{|UNkB`vM2lQSn=3Sau%UX!Y%Ixc~d6A_BF^UF*7fwF zVc&3R{8qy?o#FoX{djLi1kQjSy$z~|10;0;pqUlqu_H(?MdaB~Z@4D8Z!K=8zx zsyx$O9@i;CR6HKbi|Oc!0UIeSoj5z_e7*&LrP-#fUA0v7fx%Q)-WAEp;W7QTW3$7x zQ;)fk*NWfH>YsM*z9`ZVdcILn{)t(Ic$9@9x9G&dj_B8;J+W+DZY2UH*mH>57Zve? zW!BM86SO>M(&Hx7;vduwq%_g9(_4S6g)hZwia5vWCB?J>0X3RK!g0}A*g(kQmuOw~ zfo5a<$>7+fOil}2@B!Nh!vk}rEEkNp3Z&RpTCD9HtM}qEBzAW}8s!cyVh-dOXf6pP zCiXn6KbO>QkMpTdsF65+p;@Pb*gU5K)?>pSfu6?L$f5JySBlUT^e)Z#1 z?rM)^Rc(0pUpd)4I!H02RhXD5gDi8IFFom(RjS*GxFR?4$asqPV0n_3-dR6^(HSko z*O?S8RfZGM13X3x4i6NP$Cq7z0BO<`)noQiy^Ht@)~LR^%4Kj{Pvy%qIg)lA2j(iv6Mq$n>s}FrY~vyDZ6M4aDV_RI zq*0CC>#0IrSCh0a7n{!&s|wF?gO?dhPX1+eM(&DM4tIkN701?wiqGIHUpSoRcJIZe z4rhrm)z{6edeVQJYThqL)7Wjzk6Ebeni7DQESk&5-IPR?=Fm1(PFF!L>iXO>I9``P zrS3YN`!LK1{5FYcwsuB0`osrMftqrL(htx>O?6*`+eRXmc$)+4Sxy6wucD8aVCD!9 zG{jXVt2t+*_55uZz5d3mZbA?4POYvdHT5`}KdCfdm<|Xe-%0#h zV25e-_Ur8-g6>`q%joV93X7_E*s5CH93Of(de_GkLL=k?X1cMv?}$c$U=CqU3NxSZ zdy~XzE-$+1Y6tj867CPY)7M3$(t8{51d0ecLj>8lnmg7t1XNDZjJ!w}U7UE973ob; z-@6Jtf7oN0)vBFxk-M`ne+?OE7y`mrLZj$VIVx*-KJQ7$xrJ2&pld36{xpJ-`Bop({Cn(Ep z5HE&*`p~FmXk?{nsY2VUwDk^tsbA3#_}elso;|b9VzQBR>ojHSI3?g<-!2kk6^`>9 zPtd=gwJ*F%rSMa8mu^Jmqk7ZZ0?oXz{O5$Y@Tx$VNXfOyU+0wW^A4TI-M?5EXDob8 zZej$=89vs`6@q|Y$hr--dr?qU)M<_o5O2J9Pd(8HS@p+z4rPum&FCWouH_Z{>{0K6 zu1F^hJH=fo5Owyd!tH&zd^blQBW3)m=E(HM;&mzh(8Li?KK%vkO6XyxdEvwpS>OL?fK?PAwG>An%cw7oK9u zP;APm*KgCnBQZ2*j^ zOnkeVbB<7B40pF$aGFn7JR>~5UU_Ne-Z!TLVRaFwFCN*c8Tt4GjM-2%%LhkssFI=F z17XbR*B>T|XRr?t$732*24eX$>LIx$M9^FFxzfh46E)0*=D`=8SHCJJE z68!1r+INP=>dy+KRIucJnH&#?Di>%6&+TojG%(=1<@7Eyvko@Vv@+e|lUyS@wQwQ- zieYqyV7H=Bc(qsZ65Gp?7daPOo|MJkzaKqg0{#4=megX(G7>-J>+tZt(Z(b$oGw^%AJ@Lx6};m7;=~3JatJUDtZyG0!wiE z))$~=Gmsz3&2iSP8a>PHqIuthV`2eke3t%R2X}2X!WP$XyY#%tt*B0kj=icg>B^c~ zo#&Q=2YXNsBe0h26}uZZ8gXOd&YTj*?2|NHJLc&45ww~Ll0?us!&DJ=EAuubUQWuP z(o<*XnIc!Rm_5Ud`Vi$ROSy9y@46C@XC(s*qGlRBxV#jW(dEbb%CsE`v+AW^4Ih-S zMcE~YDxC^_)*4%MR~Dt(HhQ}`lEzRoXjm`X2CDJwRY_y$v}_R(*m%m zG0C5;S9I;3jq9oRU3B8V_GG>DJ~3$#lWGkX(rSfezQ{%TRV%f`7tX+W1(HUaDSJGn zHIKjbwQ%lA;MF#IIEC_h(%a5^8=kKD?O075v|2)a7Iz|Op|#Ynh-UFtqAPFDcqHb1luC@|oJ*cliK>+bbi6UXD?=@~ zX)?+=aG{?!(zVNS&VWDJyY0KhW zt3EjD#dt|IL4t3jD@m5#_bEbHGuAeOSrGnD|qL*$%7@5`bJ!7Zet@_M9}@b_a9wV zdTXnUBQ?YBPMwT)9c^!!vOLiIz@PbSMyO{}jO7EvX9ez}oHI7*R&yaE0p3d2n*__p zlDriCCi9^eKl#g@a?IqaJ}|e^_~@!p(u?{#*T5|t&jhS+$6LpY(q^w0;GYg2o56Bd z2zP`9%wp+}_-kLah^!X-HNL(>yVz(!^R#M@vw?)iqs$I=pMXWaEa4gVD=Tpi@1_Om zVmlYBhM&I>$?}WlOOC%*CLZk{&=`@VlEsx-WYyTpeYDE?0$ojbeCy(`Ifwz_5EuE2 z4ex^Dr~C{1u7pN=ptKA3##MEp8YXBa4!|mjAWb_dm$N#O7R!$2!UHcSOAo#H5|3XH zb|@!;{+QA(q-7GzRXFxi_euP3uW;opVs)f#X@OcD(FRo#D0EPwVFOsv@$) zCOvY33(a8H^(L)av*X=J{=(U)9vAI`G8IcvFNK8!uiB2YQODe!MqYC-apaDud&H_) zh@VkucmEa5>rj~9YSK8PT6ZQ4S)C$-J!++J94{t44Emv-0 zi@5u=6n`eRf0#)DrgYkE+_d<9IF{L_x-qsUPgpnG*2#astV5A)mscBcYTtW37+7iH-m@4AC zGKl;7q2i<9m%-5K;RWxI)__Eh(^u|@Fs8USnm?7*P7VsjK`lhZ>=?crcsfRkcmkKo~He9A~r(AqEWSp$t1EJ?^NbmMgOdM_;eVzC*rX^qTh(~pdvAY** zv_t5_5&WUD;$5|76V`l7WxytTdI{y4U{jFjz;&gkwk;n?YbcREhxrXJ`W3o=(XQ*Z zxOg|`!Bfgv2`6u4)Q`oe(wx8Dc_I_v&y~G^$oM=7pMGC{>_1R{bv`DpSH;WbyAW{C3Z(xbi| zJcOB>4MXW#mac=eHS{`<3}b^kMPE$~*rc4Q5i(GnjNTW2IpGer6(glthRE(iOjokvHe_J*s<1yW|ejm@SoRJ_G)?Wn%kP z=NqZ#u^)<6RG+ce7L(B6%&@V}@RhT)b z7WdGDLOwxk5JFn5=Ubh>A`>R5JB|pNKWgkNrp)M>9jk0vT(bmT60cPL(3@Ho*i%Di zHFoGQSfUvI7C4r~Kl0!PORw=DKJ-Eaa0X{z@ddT1qaPlB!m7U0{XE}nYNKKTy@QJo=2ANF z*Wgktn#Ui$EVi_7b(vT_;|&gCX3?|>5ba5FsuIyDaMP~=9^v|gWqg63Dk*x9)mT+< z+}PJs8p=8CK?)<@z#P@}KBcEx8-!ehdGi+gG#-c2JK-(#oMNU|zLgXoygxXI0pfpx zJ%pMUCwi$e4!nlb*K~`fe$`pU>CIIL5J87#w5ydDy>uXqS;sRo84uYt0;b8teo4bH z;X@|c8r~TR8@xB$BqtNEia@cu=FF1N5UqBs(EYm!?_7`-1T;amb+Yh)QzYBG zU+2dov-dyu`p_QEM^<$Jp&R!oPHD&ozhU$WliKXPv?R%E_8|sKsuL`4THq@Zu~p(J zkmG(4?TwSSAC%tL&`Eel<7P2M1hHAFej2h|NLXG>8}xq%S``hIeSj%^Ci%zk6|+*V*)eYq8lS}f^87WtZK$Cj z3Sm42TO7siy|+@_3_R3{Pijhq921vKp3Y)COsIOnqn%zrU)()06>NFmdT`;95>{L` zWvu8-uzJ_!xa0W!4_i8ERK2YwQGQbg4G1&P4@{Vkv+!xCAFo?RaZ(~S^iyf0{WzU( zzMKe@-b*FHE!^p}v_Y?mT1-eOgS9Kte8LjXkdPguaJ0~dZqnSXvWUOQ;7f;=O2@E^ zX4~*^d$n=lALCz3#h(c;unD+ng#K>bm8BqrZ&C`5Xmyk7$hikS$lTN_>UXxFsyZUl z_FaXAU}oNONFSGA8(cF<%lcTiswfKi>{{2i%;pN$6f?Kb7|rMLm#R{($Ut1Z9^owH zVtU!>Q#cdJkySe-CCNE0gnzd&1j!gKhk-|0hv|^vVap3}DybUq#h&)vmxP%lg znBZ?A|DC{{X5U5O1l$wLyM)M2CV7R%!Gr7%1n;RP?3>bL6itF@jt^-lxrffcIqDY` zMFN#;rw9}=y~`YLBZP1rIeyTg5g%xaU4zXE?*}$XhR&dcq;4yGyg2)`+x`-!{XHx< zy;+AP54biyRZ{FRWPawasOI@OH=ZzNtwsdtD%!Y~IT@)4dbX5$KoYz4!t004Y~&Rt zAI+7f%uQJ4OULxOGg@b6cV^7opSq8w!Hxu70>hU}_bOeIa1me7P4LsbaHhqitn*H* zNGSip#};rsT~GOad?8`SW)_|J~*J-OqDh*Y#xjS%IG_)?fhc9g8z9 z^vQkSgeQQ?5|KS;F-$cRK(hHIESGV&I)DHL?@1o^ZJ}2tsODWvlEcj|X-1#g*MgOY z2ZFqpiT%a7^;iXp^E^ppG;!l-#eM}5GAn3|0yDLC9ZE{rAox76TVhwy|Me-bA$Exj z{#KwrUf#t9-x6D{|5~)clZ6Y21-zyN8ex-d{q{%v{iIu^InpEbK+j*CJGI-owOpst zL+eD;f3&ZxIK;S}g~mGxTo`2XsR9;`P+Bbd-{D7!wM1B!2UhVn6~ zs#WWeH%Sd5Mh~hIZ%iiqS1dT=M{O);nf3sw5xR~frad9-t}0+;9&&UjLY0e7Oawo> z&p+<{RKf}6U8vC@o~{?<)i;vit~V_?-R^2Y5;6Gt6$0(|YTp}NJ+aIq55@Qapwo>$J~`J#y4~8+0F0W%R80#M6H|Sg)D46veCyxHYubn zZqokY2`qPFBQRv>|I}2aS#<@Q-hbDW^GzYQYii3fn7zv^JxhdLn=Nk_U6MmFilVu@ zx*A#`j=;_x$bGd(X*wXq$bg%`(0Z>nJC7ZBs9m5nqgDHzHQE&~ zxgG2rn(RUt;l%DucR5aTucbXY2MPSv8k^NSN7vh$7RSZ2VS>iL^ep?9<34erA(~>r-YbNa4fm#Qbpc=kl4im*%MQUEXyo*{MNNqu{AdGR+%fM!oMX&g|GE%edDR7gKyES<5|MKR!*}Xy67t%S!UCJ zOguFr9%_yJJSN#l%2y7POg83)e+kM9>(P*Ham^ci#o??mQY%?m!WVtepzxN!Gi)ea zK@gu!vf%6BlT)?B?AT*gNQHk$KduR@Z4{CWK6rr}U>Kvf$j`J`y;+OQXAZk+ zIJD&9P#~cUWdu8i%U8-C@@4a1z78adiPgKsr}~p<(waOj&X;AQuA}uyIOpYXeYSC# z^EPt7$>a%J`Wm8=vKkAMf81yYWANF-Cd6%EOdr*S6G5V@%6zoCS`}fljF%F#ovEv>?SGNTs+A)tTJ& z$G@$Cdp}$-@4UTIL*4Kz0B_AzM4BqSm!3bTD1LD~?CARbnvq@GMW?&`x1mc^Fi7H{jjA9NF@G^~ekauD&kTlPFC)H9Q_l!VskA?PH4 zcRVk@5u9#ag)%bn6nQjuAM@NpZ89KcvO%(O8(3tG%6^xQ?$Q+iDPtz;akYW-#?qyy z!;i+D^>WB&DTO1-dVL`JE;&n8jbHmaqEWV)ZeSTQlBA?K;QduyCiq%eMNb*!5*9Eo z3y5gA)mq|9dV?}7$kv`~v3O^1S?k+WoGxSHsk!ca$m>+fSSK{Bb2XiwlF{U5TiYYc zEF++KWiWf}HnB#Kf!m0^j1h^!skE4~uPQJ94)vBLs!t z(=Dt1d<9VUe=ph(E^NC>%0Dz<{~W%|wLV&)br}5xX6%^7dFVXV@Pb&wfZt}cx|+Pi z<(hj+PrclRQ>RRXt1ofADtl`_$6=6suw;J<{9t~zp$rfnF64^WPvh{Wif+$qX$ z;t>cc%Q^u*|EbjBMUKPb;2GqM$Er&d_9k{;s?Txa#~``ck!nMD#A=AivuX&Z+Cs5N zKG(1vDC%1e$u(Kw>;S~6d>S~UwT3z|vxThQ+yUOB2A57OlU%TevxW`kW-%(emyj}g z+-9oNIv7j(hUe6{tBv<*TZmylmkVTD`k z(_Ku8VNGnYH(w0+!C8&oZ4EGZVLtK56&Vcv*HADqbp2eLcDOqooc%0~4oO|*jA)|8 zVem=R6l?Ac;$rW!=ZlxV^-&gD6%9514rW0OCm&O3lH1L+*$r8gyE!WC{kqy6y0s@r zI{)>_CRbI&YvjM}s{XqwejJg&WR5;=Liueve-DnyA23*3+Tj{6z7fv58-K9WPuu)? zZv?Emv*5JZht8~>FuMxVR=8Cn#Nky`Be=R(2+i_~N_qQ3&K(W7OKJ5s_x&@_xLtIh zo@vU^;~-S!2%u(=owB;?N`z`_E7aq(g>JDC7Kjm6;RW)L@uxUDUOhLe9DD$)pOLYJ ze?xtu)19g@C3z&oDW}5(h(e`Y4`>YP(+4J-_4uah>V}}x zg|V604ee%@mG>zi0X*EjroRV=Hui4OlgMrQ-)giKDL#FA&K~xLwOr?OMKs~bR3(^+ zX(MqqJzal|3fok`6r74W5vOs{G}&o$UtO0z@@&7jvO5@3^2 z&?2ExJ(&~*fj(t7g&Mv!kfX}kIw`}mTuX)cr*7zHrA|bYU#a}ouZbG(Q)WQDfYT?1 z3$8=gIiJpj?zn9!S%!oLS_dlP` zi!R3v6l3PgU5;0pL~T^U70y*MQa?z#uVOxhrz&#mUSB6BljQapXAA5{eJX~X%2)!3 zPVk*{%u)jm$+SkB)2vb+7=}4x-`tFCr&=X=Dxc>xBq$ znScKKZToJ8w+)T$z*IYizhiQns#rA5`miRQWbR%`l2PL10z@FVqEBvK;&h4=pii9T zJ2`+MLIaYij)?jG)!vJ@&C}nnntD{qgVkRuG&4+Sk`{N*=3tWi(%F7%>ig2F_-i4(PD_b@WD6JNWZ`*8rE zf*a|uhOc{Prq&5Ot!;5#STV2}H9=$-xN_aa=0mKwu~W_4D+7pDWWMNfPR`atOCI~S zaUXlz0*K#^=Ax_enQ|(7O`WAS1~roA4l>LHK5vHRw-TS(TehpHIMS>W-kR1*737WJ zeyg_31F<;znYQZSR9;{Q2qsELpMB_D=hrOIQxE}mOmm(m+@@7W^`L0&XKxO>-TDdf zd1K^evv1Vs`u9N*-|YrfW=C1qUj1O^XP}~j8{+-=#S0fmmu+y>y1lK=;Y8+ugxTB7 zt``Lu2XyP^;gJ7&n~NzIw;Qe5iv*jj6`JUCgyV*=oMJ*xJy&vd*vundDm%>>HaztN z=5+R{PelwS9$FQ7`ChI<`w7NQE8c+wg1?*BVy7$pEYtkkx0u+4p1Ng)2_RBPO3?sB zTrza>I2qCzM<^LzqDpZKhgxNJ$mGB~UZSWKvCcTT{9=U~kgHNqVVx=6CMWVs8i}x{ zvzS#^*RAfa?tm2x$vl(EdPWi2^*M(!V4UG85 z$tlVa8h{&LSUmw@@#>Evif4SL+^_VykVQ?H<*Y4Q^QNjja$xLcBumUwoOkLfIpFM3V9P*^?%`ptYSa1} z_}s<4{4(bP$w0TR;?W6^s3F>FyT{#i)M6%^=-*KQ_Qehv=bo;~8na6Lmf{)1JQH9) z6FT=*=qtijF{ulz>K{)wyc{T%taf900aF?n<0JkPe`@AQlHvoGR&5Q3pHXHj6S(K>!s2hNeG zj8p%Y0!*Nw#n+$K8Z4oKA~J)Xzh1n9ko8|b-mMsWrU=d4nuD3&UE{}1sK3GqHD&8L zsvB#0m21(?PUau$Y452OEk8HNZ?OfQZ_;ncpFL|2p70TI^0yoU74)lBM0lb_03t%$ zcy(O&0>l*Zj%{wHYs1O0oNOu~`EX|&Ec>K2_@(hY;H07ikhi-4N}t#tdZ{}r0_Zyu zGp#q!HD8-5Eah&)52n3cUs`9JXkB7gj4HDf`!GE%{$+X|C!Nt%Ji2+|Ww|wXD`~-l>y};qj@isjQR~oZwiQ{+lwuT~qZC5yJ@Yf1UAR zvq(%@T4ntIlA-tRsVm)-;p3+8Ftulslc7FSl1o(1=sGkohTEf2r)4zK1E^pd#qgf2 z{~!*{Ax`%6Z?+t%StviwcAiO{T;1+qt#e;boU7*=vBN9j;1izn=JO*Ud~+e&WDTIu zgXtw7z%LZW-7dX6EZ^-)uNoJLG)&cF_>^+xDP^&FSi}suF z4&Jw6gK}faU4a=}ocX)N0Cqqf2U{e?>H@+@c7Px{su`D4mX20M8Bi5X{kC5cg*s3A zlvppVo2*{BdCOd0_jiHtL~5`S2c>T)*h5sm*o-q9H$P7Kvh$de91V6YC`Li3daaxG-f_r zSHTHn7z8QT`W{m3e(u*q=%f_%30+(d?3M`<=p5ChGMydd1&9v;{(IuKc+RMJxg?|ZV6WB zsY)}=#)CG#v~eLUdp(&_f4fLBs~JK~QsgYCUONc$KmM<2_aNsElw(&a3Kd^I57XEe zFQ|5dYWr4i1-ec2h)EO!a%^}FA_Y<)hTAv~-^ht>PPwF8)9cFbmm=TxJl9T&o>w;` zYy(dTDUqD^7gkzrDV82maLFd!i)J+mc?fdzso9>^PC0!xhO_a@xTIXl^w~=PL{fLM z-^$IZTju;+E%l4b&$nW zbz4LL{>6ZYl)iPQ)KINA`#)g83oR)>eXVM@kvG9)qxI^tIeL70iO#8y7d;9bdpl=6E=dQJ(c71YwD0}4WK#IQG>O`jP(1#0vRJYy#8ZP@;%=C#p zk$q}RQgR#a`h40$!KIlC`O{9At}c{I_&k5Hk|C6NsiI-gj@bw%5tu*w5mpe4e7eSD zmIw1ageFjIN1VPxt@v3t@drBzo9eJD`!i;zueZf$4(^vt%zN4jC!k~~-w?*kFb`sT zllp|uHN=tg<;xJtl2t+>$?r8RqMizXXv;c$Bvq35i*XfKcegOvkL&{%_z8NM?$Kf# z`J76~YA&6o+R^pBX?M>fBj?1)^8Lv$_L|}So}4wLZGrDT)y~*vo{2qPhSK+;|1mR1 zH3koq$Guz8=6h}mD=7Af$s@lKiU}j}ASRql{ol^NH}qbwP~EO|hPhNZGrvB-6HELh zS~Gu1Eq`6oAG6*PET;TQaxj`(*kYtTd(-{huYP;es>zANTLJ8fEBdNjk$m5ZJ^ zIW9*!F4Uq96UY_>iwebcACt3C;`9KcAjKf2yltv?70t_bWGck z1gl-16S`}mw!JHH81BY%^#1n5O_5#OcJoo>k7E+55f7Vp4<0ak+`v0`g` zoFxipCgtsAPgdH-t@arLBMwr(GVNLNLe`M1@7Wy{L|!yD2$Sqz@3+df3Zzb0@sYB! zLf&l}N4y?SZy%+(mOKDF|3x@)^0r*9wZvgb=0c-!x+4fp^BJ6}%#@5|53g3M44jeL{N z+J}6aRZQC?mg-f>k7*_@G`%25=fE0{dL%UzA0I1KzS5rKg(I3IG;8vIBpDzyht@^O z?vg!b!Qxi(MZfr(EU+9nE5T~lEoD5l7zMi&gFJPXByGWB(ETuNr%+=WMiTCr6&CK? zcbc7Oq*-3L?!8>x$h92C8m2rOCV$RbxnJlR8VPAn#7%GYf<@#}5w zU$lxD4Y_&!s3MUPJ>a~^JpiHU;w0i%{KWrDBHf!hh9qNDZ;aF@KkE%T0xcdAhqKrUR`yt7w1A(1NGbyX5O;Lsb zkGd;B3hlugyO({N4Os(MrCj|S#)$*ObEak?Q-MGx_hvMFNq$~IQ`ntPg)b!~_KA0+ z^bmR+DLlHG3Hh*f%-VJm+o384%l-wdn7TI6-p1~oN2z*U^sUL$3-(^8+63T}7kVVy znoQ9r9@mSJiFqm5>7u^-jk|43MzvS?y}>3g%DZ-wg`%SW&SZ@LAjQF+Q)BMS!UZ!D z9zr(AiT3Mp$Pd4Mx^3Yg!j7_JFsNq>V&v2nn4DQ0V#>MoIBe6(3E#&qC}8OGOAj)7&DwzJyT2x zhUA~w=ccx4(ZG+ulaoWuSyPg50a|08RTJ;eM-lKnm1e_9nhBEcU9vSzAMhrTMww;5 z;b(X5XQ~BDO}q9p)((yc>@74hk2%CKgvNl=CXc+#cK8iX7#u<+NlKZe0dRb-}>7O zYOGK3p7s_;@js7&djsB%qPq$~=(es&t#=Omr!GeHS zOdnj!MtbT6i*$N^FYrrSaxx5WdOTpo)>!6?AOXKEY)I>YpF&AgRF=6b1HqP{ZRP)~ zuIyRENAG$G9#*l&hM}pwKkwoGnMeEFkXx zCGFlYZ&u)YG;nB&B^&3g#MW9nC+~dPi*kQw&z7_bWQ`chOcHo4_Dpz5MC>ZJ*gBnE z%&Vo`y5>vPBcfQuU3O8l^E+&}*u_*#OIYoXM18!fofAH}JGIDhba9KdGVOUk_CnOm z3qLyaDJ{Ozs<*06)EGe?*bzR!Q{9Kw^e)y1SN&J_^tT84MpHlb?KQaY>DcqpHU~;~ zy#rx6DKoQPl+gEG(;Q}fXjmGSeITdLA5T{%SR+aK5rtXYX2@1{%T`ORsG)1+++KMq`(}HB3W@-_90M%mLp9H znBv4xPinjqLHFw#JY~tz{k(oNNHH)h&$USw6sG*o0s37Um& ze}`zJ!M^9OW}L~!rlp2EcSbq*&9z!-mq`GFp4?0Kf$E(57gD8_uCS2of-70|Qyl!L>my*RhH zvN_lu7!XUIt(l_vM=`AhnM;Kn^bl<_l(C*Cq6h(E(}0Cg9>o+ukhf_;B(y*(GYcmp z)|`z+dI`ep;pF)o21shcHqu0O0yGad>QLkVCM@tswP9c2W!^wWy{Ql`bC35;qHWhz zht!Fbrv0O6CWNBg1@?>?x>MQ98XtQ%lzBW_(^@Tt8>+~Z_a9TPr8Y>uneS6PcU}%C zLpA?8_y(q20m3B+CuRv58*bp@o%-i$2TW=Q(P1eT#@Wcj`Ht}a-b^rUwR1tn?z?%L z)BH$Cu8sEV^)Xc)k zsox!E&uR8?J*`Rkjwtt5=g)h0uPF`WtHo}cJx<|D#G(VX)GnY$tMAixQhf~}l(DqH zpkm_EN$8&K!@p+3-&<5@S5DWAcWn0az5hBm(!#7FYR0cWn-rK`UV6@C5(?yQH> zGO^mPG-D3~*>Br|{nFgEA zo*C+nsDxO;ce`xyWTqk|`zGZ0!mvZqn?|jv96dq4<1VR6=dWwiGZQpl)Abx5tde&5M!Q|BaXV6ZFi|D zEL<0mG9++62dCnwcJ$=69t8O~Na$;=#G#l*=8!EywTODS9ccJ*_{r9^gMo6Hps=>Y zqhN83s@TATtPaDVtQKv)xESt|OyG|4yG**G_&LBUSyp*@H44IchrQ!{j$=QE4T{$)>M0i3M zNU2^ktD7rI!Eds8%b&m4pW75%e~{`W-c~QA46@01Ys=BNIhIwd)vv9fu}Cz~7rOX9 z(Cf3>{0Y(pysW7;o(^4hbj_ED zL8s#9LUcUcmIq3wq^LoZ`)05-ENrq!cse68bj6P9O0vmXJSbTt)z|Q-+aXuEg*hyP z!Y;oj9OQ!*x%1CjCRNJ+K5Tzu{o$NAC_VpmPWeuYdOimTQpeThwjD49 zsYqNh@|zb+nr?3^*YGLxV-`H}zdJJSNw)eTEV(?J9eM_8j*?d0wV@{h7V$OGk4cL= z&WyR#5Y79R-iYn>$mr$L#3LQ~p|Mjw`b4&LomJV%0szB9YlaMci8UgcmW*Y43|KSJ ziI^Y$9BVZWmvdV|)mRIkVO}>3U@dHbY}+^26Eq-aI3`Blwy+H`O0qO7SbkwK(i07k zLIqzqc1(8YCz--k*vnPJlf^`-kXJ@i#sp{1Kkr38TW+{yB^@YfM+X$g9R(DGn6P=% z?QGBP%9k+5avvIOjC3pA505enfw*3DU8v!)9nEoj2EJ)$pz7nVWzUMxC-0Z=qn@tu ze#x`VtN5|qR8TD|-T!kv-urQB!A(Ba-~coxoh0L7dfT|x)$bvvBZ@KnydJf_>7tbiv{IJ#ZvQ^y8M-f8ALs=WS?yx0Oo@%p6&3xcUh1U(j?Kn zSL_Ow>Ne2s233M&#xT*|25uelJskW;^~*B@J_f-7z9H6t*Vt{_@gzL#n*%>|HTW?pc)8Jjn4EIir$t@(g9G0A!C%g-* zTId%J1$nW`q@2d&504Q^5&QB?AL&++a< zYTvF`@3_zkl`{&eYXU_R>Ri8_y^LWqJ+^-rBm3~3@S9{)dZ1JGx3lbT^A`X7nKWf0KAuE9!>+}>4nyc_n<}I1LToH&qm@Hx$!W z>{l=}S!d4pn8;cVXP)3282$##84#w6`cb_3Sk5YkYB2dZ!zjYcVZJ#lB2HXxC#{-Y zNLisOL(`qTM7qhMdgPbL>G#SY+mj`hSy#8noh$lliPVxM)ibWS(LtFAp7PD1x~w_@ z+MPrqCHb~;!WJZB@HtlVbc_A^&wH6`BcdDt7x#*UE%gt#{>P)ouF-$*_`kJs|CdVT zmCiXE$Ait>T04V^W$kz|K@Y~$E`J!r_4f5h9<<&~q+;j3tmG}9<2nc8^m)1upAz+( z7Hd%`%Hvvzuyi5D%HK@ehrGU&o86M$a#g5g5?Jt}PwbiY7wF_z#&d)Js1Fi^$?{zI zam5HkWW;w5toniMV0J{hIn^@2YcXak4ue7k&no#ZSpZ6r?R+0yV_h!4gbk3YMhn~nPrO9g3mfK)oQtF=*)}=MH zQ887`!ENo{SKLswxTj&NG!-Ky>n0K=20(|J7YXxAya*U@omMTF=qrvH=jOc7nYuyV z!B}p$BV0mmxKSxbBmewc2mie>^8S@usH~Oe+=C^(I}L)ab^ZF+t&26kja=y-6pOa9 z^mpxhbbOlNR=5R~Tz~R=wp(ddTFinf+b{0Fcs5`?St4+y3MyDH*Tuup-cp#Cuz-|e zYvwzwOmm`8?`v{)#3>)qsbx2|N$2{5t-YX0J^+M&BI&j#@Jk}v|0w2@X?&K$NB#U% z=d4|g@ItCT{OZu8j;v4Tb(SP*Iq^bP?!Xwi-HTJHyAT5_12T|SyY`|g3<)XeSsv-T zaGiIFB;Gqtved^3RIvcE<~ z<2Y|WUyAvDhXkgNtU>095|^Mlp_Q$JedEB||>CoS`Gpx?~uj%HyrQkov#a zwZ+{vN(vdLrERVUG%DRk;%~Ty7+=uf*#t>gO0_g_#VM!n?qMSgHQK0lf%Ss z(&;8=Gt!#i2UrSYw6o==qr|swgaOmKwne#gBbx*9fi9R4tUaeT5}o(y&wHWAsef!P z%d^(*jH_q{2;2ja52n6cL-E2pR)=dFxQ+Fdieet0$N7n9OT zzaoiz=Ejt>_jZh#|K)+$x)2vBjd1J6r1Jp+ntGFhM0f*Q{lqnNT%WlEyM= zwQgSEC^BX_2m5%Wjy(rg*C90+@LL~6{OZ@17r18v%+aQf4vN25XBD;{zmi5HI2M1J z%U|vD*M@As=YBKoQ_OI$L$v8?%ak%9Cv2Dr)gGkPe!(oOc)p!w*0Yyuy!EwNmg&QW zc03LEZ-7EKJW+yO>PsR@qp9ugK=J6kL6GfDv$#fyAazS3;*x10)bInMK)$ef#@|5L zu51A4^R4B@#%^@A-FkX$M@ba3qD9;BgIQqrpZAJx!~$9UoeesIsI#}JF&4MiTn8(a zPcJBx%Z-C5k(TR)dzc6)KH#}S*%g@7lxVM5maIJy;&_tn_6%<{Zt?EYO0>)ZpUaQ1*8`B2t}>Cj!}WW zA%VgDTMLJABX|o8yPJE`wB!Ym^nTh-@!z}huPZYaMTNb=%LG77>rP zqgxVzu2{QtL4$(wGR>V1Tz^U#+uVrIZ__gA6)=~8Eu2Xw1!z3;?9Yns< zZZ2J1%Or#~OGdRmnB>y)gWw-oP--KkC32xnu6IP+yXH-Pk$Y(K(dP4~e|6G-u>5gw zHC{udE{u1lZcsG+>t59za6@MgL9iOrcJxql>iAWDKWfLP+wJU@C5WX@!F($-nk*l@ zzgQc1)9XP0FGswTbqaQ^yrJMu5|!w0Ge5L?-+O#u^Bi7pGagM}Gy@5htdIjbF?sM` z6cg{uQ{@4#OxrbAkDa{nn;QOxUy*}(dqq9`Ay$o9z1n=O78+#*yuuS;wSK`=Pybkm zIVG}ZjgNCiKCTeYXYgzBrnHa@Z?!7DNwFCJl{Al{frn*;N1L(J@+@nZTQ1tGk2toe zKGWt{w$ZBnV)Km2l@ow1c2zQNkqhJ%ss^e-kAM%R3X?l+Bp%hNbC&Jj*a=*i5i<>X zHbbu(aL}mBxZR0*h~R(l*k6_&j6UbRle^zP;RfOriefDKq^DeHA2YzDNgbiZWA}c5 zPVk!A$3sNY&*C#q7>V`@-p~{OwA-6B>~+@aNah!^IgyhWcDW3pEH_K|45#V;Qr*^f zGq#RHEbP4jko6p-_U7pm&)*pYb7z_whP(RjNLo7OPrJwpl7Mi7D4sL_v4IacMTygo z-B$(D#BC9^1(`J|?!!{vy*E!qKx)42FIq8{Db9!)4DOxZLjhS;*q7Uw2zDXKHz>>e zjZ=#aL(fJMZ1+u5cHwm_F+e!TiR!B_BB=X&wTg-ts7<*%DoEV%w_Sn4=-EiL}?LQ zz__Qk$oYt8&wP7^j|&T%3)846vm%A>KHI@8!oJl{m!Dm#uUVt~dyZ0VN7gTqSP^ZZ zi&_dTEFjgxPAhYd?Et3!vf(`csZ8qb%|=?}!G-sU1zsgxJtQi4;`%mW*$#wCwWnN{YGJkmmQ zn>O$@z5`vriGP*ZI86Wzlun!&XLfuYiXkWa2)1ux+k5%X63F(fDHq)aK_Ny#G`?ej zmkXUfo>EAqkh4dZNXs-YBAhO}+G=5!i9N?GoPOBxQ$4Eh>IwThShYtCmo1J*d28%8k5VEScC5 z78&s3`Zlr0%%_77QL+j5U9b1A0pi3;28#O(2k|)qa=nRdQ|k55J@rq@eK%}79#d(VviX2FNo+65ILb~oxe2EpbQ7PKSJYnbo(><0v*&N$Z@HVu;370v z$OkHqv(g@>_1Q^4oO>l}36PVK#kMi&F?gysiL#H25&mSEI=IOP&*N+r`}(*f>S|Bs%W?Zn+P~j8!&?G?tp-TG zv@)%F`Fj%+g;Kh5Ea!cmTGIsj3G4ln6Bs#;eohTZt{%ENbdzNZUu;(19jSmqc&{+R zWYd~r;b~<1m4DQZ>~s1fDQKs-IPifyk^b!HInftk=%^cLIWpH@y4NZ%CV# z@)sT2jm?nxv8IaRX;z`rc8w8n+l?6h2K6wPh$BItpm~=af0Nc~zS#ivx%gq-JFQBW zNDptoag51@aXCUrU9G%f34c9_Y2gc;s}jT>F5~sG^V4L1X;R)L(e}$x1qC79G|Sp4 zm?aK)3ZBWXuHh1`X>|G_!rWH|5KmU2}UphtGK1IT3ho<q*# zdZn`H-_=%WsAzG)KE!X45UXanM~6{$S;~^vFPtn0vu}dvId8FRd~wwS>K{E0A*0+o zdx_1)jvlfhdD|UH_Z=+R6OUj8t$S3pg z@$<W7cL_bG}$lF3&*@n{1sE#C9v=6 ziwnq4urCj#b|kAfjV{z?^_t$^^sE-E^cO!r;3x`-U+<`!P`8Nu?C!aCoU=uXzh-xf zn8S>At~bjrFpg!e_C;1`DXx`w%{L3fIP$?*y5WcMIrC`|>wyP})h1uD2NM6vH&3$4 zm>edV;e3SZR#P+vHR_hvNYi?HhwZ~rY6tGKxi;AM@>#_-ooUK^ODHRPO8wVn=~llx z1gIrt<4|P4a3Qa~SG#c9P6}H%9&hv&X~g=;A~I5g$Muga%M)8WiFY=;(BCK-+*Zj! zA`FdEspZs2XWAi*qlK7WyH}VzbBACS^FFo{#qNy3-3N#v8&`kco3-eX9Bmf~4HLJn z!6TGII_#{#3iX5sZ5P5Ln^gQl{}SE|O%3@cnTo1hbqoKgm3MAI`2WZKKOCy-TRoa9JIoBr9j3>c36&5#=|zlHmS+VlE_maXT8o5wP&mE$fZ_w}yF;-p)B>n(a!FTW>` z$dm=rXAIA`{i?Ae_#E7M-{{ZxkMqGYCd zNcHK2*l`kPE|1<>Xo;k+W7oRcLQE0*yV1%9S#hxF}VPo#`=VkeS{D-Xm zpG!Ync{Z|^YKVTluq;@h4O4XvjDU|wD~FVUiv_AKUX4=B zD39%Yj1!8tXh&rq5VRdfZh?lw*F8PD;dait^+p!M;f-&ScN&LSoNGf|BJ=VGUKW-# zR92c)EZ+gEN36F46^`L`EMG(I- zZmO~dGrpRy$B1fcQ7my=S?)%*xKsaOxd&lXc_l-g&UuyzaiR zI&v8CXhk4ykQT(&pK6V~fi9$bl@Q+wtUwpkLm&}is;1SN_1_H}hIF!!9@a<63^+C`&{Bf|79>160{JuvJTe8{u64~RWX`okW35aq8 zY$(pA6G_W_@XQ+CKMYaYZPF2@&(=GWQF&K9tBbu15Bs>4nq{oZ9WjgEW?F+HI&WbSRyISrE-WtK%0qkj#3XP`C2QQNQJpp-GL=YPMaX z6PElDChOj>gJDkXbrFadvya6)JGcfq`3_L(9i=(;o&=k=MK|9)KGcJ#^b{M>!VWBM z&RJDbeX>_2lZ#t+uJyB+2-hhw{LHXYl%m&V{Q+W++cTLwa+f8VEq>GayNr9;X5fc#WhbHB7frrAP>QZ>2 zckSkwHamK$mWLJjTSqf6{X>9ok`NlN!|Yf}A6si&7JDmLdzA7U#fduzvoM&fKd!6z zNngQjp!ZJmVA1xFPIYR2rk~+u3^vIwxoX_Z_iA#jk`q^?dn0Zq>#>sBAStRlxu?<7 z{{D(PbhoHsv4h^%YipIf@DX3~^cLaaBX#XwUwyLf5+qr*IM#fEQ&T-GE-92}t+2r# z>)yRXmVc@^rZW0JWAg96e>5R*fZRKw>@^2L#~FwU_mjHH!ON<*L~a$wwfB6>oct4u zLs5F4$SA!x)2IsGb!8Q+>7b-KvE?1RgguvaQ`)Id`NEb8uH&>IE#=Cr?gl~Txab&? zJX}5Bz1nKZW80@biMt=BY47nu2h5r3Ljn30`4(N2fST|B zo3ZzfN;7-=z4Lo!GMN;U7?T)do5ZNGps`>@J(EO@8a4I~V;2;O4aNGK#MsNI*xOi% z1uKdQ=)@XDB^IzC8nIXG1e?0Z4h47w%hT7%C;O)IkzP=7$7pVEOBph!^&7; zsw8fF_{dvg#HbpD^bG$zVXFj={nbR;xn`-=;;I84x+Gt(DW7vAws~AXU=^)@(&O^*>B~SO#-7K&Y6ty{vIi0WMGOB zS06JzJJ{ED3Pbg%M57=&b>tR6Gnwzn+09MAU8#NH1mw9~!21#|#G97-)HFJ66jrSn z6qz~5w(D;vP~NYbx})fbgb4BB0_z}eHbRU07|yd(0Er*l#(dTc`sbzke`d}vj?gDX z#$B~KaGlQd0RBX89Q=vE_FCUTy4KI1|GpBsLNMzViP`~8;a6~5dx2o17V};3_>!&MxM8`r<;w`?*nF}A9&>OZTRE%ja~>zXw0jInUraT@~k zV%{X^$e&EFm&4oRqu1BAX?B0lrvEl; zHJu6Q`_wM8Ml^X@5M3+1&WNmOEm(7=4i&o&I&)aZ8R`+uNJ%U|18=+ z4uDqA9L}wid4jUbPwX81mtN@>J(|%`pih|h*cQI2G+3ta?vZ*t<9{{0Z!`uySEVfN zhdo);`Y`0P$b6VYEMW+A2+n0HR@$RA$`TGW18XiAD?JAeZJQ)xDdDd#3vS+jD90o9 zW3b&5ch7k{Zv&T!z~#Uh5#GQb6>T?IZfBY4h{-v4qZQS5-cK_>B%_941!kh!ZT-gy zWT|WFz2Y#M##VEj2rARIEhx=k*~d0^dZ5Pqi>G)yL z?fdk=I$hQj+5FYualLPx+iRU2ygbJCI_6fuF?S#CZ71W~d+NeyOAU=!*r?iO20zL) z?vbsSL>kz^Wgqsf<0VcG*f@~8A>V;=vXyfE?7xL1b$jmUkofm) zAIF$!Wb&vMB(4c}|Cf@FQ3ZCdstX7h2hIU-F7Ixmc8DHdPSETQ-uoR3qz+rNHjPs5 z1>Z58pCsf2_tg(>$j*}Gr;RizuUzH&KiMo}9DoD|wTA$HSt|9UxAIf4k8vr4=}Saj zOvQM&goTV}I#f0ad9hl1msa@6o`OiL+yVOPZ+1BcQbX|k<~_h$&h@MI0)N1^61w=^ zxXsqCplOn6TrvG;G)2_8Qle8T)IZ!wtitb=rG&Wj6FEHauA%n$96}@33fjOka^sAw z>FTMOs&FfZ+e`mtXrqy7kz0`ZJZ-V*Sykv6eCNJ`w~8CE;Zz!C>ye`^Gc zSg%NSE~WF@GVhOWJgff*E$Ug3@0MP~BhzGyp}6}{ZP5m>ZUuC$>8U`JC&IPQV9KjM zXV3Y#b+ZV3ostR2I*u}QPpk03sme0MX)hdjTNYaWz9OAJXBO6lVlpPAq(f9yW@a#M zv&3%(0S!6=2lkN)VVp8}(dW8jXLyv{rX`wn`QaUmFVd-1(jDl4^r z)y(u;ea=auc+GPh9iG25F|LBCE7#49m$t?k%6iIvcU>rmNB$akbtn(M^Ki+`d#TvTVRgig?g1v!HWgpvvxk~(*nxke*Dl=xxtGm zw!sj=uTyU0z^b}W>UG!j+?^JR{w~i4#TwNS$qL)`X2or&<4R_ZL`z37%6K;UPbm+Q z)5s`90QTNxbR7_N;i?PRlumxjOCOCsMPJf=sz6+5Og6*;BX(A_1gq}~#szkh*)n?}mm3TO_3 zdcL``S;NDJ5X##>p+L~^J2}vCk;ih~rc=_VjlIgVgsutf01{kY*RX&1^hPl5DLv7Q0WLelXB-_+z=W0W;=JsYr`MJ>j$?Nt%SV?#n>( zeklnw$l(f85*L{F{)X*pL*q1`75UCdi)!i@UYlFo<@`eO?)4F$$8U#6Kpe!a4_q3i zm{Bvs?xNml!1r4FK%#<^KRr&I0Mb4}_Hv&O*m%>bj#7_x$|Kk@Y|QWL3uYy86zkC6 zm+nLwMaSzD*RL*au##!QRfc2#f5k&Td@uAcPF4g7?-;H8I>w@M^zIeo&7}(<{lo^F zS}Vq8yEdz^Wz1(*Bsu#1*&=RhARMf)hs^)<-D)A!H${#lA*Zla$Ve{K@&{GoTd_6k zO^0o}U05^4g=E45ob!RE`hxw-bF&zTiKYUX1LVO6Ayabz03WMP&33@jjnF#1@Shq` zuOv~`00Mfobl*@<#_KmuZy(toS@UC~Z-wbnpGv2V`ta~?(*R_AoXdez&6=Zj(;zZv zeR+@WGT~zq7a!JOwA+sm7_59(La};8Y5LIPITU_0U7NS7?P_P$_PLEixgOt7k`2GC z+~3NC6xaG0zd3qkV9`8BT3l9mJ5*Lzt@BlMLRHSaX5)`2y%oOBX;ekd3N-xGiF2AeJqp(cUki8sLGkWbjfc6UBmLGxmyhiTt-!1OMLoLL9EvF zs4+W)&`mxmqSmkMo53$9c0Tq9@+5gnk@su^BA(HpJr`#vCQxa6w0olcIa|2y96@m` z!)lT_$oCq=Jq|{Ba$>c?xzz8B%4vJDFKC|v+pa75*KT@0u}lp1snEeHXAR5Sm>Rc1 z%Y#>}$V%0;F&^5zPyfej;2*zyv>4x1bdX=Lrh3mKJUw+RYNV(^i7ML463UCIUZsPt z5fY}&q~fN;atdM^8cJHKSZ;bSEXqy@egq`mD`t5$edh;_x>t@bS(- zi&eM7WROXsf&42)}B>ED+)lwTW-V^&&0KP6ZGuCaSZb}T3@$pa%S`Ymao zxBxsytf3Elc4_xi{bIeCah^4-5)am9G=CDQluQ9br0-=VrpEqi;U0<|xfx82d|*k} zn0T8}{@c{mw@ajpv%A^LBFXYO)(mXFb2dxDJ7K3Z4`Q|GHj(Gm^rFgE9Z$}?+>_Hx zjZ?-=IOMDj=0H4OV{Q3%9@c8yiE&8RjSIZPJ?APj_jQ{f-0iN1-B$o%$7YvLwv&Kr zHu!|_I~MJOtT&ZlksyzAQRdBUxLwqm?ALs~5Q|N_ZlC2fJjZFh@_U%Xm!|rv(Qaew z&_w$1RggmLaIkJs+8RQ*5R!Xv+VcM2{}?I%`$V|TnITCG8)O_c_aXSFKNoD5KeRF> z$L9|G)jFdhV2FF3N2ZW!KZkPWNsC+57?h44JnP6E3(Z5ii$7q>Rgwa+?yxiX#!0y5 zN}i&p{YFj`+WdK(t}~<)M9#x}+7S z4Xgs#{CwDWbtTFU&ZX)=cXcvZHm?YBnPYj!?i=!3%wI`6?9IaRZWeBh3gE6c&g&TW2UBZCfkYqKa+4s#MZNVo~P`)qOn&W_>u956e z*8gE-yO7h$6@*}3yB$>a7aJk`zHA!nTtU~tiWkD}92Ut+XfFd$CDaYrY`w>tYzENQ zt4%|@ZYdFKGi}#t@V|%7KRpYIjPmpj{qUFZEmjN51}$lo5N4U}vJ@TQ_w4i+5@Yd9 zTfP@#l57y=3n^6!75TKnWV505y5Pq3WIhzvLPV?@hpCW<2!vRUy9NZJ0;TdznZ_(? z+CXxvF1eXpzi)-s9G$cJoG+%1SU^NXhJwQHG^%q?&46TI*;x`^>rjt5sw2!O_KCiv zMCcs}4$|~b%5%8Kt2P6{*tgqwiTT9lW6tSc$?(xuv$DK|xtm@4y{7aq(??0>${~VQ zKYW=R?`G#P!r#}^OK#MC9+>vI*)f~qZ;I0f!xj%To21DkB>kh>~5NU;AjazC@R5e3-C{&g8L`{{yEq7M|D` z>?JiGmr&qqgL|!Cs%&4Ws=evge|?=llc(SI{fC5-JWy&6a2l3aR7=Fr ztfw+}=>#|p%in2qlO`06y)>{ae{QcQePqfpPl_JgRtNNG_E+wkX(o2?YV|5YJjMpQ z{i0crM!V4{f$KexJ&m5}LYb7B3CJJjRc2F7#2|z4kqR8-5Dh_w@%+{D$Sa@2kbLJ7wY)^wEWSbB>BlPVe=97P>e2d_+QCvQ}(8H-)SCjy>MIgjDhjjO2Em!#U^wg;aeY;BaP zd4;&du!CJlGbMX}x&QN!GLEI7prCm?qEbKcP$ecQ@$d#HIa{~>=R}MzSux|@F$x{C z99bT9V$J4>F>#vJoThwt=Sa&wRZ+zKz5}%QTG5*Odm2CddyUX?HpX0ODTiP1hK{ak zf)Sc4j&U_sz}&cpC#8!=#)E?~ixabFQ>M##xt$Dmr{On{(yrRw&{oCV?9;uzh}d!_ zPxDQsb4_K675Px~fkdmWI#DRFCWd3>>bS;bp_9Azv7n!td-nq>!`4_u4lvBQ#ra@k z5J>;psBusC`9bIQ(+7+wRWlgm-l0gh^P_!DtL95L%jdJmR8uNm|B)xZ`_Gd`ceG)E zp<8Rc@5mwOJRhKODW}CHp@3X#_V6$U-PVaUA454D&2$q*1s`mP5{6$mgEe5?A|KZA zB1x#tvTT*|UGZIcPfF!IEEu5a)&~EUz*b`D9ZK1c9i|{U+|Kyq!y?=NT`YZhQ*~<%gY)}Jpqf_%onzP^!hLyAU z2%YeuLl3RhF$d_cwJbf9Xn_^Z-t%^}u?Gvz%|A#AI0&tosof$Vi1`Db`~C)^6}7;%_VLAyb`d)rN>rt}Pakj~ zX`^OJF%(>%Y@o2^t)i*dUmbI#Y4Dj`V7inU*a(`lQXeD`O>nO)EF9Zc)H9Sa0$hKj ziC*d`?xTs^hMSk7RpLL-vfO8|y7!j)lnGxu97?j7i4ulq*YWh9DPN2Z_H@Q@e%@te z>iIIta!~?~$+6=)$-_{m5g{%_;kMg0*}yihNc`c$48P{LZ)eePd6RG1pT)hd|k3DBPK>C@I@*)S)0nc(eS*gbU$ge zY#}wSQBV0(+rDVju0RUTyCg*0=$=oQ@Y_K7Fu$8-0_g`>)88FjXS_faAcgNO|3pkzK)Cs~1Y`4hk=cf?+=@`XyHfGrqQb`G;WspTj@=DV%np zr6Dh|6P7>mL5L4FcWy~iHU^KwS4jD)va3%-FPrtw48yv2saqH(Q9lP{W=knMQQz)8 zvJ$^faWD$z@Z|(WCbTfj{fNYq3=B6+IO|~T?<+$dl!HcNSferK$oZt>_kDMGh(VaQ z9rQh=gl9O+PZ%BMKEtLohCa*znWTX{m>K9UWValx>yME=bf=fOS6jocO5H21Ho+u)9`4d67zB19C6|x#1pMyr z?QW}i^I%xZwe>YLmu;u)uvh=B(Iml2R(mm6DJS=}NTwL1;)hwK>7~xl zyq}*v+Rl(Sa!&0542h*-B$LXZ2MK}j2jv>aXdquX;k8->N1t4Kdy=kGl8mi2EjC0w zYw!yzIZ$j$WDm9p4N~%`9PaJYC%YkWH9%3`5mGXMf{GtB81du=e!7_;nOO1IeoSy} zDh(VX9!N_X>#i3J(rVSf<2 z)s5ojH8d5=8|ovGY(b1MH$VszG^D`ghAm@ORs4KB%pF@f`kEf(>NrF~LTk3rU{M)T zqD&a*m0ITPeea4rL+MbHYDzLeiX#lr$Ay*GrBsm}%6vtCWTs9%O5>N52vO51o?U;aZ?+Y7j3w6x17+{?0*xa(~Li>H z`8yATlqg9p!j_+w3qy=^@)mFvDg(nwE0}>AQ}H&DTjWzt$~CPw}NB}VaGW_;<+AE2Z=X&0pj^* zB28msJ-zDP_j{*~(c%$HV26o}*gPa$I%LtLDv&$Cjj z=|}xb?D)5gIZKf?j0qxR$l}8DP+MGjskX?oU`@nRw)IislI6XDVIBj){?~pMAL7vL z@T;3Xf=n~J(ZSX_e2@|w=Erb5+Cd766#{XO5$=;42NrYpfsbRS_i~sY^ZcYWr`%lE zWO51hTPAOX#?X|ko~$e_`)mS@iJp@Ljsy{&jyRx6Z;Up?@;k5qffdX@2miVN0; ztO70Q&Z9H!r($8xFY!J^tLWDVoNwl8#A}2>yYzt%bCLtx4QvzKdV__$NjI$Q!&FBh z6W`P%cj)4cP38qGpFV9aFn+v+aFyFwQ!f3_+(47mb{4vmZtprr0#p`$56B5@3tLpU z@yGPL%pfBTXT>9*2!dZ#Y`o6S&X!K0Ql=u4%x}v-TJ_6+of7|JR5(`ysG+Jz`3dU{ zQr;QZOP_dP@$u8pX!qJ0w5AqUd8%6)Ol}C?e)6Ab@%I%@UN|>QozOh`QnTwfJ@jAUApb5s&AU+ZHhwYGB_Gp6q9e?g^VJtpbD$Tb{4QA9>|*p z;g%(j+6m{JLIS)f*gehh{^#m`*P57)4qw%xi4sXvW|NjYHwl9>MTsWZrG|riPe`9={MKD|;LmHYPkFpDy9Qc3qbK2oL-R2{ zp|7+;o)LPZJ)ad%Q@#j3yy3MBwBfvs8-0@1?Vfp6fDIpdaeVt}m`D9Ro9FR1D0$q7 z0)M4c*{iop%V!kP?ELy#L-o@+k=^pcaoU3Jk%#UQHIEnCu$4*J47|wg;Vzq_%jVf@ zVx@(A3R!CG1Iq$>$$wn-Ogbv=q8kVq%i`6~63fVWB+`ipzgN|be7OuGrF0Vs$A)Fq zX^ZqKl=%I$xq42?_4!m{(DEix%TRx){21X}_f6*{2X6lN6%T?bUDYr&F*BEu$oom^ z%wr(;)0^_bmikPAw{WRRRuewzqj_BdebKs0aXKGlSK^o~#;^@JyKU3t0-;WWJ`1Rftr$UP-4G$Yx6 zBn8Ub5{+ zVB~8iA6h+uS%FEy%p10e4Yfu=sX=)PL`cd8Q6z3c^Et`2dsjw~fulJdYiSD`cq<+F zGJC>GY3Z|R0V-H4ohp;cKyC>ty~5PKEw&V9X5NLeH{9TC$lcmuXZQVQH|+E*}}EjlfufLLyb8?jvq_HYLz# zsATW|M*?Yy1w+|kc01+>kjxImEaA|4-*o(Nz|=IcWKGf^qG!IjGOE$QhMh#;>nSPS zU)~Opo06U}6ZLaXte6+-SUMqIEXV+{o|2gsRr<`!rPdyc+%!08MR}s;5?=7@wD*`! zMx#0l#ev?OX$d8lhG`PCD`51({!^yaqDQ|{p@68Hi)3SF#f@;CNu(#FLXQO!N6loqVuN<8I zyhW+_v}{M$xD%HWN1%6@sD?{cMzl1< zuq~?<&}5TU!NY;Dn4@c3lCWMKZh6if@MNv6`$i7tlmJW7fYpv_6+dE4u^|k7W zQtsL&N)i&bI^l_B@I~KC3U?sfTQ6>UT>=6&uG$pp zyapDf4;A`}@>76H7HCt%^^Qew54`NA&bk$HBNWk*A@4%Fn6hpP)Gmkdsu|8<%i4NH zf4V#fP0IYZYp~|qJ9a+J0B5vT;0QJ8RikZ1{JAJR?;&`Fr2&cBeY{u-ZtU;bH~=j- zN7KRtNTMyrf8CZZ>j4RVK9kMhWrsnPb@nm>BPX^~XJ!2ZXB6VLRtNV`5zr9XkC3>) zL`-L>3Pz6g*L$KPsK?R?F{DDht#J%HXg>8Vvob zO#E4oSk&$@AFzZWmwL)EW|bAfJ7u?<*8v+6p0Y$m{`wt?1_-+C(u5WVgp+2WOz?5Z<_Db^B z4RXr#0CRg_g9Z@9u6n47tSWD`ui?&K+f2SzvUYIL^#<$g5j8!XU~2NA(*Usy+jC(V zjf}A`i*mVfvbNurQgeHGQ=jMu+ogdrT1hSqN7_^P@OMdi5?{(9V_!?i7vzPKsmmX1 z4P+&F*Z3>E4a|R;sY_k;dha}I375Oe(&UHwR{niOqT=e7!Oib&`4j&d8yxG*pq|Q43wGQr zJ&hw{W?hLLf6WKj9pe$ZRmKq_4gu`W8>tSNJudYM*Xy9|9Z&NXokcSXzuW(wa4)UP z(>&kfbDF+D})CO$(1O*vf%_C{MpkC{e4!M?!;R?WDyAv zYbe?6e{7>?Rr_o&(r3q;)*T{cpU5IB_S16F*xSrvA=i%*FV0&n51Nj7V0 zO<`gyv{&-wb8C((EbxBK_j5~j$Qj6)y$d_cv0bXdTf@w^C0?#iH#>`F;ewIT5Z-Fr zwEnN2igql!S8MIbnkgXocX8qA-MOFUoXV6cW+$m>hsrp=Ez_L6utIC1A~IAt&QMI1 z$ig|~jO_}77Kna3g^x0;HLnNtf4Kym_&G9le`KiI&c4cMy56(_@YH3EP^|3FR z=iGwY(iqnyqrPyHGSC#}v|YyV@C!f}o;W^;sr5J2{j|G1YR2`SdlhO0e>f`q+m6gI zb9BvTt*&>x^flrlh+=cprd@`et&ae_y!1BBC8t5Ox500Ahmd&94ii;*W5~J|T7%cH zy!@7rZQpZm5sy>n$M5Z{5V2S?w0Q)aFd36nr3iORMH4PXKbH~Bvp-e7H@MF0Jc*Ym z5s)s`fAYF64k7e-b~zgFTVAx7 zBn0NYYffWhT-T9vVzSPB3vu>&G;enUYA}gWK5lt%y429;91=egt&yXCG}X*$I51%q zqB4^PZ{cDXLx*mE&ITXOlsYB^<8C<^_h6)faglYjVC)-&*&QxLmQH`OcaRt2Qd~EggLRA^QG`7 z{5GiLKVq!X__UYOxBH1N(8%6UU1XAJzV3$7cQ#RqNVRQxW*n-W%a<~5V=scuVs3=LbR=%smjZ2;4Z z0iodAvL;6GGS}Ovh7!^30pO)Px;1pBHDo?Oo8zqg0_``_@w;_Q%2f|va(F^h@UhD) zl|F$6gs(*w9cuc{B1%{$7?7=*)^MY#qC7W_5%8KhLiMJaw3R$Rd&lNe@uPDD?YyOL zpN#_J*cR@h*`sL}04*kI#kEs~R7Yv-eT=nCmG5hs#>%cuVEA)wV|%K5N=9(Dt0X6C zfsvI(>Bht8bx7mQQ850~C2(YC0o>s;qS96hhrRSY@__gknV|f%Mmn~1kBs(z_j#UI z0Aq;na;)owhQmsJRU?|LEv&F=lgYJ1Ytu8ELJ$8TxvnkLHXC#kwjb>{M+g1zw)I^B z2|Ix8+{m%qS?+R}0DZrd)6GBCV;;|k-fP0xXVB*bIL4I?rw_g#Fg1$E6-30N3i2G3 zz7vb;aKucs*KF5dBvcLL(X;l2x%=S@%Nj-)G0d~+vG%{OO#FStO_JQ|+9FcCMKbnE2dtfff?V({5%p&nL(xwU64K+k zUn)?gAA%VKo=>7c6|q^7{N^vnlzRy*<}f#OJ3hT;G@<%kvLekYJX@j83}uJg;yS)% z9ZdgB&MX<`9^WBp1@8jf8fB5GY@^smBV~_dMTld%$fp9{m=Ignj^^@p-%%1MfFn@%J?doSQL))vPYEx9Glg)vq2FXZTDMA)7v-${S3~ zC?alTUG7<1^2mYKo$r-41Ev>clLz2C{PT={A1M8qG8H=wGcD)v@Ej|!7u6P3DAPF& zB~iuMl&$u>5p0=k}d~=L27ICbx*v;1mf(l4WzI746k@nK)bD=G=<7*<$=KPeG{m z5$rJ7cCof;>L4FU%J1Rw(;@g&=~TnsVXwu$^nv!A4wg*U>2n4aJ2{_0-oX2F0)EUw^ZDl1)fE;9{lCAY>W6DgBJk^(dDpPy?ENLZ@d7wVJa*}wuxy^QXHXWpv z@M77I?vb%gmspbN?X9Cuc`Kkrw#b2#gyAPnP5=;^C8OHNyU(!^Kj0j$EO5-WM>ekY zU6x6Eh>{RudlW%dha#XE)(t1DXCqKVkw|9RMd|j2Vg#diNYrrU)5wu(HF0y&3jIsk zQC;2c%$GS&nfly#RKEk$MO#%SzMika_P%WvJb$xYnn{v0IQJnr@3-Eo^B#CLLv z`k{{Ft%dXi-1&JwVETdQ$YJ~q^gq@l7?d?b*(BjZ6oB>5zKzP_2B7uiE&iVr*5aY&8oKk@M~lC zKQS)vM1^spSaa4?VtUJ7cb8K|9@Jcg&-}y1_?<5hFR^U?cG>yd6NEbasr`l^$FW22 z!uXfHj?!jt?s&!U#S75`$R8SSorfyBv`Dz~qLbb{M}5iCg%LQkV*K5ye^eT(}$ZQGWpijkZsAAx%@*^9pGL)v{_ zyiXf%7%Tbj=WRL^%ja;z12$bp3E07X`?``Lpn#k4&7bK|IfRD|8D2DZ5==EIy5W=j z=0M|`c5>^R7~f!G{>EE!(^{S99rUbYm3F~MBiyUV=z2MEaGC>Voyg91wQN{2k_sHJ z9!RhJM0HCeOM`7x*2mT#G!*cD?IZ&-9v{HGVV(EjE8Kf8d~KidoopzK>@$3g${2e6 zh{2|Kd=elFt;8*u_L}bKYOF@^pA-!*s>Q6XwUD+bVLxa!u zzxI>r-cQF-P{i0@L4Jq($Dtrn`g!CKiB0LDo$8TmR0fm2T8kM zMo(JlvRttbiR3nPuROoegU-@bsX=%~gvh>Te?xnxtNj5d%Nz4)vn}y8`&2jjc8Q;X z`n>qWRVmOn9I&a{-LhI@G=8}Pc%QVD8}=jkw957{JI2X93oGXSWvgRqzr^^z9RR-z z%9pCzj^yhU9&VTyZl@gaUh7g(0SkmzcFoUDxhERK0#G8o`v=on;!|8{+5h#i=wBzf zTY$QA784tl5+XceHSZybnA_NJJukQ|+r$nH-cnqv9i?7?>5H68fvm0180!u#LFXYO~YZ=WrL@2LqN5n@D?~@ z`XDy;Rj$gbo96@F{G}iCTzM-R6bPDD(gwm$7p;gTz}pr?zo|^A*MaVOpwEE8JRb#) zZSn>}#dc^0QemF-&1PeKT}9`5yLE05ux&Gc&N6M za;z3@;DxWzR+Nh8hLL<4z2?0W*fHBWE1J?Y{YPMvGpD@E?m&I<;n&T_lc>-tO>d1M zLzJ80*^%nZ7;&(%G79mv6Ib(6JONLRnsb_HyXW|QGRLV0IWVeh3F4Fg-ts*nsw9en9r*<6+K+H9yjZ}$ZS+RxB7AUo2@ez zbvuT9s4}dNpyZ)Qj=xy$F{MHMvTLWxvnA2bR^xG)`}nfDUQMFd zhY>+H&15L)mUk667_g%qJo)#PBT1hqk%TY$`oi;X*qH`$YQbCUp(cGBj0Ky8^HH`> z80H`1{?u$sZr*mMX&!PHzS=)lX4_sEpxB(OW+Ab15f`&WFt)SelGiozVQYBygNxHD zDP_3*ta#ln^yQ0lD<cSwRh1{-GzVc(O=V$nN|a)I{XKH88@`uE9G-?;b#Vjr%S<{D=%peKV90F zr9g+lm>yzaC0=O-*BE8)m$Wp1sMoN0mV5m4kaIvP9x8i2Yz=kH1!z9URnLyy-I{rV zak~DQC5FtCHD;9j+O6<<@Jw*JH}B8X;eL4ixKnJ5AIeQMd}=(w)RTXE&vh*5w^^yS zK#Pm1JnJ01+)8iM6+8q z`gKUU`NRYRvRK_}@E9c1(!L@*g_W4Z6JvCW6`C-?T&`;jS-3v$fGQLY5d+*Na`;vR z+BX}2qSxpQ3bEXGB)AnMOL7OBL!O$c50IX8^BmTrrox}C+2p=V8|jSi3J}fT$&rUT zwDl{j8zA_Gi}eB(4t5p%W##UkSzR&xgugNQY@$g|X`j(d`EA}j&O@%RetE`rEDUKJ z@qK$jK0q-?(iotbJ>`WEQ!Z7l^rg54=x`^=9Z1|vgJzqJOE`w89=jwKg$U*V^dob; zy8A8r9?a7YL)>z`wO;)I;I~(vz3(65Vedd2gEf%@bj)|or#t1G1t7u332$Xx`xUFf zT1cmGs}bVs5~sV&GHrt8(K5$p|Zn4sR= zRezFdH?NTpV2!KqC|G=I?yU83`1)qCY8d14Rk(dOaLt*XfZR?6xL{bXC4Lso+Z?&E ztuL`%H}T~_W~^p3^3M`ip9p^}z&YEvBX$3TUsJGXsAjxZz+^Zy3``R%0lsj~wV6B7 z(yeg)d2JeS-Ll2tzOyjNl1R#ujn9ocE#UZG3=1bmuWiH&__Ha0UqJx2erlu)&hC?U zk{S;}G`|0Rgs@24V`gJ}Zco?OuNnCSlC3uAh~ zRDf_Fv@mab)0Otif1P5tGuN)pYvU8a_dEsuWoq)NhuTp+w$UGiE}!bwJ9nlqNcO1B4ZpDPRTGwGp`Z~Iuq z<}AzZs!tc0<;|sAfIf-U0a-z<|EMeN zdTx#mmJcA66f1B`d>)XIRESWJy5BtkeK|t$$2sze%fK5C<#$cRlwXeFnr$s2YovOG zu=BZ$+qoSMJu5Ho+Fc^*EQFy`ASU<9L5bdH zrW@|nqWx@a_?D-oS*+7uhTqO)sqe??lFZkIUrS$tWqv`6CZi&RMkI}27DpCE=hNTz zPdC?aDA@XTZ)&Y`?aCWcH{Dk^NZ-gKM;Ag9`^aQ>_(Vp6^8VzJArM3>NI!fHBAZ2M zd?t|^Hvecf!<9EQhm^S5%+`%gr}2rxhVO5SHlFZG@mITKS3gcnS20Dbd}yxrDwj@^ z-(V-+(q8zvm*m*c1!o|v@YX@e-+yzh*=pu*yUV7od=z;Y{|54gG+v=CT`In5xU2 zp@tvW)8m+H{cw9^2yiNwv9>R-Ab@t-X*~aF{Y6^WRzZ)`bzNX)CV)_VkM18VNdsdS z8aK(j7~im{v$_&^K$y)t93~q`Jun!`o)-M6%Ar6auA?+$^0d*p%W!iR+H9`aW|V$y z$PzMYv44URnNShG(bctk>^baS&7LW|OSJ>BG=wpigRKAXJZW5L!t<;nje?c0u}M1Y z(uGZG8~HpZvoBu_i!uefe?|rxsQLwB%24N_T2}F=I?TiQbD8(FFc5*Jk$$mu-mck) ziFN#K8>0E||2hw^{IDlG{ljXP|F#rI^7xnKZO@d5(j#*TR!p^2OWDND8<P7{&ZjbY4 zJzj&2%Yp&JZqM!+HT_sI9&X^~XKxV69H)fmVNaTa;TH9M$eH<~md0AB8I@MfykNQc za0EoSiS22nb2`kW{LQRrXB>jd`D-GS2h{I=e*rJ)L9%`8J7svRrz0P4sFji%mqvU7 zjrRV2q2w3oE!hDxo(f-Ro_`FD)5g;5|GvUK#H}$IsBU}jPbx@UIKuC9pF^waU}n7E zu0!$89F635P^KZ| zw7{oZw%tyx8aVw&>ALiGqDC#ZbXL@DMAfEsZdKzo(Gl6e?!c12rXq9g-0x_ZI8dGW zL}RxmWPP{9)bddZ2HEcXeAJ{j2k9i$h~Xy!3-S)!&EIs7Qf`I*eZ|-H_{OkYiMCGF z(Qn0bUxdDl*6mBOl<;Dm)5LtD^Uv6_JcXwj+0|ZM{njj_Eo@|~Iao-D@{qc|V)I^hKkgg`>uRfx$*A9ag0J9%3>|6iMC2Ec<-`(QRy=e!o zaQ%I_96iW%_dohQ?XSW^_#`arDi=fXO6jO;7Ph85DS;o4!|$s@Ld}^wy9iPoMF3GjEs(R5>#`Dfw%) z&R%J86)0dd>wZL8Vi=U!zrwNz|c#XgmAkSFP{}clpC!GJbz)eEiC+VvOVQZbS*f3 zHtAepl{^p3jJD;{_6sN+0OlKZ-D@YL+8+v|EjimOHNkY>9qXZJeel?$2a>>Ep`9w@ z>;p}vg(Si(!6u_kmyi42oG*vE2add@{X+@j%9TgdGJTT7JFJmHBy&MU&sC9KPKb@k zvJ~@F@7mQWm;Li_<*E^@NBAej3ff2^(82f>J|0~i(uOX^r^{e_5VvP3#;|nyxv^*;`SugVIM(DN?1^jM5Yc z2uP4V(jh>kLuhNO^maB?YPR$iA~iq~*wQj|F(eTJWGB=RIwXXU#FI7WW^QKAT%L=$ z``7=y>s#;o*1x|0UC;Bp&r2FR7|bOgbirVn8+>A+Nr^k2e8H?d6)2aGXk@+ZpRw+z zU96?jupKbkw7T~ql=l-_4D5r9mgRF51rGzoXU*s#G8;LLV$A%!Vz22oAz?bivek84 zA!z^Bo|w>e$9tn@N)L){hAnJ%z5NYZ2BE$KwQIEnK;zKHMUY%{n|J>1&-teSjYs2ty)^oxNTcR(m-b@)TBL85^+*T(rrM`C=Wso_3gc95 zD|1pu7$Ih%72)zEF3wi+s)5VHa$zvTDw{O(a@L~fsUfcjX>Bk*>{JtJ>>k z@bk8Y%Aj^K#;{V`0OZ}=+Icq>=~sWKHh5Kb7fAK=7;VhiaIAVc=KMNvcl}r4N~DhY z%I!&#fs7qmQN`NNc_PVdJ0{`P#)L%g5V=1@^ds}5eay0QXF+p=i69)8=ipykx<7&s zJ&#G0TdHxy<93@Z%Qho_TSq2@#tSPC=ufdfZQSzTQ=K zSFMXqHe7+mUH7veA|rk6T{!Je7U%l2;eBsURY#8gx>&FRjZGtuk51Z>s1=H z49bS-D1nT2Mkbv@)ZFn5S7&W1yVE@%KJZxgTV#LPKt@wQ7j45)Sx(+;fadGH<-Inn z_t{e-cBC%h@V&8NCq$M)Qz@iSS%UaeQGCqpPPsRMtGox_TF zNU}nPyQ6?Eyx2PPD>v$XI&GeZSw^nn$9bxkmJYa&5<_E0Q&Ee_@J+nX-FwtBDWU3~ z7N=PFR^8^w8=#ql1RwpuRUe8*wsju%^{BWWHv z8?B#Afhd9hiks(mG%R*@iozNs)WR(dE(V}Pvs^VAzq0l8 zr=cKnEmv*E@4zP-3c#~8UPZ7(mAe=Zu$yc35{=00 zTu1oFnGMxSV~ktI;V{2hS^Qt;12t@v7-ft4BaFoR)r0_6Zdreh%5#kJH+&^E8R7K$ z5UglsoIcWJdh9n+-E@c8eQz*x%iB}J)^TyRDZ+*dbh2S8xHT6N+2tRPu~N?4+1dJV z8(5KlEW;MCF*aTErMzMcN6)qSQhT_UdnjaU(-e9>lSaFLvYj(io=u}_PdXz|6Y&&s93L0Xe}PJs^9q^1_4D=O1fNGk@dUj#kgn1%0!=~omC zf|x}){f|M7D8|fK=fhLa%$;}PuV0*~hp6}PHM1s~n_4P<%4St9T`WP?tFKhxsh)dYt?M-9-S(5 zS_QAutglf3a;*-pDpdZuZ108;WLkMBG1bowhR|IG?Y2DtS89?l!0;(?kLHm zF)E%=*oaSw7Yw`QQr%ed8m0ZXMWZaxJP0HDt*84p zu20~x6|?^MeM}w2C0GM(e!S~NHrgGZwrcWUOqPXMnnrppI))8W*rWml~t+V*9$|fqNkr21*j=6WWB09zL41Sx`%Ah-My2jJb#&EkyYKNqq{X_5J zKo9|Kut}|y5iL>17BfV7*b$6H50nCZ*+6h63T3M1Gl+btXPh*ZS}e8dc-eb z>1~q9JZaUQM8Q+n;blnq@iHD0A9UP}`lKJFFg;eMH`-)&3N*r9ISU@cXof7(}=*M>k!*J!*wG)jW)`BY-i-<^B?vg}R|vBQPPXb-h*bxZxK zf)LM{S3b1KGjVJ8+F1{0h1+{;gteVL(aqdrDPBm9^lg?G(-8Txx4VEo4Fo3I!E6AZ zCZ(zvEH(HSt?vzUACXw!G8gRi?VB^Ok)H76PJ85o!4V&#YxT5Lstbq70l^#a6xgo1 zD@B}l8Ce))1|0##_}VFxUC>IC3$8A-W_$it z+T)2a11bK8xs;xpr-ddBYJ@h)Jrs|1EC_rSS76m{M3s363E5Xe`nx>V^3|-tl}=t7 zucKt-7gyN{28AK71gdS$_vX*!J&xN%NDO|mqMy9hTN{6UI;CtOMA(3tNX&kzA#nek zppNtUqx&@M!N4v?M|HFeV;dAJb z$>az(YLj4V7_9#*ajz7ebFi!E+T?wJH!1LmmzUCt!$m1dCtzF=?L z>Vd-W!N|Tk`rM%cS)zimn0pgvI#aJmtW}<_8*a`InWW@%y<|kbzv_J*0?1Tx6pV&l zLJJx5gzDuhd8=9t`RcaYkPwlXHXU#0fBso->lVi zgLJuxcd`uk1~u&sW#J9WuQyd!2C@cyAZh4}kCRkRQU+>9#k#`m#gwnYjaS^m45>~+ z@rT#92O1g=LPuztXmM4 z>=%ywU(Q&Bznqb9x zTIxBqT7sQKur>e}W_n=-7?ARQHQK|-VInC}Zi~sgu-=lgU9Em-?T|?x^|XYkVx&2+ z%3jj2vGD=@B?pIfyWbcXMN0TQ&|P@vhd}3}cGb*aiWXYc^S8kWyIipGcMjVqBK2@U zcuehVStMvJ?`XY}LweuHC4&VDT22^wIjbu*wC~8EaJMW= zkveIV9U?3gylop>)#|t1onijuC_MK$Ns1fSBCbfx_LlN}YIYh{V6I{<%m_xgTF;R7 za#ld^MpP8BlqXZGkk3CwiE&`6?h<^mP1gjcp4< zK|NQtC9P$}!Rpq#(`6jUkg;Wy;^<_VT_L$*W8vPMz5ln(eNgz6#e>lLm1+6b zGt)ufBgK>ErM0f!2)NP)L~8X>Z?(Si^v60ax#G_&q!L*P*}fFXZyfy+nP#;7X)1C>d6fYmC8c)2e+wHwFC zyk#scf!|&{%|88ozvII1dp{RRdXMe~?Pu-(HeXrAB&a9Z+)QAIBnQ0!EEru+VO~!S z*x-9qj6<9(IsLO^9_m<5`yo$u!00FMpNx|EZJm1S(wE4KT&E$N(2HH3~^t z)fSm6?;OZ%ud%$ce6M!EKP2s%q_J+j;;5IQjCNW<;PF%-X?RgsY6hY!CI2X;yf>ZW$#0fL&?|^;1f~x)oGhu>LVkE>G+=;?CK^( z)mFd(hZ!GX6%h%L5kTkh++;4scQj21^flDKgdQ2h`R|QmhJ$_D_=9lv-q>5^V934m z0y;vqK^J;g@Ti4!?QS=uSOa9JDn84u0ViyD-dLUO7|hw6~}pUhmY?B2;JDts|;hptsZyG`|u8wYKeB_$wi>TQkcG?P3&W z(DdrlgU)eWdk}d1SCJfin^$3&Jm<>YoKMjO=*IbM-;#GDBbFzSOPf|mFAd*4TiM8s%y-TQCR~p3dg$CWp@)kbc75Xdtb9V@|hew+4wKrZ%uqL9wJSZRAaczhL4>xpP1V)6AQ(=~7EDG4S{0c{cvflSj$2gK@< zbgF$w^Q?<$vT!v(beZ`>;M%|h!qP^&(jW)&w3Bikhh{JPvDNZDPb1GZj{+sl^FF&p zI6!v26r>h5k8;+34+AJk=6@X-6L(dvVSy(%Lu%Gh`#e!@j)z#FO(i)qNp@ST_H)I~ zN#@O-2AG_E!ZG-d>KTN|8vSXm4&JAHwpq_&lh2arB8&G_VbCo#Ckg1T5$!BIZ$Q^>qoRrAo4*|Z6RD;3az<6TtLX_KV zDhrj~)o1)`CDiGLr@|L2j`@3sHTt`C-rgxPxA(e|;&ompd}fNPD$KhKuw9Qb zqA*rp!QT+p$@K>&&P@wEnMuu zT)$mkLf_K4@IGYD>O8#`&#_m|2H{3P%p!+ws6Ignso%J|do3-IaqFNarOoz7GneMc%gSae9og z^tlu|2=lIKL?U7sq<}tphJhY=TH4ueha8;g5R-T=*qLPc2)=)f+qHroNn@+{^KQ=O zK}_X^ouD~c+wu&wUqJ!ZFp_&)`o*hOA`94aT}~_@Z?_X-%r_~R*+%z+l??(#=h?ok;0n7YAfNnxSqHiMLtw5>RF#?22K(%G{px-w19L2%CB>^l@Td+hkQaw&HZDcMT3)0%A^z)_s{uoEa_*qesefuPUrIHe}nul4OV zIhTWOWFFb&-qI0<2f9~lr>Q2COa^xI8)ro~N+0ygJpadg{j`M$qjzjyt=Z{suboadZ#?>+b2bGLJk=V8^cT165KL%ls9$i!p= zBm_awLI~pFgLnX>$_v18*pd%|cmWJ9(0A~iF^&f;kT4G~qztZO;41>)1>m|7WH1lF zvjMCP;05FS?0grG!|c3P@Cb0q+6oAwGmn$;>p@mc63x{|iVSu{`2;MRLoU(2McmxzK#QC$pxcGabBqalUU9dQBH%TlG zjrNuF#-e>)a42_4w7+DCmp2Y2>FVO<i8$1w)# z3JTBx#w=)_3^aMwbw|6RBzJhBacHa;IzUq2T2)R_(#*xp+n0Lo@Noc39s8jJnQ{0v zs5^985aI_H1tld#zSCU&B?5l_arhR1c@nrhJZ#-1&f@4PAK-Ztxn(_L^N-`-09arg zUjbl2kQrO=0^ln&4g(OHIR&0I&i@JU&rjsGgWfhES|TsUrj%76C}9emI0c5TjLWa6 zpuls5TNaB2WV^!6hi#{P<1pJ!mtN!Yux%5%F36D$pdp@dm@O+WfZ5jm1rT^{aQVS4 z#5)eNdHAN_`EPLb&1oiN3fEz*GAo4=-2eRshdC4r{PGIrwY^Uv|C|S5_UX zADY9le`kF&h?g}033Kis_XBKJRs(bxnj<76G*f8K%$alM&z?1V{$i0ib3_&|TexuX z!iCG`&*6N=FWj5I{_@P7J$tV3+My)dEEUT}zjRQh^7RW-Lm$nyn|jda>10S7jB

    ln}HHp^W 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 qDz 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 R9~f5re;oGDC9_|L{tJr8nbrUR literal 0 HcmV?d00001 diff --git a/setup/import/images/PROD002-6.jpg b/setup/import/images/PROD002-6.jpg new file mode 100644 index 0000000000000000000000000000000000000000..73a1698c89b4f894137cfa208281426d34582504 GIT binary patch literal 129033 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

    qrn& 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 literal 0 HcmV?d00001 diff --git a/setup/import/images/PROD003-1.jpg b/setup/import/images/PROD003-1.jpg new file mode 100644 index 0000000000000000000000000000000000000000..f968e29d5cbf3f46b131083806e3ca7373b4e1ea GIT binary patch literal 161005 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

    -Q%sxjgb-6R6QTQ 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২=~^&cN3Dmc#7 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 z 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
    ?!qeuri%s+l<_AEDtUneEIr~m~@I=OS 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 C30Zsq literal 0 HcmV?d00001 diff --git a/setup/import/images/PROD003-3.jpg b/setup/import/images/PROD003-3.jpg new file mode 100644 index 0000000000000000000000000000000000000000..ff5f6a90cdfbfddd951c5d66e41331783b2000e8 GIT binary patch literal 260235 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%0Df&41WTN}_iI|D%lF@i8M6s@M6*tt#=m zfh*t*wQo=Ngy!S=Sc-p|@l!{-$cpj`Z1VF$?n*z{ovZH04(mLV5^`K+0^D2zAs+#U0l0j&7B zr`QXBd>gSfz7LaKNjoW?MSuL5A>$!axiE#?3jk02p!A_g3}ga}EjN>>Ks>Be3_0KD z@R1YKmlynYLHEs|;TGCFqs|UknhgXH=f|4Y1($N@@E$TBha)n<^7+}b>5W-@g<8Cj zPp%6@fCxZ0nsR;$PBt@lh8sJ}iL%N110I4<8!wi7i8kEDM59glr=|714;}$b={!S+ z2e;=hia)ZeAf>CCh4ee?)zH+0tBVUf zI&{%%)qv-*RMuH8JcNx4m-K!xlFLTGd;>eA6L?}b8RrxNlxae%bLoIlb4qXjacy6T z8s7F2nu(b-&en$~^0Twf$$C`d&mS9DAJQwr zi6MS2+p3tMUCT}mR_%t(W8?x;S*r^GYLpiwWFC%XQn}R*n}UapyOxf+0V$I|X``X% z)q;@wo|{ceNtNuAP_c~{@ORw<;JPAQSUDWG_hZ`~w+@=8VCMedO?q-JLvv0|KeaYJ zieV1#E22$xaZaAX3IC6Z%y&5Z$i|n zt7KbKHYzo^l7{$E2AA*qRuiG7!?Gc6>4E2?fPaw2p#LC;%8?6VyV~sak2L)EyH(vt!bx_ zM9^-m#?@E1fg?B>l^?iQ5V#g_AWW*TB^qvf$XC6nF*jv@l$(&dmO4hE(~JyW;43aV zQuv{<3dGKk7Hf-r*pt4GjE^GaZ>F+PLA%ES9`wE9ga=V^9s{8%z!u1HAlHEYbNWYs z?pa%u4tqqImQ?>lFM`gGKr^Nyj!juEE2&Q`ux_JmB|t0XS{%J!(R6X>Iq8s}^Q~E4 z!h|2cqi^$`e;l0~J*W75HLydNPSIrXFk z*Z3>W%DbyA_l|)@as2K4BfJz>aBe~pV3oWca@ZMZ6sH|9U=1^(U_xQ0aM?|bdF654 zfKEKmy1MoFB#*V+H?FmYg7(s0N%%Z?3o`%y)MG4dZ;Qu$7w8cWoVEy;mqo>6L>S>Y zPJ2r8zun8B|6hAK^$rxW(HL#)j&AecUwlYC+wZ{Zv<=+QLnYi_3^hCtVT*4)q@ROC z$yGukPwU+^s=elgzJkY+Xh`4@;mnJmk-&dN7Gcnse)r9vHr{EaBxKg!S73irkwer4 zGgS8%6Rv#?n`&*3^6(`Q7&=y#zR%O@@}w*dE_KJ9;PNuKLh6 zPm)xN|HC`IcWvVx0kBb7oPVs;;vF+6!gCo006-v}$S}m5739x#wHmzGYmey&hM5eH z{kaF`HC&gs9P;w3lZz<+lFe{_0)^yq9NiAS3+;OO5hv3)(X8t}TL>J%Elyxjl)(03 z2e#vRdVbdVsrBIhr{Ro99MgpKOm@)CS&%eHf80p5i!vX%J5I)Ja0{AcpJuVaJqmjR zZ#ub zvJ=xEen2TSzkH;f0J*Z9tBV?(3qbJsygu?^o-D$_Wjxy|)mpvjQ+=RiWg!%zQJ2+|J2vI4l8TB}10?D-rD2km82 zzBPT+e(s6&y|^9UX6&-#sOti`V4(o*58%zgGsK2|$qJn0y0YgPU!v_><;E#%X%|Xw zFLTo4cP|e;)7uW7d1FlPanHLBq#KvOWyiL!6|a)A*#i;|0+V0F4e@suDQh~V3!|xc z-X{o9W34x=NjbjW&`ibqpm(JQi6#C1xU>`Gc#0q= z$QSC>z?1fw*ukVlG4}sa_MbsbwO`yYiWNl!6;OJlNH0=FN+ME2i!|v(dJ~Z*ohT?B zB1NhYdgzfZH6kJcA|({*Lg>8{((beWGv~~lnRn)$=Na`2Un1GpUe{W`wm`{{fQ_49 z&x-h8rAI;}xI1lVCD@-Iv`ZZf2cvZ1Rmx)f4JKpWV?!KT=h-!^FZP3~edy<5 zuDh=cL9n+%cT0=L-U`EK##82sY&>jL3`%~9IpQny5}Ey(?SNwaFD9sfsE1hL*mFrG z16V^+N{Fs-;=5He7Pv>+gD|iWLAeBh)=50ueWqhR*gGXtnc>+HABJE6qUx=M7H0(yl z&^lWE=*EQSReUPDdg4v+y-TLNk~#dL;FNsCasNn=9@E)K_{F2O5udNx_gCs>et8EnAwk z;#-6M58p7$QQwjj^0+kL>ypasnm>*Or)yV1=IVV{8+)UtCE57UF~TVL&?Ne^7SU1n zo8WnL#!$I)HqVU?J?W?JV(-GYtnHNH9e{Y&lDd1SIeN$AG~6~!mOo7GTdD<;$R%$Y zcQt4!G440UAe#>XIfrbY7e)d3HB2S#c`qD;&h7INwWBj{TDh5iK{TURJ`W!!{`xM> ze3D6wDZcS6i?IkIi%lUV9ff&M}#bu3) zCMZT@Fn2XA2S!WsNr73}pB&9BM4*pCgelzS)MV|4<1|aqqRcEG$lG+V9hqp zG_=v@cZ!^Hgb>+2GablAG1B$J722Eq}KbBm;8i3+;`$cLfx`nSmBmsbUCGZPDo<8j?c*m*um+U_>_p}7k4>GWgMasS8(+| znvOaBkVV;23^N$f%g+5NZMab-1Zr5px)!J4HX(P&D2eNRm==z}XLA1;Z)X!dqzUWH z0!BD>8Et{a>-R#-+!22PnS_CNkXzvgJHN3y{f$I~Z|^b%gCUUIR#m^njqT%mx$X@t z>K$&e%Hp^5P6nNIni4a*^kqF){9MT?Vc3Q`YbN&OH7e#L{7=J31Iy)K2Vey% zuxmUbaXsvndwC*mYNPL@t}gv3gS=c9zPG3GAB{ZkAtL(}>NhQlXOu*(q59hu9|gX| zH}8uJEFrqOK?6uwpw8d-qqsk5$5abhIeQ3_jLK|(HgK($-}Tg7+uiN**xJC#lVFkA zYE*ZWc_>r}%(!uIwEnE9C+$1zrjrBIR7Dn8)>@%vd^!$lfW&CX&d%x=!Z?9UU-jb< zEq?mbUG}BYsJu@NFB%gs^zPpRTN0c1yhx^Plp=0==z6?m@zM|^{DEeHH_>2Ubv`{?z|C$x6ym&QBmYp=IT{cC1m zl)cuXkkEKl4LL-s7WKUUqn4KZ*@PKl_ra_YqSy}sG~H*rpHBY&m-@Xo?s&MSaM^n&~Zys;xi6hRFRpEpUiS1h+X ztPdz-KKd1I_N3SrrXXj~J}=PY2Jr*Ud+u40eaXAq!yx#HS=s7Zmf5rR&J4<4X@$*s zsyWZt9)p3oW0q-!>m5ZN+B~TI{o@PSjv9I9>UlS)ZT)3wUHezO7QKR$l{(J1;I zE7b;+Ak3(bi>QxB161bh74?#WbMBv9WZw`j7rvt0SX%-~PXf(lBKrNIS$GOY@;u`( zL_{i7R8Ts1=KIb}iZkP=pyU6eReu zxrBg}j9L_3%jcCpKl_zd_hhtBLrzu!1DR9R0&141Obp`B|NQ&S%Og9VuH4fVe{hN0 z;X@!JJQK5K5c8@zC*6XH^te^H4R~Vz?z}0RlkL5pm!Dl4hm>p1Ge3kGE@cOG_I9gC zXabSO1AVf|x?&^hc@WOL$?2bL@m2IsO|FX1*$TqG!^%rw1I5xuI_BY3b^R%5ycU23 zx$XPqOabIKVindK`d)kj`{2>ffR|nTJ`Sf7tC?P&?Z-#K02%fu`at0_H;wob2^ty< z@tQtj&Anifm|mEOZlC<%cXr|Q8EydMi3*hTX$e2-o(}4SRwE+(4pOO)=21I}^{-<8 zqxm4XTV;p-5gNat2M%XB25)Y)zn}5J_TaIz6N^6B9|uQ6h#&g8_nHuIvbYR|IEI_g zEl~%%b+n&4&&&$=Y+tUJFN1o4b9?du5DSBAJcW8h{6a+*@+-5e#l|6TrN2 zWs(5UVI2?`vRA>S^Q2dwpCiu0Lt}xpL=%#)@%2h{86b`H8Nln`saO{;)pB|&(O536 z5DTzCv1J~PtB)Upazf@Z{aVx=uk)sJ;eXLFZ5bqo;UDRS!0jmgvz{xAH+CdiaUHU4 z#R$M&Wx|KE@`(;PxjH^|u1M!D_C}4*>f?Zss?{fwV2>KqN_ig`v=YYXvV|b=uE-t0 zV^!1#+QHTutcI65L)mP`&A-qe3q%z(u4rc8lpByqC8vtb6 z^{SEm2ueT?fFG$=tnut_t@A6#N@Z?NTcrAWRZ~+3k!a>I3*|>=5w5OGQ1!CsI z;a+;g?%&kuunM=r89{x%?vxM$!=Lm#LXs`$j+5(ho{Do?pcgQ*<}7TH{CCrNi*J|VDW>Pg5-XKs zUwz_*53oFhBUF8UUS4NXa)Au%zo@LaC5Cye0H8=@XL}K2;ukurm320+Y*BSwsFDTS z6U~oACF0s^WJqCX_HXyWX-WG98|W>=3Y%sI%zxQ)fZeLi`Tk0SRpt2w~W;20j^L{zu== zjUnC8@L$y3#0Lk|V{9AeEaN-{b7qI!*x}ERR;oqkbB6hz1Y|2E9N+3&6PIL!{mt;D8$T)Q%=lCo?@b1qeCe&`ItF z#iJwvD7>Bo?k|3kcJb5D-z&;nD@o}h{YxgGDZwMTLrRBzWqHPr9}51-McS)gvqH+g z8e(ujS=RDucmh;$nJKb&%(znZvi*|+-?6~*7wJN4q_2EVUL3NJX0e66cW3`5mM>M) zPQ@LQbfs%mFQA78O8b8ad5Gi|njTP^B2Dh99|RW3gE>+k5wU`GGvni+cvT&8FJs1e zunm3lo8kB2V8O0ls_1AgU+ZCVs*62;$~cqWc&bUo569#RfnUFs-!J6RHqKmr9lrjh zhnX`7-@|n+==8mrqTfAfy^f;xau;SZ==r;DjP z<*m??q4T~K68`&P_w8E;Hy?r4R0;ztpK0@c>H$BwkaP*y+_zYcTMDAW71zjIs!4S9 zido|P&I)5+KMH=Jl|~YKcHXY@UP`(erUE-e8?>iyv8n$+mydK^`tr2g5dUG+ECEXO z9gqT!c_#RT#;74J;#(*+aB7hdLpNS~L<82lcDT4TX{DIx@WUj_42JZ61v4nZt5anx7L$ZRAA#z3 z%p`xK-6PGCb6C#lFTf0PR^y{QC-^zTQx>RICBCO8e_BVD-N@+EsktQwN{-bjStbnO zLXAExMO@QqtX9SjssVxlMt!R@i^0VNK$nnLv^Hs)QtbEp^0e)|DR6xeSqlN@+gZjn z)l0NU66@CUgN9V(XfLtCchuHm%Kh^3c3I_(4VQ*k2Vi_tS_G|zjy40Ydqapwisq-S z6<{+6uD=++G8`ck`II+j<&c6>rY94l<)1boO>Xlz2k`~xfcSlXIsi`(4tJg3luJOO zmpo1pIcR)CQ;Urc_oaFw8#PS6&r}ReuCoc=5}LD1QZi}Jvs+=(y-h(L!H)$SQgsdi zYpu&4^bjxtTYu4FN1~DM4MYiGa|j5ue?oT;6PMc~r=p`b07=qGms+PRFlKbGLE5!; zW~NyF+<8S4igj`WmYGZ6Fw0~sN$5@x+@a)!X%=Kx>Er2?JuWgVrch;IS%qh2R1v*U@sqiB|@R9>c^t7NLFH?>= z7MWN9SdpDShVN?D2-&>_UY(sFPe36;&KsZ6KkfC%%%$;ni?|=9+_f`8{mxY z+1myNvJZgJM*`WbrFpjG?CZVV4+aRn5y!>Zz}*I%-q>|Xp#oym#*ft;Jo%h@}QxO=;TT1-Y^^PVbT8kUu*f^!a$~W+4_d)r z4+@lB3O7Oy9HB5o=rOwOf&T)_*>zv95)bOm!&(j<3VbcXcHYmhoG=G+b!bhu z89zv=&TESM;8uSBr6BsCG`e@UrnZ~AU#oiV6>=uzpi6$+&r*2r6}Zud;j$d z@k}-h&bmFscT`sQg7<)PMUC|gFUxn;l+y7==Ji^*>CDFgU#yiek#Xq}*}-DHVRs>C z#(-{0N=cM;O6M!Eg?rL*S<3i(#zE@om*CP`;KD4LV>e^DanouosjzxsLH9w5m1q1* zNy&pjpjTrB%mDdJ{^YEMEa^eR4$w_~Ql9JU2+mNyd9Nd|TLH-T2k2lF{_;a>MnXPg z2C;H1poLU4_y{%Q)p;4dpEpDVQ6CLoK<(&Q7gs-c)q1Ky z`R&1ufEDeSAtS3sGRNl6nm>dXfB-%g5^^v8KZ3#WS@Z28d573&0CBsHo{P|Vx4fY*wIpgm<=IQ@YZ8Xm=o7tmrhHV4pGQJ~3-WssbaHQ#Z3A4%m zA!cgg&r<)i@VzHj1J;`4BMP;bgSCYn4uUEK(&3ywj8i0Yea;hjhz+o;6T7pjRk0!a~e_;{T+MVL=MQpz z|39?;{$FiB7*RQo2WZ#>M2)eukysL8j>*LS4fy(~R-F6aLh0u&(s{QmIk|5-X=Qzt z);{X03O-@wnhB| z?rOJ@fZo%q_zaK1uMAI1qjL6&N{Z0#99z{9z!dAwK1FQ=c`5bEqK=~*NBMOZA3yh- z)B=d=TY?9{8?p|EB*mB)Yg{``eXsIXP2zjDx50E{~Az%1Asc?b=qEsZ7{oW>59;kf4T?_pmQ|Km5R%Yx~sH$()ws@ z&@&%6U&mZvNH2vUW5I!8{x7B4G()c5=#k}KsLPz1SlUTL%XGh`WPRo!{qc8p($h35 z3|Qcu2jLI@b#~|OqYHiU-IA8WAMU#hv<(pDc#FzG8SwAXp&o6RQKE1v1xuj?NW7rL|c2V`pPAqBL{(MH$2kkRk;+!I}?)MDl4ps|q=RA4;4hFv*Nl#o54YPzz&{NhOerZ}?< zyL+HZAC5AaU1-q`2XqCSOuynxFH|HvZ3wQkrTxVyQtA#Zy&35AW+i|>R(pBq1BL?M z1iT<4%4PF^b7ztY3V%Deq5GH0`F|R}a;%Ii)OMHpNZFS2vkj)JNGQISMLpDRHyQ-M z2#?6=zwHn0M;9Y+nv7c~ZI)gSS6Mb{pt570C=GsB+R|Q1R|#;N!oUIlAfAe%To_T^ zX3t#0l=V3*CaJP!5Yn!~n!k5yu4ayZ zPy0s$R_p&9EHUHxqpt7DZ!9OalqiktrTlBb18R?9X!4MQ#cgyw6G%G za2e*x{;f_^9dT_(q>2uy>GcjPh3oSb@iZfeyb2I*nEPoIV!!wAcjmSq0Yqk7NA#2T z_Cl$kdr`AFc^LMu+aJW$TRLiEy6o#}KK96h>`WYcOpL$daAV2{Z+&JX;J12oYJ+ID z>5sqJw8GD>3Auea;$otPQhKNP$z{LG9n1Q4hwJlIhWgSPMAzN*+r3?~!CXo>0%V@( zZhKx_@Y8hA>L+ojwQ7 z&)xZIm+K|2^H0+rFRocS=FvtQ7Lm+UR!+#IBntn%JKE66%g!pH?!txfD^Hf*zA;u& zn?nh_xf{S?rNN(7U6kee)OA+&K#pTV?N*%7PfZTh+hw-^$qG;Wl>hiHUiL}P3pO_b zo7E-ee4rmoNFGg$o|15zk=&8MTiJBKq)m|U2N)9|ttl0&5ij!>;&nC>NA?Y_mz5P_v7HBihiT>aAj4kKoa?FHwJ3WCC=+&=9(ZBRJ>P8V8dl8dyTneEzYr)QFEol`tq$K2;T{jJ+r? z-E6uqBV+uMkE;%PAEmHj1d~`1GPa+4Tp@T=o64B?Bve4}b7*u8Btvz>&eIV37LYe@ z9#O-5Fg16ea(dsN9-1f(as<)GE>W`V0Z0Jg0V(Cp$((ooWv3dhCGjEki*J@`0R|Uf z3e%WrOlX{m$Qx;VLftmDzjF!=Hj}brfbruf2>UVAS$@)wAX2)Nt-xz05E4ZAV zx*VHQZwiutBkl(dC!ac$^sqc_i3pP8_uQaJS%PG-`%K8{-dfGZ5)V}>U0y`trgdcdVX;DeJzcZ>6I0a8wMzOLEi;eR7($7IXVLBwY#x&b(udWKiFxUfLQ1t`}KA zGN1DOr{+F2nK!J#))nD0cuWov%{HIXaQlgp?C%iaew_AgINKX|Y)6}Fqoa!0StVuc zrw?8nI0|Mj>@ju+F(5g)bLIE-vawvaq>c+2T`gRs9f2o#{`0I0|x(r8-j`c~xrS~NNk#QQvUcpV6u-2am$e^>bG=v0a}+kJ%= zZclNyJJ49L5(0IKs8vNfOqasWIKO+GPM#iPvoTi0?%&A;6gzpybP(WQSQ$} z%RH5ERXZv$F$$6plYka1BE;U}i=I~d{vy@dI1&6OSF8970oZXgff|5#JzFZSaF=@K zgu867ZR;r&e*Ez-z-&H5y8YPTy(DtV8HOg$38%YG*j&HsxCnfGpS=m^^P0jd?PGPk zh26^|tLY2>ivqd?kX&JPySJgw1pxUG1@2|abPi0fW<;z+NrT)i@gjGqX_$`|r+x0p z40(J0Hef=c)SXE)@9;+Qzos-CQgQ{kS$e}O{PM0V*N+;j&tuvXZ*MqcjEMb5vx*1? z9i}3jj`|1bb&3vxLJ5v8MIru0RdLF#_z&(e!u4tOx*UVZIZ_2%FUf8^5Nj`+Jt9=yiUt`WsO%1CUYC8@liv{6QJG6-5GA z78)?Q-L?GoT@nbz&FOJ;zE->pWzXdfhCpmV83SChb?GVU_Jcf0N@`(Oy~OfF5t$G5 zxAWd;a95KQs3t0ssv3#78&t0~oP@LdTiN|0S;HRQ-=o3zp#u2cB{Cxc<&>gR=R^Jw6B2a*E`)rZS3fkDBxV#`fRoF88ulk+y_Pkf2vn0vS1p8#^;e($l zf#=7X2T)p{ep|6EG)TvIphQDn(e1-@y1cQ9BJ)jrKvGlZwHLSM5p&?6_Hf8h-PCGM zThCHH=xJ!8%;%+CCgt@~HO__08hwyq1EA;q)4?C`hVXsI!hPLaHa>H1eEbuuN;R@1 zJzd2s=?-4{T&EEjI3hvu-zW9)6?yP`yXYj9P!hwuHurAe&hUj>x4-BNyI+kfQq27- zQhnpuXCeM;EdigJ#m{-ZVq1xxQLHH*=rDhZJCsxSTRTp`K?CCwvaTW~FX`G_CxVDw z<56mREC=L}ShMJ5W(v{EVx1DZjGXOA+3#YzzS+X2%~#*d9-GgCaorZDnY6WwYEXM5c#2B2s0tYN&!A`{J@nDeKFJ17fZG z2PFC7kuumlo!ifidM&P0T)H}1C6mXW&F+U7Q0iQ$)s>r=>~9kG7hFe2GKQRy*%z!@ z5yO!KMepLyt-gvhcC|KNG&CGm#aGWLL}#$*ol6S6U#bhz25cSqh@5N%>^OB9wTpep zVKQd@lZAo9?DhEO;NicgRF{GBRf*u)5kG6|o<%{2@42}^i25FdvA3wk3bnj@KAQ&W zmP#G*)Z>>~Pjtu=aR(ZE@|!||yajJls@E<+6Nn?4Ir{cStlskzv^mTUUY|!EEgD+} zT?{^10DIl5R{x@Xm zb(Es90tEI2L%zK59NAhb=L~n*J{g)aQc=z@-#xO@Sn3#xJ^(rliX~CwdFb0e$yu$!EJj0|3ZbL;SwQDJ!no2rpwdumgGAVTzxBxUdT- z93bW)xZ{Lv1_12(Iih#8TwVaLL+&~hcpVBYWlJ7m<50vN5`1?k{FZygr%P<52nc)y z3C@`Heb71ET9Q$im9aCuT`GW;O0=Hbk10)|+vz@)J7+x1>P#5~TG)6;(7{jGDbml+ z8x(gr&A0>weGC-V0i=P(pNDgn)^i$5VZ3jY);DNtrKYwIR~85G3w}$FJ_o(L^16A} zK0xJBdQg6G^j_y?(aT+HM2hh89XhI5a~ z42Q2}?#}nG68j}9_~6c+eZbC1DlPB_Jjiu9vecKL;4W3FH?MUwEm9NwGD@N*yNLTm z$iRS6UOT``-GIo&A&b2Pft92nYHRJ)ychJlKO7)*g-EzwKQ4iV_AnlQx_@mE%_>SMzzt);^ms+g9LL%*B9QKr7MDz!X%zPqph3drS5T`c)!xAJ?J z5!vwNH_uTos<5oQ{P#(t3N`>_%4`})Xf#oMoubOeEuyyod)>#`dP7uZ{hQ(wzM&nL zF(25gt6Cw(d-mIA6QSteX3~AN?Uti1dqfG!wIqO21rp}>$p~5(EA@Xz=81#RJ+J5) zbmC*-hT;_;4;afpNrn=s5Wf!{^Bgn z8rIxY37MTx)XP+1_Po*y`J;Plr z{@B2}1-M)PqwzUSa#%|o@(kGk$Bn`YVYD42&`GWew+j&Isn2zXQgG1xg}0aB+H5=j zd$G>*%eEQm=E0_7RO?oyB2rtX0 zENGjFi(um%_OpA#t{2K5b35>#)2$W8 z0{eyP;=9t#i)T{cjI~@qvrdHd4r>{A5Cdo%J&rJLbxNVZRUPI^|BXdd`;&BRrPzmCRF#jh}la^{=O=w2D{=Oj5UzXI$}#f4(ni+gWIU z3_f1sd1if~eC&+~?s?I4w;{b*TT$nWnXvBKFAFci^;(jIcG_0e4{%s~5&9ntX&nsw z(i%r~!9$PV%{8VNL|%DY9Q>I%h?wy5o4rHfuRxzb8|2%xG2CZNp4U`a#()_S0^~ir zOg0Hvo#naFxxKM@xqPL_@VkU6@7HSBMYrBEhTbfmh*_&Jv0?%yT1%ap( zPEg!?s_!#yzAtxYchi?8#AVghjrGMP=sr4l93VDNqY(}pr2p6_hHaE+fz(#tnbn-w zP=8vhbW^-I7m((aU23VgF-f!hx=d*%U^Rs<7NQdru7XGes|3qB5R_yQw19qrZ)%() zK-e(jaol#vi=@(w2kOa$gL9GC!feLYBGS;`LOFPdDSw?+4|7dQ;5^Jubf7p!W~~0T zq23*DLtB>0G2GRt_s7apyBMd>`b#hJ0Dd3Qaqedk5OwGa&#LOqjuXOX7h39AzPSa} zg~{nx3hMz7QW|5+TQ#lD;3x@Rvq8dw zEdK$0{I}OYv?;<%Q^rnTtn~}4Gg{D3Hk|_Mt z9RfN=w1Nj=cm1xs>di<#2Q7iT4mWHELjvq%12{~303s@K2npH{B(^C^WVH)~I6w_k zW;*qnc=Aq2-W}n_x6&;fe+--y_cKlc)2EylU~yR08rXEPS4CWo)SF zRfw5v%yz(Ao>{jkUw|gVM&qN22zJn#JF^k@RpK-@zKh zoe(Cm0TmL~(YCa?j_&UvfLfViJ3ht7;$N`2SCSM?t`F6=+RR>sjh;J@b4AOWpM2IW zFLKt-orau%Rm_TVpY8AkPVX|=QpnJlg^#nVrKHYA#);ZxNm4kp9ezwYMl_x2#+qsftHJLpIHOPu z=?_X{<&ZFlB^}i|*uvh@i!n?SK@gGLop0pUCV%ZZ$Nen^dF@Ssf$unj3PS&wxdY(XN#-ZP=Zm>PC)gEC{IpfMrRnF| z`>x6|E6LOWSa|1<9)5DIQiA4wPaLH;q^iQnSif$#K>F3 z9qx`?b057#KGf0)YT-p@pP7|n?-(8uk~u*r-4)8O6K#8KOO@Mw{Js{;hl5^^0MJEv zpA=TpuCYI##urPg97yT7Ix44@ry>h8sxvjpTuQnP+E7GbqO-{4Fel&&-FckMZ@&Ka z_8K*q(jIIZE2Q@MWKIdHqDU9)rtEj5o&vo=IMz^p)3C6MJR;%`b$75_PXmQ=^AA7} zxP%;wO0c7$k@l}6KtF?Uv4B5N;qQAErBR+#K-a@O|5yV%HyN?88=E@6@+rYg?8Jy8 z(GA%5T2BAsV~n2~3`v2bZ0}4Anipx!YF6yd1DA>acf_C?urj%$K=S%CQTP!f4=I#5 z-N*h7VOHw$3s_}a%rj+Ln&iflSXie^-;AdM4OAxV%4jN_1K+qS(17K_*U{Ord`7UOyB* z2cYr%@fEwT315$>@PAvQ4q4f9ad+KB?vH(!tbj5%#pna0*&@tUf`vQ6$lsXEDSG~H zVsuYKci>4h1^(+eWllu+!3W1!N6Son&L~wMFmsB_^`6%NTO_CSFs!Lv0*x#u_-sT* z!QH+J*JWWjSwtBiiPq!v7pc^}PYMZ~)^q~P-iZgu`wl%IT#S1v=c!gVMe9gVg_C0a z+YgN(VsY=1G89yrjZ;2tI(=aOq!lGhAH0zbId8iTfK622si1M$47L4tPXeWK@9_#;K96Z%RJC>VTHgMw2DYRQ&mZb?EHt|w#ODlRI=+jG`>ICEL{b{4f)(Dc!S zqF(s(SmioIujCADa$BVZ>NhEm)%NFIck)qzc}P|zXwuTiJfqbN{nYR48)|jB*81zk zN{+A|Q=hH$o519J>SI1cx?X8U_mxA-@&bItf74=s(|kleSlse$b|!X2sd(=&_iKE z(SL_Ig=WRmo1vK%VwK%o&c@p%QHN@b6YLx)0+X20ca_bDPG(SJC|UJu4Kf3L{EM&n zG&s2m^`-@&9Ldc8h>-Dv^H3sNMg7?B{))5~NWaOxyfpOrRmKXF%(stUPUg{}+JBh> zYo6=Q?V>Itf94G;-_N(#x?fX7k;JpgIlyI}RXkL@4L(K^&k7~yphZs+Fv2PoMJD8m z2+kA8=`wujC~wnYqb0jiQpL1udz}{lk^aBl5#VjTP+7;K6B-UbdyYLtdWngYYmdz9 zh+Am5dhC}GEPm}^7BQNAzrVm7e7$dOmoqCWjer4!;T_~sXVM@dGT)8_zOA2?+GBY6 z@Y;VgQT^3-8^9Lra=zwt?)}JxLjra%7&4c4YX2-r=V9vpJ}@zP@%mc6CIt&Nt_40< znlseJhcgmy5+%=n|8Y=}?X$?PstJ4{4aoBD=s$q!>aWDvN$snhflkUPliwdWA6)mL z{ox+IkPfH=t=k6YhDJMP2+<>e8yS8YZ0P?$e!XhWJZ`Ys(59jJioff3JRtKF!Kc`V z;wC=lu?Gi#mWMGJ2{eohkiZg-6s%i86JjDoz}3QWv?LHDQ|@Zog$ejbewxc+;lJCv;tt%`JxmV3oHOcIoMY1Z82y#*~8UN^#aVd~A_5R`<;Zn&`Ut@X5@ zhKBw>F9k}zaM*7MB4dnRoDO<|9GwvDwfb6#C7!8y<=>rFKL;XWf-W2OoR+Vps{c<3 z_-5I5EqSMxM%KO3KEeOlr*2bdwF1+-j2k{HE7k@pE!hot@?7@h^-=R(%3vOXf_!29pz&ABLSOdJ%4(84<8^ z;kf<@sI)ADYTn!45?8SQc=vXBL5XP6dn;ta=NS(%H^jgwOa_qu0BFQC4giy1p9UeZ>#-(~e{=dIwref&siiuNlls%N4Ukn<9;3 z_~gl-tP}TejE*WX8?>BMI0!J?jnhSx8Re@JhSjqAQ}ZZLFBya^Ozu!xxRkt8J>Gaa zt3cir(Z}A!bpyC!LZj5AS&;H$2tCUeM2jLF#ztAHXOZGYLanJp21Ot5rs&#dtFl`& z&CdH_est_f5~z5y-Z)EIP6e7E7m+odBHm(JKr88z}b_@ZZ&GJ$L*6wxvGisEE+80V_K8Mp7ie6-k-8O2QBjEt)hLj zkW`fx5oyKe5j9QbZXayCqWP|PQrFnQ-PQ_xrl&K_9|^Q6RzU^&Rly%_q$UQ z#Q}XHx_Jm(eWqXCl})*Xst=#*%Q81C*y$T8&wEJ{V}KshaL=qhPf}?91T6 z@f={i)W8GSTv${z2{C&@;;FR@vG?3Qbz{Ghp_r|(6^GCZ|0dd7RT@2YGu5T}Zbr^; zZFt8B6VMr$5!ENhgZFG2W4Dts`uz|(XW;2MbH&}CeW#@x#eZIATf;qeKdesYn^D?ea>vzP0K6ue_#mhdjt zS)AvYS!0Z|v*m^SsweeVOY=r1rKv|KU*z2B{;qY~0QZ%i_CKj=?t7rv8|a@gdl_2l zgpfHdoR+=+i`=2fz-OjAptlXX*N#TQf56uubG5D%toQ12 z#KV$sUe@O2(B8kHggA%tkn~5lg97-vr>?Xc>=992s4*%8d8opoa;BQovwOX^k=e+2 zKug;}Dh!+CS5;Kpa6Fo%tbv%T1u84VY91C`zpwoGa`D@`XOVH@8d95(_{89xAosOb z?K3^U()0TOx#Z+DVjW@2vM%1cD!QIhQkYc~;bxQfq_e5=V8HaU&%p85DA+Xcs+gYg zraX|IsVRJ58AJtrK%Q?=B%+$1-_5xCKR2}n0*|@`+~0Ckl##nAzF*hi6HkR`c?rdX z2{mfBNv}hcpL`zQ04}PH z^pu*sXtAZd^5=>zh9&Ppvqkej)1c#_HGq8S92}d4U3$RaT}jX)hrq}#MWQ)DyKe|& zD@0@@fJ6ZznraC{Sxhs0jbvFfaC^B~bSu*fGRDAe|h{-`!Vr@>^19Z@-u?|j^; z(A>FSUS%AO=Ki2(<5;p`hcx=dp|AH4%5TRBWc8;GNbXr3ZTC2KNnyP{A^!LdGZ5!! zfNfZ)f8qw*fvg*FoA`=6=DuRFijiL@-m2aG$%r-xq+`eU?zO?gqxHugA@oMj7o+E= z_ZCqS*}~=N6=_}4-TZX^NJHoY{Auyw0@ZMc*p1sAPJP|UnT8=CmRhB=-$Z!xJI1<^ zR1jY0!5S|6<)mSgD}JuSVs%yF&4<3s&HvHJe50U|P4u!=Bn zeeLlr47FLN9Lz%*YVv69md%;u1n<3E6}?|NdwkqIqLorbse1D-N(gh=*d(U&PdlR5 zB=$d==547U_e%bknPaUM$VI+I+MRz|2k!81(EdHovo_nn8Ah==6k}*(LPtFWpD2Ag zXgz{xiX^h*_K$0)tTsi6iqB)mb@<;1cyAsenz40Ol`>}1@{Gs9H;%MKp&q_Mz&XKl z-ALm|&|OZGhB6nhjAab>F(-Rah7L~6#EU-06UI(Jb1$i&DAal^wO|+-JzLMlE|-;e z_dgni+A6OSAO{1{rgd_v>+8iI)=M82eC3rAzn#CbU&b1|d7wa3Z1!o|^=vJN2TD~x zVeloZ|7b9K!}B*49uE=ghuQTT2fL(@z+Caj;IG&KSXaK`@HWrD67w}P0P1phxfBSf zT<|qmd;Qj(0>yW`_WI$oh}2?^rrEngFM~dqZIt3EN?F*x;Vf7Nld+blO!$oJ7Ym~& z04}I1);kaata7E_6?zRB-x?P1>`1YXrK(XcB&C_irYgTxt{NG7pgS7e9?qtWZM#SC z-RXKg4NSgEHQ`!Ag&vhLBLw};+;2x7w+im9bk4aAM$hxxMO+nr_THAA%GoaL96)(mAw`> z_q`F#m@7;T_0yNHL~m0kk^6{Ba;`*O!^p5fsZOasibubsxSG;XcAzgiVsJkqJ&z7a zyF>Da<#cGpK<;-BWo01HWW(^6Q~u5{aSZjHK|wkiiv+A>*i{<`FqW@ zZaKYSfCfe!u|t-JTzC1^6Wg^NUW}JOdDBW@8FUDVTnl<%wM8vJI@5X?L&T!AchCkK z(fLtXIo-Nu{5gH(eHzyO;PB0pW43S3U2tF-xtY|0RsypLW+{A~?~ zdbEl6VL*q*pb&1p?lf!SB$d|a=QG~Oe5iYw+rNj%Ul@1eya0_BBvX-d|Iw&Ok~6jk zOH{_*NNK%$w(y>TN2^-tD{5xkD}^IO*R3GK+CVlONTu8tBqNHip>y+#bIVvJO5F0? z3X_C|=N~6P>b=hNwYEtbOX)#*!Xm}=|026Vd`Za-(%+|%rz!?NaVBb49GzTJo^-O8 zYCDtsk}fG9A+jJHFu>3!+Tx*Cgp=^!krnHFZV4$-nCk3i7frp?10hmJHixGTL{}{F?_~cm>Rx-djTca6R0Mdk_a{GH zoiG*euN5RFQ|GemZ^tah**ayD5n04@$Xw@!oNeaCMotwKgd`mNIZ7i|2mvD2o)d%o zO6JXp3E`)Is)~BdOm!Q4<-%i(691!#-67cJRWM#C=cda#zyMJVl*YQi+P?NDmD)zy zfA>pt$^}`v(C3OutA_H`ogSG~1>_L6mI~h+Iy@dQ7MvNcROQ8;Pe>E*3XSjs)O*kI z+EnVSYjDNdA+uo2y5OC_VbE>4_a~U;-~mA9E;r^qs5Fmg*KtY2;@@Lek`aS@#Pc1A zOF|fKT0n=2vHe)}<|t6g<@kV#`UiZ+=x1klZ(9C;D7y|vs@wPNZAp<7*-rM}q^y%{ z;v__7vI$w)PEmw7*&$B$CVM+c$liM#dmkK*}4@HwDmZ0yD#(^qEl|5C+vsX90pW_hljNS&1PApz76Paox! zY8*>)5nf2rE7N-!<}P<7MszGNw04w!>E;yFemlnsZY#~EU45+Vjx*NJ{Se}4(pwXgw zi#a|e*|pwpeksFVtQb(W$#!uyoR_ny<}UXst<7kciV3?fJw0frv$uTI1WO*suq5jd zg%>Idbn;x!Ws+I*!$r#OzXE?`oIs9QYG#`i$328-KV)t0Cf4yO(f&F)(}r#pQ!API3xh*4j(H6>{-tc0O!H zSSpa#Fzlp0g-|$Pge%$IjPAZ7mvdJ|0cmD>UHNOD*V(iGB3xa5aSnW5pJG-_zx3@= zRAx-!V+=?&Az-nM^{B9^zA1h?8aGLa#1XEc+g{UkWepwE*2BL3LdD*gKjkR`wm&l) zSwk7kUAR92^^N{v0+{285MtRI@O(D$7D}Xfz59>k^Q-2eVpJsMYeLFt4ZEyYpl0Hf zodAh8bHgT_D)<+C4?Oi3VROXopj;|~-A z`a|4DBRnrTd=~eLi7%h+!d>3lsez|{bd{x0=HYB!+hWO1+LlwM6qxzMo$^UV^)97& z_d!WS6?MVOvi;0UHpUQE3HZ*V^zL7oUO>msk7)SX#bIyqV|SDm4{)(Cl!{;k$~kIV zXdUF*M~EhJ`lJ{Oh6w^WIw+Km^lkfDDy3;s;!HOor1?Zeg}2U z%+tx;qW)odh5|-ohD1Ouaniq?Bza*1Y)~F`dt`jqr8`jSeW)8t{aT2c!GbOI^bO`^ zqp#`Fd~=w_J%+&>P_A$V5(p!R#)L~PE_#uC4zhnzi4b-LB>Ujc9{%JTIa+=7q>nyLasj}EJ^_i#%c7PmzwE3BGYSZOajOzvcL9Sj ztl+-?*ONo#mLikJ&0WO1V)Q{66os@UAgG^cD5aN%fHug?7ROdq?s<*jxTKsc`N+Aj z&jCQAP-N^pJ2UgjJFIIqCy5AsT-L1PVt=}6a#3MG8F|0;h#s}psL1_ zTVItK7XEs(l-@T|Iq=Tuc<9_lUpBD^yYh#KSba!`rgO6K{haRXbQZLK!;2$n5PM1J zM*>(N8q2?xU|)-@lvsBU(8vApUeXx0yC`=YphZ`QH> z6e{J(QQFFSH+Ez(hm&e0(5Xgn^CZW&&^WN`+piCIoJUt8b0kpoUiCfV|=3Y^K@q!^> z;%OV$IIjS8>*!uwhgsEnFxw6=hu6C-oSWiW|MVDd2+PW$XE(VA9Ln5fSjt4)>?NZ< zXZ+ddg6OX$6_aL<4zQ0JjAVZIU%ye6JC$anH|EsLBHk^3@V=4#kCNt6nf+{@_6+$v zd6q2r!c_m7y*SVhgK9(<60G_H8=SfqneZNy`VH6_TK%YgPm6)FrL--u7yaVc+I9&V zS9rRM?thlpiEs!V7QfV^7wthc`;S>0I+zmbGp*vpyxclseFmM&*_OP;!jC>Dg~i~& zlbs0Q^nmZ?v7R!65j=C|+06=`?A1z2n}W|bRUeb;Q60sf3Kv=F8qgb_L5&d8bHmZ- z%OriA%gUG?oI5co_N80-o*&>Rl7Dbz{<>F_C~AhJfqtya2rQ)j&Q1YZ4_QER7%wOI zD?32laS`f!iXFCV>dEgLJFX^E_NvM2(|}DU$dcqW&Eiqj^=l0oXzFJ;wj37I$z7NL ze?8+Eyb=kj#~Olh!yt6{SijNm_kQ~`)*%mi)W+r@dCJIahVN8Y<%wV&a)o)&UBti+ z(+EBO3qojk{YJ#1*S}QD zZ%$hwD@S|t=v@k2o37o6KHDs**9EwU!Z;219QMi`-GPwykc4I5^*3jOND>Vhd>+bq zU4gR*34dT&ev?Rl;eEv#elmIv9V1&Je3L#-7nVqa;PR zuZK`$rvh`Wf};%^eM`xkN{)wp`G0}Gikn5IU-Edhb~|j#vfN;x|L|xQ5*2I5LG?nO zib`aK)yQ_Y)@{UchxvFAMTM=)!M3f~Bx{XB*9~(2rMd!Bjn?>=N(Z=_v2B?674~=X zC2^8+wfeB$PBm$h+Y$$uhy2+-x6{-$zQjbWw5yDSf>Hv{1V zk-+4CM#%@eA(!@ip_@}Mxf@N7{)hoe+^%fjU|vVNi+4lasOj}2J6i84-Df{~osxu= zWm)qoh?&9Q7C3p<$ZOdn{Fg7J?Cn0XXe9_F_PjFLhILrg+MtbY2)iz7%+C`Vj$9pI z0e;_LmtE$hh<>Y{&CgSGYI@;yTfipQ5*&ycdOcoEsQQR4^lTuj=Ac0P)0C7Kh~d_+ zGlw+|Bs=hQHCd1V|FI+e7(Hytq(CqJ=*2VMFO?e5o%~qyKbSLpLw@KIc_r+Nn4}W7 zYaJVcyf`TKSrkG-;lR8uklqLcNU9vZlXz1gHCF8Iy zSlhRFm)Hr%Ftv1oZTHyS&Ow3}O$rcygHMQ1<#X2KEHznu-vrPvZ^-)%(zm^d3T4yVm2%R}(dFkR@Y|Hc|GcDaw=GcbOgQv{9}l z1AYU5DyWhyL`|qW#bX)=_VUVqL$%=hAg{q6`C+Ixo<|EU9UZ26Y_x?}ofOM-|B0V2 ziXETU+^k7+;hz8sF* z;fip=rEg#n|L2Rmq8W=pY)f25%JR*jpA1DBm=I6r@ca?(Q1eiL+3cqbY{Wj`zrD{N z1^*eZKl`{PY0z`|u(C=2+N`_pou}U@s+$z;eCei(hk>~tWo1UJ8^YtkXP(H}WygBD z(qFjX$cy;6r%B)wKdE(vOW$&7cr#uYTnFk;PBPqXC;iS z@MQv%;B#nlt~N7#W=yRjh;_UmKrI*QOWH{TsC{WHXU<<9T_Id(2h=(JvHo(oUcYdq zETy_Gm)dLFDXmG6O{T!3`8(*$`B{E(UoSNt_HbPiw}<-s@>P>A&5@|>#ScXqPhv2C zWwIirdK}ufOz}Iz?Ar7eG~Dgy2+m~Xo8{FBgQ6AIZSi1Ch_|QE6`l<~JYYR zk$c?NKE&_K=1vK;Y zco#{>hC|o(^wl(tOqF*_uf#zpMutc5(?p8HAeoyCbF4uyp$QJNLSF{fc&eV77POYh`pJN@e-lW{4gzxxH^wEk8MNOw$>6)x{xCwz zy(bi*nz&Ni-=Rh@_Xd&hJFsrp)>vH|`q|a|BI&a*pUUL z>+;qot{)x?aZ>14_xhWt@;R>ZjH6lA9p!5c9r+E|81ZrSvyt zk7H}U79?D`F}2eVojyCzbqUWhc^(dPCLkvKU<3B4Y{gdoVs>ctyZ!3|Y%zIcxZK#1 z0g=E)JMr00huB_I;1GsSif!!yRU-LFz|W!ii+&iGn1fu<|6iJb#>m- zVqJUmpt9|DdFTlgenxaSkcodb?Uw)o^PW``qD>PI*Lgr+S`5E^^8J+HGQVAJ!4~LN zkO1b+%pasl>5=;t2pvLFECAbvdkuEhR`f$tZ>#5t!8Wh0HJHY|)~CX9OpAey$=eqN zwqf5F{FA4`2DS(rY|N^1P)!rxtSu3YD$fabyCOQ`ZoE`8$ zrnnQ$PiaL%O)*^N6l>~C?9T;d=`{>*r~knQiD30w*eS)h-dmlvhK@F#qc)@cWWkm` zn)C-#HjLK6n^pD~YABBvC}I9a9HP%0&T4wFGFy6hjQ8Op~fws@xB@fs4w3$1_YWUfufD zlJbI^0C;CYOQ7i$ZGtpL7Go7t^K1pVW-+Dn1w~WI!)pKoTnB_sZ6yPL+5+0SJLP7R z%D04Q9&Xq+6}0!YYI{1KIL7d2=D^^)|MZQX?s1+%efy15=2T4UnSNsMjQtJ@HJ<>A zXZykV)4-R#JdK?+C}mcT=_}9U{)pM7f*TGcn;SYPTOOX%fnTR<-PA;S;v`s@v|cF} zIC>V0x>k5#m*L;=dDzACR|yYSRg)2a0H~+|`S6fe5v*2t?MBg!`ZRg7*fgE>=fz`) z$w3AX{B@f-t1w`O@4TSsbKn;h;*;RY7fCizp$V~ji(?h7YjIiRH@XwJ%L{g8IUUl* z+eS2zFqn2-dM=a?imi=VWbhLr<9CmcaVC5sJ@&73RfO}Cuwr*+=k8eZcFCfEEW|2q0>JSQG(wLS<#{7Y zOhT3wqU^_*IGE92@ixPChjNoq&JqgRkqSdB0<2HK;8xr@Fc5?|?cJdhW%OG8AyUso z{dlsdz6h>31?})-SW&QKcW8>3dGu5lfMu{XgWG`08{kj-#^_@DMoFG}FLTnQ#m*TT z9HNhea}xrgt46V)7VzfJgCxnb+7O@XwDB+QUoy13Z{jd!_WtjBFf~LO;>DyQTLJBW z*8TG9Yd(=xvG&)W>bB-m>I)Lyg!P6Z0J??@C#0i1eh=PGddZ=2FM~sNZ;uEbortgY zPPh`a%$S=@w$4E`m9PN29`c`sQwn_Zg`uD-^St7y4MIr0kJhfE;uT2+y$(+S3_DESyAs60#BYg8k`T(#l=k}ha^67KE&n^jnb+7xR_;WU|{*LO* zrhWt5&7-!F=oN>>ToQdQ1$?)z8F;PXz$@mY$l4j|AWh6`+ZgS!N;s=n%mt_xmCv9n>tvggOx$kEFM|=W7r$H{Jj8kGD z>f>K^CJn)O(+*b?sEXV{8Q5p#*@6Pp8x@DdP0r2zIynFi?yPJ+kOA%T-%n>pnD(6B z{rRAgnI4wlfwZQEV3z&DyrvtN7-o;+$J+u_AEX~EG+so(MlaZteLPXq+H%Q`B5v&_ zH9X<#fiC$vXQ^+hGIuU|kg+GY>PlcO{j9i;G7hRE7h@Dra2e~Db90ovx>&yPJAu$K z0}wRg)UG((}`-s+C`a0CMMMVp?3ZKG*Vi)}zcIfL)T11q=OI?78 z`*k;$_2MLvlFpe7Qeq)Eep&m7bMS4HZAF~bti`gDJdgrAN1%XLcdIxTMmPti#raRx zfGcvsBiKbrF1$8finoV#Z#TZ!S!h-qY03pG07B+WEEOErN;Vg#FoCx1(Xu(qZ)Z(5 zW#quWbBhMTw)`4Q8Zh*mFpZd9Yx_av9%ZH87RQKF`nwi_(fL}i3j}bps>8AK6mO%?qnG2zSFp(Vsu-O#;`Rjy%x`hBxz2 z=v%ylU~7mYr#hyO12e`Z(3_>P=7nX^z%Wv~8GD?*Gapo)ivOrj5pD%yY``Q{`dRJ& zZhbHLdI0J-9r5c$+?9sepeFq)dJJryf+m5+_UNV-yD!_KxuR+AU5aL+#4FJUdmP?E z8=D$ITF@=vx{<-8s8|a^CKL#soTn)j*(CohoZN(6DCg|Nxx-54B?U4>*Ye)GmD0{(9z>;KotwqpHztkjT zO`bR8uT24P9D)>A<3x(VFe4QZWmoZ#|_q<3-HN_lw<4bu@F?fLaua4vB9% zTA2wc94570trrfm4<*Rwx%eH8qp>bYmvM+M8>9JI0xK)*XX}-~p4b9YcK&R`{2p`2 zD?+{#s&M(OKL-86;Z!NvdF{s!U~~=zq1_(Z6EoQ$t+8pr@TOUIyvo<(xQ9}oKYHef z1@Fc_zH(>y@m1-^I!2ETM52ubk!=zOtw+ERUDC?aX$CwsP91sUNj9ML>tOqjtWg86 zD6J%QYI*K^9Grqmd_uxGdcfuvU=4p;YrB({D-?R8*acizON$~>`V+tpU6ohiGV>sB zuDEOhU4H9|0oR5~e0VJ<(aviuL!#{*NbjL0*{h!~FK)ZbZG~;Kv_tN6lk*RNZ@v+h z&2S7`tV&2PYm(@mo4Q+h3yF&FYW=aq$_8pm4m~8L&#ykRSgG4jXp;)qCjDAnPxm-KLUyCXunO$0O4R%cOB>kbci0uY z$U{=9OwWa_^CnFD6LL|t$0KWM_W8>3nfn~dKRO#(r}5ornWEzLQc?V(%AVy4f5 zY(O}&jRc@ZJ)~>?KiNyGLEWq=Qq<`;#=}%gJzqA<%>CSkJ=|HU!P1rnSS9m}`bpkay?dLN2Q2vxyfMk!Xd5AV5*gSCR2$)E-(|k215eg zW01eZ!k+JKHq*ZTjKnVtfWi3e%5k+8Vpq_ah}1A%yS4@Y(HVNI+EiXO=<(&jX5pbq zWSVAPtd4@Jt|%fFHK4l-@V+SvZ$90Z)}_1?e`-$%k-#4KOKI0y)en_3F{W~7aeis1 znJ~|n7dH3@L2u4Y-d3IO9#Wk;Ui_{UsFW}sMmOa7tgS$DUItnah(wSD5M9%K@8qxP zgVc;nA9DL7>C#G>S}6QTv;8M_>`(am#-BtyAAm!S47PpsgPZ%o1@!6k+;HyXy;&N( z*8al!k*FiMoa&g8EouXH4W?h+&33@{7^qK84hpVl8tWSwaDBj3FpkY=>hMI9rZ|eT zC^SbhApy_XXr=DsgZ{}3;$k}BIc#cPH+PH`zthJ9ChDa~ooOEPm8<6sAv!a;N@26f=Uga$J(`<7T;kO>z&Qq-oK!YyY^nb^2=WW z5_`}TdVDDkjkJxd1NPW=Z!M)dCDm%_-jlvF47sDfK?9-rI;^_}PB0_S5)pF&Sh0ot zmv;XknApkEMF6K@ggU!is_xi`M*VW=9zV!AJ3$aS>7^9KS_pRyUNt8l zF%SO96QTj+K$O`doyKPJ_1AXDdpwHP(Gq4Ftc^W3r~II0^1nWwOsgk?+oY7fOYC(p!sA+vgE%?8AV6~#_wI=fpm5;aDgef+ z+#!4?U+(Ttm)28-cP&7ZsT6l14e5Z_9JynWCtw!yyj`^e&SrKpsi-eun_&DTNes=ep z{A{C4V^YVBX4;Jm*N>*mQ>7*M#!e~6(lCeg2OCc_lYiVgXejFwc4=jL7w+#^Qu)GF zz^>Uxad`{F!2i@6fD0DnsA|+p-ULlHSNh^S%$05N$_e%tm$h-3KpZhpa!eIvvYhYp z-iYCuHjdJU&3akMbG-xy%qvm?p#W$JPXexLixGnLn;24%vdG5sj>T zZZAcA?i`dxSj_L7b?@-7LFXWgv62fwOOrKwI4*Es<4KyC#hw_+Bx#!I_v$NJ=TE^( z*83AI16G>VR>2r|XxD!g7D%5Xc=xTZf7r})u8fE+bS*F8D~e!q`?i@=1_DR;8oB)y zb_0)U0{c}eyREYpbu{ey;z9)`vE$`m*<&dyU$ujrZ{S7+cRQmYT>xqZpcoG9Z1~N( zV{J$-F+;e(Rn$i=LOxRgt*#JB!XV$-m6Vhi@3g{y@KX`)7WVS{ zUs(%O<+$#IgX1yKG3aqH7^HS#>4CeYFRLj-?zTUB#5R+cnpac`J*~My6$Es0J&=qI zbPpL|?5F2U#qxQ=)XH2J3dY8a z4o(v~%Fo>B zbS$78G7wuj6|1QQ-Yl%sU!1$9B4ji@?%UT4i6=xkmM~3;H z6J0qNZSRRod~#j#xf*yk(uOZ`4C>d~*b!mbcQ~Gp#zYPnLGCtUDhz2Mc|uWEA2w`5^@&RC2Y^~WMV5 z4n}bN* zbN~vmOie=KN44u5jIQak8FOi0F^gAjZ{GMpx_DkMtHn3!=-Q1p8y$@bej&it8Qb9a zMk6(aE-uN>P2_hfqYvw=%o_-5_(k}p+6Dpe$u4gF>BYGFCB>nnm?2TC(AUCvayG9k z#6`R?cKx8c*>`?jfF9FnLUiBj&b{pWs?2RG%0;B)j#%~lCNFy6s)oE2-j-rGTx}xv0%&Df?^P4LC?`Oo+vq9@=g)gJqH-Z4 ziXtekoRX@`rO}|th-lgVJWM@#6bhWP8Oi^;{B$vFoRB};_32-kk==i%fDKeq>9mA% z1VR7$!eY1df3jCV48j7S47e#JV?Xz&!eaJv}IvVN*mP;>nbdB{2Uf4YQ_t# z79n0gq}j0Q_qR~u7Eacq`~ykRiAI5&gaSm(v8sk!28q{VoTB%Of$AVlmLrDpt6}|k zo^7Hr-kK0uvFCsolyzJ6;mSk1Gj#*t*7S4rT~oiJaaZg7Aqxx0>+#D&i7E?iSOm1J zL&{NvA3askAf0GrocHaqaC<*+_{Q#K=PB~AFhQliBh=SqvLRGvX8g6wo|iUE_OtL)u)7*P zv7Ef97{aL0uHT@%XJqfsGnqb=O$J%jD_HqWlMKau2x6==bs9x&030ZQc_{WT{y zgAQeXSu?GMM=U3E+opiAO{SQWD%()1pdj`>Mck5_^fhO?Z)xP^(zP(r-6ukPp;5KP zr<_`K`aI^kj6VG3#pUI>&SGjRQk4;8UPrE-JjCXMRxX6m_E~IJ$Cr3q6Ab zcphXk@XZ9W<|D2b-Eg@444AE0xk&|ARvbD#n0#Wx;j%UlWF{3L9$rCkad+miJv|5i=l&~Qzxs`ixV){ z=aYR_Urh6zfj!;J^f)?Bl5wC@O878P7D>w_+kMdDvpV5iM%!ISXch}-e=Fzm=tH*ccKKK zG(~q(7&)67Byv%C?d}#b0DJGU->Zw^TZ6dsq=gLDI`$VL{ffR#?{GxU>e@!blW1~Z zPjekB9g<}Bh{JZvNUJCZvdHzhEvO>di_N4yvA3LcO-sbifs&L@t=Q}ypf^pY6mr40 zc$^;A-kdqxy`Wmkr;C6+0k%X)Z;P?sh>ZY066bBY!G_b2g>?6GUlh*OwT9sk-@2kV z)F3Y4%iczv2|D(0+WT@uO(Ap4Z% zj2xx$`yTL|ieIZf--O&nYZ~qX%?~u0{2ku5s|#-2J5(QduEyChVCCU6;^Ck7-;#^h z+z}jROPVs^WITJESe2*mUh)IIW#B@Xq&)b%2k=qtenkr%?nu_E+QZ|Nxi>?}{!c^7 z|H(p06hDeB!SFlQqoMNw z+1Q)a<2km6APe{L`FvZaCdfrR^mrs*^7!6p#)D291hD4E0a+V@v%OOS=sq35HpDA0 zowP;_Z~?pdd-aUeCzbQVmDb@wSh+>dYSe+K0@r5$jKfbQB{nCbR~?0hq{l+?3GAE^ z2j$N(Xa89A42n)~@flHhv8a=zt7@k3Xbf7+2JIufY&g1jrySRQc9lH)A*gxRkMb$C zEYOvLrSJlSLYVF27prruP#B!6b+Jt0{0elXBLwEXSuTaAar2&%_EbiheB-Q1sEEB0 z9D1(0kW0hSkTNl>FIPzNQ4R*p!QaN%FZLAFNR=Oq&0XPhd*2b_@9^_};xeS}z4Aq; zMM(1T=)<#|-U%`<&Kt%S{YS@G`wRR71LmE*ieNYuX2y53`ivEqKfwa*aoICBU>lEC z!r5F39-`uB&d0E~FqP%y>ILc~K`Ko59>r8fn{qUMM3j5Gh%zHqL?rx9MCaNsNT0C+ zn(LRYhuY!-sLnSRla>xvxapDj+ZU5tRp0Q&)uq1|kf#CVq_F7LU1lpXvD*KCi$#L| z`~L}jpJ{`S1g!O9NBZOOW|O#~cz-Q=5DDBQJ;(O4%vUb3-4A*s302poqhRBhAvDE* zVT@5MOoBgQBfH#lk{_SP`S{hTFnvDSSXTQpWg?W@btRN$RxzBo(q-eTXhEzQRI;76 zp10Utx^HqEXiw?g!6Ca0Top34b17Gn%NB5uQ*}F3yVL3dIjiFU`@Vln^Zl>Qct5%G zz|nQ1nc>X^cvp!??d{pjm{9n39(fjWVT-TfLbf){`^Wf%>SpM|j~j49 z7VASVRrUV%9;Tz?kfQ5yE@ag|8qlt}V+#DlPc!`GdSUs>qwGpV6EL@^ELEFiv8nF& zi^4C=XS^k*`{*VQI5#fasQcUXFc}mt)noi7JYDwP@~Y#kOd0SSvq!wkVn^@Dgq@HY zP1$eb5A)?1S+{EO1sM%pPEH>S6Zw0n$NIru7OLZLz zxC52-mo4HJ9<|9<)U<)T4zv5OAqPCg-lRB{>Ba9rv>9a`PR2Y-&){7rV2`+p3K)oA zUJT){r|hGXGYSn3$29#U+$_lf(M+z6BmbqMg>@*Y(qqX_J>0pF-u`r3#UBF6fT?yp z0A+FoF$DH^$k#{N$tSX#X5Hk{_>zS-?fS+Ukn|kqhZbpB`;B}GyX^ygNz)u6c>N_^ zf9mk+T2c2#>0V)4gh+wzX3q7MAe9=g5vigcL5U;V+?Fsi=hr+gv+V7lzDf*_0OF#9 zlc#kv0|8w)~yqd#ED7ER%AD#30U3e>W}nv1H_2ThXt1YzpMEjQn7tJ)$P55j~+hV+X= zq5H5Oqmn*Y^3S6Hi1_R-B?}O;;ftr8LVGI!=NuqR2}C`IqmIg_PFhw{2!1VGO24>Y zI@G0YCT=BbN&0oB?9)ftzo0!#9CU0uCTf+jRB=U*JI1hpush&%trd#Tkn+Xfkj7~R ztWr^r92kXBg!U@7TOXtgohSE> zh;Ap)+{=DK{>A7K4CCWDPgT7R9WpTq0_F%0LajnBTX##@RV}%1Bs@GTS+h-l9=;q% z*A7`r|7H(Hf2ba&hGGcfA^m*cO$3*@bE4{c9@iNM*#`-5v5oehc5jnMaXSG2NTd(U zmC%z?WugnIZ$jSy)kCvj#*z|Jald^TP8{MoVTFho)q!y2{J75&OOPECRe8Irj)18Q z5LUhz{u#RE=>`MV`UfTHYr;P5w|qHK83eSzB-`#HII6*4#)CapcQx~N$Sg&n2iVio zCVAOD9(f-7Z1AgNQh__#VC$66?Q1{9Wsn(zA**~5JGy+CxtmfAf3ETo{Q-lZw&^pS zdOq;9WGofaN{LYp)n^8w`^eP`le)J)0p?9+xZvsKcH>^T0NAL{ahOQ6Wi_Pqx{&HQU=6*d{lDlzpOQ(r39=$Dpnq+HwTv1 zDoH9=usxB%1+mau1a*#b(?U_X>GO1d1GlZAH{mDyPN4o^poMPhTtA&Z6PQ5GhkrrV zSt#I)^Lk?ca*9IFUpP%uh%mP`x1G__TFN94m7Ua{Zfei#Y7lHnMs(4qtFfY#AWtL~ z2VDb`o~(e+%GB!c%5Yoe3CfrOs}m3pKc*h^vut3m5AVl+`1Dl8^9ggZ=~>1-G}#Zl zf~zKjRlA8_-q_O>p8!TLG~1PBnvD&PFbc0A$v3~Ww!C!ZVVOl>nrp|M=XLJ0{5UkU zl^$Ps!2#K@M9S%P#Qh@tXU1zjJ~UIutM6G8o*524cb?6cgatVy+6dnpG@=-`$J;hB zA5ks{lo@99b>+v5;C+=R0dZ`lT5+l%C?I%(^iFl@)B2A14Gps?k2l40C-KS`e*8cL zZ`+Pj0_MM%-5;BQ!RkhNv9#X1Aisn&8TD>}NGcc3;k?0eV>>4;?MoG$>1ncD%DSY` zrTd~9vh1K!INqI%aQdnjAxCxMqef-6qkabX<_Pn@mlkV5`xgT;3!?}9 zJqGem%Q>X_ID7-|N4Z1WC^Laj=mm5S=$GBfv}))0)#Mnveq755);Sv8>dOZg=t}U! zNcaKkpg@#$Koz2q;-ObQl(^ZC`EP)NPJmJt1~Sx2GZqv~^d zimz3sSe1Io+ZFCtCXt^w4CJZi@xfe*@k}p~!(KifKxbNq_6O!4V9Xpe=6pWL7x8F4!j3o=n~X^ZR2ycD?wsY6lPSJek07%CbN>A2!~w*DLdoR>nwPnU*tjw>!%SJu!wUEMJF?gddZZPD9G; z0+?=$2jyPN=$F5_WB3R^oBQYSk+?S#;-fg|L=}NKM&=jAR&c)VR+GCvx7ky#`?9>p z*jV{&V@)=E__jc8UJ;-LWhTG`Nq*RIek;XGf8V-4(RD2Swf-kavM?-Ix8>=9d|b7I z@Ekw~7XdJR1p}ovI+?{wq(>Gc@0~k$C#4w)s z!rDzw=u3@IeU&?eyJS`eRdT*&G#)h%b#+Oyvg}!XiWVfu+S05ek&pjU zZ4#7KZ5a{hNi6xmoP59HZ;X0oyhen)nNgLn-gt-inA5t>vIo59x{Ww=l>)~j0avSU zxwDc&gKWhMRjGhw72rgz@f`Pq2t9R+=d#6tiQ2V$PUR-CV_~VvLN3CQdSrw|+MJc^ zmj+)nIWk_;7cPkn9{ticxl#69#aqHcU1|8)iuooheSM}-`-B?XO=m7j^y7XCg8d)H!e^ zfm?p)t`+3sceo>fSX92>>D9UvP0iFpJqlZ-+=`W4TNGbUe9p@;Dx@md>r1k+;Y#38 zU5Sd%h69hy%}=Kp>JV*y1KrAA(>^mJql?>tc6n(xguqC&pgg}T&0kHFZExsQ1nq6}$R)<7-- z9zz7gF7@7Ih}niT@d-jU*;v3HXOdDcC$4!h{nNNxpL%WvA~y-Y!iYE>>;aCb?*%WG zZTlwt#&q_uu7L=_Uy6!OOjnuupGCt*N1P&CyOk0K6-{@5{`}EcOfCo~rwTyVK*LdB zdTDAjgXwzr$q<6d5a>5^JUydf1bQ-`^V(^3vDzNW(FwSA<>d#|A${z$g=F=~=L6ds zH`SHeyV=F!LvKAOlDl1uQZUH4fn4rswc&)wl&C%!+?;dW>;k%d{+I;qV+49m_IYCK zLlhGR;8k$KfLx2ADZ;NCW_u!t3k=H+5j0GQxgMWu<f$H(|&oR8V|(+cCnT zzv$${c5zYeC-7!F6Px;;(o>w32qCIMKn0-7irlB^o|hgVPT8P_Q=K5}DY<7f{q>@hGh)`W1_dIOi_&pv6o=Bd|HTFg%?qD-R?THE*| zUrC{RNrZd%eLvQf!?Y2%-hZjqq1$6%xW2`{l*^sadabF)l6s$ zV(}je3R^`zom;}tU&1KQE0?RPzB6Y1@#nD4Iv*H)@Y|ju~qh1;o=1MKa=r+^mUxq-<^+j9ToJgLb_meF{AKjqP2H^ zHmrJ!TP{tU1Nz_KAHU2RlmEzq~xsd6ZGe@THFRE{n zg3k{OK*u0-Jhbn`j~11XT8{5oQ6U@8Jalc0nqAJ$k6X+_UWK&PywrX0$67Xd$UXq( z==?59mZCDW;{b{7?b6>$E64Q%M4@m0_6*zH56k84wOH2=p7&mGy+8QHlUmBQ7|#iB zY0lXUn|}i?S4CD{OjGK+EudEv0m2Hrq48f7M$vJ1ZoUGkjgY+2xw+h&vp#|qprAOm zZh=I{$lfzShjKwfCaK>L7t-_ApWq|Eq%a|74oAYJrRyc7M0!LjSJESqvb%H9K2b9> z`{UvT=&c+xKNv;z2sZZ_-b;p$K_e?F=Z~utTqs31Z7+L3P)J~^^yJDo4oLt}KMvE7 z>(HGD3Qg!=M6fHQ`+Ic`4cR>aRvg|0g-H5&jZ7gk_Jk;BvNKBR{vK8mz4Ipy<#o65 zO;`N!`xZ3rAe^$7(Q4q0%8Sa;H}gDAjcqkS?PfY$EDp2&WJT4_m~cAp1K6;lYO-U) za!Z8u%(f`*kOBny>P*n@y2K-`;A8(%d6L1Q%XlNS*J@+;!ZPQ_L(aZa=$3>6P5o(5 zRZ~{20+(+kHr>yo-I@c?XpQ{tGTL%`ODy-c4=~HDO{O=#FnXp>YwMi{(f&DoKGjCo z9^y2SWOa5^cb%0lAW+;I7@~bG>ck_E!obp+oEE&~z*b_t)|Xzo-`##Nh8Y{oAlRxw zx^+zWx&V;ASoi%L0&G3XrcJ&+TsyRKc{pk)6G2m-oLc+ zRXC2n7+r8?hc~Uv>NCx3$TxlP_k$7cmF(qrMQZoW<0h?K;II9T&u%vEDM11Uzn5Fo z?r~~rq~i5j@fKoX{8D!&e~UVo%DuI3m+VXFVJ6j$A0mA^6lSRwo{XoyN)a?Q|H`CQ zsr51bK0PL%v50}FFqqXi?cuL7JQw7g$gJJ#KU>#v-gfXC$lnSJUdW={O(r!qQLCSi zY~Y(#l-}jvTtsq9G2#-+7VyE6je|fJtpPE;_BvVcrLHOSvV8#a8?!D*a%K)>xv1CJ zD1Sk>`0>b@vQ&?2-9l&c8mI*LcQI>w0C`u3>Gq$MbZKD-(zc6TUuW~I>ysO0TE5w0Qo}e%a>_a>w*1rG>ndOE$V3 zy3UA1`blK|qlemj?<=1HPbqeTPgqRLH15t@Fw(Zgvv1@gz-k&bJY;Drg$PYUT>XAb zas~L)=FwBl6Icf944@nL3*G<&4`I^Qz8Ad@k_Av-@PwobI^ z!f#66GDHTvk?Kf0?Lz>M1S^LRb!)cH8FJ>Mo3-S`YWu$SX;iA7$0i7dL{6vFus)CGrHx%p44`g2gkl2e`|=b> z^e2AS7ua9RVP@8m2RU;tSh&*~-+&V~`qe8RBNeW*gN`*d?d<%a?FUOzCX+M%HWyu^ zbejAcHTwEnLH3kCgiA}q^;R}k;l#l6`Ht#PHdPh+xm`d~=e2eYCtlmSF-O_aufBD9 zvls%hb;e9+P;MnJ+Q4sqE*f|<+K``+(A+P7PgN^sZ?^zYi-Wti&!+GtWm>R$^q?dP zjNOd3+C{A;zw@YacdthORi(zs7jNk11LCt{pkrTnv{sX_zhG(J8BdX;P?K)KaI4|v zv-l5<0+F&~^5e!YG+Q6cT+8>EHDO9qH-_9oRaA77kF&@~gC=*?5!*8x$wtU|ILRSC zC}MAt=v4@;NsKSwrAW_HCi7HI?-Gl;tq}R^t%5|La!2p4c~54JRL*C(xUm)Se&{YR z8dkt7(zxa)xs|pM7Q6_V$474xqSGtmh2(1g*(){&)sgtlPd7$h*n3>~E{SLAw5zap z923I(;ZMRxHx+dqL|?_`2;Zj{cR=fMniwg_h9AGD7XqdNpk^9D8C(Yl75-Z(zDx7O z^ehuLf>_PnfXq*12?@9s#4qvPd_qt1ibn5Nr$Sd0uQXi~$!qFQtgeU=OcpqkV;q)C z;s+mVYHy#C8^CZ<;%0guF&ts%>sGTb{VYOm2XeQ!o$ld>r=f(DcX7KY6N?4)GRfLG0wRd!KBfw1&+3N|mZKu`JlM`r z@~pKyxYiEMg|h7~d<>2Q^-RUr@6I1Pm{JDR&`s|Ut793YFnHhCo62OiZyy6tS<&cQO7DRnm&E|x3m-pEFy(Ww!xnF4j1M(x@^!(ZU8eE;2Q0U zyh$widJmn)G|3pdfMMZ*VK?J)+^*PwUo#$l1)6r4dSUH}{UdqM**O4G-@Z8<`^wNQ z7Ef@L;XRWCpJz(C6-KEjX5syhmtDxCo63NJ^F&pofMAZ0bK1QxRiB(o#wZU-&wC^> zoAlU~!4f}2RQA7Ad%-+yH79nd>tAs2Jw^7$ZEvI3MAva^Q+aLZ8KQ|;`+uChXHb)U z^exJ(D2gc3J5lKf(m`nv0V5!Uj(~vDi!=f0iGosv(7Qxx=txHdA|eC?gixiI(0dJm z6z}7I&b>4D)0uO=W|)vX`IWubT6?Vk1PE$hR}szkz;5(qo4Z4+y4bVz9}6=3(hZuq zo}5_)py@09CJFEsQfr`N%>h{@V{%TNb0|jN2$6UObOOmG;Q><)ruz^_-w^n_cI!{U z57IF)IR1nlPNz6K7j6t6#+-ehfJXfX{tYk3xBJIIqXk^=2jR%pp>D6Ht0?K(+DfW6 z-$VXV{W)GwBGndaS0W+LTC#$;$<)&NzAh0EfgSFY28fQXHKW%!FV4F^wj({0BedGyQr1drsj(nB!UPC_flHmwOZJQNrqif8{aQGGk1$j z+D7Efk3yu_$*`vt!uNeSzcOr&40m3;+bK&Mi646Wc7uWeAK1K+;$ur7S`TK2JN2ET@M&pI|^FbhgRHKzw82#g5kJq!RI#z`azS9JXsp&pwX*L{yR(MYc* zGM)u1Yzx#73Oo#UGVUCyE;Z6i!($X zg8;&NB(KiJxKsCrJPY#|O=+FA#DXXeenztLj}xPZ;DIwRt`0DRnk=Ngf@Arttf%7k z(;gvuj=UGm*OoNpGT)UJPKhOf7S^@9Ux*y0#zM`Ek};4hiY4?Pb`s>aAQWUbaxX}c z72mBG&SJn(*eMn(?ye#+(@hahy00NQAjSkw8dZl9H~6uDs$uXbceIj87vkb2cZ2!6 ztn$MiF>vRBFJGNzn2zf-3=sotf^eWP0L&AiBdpgrVv4u#VZv{@x-6EJ#~r8{+ZAX% zwF#yhQB%=`Fr)1c1|*2(Q{>xrkF>5py?!9%sYj6!@0kce{B@zV(-{gGD{@h0kKVv_ zfeyT$bPQ8Pjbw%BYM8|GsBj6uXG0qwwIu1nxI)wC4QPX^Wm)teQb0#v2*|0&hO!C2 zP$tg(%I!D%)Wg+LQK-j#%^i(8Zaybck9cj~twQlp8vuk32qgX3{IRAN%7Njmsa*T}2LDz|JCp zG5E^|&(}_j&^C^3pdt9XkvhV$Z&Jz6j)Ve}h=^R|h}A`hyyEiw;vl3#7G3BonL(3< zu;N@A1ZIU?4I#aqe#rdsL#O`-(S|DKn5+wzsH(28oZS?)n88qPyB8cI(U0Fx02ry0 zQwLdAH&kW$AW)>#zUL>K-k-eaB~)Y|e=fM5oaqn|MBkiSaGLv|AeIbC?iEA`wMmNW z&%e8T3A)&kXOX=8J;=4Rxa#A*wbak&*>FNEK%xRNCNgkGwgIA%&k?m+GV~BF0~QnG zkpTf!?SN@MZog`}FCU%eq6ep;HgTv((%McSe1JgaT{rv5EGNk{r}@y80cGO#?7yFe zts?Q^Yzn9TZ^p4|w-5xfjn0}ix*MKn5p*2hv)KM4>~R=}VDCgG|7UM+9+vxQ!+q4C z{W}av;S_8!;+3Rxa$~XS;vvhxWqM%m#V~J_R25{c3V%fBtAaPq;V2a7@HnyvGxjsX z^+3SndFt1p)Y?G4#hqY|wiib? zuQ$=p%6dv=aXzy}l@vK$+=U%VzufPTB=4QM5Nm;hV$d~326U%P7?N4i_1^>HYgp*5 zmYFJn#)GBU=BzU}&=Q)bAeKl#;X<)f}SqW#ia5Sqw;&2?nd9c7x&%BGFxACYXFUeC7%9V_%vbK?BNgg!kQDz9u0S=!m)SV`bB!Xg&0WMO7ZN34cJ5w&V z7|Y7~8+I?HwZgAo=fcx^ZJI0x^ppC&eCw(j*iE)3CHImH}%TPFAUpy*Svi6 zOIMs#F+R0E9oke_6d|&djw}Ml&NUuqO<`{(wclxd3hmFC*j~5!_5t0N?EPB!uxD@C z@7pMB>g2bmv(;@U{euQMyPjeS_;z~Vayn2MXGTut3CD43%D0*0KB9#X;XAx1)bWf@uiI~sKDc43fe*;_7m*Gx?tS<|;<#umb@o5D(ob^SHY}S|R@Zs&Nhjelz+R=bA1mL!^T{fF?Ol#3(o?N+nDQh)lM^(NWCc>a zYC{jOD~0QnkXuEanr*LB`(opK#N*=A!W_wUJmL<<%q9)SF#1CuxKb~G%-cqTr%1Vf zOh)g?3g~_G{%*?>b$E9E4nL8HX=I#|KlQ=sR(tIeRTYcdG1cejf#LZxuQ%}u#nQ-r z)Ym%V%q+WwXupc;__p=n%(wY3Yg@|JKPtX=01d%(@if*Dl2DP{CoVB< z3>7*{$Fr@R@s7Jim+)@Xm&64q57$^-JQwI=^)^`CL|JX&B~tTvrw&6TbrvUEp)%-w zdiv*sl-cq);ZKCr5LH?&KBr)=I_JEVIvFRv&DDRRgJgPrh#92ZNrgoq)Y zkZoFyWcui?(LR#Ij$dy=61=r6TzPgd&M)w;0vz!t5ko-~5Wp*AV44LuhH$c?Ss^(& z)#XnAfm+i4+h3}7CIWc%8|A@2E3hF6xZJmLzYx7m-QGE#Xsrep*h7!_h8}%in1ZuI zyschxlIvN?mS}PJxcFEJvlZI+CfII@V1sVr zFdV-@A;9N>q!Iel`Ewz&Nxtc(F?1%NCYzf*-#ZUYx7h>d-9z6=FH`YK44;zqI8@_+LigxYqTI^ z9vAuU*Z8a1>f|g56+y7y-YX#AdC&&kg=Aa=L1E%>a}nrpZpZAZlkW%HI=r zl|6{7I-iLw8$aAj*wjKHBlTsIf7IWgxh}VrpW8>C17JVTex+{G!OWiBg2rA1=(NQR zj?XgcY2I?VNyW-Le3IPezc(BFf0DE|{C|MhOtk$k1rm)_?06`AI@nUEhA83WKD*N( z4a|JNuK6qp``ka%s8JRy77gktyCe{*khVXnneS|W(*2#-Dy?&kCjK$xqQK*X5YoBG zT%!syqp|N3Ds=iz%akL}et#AY{x2%$9YvPJ|Dz z^QHbUGO}+p5romj9~M8z>AEh)a#7*SVp6fFYgTnbQF(YT?hu~C=`q3d{B;*LPEMaM zZ&b4MY1%MHm`G|2OL37bb?&b0>*~96!7umVADTT*>HTYu6y8R&Lr*zf>S_G3mDt6A z*&%Q@Vsh?$%V$k~W->VY;=X^2n~OqP$L8Evd_l46?N^0L1rNpvZRM^05z~|RxpSYW z$5AA5rhOmmw4J`zSxU38aEe#q{hq(Ib*g7GJx^qEkre@WJ||*#J#dy!1U|6&>0yeV zRkrd^(z%G(V*7G`rLo8L4+^(AcAisN6_>>1ULW+F- z;)r?j3ebuF9`2LXqvk2O#3ZpfpFW^m zR%7WB+t8ZW zl4{PRsSsnXVZh<3TxWca-q?hD{t5EDasS9wt@@0<$`#(Rg=L-h!(rHBiC)3YPCfr2 z@VTD^9l8um2NB4-Mt7EqijzPMMMbf<^)uCi^k?>vke|#?;3V zHwDNtlqyxY#3GMS#CxdO!=8 zBL8@SQRNZ(=l)Fyin|RN;Hmi--mdtpsg3%fU+MQzxfD>W?)rRn_0J2l)hmo0`x(7- z(7O_&)b}rs$&7;CDY|-ROTpWxHf=hBvAWYl)IG9sf=uGyL`72XC+0OmptquZm!Zm(t(rbAi-uTA9H+s z%raAO*BZ6G8t^)Gf{rg)#$2=)g%nEPpd4-2F1W_K@@_V11xATAvSP?=8_DH#o2$}Y zH)0|_HYk-9B5-kK$|11r) zOt^I2!G*5BR4jH`;!Ys2e>I=M^5@Unjs}h z_nj$DdCBg&{4DosWpsE{l-Q`qX45Ipt~U|HGZbyQzTx?;FC8&>t5Fc_np#S?-KVqD@S-J{mM()6ymM6A*IWlNPAj1DGCWwkW z9(cy2PC2qTR;X=qOt!_cB8H&^jAJ~70;xqKQ^WT6SJ2Mec2^<;rW>$KfiA@^f^%G)=ThZtCTN8h{c8eb%dz zqtOtdzbxa*QhoeZZb{c!Q}*mEH(beM@XitJ)ZNFe;xUlVw>(h|JTT4>`r*a`r{$Nf z&EsiVRdn?Mdvx8}+Rp1hcP}Grmc840dJ{u@4eU4gsnf2ayyC?#qCFRe7A_s~{cgRi zI^Sie@#DuXM;OG8sZ%wc@_Ud#X&(R`Tem0nYTnNliRm>g((ct2XFHSWhGA!{%Y?~`#GkqSP1Y$r%|{) zy|4O9n?|?IbR%N&W7tbYMN#=F>RwN!3*l#8kq70A-joggRiLo(=OwnB3H zXWFR+pr+z&3(Xp-Ya1aKM~zs7fDoTI!>a^ymR%18uNn2m{1O*n(KJpR#db){sVe}} z7s-P}pl8EK&{vbIpurBt$^W_B(i|>KcvyM0>ISq(=1ApI-k&|b_*Kh{f_=Vd&?8ke zpsVTtel}d_9skSIy+%;|lloeHhb^}cD)%0g3B(sk%Y}K?#pK#*Lc+JfKBu;kr@jHp zr)HP@Kv6PS<7BJH^;8E%G6^!;yiv>3RpO4k^3!=RYRHB_^klAUs~Ekmj`;JyO<~R} zcZ)zPU_Y82*x)P-vpc|oJ0w08?@3~{zeLhxzP@G?08Cu;d~=meP@`b4pZ5&9VE(^pmBzT4<4a9bagw!|5 z8V8jnU2@Z`-rwXm9&fmlBQ=`YYbsByB$+7{eS{KD@bJQY8wd=I0VF7@F`%RCVgJ<~ zWGnoqsT&_I^r^728re%sWj=nCUt0x?jO_|tj@u)mH&rmLm?c?#3kbvnHD z!hHOzkJ(XpOW?hx7-~|yzgz2Gj;{U_nw3OML54Wz+_fjR@$ac6F#Cb@da0QlTT*^F z*5Mjgi(bJP?i?QoJ1WiSY7w!|=aN2Fi1cm;8Ye3k|4{9^b|{KOgIK`^KTM9cPg7yx zR8lpcC^++zWH;)CvZtCm0U?NC>Qx%WX;Kp75~u!1n*z#%4Y*t7GPZn_o4!7zb?bSM z{;`>;lA)tAA-!`2IXJfV(t*mnyj*3+R09@jedGtQ+o~+%`XAH>`p*N&d(O^>Z6QQF6 zr54qK zoG}iFQ=x~0Cd6nDXWS7Skv*IFVq!`2W3Dm~#47ov=?m6}MUw`Y0T0Hk3}r*Z`i9la zE=igTW+~DNo72x|$tLTpNuB{5v<$x8>U!SRq1tMzX;=J=VBQfKi-TQ!~ z9$yFn)HZS+N;luvRAf7FEWi14CEqo)CVso5tWm;#8SiI``R&0Q$z>_gyb8ppU4O-V z!V!l{%9~@!XwmLwGB)_=bp~Dr!}u+NS(@${k38^PRg?3so1ubX?>q z`YV47CB~CfkM;giO=x^z01xv66vL4LQ@+(qaCxYI?)sU`A*h;3ys3qL3H^Lrr{U0L z71MLjX(B%~dHl`8RZ7?3(wps>*XSu7U1E*Cx`A>KpYH3+3KZMm`~I=J&%Z_sK4}Gm zh|mi>&d5AUB-b}QABCErn1Ltfj=MAtAYrlA?PSp2sfPa^MHWh!KDI*VrU~*S?|(ZB zeRZy=i+(qtJ4B$FIeOu2i@}aNC2)(QYKFUQPb6Zc>TH{VI_L&dfPs2 za*(a$*PY6Y9(Uc2_HX)*J}1(Ko^*3E0_K|UD?8PU>6jB7MGn?iAG{P4UXa2NJ#tsM zzIk7NXX)>h>&}qx%6TpNilK?O$#{p~g(>V&7AOY}QwZ%tQVu4vUFWYhxp5H|wS=?y zw5UetM0ox3pPrvkWP`v9TfX$mCd1Oc^M@1btyPX64fm{xu`-7;Ay4+j7{~2{U7HBS z(=KM47TMLMUZcSGSetx9T*NdFxOhNDriDMympq>!uQyp`;s?`TtW-f($h8cJYc}WZ zp@3EF0MBzsZEoaj@O;au_33Wg|A!s??_Yrb9r?cjCH}p!$)%$`l=pNW`Ib9f$i6#i z-uKn78ClDBU)j%G58&SgdL$R-vSa^JwZI|Ce=yFb=xK*9DSgKk@gLVkS#sY>v6nEj zuv2@h_(1lcwbl2Cne@`zHJUew!OUz=_V(Etwt;dWU>XCmav|!J z?nE{;t(k=+A{)GvHrc(v-M6RwzCM))xex7KZ)#loCssidx>CW*ug~Bvj9TD9{@lf# zxgGr1H||}m5!Zjx!i#xtL~>B*ZPKlt;wAi>R(I94bStz@EESbd3kS+jE})AH*C1cA z>G$zmT>r+#^(W;xc})GQyr=nTiX1SxnyZ~-y*%0cs(U}Ld;Af6K@*x)oX-Is2qj6u zTSmt52jAL|_pPjj@T#J2P=W@~ZJj{TWL#;aywS5nJ8b78Ft<-IjxlJRkdVPU@yn4}F(73T-F2-#au zX8__vXE!`2vfuBh<1}sBaAIE7BgV}oc=_NP%{deg_Eb0BlC87Nua5t^l$2^1$C~sF zqj%SxZn&2?5-QSq74Wq81D(8-JcF^t%|jeZuzYj`QAfZLn+P-ku(r z*Jdwh4voP3GLG1zAU%f5ZfO~`D&9rn8eakn(zL<#v8OK-vO5b%Yb4}$*iq*&9}V?c z*xl}So5jtC&9zaL72{rnl=Oq55TrTr?gptv-N{h{b)mL6z+i)~_hE%{g2^CTQUd4- zISN&hpZKqaonb%`p_M#!QU=^wVc)$Mk1&g-pqoTRHh0n86>%JBY8^augu^_#Pne)0 zH;a%X<~@^QT%RzAteQCx5r?Hbo6G6H0KhbUz{m8ink24ha5obnSe2fz0>^#2;PdmqSPMVJ$qzQMv5vN*Ah+N{?cLRnZuuOX z@ORy*mm-WEz=24p!IBeKWwDo`hDH_M+Euxao3)4 zkaJQV3FhwVn{H&A&#pk`A%i?D70FKkQuw7Wk}Dh|7$(QKp^lrY#u1k z2j*YN2t2%6{<$?VPH{@b@81{@FpT9S@Zse_|Aus7947G?h&Gvz0(`pvB+1@BxwU^T z)HXG2Cs=~{U~>|3t}nlY6o?-Zz2k0E&_9pD6G%4GQa=-CXc&Oa3(5Dc({u=}{vk(+ zR9l5hisJ9V;sc@C1XC>=Be%Hu9f!YEQKwcvF6J-(z#E`DhtRIm{oG^q&(%R2WDWSi z0am-fH^6ibJ-uj2M%2C!fs8+VUM}`YSeWE*Ns-$$BAoxFsyxFlnH^SZoN|@`so2Gj zE}L zC)bV6AM3k*DPs&B+z!fE!B}MviDhZnGI9+)*M^y1f4n{g$8ou&ZB_$S==~aHh*PY&_^%TvikC~ttF>3*Y$w! z`eVjo*pY#J`zqN-B8!JTA?SM1<%mFZ!04bt{QN3<8R?WJ8Sy+sV;@x|lQW7N!TYi8 zDo8!XDs|}}xRr&Vsf48vgZN`dJnvnJX!e*O$9L#REgp|F=Mb34U~VHv{}JN)rKf9I zushj*lBNVdgb3cLoK3pVoi)0s1){&WmK$~FTl?3H85H#%=d3FIX)6gta{$bXbA-rF zivCh`J)gQ#*n^dKGEQx`5OFH)9k}jJKRKWRIS$9*=MR9K%^g%jJzwX9wiI`;>$5Sx zq_R$I57_&Z9;Hg~w z*3I}BkVIr35#+vBLX0LE=@4sl3TD%_Gj&~0N?tDCg^C)F4&{Uowg2Y$OV#+5f&p5* zci<_Qie~{qF|kSVB-!)Rc*mBQeorrHzLbF50xBKOJ8%3c;B&sbJ81WH=H?P= z-`XLCh$KbF81Ugd-49nN_5AV(<>wrfumT)oZ-O6d$GtdB`vIio%7k~fryOkp9@}%= z1`>{laL55rBp;t&JDg@xG0936hzX)aw1wry6f26xXme)FlSm^5K(lWmJH|Fa%(Y=l zCtD+eP3U+^3MFYD<|B3#KdgJCq znBCY1@$Zp5M+8r&CcoNeIZdNoQu7OmQcp*Zz>}swUhXqMPES;W5KZ~HP>J-eduYN2 z5jF#f8;#1%GEKRKZxo4pTpXk8rf&1x*P#EK$MOJ<%k!W>SPTSx6Q;<(n zzR^fTVipgL3_Czm9?E{Mt;}P-0RP+7dAf3>OIdE^y-L#WS|U&WQ*=xiKpy)W6li_t zJ21}5-P9kVwI|7LaBXvaXdDCbp_#4HMfL$u7zBr73ih2z@bChLq{)PsUjE__Sx_-Q z6J85iHK;E0k=kNRj2CRxPWxpbfFmjanN&3elLd8~{JlmNxmdLv{R7z|n7!GrPgmFe zxOZ+n$)`+M;^Bk9?fyT~y~0g7K?#P_^7ybs!QS7K7R7(5yz7ic1mt+0A9YBCHIXsu zX{Ep~^~UCC3fM5y{4q4*`o75bZ!aXPt4|jqWH9^3vuz)e=eacgfoKvq7!9C^A`s=) zNpQrzuhOEVZ*zqV5KLfTmt_Dgt?$Em%b^|ZqyUu!a<^Kny-z6fb+}d~7&%Q0DGSPM z)J?i}_xhVR3>}o}6Yx2#47Zk2pZYD?ZSs8**3e8#HvEA9xL#7d2e}KID+@u!gI;_Z z8*92In6M%Te9G4U)+`uDd95y;j>eu=ZAg;1>;RYu=;S{71KjpzJDZf=%O3S>L1_xw z8Chy?5Tqu=`M~y=!W9koD>yw~^k%gI&V3}>-9Gt4Fg+2YIT1V_TI5=|!@N)a_&UFO z*R7a5!t4mt(w%=if|DFLH!Na8i|aw@Mr?PdGk0P;jgz~8sURE}`7|4ruN^HVW2&6M z*@B8ldlZtypYmFL>97N%0A5o`uRvC9V@xh-onj9M8rPAe*T`C(#iR+qN*^k;z>Z!)B%*ERrwO@S)9F_X8 z`8rF8jIQTmCG_IcHNZ&Q)9ZcbOIaEJWFQ&&a1{J@Eze4*JiUM9@kmqZNdOA~iUda8K@UR;?&QYC!Is-uP-*2IGwAgj`3%PKb7iVS^iJc9Ny-O@AvId+% zU&s7Lf7+$dy=Mc~2|Sb6yc#t@*~Qzw)e!&w)->lnJXt6rNbss$e{Jh~3_Z270mbGv z1{7ZWp=Wr&gh#BQR!y-%*+^F`_p1>?%-Uva=h0Jyfl>E+IZ#r#!*1RJ#2%<}~X$4x0#IeAdT= z7+0I4uX>yn82{e6Om*&=DXqm<*Pik2vL_#y3wAdCFgg=&g( z^t`0q9Vip<%xf%RRZ>cq4%lp(m-TWRaEAftSwIZatH4U*+2XP|N+l1(0GQ={Wc z-rV-XS@e4pHEBOZC^v}Xsc4GdH4&gIkCEWmTJ@a~fn;Q#G^b}d<2-wS`H{65Z{I}|#$ zA)5p!utVq1F6#);S$o_EWS`I%u;*XX_U3dOY>pQZsd-rPb$=+fy4kxDS+6umJUiX0 zgzqpY(taUS&NqY8Cp3;L8g?Wc{U_W`(w}sSUvl{cN$K!ZJ}CHZIDQr0`|;1D+igi> zBlxFeiq2{BoA|o9SFa1*7alrg>oCe)>6E;5MG+FEE^*v(<-+^>mlV>2K1%l3Va)pd8hdjWod_xI;$&^4fYPy6`4pfbdXE)CzkD7Y9n81ee?Rma~Aj18jHBp z*d(VqG>DTl$!?@;H3GuGl6}XZE#<#`@cGOjcO7nc(>DFCLtc~Bu*mIwzz_Vf@WW8S z2TE?sArL#gp{}=!YVzccroQXb)8+RYw*U%(%W`X4q+yH9=8rsPvgx3PaViRR02T_G zJ2#)wvvy_WyDf3@eUc{!3NbEA&Nv zOICqxoNcX^1OLysW3{sdY(7?l5pRp%c!m6zk+s>vhti;5sbb$lto#Q^>6i0geQ=!Y z@rUSnYKNMbq;hP74e=q9@ok3(r%Yxqh5ZE_lx=qB8HGqpQ@f6H!2Ycq7#!2#pEt%= zQ?UO$c7al>`<&iAI0QRMjCI_nAl@gVh@sAa0a}pKIUnf1*M1K?GRnJ^jOA6icV21f z9T3)vUmI4j7qwmpfX!XefFH7b9dz(|wW76ou}~MG|J*F{*d@LheEPe-uI4nzl3oeqF8ZOq_N2qm2PI;!7F_Ejc|=al8!h|*4$ZmDJH zlyVD(ONZR55a)4KghxrmD9ZE8*>Ox-c!yltv(+k!5b1%-6~;nF^_wxSWi53oa^Rdn z2@%R02}|OY*%w%6`fA#P5}FTpSAM=Y7K`xYmDsMg%xKtB$s+Jv0f(=B$KOag%PFGv z4YV*qIF=V0y9PQ%VoZmgykz#)y>0~wV;6Z36+)0F$aOf4aWj^>=+6TT88NF3U2501 zR-o3y&a+nh-MZ?# zmJiPMh=(?Gy>}Ff!OwH15vOJ~0oRHKud4q{2mnv09Fo_;)s0WQm?H@-Fx^6hh+(aR6Xf-;rZ(V&?q9;6?jI|H&*m}5 zf2s1xefV>z{K%jS%UTuf>7M+>=F;$g`8Xq5mc%x20(CQq3y5Tpy|;(sF_K`Tkq+cSD9a*T)TvO|%9>WXn0_+rurl0_08K?yqm3^zU%QnRxszEq?^hNw7JRI44d2xd=0{ z7q@_yuZ&9{<*0Qy%JMwZ>nM_|Pf?2~GbucfevHjz8VZQ9WLR7~4!-Wb%igW)VyFt= zJoAeRnf4NQ`YK2EWNkPk0WL7u_DTKmTTfhXM?B8DKPMOMK#T%V6B*|D6DBZm4S#=X zzr|$+?%4yX2gJ`O|LvvUtY6!3NR=u0l>{VllRt6twoM<5b=a6I=?!ZcRC4Wz@Rx>Z zk@g4ZPmsX-pOre0=Lu`u>+ESCTN;?+vHGt?j&R>|&Uw>cDY?$`r(f)XcI?AZP(T*C z0mhNJ`ftn^Ab2!yJgH9&*bZ^Iq^ZNc$+V5O>!Trg6On|q-Axu(wLNL7tGH>zul7$+ zCDVCoQ`W`_6$3Sqiv1W#)x7>KaotOJf2`3bKkhYb>ej)G50tV%T4* z-FY_B^l95ev2yUb6A}wd{;uy$RHG>XQ0p=j_eDNUhfn@> zBMU05Sf#_zH5EQU{z<41e*xq<@0JvY*#k|rD#$I#*Uj-W?UIpAeHpLnXQSay9EWRS zR?j_7C$3H^jQ%gfKq&sx4Xqm63M-bx%@XGma;KP~TN+0Qx=wb;CJMX_sy!3fW#2p5 z5`ANB5aA}y#^9DtIDhJJUi@Iw@QJ;JV{)db%X+JyBxP_o1`eK4J2e5Vp>fs3y6K@` zvLE;*`somL{bqv`gC$MbD(xSw2t#HhX^ zQRjm2p>aKPz^3qFW>!v{>#$+KmTS423mjI}=aY~jt7Du>7NIfuYt*T5v3SZLniV{g0A|#nbCf`&lkR zJ)>)qs_Y^1ZMq%{T^-lg!p82<6L$D*)yLehuxJ#pG6nxXV7^bPj`_%BL0Y2ewi~h28#Agl)Eyy%r4LD=#e|qmK+bwy%A)x(oGK*vR%J$V36IOeduI~OaY1vPc>Ts#wPV%S7j3^IrJ-Dae(Zqbg^ z=`Wxwfp?G&h9+mpOx%aQm?<4NzCgBD8oPNCLE?5roJYWa!TQDzMilQ?Ug1#%3wm zs5|iyFNp4Vf69}N`A6W-#a08%(s?j=YSPV`)A-BaiWPQ59#?60q=dg1B!Gmd~HJw&wLUPbEUAXDzCg)3gEBOEekJ_dX5$ zy#lQtPNHB&xLFTK#bO+9ris;3*)lNEdt$_?A^0x%&eQ$A&qZN( z;7u*b5R$iIo#(34x8;G5HwceWWxt!tM5W?==^wR}=Jmsjsb7PW;mD(XqWYeh0z|Iq z_I4viV`Og}ee#F~NeNlE-0{Ch=JI(ANCZkLoAVR}MIj5I4Ez!0`U0~6yX9_y=4Q$E zseCj0)Tf@c-{G{*L`$ zHG>7(qBH;yv+Z0oeB zsX2M__sjPBsJ4}qFa24nQV;-;2A@=!@Xn?sFUym)3iEnxgZ=Y@?Wq6!DtlVwXv9ID z{+zAoT2d!p+}YW9lsWY?Nf@XzMbqzI>jj1xRNt%aTZ+|i6s8j`2)tt-GEah|2 zCBf-!il;2pNd#U_F^}~~skqM-Kz}$FzU@S=4j5_LP5ji9I_DAsJunA8_VhX&fcLCE zkmrlHVEYC8iw6KeSr#-xd4RR(wcGMXAO6}Ek9?X?G3$0{)FOzAe~=GgMD@X))g`AU z-0fWCpF{SCUjVDO9bW9b$ChW);qssap6jHV2CE?{&#-X zqMy)eAq)3i0^&wHoI=W}J+*VQTDBr zJ7?LZ*?YO{ecvjGLzCY5VO(Ppums92EUuFkM6*RwV*rJ&gkFpoRc81=fw7SH@g5Q ze`%c2xoD-$5(!Pev%9ltHMza;DL>xeT#N0PfeV2-gWce5BY$FT>k@e0a9yHI&h)X7 z$ON1@Oa$&vK1KWiSmXcfXz!EIV}L4Xbg&L{L4z@qoNEJQRy?(zsekcPFPd#A4pcx| zIDB`4n{0{WiTmm6V=vpZNryPOk!a%m#P*V$2HI<51-!es0`zvU&{8J@UBR}ttDh5D z^>+70HknOWB>QyleM?dI12wIqiFFhYqTMr7PrVc^Wj zKO-XZG=eo?{DuTy?1bpka%_iKt#m2hqi|1{`H$L&&E!9oGuV8uEgn7X=eb-$S`1)s zgZS!LJo@q1{3Ky8_+Wb4j1v`RV)Frup4?a$!+n_*^I(U?Xy?GiZTdc6^fdjTM%~XB zkWnC;69iCaFW{;_5(b_eEASS5nj5X-U|NK|rxi=#O^Nq)q9nFA!S``TJ1-K-mYqI- z7<)g@^wVW1xv|DFn~xv<1HZf2Ti%2sz^;i~!r(>X0K|G=IfyDGXiC7JPpv6dUhjIQ=beE`_jKe+<2d4kwvSh z%LxC}uyt4Dj4JrXE-@bK^-$*r?p)+HU}cn>*KXG^d1}M7?tfe1TqB$EcJq4+5x4eB zlva4IuGq);$^}uagx&?0<#(j^o44OjR6@=)Fz4`>|LCuaT0$dfZsv>{RsUJh;2QuS zpk^&Iv~tGZRK}uzgAUt94afYObBDd z9OJ50oNG<9JqjNHhN&VCgXOH9nul}wsXvr_Y;}=(*orgU7SL z#na7%TQ@H5$Ik*jZi2t0*mcO$n4GRFq;%lap;m>XW}rkVU{Er&OnKZS#ra_f1+;Ru z&l`H}7QXt^?8$S>slxdqOUi?hv+XuwRIxTw{asUYk&_=ogUeW7ewCQ9W5<5#|jr99V74*i`(KTkai{zM^lxqXp z-&-WK+A{ctH&Z{F~30skC3>Bcwm|OAl5~p&PHfU zQv zG=wsre%@}Si&p{+4GPtE&fR)Q{pIm#4;KG$MW78w#&q$i#vpGxKV%(!E~vR^pWMIS z3O{y2->{Dku79FTd;&NYAn1>Lx#m~eS`g1oEr8?LmlbkUCzKKryQGMGGX{Yur|8um zF4-sVzLccwMgE5O0+zmDpK17bf|-6)S-DGhylQJe$a%!7a)*+YuHBa>2mCEyn)7;J zvijj^jVLa%6Fa>faj0woy2@HZPbxjzqRa&aAy1*{a~S!%m&C6b0maZIi_F7n6V{vq ze(wO~uLAH96aa2a7{kTCU2yfrZRpNlV@V#J6mQ^fhe~V@KZVB{v5V3~&Y>&T_1-xH zE^1`edn&>)ou5b&XQs;s=n)hV^Q3>GFCOz=S7amZu+A)y&*0jkLy2pKge-WU7X9x$ zeFFz9VW!fvL7f6($Z!3O0rnx{z<=$;GUJsAwf=`cbFWcUoPizx`(4|}(cPe4RZ(q9 z^?VAuh1eWxwG4Mgr_nO1+u=oJRSZW7fcSdcion8wGty^Dezl45XZKb8`l#oo4YVC` zS9-ogx}|@ZJ!P@zX|tW0 zz%oJLWj4|k^aSNS-s{2ez&j)A&&l6W|E&CDH|Xm2F5sZMIx(SWV1?!VKb*Z+SW{cn zHpu1WWzN|b{bh zSOQM+4jtBI74pYRKKy19PJBg9D=m*sxK&XYtiyNb1<`0&iwY(X1-Gnsav!;1FXAdJbc^76 z>CJ=Z2|zA<(cB#Af}|R7UZz^fqmbfj ztEefv(IHACN{h?ZfBLyj`g7Q=-%K*9xPL(7oZG`a)6KI1H0bW~EZ<7(Blr$vr|PuE zy_O9pbYK7-!}W1pk_j9_gC9LY}0REU&$4HWf_K@V_^>GHb-xnL)IPNZ00 za@v`@x9p6>pHxoM4p?5WQX>%Pqmhj7ey7h0xM9U!L(tV!;}?U|)Yyu#|eew z4az=U3wd3X1y}rzig$5?r) zsrj3H7%Ef3)A!|P5j+P3EHAN&_(118q z*kyuT_KVspQB+u7na1Nt-<_xCUFel=b_!j+J1|TB{VLRc}4K>IvuGI0=HX zJQje63T&E-4$R9?UYJ$?W_?=N{!cUJ^#v!!^7uv&=<)y-Ea-6r zW-sqnMNHdD%;ww=ly&SH;>C=Z(?hp=qpu!B@ zLPTcN>c0P+HS){E%&VEeez+34gtrK*vvJc=?FE(v3u9}G!GVW0gBjAqzCLW9? zIWV4TtZnzUP$Pa=pad}_1bC9|*D>V7DsSp3uBV?#5NtM`_4Zco}`eOSVQw zd{go0?f4@Q@91H|j=R*FANN`ls^W{DTCNz~Or?47#}2{F^YTR{Fo)iDM@{70m!&gr%efm7tL9l1eKq*(Mo@fYEU7aDbcQn3KgI8#hl*7-L ztGt#dl7kbkrtA2;gkJ^9fwaXH!1&NMWfWLj)51bJUe;n@na+J zI+#C?pnBB=mL@>CY1Ty(Y*%TD@$B1Tdst*GzP9EjXfSfnnW7Q&jGEqsLgn6sKm3d8pW9+n!PZD%kJB8KrEx%}Bf~f8@}lfpKU7$5)EvLJ zdyx^DV6VvOC95fLTF1C)hu;vIW)-=LGoq>Fmhd7(2Rgwmwj}*Ub+%{1F9i05K{7FR@u1qYo3f;bc zSx=tbco6J;z=Ax#pi8LE(`r(N%a07KT(<$FQ(x#^h8`lN4=rdE^?r++=zAMG8xhll z1mOfV*ckZuu8XT0Sla;O?Jul@uA!-dk@Ewq@(w=|7p*418e2h6Oi8Vkp4Pe^Si<|B zM_m?)T2pWI@#6EKNe>U!$~3?2*0@7493Q`&#Epnv)p7BF>>pF|JO-+CSUUu5Z9kT& zS&~b&eHs+fLnD<%mC6k74HkR z5))&L&N5&pyL9#9h+^h`k)&7HEME52;i|()?^ixbQH#^#%nT(Q6{`!agr=wWYfMuO z;x4xL|MCy6_$bj=Et9=GPCZ-V3|c zwamIOt-@&t-`b!lE7o^0*4Diwhtc`rU9bcQk!B#9MwQ zt>I0wIo#4b|Iqk!$v;lsaCY)O!^aF5+fu#0-*R7MOeRj3@Jr%+UK$UEV1IQ!P^>xP z%|FvV{JQ~f@eE=2SUN$c38a`EJ$YhzuzHd|QFG5P2VNg<_WjkapztMo5!t9A`hw(< zjn+clAFE)=)Q>(^?{{4T>B_trWI0ZT{pnkZPR;lEg63}dlrXYEei#cSWOz7jrbB2v z!c*NUs`}YCUSKvc7sc`tjW$>y!7{SUx`>~^HOPX;W$xh1HEC21|MeN~bl+&|%~0^N zso0r%^Ky?lusYlpaRsSEMyPnO6(cldeIbrMIRyG|)Q73JmUBNzLe$X{(~Il9_OK(n zkop6^)beC^;X+TV+&eaBJ=Q^dE(Cc58V_ywfI5i7`HY*l-k~_w4Q8@m2s~+4dtL1r zCd=JJeJ!G=C8fVqR+=e&SP#7Zu!o%0fK8K1;Qy(zP%vY};9a(N$Crp>;dmqd)Zu%r z5|KAWI#r%oFVo+9-RRLJyFmYJClwfl4EF7kc+(*?4Pj$tT{twgaYmO7RT0BoRGyeW z4sA}pUS57+^sh`8>!$_Ofv;VzGO)hd!6BLaQa$`tf8mF*T3drex5AjH7L#(w)S*7t ztcaO5wI(Vr`XprL1f1}dsir-fs9vhZWZ`WQA<)hagkt)O97JpDF;hV?>CmTfovkG* z(|6YHe>wk1Hr3QzQ;eJexPA6$KbA4xCqqN1f>57-zOR=tL4@()KP@iiK$n_6&cADl zvw5|@)pegzoU9cGnX1}@v9Zr|5%Hip8tnP|*Y-gKdY<}qADlTX`-`sysi}Ar^gXV^ zDya6HvAt&M`C6phCd?U~tmomj*X@{L77A=~Z8E-LBKZB`AXLRL&f5R*AZM~c+l4QYa<8d7lEUzKW3|&4&BcX`&Im_&{MxFbd~1*Stl*34zcd>+{B_#GUf4qb#~S zzx=r)OyKdR2*Q_5(p0bZu5=7I=@N+zO4TILod`Mi?%FzB9qdEN;Vw#i`ZPUYxYaj* zA)|aF?$uPTUd2jjqN=I3ShAi=CinmYt-yd9aKO?SX(zzKQjC;59l>rk9qa8z*c&$< zs^-YY!C`!6RiILDJM`6iV0+>Q1c&h{ipUvf01VtZ|h+Rvh253;lD_1s{J-~ z&JL~<{KKIb9~ij-JCnu=y9gGJhlq=Of#QUEIG2sfLk%)Y>dg(0`plP`^d91WM@ z4=gO?q_;6K(#@f?I&Kd&xd)kf2MDDU+V0LDKeNXw+Cmav^ERl^{^6i@bc4Op#`NYI z(;R}m#zfP^TH8=cfwgX!_gf`sdR2(!Fmo9C!ZNFA4CdHd62Z0iqkFtclBd|4Xmpla zbj);m>pb+xd`+>JX7)w%TGv$x2@99ROqGT!W_ZwTgBGYM&uP9F)l^7=dV!p1nO_k;JEYs?pq7nCQh&F6ZBMb;Qt;9r4{ z`4dA>XG9ISFw^EYT#>9xF`g;N(qeMl$nnrW!_IFNBt~ zH9EPSp6^`ed)|UG|0nW4Fec*2QyG!k@>FX^6gT8k&4^Y8t$C9H9Euul?@im`^TR(_ zRV3ca{g^$kPi3@Q*JK_=zb(EV8bq(il+$w22^PGo}1!whX%}g4GFqDxv zaw(X9Kvb*gaJv_Ow~KL;|8yiJUg^cvy4ShaqI;m(0LOY*s*j_z`L*h}bgwkhmQz&>tIy z909prgghuQ{Ek(e0bwM<*Q?|DMTuP8uKnu<8QU48Z)q#RiV{%zxNVMF#p;+xTn9XNb>>f)1gtCNS@6SZZ^-?zH8Q= zv8{ToA>PIWTEDfc1?qJ*OF9#EU^{^dQUAVw)3(F*#YDGVl|?#(p#*Pn`q<}Io3X$a zI-8oe%$Ks`v3Wh2|3$92X8`~u(hs1sxvsXDK>E@gAC*s_?B~QHATSa8n@K|qVG;SV z9=W*$^Hwa1@7h=60!y-Dr14wKHMiovB^5W0mea|F>NC0A(~5EWS0MTgb(mdf8&%_H zo_ok9osgrH(}y^T?xVh;K%*UAfa87e^}v^vPpBFbjto$hCIt{El!*y4&azjj*P-Qk z=J6Rxt=exXa06JP0PdnnVg_KvvIi>5vm8)i1QKf;!Eai*KcF+qK7}hw2v85TXgv+gr&b(pW-J7<6&STmZ;$->YMSDUz-{Kw z6maZpJFdYs2)O)j2(tgfsr^0iznuv0t0um+{8<;I21?i$W#453cx~3bc%au|`y5`x znfzTvdd^#$F$MfN*_Q-R*P;VEIIe_6xz#og#9}MA6-``whKU_axCg`Vo;R-#;TdHf zGDmfq;hAx*Z(JUaIe0=zzO!^}3ibk3o@8=eEyw?wsP{O_ndpmOg`%@B>68uzTUIht zV}7JDNVd~Td*d-6_yqB9% zQjg7ISVYQ!PV3D3KwH!S0@o0;jhi4 z>*IO*jH;#+MVsi;$#DfvDCP1nUfy0CC*xX8L)L{ZFs9-7N>uj(h&T#GBuS&I?hy?L ziS8bn41PwGpX}JLj`oI@y$Ux7&9^i255wL(gagY0lQhv3F>`uEU6UxE#hS>c#%>*G zN@H_BHVMe*-YFE6o*rXt0akv@twFE<;{7zOW29O}|Hqj9Ja49RF52jA=Pxy_PrF-w z*=G`uhG}OB1V#?@T2sei^3pDfQ%XwyUif`biMkj~^fp#Y31vpqf4c!)<}+h-*w7P* zsvPm!UB#l?W9tsPhszjMnX(8Em>$&Za_ijD=9nn%GGcSr z$61gMdTL}-&R?Mi7$XO9tkn5c8Wr3{_vTyU-iSdbQ0~r2j|4V{sNT~>VK@ z4Q+?)w+=SFI$QTYf&mrc^GF+9x+Sn*M?UXs*FI^t8tDo=?RvZ4e^mk0E*l@(c!s(r zyR#{9&7w|L`N4|bKs_^e2=8tk`8sUE_rnge#SOUzo9@tQt8Q)|ZewThYD(<#1xT1< zphDL&0T1-2EKcZY8_Q7nIMe#gasdCg2!dRP)`LB5yGAQ0z))d#oN23wA7_gSI$#7r z-g1~wRapAHj?MTIeykY22hatb9naWAeRhnLtC#cBveE-ZpjpWaDp}DG@h;W_d2-NjYayTtH2BkpHWv8M&9< z)cOkd@Ei;WaXV_&zkcut!PO1^l;GNB+#vCI&}7i~h_Br9UFv=RFpY6N0y>LSl3Cld zy@A>E-RWD0G}WKDh~T3cm3hbEAT;GJ+!gvUJm4#71-^0Cdrlv5UQ^`wL9eZWNV1%y z3>Yvb^Fs}afu_vpbNl|f_WnCPMspO%=zBSUtizLCVy0`Pe|$IPmaRv z+K6MEXxQhzhv3;)8~|7)Qr*QW=jMx;U+es|$#PNc_~Vq4YyhxW8c`fr+DGbT7G$cp zm6fBD1%dGNU9pe!th?-}8P^+=A!k6^A;bA-fPaD?v!j(1+Tog2Bdg$t$7-17h!Yay zt{9AQ2+CtXHT35Jx7j5hkCg*Wv7M9pFcH$q3uM6!4lJ51NAzDOE5+QTS5q+4LHs^! zBe-(+@`LgbP=+;@U>0{-RGkA+$0`?A?&&2|3XX{&bXGjfn79@(1Ukx=%V9MTO(+Or zby(`h(TI2@D0uk>W%*CqndlIBK~n(E8Xycq5D|e~uTCT!)4Mb+*`Mc~gpie962PjQ zdHiSgD|w~!T1ezfl)@1deBUpM6QerLgmk(#&n(7Srf9*gCjg(pdP)({=_V@fek?&p z`z@7~m!uWwIX@kT>x)VTj(53Tz(5ziIff0S8!ud({Kqa4(!(@5Gb6g_aTH=PREJgfR`59isd^I%=dN{8P z)&#I4e-cspqVC3jD?A+&dD@3ggs8w2HBSo(qpa^_{`aw10W|xilreCIjE`{N6HEP#IXvlaE!7Zl zHf@*Cl9V2PQ$453;#gd&Oc#_aa9W;M?T?&!b(=y*yTe@yBwT?;^@jaZpRK8 zs`XK5q(6{D9Dgpt!pVWdF{ER4OeQmIbT>Q(og1HrmX`~a_R+gDy5OWKJ3C*2$8|>X zwdB=u^j_F60DSl71ffI}Qo>l_@0+mO*gp`#iHbG%rHi2KF#NKgdWu@HBwXa+W$e?xmQ;6JS$Yo9-&_0g1$@S`+;S;N8)V&cQp zCzZ8kJ_eHqvid8}(qQeSz;qVLF$Oqzr7_b*l?AX;kf!aYm8VY!1x0@r4GPUU9f2Vv zD7suPh+Jk~@USMm?Xi#Pu`s#wqDu`?$4=Izwt7H+fQ5%-!Db-V4K0E$Qf}t?Cf+TM z-3&5RWm!~zL9_Wt>gN(ikA~@G|faD zc-pP`S@Ed$f|ASVG-J_t1XYs?tzBRq=Dy{`icxz;RFGgtv)7d@kPSth3KC-{YJOj}?1$LkH`Yk7qllDB!^`keX6rYCexz7||a z2ZtUvleYVPT;MIAOhk0q4aV;Nw2u7DEqRCaEmP_1u$h?_pLuNL^5L;+kSVe;0VyjQ zp{8}HMGKJr`6235;gyDiT1$=V1! za-Ongs^n|n%{ja=etst3FYX#Ie$?H#Z{w_{g?|b;boU;QIK(Pv>~%1i$~-A zqPt7vw9d2~9#0InP}lrBbnzzw`)~UlRR{{5A-<$duWhNR2`VIV7p6FqLQPWOr)R0_ zK*So?Lta_S4&$|#spc>u$~pVsC#BRM4? zadM*P(l-kK<~Rty=0m509L0h@%t|zv^$O_BO@;yuiFH&#Pl}q4;!qbA^tPL8eXj;= z11t1BY^L&a>oDkiuCHEQNbu=OUm8+m7fN%gE)!_%GT!gygVG9Y+Q5^)2HJ6XxC*7$ zP;RBk@8cH_+6XrdVZ0|xnY990l4HSU0G6klEPV*_WcoU{Ni0FW0lV2=6bH*3`A7&K z4YX(a&GcVT;jH1yL?6>82r3MA@-%KxjV`2WMj$zFyz@Q(!s z47oYynX+(XZVO){d?+i+ZM!g6-y$KOY{QC_h(pQUI>7qa!JWr|Kq`-6pq9@sh)`y}aV4>}%oBp$ANr<2!oC#nyTs)t>TfrbB}C`QB+9sg4hO-)aWJ zX4^K6c&}{abqyC%+)*?E%X#9g{G{M_vSV~+{-(_Fajz%1gNNJFGUuPVg$nNlVQkVX=@} z&5Bss!x{bBr{*BH|yCeoN&{kL6`&KSr`o4S}&^ z1vc*&X!!p7(PL{SVQlS)A;c8sGmqus&YI)tlA<^f#wg1M_vhVPKjyi8+BT&yDYMjS z=rt3k+g8(IUN=R`GEQPIU8rZFM2OG&66%_~vR)s3tR}`gFtIC&ardqry2bT-)ucR` zFB(3Zvb?aG4@HlE#asZ9R|k!=`?j0Q8jsZGU5e12$kv{*-dl<>`fs2O?|Vla-mg%= zZWrtY8UA!^NEV$=M<%tOg(lQ)Gg2M$Bloc@Dr~+;f=^b#pi4avZv$u&fFs;8d$ ztRk1`aftRJw9Otqb|nJ|HKZwi`bg^yP9| z7+-fYLwFuG9m>FCKiq0b)3^3+7^DH%@o+jGe%HKi`OxYyOQQM(*acI4Gb6EG;C*Hw zagWixuzHPNO>WsW<0o_O>UJazWDOY)&kcg`N|P` zt=X%R7#_!rsA{tAW(vcGv5Fer`O$vrV*%g>uD6y)Je1-Ueb0+49L0Tq;yV12GtnY^ zD|;p1IWD!#(>dl&hSyEQ;PNFNh|tk0 zx=!h3zmvIo|HQjqfbqM@<{39@J35*FLMw?=_43LvR0Cc{Ut9@AW}77_dtj z3+5_X3o5X|r9ixelCQiV!SkeMsEQteY)Fv7p|wHJq54l ztS=dTBmA!{s;AQyMOXI*RINOe_(zGe*Uek}P6H%$aUG@Kkvqa38X>KUdZo1^yC& z4uM|*px+1bDjM}HGU3(5i7()q7Yzz*27;z+x~RiO%-_;U>*Ye=oVL8LEdd36na8@l zf29VWGctetDR4ug{p>HBQybwoJ6h_}_$;j-1@4n*XF=wJ0@^B|Z6qeK^L%zA{N}oN zQ5>(y>rkgX+b>}I@GN$_LPFwUES7499MH=vJc_7@UepnJuvhj$e0dXFKgxc6`&56d z1K%R9WhP4R_4bv0G|iU++3)=Eex~Vmy#i;$+iZ|>?o~0CQBCeqRt2Ef6Q2ONCX57`fF1)g8-d1q6jHYRK442{uZ ze%reYsUxL~0+(aA%LazuYhd=G!qvCzvw=*52FqG=Me)`F54VFx_9UM$?zUH zKBJDPO1pvkmz6LK@pmip%)l z-2NIn5QiTK!$UOQaAmSe@ykqq2dn4I(Kd>FS}%Em-~FSPbELHFV%d#ycc-di8mf6Q z0_3ILK+!d^^jMO~wKFd8NX*{TenkB~BTCBHImh{uHV39mY|lLigtb8_IVCl9>%O*; zg-T{*D$87#NVR~gN^V7uQCNO#KP%%D17XBGCd&;P(n+V#3+MPj_gW*v6^(@%lT6A6 zIjDZuW3hYp`V~529po8+-^SYG$=aO+d^E@}>T}GD^Ocg6)mLDdAIJK#YTO6_ykM*f z8X?K<%llz2^kxF_%jg4B;a|D@H)+k5udCF>hw8lBaw#(#ACjRL7)l^RaoyjfLH1p} z!n@-;Co9hr&xcF2_6k?V7Z#w0QR-)|2>USkvVOUv`54BZ?8?u z-AWLL9I4!03DEp2o7%F=RFRv0f^EMsE#zMPHuNHh3M5{SVj5vMd7nkPoe^BQhi zv{vwY3B{x-Cd(h_2uHf;?rJKCWqmQDa>9AR&uB|SUzh}E?MtkQ1F-)iUKuH^ZZJ`! z{BxsLZfxjQKrK&6Os;3RJ3_$T(3*<8fjmg_t)toi>i0oSX9y_@*nrH_Zp_tJvxD$e zX%OAw-8zNaW3$GA-~QI!l49tx0$hf$wAZVY>F$^tF23Qhnu{JJBEg~vek|tSq2<0*C)VV+s(*;5dRL zzGdXQp!&BMkx-5H{G6B!igea0VKgH8lJOK%{ZQB4w+sPTitmAnXIx*iYfL%+JLry% zyM)^?HMvKce6u}o1wYO6@JaA(-t&+;;y$#lDBv?*(%xLUH!n^;^^EmzrWbcDb=6g? zTwFN$TT~5+^=>_qYVR>I8Lr8`(((NtrAbayYsY3g8|4Sf_4{b{JgWK`bXMzFk+sX1NC@R$IQ|edgJpY3?p%GgG{{rn20a!mkTU zoKSFj;$MOdZ|O=Em+UZI|=>OjlI%*nL-Q0Pj6p zBaq%Qtib}ZC$6KU+>fhur9FIEjgPt(NoVHDP(p7qrp5FHL@xD8$8T!|Oo!{26~At; z`3|n>-{daLI9R=IX!SjRAe@A_CUf`DVv+CV?Qxkv_FF#u4M0?b?>`y7>05(bgld8= zv%CMKX)L;YL%jS^gW@w2xHKrKjK{_yxCpfGzHVz5s@I&6;+v zDRgvI{IXt!U#`SSsag&AiYp~TSF6Uhs&-w|;8hL9qo1q4ymBt>Rp>MCl=<%z_Xe62 zG-W?K+4UH7P!P%5I-9AX9+e0_0lNT1^UU@Sf^86q*<2wn5cOrH5!qXqJZ}{6P_gsT zNB8!Ho!ygmk-W{p-Pg34nz?DJs@Kt_&=_jQ5^%K6d^zO!2;H!A$>@jW&cO;>)fGk{ zhJJ1s(4P=p5HLiQy>~7w$=^~N)GO1tYa}2z+tp>uMMh2LqIaRo)z$Rssp?M_N*3Ai zyHAcK5fvKUZ-qhPi2ec{5naG|(#*yG<@*!pZW|dw|D{qay<$)3i|nqWINd8Vt?J25`eB4tx2oSYDnU(NbI0(*W>nvyn3<7%iNg2Y~DyALgE+Lo9NbEl zMkkwfEgQu_PvF4(TwX;O(PXIZe?2w--y~iCA5-(6HSl;bAmxZ1_r2IN-SBo|NWY=Y z6fKuk)zfvC^B#zzFK`~+!PLbHLuWF?%QeOed`Z4>VMS;<&MDXFN^hUyAa5IVtwrj= z`Kw9y^OVZWJ>vwl_Qodur57iUEbI;{4ojMT3G*7TjV5|&g@ol?g6MwBR9)EfiUP1> zE+oc1eGUC5ivMEahNxKq?}-zho8s=j`pg0DE~4F(1hnoOn5eLlC(1I51xwXpx?M8R za7aoC^HJYS30aZ>8BXosbFBr6kyI%Zg9Rnr9IdyZ94N4IU;B6KR?T#TtYF82Ewt|X z#~)6r!cG$t-gC>J4pkw3PRK)9MWk^BUov%T9yezW{Y(@L~N@e>(ibv zOlF9o$i(SQ?EYftlKwEBp!+At)Cj;&&@VpYi=l_f@7v8zp9nISGOnpW!R5lX0BGVB zY`5^E!e`?8_Ik(uY11KG_NMet>gJ#U592eT) z)G5aP^ui}i2`JqTMm{V8LbuCRH&qS$z?*jk9ATsG1l?LH!bOG;fb5A({!h_=-G7)O zhG63lYLMcPuQ&e*yo0@eI;z7k@FiJ(*e{&d^R<{4-1F{Yx@`0OEHl@?&$;4xAEG`@ zRA=M-p0G^QCl%k`cN!L^LGj@ynQB?O52-LXsaeVAUO~B5>HD+?o}#Z&g<1h%W6Y0P z!jNyyHuyG7cm2(cuZ;)uT7pxujK6rDZujK?if3r8tgAXzXM4XR%<4ZtE^v zuX@c%UjTH_jIkYMNp1}lNtrTUZlCt{udstm;Gfy$H4OoJi_MGojv|^BC;DsV>~>O^ z=^EV=^Pn*m0~*ax9$);;bfJ?g(&9v_PWaBi_{}I{l{YUCNrm1<9XMBPY)UhaX1D`= zp8nhh9>-XYOF&M%R;nPutFU<|1Y|ff)YiJ;~j3!JBuFc#)UZxd5{0S6s3Ly)>-tHF>Wo=cUXQPWLe{0?%mXFgN(FH zedw&ZXr%l|u{wmBvTph8jkCQTp@B!otPkPad_Jk)2qs3dsvL#F;s*N^4j352AjJjP$zN?Ei)mRx5# zW{wUyfHY2v!;_QTO}$D}X|YoWICfltZDO#*utXk_p2Iw5U)H{fq3%+V$UjD9HTC-u6n9Ri%cH5&tbWGJKRDf9dIknOE)3;NOB*jM90r&Vu+TDqCjTuE&m3 z0WKdjCGP2eIjU7xX*X(O>&pP-Q{E~thiDO7Bej6^!3JxAr$+yoDOXR~Ag$HIjeX*@ z#a+ZU+A%0yN~gxt$`Z!BE3Y4UgFpM-kVBkkoQDKrP?F)RrbH*NzrpKLI}t;9I~b2Q z0qmDjyB;`^$&|RH%soMSG5#L$WM#u72AIb1I>eY-qMIx76f1g5Q!9ae3J=ch$>8F< zOY*0YIxGwPs=y(yKEj1*|L=-R1`MP#*$wxjGZ&@XF;)Eeob;v`EFz*#>7_irE2HP)~Q1>)h24_m_MyhCe0ae-cm67$zA<(C-{}MU~lmdsjsPMhlyv~2!J@re( zv;{qlMBs`o`M*5wlUj&9Qi;}fXi;8bLtzUB6(w5rmP)HHYyO+YQ<6@?RMGPM|5S%L zWIZf=??u$|Ii?EN=3?j=;`V*#i?5gF8VTHbZ>kGHV|Or(gp&UDW5u^x_~^*fy57X{ zZc~e8&-MMOv%d~4K=sYvxp?*_dP{q!v}7&dq}%i?*&xn?`v$A?sqP8l!}0eT=9?i( z+t>Ol>P}R?X4Q7)7nWir@c1#_47{+uzQRh$0q%BDVN9qv;B*vLlun95&gG9}F8vkJ zw!WOr%Ia)>q#4yx@6BrzI49T%vaA90dTq4$TfE51qsnbtL%94WL@!TTq9xN#3byUPRi9#J@+EpPXI35hrynHwT_WUq&*6}?pdh)V=39P|F#aEA4noO z(21}EciKpoQnLFkEhvnlIiL2!(lfPuk8pRn3s1LN`@qsHf9eP`&z=W*yy8lgC40P# zhb4n+C3=g~c+@TePo(8RQu5pxK~Ydx-Ado~cFi||8Ssbuqf_rtCeT~niw~}QI6>CG zfnVQO!0kS#Ye|u&s9J04qW_IhUo>?4MwG#wFo)0!a`LzP#b)J`!yX+DF2@rcV=jQM9C{>u$+@Tgdx<=U3S^)>M>gcf z$aO6q;kvCa8(u%lAH7<8FZSLsfm{BPxw#P}W(d0iVoZJF=N1!TWDh#Zhnwlu5-%hs z^#Hfk^A|O;byl^i?XS`YJfH(S8KjOm1hHko8?`lR894QVf&wZ);&D=<1=Hu)DMwA6I+h;@xsb2osF}@gIgsne zp0x&~%kJqE;BZy*;@6n0o0j@-u=8m#c>;WfzYtC6l$*L-WM_OA=@@=$$1Qdz5-B}5 zK}UuEqddeRYl8f&o0k)~53)E~FIoGtgY*;!$*XzM6koUwij=iERBSI>}x6sB8Z zzA0;D?ohy{GIae=y-mV?Z|qK{3P`yWktOV3esI$M7OyEU*CplcyAahaml*~I3_{Wn z_rgSgS>kLO$k51VPlfj98H}WAbnqw=ukSHpF{Kf{3TmACcLkTGk2wxadetS5Ig?EE z-&Pjv4YEZl%Q4ItX6n4U3QFXuN3hwHA^ zu@A;C=A1RZqc4`=>7VqdHt3(OS}vtz-4-#7`f^kHE)BK zcFfB37lvy!Wqp$zPRYOq^U7DBo!}yDSX`(ste}>pRMoYp-^R)(;|Fi?CYID*QsCOF z9Jn3Tpd}MUY+j-I9wPQf^cLo9W=s|B{Tb=duc2WCNPRSZ*pMLY@-CWjn}IK3!)rje zl2L!l%oMuU%h!(d65mJ8-^)zPeH!H~wp59~mQY5SYSDZbhrEre$Y_mjh)b@3CE-(t@={yO!G^fek)G~45SV=wi zTky7ys#t49x|o22aXdtpf7wF9uEEDNeQRy`n-P?(Hd*Ps;&D9@!QmiHvWb|jkrTIs zRQ~8s!T#Yd8CXGY}6hwwAv>o-ft~XuRsrByC*G)oy=msTa4!kj) zHet6Jkf}_ofCo5|#`$tyoERz}+NqzA82fvyA>FFX)ot1@#*s`8feR-q6U6&$wt|XC19DLE`88Dp} z#IET$V%hmf?7nM$dSjj>Z9g%I9;Bo=uh1TjJ%XYr9#hrjGvrJAUOql%0sl}7w;dpQ2rh=RtlEJ1@%HK`vSTb zW_7#u6tLeRVa@fHJx~k2>I*hr##n~@#GddbLusQ#R(=Lc__*}l*>gWuxNZ}j>^+x& z#c|q$G}gY!t;F?iZfR1Ax#pzytW`D^cl5h_=VkZEBx7bZ0#OjVqDhkhJa>T z!G@ATw(RF1k=uV7IohqjO zmvXFcQ%zl#F0og-UzaLyv3_fETHN!^jrfXjye@&Bc=xd1_hfs^2HG?7DG8>6l0NAy zz-o82Bu@5uEyECN>~;COgyzpKs+u25H!Fm)gbbg}s>X8)&Qx}pI9rB02g<*LI(9G) zcq_YS?s(e;8|kRzW?HqU>Mtcjb=xCI3xN?ZA9Cw@ayr`gw$R;q=hoo3*ezMd+jrMZ zRklea=L5CxGZ$CJr-iZtbA3l?{$Eag00*9rP*kaTR%aI9`)vc>^32!ySYpg?rpog2 zLJ*oQtt_o9pKgPC|N3+k7}c~du~EI#;6@9GyOFe%0&e>puI|{Oy+ZmNCbnL4)EYri zD%Vk@7BL1hsKwua{?wY7a95s&!D$7;NBza{YLd z5o;b#`?`AfpyOdoz65g{J39;x;}6ikX4#d}JFfXlY!gOQcr8YY-EpFpc$;pkWA!VgoxorTtMD(rSD*)n|+sd@uJ-&U!ExCos4-z$v&SNY9Iyz2EYgDJ!f*SH@n-=*H^O9@UAyi~Z_R_N)E)-NF$Gu@kQT z3%qrWbjALl><(|v%HcWHHqsjK`Sn5-6{K3st5B{kK!dtkY&zFP>KMsl6o}hChN86v zt_RkY79uP|yjA#-Nq+`Zb?>I(mTr1F%NgF3H@KU@w} z*lC0ZiSNDS(1{<8&baY@9s^xe#J4<{J&0s>5VeYjGv*A-F8iVQx` zhv_%hjB&~b9W|tuNZv9?@Lc?!;pO!hh(_k|D_lM)IA}$#Zj#>N$5$5lI<$S}=auEA z3*Ovi9sSqE5B6Tr-p^|n(x-GamuRQy6j88F(9frx&Db5M$h)KWkL~krCSBI!wdSH#1QPB%7!YV(8{PS`S* z8N;S|$y-uODD6@E#MDEu&-5C~-?v<36Z63jKXLOPb5UF{9kd{vYpS_*qX}^C)fKsI zd0wUEWSR=aUBLIhrB9caY3k}i3I}<7)>~)gW5&NHIGwrsHe0-)S@N&L^0F_inirqX z??fEdM?5}w%y%}Cn)McmUNl5J{osGHGDP_rd6p&WX8gt%(zp2y^`w|h!Hj7u@A&aa zrF~QHgo?YgTS+dU*3-4ZjT%?}=9@(c`*d1CiM40(OK3noJ=S9UMsKo(hLAFI=*z6p z%xv;$wf~2+_Y7)s3;#uNiy|tb6s1S0f*_(4sSyDYFhmHwDm_#w(jf{80urQSgoGYC zBE3dLh=>Rz6d^R}y%Pv2`@H*nI5T(d%$@r`ANZ1C-pORGcdh67wTGz)j{H0ya%7Ea zj%Rq3mw$8`0UQ-HAAr~yVx;EQDom=9Bu!0CK3=Rfup)?>a`v*#WA{U7Kpz2q#yUVP z$8bnAiZ-fn>f_D!)gF$$lJBg>eh@shJkuD~EQ(qV9-w(~9)n%?SI$p9{q)JN>qnRznpgzr?YrCfhKmjJ6l_FkaaiB})Ooe3^*#Rg@lg!tm)Rh%Y4xLn0I* zZ(8&z{BA;W;$kbAz_PVP(kWxQ5CP*h&$6Kw%X}muI4_#<5sx7wej_>;$bU&)S1jZx z;jw*SaNWTZ(fB!sIouk(U8xh6-t+zVMCDzf)!SsLU%*hJD9PujeF)dlk}nkp9oj7Q z5;b$adzr@tBa0#7H&#Y`KEA1~_=2ydfogxfSi9vUg-w1|R%sP)F-J9h2;WG42zIgl z$-cpU41mA_?JHL6=imN83)$IO?g2@T>kwrKd@dLZh#G?NC*{Q1UnblpsWNJHA9@A$ zbp!&06jKI``ftYYfWc6T^ESl0`1Rx}%i4EX2?B4oDB{s2?AZ>=T9$;|$No{l{!Cww?E+cc;GrrhXmu1hWCW8+Fa z;BrJw!Tb!qHFk+f#s*P~I%%Rso&nI%QLtB0h1=u7B51NeFmXBQ(6Q)g|BKT6VN}P9 zV1S3QTvMis$EXDEh|qBx>Cp%0gk!s;i)Z%InE}b^2h5+N0_Q8DVz-_kQgCkISs`0_ zg6*iTJ8=M*KMeZ2zuFM0&8p^MlvJ1^X~)GiA{Qze-4%j+77YFwK2tAIFC*~G>?2R- zL9y?;jZk_*+||cf-O|y(X=sGUSQhZCJ&7=aFT|K(Q+NsFLyDV!9GWb z1$IyT`7#p@*82xE`u&Tpd#klF8>u=4v2l#*MoIvI;U51z%7G&FqNPkcp~q>rb1q)W z3aUVR5Q1Algxx88&x408KsRy^fYhOtu5O~I3&*)79>`08EOR|pF&flOD#5o5JRJ}< zN$x_%oLh*p7u|=*k34dFb^^Rs8x-{kRkx9IM$-jMr=N^sPcO$GSo`}5E00_Y1*yOR z?!HnbU5Fzejkp#Jmu-uFvll*P_9@wknPU3`j)xqCwgFU`tDf1HE5gfP^d> z9@sC~(rv_Jsqow2%n5%(0fa`Xt^AnWT8OU%FtR5YKrj#QX54hZ58op`>RU|w_%Zw~ zcmQ&f(Xo0kq|3|2RZUqZ=s6{C&DrzI0|9m~-%75EW&Ws}@g^uyzRgr;A*O!-k`?-p z%&qH$eCz-jQQnti4&UOI5AG0C>5}1lkf=|nt<+BL6?#Lj$Hw;45mRb7TF&OJO}za- zn&1I&EkhQYvZTlIUbu*b2GC8JbYwP3Hgm65J_^PqcS@>@TbHEmj0$#$f>*=HOJ0$H zR$xMX)Y`XDO1I>-{)ao@H|A==^c)^Ngxa9aoWA`|&-QWsw51H5XDR&M z%v2XD8!MQvKmP2^h^94TRY6o@3sKLQX}J2Q0CMuI1^K6*(Z<>4^9)B*718c;s~IqINNHd%!Y% z+huIiJ%&K-25v3+lHBgWLyt?CUZwLP)e)VVgg8n%2SbU38>BLr5z)sAz~rdt_CQ9E z|0wEAk|1+^$EiejJ$J-AlYXu{U8a6gz?`G+77m^#PZV3~@ScW2Zov!{ z`d1;Lu{U$QS>(TZK^Q(mo7II@Mb1`V5PTWjRa_@)0&1Oqk;#CK z(qcEzHIw_|KPQ$v)44TNYR2w0Is6!cf~fEBnGen1+?DSD9rNu%7;C`1g{h=%XEoup zxHe}d)a`WPcz33MvfaX)DCjp0({uKlnWk}K26e}WN7&Bl6QLZ}shL|x80Rd*BmAbc zyLlgk*^f9cwRc~hUW)6Rtzg`i@~uCM)1~}D1ls!P%`-^1r|N@8OiP!34gdCd!Z)}O z-mlh0N@@w~IX;rJRj6UaMjZ~3J&pmNcwZ5odcPF|Cu)#-=L35-yBt5K`Qmln=VnN! z4bP?WCsr0>UKlyAmED{z!oFSDi`?k2MKlWGNLDR6+BNQF#_{L8nJ$}}zAN^B=&{hD zTfT){_kc9dH=ssTHQ3m95PYh*6C8`qk;vZsy}G;Og59-}U&5SR;g0&*V&Nl}0A}xf zx4cWnKheKiU2(c$nvv@+{r$4$JgF@GOai=!mFYP| zuY%GTp6cJ;GA_QO-K~%t;f9z#OdFd4daI*1tFkQ`o`Ej=*l6BQHmaK?B?U#P7c|aZ ztmI<&fXAIZp8filiAy6CjsuW*cMF`A9zDtP39GHN=7Y3K(~;7zIVxW?hQ4*!@@)x_ z`puIg?oC;%Imqyx7byTZZfM1Nk!baSq+wjO>+{^n<6p%-{K(h7JvJ46I#446!y8on zyp#%_&@fo!x6V}Pp6}w$3gXCq#lW?UaKbB`b=^he6)}4jac=n3KZWNh7nS;~)BDkj z9`kzni?oBlAPS;T-woi{Ok1ne@xzw9jiX)esHt+9P{DzQIS$HAiJX6#=5}=+gZn|U zvV7)`fi402xkfO)5aF;* zMmPXeCA*o=u15%roailkOB-;gqRuOTe3d3st8UQMGdx!h zlx7}#oAhkyw+6wPUKj8Vvtuo6x0S@U)T(dkHuMUPR1hK)u#vUZvpotS;p;V+Q+@Ci}^7HQp1PfAVIE|zr^GDdh`BEXo>f+K*`B+6emg4L<~>-%+-;8P*H;O)YeSY#nV_$n(7AH*4~+}W8FFJo1C#mR_`Pk$Md1!%Bs<#x-PkXn;Q$C? z^}l|PbYMajA1~_h+4@mEU{v(*aK>T#d@8r8m1oV>6vCLH_2|dc;<=Iy z<}!x_k|~_lZ^(kl)y?*iOQ7kLj>Vuk(NzG!)RcDvr0VRzPe092j{wbh<8<4-!t4pb zflu91ly?48i$Ur44}mmFlh?G7^0nHT``4$Qq<(e(9K0cF%Aq@-B&PeiC?-iz8hpqZ z4-lNaLQ6iaV!w!9{AKpNC%^YVwFd-sa0aplx?S|Fysn_@+KMRR0ED3VR09{)-cV;> z18{rezf~wal=nBLIj+Wunw`W}{AqHZ10VWK7PTn0|D=~PkbrAm{j{t7}_SV8wD`$N0`;}e*skG1?ij06AQAN=3XaE2V#r!}4EmrcGkRc8|vQ_!)sbv79y z5{(F&oDg+Wo4r+R6dKJlzK~)d`V0Y>4~9pObxV}w$sFr(@b$=t-nNxZI}~r+#w2p; z`+QK>{Nhi0YL4yua&);n!GMK?INxgyzzcJKCARuFu_Oj*{l$@je|R+9E5Wt# zMTHdtD-#1-3LRe`giat@HKx9V0aW3UKM;%1w3X5|E1vZF##>JM=9G$vh2gKf&LHGf z!I{tGEe}5*sVVHG-YHU4s&5V!7G3dEt6^pTo>A9*?AL)hEd6KGLP9sW6aZ!=*55be z6t4-s86WR^>EQxs*Phdr7%UrOfcNC(NB;D~R{MlcS@|gd4p1Awh&=$a&{@U=`_a%b<*2TR8_%)GO*nvoU3L~2Yvgc%<mi#$AH9-e1g?6BZvVo&*v=TNI43Ej*sSPcN@g zV)qDRtJ{;j6C7XiC{?Slsv>Pf|1>5>B^{>qu3>VyU!b+#Mhv+uG4$hkNF6vbJ}4i- z6v2yFk?5>0&WTO>wk1tI?H$p0dP+*ZrvKas6Z*QSM{@XkioH9M-0ql!J(TGs$ z4@$UCWpGGi34GG4*w6UU^17TpaCl#)jdu=T>s&j^;uF16WQx z)TO%dE`(z>;02qcRrcS+7eZ-2XziiqlH*$;LH@zT=|}wcan`ygp&kr&_7k8$*2@Y! z+aJn@o5Ksn6nV0#+woatCuNFKtj4iu_AmK)**3w~foXYJd34qVdgQ2`)nnnOA4=0p zei@j?qmqjNri^{(%xuf&DVD%e#bS@tCY$5S?Z~>(lc^cptTrQdH;u-}&`7Q)saD@r z^^?v{hd|6>ACU1?Wlvt3J}%CWvCNCHDFkiB$CrSol0)F(pTQKIGslFEiED#XTmchG zPO3m~{`lR#t-d}wy^tE9Xx8tA5H{Qc4%iwnmJU8Z9j-(s*HJGxM||LLMX7|8NnM%i z(UI};lszMXig%v?Hx(7XF*yd2+d3=)5P*u`b8Pm)1HDb7(ikaL!Cd#ep0fDx6W8_r z=PfAeG4;Gh1PFhu0Y0G1;0BM37qCUeKeyV_xLO+X6vTx9#Pe3agYz8A;mP8(&?|xpWE%T1ag)Ka zs%5_0TIzdCdmM6T^Tn+GNm^RnXM%x@m(o;3JC}K$!Xw_bn0GYvO+em<8`@O$N|zog z2s9~s#b(x?pHTK@r}7Mf{n8sRx?RJSzKDLU!_zI|i4kcV#|jL@F7m^DM%lCY4FZU_;@)oe2m7u^4IG+PTz80 z9(v+TternT2wDd!=Ltk??y}e}Ba`=&s&{A^pH0QMeNEC9{E5YK0{OMPCG(lYE0XXwP3=HdU(JWjZE23$wC7-r#0WW&fCsd}TuKn;d0BQ8n zbQxAFxYo*lJ>?>nsR)L?IAO2} zwL^by*!&=x-acE5M1>}+=_e-_LuDz|fO1O#p;QlQ4O4Y|_Qvc#RL!-xvN0fv4H{%m zEXJ-jc$G_;4(pgFmhP*WaxF1iq{tZo$yFDJp#8{d*}8SOaBo>mQK{ydI=GLR&|dxe zT6CbCmL-6cfpG0Q?0 zkZ^~0!Nmz(?3*xRp9U^4K1m{~p`OXak!SY)v-q*XYerqnzBYRDPn@>p#hd4{{T3Xt zZGl}=lpnddMO_NErh&$&c;#ZZd8GUJqHz38DB;So&}ijrH^(u~d$-PT{Vi>R5i6~| zuljFY9kPOmtZ!&T=Ml0`4tASDZ`CUBkn7QW_8| z1+MGzYD#M`=$RSa&T0UrK*9Ndoo;Lu6;?|ygqzf5XK6n$5ELo~%`JV`d1{-`~mRk2klMNdPxUW6JvO{6%Kp#NoB z&M(;S?8j58z3K~!Q)=#3-Veb%Xrkw+-`+~;J+F4chLBw`r?qRQx-Dw4y5tl1z#_b2 z^zTZjqx~z3S)pnj2hwF4z)9UaQ*hR42_r-UQ5ei9*!6BdkSGnF)B-|=i?qqa@m`xpJn&Lx z_Yy8;${6{wiV8{m+fxV+>(E2DA5|ZO>&zHhYr4Gq~RtmrN?hmj$o7qQ0ob zoR^XYSm}U|OHo*mk-FS#Jgxq}T&8l1e>VA|OcKQs4b!O>m%qF2Q$sm6sh+?QeY>~$ zPm;i;e*3er0G$o!HtPbC%hw_YNZb}E{cu%+mf*P`PreLy8$F@$zP}eSJV-hY-=DA_ zPwHmCK?h;a8%EXFC-M{ohTY}+?{lt5?u^B1s^dLT-8{V@KV6`i8^Kd(T=T;jBvM%5 z((X6+igt1BAwpYLn1Ru3#hsykYsSLgdJR5cRF(_)8jX2~idmx9i2pIj2r!a@Zz;%& zzb)xHUw^El!RH#QW9_HeVu$zgl8&)l1Vj=Te8C7fx`LXKk-(e&M3K|w*=NGS-TT`O z@t^xpL(=uIPD_KON_2@96n0Tk0%?hGF@XYysPcAC_xGfW2D}ch&ga-UT``8jI|t|EWv>lKAXbvdxJWvwO!tO|Soqq_`!Kp)&bh$KF(*>R zc0t2V_x#Q<0|7v^W-4s^2O;3*Dl7Ay>w9h?+Cx1ZH@B&Fh<$s~kz?cYQ&yz#)x}lA zx1UV=<6?&Ug&OuxL-&X9eTCE3vQ6csyT|EBen-0pLOG&AzLLA${s>CzMrDPURx1w* z1D3)Z=M5buqQ|^sM)nOP))2hMa3Ht&YDe$40ZoG(bF910&RC`12Ylhf%Y6$O_DAO1 z05qQx@tzX7rtH*U8~OoG&J9y|XS&};H2btf;{J?IS0R$MEaNF7D6N7+y9J^>Bkan=bTO4M-~ zy_6~EInCpepWXU9@(!o)%o^^G5tAX(n~k>}qL!A-C$4`4*~QWY-BwNnId|9lfUE>E zLJRAYHTC0Tfo?8EJ2Ox~W*8eOY2Q$@XRQ+}2Fu z44J5IA<@$oag}gPQrznFbmtTNG3Ax{Nu*_W^uGxk&jd#+0{y73+jz!Oi?1XTmYS7(w(JtwcuXLuDP^ejsBY)lRnBuHjeq+4Y`@X9gro4s$$08J6qgq{ye){0B7=iPri@H&8c8IAbP+oUmw%Z$ zft>BfK2?oQjT2pDuMQ~*_aN7_pZOaxQ}8c6+Low%FFKpze%(% zo&8@Xo|OW0gOJTK!wNT{Gu${FN5qd+)8`op>wz6t5`zKSl7kZRjzo`RXf z^w>J>nJt*h)>LxCE-BE;>gV0?U5EWEjv7aTMvj6I(Z2OP(RZm&!V;@iT-xi>RP;Bx z=#4?glEbGIyTG@_s)%YTYUh$U>B6^>6)dEwd;c$A%m2?0{{6q26mA~$+h<8^7{eM! z(?b_yLIZCb#+2dMYidSz9SP`|bMG^KP4{wacV)ZvPrB*sJrv*srm|Ri9JzAtC*2@X zU;pA)v+od(S5Dy?UA=^Rtx7%o-;-PMDn;2rKh`$LvsI;eJx>RFjf|iMUv?-Jh^e{1 z1t`nBUe{Vq)>T{_WH}bE7n{^=ut;wf4N+M4>++fioT`%C7Ry-MudUtj_%CgR|4?|! z`&0KOt<>up!AiH<9(YU2PXs0JDOdwWs%DW%o`}_~vJxz*gD>$@c7{zP>{fQH!bOTy znc8=-SM2wT(^5X7U@rrz{j)SQyB#jbI%2O!726gsxv>DecyTmVmIDy*OcpBMG{vjo z#K63E6lW2;=Lj4+_jvrWj$yk@<3=OiEE>DX+4! zx^RLzmm22P_Nrw3Qw9>T7uqCMD@V}f@K1J{kh1}+qKDkwOr=dL-YSj_u* z*vBXaiU^tBueLCC3JUWo$H>en4zyZ%efW(cTCqeq1?i5_UaadLtAas~p#F=IeB|%j z*;B3d0Rf|nKZrz=t|rCAC#C@=+#e{Tq5@8=+ znj6HZxigi5Hsg4ItX->L+A^EA^5CDgY_3gS+}^S8iM0y%$=5yxPk0KAD=%(B;K`O&`({9Kb@ZcBofU`jA376WLx5I$Wp5(q9aQE%tbei#1{jc`>IcP3^-*2y?B=#fwFuE%$ZD zjh{&#qQLTZy441^ty0+-N3#KD<_a_3Og5QCmI?X3+dfVlDV1@xD)`;9TSL8bj(UXX~GQakZov2^xEn!TVIk6s&XsxDbo zvm5qHXn6g5sOcEcZvqO8mU$qJbxJ(>H>d8y=8(31JCMi zBXV|uq__`T+GtYUr3yAJU7O@5#H8O@>Xzz&l$2_JF9o>9q>XDJFz$G_EV?ny<8cHqn%T`l zp@tC{M|T0Ax$gX4So0+I!Uow?vlo*ZRwi_(Sqzc=A#9+cGjwl(4dYljsE#a9NtM zX%I7qkb+$Dx3oRA`m>S~5Q`Z3t zq4J4Z|g9(4eQBKA%~ zM8}1#vXU~XHP!8cwE{T!$7rWfI$q{F3h;EW)#PUO!v9F2Ig`PgYhr)JJJ5 zI6M-1yuJ+=`(5aqazlr!&_nZy`FuZI|KwnYOwH83g7@vu0GD2M0tg&i+{p6qFWoLi zBex&Xxx>;k-YSWGdRX9smuvFs%3O?({NTWcGI>}Wy)GeJvA8bU$!5XiM@12tIi^Jw+= zbYM5^X{*`U+qc#)o~YDLvw7<%=m?r&f5tZ-bo&#+s-6N`K2wa6bp#*6(C{bt1VJ*) z#Uy6AhuGN!{X*836u$M7R11OrH5xAB+4(Al**F45s{(0iqQHIL0$j!BoAu4@fwz6E zb@)02+}Q5BL~GRTX|!Kw6z$!s!$5xr%4Hr?2k0!L_gnsnk5{f4LCChWJP92o4nPHz zC+>f9@(78hB^)1`DqVg6fDVWW^_I+|8zr*B!#qX-U(Y~KWA(U;f@v*n*&q8pL6~Z4)fUIkurm%em2Q5M9;no83bLV|l zcisGTH!(XJ{GKAsSRsR{* z**`DBETSD}57j*Sj9>iJP33ONcBSGNIl$pEL9Z{<(Q#}UWS_fGj=W&*nLIo1GC7D;+sZ|Fa$2936N0p}4l*>o%HPHB>biWcNrniM5FVxDYNhWf zw180nL;%>uO_h1gT?5x{Bk2Rcaoh0Zt_dGJ{y*&;!d7WC@n zCd-Qnz88`H$L`^4^7YUhIehgc?M1-kHkLL25lmQT{O1SXUw+8DQqka^k&jARz*#J; zx)&pL!qavmHhsnon8i~Ej6ReVe*!TcVGa&CXI{1OmF7PFb$57pxF@^j%nPtez!xFQ z&*=HiPm}AeaSJpAKQKt5opGtqI6Qos?JUHFA~`1iKCud3>L-u!(S`o~)OArFMsM8t z8R|o+r`jcvlfp&@{e{tvXeziJcujN_w+pEuM8@p58Yy?pK)SkqM9En?iF=ok4 z?oUqVUV^K+O$vyDraNlgTtjqK+7KzfWpdh z8RNz8T7EB1=xi zq$_MvoSR>)2tR#))3UWSQoHh0b+O8Yf0-)BRtyf&bEM$AI=ih5_9NW!vYzv?=BJn^ zmXVY{NqV{5ihpfy}@@8Y!Lgwt| zCwn|&gp&@Y3JOaygu;*n~{I#V!P(zd3-u|ex)$B6S@z{G^n3Q zx*2U4YNx->+xWHkDBt}nOftH_CiAdfzq zA+K{y^i_uxoKpnQ#x2AhOD+Mr!4niBvtd3DmAiPi)q^Fb0A1wT3o)OIlWf!Qksg;- zhen}icE{*iR9QuHY2GJya$&oiUoQ?XywaG#7$)YQ@QPu4mu@-LLwmL`(Ywb8mi^Uz z*4^lNtX09lpO@CUAzRNM-rCJtLxluYQ{)FbrSHxM(k>G=S3CeM*-~M3c|vz}@4`Xo z&nn>tAQ&5EsrE97iK89+<7OUJ?a@~?_;*OXzxY63pI`s44#nBsKsNw$Ogd`ZFf8K- zC`eWIWq~kNg*T-W!IP#}p@F>yw`cPvTQfqXRR|^zDd8EXw_Xf6>oCWGqCUmjnx)z$ zxvFx#P%m5(|InuvBQBxBtWV%B=@XQ4{|Z0*>Sms}<|KB4%M$}V}nuDZ))`5 z59)k)l!^JA+tF3=a+chFQKHd%?@->gKt^cnQ7RB0VtOq@g8qYs9-;=ddbMu#KbMK2 za(+t|uLG(h4UO1n2K?~8zjMwssmV5&WP=+7)F!zKcnL!)Kc{(zV*RC{h%GA>Mh^;i zeQjTsdZ6giN45HSAO7O-!y>$vR|Y_7(M~1hKO#rYoRNws^n)&;0|aH#JI0u+y`*cm z$83|tkw2~gm)bd$n%=)mLbxlO0E_)8=bwqW{eYIZ+YUR5e^iG=0C5ZAI1=|7oR>F~ z>rtchPe8FXd)kEcyj+uFy_wg|eQR@t79gAS9#7K~rG#x^h8Xowf#LqH5TIX+ipIFE zw3}B?Y>q3AU%h472o>@<>gs5O5|5{$2TF*QaL_*>m_Uyi<>Ue@+EN0E{&tzhBZeBuv%#XQ!E`l;U$7f?8 zWJ@Nws8mlRSrqDIQxv@U+tq3O2r9%JYXgL|X)&0S0W}C1Wa$4skl+{I+5@O+{Smnc z=n4Gz;3We56GmYi#YW72>D^ay-@F(jar%S1XQT6BL{Orj|0v0#qUfwYuV&WwQG(O1rMuLV3|TQ` zNqjBn1AerN+g9u)w-YmQWXOd0t6Jb)KrjD4>Yp`v*2P7V#k4ad#yA5ux7zLhhcP|4 ze@Fg@V^#uUHv~y%d&c?8gH5#EMMzmzG!&tfY1D-H6(Vz4)r!keUXc(3c9 z_xFJAi(T6W-%j#dmfcqC3l(ak zdKeg>;4Re3uu&x-ZIIg=YP#k=%vD%hQezOtGVszR%<-FpvtM}2))lM#GEnE&-ihxS zh}y}@QmdfPep`{lawy*Yo1PKBW2{X#SpD7iR1p3B5l-?Qhg3wrgL=jqn19rbJhNc2S)I&VU~-ZI$&=h|lq7)tsXaGDT6AJsDe z>C%c~+XC1xvRqq@^jr+{1``zkz=crGV-Z%U5} z*K!kZ0&*mXR33oDH)VRyk*6bz)jV;FX*|A`G^K3`x{y^U+&S|*nuaFY&#>8a^{3eM z($1j;0Nthb5qfX0XNoJo%On0Y4XDpoF2#wjuM2hd_G2(#8b$wfEENL%^s=qEN(Zzd z3US=#qIA{a%bVxRrN#RZ*>#Bexj5hy-ZK899OOEFrZBJpeh_m7IyE$PaeZ-A zotm^A)2dqD{`2G}U?ZD()W~3FV0K=9KH6Jbmnj&^afW>GO6Q%DzhX2z;{C(e#^z%- zV^PB@Jey~NMAX!ZF3u>sH<$U-Q7$r3=zG$OMs29H=X&w04Dol^gRd-1+{5;Iz3ziA zySJQ|y}B?V`=LuyB=5{8K`Js~hby{~14nOkgNA4bj474&T~$>qZCaU5i7zR^Z$XMQ zuDy8L1yTN&$=8xC&RP$~Eu%J1%jXyH&vMc*`Wvv@J5LU2$XaR$cwT(EOo3^zgl~+6 z`PDd!h86T-l4rw;axBV6Iwq%W*tnc_{5t8Z1?<>EK zTfE72CvIc*P~&K>v(4+LWEv>SuBf9;9AXJ{X}}d_0MDdz_So}^Xm4z9$8@wvR;;gF z`+3m4r))CxVV6LBRP^W3KiUqc&>PgxCJ!{$`xavR7(on`FtO>tPbH!m!OlK{!y%!g zXl*CH_}#;GQqcV^JMNaEk`XIF&&Bw8r4sD=VdYBcxaDNPag*O~$D*?MlziUu(#3b0 zKs?RXz+dokDGk*4pZDzzwr#R9c_D1+)XK>9Wo3B=pF^8U^8D2G9I+IBWe%4!IO04z zBcpk2u=JXl>D-IUE>cB!o%rhh`2yt20-%MG8pnmYgB8?ex)mP0a0FbL(8*m~W99bk zfHs{$Rh4)`@f+I1T(g)a>OHN|Dru#w4fT^-&XR2MzQ8>Kw8VW_=|;%Ik^61ww;!fd z#mc5o`SeCJ?yoy&aUB+`tjHd50akFJ&jv6n030AreH3Mf3W#=yr_1LRr?~Zfe*r|} zT`CuAn0JMH-oV(v^z!Zougoo<*<`w!^Fan_O~ zlF5G}!tlTZ+7MKN(s-oj_2zX(QB*oN@0|YHP&CRo`mMqXb+LfyX9!Stp(K!TIi%`O z1F`5wl#lRh*mNL-NRi4Vj^B)+=GMl9`RS-)A7)Uu+oHk&?u7=!N7M*Yl?1A<>Et+m zS7ABQZ5e0lG;g6`YdNc7qHf07GBq{%@aV4EQ{COxx2)B*wwDqStL#Ftv;pnIO+k5i z0hL)6#U?W;7nkH=O+a zHNL2^t>Eg6FV_stxg4lMqGz{(YA0+o=RsGv*Ppvy(k$~t~6iQKk+hs$t2^tQl_WpQQ5;UzN&@ZB`G^y@K~o0 z_%|o{>Itf<66XhjTKXV%90Y2p@{>|2)3PUTnr9UMVqJ(=hCj{-St(~3MK_!V)=vqL zxd0;xC6M_O3YPLc6H;rlZ~5H9EF9jz`UYYzyFnVg#;oVM<#46jx{z~k<-;#w++9yx z^Dg+(yw*N?luNy!+P_c>FuB}s8lNh{t*>{nYvWml(L@=q*?A*%bx2^%JfIwH1yqk-4Hd{D4xP{(Y2J^Cs;>!BtW~TuTkfrW z`5+_9?iPdDUeJMHI-cbiTpKAkzk9HaJf5jBdj~jOx?SEJQ1s;L(tS$*{=>1(T>d=Y-!YJdJlP)AW*QmUz+HLf4a* z=-kcsD2_em)SZV!&~sQ!!JudH`Ng?oOV%EaE>#tr@@bgwFaaIU1BR;v5-|P*$<~tDkw*`ol;3 z%m&yr^z$>27B_QI?8nVUh}JSm_!2_CfNm8`|5#LG79edJlYiQ1{DH{3>c7ludq1#x z5?(VFD@ z8IM^G2=H$RpwjJiZxp`1zxK%F7DT-$yw;GblnSlZ4jkj(%pQ}xXrxy2eGA}v0{{ly z-c=9iF7+02W0|w;TdVR*@q|$w^$X{-*0e`p2~c)!E@#7*5X5{^0ezG~_@sO*&*dM5 zq^H2n$PY$dkDeI$OBPDkZ1O&B`n_T3x9fWqF5THV%r?+^Ud8PobI3SdGxL#mekKRW zqC0q9fnp!N;QTn(7`Kb^ODKn%&LP3zKLBPIw`sh&`x+c4bBb#onxlEzATR~KcPMy| zZF7@8GxY6CPb7Fp^=Of26~q=!mm{W2JdizVNCjEnwnAfMk}8wS{>I|}ro@zYo++-9 zpkW56m}W*bFp<^TDavffSL)~5_-V+^0Lol!B6M-60un6VK&rlxEL=_9);$0d02BqZ zx$2=gcrZN7F#xl*+jGoI_|e8InqToVqD^t<^--;H78E5JZr?&q>Sg#(MDwqFIQ8~7 zORDde@vX zRHQ;yV>8?e9xr9ce)-fde^3YLw_t{LU~%x3y~UvfH7tgMUPf*I8^gJZGDFNV7{z>_5RjoHD}`W1823coHRN6$PaPHj*pU# zyTMqh$|b2l=4vBbPNFM(AxaZ6=OL zmXdh_&yi|TPOf52BnCge;|uK7KPx7k2SWJCrj7S_xhCPt{P%6Cqy2hM_`uV#-AWtm zU)ugI{5O<(G-<4Q!r#;Rr5W5z`%sD{t6xX=<9_%3vAo~Ji$SA=_WB=su$}*ajKrgZ z;ZRO?i1EG_q&W))(Ph>z*Myl~+vd@$+Ic!1za&D9l$DLw-V3I$A34djHoS6VKL3<+ zb&7=K;i{A$&AIndXm;IyT=p%EkDcZN-Ue-|SbE=1U%!fX6vHdJBU|jJdyR~{uUbJa z_cCDy&a6JVeI9zeENu^5`ZDTuR8L2PLicOCH%~$2tX^Xu3x&pLOefn_SVvSQkhZSf zwTqM=OaUJ-*!bil)e*C+ER82huI3AS@*&r%LQ1a|X%Nt8*sVV1&zj`=RFwY`IwSNu z6?ZMO>)IB=XKKDC?(uN7$;c}Mxe#Blbr`9VZ3n!SDvI4X~%e8*Tm9m-1gc z&bzL}ca>-_izy1d2EOetuXqLG6Ex?|&Y(f~sH;1wz@=mkT%!LnIco_v=H-2dLT?92 zER=TT>qw%Y@k7@wU*a# zdk&cO_D4d&OWU7FHC}R$eoTvVm+(KmKAUXxt2Ib;ecE*u`-LSfxUi_yH2U%2de8DuMI%nT3%hbNN5J8sU<|Ljt|=iM92 zQ#r2gGO4&}S_zuCpU}!5g#TFC8t|A}z#)6QzAd4JC0r8uz#zoqt#6UIn}Bp%Y}<<$CtoPZj-K zE){DRG`SO8$@T(6L$Rg+C1L4vgcton1q?F(SWNAV_2?T%H8#yz&6OpYxxJCfAZ2nB zE)cid!(N5^3jXuIID7MdsK5VxT#K|QEhNHJNJz3}H%YRk!C11FeMu6sgei)Und~)U zvhPdwY?Gw1X5aUHUxqPb%*>$+dp>Z?1r`WM66 z3ZxCbncuc{xzR59eIA?pX?|BSq2VDh;{4LTFf!Bu|RJs@h3MqgEQfMl6#A{GiBC)$y>3JT)ll%M`VKrQnp6(;jfzYX{&(9nb#qzsm(%1So zpuQ8t>_*+^EZSQnHKQ+=k%G}vd#0M#(b>$nwD7#Nwy*Ex^7y0LxZ6h8d?jMzA_+7D zDry=U!T!|}bQn?-PGgfin~?hQhP&W zadxaAI>6|@sRpg9D(w_`?}YARorLi&WU8#0NC1ww?(1_tRneBk=^uY+$>@E2SG<2$ zZnyX@;<>oyc3wyHZOBu4T^_P{2%1$c1qjW3{cdEjF z38peX8T@h3E?>%&ud$%LufL};r1@T)w?`kyC2;vb{PT~g==PblXVHaC4-0Ao(%yfG zkBI24V_N_zCPPn^6Dh%`J{S1ZC;j$&8YQ#VjqRHrB9i!@q4zf?YbF$5yKdIqS)LfP z6^kp#B0LK${u){0b8MK<1et2QZFQ?}Rf`$hOF}2H&^{4prTeiIX{}}Q@p7`y*y(07 zwenNu;rMdw5J_N7k&FtU6#kvOVS|tGOJCm>0-)-_og~b>_%GI?>)DD!!;HOz3Axe7 zJAKa>6WvMfuKj8P*SWHG9qtsqAhfF?!6Orl5U0Y25&pE24F|5QQRT7mIq10Edl)0D zyr(pJA8#TnyC4JTa!o^kMnE8)D^t`Z55-(U0G<0DR(_dP?5kFVg=EClkqUykKqMC*Ye&cVc+W(BI z4*svGDhoZdacGkdH~D$}nY)Z?T4uiQRp2zN%m?RJH@9TBnLb8S@BtkiGdZp2w~z7q zuWajsT&g$k>$1x6=g^pE!kF8|9~s}>_nXr3^rviQb@beQ+pwv4Bh#FmC9PG?`+e$c zF(SB;?Vk<|%>KEhu;#g)rUM3MuBNIX>{m^HQ~wJ&=_2J9O#B!N+odzwNo%tcm45ai z9{)!bHx@$y`w9htLqwCR2FYg|ji$sY&&}kduU$hu4pPzj8+BIhELQu@Pg_CewxL~) zq$#&(;8zuE*eGKvO=U($h}plpV-p@Gr4qg=KM8w_ z2asZe)Yzan>j=6%yZ`q=C9XgJ#_%TnSg$xY1r)U!iUJBe%afZU!D^ z41b!l(`71L%2@Y1HY=W9Ur}9|EI0@RtSs#sj*bWQ{wF0!$v$vn@?y^fFU#2LB}H7z zkRd5yH>dT9L>$eWQ_LsyY-f+-nE8j7(dFB4l%jb{SZfR;l zt&JlvVIPg>QhJy4H=Fl!m(CA~v4?F}DlW3wBQk|Wl(KTvp_li&vFx|nea_4Y{%W0R zYtQD{~3p3{+NvIpHA14)`d|KdIN^~b-_|I5t>Mf05KcP zz)e@ayy(Xzx_$OITSRQet&%_0PmW>d4-dST-B=oLcyaleQeS=Km=pY@5NLY;97wwi zt*+?dHV!m=P{8Z@tAWAvs@=Cvf+fNnwk@0{QK{fx(65*fQ^hY!Rd#sMJt~)H7a6WU zm(8fQWF)o+d~f+6z)~Gx`Rn83+d>@>ui@Ni#kbri27eTtm826ui2>gU0-h=GkUXOe zup{dnCa#y}?jRBg#_BSvJ6e?Ux>1bkmPA}ejdE0_qM6wr2Y6vlB^ats%2kWGndpRb z`f=p`_woGyzAL_Xfh8`sQiWwN^mq+n5i_w z9poQc?>K(n5}FV&HaT1QsYEHR^VGoLOzf4=j>1e`FOm%Ur4!=dlWR{_&hYD#E z7rq1a^8SVIK&Z=m)I71Mq|EN+Zs$7;FS$RummvK)PvNVZNr;R(>)A$WIOyY<-M4(R zpkIFQ{?|t*%{BPXws0989=aEQMWp)(nQv7#Gf;tB!`Y@vR_c`a8TLqxpXg+CGSCyE zbmJ8tq`b|QFg@Bl@6l)6uZLpGF|~_ak1~|<%}gsSrn%!YQ;wox0xIIx8=$LuiEtVm zSpLwqxzN(ymi^2r)j#G`L~CXm3ZSm97tV4wqKz#ditzrV_}!? zT(jpWH8j2@bX7ymDH81? z%Z}NMvL}@=9^v28q*XAKs6Yme1(|y%bh2e>ZTM#7X$0LuNzbTXOXihi5$by$_T(t0 z&?wL=o)1AWiKgQ!S2o{ry}4!qiwtjz&FH}-Nw`oAhmLyZY>-#P?L9e{AvkGeI{?)e z7%1v#E+{I?tY))%f!AD@)p;rA$W1MMb#bcWdMAXK&fTRdMe9J`|Cr_@ouBXv?mb`` zi z_6_RaR~c9G^sQ@f_Cn=Tat9l(^sbKxwIa?6YukL5F4R@_clfK^<0dO`kPE2Xcc^Kw zYJq|!udU_Z5^N<63r$$I1_V{E$3$-0qBZaL1@;3MKNKBU!9YI*C>hMEW+lq~F6Tu= zqa)~W+?VCp=cAkCt&<1mL;?bnH$kTZwg8JZ-Pl@gPaal%vy+=}T1I;BVivKJa}vdd zt%8npB6L(RvWe}o@!+^6GpPNN^k(T`k9(roCMS<*ujUr>c==U5SNxK)Z{dS$1U?af z;vzAQM_Ka3N$T4XCE+nR9s#TzJ-TsechEOA6jljc51Ks+Oc7Q#vh)Uy>z>54Rk-LO zjqd_yINp?$+Ld=eP3y+j8*ThBgA`p zRT|YU<_@hh@Lt`T3X^$f{i$dAXS5{7TlC_&0f{m6x1fGQx#q#uney=~~9PnhOY2k$hY(UN95)JVW zDYxD-RKD9)E=SKL@)c?&V*YIRB7M`*P7RwbB3<>nj0z=6_7^zNFYVvY5M{bc;`6&Q z^hPOQt=D|)@l4<=Vo*75bzeclz`Nq&Bmd-Pok#+5pe`YNJlvHJQGwe+wLhg<%Z|=p zN3mMh9{guqwqj%XQlgt@TP5JMr)pz08?HT#=GI_9F*!?s1%p)sI-30pL{ciWY}|~{ zl3t10k$$Of+%A*OsF|AF=>kvK3?run)Q7VS)MnT7Y6pqZcS0dSC~>pJjP9kb!lJR4 z?Jiq0C}yepS7&KXf?<%NsxHEuV#HB=bE<-KnE{Lf)OFsSKm7gUY4zNP0dd^1Ipkv2 z7c19?${$u{Z`{%G`{v)x~!`#bpPmm4i1D z(#18m#f)PRCJ4?E4YJ#O77Zhlo#5n1Gjn>vIQNe!{sS!2?4G0QkSGil6vcbYkoR>|&cprz zlE;9+i|%UWNCHx+XwMb41*oZgS6wJf?-NN@NH*Hl{-%kN$pLdEqgL ztS-#_qZJu^!qsblFqd_{$>~Psu9~uJXgc}4d^$i`ZWhn)2&9ni2|5eJAO11(kxiS2 zsp+kJj42 zq$i$c2UHTO(yhl*mD`*!^D9Nx0Rv7i-#}C!q!N1LPNBA~Lk#!ommBkDK4uYlnh!q( z4N=)a080pE6}~b=o!S?|pOmop%`j$BaKl`psxUV1>~ms|sOwn@C2E=5p>)DK*xAObZ%~Zs&Dj^p_~1 z8mH5_8Nc6~eUaJVIrLXJMp>#amt9ZCHEryEgXl7-zYi{CIJ|c2H>f_h5Wqxpb!l#HaJyfeQ4;6; z1@KR22shW$H^}Sckz~#lk&_Z}X*41<+)&y`LZGDg?)9)vbCz-HDt-UXM_$icRrT(ntLCi6=LFH3W^iZRn5T*yos3N{V6)-3>*lOq4lJ?-o_m;s|O-f6)R z`CMp%F1g=I(}vc?KFPJ>oC++OceOy&%q=_&GjZ}5+w21;BkjCoey-GMIm5+@edoRi za%n3^Z8PJY=5qKjj>JL&mpZRq>MwO3xi$e>%WB5Q3%V4q_zHelM<41-ac(Z$6M6~T zwN6zY=y~Jw%Ka?W@B#uZMSZcef}ARdFViUoPNaXM$Ld9r_8Ue+*sNuQh6Cd&s#j|s zK8!2vG+}lpYJI~tBsMWilMpl%u^kMrR&CsjZg>-37^^E%a6#*Ojbyv_S=3EG68l6^ z(QNFBfiR!=vdTLRz^Qtj?Ri#nsfs!9j(=M84u|K0r{Uu-&Wl-5^HO>sVU2FT&j+dD>l@zS%Wz;&6W6S(DDY{mwa|xiWt^`H~M)Y}qN2V^*z@%;a+N%6{L2 zs(soXo_2qEG2qfz^+8uWN}#)^UhKi^xhb;&orfI)31RCrDSmZROz>2Y#IV-V4n?q&$@JA|Lb0CME z_xOKVD9XLh3yM^o2QthOwi^|Y%?rVZn|yvxcY!Fe4Ut3ufnLQn*>Noqzn^|LV~h92 zsBrBphkfxgI~AFGH4cgdd7-FW_^7uz6&IrD=X0Vk_N){~x9yHJ$)I1aw?8m+X1kM> z>*R3IWN%;ZUzJ&R0mQhl+(3O9$>tCGLlSCmXW zNB$oCfThVSuMZ-Fh2}EZw3OU`Li>?6-EP{vEAwMx4tOv7J1KlPuD2MSP5Gztqh{kh zjlG-PZ8zf&`TM0qS7{Otr`)fhlE}PnF*okVW-PcT-}_W>{A!?6izp)g(BGG5?!E*p z^d#lwM1AB)r>iHs#I?XXuY2G#qZc6fNIxC%YjV9{y>nqy1`exRgEmJ-gJuJaj3fefGn5676D!R*wUM;ILB1F$(j$6UA#UL^CdOfJ=Oi z3~SFdZP>AzoxEa4X7F{YD8GzCZAbyVruPwh`q|Bz$&&o#hW0h6ym&3Q3PHqdz4!97 zz`1OU2y#@!f1aqS`Bs>dn=vv)9D|W#sP;Vv$~hSK+Vj2}FRulv=^IN=dt@+$t!MhO z9STwGUmHs(=BOz1H z$KHQhnv9M77O%Oqpz8cw_J3zUGY`nN>;~%g&OFJP@t*@f{tnsAWkso!32hEl$Y8FH zTee>ee_m_}>eg%5P=vj`z)8xWn)g=F+QfgZ{{N*5{(qRl{x|eLB6;4Sn&}C$p+=_s z(Y(Bu{4E8lZ=f#nhipw4#og{5S162{DRGkcGBH+BDqW(bu4^RlIWr$E%%21^J*(uZ6$6YD3}mN zw(289QOSj;tKUyy2!VAatvVty;u}D3^aL3D{$tWRfOmpnLcVoAy%z7H7-0yphx~TG z_Tu`0-HSic+~z zMt)dI%5f`hcb<6mNsA~xhsxqDS7D)0_Z{b@@~L`((q_(d!u9GYwK&Uy0(*l-i?=`Z z-^gG4%GRZSWE&guC_+AQ95s3BI)QW9t$6>6E?eo zByp_nPH@|`w)M%Oal`(@m+Ingqt2(qG@!LrL;?g@Zmn4hy3ABgdr1& z^8%hgYjWu7E|9Q=|6{V=3<9>!WOun6sWIAON>Gqh1$BwetI@0EQ+y69-m{JGPd>zD z`8_fr?`{Q`Q=$;t1oGx>+dL6RwEM2ni^-GujEbOeCH!V#P+L+>-X=+3|GmJ_+e=Dk zToe!s@7_2s!%gT4ML1(TyL_EXYZi0_@ zSyI4$dQHw`gVq>$=lHmbFCUbpaOE=ByF4l&HWnu+NHfN~Dyw=&AeH|!goe>k-)jBl zM8+J95Vui3g0+QrPEXTDKfYIfuGpkx1!ERNO!ZP@-~#$;vwKi=UHHb&*2mp+8>~c5 ziG3>jH--22`kAvkU5< z0o-eZxrvta%fL^OjqtGbC}a2*^os>u)-Fq3+R=j5L^x0EoHI&xA9=6;Y) zDqMqcQ^126sS@B-gdX3*5 zSEH~$Va>z}b4j9$> zciVdUQ)m9f@!iKVxkeCoi~I}gYYQe%>Kt?dzi<@npknV>BD>4QqI@BJb1_}z`(A}o zh6aXOGD=eVosex8MXGChNC@wA{H&fn?wWB8`))IQL$Yt%ZU`5gi96p4O-5+ort0oG|_OMxFdg*buOcrB|;Hi z0oo9!|1DtsHp&{UB+0e1-o(374en%r;e}edB2wO?x;1>?B$6IRG2* z)=8iGU>2MeQ9n%j#(u4wrc_fwLg`&|=e#crlprcj`v)$C-_l#>NALWuFcJ$OW~tjp zT-7zwr}15KeXTI6n6W>LR4X)}L?busKzCY0{8WEbEAkp+U$MJi_sx#`5 z$$JRC0;F>c(ZmzxTI#2nWmxkCpGo(ZkB%m2!^`R*ZmrZ{wpr^1E0_>k{Pl)|S(OKS zr!YbrY3$qW^`w$Dy7}aoFKT6qfq-IjhR4r*t(O|I$;q?LAsDY_MWJ5i$iG0h3)Nlqz!P5W?+wdv}2xrq8M6U4=9 zA-cC@J2P`6c98l?Fndb*r$%MAt-zKZaLoglhPHj`tJf?6W24xKec z{Lo^((*u1){Y=LFN%oyfBtxSq{qY+V87-b34K$)I|7#~(7^4T$gTH1BT*R!u-s29@ z4$8NiM+#9LF`ua3OCil25<#(GTb41*4t)Gw{4;VRxHz0wGGZc}b2E}QLCp$3y3-{~ z!*Af%Zkj2jEHAMZy?!8aMk9KTKu?QbvC-iD{qow^Y)3~zuMe!^Mktp}{Hk!Bq;ZD7 zUpD%4P}he>X&@F-qi__@Br^K8T#oC#i@t|)%oP2V&C;HcTXC;)^k@U@0KXg*Gw0CE zD!pxTvLZ7g1`foudmjClmfh5kA`x_R$`S*&3&tP-QRqaT#O{CaW*H&PNNX_q2_u_WM^AzlNxf&*fmuJHo zIYW=j0jtGmXp1_viyNaZj3b-M62A1GUTrPS4+8Jyf6Gw|bQy0X;VYB7LQBhZ`>meOGz6U?+urXULM05)ZO@1KGSM&R@<6@`f5)U#^GlN#l=Bfc#8!CmPcTK^?+JxLhW3o3L+kG8(jXRZZ z(=aTXY9O?cqMsZ6_^dAAFLnHIW_AHJqZ_q>8POJ|W4^H{7-4W4q6`Qe zaNHp*p`UOU=OJ)zesyM7N11b~&v1Tvw?~Lx5#EdN7L0%Mjl=QSm#lPxuByJCN{?Ev z<-l?DLduO;(i9^Lyv{0-7d_oO8C!(bFxu!r+gJN%Qh{`RBZD5KDi-2YGJK)RECwF~ zm0@fP%Hc7N!jEALn!h-f_Se+*@v!67yWCOCOuL1TP7?JOPCqw3P1}?m%Z%~Mj{3)x z6@D-ZUk-vgVQ&>K2OUMuOMp(R_N_qQT*xdm7UBOx0G%hd!yZ`p@$+Y)dc=`-=@5z^ zn5#@_dqwb>+H84FF3a8R`cQFYshbK-mWqyK-7!D5=Xeu07yTCtJRi700{zNC#W?wV zN?uHIx+XogU7$~MJZ?8Bh%`m&lS9}mF!h{T4#G8g?Sw zsd!fS52y$7?Ac6VeIs#%)WX0gf~&--u(5RfxPF*Jiwl!AIXd5YrnN1%tO94eccmjS(}%q@kziqkrCK=~h& zgf&)L5nd$vLQzpv3yGWfyk4mg?3>SQ|L9t1X+GC!LBp~pedxYNKk3oc|LOqIx@el( z>2!<9k;hk9(U;1OwGkq)L#%guaZ))?_&z+B|LV!hNa(5XX}nYAGqkNX0=S<*ZcfHl z;U{?Xk_BQ2-p)3=(x!IP4xt{RQCokyFGbw3rW001y3Z@T94UCGwnbN{pUsQZ6KEdGN;EQ>UF`n6sBvA-NRP8SgZiyP`)rdKC`G)?veHcICmU=JmA|pZ1#OR)3zd!h$h(9$ zJNyJiLVFXSor6B;xtCF?w8u@cvtLN7-EF_bt*Kk1v*2pCQ9bUUJnr9An|qO?XLjxz zP7#xm_8=uK<&N1~!JDbJ#FpqzaV0AN1tX~Z6H$2~IrBVT7i;V59EPkh-)vtt8=WUe zz};CR)3PabG1RM(ji%6R`qp^YNnh0B)&}i~*#jn*9t01hL8b-}yB#RL4aVVhmgj=t z`%4G->>h{7OGk^bF;P~9PHB>N%ca|;^#}ZZgo?9H?c^h5(XjnB5jYi4RpzIkg<^Z=$mY_|pbIMojn&5K#;FlRx!va?6-C0` ze5;E(b`|FdMee7jhrpdNKu5h*5KGRiD0v;ii!YOVW~qL+y}Q3pP*A&BpxR=C!@@iT zB|*bXkK{|B+-^C zF1OiexH*vy%IeE>7+(W}ZC~1HHKW!Y{NT)={#;C}IaxaX%a?@&p`80EH69u|ix+oQ zO;n|2&S}j?(i85_D4*Ei>ydq5ZNBPKEzpg9tEZ`;!5wkdNe<1c8Ib;?lW*a9tQO|n zZzmSV#$qc>TiAj3T;eilxqk)Pv*Cm6p2^!deC#TbtyhXhkavH&e%~7&sbfO+Q@`b< zeD$kllpz4{vO-VpsBiSJ}E~`FHVR4f-Bd5&mrjhztqo(<`_abDW#G*R#_J zc1~sr@30ThT!O)97flUnl3~BENZ$1wR4Z(=OQ=)`cFt*FzBA}v%2%gHD92=fj&}Pr zS4W-4lj77}U@~{9UBCnuHHd?RYBPiEot@*eQARrkOs#nfDY02(R|ia zdobNhQJ3CswU_8SoZZDPJzIwu!Q6_-ta9dWh?u=m2LmzVD$>hUjxXdz1R-N-SGB+Jk>r`cX#aTm%M= z({GrmvJO{bJ9Qrc@-Cp$&ikOBAyL0Cpp&>hq$DryDywr6MUI;}?MU?vwzG}QU%@(w zpio_AJG!uqp#BpA{>p2}@7-F1n*I0>!RnU`dFErAn9eR4D(w z2I;k?QL45VZfnLkR}$&y+%Q?T>Btew2B)8>qAGQ3vC&7o7(rutrlio`tZMxS zNBbA!cT!>3GHj?ohzJzy>M}dpE9UgSEgFW~GoZs5Q(4!gEInWSo z&l@ubNlf**St;b*2{KDUKG@Zaf(&AO>$aO`Xs=N<0l38g>&-52Rzs{!T_9>;=~qgi zb79upw)bD{OVenxh?Week@QfFs8q&^5{MLEM^3`B*IOaisrcIPlg>~9>ht!>57(tZf!XB6h8Yx2KWmk+*mRT99uH+CN>Ndlsb2fsK~`{uQ#P0Md&8_qo% z-oDW1ao6-#P?qiskdboc%S+NZqh`y);rvlq>93OK3$(E~*{~+ru*SXZhroseKgw9o zx`#fBu^7aO-}4PPxK;bWJr5`ma0dt@TPMzq)$|M+Ily{yPKdE0sHHSzZ%)?hP+6=@ zhkm$%E-Bn7!yg@yyE~_*`Wv@n=oPH<#7s0U(qfX+7J^TsNDL(uYwJIz(=_Lt>^`ZW ziHAGAwrPwns0HmyB6&eresCf~`1RLr=PU*;Ep?rQ+n*rup%P7;HtBLR+rYRBF^nUk zQyV|F86jASvvgO4c@c*{eg`GckE@rqx}-8kPhbNb66gUZg5b};a|egqEnHJ=`q1pr zM5ZFM;@vI1KSL)_7!941+{*1py)t8cJq@063ALl&Tj#SqX}6nhsyM+N-T_LY(>If{ zOv>%IwN&s0?e!Cn8MU66(|>0X+>hyU0k={Y$lI684%?&c`^<&Va9D%{k`*~A&Z^WA zZ~-0$kX>Ho^ti#D(`p=$O@mc{2M(uwW+LzL-d9xDN^z$5^NEa%E|YniFLk{J$Rvxjm3O1v}EoBK={B?exXjFr;BO1p@ZRF0gK z)Qq>egO%3Yz79$B-|%g2uDm)>n!^7cFv=x4?haWP;OA#>R?1ErF8E=xZ?X-<#^cc{ z@51GBLqs5RmywOJ{z^?{VDR;;1w>Q}I4u3sr7j9;8K^r`52yg2fa?|}e4cmjB_hkR z101e%4+|W=B=j~brs`K0Nedd8L)z5@%yR#zh z(mGxDU0{j@ft+3lyVfl&rVgkIJ?UOB5#OcHT80Bf9U6w0#Sqx7tS{heVl;bnue?## zk_TUyN%T>adQrHvk{Ns%ejr|K@MI91S5%7jH@lN-Du6zbOZQsgk#Ru5f?>PeMt*hC zs2)B>@);RsA+iT)x6lRN+V?_rx>X?m7W%7eWi#^94m&^WW_0F-PTlDw3f_le&v;8$ zKi zWk2i-ujGQA*-Ghh{UNJ?Fs(ACDKEX=ZEJ!I%g6g2e?IU|*Q&@7G|1tSF=Y?n( zAxuZmb*w!TU zs7G-gyh>mu4(YBW1?_39(OPGzQ}Vocc$B5R^Gw4 zaOi*=j$sHj?jLlSs+&;6bXhMHc=XRUv?(9MO6Md|vazuJQ%LyMG7!_yD&T)#@4h8+ zTvcVK?>PVbx}*{m`1)7UpOeX-R~0vm;0qiwrwm5ZwG+Y!_xDmCgP1X*@kQ47(S7Q9JqtsHlXMybbS_1BZ90H`r9RV^8sOox?F9M8W*+|CF!5n#{ zS8q))#M$1$?v0UgMUkt8af*e8DsQh?hg;$#Yt81Q(0v3M{UO<5Oz|EbrjwS2O>?0u zGvB$IjXs{coa=J^?EE4Dc)Mm8nLrzWeSB-hi4ZEKe$^DtjNm$A@`i^U(^-m-h$}W4 zCSOiEzNnR+*c>bnX8jY``ZKobfdLWvbHfQ$6)?`{j~sAulCZwKoa!v#DYP+P`zoUH zgPHq}s__ZX)Q(*5|2W?KvSQs;Pii;Oq-!WlZOZAqt5|K4!4^%R4!-vse!w=pI=*wv zRA4}#z2r}?#%%}Z0QZ?iSl8gFa%8e`g{o@*=gzCKfPDxGuB$T=i^)p4__(iAA8E>y z0{q%wyN)SJQ=~OuT;X@G-*)?zXz_a`C%iy$J_2Q5*B$bN%o_bOD zs}tJXXzI6j>C-BqKGT@1-lOg!7bs2a&m4ezS%tpaR29cSE zjwT$=Fv{^|PV4^1lnIG=AFmM1p~YlYyF>)H^-YFHfV?aeco2*aOyG}eKIF6rv<=4VH<41Y8N&WO^$zCM&D&8 zGGXWcF=@Z?j<;%j=IpJUTeUsqfh$`e;tu$Wb1_EiJSIloiI#hzXN9({s)xrAPi7An zy}#6%`iAi2M!nDhaxQk%6cNe)W40^5sKrc;x3I9H+@JrT@=;bkF~v zK3Y&VMNsOsqXb5TYd*v832ZPcE+X$K1K#yZx!zqo?55izWoG#y2T%gU`)m}TTm{RP z!6lUpcEn}X9+r+j-*t~(=XI5h=693uonhc4sz_w{%BKQP%ZZSsCue~5;m4`IfXwAt zxf=Uk;7krtBwZuZ7{M1FU`}Az)Zl5jdq{zJe9tU`m+bAd^)>M zJk#OgA7>_Fb}Tm_UxRG}fGa7Fot78V!|2&tPA*PLJ8I%Ii>V*Wm=@l;%A4G`WkiM$ z2WoFslkXO4#;^`VU7yqpi@OGkKTiCy%k!wIOYs=OVNg zTJGFRV8&`+RgcO{OARgNl%D;p7I7_H3?aVR4l4D+v^zW8*WI8@gV6oA@?>I3Z{&7^$c3e;yl%CKImI{z!o-9-Tm zC(^*#uH9&zw^KJEKa$Iom8CH;yLk{~D*$h^2+ohRxJs>!goD3ZdPr%u(cN17{WoW24Gp%xH+CJtosOokr3&biK5_e@5U%5nmh^mA-40$~@AL zuxL&pzMe&3G{7|j$7Bs}iz2l?6*&$b(IS}PXQut#2@JZS+<^(yBgc(OaTShSqi#A8q zzL!DKUoxibxAa`n;z4XW%Z|#IrVQl~4q|c*kswOgqF@^<5+r56I+5-Bf+e3b` z!yCZ#W8hohe061*y>``O4!Lme2VdC2k_CYH)0F>=7xX>^o+YWM{IYMzSJOfRl08kV z+eUNg-$J=j?6@CC^&m>hA(}MhJ$-7kSe))j(SVHvf6Kp)WwUTdZ|B-6&b~huUv~3l zh7jY_19Y^sd5};dznBuz4{F0+IQlZ^hsq|Xm9w`|KPLgy*EyU9-UEGD?P+ZjgJd&i zXYxvJb~ALAiNt$Bqe`Pl_Z(Ce3M7&=6m>V({8+3eAg8Esd`DC0~ytt*DHgS(*zYdjDqN zR#e!c`mBR6q~uG0E2uFc zRrB<-CB{3i5mFl_*!pDGG!CY~AHi~fASa*f?^2rd)Mw|DO^Z@0DG(w+Ml^W667Yzx zOkoqE7LS60PE0w|R(nNX8^DB_$`aO9si*Tb`v*7=I1liX3a*5iwd^dc-?ahqu9gh^ zqXvZyp$xiC2{x*9KP8F2RAXeE*YuV!0v%Qf^gpF#7iPWfedu5 zb<(fyHh_YbE&w845WveDgCAW^Eui_^=^VwyT2?M}6u93^4uZbs7??!zGaKaJCxzyr z&CV_C1}VXJUvFSGPz3AOB3U2h4AO9`JB)gRQ3v;2Nnm=gFYWcm9{VtHbU^wAL6<`* z*07UDHZK7Nx`=D(ppyU|U$S&>h(NQh{}93*a#uL^Vag>wJT9>-qtvRPmmxiYV?hyt zxV6l#q#Wh0s>7X~O~_2o4%NE8y|2V~2{nBmKD_ITcWqB+Sl8aR%_)-e^GCLmjXxJE z`;3vcgfz!H}T zd=2HxMRKE>C^KCc?4UvA$J3mJ0&V83OlRR$6M|%g5c*pyIackcCn_$mnG>A!ZKzJ) z@*vC*un*_j6SDwaLEqo>jT!A1b3=vY<*$mLp_*X~>kS19+iR`Tg^Lmzr^L>yTIAYhRY!s9yso~~9$1C`wlG0C@+Dg2G2$|Qt9!g67 zb=Ei5LSnyP1SFxy-CK>>pda&s%-l&*zKSM|Hwx+vAn!y1+KCw zYA`hX676$9j~ZtvY{yreWrM2Rds~-j4k~V6uqxa;rKGQ&e0_&tBp}5IZuL`2kuwLk z%X4>GtP6ZNw`$A~)e}Vi9uYb~gMZ=ih3ywb-kJwmjB`M+v-SRcYG%~j8_7qKwje#%}aw&UB_19#W5LSv4+wZZ%)@&MfGbFR zT?ewoO$`arzYlGhJt#romYNv%8S$$mOIz!?l`f@TRZ|TE{yt`D>8V#St*kGzsml*1 zpQGB~uL+ww>F3d$<*eJ(e@x9@8yijcdUR)kBD@GX%A&tZ`;;x8XKkzURKONls2KL{ zM%Dksd|I@$eBtB2b9cJfDnpd7ndg|vO`a>>SJ)DdE)Eqjj9M84yedMU+2xw<4TX1^5nHwz8?>F)4xm=rhjVg zFe(cq(2s+ber)Hp*PF<9%(_ki`MX`*bNS6T^G16grwFUC9l#j)N1`ucio=?&mB))+ z)&i@kfd$pgf-NN%EGufUep!^sLyZ79Ba<_{aGv!nOAlY$oPo9#BtrkH{jRiE*Ak=k zynI>`Kzt1i|AW@3{EU%}vNe=2#DIa1jyo{e)wF-%L~icj^&+Lsf&n4Qi*Q zl>!}b^#594hPDs6@0@nu_9qahhTFZ+E4T3lU%AD&1(mc`Nc0&R)bTxtC7`znYSP~| zieQuAz{I-$$evBNt^qSqQuEy}sE#r@b5<#g9;dzsD-5=f+%FH07^#_3QQ?PJz6-{6i1W!6f5UTLFk zz8lvDQQZ(65JlTw==P1o-*)-=qB|Ef^vwm8jf}Mm)Di5*oC9v#5RqxJP%R?6E~?^^cxySD$t8sfSUB0#ok)$Jv`lL*0k( z&cclm+gc>pSu{POvlcWjBGM229?7OiH zv%UMi`uxuM{r~x#DBB@{Q4EM_z?p0b14% zi0OEuRE-NSIEZ>f-GOiNbdf%nXcZS@gI>5f_lO`?3YIxi?=;8zPNSZS#7Zx%Bk^Kk z+tKp)VsKoffpf;Z#?!qbFBj$7MC=-QMPwy545w4s-@><$vt$No+ota0X+ITo3IeI9 zt$oK{I{cDAWvAjT7s(FY8CT~>lJ^@uRu3=tvvXK{sanO4NJ+im2xi3kyj^GhJbXBs z?jv{o=Q6GKu61%D*qY#7k)#TnSSjoA2o49h0Ne5gUTIbl>=o?R)180g`2R zV@;*VA}p27x$uWeYdRS{1}(#J&bPmp@C(Ewy%$ar;=0IVq8_J_I2y9!xBrf@>dbU` zi~qz`zu*3ZHIEZuC2#fmWRC=VyU|v$4VsyxWktyBwKf*5*nWWtUMY~v7IwH~M;d%nZEsgswzSko8cQN^fLt}=u@Q>?G?P@kfw2o%}!&oqtYw3tMT!-2=9lAg2 z-&htHqP8XxmKLF2mV)v@6JHK6SMzW~a= zT6NvaWe-tT-*q}AowS#_mR0zaOg~iu-Y!sJBm=&!0b1uS&7)|v9aL5R4~k%`FQzup z)(2P8?^7R7h2!&Ad71jFDCX{rtn6Dyu8KsTG1P=elN_Ri661MG9Pw|dJTu6Cx->U< zm=}+jg^8$+e5;}U?1-*b5MtR-&bhS=fxd|8jbNI&* z>o{l~qojWbi)IGSL4NO!ZoT;L;9c_^k+?e|T*TS1zEB^(U?c=*D^H$z)L@hn`){{flQfpf; z_;;QXev4fF_R!#zn|Pc2%Yh-`;Zt=)VTo30K9h*`fKch2kodOdSczLnUbq8WsIGnibMs4KRG#g@DOk$jY zPnY4I;y1PKqp_FI*tA)^PIir;X%w^1ciF%?uQG~hQPklmTc~X^X3FI7e$w+}Klqbu z5Af`yiktoS{;c|gUBOo*OiA(xRNx~zXKe?Mn8a=pI0tsLLoEqk#D28-+H5H8B>wb$ z+m0LcJj@&o;Gv>)Pzv|-w1K^v?5m42?FZHGDtGF~d>IgC1g!5&3@$lTbeu08@j4YV z6@TxQ)j#U}nV<6f`0wlOra283x0KZn^9?mUY8qS3iam+WP7^~tsWZve&#TrCpfDlr z>bYjC-__$)s+Ree~zqH$m1q5#2dm5`MC8Qc2+ajWDtzlQi11qUQ#7 zLy8*oPF$nJx_yeDPQOGjtt7IlD`Jf=$$L4*+HgE%8k~FB7{pg#BjIWPQ7T&GjI3?J zR&72;0*~S5T!8vCsarC@;xZVee)osRG&=(1G5y^7&0UKFDfcMkL!$x#W6MtZl&* zw4seTG{AWWQ_-9-4whnm9TOGn0pMd)EA(@+_vCc=^)++!z?}T(TOR(3^jng)$MYg( zWo7oXiKu+G%_ppZw>$tl(#h%#AU#&VqNMAZO0%zM6w2xoc;B`@a*MYc%<|YtKKt8W zX{SjRYJj@a_V)ec&n$ZI!d@W6*OW5Q@OEac&5UkgbULf(8B{%W;IpCH3M0f0oLOqM zWwOSu^H+q4vpP?%a-Ppr5IZvPJ+3uOpdmus-$cg2Ve^>M{LB*2^NHib$d8dtrERi&jbej0=mcbLa- zY9Ek$`>B*7ah{?vmrLU;y=LU$Y$HZ_neQ+gcee5(s`+FaH15W@M zKEWHWEniN>I9U~hU$>P6){5zFgmgvF+VO^2bWXW!{jq=eyGlI%3h0VN6)9e&?IAZ) z&(ehMI>$)FXUCqmb4fN-jRO=Ot2>Lp5~)68?>!gbvk$^n%3xQHDOsbU;83HZ zb6Ydt!N+d4chupp2Dy2hE)m4v`Q|ss@A#R}(d)Uf_@NdCBWP`2K1I+w?>S)F|JoKf z;)G_xlXKl90%Z#(Lxl@}M@p;#Mc9*0@+dTn@(OUwuWOSArH&Q!n|X7?P{q4rBH#sc z`SG;9f(m?sU~8ulWnr52K}$dzz0m}110?MQ%@4ADXe@uD`Dg>xOo1+8P%y!=X_9NX zFMzFS;)e^%?wPM)8If{B*?xHtKFt5IiAqBWuwQ}<9;bp=juTnvf*CZ zU_mVd6Hyb%tLR^BQ5*{aLyP$zl`Ia{Bq!W^=KgYqket|Z%J6jVd-ywI4Z#@$)Mew& zb)-pyat`iyI=Z84ePKZ=CKtsEJe_p;EhskqDM`*0#PXMCGLk_UUiM?s66h!2B29tY zl(gr9G!p#d^!g?o>ZL5B@n;OrAFd$$ zHmQ^4y3foyjAQk8{jR+yKUVDJy~S5G7WAYGZ;uysp(J<@9oRL*4d1F3x zq%9jKR@do>e5ogeLn?I~ugviQck?kLFY0e6=~(~}h7@DB&X@|TUKK(1v*Xqms^uml zef5~==3Yk;ZSkE~udQGHF2D)<#)~7T&%>MWiN6)ADm;Z=2Dnx&{5H*r6SqF)8-K6N z_Vef;E>D=a<*~R=|7aXBHmmmR1nz=n()msib8?|N_^#AnaI4J=q!%~_U<==zW3O1O zj9s4%$5Op{GFH^8GrPE2Tg2X{*%SB8w$Id@tZy|L6e;eW-!OhFlT*<2W(@`IBY1|5 z2;%tWG17_d0GinQkfQndSS|C!jbo z@FT&_w@J<*>@m1PsJzNcrx82Wi7AIRT}Pmo-K0JcUe^5jvE!alr7&rkJP~td{d&Uf z&flqQ{Bl$JoE5GDG0kB5W;xp-cnf+b?i4;tS9^BxwISjKmipEi2iT!HXbh&eyFSTZ zU!Rz!MDm%4K!m}A#kyb)8@;PVwxUnqfXJIQ5R)DSq4!4#ktQRaIn&dQ2LIfhq^acw zJN3RZ-BB~$(P>g_=4hwpe-zl<#Vh``r@KUuxb2jWZ{|O*!y1P+#14RJt^-|H%9B@o zwr`908f@p)Zr|)X--UsrnKG1I7qRp_RU>AQw^3=^^m|Kq^aAhrTGubc*5$FJe6C(i zQ1c3cpZ=JJ2fil!cX$mSr*Ox-2zk4zQE{R1hGi1MTjWCE-HpIZ(1C!qA87xSIVJQU zkfOqZK5ICfD=r?!8-GBM2f2%JuJiMA`Hf2QiSmgIr^r8C?)x25wn<&k8-9>of?YrN zL_5W0Ou*Pit%k*ly>7ElBV-7Rq{uWfNQ-6I9|ldGT}*u(i<8_I(ER zS^y{S{gZ>4ducgG9sjKx zkNu3KEkbcj1P%TXiC=#-UgOoykl8SPI8iwL&8d`inRwPscKFgBfeY4{Pzn;4V4S*J z`}9;wt9-hQGkOc#@mP~OW+Z5Ssc=`Y(c+%t=I&2ocV`Y(i4+BQu+xBh>?Z2GzswG6 zTx}H<0~Dq=iHqVlzrWUfwR*D*yP*c|)#S@x@E5VKegjk{YMt_M)Jr$A zwGT=9H!Dkhk~X*Tmj<}-g*qd?J%8-l8S%A)*l|q_RMn{MP+O=cR<%XbPQ$3q!q6tO zPg5lkJD$7lvDT`_kOo}lr?{bQ^B?(o=XseCR|~`|5@xSKP6%d&Z^yQZvVohe)5d_M zMAC(}Q-lqDJ(cl)X7G!gNN7rB`@Z$A0u$ZY*_%Shcs5h#&_J2NX=pk9&L1v1eqpfN zzV>nYNmWr-LQ-i@uMMzcE^-fWgj8KO0+fz}6SE>i;FV6{j1Y$p*e98n)0_N(zt$T9hOdsIK?C(rVx_y(A}dX~!e{^tES7dtJX~S7ikLy2@%A!T=E_ z&salgK$GGx;M0ghB3zo_&ACqKvulv*Mq~MU{q%LC=Lb#dqek$EDto6d61GZ08gJF8 z4xw*aZ|P_$h+W3yG$9$bzD)Fp+1Cej<9|(5+<2qNeIat_pX7~2BIJv`?Qzbok(w9H z@;oXI?7^sT$l^ncEA#ug#{UcMqx@fSpI&{#1zHa(;>XUisK+5yi~Q;potcvC#yGY& zD52WKx-JIpR=$QxCl0l+8y(5x%8s|PhiY-^4KV1IOs)Y9@qEwYw%_x^$62c9Ed#(l zMinL+uL^9Sk<2*9H?Jw`DgfYh6l;#kJAhi?_)=;H^>kc8O4p%yokNMCX~w8CEmL_3 zh@UL9=HP~R7HR`1eJbsgUKr6biG+4iSKO7^U?2 zNpORQ_wUwCY6&m^#8cpKQXEs1-*Y+IL4sl;roA`$Lz(c!uVy+X7RDkc3P|pOM7Bm% zdh&ibnWkaIp{*S6KU{C=Up{reI4JvtNA4OI2Ko6DS5b}=7@spsrakD8enlhiP)fBA zcae8Qj~=DyH}4?1uZqceqRwfQ#bWB*@4sx0&r5dK%}bOFXAO&>hfx3I6_l`u8+g#Y z1(!(aavpp<{3*UDC+fVUTmFJoCcjjJpRhNZ2|1Ro-L0$eo>+`-1U~VHD{gMChC-l| zxQWywRni*-RFY0yb53yorc~i=c5?<h$S7*`{nIaQ?QYzcSdA|C&%L$j}DTk8WkvCs&75>I06w1Ca z)UHB#tyi|T?#)=LH_kcR^E+DH)y84ifJ;^HpWXx4Vy-XvPnS$O)YB28k^UV{XNK%_ zG|$>k{NWPzc*DH^C^nYwOG2HT3F2P@*imHlIZi7%cZ?k z6XRWl$R`xkEtmA)cIfDnMcz`>4>l&kV$)j$?DN_Py_FcmoN@ql9<-;7)2bU_Yb$dd zP8&m@&;HG(1=Lzpc5z81kbkZHbVN%6E>-XyvXn??H=!NsJ4^=JJ~0E^EY`|AFjvQf z3)c`BbNzEZF9xRh-Ku<&lD^OHNF{!P<{W+X=l&CI-jKc4m&B3jXO$HmI8&HjeIGMi zDC?emh|T>f&3w)0aMkenm*>|3hldNz#jq7{jdUIbP9BOE`BC;CNn_HRNKnV$r zjg8CRxy+n?y&B7mExGrNeSOSI#Y2QB>ZM#kSJ3q4*zDQ5p4xh|M(e?p#FF zu;=ZD962BDu?M92-B1nzvE7ucj7Z$~EL~+48Czjxb-u^2NOVBR?k!~->QExBph{&z zz7k&k)pXtir&3g_Y;YvbBO~(G)6YsF>tmFe26a=)VD|Cpxp^_tqb1P%cy<;!&Kltm z){tgOR(Ltu5&l-p_^VMX%NX&7t$I8A%Gkm@9D4g#ie{0SOorBJwaYYV#4gHe2J9|{J+_R?}|&FGIiM(V^b#U>st5^>4iWzEp#loFbNz)|baGRo4S&>L^ecJfK#P%`vz0lWU5fu~Q?uq5e3 z&fxOA7$Z#6Q~c6Cd|uvL{vTmxiD5TYi76&^Ug5T$vD?DN;K?Ev?W@^NghB=4My^+H zNYaqm_r7&aGxM!;XTK(8Fxcgs84BkQ*LK_zl)r6d(wwNq=T1maPz{>p{HLX%T2;}g zuZ_4c5c3iR+hYMf2?W_kn za;RSVqQ4ct^a_Kg?}AGXtF90ZS`cFR5%-yxgRV;KfYZ)~h6jocAjnq=XY#`c5k_5c zDj>6?+bMwyQ+jyOnB2lh8l@L#c*@mm%o*@NHkv`*a)Sp~AEYD*?Y%F6IeqeReB9?s zLf7={9o%zGPrlZ=;Y`FvA14kNfLOq4Ad4+%a)Q^Z#ZlK!GptfG60&gWPVrUA*9uX! z&z!(<`e<3RAp7VHcvdXrrZ}r7>Y>EZukBOjjV1B)C)vy79bO~JK;aV=J|cJI@!fU4 zz`<(nX6fK2$fgyBrx}6uz%R@>5tdiBwy=T{ybULCBzD|N9AjP+Jpw%2hFuj^3gy~M z=B-XmMv$Wz_;O02an&7of8J|G8XC zk48vGv$w}P(^+qkZL@Hx-e0u{DzDB#PRQBz0Q+2q;*T85yX>c%^ShUiRlg8lS#hC3 z&#+w}WqA$_YM^4qT5o|#f2@r^Csei?FVSb~-f;1{E1R@}-(JV_(j~y_@p}WwLRTV; zFU4dBO31WEeQ*B~Qpm%LKj@CsZah5V>>Q8wsabQ{*}Oiz303<86DOvB@eX0w&_tzz zqzK=zFp==q()0^Vye)Evcf4V(1#SF`b?YpiK9vl3cX+9$yrwyZVBIP^U2|W>Y>M|7 zgj7vjI(b>=Nc5uyogv!SRp15?8+@G)8SE^QkdjRhocK zAeudvimsBZ9F^!jHskKTCuDbT1NR6@nWDTt?;8UZ6FG!QL(&La5RF*#``@!vx~OIpEbLtbj@cI8K5Jn{e-8Qo%0pVo*MX?+h@lnlDGp=p=b za9G1?Z_Fl-?ClLxV1Gnn!+;n(F&~ZDLUw7mx3_XiYvjH5x(}?3VqM3c;^c;1^#foc#V{|(UPtn_O}&Y@S~nNMq(?0 zJBe43X5CD88UpGV0EHcH!oz`XzWPNs+gf`9WPszf;?feT8qYcgby9<^NUPRw>q86A zYJ3PsdDxLHg0ItWu!zFVn|GW;HD!i_~TX#cU{Wm0dlkdBEQ+&-A{Dx0?Ih;xA z=V<4glb-Q5Sm1r^;8gh9!dZ%J68FiPVuBcZdn!sO&W5+_Ne}=6#Ff9zTd{FW!CK#S z^p|G2;j5kM4BnA+O^xx!iG8H;Qq9J=Y_b-JG8>%(8t%wcN4tnSpUE>u-_6_v==R5J zPp51*hk@`R2VU!XR`#-l;$` zy0EXuY)k{6Mg5NYWI2$Ov7Wz?tI51jT{S9RF_2nO;LkZQ0qt<`CfzgIffOq%kG3tp zkY1emXd(32G=0_g+fkY`RYazz-4d0yo~cYg z9p2fYZkYE2Y>K=JXyDV*E4(v^h{ytEEkNB~melN9`G6$tFl4jd24Dx=J_-nF`bsqa z;gUHHv|P&?ZMEhl82728(`Tiphg`G}|y zXGP+ggpUVcWaD@_2l^E0zQHIdtBb@huQpUvD(iB7tjZ7UOOwdL@vfuRwLcW_^*MLN zB1J%o=s+RrI#efRU!FF(qV{D%TWt4%1o#S~D(wQtsfKnYZ-_Yt7CZVN!Z?K?P*_I2 z54)IQoR~`({HPIK>n|Vs>#UJ|1MHe&iwaB`memYj*1gvRXW12VyH3*HwRuQJFXx}# zc>Ap=EB4l8)X8@Z3BgpElj)AS4vbc9KWk|gh8v|nJYbV0cRAY{!K+-U($q`-J!{jrFp-pn7}=VV+U`$#S-u~jh|%|d@%`JFIkELyB@ zC&*R0Zi+=nN<885#o5gE*?;_rs@<>(r(&dPoKhNDunHUT3E<#f-nf!d2yoM6nI>gO zaplFZ(1U=C@!(l*wMTRby%0ad_)1?YtJlrLk*R0)Y$S2A^gf<(jo!Iv?jv&dWoDMb zLtmmN?{{zHeft4ADMc_TkT02z=G85D5WBUrMS>tE8d$tp2QN$O!2c)usqg)n^@W182P)=g$5x?X>PMY^Mm}b=OaTO(%tJnc3hgkkiM*p`Q>lm^hqp z&2^7;&BPaBr#Qs=V20juamqfEP$n2;UF;d^aUQ>IT^Nf4KgaL6WA@3qLzQ`XJU^&?;m zNP+0GcPGtXb6Jx8d1ZIsFmFODleKI;wF&N&^N~_8GHlHisM9bz$UKgqXMdH<#_b4c zQDAJ#cNZ18cXLT5(@l@Hj0O`3p?Wt@KV&orBW`TYeXoWFt9%vrbLaFfj8 zlf6cUZcQUQA?lrx@flgqf@IHKNTldkh&&{VvhT!6)oPJCN?%^eJNs_$y@##7y|1da z_v{j!IQ`6mvRkUsdP6qY|Ho*#_sbd52usD4qZa?6LOYI;4e#OavQZo4K+&OXFT%_J zO~@(!L~fkR2pm3}Yf!%V5zu0j$|`;cA58>CBfvR1S#c14gc{vew!hIm{FHxve}0s# z&l9DEnH*DkLJRlrOAAs{<5rRWxA}3y(^8epK2Rh^VAWlovS4kpFB>|!McI_x_w#*_ zlC8XP|3vBXMMKg{OU*atgC}I5$g3!eR#i=~UV^y&NIKR4EI+R}w$j^n<+!S&ZSZAY zH&5{^+)q?iHg+4{5#66fFYEBAi8cJ45RB^iYcuzhsviW-#8-BOYtNc5sbv$}ZnUqh z_jd}9nW^)Jg`=EOg<0;6aUl}4R5Ty5!2oge@=|gz<0rqeRac_G1DtoSo{7F#_y|-P zQs$VvB8SLL0>52eW7(8zWxDMy`9_m;C$C!Jp~kt z036jY8|mGtHTj2<7rF{74}PL`?mq=zZwR`O67SD*;nv8ipv?W>@PRbMv z<;8P_|Gewy8w3D(sz1Jn)-0iX)fOOoE&b7E*o+%Mx_cL9Z%hg9?pXP?=>Ak98_D7x(v3# zgTgnhJH1aROSs}nPQkKDr)D{>+iCV@c(DGtX8A{{_4bd*icY}c+rm>`*rK=i){;?K zHBL)~KR&K@vPE%;@;Aq=GL*-7Mq*AWQI-%3M1Au|17n*s#Rvq8Y^XW#wY5z?v02Yh zB6?4`QeO-Fpc!7s;=~P2>ZT)uZrA>EI?KFo;|~|t<`zMB@W0Gz`2-V;r(nzkR0KA2 zQjUAL6`L7#?D1U|*8jyLV*Q6p10#q#0Y;vAYk(oiAFhgEh%C>;1#LZ?FqfO|v0qiV z<^*@N%F4*i*2iIX$?}Xo26AD8_Xd znPk9%v|o>}Z~8P?7%RSnfP@jw?x=DgLrFPUJE?-?iuU_}S$5hfkHlsJ8If%(iVBe9R`roTJf+#VvGPCfVSH)G|e%t05Y(hm$QIq5+Z}L9;dkA=n zCK#0U8N)suGs(Azn=0A*;g^tOO$(AiQTHOc*a(-iT0y2G4^*ONS%!aIZ$#!hg#({k znYFmOxO*NmoKCQ_-E)z4O%wQnb+JK_ssVEfemXw}c32zOap{r@tkO=waWrRH!}Hq% zrtDIP`>sMOOY86B$hzcAz{V+0b5@BAJmZ4aPt=(s9?uNH6SiTS&hvCB42?Dm7A-Cq zJz(pJ@MVNY+2LLqp-lUp8A>J6d6PeyY^wl}OC7Cc~nNu05vwC96%7>(wr>lC^j^?{+dy^r?0d(v{Ct8)>dh+FUA!IZsH0r@W06lyc=$? z;7seXk-TgLnyL70eRd9dK6^|%&qTMP0xK;Ymx4Djtg!o9R@TZS#SzUZ-xtk}DH+Q1 zeSKYj$MD#DC_TCpjLW5YY~QQdd7^p>45tGaCqQ|)?7=Luhc>w_rt=gF@vRzdYB4iu zIW+yraK&+&&TKWlnVVI_8Cl7iv2&v&&bF{gzc%KbNB(<&(>#~zk(F%Zmm+kt66{xy zex`LjUG?II33w-B5u1zPGs|*BCqrvQ3X{~;6T%8epxWoyv9$^2ZF0HF#>&R#6>m0- zg~?NEec+NV<*s#+*`%fbDk7NIA{1q2|NRu`}?w~^{Mf#P)ohs)hw;%+n$QTtWOZ(DI zT&`XYJoPG66M^qykmw{oLCiY;U(Jl&h(daL8`RG^Tr=?N?4y8za3|Eow>ekxglz$z zmwMEMcZ5R+3FLhvx63XBUbKMl_B&uZOINY>JPq3&yely60_V*KD293(*MC+1TXo|NRjG)f?w zoivuppF)qWLv`*M_~z~1%OIyeq0Th+pL6P`3W?7yPI;`uVxs2Tj-&+Sv6GAt#Z7QZ z|8TJx-8QusY2TbZ<~$x&95e0F*GshZ_#LhxQJfXssiPnuAgZVMEPDkxmhgAV05P}i zAYtyo5ja=zV6AZK$Uj2FcPyEf3~NUDxINX7uM?Kp7qK(dGqk30M#KN_?bX7JCwZbH zV0%~Zgg3)B|Al4g)cR$tOn&LRgF}m0($skZJB8DTZC|y%WGar+PAJOD*{AN}2<36J zROfGwwBL?fp^mFn5332Cc_GzP!oD9-Dmn&hf0-kNTy7^ngB>s5=D}3ub#9S7m#HFo zXA9G_clPam{MI8t8RXDUny+^nfXI-{AvuILHfX_TlUxfE@&X2p+H`Q(V|rW@c8B^L zmU0%}50Y+=Jr=x@2ITG%&?cT1w;fBgk-V)qYI)Tls$Zo`yiEl^d+c)OM6%E_9hAXf zf+D18>g{jS_)9x4fEtw4($^LkF!TGihbzeziTEE^N2`iQ;?hwUE|NsR)J))CQgvb- zUSmZ@upfaW8=QR;_i1h z+pHtdry+7Se2e8?X?KcaX2C9xQ-%*muD&Z7SwL(d`>8`aOvS*lj>w`!nX83`|)u{AelwSh`$=UT?)W9+YC8|?fB4_vFnA*aJC4KCTL5PqRzc6u0H88FHz00Ve_tG z!PG^A-)-Y=0ijV9^%wh;Y7?@zPVDwf<)dlUM-cSl?^uAsvHS8ojF?Ga`=?pNdt_3|BG8dZFvxDq?+<%x|>o<)`D59L&8?zm5Vi&S2d( z$#3O<319#8|6h^oUvu{!35H;W%NHyCI@kH!6yAiQ$aNmU<=nky(ksJGck>SB3%0TF zD`VK!%c2X4I}Oju`dk@7gT?%;uHZoL`#yq~JgrG9Re=`do*l&BjXN{zVB~mnuW3I; zLC0zMlI-y+{EE{teegdZ1KmLocmK?@mJrgk>$CKWK2FM3>uI|D8=6utd?j%{^px6ZvhH1p#94aqBbylQv6LRu>G+ z+!A4@r&A&9R*%IV#b#_7NV6HQFGN+~Y@DJ9BU-wG#!~c78{!5d=Y<~FJ zyJ4pRDT|l3BfmBC;Cj(ZNI)Pc7L}`x*Nm#&7MuZGh_bL17|pxI1cg? z4v^z>U?y-Ay}j>Cstmh@30Led3lvdng{L~nz$>aPg79s&%7xzvRF+vOov7J%!wJsM z-1TojAgc9YILm;M)fTq*g03^A#cJP^^Lkfk!teGRN1lt`HaJIA@Mozcl4-M*p@@AE z1{i1dVcez%j3oEJ-l8KL8NED{_bg%eq3%z}Hqv(lfULRX!B=e5)Pl3{LlAZ8@+0wSyAC$SOAP~&ekWh5wyn816FTqWDAt|DLISMvA6g? zm+Mag5!d;(PF_Yli@FY#-4Bry9t5-W=5n{ls*T?jfA4T4=SvfN`;>lsEDLZpaZ#3t zLoh_NZ~x&c;bj49wVOJ-^WGqrpdwhVXlSVIP#EZY+B6RyZ0Gt|9chhNkGq(A%Q1e6 z2ED_>m&LSF48C8#kRF>nW)+O2HcI)Jby(~%%ZOud;= zn+VFi^fxL!dfkDjJ(j9``X|*A2;v`55bt;h5H&^0*pFnYs99RuHIUIA6~=Jrs!?E$AR;0**T z-EI!6g)^zN4$7C06$y;z3WaAUAIID#%daz_&Op+b_R!r~6#)e1`lF92^&c$C%YF*D zzRNK|&#G?l0>BnA!W+B?E9_UD79SL&ApSB{_h_5Sg@_n?Xbh_!BKQj*+-;{L40>{f zY0?jmYh-e~%5`25R9tO^MFB)jP>ZGg;Yv?U1$~!Qrr)yNu{pzha3`5fKVJW<+tX)P zcRcVdDg5z^d!UR*?6jyQ^O0u+w>|y#)oMv6iN;2(E7lzQJ^$Gcu)y{Wu4jz zXg+^{>{-OI?=j{%&%iWSp`V!>W@0{2bt~bAW7F2S%FlC8d=GI7_FM_2b-U zqA6ydJ2B^KNcwp~U+$W9>uSF0Nl8Gem<5V6bre^jbWqdbX@lMHYL52Dy?^by78k>M zJikO~UUo&j)JW6+$5#87)7N*he3n?0RJ}Qb>KYz_pKm)JJ^rEwzYZm`$E?SK8=O3W zumYK@X{P(@<+RIdcR8jwhzvlBRnYYF&16!k)HY^{#5r2Ns(rA2O=fhy~zkpVyfF;2HP$~SB2 z%1aiEbh`PDfHP=O37U$%Dpn;Y7!L-&?{lc!3=%_e#Q6yGs>Y8thxgARLk>*GF zm`N84CcEcWeAm)A7~eeSx4)B{SzzR6csbcV)X$JFQPWY7=0@3#2oX( zY~NcXY5SO|jUa+oPDm^eh$9;dufG-#BUl)wVu8z>W~CQ>;%MntYReleY9;FnC6ok$ zasp?*?OusDP=&-*Ce*ggOVD~m#b#S zZHFjhyJlI4+P{kL9M@dpCuBdsfQkf@^6S_6^7pB|zCKPobhPat`4p|g^~_r+oy6X+ zP4dlDfsaydEOiR9rZo&*E)LY#BLQ{@&Kam%^t|?%em?HK1*OOeE|@=^ECY1~c3M)PPm%B} z{AxXzZe!slfVvT~2yhavQK0Q^nPzE#nHg}A$oaAIV*b2Oj(J&ey83LA#n;#RK#Ap# zSa*k*f%543rK;cOwtK-FRy2iFQl^}I@5%E#KVi#8)XhY@9fDOP(^WfRO796L_O9d=YhvG%jj`YXW>jR^$RhqarrmxmAVg@o8QTVqd*dKt? ze&97eh?l6WkFr$s5s4(iBKDV&agz%>KK-S=EBk+^8^wt_Q$59X5UdX#0U^DdMpfM- zp$*zd>C{#hb%pe(!99yhAm#`Kp)K&~lw(qf@^oKr-OY~}s6=tD0f$^fvrvE$r}h~&Qv+fMVZ{jY3Y*Og^-MZ-{f1ux{pqIG7MO7ToLeHzT z<>nEh3}zDPNdFc!#_IY*z(>GfImB|xyD&kQf86HjK_Iw0WwBBPT`Sb+T9(9bh%~AY zbG4o}W?1hJOGRa$)Yng?8dv=)?3|`0U3%3oh7hfqqx}q!)pMC@Gf9YO;bwfx@?Dn* zq6}%ZelFd2-R!uj<>OjzxjO=I{AvANSIO5t+@cqyGO`wiJqgLqp-rew%u`iZ`wtg* z4Sp>;cZL1o`uF1Y*IO*L(y}%4sd_?Vd0$}X>f7%7m(lKEw}44R|1H@e;^n(l;p*l6 zhGgorySps1bLW^+bZX+ox6Oq?%x=?i$k=3W$Tx|n7B}Ao>nz7aREdDt-B~*%EfZtv1UO)N&?b@P77V&>R0{!{lZX*Bxzsdd>SM9~Wm3x0V12o%| z(`$duNA5KDTh`ZOw|On;E-lM3%o_Lh8~3dp*DqfSFMsqaXtqoV3;kv#r)SlD2$M-_ zoz!2}*`;r$`3M=aKaYAbzZx;RZot!%s}E$b1Ec$({yVYc>S{KnW821jgm}RF8ABP0|3_h61T^h7qurc)3yB>34FtsrD zSzgXPH+MNii=6NI2&3YK=xg!oOvC5%&DbIlj2YVp=PXLOIY%e8!Y#TTX% zZyFMFb@5nrXE-ZmRbqJiwu#{VE#zDz@+q_JJz1a6Vo-_m#qXG*Mx;cPGLP<2&|lrr z9*^~z_*^{B5S(=Dd?q zJrI@>ImImb#*kxR%=4T^K;Bxb3c%lQtef8x(_}JVW0#brS^8De)us^^syb!{8K(_Y zgxa`zuKqq8QWq0AOrJPYnc`KM9Qktvrbghc7|-r~Z%xVG4=HjG!x z$#4-x+);YBjmY6HLrwgKcWC21(LlU6?#assS5($r;_-&Ncb89Kl=HnsPw2p^bvN65 zI3+DPfEiE`57*)af7ckmXmRMtg;uxHRylDLzlSuvKohFwK}K)0FCsjlOTYo1lWwfa zziV%(w!Oi{%b19>`f-Tn-mEuYFLW`PoKMc?qtQ6zSz}B`}75gSxUJua%u_VbG5AYdji|7?5_Y?M7+1o`Zznc?)1c zL%Nc>>cR#+73>L4rhooq7~I8-xGudpc#StMV^zlHU*VVH`L1jqi@XBLrm<%Cjw2JH zhO7p&a;%#xVuc0s>>VgIYbXc(R0`lIwkY?B_S0r)Dg7Uvg|00s4|jUiGdBWr0mX)F zLa+y!B;Uv@ueZgJze=D!4RO6=CJJ5A-OKvMyPW1--dUfWFbsKN$7D+hMf`dT&2&{V z_D6;Me^&9|y~)4G%IRsjuNI;N@l#u9=)ykD635v zrm}eV&%nz$?o#gvjJo2eq9fRx`By%dtgWN+kVXvTWE`uzXZgD7;{iN)yPWd$BVs~T zr>t`CIm_3%OX&8JKA?Dy`T#QIG4xGr^h#6)z&%AAbVrW=>1gi-6HWe}r28?@jTpeT zUD`(2lEy?5Atv9LK=emxjy?yNU;av76oi=g0zTc1dD9Y+M`|$>4ou|zZHNqevI3sD z&BMf<4{x1a94u&?DR_k1Scx6^q%xH7He{b6xcmM>4zutB5*Q=vlXca$oB)-RO;&WY z%sV!Qo+dj%$cc@WEztEmX&Kb;dS^w`v_iV?YR13=p) zu=3noUGG1oFFh89hhh_7KszhYMk;4CeFQO=|5H4US>v0$GKO z=aSgeb?&P7FHRS#L#Z77+~bX_pnv(f&Wv)c?%u6ee65ALZmBII34tXu$pEtw*xvN^ zwqZx1zn&1La|7zPg^?c@E)l}dN}SGKm$#dI2Xzuwy=OL{`tQQX`BhRtMuJBR2VKo> zwDRoJky+g1cjPNA=7Rjug6`fnR@?-fz9k-UhQxa((##GJc~=*om+2^3S$zIj+&%Z0 z1_My1#X{1?p`pJ=dhW&vrKn>X#XWNJ`J@r)8&(ek55*QKUr*5gHvsanR|iQAzR%X0 zGqk*{A;VdAa8{y_nVl(srg`JiE|SQy`QG$5 z2b>L$tFE_Z8<7%q@c_1}bpHoH7s{(B++B^ptbvLmZr^sX$=+IcaLeCD8;^(qFnLyD zT}Od^K92bizpme?YUTqjb;<9Rr|QE6pI+jMCT1$(t?^`>326-32)B$ypED>BCrnji z`khn0tT9`R5i9zSV-+Rts18tTk?D%#h(Y+xc1HVo17ufW>!EaelcJ|WY)NZ9TX8@0 z>i9`8E{^q)AC&aQbHKJOsouGM;ntZc<26XAt*EIGPU zg}MZ;ZH7~}(5#9u0xdPly@vCmOpo-u^fwd(W{z#4k#rtHS{w7XjZAh}d7j>zP6Gaf zqpu2Si;D;KMUCD`(kdWt^}OC512ha6k+wfv>-yCLdaggRqc)Ron~D4D4H!iU-Tr^1 zy?Hd->-#p^@9v=8yZCm{$&lUBDy7<*T0^qCQAJ5jRg|=)W{G*0>|HG_B}EOTs0J~s zDM65`lA`7kL5UnU%3-_9z9#K{U=s^JREQ+sB>Y=$v zH_uf22yqmqVeS=KXN~nkaQeGkT zxYDmQ|C8@lMe={vJ3MsN0Wb}#PS zQ31{0FkpV^ zFjy$64EUZ3$ua>(%=#Al>n{JN+^3h%&&i3gQj~sGoTZXK?fBt+0uO%rKYw+1*uEX~ zRQ1dynVDLitn1U*Yg*tKH8TSo|J;F|cTu*uHvet!KZym4%bi&D4bQfg#@f$~nXz4h zV<+gSe-Y^#b+>tBij>yM6TF5w%kv zkG|uqGsWC)v*xwmoj3nXkMW-553B+?;ZU+Sh97HpNU#owl`B?UZv))OKMQ07nd;?X zc}||i;?t(+F88e_KZ79?Eeb@&5}IHA)${Tw1HAOGxVShzU+;ew!j4GC|nvlJ0Vu};ky3GeiP^+5nM8i!D?PP6{j32nCDQ1}BcS8|;iG@iFgY z6$OoPm1XGjP?y{4NLynwQ@uMW;<>zeR_tPIeg4AqE%=qy>c#NJ0;d@1%}eNHg##Pn z+?64bd)8H^z7DY5rR3~KsQe7|_DQAQ#?V7H$Td89HmXSIJx;s{OChX34ZjMC9bx*# zcTLs$MTTF}2zwH2|1fHB{(a(J=_XIjKr56zd6dnb{GsO#p3zXVwy-?G8+D3SNbmKSZOm|ZnzDa3%zR|GCNeT zN)ulf#vXQ&-cAZ)KjoAFbpF&P07YrP>+kgDf#$*?=SHpqx$4_8q!slIr?3-uOoHpj zC{M;(tH)#nJs7j=;zF0x?kZX;EWh43w16WdC-3A&kXBbb%elOGll_V>qgOH>---GL zMsT{na_+{j<4i9Wyxi1N_S{+lu9Q*L%XU2gZ?^0pM{CRtbnR7rSigsZE*v_oSU<;P z{5^T5e|Ah3_^+7L`BTrW1}PD1sxe4KiDm;p8{6Z0-I%F*48q|;Y@1bs7O?8Grm_$h zQ0tzk`CdEEPZg=g`Rno#`Jd-fK0zOb54iTg1GGiro|Ei7W8p;ubXHH z>LBEriT1wWhUwWY9RWu5*s`_J;`4)GdxfH?-9+JJk1eGy)~)qnpFF**3J7Z5dcR!` z3-xug4Yax6VexM2#8TZ!6=$eg+OS8A-J`*ItXT1=jQvir_M?KWo)PGtSG(jP=co7g z6({)|DhwoT{rW+LT_|`mx#!B9AHPx&LAM}yyNtp}HT85r^bxfZawfh(DuNCBM7_PwRBr^@m?n3Gg2y}k)>JBfugtc4V>X>}7Irj^M|4GlQbq2$@O2-& zEQhZ2xl4Rg)hFW5#6%aXkW3G3P01fCp1rsegR=EbzVF9QY!TPY@1YAJ*lKVx({q9R z$J`dhGiEF-lLTIP8pSE${oaV88?f~ z%i{(}T0vCpFT+#YCy$%Q==~D&r;5{GM^2VjdH-ozy7r)PlI1~FtjA5l^S2K-e$N3t zLamM#N%=0FHu9s6HeM6d*Iu7E!07K3?k}%zR#or0)HSnrWaZlKJG&-iXTmZ2+SW-u zxeqr?7HbkgC$P+DQyngzS7)-T!Vg^kt*rOlNP_*Zf0^d}q2M0kiQgt)d*leu{pKu5 zW-esWhYNO*Qh$j$wh`{0f@sm9PC~gXzV6H;@B)PjQ=n0As?W7vi++1sN6t_6o>*A| z+JapA^=D}=W3710c-0_BMTkDD&k}fB20ZG!kiJlPWbW_#Do%T;u8R9c(xMSenZc3z z4PBL^+bdAu52aj67I6g?O_&p8CbUu&8&@5jHGeh;dz z6v#7P-tzIM1G*jtGinWK_akb9*2w^`oFIDq**W#UDKN?0A+M8vEMzEY%7ea2MwI#_ z^2t+IV_Q=AbDT-VO~{bom;j=HCIQ|&q(8MFYI=%pocy6R$yMuST=gbH?r3yHae44V z)w>*8;BdeCGX)*_g#1r^?jI|v`$f5;V(>k;t{CV7nnP9M{EVU0y(EN1nzY`sozsDS z+SipUK0SX>p~x=O%Mi2tuyVfDCB^h5fMo)6D|kVih-h7g$_}?(4r(hK7oa>@m!m5% zfzfdnC-Sbhtc7`uO!Hz~$BHujx;@YV_Dr?>?}JaP?yzUfqgI~@s*cci1xAsB6l0yh zN0le^4RW+H?xXG@u>n7$Z^mfv6sty^AZ_3c9=SSA8mRM4r;Qoh}KspMm~h?JIC zYSVYJXMNk(czSyEWOx|obtCkAu4!a6PwGtS2xmC9r^nfmZ)J6fp>n{5Uo`BMEGn4HVXB&-oc!Ubl8t|m}n2;N5YZS z-A4%e+H?OFWwWvJH-XMdTfPYS2ZHs+QJqN6b`jNw<=xpKu~Y~qHw+E)JLmz|mTm-E z5>__t8qd60Y}MKv?Xl3HS}bj~BIS=?fTIZdA%u7O`xARGcZwkyT5+p6{LPQ$9M0+N zhf@_y+{}Jp^tOViso(VC(L{P7`{p2dcc=qwX%BAk)vr^zL6{27x+l(FEQQXB;;he* zz9md$&H9_JQ`0B+z6U-(m%UcB1^S!`lFM1(2!g8@cOPWdZrJQsi`r7uNU(mCLN&c9 zH!tV}CEu0KZ zb}Vr$j+x?COZ2@+{QH54 ztlt`y94^@w9hD0#cFf(Vx~TxZb6VjWLx++%h|s;!Pj@lVUGcI+V0fT5#eWx5MnBrR z0dzt5*B|WgkT4H+K^0EH=&_lD_|48O%bHeHQ^9#9lKWh@g=J%5oW7+sUR7mw$1Jrp zt-K|x?^jbOW;}lk`lEGBF4w=+IRt!bw9@Nb{Pptq1gPA97XL69>)}RE4$zw^UH##9 zmhw3#oP43l|LohpzG~Y{{BVg!@*6}?PUzA0=WHPRzPtZUL!CQ)td+jOY@wihrCil1 zQVW8_oTJ|$9hY*is~a@6z+`?weJ}&f%q_t^b-9i8=+&nweLxN!V)~%-uUSDQk2r=N9aZKGbjaiYkHY zb-Jy@;L8n4rnI-g=t(Tva#f6%E#4n%&%Oi8FgJeujJY zqK}U`=RdF)za)vL!)@>PM`;%@m;1H`8^7fOg?X}0d;hu7dcIcs&{rOw@UecjIjvcz+0Mnp_^v}U8Pt+EULitr2#m<%E; z)U53-sw05c8g>WuWc#JD>*)9zzHPWvQ&xiUOPqzW=EIm-wwE)a>j zwZc#e$tObE04#EO!HPOflnu;&=o3VxG@YM*ukkikKCNV8YZolx+Zo^E9@w1U#z@pd zHDkoGMt64q`|~HcPsZNnqH^-WdqWnt=GsNZa&o9#nA4%ZzV9RRymI1>#+cgs{^_Io zYc7Zo8o$_RqWwa@V2l&qqGu+833uRur#7w5op@pu~Hwe~cN;q5&Fee`*L+Cz;@&t~u5%FK05OfikB=&6U2h*4_ zWo^|O<3o)Gl=WsCRQ=AI8C)zo{BU) zEFPi44SxD>yey%^xq803zXpDD+0_u zh$|rnZB#th?j3B=xumiWUSCsIm@DeD z?Xf?-=?&Y(z8szWo3Lcvd_m-{==1P9a;y)XnWG(Ra%Isf@pnO+-%wXGegqz38TGGC z>69`Z3N(a9DQjXsL05D|b=ax>p+jyQ1{|c5$7_6-i#TseZocPNw}%HkWbS3=$3@+K zQ<%_`Li)LfdIL-jr$vWtc0Rbp1*AD=X#VPzl4R|`2BxY5A0y*PRi@mSDL9Vcxf!nY zei7P1qY1q+^?Vc{^puU0-nq+A*)g27ZNVQ3)YIJ$%l^1JBS?5mPY;5dJ)yi`>&M6U z_?b7We4Z3K&>q_u#3Rlb*byUV)42u+#w6a=Pek*PvXS1mdJ?t$a@E*IwspaN=+s>$ zewYks_Fx~^ua3_c0oM41ppJ>xJcvRAODxqdf7qF@2WT8;I1Uey;yXO?Szey_gA#r* zerIT>09bSFrWcr*QsIy2H7K@}T8-n$X#k7q-cJ*q?1mLy8{(w|KQ8gvhIwJ^H!E)U zzXV`^m2Mz!tYnB;oS_Z!jS^PqZoz0mJr68-ZnO~Uhth0KhV@L>+(SjQP-1pttp+CE zw;$Yz5~53+2V_x zO7A{iFnZ~B)t%6}wwtSpT7#+3SZ;W{(&scvOy;e8hm8>6lbpl=14r!Ip>8qUmg%P) z(Fi|Lg<~$RCNfrd8yws7&5&VO04iKHKr3Pz<_drHRAzsmD8*!<0{gCy({dcj4SQj$ ztjl^ki7O*`Ln=z5T zY^Ah_&=r%kVDLtGI$pjsR?+x&mUCoag%1Pb?E}c^`l1M9J6$m}qT5zFY<6Qq3>E_| zi1$!B01)L?9U5UsRZlt^;y;HgOfacc*143u*y3i*El>X7b?5gvYH(S?_1$buXk20U zZ48h4>|~uud=_Vc%(#fX#T>~c<+|BFd^P;XA3n?TW#q-%M%D#cPU%cRQ>>Cri2(Fw zyQF7&{-5xir z9juuVVGKaFJ#Yz&5k#3EQ6Yx+FK-uXBS zOj*7N2(d2Zoz2D^#3_8NJiuFs`4bbn zacg^{uk4He`eG7&Hs*LJe}lG&5U99bZe9>R)+t}nFFXf8UPSKlmw)!LVl}ovKhi6F z^lMIR^@aE!U7BR5FUCfU zioYX{|`caL%gJMv9_z2Gh@V;Kzf|%`- zO$!ZA)ikzpy7{3K3su!^UjOPXu~8s?$i^xvV=r<{RyUAQg=x`ThIdXJW18nz&on2V z(h5~RR>+e8t8#8tS(UNqW)mH`D4Ts~Xz8H1UG>*)2%fbB(#|J+; zb~ejI>0tCu-fzIG_5SC(ywm#ITipZtc3D}~D42*S3>Kr-juNjR^*p2a;C{obMrl_E z`@_EB_ulWfj_bBFdRO^HRDy)z1Xb8u1H)}M#TPksU1}QQLQ##Y$CRRP$Z1SB>V^Gl zg^ZIw+Zz?*BSOx#az=ABT-PRVg{^m^fyF|8g7ZYIVFm+UyWUTjaQ+iM@HOm`ZqTUz z-SW%sr<12M>bhXStfIpgOp&=^#$js*jYYxtd;R zdPKHK{9tSP{h&|AzGLPix2UmgOBITJ20e`%HezPo^zaNqqV^aBsG#Yu3S?Kvlfxaz zk@ce!Gmd(Oz?`D4L2!Y=tQ}7LUBFSe=~lL7aTV=58bSfs zYN&`mhKx}*>33|EMiY)cm#ES^H_b?!aoNX7YaOxRqo#mCz4x#rgO%5GdQw0Niis63 zbCV?;=>gH5jTJaRmw=Jis6d;FRQu61S*!2k_qI&D#nG{f@YtNcka*s#5Ik=@{%X#J zl%t+z7vFvMs{D#YSXB(Wbkr$lq5E=svU%vm?ZJka#UFi|wIZtYY$QN4r4PNzfy{^x zh$Yq%3H1v&`kr<^uaD3&D!U!$?_Lqq)HXLI!|R`WPTKgcW8x95;ZTQ%xZZtSJ|)l( zp$FOmRgIYjZOmSgWQ}osae0d4LeFNUYGidC4T^7ZySVaa`j-Qwh`yg`zT*x-8jS|n zo(ExsWcGEW2%56G%bOBQ7@G<~486w`Lr)w(3iFwu_?ep$9)^e!d!Ba8E${Upz8YPu zKQmG1de-a5&qDH^HEc#-2SihXufI01@ z$lr4YU1bRuwoAHvPY-v{#DKo^DiEeWEmLV1!4@0xW74)EXkP@JI1yn;#BU00pUwx> z(K%oQVhQkZcwO(Pb`->fTof_#>wJ1!U$i@wJ$wJpzTlz!EmJr*0X2PT2BDigd)p(+ zwxbYy;4YOu1n4OY(nY4^aTlfnZA0MeAHZ;a1aqAGgHP3`vVF%{0L{`LD*Q|Qi(43T zbmE_VKRkosURYWiepDY_6&QW`w}X#(F&7WGq^ikcf)~QCnj?rm7PuFYJ@Mu~H_OV( z0yhbFTqC6#X4-0iI zy09u{$M(+gE4}U^TjJ%W;F$sEmZfTQB4r~SR@C}jg_-)#zPY!z6+ig`%g}f5YknM! z-~_Lw_i(0vOmw8d8F|Q3>q^c)`>r+~-+SrO%teR0UlSls>oF9X*X3*RpCkOtdlm0> zyGaV4)|K1N3eel$+gif_|3J0Y)}UYl6*0_3EnG=rB=}4q^tlU}-qhvc$*NsWXzI+` zj+`@mF1!Vx)9KtyRW$x*A2QU<`M0^QQ|l{7;Sxvc*YNQjQv^+E2Pw`M#&l5x`#DPLw7n7LahTl9}h%{*cMs-ejI{+QAF`3F&Wq_f$oOyzK$MS2zPLf z0*HaMFD#y3xz%^xdW+r_93JEo+WFJ6x&0P%0KcK8;H;e_=rz#TTB*>SI6BCM*I{@D zLvF#@WK2bAipEaE;6k!?OSJZ-uba%{6VtqTkn}g6c1eSH;4Y8?0JAG5<=2Klqu?j( z0*BKAQ)6)foA1h&?i=_?5n;9k_0j469?{sKnCywh-CVSvU*6oiHDTEJ#y$T>^^Eqh z`05mbJk+r@j2dPp9_>%D!B>@*5g1)W6aUqaS9jP8RM81OD0fC!}LkCm7dmXE_Z!77eT9!zx;` zVuUD4lL{U;KNS(>-W}Gxkj2uJ#TvGAs&(QqpcWrZ=Zfpvo|$+~YuU+s^sipO$BsUJ zxoklg_dsNX@KDLE&@6>wQ5JJI(jWhjF&-^b?&Jh48|0x2Pt^Yznp9cZ{%pel)@x3! zYWYObPg)Gs2|}Zuc&|wC4J?WIHHnYDJ&ZZIl)F*a+?@2!zW27XNgoRvS5xQo|q99DC z^pmq4#m4IqncWkFS}H+bed8v;`#anx{YG=SlmbvA$$(Cq-fMizZ{B`wH52;L{=zqf zQ-a)jOfS}hQ=$=09)|-xzv=s4>xEBUOlWI97SW&h6>3H=!X{>_!~%<=2I!46SY#zu z$m!y>VvtGx-g!^lBij|)|sdqN@@~D-KNBfM> zxt1Q^sg6Pubva0v?#$2*@Fu9*lV!DK)|sX0UEFN~$y$KaGO3RyHT|KaV~`MeaiR)k z4g+hYwMg`SFlc##WEi|w3g4UwHeDI4f$;`WC=zB1%hrmKzbs3~Kg=7G683Np5HR|d zjq4m8GG&+I8}4~s6l&^VZ+e5g`{-J1KVUA=ecO~?R4JMa3^W)f@rB|(3Brdj5OWCJ z!#L<@8}?k29T~##9i=lz8GTdE&eJ=lybs4QSkz_=NMaKO{g{HM58CvcqL;`g6Bc?| zY6GUa`O~BRRa+uf{{ze0Y2RWiDPR2@Xd?8)xTTm5(2jrK<^!VBP#8{`8<(f}Tm}Yk z1VZ+$8c5T}oWf$?e_S;cO3h4|HFY%+by3MhPRDk|(zCGIn*nfQlRoz-()pXBKI# zZ*Cbl*XOCChL7w**2WL%=~E2TIdN{j6}izh$34>@4FVg8h>^8~N*x8yuu<03uQT5U zSm&)jBxp4G1lZVlsFZQ%vW@ku+r*wv<8N};h8IEmIbLj3o21ss zV6xqi5rh?aA?4On5rUpnVgz?WlfR5Z4>?dA#?yPD~0o8i) z0QJ57Zkdb~Gl6^k^654x5X!Z6uLz7#lTwhLmq{OuY^Re1#74~?B@~4-ZGdIkcdvs*n>=73^4_2A~0k(M&3QaqbrT#+ZrIR z{h@T~hP^{4x}TYj*D;j0vPtUX7A&S)gS6OVG(2EwIuAfQ!^-ut)ljZ%W>|gO&Y>Nd zs)DUg(9lWoC{diSf`=~+m@WDDx>UGNwpVXK_O}M0x@q-Ao{mg7Zo}_RFwd%Ya`&tn z(y1N+SC#K+|2)y6_v6Klf(A&E6#-J4cunkdI>99{Df$Q?RCjO5+1{Ka0IqG4btg5e-_$(TDSAK`f!wVY}ro(_G@ zvPZ!p(9K74;thgo^V4np8aom?*Q_dpTU<;mF0B;*=5oW-firBOW&=p#4cAQh4p?$e z__pwsXF~hsoB;1C))5{*iuAr&BA_;9O9vr!I?EK80hgnBdiNo&q0^nx_NV&#>}*K4 zK~w#gocGf)n|->%UjSxqNoi)3Hwn!}&F1$!nT-9`n!@U!UWgOva{zS~VEe5HAySbp|x6>B81|;7DkX7w(;+ zD;3fXJGx_RSg@J$3V(4S_konKSRFOGney{ zduna-aqa58<4`VbRV?v8Yw&WbyLFtXS+CqD8JAc9KrbHM44HiKX+=)wTt&@%L9knx zRg_-Yy8Z;*Ap%6MaRpD)KQx>H+co|19H&NRKxUlW#+d--}s z_PO4T6iQAD)>Fi=Qmv)unEN~|-d-sfR<4;^!Ap5P^zd%>IeX!)O*1BOJljghmLhU2 zrkttmF6gyIw08tyj(5V8!~;uV?)xLNNld+7;UQb_dpYjr0jJWic%OO|9EOsadoHYc zv$FRmQ?eowfX*(aB*ISCea*is^vWM|f(2{$s@VoLME$2X0!uh)n4_7vRdWxn@I&y} zqm~fMUtMYxljs{8!$MStFpB?IlV$N=-OMUteKbnHF<5`_%GLuWnof;ve}vFOi)-3PCYT;;Be9O5LT zo?>xd7<8$HBPIYU>ITbdFs_>WK%zo5?9$|#sA5V>U-$8_z5ko)fA+0c`ne=q*9&ZK z;pXEL{YvPa{fT8itUYy=z=-*=WA>;FUlb^gGdeRGKz*|ws;v6R?DEAEjS&UVpQP_c zrLVTO4{ZBAHA#3cHjD*m&!m5kS}Is7|3;7zAz0QmUArX;A0CQ+RJ~F;VQ7>yO(00u z>Bzlb^}TX=?X#vR`RZJPOhZNe2|F9>9{c&k3R7Vq)MvK+y}=(sd{B;9(+DeCltfN1 z4}MzY=w@Y3Q=EgrO(=AC$p6UZR=_L_2`$m4K5*(7^&xWLD-)ge-bZ>i_w>SnyhV*^ zKT(ZiLc#v@DHzqMSI+-XRD!ONBfX-usywk`_;m89(cak{;JR#P>L-^lZyL91X-jXB zLFhg#-0*G6+THxo*d#UpqBj6D3gD1054^o4e!FK|8|51idg!+R`f6BBsJr5fJS~qB z`x>vmUt&V=`Ja8qD?2Qt1~I+#-zRq`9$v}?oeZ>qEe`F7h50{T2+U*E*}eDOfY416 z9T~a9Nt-u25Eita0|C@6QZjFN3bM|BZqXUhHX8aa7~ zzI8D9$?5ig=Xx>+7N@$8rYPzgB_~J$NYrm7+heg~P%6n~Wmr#O_^GqwRBz&!p30|1 z4&PN|J1NTPqB~g3l6hdD8`g;_>s94 zQJ$Oc1cjPsjeCG3EP+=`*8!L%T zyJa3~lD%@J1zv%ldkAE?p?Dlh~guUV7jjc&(QmFt=3FW6fwSmYdms|8dE4JWxo6 zi!d{1r~E(nx4{_P%-Y+#NI9{r5UHo9kHHF{-1a)nV8_$`pNa9X6JIvQ3s}uy3E;c< zum9|OvCT5~UlkU$s|_BgP|Jp}%Wytp?%NSpu8G>(4cK_`yZI{9)`ltKLV@r2c?50S zzFA-@46dl>JR5fSS5f2t1d04-`2UZF$Jh;&&Xl>&w8FQ)Dxz#R>o^d1mzr7=#_E;=eO21L&P;Us~VA z>z6K}>JBfXc;b}CIzzK&uGB(Do4kd8o`^;n4SQNUsd^Zd_)KSs^dqulX73(YQ+xm= zS3-&0fRn%R7Pn%@&GGDrP(j=+t8sc}GhBnZ$rE(%X~Y8`@YTEgV-U3Qju1sU=fwk6 zCeW@vq3V_)>tNFUl&4$rz*$cb0TFX`7%aWo-dMx#4o8UV#DKJcOkCprYl~58z2i+aLz9C{PDFZ@@_$$*3j#@Pcd)+FNoV} z6=f2qz|FKTYsGbq5Bmp`H`E38W>9-v^o`pMxMZ-cwD9UDqD1l_yk_1pr&UUyd1t(^ zte0s%C@ELhMNfRMv`Z?Swq+b_UzADNK{Y?LkRZE6Ov!8MDSycs21^VBY=n*xNXR7$ z>ng|BAGb`3A0gjqKpoQ-8=ezui3{i}4Q}n~v$ep!hf3>aG+tYJGb*+tx%>+~pmA%K z`!jOwk)+4Da=(lxf>*wr4AVVhSfjnAissx!?>DH|Bb^qnE)pv7P-lmNd13VwVM2mccDs ziRU@e0#nvmk0lG4G-DCjS4;)Y$5Kk2GQR>abBSGA1%NuGBfzo|`{P3n{runi4XqKZAGenkq0Wgll%x#O)96HCODOiW*MYIi8f3cq*NE8AUlX=x% zXhk8jW*GqYfY*FDyZ+*&yji1nRpv~a(O0qcQfLY8ARw0pavxVb#$gb0LZ*yX2BTD24JP#sxS!?tUcWIWxejH)?^Qpb7=80K zH7^Zv=$N6McSw1n+C;G3j9T>I$cph6_4n9w!&i&YK)$MP)29&yR-a^&nS1f;nRAKC z6K*YAGsebbA;Nb)CJF$4W=_;&2YS#RjH%?}rrPYOjc(@vBVa|^)@`AvYj&X~tu9M3 zt($qP;`*nOg8fFg_0KAfsg+scUuHc@^DU2ian3F}BAlG_;(@;75!qTv48|9H$(Lf2 zYi2Fw)3F`2p^EH<`j`IU%^Mf)KF*lk)biSzMWOGYNma*Y(*f#&+0Qj<>R%N7s7F_$ z)m@r&$2YK*l~m`Q{gMYFS`0gm-XEJ=4O`F=@C{sbS`Z2+7@xL~eLdC!^t$AZ)ZWRM zo?}z^+j9DLEu*dt{0c0J9C_jnfZWD)#vXnf0|MQV1yA+Y_7algoAGA|Y%f5`F3xo2 z6NHmj(4DhDo)KN-4D?np6s7n-iX{yVfiI2*w^t9vir#E`bmHJz+3juwJTwcb}F>O%bVq)fVrNo=&(WeM}$ZiVx>$L3vaGl~!M0XxUDS!igmZ*F`YFJ0^=(1wJ57m>r&Y4Km># z8&Bh~CvFK2#kiPmwn}MUhX!9%SYfHxNO@jNm=qP}$9t)it?&WC-;)6HmskFS4CvD& zUtWT?$h*2+r64pk`{z5FVG#&6Y~@HOM%0@x9Y>`94N0bbTT#JNa9c{w8c8Pw{v{23 z8aq60^AGga3iNrnIKk6}^&xC>jatzh4bnHk`r7*wxqBPJbeo>H9|zoGNS<&5znhcW z5BKo$Iu4ysPRI zw+E(9C57rJ9LzB(9A4R?qHddfNxZS-`@`b~MD`(ZTPwHc|8?HqcggjHd z{H%xM*s8mT;-&{#War8v=7_%U0Qf6VuCDJS5HJuueC2h?0+06ENnAw%S9;Y}L;y%W zrRIjc{Ba8bdkYmA0dzeKz1qB0pp=c?kZP)C%F(=ctJ1e?->B#41PheVa}EBza1@?KIzqQBSWbh-WJ^okh?PZB zhwc>6ISAzZ!EQ3PE=PyO8+MJ>78s`1UB2OazZgajVSM*wu+vKYX5&h#mY1<50zlma z#ykM3(sA{i;smqFe3pTWd>)@FmXsFL0Dq0u+uIK+&NgwA!Cl3aG1(|fJmm`+eoON> z>7f8p6QIw%{=RGc9I)-~$;$}q!2lA98p4B>h-pjYGA^QJ`5Ud(%9#~nY%1>1 z#(oj;hez)KWp;fOpHbo2xbSVV)lg6?zl-JYkDCJ2rdTepL$g}2pz$LHIYDXDxBf|Z zP=DTXTGlnCU9N=DIZ~`}%~Bnd0QUe7GJ|DuyGvdeIqEWpY(|D2n9x&D&Vp-815aDw z@RUx^srhvOyJ=QjR=N|a`xsb)$5)(Sh_f=>nx|_P`S|gI%?1GUgNT7~AjE-*WRt>i zlVZaLUsc^ZzKh)>)7fF24E~-DSR!^qgcq%SVJ9mHG4a^*$+;Kn>mdk-`6Px=Z=x_ea*RXz5+>wUjRWzZ(7IQJ^u7!?@u* zr(HzQt-L-hcO=s%&$KcJ6NH#wG(#s}`JOLLgnjNc zf6YzpaQszir@wfSvF+^l;1t+!A*gkTYAMQpAv(Le!s0EM4%h60!JjNj8UD&GGa4Gg z-@xCmRz0@*XP+!R&WK2wtU3@HruNXPVbqWPmwz->E)}+%uk##;{ zGOw@&FE=qQ^*!ODBUf_|;2eKmsFw-kl@}MkzK}jF%kRPEh3SurX5j@cxQ;@3_N5o^ zY3&Chb}>8@8em^a(}p>7p*mZ5hL=DKr<=YWD<$Fsv3t{N3lb+%6v`XMq^!#m-*j$3 z(x`~L1kWn&slgxP;U&YA_1oE5o}{A>qbw`(J7kV#krtNM~#w|21Sw}#^}eI3p+AP zyRmM#=`M|A17cho4RC=z@(aq6Cc^CA6S3NZWqpI@`1;TC3hYHogQ9_@s={xS^OpEc zc4ON3Q(&c}_a}XG$IUbT%wj2k4sW+aDs8PN15uYU7^usP$N>TmZff2V-zA=buu-en zS>v^UWw;|H($&HOP?aJ_3Z;1vw1{}e?f8Tf4NW<5zOACvdA~K`nzMs?OI`C3w~i7> z&=cQa(3dAYZeHa+*MHt>E?v3)&%SRLMdgR{VVBT44WOM%RDd*{`zZIF4K-GBydh2` z=41+E($3zR7mW~$lFPsIu%MBelgq8Jd6IZyf_*d(GxeFf>=7~d9o755dQF%wiR>nn>>}Kr z$>a&^NS_?|*ktXM*jNB4|3$e&Oa+d}9}GNV>uPn)T%wAGg3{(O+MjoG^uZ7k1UN;E z6D2Mk>8r7MP$4wZvs`g~8qOk-nIGWP%1+NKmn+tv?U#Kw)f6?zJ@04)b@}y~uB5zH z9k0wg4d9^!`JccpR*hUi70;Xp(4>jqGlY`fg+e5k2LhOV$^e(ym^}J{1Rsrk@RRhV zHD4)`9sWuAX$j`+~1euKRFBbXW%hP(x;C&D^vc;dtS zn>sqUT!m$wt>y`{&m>4KL8p?NWZCiWI{Kx*W$Y9`VHmOQ5Bh!l@R4eDnXWb0~8 z8xV}JY{(Eh2DFp@ky_G?Pd7nc%;I*9)vVlB6do=(00$Z~pyx!xY;_S2H~I@&%j@r_}F`LmgZM+0ve3OtP8H-MXz%vPRV)zINZ@@@l!zaMZ-M`4j%=q!{i zIuiT$sIy98_MFbrSX%up7t@4w$IqdmX7Zj}i4T1*Z)en79@I_XX(al+sEZ)_JV*B^ zGr?#Cax=%GDQ#fAbJ{bjo_AtvUHrm(izqN&8@cVPKnvk!rW)p$h^bV87D@sIOvHe< z8CO{FiF4ZC6H~o7>UK+9{)?tNe>{frLGc(`XT2ig7rZmA+r zqyJh1RO&jb8;-GoIHv5wobAi4UJ%f~M$IB%Jx~@*Y>{ z;gNnml&CB%FQMGbi4=2E%ZtwV#dyojfVOK6=jV1BYNrdyO}g2)I@7`gD-2?kR{`%h zFnUQ*wpki&+&Q>Ne8V{w0U7-pvbJmzt}$jP|K^8jveo#+^|1$42G@Bz3U}8~;o@KR z+W9&8XN9072A=((NKW_C3`wruQsxDU1vI!NK37|L0!J77 zq)$xO+R`3VWlFz=&RUkjs?vyRz-sJuT*dv~Ry90qE7z)~C`QXF!(!grBhIGt*Lh z{s*cOfRKRhzkBpk9w`g{$eOLl_sfG|7~BA=}0Qp%|#iK&3y4mxFWO7GXQdi{94A2EF=ej3@&L$yMJ zL<`EDW}Gq5c6`D1xCTW`Ygkp%0f3fd;2fO5UYa@`l+Yo99fHp0jbcuuFk0m6M;{)( zym`YYC+e&X;ku)`y}X=0O7Zke$5l#qr=iuKbuBqPf;8k$*E26N$8{} z?#FMOv&Y##_8#Yb-!sM;-(Ln~k~!ydm+QXn>oVF#b*{92>QHm*u{z|oBF-j*n?&qu zW%haO+~_aU+#PlZ$oPY^+6B}EmgZ|R^G8zksTV^_+atgAPP)Hua>;zR+xcuTi}V^O z#hAr_8-I$}hHY=wE4<(~m4F#okAoaWm|t_>`>33+=WQp)CC3Y)Rj1$+PO?bAoSE@JNd9^EukT=qI#eKV}QG^y@G=DA9r z^qGL^5i#s3aXGAP&P;BtFC`u6s}Om7b)&C>lrGoTJhXgC3wkF!sN~mO&|4>^pBHfa z$#|M2sdy@^WC1^VG%5%xeE?gj#!K?vriXJGHcJI`^8-x zZ)@Cj-9{dvw)bTjet&W0aOF;flf=Uqq)#?RCG_vw)vIwvivd&G1r3S80VnWz=6_y) zF&iup=mLSnx!DzD@A{_cKSFj+yguV)rz%N_UcMxR*6m`W5vtw}?3*T`UaXnQyyD6c zk07_Ty@vbl#wMrBnoXw&V+pK!65!hysxFFWGLWc`OI3nb19L9LI_LBQ;ZdS=36KfQ z`S?d-MuSJWElyXxe#^P903U>X5}libOSFjFhB0%eJ~%KJ33E0bdWTamrP^NzYUmoZ z%HSd$4FR&?dveN=xVPEiD4r8;xN!k}h_Lv}bfIxI3Bw4qeqZBx-c|Iw{1y}t{?gC^ zt-$PH--|L|)Y3L58go1<$V4Q!Q8NpaKmihrT(=7#*s|4wh@XwNS zUxKl$8l)rKS|h((-(N#LaI_QrQ%xeJ_|Y`WBtOZ$62euYNTSbHB&;RBPU~A>%3vk~ zB>Z~)o8bo9n^g& zL$mA?eB{FY{E;-4log2N&jYX%U*FqZjTLzmdv&e{s(m=(A(f%Qu$MTes*F~!r$r1hLt;)bb$|K&c z^t7mlA2x2yBcTgRY7#$%Sg!w-4wSMadODJOZIFk4pM45oPRy17c1`H*dqZI=ld!`0 zW3{nsV&nnXgaHUa+&Jj{Y!3n#5+E;EB8wcKW;INaDt290X{gfeu;#?id=#N*8D-w&5R(1iyBE&DKBW`+{n z8mfOIMHM^2hS>|NJ6wEBFD#XYJNkL`e;V*=8NT1_93fYPsydHhU{_wh`*I0RYfy?x zu)K?2OGB~uG7>sNr=xS(^yHHq)xEm~)71|^QyBQLUw$VjEnyHU;9N!L$HrX?ZTPJ; zuI?5;lqIb`bVYeKPiODlHH2~+`u&yX~9SOg3!?GOz*HLhVX3s+zb7Ef9#DE zZK4rt6*VmqD%$ngGR2i%Iunc&LSR}ARpT@Q{yt`t7cq|_E0H5xg? z6^0nz8kZtmqMJ>mOB$ufBzrcEEn6V+IiIW)DUM%RZyTKsG0j)kml2ME z$TcB4rmfApB#bA%f2dorDur71yBQ)m zUes|jX4ImtU4EUhwV?EUCsM5{U%4+w}4#n(;FnVTo3#M^< z(1hqE+goLFRDO^;KjHutg9XFREK`Oq@_z>CyON~ zZoZM43Uu}p8y+F>c6Mo`M7>MMct{9k)k4d)cEHKf@N9l3*64%fr4-6!X-Yyw@r3xK zLg=kV-~@(}Q%w$@@fy8wh8@ifzAaWAHCaHV3f57Xf-Qbakr=+V@IDefHrU%UVy9P0 z1C+-Wfu9^WHVlA!he0$DnDx-%E5fjSm{?J!zJ6Jv$6cROLopT9_9PUh@`M86oMvlN z|81jkkCn<^Bv0Ne#mmS@4#OMDNC0oN@481yfFOrvKRmjM-t1#&w~i7^a%f`Rj16$J z&%})^&_eAfezSg5S}W2hy2CzD*TLVpf-Y-6-7rCuy7Y3`Z+{U-VJB9_Q9FLoT``AP z*sY+%(&sD28SS1OJm^bNX4W=!W8T**Fead%nk%3ll_cbDPT-_YxLD>Z0-0CbW3gaR z{C;kGpKP?N*9LRf8;Yr!@q}~3^n#mx>`A!t#qH-fFD>VFuo&L_A#A`?T?WS~>NrG7 z`&}geMPSz;->Q7+m}tMYoUSfd>W%e46P5$lOXgPrh6H%`pd}@WBt_{4^$VkWT(ln& zAmdJBR1Dp_ne+Ex7{F*I0-YTI8}S#q`qo%nRgM~O{kFcq&MI$vGC{uTNZ0hC;_a*u zqaT};jr_$*<268h_6WlYBB8jwpoH#S@8AV%3{2VAeU{-)z5qEbRZ0&q_SYHZTFj;T zN3;;VAZI?1kQ~4^qoe4uHF$MX$iBR~FridooMyNGyvBhbIEg2xtCcA$U5`;O=1&Zy zO_OtI!%cv>Fng5$l{xs1E=10TLb4!k8b1pdyk&!-)(u1>$Ao}P8zkPbh$tEk>yP=e zDBs!PFLzZ>hME*xTKHwrmQuml3Jd(cOjSuQsZo`UX%dl^@r}7dV)q?4;za#n%Gc7X z1ihCI(_We2hWAiOCy`hAC)0xHAPlW!;3c~F+DH>CK+Q+O8~m&FAVJ08*W@0HJ-a$% zcXdz#g};kLp!b^5j}Kd{UuM>Kc23u{hTvjYLtR3{VgI|OP@nmLDV7;=-S)fXRA$q( z?u>w>%ci{^K>!Ewk zgwrOaBqc$th#_reApL?^l6Ge(fL;`k=uaw-=6rn->Y5CzpOZ%gay7VnAXm|TY)HiS z8Vf6$4IQdx$bi${zUwQR{j<|oEj*9#PhV=E=u7$5;}TF0zlRl*n%L9S<|+7ZI^6^I zAJ-gn@9`K2O+AIJaPI};hi|}c{gs)XbR3iv=Ak@2%#LZYPO)}P>zq%wi{y5Tk)RpN zEgIvB)#s`XF8GuujE-YgnpGe@D_1{2SB)2@99YyPP^5NOoAzL|SKlQ3f?=#o>?oaH&s+6>s((#kv zglW^YiO!K%(BYzN623D=pmn^KzYx|VGeREu8jYe9Ac;R|Is~r9x-%zsmf9S?fUjOe zG#d_T%O?ih5olNCxW5%II~^GoDB56M?EJUF+$ZoeN2*B#S96w?j;-REcM2O=o z$Q7ze`7ji&pksh1H3?*hhdXiakOaUR(iEoi%4xRI3Wo%z68-$r1`FLu4d1<~ZRY&H zN4SuT&<1YjAp6@*q-0d?no^{sp6YO;s<7Z%x<3nDNw#eBZnr1f1_5zTbYVYiBO6Vb z01Q;omO(M&y)c|aTb&mGBSOBUxae3p@_j|OpgORe{q0{@u8&ejy0zx94 z!A5|eUTY{FhYj}Mfma!wLONt95vW|L(o&JFNWw4u;HdyxXC(>MZ|;i|%$+sp{Z0Pq zC~O#wn$k9K$x!`5P|kOn=|$xT`5M_R&2kF*H|j02x{u#K{#fql*F*;z2|Zd1H0`Ur zRsePSUV%TQ5ZxQN!nh2uEhCLtaqqkJUK=~l)gfO;j9%%FO~3WcjcXlSxUwu|Ju40u zh8;qXg(-m*W35JK=-dYk*=YIo^*#C+G6`!9?NJb`-6Wofj>IQd?fZ;=TFYI7E=#0{HThESK0*q+ zW)l*w#E)Mcwz_7&yK90mncYnMc3FuaEW}W${TH|(kkjvC_`xjm4UZH>g1+!}32cl{ zD|`+W!W0_dPqEUufQ}1Vo360Uf>z$SK(B+b6}h^{IadL@A??Dc>edQfoq#QAYCFo} z^-(be9axpmG9#ZLI;Lg;8rcw_aLsQ%I|Od9yKOH83-5WUf`)-;_?`ocFFL~4PXFVx zI5kn^F<&4^`HsG`Zi^o-7}XHf^mX4|eeQIRr@J&S-@5S3j*-6>rZ~zCf_n|VFMfP% zRo`qpK}G%|jQaB4+Ha(2*+%7iLdl5?^th7XW;(%V3ekKwZZJ5?z+_pm%nxFVT!vGr z3^|iaF}cm2`CugzarJ7cg5~R>;2U;6*Lml!;>IlvNTzDj^T=4o4^YdgNwD*6wh(Ky zTO0#NV0G24u^s*EYL`4RBsUATbPHX7hI){H(3z+4*7Rd5Ud$OK+$8c8Ar&;zMu0CvJmNG`X9#F6q4^AdqI#3aN9t3(^UNpZV4e&eke zVaN_vwsmqkAU+~It*`}CLjaK0PZB>1SA}gol-rilR!r^OqqIPzh~tnf1|Rk|^S>r<>x%1|j6kRDGU)B%$;P$IH;s>zN&;XibuL zxijGE1kKv6BwR$Dj5-N{0PJ5n#M8IJj0jVzF_N5#&mNB8`WH7qFKNm@HBuF85fT{d z^YI~W43#$5E53JBNzYD_CmYIaJw@hk{ldx*&3AFP`LW5}uj1&tNs0CydV=z;Q#q8s zbkmT|>6Jy33HB1lEiTEdFF8W|kEzl~q)*#vB4=X+AQLLa$cd$%o>HEau=&q(`Lpx~ zuU1X_%namZ>nb*V)0>VRJ+T#XxHTa(rHBTnqEzpT^9Qi)Yi??#Q7DtSp8!=6jU^qWwsix1_;0A)@8KMBwD$^MOTC;U<%axCh!)3F$|3&d zxAAua$lvI%IA{YC)M$!}ti_4xrkP}$#mUTTZuZIUMYW&0SoK2<;;+r$;}uA!$D{Qq zN{hz?VPwej9M?^i07|oN`a0AOI$30oL3iICY)!mJMdAh-q`6B($MiMAyUq86#D&;T z!)C8NQ=LQdIZmb;())*X7VdHsdy881rt7xCLmXVPDangE5H2pO5nveYeyee6P!KO@MI`#{@yYHykN?9Id;p{;!p!j-ck&0W zPPfm4#CZ}eE(p`X?q{DdEA@Xx8w~SAw8nj*XwpWkZ$BFc_f@e?yz;H>&fdK*)z{DR z6o}ESqSuq6vW*7a#kE&c6^&yn`n$ia@VbxO#Bijr46JJf>2}SkKEp#zT>l7Y!9Zl7AwpTn%&wEW z9zr~|DC^(v^~{9Tsp>eJEM+Zpo%<=|Eb*D!&BqR(OlwpK+r>bSelc|rcsNfUcXJrD zj9h~%e{9-;oLufqc`IncU%fzXH-8WIgaW2n!vg|`=%Cj@c*PpapT!e^Bv&XmUorzo zw>fb`)hiR7=IbRojL zJqbK`qG-_7WNlG#roBUj6gWJJW{Drpbt9+KBAMcJ;7nn;jkWW`h>v(ZT85pttVm|3 znxoB~&%G2`rWCfH?*SviX93yl4rRPW$$?YP*e2R(ZF3)-=99A5dyg^8u(bpBO+))!Sypsa7DHN`F)up zv)F1F_5MA9J&kr}r}l+Hp{x?f}^-$ziW`}dP4Cg`Sp2PdP_vMqAG@dq4Nl_KuRSo z2Km;Dq1Dk8L(FFzM~as>7~9FU3)Hq zGRebJ|FB@WmG&?(gOQ*&ur31_aYmx4;SBff5yo9#fSO zv{Goxg+SuO3o$%!BT)5bQKt(tCTTDPk}G3x?V*JnbHD3wc0zNY^Yb{niP5A_VRe09 z?(5q>Z{el;;wvKd%RkjxgagS}2Y88Dcg!$7dE{lY&7#>5hS@?QFxsqqY0|t|1mPFx zTk48>UEE!rJJ#52RO`XUF?R7*TB)6jd8})oY&hPPXAl)`H#8jUo^K zDOqb_lw5Ar>5`XqMIXNt(>XfcQ$Bu&?;p#&)LGg3I;^B@WrpE3>eR~zqR`64%+AY;1@)NbE>v;#_MJMx)OX0fB4HeIJPkN3 zJvB!e*rGKQu<9Bw`*(9)vhpG>&dodn+@(3|1V*-xd?E8Su&$wrD&FI^3B@6qN z1E;>}sH9N48Y_IxiQ^|-Pkg^{=&9({k4+CuHING-TfD@hJ`pSMKBH2~)(NrrVMQ<0 zaZOzYAb9zH>Qqs~%+8q5)7W`SWimreTnjDj0phs5C{ycIoLGtzRiL4rPP_^an7Y!h zaT-j3ByDhTKs5bytq8ZM8{m%Pct+U36U7$=f3!Cr>MX4-D#4L$UARZ8nP9Iep6CGj z?-=AX@s=WEF`=RA_jim6-1`(zJWB!w&Uet+kIM1i$A06=tTtq-Ntt*tb*JA^y4sJ1 z#jZE?8&Ax;wUL)kMI(2>aPh!W=q1BnR5ZfgN-ruZaExjQ`k2s*5%AO%$+I_;zeAk* z_hAW!w%tzERQR>R@90ki@al}h^oRnA!6~hdhHo{js9hyFaT$7+k|VeJ$5(^+{NOxF z@&#y2L*E4yhwb08MEJ&iA$H#t>OZ(aU1S0PURKs^{p)~{NrMKF?E{8(bCSkgh!=F; z(0%ds>$9`$(d*aUbFA`I<>jw`E82kxQD0}QV3&iw6Bfy1<~;J&NXU8QL(5uF_sEE7 z3toxxZlgARY@@_>F6@|d4gcG@GXa&>wqZjL#H4zIP zFw0$Q(ka;YnDL5_S~^cslZDr$FhaEnXzbekW2KQ^)L<0HtfKvt9a@#!x0cBvk9949 zz*u&(gM)t)vfv~1=T=#F@j40Ki->Nr<{1w+W=9hvTK(1?&f?vY@Q)t_@qXCaosJu( zT_tue4+*TAm1qj>e7#Fm<&kjxJ?#1CxAfNA*79kws%mMzb`*b#0S z4ZSR;9SlDPJ;Syj;Uj&H$Ol?y!?AUvh49}!k9MoWe#J|MUv`DoQ~6q37b=|0zZtcznuHDBbxz4=Gfc2` zyobX)*M*hfCm;9kuYj!E4Id=O?s%mOyI6I&sju%A%32u%DeGQ5ZlE!HxO7B?ml#Bc z3l=-Gmch&TX(huo{%YA$S2|39PcXuHx7OH3G<(QA-S9>(2WWXfavB`A2QX_w&N;{p zBF_Z^(05jjXi1<9+=V+qdK-&+FvB;EESv1D%DR)uRytl+ccjV3Mx?kHYU(YXf<|o2 zHqIFcq{Zz4XB?|YDM=jql6};mrxAX;A}I*@5ln6Pl9{Cf-KW9fjuAm@x#Wi6m1(8{ zU7!=J-7AJ4h1$Q)-eIIn)PY_x49XUVQx{5o_9Kd_PQcSlKEk)kdQ8I2Hy`uyB0+>?jTD-c)0R`izWAvykKz_6oS zT4Vj?Mw!{!=HHCuY>Z8f`#ztLw;;ZM9;Emv_V;_xc>MzXc2OX7VksOkXlqh+bY9CY ziLq9hrrR)kDt+C&a!(1x>^4gBLAW5M>fqb-QSs>~`D?!{uuVcrSt)OB>3d@%JG5b$ zB4RR}9%qqVOpY&IM&8FabpQSZI<~Wy6nNWbXZfmEq_b!K#!kc;4}Z_m;&=&~c2wNK z&Kj{y+{0-9-i;>Bj2Vu{T#k+zYT>W6i4RCGcstoQaW0HPmr9r{nhgj7IWK&^9syKB zFzfs{FT}{h`7f%n@t#OXiI2n+*2R)58z5UA0%=b2D>|mvK`ls^oL(F#*7zm5q$Z)3 zt+*Tk4Q(Y#32**V!R{OTywT(^cYG$1twpC&OF-=Q%g>G^f@SAho@bUb)TcX+3961LAiT-Fv^}&2 zT_-|TLdfHdXphqB7m`+BUUQx?d78F#BKhJf*w!ikS0mu4?DSPsD7ryk3~z}UB_9!zMqv3ojnyYy`Ipg4bGK_aEH&2v9o}QWAC3sQkdnL5AE$~gc zd|fju^h((7j@j8{VCJAfULgyickts4A1jv1X}$`BkL%jEVUG(t}_KKcb12S*X$t z_EUoHLkFP-^-vIpVzl<<1lZzxa=tp9eiv6N17hzEooDS6u_fu}#1qafLH2>Ufb(2>00kqf?-9BDsDo^(U~p16~@^ALhs-Y9o+#dj{*J$_-Pf6<)1 z)0iYDUPZE8J{GUQxb)q%X8%Z=C5nDyrh_g73X7eYYWhGOWeF2#= zgK`gInw@W`i?Pk+=l?ACyM?lhjzmg_xzJ7;y1?p<_$vrFQmHe3~T$?|DaL)l7YYR&VA zQ_sTimtzx7R!pBNgdvyEX4M&Q>#f*qjfTh-adQ|6grg9%OAW2g^ z&kD|nD3z3ChzyY1WH+u{PyAQq$!B{*ghqJhO8ubD2`MaQb|b*P9I5fxMxq2v3r=mt5ySzx+wZwd=nrcDCMK zk#P&2P8@RQ#8)|UTR7S}SIyTh&;8hRo3152wAQJK{g6Qm2CqxnQ{=>V{x2&~Gw!>- zoIz-es-Ks#U;pmDzB|6Q6XXc_YzwEg%P!%Pn8&# z7f%y&-hTURVij6_emo)X0iG#H|{!% zt5_>Lk6Neo7Z!^o|AE@cs_gW+b${y=9M4tQId9vToc~RT;BBQS?UjBdzvI^d^$dV)`6MK>0Z>G(&_c;N{b$8VRHRt#YSPh<*xJJ?0y_^%HD zdjhtyaf}tpYSCOVIy;(Go(kZ(O9jXYw{G?@62zHgnR}iW?yKeLs`;ZopCOExnNoLs z8ci*(Ia@<2hd&NGZnyhYvtGGR4K2vgqxj?XADbF-6~r<-RWm6%dyZ;d8_5Y?{L*GY zxA3H4lktCG_5?z6-_`(i>yOv)*uN|5MAM1pf`lod?`+I&B*XQ|3$}j%<~QUkAcS#> z*s<80mnZl@hSw|JP!ukzprdFL?LmWbzdXB%6rqxuC zP_zN9#_x5G*2WcYQyz#Z!$G1{_KNdL_E4=ifYj3h(VT~TWa4!q$2Z-X@Wp7R0oHY` zR~$Oa+AwcI6GVrys?&2c_kAlUd$6|OsOB)sT- z+ZzO&0vB@X((0E5)>JtO*^V!xO0Rm=WyKV)MPv zH$L`FxkU9$pZ(Z61u3ZG{~A1NIf5wax9A05lJ6}>vc;*ARkHUZM%Mt7qTs#gsYv3d z%5$$$;TkRT&J1uhH6PTFRhOo|x%|y-C1k;AGHWf^8MHtzTehcfHvkb^L%P19!aUKY zv201(tGTw-Em-F!m>i--NVe#j`E9mf*LTt=hGmR)*-|a&oj^ZW_j6PHB>mn(tLI@! zMr=u@WPO0fsXoc^=LV52(EiMZuqhW_GE@1_!SB;?n6&?Em5r z1^UtdAJsO7&;@Z;J`?lApH?J!^LX2a;?fr{cAR4DMc`U(=?j*ob_Zwei-<^0N9+up z7NQ7)B7(Pht+uvT?W-_fp!8s8(Gs6co(({@3g8eyNWVVXjyvWtbK2u#_A;|5BM2ix zHl?qW5e48qrH63M9Y|9<_uWj(OS^wCG;3E@G|Y0W*~I8|8m3fA+_rJCngpJPhByEg zIwGPW!`1ltBf@j+ky7M!}&vjMnZ zQKS`%dU|`~GaF_~l$LA8Dk@GaS8@UnD1K~8`>{#qWa%q{@lW6Kf83b*-*l4XIGUK* zWb;2Q(7!^LW~#4*L2C|H$G{~r=nMF`LAMHsGu4L^r|yyL1ts*xsodGKWGOtt4{QeR zn&24^y%c;X&BD>*Jnio05quoqC5k-{nK@qILhX2fq+x_p<8>Zag9_ZOdQCeVm>wqtnFvUsZ0;87zuC{)K|%|6L7J zxxY(f4ACUPbRl4``QuGc0f<6{cK==t^nbkMT;{o_O^Z8jq9l?s!WEvh{XKAZwQ|1l z>w3}-=c~z9%8!4uQTf_sX56y!En+N!vzWh4;?~C6cAoiwL0?#Z+E80;dw**2kQ~y` z`tL5D;;?iGK_QZcx2#W}?9+wuj){s!FMR9vAz$=zvsaCD6)mRsqWO~f??@>ejxx*F z2I#qbR}wT3P52pdjPPOawqtq8A3T=AT4RXIQ3Zb8i#K+dJ?CYo2-BJ9h*GeE#84xb z;P2VK_cdPg(Vr=Bj zBO>};dD}m^n01)7CG;h%dVq)vJ^n3l>#Y~Lt4N?I6o6Cq?1e8Hl~j~{WFiW32x}P` zq~BiTMxi;5X2(XY1lThC+*D3E`2WWz^}jEH$v+1ElaSP77|hbyCmgm;arAOO-i)O){%ONL+t~d4H|JxBOUBQd zO{5&`74{m&o(apYije&fjGc+LQ9XbH8av}L!s>wGack|@Uaa@s-iMNVMOsj!|C&7y zJ)lh*?`)23o-dfWq-DxHBp#!_GJ9bHV5>!=I!lZuWWRXrNb)#r+(P-K#-Cuczvag! ztDj+P*{>8Lw&oQE{ zB*M4PH;l1w5TaelW7^HT&OEy`29h#_(AgbwK|o?UxXhq^dMp6J->?7zE!>q+_K0|S z3V-X0nDXUj{X2w5^(={D>xo!;mgIh}hT@D3>nEh{dY>GPd`Ov^Q;c45jwnXg@~-y% zvap@%SCN)z$LhcTZ@w1)VypE3)m1(MJ893w=0o1}NoTFye?xEJU?v3uS!f6J8o%&% zBsF}vF7e>ycCb}(B<*V-1s<2lT$5cxSYCC`1bB$3O-k>34uJFojnp&5(ThET&xu0x zJTdGbvJ9vO|J=-6SU6q49H(8>ZD@+#$c)-Dn@6c#eO}>kz%b#P{zQi{_j`_;`|;$G zgElY!21ym{#IsK$XEAr%Y3}9moUqm*eet+ha!wc~%_8-lw!NH)nXNl{Zhy=S9g$Le zA6+P4gRH699E8PJQeT#&de@^77=y^nyfoPrbj%vUk+ITp!VYcUPITe7kE`q}K0df- zy(V}xf#O*cn7Do?x`>!~d1LF)?5LQ8k7O>90hSZ_c7{(tkIKqIMPI#{;X=tdpQ}AM1DFG`iZq0K5DzyMzCk1NDDh zHD5`1BK*4@I>28nF^#sq+kQ2$$aR*D^PiZV*lqA)fwxdpPO4qla`3&j8r)K0*X7Fw z0JXK;^<-A`rG9bMzkY?J*JgYLUqYGa=8g%WHNu3jI!TlYUVt!UQ+(BvIb zBnhZ>3pcQztz$-H0aN2;{v$_+R)e5WMu_5`G}jVS2#XXB#;q`mJEvpPs_=Vz`)6$C?jsfrEn>sG}7@_$>>54 zJJJk5*;a%t89asMwCG&5;3FnOKQ_rMj4d!@bb5nNpRS%z;3VxTX_r!NeE%@*;i)%> zPZQi*@qE$rKI$<28d-ZSrEke3K6~!+NvdUR9ga3$2 zP*ibxYi5TP?Ix>k$g+3+257|RWC)lGO9?ekoH>IQ{_H)u?kDVX8V36{kc*}WU0Rk{ zAuccZG*E**n;Go!)-WWN(qDc^#^YGsYYoNToto5z_=JVR=<8fnd2_sD4!#qQbH8*} z*BwhFc_71kT7PUh-M;}Xws;7jL`@47V)8oW!BFbf;D-BgK^e3?H$rhgHt7NlXs>dn zOCR*_9_gQGEcD|)@|^j3X}{DFn(uG50gI5ESE$jxKrb&(UDPj?XOs3j2_WMYP#7XhQ{Ja8qT*hH_7$A@NWPn3^?Xo8; zoqdjz0ZEt)s;+Sct-o@}i!Ok@*(**L;6J1kaPB&sB4r^$eT<&bUsLD7j!t~D;5pYm z|78+E_#RBn1}scQjM_q^_D z$J#`a`#0&EMV@xxJN`D0Or!FF5Z`lj8ectEeMJ#-=G01!kMfh(+wYyL36!)v3=o{6 z$`2!!XW&QNS_97GYXP|jSh_&9illi*c72nq#S$-SO&|^KziaA}m@|~>_IcNASa)TO z^`snDU+xTS^NUQX_T5+m06>(K`WR|B-~AwoYS(w%-?HC+l}nx=6?-vC3JU592Uc1^ zVb%HE^`|gAI6HprY$iv>+&YUi#_Se>R(Tebi-h$T+>NsHKQ^7fU)xaCzf`LUncoVC zSkL@4z}_nCyrWs)J0yEE_T&e+;%uAKTK`a6DC4u{lyuK6V_s9c=&T+T-><*-|M{V2;>1%IXdKUlQ}bI8*u0 z)Ls88)R-{Zqj^!3<P9iwdpU`(J{&-WpCo@jxw4TN2rVwfTYm_2*1f_`b=K2( z(|OxKJtW%SU>|dM?q%|c&@YEH=frTdCA&)x?7Pin2&`=J$b+a^wt1x&JVDLSJ8WM} zO=DNG1_#VJ@L4e*UU}YbI_-hur~#@BAa_Ko{%v{}KImXnNvfyP3ZCM|<6S-!*La0v zd)p(M@%=8;o;&ZFzKh2$O)rDBBcRU*jc|Nh18O^6AdN?H4M6FAc4;7)t_>3{ZD^gT zW~g5DS{;z()`qCR(hzS`|LGd}%rBOQhGAH#Yvq8ham8!9)fFb_-${7 z%l~%#2mm8245x2vWTTV5GPoY{gm<2iQWcT}XGNwQk1`06Q!=^_1JY9OkY(b?%i{Yf zi5ynC^R&D*Y#di02b)08YWV{u&m8c3vi+r7RK}7upo;Vd<-*~yqw48Fo+Fz0APT>C z(pp5SYP2~&zaTehwC7stPTi&dE_Hu2#(*SPTKEZ*N<**xuXeB`6B+7(MQ$j|)c0X* zt?0X~;T_o9zDF?V!7^!!16i3F5q(|VCUPV}|K9VBJ8qHLlYX2(Mml#*bsVA;`9<}9 zI_WV{GkYZ%7;VS`eHx7A$<~VKa-W-RFpq>qxA7I>7A}K~f%s$zQ$iFi2tPK`*+sK- ztsbu7X1kn@ZuIiBJ#(src+VMm|KN@dtfO?lw69~1YmW{T%_d**7T4ik2{X%>gR)_< zZHX^zZmDcjOZ7qWgOS7m4c}NnJ&PopJ*!!DM`RxOKwBNZt8+bdkJtPhzLggICgG1j z`%~ULl_Fzf)NxB?W1`^Xksq57G7+vi`$XydSDCaLk_v+ObhCy2fi=IIa!SJ_lgb8Z zvY9d%fN!m@xChF}uV8$yvhcAcA2g_iv!feTXNs6@@+K-P?SZ@W7Tqdv&UfynpGzCE z_9`raIJ+x2Y|sdCFtWW>TWpo+?#~Of}}B-qq?N7EkBWJ=?%ue zJ|p{|jo*K!Au@Pn2*ar6SWR-43|Po`ayz7LOQ-%mK9s6a!q)vd#C`L!BwM#c?Lp*6 zj>3)Im-lV9e%|3_p8c}*IHv6B#GvS53?YQ3G|d`xPr&Wr51a@=PG@+)mO^zq-uF{E zhLSjyz?wfWoKxoD>>B)6Tb>KS5$S`nJw~O2spfHCCnjliIuDmK@oY@OAV1N4!NQCnz(kfl3vW{SiLX>VXdMq=F@bKa{^^GvQ$ z;zHVMs-Q-OTqBFeCLOl>3I{`(30^SVQE>$q9P)uS1vQ1BDQkh{gt#cpV~%97mOP(0SF}?&AUgbGOi>OK; z%@XD|q=HT=m*{bUhrBXfIaD?%bs`G6o*EV=-iFm;MJ}h0>$bMMf8nG_Zi;>WW$JK} zpP|w7cMGo?v!pZg?CUfkg|Y4QDu>4XE_nxOD{xGJhshIcKa`O+U0&K~?=Vk1mYg&22%duj_) zNZL#LG}Df2YG;#-U=QaG`+!*et#w1O{93k_9-hSC*V zu&p8?-c^2!K@YCKFNw#Bn-;X@pXsvafit|o#A)W7ihBBIHCc1DT@JDsOOR=!A0elP zhM?)er=u5F9&*)J^VY*G-RsQ{bhZnv#AH6UC2p2G) z`frv_m>>VqipzhMO@*Mmy+ad_v$UmpiY0mtC3wwa24@9JGR-4YTqP~!aWiMIJ3VXpOzjS`3tKXi z3mXd*Zq^NRO8gkQQ6ip?e?byhq`6K8tM~(giQozlwMah*!K`LEoEEQ&{2Ovx`?8vE z-FEQp6MXqNofUoLWl8{8zi%+qz@!TsHFhA&fu0^j$B)OF%yjy~qb*H>nF+mPfdfmK zT)|J2bXQj0cxM9kjE><2$O`=_S>4|j(yZz9;UdyT?-9O}!ZKgmf^BCXPT5Z%KU zU3*TfaP5i~hA~U#_68^lPndRERwy55fSfw5Aj2mI%Y4M1jf}cxpQOwHcu^UEjHGfl zC&8U9oGvM&;p@7f7cdwcv`bDqXkkx$xPOfJP(9-JyD`UN_h;xw?SB`mdc)Y{tNNx* zB>w26SB5z2zfF@?_@t5q5_(yuIPib8ccoEHomX%qrMgQZv*!ca_(C$~C4Gs$o zq!g+vtC7ha=?s=|S+_7gGEWXWdNeu?oYd4LtA9PDE9!C+eu9M?J-o?EB&I&e#0-&= z)rgt!VS(4M^A!)HmrI)I(w+fo$k{{Zag#{(Ng`g%kN4ulgRk^7ur%IY1GEjc*P@y21wT{`||%3Y}O%_6%O^Kan-IgV$gJ+{Y8A`KL(#SoLY zk+vr83xujY^}OQr8(7#ZvJn)W&=RJH3QKk8AaXYJay3t4HQoa@RRl{3I8zL=%ziib z2BxZVOkVDQ7UBa;<-l99{k+y|F-0#Kqq9dBp`v38L3lZ36H2q2RSdR$V&%hNHfWnR zs~mK+_!@ALe*ZKC?WsUQuU;{W-5&>BTt3^u@BCB>Ex#Yqydi@P35*GuwAwDD;hLFY z``=~-g}Un3rNSZp+gzYQ2F~!DXtb!}LE8^c`db(e<8C=WMX?unuv|ma*P6p%cgCD& zUsV|y%1xmQ7E}X&Y)fclQhbt^<=yP{v0p5%4i+$cNqSP`cxrDIr?@S65;a;z zl(*XBYr$lGGpZyV1)Jar6VFPwM9m7P*(t}Fi_p>7l3Iq`NM?iCEt2SBUG~-1eU4nR z>S_j_9gU9LhHOWVX}Xd(8sBHZHdm^rwH!2)Cp+g4j`p6&H!Hd`;B>?l4mVzxT!f+t<5eF8f>49Ips+(e=oP%@+(H z0$ZPcQC_E((N)qqi-=i=a=I_r3Oh(0WE(Lr+eS@{Hoi;W<<)jWJ{88Z`gc( z@@GJHS-_xrCLgb__lQv~GoMCQrlOMz`wF+XKZbq%V(hm0V+XDHlxr<6Rr6pnxDkHn zvblyH4nJj$`C@e9k!;@1(L1Fp^fbZ|wM4f|tYLR^8Yr2ktg^E?6S~$OiPbFi0=%&P zD!B;keu__H|6{r|7$AzS_wlq;q7tM7G_n;q<%?Gb)Kn72>L-$>d;`;pOw?^2u6DFwA6ZebDN)bDw)i#?}l33>` zgJAI-IXXM2Se%nQo(#^HB7?eWxE70n>!h6)IDA*bub~rWHuNS{Xf`al4QbOf{h2>% zFfs`D5nW}`Gb6)0^2otR}e*#$iE~(e_Qv+lK>GuQ->gW4gJ`C!e1wzxN}t zT*J%P%X`xf;#E;a*$%UzJ`8FUYqvAsm|+n;`PkME>``X-1a{5QAjG#CX~MLr6rLjY zoj8hZG0FSbEi2d1laTijTA&6+2h*1RHMaO{J6PQgs^MyQaEd4@G=*XSE+=RuKH1S+-6j#t0R?@-a{>*r_DA4;DF_wKct>MLw?UQ~!DN8lzXT zb38-Qg;LPj@NNsO@+;zRTEjk^y8vsD9bVBnD zh*-gn(xnL4X(~vEB>!vzh*$3WzW-PL=X<}Oh3uX==giERGiPRJXV2^~ni*ZI-daT9 zd?CojMiJtHAV>s)*bopKfE*D3oQ8GSA&4Eo00n&lKdxy!Ktqez*dYUO?E^m{0CR!s z8j!$Z051ZtGJr*<`QdcMr(rm)9FHgCi61XbRRxCLBlcm%-q1!NE9!pG+{C;t!dj2}ANMCWz3wlRgp4wXbi{|U?2^3q^5zozJa=q3=(Oet!;qRf+(Q` zzhF3qjEamUxZrVUP%0THbuUXl%Yp1?r(szD%N}Hv9oC`3H2fIA&{1xP16`AP=JYoK6yf=V3r||&*=1yYe%L($}orV_! zm~Wbg1bBp#SULx2=vWdv(`K}EASh`L44t2r6REDwcAk|cg8^hX&x#A%9%34XZEw*< zmTZv#FEkDB1@PjFthlfpvSqMfIA8WTFk%kOH3#OIhT*upb6~zXFf%Q1VwM+Nff>Q| zhlJ}7iG=G%4#+%0Q6BbQr1?f{FnQ9pQt* z;VWoCh-v$W+tN%MX#wS(X(R6dJhzRov9t8n1MuwAaNkO1Vvses!1>Nx8O@A$0#|Iz z%)B-`Iau0kvH-0df&@;ZgM;zxpfZC96q1vbsf@=KPZ{oZh#OiA@q+|3(HL^D$>zxH*t~tnm>>Y(0KeUsU=jsbgBHNchf{)K z*aN^~Bp@Jw;e5pWSnzHb_GZB+m^>~{W`O4k(6|5^P4a^v{u=-<6Nd2v>G0PBSe@X5 zBY^V5&Bh4y06qXV2e5Kb5D|uh0le0GPC9;bU^Lo$Hcd3zZx&{i1;hjyo8!pAc=Rr2 z;J@+|gbxM!Vjfc9EIx_vHrkFa-z&MJH%M9!vYVA4$ zhX%Tu%)o)fjkEj&Z+nLsJceurbk9mN(%;2>2KK?4Tg<>DqSGutIm~$$AL(yqKf@D% zwuS4PDI1yuplKM3x0=m2n6i0RP6FP3wk*CR%UK>Q`Db}4{w~%t=}<^6vpl{yOPd+I zKgoI)AB<<(G*bprsMD+-umsmx9r~cnXLSqVAUg;RVJO%LU_%gOMhxCX!uk1AWK4k7 zW0hrW2pCmm8MvE=;5G#FK+q2fX4_zsc={6;auBYDwGagg04XM&^4$Ox((ffs-S1kE2sf#g*u^+P%rcy z8i6L+*x0z)1ldH{ma$2*t!7hV(_qtMGh(w~+r;L?wuNmcn;#p2EtKsKwtZ}e*^<~& z*)FhUvlX%3V!OxogzYuk8@4XCZni}_x zN3!o{PhdaIevv(oy@dT9`!n_i_D=R*_F*vI;73RxRv}andI&Rw1Hu#Giy$Fl5OIiP z#6?5_q6|@us6%uj`ViwBTpXetG8`%#>p84BTsbftAsjIrM>tYBu5graJmje3=;HX! zLFW|YT*0ZtX~1d2>A~s88P0itGnq4!vzYS{X9MR)&JivyE(tCLE?q8bt}R>vTv1#{ zxXyAFa^2;6&GnvZn46n>8MhL*A-4lJnw!FXfIEddkGqn)mir_37!N;>G>-<4C66Z$ zfoCsIGEWZA9iCdA&pea7i+NY`8t^*s`ta`JP2|nsE#s}>{m47XC(Nh7XUONm7r?iN z?=)Wl-y^;@z90Pj{IdM|{EqxM{@whi`LFUn=I`Pk7Z4Fp6fhImCJ-u+Adn?+SKy7n z4?#h}HG;;1o`Mv?1i@^<2ZC<}#})? z7r7+zK;*qBLR3!FOcW!!Pc%dHk?2P;E-?i$8?gYf!(#bjFU7u#i->E9yNO4Lr-@gH zcS;~6)=1b$;3X0zu1PdXOe|Ts#AFF}$)P0$OKO*lE|pwrycD}MZfW7thNTnBWR_Vh z3tV<=S?RL&D;j|)Z#ibR`R}8O| zT4}X1cxB4U2P^xeB&3X`0;Enz-I3~+7L_)V#z~)$u9WVP5tlKM!ONVMc_{OJ)rwWt zt3p>@SoLz%q^yFhtL$FcLfLjXJ~=%(U%3-<_vOCJOUv8I{~@0%-?Ex_wccv~)u&ch zuO3~au*Q8&?3&UwUlf)q*eFCQ-5$It~#KDO{#lUOI5$B$*Xy)9aF1T zqpNGHui14cHAC8{Qkr8lnv^70q5*BoJPWgch#(n7?-)gsm6t);A`pJlG)cPnkHD66~HoYotyk6Aa_ zthB+{WZQhV)wPYbeYjCzqw~hpjqf%oZX#_evtzfjwL5OtX205=U|;G0IoLQHcWB?N zusLLNxg(e3X2&$gPfkduKb)$aMV-BzbDT$9OkEOPT3y$=hPvK&6LQ<;mhCp`ZtkAs z-sz#{5$*A8%knL_EjK;6J>5JrJ%_hiY(2U4<2LPW2evhCSJ)o0{mG8yJMcRyyo9{a zUe|YW?sVUovvUgVfWC+x_O|gpvu{|xO4GYU%!8w+;}zaAkRL5O(1OL5nsU7sT@ zBQHmBL}8-t|FP1mA?0i8_hrj&dC(9Bn*?I(8*VI4Lse{c*eFB`0J~#GM#A>2>l+vQ~2XDZW#o zr#eq>I(;)mKILf2RH}b!Lz-z?;h7a@4xJf2>vOjDobkDW^p)v{(OC!ert_@ix%Tto7uqk1U+TOpsnM;u`AYv) z+3O9j@6@7d@70;tRn^!Ijv146FVW&=KMVEQk^LNhgTHj;d_kJLMnEJT?li;W1&(fc>zi529-EGq!u@ByuKjxBoAI~j-#xy693Txa29Nw$_9JUZYv}&)=Ha&^K_io+abwHI zu8ixAS5LT4e4Y%S;+{H9TSqISZ=|;|f*6coGzrZd3n0Lm-Pad_2D2bYa0?hayaG>T zi&$e^CI=g9Tn=C`O8+~UH4bL-gQvADV+eBH4MCgkLeM$zTMb|VaD|6!F2)eMrsnJq zVBmx7tEs^R*aS#mXfnoN`~XiN++`3%BQY40XBiAy1{jOKfuOq~tg$uB&9xYU&Wpg% zb1Bj)_&WDs^g{y7=V>o9JBXd}62=nvt3yTX0 z2ndNU6%`d16_U;LoV>WxJ#S4d(%#o* z+^dtEzjqB_$l4MYukBl7e%!^!;{GLy&XQW!ci6$}`ybSWzW-sVa3bT+8z&#ue;B%4 z{HWpMu$yn#f#l4Rs>V+vx>oLf;jyQ(N~@bbj|zilNgyo;QzmXMPHm?m4~wt|{-`McSKW<}8jOYYnXCf(77SqkX>?2ytnNkAd#|S+y9LMj_N=$H|AfP?kf6|_$_h+v zZZ^94?vI^0=Ka^3sol|Py-0pZPydl1`P|C&EAw;^xAr;Fm!o|jT^J4ZrB8W;0c}^}%L-Zjq;;49WvXl6_0cm3>(9<-KsBWVQwCIx5WgQ# z{WLg9SJ+xau63$wG^+XJnBwgnk5*TsdiyuEmrJg`kZy0`X+{1zlI=V^x#+Q^+M>M} zEaClql>qln*Bz^RYq!1BZ8~>6#D91r{~nnw&aKFrvdZnbUP5_j-;$6%Y+?T$Y1S3A2Ij1s;Ct(_{GC=y$BUM4&$kyg*&ga1@8{ypcv~aq5yXJr(AEeB))WNU zMTkdBng8IX$upn>*T-8?1-pATxNp4hJ#=N5TVU#BL6~#e`g3^lY5uSckujC|UnbJ> zhS$-_eq**LF=Qm|>(1b4Y=X3H`=bl}e%+|k)!E;ocf@v!8}ts5IJgTW?KCY-l5GPoHXZ!c{Kqw#b_sQRl*R!#Eo}RbTr4bqU z;&GIu%&ig+{?^CsI~Wkgqv7)Knr93M_qJWq>}p?0wXWrxMb!kQyuj$flJXt2Q&iLx zefZ@@NzBH3D#yz7_e`cgr8P7~dtmN7Xw$wT4GAMlMAO6_`G~HC< z!GN28l&eP4sm|Tv*ENF5?sW$>cL|WwdiV*~>n80AvyWV?w6FX=E_Jz4S@v0e@!K^1 zx2wMZya_ZplGsiXyye>$c)C$HBJcL8XpxqYqP!OL zohpydR4=-=9-oQM^R8t57uOo&^U102`*F}@v~Jnfp!D=^>b_w`24o!@BysIRVCuI` zHRXYO5Uoi5=ay+Hbp@JaF8$|dew2cmU#+M)|1 z)1UfCM8EI3Tz%OkU$SC^`Z*pGIPKM!kCQhn;XwPR-> zPk|xdxiyW3M*>S@jxjoTu>0k=dmi6Qjon60}>?E zyrw>!q@g~$t_b&W>+PU?mwNX#yiD3_r2W>F(V_-I!;#{BL%N>Z{ry*spoqEsWiOr= zRHUIyK+pCd=hl{l$Hj%Qe5sz%OUld>Govf5B5k)yl^3pGS{rsyEirJ@%CwI0JD2vR zRO4hzH>9<7N^Y*b&m(^)HN8K^sBt2#lzy&+x|fc&(jRW!9W9|nl3Vb z=uJQMOLRl!kk@ktwBNNgzCIu0;Tc`qWbimJ_1@&jn+dOtWYDeKZ2EeB_h|jdwwCi- zi|*bk+|y%c)^R;*q&Se0P#nH7S4mQS{nGX=`Gwlwh6;Tr2J)gk2@Hte^*Nn9*~I!J%0KuI>l{bTt_cbqM^q+%CMVAuKF9XuO9(5{{w(WUO%8Bhn zNAaS*tF=n`Z!?=3H>!1DJgW#D{Ub3k!=D+D(?IUZkR!)@H3Q3@s<1C=D$D85e!+nD zm9Jz#8yOH{$En(bdOHvF(^l7Rpl#JHpCpW~p(poNTKT@Skv~(+sAV=#?Z`vYzRjB? zrK*I|(#q+32WtlYjHVV}37R~EP+q@Y|K*TWV?}w&PnaE?{@m9wvji!H7|01^i5DNO+B-J@F*{? z|JkiawVsWl==B>xpAfkGQ+)?Di&i;NyLL-#-*fSIdpruvqAZqbb!LlCgix6UI(t171_^VNliqG z9g=?@y(BU=yplRx>#Q(z2HXntlb`Vn;OZC<$EKHOM#{F6`D0%nxVLD40r6BbphuP6 z*_DdfMri`Uh$9bqTVA9O)kWttnIVQCnsA=|^=IdjP9BfLYa<(xCz|q49!UA))=Q24 zw>6)YhZqpKp=fF2XWbyRp{;BgS4G~nhr9Kv4(rev&}-WR?ft7e5#z0%oovgSpP|yi z8Ugw`^-Defixjq#BHN`#wONLXb+P&BlT`OCEbySH@?N{962x)!vLYMJSB$&utqcX7ol^zSQ-bQWVbzHhUe6xy%@Kpar>3 z99FrGSX1WXIdQJ#{nEb<=P7~=iPjHVI(7MhyzKsS4Uc?8UiB{OU{aoWW zzls#?3ZU%FHxpWc6JCudi;rW=B=lbdCr^ZZl_v~KA-$ptZZ*=6O;!%_-wYjVx60W$ zRQ9YwIXUTFlY~UW#%T8mqVF@MsJ@|rwC>9Kq3F=M(n~|1u45Ein%UV5?p!pb8gfg}H%5(9uu5XF&E9Y6?A{)>xRP?b8TY;eNEL`ORQpOHT?d)opwF=7~+h zt~!`RfxtdYj7#$*k^zlum;7$A=+7Ssxe1M2*!pD&?eTA$TkO(LKkdzqZ|Uh>uiV}p zc`j9SnQwUE!Q1sXW3xU=@m9Ax%^X6;V9Q>4x9Gza%$7)t7m8K%9L>Jw*Kx{ zg8G&|CNd;6MaZoi2E#QwaZtlo5(g-6xceJLw40V+XFya_kj%b*=&{s_1j7!{|6V-W zaSWpzbX4f3$Q!P(q_D|S2GqfTdIMhxjon03XtyTLVnl8>OS(Ls8iQwTRV^b=LR##riprX%nzAuDz?iyF_Z62#X>6;yY9IJySn<3;b@`9*34xBN z@TiquU!srfIOZ@`*&P{Kzx8-tdhrLNs&n+76u&p1zP1E;NAGx4Ram<-NNXhXfKG|f zL@U*T0qsF58J;xD{^Q)aw8m(~XTcg)8Lw8Th`WCZb3Yd3j!dg~d#-97nzp&u(5@zQ z@+#8f%eA)5KKEf=iS4Cr3}{CyC?yzx(uj7ElaZDPV@ck`k2k6HH??>A_|(1r zQP5o&GNePhcpa@4f<1R33STst9@yL$l{VqL zJs#E@dR|Lbo+waIp)%^3H?a*Uk80Yn;nK^W>QNTH)`foi$hzL;B^|zY=dx<)LE-#0 z@rHr9w1}*%P)U!8NNmmXD9KX4i!T!Hk+*&;%WV%Drc>{v=FuacHl5F`E==vF3_8L0 zNE`ViTL2`T0FPIf!DHw;CgR<7WNU*_xsP|730C=H(!H9?MQ@0zbi1@d(Aow23DZq5fM0*jLyic(@O$E4y*wy&fo5|aKj zx{`hF7OvcXn4e8hH8G~@=B-xUby=W@4a_34o`U6*oZu%tc!WJK!h!LI(XZ6^(-T2c zRUOhZwXx%1y*whWVDp3!lB=y&fXNAVh+{Sg-iU+$73>j^{(sn2Vg)+^5}n7bVFf!G z;?dOA)X>$_)m*{O`Jc){7vh26#;fZikt^6YK>SFghMtD5k~%n6uwx+}7vRu=M-zNj zurGtS(F6)EBoqt7JTuN7aDdMnc!Btlh@mV#4sSe*i3@`!g<+X-Il+5j9Eq6<29G9_ zahPeCNXCW+GgHLii4=d}CjtjJF+@C($xU*_nBsH$qRIX^77wp)D2afhgpybkKP({>M_|I7ek3fG8Cd{_ z$A^+BB#;j)68E%^3sbTge-}8w5lA3yv}nL0#}rgcfeQbmQy}A*L=H017tP`dMzb`*IV%=74B^QBFr6EIH9M^lo@tmV124dagc5ON zW)^&*z~u%{reI0TD&n5Db!HCX{x}MgX~Aq3%;x{vY$)?~eXPEBHFF|(aq#k8A7blb z4XZILgs&L3s1o04V0qq)kC*?%*AOfh7e$a7=3keoX>7`N+ul5JSC< ziJfqed03GMzu`>rzw?=rd|X@!6iYcLJk#-GCcY`&M`k{}6B$oo;x|X&jh$w=A-*sy zhC(EnqbX>(1WX|}`)wxAR2mG!%;3tb&`nrhRx*Fd)&=+$&X=t-2G7E8CSi=h+aUOW zYY)-S1Q$;`g0atBnKiqHNt^akgJIO}={gr=Qs5DT6q9q=uVKUwW|)_G1}8RVUJ9^% zfR|7+RRFOwB^YL6tsyn=wu%kHgEQ>l21jCHE~KQ+VlhFbpa<0kCoV%AuwhF2Xk!2468H4>})J5EH_*hxW1X%-~b*+ z;FxYn?8X2Me$!fqJ-X(mwHyv2;M!zq0}ev$;5{9}5db2PB}9ZM;D-m^NodFm(u8!u zPXnCwn2;Cb4EUxS1RQtvn1h4Ug46uAFcjbf z$x;h!vUnl^xXG~&*tF+{O)116R+uG*6Y#2Hg_*_VBI9uwEZGge32q>4zvRQoqyaSC z^Kdf*Hs*8E=7vXj!M~umh`?bE%8RQ5n|5uD1*>7&Q4TM7DDK2QgU$_=wupk~7 zB-xOyUFwe*Xk;N3MJS;O^rZSMZ@1AQ^gR2)FRNqYDiUe zHE07W0(edaVkt7-Sm60!DEqCvQdS1%V<_vcZKrM*Y=-s6Sx1tv&XM*mn8-kkzK<-* zNM=KXK}1k+5SD_Li3q|I$OaLHvdqK{01TtmWM!Bvlt4pS=K5?I54+7WW<(NJMq5=~ z1*5Kml+n>rMQW+*Yw0t;jH9lG)KF8`RY9s7XzLoNBW0!!S&$pa$JfBg+;TcE5HggV zE>w7UxN5kjDv{);hSb;BS5wze)6h@>94h2p;EQe%Dg?6JObX`UYf>Z}(;rO+P7(N8 zg;ES{k(07Ht#20cKqlZS|m_pC}u1fYh18V?*#I!hC8-8Ep_* zMqN!E{;^^>1NUk)-aa(Q8%qLd>+6AUt7vQKPiJov1U~pTOO%!I!5H`wNkM3!9UM$j z3kb&g$;!;uj=?72ZjISxv)RSW9OnnTpABWr^^m&e+PX+RJsnd$Ju^!^U8JR{rj8!c z(!vC(p{X%9HgN94nvsB0GZwTh*hO7MU0(%>beZ{J++1EW;50=c?J|^|@mBwZ2)w3o zAoF=V>F2UJGi%RKcE+)OE{*9$V+VY*0U55@U<0OPz~u&bAI>z`&2v9jDC3SJ_z=U% zEN(l{!hL|VB3veBVKm{wsO!LmVSc?(NnOK09n=DxG{^_%yX#+KW$9;@^{*;Y)zX=h zu$`TOIS~^IH#gWUKvt?gI3Lh?=$M&kSXx+EBDF1$NTj}|4$@2?sjjD`qoHr9rNa~o z#I+%iDX{naOk5m@t6{2dVQvDJ4wz}EgIWajYNlhUX=1KvVX9$fYHl$Tm*o+L#{b9i z2W`l}1P@HXXBYf=FdS?UE~HSbtPD&s1#1ngLxEa>`ewq;Oy7Cfk@hE=>9It>l0h?3 z(w^ouV>ZIgB%&`44^m)tyw0GQK4_8;E4g1-X6#rWX{m0ZudQ!pW@f2nsi$sfs;y&b zYKqj;)wTetoJrlELaEJ7Il7 zF|49#Xiv*XB)}eHE<`I5dKVdkhRb4!#*?QtWRCTPmreXskwru>kqn&sLHg>dGrF(@ zD;ze#-(UmX!*l_x;MEUvb<0G|qg-n=*^C5t*K=|OIOpk(ZEkg0gDij}oIk}0EZ_iA zgFf;v*T;cOmnBvV(vI89yxWCO$bRePUs^^#7HiweH z7wP7Y2dZLz!WQ5gNDQB)Z3+#-5#YA-H^rNW{!1a}q5oRcc^Lj$;CWd7QtWv+{!;jP zIOeKg9`fHQ!a0b@TI*vdJ7a&F!MAw8NQi{Pn4?L7pp{Nr#ZUaK={SQ<0GO%nwE54& zF<*41anDDv!}(BvXXJFMzsutczGz7dpC-?=xu2P`$a4}Vk|}U&aD&}FDHNe|HX1x zN_GLuIA#?&tM_R$0AUgs8kvK8Ee_n2XDVtMZQQ4!b zwOAc0v#wo;1i);H2CLsNKRbXqq*;5MTc7jMf0plO*02e)a$uF?Z_;29=Sjc?3&w%q zro!yTwZJ!kS(39fq%_l|f*i1B;DeV~cqxjZtQ{B$g$9Ag3NTtilPRnyz^j2(QpgQz@B;`Q2hwLktgO`L2mnBGsCNKZ7cwn_DcWyV8l&lji*u5hPH$!v8oc)Mcl^vk%-<=~t1{;y%q-FToix2(a~=XbeEA(ccO~aMRMw}< z|CZqMI|W|w`8#%c_2)cw&;RUSopy5Tf^P|Di*53)!Yg_-8 zFppklSHS)r>F09T-)YmG-|qzGLfPNZ3w;*c-B0(^%x8s#J_~;C``uEem!JPFVICV^ z=(FI_#6q71l<;5DXE8@*tRWXXD*HJU0|DmD3wgRN|MNlOJo9vOEc-9RzuB}wKJbnK z)AQB;a%TSxBhp{R0Ml$>^2{1X2J4k~O^fA>4VmrPWSA4o2I%Q29WokxFGF@32|k$t z<|V)!1DF+NvEk;Kg!|_cc&xa=tOsl`+BcN-1v67JtXW$M&evB4?3yxn4wn@Hd@F(i zPePl(QztXCV}CQt$%+x~j|DSs%*k3XU#p?%qM>P^rDdR{t)vcKQK-wR{TCKn-O|h) zOj&B^=^#y*^OmL-NJ}kkeRCak6K!2{Flqf?R0@3;q`rZso`I&uKPv@>H4pcHTY*UR z|8XT@nc=@yUGv$bhRHvh82*dF{N053zgmZLw+EW3`8mz!KT(o@I>r6}z9h^(kkyH( z{k4CApWkPn`se9yjMSB7)aUf4)8i{m4e(M?<9ED{ma>et&hL2el^|sqaGHmr50XOa z&l5*OTN`Aetvx5s+>-oNawcugJ4jF%CJMaRgu&T2szx(!J{PVF8d%W4f(8~eu%Lkj z4g7zkfuBBESOR!j3I`rnbN0C~hCREO`&_Vgk@%O+>^~30>@g=MysHEIEa6`T81Oz9 z>^cZX1RK~G;^#gWfncADi$F{+cCc5&?7_{$#mT{o;A3Zlz&;lc7vkp@7$C&Sf#7E6 zVdI7P_!q+)i-Mgl5U@n-T)d%RUrG*PP7$tE+@i7&4^qrTLr$F6(NqF0uero2WY1FX zW2?H34Z z_v`e0e}pRP8(7=ef^F6O{BZ$c;Sswc|2z$w}d8dk^H^aW~A>+y7p>;4LX)$%m*%BTcf?qMaRNN zfsefJxFrRa*A*M;rn~=7rocbeEkBWQ1Ky(JBx{e3wN~!Fdb8Vf{M@6%+QUEM;OQ$j zA2)v))3@1z+jS@<`__{;-Q$V|ww?izaj7|FPg{B>e%(r=%7$Zyr2AtlL%&v_Y21_OZ|zZq9#j*0bJXaL-o}50DPJ)rCu>>? zg$eN8@Fc4#=f4UPK9hJsANQ-RF!idm2@yz0F-AFpJPY6gFd(KxBm2RZ(JKe78BiQ7 zM2jfRmH|DHqpySc`cUT?5FRd1<3C_4^miCmVnFhVV_9&?E}-fQr;Y%B@0KO;bj9K=L19A@hC;c@pJ1!&OoOE61Xc zUiwdD`lZDGpeWy6rxX)MAnHR{O|w#l!x9*{&|IlZp`%Qx*UAHuK(X6 zU6}xigj>({<{8`1|E0P7y{dj%_OCp(Sv@(_X4q`PAZcUniTiJXb$q=`v!DUnZTPLx z75p0e*G8P4Q^;zW|FT*C0~0F0O5aDj3ikm&&9ryM#KX};rP6hGH5U*!1@ zS(NSH6yh?qo>jOj6LTASA>&oY8@mRFG3p%#6bVbK2IPo>n;RUc080F}fcW>(hiN1A z0qrwg33N_{jMp8Fs8^M}aJQ8X_k}PL4!})hbOG`2qmMMWGh@^)ROkN=<7HK6-9mN# zZ>rAvh3fp@RGkg~_SMP%Ou!}wC!)=OTs0$_Xt(#ngJhjM;ex_9ZsC2xiiewO*M07; zPNp~GE-k}hdY&e9@JU^GQdZLEm8)$sT-slsm&|~&(G}eV`AzZ9{b<*QiCkn)O9u4K z&^UVZ#-&wTb#0dpU~RLA)l;PXt-bx1s6Kk_3X@It{9BLjLkuU_-+wb8a?MwGyJ@nS z)v@|A2Go=>71h$=DN%cBo&Al*QpK`6XD6!GEBQpDZfouAa41l`xtjrb4}ES;cNH24 zEzC+AGk8Eh9=7-<{Rif&UU3dyXyRy02iU_Uv5dC8azJ{lW4x@Ru7*BA9FB<&G0eJZ z0!Yb+)1Qtv3soZ?k-u5?G+1J_C#CcGqmsGp%IPnQN(1|Zt4HI`43IMwFQOVN_ivjl zZERscPfh6$8tx=~qkRWkHRVye19u*yz8}~zQhFc*DcyKajTl6WzN{UQS=lX3-`z{K z0$Zc4?Vq$7pXe^fc&|zOY$8xrm1ju~`Ud{2 z44|eLBnI`#l+v}pV>h2cyVaDjR_E4s>aHzRVFnaIo#4);3D!(@Q~i58x&zT3UYatu z*gGCvbJx|8P})d4POt8$jM$Q1)$vV)0liwe`Au6k{b3B4sW@NuvLg5DY3d`oxJ-cJ z&@QN>v5#|A9lf%yy)weHdo1+^of~i&jMi>*yThB+V(^iEqJ(V)!GJiNnkJLp-`Wq2 zI^F_%+*GE~x){)xMJ4#JmI8hw!_ECG_eV&^oj97+%NgNB%`CZGS*i0L_t_x*@o<+P zh5Bk~OtfucQOTw(+pimkm&9O; zQ*-9$d)pEaAN@Bopdvx_(aQX5UBe;N3N=@qQaQR@<>a$a6t;k$2l$&xvMD)(*XibA2y5)Gzkk{+#t1o4PN{6-3se>P8Ct9b9^>;9+fW%mMnp z)ex5mKWi}>|4q7_w1B~zEo^kJqZcl|cOT#GYN%fu6T9gedvvjU(L;poMC4T~@?~dt z>k0a^H}z}pe!P@@(xvQyZC;J+qK%eyW9!=3hKDDu!}&E&oVZ2b9nOFfhA!X<9;4@k6lIrH(+7T6|gRRE&YAEmKvP?Gc6R_dqNl?6Z&zb0@JMyqK{m+bp(x``EyV+M( zmytnT<_lbKBPWas+_ZbCjO}nWTTLTXFXIn}(!_cb+#dMq3d1l+^IRK$&){`o!;2tr{;B4q2pBwn~o}>{3xaA?U0y^}dO2+5P9$v`kmexcFxY z)pl~1c5HfTqo|~W#Cm$XUDb0WKVwNn!JTgF193OxXzK$&|0Y^nTv}Q$zNr9pK9%~o zLZ=DeqI}Y`5v#i=>7v&6#2e3uoR_gnNP|wB?Hp_zHIqv!`H}SVkm2is^JdP`g!Fzh z>VdO*C9)?Hsy?J&cd$Qvqv*($olidm9F#f6)%N@`-mS;+^0nfcVWRtuPZO_;)_kb! zccIo~WhLJa?JCuHKcLQlkiAf=h+6+MsXs2Q4;1bUaQy?_S0>P)=yD?r(|whAnSQ5x z^67np^tZ|=IXdB-gvu%g6aq9|BK@hyyd1+ObNeQ(&S|75AXOkTHqk4O<4Q{65o&=2 ztt9-J?ZuKVRq93Ri^i%KArH6Q1Kap5nWCZBdj;01TnW*S+p_(z^@O^$eeNxTRoO@O zV!dNPrxo2W8YnVB&-~^v;Rd#b+_C-I2R4r&)Z1LTaJ@t4*y-BZSFWcVhj0S}yIb-i zCZFV24~;Z^OSAp-uDcR!oTh7kHphwjPOabJ2c^kO0)aJ>SZ<5p{8&84lD?5G+4qa5a<*3n^j*F!3K9`nx?|nTgY1{BYnLpb$ z8-BeMum04o7}*(PI7TShWSsC84LUT?z1pA1PmOz>S2IcdakKk@(2;wu?3YL4<2N}- zBzsoeak+W4*S@=Dil!=r_7-BSHukf@)UCRZvX;%{+lwz|_m z4W2KJQ4< zlIE9=UDAPS{qO5fhkdQ}jOdD#-X!+)iG#q+q4+>Qm&j47Jib=5{s2_ILpLl+xz z-TY_;Wf@hI)BA^S(Q%}^@6el&LA4W#bo<271bq3Q<$T)r({CgWGN9a#jZHyE0&vP7 zg}&^k?ys9#xiP@tRE8QCSyDWhdzUZ$Z>`5pQ1WEea;62vDqiPWgjqj7#6z3X}`*o zhPzS?viGYFb~2#LJ5lfR?Ng5v_m}!yxYGc7811a7z{@%)-P<@p14k@LU3ozMoN`QO zR>Zsg6DL38Ln+?khEesX6#iu5!W@rOJMC zPz>nAVW|CNvtGka(w0+)9XI=3+O&JM$9`T%SGyh0x0SN#qpQpFhkN2xg14YDb2_?Q z8IaJXm`_9LRn)mt7BNecD4ptkYDk80w`4XH+p4Vrw_8lp6b2D<(64Nmtd&l4)U%QkO| zR;w8r8Fl#|IZv0#fWTt}mC^M7aIn(7Pc8kyP8rWLRkp{aMSGF7=XvTS(cePWHe}&=)rbDpkvAq`$ksKWVZvvbC@2OR+Gw^lPOnF;>>} z=oKs0yubI=R_pOjQu9=?T!s_xz_6ps#Y68ktUg$udBU%^gkScOWR!ZGPl`a%)62L4 zu6hIIq;;}EB60`1-1?=TU0zaJRygm>eZ6Pg!FAr6E;Zs>*2>s()?M*-mG3i>ml*Xt zhw9sj@Z5@t)+oZau^OB7 zZ&d8p<_}4UV>z`hf?_|!)1~cKZOs-}lJze7?6Jh)QW3&Y!suD*NKaU;e6r<`TW#e) z997qFso+hfMbxv}%h$n8LCb`u!B4&Ye#%hK zLQ3MyLCnSb4la=YCEVb$&nmgcbM~H#R3M=^zLdUiCEm2WbnRtqLkB8pua(2gBx&?ONylRDg2SvxGCjSs@G}Vrkd)#9zH0fG6W?=iHUs$Nl+N!1C1GOXw z)%As|jjBdp)9K%Y;Ap*z@*V5NCAYkt9xub&ruPg#=?~%lkRvn|kd=|%XuUC@ zc6dBlj;_J>MXjy!#kcpCB1P*$S{*(}e2j02!tQUz8?AeHIbQz6Wu4BaK}Y%;v*hE& z^7w_gr+8?U1T|IBwugv8Wcnx3Ov%${&MF?Xdf`EprE!Z_zVyoxaJr*;xty;o*VWtc zk=MC6gUEy3kWWhPx*rW1bxv+~33;zXjFLyXKaMMTWfwL-hX>~2AM_-^{RNaZHbXxB zW#O{XP?zshZui`IUSuCRd+*jGJClman3S;S?S|^5O`|*Bwo7uXw!gJ?aF^8-t|30P1r+P@iiSVbOLov0P^dlor9LoJj1(9Z`cd9Lu}o2MZ6x(_QN62% zhPTXPTGft=OD(ov%zo_hz}-Ti+siyukgpQokyl#RUai{yv@&r-cbumuzOo}pt7#-5 zt%rK1=BYsd@m5ANN^;QK#wQ@c^6`^b6|TymE_cgP`+GY4>m04O53{dJe6>l{uw#^~ zeM)Yenhx$c(OzI`A`z5E*CQ8oR^dr~j!Q;Q!BG$4%bFI>SH*KA`%`N;T#;ehg2%73 zgPqJnmADT#NwWy+hi z#&7s;6pP((6??5?mzx${+T!RdbM%G4n$u6L_tq{!c~af+xLo%sKl*{5XLq*O*$2`K zPi-2ie3|$GYiH4Mr3`)EOJi(Fzys^SFU2_$`J>nC61zLs)=>MmzO7bm{^}!vc}c= z***+MWq+)=bqDo5eS$wXo<8-*nte1c)eO{+$Z<7Q9slk~zYBxo9zM4aEendyb#7yT2Y) zQN$(jl!Te?y_RH0seilV3izaAgPF(uEduE!xpW82@J)ji<=!^hR8g8&ZEr`V8tNdd z$X-cMA%(}CJ*?^sMTM#6jvtUIT3aIIUoMfp9jKVBZp^XtYfP!`DEV2VynlEk*vFgr zW4N%Rv}1SHl;2dl3V0OyvA18QYjjD~ovZmr94=gX@b$<^!Huf%YYak0QV^@X+G6PE zpp4JGL;i#9=M9o^)N~q0WH4Fq^E(r-XY@TQ`Lo8W-X$j~5DzcI>~K3;f6u)l_siP- ziRy8e`U5WBcXO*Zflvju2GL%xqNBeI4kmN=IDD$1J2zG_AoVFII&R+-f9-Xlska7` zN~@BI39WCHqt{nYnc~+(p1W3(z+1T7ZncDE=CS9MBrX36FqrM?KcpY@m;sR_(m`FO zJ2(`o;~0<`C|j}g$CXNosI>5^mSx%9y=CPew3nvb$oGGQ-($hQoqWvbEQ2$ouTovv$%L)sR1R!Un+UM`*`k@Y@11|T65F`jK1wU+@%`) za@yU%>_H79fVi*U{ZxzaBye|$6j z`ewZ0dv26#+y>pp(ec)F`749pj>Lqcoeq9ne#tk#=9QDcH zOA%_IGt%kIBmWLz>2Hdt_Zbv@{MWlZi|*xK$?8?@=-ocL-Tv$Kg2#P$E+6L&A=UDS zWi4EDG_LeG)ZX1U&QUTld0SzlMB&6{>Rqcb1JAVfBZnNjZg|Pwt3+CUF#{7Reu_6l zi|s5_&o8c)=-m6(LC#9a(XHmoE`8bOs-Yg~K~Gd#u8Q10Le1czyP&$d?J9=%G`TI` z`s#{w$>GU$bryP$@2&h}%eFPkdIFV}7xiQd2C15ghB}G`YFMzDiQtA+lBa^XE2?AE z1@AypDv8Z}Ll=pckKUCav8$d{%@Atgq^AGqT}_Gbd*rZ@b4OomaRZlm)?-KK+OM(I z*4wOCA0pMCL~6-?SbNroFSD)XZG%eRM%mH_gPle#d#W#fx-oF>+zR^}?+O;Dj}*(N zKabh&laa7&xq-E=jzPgK8PUflUvG@fZwwVr@;$vYw36#S(%bsh#7QIdn?CGYyIA(Zo!0cd_vUy`G*wU?i|&;OYoJIPZs*u87tx3)d5iE0Nf z=Q{;`u6j9?)S9&A%V%**Q;WPMRoufP6NDrA7vCu+UZ1*cpmqxDQy7b6Ktc4Fm3&JJ zI^XDvUJMv7(v)!h{-M*~-MPb2Tiwt?BPTsOEU~4&O(lIm997%Rk-Wr_0bSq%PdKmQ z&63VPdFWT|R_lIW(j+M^lkes*wb;f%z9<1zSZw`7ram#-z}kc>HoJ4*kkPlsvTuL& zE7_Us-xdGyT``=-X|KP849HMm3` zIJm|$w(MqnY^(90%NvLK6X2OQQL1l7cI7LBR`$ma=JLsKw!N}{-NdoEsovSDSbdv`L5j);cZcHv-C9>)Ab36= zYDmm!np&y2hr7Fzu&v#f~%{EmHlw2Q#I#?wKekBQ3-lY zy9JKi6E~S^lMukGT1)jjUmQRvVNpyjy$NO(E4tLWorW8)3~6TB;-S~n3&a6 zp{}`tpoA{L;-Yb}b9Pd0U6;wTwYnjn+`LsvZWohP%-G+0Bfn^7w;bexWGHH_`dHIw z`~Fqd45%Y;AZ~OW(KJB47*lorSc7g@6ERHsG5(}-#EXXV5+SF0pY5w8{||5P70}cc zb&cY&a6}Oi5UEiSkRT#RkqAV@fPi#DFG?pg>7A$uNGJiM2q>YKgx)(ULg>9$>AiPS zxI5?nAMe}!zWbb=ow?SUbFDe%7<0wHl>6i6;~7QjWNV(hDJQMIEzX+tyriGenqe;e zmU~(s-XQpLEci4u%!R6b5;`jdPLeYO35IIKy5O7?YTJKA?^T5Ut^ftTS3P}wYMIS) zH~BMdVE^+9H0!)ERn*9K`e_23*9DwVcf zJZX1I=HGL_a>^^c!K$X_P7G3(nM)xxWC_`q35ygI=X7Vys}`A2Gnzsirv22z+fcsR z?kZJN*xhgDsRh9-RVj(zIvYHROoxm`h1-G4_`6po{iL>@r=g5(ZOjHv%8tkbivHbY z!`6DyY#DavRLrNBZ3*5{BZGPcxco4;rR7P&%S&-yX@Br>?UqhO4;Fs*HOa^4;|g1{ z$J#X#X}o6fnsoc`FWlrQp`r9^G!7sg`JB?9u|<4s1)dN z&8bIC>L*r}UqAcI7cQqoH(q_3G5!a8@jfZ`5nPEwpertsg{AfOUBuD-0RM!m5nB+9 zdH{YP09npYj!)Sf5zJ-H&rCURSS0o|n;bL;%V93gkc_HsL$A#1vnD(+*JqCv+0mYQ zL2`N(YkP}rH@6o^lS@544EQ`1fl$2KjC8yavN$1lpQBd@y@=Uyz5DodEU%`qZuG7I zDK8T&1!NQPu_mPX@l-dPWsjQ#Mf52lqfuD`0;|g=;aoB8N6W_V_^{yhV=-w6!g?Xj zCcbk=o>3`x4C{M8P6RGzs;~CXzK`F-i9lcto`HUg(w%gt4mHOPa7bSRHXHf@fQwiW z>F`Y&Jt&n`3XP~0lq{U1yXo~VB$2Kfy#->qp?vq2=FK(B-Jn4MpV0JpkJm9am2aUL zuIE%i`R7zDs~Yw?w-6U1{q-BWDDQgS>Kia65q19^-`|vQ3(rQ=XW5Bbk6hap6@=-o z=l86O)X}9J8SorFz1_Qu1(J%|Q_R`L^k)^%MrzEt8{AA5pexdm16GyY&Z*`dQr>qJ z{?XD|6e{9LcmQ#exh;pyDQaA`q0V?;IX}*4X(Qtimw~*)(^v`GoesCJIAJK4Bu3t% z+u(RMU_Z{4hON1vn`%Dt{I#_WlR3EMo{?5ecdPNeJi5UbXQMuXapW<6#&}xZ1GPb9 zJds22jG9-!1v?Y0tA?CLK$`~05b8i*PsnS=SF|lNO-g#A&#r7(v}r%k%E_9nsim`t zfA4NOdE(B4&92ZRHT_(@{yP(IKr_mk5mH6O*QD^YK3m!< z>Yy}Qq?A5#{@xi6Vf!@7SAM;^>$3FWWbIt>YO=m{g)t914;Y)1`^0R1l2iPTP7l|a z;p0~{Ci${2C5{?6^%Aw|gha_aDO{wDTK{I_NY&2vl)M*6G3p~vTY{UbIwAhFV(CbF z_}6j;`lY>8;p4eHp8d>Cib>NWk00iB4&R13qrs$v2S0b zcnc5uH|4k{WLNQI>F^F7om1hx`48(us!K)p8(zwHm?QWR+_^dV9q^^Sr-Q>E{-LQU zCd$>+zqotjvPtEKe`_==vsBXD#1%JF>%=*QOBtl(chWhH!3pztt+`@7%pL;#b5J}j zpKBv{XAN`~N^aO3sbO8;^GQTV)s`ci%b!h7NxD7nDHgv8+BMJ0tFBrmqJr(-^81ey zNkfLcgk$5CitVl6Q_q8+bNfT07SrPrlUOPqW`3Dw7r31+H#9kO5zo3$T`E@etvbLxmXr{W38k6!X;Cu8AWt%BS1!ft|t}oL((c5 z9r_^4PFh}SPK0ki8@Ehp&YrUtmS`fF-gt4H`7Ji$fz(KmBX!6p*thx16d|Y)G%}$g zn$vtv<>eu2wR7_HZPER&w6aDS+9pI~8!bhcOYNaGSJAT2u?dk%s1lEG;Sdm^zaFO_ zk;D?CKMOO0>B!1fsP2M^-n}=F?f3&IMQ{8P4i`I0Oibr5NI#iOa!!1Bw5S64O89C( zJ)YQC+3<({NCqgFwKXhnom2fayq~@$0Ek9Ykk&uy>nhpoX-M@oVk%3xcy6Nle4B>( zPK?Pf0Rtl)J^2JO^Vc+d`Beb6))e;uf-y;O)J%|y zeHSn!V{7)SX!#6R5b{yE?piyF7aK=ci_ONS0X9D-%pY8H1kx_<#mR$cMd%mvwTJw4 zM4Bvo#6tx2-9*Bf%zuh&70xxQRTH5P3vMdigvVT;aVKVVcNkl(j*2S&1SD)x9V4gp~{1pCov@=72o)C2zKj!yi zOWFSsG6r)>Y3@ju{nWioD`xvo`ETC{RzrUzwPwWE9@S_<@hg`*SctF;fwl`qR+m3H zr+N-No<^#B3io0ka*eRD%xwv?6Ph!}YiN4fz{L9x%;y!}J_CHWpY^Mo^>_6i*@&Pl za60uD^?v#b?6>}qB{2K{O?VkgqT_6I`-A}-_v2e&YwiLxtz)sKHw0|b09L*U!ZZUu zqDa3H>|Y7d?UO zny)Ax>Nh(seB+i(%FPbCb1!>B&!~Awk2Mj{ysUvXZCAwYmss&%KzjzC6j+ z+gMu09VXBMHUe#Ba8#&r6lNQ}COtD++qae;J0=!!hBpVV-pdk#L5BJYV5`>VAD6V^ zxbDA>_+=z>`zV&HvDl5DKd+IeaPJo=UMXnV(X-4A^_u+ivj0#n^xKLBs!&Ll-NryR zyknrfL-;Wwn#RjK?3#Ww7M}gd)!pa;o{Mh9@7s^*&6cE&*UKiOGuxJ7(CM08RJ-E0 zElw^H=PZzJ6kyuClO!j^d>VA9e~de~2E*W&n)qej(oU_G@LztVn7;Nd_G9@6&H+Do zz>}AIFJ$&vzaDY$lEsI^1Lyg6j3we1tdVi4sSVvcmMxgdRn+vBi8I zshQq)T4YvduSeR6`?-pba1t?oh1PnV`6x)#;= zgO^17i=e|5tkkiNs!_Fv3#kQCkd_Tvo|t&*+^?zD2F5rVuPvka zQ|y~o`7hV_RJF@dA3<+HQE8-aDW^BksYUvwQZ>s%5&0$-$R^GGHNKNWWj%Qg$>&3* zQT=^G^AWrP749M@A->h3g|gh-xBG$~j<6|C|I78ltXFSQC$S%FGJWel%~SWe@|138 zIr;30!zK3p%~9RdtMYOiAAM)t)ZgL{_OSJ z%oejG8Zdb8hh}V6vso9TTawNAM_#OVdmhaH%i9n`gHLNFEC*Fk)+0=31awt}KN0gl zcr?)PehKJ{`1^e47m`n#KVJEk)1^Gzbjnow-n2v#r&MJvL=&sG*_hZ0lV1GUJ1AhC z);{kN)7Nps#lf5>-R+Y*?YwTH#2@%o&Fj>CTl=~S*TuuxzN_+__Rv5XJWMf z@{Inik+(G&h(AGIy+aJ{QQ`li_DQAS_eOovm}gswkE#HNX}^{z=Svh^WbBQ-Vl!hK ztvzE!&SwQ>9rmavtlX#rCm6CxboD^-o=6o=E4bxQFNM! zM*mI^y5j#|`M>|Ktvvsy=J5YVM+u7A*1>J6HZk3*mZA8lUu2^Ge%OU7VfBmm-zJ*& zc)zwYi<6>Z87rrjEBRQRqgmcf0T>W~cw1kPD15}w(v|eV27ul{qtk=JE_=B1X zRrmFg_aS+Wu||nc^`Hmt;0z(wx=Rza^btYANkQq4hE&Vl+1`ZT*RcPtBK>92`2bmQ z=!&#bSkKP?c1z?cyXm~L?Krj}Amp5ikNo9g04KUT_s3hgwClt*&$YvM`k+;Wq?YU5 zLlYDE&l$lUOMg?^tk$rLZEB`_H_9SCU)`+tw-q#*HB*fUA2YXMH!_dXkaC8|WeO`E zt90tZ09cNZ#C+Q^*Y(IRDV>nVM;`k}umPE@D#ANP4aRj)+&V#(Hinj;B@ z4Z{cX~le80R=}}8kb%Vf2Dod78#Mb3NBlFqG7==lDF5vEkaWRGcXY} zRJ|xN@Nd4!P5{|V!`~9+{E$KF(lMuLW#zZbx+{A4KlmU&+r>r0iVKfu<>9JHWCx>w zsLuJcR{PCz17)4atmyO$l`DqB=Bu_=X{cu<2PIjE(re+Lb*6DJNztpb4`4pOHa5LX z$3#7KZlxE`!g|Ita#zr29iIBpG7N%|1@hY0c4tn*T!RtXvK7a{N%>F9Ywn?Zr!1as zV#8v}|A}CI=5ZnGqctKc50$E=^@~QD$SJ>v_lp=j$0v%mc>fGSbj}3VLpLq4Qvpn44qK-0t$o70-_I^vIvX*vwJR>PC3bz0x+E*aX z0yVE50DNoq6)q4o1ew5<>L2{p{>&z4b=`SzsG0`Gcs-XAQE`Xo zW-DCe{^j})SIFa}zZrvnZk|>5OOL~o_OjtS+Ic5@D=8yKMPxm)(PKV7p+S*+kv<*R zt(S$1ol0TjuB*3F?+rta^V%eBS7+bJIyRpi7fY7Vs>NAkUuLByOvX^m%E%fPyZ0$5 zAKaBks^Ka;ap`?NYQjT?9_(pJlQ-@21F_i=(XggDYj8_@14%0v+%%Vpu!cM7B6LE7d zg520WZ<-tx+F2bj^t$_-CcZpl`FIMK-?Y~N9b?^${LsYT(%MH|Z%#UUEEX%=p}djV z=}nuYkLq8>qs+*&#oI@H4*9J%$M=U=5h>?XmFx;?mKWeuG&fAg^XAlZ^@2N(&}~2^ zC?L(ovB3NpH~)%Hqpj8Hf#&n4CC3HwzHqzK)nhudBYP=-dFE)`^$jeN;rI%?wWW4(a`D#^)+q5UnPnGoeGkf>7JntDR`|hO;&;8gjRFlF{ zl3|Au{1PGLXL?#%DlWa-+^Nyx_~5J7dmDM_%6n9e49G!)|&^E2?A>cd@iKcLR& z=jgVDGNyCzYnjNNDzbQT3mI>o-S!TFYYa9oHnE63=vUh%zNUXkt2#+R{%v*}H(sU- zDI{h8GR5)b7Csi!gSM^CW~33;#@X{75Jl|nAS!3jqG&91(63$`0GuDEM>b?&k$(AM ziAKL}8~TxVCXu@iSv}^~wp3{ZF#mM0_1wWZRaAukHu(|~4SXZOa7nDDzR2y{*|*)j z1^;0?#~B@DOrOTCjI11VQHj*r=LC1$qg3+Ea^AdQi~CgJtJUv?G=*e@gh)J*pB^TC zVXoW-oyt+v+ggl6edf+CI)e$O;m&SM2U%4M4M%aEm+84e&#BZ8D5ZdOc^J1LT&vdc zs*!qhw17IPUJ9-Z_Y>zgQXtE|5cUP+@YEEDj@N=EkB@co9`_VxppqeBfl@adDj9UH zC^4xUD75zthXEPGSMnK!1bAX{&pnn_M{i*t;~Ar2Pa{~>k|m~EmD4uAFM$BJL+i@l z6Cl?er&Ukpfj7$>ccM@z{qEukUF*!8@iHHkhwqK~q?Z!i(=t=j7=0%bNg&l6(m7Qj zU~LJ}Ybrti8-In|Li0QDI!p!1{5e$A&?za-7tv2wmqFmce~+^kprr>6MF2Z1zJ8Z| zwogI6TGd^pbJ6v}cXC!&OGHNX6S9{^%FL4*&4o|6kMvif`!Bx*pGv6%i*GCFB_ z(Luw)8Vi0hhREgTLpVbnjTB%ya+jG$k@RT|(zU>9b*<)-0O$>x?N|_+_*x|9V4Ndg zvCl?RzyBVD$7Z9B|7A47nh&O#V(GkevDqY^iU|JkQZ$?%49g7L^w-SOB2p ze&(+&@FCQyImSY|9aP5*@Lzz@DZDkA?GE)#u`PB+l@H3wMH;ufYuP^IS{INZiO`aN zYAVp6Sbf1c%sR3HSnWQ$$!A^_&D>0KE)F_=gCZh$F1RMQz3Ap!`O)vzZDVc*TMm?3 z!Gp!pLs5}EjRgyl@)AvD*h0NP?g!`s@~s^er5L4O-*;;%H^+KqF*7lHD|a@IrD1(T z5yzlCQn|beR0cwTVZaoOowUlVM z#7oPhkRv1d8jp;bU*r2YK-7*X_%dA+OxEz9M8@_5TFjql!2g-!CPWykuwnDd6;lFl z$^h;$2(g1kPu1r>V&tkDW}`(eXDlRbEoq(9m&DJlSyG=?PhkFj9+`2}PV&;6uK zHqWUhD64tz%LY4nurRH2mVY6=bq?WsuzibEG80Eo0{rjx9`dh+DBvNk9%92Af80$p z9PPJ_%6Cp^n?wFA{7K*g@hb=B09z5#2mU#YumxMU2V(L)#e&OCjshJYT4wp3y%Y_z zntKKZekNswZmsdHXi@R|pY#Ddr(ko^In`Gt{RJLXuP6zk>eHuGh9ve##tQRj= zk<{$bF)6JLaUpEeYrc-{+?AD$nN-JD36(JpzIlsEMtQP&K(g=dZ$5}~@7K;HJV8#Y zS`%YjQy&*_{T(8>0PFy$3oRc|2>s!I_zOel=j)u=tyZA@jQH~At&P+<%wqwC5-$8F6T;rk3YXWb&G8ar3A5!PRQXXDZ29 z1AMETN-EnY7yRpf->QZivTm2GxBAL`I5Kc>oMfXcak@kHT&eV6Zg-6MadZ5+Nu_(i zU_rKSHinsfNTQRd0C&UJ%YiQ6)@X=kZK?WFC!DwN;XA>|v2u&KApes6U-JF;jUBQ@QL8>BF>bZNK}y>_eexMV#R>x6MG+Z$IfL z=+dOa81DP2ar%uL>$+(_F-k3re1IU1<;b5^9qLxcl;&247I}pY>|H~T4NV?aS|9c} zZ9?qlhY1a#u6C23S#|E^FC+>w2)DAgMrpNO!e+yiTC@ZoZRHhQq-C%55g&XZoqDxj z_yY9Z9ChNnPIGVn_!3)DINN%~`=_6@PR*UDpY`m_Q>RRL*pD~VY(VUn192h*Rp+u^ zDoXubUUJ~D;runHhocxOF z>B7}an?B_~w?~{jHCod4&Df})I_Snx_F%A(GJJ;JV_e{WKyPW}aLOS^KzVt%Hb zKiz5}I}&#~lFqiN^ZI}M=7`lsU|%))U%%bp-K3tyufO{&Ea|Z`C|(Xu4L1n<9Ss0FZozlhuCN=xE_~gJz}j3JVD{q$d39 zR#M^0coU<^?bvgwaAcA9bpOY)_DP?{IOK0+yaIHoe9t&N&08_pcGG+O`)%8DXZp>v zun4g$sFDB+`zl0cuA(=JZ@3@`oT*nfBqx&%XLZaaaGGs)>vlr1T{-PL*p0w4bWH)-hk~TS{VqzmlHQckvnOCDGDw zN&zRkBgD2rd|B_O4P?IfIOsRN?-#o)uG0&LELdVo;s?NWNTX^X(4zN4D%GKz9sT3cc7@=G*Lz z)rRYER%w!v%e{>iz^UoK-D6?#M-cCOMHu^UTGBpp>`k&W&}FD<=MdioT!ij4IZn9wOc z+kUPdS1^5`8km)f&HR+aC8MsXS(RF@4)r*4Gvg)Na$3_3|M5eP9HnPL?(El&I2=x# zQ@KCqcG5#lGVh%3>aot$=4MY4ZdIbdbplLxY?m8aiqLz>{=-+16l@A;iD=?0 z7|a)rS@OvYFy)FT%2e%^rCL8X!wT58pXj8gOu$=)V$P}dDxnk*=|3^0s~i$I#i3JC z(myY5r*>L<(WTFfR$1jBr|?QiA(L!k8X*3Zy&P6p2qct18i}kTX9F9UOmg=|ch7XK zB06LDSyZji&|u1ZalfhcQf`Yz;i=Ur#}@+lI^2s1;kj zmAl*Yts31wns0@?L?>yMiqtf+tFtv8I0?g85XbXRaI0&26IBdPV%xB$29 za$U|=`m*coqKhO7*bYfndXDLm4eeaWPU{-fRv#SEHg6G&PW)!xu+z)-@elxF9~;*v z)&Ve<-PLi;GQDMCJ}x4%%+%zjIKFwE5@$fQK2%q{I$yq*<VweS-^z$xf`YrA`w#l<)(&XjH-nJW=i zoy)~S-`$i=hlj9zK-Q^Vc#%ccUmmoFZYBZGQ)~DJPaa6HdxSDn+6tX~SC(X|b@qi$ z&X#)BNNV);Zq*I(W`vOiRY@=P?@)dq^Q3Q7ZNAp*T9rqHoc?xgR_k1GwOy=~-H?zu zE%()Q_2UlWbIb`H$&nI25#1V!kf({kh^(>SBaRYSo=yv!bX;ziigb4&F%Ph(`Og&c zF9(!(IfD`bY<15)91i3DNpjpAS9}yF7nh7-QC4_R*Q5YUUM#$P&_r&y^JNnR%jyLjd)fWp0FchF2f*0>`6ji)fx{g$AyR6ou$P^2U#E_i z>D~z|N+0q)u5-%M)amfsFB2n^OzWT*HxXWy6p;I37@=H$+sQQR&*B=kuF*^>n!bM? z%fmufOxQP)HHd0QRx?CGci7NJ)4;M?F``kEqSg20H3dXzB|c$T*weD&5VncnGvMNh z6g%%E(tlSie!WoTtTo1-fFJCivvH~{%^Zs8xEWfZP);?FM?8pjg$?NZEJfiPyv%PbgUTkM?Fm z?H0S8-giz}CV1qRQ}T?>q77fk0}$Mv+kI@Zg1|{f%m<*Q8pURPJHMvy*}hxUf+ab# zZ0?U-1u;8sp9~%j9%j%$6dSkN+RYkH=uY8(De#;(dR?kEa)N1;STWZ%TeFqUPedpn zY;#t358#Yim<87ux9U27O(#p8jaSQGDFqkt5=i5G76`;RsysC2`db}~77;6BLpuz! zU4)T!ZH2HeG)a`p973}IHgbZ#{BX|0!JeBm6Cj?-UXZ|0kXjjfJfdOWV!a)-M1EUJDPQfbbN|-(!(Ea8IG8i`*m?ESLX%nNCDnm z-F-yzFt!A{b7>AQ0^PsmciwPYNWmXV$Ju8mUTG-Z&IyvnLoGh518BLOH-OYwbF5L( z!?4xVwA>CxRF>SFbm(25=~vS( zqg{5n{`CWLKSZsv(rK1gDEaLW>g$1wJ~v7?2yE(?sl66zFE4HnHK8gzGcM(6V6#u9B2L3nD%iC*FktY zpvzJQWY*%Rx`!3h$2>!49pt@q;*VR>9jC>6KIMa|wbBYlFxVAsy|>8$^gJ``d9E$r z``c8$s&DwpO@6N6u+h8!Db>=;0`mQ9tHG6t%87WfqbI43f0)%sK>^GC3YFI;KH!|( zH*m{1Xir+INmPm`lSJaGvV|K=COIozP*W$mO?&WzZNrB4Fi`(us(C>~s&6_fK!l}a zYmRufM_HuuD}$QTHXxD>N_?8KRYfsh`?u~~V+hPoOU=7@GW~3nwcXp~zY;VL&YRcI z-QBw1@`#5n4{MgxB?}+%F_#H1#LkmCwK4V7G&6^<6*4F#K}8dk$>Un_zi7W^g{qQ6 zAXm6Od$pmWnKiM_!3EJHCBR{Kg4GWSzItUI-xHaRO0>cC{-9+u;usloSg(++p76YN zZ}&xxRJBvq^6-H$@&eadUnq1>YgZ$3o)r zryig}CkwzA=H-~E_wY-N(jg!_N6D)z%hih{I;;;s%(K|{qOilBDz$jh4Abk(?ajtNKnkel@{|8%|Yx+Wmi%5Nh7L@I8oE0}+a_8N@ zxap61`iRY-#(OQjd^3t1dPnFr#BYh2y}aEAGp%laZB{h7EA_!w}cr^@q{}L;F6gZlJ?$AP)a0_5K4$ zVDD=@|KGkN?h;v6tDO0bJGZIQoXCVX;?r@_E5$^y$gc+j^Kw9wrUl`La(MsO-#pOL z%!#+u@5>57O!AxfSG@KYct+R9<71v+T(($EuOS8xTn`66*<04c+(o{W`q)3CT(>Aq z1GM9V51v&ge5?70p*0{%(N86O${&*&8<*f)MtK`XcrYj7m6g{c{_(lyKab1hCVJ&& zr_?o?3`=EB-m|JIxj0LY!~?lNinrMK9X36kkIw*_3bb*k(b(gihUNTya(pua60)!s zR=6`dWfLQ6H@1N=w_fATgyO+`h}=N|1Owf6ml=I3rmg?Q5)yseclcdC~kINd6=?<6!qWQ^##~@opWD2mu_d$LxtgO91oUx2~*5<2Kr1Z#56jSdrj^4(#UTA2txrvB1v25I@B;Kqjob+%(Nzm!Pzpf#x{+TJE zJb%^x#^IR3givKgmMsn;e5iLeGwb;$cLr*v3{%Tm!iGLI2rvxi%q*8@GO-1WO21a) z-C_4j3H|F`scLdc?mrU@9*c5KNWe;~#=dO0{n03) z2_Y~2+|$H)?)b+Qo=695r>K3;PR%&sBCJZRXG~f3=$MR20$|CC@`iFi3Bk;)ty=7J zpSIQ9@68Rd-h#C5@6C|Gce=yF_G@4W&;5wHK5hNdEm-S!6JWbkFwQ=i|1_>?$zRJ+ z=HORebF`(yCd&DKj<4v%`<|?x9)=}x!fapUN<#^&8IYJFi_L(sanG9ul3v|IypYmz@fhl)y#9 zvzPQ~Dyzn&P2Y)1Xg9+-NaT0@-SYwq0%(7SjVuZnmI5?JNUOme9uG~_GF&LxHGm>4 z5QyT~I~n=dHn_4@jCaFYK?RP~GR!9qz`xAQOi4<1xZwDPLtEF}z4?ZUp%}ljMrG{% z?2POn^!?Y=8#v_);w^sY$^COGEi#ZB<_WBaO@D)IwgvTAu6f+HW#Sgf=+LrgtTVPV zV?$QGGcoxp{)ifcrl7fu1qnXWiQ*B5+i}Ud>y48ZT3Rm>_YGW(6n@paHB%oj-=^d| zl4IDwiEm$?C_IQ^5{2K-_!hjekOLk}loM-bWdj|5C3yl*4TZRBkB<4+=0B+qsV5Jb zS4L$MFw?gEWzChJSU)4j_3G&oDU&C^QL(R@^w`MQ(6nAiJ^ zrPQaHy5y^hh?N5EIt;)FQuw8n-xfQrB$wR?eOOka1g#46{i3Pv+P0oLOb=#|NZ=+J zr)AB^Qbsf4YPUI1@8siB42j6cIy)YXeOI>Ryr6d)0omYth{eIK=eCHI^1Q8B*Vlf(2-RNe9jhqm>+ zte-;$)wZ@dV0S684)T`fypsrFm_6j00W6jU5J<-Xde(Tq^6jJlyvk4zFL_&ux$<7; zf_Q|u_m*E_HUGoizIhvPE%izkDUqzRjDcCfO97}$9bda^I?89!= zCqF`#2PP@i2P;NvW$j@7o>3w-ATRT`Wu*#d7VA5>j;Qt>)Hn^|+E?-dvldA8gqmDU z*=93Vlj}Cll3Q_8KTxMO$|72WJqC%n@SK9|G~SJ_%l{sbKAJi9Z~_i3*2%d10T1Jiej6<#~bMwQ^ z_`&=(Hhd|BL}BTlsPQ@Hcg`3K^2vW>xK-Uzqpl-3e4_Gb${u?B)!H=NK~O3*2iG|u zpgK;|J_&yh{Zl;jp*P6|PToGJN|L68*XO*Xdtwf84T)eo`Y&2A0jA4$Zff-oC9>XC zATu2wf%ZZVF3k`D0ONMSGVf0Bd*RpR_p=U{9)>^Gpm~QZDaQ}5`yf>TW1rjWKPpft z?z31k&+cwB(RzQXIKC!nlbt12-L0dY!}Dq8aN-Q`|Fxc)Woy;S9fAj#jAiFVrHWMFQkcHK0dDnP)T^%`Puuk!Qa)p8Cfz2VGRA~ z?(Vix3IcsOt)`FxLAbg}vBe*GZuneo*T$(3OMSc=tD75yJbNVKucZ!l}qlcRvj_> z+YA2nthP>{^uY)OW=F&eMl{=ZewU~(RyrQ4_7TTP$P%SX5D175vgW`48i;>A!7v{& z+%=!k0sEHKVS)9So>BxO6vL)xf1|+cfUxV+uo?as(RiC~k`;YgO0lf5+{euINN&e3 z)g$DLKap*!hm@g*PI5$*c&pNdO+PP) zNKC8brXEw1jN#(0ei|zxOBOKT397sohPMw-2lOOB-SNG0@bVeu#EU&LX>BKM)|Bs!wzOR)&o5wxxF^qdL=_=Kb{5;vjleudX>tDvuC zj;DD6k(D!^z}+4;jle~{7`zw0pU!iE2s)x5`?Zee24xj=`kHS`eBvr9g82;$RQ&Pu z_j0>{`%kEbhr+mT=WE^Rp!hmAW7;5{?fc|Jcj0AGWwD8z{5A`x>clndcp}!9cM7PC zEP}S)==TC~1o-$3;378!)+YX9LR_sBdy97sqAH$QSv6Gre#zK{j0L(8(k?J7gR5Yp zC*=~7BcoOppEPVVAed^xO-ID9Bgx(wGTe*#j4~kJb@0H`iu86ZncG*AnD}KFgIH(E zz8gCIdaxh^3it)QrZ;{#sYxIPxBlJOr$}7e%!;EUJiDu0d$j{@miob><-3&MWjDVT zkwA983m8f~tXQ8m)J6!bmpeb5D}J_Fcw~QLG$Qdwak=KKwG-6Ows%a1eD9o!s$l~t z;B1nBK&)x})tT>aHCx$i*rJh(!>yAcKr4xbYjj?}PKVgfKMdM?`BLD{A(`^%;RVf?89;k(5AD7(*jL6$z5^|;RQo2Nk{_q9PTC#vF#vryk$y_@XdLh0 zVeDyMoHmGsdSB614mqENUU#(0OB68W_GypUNHzf1L7yM8WYZsEn7uac~*5!7|1*P(48h)*(Of9^M!~Vk;pcplfr7 zWv<9n{O*fLcuPcTC%@(hq)IKF!rBcdtJbfvM3GpH0rD{Wx|1XzwM^--+A6@GVkzve6R zf}FIe(kl8QK}}9MsaZ6NcUM_tF00nP*x=UvNTzTv>E7r}Ib#Kr2-`u8g%BlQmpIj6Uh z=MAMSrzU>j8?7tydB$6oo{Sz%N=S0vzV2p1q-!GOJG@wYSo~Le$3gyNz~`1L^J*>2 zSIo6QY=`UvJyc#ZatDjue%Pk*OH0s*Y|_>J!uj7y&@APccDxo%<}J^Sc=@{6*rxNK zANIy37Z-A-droy@e!wvoxaXDgzAg1w$*o z@sktI3M2hsGG_co+2fR&cpa#*#T4cMFC2cnzq#2}ef)T1)WC&HK5-n72+ys8onlalED+Eww29HVvBf1R=;{q9vrW7*moD1 zki5?5hY!~Sk=Vb;=%N3**k*be9Q|vyx*A6kR`z)v7ClPs>=#2ba~f`4|AAmdur}7q z5+SHYHj~+8^y+)n1IjFf>|djnl@A)#3YU@`qw&Mng&nF#I=*q%DZujk4AV924H{tf zr-A*_>QAX_99IE>&U&l3PVCW`K4xAw&%WqT!tjSZxBbm5cQnvf+=_kjN6Qy*wb)I0{^bC~Y2C82= zxAYPDVA^+k0=dtL!Xayybq;2^Tyd6JuO!=3b36aIA+>oFV-LR zDtyqn&F`5hnn%y}4PoM+aG~9l^a);ms>spY=wn=K(XXVc6W?KJ>(l}c)#$1q@72^a zo-kh|wE=FsV?y+$EP~3A1=wlAIMX9W@1Zq@m;5))C-EB?+3HU?K~A3`gIVb=G!hH` zTY|sN@bEG-zhVJj1XzBT&or(iD}BrVd*Uss`UZ^ZA*ImUSG0a(aXh^c>#b7<1`Bz9 z|Ax)~|h3K?eJU=ChpSj4+FAQPi7E?;fb#vYj$D@hi2F?G7)-1hqenFlXiLw3~z9@fR4 zQ6|JS{BJt6{sH}aXfS%+!4aU!`j(6V5gmOd>qsw)g~6T-I5&8WZ(I}nkC-Ud z=n|EZGHAQhuhBs(7@?O{lznM(7`PCrqm|+0znt2CdMbgVQ4bcG);>JDr!~at!~$Uf zQX^VrfFoXG<}5sL# zv<=Ila55$SJjMKdm@3YGdpm?p)W&-(?8k~6GNCyqJKovsj-Ejp>k2Xo@(M3*t?#`^ zblfu_6;imL)$~#!wx>`TZe`yI7Y7IM8pPVoQT2FhOVSAF^R-OA0V$eyJQ{Qp$tomK z5ZlM<%B<#9DNNkB!9NXXm+c<|C^8$5N|3%{o;w@J09g<976{MpMqM}p?m#M^JK_YU zl=nS8GNT~ZZjwdtud~`<;x3%qB6qFf+q~@YWEgsv%jZHX;3mUw-gpux^`1R(jLdH9 z0FY($3#9+GNLqTai>r<)l;2JO=Pdkw`yfC{h8qt2>zmF_v4HwH)jev|TKm3PxA8JD zj^fcJH!4rXhpH+kgmg&Vx8jm4W}l2r4ZvYqRS*vR=PVJE-&gsG@+aOiTmB2c-+}#i zY6PBIjqjMf(S2k&J(l#9fUj6B@#Hw6S=eKICOMj)T8IE&V|R0FZs^YX>jE5PDYBNn zMuqLO#VpDb4SZrLJ$-&l%vYtK^GCN1&tE3D6jb%ywB9|1NuvL66=79Swxm`touKzO zE2W^VtHSwNUlRK2arJdK_wjsOI$_@U;ZLSA2?))=$=^_l$KrjPGVlZTo!mD-%w!kxOm4+Q)ZT^v_&8*x`}FFj%E+4$TlpyZ9ZN&&)akfprfOf9>0NeMiJ(LVXnJ=ePk{FlkJvcMy)QNNcm)70s8khS{*( zlOf83s6;{g{*)ECN!E2WHt;ufA}q7%sfPdBh^S6Y3ufKJRAWS6jdb>tUK4hW$V~uZ z)IB?rj&0qXyutNW-M%wIS8V|4^`ti4^qh*VtLI1;UE2j;ekwY;V_m#zLROZup#-0a z|LaY^kHxj9G>%eqr+t`~?o?*YyJoZCNv%!aDQ$sLc+8BCq2INzLMqHE5*Wf|pF*yx zN@~-FjY+*p!|J?1WsyC^U#*ut3J_pa5^;V=O8mp-ovRgWom~^YTl_z~ zef2|=ZTmL{avOj_NjMQ{5NSkYaw8%!YK#=7(nDI1a7;x(MvPX5l2RMpjYy1?95q5p zx|@ypUgLTHgy;MG%*D0qJkR4i@^gHS+X}q(6To8{ z(;@{UDwTIDRvcPX;i|fG?HatQTY1TR36Ds zo$Fh>orn#I>?e1SE$Shg4?}-POit}6U=`cvfJTi{PrI8@4h+XoQX|H4d7-U8K{+k6 zPSR7ZEjvzQS#dpm&zXeFigHtmWlgZN(KmqHH)Ogk)%sxxpf+yy3-HE>CEJ<~|D~%b zWS}Z4MwgYEH0c{(QOVpB;-e}lilX@T-W-10-|)zDTdHyc-`pEq%zha8q~Bn-{He2? zz2&`^_|wn<2%qLX^b><2F^0ki<9sC_407QI(?b-7??zp4TqMQ;s5OKYfTk9%9DrdO zqo7|BMfNvc+Oj%ky!HGdV({GgjVJ3;9s_YYC5@S(ZAO z0Dan+Els-H|w^8+;7 z|HA7{#~Okj3rR_>fj5>UPFhoZ|$JR)ntazpS`lg z;xjP8)zq&jUdtdCg&1?4%*r2`=_XfE@tOL{Dteb>WJpwL5UE$IjL}-+Zb^Zmt%zLC zwv19tc3}GE%h}O^Dgrp>b+3b+t56Jd>lgT^@!n3RLrhNMl@8)Z^-H;^1&Pib;DE7~ zjhGTt9Cf)>uQ%QB*h-*pQpV8n5>zaP48BhhsEervAU2*(^$|D+)AItd<{({2Kn< z=)n6U{8>Gss-Gg}t6KlV%yBN)G}0O*E<*(3w#@m#$m;O3t!;Z1*f*9Jq=fPQQ_TX> zJh2>0?W3H%zGC4p(HLv>u?x8R5^}fvvGiE5@7Y&bsrZhS)m-hEN`>vKE*J8ZVhwx0 zCQ3To^$h%=-!p`un?-#>6%^h86aW_^%<#)oCQ(n~kkfeMN8IIs=~(~(CL&W~+;d^{ zrbY^AST#R`n!CW(GV;;~Px@{If zN&oe=uc@Xs95rR~!eKX{l)Gq=MhkV9EIvx;Upm^T!QNwx7>~mD z72;)%wyd5YO77Macm`u`ds$ z;Tr;zTamOdjpzq;DOs8rA6-8tM7uau32iArnyj*Nvf6C!R%iSvD_%c6QO$$Cb?UJ* z<5c+(b$Og?VqtX0eA}_(^XQI@EEis0?PDHQdM1@Y81j*K;T&gGF%`OnvSWN$aDz?v-X7aD~Fnsu^&zP4179sYHV`J9cC*mLK0}J(?RKkqgPSU`zE}+3vg-6Y+ zx#HHl#uFRF454z{;dq8h`z7V&#t2qbBeS<2`-6Eva-3#{7)1&b-hXzr-L8yxtGs?@ z-my68xi}BRNY5B%R!#~0<$*jf zT4o=r8d-4Saj`Jht*{31C<#G(6;9n;GL6%Z2gtbM_h>Z=|K9 z<_U6TQuQ&1pnjTROk)@!TRFIdS6~WVSvkfjTZ0Bu9;_7?%#=JIBXDIoz4|bK(UN(p z;^|+y%?neuEG2Q$NCG!)@AAttM8(lvnuzR=XQhZRRD_TJbO!bd5gByIeAbw>ZNMx~ z0iIh_Dn0z?1^#Q2n116PA>kCNU;U_(tsayFxED4)nYhf1toMBK<4sD1KBABv{e-&( z^>qFcv{0^p?>>Fpn2(B@PNDj3lPcUowg|pH(4c!yCa``L+|kw_!Ol+0)-GC9xv`j- z@zlgbL#?;3T3tFsVE@5U2ZID7l=`yj?_JWlPl>tGTz}H@bb3R@*pMBPv8mtR^#?TD z5<@SFO0ERY{AaXqPe{`~p1DK#eRG91tfsXBn0 zzMp8IAyjNGSOdQwoYHCdyNH7^{psD|;}k>t?hyn1-rvh@Imx#t*F>m^%zG2d~-QKW~83xL_G=+jU^R0 zi?9TK7_T3D<9R3Zz;4_;QJkVZlZR@hg;WJIS<+Y9EbiC}*(8T!@dq_9S@$ z4t)C77!kgJ1RR1D`j^**MK%t+qdxOem!dK>AIP$N$JC{P&^L64!f8*4aPT)fEq%`m z43eZ6)EtM&z$QH*y3l`}5!AhRsMde@Fqv{R$xjen%50s|4igt31)_bm4Gr(Mx>#tz z8}P}Mbj)22G|^fXfD2oGsZoM99rRV zFqS8_^e!pD-j45w%U3VrPkmy)63Rn)xOFNU9Dq!BI{&BmROJGyonCjAc9wTn#DlBL zoXKro63=W}jKyO^8uVG*ka-s_xEZS>k|jK-3uIL)1F&}w?fmA*qR6!xOLhF>E$X#W zyxL`%=go&i-hT% zk-v- zaeKAeEhAxFeFQe;@ye9jlzi^=pppTcrtB6U9gite%alu3b8OeLvr|5FlH0X;_@K6n z{{1UmHeRe?^bDevFp;q4AL|by06!4LP_H=i(rU}|0kl8_vFw<>p%Ix2pZYRco!W=$ z$O8utxly5eC(whhdyj$4JBm>b?)tEDeA1X7;_Po0@9217lk#a)P zR!cq@J|(8Syy$WgamNOHM$DA+_}>ZOmG#m|O<0lK_1x&~Gtg1qRUx1DkLS))oU}#_ zQtJR!Ajzs=me@*)m8q7#_L*=f;#RHORZ+Ko@Ri6RGWuJ6MDI!{s9Cgo^cdWF41`}? zo_hmXjYEG#Y#IsizE4pB5+w`8uS{xo&$)j9?npjRgL5QCAWhJYG z5AJ-WEpKUtO`H38$5EP9NB$+nd!e>}_(fG}L4OM=$VVfB(53XMnKd&td2~nir$$WC zVS1^U=6fC-nRutz_ceRl#Bj%p zKlnrp*TU0C%_J(`JRBBc)-@=y|Xc; zcb@~j?~pIyd1V7!hS5g8E1jEopz&?=B8!Y{{3ZY2qY6iq&`XdT>JnN47g=K^ z39O+p@he7mzPoF->E(KSkNP%!hrSLc&881uWSacLzLMFI?gsh&H2Cq83thSkJn$~h z{9$Dzn-11jdGTPo%1h2#=NfXwcZoAgM8h|WZ=A!d=8lTMR@jq+!HA}>9vgRH19X~pvX+1*T4XqVXslqBV-=YDAwLAGT7hPhosaGSXE#lo$G z*S!2{cgAr!XdGVBB0y8TtBQJHO+ChEEq3wT`_7W&VfIA6WEReyYM&O*;3$y4pTCR3 zWAuT^5s^~>Z_$q6&hDLS7oq`+IOsA(67_}|>sik>!e%#!b% zl0|=JQTWB@E3EWlJ5s74Goch@niVn4wpeUR9UN`zqy!1_d@B@HW_Bo2A>EM`6J?qED=Cj!d z17TdIvMd>g@KyDcMLkov2~VOG^)r=_Har4zZH&dx$d(~%tBw9PfhTMxeNu1PNl)}<}MgD1Q8HDAwfDf9Os%)0v885!@fe30l? z&K{@7-``PZ2**;}v;zrQg&<`T5)}nn`t_lP#DShj74}2jW3_9jspJhX9TISaUiGSf z$ZEF1ZvokQ11lksXHoCtyY$+Jk5NRf!0El;fUB@9H
    ?uQ=4E1v9?q&bbIG_SJ}MEaQOu(c=EC}%y8;ce5OvP2y#D^g~4T4ZFMgkJN$|d6Ld#A{W z0xdqF>N1T}ItZ`CR`p9ykFaABbLpkojBxiTF{;E=P{rC?^BD2&p1vZAc8Wy>#bcyH zj^_2K`9yqsl946gAW(5512^!VkvcfraeMO`XyTU*n7mB#>+YRL8m>W-?FQ#GseZfJ zxbupwIkpjYf*UqOhg?^3-<UI zc;##0y8oR0C!a7ma4>Y#t^lW<&@N1rmeo2F%pweeHw=->x<< zd4iHXQmjnV@<1xGrjAcg}|N~ ziXFYBZyUW4noRE^($EFduQ}xHNXF^>yFyVnG;hd+?PlPj>A^5FvM4>hZKUg|e#gSZ zh5!XIzPZ*WT#Fg)5V@z!mIqa#m6fy4Hj?mhO&L7|*F_)hxoqO(ZtT!RuRSDaD)_J( zk7)Hpo3)Lj%Rqs`(H>=$bnSuySZUU&M>(;FFFYp+ZP1bGVgjea(b|(YhKV#`WD8sn zEmX84$14BwR$)&ECtdC?I;MvGGmYWkYj}K64tuJ{CLw=TL_Zp|X^qQ~K$X^2;B0If z_>5bP6t2IoFWP&^qgy8}6+x01M-a!bWCpo7L!2&q-vj$H;i=HXV7td@uFlripO zawO)aN?&Y;WNbX(JFvrVV*iI7GW>}WHf;;UHbzBT@0HwYp(rc&Jc6Uvnd>3ayh#dp zAV($)edQ)b7~+%mB7Bg7YQOA=`=aQgkFgCi&E?>!o(K4^DodFJ#NE=U{W|_IBsROJ30!|&r*>=%tt)G5%vpC*>~ura za4T*CQ$$)Mv}ySWUlq}4xDAKG($=qMpkIa!UOOUZcA(Tj+d;!1-W*BMfDD86=rUs` z0q*bk%)$-OLT2j{4rB}F57XotyRfsk+NZ8#%~|}<8k0=hKV_Le%-DtbT0!OY@rtIp znC#mr0=1G9@Vy#QIOEt#5bh8iBD`OyIVXz}RTZqU(XxmMY5Z8Po`y9v=U@WDqbJY6 zhNtfOyv)7s!pSh9@@-iby(HW_H72>xapl$E`@Sb0m7hYJ*(<1T&!0e-`4%QUz+w3! zCKqB}F8a3g^fz3&`0#qxL5zZTEurNXnzr6aOjfc-=LdTR^hDcTG~Y7$l1Z)IRVWA5 zXc?eqO-^vtHZW!!bqBNy7kj5q*L*5M4}z2Cjb3zf#d`3Pe|%^yBnJDg_e;?0=Aor` z+6>0$8R(p_R|!>RZ+W44XlBfNlbdg9kM+7M!S0V=6U&=_ZNyKN2|GFbMh~M6spwkZ zn3}*2jMBTphsd>sg+Zn#g?jg)U*_%T(_swKcfiQwkrYe9OFb?ihwh|DA~)MEbjkhY zA+EnR!Tl))n)$ExjDIt`6<`va-tYW^X*gVBd;Y_$$j$E3J#*-^h{}8M2b0qBNNX?w zBi4q`r;eBK^$P}E|Ah$*M~7?W95r@0S`raUD&l+c3-xeTbN+R5(saf2U`>fmQ0b&$ zV-kcR?cjNd9XFexwSZktuSRFYlvOP2(eM%0i;tT=lch{WuXJ1F-^$$Y++kW%{b=3g zX9l+?dG0)DvTP5AHA^Y@&7q&u@99*eqkL4HM-2d2i||fz(bPm{Y6tz5R?b%!kIDsI zw5{4#m|zpW+?sK-=mmO|dbC5^b)oE&Cx!AfMsIiQn|9;T?0bd@qj8VCmUAPVCWTLdL z%CYBWWQ0I?h^E~lg?c>pN@&&V@s}627SG}nA5~rxA!#5A3gyBjq6ZcizvS;c&YAku z{f2BzvU^cN(T?IB1&y2qQ4k$;Q7ztuf_g+uJ$iX~tX(SSjPmREc@uC=%==0jwdX-A ze@UomTM&7UAe_)(*Mx{bpTdv5=8wmv9ZpZ;&^oz!RkJfho2~O1@?8P!n)ZFDmD2ctOVDplMEB0&`Gu*uG|o@yWb5ds1#$HF)A~G zlB+8T`wy$o!=Xh4x*86q*W5-&pmy(P! z;ko6CnzK9b3lkB$irBi&3cpQ{-b+#gcZBwML=m;IHmkvKsI#8z-|TpkhAmI`z_oyv zHp9BZjkJk-`lGwBWuzF95LfzOuh0G$DqR>dwrv^AJCIP52eIPHv6)EL`uf_a5jJTrA&%JBw~JIyeLtb2F^put1v^*1;%xk{6tE@4WAHy2X)0 z_qRF|e#w&u?MI8j&E$^Zm_mE1*r0Z`lySIg8t`l!h$X5@VzVH_(^n)z-9=8Ouj_-} zbG7Cg?UXjB8^MN1i)Yw`{W}s5rHyn3?%jNMeV|ta?tNVaBXO}h$g?QPx~sPn?rzO9 zP*$}g1P9Q)VWOlXDtw|v`HEY*_+_f9!Jo3DL%PPb+RQ1$5hL@b(GYH{gbP50aJUZw zKizJXVP@iWPJLp}Zqb=nsT-HO7_hE|nPVya{m>$-NrJ12qGz#q(;$Xa2d=N!7`WQ& zv-9{Cg&W8rL6=Jpu-h3A0${zp@iVW|H~IDNiE(bIM9!?SPUSBxi4dA#K$3aU^#hlW zI;xB8r6jqwjJ16|X(4;LBkyQvy;}PPzr zHF&Z@1)_inZ1zSz>%nCRk+;zEt8p2f^|J>t+hCFFGH|q0`0Otj#z9!gr~Hf?TMct#RO~isyEKzAPYS)lau!7w-EUp_ zF!c5~_$!C1pjG)cstuV(-;Zcy0;)UAh_&{e`(LZ4~xX{oZOmkt+g!Xr_8n$YP5 zZCyCz;6L@SC-Yx)J_&i4eGGKDSuM}cEXSPpT?#SM;v)6o20kz);I7~an*-2K6b@y53gO5|Kv`SoQEgR*9b?{viq267UFEgbn0l>d*scx z$wqCHyO@AEWsEo#Pv5&ViWolxq1c6XB#$&Nge>dL!%L_^e3g)N%B#HQwVw|1W){Zp zbu!!*%R4hrk@dl?>!oqx4!xUc@eBdk@^9vmYeMNjxP zS|LkLmgI8*41l5+v6`D3Pq@x?X2xRscCyEMg|dNfI9Q?It7`Kxxv59yF)Zn zY><*Ds)&YlVZ$Wd(zK+M+@nmik18GJhN63W83t3iA;cCJ6D?0;q-;R`dF zBB@cry7%$<6Jl)7Yle2Tx9wH0hKES0gQC zactw>_WMw{t8H4|+(hKN`CZwPu|A+%?kQcTk_lW}baQi6L>Zjzc!`|gdTbJx)|E{$ z`ij1wM&ToC<3BN&K(kedBewe^Y9t^IDsR93(hC{`-9@36v8yHywIOz)<}@i^ZK2EC zO4hi9ThsWOiClv-qQrVOT6I3gScUg-U+~mJZ`_n4b}0+A&IT_Q)z??#PS71;1SSwY z@m}s$JO63z!oir33hE~9)LwT*%?GoDuNQ8`HWrFS?sC%Emv)E}zP4hx&1+%i^yU$d zHZ$qdw^1WfW3RX4%1_pnGp>Sk!Ya<8<_KA)%BY^2Cy+xs3K4~4n1_;%;4b9x;%A4{ z)bJCZBy=Xabc0%kwc`YwuwGR>OzeCazySXZ!4{QRd>~5(Z-C zh>ECcz{?UvlgFlTV8p%^RV#7ZwB|f)fZoD> zn{L=>?>78Lt*;weaBt1t57X3JH2xUFBW3O`vJ1LXdSu#IJ$Om9w(8CeE zVo%z#Ty6<0$7IUgx@dmSmk;k44DQTGuR$BAcF`K|qY$gjdv`cRor*ILu8kt&9>QiM zV;Q~uY%(J;skzdd?h9-%LaRN2D@8qnNSrV;H~gh>;|I*r7-K7Ue>-Cn6x~P*AdZ;WHRoD} zalwv8zW(xZFt)M!a>q#(i;PPSBDv7;%z{1GJR3|`mK6rpHXpJ$C17TUe57$fG-Xfr zg2@ig&d>9Dd&+RxV>Iq^;w_wZzW(Mn^W&4}J(fr2cMh)!fLWhY4Twf8rzKXnyKi$R zoA@Lx-gN6Kz)n3(eGo47VAhgv2|p!3e*7+9xx7ef!D$g2J^7jnjnwL(R#Ba&zsk`) zMrzOlu&dL2AFG^}>u^F8`l9kEH&h6K} z-adp84fS8FF$I6iwk;0g2{3_+my^Tx+n%829JfDAm8gFx7Wo`@Icmp6JNb!qt}(U)hcit!OBb0s(mSC44A&X+pMPQ$$$xGJ zg+k~~p3ib7GZvpsYCZhr_`bmHP0d1yZoAGrd}aPD-e#mk1!9ZONlOfZd@6hW*f8i( zHplB$+}(LAQP+>Wm(OQ42{$(%d|xCR5c6J(vEV;z#N!FWC(q`hx0EM13Qky?C1aa+ zmefFxmDexjD~gzOeUQ$~owSP-4o|A~Fc{*y9;`hobMYulf`)yQ2+m*kT*jq3dqeM6 znX9+^(VrUAu}Kam$ZFG&;(*!GQMn)<--G?Aa2|B!WAyuTONI9IQNHE84h}b^J~|0c4arPuK2Xx+o|~PY3U1)WBaH514S1&5G@u>xoQw#(T-8?gRyP_=``wV6lx-qZ1ig4vaF6lzT z>1T`-7-5F7$f&5@q)F*~{+iI0~r6r#MZ}VX(IT3$H@q-2{TBnV`{3Y4OLkUt$x|jge1NC5EnV;ilGQ^%|NS zE6K$Z;$fG5;f#>8U7x39XeIm9OA@nKl#Ofaz3jQmqhp8lk+vvXCmm> ztUVKm!udZKZasHD1eIW?z#fuvQD`e<=>40qxoLcwfuuLF?KSPVd*RI3jd%Iw7H&37 zVCMoIwv~}e6KGn``_y&zjsg{m|72x%@-`zJh~AkDo(CD%&?XKa?vS>>La4TQoBw)f zDlNJQVm7Xw^o2$(38D#yE(k&(3ln^|#XZ`n;Ks3w9>xR;rk?@T=oX6CE5Duziq;vE z0~HBnkc@l{RU9>tQQxn-QL-uY;q50EQUbYT9CIX{%e3A^odG8;bfSl5+Jkzb<`ry2P9{>&p9h^t%Zug^szN>8sNhl-E=OEh7o~vo8YiNQi_6|m zhEJufdpVrN30pAMypL%vMfyh3#*Zm{t;Q6Fb|Sb-*WFk8fKahz+>?|{R7=9-6yr$J zc;5)zq*j}0DtOYREYAi{y6bx8rt;S%Rxvk`Q*LZ zp5SR24T~&1=%*Y%gTLn837IOI2`w1bG^60Kri9o= z{w~QqA-bsiL4{RAu+J7iY|IZwUsS# zRWV?DrJ^iGpx*`KFU<0vLV#}dUirh|Lro&Xjj!R#h#9-C2*dIGRyDK zf;QNe@EOBZDP_YDQ!^qZtTSP$(JcQ;&H3uk$X%ZgZBM=;>F^X62_84xf`|y+cfk;P zVttaQ!fZ$uXRHOu9U96#v9AY@)P!i>BHW`0O+GW+m))E39_msbxl zq-#|5w(j?J$A?Q=i2=*irV9K6vyt<;Tvz^1nA3C?AdQlNhB6QRk9{oL{}&SkXNGa0 zTx>7Y1^UtMAAXt&Wl0oL&1qQ*$$_ywDQhWLrcqjea6p6`R0 z%g_|koa5%uILi`~Kv%w2Gaa~rS{<%$$3JxR2w%Et1of{9dwHQ^_mOM10S3V2a#_Ea z8bsO9nDrq8cCTzm!S79!ALv8`M(sF%iTBU3(0>hB>kd zsIJx8^OU;paX&~}9!MLq^6~@+9K(_J($4wX|H!|&`kidiWq(p5DpZN{c9lbdLB z?!~;2jIAl~+@j@a`8lasR=8gfkUFrWH3MiYWLaj(eOqCE89tLPt${H|4M1+kg~P~0v?Lhy_cQoB3#LgM9#>qB<3&PTY%n~?==c${c{57YAaWbeZcISDyalFlGFJyZ^20QAv( zg;T^U2|6LmtRo8hR2hxg7)MQT1~dq;CCJkrMQ4c8k4ujJj`AN)4kBD3^)fdC%pf&+ zpNNrl6XSyJTMA6}q2`yhHD`WCQZ+cDRizft95vcOQLM0LCp zJ$WT0Sva^1-A0Yri`>yc-pvWiNhZ4;qk4^-gJ2w-8j^|jm}x2WZ!qovfVQ*fa5kv( z5elAe3*6aPJ2`Uj=dkf6^2_TZJ;Zy))(4ZH%jz%`mjS5te1HC7cs!#(l8{x)ZVoK) zTc!>G^HBqiX5Cj2#;5=~ZC8MGV?5{W0oS+vOVFR(62v)asojN@bHN+)0~lfdU~MV@rPYmEb!f+#dR; z?pM2@zg~)U>Ba<|I=YdC@Ly%Q3|V4Tz6whe2I&7&t-aU-mv5uVx+JcQ=k9{U{>p{0$&?dUzFBUfZ}anyw9} z6cpO|))b`i^D*6|G_LJ9p)2o67;uOxVjWd7#7hzvUco7eF=od~IPuF&t2;N$GHZ9O&>*h#WzWU$AL};R#_=#u z-G{L^L#DN3Q^%i5rHMib5*xE?zRTM6Uu>IJCVQJMgtQSBb}mUNLR`@ig8Z186WJn! zmM#zb-nw_Xp;DvW*Up#8qzxHs0;FZV!QLA^P`wPotKN{_r2FY_)BL(a^5Z5Gpx>g% zTrwB(*xo4UFu_#b=rdHW-qu&r$TRn4DZPgd&m~e!`wFvRFqXD@1iQmc$V&L?v|*Yl zkFP&DaCGDuaSO9d;6VL&mG7Bar2$lt&>ukMqKa`w*6UcuKEN_*8 zka3@fls3X!&;6>Q)3L#iD^Tu&1&KVuJ~v4zI*m5Qo3M6F|HkE|3Ln9gPmHd$TUtWz znZ4*_c_baQd%^J|i6b?TpzI4l?EOq6+I_h=`6s!e{&4Wz@NfB$`3J?H@jUAjnAW_*RUh$`}V)k>zn{vpH>$9nm)AQN?JWyFrUuaXQ z=Dwg@uqn;|fO(l*H$WRxUCnG+fQ_M?S6WI!wtN+He*^%3O|r4lNh!7yQIGjY4<5V& zw*g`2+h$41B}ii-qH`|g?>Cjas5IE_T{OoMF>w2~z}*N(v|}5f!$_{T#4vqcST&^j zPlw9z2&IX4qmR@r0fC6Y8LtF7j|!p@EX?sb7Ti2@Rnc&~9+$ z{J>K`&dMf*5xyq3tXI3OE_A+auI|-n9Brz@jQf9DC-CGag4Wy*3{Xox-0DN$X~Zig z5E7N(DG7PLOg|ZikG?)>oz@C$bWm+lZzng=RCS>PSbrob+BAqzNfxlyhrF;I_o!>C z4oFEue0Fwr$#JkglWgyPzL4}Xl&3^F`@y?Xu}2jpm>4Oum-L5Qm+mbeJiGEH87Y(Y ztNr+j-Ee_0DRB*g#q*4bEe9?IsZ{oa-+4NdH~6uB*wn|9uMZ;Pm}6z@%Q_lXHKwOO z#?<7!_PO8|T`Rvv;019GFXSZnA#ZgS%`-~Y==NI(AbTWOM5oKnr+{^U$r1Zg&DX|E z-NQvL5Y~|XHSo2%cfay38eH}})wwMohr*CYhsJd6wgv7(`=+Uf<=&e`;aQx2LfQmb zY)<4#`gx&S?SoDPx8%|zMlC!zGaS@ztmt#P{rh>+ZYE;nc&hB^4JS2Z5L>V4pwL)k zrgocdcwGLeErg7z%gzeFavedC>Q4eq^s4ZCaM46YL5X(DV2`<*M$D!-bSOb&adCvn zcdSY+zMLAbZYGum+x2{M%5C%qb;HIv@n*WOz3slH;_H?iHx^@>`qs|S4T9MG;goO^ENAL-C%viIfBglMB!|)OH5TFwr9}?DO15V)z{8-M6=DhU**~MB zi&X!nyfmXI7FFSo2o?|1OZ7)X$t$|t8_0Wwn~zaI0+x=e8TyIPjyOk=A!ni6sk^2p_IQv(ztgKzOkRQ>wWpK z!&tX>FOX;uCfp6$7C0p{tgLTrA%2xT>!x+ZzDCZ2zKEVJ#n)q9dgSx-kbe_)6xrZ@ zXcqA&`J{S3=3tDQISaMR_b+&8(PBDj2QUp>YNmyDD1X%&X{1`Ca)LBckB+o-^veN=A+@d}jWw!k2+Mr+LOI3V98IswY)y4J}lHMl=QSHBHf2Vy`y{Ph92 zUi$l=?;iEy)zadUU=y0!8ft&S`rbEe8Oog1!UZB z#onulLqWfUarn>{@L(WX7o@dImGmD`;@T+PSrLU}x$e*f+8fpN^$B3X>FoC`hJI}< zbRKTP08)xvl~|2cJKVj;Fi|tHs6V-`N5iw~goXx5Jz>4{80n(gIl4!hw|GCsKcFBbv4$jxY8OqK0ZYwsN zctRm>1`srP#*(w>OnoC9zgs-S^Bd|d4?Yc`Zl{jgF8G#5V%fZr)~G8Bk((dTC;b<< ziU1Cd`Uo`5Yzs)Zh9FY!&xuYBT=i&T=~CW}o`i5Yx%SYaci-dJ(z`3z$j@bQn@T6Km4{8)1>~s2V zUfvDhxYwKGQ3b_C1?fFkeHoL;H!*ijx`#$5jlxW*c_juOihPd;k;XVtD6h`cE@*^Dk$t|)Opi*@Z@P>8{MLtQrg|}MsTJWfw&2zwaPI+j29+l2M zTI|_{YM990QE4jWm7PSqf2A;i`bI6%U*mn$`B7B}X!LVjtJO>;xQBA9`M0&mJY?$n}y+oBC_tdpag| zQ1`hw-nJ84W4c zXdJX|KPzxcJ3CzIrbl^orMdQ5+W@IiFmhO`%dOL<3Ff7m6T*z0_WyJ^QAsx~)8sr~ zn|yY`n8*;8i(`NGdY^~Y4US9Z$4M}lo?CFd5+4IuBrJ?fu5An8I_B7n=h>5B>PFS$ zJweTlg8^fR3NGt1EI5_GsYUn!$(TNJ>4&8HG`b1UJ~{`3vbdyUTy6hxSWR(Ax+Qgo zC23hZhWKt-+KQob^$CY*I&2=~NLztAa(HiDM%R7~)`i%I_OiPhu%)~Zptfd`!6p%< zs{CUsrR{xZXeS)ot7Qd-StKewR)|8+wfT{Zw-Y`RTOp8HLcV~yb%d`9tdfa;Nh$^D zaFq%n%0p1~RRTZz6V#@pR|nyoV2sSt8(OmRC(e~1gu#&vNqj~SyC9EYhC4(O}q4oo2bjA?(LqG`lM z>=YyHas$`@f-BnskurlK1+xu84y8$C+@^M-CGE8#4F<&n!YB@8j>h*uMKsFOt|S_d z71S_=aO;DOF(VzmtncQCBx0XMbN>Ot6kj!HgAPObFZe(TXXw;0<|ls#kzdhs zTIc$*WA347$GzbQIbqu?6)oTO-aSnVX_bA8LVeBh)+iu!5yE3h1(siqJyq_ndJS~Z z_=_BVz+%uiT17VyB4I*lDt@#4s?-4aU=NPW^T)BfxYYWidMG#%H%;4}tZ>%Z+4yvo z*m6~=*81<9K4oz8(2;Z6IKlf1U;|n+L#u36rJ=nR`8v$;ir=GXcTBF!TqRu|=v&{=TNG z9BX+f19wg-*YrVlZ?(=S%PSZLp1$Fv>Njy~kS|5;^5?b77o*_NNY(L1-dnj>A1%n# zfdNMJ7Hc1~@D$mnAZqDdwXB)nxw3052|Kt)Ax7QfMO4yF&10YM4^PA@B#+#qe$Wa5-`+vx=U`&nI8J?Ap#E@BdY^Id>E8}Npl#!viA;>7`>3zNL1&j&R?!D0v^P*0 zxZBOJW#k*gP*=Us2svmy@(!O-PnP0sgySYb_im#EV4VrP0nUI%h@e@9w7uPG>V*^F z<=r#63bc&=ia++zly&i_z9cgGm&O-^oIR3~GaKTnOI6zfQ|Mu(8z&xWW6YBOOy*N= zWexSdd$00pBA)kg@)>>U@^AzJ@Vmb7^jRoqoGRL4S9qU4x``t1T;6@-ijL6xBt$=sSZ&>&f2cBcG+BbC5Ut?=yB!kgU+EUVr-&%@Bz0BwZ|%2 z9RAKXPu>k8cM|};^_S|s4#X?X4Q3hAkL*`W^P}(0%<_iC@V&7@n~@b~?-iV2{#q#< z^U5zg`cM0KYFcm;uB}E#CSv2}O=!V1Z_~}zL$4m z?W^wXWcSQomq8W#fUce2uq^y&nqv%E3b|6p{6==O1Lig359}u8qxSKD!0?()ZV$#^ zw2oGUedc}y@AgeWsHSM`FrLBR_b+)O_#L{cCi>Pp(LqQwyEsFCysAuiKS&WFxwW#9 zh3LG@Exe0YrpQ&H{JGbW38TrADN@|V3;1nLsg!-9Wap+;&&sBTwx5)+UM zddKcR|HY$eRzqzSz=K5-8$XQJSQghM`NZJ&p%6J}5l?k%YLxEEttgNlvG14ZrWq!G zNQPaxK&P-ad85FF8;?_R&3~Hq;Cqs^0$~Oekjp?p7=xUQCl_k|a4inAEu_I6xiT0X zI%Bb4H%O>-#JhKWIsOr%{0ihPh3g5i!jcpQyDbBJP?X00Lw>+C5!qA zf)~47P_l_`i2l1Pmkx(y+hUBtUm}k{AfcgHKD>fx>%!Q)MB6Po(flk~$CoEgpJbD` zUG?5LgT7!;DEU+_oDX9K^%gzan!&O#=t;N-vEXnGrBuA0qkfK!2?EbiJ>GdyA&;c} zqP4RA<>1^{8ABMup%<*DEk6oK?Pq^*^PS;B;p=o9S_ejeDeFK}-QIo?KT5j6;$f;G zIAnlFx>I?`5Y=hG0HEhJ=}&?~6MC%f+#xq4d+fUOi1*kRU%50k2W(K_)^x-;9Kkyu zdHMjhPHLf5k*FJuBXGTp1qxrL;&~$80!hEew0GhDqPUQMI z+C`4lMHxai^5r6i_2`=(+eIXlIgwTASls>0K7iu{>Dy#O&~L}!>NbVIHmg^R&0f#oNPjd#%&Gd1;cqhGz&6Mq&vg_uUXfB#Z$V9TWpqJ zORx_N**cx<2loBtVPfhZn|!vcmb~hezlRv+Q=Q;wPXn?(Z4@s7WnQERzK_+$^+pY zArcZPWE1~wtyJ?U0d}M`Q^`H4Oet6ufLeGk#*@G4UXT#7I7b;deRH<$l#=lyrjJnK zCNDC`v{yZgIUNs(YnPFpVYI-=_@Zaef->>6>X?;KK^;RK*(YfCOjaotd_{I21uD3Vezqwn{(j4 zHC|It5u?;TGBapAXad~w!HI~wGIbFOsppn7nzJ(wS8{5!c<>!beHQk+z8NNe`&-a( z?{v+Vq^F6dNo1XGCNBgEaZSbXxBk>jz6YVulggT~(ikjq_Qd~Y74*MyIp)6~Rdqk?i2>ii&w>Y< zPyex=b0^y`o9BP=Rdk;hel49{o3BW`!lobJdPA8vL*@sbUpjfF!2{2y=~?STmt-^_ z`Cs#S?-idq;pR94VpEI+eun0Vo&qaqf`-?xjLxsVOy$=XPAdS9nSB4q{_!O^wKr zD;eo3`tMY&B~dzJw9aBGI1cp$Nc9)0$T)jiY_`UuXjwI*PN}$>%=D07&=Jzx$fApP zj=W<#$Wdd!p|H&p>l}(vha{xdUEJPSgtv+&>mhx+wz@Wg>UQ>0V7=gl`S_Ol%jVOd z3fDJ6(J5>@Dc(K^%T2jH8NLSmYMi(IT-AvT#KWh1_w7wFJirNHPy@bA0*d?^V(big zN1uO|{|xoSsO*J0Ex1i74!_AQzl62?;1j~~$TaCXb-Zd%?XFlYd1g3iZ6i;#Ri2S` zDup&pbq-)%7s`F`>w(Gx73I$6F76_^rqwLzkXNDlyX6@1nY=EEe=ZEBjH?zI5&$}5 zJ}xV^BE+(RZJp0y$3X;ckaD&K95}8Vlq&l#FbuRuA@S=~eZ7$_D;^etjwRuI_;oVW zJTkLq-cj0#Y5zHd^))xq{6pwruiuS^?>BYwYe;IQd9iAJha8d(GRj}&3g9fOZ~v$K z;0iCYF#977>p{hmW1PGl&3|TLOBYK(o%za@uOJs$l;O2^^fwZ(6c=;IPTsdg`qRp1 z`Zl5FCo!&=7^2#KpSrq$TN%o`&rx^PYMb1C!AW;y08*e_8?sPXytmIvJNt4X#|=5- zDSU^;sv5#|`!AW)PH~YMOMep7dL9Qn(AEBdU;jA6m4MC}{|RX(6Ei>C(h5yR`d3&4 z*&Q#pCi#;iOk^(13CK2G+xarWpH(}OcwAagN6}** zC-%6B+_9e7;cMauaBdHyjhx+wbv#5t4(BvVh<;5i_Ynkc^nvFW3y^j?Qq4*nvnNPMatPrh{IsY)^Q z8=ODOB??W9QvwtdLRchIS0E2+?Z1L4fcA3#O!lQaUMGt-aQ4Av65FO~B{=+W9d1cD zgLPZ^S^@2#^{A**NFeAc1Qq@AGQD}TO|QIb#;+dH9&$38oQ$oGlB7Jg1$w52=xOE` zrEOk18sj_+JpId|0|$T_o)vc`&KLf+C_1OWu3d#y%&t8^)p?7Scjw~AB;{T>E<5-B*5PuN1z_ihX5ea(u~_-^Mc6bEWLU?vK5 zi^vShoWdIF>ZxDjWYk@(d6V?4u1c&ohQSBDY08Th5)ZT(&2h77(vPfIa^~lDolspn zGqJ(LZs3qTCs4fidQ*?ZvE+A=3Gms5kD4Kbo@j z2h|%Cnl#DY_*;TTU6VT|Q+!ez881^yb8_tma7#cc z6wUw}G7Qc?pP_vJQDgQ|L*~>yr2-!Em|+?(!&X&s_3x)`f&BH^-uCO`J;~a!dD7Pm z)t}p%=-BFH5Qb^;WDGuyzqF3iZbYdrK)V^E&wSn$owYiOnW}^iNPsXW@;zc~iSgk^ z)GD(RlWP21guJX-z3g0Y<|DdxILPq&;7Oa5M`P_?chj2rV@GcDYlrLo7j(*?TeQ0u zA%m#{h`x%>WAgTK$`~j^b0x^YV4AAR|I3dW&Io;-vc`Qhp(VoHhf2vWe#jAcqeE!$t(IRg%)fq#IgTBC)WRu?9=}s zw`)h{(SgXCW{;e=MRhY*&P8_Ag!I|f4itE>hZOI~C8TQAd-)HhYQ!OsQr4WUcVAGq zU5mcFxEAx|y?)e`Z-QRCPezgq>MngmzCVaPFmsr+x;rb-WYF6v86)y*txvj!qEU5i!g;Lz=QBmR^xqrsG|qOX9< z1#oi_9IoBFqv7{**@nlN*Gz6G69Qxij`Q>tC=EKf@FFf}Ypo+r%t|3iEnn$$)5(;- zYLH1jkyv?xO<8ix$;w$iXZbr**Ecb+=U6km(Oa;$RpcrfrCTqn2E+Ug`V@! zzHNb*9$QJdD!l!6T9vc#&LgHJIVJ9dMxg*ZcCB9uYCj&>kx9@PPSKkiZp#y zV)`j3vbz`Z(+wO}-o1XDC7$FUyL($;XU(P6pnTFUOwIa~w~7wOvzvTxg>|H-?OJ$u zvh8c3MBWY%l3>smRz0sGYTHY644(HQ9`}t;Cm|O@f-<3h&_cA)s1VNW(B2m$jFaSN z=!%Ed&UVu(!lvdG0XiRpSf;I&Q!6hWM!d0!)i@9hv>ITt%HXY4^NU?MQIGy#X ztYh(q%gzqdXKAN4juGeC8&+>1FVFQ=Rko2!r<9Ji?Yby+Rg<&iieu_B$T2H{|A_m^ z9)3=hcsTZXMF=do`Ik7lj(n)1X)!7c_KWHo<4mt4qoC0sl(%KG1s`JY#Df}9vds6V zy>d`@{v0TbUaR7}V204BujBV7x(0eMN1kXSXM*32iU0a`@h=axcgz(RW}WqFg;{EF zRu2`t5=^c41GA1G$tBnKvduEe8d5_z4_qBLQE1$Auxn<+#^1WnWS)@fejxe|#(_Wq zmIJSnNUG`Dg%ovG#^>Dw5r5mOL6Yo2r_iHhz3&x$6&z~#Q6~hd4c|7197`)Iha*_#WgLu zj{#>BfZC1h3~9TW7;E#lXRA~Cm;vyy^^Gqr&>CL4I&N8!pivUCEg;K)F2>aR%Ao8& z;l32VqguTayfkBz77Oh{L-l6KG)mFMKiQ?;ESpq!Z%!3tnFO(nSRZ%ED1?~#;@yvW z7GA_yt^F(2bB0Fq)qPhOCFaW!h;LV~XNGt~2f^+RfIOmce?HfjR&)!|<)V&zN?L?3 zV!1mO29xU>$Q}!JEMaf|89oezB2PC=0Qq&qIMvD&JP#|LvzdQqSbW3HjY74@6#St# z>+B?!0&b4+hVD8F0@9%p7qAk;+}(gyP;PW9wJs_jtw;I;XLv0XW;=m(h&myo4an(` z;9_G4vxK~fAp}Ks$q);a#u4r3gptLlo1nMdABEz|{!85|w11t%GP3#p0?;9}5Xpz= zT8qQE7hQ9E{u{flFvR~0Y~*uhN=oz&HKw=FIz6dbLdvDuSplY?8uXp)4d~G=!WI0DS@QH?(T-b=yMNP$W?JI-M zAmEo{-zRYe*&q;DZ`~{hI<>)ur!L4e?dYm@IO8{ANn#2WAqD7G?9TE(zg+xZ?pLeW@aVY53V5`Kc-*K^UxXCZ0C8&*a`X0h& zcwqbJhS8r|U7Z(Y)bO>UynRyUO2-^AE|k_$ShW-i`j-#m)(^e55tLEPji32i_YoR; z`MtuPacBz_0z=&G%|coca;p%Rk2&o61>>55CY^XZ_WQs2@_S}wr&&EO9h5kzv&&Vc zmQ3@bc0r#rOlLTJ81eGXQc_G|hr~PSC!7Jztt(GfEbyr>!N(zCcU5*xj zMfGFE11buXTdzMCtDo`jPTQoM=jeltXcdR)L+2!ynpPC0njzaHRRUxlP_D42DIfy-qwQ1 zr2MChxweM>V#R+<_Y4mG!NdoYRPCz;9W%{V-@wUAC#@dy>G8TktlB}7zHk+Zc{Ufe zlF6Ed4s-=pV;^W8_L`P1xa5Z`Qsn|+z$iH4yG3742R+$+YA)Xm_|Pk7MtfTz(znj5 z(H@?Te~^*KN2ac!RYA8eTl7u%9io;2evElCTG&30e?eeo1KN*9{gJ+4AoGuR7TIFO z1Z5hwR{oXa8jBevZhj0S$W#{fUK8I}1>is}&~~9o+Py{l4M4E&%jbw~D)Nj;p5%_a z6)|i7ovy9Dy-W4s+X5jul{kz#>5Kgs?*Mw31nREk`z>o5RW~I&D+C z^e6_KFW$ba7A&%Pn{FN)p@7m_@6d^tIl*jilpT+)ixA*`o?=kQGls=tl$C(_kx=I+ zmjC=QH>93^cNyL48p2fB!AS!$uF7&(^8IGVDZd6E@{q6Pi}t+wp}}`I0WZ%}lNnH% zfjj%U$7S*zjWO?I>*90XT&4#O4{}`DG7q$Lq89IdkZ^pSk$>VuRd_#(pcubkLgACF zfKNCUd!wTHADl|z{-fk(s`UPHfc^BCOxi(t(2O)eRUAzc-ggyIFwB_K4c=*zGMR1= z|1bD&z=rLZIEufe^Y)@(v7Wx{`7x!k>J(t)siqEEcLV~?#jIxXygeokB4R93I3GEs z5!M=5=6egTv!?Rf+t&gdxHzDXWIghz4yUcc)Vu-o-%2Ov8{f4%GARrd7V ze3n#(mc#UmS5TXO%{`jCz=$;8Fodby4XG(U)1y~~J~t)98Txfi#c|U~B=T@bHy+T`p(^T&Wfx2XO`1mI9e54XG!32~LDMpb_pb}$U zK%%>jM1!Z%AW6dQNu8}@j@mzWOtTuh_|4V=r!%0Eq0nsMfQ0HKyd~!2be>$(6E)( zGVaSR?)DWvC5bXE25E5uYQXTUkgHEY!6fbBp=_(un2H0K=J4_wqLiwGbwOQgv5sSE ze2^n}R)VTF3e(S}aikU2n0MG)dy3h1Z;lPVDP zZVPnRRF!OQ*bCfV%QTh6;B2nHIZizYW7gGLqjxXt5LyQGh6_(^!u397Yj5K8a>@<6 zFZjSH?P^GLHE(q>AbY~2xUTUE>w;+sA@qLqi%=1^nroAkBL_w1Vgl55ACc0wdo6Ej z+mrCY;c}wosqo~6_zK)m1XL4hu=^@02FQz~oG*nn_59Oc?}xu5n8qU>l{V zx?2I{+-DX#Vm6+SPB@4Z(HOm?dH8%|#=t4U)>@9F;xr}4mXc%UY%jJB*7MVs!Nmhi z?YW$WF+w*LYB~zyO(o+DG+_C`pxp&N2Fm>85wn6UfRcN@b6Y^2<31nIv~|64@`-uncP@{;g{owptbK1n@8Y{D0py$YRWD2Uxg)th{ER>xfM}qv zbZk8bIv-#E10LZObL%1L;9C9{l7p|j#)q7xA)$tkqI*vahP$7KP1I!sWqQ{JF33qe zH~FlAk)P&mK51n=g(Jm$TtP`VB(S7L$Pf07Z%7mz;x@?N%+4~ZAGHcQ+Q&c^ zx;C>mjK+{XJYB=P7gYAbOL30i6%Jb$8YK%avy7^kS~kvs_M|>>x~cLa%4(T)^2cG` zoONqmF+*OE0ETR~gyD$w%A)fqIM|ZQl0+pyxh|nXyq#zkj=jX%_otdUjB&$MdYkyCiBYI)3tg8 za8u}#8R8;8hes@5WxvO@pW2y>nf$B;!*62V6Nel~d*arp>3YgOtQUR=5kYFcQwCHa z(I4APWM~L0$`p^8m|DlyMuo1P6DYzIa8h`<5^T}PpM%1mz}%8=ex&wK%F#Zn03i1n zjwUNv<ALztq|T?KuMw6aauApXkdH6Vf76Mv_~NKos{IsB*{Y5Q`O93m49m@{ted2zicx_&XU)xn z26mFj@Lm2OZcKb&C6zSiy1Sr|q=^&`_Y1}xe~c7UdQ<#2w1S=nL1133wXt@+%f$8} z_~syFoT0~blxW6m*0tPKE=C>UOGkim1zT!)QQsj`rmzz)NH{foR(n9=4`~kC51-Xt zhVVDv;KGUWR0+yL|UL1KYq7HXnV5uv|x~ zB7D-X*>Bdh&+Xt>-^NI?G37isW3d@~^oVXaWMaJcg-D?es?t*Bv=JZM-r)~W8fST7)1zQ`1d-KWY0T@Ie)f=d!FUa{XAwg$@nurv<=(o%huFzY zvxUjIr}shs9C*5yvm30;#F7pfe)!qX>~5&bf*mM8ztpxvLcbKQL*^G?H9HG_Am*=& z6KEm^yw#I(l!qi(<|K!&TRBkN=zi8AdzN)IeBeputR1+8dp(S3EWJ88(icZH!xYUk z$G-CQawrYai2cqVjqBAk*JPKsAl8c}z~L}9!VE}Q;~$Pe`rZEk?ZlqE&+n=xE!v}C zi{J<_Ed~gPq?X$Ygc6$2&AUSXddr&}n6zK}3?6J``Q&JnSIT71_kkt$?C=Xx0nsJZ zahB5$4s?l3VqHUBl~L)Z%)M?URfQm~01r8;tNwg+zI^UEC7NP^pD@1FA_?44=J{6v z()dEI#$!jUnIK~xFPiuAMY8R!&@cX9Nm63p%Q-lNr!=Nwp2tBsu>hL1wt+)CCNP6z z5oHLjw|hBf|1AT}*08u~4^9{6ST`;j;Z7D=08W^5et-rqb>PEX-u2A>Ywb?ens*H4 zTVL~pf?>NtBNz;9PU+C^^L7!?-r`qKc%^38=mm?-oD+~{moVH=0fu5*e2Y8CwUzjq zL0!B!FzEMJx$fkcE1LspFxTGf;y0zm#l>~WNu1*ttHAJ?0Wr5DEXDuw zjsV;Lt-SP;P11)LwE2p}-+PaO%uF5df^UZt=h8F3MVp3ETdD=6b@au{n%vfG?IDCk zd*~Nd=+gMp-963z@DE)pl8!5^1_&bKhSa|<3neFWne-NhULIzRrb}N=?jg-1<&^NP zKgCW)XgG&=lY0lLGPKXi50UNnlXeT1qK)jGe!5t#Zpwqj1=$Qfs=?e=9}DToeYrz2 z#f=@CJ00&VL)AC2$&3|K1WaY-4328Yq}si;sRGDQyUd~cf^>S*`*cuu`vF`^Q5?|K_Xs$m;F*`(UvCQVujV?-KcyjDlO3_-}0ze zL?Shs#I4|LflUO9AYy<=+EKTd=A~R`6ntnJhFA3 zn}ag1JtrA9GlCHFC@Mf9UoCvI6}zUobAdF6@qemfL8KNxflyh4A9VbhsH#@o(gT<* zi5id(xJ&?Z-*Sa+#fVn2-cL>HD}b7@?RO4(QOAu=PyES~_N_##)aF#|$hjsq54;3O z)M5B2&p1G^DO~0*9NHwx>DQC@OM(xA zs=(cfF?I@~x(|Ch@eDGvhQbH+<)^f#tnXDQqLJbn){zU#M{0p>3JavSd0ovkzq!Q@ zj6dMK3tZF2xHX4X74vG_))Bv+3DMH^GBKkVLfr&OFQXZaGJ2Sc@tC1fM}jy!%+S6Z;2)=|nn_6q07+NA^qU(rIGuYW54 z3z4&MgjId#GbM!93eG~QJ84y& zpwL)zENPx)aZ`Ha&Z_t@NWQ`B+TpEr`dhwCl}E1ox6?Fz5OYfL1G(-ISt z)KH&GYDeppFb$C98NhI{-1`& z2WvUp^hf(Kes8?Vg7eK+k~f67nc`3M(T1=sQsBY;@ou4o`&)8fF&0Fuji>VOM&KVQ ztiLnndZT|?p9y3XzgZV2EvP~oWMlln3<7&$>g5D7G-2efcH7;< zQC&>WhY?T^^ujlq==DW5eY#gaTBAijW!{U|h)0NY_6{t1eg|sw7LLDEoS}4|m514M z|I-y9i5W!Wz!^9eJSK*HK&kXOu#1}llzTn?zVdgzHfe~D8P%nj`{Hq8VCQX&WA78yRGF0HevAUVJ@s9MX;xMu|22@u ziwwM}?j5AcmU$bLY5wZCrt1Xe0wxY*?&K#%tWWD^U;Q_tTc0AT+41Q*t9P$7D_;n2 z$Z5k|(jwOA9)-m%t(eR4f+fEin*OsVFRxc`RGrrhgX_{G2!R+XZB+FBpmOH9FYZ?x zKp67TcH=&XYi#`AZ42aVu{}ozm^=Q9?vwxHoOP&sqf^*VX^CY*Lu8bx z*`*95e*zcocTCpbad)^Q+}_?^*ML8yj(u%?_=30#Iz$ z#@B#_NUki0Fp)A;@WqU_D1q5S{9aV2Rrt+X)}Weaab%Y;#~r0n}%X+un8#As$J6)j8> zk{J8g2VpFYQDRa_88ahmmSSe?W(>1j@B7v7cg}sz=a29AKA&^?!#O%Noa=gSkF9&i zeEDCQwI-<)+TlltqRe6|9naD7!!Lh)(ut@#ET-Aa8Xw!_AE7EfSBA!#)C%qB%V=85 zvOqbFCTm+MqOpaz8um_~ZBg)ZfudX(c@ewxJ^s8t+!~F zJ#!e%{Ba_QKt#LBdbZDo-**@AoROnG>TYKSiLbxyrJ(`A9G~YM8Smca|P-hA$}9eg7aC z0+wWCF)Wzl>DJ8cO?NR0Y5cWizt?5~xL}P2#XvNQlPNj2r67-mGs!)>Gh_vx$?diT z#3uG5d4=jLA(biUZmdoxd}?NTG}Z>VEywt^-7`prcf%(lE9D2{I<}z;rgwRf^}p*H zBe3ge>{(0N9(@%bXZ?-7xgA`A@&QmkL4}Y`j}Ov!!A)M>A#D9pKI*fM3(J2j2!#OU zm(rqqB2SiW{@7K!Fwr}P3Lq@4SHXiJT(#= z7#W>u^8fYGnIN~&VSazUi&k!7(8@l~gzYpYfQnoCcF7qoqp|Df&>dbGtA3{Rp2JsA zJI7-L!keSR>IHe`OU~$yRp)X>y#AGWMC{~CaFN1Oz^8_pLemm-_$TqJDEV=|7pPFK z^dWUpdpV&L-YsC~kJKhZDV2M%FxiFa4-ePObJEu3c5e{$ZF4HS+P$`MJ=SJP(jSJ* zr%ok1^E_@bf>e)O*S|*A>9Vo(V=zJU13{xL^2K@qytqp$7pz~dGpEt#1dBhm9oC#z zHoDBJ)bk$AG*ezu!<8K~NfL;*@{u#LgE7i*eMq5nNA4ZM5~g#jqTKscglyW%MK}+_ z{@mzHabp%$tJJNwf4a~9P2W7ea14v>UMC~HJ`v`$SFnFyVb+^l%M2{+Js49fg;z!l z!)Jc&!XjoqWz*Qd?Zhx}-iI%mOcmX+UPd=OVU#}Lx-g|lxpUG;aHA9!l;NGoaH2vL z7g7CLMaX~Z_4k+98?QFXe#!A2tgE4Ue-=p0lD zkp>HkPs;mFUosTDw@jQgxks!1=nbO-bGg33rlZT~JH-;w96_iD@t7qN6WTctdqT$i zutc`7ev0MEPDXD;3Hc~SCwvAzJOveXJBS_kzl=UsdRP;%^V-N$suuRwNG*>7!xz?U z5A53U^TK1pPtD%O@ejaF8UkGfV`GI5(iMTk! ztgM3MVP^fc1Z9fydAXe2lzoe=V%`{gpfK(R}k z71?XC3IRpFO(zP8(LV}rKjTkR)hh(w6jc|SgFVS2Lg@lDfabSy>V+oP-^=>0@NS{dMBRGV*?j&|hMB5m-Z^OnO6)s5`q5`EJI{7- zKVVa8fj0Q3IsnBZIbdgJr0)7qyc64Cdy&yn`?8E z_eGoh1J+C6#8xO|s0T9+6W)!EY)m~cc}IE$1)Z!J_#5HWv7RVejYTdbH}nyH+Ic7Z zzk2ZZ|28Vyg4W5Vz%Sj=&gY4Ckz&>Ru>?x(ErM0r{AhC)w2DK#-&G~`{2M!=ba5bN->Epf;zi| zlHQ?t?P%mw(Oe`xRqD*E@ruaU{|1w>+aN5gNFX=@9C>jY!I)gL*4eVQGFmml*S2l}+?UZ!^=-qRSRHv2Dedt0}{@w?P3SAb-i^<7@v?Mm>=~@g;2X%0~yD zBe))St{#RLH{JNeSxVQS)K9nAG-R;i zaFpWKt98K|+wo)&n;>*F%(F=2wN}e-r+Zu3Dw_6Mg0~#fn`tqM3}@Z_8Di|eW&cxm zFTxbiga0G1ULd=j_f+d>`VN7gXB9D=4gaznKK@XTjEQ#drEvBDD^L<+a8v=`C8+8RNO)&>L^0`HU&_%+%IG{&eL$o2Ta$6X=bVUH z-sTtcRrt#*L^LB94-!FKdR;=vZWl|k&yf^0r$ckOsgj5Y5dn#8(gh zhO*hJW9rV9^odb7hQ#C@ypy&IQh0~P=Rkg3yl!`;R#d_V_AhaRQGj*$7gcHy>mN?wbEL>I}@e4mM4DWMq4s0AWhf>#mRUzc}zY~}A;^$(&&TN~ihev5xGRo-6y zMB!+6vh>iE+A^aB`Vy{0OcDLHusO@#GGf8rr$Fmm8oat z;wZrb}1c(jphWbIrom$0j#ASieb>Jzq zTi}Fi%#kL*mrEE2Cnx&ZU5pQ3*#d(EJbG}v1JzMB{X}L7bMncNZQ&trJwn(AN5x2R zQ%(e0(^`4gX;i9jLhH5x+OJ+5jRy<2dl1fx5}XKsNJ#>wi9n>Q15p~$zd~8=rq8z& zpTidiVT@}%yy7wShp>n=<+uv}PVsg?o!l+oS5nBfQz$n~P(I!kz8)N|el^kNlq5J~ zW`1W&7n86D^XGEJUfhZXaQnbJU6jf*#Ob+P++~XZ#yD-G~z$UoN-2E7#+NO-571qZ>$j1ye>~%Nqce>h>QGrqsBxU_C8My!c_-}i6 zk)1?i0r$GRZE2ZxI^z1xXeBhtL(^X^pkyGby4lN zS-(@KQ(nrGQYg$uXKBWoT;xxR?YU?inF-a4@E^tY<`~b7h`D`T>|X?%SALL&4kVoE zxj1het%dV14I!OdnJ;rOJMCfF#UNq_wbl&3QHE2n;SZ_sqo!WzBVhjv$}aHb#eP>w zyCAQU%ehpg!N|sgrrL-coS9+5H|jGDh)+8UL$(Ojt;vhDA-{nJwnM>Qm}^Sc5LmPK zi=s<*trO&2*Y0+CUU3akt+*?kEZHq3m`ujHmZzl}a8)04aW`3)t_suEn<6gtP$P1(P)| zBWswHe*G8FFA5-<9d3iBVw17MOIGk6#IUw1rpG5dy^tn22EJb@jJUGY>Fg2~u27Mh z=-Q0Kn%#run*WX#o&ZDXYG@ey%!6)BRLvHzU4^fdCoT~pNV5VT02ZuOeraKmRJhR% zie2C<3IC{F`^|JQGr@4jos@PdKZlZ`*r$CGJc*{KGX1WbjB-B^e5Soq64n6jY^UX@ z6VK186Fj#YoMP!6cvYR5TN(7}o^3s%o zBTU6O+j8Yl|DyOdN@z|;E6vEaS;2Vf)#lT;nA^iuh7;-=ANaUBMHA?wQYN?(@<^$+ zNHpSCXZD>GsW-=uY%=*(upYHN)JsW@mKrEABBi02?H6RxT9uWKb6Lwb!7p9eSk+Pmv4@k8+f zx)OX6JGtb-W^Vmh9@A1NV)ne{-qhJEala*9BY_3$q0v_}j!R!M*n8(R8lYSe-u`cw zpqzRX+Dn^?Q`!<))H8X*`&q#dONbG812Fq?Lf|t<+YMO>3=1z*yH>`EDO$m{xodYQcb%mXZo39l^aR%><-KGf=&=;^hVpd49CuK10M25vzz&Yk zxNbT87dh3#nd^Wju~{G!v8Zv4y5D4&^5zNk+mUQAwH&24z4qs>S-di>9!2}8pp z7XHuhjod4!o~J}nTBnGBF1~)ir~$X9b7%?U?4RxW`fRt=7Gk^2T9oi|fqhVz3~|{* zy;UG|ntM)+%{`~l_<+2GiP(^Ro&XiD#?MLCNB_twQHhUz0d5gq+zZ>T^8-*>G;zDI z$@uy@^lRj9!*+z57&(5NvP52r7G590{J1t^X}f8EPH9&FqRts`|L~n7{n6P7H|66w zv8DI&uYOnD?t0ACXbBWjjIfYd6E2GJedBMVoo`X`MMRE{p(6=_GBS4>!q@Fmcx$Qh zc=I_u?Te_zRq1}c;r3P6e<8fdeWilTgIiyGj$kugxHS#WOi!0LdiMPWu7>w+qn0=Ane#<2jO!Xay|X@Q5p|jLVdu!Rp(^4Z zUO7C>rdAsns7gc5X@}LLgc$(;Uzl+&Tz7w`e3mT9O1dWj$)dbHXt0@4I#*$MnR{LH zlkD>ojd;R1xR}j^5Q(P^%1nF^&Gy=aDcIsVxmfY{#cY$UZ^HAnEXP?s5iT5Cu4W%7QrXi5%a z>rxNggAact0#0aN@^+%X}v9M&i(4qeaek`YBqr?@-yi$%%1K806; zW)~4SonxSZZS>b@o(KIw?o$;2_NSy9p!-w`e(esZsCysZm4S(F^2gVHl z0%}MK@{yl89qC6GZ=HFchADEv8wnm3bQiNLsZ?*!X@qa5-&gvk<67wDU7Y2sL4HiA zf+A*93mNQJTw_c7GbysJnW&{dzd$~qi{tK+w<~EV-@==TNoegteB~IPETGY>!n2JX z?0|r%Hp_j;PW%Jla8n;NnWxAO4_)1Ay0(% z>i)o@@Qv=#shdjI7$HK;_BSEgyk!iaJO}XkJ^O)>X!0K|OyGIw6;F2e`U5mONh%#V zi51T-Iu%I74I_k-?hl{xaBumNzbC(x2g;`CKf1>SgB0}-K8AXWXz&w)W2ZBgOZrvF z8=%46f3_vNsHfxP;RM`a&28D-nrzUt)#dT87?v z^;!B@WWIYHG{9CvTz#o*{o0f-MOGo%Dts+9)LY4bd$$D**f{2n+h=IGlf8pKO{vhstB_+=Xsv5saNJt?vHmx66OG4z{SN#uwtjf zDmD53p}xvjJPg|W<9f%%dY#?7WjjiZ`?qXr%ecM??lsHHzo_j^Jb#(QsoXyH}HP zBlrR@{au4Y>wSH}dhh$-76Y5m0}y*{uBEbu%!DGjzmn|X?{ zXMOd<;(|LFlCyPQ(N_`^Kf`=qYFB05YAMaV7Y)?lTsP^g@RBAoH_0b7Gw*YX(fxIO zb_GLI)B#o+*)~g7Y|^;J;7Xbc0Iq_^6l?t z9fZsXu7wig%W85#F-3MFvheLpB)5n6SWWrD)5CLrgEJXJZ%^4Oy9fMO;BCh4pR_`? zCAI>rB${c;X}Fi!c!+Yr41)(ZiztzJb{p@4Q~q{iqZ}>Fj_*Y0lt$ zuHU&1lV%yE`*P%7YKGw5Rz%i|Liw^1%LcAlA6TbiNLus$5Ai6+ zOL2 z@_u*7y}pr?A4Ps;pOJ~RBhbm&%<@-3+LV)xRTaqkJ(WFmeLt)A9sXA)Bj(HN5Y*(8 zNk{vkk6Hi997eXYVYsF5bQo1!Nr>s`rAVE?yJjK?%VeOR8voB;W&i$Hsl{uNX85w1 zfoL+3y^!(goQtH@#evPLc9v0^<%>CeXnFdRe)FLa%}KF={K z-hOTwt#~?r!%e8ki6@Gu^#J4ue!E#^4;HZ7ADv~~$=2GB(d(`<&*p<(e-yUN=mfu} zCQ)?urJ;Oys`HCYKe$N+PO7^!_Z4c@giGGS2YxtM;;HI(lG4+Tb`fUTx8@Y!3qtc3 zl!Q7Uoar7ojD5e$3~##w|4teSbP>S*;U7-T8lJQ9#RHem$lPxSRmX3EZo<#^Fh^8B zOeDC+Rd!=_TLeL)qCn6E>~PJO?uf2=$l9g)@;MD`YeY!8XZWk^UOiKV? zdh%Ss()A{j*?n8e_&n=8BpvA&&wYANKVP#^Gl`|Bvtv#c7rZ2Z)*OYOn(j@D4#+J0 zREO8Ce2xyNAwx2oEXDrI!V#Gpv&POFgHB~OTw{O|^Bid>hA$Cty4%KXqn%7c*)lSM ztwm)yBAO**Ky``mlNIaj@bfN{3;(IOXER_Tj1DC~eZH3NyPAqFvtH4n-#BkMGT!HZ zFuBv^>Uu{zpN2#ITf_9O_?puk_V{s)`wIj0i05HjM~yGO9!?7`x&f1Hy|+YJiVi%l z&$|%dz(OZlKhHPp9V!O%Ie{cAeJE{E$TA&es;TV0{|51)GW&`gfh`$Qm5vh@2YK0s zjp%@06N zle@4(oe`Zrw5a8`*sZBJ(5@~#}#*!@kJIJ}IPz!9}f4=~B zsV{$;=c!?Hz2(5#3ip~5QGZsK!=5AfhZ}=>fDcml*+6eJB z_xd5Dh8Im~(`OS`g5|maKQR+>J8&7VTOvAzwe!Au;qyblI*O5p7vxAoEgF4bUGmy1 zU06&#pb1ZPFIjpi-_i-Iz0&>J5Z^?VE_=E4G2=)+*(+9Drvpe$6n2~<5IWq|hI{TD zR`)13I`4C@JBrC42j(;6&G~P;s6GSKn*q5`nLFe~GNuRp^6S)A%v`0CCHWJ>&yT7pJ*Ba3A|tu;>dVTp@JChF(IpS0gQFV`nQ#n<%I#W36f zt2v_vMAfquBT<5X-pYlYWiR=tv-uME9MH&rYuI=PbA(`9{!Q5`VV?X2*-^A7)hn-I7K|uNx2TY$(b#-Eq_xTXrpodMx<+K5Y`;Zo!6Pp7UW;zND;dQ zh?XOFznPUB)2MZTP(&sk)Mo$bvRs7SZCh0<8VB=Xi~IXa`PDV$k${IC>`$+?t{N|S zz`f8nzutwbynUqCS`_676rLEFRb`gGbie+EwlTzMa8<&rR16 zgx_yMe0@OUa-m2tA?0s-Ln^iZXJOR8|5aA<|KD)^<9OiDI6=}M_!{*`bw0uMKnL=I zf582Ab#d{=^qPG#Q6a_|roH}gAfy#DDIB=YS@e5hC(-p2QIRgqSTe-qud;x6`((plgW4-^g*%%qtJ7a7jRcNzlCjV+QE&#m57gT;cGTSWlsRa(38vATpHjXmDIU>(8A zi&4?rLW-q1)SG*;GW-S}m}2%zqHpKDu{+-_u|5_ z2Zc{gt3Q|%11qyji@@~q`-S)68^WJk{(3hdy;$L)lz<~9fWwR@G-Il8T=3^P1?8Uh zAaHn_rs$EnsE-G=4Bj)yaiks_dBW@~e^nS1uUndW=&SjR02q$i;a0}m-)ZQ(az~YI z)%+A+E&A(DFc4I##@SFtI*Zu;>hDU%X{EA=kJi3R!DY7 zFDAQwcp{)}&hs(G=#Q={lx1LTI+w7>k<3LI_}k()WRBqRhr|7w_K-QFToefHX(TGV zuIzFtFH^n{w{h<=(OZyYxiE8fHlZBxD@zFsv?sb~1Tv$~kFdb=#a?!+pia6iNbyHS zaL&~H>9I@-$yJlJzrk?dt{Oe~j1hr1rN8YxH;b)WzIuyKZlmFw_GOA_QG_)Xo0ex5 znKQ_C-Y;dftng+qm!>#V$@8ds5rnPF3R18|*r=M^e}GnTW@yKsNjP(#K6_*1^3lca zCtIvlly4Y3(;jC9Z#g#ERDSli^Cz29(@F_o7cX3@I>w>6Ty-g-xKH2BI~V$?N_xYl zQ&2Aw7im5KW~E!_5*n_W1i=}>_)(EO5=1=XYyKknzNksM=$+`#=Pzq$Sv^n^UkP-! z7D7bV2PDzCo2-Lqd%Vg2)>6|8;%JB+V_;=YMW?G=hApDw8=0&~{Y(9#8nTa&?S7O& zl}KLn0F30>ZEWccOFXAoBm=F(qtbyqm5V0tZ0PykzmNCnlXHfvDz6ZXT0+1UWO}2o z`WSTj5FGCZx(W|=gwjv2yB|`!cc#zdQfj1=6~Nmic-tc}Vq#64s0hkUuD&Kgj^QNPYes$FeQOq>pKbc~ zeridoUd4Y3Vjg%;Zl0Gg;t1;|XqDhfwHwT^D+II_GhBOv$1=iM=U_$Z&! zXdOgi6m!>J!XR<+4>Z~YB^=Dz3(-|vW<${Q2vav$z<9~24#pm$QF%EWOFXQbC$ zldWAJv{m3A)Qhg)#RRHw)0T*>ny*}O* zV5b{jcG32ec312Eea;qVte@s@J$)bFmjDxYQa10H9saRAn>4(W_s}TtGcG^PrdjgI z^p_W>S@`?&cxPFoOR-VIt9y<|FL`wh{)N>lhxp~TGZS_59LTNWCkxu39~8_ll>N!wi@!vMyot_x`5NW7Lv8si`Ut> z&dnI9jNYh>XfE6E$8OJ=r%952Hj?J-9W_xFh@f2P_8Mp2LV%kQoS4B{?6u@aPcweO*Sme~ZM-h%=0`js2kvNA>O!~ITW zy~sqLtxk6oTE~>bp9xVBDVOx}zh2X`e741NQC@Oay#L+aPa2UL@UO&qK?_)Pwl}8_ zcJv}OZUj3)MS;M{zo8x#fN5>|U(U$?RqXQrU12l*7UJ8O_V|AYFJHWBOQPO1Jmspl z3)^HyK6)km@C&?K>DmdEfVd_tujlgQ$Pne!2DqVMixdi*7-=N3e zPfrJA%t370zE%FQ%c3vFO`b`-u44Jq&a#CI9OiNtWpS~x#CXG@R{=<_fYbZ>($4Vt z20U_3@u)-`3fq*M`%rzBKY4IngTG)mXoBZ%qJjv^aO&FtYju^E7N2JZG3bQQvD%FN zy~hD(N1!w^*v}jyl?6;O+4=X*y~t1PQUdf*@XT!HJQ~4Vd#?TN$+HIpM^Rl3&<0M+ z79ZE59Sw zx0lKk`7e+2pg!Kr5c~`Ijwaxje^Ovqu*aa>=lDLcFpxNrnf?hybWcpS`nCJe8$}r} z(PsLd=q!!;oyPX}ngwl^O=&AGJmoVXS?J)PWQfk{BzvQ|V^8t^91*f*Fzu-dmHl+n z4RacZy%^EOvdN*w;eM`QL^z}u)?ZJ3xCHVn7Tq6kU$3n6j6y#?xUX4JB8nX)kb$ze zT{TeoK%%prLR}i#YK7u4{_`8SM*yotv&)K>Faye#Psdr84t==ZuY87UHz&*EEA1JQ z;v*!UqdfQZ*>mjuD%WF4-NEfpsv`AM{pi5`w{1a8<>cL^W@nSVv7p}jdiM@ZmCbkt zief#x*Kw3DC!E?l7FN*i4}~5=l1IU%V3AOGv(p#HnCCs$Qu&N@<1wcPv2LBEtH^J9 z`lJ;QeTi^`I7MS}7$mVtebFj%aubmorOu6%7j2&YB$|~TZO_$YKd9tfQVTvr>y-!F zG>+9ojW)xe+dk%#Sj4$bNS*&T#)2&Ame9HpGzpj_-KKb7Th-L(TABFf^(!C>UzpSC zP1L349bUn@F!>aoc#e?OWqBCZ0rYkQ?TF|$Ot0of(H+DmEnnp1eZx(%PlH5*LouCz zcvfW)-iGMYLi&6dD+<=A4MFw{0%SG_Z#O5rtdn{QM&zpFRhlLKW7Bnv?r!e4_bcL17KGRd9Hk6m=7L-KNuK{QAhtD)56Ete;xv;<%2$zDk95JO;?h_W7^!iYF9eR0`v z=#v_(upWBn3vu1|s+X-{zJZz4ecrVDUl|KTEP}uSKSe$mt_CNx&FIVgz7=-c_Mp|b zZjQ=(wfExrA9>m&LAMQbNpl)0D@1aJs9UNFN2tEN$Srn!s@}vlhQsSGwGB^;@6nfy zr+(9rv-?r~!rF-SBPsx&SNYj|4^44=P~JYq=Q^}_aY3XfvH;?jdZ3+hmFIoGF`8tgy!Mn?*^Z^&}b z2|8r+xPro12=aw`zqe&XH4{3OG1FE!H+`l@GAN_`k zaMnI}f2u(kfj8VxD;a!JpvR+EtxxjkYpmXYYsUN^KLtApN=hWYGAx(Jy(9I(nA{B##+)`=fE=#Ptc~Ka+1m zw7IEUg2mwL&1de{yOPBn$WFF1^hf-Ox>$K=J%A=Cj8+gF8Quw)7ii1yx%M3q`sdf_ z#}nU+L-zeEgTTG>J~!E>UZnn|bg&Am|Ae2N|8loATCRSaC(!vH+mm1BVBWf{E&;73&R`+)>;4I2A68>v-vKTxg7CTVBj!4lIe}eW-jwT zT=Fq>_Z=#cT1xE1D0)M_p)fpU)Hh-9)$h%#D{GiHy(rn)q!O+O{99OmgvXxa&9daE~bIN$H{>umtOAZBi;Z(mpyXO1p7alK%{M4jts5F+)#(|aPpNGkh|BCK( zzpS0>O6!&bFG;gR4g>}F6bBS>swO>21b4%?XRkW^-E>C)-hJvpRXVX=SRDMdaA zydKn%8rL=$JelM9yC4>}yE=qk8X}2c!XbdIKES7XEyZ@0%B_ih6uhrgN#w`tWDq*3 zd-T^cJ?7X?NQo(bK0~R%!wF!zQtZq*E_u13%+Ic~RMjHOJrrlqmxNzz88A1Ll&}+u zM+x5P^rFWXwq+<$1n}=5rXf&uRJKg<0yQc(-aZwXw*++N``_OH@e9kzZX=u*Ut5eY z&wg*}uYG}*j^=qyx7xO$`>s^gPmqis!SdezW=2EU+r!;-n|nWQ zW!+r^y@TwiOBdtsh=g(W_JZG=OJ6sQRRQ)L4RnGezOZa5cmVivAHkoK}~0@(*9Xa<2yeKiYQbgtS?;e0T1&M4)VRyI@oJ+pW< zELLRL6)v0k&dUv->U|~Q^bNxmOJ+Dc3!=^V^0{=`SWgRIzTAb!APQ|<6g}&Bis>0XdN_9xow4?!Q9GAE7lwQE5dzL` zjyZ0&${u?jJ@hIM3VQ>$Tx5-k<~ms-Dx;2!YGGtN8^~=eKmXAR z_ca)pm7;#Q)@BvE&<)Bs(Qt_p4KD8S9q)UV(csO$ zl<+z{tJB+A(eI}`LmUwjRVi`b1Xfo1VD3Fg){0AiJ>2S?>AAXM=TPx6K<9*1Yo$1zUHt@ND%%66w@bn+3_C z1C?AfIvemJGvJ^*bLy6y+QLoP=pr5f^w;yAZ}ccswm4Zjxw*yP&JPSR&vqX*X<8co zF5Yvx;%p7#X?X=YG)5G3y*5RCDR${8i??`6v$X2AYpLZF+0W$N@4BON9q&3DQkjBd z!ozs#Hz}-%^F8Q)IeGur0ntTdiRO_q_Ym5%f$F#y=3cd8*^8`Av~nLx;>Q`ST^^6e zo)qt?2~L{0gPLsn#PmFh)R%w*3f~Qy%LE!Iaect}c&u`p~EkS}AI6nHjE^lGNYgO^6GSbP<<`Izt{y8r|7BT70*ULhj-29e>_NH*%^ee`uDR0(zsG$+>?qtme{vGV`CfvfT+u?mja4JbIo9Vkb zu7X};&sSJLsTDv(Vu&7$*qJvU`O;vRVSeVHYP0w6b*|zU?tsL-)+r!Ej(F^LO5;}7 zPLCSlEXT+|?|I5qQQ%e4tX=Ka&Vsyo?uORz40SK;PNaUet8}o7NL+g(ivQ+2*+)axUWarpNJ#|xK0}HZ5^&(2 zs#0s{R7&)5)8SHzhi2**$A@P~E@I4xVVgZBEhN00$XWX9)U-aIPI4=ArTV*xwh)U5 z;`U=;APZNsm*uc)USbmJIAdocx?_2tM43p|=-`Aaf%PhDidQeQ5O~Hn#8UJCoW&yn zG}ajuYik_vI&lJ5$+7BN;7T+kw*+eGQe>Z)9aw`2^3pF<4yXNz@f;Z>2=B^|F3h}d z48-IrqheT^Tdn(dZ(RLBSfS2CwMscs3wbxz>xQ;dA=`R1MP8f`R3`%%Mq}x*D#gY;-hr;rAQ)GQOoY%=h-^!RVj;3`y+LA|RYh%L*lL=9Odo?sUvr-C^mMtl zK=PkuVh6FDGzPoG|moFJ=5|L#(JMRk0cj^ zzcDKkGc^4sMZxZr#SDyLnCDT&=zBqa+*9(B5KEd?_hE`kdB@CJ1?7Q)N>SGn8 zurZqaXwZy=){`^7d~wX>ke4m7x$d_Emup>I=Tn&+Vi@yTSKb0bU#o}}swmKg(q*A3Vb5>IJ7>MrN@s#nQc*8Bn z6EZBaWy>dj_Ypf`;9`i1?&>XJ)#xDFf!&4Sl;{PEjmOv@FS*GJG<&Ye-np`MQ=we~Pl6sC6xLQlKU^}vIx2k@%+EYKtD`Y+E{u z3cslxbb85!qEk#`+IO_?&BT7rn_;)ZS8nXKZ`VXpUK zc~s#Qv-fZZ&;=uf-n9s<+67Ex!v2r-2)kWM(%2=bB{kDni||YN1mk1T==%36^?Q!} zn!{mhKX2Qz8WZZ}_LCtv6r7tV0{=uoP>*tcvS>0)fbn+J(`A(y1q4W)P#y&0@H z4X1Ui!`*Hl`7Y0SyYrCdi?~GqX}S z5OUFo(r&cyuHvhr6GiG6jGQYo#_C^qbo}Cz9f|%=w$Gh@f?c~uwRH<@c5cOF62W`t ziP3H%ke&X=LjND8-v9pBGHGjCXKXQzHY9sYaV{tCi8t8>6`$R6I%um}B<6Km1TNyF z@1T5M|MhvPP4;3z*Xcd?qtAy+pnVb$)mj=aF1@w6$9Sl>OmI(ebQOy()mPb%Z%cv< zS+P5#x>mU>o?)IF^EpIk^IsDZkON!sZx%!4TeDOeR|JPu9<1g(BB%xaK2>CpErI`t zhOId`!d}d`rdp<+{<6Myo5{6&^oF7QbKaRUO5hDpg4-fTu#+yBT|MUsT`ykWx)}mv zyQxZoLr#oKQK(0sx)CRyS;*VXTI--3Mb(&C@eG;Lai_sqbDU9j;x>L;>ASsl41wQd zAAoI57~SksBZ&UObxXNLFSIorZSyyBn9?;AYUN&L!}*qNA?betWCIulJQ1yjFaV#D z@?xAt;f!^#&b$G?6ex8+6z@Pj3J4K=Md2wm;@vrpLAAszZ@})&$6tz@0|kd;q*0<3 z7nhNCLgMZCw49maoK>$Kidzbly6@y|m--FE6+t@-R5aoDzU6d9FouaEoa$7}qZFia z$`Jb#vJ7C4enT%o{d|Qr=#CWJk8(&f)oP;Ik~@oZlbUlM!XVL31V^&^YNnHggb`g^?ZOY@&n@AZwfGl^nI~WqurOE%Z{fwED@N%uJcwaAaNHb`fbkRH6JxVdS|4Z zIHc6|jw|ruK#D;_gOBZpe(=tJRTBAJ@-Y8Dti5MY)6ussj1>hDD<~~0C`uKiC;~x| zE`(mBL;(vRL`o2XNkm0Nln5v&2vJ(-5fJG{MGQryBoL)VI!Wjxlr-=5%zI|;mwVp( zpSj;M%n-=VZ?C=fv!25K<{hO$w%8nsAahp#d}$&ORi(=-`dq^v*+Y677X?`2+5kOq zS03`Zx2c=MAi)4ulrc+KiZ&FghYCp~V?e8wwz5CTGgxYPC0SHW_a;GYgv2#GYRAY& zbd-54YIeM@UGe-qx&<^g=pJ}HhdR=r1@DcVTh4Lg%N?x_9_|P*72rDAayx-gYw?6P zl6Ao**8=Z_sVY1a2pqrh=3p5x(0w1vvBwiG{G zT{zVB^8};lb2|*a=3BXcUsXFJl8LQ38eLN_CKvUJIdx#6qR;&+#>Lww>(WL~7WOlA z#%Sia<`QF3HhPhz7U-c)=1FqM5Z3biWv$H=!md4LQJkaJZ?9b=anmH$#s#n%^B1Fm zsCP~@t>b?-8o_-mxWhx#kGVv9F7nqk)x6}QzapPN55PyGS@z6+*)`Oho{BY&8Vu5| zCu`QB_;>g8dB zt9p1Xx6g)yQ9=?t_~GGfLZ|TY^rsU~gJ*$W&}}iIq*sQbB5C~%ihzMztmKN~P=bRP zp_4C=72A51^;Rd$B-@E&NTd!o16_NBpi@9_LuZV*v$Ei{PH zjkOnkfO>|`J?Mqy8#os4V++g+uZJ~1++&aiFA}D&dRxQf*nbW%OfBq8cdyw5LbEM) z1Kr_Q3SmDI-E{o$BU72R=Q>YL*VCD{IK#czn5~5OZ06lk-6s)kPG>IoMzr%8GNceX zl^0;Ea)+y%pzFLIK~t(ImVLGXG7D@Mp}$1{L;Yhf{1ThcgrB0iz0^LVua2D|@ql9@ zdOhQf*!8?+37ww?c5WwMS)1TLkbB780#VNRU`&Nrf3BRxIab>j(P!)|+zF$j7s~h5 ztKN7qw@s;KbkQ`7z|VUw%>H#vr)OOm@G<%IA|W+LCvuSCkk-V)iJ4Bkr@j&VsqRZm zX1^z`a%r!%VYcCt17&u{xl@=e8i?@ozCuzkXT>9GVm}RbWn|?EWNm(#wGFez?^K}8 zqUVP8(Z|j{rS8(?_rPh0wRwI}*}|uHHI>{=DY?!!V*Kg zYXt@m`H}VmEHg*;zJ#0UIq$YnFQk8k9kj)0R@O9Lc_ZmNEw|ijxI8)r`}_6)Y<5;7 z_a*j64UP6)ydrW19x_?AcJUi@Hhchn%BA{L1Vtl3i^E1Pec9ZFTX$=3){z5P0PH%0 z_z^GjZqv*epN7=RIoHhc-Vbw;e?{hWKCo2&isXk(Osm}sm#U6?)!f#hxdH%H1Y3B2 zdDe30-uHfQgP#tbE8dBM+dD@`XvTV;M?L3a8U@&9K6R`z_&cE234DIf!lj44oB_?&sqa(iQjAE;FpG4jG(N z>&L=)L|~jltY^>LRiH)%E#6zeu2OIThutSRA^HQ8-D#D#siSaz*SAuat;FT*GB}8+ zXxQywm-3pOR=TZVSqi}_x|l(pid|m;sWtGODL+bNqSzT_8L#cW9?LR$<88_a#kR}~ zNjyl*)zQV5>U0 z%Lk5eg`y=(W}rR{OKk_1Lq0_ZU$|2Q@T!8I?pi^mrXUkg{&g;r=-KZ-WHkhj&Z z4U9qKX?*p$*Pac5>fOgZRo!Nhhp7WCb#BJguu?!l*1>D@V=1JNyW}(j@{A|9hK{O}7Fu#Z$B` z$1De&Lct@LbQAk_BY8Nb3=+zm;rh>x(JuOSeTpsN8N|~Vg;+R&vr3@k0vA`^AeNS@ zc3IpUiM1aXmF}Kxj|Vh?;^$<%_dBipSXW^?7QP~f29}x7K+d1)n+vR1nhHaiDp@jZ zjQ0s%7Zs4|uTrM^7H~@}Rpn9@N1DHO<|N1R$%HM`Ec)} ziK%%$gXj%XQ;gP{hO+G%QJhI?yoJMDjy~w{1#Wz4q1kK&Od=knKHZ>vby-LL&^=Lc zG-O*PMsjUX0nLrGLt&J6tc_8-kIN*8Kt=yW#)=pZ?Xa5bwBA>f?$KCyk0uc#*acYu zYa4lVpHl)0d0B@unr~It0|T;W4v5I8q2NbZHj6tOu!p6qXByF4NMDBe?O(Z^%dT0M z-6%ieS_JS#C?$5TKJJ!Q@3R11rn%l3SBtWxV;Lp^CpePp(JwCjWBa%7Zf`L*&l%YSP7*l;yZGP z^u8bZ=e4JRWXwO{M)>@ev7)bide7E=lV1c=TYxBGj3k>XtaCoY=5dU5ie5* zTyMdp1u-9D=@s!uMRuwu?O}$dn(YB zn+v{;V1N2_wX}l@fGL4|H3+Z$FR#Ip6;4up)blNmZ+&0w!}d)vEg*0Ld$qXekmB`R z*{B0$K6LqGDwlTiKAo;@I0dZjp?~P}W%E~@#^g0+s8JYiy>$3tYB0u;|0|9=z~8W1 zZR@xv3R}^aVY^!r1e%NGl5;2tSZP2P5R$|(T9)-$!ofo;* zbvn(*8a9Cn#!m!mrx=*3yfc>9G@eXc@jhi`pAttg&p$DdY9+yQ>`mqwZU94%DgG+| z{mNj8dq)%!lmQdj0peyOa-v-g0CpY>Mcn$tp1OVKZmWG^A-$nvZy(S1!xf=D@Al;` z?7p8Jl1HfP@;_?X`1QK;SZa)7{gJoleG5p}B^Pj0G?kBB!{5h7e(*$9@;HybblCyX zv?G=~nJZwGy=uy5iE&r|M`Q8-T-n_%Ewwt=MC(jlA7tCG^*iloh52M7J<8nUK)ay< zCDXCIOy0;oHn073;~^0(-dy70EDsaDNGBCs;w?1EnA&^BY36_tcy7|94$4+wI^e3wn_;{KQ%<<3W_Xf!p$Z|8AoNeaNDN6 zDF*d1-(2I<7Au9xx1#uH%EncrWHM6OSUg!7n&ZejL4X& zCdD_P$&U#65^@tEWV<(8OOl0zD20K`F))AC4<5-RaucK+xVVAQ1d#0 z%h{g7JBI9cqL{^=jEsUTI@O}@4-q`P6c%D}b#$7{_10T71{`md%9q-wz7^QoGU4lW z*ahS1pLe@!**+cF$u7@eJMJB6ymc3xA%Sp|s19R)o4_C^(-1YhT{$o`bLaiWWP)WXlH2RwU8Z; zOFBeysQB_qxZESeUlBRzAInv9|3FsA^Ok_fj^79>hlP3wop|-gId0nok8ahn6ghUi zpexXp!J{);NHx_ z)*DUN0z=c8-I{z$mMpt(r|>a956hII_J~8c;LhK)mgseeiLc!yXNUUQr2Dw1|5V)} zIO9gZRWAAr1diIPd!jh&B)>*JOmI0hfAPWZ@cr%dfnE!n0y>PN$6W>-$Lelj$cN}# z3<4GTiT&fWjFY~DAcVRbCD|1|Da_^{-Ct;zAuKy7UvrwN7?I=oO@DLT`((rjm{gX&G?uArv;+3k9R%a&FG5V>+f$X z#~1T6rwhd11Phf?fuD|A{Z1#Nfc3~}0JO%^G7FZs{HQujTG{Qk$5L4HAbkGfwC%b7 zBKFz5gCFlerV1n`xApR!_F@UsCDPnbA+UO+54|kv#B)FXENmoUn>)&B1y$Oz8rOH_ zGK1x@ApQWB7qe1*+MF=aYxglsN`^zQj6lmj9g{7vWD)^)q{vx3cKdSKi}R^$%h@&<}FxtV`kZ zEle#1RH)u|RpB`DN4@)g&h<=={3We-xYeT0riy)Euq8{ZppHs6eR(T+eaka9C;Z^7 zoRr-{L*b$_W8VCNpZ75mb3J076JZV=OsZ_5yyPI%>QF2Er#jR^1X)iU0cLF;Iv*1?nF~xuq&ZDWQ{f_b^8z|=Bf7s#$b)ne zNVhKi6(PYK6`6v9*VRVh*w3uIF+SQbd^SIlm~Mv|uPRriwy?4aKd9TNVykt%fxF=% zZEX9*4G|kAF3;T8A!2#SG{Bx@sl8 zdQ?faIK!CB+K}|=SkdMHMQkIsEGFjnS`61wwWKCLL_?(HfW4JE_?{$JgacP8E6B@1 zJ*iIHdY?AgjG2KH1#C7ndrN1-@i)qy@z$4dPPlX{RNwtMwJ8U=00c{5Od3IeU1h7H zB(f8?;fO|R<(WRW7rOqExYW-m7G?`23xu1?v&q3)HF1v8{gmYpxR~stc>NR zQGL9WrBzxOig*McIfRQF7QtLz^}g|8k1|QwXoHs zOQ=w#W#otDqMSEvZ91fq&-VtM*^a_HTFzAHSbu}X(I+lHbaB-&I9?AG^RtpLhyPjf zF8oKQ$}n^-X;BJ%U)e8tVB?~^ZG_8x&m?kuSx(L8_sHP#!Yo7tF9XYjv%D)juw5y? z8!uYEU1AYFRBe0_lHq@@>^R&UDT@k~ndS`B*~=*hZ{>KX!`SGoN58BM>${78+8 zMr+Od#|L)>E^WcFLJ>dWNXCPQe~B2zJMQd_*|Q@leV=aF$pm4k#THAzYyqw$#oy0s zP5T9_WNnVfOGtdq|K*;_hOqDpqz21;_B)<|?!9w)wEP`=E~azzaoHRAk}Nh9hD!bF zh&Di;Uob?ub=eddSvcRE@?4&N7EU&VL6e@!FH_nV`ID8b~lW{O8#onY*W7SIwF9U^}2=ASg%K5LCk3V2d{-qXQ1f(eDM zNGr^l5IYIIFI0WrK2BWU|Dw&|@+LS-NKOLieSOy*Q-XZ1p|p{262bMY{D2dx8nSw| zR$u|f;~O5$vc8lpX6KO&yytXc$%e#ZfF=oNNn$p@_S$8OEoLl&{p%%Rb)9PbhU)^; zP$zJKoB&O;r&;@zMA?i`I*Cf3jK*)79F2H5#>HUC0$fwi!z?}KcY_pVTjP`rcMlpY zb&>r6zXG8QzgJf+DQJ`?dbOO}yuR_b*_|u z<&r{in_V-_a@f?@7UXR0W^;YU@dT2Jv|%`{@l;an*;WEbrF;ZgRK{UWn40$XorK}N zKEY@!XY09`60l@rM^X}*@ zvz+r>}2DyY+0oEr0`6ZVYkkN_JE3!U0r^T;kZVm2(0p9W5cCg3**lX**I5 z`RZo>BVcQe@)Y2J_8Yu%1cBfKUnZJ1`%E`_vH*(a$u}B$9$DkoCHg2E9TqLY2?*XX zSkp)2doG+_wLSFo!dP+XjqoYjVV$s4rZjh%17&&PF{-b#8~wzB>>4~a$h>NTA$kQC zz$(LdWy=Q9;wr8S)LXmM_BnOr&{%|34dk^Cq5Z7 z-#EUZl|5G_mpj&**C#A`!I|p5Sn{;ye2cSKYEomNXS};l)cX$~9E##8iNezW2AKQ4 z-^|8|;JV$T2qdkJn)Qf1qr08}AH-`TtSjc%wy{yND>pz?p>BQq=D-HY+yDq{MHv98 z#X)7VMlNssH#Qo43p`@^kTBI7qY24|affF%U(t0U+!1Rs_{7nQtEvqWK1Zy+ovk!k zVz6UR@8Eo94WHsj2=478v$;YTXBB;O`(Kfh%;C-F8cBEu+h9W_-Is}pyM1lT{BD7Z zdi1KpTib}Sd{YiC&aN?N)1f`5G{una$uYPVlCgmBBgvpZ5i?gSSa-ajtzU??1&@n6 zaE+8~Ah!Gp@67-s$?mNv_Q7pGpGF4xOwy^@>cAsM9(Bb9|1 z*%U_aTZlH?gaxy}Z7zl8sN$bGP95u9!C#RT;at5=pj~Q_ZkGUnzsb#$;>fGqQ<8%u zWxj;q{ZIFM@ykr6c-u%UB{m8yXASH zkg~fI0(^Q|G5w$@U5el_-YzhFGL(yh7#ZRL!I#19M6X7Aqj1QPo}`gHXk9UJlmRum z8E(ydo$9+k^S%%YE5or@EpBxt-CwOixf1f`0&8YRE}QV`6c;VzLePLxQh!I0X}R*# zX%t%2rF@GN?Z4o=#@$&QXsvFx$C(*fe@)wg^ejblw8bwN3>xcU7++b(s<9s=jZJUT z7!mD6#NMezeLlCzJ$;F=2D-GP!jK3!yw^8{aMN#9S8tW>a9R-8?;Qow#bwUGC@r2x z_w7@>A6=ZOqKe6DyCgTOHxlKv)g!odil>V$m!2N?+_}My%WHlv<%3B4`L32 zNn~JudJg%8gPmb=+ll-Pv4ntYeTM0c&^hBPfON=cBAK`*E?`UKE$zRz2GT{j4JbUW zY|+_?vR)m4!{@;%E4Vc}A6@^vxcp;WL&#*ieIWU~tLkyNP2)8^gXnFLzLjw-@KC#G zWn`J@&7Echo4P*G3@k8(-}(=C@JeX+p_PJ%N+S|8m3SStK*)iIQGxuGhBZ=t*h%X>z#jr5OJe2_w~ z8#8`|{WQ(56> zhrj2Kd973yy0-{zQy4}_UL&o+2YLhD@&iXdHeDr@+Kc#soQR;}?nU9er~nb78tN*4 zM(%kl>rsi);D<6>ZZ#U*qddV3i;}OPjZ&yox2YOF^Gqn62EngsHa%)<#k}6DIU-tq z{%w3Ag5HBxyHxHw!J}MlE5ggbJ_yi%$}duz)}Ul1UC+Ur%~0Q2v$5_K5u%lg63OP z{V0_YbKDbS+ooSv-B~YUI_+b0)+`@hbi(7%ABKXRl@Nbl*o+I=nzP?f@?zsvf8tA) zO1taXAa+e|YA1ug=tm|w7F&#r^kViHMRD4SH=jdlr!)qfyRyy&B)V0<0zQhY|8xFx=^%#W@)lGrwr4sp3`^ zIlXAmdi1$bqhU}5*K6RO2{#-#JJ1VdcgsX{K8Oo9MzyGYrmeV#hNvT0;X&?u=Sn}v z`5K+B*z)xS>(uw$S5`r?p_ij;#(GPJ+QeeG#b!z0vzx|yukHA8b<;zAA!&@Wnlqe7 zD_IL1_Kv(-yDSzdEyTm}iQMRaUs--a$(m6>jxJ>knd~31t?JU$^dCa0l{LQ~%r|S=)oc>yP+p4XJ z?uiUH!UY?`M02@>XUB!@!Cszh1?T`!P7Dl92N61pqXHIb<)(+WbM}Kr*^O_4KvJb; zP`_$mPE?N|Xk`1~p>e5qBnrMIo;NaAeDL*#PZ6_LxEd*b(!!K&g>i-$d%1VO{%kqxT{wVae>J<_nYV&tX`_ zWkeAOqG^{pj2tUNUkI!(%Fe~^@jg0i;+7PG!FPGx$6~hSssXyOSL_4%3kOe@hFHg< z?UaDTM3HYav)}ZR43}0cn=)0nG#O1jpyd?AG(HMpA>I>WAGNgz>%Av8s0#> zCFc#&lPuQ4(6p~q9R}H1+B!+9j+N^*k@sQ)MR3q$it+i7WXuL!Kp&o*mTF}nEoTl7RroA^g+$Bqj&pcVF1$}YneOEEG;rvi5RPUAsHiJZ%N3sIqQ-?412~rp;0ZYvvskPi)GM)cuxO$urM~RY zg@;nEw-w6t6)MQ%nG3Ln-R5O618)^5H%2f8h*{aZJW9XWl;9V%d3kL$r(WI+br$hJ zkaddMyOsS)4M@-+@YUGQ%7CBUe&ER>WAn1ob$LZrn03b8t5-eKo`LgOvITH6Bl=3r zd0{aWy>u#jXJaqU)!m_{_<|kIuD3SDi0KCpSsQ7K2)R7xl{NOC7hqvT+=u`v>ATr2k+^^Sq^G^l9NSA!G%$eP~z*_2<6e2j7+tW$RmI zm<8N3&*@^0+|*P`6EI*~2YJ7*2d2ar?C4bU6N$v2LjVl9{lnUa0l)GF*u=F_a;5)j zud_FdM)@8q7HnJLqF@v4)_u>t+Sn8+Xo5U*r|+SU&7`e&GRP$ju%#urJGDaZ@bLNc zPHbcJeZTRuAm&ZF0;YgnCqh4wX0ObHD7&m+*;!F{TiSnj5&r`_^gl9e_}|~}(yPBB zUs5pgV*NWmuD^J%73-g`BkwXOVI!YyZIN~%h=cHp(Kp`>>fYCo3{* zJ}cLZLN1R&weYQ+OnQU@MrxHutV!?rml83iM>?^WcNLJ6vgos(Wrl-!8v_mAd^?t6 zk!qFLwqy0Zi{f|82M`-C&0g_udM_a$0-~5*)rit@D!9%UpyG@2iXM8nnj<`4L5C3Q zdzyiw`#A<(D_3MXi8__gUa#;x>dvTA1&VV5x(Hh>0c?btMl;7e1*07wp8j~5=PefX z{pGW7UlWVo1sf88LJVA7qE|*AcjKC=FKXs2oh)nuRo=Mv*I7Km0s9Ucq19@nW4qLQ zBQfh1y+Cq2%a3Yd)_}m>%h`?OjBgw@ozM0q8(_ie?_*IrLJuamsPTIs99QC zKR(IdZISXQwrQzK6c zvAlN@bjxEtobX+x_p>1Opzqj{gY9hs``A5wW4 zo|&Ei2w}|C`xwUdtgY@3?TaXfS+5Uel}0tqZHWU{DKr-2a=3_Sq;B)82P*Aj@bb64 zcvu^odmjMrsfgKG=Oso}G~^Yly8YYd15%VVjVL_`HFn*2`hXK*tj=ve)63%!tDxD9 zI}U8HhMuP~C|^uaDb+LL61IpL97Fi2pFH&WYS|VGPY;n1T7Xv$T?~Gk|*+ zh&bA2%$_c#_73%?p+!q^9(!w&l&dy#m#}195wMRmQ?}NX^z@7^PBLikwN=!mI|iyW z+k1j4RNGE&ctr4Vv;UZNHKlaFm@F$Og>G;B0RkhEEVo~h>U8ng4LmOpZewB&v9;3r z0FnYq`Ng^N(&KKMI!jaw@O`XQ>V+StmFEL?2&it z$j?D1X2E(yiwdUQV~QRhp6dPhHXiTcPki9+GtU-8N^#K`fODbeFJ7kZEW92FY(M?e z%&33{S4QS-5Yp*c$&Jf>Y4(74;`6bc28bNLfJCJUn0c7T-{Y8`#Y%fYj`%$Tq)1WI zTWTR@b^pApC)`&!aJl5vzJuDOQp4sH?#<4&(Pq{aEK>Wf2t;yc<23`;6uFRmB-DeOH^fWa)Pk1;FVEw&+T)u-xkjpF#(2zcU(t@@SIf(+9d$`0~1>WqJlHU>A*{wN>fjzXksdwWD6-*pEtwgENl`k#HLRR_kg-7o@7LG`}*mQ zyskQ(hl4C~_S|W+XOyBc&z~?9V5N_IBM*Ht2sE%Vo+yB&+mhAB<`hv6#gg&1u_345 z)ovvVR@VadKmJG{T(qrw);VHi;UH~LJjZQ1ugXmo)N+6QOJfd<+k78{GnM{4z>&GH zFMr{Ij*y_dWOUgby#eY8*c@y4V2!jK7TK0uU*+nJzOCV-kHYTDfc`vN{?-q22#vUf z9SEPRcU$;?qJ;Dh=f>N{-@@&Ig0IaN#bF!;0p3F|C%}B78q-BNeHvfdYwqd zzU!Q0EV8=nMRz+F--jnhaD6tO93Q^t0LmgHik&yt-8V+!Y1BSpz)SlKy|DSeKV-(qLP0yC4b!ayi<#=#T*(tWHEhi+e3d1Mr<&GNd1R{cwv<=569MJb8j|>~OQ#()jyQeOuI&pjUuyl6fT+ zUyYSsgfJqGjTfZffe(jY3K#&JnUp}v?^!A)uF4~qkz0PnazsR+WC3dk_tgQgyk8-o zipc9Z`};Xh_yy_X90&NKG{$_ymOvQ9E|E~X?f7Z-gAV^uw=F~GWxa*?v2cOr?1x??!iC zvSGG)irX=(yiA4~J@Hpe(H@1K@NU_`H>H;&blEVckdLfci8yM^p2ya+lwY1zvhPp6 zXNn{&c^FIw96mKD{2?L6%E*DOx~RdFSB!ehoy}c?PYjhT$w5!`H*JX~yqr1XcX{|s zY6MzOO6uuZY&9P`n^}$G#_*#Vw!}qRoVXMK}`kLVM#Q;ue;zbt$b z2#wD8-f84dUycl)F`n^$)y5%CO|0*btSVOuchd@y8~PqY)1Jf5Avu)qKvvz^j2rRk z1;!#>BXdo=|7(2ne{Q7ywMPHBk;Z>3bxh)0eNy}BiUt-{TvOEf%HW^v{T{(po*G$> ze#~O09|=Et5^+mIq*o8KD@CG~O&VhwZAYvtX(RbiP0jC@*|$4n1@o%QTRXqUgadAx zhqqdXunVkAdiBTQk3Lxfs%%5vS|;)O$sxS?`jA0c_&tsaoYi16UBm5>bRE`|%P(@^URNOI|fCN5ZtV4%NZ zq7M`YE=>p2Aoc_;p!U97zuTq!NIh;|f!Ku|HU2o%YWH(f(Wc-*PU>jH;nAgMKVd@VT|XFd54FuZv~lC*bgXv~VP z@0Vx!&eDT{9}ki3DZIxwl9o^JcWT*huHC@T{p@w3GD`mIhQLeBV7OdRQTVX0(rPx= zZc<{PI14EA%H_{_<<4D57vmvkE4UreIl_ZGWH4ubvuuWN+r#(1q;+gmi9(+HG0S*3@Y*U36Ll2f>^AKk=$Inu9-Zg*Ra8 z4%P%kyTv%tb6c}KST%>YQS%%fVJyWhkSjlvhk{5hY zC_0qjDknJu%Jw?SL19#sOnYc|RL$lc_f}c{C(t|k2w4TtQ$jnuEj3C0%;)Fk$i#Lg zy>1->XIx=a$nioQ4Z0MvY^fBO2mScIZ7p_bJ(4FlT*)Hg>svWT3i=0f&+o%I6DD~G523q%N<32Cv`pYVH5%I z`WFQ8!VPM7mhjqw7BY}&hCR1jew8)(ZkUl+Ipdv zq$ZCQQwGg}B3!v_4(o{j=T!5WkHnJW!Z+A=tHlzRf+!^CdZd&5)%26k2rsV!YNQ4Ort~bB z-!B3Vkh-c}8OIbJx5Uc4`eIGHNG<9r)N#vf3vLW#^}HFz{^N*r7NdQOkzc$XZE_{` zm_3?eA>=?PC8M5{@TXP+@<6+c~K(l3c|+6{}U z@1xF1*MPav<=`O6NNZd(CAij%rj_Db+83VS#EtL8r12A%eYgD!MqAtCPQ{i?QDErb zNfjN>{XY3?kf&u+*M;!|Pl$_R3aJ{?5Oz`D_OQhc6%o^IX`k<5VPzyDAokZBF7CTu zmiWit7zhS+%Hs^DZ9h?npyftKlXzouRNuF{u@vo)iidrWQpq&85Kq^9zScO_20&K= z3(|h-ZzxmHq|fWL=5t%5Zf-5ydoepX#2vq)I1TF?=7WSO&#AJkACeDtbD!${p*hYS za}m=FhR2fGW56zorC4=awDaQAHt`3VNwrv+{kz*Kts!~L4Xu;Sv9~nNtll|Ynx!Nd zzq@8dI~d+3UbvJQP$eHJeDKRNGj*MBgRr+aBt8gg#_Q_6nw&Xf-er8V17u^yRm#&gG+>267< z{a|^xqcb8>W7$U2ceRMn>y~ph`4HFr6@4<724AL{8>r>OAID!XIPSmOFiqfdg+n53 zRf&lAjX*`bs1YyPF10c@gm0!02CkoPkt=p_*(k4m>vxXMG!M`XR&t%hB~Ts;$1ea zh4-3%mR+l9c&vdRnPbWH1^-GtSN7e8_x;Ha2b+tk(Cav@d*ayZ%X1me###t`LGQzn z_a`W0-nRdYsgiblP;)k9{|ZpCQN!20EGsEYC3EgFUlkQSsv&Ji^QU4cd~U$)And{4 zdW0*2W2~)+N>*qD&b^l!)vjXptn_s4=si8$%9)qVEkscsxxV3~_+d&u+Tg@cUB_zh z`=!C5yxqhFw!%#H_m#d#gJMG2n|^H6rNBCi$2Fl=;IwFkF3n6a{)(J{%qtAmNNS|@ zwUz?7XB3*wt&Z3@ak>T`Ueh|iSyEc%%fBCk3R@0*uyNlGolE@Y*nOd*+16%ftc+wS z7EaVt=q)^?BHYjy_=_w>zmc|ZN1ST?z0#)qM=+H6@~QM+kqw;`5Xa<1HbPC^+TLSa zWvDY~o8N6k@dJFnE0?3etcx3S)efVw^M1_3`QP!=r%S&(yBI!yKWcT**)RjWyJdZ2 z0H#75pD&;|h`))Ds2`lH!(TAcDf4yeIFMJe?2<|L_GT}-i~BJye)<*4tKz*;I`Fep zcoaxXVS+7PVUvO&CD%?|izc5ZE!fg0^EjouTFI^=SL?PvbSh7JGUk^+vi`+29i<3! z9~~XLe7~aM$Rzz8!luIrVKY~fV9Xa?jCeInsM=Ik15CKi;Kd|-;1T>E!@r)Mo~;iv zilK#_Gn2^V#B@UM!4$h^WBwWf4&DZHtWxCA;M)<)yC?C~!5 zn4oG{YQZE=_|60apPmIX&iVoJZ-l$V{{_1CUrphE?6~sZP2s^3OJiP01$DQN$PH*)kYNf)9^~B1Xncw=LBVaJi zauXOJ56_?w8^~RH>`>-3s#@=d6&w|#dW?9 zZ&}MVqAzAazYbj?HV*&tY6}y`65#9VWy>&tB=TFaLV z?%^jlzmLc19u%gpe7~9%)->$bxwMXyTe7Hijp>jeAYlZ0neZqdK8wxm>P-6KAHb2> z(S$S%g=XxxlEh78KP7q!FVTmlozr)64PMUHsIKiylyBi1KaWS!tizeGIM zewa|aG#aS6?fvi-=(-Vrm-S%{aw*O5H3N^3Z0)V@hRWukV*vS-$9Kz>n7V0O_Dfy7 zL;bCkDRf^8gn~xFb125Ls86&5I>GqTKx$zVg|voJ@nb$2qk&%Ujf->xzxAs5?-lL> zY{TKtN+X#d+G}`@sX41YjAx)2m6d9@Z{NuCz@!ip1vQ}KOIUp`lU4?TpAp8g@}}kZ z6V8cwu)>pD`)9CaWdihc-rc>U5xJ|iTVv~6>!PVlDWpmS`lbaB0@6=hAxtA91(wB# zT>&}s@S*oB4{BCyNf0=BY#?!=1tili4maeNL?XY3Y{!hewk4c9YN-f3U=Xb<^n_tJ zz#@8=8P@Zv3qj0ajjUj4R3kQ%PEH6N@}G)Z=(V)$aA#GAlK~S&8Ox+!s%7 zz;=+GRMsj(QW(qjt3#qY_8c%qoJW z`%VL7XoCp?;{kP&LzRRSjZCx{q})Dq?L+m)#DK{@fmdhh{HI&?_}IKwRiAFEXWgrqDa|>_d~%iL7e;0q@(~ zXThBfTBtyO#{EVR?K~LGNy-hiDQ76Z&8>P7B083|oex-JfhdRV{Q8jK5t}Ro)#LW& zySftw_8z4x%FFAdwV3Yf3d*-72YQ?uz9?w$k=s{gr~Nj0@T3u|4L5C|@1jV!1d@MX<>*mXk*`4#FaIVpnGqL-6sxS1r zq^FdMa`X&;WlBcKh+I)b!s*&&&F!+Kd!~F&BimdxW`m+l8sYa#@GM|-%G{u`#&|(L zU}j8U$zHz}FlHTUboqu~5LvF=5TAVo!4et|s$n+ZL7vs2v!55MiMKt}U%uF__|=a5 zT`52sqIP@q5ANi2^#y6vQ zM8ep>xu>4>8BNX+tmgVCgbmt&^w@=Ys#_aYT%wtn=dG~k&^^MDMM%+mS^=SkZ$a8n z00Tz-7u)4qOL27ctoVQZI+6h7t}HIXNutV>}41 zSAt0~XK`#dn9rr}j>d(zMv>RI$f~+IIg9}MXng^g2Eikg-LkM0g>0*t97K12HMSt6 z>h*+mTHwtPsf4yFn=L!EFmyT78zx*lYu@A7$9>nqvF)~o!m{R)i+0$5g7$FYmJh1D zNWRwLntW(+dTFB{PVkhZFnbYu1JK+HWG0s!tX8F&Ixn=W{R31~0yk|e#f;%v|Lg>= z(B1og7Wl2OKS_-<0d&Zye-h}Rs~shP7u^Mb_5C3e$_vDATJ->Nn?ZuH$LFg7y*lb3 z!aJTz#}S+EHM2Pp*`DnEw^Q?WPRs=Ekh^MYU)*|8%+V3de%gaxKT{Wi@ln0iVFw~S z{1zpRsW*ua|6m)3c}c?6)--Qi)wdcVeOT4>^-oo-eZg4NvXZ+mM&yNIlP&;9W4M4L z_`S#CdWxOuqU17{ePH6J!z46J|A4;64S~c9Xyu20&_rVHkIF^omvVPPEkpVH5E2D`fG2YGCRN(OleTNckh$3>%OEGM&u zAn=fYJ=wx%bw^-3HejFA-VYgtgCrVvD+y zJeSnKK*!pt)WEKV$YB)jU5oG7B4r$KVc>qa9p>5C!hx6B1?8qfW}KixaivOnE#0l3 zl#o7oDY45ftBx2v?&A!+5s&~0Q|c9Fz}d&sxflE0hy|;r5g$6%7AZrwd(bf^HzMP` zX75D){`$={y7-4obkOqtiSnL_Q?Je(D=Ut9)_aOnDSZ_0^f+ak^6U~%bi)$sv0>YH z*>v6c0it%ua?oJNWB^1^v4-s-d?9rU@~*DVJ^KHV`VIeoUIC>4-1Fyu?>W16FX`v# zU2n@yp20k&Q%AjtzZybnwz%0RZ&#_%ecgK{{MUlnL(?r8_p&P`33H}Fy!Ro#m)i$L zHUape^@#$|{lC)JaGX@fztSr@5fh-@itiB~MNAv4)bQQl+K^SOx#BE(ChvK8d- zY=_BUQdS+}+9bM&ZW*|}R1gAELPwAqgs3zD zkrH}6vFp*L{z9NmL&*LurRDZx-X^g#IvB8~+FwJfEe6GJb5nyoXN z2pJwr|5v=m*Lx0U2{HrHF~k9l;(EtuNPB)|?n=7gdj9XyUp>a!mDdCO2XuI_zX2;q zNVvN9-A{m_fSar6I(=)_8QUjx^HBq<$}VT;?S;(r3qsSC7Q!D=Wj{(kUvE;*HSq4%O;@h1D+LavvhEZ`yuK_iU=ww`vb-CP zxGwTHH~W2-b-uZ1xr|Mf_P26VqThEXp|icNB?Ns{DtCjqdL7VceUaU>H)d&6a=%J) zD~=RJ)~dLb=b)%i5aB&8T27x!gmQj}Poo&!GYV67iPPFq;F1^VUt1ByiCuo@EHrO4 zs5_y~8!41^uSbI;qV{H`E=rFhbbvee8eRlBiR!`P zHgY~Dua!f7&$tUWISM7>?Ym_XDupknnnd)k1!m&eAnC zp|6(y8()#66vYW@c5zwRM&2>TqZueTSNo$pt-r+X;65H)LziisBlAr7nBIv%Kc<0c*&4)q{-65vCim1yAE>hODqh- zF>YNj!d9U_6@&~Ay&&W}g&oUh^ zt5smqFgY^nkPwXp(zKqTeHX>nv%xEY>Ex*!3>bI|%@V8lP`*djI9_S}?njh0>6=xg z4C>i~19!NHH}r|L>Q}foY~3pi=Nm%17m;1amB5-xy92i-`d$y{HP;zq#NreC`#%SP zzzZ`82e$Zu9U)TU@|$cqQu=2cyO*YcA*kx)D?U<;5FHWGu?dzshwM+7CeBVi4g5mv z!yrDn%i+S2%mD|>4hf2n718m{3B;GeY^fw&9gGi+P zG@Yrdb~vA|&O#p3RPtdVa{vca?z3Bek>pb~H!$?D1$a$OiU~aE58oNeGy7jQ!z&N! z$R_pVtsoH=^qUU<57qT~(~QCd)F;3>jD)V3yn~^*AiJVECXcn8sd!Y>FD);LUO08& z;u>scEMHQLfBi+>HGiN#D3-8sd!Pg|m;vVKsxECiexHBT;+IUnUx6;1I(JFr<9sX; z9lG^TUDi9K4+UvmBaE`1w&q@@?RBce8fAR=&YX)rX~OYS%&Q;Zh*wQ-4gWN!1Cw_5Upg>Y)?m+_GV!7o%~o^HH`~mM zZOnL=Zy#|W5T71Z6GPzf9t^+6z-i)!#kl5oOQYn3#!FrqoL9;=Cu~H-dE@IpBSaW$ zFw@t7fyqM)pC`tW-_dK>pCSJiXU2#n6($?f4wm|Oq)CEjw4BNT`hv~tJSSi%wklbr zS~SYiv;*#oCN^>RN8Nj6XZ*|V)vSnb`x00Y_t;)Lz+^w5rUm!5ak(Bg4~aBk!Up9ySV1qI+A zu}3eN$WXr~|2zFf%i-piQamW#+TYzJY7xkf)ZZ9YHdT(A>fQ%FY+d#4HQnr7Gf3b@HEWL%4c|59?ANt2VHT;Uqx_lLq)itAC zoq<sXhc|cizPrWidk{%Rj}8#-3KKr$z||OMEgY!QUHexhkc#_o>$@+?1%W2j@M3 zgUBV(g!zmdhud7hFiY=^jSJJBnrw~iSr^nC6FG~$e{)rNR5c0XB5{gSFDtxQxs?{l z?sakg;K9PYxWq_gqV%vOJ zDPSw;H?pFv-(B%)YBd1Jl(y5$IQcs>M<8L?^Xwi`7P6*E3y3oD4q{%R`f4zf;LK2T zRe6@DucBXOvJe3|>#-d19Z(n_xW+*eve`c03%$zaSf8=ShyxFeQ4e{-0HsaHg8w1D zYh+pIjIXc^q@`DR5rO!KkXq(l{lhmh5D=$27ZHdY&V7l4%UD@Z!vQ~tFf1%xN@;cd zep*A7Sq~!(w*r1DDiS*l-_$X!hmIFkYbB{BDU#Ef*g%=C>&K|9JSY%f9Rr8wYr{{4 z72lcJ&MhA9R?mB97WF3eZZTtlb@Cn%nTCD)h}Ilhq6ac_u{a)SxAG$_dOzx~+m_z? z4^fm2KA9ZWJiw8I&fRpj_gqK4%U(YAV0~AZ&5!9170pcd28{a}5#+)hebyrt_awE! zzB8a2!#m*qUfuLrlW&(pmUpVZfxZ6*&%8%J779T|!ZP&;Yg*8G5rM8|UQYXCd0-XU zw{ZVO8dnxX=Ti=0|8uL0|Fi!6Z~0VzhKLLQQ&q-)KF_Zh*kLgRz&>H4qCYBM#61gO zk1|bNz`+YO5BFa~RsDKlQ?gNP65lS%=SkclbHvK+t zn7p(&n3Or54 zTflbYI)r>xbeW_2RdU+y`qaz(6_##~CjjN8$0s*?8Qa3TR{#=|ivuc8i!nb$zH4ll zop{`>i##K$OB-wY@ikZfsF_|l*%p^JoywF!wj!avi}6}xCL0vV)-Uwx0OE&m7I63WuOn}M{bbB}N-!Ua(Fho08meAk# zsMZj)$+?64Oy#~eBZHiO0~G|m>1few5j&=gu3$bam}7+9vTe6I_#w6TtsKFIr- zVZ)-Gzk1pgiNV|RbJo@d76?=-#a|{KT@v-JkZd_p16S^G5wcsS6Tze;RpAZ zes_U~D+yN(^wt2lcKAS>uI(#p!tEx?aPJEftL|H%N%3tyehLiX9_A}uDPVDm@;Xf_ z40*ieoV^DU0LFF(uB*Gsx%mRhGisI=*vBv@$3?j`M=a2sjN?dMfX@3M(x0 zung&z(KttN2u6dEr)nfY zPDxfV)ToZ39w~(Zuhh@OMsD5ciqE7*HZ0IrY2$C*H9gw2AZfh%g=nj=Fp6#ff@4k6HMuw?%fz#;;|3#xa99jA@cF%{hVhy>SpenRlmiEXTep zsSAa<-PC>l8dgXAhq}fZg$4McueFl+l&o(@jZ}R|_oYZS(PUy(@d1*_C+6GHTObOY z7?>~RLM7ZPIvSW`crgaL=I5wdB56QG^;ZP&8XJDxO;mL|d86M#!rb7f4`#5Yl*)oE zY{9yL|8AV{^dHskM0JN$UCBQWTN)Rwus=0>QF)~~m^hCtYRl!oKT8}(5%9(jlO6|Hg&j5} zhZ>D5Oar9xt1M^?vIqx|2TN`D7E=2HH)9J-Moe~IKa3r(_xd{L#pP zBcb+MYEC!MAd~pY<)l2Lf5)v1d9AKh0Euy8i`h)?`dFY;z-`oLZ#<-%sg?OJLg_Qo zitvO7*8Xa?hu`5wEW0&AGdaZ7)&`YxN6K1(XL^IVas3#csOM6TJRtUmuLQZmKz2u& z_7kpR=?y}Mpm)T$1h=kOK&P*J0a$b^foDFQ{e&!DTagdh0C27rHI(O4BaAxJYGgSH ze@0nEiJFg7hq?|n17m61B<`f0S>d8=GCPI#+c*Q?h z3h|V44~t$iPfM8nJ!LGaxXWvsarTncs1@DKeNNE&q$L_$$mXtf0{Lqu*fZh0FI~eg z7n~FvLUVP`p}#M18`*&4^=WO9m#w!SN*mR#jD=XxUe_(?Ximoa&MzoBE*ku z@-Z3`M@VEFLId3A#1m>U2BPFIq1|IOt~RB%lE@8EDu{tSQgX4kjnYZ-c*(p(Ad~Ng z76x4~lfETt+t&N8KOkfR&`0?nJXgz}*r(M|fsA`aDu2~kfn3n)ImiRO!oJW8k`AV- z9X^pKQ1b5cJ2~K43LO@UXhZM#&nAAzs`r&l*aEg{OT9%>_C)}jZ}(#2W~0mpF6B)5 zy<5sG)H-RGZS2K+?LM6#6mZAhy6w#_2UjrYPBzXmZHcHwn(>}e_(vjh@y+tz_9s;X z_A~vJJ&b$>^h@jFZ`dvAQtJ1r6W_kVFc3C~wgwA#($Lkm%GekByJiotFUA~zm2#YC zU+w5B+Exje9#%O15W{xEF#z8WimNy>mMEsB)td~^!PZ|*C8#?}(9i|>WmWN6Cel-E z_dOckt1~;NA-jnO4ks6XAVL*nkOX?Bqpe*M)A|U>#ePS354U$24uLg;-(GE4nIFAo z-|I+dIEW)?LCt?QP}WLE*hlWusye$2o=;s93Y^z0CUkbBs!q;d8nGO-l6iLVo}-_{ zy~}2@Pc!ZBvl?qJ1epKmD@+R^o0L-GovW6kTLT{v+LpixP1C)@w}>4-r?T_;iCF#r zpA+rBSRwL%-B#@X4l(}yOQDi5UTZsDMfOrNmczZEQ*Rzt*Ysf2PVZxra>8?oAwM;@dKj{*ewle8vA*&xY!a+Flzn{rITw79&iKxuRIk|)&E zd>GItR$zASadl@*tRW{sdKm^`j{@~;v%$lp-AAT2MyXz zj){{L-de_py_`4#5UF?#)uF?1ys^GS--CwMQOV?IkH@}t*&gb%*khF0({DK^exx-!21gzOF&` zKuxLCmU5i{0M7)z#kIf}jv#A#fBWVo#N4LwOW!osVfrD@A>**>mu*shl<3s^fd=xv zEJ-4l=m5!7tabY)F3zq9C~iXM4(zU)`=2YrbS+BT(jw&*YDRAc9|RIzHW}3?=Ie)x z5Z}ZK!~!E2TAqLSLM&AP&Vy<1%*7RUW|^{L>K8Lp!}gvVn`7Oy)}+tiEnMKMc*%o8 zeJz}sg8|Vy)93sGr&}I^hZ)F0-HZ3uE32)Rirx-umLr=FE0kHnb`J>NVsUlZWa)4v z34gBay}{xEVwFVV_o|J-f)%o)pEPw&@LNr6dOlZSZEwPA_%T-9I7jkeLc={1-1Vq2owC`X=2<) zD{%b6=PW}*&|Z$l+YlsOL~rG*f$v(i(Z?Oh$t!|^>7@&@MuLU!oKg1WX|O<(CNN}+ z;ohOaA6lvfKO`zNrf<)0`1?dDZvWGTr!?tgzDCw8w^M^MaJzWU586IHu2Gus{U6gt z7EeVVcz=Ko#=L&?o}?&C+MSH?Y6;J%_#i2Ljnx3=^0rA62flN>B;SLBotic-)N5<4 z3{cx9@$z9b+yWPed-RAAwjlz-Z%}@0m2CN0^@6_~K|WnT(e)Ts2aYq285sg{73YYG0G6CUN_ zS>k|7GYIGSd(d)uV57I|6~#8d#9mRx<{*m35<5cjPL ztOe8Rsg@1U3M>0Bpp-m>8TiBrh%^VbzPNYdcACWSJ}bR~lKL}OP-SOE6cKu{L<3rl zD8s&#>6UXrtRD-8)8ZeuYVCHFLMf#KOjJHjoc*ab#X-yD!0v+>{l{Tn?ypEII6jN% z9_Psf1x7P33sJR0JKp#3G1sGFE-ZIQ2=AOMlN~-^Sb_2P z88G)493`DgDR!!wA(TPV+A=vu4sd4Mldk|HI`~l2^Yr;!tp}>2HU6z9qKs&qx*g@C=2H?>{vLltF8)LxHa~ zOH z91qggKB?AF_9X{L&_ci zG(_j$P9*U7Qj=+4{)u4XYQB%X3q z_RuS4c{*-g4!3Ky+vzD z*nEtSjvi_;D!>#~hWPttXV+2Ak6kZ~a#AR3FY!&6QBw7HxM8Tyk3v*?AGx$kTVb5u zqSBLzBy6{JYV}*S(z4C#SDmz_@+xt8A2HT2ge;}<#mT|YAB~L5;V!Nu6w|(#R)sP0 zICORv2mn1XuzMcwCx@nSM~;^Z4SCFbJH2OJzhf%LaC5rQL(s~o7VtI$anCOMQTUn?;Zb>7)d>Z)91n;? zy4Rz9d#{@tM|t}!I24LpNPc;Ri$!@oO7jaicg*0*j$9udsi~I}qPP*V{*btvj8D-_ zz^(zL5*AVdj}Y4Z*z||byq}}{pm7c45c0oJh5d!Ep#L=^vj2d5oq*&L1?i}MVzM(1 z6GAc6Z~lDpK5O8S&5dD;S_V%q&8vOM>J|>k3`3@t1RoSyx3sx+eOt-X?U0T6XMd^jOY=`T@r^+%cg`;|@;R9EVRq!G6# zrl)wTrj0>PV4DNd)7ECR%V@RNPjfF3>%O?f*X_C^5a`buAwZq+@W(-IbzDJcDGVm9 z&O)6XXF6Bly-H=BZ7eme;JwpDrLwN@VklSsi59@Azp!T-Q{mW1*av0j1XnN#j(xU; zHv^{Bg(?5`e9(UR_|ZOR&MLU3lgrFeW;&O}_=kc!t5UHKa-WqPezdhK&HGUY@Gy@9 z#~JEK$VM1!SPE;bT!1La6ns|{dpWT}SUg!njLF0eGnToy)@vyrazr#TDyn?(p-oYa z21XV}sLW4dziMmgWU(%Gg!-~uBZ z;16Z)S*I%-yf4{D&<`}QjY7-~eKVpborC}q6U_VZ>$pvjIf!;h*;cEZ>%#{$-30bv zoxq%v(8@@t1bSlrT_YO8a`hhpQ=!ej_V@-*9^6Z~(d}w`5rmKbqD*Dv`z!Aizz6~0 zD;lee^li?Z@c%foKF)(Ra=2rfQ!}XBe8tmO58(Y{{Y(cT)IWSF#<VCpGe{R1>a)jTgVQu?I^x&>=s`x2HyyLuD$WI z>&cYg;j_=4^%plZTtW|SnOaMXZM`Dw@zitnx9tb>%OIwttmRF~<6AO@K)1V?7L5iO07K zn5kAr-HqQ7xQ3-Sz!Gw+>6?jsZI5qI)DY%diPr;n0O-|*8+kl!KX`t|H=0F^LH4#h zVn_YH1`oB-idQao8PoAQE*Pl;kPukSVZNK%TMSHgRcv;k6)=Vqa#?9adwG}FOpqTO zv5F=Ye-I8U^eFJUCQgqoht)QY$vIrF2OTC+B*Pg7i0RdEigL^s)~nGl ztvTKs$QjNfAKA#F&M~V#^NYOgwzlGT9`PBxl;PtbUt`)Jxe8FuTxy{ z;vz0e7PKCQaTRP^Q%E`H<{q1)9Bo<;2{Zv*SvHKsJ_x)d*Ri9f;P=*Pzh#NiP)5~z zchbx}+38d8tF8{A zkb@9l!f|-1vol7z4%9FhBXsgO)z!sy8d>a3(l;Bg#{ z?9@)4-Qq`nT%7GDkPdExdXNJ{KO~2?>(0d8ufwoxNwes? z3m?GsN!=Zvxfkbaz~d-j>LP^rr=;?@@zT&}V`GcDbVH9Qw;ECta8`Zz9=|EwO@ z@6s!}a8`i(kBPi0EAtXZ4D~e-+)e@n5=;w3^y$vJ>*%=Bt@&I2(Piz0M4N$Ak8>fr z8`W$O!byaw?WQ@Huo;FjR97uF@rf-S{Ghg2_XLV2b+dS6Sz+NMd3O_(@f)IF1bY;ba9;Kzjbx9;1gbl z5waxVAM-|B|He1P)E@2Hic>Y$ua7t=e*u=`bqJMl=SPIHwgqj^*^kA!*tFVOBh9q0 zt=IGFUjRu)@Ja7VOYBx|a9yM}#q4TJ1120WIfRpv!J;k&kZ;wBJR)FnS?#PK;AnT@ z&cS^qm|=q;rYK7ciE2IGF+%OTS!Gl+vYDp&LeBaUOI{qIyPBRzo$u0kA4IkZ9X7d; z0h;0g8xS;|37T7f-cTl(DPt;95oKe2=X;G)FVwi4C%r?(u?Jc|1_*OoFDBWvX+JK0 zuJdHS_MN?N8fmS#@nyn;scejJ=sEHrE)(?iJ>w@hl@Q|9e=I=NZmpqsrnTk$i<|c) zYDyJWFTJ)!m+3SxE1wSyPyIeIYyp$F#gD`@iK)HxSAOp*JzQ4r;lome!WNUn(4Bf+jNGDqQ2czyRu@J6?f)U z`>=swQrD0n=%3-iA)}g(n3Z?|9k!hI`?&j~Ggc-&a<3>TQBf_e^nu9Gr45;M>lVZX z*ehK7Z~_r~|NlF|_y2VSiuLkX40JmUiRUKym{nwN~a$GpZFDnM_DWWHH0XJY#|u=ZGA z54cPve*rp!dLxW!J9UnEw(!F}MH~EqGdbjt0QxKmM;GgX0kK|^-1R?kw?IjEK)L2u$-jd%ea*DGd zZk$m;ZPq4D5nLzcpWXSGRgmf~pC?&rYhjSfFATh_w?V96Rt>6KFM>ZH+ihx}BAFNjSmpz$P~I<;vD4==cgSpAe@1Mj-pDqh%y4>4F?}Y zNmy$3S*NtRr)B2k_MZO3SJo)Xa*6qRftaki;gp&iQ!I!-QLNpe=F@F$=ohjpk1(ER z;Kn(+(oIO+lg{KK93J5o8hX=Xu~HaU^W5k0d@k#s*K4R(8dF zpVKD@0J)7Van;~ScSr246?svJa`rvSc%IPpW(xvbQ&e#7vlrVLN~x9Q7d;JaEkT^Z>F$jm zy(|6DSAdms_3~i*n+NxzzwuP(Z>QQYeI%uo@}is#E}#Hr`ToickGZjKU8VX-<;ff8 z$WZ}gkVK*ZFfYFz!I=O&cnM#V-Y7)5XtqQU4&{C-)_bYmTRGHCde-zx%Xdd}6t2QvkU;(R-;5lq+U2u_3uojN$Q$J-n`E-be{{kMT zz}cZ0c^Y}7hK6VVVz|&nidd0m5w?7X>?{OGdUe<}f#j3Bp_B2-V3nFKpC2*bqK$aD zS2#Q{2o+^)HG`?tdHA9%xmBjF$20wQrKq!7eT9BA$QlNB#~QU|U(SQ!bxj-=vtQc5 zY^k5R7kC&Bb^3@9X~QrT<(Z?MMYSQ&2%pssdE^#IL>mm(Mt8gsXFk8PZ9GP_UaKYF z?8|p*jjVG%=mvkDP}OC8Mohb4Q6eL-@08@hwf;YR{n5b6=xSwmT3S`~@m_}##~q)k zxAgNeqQ0s)87O(5^^3Y;tbC`T^`zu<*oQ4b;*~pFNcYF!GRE}B=zF4FxI!A@Umw12o>=1?Gat*wldd9{XG@6xY1J4Ic*vyhUu&tHaPVkz5Obzw_J>0ylY zGGx0E)VNAXL~Ov{G{FmgY7uB(uLnWNu;!KhMtT-WKZw!6qiV&eJn{oQ| zjs}9CgU&PLpd)81P|*ARMr-8C9`)ef%Po7WihX?5>eI#eGYP_=MOz|dMqg{U89!P7 zIiH>IC`g)V&qNGpaJuIxRlFWHCSV;ZHx+o4xXvO{RqX$|V<3QO5_%q(hcTlnrs6|R z);&?F|If&I1%CPwdLTk6g8Y#f#m+pga-S~!mhaBCe-0UcyS}&+bxiw|G-=AWqV(WGj z#a%&wyJrj!4&%=P(!(Wun{2Oyn%T%FOP#(GeZNX+bIXyP--c!&Ge;}-^aA3*BE zd=yENAKXdS7BUD657g0FkIq-;*n}oOkvH+Q^V|J{aUp7T&=aAV6=@&hq|`<3t9{=w z7$AShg{oif48Dn5Yb%(|NV=1($P-MKeYaZN^bFem*8@ncG8bZH`h^#lsJd>99Efcv zBgYutM<+d!)00NPp;lq3-rui@oU#?LS~+@AcI#FoXHzA5wLD1bI$IkXD5~U3eFKOW zgKU4C2{Sga7uCbHmAp6)@cMwsDIrv8LK%uS-ItvuNHE4wu{o#0E*mdpRg0O3p=|uN z7dcSFbpS0gnK(v*P)!m0igEAxeW@nFY}|KZ$I@M^#B z8lv~MNoxKFjMgRlVB6Wq_vPMSl)IA%wya8*gHSt>W{(AxY zAHN4gi9xWib&SdHta)Rue^pK4y!!s>0q-$fDDd---|*0G(aa~;P>%>Rcpv&!^Sv2f zc1u-Kv`JEY=5SXpY~eSDi|n2;(5^b59kiZhbalY8(ATkDL*LbS-21nFKTgC=s8MH| zdoH!;H3RJO{O0+|m)E>l zDw(~j!$6SQd%)l=S^4WdwfE;&U_VtT!p2_W;xgr&*3ZNa%Li$*tU4eWOze(qf46>2&xupwb*JvD6>06Dhqy z(Y|@~0eTHo&eLaXwC{#87C5X_aVf8lM>Y8SwCGR&@QEDPuI+NBKv|q^;9U+*8ZkZVCY%4s6*Rhy$t704N?K;ak(p8{F&<14ptargh#wHTRP>^Lx?bHIg^1wsn^* z>CZG~2THTFjZ-N(XgDguiB94A)5Shf=}VH_H(O?%0l43@XQ9$6864%Yamhj2v;Rq8 z&Hs~s^M4tdLI3N%W&fcZ`1``>BjjaROv|HX<8JfWubV?d;o+ki@bVHZ8Ol-QH^u{- zud?54M|&&o5(q!DK(&=Dr9k&mZYXJe6CAty!y+vjJgEcut;2fV`hfwA;R%8d>xmv4 zQ$^fs0N6)N0qwH1DJbspR@lzFRg2Un%?sq8YZCal5&}Ej-_wu&d!fVbtFne2Sl-Z9 zL)Pnn=}Den%NgjA?u&o;eCT1~Pvhe+YG0RmECYH@o6tpv)XX;YNeq8mQ&9>$?)B=; zoEPi`_SgkW1z+$a7Yukgvc=dT_JO%c@>$e&%hM-(xc8~i;0~Y-U!ECR#9*9@k3@z} z%8qZUUz%$I<}2Gs%ouNVT5bG|YeZPm`_iFcA!hb0;4}uLYFem`eW`xrmTV@0oa6u$ z!73q9X;joH-5I_5Pz{b_;>Lhm4CtDkxpuj-HtLr)E~wA1A?GI0$RW2FcPp9MyHsLqMsIS> z+Z08ikuzaYZ8*qE1Y=FwIOhrtcPz~A-Q4)8mp9hbp?8#n;Qam$TyQmOmMns*(v#2> zDbH`BP2bXM7>0cvDgH*pZ^7t1#%X?;`<2+MU#?K%yU17dD)p-E<(^V`1LLG!MxCYU z)7-2e4L#RziMoFZwf%TgJMbW6f9oW~7mxSs)1RmH0I9_%Pml#-So@hAhlhJa7-i=h zpW9`UpBYI;`v%%46c~;~I^|TC9X^!Jmg)XyoOYl~s6mfDTV_K= z-x)~oNg9XHkAHY|uH;$%NYQ+GX|lSwix5*7(!ESfi128!!V&QIN#9rN!;sV&oyZ`P z*?w{1$iv-E20*y#u|ug(lNbB7v|?xJb=DIabZm)GxdhSz$zOPMgR&%%`;*HZ* zzh-^i&zAVtygTH<&mBJ&CRN7If(%eOZ0gfz0E!_}&8XDIzPy^{s~iq*$$W;py{W~S z&j|z06BlZY&Cr0Od6#IGVd2mc)sBf;e|oU_vlKw#YB?c%B%}Kc0q~-TI@&?zopcCb38jGv>>0y{QxInpnMC(vx?xh6B~+!L^zslM(HN%{Yj`@9SN*B%&3leP zwUP-uWxSESt^wbEe)XU+t8KQv7%~q6a^bh^FRSM^m;o^uL}$PVjX2x#*&@mUta`h? z;FB@hVGK1Uh+fUr0F;gwW~uR0FO0Nz@`i&(GL!b02sby$x*{4_l2?F??_V~zFuIPG zwQ+H7Y8R^bq4uO^M(YvMC~4fUs2Q9o;<*3a~i9sAjItIDEo%K*AS>c@8BQ8>*mJMINa!lDJpfoBC3h@ zn$Nvy88u8qF)^5#HegHs8#3mX~>0a_3HL)XN_WzW18)~2ulv^e) zXeRIie|Q5XH~eg~AkEj2XR+OTIM5-seEP1CUcTyMU3>!_m$uP(F^=7arYc)AG5@`v zd(HASWOv$0gR+tE$)6s{@xWyA4QRYk3^lzoli0LXeXG3yuDN z7ef7S8BqO4Hp|BZUR#g~Cb_cW;fnFg))y81aBhj;(T5<#n`f7G$ z8C{7O3+)8@6D_@qt+Hi2Sqg-cBVL!Tonsb!N4d(169m-Lk#z6+u(J1IgRfH|!PNH^ zh6+OyT%=}eHLq(KNM-#rw`-5#(^eb~e`qivVFtrvIM?aFDE;jv#fGvkV)%JAL%c62 z#JS_$Wl0`Y7U%eHmzPJWl=5iZts?xw6!-U0-QmZA$gE)S0u+L2r6HO{Q&jR7VC})< zKp6>Vk3Z_e)L%er)A|!bB+gC7^RoZ&wQ=A?+tKod9L@fd{3S`+$k{6_KpQ*fCRfI| zmtA7jS#A&7^il*aK9yarQr%emoiFS~!5tOkr@KJ+a+bvoDgGkiG1%es9oUQ*PWie< z3Si44RBc-byBk2x7;Z$=()g!M+H8)9CCLsn1(e3!vm@*S@>fXx%fNIHXhtYI<)1wmmT|H}z_LUmm#zmCK zKHp8m79T$tQL?BHD5c?T9~`e;3mp+GZIG!66czcyXUU4vP@v6vYenPI)8JhLI$>d! znOl9J1o>0MR-V9YVF~}ZT`{-S@bTi=1)mvAc5JH!k2aiEwNKStSNTJ6YT6&Ztzn;{ z=Q|z)t&fCf4@FXPMw1FQP9GwVw%yg1iPKOeG&{qrn)QuhU+! zV}wCmmw$OSPLjx$oXx&@{6Ld9B9jK9(3<>%k+ZtZx5>LX1D2TwcD@P`dVBj| z&9@Kd3N0SLhYXMjyDPs-v)7go1uFhxW05AN{SY@3&zp#jp4op#@HP2}Dee3D)OmM7 zz&J*Wg#?5OdBU-|x(>rx*k4Ga)GsU~iq^C|TTg$?YIx7Ve&3_L4>%5r9dH}s~r zSIKA+Yqc_)f&|3ZjB)H@S$h(A+f2xDfg86xBMP9F-np*#_x5}K+JRx11dd+rsyx$o z)H&{vtIwP6LVnE@s$Ol$;Vu>RsUNnTmBqjzM`ppB^E}Q_rVegYJ0hJ3n?mHje0h%n zz*(S?VUB&wYCFzzy_fVhwGdEq+3^hgw`j|hU4}!ujbx)@v9aT!h}UMvjnC>OG1DnL zfJXe6(mPZ3J*>OE+V7~293@TpDGSQB=O8~H30j}qJ3e0ACxUVP7VCM(q7Jp@GIQ&% zn?I1%LLcZrtMLSLm{5SXAOxwa`3(8K_^^_Beu29%(=v}ln_gO2!q-LFkI1_P4GVCB_xMeL6?2p2~hC*A#O4hn}>k z^_w0qvd>D%MG~p7yu7lkqBJ(`tlyOnK$v!JTUBJ*U+=x}UJ|ddZuQn_(@{T@?IT-S zx3t9A{))~m1On=A_un`5MQXF-gdV~vVu7b!FA;{BfP_mi zR9^!oUcgbHk>XHg&w|E=@e+X@=v|nqt(1&U;#m3}e4Zl@c;~lp{^QsCqjIk-7t)-3 zygA74I1mbc6jLtYdinb;CC_ufBJoFDWd#N5uD!(1jN1CZqdH_qa7J9?BqW3!$tWXR z-)=OO{Pcg&_TFJlu36VO_KMM?f+CQkpooZAC`yYS4k93gj(`vmQ2`->1R;>*SW!WG zQ4pe1LXXly3sFH45h)>bh;)(=LJNVE$KUN--@M;9zjtP?_nkTOr@2VX^W?er-fQi( z*EUgm?0oJ$qe0XvjQ(u65ZTKoZz;Dw*E(?d+A&qQ1tA9?{4+E4><#8)A97+n^3Um> zdkden1Qf{dEz1H~isQwmvmd^m{2}$KMP?MFx@PQS&C@5HENs@E&csz}WZy>tq0-x+|^(g`p-ZjYSDph>bhg_EmMf1Z&AdhY#&tm%4yse5x zjzj~oeiu4TjegBOOgN*O_Yr&_yZl=u&;z?)WRLEhs_GI+VbVGectpgcbQ%- z;FwJVdEA+a!oQ{)V;TBYO*>)_wy#5=7*H>B=oVmGbM57P(o+w8?cn@jPf-FvAT>xh z3u!AZs*cr>wvbzj;?Kl9H^QerxLN^6y`;&5^gl6Rd-(i4gX5FE*VAssBs)kqYEyEc zG4gww4uyK`nzc2fQwv2YVv({)c@MpE$MP_!zNe>u(NDh+*cZ0}oNV}#3Y8rG)Z8tm z-&9$r^F%_2ZgPs*lNS!otCiIq42@^Z!m5-ZMOb7vps>N@Z|J3se;{|FmUuv(pz~?& z{a5Xon^%${y^bogFO3IhZO_w>VzIl;*}}nHX!Yg?p9KM4_Sq*f)FDVS#`lnbiVeI~kcI+igp!NwJ_ zv~HMy9MoVT5Lb=<9%Q9CKx2RnGiA$y49lXF{B#5NLoZ3IggDUj(BU~dwqn>sx8ew< zknr?})TkS`vnt7cgM+ce2eebC&WM=<78}S!2V-v*NAqTGdmSCUC?){Q@i&Us!YvO$ zN*!%-F-pG@-X}zW!U{DD>hcgl_A5DEt3FGLKYk4O^1G4J3<3X>3q zl}XW)ooI621d#>s4xBVG*l5P$c;Cm9Tvu(0A@~5b#u_n^v?Q8on`4i->I=uGU%@|X z5iH<8i4j9_y;qB!P45HU;nDS@>XNfWei0}s5FfDqhI_kgwB84;GJXJ-gsFQ#6j1~9 zB$u4*?CM+=!cR*wIPK&Mbu@uY7$OL2TMiTEkS98NZ~7KKj2GgRgv@jc9)#%XyZoC> z*))r7V`0}|wtn?B)87mnN8$*wqae{&-whv9ux}zp)zT%?DagU(xP8D0x{bj?O3qo=j;bsF!Rv-_`-FP58*OuVRglhf|Hh=+-UL(&z8W zY;U^%)kw{1bVz7wu4Yj4=AF%~cCu|l)8Z@~{R~RBku6vJK8^34_Y6OFK_LjWdgkW# z4@@~Y3$F|%_jP@PRaV8{#;g?%DBx-q`3{UhJtGbKy92?_z>{NFO_a8^w5vv!fc3HH zsq9pTTIOFg^LOqQc%Du6bnuYC`In*(aNg8Z(zq|0OMUwW+inkYbPXDt!04qm z8clX*3>H%+osA&6a$FtIAj6R%(rgQL#BrgD>6c!z)%>D%8Y&YIzqMi!%{hnjFqJIZ zK|{_`fnx@ao#tZAS@mGkZ5N%^)LYOxBDU!Gtxnd!KwVDzudctc+i5)$V#Kfkuh5FW zJMN=~5T6nVs!_URWH4N@96Yw14KN%SX9owzmuG&F&89NJ+&V63?-|*3vkfDI-{dj& zJcV1zH-Xj*WHlUL;Ju|Rmx`V7lVd^ZE#Q#HhIXxRE4r|~^XS?bUx^=a3MpbzRX*ru z_!|VW;dc#?%?X5XVShSqxs>8Q()rP`0`oQho=mZ?5P$}-Qi@tmrZejDju1QA8j222 zHF4ygR8+bJudSQs3mkH7T%uhx;V{>F1MhS8au41Qi-8In#KzDL?5x( zRKGuZc^zk(kGe}cLb0CZ1H{;5aXe1xVbOkH)zO;YfWDpF8k+yY_VZCzvP7qh*zAh6 zwfPX&?6m2r-T1jN?Kho?vAsThkP(Plp}*}u2)q14D*0v0F(=l*bOM-#&;SJE#W1Vd z!3>QR}`(xCwrK{9Y6Pkt}SYvNXTzeDHO*)ca=_5&7)i%Aft1(<|x<+td8pKlU_; zWGO(zPsC50slOhmvL0*3z(eWvRT(rF>> zfNj2z29{F6<9T@Fs+#KsfsO^U8Xb2&Q$~bLW;ogM?4U_*)K?0PHAkpHNq7T~GvE}` zhIZN^%padMt~eORej|55)aWW)+I8X(=j+G7o`MI{ADCpx9WYX{CDkO$ztecF*p>GF z&RZdzgrE<8NSb54tH;rfRD?tZbs||qzJz53s>m%ioswbQ;IzJiA~prO=C?E|X1cOI z688(hKItYS9G+=IT}+^eAg7r1A={zmwBikm=p}+RWGMD#u3)D{%tobUxZa%Ev6axN z{Bv^e5{`3(Xh=>VBwJp&v(4s|4?Y7@8hEi7%h(~xWz)!6AJ`&1q93?B2yEX? zvQEWSs$>vn?hX4bE=SC5A`1~$^XZY?keq>287ph{Xn0sRZWcA%WO!fN~FJP!rTf;x((-~Yk2z_IQe<)^<110bKsAZ$vzULZ0r24bCcL>aR$|86NLT4tA zf-o|G=n*k6FFpkhf@faWrsDqO&m9A#(prUIB85nLnX(gC`BK*6m z+P}dm|NJlh{c-qzoXMQQXp=s1?5zrZDutZrs&hv)$mI0@8vgdE=8kl;!sV{+ob+?^ z9f30k(<#AI8w19*RyR65(SYT$ax)h5dR;Y*X1%9W{vZph3HJq9ej*_#IwbsnUqgK5 zLvV`hd83j8=!d;QKcot_&m=FoR4-MvwWvj7H-?)c%(P2^UPgOXvM)J$X7T#{9m+5G z^y~e)Y=r}Pd#`QQj3CtbFQ~Bb>HWFh>e%3|6|B1#Ou-6`5?2>Ui}22nOLAlhF;wSJ z;hkUKK%dBqiEn`vBy?iHKjRCnr7(!iJ{E&I2X)E$hJq&x1Pi`|XQhNpcFR#S~$S|UHb_9D( z60-+I>LP;H8o#72r+%frA7x_FFgnz~g=VMYBjh6=@JX(^aYqovh(WNa62FKjLAbM@ z*7J88omiFmi)<1wF6v8#zY|#PF3D6Z{pvWyiQlv7k1C|d>Sv9HZ%KBUUgm#-43RlF z;Kw7O@dc<1ckhnl32~#2PT(98Ob9OFp>Qsu50UtoC zc@_fY9wPcSqF1Ab5&i)?J{rr8$;&VaQj;8j&mtSBZw{|#88jX0ZER0Zxqd#O?6rzh zcIo*%w3mAVY*2VHdU23l_NMCqap4IblJ9W5*vMM=;-36BkiSvu8_hSUQ3SVzG6 zXKTQwKVaZYXhSeq3SDK=&x9C>7@3y1tSa&uare<-L3B9Da6ywUuRFuA%*y+; z63YJ}<%NMwg5F9WWujAr$6cX&U>LrJL^^>)^=Kkp=gjcO=!cfi7pwr5`w)#MH7_yX z3{Q8_pJhkGiWFTw*LzoEpAku25?U9thBLufO)XWD$MQb=Hou3GfbFAw#~}66>i7T` zi7#r_9Q>PY^!oG8{UdZf19~S}@tsf;n*RVHYqmG`n{3gS-=BU4->5?#)CPkDLjl++ zGMhjqI<2@*%h~R~B*d%dGgFPRy=>Je1@nkc6K7+jYm=#k%aqYQghHO3vsjq-rDGHQ zzM4oX2cR8E#5T~sk-$j7G$B8iE~0i9)%W!;dOuzp^GuD)BzCp{o^v)s)5JZ zNYepfSOdMLy-t2(^IqRyAC%t5uS3v@UTN=jle1mxub-!)CE{fK3Q`?2`Y3Nea!+I^ zh%l1C>IX7$f=2A!6?1uZ6u)h6I{IWKWnXIr~glqJ@ z3*&IQ4&Z0qI69U3-xsSfZTk7;Nl#!)9zX?(g!&gr;={0EHrwEBr@=oCpZ^>g{LKi& zpEOGQH=p@e*xLk0g^*bqMgR(0(FuFZ4@C$4RwotLUtMtw_z(B z>!7PaV8OLW5=~*;yUD?jO?z?^SIw9T*`Af7KcpUnR~@xl50`b&QW~S*Xcb=QhB>l+ zNP#9;{x-LagU2Y`@D3*9G-AjnwAWi~U=5}^K9@WVV|gCBAx-OgBLt+7w2`w1oqXht z?zr-h>$wT&ps&vs4Rok_ni+P$amcS^CG9k!kj8}jffAYytnDix~E$=xKUDD@w+eOa`qt=O$)wc;S=T6<>#^rU6d|eQE(9peuIRfHKep?JB`S+Tt6>ANoS^_nY{!(E-+25{hMt2GbT0hd-zZ(ONIm+}gN zSM z*%&S9D95d#k*Kkm`P+buA>~={8>B*5mCaejw72tg)hOMs!P!S;Dl&3piISV%8oV#( zezP4`BTY?4_TaLhQ?{&y^M%Xm9c%2$)W0m0QUEq=f-8R6*(DGzdoq zO3SU60>67|dKzFI=YHAX=g_n;%$(B*QnLD$pT*76ZP@UuDkBFlfWV2xZpp+!>>ASg zWv2-nYRQLGgwfbQMpt4fzp>_zx{&bp{$nbf&|joLwICRm7JAfk%pAdn`-04JB6#lM zIkW|u;$kli=C)&=^Xp-UxwUQx9hEx}6|~zA;g1-g)n;ZmDLYGK_D)@- z{n^c0TPjaPT{#OdrZrR#A!GzKR&R#7A|7!4s-7+%I(G#kNdzL`c-_h>!p>qqm1G-p zs#->(p9I>~!CuvPc8?;n61rW$0pH&hQAtW~6Zrwo2Sl^tUcF9QD+c46A z(CQ3qHkK7RNhl(6zHlYbo8UyA#jbQYIvSfg)k}WRULm?Sd?q%{6#{x{it0xV1Hb)Zx-+q>1Qi;1o)&F z-yA6ZV?X2NMwosWL_jTD3n7`^$^2QD?d8vKvJ9^)Hq!~4701)lzEnPY+DE`=C%q$vCP{-ku2;9^|p z2`AIdXEXA@Dxi25&mol3t9CclbT!rVQQlVtEOOD9tIWqPj-sw%2Poop;6`M$@|#!} zNB$}fUpXFX=zI0xV88A!58lz~`rYGBPG(r=-f$6^uOUnl*$W&(c=m|V{zt|O(7MhE zR_M=Nj3la>&gxy9^B`5+NO^jP`XXNFrye@nuoU`AOSzL&c*wQ@CKG$poKSXwP*21( zI`F8d40i&(Wx0j5K>HrrS$LA(S!&yoGqhvtmO}W5BzTlifa7Z7aUuE3n0Gk= zD>geK|FVs|EPv~IcFM}gEg8kE_WYcZn8wUo9?cCRw161MIP*KuMhSDpLf;I!mWk`R zO*&a?mPfG|rsVqyp5+H%eO4A3Kal=*$=TrdnJh%fIE=fQ%4()Zc4hY6vPL#t=)k{&ICdZ-Q!H1S7 z1~$0r>s1Xt-wg!qr%TQnVQIRAZVAGWYi*(EM)eC1w@kR4yyUs!?u!Cuz125`6_IyD zIuC(qChWHJ)+hUh`*mT{vE=E%EAb)~&b@>vl5Pb5V%FNTVj;xa2|VsxIE&Fdi@R)t z4U#8h@cHJbdx z7u7Zmw=~qTcRzNL8O+E>wc_wZPUy|!<+}X!oQ4j0FS&|g<`kePe0i4d6LYXdaj(~^CDez`@6bouulcNS>8fo`%qz`!me5TMh)rQA6FtVLF6F;Fs_)FS+=&=DEm|z& zvr~`&V`}I3fk0g9+zC3|1vo}Rk_h`o33*ZLI=Wx%-?EAWR^5TeQhg9RutDJkcB&>) z7`#!A9e8h42cj9Z&}3D@?X6(8Hb;%Wy=JNe3%M}9&R~fdty%vP*E{?c=3fT2HIbdiX@}+ zSA18-IiRzPG$4S1iC&SFx#0@FxwD!QH^f{yWGRWBS24K9-O~MOv>f&cD_2?wgxVj~ zWyYq;vWSA4I3MMiZQ>(2??-aJ-Lf##NlJanY8TEbRCvs!*gNkh93s)3ODborJKJye$x?FkfSao{6YI=<9Du)>u> zx!Lg{Rrc{G8260p?-g+r)tUk`?*whW|Kw{LhE1{_+`r;-J;vPc}a{4E{tI-lk%R_MBpA zed!j^=3`qnycMk~0}9ZaqU4a##Um=kYKvQJsxFxOTHLX)U1QRVo_e)X$yz?$%t@~8 z)0~QQ!KYJa@8!L~A0ke^U04o0I+}j9W=wjT9#TrHjxhQ7-Lh4WV9Z=1WH2@_w7h@X zB(q&Qe%YitK%{naI{S{c4)VrR>K69&R8waiWFljEH(i%~_#*$T9q>=Q?#-?sD0^{@ z{LsDIWFk1A_@LekyNv}Z zb(KhZPc9rSK=rw{zU-^yc>_Rea7>L*Q=T-LJ+7VYvd(tDqUGH%&6)DYsy>&K;sO&0 z&3P?lIUsmY1UQUl-h<_9uNc&^tWmsrS-UwLcmr80|v%5>%MK2+_KPp=9DU2hQ_P zUp}5ch7A-3W>O|3cwg>2tDCIi3;vwgPnI7&Vl}}b4YCmV15$pThwbVjdl{yg+|bXy z`nYZrK24uP6Z`Aq)On{lS_|yDQvMe5t`3%bQA&nSjc?w>jOhgNmB7KCPA02rwRNq@ zye7;)R1(Z5Dwkip~So0;m{}uX1Ep3pNM3hWILcVpjA)S`xSC zX&VZ^Am!eeO`;f-DtcgIP0z3BB>~dO%+C9b zm2P3&RGz+@C0f)e4DD^t0K6>1hTlof+sVrEirERzO@PRbT`XvxM<79Yd}kffMX0~( zk34lB7JN?6Wq?tpj?Hz}3KPEHuhlt90D!;HE^Ku*3mnD{9MhZ<>En&tKIInBG|O)jia;&f-y1ikRfNu)($YarG7DT2`l8i78+R!&J z`gdC#IeAf>-r7`o_Q68F9@GZ$qh~NM9y1i_z4)0au%-p++vhv(6_i^pe|^9ar;pa_1E>|*pX$Orn9=X#o%bm0*=T;8 zv+8~mQc{XpIMOTiX6!;<;Rf-Uvh9#Gg8Pun00e5izTsJ`O{ zYZDQ<^w=B^+Zld7>;o)HFGJx#8}BK-EMHG!loxU>?;vzyYIB9?Yo^woIH#<9E)aa) z6Gy1U-E+O7wG%Px^D%?bD2m7T+GIE+?qW5o*GEy*m-dROLFoGa)h=KRt3^{_Tc70b&1kf`VY91K+1+q3HDvcvdch+p z!+U*cI$e*}u?;|B(Pr(Z1zS?3h><|<9ivCd7mnb6n?d7gJuY8%uYG=bK+kqXg;D~3 zb=%n6GRL2~$|Mu(OuZFz%7lAa<*Df-lw+ZrSnfZh&P@?#2OnpPAbWTdsd#_7Z`s9Jv}l>^2>ywA5xac zJrH>*ZHH?g0LoL4b7*4rjcaZ}ZVhudTd$z$xw!STF|d?8X8@EPU|+Uu{K0J47=&{@ zCj-Xv@c3%g6{%-&S$EvOp-*a&%b> zaxD@sTjH;a9J71?*upTT|LfBfd0GjL?E8Vxd5f-0n0bzRlJKE}%AZ>kTq1X$;~g!C zEy?Zn2OBRg0MPo7=0{+Ng-$=D))EY_(#wSd6oG!_gF!WSt_e%(vjG4N9aPCFhv z3Z$;sX9rQs=G}XS(~bDzwh84`gDDcPKfV~cGRG7Y-U}FGcU40^Q<|Wp;62b=jdN`B zl6ga8eQ2xr(c}i;xvsIh$1a7|UH7P9-^3tP1N`GanRbvBhQcWt1A1gkx=%7aK${q2 zrRPK2rRS!#(3EM!Q--nx(NFWVCLlRoiH1|?nCPjNIW}|VdccaIradiF;Q9(BCv?OI zP~(ZGu0UKmgji=`08UR=e8uY6a{w&RIh04Te=}fUEp=Er3Qhoq5i&}U?=!A+* z!1bjqzy4eZ#X|a-#ERz8fz)0L$Fjm@Hj%31b_KZtud&9N5HYl5Uscio0rkt* z#+}&+1^*GrdH=;^d(-_DGH(VixeQp0Dn&+!V5d(AG8V1-Acqie9#bZuQp{S^sEN3F zRfz1!{cwp*)E9QN;I0mhio1g1F-Hl_^bDTXRPGO{v^uD{h{iFoC?V{FkB6x33G+%& zmmp^2bt8}WNpK5>wTpf)(F+svBX-O-C1HSs*wF}vrUcCulq!jD z#c;C-W;!Zr2|Y-I>6`-73qE9FTgL))hVZq?h`6xgaR*u`LgYu&!DCGOjsx9wGUEX8 z=|Q{+beH1=Zr54b9Oa@d6jDUsINI!m&Je#gKOqZOe0t@9IUdyIuulU%%@Zv5j*6IF z?>`laV9r0J?uPgLiXpgw3Z)pRN3XFuHI|UPd98G9+cwd0rG`8bMfmlxA@R(XDfvzQ zysL``P+S=r3%1-~0jDC14-v*Z0liXeP82dao*{+|5ntV)0seJq&*>e6A=|!Z&quYt z!{@Nhv{0Qlomrr7T!vm=T8KkY8%iEYQEL19pjW97-Y;Q+IP(HMzUgFXheY~JE@A9M zsdr`@L3pnRbD;BQkAX&}$R8x^Z8s9o79+zD)KutIJVaS21EKT7Rp@5dx%~L4=%**w zyYTgRTk0Cmy_gr-xduDfnD7nzgiBsClqEz{n`a9+^1B))r$qH&jo0PX;M=5!<5I!b z#&EwRpQ(i$FxkvUao1c^JFCf<4g&poNovGZdK6;3tEzTbKf@g)sdwwnxByOxrv5u^ zIzLt;3+UA8@8M#MpYF-(RnYcrvl+j%nf4&|ifGtLT9R~bM7Jcw^cbA`%ZN_djoUw@ zHs0Z8RG7Vs-a>RIEqjTpq6Mg0^2zh6B>`6%HxNUG1`T4#N-!COHNg3bBM?a>*UaOl zZJ2?3_FFBqTvKVcv)NbuTaujje;JvXqYQsa1&mW~5ZF^>utRulxs@`{J~D`3P@G5a zupf{0f{UxqtVYciZf4FF6~GE1b+I3Ny}M<>q}!|RwQKes0xoU7=e2xRp4xsTcUEby zj`)G9VfWRb!{%?vS+Kc6-Nyoa$i$J$UhvTIP|j;6uW^*H^sP_<2253OCM+MqCkgK* z<#+M~tj;xdULz+jD9NJBZ_%(b2bu%u<%-o~)%j2*Y@4RN<~3fVJ}jy?7|VS;Cm7Bifi?_0ledE4$z+J# zbq0c-AW9KbL+xOjj27ADUdJcFKcq}b-6OB8)D4-`GuZ-8He^fux^9*Dz2RZ*fXLR? zT-JB$*{sOC;;27NKGyHtbq$j$_djBXKl02Dx@E%!7wt{0K^N-;*ZHJ>dyq5cdU`*b z`ZsmwUt7xmLSg)uxBU2%Cj$RULjCniwrVlcM!JCK0+xUm5UzP<)Zh44`_AE706ord zy!f0+gu=s5A8_^|F9yO|+ii^bNg-A^1IDvMY=avsEp(TcjH+&5o7Y&z^%B)p`@UnhbO^Ye0EAZ_!27xts0-TVt`=@O*fLn5)rmsv?FVukVgfu%N#S*;3vL zInZ_;zq+yI`2gjCw*tQ>m@wpeqTDA}<^`W((KG~P2dZ)-d(xP1-o<^{w=H<~@n*s_ zYkTjrj7>@G;-iRcs;f$wg4W+J`~St;@BKqcJi@t}I=ba}?BTX{ZgcJ?VPQtIf*q4* z8){-$XyJU5b!ErQRna;-S8-2}!~r=ZsQYTX1@wr-Ol*+Iy3S&C+0Mkoz*Ja~>cOO_ zgW>&+T6R4rjk`qN#a{H1gw{KTl^dfK2-~D`1s3~>$Bpf-3sOwdH8(K7lcnQ3`eqsj> z3@k^10cH|gCxk850bfbCH$ac`=BJRm;Gg`JYd7pA1;CB}IR(qUk4TkmsI21Ma>x5m z>C1I_sIso>ibe+qNu=ZSiE>3trOY+uD!#sk z0T@a^(*)m!{YQf_HfkUxRLBo1-MTa*N?s9@+4TL^QVrf`Q_`#0YcIcC4oG;@Ia0ji z*1^&aOyI4|*mEb3Q6+_}^mNJpp>O|sa{iqMj_@Ctr24<0To`}@-!&69->}?R30)OG z?L(}>>pL_)@799_H$3bw8CEm>i2lZ0i#01T@YE20koY5|&tJ_Dci4P%alAEjuh%r4 zWMY}~auN$zkd1F#TWS{@&J1~_l#DnwY^=evdAP>K59x+OT<13FD|!J1AED5t0bh8( zJsngzYvoc7A-SZg`jn^GK)5t!nNRt;)!1~0X2-1Zj)g|~qh~gI$sheFfBE36CkG|R zj5c4o;P1{wn_`neBlh2!PWx}FPlow&WfzXuD5f4t`%Ml65KKL8!QJ~|Z zQS*au>XPd(Kp(uZ+kEvX(-KOGZ?eezna4dzHr1l_u{b}J_ofzLY~3x%T))<4>BbsR zD#CBK%tj8=+ih!q^Hwa%?G5DfW7_C++d6C8({Gl;{Ef#_?TCGgqki7@kh;D29qAnR zwn_M9X3&ElQvMUcdn8q+P=iZbsC6s)PrXT&(`j$-3|6BJN_8xcBsSo zn42Wjjj=p4K3g&B@o(&H%_a$5f|2x^W1R`8}Zk5>9Imei}pa{WcQxP8ZGd+rNY>j?iFv*T#ZvOQ;M;@5F{w<2=U0#}`~qqUlWeK5oF z;KhvWe_ILs*A5ZwKQ(glGgjDTh=E}8StMaotzpv}?EEnW#Ammem!B^Moz70tsP0L% zbYIkqf4iSgh;1<+7wOwYNr{%_&~4@_<(@dTzJ~mq+!p7Wup^UC`^vNz>HRJQKje#L ze-EWS59Bor-DU@q}xg~uE z!?trCwGBGKMLbU1Q>J^*r)u<&|7=t8pv&vuXS;Z=f@j;1l{%It5#gUZiymbl#=R~- zK}>}nwQpCYAL;F;oJ9{*k^a>>=Ko)J{3Uv}3E_OO0{Evv!4c>h#wTXkzvl9xuWe(q zfxY32hArzJg-b?yPa#Utlq_qpf+J}@CekX*Xla8H{FRRY-FW^*M5g5WTM629op5lH zBfJDkYzDNY6voEm_R@xQ4ZUd3%eP!(K*(0T=ADEAFZph!rlCOgQ<}G%dRMDU?{qx> zU#t-RVHRLqC7fVB*-eWz*dv)|_xd9C>Z%v-;pI+bp%ku;M9KMUPja4*JxWT62(_|V z@eARLSaaeIxi8?zD|&3%E=;zpH*adfm1h|bc@gEI3E#0?9qmnf26r7CN=kRl>V6hN zd)RDWc`Uh9^Hg9lsa}hIdtSwhtg%8 zA{o`W3vc!9ckb~CXj@@gsaxkxF<jgYL-wVbJ`nhU;(T@@R@F1lq^=HzaT-YK(Zk2KdMrMatFT46u1 z3k=G;qR9Tb6QfwZ;y_y152-oPgqHXN-aLr;l@~YH7|l|T)^w`*B%Pgf{-T~=bTbrP zW#Y?x{>?1hWEKuz?p>E+iWp|6x1R96EYUp{RUQdh5#*RpUB1_lzwT3-*AFRK)M>Pj(Bn_dO+Rl()xP1MVY=go)N*W?^*gcG zvQowED@zC2wfn+Y7mIqPA~$O`%D^w(#s%JTuy^=4B8j}A*WvTo#uVa^&F)7^t8$g| zUzK4OvbS4d4-p&V$JUNPDB7{xKSv%~%p|tGr}EBnaLutfv%{~yjhggKsnb`}SFGOQ zQgq+s(dTWV%Xzw{$`VDv_6NCqc2VNAf?ucfM@b$l>far7{24<2tc^f_6OP)nWkKoQ z8BhF1AOFN!E}L_?LC|1EVYtcNI6}2jCNnXZ-H5o4KGGV&+gl*&?M0mHtzP+1?(_JI zU-r(79%?9(LwR||9Bb7LSs6(&Z@Ev~u=qo&5gP0v$iGRLcMLOL%5sVrOygG6Abc$b z6y7`O4BGfUY1vT9{FMI^`=p96Z@25Z&3dpqTahJ??WNvGlhSc{YSV7pW=pqjx2-cb zH{BfAQQFb^5s9=wZpQC&zkAT+;V#vo1(RJeQZBuN&)B#BSGeMTYN$((|0(v7#H|CBdTK$~VYFh!P%~0?nJ2_>w~vjot|-6GwQai!h3$BFZ=`GP{mYo==M4yR zzrE^7ZqSIk*y4s~&8%qQh0@8B#`Is)ZiEQ|k@+E5NmbnBe^-wD%~w^N z0uijjCYDHdbNij{7feUxWPY52zC8iAx&NUbqWqXIb-}AU5#BU|bk3Y^NkCZul>E3<)`|_rNj@{?izBdbb z9aVDOw?wvQ+Oqyx9KLnraw_-O+&QV8bKshr+Z(yLsNeXQoh{C^urrfXPM3?z4I|1; zx*sBmc*Hw?)f@jZbB$SxtYU%kn`Wnq`L#YB?i2knzdzr6KMv1bD;Jf13gNHP`Dm>{ zn(i8JpUxQ?%<#w*?~&`aQtU17gwOV^4F^0z{o)lt6UY>rgH&uTAu*0&U2n9 zuye6K*KLfo^x{cFXSIT3es+1|wY>n;GTlyN-6FH^SYxJR{>e@%npP&z-h}n7*~05xHq#&P8`u?z4_)!R zp=s>(m!bI`fUWSE921uAw6n>)H{Vi5J-{;hH-YqzKhJXf=e=#U7@#)1HAL{wil*JZ zHZ|PuQ3$1QbhcnCK`%;k$K&e<5577~yPf#e(OhA_GTbRI`**R3uCR}KV`F+Pey2fd z1?^c&lV$%hd2anKU1VWE?2Dl8+-FVUdC;EmRCoRnIAlHkapZcSoo8k=w8kgN6!D!< zy2UAq#F`2JL%~-^oBry>i1{cO`?GFMYMK>JEn3?{xhNbFJbQH)s0!vEPDp1wJ!c_OoG&% zG!UWud<(C!>zI#4#filIv`-hm(&2(yTyoi=fkPI$*v*6?)0jr%Vp_7nO6(O>w4~nA zQ5=}!2TC|J6x!EL@PwZSc8-=HD-rAv^9M4L1}h+qshmC`B(NF+!Tj-J|H(MR@_v}h zV5lqI^`9T`e*+^~?2fcNfq4Ao(k)HR9(_X}xZ{&151-dglXEA(rfHUjY}{C}f7lya zrRsLdO5zdv(+mGR{25&On8dMGWb!?GF)0{JD|RQotySaY6??{`?Id66!w2^Qi>$<+ zQzc@M}Bgte?qEv-R@5KIgl1Ao`{9v%YbOsX>j~l%ppU}!|aitcQqOD^h%^~xL;SG`sgLci14pw`ZCda?m z`@+Fo)+EboI6FJ*p{}>Hcd!TPZc6%&ZD&?*`%VAo`_}$+_vEg8z51 z&0ooy|Hd|_p4cuaS5vXYA<$=>j)AcS&Eh7gf%UV}Q_qiZTx^MVD~u>*b~=^q)Me6XfCX&>8#1J5oA0i#3|Pvmw{V02Fi@JcTeR zolR4>OgQeiAQleZ9^y4}mN>`oe6%|Ky^u_xy5)c30 zeeoscQR;556jj40gMzhG<$Y;#@KDab8e~v^Vh_xIlXw{MOkL+a@hM{=RYwg8|GedU z))!wlQl@FEJ-55&H-&~C`g1+L(v~iJ` zgu|Rv5j@2OkU8W{oV~wKrsS7gH#1C(I)o=M8Uu_yNA&dd1vpR^+ZHn3!_+{4bE^-MubVmFsXWurRgfJftE9IpQm#ROo=jn_w zkda{s&j@&9UN|^v*9zah=K!1kDxW`{WB8kpG8qx^GYegSkKdau4j*a2>0pN!#r90N zp_RE~sa~qz;nhPkY2gW(=^MXP4!t4Wz4zvr`vgtQ1v&=3Ul*e=%~<D~TNu8#328F$Q)UtG$p+OBE6RL~jpStxz_gCp? zUoHF`6}>Yuy!p^ah4(o{xqB~Vk)q~0IzGpK(y9L&k~x- z?6!p*t}MRZ#d7eY?p3=W7E)>6*#GUmzQ1`m{%1+-E`FhK*K{Jcs_%iwuVOH6C1IVY zIyMrRre%M}b`R@z+%Cu&E8<@C-ZfR?aA~p&a<+(jvLSo~(hD_O!rCtB0;uyLe^)~< zYU8Ap&N9MIkeWvp_w?i3Wku+o#j%z;_|N>L1oD%}m@uwl*5EiLc4yb4kdmcHcLcwh znE{s1i-kSk2hhG;l*PY-rvG;}U#rU8_Dt>Dp9fzsT~E|{)jw0XR0MMEqO)ip+lQ331JEiMrUV#x=d@Bc}Lfg${sNk z4q)1`6|mdvw11%p{xi(V{tsQ3{zIx|)wtWpvc+Ka?d1S**ykToTl@5ow`?p1o;%Ck zQ`9r)-huc2T%L5cNUhHsL*2aH!822c6Cy;#ceFCoja)a;pB!_0Ub|InP#=~AGz+bI zeknmqA7@9c{46K>W9gELDfLE2m2~;d^S_yh5}3=*D)T_>cyO2VwJ1c}x~fkpRl#YS z<~ja{Hp=OHDjd**TOf_koH1XsbEksxHd`AT>-MvIv$8WEZdDy7W#3gkmmw8AVr5Xs z(y&zgPZoH8J%N+e;$NDe5jvM7R=!y#koox_9R)I zxodOSFCqC#Og%%Q>L#3OM!}ah3lrH9X!ZL|ja&_k@yUg(r9klh4|&&U*f7I8PfHhQ zAQwFH+Uh1y{5Xxx!EvIYe z&vkt>nDQ)`OS{PFKU@a>7lmUTJs-R@l=v#Em#I}%b%!3rKW`W8)}Qq%Tri(@$@_=Y zXTgp(BM)oaHyn=g3DZVsw~atj<<8Y)S)F59RG!_tf2gy@6*IUK)#Nx~axtu``&b7t zlAz2vbTqA`{OwD*!=9FI*L`%#chyPfLZaQ)88S1j zh4Vp!!|$ghw0i@g*Hlej^i?Nsk7~Je>*W7e-FJsIxn+BEj=dnqBZ`2Kqo_0y3yOk} zqo{}ikuD%a0i_d_Uc!59pdds+iXcR#cd0=jM5IKTNG~Bo2|a`!(qF&L%s2DRedf;0 zIWuSO-0v@*C%k#H_g;Iiwf0)S^;_KF;rl8f%^mg68b+MPzVGPlHZqJl52XZJcO1n3 zx5>c2uW){cT#^a8mBRg{U9f}m)ygOKOaizZGgCh@Ws~ZsA}_u?3pxSp{ z#z?jpig}x1XQ>W3`@yM7Xsg zfa9{W-5S5n68-7u{IlMJBL1Y3D6)Rb)HBF5@lNCm3?PPoF|CGR^-}Hx{fJGn^eeDx z7woyuAvH}z8<*ViU1viVD8sk(BI>`UCkj-?6C0U(<`GVlm*yt6gBYMWQZRz7^Iq49 zIL!t~$Sx+cL>oW78lBmTn^3~=$6=OezsJS;AHU-d0gPLAN8%53uQ`qqOCa|Q-|3tBC|L5}b@O~efYN}} z#|tH&O*>oKKjNRR+)+D^j*{v&ZpoY8GQhc1y)Ra~c-qBMoj|63y;7}POFm}W>26i- zx}P`dV~DX;1yh%?L&@_i2PAAZ>t6aU+wVD9*8<))yNJGRcAZeLFf*HwLG~FxZ8l2F zr+;kY_q)fPGc^o!ZErnHM6(V3qeuwW!q*%Kvph-6eB8MDaGUB87sT9feVQPr&)nbBAa z)5w`Gf$eIHYZiH%d^2u)sE!?5pcHDO*)l3-Vi#E@&zGd7?MEFKjOb<6$Fqw(h>T2V zRMushR&co7AzUy6@UJ!o2k$N4^y#8%tU097FUHjmGH+~phe)8li+l>I^;7a*O|}@G zk@=BnTa_CpDE9K(|1PBogWh@3R_?G}C!ByE$c)wy@VY|xdi%q)$^3uy!2J4S`Nn^7 z^q%0tjCI-5zT6*o@aBcn?*ThWia@NpbJ(yn4z>tvNDK_BX}x@2F(}b-B-PJ*!U7cHSqoRY!611NJG7ioS`Wy;>)uoJT!ZOXG_kuM{bWJ{)Jgf&$>hPO9jQG8-NQEY&?8&6r1Dby7YRxhZhyELdv zC$|}W6RFG$+V3XoaS|Hcff*FacJBV}7mw%SJ!)IDFk17vBf$+^*UvV$X+-ShsB6A6 zYm+N7WX2<{i0{e)EOGB(AbQVtRc3vsx{jJ8&L41!5~Fx67aG2{joPZy9>K0I{j-t& z$L=KbucfSd-au_8V-EjzWgc5vu4$Vy zh~Bi{LSp>f!WVBzJl z{<`>NwfY)|A*Z({23rxMlwM`M6aeQ^D3?MambX!Ele4NnwiiQId*|AvSt&8TuMCL8T#LaOn>86`3+|c zv&e@Vx4mmrs<;&&%2K<1f0%kg5&G0zht6Oyvq0%WZ~>x$gt2-H$!m@F2F8sa*WFsm z-mz|9LMGF_v2yWw{8T}CCV&uCMILP)9ZP;2+z~ut41(<-G48JQHq?Y{E2H$>7}+ey zNQXFP($Ndn!%OyjgjA&g2D`0NNhRSw>Z&XZbCL6JYi!a z)=Qwncz*7gh;0F^vM;rHUxc~;lj^7d>!%H@SNAwKQs7D!_;A0o?(6DXpHr8 z-k-_3cQ~{j^Q83vXzaFm^JlV?qJr;@&23Lpkqf2l4Ty>5NQd3cV&Q2|Oj}g5&$@mceZX9Wu=4DT7)P?}}n%H8vX5M~ByzC|yrL_l5E)I%0GBp~!jf zH|c-_6rSDYkeqX5$_~bQ_yMd%)+F*bPzwF?*(O#d;&Qbdd{sp|#CYwGIdFh9yE~+)2(y5rCq@O3KRPHOsip;dfckv2acORQ zegHM_Ye9o(<-BG}8O_pOYF8v3pJCN>ek$ysb&HSR7DonUR~-&X{_$Cjo!#fQ zpV#qY1^X73&%wa3+ATGH}Nus8`Hw&>za_e8s!P zP#4I1OQnpHZ#0iAs37&+oT@@$x25qb^%!33tdsXnNW02Umhf;n=idO+`kSeY6$SWe z-ALORcPLs$g%|*NJBNri;#40ta|F@M*7iuE?cktS5JH?&m8&O@7~j(?GYwBn=6SKa zuxp7=*ETaJ4;zI4dEuHUd9 z#hH3c7Y4USk{1dt2CiRVxQdNREPl8@j<0JisPdFl@~?yne#F_aMZYh+_=2!TMiG{* z4EpYF7%tH63!lU#SjB9GDzLfdvzKBTqFlQ(_$0GmdC~aia%1uY?a}ws#COR<(gi9y zzfd&oMV}8!-&cPYZ(={k(bqcAe<0bg%pS8{Yu{$Ey%{`tU}Q?PnebvGq$ZZ2**Wrw zb+1S@JZYVguzyM=>)Ez*y0QB1`rUp~8=G|ahq5+L_!woQzmj{Ruoa>`e5=d~VM zI23F2BP`dGs-cXqsAR(blOEKc%;KBC#aZ{7%4%8PAxhTcn`uqcZDrXHNjmMDKkavU z3r*G;%;eSPsLEyr(q-oc1H*|GmoOeLgZ0l z{-Qz)_S2S#kubeI!aNLJh@m@&PubWw?VLn}wyy^FyNjQo{`V73r)|`}iEJgg)dCjeeH;bw>?DVjP>4WvOrN-9#TK#4(V;H?bWi_0JyD#hGr$e$txL@ z&Kn|TPgeii9D=`{LU=tp);<5BU{y4Qbff}){5tPFD7zaFl4W+OINx$L-91n_IE9yc{Xl{3y%YaAmgJkH@cW^d$-(td;vh>fi(=Ev<=G!|Uu8Xbt2ZK~^# zkCrG?Vkm#bYll{!!2zKKMZS0p@=gJ~7#_K9kg+_z$AVZtLnULMUCHJYHaqor&fH)+cf$^>*^)ep$k!GzdUU(1%866;fn44li>gMx# znhQz54|bV}m@hAjTWIDmp7Du{zV7%ZxS-KYmwo)8{j|i|_*%CEPe6s{i}cJ_p`0-{ zkWHW1opB#Fw$aLn>8TJiRHzU5PFo^Ki|o6D-v{kHe%9>r(zxa2&Kbi|>Qlvx%qDs| zz|`C^GC?_FoJ+<8oZ50R7TnaRZ%s~b)C1h!rKE}zQeswT*9Rye=Q7_tARW^Pektu&y?aC@ ztvcPKy^XM=5VW7>ceSPsYuTJLtJp#MdeX~Xq7?;N+?b{HJ^!3vz%4EfNI(Say2jUF zM|)S0OSRPhYW)BH5A=wX(p#EzxAA39?0g?0Y_(1bAtyX67ZBzGP@<(4X9kW1|Mm zET%VS!3cmJh}n>d7otlKm%Z-rH_E+&#%7{?71Ix*`ZH`lwy&rksgoxF|XIBtkOB zwFQqn5YJ>nJZ^moRpN|%dbOc(3pYAjq!08^P@_yfvkiQ=V{>#9z8B6d|Ym!;2e+;?@IXrZot z_OV($bb7L)0ap(XAu#f*1r_a!3{N!1>whSU`B!mHvp~UT_@Eiv*HEXQB7tDb5IWWt zczv49oDo2&Sl>`c38!5Gd>?$A$5 zukzCv*ex%a*tnr2i(V?Z_l3d&U%tpEd7Hm`!qRnqUkh{dvA4P^kALXt^shRq%L+4f z5CocMTrSXC|9S%T4}&b|-&W6cwhz5hHGzhX$}GlnTLn$(NGpeIrEKk^f<0*|120;x z`PW8No zx8n!0Nklczo34c=Keib<>ds$Mv-??^BC)YmHfGWw_3^H+sSNbAtepDYbjFkY!(_AT z>>Yz~>LtEAWOM4-@wxS~J1TJd!gGFTGeM1~=ht!o5VV=6)xFBebTa4ODgU;%>~g;;+1*{9|A0H$HJ+;hNbm*J%Bq z%_nfxx-!7Efh?2P10sr=5Pf86!#ZPjLvNhF`xAfM@}W75RmH^7odVyzI$J0-QqEf(#>Z0(o-jQ8Tm@JFcO%|EWtZo1DZbKO}C{g`DlQ1Eg${g5$ap zUw|`E6VddgdRUcP8ijI^bJvkMRGW8CtMVV^kA7RaZG-g1qt@n6t!RuD({eg8baAQ^o`h)fs;rfBu3An?4Kf@$4o}%pu zNc%eT^ycNQW*~L9_CYErS1iffpLGb@=95gZ%i{w$-DF%Khs0Rj$V?f$-rJcX(wReq zPjk}h1#I}5>H5~6>Sn8lUO6WqL6gWnYYS;W_7My$&)IO$R^%?jqu_rmFZN$1|0mbD z=NS98$u2|@Xn>f|2j z4M#Z$NF~Lc#^$Jl&(EPZR0ixs#;|SNiO*;Kd^AzB2snX|C*b&08w72BgX5JYMy~ zY{d2iDlR-N3ZY7)FWl<6=`;Ab2A;W>o?Mg&qi_TAHd{mwcfRlPa{ngs6w%7eT3AKL zqR)&R@e-#db!^8JtlKrDkh7c~aQ3Z?H~$26Ju;zWh8J96xEUz+^vKfwBcXs54WD@Aq{c1- zQQJ%M)_M`I$epI<77of&ds0*0q-H!$PslFHzw^}C#N@-V#=Wr->$>>uKY731z|g?} ztE6(=aZwp|#yZ}coSG!48!kODI4oDBv7yvz8Nh!hUnL7M9(l zlhqo_ZD)OYTH0|#m3Rl{t~M8Mi=hKX-#tG`eYkcMC;Ir~i`WbMp0yky?}-o3(C$*w z_ll6hWgl`0zGV0WA9uE=(VO6Lya>VW)F5j>CDABeRYhqsk;|HEEBT`5quaP8tEqL5 zT-osqFXL;Aw|9te(rO%`kg+}SQ05^T_0bJZPtuRAj-Kn53nwSc6Gt3%ewN9Y*;4+? z9)?dQwcG`}L5NC7gS4l11}rtD5I$%)C5~D&Sh?FmPi;;bO0fJZ<($u9crTvIPQS)~ zjUYMlW!!2!$9Lgpk<(sO)fQyfS;*}RDRd9465_idqES-hV|rMTzAT@@ElG`Xw^f(|d#~3_Sd~YoH`>oc zo{1c;U6?A;IfVulet_!=v|!1wU(kIWRa5C|rz()XWh};y8WI{Yx)rb*4Irw|6J0|i z9G3$9Tx%`?J|Q+!r?=oT&nxj`&<9RINFoyySnSd86f=FxjX3D|wrof#qXu9ff-I$` zoU7y(mIJ-?@jH&j zNu)}!rkEgyqW(=JznU>zFfTR$wf2%cJxEJ#mES~OqIy>eK4@=N?HwH_gA{WN<|f1f z&7;n-(Cif0gTPM#!%VqB77Rm+-T>Hl2y-8ek3-6?;|U9kb@@Xk)G9L;teZ}88`PDl z#;`+Iei^m+14oI329J?*0Og%Z4ora$BIgT&=ZC+E1dH|ekbG%SlQ?a5oq+0z8Izp5 zzBZlfK0j~4Be=Mq2L2_?rq>H}g(FL}&qGktUed~g*DzzsbEhGT<^tS30o3w&fF`^} zAFA>rJz{}&VSqYQk1u8mjUAiQ0Cc#O9L_5&M3-j*&xJfBq@NRD11B)h=q}cMco*&q zQaH*c&k7|2R~#Fy**YAD*V}FjRf}CkbEAS*<5+_C93F|W>;XKKDO&Kn9IQ=TvcS*Y z?}9jYKw6X!PzS{k^W!L9!4kd}(xsc#5Rw4RfM%4Fqk-xT5W1iwOE$FIIip?FSyzIX`Q=7pl`BwA(<{(z&97 zc2eA(aQq9rENRK%3zC;XJ>|uc0TV&e*5%4`)4z!vyj9WGDu$E7@JJno>sFdjyvGI4 z)8T`JCH0lz?uT7T&9_Byt!NxF!$Rh9NH8+5jvOA?+jS09_Oh|Ff|TS!^+gBRiovUP z6$Bs{%loBaQXs8M2do(QKmQBsF6c{*S!gpjSM3qx13HTV{`_sClc0SN8_S>C4OWI< z%@)oDMABO6Tn9PJ>f1q{;57#&R$haXnD;JtT?M2g8%we0J{PPTD%tLDleW;Cs=ih` z#4k%(Y2KQGu#`EbU$@gPu@3d<6ND0Yv9Bx1igjXKPx(h}>qdiJ=fRweoEW4ydV0aU z8lM9vgfGx{KbgDVKX@iG?9G9;`BQG5=6=`i*?-AP(4jB*(J%4c-ug(1>Ff1rR&=|L zC%-KCWLQ$op9TD=Ui$o^D4`co;c5Zp)hjUF{jq}UXm?oVTgNfzH>OV6)|?H zy87Jm%*V;3g34fH0gj@HIZC{9`^$X4euMfu?S&vS@y>a*rKKOZ0()UM^K*@1mV~b1 zUSs{CU5BT%Y=BAvAdNc!CPSOpW4h?hJOd4j5zZDSi*~oh^wGa#Y{q}`x1)`HzP?@!kMM*1^|t z#?j?(co6zE`}Q97wT$x}BhYK_yQCz-LXoXlt1K928(<%ErIi-66<|TKy+*)e3$#cJ zZ#(mXoxGO9K|E^_wR;760JDbW=UD~mc;Ou6c%^Nz0ya;9$ECBiR9;OsqF69~4ly|! z&^z8+9SePdu@0DVXF-AL^~F^=6d@|IsLTePe9Cm3nzO)wE+P5Ttf$b*JnnM1-r!ow z(gw57#P+TASRXJ~np7>$$U-LhE_{rn3lpdh1OxL=Qscn&MMSG7qcy<$IR71LlH4Q4 z2}F%Pk~9$}Fdt`C|8g!CoO@;d+r4v$FOy%3X5_z?BIlD+8U?e+m|K@pg8zQmiQ7LLj_>9(NVIr3q+FRGhqE#{nRw%YmLBFkc`} zuc@$>2(<&lOcXZKb=(EJi#*8I?YvnKCg!jP-))@H=i(lo6_neHSZNp0K>KXV7f zAkdhQNTBO7Is?SOCKBWHt@-5Ysqj57m2&Jb)H85*HdqNPo}={~r8CV&qSY|v<6H47 z9)p<&j@8*uiSp?Qn)3&aeiK>GcfJO)4=47{gF=?dsC9T-rxEnQm=b7znfq-cy%J43 z1G_0i-eO4tsfXXLzmD{ygpBJY#K9OZD*4it(5 z*>S^B%A7g5Fj!WQKJC)?qmiDOPGP3cSV#8O4>z~#1kLD|AzgKzkOZmCCgQfLwxr;W z>0^qQk)60X5voGjy_18A6%j~9Bt0{tCj;G*!o4eK;}$1nb6U$h6Xh`OgGuNCk53Oc z)IPPOESpPD7UK7XllTlLEX|ae{k{8W?Xc%bsVuGAje8L(12-=(na9{5Uq29nUc>px z4@_hdZ~T($e5#VLR4EPL4${N1XA+i>fG7(&`Z~VWV&qVKXhtK(y{|7Ua)hZ7 zKL@SZihGLxUIRnS$RAW|@Ae)NW*=!hI61Ji6oOMeMH{~{nCNk>TtFIxDjlA5ngRVP zgKbYSAJ%wlr;#FC3+rPSyC|PXMb+Aki8UVS7Yo?DpsO=LF_MMjCa7bz=U!04V?VeH zYBGV_Hl+KB0@}`aGYv2ohn3KyNvlwLzac z2droIg6oyRM-AK_<(~-r;$~)%*t2-3OzTwdf&N2QATX&wYW;lDx}Suc5YW6A3&z?K z%|k*eb1FXQ?FIk+l*$f304q-PCP@;(eSciSK)$Hj({y)K##nD-<1uSff5WherW#nP zN~me_o?ZGZRMHARS&{S6&0vW3HpVNK?}?4A15VaDT#ipKkfbFfFGtO6@6$8DML=tab5_ zk!CP{n!v%kWvNX)u1#;O+>_S}uRi=u=ekcJBJ|ltF>>qz z<4eQnVZ?J@oRBwae?9&f84!%^6>T=2!+=%hxNEpq)Q1~RE z6~g$%C=`#c_Ro)(m z2vnza09l|pvO46vWD@Rh1Xcw!Cn}s5=OQzD(?}U4tUFavrmN(eh&~ed^Zr9yj>ro} z;($)x;#B=}N3+z%h`SoauHA@*c22ZW3TzEE$jVOis=GD}quH;&iTupE{_ZMX4Va2( z@STsR7gm`*Q(#EG&?}7QItmO4h+z#M8a`NEJ%Kcs1r3FAE1U_EA9})JwyMy5>J(|Z z?p!7|&iv_R1m6c!uZv@}KG4#frCIp+(e%(IP-0$U|3KOZ*oUop5CdZbHrO6}oW)#l zQZz~`8ySnL&pWRP$gYv|;g5M@!I4wL+TG>RT9oJ^Fd{wCQMgeJJOTyf%uU~b6b%7=hzBzuhD%z^LZPJ*A=kJhc zuoOe0Gi(VYtm%l@kLECXX`Mx?{DWIiH=4I8-6{+;ppue#*5TF>Ac0z_=5$X02r+Fw zQj1@oC_pOyW+H@)z3vxEn46mjgAKzK(b<-R)wBaXQFxQ z@?1h;BM|Y6ZbOpuNOa_qm_fnai_%WWsRAJGW5LSr zTyLh_ZcjR=qoQ&gw_lxmEeMLd_yQT&df;;p>(j+#%PDB|Ir=qHmq@Hj(VzfH%H@b< zfU)`^rwBqfMpu0P?3JGFliK;F=U181nt+Md1oz1v%k;R6ym9vR+lLU+ASMh=$d&}- z|GXaQgnn%2Xu^dG%=O|6L+8;PfX|3Tj-O0ihUlWfZM{R)+2~=2Ll&;;_M$*dr@$qX zN9|QCMC_(V?!=vCarpkJehwM1C4R>P+!!1;sR+UW6!+UIp5T^Vg#(NKC>OYnvSRGV zK*R=%m)R`0sAIb4-E9o^2BV5$OPXXRi({97;LeeX;XpW<-y4CP2O&YS^;|B1^dq

    fp{Mg7(a%SaVrLsL2weTwd7a=8Fyd8$5%fZ*V4UPv4B$mV{Ioav z`&!rtsEwE4whcelLi}8w$V?5-b=MzXiz|R>?|*s$ zdLJY*gL`a_m^7|_Ji<2Fn>!GY&2ibdB~t9YXvCn+jS6)~Tg=egCYE_~;*A^XTY3h# zHlZ*2qO^7Q#fM2wWoEJui1%-95&uj+h8%)o{7UxT(c>K(I&`6jdid7YhZ+YFhjWx1 z;cLQGYxeDm>F)GEhhOn?>V6Y>k=I0I#~rF4OBCSSOpK1`j%c4^tNHXRjV#8-TC!gNGH~#OCPY z*lK}uQD!oh=0DQ1I@9F}wVgljT_xGQrPHKke?%q}+g7g>5E{+k4`H6XM9ns<)L3y^ zQ3Uwmq-9hSX=V*c0Ky6R!~0IYmYecrYPtThbtu?Czz)X_p!ff(dbDe3}4HQ!i3F%9#{;| zI;KhC#-Ua})qTWOkvmhEqN_WaA_MLO5l9L1lunHRmxj9XD_MxW+TwZ z`zDKLNiVt@cR3;!78ES)H+}{L>84L;_*|q^DDl8z0Z)y#_;l%OAh6q8RY>EjZIp~N zxCz@Mx5BLz*<{CPVVrGI2#R5kiP$qJ#4=MWFpu%e_(j&`o|K0rh{Z7NA`bK-$=+6p zmau7084)>MHH{#A6Um}Ymj|;e{J_wpgFE41VsuFQ7!l zrT9EN1w_<35g<(!I0M=j(C-Onkwy}vQ2yZBwDp{;gVdBlqt1U6ESsS@U%TTE7r^fI zo3*4cGkJTN7k7YaTCJ;k>lg3Cw{<#`w6}3zzqt^e1Yf^J{wA_3h0&yh0dcmLrMyFl zwD4wdVV~8_Bi7kIg@E7G&rmtIjhoUky{F}y$l>&Z-X*TZ+C#_;Sq!JHt4Efd4-G>g ziq>iMW(mydB`|KEWlkl%6LefrbgvPRN3zX7w|9PFOfCf@+jP2tqQNp662V_rC^5bC zG>F;&(S;#-y}c)VEEdn?CS3`Jd|+Z@<1=jfqelSwG$UHfkKGm$Zub{1ZIRGQ^0)ez$w*>sF{}^ z_i^4eI)QvK^yON6MXhxovDIXZ#C@uYBM?Pqlv7|esb%1RIvANOimh+ELj7^nKu{5U zam>Xf2c4zuLuPl!cqgBzR4&e(pB#^MDO~otHLjR7F`<{ZY>!)h6MiDg z1sQ|hkD*vx;|5etTJWt#iHVzurJDOs$^s%!iaJ|%@+C!sw17vNC<50*^<##1 z^%L$(xf|_#YB5QWj1;b~uHv(QAlS89>`kkRCy|D`9%qFGoXS6;vp#IilLq@!FeKX_yJsoGP)>nUQP6}Nc};19 z9f>?v1b{+Pbi8z7f`FKfVUpHV_|~KG`kv6#f<;~Mn?WsXmAcP5zZ;&3i;7iif~jN+`%Fbe#-Z|Er%YFIo;0NU*VLAT zT+)R-Df6$-wVA%?I4`^N)x=VuXZn9%Z(H$pr49Euth~awb_K%mJwbGEWgT*nWFd(B zh4BF%qUSHxgdqkzT@Pru8el+Jp&UT>g`7u&6%42qKomTuU`24(VI;FnV6j3S^;=)x zgI@;GYz!DpelCd#F+phRk3&E&la?2tKZu2)%1874k$)IMuP?WovmoUlMxh5zH4Hp9K}5bBSMdIOjZurl(0T-TyMB(w<8 ze-xZ01e^v681o-R_vd%7$nGx|Zs`9l?(}~~yu+$Mve}oWp^?_o%1uRl>9-amva=s* zN$O=IL+JOf`cLc%oePL)j=`&%{d~ks@@!^qNOAyqD>6)u-hr%3JI+$2cGUR)OnOBs z7AC)N{w5N&&gPYo<-(@IDQHUC)oscU>WOh7$qJX4QvqyXYMaZ2Ne7l^7p_j~%bG|> zWie+4nqGRGzei$@;2b(mn=G5%>e-q0gL@^%<*>5gtH*(fgc*yZ>TbbBGwOm3~V1|SJs}R-YqczMpW|W*^m8Z0K0j7EO zp(bJU%$K7{m?TQMXm^RP2TD3dI@v8vYfbPL(fSCgDdcP!aWDN%WJRL#X4*^vH4KAz zw)ZSsS7EO^HsHwciJzwgq-XNv1WZKv!7q%D#qzhzE*ra74cYJ8b*CN|s$Au}pWWR0 zxK8IJANTcyi_!(>;V3lqd5WGq<8y4d-Z8_MF3&PqZ%G8+@7sdlHzMhN-PTxnDd~42 zKl%@C7+0iVfSsp3$wlatEN=JcgX1Wb+dP>c$6}3eA7+ALY<%dA4g%ThDE14f^$L?| z(f60Dan3eaPZnS~>87-*p~{55$L3_emw2^gcI| z=*)?M%~D79a7FQNou%C9PIvj9@!8bKn1W@k)mrw+5yvZQHI=$`M70du+(%iB>az$j z1aTc6O(c2?cuwBHpIC_gfGucXHor@j{Lx^Pl1SLM>0`yIt}6kXWd}o0^J|0LhPvt$ zh~{Wq&ZXtqe*~rb-?DnY4X^sYWz>HfhXtZVb+odJrpoqFg*-%QRb>a~8os1ZIvkD{ z)}nNur=;X06mLCvNha=9);3f7n>o)`kq?}|l6YFU;pW~)C%X&Mwi>oyQ#DOXgw2tf zx3H;|a<1+~TpR;r9WhIp>iI{dA4TujUt-3J-w3=?qPX`5#A4U&j&7*+9YQc(QF694 zAk!fOZ+&=4%*d_+k+CdqYNur2C9Shz`*vHS;VTH$xXh@lA)bf#{uB&Q0>rBwkGS*a z88SlIE(OpX6HF`tMkA1XaBjR?f<8f{of*mZ~gxVr~6Lc literal 0 HcmV?d00001 diff --git a/setup/import/images/PROD005-6.jpg b/setup/import/images/PROD005-6.jpg new file mode 100644 index 0000000000000000000000000000000000000000..f48cac2428e4b456edd146856a471d9841f39ec9 GIT binary patch literal 142119 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 z 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 B)xrP( literal 0 HcmV?d00001 diff --git a/setup/import/images/PROD006-1.jpg b/setup/import/images/PROD006-1.jpg new file mode 100644 index 0000000000000000000000000000000000000000..ac75a7ba247e478d8a7a1dd46aa8660627852d60 GIT binary patch literal 212734 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

    f+Nc(+-B)lB{$TO7|A2f1XQ76(*$)aW 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�bCC)JoWcT2 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 M`#%+sxcmM;0o6+PzW@LL literal 0 HcmV?d00001 diff --git a/setup/import/images/PROD006-2.jpg b/setup/import/images/PROD006-2.jpg new file mode 100644 index 0000000000000000000000000000000000000000..fb72ae255b13ac4dca9466010b863ee03d2d66fd GIT binary patch literal 130205 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%0DT;ablYKOpw94xU4dwM3BTI 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�fX?>5;Wc}Qe{jIDcL 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
    -?cu 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 qUkkydICx7u+|3{|(*fa>GO|>}>%;%NOMU00stt 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
      W3}L=e#a@gP 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 Z|7EuQ-)f})e}4Xr%KqOHi23c~{{bN4Aoc(N literal 0 HcmV?d00001 diff --git a/setup/import/images/PROD007-1.jpg b/setup/import/images/PROD007-1.jpg new file mode 100644 index 0000000000000000000000000000000000000000..fda1d28801b5e21b1c79de74bcc24826b67f204a GIT binary patch literal 259549 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

      (ZUs-#v$H32jV}h`8D%?g-K;es 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

      lB>Q+WtM^{r4Zi|72Z7P19xb6x@29tRlWEmz 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

      3j=1R&!zO%AqR;m(i!`y4LK+ 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 z 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⋘3co@pF%W2iNl+?-VZ;ptYQCVhJIrv8_f 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 literal 0 HcmV?d00001 diff --git a/setup/import/images/PROD007-3.jpg b/setup/import/images/PROD007-3.jpg new file mode 100644 index 0000000000000000000000000000000000000000..30b5637ae5b0970642b852fc056805ba1ab8343c GIT binary patch literal 253321 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
    1. vhIO9b2NZ@oBrxE+0eN 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

      y^?6+Y^6|eG>amy=)yIl!&dk0b^E|ydp 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 WW%`4z`TvGa{yWPbnH>K4?f(H&t_r*W literal 0 HcmV?d00001 diff --git a/setup/import/images/PROD007-4.jpg b/setup/import/images/PROD007-4.jpg new file mode 100644 index 0000000000000000000000000000000000000000..00556c6658895c6586fee2fed0187fc94802fe74 GIT binary patch literal 252812 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ɩ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�kHdW4mrUF}8YP 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

    2. xDy!tQ>1z(4)c6b|g2z)wxIm&6Sj(MH&^p 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

    IZJdf8gKvP}Zct9%1Y0%_CLWSihss*&D07 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

    %rnmOeiAS92nxOc-Z@1&1 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�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"{UzmYuvQ^AF0(wVijROFGsKR0Ye;N(8fHTy)e^U zhP|)uPMb4gwD|);N&JOYFp@3&tMsZg>`}1_rXQNiNDZm2sN}CIn)ENSI%-5O;qZ�Z_P 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 ZfBdiA!qT1pBX(LE=bm1r9Wni!`d@ts{XqZ# literal 0 HcmV?d00001 diff --git a/setup/import/images/PROD005-1.jpg b/setup/import/images/PROD005-1.jpg new file mode 100644 index 0000000000000000000000000000000000000000..5e2e29dec2960ae16f5a602fc1e6d977eef17b1b GIT binary patch literal 159109 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%0D^O+a4eWyxDcSpWR#6HLh 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 jxiZ05HXCCr2NhL#%T8QBC#BIH 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 C20Tvy literal 0 HcmV?d00001 diff --git a/setup/import/images/PROD005-3.jpg b/setup/import/images/PROD005-3.jpg new file mode 100644 index 0000000000000000000000000000000000000000..51697517fcfa020ea882a3ea44dc43279f3f1c48 GIT binary patch literal 144428 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 literal 0 HcmV?d00001 diff --git a/setup/import/images/PROD005-5.jpg b/setup/import/images/PROD005-5.jpg new file mode 100644 index 0000000000000000000000000000000000000000..81c791943ffdefe6c773c4314e0eb1920a2951de GIT binary patch literal 147598 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 z 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