From af1552b3908d8dcb5bb291b83f05c4c743d4b581 Mon Sep 17 00:00:00 2001 From: TheCoreDev Date: Mon, 25 Jan 2021 18:42:52 +0100 Subject: [PATCH] Quelques nouveaux fichiers et modules en conf --- .docker/mysql-data/.gitkeep | 0 .docker/nginx/nginx.conf | 55 + .docker/php-fpm/Dockerfile | 19 + .docker/php-fpm/php-ini-overrides.ini | 17 + .github/workflows/test.yml | 65 + .gitignore | 33 - .htaccess | 6 +- composer.json | 4 +- composer.lock | 1326 +++---- local/modules/Atos/Atos.php | 363 ++ local/modules/Atos/Config/certif.fr.dist | 0 local/modules/Atos/Config/config.xml | 22 + local/modules/Atos/Config/module.xml | 18 + local/modules/Atos/Config/parmcom.atos | 39 + local/modules/Atos/Config/parmcom.dist | 15 + local/modules/Atos/Config/pathfile | 31 + local/modules/Atos/Config/pathfile.dist | 31 + local/modules/Atos/Config/routing.xml | 27 + local/modules/Atos/Config/schema.xml | 12 + local/modules/Atos/Config/thelia.sql | 44 + .../Atos/Controller/ConfigureController.php | 166 + .../Atos/Controller/PaymentController.php | 252 ++ .../EventListeners/SendConfirmationEmail.php | 94 + local/modules/Atos/Form/ConfigForm.php | 249 ++ local/modules/Atos/Hook/HookManager.php | 93 + .../Atos/I18n/backOffice/default/en_US.php | 13 + .../Atos/I18n/backOffice/default/fr_FR.php | 13 + .../modules/Atos/I18n/email/default/en_US.php | 12 + .../modules/Atos/I18n/email/default/fr_FR.php | 12 + local/modules/Atos/I18n/en_US.php | 44 + local/modules/Atos/I18n/fr_FR.php | 44 + local/modules/Atos/LICENSE.txt | 165 + local/modules/Atos/Model/AtosCurrency.php | 10 + .../modules/Atos/Model/AtosCurrencyQuery.php | 20 + .../modules/Atos/Model/Base/AtosCurrency.php | 1144 ++++++ .../Atos/Model/Base/AtosCurrencyQuery.php | 419 ++ .../Atos/Model/Map/AtosCurrencyTableMap.php | 411 ++ local/modules/Atos/Readme.md | 71 + local/modules/Atos/bin/request | Bin 0 -> 790680 bytes local/modules/Atos/bin/response | Bin 0 -> 774424 bytes local/modules/Atos/composer.json | 11 + local/modules/Atos/logo/1EUROCOM.gif | Bin 0 -> 1484 bytes local/modules/Atos/logo/AMEX.gif | Bin 0 -> 1954 bytes local/modules/Atos/logo/AURORE.gif | Bin 0 -> 1513 bytes .../Atos/logo/BANCONTACTMISTERCASH.gif | Bin 0 -> 1273 bytes local/modules/Atos/logo/CB.gif | Bin 0 -> 1867 bytes local/modules/Atos/logo/CLEF.gif | Bin 0 -> 1254 bytes local/modules/Atos/logo/CREDIT_CTLM.gif | Bin 0 -> 1877 bytes local/modules/Atos/logo/ELV.gif | Bin 0 -> 682 bytes local/modules/Atos/logo/INTERVAL.gif | Bin 0 -> 89 bytes local/modules/Atos/logo/JCB.gif | Bin 0 -> 1343 bytes local/modules/Atos/logo/MASTERCARD.gif | Bin 0 -> 1174 bytes local/modules/Atos/logo/NXCB.gif | Bin 0 -> 3403 bytes local/modules/Atos/logo/NXCB_rouge.gif | Bin 0 -> 3038 bytes local/modules/Atos/logo/PAYPAL.gif | Bin 0 -> 956 bytes local/modules/Atos/logo/VISA.gif | Bin 0 -> 1389 bytes .../default/atos/module-configuration.html | 120 + .../default/atos-payment-confirmation.html | 23 + .../default/atos-payment-confirmation.txt | 9 + .../frontOffice/default/atos/payment.html | 7 + .../frontOffice/default/payment.html | 7 + .../modules/CustomerFamily/Config/config.xml | 167 + .../modules/CustomerFamily/Config/module.xml | 18 + .../modules/CustomerFamily/Config/routing.xml | 56 + .../modules/CustomerFamily/Config/schema.xml | 116 + local/modules/CustomerFamily/Config/sqldb.map | 2 + .../modules/CustomerFamily/Config/thelia.sql | 207 + .../CustomerFamily/Config/update/1.3.12.sql | 16 + .../CustomerFamily/Config/update/1.3.sql | 93 + .../CustomerFamily/Config/update/1.5.1.sql | 59 + .../Admin/CustomerFamilyAdminController.php | 450 +++ .../Admin/CustomerFamilyPriceController.php | 95 + .../modules/CustomerFamily/CustomerFamily.php | 131 + .../Event/CustomerCustomerFamilyEvent.php | 123 + .../Event/CustomerFamilyEvent.php | 130 + .../Event/CustomerFamilyEvents.php | 25 + .../CustomerFamilyCartListener.php | 58 + ...stomerFamilyCustomerConnectionListener.php | 118 + .../CustomerFamilyFormListener.php | 254 ++ .../EventListeners/CustomerFamilyListener.php | 246 ++ .../CustomerFamilyOrderListener.php | 102 + .../CustomerFamilyPriceListener.php | 302 ++ .../ProductCreationFormListener.php | 97 + .../ProductExtendPriceFormListener.php | 87 + .../PseExtendPriceFormListener.php | 95 + .../Form/CustomerCustomerFamilyForm.php | 122 + .../Form/CustomerFamilyCreateForm.php | 110 + .../Form/CustomerFamilyDeleteForm.php | 35 + .../Form/CustomerFamilyPriceForm.php | 66 + .../Form/CustomerFamilyPriceModeForm.php | 45 + .../Form/CustomerFamilyUpdateDefaultForm.php | 26 + .../Form/CustomerFamilyUpdateForm.php | 33 + .../Hook/CustomerFamilyAccountDisplayHook.php | 53 + .../Hook/CustomerFamilyHook.php | 19 + .../Hook/CustomerFamilyProductPriceHook.php | 25 + .../Hook/CustomerFamilyRegisterFormHook.php | 44 + .../Hook/CustomerFamilyToolsHook.php | 29 + .../Hook/CustomerFamilyUpdateFormHook.php | 36 + .../I18n/backOffice/default/fr_FR.php | 54 + local/modules/CustomerFamily/I18n/en_US.php | 21 + local/modules/CustomerFamily/I18n/fr_FR.php | 20 + .../I18n/frontOffice/default/fr_FR.php | 10 + local/modules/CustomerFamily/LICENSE.txt | 165 + .../Loop/CustomerCustomerFamilyLoop.php | 100 + .../Loop/CustomerFamilyLoop.php | 107 + .../Loop/CustomerFamilyPriceLoop.php | 82 + .../Loop/CustomerFamilyProductPriceLoop.php | 94 + .../Loop/ProductPurchasePriceLoop.php | 84 + .../BaseCustomerFamilyLoopExtend.php | 34 + .../LoopExtend/BrandLoopExtend.php | 54 + .../LoopExtend/CategoryLoopExtend.php | 54 + .../LoopExtend/ProductLoopExtend.php | 103 + .../Model/Base/CustomerCustomerFamily.php | 1371 +++++++ .../Base/CustomerCustomerFamilyQuery.php | 621 +++ .../Model/Base/CustomerFamily.php | 3373 +++++++++++++++++ .../Base/CustomerFamilyAvailableBrand.php | 1268 +++++++ .../CustomerFamilyAvailableBrandQuery.php | 569 +++ .../Base/CustomerFamilyAvailableCategory.php | 1268 +++++++ .../CustomerFamilyAvailableCategoryQuery.php | 569 +++ .../Model/Base/CustomerFamilyI18n.php | 1268 +++++++ .../Model/Base/CustomerFamilyI18nQuery.php | 508 +++ .../Model/Base/CustomerFamilyOrder.php | 1255 ++++++ .../Model/Base/CustomerFamilyOrderQuery.php | 555 +++ .../Model/Base/CustomerFamilyPrice.php | 1530 ++++++++ .../Model/Base/CustomerFamilyPriceQuery.php | 712 ++++ .../Model/Base/CustomerFamilyQuery.php | 1195 ++++++ .../Model/Base/OrderProductPurchasePrice.php | 1255 ++++++ .../Base/OrderProductPurchasePriceQuery.php | 507 +++ .../Model/Base/ProductPurchasePrice.php | 1345 +++++++ .../Model/Base/ProductPurchasePriceQuery.php | 615 +++ .../Model/CustomerCustomerFamily.php | 10 + .../Model/CustomerCustomerFamilyQuery.php | 21 + .../CustomerFamily/Model/CustomerFamily.php | 10 + .../Model/CustomerFamilyAvailableBrand.php | 20 + .../CustomerFamilyAvailableBrandQuery.php | 20 + .../Model/CustomerFamilyAvailableCategory.php | 20 + .../CustomerFamilyAvailableCategoryQuery.php | 20 + .../Model/CustomerFamilyI18n.php | 10 + .../Model/CustomerFamilyI18nQuery.php | 21 + .../Model/CustomerFamilyOrder.php | 10 + .../Model/CustomerFamilyOrderQuery.php | 21 + .../Model/CustomerFamilyPrice.php | 10 + .../Model/CustomerFamilyPriceQuery.php | 21 + .../Model/CustomerFamilyQuery.php | 21 + .../Map/CustomerCustomerFamilyTableMap.php | 424 +++ .../CustomerFamilyAvailableBrandTableMap.php | 467 +++ ...ustomerFamilyAvailableCategoryTableMap.php | 467 +++ .../Model/Map/CustomerFamilyI18nTableMap.php | 474 +++ .../Model/Map/CustomerFamilyOrderTableMap.php | 408 ++ .../Model/Map/CustomerFamilyPriceTableMap.php | 506 +++ .../Model/Map/CustomerFamilyTableMap.php | 492 +++ .../Map/OrderProductPurchasePriceTableMap.php | 415 ++ .../Map/ProductPurchasePriceTableMap.php | 475 +++ .../Model/OrderProductPurchasePrice.php | 10 + .../Model/OrderProductPurchasePriceQuery.php | 21 + .../Model/ProductPurchasePrice.php | 10 + .../Model/ProductPurchasePriceQuery.php | 21 + local/modules/CustomerFamily/Readme.md | 174 + .../Service/CustomerFamilyService.php | 210 + local/modules/CustomerFamily/composer.json | 12 + .../backOffice/default/assets/css/style.css | 3 + .../default/assets/js/customer-create.js | 8 + .../default/assets/js/module-config-js.html | 62 + .../assets/js/product-creation-price.js | 4 + .../backOffice/default/customer-create.html | 45 + .../backOffice/default/customer-edit.html | 81 + .../customer_family_module_configuration.html | 490 +++ .../default/product-create-form.html | 16 + .../default/product-details-pricing.html | 52 + .../default/product-details-promo.html | 42 + .../default/product-edit-price.html | 53 + .../default/account-additional.html | 26 + .../frontOffice/default/account-update.html | 50 + .../frontOffice/default/assets/js/register.js | 16 + .../frontOffice/default/assets/js/update.js | 11 + .../frontOffice/default/register.html | 50 + local/modules/OrderComment/Config/config.xml | 42 + local/modules/OrderComment/Config/module.xml | 18 + local/modules/OrderComment/Config/routing.xml | 11 + local/modules/OrderComment/Config/schema.xml | 13 + local/modules/OrderComment/Config/thelia.sql | 27 + .../Controller/OrderCommentController.php | 53 + .../EventListeners/OrderEventListener.php | 63 + .../EventListeners/OrderFormListener.php | 33 + .../modules/OrderComment/Form/CommentForm.php | 31 + local/modules/OrderComment/Hook/BackHook.php | 43 + local/modules/OrderComment/Hook/FrontHook.php | 39 + local/modules/OrderComment/Hook/PdfHook.php | 35 + .../I18n/backOffice/default/en_US.php | 6 + .../I18n/backOffice/default/fr_FR.php | 6 + local/modules/OrderComment/I18n/en_US.php | 5 + local/modules/OrderComment/I18n/fr_FR.php | 5 + .../I18n/frontOffice/default/en_US.php | 8 + .../I18n/frontOffice/default/fr_FR.php | 8 + local/modules/OrderComment/LICENSE.txt | 165 + .../OrderComment/Loop/OrderCommentLoop.php | 54 + .../Loop/SessionOrderCommentLoop.php | 36 + .../OrderComment/Model/Base/OrderComment.php | 1253 ++++++ .../Model/Base/OrderCommentQuery.php | 507 +++ .../Model/Map/OrderCommentTableMap.php | 419 ++ .../OrderComment/Model/OrderComment.php | 10 + .../OrderComment/Model/OrderCommentQuery.php | 21 + local/modules/OrderComment/OrderComment.php | 31 + local/modules/OrderComment/Readme.md | 58 + local/modules/OrderComment/composer.json | 11 + local/modules/OrderComment/preview.png | Bin 0 -> 97382 bytes .../backOffice/default/order-edit.html | 19 + .../OrderComment/assets/js/cart-comment-js.js | 1 + .../default/OrderComment/cart-comment.html | 10 + .../default/OrderComment/comment-input.html | 13 + .../pdf/default/delivery.after-summary.html | 11 + .../VirtualProductDelivery.php | 3 +- 212 files changed, 38073 insertions(+), 817 deletions(-) create mode 100644 .docker/mysql-data/.gitkeep create mode 100644 .docker/nginx/nginx.conf create mode 100644 .docker/php-fpm/Dockerfile create mode 100644 .docker/php-fpm/php-ini-overrides.ini create mode 100644 .github/workflows/test.yml create mode 100644 local/modules/Atos/Atos.php create mode 100644 local/modules/Atos/Config/certif.fr.dist create mode 100644 local/modules/Atos/Config/config.xml create mode 100644 local/modules/Atos/Config/module.xml create mode 100644 local/modules/Atos/Config/parmcom.atos create mode 100644 local/modules/Atos/Config/parmcom.dist create mode 100644 local/modules/Atos/Config/pathfile create mode 100644 local/modules/Atos/Config/pathfile.dist create mode 100644 local/modules/Atos/Config/routing.xml create mode 100644 local/modules/Atos/Config/schema.xml create mode 100644 local/modules/Atos/Config/thelia.sql create mode 100644 local/modules/Atos/Controller/ConfigureController.php create mode 100644 local/modules/Atos/Controller/PaymentController.php create mode 100644 local/modules/Atos/EventListeners/SendConfirmationEmail.php create mode 100644 local/modules/Atos/Form/ConfigForm.php create mode 100644 local/modules/Atos/Hook/HookManager.php create mode 100644 local/modules/Atos/I18n/backOffice/default/en_US.php create mode 100644 local/modules/Atos/I18n/backOffice/default/fr_FR.php create mode 100644 local/modules/Atos/I18n/email/default/en_US.php create mode 100644 local/modules/Atos/I18n/email/default/fr_FR.php create mode 100644 local/modules/Atos/I18n/en_US.php create mode 100644 local/modules/Atos/I18n/fr_FR.php create mode 100644 local/modules/Atos/LICENSE.txt create mode 100644 local/modules/Atos/Model/AtosCurrency.php create mode 100644 local/modules/Atos/Model/AtosCurrencyQuery.php create mode 100644 local/modules/Atos/Model/Base/AtosCurrency.php create mode 100644 local/modules/Atos/Model/Base/AtosCurrencyQuery.php create mode 100644 local/modules/Atos/Model/Map/AtosCurrencyTableMap.php create mode 100644 local/modules/Atos/Readme.md create mode 100644 local/modules/Atos/bin/request create mode 100644 local/modules/Atos/bin/response create mode 100644 local/modules/Atos/composer.json create mode 100644 local/modules/Atos/logo/1EUROCOM.gif create mode 100644 local/modules/Atos/logo/AMEX.gif create mode 100644 local/modules/Atos/logo/AURORE.gif create mode 100644 local/modules/Atos/logo/BANCONTACTMISTERCASH.gif create mode 100644 local/modules/Atos/logo/CB.gif create mode 100644 local/modules/Atos/logo/CLEF.gif create mode 100644 local/modules/Atos/logo/CREDIT_CTLM.gif create mode 100644 local/modules/Atos/logo/ELV.gif create mode 100644 local/modules/Atos/logo/INTERVAL.gif create mode 100644 local/modules/Atos/logo/JCB.gif create mode 100644 local/modules/Atos/logo/MASTERCARD.gif create mode 100644 local/modules/Atos/logo/NXCB.gif create mode 100644 local/modules/Atos/logo/NXCB_rouge.gif create mode 100644 local/modules/Atos/logo/PAYPAL.gif create mode 100644 local/modules/Atos/logo/VISA.gif create mode 100644 local/modules/Atos/templates/backOffice/default/atos/module-configuration.html create mode 100644 local/modules/Atos/templates/email/default/atos-payment-confirmation.html create mode 100644 local/modules/Atos/templates/email/default/atos-payment-confirmation.txt create mode 100644 local/modules/Atos/templates/frontOffice/default/atos/payment.html create mode 100644 local/modules/Atos/templates/frontOffice/default/payment.html create mode 100644 local/modules/CustomerFamily/Config/config.xml create mode 100644 local/modules/CustomerFamily/Config/module.xml create mode 100644 local/modules/CustomerFamily/Config/routing.xml create mode 100644 local/modules/CustomerFamily/Config/schema.xml create mode 100644 local/modules/CustomerFamily/Config/sqldb.map create mode 100644 local/modules/CustomerFamily/Config/thelia.sql create mode 100644 local/modules/CustomerFamily/Config/update/1.3.12.sql create mode 100644 local/modules/CustomerFamily/Config/update/1.3.sql create mode 100644 local/modules/CustomerFamily/Config/update/1.5.1.sql create mode 100644 local/modules/CustomerFamily/Controller/Admin/CustomerFamilyAdminController.php create mode 100644 local/modules/CustomerFamily/Controller/Admin/CustomerFamilyPriceController.php create mode 100644 local/modules/CustomerFamily/CustomerFamily.php create mode 100644 local/modules/CustomerFamily/Event/CustomerCustomerFamilyEvent.php create mode 100644 local/modules/CustomerFamily/Event/CustomerFamilyEvent.php create mode 100644 local/modules/CustomerFamily/Event/CustomerFamilyEvents.php create mode 100644 local/modules/CustomerFamily/EventListeners/CustomerFamilyCartListener.php create mode 100644 local/modules/CustomerFamily/EventListeners/CustomerFamilyCustomerConnectionListener.php create mode 100644 local/modules/CustomerFamily/EventListeners/CustomerFamilyFormListener.php create mode 100644 local/modules/CustomerFamily/EventListeners/CustomerFamilyListener.php create mode 100644 local/modules/CustomerFamily/EventListeners/CustomerFamilyOrderListener.php create mode 100644 local/modules/CustomerFamily/EventListeners/CustomerFamilyPriceListener.php create mode 100644 local/modules/CustomerFamily/EventListeners/ProductCreationFormListener.php create mode 100644 local/modules/CustomerFamily/EventListeners/ProductExtendPriceFormListener.php create mode 100644 local/modules/CustomerFamily/EventListeners/PseExtendPriceFormListener.php create mode 100644 local/modules/CustomerFamily/Form/CustomerCustomerFamilyForm.php create mode 100644 local/modules/CustomerFamily/Form/CustomerFamilyCreateForm.php create mode 100644 local/modules/CustomerFamily/Form/CustomerFamilyDeleteForm.php create mode 100644 local/modules/CustomerFamily/Form/CustomerFamilyPriceForm.php create mode 100644 local/modules/CustomerFamily/Form/CustomerFamilyPriceModeForm.php create mode 100644 local/modules/CustomerFamily/Form/CustomerFamilyUpdateDefaultForm.php create mode 100644 local/modules/CustomerFamily/Form/CustomerFamilyUpdateForm.php create mode 100644 local/modules/CustomerFamily/Hook/CustomerFamilyAccountDisplayHook.php create mode 100644 local/modules/CustomerFamily/Hook/CustomerFamilyHook.php create mode 100644 local/modules/CustomerFamily/Hook/CustomerFamilyProductPriceHook.php create mode 100644 local/modules/CustomerFamily/Hook/CustomerFamilyRegisterFormHook.php create mode 100644 local/modules/CustomerFamily/Hook/CustomerFamilyToolsHook.php create mode 100644 local/modules/CustomerFamily/Hook/CustomerFamilyUpdateFormHook.php create mode 100644 local/modules/CustomerFamily/I18n/backOffice/default/fr_FR.php create mode 100644 local/modules/CustomerFamily/I18n/en_US.php create mode 100644 local/modules/CustomerFamily/I18n/fr_FR.php create mode 100644 local/modules/CustomerFamily/I18n/frontOffice/default/fr_FR.php create mode 100644 local/modules/CustomerFamily/LICENSE.txt create mode 100644 local/modules/CustomerFamily/Loop/CustomerCustomerFamilyLoop.php create mode 100644 local/modules/CustomerFamily/Loop/CustomerFamilyLoop.php create mode 100644 local/modules/CustomerFamily/Loop/CustomerFamilyPriceLoop.php create mode 100644 local/modules/CustomerFamily/Loop/CustomerFamilyProductPriceLoop.php create mode 100644 local/modules/CustomerFamily/Loop/ProductPurchasePriceLoop.php create mode 100644 local/modules/CustomerFamily/LoopExtend/BaseCustomerFamilyLoopExtend.php create mode 100644 local/modules/CustomerFamily/LoopExtend/BrandLoopExtend.php create mode 100644 local/modules/CustomerFamily/LoopExtend/CategoryLoopExtend.php create mode 100644 local/modules/CustomerFamily/LoopExtend/ProductLoopExtend.php create mode 100644 local/modules/CustomerFamily/Model/Base/CustomerCustomerFamily.php create mode 100644 local/modules/CustomerFamily/Model/Base/CustomerCustomerFamilyQuery.php create mode 100644 local/modules/CustomerFamily/Model/Base/CustomerFamily.php create mode 100644 local/modules/CustomerFamily/Model/Base/CustomerFamilyAvailableBrand.php create mode 100644 local/modules/CustomerFamily/Model/Base/CustomerFamilyAvailableBrandQuery.php create mode 100644 local/modules/CustomerFamily/Model/Base/CustomerFamilyAvailableCategory.php create mode 100644 local/modules/CustomerFamily/Model/Base/CustomerFamilyAvailableCategoryQuery.php create mode 100644 local/modules/CustomerFamily/Model/Base/CustomerFamilyI18n.php create mode 100644 local/modules/CustomerFamily/Model/Base/CustomerFamilyI18nQuery.php create mode 100644 local/modules/CustomerFamily/Model/Base/CustomerFamilyOrder.php create mode 100644 local/modules/CustomerFamily/Model/Base/CustomerFamilyOrderQuery.php create mode 100644 local/modules/CustomerFamily/Model/Base/CustomerFamilyPrice.php create mode 100644 local/modules/CustomerFamily/Model/Base/CustomerFamilyPriceQuery.php create mode 100644 local/modules/CustomerFamily/Model/Base/CustomerFamilyQuery.php create mode 100644 local/modules/CustomerFamily/Model/Base/OrderProductPurchasePrice.php create mode 100644 local/modules/CustomerFamily/Model/Base/OrderProductPurchasePriceQuery.php create mode 100644 local/modules/CustomerFamily/Model/Base/ProductPurchasePrice.php create mode 100644 local/modules/CustomerFamily/Model/Base/ProductPurchasePriceQuery.php create mode 100644 local/modules/CustomerFamily/Model/CustomerCustomerFamily.php create mode 100644 local/modules/CustomerFamily/Model/CustomerCustomerFamilyQuery.php create mode 100644 local/modules/CustomerFamily/Model/CustomerFamily.php create mode 100644 local/modules/CustomerFamily/Model/CustomerFamilyAvailableBrand.php create mode 100644 local/modules/CustomerFamily/Model/CustomerFamilyAvailableBrandQuery.php create mode 100644 local/modules/CustomerFamily/Model/CustomerFamilyAvailableCategory.php create mode 100644 local/modules/CustomerFamily/Model/CustomerFamilyAvailableCategoryQuery.php create mode 100644 local/modules/CustomerFamily/Model/CustomerFamilyI18n.php create mode 100644 local/modules/CustomerFamily/Model/CustomerFamilyI18nQuery.php create mode 100644 local/modules/CustomerFamily/Model/CustomerFamilyOrder.php create mode 100644 local/modules/CustomerFamily/Model/CustomerFamilyOrderQuery.php create mode 100644 local/modules/CustomerFamily/Model/CustomerFamilyPrice.php create mode 100644 local/modules/CustomerFamily/Model/CustomerFamilyPriceQuery.php create mode 100644 local/modules/CustomerFamily/Model/CustomerFamilyQuery.php create mode 100644 local/modules/CustomerFamily/Model/Map/CustomerCustomerFamilyTableMap.php create mode 100644 local/modules/CustomerFamily/Model/Map/CustomerFamilyAvailableBrandTableMap.php create mode 100644 local/modules/CustomerFamily/Model/Map/CustomerFamilyAvailableCategoryTableMap.php create mode 100644 local/modules/CustomerFamily/Model/Map/CustomerFamilyI18nTableMap.php create mode 100644 local/modules/CustomerFamily/Model/Map/CustomerFamilyOrderTableMap.php create mode 100644 local/modules/CustomerFamily/Model/Map/CustomerFamilyPriceTableMap.php create mode 100644 local/modules/CustomerFamily/Model/Map/CustomerFamilyTableMap.php create mode 100644 local/modules/CustomerFamily/Model/Map/OrderProductPurchasePriceTableMap.php create mode 100644 local/modules/CustomerFamily/Model/Map/ProductPurchasePriceTableMap.php create mode 100644 local/modules/CustomerFamily/Model/OrderProductPurchasePrice.php create mode 100644 local/modules/CustomerFamily/Model/OrderProductPurchasePriceQuery.php create mode 100644 local/modules/CustomerFamily/Model/ProductPurchasePrice.php create mode 100644 local/modules/CustomerFamily/Model/ProductPurchasePriceQuery.php create mode 100644 local/modules/CustomerFamily/Readme.md create mode 100644 local/modules/CustomerFamily/Service/CustomerFamilyService.php create mode 100644 local/modules/CustomerFamily/composer.json create mode 100644 local/modules/CustomerFamily/templates/backOffice/default/assets/css/style.css create mode 100644 local/modules/CustomerFamily/templates/backOffice/default/assets/js/customer-create.js create mode 100644 local/modules/CustomerFamily/templates/backOffice/default/assets/js/module-config-js.html create mode 100644 local/modules/CustomerFamily/templates/backOffice/default/assets/js/product-creation-price.js create mode 100644 local/modules/CustomerFamily/templates/backOffice/default/customer-create.html create mode 100644 local/modules/CustomerFamily/templates/backOffice/default/customer-edit.html create mode 100644 local/modules/CustomerFamily/templates/backOffice/default/customer_family_module_configuration.html create mode 100644 local/modules/CustomerFamily/templates/backOffice/default/product-create-form.html create mode 100644 local/modules/CustomerFamily/templates/backOffice/default/product-details-pricing.html create mode 100644 local/modules/CustomerFamily/templates/backOffice/default/product-details-promo.html create mode 100644 local/modules/CustomerFamily/templates/backOffice/default/product-edit-price.html create mode 100644 local/modules/CustomerFamily/templates/frontOffice/default/account-additional.html create mode 100644 local/modules/CustomerFamily/templates/frontOffice/default/account-update.html create mode 100644 local/modules/CustomerFamily/templates/frontOffice/default/assets/js/register.js create mode 100644 local/modules/CustomerFamily/templates/frontOffice/default/assets/js/update.js create mode 100644 local/modules/CustomerFamily/templates/frontOffice/default/register.html create mode 100644 local/modules/OrderComment/Config/config.xml create mode 100644 local/modules/OrderComment/Config/module.xml create mode 100644 local/modules/OrderComment/Config/routing.xml create mode 100644 local/modules/OrderComment/Config/schema.xml create mode 100644 local/modules/OrderComment/Config/thelia.sql create mode 100644 local/modules/OrderComment/Controller/OrderCommentController.php create mode 100644 local/modules/OrderComment/EventListeners/OrderEventListener.php create mode 100644 local/modules/OrderComment/EventListeners/OrderFormListener.php create mode 100644 local/modules/OrderComment/Form/CommentForm.php create mode 100644 local/modules/OrderComment/Hook/BackHook.php create mode 100644 local/modules/OrderComment/Hook/FrontHook.php create mode 100644 local/modules/OrderComment/Hook/PdfHook.php create mode 100644 local/modules/OrderComment/I18n/backOffice/default/en_US.php create mode 100644 local/modules/OrderComment/I18n/backOffice/default/fr_FR.php create mode 100644 local/modules/OrderComment/I18n/en_US.php create mode 100644 local/modules/OrderComment/I18n/fr_FR.php create mode 100644 local/modules/OrderComment/I18n/frontOffice/default/en_US.php create mode 100644 local/modules/OrderComment/I18n/frontOffice/default/fr_FR.php create mode 100644 local/modules/OrderComment/LICENSE.txt create mode 100644 local/modules/OrderComment/Loop/OrderCommentLoop.php create mode 100644 local/modules/OrderComment/Loop/SessionOrderCommentLoop.php create mode 100644 local/modules/OrderComment/Model/Base/OrderComment.php create mode 100644 local/modules/OrderComment/Model/Base/OrderCommentQuery.php create mode 100644 local/modules/OrderComment/Model/Map/OrderCommentTableMap.php create mode 100644 local/modules/OrderComment/Model/OrderComment.php create mode 100644 local/modules/OrderComment/Model/OrderCommentQuery.php create mode 100644 local/modules/OrderComment/OrderComment.php create mode 100644 local/modules/OrderComment/Readme.md create mode 100644 local/modules/OrderComment/composer.json create mode 100644 local/modules/OrderComment/preview.png create mode 100644 local/modules/OrderComment/templates/backOffice/default/order-edit.html create mode 100644 local/modules/OrderComment/templates/frontOffice/default/OrderComment/assets/js/cart-comment-js.js create mode 100644 local/modules/OrderComment/templates/frontOffice/default/OrderComment/cart-comment.html create mode 100644 local/modules/OrderComment/templates/frontOffice/default/OrderComment/comment-input.html create mode 100644 local/modules/OrderComment/templates/pdf/default/delivery.after-summary.html diff --git a/.docker/mysql-data/.gitkeep b/.docker/mysql-data/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/.docker/nginx/nginx.conf b/.docker/nginx/nginx.conf new file mode 100644 index 00000000..decbb570 --- /dev/null +++ b/.docker/nginx/nginx.conf @@ -0,0 +1,55 @@ +server { + listen 80; + + root /application/web/; + index index.php; + + access_log /var/log/nginx/starter.tld_access.log; + error_log /var/log/nginx/starter.tld_error.log; + + + location / { + try_files $uri $uri/ @rewriteapp; + } + + location @rewriteapp { + # rewrite all to index.php + rewrite ^(.*)$ /index.php/$1 last; + } + + # Php configuration + location ~ ^/(index|index_dev)\.php(/|$) { + # Php-FPM Config (Socks or Network) + #fastcgi_pass unix:/var/run/php/php7.1-fpm.sock; + fastcgi_pass php-fpm:9000; + fastcgi_split_path_info ^(.+\.php)(/.*)$; + include fastcgi_params; + fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; + fastcgi_read_timeout 3000; + } + + # Security. discard all files and folders starting with a "." + location ~ /\. { + deny all; + access_log off; + log_not_found off; + } + # Stuffs + location = /favicon.ico { + allow all; + access_log off; + log_not_found off; + } + location ~ /robots.txt { + allow all; + access_log off; + log_not_found off; + } + + # Static files + location ~* ^.+\.(jpg|jpeg|gif|css|png|js|pdf|zip)$ { + expires 30d; + access_log off; + log_not_found off; + } +} \ No newline at end of file diff --git a/.docker/php-fpm/Dockerfile b/.docker/php-fpm/Dockerfile new file mode 100644 index 00000000..f970b162 --- /dev/null +++ b/.docker/php-fpm/Dockerfile @@ -0,0 +1,19 @@ +FROM phpdockerio/php73-fpm:latest +WORKDIR "/application" + +# Fix debconf warnings upon build +ARG DEBIAN_FRONTEND=noninteractive + +# Install selected extensions and other stuff +RUN apt-get update \ + && apt-get -y --no-install-recommends install php-mysql php7.3-mysql php7.3-gd php-imagick php7.3-intl php-yaml php-xdebug \ + && apt-get clean; rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* /usr/share/doc/* + +# Install git +RUN apt-get update \ + && apt-get -y install git \ + && apt-get clean; rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* /usr/share/doc/* + +RUN apt-get update \ + && apt-get -y install vim \ + && apt-get clean; \ No newline at end of file diff --git a/.docker/php-fpm/php-ini-overrides.ini b/.docker/php-fpm/php-ini-overrides.ini new file mode 100644 index 00000000..0333b26d --- /dev/null +++ b/.docker/php-fpm/php-ini-overrides.ini @@ -0,0 +1,17 @@ +upload_max_filesize = 100M +post_max_size = 108M +html_errors=On +display_errors=On +date.timezone=Europe/Paris +memory_limit=-1 +max_execution_time = 300 + +xdebug.idekey = "PHPSTORM" +xdebug.remote_enable=1 +xdebug.remote_autostart=1 +xdebug.remote_port=9000 +xdebug.remote_connect_back=1 +xdebug.remote_handler=dbgp +xdebug.profiler_enable=0 +xdebug.profiler_enable_trigger=1 +xdebug.profiler_output_dir="/application/log" diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 00000000..2fc705b3 --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,65 @@ +name: test +on: + push: + branches: [ master ] + pull_request: + branches: [ master ] +jobs: + phpunit: + name: PHP ${{ matrix.php-versions }} + runs-on: ubuntu-latest + services: + mysql: + image: mariadb:10.3 + env: + MYSQL_ROOT_PASSWORD: thelia + MYSQL_DATABASE: thelia + ports: + - 3306/tcp + options: --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=3 + strategy: + fail-fast: false + matrix: + php-versions: ['5.6', '7.0', '7.1', '7.2', '7.3'] + steps: + - name: Checkout + uses: actions/checkout@v2 + - name: Setup Environment + run: | + sudo apt-get update + sudo apt-get install sendmail + - name: Setup PHP, with composer and extensions + uses: shivammathur/setup-php@v2 #https://github.com/shivammathur/setup-php + with: + php-version: ${{ matrix.php-versions }} + ini-values: post_max_size=20M + extensions: mbstring, xml, ctype, iconv, intl, pdo_sqlite, mysql, gd, zip + - name: Start mysql service + run: sudo /etc/init.d/mysql start + - name: Get composer cache directory + id: composercache + run: echo "::set-output name=dir::$(composer config cache-files-dir)" + - name: Cache composer dependencies + uses: actions/cache@v2 + with: + path: ${{ steps.composercache.outputs.dir }} + # Use composer.json for key, if composer.lock is not committed. + # key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }} + key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} + restore-keys: ${{ runner.os }}-composer- + - name: Install Composer dependencies + run: | + composer install --no-progress --prefer-dist --optimize-autoloader + composer update --no-interaction --prefer-dist + - name: Install Thelia + run: | + php Thelia thelia:install --db_host=127.0.0.1:${{ job.services.mysql.ports['3306'] }} --db_username=root --db_name=thelia --db_password=thelia + php setup/faker.php -r 0 + php Thelia module:refresh + php Thelia module:activate Colissimo + php Thelia module:activate Cheque + php Thelia module:activate HookTest + php Thelia module:activate VirtualProductDelivery + php Thelia admin:create --login_name thelia2 --password thelia2 --last_name thelia2 --first_name thelia2 --email thelia2@example.com + - name: Run PHPUnit + run: php bin/phpunit diff --git a/.gitignore b/.gitignore index 381b5d94..aaee0c3e 100644 --- a/.gitignore +++ b/.gitignore @@ -35,36 +35,6 @@ 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 @@ -76,6 +46,3 @@ config.codekit # 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 index d239cf73..ecf17393 100644 --- a/.htaccess +++ b/.htaccess @@ -1,3 +1,3 @@ -# -#RedirectMatch 301 ^/$ https://auxbieauxlegumes.fr/web -# + +RedirectMatch 301 ^/$ https://auxbieauxlegumes.fr/web + diff --git a/composer.json b/composer.json index 265673c4..9ca0b8ff 100644 --- a/composer.json +++ b/composer.json @@ -62,9 +62,7 @@ "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" + "symfony/var-dumper": "^2.0|^3.0|^4.0" }, "require-dev": { "fzaninotto/faker": "1.5.*", diff --git a/composer.lock b/composer.lock index f33ebb82..92bf8c8f 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "e6f383fd8a02cb1279f5ca2e0c78d2c6", + "content-hash": "5775e58f869179ca9e753e2556329f65", "packages": [ { "name": "commerceguys/addressing", @@ -180,31 +180,34 @@ }, { "name": "doctrine/collections", - "version": "1.6.7", + "version": "v1.4.0", "source": { "type": "git", "url": "https://github.com/doctrine/collections.git", - "reference": "55f8b799269a1a472457bd1a41b4f379d4cfba4a" + "reference": "1a4fb7e902202c33cce8c55989b945612943c2ba" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/collections/zipball/55f8b799269a1a472457bd1a41b4f379d4cfba4a", - "reference": "55f8b799269a1a472457bd1a41b4f379d4cfba4a", + "url": "https://api.github.com/repos/doctrine/collections/zipball/1a4fb7e902202c33cce8c55989b945612943c2ba", + "reference": "1a4fb7e902202c33cce8c55989b945612943c2ba", "shasum": "" }, "require": { - "php": "^7.1.3 || ^8.0" + "php": "^5.6 || ^7.0" }, "require-dev": { - "doctrine/coding-standard": "^6.0", - "phpstan/phpstan-shim": "^0.9.2", - "phpunit/phpunit": "^7.0", - "vimeo/psalm": "^3.8.1" + "doctrine/coding-standard": "~0.1@dev", + "phpunit/phpunit": "^5.7" }, "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.3.x-dev" + } + }, "autoload": { - "psr-4": { - "Doctrine\\Common\\Collections\\": "lib/Doctrine/Common/Collections" + "psr-0": { + "Doctrine\\Common\\Collections\\": "lib/" } }, "notification-url": "https://packagist.org/downloads/", @@ -212,10 +215,6 @@ "MIT" ], "authors": [ - { - "name": "Guilherme Blanco", - "email": "guilhermeblanco@gmail.com" - }, { "name": "Roman Borschel", "email": "roman@code-factory.org" @@ -224,6 +223,10 @@ "name": "Benjamin Eberlei", "email": "kontakt@beberlei.de" }, + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, { "name": "Jonathan Wage", "email": "jonwage@gmail.com" @@ -233,15 +236,14 @@ "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", + "description": "Collections Abstraction library", + "homepage": "http://www.doctrine-project.org", "keywords": [ "array", "collections", - "iterators", - "php" + "iterator" ], - "time": "2020-07-27T17:53:49+00:00" + "time": "2017-01-03T10:49:41+00:00" }, { "name": "imagine/imagine", @@ -534,6 +536,55 @@ "abandoned": true, "time": "2017-03-28T22:19:25+00:00" }, + { + "name": "paragonie/random_compat", + "version": "v2.0.17", + "source": { + "type": "git", + "url": "https://github.com/paragonie/random_compat.git", + "reference": "29af24f25bab834fcbb38ad2a69fa93b867e070d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/paragonie/random_compat/zipball/29af24f25bab834fcbb38ad2a69fa93b867e070d", + "reference": "29af24f25bab834fcbb38ad2a69fa93b867e070d", + "shasum": "" + }, + "require": { + "php": ">=5.2.0" + }, + "require-dev": { + "phpunit/phpunit": "4.*|5.*" + }, + "suggest": { + "ext-libsodium": "Provides a modern crypto API that can be used to generate random bytes." + }, + "type": "library", + "autoload": { + "files": [ + "lib/random.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Paragon Initiative Enterprises", + "email": "security@paragonie.com", + "homepage": "https://paragonie.com" + } + ], + "description": "PHP 5.x polyfill for random_bytes() and random_int() from PHP 7", + "keywords": [ + "csprng", + "polyfill", + "pseudorandom", + "random" + ], + "time": "2018-07-04T16:31:37+00:00" + }, { "name": "psr/cache", "version": "1.0.1", @@ -816,27 +867,27 @@ }, { "name": "spipu/html2pdf", - "version": "v5.2.2", + "version": "v5.2.1", "source": { "type": "git", "url": "https://github.com/spipu/html2pdf.git", - "reference": "e6d8ca22347b6691bb8c2652212b1be2c89b3eff" + "reference": "7dca57b61fdb2d6920635ff2332dbc82d4be19f3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/spipu/html2pdf/zipball/e6d8ca22347b6691bb8c2652212b1be2c89b3eff", - "reference": "e6d8ca22347b6691bb8c2652212b1be2c89b3eff", + "url": "https://api.github.com/repos/spipu/html2pdf/zipball/7dca57b61fdb2d6920635ff2332dbc82d4be19f3", + "reference": "7dca57b61fdb2d6920635ff2332dbc82d4be19f3", "shasum": "" }, "require": { - "ext-gd": "*", "ext-mbstring": "*", - "php": "^5.6 || ^7.0", + "php": "^5.4 || ^7.0", "tecnickcom/tcpdf": "^6.2" }, "require-dev": { "phake/phake": "^2.0", - "phpunit/phpunit": "^5.0" + "phpunit/phpunit": "^4.0 || ^5.0", + "squizlabs/php_codesniffer": "^3.0" }, "suggest": { "ext-gd": "Allows to embed images into the PDF", @@ -866,30 +917,29 @@ "html2pdf", "pdf" ], - "time": "2020-03-22T16:23:26+00:00" + "time": "2018-10-26T13:33:18+00:00" }, { "name": "stack/builder", - "version": "v1.0.6", + "version": "v1.0.5", "source": { "type": "git", "url": "https://github.com/stackphp/builder.git", - "reference": "a4faaa6f532c6086bc66c29e1bc6c29593e1ca7c" + "reference": "fb3d136d04c6be41120ebf8c0cc71fe9507d750a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/stackphp/builder/zipball/a4faaa6f532c6086bc66c29e1bc6c29593e1ca7c", - "reference": "a4faaa6f532c6086bc66c29e1bc6c29593e1ca7c", + "url": "https://api.github.com/repos/stackphp/builder/zipball/fb3d136d04c6be41120ebf8c0cc71fe9507d750a", + "reference": "fb3d136d04c6be41120ebf8c0cc71fe9507d750a", "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" + "php": ">=5.3.0", + "symfony/http-foundation": "~2.1|~3.0|~4.0", + "symfony/http-kernel": "~2.1|~3.0|~4.0" }, "require-dev": { - "phpunit/phpunit": "~8.0", - "symfony/routing": "^5.0" + "silex/silex": "~1.0" }, "type": "library", "extra": { @@ -912,11 +962,11 @@ "email": "igor@wiedler.ch" } ], - "description": "Builder for stack middleware based on HttpKernelInterface.", + "description": "Builder for stack middlewares based on HttpKernelInterface.", "keywords": [ "stack" ], - "time": "2020-01-30T12:17:27+00:00" + "time": "2017-11-18T14:57:29+00:00" }, { "name": "swiftmailer/swiftmailer", @@ -1031,16 +1081,16 @@ }, { "name": "symfony/browser-kit", - "version": "v2.8.52", + "version": "v2.8.47", "source": { "type": "git", "url": "https://github.com/symfony/browser-kit.git", - "reference": "b507697225f32a76a9d333d0766fb46353e9d00d" + "reference": "fe44362c97307e7935996cb09d320fcc22619656" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/browser-kit/zipball/b507697225f32a76a9d333d0766fb46353e9d00d", - "reference": "b507697225f32a76a9d333d0766fb46353e9d00d", + "url": "https://api.github.com/repos/symfony/browser-kit/zipball/fe44362c97307e7935996cb09d320fcc22619656", + "reference": "fe44362c97307e7935996cb09d320fcc22619656", "shasum": "" }, "require": { @@ -1084,30 +1134,31 @@ ], "description": "Symfony BrowserKit Component", "homepage": "https://symfony.com", - "time": "2018-11-26T06:55:10+00:00" + "time": "2018-07-26T09:03:18+00:00" }, { "name": "symfony/cache", - "version": "v4.1.12", + "version": "v3.4.35", "source": { "type": "git", "url": "https://github.com/symfony/cache.git", - "reference": "399ddbf0ff98f42593827141b5fcd95d51c36b28" + "reference": "8d5db9c0cecf8b6f79fa96583fae652224d897da" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/cache/zipball/399ddbf0ff98f42593827141b5fcd95d51c36b28", - "reference": "399ddbf0ff98f42593827141b5fcd95d51c36b28", + "url": "https://api.github.com/repos/symfony/cache/zipball/8d5db9c0cecf8b6f79fa96583fae652224d897da", + "reference": "8d5db9c0cecf8b6f79fa96583fae652224d897da", "shasum": "" }, "require": { - "php": "^7.1.3", + "php": "^5.5.9|>=7.0.8", "psr/cache": "~1.0", "psr/log": "~1.0", - "psr/simple-cache": "^1.0" + "psr/simple-cache": "^1.0", + "symfony/polyfill-apcu": "~1.1" }, "conflict": { - "symfony/var-dumper": "<3.4" + "symfony/var-dumper": "<3.3" }, "provide": { "psr/cache-implementation": "1.0", @@ -1122,7 +1173,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "4.1-dev" + "dev-master": "3.4-dev" } }, "autoload": { @@ -1153,20 +1204,20 @@ "caching", "psr6" ], - "time": "2019-04-16T09:37:00+00:00" + "time": "2019-11-12T12:50:33+00:00" }, { "name": "symfony/class-loader", - "version": "v2.8.52", + "version": "v2.8.47", "source": { "type": "git", "url": "https://github.com/symfony/class-loader.git", - "reference": "8194721a1e2768cfb95079581889c41eec7a5959" + "reference": "5694f145b1f7b35a55d7d31c58f12d72803f7d7e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/class-loader/zipball/8194721a1e2768cfb95079581889c41eec7a5959", - "reference": "8194721a1e2768cfb95079581889c41eec7a5959", + "url": "https://api.github.com/repos/symfony/class-loader/zipball/5694f145b1f7b35a55d7d31c58f12d72803f7d7e", + "reference": "5694f145b1f7b35a55d7d31c58f12d72803f7d7e", "shasum": "" }, "require": { @@ -1206,20 +1257,20 @@ ], "description": "Symfony ClassLoader Component", "homepage": "https://symfony.com", - "time": "2018-11-11T11:18:13+00:00" + "time": "2018-10-30T16:24:01+00:00" }, { "name": "symfony/config", - "version": "v2.8.52", + "version": "v2.8.47", "source": { "type": "git", "url": "https://github.com/symfony/config.git", - "reference": "7dd5f5040dc04c118d057fb5886563963eb70011" + "reference": "506aaec58da5b042ec23f7de5cc866eb4b57a21e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/config/zipball/7dd5f5040dc04c118d057fb5886563963eb70011", - "reference": "7dd5f5040dc04c118d057fb5886563963eb70011", + "url": "https://api.github.com/repos/symfony/config/zipball/506aaec58da5b042ec23f7de5cc866eb4b57a21e", + "reference": "506aaec58da5b042ec23f7de5cc866eb4b57a21e", "shasum": "" }, "require": { @@ -1263,20 +1314,20 @@ ], "description": "Symfony Config Component", "homepage": "https://symfony.com", - "time": "2018-11-26T09:38:12+00:00" + "time": "2018-10-30T16:24:01+00:00" }, { "name": "symfony/console", - "version": "v2.8.52", + "version": "v2.8.47", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "cbcf4b5e233af15cd2bbd50dee1ccc9b7927dc12" + "reference": "48ed63767c4add573fb3e9e127d3426db27f78e8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/cbcf4b5e233af15cd2bbd50dee1ccc9b7927dc12", - "reference": "cbcf4b5e233af15cd2bbd50dee1ccc9b7927dc12", + "url": "https://api.github.com/repos/symfony/console/zipball/48ed63767c4add573fb3e9e127d3426db27f78e8", + "reference": "48ed63767c4add573fb3e9e127d3426db27f78e8", "shasum": "" }, "require": { @@ -1324,20 +1375,20 @@ ], "description": "Symfony Console Component", "homepage": "https://symfony.com", - "time": "2018-11-20T15:55:20+00:00" + "time": "2018-10-30T14:26:34+00:00" }, { "name": "symfony/debug", - "version": "v2.8.52", + "version": "v2.8.47", "source": { "type": "git", "url": "https://github.com/symfony/debug.git", - "reference": "74251c8d50dd3be7c4ce0c7b862497cdc641a5d0" + "reference": "6a198c52b662fa825382f5e65c0c4a56bdaca98e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/debug/zipball/74251c8d50dd3be7c4ce0c7b862497cdc641a5d0", - "reference": "74251c8d50dd3be7c4ce0c7b862497cdc641a5d0", + "url": "https://api.github.com/repos/symfony/debug/zipball/6a198c52b662fa825382f5e65c0c4a56bdaca98e", + "reference": "6a198c52b662fa825382f5e65c0c4a56bdaca98e", "shasum": "" }, "require": { @@ -1381,11 +1432,11 @@ ], "description": "Symfony Debug Component", "homepage": "https://symfony.com", - "time": "2018-11-11T11:18:13+00:00" + "time": "2018-10-30T16:24:01+00:00" }, { "name": "symfony/dependency-injection", - "version": "v2.8.52", + "version": "v2.8.50", "source": { "type": "git", "url": "https://github.com/symfony/dependency-injection.git", @@ -1448,16 +1499,16 @@ }, { "name": "symfony/dom-crawler", - "version": "v2.8.52", + "version": "v2.8.47", "source": { "type": "git", "url": "https://github.com/symfony/dom-crawler.git", - "reference": "2cdc7d3909eea6f982a6298d2e9ab7db01b6403c" + "reference": "a02078d236b10cbd27e003734afd4cdd35dc7da9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/dom-crawler/zipball/2cdc7d3909eea6f982a6298d2e9ab7db01b6403c", - "reference": "2cdc7d3909eea6f982a6298d2e9ab7db01b6403c", + "url": "https://api.github.com/repos/symfony/dom-crawler/zipball/a02078d236b10cbd27e003734afd4cdd35dc7da9", + "reference": "a02078d236b10cbd27e003734afd4cdd35dc7da9", "shasum": "" }, "require": { @@ -1501,29 +1552,34 @@ ], "description": "Symfony DomCrawler Component", "homepage": "https://symfony.com", - "time": "2018-11-24T22:30:19+00:00" + "time": "2018-10-02T03:12:00+00:00" }, { "name": "symfony/dotenv", - "version": "v4.4.18", + "version": "v3.4.18", "source": { "type": "git", "url": "https://github.com/symfony/dotenv.git", - "reference": "2befc49ec50b4d6ffd100b332389260c9069ba1c" + "reference": "6e949fc1bfa9d76b8a986fbfaab4dbc188927126" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/dotenv/zipball/2befc49ec50b4d6ffd100b332389260c9069ba1c", - "reference": "2befc49ec50b4d6ffd100b332389260c9069ba1c", + "url": "https://api.github.com/repos/symfony/dotenv/zipball/6e949fc1bfa9d76b8a986fbfaab4dbc188927126", + "reference": "6e949fc1bfa9d76b8a986fbfaab4dbc188927126", "shasum": "" }, "require": { - "php": ">=7.1.3" + "php": "^5.5.9|>=7.0.8" }, "require-dev": { - "symfony/process": "^3.4.2|^4.0|^5.0" + "symfony/process": "~3.2|~4.0" }, "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.4-dev" + } + }, "autoload": { "psr-4": { "Symfony\\Component\\Dotenv\\": "" @@ -1553,34 +1609,20 @@ "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" + "time": "2018-10-12T12:54:24+00:00" }, { "name": "symfony/event-dispatcher", - "version": "v2.8.52", + "version": "v2.8.47", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "a77e974a5fecb4398833b0709210e3d5e334ffb0" + "reference": "76494bc38ff38d90d01913d23b5271acd4d78dd3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/a77e974a5fecb4398833b0709210e3d5e334ffb0", - "reference": "a77e974a5fecb4398833b0709210e3d5e334ffb0", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/76494bc38ff38d90d01913d23b5271acd4d78dd3", + "reference": "76494bc38ff38d90d01913d23b5271acd4d78dd3", "shasum": "" }, "require": { @@ -1627,20 +1669,20 @@ ], "description": "Symfony EventDispatcher Component", "homepage": "https://symfony.com", - "time": "2018-11-21T14:20:20+00:00" + "time": "2018-10-20T23:16:31+00:00" }, { "name": "symfony/expression-language", - "version": "v2.8.52", + "version": "v2.8.47", "source": { "type": "git", "url": "https://github.com/symfony/expression-language.git", - "reference": "fa9be1b831859b56d244137fabbfd01a46dbdb36" + "reference": "aa8931b2c8ae64f58db2617cf109deebdb31d967" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/expression-language/zipball/fa9be1b831859b56d244137fabbfd01a46dbdb36", - "reference": "fa9be1b831859b56d244137fabbfd01a46dbdb36", + "url": "https://api.github.com/repos/symfony/expression-language/zipball/aa8931b2c8ae64f58db2617cf109deebdb31d967", + "reference": "aa8931b2c8ae64f58db2617cf109deebdb31d967", "shasum": "" }, "require": { @@ -1676,20 +1718,20 @@ ], "description": "Symfony ExpressionLanguage Component", "homepage": "https://symfony.com", - "time": "2018-11-11T11:18:13+00:00" + "time": "2018-07-26T09:03:18+00:00" }, { "name": "symfony/filesystem", - "version": "v2.8.52", + "version": "v2.8.47", "source": { "type": "git", "url": "https://github.com/symfony/filesystem.git", - "reference": "7ae46872dad09dffb7fe1e93a0937097339d0080" + "reference": "56a92481a4969b234b1647b1fd1170281e80e2ca" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/7ae46872dad09dffb7fe1e93a0937097339d0080", - "reference": "7ae46872dad09dffb7fe1e93a0937097339d0080", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/56a92481a4969b234b1647b1fd1170281e80e2ca", + "reference": "56a92481a4969b234b1647b1fd1170281e80e2ca", "shasum": "" }, "require": { @@ -1726,20 +1768,20 @@ ], "description": "Symfony Filesystem Component", "homepage": "https://symfony.com", - "time": "2018-11-11T11:18:13+00:00" + "time": "2018-10-02T03:12:00+00:00" }, { "name": "symfony/finder", - "version": "v2.8.52", + "version": "v2.8.47", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "1444eac52273e345d9b95129bf914639305a9ba4" + "reference": "5ebb438d1aabe9dba93099dd06e0500f97817a6e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/1444eac52273e345d9b95129bf914639305a9ba4", - "reference": "1444eac52273e345d9b95129bf914639305a9ba4", + "url": "https://api.github.com/repos/symfony/finder/zipball/5ebb438d1aabe9dba93099dd06e0500f97817a6e", + "reference": "5ebb438d1aabe9dba93099dd06e0500f97817a6e", "shasum": "" }, "require": { @@ -1775,20 +1817,20 @@ ], "description": "Symfony Finder Component", "homepage": "https://symfony.com", - "time": "2018-11-11T11:18:13+00:00" + "time": "2018-09-21T12:46:38+00:00" }, { "name": "symfony/form", - "version": "v2.8.52", + "version": "v2.8.47", "source": { "type": "git", "url": "https://github.com/symfony/form.git", - "reference": "74382a47aa97496d181fbb598822fdfb9e1744e4" + "reference": "783643f8d0aa39a1eedb67747b7ab23949152707" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/form/zipball/74382a47aa97496d181fbb598822fdfb9e1744e4", - "reference": "74382a47aa97496d181fbb598822fdfb9e1744e4", + "url": "https://api.github.com/repos/symfony/form/zipball/783643f8d0aa39a1eedb67747b7ab23949152707", + "reference": "783643f8d0aa39a1eedb67747b7ab23949152707", "shasum": "" }, "require": { @@ -1851,7 +1893,7 @@ ], "description": "Symfony Form Component", "homepage": "https://symfony.com", - "time": "2018-12-06T11:12:46+00:00" + "time": "2018-10-20T23:16:31+00:00" }, { "name": "symfony/http-foundation", @@ -1910,16 +1952,16 @@ }, { "name": "symfony/http-kernel", - "version": "v2.8.52", + "version": "v2.8.47", "source": { "type": "git", "url": "https://github.com/symfony/http-kernel.git", - "reference": "c3be27b8627cd5ee8dfa8d1b923982f618ec521c" + "reference": "10b941cef0cd380d8be62772e4882568ec320a71" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-kernel/zipball/c3be27b8627cd5ee8dfa8d1b923982f618ec521c", - "reference": "c3be27b8627cd5ee8dfa8d1b923982f618ec521c", + "url": "https://api.github.com/repos/symfony/http-kernel/zipball/10b941cef0cd380d8be62772e4882568ec320a71", + "reference": "10b941cef0cd380d8be62772e4882568ec320a71", "shasum": "" }, "require": { @@ -1928,8 +1970,7 @@ "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" + "symfony/polyfill-ctype": "~1.8" }, "conflict": { "symfony/config": "<2.7", @@ -1991,7 +2032,7 @@ ], "description": "Symfony HttpKernel Component", "homepage": "https://symfony.com", - "time": "2019-11-13T08:36:16+00:00" + "time": "2018-11-03T09:53:57+00:00" }, { "name": "symfony/intl", @@ -2070,30 +2111,32 @@ }, { "name": "symfony/lock", - "version": "v4.4.18", + "version": "v3.4.21", "source": { "type": "git", "url": "https://github.com/symfony/lock.git", - "reference": "8017f2ecc7de4b6cc1585d502e65ea4f56d42051" + "reference": "c9b09fe759e803fb0ff51218f48bf1c2328e1133" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/lock/zipball/8017f2ecc7de4b6cc1585d502e65ea4f56d42051", - "reference": "8017f2ecc7de4b6cc1585d502e65ea4f56d42051", + "url": "https://api.github.com/repos/symfony/lock/zipball/c9b09fe759e803fb0ff51218f48bf1c2328e1133", + "reference": "c9b09fe759e803fb0ff51218f48bf1c2328e1133", "shasum": "" }, "require": { - "php": ">=7.1.3", - "psr/log": "~1.0" - }, - "conflict": { - "doctrine/dbal": "<2.5" + "php": "^5.5.9|>=7.0.8", + "psr/log": "~1.0", + "symfony/polyfill-php70": "~1.0" }, "require-dev": { - "doctrine/dbal": "^2.5|^3.0", "predis/predis": "~1.0" }, "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.4-dev" + } + }, "autoload": { "psr-4": { "Symfony\\Component\\Lock\\": "" @@ -2107,13 +2150,13 @@ "MIT" ], "authors": [ - { - "name": "Jérémy Derussé", - "email": "jeremy@derusse.com" - }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" + }, + { + "name": "Jérémy Derussé", + "email": "jeremy@derusse.com" } ], "description": "Symfony Lock Component", @@ -2126,34 +2169,20 @@ "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" + "time": "2019-01-01T17:35:40+00:00" }, { "name": "symfony/options-resolver", - "version": "v2.8.52", + "version": "v2.8.47", "source": { "type": "git", "url": "https://github.com/symfony/options-resolver.git", - "reference": "7aaab725bb58f0e18aa12c61bdadd4793ab4c32b" + "reference": "43441c14988c1c66b16db5a88c4a70920f60bd56" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/options-resolver/zipball/7aaab725bb58f0e18aa12c61bdadd4793ab4c32b", - "reference": "7aaab725bb58f0e18aa12c61bdadd4793ab4c32b", + "url": "https://api.github.com/repos/symfony/options-resolver/zipball/43441c14988c1c66b16db5a88c4a70920f60bd56", + "reference": "43441c14988c1c66b16db5a88c4a70920f60bd56", "shasum": "" }, "require": { @@ -2194,33 +2223,29 @@ "configuration", "options" ], - "time": "2018-11-11T11:18:13+00:00" + "time": "2018-10-02T11:25:20+00:00" }, { "name": "symfony/polyfill-apcu", - "version": "v1.22.0", + "version": "v1.13.1", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-apcu.git", - "reference": "3b3944f40987b9d3f9b9147f86c32df87d9f3505" + "reference": "a8e961c841b9ec52927a87914f8820a1ad8f8116" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-apcu/zipball/3b3944f40987b9d3f9b9147f86c32df87d9f3505", - "reference": "3b3944f40987b9d3f9b9147f86c32df87d9f3505", + "url": "https://api.github.com/repos/symfony/polyfill-apcu/zipball/a8e961c841b9ec52927a87914f8820a1ad8f8116", + "reference": "a8e961c841b9ec52927a87914f8820a1ad8f8116", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=5.3.3" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "1.22-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "dev-master": "1.13-dev" } }, "autoload": { @@ -2254,38 +2279,24 @@ "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" + "time": "2019-11-27T13:56:44+00:00" }, { "name": "symfony/polyfill-ctype", - "version": "v1.22.0", + "version": "v1.10.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-ctype.git", - "reference": "c6c942b1ac76c82448322025e084cadc56048b4e" + "reference": "e3d826245268269cd66f8326bd8bc066687b4a19" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/c6c942b1ac76c82448322025e084cadc56048b4e", - "reference": "c6c942b1ac76c82448322025e084cadc56048b4e", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/e3d826245268269cd66f8326bd8bc066687b4a19", + "reference": "e3d826245268269cd66f8326bd8bc066687b4a19", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=5.3.3" }, "suggest": { "ext-ctype": "For best performance" @@ -2293,11 +2304,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "1.22-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "dev-master": "1.9-dev" } }, "autoload": { @@ -2313,13 +2320,13 @@ "MIT" ], "authors": [ - { - "name": "Gert de Pagter", - "email": "BackEndTea@gmail.com" - }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" + }, + { + "name": "Gert de Pagter", + "email": "BackEndTea@gmail.com" } ], "description": "Symfony polyfill for ctype functions", @@ -2330,64 +2337,38 @@ "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" + "time": "2018-08-06T14:22:27+00:00" }, { "name": "symfony/polyfill-intl-icu", - "version": "v1.22.0", + "version": "v1.10.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-icu.git", - "reference": "b2b1e732a6c039f1a3ea3414b3379a2433e183d6" + "reference": "f22a90256d577c7ef7efad8df1f0201663d57644" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-icu/zipball/b2b1e732a6c039f1a3ea3414b3379a2433e183d6", - "reference": "b2b1e732a6c039f1a3ea3414b3379a2433e183d6", + "url": "https://api.github.com/repos/symfony/polyfill-intl-icu/zipball/f22a90256d577c7ef7efad8df1f0201663d57644", + "reference": "f22a90256d577c7ef7efad8df1f0201663d57644", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=5.3.3", + "symfony/intl": "~2.3|~3.0|~4.0" }, "suggest": { - "ext-intl": "For best performance and support of other locales than \"en\"" + "ext-intl": "For best performance" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "1.22-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "dev-master": "1.9-dev" } }, "autoload": { "files": [ "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Intl\\Icu\\": "" - }, - "classmap": [ - "Resources/stubs" - ], - "exclude-from-classmap": [ - "/Tests/" ] }, "notification-url": "https://packagist.org/downloads/", @@ -2414,38 +2395,24 @@ "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" + "time": "2018-08-06T14:22:27+00:00" }, { "name": "symfony/polyfill-mbstring", - "version": "v1.22.0", + "version": "v1.13.1", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "f377a3dd1fde44d37b9831d68dc8dea3ffd28e13" + "reference": "7b4aab9743c30be783b73de055d24a39cf4b954f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/f377a3dd1fde44d37b9831d68dc8dea3ffd28e13", - "reference": "f377a3dd1fde44d37b9831d68dc8dea3ffd28e13", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/7b4aab9743c30be783b73de055d24a39cf4b954f", + "reference": "7b4aab9743c30be783b73de055d24a39cf4b954f", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=5.3.3" }, "suggest": { "ext-mbstring": "For best performance" @@ -2453,11 +2420,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "1.22-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "dev-master": "1.13-dev" } }, "autoload": { @@ -2491,49 +2454,42 @@ "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" + "time": "2019-11-27T14:18:11+00:00" }, { "name": "symfony/polyfill-php54", - "version": "v1.20.0", + "version": "v1.13.1", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php54.git", - "reference": "37285b1d5d13f37c8bee546d8d2ad0353460c4c7" + "reference": "dd1618047426412036e98d159940d58a81fc392c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php54/zipball/37285b1d5d13f37c8bee546d8d2ad0353460c4c7", - "reference": "37285b1d5d13f37c8bee546d8d2ad0353460c4c7", + "url": "https://api.github.com/repos/symfony/polyfill-php54/zipball/dd1618047426412036e98d159940d58a81fc392c", + "reference": "dd1618047426412036e98d159940d58a81fc392c", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=5.3.3" }, - "type": "metapackage", + "type": "library", "extra": { "branch-alias": { - "dev-main": "1.20-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "dev-master": "1.13-dev" } }, + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Php54\\": "" + }, + "files": [ + "bootstrap.php" + ], + "classmap": [ + "Resources/stubs" + ] + }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" @@ -2556,49 +2512,40 @@ "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" + "time": "2019-11-27T13:56:44+00:00" }, { "name": "symfony/polyfill-php55", - "version": "v1.20.0", + "version": "v1.14.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php55.git", - "reference": "c17452124a883900e1d73961f9075a638399c1a0" + "reference": "58a98ed90b40a15a1a76c59417386395d5b1ec76" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php55/zipball/c17452124a883900e1d73961f9075a638399c1a0", - "reference": "c17452124a883900e1d73961f9075a638399c1a0", + "url": "https://api.github.com/repos/symfony/polyfill-php55/zipball/58a98ed90b40a15a1a76c59417386395d5b1ec76", + "reference": "58a98ed90b40a15a1a76c59417386395d5b1ec76", "shasum": "" }, "require": { - "php": ">=7.1" + "ircmaxell/password-compat": "~1.0", + "php": ">=5.3.3" }, - "type": "metapackage", + "type": "library", "extra": { "branch-alias": { - "dev-main": "1.20-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "dev-master": "1.14-dev" } }, + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Php55\\": "" + }, + "files": [ + "bootstrap.php" + ] + }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" @@ -2621,49 +2568,40 @@ "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" + "time": "2020-01-13T11:15:53+00:00" }, { "name": "symfony/polyfill-php56", - "version": "v1.20.0", + "version": "v1.10.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php56.git", - "reference": "54b8cd7e6c1643d78d011f3be89f3ef1f9f4c675" + "reference": "ff208829fe1aa48ab9af356992bb7199fed551af" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php56/zipball/54b8cd7e6c1643d78d011f3be89f3ef1f9f4c675", - "reference": "54b8cd7e6c1643d78d011f3be89f3ef1f9f4c675", + "url": "https://api.github.com/repos/symfony/polyfill-php56/zipball/ff208829fe1aa48ab9af356992bb7199fed551af", + "reference": "ff208829fe1aa48ab9af356992bb7199fed551af", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=5.3.3", + "symfony/polyfill-util": "~1.0" }, - "type": "metapackage", + "type": "library", "extra": { "branch-alias": { - "dev-main": "1.20-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "dev-master": "1.9-dev" } }, + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Php56\\": "" + }, + "files": [ + "bootstrap.php" + ] + }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" @@ -2686,49 +2624,43 @@ "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" + "time": "2018-09-21T06:26:08+00:00" }, { "name": "symfony/polyfill-php70", - "version": "v1.20.0", + "version": "v1.10.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php70.git", - "reference": "5f03a781d984aae42cebd18e7912fa80f02ee644" + "reference": "6b88000cdd431cd2e940caa2cb569201f3f84224" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php70/zipball/5f03a781d984aae42cebd18e7912fa80f02ee644", - "reference": "5f03a781d984aae42cebd18e7912fa80f02ee644", + "url": "https://api.github.com/repos/symfony/polyfill-php70/zipball/6b88000cdd431cd2e940caa2cb569201f3f84224", + "reference": "6b88000cdd431cd2e940caa2cb569201f3f84224", "shasum": "" }, "require": { - "php": ">=7.1" + "paragonie/random_compat": "~1.0|~2.0|~9.99", + "php": ">=5.3.3" }, - "type": "metapackage", + "type": "library", "extra": { "branch-alias": { - "dev-main": "1.20-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "dev-master": "1.9-dev" } }, + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Php70\\": "" + }, + "files": [ + "bootstrap.php" + ], + "classmap": [ + "Resources/stubs" + ] + }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" @@ -2751,49 +2683,39 @@ "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" + "time": "2018-09-21T06:26:08+00:00" }, { "name": "symfony/polyfill-php71", - "version": "v1.20.0", + "version": "v1.10.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php71.git", - "reference": "2d6cdeca7ea470e50db9e544c9ec4b1955036c22" + "reference": "1766834a22738196eb45486c4ca23c5739513bf4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php71/zipball/2d6cdeca7ea470e50db9e544c9ec4b1955036c22", - "reference": "2d6cdeca7ea470e50db9e544c9ec4b1955036c22", + "url": "https://api.github.com/repos/symfony/polyfill-php71/zipball/1766834a22738196eb45486c4ca23c5739513bf4", + "reference": "1766834a22738196eb45486c4ca23c5739513bf4", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=5.3.3" }, - "type": "metapackage", + "type": "library", "extra": { "branch-alias": { - "dev-main": "1.20-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "dev-master": "1.9-dev" } }, + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Php71\\": "" + }, + "files": [ + "bootstrap.php" + ] + }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" @@ -2816,47 +2738,29 @@ "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" + "time": "2018-08-06T14:22:27+00:00" }, { "name": "symfony/polyfill-php72", - "version": "v1.22.0", + "version": "v1.10.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php72.git", - "reference": "cc6e6f9b39fe8075b3dabfbaf5b5f645ae1340c9" + "reference": "9050816e2ca34a8e916c3a0ae8b9c2fccf68b631" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/cc6e6f9b39fe8075b3dabfbaf5b5f645ae1340c9", - "reference": "cc6e6f9b39fe8075b3dabfbaf5b5f645ae1340c9", + "url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/9050816e2ca34a8e916c3a0ae8b9c2fccf68b631", + "reference": "9050816e2ca34a8e916c3a0ae8b9c2fccf68b631", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=5.3.3" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "1.22-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "dev-master": "1.9-dev" } }, "autoload": { @@ -2889,47 +2793,29 @@ "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" + "time": "2018-09-21T13:07:52+00:00" }, { "name": "symfony/polyfill-php73", - "version": "v1.22.0", + "version": "v1.10.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php73.git", - "reference": "a678b42e92f86eca04b7fa4c0f6f19d097fb69e2" + "reference": "47ad352296d61aae366f075b8609f4dcc28853ef" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/a678b42e92f86eca04b7fa4c0f6f19d097fb69e2", - "reference": "a678b42e92f86eca04b7fa4c0f6f19d097fb69e2", + "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/47ad352296d61aae366f075b8609f4dcc28853ef", + "reference": "47ad352296d61aae366f075b8609f4dcc28853ef", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=5.3.3" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "1.22-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "dev-master": "1.9-dev" } }, "autoload": { @@ -2938,9 +2824,6 @@ }, "files": [ "bootstrap.php" - ], - "classmap": [ - "Resources/stubs" ] }, "notification-url": "https://packagist.org/downloads/", @@ -2965,47 +2848,29 @@ "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" + "time": "2018-09-25T06:33:47+00:00" }, { "name": "symfony/polyfill-util", - "version": "v1.22.0", + "version": "v1.14.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-util.git", - "reference": "ccda17fe137336f3c2c5321167c4a5e26371171a" + "reference": "ba3cfcea6d0192cae46c62041f61cbb704b526d3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-util/zipball/ccda17fe137336f3c2c5321167c4a5e26371171a", - "reference": "ccda17fe137336f3c2c5321167c4a5e26371171a", + "url": "https://api.github.com/repos/symfony/polyfill-util/zipball/ba3cfcea6d0192cae46c62041f61cbb704b526d3", + "reference": "ba3cfcea6d0192cae46c62041f61cbb704b526d3", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=5.3.3" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "1.22-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "dev-master": "1.14-dev" } }, "autoload": { @@ -3035,34 +2900,20 @@ "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" + "time": "2020-01-13T11:15:53+00:00" }, { "name": "symfony/process", - "version": "v2.8.52", + "version": "v2.8.47", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "c3591a09c78639822b0b290d44edb69bf9f05dc8" + "reference": "a15cb61190c6fe37168600922e82295eb5e5449b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/c3591a09c78639822b0b290d44edb69bf9f05dc8", - "reference": "c3591a09c78639822b0b290d44edb69bf9f05dc8", + "url": "https://api.github.com/repos/symfony/process/zipball/a15cb61190c6fe37168600922e82295eb5e5449b", + "reference": "a15cb61190c6fe37168600922e82295eb5e5449b", "shasum": "" }, "require": { @@ -3098,20 +2949,20 @@ ], "description": "Symfony Process Component", "homepage": "https://symfony.com", - "time": "2018-11-11T11:18:13+00:00" + "time": "2018-10-05T07:35:28+00:00" }, { "name": "symfony/property-access", - "version": "v2.8.52", + "version": "v2.8.47", "source": { "type": "git", "url": "https://github.com/symfony/property-access.git", - "reference": "c8f10191183be9bb0d5a1b8364d3891f1bde07b6" + "reference": "39eaaa4e316fbb246b9e3ea1150a284185804f49" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/property-access/zipball/c8f10191183be9bb0d5a1b8364d3891f1bde07b6", - "reference": "c8f10191183be9bb0d5a1b8364d3891f1bde07b6", + "url": "https://api.github.com/repos/symfony/property-access/zipball/39eaaa4e316fbb246b9e3ea1150a284185804f49", + "reference": "39eaaa4e316fbb246b9e3ea1150a284185804f49", "shasum": "" }, "require": { @@ -3159,20 +3010,20 @@ "property path", "reflection" ], - "time": "2018-11-11T11:18:13+00:00" + "time": "2018-10-02T12:08:28+00:00" }, { "name": "symfony/routing", - "version": "v2.8.52", + "version": "v2.8.47", "source": { "type": "git", "url": "https://github.com/symfony/routing.git", - "reference": "8b0df6869d1997baafff6a1541826eac5a03d067" + "reference": "066acfcc71bb8274dc4fcd6d438a2e368053f3a4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/routing/zipball/8b0df6869d1997baafff6a1541826eac5a03d067", - "reference": "8b0df6869d1997baafff6a1541826eac5a03d067", + "url": "https://api.github.com/repos/symfony/routing/zipball/066acfcc71bb8274dc4fcd6d438a2e368053f3a4", + "reference": "066acfcc71bb8274dc4fcd6d438a2e368053f3a4", "shasum": "" }, "require": { @@ -3233,11 +3084,11 @@ "uri", "url" ], - "time": "2018-11-20T15:55:20+00:00" + "time": "2018-10-02T03:12:00+00:00" }, { "name": "symfony/security", - "version": "v2.8.52", + "version": "v2.8.50", "source": { "type": "git", "url": "https://github.com/symfony/security.git", @@ -3384,16 +3235,16 @@ }, { "name": "symfony/serializer", - "version": "v2.8.52", + "version": "v2.8.47", "source": { "type": "git", "url": "https://github.com/symfony/serializer.git", - "reference": "2939e67396f7356aace05c90e5913736fcb46a20" + "reference": "b72447abdab3050a46fbedfa11e66e7c515e797d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/serializer/zipball/2939e67396f7356aace05c90e5913736fcb46a20", - "reference": "2939e67396f7356aace05c90e5913736fcb46a20", + "url": "https://api.github.com/repos/symfony/serializer/zipball/b72447abdab3050a46fbedfa11e66e7c515e797d", + "reference": "b72447abdab3050a46fbedfa11e66e7c515e797d", "shasum": "" }, "require": { @@ -3445,20 +3296,20 @@ ], "description": "Symfony Serializer Component", "homepage": "https://symfony.com", - "time": "2018-11-11T11:18:13+00:00" + "time": "2018-10-02T03:12:00+00:00" }, { "name": "symfony/translation", - "version": "v2.8.52", + "version": "v2.8.47", "source": { "type": "git", "url": "https://github.com/symfony/translation.git", - "reference": "fc58c2a19e56c29f5ba2736ec40d0119a0de2089" + "reference": "cb34ec9549ab65f7f512819441f2d6af4d12c294" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation/zipball/fc58c2a19e56c29f5ba2736ec40d0119a0de2089", - "reference": "fc58c2a19e56c29f5ba2736ec40d0119a0de2089", + "url": "https://api.github.com/repos/symfony/translation/zipball/cb34ec9549ab65f7f512819441f2d6af4d12c294", + "reference": "cb34ec9549ab65f7f512819441f2d6af4d12c294", "shasum": "" }, "require": { @@ -3509,20 +3360,20 @@ ], "description": "Symfony Translation Component", "homepage": "https://symfony.com", - "time": "2018-11-24T21:16:41+00:00" + "time": "2018-10-02T16:27:16+00:00" }, { "name": "symfony/validator", - "version": "v2.8.52", + "version": "v2.8.47", "source": { "type": "git", "url": "https://github.com/symfony/validator.git", - "reference": "d5d2090bba3139d8ddb79959fbf516e87238fe3a" + "reference": "7a97eba653f55581bf01f04431a936c4a9a83b93" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/validator/zipball/d5d2090bba3139d8ddb79959fbf516e87238fe3a", - "reference": "d5d2090bba3139d8ddb79959fbf516e87238fe3a", + "url": "https://api.github.com/repos/symfony/validator/zipball/7a97eba653f55581bf01f04431a936c4a9a83b93", + "reference": "7a97eba653f55581bf01f04431a936c4a9a83b93", "shasum": "" }, "require": { @@ -3583,26 +3434,25 @@ ], "description": "Symfony Validator Component", "homepage": "https://symfony.com", - "time": "2018-11-14T14:06:48+00:00" + "time": "2018-10-30T16:24:01+00:00" }, { "name": "symfony/var-dumper", - "version": "v4.0.15", + "version": "v3.4.38", "source": { "type": "git", "url": "https://github.com/symfony/var-dumper.git", - "reference": "3af63f44ddb45b03af4d172a4ce3e5c58b25fc5b" + "reference": "07801f3330aea80d58cbd125ad13a2f0b26c9d18" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-dumper/zipball/3af63f44ddb45b03af4d172a4ce3e5c58b25fc5b", - "reference": "3af63f44ddb45b03af4d172a4ce3e5c58b25fc5b", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/07801f3330aea80d58cbd125ad13a2f0b26c9d18", + "reference": "07801f3330aea80d58cbd125ad13a2f0b26c9d18", "shasum": "" }, "require": { - "php": "^7.1.3", - "symfony/polyfill-mbstring": "~1.0", - "symfony/polyfill-php72": "~1.5" + "php": "^5.5.9|>=7.0.8", + "symfony/polyfill-mbstring": "~1.0" }, "conflict": { "phpunit/phpunit": "<4.8.35|<5.4.3,>=5.0" @@ -3613,12 +3463,13 @@ }, "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" + "ext-intl": "To show region name in time zone dump", + "ext-symfony_debug": "" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "4.0-dev" + "dev-master": "3.4-dev" } }, "autoload": { @@ -3652,20 +3503,20 @@ "debug", "dump" ], - "time": "2018-07-26T11:22:46+00:00" + "time": "2020-02-14T12:39:29+00:00" }, { "name": "symfony/yaml", - "version": "v2.8.52", + "version": "v2.8.47", "source": { "type": "git", "url": "https://github.com/symfony/yaml.git", - "reference": "02c1859112aa779d9ab394ae4f3381911d84052b" + "reference": "0e16589861f192dbffb19b06683ce3ef58f7f99d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/02c1859112aa779d9ab394ae4f3381911d84052b", - "reference": "02c1859112aa779d9ab394ae4f3381911d84052b", + "url": "https://api.github.com/repos/symfony/yaml/zipball/0e16589861f192dbffb19b06683ce3ef58f7f99d", + "reference": "0e16589861f192dbffb19b06683ce3ef58f7f99d", "shasum": "" }, "require": { @@ -3702,20 +3553,20 @@ ], "description": "Symfony Yaml Component", "homepage": "https://symfony.com", - "time": "2018-11-11T11:18:13+00:00" + "time": "2018-10-02T16:27:16+00:00" }, { "name": "tecnickcom/tcpdf", - "version": "6.3.5", + "version": "6.2.26", "source": { "type": "git", "url": "https://github.com/tecnickcom/TCPDF.git", - "reference": "19a535eaa7fb1c1cac499109deeb1a7a201b4549" + "reference": "367241059ca166e3a76490f4448c284e0a161f15" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/tecnickcom/TCPDF/zipball/19a535eaa7fb1c1cac499109deeb1a7a201b4549", - "reference": "19a535eaa7fb1c1cac499109deeb1a7a201b4549", + "url": "https://api.github.com/repos/tecnickcom/TCPDF/zipball/367241059ca166e3a76490f4448c284e0a161f15", + "reference": "367241059ca166e3a76490f4448c284e0a161f15", "shasum": "" }, "require": { @@ -3744,7 +3595,7 @@ }, "notification-url": "https://packagist.org/downloads/", "license": [ - "LGPL-3.0-only" + "LGPL-3.0" ], "authors": [ { @@ -3764,34 +3615,7 @@ "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" + "time": "2018-10-16T17:24:05+00:00" }, { "name": "thelia/currency-converter", @@ -3838,54 +3662,6 @@ "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", @@ -3991,63 +3767,39 @@ "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", + "version": "1.0.5", "source": { "type": "git", "url": "https://github.com/doctrine/instantiator.git", - "reference": "d56bf6102915de5702778fe20f2de3b2fe570b5b" + "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/instantiator/zipball/d56bf6102915de5702778fe20f2de3b2fe570b5b", - "reference": "d56bf6102915de5702778fe20f2de3b2fe570b5b", + "url": "https://api.github.com/repos/doctrine/instantiator/zipball/8e884e78f9f0eb1329e445619e04456e64d8051d", + "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d", "shasum": "" }, "require": { - "php": "^7.1 || ^8.0" + "php": ">=5.3,<8.0-DEV" }, "require-dev": { - "doctrine/coding-standard": "^8.0", + "athletic/athletic": "~0.1.8", "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" + "phpunit/phpunit": "~4.0", + "squizlabs/php_codesniffer": "~2.0" }, "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, "autoload": { "psr-4": { "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" @@ -4061,30 +3813,16 @@ { "name": "Marco Pivetta", "email": "ocramius@gmail.com", - "homepage": "https://ocramius.github.io/" + "homepage": "http://ocramius.github.com/" } ], "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", - "homepage": "https://www.doctrine-project.org/projects/instantiator.html", + "homepage": "https://github.com/doctrine/instantiator", "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" + "time": "2015-06-14T21:17:01+00:00" }, { "name": "fzaninotto/faker", @@ -4136,33 +3874,29 @@ "faker", "fixtures" ], - "abandoned": true, "time": "2015-05-29T06:29:14+00:00" }, { "name": "myclabs/deep-copy", - "version": "1.10.2", + "version": "1.7.0", "source": { "type": "git", "url": "https://github.com/myclabs/DeepCopy.git", - "reference": "776f831124e9c62e1a2c601ecc52e776d8bb7220" + "reference": "3b8a3a99ba1f6a3952ac2747d989303cbd6b7a3e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/776f831124e9c62e1a2c601ecc52e776d8bb7220", - "reference": "776f831124e9c62e1a2c601ecc52e776d8bb7220", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/3b8a3a99ba1f6a3952ac2747d989303cbd6b7a3e", + "reference": "3b8a3a99ba1f6a3952ac2747d989303cbd6b7a3e", "shasum": "" }, "require": { - "php": "^7.1 || ^8.0" - }, - "replace": { - "myclabs/deep-copy": "self.version" + "php": "^5.6 || ^7.0" }, "require-dev": { "doctrine/collections": "^1.0", "doctrine/common": "^2.6", - "phpunit/phpunit": "^7.1" + "phpunit/phpunit": "^4.1" }, "type": "library", "autoload": { @@ -4185,40 +3919,39 @@ "object", "object graph" ], - "funding": [ - { - "url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy", - "type": "tidelift" - } - ], - "time": "2020-11-13T09:40:50+00:00" + "time": "2017-10-19T19:58:43+00:00" }, { "name": "phpdocumentor/reflection-common", - "version": "2.2.0", + "version": "1.0.1", "source": { "type": "git", "url": "https://github.com/phpDocumentor/ReflectionCommon.git", - "reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b" + "reference": "21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/1d01c49d4ed62f25aa84a747ad35d5a16924662b", - "reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6", + "reference": "21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6", "shasum": "" }, "require": { - "php": "^7.2 || ^8.0" + "php": ">=5.5" + }, + "require-dev": { + "phpunit/phpunit": "^4.6" }, "type": "library", "extra": { "branch-alias": { - "dev-2.x": "2.x-dev" + "dev-master": "1.0.x-dev" } }, "autoload": { "psr-4": { - "phpDocumentor\\Reflection\\": "src/" + "phpDocumentor\\Reflection\\": [ + "src" + ] } }, "notification-url": "https://packagist.org/downloads/", @@ -4240,41 +3973,38 @@ "reflection", "static analysis" ], - "time": "2020-06-27T09:03:43+00:00" + "time": "2017-09-11T18:02:19+00:00" }, { "name": "phpdocumentor/reflection-docblock", - "version": "5.2.2", + "version": "3.3.2", "source": { "type": "git", "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", - "reference": "069a785b2141f5bcf49f3e353548dc1cce6df556" + "reference": "bf329f6c1aadea3299f08ee804682b7c45b326a2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/069a785b2141f5bcf49f3e353548dc1cce6df556", - "reference": "069a785b2141f5bcf49f3e353548dc1cce6df556", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/bf329f6c1aadea3299f08ee804682b7c45b326a2", + "reference": "bf329f6c1aadea3299f08ee804682b7c45b326a2", "shasum": "" }, "require": { - "ext-filter": "*", - "php": "^7.2 || ^8.0", - "phpdocumentor/reflection-common": "^2.2", - "phpdocumentor/type-resolver": "^1.3", - "webmozart/assert": "^1.9.1" + "php": "^5.6 || ^7.0", + "phpdocumentor/reflection-common": "^1.0.0", + "phpdocumentor/type-resolver": "^0.4.0", + "webmozart/assert": "^1.0" }, "require-dev": { - "mockery/mockery": "~1.3.2" + "mockery/mockery": "^0.9.4", + "phpunit/phpunit": "^4.4" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "5.x-dev" - } - }, "autoload": { "psr-4": { - "phpDocumentor\\Reflection\\": "src" + "phpDocumentor\\Reflection\\": [ + "src/" + ] } }, "notification-url": "https://packagist.org/downloads/", @@ -4285,45 +4015,44 @@ { "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" + "time": "2017-11-10T14:09:06+00:00" }, { "name": "phpdocumentor/type-resolver", - "version": "1.4.0", + "version": "0.4.0", "source": { "type": "git", "url": "https://github.com/phpDocumentor/TypeResolver.git", - "reference": "6a467b8989322d92aa1c8bf2bebcc6e5c2ba55c0" + "reference": "9c977708995954784726e25d0cd1dddf4e65b0f7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/6a467b8989322d92aa1c8bf2bebcc6e5c2ba55c0", - "reference": "6a467b8989322d92aa1c8bf2bebcc6e5c2ba55c0", + "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/9c977708995954784726e25d0cd1dddf4e65b0f7", + "reference": "9c977708995954784726e25d0cd1dddf4e65b0f7", "shasum": "" }, "require": { - "php": "^7.2 || ^8.0", - "phpdocumentor/reflection-common": "^2.0" + "php": "^5.5 || ^7.0", + "phpdocumentor/reflection-common": "^1.0" }, "require-dev": { - "ext-tokenizer": "*" + "mockery/mockery": "^0.9.4", + "phpunit/phpunit": "^5.2||^4.8.24" }, "type": "library", "extra": { "branch-alias": { - "dev-1.x": "1.x-dev" + "dev-master": "1.0.x-dev" } }, "autoload": { "psr-4": { - "phpDocumentor\\Reflection\\": "src" + "phpDocumentor\\Reflection\\": [ + "src/" + ] } }, "notification-url": "https://packagist.org/downloads/", @@ -4336,43 +4065,42 @@ "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" + "time": "2017-07-14T14:27:02+00:00" }, { "name": "phpspec/prophecy", - "version": "v1.10.3", + "version": "1.8.0", "source": { "type": "git", "url": "https://github.com/phpspec/prophecy.git", - "reference": "451c3cd1418cf640de218914901e51b064abb093" + "reference": "4ba436b55987b4bf311cb7c6ba82aa528aac0a06" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpspec/prophecy/zipball/451c3cd1418cf640de218914901e51b064abb093", - "reference": "451c3cd1418cf640de218914901e51b064abb093", + "url": "https://api.github.com/repos/phpspec/prophecy/zipball/4ba436b55987b4bf311cb7c6ba82aa528aac0a06", + "reference": "4ba436b55987b4bf311cb7c6ba82aa528aac0a06", "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" + "phpdocumentor/reflection-docblock": "^2.0|^3.0.2|^4.0", + "sebastian/comparator": "^1.1|^2.0|^3.0", + "sebastian/recursion-context": "^1.0|^2.0|^3.0" }, "require-dev": { - "phpspec/phpspec": "^2.5 || ^3.2", + "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" + "dev-master": "1.8.x-dev" } }, "autoload": { - "psr-4": { - "Prophecy\\": "src/Prophecy" + "psr-0": { + "Prophecy\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -4400,7 +4128,7 @@ "spy", "stub" ], - "time": "2020-03-05T15:02:03+00:00" + "time": "2018-08-05T17:53:17+00:00" }, { "name": "phpunit/php-code-coverage", @@ -4604,29 +4332,29 @@ }, { "name": "phpunit/php-token-stream", - "version": "2.0.2", + "version": "1.4.12", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-token-stream.git", - "reference": "791198a2c6254db10131eecfe8c06670700904db" + "reference": "1ce90ba27c42e4e44e6d8458241466380b51fa16" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/791198a2c6254db10131eecfe8c06670700904db", - "reference": "791198a2c6254db10131eecfe8c06670700904db", + "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/1ce90ba27c42e4e44e6d8458241466380b51fa16", + "reference": "1ce90ba27c42e4e44e6d8458241466380b51fa16", "shasum": "" }, "require": { "ext-tokenizer": "*", - "php": "^7.0" + "php": ">=5.3.3" }, "require-dev": { - "phpunit/phpunit": "^6.2.4" + "phpunit/phpunit": "~4.2" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0-dev" + "dev-master": "1.4-dev" } }, "autoload": { @@ -4649,8 +4377,7 @@ "keywords": [ "tokenizer" ], - "abandoned": true, - "time": "2017-11-27T05:48:46+00:00" + "time": "2017-12-04T08:55:13+00:00" }, { "name": "phpunit/phpunit", @@ -4796,23 +4523,23 @@ }, { "name": "sebastian/code-unit-reverse-lookup", - "version": "1.0.2", + "version": "1.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", - "reference": "1de8cd5c010cb153fcd68b8d0f64606f523f7619" + "reference": "4419fcdb5eabb9caa61a27c7a1db532a6b55dd18" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/1de8cd5c010cb153fcd68b8d0f64606f523f7619", - "reference": "1de8cd5c010cb153fcd68b8d0f64606f523f7619", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/4419fcdb5eabb9caa61a27c7a1db532a6b55dd18", + "reference": "4419fcdb5eabb9caa61a27c7a1db532a6b55dd18", "shasum": "" }, "require": { - "php": ">=5.6" + "php": "^5.6 || ^7.0" }, "require-dev": { - "phpunit/phpunit": "^8.5" + "phpunit/phpunit": "^5.7 || ^6.0" }, "type": "library", "extra": { @@ -4837,13 +4564,7 @@ ], "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" + "time": "2017-03-04T06:30:41+00:00" }, { "name": "sebastian/comparator", @@ -5362,31 +5083,84 @@ "time": "2014-12-24T09:51:48+00:00" }, { - "name": "webmozart/assert", - "version": "1.9.1", + "name": "thelia/installer", + "version": "1.3", "source": { "type": "git", - "url": "https://github.com/webmozart/assert.git", - "reference": "bafc69caeb4d49c39fd0779086c03a3738cbb389" + "url": "https://github.com/thelia/installer.git", + "reference": "dca473563e05011c7aea3aaebc6f154fef4187fe" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/webmozart/assert/zipball/bafc69caeb4d49c39fd0779086c03a3738cbb389", - "reference": "bafc69caeb4d49c39fd0779086c03a3738cbb389", + "url": "https://api.github.com/repos/thelia/installer/zipball/dca473563e05011c7aea3aaebc6f154fef4187fe", + "reference": "dca473563e05011c7aea3aaebc6f154fef4187fe", "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" + "composer-plugin-api": "^1.0||^2.0" }, "require-dev": { - "phpunit/phpunit": "^4.8.36 || ^7.5.13" + "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" + ], + "support": { + "issues": "https://github.com/thelia/installer/issues", + "source": "https://github.com/thelia/installer/tree/1.3" + }, + "time": "2020-10-26T10:32:18+00:00" + }, + { + "name": "webmozart/assert", + "version": "1.3.0", + "source": { + "type": "git", + "url": "https://github.com/webmozart/assert.git", + "reference": "0df1908962e7a3071564e857d86874dad1ef204a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/webmozart/assert/zipball/0df1908962e7a3071564e857d86874dad1ef204a", + "reference": "0df1908962e7a3071564e857d86874dad1ef204a", + "shasum": "" + }, + "require": { + "php": "^5.3.3 || ^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.6", + "sebastian/version": "^1.0.1" }, "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.3-dev" + } + }, "autoload": { "psr-4": { "Webmozart\\Assert\\": "src/" @@ -5408,7 +5182,7 @@ "check", "validate" ], - "time": "2020-07-08T17:02:28+00:00" + "time": "2018-01-29T19:49:41+00:00" } ], "aliases": [], @@ -5422,5 +5196,5 @@ "php": ">=5.6 <7.4" }, "platform-dev": [], - "plugin-api-version": "1.1.0" + "plugin-api-version": "2.0.0" } diff --git a/local/modules/Atos/Atos.php b/local/modules/Atos/Atos.php new file mode 100644 index 00000000..a2e87d39 --- /dev/null +++ b/local/modules/Atos/Atos.php @@ -0,0 +1,363 @@ +insertSql(null, array( + __DIR__ . DS . 'Config'.DS.'thelia.sql' + )); + + // Create payment confirmation message from templates, if not already defined + $email_templates_dir = __DIR__.DS.'I18n'.DS.'email-templates'.DS; + + if (null === MessageQuery::create()->findOneByName(Atos::CONFIRMATION_MESSAGE_NAME)) { + $message = new Message(); + + $message + ->setName(Atos::CONFIRMATION_MESSAGE_NAME) + ->setHtmlTemplateFileName('atos-payment-confirmation.html') + ->setTextTemplateFileName('atos-payment-confirmation.txt') + ->setLocale('en_US') + ->setTitle('Atos payment confirmation') + ->setSubject('Payment of order {$order_ref}') + ->setLocale('fr_FR') + ->setTitle('Confirmation de paiement par Atos') + ->setSubject('Confirmation du paiement de votre commande {$order_ref}') + ->save() + ; + } + + $this->replacePath(); + } + + public function update($currentVersion, $newVersion, ConnectionInterface $con = null) + { + // Migrate old configuration + if (null === Atos::getConfigValue('atos_merchantId', null)) { + if (null !== $atosConfigs = ConfigQuery::create()->filterByName('atos_%', Criteria::LIKE)->find()) { + /** @var Config $atosConfig */ + foreach ($atosConfigs as $atosConfig) { + Atos::setConfigValue($atosConfig->getName(), $atosConfig->getValue()); + + $atosConfig->delete($con); + } + } + } + + parent::update($currentVersion, $newVersion, $con); + } + + public function destroy(ConnectionInterface $con = null, $deleteModuleData = false) + { + if ($deleteModuleData) { + $database = new Database($con); + + $database->execute('drop table `atos_currency`'); + + MessageQuery::create()->findOneByName(Atos::CONFIRMATION_MESSAGE_NAME)->delete(); + } + } + + protected function replacePath() + { + $pathfile = $this->getPathfilePath(); + + $pathfileContent = @file_get_contents($pathfile . '.dist'); + + if ($pathfileContent) { + $pathfileContent = str_replace('__PATH__', __DIR__, $pathfileContent); + + if (! file_put_contents($this->getConfigDirectory() . 'pathfile', $pathfileContent)) { + throw new \RuntimeException( + Translator::getInstance()->trans( + 'File %file must be writable, please check Atos/Config directory permissions.', + [ '%file' => 'pathfile' ], + Atos::MODULE_DOMAIN + ) + ); + } + } else { + throw new \RuntimeException( + Translator::getInstance()->trans( + 'Failed to read the %file file. Please check file and directory permissions.', + [ '%file' => $pathfile . '.dist' ], + Atos::MODULE_DOMAIN + ) + ); + } + } + + /** + * @param string $key atos key parameter + * @param string $value parameter value + * @return $this + */ + protected function addParam($key, $value) + { + $this->parameters = sprintf("%s %s=%s", $this->parameters, $key, $value); + + return $this; + } + + protected function getParameters() + { + return trim($this->parameters); + } + + /** + * + * generate a transaction id for atos solution + * + * @return int|mixed + */ + private function generateTransactionID() + { + $transId = Atos::getConfigValue('atos_transactionId', 1); + + $transId = 1 + intval($transId); + + if (strlen($transId) > 6) { + $transId = 1; + } + + Atos::setConfigValue('atos_transactionId', $transId); + + return sprintf("%06d", $transId); + } + + /** + * + * Method used by payment gateway. + * + * If this method return a \Thelia\Core\HttpFoundation\Response instance, this response is send to the + * browser. + * + * In many cases, it's necessary to send a form to the payment gateway. + * On your response you can return this form already completed, ready to be sent + * + * @param \Thelia\Model\Order $order processed order + * @return null|\Thelia\Core\HttpFoundation\Response + */ + public function pay(Order $order) + { + $pathBin = Atos::getBinDirectory() .'request'; + + $atosCurrency = AtosCurrencyQuery::create()->findPk( + $order->getCurrency()->getCode() + ); + + if (null == $atosCurrency) { + throw new \InvalidArgumentException( + sprintf( + "Atos does not supprot this currency : %s", + $order->getCurrency()->getCode() + ) + ); + } + + $amount = $order->getTotalAmount(); + $amount = number_format($amount, $atosCurrency->getDecimals(), '', ''); + + $transactionId = $this->generateTransactionID(); + + $order->setTransactionRef($transactionId)->save(); + + /** @var Router $router */ + $router = $this->getContainer()->get('router.atos'); + + $this + ->addParam('pathfile', Atos::getPathfilePath()) + ->addParam('merchant_id', Atos::getConfigValue('atos_merchantId')) + ->addParam('customer_email', $order->getCustomer()->getEmail()) + ->addParam('currency_code', $atosCurrency->getAtosCode()) + ->addParam('amount', $amount) + ->addParam('language', $order->getLang()->getCode()) + ->addParam('transaction_id', $transactionId) + ->addParam('order_id', $order->getId()) + ->addParam('automatic_response_url', URL::getInstance()->absoluteUrl($router->generate('atos.payment.confirmation'))) + ->addParam('cancel_return_url', URL::getInstance()->absoluteUrl($router->generate('atos.payment.cancel', [ 'orderId' => $order->getId() ]))) + ->addParam('normal_return_url', $this->getPaymentSuccessPageUrl($order->getId())) + ; + + $encrypt = exec(sprintf("%s %s", $pathBin, $this->getParameters())); + + if (! empty($encrypt)) { + $datas = explode('!', $encrypt); + + if ($datas[1] == '' && $datas[2] == '') { + throw new \RuntimeException( + Translator::getInstance()->trans('Request binary not found in "%path"', ['%path' => $pathBin]) + ); + } elseif ($datas[1] != 0) { + throw new \RuntimeException($datas[2]); + } else { + /** @var ParserInterface $parser */ + $parser = $this->getContainer()->get('thelia.parser'); + + $parser->setTemplateDefinition( + $parser->getTemplateHelper()->getActiveFrontTemplate(), + true + ); + + $content = $parser->render('atos/payment.html', [ + 'site_name' => self::getConfigValue('store_name'), + 'form' => $datas[3], + 'order_id' => $order->getId() + ]); + + return Response::create($content); + } + } else { + throw new \RuntimeException( + Translator::getInstance()->trans( + 'Empty response recevied from Atos binary "%path". Please check path and permissions.', + ['%path' => $pathBin], + Atos::MODULE_DOMAIN + ) + ); + // FIXME : show something to the customer + } + } + + /** + * @return boolean true to allow usage of this payment module, false otherwise. + */ + public function isValidPayment() + { + $valid = false; + + // Check config files + $parmcomFile = Atos::getConfigDirectory() . 'parmcom.' . Atos::getConfigValue('atos_merchantId', '0'); + $certifFile = Atos::getConfigDirectory() . 'certif.fr.' . Atos::getConfigValue('atos_merchantId', '0'); + + if (is_readable($parmcomFile) && is_readable($certifFile)) { + $mode = Atos::getConfigValue('atos_mode', false); + + // If we're in test mode, do not display Payzen on the front office, except for allowed IP addresses. + if ('TEST' == $mode) { + $raw_ips = explode("\n", Atos::getConfigValue('atos_allowed_ip_list', '')); + + $allowed_client_ips = array(); + + foreach ($raw_ips as $ip) { + $allowed_client_ips[] = trim($ip); + } + + $client_ip = $this->getRequest()->getClientIp(); + + $valid = in_array($client_ip, $allowed_client_ips); + + } elseif ('PRODUCTION' == $mode) { + $valid = true; + } + + if ($valid) { + // Check if total order amount is in the module's limits + $valid = $this->checkMinMaxAmount(); + } + } else { + Tlog::getInstance()->addWarning( + Translator::getInstance()->trans( + "Atos payment module is nort properly configured. Please check module configuration in your back-office.", + [], + Atos::MODULE_DOMAIN + ) + ); + } + return $valid; + } + + /** + * Check if total order amount is in the module's limits + * + * @return bool true if the current order total is within the min and max limits + */ + protected function checkMinMaxAmount() + { + // Check if total order amount is in the module's limits + $order_total = $this->getCurrentOrderTotalAmount(); + + $min_amount = Atos::getConfigValue('atos_minimum_amount', 0); + $max_amount = Atos::getConfigValue('atos_maximum_amount', 0); + + return + $order_total > 0 + && + ($min_amount <= 0 || $order_total >= $min_amount) && ($max_amount <= 0 || $order_total <= $max_amount); + } + + public static function getBinDirectory() + { + return __DIR__ . DS . 'bin' . DS; + } + + public static function getConfigDirectory() + { + return __DIR__ . DS . 'Config' . DS; + } + + public static function getPathfilePath() + { + return Atos::getConfigDirectory() . 'pathfile'; + } +} diff --git a/local/modules/Atos/Config/certif.fr.dist b/local/modules/Atos/Config/certif.fr.dist new file mode 100644 index 00000000..e69de29b diff --git a/local/modules/Atos/Config/config.xml b/local/modules/Atos/Config/config.xml new file mode 100644 index 00000000..e4f319f2 --- /dev/null +++ b/local/modules/Atos/Config/config.xml @@ -0,0 +1,22 @@ + + + + +
+ + + + + + + + + + + + + + + diff --git a/local/modules/Atos/Config/module.xml b/local/modules/Atos/Config/module.xml new file mode 100644 index 00000000..973befc0 --- /dev/null +++ b/local/modules/Atos/Config/module.xml @@ -0,0 +1,18 @@ + + + Atos\Atos + + Atos-SIPS payment module + + + Module de paiement Atos-SIPS + + 1.2.1 + + Manuel Raynaud, Franck Allimant + manu@thelia.net, franck@cqfdev.fr + + payment + 2.1.0 + prod + diff --git a/local/modules/Atos/Config/parmcom.atos b/local/modules/Atos/Config/parmcom.atos new file mode 100644 index 00000000..5390f444 --- /dev/null +++ b/local/modules/Atos/Config/parmcom.atos @@ -0,0 +1,39 @@ +# couleur du fond d'ecran (blanc) +BGCOLOR!ffffff! + +# Mode d'affichage des blocs de paiment +BLOCK_ALIGN!center! + +# Ordre d'affichage des blocs de paiement +BLOCK_ORDER!1,2,3,4,5,6,7,8! + +# Mode de securite +CONDITION!SSL! + +# flag d'edition des libelles des blocs de paiement +HEADER_FLAG!yes! + +# Code langage de l'acheteur (fr=francais) +LANGUAGE!fr! + +# Logo ATOS paiement +#LOGO!logo.gif! + +# Logo Banque Populaire +#LOGO2!logo.gif! + +# Code pays du commercant +MERCHANT_COUNTRY!fr! + +# Code langage du commercant +MERCHANT_LANGUAGE!fr! + +# Liste des moyens de paiement acceptes +PAYMENT_MEANS!CB,2,VISA,2,MASTERCARD,2! + +# Passage en une seule frame securisee au moment du paiement +TARGET!_top! + +# Couleur du text (noir) +TEXTCOLOR!000000! +# END OF FILE \ No newline at end of file diff --git a/local/modules/Atos/Config/parmcom.dist b/local/modules/Atos/Config/parmcom.dist new file mode 100644 index 00000000..3f01c784 --- /dev/null +++ b/local/modules/Atos/Config/parmcom.dist @@ -0,0 +1,15 @@ +############################################################################### +# +# Fichier des parametres du commercant +# +# Remarque : Ce fichier parametre est sous la responsabilite du +# commercant +# +############################################################################### + +# Logo du commercant (il apparait en entete sur les pages de paiement) +#ADVERT!merchant.gif! + +# END OF FILE + + diff --git a/local/modules/Atos/Config/pathfile b/local/modules/Atos/Config/pathfile new file mode 100644 index 00000000..f798bdc6 --- /dev/null +++ b/local/modules/Atos/Config/pathfile @@ -0,0 +1,31 @@ +######################################################################### +# +# Pathfile +# +# Liste fichiers parametres utilisés par le module de paiement +# +######################################################################### +# ------------------------------------------------------------------------ +# Chemin vers le répertoire des logos depuis le web alias +# ------------------------------------------------------------------------ +# +D_LOGO!/atos/logo/! +# +#------------------------------------------------------------------------ +#------------------------------------------------------------------------ +# +# certificat du commercant +# +F_CERTIFICATE!/home/pala4545/public_html/web/local/modules/Atos/Config/certif! +# +# fichier paramètre commercant +# +F_PARAM!/home/pala4545/public_html/web/local/modules/Atos/Config/parmcom! +# +# fichier des paramètres ATOS +# +F_DEFAULT!/home/pala4545/public_html/web/local/modules/Atos/Config/parmcom.atos! +# +# -------------------------------------------------------------------------- +# end of file +# -------------------------------------------------------------------------- diff --git a/local/modules/Atos/Config/pathfile.dist b/local/modules/Atos/Config/pathfile.dist new file mode 100644 index 00000000..b2107904 --- /dev/null +++ b/local/modules/Atos/Config/pathfile.dist @@ -0,0 +1,31 @@ +######################################################################### +# +# Pathfile +# +# Liste fichiers parametres utilisés par le module de paiement +# +######################################################################### +# ------------------------------------------------------------------------ +# Chemin vers le répertoire des logos depuis le web alias +# ------------------------------------------------------------------------ +# +D_LOGO!/atos/logo/! +# +#------------------------------------------------------------------------ +#------------------------------------------------------------------------ +# +# certificat du commercant +# +F_CERTIFICATE!__PATH__/Config/certif! +# +# fichier paramètre commercant +# +F_PARAM!__PATH__/Config/parmcom! +# +# fichier des paramètres ATOS +# +F_DEFAULT!__PATH__/Config/parmcom.atos! +# +# -------------------------------------------------------------------------- +# end of file +# -------------------------------------------------------------------------- diff --git a/local/modules/Atos/Config/routing.xml b/local/modules/Atos/Config/routing.xml new file mode 100644 index 00000000..d8e55db6 --- /dev/null +++ b/local/modules/Atos/Config/routing.xml @@ -0,0 +1,27 @@ + + + + + + Atos\Controller\ConfigureController::configure + + + + Atos\Controller\ConfigureController::downloadLog + + + + + + Atos\Controller\PaymentController::processAtosRequest + + + + Atos\Controller\PaymentController::processUserCancel + \d+ + + diff --git a/local/modules/Atos/Config/schema.xml b/local/modules/Atos/Config/schema.xml new file mode 100644 index 00000000..21a4c73e --- /dev/null +++ b/local/modules/Atos/Config/schema.xml @@ -0,0 +1,12 @@ + + + + + + + +
+ +
diff --git a/local/modules/Atos/Config/thelia.sql b/local/modules/Atos/Config/thelia.sql new file mode 100644 index 00000000..b80b9ffc --- /dev/null +++ b/local/modules/Atos/Config/thelia.sql @@ -0,0 +1,44 @@ + +# 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; + +-- --------------------------------------------------------------------- +-- atos_currency +-- --------------------------------------------------------------------- + +DROP TABLE IF EXISTS `atos_currency`; + +CREATE TABLE `atos_currency` +( + `code` VARCHAR(128) NOT NULL, + `atos_code` INTEGER, + `decimals` INTEGER, + PRIMARY KEY (`code`) +) ENGINE=InnoDB; + +INSERT INTO `atos_currency`(`code`,`atos_code`,`decimals`) VALUES +('EUR', '978', 2), +('USD', '840', 2), +('CHF', '756', 2), +('GBP', '826', 2), +('CAD', '124', 2), +('JPY', '392', 0), +('MXN', '484', 2), +('TRY', '949', 2), +('AUD', '036', 2), +('NZD', '554', 2), +('NOK', '578', 2), +('BRL', '986', 2), +('ARS', '032', 2), +('KHR', '116', 2), +('TWD', '901', 2), +('SEK', '752', 2), +('DKK', '208', 2), +('KRW', '410', 0), +('SGD', '702', 2), +('XPF', '953', 2), +('XAF', '952', 2); + +# This restores the fkey checks, after having unset them earlier +SET FOREIGN_KEY_CHECKS = 1; diff --git a/local/modules/Atos/Controller/ConfigureController.php b/local/modules/Atos/Controller/ConfigureController.php new file mode 100644 index 00000000..d897dc15 --- /dev/null +++ b/local/modules/Atos/Controller/ConfigureController.php @@ -0,0 +1,166 @@ +, Franck Allimant + */ +class ConfigureController extends BaseAdminController +{ + public function copyDistFile($fileName, $merchantId) + { + $distFile = Atos::getConfigDirectory() . $fileName . '.dist'; + $destFile = Atos::getConfigDirectory() . $fileName . '.' . $merchantId; + + if (! is_readable($destFile)) { + if (!is_file($distFile) && !is_readable($distFile)) { + throw new FileException(sprintf("Can't read file '%s', please check file permissions", $distFile)); + } + + // Copy the dist file in place + $fs = new Filesystem(); + + $fs->copy($distFile, $destFile); + } + + return $destFile; + } + + public function checkExecutable($fileName) + { + $binFile = Atos::getBinDirectory() . $fileName; + + if (! is_executable($binFile)) { + throw new FileException( + $this->getTranslator()->trans( + "The '%file' should be executable. Please check file permission", + [ '%file' => $binFile ], + Atos::MODULE_DOMAIN + ) + ); + } + } + + public function downloadLog() + { + if (null !== $response = $this->checkAuth(AdminResources::MODULE, 'atos', AccessManager::UPDATE)) { + return $response; + } + + $logFilePath = sprintf(THELIA_ROOT."log".DS."%s.log", Atos::MODULE_DOMAIN); + + return Response::create( + @file_get_contents($logFilePath), + 200, + array( + 'Content-type' => "text/plain", + 'Content-Disposition' => sprintf('Attachment;filename=atos-log.txt') + ) + ); + + } + + public function configure() + { + if (null !== $response = $this->checkAuth(AdminResources::MODULE, 'atos', AccessManager::UPDATE)) { + return $response; + } + + $configurationForm = $this->createForm('atos_configuration'); + $message = null; + + try { + $form = $this->validateForm($configurationForm); + + // Get the form field values + $data = $form->getData(); + + foreach ($data as $name => $value) { + if (is_array($value)) { + $value = implode(';', $value); + } + + Atos::setConfigValue($name, $value); + } + + $merchantId = $data['atos_merchantId']; + + $this->checkExecutable('request'); + $this->checkExecutable('response'); + + $this->copyDistFile('parmcom', $merchantId); + $certificateFile = $this->copyDistFile('certif.fr', $merchantId); + + // Write certificate + if (! @file_put_contents($certificateFile, $data['atos_certificate'])) { + throw new FileException( + $this->getTranslator()->trans( + "Failed to write certificate data in file '%file'. Please check file permission", + [ '%file' => $certificateFile ], + Atos::MODULE_DOMAIN + ) + ); + } + + // Log configuration modification + $this->adminLogAppend( + "atos.configuration.message", + AccessManager::UPDATE, + "Atos configuration updated" + ); + + // Redirect to the success URL, + if ($this->getRequest()->get('save_mode') == 'stay') { + // If we have to stay on the same page, redisplay the configuration page/ + $url = '/admin/module/Atos'; + } else { + // If we have to close the page, go back to the module back-office page. + $url = '/admin/modules'; + } + + return $this->generateRedirect(URL::getInstance()->absoluteUrl($url)); + } catch (FormValidationException $ex) { + $message = $this->createStandardFormValidationErrorMessage($ex); + } catch (\Exception $ex) { + $message = $ex->getMessage(); + } + + $this->setupFormErrorContext( + $this->getTranslator()->trans("Atos configuration", [], Atos::MODULE_DOMAIN), + $message, + $configurationForm, + $ex + ); + + // Before 2.2, the errored form is not stored in session + if (Version::test(Thelia::THELIA_VERSION, '2.2', false, "<")) { + return $this->render('module-configure', [ 'module_code' => 'Atos' ]); + } else { + return $this->generateRedirect(URL::getInstance()->absoluteUrl('/admin/module/Atos')); + } + } +} diff --git a/local/modules/Atos/Controller/PaymentController.php b/local/modules/Atos/Controller/PaymentController.php new file mode 100644 index 00000000..a92b70c7 --- /dev/null +++ b/local/modules/Atos/Controller/PaymentController.php @@ -0,0 +1,252 @@ +, Franck Allimant + */ +class PaymentController extends BasePaymentModuleController +{ + + public function processAtosRequest() + { + $this->getLog()->addInfo( + $this->getTranslator()->trans( + "Atos-SIPS platform request received.", + [], + Atos::MODULE_DOMAIN + ) + ); + + $binResponse = Atos::getBinDirectory() . 'response'; + + if (! empty($_POST['DATA'])) { + $data = escapeshellcmd($_POST['DATA']); + + $pathfile = Atos::getPathfilePath(); + + $resultRaw = exec(sprintf("%s message=%s pathfile=%s", $binResponse, $data, $pathfile)); + + if (!empty($resultRaw)) { + $result = explode('!', $resultRaw); + + $result = $this->parseResult($result); + + $this->getLog()->addInfo( + $this->getTranslator()->trans( + 'Response parameters : %resp', + ['%resp' => print_r($result, true)], + Atos::MODULE_DOMAIN + ) + ); + + if ($result['code'] == '' && $result['error'] == '') { + $this->getLog()->addError( + $this->getTranslator()->trans( + 'Response request not found in %response', + ['%response' => $binResponse], + Atos::MODULE_DOMAIN + ) + ); + } elseif (intval($result['code']) != 0) { + $this->getLog()->addError( + $this->getTranslator()->trans( + 'Error %code while processing response, with message %message', + ['%code' => intval($result['code']), '%message' => $result['error']], + Atos::MODULE_DOMAIN + ) + ); + } elseif ($result['response_code'] == '00') { + $atos = new Atos(); + + $order = OrderQuery::create() + ->filterByTransactionRef($result['transaction_id']) + ->filterByPaymentModuleId($atos->getModuleModel()->getId()) + ->findOne(); + + if ($order) { + $this->confirmPayment($order->getId()); + + $this->getLog()->addInfo( + $this->getTranslator()->trans( + "Order ID %id is confirmed.", + ['%id' => $order->getId()], + Atos::MODULE_DOMAIN + ) + ); + } else { + $this->getLog()->addError( + $this->getTranslator()->trans( + 'Cannot find an order for transaction ID "%trans"', + ['%trans' => $result['transaction_id']], + Atos::MODULE_DOMAIN + ) + ); + } + } else { + $this->getLog()->addError( + $this->getTranslator()->trans( + 'Cannot validate order. Response code is %resp', + ['%resp' => $result['response_code']], + Atos::MODULE_DOMAIN + ) + ); + } + } else { + $this->getLog()->addError( + $this->getTranslator()->trans( + 'Got empty response from executable %binary, check path and permissions', + ['%binary' => $binResponse], + Atos::MODULE_DOMAIN + ) + ); + } + } else { + $this->getLog()->addError( + $this->getTranslator()->trans( + 'Request does not contains any data', + [], + Atos::MODULE_DOMAIN + ) + ); + } + + $this->getLog()->info( + $this->getTranslator()->trans( + "Atos platform request processing terminated.", + [], + Atos::MODULE_DOMAIN + ) + ); + + return Response::create(); + } + + /* + * @param $orderId int the order ID + * @return \Thelia\Core\HttpFoundation\Response + */ + public function processUserCancel($orderId) + { + $this->getLog()->addInfo( + $this->getTranslator()->trans( + 'User canceled payment of order %id', + ['%id' => $orderId], + Atos::MODULE_DOMAIN + ) + ); + + try { + if (null !== $order = OrderQuery::create()->findPk($orderId)) { + $currentCustomerId = $this->getSecurityContext()->getCustomerUser()->getId(); + $orderCustomerId = $order->getCustomerId(); + + if ($orderCustomerId != $currentCustomerId) { + throw new TheliaProcessException( + sprintf( + "User ID %d is trying to cancel order ID %d ordered by user ID %d", + $currentCustomerId, + $orderId, + $orderCustomerId + ) + ); + } + + $event = new OrderEvent($order); + $event->setStatus(OrderStatusQuery::getCancelledStatus()->getId()); + $this->dispatch(TheliaEvents::ORDER_UPDATE_STATUS, $event); + } + } catch (\Exception $ex) { + $this->getLog()->addError("Error occurred while canceling order ID $orderId: " . $ex->getMessage()); + } + + $this->redirectToFailurePage( + $orderId, + $this->getTranslator()->trans('you cancel the payment', [], Atos::MODULE_DOMAIN) + ); + } + + protected function parseResult($result) + { + return [ + 'code' => $result[1], + 'error' => $result[2], + 'merchant_id' => $result[3], + 'merchant_country' => $result[4], + 'amount' => $result[5], + 'transaction_id' => $result[6], + 'payment_means' => $result[7], + 'transmission_date' => $result[8], + 'payment_time' => $result[9], + 'payment_date' => $result[10], + 'response_code' => $result[11], + 'payment_certificate' => $result[12], + 'authorisation_id' => $result[13], + 'currency_code' => $result[14], + 'card_number' => $result[15], + 'cvv_flag' => $result[16], + 'cvv_response_code' => $result[17], + 'bank_response_code' => $result[18], + 'complementary_code' => $result[19], + 'complementary_info' => $result[20], + 'return_context' => $result[21], + 'caddie' => $result[22], + 'receipt_complement' => $result[23], + 'merchant_language' => $result[24], + 'language' => $result[25], + 'customer_id' => $result[26], + 'order_id' => $result[27], + 'customer_email' => $result[28], + 'customer_ip_address' => $result[29], + 'capture_day' => $result[30], + 'capture_mode' => $result[31], + 'data' => $result[32] + ]; + } + + public function displayLogo($image) + { + if (file_exists(__DIR__ . DS . '..' . DS . 'logo' . DS . $image)) { + $sourceImage = file_get_contents(__DIR__ . DS . '..' . DS . 'logo' . DS . $image); + + return Response::create($sourceImage, 200, [ + 'Content-Type' => 'image/gif', + 'Content-Length' => strlen($sourceImage) + ]); + } else { + throw new NotFoundHttpException(); + } + } + /** + * Return a module identifier used to calculate the name of the log file, + * and in the log messages. + * + * @return string the module code + */ + protected function getModuleCode() + { + return 'Atos'; + } +} diff --git a/local/modules/Atos/EventListeners/SendConfirmationEmail.php b/local/modules/Atos/EventListeners/SendConfirmationEmail.php new file mode 100644 index 00000000..32412459 --- /dev/null +++ b/local/modules/Atos/EventListeners/SendConfirmationEmail.php @@ -0,0 +1,94 @@ + + * @author franck allimant + */ +class SendConfirmationEmail implements EventSubscriberInterface +{ + /** + * @var MailerFactory + */ + protected $mailer; + + public function __construct(MailerFactory $mailer) + { + $this->mailer = $mailer; + } + + /** + * @param OrderEvent $event + * + * @throws \Exception if the message cannot be loaded. + */ + public function sendConfirmationEmail(OrderEvent $event) + { + if (Atos::getConfigValue('send_confirmation_message_only_if_paid')) { + // We send the order confirmation email only if the order is paid + $order = $event->getOrder(); + + if (! $order->isPaid() && $order->getPaymentModuleId() == Atos::getModuleId()) { + $event->stopPropagation(); + } + } + } + + /* + * @params OrderEvent $order + * Checks if order payment module is paypal and if order new status is paid, send an email to the customer. + */ + + public function updateStatus(OrderEvent $event) + { + $order = $event->getOrder(); + + if ($order->isPaid() && $order->getPaymentModuleId() == Atos::getModuleId()) { + if (Atos::getConfigValue('send_payment_confirmation_message')) { + $this->mailer->sendEmailToCustomer( + Atos::CONFIRMATION_MESSAGE_NAME, + $order->getCustomer(), + [ + 'order_id' => $order->getId(), + 'order_ref' => $order->getRef() + ] + ); + } + + // Send confirmation email if required. + if (Atos::getConfigValue('send_confirmation_message_only_if_paid')) { + $event->getDispatcher()->dispatch(TheliaEvents::ORDER_SEND_CONFIRMATION_EMAIL, $event); + } + + Tlog::getInstance()->debug("Confirmation email sent to customer " . $order->getCustomer()->getEmail()); + } + } + + public static function getSubscribedEvents() + { + return array( + TheliaEvents::ORDER_UPDATE_STATUS => array("updateStatus", 128), + TheliaEvents::ORDER_SEND_CONFIRMATION_EMAIL => array("sendConfirmationEmail", 129) + ); + } +} diff --git a/local/modules/Atos/Form/ConfigForm.php b/local/modules/Atos/Form/ConfigForm.php new file mode 100644 index 00000000..c27cd18a --- /dev/null +++ b/local/modules/Atos/Form/ConfigForm.php @@ -0,0 +1,249 @@ + + */ +class ConfigForm extends BaseForm +{ + protected function buildForm() + { + // If the Multi plugin is not enabled, all multi_fields are hidden + /** @var Module $multiModule */ + $multiEnabled = (null !== $multiModule = ModuleQuery::create()->findOneByCode('AtosNx')) && $multiModule->getActivate() != 0; + + $translator = Translator::getInstance(); + + $this->formBuilder + ->add( + 'atos_merchantId', + 'text', + [ + 'constraints' => [ + new NotBlank(), + ], + 'label' => $translator->trans('Shop Merchant ID', [], Atos::MODULE_DOMAIN), + 'label_attr' => [ + 'for' => 'merchant_id', + ] + ] + ) + ->add( + 'atos_mode', + 'choice', + [ + 'constraints' => [ + new NotBlank() + ], + 'choices' => [ + 'TEST' => $translator->trans('Test', [], Atos::MODULE_DOMAIN), + 'PRODUCTION' => $translator->trans('Production', [], Atos::MODULE_DOMAIN), + ], + 'label' => $translator->trans('Operation Mode', [], Atos::MODULE_DOMAIN), + 'label_attr' => [ + 'for' => 'mode', + 'help' => $translator->trans('Test or production mode', [], Atos::MODULE_DOMAIN) + ] + ] + ) + ->add( + 'atos_allowed_ip_list', + 'textarea', + [ + 'required' => false, + 'label' => $translator->trans('Allowed IPs in test mode', [], Atos::MODULE_DOMAIN), + 'label_attr' => [ + 'for' => 'platform_url', + 'help' => $translator->trans( + 'List of IP addresses allowed to use this payment on the front-office when in test mode (your current IP is %ip). One address per line', + [ '%ip' => $this->getRequest()->getClientIp() ], + Atos::MODULE_DOMAIN + ) + ], + 'attr' => [ + 'rows' => 3 + ] + ] + ) + ->add( + 'atos_minimum_amount', + 'text', + [ + 'constraints' => [ + new NotBlank(), + new GreaterThanOrEqual(['value' => 0 ]) + ], + 'label' => $translator->trans('Minimum order total', [], Atos::MODULE_DOMAIN), + 'label_attr' => [ + 'for' => 'minimum_amount', + 'help' => $translator->trans( + 'Minimum order total in the default currency for which this payment method is available. Enter 0 for no minimum', + [], + Atos::MODULE_DOMAIN + ) + ] + ] + ) + ->add( + 'atos_maximum_amount', + 'text', + [ + 'constraints' => [ + new NotBlank(), + new GreaterThanOrEqual([ 'value' => 0 ]) + ], + 'label' => $translator->trans('Maximum order total', [], Atos::MODULE_DOMAIN), + 'label_attr' => [ + 'for' => 'maximum_amount', + 'help' => $translator->trans( + 'Maximum order total in the default currency for which this payment method is available. Enter 0 for no maximum', + [], + Atos::MODULE_DOMAIN + ) + ] + ] + ) + ->add( + 'atos_certificate', + 'textarea', + [ + 'required' => false, + 'label' => $translator->trans('ATOS certificate content', [], Atos::MODULE_DOMAIN), + 'label_attr' => [ + 'for' => 'platform_url', + 'help' => $translator->trans( + 'Please paste here the certificate downloaded from the Atos SIPS platform', + [], + Atos::MODULE_DOMAIN + ), + ], + 'attr' => [ + 'rows' => 10 + ] + ] + ) + ->add( + 'send_confirmation_message_only_if_paid', + 'checkbox', + [ + 'value' => 1, + 'required' => false, + 'label' => $this->translator->trans('Send order confirmation on payment success', [], Atos::MODULE_DOMAIN), + 'label_attr' => [ + 'help' => $this->translator->trans( + 'If checked, the order confirmation message is sent to the customer only when the payment is successful. The order notification is always sent to the shop administrator', + [], + Atos::MODULE_DOMAIN + ) + ] + ] + ) + ->add( + 'send_payment_confirmation_message', + 'checkbox', + [ + 'value' => 1, + 'required' => false, + 'label' => $this->translator->trans('Send a payment confirmation e-mail', [], Atos::MODULE_DOMAIN), + 'label_attr' => [ + 'help' => $this->translator->trans( + 'If checked, a payment confirmation e-mail is sent to the customer.', + [], + Atos::MODULE_DOMAIN + ) + ] + ] + ) + + // -- Multiple times payement parameters, hidden id the AtosNx module is not activated. + ->add( + 'nx_nb_installments', + $multiEnabled ? 'text' : 'hidden', + [ + 'constraints' => [ + new NotBlank(), + new GreaterThanOrEqual(['value' => 1 ]) + ], + 'required' => $multiEnabled, + 'label' => $translator->trans('Number of installments', [], Atos::MODULE_DOMAIN), + 'label_attr' => [ + 'for' => 'nx_nb_installments', + 'help' => $translator->trans( + 'Number of installements. Should be more than one', + [], + Atos::MODULE_DOMAIN + ) + ] + ] + ) + ->add( + 'nx_minimum_amount', + $multiEnabled ? 'text' : 'hidden', + [ + 'constraints' => [ + new NotBlank(), + new GreaterThanOrEqual(['value' => 0 ]) + ], + 'required' => $multiEnabled, + 'label' => $translator->trans('Minimum order total', [], Atos::MODULE_DOMAIN), + 'label_attr' => [ + 'for' => 'nx_minimum_amount', + 'help' => $translator->trans( + 'Minimum order total in the default currency for which the multiple times payment method is available. Enter 0 for no minimum', + [], + Atos::MODULE_DOMAIN + ) + ] + ] + ) + ->add( + 'nx_maximum_amount', + $multiEnabled ? 'text' : 'hidden', + [ + 'constraints' => [ + new NotBlank(), + new GreaterThanOrEqual([ 'value' => 0 ]) + ], + 'required' => $multiEnabled, + 'label' => $translator->trans('Maximum order total', [], Atos::MODULE_DOMAIN), + 'label_attr' => [ + 'for' => 'nx_maximum_amount', + 'help' => $translator->trans( + 'Maximum order total in the default currency for which the multiple times payment method is available. Enter 0 for no maximum', + [], + Atos::MODULE_DOMAIN + ) + ] + ] + ) + ; + } + + /** + * @return string the name of you form. This name must be unique + */ + public function getName() + { + return 'atos_config'; + } +} diff --git a/local/modules/Atos/Hook/HookManager.php b/local/modules/Atos/Hook/HookManager.php new file mode 100644 index 00000000..1bd85e04 --- /dev/null +++ b/local/modules/Atos/Hook/HookManager.php @@ -0,0 +1,93 @@ +. */ +/* */ +/*************************************************************************************/ +/** + * Created by Franck Allimant, CQFDev + * Date: 11/01/2016 11:57 + */ +namespace Atos\Hook; + +use Atos\Atos; +use Thelia\Core\Event\Hook\HookRenderEvent; +use Thelia\Core\Hook\BaseHook; +use Thelia\Model\ModuleConfig; +use Thelia\Model\ModuleConfigQuery; + +class HookManager extends BaseHook +{ + const MAX_TRACE_SIZE_IN_BYTES = 40000; + + public function onModuleConfigure(HookRenderEvent $event) + { + $logFilePath = sprintf(THELIA_ROOT."log".DS."%s.log", Atos::MODULE_DOMAIN); + + if (false !== $fh = @fopen($logFilePath, "r")) { + if (filesize($logFilePath) > self::MAX_TRACE_SIZE_IN_BYTES) { + fseek($fh, -self::MAX_TRACE_SIZE_IN_BYTES, SEEK_END); + $truncated = true; + } else { + $truncated = false; + } + + $traces = implode( + '
', + array_reverse( + explode( + "\n", + fread($fh, self::MAX_TRACE_SIZE_IN_BYTES) + ) + ) + ); + + fclose($fh); + + if (empty($traces)) { + $traces = $this->translator->trans("The log file is currently empty.", [], Atos::MODULE_DOMAIN); + } elseif ($truncated) { + $traces = $this->translator->trans( + "(Previous log is in %file file.)
", + ['%file' => sprintf("log" . DS . "%s.log", Atos::MODULE_DOMAIN)], + Atos::MODULE_DOMAIN + ) . $traces; + } + } else { + $traces = $this->translator->trans( + "The log file '%log' does not exists yet.", + ['%log' => $logFilePath], + Atos::MODULE_DOMAIN + ); + } + + $vars = [ 'trace_content' => $traces ]; + + if (null !== $params = ModuleConfigQuery::create()->findByModuleId(Atos::getModuleId())) { + /** @var ModuleConfig $param */ + foreach ($params as $param) { + $vars[ $param->getName() ] = $param->getValue(); + } + } + + $event->add( + $this->render('atos/module-configuration.html', $vars) + ); + } +} diff --git a/local/modules/Atos/I18n/backOffice/default/en_US.php b/local/modules/Atos/I18n/backOffice/default/en_US.php new file mode 100644 index 00000000..e9673d2c --- /dev/null +++ b/local/modules/Atos/I18n/backOffice/default/en_US.php @@ -0,0 +1,13 @@ + 'Atos Configuration', + 'Atos-SIPS Platform configuration' => 'Atos-SIPS Platform configuration', + 'Atos-SIPS call log to callback URL' => 'Atos-SIPS call log to callback URL', + 'Callback URL' => 'Callback URL', + 'Download full log' => 'Download full log', + 'Operation mode' => 'Operation mode', + 'Payment configuration' => 'Payment configuration', + 'This is the callback URL, that will be called by Atos SIPS after customer payment. Be sure that this URL is reachable by remote mechines' => 'This is the callback URL, that will be called by Atos SIPS after customer payment. Be sure that this URL is reachable by remote machines', + 'You can edit the payment confirmation email sent to the customer after a successful payment.' => 'You can edit the payment confirmation email sent to the customer after a successful payment.', +); diff --git a/local/modules/Atos/I18n/backOffice/default/fr_FR.php b/local/modules/Atos/I18n/backOffice/default/fr_FR.php new file mode 100644 index 00000000..aabad192 --- /dev/null +++ b/local/modules/Atos/I18n/backOffice/default/fr_FR.php @@ -0,0 +1,13 @@ + 'Atos Configuration', + 'Atos-SIPS Platform configuration' => 'Configuration de la plate-forme SIPS-Atos', + 'Atos-SIPS call log to callback URL' => 'Atos-SIPS callback URL log', + 'Callback URL' => 'URL de retour', + 'Download full log' => 'Télécharger l\'historique complet', + 'Operation mode' => 'Mode de fonctionnement', + 'Payment configuration' => 'Configuration du paiement', + 'This is the callback URL, that will be called by Atos SIPS after customer payment. Be sure that this URL is reachable by remote mechines' => 'Il s\'agit de l\'URL de retour appelée par Atos SIPS après le paiement de vos clients. Assurez-vous que cette URL est joignable par des machines distantes.', + 'You can edit the payment confirmation email sent to the customer after a successful payment.' => 'Vous pouvez modifier le mail de confirmation de paiement envoyé au client.', +); diff --git a/local/modules/Atos/I18n/email/default/en_US.php b/local/modules/Atos/I18n/email/default/en_US.php new file mode 100644 index 00000000..04833e13 --- /dev/null +++ b/local/modules/Atos/I18n/email/default/en_US.php @@ -0,0 +1,12 @@ + 'Dear customer', + 'Payment of your order %ref' => 'Payment of your order %ref', + 'Thank you again for your purchase.' => 'Thank you again for your purchase.', + 'The %store_name team.' => 'The %store_name team.', + 'The payment of your order %ref with SIPS Atos is confirmed' => 'The payment of your order %ref with SIPS Atos is confirmed', + 'This is a confirmation of the payment of your order %ref with SIPS-Atos on our shop.' => 'This is a confirmation of the payment of your order %ref with SIPS-Atos on our shop.', + 'View this order in your account at %shop_name' => 'View this order in your account at %shop_name', + 'Your invoice is now available in your customer account at %url.' => 'Your invoice is now available in your customer account at %url.', +); diff --git a/local/modules/Atos/I18n/email/default/fr_FR.php b/local/modules/Atos/I18n/email/default/fr_FR.php new file mode 100644 index 00000000..a41a15c3 --- /dev/null +++ b/local/modules/Atos/I18n/email/default/fr_FR.php @@ -0,0 +1,12 @@ + 'Cher client', + 'Payment of your order %ref' => 'Paiement de votre commande %ref', + 'Thank you again for your purchase.' => 'Merci encore pour votre commande.', + 'The %store_name team.' => 'L\'équipe %store_name', + 'The payment of your order %ref with SIPS Atos is confirmed' => 'Le paiement de votre commande %ref avec SIPS Atos est confirmé.', + 'This is a confirmation of the payment of your order %ref with SIPS-Atos on our shop.' => 'Ce message confirme le paiement de votre commande %ref avec SIPS Atos dans notre boutique.', + 'View this order in your account at %shop_name' => 'Les détails de cette commande sont disponibles dans votre compte client sur %shop_name', + 'Your invoice is now available in your customer account at %url.' => 'Les détails de cette commande sont disponibles dans votre compte client sur %url', +); diff --git a/local/modules/Atos/I18n/en_US.php b/local/modules/Atos/I18n/en_US.php new file mode 100644 index 00000000..f5cd4492 --- /dev/null +++ b/local/modules/Atos/I18n/en_US.php @@ -0,0 +1,44 @@ + '(Previous log is in %file file.)\n', + 'ATOS certificate content' => 'ATOS certificate content', + 'Allowed IPs in test mode' => 'Allowed IPs in test mode', + 'Atos configuration' => 'Atos configuration', + 'Atos payment module is nort properly configured. Please check module configuration in your back-office.' => 'Atos payment module is nort properly configured. Please check module configuration in your back-office.', + 'Atos platform request processing terminated.' => 'Atos platform request processing terminated.', + 'Atos-SIPS platform request received.' => 'Atos-SIPS platform request received.', + 'Cannot find an order for transaction ID "%trans"' => 'Cannot find an order for transaction ID "%trans"', + 'Cannot validate order. Response code is %resp' => 'Cannot validate order. Response code is %resp', + 'Empty response recevied from Atos binary "%path". Please check path and permissions.' => 'Empty response recevied from Atos binary "%path". Please check path and permissions.', + 'Error %code while processing response, with message %message' => 'Error %code while processing response, with message %message', + 'Failed to read the %file file. Please check file and directory permissions.' => 'Failed to read the %file file. Please check file and directory permissions.', + 'Failed to write certificate data in file \'%file\'. Please check file permission' => 'Failed to write certificate data in file \'%file\'. Please check file permission', + 'File %file must be writable, please check Atos/Config directory permissions.' => 'File %file must be writable, please check Atos/Config directory permissions.', + 'Got empty response from executable %binary, check path and permissions' => 'Got empty response from executable %binary, check path and permissions', + 'If checked, a payment confirmation e-mail is sent to the customer.' => 'If checked, a payment confirmation e-mail is sent to the customer.', + 'If checked, the order confirmation message is sent to the customer only when the payment is successful. The order notification is always sent to the shop administrator' => 'If checked, the order confirmation message is sent to the customer only when the payment is successful. The order notification is always sent to the shop administrator', + 'List of IP addresses allowed to use this payment on the front-office when in test mode (your current IP is %ip). One address per line' => 'List of IP addresses allowed to use this payment on the front-office when in test mode (your current IP is %ip). One address per line', + 'Maximum order total' => 'Maximum order total', + 'Maximum order total in the default currency for which this payment method is available. Enter 0 for no maximum' => 'Maximum order total in the default currency for which this payment method is available. Enter 0 for no maximum', + 'Minimum order total' => 'Minimum order total', + 'Minimum order total in the default currency for which this payment method is available. Enter 0 for no minimum' => 'Minimum order total in the default currency for which this payment method is available. Enter 0 for no minimum', + 'Operation Mode' => 'Operation Mode', + 'Order ID %id is confirmed.' => 'Order ID %id is confirmed.', + 'Please paste here the certificate downloaded from the Atos SIPS platform' => 'Please paste here the certificate downloaded from the Atos SIPS platform', + 'Production' => 'Production', + 'Request binary not found in "%path"' => 'Request binary not found in "%path"', + 'Request does not contains any data' => 'Request does not contains any data', + 'Response parameters : %resp' => 'Response parameters : %resp', + 'Response request not found in %response' => 'Response request not found in %response', + 'Send a payment confirmation e-mail' => 'Send a payment confirmation e-mail', + 'Send order confirmation on payment success' => 'Send order confirmation on payment success', + 'Shop Merchant ID' => 'Shop Merchant ID', + 'Test' => 'Test', + 'Test or production mode' => 'Test or production mode', + 'The \'%file\' should be executable. Please check file permission' => 'The \'%file\' should be executable. Please check file permission', + 'The log file \'%log\' does not exists yet.' => 'The log file \'%log\' does not exists yet.', + 'The log file is currently empty.' => 'The log file is currently empty.', + 'User canceled payment of order %id' => 'User canceled payment of order ID %id', + 'you cancel the payment' => 'you cancel the payment', +); diff --git a/local/modules/Atos/I18n/fr_FR.php b/local/modules/Atos/I18n/fr_FR.php new file mode 100644 index 00000000..f7200749 --- /dev/null +++ b/local/modules/Atos/I18n/fr_FR.php @@ -0,0 +1,44 @@ + '(L\'historique précédent se trouve dans n %file file.)\n', + 'ATOS certificate content' => 'Certificat ATOS', + 'Allowed IPs in test mode' => 'Adresse IP autorisées en phase de test', + 'Atos configuration' => 'Configuration ATOS-SIPS', + 'Atos payment module is nort properly configured. Please check module configuration in your back-office.' => 'Le module de paiement Atos n\'est pas correctement configuré. Merci de vérifier la configuration dans votre back-office.', + 'Atos platform request processing terminated.' => 'Traitemenr de la requête ATOS terminé.', + 'Atos-SIPS platform request received.' => 'Réception d\'une requête ATOS', + 'Cannot find an order for transaction ID "%trans"' => 'Aucune commande ne correspond à l\'ID de transaction "%trans"', + 'Cannot validate order. Response code is %resp' => 'La commande ne peut être validée. Le code de réponse est %resp', + 'Empty response recevied from Atos binary "%path". Please check path and permissions.' => 'Le binaire Atos %path a retourné une réponse vide. Vérifiez que ce fichier est exécutable.', + 'Error %code while processing response, with message %message' => 'Erreur %code lors du traitement de la réponse, avec le message %message', + 'Failed to read the %file file. Please check file and directory permissions.' => 'Impossible de lire le fichier %file. Vérifier que le fichier existe et est est accessible en lecture.', + 'Failed to write certificate data in file \'%file\'. Please check file permission' => 'L\'écriture des données du certificat dans le fichier %file a échoué. Vérifier que le fichier est accessible en écriture.', + 'File %file must be writable, please check Atos/Config directory permissions.' => 'Le fichier %file doit être accessible en écriture, merci de vérifier qu\'il possède les permissions nécessaires.', + 'Got empty response from executable %binary, check path and permissions' => 'L\'executable %binary a retourné une réponse vide. Vérifier les permissions du fichier.', + 'If checked, a payment confirmation e-mail is sent to the customer.' => 'Si cette case est cochée, un mail de confirmation de paiement sera envoyé au client.', + 'If checked, the order confirmation message is sent to the customer only when the payment is successful. The order notification is always sent to the shop administrator' => 'Si cette case est cochée, le mail de confirmation de commande sera envoyé au client seulement si son paiement est validé.', + 'List of IP addresses allowed to use this payment on the front-office when in test mode (your current IP is %ip). One address per line' => 'Liste des adresse IP qui pourront choisir ce module de paiement en front-office pendant la phase de test (votre IP est %ip). Une adresse par ligne.', + 'Maximum order total' => 'Montant de commande maximum', + 'Maximum order total in the default currency for which this payment method is available. Enter 0 for no maximum' => 'Montant maximum dans la devise par défaut pour proposer ce moyen de paiement. Laisser 0 pour ne pas fixer de maximum.', + 'Minimum order total' => 'Montant minimum de commande', + 'Minimum order total in the default currency for which this payment method is available. Enter 0 for no minimum' => 'Montant minimum dans la devise par défaut pour proposer ce moyen de paiement. Laisser 0 pour ne pas fixer de minimum.', + 'Operation Mode' => 'Mode de fonctionnement', + 'Order ID %id is confirmed.' => 'La commande ID %id est confirmée', + 'Please paste here the certificate downloaded from the Atos SIPS platform' => 'Vous pouvez coller ici le texte du certificat téléhergé depuis la plate-forme ATOS', + 'Production' => 'Production', + 'Request binary not found in "%path"' => 'le binaire request n\'est pas trouvé dans "%path"', + 'Request does not contains any data' => 'La requête ne contient aucune donnée', + 'Response parameters : %resp' => 'Paramètres de la réponse : %resp', + 'Response request not found in %response' => 'La réponse ATOS n\'a pas été trouvée dans %response', + 'Send a payment confirmation e-mail' => 'Envoyer une confirmation de paiement', + 'Send order confirmation on payment success' => 'Confirmation de commande si le paiement réussit ', + 'Shop Merchant ID' => 'Identifiant Marchand', + 'Test' => 'Test', + 'Test or production mode' => 'Test ou production', + 'The \'%file\' should be executable. Please check file permission' => 'Le fichier %file doit être exécutable. Vérifier que ce fichier a les permission nécessaires/.', + 'The log file \'%log\' does not exists yet.' => 'Le fichier de log %log n\'existe pas encore.', + 'The log file is currently empty.' => 'Le fichier de log est vide', + 'User canceled payment of order %id' => 'Le client a annulé le paiement de la commande ID %id', + 'you cancel the payment' => 'Vous avez annulé le paiement', +); diff --git a/local/modules/Atos/LICENSE.txt b/local/modules/Atos/LICENSE.txt new file mode 100644 index 00000000..65c5ca88 --- /dev/null +++ b/local/modules/Atos/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/Atos/Model/AtosCurrency.php b/local/modules/Atos/Model/AtosCurrency.php new file mode 100644 index 00000000..699975e8 --- /dev/null +++ b/local/modules/Atos/Model/AtosCurrency.php @@ -0,0 +1,10 @@ +modifiedColumns; + } + + /** + * Has specified column been modified? + * + * @param string $col column fully qualified name (TableMap::TYPE_COLNAME), e.g. Book::AUTHOR_ID + * @return boolean True if $col has been modified. + */ + public function isColumnModified($col) + { + return $this->modifiedColumns && isset($this->modifiedColumns[$col]); + } + + /** + * Get the columns that have been modified in this object. + * @return array A unique list of the modified column names for this object. + */ + public function getModifiedColumns() + { + return $this->modifiedColumns ? array_keys($this->modifiedColumns) : []; + } + + /** + * Returns whether the object has ever been saved. This will + * be false, if the object was retrieved from storage or was created + * and then saved. + * + * @return boolean true, if the object has never been persisted. + */ + public function isNew() + { + return $this->new; + } + + /** + * Setter for the isNew attribute. This method will be called + * by Propel-generated children and objects. + * + * @param boolean $b the state of the object. + */ + public function setNew($b) + { + $this->new = (Boolean) $b; + } + + /** + * Whether this object has been deleted. + * @return boolean The deleted state of this object. + */ + public function isDeleted() + { + return $this->deleted; + } + + /** + * Specify whether this object has been deleted. + * @param boolean $b The deleted state of this object. + * @return void + */ + public function setDeleted($b) + { + $this->deleted = (Boolean) $b; + } + + /** + * Sets the modified state for the object to be false. + * @param string $col If supplied, only the specified column is reset. + * @return void + */ + public function resetModified($col = null) + { + if (null !== $col) { + if (isset($this->modifiedColumns[$col])) { + unset($this->modifiedColumns[$col]); + } + } else { + $this->modifiedColumns = array(); + } + } + + /** + * Compares this with another AtosCurrency instance. If + * obj is an instance of AtosCurrency, delegates to + * equals(AtosCurrency). Otherwise, returns false. + * + * @param mixed $obj The object to compare to. + * @return boolean Whether equal to the object specified. + */ + public function equals($obj) + { + $thisclazz = get_class($this); + if (!is_object($obj) || !($obj instanceof $thisclazz)) { + return false; + } + + if ($this === $obj) { + return true; + } + + if (null === $this->getPrimaryKey() + || null === $obj->getPrimaryKey()) { + return false; + } + + return $this->getPrimaryKey() === $obj->getPrimaryKey(); + } + + /** + * If the primary key is not null, return the hashcode of the + * primary key. Otherwise, return the hash code of the object. + * + * @return int Hashcode + */ + public function hashCode() + { + if (null !== $this->getPrimaryKey()) { + return crc32(serialize($this->getPrimaryKey())); + } + + return crc32(serialize(clone $this)); + } + + /** + * Get the associative array of the virtual columns in this object + * + * @return array + */ + public function getVirtualColumns() + { + return $this->virtualColumns; + } + + /** + * Checks the existence of a virtual column in this object + * + * @param string $name The virtual column name + * @return boolean + */ + public function hasVirtualColumn($name) + { + return array_key_exists($name, $this->virtualColumns); + } + + /** + * Get the value of a virtual column in this object + * + * @param string $name The virtual column name + * @return mixed + * + * @throws PropelException + */ + public function getVirtualColumn($name) + { + if (!$this->hasVirtualColumn($name)) { + throw new PropelException(sprintf('Cannot get value of inexistent virtual column %s.', $name)); + } + + return $this->virtualColumns[$name]; + } + + /** + * Set the value of a virtual column in this object + * + * @param string $name The virtual column name + * @param mixed $value The value to give to the virtual column + * + * @return AtosCurrency The current object, for fluid interface + */ + public function setVirtualColumn($name, $value) + { + $this->virtualColumns[$name] = $value; + + return $this; + } + + /** + * Logs a message using Propel::log(). + * + * @param string $msg + * @param int $priority One of the Propel::LOG_* logging levels + * @return boolean + */ + protected function log($msg, $priority = Propel::LOG_INFO) + { + return Propel::log(get_class($this) . ': ' . $msg, $priority); + } + + /** + * Populate the current object from a string, using a given parser format + * + * $book = new Book(); + * $book->importFrom('JSON', '{"Id":9012,"Title":"Don Juan","ISBN":"0140422161","Price":12.99,"PublisherId":1234,"AuthorId":5678}'); + * + * + * @param mixed $parser A AbstractParser instance, + * or a format name ('XML', 'YAML', 'JSON', 'CSV') + * @param string $data The source data to import from + * + * @return AtosCurrency The current object, for fluid interface + */ + public function importFrom($parser, $data) + { + if (!$parser instanceof AbstractParser) { + $parser = AbstractParser::getParser($parser); + } + + $this->fromArray($parser->toArray($data), TableMap::TYPE_PHPNAME); + + return $this; + } + + /** + * Export the current object properties to a string, using a given parser format + * + * $book = BookQuery::create()->findPk(9012); + * echo $book->exportTo('JSON'); + * => {"Id":9012,"Title":"Don Juan","ISBN":"0140422161","Price":12.99,"PublisherId":1234,"AuthorId":5678}'); + * + * + * @param mixed $parser A AbstractParser instance, or a format name ('XML', 'YAML', 'JSON', 'CSV') + * @param boolean $includeLazyLoadColumns (optional) Whether to include lazy load(ed) columns. Defaults to TRUE. + * @return string The exported data + */ + public function exportTo($parser, $includeLazyLoadColumns = true) + { + if (!$parser instanceof AbstractParser) { + $parser = AbstractParser::getParser($parser); + } + + return $parser->fromArray($this->toArray(TableMap::TYPE_PHPNAME, $includeLazyLoadColumns, array(), true)); + } + + /** + * Clean up internal collections prior to serializing + * Avoids recursive loops that turn into segmentation faults when serializing + */ + public function __sleep() + { + $this->clearAllReferences(); + + return array_keys(get_object_vars($this)); + } + + /** + * Get the [code] column value. + * + * @return string + */ + public function getCode() + { + return $this->code; + } + + /** + * Get the [atos_code] column value. + * + * @return int + */ + public function getAtosCode() + { + return $this->atos_code; + } + + /** + * Get the [decimals] column value. + * + * @return int + */ + public function getDecimals() + { + return $this->decimals; + } + + /** + * Set the value of [code] column. + * + * @param string $v new value + * @return \Atos\Model\AtosCurrency The current object (for fluent API support) + */ + public function setCode($v) + { + if ($v !== null) { + $v = (string) $v; + } + + if ($this->code !== $v) { + $this->code = $v; + $this->modifiedColumns[AtosCurrencyTableMap::CODE] = true; + } + + return $this; + } // setCode() + + /** + * Set the value of [atos_code] column. + * + * @param int $v new value + * @return \Atos\Model\AtosCurrency The current object (for fluent API support) + */ + public function setAtosCode($v) + { + if ($v !== null) { + $v = (int) $v; + } + + if ($this->atos_code !== $v) { + $this->atos_code = $v; + $this->modifiedColumns[AtosCurrencyTableMap::ATOS_CODE] = true; + } + + return $this; + } // setAtosCode() + + /** + * Set the value of [decimals] column. + * + * @param int $v new value + * @return \Atos\Model\AtosCurrency The current object (for fluent API support) + */ + public function setDecimals($v) + { + if ($v !== null) { + $v = (int) $v; + } + + if ($this->decimals !== $v) { + $this->decimals = $v; + $this->modifiedColumns[AtosCurrencyTableMap::DECIMALS] = true; + } + + return $this; + } // setDecimals() + + /** + * Indicates whether the columns in this object are only set to default values. + * + * This method can be used in conjunction with isModified() to indicate whether an object is both + * modified _and_ has some values set which are non-default. + * + * @return boolean Whether the columns in this object are only been set with default values. + */ + public function hasOnlyDefaultValues() + { + // otherwise, everything was equal, so return TRUE + return true; + } // hasOnlyDefaultValues() + + /** + * Hydrates (populates) the object variables with values from the database resultset. + * + * An offset (0-based "start column") is specified so that objects can be hydrated + * with a subset of the columns in the resultset rows. This is needed, for example, + * for results of JOIN queries where the resultset row includes columns from two or + * more tables. + * + * @param array $row The row returned by DataFetcher->fetch(). + * @param int $startcol 0-based offset column which indicates which restultset column to start with. + * @param boolean $rehydrate Whether this object is being re-hydrated from the database. + * @param string $indexType The index type of $row. Mostly DataFetcher->getIndexType(). + One of the class type constants TableMap::TYPE_PHPNAME, TableMap::TYPE_STUDLYPHPNAME + * TableMap::TYPE_COLNAME, TableMap::TYPE_FIELDNAME, TableMap::TYPE_NUM. + * + * @return int next starting column + * @throws PropelException - Any caught Exception will be rewrapped as a PropelException. + */ + public function hydrate($row, $startcol = 0, $rehydrate = false, $indexType = TableMap::TYPE_NUM) + { + try { + + + $col = $row[TableMap::TYPE_NUM == $indexType ? 0 + $startcol : AtosCurrencyTableMap::translateFieldName('Code', TableMap::TYPE_PHPNAME, $indexType)]; + $this->code = (null !== $col) ? (string) $col : null; + + $col = $row[TableMap::TYPE_NUM == $indexType ? 1 + $startcol : AtosCurrencyTableMap::translateFieldName('AtosCode', TableMap::TYPE_PHPNAME, $indexType)]; + $this->atos_code = (null !== $col) ? (int) $col : null; + + $col = $row[TableMap::TYPE_NUM == $indexType ? 2 + $startcol : AtosCurrencyTableMap::translateFieldName('Decimals', TableMap::TYPE_PHPNAME, $indexType)]; + $this->decimals = (null !== $col) ? (int) $col : null; + $this->resetModified(); + + $this->setNew(false); + + if ($rehydrate) { + $this->ensureConsistency(); + } + + return $startcol + 3; // 3 = AtosCurrencyTableMap::NUM_HYDRATE_COLUMNS. + + } catch (Exception $e) { + throw new PropelException("Error populating \Atos\Model\AtosCurrency object", 0, $e); + } + } + + /** + * Checks and repairs the internal consistency of the object. + * + * This method is executed after an already-instantiated object is re-hydrated + * from the database. It exists to check any foreign keys to make sure that + * the objects related to the current object are correct based on foreign key. + * + * You can override this method in the stub class, but you should always invoke + * the base method from the overridden method (i.e. parent::ensureConsistency()), + * in case your model changes. + * + * @throws PropelException + */ + public function ensureConsistency() + { + } // ensureConsistency + + /** + * Reloads this object from datastore based on primary key and (optionally) resets all associated objects. + * + * This will only work if the object has been saved and has a valid primary key set. + * + * @param boolean $deep (optional) Whether to also de-associated any related objects. + * @param ConnectionInterface $con (optional) The ConnectionInterface connection to use. + * @return void + * @throws PropelException - if this object is deleted, unsaved or doesn't have pk match in db + */ + public function reload($deep = false, ConnectionInterface $con = null) + { + if ($this->isDeleted()) { + throw new PropelException("Cannot reload a deleted object."); + } + + if ($this->isNew()) { + throw new PropelException("Cannot reload an unsaved object."); + } + + if ($con === null) { + $con = Propel::getServiceContainer()->getReadConnection(AtosCurrencyTableMap::DATABASE_NAME); + } + + // We don't need to alter the object instance pool; we're just modifying this instance + // already in the pool. + + $dataFetcher = ChildAtosCurrencyQuery::create(null, $this->buildPkeyCriteria())->setFormatter(ModelCriteria::FORMAT_STATEMENT)->find($con); + $row = $dataFetcher->fetch(); + $dataFetcher->close(); + if (!$row) { + throw new PropelException('Cannot find matching row in the database to reload object values.'); + } + $this->hydrate($row, 0, true, $dataFetcher->getIndexType()); // rehydrate + + if ($deep) { // also de-associate any related objects? + + } // if (deep) + } + + /** + * Removes this object from datastore and sets delete attribute. + * + * @param ConnectionInterface $con + * @return void + * @throws PropelException + * @see AtosCurrency::setDeleted() + * @see AtosCurrency::isDeleted() + */ + public function delete(ConnectionInterface $con = null) + { + if ($this->isDeleted()) { + throw new PropelException("This object has already been deleted."); + } + + if ($con === null) { + $con = Propel::getServiceContainer()->getWriteConnection(AtosCurrencyTableMap::DATABASE_NAME); + } + + $con->beginTransaction(); + try { + $deleteQuery = ChildAtosCurrencyQuery::create() + ->filterByPrimaryKey($this->getPrimaryKey()); + $ret = $this->preDelete($con); + if ($ret) { + $deleteQuery->delete($con); + $this->postDelete($con); + $con->commit(); + $this->setDeleted(true); + } else { + $con->commit(); + } + } catch (Exception $e) { + $con->rollBack(); + throw $e; + } + } + + /** + * Persists this object to the database. + * + * If the object is new, it inserts it; otherwise an update is performed. + * All modified related objects will also be persisted in the doSave() + * method. This method wraps all precipitate database operations in a + * single transaction. + * + * @param ConnectionInterface $con + * @return int The number of rows affected by this insert/update and any referring fk objects' save() operations. + * @throws PropelException + * @see doSave() + */ + public function save(ConnectionInterface $con = null) + { + if ($this->isDeleted()) { + throw new PropelException("You cannot save an object that has been deleted."); + } + + if ($con === null) { + $con = Propel::getServiceContainer()->getWriteConnection(AtosCurrencyTableMap::DATABASE_NAME); + } + + $con->beginTransaction(); + $isInsert = $this->isNew(); + try { + $ret = $this->preSave($con); + if ($isInsert) { + $ret = $ret && $this->preInsert($con); + } else { + $ret = $ret && $this->preUpdate($con); + } + if ($ret) { + $affectedRows = $this->doSave($con); + if ($isInsert) { + $this->postInsert($con); + } else { + $this->postUpdate($con); + } + $this->postSave($con); + AtosCurrencyTableMap::addInstanceToPool($this); + } else { + $affectedRows = 0; + } + $con->commit(); + + return $affectedRows; + } catch (Exception $e) { + $con->rollBack(); + throw $e; + } + } + + /** + * Performs the work of inserting or updating the row in the database. + * + * If the object is new, it inserts it; otherwise an update is performed. + * All related objects are also updated in this method. + * + * @param ConnectionInterface $con + * @return int The number of rows affected by this insert/update and any referring fk objects' save() operations. + * @throws PropelException + * @see save() + */ + protected function doSave(ConnectionInterface $con) + { + $affectedRows = 0; // initialize var to track total num of affected rows + if (!$this->alreadyInSave) { + $this->alreadyInSave = true; + + if ($this->isNew() || $this->isModified()) { + // persist changes + if ($this->isNew()) { + $this->doInsert($con); + } else { + $this->doUpdate($con); + } + $affectedRows += 1; + $this->resetModified(); + } + + $this->alreadyInSave = false; + + } + + return $affectedRows; + } // doSave() + + /** + * Insert the row in the database. + * + * @param ConnectionInterface $con + * + * @throws PropelException + * @see doSave() + */ + protected function doInsert(ConnectionInterface $con) + { + $modifiedColumns = array(); + $index = 0; + + // check the columns in natural order for more readable SQL queries + if ($this->isColumnModified(AtosCurrencyTableMap::CODE)) { + $modifiedColumns[':p' . $index++] = 'CODE'; + } + if ($this->isColumnModified(AtosCurrencyTableMap::ATOS_CODE)) { + $modifiedColumns[':p' . $index++] = 'ATOS_CODE'; + } + if ($this->isColumnModified(AtosCurrencyTableMap::DECIMALS)) { + $modifiedColumns[':p' . $index++] = 'DECIMALS'; + } + + $sql = sprintf( + 'INSERT INTO atos_currency (%s) VALUES (%s)', + implode(', ', $modifiedColumns), + implode(', ', array_keys($modifiedColumns)) + ); + + try { + $stmt = $con->prepare($sql); + foreach ($modifiedColumns as $identifier => $columnName) { + switch ($columnName) { + case 'CODE': + $stmt->bindValue($identifier, $this->code, PDO::PARAM_STR); + break; + case 'ATOS_CODE': + $stmt->bindValue($identifier, $this->atos_code, PDO::PARAM_INT); + break; + case 'DECIMALS': + $stmt->bindValue($identifier, $this->decimals, PDO::PARAM_INT); + break; + } + } + $stmt->execute(); + } catch (Exception $e) { + Propel::log($e->getMessage(), Propel::LOG_ERR); + throw new PropelException(sprintf('Unable to execute INSERT statement [%s]', $sql), 0, $e); + } + + $this->setNew(false); + } + + /** + * Update the row in the database. + * + * @param ConnectionInterface $con + * + * @return Integer Number of updated rows + * @see doSave() + */ + protected function doUpdate(ConnectionInterface $con) + { + $selectCriteria = $this->buildPkeyCriteria(); + $valuesCriteria = $this->buildCriteria(); + + return $selectCriteria->doUpdate($valuesCriteria, $con); + } + + /** + * Retrieves a field from the object by name passed in as a string. + * + * @param string $name name + * @param string $type The type of fieldname the $name is of: + * one of the class type constants TableMap::TYPE_PHPNAME, TableMap::TYPE_STUDLYPHPNAME + * TableMap::TYPE_COLNAME, TableMap::TYPE_FIELDNAME, TableMap::TYPE_NUM. + * Defaults to TableMap::TYPE_PHPNAME. + * @return mixed Value of field. + */ + public function getByName($name, $type = TableMap::TYPE_PHPNAME) + { + $pos = AtosCurrencyTableMap::translateFieldName($name, $type, TableMap::TYPE_NUM); + $field = $this->getByPosition($pos); + + return $field; + } + + /** + * Retrieves a field from the object by Position as specified in the xml schema. + * Zero-based. + * + * @param int $pos position in xml schema + * @return mixed Value of field at $pos + */ + public function getByPosition($pos) + { + switch ($pos) { + case 0: + return $this->getCode(); + break; + case 1: + return $this->getAtosCode(); + break; + case 2: + return $this->getDecimals(); + break; + default: + return null; + break; + } // switch() + } + + /** + * Exports the object as an array. + * + * You can specify the key type of the array by passing one of the class + * type constants. + * + * @param string $keyType (optional) One of the class type constants TableMap::TYPE_PHPNAME, TableMap::TYPE_STUDLYPHPNAME, + * TableMap::TYPE_COLNAME, TableMap::TYPE_FIELDNAME, TableMap::TYPE_NUM. + * Defaults to TableMap::TYPE_PHPNAME. + * @param boolean $includeLazyLoadColumns (optional) Whether to include lazy loaded columns. Defaults to TRUE. + * @param array $alreadyDumpedObjects List of objects to skip to avoid recursion + * + * @return array an associative array containing the field names (as keys) and field values + */ + public function toArray($keyType = TableMap::TYPE_PHPNAME, $includeLazyLoadColumns = true, $alreadyDumpedObjects = array()) + { + if (isset($alreadyDumpedObjects['AtosCurrency'][$this->getPrimaryKey()])) { + return '*RECURSION*'; + } + $alreadyDumpedObjects['AtosCurrency'][$this->getPrimaryKey()] = true; + $keys = AtosCurrencyTableMap::getFieldNames($keyType); + $result = array( + $keys[0] => $this->getCode(), + $keys[1] => $this->getAtosCode(), + $keys[2] => $this->getDecimals(), + ); + $virtualColumns = $this->virtualColumns; + foreach ($virtualColumns as $key => $virtualColumn) { + $result[$key] = $virtualColumn; + } + + return $result; + } + + /** + * Sets a field from the object by name passed in as a string. + * + * @param string $name + * @param mixed $value field value + * @param string $type The type of fieldname the $name is of: + * one of the class type constants TableMap::TYPE_PHPNAME, TableMap::TYPE_STUDLYPHPNAME + * TableMap::TYPE_COLNAME, TableMap::TYPE_FIELDNAME, TableMap::TYPE_NUM. + * Defaults to TableMap::TYPE_PHPNAME. + * @return void + */ + public function setByName($name, $value, $type = TableMap::TYPE_PHPNAME) + { + $pos = AtosCurrencyTableMap::translateFieldName($name, $type, TableMap::TYPE_NUM); + + return $this->setByPosition($pos, $value); + } + + /** + * Sets a field from the object by Position as specified in the xml schema. + * Zero-based. + * + * @param int $pos position in xml schema + * @param mixed $value field value + * @return void + */ + public function setByPosition($pos, $value) + { + switch ($pos) { + case 0: + $this->setCode($value); + break; + case 1: + $this->setAtosCode($value); + break; + case 2: + $this->setDecimals($value); + break; + } // switch() + } + + /** + * Populates the object using an array. + * + * This is particularly useful when populating an object from one of the + * request arrays (e.g. $_POST). This method goes through the column + * names, checking to see whether a matching key exists in populated + * array. If so the setByName() method is called for that column. + * + * You can specify the key type of the array by additionally passing one + * of the class type constants TableMap::TYPE_PHPNAME, TableMap::TYPE_STUDLYPHPNAME, + * TableMap::TYPE_COLNAME, TableMap::TYPE_FIELDNAME, TableMap::TYPE_NUM. + * The default key type is the column's TableMap::TYPE_PHPNAME. + * + * @param array $arr An array to populate the object from. + * @param string $keyType The type of keys the array uses. + * @return void + */ + public function fromArray($arr, $keyType = TableMap::TYPE_PHPNAME) + { + $keys = AtosCurrencyTableMap::getFieldNames($keyType); + + if (array_key_exists($keys[0], $arr)) $this->setCode($arr[$keys[0]]); + if (array_key_exists($keys[1], $arr)) $this->setAtosCode($arr[$keys[1]]); + if (array_key_exists($keys[2], $arr)) $this->setDecimals($arr[$keys[2]]); + } + + /** + * Build a Criteria object containing the values of all modified columns in this object. + * + * @return Criteria The Criteria object containing all modified values. + */ + public function buildCriteria() + { + $criteria = new Criteria(AtosCurrencyTableMap::DATABASE_NAME); + + if ($this->isColumnModified(AtosCurrencyTableMap::CODE)) $criteria->add(AtosCurrencyTableMap::CODE, $this->code); + if ($this->isColumnModified(AtosCurrencyTableMap::ATOS_CODE)) $criteria->add(AtosCurrencyTableMap::ATOS_CODE, $this->atos_code); + if ($this->isColumnModified(AtosCurrencyTableMap::DECIMALS)) $criteria->add(AtosCurrencyTableMap::DECIMALS, $this->decimals); + return $criteria; + } + + /** + * Builds a Criteria object containing the primary key for this object. + * + * Unlike buildCriteria() this method includes the primary key values regardless + * of whether or not they have been modified. + * + * @return Criteria The Criteria object containing value(s) for primary key(s). + */ + public function buildPkeyCriteria() + { + $criteria = new Criteria(AtosCurrencyTableMap::DATABASE_NAME); + $criteria->add(AtosCurrencyTableMap::CODE, $this->code); + + return $criteria; + } + + /** + * Returns the primary key for this object (row). + * @return string + */ + public function getPrimaryKey() + { + return $this->getCode(); + } + + /** + * Generic method to set the primary key (code column). + * + * @param string $key Primary key. + * @return void + */ + public function setPrimaryKey($key) + { + $this->setCode($key); + } + + /** + * Returns true if the primary key for this object is null. + * @return boolean + */ + public function isPrimaryKeyNull() + { + return null === $this->getCode(); + } + + /** + * Sets contents of passed object to values from current object. + * + * If desired, this method can also make copies of all associated (fkey referrers) + * objects. + * + * @param object $copyObj An object of \Atos\Model\AtosCurrency (or compatible) type. + * @param boolean $deepCopy Whether to also copy all rows that refer (by fkey) to the current row. + * @param boolean $makeNew Whether to reset autoincrement PKs and make the object new. + * @throws PropelException + */ + public function copyInto($copyObj, $deepCopy = false, $makeNew = true) + { + $copyObj->setCode($this->getCode()); + $copyObj->setAtosCode($this->getAtosCode()); + $copyObj->setDecimals($this->getDecimals()); + if ($makeNew) { + $copyObj->setNew(true); + } + } + + /** + * Makes a copy of this object that will be inserted as a new row in table when saved. + * It creates a new object filling in the simple attributes, but skipping any primary + * keys that are defined for the table. + * + * If desired, this method can also make copies of all associated (fkey referrers) + * objects. + * + * @param boolean $deepCopy Whether to also copy all rows that refer (by fkey) to the current row. + * @return \Atos\Model\AtosCurrency Clone of current object. + * @throws PropelException + */ + public function copy($deepCopy = false) + { + // we use get_class(), because this might be a subclass + $clazz = get_class($this); + $copyObj = new $clazz(); + $this->copyInto($copyObj, $deepCopy); + + return $copyObj; + } + + /** + * Clears the current object and sets all attributes to their default values + */ + public function clear() + { + $this->code = null; + $this->atos_code = null; + $this->decimals = null; + $this->alreadyInSave = false; + $this->clearAllReferences(); + $this->resetModified(); + $this->setNew(true); + $this->setDeleted(false); + } + + /** + * Resets all references to other model objects or collections of model objects. + * + * This method is a user-space workaround for PHP's inability to garbage collect + * objects with circular references (even in PHP 5.3). This is currently necessary + * when using Propel in certain daemon or large-volume/high-memory operations. + * + * @param boolean $deep Whether to also clear the references on all referrer objects. + */ + public function clearAllReferences($deep = false) + { + if ($deep) { + } // if ($deep) + + } + + /** + * Return the string representation of this object + * + * @return string + */ + public function __toString() + { + return (string) $this->exportTo(AtosCurrencyTableMap::DEFAULT_STRING_FORMAT); + } + + /** + * Code to be run before persisting the object + * @param ConnectionInterface $con + * @return boolean + */ + public function preSave(ConnectionInterface $con = null) + { + return true; + } + + /** + * Code to be run after persisting the object + * @param ConnectionInterface $con + */ + public function postSave(ConnectionInterface $con = null) + { + + } + + /** + * Code to be run before inserting to database + * @param ConnectionInterface $con + * @return boolean + */ + public function preInsert(ConnectionInterface $con = null) + { + return true; + } + + /** + * Code to be run after inserting to database + * @param ConnectionInterface $con + */ + public function postInsert(ConnectionInterface $con = null) + { + + } + + /** + * Code to be run before updating the object in database + * @param ConnectionInterface $con + * @return boolean + */ + public function preUpdate(ConnectionInterface $con = null) + { + return true; + } + + /** + * Code to be run after updating the object in database + * @param ConnectionInterface $con + */ + public function postUpdate(ConnectionInterface $con = null) + { + + } + + /** + * Code to be run before deleting the object in database + * @param ConnectionInterface $con + * @return boolean + */ + public function preDelete(ConnectionInterface $con = null) + { + return true; + } + + /** + * Code to be run after deleting the object in database + * @param ConnectionInterface $con + */ + public function postDelete(ConnectionInterface $con = null) + { + + } + + /** + * Derived method to catches calls to undefined methods. + * + * Provides magic import/export method support (fromXML()/toXML(), fromYAML()/toYAML(), etc.). + * Allows to define default __call() behavior if you overwrite __call() + * + * @param string $name + * @param mixed $params + * + * @return array|string + */ + public function __call($name, $params) + { + if (0 === strpos($name, 'get')) { + $virtualColumn = substr($name, 3); + if ($this->hasVirtualColumn($virtualColumn)) { + return $this->getVirtualColumn($virtualColumn); + } + + $virtualColumn = lcfirst($virtualColumn); + if ($this->hasVirtualColumn($virtualColumn)) { + return $this->getVirtualColumn($virtualColumn); + } + } + + if (0 === strpos($name, 'from')) { + $format = substr($name, 4); + + return $this->importFrom($format, reset($params)); + } + + if (0 === strpos($name, 'to')) { + $format = substr($name, 2); + $includeLazyLoadColumns = isset($params[0]) ? $params[0] : true; + + return $this->exportTo($format, $includeLazyLoadColumns); + } + + throw new BadMethodCallException(sprintf('Call to undefined method: %s.', $name)); + } + +} diff --git a/local/modules/Atos/Model/Base/AtosCurrencyQuery.php b/local/modules/Atos/Model/Base/AtosCurrencyQuery.php new file mode 100644 index 00000000..589ccaa2 --- /dev/null +++ b/local/modules/Atos/Model/Base/AtosCurrencyQuery.php @@ -0,0 +1,419 @@ +setModelAlias($modelAlias); + } + if ($criteria instanceof Criteria) { + $query->mergeWith($criteria); + } + + return $query; + } + + /** + * Find object by primary key. + * Propel uses the instance pool to skip the database if the object exists. + * Go fast if the query is untouched. + * + * + * $obj = $c->findPk(12, $con); + * + * + * @param mixed $key Primary key to use for the query + * @param ConnectionInterface $con an optional connection object + * + * @return ChildAtosCurrency|array|mixed the result, formatted by the current formatter + */ + public function findPk($key, $con = null) + { + if ($key === null) { + return null; + } + if ((null !== ($obj = AtosCurrencyTableMap::getInstanceFromPool((string) $key))) && !$this->formatter) { + // the object is already in the instance pool + return $obj; + } + if ($con === null) { + $con = Propel::getServiceContainer()->getReadConnection(AtosCurrencyTableMap::DATABASE_NAME); + } + $this->basePreSelect($con); + if ($this->formatter || $this->modelAlias || $this->with || $this->select + || $this->selectColumns || $this->asColumns || $this->selectModifiers + || $this->map || $this->having || $this->joins) { + return $this->findPkComplex($key, $con); + } else { + return $this->findPkSimple($key, $con); + } + } + + /** + * Find object by primary key using raw SQL to go fast. + * Bypass doSelect() and the object formatter by using generated code. + * + * @param mixed $key Primary key to use for the query + * @param ConnectionInterface $con A connection object + * + * @return ChildAtosCurrency A model object, or null if the key is not found + */ + protected function findPkSimple($key, $con) + { + $sql = 'SELECT CODE, ATOS_CODE, DECIMALS FROM atos_currency WHERE CODE = :p0'; + try { + $stmt = $con->prepare($sql); + $stmt->bindValue(':p0', $key, PDO::PARAM_STR); + $stmt->execute(); + } catch (Exception $e) { + Propel::log($e->getMessage(), Propel::LOG_ERR); + throw new PropelException(sprintf('Unable to execute SELECT statement [%s]', $sql), 0, $e); + } + $obj = null; + if ($row = $stmt->fetch(\PDO::FETCH_NUM)) { + $obj = new ChildAtosCurrency(); + $obj->hydrate($row); + AtosCurrencyTableMap::addInstanceToPool($obj, (string) $key); + } + $stmt->closeCursor(); + + return $obj; + } + + /** + * Find object by primary key. + * + * @param mixed $key Primary key to use for the query + * @param ConnectionInterface $con A connection object + * + * @return ChildAtosCurrency|array|mixed the result, formatted by the current formatter + */ + protected function findPkComplex($key, $con) + { + // As the query uses a PK condition, no limit(1) is necessary. + $criteria = $this->isKeepQuery() ? clone $this : $this; + $dataFetcher = $criteria + ->filterByPrimaryKey($key) + ->doSelect($con); + + return $criteria->getFormatter()->init($criteria)->formatOne($dataFetcher); + } + + /** + * Find objects by primary key + * + * $objs = $c->findPks(array(12, 56, 832), $con); + * + * @param array $keys Primary keys to use for the query + * @param ConnectionInterface $con an optional connection object + * + * @return ObjectCollection|array|mixed the list of results, formatted by the current formatter + */ + public function findPks($keys, $con = null) + { + if (null === $con) { + $con = Propel::getServiceContainer()->getReadConnection($this->getDbName()); + } + $this->basePreSelect($con); + $criteria = $this->isKeepQuery() ? clone $this : $this; + $dataFetcher = $criteria + ->filterByPrimaryKeys($keys) + ->doSelect($con); + + return $criteria->getFormatter()->init($criteria)->format($dataFetcher); + } + + /** + * Filter the query by primary key + * + * @param mixed $key Primary key to use for the query + * + * @return ChildAtosCurrencyQuery The current query, for fluid interface + */ + public function filterByPrimaryKey($key) + { + return $this->addUsingAlias(AtosCurrencyTableMap::CODE, $key, Criteria::EQUAL); + } + + /** + * Filter the query by a list of primary keys + * + * @param array $keys The list of primary key to use for the query + * + * @return ChildAtosCurrencyQuery The current query, for fluid interface + */ + public function filterByPrimaryKeys($keys) + { + return $this->addUsingAlias(AtosCurrencyTableMap::CODE, $keys, Criteria::IN); + } + + /** + * Filter the query on the code column + * + * Example usage: + * + * $query->filterByCode('fooValue'); // WHERE code = 'fooValue' + * $query->filterByCode('%fooValue%'); // WHERE code LIKE '%fooValue%' + * + * + * @param string $code The value to use as filter. + * Accepts wildcards (* and % trigger a LIKE) + * @param string $comparison Operator to use for the column comparison, defaults to Criteria::EQUAL + * + * @return ChildAtosCurrencyQuery The current query, for fluid interface + */ + public function filterByCode($code = null, $comparison = null) + { + if (null === $comparison) { + if (is_array($code)) { + $comparison = Criteria::IN; + } elseif (preg_match('/[\%\*]/', $code)) { + $code = str_replace('*', '%', $code); + $comparison = Criteria::LIKE; + } + } + + return $this->addUsingAlias(AtosCurrencyTableMap::CODE, $code, $comparison); + } + + /** + * Filter the query on the atos_code column + * + * Example usage: + * + * $query->filterByAtosCode(1234); // WHERE atos_code = 1234 + * $query->filterByAtosCode(array(12, 34)); // WHERE atos_code IN (12, 34) + * $query->filterByAtosCode(array('min' => 12)); // WHERE atos_code > 12 + * + * + * @param mixed $atosCode The value to use as filter. + * Use scalar values for equality. + * Use array values for in_array() equivalent. + * Use associative array('min' => $minValue, 'max' => $maxValue) for intervals. + * @param string $comparison Operator to use for the column comparison, defaults to Criteria::EQUAL + * + * @return ChildAtosCurrencyQuery The current query, for fluid interface + */ + public function filterByAtosCode($atosCode = null, $comparison = null) + { + if (is_array($atosCode)) { + $useMinMax = false; + if (isset($atosCode['min'])) { + $this->addUsingAlias(AtosCurrencyTableMap::ATOS_CODE, $atosCode['min'], Criteria::GREATER_EQUAL); + $useMinMax = true; + } + if (isset($atosCode['max'])) { + $this->addUsingAlias(AtosCurrencyTableMap::ATOS_CODE, $atosCode['max'], Criteria::LESS_EQUAL); + $useMinMax = true; + } + if ($useMinMax) { + return $this; + } + if (null === $comparison) { + $comparison = Criteria::IN; + } + } + + return $this->addUsingAlias(AtosCurrencyTableMap::ATOS_CODE, $atosCode, $comparison); + } + + /** + * Filter the query on the decimals column + * + * Example usage: + * + * $query->filterByDecimals(1234); // WHERE decimals = 1234 + * $query->filterByDecimals(array(12, 34)); // WHERE decimals IN (12, 34) + * $query->filterByDecimals(array('min' => 12)); // WHERE decimals > 12 + * + * + * @param mixed $decimals The value to use as filter. + * Use scalar values for equality. + * Use array values for in_array() equivalent. + * Use associative array('min' => $minValue, 'max' => $maxValue) for intervals. + * @param string $comparison Operator to use for the column comparison, defaults to Criteria::EQUAL + * + * @return ChildAtosCurrencyQuery The current query, for fluid interface + */ + public function filterByDecimals($decimals = null, $comparison = null) + { + if (is_array($decimals)) { + $useMinMax = false; + if (isset($decimals['min'])) { + $this->addUsingAlias(AtosCurrencyTableMap::DECIMALS, $decimals['min'], Criteria::GREATER_EQUAL); + $useMinMax = true; + } + if (isset($decimals['max'])) { + $this->addUsingAlias(AtosCurrencyTableMap::DECIMALS, $decimals['max'], Criteria::LESS_EQUAL); + $useMinMax = true; + } + if ($useMinMax) { + return $this; + } + if (null === $comparison) { + $comparison = Criteria::IN; + } + } + + return $this->addUsingAlias(AtosCurrencyTableMap::DECIMALS, $decimals, $comparison); + } + + /** + * Exclude object from result + * + * @param ChildAtosCurrency $atosCurrency Object to remove from the list of results + * + * @return ChildAtosCurrencyQuery The current query, for fluid interface + */ + public function prune($atosCurrency = null) + { + if ($atosCurrency) { + $this->addUsingAlias(AtosCurrencyTableMap::CODE, $atosCurrency->getCode(), Criteria::NOT_EQUAL); + } + + return $this; + } + + /** + * Deletes all rows from the atos_currency table. + * + * @param ConnectionInterface $con the connection to use + * @return int The number of affected rows (if supported by underlying database driver). + */ + public function doDeleteAll(ConnectionInterface $con = null) + { + if (null === $con) { + $con = Propel::getServiceContainer()->getWriteConnection(AtosCurrencyTableMap::DATABASE_NAME); + } + $affectedRows = 0; // initialize var to track total num of affected rows + try { + // use transaction because $criteria could contain info + // for more than one table or we could emulating ON DELETE CASCADE, etc. + $con->beginTransaction(); + $affectedRows += parent::doDeleteAll($con); + // Because this db requires some delete cascade/set null emulation, we have to + // clear the cached instance *after* the emulation has happened (since + // instances get re-added by the select statement contained therein). + AtosCurrencyTableMap::clearInstancePool(); + AtosCurrencyTableMap::clearRelatedInstancePool(); + + $con->commit(); + } catch (PropelException $e) { + $con->rollBack(); + throw $e; + } + + return $affectedRows; + } + + /** + * Performs a DELETE on the database, given a ChildAtosCurrency or Criteria object OR a primary key value. + * + * @param mixed $values Criteria or ChildAtosCurrency object or primary key or array of primary keys + * which is used to create the DELETE statement + * @param ConnectionInterface $con the connection to use + * @return int The number of affected rows (if supported by underlying database driver). This includes CASCADE-related rows + * if supported by native driver or if emulated using Propel. + * @throws PropelException Any exceptions caught during processing will be + * rethrown wrapped into a PropelException. + */ + public function delete(ConnectionInterface $con = null) + { + if (null === $con) { + $con = Propel::getServiceContainer()->getWriteConnection(AtosCurrencyTableMap::DATABASE_NAME); + } + + $criteria = $this; + + // Set the correct dbName + $criteria->setDbName(AtosCurrencyTableMap::DATABASE_NAME); + + $affectedRows = 0; // initialize var to track total num of affected rows + + try { + // use transaction because $criteria could contain info + // for more than one table or we could emulating ON DELETE CASCADE, etc. + $con->beginTransaction(); + + AtosCurrencyTableMap::removeInstanceFromPool($criteria); + + $affectedRows += ModelCriteria::delete($con); + AtosCurrencyTableMap::clearRelatedInstancePool(); + $con->commit(); + + return $affectedRows; + } catch (PropelException $e) { + $con->rollBack(); + throw $e; + } + } + +} // AtosCurrencyQuery diff --git a/local/modules/Atos/Model/Map/AtosCurrencyTableMap.php b/local/modules/Atos/Model/Map/AtosCurrencyTableMap.php new file mode 100644 index 00000000..73dbce52 --- /dev/null +++ b/local/modules/Atos/Model/Map/AtosCurrencyTableMap.php @@ -0,0 +1,411 @@ + array('Code', 'AtosCode', 'Decimals', ), + self::TYPE_STUDLYPHPNAME => array('code', 'atosCode', 'decimals', ), + self::TYPE_COLNAME => array(AtosCurrencyTableMap::CODE, AtosCurrencyTableMap::ATOS_CODE, AtosCurrencyTableMap::DECIMALS, ), + self::TYPE_RAW_COLNAME => array('CODE', 'ATOS_CODE', 'DECIMALS', ), + self::TYPE_FIELDNAME => array('code', 'atos_code', 'decimals', ), + self::TYPE_NUM => array(0, 1, 2, ) + ); + + /** + * holds an array of keys for quick access to the fieldnames array + * + * first dimension keys are the type constants + * e.g. self::$fieldKeys[self::TYPE_PHPNAME]['Id'] = 0 + */ + protected static $fieldKeys = array ( + self::TYPE_PHPNAME => array('Code' => 0, 'AtosCode' => 1, 'Decimals' => 2, ), + self::TYPE_STUDLYPHPNAME => array('code' => 0, 'atosCode' => 1, 'decimals' => 2, ), + self::TYPE_COLNAME => array(AtosCurrencyTableMap::CODE => 0, AtosCurrencyTableMap::ATOS_CODE => 1, AtosCurrencyTableMap::DECIMALS => 2, ), + self::TYPE_RAW_COLNAME => array('CODE' => 0, 'ATOS_CODE' => 1, 'DECIMALS' => 2, ), + self::TYPE_FIELDNAME => array('code' => 0, 'atos_code' => 1, 'decimals' => 2, ), + self::TYPE_NUM => array(0, 1, 2, ) + ); + + /** + * Initialize the table attributes and columns + * Relations are not initialized by this method since they are lazy loaded + * + * @return void + * @throws PropelException + */ + public function initialize() + { + // attributes + $this->setName('atos_currency'); + $this->setPhpName('AtosCurrency'); + $this->setClassName('\\Atos\\Model\\AtosCurrency'); + $this->setPackage('Atos.Model'); + $this->setUseIdGenerator(false); + // columns + $this->addPrimaryKey('CODE', 'Code', 'VARCHAR', true, 128, null); + $this->addColumn('ATOS_CODE', 'AtosCode', 'INTEGER', false, null, null); + $this->addColumn('DECIMALS', 'Decimals', 'INTEGER', false, null, null); + } // initialize() + + /** + * Build the RelationMap objects for this table relationships + */ + public function buildRelations() + { + } // buildRelations() + + /** + * Retrieves a string version of the primary key from the DB resultset row that can be used to uniquely identify a row in this table. + * + * For tables with a single-column primary key, that simple pkey value will be returned. For tables with + * a multi-column primary key, a serialize()d version of the primary key will be returned. + * + * @param array $row resultset row. + * @param int $offset The 0-based offset for reading from the resultset row. + * @param string $indexType One of the class type constants TableMap::TYPE_PHPNAME, TableMap::TYPE_STUDLYPHPNAME + * TableMap::TYPE_COLNAME, TableMap::TYPE_FIELDNAME, TableMap::TYPE_NUM + */ + public static function getPrimaryKeyHashFromRow($row, $offset = 0, $indexType = TableMap::TYPE_NUM) + { + // If the PK cannot be derived from the row, return NULL. + if ($row[TableMap::TYPE_NUM == $indexType ? 0 + $offset : static::translateFieldName('Code', TableMap::TYPE_PHPNAME, $indexType)] === null) { + return null; + } + + return (string) $row[TableMap::TYPE_NUM == $indexType ? 0 + $offset : static::translateFieldName('Code', TableMap::TYPE_PHPNAME, $indexType)]; + } + + /** + * Retrieves the primary key from the DB resultset row + * For tables with a single-column primary key, that simple pkey value will be returned. For tables with + * a multi-column primary key, an array of the primary key columns will be returned. + * + * @param array $row resultset row. + * @param int $offset The 0-based offset for reading from the resultset row. + * @param string $indexType One of the class type constants TableMap::TYPE_PHPNAME, TableMap::TYPE_STUDLYPHPNAME + * TableMap::TYPE_COLNAME, TableMap::TYPE_FIELDNAME, TableMap::TYPE_NUM + * + * @return mixed The primary key of the row + */ + public static function getPrimaryKeyFromRow($row, $offset = 0, $indexType = TableMap::TYPE_NUM) + { + return (string) $row[ + $indexType == TableMap::TYPE_NUM + ? 0 + $offset + : self::translateFieldName('Code', TableMap::TYPE_PHPNAME, $indexType) + ]; + } + + /** + * The class that the tableMap will make instances of. + * + * If $withPrefix is true, the returned path + * uses a dot-path notation which is translated into a path + * relative to a location on the PHP include_path. + * (e.g. path.to.MyClass -> 'path/to/MyClass.php') + * + * @param boolean $withPrefix Whether or not to return the path with the class name + * @return string path.to.ClassName + */ + public static function getOMClass($withPrefix = true) + { + return $withPrefix ? AtosCurrencyTableMap::CLASS_DEFAULT : AtosCurrencyTableMap::OM_CLASS; + } + + /** + * Populates an object of the default type or an object that inherit from the default. + * + * @param array $row row returned by DataFetcher->fetch(). + * @param int $offset The 0-based offset for reading from the resultset row. + * @param string $indexType The index type of $row. Mostly DataFetcher->getIndexType(). + One of the class type constants TableMap::TYPE_PHPNAME, TableMap::TYPE_STUDLYPHPNAME + * TableMap::TYPE_COLNAME, TableMap::TYPE_FIELDNAME, TableMap::TYPE_NUM. + * + * @throws PropelException Any exceptions caught during processing will be + * rethrown wrapped into a PropelException. + * @return array (AtosCurrency object, last column rank) + */ + public static function populateObject($row, $offset = 0, $indexType = TableMap::TYPE_NUM) + { + $key = AtosCurrencyTableMap::getPrimaryKeyHashFromRow($row, $offset, $indexType); + if (null !== ($obj = AtosCurrencyTableMap::getInstanceFromPool($key))) { + // We no longer rehydrate the object, since this can cause data loss. + // See http://www.propelorm.org/ticket/509 + // $obj->hydrate($row, $offset, true); // rehydrate + $col = $offset + AtosCurrencyTableMap::NUM_HYDRATE_COLUMNS; + } else { + $cls = AtosCurrencyTableMap::OM_CLASS; + $obj = new $cls(); + $col = $obj->hydrate($row, $offset, false, $indexType); + AtosCurrencyTableMap::addInstanceToPool($obj, $key); + } + + return array($obj, $col); + } + + /** + * The returned array will contain objects of the default type or + * objects that inherit from the default. + * + * @param DataFetcherInterface $dataFetcher + * @return array + * @throws PropelException Any exceptions caught during processing will be + * rethrown wrapped into a PropelException. + */ + public static function populateObjects(DataFetcherInterface $dataFetcher) + { + $results = array(); + + // set the class once to avoid overhead in the loop + $cls = static::getOMClass(false); + // populate the object(s) + while ($row = $dataFetcher->fetch()) { + $key = AtosCurrencyTableMap::getPrimaryKeyHashFromRow($row, 0, $dataFetcher->getIndexType()); + if (null !== ($obj = AtosCurrencyTableMap::getInstanceFromPool($key))) { + // We no longer rehydrate the object, since this can cause data loss. + // See http://www.propelorm.org/ticket/509 + // $obj->hydrate($row, 0, true); // rehydrate + $results[] = $obj; + } else { + $obj = new $cls(); + $obj->hydrate($row); + $results[] = $obj; + AtosCurrencyTableMap::addInstanceToPool($obj, $key); + } // if key exists + } + + return $results; + } + /** + * Add all the columns needed to create a new object. + * + * Note: any columns that were marked with lazyLoad="true" in the + * XML schema will not be added to the select list and only loaded + * on demand. + * + * @param Criteria $criteria object containing the columns to add. + * @param string $alias optional table alias + * @throws PropelException Any exceptions caught during processing will be + * rethrown wrapped into a PropelException. + */ + public static function addSelectColumns(Criteria $criteria, $alias = null) + { + if (null === $alias) { + $criteria->addSelectColumn(AtosCurrencyTableMap::CODE); + $criteria->addSelectColumn(AtosCurrencyTableMap::ATOS_CODE); + $criteria->addSelectColumn(AtosCurrencyTableMap::DECIMALS); + } else { + $criteria->addSelectColumn($alias . '.CODE'); + $criteria->addSelectColumn($alias . '.ATOS_CODE'); + $criteria->addSelectColumn($alias . '.DECIMALS'); + } + } + + /** + * Returns the TableMap related to this object. + * This method is not needed for general use but a specific application could have a need. + * @return TableMap + * @throws PropelException Any exceptions caught during processing will be + * rethrown wrapped into a PropelException. + */ + public static function getTableMap() + { + return Propel::getServiceContainer()->getDatabaseMap(AtosCurrencyTableMap::DATABASE_NAME)->getTable(AtosCurrencyTableMap::TABLE_NAME); + } + + /** + * Add a TableMap instance to the database for this tableMap class. + */ + public static function buildTableMap() + { + $dbMap = Propel::getServiceContainer()->getDatabaseMap(AtosCurrencyTableMap::DATABASE_NAME); + if (!$dbMap->hasTable(AtosCurrencyTableMap::TABLE_NAME)) { + $dbMap->addTableObject(new AtosCurrencyTableMap()); + } + } + + /** + * Performs a DELETE on the database, given a AtosCurrency or Criteria object OR a primary key value. + * + * @param mixed $values Criteria or AtosCurrency object or primary key or array of primary keys + * which is used to create the DELETE statement + * @param ConnectionInterface $con the connection to use + * @return int The number of affected rows (if supported by underlying database driver). This includes CASCADE-related rows + * if supported by native driver or if emulated using Propel. + * @throws PropelException Any exceptions caught during processing will be + * rethrown wrapped into a PropelException. + */ + public static function doDelete($values, ConnectionInterface $con = null) + { + if (null === $con) { + $con = Propel::getServiceContainer()->getWriteConnection(AtosCurrencyTableMap::DATABASE_NAME); + } + + if ($values instanceof Criteria) { + // rename for clarity + $criteria = $values; + } elseif ($values instanceof \Atos\Model\AtosCurrency) { // it's a model object + // create criteria based on pk values + $criteria = $values->buildPkeyCriteria(); + } else { // it's a primary key, or an array of pks + $criteria = new Criteria(AtosCurrencyTableMap::DATABASE_NAME); + $criteria->add(AtosCurrencyTableMap::CODE, (array) $values, Criteria::IN); + } + + $query = AtosCurrencyQuery::create()->mergeWith($criteria); + + if ($values instanceof Criteria) { AtosCurrencyTableMap::clearInstancePool(); + } elseif (!is_object($values)) { // it's a primary key, or an array of pks + foreach ((array) $values as $singleval) { AtosCurrencyTableMap::removeInstanceFromPool($singleval); + } + } + + return $query->delete($con); + } + + /** + * Deletes all rows from the atos_currency table. + * + * @param ConnectionInterface $con the connection to use + * @return int The number of affected rows (if supported by underlying database driver). + */ + public static function doDeleteAll(ConnectionInterface $con = null) + { + return AtosCurrencyQuery::create()->doDeleteAll($con); + } + + /** + * Performs an INSERT on the database, given a AtosCurrency or Criteria object. + * + * @param mixed $criteria Criteria or AtosCurrency object containing data that is used to create the INSERT statement. + * @param ConnectionInterface $con the ConnectionInterface connection to use + * @return mixed The new primary key. + * @throws PropelException Any exceptions caught during processing will be + * rethrown wrapped into a PropelException. + */ + public static function doInsert($criteria, ConnectionInterface $con = null) + { + if (null === $con) { + $con = Propel::getServiceContainer()->getWriteConnection(AtosCurrencyTableMap::DATABASE_NAME); + } + + if ($criteria instanceof Criteria) { + $criteria = clone $criteria; // rename for clarity + } else { + $criteria = $criteria->buildCriteria(); // build Criteria from AtosCurrency object + } + + // Set the correct dbName + $query = AtosCurrencyQuery::create()->mergeWith($criteria); + + try { + // use transaction because $criteria could contain info + // for more than one table (I guess, conceivably) + $con->beginTransaction(); + $pk = $query->doInsert($con); + $con->commit(); + } catch (PropelException $e) { + $con->rollBack(); + throw $e; + } + + return $pk; + } + +} // AtosCurrencyTableMap +// This is the static code needed to register the TableMap for this table with the main Propel class. +// +AtosCurrencyTableMap::buildTableMap(); diff --git a/local/modules/Atos/Readme.md b/local/modules/Atos/Readme.md new file mode 100644 index 00000000..dc818291 --- /dev/null +++ b/local/modules/Atos/Readme.md @@ -0,0 +1,71 @@ +# Atos-SIPS Payment Module +------------------------ + +## English instructions + +This module offers to your customers the Atos SIPS payment system, which is widely used by the french banks under different names: Mercanet, E-Transactions, Citelis, and much more. + +### Installation + +#### Manually + +Install the Atos module using the Module page of your back office to upload the archive. + +You can also extract the archive in the `/local/modules` directory. Be sure that the name of the module's directory is `Atos` (and not `Atos-master`, for example). + +Activate the module from the Modules page of your back-office. + +#### composer + +``` +$ composer require thelia/atos-module:~1.0 +``` + +### Usage + +You have to configure the Atos module before starting to use it. To do so, go to the "Modules" tab of your Thelia back-office, and activate the Atos module. + +Then click the "Configure" button, and enter the required information. In most case, you'll receive your merchant ID by e-mail, and you'll receive instructions to download your certificate. + +The module performs several checks when the configuration is saved, especially the execution permissions on the Atos binaries. + +During the test phase, you can define the IP addresses allowed to use the Atos module on the front office, so that your customers will not be able to pay with Atos during this test phase. + +A log of Atos post-payment callbacks is displayed in the configuration page. + +### Payment template + +You can customize the payment page ```templates/atos/payment.html``` to provide a better integration in your template, but the payment form data cannot be modified, as it is generated and signed by the Atos binary. + +## Instructions en français + +Ce module permet à vos clients de payer leurs commande par carte bancaire via la plate-forme Atos SIPS, utilisée par de nombreuses banques françaises sous diverses dénominations commerciales: Mercanet, Citelis, E-Transactions, et bien d'autres. + +## Installation + +### Manuellement + +Installez ce module directement depuis la page Modules de votre back-office, en envoyant le fichier zip du module. + +Vous pouvez aussi décompresser le module, et le placer manuellement dans le dossier ```/local/modules```. Assurez-vous que le nom du dossier est bien ```Atos```, et pas ```Atos-master``` + +### composer + +``` +$ composer require thelia/atos-module:~1.0 +``` + + +## Utilisation + +Pour utiliser le module Atos, vous devez tout d'abord le configurer. Pour ce faire, rendez-vous dans votre back-office, onglet Modules, et activez le module Atos. + +Cliquez ensuite sur "Configurer" sur la ligne du module, et renseignez les informations requises. Dans la plupart des cas, l'ID Marchand vous a été communiqué par votre banque par e-mail, et vous devez recevoir les instructions qui vous permettront de télécharger le certificat. + +Le module réalise plusieurs vérifications de votre configuration, et vous signalera les problèmes éventuellement rencontrés. Il contrôle notamment que les exécutables Atos possèdent bien les permissions d'exécution. + +Lors de la phase de test, vous pouvez définir les adresses IP qui seront autorisées à utiliser le module en front-office, afin de ne pas laisser vos clients payer leur commandes avec Atos pendant cette phase. + +## Template de paiement + +Vous pouvez adapter la page de paiement qui se trouve dans ```templates/atos/payment.html```, et l'adapter à votre template, mais la form de paiement en elle-même ne peut pas être modifiée, elle est générée et signée par le binaire Atos, et ne doit pas être modifiée. \ No newline at end of file diff --git a/local/modules/Atos/bin/request b/local/modules/Atos/bin/request new file mode 100644 index 0000000000000000000000000000000000000000..375e42842dbb8de3f63ec174305ff6c82f6da7ae GIT binary patch literal 790680 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

9rxHIwif-G> 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

x%33a(-+t!yfmFBR}e`gO133mQi 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 literal 0 HcmV?d00001 diff --git a/local/modules/Atos/bin/response b/local/modules/Atos/bin/response new file mode 100644 index 0000000000000000000000000000000000000000..19ec308a51749e3b1eeb40f04fedb14f223e491f GIT binary patch literal 774424 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%0AK5xwm(x-(Z^38Ueb8`1xF^QGh!;qFzh%R zH919yL=F>lgp-0J6%S4N9rZf2fn5!B|I!G6KVx@euU2Ds=k7-Mki{?MYv4U{VSL2;<(o1|C{U+-&w|0zVN^-E38*0EG7-eoAmma;g*ma*)0 zY*L!Zn=lh5TE3?J-)W6fW#up0DPbAm0a?EIjEA5i7AzwBK@^kl7~TZ|uJisMUZ)<# z-qe^qe?Ku9v7I}D|If9zKvnV9*izLxV<zp5o-HU9GkrGlFW(Y$sw#{j`+ki=IOm zrJsJ<{HwEAE8wieYM~QGhT>W@ana;yJ?U6etL+jbAR^n58IcoOR;ljEaQkigq$98;_vd1+$l3}99}d8j}>gLbMQbG zs(84e-tZt>Uxv~muXyrwgzOsP=k@j$oB@~XBE2+jEbCYU-Bl3)q_9U84j9SLDnoKH z*GGF?LQ1f!ZI|L6`I5UDvrM51`)CoiGS5aba6Y~v% z*gDZoFYC2IF>AP2S;ctx|M~h)H@b5*0`id@o##?pf;m8fP7l&ZD);8G*xH;&1arR+ zl8jAF4-WfW*KwHlQfUdY0I3)dF^VX_nHLoWcB<>Ppf6TGW9yj{%^I}(`3Qu?iWsme z6{c|hPTQQ{`F6dy7b4Dsu1>eNkC*XV9Vb|(|J`5z5h5>9Q|W#tAcBY}m&QNPky@Xg oa-wJIPbdpIUk9!g!N<>)x9Ok`_u^)1${7j{KfE#d{Y*;!3qS?AtpET3 literal 0 HcmV?d00001 diff --git a/local/modules/Atos/composer.json b/local/modules/Atos/composer.json new file mode 100644 index 00000000..477858be --- /dev/null +++ b/local/modules/Atos/composer.json @@ -0,0 +1,11 @@ +{ + "name": "thelia/atos-module", + "license": "GPL-3.0+", + "type": "thelia-module", + "require": { + "thelia/installer": "~1.1" + }, + "extra": { + "installer-name": "Atos" + } +} diff --git a/local/modules/Atos/logo/1EUROCOM.gif b/local/modules/Atos/logo/1EUROCOM.gif new file mode 100644 index 0000000000000000000000000000000000000000..37bd942ef31c90d50cd0026c6cf89568694be395 GIT binary patch literal 1484 zcmWlWe@s?Y7{~9+n|XWHw}Ya1oEZ#LuCnG4n1V4uMePn7TnqJRHW~iBw#;kG`5L}X z#KhZ3y(;L*5O|dz9+lW_CStNA3Fj5HXgWDLlcU+zVY%X;@a=H^_&#UPzUO?C0)0UNE-5YXB(bXZR%7M*+>QUfu?8tn=Ne_1@CPXR_1KhF+ zA8@rq=rB#22Z>89!7P(m0&6Blf+3S3fh`Rq%8`Om%L(C0f7cm!MHw0ZoTm*F!8pBXsHm{1gQks zGK5$#}oS|mgTMLaab*&8xQk$|K@<;dnp0zwW& zstTP*X@se+B-O^r0Cy#+HmQIR+U8O!G}AOY1f@Nih;)zv>dII0CtWvnQ!_Qo)HPGp zRMi$LABaXpRE;V=b>iX+)$M!KG1FFcUO4r`K9Ho7#mzMx2gavvdeGTid%a@V!~L;K z%MwyUzH48Ox%6O6cMRBV;*7bKSxvdAotu;&DWAjHnXwK?fvNC4*4xCU~GyBaKzkhlx z?`dmMT>GBk+ooo8w-gjc2hWmAS@)C;2lkf~Z2qVzsVR_>e`vk3HEl35d08;~v2qyZ z#|2_Oi;aKv4o$nWYQepw*RqQH=Lb_?)EzlgSmGO-z4Gvp_FHAedEGtlL-fxiC3jVN zu0A-JGj7Gz=6E=_tKcYHR+O;);N0nME(q@YqOLQ$Z^PPmmGt|Q7v}VXUka6{8;Wak zhNbOUozt7~vpr{7QQgBs{=V)Cg{xae=KSq!^s4;5GZv0tV<(1{SxWz2V&17MC|)pX z@)Hv7@@J0^kDE~T)!r$MPZth*s8np8m8_qhyH+nxu0B$PlTS?YWtL^HnfSZ|g(vAx z$*i5e`jg>rRy0&kYG}?plM_Cf3L0YU#3sdmWLkHIRr2h1!{u?0r`KD@Tg>y;k4gD; zF;~kA>T80>Q|QfL+$}QLxhdGfCkB)YF_&u#PNn&trQ~c6jL2@f5vcpCrF~uLpJe^I z9V5?O2d%u)DvK4ZzPsk>w#xgL%u~O0CH+z5e|-dPjUSuY9bXmbrr86JZk+utCL<+$ q@=Q-dELmRSJ99Dq{O0`eD}s&dcc<(setvWIle5pgx2DGdWzPS*NUziY literal 0 HcmV?d00001 diff --git a/local/modules/Atos/logo/AMEX.gif b/local/modules/Atos/logo/AMEX.gif new file mode 100644 index 0000000000000000000000000000000000000000..507d52ca22ad3535186d18177b5e20077bc6cc9e GIT binary patch literal 1954 zcmdUu|65bn9mj7%0zp_z5Ex&QkVHTd=^nykEvTJIgka*AN=hB1c8Z~5o3y2i?RXle zNel^wv;tn0>a~LQKDvk98IWVK?Og+t1E{-2w%ztwdG3G*4Xay&Jhq|EHM>0BKe6-6 z`JD6ld|vO*IiGW?jE1uE`cmX6Bo;^F@i;|M48uesk!Um;i^ZbLMueT?@fb~0(HOgq zL}SrdJO(L9(G(M5qVXtXAVC2p8UZwaSD0?@jq5PPXCCG#aInG!e&Mx zO#=u?ilSMYVW>!iWOrzqpePJN2SGS+!iEzB&EOP`K`KZ>l!Sn02#V!XUXpSGHjJdB zF)9)zX$DX<0Vx#HLDof(7M!glf>R6zX(tXGfU*(Lijx)$m{9^HsUUz(Ksg9#!$~~~ z%7cW)i;El>6OGX;J z2SK@)&^U387bu)W)^a?KSTR7ccS{EWN}85afXYcI9C((45ZQ2n z6+$RX5Nuz*rE=xmGkkoqtV!?ud_Oe)vw4uO(Q&yBj z%qSCy(vcW|G-3+=*nWy;*!CkP*2O-PIP(8L!r`#udmaZt;z;rGX_o(lRuD%x0$zK= zN#%}!u(0AvNbyI1%IXd171at)Vgg6oaVm6a^n`p%;K`uc$K_;yHML|-S?OATUG#2k zb=B?@wY~GT`x^>QC@Nc;C9{q-CvZjo`aca8*fQGd`c0C*HKg6s7A0U=RvEa?7hT&|(j8KZ9*lkFil5$eBl+_WEBOg)fBCzE zC41kk%iboeOB;3tkF2qMSGzcL&s}z3l3l7yJ+DQub;gC!MDYe+@x6l=R}0!Vm;X>! zq#qTg%eAj|{dR7~)m8qH@U0)Fp83`23snny9?#w1DgD{mSKt0RRG1<)7PyMyUw5>2 zo-;hHtu{8`z1>6Nl8t}glzqhDPR@}Rx%M4B8voD3*aa6ySUc_hw^Z&#MSV-L>?*>`?e^rTqXpqm&)U@(5(5XF0h_ z|5&TP;N`B4QFU(V87=q7yx6F;uJibFF9qwNq~=MF(SE+B&m`+dl$d-s686jX3;M^E z=a7!kjKIPA(!&QTFsxr&(DR66%zv&)q;2`dOM=P#0aD}ga=H^KD4)7j)q8Rwi zx93WXxw5II4|>0>>l;aL#4evte%US>$y{sx7k1`Qh@Y2zr=OqP^h7tDxjGoC6zN>; z@Xm`L>bNP=sXcAuYS+F+L9sVfnfZnR6AR0V_6KCep}ymVMx=gM{!V$PPb8h-_%fTO zXZ(ttSWioW-&G2;uG!80f~v9EEt74+njz`wu*Ros+!J5iaPuJ%L-l@?*Q(A$qZU*X?{@ zzxz1l*}>_@(m?nREkXm*SNYTCG4o%;a*d8B-dLOm3*QLc-6Zbt4#7op>ZBp}b`ZB<>v=g@L%CNb+&cTkRWF5gX-6w25;M0Bt=!@A@RNXem(uL{#%g$&2xwmv*cgE)e4gXV7z5VdCj~8BHzA~JUd;F3l zL&T}R$rWGQ>UnCNVN9R1*e*LcvN~Ps3QGQgB(=Ko*BHl5mc`C4bPh?JKvwd2$j1Ky DoT6mh literal 0 HcmV?d00001 diff --git a/local/modules/Atos/logo/AURORE.gif b/local/modules/Atos/logo/AURORE.gif new file mode 100644 index 0000000000000000000000000000000000000000..3807ef7c327e8a24610d61a59fdbbedf25659640 GIT binary patch literal 1513 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 literal 0 HcmV?d00001 diff --git a/local/modules/Atos/logo/CB.gif b/local/modules/Atos/logo/CB.gif new file mode 100644 index 0000000000000000000000000000000000000000..cbbd626d0b44ff47ee17835bfaf9e3ad1fcec54b GIT binary patch literal 1867 zcmchW{Zkb88Niq0W$+Hp;}Bdx3M&Lz0v;QTdZG?2BInwf$c|O#FyzPqo~|h5tTAjX za4auT;|s2DnJ?ueT%yAArYl7_!%N+O(ABi*nuhiot@W6K9+T3XCKC(GvE2n zGtc*VzCS!q-nOml^+oHT1jq|50>c=BzzBjO2&O>@6oq|P3`I~B!%#hf;uwm^DaU(zr zIjqouQ5>-k7+KQDkrYqTPO{`;m6Zcl+JRHP5J&pHLOb=0fL9G0Str4Y6mXJ2G&)4H zL$q={#fc6h>V{!AjJi>uxF;C$Xdo{Nd2vW4eQLZo>>*Jvsb`J2Yz~$w4NoC13gIYJ zwxYmFdT7#1TV>iRGMLN|fU(L9E3>e~>KS$s8K4{hvV)Kur0lRdI1+F)&jE&~B%Wq? zhT#G0WEp`30x1e4BTzuF$`U3^xL2ZO7cKEX5`aepUK+5BL*^U~fs@^wEOQLt8J=eZ zo@IHK_f_S6NFwhMd9TaK0097j1A@#83@@@y5eOnLilS3=OQOdu%AzQHMOhXZLE?Px zL`iZAK>)roBtF-W@jz#$8W0T}bjaq~|MgtIo@Y^z1sV z!g!U@%2;-@Eid)hmg9t`G&ell<|jn#GS$@8MHUWUjWAVDBMrMv755rro8Z>^SaLm5 zRI)eB+_3u;B7D63ctss-uCB=6BF*gyiYlN)U?&LzUdZTSMc|L5SaXv-G#wJoI} zyEvM-k^N0{Y4x_PQ3u*8gbRCGYo6sei$B|M>ZA8{zSV_czX-|L;u$1+GykS)icEXc}sJdVZ+za_FsI9emZ5UEYVFKF|N|t zwL(h!LUU(PSjH{szzp|0*PS5U^&7(zUA^l6yxv_lkEiIqO>Cd-ojCNT?J*_2cV=2g z)RZNoEqZkJ_WjNCDqZu@AKTl@s()&~Uirr8^E*px3SJC!sxv!!j{nfRx^K#2F6;k# z!@N=_iv@>cyqzH zy9Vd~xVEczJjp)RG@i7pfctgQm7R(c%ddRcv@PM2olPGlz1g&w@>|ZBs0Ex;P1bE z6kq$|r0$Djo{YVsV*aal)T7F~4nC1zYO^+zbhD4n&xZ~-4Kl)^IOpwF zQ5w4y3;UPWMy)XYM3&o@4Q2f%)sU?$DYwmCIGmia^YN3<-p?GXPzS|K+Cz5DDHg7O z7nnMjS+m42W(#L`1m+$rQsvu6BCcfxrX-%sG34Hh3vEMGma}gM1VB*ce*wd< BDM0`L literal 0 HcmV?d00001 diff --git a/local/modules/Atos/logo/CLEF.gif b/local/modules/Atos/logo/CLEF.gif new file mode 100644 index 0000000000000000000000000000000000000000..8b791b612c5ba1956b13dc3af1d0b6f337b13196 GIT binary patch literal 1254 zcmc(e{cF=#6vj`qshLxV)iO8YnzpFKxDj?LxVpi&ZjGs(7H3Urnw2Ver^V`~wT21K z7p5{0R%xxbx*El|si4&e&cSBaRiwM1MeVv5q2ScED6HFxa}3X(oBa{Hzula3p7VL0 z`^|!~@Z8r|ET$ZKLjN5mQbd}_5D6|!%%qq!lVK9n6tNSv{FVXfjw-+MJuh9 z(MsSJ5U3fYjWR|F;s7OvMQKq+tUts7N(>_p1ON(H1T?fj4NUX`1e+lZZHS5OwU+P$ zj?r3>BkW--E=C)p1wq3FbocqCG%qTbFhXpFN~P&i)LQQV%gx~-bQQV$fN~i``#JH z7TTJClEt)PWi|^AzK_f_+EKS3%l~uopJus;&eCkV-u@>X&of&7oG)@d)w$C%c~;{3 z2dS2&UiYCocWr~K~_=B~P^q_Mj^2v;JPNcA4`^n1_A_vZ#zH_GPVqJG}gFiPKdcSc~vZtWciO!F^ zLgd7QTP}Nk?H_4NfAz||;k!Riy82%8=H*u&E$m)5&{cVD{_&}M3QC=&dl$B^ExH*v zuqXQYj(1wlJ-qSJld1c!_4L$qZ{0N`{8y+hkzQS$efLyrd7`;&<5=(G3(i2N`}w@^ z8_^qqsQ=5sp_~omr|(C-$EpY7<(;Xg!+qt+KYzRJ>HRMLV#Tw$_x~8|s!ksr_xQo} zp?j16`Dw$YZ+C~vJBnAizb+a6(Y^X$eS1J1cE-Kb9Ibpb(lEZ_(~dE<+uA=|5esko ztnc7<>Tm9kWxH374<;%bd~d%S2)AzTx|FP1|IKLbFLR3estS|tmPk{;yQHY;<@(;} z59_boZ=CqTtKHeYlC6n*`HRjDM7)0QvNbD%v8-HA*~Xzc@tP@rmloF4HZHiOxnp0- jnckk9{&D@L{AneneQQpx>pb$s!?xc?hh_#{E}Hi*u1*qI_*fXIs=C^#rY4CGFbZ74!xjDZSQ1cY=*1_XwKfebtZ zj1UDS8|Y#t$iShz1$P07CVG`=20DkC#yb@+LD@R?SMNUXt$HZNIx+H#P{*`tOm#!o=S>x!=zoO| z8IGxnWtk1W{$&oCfghZ?Ypr~)d#Ml9yy|JY2h`}F>&IjQ%5C4Ex~{K?<``1TZK)q9VZ0Y>Mnf)g%4t+C z!?g}0$;|0aEEHJ}%gi?HLmBqkJLNPVn#iD)hJ9t~v|%@|4!lWPO@DvG;|g?0Y3exG zzns<(W+A$^A^^q=g_nF_hfY%j=$&=^&8A7KImpFVjeWBgF%?HqMOQYr5$&<*UPx-4+D`CCXFB3XqUAvPnQWKVTieq3ARdAq z{gx|H%yL(@WN3RW(=h3E$oz;G8S>1zO4@XAf>q8?H>PzB?_8=R!^Chvh(DUV)@}D< zulRF2T6hy=yWHgt`L%Au2}J9YX`Obe-7dp~(((De5=qP~MCB@!6@Cl55fYQwCT%+| zQ7__l33Eq9FuQb;?O`Rm+~RuJc-uRE$T?_>MrWBY-&0KXztqDr5gZFpN z1lGn|Zrwr8G2e0@vMp=xIbL=rs|x0X;vmIp^(TEQpVPi~sTr}0FA0fg(_`BF%xAL_ zM|9(A7ovMzSP=DF_Cm9KB%B;z)*pB(xn6xU09a$n99e~R6_OrMg- zuN)othYdfWFK4xHUsTQMLZhF8kKXZ(>$<0zeAx4yGgud@a4aDJWH%rn)qXh;&p#KcI@qD!L`>3u%yfFLDz*^OgKk~-hr#XFI zOyh;j%V$zB$Sr43~Z7FZ;I= Q)a)YTCO5d0NCZCk7lYyxY5)KL literal 0 HcmV?d00001 diff --git a/local/modules/Atos/logo/ELV.gif b/local/modules/Atos/logo/ELV.gif new file mode 100644 index 0000000000000000000000000000000000000000..886b1a1930e083c112fd8efb2e08a5888b86698d GIT binary patch literal 682 zcmV;b0#*G-Nk%w1VJHA70K@407cgf_jv9VgX+x~MX05EQZ z0(-3lTYwoE82|tPA^8La6aW$cEC2ui04M+`000I5pd<-|VxDNKt|=jo=0VJKZQnTU zIEnepH zf0~?>432m!Et(u$wg`SB3r;QZ@LXx8czI?!$g2TnK3AM{Y38Kr< zm%$bc2W!_K#{;z(kUsA1899_Z`DMVMT z1q1d$VmUBShL<6Y4e7=&!9D{3h>F{UG-i+ijT}Aj230DxKvj7P3Azs69k2E7iOrQT zE3Y7E3941PwCvlcI9tjEnG}(LzYDWwZ5P*q6$kdtd6>XhW}}q23TK$?ps%Mxj?Kc& zThu75%ZEI06I^PurJTY(gBBea6;#vnroOW5i8aYlDusBR%=;*S37|do{5OOs0R}0^ z0YCtOvGWNdo8w33?MTYSlB+C^jy8yh`|~FsaqTg literal 0 HcmV?d00001 diff --git a/local/modules/Atos/logo/JCB.gif b/local/modules/Atos/logo/JCB.gif new file mode 100644 index 0000000000000000000000000000000000000000..4f51970fc687fcdc4a5efb394e71ba9c8a506c77 GIT binary patch literal 1343 zcmXAoeQ4KJ6vodsH8;gff4-$?tE0I{YBgVGFHD>1)s}8{Y~jkL(+oZMN4_*M*=EyV zCV6mVU#NFjBiXp*EbCB524i6JzIe1AQCe|7)3T)6P?oaghL@!{oBBP;vE zqi_TMKLnrv4hVn*sDKUuAP@wF;J^S(zzXaj074)N;$Q$qU<&3C0U|+Eh@L2c6S#tV zS`r9B5gZW^2~iOp17IKwiouZqnUEFPQ2>Qd6vfd1jnEX$F#<-ys2DwQhfe5!~I2*7Lo3c4a;7A;mqbDh{6T7l|I!+(~ z6>vciBtaE)2_S(as00@VVG>qh7Xc9xQ4tpdF%nZTmk1I`qDu6Hj5vv_xTg^T8K{99 zf*~2Ip<4h8WI-*sF&LAv8oLRYkcpbO8JLlonz===NEX$iC$!DUT+Ka=9VmiE@Q4tR zB5FjB0b-ySGzO0hktwo9_9zgAqG%M42GJ;*M)MdUMv75m^rS)2DY{1Ybd`V{G-*{* zCP#AAqyY(d59C1;S_vd)a@Hi-Bv2P}(IkarcsFv>#BpNOBYD(BJrQ*$cTHZow>tc{ z15c*!^iC9YPJY|_-<;gGzpk}gx97`uwT-Rw3Cr$WpBytg_UToS)oIORyE=94TQK+F zrnV%ptA%&1sD4Ys&YGXrZdEqx88w*-~Rk%+o6r0X55^#ucd9|>Mp(ElgFp-+;adA zH0{W#-gLI1%ZR0Se}&rCRHvsV4V!-Q^!_!^Ouu+_j?p?xCw6SNZPT z_0=0DPCLEyQr@*Mzt~&y+LZN0C5KbBr4J9VR8?mC(bLO17uHMF#a^=qX5Y^(NM&!? KxVfwdp8FS2_kY6x literal 0 HcmV?d00001 diff --git a/local/modules/Atos/logo/MASTERCARD.gif b/local/modules/Atos/logo/MASTERCARD.gif new file mode 100644 index 0000000000000000000000000000000000000000..9dc0ccfdfee00ef260de87d1e87bcc3384cdcb4c GIT binary patch literal 1174 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 literal 0 HcmV?d00001 diff --git a/local/modules/Atos/logo/PAYPAL.gif b/local/modules/Atos/logo/PAYPAL.gif new file mode 100644 index 0000000000000000000000000000000000000000..2a5871650a7192df985c5435f75486f546c315a4 GIT binary patch literal 956 zcmV;t14H~rNk%w1VLSjP0M!5h|CuwDsI~m)!vFvOo3O(E`tkeYvS)UT8#ZM8?9BY> z#xY57{`czs^y4#Tm&eD%Mp=6O^4$II(f|DS`{uj<{rdj<_5c6={O7*=;ja7Sw*L6- z|Ni{@<+%Lo%E-gFw86;Z+sks2tc{kY*2KN7;nTTHcb>k* z!qd&bA^8LV00000EC2ui06YLD000L6K!9*aEELp zV5;y!E}PHjw0g}h3pwz(d`_?1@A$Z|!teY4fPsR8gndF2h>41ejE#55tzUx|-B^_P25v<>1S;%}1ZUB~ z!v-x)v_xkDMuUb9NMx*M??AWzmp&2bBPsOchz2?qbbEmFhCQ4Ca;S@et_F>BISe)s z5}~V7c_o4(C{bcXR}~@gAvh2L{Iv++mrrD;e&ToYZXdX}2>D?= zI0?bO%>a&$Id$DNZp2)1&II@F03=B8CPTk}<0KuRpLs&*_rN(l_~%~=k-ekBI|}M2 z#DFc#5TSl3=+i=ZE&Pz#fCK=B@SzL=1mMGk5>#eF3O|%6!wN25C`1A@)@b96I3}Q6 z3pw`aV~;|3Amorl7HQ-Rjmco-l1w%!q!0>3Ddm(@R{7NoRc5K>mQq5=C6_`m}aW!q(W%m>8GHED(a}DmTKy!LKvXxs;su^>Z`EED(kAL&T8we exV|bx2E6v_>#x8DE9|hu_PWHe$R@i)5CA*Ec=mMw literal 0 HcmV?d00001 diff --git a/local/modules/Atos/logo/VISA.gif b/local/modules/Atos/logo/VISA.gif new file mode 100644 index 0000000000000000000000000000000000000000..cd93a68f9c9b3c713281639331ff82e2a62bbbaa GIT binary patch literal 1389 zcmZ?wbhEHbG-ps|_|Cxa9|*pGPj)ig>csFonc;o4!24o`_fs_A&oO+z)bRiR=l}no z`~QFMz4!m;Y`wO2@3rbFdo7cfDtb*3ux#0S?D>?X$Ie}Q9#y=S!>~ufvPZ(OIx2gq zfMzv^Vljh6u~X2LmY%KI#dA0$l8dX?MkUV)ikiZ}k-T;5xur|@1_kvnFeoxG7&0(8 zF)#$RR4*+~p7Q_ue}+*o8UpkR0mYvzj0_CS3_2hSL3x6K;~xY25ebhC3l27O2y6Lh z7_c?83n+Wd@z}WNXeWz))}0d*A024dj@TmMIjQyJWR2i1lbcPcrzdJAE(&@0;GsK% zu2IU21DlthpYPDjC3K_$MBaV|eDe{9>8V!~`bxUzHuf*+Nqjnp!uinm5&c$b8}yr2WC{VV$7Q z7Dx7rOARii>lP#|a#e79!c?GE!*H?YJL7`J7G91_DQ-EF3k(bj2Yw{h2=9F$#x1yZ zN<7cxtpbxccsmw2l`^c^?$jf0tKi6K=4au^sbCY*$Rb=Ia4<*2XM(beNXmjI)B03z z1y1ZTTP4oGrl9b0$&|3HmrG})bvZB!+;wqaT+pWVYQ>UiS+7>I3LH4Fm__EntJOXm zj%mGKv*lV<10(l_tk>)IeCt}hZZDhmo7MZfz6Pv5taf@e<7z2x21Yg)?YCR5gk`_o idPB;=Vcj{aSGg{dwZGpw@am?#+xbGu#KD1q!5RQ1a8JGf literal 0 HcmV?d00001 diff --git a/local/modules/Atos/templates/backOffice/default/atos/module-configuration.html b/local/modules/Atos/templates/backOffice/default/atos/module-configuration.html new file mode 100644 index 00000000..27227cf8 --- /dev/null +++ b/local/modules/Atos/templates/backOffice/default/atos/module-configuration.html @@ -0,0 +1,120 @@ + diff --git a/local/modules/Atos/templates/email/default/atos-payment-confirmation.html b/local/modules/Atos/templates/email/default/atos-payment-confirmation.html new file mode 100644 index 00000000..db3db83b --- /dev/null +++ b/local/modules/Atos/templates/email/default/atos-payment-confirmation.html @@ -0,0 +1,23 @@ +{extends file="email-layout.tpl"} + +{* Do not provide a "Open in browser" link *} +{block name="browser"}{/block} +{* No pre-header *} +{block name="pre-header"}{/block} + +{* Subject *} +{block name="email-subject"}{intl d='atos.email.default' l="Payment of your order %ref" ref=$order_ref}{/block} + +{* Title *} +{block name="email-title"}{intl d='atos.email.default' l="The payment of your order %ref with SIPS Atos is confirmed" ref=$order_ref}{/block} + +{* Content *} +{block name="email-content"} +

+ + {intl l="View this order in your account at %shop_name" shop_name={config key="store_name"}} + +

+

{intl d='atos.email.default' l='Thank you again for your purchase.'}

+

{intl d='atos.email.default' l='The %store_name team.' store_name={config key="store_name"}}

+{/block} diff --git a/local/modules/Atos/templates/email/default/atos-payment-confirmation.txt b/local/modules/Atos/templates/email/default/atos-payment-confirmation.txt new file mode 100644 index 00000000..588a1971 --- /dev/null +++ b/local/modules/Atos/templates/email/default/atos-payment-confirmation.txt @@ -0,0 +1,9 @@ +{intl d='atos.email.default' l='Dear customer'}, + +{intl d='atos.email.default' l='This is a confirmation of the payment of your order %ref with SIPS-Atos on our shop.' ref=$order_ref} + +{intl d='atos.email.default' l='Your invoice is now available in your customer account at %url.'} url={config key="url_site"}} + +{intl d='atos.email.default' l='Thank you again for your purchase.'} + +{intl d='atos.email.default' l='The %store_name team.' store_name={config key="store_name"}} \ No newline at end of file diff --git a/local/modules/Atos/templates/frontOffice/default/atos/payment.html b/local/modules/Atos/templates/frontOffice/default/atos/payment.html new file mode 100644 index 00000000..1787423f --- /dev/null +++ b/local/modules/Atos/templates/frontOffice/default/atos/payment.html @@ -0,0 +1,7 @@ +ATOS - Paiement Securise sur Internet + + +

PAIEMENT SECURISE ATOS



+

{$site_name}



+ {$form nofilter} + \ No newline at end of file diff --git a/local/modules/Atos/templates/frontOffice/default/payment.html b/local/modules/Atos/templates/frontOffice/default/payment.html new file mode 100644 index 00000000..1787423f --- /dev/null +++ b/local/modules/Atos/templates/frontOffice/default/payment.html @@ -0,0 +1,7 @@ +ATOS - Paiement Securise sur Internet + + +

PAIEMENT SECURISE ATOS



+

{$site_name}



+ {$form nofilter} + \ No newline at end of file diff --git a/local/modules/CustomerFamily/Config/config.xml b/local/modules/CustomerFamily/Config/config.xml new file mode 100644 index 00000000..900767f3 --- /dev/null +++ b/local/modules/CustomerFamily/Config/config.xml @@ -0,0 +1,167 @@ + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/local/modules/CustomerFamily/Config/module.xml b/local/modules/CustomerFamily/Config/module.xml new file mode 100644 index 00000000..0141fb50 --- /dev/null +++ b/local/modules/CustomerFamily/Config/module.xml @@ -0,0 +1,18 @@ + + + CustomerFamily\CustomerFamily + + Customer Family and Purchase Price + + + Famille de clients et prix d'achat + + 1.5.5 + + Guillaume Barral / Etienne Perriere + gbarral@openstudio.fr / eperriere@openstudio.fr + + classic + 2.3.0 + prod + diff --git a/local/modules/CustomerFamily/Config/routing.xml b/local/modules/CustomerFamily/Config/routing.xml new file mode 100644 index 00000000..0e7379bd --- /dev/null +++ b/local/modules/CustomerFamily/Config/routing.xml @@ -0,0 +1,56 @@ + + + + + + CustomerFamily\Controller\Admin\CustomerFamilyAdminController::viewAction + + + + + CustomerFamily\Controller\Admin\CustomerFamilyAdminController::createAction + + + + CustomerFamily\Controller\Admin\CustomerFamilyAdminController::updateAction + \d+ + + + + CustomerFamily\Controller\Admin\CustomerFamilyAdminController::updateDefaultAction + + + + CustomerFamily\Controller\Admin\CustomerFamilyAdminController::deleteAction + \d+ + + + + CustomerFamily\Controller\Admin\CustomerFamilyAdminController::customerUpdateAction + + + + + CustomerFamily\Controller\Admin\CustomerFamilyPriceController::updateAction + + + + CustomerFamily\Controller\Admin\CustomerFamilyPriceController::calculatePricesAction + + + + CustomerFamily\Controller\Admin\CustomerFamilyPriceController::updatePriceModeAction + + + + CustomerFamily\Controller\Admin\CustomerFamilyAdminController::saveCustomerFamilyCategoryRestriction + \d+ + + + + CustomerFamily\Controller\Admin\CustomerFamilyAdminController::saveCustomerFamilyBrandRestriction + \d+ + + diff --git a/local/modules/CustomerFamily/Config/schema.xml b/local/modules/CustomerFamily/Config/schema.xml new file mode 100644 index 00000000..184bd1e6 --- /dev/null +++ b/local/modules/CustomerFamily/Config/schema.xml @@ -0,0 +1,116 @@ + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + +
+ + + + + + + + + + + + +
+ + + + + + + + + + + +
+ + + + + + + + +
+ + + + + + + + + + +
+ + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + +
+ + +
diff --git a/local/modules/CustomerFamily/Config/sqldb.map b/local/modules/CustomerFamily/Config/sqldb.map new file mode 100644 index 00000000..63a93baa --- /dev/null +++ b/local/modules/CustomerFamily/Config/sqldb.map @@ -0,0 +1,2 @@ +# Sqlfile -> Database map +thelia.sql=thelia diff --git a/local/modules/CustomerFamily/Config/thelia.sql b/local/modules/CustomerFamily/Config/thelia.sql new file mode 100644 index 00000000..908b6601 --- /dev/null +++ b/local/modules/CustomerFamily/Config/thelia.sql @@ -0,0 +1,207 @@ + +# 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; + +-- --------------------------------------------------------------------- +-- customer_family +-- --------------------------------------------------------------------- + +DROP TABLE IF EXISTS `customer_family`; + +CREATE TABLE `customer_family` +( + `id` INTEGER NOT NULL AUTO_INCREMENT, + `code` VARCHAR(45) NOT NULL, + `category_restriction_enabled` TINYINT DEFAULT 0, + `brand_restriction_enabled` TINYINT DEFAULT 0, + `is_default` TINYINT, + `created_at` DATETIME, + `updated_at` DATETIME, + PRIMARY KEY (`id`), + UNIQUE INDEX `customer_family_U_1` (`code`) +) ENGINE=InnoDB; + +-- --------------------------------------------------------------------- +-- customer_customer_family +-- --------------------------------------------------------------------- + +DROP TABLE IF EXISTS `customer_customer_family`; + +CREATE TABLE `customer_customer_family` +( + `customer_id` INTEGER NOT NULL, + `customer_family_id` INTEGER NOT NULL, + `siret` VARCHAR(50), + `vat` VARCHAR(50), + PRIMARY KEY (`customer_id`), + INDEX `idx_customer_customer_family_customer_family_id` (`customer_family_id`), + CONSTRAINT `customer_customer_family_FK_1` + FOREIGN KEY (`customer_id`) + REFERENCES `customer` (`id`) + ON DELETE CASCADE, + CONSTRAINT `customer_customer_family_FK_2` + FOREIGN KEY (`customer_family_id`) + REFERENCES `customer_family` (`id`) + ON DELETE CASCADE +) ENGINE=InnoDB; + +-- --------------------------------------------------------------------- +-- customer_family_price +-- --------------------------------------------------------------------- + +DROP TABLE IF EXISTS `customer_family_price`; + +CREATE TABLE `customer_family_price` +( + `customer_family_id` INTEGER NOT NULL, + `promo` TINYINT DEFAULT 0 NOT NULL, + `use_equation` TINYINT DEFAULT 0 NOT NULL, + `amount_added_before` DECIMAL(16,6) DEFAULT 0, + `amount_added_after` DECIMAL(16,6) DEFAULT 0, + `multiplication_coefficient` DECIMAL(16,6) DEFAULT 1, + `is_taxed` TINYINT DEFAULT 1 NOT NULL, + PRIMARY KEY (`customer_family_id`,`promo`), + CONSTRAINT `fk_customer_family_id` + FOREIGN KEY (`customer_family_id`) + REFERENCES `customer_family` (`id`) + ON UPDATE RESTRICT + ON DELETE CASCADE +) ENGINE=InnoDB; + +-- --------------------------------------------------------------------- +-- product_purchase_price +-- --------------------------------------------------------------------- + +DROP TABLE IF EXISTS `product_purchase_price`; + +CREATE TABLE `product_purchase_price` +( + `product_sale_elements_id` INTEGER NOT NULL, + `currency_id` INTEGER NOT NULL, + `purchase_price` DECIMAL(16,6) DEFAULT 0, + PRIMARY KEY (`product_sale_elements_id`,`currency_id`), + INDEX `FI_currency_id` (`currency_id`), + CONSTRAINT `fk_product_sale_elements_id` + FOREIGN KEY (`product_sale_elements_id`) + REFERENCES `product_sale_elements` (`id`) + ON UPDATE RESTRICT + ON DELETE CASCADE, + CONSTRAINT `fk_currency_id` + FOREIGN KEY (`currency_id`) + REFERENCES `currency` (`id`) + ON UPDATE RESTRICT + ON DELETE CASCADE +) ENGINE=InnoDB; + +-- --------------------------------------------------------------------- +-- order_product_purchase_price +-- --------------------------------------------------------------------- + +DROP TABLE IF EXISTS `order_product_purchase_price`; + +CREATE TABLE `order_product_purchase_price` +( + `order_product_id` INTEGER NOT NULL, + `purchase_price` DECIMAL(16,6) DEFAULT 0, + `sale_day_equation` TEXT NOT NULL, + PRIMARY KEY (`order_product_id`), + CONSTRAINT `fk_order_product_id` + FOREIGN KEY (`order_product_id`) + REFERENCES `order_product` (`id`) + ON UPDATE RESTRICT + ON DELETE CASCADE +) ENGINE=InnoDB; + +-- --------------------------------------------------------------------- +-- customer_family_order +-- --------------------------------------------------------------------- + +DROP TABLE IF EXISTS `customer_family_order`; + +CREATE TABLE `customer_family_order` +( + `order_id` INTEGER NOT NULL, + `customer_family_id` INTEGER NOT NULL, + PRIMARY KEY (`order_id`), + INDEX `FI_customer_family_order_customer_family_id` (`customer_family_id`), + CONSTRAINT `fk_customer_family_order_customer_family_order_id` + FOREIGN KEY (`order_id`) + REFERENCES `order` (`id`) + ON DELETE CASCADE, + CONSTRAINT `fk_customer_family_order_customer_family_id` + FOREIGN KEY (`customer_family_id`) + REFERENCES `customer_family` (`id`) + ON UPDATE CASCADE +) ENGINE=InnoDB; + +-- --------------------------------------------------------------------- +-- customer_family_available_category +-- --------------------------------------------------------------------- + +DROP TABLE IF EXISTS `customer_family_available_category`; + +CREATE TABLE `customer_family_available_category` +( + `customer_family_id` INTEGER NOT NULL, + `category_id` INTEGER NOT NULL, + PRIMARY KEY (`customer_family_id`,`category_id`), + INDEX `idx_customer_family_available_category_customer_family_id` (`customer_family_id`), + INDEX `idx_customer_family_available_category_category_id` (`category_id`), + CONSTRAINT `fk_customer_family_available_category_customer_family_id` + FOREIGN KEY (`customer_family_id`) + REFERENCES `customer_family` (`id`) + ON UPDATE CASCADE + ON DELETE CASCADE, + CONSTRAINT `fk_customer_family_available_category_category_id` + FOREIGN KEY (`category_id`) + REFERENCES `category` (`id`) + ON UPDATE CASCADE + ON DELETE CASCADE +) ENGINE=InnoDB; + +-- --------------------------------------------------------------------- +-- customer_family_available_brand +-- --------------------------------------------------------------------- + +DROP TABLE IF EXISTS `customer_family_available_brand`; + +CREATE TABLE `customer_family_available_brand` +( + `customer_family_id` INTEGER NOT NULL, + `brand_id` INTEGER NOT NULL, + PRIMARY KEY (`customer_family_id`,`brand_id`), + INDEX `idx_customer_family_available_brand_customer_family_id` (`customer_family_id`), + INDEX `idx_customer_family_available_brand_brand_id` (`brand_id`), + CONSTRAINT `fk_customer_family_available_brand_customer_family_id` + FOREIGN KEY (`customer_family_id`) + REFERENCES `customer_family` (`id`) + ON UPDATE CASCADE + ON DELETE CASCADE, + CONSTRAINT `fk_customer_family_available_brand_brand_id` + FOREIGN KEY (`brand_id`) + REFERENCES `brand` (`id`) + ON UPDATE CASCADE + ON DELETE CASCADE +) ENGINE=InnoDB; + +-- --------------------------------------------------------------------- +-- customer_family_i18n +-- --------------------------------------------------------------------- + +DROP TABLE IF EXISTS `customer_family_i18n`; + +CREATE TABLE `customer_family_i18n` +( + `id` INTEGER NOT NULL, + `locale` VARCHAR(5) DEFAULT 'en_US' NOT NULL, + `title` VARCHAR(255), + PRIMARY KEY (`id`,`locale`), + CONSTRAINT `customer_family_i18n_FK_1` + FOREIGN KEY (`id`) + REFERENCES `customer_family` (`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/CustomerFamily/Config/update/1.3.12.sql b/local/modules/CustomerFamily/Config/update/1.3.12.sql new file mode 100644 index 00000000..2bbf3393 --- /dev/null +++ b/local/modules/CustomerFamily/Config/update/1.3.12.sql @@ -0,0 +1,16 @@ +CREATE TABLE IF NOT EXISTS `customer_family_order` +( + `order_id` INTEGER NOT NULL, + `customer_family_id` INTEGER NOT NULL, + PRIMARY KEY (`order_id`), + INDEX `FI_customer_family_order_customer_family_id` (`customer_family_id`), + CONSTRAINT `fk_customer_family_order_customer_family_order_id` + FOREIGN KEY (`order_id`) + REFERENCES `order` (`id`) + ON DELETE CASCADE, + CONSTRAINT `fk_customer_family_order_customer_family_id` + FOREIGN KEY (`customer_family_id`) + REFERENCES `customer_family` (`id`) + ON UPDATE CASCADE +) ENGINE=InnoDB; + diff --git a/local/modules/CustomerFamily/Config/update/1.3.sql b/local/modules/CustomerFamily/Config/update/1.3.sql new file mode 100644 index 00000000..cbf241c4 --- /dev/null +++ b/local/modules/CustomerFamily/Config/update/1.3.sql @@ -0,0 +1,93 @@ +# 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; + +-- --------------------------------------------------------------------- +-- customer_family +-- --------------------------------------------------------------------- + +ALTER TABLE `customer_family` ADD `is_default` TINYINT AFTER `code`; + +-- --------------------------------------------------------------------- +-- customer_family_price +-- --------------------------------------------------------------------- + +CREATE TABLE IF NOT EXISTS `customer_family_price` +( + `customer_family_id` INTEGER NOT NULL, + `promo` TINYINT DEFAULT 0 NOT NULL, + `use_equation` TINYINT DEFAULT 0 NOT NULL, + `amount_added_before` DECIMAL(16,6) DEFAULT 0, + `amount_added_after` DECIMAL(16,6) DEFAULT 0, + `multiplication_coefficient` DECIMAL(16,6) DEFAULT 1, + `is_taxed` TINYINT DEFAULT 1 NOT NULL, + PRIMARY KEY (`customer_family_id`,`promo`), + CONSTRAINT `fk_customer_family_id` + FOREIGN KEY (`customer_family_id`) + REFERENCES `customer_family` (`id`) + ON UPDATE RESTRICT + ON DELETE CASCADE +) ENGINE=InnoDB; + +-- --------------------------------------------------------------------- +-- product_purchase_price +-- --------------------------------------------------------------------- + +CREATE TABLE IF NOT EXISTS `product_purchase_price` +( + `product_sale_elements_id` INTEGER NOT NULL, + `currency_id` INTEGER NOT NULL, + `purchase_price` DECIMAL(16,6) DEFAULT 0, + PRIMARY KEY (`product_sale_elements_id`,`currency_id`), + INDEX `FI_currency_id` (`currency_id`), + CONSTRAINT `fk_product_sale_elements_id` + FOREIGN KEY (`product_sale_elements_id`) + REFERENCES `product_sale_elements` (`id`) + ON UPDATE RESTRICT + ON DELETE CASCADE, + CONSTRAINT `fk_currency_id` + FOREIGN KEY (`currency_id`) + REFERENCES `currency` (`id`) + ON UPDATE RESTRICT + ON DELETE CASCADE +) ENGINE=InnoDB; + +-- --------------------------------------------------------------------- +-- order_product_purchase_price +-- --------------------------------------------------------------------- + +CREATE TABLE IF NOT EXISTS `order_product_purchase_price` +( + `order_product_id` INTEGER NOT NULL, + `purchase_price` DECIMAL(16,6) DEFAULT 0, + `sale_day_equation` TEXT NOT NULL, + PRIMARY KEY (`order_product_id`), + CONSTRAINT `fk_order_product_id` + FOREIGN KEY (`order_product_id`) + REFERENCES `order_product` (`id`) + ON UPDATE RESTRICT + ON DELETE CASCADE +) ENGINE=InnoDB; + +-- --------------------------------------------------------------------- +-- customer_family_order +-- --------------------------------------------------------------------- + +CREATE TABLE IF NOT EXISTS `customer_family_order` +( + `order_id` INTEGER NOT NULL, + `customer_family_code` VARCHAR(45) NOT NULL, + PRIMARY KEY (`order_id`), + INDEX `FI_customer_family_code` (`customer_family_code`), + CONSTRAINT `fk_customer_family_order_id` + FOREIGN KEY (`order_id`) + REFERENCES `order` (`id`) + ON DELETE CASCADE, + CONSTRAINT `fk_customer_family_code` + FOREIGN KEY (`customer_family_code`) + REFERENCES `customer_family` (`code`) + ON UPDATE CASCADE +) ENGINE=InnoDB; + +# 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/CustomerFamily/Config/update/1.5.1.sql b/local/modules/CustomerFamily/Config/update/1.5.1.sql new file mode 100644 index 00000000..8cb7e878 --- /dev/null +++ b/local/modules/CustomerFamily/Config/update/1.5.1.sql @@ -0,0 +1,59 @@ +# 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; + +ALTER TABLE `customer_family` ADD `category_restriction_enabled` TINYINT DEFAULT 0 AFTER `code`; +ALTER TABLE `customer_family` ADD `brand_restriction_enabled` TINYINT DEFAULT 0 AFTER `category_restriction_enabled`; + +-- --------------------------------------------------------------------- +-- customer_family_available_category +-- --------------------------------------------------------------------- + +DROP TABLE IF EXISTS `customer_family_available_category`; + +CREATE TABLE `customer_family_available_category` +( + `customer_family_id` INTEGER NOT NULL, + `category_id` INTEGER NOT NULL, + PRIMARY KEY (`customer_family_id`,`category_id`), + INDEX `idx_customer_family_available_category_customer_family_id` (`customer_family_id`), + INDEX `idx_customer_family_available_category_category_id` (`category_id`), + CONSTRAINT `fk_customer_family_available_category_customer_family_id` + FOREIGN KEY (`customer_family_id`) + REFERENCES `customer_family` (`id`) + ON UPDATE CASCADE + ON DELETE CASCADE, + CONSTRAINT `fk_customer_family_available_category_category_id` + FOREIGN KEY (`category_id`) + REFERENCES `category` (`id`) + ON UPDATE CASCADE + ON DELETE CASCADE +) ENGINE=InnoDB; + +-- --------------------------------------------------------------------- +-- customer_family_available_brand +-- --------------------------------------------------------------------- + +DROP TABLE IF EXISTS `customer_family_available_brand`; + +CREATE TABLE `customer_family_available_brand` +( + `customer_family_id` INTEGER NOT NULL, + `brand_id` INTEGER NOT NULL, + PRIMARY KEY (`customer_family_id`,`brand_id`), + INDEX `idx_customer_family_available_brand_customer_family_id` (`customer_family_id`), + INDEX `idx_customer_family_available_brand_brand_id` (`brand_id`), + CONSTRAINT `fk_customer_family_available_brand_customer_family_id` + FOREIGN KEY (`customer_family_id`) + REFERENCES `customer_family` (`id`) + ON UPDATE CASCADE + ON DELETE CASCADE, + CONSTRAINT `fk_customer_family_available_brand_brand_id` + FOREIGN KEY (`brand_id`) + REFERENCES `brand` (`id`) + ON UPDATE CASCADE + 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/CustomerFamily/Controller/Admin/CustomerFamilyAdminController.php b/local/modules/CustomerFamily/Controller/Admin/CustomerFamilyAdminController.php new file mode 100644 index 00000000..76ce6cf0 --- /dev/null +++ b/local/modules/CustomerFamily/Controller/Admin/CustomerFamilyAdminController.php @@ -0,0 +1,450 @@ +find(); + + $con = Propel::getConnection(); + + /** @var CustomerFamily $customerFamily */ + foreach ($customerFamilies as $customerFamily) { + $categoryRestrictionSql = "SELECT c.id, c.parent, ci18n.title, cfac.`customer_family_id`, + CASE + WHEN cfac.`customer_family_id` IS NOT NULL THEN 1 + ELSE 0 + END as available + FROM category c + LEFT JOIN `category_i18n` ci18n on c.`id` = ci18n.id AND ci18n.locale = :locale + LEFT JOIN `customer_family_available_category` cfac ON c.`id` = cfac.`category_id` AND cfac.`customer_family_id` = :customerFamilyId"; + + $stmt = $con->prepare($categoryRestrictionSql); + $stmt->bindValue('locale', $this->getCurrentEditionLocale()); + $stmt->bindValue('customerFamilyId', $customerFamily->getId()); + $stmt->execute(); + + $categoryRestrictions[$customerFamily->getId()] = $stmt->fetchAll(\PDO::FETCH_ASSOC); + + $brandRestrictionSql = "SELECT b.id, bi18n.title, cfab.`customer_family_id`, + CASE + WHEN cfab.`customer_family_id` IS NOT NULL THEN 1 + ELSE 0 + END as available + FROM brand b + LEFT JOIN `brand_i18n` bi18n on b.`id` = bi18n.id AND bi18n.locale = :locale + LEFT JOIN `customer_family_available_brand` cfab ON b.`id` = cfab.`brand_id` AND cfab.`customer_family_id` = :customerFamilyId"; + + $stmt = $con->prepare($brandRestrictionSql); + $stmt->bindValue('locale', $this->getCurrentEditionLocale()); + $stmt->bindValue('customerFamilyId', $customerFamily->getId()); + $stmt->execute(); + + $brandRestrictions[$customerFamily->getId()] = $stmt->fetchAll(\PDO::FETCH_ASSOC); + } + + return $this->render("customer_family_module_configuration", compact('categoryRestrictions', 'brandRestrictions')); + } + + /** + * @param Request $request + * @return mixed|\Thelia\Core\HttpFoundation\Response + */ + public function createAction(Request $request) + { + if (null !== $response = $this->checkAuth(array(AdminResources::MODULE), array('CustomerFamily'), AccessManager::CREATE)) { + return $response; + } + + $error = ""; + $form = new CustomerFamilyCreateForm($request); + + try { + $formValidate = $this->validateForm($form); + + $event = new CustomerFamilyEvent(); + $event->hydrateByForm($formValidate); + + $this->dispatch(CustomerFamilyEvents::CUSTOMER_FAMILY_CREATE, $event); + + } catch (\Exception $e) { + $error = $e->getMessage(); + } + + $message = Translator::getInstance()->trans( + "Customer family was created successfully", + array(), + CustomerFamily::MODULE_DOMAIN + ); + + return self::renderAdminConfig($form, $message, $error); + } + + /** + * @param Request $request + * @param $id + * @return mixed|\Thelia\Core\HttpFoundation\Response + */ + public function updateAction(Request $request, $id) + { + if (null !== $response = $this->checkAuth(array(AdminResources::MODULE), array('CustomerFamily'), AccessManager::UPDATE)) { + return $response; + } + + $error = ""; + $form = new CustomerFamilyUpdateForm($request); + + try { + $formValidate = $this->validateForm($form); + + $customerFamily = CustomerFamilyQuery::create()->findPk($id); + + if ($customerFamily === null) { + throw new \Exception("Customer Family not found by Id"); + } + + $event = new CustomerFamilyEvent($customerFamily); + $event->hydrateByForm($formValidate); + + $this->dispatch(CustomerFamilyEvents::CUSTOMER_FAMILY_UPDATE, $event); + + } catch (\Exception $e) { + $error = $e->getMessage(); + } + + $message = Translator::getInstance()->trans( + "Customer family was updated successfully", + array(), + CustomerFamily::MODULE_DOMAIN + ); + + return self::renderAdminConfig($form, $message, $error); + } + + /** + * Update default family + * There must be at least one default family + * + * @return mixed|\Symfony\Component\HttpFoundation\Response|static + */ + public function updateDefaultAction() + { + if (null !== $response = $this->checkAuth([AdminResources::MODULE], ['CustomerFamily'], AccessManager::UPDATE)) { + return $response; + } + + $error = null; + $ex = null; + $form = $this->createForm('customer_family_update_default_form'); + + try { + $vForm = $this->validateForm($form); + + // Get customer_family to update + $customerFamily = CustomerFamilyQuery::create()->findOneById($vForm->get('customer_family_id')->getData()); + + // If the customer_family exists + if (null !== $customerFamily) { + // If the family to update is not already the default one + if (!$customerFamily->getIsDefault()) { + // Remove old default family + if (null !== $defaultCustomerFamilies = CustomerFamilyQuery::create()->findByIsDefault(1)) { + /** @var \CustomerFamily\Model\CustomerFamily $defaultCustomerFamily */ + foreach ($defaultCustomerFamilies as $defaultCustomerFamily) { + $defaultCustomerFamily + ->setIsDefault(0) + ->save(); + } + } + // Save new default family + $customerFamily + ->setIsDefault(1) + ->save(); + } + } + + } catch (FormValidationException $ex) { + $error = $this->createStandardFormValidationErrorMessage($ex); + } catch (\Exception $ex) { + $error = $ex->getMessage(); + } + + if ($error !== null) { + $this->setupFormErrorContext( + $this->getTranslator()->trans("Error updating default family", [], CustomerFamily::MODULE_DOMAIN), + $error, + $form, + $ex + ); + return JsonResponse::create(['error'=>$error], 500); + } + + return RedirectResponse::create(URL::getInstance()->absoluteUrl("/admin/module/CustomerFamily")); + + } + + /** + * @param Request $request + * @param $id + * @return mixed|\Thelia\Core\HttpFoundation\Response + */ + public function deleteAction(Request $request, $id) + { + if (null !== $response = $this->checkAuth(array(AdminResources::MODULE), array('CustomerFamily'), AccessManager::DELETE)) { + return $response; + } + + $error = ""; + $form = new CustomerFamilyDeleteForm($request); + + try { + $formValidate = $this->validateForm($form); + + $customerFamily = CustomerFamilyQuery::create()->findPk($id); + + if ($customerFamily === null) { + throw new \Exception("Customer Family not found by Id"); + } + + $event = new CustomerFamilyEvent($customerFamily); + + $this->dispatch(CustomerFamilyEvents::CUSTOMER_FAMILY_DELETE, $event); + + } catch (\Exception $e) { + $error = $e->getMessage(); + } + + $message = Translator::getInstance()->trans( + "Customer family was deleted successfully", + array(), + CustomerFamily::MODULE_DOMAIN + ); + + return self::renderAdminConfig($form, $message, $error); + } + + /** + * @param BaseForm $form + * @param string $successMessage + * @param string $errorMessage + * @return \Symfony\Component\HttpFoundation\Response|static + */ + protected function renderAdminConfig($form, $successMessage, $errorMessage) + { + if (!empty($errorMessage)) { + $form->setErrorMessage($errorMessage); + + $this->getParserContext() + ->addForm($form) + ->setGeneralError($errorMessage); + } + + //for compatibility 2.0 + if (method_exists($this->getSession(), "getFlashBag")) { + if (empty($errorMessage)) { + $this->getSession()->getFlashBag()->add("success", $successMessage); + } else { + $this->getSession()->getFlashBag()->add("danger", $errorMessage); + } + } + + return RedirectResponse::create( + URL::getInstance()->absoluteUrl("/admin/module/CustomerFamily") + ); + } + + /** + * @param Request $request + * @return mixed|\Thelia\Core\HttpFoundation\Response + */ + public function customerUpdateAction(Request $request) + { + if (null !== $response = $this->checkAuth(array(AdminResources::MODULE), array('CustomerFamily'), AccessManager::UPDATE)) { + return $response; + } + + $error = ""; + $form = new CustomerCustomerFamilyForm($request); + try { + $formValidate = $this->validateForm($form); + $event = new CustomerCustomerFamilyEvent($formValidate->get('customer_id')->getData()); + $event + ->setCustomerFamilyId($formValidate->get('customer_family_id')->getData()) + ->setSiret($formValidate->get('siret')->getData()) + ->setVat($formValidate->get('vat')->getData()) + ; + + $this->dispatch(CustomerFamilyEvents::CUSTOMER_CUSTOMER_FAMILY_UPDATE, $event); + + return $this->generateRedirect(URL::getInstance()->absoluteUrl( + '/admin/customer/update?customer_id='.$formValidate->get('customer_id')->getData() + )); + } catch (FormValidationException $ex) { + $error = $this->createStandardFormValidationErrorMessage($ex); + } catch (\Exception $e) { + $error = $e->getMessage(); + } + + if (!empty($error)) { + $form->setErrorMessage($error); + } + + $this->getParserContext() + ->addForm($form) + ->setGeneralError($error); + + //Don't forget to fill the Customer form + $customerId = $request->get('customer_customer_family_form')['customer_id']; + if (null != $customer = CustomerQuery::create()->findPk($customerId)) { + $customerForm = $this->hydrateCustomerForm($customer); + $this->getParserContext()->addForm($customerForm); + } + + return $this->render('customer-edit', array( + 'customer_id' => $request->get('customer_customer_family_form')['customer_id'], + "order_creation_error" => Translator::getInstance()->trans($error, array(), CustomerFamily::MESSAGE_DOMAIN) + )); + } + + public function saveCustomerFamilyCategoryRestriction($customerFamilyId) + { + $customerFamily = CustomerFamilyQuery::create() + ->findOneById($customerFamilyId); + + $restrictionEnabled = $this->getRequest()->get('restriction_enabled') === "on"; + $customerFamily->setCategoryRestrictionEnabled($restrictionEnabled); + $customerFamily->save(); + + $con = Propel::getConnection(); + $deleteSql = "DELETE FROM `customer_family_available_category` WHERE `customer_family_available_category`.`customer_family_id` = :customerFamilyId"; + $stmt = $con->prepare($deleteSql); + $stmt->bindValue('customerFamilyId', $customerFamilyId); + $stmt->execute(); + + $brands = $this->getRequest()->get('available_categories'); + if (is_array($brands)) { + foreach ($this->getRequest()->get('available_categories') as $availableCategoryId) { + var_dump($customerFamilyId); + var_dump($availableCategoryId); + $customerFamilyAvailableCategory = new CustomerFamilyAvailableCategory(); + $customerFamilyAvailableCategory->setCustomerFamilyId($customerFamilyId) + ->setCategoryId($availableCategoryId) + ->save(); + } + } + + return $this->renderAdminConfig(null, "", ""); + } + + public function saveCustomerFamilyBrandRestriction($customerFamilyId) + { + $customerFamily = CustomerFamilyQuery::create() + ->findOneById($customerFamilyId); + + $restrictionEnabled = $this->getRequest()->get('restriction_enabled') === "on"; + $customerFamily->setBrandRestrictionEnabled($restrictionEnabled); + $customerFamily->save(); + + $con = Propel::getConnection(); + $deleteSql = "DELETE FROM `customer_family_available_brand` WHERE `customer_family_available_brand`.`customer_family_id` = :customerFamilyId"; + $stmt = $con->prepare($deleteSql); + $stmt->bindValue('customerFamilyId', $customerFamilyId); + $stmt->execute(); + + $categories = $this->getRequest()->get('available_categories'); + if (is_array($categories)) { + foreach ($this->getRequest()->get('available_categories') as $availableBrandId) { + var_dump($customerFamilyId); + var_dump($availableBrandId); + $customerFamilyAvailableBrand = new CustomerFamilyAvailableBrand(); + $customerFamilyAvailableBrand->setCustomerFamilyId($customerFamilyId) + ->setBrandId($availableBrandId) + ->save(); + } + } + + return $this->renderAdminConfig(null, "", ""); + } + + /** + * @param Customer $customer + * @return CustomerUpdateForm + */ + protected function hydrateCustomerForm(Customer $customer) + { + // Get default adress of the customer + $address = $customer->getDefaultAddress(); + + // Prepare the data that will hydrate the form + $data = array( + 'id' => $customer->getId(), + 'firstname' => $customer->getFirstname(), + 'lastname' => $customer->getLastname(), + 'email' => $customer->getEmail(), + 'title' => $customer->getTitleId(), + 'discount' => $customer->getDiscount(), + 'reseller' => $customer->getReseller(), + ); + + 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(); + } + + // A loop is used in the template + return new CustomerUpdateForm($this->getRequest(), 'form', $data); + } +} diff --git a/local/modules/CustomerFamily/Controller/Admin/CustomerFamilyPriceController.php b/local/modules/CustomerFamily/Controller/Admin/CustomerFamilyPriceController.php new file mode 100644 index 00000000..27059277 --- /dev/null +++ b/local/modules/CustomerFamily/Controller/Admin/CustomerFamilyPriceController.php @@ -0,0 +1,95 @@ + + */ +class CustomerFamilyPriceController extends BaseAdminController +{ + /** + * Add or update amounts and factor to calculate prices for customer families + * + * @return mixed|\Symfony\Component\HttpFoundation\Response|\Thelia\Core\HttpFoundation\Response|static + */ + public function updateAction() + { + // Check rights + if (null !== $response = $this->checkAuth( + [AdminResources::MODULE], + ['CustomerFamily'], + [AccessManager::VIEW, AccessManager::CREATE, AccessManager::UPDATE] + )) { + return $response; + } + + $form = $this->createForm('customer_family_price_update'); + $error = null; + $ex = null; + + try { + $vForm = $this->validateForm($form); + + // If no entry exists for the given CustomerFamilyId & promo, create it + if (null === $customerFamilyPrice = CustomerFamilyPriceQuery::create() + ->findPk([$vForm->get('customer_family_id')->getData(), $vForm->get('promo')->getData()])) { + // Create new CustomerFamilyPrice + $customerFamilyPrice = new CustomerFamilyPrice(); + $customerFamilyPrice + ->setCustomerFamilyId($vForm->get('customer_family_id')->getData()) + ->setPromo($vForm->get('promo')->getData()); + } + + // Save data + $customerFamilyPrice + ->setUseEquation($vForm->get('use_equation')->getData()) + ->setAmountAddedBefore($vForm->get('amount_added_before')->getData()) + ->setAmountAddedAfter($vForm->get('amount_added_after')->getData()) + ->setMultiplicationCoefficient($vForm->get('coefficient')->getData()) + ->setIsTaxed($vForm->get('is_taxed')->getData()) + ->save(); + + } catch (FormValidationException $ex) { + $error = $this->createStandardFormValidationErrorMessage($ex); + } catch (\Exception $ex) { + $error = $ex->getMessage(); + } + + if ($error !== null) { + $this->setupFormErrorContext( + $this->getTranslator()->trans("CustomerFamily configuration", [], CustomerFamily::MODULE_DOMAIN), + $error, + $form, + $ex + ); + return $this->render('module-configure', ['module_code' => 'CustomerFamily']); + } + + return RedirectResponse::create(URL::getInstance()->absoluteUrl("/admin/module/CustomerFamily")); + } + + public function updatePriceModeAction() + { + $form = new CustomerFamilyPriceModeForm($this->getRequest()); + $vForm = $this->validateForm($form); + + $mode = $vForm->get('price_mode')->getData(); + + CustomerFamily::setConfigValue('customer_family_price_mode', $mode); + + return RedirectResponse::create(URL::getInstance()->absoluteUrl("/admin/module/CustomerFamily")); + } +} \ No newline at end of file diff --git a/local/modules/CustomerFamily/CustomerFamily.php b/local/modules/CustomerFamily/CustomerFamily.php new file mode 100644 index 00000000..e6472856 --- /dev/null +++ b/local/modules/CustomerFamily/CustomerFamily.php @@ -0,0 +1,131 @@ + + */ +class CustomerFamily extends BaseModule +{ + /** @cont string */ + const MODULE_DOMAIN = 'customerfamily'; + + /** @cont string */ + const MESSAGE_DOMAIN = 'customerfamily'; + + /** @cont string */ + const CUSTOMER_FAMILY_PARTICULAR = "particular"; + + /** @cont string */ + const CUSTOMER_FAMILY_PROFESSIONAL = "professional"; + + /** + * @param ConnectionInterface $con + */ + public function postActivation(ConnectionInterface $con = null) + { + + try { + CustomerFamilyQuery::create()->findOne(); + } catch (\Exception $e) { + $database = new Database($con); + $database->insertSql(null, [__DIR__ . "/Config/thelia.sql"]); + } + + //Generate the 2 defaults customer_family + + //Customer + self::getCustomerFamilyByCode(self::CUSTOMER_FAMILY_PARTICULAR, "Particulier", "fr_FR"); + self::getCustomerFamilyByCode(self::CUSTOMER_FAMILY_PARTICULAR, "Private individual", "en_US"); + + //Professional + self::getCustomerFamilyByCode(self::CUSTOMER_FAMILY_PROFESSIONAL, "Professionnel", "fr_FR"); + self::getCustomerFamilyByCode(self::CUSTOMER_FAMILY_PROFESSIONAL, "Professional", "en_US"); + } + + public function update($currentVersion, $newVersion, ConnectionInterface $con = null) + { + $finder = Finder::create() + ->name('*.sql') + ->depth(0) + ->sortByName() + ->in(__DIR__ . DS . 'Config' . DS . 'update'); + + $database = new Database($con); + + /** @var \SplFileInfo $file */ + foreach ($finder as $file) { + if (version_compare($currentVersion, $file->getBasename('.sql'), '<')) { + $database->insertSql(null, [$file->getPathname()]); + } + } + } + + /** + * @param $code + * @param null $title + * @param string $locale + * + * @return Model\CustomerFamily + */ + public static function getCustomerFamilyByCode($code, $title = null, $locale = "fr_FR") + { + if ($title == null) { + $title = $code; + } + + // Set 'particular' as default family + if ($code == self::CUSTOMER_FAMILY_PARTICULAR) { + $isDefault = 1; + } else { + $isDefault = 0; + } + + /** @var CustomerFamilyModel $customerFamily */ + if (null == $customerFamily = CustomerFamilyQuery::create() + ->useCustomerFamilyI18nQuery() + ->filterByLocale($locale) + ->endUse() + ->filterByCode($code) + ->findOne() + ) { + //Be sure that you don't create it twice + /** @var CustomerFamilyModel $customerF */ + if (null != $customerF = CustomerFamilyQuery::create()->findOneByCode($code)) { + $customerF + ->setLocale($locale) + ->setTitle($title) + ->save(); + } else { + $customerFamily = new CustomerFamilyModel(); + $customerFamily + ->setCode($code) + ->setIsDefault($isDefault) + ->setLocale($locale) + ->setTitle($title) + ->save(); + } + } + + return $customerFamily; + } +} diff --git a/local/modules/CustomerFamily/Event/CustomerCustomerFamilyEvent.php b/local/modules/CustomerFamily/Event/CustomerCustomerFamilyEvent.php new file mode 100644 index 00000000..4063894d --- /dev/null +++ b/local/modules/CustomerFamily/Event/CustomerCustomerFamilyEvent.php @@ -0,0 +1,123 @@ +customerId = $customerId; + } + + /** + * @param int $customerFamilyId + * + * @return CustomerCustomerFamily + */ + public function setCustomerFamilyId($customerFamilyId) + { + $this->customerFamilyId = $customerFamilyId; + + return $this; + } + + /** + * @return int + */ + public function getCustomerFamilyId() + { + return $this->customerFamilyId; + } + + /** + * @param int $customerId + * + * @return CustomerCustomerFamily + */ + public function setCustomerId($customerId) + { + $this->customerId = $customerId; + + return $this; + } + + /** + * @return int + */ + public function getCustomerId() + { + return $this->customerId; + } + + /** + * @param mixed $siret + * + * @return CustomerCustomerFamily + */ + public function setSiret($siret) + { + $this->siret = $siret; + + return $this; + } + + /** + * @return mixed + */ + public function getSiret() + { + return $this->siret; + } + + /** + * @param mixed $vat + * + * @return CustomerCustomerFamily + */ + public function setVat($vat) + { + $this->vat = $vat; + + return $this; + } + + /** + * @return mixed + */ + public function getVat() + { + return $this->vat; + } +} diff --git a/local/modules/CustomerFamily/Event/CustomerFamilyEvent.php b/local/modules/CustomerFamily/Event/CustomerFamilyEvent.php new file mode 100644 index 00000000..a188cd2d --- /dev/null +++ b/local/modules/CustomerFamily/Event/CustomerFamilyEvent.php @@ -0,0 +1,130 @@ +customerFamily = $customerFamily; + } else { + $this->customerFamily = new CustomerFamily(); + } + } + + /** + * @param CustomerFamily $customerFamily + * @return $this + */ + public function setCustomerFamily(CustomerFamily $customerFamily) + { + $this->customerFamily = $customerFamily; + + return $this; + } + + /** + * @return CustomerFamily + */ + public function getCustomerFamily() + { + return $this->customerFamily; + } + + /** + * @return int + */ + public function getId() + { + return $this->customerFamily->getId(); + } + + /** + * @return string + */ + public function getCode() + { + return $this->customerFamily->getCode(); + } + + /** + * @param string $code + * @return $this + */ + public function setCode($code) + { + $this->customerFamily->setCode($code); + + return $this; + } + + /** + * @param $locale + * @return string + */ + public function getTitle($locale = null) + { + if ($locale === null) { + $locale = $this->customerFamily->getLocale(); + } + + $this->customerFamily->setLocale($locale); + + return $this->customerFamily->getTitle(); + } + + /** + * @param $title + * @param null $locale + * @return $this + */ + public function setTitle($title, $locale = null) + { + if ($locale === null) { + $locale = $this->customerFamily->getLocale(); + } + + $this->customerFamily->setLocale($locale); + $this->customerFamily->setTitle($title); + + return $this; + } + + /** + * @param Form $form + */ + public function hydrateByForm(Form $form) + { + //code + if ($form->get('code') !== null) { + self::setCode($form->get('code')->getData()); + } + + //title + if ($form->get('title') !== null && $form->get('locale') !== null) { + self::setTitle($form->get('title')->getData(), $form->get('locale')->getData()); + } + } +} diff --git a/local/modules/CustomerFamily/Event/CustomerFamilyEvents.php b/local/modules/CustomerFamily/Event/CustomerFamilyEvents.php new file mode 100644 index 00000000..18825d7c --- /dev/null +++ b/local/modules/CustomerFamily/Event/CustomerFamilyEvents.php @@ -0,0 +1,25 @@ + + */ +class CustomerFamilyCartListener implements EventSubscriberInterface +{ + protected $customerFamilyService; + + public function __construct(CustomerFamilyService $customerFamilyService) + { + $this->customerFamilyService = $customerFamilyService; + } + + /** + * Returns an array of event names this subscriber wants to listen to. + * + * @return array The event names to listen to + */ + public static function getSubscribedEvents() + { + return [ + TheliaEvents::CART_ADDITEM => ['addCartItem', 128] + ]; + } + + /** + * @param CartEvent $cartEvent + * @throws \Exception + * @throws \Propel\Runtime\Exception\PropelException + */ + public function addCartItem(CartEvent $cartEvent) + { + $pseId = $cartEvent->getProductSaleElementsId(); + $pse = ProductSaleElementsQuery::create()->findOneById($pseId); + + $prices = $this->customerFamilyService->calculateCustomerPsePrice($pse); + + if ($prices['price'] !== null) { + $cartEvent->getCartItem()->setPrice($prices['price']); + } + if ($prices['promoPrice'] !== null) { + $cartEvent->getCartItem()->setPromoPrice($prices['promoPrice']); + } + + $cartEvent->getCartItem()->save(); + } +} \ No newline at end of file diff --git a/local/modules/CustomerFamily/EventListeners/CustomerFamilyCustomerConnectionListener.php b/local/modules/CustomerFamily/EventListeners/CustomerFamilyCustomerConnectionListener.php new file mode 100644 index 00000000..b1cfd0ac --- /dev/null +++ b/local/modules/CustomerFamily/EventListeners/CustomerFamilyCustomerConnectionListener.php @@ -0,0 +1,118 @@ + + */ +class CustomerFamilyCustomerConnectionListener implements EventSubscriberInterface +{ + protected $request; + protected $customerFamilyService; + + public function __construct(Request $request, CustomerFamilyService $customerFamilyService) + { + $this->request = $request; + $this->customerFamilyService = $customerFamilyService; + } + + /** + * Returns an array of event names this subscriber wants to listen to. + * + * @return array The event names to listen to + */ + public static function getSubscribedEvents() + { + return [ + TheliaEvents::CUSTOMER_LOGOUT => ['customerLogout', 128], + TheliaEvents::CUSTOMER_LOGIN => ['customerLogin', 128] + ]; + } + + /** + * Update cart items' prices when logging out + * + * @param DefaultActionEvent $event + * @param $eventName + * @param EventDispatcherInterface $dispatcher + * @throws \Exception + * @throws \Propel\Runtime\Exception\PropelException + */ + public function customerLogout(DefaultActionEvent $event, $eventName, EventDispatcherInterface $dispatcher) + { + // Get cart & loop on its items + $cart = $this->request->getSession()->getSessionCart($dispatcher); + + /** @var \Thelia\Model\CartItem $cartItem */ + foreach ($cart->getCartItems() as $cartItem) { + // Get item's corresponding PSE + $pse = ProductSaleElementsQuery::create()->findOneById($cartItem->getProductSaleElementsId()); + + // Get pse's prices for the customer + $prices = $this->customerFamilyService->calculateCustomerPsePrice( + $pse, + null, + $cart->getCurrencyId() + ); + + if ($prices['price'] !== null) { + $cartItem->setPrice($prices['price']); + } + + if ($prices['promoPrice'] !== null) { + $cartItem->setPromoPrice($prices['promoPrice']); + } + + $cartItem->save(); + } + } + + /** + * Update cart items' prices when logging in + * + * @param CustomerLoginEvent $event + * @param $eventName + * @param EventDispatcherInterface $dispatcher + * @throws \Exception + * @throws \Propel\Runtime\Exception\PropelException + */ + public function customerLogin(CustomerLoginEvent $event, $eventName, EventDispatcherInterface $dispatcher) + { + // Get cart & loop on its items + $cart = $this->request->getSession()->getSessionCart($dispatcher); + + /** @var \Thelia\Model\CartItem $cartItem */ + foreach ($cart->getCartItems() as $cartItem) { + // Get item's corresponding PSE + $pse = ProductSaleElementsQuery::create()->findOneById($cartItem->getProductSaleElementsId()); + + // Get pse's prices for the customer + $prices = $this->customerFamilyService->calculateCustomerPsePrice( + $pse, + $event->getCustomer()->getId(), + $cart->getCurrencyId() + ); + + if ($prices['price'] !== null) { + $cartItem->setPrice($prices['price']); + } + + if ($prices['promoPrice'] !== null) { + $cartItem->setPromoPrice($prices['promoPrice']); + } + + $cartItem->save(); + } + } +} \ No newline at end of file diff --git a/local/modules/CustomerFamily/EventListeners/CustomerFamilyFormListener.php b/local/modules/CustomerFamily/EventListeners/CustomerFamilyFormListener.php new file mode 100644 index 00000000..29a8bb21 --- /dev/null +++ b/local/modules/CustomerFamily/EventListeners/CustomerFamilyFormListener.php @@ -0,0 +1,254 @@ +request = $request; + } + + /** + * Returns an array of event names this subscriber wants to listen to. + * + * @return array The event names to listen to + * + * @api + */ + public static function getSubscribedEvents() + { + return array( + TheliaEvents::FORM_AFTER_BUILD.'.'.self::THELIA_CUSTOMER_CREATE_FORM_NAME => array('addCustomerFamilyFieldsForRegister', 128), + TheliaEvents::FORM_AFTER_BUILD.'.'.self::THELIA_ADMIN_CUSTOMER_CREATE_FORM_NAME => array('addCustomerFamilyFieldsForRegister', 128), + TheliaEvents::FORM_AFTER_BUILD.'.'.self::THELIA_ACCOUNT_UPDATE_FORM_NAME => array('addCustomerFamilyFieldsForUpdate', 128), + ); + } + + /** + * Callback used to add some fields to the Thelia's CustomerCreateForm. + * It add two fields : one for the SIRET number and one for VAT. + * @param TheliaFormEvent $event + */ + public function addCustomerFamilyFieldsForRegister(TheliaFormEvent $event) + { + // Retrieving CustomerFamily choices + $customerFamilyChoices = array(); + + /** @var \CustomerFamily\Model\CustomerFamily $customerFamily */ + foreach (CustomerFamilyQuery::create()->find() as $customerFamily) { + $customerFamilyChoices[$customerFamily->getCode()] = self::trans($customerFamily->getTitle()); + } + + // Building additional fields + $event->getForm()->getFormBuilder() + ->add( + self::CUSTOMER_FAMILY_CODE_FIELD_NAME, + 'choice', + array( + 'constraints' => array( + new Constraints\Callback( + array( + 'methods' => array( + array( + $this, 'checkCustomerFamily' + ) + ) + ) + ), + new Constraints\NotBlank(), + ), + 'choices' => $customerFamilyChoices, + 'empty_data' => false, + 'required' => false, + 'label' => self::trans('Customer family'), + 'label_attr' => array( + 'for' => 'customer_family_id', + ), + 'mapped' => false, + ) + ) + ->add( + self::CUSTOMER_FAMILY_SIRET_FIELD_NAME, + 'text', + array( + 'required' => true, + 'empty_data' => false, + 'label' => self::trans('Siret number'), + 'label_attr' => array( + 'for' => 'siret' + ), + 'mapped' => false, + ) + ) + ->add( + self::CUSTOMER_FAMILY_VAT_FIELD_NAME, + 'text', + array( + 'required' => true, + 'empty_data' => false, + 'label' => self::trans('Vat'), + 'label_attr' => array( + 'for' => 'vat' + ), + 'mapped' => false, + ) + ) + ; + } + + /** + * Callback used to add some fields to the Thelia's CustomerCreateForm. + * It add two fields : one for the SIRET number and one for VAT. + * @param TheliaFormEvent $event + */ + public function addCustomerFamilyFieldsForUpdate(TheliaFormEvent $event) + { + // Adding new fields + $customer = $this->request->getSession()->getCustomerUser(); + + if (is_null($customer)) { + // No customer => no account update => stop here + return; + } + + $customerCustomerFamily = CustomerCustomerFamilyQuery::create()->findOneByCustomerId($customer->getId()); + + $cfData = array( + self::CUSTOMER_FAMILY_CODE_FIELD_NAME => (is_null($customerCustomerFamily) or is_null($customerCustomerFamily->getCustomerFamily())) ? '' : $customerCustomerFamily->getCustomerFamily()->getCode(), + self::CUSTOMER_FAMILY_SIRET_FIELD_NAME => is_null($customerCustomerFamily) ? false : $customerCustomerFamily->getSiret(), + self::CUSTOMER_FAMILY_VAT_FIELD_NAME => is_null($customerCustomerFamily) ? false : $customerCustomerFamily->getVat(), + ); + + // Retrieving CustomerFamily choices + $customerFamilyChoices = array(); + + /** @var \CustomerFamily\Model\CustomerFamily $customerFamilyChoice */ + foreach (CustomerFamilyQuery::create()->find() as $customerFamilyChoice) { + $customerFamilyChoices[$customerFamilyChoice->getCode()] = self::trans($customerFamilyChoice->getTitle()); + } + + + // Building additional fields + $event->getForm()->getFormBuilder() + ->add( + self::CUSTOMER_FAMILY_CODE_FIELD_NAME, + 'choice', + array( + 'constraints' => array( + new Constraints\Callback(array('methods' => array( + array($this, 'checkCustomerFamily') + ))), + new Constraints\NotBlank(), + ), + 'choices' => $customerFamilyChoices, + 'empty_data' => false, + 'required' => false, + 'label' => self::trans('Customer family'), + 'label_attr' => array( + 'for' => 'customer_family_id', + ), + 'mapped' => false, + 'data' => $cfData[self::CUSTOMER_FAMILY_CODE_FIELD_NAME], + ) + ) + ->add( + self::CUSTOMER_FAMILY_SIRET_FIELD_NAME, + 'text', + array( + 'required' => true, + 'empty_data' => false, + 'label' => self::trans('Siret number'), + 'label_attr' => array( + 'for' => 'siret' + ), + 'mapped' => false, + 'data' => $cfData[self::CUSTOMER_FAMILY_SIRET_FIELD_NAME], + ) + ) + ->add( + self::CUSTOMER_FAMILY_VAT_FIELD_NAME, + 'text', + array( + 'required' => true, + 'empty_data' => false, + 'label' => self::trans('Vat'), + 'label_attr' => array( + 'for' => 'vat' + ), + 'mapped' => false, + 'data' => $cfData[self::CUSTOMER_FAMILY_VAT_FIELD_NAME], + ) + ) + ; + } + + /** + * Validate a field only if the customer family is valid + * + * @param string $value + * @param ExecutionContextInterface $context + */ + public function checkCustomerFamily($value, ExecutionContextInterface $context) + { + if (CustomerFamilyQuery::create()->filterByCode($value)->count() == 0) { + $context->addViolation(self::trans('The customer family is not valid')); + } + } + + + /** + * Utility for translations + * @param $id + * @param array $parameters + * @return string + */ + protected static function trans($id, array $parameters = array()) + { + return Translator::getInstance()->trans($id, $parameters, CustomerFamily::MESSAGE_DOMAIN); + } +} diff --git a/local/modules/CustomerFamily/EventListeners/CustomerFamilyListener.php b/local/modules/CustomerFamily/EventListeners/CustomerFamilyListener.php new file mode 100644 index 00000000..7213ceff --- /dev/null +++ b/local/modules/CustomerFamily/EventListeners/CustomerFamilyListener.php @@ -0,0 +1,246 @@ +request = $request; + $this->parser = $parser; + $this->mailer = $mailer; + } + + /** + * Returns an array of event names this subscriber wants to listen to. + * + * @return array The event names to listen to + * + * @api + */ + public static function getSubscribedEvents() + { + return array( + TheliaEvents::AFTER_CREATECUSTOMER => array( + 'afterCreateCustomer', 100 + ), + TheliaEvents::CUSTOMER_UPDATEPROFILE => array( + 'customerUpdateProfile', 100 + ), + CustomerFamilyEvents::CUSTOMER_CUSTOMER_FAMILY_UPDATE => array( + "customerCustomerFamilyUpdate", 128 + ), + CustomerFamilyEvents::CUSTOMER_FAMILY_CREATE => array( + 'create', 128 + ), + CustomerFamilyEvents::CUSTOMER_FAMILY_UPDATE => array( + 'update', 128 + ), + CustomerFamilyEvents::CUSTOMER_FAMILY_DELETE => array( + 'delete', 128 + ), + ); + } + + /** + * @param CustomerFamilyEvent $event + * @throws \Exception + * @throws \Propel\Runtime\Exception\PropelException + */ + public function create(CustomerFamilyEvent $event) + { + if (CustomerFamilyQuery::create() + ->filterByCode($event->getCode()) + ->findOne() !== null + ) { + throw new \Exception("Customer family code is already in use"); + } + + $event->getCustomerFamily()->save(); + } + + /** + * @param CustomerFamilyEvent $event + * @throws \Exception + * @throws \Propel\Runtime\Exception\PropelException + */ + public function update(CustomerFamilyEvent $event) + { + if (CustomerFamilyQuery::create() + ->filterByCode($event->getCode()) + ->filterById($event->getId(), Criteria::NOT_EQUAL) + ->findOne() !== null + ) { + throw new \Exception("Customer family code is already in use"); + } + + $event->getCustomerFamily()->save(); + } + + /** + * @param CustomerFamilyEvent $event + */ + public function delete(CustomerFamilyEvent $event) + { + $event->getCustomerFamily()->delete(); + } + + /** + * @param CustomerEvent $event + * @param $eventName + * @param EventDispatcherInterface $dispatcher + */ + public function afterCreateCustomer(CustomerEvent $event, $eventName, EventDispatcherInterface $dispatcher) + { + $form = $this->request->request->get(self::THELIA_CUSTOMER_CREATE_FORM_NAME); + + if (is_null($form) or !array_key_exists(CustomerFamilyFormListener::CUSTOMER_FAMILY_CODE_FIELD_NAME, $form)) { + // Nothing to create the new CustomerCustomerFamily => stop here ! + return; + } + + $customerFamily = CustomerFamilyQuery::create()->findOneByCode($form[CustomerFamilyFormListener::CUSTOMER_FAMILY_CODE_FIELD_NAME]); + + if (is_null($customerFamily)) { + // No family => no CustomerCustomerFamily to update. + return; + } + + $customerFamilyId = $customerFamily->getId(); + + // Ignore SIRET and VAT if the customer is not professional + $siret = $customerFamily->getCode() == CustomerFamily::CUSTOMER_FAMILY_PROFESSIONAL ? $form[CustomerFamilyFormListener::CUSTOMER_FAMILY_SIRET_FIELD_NAME] : ''; + $vat = $customerFamily->getCode() == CustomerFamily::CUSTOMER_FAMILY_PROFESSIONAL ? $form[CustomerFamilyFormListener::CUSTOMER_FAMILY_VAT_FIELD_NAME] : ''; + + $updateEvent = new CustomerCustomerFamilyEvent($event->getCustomer()->getId()); + $updateEvent + ->setCustomerFamilyId($customerFamilyId) + ->setSiret($siret) + ->setVat($vat) + ; + + $dispatcher->dispatch(CustomerFamilyEvents::CUSTOMER_CUSTOMER_FAMILY_UPDATE, $updateEvent); + } + + /** + * @param CustomerCreateOrUpdateEvent $event + * @param $eventName + * @param EventDispatcherInterface $dispatcher + */ + public function customerUpdateProfile(CustomerCreateOrUpdateEvent $event, $eventName, EventDispatcherInterface $dispatcher) + { + $form = $this->request->request->get(self::THELIA_CUSTOMER_UPDATE_FORM_NAME); + + if (is_null($form) or !array_key_exists(CustomerFamilyFormListener::CUSTOMER_FAMILY_CODE_FIELD_NAME, $form)) { + // Nothing to update => stop here ! + return; + } + + // Erase SIRET and VAT if the customer is now in the 'particular' customer family. + if ($form[CustomerFamilyFormListener::CUSTOMER_FAMILY_CODE_FIELD_NAME] == CustomerFamily::CUSTOMER_FAMILY_PARTICULAR) { + $siret = ''; + $vat = ''; + } else { + $siret = $form[CustomerFamilyFormListener::CUSTOMER_FAMILY_SIRET_FIELD_NAME]; + $vat = $form[CustomerFamilyFormListener::CUSTOMER_FAMILY_VAT_FIELD_NAME]; + } + + $newCustomerFamily = CustomerFamilyQuery::create()->findOneByCode($form[CustomerFamilyFormListener::CUSTOMER_FAMILY_CODE_FIELD_NAME]); + + + $updateEvent = new CustomerCustomerFamilyEvent($event->getCustomer()->getId()); + $updateEvent + ->setCustomerFamilyId($newCustomerFamily->getId()) + ->setSiret($siret) + ->setVat($vat) + ; + + $dispatcher->dispatch(CustomerFamilyEvents::CUSTOMER_CUSTOMER_FAMILY_UPDATE, $updateEvent); + } + + /** + * @param CustomerCustomerFamilyEvent $event + */ + public function customerCustomerFamilyUpdate(CustomerCustomerFamilyEvent $event) + { + $customerCustomerFamily = CustomerCustomerFamilyQuery::create()->findOneByCustomerId($event->getCustomerId()); + + if ($customerCustomerFamily === null) { + $customerCustomerFamily = new CustomerCustomerFamily(); + $customerCustomerFamily + ->setCustomerId($event->getCustomerId()) + ; + } + + $customerCustomerFamily + ->setCustomerFamilyId($event->getCustomerFamilyId()) + ->setSiret($event->getSiret()) + ->setVat($event->getVat()) + ->save() + ; + } + + /** + * @return mixed|null + */ + protected function getCustomerFamilyForm() + { + if (null != $form = $this->request->request->get("customer_family_customer_profile_update_form")) { + return $form; + } + + if (null != $form = $this->request->request->get(self::THELIA_CUSTOMER_CREATE_FORM_NAME)) { + return $form; + } + + return null; + } +} diff --git a/local/modules/CustomerFamily/EventListeners/CustomerFamilyOrderListener.php b/local/modules/CustomerFamily/EventListeners/CustomerFamilyOrderListener.php new file mode 100644 index 00000000..682a733f --- /dev/null +++ b/local/modules/CustomerFamily/EventListeners/CustomerFamilyOrderListener.php @@ -0,0 +1,102 @@ + + */ +class CustomerFamilyOrderListener implements EventSubscriberInterface +{ + protected $customerFamilyService; + + public function __construct(CustomerFamilyService $customerFamilyService) + { + $this->customerFamilyService = $customerFamilyService; + } + + /** + * Returns an array of event names this subscriber wants to listen to. + * + * @return array The event names to listen to + */ + public static function getSubscribedEvents() + { + return [ + TheliaEvents::ORDER_BEFORE_PAYMENT => ['createOrderPurchasePrices', 128], + TheliaEvents::ORDER_AFTER_CREATE => ['saveOrderFamilyAndEquation', 128] + ]; + } + + /** + * Save purchase price for each product of the order + * + * @param OrderEvent $orderEvent + * @throws \Exception + * @throws \Propel\Runtime\Exception\PropelException + */ + public function createOrderPurchasePrices(OrderEvent $orderEvent) + { + $orderProducts = $orderEvent->getOrder()->getOrderProducts(); + $currencyId = $orderEvent->getOrder()->getCurrencyId(); + $customerFamilyId = $this->customerFamilyService->getCustomerCustomerFamilyId($orderEvent->getOrder()->getCustomerId()); + + /** @var \Thelia\Model\OrderProduct $orderProduct */ + foreach ($orderProducts as $orderProduct) { + // If a ProductPurchasePrice exists for the PSE & currency + if (null !== $purchasePrice = $this->customerFamilyService + ->getPurchasePrice( + $orderProduct->getProductSaleElementsId(), + $currencyId)){ + // Initialize equation + $equation = 'Equation not used'; + + // If equation was used, get information about it + if (null !== $customerFamilyPrice = $this->customerFamilyService->getCustomerFamilyPrice( + $customerFamilyId, $orderProduct->getWasInPromo(), 1)) { + + $equation = '( ' . $purchasePrice . ' + ' . $customerFamilyPrice->getAmountAddedBefore() . + ' ) x ' . $customerFamilyPrice->getMultiplicationCoefficient() . ' + ' . + $customerFamilyPrice->getAmountAddedAfter(); + } + + // New OrderProductPurchasePrice + (new OrderProductPurchasePrice()) + ->setOrderProductId($orderProduct->getId()) + ->setPurchasePrice($purchasePrice) + ->setSaleDayEquation($equation) + ->save(); + } + } + } + + /** + * @param OrderEvent $orderEvent + * @throws \Propel\Runtime\Exception\PropelException + */ + public function saveOrderFamilyAndEquation(OrderEvent $orderEvent) + { + $customerFamily = CustomerFamilyQuery::create() + ->findOneById( + $this->customerFamilyService->getCustomerCustomerFamilyId($orderEvent->getOrder()->getCustomerId()) + ); + + (new CustomerFamilyOrder()) + ->setOrderId($orderEvent->getOrder()->getId()) + ->setCustomerFamilyId($customerFamily->getId()) + ->save(); + } +} \ No newline at end of file diff --git a/local/modules/CustomerFamily/EventListeners/CustomerFamilyPriceListener.php b/local/modules/CustomerFamily/EventListeners/CustomerFamilyPriceListener.php new file mode 100644 index 00000000..30afbcca --- /dev/null +++ b/local/modules/CustomerFamily/EventListeners/CustomerFamilyPriceListener.php @@ -0,0 +1,302 @@ + + */ +class CustomerFamilyPriceListener implements EventSubscriberInterface +{ + protected $securityContext; + protected $taxEngine; + protected $customerFamilyService; + + public function __construct(SecurityContext $securityContext, TaxEngine $taxEngine, CustomerFamilyService $customerFamilyService) + { + $this->securityContext = $securityContext; + $this->taxEngine = $taxEngine; + $this->customerFamilyService = $customerFamilyService; + } + + /** + * Returns an array of event names this subscriber wants to listen to. + * + * @return array The event names to listen to + */ + public static function getSubscribedEvents() + { + return [ + TheliaEvents::getLoopExtendsEvent(TheliaEvents::LOOP_EXTENDS_BUILD_MODEL_CRITERIA, 'product') => ['extendProductModelCriteria', 128], + TheliaEvents::getLoopExtendsEvent(TheliaEvents::LOOP_EXTENDS_PARSE_RESULTS, 'product') => ['extendProductParseResult', 128], + TheliaEvents::getLoopExtendsEvent(TheliaEvents::LOOP_EXTENDS_BUILD_MODEL_CRITERIA, 'product_sale_elements') => ['extendProductModelCriteria', 128], + TheliaEvents::getLoopExtendsEvent(TheliaEvents::LOOP_EXTENDS_PARSE_RESULTS, 'product_sale_elements') => ['extendProductParseResult', 128] + ]; + } + + /** + * @param LoopExtendsBuildModelCriteriaEvent $event + * @throws \Propel\Runtime\Exception\PropelException + */ + public function extendProductModelCriteria(LoopExtendsBuildModelCriteriaEvent $event) + { + // Get customer's family + if (null !== $customerFamilyId = $this->customerFamilyService->getCustomerCustomerFamilyId()) { + // Get associated prices + $customerFamilyPrice = $this->customerFamilyService->getCustomerFamilyPrice($customerFamilyId, 0, 1); + $customerFamilyPromoPrice = $this->customerFamilyService->getCustomerFamilyPrice($customerFamilyId, 1, 1); + $useProductPrice = CustomerFamily::getConfigValue('customer_family_price_mode', null); + + if ($customerFamilyPrice !== null || $customerFamilyPromoPrice !== null) { + // Get currency & search + $currencyId = Currency::getDefaultCurrency()->getId(); + $search = $event->getModelCriteria(); + + // If $search is a ProductQuery, table alias is 'pse' + // Else $search is a ProductSaleElementsQuery ans there is no table alias + if ($search instanceof ProductQuery) { + $searchType = 'pse'; + } else { + $searchType = null; + } + + $tableName = ProductPurchasePriceTableMap::TABLE_NAME; + $colCurrencyId = ProductPurchasePriceTableMap::CURRENCY_ID; + $colPrice = ProductPurchasePriceTableMap::PURCHASE_PRICE; + + if ($useProductPrice){ + $tableName = ProductPriceTableMap::TABLE_NAME; + $colCurrencyId = ProductPriceTableMap::COL_CURRENCY_ID; + $colPrice = ProductPriceTableMap::COL_PRICE; + } + + // Link each PSE with its corresponding purchase price, according to the PSE id + $productPurchasePriceJoin = new Join(); + $productPurchasePriceJoin->addExplicitCondition( + ProductSaleElementsTableMap::TABLE_NAME, + 'ID', + $searchType, + $tableName, + 'PRODUCT_SALE_ELEMENTS_ID' + ); + $productPurchasePriceJoin->setJoinType(Criteria::LEFT_JOIN); + + // Add the link to the search, and add a link condition based on the currency + $search + ->addJoinObject($productPurchasePriceJoin, 'purchase_price_join') + ->addJoinCondition('purchase_price_join', $colCurrencyId.' = ?', $currencyId, null, \PDO::PARAM_INT); + + // Add + $this->addProductCalculatedPrice($customerFamilyPrice, $search, $colPrice); + $this->addProductCalculatedPromoPrice($customerFamilyPromoPrice, $search, $colPrice); + } + } + } + + /** + * @param LoopExtendsParseResultsEvent $event + * @throws \Propel\Runtime\Exception\PropelException + */ + public function extendProductParseResult(LoopExtendsParseResultsEvent $event) + { + // Get customer's family + if (null !== $customerFamilyId = $this->customerFamilyService->getCustomerCustomerFamilyId()) { + // Get associated prices + $customerFamilyPrice = $this->customerFamilyService->getCustomerFamilyPrice($customerFamilyId, 0, 1); + $customerFamilyPromoPrice = $this->customerFamilyService->getCustomerFamilyPrice($customerFamilyId, 1, 1); + + if ($customerFamilyPrice !== null || $customerFamilyPromoPrice !== null) { + // Get loop result, tax country & security context + $loopResult = $event->getLoopResult(); + $taxCountry = $this->taxEngine->getDeliveryCountry(); + $securityContext = $this->securityContext; + + foreach ($loopResult as $loopResultRow) { + /** @var \Thelia\Model\Product | \Thelia\Model\ProductSaleElements $product */ + $product = $loopResultRow->model; + + $customerFamilyPriceVirtualColumn = $product->getVirtualColumn('CUSTOMER_FAMILY_PRICE'); + $customerFamilyPromoPriceVirtualColumn = $product->getVirtualColumn('CUSTOMER_FAMILY_PROMO_PRICE'); + + if (!empty($customerFamilyPriceVirtualColumn) || !empty($customerFamilyPromoPriceVirtualColumn)) { + $this->changeProductPrice( + $product, + $loopResultRow, + $taxCountry, + $securityContext + ); + } + } + } + } + } + + /********************************/ + + /** + * @param \CustomerFamily\Model\CustomerFamilyPrice $customerFamilyPrice + * @param \Propel\Runtime\ActiveQuery\ModelCriteria $search + * @param $colPrice + */ + protected function addProductCalculatedPrice($customerFamilyPrice, $search, $colPrice) + { + // Check if products' prices have to be changed depending on the customer's family + if ($customerFamilyPrice !== null) { + $search + ->withColumn( + 'IF (' . $colPrice . ' IS NULL, + NULL, + (' . + $colPrice . + '+' . $customerFamilyPrice->getAmountAddedBefore() . + ') * ' . $customerFamilyPrice->getMultiplicationCoefficient() . + ' + ' . $customerFamilyPrice->getAmountAddedAfter() . + ')', + 'CUSTOMER_FAMILY_PRICE' + ); + } else { + $search->withColumn('NULL', 'CUSTOMER_FAMILY_PRICE'); + } + } + + /** + * @param \CustomerFamily\Model\CustomerFamilyPrice $customerFamilyPromoPrice + * @param \Propel\Runtime\ActiveQuery\ModelCriteria $search + * @param $colPrice + */ + protected function addProductCalculatedPromoPrice($customerFamilyPromoPrice, $search, $colPrice) + { + // Check if products' promo prices have to be changed depending on the customer's family + if ($customerFamilyPromoPrice !== null) { + $search + ->withColumn( + 'IF (' . $colPrice . ' IS NULL, + NULL, + (' . + $colPrice . + '+' . $customerFamilyPromoPrice->getAmountAddedBefore() . + ') * ' . $customerFamilyPromoPrice->getMultiplicationCoefficient() . + ' + ' . $customerFamilyPromoPrice->getAmountAddedAfter() . + ')', + 'CUSTOMER_FAMILY_PROMO_PRICE' + ); + } else { + $search->withColumn('NULL', 'CUSTOMER_FAMILY_PROMO_PRICE'); + } + } + + /********************************/ + + /** + * @param \Thelia\Model\Product | \Thelia\Model\ProductSaleElements $product + * @param \Thelia\Core\Template\Element\LoopResultRow $loopResultRow + * @param \Thelia\Model\Country $taxCountry + * @param SecurityContext $securityContext + */ + protected function changeProductPrice( + $product, + $loopResultRow, + $taxCountry, + SecurityContext $securityContext + ) { + $price = $loopResultRow->get('PRICE'); + $priceTax = $loopResultRow->get('PRICE_TAX'); + $taxedPrice = $loopResultRow->get('TAXED_PRICE'); + $promoPrice = $loopResultRow->get('PROMO_PRICE'); + $promoPriceTax = $loopResultRow->get('PROMO_PRICE_TAX'); + $taxedPromoPrice = $loopResultRow->get('TAXED_PROMO_PRICE'); + + // Replace price + $customerFamilyPriceVirtualColumn = $product->getVirtualColumn('CUSTOMER_FAMILY_PRICE'); + if (!empty($customerFamilyPriceVirtualColumn)) { + $price = round($product->getVirtualColumn('CUSTOMER_FAMILY_PRICE'), 2); + + // If the customer has permanent discount, apply it + if ($securityContext->hasCustomerUser() && $securityContext->getCustomerUser()->getDiscount() > 0) { + $price = $price * (1 - ($securityContext->getCustomerUser()->getDiscount() / 100)); + } + + // Tax price + try { + // If $product is a Product, getTaxedPrice() takes a Country and a price as arguments + // Else if $product is a ProductSaleElements, getTaxedPrice() takes a Country and the price virtual column name as arguments + if ($product instanceof Product) { + $taxedPrice = $product->getTaxedPrice($taxCountry, $price); + } elseif ($product instanceof ProductSaleElements) { + $taxedPrice = $product->getTaxedPrice($taxCountry, 'CUSTOMER_FAMILY_PRICE'); + } + } catch (TaxEngineException $e) { + $taxedPrice = null; + } + + $priceTax = $taxedPrice - $price; + + // Set new price & tax into the loop + $loopResultRow + ->set("PRICE", $price) + ->set("PRICE_TAX", $priceTax) + ->set("TAXED_PRICE", $taxedPrice); + } + + // Replace promo price + $customerFamilyPromoPriceVirtualColumn = $product->getVirtualColumn('CUSTOMER_FAMILY_PROMO_PRICE'); + if (!empty($customerFamilyPromoPriceVirtualColumn)) { + $promoPrice = round($product->getVirtualColumn('CUSTOMER_FAMILY_PROMO_PRICE'), 2); + + // If the customer has permanent discount, apply it + if ($securityContext->hasCustomerUser() && $securityContext->getCustomerUser()->getDiscount() > 0) { + $promoPrice = $promoPrice * (1 - ($securityContext->getCustomerUser()->getDiscount() / 100)); + } + + // Tax promo price + try { + // If $product is a Product, getTaxedPrice() takes a Country and a price as arguments + // Else if $product is a ProductSaleElements, getTaxedPrice() takes a Country and the price virtual column name as arguments + if ($product instanceof Product) { + $taxedPromoPrice = $product->getTaxedPromoPrice($taxCountry, $promoPrice); + } elseif ($product instanceof ProductSaleElements) { + $taxedPromoPrice = $product->getTaxedPromoPrice($taxCountry, 'CUSTOMER_FAMILY_PROMO_PRICE'); + } + } catch (TaxEngineException $e) { + $taxedPromoPrice = null; + } + + $promoPriceTax = $taxedPromoPrice - $promoPrice; + + // Set new promo price & tax into the loop + $loopResultRow + ->set("PROMO_PRICE", $promoPrice) + ->set("PROMO_PRICE_TAX", $promoPriceTax) + ->set("TAXED_PROMO_PRICE", $taxedPromoPrice); + } + + // If current row is a product + if ($product instanceof Product) { + $loopResultRow + ->set("BEST_PRICE", $product->getVirtualColumn('is_promo') ? $promoPrice : $price) + ->set("BEST_PRICE_TAX", $product->getVirtualColumn('is_promo') ? $promoPriceTax : $priceTax) + ->set("BEST_TAXED_PRICE", $product->getVirtualColumn('is_promo') ? $taxedPromoPrice : $taxedPrice); + } + } +} \ No newline at end of file diff --git a/local/modules/CustomerFamily/EventListeners/ProductCreationFormListener.php b/local/modules/CustomerFamily/EventListeners/ProductCreationFormListener.php new file mode 100644 index 00000000..2772eb79 --- /dev/null +++ b/local/modules/CustomerFamily/EventListeners/ProductCreationFormListener.php @@ -0,0 +1,97 @@ + + */ +class ProductCreationFormListener implements EventSubscriberInterface +{ + /** @var \Thelia\Core\HttpFoundation\Request */ + protected $request; + + /** + * @param Request $request + */ + public function __construct(Request $request) + { + $this->request = $request; + } + + /** + * Returns an array of event names this subscriber wants to listen to. + * + * @return array The event names to listen to + */ + public static function getSubscribedEvents() + { + return [ + TheliaEvents::FORM_AFTER_BUILD.'.thelia_product_creation' => ['addPurchasePriceOnProductCreation', 128], + TheliaEvents::PRODUCT_CREATE => ['createProductPurchasePrice', 96] + ]; + } + + /** + * Add purchase price input to product creation form + * + * @param TheliaFormEvent $event + */ + public function addPurchasePriceOnProductCreation(TheliaFormEvent $event) + { + $event->getForm()->getFormBuilder() + ->add( + 'purchase_price', + 'number', + [ + 'constraints' => [ + new Constraints\GreaterThanOrEqual(['value' => 0]) + ], + 'label' => $this->trans('Purchase price'), + 'label_attr' => ['for' => 'purchase_price'] + ] + ) + ; + } + + /** + * Create purchase price when product is created + * + * @param ProductCreateEvent $event + * @throws \Exception + * @throws \Propel\Runtime\Exception\PropelException + */ + public function createProductPurchasePrice(ProductCreateEvent $event) + { + if (null != $purchasePrice = $this->request->get('thelia_product_creation')['purchase_price']) { + (new ProductPurchasePrice()) + ->setProductSaleElementsId($event->getProduct()->getDefaultSaleElements()->getId()) + ->setCurrencyId($event->getCurrencyId()) + ->setPurchasePrice($purchasePrice) + ->save() + ; + } + } + + /** + * Utility for translations + * @param $id + * @param array $parameters + * @return string + */ + protected static function trans($id, array $parameters = array()) + { + return Translator::getInstance()->trans($id, $parameters, CustomerFamily::MESSAGE_DOMAIN); + } +} \ No newline at end of file diff --git a/local/modules/CustomerFamily/EventListeners/ProductExtendPriceFormListener.php b/local/modules/CustomerFamily/EventListeners/ProductExtendPriceFormListener.php new file mode 100644 index 00000000..60d1252d --- /dev/null +++ b/local/modules/CustomerFamily/EventListeners/ProductExtendPriceFormListener.php @@ -0,0 +1,87 @@ + + */ +class ProductExtendPriceFormListener implements EventSubscriberInterface +{ + + /** + * Returns an array of event names this subscriber wants to listen to. + * + * @return array The event names to listen to + */ + public static function getSubscribedEvents() + { + return [TheliaEvents::FORM_AFTER_BUILD . '.thelia_product_default_sale_element_update_form' => ['extendProductPriceForm', 128]]; + } + + /** + * Add a purchase price input to the product + * + * @param TheliaFormEvent $event + */ + public function extendProductPriceForm(TheliaFormEvent $event) + { + $event + ->getForm() + ->getFormBuilder() + ->addEventListener(FormEvents::POST_SUBMIT, [$this, 'handleExtendedData'], 0); + + $event->getForm()->getFormBuilder() + ->add( + 'purchase_price', + 'number', + [ + 'constraints' => [ + new Constraints\GreaterThanOrEqual(['value' => 0]) + ] + ] + ); + } + + /** + * Create or update product's default PSE's purchase price + * + * @param FormEvent $formEvent + * @throws \Exception + * @throws \Propel\Runtime\Exception\PropelException + */ + public function handleExtendedData(FormEvent $formEvent) + { + if (!$formEvent->getForm()->isValid()) { + return; + } + + $data = $formEvent->getData(); + + if (null !== $purchasePrice = ProductPurchasePriceQuery::create() + ->filterByProductSaleElementsId($data['product_sale_element_id']) + ->findOneByCurrencyId($data['currency'])) { + // Update purchase price + $purchasePrice + ->setPurchasePrice($data['purchase_price']) + ->save(); + } else { + // Create new purchase price + (new ProductPurchasePrice()) + ->setProductSaleElementsId($data['product_sale_element_id']) + ->setCurrencyId($data['currency']) + ->setPurchasePrice($data['purchase_price']) + ->save(); + } + } +} \ No newline at end of file diff --git a/local/modules/CustomerFamily/EventListeners/PseExtendPriceFormListener.php b/local/modules/CustomerFamily/EventListeners/PseExtendPriceFormListener.php new file mode 100644 index 00000000..055d208e --- /dev/null +++ b/local/modules/CustomerFamily/EventListeners/PseExtendPriceFormListener.php @@ -0,0 +1,95 @@ + + */ +class PseExtendPriceFormListener implements EventSubscriberInterface +{ + /** + * Returns an array of event names this subscriber wants to listen to. + * + * @return array The event names to listen to + */ + public static function getSubscribedEvents() + { + return [TheliaEvents::FORM_AFTER_BUILD . '.thelia_product_sale_element_update_form' => ['extendPsePriceForm', 128]]; + } + + /** + * Add a purchase price input to PSEs + * + * @param TheliaFormEvent $event + */ + public function extendPsePriceForm(TheliaFormEvent $event) + { + $event + ->getForm() + ->getFormBuilder() + ->addEventListener(FormEvents::POST_SUBMIT, [$this, 'handleExtendedData'], 0); + + $event->getForm()->getFormBuilder() + ->add( + 'purchase_price', + 'collection', + [ + 'type' => 'number', + 'allow_add' => true, + 'allow_delete' => true, + 'options' => [ + 'constraints' => [ + new Constraints\GreaterThanOrEqual(['value' => 0]) + ] + ] + ] + ); + } + + /** + * Create or update PSE's purchase price + * + * @param FormEvent $formEvent + * @throws \Exception + * @throws \Propel\Runtime\Exception\PropelException + */ + public function handleExtendedData(FormEvent $formEvent) + { + if (!$formEvent->getForm()->isValid()) { + return; + } + + $data = $formEvent->getData(); + + if (is_array($data['product_sale_element_id'])) { + foreach (array_keys($data['product_sale_element_id']) as $idx) { + if (null !== $purchasePrice = ProductPurchasePriceQuery::create() + ->filterByProductSaleElementsId($data['product_sale_element_id'][$idx]) + ->findOneByCurrencyId($data['currency'])) { + // Update purchase price + $purchasePrice + ->setPurchasePrice($data['purchase_price'][$idx]) + ->save(); + } else { + // Create new purchase price + (new ProductPurchasePrice()) + ->setProductSaleElementsId($data['product_sale_element_id'][$idx]) + ->setCurrencyId($data['currency']) + ->setPurchasePrice($data['purchase_price'][$idx]) + ->save(); + } + } + } + } +} \ No newline at end of file diff --git a/local/modules/CustomerFamily/Form/CustomerCustomerFamilyForm.php b/local/modules/CustomerFamily/Form/CustomerCustomerFamilyForm.php new file mode 100644 index 00000000..5bf34a10 --- /dev/null +++ b/local/modules/CustomerFamily/Form/CustomerCustomerFamilyForm.php @@ -0,0 +1,122 @@ +getRequest()->request->get("customer_customer_family_form")) { + if (array_key_exists("customer_family_id", $form) && + $form["customer_family_id"] == $customerFamily->getId()) { + if (strlen($value) <= 1) { + $context->addViolation(Translator::getInstance()->trans( + "This field can't be empty", + array(), + CustomerFamily::MESSAGE_DOMAIN + )); + } + } + } + } + + protected function buildForm() + { + $this->formBuilder + ->add('customer_id', 'integer', array( + 'constraints' => array( + new Constraints\NotBlank() + ), + 'label' => Translator::getInstance()->trans( + 'Customer', + array(), + CustomerFamily::MESSAGE_DOMAIN + ), + 'label_attr' => array( + 'for' => 'customer_id' + ) + )) + ->add('customer_family_id', 'integer', array( + 'constraints' => array( + new Constraints\NotBlank() + ), + 'label' => Translator::getInstance()->trans( + 'Customer family', + array(), + CustomerFamily::MESSAGE_DOMAIN + ), + 'label_attr' => array( + 'for' => 'customer_id' + ) + )) + ->add( + 'siret', + 'text', + array( + 'required' => false, + 'empty_data' => false, + 'label' => Translator::getInstance()->trans( + 'Siret number', + array(), + CustomerFamily::MESSAGE_DOMAIN + ), + 'label_attr' => array( + 'for' => 'siret' + ) + ) + ) + ->add( + 'vat', + 'text', + array( + 'required' => false, + 'empty_data' => false, + 'label' => Translator::getInstance()->trans( + 'Vat', + array(), + CustomerFamily::MESSAGE_DOMAIN + ), + 'label_attr' => array( + 'for' => 'vat' + ) + ) + ) + ; + } +} diff --git a/local/modules/CustomerFamily/Form/CustomerFamilyCreateForm.php b/local/modules/CustomerFamily/Form/CustomerFamilyCreateForm.php new file mode 100644 index 00000000..90c7738f --- /dev/null +++ b/local/modules/CustomerFamily/Form/CustomerFamilyCreateForm.php @@ -0,0 +1,110 @@ +findOneByCode($value) === null) { + $context->addViolation(Translator::getInstance()->trans( + "Invalid locale" + )); + } + } + + protected function buildForm() + { + $this->formBuilder + ->add( + 'code', + 'text', + array( + 'constraints' => array( + new NotBlank() + ), + 'required' => true, + 'empty_data' => false, + 'label' => Translator::getInstance()->trans( + 'Code', + array(), + CustomerFamily::MESSAGE_DOMAIN + ), + 'label_attr' => array( + 'for' => 'code' + ) + ) + ) + ->add( + 'title', + 'text', + array( + 'constraints' => array( + new NotBlank() + ), + 'required' => true, + 'empty_data' => false, + 'label' => Translator::getInstance()->trans( + 'Title' + ), + 'label_attr' => array( + 'for' => 'title' + ) + ) + ) + ->add( + 'locale', + 'text', + array( + 'constraints' => array( + new NotBlank(), + new Callback(array("methods" => array( + array($this, "checkLocale") + ))) + ), + 'required' => true, + 'empty_data' => false, + 'label' => Translator::getInstance()->trans( + 'Locale' + ), + 'label_attr' => array( + 'for' => 'locale' + ) + ) + ); + } +} diff --git a/local/modules/CustomerFamily/Form/CustomerFamilyDeleteForm.php b/local/modules/CustomerFamily/Form/CustomerFamilyDeleteForm.php new file mode 100644 index 00000000..fa227f9c --- /dev/null +++ b/local/modules/CustomerFamily/Form/CustomerFamilyDeleteForm.php @@ -0,0 +1,35 @@ + + */ +class CustomerFamilyPriceForm extends BaseForm +{ + public function getName() + { + return 'customer_family_price_update'; + } + + protected function buildForm() + { + $this->formBuilder + ->add( + 'customer_family_id', + 'integer' + ) + ->add( + 'promo', + 'integer' + ) + ->add( + 'use_equation', + 'checkbox', + [] + ) + ->add( + 'amount_added_before', + 'number', + [ + 'precision' => 6, + 'required' => false + ] + ) + ->add( + 'amount_added_after', + 'number', + [ + 'precision' => 6, + 'required' => false + ] + ) + ->add( + 'coefficient', + 'number', + [ + 'precision' => 6, + 'required' => false + ] + ) + ->add( + 'is_taxed', + 'checkbox', + [] + ) + ; + } +} \ No newline at end of file diff --git a/local/modules/CustomerFamily/Form/CustomerFamilyPriceModeForm.php b/local/modules/CustomerFamily/Form/CustomerFamilyPriceModeForm.php new file mode 100644 index 00000000..554a1f06 --- /dev/null +++ b/local/modules/CustomerFamily/Form/CustomerFamilyPriceModeForm.php @@ -0,0 +1,45 @@ +formBuilder + ->add( + "price_mode", + CheckboxType::class, + [ + "label" => $this->translator->trans("Use the product price", [], CustomerFamily::MESSAGE_DOMAIN), + "data" => $value, + 'label_attr' => [ + 'help' => $this->translator->trans( + "By checking this check box this module will use the product price of Thelia instead of the the purchase price of CustomerFamily", + [], + CustomerFamily::MESSAGE_DOMAIN), + ] + ] + ); + } + +} \ No newline at end of file diff --git a/local/modules/CustomerFamily/Form/CustomerFamilyUpdateDefaultForm.php b/local/modules/CustomerFamily/Form/CustomerFamilyUpdateDefaultForm.php new file mode 100644 index 00000000..824e075f --- /dev/null +++ b/local/modules/CustomerFamily/Form/CustomerFamilyUpdateDefaultForm.php @@ -0,0 +1,26 @@ +formBuilder + ->add( + 'customer_family_id', + 'integer' + ); + } +} \ No newline at end of file diff --git a/local/modules/CustomerFamily/Form/CustomerFamilyUpdateForm.php b/local/modules/CustomerFamily/Form/CustomerFamilyUpdateForm.php new file mode 100644 index 00000000..d282f660 --- /dev/null +++ b/local/modules/CustomerFamily/Form/CustomerFamilyUpdateForm.php @@ -0,0 +1,33 @@ +getCustomer(); + + if (is_null($customer)) { + // No customer => nothing to do. + return; + } + + $customerId = $customer->getId(); + + if ($customerId <= 0) { + // Wrong customer => return. + return; + } + + $title = $this->trans('My customer family', [], CustomerFamily::MESSAGE_DOMAIN); + + $event->add(array( + 'id' => $customerId, + 'title' => $title, + 'content' => $this->render( + 'account-additional.html', + array( + 'customerId' => $customerId, + 'messageDomain' => CustomerFamily::MESSAGE_DOMAIN, + 'particular' => CustomerFamily::CUSTOMER_FAMILY_PARTICULAR, + 'title' => $title, + ) + ), + )); + } +} diff --git a/local/modules/CustomerFamily/Hook/CustomerFamilyHook.php b/local/modules/CustomerFamily/Hook/CustomerFamilyHook.php new file mode 100644 index 00000000..1793ecd0 --- /dev/null +++ b/local/modules/CustomerFamily/Hook/CustomerFamilyHook.php @@ -0,0 +1,19 @@ + + */ +class CustomerFamilyHook extends BaseHook +{ + public function onAddCss(HookRenderEvent $event) + { + $event->add($this->addCSS('assets/css/style.css')); + } +} \ No newline at end of file diff --git a/local/modules/CustomerFamily/Hook/CustomerFamilyProductPriceHook.php b/local/modules/CustomerFamily/Hook/CustomerFamilyProductPriceHook.php new file mode 100644 index 00000000..5e747689 --- /dev/null +++ b/local/modules/CustomerFamily/Hook/CustomerFamilyProductPriceHook.php @@ -0,0 +1,25 @@ + + */ +class CustomerFamilyProductPriceHook extends BaseHook +{ + public function onPsePriceEdit(HookRenderEvent $event) + { + $event->add($this->render( + 'product-edit-price.html', + [ + 'pseId' => $event->getArgument('pse'), + 'idx' => $event->getArgument('idx') + ] + )); + } +} \ No newline at end of file diff --git a/local/modules/CustomerFamily/Hook/CustomerFamilyRegisterFormHook.php b/local/modules/CustomerFamily/Hook/CustomerFamilyRegisterFormHook.php new file mode 100644 index 00000000..721b6d16 --- /dev/null +++ b/local/modules/CustomerFamily/Hook/CustomerFamilyRegisterFormHook.php @@ -0,0 +1,44 @@ +add($this->render( + 'register.html', + array( + 'form' => $event->getArgument('form'), + 'messageDomain' => CustomerFamily::MESSAGE_DOMAIN, + ) + )); + } + + /** + * Javascript for extra form fields. + * @param HookRenderEvent $event + */ + public function onRegisterAfterJSInclude(HookRenderEvent $event) + { + $event->add($this->addJS('assets/js/register.js')); + } +} diff --git a/local/modules/CustomerFamily/Hook/CustomerFamilyToolsHook.php b/local/modules/CustomerFamily/Hook/CustomerFamilyToolsHook.php new file mode 100644 index 00000000..ec045045 --- /dev/null +++ b/local/modules/CustomerFamily/Hook/CustomerFamilyToolsHook.php @@ -0,0 +1,29 @@ +add( + [ + 'id' => 'tools_menu_customer_family', + 'class' => '', + 'url' => URL::getInstance()->absoluteUrl('/admin/module/CustomerFamily'), + 'title' => "Customer families" + ] + ); + } +} \ No newline at end of file diff --git a/local/modules/CustomerFamily/Hook/CustomerFamilyUpdateFormHook.php b/local/modules/CustomerFamily/Hook/CustomerFamilyUpdateFormHook.php new file mode 100644 index 00000000..83f637ed --- /dev/null +++ b/local/modules/CustomerFamily/Hook/CustomerFamilyUpdateFormHook.php @@ -0,0 +1,36 @@ +add($this->render( + 'account-update.html', + array( + 'form' => $event->getArgument('form'), + 'messageDomain' => CustomerFamily::MESSAGE_DOMAIN, + ) + )); + } + + public function onAccountUpdateAfterJSInclude(HookRenderEvent $event) + { + $event->add($this->addJS('assets/js/update.js')); + } +} diff --git a/local/modules/CustomerFamily/I18n/backOffice/default/fr_FR.php b/local/modules/CustomerFamily/I18n/backOffice/default/fr_FR.php new file mode 100644 index 00000000..2c67259d --- /dev/null +++ b/local/modules/CustomerFamily/I18n/backOffice/default/fr_FR.php @@ -0,0 +1,54 @@ + '(nécessite une intégration spécifique)', + 'Action' => 'Action', + 'Add' => 'Ajouter', + 'An error occured' => 'Une erreur est survenue', + 'Brand restrictions' => 'Restriction de marque', + 'Calculated price' => 'Prix calculé', + 'Calculated prices for:' => 'Prix calculé pour :', + 'Calculated promo price' => 'Prix promo calculé', + 'Cancel' => 'Annuler', + 'Category restrictions' => 'Restriction de catégorie', + 'Choose what brands will be available for this customer family' => 'Choisissez les marques disponibles pour cette famille de client', + 'Choose what categories will be available for this customer family' => 'Choisissez les catégories disponibles pour cette famille de client', + 'Code' => 'Code', + 'Customer Family' => 'Familles de clients', + 'Customer family' => 'Famille', + 'Default' => 'Défault', + 'Define if your prices are the products\' ones or if they are calculated by the equation with your parameters.' => 'Définit si les produits affichent leur prix ou un prix calculé à partir de leur prix d\'achat via l\'équation suivante.', + 'Delete' => 'Supprimer', + 'Do you really want to delete this customer family ?' => 'Voulez-vous vraiment supprimer cette famille de clients ?', + 'Edit' => 'Éditer', + 'Edit information in %lng' => 'Information d\'édition en %lng', + 'Enable brand restriction for this customer family' => 'Activer la restriction de marque pour cette famille de client', + 'Enable category restriction for this customer family' => 'Activer la restriction de catégorie pour cette famille de client', + 'Enter here the product purchase price in %title' => 'Indiquez ici le prix d\'achat HT en %title', + 'Equation: ( ( product_purchase_price + fix_amount_1 ) x factor ) + fix_amount_2' => 'Equation : ( ( prix_d_achat + montant_fixe_1 ) x facteur ) + montant_fixe_2', + 'Factor' => 'Facteur', + 'Families' => 'Familles', + 'Family of this customer' => 'Famille de ce client', + 'Fix amount 1' => 'Montant fixe 1', + 'Fix amount 2' => 'Montant fixe 2', + 'ID' => 'ID', + 'No' => 'Non', + 'No family' => 'Aucune famille', + 'Not using the equation will display the fix product price to customers.' => 'Ne pas utiliser l\'équation affichera le prix fixe des produits.', + 'Placeholder SIRET' => 'SIRET', + 'Placeholder V.A.T.' => 'VAT', + 'Placeholder siret' => 'SIRET', + 'Placeholder vat' => 'Taxe sur la Valeur Ajoutée', + 'Price for:' => 'Prix pour :', + 'Prices definition' => 'Définition des prix', + 'Promo' => 'Promo', + 'Purchase price' => 'Prix d\'achat', + 'Purchase price (w/o taxes)' => 'Prix d\'achat HT', + 'Save' => 'Enregistrer', + 'Select customer family' => 'Sélectionnez le type de compte', + 'Show taxes' => 'Afficher le prix taxé', + 'Title' => 'Nom', + 'Update' => 'Mettre à jour', + 'Use equation' => 'Utiliser l\'équation', + 'Yes' => 'Oui', +); diff --git a/local/modules/CustomerFamily/I18n/en_US.php b/local/modules/CustomerFamily/I18n/en_US.php new file mode 100644 index 00000000..e00d3ff2 --- /dev/null +++ b/local/modules/CustomerFamily/I18n/en_US.php @@ -0,0 +1,21 @@ + "Customer family", + + //F + "Family of this customer" => "Customer family", + + //S + "Siret number" => "Siret number", + + //T + "This field can't be empty" => "This field can't be empty", + + //V + "Vat" => "VAT", + + //P + 'Placeholder SIRET' => 'Siret numbe', + 'Placeholder V.A.T.' => 'VAT', +); diff --git a/local/modules/CustomerFamily/I18n/fr_FR.php b/local/modules/CustomerFamily/I18n/fr_FR.php new file mode 100644 index 00000000..cf3c290f --- /dev/null +++ b/local/modules/CustomerFamily/I18n/fr_FR.php @@ -0,0 +1,20 @@ + 'Code', + 'Customer' => 'Client', + 'Customer family' => 'Famille clients', + 'Customer family was created successfully' => 'La famille a été créée avec succès', + 'Customer family was deleted successfully' => 'La famille a été supprimée avec succès', + 'Customer family was updated successfully' => 'La famille a été modifiée avec succès', + 'CustomerFamily configuration' => 'Configuration des familles de clients', + 'Error updating default family' => 'Erreur lors de la mise à jour de la famille par défaut', + 'Invalid locale' => 'Langue invalide', + 'Locale' => 'Langue', + 'My customer family' => 'Ma famille de clients', + 'Purchase price' => 'Prix d\'achat', + 'Siret number' => 'Numéro de SIRET', + 'This field can\'t be empty' => 'Ce champs ne peut pas être vide', + 'Title' => 'Nom', + 'Vat' => 'TVA intracommunautaire', +); diff --git a/local/modules/CustomerFamily/I18n/frontOffice/default/fr_FR.php b/local/modules/CustomerFamily/I18n/frontOffice/default/fr_FR.php new file mode 100644 index 00000000..bed9eb21 --- /dev/null +++ b/local/modules/CustomerFamily/I18n/frontOffice/default/fr_FR.php @@ -0,0 +1,10 @@ + 'Famille de client', + 'Placeholder SIRET' => 'SIRET', + 'Placeholder V.A.T.' => 'Taxe sur la Valeur Ajoutée', + 'Select customer family' => 'Sélectionnez un type de compte', + 'Siret number' => 'SIRET', + 'Vat' => 'Taxe sur la Valeur Ajoutée', +); diff --git a/local/modules/CustomerFamily/LICENSE.txt b/local/modules/CustomerFamily/LICENSE.txt new file mode 100644 index 00000000..02bbb60b --- /dev/null +++ b/local/modules/CustomerFamily/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. \ No newline at end of file diff --git a/local/modules/CustomerFamily/Loop/CustomerCustomerFamilyLoop.php b/local/modules/CustomerFamily/Loop/CustomerCustomerFamilyLoop.php new file mode 100644 index 00000000..d8e0d74d --- /dev/null +++ b/local/modules/CustomerFamily/Loop/CustomerCustomerFamilyLoop.php @@ -0,0 +1,100 @@ +getCustomerId()) { + $search->filterByCustomerId($customerId, Criteria::IN); + } + + if (null !== $customerFamilyId = $this->getCustomerFamilyId()) { + $search->filterByCustomerFamilyId($customerFamilyId, Criteria::IN); + } + + if (null !== $customerFamilyCode = $this->getCustomerFamilyCode()) { + $join = new Join( + CustomerCustomerFamilyTableMap::CUSTOMER_FAMILY_ID, + CustomerFamilyTableMap::ID, + Criteria::INNER_JOIN + ); + + $search->addJoinObject($join, "customer_family_join") + ->addJoinCondition("customer_family_join", CustomerFamilyTableMap::CODE." = '$customerFamilyCode'"); + } + + return $search; + } + + /** + * @param LoopResult $loopResult + * + * @return LoopResult + */ + public function parseResults(LoopResult $loopResult) + { + foreach ($loopResult->getResultDataCollection() as $customerCustomerFamily) { + /** @var \CustomerFamily\Model\CustomerCustomerFamily $customerCustomerFamily */ + $loopResultRow = new LoopResultRow($customerCustomerFamily); + $loopResultRow + ->set("CUSTOMER_FAMILY_ID", $customerCustomerFamily->getCustomerFamilyId()) + ->set("CUSTOMER_ID", $customerCustomerFamily->getCustomerId()) + ->set("SIRET", $customerCustomerFamily->getSiret()) + ->set("VAT", $customerCustomerFamily->getVat()) + ; + + $loopResult->addRow($loopResultRow); + } + + return $loopResult; + } +} diff --git a/local/modules/CustomerFamily/Loop/CustomerFamilyLoop.php b/local/modules/CustomerFamily/Loop/CustomerFamilyLoop.php new file mode 100644 index 00000000..7f030ac6 --- /dev/null +++ b/local/modules/CustomerFamily/Loop/CustomerFamilyLoop.php @@ -0,0 +1,107 @@ +configureI18nProcessing($search, array('TITLE')); + + if (null !== $id = $this->getId()) { + $search->filterById($id, Criteria::IN); + } + + if (null !== $code = $this->getCode()) { + $search->filterByCode($code, Criteria::IN); + } + + if (null !== $excludeId = $this->getExcludeId()) { + $search->filterById($excludeId, Criteria::NOT_IN); + } + + if (null !== $isDefault = $this->getIsDefault()) { + $search->filterByIsDefault($isDefault); + } + + return $search; + } + + /** + * @param LoopResult $loopResult + *` + * @return LoopResult + */ + public function parseResults(LoopResult $loopResult) + { + foreach ($loopResult->getResultDataCollection() as $customerFamily) { + /** @var CustomerFamily $customerFamily */ + $loopResultRow = new LoopResultRow($customerFamily); + $loopResultRow + ->set("CUSTOMER_FAMILY_ID", $customerFamily->getId()) + ->set("CODE", $customerFamily->getCode()) + ->set("TITLE_CUSTOMER_FAMILY", $customerFamily->getVirtualColumn('i18n_TITLE')) + ->set("IS_DEFAULT", $customerFamily->getIsDefault()) + ->set("CATEGORY_RESTRICTION_ENABLED", $customerFamily->getCategoryRestrictionEnabled()) + ->set("BRAND_RESTRICTION_ENABLED", $customerFamily->getBrandRestrictionEnabled()); + + $loopResult->addRow($loopResultRow); + } + + return $loopResult; + } +} diff --git a/local/modules/CustomerFamily/Loop/CustomerFamilyPriceLoop.php b/local/modules/CustomerFamily/Loop/CustomerFamilyPriceLoop.php new file mode 100644 index 00000000..68ee67d9 --- /dev/null +++ b/local/modules/CustomerFamily/Loop/CustomerFamilyPriceLoop.php @@ -0,0 +1,82 @@ + + */ +class CustomerFamilyPriceLoop extends BaseLoop implements PropelSearchLoopInterface +{ + /** + * Definition of loop arguments + * + * @return \Thelia\Core\Template\Loop\Argument\ArgumentCollection + */ + protected function getArgDefinitions() + { + return new ArgumentCollection( + Argument::createIntListTypeArgument('customer_family_id'), + Argument::createBooleanTypeArgument('promo'), + Argument::createBooleanTypeArgument('use_equation') + ); + } + + /** + * @return CustomerFamilyPriceQuery + */ + public function buildModelCriteria() + { + $search = CustomerFamilyPriceQuery::create(); + + if (null !== $customerFamilyId = $this->getCustomerFamilyId()) { + $search->filterByCustomerFamilyId($customerFamilyId, Criteria::IN); + } + + if (null !== $promo = $this->getPromo()) { + $search->filterByPromo($promo); + } + + if (null !== $useEquation = $this->getUseEquation()) { + $search->filterByUseEquation($useEquation); + } + + return $search; + } + + /** + * @param LoopResult $loopResult + * + * @return LoopResult + */ + public function parseResults(LoopResult $loopResult) + { + /** @var \CustomerFamily\Model\CustomerFamilyPrice $customerFamilyPrice */ + foreach ($loopResult->getResultDataCollection() as $customerFamilyPrice) { + $loopResultRow = new LoopResultRow($customerFamilyPrice); + + $loopResultRow + ->set('CUSTOMER_FAMILY_ID', $customerFamilyPrice->getCustomerFamilyId()) + ->set('PROMO', $customerFamilyPrice->getPromo()) + ->set('USE_EQUATION', $customerFamilyPrice->getUseEquation()) + ->set('AMOUNT_ADDED_BEFORE', $customerFamilyPrice->getAmountAddedBefore()) + ->set('AMOUNT_ADDED_AFTER', $customerFamilyPrice->getAmountAddedAfter()) + ->set('COEFFICIENT', $customerFamilyPrice->getMultiplicationCoefficient()) + ->set('IS_TAXED', $customerFamilyPrice->getIsTaxed()); + + $loopResult->addRow($loopResultRow); + } + + return $loopResult; + } +} \ No newline at end of file diff --git a/local/modules/CustomerFamily/Loop/CustomerFamilyProductPriceLoop.php b/local/modules/CustomerFamily/Loop/CustomerFamilyProductPriceLoop.php new file mode 100644 index 00000000..42108196 --- /dev/null +++ b/local/modules/CustomerFamily/Loop/CustomerFamilyProductPriceLoop.php @@ -0,0 +1,94 @@ + + */ +class CustomerFamilyProductPriceLoop extends BaseLoop implements ArraySearchLoopInterface +{ + /** + * Definition of loop arguments + * + * @return \Thelia\Core\Template\Loop\Argument\ArgumentCollection + */ + protected function getArgDefinitions() + { + return new ArgumentCollection( + Argument::createIntTypeArgument('pse_id', null, true), + Argument::createIntTypeArgument('currency_id', Currency::getDefaultCurrency()->getId()), + Argument::createIntTypeArgument('customer_family_id', null, true) + ); + } + + /** + * this method returns an array + * + * @return array + */ + public function buildArray() + { + $items = []; + + $items['pse_id'] = $this->getPseId(); + $items['currency_id'] = $this->getCurrencyId(); + $items['customerFamilyId'] = $this->getCustomerFamilyId(); + + return $items; + } + + /** + * @param LoopResult $loopResult + * + * @return LoopResult + */ + public function parseResults(LoopResult $loopResult) + { + $items = $loopResult->getResultDataCollection(); + + /** @var \CustomerFamily\Service\CustomerFamilyService $customerFamilyService */ + $customerFamilyService = $this->container->get('customer.family.service'); + + $pse = ProductSaleElementsQuery::create()->findOneById($items['pse_id']); + + $prices = $customerFamilyService->calculateCustomerFamilyPsePrice($pse, $items['customerFamilyId'], $items['currency_id']); + + $loopResultRow = new LoopResultRow(); + + $loopResultRow->set("CALCULATED_PRICE", $prices['price']); + $loopResultRow->set("CALCULATED_TAXED_PRICE", $prices['taxedPrice']); + $loopResultRow->set("CALCULATED_PROMO_PRICE", $prices['promoPrice']); + $loopResultRow->set("CALCULATED_TAXED_PROMO_PRICE", $prices['taxedPromoPrice']); + + $loopResult->addRow($loopResultRow); + + return $loopResult; + } +} + + + + + + + + + + + + + + + + diff --git a/local/modules/CustomerFamily/Loop/ProductPurchasePriceLoop.php b/local/modules/CustomerFamily/Loop/ProductPurchasePriceLoop.php new file mode 100644 index 00000000..5579c532 --- /dev/null +++ b/local/modules/CustomerFamily/Loop/ProductPurchasePriceLoop.php @@ -0,0 +1,84 @@ + + */ +class ProductPurchasePriceLoop extends BaseLoop implements PropelSearchLoopInterface +{ + /** + * Definition of loop arguments + * + * @return \Thelia\Core\Template\Loop\Argument\ArgumentCollection + */ + protected function getArgDefinitions() + { + return new ArgumentCollection( + Argument::createIntTypeArgument('pse_id', null, true), + Argument::createIntTypeArgument('currency_id', null, true) + ); + } + + /** + * @return ProductPurchasePriceQuery|\Propel\Runtime\ActiveQuery\ModelCriteria|\Thelia\Model\ProductPrice + */ + public function buildModelCriteria() + { + + if(CustomerFamily::getConfigValue('customer_family_price_mode', null)){ + return $search = ProductPriceQuery::create() + ->filterByCurrencyId($this->getCurrencyId()) + ->filterByProductSaleElementsId($this->getPseId()); + } + return $search = ProductPurchasePriceQuery::create() + ->filterByProductSaleElementsId($this->getPseId()) + ->filterByCurrencyId($this->getCurrencyId()); + + } + + /** + * @param LoopResult $loopResult + * + * @return LoopResult + */ + public function parseResults(LoopResult $loopResult) + { + /** @var \CustomerFamily\Model\ProductPurchasePrice $productPurchasePrice */ + foreach ($loopResult->getResultDataCollection() as $productPurchasePrice) { + $loopResultRow = new LoopResultRow($productPurchasePrice); + + $loopResultRow + ->set('PSE_ID', $this->getPseId()) + ->set('CURRENCY_ID', $this->getCurrencyId()); + + if (is_a($productPurchasePrice, '\CustomerFamily\Model\ProductPurchasePrice')){ + $loopResultRow->set('PURCHASE_PRICE', $productPurchasePrice->getPurchasePrice()); + } else { + /** @var ProductPrice $productPurchasePrice*/ + $loopResultRow->set('PURCHASE_PRICE', $productPurchasePrice->getPrice()); + } + + $loopResult->addRow($loopResultRow); + } + + return $loopResult; + } + +} \ No newline at end of file diff --git a/local/modules/CustomerFamily/LoopExtend/BaseCustomerFamilyLoopExtend.php b/local/modules/CustomerFamily/LoopExtend/BaseCustomerFamilyLoopExtend.php new file mode 100644 index 00000000..67cb3abd --- /dev/null +++ b/local/modules/CustomerFamily/LoopExtend/BaseCustomerFamilyLoopExtend.php @@ -0,0 +1,34 @@ +securityContext = $securityContext; + } + + public function getCustomerFamily() + { + $currentCustomer = $this->securityContext->getCustomerUser(); + + if (null === $currentCustomer) { + return null; + } + + $customerFamily = CustomerFamilyQuery::create() + ->useCustomerCustomerFamilyQuery() + ->filterByCustomerId($currentCustomer->getId()) + ->endUse() + ->findOne(); + + return $customerFamily; + } +} \ No newline at end of file diff --git a/local/modules/CustomerFamily/LoopExtend/BrandLoopExtend.php b/local/modules/CustomerFamily/LoopExtend/BrandLoopExtend.php new file mode 100644 index 00000000..7b5d7091 --- /dev/null +++ b/local/modules/CustomerFamily/LoopExtend/BrandLoopExtend.php @@ -0,0 +1,54 @@ + ['buildModelCriteria', 128], + ]; + } + + public function buildModelCriteria(LoopExtendsBuildModelCriteriaEvent $event) + { + if ($event->getLoop()->getBackendContext()) { + return null; + } + + $customerFamily = $this->getCustomerFamily(); + + if (null === $customerFamily || !$customerFamily->getBrandRestrictionEnabled()) { + return; + } + + $query = $event->getModelCriteria(); + + $join = new Join(); + $join->addExplicitCondition( + BrandTableMap::TABLE_NAME, + 'ID', + 'brand', + CustomerFamilyAvailableBrandTableMap::TABLE_NAME, + 'brand_id', + 'customer_family_available_brand' + ); + $join->setJoinType(Criteria::INNER_JOIN); + + $query->addJoinObject($join, 'customer_family_available_brand_join'); + $query->addJoinCondition( + 'customer_family_available_brand_join', + 'customer_family_available_brand_join.customer_family_id = ? ', + $customerFamily->getId() + ); + } +} \ No newline at end of file diff --git a/local/modules/CustomerFamily/LoopExtend/CategoryLoopExtend.php b/local/modules/CustomerFamily/LoopExtend/CategoryLoopExtend.php new file mode 100644 index 00000000..f8d68ab1 --- /dev/null +++ b/local/modules/CustomerFamily/LoopExtend/CategoryLoopExtend.php @@ -0,0 +1,54 @@ + ['buildModelCriteria', 128], + ]; + } + + public function buildModelCriteria(LoopExtendsBuildModelCriteriaEvent $event) + { + if ($event->getLoop()->getBackendContext()) { + return null; + } + + $customerFamily = $this->getCustomerFamily(); + + if (null === $customerFamily || !$customerFamily->getCategoryRestrictionEnabled()) { + return; + } + + $query = $event->getModelCriteria(); + + $join = new Join(); + $join->addExplicitCondition( + CategoryTableMap::TABLE_NAME, + 'ID', + 'category', + CustomerFamilyAvailableCategoryTableMap::TABLE_NAME, + 'category_id', + 'customer_family_available_category' + ); + $join->setJoinType(Criteria::INNER_JOIN); + + $query->addJoinObject($join, 'customer_family_available_category_join'); + $query->addJoinCondition( + 'customer_family_available_category_join', + 'customer_family_available_category_join.customer_family_id = ? ', + $customerFamily->getId() + ); + } +} \ No newline at end of file diff --git a/local/modules/CustomerFamily/LoopExtend/ProductLoopExtend.php b/local/modules/CustomerFamily/LoopExtend/ProductLoopExtend.php new file mode 100644 index 00000000..6d3f869a --- /dev/null +++ b/local/modules/CustomerFamily/LoopExtend/ProductLoopExtend.php @@ -0,0 +1,103 @@ + ['buildModelCriteria', 128], + ]; + } + + public function buildModelCriteria(LoopExtendsBuildModelCriteriaEvent $event) + { + if ($event->getLoop()->getBackendContext()) { + return null; + } + + $customerFamily = $this->getCustomerFamily(); + if (null === $customerFamily) { + return; + } + + $query = $event->getModelCriteria(); + $this->addCategoryFilter($query, $customerFamily); + $this->addBrandFilter($query, $customerFamily); + } + + protected function addCategoryFilter(ModelCriteria $query, CustomerFamily $customerFamily) + { + if (!$customerFamily->getCategoryRestrictionEnabled()) { + return; + } + + $join = new Join(); + $join->addExplicitCondition( + ProductTableMap::TABLE_NAME, + 'ID', + 'product', + ProductCategoryTableMap::TABLE_NAME, + 'product_id', + 'cf_product_category' + ); + $join->setJoinType(Criteria::INNER_JOIN); + $query->addJoinObject($join, 'customer_family_product_category_join'); + + $join = new Join(); + $join->addExplicitCondition( + ProductCategoryTableMap::TABLE_NAME, + 'category_id', + 'cf_product_category', + CustomerFamilyAvailableCategoryTableMap::TABLE_NAME, + 'category_id', + 'customer_family_available_category' + ); + $join->setJoinType(Criteria::INNER_JOIN); + $query->addJoinObject($join, 'customer_family_available_category_join'); + + $query->addJoinCondition( + 'customer_family_available_category_join', + 'customer_family_available_category_join.customer_family_id = ? ', + $customerFamily->getId() + ); + } + + protected function addBrandFilter(ModelCriteria $query, CustomerFamily $customerFamily) + { + if (!$customerFamily->getBrandRestrictionEnabled()) { + return; + } + + $join = new Join(); + $join->addExplicitCondition( + ProductTableMap::TABLE_NAME, + 'brand_id', + 'product', + CustomerFamilyAvailableBrandTableMap::TABLE_NAME, + 'brand_id', + 'customer_family_available_brand' + ); + $join->setJoinType(Criteria::INNER_JOIN); + $query->addJoinObject($join, 'customer_family_available_brand_join'); + + $query->addJoinCondition( + 'customer_family_available_brand_join', + 'customer_family_available_brand_join.customer_family_id = ? ', + $customerFamily->getId() + ); + } +} \ No newline at end of file diff --git a/local/modules/CustomerFamily/Model/Base/CustomerCustomerFamily.php b/local/modules/CustomerFamily/Model/Base/CustomerCustomerFamily.php new file mode 100644 index 00000000..ad735a74 --- /dev/null +++ b/local/modules/CustomerFamily/Model/Base/CustomerCustomerFamily.php @@ -0,0 +1,1371 @@ +modifiedColumns; + } + + /** + * Has specified column been modified? + * + * @param string $col column fully qualified name (TableMap::TYPE_COLNAME), e.g. Book::AUTHOR_ID + * @return boolean True if $col has been modified. + */ + public function isColumnModified($col) + { + return $this->modifiedColumns && isset($this->modifiedColumns[$col]); + } + + /** + * Get the columns that have been modified in this object. + * @return array A unique list of the modified column names for this object. + */ + public function getModifiedColumns() + { + return $this->modifiedColumns ? array_keys($this->modifiedColumns) : []; + } + + /** + * Returns whether the object has ever been saved. This will + * be false, if the object was retrieved from storage or was created + * and then saved. + * + * @return boolean true, if the object has never been persisted. + */ + public function isNew() + { + return $this->new; + } + + /** + * Setter for the isNew attribute. This method will be called + * by Propel-generated children and objects. + * + * @param boolean $b the state of the object. + */ + public function setNew($b) + { + $this->new = (Boolean) $b; + } + + /** + * Whether this object has been deleted. + * @return boolean The deleted state of this object. + */ + public function isDeleted() + { + return $this->deleted; + } + + /** + * Specify whether this object has been deleted. + * @param boolean $b The deleted state of this object. + * @return void + */ + public function setDeleted($b) + { + $this->deleted = (Boolean) $b; + } + + /** + * Sets the modified state for the object to be false. + * @param string $col If supplied, only the specified column is reset. + * @return void + */ + public function resetModified($col = null) + { + if (null !== $col) { + if (isset($this->modifiedColumns[$col])) { + unset($this->modifiedColumns[$col]); + } + } else { + $this->modifiedColumns = array(); + } + } + + /** + * Compares this with another CustomerCustomerFamily instance. If + * obj is an instance of CustomerCustomerFamily, delegates to + * equals(CustomerCustomerFamily). Otherwise, returns false. + * + * @param mixed $obj The object to compare to. + * @return boolean Whether equal to the object specified. + */ + public function equals($obj) + { + $thisclazz = get_class($this); + if (!is_object($obj) || !($obj instanceof $thisclazz)) { + return false; + } + + if ($this === $obj) { + return true; + } + + if (null === $this->getPrimaryKey() + || null === $obj->getPrimaryKey()) { + return false; + } + + return $this->getPrimaryKey() === $obj->getPrimaryKey(); + } + + /** + * If the primary key is not null, return the hashcode of the + * primary key. Otherwise, return the hash code of the object. + * + * @return int Hashcode + */ + public function hashCode() + { + if (null !== $this->getPrimaryKey()) { + return crc32(serialize($this->getPrimaryKey())); + } + + return crc32(serialize(clone $this)); + } + + /** + * Get the associative array of the virtual columns in this object + * + * @return array + */ + public function getVirtualColumns() + { + return $this->virtualColumns; + } + + /** + * Checks the existence of a virtual column in this object + * + * @param string $name The virtual column name + * @return boolean + */ + public function hasVirtualColumn($name) + { + return array_key_exists($name, $this->virtualColumns); + } + + /** + * Get the value of a virtual column in this object + * + * @param string $name The virtual column name + * @return mixed + * + * @throws PropelException + */ + public function getVirtualColumn($name) + { + if (!$this->hasVirtualColumn($name)) { + throw new PropelException(sprintf('Cannot get value of inexistent virtual column %s.', $name)); + } + + return $this->virtualColumns[$name]; + } + + /** + * Set the value of a virtual column in this object + * + * @param string $name The virtual column name + * @param mixed $value The value to give to the virtual column + * + * @return CustomerCustomerFamily The current object, for fluid interface + */ + public function setVirtualColumn($name, $value) + { + $this->virtualColumns[$name] = $value; + + return $this; + } + + /** + * Logs a message using Propel::log(). + * + * @param string $msg + * @param int $priority One of the Propel::LOG_* logging levels + * @return boolean + */ + protected function log($msg, $priority = Propel::LOG_INFO) + { + return Propel::log(get_class($this) . ': ' . $msg, $priority); + } + + /** + * Populate the current object from a string, using a given parser format + * + * $book = new Book(); + * $book->importFrom('JSON', '{"Id":9012,"Title":"Don Juan","ISBN":"0140422161","Price":12.99,"PublisherId":1234,"AuthorId":5678}'); + * + * + * @param mixed $parser A AbstractParser instance, + * or a format name ('XML', 'YAML', 'JSON', 'CSV') + * @param string $data The source data to import from + * + * @return CustomerCustomerFamily The current object, for fluid interface + */ + public function importFrom($parser, $data) + { + if (!$parser instanceof AbstractParser) { + $parser = AbstractParser::getParser($parser); + } + + $this->fromArray($parser->toArray($data), TableMap::TYPE_PHPNAME); + + return $this; + } + + /** + * Export the current object properties to a string, using a given parser format + * + * $book = BookQuery::create()->findPk(9012); + * echo $book->exportTo('JSON'); + * => {"Id":9012,"Title":"Don Juan","ISBN":"0140422161","Price":12.99,"PublisherId":1234,"AuthorId":5678}'); + * + * + * @param mixed $parser A AbstractParser instance, or a format name ('XML', 'YAML', 'JSON', 'CSV') + * @param boolean $includeLazyLoadColumns (optional) Whether to include lazy load(ed) columns. Defaults to TRUE. + * @return string The exported data + */ + public function exportTo($parser, $includeLazyLoadColumns = true) + { + if (!$parser instanceof AbstractParser) { + $parser = AbstractParser::getParser($parser); + } + + return $parser->fromArray($this->toArray(TableMap::TYPE_PHPNAME, $includeLazyLoadColumns, array(), true)); + } + + /** + * Clean up internal collections prior to serializing + * Avoids recursive loops that turn into segmentation faults when serializing + */ + public function __sleep() + { + $this->clearAllReferences(); + + return array_keys(get_object_vars($this)); + } + + /** + * Get the [customer_id] column value. + * + * @return int + */ + public function getCustomerId() + { + + return $this->customer_id; + } + + /** + * Get the [customer_family_id] column value. + * + * @return int + */ + public function getCustomerFamilyId() + { + + return $this->customer_family_id; + } + + /** + * Get the [siret] column value. + * + * @return string + */ + public function getSiret() + { + + return $this->siret; + } + + /** + * Get the [vat] column value. + * + * @return string + */ + public function getVat() + { + + return $this->vat; + } + + /** + * Set the value of [customer_id] column. + * + * @param int $v new value + * @return \CustomerFamily\Model\CustomerCustomerFamily The current object (for fluent API support) + */ + public function setCustomerId($v) + { + if ($v !== null) { + $v = (int) $v; + } + + if ($this->customer_id !== $v) { + $this->customer_id = $v; + $this->modifiedColumns[CustomerCustomerFamilyTableMap::CUSTOMER_ID] = true; + } + + if ($this->aCustomer !== null && $this->aCustomer->getId() !== $v) { + $this->aCustomer = null; + } + + + return $this; + } // setCustomerId() + + /** + * Set the value of [customer_family_id] column. + * + * @param int $v new value + * @return \CustomerFamily\Model\CustomerCustomerFamily The current object (for fluent API support) + */ + public function setCustomerFamilyId($v) + { + if ($v !== null) { + $v = (int) $v; + } + + if ($this->customer_family_id !== $v) { + $this->customer_family_id = $v; + $this->modifiedColumns[CustomerCustomerFamilyTableMap::CUSTOMER_FAMILY_ID] = true; + } + + if ($this->aCustomerFamily !== null && $this->aCustomerFamily->getId() !== $v) { + $this->aCustomerFamily = null; + } + + + return $this; + } // setCustomerFamilyId() + + /** + * Set the value of [siret] column. + * + * @param string $v new value + * @return \CustomerFamily\Model\CustomerCustomerFamily The current object (for fluent API support) + */ + public function setSiret($v) + { + if ($v !== null) { + $v = (string) $v; + } + + if ($this->siret !== $v) { + $this->siret = $v; + $this->modifiedColumns[CustomerCustomerFamilyTableMap::SIRET] = true; + } + + + return $this; + } // setSiret() + + /** + * Set the value of [vat] column. + * + * @param string $v new value + * @return \CustomerFamily\Model\CustomerCustomerFamily The current object (for fluent API support) + */ + public function setVat($v) + { + if ($v !== null) { + $v = (string) $v; + } + + if ($this->vat !== $v) { + $this->vat = $v; + $this->modifiedColumns[CustomerCustomerFamilyTableMap::VAT] = true; + } + + + return $this; + } // setVat() + + /** + * Indicates whether the columns in this object are only set to default values. + * + * This method can be used in conjunction with isModified() to indicate whether an object is both + * modified _and_ has some values set which are non-default. + * + * @return boolean Whether the columns in this object are only been set with default values. + */ + public function hasOnlyDefaultValues() + { + // otherwise, everything was equal, so return TRUE + return true; + } // hasOnlyDefaultValues() + + /** + * Hydrates (populates) the object variables with values from the database resultset. + * + * An offset (0-based "start column") is specified so that objects can be hydrated + * with a subset of the columns in the resultset rows. This is needed, for example, + * for results of JOIN queries where the resultset row includes columns from two or + * more tables. + * + * @param array $row The row returned by DataFetcher->fetch(). + * @param int $startcol 0-based offset column which indicates which restultset column to start with. + * @param boolean $rehydrate Whether this object is being re-hydrated from the database. + * @param string $indexType The index type of $row. Mostly DataFetcher->getIndexType(). + One of the class type constants TableMap::TYPE_PHPNAME, TableMap::TYPE_STUDLYPHPNAME + * TableMap::TYPE_COLNAME, TableMap::TYPE_FIELDNAME, TableMap::TYPE_NUM. + * + * @return int next starting column + * @throws PropelException - Any caught Exception will be rewrapped as a PropelException. + */ + public function hydrate($row, $startcol = 0, $rehydrate = false, $indexType = TableMap::TYPE_NUM) + { + try { + + + $col = $row[TableMap::TYPE_NUM == $indexType ? 0 + $startcol : CustomerCustomerFamilyTableMap::translateFieldName('CustomerId', TableMap::TYPE_PHPNAME, $indexType)]; + $this->customer_id = (null !== $col) ? (int) $col : null; + + $col = $row[TableMap::TYPE_NUM == $indexType ? 1 + $startcol : CustomerCustomerFamilyTableMap::translateFieldName('CustomerFamilyId', TableMap::TYPE_PHPNAME, $indexType)]; + $this->customer_family_id = (null !== $col) ? (int) $col : null; + + $col = $row[TableMap::TYPE_NUM == $indexType ? 2 + $startcol : CustomerCustomerFamilyTableMap::translateFieldName('Siret', TableMap::TYPE_PHPNAME, $indexType)]; + $this->siret = (null !== $col) ? (string) $col : null; + + $col = $row[TableMap::TYPE_NUM == $indexType ? 3 + $startcol : CustomerCustomerFamilyTableMap::translateFieldName('Vat', TableMap::TYPE_PHPNAME, $indexType)]; + $this->vat = (null !== $col) ? (string) $col : null; + $this->resetModified(); + + $this->setNew(false); + + if ($rehydrate) { + $this->ensureConsistency(); + } + + return $startcol + 4; // 4 = CustomerCustomerFamilyTableMap::NUM_HYDRATE_COLUMNS. + + } catch (Exception $e) { + throw new PropelException("Error populating \CustomerFamily\Model\CustomerCustomerFamily object", 0, $e); + } + } + + /** + * Checks and repairs the internal consistency of the object. + * + * This method is executed after an already-instantiated object is re-hydrated + * from the database. It exists to check any foreign keys to make sure that + * the objects related to the current object are correct based on foreign key. + * + * You can override this method in the stub class, but you should always invoke + * the base method from the overridden method (i.e. parent::ensureConsistency()), + * in case your model changes. + * + * @throws PropelException + */ + public function ensureConsistency() + { + if ($this->aCustomer !== null && $this->customer_id !== $this->aCustomer->getId()) { + $this->aCustomer = null; + } + if ($this->aCustomerFamily !== null && $this->customer_family_id !== $this->aCustomerFamily->getId()) { + $this->aCustomerFamily = null; + } + } // ensureConsistency + + /** + * Reloads this object from datastore based on primary key and (optionally) resets all associated objects. + * + * This will only work if the object has been saved and has a valid primary key set. + * + * @param boolean $deep (optional) Whether to also de-associated any related objects. + * @param ConnectionInterface $con (optional) The ConnectionInterface connection to use. + * @return void + * @throws PropelException - if this object is deleted, unsaved or doesn't have pk match in db + */ + public function reload($deep = false, ConnectionInterface $con = null) + { + if ($this->isDeleted()) { + throw new PropelException("Cannot reload a deleted object."); + } + + if ($this->isNew()) { + throw new PropelException("Cannot reload an unsaved object."); + } + + if ($con === null) { + $con = Propel::getServiceContainer()->getReadConnection(CustomerCustomerFamilyTableMap::DATABASE_NAME); + } + + // We don't need to alter the object instance pool; we're just modifying this instance + // already in the pool. + + $dataFetcher = ChildCustomerCustomerFamilyQuery::create(null, $this->buildPkeyCriteria())->setFormatter(ModelCriteria::FORMAT_STATEMENT)->find($con); + $row = $dataFetcher->fetch(); + $dataFetcher->close(); + if (!$row) { + throw new PropelException('Cannot find matching row in the database to reload object values.'); + } + $this->hydrate($row, 0, true, $dataFetcher->getIndexType()); // rehydrate + + if ($deep) { // also de-associate any related objects? + + $this->aCustomer = null; + $this->aCustomerFamily = null; + } // if (deep) + } + + /** + * Removes this object from datastore and sets delete attribute. + * + * @param ConnectionInterface $con + * @return void + * @throws PropelException + * @see CustomerCustomerFamily::setDeleted() + * @see CustomerCustomerFamily::isDeleted() + */ + public function delete(ConnectionInterface $con = null) + { + if ($this->isDeleted()) { + throw new PropelException("This object has already been deleted."); + } + + if ($con === null) { + $con = Propel::getServiceContainer()->getWriteConnection(CustomerCustomerFamilyTableMap::DATABASE_NAME); + } + + $con->beginTransaction(); + try { + $deleteQuery = ChildCustomerCustomerFamilyQuery::create() + ->filterByPrimaryKey($this->getPrimaryKey()); + $ret = $this->preDelete($con); + if ($ret) { + $deleteQuery->delete($con); + $this->postDelete($con); + $con->commit(); + $this->setDeleted(true); + } else { + $con->commit(); + } + } catch (Exception $e) { + $con->rollBack(); + throw $e; + } + } + + /** + * Persists this object to the database. + * + * If the object is new, it inserts it; otherwise an update is performed. + * All modified related objects will also be persisted in the doSave() + * method. This method wraps all precipitate database operations in a + * single transaction. + * + * @param ConnectionInterface $con + * @return int The number of rows affected by this insert/update and any referring fk objects' save() operations. + * @throws PropelException + * @see doSave() + */ + public function save(ConnectionInterface $con = null) + { + if ($this->isDeleted()) { + throw new PropelException("You cannot save an object that has been deleted."); + } + + if ($con === null) { + $con = Propel::getServiceContainer()->getWriteConnection(CustomerCustomerFamilyTableMap::DATABASE_NAME); + } + + $con->beginTransaction(); + $isInsert = $this->isNew(); + try { + $ret = $this->preSave($con); + if ($isInsert) { + $ret = $ret && $this->preInsert($con); + } else { + $ret = $ret && $this->preUpdate($con); + } + if ($ret) { + $affectedRows = $this->doSave($con); + if ($isInsert) { + $this->postInsert($con); + } else { + $this->postUpdate($con); + } + $this->postSave($con); + CustomerCustomerFamilyTableMap::addInstanceToPool($this); + } else { + $affectedRows = 0; + } + $con->commit(); + + return $affectedRows; + } catch (Exception $e) { + $con->rollBack(); + throw $e; + } + } + + /** + * Performs the work of inserting or updating the row in the database. + * + * If the object is new, it inserts it; otherwise an update is performed. + * All related objects are also updated in this method. + * + * @param ConnectionInterface $con + * @return int The number of rows affected by this insert/update and any referring fk objects' save() operations. + * @throws PropelException + * @see save() + */ + protected function doSave(ConnectionInterface $con) + { + $affectedRows = 0; // initialize var to track total num of affected rows + if (!$this->alreadyInSave) { + $this->alreadyInSave = true; + + // We call the save method on the following object(s) if they + // were passed to this object by their corresponding set + // method. This object relates to these object(s) by a + // foreign key reference. + + if ($this->aCustomer !== null) { + if ($this->aCustomer->isModified() || $this->aCustomer->isNew()) { + $affectedRows += $this->aCustomer->save($con); + } + $this->setCustomer($this->aCustomer); + } + + if ($this->aCustomerFamily !== null) { + if ($this->aCustomerFamily->isModified() || $this->aCustomerFamily->isNew()) { + $affectedRows += $this->aCustomerFamily->save($con); + } + $this->setCustomerFamily($this->aCustomerFamily); + } + + if ($this->isNew() || $this->isModified()) { + // persist changes + if ($this->isNew()) { + $this->doInsert($con); + } else { + $this->doUpdate($con); + } + $affectedRows += 1; + $this->resetModified(); + } + + $this->alreadyInSave = false; + + } + + return $affectedRows; + } // doSave() + + /** + * Insert the row in the database. + * + * @param ConnectionInterface $con + * + * @throws PropelException + * @see doSave() + */ + protected function doInsert(ConnectionInterface $con) + { + $modifiedColumns = array(); + $index = 0; + + + // check the columns in natural order for more readable SQL queries + if ($this->isColumnModified(CustomerCustomerFamilyTableMap::CUSTOMER_ID)) { + $modifiedColumns[':p' . $index++] = 'CUSTOMER_ID'; + } + if ($this->isColumnModified(CustomerCustomerFamilyTableMap::CUSTOMER_FAMILY_ID)) { + $modifiedColumns[':p' . $index++] = 'CUSTOMER_FAMILY_ID'; + } + if ($this->isColumnModified(CustomerCustomerFamilyTableMap::SIRET)) { + $modifiedColumns[':p' . $index++] = 'SIRET'; + } + if ($this->isColumnModified(CustomerCustomerFamilyTableMap::VAT)) { + $modifiedColumns[':p' . $index++] = 'VAT'; + } + + $sql = sprintf( + 'INSERT INTO customer_customer_family (%s) VALUES (%s)', + implode(', ', $modifiedColumns), + implode(', ', array_keys($modifiedColumns)) + ); + + try { + $stmt = $con->prepare($sql); + foreach ($modifiedColumns as $identifier => $columnName) { + switch ($columnName) { + case 'CUSTOMER_ID': + $stmt->bindValue($identifier, $this->customer_id, PDO::PARAM_INT); + break; + case 'CUSTOMER_FAMILY_ID': + $stmt->bindValue($identifier, $this->customer_family_id, PDO::PARAM_INT); + break; + case 'SIRET': + $stmt->bindValue($identifier, $this->siret, PDO::PARAM_STR); + break; + case 'VAT': + $stmt->bindValue($identifier, $this->vat, PDO::PARAM_STR); + break; + } + } + $stmt->execute(); + } catch (Exception $e) { + Propel::log($e->getMessage(), Propel::LOG_ERR); + throw new PropelException(sprintf('Unable to execute INSERT statement [%s]', $sql), 0, $e); + } + + $this->setNew(false); + } + + /** + * Update the row in the database. + * + * @param ConnectionInterface $con + * + * @return Integer Number of updated rows + * @see doSave() + */ + protected function doUpdate(ConnectionInterface $con) + { + $selectCriteria = $this->buildPkeyCriteria(); + $valuesCriteria = $this->buildCriteria(); + + return $selectCriteria->doUpdate($valuesCriteria, $con); + } + + /** + * Retrieves a field from the object by name passed in as a string. + * + * @param string $name name + * @param string $type The type of fieldname the $name is of: + * one of the class type constants TableMap::TYPE_PHPNAME, TableMap::TYPE_STUDLYPHPNAME + * TableMap::TYPE_COLNAME, TableMap::TYPE_FIELDNAME, TableMap::TYPE_NUM. + * Defaults to TableMap::TYPE_PHPNAME. + * @return mixed Value of field. + */ + public function getByName($name, $type = TableMap::TYPE_PHPNAME) + { + $pos = CustomerCustomerFamilyTableMap::translateFieldName($name, $type, TableMap::TYPE_NUM); + $field = $this->getByPosition($pos); + + return $field; + } + + /** + * Retrieves a field from the object by Position as specified in the xml schema. + * Zero-based. + * + * @param int $pos position in xml schema + * @return mixed Value of field at $pos + */ + public function getByPosition($pos) + { + switch ($pos) { + case 0: + return $this->getCustomerId(); + break; + case 1: + return $this->getCustomerFamilyId(); + break; + case 2: + return $this->getSiret(); + break; + case 3: + return $this->getVat(); + break; + default: + return null; + break; + } // switch() + } + + /** + * Exports the object as an array. + * + * You can specify the key type of the array by passing one of the class + * type constants. + * + * @param string $keyType (optional) One of the class type constants TableMap::TYPE_PHPNAME, TableMap::TYPE_STUDLYPHPNAME, + * TableMap::TYPE_COLNAME, TableMap::TYPE_FIELDNAME, TableMap::TYPE_NUM. + * Defaults to TableMap::TYPE_PHPNAME. + * @param boolean $includeLazyLoadColumns (optional) Whether to include lazy loaded columns. Defaults to TRUE. + * @param array $alreadyDumpedObjects List of objects to skip to avoid recursion + * @param boolean $includeForeignObjects (optional) Whether to include hydrated related objects. Default to FALSE. + * + * @return array an associative array containing the field names (as keys) and field values + */ + public function toArray($keyType = TableMap::TYPE_PHPNAME, $includeLazyLoadColumns = true, $alreadyDumpedObjects = array(), $includeForeignObjects = false) + { + if (isset($alreadyDumpedObjects['CustomerCustomerFamily'][$this->getPrimaryKey()])) { + return '*RECURSION*'; + } + $alreadyDumpedObjects['CustomerCustomerFamily'][$this->getPrimaryKey()] = true; + $keys = CustomerCustomerFamilyTableMap::getFieldNames($keyType); + $result = array( + $keys[0] => $this->getCustomerId(), + $keys[1] => $this->getCustomerFamilyId(), + $keys[2] => $this->getSiret(), + $keys[3] => $this->getVat(), + ); + $virtualColumns = $this->virtualColumns; + foreach ($virtualColumns as $key => $virtualColumn) { + $result[$key] = $virtualColumn; + } + + if ($includeForeignObjects) { + if (null !== $this->aCustomer) { + $result['Customer'] = $this->aCustomer->toArray($keyType, $includeLazyLoadColumns, $alreadyDumpedObjects, true); + } + if (null !== $this->aCustomerFamily) { + $result['CustomerFamily'] = $this->aCustomerFamily->toArray($keyType, $includeLazyLoadColumns, $alreadyDumpedObjects, true); + } + } + + return $result; + } + + /** + * Sets a field from the object by name passed in as a string. + * + * @param string $name + * @param mixed $value field value + * @param string $type The type of fieldname the $name is of: + * one of the class type constants TableMap::TYPE_PHPNAME, TableMap::TYPE_STUDLYPHPNAME + * TableMap::TYPE_COLNAME, TableMap::TYPE_FIELDNAME, TableMap::TYPE_NUM. + * Defaults to TableMap::TYPE_PHPNAME. + * @return void + */ + public function setByName($name, $value, $type = TableMap::TYPE_PHPNAME) + { + $pos = CustomerCustomerFamilyTableMap::translateFieldName($name, $type, TableMap::TYPE_NUM); + + return $this->setByPosition($pos, $value); + } + + /** + * Sets a field from the object by Position as specified in the xml schema. + * Zero-based. + * + * @param int $pos position in xml schema + * @param mixed $value field value + * @return void + */ + public function setByPosition($pos, $value) + { + switch ($pos) { + case 0: + $this->setCustomerId($value); + break; + case 1: + $this->setCustomerFamilyId($value); + break; + case 2: + $this->setSiret($value); + break; + case 3: + $this->setVat($value); + break; + } // switch() + } + + /** + * Populates the object using an array. + * + * This is particularly useful when populating an object from one of the + * request arrays (e.g. $_POST). This method goes through the column + * names, checking to see whether a matching key exists in populated + * array. If so the setByName() method is called for that column. + * + * You can specify the key type of the array by additionally passing one + * of the class type constants TableMap::TYPE_PHPNAME, TableMap::TYPE_STUDLYPHPNAME, + * TableMap::TYPE_COLNAME, TableMap::TYPE_FIELDNAME, TableMap::TYPE_NUM. + * The default key type is the column's TableMap::TYPE_PHPNAME. + * + * @param array $arr An array to populate the object from. + * @param string $keyType The type of keys the array uses. + * @return void + */ + public function fromArray($arr, $keyType = TableMap::TYPE_PHPNAME) + { + $keys = CustomerCustomerFamilyTableMap::getFieldNames($keyType); + + if (array_key_exists($keys[0], $arr)) $this->setCustomerId($arr[$keys[0]]); + if (array_key_exists($keys[1], $arr)) $this->setCustomerFamilyId($arr[$keys[1]]); + if (array_key_exists($keys[2], $arr)) $this->setSiret($arr[$keys[2]]); + if (array_key_exists($keys[3], $arr)) $this->setVat($arr[$keys[3]]); + } + + /** + * Build a Criteria object containing the values of all modified columns in this object. + * + * @return Criteria The Criteria object containing all modified values. + */ + public function buildCriteria() + { + $criteria = new Criteria(CustomerCustomerFamilyTableMap::DATABASE_NAME); + + if ($this->isColumnModified(CustomerCustomerFamilyTableMap::CUSTOMER_ID)) $criteria->add(CustomerCustomerFamilyTableMap::CUSTOMER_ID, $this->customer_id); + if ($this->isColumnModified(CustomerCustomerFamilyTableMap::CUSTOMER_FAMILY_ID)) $criteria->add(CustomerCustomerFamilyTableMap::CUSTOMER_FAMILY_ID, $this->customer_family_id); + if ($this->isColumnModified(CustomerCustomerFamilyTableMap::SIRET)) $criteria->add(CustomerCustomerFamilyTableMap::SIRET, $this->siret); + if ($this->isColumnModified(CustomerCustomerFamilyTableMap::VAT)) $criteria->add(CustomerCustomerFamilyTableMap::VAT, $this->vat); + + return $criteria; + } + + /** + * Builds a Criteria object containing the primary key for this object. + * + * Unlike buildCriteria() this method includes the primary key values regardless + * of whether or not they have been modified. + * + * @return Criteria The Criteria object containing value(s) for primary key(s). + */ + public function buildPkeyCriteria() + { + $criteria = new Criteria(CustomerCustomerFamilyTableMap::DATABASE_NAME); + $criteria->add(CustomerCustomerFamilyTableMap::CUSTOMER_ID, $this->customer_id); + + return $criteria; + } + + /** + * Returns the primary key for this object (row). + * @return int + */ + public function getPrimaryKey() + { + return $this->getCustomerId(); + } + + /** + * Generic method to set the primary key (customer_id column). + * + * @param int $key Primary key. + * @return void + */ + public function setPrimaryKey($key) + { + $this->setCustomerId($key); + } + + /** + * Returns true if the primary key for this object is null. + * @return boolean + */ + public function isPrimaryKeyNull() + { + + return null === $this->getCustomerId(); + } + + /** + * Sets contents of passed object to values from current object. + * + * If desired, this method can also make copies of all associated (fkey referrers) + * objects. + * + * @param object $copyObj An object of \CustomerFamily\Model\CustomerCustomerFamily (or compatible) type. + * @param boolean $deepCopy Whether to also copy all rows that refer (by fkey) to the current row. + * @param boolean $makeNew Whether to reset autoincrement PKs and make the object new. + * @throws PropelException + */ + public function copyInto($copyObj, $deepCopy = false, $makeNew = true) + { + $copyObj->setCustomerId($this->getCustomerId()); + $copyObj->setCustomerFamilyId($this->getCustomerFamilyId()); + $copyObj->setSiret($this->getSiret()); + $copyObj->setVat($this->getVat()); + if ($makeNew) { + $copyObj->setNew(true); + } + } + + /** + * Makes a copy of this object that will be inserted as a new row in table when saved. + * It creates a new object filling in the simple attributes, but skipping any primary + * keys that are defined for the table. + * + * If desired, this method can also make copies of all associated (fkey referrers) + * objects. + * + * @param boolean $deepCopy Whether to also copy all rows that refer (by fkey) to the current row. + * @return \CustomerFamily\Model\CustomerCustomerFamily Clone of current object. + * @throws PropelException + */ + public function copy($deepCopy = false) + { + // we use get_class(), because this might be a subclass + $clazz = get_class($this); + $copyObj = new $clazz(); + $this->copyInto($copyObj, $deepCopy); + + return $copyObj; + } + + /** + * Declares an association between this object and a ChildCustomer object. + * + * @param ChildCustomer $v + * @return \CustomerFamily\Model\CustomerCustomerFamily The current object (for fluent API support) + * @throws PropelException + */ + public function setCustomer(ChildCustomer $v = null) + { + if ($v === null) { + $this->setCustomerId(NULL); + } else { + $this->setCustomerId($v->getId()); + } + + $this->aCustomer = $v; + + // Add binding for other direction of this 1:1 relationship. + if ($v !== null) { + $v->setCustomerCustomerFamily($this); + } + + + return $this; + } + + + /** + * Get the associated ChildCustomer object + * + * @param ConnectionInterface $con Optional Connection object. + * @return ChildCustomer The associated ChildCustomer object. + * @throws PropelException + */ + public function getCustomer(ConnectionInterface $con = null) + { + if ($this->aCustomer === null && ($this->customer_id !== null)) { + $this->aCustomer = CustomerQuery::create()->findPk($this->customer_id, $con); + // Because this foreign key represents a one-to-one relationship, we will create a bi-directional association. + $this->aCustomer->setCustomerCustomerFamily($this); + } + + return $this->aCustomer; + } + + /** + * Declares an association between this object and a ChildCustomerFamily object. + * + * @param ChildCustomerFamily $v + * @return \CustomerFamily\Model\CustomerCustomerFamily The current object (for fluent API support) + * @throws PropelException + */ + public function setCustomerFamily(ChildCustomerFamily $v = null) + { + if ($v === null) { + $this->setCustomerFamilyId(NULL); + } else { + $this->setCustomerFamilyId($v->getId()); + } + + $this->aCustomerFamily = $v; + + // Add binding for other direction of this n:n relationship. + // If this object has already been added to the ChildCustomerFamily object, it will not be re-added. + if ($v !== null) { + $v->addCustomerCustomerFamily($this); + } + + + return $this; + } + + + /** + * Get the associated ChildCustomerFamily object + * + * @param ConnectionInterface $con Optional Connection object. + * @return ChildCustomerFamily The associated ChildCustomerFamily object. + * @throws PropelException + */ + public function getCustomerFamily(ConnectionInterface $con = null) + { + if ($this->aCustomerFamily === null && ($this->customer_family_id !== null)) { + $this->aCustomerFamily = ChildCustomerFamilyQuery::create()->findPk($this->customer_family_id, $con); + /* The following can be used additionally to + guarantee the related object contains a reference + to this object. This level of coupling may, however, be + undesirable since it could result in an only partially populated collection + in the referenced object. + $this->aCustomerFamily->addCustomerCustomerFamilies($this); + */ + } + + return $this->aCustomerFamily; + } + + /** + * Clears the current object and sets all attributes to their default values + */ + public function clear() + { + $this->customer_id = null; + $this->customer_family_id = null; + $this->siret = null; + $this->vat = null; + $this->alreadyInSave = false; + $this->clearAllReferences(); + $this->resetModified(); + $this->setNew(true); + $this->setDeleted(false); + } + + /** + * Resets all references to other model objects or collections of model objects. + * + * This method is a user-space workaround for PHP's inability to garbage collect + * objects with circular references (even in PHP 5.3). This is currently necessary + * when using Propel in certain daemon or large-volume/high-memory operations. + * + * @param boolean $deep Whether to also clear the references on all referrer objects. + */ + public function clearAllReferences($deep = false) + { + if ($deep) { + } // if ($deep) + + $this->aCustomer = null; + $this->aCustomerFamily = null; + } + + /** + * Return the string representation of this object + * + * @return string + */ + public function __toString() + { + return (string) $this->exportTo(CustomerCustomerFamilyTableMap::DEFAULT_STRING_FORMAT); + } + + /** + * Code to be run before persisting the object + * @param ConnectionInterface $con + * @return boolean + */ + public function preSave(ConnectionInterface $con = null) + { + return true; + } + + /** + * Code to be run after persisting the object + * @param ConnectionInterface $con + */ + public function postSave(ConnectionInterface $con = null) + { + + } + + /** + * Code to be run before inserting to database + * @param ConnectionInterface $con + * @return boolean + */ + public function preInsert(ConnectionInterface $con = null) + { + return true; + } + + /** + * Code to be run after inserting to database + * @param ConnectionInterface $con + */ + public function postInsert(ConnectionInterface $con = null) + { + + } + + /** + * Code to be run before updating the object in database + * @param ConnectionInterface $con + * @return boolean + */ + public function preUpdate(ConnectionInterface $con = null) + { + return true; + } + + /** + * Code to be run after updating the object in database + * @param ConnectionInterface $con + */ + public function postUpdate(ConnectionInterface $con = null) + { + + } + + /** + * Code to be run before deleting the object in database + * @param ConnectionInterface $con + * @return boolean + */ + public function preDelete(ConnectionInterface $con = null) + { + return true; + } + + /** + * Code to be run after deleting the object in database + * @param ConnectionInterface $con + */ + public function postDelete(ConnectionInterface $con = null) + { + + } + + + /** + * Derived method to catches calls to undefined methods. + * + * Provides magic import/export method support (fromXML()/toXML(), fromYAML()/toYAML(), etc.). + * Allows to define default __call() behavior if you overwrite __call() + * + * @param string $name + * @param mixed $params + * + * @return array|string + */ + public function __call($name, $params) + { + if (0 === strpos($name, 'get')) { + $virtualColumn = substr($name, 3); + if ($this->hasVirtualColumn($virtualColumn)) { + return $this->getVirtualColumn($virtualColumn); + } + + $virtualColumn = lcfirst($virtualColumn); + if ($this->hasVirtualColumn($virtualColumn)) { + return $this->getVirtualColumn($virtualColumn); + } + } + + if (0 === strpos($name, 'from')) { + $format = substr($name, 4); + + return $this->importFrom($format, reset($params)); + } + + if (0 === strpos($name, 'to')) { + $format = substr($name, 2); + $includeLazyLoadColumns = isset($params[0]) ? $params[0] : true; + + return $this->exportTo($format, $includeLazyLoadColumns); + } + + throw new BadMethodCallException(sprintf('Call to undefined method: %s.', $name)); + } + +} diff --git a/local/modules/CustomerFamily/Model/Base/CustomerCustomerFamilyQuery.php b/local/modules/CustomerFamily/Model/Base/CustomerCustomerFamilyQuery.php new file mode 100644 index 00000000..da8afff9 --- /dev/null +++ b/local/modules/CustomerFamily/Model/Base/CustomerCustomerFamilyQuery.php @@ -0,0 +1,621 @@ +setModelAlias($modelAlias); + } + if ($criteria instanceof Criteria) { + $query->mergeWith($criteria); + } + + return $query; + } + + /** + * Find object by primary key. + * Propel uses the instance pool to skip the database if the object exists. + * Go fast if the query is untouched. + * + * + * $obj = $c->findPk(12, $con); + * + * + * @param mixed $key Primary key to use for the query + * @param ConnectionInterface $con an optional connection object + * + * @return ChildCustomerCustomerFamily|array|mixed the result, formatted by the current formatter + */ + public function findPk($key, $con = null) + { + if ($key === null) { + return null; + } + if ((null !== ($obj = CustomerCustomerFamilyTableMap::getInstanceFromPool((string) $key))) && !$this->formatter) { + // the object is already in the instance pool + return $obj; + } + if ($con === null) { + $con = Propel::getServiceContainer()->getReadConnection(CustomerCustomerFamilyTableMap::DATABASE_NAME); + } + $this->basePreSelect($con); + if ($this->formatter || $this->modelAlias || $this->with || $this->select + || $this->selectColumns || $this->asColumns || $this->selectModifiers + || $this->map || $this->having || $this->joins) { + return $this->findPkComplex($key, $con); + } else { + return $this->findPkSimple($key, $con); + } + } + + /** + * Find object by primary key using raw SQL to go fast. + * Bypass doSelect() and the object formatter by using generated code. + * + * @param mixed $key Primary key to use for the query + * @param ConnectionInterface $con A connection object + * + * @return ChildCustomerCustomerFamily A model object, or null if the key is not found + */ + protected function findPkSimple($key, $con) + { + $sql = 'SELECT CUSTOMER_ID, CUSTOMER_FAMILY_ID, SIRET, VAT FROM customer_customer_family WHERE CUSTOMER_ID = :p0'; + try { + $stmt = $con->prepare($sql); + $stmt->bindValue(':p0', $key, PDO::PARAM_INT); + $stmt->execute(); + } catch (Exception $e) { + Propel::log($e->getMessage(), Propel::LOG_ERR); + throw new PropelException(sprintf('Unable to execute SELECT statement [%s]', $sql), 0, $e); + } + $obj = null; + if ($row = $stmt->fetch(\PDO::FETCH_NUM)) { + $obj = new ChildCustomerCustomerFamily(); + $obj->hydrate($row); + CustomerCustomerFamilyTableMap::addInstanceToPool($obj, (string) $key); + } + $stmt->closeCursor(); + + return $obj; + } + + /** + * Find object by primary key. + * + * @param mixed $key Primary key to use for the query + * @param ConnectionInterface $con A connection object + * + * @return ChildCustomerCustomerFamily|array|mixed the result, formatted by the current formatter + */ + protected function findPkComplex($key, $con) + { + // As the query uses a PK condition, no limit(1) is necessary. + $criteria = $this->isKeepQuery() ? clone $this : $this; + $dataFetcher = $criteria + ->filterByPrimaryKey($key) + ->doSelect($con); + + return $criteria->getFormatter()->init($criteria)->formatOne($dataFetcher); + } + + /** + * Find objects by primary key + * + * $objs = $c->findPks(array(12, 56, 832), $con); + * + * @param array $keys Primary keys to use for the query + * @param ConnectionInterface $con an optional connection object + * + * @return ObjectCollection|array|mixed the list of results, formatted by the current formatter + */ + public function findPks($keys, $con = null) + { + if (null === $con) { + $con = Propel::getServiceContainer()->getReadConnection($this->getDbName()); + } + $this->basePreSelect($con); + $criteria = $this->isKeepQuery() ? clone $this : $this; + $dataFetcher = $criteria + ->filterByPrimaryKeys($keys) + ->doSelect($con); + + return $criteria->getFormatter()->init($criteria)->format($dataFetcher); + } + + /** + * Filter the query by primary key + * + * @param mixed $key Primary key to use for the query + * + * @return ChildCustomerCustomerFamilyQuery The current query, for fluid interface + */ + public function filterByPrimaryKey($key) + { + + return $this->addUsingAlias(CustomerCustomerFamilyTableMap::CUSTOMER_ID, $key, Criteria::EQUAL); + } + + /** + * Filter the query by a list of primary keys + * + * @param array $keys The list of primary key to use for the query + * + * @return ChildCustomerCustomerFamilyQuery The current query, for fluid interface + */ + public function filterByPrimaryKeys($keys) + { + + return $this->addUsingAlias(CustomerCustomerFamilyTableMap::CUSTOMER_ID, $keys, Criteria::IN); + } + + /** + * Filter the query on the customer_id column + * + * Example usage: + * + * $query->filterByCustomerId(1234); // WHERE customer_id = 1234 + * $query->filterByCustomerId(array(12, 34)); // WHERE customer_id IN (12, 34) + * $query->filterByCustomerId(array('min' => 12)); // WHERE customer_id > 12 + * + * + * @see filterByCustomer() + * + * @param mixed $customerId The value to use as filter. + * Use scalar values for equality. + * Use array values for in_array() equivalent. + * Use associative array('min' => $minValue, 'max' => $maxValue) for intervals. + * @param string $comparison Operator to use for the column comparison, defaults to Criteria::EQUAL + * + * @return ChildCustomerCustomerFamilyQuery The current query, for fluid interface + */ + public function filterByCustomerId($customerId = null, $comparison = null) + { + if (is_array($customerId)) { + $useMinMax = false; + if (isset($customerId['min'])) { + $this->addUsingAlias(CustomerCustomerFamilyTableMap::CUSTOMER_ID, $customerId['min'], Criteria::GREATER_EQUAL); + $useMinMax = true; + } + if (isset($customerId['max'])) { + $this->addUsingAlias(CustomerCustomerFamilyTableMap::CUSTOMER_ID, $customerId['max'], Criteria::LESS_EQUAL); + $useMinMax = true; + } + if ($useMinMax) { + return $this; + } + if (null === $comparison) { + $comparison = Criteria::IN; + } + } + + return $this->addUsingAlias(CustomerCustomerFamilyTableMap::CUSTOMER_ID, $customerId, $comparison); + } + + /** + * Filter the query on the customer_family_id column + * + * Example usage: + * + * $query->filterByCustomerFamilyId(1234); // WHERE customer_family_id = 1234 + * $query->filterByCustomerFamilyId(array(12, 34)); // WHERE customer_family_id IN (12, 34) + * $query->filterByCustomerFamilyId(array('min' => 12)); // WHERE customer_family_id > 12 + * + * + * @see filterByCustomerFamily() + * + * @param mixed $customerFamilyId The value to use as filter. + * Use scalar values for equality. + * Use array values for in_array() equivalent. + * Use associative array('min' => $minValue, 'max' => $maxValue) for intervals. + * @param string $comparison Operator to use for the column comparison, defaults to Criteria::EQUAL + * + * @return ChildCustomerCustomerFamilyQuery The current query, for fluid interface + */ + public function filterByCustomerFamilyId($customerFamilyId = null, $comparison = null) + { + if (is_array($customerFamilyId)) { + $useMinMax = false; + if (isset($customerFamilyId['min'])) { + $this->addUsingAlias(CustomerCustomerFamilyTableMap::CUSTOMER_FAMILY_ID, $customerFamilyId['min'], Criteria::GREATER_EQUAL); + $useMinMax = true; + } + if (isset($customerFamilyId['max'])) { + $this->addUsingAlias(CustomerCustomerFamilyTableMap::CUSTOMER_FAMILY_ID, $customerFamilyId['max'], Criteria::LESS_EQUAL); + $useMinMax = true; + } + if ($useMinMax) { + return $this; + } + if (null === $comparison) { + $comparison = Criteria::IN; + } + } + + return $this->addUsingAlias(CustomerCustomerFamilyTableMap::CUSTOMER_FAMILY_ID, $customerFamilyId, $comparison); + } + + /** + * Filter the query on the siret column + * + * Example usage: + * + * $query->filterBySiret('fooValue'); // WHERE siret = 'fooValue' + * $query->filterBySiret('%fooValue%'); // WHERE siret LIKE '%fooValue%' + * + * + * @param string $siret The value to use as filter. + * Accepts wildcards (* and % trigger a LIKE) + * @param string $comparison Operator to use for the column comparison, defaults to Criteria::EQUAL + * + * @return ChildCustomerCustomerFamilyQuery The current query, for fluid interface + */ + public function filterBySiret($siret = null, $comparison = null) + { + if (null === $comparison) { + if (is_array($siret)) { + $comparison = Criteria::IN; + } elseif (preg_match('/[\%\*]/', $siret)) { + $siret = str_replace('*', '%', $siret); + $comparison = Criteria::LIKE; + } + } + + return $this->addUsingAlias(CustomerCustomerFamilyTableMap::SIRET, $siret, $comparison); + } + + /** + * Filter the query on the vat column + * + * Example usage: + * + * $query->filterByVat('fooValue'); // WHERE vat = 'fooValue' + * $query->filterByVat('%fooValue%'); // WHERE vat LIKE '%fooValue%' + * + * + * @param string $vat The value to use as filter. + * Accepts wildcards (* and % trigger a LIKE) + * @param string $comparison Operator to use for the column comparison, defaults to Criteria::EQUAL + * + * @return ChildCustomerCustomerFamilyQuery The current query, for fluid interface + */ + public function filterByVat($vat = null, $comparison = null) + { + if (null === $comparison) { + if (is_array($vat)) { + $comparison = Criteria::IN; + } elseif (preg_match('/[\%\*]/', $vat)) { + $vat = str_replace('*', '%', $vat); + $comparison = Criteria::LIKE; + } + } + + return $this->addUsingAlias(CustomerCustomerFamilyTableMap::VAT, $vat, $comparison); + } + + /** + * Filter the query by a related \CustomerFamily\Model\Thelia\Model\Customer object + * + * @param \CustomerFamily\Model\Thelia\Model\Customer|ObjectCollection $customer The related object(s) to use as filter + * @param string $comparison Operator to use for the column comparison, defaults to Criteria::EQUAL + * + * @return ChildCustomerCustomerFamilyQuery The current query, for fluid interface + */ + public function filterByCustomer($customer, $comparison = null) + { + if ($customer instanceof \CustomerFamily\Model\Thelia\Model\Customer) { + return $this + ->addUsingAlias(CustomerCustomerFamilyTableMap::CUSTOMER_ID, $customer->getId(), $comparison); + } elseif ($customer instanceof ObjectCollection) { + if (null === $comparison) { + $comparison = Criteria::IN; + } + + return $this + ->addUsingAlias(CustomerCustomerFamilyTableMap::CUSTOMER_ID, $customer->toKeyValue('PrimaryKey', 'Id'), $comparison); + } else { + throw new PropelException('filterByCustomer() only accepts arguments of type \CustomerFamily\Model\Thelia\Model\Customer or Collection'); + } + } + + /** + * Adds a JOIN clause to the query using the Customer relation + * + * @param string $relationAlias optional alias for the relation + * @param string $joinType Accepted values are null, 'left join', 'right join', 'inner join' + * + * @return ChildCustomerCustomerFamilyQuery The current query, for fluid interface + */ + public function joinCustomer($relationAlias = null, $joinType = Criteria::INNER_JOIN) + { + $tableMap = $this->getTableMap(); + $relationMap = $tableMap->getRelation('Customer'); + + // create a ModelJoin object for this join + $join = new ModelJoin(); + $join->setJoinType($joinType); + $join->setRelationMap($relationMap, $this->useAliasInSQL ? $this->getModelAlias() : null, $relationAlias); + if ($previousJoin = $this->getPreviousJoin()) { + $join->setPreviousJoin($previousJoin); + } + + // add the ModelJoin to the current object + if ($relationAlias) { + $this->addAlias($relationAlias, $relationMap->getRightTable()->getName()); + $this->addJoinObject($join, $relationAlias); + } else { + $this->addJoinObject($join, 'Customer'); + } + + return $this; + } + + /** + * Use the Customer relation Customer object + * + * @see useQuery() + * + * @param string $relationAlias optional alias for the relation, + * to be used as main alias in the secondary query + * @param string $joinType Accepted values are null, 'left join', 'right join', 'inner join' + * + * @return \CustomerFamily\Model\Thelia\Model\CustomerQuery A secondary query class using the current class as primary query + */ + public function useCustomerQuery($relationAlias = null, $joinType = Criteria::INNER_JOIN) + { + return $this + ->joinCustomer($relationAlias, $joinType) + ->useQuery($relationAlias ? $relationAlias : 'Customer', '\CustomerFamily\Model\Thelia\Model\CustomerQuery'); + } + + /** + * Filter the query by a related \CustomerFamily\Model\CustomerFamily object + * + * @param \CustomerFamily\Model\CustomerFamily|ObjectCollection $customerFamily The related object(s) to use as filter + * @param string $comparison Operator to use for the column comparison, defaults to Criteria::EQUAL + * + * @return ChildCustomerCustomerFamilyQuery The current query, for fluid interface + */ + public function filterByCustomerFamily($customerFamily, $comparison = null) + { + if ($customerFamily instanceof \CustomerFamily\Model\CustomerFamily) { + return $this + ->addUsingAlias(CustomerCustomerFamilyTableMap::CUSTOMER_FAMILY_ID, $customerFamily->getId(), $comparison); + } elseif ($customerFamily instanceof ObjectCollection) { + if (null === $comparison) { + $comparison = Criteria::IN; + } + + return $this + ->addUsingAlias(CustomerCustomerFamilyTableMap::CUSTOMER_FAMILY_ID, $customerFamily->toKeyValue('PrimaryKey', 'Id'), $comparison); + } else { + throw new PropelException('filterByCustomerFamily() only accepts arguments of type \CustomerFamily\Model\CustomerFamily or Collection'); + } + } + + /** + * Adds a JOIN clause to the query using the CustomerFamily relation + * + * @param string $relationAlias optional alias for the relation + * @param string $joinType Accepted values are null, 'left join', 'right join', 'inner join' + * + * @return ChildCustomerCustomerFamilyQuery The current query, for fluid interface + */ + public function joinCustomerFamily($relationAlias = null, $joinType = Criteria::INNER_JOIN) + { + $tableMap = $this->getTableMap(); + $relationMap = $tableMap->getRelation('CustomerFamily'); + + // create a ModelJoin object for this join + $join = new ModelJoin(); + $join->setJoinType($joinType); + $join->setRelationMap($relationMap, $this->useAliasInSQL ? $this->getModelAlias() : null, $relationAlias); + if ($previousJoin = $this->getPreviousJoin()) { + $join->setPreviousJoin($previousJoin); + } + + // add the ModelJoin to the current object + if ($relationAlias) { + $this->addAlias($relationAlias, $relationMap->getRightTable()->getName()); + $this->addJoinObject($join, $relationAlias); + } else { + $this->addJoinObject($join, 'CustomerFamily'); + } + + return $this; + } + + /** + * Use the CustomerFamily relation CustomerFamily object + * + * @see useQuery() + * + * @param string $relationAlias optional alias for the relation, + * to be used as main alias in the secondary query + * @param string $joinType Accepted values are null, 'left join', 'right join', 'inner join' + * + * @return \CustomerFamily\Model\CustomerFamilyQuery A secondary query class using the current class as primary query + */ + public function useCustomerFamilyQuery($relationAlias = null, $joinType = Criteria::INNER_JOIN) + { + return $this + ->joinCustomerFamily($relationAlias, $joinType) + ->useQuery($relationAlias ? $relationAlias : 'CustomerFamily', '\CustomerFamily\Model\CustomerFamilyQuery'); + } + + /** + * Exclude object from result + * + * @param ChildCustomerCustomerFamily $customerCustomerFamily Object to remove from the list of results + * + * @return ChildCustomerCustomerFamilyQuery The current query, for fluid interface + */ + public function prune($customerCustomerFamily = null) + { + if ($customerCustomerFamily) { + $this->addUsingAlias(CustomerCustomerFamilyTableMap::CUSTOMER_ID, $customerCustomerFamily->getCustomerId(), Criteria::NOT_EQUAL); + } + + return $this; + } + + /** + * Deletes all rows from the customer_customer_family table. + * + * @param ConnectionInterface $con the connection to use + * @return int The number of affected rows (if supported by underlying database driver). + */ + public function doDeleteAll(ConnectionInterface $con = null) + { + if (null === $con) { + $con = Propel::getServiceContainer()->getWriteConnection(CustomerCustomerFamilyTableMap::DATABASE_NAME); + } + $affectedRows = 0; // initialize var to track total num of affected rows + try { + // use transaction because $criteria could contain info + // for more than one table or we could emulating ON DELETE CASCADE, etc. + $con->beginTransaction(); + $affectedRows += parent::doDeleteAll($con); + // Because this db requires some delete cascade/set null emulation, we have to + // clear the cached instance *after* the emulation has happened (since + // instances get re-added by the select statement contained therein). + CustomerCustomerFamilyTableMap::clearInstancePool(); + CustomerCustomerFamilyTableMap::clearRelatedInstancePool(); + + $con->commit(); + } catch (PropelException $e) { + $con->rollBack(); + throw $e; + } + + return $affectedRows; + } + + /** + * Performs a DELETE on the database, given a ChildCustomerCustomerFamily or Criteria object OR a primary key value. + * + * @param mixed $values Criteria or ChildCustomerCustomerFamily object or primary key or array of primary keys + * which is used to create the DELETE statement + * @param ConnectionInterface $con the connection to use + * @return int The number of affected rows (if supported by underlying database driver). This includes CASCADE-related rows + * if supported by native driver or if emulated using Propel. + * @throws PropelException Any exceptions caught during processing will be + * rethrown wrapped into a PropelException. + */ + public function delete(ConnectionInterface $con = null) + { + if (null === $con) { + $con = Propel::getServiceContainer()->getWriteConnection(CustomerCustomerFamilyTableMap::DATABASE_NAME); + } + + $criteria = $this; + + // Set the correct dbName + $criteria->setDbName(CustomerCustomerFamilyTableMap::DATABASE_NAME); + + $affectedRows = 0; // initialize var to track total num of affected rows + + try { + // use transaction because $criteria could contain info + // for more than one table or we could emulating ON DELETE CASCADE, etc. + $con->beginTransaction(); + + + CustomerCustomerFamilyTableMap::removeInstanceFromPool($criteria); + + $affectedRows += ModelCriteria::delete($con); + CustomerCustomerFamilyTableMap::clearRelatedInstancePool(); + $con->commit(); + + return $affectedRows; + } catch (PropelException $e) { + $con->rollBack(); + throw $e; + } + } + +} // CustomerCustomerFamilyQuery diff --git a/local/modules/CustomerFamily/Model/Base/CustomerFamily.php b/local/modules/CustomerFamily/Model/Base/CustomerFamily.php new file mode 100644 index 00000000..dc34dee6 --- /dev/null +++ b/local/modules/CustomerFamily/Model/Base/CustomerFamily.php @@ -0,0 +1,3373 @@ +category_restriction_enabled = 0; + $this->brand_restriction_enabled = 0; + } + + /** + * Initializes internal state of CustomerFamily\Model\Base\CustomerFamily object. + * @see applyDefaults() + */ + public function __construct() + { + $this->applyDefaultValues(); + } + + /** + * Returns whether the object has been modified. + * + * @return boolean True if the object has been modified. + */ + public function isModified() + { + return !!$this->modifiedColumns; + } + + /** + * Has specified column been modified? + * + * @param string $col column fully qualified name (TableMap::TYPE_COLNAME), e.g. Book::AUTHOR_ID + * @return boolean True if $col has been modified. + */ + public function isColumnModified($col) + { + return $this->modifiedColumns && isset($this->modifiedColumns[$col]); + } + + /** + * Get the columns that have been modified in this object. + * @return array A unique list of the modified column names for this object. + */ + public function getModifiedColumns() + { + return $this->modifiedColumns ? array_keys($this->modifiedColumns) : []; + } + + /** + * Returns whether the object has ever been saved. This will + * be false, if the object was retrieved from storage or was created + * and then saved. + * + * @return boolean true, if the object has never been persisted. + */ + public function isNew() + { + return $this->new; + } + + /** + * Setter for the isNew attribute. This method will be called + * by Propel-generated children and objects. + * + * @param boolean $b the state of the object. + */ + public function setNew($b) + { + $this->new = (Boolean) $b; + } + + /** + * Whether this object has been deleted. + * @return boolean The deleted state of this object. + */ + public function isDeleted() + { + return $this->deleted; + } + + /** + * Specify whether this object has been deleted. + * @param boolean $b The deleted state of this object. + * @return void + */ + public function setDeleted($b) + { + $this->deleted = (Boolean) $b; + } + + /** + * Sets the modified state for the object to be false. + * @param string $col If supplied, only the specified column is reset. + * @return void + */ + public function resetModified($col = null) + { + if (null !== $col) { + if (isset($this->modifiedColumns[$col])) { + unset($this->modifiedColumns[$col]); + } + } else { + $this->modifiedColumns = array(); + } + } + + /** + * Compares this with another CustomerFamily instance. If + * obj is an instance of CustomerFamily, delegates to + * equals(CustomerFamily). Otherwise, returns false. + * + * @param mixed $obj The object to compare to. + * @return boolean Whether equal to the object specified. + */ + public function equals($obj) + { + $thisclazz = get_class($this); + if (!is_object($obj) || !($obj instanceof $thisclazz)) { + return false; + } + + if ($this === $obj) { + return true; + } + + if (null === $this->getPrimaryKey() + || null === $obj->getPrimaryKey()) { + return false; + } + + return $this->getPrimaryKey() === $obj->getPrimaryKey(); + } + + /** + * If the primary key is not null, return the hashcode of the + * primary key. Otherwise, return the hash code of the object. + * + * @return int Hashcode + */ + public function hashCode() + { + if (null !== $this->getPrimaryKey()) { + return crc32(serialize($this->getPrimaryKey())); + } + + return crc32(serialize(clone $this)); + } + + /** + * Get the associative array of the virtual columns in this object + * + * @return array + */ + public function getVirtualColumns() + { + return $this->virtualColumns; + } + + /** + * Checks the existence of a virtual column in this object + * + * @param string $name The virtual column name + * @return boolean + */ + public function hasVirtualColumn($name) + { + return array_key_exists($name, $this->virtualColumns); + } + + /** + * Get the value of a virtual column in this object + * + * @param string $name The virtual column name + * @return mixed + * + * @throws PropelException + */ + public function getVirtualColumn($name) + { + if (!$this->hasVirtualColumn($name)) { + throw new PropelException(sprintf('Cannot get value of inexistent virtual column %s.', $name)); + } + + return $this->virtualColumns[$name]; + } + + /** + * Set the value of a virtual column in this object + * + * @param string $name The virtual column name + * @param mixed $value The value to give to the virtual column + * + * @return CustomerFamily The current object, for fluid interface + */ + public function setVirtualColumn($name, $value) + { + $this->virtualColumns[$name] = $value; + + return $this; + } + + /** + * Logs a message using Propel::log(). + * + * @param string $msg + * @param int $priority One of the Propel::LOG_* logging levels + * @return boolean + */ + protected function log($msg, $priority = Propel::LOG_INFO) + { + return Propel::log(get_class($this) . ': ' . $msg, $priority); + } + + /** + * Populate the current object from a string, using a given parser format + * + * $book = new Book(); + * $book->importFrom('JSON', '{"Id":9012,"Title":"Don Juan","ISBN":"0140422161","Price":12.99,"PublisherId":1234,"AuthorId":5678}'); + * + * + * @param mixed $parser A AbstractParser instance, + * or a format name ('XML', 'YAML', 'JSON', 'CSV') + * @param string $data The source data to import from + * + * @return CustomerFamily The current object, for fluid interface + */ + public function importFrom($parser, $data) + { + if (!$parser instanceof AbstractParser) { + $parser = AbstractParser::getParser($parser); + } + + $this->fromArray($parser->toArray($data), TableMap::TYPE_PHPNAME); + + return $this; + } + + /** + * Export the current object properties to a string, using a given parser format + * + * $book = BookQuery::create()->findPk(9012); + * echo $book->exportTo('JSON'); + * => {"Id":9012,"Title":"Don Juan","ISBN":"0140422161","Price":12.99,"PublisherId":1234,"AuthorId":5678}'); + * + * + * @param mixed $parser A AbstractParser instance, or a format name ('XML', 'YAML', 'JSON', 'CSV') + * @param boolean $includeLazyLoadColumns (optional) Whether to include lazy load(ed) columns. Defaults to TRUE. + * @return string The exported data + */ + public function exportTo($parser, $includeLazyLoadColumns = true) + { + if (!$parser instanceof AbstractParser) { + $parser = AbstractParser::getParser($parser); + } + + return $parser->fromArray($this->toArray(TableMap::TYPE_PHPNAME, $includeLazyLoadColumns, array(), true)); + } + + /** + * Clean up internal collections prior to serializing + * Avoids recursive loops that turn into segmentation faults when serializing + */ + public function __sleep() + { + $this->clearAllReferences(); + + return array_keys(get_object_vars($this)); + } + + /** + * Get the [id] column value. + * + * @return int + */ + public function getId() + { + + return $this->id; + } + + /** + * Get the [code] column value. + * + * @return string + */ + public function getCode() + { + + return $this->code; + } + + /** + * Get the [category_restriction_enabled] column value. + * + * @return int + */ + public function getCategoryRestrictionEnabled() + { + + return $this->category_restriction_enabled; + } + + /** + * Get the [brand_restriction_enabled] column value. + * + * @return int + */ + public function getBrandRestrictionEnabled() + { + + return $this->brand_restriction_enabled; + } + + /** + * Get the [is_default] column value. + * + * @return int + */ + public function getIsDefault() + { + + return $this->is_default; + } + + /** + * Get the [optionally formatted] temporal [created_at] column value. + * + * + * @param string $format The date/time format string (either date()-style or strftime()-style). + * If format is NULL, then the raw \DateTime object will be returned. + * + * @return mixed Formatted date/time value as string or \DateTime object (if format is NULL), NULL if column is NULL, and 0 if column value is 0000-00-00 00:00:00 + * + * @throws PropelException - if unable to parse/validate the date/time value. + */ + public function getCreatedAt($format = NULL) + { + if ($format === null) { + return $this->created_at; + } else { + return $this->created_at instanceof \DateTime ? $this->created_at->format($format) : null; + } + } + + /** + * Get the [optionally formatted] temporal [updated_at] column value. + * + * + * @param string $format The date/time format string (either date()-style or strftime()-style). + * If format is NULL, then the raw \DateTime object will be returned. + * + * @return mixed Formatted date/time value as string or \DateTime object (if format is NULL), NULL if column is NULL, and 0 if column value is 0000-00-00 00:00:00 + * + * @throws PropelException - if unable to parse/validate the date/time value. + */ + public function getUpdatedAt($format = NULL) + { + if ($format === null) { + return $this->updated_at; + } else { + return $this->updated_at instanceof \DateTime ? $this->updated_at->format($format) : null; + } + } + + /** + * Set the value of [id] column. + * + * @param int $v new value + * @return \CustomerFamily\Model\CustomerFamily The current object (for fluent API support) + */ + public function setId($v) + { + if ($v !== null) { + $v = (int) $v; + } + + if ($this->id !== $v) { + $this->id = $v; + $this->modifiedColumns[CustomerFamilyTableMap::ID] = true; + } + + + return $this; + } // setId() + + /** + * Set the value of [code] column. + * + * @param string $v new value + * @return \CustomerFamily\Model\CustomerFamily The current object (for fluent API support) + */ + public function setCode($v) + { + if ($v !== null) { + $v = (string) $v; + } + + if ($this->code !== $v) { + $this->code = $v; + $this->modifiedColumns[CustomerFamilyTableMap::CODE] = true; + } + + + return $this; + } // setCode() + + /** + * Set the value of [category_restriction_enabled] column. + * + * @param int $v new value + * @return \CustomerFamily\Model\CustomerFamily The current object (for fluent API support) + */ + public function setCategoryRestrictionEnabled($v) + { + if ($v !== null) { + $v = (int) $v; + } + + if ($this->category_restriction_enabled !== $v) { + $this->category_restriction_enabled = $v; + $this->modifiedColumns[CustomerFamilyTableMap::CATEGORY_RESTRICTION_ENABLED] = true; + } + + + return $this; + } // setCategoryRestrictionEnabled() + + /** + * Set the value of [brand_restriction_enabled] column. + * + * @param int $v new value + * @return \CustomerFamily\Model\CustomerFamily The current object (for fluent API support) + */ + public function setBrandRestrictionEnabled($v) + { + if ($v !== null) { + $v = (int) $v; + } + + if ($this->brand_restriction_enabled !== $v) { + $this->brand_restriction_enabled = $v; + $this->modifiedColumns[CustomerFamilyTableMap::BRAND_RESTRICTION_ENABLED] = true; + } + + + return $this; + } // setBrandRestrictionEnabled() + + /** + * Set the value of [is_default] column. + * + * @param int $v new value + * @return \CustomerFamily\Model\CustomerFamily The current object (for fluent API support) + */ + public function setIsDefault($v) + { + if ($v !== null) { + $v = (int) $v; + } + + if ($this->is_default !== $v) { + $this->is_default = $v; + $this->modifiedColumns[CustomerFamilyTableMap::IS_DEFAULT] = true; + } + + + return $this; + } // setIsDefault() + + /** + * Sets the value of [created_at] column to a normalized version of the date/time value specified. + * + * @param mixed $v string, integer (timestamp), or \DateTime value. + * Empty strings are treated as NULL. + * @return \CustomerFamily\Model\CustomerFamily The current object (for fluent API support) + */ + public function setCreatedAt($v) + { + $dt = PropelDateTime::newInstance($v, null, '\DateTime'); + if ($this->created_at !== null || $dt !== null) { + if ($dt !== $this->created_at) { + $this->created_at = $dt; + $this->modifiedColumns[CustomerFamilyTableMap::CREATED_AT] = true; + } + } // if either are not null + + + return $this; + } // setCreatedAt() + + /** + * Sets the value of [updated_at] column to a normalized version of the date/time value specified. + * + * @param mixed $v string, integer (timestamp), or \DateTime value. + * Empty strings are treated as NULL. + * @return \CustomerFamily\Model\CustomerFamily The current object (for fluent API support) + */ + public function setUpdatedAt($v) + { + $dt = PropelDateTime::newInstance($v, null, '\DateTime'); + if ($this->updated_at !== null || $dt !== null) { + if ($dt !== $this->updated_at) { + $this->updated_at = $dt; + $this->modifiedColumns[CustomerFamilyTableMap::UPDATED_AT] = true; + } + } // if either are not null + + + return $this; + } // setUpdatedAt() + + /** + * Indicates whether the columns in this object are only set to default values. + * + * This method can be used in conjunction with isModified() to indicate whether an object is both + * modified _and_ has some values set which are non-default. + * + * @return boolean Whether the columns in this object are only been set with default values. + */ + public function hasOnlyDefaultValues() + { + if ($this->category_restriction_enabled !== 0) { + return false; + } + + if ($this->brand_restriction_enabled !== 0) { + return false; + } + + // otherwise, everything was equal, so return TRUE + return true; + } // hasOnlyDefaultValues() + + /** + * Hydrates (populates) the object variables with values from the database resultset. + * + * An offset (0-based "start column") is specified so that objects can be hydrated + * with a subset of the columns in the resultset rows. This is needed, for example, + * for results of JOIN queries where the resultset row includes columns from two or + * more tables. + * + * @param array $row The row returned by DataFetcher->fetch(). + * @param int $startcol 0-based offset column which indicates which restultset column to start with. + * @param boolean $rehydrate Whether this object is being re-hydrated from the database. + * @param string $indexType The index type of $row. Mostly DataFetcher->getIndexType(). + One of the class type constants TableMap::TYPE_PHPNAME, TableMap::TYPE_STUDLYPHPNAME + * TableMap::TYPE_COLNAME, TableMap::TYPE_FIELDNAME, TableMap::TYPE_NUM. + * + * @return int next starting column + * @throws PropelException - Any caught Exception will be rewrapped as a PropelException. + */ + public function hydrate($row, $startcol = 0, $rehydrate = false, $indexType = TableMap::TYPE_NUM) + { + try { + + + $col = $row[TableMap::TYPE_NUM == $indexType ? 0 + $startcol : CustomerFamilyTableMap::translateFieldName('Id', TableMap::TYPE_PHPNAME, $indexType)]; + $this->id = (null !== $col) ? (int) $col : null; + + $col = $row[TableMap::TYPE_NUM == $indexType ? 1 + $startcol : CustomerFamilyTableMap::translateFieldName('Code', TableMap::TYPE_PHPNAME, $indexType)]; + $this->code = (null !== $col) ? (string) $col : null; + + $col = $row[TableMap::TYPE_NUM == $indexType ? 2 + $startcol : CustomerFamilyTableMap::translateFieldName('CategoryRestrictionEnabled', TableMap::TYPE_PHPNAME, $indexType)]; + $this->category_restriction_enabled = (null !== $col) ? (int) $col : null; + + $col = $row[TableMap::TYPE_NUM == $indexType ? 3 + $startcol : CustomerFamilyTableMap::translateFieldName('BrandRestrictionEnabled', TableMap::TYPE_PHPNAME, $indexType)]; + $this->brand_restriction_enabled = (null !== $col) ? (int) $col : null; + + $col = $row[TableMap::TYPE_NUM == $indexType ? 4 + $startcol : CustomerFamilyTableMap::translateFieldName('IsDefault', TableMap::TYPE_PHPNAME, $indexType)]; + $this->is_default = (null !== $col) ? (int) $col : null; + + $col = $row[TableMap::TYPE_NUM == $indexType ? 5 + $startcol : CustomerFamilyTableMap::translateFieldName('CreatedAt', TableMap::TYPE_PHPNAME, $indexType)]; + if ($col === '0000-00-00 00:00:00') { + $col = null; + } + $this->created_at = (null !== $col) ? PropelDateTime::newInstance($col, null, '\DateTime') : null; + + $col = $row[TableMap::TYPE_NUM == $indexType ? 6 + $startcol : CustomerFamilyTableMap::translateFieldName('UpdatedAt', TableMap::TYPE_PHPNAME, $indexType)]; + if ($col === '0000-00-00 00:00:00') { + $col = null; + } + $this->updated_at = (null !== $col) ? PropelDateTime::newInstance($col, null, '\DateTime') : null; + $this->resetModified(); + + $this->setNew(false); + + if ($rehydrate) { + $this->ensureConsistency(); + } + + return $startcol + 7; // 7 = CustomerFamilyTableMap::NUM_HYDRATE_COLUMNS. + + } catch (Exception $e) { + throw new PropelException("Error populating \CustomerFamily\Model\CustomerFamily object", 0, $e); + } + } + + /** + * Checks and repairs the internal consistency of the object. + * + * This method is executed after an already-instantiated object is re-hydrated + * from the database. It exists to check any foreign keys to make sure that + * the objects related to the current object are correct based on foreign key. + * + * You can override this method in the stub class, but you should always invoke + * the base method from the overridden method (i.e. parent::ensureConsistency()), + * in case your model changes. + * + * @throws PropelException + */ + public function ensureConsistency() + { + } // ensureConsistency + + /** + * Reloads this object from datastore based on primary key and (optionally) resets all associated objects. + * + * This will only work if the object has been saved and has a valid primary key set. + * + * @param boolean $deep (optional) Whether to also de-associated any related objects. + * @param ConnectionInterface $con (optional) The ConnectionInterface connection to use. + * @return void + * @throws PropelException - if this object is deleted, unsaved or doesn't have pk match in db + */ + public function reload($deep = false, ConnectionInterface $con = null) + { + if ($this->isDeleted()) { + throw new PropelException("Cannot reload a deleted object."); + } + + if ($this->isNew()) { + throw new PropelException("Cannot reload an unsaved object."); + } + + if ($con === null) { + $con = Propel::getServiceContainer()->getReadConnection(CustomerFamilyTableMap::DATABASE_NAME); + } + + // We don't need to alter the object instance pool; we're just modifying this instance + // already in the pool. + + $dataFetcher = ChildCustomerFamilyQuery::create(null, $this->buildPkeyCriteria())->setFormatter(ModelCriteria::FORMAT_STATEMENT)->find($con); + $row = $dataFetcher->fetch(); + $dataFetcher->close(); + if (!$row) { + throw new PropelException('Cannot find matching row in the database to reload object values.'); + } + $this->hydrate($row, 0, true, $dataFetcher->getIndexType()); // rehydrate + + if ($deep) { // also de-associate any related objects? + + $this->collCustomerCustomerFamilies = null; + + $this->collCustomerFamilyPrices = null; + + $this->collCustomerFamilyOrders = null; + + $this->collCustomerFamilyAvailableCategories = null; + + $this->collCustomerFamilyAvailableBrands = null; + + $this->collCustomerFamilyI18ns = null; + + } // if (deep) + } + + /** + * Removes this object from datastore and sets delete attribute. + * + * @param ConnectionInterface $con + * @return void + * @throws PropelException + * @see CustomerFamily::setDeleted() + * @see CustomerFamily::isDeleted() + */ + public function delete(ConnectionInterface $con = null) + { + if ($this->isDeleted()) { + throw new PropelException("This object has already been deleted."); + } + + if ($con === null) { + $con = Propel::getServiceContainer()->getWriteConnection(CustomerFamilyTableMap::DATABASE_NAME); + } + + $con->beginTransaction(); + try { + $deleteQuery = ChildCustomerFamilyQuery::create() + ->filterByPrimaryKey($this->getPrimaryKey()); + $ret = $this->preDelete($con); + if ($ret) { + $deleteQuery->delete($con); + $this->postDelete($con); + $con->commit(); + $this->setDeleted(true); + } else { + $con->commit(); + } + } catch (Exception $e) { + $con->rollBack(); + throw $e; + } + } + + /** + * Persists this object to the database. + * + * If the object is new, it inserts it; otherwise an update is performed. + * All modified related objects will also be persisted in the doSave() + * method. This method wraps all precipitate database operations in a + * single transaction. + * + * @param ConnectionInterface $con + * @return int The number of rows affected by this insert/update and any referring fk objects' save() operations. + * @throws PropelException + * @see doSave() + */ + public function save(ConnectionInterface $con = null) + { + if ($this->isDeleted()) { + throw new PropelException("You cannot save an object that has been deleted."); + } + + if ($con === null) { + $con = Propel::getServiceContainer()->getWriteConnection(CustomerFamilyTableMap::DATABASE_NAME); + } + + $con->beginTransaction(); + $isInsert = $this->isNew(); + try { + $ret = $this->preSave($con); + if ($isInsert) { + $ret = $ret && $this->preInsert($con); + // timestampable behavior + if (!$this->isColumnModified(CustomerFamilyTableMap::CREATED_AT)) { + $this->setCreatedAt(time()); + } + if (!$this->isColumnModified(CustomerFamilyTableMap::UPDATED_AT)) { + $this->setUpdatedAt(time()); + } + } else { + $ret = $ret && $this->preUpdate($con); + // timestampable behavior + if ($this->isModified() && !$this->isColumnModified(CustomerFamilyTableMap::UPDATED_AT)) { + $this->setUpdatedAt(time()); + } + } + if ($ret) { + $affectedRows = $this->doSave($con); + if ($isInsert) { + $this->postInsert($con); + } else { + $this->postUpdate($con); + } + $this->postSave($con); + CustomerFamilyTableMap::addInstanceToPool($this); + } else { + $affectedRows = 0; + } + $con->commit(); + + return $affectedRows; + } catch (Exception $e) { + $con->rollBack(); + throw $e; + } + } + + /** + * Performs the work of inserting or updating the row in the database. + * + * If the object is new, it inserts it; otherwise an update is performed. + * All related objects are also updated in this method. + * + * @param ConnectionInterface $con + * @return int The number of rows affected by this insert/update and any referring fk objects' save() operations. + * @throws PropelException + * @see save() + */ + protected function doSave(ConnectionInterface $con) + { + $affectedRows = 0; // initialize var to track total num of affected rows + if (!$this->alreadyInSave) { + $this->alreadyInSave = true; + + if ($this->isNew() || $this->isModified()) { + // persist changes + if ($this->isNew()) { + $this->doInsert($con); + } else { + $this->doUpdate($con); + } + $affectedRows += 1; + $this->resetModified(); + } + + if ($this->customerCustomerFamiliesScheduledForDeletion !== null) { + if (!$this->customerCustomerFamiliesScheduledForDeletion->isEmpty()) { + \CustomerFamily\Model\CustomerCustomerFamilyQuery::create() + ->filterByPrimaryKeys($this->customerCustomerFamiliesScheduledForDeletion->getPrimaryKeys(false)) + ->delete($con); + $this->customerCustomerFamiliesScheduledForDeletion = null; + } + } + + if ($this->collCustomerCustomerFamilies !== null) { + foreach ($this->collCustomerCustomerFamilies as $referrerFK) { + if (!$referrerFK->isDeleted() && ($referrerFK->isNew() || $referrerFK->isModified())) { + $affectedRows += $referrerFK->save($con); + } + } + } + + if ($this->customerFamilyPricesScheduledForDeletion !== null) { + if (!$this->customerFamilyPricesScheduledForDeletion->isEmpty()) { + \CustomerFamily\Model\CustomerFamilyPriceQuery::create() + ->filterByPrimaryKeys($this->customerFamilyPricesScheduledForDeletion->getPrimaryKeys(false)) + ->delete($con); + $this->customerFamilyPricesScheduledForDeletion = null; + } + } + + if ($this->collCustomerFamilyPrices !== null) { + foreach ($this->collCustomerFamilyPrices as $referrerFK) { + if (!$referrerFK->isDeleted() && ($referrerFK->isNew() || $referrerFK->isModified())) { + $affectedRows += $referrerFK->save($con); + } + } + } + + if ($this->customerFamilyOrdersScheduledForDeletion !== null) { + if (!$this->customerFamilyOrdersScheduledForDeletion->isEmpty()) { + \CustomerFamily\Model\CustomerFamilyOrderQuery::create() + ->filterByPrimaryKeys($this->customerFamilyOrdersScheduledForDeletion->getPrimaryKeys(false)) + ->delete($con); + $this->customerFamilyOrdersScheduledForDeletion = null; + } + } + + if ($this->collCustomerFamilyOrders !== null) { + foreach ($this->collCustomerFamilyOrders as $referrerFK) { + if (!$referrerFK->isDeleted() && ($referrerFK->isNew() || $referrerFK->isModified())) { + $affectedRows += $referrerFK->save($con); + } + } + } + + if ($this->customerFamilyAvailableCategoriesScheduledForDeletion !== null) { + if (!$this->customerFamilyAvailableCategoriesScheduledForDeletion->isEmpty()) { + \CustomerFamily\Model\CustomerFamilyAvailableCategoryQuery::create() + ->filterByPrimaryKeys($this->customerFamilyAvailableCategoriesScheduledForDeletion->getPrimaryKeys(false)) + ->delete($con); + $this->customerFamilyAvailableCategoriesScheduledForDeletion = null; + } + } + + if ($this->collCustomerFamilyAvailableCategories !== null) { + foreach ($this->collCustomerFamilyAvailableCategories as $referrerFK) { + if (!$referrerFK->isDeleted() && ($referrerFK->isNew() || $referrerFK->isModified())) { + $affectedRows += $referrerFK->save($con); + } + } + } + + if ($this->customerFamilyAvailableBrandsScheduledForDeletion !== null) { + if (!$this->customerFamilyAvailableBrandsScheduledForDeletion->isEmpty()) { + \CustomerFamily\Model\CustomerFamilyAvailableBrandQuery::create() + ->filterByPrimaryKeys($this->customerFamilyAvailableBrandsScheduledForDeletion->getPrimaryKeys(false)) + ->delete($con); + $this->customerFamilyAvailableBrandsScheduledForDeletion = null; + } + } + + if ($this->collCustomerFamilyAvailableBrands !== null) { + foreach ($this->collCustomerFamilyAvailableBrands as $referrerFK) { + if (!$referrerFK->isDeleted() && ($referrerFK->isNew() || $referrerFK->isModified())) { + $affectedRows += $referrerFK->save($con); + } + } + } + + if ($this->customerFamilyI18nsScheduledForDeletion !== null) { + if (!$this->customerFamilyI18nsScheduledForDeletion->isEmpty()) { + \CustomerFamily\Model\CustomerFamilyI18nQuery::create() + ->filterByPrimaryKeys($this->customerFamilyI18nsScheduledForDeletion->getPrimaryKeys(false)) + ->delete($con); + $this->customerFamilyI18nsScheduledForDeletion = null; + } + } + + if ($this->collCustomerFamilyI18ns !== null) { + foreach ($this->collCustomerFamilyI18ns as $referrerFK) { + if (!$referrerFK->isDeleted() && ($referrerFK->isNew() || $referrerFK->isModified())) { + $affectedRows += $referrerFK->save($con); + } + } + } + + $this->alreadyInSave = false; + + } + + return $affectedRows; + } // doSave() + + /** + * Insert the row in the database. + * + * @param ConnectionInterface $con + * + * @throws PropelException + * @see doSave() + */ + protected function doInsert(ConnectionInterface $con) + { + $modifiedColumns = array(); + $index = 0; + + $this->modifiedColumns[CustomerFamilyTableMap::ID] = true; + if (null !== $this->id) { + throw new PropelException('Cannot insert a value for auto-increment primary key (' . CustomerFamilyTableMap::ID . ')'); + } + + // check the columns in natural order for more readable SQL queries + if ($this->isColumnModified(CustomerFamilyTableMap::ID)) { + $modifiedColumns[':p' . $index++] = 'ID'; + } + if ($this->isColumnModified(CustomerFamilyTableMap::CODE)) { + $modifiedColumns[':p' . $index++] = 'CODE'; + } + if ($this->isColumnModified(CustomerFamilyTableMap::CATEGORY_RESTRICTION_ENABLED)) { + $modifiedColumns[':p' . $index++] = 'CATEGORY_RESTRICTION_ENABLED'; + } + if ($this->isColumnModified(CustomerFamilyTableMap::BRAND_RESTRICTION_ENABLED)) { + $modifiedColumns[':p' . $index++] = 'BRAND_RESTRICTION_ENABLED'; + } + if ($this->isColumnModified(CustomerFamilyTableMap::IS_DEFAULT)) { + $modifiedColumns[':p' . $index++] = 'IS_DEFAULT'; + } + if ($this->isColumnModified(CustomerFamilyTableMap::CREATED_AT)) { + $modifiedColumns[':p' . $index++] = 'CREATED_AT'; + } + if ($this->isColumnModified(CustomerFamilyTableMap::UPDATED_AT)) { + $modifiedColumns[':p' . $index++] = 'UPDATED_AT'; + } + + $sql = sprintf( + 'INSERT INTO customer_family (%s) VALUES (%s)', + implode(', ', $modifiedColumns), + implode(', ', array_keys($modifiedColumns)) + ); + + try { + $stmt = $con->prepare($sql); + foreach ($modifiedColumns as $identifier => $columnName) { + switch ($columnName) { + case 'ID': + $stmt->bindValue($identifier, $this->id, PDO::PARAM_INT); + break; + case 'CODE': + $stmt->bindValue($identifier, $this->code, PDO::PARAM_STR); + break; + case 'CATEGORY_RESTRICTION_ENABLED': + $stmt->bindValue($identifier, $this->category_restriction_enabled, PDO::PARAM_INT); + break; + case 'BRAND_RESTRICTION_ENABLED': + $stmt->bindValue($identifier, $this->brand_restriction_enabled, PDO::PARAM_INT); + break; + case 'IS_DEFAULT': + $stmt->bindValue($identifier, $this->is_default, PDO::PARAM_INT); + break; + case 'CREATED_AT': + $stmt->bindValue($identifier, $this->created_at ? $this->created_at->format("Y-m-d H:i:s") : null, PDO::PARAM_STR); + break; + case 'UPDATED_AT': + $stmt->bindValue($identifier, $this->updated_at ? $this->updated_at->format("Y-m-d H:i:s") : null, PDO::PARAM_STR); + break; + } + } + $stmt->execute(); + } catch (Exception $e) { + Propel::log($e->getMessage(), Propel::LOG_ERR); + throw new PropelException(sprintf('Unable to execute INSERT statement [%s]', $sql), 0, $e); + } + + try { + $pk = $con->lastInsertId(); + } catch (Exception $e) { + throw new PropelException('Unable to get autoincrement id.', 0, $e); + } + $this->setId($pk); + + $this->setNew(false); + } + + /** + * Update the row in the database. + * + * @param ConnectionInterface $con + * + * @return Integer Number of updated rows + * @see doSave() + */ + protected function doUpdate(ConnectionInterface $con) + { + $selectCriteria = $this->buildPkeyCriteria(); + $valuesCriteria = $this->buildCriteria(); + + return $selectCriteria->doUpdate($valuesCriteria, $con); + } + + /** + * Retrieves a field from the object by name passed in as a string. + * + * @param string $name name + * @param string $type The type of fieldname the $name is of: + * one of the class type constants TableMap::TYPE_PHPNAME, TableMap::TYPE_STUDLYPHPNAME + * TableMap::TYPE_COLNAME, TableMap::TYPE_FIELDNAME, TableMap::TYPE_NUM. + * Defaults to TableMap::TYPE_PHPNAME. + * @return mixed Value of field. + */ + public function getByName($name, $type = TableMap::TYPE_PHPNAME) + { + $pos = CustomerFamilyTableMap::translateFieldName($name, $type, TableMap::TYPE_NUM); + $field = $this->getByPosition($pos); + + return $field; + } + + /** + * Retrieves a field from the object by Position as specified in the xml schema. + * Zero-based. + * + * @param int $pos position in xml schema + * @return mixed Value of field at $pos + */ + public function getByPosition($pos) + { + switch ($pos) { + case 0: + return $this->getId(); + break; + case 1: + return $this->getCode(); + break; + case 2: + return $this->getCategoryRestrictionEnabled(); + break; + case 3: + return $this->getBrandRestrictionEnabled(); + break; + case 4: + return $this->getIsDefault(); + break; + case 5: + return $this->getCreatedAt(); + break; + case 6: + return $this->getUpdatedAt(); + break; + default: + return null; + break; + } // switch() + } + + /** + * Exports the object as an array. + * + * You can specify the key type of the array by passing one of the class + * type constants. + * + * @param string $keyType (optional) One of the class type constants TableMap::TYPE_PHPNAME, TableMap::TYPE_STUDLYPHPNAME, + * TableMap::TYPE_COLNAME, TableMap::TYPE_FIELDNAME, TableMap::TYPE_NUM. + * Defaults to TableMap::TYPE_PHPNAME. + * @param boolean $includeLazyLoadColumns (optional) Whether to include lazy loaded columns. Defaults to TRUE. + * @param array $alreadyDumpedObjects List of objects to skip to avoid recursion + * @param boolean $includeForeignObjects (optional) Whether to include hydrated related objects. Default to FALSE. + * + * @return array an associative array containing the field names (as keys) and field values + */ + public function toArray($keyType = TableMap::TYPE_PHPNAME, $includeLazyLoadColumns = true, $alreadyDumpedObjects = array(), $includeForeignObjects = false) + { + if (isset($alreadyDumpedObjects['CustomerFamily'][$this->getPrimaryKey()])) { + return '*RECURSION*'; + } + $alreadyDumpedObjects['CustomerFamily'][$this->getPrimaryKey()] = true; + $keys = CustomerFamilyTableMap::getFieldNames($keyType); + $result = array( + $keys[0] => $this->getId(), + $keys[1] => $this->getCode(), + $keys[2] => $this->getCategoryRestrictionEnabled(), + $keys[3] => $this->getBrandRestrictionEnabled(), + $keys[4] => $this->getIsDefault(), + $keys[5] => $this->getCreatedAt(), + $keys[6] => $this->getUpdatedAt(), + ); + $virtualColumns = $this->virtualColumns; + foreach ($virtualColumns as $key => $virtualColumn) { + $result[$key] = $virtualColumn; + } + + if ($includeForeignObjects) { + if (null !== $this->collCustomerCustomerFamilies) { + $result['CustomerCustomerFamilies'] = $this->collCustomerCustomerFamilies->toArray(null, true, $keyType, $includeLazyLoadColumns, $alreadyDumpedObjects); + } + if (null !== $this->collCustomerFamilyPrices) { + $result['CustomerFamilyPrices'] = $this->collCustomerFamilyPrices->toArray(null, true, $keyType, $includeLazyLoadColumns, $alreadyDumpedObjects); + } + if (null !== $this->collCustomerFamilyOrders) { + $result['CustomerFamilyOrders'] = $this->collCustomerFamilyOrders->toArray(null, true, $keyType, $includeLazyLoadColumns, $alreadyDumpedObjects); + } + if (null !== $this->collCustomerFamilyAvailableCategories) { + $result['CustomerFamilyAvailableCategories'] = $this->collCustomerFamilyAvailableCategories->toArray(null, true, $keyType, $includeLazyLoadColumns, $alreadyDumpedObjects); + } + if (null !== $this->collCustomerFamilyAvailableBrands) { + $result['CustomerFamilyAvailableBrands'] = $this->collCustomerFamilyAvailableBrands->toArray(null, true, $keyType, $includeLazyLoadColumns, $alreadyDumpedObjects); + } + if (null !== $this->collCustomerFamilyI18ns) { + $result['CustomerFamilyI18ns'] = $this->collCustomerFamilyI18ns->toArray(null, true, $keyType, $includeLazyLoadColumns, $alreadyDumpedObjects); + } + } + + return $result; + } + + /** + * Sets a field from the object by name passed in as a string. + * + * @param string $name + * @param mixed $value field value + * @param string $type The type of fieldname the $name is of: + * one of the class type constants TableMap::TYPE_PHPNAME, TableMap::TYPE_STUDLYPHPNAME + * TableMap::TYPE_COLNAME, TableMap::TYPE_FIELDNAME, TableMap::TYPE_NUM. + * Defaults to TableMap::TYPE_PHPNAME. + * @return void + */ + public function setByName($name, $value, $type = TableMap::TYPE_PHPNAME) + { + $pos = CustomerFamilyTableMap::translateFieldName($name, $type, TableMap::TYPE_NUM); + + return $this->setByPosition($pos, $value); + } + + /** + * Sets a field from the object by Position as specified in the xml schema. + * Zero-based. + * + * @param int $pos position in xml schema + * @param mixed $value field value + * @return void + */ + public function setByPosition($pos, $value) + { + switch ($pos) { + case 0: + $this->setId($value); + break; + case 1: + $this->setCode($value); + break; + case 2: + $this->setCategoryRestrictionEnabled($value); + break; + case 3: + $this->setBrandRestrictionEnabled($value); + break; + case 4: + $this->setIsDefault($value); + break; + case 5: + $this->setCreatedAt($value); + break; + case 6: + $this->setUpdatedAt($value); + break; + } // switch() + } + + /** + * Populates the object using an array. + * + * This is particularly useful when populating an object from one of the + * request arrays (e.g. $_POST). This method goes through the column + * names, checking to see whether a matching key exists in populated + * array. If so the setByName() method is called for that column. + * + * You can specify the key type of the array by additionally passing one + * of the class type constants TableMap::TYPE_PHPNAME, TableMap::TYPE_STUDLYPHPNAME, + * TableMap::TYPE_COLNAME, TableMap::TYPE_FIELDNAME, TableMap::TYPE_NUM. + * The default key type is the column's TableMap::TYPE_PHPNAME. + * + * @param array $arr An array to populate the object from. + * @param string $keyType The type of keys the array uses. + * @return void + */ + public function fromArray($arr, $keyType = TableMap::TYPE_PHPNAME) + { + $keys = CustomerFamilyTableMap::getFieldNames($keyType); + + if (array_key_exists($keys[0], $arr)) $this->setId($arr[$keys[0]]); + if (array_key_exists($keys[1], $arr)) $this->setCode($arr[$keys[1]]); + if (array_key_exists($keys[2], $arr)) $this->setCategoryRestrictionEnabled($arr[$keys[2]]); + if (array_key_exists($keys[3], $arr)) $this->setBrandRestrictionEnabled($arr[$keys[3]]); + if (array_key_exists($keys[4], $arr)) $this->setIsDefault($arr[$keys[4]]); + if (array_key_exists($keys[5], $arr)) $this->setCreatedAt($arr[$keys[5]]); + if (array_key_exists($keys[6], $arr)) $this->setUpdatedAt($arr[$keys[6]]); + } + + /** + * Build a Criteria object containing the values of all modified columns in this object. + * + * @return Criteria The Criteria object containing all modified values. + */ + public function buildCriteria() + { + $criteria = new Criteria(CustomerFamilyTableMap::DATABASE_NAME); + + if ($this->isColumnModified(CustomerFamilyTableMap::ID)) $criteria->add(CustomerFamilyTableMap::ID, $this->id); + if ($this->isColumnModified(CustomerFamilyTableMap::CODE)) $criteria->add(CustomerFamilyTableMap::CODE, $this->code); + if ($this->isColumnModified(CustomerFamilyTableMap::CATEGORY_RESTRICTION_ENABLED)) $criteria->add(CustomerFamilyTableMap::CATEGORY_RESTRICTION_ENABLED, $this->category_restriction_enabled); + if ($this->isColumnModified(CustomerFamilyTableMap::BRAND_RESTRICTION_ENABLED)) $criteria->add(CustomerFamilyTableMap::BRAND_RESTRICTION_ENABLED, $this->brand_restriction_enabled); + if ($this->isColumnModified(CustomerFamilyTableMap::IS_DEFAULT)) $criteria->add(CustomerFamilyTableMap::IS_DEFAULT, $this->is_default); + if ($this->isColumnModified(CustomerFamilyTableMap::CREATED_AT)) $criteria->add(CustomerFamilyTableMap::CREATED_AT, $this->created_at); + if ($this->isColumnModified(CustomerFamilyTableMap::UPDATED_AT)) $criteria->add(CustomerFamilyTableMap::UPDATED_AT, $this->updated_at); + + return $criteria; + } + + /** + * Builds a Criteria object containing the primary key for this object. + * + * Unlike buildCriteria() this method includes the primary key values regardless + * of whether or not they have been modified. + * + * @return Criteria The Criteria object containing value(s) for primary key(s). + */ + public function buildPkeyCriteria() + { + $criteria = new Criteria(CustomerFamilyTableMap::DATABASE_NAME); + $criteria->add(CustomerFamilyTableMap::ID, $this->id); + + return $criteria; + } + + /** + * Returns the primary key for this object (row). + * @return int + */ + public function getPrimaryKey() + { + return $this->getId(); + } + + /** + * Generic method to set the primary key (id column). + * + * @param int $key Primary key. + * @return void + */ + public function setPrimaryKey($key) + { + $this->setId($key); + } + + /** + * Returns true if the primary key for this object is null. + * @return boolean + */ + public function isPrimaryKeyNull() + { + + return null === $this->getId(); + } + + /** + * Sets contents of passed object to values from current object. + * + * If desired, this method can also make copies of all associated (fkey referrers) + * objects. + * + * @param object $copyObj An object of \CustomerFamily\Model\CustomerFamily (or compatible) type. + * @param boolean $deepCopy Whether to also copy all rows that refer (by fkey) to the current row. + * @param boolean $makeNew Whether to reset autoincrement PKs and make the object new. + * @throws PropelException + */ + public function copyInto($copyObj, $deepCopy = false, $makeNew = true) + { + $copyObj->setCode($this->getCode()); + $copyObj->setCategoryRestrictionEnabled($this->getCategoryRestrictionEnabled()); + $copyObj->setBrandRestrictionEnabled($this->getBrandRestrictionEnabled()); + $copyObj->setIsDefault($this->getIsDefault()); + $copyObj->setCreatedAt($this->getCreatedAt()); + $copyObj->setUpdatedAt($this->getUpdatedAt()); + + if ($deepCopy) { + // important: temporarily setNew(false) because this affects the behavior of + // the getter/setter methods for fkey referrer objects. + $copyObj->setNew(false); + + foreach ($this->getCustomerCustomerFamilies() as $relObj) { + if ($relObj !== $this) { // ensure that we don't try to copy a reference to ourselves + $copyObj->addCustomerCustomerFamily($relObj->copy($deepCopy)); + } + } + + foreach ($this->getCustomerFamilyPrices() as $relObj) { + if ($relObj !== $this) { // ensure that we don't try to copy a reference to ourselves + $copyObj->addCustomerFamilyPrice($relObj->copy($deepCopy)); + } + } + + foreach ($this->getCustomerFamilyOrders() as $relObj) { + if ($relObj !== $this) { // ensure that we don't try to copy a reference to ourselves + $copyObj->addCustomerFamilyOrder($relObj->copy($deepCopy)); + } + } + + foreach ($this->getCustomerFamilyAvailableCategories() as $relObj) { + if ($relObj !== $this) { // ensure that we don't try to copy a reference to ourselves + $copyObj->addCustomerFamilyAvailableCategory($relObj->copy($deepCopy)); + } + } + + foreach ($this->getCustomerFamilyAvailableBrands() as $relObj) { + if ($relObj !== $this) { // ensure that we don't try to copy a reference to ourselves + $copyObj->addCustomerFamilyAvailableBrand($relObj->copy($deepCopy)); + } + } + + foreach ($this->getCustomerFamilyI18ns() as $relObj) { + if ($relObj !== $this) { // ensure that we don't try to copy a reference to ourselves + $copyObj->addCustomerFamilyI18n($relObj->copy($deepCopy)); + } + } + + } // if ($deepCopy) + + if ($makeNew) { + $copyObj->setNew(true); + $copyObj->setId(NULL); // this is a auto-increment column, so set to default value + } + } + + /** + * Makes a copy of this object that will be inserted as a new row in table when saved. + * It creates a new object filling in the simple attributes, but skipping any primary + * keys that are defined for the table. + * + * If desired, this method can also make copies of all associated (fkey referrers) + * objects. + * + * @param boolean $deepCopy Whether to also copy all rows that refer (by fkey) to the current row. + * @return \CustomerFamily\Model\CustomerFamily Clone of current object. + * @throws PropelException + */ + public function copy($deepCopy = false) + { + // we use get_class(), because this might be a subclass + $clazz = get_class($this); + $copyObj = new $clazz(); + $this->copyInto($copyObj, $deepCopy); + + return $copyObj; + } + + + /** + * Initializes a collection based on the name of a relation. + * Avoids crafting an 'init[$relationName]s' method name + * that wouldn't work when StandardEnglishPluralizer is used. + * + * @param string $relationName The name of the relation to initialize + * @return void + */ + public function initRelation($relationName) + { + if ('CustomerCustomerFamily' == $relationName) { + return $this->initCustomerCustomerFamilies(); + } + if ('CustomerFamilyPrice' == $relationName) { + return $this->initCustomerFamilyPrices(); + } + if ('CustomerFamilyOrder' == $relationName) { + return $this->initCustomerFamilyOrders(); + } + if ('CustomerFamilyAvailableCategory' == $relationName) { + return $this->initCustomerFamilyAvailableCategories(); + } + if ('CustomerFamilyAvailableBrand' == $relationName) { + return $this->initCustomerFamilyAvailableBrands(); + } + if ('CustomerFamilyI18n' == $relationName) { + return $this->initCustomerFamilyI18ns(); + } + } + + /** + * Clears out the collCustomerCustomerFamilies collection + * + * This does not modify the database; however, it will remove any associated objects, causing + * them to be refetched by subsequent calls to accessor method. + * + * @return void + * @see addCustomerCustomerFamilies() + */ + public function clearCustomerCustomerFamilies() + { + $this->collCustomerCustomerFamilies = null; // important to set this to NULL since that means it is uninitialized + } + + /** + * Reset is the collCustomerCustomerFamilies collection loaded partially. + */ + public function resetPartialCustomerCustomerFamilies($v = true) + { + $this->collCustomerCustomerFamiliesPartial = $v; + } + + /** + * Initializes the collCustomerCustomerFamilies collection. + * + * By default this just sets the collCustomerCustomerFamilies collection to an empty array (like clearcollCustomerCustomerFamilies()); + * however, you may wish to override this method in your stub class to provide setting appropriate + * to your application -- for example, setting the initial array to the values stored in database. + * + * @param boolean $overrideExisting If set to true, the method call initializes + * the collection even if it is not empty + * + * @return void + */ + public function initCustomerCustomerFamilies($overrideExisting = true) + { + if (null !== $this->collCustomerCustomerFamilies && !$overrideExisting) { + return; + } + $this->collCustomerCustomerFamilies = new ObjectCollection(); + $this->collCustomerCustomerFamilies->setModel('\CustomerFamily\Model\CustomerCustomerFamily'); + } + + /** + * Gets an array of ChildCustomerCustomerFamily objects which contain a foreign key that references this object. + * + * If the $criteria is not null, it is used to always fetch the results from the database. + * Otherwise the results are fetched from the database the first time, then cached. + * Next time the same method is called without $criteria, the cached collection is returned. + * If this ChildCustomerFamily is new, it will return + * an empty collection or the current collection; the criteria is ignored on a new object. + * + * @param Criteria $criteria optional Criteria object to narrow the query + * @param ConnectionInterface $con optional connection object + * @return Collection|ChildCustomerCustomerFamily[] List of ChildCustomerCustomerFamily objects + * @throws PropelException + */ + public function getCustomerCustomerFamilies($criteria = null, ConnectionInterface $con = null) + { + $partial = $this->collCustomerCustomerFamiliesPartial && !$this->isNew(); + if (null === $this->collCustomerCustomerFamilies || null !== $criteria || $partial) { + if ($this->isNew() && null === $this->collCustomerCustomerFamilies) { + // return empty collection + $this->initCustomerCustomerFamilies(); + } else { + $collCustomerCustomerFamilies = ChildCustomerCustomerFamilyQuery::create(null, $criteria) + ->filterByCustomerFamily($this) + ->find($con); + + if (null !== $criteria) { + if (false !== $this->collCustomerCustomerFamiliesPartial && count($collCustomerCustomerFamilies)) { + $this->initCustomerCustomerFamilies(false); + + foreach ($collCustomerCustomerFamilies as $obj) { + if (false == $this->collCustomerCustomerFamilies->contains($obj)) { + $this->collCustomerCustomerFamilies->append($obj); + } + } + + $this->collCustomerCustomerFamiliesPartial = true; + } + + reset($collCustomerCustomerFamilies); + + return $collCustomerCustomerFamilies; + } + + if ($partial && $this->collCustomerCustomerFamilies) { + foreach ($this->collCustomerCustomerFamilies as $obj) { + if ($obj->isNew()) { + $collCustomerCustomerFamilies[] = $obj; + } + } + } + + $this->collCustomerCustomerFamilies = $collCustomerCustomerFamilies; + $this->collCustomerCustomerFamiliesPartial = false; + } + } + + return $this->collCustomerCustomerFamilies; + } + + /** + * Sets a collection of CustomerCustomerFamily objects related by a one-to-many relationship + * to the current object. + * It will also schedule objects for deletion based on a diff between old objects (aka persisted) + * and new objects from the given Propel collection. + * + * @param Collection $customerCustomerFamilies A Propel collection. + * @param ConnectionInterface $con Optional connection object + * @return ChildCustomerFamily The current object (for fluent API support) + */ + public function setCustomerCustomerFamilies(Collection $customerCustomerFamilies, ConnectionInterface $con = null) + { + $customerCustomerFamiliesToDelete = $this->getCustomerCustomerFamilies(new Criteria(), $con)->diff($customerCustomerFamilies); + + + $this->customerCustomerFamiliesScheduledForDeletion = $customerCustomerFamiliesToDelete; + + foreach ($customerCustomerFamiliesToDelete as $customerCustomerFamilyRemoved) { + $customerCustomerFamilyRemoved->setCustomerFamily(null); + } + + $this->collCustomerCustomerFamilies = null; + foreach ($customerCustomerFamilies as $customerCustomerFamily) { + $this->addCustomerCustomerFamily($customerCustomerFamily); + } + + $this->collCustomerCustomerFamilies = $customerCustomerFamilies; + $this->collCustomerCustomerFamiliesPartial = false; + + return $this; + } + + /** + * Returns the number of related CustomerCustomerFamily objects. + * + * @param Criteria $criteria + * @param boolean $distinct + * @param ConnectionInterface $con + * @return int Count of related CustomerCustomerFamily objects. + * @throws PropelException + */ + public function countCustomerCustomerFamilies(Criteria $criteria = null, $distinct = false, ConnectionInterface $con = null) + { + $partial = $this->collCustomerCustomerFamiliesPartial && !$this->isNew(); + if (null === $this->collCustomerCustomerFamilies || null !== $criteria || $partial) { + if ($this->isNew() && null === $this->collCustomerCustomerFamilies) { + return 0; + } + + if ($partial && !$criteria) { + return count($this->getCustomerCustomerFamilies()); + } + + $query = ChildCustomerCustomerFamilyQuery::create(null, $criteria); + if ($distinct) { + $query->distinct(); + } + + return $query + ->filterByCustomerFamily($this) + ->count($con); + } + + return count($this->collCustomerCustomerFamilies); + } + + /** + * Method called to associate a ChildCustomerCustomerFamily object to this object + * through the ChildCustomerCustomerFamily foreign key attribute. + * + * @param ChildCustomerCustomerFamily $l ChildCustomerCustomerFamily + * @return \CustomerFamily\Model\CustomerFamily The current object (for fluent API support) + */ + public function addCustomerCustomerFamily(ChildCustomerCustomerFamily $l) + { + if ($this->collCustomerCustomerFamilies === null) { + $this->initCustomerCustomerFamilies(); + $this->collCustomerCustomerFamiliesPartial = true; + } + + if (!in_array($l, $this->collCustomerCustomerFamilies->getArrayCopy(), true)) { // only add it if the **same** object is not already associated + $this->doAddCustomerCustomerFamily($l); + } + + return $this; + } + + /** + * @param CustomerCustomerFamily $customerCustomerFamily The customerCustomerFamily object to add. + */ + protected function doAddCustomerCustomerFamily($customerCustomerFamily) + { + $this->collCustomerCustomerFamilies[]= $customerCustomerFamily; + $customerCustomerFamily->setCustomerFamily($this); + } + + /** + * @param CustomerCustomerFamily $customerCustomerFamily The customerCustomerFamily object to remove. + * @return ChildCustomerFamily The current object (for fluent API support) + */ + public function removeCustomerCustomerFamily($customerCustomerFamily) + { + if ($this->getCustomerCustomerFamilies()->contains($customerCustomerFamily)) { + $this->collCustomerCustomerFamilies->remove($this->collCustomerCustomerFamilies->search($customerCustomerFamily)); + if (null === $this->customerCustomerFamiliesScheduledForDeletion) { + $this->customerCustomerFamiliesScheduledForDeletion = clone $this->collCustomerCustomerFamilies; + $this->customerCustomerFamiliesScheduledForDeletion->clear(); + } + $this->customerCustomerFamiliesScheduledForDeletion[]= clone $customerCustomerFamily; + $customerCustomerFamily->setCustomerFamily(null); + } + + return $this; + } + + + /** + * If this collection has already been initialized with + * an identical criteria, it returns the collection. + * Otherwise if this CustomerFamily is new, it will return + * an empty collection; or if this CustomerFamily has previously + * been saved, it will retrieve related CustomerCustomerFamilies from storage. + * + * This method is protected by default in order to keep the public + * api reasonable. You can provide public methods for those you + * actually need in CustomerFamily. + * + * @param Criteria $criteria optional Criteria object to narrow the query + * @param ConnectionInterface $con optional connection object + * @param string $joinBehavior optional join type to use (defaults to Criteria::LEFT_JOIN) + * @return Collection|ChildCustomerCustomerFamily[] List of ChildCustomerCustomerFamily objects + */ + public function getCustomerCustomerFamiliesJoinCustomer($criteria = null, $con = null, $joinBehavior = Criteria::LEFT_JOIN) + { + $query = ChildCustomerCustomerFamilyQuery::create(null, $criteria); + $query->joinWith('Customer', $joinBehavior); + + return $this->getCustomerCustomerFamilies($query, $con); + } + + /** + * Clears out the collCustomerFamilyPrices collection + * + * This does not modify the database; however, it will remove any associated objects, causing + * them to be refetched by subsequent calls to accessor method. + * + * @return void + * @see addCustomerFamilyPrices() + */ + public function clearCustomerFamilyPrices() + { + $this->collCustomerFamilyPrices = null; // important to set this to NULL since that means it is uninitialized + } + + /** + * Reset is the collCustomerFamilyPrices collection loaded partially. + */ + public function resetPartialCustomerFamilyPrices($v = true) + { + $this->collCustomerFamilyPricesPartial = $v; + } + + /** + * Initializes the collCustomerFamilyPrices collection. + * + * By default this just sets the collCustomerFamilyPrices collection to an empty array (like clearcollCustomerFamilyPrices()); + * however, you may wish to override this method in your stub class to provide setting appropriate + * to your application -- for example, setting the initial array to the values stored in database. + * + * @param boolean $overrideExisting If set to true, the method call initializes + * the collection even if it is not empty + * + * @return void + */ + public function initCustomerFamilyPrices($overrideExisting = true) + { + if (null !== $this->collCustomerFamilyPrices && !$overrideExisting) { + return; + } + $this->collCustomerFamilyPrices = new ObjectCollection(); + $this->collCustomerFamilyPrices->setModel('\CustomerFamily\Model\CustomerFamilyPrice'); + } + + /** + * Gets an array of ChildCustomerFamilyPrice objects which contain a foreign key that references this object. + * + * If the $criteria is not null, it is used to always fetch the results from the database. + * Otherwise the results are fetched from the database the first time, then cached. + * Next time the same method is called without $criteria, the cached collection is returned. + * If this ChildCustomerFamily is new, it will return + * an empty collection or the current collection; the criteria is ignored on a new object. + * + * @param Criteria $criteria optional Criteria object to narrow the query + * @param ConnectionInterface $con optional connection object + * @return Collection|ChildCustomerFamilyPrice[] List of ChildCustomerFamilyPrice objects + * @throws PropelException + */ + public function getCustomerFamilyPrices($criteria = null, ConnectionInterface $con = null) + { + $partial = $this->collCustomerFamilyPricesPartial && !$this->isNew(); + if (null === $this->collCustomerFamilyPrices || null !== $criteria || $partial) { + if ($this->isNew() && null === $this->collCustomerFamilyPrices) { + // return empty collection + $this->initCustomerFamilyPrices(); + } else { + $collCustomerFamilyPrices = ChildCustomerFamilyPriceQuery::create(null, $criteria) + ->filterByCustomerFamily($this) + ->find($con); + + if (null !== $criteria) { + if (false !== $this->collCustomerFamilyPricesPartial && count($collCustomerFamilyPrices)) { + $this->initCustomerFamilyPrices(false); + + foreach ($collCustomerFamilyPrices as $obj) { + if (false == $this->collCustomerFamilyPrices->contains($obj)) { + $this->collCustomerFamilyPrices->append($obj); + } + } + + $this->collCustomerFamilyPricesPartial = true; + } + + reset($collCustomerFamilyPrices); + + return $collCustomerFamilyPrices; + } + + if ($partial && $this->collCustomerFamilyPrices) { + foreach ($this->collCustomerFamilyPrices as $obj) { + if ($obj->isNew()) { + $collCustomerFamilyPrices[] = $obj; + } + } + } + + $this->collCustomerFamilyPrices = $collCustomerFamilyPrices; + $this->collCustomerFamilyPricesPartial = false; + } + } + + return $this->collCustomerFamilyPrices; + } + + /** + * Sets a collection of CustomerFamilyPrice objects related by a one-to-many relationship + * to the current object. + * It will also schedule objects for deletion based on a diff between old objects (aka persisted) + * and new objects from the given Propel collection. + * + * @param Collection $customerFamilyPrices A Propel collection. + * @param ConnectionInterface $con Optional connection object + * @return ChildCustomerFamily The current object (for fluent API support) + */ + public function setCustomerFamilyPrices(Collection $customerFamilyPrices, ConnectionInterface $con = null) + { + $customerFamilyPricesToDelete = $this->getCustomerFamilyPrices(new Criteria(), $con)->diff($customerFamilyPrices); + + + //since at least one column in the foreign key is at the same time a PK + //we can not just set a PK to NULL in the lines below. We have to store + //a backup of all values, so we are able to manipulate these items based on the onDelete value later. + $this->customerFamilyPricesScheduledForDeletion = clone $customerFamilyPricesToDelete; + + foreach ($customerFamilyPricesToDelete as $customerFamilyPriceRemoved) { + $customerFamilyPriceRemoved->setCustomerFamily(null); + } + + $this->collCustomerFamilyPrices = null; + foreach ($customerFamilyPrices as $customerFamilyPrice) { + $this->addCustomerFamilyPrice($customerFamilyPrice); + } + + $this->collCustomerFamilyPrices = $customerFamilyPrices; + $this->collCustomerFamilyPricesPartial = false; + + return $this; + } + + /** + * Returns the number of related CustomerFamilyPrice objects. + * + * @param Criteria $criteria + * @param boolean $distinct + * @param ConnectionInterface $con + * @return int Count of related CustomerFamilyPrice objects. + * @throws PropelException + */ + public function countCustomerFamilyPrices(Criteria $criteria = null, $distinct = false, ConnectionInterface $con = null) + { + $partial = $this->collCustomerFamilyPricesPartial && !$this->isNew(); + if (null === $this->collCustomerFamilyPrices || null !== $criteria || $partial) { + if ($this->isNew() && null === $this->collCustomerFamilyPrices) { + return 0; + } + + if ($partial && !$criteria) { + return count($this->getCustomerFamilyPrices()); + } + + $query = ChildCustomerFamilyPriceQuery::create(null, $criteria); + if ($distinct) { + $query->distinct(); + } + + return $query + ->filterByCustomerFamily($this) + ->count($con); + } + + return count($this->collCustomerFamilyPrices); + } + + /** + * Method called to associate a ChildCustomerFamilyPrice object to this object + * through the ChildCustomerFamilyPrice foreign key attribute. + * + * @param ChildCustomerFamilyPrice $l ChildCustomerFamilyPrice + * @return \CustomerFamily\Model\CustomerFamily The current object (for fluent API support) + */ + public function addCustomerFamilyPrice(ChildCustomerFamilyPrice $l) + { + if ($this->collCustomerFamilyPrices === null) { + $this->initCustomerFamilyPrices(); + $this->collCustomerFamilyPricesPartial = true; + } + + if (!in_array($l, $this->collCustomerFamilyPrices->getArrayCopy(), true)) { // only add it if the **same** object is not already associated + $this->doAddCustomerFamilyPrice($l); + } + + return $this; + } + + /** + * @param CustomerFamilyPrice $customerFamilyPrice The customerFamilyPrice object to add. + */ + protected function doAddCustomerFamilyPrice($customerFamilyPrice) + { + $this->collCustomerFamilyPrices[]= $customerFamilyPrice; + $customerFamilyPrice->setCustomerFamily($this); + } + + /** + * @param CustomerFamilyPrice $customerFamilyPrice The customerFamilyPrice object to remove. + * @return ChildCustomerFamily The current object (for fluent API support) + */ + public function removeCustomerFamilyPrice($customerFamilyPrice) + { + if ($this->getCustomerFamilyPrices()->contains($customerFamilyPrice)) { + $this->collCustomerFamilyPrices->remove($this->collCustomerFamilyPrices->search($customerFamilyPrice)); + if (null === $this->customerFamilyPricesScheduledForDeletion) { + $this->customerFamilyPricesScheduledForDeletion = clone $this->collCustomerFamilyPrices; + $this->customerFamilyPricesScheduledForDeletion->clear(); + } + $this->customerFamilyPricesScheduledForDeletion[]= clone $customerFamilyPrice; + $customerFamilyPrice->setCustomerFamily(null); + } + + return $this; + } + + /** + * Clears out the collCustomerFamilyOrders collection + * + * This does not modify the database; however, it will remove any associated objects, causing + * them to be refetched by subsequent calls to accessor method. + * + * @return void + * @see addCustomerFamilyOrders() + */ + public function clearCustomerFamilyOrders() + { + $this->collCustomerFamilyOrders = null; // important to set this to NULL since that means it is uninitialized + } + + /** + * Reset is the collCustomerFamilyOrders collection loaded partially. + */ + public function resetPartialCustomerFamilyOrders($v = true) + { + $this->collCustomerFamilyOrdersPartial = $v; + } + + /** + * Initializes the collCustomerFamilyOrders collection. + * + * By default this just sets the collCustomerFamilyOrders collection to an empty array (like clearcollCustomerFamilyOrders()); + * however, you may wish to override this method in your stub class to provide setting appropriate + * to your application -- for example, setting the initial array to the values stored in database. + * + * @param boolean $overrideExisting If set to true, the method call initializes + * the collection even if it is not empty + * + * @return void + */ + public function initCustomerFamilyOrders($overrideExisting = true) + { + if (null !== $this->collCustomerFamilyOrders && !$overrideExisting) { + return; + } + $this->collCustomerFamilyOrders = new ObjectCollection(); + $this->collCustomerFamilyOrders->setModel('\CustomerFamily\Model\CustomerFamilyOrder'); + } + + /** + * Gets an array of ChildCustomerFamilyOrder objects which contain a foreign key that references this object. + * + * If the $criteria is not null, it is used to always fetch the results from the database. + * Otherwise the results are fetched from the database the first time, then cached. + * Next time the same method is called without $criteria, the cached collection is returned. + * If this ChildCustomerFamily is new, it will return + * an empty collection or the current collection; the criteria is ignored on a new object. + * + * @param Criteria $criteria optional Criteria object to narrow the query + * @param ConnectionInterface $con optional connection object + * @return Collection|ChildCustomerFamilyOrder[] List of ChildCustomerFamilyOrder objects + * @throws PropelException + */ + public function getCustomerFamilyOrders($criteria = null, ConnectionInterface $con = null) + { + $partial = $this->collCustomerFamilyOrdersPartial && !$this->isNew(); + if (null === $this->collCustomerFamilyOrders || null !== $criteria || $partial) { + if ($this->isNew() && null === $this->collCustomerFamilyOrders) { + // return empty collection + $this->initCustomerFamilyOrders(); + } else { + $collCustomerFamilyOrders = ChildCustomerFamilyOrderQuery::create(null, $criteria) + ->filterByCustomerFamily($this) + ->find($con); + + if (null !== $criteria) { + if (false !== $this->collCustomerFamilyOrdersPartial && count($collCustomerFamilyOrders)) { + $this->initCustomerFamilyOrders(false); + + foreach ($collCustomerFamilyOrders as $obj) { + if (false == $this->collCustomerFamilyOrders->contains($obj)) { + $this->collCustomerFamilyOrders->append($obj); + } + } + + $this->collCustomerFamilyOrdersPartial = true; + } + + reset($collCustomerFamilyOrders); + + return $collCustomerFamilyOrders; + } + + if ($partial && $this->collCustomerFamilyOrders) { + foreach ($this->collCustomerFamilyOrders as $obj) { + if ($obj->isNew()) { + $collCustomerFamilyOrders[] = $obj; + } + } + } + + $this->collCustomerFamilyOrders = $collCustomerFamilyOrders; + $this->collCustomerFamilyOrdersPartial = false; + } + } + + return $this->collCustomerFamilyOrders; + } + + /** + * Sets a collection of CustomerFamilyOrder objects related by a one-to-many relationship + * to the current object. + * It will also schedule objects for deletion based on a diff between old objects (aka persisted) + * and new objects from the given Propel collection. + * + * @param Collection $customerFamilyOrders A Propel collection. + * @param ConnectionInterface $con Optional connection object + * @return ChildCustomerFamily The current object (for fluent API support) + */ + public function setCustomerFamilyOrders(Collection $customerFamilyOrders, ConnectionInterface $con = null) + { + $customerFamilyOrdersToDelete = $this->getCustomerFamilyOrders(new Criteria(), $con)->diff($customerFamilyOrders); + + + $this->customerFamilyOrdersScheduledForDeletion = $customerFamilyOrdersToDelete; + + foreach ($customerFamilyOrdersToDelete as $customerFamilyOrderRemoved) { + $customerFamilyOrderRemoved->setCustomerFamily(null); + } + + $this->collCustomerFamilyOrders = null; + foreach ($customerFamilyOrders as $customerFamilyOrder) { + $this->addCustomerFamilyOrder($customerFamilyOrder); + } + + $this->collCustomerFamilyOrders = $customerFamilyOrders; + $this->collCustomerFamilyOrdersPartial = false; + + return $this; + } + + /** + * Returns the number of related CustomerFamilyOrder objects. + * + * @param Criteria $criteria + * @param boolean $distinct + * @param ConnectionInterface $con + * @return int Count of related CustomerFamilyOrder objects. + * @throws PropelException + */ + public function countCustomerFamilyOrders(Criteria $criteria = null, $distinct = false, ConnectionInterface $con = null) + { + $partial = $this->collCustomerFamilyOrdersPartial && !$this->isNew(); + if (null === $this->collCustomerFamilyOrders || null !== $criteria || $partial) { + if ($this->isNew() && null === $this->collCustomerFamilyOrders) { + return 0; + } + + if ($partial && !$criteria) { + return count($this->getCustomerFamilyOrders()); + } + + $query = ChildCustomerFamilyOrderQuery::create(null, $criteria); + if ($distinct) { + $query->distinct(); + } + + return $query + ->filterByCustomerFamily($this) + ->count($con); + } + + return count($this->collCustomerFamilyOrders); + } + + /** + * Method called to associate a ChildCustomerFamilyOrder object to this object + * through the ChildCustomerFamilyOrder foreign key attribute. + * + * @param ChildCustomerFamilyOrder $l ChildCustomerFamilyOrder + * @return \CustomerFamily\Model\CustomerFamily The current object (for fluent API support) + */ + public function addCustomerFamilyOrder(ChildCustomerFamilyOrder $l) + { + if ($this->collCustomerFamilyOrders === null) { + $this->initCustomerFamilyOrders(); + $this->collCustomerFamilyOrdersPartial = true; + } + + if (!in_array($l, $this->collCustomerFamilyOrders->getArrayCopy(), true)) { // only add it if the **same** object is not already associated + $this->doAddCustomerFamilyOrder($l); + } + + return $this; + } + + /** + * @param CustomerFamilyOrder $customerFamilyOrder The customerFamilyOrder object to add. + */ + protected function doAddCustomerFamilyOrder($customerFamilyOrder) + { + $this->collCustomerFamilyOrders[]= $customerFamilyOrder; + $customerFamilyOrder->setCustomerFamily($this); + } + + /** + * @param CustomerFamilyOrder $customerFamilyOrder The customerFamilyOrder object to remove. + * @return ChildCustomerFamily The current object (for fluent API support) + */ + public function removeCustomerFamilyOrder($customerFamilyOrder) + { + if ($this->getCustomerFamilyOrders()->contains($customerFamilyOrder)) { + $this->collCustomerFamilyOrders->remove($this->collCustomerFamilyOrders->search($customerFamilyOrder)); + if (null === $this->customerFamilyOrdersScheduledForDeletion) { + $this->customerFamilyOrdersScheduledForDeletion = clone $this->collCustomerFamilyOrders; + $this->customerFamilyOrdersScheduledForDeletion->clear(); + } + $this->customerFamilyOrdersScheduledForDeletion[]= clone $customerFamilyOrder; + $customerFamilyOrder->setCustomerFamily(null); + } + + return $this; + } + + + /** + * If this collection has already been initialized with + * an identical criteria, it returns the collection. + * Otherwise if this CustomerFamily is new, it will return + * an empty collection; or if this CustomerFamily has previously + * been saved, it will retrieve related CustomerFamilyOrders from storage. + * + * This method is protected by default in order to keep the public + * api reasonable. You can provide public methods for those you + * actually need in CustomerFamily. + * + * @param Criteria $criteria optional Criteria object to narrow the query + * @param ConnectionInterface $con optional connection object + * @param string $joinBehavior optional join type to use (defaults to Criteria::LEFT_JOIN) + * @return Collection|ChildCustomerFamilyOrder[] List of ChildCustomerFamilyOrder objects + */ + public function getCustomerFamilyOrdersJoinOrder($criteria = null, $con = null, $joinBehavior = Criteria::LEFT_JOIN) + { + $query = ChildCustomerFamilyOrderQuery::create(null, $criteria); + $query->joinWith('Order', $joinBehavior); + + return $this->getCustomerFamilyOrders($query, $con); + } + + /** + * Clears out the collCustomerFamilyAvailableCategories collection + * + * This does not modify the database; however, it will remove any associated objects, causing + * them to be refetched by subsequent calls to accessor method. + * + * @return void + * @see addCustomerFamilyAvailableCategories() + */ + public function clearCustomerFamilyAvailableCategories() + { + $this->collCustomerFamilyAvailableCategories = null; // important to set this to NULL since that means it is uninitialized + } + + /** + * Reset is the collCustomerFamilyAvailableCategories collection loaded partially. + */ + public function resetPartialCustomerFamilyAvailableCategories($v = true) + { + $this->collCustomerFamilyAvailableCategoriesPartial = $v; + } + + /** + * Initializes the collCustomerFamilyAvailableCategories collection. + * + * By default this just sets the collCustomerFamilyAvailableCategories collection to an empty array (like clearcollCustomerFamilyAvailableCategories()); + * however, you may wish to override this method in your stub class to provide setting appropriate + * to your application -- for example, setting the initial array to the values stored in database. + * + * @param boolean $overrideExisting If set to true, the method call initializes + * the collection even if it is not empty + * + * @return void + */ + public function initCustomerFamilyAvailableCategories($overrideExisting = true) + { + if (null !== $this->collCustomerFamilyAvailableCategories && !$overrideExisting) { + return; + } + $this->collCustomerFamilyAvailableCategories = new ObjectCollection(); + $this->collCustomerFamilyAvailableCategories->setModel('\CustomerFamily\Model\CustomerFamilyAvailableCategory'); + } + + /** + * Gets an array of ChildCustomerFamilyAvailableCategory objects which contain a foreign key that references this object. + * + * If the $criteria is not null, it is used to always fetch the results from the database. + * Otherwise the results are fetched from the database the first time, then cached. + * Next time the same method is called without $criteria, the cached collection is returned. + * If this ChildCustomerFamily is new, it will return + * an empty collection or the current collection; the criteria is ignored on a new object. + * + * @param Criteria $criteria optional Criteria object to narrow the query + * @param ConnectionInterface $con optional connection object + * @return Collection|ChildCustomerFamilyAvailableCategory[] List of ChildCustomerFamilyAvailableCategory objects + * @throws PropelException + */ + public function getCustomerFamilyAvailableCategories($criteria = null, ConnectionInterface $con = null) + { + $partial = $this->collCustomerFamilyAvailableCategoriesPartial && !$this->isNew(); + if (null === $this->collCustomerFamilyAvailableCategories || null !== $criteria || $partial) { + if ($this->isNew() && null === $this->collCustomerFamilyAvailableCategories) { + // return empty collection + $this->initCustomerFamilyAvailableCategories(); + } else { + $collCustomerFamilyAvailableCategories = ChildCustomerFamilyAvailableCategoryQuery::create(null, $criteria) + ->filterByCustomerFamily($this) + ->find($con); + + if (null !== $criteria) { + if (false !== $this->collCustomerFamilyAvailableCategoriesPartial && count($collCustomerFamilyAvailableCategories)) { + $this->initCustomerFamilyAvailableCategories(false); + + foreach ($collCustomerFamilyAvailableCategories as $obj) { + if (false == $this->collCustomerFamilyAvailableCategories->contains($obj)) { + $this->collCustomerFamilyAvailableCategories->append($obj); + } + } + + $this->collCustomerFamilyAvailableCategoriesPartial = true; + } + + reset($collCustomerFamilyAvailableCategories); + + return $collCustomerFamilyAvailableCategories; + } + + if ($partial && $this->collCustomerFamilyAvailableCategories) { + foreach ($this->collCustomerFamilyAvailableCategories as $obj) { + if ($obj->isNew()) { + $collCustomerFamilyAvailableCategories[] = $obj; + } + } + } + + $this->collCustomerFamilyAvailableCategories = $collCustomerFamilyAvailableCategories; + $this->collCustomerFamilyAvailableCategoriesPartial = false; + } + } + + return $this->collCustomerFamilyAvailableCategories; + } + + /** + * Sets a collection of CustomerFamilyAvailableCategory objects related by a one-to-many relationship + * to the current object. + * It will also schedule objects for deletion based on a diff between old objects (aka persisted) + * and new objects from the given Propel collection. + * + * @param Collection $customerFamilyAvailableCategories A Propel collection. + * @param ConnectionInterface $con Optional connection object + * @return ChildCustomerFamily The current object (for fluent API support) + */ + public function setCustomerFamilyAvailableCategories(Collection $customerFamilyAvailableCategories, ConnectionInterface $con = null) + { + $customerFamilyAvailableCategoriesToDelete = $this->getCustomerFamilyAvailableCategories(new Criteria(), $con)->diff($customerFamilyAvailableCategories); + + + //since at least one column in the foreign key is at the same time a PK + //we can not just set a PK to NULL in the lines below. We have to store + //a backup of all values, so we are able to manipulate these items based on the onDelete value later. + $this->customerFamilyAvailableCategoriesScheduledForDeletion = clone $customerFamilyAvailableCategoriesToDelete; + + foreach ($customerFamilyAvailableCategoriesToDelete as $customerFamilyAvailableCategoryRemoved) { + $customerFamilyAvailableCategoryRemoved->setCustomerFamily(null); + } + + $this->collCustomerFamilyAvailableCategories = null; + foreach ($customerFamilyAvailableCategories as $customerFamilyAvailableCategory) { + $this->addCustomerFamilyAvailableCategory($customerFamilyAvailableCategory); + } + + $this->collCustomerFamilyAvailableCategories = $customerFamilyAvailableCategories; + $this->collCustomerFamilyAvailableCategoriesPartial = false; + + return $this; + } + + /** + * Returns the number of related CustomerFamilyAvailableCategory objects. + * + * @param Criteria $criteria + * @param boolean $distinct + * @param ConnectionInterface $con + * @return int Count of related CustomerFamilyAvailableCategory objects. + * @throws PropelException + */ + public function countCustomerFamilyAvailableCategories(Criteria $criteria = null, $distinct = false, ConnectionInterface $con = null) + { + $partial = $this->collCustomerFamilyAvailableCategoriesPartial && !$this->isNew(); + if (null === $this->collCustomerFamilyAvailableCategories || null !== $criteria || $partial) { + if ($this->isNew() && null === $this->collCustomerFamilyAvailableCategories) { + return 0; + } + + if ($partial && !$criteria) { + return count($this->getCustomerFamilyAvailableCategories()); + } + + $query = ChildCustomerFamilyAvailableCategoryQuery::create(null, $criteria); + if ($distinct) { + $query->distinct(); + } + + return $query + ->filterByCustomerFamily($this) + ->count($con); + } + + return count($this->collCustomerFamilyAvailableCategories); + } + + /** + * Method called to associate a ChildCustomerFamilyAvailableCategory object to this object + * through the ChildCustomerFamilyAvailableCategory foreign key attribute. + * + * @param ChildCustomerFamilyAvailableCategory $l ChildCustomerFamilyAvailableCategory + * @return \CustomerFamily\Model\CustomerFamily The current object (for fluent API support) + */ + public function addCustomerFamilyAvailableCategory(ChildCustomerFamilyAvailableCategory $l) + { + if ($this->collCustomerFamilyAvailableCategories === null) { + $this->initCustomerFamilyAvailableCategories(); + $this->collCustomerFamilyAvailableCategoriesPartial = true; + } + + if (!in_array($l, $this->collCustomerFamilyAvailableCategories->getArrayCopy(), true)) { // only add it if the **same** object is not already associated + $this->doAddCustomerFamilyAvailableCategory($l); + } + + return $this; + } + + /** + * @param CustomerFamilyAvailableCategory $customerFamilyAvailableCategory The customerFamilyAvailableCategory object to add. + */ + protected function doAddCustomerFamilyAvailableCategory($customerFamilyAvailableCategory) + { + $this->collCustomerFamilyAvailableCategories[]= $customerFamilyAvailableCategory; + $customerFamilyAvailableCategory->setCustomerFamily($this); + } + + /** + * @param CustomerFamilyAvailableCategory $customerFamilyAvailableCategory The customerFamilyAvailableCategory object to remove. + * @return ChildCustomerFamily The current object (for fluent API support) + */ + public function removeCustomerFamilyAvailableCategory($customerFamilyAvailableCategory) + { + if ($this->getCustomerFamilyAvailableCategories()->contains($customerFamilyAvailableCategory)) { + $this->collCustomerFamilyAvailableCategories->remove($this->collCustomerFamilyAvailableCategories->search($customerFamilyAvailableCategory)); + if (null === $this->customerFamilyAvailableCategoriesScheduledForDeletion) { + $this->customerFamilyAvailableCategoriesScheduledForDeletion = clone $this->collCustomerFamilyAvailableCategories; + $this->customerFamilyAvailableCategoriesScheduledForDeletion->clear(); + } + $this->customerFamilyAvailableCategoriesScheduledForDeletion[]= clone $customerFamilyAvailableCategory; + $customerFamilyAvailableCategory->setCustomerFamily(null); + } + + return $this; + } + + + /** + * If this collection has already been initialized with + * an identical criteria, it returns the collection. + * Otherwise if this CustomerFamily is new, it will return + * an empty collection; or if this CustomerFamily has previously + * been saved, it will retrieve related CustomerFamilyAvailableCategories from storage. + * + * This method is protected by default in order to keep the public + * api reasonable. You can provide public methods for those you + * actually need in CustomerFamily. + * + * @param Criteria $criteria optional Criteria object to narrow the query + * @param ConnectionInterface $con optional connection object + * @param string $joinBehavior optional join type to use (defaults to Criteria::LEFT_JOIN) + * @return Collection|ChildCustomerFamilyAvailableCategory[] List of ChildCustomerFamilyAvailableCategory objects + */ + public function getCustomerFamilyAvailableCategoriesJoinCategory($criteria = null, $con = null, $joinBehavior = Criteria::LEFT_JOIN) + { + $query = ChildCustomerFamilyAvailableCategoryQuery::create(null, $criteria); + $query->joinWith('Category', $joinBehavior); + + return $this->getCustomerFamilyAvailableCategories($query, $con); + } + + /** + * Clears out the collCustomerFamilyAvailableBrands collection + * + * This does not modify the database; however, it will remove any associated objects, causing + * them to be refetched by subsequent calls to accessor method. + * + * @return void + * @see addCustomerFamilyAvailableBrands() + */ + public function clearCustomerFamilyAvailableBrands() + { + $this->collCustomerFamilyAvailableBrands = null; // important to set this to NULL since that means it is uninitialized + } + + /** + * Reset is the collCustomerFamilyAvailableBrands collection loaded partially. + */ + public function resetPartialCustomerFamilyAvailableBrands($v = true) + { + $this->collCustomerFamilyAvailableBrandsPartial = $v; + } + + /** + * Initializes the collCustomerFamilyAvailableBrands collection. + * + * By default this just sets the collCustomerFamilyAvailableBrands collection to an empty array (like clearcollCustomerFamilyAvailableBrands()); + * however, you may wish to override this method in your stub class to provide setting appropriate + * to your application -- for example, setting the initial array to the values stored in database. + * + * @param boolean $overrideExisting If set to true, the method call initializes + * the collection even if it is not empty + * + * @return void + */ + public function initCustomerFamilyAvailableBrands($overrideExisting = true) + { + if (null !== $this->collCustomerFamilyAvailableBrands && !$overrideExisting) { + return; + } + $this->collCustomerFamilyAvailableBrands = new ObjectCollection(); + $this->collCustomerFamilyAvailableBrands->setModel('\CustomerFamily\Model\CustomerFamilyAvailableBrand'); + } + + /** + * Gets an array of ChildCustomerFamilyAvailableBrand objects which contain a foreign key that references this object. + * + * If the $criteria is not null, it is used to always fetch the results from the database. + * Otherwise the results are fetched from the database the first time, then cached. + * Next time the same method is called without $criteria, the cached collection is returned. + * If this ChildCustomerFamily is new, it will return + * an empty collection or the current collection; the criteria is ignored on a new object. + * + * @param Criteria $criteria optional Criteria object to narrow the query + * @param ConnectionInterface $con optional connection object + * @return Collection|ChildCustomerFamilyAvailableBrand[] List of ChildCustomerFamilyAvailableBrand objects + * @throws PropelException + */ + public function getCustomerFamilyAvailableBrands($criteria = null, ConnectionInterface $con = null) + { + $partial = $this->collCustomerFamilyAvailableBrandsPartial && !$this->isNew(); + if (null === $this->collCustomerFamilyAvailableBrands || null !== $criteria || $partial) { + if ($this->isNew() && null === $this->collCustomerFamilyAvailableBrands) { + // return empty collection + $this->initCustomerFamilyAvailableBrands(); + } else { + $collCustomerFamilyAvailableBrands = ChildCustomerFamilyAvailableBrandQuery::create(null, $criteria) + ->filterByCustomerFamily($this) + ->find($con); + + if (null !== $criteria) { + if (false !== $this->collCustomerFamilyAvailableBrandsPartial && count($collCustomerFamilyAvailableBrands)) { + $this->initCustomerFamilyAvailableBrands(false); + + foreach ($collCustomerFamilyAvailableBrands as $obj) { + if (false == $this->collCustomerFamilyAvailableBrands->contains($obj)) { + $this->collCustomerFamilyAvailableBrands->append($obj); + } + } + + $this->collCustomerFamilyAvailableBrandsPartial = true; + } + + reset($collCustomerFamilyAvailableBrands); + + return $collCustomerFamilyAvailableBrands; + } + + if ($partial && $this->collCustomerFamilyAvailableBrands) { + foreach ($this->collCustomerFamilyAvailableBrands as $obj) { + if ($obj->isNew()) { + $collCustomerFamilyAvailableBrands[] = $obj; + } + } + } + + $this->collCustomerFamilyAvailableBrands = $collCustomerFamilyAvailableBrands; + $this->collCustomerFamilyAvailableBrandsPartial = false; + } + } + + return $this->collCustomerFamilyAvailableBrands; + } + + /** + * Sets a collection of CustomerFamilyAvailableBrand objects related by a one-to-many relationship + * to the current object. + * It will also schedule objects for deletion based on a diff between old objects (aka persisted) + * and new objects from the given Propel collection. + * + * @param Collection $customerFamilyAvailableBrands A Propel collection. + * @param ConnectionInterface $con Optional connection object + * @return ChildCustomerFamily The current object (for fluent API support) + */ + public function setCustomerFamilyAvailableBrands(Collection $customerFamilyAvailableBrands, ConnectionInterface $con = null) + { + $customerFamilyAvailableBrandsToDelete = $this->getCustomerFamilyAvailableBrands(new Criteria(), $con)->diff($customerFamilyAvailableBrands); + + + //since at least one column in the foreign key is at the same time a PK + //we can not just set a PK to NULL in the lines below. We have to store + //a backup of all values, so we are able to manipulate these items based on the onDelete value later. + $this->customerFamilyAvailableBrandsScheduledForDeletion = clone $customerFamilyAvailableBrandsToDelete; + + foreach ($customerFamilyAvailableBrandsToDelete as $customerFamilyAvailableBrandRemoved) { + $customerFamilyAvailableBrandRemoved->setCustomerFamily(null); + } + + $this->collCustomerFamilyAvailableBrands = null; + foreach ($customerFamilyAvailableBrands as $customerFamilyAvailableBrand) { + $this->addCustomerFamilyAvailableBrand($customerFamilyAvailableBrand); + } + + $this->collCustomerFamilyAvailableBrands = $customerFamilyAvailableBrands; + $this->collCustomerFamilyAvailableBrandsPartial = false; + + return $this; + } + + /** + * Returns the number of related CustomerFamilyAvailableBrand objects. + * + * @param Criteria $criteria + * @param boolean $distinct + * @param ConnectionInterface $con + * @return int Count of related CustomerFamilyAvailableBrand objects. + * @throws PropelException + */ + public function countCustomerFamilyAvailableBrands(Criteria $criteria = null, $distinct = false, ConnectionInterface $con = null) + { + $partial = $this->collCustomerFamilyAvailableBrandsPartial && !$this->isNew(); + if (null === $this->collCustomerFamilyAvailableBrands || null !== $criteria || $partial) { + if ($this->isNew() && null === $this->collCustomerFamilyAvailableBrands) { + return 0; + } + + if ($partial && !$criteria) { + return count($this->getCustomerFamilyAvailableBrands()); + } + + $query = ChildCustomerFamilyAvailableBrandQuery::create(null, $criteria); + if ($distinct) { + $query->distinct(); + } + + return $query + ->filterByCustomerFamily($this) + ->count($con); + } + + return count($this->collCustomerFamilyAvailableBrands); + } + + /** + * Method called to associate a ChildCustomerFamilyAvailableBrand object to this object + * through the ChildCustomerFamilyAvailableBrand foreign key attribute. + * + * @param ChildCustomerFamilyAvailableBrand $l ChildCustomerFamilyAvailableBrand + * @return \CustomerFamily\Model\CustomerFamily The current object (for fluent API support) + */ + public function addCustomerFamilyAvailableBrand(ChildCustomerFamilyAvailableBrand $l) + { + if ($this->collCustomerFamilyAvailableBrands === null) { + $this->initCustomerFamilyAvailableBrands(); + $this->collCustomerFamilyAvailableBrandsPartial = true; + } + + if (!in_array($l, $this->collCustomerFamilyAvailableBrands->getArrayCopy(), true)) { // only add it if the **same** object is not already associated + $this->doAddCustomerFamilyAvailableBrand($l); + } + + return $this; + } + + /** + * @param CustomerFamilyAvailableBrand $customerFamilyAvailableBrand The customerFamilyAvailableBrand object to add. + */ + protected function doAddCustomerFamilyAvailableBrand($customerFamilyAvailableBrand) + { + $this->collCustomerFamilyAvailableBrands[]= $customerFamilyAvailableBrand; + $customerFamilyAvailableBrand->setCustomerFamily($this); + } + + /** + * @param CustomerFamilyAvailableBrand $customerFamilyAvailableBrand The customerFamilyAvailableBrand object to remove. + * @return ChildCustomerFamily The current object (for fluent API support) + */ + public function removeCustomerFamilyAvailableBrand($customerFamilyAvailableBrand) + { + if ($this->getCustomerFamilyAvailableBrands()->contains($customerFamilyAvailableBrand)) { + $this->collCustomerFamilyAvailableBrands->remove($this->collCustomerFamilyAvailableBrands->search($customerFamilyAvailableBrand)); + if (null === $this->customerFamilyAvailableBrandsScheduledForDeletion) { + $this->customerFamilyAvailableBrandsScheduledForDeletion = clone $this->collCustomerFamilyAvailableBrands; + $this->customerFamilyAvailableBrandsScheduledForDeletion->clear(); + } + $this->customerFamilyAvailableBrandsScheduledForDeletion[]= clone $customerFamilyAvailableBrand; + $customerFamilyAvailableBrand->setCustomerFamily(null); + } + + return $this; + } + + + /** + * If this collection has already been initialized with + * an identical criteria, it returns the collection. + * Otherwise if this CustomerFamily is new, it will return + * an empty collection; or if this CustomerFamily has previously + * been saved, it will retrieve related CustomerFamilyAvailableBrands from storage. + * + * This method is protected by default in order to keep the public + * api reasonable. You can provide public methods for those you + * actually need in CustomerFamily. + * + * @param Criteria $criteria optional Criteria object to narrow the query + * @param ConnectionInterface $con optional connection object + * @param string $joinBehavior optional join type to use (defaults to Criteria::LEFT_JOIN) + * @return Collection|ChildCustomerFamilyAvailableBrand[] List of ChildCustomerFamilyAvailableBrand objects + */ + public function getCustomerFamilyAvailableBrandsJoinBrand($criteria = null, $con = null, $joinBehavior = Criteria::LEFT_JOIN) + { + $query = ChildCustomerFamilyAvailableBrandQuery::create(null, $criteria); + $query->joinWith('Brand', $joinBehavior); + + return $this->getCustomerFamilyAvailableBrands($query, $con); + } + + /** + * Clears out the collCustomerFamilyI18ns collection + * + * This does not modify the database; however, it will remove any associated objects, causing + * them to be refetched by subsequent calls to accessor method. + * + * @return void + * @see addCustomerFamilyI18ns() + */ + public function clearCustomerFamilyI18ns() + { + $this->collCustomerFamilyI18ns = null; // important to set this to NULL since that means it is uninitialized + } + + /** + * Reset is the collCustomerFamilyI18ns collection loaded partially. + */ + public function resetPartialCustomerFamilyI18ns($v = true) + { + $this->collCustomerFamilyI18nsPartial = $v; + } + + /** + * Initializes the collCustomerFamilyI18ns collection. + * + * By default this just sets the collCustomerFamilyI18ns collection to an empty array (like clearcollCustomerFamilyI18ns()); + * however, you may wish to override this method in your stub class to provide setting appropriate + * to your application -- for example, setting the initial array to the values stored in database. + * + * @param boolean $overrideExisting If set to true, the method call initializes + * the collection even if it is not empty + * + * @return void + */ + public function initCustomerFamilyI18ns($overrideExisting = true) + { + if (null !== $this->collCustomerFamilyI18ns && !$overrideExisting) { + return; + } + $this->collCustomerFamilyI18ns = new ObjectCollection(); + $this->collCustomerFamilyI18ns->setModel('\CustomerFamily\Model\CustomerFamilyI18n'); + } + + /** + * Gets an array of ChildCustomerFamilyI18n objects which contain a foreign key that references this object. + * + * If the $criteria is not null, it is used to always fetch the results from the database. + * Otherwise the results are fetched from the database the first time, then cached. + * Next time the same method is called without $criteria, the cached collection is returned. + * If this ChildCustomerFamily is new, it will return + * an empty collection or the current collection; the criteria is ignored on a new object. + * + * @param Criteria $criteria optional Criteria object to narrow the query + * @param ConnectionInterface $con optional connection object + * @return Collection|ChildCustomerFamilyI18n[] List of ChildCustomerFamilyI18n objects + * @throws PropelException + */ + public function getCustomerFamilyI18ns($criteria = null, ConnectionInterface $con = null) + { + $partial = $this->collCustomerFamilyI18nsPartial && !$this->isNew(); + if (null === $this->collCustomerFamilyI18ns || null !== $criteria || $partial) { + if ($this->isNew() && null === $this->collCustomerFamilyI18ns) { + // return empty collection + $this->initCustomerFamilyI18ns(); + } else { + $collCustomerFamilyI18ns = ChildCustomerFamilyI18nQuery::create(null, $criteria) + ->filterByCustomerFamily($this) + ->find($con); + + if (null !== $criteria) { + if (false !== $this->collCustomerFamilyI18nsPartial && count($collCustomerFamilyI18ns)) { + $this->initCustomerFamilyI18ns(false); + + foreach ($collCustomerFamilyI18ns as $obj) { + if (false == $this->collCustomerFamilyI18ns->contains($obj)) { + $this->collCustomerFamilyI18ns->append($obj); + } + } + + $this->collCustomerFamilyI18nsPartial = true; + } + + reset($collCustomerFamilyI18ns); + + return $collCustomerFamilyI18ns; + } + + if ($partial && $this->collCustomerFamilyI18ns) { + foreach ($this->collCustomerFamilyI18ns as $obj) { + if ($obj->isNew()) { + $collCustomerFamilyI18ns[] = $obj; + } + } + } + + $this->collCustomerFamilyI18ns = $collCustomerFamilyI18ns; + $this->collCustomerFamilyI18nsPartial = false; + } + } + + return $this->collCustomerFamilyI18ns; + } + + /** + * Sets a collection of CustomerFamilyI18n objects related by a one-to-many relationship + * to the current object. + * It will also schedule objects for deletion based on a diff between old objects (aka persisted) + * and new objects from the given Propel collection. + * + * @param Collection $customerFamilyI18ns A Propel collection. + * @param ConnectionInterface $con Optional connection object + * @return ChildCustomerFamily The current object (for fluent API support) + */ + public function setCustomerFamilyI18ns(Collection $customerFamilyI18ns, ConnectionInterface $con = null) + { + $customerFamilyI18nsToDelete = $this->getCustomerFamilyI18ns(new Criteria(), $con)->diff($customerFamilyI18ns); + + + //since at least one column in the foreign key is at the same time a PK + //we can not just set a PK to NULL in the lines below. We have to store + //a backup of all values, so we are able to manipulate these items based on the onDelete value later. + $this->customerFamilyI18nsScheduledForDeletion = clone $customerFamilyI18nsToDelete; + + foreach ($customerFamilyI18nsToDelete as $customerFamilyI18nRemoved) { + $customerFamilyI18nRemoved->setCustomerFamily(null); + } + + $this->collCustomerFamilyI18ns = null; + foreach ($customerFamilyI18ns as $customerFamilyI18n) { + $this->addCustomerFamilyI18n($customerFamilyI18n); + } + + $this->collCustomerFamilyI18ns = $customerFamilyI18ns; + $this->collCustomerFamilyI18nsPartial = false; + + return $this; + } + + /** + * Returns the number of related CustomerFamilyI18n objects. + * + * @param Criteria $criteria + * @param boolean $distinct + * @param ConnectionInterface $con + * @return int Count of related CustomerFamilyI18n objects. + * @throws PropelException + */ + public function countCustomerFamilyI18ns(Criteria $criteria = null, $distinct = false, ConnectionInterface $con = null) + { + $partial = $this->collCustomerFamilyI18nsPartial && !$this->isNew(); + if (null === $this->collCustomerFamilyI18ns || null !== $criteria || $partial) { + if ($this->isNew() && null === $this->collCustomerFamilyI18ns) { + return 0; + } + + if ($partial && !$criteria) { + return count($this->getCustomerFamilyI18ns()); + } + + $query = ChildCustomerFamilyI18nQuery::create(null, $criteria); + if ($distinct) { + $query->distinct(); + } + + return $query + ->filterByCustomerFamily($this) + ->count($con); + } + + return count($this->collCustomerFamilyI18ns); + } + + /** + * Method called to associate a ChildCustomerFamilyI18n object to this object + * through the ChildCustomerFamilyI18n foreign key attribute. + * + * @param ChildCustomerFamilyI18n $l ChildCustomerFamilyI18n + * @return \CustomerFamily\Model\CustomerFamily The current object (for fluent API support) + */ + public function addCustomerFamilyI18n(ChildCustomerFamilyI18n $l) + { + if ($l && $locale = $l->getLocale()) { + $this->setLocale($locale); + $this->currentTranslations[$locale] = $l; + } + if ($this->collCustomerFamilyI18ns === null) { + $this->initCustomerFamilyI18ns(); + $this->collCustomerFamilyI18nsPartial = true; + } + + if (!in_array($l, $this->collCustomerFamilyI18ns->getArrayCopy(), true)) { // only add it if the **same** object is not already associated + $this->doAddCustomerFamilyI18n($l); + } + + return $this; + } + + /** + * @param CustomerFamilyI18n $customerFamilyI18n The customerFamilyI18n object to add. + */ + protected function doAddCustomerFamilyI18n($customerFamilyI18n) + { + $this->collCustomerFamilyI18ns[]= $customerFamilyI18n; + $customerFamilyI18n->setCustomerFamily($this); + } + + /** + * @param CustomerFamilyI18n $customerFamilyI18n The customerFamilyI18n object to remove. + * @return ChildCustomerFamily The current object (for fluent API support) + */ + public function removeCustomerFamilyI18n($customerFamilyI18n) + { + if ($this->getCustomerFamilyI18ns()->contains($customerFamilyI18n)) { + $this->collCustomerFamilyI18ns->remove($this->collCustomerFamilyI18ns->search($customerFamilyI18n)); + if (null === $this->customerFamilyI18nsScheduledForDeletion) { + $this->customerFamilyI18nsScheduledForDeletion = clone $this->collCustomerFamilyI18ns; + $this->customerFamilyI18nsScheduledForDeletion->clear(); + } + $this->customerFamilyI18nsScheduledForDeletion[]= clone $customerFamilyI18n; + $customerFamilyI18n->setCustomerFamily(null); + } + + return $this; + } + + /** + * Clears the current object and sets all attributes to their default values + */ + public function clear() + { + $this->id = null; + $this->code = null; + $this->category_restriction_enabled = null; + $this->brand_restriction_enabled = null; + $this->is_default = null; + $this->created_at = null; + $this->updated_at = null; + $this->alreadyInSave = false; + $this->clearAllReferences(); + $this->applyDefaultValues(); + $this->resetModified(); + $this->setNew(true); + $this->setDeleted(false); + } + + /** + * Resets all references to other model objects or collections of model objects. + * + * This method is a user-space workaround for PHP's inability to garbage collect + * objects with circular references (even in PHP 5.3). This is currently necessary + * when using Propel in certain daemon or large-volume/high-memory operations. + * + * @param boolean $deep Whether to also clear the references on all referrer objects. + */ + public function clearAllReferences($deep = false) + { + if ($deep) { + if ($this->collCustomerCustomerFamilies) { + foreach ($this->collCustomerCustomerFamilies as $o) { + $o->clearAllReferences($deep); + } + } + if ($this->collCustomerFamilyPrices) { + foreach ($this->collCustomerFamilyPrices as $o) { + $o->clearAllReferences($deep); + } + } + if ($this->collCustomerFamilyOrders) { + foreach ($this->collCustomerFamilyOrders as $o) { + $o->clearAllReferences($deep); + } + } + if ($this->collCustomerFamilyAvailableCategories) { + foreach ($this->collCustomerFamilyAvailableCategories as $o) { + $o->clearAllReferences($deep); + } + } + if ($this->collCustomerFamilyAvailableBrands) { + foreach ($this->collCustomerFamilyAvailableBrands as $o) { + $o->clearAllReferences($deep); + } + } + if ($this->collCustomerFamilyI18ns) { + foreach ($this->collCustomerFamilyI18ns as $o) { + $o->clearAllReferences($deep); + } + } + } // if ($deep) + + // i18n behavior + $this->currentLocale = 'en_US'; + $this->currentTranslations = null; + + $this->collCustomerCustomerFamilies = null; + $this->collCustomerFamilyPrices = null; + $this->collCustomerFamilyOrders = null; + $this->collCustomerFamilyAvailableCategories = null; + $this->collCustomerFamilyAvailableBrands = null; + $this->collCustomerFamilyI18ns = null; + } + + /** + * Return the string representation of this object + * + * @return string + */ + public function __toString() + { + return (string) $this->exportTo(CustomerFamilyTableMap::DEFAULT_STRING_FORMAT); + } + + // timestampable behavior + + /** + * Mark the current object so that the update date doesn't get updated during next save + * + * @return ChildCustomerFamily The current object (for fluent API support) + */ + public function keepUpdateDateUnchanged() + { + $this->modifiedColumns[CustomerFamilyTableMap::UPDATED_AT] = true; + + return $this; + } + + // i18n behavior + + /** + * Sets the locale for translations + * + * @param string $locale Locale to use for the translation, e.g. 'fr_FR' + * + * @return ChildCustomerFamily The current object (for fluent API support) + */ + public function setLocale($locale = 'en_US') + { + $this->currentLocale = $locale; + + return $this; + } + + /** + * Gets the locale for translations + * + * @return string $locale Locale to use for the translation, e.g. 'fr_FR' + */ + public function getLocale() + { + return $this->currentLocale; + } + + /** + * Returns the current translation for a given locale + * + * @param string $locale Locale to use for the translation, e.g. 'fr_FR' + * @param ConnectionInterface $con an optional connection object + * + * @return ChildCustomerFamilyI18n */ + public function getTranslation($locale = 'en_US', ConnectionInterface $con = null) + { + if (!isset($this->currentTranslations[$locale])) { + if (null !== $this->collCustomerFamilyI18ns) { + foreach ($this->collCustomerFamilyI18ns as $translation) { + if ($translation->getLocale() == $locale) { + $this->currentTranslations[$locale] = $translation; + + return $translation; + } + } + } + if ($this->isNew()) { + $translation = new ChildCustomerFamilyI18n(); + $translation->setLocale($locale); + } else { + $translation = ChildCustomerFamilyI18nQuery::create() + ->filterByPrimaryKey(array($this->getPrimaryKey(), $locale)) + ->findOneOrCreate($con); + $this->currentTranslations[$locale] = $translation; + } + $this->addCustomerFamilyI18n($translation); + } + + return $this->currentTranslations[$locale]; + } + + /** + * Remove the translation for a given locale + * + * @param string $locale Locale to use for the translation, e.g. 'fr_FR' + * @param ConnectionInterface $con an optional connection object + * + * @return ChildCustomerFamily The current object (for fluent API support) + */ + public function removeTranslation($locale = 'en_US', ConnectionInterface $con = null) + { + if (!$this->isNew()) { + ChildCustomerFamilyI18nQuery::create() + ->filterByPrimaryKey(array($this->getPrimaryKey(), $locale)) + ->delete($con); + } + if (isset($this->currentTranslations[$locale])) { + unset($this->currentTranslations[$locale]); + } + foreach ($this->collCustomerFamilyI18ns as $key => $translation) { + if ($translation->getLocale() == $locale) { + unset($this->collCustomerFamilyI18ns[$key]); + break; + } + } + + return $this; + } + + /** + * Returns the current translation + * + * @param ConnectionInterface $con an optional connection object + * + * @return ChildCustomerFamilyI18n */ + public function getCurrentTranslation(ConnectionInterface $con = null) + { + return $this->getTranslation($this->getLocale(), $con); + } + + + /** + * Get the [title] column value. + * + * @return string + */ + public function getTitle() + { + return $this->getCurrentTranslation()->getTitle(); + } + + + /** + * Set the value of [title] column. + * + * @param string $v new value + * @return \CustomerFamily\Model\CustomerFamilyI18n The current object (for fluent API support) + */ + public function setTitle($v) + { $this->getCurrentTranslation()->setTitle($v); + + return $this; + } + + /** + * Code to be run before persisting the object + * @param ConnectionInterface $con + * @return boolean + */ + public function preSave(ConnectionInterface $con = null) + { + return true; + } + + /** + * Code to be run after persisting the object + * @param ConnectionInterface $con + */ + public function postSave(ConnectionInterface $con = null) + { + + } + + /** + * Code to be run before inserting to database + * @param ConnectionInterface $con + * @return boolean + */ + public function preInsert(ConnectionInterface $con = null) + { + return true; + } + + /** + * Code to be run after inserting to database + * @param ConnectionInterface $con + */ + public function postInsert(ConnectionInterface $con = null) + { + + } + + /** + * Code to be run before updating the object in database + * @param ConnectionInterface $con + * @return boolean + */ + public function preUpdate(ConnectionInterface $con = null) + { + return true; + } + + /** + * Code to be run after updating the object in database + * @param ConnectionInterface $con + */ + public function postUpdate(ConnectionInterface $con = null) + { + + } + + /** + * Code to be run before deleting the object in database + * @param ConnectionInterface $con + * @return boolean + */ + public function preDelete(ConnectionInterface $con = null) + { + return true; + } + + /** + * Code to be run after deleting the object in database + * @param ConnectionInterface $con + */ + public function postDelete(ConnectionInterface $con = null) + { + + } + + + /** + * Derived method to catches calls to undefined methods. + * + * Provides magic import/export method support (fromXML()/toXML(), fromYAML()/toYAML(), etc.). + * Allows to define default __call() behavior if you overwrite __call() + * + * @param string $name + * @param mixed $params + * + * @return array|string + */ + public function __call($name, $params) + { + if (0 === strpos($name, 'get')) { + $virtualColumn = substr($name, 3); + if ($this->hasVirtualColumn($virtualColumn)) { + return $this->getVirtualColumn($virtualColumn); + } + + $virtualColumn = lcfirst($virtualColumn); + if ($this->hasVirtualColumn($virtualColumn)) { + return $this->getVirtualColumn($virtualColumn); + } + } + + if (0 === strpos($name, 'from')) { + $format = substr($name, 4); + + return $this->importFrom($format, reset($params)); + } + + if (0 === strpos($name, 'to')) { + $format = substr($name, 2); + $includeLazyLoadColumns = isset($params[0]) ? $params[0] : true; + + return $this->exportTo($format, $includeLazyLoadColumns); + } + + throw new BadMethodCallException(sprintf('Call to undefined method: %s.', $name)); + } + +} diff --git a/local/modules/CustomerFamily/Model/Base/CustomerFamilyAvailableBrand.php b/local/modules/CustomerFamily/Model/Base/CustomerFamilyAvailableBrand.php new file mode 100644 index 00000000..a374c5f8 --- /dev/null +++ b/local/modules/CustomerFamily/Model/Base/CustomerFamilyAvailableBrand.php @@ -0,0 +1,1268 @@ +modifiedColumns; + } + + /** + * Has specified column been modified? + * + * @param string $col column fully qualified name (TableMap::TYPE_COLNAME), e.g. Book::AUTHOR_ID + * @return boolean True if $col has been modified. + */ + public function isColumnModified($col) + { + return $this->modifiedColumns && isset($this->modifiedColumns[$col]); + } + + /** + * Get the columns that have been modified in this object. + * @return array A unique list of the modified column names for this object. + */ + public function getModifiedColumns() + { + return $this->modifiedColumns ? array_keys($this->modifiedColumns) : []; + } + + /** + * Returns whether the object has ever been saved. This will + * be false, if the object was retrieved from storage or was created + * and then saved. + * + * @return boolean true, if the object has never been persisted. + */ + public function isNew() + { + return $this->new; + } + + /** + * Setter for the isNew attribute. This method will be called + * by Propel-generated children and objects. + * + * @param boolean $b the state of the object. + */ + public function setNew($b) + { + $this->new = (Boolean) $b; + } + + /** + * Whether this object has been deleted. + * @return boolean The deleted state of this object. + */ + public function isDeleted() + { + return $this->deleted; + } + + /** + * Specify whether this object has been deleted. + * @param boolean $b The deleted state of this object. + * @return void + */ + public function setDeleted($b) + { + $this->deleted = (Boolean) $b; + } + + /** + * Sets the modified state for the object to be false. + * @param string $col If supplied, only the specified column is reset. + * @return void + */ + public function resetModified($col = null) + { + if (null !== $col) { + if (isset($this->modifiedColumns[$col])) { + unset($this->modifiedColumns[$col]); + } + } else { + $this->modifiedColumns = array(); + } + } + + /** + * Compares this with another CustomerFamilyAvailableBrand instance. If + * obj is an instance of CustomerFamilyAvailableBrand, delegates to + * equals(CustomerFamilyAvailableBrand). Otherwise, returns false. + * + * @param mixed $obj The object to compare to. + * @return boolean Whether equal to the object specified. + */ + public function equals($obj) + { + $thisclazz = get_class($this); + if (!is_object($obj) || !($obj instanceof $thisclazz)) { + return false; + } + + if ($this === $obj) { + return true; + } + + if (null === $this->getPrimaryKey() + || null === $obj->getPrimaryKey()) { + return false; + } + + return $this->getPrimaryKey() === $obj->getPrimaryKey(); + } + + /** + * If the primary key is not null, return the hashcode of the + * primary key. Otherwise, return the hash code of the object. + * + * @return int Hashcode + */ + public function hashCode() + { + if (null !== $this->getPrimaryKey()) { + return crc32(serialize($this->getPrimaryKey())); + } + + return crc32(serialize(clone $this)); + } + + /** + * Get the associative array of the virtual columns in this object + * + * @return array + */ + public function getVirtualColumns() + { + return $this->virtualColumns; + } + + /** + * Checks the existence of a virtual column in this object + * + * @param string $name The virtual column name + * @return boolean + */ + public function hasVirtualColumn($name) + { + return array_key_exists($name, $this->virtualColumns); + } + + /** + * Get the value of a virtual column in this object + * + * @param string $name The virtual column name + * @return mixed + * + * @throws PropelException + */ + public function getVirtualColumn($name) + { + if (!$this->hasVirtualColumn($name)) { + throw new PropelException(sprintf('Cannot get value of inexistent virtual column %s.', $name)); + } + + return $this->virtualColumns[$name]; + } + + /** + * Set the value of a virtual column in this object + * + * @param string $name The virtual column name + * @param mixed $value The value to give to the virtual column + * + * @return CustomerFamilyAvailableBrand The current object, for fluid interface + */ + public function setVirtualColumn($name, $value) + { + $this->virtualColumns[$name] = $value; + + return $this; + } + + /** + * Logs a message using Propel::log(). + * + * @param string $msg + * @param int $priority One of the Propel::LOG_* logging levels + * @return boolean + */ + protected function log($msg, $priority = Propel::LOG_INFO) + { + return Propel::log(get_class($this) . ': ' . $msg, $priority); + } + + /** + * Populate the current object from a string, using a given parser format + * + * $book = new Book(); + * $book->importFrom('JSON', '{"Id":9012,"Title":"Don Juan","ISBN":"0140422161","Price":12.99,"PublisherId":1234,"AuthorId":5678}'); + * + * + * @param mixed $parser A AbstractParser instance, + * or a format name ('XML', 'YAML', 'JSON', 'CSV') + * @param string $data The source data to import from + * + * @return CustomerFamilyAvailableBrand The current object, for fluid interface + */ + public function importFrom($parser, $data) + { + if (!$parser instanceof AbstractParser) { + $parser = AbstractParser::getParser($parser); + } + + $this->fromArray($parser->toArray($data), TableMap::TYPE_PHPNAME); + + return $this; + } + + /** + * Export the current object properties to a string, using a given parser format + * + * $book = BookQuery::create()->findPk(9012); + * echo $book->exportTo('JSON'); + * => {"Id":9012,"Title":"Don Juan","ISBN":"0140422161","Price":12.99,"PublisherId":1234,"AuthorId":5678}'); + * + * + * @param mixed $parser A AbstractParser instance, or a format name ('XML', 'YAML', 'JSON', 'CSV') + * @param boolean $includeLazyLoadColumns (optional) Whether to include lazy load(ed) columns. Defaults to TRUE. + * @return string The exported data + */ + public function exportTo($parser, $includeLazyLoadColumns = true) + { + if (!$parser instanceof AbstractParser) { + $parser = AbstractParser::getParser($parser); + } + + return $parser->fromArray($this->toArray(TableMap::TYPE_PHPNAME, $includeLazyLoadColumns, array(), true)); + } + + /** + * Clean up internal collections prior to serializing + * Avoids recursive loops that turn into segmentation faults when serializing + */ + public function __sleep() + { + $this->clearAllReferences(); + + return array_keys(get_object_vars($this)); + } + + /** + * Get the [customer_family_id] column value. + * + * @return int + */ + public function getCustomerFamilyId() + { + + return $this->customer_family_id; + } + + /** + * Get the [brand_id] column value. + * + * @return int + */ + public function getBrandId() + { + + return $this->brand_id; + } + + /** + * Set the value of [customer_family_id] column. + * + * @param int $v new value + * @return \CustomerFamily\Model\CustomerFamilyAvailableBrand The current object (for fluent API support) + */ + public function setCustomerFamilyId($v) + { + if ($v !== null) { + $v = (int) $v; + } + + if ($this->customer_family_id !== $v) { + $this->customer_family_id = $v; + $this->modifiedColumns[CustomerFamilyAvailableBrandTableMap::CUSTOMER_FAMILY_ID] = true; + } + + if ($this->aCustomerFamily !== null && $this->aCustomerFamily->getId() !== $v) { + $this->aCustomerFamily = null; + } + + + return $this; + } // setCustomerFamilyId() + + /** + * Set the value of [brand_id] column. + * + * @param int $v new value + * @return \CustomerFamily\Model\CustomerFamilyAvailableBrand The current object (for fluent API support) + */ + public function setBrandId($v) + { + if ($v !== null) { + $v = (int) $v; + } + + if ($this->brand_id !== $v) { + $this->brand_id = $v; + $this->modifiedColumns[CustomerFamilyAvailableBrandTableMap::BRAND_ID] = true; + } + + if ($this->aBrand !== null && $this->aBrand->getId() !== $v) { + $this->aBrand = null; + } + + + return $this; + } // setBrandId() + + /** + * Indicates whether the columns in this object are only set to default values. + * + * This method can be used in conjunction with isModified() to indicate whether an object is both + * modified _and_ has some values set which are non-default. + * + * @return boolean Whether the columns in this object are only been set with default values. + */ + public function hasOnlyDefaultValues() + { + // otherwise, everything was equal, so return TRUE + return true; + } // hasOnlyDefaultValues() + + /** + * Hydrates (populates) the object variables with values from the database resultset. + * + * An offset (0-based "start column") is specified so that objects can be hydrated + * with a subset of the columns in the resultset rows. This is needed, for example, + * for results of JOIN queries where the resultset row includes columns from two or + * more tables. + * + * @param array $row The row returned by DataFetcher->fetch(). + * @param int $startcol 0-based offset column which indicates which restultset column to start with. + * @param boolean $rehydrate Whether this object is being re-hydrated from the database. + * @param string $indexType The index type of $row. Mostly DataFetcher->getIndexType(). + One of the class type constants TableMap::TYPE_PHPNAME, TableMap::TYPE_STUDLYPHPNAME + * TableMap::TYPE_COLNAME, TableMap::TYPE_FIELDNAME, TableMap::TYPE_NUM. + * + * @return int next starting column + * @throws PropelException - Any caught Exception will be rewrapped as a PropelException. + */ + public function hydrate($row, $startcol = 0, $rehydrate = false, $indexType = TableMap::TYPE_NUM) + { + try { + + + $col = $row[TableMap::TYPE_NUM == $indexType ? 0 + $startcol : CustomerFamilyAvailableBrandTableMap::translateFieldName('CustomerFamilyId', TableMap::TYPE_PHPNAME, $indexType)]; + $this->customer_family_id = (null !== $col) ? (int) $col : null; + + $col = $row[TableMap::TYPE_NUM == $indexType ? 1 + $startcol : CustomerFamilyAvailableBrandTableMap::translateFieldName('BrandId', TableMap::TYPE_PHPNAME, $indexType)]; + $this->brand_id = (null !== $col) ? (int) $col : null; + $this->resetModified(); + + $this->setNew(false); + + if ($rehydrate) { + $this->ensureConsistency(); + } + + return $startcol + 2; // 2 = CustomerFamilyAvailableBrandTableMap::NUM_HYDRATE_COLUMNS. + + } catch (Exception $e) { + throw new PropelException("Error populating \CustomerFamily\Model\CustomerFamilyAvailableBrand object", 0, $e); + } + } + + /** + * Checks and repairs the internal consistency of the object. + * + * This method is executed after an already-instantiated object is re-hydrated + * from the database. It exists to check any foreign keys to make sure that + * the objects related to the current object are correct based on foreign key. + * + * You can override this method in the stub class, but you should always invoke + * the base method from the overridden method (i.e. parent::ensureConsistency()), + * in case your model changes. + * + * @throws PropelException + */ + public function ensureConsistency() + { + if ($this->aCustomerFamily !== null && $this->customer_family_id !== $this->aCustomerFamily->getId()) { + $this->aCustomerFamily = null; + } + if ($this->aBrand !== null && $this->brand_id !== $this->aBrand->getId()) { + $this->aBrand = null; + } + } // ensureConsistency + + /** + * Reloads this object from datastore based on primary key and (optionally) resets all associated objects. + * + * This will only work if the object has been saved and has a valid primary key set. + * + * @param boolean $deep (optional) Whether to also de-associated any related objects. + * @param ConnectionInterface $con (optional) The ConnectionInterface connection to use. + * @return void + * @throws PropelException - if this object is deleted, unsaved or doesn't have pk match in db + */ + public function reload($deep = false, ConnectionInterface $con = null) + { + if ($this->isDeleted()) { + throw new PropelException("Cannot reload a deleted object."); + } + + if ($this->isNew()) { + throw new PropelException("Cannot reload an unsaved object."); + } + + if ($con === null) { + $con = Propel::getServiceContainer()->getReadConnection(CustomerFamilyAvailableBrandTableMap::DATABASE_NAME); + } + + // We don't need to alter the object instance pool; we're just modifying this instance + // already in the pool. + + $dataFetcher = ChildCustomerFamilyAvailableBrandQuery::create(null, $this->buildPkeyCriteria())->setFormatter(ModelCriteria::FORMAT_STATEMENT)->find($con); + $row = $dataFetcher->fetch(); + $dataFetcher->close(); + if (!$row) { + throw new PropelException('Cannot find matching row in the database to reload object values.'); + } + $this->hydrate($row, 0, true, $dataFetcher->getIndexType()); // rehydrate + + if ($deep) { // also de-associate any related objects? + + $this->aCustomerFamily = null; + $this->aBrand = null; + } // if (deep) + } + + /** + * Removes this object from datastore and sets delete attribute. + * + * @param ConnectionInterface $con + * @return void + * @throws PropelException + * @see CustomerFamilyAvailableBrand::setDeleted() + * @see CustomerFamilyAvailableBrand::isDeleted() + */ + public function delete(ConnectionInterface $con = null) + { + if ($this->isDeleted()) { + throw new PropelException("This object has already been deleted."); + } + + if ($con === null) { + $con = Propel::getServiceContainer()->getWriteConnection(CustomerFamilyAvailableBrandTableMap::DATABASE_NAME); + } + + $con->beginTransaction(); + try { + $deleteQuery = ChildCustomerFamilyAvailableBrandQuery::create() + ->filterByPrimaryKey($this->getPrimaryKey()); + $ret = $this->preDelete($con); + if ($ret) { + $deleteQuery->delete($con); + $this->postDelete($con); + $con->commit(); + $this->setDeleted(true); + } else { + $con->commit(); + } + } catch (Exception $e) { + $con->rollBack(); + throw $e; + } + } + + /** + * Persists this object to the database. + * + * If the object is new, it inserts it; otherwise an update is performed. + * All modified related objects will also be persisted in the doSave() + * method. This method wraps all precipitate database operations in a + * single transaction. + * + * @param ConnectionInterface $con + * @return int The number of rows affected by this insert/update and any referring fk objects' save() operations. + * @throws PropelException + * @see doSave() + */ + public function save(ConnectionInterface $con = null) + { + if ($this->isDeleted()) { + throw new PropelException("You cannot save an object that has been deleted."); + } + + if ($con === null) { + $con = Propel::getServiceContainer()->getWriteConnection(CustomerFamilyAvailableBrandTableMap::DATABASE_NAME); + } + + $con->beginTransaction(); + $isInsert = $this->isNew(); + try { + $ret = $this->preSave($con); + if ($isInsert) { + $ret = $ret && $this->preInsert($con); + } else { + $ret = $ret && $this->preUpdate($con); + } + if ($ret) { + $affectedRows = $this->doSave($con); + if ($isInsert) { + $this->postInsert($con); + } else { + $this->postUpdate($con); + } + $this->postSave($con); + CustomerFamilyAvailableBrandTableMap::addInstanceToPool($this); + } else { + $affectedRows = 0; + } + $con->commit(); + + return $affectedRows; + } catch (Exception $e) { + $con->rollBack(); + throw $e; + } + } + + /** + * Performs the work of inserting or updating the row in the database. + * + * If the object is new, it inserts it; otherwise an update is performed. + * All related objects are also updated in this method. + * + * @param ConnectionInterface $con + * @return int The number of rows affected by this insert/update and any referring fk objects' save() operations. + * @throws PropelException + * @see save() + */ + protected function doSave(ConnectionInterface $con) + { + $affectedRows = 0; // initialize var to track total num of affected rows + if (!$this->alreadyInSave) { + $this->alreadyInSave = true; + + // We call the save method on the following object(s) if they + // were passed to this object by their corresponding set + // method. This object relates to these object(s) by a + // foreign key reference. + + if ($this->aCustomerFamily !== null) { + if ($this->aCustomerFamily->isModified() || $this->aCustomerFamily->isNew()) { + $affectedRows += $this->aCustomerFamily->save($con); + } + $this->setCustomerFamily($this->aCustomerFamily); + } + + if ($this->aBrand !== null) { + if ($this->aBrand->isModified() || $this->aBrand->isNew()) { + $affectedRows += $this->aBrand->save($con); + } + $this->setBrand($this->aBrand); + } + + if ($this->isNew() || $this->isModified()) { + // persist changes + if ($this->isNew()) { + $this->doInsert($con); + } else { + $this->doUpdate($con); + } + $affectedRows += 1; + $this->resetModified(); + } + + $this->alreadyInSave = false; + + } + + return $affectedRows; + } // doSave() + + /** + * Insert the row in the database. + * + * @param ConnectionInterface $con + * + * @throws PropelException + * @see doSave() + */ + protected function doInsert(ConnectionInterface $con) + { + $modifiedColumns = array(); + $index = 0; + + + // check the columns in natural order for more readable SQL queries + if ($this->isColumnModified(CustomerFamilyAvailableBrandTableMap::CUSTOMER_FAMILY_ID)) { + $modifiedColumns[':p' . $index++] = 'CUSTOMER_FAMILY_ID'; + } + if ($this->isColumnModified(CustomerFamilyAvailableBrandTableMap::BRAND_ID)) { + $modifiedColumns[':p' . $index++] = 'BRAND_ID'; + } + + $sql = sprintf( + 'INSERT INTO customer_family_available_brand (%s) VALUES (%s)', + implode(', ', $modifiedColumns), + implode(', ', array_keys($modifiedColumns)) + ); + + try { + $stmt = $con->prepare($sql); + foreach ($modifiedColumns as $identifier => $columnName) { + switch ($columnName) { + case 'CUSTOMER_FAMILY_ID': + $stmt->bindValue($identifier, $this->customer_family_id, PDO::PARAM_INT); + break; + case 'BRAND_ID': + $stmt->bindValue($identifier, $this->brand_id, PDO::PARAM_INT); + break; + } + } + $stmt->execute(); + } catch (Exception $e) { + Propel::log($e->getMessage(), Propel::LOG_ERR); + throw new PropelException(sprintf('Unable to execute INSERT statement [%s]', $sql), 0, $e); + } + + $this->setNew(false); + } + + /** + * Update the row in the database. + * + * @param ConnectionInterface $con + * + * @return Integer Number of updated rows + * @see doSave() + */ + protected function doUpdate(ConnectionInterface $con) + { + $selectCriteria = $this->buildPkeyCriteria(); + $valuesCriteria = $this->buildCriteria(); + + return $selectCriteria->doUpdate($valuesCriteria, $con); + } + + /** + * Retrieves a field from the object by name passed in as a string. + * + * @param string $name name + * @param string $type The type of fieldname the $name is of: + * one of the class type constants TableMap::TYPE_PHPNAME, TableMap::TYPE_STUDLYPHPNAME + * TableMap::TYPE_COLNAME, TableMap::TYPE_FIELDNAME, TableMap::TYPE_NUM. + * Defaults to TableMap::TYPE_PHPNAME. + * @return mixed Value of field. + */ + public function getByName($name, $type = TableMap::TYPE_PHPNAME) + { + $pos = CustomerFamilyAvailableBrandTableMap::translateFieldName($name, $type, TableMap::TYPE_NUM); + $field = $this->getByPosition($pos); + + return $field; + } + + /** + * Retrieves a field from the object by Position as specified in the xml schema. + * Zero-based. + * + * @param int $pos position in xml schema + * @return mixed Value of field at $pos + */ + public function getByPosition($pos) + { + switch ($pos) { + case 0: + return $this->getCustomerFamilyId(); + break; + case 1: + return $this->getBrandId(); + break; + default: + return null; + break; + } // switch() + } + + /** + * Exports the object as an array. + * + * You can specify the key type of the array by passing one of the class + * type constants. + * + * @param string $keyType (optional) One of the class type constants TableMap::TYPE_PHPNAME, TableMap::TYPE_STUDLYPHPNAME, + * TableMap::TYPE_COLNAME, TableMap::TYPE_FIELDNAME, TableMap::TYPE_NUM. + * Defaults to TableMap::TYPE_PHPNAME. + * @param boolean $includeLazyLoadColumns (optional) Whether to include lazy loaded columns. Defaults to TRUE. + * @param array $alreadyDumpedObjects List of objects to skip to avoid recursion + * @param boolean $includeForeignObjects (optional) Whether to include hydrated related objects. Default to FALSE. + * + * @return array an associative array containing the field names (as keys) and field values + */ + public function toArray($keyType = TableMap::TYPE_PHPNAME, $includeLazyLoadColumns = true, $alreadyDumpedObjects = array(), $includeForeignObjects = false) + { + if (isset($alreadyDumpedObjects['CustomerFamilyAvailableBrand'][serialize($this->getPrimaryKey())])) { + return '*RECURSION*'; + } + $alreadyDumpedObjects['CustomerFamilyAvailableBrand'][serialize($this->getPrimaryKey())] = true; + $keys = CustomerFamilyAvailableBrandTableMap::getFieldNames($keyType); + $result = array( + $keys[0] => $this->getCustomerFamilyId(), + $keys[1] => $this->getBrandId(), + ); + $virtualColumns = $this->virtualColumns; + foreach ($virtualColumns as $key => $virtualColumn) { + $result[$key] = $virtualColumn; + } + + if ($includeForeignObjects) { + if (null !== $this->aCustomerFamily) { + $result['CustomerFamily'] = $this->aCustomerFamily->toArray($keyType, $includeLazyLoadColumns, $alreadyDumpedObjects, true); + } + if (null !== $this->aBrand) { + $result['Brand'] = $this->aBrand->toArray($keyType, $includeLazyLoadColumns, $alreadyDumpedObjects, true); + } + } + + return $result; + } + + /** + * Sets a field from the object by name passed in as a string. + * + * @param string $name + * @param mixed $value field value + * @param string $type The type of fieldname the $name is of: + * one of the class type constants TableMap::TYPE_PHPNAME, TableMap::TYPE_STUDLYPHPNAME + * TableMap::TYPE_COLNAME, TableMap::TYPE_FIELDNAME, TableMap::TYPE_NUM. + * Defaults to TableMap::TYPE_PHPNAME. + * @return void + */ + public function setByName($name, $value, $type = TableMap::TYPE_PHPNAME) + { + $pos = CustomerFamilyAvailableBrandTableMap::translateFieldName($name, $type, TableMap::TYPE_NUM); + + return $this->setByPosition($pos, $value); + } + + /** + * Sets a field from the object by Position as specified in the xml schema. + * Zero-based. + * + * @param int $pos position in xml schema + * @param mixed $value field value + * @return void + */ + public function setByPosition($pos, $value) + { + switch ($pos) { + case 0: + $this->setCustomerFamilyId($value); + break; + case 1: + $this->setBrandId($value); + break; + } // switch() + } + + /** + * Populates the object using an array. + * + * This is particularly useful when populating an object from one of the + * request arrays (e.g. $_POST). This method goes through the column + * names, checking to see whether a matching key exists in populated + * array. If so the setByName() method is called for that column. + * + * You can specify the key type of the array by additionally passing one + * of the class type constants TableMap::TYPE_PHPNAME, TableMap::TYPE_STUDLYPHPNAME, + * TableMap::TYPE_COLNAME, TableMap::TYPE_FIELDNAME, TableMap::TYPE_NUM. + * The default key type is the column's TableMap::TYPE_PHPNAME. + * + * @param array $arr An array to populate the object from. + * @param string $keyType The type of keys the array uses. + * @return void + */ + public function fromArray($arr, $keyType = TableMap::TYPE_PHPNAME) + { + $keys = CustomerFamilyAvailableBrandTableMap::getFieldNames($keyType); + + if (array_key_exists($keys[0], $arr)) $this->setCustomerFamilyId($arr[$keys[0]]); + if (array_key_exists($keys[1], $arr)) $this->setBrandId($arr[$keys[1]]); + } + + /** + * Build a Criteria object containing the values of all modified columns in this object. + * + * @return Criteria The Criteria object containing all modified values. + */ + public function buildCriteria() + { + $criteria = new Criteria(CustomerFamilyAvailableBrandTableMap::DATABASE_NAME); + + if ($this->isColumnModified(CustomerFamilyAvailableBrandTableMap::CUSTOMER_FAMILY_ID)) $criteria->add(CustomerFamilyAvailableBrandTableMap::CUSTOMER_FAMILY_ID, $this->customer_family_id); + if ($this->isColumnModified(CustomerFamilyAvailableBrandTableMap::BRAND_ID)) $criteria->add(CustomerFamilyAvailableBrandTableMap::BRAND_ID, $this->brand_id); + + return $criteria; + } + + /** + * Builds a Criteria object containing the primary key for this object. + * + * Unlike buildCriteria() this method includes the primary key values regardless + * of whether or not they have been modified. + * + * @return Criteria The Criteria object containing value(s) for primary key(s). + */ + public function buildPkeyCriteria() + { + $criteria = new Criteria(CustomerFamilyAvailableBrandTableMap::DATABASE_NAME); + $criteria->add(CustomerFamilyAvailableBrandTableMap::CUSTOMER_FAMILY_ID, $this->customer_family_id); + $criteria->add(CustomerFamilyAvailableBrandTableMap::BRAND_ID, $this->brand_id); + + return $criteria; + } + + /** + * Returns the composite primary key for this object. + * The array elements will be in same order as specified in XML. + * @return array + */ + public function getPrimaryKey() + { + $pks = array(); + $pks[0] = $this->getCustomerFamilyId(); + $pks[1] = $this->getBrandId(); + + return $pks; + } + + /** + * Set the [composite] primary key. + * + * @param array $keys The elements of the composite key (order must match the order in XML file). + * @return void + */ + public function setPrimaryKey($keys) + { + $this->setCustomerFamilyId($keys[0]); + $this->setBrandId($keys[1]); + } + + /** + * Returns true if the primary key for this object is null. + * @return boolean + */ + public function isPrimaryKeyNull() + { + + return (null === $this->getCustomerFamilyId()) && (null === $this->getBrandId()); + } + + /** + * Sets contents of passed object to values from current object. + * + * If desired, this method can also make copies of all associated (fkey referrers) + * objects. + * + * @param object $copyObj An object of \CustomerFamily\Model\CustomerFamilyAvailableBrand (or compatible) type. + * @param boolean $deepCopy Whether to also copy all rows that refer (by fkey) to the current row. + * @param boolean $makeNew Whether to reset autoincrement PKs and make the object new. + * @throws PropelException + */ + public function copyInto($copyObj, $deepCopy = false, $makeNew = true) + { + $copyObj->setCustomerFamilyId($this->getCustomerFamilyId()); + $copyObj->setBrandId($this->getBrandId()); + if ($makeNew) { + $copyObj->setNew(true); + } + } + + /** + * Makes a copy of this object that will be inserted as a new row in table when saved. + * It creates a new object filling in the simple attributes, but skipping any primary + * keys that are defined for the table. + * + * If desired, this method can also make copies of all associated (fkey referrers) + * objects. + * + * @param boolean $deepCopy Whether to also copy all rows that refer (by fkey) to the current row. + * @return \CustomerFamily\Model\CustomerFamilyAvailableBrand Clone of current object. + * @throws PropelException + */ + public function copy($deepCopy = false) + { + // we use get_class(), because this might be a subclass + $clazz = get_class($this); + $copyObj = new $clazz(); + $this->copyInto($copyObj, $deepCopy); + + return $copyObj; + } + + /** + * Declares an association between this object and a ChildCustomerFamily object. + * + * @param ChildCustomerFamily $v + * @return \CustomerFamily\Model\CustomerFamilyAvailableBrand The current object (for fluent API support) + * @throws PropelException + */ + public function setCustomerFamily(ChildCustomerFamily $v = null) + { + if ($v === null) { + $this->setCustomerFamilyId(NULL); + } else { + $this->setCustomerFamilyId($v->getId()); + } + + $this->aCustomerFamily = $v; + + // Add binding for other direction of this n:n relationship. + // If this object has already been added to the ChildCustomerFamily object, it will not be re-added. + if ($v !== null) { + $v->addCustomerFamilyAvailableBrand($this); + } + + + return $this; + } + + + /** + * Get the associated ChildCustomerFamily object + * + * @param ConnectionInterface $con Optional Connection object. + * @return ChildCustomerFamily The associated ChildCustomerFamily object. + * @throws PropelException + */ + public function getCustomerFamily(ConnectionInterface $con = null) + { + if ($this->aCustomerFamily === null && ($this->customer_family_id !== null)) { + $this->aCustomerFamily = ChildCustomerFamilyQuery::create()->findPk($this->customer_family_id, $con); + /* The following can be used additionally to + guarantee the related object contains a reference + to this object. This level of coupling may, however, be + undesirable since it could result in an only partially populated collection + in the referenced object. + $this->aCustomerFamily->addCustomerFamilyAvailableBrands($this); + */ + } + + return $this->aCustomerFamily; + } + + /** + * Declares an association between this object and a ChildBrand object. + * + * @param ChildBrand $v + * @return \CustomerFamily\Model\CustomerFamilyAvailableBrand The current object (for fluent API support) + * @throws PropelException + */ + public function setBrand(ChildBrand $v = null) + { + if ($v === null) { + $this->setBrandId(NULL); + } else { + $this->setBrandId($v->getId()); + } + + $this->aBrand = $v; + + // Add binding for other direction of this n:n relationship. + // If this object has already been added to the ChildBrand object, it will not be re-added. + if ($v !== null) { + $v->addCustomerFamilyAvailableBrand($this); + } + + + return $this; + } + + + /** + * Get the associated ChildBrand object + * + * @param ConnectionInterface $con Optional Connection object. + * @return ChildBrand The associated ChildBrand object. + * @throws PropelException + */ + public function getBrand(ConnectionInterface $con = null) + { + if ($this->aBrand === null && ($this->brand_id !== null)) { + $this->aBrand = BrandQuery::create()->findPk($this->brand_id, $con); + /* The following can be used additionally to + guarantee the related object contains a reference + to this object. This level of coupling may, however, be + undesirable since it could result in an only partially populated collection + in the referenced object. + $this->aBrand->addCustomerFamilyAvailableBrands($this); + */ + } + + return $this->aBrand; + } + + /** + * Clears the current object and sets all attributes to their default values + */ + public function clear() + { + $this->customer_family_id = null; + $this->brand_id = null; + $this->alreadyInSave = false; + $this->clearAllReferences(); + $this->resetModified(); + $this->setNew(true); + $this->setDeleted(false); + } + + /** + * Resets all references to other model objects or collections of model objects. + * + * This method is a user-space workaround for PHP's inability to garbage collect + * objects with circular references (even in PHP 5.3). This is currently necessary + * when using Propel in certain daemon or large-volume/high-memory operations. + * + * @param boolean $deep Whether to also clear the references on all referrer objects. + */ + public function clearAllReferences($deep = false) + { + if ($deep) { + } // if ($deep) + + $this->aCustomerFamily = null; + $this->aBrand = null; + } + + /** + * Return the string representation of this object + * + * @return string + */ + public function __toString() + { + return (string) $this->exportTo(CustomerFamilyAvailableBrandTableMap::DEFAULT_STRING_FORMAT); + } + + /** + * Code to be run before persisting the object + * @param ConnectionInterface $con + * @return boolean + */ + public function preSave(ConnectionInterface $con = null) + { + return true; + } + + /** + * Code to be run after persisting the object + * @param ConnectionInterface $con + */ + public function postSave(ConnectionInterface $con = null) + { + + } + + /** + * Code to be run before inserting to database + * @param ConnectionInterface $con + * @return boolean + */ + public function preInsert(ConnectionInterface $con = null) + { + return true; + } + + /** + * Code to be run after inserting to database + * @param ConnectionInterface $con + */ + public function postInsert(ConnectionInterface $con = null) + { + + } + + /** + * Code to be run before updating the object in database + * @param ConnectionInterface $con + * @return boolean + */ + public function preUpdate(ConnectionInterface $con = null) + { + return true; + } + + /** + * Code to be run after updating the object in database + * @param ConnectionInterface $con + */ + public function postUpdate(ConnectionInterface $con = null) + { + + } + + /** + * Code to be run before deleting the object in database + * @param ConnectionInterface $con + * @return boolean + */ + public function preDelete(ConnectionInterface $con = null) + { + return true; + } + + /** + * Code to be run after deleting the object in database + * @param ConnectionInterface $con + */ + public function postDelete(ConnectionInterface $con = null) + { + + } + + + /** + * Derived method to catches calls to undefined methods. + * + * Provides magic import/export method support (fromXML()/toXML(), fromYAML()/toYAML(), etc.). + * Allows to define default __call() behavior if you overwrite __call() + * + * @param string $name + * @param mixed $params + * + * @return array|string + */ + public function __call($name, $params) + { + if (0 === strpos($name, 'get')) { + $virtualColumn = substr($name, 3); + if ($this->hasVirtualColumn($virtualColumn)) { + return $this->getVirtualColumn($virtualColumn); + } + + $virtualColumn = lcfirst($virtualColumn); + if ($this->hasVirtualColumn($virtualColumn)) { + return $this->getVirtualColumn($virtualColumn); + } + } + + if (0 === strpos($name, 'from')) { + $format = substr($name, 4); + + return $this->importFrom($format, reset($params)); + } + + if (0 === strpos($name, 'to')) { + $format = substr($name, 2); + $includeLazyLoadColumns = isset($params[0]) ? $params[0] : true; + + return $this->exportTo($format, $includeLazyLoadColumns); + } + + throw new BadMethodCallException(sprintf('Call to undefined method: %s.', $name)); + } + +} diff --git a/local/modules/CustomerFamily/Model/Base/CustomerFamilyAvailableBrandQuery.php b/local/modules/CustomerFamily/Model/Base/CustomerFamilyAvailableBrandQuery.php new file mode 100644 index 00000000..495264d1 --- /dev/null +++ b/local/modules/CustomerFamily/Model/Base/CustomerFamilyAvailableBrandQuery.php @@ -0,0 +1,569 @@ +setModelAlias($modelAlias); + } + if ($criteria instanceof Criteria) { + $query->mergeWith($criteria); + } + + return $query; + } + + /** + * Find object by primary key. + * Propel uses the instance pool to skip the database if the object exists. + * Go fast if the query is untouched. + * + * + * $obj = $c->findPk(array(12, 34), $con); + * + * + * @param array[$customer_family_id, $brand_id] $key Primary key to use for the query + * @param ConnectionInterface $con an optional connection object + * + * @return ChildCustomerFamilyAvailableBrand|array|mixed the result, formatted by the current formatter + */ + public function findPk($key, $con = null) + { + if ($key === null) { + return null; + } + if ((null !== ($obj = CustomerFamilyAvailableBrandTableMap::getInstanceFromPool(serialize(array((string) $key[0], (string) $key[1]))))) && !$this->formatter) { + // the object is already in the instance pool + return $obj; + } + if ($con === null) { + $con = Propel::getServiceContainer()->getReadConnection(CustomerFamilyAvailableBrandTableMap::DATABASE_NAME); + } + $this->basePreSelect($con); + if ($this->formatter || $this->modelAlias || $this->with || $this->select + || $this->selectColumns || $this->asColumns || $this->selectModifiers + || $this->map || $this->having || $this->joins) { + return $this->findPkComplex($key, $con); + } else { + return $this->findPkSimple($key, $con); + } + } + + /** + * Find object by primary key using raw SQL to go fast. + * Bypass doSelect() and the object formatter by using generated code. + * + * @param mixed $key Primary key to use for the query + * @param ConnectionInterface $con A connection object + * + * @return ChildCustomerFamilyAvailableBrand A model object, or null if the key is not found + */ + protected function findPkSimple($key, $con) + { + $sql = 'SELECT CUSTOMER_FAMILY_ID, BRAND_ID FROM customer_family_available_brand WHERE CUSTOMER_FAMILY_ID = :p0 AND BRAND_ID = :p1'; + try { + $stmt = $con->prepare($sql); + $stmt->bindValue(':p0', $key[0], PDO::PARAM_INT); + $stmt->bindValue(':p1', $key[1], PDO::PARAM_INT); + $stmt->execute(); + } catch (Exception $e) { + Propel::log($e->getMessage(), Propel::LOG_ERR); + throw new PropelException(sprintf('Unable to execute SELECT statement [%s]', $sql), 0, $e); + } + $obj = null; + if ($row = $stmt->fetch(\PDO::FETCH_NUM)) { + $obj = new ChildCustomerFamilyAvailableBrand(); + $obj->hydrate($row); + CustomerFamilyAvailableBrandTableMap::addInstanceToPool($obj, serialize(array((string) $key[0], (string) $key[1]))); + } + $stmt->closeCursor(); + + return $obj; + } + + /** + * Find object by primary key. + * + * @param mixed $key Primary key to use for the query + * @param ConnectionInterface $con A connection object + * + * @return ChildCustomerFamilyAvailableBrand|array|mixed the result, formatted by the current formatter + */ + protected function findPkComplex($key, $con) + { + // As the query uses a PK condition, no limit(1) is necessary. + $criteria = $this->isKeepQuery() ? clone $this : $this; + $dataFetcher = $criteria + ->filterByPrimaryKey($key) + ->doSelect($con); + + return $criteria->getFormatter()->init($criteria)->formatOne($dataFetcher); + } + + /** + * Find objects by primary key + * + * $objs = $c->findPks(array(array(12, 56), array(832, 123), array(123, 456)), $con); + * + * @param array $keys Primary keys to use for the query + * @param ConnectionInterface $con an optional connection object + * + * @return ObjectCollection|array|mixed the list of results, formatted by the current formatter + */ + public function findPks($keys, $con = null) + { + if (null === $con) { + $con = Propel::getServiceContainer()->getReadConnection($this->getDbName()); + } + $this->basePreSelect($con); + $criteria = $this->isKeepQuery() ? clone $this : $this; + $dataFetcher = $criteria + ->filterByPrimaryKeys($keys) + ->doSelect($con); + + return $criteria->getFormatter()->init($criteria)->format($dataFetcher); + } + + /** + * Filter the query by primary key + * + * @param mixed $key Primary key to use for the query + * + * @return ChildCustomerFamilyAvailableBrandQuery The current query, for fluid interface + */ + public function filterByPrimaryKey($key) + { + $this->addUsingAlias(CustomerFamilyAvailableBrandTableMap::CUSTOMER_FAMILY_ID, $key[0], Criteria::EQUAL); + $this->addUsingAlias(CustomerFamilyAvailableBrandTableMap::BRAND_ID, $key[1], Criteria::EQUAL); + + return $this; + } + + /** + * Filter the query by a list of primary keys + * + * @param array $keys The list of primary key to use for the query + * + * @return ChildCustomerFamilyAvailableBrandQuery The current query, for fluid interface + */ + public function filterByPrimaryKeys($keys) + { + if (empty($keys)) { + return $this->add(null, '1<>1', Criteria::CUSTOM); + } + foreach ($keys as $key) { + $cton0 = $this->getNewCriterion(CustomerFamilyAvailableBrandTableMap::CUSTOMER_FAMILY_ID, $key[0], Criteria::EQUAL); + $cton1 = $this->getNewCriterion(CustomerFamilyAvailableBrandTableMap::BRAND_ID, $key[1], Criteria::EQUAL); + $cton0->addAnd($cton1); + $this->addOr($cton0); + } + + return $this; + } + + /** + * Filter the query on the customer_family_id column + * + * Example usage: + * + * $query->filterByCustomerFamilyId(1234); // WHERE customer_family_id = 1234 + * $query->filterByCustomerFamilyId(array(12, 34)); // WHERE customer_family_id IN (12, 34) + * $query->filterByCustomerFamilyId(array('min' => 12)); // WHERE customer_family_id > 12 + * + * + * @see filterByCustomerFamily() + * + * @param mixed $customerFamilyId The value to use as filter. + * Use scalar values for equality. + * Use array values for in_array() equivalent. + * Use associative array('min' => $minValue, 'max' => $maxValue) for intervals. + * @param string $comparison Operator to use for the column comparison, defaults to Criteria::EQUAL + * + * @return ChildCustomerFamilyAvailableBrandQuery The current query, for fluid interface + */ + public function filterByCustomerFamilyId($customerFamilyId = null, $comparison = null) + { + if (is_array($customerFamilyId)) { + $useMinMax = false; + if (isset($customerFamilyId['min'])) { + $this->addUsingAlias(CustomerFamilyAvailableBrandTableMap::CUSTOMER_FAMILY_ID, $customerFamilyId['min'], Criteria::GREATER_EQUAL); + $useMinMax = true; + } + if (isset($customerFamilyId['max'])) { + $this->addUsingAlias(CustomerFamilyAvailableBrandTableMap::CUSTOMER_FAMILY_ID, $customerFamilyId['max'], Criteria::LESS_EQUAL); + $useMinMax = true; + } + if ($useMinMax) { + return $this; + } + if (null === $comparison) { + $comparison = Criteria::IN; + } + } + + return $this->addUsingAlias(CustomerFamilyAvailableBrandTableMap::CUSTOMER_FAMILY_ID, $customerFamilyId, $comparison); + } + + /** + * Filter the query on the brand_id column + * + * Example usage: + * + * $query->filterByBrandId(1234); // WHERE brand_id = 1234 + * $query->filterByBrandId(array(12, 34)); // WHERE brand_id IN (12, 34) + * $query->filterByBrandId(array('min' => 12)); // WHERE brand_id > 12 + * + * + * @see filterByBrand() + * + * @param mixed $brandId The value to use as filter. + * Use scalar values for equality. + * Use array values for in_array() equivalent. + * Use associative array('min' => $minValue, 'max' => $maxValue) for intervals. + * @param string $comparison Operator to use for the column comparison, defaults to Criteria::EQUAL + * + * @return ChildCustomerFamilyAvailableBrandQuery The current query, for fluid interface + */ + public function filterByBrandId($brandId = null, $comparison = null) + { + if (is_array($brandId)) { + $useMinMax = false; + if (isset($brandId['min'])) { + $this->addUsingAlias(CustomerFamilyAvailableBrandTableMap::BRAND_ID, $brandId['min'], Criteria::GREATER_EQUAL); + $useMinMax = true; + } + if (isset($brandId['max'])) { + $this->addUsingAlias(CustomerFamilyAvailableBrandTableMap::BRAND_ID, $brandId['max'], Criteria::LESS_EQUAL); + $useMinMax = true; + } + if ($useMinMax) { + return $this; + } + if (null === $comparison) { + $comparison = Criteria::IN; + } + } + + return $this->addUsingAlias(CustomerFamilyAvailableBrandTableMap::BRAND_ID, $brandId, $comparison); + } + + /** + * Filter the query by a related \CustomerFamily\Model\CustomerFamily object + * + * @param \CustomerFamily\Model\CustomerFamily|ObjectCollection $customerFamily The related object(s) to use as filter + * @param string $comparison Operator to use for the column comparison, defaults to Criteria::EQUAL + * + * @return ChildCustomerFamilyAvailableBrandQuery The current query, for fluid interface + */ + public function filterByCustomerFamily($customerFamily, $comparison = null) + { + if ($customerFamily instanceof \CustomerFamily\Model\CustomerFamily) { + return $this + ->addUsingAlias(CustomerFamilyAvailableBrandTableMap::CUSTOMER_FAMILY_ID, $customerFamily->getId(), $comparison); + } elseif ($customerFamily instanceof ObjectCollection) { + if (null === $comparison) { + $comparison = Criteria::IN; + } + + return $this + ->addUsingAlias(CustomerFamilyAvailableBrandTableMap::CUSTOMER_FAMILY_ID, $customerFamily->toKeyValue('PrimaryKey', 'Id'), $comparison); + } else { + throw new PropelException('filterByCustomerFamily() only accepts arguments of type \CustomerFamily\Model\CustomerFamily or Collection'); + } + } + + /** + * Adds a JOIN clause to the query using the CustomerFamily relation + * + * @param string $relationAlias optional alias for the relation + * @param string $joinType Accepted values are null, 'left join', 'right join', 'inner join' + * + * @return ChildCustomerFamilyAvailableBrandQuery The current query, for fluid interface + */ + public function joinCustomerFamily($relationAlias = null, $joinType = Criteria::INNER_JOIN) + { + $tableMap = $this->getTableMap(); + $relationMap = $tableMap->getRelation('CustomerFamily'); + + // create a ModelJoin object for this join + $join = new ModelJoin(); + $join->setJoinType($joinType); + $join->setRelationMap($relationMap, $this->useAliasInSQL ? $this->getModelAlias() : null, $relationAlias); + if ($previousJoin = $this->getPreviousJoin()) { + $join->setPreviousJoin($previousJoin); + } + + // add the ModelJoin to the current object + if ($relationAlias) { + $this->addAlias($relationAlias, $relationMap->getRightTable()->getName()); + $this->addJoinObject($join, $relationAlias); + } else { + $this->addJoinObject($join, 'CustomerFamily'); + } + + return $this; + } + + /** + * Use the CustomerFamily relation CustomerFamily object + * + * @see useQuery() + * + * @param string $relationAlias optional alias for the relation, + * to be used as main alias in the secondary query + * @param string $joinType Accepted values are null, 'left join', 'right join', 'inner join' + * + * @return \CustomerFamily\Model\CustomerFamilyQuery A secondary query class using the current class as primary query + */ + public function useCustomerFamilyQuery($relationAlias = null, $joinType = Criteria::INNER_JOIN) + { + return $this + ->joinCustomerFamily($relationAlias, $joinType) + ->useQuery($relationAlias ? $relationAlias : 'CustomerFamily', '\CustomerFamily\Model\CustomerFamilyQuery'); + } + + /** + * Filter the query by a related \CustomerFamily\Model\Thelia\Model\Brand object + * + * @param \CustomerFamily\Model\Thelia\Model\Brand|ObjectCollection $brand The related object(s) to use as filter + * @param string $comparison Operator to use for the column comparison, defaults to Criteria::EQUAL + * + * @return ChildCustomerFamilyAvailableBrandQuery The current query, for fluid interface + */ + public function filterByBrand($brand, $comparison = null) + { + if ($brand instanceof \CustomerFamily\Model\Thelia\Model\Brand) { + return $this + ->addUsingAlias(CustomerFamilyAvailableBrandTableMap::BRAND_ID, $brand->getId(), $comparison); + } elseif ($brand instanceof ObjectCollection) { + if (null === $comparison) { + $comparison = Criteria::IN; + } + + return $this + ->addUsingAlias(CustomerFamilyAvailableBrandTableMap::BRAND_ID, $brand->toKeyValue('PrimaryKey', 'Id'), $comparison); + } else { + throw new PropelException('filterByBrand() only accepts arguments of type \CustomerFamily\Model\Thelia\Model\Brand or Collection'); + } + } + + /** + * Adds a JOIN clause to the query using the Brand relation + * + * @param string $relationAlias optional alias for the relation + * @param string $joinType Accepted values are null, 'left join', 'right join', 'inner join' + * + * @return ChildCustomerFamilyAvailableBrandQuery The current query, for fluid interface + */ + public function joinBrand($relationAlias = null, $joinType = Criteria::INNER_JOIN) + { + $tableMap = $this->getTableMap(); + $relationMap = $tableMap->getRelation('Brand'); + + // create a ModelJoin object for this join + $join = new ModelJoin(); + $join->setJoinType($joinType); + $join->setRelationMap($relationMap, $this->useAliasInSQL ? $this->getModelAlias() : null, $relationAlias); + if ($previousJoin = $this->getPreviousJoin()) { + $join->setPreviousJoin($previousJoin); + } + + // add the ModelJoin to the current object + if ($relationAlias) { + $this->addAlias($relationAlias, $relationMap->getRightTable()->getName()); + $this->addJoinObject($join, $relationAlias); + } else { + $this->addJoinObject($join, 'Brand'); + } + + return $this; + } + + /** + * Use the Brand relation Brand object + * + * @see useQuery() + * + * @param string $relationAlias optional alias for the relation, + * to be used as main alias in the secondary query + * @param string $joinType Accepted values are null, 'left join', 'right join', 'inner join' + * + * @return \CustomerFamily\Model\Thelia\Model\BrandQuery A secondary query class using the current class as primary query + */ + public function useBrandQuery($relationAlias = null, $joinType = Criteria::INNER_JOIN) + { + return $this + ->joinBrand($relationAlias, $joinType) + ->useQuery($relationAlias ? $relationAlias : 'Brand', '\CustomerFamily\Model\Thelia\Model\BrandQuery'); + } + + /** + * Exclude object from result + * + * @param ChildCustomerFamilyAvailableBrand $customerFamilyAvailableBrand Object to remove from the list of results + * + * @return ChildCustomerFamilyAvailableBrandQuery The current query, for fluid interface + */ + public function prune($customerFamilyAvailableBrand = null) + { + if ($customerFamilyAvailableBrand) { + $this->addCond('pruneCond0', $this->getAliasedColName(CustomerFamilyAvailableBrandTableMap::CUSTOMER_FAMILY_ID), $customerFamilyAvailableBrand->getCustomerFamilyId(), Criteria::NOT_EQUAL); + $this->addCond('pruneCond1', $this->getAliasedColName(CustomerFamilyAvailableBrandTableMap::BRAND_ID), $customerFamilyAvailableBrand->getBrandId(), Criteria::NOT_EQUAL); + $this->combine(array('pruneCond0', 'pruneCond1'), Criteria::LOGICAL_OR); + } + + return $this; + } + + /** + * Deletes all rows from the customer_family_available_brand table. + * + * @param ConnectionInterface $con the connection to use + * @return int The number of affected rows (if supported by underlying database driver). + */ + public function doDeleteAll(ConnectionInterface $con = null) + { + if (null === $con) { + $con = Propel::getServiceContainer()->getWriteConnection(CustomerFamilyAvailableBrandTableMap::DATABASE_NAME); + } + $affectedRows = 0; // initialize var to track total num of affected rows + try { + // use transaction because $criteria could contain info + // for more than one table or we could emulating ON DELETE CASCADE, etc. + $con->beginTransaction(); + $affectedRows += parent::doDeleteAll($con); + // Because this db requires some delete cascade/set null emulation, we have to + // clear the cached instance *after* the emulation has happened (since + // instances get re-added by the select statement contained therein). + CustomerFamilyAvailableBrandTableMap::clearInstancePool(); + CustomerFamilyAvailableBrandTableMap::clearRelatedInstancePool(); + + $con->commit(); + } catch (PropelException $e) { + $con->rollBack(); + throw $e; + } + + return $affectedRows; + } + + /** + * Performs a DELETE on the database, given a ChildCustomerFamilyAvailableBrand or Criteria object OR a primary key value. + * + * @param mixed $values Criteria or ChildCustomerFamilyAvailableBrand object or primary key or array of primary keys + * which is used to create the DELETE statement + * @param ConnectionInterface $con the connection to use + * @return int The number of affected rows (if supported by underlying database driver). This includes CASCADE-related rows + * if supported by native driver or if emulated using Propel. + * @throws PropelException Any exceptions caught during processing will be + * rethrown wrapped into a PropelException. + */ + public function delete(ConnectionInterface $con = null) + { + if (null === $con) { + $con = Propel::getServiceContainer()->getWriteConnection(CustomerFamilyAvailableBrandTableMap::DATABASE_NAME); + } + + $criteria = $this; + + // Set the correct dbName + $criteria->setDbName(CustomerFamilyAvailableBrandTableMap::DATABASE_NAME); + + $affectedRows = 0; // initialize var to track total num of affected rows + + try { + // use transaction because $criteria could contain info + // for more than one table or we could emulating ON DELETE CASCADE, etc. + $con->beginTransaction(); + + + CustomerFamilyAvailableBrandTableMap::removeInstanceFromPool($criteria); + + $affectedRows += ModelCriteria::delete($con); + CustomerFamilyAvailableBrandTableMap::clearRelatedInstancePool(); + $con->commit(); + + return $affectedRows; + } catch (PropelException $e) { + $con->rollBack(); + throw $e; + } + } + +} // CustomerFamilyAvailableBrandQuery diff --git a/local/modules/CustomerFamily/Model/Base/CustomerFamilyAvailableCategory.php b/local/modules/CustomerFamily/Model/Base/CustomerFamilyAvailableCategory.php new file mode 100644 index 00000000..d8bbaa61 --- /dev/null +++ b/local/modules/CustomerFamily/Model/Base/CustomerFamilyAvailableCategory.php @@ -0,0 +1,1268 @@ +modifiedColumns; + } + + /** + * Has specified column been modified? + * + * @param string $col column fully qualified name (TableMap::TYPE_COLNAME), e.g. Book::AUTHOR_ID + * @return boolean True if $col has been modified. + */ + public function isColumnModified($col) + { + return $this->modifiedColumns && isset($this->modifiedColumns[$col]); + } + + /** + * Get the columns that have been modified in this object. + * @return array A unique list of the modified column names for this object. + */ + public function getModifiedColumns() + { + return $this->modifiedColumns ? array_keys($this->modifiedColumns) : []; + } + + /** + * Returns whether the object has ever been saved. This will + * be false, if the object was retrieved from storage or was created + * and then saved. + * + * @return boolean true, if the object has never been persisted. + */ + public function isNew() + { + return $this->new; + } + + /** + * Setter for the isNew attribute. This method will be called + * by Propel-generated children and objects. + * + * @param boolean $b the state of the object. + */ + public function setNew($b) + { + $this->new = (Boolean) $b; + } + + /** + * Whether this object has been deleted. + * @return boolean The deleted state of this object. + */ + public function isDeleted() + { + return $this->deleted; + } + + /** + * Specify whether this object has been deleted. + * @param boolean $b The deleted state of this object. + * @return void + */ + public function setDeleted($b) + { + $this->deleted = (Boolean) $b; + } + + /** + * Sets the modified state for the object to be false. + * @param string $col If supplied, only the specified column is reset. + * @return void + */ + public function resetModified($col = null) + { + if (null !== $col) { + if (isset($this->modifiedColumns[$col])) { + unset($this->modifiedColumns[$col]); + } + } else { + $this->modifiedColumns = array(); + } + } + + /** + * Compares this with another CustomerFamilyAvailableCategory instance. If + * obj is an instance of CustomerFamilyAvailableCategory, delegates to + * equals(CustomerFamilyAvailableCategory). Otherwise, returns false. + * + * @param mixed $obj The object to compare to. + * @return boolean Whether equal to the object specified. + */ + public function equals($obj) + { + $thisclazz = get_class($this); + if (!is_object($obj) || !($obj instanceof $thisclazz)) { + return false; + } + + if ($this === $obj) { + return true; + } + + if (null === $this->getPrimaryKey() + || null === $obj->getPrimaryKey()) { + return false; + } + + return $this->getPrimaryKey() === $obj->getPrimaryKey(); + } + + /** + * If the primary key is not null, return the hashcode of the + * primary key. Otherwise, return the hash code of the object. + * + * @return int Hashcode + */ + public function hashCode() + { + if (null !== $this->getPrimaryKey()) { + return crc32(serialize($this->getPrimaryKey())); + } + + return crc32(serialize(clone $this)); + } + + /** + * Get the associative array of the virtual columns in this object + * + * @return array + */ + public function getVirtualColumns() + { + return $this->virtualColumns; + } + + /** + * Checks the existence of a virtual column in this object + * + * @param string $name The virtual column name + * @return boolean + */ + public function hasVirtualColumn($name) + { + return array_key_exists($name, $this->virtualColumns); + } + + /** + * Get the value of a virtual column in this object + * + * @param string $name The virtual column name + * @return mixed + * + * @throws PropelException + */ + public function getVirtualColumn($name) + { + if (!$this->hasVirtualColumn($name)) { + throw new PropelException(sprintf('Cannot get value of inexistent virtual column %s.', $name)); + } + + return $this->virtualColumns[$name]; + } + + /** + * Set the value of a virtual column in this object + * + * @param string $name The virtual column name + * @param mixed $value The value to give to the virtual column + * + * @return CustomerFamilyAvailableCategory The current object, for fluid interface + */ + public function setVirtualColumn($name, $value) + { + $this->virtualColumns[$name] = $value; + + return $this; + } + + /** + * Logs a message using Propel::log(). + * + * @param string $msg + * @param int $priority One of the Propel::LOG_* logging levels + * @return boolean + */ + protected function log($msg, $priority = Propel::LOG_INFO) + { + return Propel::log(get_class($this) . ': ' . $msg, $priority); + } + + /** + * Populate the current object from a string, using a given parser format + * + * $book = new Book(); + * $book->importFrom('JSON', '{"Id":9012,"Title":"Don Juan","ISBN":"0140422161","Price":12.99,"PublisherId":1234,"AuthorId":5678}'); + * + * + * @param mixed $parser A AbstractParser instance, + * or a format name ('XML', 'YAML', 'JSON', 'CSV') + * @param string $data The source data to import from + * + * @return CustomerFamilyAvailableCategory The current object, for fluid interface + */ + public function importFrom($parser, $data) + { + if (!$parser instanceof AbstractParser) { + $parser = AbstractParser::getParser($parser); + } + + $this->fromArray($parser->toArray($data), TableMap::TYPE_PHPNAME); + + return $this; + } + + /** + * Export the current object properties to a string, using a given parser format + * + * $book = BookQuery::create()->findPk(9012); + * echo $book->exportTo('JSON'); + * => {"Id":9012,"Title":"Don Juan","ISBN":"0140422161","Price":12.99,"PublisherId":1234,"AuthorId":5678}'); + * + * + * @param mixed $parser A AbstractParser instance, or a format name ('XML', 'YAML', 'JSON', 'CSV') + * @param boolean $includeLazyLoadColumns (optional) Whether to include lazy load(ed) columns. Defaults to TRUE. + * @return string The exported data + */ + public function exportTo($parser, $includeLazyLoadColumns = true) + { + if (!$parser instanceof AbstractParser) { + $parser = AbstractParser::getParser($parser); + } + + return $parser->fromArray($this->toArray(TableMap::TYPE_PHPNAME, $includeLazyLoadColumns, array(), true)); + } + + /** + * Clean up internal collections prior to serializing + * Avoids recursive loops that turn into segmentation faults when serializing + */ + public function __sleep() + { + $this->clearAllReferences(); + + return array_keys(get_object_vars($this)); + } + + /** + * Get the [customer_family_id] column value. + * + * @return int + */ + public function getCustomerFamilyId() + { + + return $this->customer_family_id; + } + + /** + * Get the [category_id] column value. + * + * @return int + */ + public function getCategoryId() + { + + return $this->category_id; + } + + /** + * Set the value of [customer_family_id] column. + * + * @param int $v new value + * @return \CustomerFamily\Model\CustomerFamilyAvailableCategory The current object (for fluent API support) + */ + public function setCustomerFamilyId($v) + { + if ($v !== null) { + $v = (int) $v; + } + + if ($this->customer_family_id !== $v) { + $this->customer_family_id = $v; + $this->modifiedColumns[CustomerFamilyAvailableCategoryTableMap::CUSTOMER_FAMILY_ID] = true; + } + + if ($this->aCustomerFamily !== null && $this->aCustomerFamily->getId() !== $v) { + $this->aCustomerFamily = null; + } + + + return $this; + } // setCustomerFamilyId() + + /** + * Set the value of [category_id] column. + * + * @param int $v new value + * @return \CustomerFamily\Model\CustomerFamilyAvailableCategory The current object (for fluent API support) + */ + public function setCategoryId($v) + { + if ($v !== null) { + $v = (int) $v; + } + + if ($this->category_id !== $v) { + $this->category_id = $v; + $this->modifiedColumns[CustomerFamilyAvailableCategoryTableMap::CATEGORY_ID] = true; + } + + if ($this->aCategory !== null && $this->aCategory->getId() !== $v) { + $this->aCategory = null; + } + + + return $this; + } // setCategoryId() + + /** + * Indicates whether the columns in this object are only set to default values. + * + * This method can be used in conjunction with isModified() to indicate whether an object is both + * modified _and_ has some values set which are non-default. + * + * @return boolean Whether the columns in this object are only been set with default values. + */ + public function hasOnlyDefaultValues() + { + // otherwise, everything was equal, so return TRUE + return true; + } // hasOnlyDefaultValues() + + /** + * Hydrates (populates) the object variables with values from the database resultset. + * + * An offset (0-based "start column") is specified so that objects can be hydrated + * with a subset of the columns in the resultset rows. This is needed, for example, + * for results of JOIN queries where the resultset row includes columns from two or + * more tables. + * + * @param array $row The row returned by DataFetcher->fetch(). + * @param int $startcol 0-based offset column which indicates which restultset column to start with. + * @param boolean $rehydrate Whether this object is being re-hydrated from the database. + * @param string $indexType The index type of $row. Mostly DataFetcher->getIndexType(). + One of the class type constants TableMap::TYPE_PHPNAME, TableMap::TYPE_STUDLYPHPNAME + * TableMap::TYPE_COLNAME, TableMap::TYPE_FIELDNAME, TableMap::TYPE_NUM. + * + * @return int next starting column + * @throws PropelException - Any caught Exception will be rewrapped as a PropelException. + */ + public function hydrate($row, $startcol = 0, $rehydrate = false, $indexType = TableMap::TYPE_NUM) + { + try { + + + $col = $row[TableMap::TYPE_NUM == $indexType ? 0 + $startcol : CustomerFamilyAvailableCategoryTableMap::translateFieldName('CustomerFamilyId', TableMap::TYPE_PHPNAME, $indexType)]; + $this->customer_family_id = (null !== $col) ? (int) $col : null; + + $col = $row[TableMap::TYPE_NUM == $indexType ? 1 + $startcol : CustomerFamilyAvailableCategoryTableMap::translateFieldName('CategoryId', TableMap::TYPE_PHPNAME, $indexType)]; + $this->category_id = (null !== $col) ? (int) $col : null; + $this->resetModified(); + + $this->setNew(false); + + if ($rehydrate) { + $this->ensureConsistency(); + } + + return $startcol + 2; // 2 = CustomerFamilyAvailableCategoryTableMap::NUM_HYDRATE_COLUMNS. + + } catch (Exception $e) { + throw new PropelException("Error populating \CustomerFamily\Model\CustomerFamilyAvailableCategory object", 0, $e); + } + } + + /** + * Checks and repairs the internal consistency of the object. + * + * This method is executed after an already-instantiated object is re-hydrated + * from the database. It exists to check any foreign keys to make sure that + * the objects related to the current object are correct based on foreign key. + * + * You can override this method in the stub class, but you should always invoke + * the base method from the overridden method (i.e. parent::ensureConsistency()), + * in case your model changes. + * + * @throws PropelException + */ + public function ensureConsistency() + { + if ($this->aCustomerFamily !== null && $this->customer_family_id !== $this->aCustomerFamily->getId()) { + $this->aCustomerFamily = null; + } + if ($this->aCategory !== null && $this->category_id !== $this->aCategory->getId()) { + $this->aCategory = null; + } + } // ensureConsistency + + /** + * Reloads this object from datastore based on primary key and (optionally) resets all associated objects. + * + * This will only work if the object has been saved and has a valid primary key set. + * + * @param boolean $deep (optional) Whether to also de-associated any related objects. + * @param ConnectionInterface $con (optional) The ConnectionInterface connection to use. + * @return void + * @throws PropelException - if this object is deleted, unsaved or doesn't have pk match in db + */ + public function reload($deep = false, ConnectionInterface $con = null) + { + if ($this->isDeleted()) { + throw new PropelException("Cannot reload a deleted object."); + } + + if ($this->isNew()) { + throw new PropelException("Cannot reload an unsaved object."); + } + + if ($con === null) { + $con = Propel::getServiceContainer()->getReadConnection(CustomerFamilyAvailableCategoryTableMap::DATABASE_NAME); + } + + // We don't need to alter the object instance pool; we're just modifying this instance + // already in the pool. + + $dataFetcher = ChildCustomerFamilyAvailableCategoryQuery::create(null, $this->buildPkeyCriteria())->setFormatter(ModelCriteria::FORMAT_STATEMENT)->find($con); + $row = $dataFetcher->fetch(); + $dataFetcher->close(); + if (!$row) { + throw new PropelException('Cannot find matching row in the database to reload object values.'); + } + $this->hydrate($row, 0, true, $dataFetcher->getIndexType()); // rehydrate + + if ($deep) { // also de-associate any related objects? + + $this->aCustomerFamily = null; + $this->aCategory = null; + } // if (deep) + } + + /** + * Removes this object from datastore and sets delete attribute. + * + * @param ConnectionInterface $con + * @return void + * @throws PropelException + * @see CustomerFamilyAvailableCategory::setDeleted() + * @see CustomerFamilyAvailableCategory::isDeleted() + */ + public function delete(ConnectionInterface $con = null) + { + if ($this->isDeleted()) { + throw new PropelException("This object has already been deleted."); + } + + if ($con === null) { + $con = Propel::getServiceContainer()->getWriteConnection(CustomerFamilyAvailableCategoryTableMap::DATABASE_NAME); + } + + $con->beginTransaction(); + try { + $deleteQuery = ChildCustomerFamilyAvailableCategoryQuery::create() + ->filterByPrimaryKey($this->getPrimaryKey()); + $ret = $this->preDelete($con); + if ($ret) { + $deleteQuery->delete($con); + $this->postDelete($con); + $con->commit(); + $this->setDeleted(true); + } else { + $con->commit(); + } + } catch (Exception $e) { + $con->rollBack(); + throw $e; + } + } + + /** + * Persists this object to the database. + * + * If the object is new, it inserts it; otherwise an update is performed. + * All modified related objects will also be persisted in the doSave() + * method. This method wraps all precipitate database operations in a + * single transaction. + * + * @param ConnectionInterface $con + * @return int The number of rows affected by this insert/update and any referring fk objects' save() operations. + * @throws PropelException + * @see doSave() + */ + public function save(ConnectionInterface $con = null) + { + if ($this->isDeleted()) { + throw new PropelException("You cannot save an object that has been deleted."); + } + + if ($con === null) { + $con = Propel::getServiceContainer()->getWriteConnection(CustomerFamilyAvailableCategoryTableMap::DATABASE_NAME); + } + + $con->beginTransaction(); + $isInsert = $this->isNew(); + try { + $ret = $this->preSave($con); + if ($isInsert) { + $ret = $ret && $this->preInsert($con); + } else { + $ret = $ret && $this->preUpdate($con); + } + if ($ret) { + $affectedRows = $this->doSave($con); + if ($isInsert) { + $this->postInsert($con); + } else { + $this->postUpdate($con); + } + $this->postSave($con); + CustomerFamilyAvailableCategoryTableMap::addInstanceToPool($this); + } else { + $affectedRows = 0; + } + $con->commit(); + + return $affectedRows; + } catch (Exception $e) { + $con->rollBack(); + throw $e; + } + } + + /** + * Performs the work of inserting or updating the row in the database. + * + * If the object is new, it inserts it; otherwise an update is performed. + * All related objects are also updated in this method. + * + * @param ConnectionInterface $con + * @return int The number of rows affected by this insert/update and any referring fk objects' save() operations. + * @throws PropelException + * @see save() + */ + protected function doSave(ConnectionInterface $con) + { + $affectedRows = 0; // initialize var to track total num of affected rows + if (!$this->alreadyInSave) { + $this->alreadyInSave = true; + + // We call the save method on the following object(s) if they + // were passed to this object by their corresponding set + // method. This object relates to these object(s) by a + // foreign key reference. + + if ($this->aCustomerFamily !== null) { + if ($this->aCustomerFamily->isModified() || $this->aCustomerFamily->isNew()) { + $affectedRows += $this->aCustomerFamily->save($con); + } + $this->setCustomerFamily($this->aCustomerFamily); + } + + if ($this->aCategory !== null) { + if ($this->aCategory->isModified() || $this->aCategory->isNew()) { + $affectedRows += $this->aCategory->save($con); + } + $this->setCategory($this->aCategory); + } + + if ($this->isNew() || $this->isModified()) { + // persist changes + if ($this->isNew()) { + $this->doInsert($con); + } else { + $this->doUpdate($con); + } + $affectedRows += 1; + $this->resetModified(); + } + + $this->alreadyInSave = false; + + } + + return $affectedRows; + } // doSave() + + /** + * Insert the row in the database. + * + * @param ConnectionInterface $con + * + * @throws PropelException + * @see doSave() + */ + protected function doInsert(ConnectionInterface $con) + { + $modifiedColumns = array(); + $index = 0; + + + // check the columns in natural order for more readable SQL queries + if ($this->isColumnModified(CustomerFamilyAvailableCategoryTableMap::CUSTOMER_FAMILY_ID)) { + $modifiedColumns[':p' . $index++] = 'CUSTOMER_FAMILY_ID'; + } + if ($this->isColumnModified(CustomerFamilyAvailableCategoryTableMap::CATEGORY_ID)) { + $modifiedColumns[':p' . $index++] = 'CATEGORY_ID'; + } + + $sql = sprintf( + 'INSERT INTO customer_family_available_category (%s) VALUES (%s)', + implode(', ', $modifiedColumns), + implode(', ', array_keys($modifiedColumns)) + ); + + try { + $stmt = $con->prepare($sql); + foreach ($modifiedColumns as $identifier => $columnName) { + switch ($columnName) { + case 'CUSTOMER_FAMILY_ID': + $stmt->bindValue($identifier, $this->customer_family_id, PDO::PARAM_INT); + break; + case 'CATEGORY_ID': + $stmt->bindValue($identifier, $this->category_id, PDO::PARAM_INT); + break; + } + } + $stmt->execute(); + } catch (Exception $e) { + Propel::log($e->getMessage(), Propel::LOG_ERR); + throw new PropelException(sprintf('Unable to execute INSERT statement [%s]', $sql), 0, $e); + } + + $this->setNew(false); + } + + /** + * Update the row in the database. + * + * @param ConnectionInterface $con + * + * @return Integer Number of updated rows + * @see doSave() + */ + protected function doUpdate(ConnectionInterface $con) + { + $selectCriteria = $this->buildPkeyCriteria(); + $valuesCriteria = $this->buildCriteria(); + + return $selectCriteria->doUpdate($valuesCriteria, $con); + } + + /** + * Retrieves a field from the object by name passed in as a string. + * + * @param string $name name + * @param string $type The type of fieldname the $name is of: + * one of the class type constants TableMap::TYPE_PHPNAME, TableMap::TYPE_STUDLYPHPNAME + * TableMap::TYPE_COLNAME, TableMap::TYPE_FIELDNAME, TableMap::TYPE_NUM. + * Defaults to TableMap::TYPE_PHPNAME. + * @return mixed Value of field. + */ + public function getByName($name, $type = TableMap::TYPE_PHPNAME) + { + $pos = CustomerFamilyAvailableCategoryTableMap::translateFieldName($name, $type, TableMap::TYPE_NUM); + $field = $this->getByPosition($pos); + + return $field; + } + + /** + * Retrieves a field from the object by Position as specified in the xml schema. + * Zero-based. + * + * @param int $pos position in xml schema + * @return mixed Value of field at $pos + */ + public function getByPosition($pos) + { + switch ($pos) { + case 0: + return $this->getCustomerFamilyId(); + break; + case 1: + return $this->getCategoryId(); + break; + default: + return null; + break; + } // switch() + } + + /** + * Exports the object as an array. + * + * You can specify the key type of the array by passing one of the class + * type constants. + * + * @param string $keyType (optional) One of the class type constants TableMap::TYPE_PHPNAME, TableMap::TYPE_STUDLYPHPNAME, + * TableMap::TYPE_COLNAME, TableMap::TYPE_FIELDNAME, TableMap::TYPE_NUM. + * Defaults to TableMap::TYPE_PHPNAME. + * @param boolean $includeLazyLoadColumns (optional) Whether to include lazy loaded columns. Defaults to TRUE. + * @param array $alreadyDumpedObjects List of objects to skip to avoid recursion + * @param boolean $includeForeignObjects (optional) Whether to include hydrated related objects. Default to FALSE. + * + * @return array an associative array containing the field names (as keys) and field values + */ + public function toArray($keyType = TableMap::TYPE_PHPNAME, $includeLazyLoadColumns = true, $alreadyDumpedObjects = array(), $includeForeignObjects = false) + { + if (isset($alreadyDumpedObjects['CustomerFamilyAvailableCategory'][serialize($this->getPrimaryKey())])) { + return '*RECURSION*'; + } + $alreadyDumpedObjects['CustomerFamilyAvailableCategory'][serialize($this->getPrimaryKey())] = true; + $keys = CustomerFamilyAvailableCategoryTableMap::getFieldNames($keyType); + $result = array( + $keys[0] => $this->getCustomerFamilyId(), + $keys[1] => $this->getCategoryId(), + ); + $virtualColumns = $this->virtualColumns; + foreach ($virtualColumns as $key => $virtualColumn) { + $result[$key] = $virtualColumn; + } + + if ($includeForeignObjects) { + if (null !== $this->aCustomerFamily) { + $result['CustomerFamily'] = $this->aCustomerFamily->toArray($keyType, $includeLazyLoadColumns, $alreadyDumpedObjects, true); + } + if (null !== $this->aCategory) { + $result['Category'] = $this->aCategory->toArray($keyType, $includeLazyLoadColumns, $alreadyDumpedObjects, true); + } + } + + return $result; + } + + /** + * Sets a field from the object by name passed in as a string. + * + * @param string $name + * @param mixed $value field value + * @param string $type The type of fieldname the $name is of: + * one of the class type constants TableMap::TYPE_PHPNAME, TableMap::TYPE_STUDLYPHPNAME + * TableMap::TYPE_COLNAME, TableMap::TYPE_FIELDNAME, TableMap::TYPE_NUM. + * Defaults to TableMap::TYPE_PHPNAME. + * @return void + */ + public function setByName($name, $value, $type = TableMap::TYPE_PHPNAME) + { + $pos = CustomerFamilyAvailableCategoryTableMap::translateFieldName($name, $type, TableMap::TYPE_NUM); + + return $this->setByPosition($pos, $value); + } + + /** + * Sets a field from the object by Position as specified in the xml schema. + * Zero-based. + * + * @param int $pos position in xml schema + * @param mixed $value field value + * @return void + */ + public function setByPosition($pos, $value) + { + switch ($pos) { + case 0: + $this->setCustomerFamilyId($value); + break; + case 1: + $this->setCategoryId($value); + break; + } // switch() + } + + /** + * Populates the object using an array. + * + * This is particularly useful when populating an object from one of the + * request arrays (e.g. $_POST). This method goes through the column + * names, checking to see whether a matching key exists in populated + * array. If so the setByName() method is called for that column. + * + * You can specify the key type of the array by additionally passing one + * of the class type constants TableMap::TYPE_PHPNAME, TableMap::TYPE_STUDLYPHPNAME, + * TableMap::TYPE_COLNAME, TableMap::TYPE_FIELDNAME, TableMap::TYPE_NUM. + * The default key type is the column's TableMap::TYPE_PHPNAME. + * + * @param array $arr An array to populate the object from. + * @param string $keyType The type of keys the array uses. + * @return void + */ + public function fromArray($arr, $keyType = TableMap::TYPE_PHPNAME) + { + $keys = CustomerFamilyAvailableCategoryTableMap::getFieldNames($keyType); + + if (array_key_exists($keys[0], $arr)) $this->setCustomerFamilyId($arr[$keys[0]]); + if (array_key_exists($keys[1], $arr)) $this->setCategoryId($arr[$keys[1]]); + } + + /** + * Build a Criteria object containing the values of all modified columns in this object. + * + * @return Criteria The Criteria object containing all modified values. + */ + public function buildCriteria() + { + $criteria = new Criteria(CustomerFamilyAvailableCategoryTableMap::DATABASE_NAME); + + if ($this->isColumnModified(CustomerFamilyAvailableCategoryTableMap::CUSTOMER_FAMILY_ID)) $criteria->add(CustomerFamilyAvailableCategoryTableMap::CUSTOMER_FAMILY_ID, $this->customer_family_id); + if ($this->isColumnModified(CustomerFamilyAvailableCategoryTableMap::CATEGORY_ID)) $criteria->add(CustomerFamilyAvailableCategoryTableMap::CATEGORY_ID, $this->category_id); + + return $criteria; + } + + /** + * Builds a Criteria object containing the primary key for this object. + * + * Unlike buildCriteria() this method includes the primary key values regardless + * of whether or not they have been modified. + * + * @return Criteria The Criteria object containing value(s) for primary key(s). + */ + public function buildPkeyCriteria() + { + $criteria = new Criteria(CustomerFamilyAvailableCategoryTableMap::DATABASE_NAME); + $criteria->add(CustomerFamilyAvailableCategoryTableMap::CUSTOMER_FAMILY_ID, $this->customer_family_id); + $criteria->add(CustomerFamilyAvailableCategoryTableMap::CATEGORY_ID, $this->category_id); + + return $criteria; + } + + /** + * Returns the composite primary key for this object. + * The array elements will be in same order as specified in XML. + * @return array + */ + public function getPrimaryKey() + { + $pks = array(); + $pks[0] = $this->getCustomerFamilyId(); + $pks[1] = $this->getCategoryId(); + + return $pks; + } + + /** + * Set the [composite] primary key. + * + * @param array $keys The elements of the composite key (order must match the order in XML file). + * @return void + */ + public function setPrimaryKey($keys) + { + $this->setCustomerFamilyId($keys[0]); + $this->setCategoryId($keys[1]); + } + + /** + * Returns true if the primary key for this object is null. + * @return boolean + */ + public function isPrimaryKeyNull() + { + + return (null === $this->getCustomerFamilyId()) && (null === $this->getCategoryId()); + } + + /** + * Sets contents of passed object to values from current object. + * + * If desired, this method can also make copies of all associated (fkey referrers) + * objects. + * + * @param object $copyObj An object of \CustomerFamily\Model\CustomerFamilyAvailableCategory (or compatible) type. + * @param boolean $deepCopy Whether to also copy all rows that refer (by fkey) to the current row. + * @param boolean $makeNew Whether to reset autoincrement PKs and make the object new. + * @throws PropelException + */ + public function copyInto($copyObj, $deepCopy = false, $makeNew = true) + { + $copyObj->setCustomerFamilyId($this->getCustomerFamilyId()); + $copyObj->setCategoryId($this->getCategoryId()); + if ($makeNew) { + $copyObj->setNew(true); + } + } + + /** + * Makes a copy of this object that will be inserted as a new row in table when saved. + * It creates a new object filling in the simple attributes, but skipping any primary + * keys that are defined for the table. + * + * If desired, this method can also make copies of all associated (fkey referrers) + * objects. + * + * @param boolean $deepCopy Whether to also copy all rows that refer (by fkey) to the current row. + * @return \CustomerFamily\Model\CustomerFamilyAvailableCategory Clone of current object. + * @throws PropelException + */ + public function copy($deepCopy = false) + { + // we use get_class(), because this might be a subclass + $clazz = get_class($this); + $copyObj = new $clazz(); + $this->copyInto($copyObj, $deepCopy); + + return $copyObj; + } + + /** + * Declares an association between this object and a ChildCustomerFamily object. + * + * @param ChildCustomerFamily $v + * @return \CustomerFamily\Model\CustomerFamilyAvailableCategory The current object (for fluent API support) + * @throws PropelException + */ + public function setCustomerFamily(ChildCustomerFamily $v = null) + { + if ($v === null) { + $this->setCustomerFamilyId(NULL); + } else { + $this->setCustomerFamilyId($v->getId()); + } + + $this->aCustomerFamily = $v; + + // Add binding for other direction of this n:n relationship. + // If this object has already been added to the ChildCustomerFamily object, it will not be re-added. + if ($v !== null) { + $v->addCustomerFamilyAvailableCategory($this); + } + + + return $this; + } + + + /** + * Get the associated ChildCustomerFamily object + * + * @param ConnectionInterface $con Optional Connection object. + * @return ChildCustomerFamily The associated ChildCustomerFamily object. + * @throws PropelException + */ + public function getCustomerFamily(ConnectionInterface $con = null) + { + if ($this->aCustomerFamily === null && ($this->customer_family_id !== null)) { + $this->aCustomerFamily = ChildCustomerFamilyQuery::create()->findPk($this->customer_family_id, $con); + /* The following can be used additionally to + guarantee the related object contains a reference + to this object. This level of coupling may, however, be + undesirable since it could result in an only partially populated collection + in the referenced object. + $this->aCustomerFamily->addCustomerFamilyAvailableCategories($this); + */ + } + + return $this->aCustomerFamily; + } + + /** + * Declares an association between this object and a ChildCategory object. + * + * @param ChildCategory $v + * @return \CustomerFamily\Model\CustomerFamilyAvailableCategory The current object (for fluent API support) + * @throws PropelException + */ + public function setCategory(ChildCategory $v = null) + { + if ($v === null) { + $this->setCategoryId(NULL); + } else { + $this->setCategoryId($v->getId()); + } + + $this->aCategory = $v; + + // Add binding for other direction of this n:n relationship. + // If this object has already been added to the ChildCategory object, it will not be re-added. + if ($v !== null) { + $v->addCustomerFamilyAvailableCategory($this); + } + + + return $this; + } + + + /** + * Get the associated ChildCategory object + * + * @param ConnectionInterface $con Optional Connection object. + * @return ChildCategory The associated ChildCategory object. + * @throws PropelException + */ + public function getCategory(ConnectionInterface $con = null) + { + if ($this->aCategory === null && ($this->category_id !== null)) { + $this->aCategory = CategoryQuery::create()->findPk($this->category_id, $con); + /* The following can be used additionally to + guarantee the related object contains a reference + to this object. This level of coupling may, however, be + undesirable since it could result in an only partially populated collection + in the referenced object. + $this->aCategory->addCustomerFamilyAvailableCategories($this); + */ + } + + return $this->aCategory; + } + + /** + * Clears the current object and sets all attributes to their default values + */ + public function clear() + { + $this->customer_family_id = null; + $this->category_id = null; + $this->alreadyInSave = false; + $this->clearAllReferences(); + $this->resetModified(); + $this->setNew(true); + $this->setDeleted(false); + } + + /** + * Resets all references to other model objects or collections of model objects. + * + * This method is a user-space workaround for PHP's inability to garbage collect + * objects with circular references (even in PHP 5.3). This is currently necessary + * when using Propel in certain daemon or large-volume/high-memory operations. + * + * @param boolean $deep Whether to also clear the references on all referrer objects. + */ + public function clearAllReferences($deep = false) + { + if ($deep) { + } // if ($deep) + + $this->aCustomerFamily = null; + $this->aCategory = null; + } + + /** + * Return the string representation of this object + * + * @return string + */ + public function __toString() + { + return (string) $this->exportTo(CustomerFamilyAvailableCategoryTableMap::DEFAULT_STRING_FORMAT); + } + + /** + * Code to be run before persisting the object + * @param ConnectionInterface $con + * @return boolean + */ + public function preSave(ConnectionInterface $con = null) + { + return true; + } + + /** + * Code to be run after persisting the object + * @param ConnectionInterface $con + */ + public function postSave(ConnectionInterface $con = null) + { + + } + + /** + * Code to be run before inserting to database + * @param ConnectionInterface $con + * @return boolean + */ + public function preInsert(ConnectionInterface $con = null) + { + return true; + } + + /** + * Code to be run after inserting to database + * @param ConnectionInterface $con + */ + public function postInsert(ConnectionInterface $con = null) + { + + } + + /** + * Code to be run before updating the object in database + * @param ConnectionInterface $con + * @return boolean + */ + public function preUpdate(ConnectionInterface $con = null) + { + return true; + } + + /** + * Code to be run after updating the object in database + * @param ConnectionInterface $con + */ + public function postUpdate(ConnectionInterface $con = null) + { + + } + + /** + * Code to be run before deleting the object in database + * @param ConnectionInterface $con + * @return boolean + */ + public function preDelete(ConnectionInterface $con = null) + { + return true; + } + + /** + * Code to be run after deleting the object in database + * @param ConnectionInterface $con + */ + public function postDelete(ConnectionInterface $con = null) + { + + } + + + /** + * Derived method to catches calls to undefined methods. + * + * Provides magic import/export method support (fromXML()/toXML(), fromYAML()/toYAML(), etc.). + * Allows to define default __call() behavior if you overwrite __call() + * + * @param string $name + * @param mixed $params + * + * @return array|string + */ + public function __call($name, $params) + { + if (0 === strpos($name, 'get')) { + $virtualColumn = substr($name, 3); + if ($this->hasVirtualColumn($virtualColumn)) { + return $this->getVirtualColumn($virtualColumn); + } + + $virtualColumn = lcfirst($virtualColumn); + if ($this->hasVirtualColumn($virtualColumn)) { + return $this->getVirtualColumn($virtualColumn); + } + } + + if (0 === strpos($name, 'from')) { + $format = substr($name, 4); + + return $this->importFrom($format, reset($params)); + } + + if (0 === strpos($name, 'to')) { + $format = substr($name, 2); + $includeLazyLoadColumns = isset($params[0]) ? $params[0] : true; + + return $this->exportTo($format, $includeLazyLoadColumns); + } + + throw new BadMethodCallException(sprintf('Call to undefined method: %s.', $name)); + } + +} diff --git a/local/modules/CustomerFamily/Model/Base/CustomerFamilyAvailableCategoryQuery.php b/local/modules/CustomerFamily/Model/Base/CustomerFamilyAvailableCategoryQuery.php new file mode 100644 index 00000000..dae59ff6 --- /dev/null +++ b/local/modules/CustomerFamily/Model/Base/CustomerFamilyAvailableCategoryQuery.php @@ -0,0 +1,569 @@ +setModelAlias($modelAlias); + } + if ($criteria instanceof Criteria) { + $query->mergeWith($criteria); + } + + return $query; + } + + /** + * Find object by primary key. + * Propel uses the instance pool to skip the database if the object exists. + * Go fast if the query is untouched. + * + * + * $obj = $c->findPk(array(12, 34), $con); + * + * + * @param array[$customer_family_id, $category_id] $key Primary key to use for the query + * @param ConnectionInterface $con an optional connection object + * + * @return ChildCustomerFamilyAvailableCategory|array|mixed the result, formatted by the current formatter + */ + public function findPk($key, $con = null) + { + if ($key === null) { + return null; + } + if ((null !== ($obj = CustomerFamilyAvailableCategoryTableMap::getInstanceFromPool(serialize(array((string) $key[0], (string) $key[1]))))) && !$this->formatter) { + // the object is already in the instance pool + return $obj; + } + if ($con === null) { + $con = Propel::getServiceContainer()->getReadConnection(CustomerFamilyAvailableCategoryTableMap::DATABASE_NAME); + } + $this->basePreSelect($con); + if ($this->formatter || $this->modelAlias || $this->with || $this->select + || $this->selectColumns || $this->asColumns || $this->selectModifiers + || $this->map || $this->having || $this->joins) { + return $this->findPkComplex($key, $con); + } else { + return $this->findPkSimple($key, $con); + } + } + + /** + * Find object by primary key using raw SQL to go fast. + * Bypass doSelect() and the object formatter by using generated code. + * + * @param mixed $key Primary key to use for the query + * @param ConnectionInterface $con A connection object + * + * @return ChildCustomerFamilyAvailableCategory A model object, or null if the key is not found + */ + protected function findPkSimple($key, $con) + { + $sql = 'SELECT CUSTOMER_FAMILY_ID, CATEGORY_ID FROM customer_family_available_category WHERE CUSTOMER_FAMILY_ID = :p0 AND CATEGORY_ID = :p1'; + try { + $stmt = $con->prepare($sql); + $stmt->bindValue(':p0', $key[0], PDO::PARAM_INT); + $stmt->bindValue(':p1', $key[1], PDO::PARAM_INT); + $stmt->execute(); + } catch (Exception $e) { + Propel::log($e->getMessage(), Propel::LOG_ERR); + throw new PropelException(sprintf('Unable to execute SELECT statement [%s]', $sql), 0, $e); + } + $obj = null; + if ($row = $stmt->fetch(\PDO::FETCH_NUM)) { + $obj = new ChildCustomerFamilyAvailableCategory(); + $obj->hydrate($row); + CustomerFamilyAvailableCategoryTableMap::addInstanceToPool($obj, serialize(array((string) $key[0], (string) $key[1]))); + } + $stmt->closeCursor(); + + return $obj; + } + + /** + * Find object by primary key. + * + * @param mixed $key Primary key to use for the query + * @param ConnectionInterface $con A connection object + * + * @return ChildCustomerFamilyAvailableCategory|array|mixed the result, formatted by the current formatter + */ + protected function findPkComplex($key, $con) + { + // As the query uses a PK condition, no limit(1) is necessary. + $criteria = $this->isKeepQuery() ? clone $this : $this; + $dataFetcher = $criteria + ->filterByPrimaryKey($key) + ->doSelect($con); + + return $criteria->getFormatter()->init($criteria)->formatOne($dataFetcher); + } + + /** + * Find objects by primary key + * + * $objs = $c->findPks(array(array(12, 56), array(832, 123), array(123, 456)), $con); + * + * @param array $keys Primary keys to use for the query + * @param ConnectionInterface $con an optional connection object + * + * @return ObjectCollection|array|mixed the list of results, formatted by the current formatter + */ + public function findPks($keys, $con = null) + { + if (null === $con) { + $con = Propel::getServiceContainer()->getReadConnection($this->getDbName()); + } + $this->basePreSelect($con); + $criteria = $this->isKeepQuery() ? clone $this : $this; + $dataFetcher = $criteria + ->filterByPrimaryKeys($keys) + ->doSelect($con); + + return $criteria->getFormatter()->init($criteria)->format($dataFetcher); + } + + /** + * Filter the query by primary key + * + * @param mixed $key Primary key to use for the query + * + * @return ChildCustomerFamilyAvailableCategoryQuery The current query, for fluid interface + */ + public function filterByPrimaryKey($key) + { + $this->addUsingAlias(CustomerFamilyAvailableCategoryTableMap::CUSTOMER_FAMILY_ID, $key[0], Criteria::EQUAL); + $this->addUsingAlias(CustomerFamilyAvailableCategoryTableMap::CATEGORY_ID, $key[1], Criteria::EQUAL); + + return $this; + } + + /** + * Filter the query by a list of primary keys + * + * @param array $keys The list of primary key to use for the query + * + * @return ChildCustomerFamilyAvailableCategoryQuery The current query, for fluid interface + */ + public function filterByPrimaryKeys($keys) + { + if (empty($keys)) { + return $this->add(null, '1<>1', Criteria::CUSTOM); + } + foreach ($keys as $key) { + $cton0 = $this->getNewCriterion(CustomerFamilyAvailableCategoryTableMap::CUSTOMER_FAMILY_ID, $key[0], Criteria::EQUAL); + $cton1 = $this->getNewCriterion(CustomerFamilyAvailableCategoryTableMap::CATEGORY_ID, $key[1], Criteria::EQUAL); + $cton0->addAnd($cton1); + $this->addOr($cton0); + } + + return $this; + } + + /** + * Filter the query on the customer_family_id column + * + * Example usage: + * + * $query->filterByCustomerFamilyId(1234); // WHERE customer_family_id = 1234 + * $query->filterByCustomerFamilyId(array(12, 34)); // WHERE customer_family_id IN (12, 34) + * $query->filterByCustomerFamilyId(array('min' => 12)); // WHERE customer_family_id > 12 + * + * + * @see filterByCustomerFamily() + * + * @param mixed $customerFamilyId The value to use as filter. + * Use scalar values for equality. + * Use array values for in_array() equivalent. + * Use associative array('min' => $minValue, 'max' => $maxValue) for intervals. + * @param string $comparison Operator to use for the column comparison, defaults to Criteria::EQUAL + * + * @return ChildCustomerFamilyAvailableCategoryQuery The current query, for fluid interface + */ + public function filterByCustomerFamilyId($customerFamilyId = null, $comparison = null) + { + if (is_array($customerFamilyId)) { + $useMinMax = false; + if (isset($customerFamilyId['min'])) { + $this->addUsingAlias(CustomerFamilyAvailableCategoryTableMap::CUSTOMER_FAMILY_ID, $customerFamilyId['min'], Criteria::GREATER_EQUAL); + $useMinMax = true; + } + if (isset($customerFamilyId['max'])) { + $this->addUsingAlias(CustomerFamilyAvailableCategoryTableMap::CUSTOMER_FAMILY_ID, $customerFamilyId['max'], Criteria::LESS_EQUAL); + $useMinMax = true; + } + if ($useMinMax) { + return $this; + } + if (null === $comparison) { + $comparison = Criteria::IN; + } + } + + return $this->addUsingAlias(CustomerFamilyAvailableCategoryTableMap::CUSTOMER_FAMILY_ID, $customerFamilyId, $comparison); + } + + /** + * Filter the query on the category_id column + * + * Example usage: + * + * $query->filterByCategoryId(1234); // WHERE category_id = 1234 + * $query->filterByCategoryId(array(12, 34)); // WHERE category_id IN (12, 34) + * $query->filterByCategoryId(array('min' => 12)); // WHERE category_id > 12 + * + * + * @see filterByCategory() + * + * @param mixed $categoryId The value to use as filter. + * Use scalar values for equality. + * Use array values for in_array() equivalent. + * Use associative array('min' => $minValue, 'max' => $maxValue) for intervals. + * @param string $comparison Operator to use for the column comparison, defaults to Criteria::EQUAL + * + * @return ChildCustomerFamilyAvailableCategoryQuery The current query, for fluid interface + */ + public function filterByCategoryId($categoryId = null, $comparison = null) + { + if (is_array($categoryId)) { + $useMinMax = false; + if (isset($categoryId['min'])) { + $this->addUsingAlias(CustomerFamilyAvailableCategoryTableMap::CATEGORY_ID, $categoryId['min'], Criteria::GREATER_EQUAL); + $useMinMax = true; + } + if (isset($categoryId['max'])) { + $this->addUsingAlias(CustomerFamilyAvailableCategoryTableMap::CATEGORY_ID, $categoryId['max'], Criteria::LESS_EQUAL); + $useMinMax = true; + } + if ($useMinMax) { + return $this; + } + if (null === $comparison) { + $comparison = Criteria::IN; + } + } + + return $this->addUsingAlias(CustomerFamilyAvailableCategoryTableMap::CATEGORY_ID, $categoryId, $comparison); + } + + /** + * Filter the query by a related \CustomerFamily\Model\CustomerFamily object + * + * @param \CustomerFamily\Model\CustomerFamily|ObjectCollection $customerFamily The related object(s) to use as filter + * @param string $comparison Operator to use for the column comparison, defaults to Criteria::EQUAL + * + * @return ChildCustomerFamilyAvailableCategoryQuery The current query, for fluid interface + */ + public function filterByCustomerFamily($customerFamily, $comparison = null) + { + if ($customerFamily instanceof \CustomerFamily\Model\CustomerFamily) { + return $this + ->addUsingAlias(CustomerFamilyAvailableCategoryTableMap::CUSTOMER_FAMILY_ID, $customerFamily->getId(), $comparison); + } elseif ($customerFamily instanceof ObjectCollection) { + if (null === $comparison) { + $comparison = Criteria::IN; + } + + return $this + ->addUsingAlias(CustomerFamilyAvailableCategoryTableMap::CUSTOMER_FAMILY_ID, $customerFamily->toKeyValue('PrimaryKey', 'Id'), $comparison); + } else { + throw new PropelException('filterByCustomerFamily() only accepts arguments of type \CustomerFamily\Model\CustomerFamily or Collection'); + } + } + + /** + * Adds a JOIN clause to the query using the CustomerFamily relation + * + * @param string $relationAlias optional alias for the relation + * @param string $joinType Accepted values are null, 'left join', 'right join', 'inner join' + * + * @return ChildCustomerFamilyAvailableCategoryQuery The current query, for fluid interface + */ + public function joinCustomerFamily($relationAlias = null, $joinType = Criteria::INNER_JOIN) + { + $tableMap = $this->getTableMap(); + $relationMap = $tableMap->getRelation('CustomerFamily'); + + // create a ModelJoin object for this join + $join = new ModelJoin(); + $join->setJoinType($joinType); + $join->setRelationMap($relationMap, $this->useAliasInSQL ? $this->getModelAlias() : null, $relationAlias); + if ($previousJoin = $this->getPreviousJoin()) { + $join->setPreviousJoin($previousJoin); + } + + // add the ModelJoin to the current object + if ($relationAlias) { + $this->addAlias($relationAlias, $relationMap->getRightTable()->getName()); + $this->addJoinObject($join, $relationAlias); + } else { + $this->addJoinObject($join, 'CustomerFamily'); + } + + return $this; + } + + /** + * Use the CustomerFamily relation CustomerFamily object + * + * @see useQuery() + * + * @param string $relationAlias optional alias for the relation, + * to be used as main alias in the secondary query + * @param string $joinType Accepted values are null, 'left join', 'right join', 'inner join' + * + * @return \CustomerFamily\Model\CustomerFamilyQuery A secondary query class using the current class as primary query + */ + public function useCustomerFamilyQuery($relationAlias = null, $joinType = Criteria::INNER_JOIN) + { + return $this + ->joinCustomerFamily($relationAlias, $joinType) + ->useQuery($relationAlias ? $relationAlias : 'CustomerFamily', '\CustomerFamily\Model\CustomerFamilyQuery'); + } + + /** + * Filter the query by a related \CustomerFamily\Model\Thelia\Model\Category object + * + * @param \CustomerFamily\Model\Thelia\Model\Category|ObjectCollection $category The related object(s) to use as filter + * @param string $comparison Operator to use for the column comparison, defaults to Criteria::EQUAL + * + * @return ChildCustomerFamilyAvailableCategoryQuery The current query, for fluid interface + */ + public function filterByCategory($category, $comparison = null) + { + if ($category instanceof \CustomerFamily\Model\Thelia\Model\Category) { + return $this + ->addUsingAlias(CustomerFamilyAvailableCategoryTableMap::CATEGORY_ID, $category->getId(), $comparison); + } elseif ($category instanceof ObjectCollection) { + if (null === $comparison) { + $comparison = Criteria::IN; + } + + return $this + ->addUsingAlias(CustomerFamilyAvailableCategoryTableMap::CATEGORY_ID, $category->toKeyValue('PrimaryKey', 'Id'), $comparison); + } else { + throw new PropelException('filterByCategory() only accepts arguments of type \CustomerFamily\Model\Thelia\Model\Category or Collection'); + } + } + + /** + * Adds a JOIN clause to the query using the Category relation + * + * @param string $relationAlias optional alias for the relation + * @param string $joinType Accepted values are null, 'left join', 'right join', 'inner join' + * + * @return ChildCustomerFamilyAvailableCategoryQuery The current query, for fluid interface + */ + public function joinCategory($relationAlias = null, $joinType = Criteria::INNER_JOIN) + { + $tableMap = $this->getTableMap(); + $relationMap = $tableMap->getRelation('Category'); + + // create a ModelJoin object for this join + $join = new ModelJoin(); + $join->setJoinType($joinType); + $join->setRelationMap($relationMap, $this->useAliasInSQL ? $this->getModelAlias() : null, $relationAlias); + if ($previousJoin = $this->getPreviousJoin()) { + $join->setPreviousJoin($previousJoin); + } + + // add the ModelJoin to the current object + if ($relationAlias) { + $this->addAlias($relationAlias, $relationMap->getRightTable()->getName()); + $this->addJoinObject($join, $relationAlias); + } else { + $this->addJoinObject($join, 'Category'); + } + + return $this; + } + + /** + * Use the Category relation Category object + * + * @see useQuery() + * + * @param string $relationAlias optional alias for the relation, + * to be used as main alias in the secondary query + * @param string $joinType Accepted values are null, 'left join', 'right join', 'inner join' + * + * @return \CustomerFamily\Model\Thelia\Model\CategoryQuery A secondary query class using the current class as primary query + */ + public function useCategoryQuery($relationAlias = null, $joinType = Criteria::INNER_JOIN) + { + return $this + ->joinCategory($relationAlias, $joinType) + ->useQuery($relationAlias ? $relationAlias : 'Category', '\CustomerFamily\Model\Thelia\Model\CategoryQuery'); + } + + /** + * Exclude object from result + * + * @param ChildCustomerFamilyAvailableCategory $customerFamilyAvailableCategory Object to remove from the list of results + * + * @return ChildCustomerFamilyAvailableCategoryQuery The current query, for fluid interface + */ + public function prune($customerFamilyAvailableCategory = null) + { + if ($customerFamilyAvailableCategory) { + $this->addCond('pruneCond0', $this->getAliasedColName(CustomerFamilyAvailableCategoryTableMap::CUSTOMER_FAMILY_ID), $customerFamilyAvailableCategory->getCustomerFamilyId(), Criteria::NOT_EQUAL); + $this->addCond('pruneCond1', $this->getAliasedColName(CustomerFamilyAvailableCategoryTableMap::CATEGORY_ID), $customerFamilyAvailableCategory->getCategoryId(), Criteria::NOT_EQUAL); + $this->combine(array('pruneCond0', 'pruneCond1'), Criteria::LOGICAL_OR); + } + + return $this; + } + + /** + * Deletes all rows from the customer_family_available_category table. + * + * @param ConnectionInterface $con the connection to use + * @return int The number of affected rows (if supported by underlying database driver). + */ + public function doDeleteAll(ConnectionInterface $con = null) + { + if (null === $con) { + $con = Propel::getServiceContainer()->getWriteConnection(CustomerFamilyAvailableCategoryTableMap::DATABASE_NAME); + } + $affectedRows = 0; // initialize var to track total num of affected rows + try { + // use transaction because $criteria could contain info + // for more than one table or we could emulating ON DELETE CASCADE, etc. + $con->beginTransaction(); + $affectedRows += parent::doDeleteAll($con); + // Because this db requires some delete cascade/set null emulation, we have to + // clear the cached instance *after* the emulation has happened (since + // instances get re-added by the select statement contained therein). + CustomerFamilyAvailableCategoryTableMap::clearInstancePool(); + CustomerFamilyAvailableCategoryTableMap::clearRelatedInstancePool(); + + $con->commit(); + } catch (PropelException $e) { + $con->rollBack(); + throw $e; + } + + return $affectedRows; + } + + /** + * Performs a DELETE on the database, given a ChildCustomerFamilyAvailableCategory or Criteria object OR a primary key value. + * + * @param mixed $values Criteria or ChildCustomerFamilyAvailableCategory object or primary key or array of primary keys + * which is used to create the DELETE statement + * @param ConnectionInterface $con the connection to use + * @return int The number of affected rows (if supported by underlying database driver). This includes CASCADE-related rows + * if supported by native driver or if emulated using Propel. + * @throws PropelException Any exceptions caught during processing will be + * rethrown wrapped into a PropelException. + */ + public function delete(ConnectionInterface $con = null) + { + if (null === $con) { + $con = Propel::getServiceContainer()->getWriteConnection(CustomerFamilyAvailableCategoryTableMap::DATABASE_NAME); + } + + $criteria = $this; + + // Set the correct dbName + $criteria->setDbName(CustomerFamilyAvailableCategoryTableMap::DATABASE_NAME); + + $affectedRows = 0; // initialize var to track total num of affected rows + + try { + // use transaction because $criteria could contain info + // for more than one table or we could emulating ON DELETE CASCADE, etc. + $con->beginTransaction(); + + + CustomerFamilyAvailableCategoryTableMap::removeInstanceFromPool($criteria); + + $affectedRows += ModelCriteria::delete($con); + CustomerFamilyAvailableCategoryTableMap::clearRelatedInstancePool(); + $con->commit(); + + return $affectedRows; + } catch (PropelException $e) { + $con->rollBack(); + throw $e; + } + } + +} // CustomerFamilyAvailableCategoryQuery diff --git a/local/modules/CustomerFamily/Model/Base/CustomerFamilyI18n.php b/local/modules/CustomerFamily/Model/Base/CustomerFamilyI18n.php new file mode 100644 index 00000000..75e281e1 --- /dev/null +++ b/local/modules/CustomerFamily/Model/Base/CustomerFamilyI18n.php @@ -0,0 +1,1268 @@ +locale = 'en_US'; + } + + /** + * Initializes internal state of CustomerFamily\Model\Base\CustomerFamilyI18n object. + * @see applyDefaults() + */ + public function __construct() + { + $this->applyDefaultValues(); + } + + /** + * Returns whether the object has been modified. + * + * @return boolean True if the object has been modified. + */ + public function isModified() + { + return !!$this->modifiedColumns; + } + + /** + * Has specified column been modified? + * + * @param string $col column fully qualified name (TableMap::TYPE_COLNAME), e.g. Book::AUTHOR_ID + * @return boolean True if $col has been modified. + */ + public function isColumnModified($col) + { + return $this->modifiedColumns && isset($this->modifiedColumns[$col]); + } + + /** + * Get the columns that have been modified in this object. + * @return array A unique list of the modified column names for this object. + */ + public function getModifiedColumns() + { + return $this->modifiedColumns ? array_keys($this->modifiedColumns) : []; + } + + /** + * Returns whether the object has ever been saved. This will + * be false, if the object was retrieved from storage or was created + * and then saved. + * + * @return boolean true, if the object has never been persisted. + */ + public function isNew() + { + return $this->new; + } + + /** + * Setter for the isNew attribute. This method will be called + * by Propel-generated children and objects. + * + * @param boolean $b the state of the object. + */ + public function setNew($b) + { + $this->new = (Boolean) $b; + } + + /** + * Whether this object has been deleted. + * @return boolean The deleted state of this object. + */ + public function isDeleted() + { + return $this->deleted; + } + + /** + * Specify whether this object has been deleted. + * @param boolean $b The deleted state of this object. + * @return void + */ + public function setDeleted($b) + { + $this->deleted = (Boolean) $b; + } + + /** + * Sets the modified state for the object to be false. + * @param string $col If supplied, only the specified column is reset. + * @return void + */ + public function resetModified($col = null) + { + if (null !== $col) { + if (isset($this->modifiedColumns[$col])) { + unset($this->modifiedColumns[$col]); + } + } else { + $this->modifiedColumns = array(); + } + } + + /** + * Compares this with another CustomerFamilyI18n instance. If + * obj is an instance of CustomerFamilyI18n, delegates to + * equals(CustomerFamilyI18n). Otherwise, returns false. + * + * @param mixed $obj The object to compare to. + * @return boolean Whether equal to the object specified. + */ + public function equals($obj) + { + $thisclazz = get_class($this); + if (!is_object($obj) || !($obj instanceof $thisclazz)) { + return false; + } + + if ($this === $obj) { + return true; + } + + if (null === $this->getPrimaryKey() + || null === $obj->getPrimaryKey()) { + return false; + } + + return $this->getPrimaryKey() === $obj->getPrimaryKey(); + } + + /** + * If the primary key is not null, return the hashcode of the + * primary key. Otherwise, return the hash code of the object. + * + * @return int Hashcode + */ + public function hashCode() + { + if (null !== $this->getPrimaryKey()) { + return crc32(serialize($this->getPrimaryKey())); + } + + return crc32(serialize(clone $this)); + } + + /** + * Get the associative array of the virtual columns in this object + * + * @return array + */ + public function getVirtualColumns() + { + return $this->virtualColumns; + } + + /** + * Checks the existence of a virtual column in this object + * + * @param string $name The virtual column name + * @return boolean + */ + public function hasVirtualColumn($name) + { + return array_key_exists($name, $this->virtualColumns); + } + + /** + * Get the value of a virtual column in this object + * + * @param string $name The virtual column name + * @return mixed + * + * @throws PropelException + */ + public function getVirtualColumn($name) + { + if (!$this->hasVirtualColumn($name)) { + throw new PropelException(sprintf('Cannot get value of inexistent virtual column %s.', $name)); + } + + return $this->virtualColumns[$name]; + } + + /** + * Set the value of a virtual column in this object + * + * @param string $name The virtual column name + * @param mixed $value The value to give to the virtual column + * + * @return CustomerFamilyI18n The current object, for fluid interface + */ + public function setVirtualColumn($name, $value) + { + $this->virtualColumns[$name] = $value; + + return $this; + } + + /** + * Logs a message using Propel::log(). + * + * @param string $msg + * @param int $priority One of the Propel::LOG_* logging levels + * @return boolean + */ + protected function log($msg, $priority = Propel::LOG_INFO) + { + return Propel::log(get_class($this) . ': ' . $msg, $priority); + } + + /** + * Populate the current object from a string, using a given parser format + * + * $book = new Book(); + * $book->importFrom('JSON', '{"Id":9012,"Title":"Don Juan","ISBN":"0140422161","Price":12.99,"PublisherId":1234,"AuthorId":5678}'); + * + * + * @param mixed $parser A AbstractParser instance, + * or a format name ('XML', 'YAML', 'JSON', 'CSV') + * @param string $data The source data to import from + * + * @return CustomerFamilyI18n The current object, for fluid interface + */ + public function importFrom($parser, $data) + { + if (!$parser instanceof AbstractParser) { + $parser = AbstractParser::getParser($parser); + } + + $this->fromArray($parser->toArray($data), TableMap::TYPE_PHPNAME); + + return $this; + } + + /** + * Export the current object properties to a string, using a given parser format + * + * $book = BookQuery::create()->findPk(9012); + * echo $book->exportTo('JSON'); + * => {"Id":9012,"Title":"Don Juan","ISBN":"0140422161","Price":12.99,"PublisherId":1234,"AuthorId":5678}'); + * + * + * @param mixed $parser A AbstractParser instance, or a format name ('XML', 'YAML', 'JSON', 'CSV') + * @param boolean $includeLazyLoadColumns (optional) Whether to include lazy load(ed) columns. Defaults to TRUE. + * @return string The exported data + */ + public function exportTo($parser, $includeLazyLoadColumns = true) + { + if (!$parser instanceof AbstractParser) { + $parser = AbstractParser::getParser($parser); + } + + return $parser->fromArray($this->toArray(TableMap::TYPE_PHPNAME, $includeLazyLoadColumns, array(), true)); + } + + /** + * Clean up internal collections prior to serializing + * Avoids recursive loops that turn into segmentation faults when serializing + */ + public function __sleep() + { + $this->clearAllReferences(); + + return array_keys(get_object_vars($this)); + } + + /** + * Get the [id] column value. + * + * @return int + */ + public function getId() + { + + return $this->id; + } + + /** + * Get the [locale] column value. + * + * @return string + */ + public function getLocale() + { + + return $this->locale; + } + + /** + * Get the [title] column value. + * + * @return string + */ + public function getTitle() + { + + return $this->title; + } + + /** + * Set the value of [id] column. + * + * @param int $v new value + * @return \CustomerFamily\Model\CustomerFamilyI18n The current object (for fluent API support) + */ + public function setId($v) + { + if ($v !== null) { + $v = (int) $v; + } + + if ($this->id !== $v) { + $this->id = $v; + $this->modifiedColumns[CustomerFamilyI18nTableMap::ID] = true; + } + + if ($this->aCustomerFamily !== null && $this->aCustomerFamily->getId() !== $v) { + $this->aCustomerFamily = null; + } + + + return $this; + } // setId() + + /** + * Set the value of [locale] column. + * + * @param string $v new value + * @return \CustomerFamily\Model\CustomerFamilyI18n The current object (for fluent API support) + */ + public function setLocale($v) + { + if ($v !== null) { + $v = (string) $v; + } + + if ($this->locale !== $v) { + $this->locale = $v; + $this->modifiedColumns[CustomerFamilyI18nTableMap::LOCALE] = true; + } + + + return $this; + } // setLocale() + + /** + * Set the value of [title] column. + * + * @param string $v new value + * @return \CustomerFamily\Model\CustomerFamilyI18n The current object (for fluent API support) + */ + public function setTitle($v) + { + if ($v !== null) { + $v = (string) $v; + } + + if ($this->title !== $v) { + $this->title = $v; + $this->modifiedColumns[CustomerFamilyI18nTableMap::TITLE] = true; + } + + + return $this; + } // setTitle() + + /** + * Indicates whether the columns in this object are only set to default values. + * + * This method can be used in conjunction with isModified() to indicate whether an object is both + * modified _and_ has some values set which are non-default. + * + * @return boolean Whether the columns in this object are only been set with default values. + */ + public function hasOnlyDefaultValues() + { + if ($this->locale !== 'en_US') { + return false; + } + + // otherwise, everything was equal, so return TRUE + return true; + } // hasOnlyDefaultValues() + + /** + * Hydrates (populates) the object variables with values from the database resultset. + * + * An offset (0-based "start column") is specified so that objects can be hydrated + * with a subset of the columns in the resultset rows. This is needed, for example, + * for results of JOIN queries where the resultset row includes columns from two or + * more tables. + * + * @param array $row The row returned by DataFetcher->fetch(). + * @param int $startcol 0-based offset column which indicates which restultset column to start with. + * @param boolean $rehydrate Whether this object is being re-hydrated from the database. + * @param string $indexType The index type of $row. Mostly DataFetcher->getIndexType(). + One of the class type constants TableMap::TYPE_PHPNAME, TableMap::TYPE_STUDLYPHPNAME + * TableMap::TYPE_COLNAME, TableMap::TYPE_FIELDNAME, TableMap::TYPE_NUM. + * + * @return int next starting column + * @throws PropelException - Any caught Exception will be rewrapped as a PropelException. + */ + public function hydrate($row, $startcol = 0, $rehydrate = false, $indexType = TableMap::TYPE_NUM) + { + try { + + + $col = $row[TableMap::TYPE_NUM == $indexType ? 0 + $startcol : CustomerFamilyI18nTableMap::translateFieldName('Id', TableMap::TYPE_PHPNAME, $indexType)]; + $this->id = (null !== $col) ? (int) $col : null; + + $col = $row[TableMap::TYPE_NUM == $indexType ? 1 + $startcol : CustomerFamilyI18nTableMap::translateFieldName('Locale', TableMap::TYPE_PHPNAME, $indexType)]; + $this->locale = (null !== $col) ? (string) $col : null; + + $col = $row[TableMap::TYPE_NUM == $indexType ? 2 + $startcol : CustomerFamilyI18nTableMap::translateFieldName('Title', TableMap::TYPE_PHPNAME, $indexType)]; + $this->title = (null !== $col) ? (string) $col : null; + $this->resetModified(); + + $this->setNew(false); + + if ($rehydrate) { + $this->ensureConsistency(); + } + + return $startcol + 3; // 3 = CustomerFamilyI18nTableMap::NUM_HYDRATE_COLUMNS. + + } catch (Exception $e) { + throw new PropelException("Error populating \CustomerFamily\Model\CustomerFamilyI18n object", 0, $e); + } + } + + /** + * Checks and repairs the internal consistency of the object. + * + * This method is executed after an already-instantiated object is re-hydrated + * from the database. It exists to check any foreign keys to make sure that + * the objects related to the current object are correct based on foreign key. + * + * You can override this method in the stub class, but you should always invoke + * the base method from the overridden method (i.e. parent::ensureConsistency()), + * in case your model changes. + * + * @throws PropelException + */ + public function ensureConsistency() + { + if ($this->aCustomerFamily !== null && $this->id !== $this->aCustomerFamily->getId()) { + $this->aCustomerFamily = null; + } + } // ensureConsistency + + /** + * Reloads this object from datastore based on primary key and (optionally) resets all associated objects. + * + * This will only work if the object has been saved and has a valid primary key set. + * + * @param boolean $deep (optional) Whether to also de-associated any related objects. + * @param ConnectionInterface $con (optional) The ConnectionInterface connection to use. + * @return void + * @throws PropelException - if this object is deleted, unsaved or doesn't have pk match in db + */ + public function reload($deep = false, ConnectionInterface $con = null) + { + if ($this->isDeleted()) { + throw new PropelException("Cannot reload a deleted object."); + } + + if ($this->isNew()) { + throw new PropelException("Cannot reload an unsaved object."); + } + + if ($con === null) { + $con = Propel::getServiceContainer()->getReadConnection(CustomerFamilyI18nTableMap::DATABASE_NAME); + } + + // We don't need to alter the object instance pool; we're just modifying this instance + // already in the pool. + + $dataFetcher = ChildCustomerFamilyI18nQuery::create(null, $this->buildPkeyCriteria())->setFormatter(ModelCriteria::FORMAT_STATEMENT)->find($con); + $row = $dataFetcher->fetch(); + $dataFetcher->close(); + if (!$row) { + throw new PropelException('Cannot find matching row in the database to reload object values.'); + } + $this->hydrate($row, 0, true, $dataFetcher->getIndexType()); // rehydrate + + if ($deep) { // also de-associate any related objects? + + $this->aCustomerFamily = null; + } // if (deep) + } + + /** + * Removes this object from datastore and sets delete attribute. + * + * @param ConnectionInterface $con + * @return void + * @throws PropelException + * @see CustomerFamilyI18n::setDeleted() + * @see CustomerFamilyI18n::isDeleted() + */ + public function delete(ConnectionInterface $con = null) + { + if ($this->isDeleted()) { + throw new PropelException("This object has already been deleted."); + } + + if ($con === null) { + $con = Propel::getServiceContainer()->getWriteConnection(CustomerFamilyI18nTableMap::DATABASE_NAME); + } + + $con->beginTransaction(); + try { + $deleteQuery = ChildCustomerFamilyI18nQuery::create() + ->filterByPrimaryKey($this->getPrimaryKey()); + $ret = $this->preDelete($con); + if ($ret) { + $deleteQuery->delete($con); + $this->postDelete($con); + $con->commit(); + $this->setDeleted(true); + } else { + $con->commit(); + } + } catch (Exception $e) { + $con->rollBack(); + throw $e; + } + } + + /** + * Persists this object to the database. + * + * If the object is new, it inserts it; otherwise an update is performed. + * All modified related objects will also be persisted in the doSave() + * method. This method wraps all precipitate database operations in a + * single transaction. + * + * @param ConnectionInterface $con + * @return int The number of rows affected by this insert/update and any referring fk objects' save() operations. + * @throws PropelException + * @see doSave() + */ + public function save(ConnectionInterface $con = null) + { + if ($this->isDeleted()) { + throw new PropelException("You cannot save an object that has been deleted."); + } + + if ($con === null) { + $con = Propel::getServiceContainer()->getWriteConnection(CustomerFamilyI18nTableMap::DATABASE_NAME); + } + + $con->beginTransaction(); + $isInsert = $this->isNew(); + try { + $ret = $this->preSave($con); + if ($isInsert) { + $ret = $ret && $this->preInsert($con); + } else { + $ret = $ret && $this->preUpdate($con); + } + if ($ret) { + $affectedRows = $this->doSave($con); + if ($isInsert) { + $this->postInsert($con); + } else { + $this->postUpdate($con); + } + $this->postSave($con); + CustomerFamilyI18nTableMap::addInstanceToPool($this); + } else { + $affectedRows = 0; + } + $con->commit(); + + return $affectedRows; + } catch (Exception $e) { + $con->rollBack(); + throw $e; + } + } + + /** + * Performs the work of inserting or updating the row in the database. + * + * If the object is new, it inserts it; otherwise an update is performed. + * All related objects are also updated in this method. + * + * @param ConnectionInterface $con + * @return int The number of rows affected by this insert/update and any referring fk objects' save() operations. + * @throws PropelException + * @see save() + */ + protected function doSave(ConnectionInterface $con) + { + $affectedRows = 0; // initialize var to track total num of affected rows + if (!$this->alreadyInSave) { + $this->alreadyInSave = true; + + // We call the save method on the following object(s) if they + // were passed to this object by their corresponding set + // method. This object relates to these object(s) by a + // foreign key reference. + + if ($this->aCustomerFamily !== null) { + if ($this->aCustomerFamily->isModified() || $this->aCustomerFamily->isNew()) { + $affectedRows += $this->aCustomerFamily->save($con); + } + $this->setCustomerFamily($this->aCustomerFamily); + } + + if ($this->isNew() || $this->isModified()) { + // persist changes + if ($this->isNew()) { + $this->doInsert($con); + } else { + $this->doUpdate($con); + } + $affectedRows += 1; + $this->resetModified(); + } + + $this->alreadyInSave = false; + + } + + return $affectedRows; + } // doSave() + + /** + * Insert the row in the database. + * + * @param ConnectionInterface $con + * + * @throws PropelException + * @see doSave() + */ + protected function doInsert(ConnectionInterface $con) + { + $modifiedColumns = array(); + $index = 0; + + + // check the columns in natural order for more readable SQL queries + if ($this->isColumnModified(CustomerFamilyI18nTableMap::ID)) { + $modifiedColumns[':p' . $index++] = 'ID'; + } + if ($this->isColumnModified(CustomerFamilyI18nTableMap::LOCALE)) { + $modifiedColumns[':p' . $index++] = 'LOCALE'; + } + if ($this->isColumnModified(CustomerFamilyI18nTableMap::TITLE)) { + $modifiedColumns[':p' . $index++] = 'TITLE'; + } + + $sql = sprintf( + 'INSERT INTO customer_family_i18n (%s) VALUES (%s)', + implode(', ', $modifiedColumns), + implode(', ', array_keys($modifiedColumns)) + ); + + try { + $stmt = $con->prepare($sql); + foreach ($modifiedColumns as $identifier => $columnName) { + switch ($columnName) { + case 'ID': + $stmt->bindValue($identifier, $this->id, PDO::PARAM_INT); + break; + case 'LOCALE': + $stmt->bindValue($identifier, $this->locale, PDO::PARAM_STR); + break; + case 'TITLE': + $stmt->bindValue($identifier, $this->title, PDO::PARAM_STR); + break; + } + } + $stmt->execute(); + } catch (Exception $e) { + Propel::log($e->getMessage(), Propel::LOG_ERR); + throw new PropelException(sprintf('Unable to execute INSERT statement [%s]', $sql), 0, $e); + } + + $this->setNew(false); + } + + /** + * Update the row in the database. + * + * @param ConnectionInterface $con + * + * @return Integer Number of updated rows + * @see doSave() + */ + protected function doUpdate(ConnectionInterface $con) + { + $selectCriteria = $this->buildPkeyCriteria(); + $valuesCriteria = $this->buildCriteria(); + + return $selectCriteria->doUpdate($valuesCriteria, $con); + } + + /** + * Retrieves a field from the object by name passed in as a string. + * + * @param string $name name + * @param string $type The type of fieldname the $name is of: + * one of the class type constants TableMap::TYPE_PHPNAME, TableMap::TYPE_STUDLYPHPNAME + * TableMap::TYPE_COLNAME, TableMap::TYPE_FIELDNAME, TableMap::TYPE_NUM. + * Defaults to TableMap::TYPE_PHPNAME. + * @return mixed Value of field. + */ + public function getByName($name, $type = TableMap::TYPE_PHPNAME) + { + $pos = CustomerFamilyI18nTableMap::translateFieldName($name, $type, TableMap::TYPE_NUM); + $field = $this->getByPosition($pos); + + return $field; + } + + /** + * Retrieves a field from the object by Position as specified in the xml schema. + * Zero-based. + * + * @param int $pos position in xml schema + * @return mixed Value of field at $pos + */ + public function getByPosition($pos) + { + switch ($pos) { + case 0: + return $this->getId(); + break; + case 1: + return $this->getLocale(); + break; + case 2: + return $this->getTitle(); + break; + default: + return null; + break; + } // switch() + } + + /** + * Exports the object as an array. + * + * You can specify the key type of the array by passing one of the class + * type constants. + * + * @param string $keyType (optional) One of the class type constants TableMap::TYPE_PHPNAME, TableMap::TYPE_STUDLYPHPNAME, + * TableMap::TYPE_COLNAME, TableMap::TYPE_FIELDNAME, TableMap::TYPE_NUM. + * Defaults to TableMap::TYPE_PHPNAME. + * @param boolean $includeLazyLoadColumns (optional) Whether to include lazy loaded columns. Defaults to TRUE. + * @param array $alreadyDumpedObjects List of objects to skip to avoid recursion + * @param boolean $includeForeignObjects (optional) Whether to include hydrated related objects. Default to FALSE. + * + * @return array an associative array containing the field names (as keys) and field values + */ + public function toArray($keyType = TableMap::TYPE_PHPNAME, $includeLazyLoadColumns = true, $alreadyDumpedObjects = array(), $includeForeignObjects = false) + { + if (isset($alreadyDumpedObjects['CustomerFamilyI18n'][serialize($this->getPrimaryKey())])) { + return '*RECURSION*'; + } + $alreadyDumpedObjects['CustomerFamilyI18n'][serialize($this->getPrimaryKey())] = true; + $keys = CustomerFamilyI18nTableMap::getFieldNames($keyType); + $result = array( + $keys[0] => $this->getId(), + $keys[1] => $this->getLocale(), + $keys[2] => $this->getTitle(), + ); + $virtualColumns = $this->virtualColumns; + foreach ($virtualColumns as $key => $virtualColumn) { + $result[$key] = $virtualColumn; + } + + if ($includeForeignObjects) { + if (null !== $this->aCustomerFamily) { + $result['CustomerFamily'] = $this->aCustomerFamily->toArray($keyType, $includeLazyLoadColumns, $alreadyDumpedObjects, true); + } + } + + return $result; + } + + /** + * Sets a field from the object by name passed in as a string. + * + * @param string $name + * @param mixed $value field value + * @param string $type The type of fieldname the $name is of: + * one of the class type constants TableMap::TYPE_PHPNAME, TableMap::TYPE_STUDLYPHPNAME + * TableMap::TYPE_COLNAME, TableMap::TYPE_FIELDNAME, TableMap::TYPE_NUM. + * Defaults to TableMap::TYPE_PHPNAME. + * @return void + */ + public function setByName($name, $value, $type = TableMap::TYPE_PHPNAME) + { + $pos = CustomerFamilyI18nTableMap::translateFieldName($name, $type, TableMap::TYPE_NUM); + + return $this->setByPosition($pos, $value); + } + + /** + * Sets a field from the object by Position as specified in the xml schema. + * Zero-based. + * + * @param int $pos position in xml schema + * @param mixed $value field value + * @return void + */ + public function setByPosition($pos, $value) + { + switch ($pos) { + case 0: + $this->setId($value); + break; + case 1: + $this->setLocale($value); + break; + case 2: + $this->setTitle($value); + break; + } // switch() + } + + /** + * Populates the object using an array. + * + * This is particularly useful when populating an object from one of the + * request arrays (e.g. $_POST). This method goes through the column + * names, checking to see whether a matching key exists in populated + * array. If so the setByName() method is called for that column. + * + * You can specify the key type of the array by additionally passing one + * of the class type constants TableMap::TYPE_PHPNAME, TableMap::TYPE_STUDLYPHPNAME, + * TableMap::TYPE_COLNAME, TableMap::TYPE_FIELDNAME, TableMap::TYPE_NUM. + * The default key type is the column's TableMap::TYPE_PHPNAME. + * + * @param array $arr An array to populate the object from. + * @param string $keyType The type of keys the array uses. + * @return void + */ + public function fromArray($arr, $keyType = TableMap::TYPE_PHPNAME) + { + $keys = CustomerFamilyI18nTableMap::getFieldNames($keyType); + + if (array_key_exists($keys[0], $arr)) $this->setId($arr[$keys[0]]); + if (array_key_exists($keys[1], $arr)) $this->setLocale($arr[$keys[1]]); + if (array_key_exists($keys[2], $arr)) $this->setTitle($arr[$keys[2]]); + } + + /** + * Build a Criteria object containing the values of all modified columns in this object. + * + * @return Criteria The Criteria object containing all modified values. + */ + public function buildCriteria() + { + $criteria = new Criteria(CustomerFamilyI18nTableMap::DATABASE_NAME); + + if ($this->isColumnModified(CustomerFamilyI18nTableMap::ID)) $criteria->add(CustomerFamilyI18nTableMap::ID, $this->id); + if ($this->isColumnModified(CustomerFamilyI18nTableMap::LOCALE)) $criteria->add(CustomerFamilyI18nTableMap::LOCALE, $this->locale); + if ($this->isColumnModified(CustomerFamilyI18nTableMap::TITLE)) $criteria->add(CustomerFamilyI18nTableMap::TITLE, $this->title); + + return $criteria; + } + + /** + * Builds a Criteria object containing the primary key for this object. + * + * Unlike buildCriteria() this method includes the primary key values regardless + * of whether or not they have been modified. + * + * @return Criteria The Criteria object containing value(s) for primary key(s). + */ + public function buildPkeyCriteria() + { + $criteria = new Criteria(CustomerFamilyI18nTableMap::DATABASE_NAME); + $criteria->add(CustomerFamilyI18nTableMap::ID, $this->id); + $criteria->add(CustomerFamilyI18nTableMap::LOCALE, $this->locale); + + return $criteria; + } + + /** + * Returns the composite primary key for this object. + * The array elements will be in same order as specified in XML. + * @return array + */ + public function getPrimaryKey() + { + $pks = array(); + $pks[0] = $this->getId(); + $pks[1] = $this->getLocale(); + + return $pks; + } + + /** + * Set the [composite] primary key. + * + * @param array $keys The elements of the composite key (order must match the order in XML file). + * @return void + */ + public function setPrimaryKey($keys) + { + $this->setId($keys[0]); + $this->setLocale($keys[1]); + } + + /** + * Returns true if the primary key for this object is null. + * @return boolean + */ + public function isPrimaryKeyNull() + { + + return (null === $this->getId()) && (null === $this->getLocale()); + } + + /** + * Sets contents of passed object to values from current object. + * + * If desired, this method can also make copies of all associated (fkey referrers) + * objects. + * + * @param object $copyObj An object of \CustomerFamily\Model\CustomerFamilyI18n (or compatible) type. + * @param boolean $deepCopy Whether to also copy all rows that refer (by fkey) to the current row. + * @param boolean $makeNew Whether to reset autoincrement PKs and make the object new. + * @throws PropelException + */ + public function copyInto($copyObj, $deepCopy = false, $makeNew = true) + { + $copyObj->setId($this->getId()); + $copyObj->setLocale($this->getLocale()); + $copyObj->setTitle($this->getTitle()); + if ($makeNew) { + $copyObj->setNew(true); + } + } + + /** + * Makes a copy of this object that will be inserted as a new row in table when saved. + * It creates a new object filling in the simple attributes, but skipping any primary + * keys that are defined for the table. + * + * If desired, this method can also make copies of all associated (fkey referrers) + * objects. + * + * @param boolean $deepCopy Whether to also copy all rows that refer (by fkey) to the current row. + * @return \CustomerFamily\Model\CustomerFamilyI18n Clone of current object. + * @throws PropelException + */ + public function copy($deepCopy = false) + { + // we use get_class(), because this might be a subclass + $clazz = get_class($this); + $copyObj = new $clazz(); + $this->copyInto($copyObj, $deepCopy); + + return $copyObj; + } + + /** + * Declares an association between this object and a ChildCustomerFamily object. + * + * @param ChildCustomerFamily $v + * @return \CustomerFamily\Model\CustomerFamilyI18n The current object (for fluent API support) + * @throws PropelException + */ + public function setCustomerFamily(ChildCustomerFamily $v = null) + { + if ($v === null) { + $this->setId(NULL); + } else { + $this->setId($v->getId()); + } + + $this->aCustomerFamily = $v; + + // Add binding for other direction of this n:n relationship. + // If this object has already been added to the ChildCustomerFamily object, it will not be re-added. + if ($v !== null) { + $v->addCustomerFamilyI18n($this); + } + + + return $this; + } + + + /** + * Get the associated ChildCustomerFamily object + * + * @param ConnectionInterface $con Optional Connection object. + * @return ChildCustomerFamily The associated ChildCustomerFamily object. + * @throws PropelException + */ + public function getCustomerFamily(ConnectionInterface $con = null) + { + if ($this->aCustomerFamily === null && ($this->id !== null)) { + $this->aCustomerFamily = ChildCustomerFamilyQuery::create()->findPk($this->id, $con); + /* The following can be used additionally to + guarantee the related object contains a reference + to this object. This level of coupling may, however, be + undesirable since it could result in an only partially populated collection + in the referenced object. + $this->aCustomerFamily->addCustomerFamilyI18ns($this); + */ + } + + return $this->aCustomerFamily; + } + + /** + * Clears the current object and sets all attributes to their default values + */ + public function clear() + { + $this->id = null; + $this->locale = null; + $this->title = null; + $this->alreadyInSave = false; + $this->clearAllReferences(); + $this->applyDefaultValues(); + $this->resetModified(); + $this->setNew(true); + $this->setDeleted(false); + } + + /** + * Resets all references to other model objects or collections of model objects. + * + * This method is a user-space workaround for PHP's inability to garbage collect + * objects with circular references (even in PHP 5.3). This is currently necessary + * when using Propel in certain daemon or large-volume/high-memory operations. + * + * @param boolean $deep Whether to also clear the references on all referrer objects. + */ + public function clearAllReferences($deep = false) + { + if ($deep) { + } // if ($deep) + + $this->aCustomerFamily = null; + } + + /** + * Return the string representation of this object + * + * @return string + */ + public function __toString() + { + return (string) $this->exportTo(CustomerFamilyI18nTableMap::DEFAULT_STRING_FORMAT); + } + + /** + * Code to be run before persisting the object + * @param ConnectionInterface $con + * @return boolean + */ + public function preSave(ConnectionInterface $con = null) + { + return true; + } + + /** + * Code to be run after persisting the object + * @param ConnectionInterface $con + */ + public function postSave(ConnectionInterface $con = null) + { + + } + + /** + * Code to be run before inserting to database + * @param ConnectionInterface $con + * @return boolean + */ + public function preInsert(ConnectionInterface $con = null) + { + return true; + } + + /** + * Code to be run after inserting to database + * @param ConnectionInterface $con + */ + public function postInsert(ConnectionInterface $con = null) + { + + } + + /** + * Code to be run before updating the object in database + * @param ConnectionInterface $con + * @return boolean + */ + public function preUpdate(ConnectionInterface $con = null) + { + return true; + } + + /** + * Code to be run after updating the object in database + * @param ConnectionInterface $con + */ + public function postUpdate(ConnectionInterface $con = null) + { + + } + + /** + * Code to be run before deleting the object in database + * @param ConnectionInterface $con + * @return boolean + */ + public function preDelete(ConnectionInterface $con = null) + { + return true; + } + + /** + * Code to be run after deleting the object in database + * @param ConnectionInterface $con + */ + public function postDelete(ConnectionInterface $con = null) + { + + } + + + /** + * Derived method to catches calls to undefined methods. + * + * Provides magic import/export method support (fromXML()/toXML(), fromYAML()/toYAML(), etc.). + * Allows to define default __call() behavior if you overwrite __call() + * + * @param string $name + * @param mixed $params + * + * @return array|string + */ + public function __call($name, $params) + { + if (0 === strpos($name, 'get')) { + $virtualColumn = substr($name, 3); + if ($this->hasVirtualColumn($virtualColumn)) { + return $this->getVirtualColumn($virtualColumn); + } + + $virtualColumn = lcfirst($virtualColumn); + if ($this->hasVirtualColumn($virtualColumn)) { + return $this->getVirtualColumn($virtualColumn); + } + } + + if (0 === strpos($name, 'from')) { + $format = substr($name, 4); + + return $this->importFrom($format, reset($params)); + } + + if (0 === strpos($name, 'to')) { + $format = substr($name, 2); + $includeLazyLoadColumns = isset($params[0]) ? $params[0] : true; + + return $this->exportTo($format, $includeLazyLoadColumns); + } + + throw new BadMethodCallException(sprintf('Call to undefined method: %s.', $name)); + } + +} diff --git a/local/modules/CustomerFamily/Model/Base/CustomerFamilyI18nQuery.php b/local/modules/CustomerFamily/Model/Base/CustomerFamilyI18nQuery.php new file mode 100644 index 00000000..90f5eeec --- /dev/null +++ b/local/modules/CustomerFamily/Model/Base/CustomerFamilyI18nQuery.php @@ -0,0 +1,508 @@ +setModelAlias($modelAlias); + } + if ($criteria instanceof Criteria) { + $query->mergeWith($criteria); + } + + return $query; + } + + /** + * Find object by primary key. + * Propel uses the instance pool to skip the database if the object exists. + * Go fast if the query is untouched. + * + * + * $obj = $c->findPk(array(12, 34), $con); + * + * + * @param array[$id, $locale] $key Primary key to use for the query + * @param ConnectionInterface $con an optional connection object + * + * @return ChildCustomerFamilyI18n|array|mixed the result, formatted by the current formatter + */ + public function findPk($key, $con = null) + { + if ($key === null) { + return null; + } + if ((null !== ($obj = CustomerFamilyI18nTableMap::getInstanceFromPool(serialize(array((string) $key[0], (string) $key[1]))))) && !$this->formatter) { + // the object is already in the instance pool + return $obj; + } + if ($con === null) { + $con = Propel::getServiceContainer()->getReadConnection(CustomerFamilyI18nTableMap::DATABASE_NAME); + } + $this->basePreSelect($con); + if ($this->formatter || $this->modelAlias || $this->with || $this->select + || $this->selectColumns || $this->asColumns || $this->selectModifiers + || $this->map || $this->having || $this->joins) { + return $this->findPkComplex($key, $con); + } else { + return $this->findPkSimple($key, $con); + } + } + + /** + * Find object by primary key using raw SQL to go fast. + * Bypass doSelect() and the object formatter by using generated code. + * + * @param mixed $key Primary key to use for the query + * @param ConnectionInterface $con A connection object + * + * @return ChildCustomerFamilyI18n A model object, or null if the key is not found + */ + protected function findPkSimple($key, $con) + { + $sql = 'SELECT ID, LOCALE, TITLE FROM customer_family_i18n WHERE ID = :p0 AND LOCALE = :p1'; + try { + $stmt = $con->prepare($sql); + $stmt->bindValue(':p0', $key[0], PDO::PARAM_INT); + $stmt->bindValue(':p1', $key[1], PDO::PARAM_STR); + $stmt->execute(); + } catch (Exception $e) { + Propel::log($e->getMessage(), Propel::LOG_ERR); + throw new PropelException(sprintf('Unable to execute SELECT statement [%s]', $sql), 0, $e); + } + $obj = null; + if ($row = $stmt->fetch(\PDO::FETCH_NUM)) { + $obj = new ChildCustomerFamilyI18n(); + $obj->hydrate($row); + CustomerFamilyI18nTableMap::addInstanceToPool($obj, serialize(array((string) $key[0], (string) $key[1]))); + } + $stmt->closeCursor(); + + return $obj; + } + + /** + * Find object by primary key. + * + * @param mixed $key Primary key to use for the query + * @param ConnectionInterface $con A connection object + * + * @return ChildCustomerFamilyI18n|array|mixed the result, formatted by the current formatter + */ + protected function findPkComplex($key, $con) + { + // As the query uses a PK condition, no limit(1) is necessary. + $criteria = $this->isKeepQuery() ? clone $this : $this; + $dataFetcher = $criteria + ->filterByPrimaryKey($key) + ->doSelect($con); + + return $criteria->getFormatter()->init($criteria)->formatOne($dataFetcher); + } + + /** + * Find objects by primary key + * + * $objs = $c->findPks(array(array(12, 56), array(832, 123), array(123, 456)), $con); + * + * @param array $keys Primary keys to use for the query + * @param ConnectionInterface $con an optional connection object + * + * @return ObjectCollection|array|mixed the list of results, formatted by the current formatter + */ + public function findPks($keys, $con = null) + { + if (null === $con) { + $con = Propel::getServiceContainer()->getReadConnection($this->getDbName()); + } + $this->basePreSelect($con); + $criteria = $this->isKeepQuery() ? clone $this : $this; + $dataFetcher = $criteria + ->filterByPrimaryKeys($keys) + ->doSelect($con); + + return $criteria->getFormatter()->init($criteria)->format($dataFetcher); + } + + /** + * Filter the query by primary key + * + * @param mixed $key Primary key to use for the query + * + * @return ChildCustomerFamilyI18nQuery The current query, for fluid interface + */ + public function filterByPrimaryKey($key) + { + $this->addUsingAlias(CustomerFamilyI18nTableMap::ID, $key[0], Criteria::EQUAL); + $this->addUsingAlias(CustomerFamilyI18nTableMap::LOCALE, $key[1], Criteria::EQUAL); + + return $this; + } + + /** + * Filter the query by a list of primary keys + * + * @param array $keys The list of primary key to use for the query + * + * @return ChildCustomerFamilyI18nQuery The current query, for fluid interface + */ + public function filterByPrimaryKeys($keys) + { + if (empty($keys)) { + return $this->add(null, '1<>1', Criteria::CUSTOM); + } + foreach ($keys as $key) { + $cton0 = $this->getNewCriterion(CustomerFamilyI18nTableMap::ID, $key[0], Criteria::EQUAL); + $cton1 = $this->getNewCriterion(CustomerFamilyI18nTableMap::LOCALE, $key[1], Criteria::EQUAL); + $cton0->addAnd($cton1); + $this->addOr($cton0); + } + + return $this; + } + + /** + * Filter the query on the id column + * + * Example usage: + * + * $query->filterById(1234); // WHERE id = 1234 + * $query->filterById(array(12, 34)); // WHERE id IN (12, 34) + * $query->filterById(array('min' => 12)); // WHERE id > 12 + * + * + * @see filterByCustomerFamily() + * + * @param mixed $id The value to use as filter. + * Use scalar values for equality. + * Use array values for in_array() equivalent. + * Use associative array('min' => $minValue, 'max' => $maxValue) for intervals. + * @param string $comparison Operator to use for the column comparison, defaults to Criteria::EQUAL + * + * @return ChildCustomerFamilyI18nQuery The current query, for fluid interface + */ + public function filterById($id = null, $comparison = null) + { + if (is_array($id)) { + $useMinMax = false; + if (isset($id['min'])) { + $this->addUsingAlias(CustomerFamilyI18nTableMap::ID, $id['min'], Criteria::GREATER_EQUAL); + $useMinMax = true; + } + if (isset($id['max'])) { + $this->addUsingAlias(CustomerFamilyI18nTableMap::ID, $id['max'], Criteria::LESS_EQUAL); + $useMinMax = true; + } + if ($useMinMax) { + return $this; + } + if (null === $comparison) { + $comparison = Criteria::IN; + } + } + + return $this->addUsingAlias(CustomerFamilyI18nTableMap::ID, $id, $comparison); + } + + /** + * Filter the query on the locale column + * + * Example usage: + * + * $query->filterByLocale('fooValue'); // WHERE locale = 'fooValue' + * $query->filterByLocale('%fooValue%'); // WHERE locale LIKE '%fooValue%' + * + * + * @param string $locale The value to use as filter. + * Accepts wildcards (* and % trigger a LIKE) + * @param string $comparison Operator to use for the column comparison, defaults to Criteria::EQUAL + * + * @return ChildCustomerFamilyI18nQuery The current query, for fluid interface + */ + public function filterByLocale($locale = null, $comparison = null) + { + if (null === $comparison) { + if (is_array($locale)) { + $comparison = Criteria::IN; + } elseif (preg_match('/[\%\*]/', $locale)) { + $locale = str_replace('*', '%', $locale); + $comparison = Criteria::LIKE; + } + } + + return $this->addUsingAlias(CustomerFamilyI18nTableMap::LOCALE, $locale, $comparison); + } + + /** + * Filter the query on the title column + * + * Example usage: + * + * $query->filterByTitle('fooValue'); // WHERE title = 'fooValue' + * $query->filterByTitle('%fooValue%'); // WHERE title LIKE '%fooValue%' + * + * + * @param string $title The value to use as filter. + * Accepts wildcards (* and % trigger a LIKE) + * @param string $comparison Operator to use for the column comparison, defaults to Criteria::EQUAL + * + * @return ChildCustomerFamilyI18nQuery The current query, for fluid interface + */ + public function filterByTitle($title = null, $comparison = null) + { + if (null === $comparison) { + if (is_array($title)) { + $comparison = Criteria::IN; + } elseif (preg_match('/[\%\*]/', $title)) { + $title = str_replace('*', '%', $title); + $comparison = Criteria::LIKE; + } + } + + return $this->addUsingAlias(CustomerFamilyI18nTableMap::TITLE, $title, $comparison); + } + + /** + * Filter the query by a related \CustomerFamily\Model\CustomerFamily object + * + * @param \CustomerFamily\Model\CustomerFamily|ObjectCollection $customerFamily The related object(s) to use as filter + * @param string $comparison Operator to use for the column comparison, defaults to Criteria::EQUAL + * + * @return ChildCustomerFamilyI18nQuery The current query, for fluid interface + */ + public function filterByCustomerFamily($customerFamily, $comparison = null) + { + if ($customerFamily instanceof \CustomerFamily\Model\CustomerFamily) { + return $this + ->addUsingAlias(CustomerFamilyI18nTableMap::ID, $customerFamily->getId(), $comparison); + } elseif ($customerFamily instanceof ObjectCollection) { + if (null === $comparison) { + $comparison = Criteria::IN; + } + + return $this + ->addUsingAlias(CustomerFamilyI18nTableMap::ID, $customerFamily->toKeyValue('PrimaryKey', 'Id'), $comparison); + } else { + throw new PropelException('filterByCustomerFamily() only accepts arguments of type \CustomerFamily\Model\CustomerFamily or Collection'); + } + } + + /** + * Adds a JOIN clause to the query using the CustomerFamily relation + * + * @param string $relationAlias optional alias for the relation + * @param string $joinType Accepted values are null, 'left join', 'right join', 'inner join' + * + * @return ChildCustomerFamilyI18nQuery The current query, for fluid interface + */ + public function joinCustomerFamily($relationAlias = null, $joinType = 'LEFT JOIN') + { + $tableMap = $this->getTableMap(); + $relationMap = $tableMap->getRelation('CustomerFamily'); + + // create a ModelJoin object for this join + $join = new ModelJoin(); + $join->setJoinType($joinType); + $join->setRelationMap($relationMap, $this->useAliasInSQL ? $this->getModelAlias() : null, $relationAlias); + if ($previousJoin = $this->getPreviousJoin()) { + $join->setPreviousJoin($previousJoin); + } + + // add the ModelJoin to the current object + if ($relationAlias) { + $this->addAlias($relationAlias, $relationMap->getRightTable()->getName()); + $this->addJoinObject($join, $relationAlias); + } else { + $this->addJoinObject($join, 'CustomerFamily'); + } + + return $this; + } + + /** + * Use the CustomerFamily relation CustomerFamily object + * + * @see useQuery() + * + * @param string $relationAlias optional alias for the relation, + * to be used as main alias in the secondary query + * @param string $joinType Accepted values are null, 'left join', 'right join', 'inner join' + * + * @return \CustomerFamily\Model\CustomerFamilyQuery A secondary query class using the current class as primary query + */ + public function useCustomerFamilyQuery($relationAlias = null, $joinType = 'LEFT JOIN') + { + return $this + ->joinCustomerFamily($relationAlias, $joinType) + ->useQuery($relationAlias ? $relationAlias : 'CustomerFamily', '\CustomerFamily\Model\CustomerFamilyQuery'); + } + + /** + * Exclude object from result + * + * @param ChildCustomerFamilyI18n $customerFamilyI18n Object to remove from the list of results + * + * @return ChildCustomerFamilyI18nQuery The current query, for fluid interface + */ + public function prune($customerFamilyI18n = null) + { + if ($customerFamilyI18n) { + $this->addCond('pruneCond0', $this->getAliasedColName(CustomerFamilyI18nTableMap::ID), $customerFamilyI18n->getId(), Criteria::NOT_EQUAL); + $this->addCond('pruneCond1', $this->getAliasedColName(CustomerFamilyI18nTableMap::LOCALE), $customerFamilyI18n->getLocale(), Criteria::NOT_EQUAL); + $this->combine(array('pruneCond0', 'pruneCond1'), Criteria::LOGICAL_OR); + } + + return $this; + } + + /** + * Deletes all rows from the customer_family_i18n table. + * + * @param ConnectionInterface $con the connection to use + * @return int The number of affected rows (if supported by underlying database driver). + */ + public function doDeleteAll(ConnectionInterface $con = null) + { + if (null === $con) { + $con = Propel::getServiceContainer()->getWriteConnection(CustomerFamilyI18nTableMap::DATABASE_NAME); + } + $affectedRows = 0; // initialize var to track total num of affected rows + try { + // use transaction because $criteria could contain info + // for more than one table or we could emulating ON DELETE CASCADE, etc. + $con->beginTransaction(); + $affectedRows += parent::doDeleteAll($con); + // Because this db requires some delete cascade/set null emulation, we have to + // clear the cached instance *after* the emulation has happened (since + // instances get re-added by the select statement contained therein). + CustomerFamilyI18nTableMap::clearInstancePool(); + CustomerFamilyI18nTableMap::clearRelatedInstancePool(); + + $con->commit(); + } catch (PropelException $e) { + $con->rollBack(); + throw $e; + } + + return $affectedRows; + } + + /** + * Performs a DELETE on the database, given a ChildCustomerFamilyI18n or Criteria object OR a primary key value. + * + * @param mixed $values Criteria or ChildCustomerFamilyI18n object or primary key or array of primary keys + * which is used to create the DELETE statement + * @param ConnectionInterface $con the connection to use + * @return int The number of affected rows (if supported by underlying database driver). This includes CASCADE-related rows + * if supported by native driver or if emulated using Propel. + * @throws PropelException Any exceptions caught during processing will be + * rethrown wrapped into a PropelException. + */ + public function delete(ConnectionInterface $con = null) + { + if (null === $con) { + $con = Propel::getServiceContainer()->getWriteConnection(CustomerFamilyI18nTableMap::DATABASE_NAME); + } + + $criteria = $this; + + // Set the correct dbName + $criteria->setDbName(CustomerFamilyI18nTableMap::DATABASE_NAME); + + $affectedRows = 0; // initialize var to track total num of affected rows + + try { + // use transaction because $criteria could contain info + // for more than one table or we could emulating ON DELETE CASCADE, etc. + $con->beginTransaction(); + + + CustomerFamilyI18nTableMap::removeInstanceFromPool($criteria); + + $affectedRows += ModelCriteria::delete($con); + CustomerFamilyI18nTableMap::clearRelatedInstancePool(); + $con->commit(); + + return $affectedRows; + } catch (PropelException $e) { + $con->rollBack(); + throw $e; + } + } + +} // CustomerFamilyI18nQuery diff --git a/local/modules/CustomerFamily/Model/Base/CustomerFamilyOrder.php b/local/modules/CustomerFamily/Model/Base/CustomerFamilyOrder.php new file mode 100644 index 00000000..9c69ad5e --- /dev/null +++ b/local/modules/CustomerFamily/Model/Base/CustomerFamilyOrder.php @@ -0,0 +1,1255 @@ +modifiedColumns; + } + + /** + * Has specified column been modified? + * + * @param string $col column fully qualified name (TableMap::TYPE_COLNAME), e.g. Book::AUTHOR_ID + * @return boolean True if $col has been modified. + */ + public function isColumnModified($col) + { + return $this->modifiedColumns && isset($this->modifiedColumns[$col]); + } + + /** + * Get the columns that have been modified in this object. + * @return array A unique list of the modified column names for this object. + */ + public function getModifiedColumns() + { + return $this->modifiedColumns ? array_keys($this->modifiedColumns) : []; + } + + /** + * Returns whether the object has ever been saved. This will + * be false, if the object was retrieved from storage or was created + * and then saved. + * + * @return boolean true, if the object has never been persisted. + */ + public function isNew() + { + return $this->new; + } + + /** + * Setter for the isNew attribute. This method will be called + * by Propel-generated children and objects. + * + * @param boolean $b the state of the object. + */ + public function setNew($b) + { + $this->new = (Boolean) $b; + } + + /** + * Whether this object has been deleted. + * @return boolean The deleted state of this object. + */ + public function isDeleted() + { + return $this->deleted; + } + + /** + * Specify whether this object has been deleted. + * @param boolean $b The deleted state of this object. + * @return void + */ + public function setDeleted($b) + { + $this->deleted = (Boolean) $b; + } + + /** + * Sets the modified state for the object to be false. + * @param string $col If supplied, only the specified column is reset. + * @return void + */ + public function resetModified($col = null) + { + if (null !== $col) { + if (isset($this->modifiedColumns[$col])) { + unset($this->modifiedColumns[$col]); + } + } else { + $this->modifiedColumns = array(); + } + } + + /** + * Compares this with another CustomerFamilyOrder instance. If + * obj is an instance of CustomerFamilyOrder, delegates to + * equals(CustomerFamilyOrder). Otherwise, returns false. + * + * @param mixed $obj The object to compare to. + * @return boolean Whether equal to the object specified. + */ + public function equals($obj) + { + $thisclazz = get_class($this); + if (!is_object($obj) || !($obj instanceof $thisclazz)) { + return false; + } + + if ($this === $obj) { + return true; + } + + if (null === $this->getPrimaryKey() + || null === $obj->getPrimaryKey()) { + return false; + } + + return $this->getPrimaryKey() === $obj->getPrimaryKey(); + } + + /** + * If the primary key is not null, return the hashcode of the + * primary key. Otherwise, return the hash code of the object. + * + * @return int Hashcode + */ + public function hashCode() + { + if (null !== $this->getPrimaryKey()) { + return crc32(serialize($this->getPrimaryKey())); + } + + return crc32(serialize(clone $this)); + } + + /** + * Get the associative array of the virtual columns in this object + * + * @return array + */ + public function getVirtualColumns() + { + return $this->virtualColumns; + } + + /** + * Checks the existence of a virtual column in this object + * + * @param string $name The virtual column name + * @return boolean + */ + public function hasVirtualColumn($name) + { + return array_key_exists($name, $this->virtualColumns); + } + + /** + * Get the value of a virtual column in this object + * + * @param string $name The virtual column name + * @return mixed + * + * @throws PropelException + */ + public function getVirtualColumn($name) + { + if (!$this->hasVirtualColumn($name)) { + throw new PropelException(sprintf('Cannot get value of inexistent virtual column %s.', $name)); + } + + return $this->virtualColumns[$name]; + } + + /** + * Set the value of a virtual column in this object + * + * @param string $name The virtual column name + * @param mixed $value The value to give to the virtual column + * + * @return CustomerFamilyOrder The current object, for fluid interface + */ + public function setVirtualColumn($name, $value) + { + $this->virtualColumns[$name] = $value; + + return $this; + } + + /** + * Logs a message using Propel::log(). + * + * @param string $msg + * @param int $priority One of the Propel::LOG_* logging levels + * @return boolean + */ + protected function log($msg, $priority = Propel::LOG_INFO) + { + return Propel::log(get_class($this) . ': ' . $msg, $priority); + } + + /** + * Populate the current object from a string, using a given parser format + * + * $book = new Book(); + * $book->importFrom('JSON', '{"Id":9012,"Title":"Don Juan","ISBN":"0140422161","Price":12.99,"PublisherId":1234,"AuthorId":5678}'); + * + * + * @param mixed $parser A AbstractParser instance, + * or a format name ('XML', 'YAML', 'JSON', 'CSV') + * @param string $data The source data to import from + * + * @return CustomerFamilyOrder The current object, for fluid interface + */ + public function importFrom($parser, $data) + { + if (!$parser instanceof AbstractParser) { + $parser = AbstractParser::getParser($parser); + } + + $this->fromArray($parser->toArray($data), TableMap::TYPE_PHPNAME); + + return $this; + } + + /** + * Export the current object properties to a string, using a given parser format + * + * $book = BookQuery::create()->findPk(9012); + * echo $book->exportTo('JSON'); + * => {"Id":9012,"Title":"Don Juan","ISBN":"0140422161","Price":12.99,"PublisherId":1234,"AuthorId":5678}'); + * + * + * @param mixed $parser A AbstractParser instance, or a format name ('XML', 'YAML', 'JSON', 'CSV') + * @param boolean $includeLazyLoadColumns (optional) Whether to include lazy load(ed) columns. Defaults to TRUE. + * @return string The exported data + */ + public function exportTo($parser, $includeLazyLoadColumns = true) + { + if (!$parser instanceof AbstractParser) { + $parser = AbstractParser::getParser($parser); + } + + return $parser->fromArray($this->toArray(TableMap::TYPE_PHPNAME, $includeLazyLoadColumns, array(), true)); + } + + /** + * Clean up internal collections prior to serializing + * Avoids recursive loops that turn into segmentation faults when serializing + */ + public function __sleep() + { + $this->clearAllReferences(); + + return array_keys(get_object_vars($this)); + } + + /** + * Get the [order_id] column value. + * + * @return int + */ + public function getOrderId() + { + + return $this->order_id; + } + + /** + * Get the [customer_family_id] column value. + * + * @return int + */ + public function getCustomerFamilyId() + { + + return $this->customer_family_id; + } + + /** + * Set the value of [order_id] column. + * + * @param int $v new value + * @return \CustomerFamily\Model\CustomerFamilyOrder The current object (for fluent API support) + */ + public function setOrderId($v) + { + if ($v !== null) { + $v = (int) $v; + } + + if ($this->order_id !== $v) { + $this->order_id = $v; + $this->modifiedColumns[CustomerFamilyOrderTableMap::ORDER_ID] = true; + } + + if ($this->aOrder !== null && $this->aOrder->getId() !== $v) { + $this->aOrder = null; + } + + + return $this; + } // setOrderId() + + /** + * Set the value of [customer_family_id] column. + * + * @param int $v new value + * @return \CustomerFamily\Model\CustomerFamilyOrder The current object (for fluent API support) + */ + public function setCustomerFamilyId($v) + { + if ($v !== null) { + $v = (int) $v; + } + + if ($this->customer_family_id !== $v) { + $this->customer_family_id = $v; + $this->modifiedColumns[CustomerFamilyOrderTableMap::CUSTOMER_FAMILY_ID] = true; + } + + if ($this->aCustomerFamily !== null && $this->aCustomerFamily->getId() !== $v) { + $this->aCustomerFamily = null; + } + + + return $this; + } // setCustomerFamilyId() + + /** + * Indicates whether the columns in this object are only set to default values. + * + * This method can be used in conjunction with isModified() to indicate whether an object is both + * modified _and_ has some values set which are non-default. + * + * @return boolean Whether the columns in this object are only been set with default values. + */ + public function hasOnlyDefaultValues() + { + // otherwise, everything was equal, so return TRUE + return true; + } // hasOnlyDefaultValues() + + /** + * Hydrates (populates) the object variables with values from the database resultset. + * + * An offset (0-based "start column") is specified so that objects can be hydrated + * with a subset of the columns in the resultset rows. This is needed, for example, + * for results of JOIN queries where the resultset row includes columns from two or + * more tables. + * + * @param array $row The row returned by DataFetcher->fetch(). + * @param int $startcol 0-based offset column which indicates which restultset column to start with. + * @param boolean $rehydrate Whether this object is being re-hydrated from the database. + * @param string $indexType The index type of $row. Mostly DataFetcher->getIndexType(). + One of the class type constants TableMap::TYPE_PHPNAME, TableMap::TYPE_STUDLYPHPNAME + * TableMap::TYPE_COLNAME, TableMap::TYPE_FIELDNAME, TableMap::TYPE_NUM. + * + * @return int next starting column + * @throws PropelException - Any caught Exception will be rewrapped as a PropelException. + */ + public function hydrate($row, $startcol = 0, $rehydrate = false, $indexType = TableMap::TYPE_NUM) + { + try { + + + $col = $row[TableMap::TYPE_NUM == $indexType ? 0 + $startcol : CustomerFamilyOrderTableMap::translateFieldName('OrderId', TableMap::TYPE_PHPNAME, $indexType)]; + $this->order_id = (null !== $col) ? (int) $col : null; + + $col = $row[TableMap::TYPE_NUM == $indexType ? 1 + $startcol : CustomerFamilyOrderTableMap::translateFieldName('CustomerFamilyId', TableMap::TYPE_PHPNAME, $indexType)]; + $this->customer_family_id = (null !== $col) ? (int) $col : null; + $this->resetModified(); + + $this->setNew(false); + + if ($rehydrate) { + $this->ensureConsistency(); + } + + return $startcol + 2; // 2 = CustomerFamilyOrderTableMap::NUM_HYDRATE_COLUMNS. + + } catch (Exception $e) { + throw new PropelException("Error populating \CustomerFamily\Model\CustomerFamilyOrder object", 0, $e); + } + } + + /** + * Checks and repairs the internal consistency of the object. + * + * This method is executed after an already-instantiated object is re-hydrated + * from the database. It exists to check any foreign keys to make sure that + * the objects related to the current object are correct based on foreign key. + * + * You can override this method in the stub class, but you should always invoke + * the base method from the overridden method (i.e. parent::ensureConsistency()), + * in case your model changes. + * + * @throws PropelException + */ + public function ensureConsistency() + { + if ($this->aOrder !== null && $this->order_id !== $this->aOrder->getId()) { + $this->aOrder = null; + } + if ($this->aCustomerFamily !== null && $this->customer_family_id !== $this->aCustomerFamily->getId()) { + $this->aCustomerFamily = null; + } + } // ensureConsistency + + /** + * Reloads this object from datastore based on primary key and (optionally) resets all associated objects. + * + * This will only work if the object has been saved and has a valid primary key set. + * + * @param boolean $deep (optional) Whether to also de-associated any related objects. + * @param ConnectionInterface $con (optional) The ConnectionInterface connection to use. + * @return void + * @throws PropelException - if this object is deleted, unsaved or doesn't have pk match in db + */ + public function reload($deep = false, ConnectionInterface $con = null) + { + if ($this->isDeleted()) { + throw new PropelException("Cannot reload a deleted object."); + } + + if ($this->isNew()) { + throw new PropelException("Cannot reload an unsaved object."); + } + + if ($con === null) { + $con = Propel::getServiceContainer()->getReadConnection(CustomerFamilyOrderTableMap::DATABASE_NAME); + } + + // We don't need to alter the object instance pool; we're just modifying this instance + // already in the pool. + + $dataFetcher = ChildCustomerFamilyOrderQuery::create(null, $this->buildPkeyCriteria())->setFormatter(ModelCriteria::FORMAT_STATEMENT)->find($con); + $row = $dataFetcher->fetch(); + $dataFetcher->close(); + if (!$row) { + throw new PropelException('Cannot find matching row in the database to reload object values.'); + } + $this->hydrate($row, 0, true, $dataFetcher->getIndexType()); // rehydrate + + if ($deep) { // also de-associate any related objects? + + $this->aOrder = null; + $this->aCustomerFamily = null; + } // if (deep) + } + + /** + * Removes this object from datastore and sets delete attribute. + * + * @param ConnectionInterface $con + * @return void + * @throws PropelException + * @see CustomerFamilyOrder::setDeleted() + * @see CustomerFamilyOrder::isDeleted() + */ + public function delete(ConnectionInterface $con = null) + { + if ($this->isDeleted()) { + throw new PropelException("This object has already been deleted."); + } + + if ($con === null) { + $con = Propel::getServiceContainer()->getWriteConnection(CustomerFamilyOrderTableMap::DATABASE_NAME); + } + + $con->beginTransaction(); + try { + $deleteQuery = ChildCustomerFamilyOrderQuery::create() + ->filterByPrimaryKey($this->getPrimaryKey()); + $ret = $this->preDelete($con); + if ($ret) { + $deleteQuery->delete($con); + $this->postDelete($con); + $con->commit(); + $this->setDeleted(true); + } else { + $con->commit(); + } + } catch (Exception $e) { + $con->rollBack(); + throw $e; + } + } + + /** + * Persists this object to the database. + * + * If the object is new, it inserts it; otherwise an update is performed. + * All modified related objects will also be persisted in the doSave() + * method. This method wraps all precipitate database operations in a + * single transaction. + * + * @param ConnectionInterface $con + * @return int The number of rows affected by this insert/update and any referring fk objects' save() operations. + * @throws PropelException + * @see doSave() + */ + public function save(ConnectionInterface $con = null) + { + if ($this->isDeleted()) { + throw new PropelException("You cannot save an object that has been deleted."); + } + + if ($con === null) { + $con = Propel::getServiceContainer()->getWriteConnection(CustomerFamilyOrderTableMap::DATABASE_NAME); + } + + $con->beginTransaction(); + $isInsert = $this->isNew(); + try { + $ret = $this->preSave($con); + if ($isInsert) { + $ret = $ret && $this->preInsert($con); + } else { + $ret = $ret && $this->preUpdate($con); + } + if ($ret) { + $affectedRows = $this->doSave($con); + if ($isInsert) { + $this->postInsert($con); + } else { + $this->postUpdate($con); + } + $this->postSave($con); + CustomerFamilyOrderTableMap::addInstanceToPool($this); + } else { + $affectedRows = 0; + } + $con->commit(); + + return $affectedRows; + } catch (Exception $e) { + $con->rollBack(); + throw $e; + } + } + + /** + * Performs the work of inserting or updating the row in the database. + * + * If the object is new, it inserts it; otherwise an update is performed. + * All related objects are also updated in this method. + * + * @param ConnectionInterface $con + * @return int The number of rows affected by this insert/update and any referring fk objects' save() operations. + * @throws PropelException + * @see save() + */ + protected function doSave(ConnectionInterface $con) + { + $affectedRows = 0; // initialize var to track total num of affected rows + if (!$this->alreadyInSave) { + $this->alreadyInSave = true; + + // We call the save method on the following object(s) if they + // were passed to this object by their corresponding set + // method. This object relates to these object(s) by a + // foreign key reference. + + if ($this->aOrder !== null) { + if ($this->aOrder->isModified() || $this->aOrder->isNew()) { + $affectedRows += $this->aOrder->save($con); + } + $this->setOrder($this->aOrder); + } + + if ($this->aCustomerFamily !== null) { + if ($this->aCustomerFamily->isModified() || $this->aCustomerFamily->isNew()) { + $affectedRows += $this->aCustomerFamily->save($con); + } + $this->setCustomerFamily($this->aCustomerFamily); + } + + if ($this->isNew() || $this->isModified()) { + // persist changes + if ($this->isNew()) { + $this->doInsert($con); + } else { + $this->doUpdate($con); + } + $affectedRows += 1; + $this->resetModified(); + } + + $this->alreadyInSave = false; + + } + + return $affectedRows; + } // doSave() + + /** + * Insert the row in the database. + * + * @param ConnectionInterface $con + * + * @throws PropelException + * @see doSave() + */ + protected function doInsert(ConnectionInterface $con) + { + $modifiedColumns = array(); + $index = 0; + + + // check the columns in natural order for more readable SQL queries + if ($this->isColumnModified(CustomerFamilyOrderTableMap::ORDER_ID)) { + $modifiedColumns[':p' . $index++] = 'ORDER_ID'; + } + if ($this->isColumnModified(CustomerFamilyOrderTableMap::CUSTOMER_FAMILY_ID)) { + $modifiedColumns[':p' . $index++] = 'CUSTOMER_FAMILY_ID'; + } + + $sql = sprintf( + 'INSERT INTO customer_family_order (%s) VALUES (%s)', + implode(', ', $modifiedColumns), + implode(', ', array_keys($modifiedColumns)) + ); + + try { + $stmt = $con->prepare($sql); + foreach ($modifiedColumns as $identifier => $columnName) { + switch ($columnName) { + case 'ORDER_ID': + $stmt->bindValue($identifier, $this->order_id, PDO::PARAM_INT); + break; + case 'CUSTOMER_FAMILY_ID': + $stmt->bindValue($identifier, $this->customer_family_id, PDO::PARAM_INT); + break; + } + } + $stmt->execute(); + } catch (Exception $e) { + Propel::log($e->getMessage(), Propel::LOG_ERR); + throw new PropelException(sprintf('Unable to execute INSERT statement [%s]', $sql), 0, $e); + } + + $this->setNew(false); + } + + /** + * Update the row in the database. + * + * @param ConnectionInterface $con + * + * @return Integer Number of updated rows + * @see doSave() + */ + protected function doUpdate(ConnectionInterface $con) + { + $selectCriteria = $this->buildPkeyCriteria(); + $valuesCriteria = $this->buildCriteria(); + + return $selectCriteria->doUpdate($valuesCriteria, $con); + } + + /** + * Retrieves a field from the object by name passed in as a string. + * + * @param string $name name + * @param string $type The type of fieldname the $name is of: + * one of the class type constants TableMap::TYPE_PHPNAME, TableMap::TYPE_STUDLYPHPNAME + * TableMap::TYPE_COLNAME, TableMap::TYPE_FIELDNAME, TableMap::TYPE_NUM. + * Defaults to TableMap::TYPE_PHPNAME. + * @return mixed Value of field. + */ + public function getByName($name, $type = TableMap::TYPE_PHPNAME) + { + $pos = CustomerFamilyOrderTableMap::translateFieldName($name, $type, TableMap::TYPE_NUM); + $field = $this->getByPosition($pos); + + return $field; + } + + /** + * Retrieves a field from the object by Position as specified in the xml schema. + * Zero-based. + * + * @param int $pos position in xml schema + * @return mixed Value of field at $pos + */ + public function getByPosition($pos) + { + switch ($pos) { + case 0: + return $this->getOrderId(); + break; + case 1: + return $this->getCustomerFamilyId(); + break; + default: + return null; + break; + } // switch() + } + + /** + * Exports the object as an array. + * + * You can specify the key type of the array by passing one of the class + * type constants. + * + * @param string $keyType (optional) One of the class type constants TableMap::TYPE_PHPNAME, TableMap::TYPE_STUDLYPHPNAME, + * TableMap::TYPE_COLNAME, TableMap::TYPE_FIELDNAME, TableMap::TYPE_NUM. + * Defaults to TableMap::TYPE_PHPNAME. + * @param boolean $includeLazyLoadColumns (optional) Whether to include lazy loaded columns. Defaults to TRUE. + * @param array $alreadyDumpedObjects List of objects to skip to avoid recursion + * @param boolean $includeForeignObjects (optional) Whether to include hydrated related objects. Default to FALSE. + * + * @return array an associative array containing the field names (as keys) and field values + */ + public function toArray($keyType = TableMap::TYPE_PHPNAME, $includeLazyLoadColumns = true, $alreadyDumpedObjects = array(), $includeForeignObjects = false) + { + if (isset($alreadyDumpedObjects['CustomerFamilyOrder'][$this->getPrimaryKey()])) { + return '*RECURSION*'; + } + $alreadyDumpedObjects['CustomerFamilyOrder'][$this->getPrimaryKey()] = true; + $keys = CustomerFamilyOrderTableMap::getFieldNames($keyType); + $result = array( + $keys[0] => $this->getOrderId(), + $keys[1] => $this->getCustomerFamilyId(), + ); + $virtualColumns = $this->virtualColumns; + foreach ($virtualColumns as $key => $virtualColumn) { + $result[$key] = $virtualColumn; + } + + if ($includeForeignObjects) { + if (null !== $this->aOrder) { + $result['Order'] = $this->aOrder->toArray($keyType, $includeLazyLoadColumns, $alreadyDumpedObjects, true); + } + if (null !== $this->aCustomerFamily) { + $result['CustomerFamily'] = $this->aCustomerFamily->toArray($keyType, $includeLazyLoadColumns, $alreadyDumpedObjects, true); + } + } + + return $result; + } + + /** + * Sets a field from the object by name passed in as a string. + * + * @param string $name + * @param mixed $value field value + * @param string $type The type of fieldname the $name is of: + * one of the class type constants TableMap::TYPE_PHPNAME, TableMap::TYPE_STUDLYPHPNAME + * TableMap::TYPE_COLNAME, TableMap::TYPE_FIELDNAME, TableMap::TYPE_NUM. + * Defaults to TableMap::TYPE_PHPNAME. + * @return void + */ + public function setByName($name, $value, $type = TableMap::TYPE_PHPNAME) + { + $pos = CustomerFamilyOrderTableMap::translateFieldName($name, $type, TableMap::TYPE_NUM); + + return $this->setByPosition($pos, $value); + } + + /** + * Sets a field from the object by Position as specified in the xml schema. + * Zero-based. + * + * @param int $pos position in xml schema + * @param mixed $value field value + * @return void + */ + public function setByPosition($pos, $value) + { + switch ($pos) { + case 0: + $this->setOrderId($value); + break; + case 1: + $this->setCustomerFamilyId($value); + break; + } // switch() + } + + /** + * Populates the object using an array. + * + * This is particularly useful when populating an object from one of the + * request arrays (e.g. $_POST). This method goes through the column + * names, checking to see whether a matching key exists in populated + * array. If so the setByName() method is called for that column. + * + * You can specify the key type of the array by additionally passing one + * of the class type constants TableMap::TYPE_PHPNAME, TableMap::TYPE_STUDLYPHPNAME, + * TableMap::TYPE_COLNAME, TableMap::TYPE_FIELDNAME, TableMap::TYPE_NUM. + * The default key type is the column's TableMap::TYPE_PHPNAME. + * + * @param array $arr An array to populate the object from. + * @param string $keyType The type of keys the array uses. + * @return void + */ + public function fromArray($arr, $keyType = TableMap::TYPE_PHPNAME) + { + $keys = CustomerFamilyOrderTableMap::getFieldNames($keyType); + + if (array_key_exists($keys[0], $arr)) $this->setOrderId($arr[$keys[0]]); + if (array_key_exists($keys[1], $arr)) $this->setCustomerFamilyId($arr[$keys[1]]); + } + + /** + * Build a Criteria object containing the values of all modified columns in this object. + * + * @return Criteria The Criteria object containing all modified values. + */ + public function buildCriteria() + { + $criteria = new Criteria(CustomerFamilyOrderTableMap::DATABASE_NAME); + + if ($this->isColumnModified(CustomerFamilyOrderTableMap::ORDER_ID)) $criteria->add(CustomerFamilyOrderTableMap::ORDER_ID, $this->order_id); + if ($this->isColumnModified(CustomerFamilyOrderTableMap::CUSTOMER_FAMILY_ID)) $criteria->add(CustomerFamilyOrderTableMap::CUSTOMER_FAMILY_ID, $this->customer_family_id); + + return $criteria; + } + + /** + * Builds a Criteria object containing the primary key for this object. + * + * Unlike buildCriteria() this method includes the primary key values regardless + * of whether or not they have been modified. + * + * @return Criteria The Criteria object containing value(s) for primary key(s). + */ + public function buildPkeyCriteria() + { + $criteria = new Criteria(CustomerFamilyOrderTableMap::DATABASE_NAME); + $criteria->add(CustomerFamilyOrderTableMap::ORDER_ID, $this->order_id); + + return $criteria; + } + + /** + * Returns the primary key for this object (row). + * @return int + */ + public function getPrimaryKey() + { + return $this->getOrderId(); + } + + /** + * Generic method to set the primary key (order_id column). + * + * @param int $key Primary key. + * @return void + */ + public function setPrimaryKey($key) + { + $this->setOrderId($key); + } + + /** + * Returns true if the primary key for this object is null. + * @return boolean + */ + public function isPrimaryKeyNull() + { + + return null === $this->getOrderId(); + } + + /** + * Sets contents of passed object to values from current object. + * + * If desired, this method can also make copies of all associated (fkey referrers) + * objects. + * + * @param object $copyObj An object of \CustomerFamily\Model\CustomerFamilyOrder (or compatible) type. + * @param boolean $deepCopy Whether to also copy all rows that refer (by fkey) to the current row. + * @param boolean $makeNew Whether to reset autoincrement PKs and make the object new. + * @throws PropelException + */ + public function copyInto($copyObj, $deepCopy = false, $makeNew = true) + { + $copyObj->setOrderId($this->getOrderId()); + $copyObj->setCustomerFamilyId($this->getCustomerFamilyId()); + if ($makeNew) { + $copyObj->setNew(true); + } + } + + /** + * Makes a copy of this object that will be inserted as a new row in table when saved. + * It creates a new object filling in the simple attributes, but skipping any primary + * keys that are defined for the table. + * + * If desired, this method can also make copies of all associated (fkey referrers) + * objects. + * + * @param boolean $deepCopy Whether to also copy all rows that refer (by fkey) to the current row. + * @return \CustomerFamily\Model\CustomerFamilyOrder Clone of current object. + * @throws PropelException + */ + public function copy($deepCopy = false) + { + // we use get_class(), because this might be a subclass + $clazz = get_class($this); + $copyObj = new $clazz(); + $this->copyInto($copyObj, $deepCopy); + + return $copyObj; + } + + /** + * Declares an association between this object and a ChildOrder object. + * + * @param ChildOrder $v + * @return \CustomerFamily\Model\CustomerFamilyOrder The current object (for fluent API support) + * @throws PropelException + */ + public function setOrder(ChildOrder $v = null) + { + if ($v === null) { + $this->setOrderId(NULL); + } else { + $this->setOrderId($v->getId()); + } + + $this->aOrder = $v; + + // Add binding for other direction of this 1:1 relationship. + if ($v !== null) { + $v->setCustomerFamilyOrder($this); + } + + + return $this; + } + + + /** + * Get the associated ChildOrder object + * + * @param ConnectionInterface $con Optional Connection object. + * @return ChildOrder The associated ChildOrder object. + * @throws PropelException + */ + public function getOrder(ConnectionInterface $con = null) + { + if ($this->aOrder === null && ($this->order_id !== null)) { + $this->aOrder = OrderQuery::create()->findPk($this->order_id, $con); + // Because this foreign key represents a one-to-one relationship, we will create a bi-directional association. + $this->aOrder->setCustomerFamilyOrder($this); + } + + return $this->aOrder; + } + + /** + * Declares an association between this object and a ChildCustomerFamily object. + * + * @param ChildCustomerFamily $v + * @return \CustomerFamily\Model\CustomerFamilyOrder The current object (for fluent API support) + * @throws PropelException + */ + public function setCustomerFamily(ChildCustomerFamily $v = null) + { + if ($v === null) { + $this->setCustomerFamilyId(NULL); + } else { + $this->setCustomerFamilyId($v->getId()); + } + + $this->aCustomerFamily = $v; + + // Add binding for other direction of this n:n relationship. + // If this object has already been added to the ChildCustomerFamily object, it will not be re-added. + if ($v !== null) { + $v->addCustomerFamilyOrder($this); + } + + + return $this; + } + + + /** + * Get the associated ChildCustomerFamily object + * + * @param ConnectionInterface $con Optional Connection object. + * @return ChildCustomerFamily The associated ChildCustomerFamily object. + * @throws PropelException + */ + public function getCustomerFamily(ConnectionInterface $con = null) + { + if ($this->aCustomerFamily === null && ($this->customer_family_id !== null)) { + $this->aCustomerFamily = ChildCustomerFamilyQuery::create()->findPk($this->customer_family_id, $con); + /* The following can be used additionally to + guarantee the related object contains a reference + to this object. This level of coupling may, however, be + undesirable since it could result in an only partially populated collection + in the referenced object. + $this->aCustomerFamily->addCustomerFamilyOrders($this); + */ + } + + return $this->aCustomerFamily; + } + + /** + * Clears the current object and sets all attributes to their default values + */ + public function clear() + { + $this->order_id = null; + $this->customer_family_id = null; + $this->alreadyInSave = false; + $this->clearAllReferences(); + $this->resetModified(); + $this->setNew(true); + $this->setDeleted(false); + } + + /** + * Resets all references to other model objects or collections of model objects. + * + * This method is a user-space workaround for PHP's inability to garbage collect + * objects with circular references (even in PHP 5.3). This is currently necessary + * when using Propel in certain daemon or large-volume/high-memory operations. + * + * @param boolean $deep Whether to also clear the references on all referrer objects. + */ + public function clearAllReferences($deep = false) + { + if ($deep) { + } // if ($deep) + + $this->aOrder = null; + $this->aCustomerFamily = null; + } + + /** + * Return the string representation of this object + * + * @return string + */ + public function __toString() + { + return (string) $this->exportTo(CustomerFamilyOrderTableMap::DEFAULT_STRING_FORMAT); + } + + /** + * Code to be run before persisting the object + * @param ConnectionInterface $con + * @return boolean + */ + public function preSave(ConnectionInterface $con = null) + { + return true; + } + + /** + * Code to be run after persisting the object + * @param ConnectionInterface $con + */ + public function postSave(ConnectionInterface $con = null) + { + + } + + /** + * Code to be run before inserting to database + * @param ConnectionInterface $con + * @return boolean + */ + public function preInsert(ConnectionInterface $con = null) + { + return true; + } + + /** + * Code to be run after inserting to database + * @param ConnectionInterface $con + */ + public function postInsert(ConnectionInterface $con = null) + { + + } + + /** + * Code to be run before updating the object in database + * @param ConnectionInterface $con + * @return boolean + */ + public function preUpdate(ConnectionInterface $con = null) + { + return true; + } + + /** + * Code to be run after updating the object in database + * @param ConnectionInterface $con + */ + public function postUpdate(ConnectionInterface $con = null) + { + + } + + /** + * Code to be run before deleting the object in database + * @param ConnectionInterface $con + * @return boolean + */ + public function preDelete(ConnectionInterface $con = null) + { + return true; + } + + /** + * Code to be run after deleting the object in database + * @param ConnectionInterface $con + */ + public function postDelete(ConnectionInterface $con = null) + { + + } + + + /** + * Derived method to catches calls to undefined methods. + * + * Provides magic import/export method support (fromXML()/toXML(), fromYAML()/toYAML(), etc.). + * Allows to define default __call() behavior if you overwrite __call() + * + * @param string $name + * @param mixed $params + * + * @return array|string + */ + public function __call($name, $params) + { + if (0 === strpos($name, 'get')) { + $virtualColumn = substr($name, 3); + if ($this->hasVirtualColumn($virtualColumn)) { + return $this->getVirtualColumn($virtualColumn); + } + + $virtualColumn = lcfirst($virtualColumn); + if ($this->hasVirtualColumn($virtualColumn)) { + return $this->getVirtualColumn($virtualColumn); + } + } + + if (0 === strpos($name, 'from')) { + $format = substr($name, 4); + + return $this->importFrom($format, reset($params)); + } + + if (0 === strpos($name, 'to')) { + $format = substr($name, 2); + $includeLazyLoadColumns = isset($params[0]) ? $params[0] : true; + + return $this->exportTo($format, $includeLazyLoadColumns); + } + + throw new BadMethodCallException(sprintf('Call to undefined method: %s.', $name)); + } + +} diff --git a/local/modules/CustomerFamily/Model/Base/CustomerFamilyOrderQuery.php b/local/modules/CustomerFamily/Model/Base/CustomerFamilyOrderQuery.php new file mode 100644 index 00000000..fa2564df --- /dev/null +++ b/local/modules/CustomerFamily/Model/Base/CustomerFamilyOrderQuery.php @@ -0,0 +1,555 @@ +setModelAlias($modelAlias); + } + if ($criteria instanceof Criteria) { + $query->mergeWith($criteria); + } + + return $query; + } + + /** + * Find object by primary key. + * Propel uses the instance pool to skip the database if the object exists. + * Go fast if the query is untouched. + * + * + * $obj = $c->findPk(12, $con); + * + * + * @param mixed $key Primary key to use for the query + * @param ConnectionInterface $con an optional connection object + * + * @return ChildCustomerFamilyOrder|array|mixed the result, formatted by the current formatter + */ + public function findPk($key, $con = null) + { + if ($key === null) { + return null; + } + if ((null !== ($obj = CustomerFamilyOrderTableMap::getInstanceFromPool((string) $key))) && !$this->formatter) { + // the object is already in the instance pool + return $obj; + } + if ($con === null) { + $con = Propel::getServiceContainer()->getReadConnection(CustomerFamilyOrderTableMap::DATABASE_NAME); + } + $this->basePreSelect($con); + if ($this->formatter || $this->modelAlias || $this->with || $this->select + || $this->selectColumns || $this->asColumns || $this->selectModifiers + || $this->map || $this->having || $this->joins) { + return $this->findPkComplex($key, $con); + } else { + return $this->findPkSimple($key, $con); + } + } + + /** + * Find object by primary key using raw SQL to go fast. + * Bypass doSelect() and the object formatter by using generated code. + * + * @param mixed $key Primary key to use for the query + * @param ConnectionInterface $con A connection object + * + * @return ChildCustomerFamilyOrder A model object, or null if the key is not found + */ + protected function findPkSimple($key, $con) + { + $sql = 'SELECT ORDER_ID, CUSTOMER_FAMILY_ID FROM customer_family_order WHERE ORDER_ID = :p0'; + try { + $stmt = $con->prepare($sql); + $stmt->bindValue(':p0', $key, PDO::PARAM_INT); + $stmt->execute(); + } catch (Exception $e) { + Propel::log($e->getMessage(), Propel::LOG_ERR); + throw new PropelException(sprintf('Unable to execute SELECT statement [%s]', $sql), 0, $e); + } + $obj = null; + if ($row = $stmt->fetch(\PDO::FETCH_NUM)) { + $obj = new ChildCustomerFamilyOrder(); + $obj->hydrate($row); + CustomerFamilyOrderTableMap::addInstanceToPool($obj, (string) $key); + } + $stmt->closeCursor(); + + return $obj; + } + + /** + * Find object by primary key. + * + * @param mixed $key Primary key to use for the query + * @param ConnectionInterface $con A connection object + * + * @return ChildCustomerFamilyOrder|array|mixed the result, formatted by the current formatter + */ + protected function findPkComplex($key, $con) + { + // As the query uses a PK condition, no limit(1) is necessary. + $criteria = $this->isKeepQuery() ? clone $this : $this; + $dataFetcher = $criteria + ->filterByPrimaryKey($key) + ->doSelect($con); + + return $criteria->getFormatter()->init($criteria)->formatOne($dataFetcher); + } + + /** + * Find objects by primary key + * + * $objs = $c->findPks(array(12, 56, 832), $con); + * + * @param array $keys Primary keys to use for the query + * @param ConnectionInterface $con an optional connection object + * + * @return ObjectCollection|array|mixed the list of results, formatted by the current formatter + */ + public function findPks($keys, $con = null) + { + if (null === $con) { + $con = Propel::getServiceContainer()->getReadConnection($this->getDbName()); + } + $this->basePreSelect($con); + $criteria = $this->isKeepQuery() ? clone $this : $this; + $dataFetcher = $criteria + ->filterByPrimaryKeys($keys) + ->doSelect($con); + + return $criteria->getFormatter()->init($criteria)->format($dataFetcher); + } + + /** + * Filter the query by primary key + * + * @param mixed $key Primary key to use for the query + * + * @return ChildCustomerFamilyOrderQuery The current query, for fluid interface + */ + public function filterByPrimaryKey($key) + { + + return $this->addUsingAlias(CustomerFamilyOrderTableMap::ORDER_ID, $key, Criteria::EQUAL); + } + + /** + * Filter the query by a list of primary keys + * + * @param array $keys The list of primary key to use for the query + * + * @return ChildCustomerFamilyOrderQuery The current query, for fluid interface + */ + public function filterByPrimaryKeys($keys) + { + + return $this->addUsingAlias(CustomerFamilyOrderTableMap::ORDER_ID, $keys, Criteria::IN); + } + + /** + * Filter the query on the order_id column + * + * Example usage: + * + * $query->filterByOrderId(1234); // WHERE order_id = 1234 + * $query->filterByOrderId(array(12, 34)); // WHERE order_id IN (12, 34) + * $query->filterByOrderId(array('min' => 12)); // WHERE order_id > 12 + * + * + * @see filterByOrder() + * + * @param mixed $orderId The value to use as filter. + * Use scalar values for equality. + * Use array values for in_array() equivalent. + * Use associative array('min' => $minValue, 'max' => $maxValue) for intervals. + * @param string $comparison Operator to use for the column comparison, defaults to Criteria::EQUAL + * + * @return ChildCustomerFamilyOrderQuery The current query, for fluid interface + */ + public function filterByOrderId($orderId = null, $comparison = null) + { + if (is_array($orderId)) { + $useMinMax = false; + if (isset($orderId['min'])) { + $this->addUsingAlias(CustomerFamilyOrderTableMap::ORDER_ID, $orderId['min'], Criteria::GREATER_EQUAL); + $useMinMax = true; + } + if (isset($orderId['max'])) { + $this->addUsingAlias(CustomerFamilyOrderTableMap::ORDER_ID, $orderId['max'], Criteria::LESS_EQUAL); + $useMinMax = true; + } + if ($useMinMax) { + return $this; + } + if (null === $comparison) { + $comparison = Criteria::IN; + } + } + + return $this->addUsingAlias(CustomerFamilyOrderTableMap::ORDER_ID, $orderId, $comparison); + } + + /** + * Filter the query on the customer_family_id column + * + * Example usage: + * + * $query->filterByCustomerFamilyId(1234); // WHERE customer_family_id = 1234 + * $query->filterByCustomerFamilyId(array(12, 34)); // WHERE customer_family_id IN (12, 34) + * $query->filterByCustomerFamilyId(array('min' => 12)); // WHERE customer_family_id > 12 + * + * + * @see filterByCustomerFamily() + * + * @param mixed $customerFamilyId The value to use as filter. + * Use scalar values for equality. + * Use array values for in_array() equivalent. + * Use associative array('min' => $minValue, 'max' => $maxValue) for intervals. + * @param string $comparison Operator to use for the column comparison, defaults to Criteria::EQUAL + * + * @return ChildCustomerFamilyOrderQuery The current query, for fluid interface + */ + public function filterByCustomerFamilyId($customerFamilyId = null, $comparison = null) + { + if (is_array($customerFamilyId)) { + $useMinMax = false; + if (isset($customerFamilyId['min'])) { + $this->addUsingAlias(CustomerFamilyOrderTableMap::CUSTOMER_FAMILY_ID, $customerFamilyId['min'], Criteria::GREATER_EQUAL); + $useMinMax = true; + } + if (isset($customerFamilyId['max'])) { + $this->addUsingAlias(CustomerFamilyOrderTableMap::CUSTOMER_FAMILY_ID, $customerFamilyId['max'], Criteria::LESS_EQUAL); + $useMinMax = true; + } + if ($useMinMax) { + return $this; + } + if (null === $comparison) { + $comparison = Criteria::IN; + } + } + + return $this->addUsingAlias(CustomerFamilyOrderTableMap::CUSTOMER_FAMILY_ID, $customerFamilyId, $comparison); + } + + /** + * Filter the query by a related \CustomerFamily\Model\Thelia\Model\Order object + * + * @param \CustomerFamily\Model\Thelia\Model\Order|ObjectCollection $order The related object(s) to use as filter + * @param string $comparison Operator to use for the column comparison, defaults to Criteria::EQUAL + * + * @return ChildCustomerFamilyOrderQuery The current query, for fluid interface + */ + public function filterByOrder($order, $comparison = null) + { + if ($order instanceof \CustomerFamily\Model\Thelia\Model\Order) { + return $this + ->addUsingAlias(CustomerFamilyOrderTableMap::ORDER_ID, $order->getId(), $comparison); + } elseif ($order instanceof ObjectCollection) { + if (null === $comparison) { + $comparison = Criteria::IN; + } + + return $this + ->addUsingAlias(CustomerFamilyOrderTableMap::ORDER_ID, $order->toKeyValue('PrimaryKey', 'Id'), $comparison); + } else { + throw new PropelException('filterByOrder() only accepts arguments of type \CustomerFamily\Model\Thelia\Model\Order or Collection'); + } + } + + /** + * Adds a JOIN clause to the query using the Order relation + * + * @param string $relationAlias optional alias for the relation + * @param string $joinType Accepted values are null, 'left join', 'right join', 'inner join' + * + * @return ChildCustomerFamilyOrderQuery The current query, for fluid interface + */ + public function joinOrder($relationAlias = null, $joinType = Criteria::INNER_JOIN) + { + $tableMap = $this->getTableMap(); + $relationMap = $tableMap->getRelation('Order'); + + // create a ModelJoin object for this join + $join = new ModelJoin(); + $join->setJoinType($joinType); + $join->setRelationMap($relationMap, $this->useAliasInSQL ? $this->getModelAlias() : null, $relationAlias); + if ($previousJoin = $this->getPreviousJoin()) { + $join->setPreviousJoin($previousJoin); + } + + // add the ModelJoin to the current object + if ($relationAlias) { + $this->addAlias($relationAlias, $relationMap->getRightTable()->getName()); + $this->addJoinObject($join, $relationAlias); + } else { + $this->addJoinObject($join, 'Order'); + } + + return $this; + } + + /** + * Use the Order relation Order object + * + * @see useQuery() + * + * @param string $relationAlias optional alias for the relation, + * to be used as main alias in the secondary query + * @param string $joinType Accepted values are null, 'left join', 'right join', 'inner join' + * + * @return \CustomerFamily\Model\Thelia\Model\OrderQuery A secondary query class using the current class as primary query + */ + public function useOrderQuery($relationAlias = null, $joinType = Criteria::INNER_JOIN) + { + return $this + ->joinOrder($relationAlias, $joinType) + ->useQuery($relationAlias ? $relationAlias : 'Order', '\CustomerFamily\Model\Thelia\Model\OrderQuery'); + } + + /** + * Filter the query by a related \CustomerFamily\Model\CustomerFamily object + * + * @param \CustomerFamily\Model\CustomerFamily|ObjectCollection $customerFamily The related object(s) to use as filter + * @param string $comparison Operator to use for the column comparison, defaults to Criteria::EQUAL + * + * @return ChildCustomerFamilyOrderQuery The current query, for fluid interface + */ + public function filterByCustomerFamily($customerFamily, $comparison = null) + { + if ($customerFamily instanceof \CustomerFamily\Model\CustomerFamily) { + return $this + ->addUsingAlias(CustomerFamilyOrderTableMap::CUSTOMER_FAMILY_ID, $customerFamily->getId(), $comparison); + } elseif ($customerFamily instanceof ObjectCollection) { + if (null === $comparison) { + $comparison = Criteria::IN; + } + + return $this + ->addUsingAlias(CustomerFamilyOrderTableMap::CUSTOMER_FAMILY_ID, $customerFamily->toKeyValue('PrimaryKey', 'Id'), $comparison); + } else { + throw new PropelException('filterByCustomerFamily() only accepts arguments of type \CustomerFamily\Model\CustomerFamily or Collection'); + } + } + + /** + * Adds a JOIN clause to the query using the CustomerFamily relation + * + * @param string $relationAlias optional alias for the relation + * @param string $joinType Accepted values are null, 'left join', 'right join', 'inner join' + * + * @return ChildCustomerFamilyOrderQuery The current query, for fluid interface + */ + public function joinCustomerFamily($relationAlias = null, $joinType = Criteria::INNER_JOIN) + { + $tableMap = $this->getTableMap(); + $relationMap = $tableMap->getRelation('CustomerFamily'); + + // create a ModelJoin object for this join + $join = new ModelJoin(); + $join->setJoinType($joinType); + $join->setRelationMap($relationMap, $this->useAliasInSQL ? $this->getModelAlias() : null, $relationAlias); + if ($previousJoin = $this->getPreviousJoin()) { + $join->setPreviousJoin($previousJoin); + } + + // add the ModelJoin to the current object + if ($relationAlias) { + $this->addAlias($relationAlias, $relationMap->getRightTable()->getName()); + $this->addJoinObject($join, $relationAlias); + } else { + $this->addJoinObject($join, 'CustomerFamily'); + } + + return $this; + } + + /** + * Use the CustomerFamily relation CustomerFamily object + * + * @see useQuery() + * + * @param string $relationAlias optional alias for the relation, + * to be used as main alias in the secondary query + * @param string $joinType Accepted values are null, 'left join', 'right join', 'inner join' + * + * @return \CustomerFamily\Model\CustomerFamilyQuery A secondary query class using the current class as primary query + */ + public function useCustomerFamilyQuery($relationAlias = null, $joinType = Criteria::INNER_JOIN) + { + return $this + ->joinCustomerFamily($relationAlias, $joinType) + ->useQuery($relationAlias ? $relationAlias : 'CustomerFamily', '\CustomerFamily\Model\CustomerFamilyQuery'); + } + + /** + * Exclude object from result + * + * @param ChildCustomerFamilyOrder $customerFamilyOrder Object to remove from the list of results + * + * @return ChildCustomerFamilyOrderQuery The current query, for fluid interface + */ + public function prune($customerFamilyOrder = null) + { + if ($customerFamilyOrder) { + $this->addUsingAlias(CustomerFamilyOrderTableMap::ORDER_ID, $customerFamilyOrder->getOrderId(), Criteria::NOT_EQUAL); + } + + return $this; + } + + /** + * Deletes all rows from the customer_family_order table. + * + * @param ConnectionInterface $con the connection to use + * @return int The number of affected rows (if supported by underlying database driver). + */ + public function doDeleteAll(ConnectionInterface $con = null) + { + if (null === $con) { + $con = Propel::getServiceContainer()->getWriteConnection(CustomerFamilyOrderTableMap::DATABASE_NAME); + } + $affectedRows = 0; // initialize var to track total num of affected rows + try { + // use transaction because $criteria could contain info + // for more than one table or we could emulating ON DELETE CASCADE, etc. + $con->beginTransaction(); + $affectedRows += parent::doDeleteAll($con); + // Because this db requires some delete cascade/set null emulation, we have to + // clear the cached instance *after* the emulation has happened (since + // instances get re-added by the select statement contained therein). + CustomerFamilyOrderTableMap::clearInstancePool(); + CustomerFamilyOrderTableMap::clearRelatedInstancePool(); + + $con->commit(); + } catch (PropelException $e) { + $con->rollBack(); + throw $e; + } + + return $affectedRows; + } + + /** + * Performs a DELETE on the database, given a ChildCustomerFamilyOrder or Criteria object OR a primary key value. + * + * @param mixed $values Criteria or ChildCustomerFamilyOrder object or primary key or array of primary keys + * which is used to create the DELETE statement + * @param ConnectionInterface $con the connection to use + * @return int The number of affected rows (if supported by underlying database driver). This includes CASCADE-related rows + * if supported by native driver or if emulated using Propel. + * @throws PropelException Any exceptions caught during processing will be + * rethrown wrapped into a PropelException. + */ + public function delete(ConnectionInterface $con = null) + { + if (null === $con) { + $con = Propel::getServiceContainer()->getWriteConnection(CustomerFamilyOrderTableMap::DATABASE_NAME); + } + + $criteria = $this; + + // Set the correct dbName + $criteria->setDbName(CustomerFamilyOrderTableMap::DATABASE_NAME); + + $affectedRows = 0; // initialize var to track total num of affected rows + + try { + // use transaction because $criteria could contain info + // for more than one table or we could emulating ON DELETE CASCADE, etc. + $con->beginTransaction(); + + + CustomerFamilyOrderTableMap::removeInstanceFromPool($criteria); + + $affectedRows += ModelCriteria::delete($con); + CustomerFamilyOrderTableMap::clearRelatedInstancePool(); + $con->commit(); + + return $affectedRows; + } catch (PropelException $e) { + $con->rollBack(); + throw $e; + } + } + +} // CustomerFamilyOrderQuery diff --git a/local/modules/CustomerFamily/Model/Base/CustomerFamilyPrice.php b/local/modules/CustomerFamily/Model/Base/CustomerFamilyPrice.php new file mode 100644 index 00000000..593d0939 --- /dev/null +++ b/local/modules/CustomerFamily/Model/Base/CustomerFamilyPrice.php @@ -0,0 +1,1530 @@ +promo = 0; + $this->use_equation = 0; + $this->amount_added_before = '0'; + $this->amount_added_after = '0'; + $this->multiplication_coefficient = '1'; + $this->is_taxed = 1; + } + + /** + * Initializes internal state of CustomerFamily\Model\Base\CustomerFamilyPrice object. + * @see applyDefaults() + */ + public function __construct() + { + $this->applyDefaultValues(); + } + + /** + * Returns whether the object has been modified. + * + * @return boolean True if the object has been modified. + */ + public function isModified() + { + return !!$this->modifiedColumns; + } + + /** + * Has specified column been modified? + * + * @param string $col column fully qualified name (TableMap::TYPE_COLNAME), e.g. Book::AUTHOR_ID + * @return boolean True if $col has been modified. + */ + public function isColumnModified($col) + { + return $this->modifiedColumns && isset($this->modifiedColumns[$col]); + } + + /** + * Get the columns that have been modified in this object. + * @return array A unique list of the modified column names for this object. + */ + public function getModifiedColumns() + { + return $this->modifiedColumns ? array_keys($this->modifiedColumns) : []; + } + + /** + * Returns whether the object has ever been saved. This will + * be false, if the object was retrieved from storage or was created + * and then saved. + * + * @return boolean true, if the object has never been persisted. + */ + public function isNew() + { + return $this->new; + } + + /** + * Setter for the isNew attribute. This method will be called + * by Propel-generated children and objects. + * + * @param boolean $b the state of the object. + */ + public function setNew($b) + { + $this->new = (Boolean) $b; + } + + /** + * Whether this object has been deleted. + * @return boolean The deleted state of this object. + */ + public function isDeleted() + { + return $this->deleted; + } + + /** + * Specify whether this object has been deleted. + * @param boolean $b The deleted state of this object. + * @return void + */ + public function setDeleted($b) + { + $this->deleted = (Boolean) $b; + } + + /** + * Sets the modified state for the object to be false. + * @param string $col If supplied, only the specified column is reset. + * @return void + */ + public function resetModified($col = null) + { + if (null !== $col) { + if (isset($this->modifiedColumns[$col])) { + unset($this->modifiedColumns[$col]); + } + } else { + $this->modifiedColumns = array(); + } + } + + /** + * Compares this with another CustomerFamilyPrice instance. If + * obj is an instance of CustomerFamilyPrice, delegates to + * equals(CustomerFamilyPrice). Otherwise, returns false. + * + * @param mixed $obj The object to compare to. + * @return boolean Whether equal to the object specified. + */ + public function equals($obj) + { + $thisclazz = get_class($this); + if (!is_object($obj) || !($obj instanceof $thisclazz)) { + return false; + } + + if ($this === $obj) { + return true; + } + + if (null === $this->getPrimaryKey() + || null === $obj->getPrimaryKey()) { + return false; + } + + return $this->getPrimaryKey() === $obj->getPrimaryKey(); + } + + /** + * If the primary key is not null, return the hashcode of the + * primary key. Otherwise, return the hash code of the object. + * + * @return int Hashcode + */ + public function hashCode() + { + if (null !== $this->getPrimaryKey()) { + return crc32(serialize($this->getPrimaryKey())); + } + + return crc32(serialize(clone $this)); + } + + /** + * Get the associative array of the virtual columns in this object + * + * @return array + */ + public function getVirtualColumns() + { + return $this->virtualColumns; + } + + /** + * Checks the existence of a virtual column in this object + * + * @param string $name The virtual column name + * @return boolean + */ + public function hasVirtualColumn($name) + { + return array_key_exists($name, $this->virtualColumns); + } + + /** + * Get the value of a virtual column in this object + * + * @param string $name The virtual column name + * @return mixed + * + * @throws PropelException + */ + public function getVirtualColumn($name) + { + if (!$this->hasVirtualColumn($name)) { + throw new PropelException(sprintf('Cannot get value of inexistent virtual column %s.', $name)); + } + + return $this->virtualColumns[$name]; + } + + /** + * Set the value of a virtual column in this object + * + * @param string $name The virtual column name + * @param mixed $value The value to give to the virtual column + * + * @return CustomerFamilyPrice The current object, for fluid interface + */ + public function setVirtualColumn($name, $value) + { + $this->virtualColumns[$name] = $value; + + return $this; + } + + /** + * Logs a message using Propel::log(). + * + * @param string $msg + * @param int $priority One of the Propel::LOG_* logging levels + * @return boolean + */ + protected function log($msg, $priority = Propel::LOG_INFO) + { + return Propel::log(get_class($this) . ': ' . $msg, $priority); + } + + /** + * Populate the current object from a string, using a given parser format + * + * $book = new Book(); + * $book->importFrom('JSON', '{"Id":9012,"Title":"Don Juan","ISBN":"0140422161","Price":12.99,"PublisherId":1234,"AuthorId":5678}'); + * + * + * @param mixed $parser A AbstractParser instance, + * or a format name ('XML', 'YAML', 'JSON', 'CSV') + * @param string $data The source data to import from + * + * @return CustomerFamilyPrice The current object, for fluid interface + */ + public function importFrom($parser, $data) + { + if (!$parser instanceof AbstractParser) { + $parser = AbstractParser::getParser($parser); + } + + $this->fromArray($parser->toArray($data), TableMap::TYPE_PHPNAME); + + return $this; + } + + /** + * Export the current object properties to a string, using a given parser format + * + * $book = BookQuery::create()->findPk(9012); + * echo $book->exportTo('JSON'); + * => {"Id":9012,"Title":"Don Juan","ISBN":"0140422161","Price":12.99,"PublisherId":1234,"AuthorId":5678}'); + * + * + * @param mixed $parser A AbstractParser instance, or a format name ('XML', 'YAML', 'JSON', 'CSV') + * @param boolean $includeLazyLoadColumns (optional) Whether to include lazy load(ed) columns. Defaults to TRUE. + * @return string The exported data + */ + public function exportTo($parser, $includeLazyLoadColumns = true) + { + if (!$parser instanceof AbstractParser) { + $parser = AbstractParser::getParser($parser); + } + + return $parser->fromArray($this->toArray(TableMap::TYPE_PHPNAME, $includeLazyLoadColumns, array(), true)); + } + + /** + * Clean up internal collections prior to serializing + * Avoids recursive loops that turn into segmentation faults when serializing + */ + public function __sleep() + { + $this->clearAllReferences(); + + return array_keys(get_object_vars($this)); + } + + /** + * Get the [customer_family_id] column value. + * + * @return int + */ + public function getCustomerFamilyId() + { + + return $this->customer_family_id; + } + + /** + * Get the [promo] column value. + * + * @return int + */ + public function getPromo() + { + + return $this->promo; + } + + /** + * Get the [use_equation] column value. + * + * @return int + */ + public function getUseEquation() + { + + return $this->use_equation; + } + + /** + * Get the [amount_added_before] column value. + * + * @return string + */ + public function getAmountAddedBefore() + { + + return $this->amount_added_before; + } + + /** + * Get the [amount_added_after] column value. + * + * @return string + */ + public function getAmountAddedAfter() + { + + return $this->amount_added_after; + } + + /** + * Get the [multiplication_coefficient] column value. + * + * @return string + */ + public function getMultiplicationCoefficient() + { + + return $this->multiplication_coefficient; + } + + /** + * Get the [is_taxed] column value. + * + * @return int + */ + public function getIsTaxed() + { + + return $this->is_taxed; + } + + /** + * Set the value of [customer_family_id] column. + * + * @param int $v new value + * @return \CustomerFamily\Model\CustomerFamilyPrice The current object (for fluent API support) + */ + public function setCustomerFamilyId($v) + { + if ($v !== null) { + $v = (int) $v; + } + + if ($this->customer_family_id !== $v) { + $this->customer_family_id = $v; + $this->modifiedColumns[CustomerFamilyPriceTableMap::CUSTOMER_FAMILY_ID] = true; + } + + if ($this->aCustomerFamily !== null && $this->aCustomerFamily->getId() !== $v) { + $this->aCustomerFamily = null; + } + + + return $this; + } // setCustomerFamilyId() + + /** + * Set the value of [promo] column. + * + * @param int $v new value + * @return \CustomerFamily\Model\CustomerFamilyPrice The current object (for fluent API support) + */ + public function setPromo($v) + { + if ($v !== null) { + $v = (int) $v; + } + + if ($this->promo !== $v) { + $this->promo = $v; + $this->modifiedColumns[CustomerFamilyPriceTableMap::PROMO] = true; + } + + + return $this; + } // setPromo() + + /** + * Set the value of [use_equation] column. + * + * @param int $v new value + * @return \CustomerFamily\Model\CustomerFamilyPrice The current object (for fluent API support) + */ + public function setUseEquation($v) + { + if ($v !== null) { + $v = (int) $v; + } + + if ($this->use_equation !== $v) { + $this->use_equation = $v; + $this->modifiedColumns[CustomerFamilyPriceTableMap::USE_EQUATION] = true; + } + + + return $this; + } // setUseEquation() + + /** + * Set the value of [amount_added_before] column. + * + * @param string $v new value + * @return \CustomerFamily\Model\CustomerFamilyPrice The current object (for fluent API support) + */ + public function setAmountAddedBefore($v) + { + if ($v !== null) { + $v = (string) $v; + } + + if ($this->amount_added_before !== $v) { + $this->amount_added_before = $v; + $this->modifiedColumns[CustomerFamilyPriceTableMap::AMOUNT_ADDED_BEFORE] = true; + } + + + return $this; + } // setAmountAddedBefore() + + /** + * Set the value of [amount_added_after] column. + * + * @param string $v new value + * @return \CustomerFamily\Model\CustomerFamilyPrice The current object (for fluent API support) + */ + public function setAmountAddedAfter($v) + { + if ($v !== null) { + $v = (string) $v; + } + + if ($this->amount_added_after !== $v) { + $this->amount_added_after = $v; + $this->modifiedColumns[CustomerFamilyPriceTableMap::AMOUNT_ADDED_AFTER] = true; + } + + + return $this; + } // setAmountAddedAfter() + + /** + * Set the value of [multiplication_coefficient] column. + * + * @param string $v new value + * @return \CustomerFamily\Model\CustomerFamilyPrice The current object (for fluent API support) + */ + public function setMultiplicationCoefficient($v) + { + if ($v !== null) { + $v = (string) $v; + } + + if ($this->multiplication_coefficient !== $v) { + $this->multiplication_coefficient = $v; + $this->modifiedColumns[CustomerFamilyPriceTableMap::MULTIPLICATION_COEFFICIENT] = true; + } + + + return $this; + } // setMultiplicationCoefficient() + + /** + * Set the value of [is_taxed] column. + * + * @param int $v new value + * @return \CustomerFamily\Model\CustomerFamilyPrice The current object (for fluent API support) + */ + public function setIsTaxed($v) + { + if ($v !== null) { + $v = (int) $v; + } + + if ($this->is_taxed !== $v) { + $this->is_taxed = $v; + $this->modifiedColumns[CustomerFamilyPriceTableMap::IS_TAXED] = true; + } + + + return $this; + } // setIsTaxed() + + /** + * Indicates whether the columns in this object are only set to default values. + * + * This method can be used in conjunction with isModified() to indicate whether an object is both + * modified _and_ has some values set which are non-default. + * + * @return boolean Whether the columns in this object are only been set with default values. + */ + public function hasOnlyDefaultValues() + { + if ($this->promo !== 0) { + return false; + } + + if ($this->use_equation !== 0) { + return false; + } + + if ($this->amount_added_before !== '0') { + return false; + } + + if ($this->amount_added_after !== '0') { + return false; + } + + if ($this->multiplication_coefficient !== '1') { + return false; + } + + if ($this->is_taxed !== 1) { + return false; + } + + // otherwise, everything was equal, so return TRUE + return true; + } // hasOnlyDefaultValues() + + /** + * Hydrates (populates) the object variables with values from the database resultset. + * + * An offset (0-based "start column") is specified so that objects can be hydrated + * with a subset of the columns in the resultset rows. This is needed, for example, + * for results of JOIN queries where the resultset row includes columns from two or + * more tables. + * + * @param array $row The row returned by DataFetcher->fetch(). + * @param int $startcol 0-based offset column which indicates which restultset column to start with. + * @param boolean $rehydrate Whether this object is being re-hydrated from the database. + * @param string $indexType The index type of $row. Mostly DataFetcher->getIndexType(). + One of the class type constants TableMap::TYPE_PHPNAME, TableMap::TYPE_STUDLYPHPNAME + * TableMap::TYPE_COLNAME, TableMap::TYPE_FIELDNAME, TableMap::TYPE_NUM. + * + * @return int next starting column + * @throws PropelException - Any caught Exception will be rewrapped as a PropelException. + */ + public function hydrate($row, $startcol = 0, $rehydrate = false, $indexType = TableMap::TYPE_NUM) + { + try { + + + $col = $row[TableMap::TYPE_NUM == $indexType ? 0 + $startcol : CustomerFamilyPriceTableMap::translateFieldName('CustomerFamilyId', TableMap::TYPE_PHPNAME, $indexType)]; + $this->customer_family_id = (null !== $col) ? (int) $col : null; + + $col = $row[TableMap::TYPE_NUM == $indexType ? 1 + $startcol : CustomerFamilyPriceTableMap::translateFieldName('Promo', TableMap::TYPE_PHPNAME, $indexType)]; + $this->promo = (null !== $col) ? (int) $col : null; + + $col = $row[TableMap::TYPE_NUM == $indexType ? 2 + $startcol : CustomerFamilyPriceTableMap::translateFieldName('UseEquation', TableMap::TYPE_PHPNAME, $indexType)]; + $this->use_equation = (null !== $col) ? (int) $col : null; + + $col = $row[TableMap::TYPE_NUM == $indexType ? 3 + $startcol : CustomerFamilyPriceTableMap::translateFieldName('AmountAddedBefore', TableMap::TYPE_PHPNAME, $indexType)]; + $this->amount_added_before = (null !== $col) ? (string) $col : null; + + $col = $row[TableMap::TYPE_NUM == $indexType ? 4 + $startcol : CustomerFamilyPriceTableMap::translateFieldName('AmountAddedAfter', TableMap::TYPE_PHPNAME, $indexType)]; + $this->amount_added_after = (null !== $col) ? (string) $col : null; + + $col = $row[TableMap::TYPE_NUM == $indexType ? 5 + $startcol : CustomerFamilyPriceTableMap::translateFieldName('MultiplicationCoefficient', TableMap::TYPE_PHPNAME, $indexType)]; + $this->multiplication_coefficient = (null !== $col) ? (string) $col : null; + + $col = $row[TableMap::TYPE_NUM == $indexType ? 6 + $startcol : CustomerFamilyPriceTableMap::translateFieldName('IsTaxed', TableMap::TYPE_PHPNAME, $indexType)]; + $this->is_taxed = (null !== $col) ? (int) $col : null; + $this->resetModified(); + + $this->setNew(false); + + if ($rehydrate) { + $this->ensureConsistency(); + } + + return $startcol + 7; // 7 = CustomerFamilyPriceTableMap::NUM_HYDRATE_COLUMNS. + + } catch (Exception $e) { + throw new PropelException("Error populating \CustomerFamily\Model\CustomerFamilyPrice object", 0, $e); + } + } + + /** + * Checks and repairs the internal consistency of the object. + * + * This method is executed after an already-instantiated object is re-hydrated + * from the database. It exists to check any foreign keys to make sure that + * the objects related to the current object are correct based on foreign key. + * + * You can override this method in the stub class, but you should always invoke + * the base method from the overridden method (i.e. parent::ensureConsistency()), + * in case your model changes. + * + * @throws PropelException + */ + public function ensureConsistency() + { + if ($this->aCustomerFamily !== null && $this->customer_family_id !== $this->aCustomerFamily->getId()) { + $this->aCustomerFamily = null; + } + } // ensureConsistency + + /** + * Reloads this object from datastore based on primary key and (optionally) resets all associated objects. + * + * This will only work if the object has been saved and has a valid primary key set. + * + * @param boolean $deep (optional) Whether to also de-associated any related objects. + * @param ConnectionInterface $con (optional) The ConnectionInterface connection to use. + * @return void + * @throws PropelException - if this object is deleted, unsaved or doesn't have pk match in db + */ + public function reload($deep = false, ConnectionInterface $con = null) + { + if ($this->isDeleted()) { + throw new PropelException("Cannot reload a deleted object."); + } + + if ($this->isNew()) { + throw new PropelException("Cannot reload an unsaved object."); + } + + if ($con === null) { + $con = Propel::getServiceContainer()->getReadConnection(CustomerFamilyPriceTableMap::DATABASE_NAME); + } + + // We don't need to alter the object instance pool; we're just modifying this instance + // already in the pool. + + $dataFetcher = ChildCustomerFamilyPriceQuery::create(null, $this->buildPkeyCriteria())->setFormatter(ModelCriteria::FORMAT_STATEMENT)->find($con); + $row = $dataFetcher->fetch(); + $dataFetcher->close(); + if (!$row) { + throw new PropelException('Cannot find matching row in the database to reload object values.'); + } + $this->hydrate($row, 0, true, $dataFetcher->getIndexType()); // rehydrate + + if ($deep) { // also de-associate any related objects? + + $this->aCustomerFamily = null; + } // if (deep) + } + + /** + * Removes this object from datastore and sets delete attribute. + * + * @param ConnectionInterface $con + * @return void + * @throws PropelException + * @see CustomerFamilyPrice::setDeleted() + * @see CustomerFamilyPrice::isDeleted() + */ + public function delete(ConnectionInterface $con = null) + { + if ($this->isDeleted()) { + throw new PropelException("This object has already been deleted."); + } + + if ($con === null) { + $con = Propel::getServiceContainer()->getWriteConnection(CustomerFamilyPriceTableMap::DATABASE_NAME); + } + + $con->beginTransaction(); + try { + $deleteQuery = ChildCustomerFamilyPriceQuery::create() + ->filterByPrimaryKey($this->getPrimaryKey()); + $ret = $this->preDelete($con); + if ($ret) { + $deleteQuery->delete($con); + $this->postDelete($con); + $con->commit(); + $this->setDeleted(true); + } else { + $con->commit(); + } + } catch (Exception $e) { + $con->rollBack(); + throw $e; + } + } + + /** + * Persists this object to the database. + * + * If the object is new, it inserts it; otherwise an update is performed. + * All modified related objects will also be persisted in the doSave() + * method. This method wraps all precipitate database operations in a + * single transaction. + * + * @param ConnectionInterface $con + * @return int The number of rows affected by this insert/update and any referring fk objects' save() operations. + * @throws PropelException + * @see doSave() + */ + public function save(ConnectionInterface $con = null) + { + if ($this->isDeleted()) { + throw new PropelException("You cannot save an object that has been deleted."); + } + + if ($con === null) { + $con = Propel::getServiceContainer()->getWriteConnection(CustomerFamilyPriceTableMap::DATABASE_NAME); + } + + $con->beginTransaction(); + $isInsert = $this->isNew(); + try { + $ret = $this->preSave($con); + if ($isInsert) { + $ret = $ret && $this->preInsert($con); + } else { + $ret = $ret && $this->preUpdate($con); + } + if ($ret) { + $affectedRows = $this->doSave($con); + if ($isInsert) { + $this->postInsert($con); + } else { + $this->postUpdate($con); + } + $this->postSave($con); + CustomerFamilyPriceTableMap::addInstanceToPool($this); + } else { + $affectedRows = 0; + } + $con->commit(); + + return $affectedRows; + } catch (Exception $e) { + $con->rollBack(); + throw $e; + } + } + + /** + * Performs the work of inserting or updating the row in the database. + * + * If the object is new, it inserts it; otherwise an update is performed. + * All related objects are also updated in this method. + * + * @param ConnectionInterface $con + * @return int The number of rows affected by this insert/update and any referring fk objects' save() operations. + * @throws PropelException + * @see save() + */ + protected function doSave(ConnectionInterface $con) + { + $affectedRows = 0; // initialize var to track total num of affected rows + if (!$this->alreadyInSave) { + $this->alreadyInSave = true; + + // We call the save method on the following object(s) if they + // were passed to this object by their corresponding set + // method. This object relates to these object(s) by a + // foreign key reference. + + if ($this->aCustomerFamily !== null) { + if ($this->aCustomerFamily->isModified() || $this->aCustomerFamily->isNew()) { + $affectedRows += $this->aCustomerFamily->save($con); + } + $this->setCustomerFamily($this->aCustomerFamily); + } + + if ($this->isNew() || $this->isModified()) { + // persist changes + if ($this->isNew()) { + $this->doInsert($con); + } else { + $this->doUpdate($con); + } + $affectedRows += 1; + $this->resetModified(); + } + + $this->alreadyInSave = false; + + } + + return $affectedRows; + } // doSave() + + /** + * Insert the row in the database. + * + * @param ConnectionInterface $con + * + * @throws PropelException + * @see doSave() + */ + protected function doInsert(ConnectionInterface $con) + { + $modifiedColumns = array(); + $index = 0; + + + // check the columns in natural order for more readable SQL queries + if ($this->isColumnModified(CustomerFamilyPriceTableMap::CUSTOMER_FAMILY_ID)) { + $modifiedColumns[':p' . $index++] = 'CUSTOMER_FAMILY_ID'; + } + if ($this->isColumnModified(CustomerFamilyPriceTableMap::PROMO)) { + $modifiedColumns[':p' . $index++] = 'PROMO'; + } + if ($this->isColumnModified(CustomerFamilyPriceTableMap::USE_EQUATION)) { + $modifiedColumns[':p' . $index++] = 'USE_EQUATION'; + } + if ($this->isColumnModified(CustomerFamilyPriceTableMap::AMOUNT_ADDED_BEFORE)) { + $modifiedColumns[':p' . $index++] = 'AMOUNT_ADDED_BEFORE'; + } + if ($this->isColumnModified(CustomerFamilyPriceTableMap::AMOUNT_ADDED_AFTER)) { + $modifiedColumns[':p' . $index++] = 'AMOUNT_ADDED_AFTER'; + } + if ($this->isColumnModified(CustomerFamilyPriceTableMap::MULTIPLICATION_COEFFICIENT)) { + $modifiedColumns[':p' . $index++] = 'MULTIPLICATION_COEFFICIENT'; + } + if ($this->isColumnModified(CustomerFamilyPriceTableMap::IS_TAXED)) { + $modifiedColumns[':p' . $index++] = 'IS_TAXED'; + } + + $sql = sprintf( + 'INSERT INTO customer_family_price (%s) VALUES (%s)', + implode(', ', $modifiedColumns), + implode(', ', array_keys($modifiedColumns)) + ); + + try { + $stmt = $con->prepare($sql); + foreach ($modifiedColumns as $identifier => $columnName) { + switch ($columnName) { + case 'CUSTOMER_FAMILY_ID': + $stmt->bindValue($identifier, $this->customer_family_id, PDO::PARAM_INT); + break; + case 'PROMO': + $stmt->bindValue($identifier, $this->promo, PDO::PARAM_INT); + break; + case 'USE_EQUATION': + $stmt->bindValue($identifier, $this->use_equation, PDO::PARAM_INT); + break; + case 'AMOUNT_ADDED_BEFORE': + $stmt->bindValue($identifier, $this->amount_added_before, PDO::PARAM_STR); + break; + case 'AMOUNT_ADDED_AFTER': + $stmt->bindValue($identifier, $this->amount_added_after, PDO::PARAM_STR); + break; + case 'MULTIPLICATION_COEFFICIENT': + $stmt->bindValue($identifier, $this->multiplication_coefficient, PDO::PARAM_STR); + break; + case 'IS_TAXED': + $stmt->bindValue($identifier, $this->is_taxed, PDO::PARAM_INT); + break; + } + } + $stmt->execute(); + } catch (Exception $e) { + Propel::log($e->getMessage(), Propel::LOG_ERR); + throw new PropelException(sprintf('Unable to execute INSERT statement [%s]', $sql), 0, $e); + } + + $this->setNew(false); + } + + /** + * Update the row in the database. + * + * @param ConnectionInterface $con + * + * @return Integer Number of updated rows + * @see doSave() + */ + protected function doUpdate(ConnectionInterface $con) + { + $selectCriteria = $this->buildPkeyCriteria(); + $valuesCriteria = $this->buildCriteria(); + + return $selectCriteria->doUpdate($valuesCriteria, $con); + } + + /** + * Retrieves a field from the object by name passed in as a string. + * + * @param string $name name + * @param string $type The type of fieldname the $name is of: + * one of the class type constants TableMap::TYPE_PHPNAME, TableMap::TYPE_STUDLYPHPNAME + * TableMap::TYPE_COLNAME, TableMap::TYPE_FIELDNAME, TableMap::TYPE_NUM. + * Defaults to TableMap::TYPE_PHPNAME. + * @return mixed Value of field. + */ + public function getByName($name, $type = TableMap::TYPE_PHPNAME) + { + $pos = CustomerFamilyPriceTableMap::translateFieldName($name, $type, TableMap::TYPE_NUM); + $field = $this->getByPosition($pos); + + return $field; + } + + /** + * Retrieves a field from the object by Position as specified in the xml schema. + * Zero-based. + * + * @param int $pos position in xml schema + * @return mixed Value of field at $pos + */ + public function getByPosition($pos) + { + switch ($pos) { + case 0: + return $this->getCustomerFamilyId(); + break; + case 1: + return $this->getPromo(); + break; + case 2: + return $this->getUseEquation(); + break; + case 3: + return $this->getAmountAddedBefore(); + break; + case 4: + return $this->getAmountAddedAfter(); + break; + case 5: + return $this->getMultiplicationCoefficient(); + break; + case 6: + return $this->getIsTaxed(); + break; + default: + return null; + break; + } // switch() + } + + /** + * Exports the object as an array. + * + * You can specify the key type of the array by passing one of the class + * type constants. + * + * @param string $keyType (optional) One of the class type constants TableMap::TYPE_PHPNAME, TableMap::TYPE_STUDLYPHPNAME, + * TableMap::TYPE_COLNAME, TableMap::TYPE_FIELDNAME, TableMap::TYPE_NUM. + * Defaults to TableMap::TYPE_PHPNAME. + * @param boolean $includeLazyLoadColumns (optional) Whether to include lazy loaded columns. Defaults to TRUE. + * @param array $alreadyDumpedObjects List of objects to skip to avoid recursion + * @param boolean $includeForeignObjects (optional) Whether to include hydrated related objects. Default to FALSE. + * + * @return array an associative array containing the field names (as keys) and field values + */ + public function toArray($keyType = TableMap::TYPE_PHPNAME, $includeLazyLoadColumns = true, $alreadyDumpedObjects = array(), $includeForeignObjects = false) + { + if (isset($alreadyDumpedObjects['CustomerFamilyPrice'][serialize($this->getPrimaryKey())])) { + return '*RECURSION*'; + } + $alreadyDumpedObjects['CustomerFamilyPrice'][serialize($this->getPrimaryKey())] = true; + $keys = CustomerFamilyPriceTableMap::getFieldNames($keyType); + $result = array( + $keys[0] => $this->getCustomerFamilyId(), + $keys[1] => $this->getPromo(), + $keys[2] => $this->getUseEquation(), + $keys[3] => $this->getAmountAddedBefore(), + $keys[4] => $this->getAmountAddedAfter(), + $keys[5] => $this->getMultiplicationCoefficient(), + $keys[6] => $this->getIsTaxed(), + ); + $virtualColumns = $this->virtualColumns; + foreach ($virtualColumns as $key => $virtualColumn) { + $result[$key] = $virtualColumn; + } + + if ($includeForeignObjects) { + if (null !== $this->aCustomerFamily) { + $result['CustomerFamily'] = $this->aCustomerFamily->toArray($keyType, $includeLazyLoadColumns, $alreadyDumpedObjects, true); + } + } + + return $result; + } + + /** + * Sets a field from the object by name passed in as a string. + * + * @param string $name + * @param mixed $value field value + * @param string $type The type of fieldname the $name is of: + * one of the class type constants TableMap::TYPE_PHPNAME, TableMap::TYPE_STUDLYPHPNAME + * TableMap::TYPE_COLNAME, TableMap::TYPE_FIELDNAME, TableMap::TYPE_NUM. + * Defaults to TableMap::TYPE_PHPNAME. + * @return void + */ + public function setByName($name, $value, $type = TableMap::TYPE_PHPNAME) + { + $pos = CustomerFamilyPriceTableMap::translateFieldName($name, $type, TableMap::TYPE_NUM); + + return $this->setByPosition($pos, $value); + } + + /** + * Sets a field from the object by Position as specified in the xml schema. + * Zero-based. + * + * @param int $pos position in xml schema + * @param mixed $value field value + * @return void + */ + public function setByPosition($pos, $value) + { + switch ($pos) { + case 0: + $this->setCustomerFamilyId($value); + break; + case 1: + $this->setPromo($value); + break; + case 2: + $this->setUseEquation($value); + break; + case 3: + $this->setAmountAddedBefore($value); + break; + case 4: + $this->setAmountAddedAfter($value); + break; + case 5: + $this->setMultiplicationCoefficient($value); + break; + case 6: + $this->setIsTaxed($value); + break; + } // switch() + } + + /** + * Populates the object using an array. + * + * This is particularly useful when populating an object from one of the + * request arrays (e.g. $_POST). This method goes through the column + * names, checking to see whether a matching key exists in populated + * array. If so the setByName() method is called for that column. + * + * You can specify the key type of the array by additionally passing one + * of the class type constants TableMap::TYPE_PHPNAME, TableMap::TYPE_STUDLYPHPNAME, + * TableMap::TYPE_COLNAME, TableMap::TYPE_FIELDNAME, TableMap::TYPE_NUM. + * The default key type is the column's TableMap::TYPE_PHPNAME. + * + * @param array $arr An array to populate the object from. + * @param string $keyType The type of keys the array uses. + * @return void + */ + public function fromArray($arr, $keyType = TableMap::TYPE_PHPNAME) + { + $keys = CustomerFamilyPriceTableMap::getFieldNames($keyType); + + if (array_key_exists($keys[0], $arr)) $this->setCustomerFamilyId($arr[$keys[0]]); + if (array_key_exists($keys[1], $arr)) $this->setPromo($arr[$keys[1]]); + if (array_key_exists($keys[2], $arr)) $this->setUseEquation($arr[$keys[2]]); + if (array_key_exists($keys[3], $arr)) $this->setAmountAddedBefore($arr[$keys[3]]); + if (array_key_exists($keys[4], $arr)) $this->setAmountAddedAfter($arr[$keys[4]]); + if (array_key_exists($keys[5], $arr)) $this->setMultiplicationCoefficient($arr[$keys[5]]); + if (array_key_exists($keys[6], $arr)) $this->setIsTaxed($arr[$keys[6]]); + } + + /** + * Build a Criteria object containing the values of all modified columns in this object. + * + * @return Criteria The Criteria object containing all modified values. + */ + public function buildCriteria() + { + $criteria = new Criteria(CustomerFamilyPriceTableMap::DATABASE_NAME); + + if ($this->isColumnModified(CustomerFamilyPriceTableMap::CUSTOMER_FAMILY_ID)) $criteria->add(CustomerFamilyPriceTableMap::CUSTOMER_FAMILY_ID, $this->customer_family_id); + if ($this->isColumnModified(CustomerFamilyPriceTableMap::PROMO)) $criteria->add(CustomerFamilyPriceTableMap::PROMO, $this->promo); + if ($this->isColumnModified(CustomerFamilyPriceTableMap::USE_EQUATION)) $criteria->add(CustomerFamilyPriceTableMap::USE_EQUATION, $this->use_equation); + if ($this->isColumnModified(CustomerFamilyPriceTableMap::AMOUNT_ADDED_BEFORE)) $criteria->add(CustomerFamilyPriceTableMap::AMOUNT_ADDED_BEFORE, $this->amount_added_before); + if ($this->isColumnModified(CustomerFamilyPriceTableMap::AMOUNT_ADDED_AFTER)) $criteria->add(CustomerFamilyPriceTableMap::AMOUNT_ADDED_AFTER, $this->amount_added_after); + if ($this->isColumnModified(CustomerFamilyPriceTableMap::MULTIPLICATION_COEFFICIENT)) $criteria->add(CustomerFamilyPriceTableMap::MULTIPLICATION_COEFFICIENT, $this->multiplication_coefficient); + if ($this->isColumnModified(CustomerFamilyPriceTableMap::IS_TAXED)) $criteria->add(CustomerFamilyPriceTableMap::IS_TAXED, $this->is_taxed); + + return $criteria; + } + + /** + * Builds a Criteria object containing the primary key for this object. + * + * Unlike buildCriteria() this method includes the primary key values regardless + * of whether or not they have been modified. + * + * @return Criteria The Criteria object containing value(s) for primary key(s). + */ + public function buildPkeyCriteria() + { + $criteria = new Criteria(CustomerFamilyPriceTableMap::DATABASE_NAME); + $criteria->add(CustomerFamilyPriceTableMap::CUSTOMER_FAMILY_ID, $this->customer_family_id); + $criteria->add(CustomerFamilyPriceTableMap::PROMO, $this->promo); + + return $criteria; + } + + /** + * Returns the composite primary key for this object. + * The array elements will be in same order as specified in XML. + * @return array + */ + public function getPrimaryKey() + { + $pks = array(); + $pks[0] = $this->getCustomerFamilyId(); + $pks[1] = $this->getPromo(); + + return $pks; + } + + /** + * Set the [composite] primary key. + * + * @param array $keys The elements of the composite key (order must match the order in XML file). + * @return void + */ + public function setPrimaryKey($keys) + { + $this->setCustomerFamilyId($keys[0]); + $this->setPromo($keys[1]); + } + + /** + * Returns true if the primary key for this object is null. + * @return boolean + */ + public function isPrimaryKeyNull() + { + + return (null === $this->getCustomerFamilyId()) && (null === $this->getPromo()); + } + + /** + * Sets contents of passed object to values from current object. + * + * If desired, this method can also make copies of all associated (fkey referrers) + * objects. + * + * @param object $copyObj An object of \CustomerFamily\Model\CustomerFamilyPrice (or compatible) type. + * @param boolean $deepCopy Whether to also copy all rows that refer (by fkey) to the current row. + * @param boolean $makeNew Whether to reset autoincrement PKs and make the object new. + * @throws PropelException + */ + public function copyInto($copyObj, $deepCopy = false, $makeNew = true) + { + $copyObj->setCustomerFamilyId($this->getCustomerFamilyId()); + $copyObj->setPromo($this->getPromo()); + $copyObj->setUseEquation($this->getUseEquation()); + $copyObj->setAmountAddedBefore($this->getAmountAddedBefore()); + $copyObj->setAmountAddedAfter($this->getAmountAddedAfter()); + $copyObj->setMultiplicationCoefficient($this->getMultiplicationCoefficient()); + $copyObj->setIsTaxed($this->getIsTaxed()); + if ($makeNew) { + $copyObj->setNew(true); + } + } + + /** + * Makes a copy of this object that will be inserted as a new row in table when saved. + * It creates a new object filling in the simple attributes, but skipping any primary + * keys that are defined for the table. + * + * If desired, this method can also make copies of all associated (fkey referrers) + * objects. + * + * @param boolean $deepCopy Whether to also copy all rows that refer (by fkey) to the current row. + * @return \CustomerFamily\Model\CustomerFamilyPrice Clone of current object. + * @throws PropelException + */ + public function copy($deepCopy = false) + { + // we use get_class(), because this might be a subclass + $clazz = get_class($this); + $copyObj = new $clazz(); + $this->copyInto($copyObj, $deepCopy); + + return $copyObj; + } + + /** + * Declares an association between this object and a ChildCustomerFamily object. + * + * @param ChildCustomerFamily $v + * @return \CustomerFamily\Model\CustomerFamilyPrice The current object (for fluent API support) + * @throws PropelException + */ + public function setCustomerFamily(ChildCustomerFamily $v = null) + { + if ($v === null) { + $this->setCustomerFamilyId(NULL); + } else { + $this->setCustomerFamilyId($v->getId()); + } + + $this->aCustomerFamily = $v; + + // Add binding for other direction of this n:n relationship. + // If this object has already been added to the ChildCustomerFamily object, it will not be re-added. + if ($v !== null) { + $v->addCustomerFamilyPrice($this); + } + + + return $this; + } + + + /** + * Get the associated ChildCustomerFamily object + * + * @param ConnectionInterface $con Optional Connection object. + * @return ChildCustomerFamily The associated ChildCustomerFamily object. + * @throws PropelException + */ + public function getCustomerFamily(ConnectionInterface $con = null) + { + if ($this->aCustomerFamily === null && ($this->customer_family_id !== null)) { + $this->aCustomerFamily = ChildCustomerFamilyQuery::create()->findPk($this->customer_family_id, $con); + /* The following can be used additionally to + guarantee the related object contains a reference + to this object. This level of coupling may, however, be + undesirable since it could result in an only partially populated collection + in the referenced object. + $this->aCustomerFamily->addCustomerFamilyPrices($this); + */ + } + + return $this->aCustomerFamily; + } + + /** + * Clears the current object and sets all attributes to their default values + */ + public function clear() + { + $this->customer_family_id = null; + $this->promo = null; + $this->use_equation = null; + $this->amount_added_before = null; + $this->amount_added_after = null; + $this->multiplication_coefficient = null; + $this->is_taxed = null; + $this->alreadyInSave = false; + $this->clearAllReferences(); + $this->applyDefaultValues(); + $this->resetModified(); + $this->setNew(true); + $this->setDeleted(false); + } + + /** + * Resets all references to other model objects or collections of model objects. + * + * This method is a user-space workaround for PHP's inability to garbage collect + * objects with circular references (even in PHP 5.3). This is currently necessary + * when using Propel in certain daemon or large-volume/high-memory operations. + * + * @param boolean $deep Whether to also clear the references on all referrer objects. + */ + public function clearAllReferences($deep = false) + { + if ($deep) { + } // if ($deep) + + $this->aCustomerFamily = null; + } + + /** + * Return the string representation of this object + * + * @return string + */ + public function __toString() + { + return (string) $this->exportTo(CustomerFamilyPriceTableMap::DEFAULT_STRING_FORMAT); + } + + /** + * Code to be run before persisting the object + * @param ConnectionInterface $con + * @return boolean + */ + public function preSave(ConnectionInterface $con = null) + { + return true; + } + + /** + * Code to be run after persisting the object + * @param ConnectionInterface $con + */ + public function postSave(ConnectionInterface $con = null) + { + + } + + /** + * Code to be run before inserting to database + * @param ConnectionInterface $con + * @return boolean + */ + public function preInsert(ConnectionInterface $con = null) + { + return true; + } + + /** + * Code to be run after inserting to database + * @param ConnectionInterface $con + */ + public function postInsert(ConnectionInterface $con = null) + { + + } + + /** + * Code to be run before updating the object in database + * @param ConnectionInterface $con + * @return boolean + */ + public function preUpdate(ConnectionInterface $con = null) + { + return true; + } + + /** + * Code to be run after updating the object in database + * @param ConnectionInterface $con + */ + public function postUpdate(ConnectionInterface $con = null) + { + + } + + /** + * Code to be run before deleting the object in database + * @param ConnectionInterface $con + * @return boolean + */ + public function preDelete(ConnectionInterface $con = null) + { + return true; + } + + /** + * Code to be run after deleting the object in database + * @param ConnectionInterface $con + */ + public function postDelete(ConnectionInterface $con = null) + { + + } + + + /** + * Derived method to catches calls to undefined methods. + * + * Provides magic import/export method support (fromXML()/toXML(), fromYAML()/toYAML(), etc.). + * Allows to define default __call() behavior if you overwrite __call() + * + * @param string $name + * @param mixed $params + * + * @return array|string + */ + public function __call($name, $params) + { + if (0 === strpos($name, 'get')) { + $virtualColumn = substr($name, 3); + if ($this->hasVirtualColumn($virtualColumn)) { + return $this->getVirtualColumn($virtualColumn); + } + + $virtualColumn = lcfirst($virtualColumn); + if ($this->hasVirtualColumn($virtualColumn)) { + return $this->getVirtualColumn($virtualColumn); + } + } + + if (0 === strpos($name, 'from')) { + $format = substr($name, 4); + + return $this->importFrom($format, reset($params)); + } + + if (0 === strpos($name, 'to')) { + $format = substr($name, 2); + $includeLazyLoadColumns = isset($params[0]) ? $params[0] : true; + + return $this->exportTo($format, $includeLazyLoadColumns); + } + + throw new BadMethodCallException(sprintf('Call to undefined method: %s.', $name)); + } + +} diff --git a/local/modules/CustomerFamily/Model/Base/CustomerFamilyPriceQuery.php b/local/modules/CustomerFamily/Model/Base/CustomerFamilyPriceQuery.php new file mode 100644 index 00000000..9445da2b --- /dev/null +++ b/local/modules/CustomerFamily/Model/Base/CustomerFamilyPriceQuery.php @@ -0,0 +1,712 @@ +setModelAlias($modelAlias); + } + if ($criteria instanceof Criteria) { + $query->mergeWith($criteria); + } + + return $query; + } + + /** + * Find object by primary key. + * Propel uses the instance pool to skip the database if the object exists. + * Go fast if the query is untouched. + * + * + * $obj = $c->findPk(array(12, 34), $con); + * + * + * @param array[$customer_family_id, $promo] $key Primary key to use for the query + * @param ConnectionInterface $con an optional connection object + * + * @return ChildCustomerFamilyPrice|array|mixed the result, formatted by the current formatter + */ + public function findPk($key, $con = null) + { + if ($key === null) { + return null; + } + if ((null !== ($obj = CustomerFamilyPriceTableMap::getInstanceFromPool(serialize(array((string) $key[0], (string) $key[1]))))) && !$this->formatter) { + // the object is already in the instance pool + return $obj; + } + if ($con === null) { + $con = Propel::getServiceContainer()->getReadConnection(CustomerFamilyPriceTableMap::DATABASE_NAME); + } + $this->basePreSelect($con); + if ($this->formatter || $this->modelAlias || $this->with || $this->select + || $this->selectColumns || $this->asColumns || $this->selectModifiers + || $this->map || $this->having || $this->joins) { + return $this->findPkComplex($key, $con); + } else { + return $this->findPkSimple($key, $con); + } + } + + /** + * Find object by primary key using raw SQL to go fast. + * Bypass doSelect() and the object formatter by using generated code. + * + * @param mixed $key Primary key to use for the query + * @param ConnectionInterface $con A connection object + * + * @return ChildCustomerFamilyPrice A model object, or null if the key is not found + */ + protected function findPkSimple($key, $con) + { + $sql = 'SELECT CUSTOMER_FAMILY_ID, PROMO, USE_EQUATION, AMOUNT_ADDED_BEFORE, AMOUNT_ADDED_AFTER, MULTIPLICATION_COEFFICIENT, IS_TAXED FROM customer_family_price WHERE CUSTOMER_FAMILY_ID = :p0 AND PROMO = :p1'; + try { + $stmt = $con->prepare($sql); + $stmt->bindValue(':p0', $key[0], PDO::PARAM_INT); + $stmt->bindValue(':p1', $key[1], PDO::PARAM_INT); + $stmt->execute(); + } catch (Exception $e) { + Propel::log($e->getMessage(), Propel::LOG_ERR); + throw new PropelException(sprintf('Unable to execute SELECT statement [%s]', $sql), 0, $e); + } + $obj = null; + if ($row = $stmt->fetch(\PDO::FETCH_NUM)) { + $obj = new ChildCustomerFamilyPrice(); + $obj->hydrate($row); + CustomerFamilyPriceTableMap::addInstanceToPool($obj, serialize(array((string) $key[0], (string) $key[1]))); + } + $stmt->closeCursor(); + + return $obj; + } + + /** + * Find object by primary key. + * + * @param mixed $key Primary key to use for the query + * @param ConnectionInterface $con A connection object + * + * @return ChildCustomerFamilyPrice|array|mixed the result, formatted by the current formatter + */ + protected function findPkComplex($key, $con) + { + // As the query uses a PK condition, no limit(1) is necessary. + $criteria = $this->isKeepQuery() ? clone $this : $this; + $dataFetcher = $criteria + ->filterByPrimaryKey($key) + ->doSelect($con); + + return $criteria->getFormatter()->init($criteria)->formatOne($dataFetcher); + } + + /** + * Find objects by primary key + * + * $objs = $c->findPks(array(array(12, 56), array(832, 123), array(123, 456)), $con); + * + * @param array $keys Primary keys to use for the query + * @param ConnectionInterface $con an optional connection object + * + * @return ObjectCollection|array|mixed the list of results, formatted by the current formatter + */ + public function findPks($keys, $con = null) + { + if (null === $con) { + $con = Propel::getServiceContainer()->getReadConnection($this->getDbName()); + } + $this->basePreSelect($con); + $criteria = $this->isKeepQuery() ? clone $this : $this; + $dataFetcher = $criteria + ->filterByPrimaryKeys($keys) + ->doSelect($con); + + return $criteria->getFormatter()->init($criteria)->format($dataFetcher); + } + + /** + * Filter the query by primary key + * + * @param mixed $key Primary key to use for the query + * + * @return ChildCustomerFamilyPriceQuery The current query, for fluid interface + */ + public function filterByPrimaryKey($key) + { + $this->addUsingAlias(CustomerFamilyPriceTableMap::CUSTOMER_FAMILY_ID, $key[0], Criteria::EQUAL); + $this->addUsingAlias(CustomerFamilyPriceTableMap::PROMO, $key[1], Criteria::EQUAL); + + return $this; + } + + /** + * Filter the query by a list of primary keys + * + * @param array $keys The list of primary key to use for the query + * + * @return ChildCustomerFamilyPriceQuery The current query, for fluid interface + */ + public function filterByPrimaryKeys($keys) + { + if (empty($keys)) { + return $this->add(null, '1<>1', Criteria::CUSTOM); + } + foreach ($keys as $key) { + $cton0 = $this->getNewCriterion(CustomerFamilyPriceTableMap::CUSTOMER_FAMILY_ID, $key[0], Criteria::EQUAL); + $cton1 = $this->getNewCriterion(CustomerFamilyPriceTableMap::PROMO, $key[1], Criteria::EQUAL); + $cton0->addAnd($cton1); + $this->addOr($cton0); + } + + return $this; + } + + /** + * Filter the query on the customer_family_id column + * + * Example usage: + * + * $query->filterByCustomerFamilyId(1234); // WHERE customer_family_id = 1234 + * $query->filterByCustomerFamilyId(array(12, 34)); // WHERE customer_family_id IN (12, 34) + * $query->filterByCustomerFamilyId(array('min' => 12)); // WHERE customer_family_id > 12 + * + * + * @see filterByCustomerFamily() + * + * @param mixed $customerFamilyId The value to use as filter. + * Use scalar values for equality. + * Use array values for in_array() equivalent. + * Use associative array('min' => $minValue, 'max' => $maxValue) for intervals. + * @param string $comparison Operator to use for the column comparison, defaults to Criteria::EQUAL + * + * @return ChildCustomerFamilyPriceQuery The current query, for fluid interface + */ + public function filterByCustomerFamilyId($customerFamilyId = null, $comparison = null) + { + if (is_array($customerFamilyId)) { + $useMinMax = false; + if (isset($customerFamilyId['min'])) { + $this->addUsingAlias(CustomerFamilyPriceTableMap::CUSTOMER_FAMILY_ID, $customerFamilyId['min'], Criteria::GREATER_EQUAL); + $useMinMax = true; + } + if (isset($customerFamilyId['max'])) { + $this->addUsingAlias(CustomerFamilyPriceTableMap::CUSTOMER_FAMILY_ID, $customerFamilyId['max'], Criteria::LESS_EQUAL); + $useMinMax = true; + } + if ($useMinMax) { + return $this; + } + if (null === $comparison) { + $comparison = Criteria::IN; + } + } + + return $this->addUsingAlias(CustomerFamilyPriceTableMap::CUSTOMER_FAMILY_ID, $customerFamilyId, $comparison); + } + + /** + * Filter the query on the promo column + * + * Example usage: + * + * $query->filterByPromo(1234); // WHERE promo = 1234 + * $query->filterByPromo(array(12, 34)); // WHERE promo IN (12, 34) + * $query->filterByPromo(array('min' => 12)); // WHERE promo > 12 + * + * + * @param mixed $promo The value to use as filter. + * Use scalar values for equality. + * Use array values for in_array() equivalent. + * Use associative array('min' => $minValue, 'max' => $maxValue) for intervals. + * @param string $comparison Operator to use for the column comparison, defaults to Criteria::EQUAL + * + * @return ChildCustomerFamilyPriceQuery The current query, for fluid interface + */ + public function filterByPromo($promo = null, $comparison = null) + { + if (is_array($promo)) { + $useMinMax = false; + if (isset($promo['min'])) { + $this->addUsingAlias(CustomerFamilyPriceTableMap::PROMO, $promo['min'], Criteria::GREATER_EQUAL); + $useMinMax = true; + } + if (isset($promo['max'])) { + $this->addUsingAlias(CustomerFamilyPriceTableMap::PROMO, $promo['max'], Criteria::LESS_EQUAL); + $useMinMax = true; + } + if ($useMinMax) { + return $this; + } + if (null === $comparison) { + $comparison = Criteria::IN; + } + } + + return $this->addUsingAlias(CustomerFamilyPriceTableMap::PROMO, $promo, $comparison); + } + + /** + * Filter the query on the use_equation column + * + * Example usage: + * + * $query->filterByUseEquation(1234); // WHERE use_equation = 1234 + * $query->filterByUseEquation(array(12, 34)); // WHERE use_equation IN (12, 34) + * $query->filterByUseEquation(array('min' => 12)); // WHERE use_equation > 12 + * + * + * @param mixed $useEquation The value to use as filter. + * Use scalar values for equality. + * Use array values for in_array() equivalent. + * Use associative array('min' => $minValue, 'max' => $maxValue) for intervals. + * @param string $comparison Operator to use for the column comparison, defaults to Criteria::EQUAL + * + * @return ChildCustomerFamilyPriceQuery The current query, for fluid interface + */ + public function filterByUseEquation($useEquation = null, $comparison = null) + { + if (is_array($useEquation)) { + $useMinMax = false; + if (isset($useEquation['min'])) { + $this->addUsingAlias(CustomerFamilyPriceTableMap::USE_EQUATION, $useEquation['min'], Criteria::GREATER_EQUAL); + $useMinMax = true; + } + if (isset($useEquation['max'])) { + $this->addUsingAlias(CustomerFamilyPriceTableMap::USE_EQUATION, $useEquation['max'], Criteria::LESS_EQUAL); + $useMinMax = true; + } + if ($useMinMax) { + return $this; + } + if (null === $comparison) { + $comparison = Criteria::IN; + } + } + + return $this->addUsingAlias(CustomerFamilyPriceTableMap::USE_EQUATION, $useEquation, $comparison); + } + + /** + * Filter the query on the amount_added_before column + * + * Example usage: + * + * $query->filterByAmountAddedBefore(1234); // WHERE amount_added_before = 1234 + * $query->filterByAmountAddedBefore(array(12, 34)); // WHERE amount_added_before IN (12, 34) + * $query->filterByAmountAddedBefore(array('min' => 12)); // WHERE amount_added_before > 12 + * + * + * @param mixed $amountAddedBefore The value to use as filter. + * Use scalar values for equality. + * Use array values for in_array() equivalent. + * Use associative array('min' => $minValue, 'max' => $maxValue) for intervals. + * @param string $comparison Operator to use for the column comparison, defaults to Criteria::EQUAL + * + * @return ChildCustomerFamilyPriceQuery The current query, for fluid interface + */ + public function filterByAmountAddedBefore($amountAddedBefore = null, $comparison = null) + { + if (is_array($amountAddedBefore)) { + $useMinMax = false; + if (isset($amountAddedBefore['min'])) { + $this->addUsingAlias(CustomerFamilyPriceTableMap::AMOUNT_ADDED_BEFORE, $amountAddedBefore['min'], Criteria::GREATER_EQUAL); + $useMinMax = true; + } + if (isset($amountAddedBefore['max'])) { + $this->addUsingAlias(CustomerFamilyPriceTableMap::AMOUNT_ADDED_BEFORE, $amountAddedBefore['max'], Criteria::LESS_EQUAL); + $useMinMax = true; + } + if ($useMinMax) { + return $this; + } + if (null === $comparison) { + $comparison = Criteria::IN; + } + } + + return $this->addUsingAlias(CustomerFamilyPriceTableMap::AMOUNT_ADDED_BEFORE, $amountAddedBefore, $comparison); + } + + /** + * Filter the query on the amount_added_after column + * + * Example usage: + * + * $query->filterByAmountAddedAfter(1234); // WHERE amount_added_after = 1234 + * $query->filterByAmountAddedAfter(array(12, 34)); // WHERE amount_added_after IN (12, 34) + * $query->filterByAmountAddedAfter(array('min' => 12)); // WHERE amount_added_after > 12 + * + * + * @param mixed $amountAddedAfter The value to use as filter. + * Use scalar values for equality. + * Use array values for in_array() equivalent. + * Use associative array('min' => $minValue, 'max' => $maxValue) for intervals. + * @param string $comparison Operator to use for the column comparison, defaults to Criteria::EQUAL + * + * @return ChildCustomerFamilyPriceQuery The current query, for fluid interface + */ + public function filterByAmountAddedAfter($amountAddedAfter = null, $comparison = null) + { + if (is_array($amountAddedAfter)) { + $useMinMax = false; + if (isset($amountAddedAfter['min'])) { + $this->addUsingAlias(CustomerFamilyPriceTableMap::AMOUNT_ADDED_AFTER, $amountAddedAfter['min'], Criteria::GREATER_EQUAL); + $useMinMax = true; + } + if (isset($amountAddedAfter['max'])) { + $this->addUsingAlias(CustomerFamilyPriceTableMap::AMOUNT_ADDED_AFTER, $amountAddedAfter['max'], Criteria::LESS_EQUAL); + $useMinMax = true; + } + if ($useMinMax) { + return $this; + } + if (null === $comparison) { + $comparison = Criteria::IN; + } + } + + return $this->addUsingAlias(CustomerFamilyPriceTableMap::AMOUNT_ADDED_AFTER, $amountAddedAfter, $comparison); + } + + /** + * Filter the query on the multiplication_coefficient column + * + * Example usage: + * + * $query->filterByMultiplicationCoefficient(1234); // WHERE multiplication_coefficient = 1234 + * $query->filterByMultiplicationCoefficient(array(12, 34)); // WHERE multiplication_coefficient IN (12, 34) + * $query->filterByMultiplicationCoefficient(array('min' => 12)); // WHERE multiplication_coefficient > 12 + * + * + * @param mixed $multiplicationCoefficient The value to use as filter. + * Use scalar values for equality. + * Use array values for in_array() equivalent. + * Use associative array('min' => $minValue, 'max' => $maxValue) for intervals. + * @param string $comparison Operator to use for the column comparison, defaults to Criteria::EQUAL + * + * @return ChildCustomerFamilyPriceQuery The current query, for fluid interface + */ + public function filterByMultiplicationCoefficient($multiplicationCoefficient = null, $comparison = null) + { + if (is_array($multiplicationCoefficient)) { + $useMinMax = false; + if (isset($multiplicationCoefficient['min'])) { + $this->addUsingAlias(CustomerFamilyPriceTableMap::MULTIPLICATION_COEFFICIENT, $multiplicationCoefficient['min'], Criteria::GREATER_EQUAL); + $useMinMax = true; + } + if (isset($multiplicationCoefficient['max'])) { + $this->addUsingAlias(CustomerFamilyPriceTableMap::MULTIPLICATION_COEFFICIENT, $multiplicationCoefficient['max'], Criteria::LESS_EQUAL); + $useMinMax = true; + } + if ($useMinMax) { + return $this; + } + if (null === $comparison) { + $comparison = Criteria::IN; + } + } + + return $this->addUsingAlias(CustomerFamilyPriceTableMap::MULTIPLICATION_COEFFICIENT, $multiplicationCoefficient, $comparison); + } + + /** + * Filter the query on the is_taxed column + * + * Example usage: + * + * $query->filterByIsTaxed(1234); // WHERE is_taxed = 1234 + * $query->filterByIsTaxed(array(12, 34)); // WHERE is_taxed IN (12, 34) + * $query->filterByIsTaxed(array('min' => 12)); // WHERE is_taxed > 12 + * + * + * @param mixed $isTaxed The value to use as filter. + * Use scalar values for equality. + * Use array values for in_array() equivalent. + * Use associative array('min' => $minValue, 'max' => $maxValue) for intervals. + * @param string $comparison Operator to use for the column comparison, defaults to Criteria::EQUAL + * + * @return ChildCustomerFamilyPriceQuery The current query, for fluid interface + */ + public function filterByIsTaxed($isTaxed = null, $comparison = null) + { + if (is_array($isTaxed)) { + $useMinMax = false; + if (isset($isTaxed['min'])) { + $this->addUsingAlias(CustomerFamilyPriceTableMap::IS_TAXED, $isTaxed['min'], Criteria::GREATER_EQUAL); + $useMinMax = true; + } + if (isset($isTaxed['max'])) { + $this->addUsingAlias(CustomerFamilyPriceTableMap::IS_TAXED, $isTaxed['max'], Criteria::LESS_EQUAL); + $useMinMax = true; + } + if ($useMinMax) { + return $this; + } + if (null === $comparison) { + $comparison = Criteria::IN; + } + } + + return $this->addUsingAlias(CustomerFamilyPriceTableMap::IS_TAXED, $isTaxed, $comparison); + } + + /** + * Filter the query by a related \CustomerFamily\Model\CustomerFamily object + * + * @param \CustomerFamily\Model\CustomerFamily|ObjectCollection $customerFamily The related object(s) to use as filter + * @param string $comparison Operator to use for the column comparison, defaults to Criteria::EQUAL + * + * @return ChildCustomerFamilyPriceQuery The current query, for fluid interface + */ + public function filterByCustomerFamily($customerFamily, $comparison = null) + { + if ($customerFamily instanceof \CustomerFamily\Model\CustomerFamily) { + return $this + ->addUsingAlias(CustomerFamilyPriceTableMap::CUSTOMER_FAMILY_ID, $customerFamily->getId(), $comparison); + } elseif ($customerFamily instanceof ObjectCollection) { + if (null === $comparison) { + $comparison = Criteria::IN; + } + + return $this + ->addUsingAlias(CustomerFamilyPriceTableMap::CUSTOMER_FAMILY_ID, $customerFamily->toKeyValue('PrimaryKey', 'Id'), $comparison); + } else { + throw new PropelException('filterByCustomerFamily() only accepts arguments of type \CustomerFamily\Model\CustomerFamily or Collection'); + } + } + + /** + * Adds a JOIN clause to the query using the CustomerFamily relation + * + * @param string $relationAlias optional alias for the relation + * @param string $joinType Accepted values are null, 'left join', 'right join', 'inner join' + * + * @return ChildCustomerFamilyPriceQuery The current query, for fluid interface + */ + public function joinCustomerFamily($relationAlias = null, $joinType = Criteria::INNER_JOIN) + { + $tableMap = $this->getTableMap(); + $relationMap = $tableMap->getRelation('CustomerFamily'); + + // create a ModelJoin object for this join + $join = new ModelJoin(); + $join->setJoinType($joinType); + $join->setRelationMap($relationMap, $this->useAliasInSQL ? $this->getModelAlias() : null, $relationAlias); + if ($previousJoin = $this->getPreviousJoin()) { + $join->setPreviousJoin($previousJoin); + } + + // add the ModelJoin to the current object + if ($relationAlias) { + $this->addAlias($relationAlias, $relationMap->getRightTable()->getName()); + $this->addJoinObject($join, $relationAlias); + } else { + $this->addJoinObject($join, 'CustomerFamily'); + } + + return $this; + } + + /** + * Use the CustomerFamily relation CustomerFamily object + * + * @see useQuery() + * + * @param string $relationAlias optional alias for the relation, + * to be used as main alias in the secondary query + * @param string $joinType Accepted values are null, 'left join', 'right join', 'inner join' + * + * @return \CustomerFamily\Model\CustomerFamilyQuery A secondary query class using the current class as primary query + */ + public function useCustomerFamilyQuery($relationAlias = null, $joinType = Criteria::INNER_JOIN) + { + return $this + ->joinCustomerFamily($relationAlias, $joinType) + ->useQuery($relationAlias ? $relationAlias : 'CustomerFamily', '\CustomerFamily\Model\CustomerFamilyQuery'); + } + + /** + * Exclude object from result + * + * @param ChildCustomerFamilyPrice $customerFamilyPrice Object to remove from the list of results + * + * @return ChildCustomerFamilyPriceQuery The current query, for fluid interface + */ + public function prune($customerFamilyPrice = null) + { + if ($customerFamilyPrice) { + $this->addCond('pruneCond0', $this->getAliasedColName(CustomerFamilyPriceTableMap::CUSTOMER_FAMILY_ID), $customerFamilyPrice->getCustomerFamilyId(), Criteria::NOT_EQUAL); + $this->addCond('pruneCond1', $this->getAliasedColName(CustomerFamilyPriceTableMap::PROMO), $customerFamilyPrice->getPromo(), Criteria::NOT_EQUAL); + $this->combine(array('pruneCond0', 'pruneCond1'), Criteria::LOGICAL_OR); + } + + return $this; + } + + /** + * Deletes all rows from the customer_family_price table. + * + * @param ConnectionInterface $con the connection to use + * @return int The number of affected rows (if supported by underlying database driver). + */ + public function doDeleteAll(ConnectionInterface $con = null) + { + if (null === $con) { + $con = Propel::getServiceContainer()->getWriteConnection(CustomerFamilyPriceTableMap::DATABASE_NAME); + } + $affectedRows = 0; // initialize var to track total num of affected rows + try { + // use transaction because $criteria could contain info + // for more than one table or we could emulating ON DELETE CASCADE, etc. + $con->beginTransaction(); + $affectedRows += parent::doDeleteAll($con); + // Because this db requires some delete cascade/set null emulation, we have to + // clear the cached instance *after* the emulation has happened (since + // instances get re-added by the select statement contained therein). + CustomerFamilyPriceTableMap::clearInstancePool(); + CustomerFamilyPriceTableMap::clearRelatedInstancePool(); + + $con->commit(); + } catch (PropelException $e) { + $con->rollBack(); + throw $e; + } + + return $affectedRows; + } + + /** + * Performs a DELETE on the database, given a ChildCustomerFamilyPrice or Criteria object OR a primary key value. + * + * @param mixed $values Criteria or ChildCustomerFamilyPrice object or primary key or array of primary keys + * which is used to create the DELETE statement + * @param ConnectionInterface $con the connection to use + * @return int The number of affected rows (if supported by underlying database driver). This includes CASCADE-related rows + * if supported by native driver or if emulated using Propel. + * @throws PropelException Any exceptions caught during processing will be + * rethrown wrapped into a PropelException. + */ + public function delete(ConnectionInterface $con = null) + { + if (null === $con) { + $con = Propel::getServiceContainer()->getWriteConnection(CustomerFamilyPriceTableMap::DATABASE_NAME); + } + + $criteria = $this; + + // Set the correct dbName + $criteria->setDbName(CustomerFamilyPriceTableMap::DATABASE_NAME); + + $affectedRows = 0; // initialize var to track total num of affected rows + + try { + // use transaction because $criteria could contain info + // for more than one table or we could emulating ON DELETE CASCADE, etc. + $con->beginTransaction(); + + + CustomerFamilyPriceTableMap::removeInstanceFromPool($criteria); + + $affectedRows += ModelCriteria::delete($con); + CustomerFamilyPriceTableMap::clearRelatedInstancePool(); + $con->commit(); + + return $affectedRows; + } catch (PropelException $e) { + $con->rollBack(); + throw $e; + } + } + +} // CustomerFamilyPriceQuery diff --git a/local/modules/CustomerFamily/Model/Base/CustomerFamilyQuery.php b/local/modules/CustomerFamily/Model/Base/CustomerFamilyQuery.php new file mode 100644 index 00000000..35d19ead --- /dev/null +++ b/local/modules/CustomerFamily/Model/Base/CustomerFamilyQuery.php @@ -0,0 +1,1195 @@ +setModelAlias($modelAlias); + } + if ($criteria instanceof Criteria) { + $query->mergeWith($criteria); + } + + return $query; + } + + /** + * Find object by primary key. + * Propel uses the instance pool to skip the database if the object exists. + * Go fast if the query is untouched. + * + * + * $obj = $c->findPk(12, $con); + * + * + * @param mixed $key Primary key to use for the query + * @param ConnectionInterface $con an optional connection object + * + * @return ChildCustomerFamily|array|mixed the result, formatted by the current formatter + */ + public function findPk($key, $con = null) + { + if ($key === null) { + return null; + } + if ((null !== ($obj = CustomerFamilyTableMap::getInstanceFromPool((string) $key))) && !$this->formatter) { + // the object is already in the instance pool + return $obj; + } + if ($con === null) { + $con = Propel::getServiceContainer()->getReadConnection(CustomerFamilyTableMap::DATABASE_NAME); + } + $this->basePreSelect($con); + if ($this->formatter || $this->modelAlias || $this->with || $this->select + || $this->selectColumns || $this->asColumns || $this->selectModifiers + || $this->map || $this->having || $this->joins) { + return $this->findPkComplex($key, $con); + } else { + return $this->findPkSimple($key, $con); + } + } + + /** + * Find object by primary key using raw SQL to go fast. + * Bypass doSelect() and the object formatter by using generated code. + * + * @param mixed $key Primary key to use for the query + * @param ConnectionInterface $con A connection object + * + * @return ChildCustomerFamily A model object, or null if the key is not found + */ + protected function findPkSimple($key, $con) + { + $sql = 'SELECT ID, CODE, CATEGORY_RESTRICTION_ENABLED, BRAND_RESTRICTION_ENABLED, IS_DEFAULT, CREATED_AT, UPDATED_AT FROM customer_family WHERE ID = :p0'; + try { + $stmt = $con->prepare($sql); + $stmt->bindValue(':p0', $key, PDO::PARAM_INT); + $stmt->execute(); + } catch (Exception $e) { + Propel::log($e->getMessage(), Propel::LOG_ERR); + throw new PropelException(sprintf('Unable to execute SELECT statement [%s]', $sql), 0, $e); + } + $obj = null; + if ($row = $stmt->fetch(\PDO::FETCH_NUM)) { + $obj = new ChildCustomerFamily(); + $obj->hydrate($row); + CustomerFamilyTableMap::addInstanceToPool($obj, (string) $key); + } + $stmt->closeCursor(); + + return $obj; + } + + /** + * Find object by primary key. + * + * @param mixed $key Primary key to use for the query + * @param ConnectionInterface $con A connection object + * + * @return ChildCustomerFamily|array|mixed the result, formatted by the current formatter + */ + protected function findPkComplex($key, $con) + { + // As the query uses a PK condition, no limit(1) is necessary. + $criteria = $this->isKeepQuery() ? clone $this : $this; + $dataFetcher = $criteria + ->filterByPrimaryKey($key) + ->doSelect($con); + + return $criteria->getFormatter()->init($criteria)->formatOne($dataFetcher); + } + + /** + * Find objects by primary key + * + * $objs = $c->findPks(array(12, 56, 832), $con); + * + * @param array $keys Primary keys to use for the query + * @param ConnectionInterface $con an optional connection object + * + * @return ObjectCollection|array|mixed the list of results, formatted by the current formatter + */ + public function findPks($keys, $con = null) + { + if (null === $con) { + $con = Propel::getServiceContainer()->getReadConnection($this->getDbName()); + } + $this->basePreSelect($con); + $criteria = $this->isKeepQuery() ? clone $this : $this; + $dataFetcher = $criteria + ->filterByPrimaryKeys($keys) + ->doSelect($con); + + return $criteria->getFormatter()->init($criteria)->format($dataFetcher); + } + + /** + * Filter the query by primary key + * + * @param mixed $key Primary key to use for the query + * + * @return ChildCustomerFamilyQuery The current query, for fluid interface + */ + public function filterByPrimaryKey($key) + { + + return $this->addUsingAlias(CustomerFamilyTableMap::ID, $key, Criteria::EQUAL); + } + + /** + * Filter the query by a list of primary keys + * + * @param array $keys The list of primary key to use for the query + * + * @return ChildCustomerFamilyQuery The current query, for fluid interface + */ + public function filterByPrimaryKeys($keys) + { + + return $this->addUsingAlias(CustomerFamilyTableMap::ID, $keys, Criteria::IN); + } + + /** + * Filter the query on the id column + * + * Example usage: + * + * $query->filterById(1234); // WHERE id = 1234 + * $query->filterById(array(12, 34)); // WHERE id IN (12, 34) + * $query->filterById(array('min' => 12)); // WHERE id > 12 + * + * + * @param mixed $id The value to use as filter. + * Use scalar values for equality. + * Use array values for in_array() equivalent. + * Use associative array('min' => $minValue, 'max' => $maxValue) for intervals. + * @param string $comparison Operator to use for the column comparison, defaults to Criteria::EQUAL + * + * @return ChildCustomerFamilyQuery The current query, for fluid interface + */ + public function filterById($id = null, $comparison = null) + { + if (is_array($id)) { + $useMinMax = false; + if (isset($id['min'])) { + $this->addUsingAlias(CustomerFamilyTableMap::ID, $id['min'], Criteria::GREATER_EQUAL); + $useMinMax = true; + } + if (isset($id['max'])) { + $this->addUsingAlias(CustomerFamilyTableMap::ID, $id['max'], Criteria::LESS_EQUAL); + $useMinMax = true; + } + if ($useMinMax) { + return $this; + } + if (null === $comparison) { + $comparison = Criteria::IN; + } + } + + return $this->addUsingAlias(CustomerFamilyTableMap::ID, $id, $comparison); + } + + /** + * Filter the query on the code column + * + * Example usage: + * + * $query->filterByCode('fooValue'); // WHERE code = 'fooValue' + * $query->filterByCode('%fooValue%'); // WHERE code LIKE '%fooValue%' + * + * + * @param string $code The value to use as filter. + * Accepts wildcards (* and % trigger a LIKE) + * @param string $comparison Operator to use for the column comparison, defaults to Criteria::EQUAL + * + * @return ChildCustomerFamilyQuery The current query, for fluid interface + */ + public function filterByCode($code = null, $comparison = null) + { + if (null === $comparison) { + if (is_array($code)) { + $comparison = Criteria::IN; + } elseif (preg_match('/[\%\*]/', $code)) { + $code = str_replace('*', '%', $code); + $comparison = Criteria::LIKE; + } + } + + return $this->addUsingAlias(CustomerFamilyTableMap::CODE, $code, $comparison); + } + + /** + * Filter the query on the category_restriction_enabled column + * + * Example usage: + * + * $query->filterByCategoryRestrictionEnabled(1234); // WHERE category_restriction_enabled = 1234 + * $query->filterByCategoryRestrictionEnabled(array(12, 34)); // WHERE category_restriction_enabled IN (12, 34) + * $query->filterByCategoryRestrictionEnabled(array('min' => 12)); // WHERE category_restriction_enabled > 12 + * + * + * @param mixed $categoryRestrictionEnabled The value to use as filter. + * Use scalar values for equality. + * Use array values for in_array() equivalent. + * Use associative array('min' => $minValue, 'max' => $maxValue) for intervals. + * @param string $comparison Operator to use for the column comparison, defaults to Criteria::EQUAL + * + * @return ChildCustomerFamilyQuery The current query, for fluid interface + */ + public function filterByCategoryRestrictionEnabled($categoryRestrictionEnabled = null, $comparison = null) + { + if (is_array($categoryRestrictionEnabled)) { + $useMinMax = false; + if (isset($categoryRestrictionEnabled['min'])) { + $this->addUsingAlias(CustomerFamilyTableMap::CATEGORY_RESTRICTION_ENABLED, $categoryRestrictionEnabled['min'], Criteria::GREATER_EQUAL); + $useMinMax = true; + } + if (isset($categoryRestrictionEnabled['max'])) { + $this->addUsingAlias(CustomerFamilyTableMap::CATEGORY_RESTRICTION_ENABLED, $categoryRestrictionEnabled['max'], Criteria::LESS_EQUAL); + $useMinMax = true; + } + if ($useMinMax) { + return $this; + } + if (null === $comparison) { + $comparison = Criteria::IN; + } + } + + return $this->addUsingAlias(CustomerFamilyTableMap::CATEGORY_RESTRICTION_ENABLED, $categoryRestrictionEnabled, $comparison); + } + + /** + * Filter the query on the brand_restriction_enabled column + * + * Example usage: + * + * $query->filterByBrandRestrictionEnabled(1234); // WHERE brand_restriction_enabled = 1234 + * $query->filterByBrandRestrictionEnabled(array(12, 34)); // WHERE brand_restriction_enabled IN (12, 34) + * $query->filterByBrandRestrictionEnabled(array('min' => 12)); // WHERE brand_restriction_enabled > 12 + * + * + * @param mixed $brandRestrictionEnabled The value to use as filter. + * Use scalar values for equality. + * Use array values for in_array() equivalent. + * Use associative array('min' => $minValue, 'max' => $maxValue) for intervals. + * @param string $comparison Operator to use for the column comparison, defaults to Criteria::EQUAL + * + * @return ChildCustomerFamilyQuery The current query, for fluid interface + */ + public function filterByBrandRestrictionEnabled($brandRestrictionEnabled = null, $comparison = null) + { + if (is_array($brandRestrictionEnabled)) { + $useMinMax = false; + if (isset($brandRestrictionEnabled['min'])) { + $this->addUsingAlias(CustomerFamilyTableMap::BRAND_RESTRICTION_ENABLED, $brandRestrictionEnabled['min'], Criteria::GREATER_EQUAL); + $useMinMax = true; + } + if (isset($brandRestrictionEnabled['max'])) { + $this->addUsingAlias(CustomerFamilyTableMap::BRAND_RESTRICTION_ENABLED, $brandRestrictionEnabled['max'], Criteria::LESS_EQUAL); + $useMinMax = true; + } + if ($useMinMax) { + return $this; + } + if (null === $comparison) { + $comparison = Criteria::IN; + } + } + + return $this->addUsingAlias(CustomerFamilyTableMap::BRAND_RESTRICTION_ENABLED, $brandRestrictionEnabled, $comparison); + } + + /** + * Filter the query on the is_default column + * + * Example usage: + * + * $query->filterByIsDefault(1234); // WHERE is_default = 1234 + * $query->filterByIsDefault(array(12, 34)); // WHERE is_default IN (12, 34) + * $query->filterByIsDefault(array('min' => 12)); // WHERE is_default > 12 + * + * + * @param mixed $isDefault The value to use as filter. + * Use scalar values for equality. + * Use array values for in_array() equivalent. + * Use associative array('min' => $minValue, 'max' => $maxValue) for intervals. + * @param string $comparison Operator to use for the column comparison, defaults to Criteria::EQUAL + * + * @return ChildCustomerFamilyQuery The current query, for fluid interface + */ + public function filterByIsDefault($isDefault = null, $comparison = null) + { + if (is_array($isDefault)) { + $useMinMax = false; + if (isset($isDefault['min'])) { + $this->addUsingAlias(CustomerFamilyTableMap::IS_DEFAULT, $isDefault['min'], Criteria::GREATER_EQUAL); + $useMinMax = true; + } + if (isset($isDefault['max'])) { + $this->addUsingAlias(CustomerFamilyTableMap::IS_DEFAULT, $isDefault['max'], Criteria::LESS_EQUAL); + $useMinMax = true; + } + if ($useMinMax) { + return $this; + } + if (null === $comparison) { + $comparison = Criteria::IN; + } + } + + return $this->addUsingAlias(CustomerFamilyTableMap::IS_DEFAULT, $isDefault, $comparison); + } + + /** + * Filter the query on the created_at column + * + * Example usage: + * + * $query->filterByCreatedAt('2011-03-14'); // WHERE created_at = '2011-03-14' + * $query->filterByCreatedAt('now'); // WHERE created_at = '2011-03-14' + * $query->filterByCreatedAt(array('max' => 'yesterday')); // WHERE created_at > '2011-03-13' + * + * + * @param mixed $createdAt The value to use as filter. + * Values can be integers (unix timestamps), DateTime objects, or strings. + * Empty strings are treated as NULL. + * Use scalar values for equality. + * Use array values for in_array() equivalent. + * Use associative array('min' => $minValue, 'max' => $maxValue) for intervals. + * @param string $comparison Operator to use for the column comparison, defaults to Criteria::EQUAL + * + * @return ChildCustomerFamilyQuery The current query, for fluid interface + */ + public function filterByCreatedAt($createdAt = null, $comparison = null) + { + if (is_array($createdAt)) { + $useMinMax = false; + if (isset($createdAt['min'])) { + $this->addUsingAlias(CustomerFamilyTableMap::CREATED_AT, $createdAt['min'], Criteria::GREATER_EQUAL); + $useMinMax = true; + } + if (isset($createdAt['max'])) { + $this->addUsingAlias(CustomerFamilyTableMap::CREATED_AT, $createdAt['max'], Criteria::LESS_EQUAL); + $useMinMax = true; + } + if ($useMinMax) { + return $this; + } + if (null === $comparison) { + $comparison = Criteria::IN; + } + } + + return $this->addUsingAlias(CustomerFamilyTableMap::CREATED_AT, $createdAt, $comparison); + } + + /** + * Filter the query on the updated_at column + * + * Example usage: + * + * $query->filterByUpdatedAt('2011-03-14'); // WHERE updated_at = '2011-03-14' + * $query->filterByUpdatedAt('now'); // WHERE updated_at = '2011-03-14' + * $query->filterByUpdatedAt(array('max' => 'yesterday')); // WHERE updated_at > '2011-03-13' + * + * + * @param mixed $updatedAt The value to use as filter. + * Values can be integers (unix timestamps), DateTime objects, or strings. + * Empty strings are treated as NULL. + * Use scalar values for equality. + * Use array values for in_array() equivalent. + * Use associative array('min' => $minValue, 'max' => $maxValue) for intervals. + * @param string $comparison Operator to use for the column comparison, defaults to Criteria::EQUAL + * + * @return ChildCustomerFamilyQuery The current query, for fluid interface + */ + public function filterByUpdatedAt($updatedAt = null, $comparison = null) + { + if (is_array($updatedAt)) { + $useMinMax = false; + if (isset($updatedAt['min'])) { + $this->addUsingAlias(CustomerFamilyTableMap::UPDATED_AT, $updatedAt['min'], Criteria::GREATER_EQUAL); + $useMinMax = true; + } + if (isset($updatedAt['max'])) { + $this->addUsingAlias(CustomerFamilyTableMap::UPDATED_AT, $updatedAt['max'], Criteria::LESS_EQUAL); + $useMinMax = true; + } + if ($useMinMax) { + return $this; + } + if (null === $comparison) { + $comparison = Criteria::IN; + } + } + + return $this->addUsingAlias(CustomerFamilyTableMap::UPDATED_AT, $updatedAt, $comparison); + } + + /** + * Filter the query by a related \CustomerFamily\Model\CustomerCustomerFamily object + * + * @param \CustomerFamily\Model\CustomerCustomerFamily|ObjectCollection $customerCustomerFamily the related object to use as filter + * @param string $comparison Operator to use for the column comparison, defaults to Criteria::EQUAL + * + * @return ChildCustomerFamilyQuery The current query, for fluid interface + */ + public function filterByCustomerCustomerFamily($customerCustomerFamily, $comparison = null) + { + if ($customerCustomerFamily instanceof \CustomerFamily\Model\CustomerCustomerFamily) { + return $this + ->addUsingAlias(CustomerFamilyTableMap::ID, $customerCustomerFamily->getCustomerFamilyId(), $comparison); + } elseif ($customerCustomerFamily instanceof ObjectCollection) { + return $this + ->useCustomerCustomerFamilyQuery() + ->filterByPrimaryKeys($customerCustomerFamily->getPrimaryKeys()) + ->endUse(); + } else { + throw new PropelException('filterByCustomerCustomerFamily() only accepts arguments of type \CustomerFamily\Model\CustomerCustomerFamily or Collection'); + } + } + + /** + * Adds a JOIN clause to the query using the CustomerCustomerFamily relation + * + * @param string $relationAlias optional alias for the relation + * @param string $joinType Accepted values are null, 'left join', 'right join', 'inner join' + * + * @return ChildCustomerFamilyQuery The current query, for fluid interface + */ + public function joinCustomerCustomerFamily($relationAlias = null, $joinType = Criteria::INNER_JOIN) + { + $tableMap = $this->getTableMap(); + $relationMap = $tableMap->getRelation('CustomerCustomerFamily'); + + // create a ModelJoin object for this join + $join = new ModelJoin(); + $join->setJoinType($joinType); + $join->setRelationMap($relationMap, $this->useAliasInSQL ? $this->getModelAlias() : null, $relationAlias); + if ($previousJoin = $this->getPreviousJoin()) { + $join->setPreviousJoin($previousJoin); + } + + // add the ModelJoin to the current object + if ($relationAlias) { + $this->addAlias($relationAlias, $relationMap->getRightTable()->getName()); + $this->addJoinObject($join, $relationAlias); + } else { + $this->addJoinObject($join, 'CustomerCustomerFamily'); + } + + return $this; + } + + /** + * Use the CustomerCustomerFamily relation CustomerCustomerFamily object + * + * @see useQuery() + * + * @param string $relationAlias optional alias for the relation, + * to be used as main alias in the secondary query + * @param string $joinType Accepted values are null, 'left join', 'right join', 'inner join' + * + * @return \CustomerFamily\Model\CustomerCustomerFamilyQuery A secondary query class using the current class as primary query + */ + public function useCustomerCustomerFamilyQuery($relationAlias = null, $joinType = Criteria::INNER_JOIN) + { + return $this + ->joinCustomerCustomerFamily($relationAlias, $joinType) + ->useQuery($relationAlias ? $relationAlias : 'CustomerCustomerFamily', '\CustomerFamily\Model\CustomerCustomerFamilyQuery'); + } + + /** + * Filter the query by a related \CustomerFamily\Model\CustomerFamilyPrice object + * + * @param \CustomerFamily\Model\CustomerFamilyPrice|ObjectCollection $customerFamilyPrice the related object to use as filter + * @param string $comparison Operator to use for the column comparison, defaults to Criteria::EQUAL + * + * @return ChildCustomerFamilyQuery The current query, for fluid interface + */ + public function filterByCustomerFamilyPrice($customerFamilyPrice, $comparison = null) + { + if ($customerFamilyPrice instanceof \CustomerFamily\Model\CustomerFamilyPrice) { + return $this + ->addUsingAlias(CustomerFamilyTableMap::ID, $customerFamilyPrice->getCustomerFamilyId(), $comparison); + } elseif ($customerFamilyPrice instanceof ObjectCollection) { + return $this + ->useCustomerFamilyPriceQuery() + ->filterByPrimaryKeys($customerFamilyPrice->getPrimaryKeys()) + ->endUse(); + } else { + throw new PropelException('filterByCustomerFamilyPrice() only accepts arguments of type \CustomerFamily\Model\CustomerFamilyPrice or Collection'); + } + } + + /** + * Adds a JOIN clause to the query using the CustomerFamilyPrice relation + * + * @param string $relationAlias optional alias for the relation + * @param string $joinType Accepted values are null, 'left join', 'right join', 'inner join' + * + * @return ChildCustomerFamilyQuery The current query, for fluid interface + */ + public function joinCustomerFamilyPrice($relationAlias = null, $joinType = Criteria::INNER_JOIN) + { + $tableMap = $this->getTableMap(); + $relationMap = $tableMap->getRelation('CustomerFamilyPrice'); + + // create a ModelJoin object for this join + $join = new ModelJoin(); + $join->setJoinType($joinType); + $join->setRelationMap($relationMap, $this->useAliasInSQL ? $this->getModelAlias() : null, $relationAlias); + if ($previousJoin = $this->getPreviousJoin()) { + $join->setPreviousJoin($previousJoin); + } + + // add the ModelJoin to the current object + if ($relationAlias) { + $this->addAlias($relationAlias, $relationMap->getRightTable()->getName()); + $this->addJoinObject($join, $relationAlias); + } else { + $this->addJoinObject($join, 'CustomerFamilyPrice'); + } + + return $this; + } + + /** + * Use the CustomerFamilyPrice relation CustomerFamilyPrice object + * + * @see useQuery() + * + * @param string $relationAlias optional alias for the relation, + * to be used as main alias in the secondary query + * @param string $joinType Accepted values are null, 'left join', 'right join', 'inner join' + * + * @return \CustomerFamily\Model\CustomerFamilyPriceQuery A secondary query class using the current class as primary query + */ + public function useCustomerFamilyPriceQuery($relationAlias = null, $joinType = Criteria::INNER_JOIN) + { + return $this + ->joinCustomerFamilyPrice($relationAlias, $joinType) + ->useQuery($relationAlias ? $relationAlias : 'CustomerFamilyPrice', '\CustomerFamily\Model\CustomerFamilyPriceQuery'); + } + + /** + * Filter the query by a related \CustomerFamily\Model\CustomerFamilyOrder object + * + * @param \CustomerFamily\Model\CustomerFamilyOrder|ObjectCollection $customerFamilyOrder the related object to use as filter + * @param string $comparison Operator to use for the column comparison, defaults to Criteria::EQUAL + * + * @return ChildCustomerFamilyQuery The current query, for fluid interface + */ + public function filterByCustomerFamilyOrder($customerFamilyOrder, $comparison = null) + { + if ($customerFamilyOrder instanceof \CustomerFamily\Model\CustomerFamilyOrder) { + return $this + ->addUsingAlias(CustomerFamilyTableMap::ID, $customerFamilyOrder->getCustomerFamilyId(), $comparison); + } elseif ($customerFamilyOrder instanceof ObjectCollection) { + return $this + ->useCustomerFamilyOrderQuery() + ->filterByPrimaryKeys($customerFamilyOrder->getPrimaryKeys()) + ->endUse(); + } else { + throw new PropelException('filterByCustomerFamilyOrder() only accepts arguments of type \CustomerFamily\Model\CustomerFamilyOrder or Collection'); + } + } + + /** + * Adds a JOIN clause to the query using the CustomerFamilyOrder relation + * + * @param string $relationAlias optional alias for the relation + * @param string $joinType Accepted values are null, 'left join', 'right join', 'inner join' + * + * @return ChildCustomerFamilyQuery The current query, for fluid interface + */ + public function joinCustomerFamilyOrder($relationAlias = null, $joinType = Criteria::INNER_JOIN) + { + $tableMap = $this->getTableMap(); + $relationMap = $tableMap->getRelation('CustomerFamilyOrder'); + + // create a ModelJoin object for this join + $join = new ModelJoin(); + $join->setJoinType($joinType); + $join->setRelationMap($relationMap, $this->useAliasInSQL ? $this->getModelAlias() : null, $relationAlias); + if ($previousJoin = $this->getPreviousJoin()) { + $join->setPreviousJoin($previousJoin); + } + + // add the ModelJoin to the current object + if ($relationAlias) { + $this->addAlias($relationAlias, $relationMap->getRightTable()->getName()); + $this->addJoinObject($join, $relationAlias); + } else { + $this->addJoinObject($join, 'CustomerFamilyOrder'); + } + + return $this; + } + + /** + * Use the CustomerFamilyOrder relation CustomerFamilyOrder object + * + * @see useQuery() + * + * @param string $relationAlias optional alias for the relation, + * to be used as main alias in the secondary query + * @param string $joinType Accepted values are null, 'left join', 'right join', 'inner join' + * + * @return \CustomerFamily\Model\CustomerFamilyOrderQuery A secondary query class using the current class as primary query + */ + public function useCustomerFamilyOrderQuery($relationAlias = null, $joinType = Criteria::INNER_JOIN) + { + return $this + ->joinCustomerFamilyOrder($relationAlias, $joinType) + ->useQuery($relationAlias ? $relationAlias : 'CustomerFamilyOrder', '\CustomerFamily\Model\CustomerFamilyOrderQuery'); + } + + /** + * Filter the query by a related \CustomerFamily\Model\CustomerFamilyAvailableCategory object + * + * @param \CustomerFamily\Model\CustomerFamilyAvailableCategory|ObjectCollection $customerFamilyAvailableCategory the related object to use as filter + * @param string $comparison Operator to use for the column comparison, defaults to Criteria::EQUAL + * + * @return ChildCustomerFamilyQuery The current query, for fluid interface + */ + public function filterByCustomerFamilyAvailableCategory($customerFamilyAvailableCategory, $comparison = null) + { + if ($customerFamilyAvailableCategory instanceof \CustomerFamily\Model\CustomerFamilyAvailableCategory) { + return $this + ->addUsingAlias(CustomerFamilyTableMap::ID, $customerFamilyAvailableCategory->getCustomerFamilyId(), $comparison); + } elseif ($customerFamilyAvailableCategory instanceof ObjectCollection) { + return $this + ->useCustomerFamilyAvailableCategoryQuery() + ->filterByPrimaryKeys($customerFamilyAvailableCategory->getPrimaryKeys()) + ->endUse(); + } else { + throw new PropelException('filterByCustomerFamilyAvailableCategory() only accepts arguments of type \CustomerFamily\Model\CustomerFamilyAvailableCategory or Collection'); + } + } + + /** + * Adds a JOIN clause to the query using the CustomerFamilyAvailableCategory relation + * + * @param string $relationAlias optional alias for the relation + * @param string $joinType Accepted values are null, 'left join', 'right join', 'inner join' + * + * @return ChildCustomerFamilyQuery The current query, for fluid interface + */ + public function joinCustomerFamilyAvailableCategory($relationAlias = null, $joinType = Criteria::INNER_JOIN) + { + $tableMap = $this->getTableMap(); + $relationMap = $tableMap->getRelation('CustomerFamilyAvailableCategory'); + + // create a ModelJoin object for this join + $join = new ModelJoin(); + $join->setJoinType($joinType); + $join->setRelationMap($relationMap, $this->useAliasInSQL ? $this->getModelAlias() : null, $relationAlias); + if ($previousJoin = $this->getPreviousJoin()) { + $join->setPreviousJoin($previousJoin); + } + + // add the ModelJoin to the current object + if ($relationAlias) { + $this->addAlias($relationAlias, $relationMap->getRightTable()->getName()); + $this->addJoinObject($join, $relationAlias); + } else { + $this->addJoinObject($join, 'CustomerFamilyAvailableCategory'); + } + + return $this; + } + + /** + * Use the CustomerFamilyAvailableCategory relation CustomerFamilyAvailableCategory object + * + * @see useQuery() + * + * @param string $relationAlias optional alias for the relation, + * to be used as main alias in the secondary query + * @param string $joinType Accepted values are null, 'left join', 'right join', 'inner join' + * + * @return \CustomerFamily\Model\CustomerFamilyAvailableCategoryQuery A secondary query class using the current class as primary query + */ + public function useCustomerFamilyAvailableCategoryQuery($relationAlias = null, $joinType = Criteria::INNER_JOIN) + { + return $this + ->joinCustomerFamilyAvailableCategory($relationAlias, $joinType) + ->useQuery($relationAlias ? $relationAlias : 'CustomerFamilyAvailableCategory', '\CustomerFamily\Model\CustomerFamilyAvailableCategoryQuery'); + } + + /** + * Filter the query by a related \CustomerFamily\Model\CustomerFamilyAvailableBrand object + * + * @param \CustomerFamily\Model\CustomerFamilyAvailableBrand|ObjectCollection $customerFamilyAvailableBrand the related object to use as filter + * @param string $comparison Operator to use for the column comparison, defaults to Criteria::EQUAL + * + * @return ChildCustomerFamilyQuery The current query, for fluid interface + */ + public function filterByCustomerFamilyAvailableBrand($customerFamilyAvailableBrand, $comparison = null) + { + if ($customerFamilyAvailableBrand instanceof \CustomerFamily\Model\CustomerFamilyAvailableBrand) { + return $this + ->addUsingAlias(CustomerFamilyTableMap::ID, $customerFamilyAvailableBrand->getCustomerFamilyId(), $comparison); + } elseif ($customerFamilyAvailableBrand instanceof ObjectCollection) { + return $this + ->useCustomerFamilyAvailableBrandQuery() + ->filterByPrimaryKeys($customerFamilyAvailableBrand->getPrimaryKeys()) + ->endUse(); + } else { + throw new PropelException('filterByCustomerFamilyAvailableBrand() only accepts arguments of type \CustomerFamily\Model\CustomerFamilyAvailableBrand or Collection'); + } + } + + /** + * Adds a JOIN clause to the query using the CustomerFamilyAvailableBrand relation + * + * @param string $relationAlias optional alias for the relation + * @param string $joinType Accepted values are null, 'left join', 'right join', 'inner join' + * + * @return ChildCustomerFamilyQuery The current query, for fluid interface + */ + public function joinCustomerFamilyAvailableBrand($relationAlias = null, $joinType = Criteria::INNER_JOIN) + { + $tableMap = $this->getTableMap(); + $relationMap = $tableMap->getRelation('CustomerFamilyAvailableBrand'); + + // create a ModelJoin object for this join + $join = new ModelJoin(); + $join->setJoinType($joinType); + $join->setRelationMap($relationMap, $this->useAliasInSQL ? $this->getModelAlias() : null, $relationAlias); + if ($previousJoin = $this->getPreviousJoin()) { + $join->setPreviousJoin($previousJoin); + } + + // add the ModelJoin to the current object + if ($relationAlias) { + $this->addAlias($relationAlias, $relationMap->getRightTable()->getName()); + $this->addJoinObject($join, $relationAlias); + } else { + $this->addJoinObject($join, 'CustomerFamilyAvailableBrand'); + } + + return $this; + } + + /** + * Use the CustomerFamilyAvailableBrand relation CustomerFamilyAvailableBrand object + * + * @see useQuery() + * + * @param string $relationAlias optional alias for the relation, + * to be used as main alias in the secondary query + * @param string $joinType Accepted values are null, 'left join', 'right join', 'inner join' + * + * @return \CustomerFamily\Model\CustomerFamilyAvailableBrandQuery A secondary query class using the current class as primary query + */ + public function useCustomerFamilyAvailableBrandQuery($relationAlias = null, $joinType = Criteria::INNER_JOIN) + { + return $this + ->joinCustomerFamilyAvailableBrand($relationAlias, $joinType) + ->useQuery($relationAlias ? $relationAlias : 'CustomerFamilyAvailableBrand', '\CustomerFamily\Model\CustomerFamilyAvailableBrandQuery'); + } + + /** + * Filter the query by a related \CustomerFamily\Model\CustomerFamilyI18n object + * + * @param \CustomerFamily\Model\CustomerFamilyI18n|ObjectCollection $customerFamilyI18n the related object to use as filter + * @param string $comparison Operator to use for the column comparison, defaults to Criteria::EQUAL + * + * @return ChildCustomerFamilyQuery The current query, for fluid interface + */ + public function filterByCustomerFamilyI18n($customerFamilyI18n, $comparison = null) + { + if ($customerFamilyI18n instanceof \CustomerFamily\Model\CustomerFamilyI18n) { + return $this + ->addUsingAlias(CustomerFamilyTableMap::ID, $customerFamilyI18n->getId(), $comparison); + } elseif ($customerFamilyI18n instanceof ObjectCollection) { + return $this + ->useCustomerFamilyI18nQuery() + ->filterByPrimaryKeys($customerFamilyI18n->getPrimaryKeys()) + ->endUse(); + } else { + throw new PropelException('filterByCustomerFamilyI18n() only accepts arguments of type \CustomerFamily\Model\CustomerFamilyI18n or Collection'); + } + } + + /** + * Adds a JOIN clause to the query using the CustomerFamilyI18n relation + * + * @param string $relationAlias optional alias for the relation + * @param string $joinType Accepted values are null, 'left join', 'right join', 'inner join' + * + * @return ChildCustomerFamilyQuery The current query, for fluid interface + */ + public function joinCustomerFamilyI18n($relationAlias = null, $joinType = 'LEFT JOIN') + { + $tableMap = $this->getTableMap(); + $relationMap = $tableMap->getRelation('CustomerFamilyI18n'); + + // create a ModelJoin object for this join + $join = new ModelJoin(); + $join->setJoinType($joinType); + $join->setRelationMap($relationMap, $this->useAliasInSQL ? $this->getModelAlias() : null, $relationAlias); + if ($previousJoin = $this->getPreviousJoin()) { + $join->setPreviousJoin($previousJoin); + } + + // add the ModelJoin to the current object + if ($relationAlias) { + $this->addAlias($relationAlias, $relationMap->getRightTable()->getName()); + $this->addJoinObject($join, $relationAlias); + } else { + $this->addJoinObject($join, 'CustomerFamilyI18n'); + } + + return $this; + } + + /** + * Use the CustomerFamilyI18n relation CustomerFamilyI18n object + * + * @see useQuery() + * + * @param string $relationAlias optional alias for the relation, + * to be used as main alias in the secondary query + * @param string $joinType Accepted values are null, 'left join', 'right join', 'inner join' + * + * @return \CustomerFamily\Model\CustomerFamilyI18nQuery A secondary query class using the current class as primary query + */ + public function useCustomerFamilyI18nQuery($relationAlias = null, $joinType = 'LEFT JOIN') + { + return $this + ->joinCustomerFamilyI18n($relationAlias, $joinType) + ->useQuery($relationAlias ? $relationAlias : 'CustomerFamilyI18n', '\CustomerFamily\Model\CustomerFamilyI18nQuery'); + } + + /** + * Exclude object from result + * + * @param ChildCustomerFamily $customerFamily Object to remove from the list of results + * + * @return ChildCustomerFamilyQuery The current query, for fluid interface + */ + public function prune($customerFamily = null) + { + if ($customerFamily) { + $this->addUsingAlias(CustomerFamilyTableMap::ID, $customerFamily->getId(), Criteria::NOT_EQUAL); + } + + return $this; + } + + /** + * Deletes all rows from the customer_family table. + * + * @param ConnectionInterface $con the connection to use + * @return int The number of affected rows (if supported by underlying database driver). + */ + public function doDeleteAll(ConnectionInterface $con = null) + { + if (null === $con) { + $con = Propel::getServiceContainer()->getWriteConnection(CustomerFamilyTableMap::DATABASE_NAME); + } + $affectedRows = 0; // initialize var to track total num of affected rows + try { + // use transaction because $criteria could contain info + // for more than one table or we could emulating ON DELETE CASCADE, etc. + $con->beginTransaction(); + $affectedRows += parent::doDeleteAll($con); + // Because this db requires some delete cascade/set null emulation, we have to + // clear the cached instance *after* the emulation has happened (since + // instances get re-added by the select statement contained therein). + CustomerFamilyTableMap::clearInstancePool(); + CustomerFamilyTableMap::clearRelatedInstancePool(); + + $con->commit(); + } catch (PropelException $e) { + $con->rollBack(); + throw $e; + } + + return $affectedRows; + } + + /** + * Performs a DELETE on the database, given a ChildCustomerFamily or Criteria object OR a primary key value. + * + * @param mixed $values Criteria or ChildCustomerFamily object or primary key or array of primary keys + * which is used to create the DELETE statement + * @param ConnectionInterface $con the connection to use + * @return int The number of affected rows (if supported by underlying database driver). This includes CASCADE-related rows + * if supported by native driver or if emulated using Propel. + * @throws PropelException Any exceptions caught during processing will be + * rethrown wrapped into a PropelException. + */ + public function delete(ConnectionInterface $con = null) + { + if (null === $con) { + $con = Propel::getServiceContainer()->getWriteConnection(CustomerFamilyTableMap::DATABASE_NAME); + } + + $criteria = $this; + + // Set the correct dbName + $criteria->setDbName(CustomerFamilyTableMap::DATABASE_NAME); + + $affectedRows = 0; // initialize var to track total num of affected rows + + try { + // use transaction because $criteria could contain info + // for more than one table or we could emulating ON DELETE CASCADE, etc. + $con->beginTransaction(); + + + CustomerFamilyTableMap::removeInstanceFromPool($criteria); + + $affectedRows += ModelCriteria::delete($con); + CustomerFamilyTableMap::clearRelatedInstancePool(); + $con->commit(); + + return $affectedRows; + } catch (PropelException $e) { + $con->rollBack(); + throw $e; + } + } + + // timestampable behavior + + /** + * Filter by the latest updated + * + * @param int $nbDays Maximum age of the latest update in days + * + * @return ChildCustomerFamilyQuery The current query, for fluid interface + */ + public function recentlyUpdated($nbDays = 7) + { + return $this->addUsingAlias(CustomerFamilyTableMap::UPDATED_AT, time() - $nbDays * 24 * 60 * 60, Criteria::GREATER_EQUAL); + } + + /** + * Filter by the latest created + * + * @param int $nbDays Maximum age of in days + * + * @return ChildCustomerFamilyQuery The current query, for fluid interface + */ + public function recentlyCreated($nbDays = 7) + { + return $this->addUsingAlias(CustomerFamilyTableMap::CREATED_AT, time() - $nbDays * 24 * 60 * 60, Criteria::GREATER_EQUAL); + } + + /** + * Order by update date desc + * + * @return ChildCustomerFamilyQuery The current query, for fluid interface + */ + public function lastUpdatedFirst() + { + return $this->addDescendingOrderByColumn(CustomerFamilyTableMap::UPDATED_AT); + } + + /** + * Order by update date asc + * + * @return ChildCustomerFamilyQuery The current query, for fluid interface + */ + public function firstUpdatedFirst() + { + return $this->addAscendingOrderByColumn(CustomerFamilyTableMap::UPDATED_AT); + } + + /** + * Order by create date desc + * + * @return ChildCustomerFamilyQuery The current query, for fluid interface + */ + public function lastCreatedFirst() + { + return $this->addDescendingOrderByColumn(CustomerFamilyTableMap::CREATED_AT); + } + + /** + * Order by create date asc + * + * @return ChildCustomerFamilyQuery The current query, for fluid interface + */ + public function firstCreatedFirst() + { + return $this->addAscendingOrderByColumn(CustomerFamilyTableMap::CREATED_AT); + } + + // i18n behavior + + /** + * Adds a JOIN clause to the query using the i18n relation + * + * @param string $locale Locale to use for the join condition, e.g. 'fr_FR' + * @param string $relationAlias optional alias for the relation + * @param string $joinType Accepted values are null, 'left join', 'right join', 'inner join'. Defaults to left join. + * + * @return ChildCustomerFamilyQuery The current query, for fluid interface + */ + public function joinI18n($locale = 'en_US', $relationAlias = null, $joinType = Criteria::LEFT_JOIN) + { + $relationName = $relationAlias ? $relationAlias : 'CustomerFamilyI18n'; + + return $this + ->joinCustomerFamilyI18n($relationAlias, $joinType) + ->addJoinCondition($relationName, $relationName . '.Locale = ?', $locale); + } + + /** + * Adds a JOIN clause to the query and hydrates the related I18n object. + * Shortcut for $c->joinI18n($locale)->with() + * + * @param string $locale Locale to use for the join condition, e.g. 'fr_FR' + * @param string $joinType Accepted values are null, 'left join', 'right join', 'inner join'. Defaults to left join. + * + * @return ChildCustomerFamilyQuery The current query, for fluid interface + */ + public function joinWithI18n($locale = 'en_US', $joinType = Criteria::LEFT_JOIN) + { + $this + ->joinI18n($locale, null, $joinType) + ->with('CustomerFamilyI18n'); + $this->with['CustomerFamilyI18n']->setIsWithOneToMany(false); + + return $this; + } + + /** + * Use the I18n relation query object + * + * @see useQuery() + * + * @param string $locale Locale to use for the join condition, e.g. 'fr_FR' + * @param string $relationAlias optional alias for the relation + * @param string $joinType Accepted values are null, 'left join', 'right join', 'inner join'. Defaults to left join. + * + * @return ChildCustomerFamilyI18nQuery A secondary query class using the current class as primary query + */ + public function useI18nQuery($locale = 'en_US', $relationAlias = null, $joinType = Criteria::LEFT_JOIN) + { + return $this + ->joinI18n($locale, $relationAlias, $joinType) + ->useQuery($relationAlias ? $relationAlias : 'CustomerFamilyI18n', '\CustomerFamily\Model\CustomerFamilyI18nQuery'); + } + +} // CustomerFamilyQuery diff --git a/local/modules/CustomerFamily/Model/Base/OrderProductPurchasePrice.php b/local/modules/CustomerFamily/Model/Base/OrderProductPurchasePrice.php new file mode 100644 index 00000000..2130c5fb --- /dev/null +++ b/local/modules/CustomerFamily/Model/Base/OrderProductPurchasePrice.php @@ -0,0 +1,1255 @@ +purchase_price = '0'; + } + + /** + * Initializes internal state of CustomerFamily\Model\Base\OrderProductPurchasePrice object. + * @see applyDefaults() + */ + public function __construct() + { + $this->applyDefaultValues(); + } + + /** + * Returns whether the object has been modified. + * + * @return boolean True if the object has been modified. + */ + public function isModified() + { + return !!$this->modifiedColumns; + } + + /** + * Has specified column been modified? + * + * @param string $col column fully qualified name (TableMap::TYPE_COLNAME), e.g. Book::AUTHOR_ID + * @return boolean True if $col has been modified. + */ + public function isColumnModified($col) + { + return $this->modifiedColumns && isset($this->modifiedColumns[$col]); + } + + /** + * Get the columns that have been modified in this object. + * @return array A unique list of the modified column names for this object. + */ + public function getModifiedColumns() + { + return $this->modifiedColumns ? array_keys($this->modifiedColumns) : []; + } + + /** + * Returns whether the object has ever been saved. This will + * be false, if the object was retrieved from storage or was created + * and then saved. + * + * @return boolean true, if the object has never been persisted. + */ + public function isNew() + { + return $this->new; + } + + /** + * Setter for the isNew attribute. This method will be called + * by Propel-generated children and objects. + * + * @param boolean $b the state of the object. + */ + public function setNew($b) + { + $this->new = (Boolean) $b; + } + + /** + * Whether this object has been deleted. + * @return boolean The deleted state of this object. + */ + public function isDeleted() + { + return $this->deleted; + } + + /** + * Specify whether this object has been deleted. + * @param boolean $b The deleted state of this object. + * @return void + */ + public function setDeleted($b) + { + $this->deleted = (Boolean) $b; + } + + /** + * Sets the modified state for the object to be false. + * @param string $col If supplied, only the specified column is reset. + * @return void + */ + public function resetModified($col = null) + { + if (null !== $col) { + if (isset($this->modifiedColumns[$col])) { + unset($this->modifiedColumns[$col]); + } + } else { + $this->modifiedColumns = array(); + } + } + + /** + * Compares this with another OrderProductPurchasePrice instance. If + * obj is an instance of OrderProductPurchasePrice, delegates to + * equals(OrderProductPurchasePrice). Otherwise, returns false. + * + * @param mixed $obj The object to compare to. + * @return boolean Whether equal to the object specified. + */ + public function equals($obj) + { + $thisclazz = get_class($this); + if (!is_object($obj) || !($obj instanceof $thisclazz)) { + return false; + } + + if ($this === $obj) { + return true; + } + + if (null === $this->getPrimaryKey() + || null === $obj->getPrimaryKey()) { + return false; + } + + return $this->getPrimaryKey() === $obj->getPrimaryKey(); + } + + /** + * If the primary key is not null, return the hashcode of the + * primary key. Otherwise, return the hash code of the object. + * + * @return int Hashcode + */ + public function hashCode() + { + if (null !== $this->getPrimaryKey()) { + return crc32(serialize($this->getPrimaryKey())); + } + + return crc32(serialize(clone $this)); + } + + /** + * Get the associative array of the virtual columns in this object + * + * @return array + */ + public function getVirtualColumns() + { + return $this->virtualColumns; + } + + /** + * Checks the existence of a virtual column in this object + * + * @param string $name The virtual column name + * @return boolean + */ + public function hasVirtualColumn($name) + { + return array_key_exists($name, $this->virtualColumns); + } + + /** + * Get the value of a virtual column in this object + * + * @param string $name The virtual column name + * @return mixed + * + * @throws PropelException + */ + public function getVirtualColumn($name) + { + if (!$this->hasVirtualColumn($name)) { + throw new PropelException(sprintf('Cannot get value of inexistent virtual column %s.', $name)); + } + + return $this->virtualColumns[$name]; + } + + /** + * Set the value of a virtual column in this object + * + * @param string $name The virtual column name + * @param mixed $value The value to give to the virtual column + * + * @return OrderProductPurchasePrice The current object, for fluid interface + */ + public function setVirtualColumn($name, $value) + { + $this->virtualColumns[$name] = $value; + + return $this; + } + + /** + * Logs a message using Propel::log(). + * + * @param string $msg + * @param int $priority One of the Propel::LOG_* logging levels + * @return boolean + */ + protected function log($msg, $priority = Propel::LOG_INFO) + { + return Propel::log(get_class($this) . ': ' . $msg, $priority); + } + + /** + * Populate the current object from a string, using a given parser format + * + * $book = new Book(); + * $book->importFrom('JSON', '{"Id":9012,"Title":"Don Juan","ISBN":"0140422161","Price":12.99,"PublisherId":1234,"AuthorId":5678}'); + * + * + * @param mixed $parser A AbstractParser instance, + * or a format name ('XML', 'YAML', 'JSON', 'CSV') + * @param string $data The source data to import from + * + * @return OrderProductPurchasePrice The current object, for fluid interface + */ + public function importFrom($parser, $data) + { + if (!$parser instanceof AbstractParser) { + $parser = AbstractParser::getParser($parser); + } + + $this->fromArray($parser->toArray($data), TableMap::TYPE_PHPNAME); + + return $this; + } + + /** + * Export the current object properties to a string, using a given parser format + * + * $book = BookQuery::create()->findPk(9012); + * echo $book->exportTo('JSON'); + * => {"Id":9012,"Title":"Don Juan","ISBN":"0140422161","Price":12.99,"PublisherId":1234,"AuthorId":5678}'); + * + * + * @param mixed $parser A AbstractParser instance, or a format name ('XML', 'YAML', 'JSON', 'CSV') + * @param boolean $includeLazyLoadColumns (optional) Whether to include lazy load(ed) columns. Defaults to TRUE. + * @return string The exported data + */ + public function exportTo($parser, $includeLazyLoadColumns = true) + { + if (!$parser instanceof AbstractParser) { + $parser = AbstractParser::getParser($parser); + } + + return $parser->fromArray($this->toArray(TableMap::TYPE_PHPNAME, $includeLazyLoadColumns, array(), true)); + } + + /** + * Clean up internal collections prior to serializing + * Avoids recursive loops that turn into segmentation faults when serializing + */ + public function __sleep() + { + $this->clearAllReferences(); + + return array_keys(get_object_vars($this)); + } + + /** + * Get the [order_product_id] column value. + * + * @return int + */ + public function getOrderProductId() + { + + return $this->order_product_id; + } + + /** + * Get the [purchase_price] column value. + * + * @return string + */ + public function getPurchasePrice() + { + + return $this->purchase_price; + } + + /** + * Get the [sale_day_equation] column value. + * + * @return string + */ + public function getSaleDayEquation() + { + + return $this->sale_day_equation; + } + + /** + * Set the value of [order_product_id] column. + * + * @param int $v new value + * @return \CustomerFamily\Model\OrderProductPurchasePrice The current object (for fluent API support) + */ + public function setOrderProductId($v) + { + if ($v !== null) { + $v = (int) $v; + } + + if ($this->order_product_id !== $v) { + $this->order_product_id = $v; + $this->modifiedColumns[OrderProductPurchasePriceTableMap::ORDER_PRODUCT_ID] = true; + } + + if ($this->aOrderProduct !== null && $this->aOrderProduct->getId() !== $v) { + $this->aOrderProduct = null; + } + + + return $this; + } // setOrderProductId() + + /** + * Set the value of [purchase_price] column. + * + * @param string $v new value + * @return \CustomerFamily\Model\OrderProductPurchasePrice The current object (for fluent API support) + */ + public function setPurchasePrice($v) + { + if ($v !== null) { + $v = (string) $v; + } + + if ($this->purchase_price !== $v) { + $this->purchase_price = $v; + $this->modifiedColumns[OrderProductPurchasePriceTableMap::PURCHASE_PRICE] = true; + } + + + return $this; + } // setPurchasePrice() + + /** + * Set the value of [sale_day_equation] column. + * + * @param string $v new value + * @return \CustomerFamily\Model\OrderProductPurchasePrice The current object (for fluent API support) + */ + public function setSaleDayEquation($v) + { + if ($v !== null) { + $v = (string) $v; + } + + if ($this->sale_day_equation !== $v) { + $this->sale_day_equation = $v; + $this->modifiedColumns[OrderProductPurchasePriceTableMap::SALE_DAY_EQUATION] = true; + } + + + return $this; + } // setSaleDayEquation() + + /** + * Indicates whether the columns in this object are only set to default values. + * + * This method can be used in conjunction with isModified() to indicate whether an object is both + * modified _and_ has some values set which are non-default. + * + * @return boolean Whether the columns in this object are only been set with default values. + */ + public function hasOnlyDefaultValues() + { + if ($this->purchase_price !== '0') { + return false; + } + + // otherwise, everything was equal, so return TRUE + return true; + } // hasOnlyDefaultValues() + + /** + * Hydrates (populates) the object variables with values from the database resultset. + * + * An offset (0-based "start column") is specified so that objects can be hydrated + * with a subset of the columns in the resultset rows. This is needed, for example, + * for results of JOIN queries where the resultset row includes columns from two or + * more tables. + * + * @param array $row The row returned by DataFetcher->fetch(). + * @param int $startcol 0-based offset column which indicates which restultset column to start with. + * @param boolean $rehydrate Whether this object is being re-hydrated from the database. + * @param string $indexType The index type of $row. Mostly DataFetcher->getIndexType(). + One of the class type constants TableMap::TYPE_PHPNAME, TableMap::TYPE_STUDLYPHPNAME + * TableMap::TYPE_COLNAME, TableMap::TYPE_FIELDNAME, TableMap::TYPE_NUM. + * + * @return int next starting column + * @throws PropelException - Any caught Exception will be rewrapped as a PropelException. + */ + public function hydrate($row, $startcol = 0, $rehydrate = false, $indexType = TableMap::TYPE_NUM) + { + try { + + + $col = $row[TableMap::TYPE_NUM == $indexType ? 0 + $startcol : OrderProductPurchasePriceTableMap::translateFieldName('OrderProductId', TableMap::TYPE_PHPNAME, $indexType)]; + $this->order_product_id = (null !== $col) ? (int) $col : null; + + $col = $row[TableMap::TYPE_NUM == $indexType ? 1 + $startcol : OrderProductPurchasePriceTableMap::translateFieldName('PurchasePrice', TableMap::TYPE_PHPNAME, $indexType)]; + $this->purchase_price = (null !== $col) ? (string) $col : null; + + $col = $row[TableMap::TYPE_NUM == $indexType ? 2 + $startcol : OrderProductPurchasePriceTableMap::translateFieldName('SaleDayEquation', TableMap::TYPE_PHPNAME, $indexType)]; + $this->sale_day_equation = (null !== $col) ? (string) $col : null; + $this->resetModified(); + + $this->setNew(false); + + if ($rehydrate) { + $this->ensureConsistency(); + } + + return $startcol + 3; // 3 = OrderProductPurchasePriceTableMap::NUM_HYDRATE_COLUMNS. + + } catch (Exception $e) { + throw new PropelException("Error populating \CustomerFamily\Model\OrderProductPurchasePrice object", 0, $e); + } + } + + /** + * Checks and repairs the internal consistency of the object. + * + * This method is executed after an already-instantiated object is re-hydrated + * from the database. It exists to check any foreign keys to make sure that + * the objects related to the current object are correct based on foreign key. + * + * You can override this method in the stub class, but you should always invoke + * the base method from the overridden method (i.e. parent::ensureConsistency()), + * in case your model changes. + * + * @throws PropelException + */ + public function ensureConsistency() + { + if ($this->aOrderProduct !== null && $this->order_product_id !== $this->aOrderProduct->getId()) { + $this->aOrderProduct = null; + } + } // ensureConsistency + + /** + * Reloads this object from datastore based on primary key and (optionally) resets all associated objects. + * + * This will only work if the object has been saved and has a valid primary key set. + * + * @param boolean $deep (optional) Whether to also de-associated any related objects. + * @param ConnectionInterface $con (optional) The ConnectionInterface connection to use. + * @return void + * @throws PropelException - if this object is deleted, unsaved or doesn't have pk match in db + */ + public function reload($deep = false, ConnectionInterface $con = null) + { + if ($this->isDeleted()) { + throw new PropelException("Cannot reload a deleted object."); + } + + if ($this->isNew()) { + throw new PropelException("Cannot reload an unsaved object."); + } + + if ($con === null) { + $con = Propel::getServiceContainer()->getReadConnection(OrderProductPurchasePriceTableMap::DATABASE_NAME); + } + + // We don't need to alter the object instance pool; we're just modifying this instance + // already in the pool. + + $dataFetcher = ChildOrderProductPurchasePriceQuery::create(null, $this->buildPkeyCriteria())->setFormatter(ModelCriteria::FORMAT_STATEMENT)->find($con); + $row = $dataFetcher->fetch(); + $dataFetcher->close(); + if (!$row) { + throw new PropelException('Cannot find matching row in the database to reload object values.'); + } + $this->hydrate($row, 0, true, $dataFetcher->getIndexType()); // rehydrate + + if ($deep) { // also de-associate any related objects? + + $this->aOrderProduct = null; + } // if (deep) + } + + /** + * Removes this object from datastore and sets delete attribute. + * + * @param ConnectionInterface $con + * @return void + * @throws PropelException + * @see OrderProductPurchasePrice::setDeleted() + * @see OrderProductPurchasePrice::isDeleted() + */ + public function delete(ConnectionInterface $con = null) + { + if ($this->isDeleted()) { + throw new PropelException("This object has already been deleted."); + } + + if ($con === null) { + $con = Propel::getServiceContainer()->getWriteConnection(OrderProductPurchasePriceTableMap::DATABASE_NAME); + } + + $con->beginTransaction(); + try { + $deleteQuery = ChildOrderProductPurchasePriceQuery::create() + ->filterByPrimaryKey($this->getPrimaryKey()); + $ret = $this->preDelete($con); + if ($ret) { + $deleteQuery->delete($con); + $this->postDelete($con); + $con->commit(); + $this->setDeleted(true); + } else { + $con->commit(); + } + } catch (Exception $e) { + $con->rollBack(); + throw $e; + } + } + + /** + * Persists this object to the database. + * + * If the object is new, it inserts it; otherwise an update is performed. + * All modified related objects will also be persisted in the doSave() + * method. This method wraps all precipitate database operations in a + * single transaction. + * + * @param ConnectionInterface $con + * @return int The number of rows affected by this insert/update and any referring fk objects' save() operations. + * @throws PropelException + * @see doSave() + */ + public function save(ConnectionInterface $con = null) + { + if ($this->isDeleted()) { + throw new PropelException("You cannot save an object that has been deleted."); + } + + if ($con === null) { + $con = Propel::getServiceContainer()->getWriteConnection(OrderProductPurchasePriceTableMap::DATABASE_NAME); + } + + $con->beginTransaction(); + $isInsert = $this->isNew(); + try { + $ret = $this->preSave($con); + if ($isInsert) { + $ret = $ret && $this->preInsert($con); + } else { + $ret = $ret && $this->preUpdate($con); + } + if ($ret) { + $affectedRows = $this->doSave($con); + if ($isInsert) { + $this->postInsert($con); + } else { + $this->postUpdate($con); + } + $this->postSave($con); + OrderProductPurchasePriceTableMap::addInstanceToPool($this); + } else { + $affectedRows = 0; + } + $con->commit(); + + return $affectedRows; + } catch (Exception $e) { + $con->rollBack(); + throw $e; + } + } + + /** + * Performs the work of inserting or updating the row in the database. + * + * If the object is new, it inserts it; otherwise an update is performed. + * All related objects are also updated in this method. + * + * @param ConnectionInterface $con + * @return int The number of rows affected by this insert/update and any referring fk objects' save() operations. + * @throws PropelException + * @see save() + */ + protected function doSave(ConnectionInterface $con) + { + $affectedRows = 0; // initialize var to track total num of affected rows + if (!$this->alreadyInSave) { + $this->alreadyInSave = true; + + // We call the save method on the following object(s) if they + // were passed to this object by their corresponding set + // method. This object relates to these object(s) by a + // foreign key reference. + + if ($this->aOrderProduct !== null) { + if ($this->aOrderProduct->isModified() || $this->aOrderProduct->isNew()) { + $affectedRows += $this->aOrderProduct->save($con); + } + $this->setOrderProduct($this->aOrderProduct); + } + + if ($this->isNew() || $this->isModified()) { + // persist changes + if ($this->isNew()) { + $this->doInsert($con); + } else { + $this->doUpdate($con); + } + $affectedRows += 1; + $this->resetModified(); + } + + $this->alreadyInSave = false; + + } + + return $affectedRows; + } // doSave() + + /** + * Insert the row in the database. + * + * @param ConnectionInterface $con + * + * @throws PropelException + * @see doSave() + */ + protected function doInsert(ConnectionInterface $con) + { + $modifiedColumns = array(); + $index = 0; + + + // check the columns in natural order for more readable SQL queries + if ($this->isColumnModified(OrderProductPurchasePriceTableMap::ORDER_PRODUCT_ID)) { + $modifiedColumns[':p' . $index++] = 'ORDER_PRODUCT_ID'; + } + if ($this->isColumnModified(OrderProductPurchasePriceTableMap::PURCHASE_PRICE)) { + $modifiedColumns[':p' . $index++] = 'PURCHASE_PRICE'; + } + if ($this->isColumnModified(OrderProductPurchasePriceTableMap::SALE_DAY_EQUATION)) { + $modifiedColumns[':p' . $index++] = 'SALE_DAY_EQUATION'; + } + + $sql = sprintf( + 'INSERT INTO order_product_purchase_price (%s) VALUES (%s)', + implode(', ', $modifiedColumns), + implode(', ', array_keys($modifiedColumns)) + ); + + try { + $stmt = $con->prepare($sql); + foreach ($modifiedColumns as $identifier => $columnName) { + switch ($columnName) { + case 'ORDER_PRODUCT_ID': + $stmt->bindValue($identifier, $this->order_product_id, PDO::PARAM_INT); + break; + case 'PURCHASE_PRICE': + $stmt->bindValue($identifier, $this->purchase_price, PDO::PARAM_STR); + break; + case 'SALE_DAY_EQUATION': + $stmt->bindValue($identifier, $this->sale_day_equation, PDO::PARAM_STR); + break; + } + } + $stmt->execute(); + } catch (Exception $e) { + Propel::log($e->getMessage(), Propel::LOG_ERR); + throw new PropelException(sprintf('Unable to execute INSERT statement [%s]', $sql), 0, $e); + } + + $this->setNew(false); + } + + /** + * Update the row in the database. + * + * @param ConnectionInterface $con + * + * @return Integer Number of updated rows + * @see doSave() + */ + protected function doUpdate(ConnectionInterface $con) + { + $selectCriteria = $this->buildPkeyCriteria(); + $valuesCriteria = $this->buildCriteria(); + + return $selectCriteria->doUpdate($valuesCriteria, $con); + } + + /** + * Retrieves a field from the object by name passed in as a string. + * + * @param string $name name + * @param string $type The type of fieldname the $name is of: + * one of the class type constants TableMap::TYPE_PHPNAME, TableMap::TYPE_STUDLYPHPNAME + * TableMap::TYPE_COLNAME, TableMap::TYPE_FIELDNAME, TableMap::TYPE_NUM. + * Defaults to TableMap::TYPE_PHPNAME. + * @return mixed Value of field. + */ + public function getByName($name, $type = TableMap::TYPE_PHPNAME) + { + $pos = OrderProductPurchasePriceTableMap::translateFieldName($name, $type, TableMap::TYPE_NUM); + $field = $this->getByPosition($pos); + + return $field; + } + + /** + * Retrieves a field from the object by Position as specified in the xml schema. + * Zero-based. + * + * @param int $pos position in xml schema + * @return mixed Value of field at $pos + */ + public function getByPosition($pos) + { + switch ($pos) { + case 0: + return $this->getOrderProductId(); + break; + case 1: + return $this->getPurchasePrice(); + break; + case 2: + return $this->getSaleDayEquation(); + break; + default: + return null; + break; + } // switch() + } + + /** + * Exports the object as an array. + * + * You can specify the key type of the array by passing one of the class + * type constants. + * + * @param string $keyType (optional) One of the class type constants TableMap::TYPE_PHPNAME, TableMap::TYPE_STUDLYPHPNAME, + * TableMap::TYPE_COLNAME, TableMap::TYPE_FIELDNAME, TableMap::TYPE_NUM. + * Defaults to TableMap::TYPE_PHPNAME. + * @param boolean $includeLazyLoadColumns (optional) Whether to include lazy loaded columns. Defaults to TRUE. + * @param array $alreadyDumpedObjects List of objects to skip to avoid recursion + * @param boolean $includeForeignObjects (optional) Whether to include hydrated related objects. Default to FALSE. + * + * @return array an associative array containing the field names (as keys) and field values + */ + public function toArray($keyType = TableMap::TYPE_PHPNAME, $includeLazyLoadColumns = true, $alreadyDumpedObjects = array(), $includeForeignObjects = false) + { + if (isset($alreadyDumpedObjects['OrderProductPurchasePrice'][$this->getPrimaryKey()])) { + return '*RECURSION*'; + } + $alreadyDumpedObjects['OrderProductPurchasePrice'][$this->getPrimaryKey()] = true; + $keys = OrderProductPurchasePriceTableMap::getFieldNames($keyType); + $result = array( + $keys[0] => $this->getOrderProductId(), + $keys[1] => $this->getPurchasePrice(), + $keys[2] => $this->getSaleDayEquation(), + ); + $virtualColumns = $this->virtualColumns; + foreach ($virtualColumns as $key => $virtualColumn) { + $result[$key] = $virtualColumn; + } + + if ($includeForeignObjects) { + if (null !== $this->aOrderProduct) { + $result['OrderProduct'] = $this->aOrderProduct->toArray($keyType, $includeLazyLoadColumns, $alreadyDumpedObjects, true); + } + } + + return $result; + } + + /** + * Sets a field from the object by name passed in as a string. + * + * @param string $name + * @param mixed $value field value + * @param string $type The type of fieldname the $name is of: + * one of the class type constants TableMap::TYPE_PHPNAME, TableMap::TYPE_STUDLYPHPNAME + * TableMap::TYPE_COLNAME, TableMap::TYPE_FIELDNAME, TableMap::TYPE_NUM. + * Defaults to TableMap::TYPE_PHPNAME. + * @return void + */ + public function setByName($name, $value, $type = TableMap::TYPE_PHPNAME) + { + $pos = OrderProductPurchasePriceTableMap::translateFieldName($name, $type, TableMap::TYPE_NUM); + + return $this->setByPosition($pos, $value); + } + + /** + * Sets a field from the object by Position as specified in the xml schema. + * Zero-based. + * + * @param int $pos position in xml schema + * @param mixed $value field value + * @return void + */ + public function setByPosition($pos, $value) + { + switch ($pos) { + case 0: + $this->setOrderProductId($value); + break; + case 1: + $this->setPurchasePrice($value); + break; + case 2: + $this->setSaleDayEquation($value); + break; + } // switch() + } + + /** + * Populates the object using an array. + * + * This is particularly useful when populating an object from one of the + * request arrays (e.g. $_POST). This method goes through the column + * names, checking to see whether a matching key exists in populated + * array. If so the setByName() method is called for that column. + * + * You can specify the key type of the array by additionally passing one + * of the class type constants TableMap::TYPE_PHPNAME, TableMap::TYPE_STUDLYPHPNAME, + * TableMap::TYPE_COLNAME, TableMap::TYPE_FIELDNAME, TableMap::TYPE_NUM. + * The default key type is the column's TableMap::TYPE_PHPNAME. + * + * @param array $arr An array to populate the object from. + * @param string $keyType The type of keys the array uses. + * @return void + */ + public function fromArray($arr, $keyType = TableMap::TYPE_PHPNAME) + { + $keys = OrderProductPurchasePriceTableMap::getFieldNames($keyType); + + if (array_key_exists($keys[0], $arr)) $this->setOrderProductId($arr[$keys[0]]); + if (array_key_exists($keys[1], $arr)) $this->setPurchasePrice($arr[$keys[1]]); + if (array_key_exists($keys[2], $arr)) $this->setSaleDayEquation($arr[$keys[2]]); + } + + /** + * Build a Criteria object containing the values of all modified columns in this object. + * + * @return Criteria The Criteria object containing all modified values. + */ + public function buildCriteria() + { + $criteria = new Criteria(OrderProductPurchasePriceTableMap::DATABASE_NAME); + + if ($this->isColumnModified(OrderProductPurchasePriceTableMap::ORDER_PRODUCT_ID)) $criteria->add(OrderProductPurchasePriceTableMap::ORDER_PRODUCT_ID, $this->order_product_id); + if ($this->isColumnModified(OrderProductPurchasePriceTableMap::PURCHASE_PRICE)) $criteria->add(OrderProductPurchasePriceTableMap::PURCHASE_PRICE, $this->purchase_price); + if ($this->isColumnModified(OrderProductPurchasePriceTableMap::SALE_DAY_EQUATION)) $criteria->add(OrderProductPurchasePriceTableMap::SALE_DAY_EQUATION, $this->sale_day_equation); + + return $criteria; + } + + /** + * Builds a Criteria object containing the primary key for this object. + * + * Unlike buildCriteria() this method includes the primary key values regardless + * of whether or not they have been modified. + * + * @return Criteria The Criteria object containing value(s) for primary key(s). + */ + public function buildPkeyCriteria() + { + $criteria = new Criteria(OrderProductPurchasePriceTableMap::DATABASE_NAME); + $criteria->add(OrderProductPurchasePriceTableMap::ORDER_PRODUCT_ID, $this->order_product_id); + + return $criteria; + } + + /** + * Returns the primary key for this object (row). + * @return int + */ + public function getPrimaryKey() + { + return $this->getOrderProductId(); + } + + /** + * Generic method to set the primary key (order_product_id column). + * + * @param int $key Primary key. + * @return void + */ + public function setPrimaryKey($key) + { + $this->setOrderProductId($key); + } + + /** + * Returns true if the primary key for this object is null. + * @return boolean + */ + public function isPrimaryKeyNull() + { + + return null === $this->getOrderProductId(); + } + + /** + * Sets contents of passed object to values from current object. + * + * If desired, this method can also make copies of all associated (fkey referrers) + * objects. + * + * @param object $copyObj An object of \CustomerFamily\Model\OrderProductPurchasePrice (or compatible) type. + * @param boolean $deepCopy Whether to also copy all rows that refer (by fkey) to the current row. + * @param boolean $makeNew Whether to reset autoincrement PKs and make the object new. + * @throws PropelException + */ + public function copyInto($copyObj, $deepCopy = false, $makeNew = true) + { + $copyObj->setOrderProductId($this->getOrderProductId()); + $copyObj->setPurchasePrice($this->getPurchasePrice()); + $copyObj->setSaleDayEquation($this->getSaleDayEquation()); + if ($makeNew) { + $copyObj->setNew(true); + } + } + + /** + * Makes a copy of this object that will be inserted as a new row in table when saved. + * It creates a new object filling in the simple attributes, but skipping any primary + * keys that are defined for the table. + * + * If desired, this method can also make copies of all associated (fkey referrers) + * objects. + * + * @param boolean $deepCopy Whether to also copy all rows that refer (by fkey) to the current row. + * @return \CustomerFamily\Model\OrderProductPurchasePrice Clone of current object. + * @throws PropelException + */ + public function copy($deepCopy = false) + { + // we use get_class(), because this might be a subclass + $clazz = get_class($this); + $copyObj = new $clazz(); + $this->copyInto($copyObj, $deepCopy); + + return $copyObj; + } + + /** + * Declares an association between this object and a ChildOrderProduct object. + * + * @param ChildOrderProduct $v + * @return \CustomerFamily\Model\OrderProductPurchasePrice The current object (for fluent API support) + * @throws PropelException + */ + public function setOrderProduct(ChildOrderProduct $v = null) + { + if ($v === null) { + $this->setOrderProductId(NULL); + } else { + $this->setOrderProductId($v->getId()); + } + + $this->aOrderProduct = $v; + + // Add binding for other direction of this 1:1 relationship. + if ($v !== null) { + $v->setOrderProductPurchasePrice($this); + } + + + return $this; + } + + + /** + * Get the associated ChildOrderProduct object + * + * @param ConnectionInterface $con Optional Connection object. + * @return ChildOrderProduct The associated ChildOrderProduct object. + * @throws PropelException + */ + public function getOrderProduct(ConnectionInterface $con = null) + { + if ($this->aOrderProduct === null && ($this->order_product_id !== null)) { + $this->aOrderProduct = OrderProductQuery::create()->findPk($this->order_product_id, $con); + // Because this foreign key represents a one-to-one relationship, we will create a bi-directional association. + $this->aOrderProduct->setOrderProductPurchasePrice($this); + } + + return $this->aOrderProduct; + } + + /** + * Clears the current object and sets all attributes to their default values + */ + public function clear() + { + $this->order_product_id = null; + $this->purchase_price = null; + $this->sale_day_equation = null; + $this->alreadyInSave = false; + $this->clearAllReferences(); + $this->applyDefaultValues(); + $this->resetModified(); + $this->setNew(true); + $this->setDeleted(false); + } + + /** + * Resets all references to other model objects or collections of model objects. + * + * This method is a user-space workaround for PHP's inability to garbage collect + * objects with circular references (even in PHP 5.3). This is currently necessary + * when using Propel in certain daemon or large-volume/high-memory operations. + * + * @param boolean $deep Whether to also clear the references on all referrer objects. + */ + public function clearAllReferences($deep = false) + { + if ($deep) { + } // if ($deep) + + $this->aOrderProduct = null; + } + + /** + * Return the string representation of this object + * + * @return string + */ + public function __toString() + { + return (string) $this->exportTo(OrderProductPurchasePriceTableMap::DEFAULT_STRING_FORMAT); + } + + /** + * Code to be run before persisting the object + * @param ConnectionInterface $con + * @return boolean + */ + public function preSave(ConnectionInterface $con = null) + { + return true; + } + + /** + * Code to be run after persisting the object + * @param ConnectionInterface $con + */ + public function postSave(ConnectionInterface $con = null) + { + + } + + /** + * Code to be run before inserting to database + * @param ConnectionInterface $con + * @return boolean + */ + public function preInsert(ConnectionInterface $con = null) + { + return true; + } + + /** + * Code to be run after inserting to database + * @param ConnectionInterface $con + */ + public function postInsert(ConnectionInterface $con = null) + { + + } + + /** + * Code to be run before updating the object in database + * @param ConnectionInterface $con + * @return boolean + */ + public function preUpdate(ConnectionInterface $con = null) + { + return true; + } + + /** + * Code to be run after updating the object in database + * @param ConnectionInterface $con + */ + public function postUpdate(ConnectionInterface $con = null) + { + + } + + /** + * Code to be run before deleting the object in database + * @param ConnectionInterface $con + * @return boolean + */ + public function preDelete(ConnectionInterface $con = null) + { + return true; + } + + /** + * Code to be run after deleting the object in database + * @param ConnectionInterface $con + */ + public function postDelete(ConnectionInterface $con = null) + { + + } + + + /** + * Derived method to catches calls to undefined methods. + * + * Provides magic import/export method support (fromXML()/toXML(), fromYAML()/toYAML(), etc.). + * Allows to define default __call() behavior if you overwrite __call() + * + * @param string $name + * @param mixed $params + * + * @return array|string + */ + public function __call($name, $params) + { + if (0 === strpos($name, 'get')) { + $virtualColumn = substr($name, 3); + if ($this->hasVirtualColumn($virtualColumn)) { + return $this->getVirtualColumn($virtualColumn); + } + + $virtualColumn = lcfirst($virtualColumn); + if ($this->hasVirtualColumn($virtualColumn)) { + return $this->getVirtualColumn($virtualColumn); + } + } + + if (0 === strpos($name, 'from')) { + $format = substr($name, 4); + + return $this->importFrom($format, reset($params)); + } + + if (0 === strpos($name, 'to')) { + $format = substr($name, 2); + $includeLazyLoadColumns = isset($params[0]) ? $params[0] : true; + + return $this->exportTo($format, $includeLazyLoadColumns); + } + + throw new BadMethodCallException(sprintf('Call to undefined method: %s.', $name)); + } + +} diff --git a/local/modules/CustomerFamily/Model/Base/OrderProductPurchasePriceQuery.php b/local/modules/CustomerFamily/Model/Base/OrderProductPurchasePriceQuery.php new file mode 100644 index 00000000..785c5fcf --- /dev/null +++ b/local/modules/CustomerFamily/Model/Base/OrderProductPurchasePriceQuery.php @@ -0,0 +1,507 @@ +setModelAlias($modelAlias); + } + if ($criteria instanceof Criteria) { + $query->mergeWith($criteria); + } + + return $query; + } + + /** + * Find object by primary key. + * Propel uses the instance pool to skip the database if the object exists. + * Go fast if the query is untouched. + * + * + * $obj = $c->findPk(12, $con); + * + * + * @param mixed $key Primary key to use for the query + * @param ConnectionInterface $con an optional connection object + * + * @return ChildOrderProductPurchasePrice|array|mixed the result, formatted by the current formatter + */ + public function findPk($key, $con = null) + { + if ($key === null) { + return null; + } + if ((null !== ($obj = OrderProductPurchasePriceTableMap::getInstanceFromPool((string) $key))) && !$this->formatter) { + // the object is already in the instance pool + return $obj; + } + if ($con === null) { + $con = Propel::getServiceContainer()->getReadConnection(OrderProductPurchasePriceTableMap::DATABASE_NAME); + } + $this->basePreSelect($con); + if ($this->formatter || $this->modelAlias || $this->with || $this->select + || $this->selectColumns || $this->asColumns || $this->selectModifiers + || $this->map || $this->having || $this->joins) { + return $this->findPkComplex($key, $con); + } else { + return $this->findPkSimple($key, $con); + } + } + + /** + * Find object by primary key using raw SQL to go fast. + * Bypass doSelect() and the object formatter by using generated code. + * + * @param mixed $key Primary key to use for the query + * @param ConnectionInterface $con A connection object + * + * @return ChildOrderProductPurchasePrice A model object, or null if the key is not found + */ + protected function findPkSimple($key, $con) + { + $sql = 'SELECT ORDER_PRODUCT_ID, PURCHASE_PRICE, SALE_DAY_EQUATION FROM order_product_purchase_price WHERE ORDER_PRODUCT_ID = :p0'; + try { + $stmt = $con->prepare($sql); + $stmt->bindValue(':p0', $key, PDO::PARAM_INT); + $stmt->execute(); + } catch (Exception $e) { + Propel::log($e->getMessage(), Propel::LOG_ERR); + throw new PropelException(sprintf('Unable to execute SELECT statement [%s]', $sql), 0, $e); + } + $obj = null; + if ($row = $stmt->fetch(\PDO::FETCH_NUM)) { + $obj = new ChildOrderProductPurchasePrice(); + $obj->hydrate($row); + OrderProductPurchasePriceTableMap::addInstanceToPool($obj, (string) $key); + } + $stmt->closeCursor(); + + return $obj; + } + + /** + * Find object by primary key. + * + * @param mixed $key Primary key to use for the query + * @param ConnectionInterface $con A connection object + * + * @return ChildOrderProductPurchasePrice|array|mixed the result, formatted by the current formatter + */ + protected function findPkComplex($key, $con) + { + // As the query uses a PK condition, no limit(1) is necessary. + $criteria = $this->isKeepQuery() ? clone $this : $this; + $dataFetcher = $criteria + ->filterByPrimaryKey($key) + ->doSelect($con); + + return $criteria->getFormatter()->init($criteria)->formatOne($dataFetcher); + } + + /** + * Find objects by primary key + * + * $objs = $c->findPks(array(12, 56, 832), $con); + * + * @param array $keys Primary keys to use for the query + * @param ConnectionInterface $con an optional connection object + * + * @return ObjectCollection|array|mixed the list of results, formatted by the current formatter + */ + public function findPks($keys, $con = null) + { + if (null === $con) { + $con = Propel::getServiceContainer()->getReadConnection($this->getDbName()); + } + $this->basePreSelect($con); + $criteria = $this->isKeepQuery() ? clone $this : $this; + $dataFetcher = $criteria + ->filterByPrimaryKeys($keys) + ->doSelect($con); + + return $criteria->getFormatter()->init($criteria)->format($dataFetcher); + } + + /** + * Filter the query by primary key + * + * @param mixed $key Primary key to use for the query + * + * @return ChildOrderProductPurchasePriceQuery The current query, for fluid interface + */ + public function filterByPrimaryKey($key) + { + + return $this->addUsingAlias(OrderProductPurchasePriceTableMap::ORDER_PRODUCT_ID, $key, Criteria::EQUAL); + } + + /** + * Filter the query by a list of primary keys + * + * @param array $keys The list of primary key to use for the query + * + * @return ChildOrderProductPurchasePriceQuery The current query, for fluid interface + */ + public function filterByPrimaryKeys($keys) + { + + return $this->addUsingAlias(OrderProductPurchasePriceTableMap::ORDER_PRODUCT_ID, $keys, Criteria::IN); + } + + /** + * Filter the query on the order_product_id column + * + * Example usage: + * + * $query->filterByOrderProductId(1234); // WHERE order_product_id = 1234 + * $query->filterByOrderProductId(array(12, 34)); // WHERE order_product_id IN (12, 34) + * $query->filterByOrderProductId(array('min' => 12)); // WHERE order_product_id > 12 + * + * + * @see filterByOrderProduct() + * + * @param mixed $orderProductId The value to use as filter. + * Use scalar values for equality. + * Use array values for in_array() equivalent. + * Use associative array('min' => $minValue, 'max' => $maxValue) for intervals. + * @param string $comparison Operator to use for the column comparison, defaults to Criteria::EQUAL + * + * @return ChildOrderProductPurchasePriceQuery The current query, for fluid interface + */ + public function filterByOrderProductId($orderProductId = null, $comparison = null) + { + if (is_array($orderProductId)) { + $useMinMax = false; + if (isset($orderProductId['min'])) { + $this->addUsingAlias(OrderProductPurchasePriceTableMap::ORDER_PRODUCT_ID, $orderProductId['min'], Criteria::GREATER_EQUAL); + $useMinMax = true; + } + if (isset($orderProductId['max'])) { + $this->addUsingAlias(OrderProductPurchasePriceTableMap::ORDER_PRODUCT_ID, $orderProductId['max'], Criteria::LESS_EQUAL); + $useMinMax = true; + } + if ($useMinMax) { + return $this; + } + if (null === $comparison) { + $comparison = Criteria::IN; + } + } + + return $this->addUsingAlias(OrderProductPurchasePriceTableMap::ORDER_PRODUCT_ID, $orderProductId, $comparison); + } + + /** + * Filter the query on the purchase_price column + * + * Example usage: + * + * $query->filterByPurchasePrice(1234); // WHERE purchase_price = 1234 + * $query->filterByPurchasePrice(array(12, 34)); // WHERE purchase_price IN (12, 34) + * $query->filterByPurchasePrice(array('min' => 12)); // WHERE purchase_price > 12 + * + * + * @param mixed $purchasePrice The value to use as filter. + * Use scalar values for equality. + * Use array values for in_array() equivalent. + * Use associative array('min' => $minValue, 'max' => $maxValue) for intervals. + * @param string $comparison Operator to use for the column comparison, defaults to Criteria::EQUAL + * + * @return ChildOrderProductPurchasePriceQuery The current query, for fluid interface + */ + public function filterByPurchasePrice($purchasePrice = null, $comparison = null) + { + if (is_array($purchasePrice)) { + $useMinMax = false; + if (isset($purchasePrice['min'])) { + $this->addUsingAlias(OrderProductPurchasePriceTableMap::PURCHASE_PRICE, $purchasePrice['min'], Criteria::GREATER_EQUAL); + $useMinMax = true; + } + if (isset($purchasePrice['max'])) { + $this->addUsingAlias(OrderProductPurchasePriceTableMap::PURCHASE_PRICE, $purchasePrice['max'], Criteria::LESS_EQUAL); + $useMinMax = true; + } + if ($useMinMax) { + return $this; + } + if (null === $comparison) { + $comparison = Criteria::IN; + } + } + + return $this->addUsingAlias(OrderProductPurchasePriceTableMap::PURCHASE_PRICE, $purchasePrice, $comparison); + } + + /** + * Filter the query on the sale_day_equation column + * + * Example usage: + * + * $query->filterBySaleDayEquation('fooValue'); // WHERE sale_day_equation = 'fooValue' + * $query->filterBySaleDayEquation('%fooValue%'); // WHERE sale_day_equation LIKE '%fooValue%' + * + * + * @param string $saleDayEquation The value to use as filter. + * Accepts wildcards (* and % trigger a LIKE) + * @param string $comparison Operator to use for the column comparison, defaults to Criteria::EQUAL + * + * @return ChildOrderProductPurchasePriceQuery The current query, for fluid interface + */ + public function filterBySaleDayEquation($saleDayEquation = null, $comparison = null) + { + if (null === $comparison) { + if (is_array($saleDayEquation)) { + $comparison = Criteria::IN; + } elseif (preg_match('/[\%\*]/', $saleDayEquation)) { + $saleDayEquation = str_replace('*', '%', $saleDayEquation); + $comparison = Criteria::LIKE; + } + } + + return $this->addUsingAlias(OrderProductPurchasePriceTableMap::SALE_DAY_EQUATION, $saleDayEquation, $comparison); + } + + /** + * Filter the query by a related \CustomerFamily\Model\Thelia\Model\OrderProduct object + * + * @param \CustomerFamily\Model\Thelia\Model\OrderProduct|ObjectCollection $orderProduct The related object(s) to use as filter + * @param string $comparison Operator to use for the column comparison, defaults to Criteria::EQUAL + * + * @return ChildOrderProductPurchasePriceQuery The current query, for fluid interface + */ + public function filterByOrderProduct($orderProduct, $comparison = null) + { + if ($orderProduct instanceof \CustomerFamily\Model\Thelia\Model\OrderProduct) { + return $this + ->addUsingAlias(OrderProductPurchasePriceTableMap::ORDER_PRODUCT_ID, $orderProduct->getId(), $comparison); + } elseif ($orderProduct instanceof ObjectCollection) { + if (null === $comparison) { + $comparison = Criteria::IN; + } + + return $this + ->addUsingAlias(OrderProductPurchasePriceTableMap::ORDER_PRODUCT_ID, $orderProduct->toKeyValue('PrimaryKey', 'Id'), $comparison); + } else { + throw new PropelException('filterByOrderProduct() only accepts arguments of type \CustomerFamily\Model\Thelia\Model\OrderProduct or Collection'); + } + } + + /** + * Adds a JOIN clause to the query using the OrderProduct relation + * + * @param string $relationAlias optional alias for the relation + * @param string $joinType Accepted values are null, 'left join', 'right join', 'inner join' + * + * @return ChildOrderProductPurchasePriceQuery The current query, for fluid interface + */ + public function joinOrderProduct($relationAlias = null, $joinType = Criteria::INNER_JOIN) + { + $tableMap = $this->getTableMap(); + $relationMap = $tableMap->getRelation('OrderProduct'); + + // create a ModelJoin object for this join + $join = new ModelJoin(); + $join->setJoinType($joinType); + $join->setRelationMap($relationMap, $this->useAliasInSQL ? $this->getModelAlias() : null, $relationAlias); + if ($previousJoin = $this->getPreviousJoin()) { + $join->setPreviousJoin($previousJoin); + } + + // add the ModelJoin to the current object + if ($relationAlias) { + $this->addAlias($relationAlias, $relationMap->getRightTable()->getName()); + $this->addJoinObject($join, $relationAlias); + } else { + $this->addJoinObject($join, 'OrderProduct'); + } + + return $this; + } + + /** + * Use the OrderProduct relation OrderProduct object + * + * @see useQuery() + * + * @param string $relationAlias optional alias for the relation, + * to be used as main alias in the secondary query + * @param string $joinType Accepted values are null, 'left join', 'right join', 'inner join' + * + * @return \CustomerFamily\Model\Thelia\Model\OrderProductQuery A secondary query class using the current class as primary query + */ + public function useOrderProductQuery($relationAlias = null, $joinType = Criteria::INNER_JOIN) + { + return $this + ->joinOrderProduct($relationAlias, $joinType) + ->useQuery($relationAlias ? $relationAlias : 'OrderProduct', '\CustomerFamily\Model\Thelia\Model\OrderProductQuery'); + } + + /** + * Exclude object from result + * + * @param ChildOrderProductPurchasePrice $orderProductPurchasePrice Object to remove from the list of results + * + * @return ChildOrderProductPurchasePriceQuery The current query, for fluid interface + */ + public function prune($orderProductPurchasePrice = null) + { + if ($orderProductPurchasePrice) { + $this->addUsingAlias(OrderProductPurchasePriceTableMap::ORDER_PRODUCT_ID, $orderProductPurchasePrice->getOrderProductId(), Criteria::NOT_EQUAL); + } + + return $this; + } + + /** + * Deletes all rows from the order_product_purchase_price table. + * + * @param ConnectionInterface $con the connection to use + * @return int The number of affected rows (if supported by underlying database driver). + */ + public function doDeleteAll(ConnectionInterface $con = null) + { + if (null === $con) { + $con = Propel::getServiceContainer()->getWriteConnection(OrderProductPurchasePriceTableMap::DATABASE_NAME); + } + $affectedRows = 0; // initialize var to track total num of affected rows + try { + // use transaction because $criteria could contain info + // for more than one table or we could emulating ON DELETE CASCADE, etc. + $con->beginTransaction(); + $affectedRows += parent::doDeleteAll($con); + // Because this db requires some delete cascade/set null emulation, we have to + // clear the cached instance *after* the emulation has happened (since + // instances get re-added by the select statement contained therein). + OrderProductPurchasePriceTableMap::clearInstancePool(); + OrderProductPurchasePriceTableMap::clearRelatedInstancePool(); + + $con->commit(); + } catch (PropelException $e) { + $con->rollBack(); + throw $e; + } + + return $affectedRows; + } + + /** + * Performs a DELETE on the database, given a ChildOrderProductPurchasePrice or Criteria object OR a primary key value. + * + * @param mixed $values Criteria or ChildOrderProductPurchasePrice object or primary key or array of primary keys + * which is used to create the DELETE statement + * @param ConnectionInterface $con the connection to use + * @return int The number of affected rows (if supported by underlying database driver). This includes CASCADE-related rows + * if supported by native driver or if emulated using Propel. + * @throws PropelException Any exceptions caught during processing will be + * rethrown wrapped into a PropelException. + */ + public function delete(ConnectionInterface $con = null) + { + if (null === $con) { + $con = Propel::getServiceContainer()->getWriteConnection(OrderProductPurchasePriceTableMap::DATABASE_NAME); + } + + $criteria = $this; + + // Set the correct dbName + $criteria->setDbName(OrderProductPurchasePriceTableMap::DATABASE_NAME); + + $affectedRows = 0; // initialize var to track total num of affected rows + + try { + // use transaction because $criteria could contain info + // for more than one table or we could emulating ON DELETE CASCADE, etc. + $con->beginTransaction(); + + + OrderProductPurchasePriceTableMap::removeInstanceFromPool($criteria); + + $affectedRows += ModelCriteria::delete($con); + OrderProductPurchasePriceTableMap::clearRelatedInstancePool(); + $con->commit(); + + return $affectedRows; + } catch (PropelException $e) { + $con->rollBack(); + throw $e; + } + } + +} // OrderProductPurchasePriceQuery diff --git a/local/modules/CustomerFamily/Model/Base/ProductPurchasePrice.php b/local/modules/CustomerFamily/Model/Base/ProductPurchasePrice.php new file mode 100644 index 00000000..5ae32e1a --- /dev/null +++ b/local/modules/CustomerFamily/Model/Base/ProductPurchasePrice.php @@ -0,0 +1,1345 @@ +purchase_price = '0'; + } + + /** + * Initializes internal state of CustomerFamily\Model\Base\ProductPurchasePrice object. + * @see applyDefaults() + */ + public function __construct() + { + $this->applyDefaultValues(); + } + + /** + * Returns whether the object has been modified. + * + * @return boolean True if the object has been modified. + */ + public function isModified() + { + return !!$this->modifiedColumns; + } + + /** + * Has specified column been modified? + * + * @param string $col column fully qualified name (TableMap::TYPE_COLNAME), e.g. Book::AUTHOR_ID + * @return boolean True if $col has been modified. + */ + public function isColumnModified($col) + { + return $this->modifiedColumns && isset($this->modifiedColumns[$col]); + } + + /** + * Get the columns that have been modified in this object. + * @return array A unique list of the modified column names for this object. + */ + public function getModifiedColumns() + { + return $this->modifiedColumns ? array_keys($this->modifiedColumns) : []; + } + + /** + * Returns whether the object has ever been saved. This will + * be false, if the object was retrieved from storage or was created + * and then saved. + * + * @return boolean true, if the object has never been persisted. + */ + public function isNew() + { + return $this->new; + } + + /** + * Setter for the isNew attribute. This method will be called + * by Propel-generated children and objects. + * + * @param boolean $b the state of the object. + */ + public function setNew($b) + { + $this->new = (Boolean) $b; + } + + /** + * Whether this object has been deleted. + * @return boolean The deleted state of this object. + */ + public function isDeleted() + { + return $this->deleted; + } + + /** + * Specify whether this object has been deleted. + * @param boolean $b The deleted state of this object. + * @return void + */ + public function setDeleted($b) + { + $this->deleted = (Boolean) $b; + } + + /** + * Sets the modified state for the object to be false. + * @param string $col If supplied, only the specified column is reset. + * @return void + */ + public function resetModified($col = null) + { + if (null !== $col) { + if (isset($this->modifiedColumns[$col])) { + unset($this->modifiedColumns[$col]); + } + } else { + $this->modifiedColumns = array(); + } + } + + /** + * Compares this with another ProductPurchasePrice instance. If + * obj is an instance of ProductPurchasePrice, delegates to + * equals(ProductPurchasePrice). Otherwise, returns false. + * + * @param mixed $obj The object to compare to. + * @return boolean Whether equal to the object specified. + */ + public function equals($obj) + { + $thisclazz = get_class($this); + if (!is_object($obj) || !($obj instanceof $thisclazz)) { + return false; + } + + if ($this === $obj) { + return true; + } + + if (null === $this->getPrimaryKey() + || null === $obj->getPrimaryKey()) { + return false; + } + + return $this->getPrimaryKey() === $obj->getPrimaryKey(); + } + + /** + * If the primary key is not null, return the hashcode of the + * primary key. Otherwise, return the hash code of the object. + * + * @return int Hashcode + */ + public function hashCode() + { + if (null !== $this->getPrimaryKey()) { + return crc32(serialize($this->getPrimaryKey())); + } + + return crc32(serialize(clone $this)); + } + + /** + * Get the associative array of the virtual columns in this object + * + * @return array + */ + public function getVirtualColumns() + { + return $this->virtualColumns; + } + + /** + * Checks the existence of a virtual column in this object + * + * @param string $name The virtual column name + * @return boolean + */ + public function hasVirtualColumn($name) + { + return array_key_exists($name, $this->virtualColumns); + } + + /** + * Get the value of a virtual column in this object + * + * @param string $name The virtual column name + * @return mixed + * + * @throws PropelException + */ + public function getVirtualColumn($name) + { + if (!$this->hasVirtualColumn($name)) { + throw new PropelException(sprintf('Cannot get value of inexistent virtual column %s.', $name)); + } + + return $this->virtualColumns[$name]; + } + + /** + * Set the value of a virtual column in this object + * + * @param string $name The virtual column name + * @param mixed $value The value to give to the virtual column + * + * @return ProductPurchasePrice The current object, for fluid interface + */ + public function setVirtualColumn($name, $value) + { + $this->virtualColumns[$name] = $value; + + return $this; + } + + /** + * Logs a message using Propel::log(). + * + * @param string $msg + * @param int $priority One of the Propel::LOG_* logging levels + * @return boolean + */ + protected function log($msg, $priority = Propel::LOG_INFO) + { + return Propel::log(get_class($this) . ': ' . $msg, $priority); + } + + /** + * Populate the current object from a string, using a given parser format + * + * $book = new Book(); + * $book->importFrom('JSON', '{"Id":9012,"Title":"Don Juan","ISBN":"0140422161","Price":12.99,"PublisherId":1234,"AuthorId":5678}'); + * + * + * @param mixed $parser A AbstractParser instance, + * or a format name ('XML', 'YAML', 'JSON', 'CSV') + * @param string $data The source data to import from + * + * @return ProductPurchasePrice The current object, for fluid interface + */ + public function importFrom($parser, $data) + { + if (!$parser instanceof AbstractParser) { + $parser = AbstractParser::getParser($parser); + } + + $this->fromArray($parser->toArray($data), TableMap::TYPE_PHPNAME); + + return $this; + } + + /** + * Export the current object properties to a string, using a given parser format + * + * $book = BookQuery::create()->findPk(9012); + * echo $book->exportTo('JSON'); + * => {"Id":9012,"Title":"Don Juan","ISBN":"0140422161","Price":12.99,"PublisherId":1234,"AuthorId":5678}'); + * + * + * @param mixed $parser A AbstractParser instance, or a format name ('XML', 'YAML', 'JSON', 'CSV') + * @param boolean $includeLazyLoadColumns (optional) Whether to include lazy load(ed) columns. Defaults to TRUE. + * @return string The exported data + */ + public function exportTo($parser, $includeLazyLoadColumns = true) + { + if (!$parser instanceof AbstractParser) { + $parser = AbstractParser::getParser($parser); + } + + return $parser->fromArray($this->toArray(TableMap::TYPE_PHPNAME, $includeLazyLoadColumns, array(), true)); + } + + /** + * Clean up internal collections prior to serializing + * Avoids recursive loops that turn into segmentation faults when serializing + */ + public function __sleep() + { + $this->clearAllReferences(); + + return array_keys(get_object_vars($this)); + } + + /** + * Get the [product_sale_elements_id] column value. + * + * @return int + */ + public function getProductSaleElementsId() + { + + return $this->product_sale_elements_id; + } + + /** + * Get the [currency_id] column value. + * + * @return int + */ + public function getCurrencyId() + { + + return $this->currency_id; + } + + /** + * Get the [purchase_price] column value. + * + * @return string + */ + public function getPurchasePrice() + { + + return $this->purchase_price; + } + + /** + * Set the value of [product_sale_elements_id] column. + * + * @param int $v new value + * @return \CustomerFamily\Model\ProductPurchasePrice The current object (for fluent API support) + */ + public function setProductSaleElementsId($v) + { + if ($v !== null) { + $v = (int) $v; + } + + if ($this->product_sale_elements_id !== $v) { + $this->product_sale_elements_id = $v; + $this->modifiedColumns[ProductPurchasePriceTableMap::PRODUCT_SALE_ELEMENTS_ID] = true; + } + + if ($this->aProductSaleElements !== null && $this->aProductSaleElements->getId() !== $v) { + $this->aProductSaleElements = null; + } + + + return $this; + } // setProductSaleElementsId() + + /** + * Set the value of [currency_id] column. + * + * @param int $v new value + * @return \CustomerFamily\Model\ProductPurchasePrice The current object (for fluent API support) + */ + public function setCurrencyId($v) + { + if ($v !== null) { + $v = (int) $v; + } + + if ($this->currency_id !== $v) { + $this->currency_id = $v; + $this->modifiedColumns[ProductPurchasePriceTableMap::CURRENCY_ID] = true; + } + + if ($this->aCurrency !== null && $this->aCurrency->getId() !== $v) { + $this->aCurrency = null; + } + + + return $this; + } // setCurrencyId() + + /** + * Set the value of [purchase_price] column. + * + * @param string $v new value + * @return \CustomerFamily\Model\ProductPurchasePrice The current object (for fluent API support) + */ + public function setPurchasePrice($v) + { + if ($v !== null) { + $v = (string) $v; + } + + if ($this->purchase_price !== $v) { + $this->purchase_price = $v; + $this->modifiedColumns[ProductPurchasePriceTableMap::PURCHASE_PRICE] = true; + } + + + return $this; + } // setPurchasePrice() + + /** + * Indicates whether the columns in this object are only set to default values. + * + * This method can be used in conjunction with isModified() to indicate whether an object is both + * modified _and_ has some values set which are non-default. + * + * @return boolean Whether the columns in this object are only been set with default values. + */ + public function hasOnlyDefaultValues() + { + if ($this->purchase_price !== '0') { + return false; + } + + // otherwise, everything was equal, so return TRUE + return true; + } // hasOnlyDefaultValues() + + /** + * Hydrates (populates) the object variables with values from the database resultset. + * + * An offset (0-based "start column") is specified so that objects can be hydrated + * with a subset of the columns in the resultset rows. This is needed, for example, + * for results of JOIN queries where the resultset row includes columns from two or + * more tables. + * + * @param array $row The row returned by DataFetcher->fetch(). + * @param int $startcol 0-based offset column which indicates which restultset column to start with. + * @param boolean $rehydrate Whether this object is being re-hydrated from the database. + * @param string $indexType The index type of $row. Mostly DataFetcher->getIndexType(). + One of the class type constants TableMap::TYPE_PHPNAME, TableMap::TYPE_STUDLYPHPNAME + * TableMap::TYPE_COLNAME, TableMap::TYPE_FIELDNAME, TableMap::TYPE_NUM. + * + * @return int next starting column + * @throws PropelException - Any caught Exception will be rewrapped as a PropelException. + */ + public function hydrate($row, $startcol = 0, $rehydrate = false, $indexType = TableMap::TYPE_NUM) + { + try { + + + $col = $row[TableMap::TYPE_NUM == $indexType ? 0 + $startcol : ProductPurchasePriceTableMap::translateFieldName('ProductSaleElementsId', TableMap::TYPE_PHPNAME, $indexType)]; + $this->product_sale_elements_id = (null !== $col) ? (int) $col : null; + + $col = $row[TableMap::TYPE_NUM == $indexType ? 1 + $startcol : ProductPurchasePriceTableMap::translateFieldName('CurrencyId', TableMap::TYPE_PHPNAME, $indexType)]; + $this->currency_id = (null !== $col) ? (int) $col : null; + + $col = $row[TableMap::TYPE_NUM == $indexType ? 2 + $startcol : ProductPurchasePriceTableMap::translateFieldName('PurchasePrice', TableMap::TYPE_PHPNAME, $indexType)]; + $this->purchase_price = (null !== $col) ? (string) $col : null; + $this->resetModified(); + + $this->setNew(false); + + if ($rehydrate) { + $this->ensureConsistency(); + } + + return $startcol + 3; // 3 = ProductPurchasePriceTableMap::NUM_HYDRATE_COLUMNS. + + } catch (Exception $e) { + throw new PropelException("Error populating \CustomerFamily\Model\ProductPurchasePrice object", 0, $e); + } + } + + /** + * Checks and repairs the internal consistency of the object. + * + * This method is executed after an already-instantiated object is re-hydrated + * from the database. It exists to check any foreign keys to make sure that + * the objects related to the current object are correct based on foreign key. + * + * You can override this method in the stub class, but you should always invoke + * the base method from the overridden method (i.e. parent::ensureConsistency()), + * in case your model changes. + * + * @throws PropelException + */ + public function ensureConsistency() + { + if ($this->aProductSaleElements !== null && $this->product_sale_elements_id !== $this->aProductSaleElements->getId()) { + $this->aProductSaleElements = null; + } + if ($this->aCurrency !== null && $this->currency_id !== $this->aCurrency->getId()) { + $this->aCurrency = null; + } + } // ensureConsistency + + /** + * Reloads this object from datastore based on primary key and (optionally) resets all associated objects. + * + * This will only work if the object has been saved and has a valid primary key set. + * + * @param boolean $deep (optional) Whether to also de-associated any related objects. + * @param ConnectionInterface $con (optional) The ConnectionInterface connection to use. + * @return void + * @throws PropelException - if this object is deleted, unsaved or doesn't have pk match in db + */ + public function reload($deep = false, ConnectionInterface $con = null) + { + if ($this->isDeleted()) { + throw new PropelException("Cannot reload a deleted object."); + } + + if ($this->isNew()) { + throw new PropelException("Cannot reload an unsaved object."); + } + + if ($con === null) { + $con = Propel::getServiceContainer()->getReadConnection(ProductPurchasePriceTableMap::DATABASE_NAME); + } + + // We don't need to alter the object instance pool; we're just modifying this instance + // already in the pool. + + $dataFetcher = ChildProductPurchasePriceQuery::create(null, $this->buildPkeyCriteria())->setFormatter(ModelCriteria::FORMAT_STATEMENT)->find($con); + $row = $dataFetcher->fetch(); + $dataFetcher->close(); + if (!$row) { + throw new PropelException('Cannot find matching row in the database to reload object values.'); + } + $this->hydrate($row, 0, true, $dataFetcher->getIndexType()); // rehydrate + + if ($deep) { // also de-associate any related objects? + + $this->aProductSaleElements = null; + $this->aCurrency = null; + } // if (deep) + } + + /** + * Removes this object from datastore and sets delete attribute. + * + * @param ConnectionInterface $con + * @return void + * @throws PropelException + * @see ProductPurchasePrice::setDeleted() + * @see ProductPurchasePrice::isDeleted() + */ + public function delete(ConnectionInterface $con = null) + { + if ($this->isDeleted()) { + throw new PropelException("This object has already been deleted."); + } + + if ($con === null) { + $con = Propel::getServiceContainer()->getWriteConnection(ProductPurchasePriceTableMap::DATABASE_NAME); + } + + $con->beginTransaction(); + try { + $deleteQuery = ChildProductPurchasePriceQuery::create() + ->filterByPrimaryKey($this->getPrimaryKey()); + $ret = $this->preDelete($con); + if ($ret) { + $deleteQuery->delete($con); + $this->postDelete($con); + $con->commit(); + $this->setDeleted(true); + } else { + $con->commit(); + } + } catch (Exception $e) { + $con->rollBack(); + throw $e; + } + } + + /** + * Persists this object to the database. + * + * If the object is new, it inserts it; otherwise an update is performed. + * All modified related objects will also be persisted in the doSave() + * method. This method wraps all precipitate database operations in a + * single transaction. + * + * @param ConnectionInterface $con + * @return int The number of rows affected by this insert/update and any referring fk objects' save() operations. + * @throws PropelException + * @see doSave() + */ + public function save(ConnectionInterface $con = null) + { + if ($this->isDeleted()) { + throw new PropelException("You cannot save an object that has been deleted."); + } + + if ($con === null) { + $con = Propel::getServiceContainer()->getWriteConnection(ProductPurchasePriceTableMap::DATABASE_NAME); + } + + $con->beginTransaction(); + $isInsert = $this->isNew(); + try { + $ret = $this->preSave($con); + if ($isInsert) { + $ret = $ret && $this->preInsert($con); + } else { + $ret = $ret && $this->preUpdate($con); + } + if ($ret) { + $affectedRows = $this->doSave($con); + if ($isInsert) { + $this->postInsert($con); + } else { + $this->postUpdate($con); + } + $this->postSave($con); + ProductPurchasePriceTableMap::addInstanceToPool($this); + } else { + $affectedRows = 0; + } + $con->commit(); + + return $affectedRows; + } catch (Exception $e) { + $con->rollBack(); + throw $e; + } + } + + /** + * Performs the work of inserting or updating the row in the database. + * + * If the object is new, it inserts it; otherwise an update is performed. + * All related objects are also updated in this method. + * + * @param ConnectionInterface $con + * @return int The number of rows affected by this insert/update and any referring fk objects' save() operations. + * @throws PropelException + * @see save() + */ + protected function doSave(ConnectionInterface $con) + { + $affectedRows = 0; // initialize var to track total num of affected rows + if (!$this->alreadyInSave) { + $this->alreadyInSave = true; + + // We call the save method on the following object(s) if they + // were passed to this object by their corresponding set + // method. This object relates to these object(s) by a + // foreign key reference. + + if ($this->aProductSaleElements !== null) { + if ($this->aProductSaleElements->isModified() || $this->aProductSaleElements->isNew()) { + $affectedRows += $this->aProductSaleElements->save($con); + } + $this->setProductSaleElements($this->aProductSaleElements); + } + + if ($this->aCurrency !== null) { + if ($this->aCurrency->isModified() || $this->aCurrency->isNew()) { + $affectedRows += $this->aCurrency->save($con); + } + $this->setCurrency($this->aCurrency); + } + + if ($this->isNew() || $this->isModified()) { + // persist changes + if ($this->isNew()) { + $this->doInsert($con); + } else { + $this->doUpdate($con); + } + $affectedRows += 1; + $this->resetModified(); + } + + $this->alreadyInSave = false; + + } + + return $affectedRows; + } // doSave() + + /** + * Insert the row in the database. + * + * @param ConnectionInterface $con + * + * @throws PropelException + * @see doSave() + */ + protected function doInsert(ConnectionInterface $con) + { + $modifiedColumns = array(); + $index = 0; + + + // check the columns in natural order for more readable SQL queries + if ($this->isColumnModified(ProductPurchasePriceTableMap::PRODUCT_SALE_ELEMENTS_ID)) { + $modifiedColumns[':p' . $index++] = 'PRODUCT_SALE_ELEMENTS_ID'; + } + if ($this->isColumnModified(ProductPurchasePriceTableMap::CURRENCY_ID)) { + $modifiedColumns[':p' . $index++] = 'CURRENCY_ID'; + } + if ($this->isColumnModified(ProductPurchasePriceTableMap::PURCHASE_PRICE)) { + $modifiedColumns[':p' . $index++] = 'PURCHASE_PRICE'; + } + + $sql = sprintf( + 'INSERT INTO product_purchase_price (%s) VALUES (%s)', + implode(', ', $modifiedColumns), + implode(', ', array_keys($modifiedColumns)) + ); + + try { + $stmt = $con->prepare($sql); + foreach ($modifiedColumns as $identifier => $columnName) { + switch ($columnName) { + case 'PRODUCT_SALE_ELEMENTS_ID': + $stmt->bindValue($identifier, $this->product_sale_elements_id, PDO::PARAM_INT); + break; + case 'CURRENCY_ID': + $stmt->bindValue($identifier, $this->currency_id, PDO::PARAM_INT); + break; + case 'PURCHASE_PRICE': + $stmt->bindValue($identifier, $this->purchase_price, PDO::PARAM_STR); + break; + } + } + $stmt->execute(); + } catch (Exception $e) { + Propel::log($e->getMessage(), Propel::LOG_ERR); + throw new PropelException(sprintf('Unable to execute INSERT statement [%s]', $sql), 0, $e); + } + + $this->setNew(false); + } + + /** + * Update the row in the database. + * + * @param ConnectionInterface $con + * + * @return Integer Number of updated rows + * @see doSave() + */ + protected function doUpdate(ConnectionInterface $con) + { + $selectCriteria = $this->buildPkeyCriteria(); + $valuesCriteria = $this->buildCriteria(); + + return $selectCriteria->doUpdate($valuesCriteria, $con); + } + + /** + * Retrieves a field from the object by name passed in as a string. + * + * @param string $name name + * @param string $type The type of fieldname the $name is of: + * one of the class type constants TableMap::TYPE_PHPNAME, TableMap::TYPE_STUDLYPHPNAME + * TableMap::TYPE_COLNAME, TableMap::TYPE_FIELDNAME, TableMap::TYPE_NUM. + * Defaults to TableMap::TYPE_PHPNAME. + * @return mixed Value of field. + */ + public function getByName($name, $type = TableMap::TYPE_PHPNAME) + { + $pos = ProductPurchasePriceTableMap::translateFieldName($name, $type, TableMap::TYPE_NUM); + $field = $this->getByPosition($pos); + + return $field; + } + + /** + * Retrieves a field from the object by Position as specified in the xml schema. + * Zero-based. + * + * @param int $pos position in xml schema + * @return mixed Value of field at $pos + */ + public function getByPosition($pos) + { + switch ($pos) { + case 0: + return $this->getProductSaleElementsId(); + break; + case 1: + return $this->getCurrencyId(); + break; + case 2: + return $this->getPurchasePrice(); + break; + default: + return null; + break; + } // switch() + } + + /** + * Exports the object as an array. + * + * You can specify the key type of the array by passing one of the class + * type constants. + * + * @param string $keyType (optional) One of the class type constants TableMap::TYPE_PHPNAME, TableMap::TYPE_STUDLYPHPNAME, + * TableMap::TYPE_COLNAME, TableMap::TYPE_FIELDNAME, TableMap::TYPE_NUM. + * Defaults to TableMap::TYPE_PHPNAME. + * @param boolean $includeLazyLoadColumns (optional) Whether to include lazy loaded columns. Defaults to TRUE. + * @param array $alreadyDumpedObjects List of objects to skip to avoid recursion + * @param boolean $includeForeignObjects (optional) Whether to include hydrated related objects. Default to FALSE. + * + * @return array an associative array containing the field names (as keys) and field values + */ + public function toArray($keyType = TableMap::TYPE_PHPNAME, $includeLazyLoadColumns = true, $alreadyDumpedObjects = array(), $includeForeignObjects = false) + { + if (isset($alreadyDumpedObjects['ProductPurchasePrice'][serialize($this->getPrimaryKey())])) { + return '*RECURSION*'; + } + $alreadyDumpedObjects['ProductPurchasePrice'][serialize($this->getPrimaryKey())] = true; + $keys = ProductPurchasePriceTableMap::getFieldNames($keyType); + $result = array( + $keys[0] => $this->getProductSaleElementsId(), + $keys[1] => $this->getCurrencyId(), + $keys[2] => $this->getPurchasePrice(), + ); + $virtualColumns = $this->virtualColumns; + foreach ($virtualColumns as $key => $virtualColumn) { + $result[$key] = $virtualColumn; + } + + if ($includeForeignObjects) { + if (null !== $this->aProductSaleElements) { + $result['ProductSaleElements'] = $this->aProductSaleElements->toArray($keyType, $includeLazyLoadColumns, $alreadyDumpedObjects, true); + } + if (null !== $this->aCurrency) { + $result['Currency'] = $this->aCurrency->toArray($keyType, $includeLazyLoadColumns, $alreadyDumpedObjects, true); + } + } + + return $result; + } + + /** + * Sets a field from the object by name passed in as a string. + * + * @param string $name + * @param mixed $value field value + * @param string $type The type of fieldname the $name is of: + * one of the class type constants TableMap::TYPE_PHPNAME, TableMap::TYPE_STUDLYPHPNAME + * TableMap::TYPE_COLNAME, TableMap::TYPE_FIELDNAME, TableMap::TYPE_NUM. + * Defaults to TableMap::TYPE_PHPNAME. + * @return void + */ + public function setByName($name, $value, $type = TableMap::TYPE_PHPNAME) + { + $pos = ProductPurchasePriceTableMap::translateFieldName($name, $type, TableMap::TYPE_NUM); + + return $this->setByPosition($pos, $value); + } + + /** + * Sets a field from the object by Position as specified in the xml schema. + * Zero-based. + * + * @param int $pos position in xml schema + * @param mixed $value field value + * @return void + */ + public function setByPosition($pos, $value) + { + switch ($pos) { + case 0: + $this->setProductSaleElementsId($value); + break; + case 1: + $this->setCurrencyId($value); + break; + case 2: + $this->setPurchasePrice($value); + break; + } // switch() + } + + /** + * Populates the object using an array. + * + * This is particularly useful when populating an object from one of the + * request arrays (e.g. $_POST). This method goes through the column + * names, checking to see whether a matching key exists in populated + * array. If so the setByName() method is called for that column. + * + * You can specify the key type of the array by additionally passing one + * of the class type constants TableMap::TYPE_PHPNAME, TableMap::TYPE_STUDLYPHPNAME, + * TableMap::TYPE_COLNAME, TableMap::TYPE_FIELDNAME, TableMap::TYPE_NUM. + * The default key type is the column's TableMap::TYPE_PHPNAME. + * + * @param array $arr An array to populate the object from. + * @param string $keyType The type of keys the array uses. + * @return void + */ + public function fromArray($arr, $keyType = TableMap::TYPE_PHPNAME) + { + $keys = ProductPurchasePriceTableMap::getFieldNames($keyType); + + if (array_key_exists($keys[0], $arr)) $this->setProductSaleElementsId($arr[$keys[0]]); + if (array_key_exists($keys[1], $arr)) $this->setCurrencyId($arr[$keys[1]]); + if (array_key_exists($keys[2], $arr)) $this->setPurchasePrice($arr[$keys[2]]); + } + + /** + * Build a Criteria object containing the values of all modified columns in this object. + * + * @return Criteria The Criteria object containing all modified values. + */ + public function buildCriteria() + { + $criteria = new Criteria(ProductPurchasePriceTableMap::DATABASE_NAME); + + if ($this->isColumnModified(ProductPurchasePriceTableMap::PRODUCT_SALE_ELEMENTS_ID)) $criteria->add(ProductPurchasePriceTableMap::PRODUCT_SALE_ELEMENTS_ID, $this->product_sale_elements_id); + if ($this->isColumnModified(ProductPurchasePriceTableMap::CURRENCY_ID)) $criteria->add(ProductPurchasePriceTableMap::CURRENCY_ID, $this->currency_id); + if ($this->isColumnModified(ProductPurchasePriceTableMap::PURCHASE_PRICE)) $criteria->add(ProductPurchasePriceTableMap::PURCHASE_PRICE, $this->purchase_price); + + return $criteria; + } + + /** + * Builds a Criteria object containing the primary key for this object. + * + * Unlike buildCriteria() this method includes the primary key values regardless + * of whether or not they have been modified. + * + * @return Criteria The Criteria object containing value(s) for primary key(s). + */ + public function buildPkeyCriteria() + { + $criteria = new Criteria(ProductPurchasePriceTableMap::DATABASE_NAME); + $criteria->add(ProductPurchasePriceTableMap::PRODUCT_SALE_ELEMENTS_ID, $this->product_sale_elements_id); + $criteria->add(ProductPurchasePriceTableMap::CURRENCY_ID, $this->currency_id); + + return $criteria; + } + + /** + * Returns the composite primary key for this object. + * The array elements will be in same order as specified in XML. + * @return array + */ + public function getPrimaryKey() + { + $pks = array(); + $pks[0] = $this->getProductSaleElementsId(); + $pks[1] = $this->getCurrencyId(); + + return $pks; + } + + /** + * Set the [composite] primary key. + * + * @param array $keys The elements of the composite key (order must match the order in XML file). + * @return void + */ + public function setPrimaryKey($keys) + { + $this->setProductSaleElementsId($keys[0]); + $this->setCurrencyId($keys[1]); + } + + /** + * Returns true if the primary key for this object is null. + * @return boolean + */ + public function isPrimaryKeyNull() + { + + return (null === $this->getProductSaleElementsId()) && (null === $this->getCurrencyId()); + } + + /** + * Sets contents of passed object to values from current object. + * + * If desired, this method can also make copies of all associated (fkey referrers) + * objects. + * + * @param object $copyObj An object of \CustomerFamily\Model\ProductPurchasePrice (or compatible) type. + * @param boolean $deepCopy Whether to also copy all rows that refer (by fkey) to the current row. + * @param boolean $makeNew Whether to reset autoincrement PKs and make the object new. + * @throws PropelException + */ + public function copyInto($copyObj, $deepCopy = false, $makeNew = true) + { + $copyObj->setProductSaleElementsId($this->getProductSaleElementsId()); + $copyObj->setCurrencyId($this->getCurrencyId()); + $copyObj->setPurchasePrice($this->getPurchasePrice()); + if ($makeNew) { + $copyObj->setNew(true); + } + } + + /** + * Makes a copy of this object that will be inserted as a new row in table when saved. + * It creates a new object filling in the simple attributes, but skipping any primary + * keys that are defined for the table. + * + * If desired, this method can also make copies of all associated (fkey referrers) + * objects. + * + * @param boolean $deepCopy Whether to also copy all rows that refer (by fkey) to the current row. + * @return \CustomerFamily\Model\ProductPurchasePrice Clone of current object. + * @throws PropelException + */ + public function copy($deepCopy = false) + { + // we use get_class(), because this might be a subclass + $clazz = get_class($this); + $copyObj = new $clazz(); + $this->copyInto($copyObj, $deepCopy); + + return $copyObj; + } + + /** + * Declares an association between this object and a ChildProductSaleElements object. + * + * @param ChildProductSaleElements $v + * @return \CustomerFamily\Model\ProductPurchasePrice The current object (for fluent API support) + * @throws PropelException + */ + public function setProductSaleElements(ChildProductSaleElements $v = null) + { + if ($v === null) { + $this->setProductSaleElementsId(NULL); + } else { + $this->setProductSaleElementsId($v->getId()); + } + + $this->aProductSaleElements = $v; + + // Add binding for other direction of this n:n relationship. + // If this object has already been added to the ChildProductSaleElements object, it will not be re-added. + if ($v !== null) { + $v->addProductPurchasePrice($this); + } + + + return $this; + } + + + /** + * Get the associated ChildProductSaleElements object + * + * @param ConnectionInterface $con Optional Connection object. + * @return ChildProductSaleElements The associated ChildProductSaleElements object. + * @throws PropelException + */ + public function getProductSaleElements(ConnectionInterface $con = null) + { + if ($this->aProductSaleElements === null && ($this->product_sale_elements_id !== null)) { + $this->aProductSaleElements = ProductSaleElementsQuery::create()->findPk($this->product_sale_elements_id, $con); + /* The following can be used additionally to + guarantee the related object contains a reference + to this object. This level of coupling may, however, be + undesirable since it could result in an only partially populated collection + in the referenced object. + $this->aProductSaleElements->addProductPurchasePrices($this); + */ + } + + return $this->aProductSaleElements; + } + + /** + * Declares an association between this object and a ChildCurrency object. + * + * @param ChildCurrency $v + * @return \CustomerFamily\Model\ProductPurchasePrice The current object (for fluent API support) + * @throws PropelException + */ + public function setCurrency(ChildCurrency $v = null) + { + if ($v === null) { + $this->setCurrencyId(NULL); + } else { + $this->setCurrencyId($v->getId()); + } + + $this->aCurrency = $v; + + // Add binding for other direction of this n:n relationship. + // If this object has already been added to the ChildCurrency object, it will not be re-added. + if ($v !== null) { + $v->addProductPurchasePrice($this); + } + + + return $this; + } + + + /** + * Get the associated ChildCurrency object + * + * @param ConnectionInterface $con Optional Connection object. + * @return ChildCurrency The associated ChildCurrency object. + * @throws PropelException + */ + public function getCurrency(ConnectionInterface $con = null) + { + if ($this->aCurrency === null && ($this->currency_id !== null)) { + $this->aCurrency = CurrencyQuery::create()->findPk($this->currency_id, $con); + /* The following can be used additionally to + guarantee the related object contains a reference + to this object. This level of coupling may, however, be + undesirable since it could result in an only partially populated collection + in the referenced object. + $this->aCurrency->addProductPurchasePrices($this); + */ + } + + return $this->aCurrency; + } + + /** + * Clears the current object and sets all attributes to their default values + */ + public function clear() + { + $this->product_sale_elements_id = null; + $this->currency_id = null; + $this->purchase_price = null; + $this->alreadyInSave = false; + $this->clearAllReferences(); + $this->applyDefaultValues(); + $this->resetModified(); + $this->setNew(true); + $this->setDeleted(false); + } + + /** + * Resets all references to other model objects or collections of model objects. + * + * This method is a user-space workaround for PHP's inability to garbage collect + * objects with circular references (even in PHP 5.3). This is currently necessary + * when using Propel in certain daemon or large-volume/high-memory operations. + * + * @param boolean $deep Whether to also clear the references on all referrer objects. + */ + public function clearAllReferences($deep = false) + { + if ($deep) { + } // if ($deep) + + $this->aProductSaleElements = null; + $this->aCurrency = null; + } + + /** + * Return the string representation of this object + * + * @return string + */ + public function __toString() + { + return (string) $this->exportTo(ProductPurchasePriceTableMap::DEFAULT_STRING_FORMAT); + } + + /** + * Code to be run before persisting the object + * @param ConnectionInterface $con + * @return boolean + */ + public function preSave(ConnectionInterface $con = null) + { + return true; + } + + /** + * Code to be run after persisting the object + * @param ConnectionInterface $con + */ + public function postSave(ConnectionInterface $con = null) + { + + } + + /** + * Code to be run before inserting to database + * @param ConnectionInterface $con + * @return boolean + */ + public function preInsert(ConnectionInterface $con = null) + { + return true; + } + + /** + * Code to be run after inserting to database + * @param ConnectionInterface $con + */ + public function postInsert(ConnectionInterface $con = null) + { + + } + + /** + * Code to be run before updating the object in database + * @param ConnectionInterface $con + * @return boolean + */ + public function preUpdate(ConnectionInterface $con = null) + { + return true; + } + + /** + * Code to be run after updating the object in database + * @param ConnectionInterface $con + */ + public function postUpdate(ConnectionInterface $con = null) + { + + } + + /** + * Code to be run before deleting the object in database + * @param ConnectionInterface $con + * @return boolean + */ + public function preDelete(ConnectionInterface $con = null) + { + return true; + } + + /** + * Code to be run after deleting the object in database + * @param ConnectionInterface $con + */ + public function postDelete(ConnectionInterface $con = null) + { + + } + + + /** + * Derived method to catches calls to undefined methods. + * + * Provides magic import/export method support (fromXML()/toXML(), fromYAML()/toYAML(), etc.). + * Allows to define default __call() behavior if you overwrite __call() + * + * @param string $name + * @param mixed $params + * + * @return array|string + */ + public function __call($name, $params) + { + if (0 === strpos($name, 'get')) { + $virtualColumn = substr($name, 3); + if ($this->hasVirtualColumn($virtualColumn)) { + return $this->getVirtualColumn($virtualColumn); + } + + $virtualColumn = lcfirst($virtualColumn); + if ($this->hasVirtualColumn($virtualColumn)) { + return $this->getVirtualColumn($virtualColumn); + } + } + + if (0 === strpos($name, 'from')) { + $format = substr($name, 4); + + return $this->importFrom($format, reset($params)); + } + + if (0 === strpos($name, 'to')) { + $format = substr($name, 2); + $includeLazyLoadColumns = isset($params[0]) ? $params[0] : true; + + return $this->exportTo($format, $includeLazyLoadColumns); + } + + throw new BadMethodCallException(sprintf('Call to undefined method: %s.', $name)); + } + +} diff --git a/local/modules/CustomerFamily/Model/Base/ProductPurchasePriceQuery.php b/local/modules/CustomerFamily/Model/Base/ProductPurchasePriceQuery.php new file mode 100644 index 00000000..3a3515b4 --- /dev/null +++ b/local/modules/CustomerFamily/Model/Base/ProductPurchasePriceQuery.php @@ -0,0 +1,615 @@ +setModelAlias($modelAlias); + } + if ($criteria instanceof Criteria) { + $query->mergeWith($criteria); + } + + return $query; + } + + /** + * Find object by primary key. + * Propel uses the instance pool to skip the database if the object exists. + * Go fast if the query is untouched. + * + * + * $obj = $c->findPk(array(12, 34), $con); + * + * + * @param array[$product_sale_elements_id, $currency_id] $key Primary key to use for the query + * @param ConnectionInterface $con an optional connection object + * + * @return ChildProductPurchasePrice|array|mixed the result, formatted by the current formatter + */ + public function findPk($key, $con = null) + { + if ($key === null) { + return null; + } + if ((null !== ($obj = ProductPurchasePriceTableMap::getInstanceFromPool(serialize(array((string) $key[0], (string) $key[1]))))) && !$this->formatter) { + // the object is already in the instance pool + return $obj; + } + if ($con === null) { + $con = Propel::getServiceContainer()->getReadConnection(ProductPurchasePriceTableMap::DATABASE_NAME); + } + $this->basePreSelect($con); + if ($this->formatter || $this->modelAlias || $this->with || $this->select + || $this->selectColumns || $this->asColumns || $this->selectModifiers + || $this->map || $this->having || $this->joins) { + return $this->findPkComplex($key, $con); + } else { + return $this->findPkSimple($key, $con); + } + } + + /** + * Find object by primary key using raw SQL to go fast. + * Bypass doSelect() and the object formatter by using generated code. + * + * @param mixed $key Primary key to use for the query + * @param ConnectionInterface $con A connection object + * + * @return ChildProductPurchasePrice A model object, or null if the key is not found + */ + protected function findPkSimple($key, $con) + { + $sql = 'SELECT PRODUCT_SALE_ELEMENTS_ID, CURRENCY_ID, PURCHASE_PRICE FROM product_purchase_price WHERE PRODUCT_SALE_ELEMENTS_ID = :p0 AND CURRENCY_ID = :p1'; + try { + $stmt = $con->prepare($sql); + $stmt->bindValue(':p0', $key[0], PDO::PARAM_INT); + $stmt->bindValue(':p1', $key[1], PDO::PARAM_INT); + $stmt->execute(); + } catch (Exception $e) { + Propel::log($e->getMessage(), Propel::LOG_ERR); + throw new PropelException(sprintf('Unable to execute SELECT statement [%s]', $sql), 0, $e); + } + $obj = null; + if ($row = $stmt->fetch(\PDO::FETCH_NUM)) { + $obj = new ChildProductPurchasePrice(); + $obj->hydrate($row); + ProductPurchasePriceTableMap::addInstanceToPool($obj, serialize(array((string) $key[0], (string) $key[1]))); + } + $stmt->closeCursor(); + + return $obj; + } + + /** + * Find object by primary key. + * + * @param mixed $key Primary key to use for the query + * @param ConnectionInterface $con A connection object + * + * @return ChildProductPurchasePrice|array|mixed the result, formatted by the current formatter + */ + protected function findPkComplex($key, $con) + { + // As the query uses a PK condition, no limit(1) is necessary. + $criteria = $this->isKeepQuery() ? clone $this : $this; + $dataFetcher = $criteria + ->filterByPrimaryKey($key) + ->doSelect($con); + + return $criteria->getFormatter()->init($criteria)->formatOne($dataFetcher); + } + + /** + * Find objects by primary key + * + * $objs = $c->findPks(array(array(12, 56), array(832, 123), array(123, 456)), $con); + * + * @param array $keys Primary keys to use for the query + * @param ConnectionInterface $con an optional connection object + * + * @return ObjectCollection|array|mixed the list of results, formatted by the current formatter + */ + public function findPks($keys, $con = null) + { + if (null === $con) { + $con = Propel::getServiceContainer()->getReadConnection($this->getDbName()); + } + $this->basePreSelect($con); + $criteria = $this->isKeepQuery() ? clone $this : $this; + $dataFetcher = $criteria + ->filterByPrimaryKeys($keys) + ->doSelect($con); + + return $criteria->getFormatter()->init($criteria)->format($dataFetcher); + } + + /** + * Filter the query by primary key + * + * @param mixed $key Primary key to use for the query + * + * @return ChildProductPurchasePriceQuery The current query, for fluid interface + */ + public function filterByPrimaryKey($key) + { + $this->addUsingAlias(ProductPurchasePriceTableMap::PRODUCT_SALE_ELEMENTS_ID, $key[0], Criteria::EQUAL); + $this->addUsingAlias(ProductPurchasePriceTableMap::CURRENCY_ID, $key[1], Criteria::EQUAL); + + return $this; + } + + /** + * Filter the query by a list of primary keys + * + * @param array $keys The list of primary key to use for the query + * + * @return ChildProductPurchasePriceQuery The current query, for fluid interface + */ + public function filterByPrimaryKeys($keys) + { + if (empty($keys)) { + return $this->add(null, '1<>1', Criteria::CUSTOM); + } + foreach ($keys as $key) { + $cton0 = $this->getNewCriterion(ProductPurchasePriceTableMap::PRODUCT_SALE_ELEMENTS_ID, $key[0], Criteria::EQUAL); + $cton1 = $this->getNewCriterion(ProductPurchasePriceTableMap::CURRENCY_ID, $key[1], Criteria::EQUAL); + $cton0->addAnd($cton1); + $this->addOr($cton0); + } + + return $this; + } + + /** + * Filter the query on the product_sale_elements_id column + * + * Example usage: + * + * $query->filterByProductSaleElementsId(1234); // WHERE product_sale_elements_id = 1234 + * $query->filterByProductSaleElementsId(array(12, 34)); // WHERE product_sale_elements_id IN (12, 34) + * $query->filterByProductSaleElementsId(array('min' => 12)); // WHERE product_sale_elements_id > 12 + * + * + * @see filterByProductSaleElements() + * + * @param mixed $productSaleElementsId The value to use as filter. + * Use scalar values for equality. + * Use array values for in_array() equivalent. + * Use associative array('min' => $minValue, 'max' => $maxValue) for intervals. + * @param string $comparison Operator to use for the column comparison, defaults to Criteria::EQUAL + * + * @return ChildProductPurchasePriceQuery The current query, for fluid interface + */ + public function filterByProductSaleElementsId($productSaleElementsId = null, $comparison = null) + { + if (is_array($productSaleElementsId)) { + $useMinMax = false; + if (isset($productSaleElementsId['min'])) { + $this->addUsingAlias(ProductPurchasePriceTableMap::PRODUCT_SALE_ELEMENTS_ID, $productSaleElementsId['min'], Criteria::GREATER_EQUAL); + $useMinMax = true; + } + if (isset($productSaleElementsId['max'])) { + $this->addUsingAlias(ProductPurchasePriceTableMap::PRODUCT_SALE_ELEMENTS_ID, $productSaleElementsId['max'], Criteria::LESS_EQUAL); + $useMinMax = true; + } + if ($useMinMax) { + return $this; + } + if (null === $comparison) { + $comparison = Criteria::IN; + } + } + + return $this->addUsingAlias(ProductPurchasePriceTableMap::PRODUCT_SALE_ELEMENTS_ID, $productSaleElementsId, $comparison); + } + + /** + * Filter the query on the currency_id column + * + * Example usage: + * + * $query->filterByCurrencyId(1234); // WHERE currency_id = 1234 + * $query->filterByCurrencyId(array(12, 34)); // WHERE currency_id IN (12, 34) + * $query->filterByCurrencyId(array('min' => 12)); // WHERE currency_id > 12 + * + * + * @see filterByCurrency() + * + * @param mixed $currencyId The value to use as filter. + * Use scalar values for equality. + * Use array values for in_array() equivalent. + * Use associative array('min' => $minValue, 'max' => $maxValue) for intervals. + * @param string $comparison Operator to use for the column comparison, defaults to Criteria::EQUAL + * + * @return ChildProductPurchasePriceQuery The current query, for fluid interface + */ + public function filterByCurrencyId($currencyId = null, $comparison = null) + { + if (is_array($currencyId)) { + $useMinMax = false; + if (isset($currencyId['min'])) { + $this->addUsingAlias(ProductPurchasePriceTableMap::CURRENCY_ID, $currencyId['min'], Criteria::GREATER_EQUAL); + $useMinMax = true; + } + if (isset($currencyId['max'])) { + $this->addUsingAlias(ProductPurchasePriceTableMap::CURRENCY_ID, $currencyId['max'], Criteria::LESS_EQUAL); + $useMinMax = true; + } + if ($useMinMax) { + return $this; + } + if (null === $comparison) { + $comparison = Criteria::IN; + } + } + + return $this->addUsingAlias(ProductPurchasePriceTableMap::CURRENCY_ID, $currencyId, $comparison); + } + + /** + * Filter the query on the purchase_price column + * + * Example usage: + * + * $query->filterByPurchasePrice(1234); // WHERE purchase_price = 1234 + * $query->filterByPurchasePrice(array(12, 34)); // WHERE purchase_price IN (12, 34) + * $query->filterByPurchasePrice(array('min' => 12)); // WHERE purchase_price > 12 + * + * + * @param mixed $purchasePrice The value to use as filter. + * Use scalar values for equality. + * Use array values for in_array() equivalent. + * Use associative array('min' => $minValue, 'max' => $maxValue) for intervals. + * @param string $comparison Operator to use for the column comparison, defaults to Criteria::EQUAL + * + * @return ChildProductPurchasePriceQuery The current query, for fluid interface + */ + public function filterByPurchasePrice($purchasePrice = null, $comparison = null) + { + if (is_array($purchasePrice)) { + $useMinMax = false; + if (isset($purchasePrice['min'])) { + $this->addUsingAlias(ProductPurchasePriceTableMap::PURCHASE_PRICE, $purchasePrice['min'], Criteria::GREATER_EQUAL); + $useMinMax = true; + } + if (isset($purchasePrice['max'])) { + $this->addUsingAlias(ProductPurchasePriceTableMap::PURCHASE_PRICE, $purchasePrice['max'], Criteria::LESS_EQUAL); + $useMinMax = true; + } + if ($useMinMax) { + return $this; + } + if (null === $comparison) { + $comparison = Criteria::IN; + } + } + + return $this->addUsingAlias(ProductPurchasePriceTableMap::PURCHASE_PRICE, $purchasePrice, $comparison); + } + + /** + * Filter the query by a related \CustomerFamily\Model\Thelia\Model\ProductSaleElements object + * + * @param \CustomerFamily\Model\Thelia\Model\ProductSaleElements|ObjectCollection $productSaleElements The related object(s) to use as filter + * @param string $comparison Operator to use for the column comparison, defaults to Criteria::EQUAL + * + * @return ChildProductPurchasePriceQuery The current query, for fluid interface + */ + public function filterByProductSaleElements($productSaleElements, $comparison = null) + { + if ($productSaleElements instanceof \CustomerFamily\Model\Thelia\Model\ProductSaleElements) { + return $this + ->addUsingAlias(ProductPurchasePriceTableMap::PRODUCT_SALE_ELEMENTS_ID, $productSaleElements->getId(), $comparison); + } elseif ($productSaleElements instanceof ObjectCollection) { + if (null === $comparison) { + $comparison = Criteria::IN; + } + + return $this + ->addUsingAlias(ProductPurchasePriceTableMap::PRODUCT_SALE_ELEMENTS_ID, $productSaleElements->toKeyValue('PrimaryKey', 'Id'), $comparison); + } else { + throw new PropelException('filterByProductSaleElements() only accepts arguments of type \CustomerFamily\Model\Thelia\Model\ProductSaleElements or Collection'); + } + } + + /** + * Adds a JOIN clause to the query using the ProductSaleElements relation + * + * @param string $relationAlias optional alias for the relation + * @param string $joinType Accepted values are null, 'left join', 'right join', 'inner join' + * + * @return ChildProductPurchasePriceQuery The current query, for fluid interface + */ + public function joinProductSaleElements($relationAlias = null, $joinType = Criteria::INNER_JOIN) + { + $tableMap = $this->getTableMap(); + $relationMap = $tableMap->getRelation('ProductSaleElements'); + + // create a ModelJoin object for this join + $join = new ModelJoin(); + $join->setJoinType($joinType); + $join->setRelationMap($relationMap, $this->useAliasInSQL ? $this->getModelAlias() : null, $relationAlias); + if ($previousJoin = $this->getPreviousJoin()) { + $join->setPreviousJoin($previousJoin); + } + + // add the ModelJoin to the current object + if ($relationAlias) { + $this->addAlias($relationAlias, $relationMap->getRightTable()->getName()); + $this->addJoinObject($join, $relationAlias); + } else { + $this->addJoinObject($join, 'ProductSaleElements'); + } + + return $this; + } + + /** + * Use the ProductSaleElements relation ProductSaleElements object + * + * @see useQuery() + * + * @param string $relationAlias optional alias for the relation, + * to be used as main alias in the secondary query + * @param string $joinType Accepted values are null, 'left join', 'right join', 'inner join' + * + * @return \CustomerFamily\Model\Thelia\Model\ProductSaleElementsQuery A secondary query class using the current class as primary query + */ + public function useProductSaleElementsQuery($relationAlias = null, $joinType = Criteria::INNER_JOIN) + { + return $this + ->joinProductSaleElements($relationAlias, $joinType) + ->useQuery($relationAlias ? $relationAlias : 'ProductSaleElements', '\CustomerFamily\Model\Thelia\Model\ProductSaleElementsQuery'); + } + + /** + * Filter the query by a related \CustomerFamily\Model\Thelia\Model\Currency object + * + * @param \CustomerFamily\Model\Thelia\Model\Currency|ObjectCollection $currency The related object(s) to use as filter + * @param string $comparison Operator to use for the column comparison, defaults to Criteria::EQUAL + * + * @return ChildProductPurchasePriceQuery The current query, for fluid interface + */ + public function filterByCurrency($currency, $comparison = null) + { + if ($currency instanceof \CustomerFamily\Model\Thelia\Model\Currency) { + return $this + ->addUsingAlias(ProductPurchasePriceTableMap::CURRENCY_ID, $currency->getId(), $comparison); + } elseif ($currency instanceof ObjectCollection) { + if (null === $comparison) { + $comparison = Criteria::IN; + } + + return $this + ->addUsingAlias(ProductPurchasePriceTableMap::CURRENCY_ID, $currency->toKeyValue('PrimaryKey', 'Id'), $comparison); + } else { + throw new PropelException('filterByCurrency() only accepts arguments of type \CustomerFamily\Model\Thelia\Model\Currency or Collection'); + } + } + + /** + * Adds a JOIN clause to the query using the Currency relation + * + * @param string $relationAlias optional alias for the relation + * @param string $joinType Accepted values are null, 'left join', 'right join', 'inner join' + * + * @return ChildProductPurchasePriceQuery The current query, for fluid interface + */ + public function joinCurrency($relationAlias = null, $joinType = Criteria::INNER_JOIN) + { + $tableMap = $this->getTableMap(); + $relationMap = $tableMap->getRelation('Currency'); + + // create a ModelJoin object for this join + $join = new ModelJoin(); + $join->setJoinType($joinType); + $join->setRelationMap($relationMap, $this->useAliasInSQL ? $this->getModelAlias() : null, $relationAlias); + if ($previousJoin = $this->getPreviousJoin()) { + $join->setPreviousJoin($previousJoin); + } + + // add the ModelJoin to the current object + if ($relationAlias) { + $this->addAlias($relationAlias, $relationMap->getRightTable()->getName()); + $this->addJoinObject($join, $relationAlias); + } else { + $this->addJoinObject($join, 'Currency'); + } + + return $this; + } + + /** + * Use the Currency relation Currency object + * + * @see useQuery() + * + * @param string $relationAlias optional alias for the relation, + * to be used as main alias in the secondary query + * @param string $joinType Accepted values are null, 'left join', 'right join', 'inner join' + * + * @return \CustomerFamily\Model\Thelia\Model\CurrencyQuery A secondary query class using the current class as primary query + */ + public function useCurrencyQuery($relationAlias = null, $joinType = Criteria::INNER_JOIN) + { + return $this + ->joinCurrency($relationAlias, $joinType) + ->useQuery($relationAlias ? $relationAlias : 'Currency', '\CustomerFamily\Model\Thelia\Model\CurrencyQuery'); + } + + /** + * Exclude object from result + * + * @param ChildProductPurchasePrice $productPurchasePrice Object to remove from the list of results + * + * @return ChildProductPurchasePriceQuery The current query, for fluid interface + */ + public function prune($productPurchasePrice = null) + { + if ($productPurchasePrice) { + $this->addCond('pruneCond0', $this->getAliasedColName(ProductPurchasePriceTableMap::PRODUCT_SALE_ELEMENTS_ID), $productPurchasePrice->getProductSaleElementsId(), Criteria::NOT_EQUAL); + $this->addCond('pruneCond1', $this->getAliasedColName(ProductPurchasePriceTableMap::CURRENCY_ID), $productPurchasePrice->getCurrencyId(), Criteria::NOT_EQUAL); + $this->combine(array('pruneCond0', 'pruneCond1'), Criteria::LOGICAL_OR); + } + + return $this; + } + + /** + * Deletes all rows from the product_purchase_price table. + * + * @param ConnectionInterface $con the connection to use + * @return int The number of affected rows (if supported by underlying database driver). + */ + public function doDeleteAll(ConnectionInterface $con = null) + { + if (null === $con) { + $con = Propel::getServiceContainer()->getWriteConnection(ProductPurchasePriceTableMap::DATABASE_NAME); + } + $affectedRows = 0; // initialize var to track total num of affected rows + try { + // use transaction because $criteria could contain info + // for more than one table or we could emulating ON DELETE CASCADE, etc. + $con->beginTransaction(); + $affectedRows += parent::doDeleteAll($con); + // Because this db requires some delete cascade/set null emulation, we have to + // clear the cached instance *after* the emulation has happened (since + // instances get re-added by the select statement contained therein). + ProductPurchasePriceTableMap::clearInstancePool(); + ProductPurchasePriceTableMap::clearRelatedInstancePool(); + + $con->commit(); + } catch (PropelException $e) { + $con->rollBack(); + throw $e; + } + + return $affectedRows; + } + + /** + * Performs a DELETE on the database, given a ChildProductPurchasePrice or Criteria object OR a primary key value. + * + * @param mixed $values Criteria or ChildProductPurchasePrice object or primary key or array of primary keys + * which is used to create the DELETE statement + * @param ConnectionInterface $con the connection to use + * @return int The number of affected rows (if supported by underlying database driver). This includes CASCADE-related rows + * if supported by native driver or if emulated using Propel. + * @throws PropelException Any exceptions caught during processing will be + * rethrown wrapped into a PropelException. + */ + public function delete(ConnectionInterface $con = null) + { + if (null === $con) { + $con = Propel::getServiceContainer()->getWriteConnection(ProductPurchasePriceTableMap::DATABASE_NAME); + } + + $criteria = $this; + + // Set the correct dbName + $criteria->setDbName(ProductPurchasePriceTableMap::DATABASE_NAME); + + $affectedRows = 0; // initialize var to track total num of affected rows + + try { + // use transaction because $criteria could contain info + // for more than one table or we could emulating ON DELETE CASCADE, etc. + $con->beginTransaction(); + + + ProductPurchasePriceTableMap::removeInstanceFromPool($criteria); + + $affectedRows += ModelCriteria::delete($con); + ProductPurchasePriceTableMap::clearRelatedInstancePool(); + $con->commit(); + + return $affectedRows; + } catch (PropelException $e) { + $con->rollBack(); + throw $e; + } + } + +} // ProductPurchasePriceQuery diff --git a/local/modules/CustomerFamily/Model/CustomerCustomerFamily.php b/local/modules/CustomerFamily/Model/CustomerCustomerFamily.php new file mode 100644 index 00000000..4fd2f7d8 --- /dev/null +++ b/local/modules/CustomerFamily/Model/CustomerCustomerFamily.php @@ -0,0 +1,10 @@ + array('CustomerId', 'CustomerFamilyId', 'Siret', 'Vat', ), + self::TYPE_STUDLYPHPNAME => array('customerId', 'customerFamilyId', 'siret', 'vat', ), + self::TYPE_COLNAME => array(CustomerCustomerFamilyTableMap::CUSTOMER_ID, CustomerCustomerFamilyTableMap::CUSTOMER_FAMILY_ID, CustomerCustomerFamilyTableMap::SIRET, CustomerCustomerFamilyTableMap::VAT, ), + self::TYPE_RAW_COLNAME => array('CUSTOMER_ID', 'CUSTOMER_FAMILY_ID', 'SIRET', 'VAT', ), + self::TYPE_FIELDNAME => array('customer_id', 'customer_family_id', 'siret', 'vat', ), + self::TYPE_NUM => array(0, 1, 2, 3, ) + ); + + /** + * holds an array of keys for quick access to the fieldnames array + * + * first dimension keys are the type constants + * e.g. self::$fieldKeys[self::TYPE_PHPNAME]['Id'] = 0 + */ + protected static $fieldKeys = array ( + self::TYPE_PHPNAME => array('CustomerId' => 0, 'CustomerFamilyId' => 1, 'Siret' => 2, 'Vat' => 3, ), + self::TYPE_STUDLYPHPNAME => array('customerId' => 0, 'customerFamilyId' => 1, 'siret' => 2, 'vat' => 3, ), + self::TYPE_COLNAME => array(CustomerCustomerFamilyTableMap::CUSTOMER_ID => 0, CustomerCustomerFamilyTableMap::CUSTOMER_FAMILY_ID => 1, CustomerCustomerFamilyTableMap::SIRET => 2, CustomerCustomerFamilyTableMap::VAT => 3, ), + self::TYPE_RAW_COLNAME => array('CUSTOMER_ID' => 0, 'CUSTOMER_FAMILY_ID' => 1, 'SIRET' => 2, 'VAT' => 3, ), + self::TYPE_FIELDNAME => array('customer_id' => 0, 'customer_family_id' => 1, 'siret' => 2, 'vat' => 3, ), + self::TYPE_NUM => array(0, 1, 2, 3, ) + ); + + /** + * Initialize the table attributes and columns + * Relations are not initialized by this method since they are lazy loaded + * + * @return void + * @throws PropelException + */ + public function initialize() + { + // attributes + $this->setName('customer_customer_family'); + $this->setPhpName('CustomerCustomerFamily'); + $this->setClassName('\\CustomerFamily\\Model\\CustomerCustomerFamily'); + $this->setPackage('CustomerFamily.Model'); + $this->setUseIdGenerator(false); + // columns + $this->addForeignPrimaryKey('CUSTOMER_ID', 'CustomerId', 'INTEGER' , 'customer', 'ID', true, null, null); + $this->addForeignKey('CUSTOMER_FAMILY_ID', 'CustomerFamilyId', 'INTEGER', 'customer_family', 'ID', true, null, null); + $this->addColumn('SIRET', 'Siret', 'VARCHAR', false, 50, null); + $this->addColumn('VAT', 'Vat', 'VARCHAR', false, 50, null); + } // initialize() + + /** + * Build the RelationMap objects for this table relationships + */ + public function buildRelations() + { + $this->addRelation('Customer', '\\CustomerFamily\\Model\\Thelia\\Model\\Customer', RelationMap::MANY_TO_ONE, array('customer_id' => 'id', ), 'CASCADE', null); + $this->addRelation('CustomerFamily', '\\CustomerFamily\\Model\\CustomerFamily', RelationMap::MANY_TO_ONE, array('customer_family_id' => 'id', ), 'CASCADE', null); + } // buildRelations() + + /** + * Retrieves a string version of the primary key from the DB resultset row that can be used to uniquely identify a row in this table. + * + * For tables with a single-column primary key, that simple pkey value will be returned. For tables with + * a multi-column primary key, a serialize()d version of the primary key will be returned. + * + * @param array $row resultset row. + * @param int $offset The 0-based offset for reading from the resultset row. + * @param string $indexType One of the class type constants TableMap::TYPE_PHPNAME, TableMap::TYPE_STUDLYPHPNAME + * TableMap::TYPE_COLNAME, TableMap::TYPE_FIELDNAME, TableMap::TYPE_NUM + */ + public static function getPrimaryKeyHashFromRow($row, $offset = 0, $indexType = TableMap::TYPE_NUM) + { + // If the PK cannot be derived from the row, return NULL. + if ($row[TableMap::TYPE_NUM == $indexType ? 0 + $offset : static::translateFieldName('CustomerId', TableMap::TYPE_PHPNAME, $indexType)] === null) { + return null; + } + + return (string) $row[TableMap::TYPE_NUM == $indexType ? 0 + $offset : static::translateFieldName('CustomerId', TableMap::TYPE_PHPNAME, $indexType)]; + } + + /** + * Retrieves the primary key from the DB resultset row + * For tables with a single-column primary key, that simple pkey value will be returned. For tables with + * a multi-column primary key, an array of the primary key columns will be returned. + * + * @param array $row resultset row. + * @param int $offset The 0-based offset for reading from the resultset row. + * @param string $indexType One of the class type constants TableMap::TYPE_PHPNAME, TableMap::TYPE_STUDLYPHPNAME + * TableMap::TYPE_COLNAME, TableMap::TYPE_FIELDNAME, TableMap::TYPE_NUM + * + * @return mixed The primary key of the row + */ + public static function getPrimaryKeyFromRow($row, $offset = 0, $indexType = TableMap::TYPE_NUM) + { + + return (int) $row[ + $indexType == TableMap::TYPE_NUM + ? 0 + $offset + : self::translateFieldName('CustomerId', TableMap::TYPE_PHPNAME, $indexType) + ]; + } + + /** + * The class that the tableMap will make instances of. + * + * If $withPrefix is true, the returned path + * uses a dot-path notation which is translated into a path + * relative to a location on the PHP include_path. + * (e.g. path.to.MyClass -> 'path/to/MyClass.php') + * + * @param boolean $withPrefix Whether or not to return the path with the class name + * @return string path.to.ClassName + */ + public static function getOMClass($withPrefix = true) + { + return $withPrefix ? CustomerCustomerFamilyTableMap::CLASS_DEFAULT : CustomerCustomerFamilyTableMap::OM_CLASS; + } + + /** + * Populates an object of the default type or an object that inherit from the default. + * + * @param array $row row returned by DataFetcher->fetch(). + * @param int $offset The 0-based offset for reading from the resultset row. + * @param string $indexType The index type of $row. Mostly DataFetcher->getIndexType(). + One of the class type constants TableMap::TYPE_PHPNAME, TableMap::TYPE_STUDLYPHPNAME + * TableMap::TYPE_COLNAME, TableMap::TYPE_FIELDNAME, TableMap::TYPE_NUM. + * + * @throws PropelException Any exceptions caught during processing will be + * rethrown wrapped into a PropelException. + * @return array (CustomerCustomerFamily object, last column rank) + */ + public static function populateObject($row, $offset = 0, $indexType = TableMap::TYPE_NUM) + { + $key = CustomerCustomerFamilyTableMap::getPrimaryKeyHashFromRow($row, $offset, $indexType); + if (null !== ($obj = CustomerCustomerFamilyTableMap::getInstanceFromPool($key))) { + // We no longer rehydrate the object, since this can cause data loss. + // See http://www.propelorm.org/ticket/509 + // $obj->hydrate($row, $offset, true); // rehydrate + $col = $offset + CustomerCustomerFamilyTableMap::NUM_HYDRATE_COLUMNS; + } else { + $cls = CustomerCustomerFamilyTableMap::OM_CLASS; + $obj = new $cls(); + $col = $obj->hydrate($row, $offset, false, $indexType); + CustomerCustomerFamilyTableMap::addInstanceToPool($obj, $key); + } + + return array($obj, $col); + } + + /** + * The returned array will contain objects of the default type or + * objects that inherit from the default. + * + * @param DataFetcherInterface $dataFetcher + * @return array + * @throws PropelException Any exceptions caught during processing will be + * rethrown wrapped into a PropelException. + */ + public static function populateObjects(DataFetcherInterface $dataFetcher) + { + $results = array(); + + // set the class once to avoid overhead in the loop + $cls = static::getOMClass(false); + // populate the object(s) + while ($row = $dataFetcher->fetch()) { + $key = CustomerCustomerFamilyTableMap::getPrimaryKeyHashFromRow($row, 0, $dataFetcher->getIndexType()); + if (null !== ($obj = CustomerCustomerFamilyTableMap::getInstanceFromPool($key))) { + // We no longer rehydrate the object, since this can cause data loss. + // See http://www.propelorm.org/ticket/509 + // $obj->hydrate($row, 0, true); // rehydrate + $results[] = $obj; + } else { + $obj = new $cls(); + $obj->hydrate($row); + $results[] = $obj; + CustomerCustomerFamilyTableMap::addInstanceToPool($obj, $key); + } // if key exists + } + + return $results; + } + /** + * Add all the columns needed to create a new object. + * + * Note: any columns that were marked with lazyLoad="true" in the + * XML schema will not be added to the select list and only loaded + * on demand. + * + * @param Criteria $criteria object containing the columns to add. + * @param string $alias optional table alias + * @throws PropelException Any exceptions caught during processing will be + * rethrown wrapped into a PropelException. + */ + public static function addSelectColumns(Criteria $criteria, $alias = null) + { + if (null === $alias) { + $criteria->addSelectColumn(CustomerCustomerFamilyTableMap::CUSTOMER_ID); + $criteria->addSelectColumn(CustomerCustomerFamilyTableMap::CUSTOMER_FAMILY_ID); + $criteria->addSelectColumn(CustomerCustomerFamilyTableMap::SIRET); + $criteria->addSelectColumn(CustomerCustomerFamilyTableMap::VAT); + } else { + $criteria->addSelectColumn($alias . '.CUSTOMER_ID'); + $criteria->addSelectColumn($alias . '.CUSTOMER_FAMILY_ID'); + $criteria->addSelectColumn($alias . '.SIRET'); + $criteria->addSelectColumn($alias . '.VAT'); + } + } + + /** + * Returns the TableMap related to this object. + * This method is not needed for general use but a specific application could have a need. + * @return TableMap + * @throws PropelException Any exceptions caught during processing will be + * rethrown wrapped into a PropelException. + */ + public static function getTableMap() + { + return Propel::getServiceContainer()->getDatabaseMap(CustomerCustomerFamilyTableMap::DATABASE_NAME)->getTable(CustomerCustomerFamilyTableMap::TABLE_NAME); + } + + /** + * Add a TableMap instance to the database for this tableMap class. + */ + public static function buildTableMap() + { + $dbMap = Propel::getServiceContainer()->getDatabaseMap(CustomerCustomerFamilyTableMap::DATABASE_NAME); + if (!$dbMap->hasTable(CustomerCustomerFamilyTableMap::TABLE_NAME)) { + $dbMap->addTableObject(new CustomerCustomerFamilyTableMap()); + } + } + + /** + * Performs a DELETE on the database, given a CustomerCustomerFamily or Criteria object OR a primary key value. + * + * @param mixed $values Criteria or CustomerCustomerFamily object or primary key or array of primary keys + * which is used to create the DELETE statement + * @param ConnectionInterface $con the connection to use + * @return int The number of affected rows (if supported by underlying database driver). This includes CASCADE-related rows + * if supported by native driver or if emulated using Propel. + * @throws PropelException Any exceptions caught during processing will be + * rethrown wrapped into a PropelException. + */ + public static function doDelete($values, ConnectionInterface $con = null) + { + if (null === $con) { + $con = Propel::getServiceContainer()->getWriteConnection(CustomerCustomerFamilyTableMap::DATABASE_NAME); + } + + if ($values instanceof Criteria) { + // rename for clarity + $criteria = $values; + } elseif ($values instanceof \CustomerFamily\Model\CustomerCustomerFamily) { // it's a model object + // create criteria based on pk values + $criteria = $values->buildPkeyCriteria(); + } else { // it's a primary key, or an array of pks + $criteria = new Criteria(CustomerCustomerFamilyTableMap::DATABASE_NAME); + $criteria->add(CustomerCustomerFamilyTableMap::CUSTOMER_ID, (array) $values, Criteria::IN); + } + + $query = CustomerCustomerFamilyQuery::create()->mergeWith($criteria); + + if ($values instanceof Criteria) { CustomerCustomerFamilyTableMap::clearInstancePool(); + } elseif (!is_object($values)) { // it's a primary key, or an array of pks + foreach ((array) $values as $singleval) { CustomerCustomerFamilyTableMap::removeInstanceFromPool($singleval); + } + } + + return $query->delete($con); + } + + /** + * Deletes all rows from the customer_customer_family table. + * + * @param ConnectionInterface $con the connection to use + * @return int The number of affected rows (if supported by underlying database driver). + */ + public static function doDeleteAll(ConnectionInterface $con = null) + { + return CustomerCustomerFamilyQuery::create()->doDeleteAll($con); + } + + /** + * Performs an INSERT on the database, given a CustomerCustomerFamily or Criteria object. + * + * @param mixed $criteria Criteria or CustomerCustomerFamily object containing data that is used to create the INSERT statement. + * @param ConnectionInterface $con the ConnectionInterface connection to use + * @return mixed The new primary key. + * @throws PropelException Any exceptions caught during processing will be + * rethrown wrapped into a PropelException. + */ + public static function doInsert($criteria, ConnectionInterface $con = null) + { + if (null === $con) { + $con = Propel::getServiceContainer()->getWriteConnection(CustomerCustomerFamilyTableMap::DATABASE_NAME); + } + + if ($criteria instanceof Criteria) { + $criteria = clone $criteria; // rename for clarity + } else { + $criteria = $criteria->buildCriteria(); // build Criteria from CustomerCustomerFamily object + } + + + // Set the correct dbName + $query = CustomerCustomerFamilyQuery::create()->mergeWith($criteria); + + try { + // use transaction because $criteria could contain info + // for more than one table (I guess, conceivably) + $con->beginTransaction(); + $pk = $query->doInsert($con); + $con->commit(); + } catch (PropelException $e) { + $con->rollBack(); + throw $e; + } + + return $pk; + } + +} // CustomerCustomerFamilyTableMap +// This is the static code needed to register the TableMap for this table with the main Propel class. +// +CustomerCustomerFamilyTableMap::buildTableMap(); diff --git a/local/modules/CustomerFamily/Model/Map/CustomerFamilyAvailableBrandTableMap.php b/local/modules/CustomerFamily/Model/Map/CustomerFamilyAvailableBrandTableMap.php new file mode 100644 index 00000000..e3d5e7bc --- /dev/null +++ b/local/modules/CustomerFamily/Model/Map/CustomerFamilyAvailableBrandTableMap.php @@ -0,0 +1,467 @@ + array('CustomerFamilyId', 'BrandId', ), + self::TYPE_STUDLYPHPNAME => array('customerFamilyId', 'brandId', ), + self::TYPE_COLNAME => array(CustomerFamilyAvailableBrandTableMap::CUSTOMER_FAMILY_ID, CustomerFamilyAvailableBrandTableMap::BRAND_ID, ), + self::TYPE_RAW_COLNAME => array('CUSTOMER_FAMILY_ID', 'BRAND_ID', ), + self::TYPE_FIELDNAME => array('customer_family_id', 'brand_id', ), + self::TYPE_NUM => array(0, 1, ) + ); + + /** + * holds an array of keys for quick access to the fieldnames array + * + * first dimension keys are the type constants + * e.g. self::$fieldKeys[self::TYPE_PHPNAME]['Id'] = 0 + */ + protected static $fieldKeys = array ( + self::TYPE_PHPNAME => array('CustomerFamilyId' => 0, 'BrandId' => 1, ), + self::TYPE_STUDLYPHPNAME => array('customerFamilyId' => 0, 'brandId' => 1, ), + self::TYPE_COLNAME => array(CustomerFamilyAvailableBrandTableMap::CUSTOMER_FAMILY_ID => 0, CustomerFamilyAvailableBrandTableMap::BRAND_ID => 1, ), + self::TYPE_RAW_COLNAME => array('CUSTOMER_FAMILY_ID' => 0, 'BRAND_ID' => 1, ), + self::TYPE_FIELDNAME => array('customer_family_id' => 0, 'brand_id' => 1, ), + self::TYPE_NUM => array(0, 1, ) + ); + + /** + * Initialize the table attributes and columns + * Relations are not initialized by this method since they are lazy loaded + * + * @return void + * @throws PropelException + */ + public function initialize() + { + // attributes + $this->setName('customer_family_available_brand'); + $this->setPhpName('CustomerFamilyAvailableBrand'); + $this->setClassName('\\CustomerFamily\\Model\\CustomerFamilyAvailableBrand'); + $this->setPackage('CustomerFamily.Model'); + $this->setUseIdGenerator(false); + // columns + $this->addForeignPrimaryKey('CUSTOMER_FAMILY_ID', 'CustomerFamilyId', 'INTEGER' , 'customer_family', 'ID', true, null, null); + $this->addForeignPrimaryKey('BRAND_ID', 'BrandId', 'INTEGER' , 'brand', 'ID', true, null, null); + } // initialize() + + /** + * Build the RelationMap objects for this table relationships + */ + public function buildRelations() + { + $this->addRelation('CustomerFamily', '\\CustomerFamily\\Model\\CustomerFamily', RelationMap::MANY_TO_ONE, array('customer_family_id' => 'id', ), 'CASCADE', 'CASCADE'); + $this->addRelation('Brand', '\\CustomerFamily\\Model\\Thelia\\Model\\Brand', RelationMap::MANY_TO_ONE, array('brand_id' => 'id', ), 'CASCADE', 'CASCADE'); + } // buildRelations() + + /** + * Adds an object to the instance pool. + * + * Propel keeps cached copies of objects in an instance pool when they are retrieved + * from the database. In some cases you may need to explicitly add objects + * to the cache in order to ensure that the same objects are always returned by find*() + * and findPk*() calls. + * + * @param \CustomerFamily\Model\CustomerFamilyAvailableBrand $obj A \CustomerFamily\Model\CustomerFamilyAvailableBrand object. + * @param string $key (optional) key to use for instance map (for performance boost if key was already calculated externally). + */ + public static function addInstanceToPool($obj, $key = null) + { + if (Propel::isInstancePoolingEnabled()) { + if (null === $key) { + $key = serialize(array((string) $obj->getCustomerFamilyId(), (string) $obj->getBrandId())); + } // if key === null + self::$instances[$key] = $obj; + } + } + + /** + * Removes an object from the instance pool. + * + * Propel keeps cached copies of objects in an instance pool when they are retrieved + * from the database. In some cases -- especially when you override doDelete + * methods in your stub classes -- you may need to explicitly remove objects + * from the cache in order to prevent returning objects that no longer exist. + * + * @param mixed $value A \CustomerFamily\Model\CustomerFamilyAvailableBrand object or a primary key value. + */ + public static function removeInstanceFromPool($value) + { + if (Propel::isInstancePoolingEnabled() && null !== $value) { + if (is_object($value) && $value instanceof \CustomerFamily\Model\CustomerFamilyAvailableBrand) { + $key = serialize(array((string) $value->getCustomerFamilyId(), (string) $value->getBrandId())); + + } elseif (is_array($value) && count($value) === 2) { + // assume we've been passed a primary key"; + $key = serialize(array((string) $value[0], (string) $value[1])); + } elseif ($value instanceof Criteria) { + self::$instances = []; + + return; + } else { + $e = new PropelException("Invalid value passed to removeInstanceFromPool(). Expected primary key or \CustomerFamily\Model\CustomerFamilyAvailableBrand object; got " . (is_object($value) ? get_class($value) . ' object.' : var_export($value, true))); + throw $e; + } + + unset(self::$instances[$key]); + } + } + + /** + * Retrieves a string version of the primary key from the DB resultset row that can be used to uniquely identify a row in this table. + * + * For tables with a single-column primary key, that simple pkey value will be returned. For tables with + * a multi-column primary key, a serialize()d version of the primary key will be returned. + * + * @param array $row resultset row. + * @param int $offset The 0-based offset for reading from the resultset row. + * @param string $indexType One of the class type constants TableMap::TYPE_PHPNAME, TableMap::TYPE_STUDLYPHPNAME + * TableMap::TYPE_COLNAME, TableMap::TYPE_FIELDNAME, TableMap::TYPE_NUM + */ + public static function getPrimaryKeyHashFromRow($row, $offset = 0, $indexType = TableMap::TYPE_NUM) + { + // If the PK cannot be derived from the row, return NULL. + if ($row[TableMap::TYPE_NUM == $indexType ? 0 + $offset : static::translateFieldName('CustomerFamilyId', TableMap::TYPE_PHPNAME, $indexType)] === null && $row[TableMap::TYPE_NUM == $indexType ? 1 + $offset : static::translateFieldName('BrandId', TableMap::TYPE_PHPNAME, $indexType)] === null) { + return null; + } + + return serialize(array((string) $row[TableMap::TYPE_NUM == $indexType ? 0 + $offset : static::translateFieldName('CustomerFamilyId', TableMap::TYPE_PHPNAME, $indexType)], (string) $row[TableMap::TYPE_NUM == $indexType ? 1 + $offset : static::translateFieldName('BrandId', TableMap::TYPE_PHPNAME, $indexType)])); + } + + /** + * Retrieves the primary key from the DB resultset row + * For tables with a single-column primary key, that simple pkey value will be returned. For tables with + * a multi-column primary key, an array of the primary key columns will be returned. + * + * @param array $row resultset row. + * @param int $offset The 0-based offset for reading from the resultset row. + * @param string $indexType One of the class type constants TableMap::TYPE_PHPNAME, TableMap::TYPE_STUDLYPHPNAME + * TableMap::TYPE_COLNAME, TableMap::TYPE_FIELDNAME, TableMap::TYPE_NUM + * + * @return mixed The primary key of the row + */ + public static function getPrimaryKeyFromRow($row, $offset = 0, $indexType = TableMap::TYPE_NUM) + { + + return $pks; + } + + /** + * The class that the tableMap will make instances of. + * + * If $withPrefix is true, the returned path + * uses a dot-path notation which is translated into a path + * relative to a location on the PHP include_path. + * (e.g. path.to.MyClass -> 'path/to/MyClass.php') + * + * @param boolean $withPrefix Whether or not to return the path with the class name + * @return string path.to.ClassName + */ + public static function getOMClass($withPrefix = true) + { + return $withPrefix ? CustomerFamilyAvailableBrandTableMap::CLASS_DEFAULT : CustomerFamilyAvailableBrandTableMap::OM_CLASS; + } + + /** + * Populates an object of the default type or an object that inherit from the default. + * + * @param array $row row returned by DataFetcher->fetch(). + * @param int $offset The 0-based offset for reading from the resultset row. + * @param string $indexType The index type of $row. Mostly DataFetcher->getIndexType(). + One of the class type constants TableMap::TYPE_PHPNAME, TableMap::TYPE_STUDLYPHPNAME + * TableMap::TYPE_COLNAME, TableMap::TYPE_FIELDNAME, TableMap::TYPE_NUM. + * + * @throws PropelException Any exceptions caught during processing will be + * rethrown wrapped into a PropelException. + * @return array (CustomerFamilyAvailableBrand object, last column rank) + */ + public static function populateObject($row, $offset = 0, $indexType = TableMap::TYPE_NUM) + { + $key = CustomerFamilyAvailableBrandTableMap::getPrimaryKeyHashFromRow($row, $offset, $indexType); + if (null !== ($obj = CustomerFamilyAvailableBrandTableMap::getInstanceFromPool($key))) { + // We no longer rehydrate the object, since this can cause data loss. + // See http://www.propelorm.org/ticket/509 + // $obj->hydrate($row, $offset, true); // rehydrate + $col = $offset + CustomerFamilyAvailableBrandTableMap::NUM_HYDRATE_COLUMNS; + } else { + $cls = CustomerFamilyAvailableBrandTableMap::OM_CLASS; + $obj = new $cls(); + $col = $obj->hydrate($row, $offset, false, $indexType); + CustomerFamilyAvailableBrandTableMap::addInstanceToPool($obj, $key); + } + + return array($obj, $col); + } + + /** + * The returned array will contain objects of the default type or + * objects that inherit from the default. + * + * @param DataFetcherInterface $dataFetcher + * @return array + * @throws PropelException Any exceptions caught during processing will be + * rethrown wrapped into a PropelException. + */ + public static function populateObjects(DataFetcherInterface $dataFetcher) + { + $results = array(); + + // set the class once to avoid overhead in the loop + $cls = static::getOMClass(false); + // populate the object(s) + while ($row = $dataFetcher->fetch()) { + $key = CustomerFamilyAvailableBrandTableMap::getPrimaryKeyHashFromRow($row, 0, $dataFetcher->getIndexType()); + if (null !== ($obj = CustomerFamilyAvailableBrandTableMap::getInstanceFromPool($key))) { + // We no longer rehydrate the object, since this can cause data loss. + // See http://www.propelorm.org/ticket/509 + // $obj->hydrate($row, 0, true); // rehydrate + $results[] = $obj; + } else { + $obj = new $cls(); + $obj->hydrate($row); + $results[] = $obj; + CustomerFamilyAvailableBrandTableMap::addInstanceToPool($obj, $key); + } // if key exists + } + + return $results; + } + /** + * Add all the columns needed to create a new object. + * + * Note: any columns that were marked with lazyLoad="true" in the + * XML schema will not be added to the select list and only loaded + * on demand. + * + * @param Criteria $criteria object containing the columns to add. + * @param string $alias optional table alias + * @throws PropelException Any exceptions caught during processing will be + * rethrown wrapped into a PropelException. + */ + public static function addSelectColumns(Criteria $criteria, $alias = null) + { + if (null === $alias) { + $criteria->addSelectColumn(CustomerFamilyAvailableBrandTableMap::CUSTOMER_FAMILY_ID); + $criteria->addSelectColumn(CustomerFamilyAvailableBrandTableMap::BRAND_ID); + } else { + $criteria->addSelectColumn($alias . '.CUSTOMER_FAMILY_ID'); + $criteria->addSelectColumn($alias . '.BRAND_ID'); + } + } + + /** + * Returns the TableMap related to this object. + * This method is not needed for general use but a specific application could have a need. + * @return TableMap + * @throws PropelException Any exceptions caught during processing will be + * rethrown wrapped into a PropelException. + */ + public static function getTableMap() + { + return Propel::getServiceContainer()->getDatabaseMap(CustomerFamilyAvailableBrandTableMap::DATABASE_NAME)->getTable(CustomerFamilyAvailableBrandTableMap::TABLE_NAME); + } + + /** + * Add a TableMap instance to the database for this tableMap class. + */ + public static function buildTableMap() + { + $dbMap = Propel::getServiceContainer()->getDatabaseMap(CustomerFamilyAvailableBrandTableMap::DATABASE_NAME); + if (!$dbMap->hasTable(CustomerFamilyAvailableBrandTableMap::TABLE_NAME)) { + $dbMap->addTableObject(new CustomerFamilyAvailableBrandTableMap()); + } + } + + /** + * Performs a DELETE on the database, given a CustomerFamilyAvailableBrand or Criteria object OR a primary key value. + * + * @param mixed $values Criteria or CustomerFamilyAvailableBrand object or primary key or array of primary keys + * which is used to create the DELETE statement + * @param ConnectionInterface $con the connection to use + * @return int The number of affected rows (if supported by underlying database driver). This includes CASCADE-related rows + * if supported by native driver or if emulated using Propel. + * @throws PropelException Any exceptions caught during processing will be + * rethrown wrapped into a PropelException. + */ + public static function doDelete($values, ConnectionInterface $con = null) + { + if (null === $con) { + $con = Propel::getServiceContainer()->getWriteConnection(CustomerFamilyAvailableBrandTableMap::DATABASE_NAME); + } + + if ($values instanceof Criteria) { + // rename for clarity + $criteria = $values; + } elseif ($values instanceof \CustomerFamily\Model\CustomerFamilyAvailableBrand) { // it's a model object + // create criteria based on pk values + $criteria = $values->buildPkeyCriteria(); + } else { // it's a primary key, or an array of pks + $criteria = new Criteria(CustomerFamilyAvailableBrandTableMap::DATABASE_NAME); + // primary key is composite; we therefore, expect + // the primary key passed to be an array of pkey values + if (count($values) == count($values, COUNT_RECURSIVE)) { + // array is not multi-dimensional + $values = array($values); + } + foreach ($values as $value) { + $criterion = $criteria->getNewCriterion(CustomerFamilyAvailableBrandTableMap::CUSTOMER_FAMILY_ID, $value[0]); + $criterion->addAnd($criteria->getNewCriterion(CustomerFamilyAvailableBrandTableMap::BRAND_ID, $value[1])); + $criteria->addOr($criterion); + } + } + + $query = CustomerFamilyAvailableBrandQuery::create()->mergeWith($criteria); + + if ($values instanceof Criteria) { CustomerFamilyAvailableBrandTableMap::clearInstancePool(); + } elseif (!is_object($values)) { // it's a primary key, or an array of pks + foreach ((array) $values as $singleval) { CustomerFamilyAvailableBrandTableMap::removeInstanceFromPool($singleval); + } + } + + return $query->delete($con); + } + + /** + * Deletes all rows from the customer_family_available_brand table. + * + * @param ConnectionInterface $con the connection to use + * @return int The number of affected rows (if supported by underlying database driver). + */ + public static function doDeleteAll(ConnectionInterface $con = null) + { + return CustomerFamilyAvailableBrandQuery::create()->doDeleteAll($con); + } + + /** + * Performs an INSERT on the database, given a CustomerFamilyAvailableBrand or Criteria object. + * + * @param mixed $criteria Criteria or CustomerFamilyAvailableBrand object containing data that is used to create the INSERT statement. + * @param ConnectionInterface $con the ConnectionInterface connection to use + * @return mixed The new primary key. + * @throws PropelException Any exceptions caught during processing will be + * rethrown wrapped into a PropelException. + */ + public static function doInsert($criteria, ConnectionInterface $con = null) + { + if (null === $con) { + $con = Propel::getServiceContainer()->getWriteConnection(CustomerFamilyAvailableBrandTableMap::DATABASE_NAME); + } + + if ($criteria instanceof Criteria) { + $criteria = clone $criteria; // rename for clarity + } else { + $criteria = $criteria->buildCriteria(); // build Criteria from CustomerFamilyAvailableBrand object + } + + + // Set the correct dbName + $query = CustomerFamilyAvailableBrandQuery::create()->mergeWith($criteria); + + try { + // use transaction because $criteria could contain info + // for more than one table (I guess, conceivably) + $con->beginTransaction(); + $pk = $query->doInsert($con); + $con->commit(); + } catch (PropelException $e) { + $con->rollBack(); + throw $e; + } + + return $pk; + } + +} // CustomerFamilyAvailableBrandTableMap +// This is the static code needed to register the TableMap for this table with the main Propel class. +// +CustomerFamilyAvailableBrandTableMap::buildTableMap(); diff --git a/local/modules/CustomerFamily/Model/Map/CustomerFamilyAvailableCategoryTableMap.php b/local/modules/CustomerFamily/Model/Map/CustomerFamilyAvailableCategoryTableMap.php new file mode 100644 index 00000000..34651007 --- /dev/null +++ b/local/modules/CustomerFamily/Model/Map/CustomerFamilyAvailableCategoryTableMap.php @@ -0,0 +1,467 @@ + array('CustomerFamilyId', 'CategoryId', ), + self::TYPE_STUDLYPHPNAME => array('customerFamilyId', 'categoryId', ), + self::TYPE_COLNAME => array(CustomerFamilyAvailableCategoryTableMap::CUSTOMER_FAMILY_ID, CustomerFamilyAvailableCategoryTableMap::CATEGORY_ID, ), + self::TYPE_RAW_COLNAME => array('CUSTOMER_FAMILY_ID', 'CATEGORY_ID', ), + self::TYPE_FIELDNAME => array('customer_family_id', 'category_id', ), + self::TYPE_NUM => array(0, 1, ) + ); + + /** + * holds an array of keys for quick access to the fieldnames array + * + * first dimension keys are the type constants + * e.g. self::$fieldKeys[self::TYPE_PHPNAME]['Id'] = 0 + */ + protected static $fieldKeys = array ( + self::TYPE_PHPNAME => array('CustomerFamilyId' => 0, 'CategoryId' => 1, ), + self::TYPE_STUDLYPHPNAME => array('customerFamilyId' => 0, 'categoryId' => 1, ), + self::TYPE_COLNAME => array(CustomerFamilyAvailableCategoryTableMap::CUSTOMER_FAMILY_ID => 0, CustomerFamilyAvailableCategoryTableMap::CATEGORY_ID => 1, ), + self::TYPE_RAW_COLNAME => array('CUSTOMER_FAMILY_ID' => 0, 'CATEGORY_ID' => 1, ), + self::TYPE_FIELDNAME => array('customer_family_id' => 0, 'category_id' => 1, ), + self::TYPE_NUM => array(0, 1, ) + ); + + /** + * Initialize the table attributes and columns + * Relations are not initialized by this method since they are lazy loaded + * + * @return void + * @throws PropelException + */ + public function initialize() + { + // attributes + $this->setName('customer_family_available_category'); + $this->setPhpName('CustomerFamilyAvailableCategory'); + $this->setClassName('\\CustomerFamily\\Model\\CustomerFamilyAvailableCategory'); + $this->setPackage('CustomerFamily.Model'); + $this->setUseIdGenerator(false); + // columns + $this->addForeignPrimaryKey('CUSTOMER_FAMILY_ID', 'CustomerFamilyId', 'INTEGER' , 'customer_family', 'ID', true, null, null); + $this->addForeignPrimaryKey('CATEGORY_ID', 'CategoryId', 'INTEGER' , 'category', 'ID', true, null, null); + } // initialize() + + /** + * Build the RelationMap objects for this table relationships + */ + public function buildRelations() + { + $this->addRelation('CustomerFamily', '\\CustomerFamily\\Model\\CustomerFamily', RelationMap::MANY_TO_ONE, array('customer_family_id' => 'id', ), 'CASCADE', 'CASCADE'); + $this->addRelation('Category', '\\CustomerFamily\\Model\\Thelia\\Model\\Category', RelationMap::MANY_TO_ONE, array('category_id' => 'id', ), 'CASCADE', 'CASCADE'); + } // buildRelations() + + /** + * Adds an object to the instance pool. + * + * Propel keeps cached copies of objects in an instance pool when they are retrieved + * from the database. In some cases you may need to explicitly add objects + * to the cache in order to ensure that the same objects are always returned by find*() + * and findPk*() calls. + * + * @param \CustomerFamily\Model\CustomerFamilyAvailableCategory $obj A \CustomerFamily\Model\CustomerFamilyAvailableCategory object. + * @param string $key (optional) key to use for instance map (for performance boost if key was already calculated externally). + */ + public static function addInstanceToPool($obj, $key = null) + { + if (Propel::isInstancePoolingEnabled()) { + if (null === $key) { + $key = serialize(array((string) $obj->getCustomerFamilyId(), (string) $obj->getCategoryId())); + } // if key === null + self::$instances[$key] = $obj; + } + } + + /** + * Removes an object from the instance pool. + * + * Propel keeps cached copies of objects in an instance pool when they are retrieved + * from the database. In some cases -- especially when you override doDelete + * methods in your stub classes -- you may need to explicitly remove objects + * from the cache in order to prevent returning objects that no longer exist. + * + * @param mixed $value A \CustomerFamily\Model\CustomerFamilyAvailableCategory object or a primary key value. + */ + public static function removeInstanceFromPool($value) + { + if (Propel::isInstancePoolingEnabled() && null !== $value) { + if (is_object($value) && $value instanceof \CustomerFamily\Model\CustomerFamilyAvailableCategory) { + $key = serialize(array((string) $value->getCustomerFamilyId(), (string) $value->getCategoryId())); + + } elseif (is_array($value) && count($value) === 2) { + // assume we've been passed a primary key"; + $key = serialize(array((string) $value[0], (string) $value[1])); + } elseif ($value instanceof Criteria) { + self::$instances = []; + + return; + } else { + $e = new PropelException("Invalid value passed to removeInstanceFromPool(). Expected primary key or \CustomerFamily\Model\CustomerFamilyAvailableCategory object; got " . (is_object($value) ? get_class($value) . ' object.' : var_export($value, true))); + throw $e; + } + + unset(self::$instances[$key]); + } + } + + /** + * Retrieves a string version of the primary key from the DB resultset row that can be used to uniquely identify a row in this table. + * + * For tables with a single-column primary key, that simple pkey value will be returned. For tables with + * a multi-column primary key, a serialize()d version of the primary key will be returned. + * + * @param array $row resultset row. + * @param int $offset The 0-based offset for reading from the resultset row. + * @param string $indexType One of the class type constants TableMap::TYPE_PHPNAME, TableMap::TYPE_STUDLYPHPNAME + * TableMap::TYPE_COLNAME, TableMap::TYPE_FIELDNAME, TableMap::TYPE_NUM + */ + public static function getPrimaryKeyHashFromRow($row, $offset = 0, $indexType = TableMap::TYPE_NUM) + { + // If the PK cannot be derived from the row, return NULL. + if ($row[TableMap::TYPE_NUM == $indexType ? 0 + $offset : static::translateFieldName('CustomerFamilyId', TableMap::TYPE_PHPNAME, $indexType)] === null && $row[TableMap::TYPE_NUM == $indexType ? 1 + $offset : static::translateFieldName('CategoryId', TableMap::TYPE_PHPNAME, $indexType)] === null) { + return null; + } + + return serialize(array((string) $row[TableMap::TYPE_NUM == $indexType ? 0 + $offset : static::translateFieldName('CustomerFamilyId', TableMap::TYPE_PHPNAME, $indexType)], (string) $row[TableMap::TYPE_NUM == $indexType ? 1 + $offset : static::translateFieldName('CategoryId', TableMap::TYPE_PHPNAME, $indexType)])); + } + + /** + * Retrieves the primary key from the DB resultset row + * For tables with a single-column primary key, that simple pkey value will be returned. For tables with + * a multi-column primary key, an array of the primary key columns will be returned. + * + * @param array $row resultset row. + * @param int $offset The 0-based offset for reading from the resultset row. + * @param string $indexType One of the class type constants TableMap::TYPE_PHPNAME, TableMap::TYPE_STUDLYPHPNAME + * TableMap::TYPE_COLNAME, TableMap::TYPE_FIELDNAME, TableMap::TYPE_NUM + * + * @return mixed The primary key of the row + */ + public static function getPrimaryKeyFromRow($row, $offset = 0, $indexType = TableMap::TYPE_NUM) + { + + return $pks; + } + + /** + * The class that the tableMap will make instances of. + * + * If $withPrefix is true, the returned path + * uses a dot-path notation which is translated into a path + * relative to a location on the PHP include_path. + * (e.g. path.to.MyClass -> 'path/to/MyClass.php') + * + * @param boolean $withPrefix Whether or not to return the path with the class name + * @return string path.to.ClassName + */ + public static function getOMClass($withPrefix = true) + { + return $withPrefix ? CustomerFamilyAvailableCategoryTableMap::CLASS_DEFAULT : CustomerFamilyAvailableCategoryTableMap::OM_CLASS; + } + + /** + * Populates an object of the default type or an object that inherit from the default. + * + * @param array $row row returned by DataFetcher->fetch(). + * @param int $offset The 0-based offset for reading from the resultset row. + * @param string $indexType The index type of $row. Mostly DataFetcher->getIndexType(). + One of the class type constants TableMap::TYPE_PHPNAME, TableMap::TYPE_STUDLYPHPNAME + * TableMap::TYPE_COLNAME, TableMap::TYPE_FIELDNAME, TableMap::TYPE_NUM. + * + * @throws PropelException Any exceptions caught during processing will be + * rethrown wrapped into a PropelException. + * @return array (CustomerFamilyAvailableCategory object, last column rank) + */ + public static function populateObject($row, $offset = 0, $indexType = TableMap::TYPE_NUM) + { + $key = CustomerFamilyAvailableCategoryTableMap::getPrimaryKeyHashFromRow($row, $offset, $indexType); + if (null !== ($obj = CustomerFamilyAvailableCategoryTableMap::getInstanceFromPool($key))) { + // We no longer rehydrate the object, since this can cause data loss. + // See http://www.propelorm.org/ticket/509 + // $obj->hydrate($row, $offset, true); // rehydrate + $col = $offset + CustomerFamilyAvailableCategoryTableMap::NUM_HYDRATE_COLUMNS; + } else { + $cls = CustomerFamilyAvailableCategoryTableMap::OM_CLASS; + $obj = new $cls(); + $col = $obj->hydrate($row, $offset, false, $indexType); + CustomerFamilyAvailableCategoryTableMap::addInstanceToPool($obj, $key); + } + + return array($obj, $col); + } + + /** + * The returned array will contain objects of the default type or + * objects that inherit from the default. + * + * @param DataFetcherInterface $dataFetcher + * @return array + * @throws PropelException Any exceptions caught during processing will be + * rethrown wrapped into a PropelException. + */ + public static function populateObjects(DataFetcherInterface $dataFetcher) + { + $results = array(); + + // set the class once to avoid overhead in the loop + $cls = static::getOMClass(false); + // populate the object(s) + while ($row = $dataFetcher->fetch()) { + $key = CustomerFamilyAvailableCategoryTableMap::getPrimaryKeyHashFromRow($row, 0, $dataFetcher->getIndexType()); + if (null !== ($obj = CustomerFamilyAvailableCategoryTableMap::getInstanceFromPool($key))) { + // We no longer rehydrate the object, since this can cause data loss. + // See http://www.propelorm.org/ticket/509 + // $obj->hydrate($row, 0, true); // rehydrate + $results[] = $obj; + } else { + $obj = new $cls(); + $obj->hydrate($row); + $results[] = $obj; + CustomerFamilyAvailableCategoryTableMap::addInstanceToPool($obj, $key); + } // if key exists + } + + return $results; + } + /** + * Add all the columns needed to create a new object. + * + * Note: any columns that were marked with lazyLoad="true" in the + * XML schema will not be added to the select list and only loaded + * on demand. + * + * @param Criteria $criteria object containing the columns to add. + * @param string $alias optional table alias + * @throws PropelException Any exceptions caught during processing will be + * rethrown wrapped into a PropelException. + */ + public static function addSelectColumns(Criteria $criteria, $alias = null) + { + if (null === $alias) { + $criteria->addSelectColumn(CustomerFamilyAvailableCategoryTableMap::CUSTOMER_FAMILY_ID); + $criteria->addSelectColumn(CustomerFamilyAvailableCategoryTableMap::CATEGORY_ID); + } else { + $criteria->addSelectColumn($alias . '.CUSTOMER_FAMILY_ID'); + $criteria->addSelectColumn($alias . '.CATEGORY_ID'); + } + } + + /** + * Returns the TableMap related to this object. + * This method is not needed for general use but a specific application could have a need. + * @return TableMap + * @throws PropelException Any exceptions caught during processing will be + * rethrown wrapped into a PropelException. + */ + public static function getTableMap() + { + return Propel::getServiceContainer()->getDatabaseMap(CustomerFamilyAvailableCategoryTableMap::DATABASE_NAME)->getTable(CustomerFamilyAvailableCategoryTableMap::TABLE_NAME); + } + + /** + * Add a TableMap instance to the database for this tableMap class. + */ + public static function buildTableMap() + { + $dbMap = Propel::getServiceContainer()->getDatabaseMap(CustomerFamilyAvailableCategoryTableMap::DATABASE_NAME); + if (!$dbMap->hasTable(CustomerFamilyAvailableCategoryTableMap::TABLE_NAME)) { + $dbMap->addTableObject(new CustomerFamilyAvailableCategoryTableMap()); + } + } + + /** + * Performs a DELETE on the database, given a CustomerFamilyAvailableCategory or Criteria object OR a primary key value. + * + * @param mixed $values Criteria or CustomerFamilyAvailableCategory object or primary key or array of primary keys + * which is used to create the DELETE statement + * @param ConnectionInterface $con the connection to use + * @return int The number of affected rows (if supported by underlying database driver). This includes CASCADE-related rows + * if supported by native driver or if emulated using Propel. + * @throws PropelException Any exceptions caught during processing will be + * rethrown wrapped into a PropelException. + */ + public static function doDelete($values, ConnectionInterface $con = null) + { + if (null === $con) { + $con = Propel::getServiceContainer()->getWriteConnection(CustomerFamilyAvailableCategoryTableMap::DATABASE_NAME); + } + + if ($values instanceof Criteria) { + // rename for clarity + $criteria = $values; + } elseif ($values instanceof \CustomerFamily\Model\CustomerFamilyAvailableCategory) { // it's a model object + // create criteria based on pk values + $criteria = $values->buildPkeyCriteria(); + } else { // it's a primary key, or an array of pks + $criteria = new Criteria(CustomerFamilyAvailableCategoryTableMap::DATABASE_NAME); + // primary key is composite; we therefore, expect + // the primary key passed to be an array of pkey values + if (count($values) == count($values, COUNT_RECURSIVE)) { + // array is not multi-dimensional + $values = array($values); + } + foreach ($values as $value) { + $criterion = $criteria->getNewCriterion(CustomerFamilyAvailableCategoryTableMap::CUSTOMER_FAMILY_ID, $value[0]); + $criterion->addAnd($criteria->getNewCriterion(CustomerFamilyAvailableCategoryTableMap::CATEGORY_ID, $value[1])); + $criteria->addOr($criterion); + } + } + + $query = CustomerFamilyAvailableCategoryQuery::create()->mergeWith($criteria); + + if ($values instanceof Criteria) { CustomerFamilyAvailableCategoryTableMap::clearInstancePool(); + } elseif (!is_object($values)) { // it's a primary key, or an array of pks + foreach ((array) $values as $singleval) { CustomerFamilyAvailableCategoryTableMap::removeInstanceFromPool($singleval); + } + } + + return $query->delete($con); + } + + /** + * Deletes all rows from the customer_family_available_category table. + * + * @param ConnectionInterface $con the connection to use + * @return int The number of affected rows (if supported by underlying database driver). + */ + public static function doDeleteAll(ConnectionInterface $con = null) + { + return CustomerFamilyAvailableCategoryQuery::create()->doDeleteAll($con); + } + + /** + * Performs an INSERT on the database, given a CustomerFamilyAvailableCategory or Criteria object. + * + * @param mixed $criteria Criteria or CustomerFamilyAvailableCategory object containing data that is used to create the INSERT statement. + * @param ConnectionInterface $con the ConnectionInterface connection to use + * @return mixed The new primary key. + * @throws PropelException Any exceptions caught during processing will be + * rethrown wrapped into a PropelException. + */ + public static function doInsert($criteria, ConnectionInterface $con = null) + { + if (null === $con) { + $con = Propel::getServiceContainer()->getWriteConnection(CustomerFamilyAvailableCategoryTableMap::DATABASE_NAME); + } + + if ($criteria instanceof Criteria) { + $criteria = clone $criteria; // rename for clarity + } else { + $criteria = $criteria->buildCriteria(); // build Criteria from CustomerFamilyAvailableCategory object + } + + + // Set the correct dbName + $query = CustomerFamilyAvailableCategoryQuery::create()->mergeWith($criteria); + + try { + // use transaction because $criteria could contain info + // for more than one table (I guess, conceivably) + $con->beginTransaction(); + $pk = $query->doInsert($con); + $con->commit(); + } catch (PropelException $e) { + $con->rollBack(); + throw $e; + } + + return $pk; + } + +} // CustomerFamilyAvailableCategoryTableMap +// This is the static code needed to register the TableMap for this table with the main Propel class. +// +CustomerFamilyAvailableCategoryTableMap::buildTableMap(); diff --git a/local/modules/CustomerFamily/Model/Map/CustomerFamilyI18nTableMap.php b/local/modules/CustomerFamily/Model/Map/CustomerFamilyI18nTableMap.php new file mode 100644 index 00000000..06cf2e64 --- /dev/null +++ b/local/modules/CustomerFamily/Model/Map/CustomerFamilyI18nTableMap.php @@ -0,0 +1,474 @@ + array('Id', 'Locale', 'Title', ), + self::TYPE_STUDLYPHPNAME => array('id', 'locale', 'title', ), + self::TYPE_COLNAME => array(CustomerFamilyI18nTableMap::ID, CustomerFamilyI18nTableMap::LOCALE, CustomerFamilyI18nTableMap::TITLE, ), + self::TYPE_RAW_COLNAME => array('ID', 'LOCALE', 'TITLE', ), + self::TYPE_FIELDNAME => array('id', 'locale', 'title', ), + self::TYPE_NUM => array(0, 1, 2, ) + ); + + /** + * holds an array of keys for quick access to the fieldnames array + * + * first dimension keys are the type constants + * e.g. self::$fieldKeys[self::TYPE_PHPNAME]['Id'] = 0 + */ + protected static $fieldKeys = array ( + self::TYPE_PHPNAME => array('Id' => 0, 'Locale' => 1, 'Title' => 2, ), + self::TYPE_STUDLYPHPNAME => array('id' => 0, 'locale' => 1, 'title' => 2, ), + self::TYPE_COLNAME => array(CustomerFamilyI18nTableMap::ID => 0, CustomerFamilyI18nTableMap::LOCALE => 1, CustomerFamilyI18nTableMap::TITLE => 2, ), + self::TYPE_RAW_COLNAME => array('ID' => 0, 'LOCALE' => 1, 'TITLE' => 2, ), + self::TYPE_FIELDNAME => array('id' => 0, 'locale' => 1, 'title' => 2, ), + self::TYPE_NUM => array(0, 1, 2, ) + ); + + /** + * Initialize the table attributes and columns + * Relations are not initialized by this method since they are lazy loaded + * + * @return void + * @throws PropelException + */ + public function initialize() + { + // attributes + $this->setName('customer_family_i18n'); + $this->setPhpName('CustomerFamilyI18n'); + $this->setClassName('\\CustomerFamily\\Model\\CustomerFamilyI18n'); + $this->setPackage('CustomerFamily.Model'); + $this->setUseIdGenerator(false); + // columns + $this->addForeignPrimaryKey('ID', 'Id', 'INTEGER' , 'customer_family', 'ID', true, null, null); + $this->addPrimaryKey('LOCALE', 'Locale', 'VARCHAR', true, 5, 'en_US'); + $this->addColumn('TITLE', 'Title', 'VARCHAR', false, 255, null); + } // initialize() + + /** + * Build the RelationMap objects for this table relationships + */ + public function buildRelations() + { + $this->addRelation('CustomerFamily', '\\CustomerFamily\\Model\\CustomerFamily', RelationMap::MANY_TO_ONE, array('id' => 'id', ), 'CASCADE', null); + } // buildRelations() + + /** + * Adds an object to the instance pool. + * + * Propel keeps cached copies of objects in an instance pool when they are retrieved + * from the database. In some cases you may need to explicitly add objects + * to the cache in order to ensure that the same objects are always returned by find*() + * and findPk*() calls. + * + * @param \CustomerFamily\Model\CustomerFamilyI18n $obj A \CustomerFamily\Model\CustomerFamilyI18n object. + * @param string $key (optional) key to use for instance map (for performance boost if key was already calculated externally). + */ + public static function addInstanceToPool($obj, $key = null) + { + if (Propel::isInstancePoolingEnabled()) { + if (null === $key) { + $key = serialize(array((string) $obj->getId(), (string) $obj->getLocale())); + } // if key === null + self::$instances[$key] = $obj; + } + } + + /** + * Removes an object from the instance pool. + * + * Propel keeps cached copies of objects in an instance pool when they are retrieved + * from the database. In some cases -- especially when you override doDelete + * methods in your stub classes -- you may need to explicitly remove objects + * from the cache in order to prevent returning objects that no longer exist. + * + * @param mixed $value A \CustomerFamily\Model\CustomerFamilyI18n object or a primary key value. + */ + public static function removeInstanceFromPool($value) + { + if (Propel::isInstancePoolingEnabled() && null !== $value) { + if (is_object($value) && $value instanceof \CustomerFamily\Model\CustomerFamilyI18n) { + $key = serialize(array((string) $value->getId(), (string) $value->getLocale())); + + } elseif (is_array($value) && count($value) === 2) { + // assume we've been passed a primary key"; + $key = serialize(array((string) $value[0], (string) $value[1])); + } elseif ($value instanceof Criteria) { + self::$instances = []; + + return; + } else { + $e = new PropelException("Invalid value passed to removeInstanceFromPool(). Expected primary key or \CustomerFamily\Model\CustomerFamilyI18n object; got " . (is_object($value) ? get_class($value) . ' object.' : var_export($value, true))); + throw $e; + } + + unset(self::$instances[$key]); + } + } + + /** + * Retrieves a string version of the primary key from the DB resultset row that can be used to uniquely identify a row in this table. + * + * For tables with a single-column primary key, that simple pkey value will be returned. For tables with + * a multi-column primary key, a serialize()d version of the primary key will be returned. + * + * @param array $row resultset row. + * @param int $offset The 0-based offset for reading from the resultset row. + * @param string $indexType One of the class type constants TableMap::TYPE_PHPNAME, TableMap::TYPE_STUDLYPHPNAME + * TableMap::TYPE_COLNAME, TableMap::TYPE_FIELDNAME, TableMap::TYPE_NUM + */ + public static function getPrimaryKeyHashFromRow($row, $offset = 0, $indexType = TableMap::TYPE_NUM) + { + // If the PK cannot be derived from the row, return NULL. + if ($row[TableMap::TYPE_NUM == $indexType ? 0 + $offset : static::translateFieldName('Id', TableMap::TYPE_PHPNAME, $indexType)] === null && $row[TableMap::TYPE_NUM == $indexType ? 1 + $offset : static::translateFieldName('Locale', TableMap::TYPE_PHPNAME, $indexType)] === null) { + return null; + } + + return serialize(array((string) $row[TableMap::TYPE_NUM == $indexType ? 0 + $offset : static::translateFieldName('Id', TableMap::TYPE_PHPNAME, $indexType)], (string) $row[TableMap::TYPE_NUM == $indexType ? 1 + $offset : static::translateFieldName('Locale', TableMap::TYPE_PHPNAME, $indexType)])); + } + + /** + * Retrieves the primary key from the DB resultset row + * For tables with a single-column primary key, that simple pkey value will be returned. For tables with + * a multi-column primary key, an array of the primary key columns will be returned. + * + * @param array $row resultset row. + * @param int $offset The 0-based offset for reading from the resultset row. + * @param string $indexType One of the class type constants TableMap::TYPE_PHPNAME, TableMap::TYPE_STUDLYPHPNAME + * TableMap::TYPE_COLNAME, TableMap::TYPE_FIELDNAME, TableMap::TYPE_NUM + * + * @return mixed The primary key of the row + */ + public static function getPrimaryKeyFromRow($row, $offset = 0, $indexType = TableMap::TYPE_NUM) + { + + return $pks; + } + + /** + * The class that the tableMap will make instances of. + * + * If $withPrefix is true, the returned path + * uses a dot-path notation which is translated into a path + * relative to a location on the PHP include_path. + * (e.g. path.to.MyClass -> 'path/to/MyClass.php') + * + * @param boolean $withPrefix Whether or not to return the path with the class name + * @return string path.to.ClassName + */ + public static function getOMClass($withPrefix = true) + { + return $withPrefix ? CustomerFamilyI18nTableMap::CLASS_DEFAULT : CustomerFamilyI18nTableMap::OM_CLASS; + } + + /** + * Populates an object of the default type or an object that inherit from the default. + * + * @param array $row row returned by DataFetcher->fetch(). + * @param int $offset The 0-based offset for reading from the resultset row. + * @param string $indexType The index type of $row. Mostly DataFetcher->getIndexType(). + One of the class type constants TableMap::TYPE_PHPNAME, TableMap::TYPE_STUDLYPHPNAME + * TableMap::TYPE_COLNAME, TableMap::TYPE_FIELDNAME, TableMap::TYPE_NUM. + * + * @throws PropelException Any exceptions caught during processing will be + * rethrown wrapped into a PropelException. + * @return array (CustomerFamilyI18n object, last column rank) + */ + public static function populateObject($row, $offset = 0, $indexType = TableMap::TYPE_NUM) + { + $key = CustomerFamilyI18nTableMap::getPrimaryKeyHashFromRow($row, $offset, $indexType); + if (null !== ($obj = CustomerFamilyI18nTableMap::getInstanceFromPool($key))) { + // We no longer rehydrate the object, since this can cause data loss. + // See http://www.propelorm.org/ticket/509 + // $obj->hydrate($row, $offset, true); // rehydrate + $col = $offset + CustomerFamilyI18nTableMap::NUM_HYDRATE_COLUMNS; + } else { + $cls = CustomerFamilyI18nTableMap::OM_CLASS; + $obj = new $cls(); + $col = $obj->hydrate($row, $offset, false, $indexType); + CustomerFamilyI18nTableMap::addInstanceToPool($obj, $key); + } + + return array($obj, $col); + } + + /** + * The returned array will contain objects of the default type or + * objects that inherit from the default. + * + * @param DataFetcherInterface $dataFetcher + * @return array + * @throws PropelException Any exceptions caught during processing will be + * rethrown wrapped into a PropelException. + */ + public static function populateObjects(DataFetcherInterface $dataFetcher) + { + $results = array(); + + // set the class once to avoid overhead in the loop + $cls = static::getOMClass(false); + // populate the object(s) + while ($row = $dataFetcher->fetch()) { + $key = CustomerFamilyI18nTableMap::getPrimaryKeyHashFromRow($row, 0, $dataFetcher->getIndexType()); + if (null !== ($obj = CustomerFamilyI18nTableMap::getInstanceFromPool($key))) { + // We no longer rehydrate the object, since this can cause data loss. + // See http://www.propelorm.org/ticket/509 + // $obj->hydrate($row, 0, true); // rehydrate + $results[] = $obj; + } else { + $obj = new $cls(); + $obj->hydrate($row); + $results[] = $obj; + CustomerFamilyI18nTableMap::addInstanceToPool($obj, $key); + } // if key exists + } + + return $results; + } + /** + * Add all the columns needed to create a new object. + * + * Note: any columns that were marked with lazyLoad="true" in the + * XML schema will not be added to the select list and only loaded + * on demand. + * + * @param Criteria $criteria object containing the columns to add. + * @param string $alias optional table alias + * @throws PropelException Any exceptions caught during processing will be + * rethrown wrapped into a PropelException. + */ + public static function addSelectColumns(Criteria $criteria, $alias = null) + { + if (null === $alias) { + $criteria->addSelectColumn(CustomerFamilyI18nTableMap::ID); + $criteria->addSelectColumn(CustomerFamilyI18nTableMap::LOCALE); + $criteria->addSelectColumn(CustomerFamilyI18nTableMap::TITLE); + } else { + $criteria->addSelectColumn($alias . '.ID'); + $criteria->addSelectColumn($alias . '.LOCALE'); + $criteria->addSelectColumn($alias . '.TITLE'); + } + } + + /** + * Returns the TableMap related to this object. + * This method is not needed for general use but a specific application could have a need. + * @return TableMap + * @throws PropelException Any exceptions caught during processing will be + * rethrown wrapped into a PropelException. + */ + public static function getTableMap() + { + return Propel::getServiceContainer()->getDatabaseMap(CustomerFamilyI18nTableMap::DATABASE_NAME)->getTable(CustomerFamilyI18nTableMap::TABLE_NAME); + } + + /** + * Add a TableMap instance to the database for this tableMap class. + */ + public static function buildTableMap() + { + $dbMap = Propel::getServiceContainer()->getDatabaseMap(CustomerFamilyI18nTableMap::DATABASE_NAME); + if (!$dbMap->hasTable(CustomerFamilyI18nTableMap::TABLE_NAME)) { + $dbMap->addTableObject(new CustomerFamilyI18nTableMap()); + } + } + + /** + * Performs a DELETE on the database, given a CustomerFamilyI18n or Criteria object OR a primary key value. + * + * @param mixed $values Criteria or CustomerFamilyI18n object or primary key or array of primary keys + * which is used to create the DELETE statement + * @param ConnectionInterface $con the connection to use + * @return int The number of affected rows (if supported by underlying database driver). This includes CASCADE-related rows + * if supported by native driver or if emulated using Propel. + * @throws PropelException Any exceptions caught during processing will be + * rethrown wrapped into a PropelException. + */ + public static function doDelete($values, ConnectionInterface $con = null) + { + if (null === $con) { + $con = Propel::getServiceContainer()->getWriteConnection(CustomerFamilyI18nTableMap::DATABASE_NAME); + } + + if ($values instanceof Criteria) { + // rename for clarity + $criteria = $values; + } elseif ($values instanceof \CustomerFamily\Model\CustomerFamilyI18n) { // it's a model object + // create criteria based on pk values + $criteria = $values->buildPkeyCriteria(); + } else { // it's a primary key, or an array of pks + $criteria = new Criteria(CustomerFamilyI18nTableMap::DATABASE_NAME); + // primary key is composite; we therefore, expect + // the primary key passed to be an array of pkey values + if (count($values) == count($values, COUNT_RECURSIVE)) { + // array is not multi-dimensional + $values = array($values); + } + foreach ($values as $value) { + $criterion = $criteria->getNewCriterion(CustomerFamilyI18nTableMap::ID, $value[0]); + $criterion->addAnd($criteria->getNewCriterion(CustomerFamilyI18nTableMap::LOCALE, $value[1])); + $criteria->addOr($criterion); + } + } + + $query = CustomerFamilyI18nQuery::create()->mergeWith($criteria); + + if ($values instanceof Criteria) { CustomerFamilyI18nTableMap::clearInstancePool(); + } elseif (!is_object($values)) { // it's a primary key, or an array of pks + foreach ((array) $values as $singleval) { CustomerFamilyI18nTableMap::removeInstanceFromPool($singleval); + } + } + + return $query->delete($con); + } + + /** + * Deletes all rows from the customer_family_i18n table. + * + * @param ConnectionInterface $con the connection to use + * @return int The number of affected rows (if supported by underlying database driver). + */ + public static function doDeleteAll(ConnectionInterface $con = null) + { + return CustomerFamilyI18nQuery::create()->doDeleteAll($con); + } + + /** + * Performs an INSERT on the database, given a CustomerFamilyI18n or Criteria object. + * + * @param mixed $criteria Criteria or CustomerFamilyI18n object containing data that is used to create the INSERT statement. + * @param ConnectionInterface $con the ConnectionInterface connection to use + * @return mixed The new primary key. + * @throws PropelException Any exceptions caught during processing will be + * rethrown wrapped into a PropelException. + */ + public static function doInsert($criteria, ConnectionInterface $con = null) + { + if (null === $con) { + $con = Propel::getServiceContainer()->getWriteConnection(CustomerFamilyI18nTableMap::DATABASE_NAME); + } + + if ($criteria instanceof Criteria) { + $criteria = clone $criteria; // rename for clarity + } else { + $criteria = $criteria->buildCriteria(); // build Criteria from CustomerFamilyI18n object + } + + + // Set the correct dbName + $query = CustomerFamilyI18nQuery::create()->mergeWith($criteria); + + try { + // use transaction because $criteria could contain info + // for more than one table (I guess, conceivably) + $con->beginTransaction(); + $pk = $query->doInsert($con); + $con->commit(); + } catch (PropelException $e) { + $con->rollBack(); + throw $e; + } + + return $pk; + } + +} // CustomerFamilyI18nTableMap +// This is the static code needed to register the TableMap for this table with the main Propel class. +// +CustomerFamilyI18nTableMap::buildTableMap(); diff --git a/local/modules/CustomerFamily/Model/Map/CustomerFamilyOrderTableMap.php b/local/modules/CustomerFamily/Model/Map/CustomerFamilyOrderTableMap.php new file mode 100644 index 00000000..943cd04e --- /dev/null +++ b/local/modules/CustomerFamily/Model/Map/CustomerFamilyOrderTableMap.php @@ -0,0 +1,408 @@ + array('OrderId', 'CustomerFamilyId', ), + self::TYPE_STUDLYPHPNAME => array('orderId', 'customerFamilyId', ), + self::TYPE_COLNAME => array(CustomerFamilyOrderTableMap::ORDER_ID, CustomerFamilyOrderTableMap::CUSTOMER_FAMILY_ID, ), + self::TYPE_RAW_COLNAME => array('ORDER_ID', 'CUSTOMER_FAMILY_ID', ), + self::TYPE_FIELDNAME => array('order_id', 'customer_family_id', ), + self::TYPE_NUM => array(0, 1, ) + ); + + /** + * holds an array of keys for quick access to the fieldnames array + * + * first dimension keys are the type constants + * e.g. self::$fieldKeys[self::TYPE_PHPNAME]['Id'] = 0 + */ + protected static $fieldKeys = array ( + self::TYPE_PHPNAME => array('OrderId' => 0, 'CustomerFamilyId' => 1, ), + self::TYPE_STUDLYPHPNAME => array('orderId' => 0, 'customerFamilyId' => 1, ), + self::TYPE_COLNAME => array(CustomerFamilyOrderTableMap::ORDER_ID => 0, CustomerFamilyOrderTableMap::CUSTOMER_FAMILY_ID => 1, ), + self::TYPE_RAW_COLNAME => array('ORDER_ID' => 0, 'CUSTOMER_FAMILY_ID' => 1, ), + self::TYPE_FIELDNAME => array('order_id' => 0, 'customer_family_id' => 1, ), + self::TYPE_NUM => array(0, 1, ) + ); + + /** + * Initialize the table attributes and columns + * Relations are not initialized by this method since they are lazy loaded + * + * @return void + * @throws PropelException + */ + public function initialize() + { + // attributes + $this->setName('customer_family_order'); + $this->setPhpName('CustomerFamilyOrder'); + $this->setClassName('\\CustomerFamily\\Model\\CustomerFamilyOrder'); + $this->setPackage('CustomerFamily.Model'); + $this->setUseIdGenerator(false); + // columns + $this->addForeignPrimaryKey('ORDER_ID', 'OrderId', 'INTEGER' , 'order', 'ID', true, null, null); + $this->addForeignKey('CUSTOMER_FAMILY_ID', 'CustomerFamilyId', 'INTEGER', 'customer_family', 'ID', true, null, null); + } // initialize() + + /** + * Build the RelationMap objects for this table relationships + */ + public function buildRelations() + { + $this->addRelation('Order', '\\CustomerFamily\\Model\\Thelia\\Model\\Order', RelationMap::MANY_TO_ONE, array('order_id' => 'id', ), 'CASCADE', null); + $this->addRelation('CustomerFamily', '\\CustomerFamily\\Model\\CustomerFamily', RelationMap::MANY_TO_ONE, array('customer_family_id' => 'id', ), null, 'CASCADE'); + } // buildRelations() + + /** + * Retrieves a string version of the primary key from the DB resultset row that can be used to uniquely identify a row in this table. + * + * For tables with a single-column primary key, that simple pkey value will be returned. For tables with + * a multi-column primary key, a serialize()d version of the primary key will be returned. + * + * @param array $row resultset row. + * @param int $offset The 0-based offset for reading from the resultset row. + * @param string $indexType One of the class type constants TableMap::TYPE_PHPNAME, TableMap::TYPE_STUDLYPHPNAME + * TableMap::TYPE_COLNAME, TableMap::TYPE_FIELDNAME, TableMap::TYPE_NUM + */ + public static function getPrimaryKeyHashFromRow($row, $offset = 0, $indexType = TableMap::TYPE_NUM) + { + // If the PK cannot be derived from the row, return NULL. + if ($row[TableMap::TYPE_NUM == $indexType ? 0 + $offset : static::translateFieldName('OrderId', TableMap::TYPE_PHPNAME, $indexType)] === null) { + return null; + } + + return (string) $row[TableMap::TYPE_NUM == $indexType ? 0 + $offset : static::translateFieldName('OrderId', TableMap::TYPE_PHPNAME, $indexType)]; + } + + /** + * Retrieves the primary key from the DB resultset row + * For tables with a single-column primary key, that simple pkey value will be returned. For tables with + * a multi-column primary key, an array of the primary key columns will be returned. + * + * @param array $row resultset row. + * @param int $offset The 0-based offset for reading from the resultset row. + * @param string $indexType One of the class type constants TableMap::TYPE_PHPNAME, TableMap::TYPE_STUDLYPHPNAME + * TableMap::TYPE_COLNAME, TableMap::TYPE_FIELDNAME, TableMap::TYPE_NUM + * + * @return mixed The primary key of the row + */ + public static function getPrimaryKeyFromRow($row, $offset = 0, $indexType = TableMap::TYPE_NUM) + { + + return (int) $row[ + $indexType == TableMap::TYPE_NUM + ? 0 + $offset + : self::translateFieldName('OrderId', TableMap::TYPE_PHPNAME, $indexType) + ]; + } + + /** + * The class that the tableMap will make instances of. + * + * If $withPrefix is true, the returned path + * uses a dot-path notation which is translated into a path + * relative to a location on the PHP include_path. + * (e.g. path.to.MyClass -> 'path/to/MyClass.php') + * + * @param boolean $withPrefix Whether or not to return the path with the class name + * @return string path.to.ClassName + */ + public static function getOMClass($withPrefix = true) + { + return $withPrefix ? CustomerFamilyOrderTableMap::CLASS_DEFAULT : CustomerFamilyOrderTableMap::OM_CLASS; + } + + /** + * Populates an object of the default type or an object that inherit from the default. + * + * @param array $row row returned by DataFetcher->fetch(). + * @param int $offset The 0-based offset for reading from the resultset row. + * @param string $indexType The index type of $row. Mostly DataFetcher->getIndexType(). + One of the class type constants TableMap::TYPE_PHPNAME, TableMap::TYPE_STUDLYPHPNAME + * TableMap::TYPE_COLNAME, TableMap::TYPE_FIELDNAME, TableMap::TYPE_NUM. + * + * @throws PropelException Any exceptions caught during processing will be + * rethrown wrapped into a PropelException. + * @return array (CustomerFamilyOrder object, last column rank) + */ + public static function populateObject($row, $offset = 0, $indexType = TableMap::TYPE_NUM) + { + $key = CustomerFamilyOrderTableMap::getPrimaryKeyHashFromRow($row, $offset, $indexType); + if (null !== ($obj = CustomerFamilyOrderTableMap::getInstanceFromPool($key))) { + // We no longer rehydrate the object, since this can cause data loss. + // See http://www.propelorm.org/ticket/509 + // $obj->hydrate($row, $offset, true); // rehydrate + $col = $offset + CustomerFamilyOrderTableMap::NUM_HYDRATE_COLUMNS; + } else { + $cls = CustomerFamilyOrderTableMap::OM_CLASS; + $obj = new $cls(); + $col = $obj->hydrate($row, $offset, false, $indexType); + CustomerFamilyOrderTableMap::addInstanceToPool($obj, $key); + } + + return array($obj, $col); + } + + /** + * The returned array will contain objects of the default type or + * objects that inherit from the default. + * + * @param DataFetcherInterface $dataFetcher + * @return array + * @throws PropelException Any exceptions caught during processing will be + * rethrown wrapped into a PropelException. + */ + public static function populateObjects(DataFetcherInterface $dataFetcher) + { + $results = array(); + + // set the class once to avoid overhead in the loop + $cls = static::getOMClass(false); + // populate the object(s) + while ($row = $dataFetcher->fetch()) { + $key = CustomerFamilyOrderTableMap::getPrimaryKeyHashFromRow($row, 0, $dataFetcher->getIndexType()); + if (null !== ($obj = CustomerFamilyOrderTableMap::getInstanceFromPool($key))) { + // We no longer rehydrate the object, since this can cause data loss. + // See http://www.propelorm.org/ticket/509 + // $obj->hydrate($row, 0, true); // rehydrate + $results[] = $obj; + } else { + $obj = new $cls(); + $obj->hydrate($row); + $results[] = $obj; + CustomerFamilyOrderTableMap::addInstanceToPool($obj, $key); + } // if key exists + } + + return $results; + } + /** + * Add all the columns needed to create a new object. + * + * Note: any columns that were marked with lazyLoad="true" in the + * XML schema will not be added to the select list and only loaded + * on demand. + * + * @param Criteria $criteria object containing the columns to add. + * @param string $alias optional table alias + * @throws PropelException Any exceptions caught during processing will be + * rethrown wrapped into a PropelException. + */ + public static function addSelectColumns(Criteria $criteria, $alias = null) + { + if (null === $alias) { + $criteria->addSelectColumn(CustomerFamilyOrderTableMap::ORDER_ID); + $criteria->addSelectColumn(CustomerFamilyOrderTableMap::CUSTOMER_FAMILY_ID); + } else { + $criteria->addSelectColumn($alias . '.ORDER_ID'); + $criteria->addSelectColumn($alias . '.CUSTOMER_FAMILY_ID'); + } + } + + /** + * Returns the TableMap related to this object. + * This method is not needed for general use but a specific application could have a need. + * @return TableMap + * @throws PropelException Any exceptions caught during processing will be + * rethrown wrapped into a PropelException. + */ + public static function getTableMap() + { + return Propel::getServiceContainer()->getDatabaseMap(CustomerFamilyOrderTableMap::DATABASE_NAME)->getTable(CustomerFamilyOrderTableMap::TABLE_NAME); + } + + /** + * Add a TableMap instance to the database for this tableMap class. + */ + public static function buildTableMap() + { + $dbMap = Propel::getServiceContainer()->getDatabaseMap(CustomerFamilyOrderTableMap::DATABASE_NAME); + if (!$dbMap->hasTable(CustomerFamilyOrderTableMap::TABLE_NAME)) { + $dbMap->addTableObject(new CustomerFamilyOrderTableMap()); + } + } + + /** + * Performs a DELETE on the database, given a CustomerFamilyOrder or Criteria object OR a primary key value. + * + * @param mixed $values Criteria or CustomerFamilyOrder object or primary key or array of primary keys + * which is used to create the DELETE statement + * @param ConnectionInterface $con the connection to use + * @return int The number of affected rows (if supported by underlying database driver). This includes CASCADE-related rows + * if supported by native driver or if emulated using Propel. + * @throws PropelException Any exceptions caught during processing will be + * rethrown wrapped into a PropelException. + */ + public static function doDelete($values, ConnectionInterface $con = null) + { + if (null === $con) { + $con = Propel::getServiceContainer()->getWriteConnection(CustomerFamilyOrderTableMap::DATABASE_NAME); + } + + if ($values instanceof Criteria) { + // rename for clarity + $criteria = $values; + } elseif ($values instanceof \CustomerFamily\Model\CustomerFamilyOrder) { // it's a model object + // create criteria based on pk values + $criteria = $values->buildPkeyCriteria(); + } else { // it's a primary key, or an array of pks + $criteria = new Criteria(CustomerFamilyOrderTableMap::DATABASE_NAME); + $criteria->add(CustomerFamilyOrderTableMap::ORDER_ID, (array) $values, Criteria::IN); + } + + $query = CustomerFamilyOrderQuery::create()->mergeWith($criteria); + + if ($values instanceof Criteria) { CustomerFamilyOrderTableMap::clearInstancePool(); + } elseif (!is_object($values)) { // it's a primary key, or an array of pks + foreach ((array) $values as $singleval) { CustomerFamilyOrderTableMap::removeInstanceFromPool($singleval); + } + } + + return $query->delete($con); + } + + /** + * Deletes all rows from the customer_family_order table. + * + * @param ConnectionInterface $con the connection to use + * @return int The number of affected rows (if supported by underlying database driver). + */ + public static function doDeleteAll(ConnectionInterface $con = null) + { + return CustomerFamilyOrderQuery::create()->doDeleteAll($con); + } + + /** + * Performs an INSERT on the database, given a CustomerFamilyOrder or Criteria object. + * + * @param mixed $criteria Criteria or CustomerFamilyOrder object containing data that is used to create the INSERT statement. + * @param ConnectionInterface $con the ConnectionInterface connection to use + * @return mixed The new primary key. + * @throws PropelException Any exceptions caught during processing will be + * rethrown wrapped into a PropelException. + */ + public static function doInsert($criteria, ConnectionInterface $con = null) + { + if (null === $con) { + $con = Propel::getServiceContainer()->getWriteConnection(CustomerFamilyOrderTableMap::DATABASE_NAME); + } + + if ($criteria instanceof Criteria) { + $criteria = clone $criteria; // rename for clarity + } else { + $criteria = $criteria->buildCriteria(); // build Criteria from CustomerFamilyOrder object + } + + + // Set the correct dbName + $query = CustomerFamilyOrderQuery::create()->mergeWith($criteria); + + try { + // use transaction because $criteria could contain info + // for more than one table (I guess, conceivably) + $con->beginTransaction(); + $pk = $query->doInsert($con); + $con->commit(); + } catch (PropelException $e) { + $con->rollBack(); + throw $e; + } + + return $pk; + } + +} // CustomerFamilyOrderTableMap +// This is the static code needed to register the TableMap for this table with the main Propel class. +// +CustomerFamilyOrderTableMap::buildTableMap(); diff --git a/local/modules/CustomerFamily/Model/Map/CustomerFamilyPriceTableMap.php b/local/modules/CustomerFamily/Model/Map/CustomerFamilyPriceTableMap.php new file mode 100644 index 00000000..1cf7627f --- /dev/null +++ b/local/modules/CustomerFamily/Model/Map/CustomerFamilyPriceTableMap.php @@ -0,0 +1,506 @@ + array('CustomerFamilyId', 'Promo', 'UseEquation', 'AmountAddedBefore', 'AmountAddedAfter', 'MultiplicationCoefficient', 'IsTaxed', ), + self::TYPE_STUDLYPHPNAME => array('customerFamilyId', 'promo', 'useEquation', 'amountAddedBefore', 'amountAddedAfter', 'multiplicationCoefficient', 'isTaxed', ), + self::TYPE_COLNAME => array(CustomerFamilyPriceTableMap::CUSTOMER_FAMILY_ID, CustomerFamilyPriceTableMap::PROMO, CustomerFamilyPriceTableMap::USE_EQUATION, CustomerFamilyPriceTableMap::AMOUNT_ADDED_BEFORE, CustomerFamilyPriceTableMap::AMOUNT_ADDED_AFTER, CustomerFamilyPriceTableMap::MULTIPLICATION_COEFFICIENT, CustomerFamilyPriceTableMap::IS_TAXED, ), + self::TYPE_RAW_COLNAME => array('CUSTOMER_FAMILY_ID', 'PROMO', 'USE_EQUATION', 'AMOUNT_ADDED_BEFORE', 'AMOUNT_ADDED_AFTER', 'MULTIPLICATION_COEFFICIENT', 'IS_TAXED', ), + self::TYPE_FIELDNAME => array('customer_family_id', 'promo', 'use_equation', 'amount_added_before', 'amount_added_after', 'multiplication_coefficient', 'is_taxed', ), + self::TYPE_NUM => array(0, 1, 2, 3, 4, 5, 6, ) + ); + + /** + * holds an array of keys for quick access to the fieldnames array + * + * first dimension keys are the type constants + * e.g. self::$fieldKeys[self::TYPE_PHPNAME]['Id'] = 0 + */ + protected static $fieldKeys = array ( + self::TYPE_PHPNAME => array('CustomerFamilyId' => 0, 'Promo' => 1, 'UseEquation' => 2, 'AmountAddedBefore' => 3, 'AmountAddedAfter' => 4, 'MultiplicationCoefficient' => 5, 'IsTaxed' => 6, ), + self::TYPE_STUDLYPHPNAME => array('customerFamilyId' => 0, 'promo' => 1, 'useEquation' => 2, 'amountAddedBefore' => 3, 'amountAddedAfter' => 4, 'multiplicationCoefficient' => 5, 'isTaxed' => 6, ), + self::TYPE_COLNAME => array(CustomerFamilyPriceTableMap::CUSTOMER_FAMILY_ID => 0, CustomerFamilyPriceTableMap::PROMO => 1, CustomerFamilyPriceTableMap::USE_EQUATION => 2, CustomerFamilyPriceTableMap::AMOUNT_ADDED_BEFORE => 3, CustomerFamilyPriceTableMap::AMOUNT_ADDED_AFTER => 4, CustomerFamilyPriceTableMap::MULTIPLICATION_COEFFICIENT => 5, CustomerFamilyPriceTableMap::IS_TAXED => 6, ), + self::TYPE_RAW_COLNAME => array('CUSTOMER_FAMILY_ID' => 0, 'PROMO' => 1, 'USE_EQUATION' => 2, 'AMOUNT_ADDED_BEFORE' => 3, 'AMOUNT_ADDED_AFTER' => 4, 'MULTIPLICATION_COEFFICIENT' => 5, 'IS_TAXED' => 6, ), + self::TYPE_FIELDNAME => array('customer_family_id' => 0, 'promo' => 1, 'use_equation' => 2, 'amount_added_before' => 3, 'amount_added_after' => 4, 'multiplication_coefficient' => 5, 'is_taxed' => 6, ), + self::TYPE_NUM => array(0, 1, 2, 3, 4, 5, 6, ) + ); + + /** + * Initialize the table attributes and columns + * Relations are not initialized by this method since they are lazy loaded + * + * @return void + * @throws PropelException + */ + public function initialize() + { + // attributes + $this->setName('customer_family_price'); + $this->setPhpName('CustomerFamilyPrice'); + $this->setClassName('\\CustomerFamily\\Model\\CustomerFamilyPrice'); + $this->setPackage('CustomerFamily.Model'); + $this->setUseIdGenerator(false); + // columns + $this->addForeignPrimaryKey('CUSTOMER_FAMILY_ID', 'CustomerFamilyId', 'INTEGER' , 'customer_family', 'ID', true, null, null); + $this->addPrimaryKey('PROMO', 'Promo', 'TINYINT', true, null, 0); + $this->addColumn('USE_EQUATION', 'UseEquation', 'TINYINT', true, null, 0); + $this->addColumn('AMOUNT_ADDED_BEFORE', 'AmountAddedBefore', 'DECIMAL', false, 16, 0); + $this->addColumn('AMOUNT_ADDED_AFTER', 'AmountAddedAfter', 'DECIMAL', false, 16, 0); + $this->addColumn('MULTIPLICATION_COEFFICIENT', 'MultiplicationCoefficient', 'DECIMAL', false, 16, 1); + $this->addColumn('IS_TAXED', 'IsTaxed', 'TINYINT', true, null, 1); + } // initialize() + + /** + * Build the RelationMap objects for this table relationships + */ + public function buildRelations() + { + $this->addRelation('CustomerFamily', '\\CustomerFamily\\Model\\CustomerFamily', RelationMap::MANY_TO_ONE, array('customer_family_id' => 'id', ), 'CASCADE', 'RESTRICT'); + } // buildRelations() + + /** + * Adds an object to the instance pool. + * + * Propel keeps cached copies of objects in an instance pool when they are retrieved + * from the database. In some cases you may need to explicitly add objects + * to the cache in order to ensure that the same objects are always returned by find*() + * and findPk*() calls. + * + * @param \CustomerFamily\Model\CustomerFamilyPrice $obj A \CustomerFamily\Model\CustomerFamilyPrice object. + * @param string $key (optional) key to use for instance map (for performance boost if key was already calculated externally). + */ + public static function addInstanceToPool($obj, $key = null) + { + if (Propel::isInstancePoolingEnabled()) { + if (null === $key) { + $key = serialize(array((string) $obj->getCustomerFamilyId(), (string) $obj->getPromo())); + } // if key === null + self::$instances[$key] = $obj; + } + } + + /** + * Removes an object from the instance pool. + * + * Propel keeps cached copies of objects in an instance pool when they are retrieved + * from the database. In some cases -- especially when you override doDelete + * methods in your stub classes -- you may need to explicitly remove objects + * from the cache in order to prevent returning objects that no longer exist. + * + * @param mixed $value A \CustomerFamily\Model\CustomerFamilyPrice object or a primary key value. + */ + public static function removeInstanceFromPool($value) + { + if (Propel::isInstancePoolingEnabled() && null !== $value) { + if (is_object($value) && $value instanceof \CustomerFamily\Model\CustomerFamilyPrice) { + $key = serialize(array((string) $value->getCustomerFamilyId(), (string) $value->getPromo())); + + } elseif (is_array($value) && count($value) === 2) { + // assume we've been passed a primary key"; + $key = serialize(array((string) $value[0], (string) $value[1])); + } elseif ($value instanceof Criteria) { + self::$instances = []; + + return; + } else { + $e = new PropelException("Invalid value passed to removeInstanceFromPool(). Expected primary key or \CustomerFamily\Model\CustomerFamilyPrice object; got " . (is_object($value) ? get_class($value) . ' object.' : var_export($value, true))); + throw $e; + } + + unset(self::$instances[$key]); + } + } + + /** + * Retrieves a string version of the primary key from the DB resultset row that can be used to uniquely identify a row in this table. + * + * For tables with a single-column primary key, that simple pkey value will be returned. For tables with + * a multi-column primary key, a serialize()d version of the primary key will be returned. + * + * @param array $row resultset row. + * @param int $offset The 0-based offset for reading from the resultset row. + * @param string $indexType One of the class type constants TableMap::TYPE_PHPNAME, TableMap::TYPE_STUDLYPHPNAME + * TableMap::TYPE_COLNAME, TableMap::TYPE_FIELDNAME, TableMap::TYPE_NUM + */ + public static function getPrimaryKeyHashFromRow($row, $offset = 0, $indexType = TableMap::TYPE_NUM) + { + // If the PK cannot be derived from the row, return NULL. + if ($row[TableMap::TYPE_NUM == $indexType ? 0 + $offset : static::translateFieldName('CustomerFamilyId', TableMap::TYPE_PHPNAME, $indexType)] === null && $row[TableMap::TYPE_NUM == $indexType ? 1 + $offset : static::translateFieldName('Promo', TableMap::TYPE_PHPNAME, $indexType)] === null) { + return null; + } + + return serialize(array((string) $row[TableMap::TYPE_NUM == $indexType ? 0 + $offset : static::translateFieldName('CustomerFamilyId', TableMap::TYPE_PHPNAME, $indexType)], (string) $row[TableMap::TYPE_NUM == $indexType ? 1 + $offset : static::translateFieldName('Promo', TableMap::TYPE_PHPNAME, $indexType)])); + } + + /** + * Retrieves the primary key from the DB resultset row + * For tables with a single-column primary key, that simple pkey value will be returned. For tables with + * a multi-column primary key, an array of the primary key columns will be returned. + * + * @param array $row resultset row. + * @param int $offset The 0-based offset for reading from the resultset row. + * @param string $indexType One of the class type constants TableMap::TYPE_PHPNAME, TableMap::TYPE_STUDLYPHPNAME + * TableMap::TYPE_COLNAME, TableMap::TYPE_FIELDNAME, TableMap::TYPE_NUM + * + * @return mixed The primary key of the row + */ + public static function getPrimaryKeyFromRow($row, $offset = 0, $indexType = TableMap::TYPE_NUM) + { + + return $pks; + } + + /** + * The class that the tableMap will make instances of. + * + * If $withPrefix is true, the returned path + * uses a dot-path notation which is translated into a path + * relative to a location on the PHP include_path. + * (e.g. path.to.MyClass -> 'path/to/MyClass.php') + * + * @param boolean $withPrefix Whether or not to return the path with the class name + * @return string path.to.ClassName + */ + public static function getOMClass($withPrefix = true) + { + return $withPrefix ? CustomerFamilyPriceTableMap::CLASS_DEFAULT : CustomerFamilyPriceTableMap::OM_CLASS; + } + + /** + * Populates an object of the default type or an object that inherit from the default. + * + * @param array $row row returned by DataFetcher->fetch(). + * @param int $offset The 0-based offset for reading from the resultset row. + * @param string $indexType The index type of $row. Mostly DataFetcher->getIndexType(). + One of the class type constants TableMap::TYPE_PHPNAME, TableMap::TYPE_STUDLYPHPNAME + * TableMap::TYPE_COLNAME, TableMap::TYPE_FIELDNAME, TableMap::TYPE_NUM. + * + * @throws PropelException Any exceptions caught during processing will be + * rethrown wrapped into a PropelException. + * @return array (CustomerFamilyPrice object, last column rank) + */ + public static function populateObject($row, $offset = 0, $indexType = TableMap::TYPE_NUM) + { + $key = CustomerFamilyPriceTableMap::getPrimaryKeyHashFromRow($row, $offset, $indexType); + if (null !== ($obj = CustomerFamilyPriceTableMap::getInstanceFromPool($key))) { + // We no longer rehydrate the object, since this can cause data loss. + // See http://www.propelorm.org/ticket/509 + // $obj->hydrate($row, $offset, true); // rehydrate + $col = $offset + CustomerFamilyPriceTableMap::NUM_HYDRATE_COLUMNS; + } else { + $cls = CustomerFamilyPriceTableMap::OM_CLASS; + $obj = new $cls(); + $col = $obj->hydrate($row, $offset, false, $indexType); + CustomerFamilyPriceTableMap::addInstanceToPool($obj, $key); + } + + return array($obj, $col); + } + + /** + * The returned array will contain objects of the default type or + * objects that inherit from the default. + * + * @param DataFetcherInterface $dataFetcher + * @return array + * @throws PropelException Any exceptions caught during processing will be + * rethrown wrapped into a PropelException. + */ + public static function populateObjects(DataFetcherInterface $dataFetcher) + { + $results = array(); + + // set the class once to avoid overhead in the loop + $cls = static::getOMClass(false); + // populate the object(s) + while ($row = $dataFetcher->fetch()) { + $key = CustomerFamilyPriceTableMap::getPrimaryKeyHashFromRow($row, 0, $dataFetcher->getIndexType()); + if (null !== ($obj = CustomerFamilyPriceTableMap::getInstanceFromPool($key))) { + // We no longer rehydrate the object, since this can cause data loss. + // See http://www.propelorm.org/ticket/509 + // $obj->hydrate($row, 0, true); // rehydrate + $results[] = $obj; + } else { + $obj = new $cls(); + $obj->hydrate($row); + $results[] = $obj; + CustomerFamilyPriceTableMap::addInstanceToPool($obj, $key); + } // if key exists + } + + return $results; + } + /** + * Add all the columns needed to create a new object. + * + * Note: any columns that were marked with lazyLoad="true" in the + * XML schema will not be added to the select list and only loaded + * on demand. + * + * @param Criteria $criteria object containing the columns to add. + * @param string $alias optional table alias + * @throws PropelException Any exceptions caught during processing will be + * rethrown wrapped into a PropelException. + */ + public static function addSelectColumns(Criteria $criteria, $alias = null) + { + if (null === $alias) { + $criteria->addSelectColumn(CustomerFamilyPriceTableMap::CUSTOMER_FAMILY_ID); + $criteria->addSelectColumn(CustomerFamilyPriceTableMap::PROMO); + $criteria->addSelectColumn(CustomerFamilyPriceTableMap::USE_EQUATION); + $criteria->addSelectColumn(CustomerFamilyPriceTableMap::AMOUNT_ADDED_BEFORE); + $criteria->addSelectColumn(CustomerFamilyPriceTableMap::AMOUNT_ADDED_AFTER); + $criteria->addSelectColumn(CustomerFamilyPriceTableMap::MULTIPLICATION_COEFFICIENT); + $criteria->addSelectColumn(CustomerFamilyPriceTableMap::IS_TAXED); + } else { + $criteria->addSelectColumn($alias . '.CUSTOMER_FAMILY_ID'); + $criteria->addSelectColumn($alias . '.PROMO'); + $criteria->addSelectColumn($alias . '.USE_EQUATION'); + $criteria->addSelectColumn($alias . '.AMOUNT_ADDED_BEFORE'); + $criteria->addSelectColumn($alias . '.AMOUNT_ADDED_AFTER'); + $criteria->addSelectColumn($alias . '.MULTIPLICATION_COEFFICIENT'); + $criteria->addSelectColumn($alias . '.IS_TAXED'); + } + } + + /** + * Returns the TableMap related to this object. + * This method is not needed for general use but a specific application could have a need. + * @return TableMap + * @throws PropelException Any exceptions caught during processing will be + * rethrown wrapped into a PropelException. + */ + public static function getTableMap() + { + return Propel::getServiceContainer()->getDatabaseMap(CustomerFamilyPriceTableMap::DATABASE_NAME)->getTable(CustomerFamilyPriceTableMap::TABLE_NAME); + } + + /** + * Add a TableMap instance to the database for this tableMap class. + */ + public static function buildTableMap() + { + $dbMap = Propel::getServiceContainer()->getDatabaseMap(CustomerFamilyPriceTableMap::DATABASE_NAME); + if (!$dbMap->hasTable(CustomerFamilyPriceTableMap::TABLE_NAME)) { + $dbMap->addTableObject(new CustomerFamilyPriceTableMap()); + } + } + + /** + * Performs a DELETE on the database, given a CustomerFamilyPrice or Criteria object OR a primary key value. + * + * @param mixed $values Criteria or CustomerFamilyPrice object or primary key or array of primary keys + * which is used to create the DELETE statement + * @param ConnectionInterface $con the connection to use + * @return int The number of affected rows (if supported by underlying database driver). This includes CASCADE-related rows + * if supported by native driver or if emulated using Propel. + * @throws PropelException Any exceptions caught during processing will be + * rethrown wrapped into a PropelException. + */ + public static function doDelete($values, ConnectionInterface $con = null) + { + if (null === $con) { + $con = Propel::getServiceContainer()->getWriteConnection(CustomerFamilyPriceTableMap::DATABASE_NAME); + } + + if ($values instanceof Criteria) { + // rename for clarity + $criteria = $values; + } elseif ($values instanceof \CustomerFamily\Model\CustomerFamilyPrice) { // it's a model object + // create criteria based on pk values + $criteria = $values->buildPkeyCriteria(); + } else { // it's a primary key, or an array of pks + $criteria = new Criteria(CustomerFamilyPriceTableMap::DATABASE_NAME); + // primary key is composite; we therefore, expect + // the primary key passed to be an array of pkey values + if (count($values) == count($values, COUNT_RECURSIVE)) { + // array is not multi-dimensional + $values = array($values); + } + foreach ($values as $value) { + $criterion = $criteria->getNewCriterion(CustomerFamilyPriceTableMap::CUSTOMER_FAMILY_ID, $value[0]); + $criterion->addAnd($criteria->getNewCriterion(CustomerFamilyPriceTableMap::PROMO, $value[1])); + $criteria->addOr($criterion); + } + } + + $query = CustomerFamilyPriceQuery::create()->mergeWith($criteria); + + if ($values instanceof Criteria) { CustomerFamilyPriceTableMap::clearInstancePool(); + } elseif (!is_object($values)) { // it's a primary key, or an array of pks + foreach ((array) $values as $singleval) { CustomerFamilyPriceTableMap::removeInstanceFromPool($singleval); + } + } + + return $query->delete($con); + } + + /** + * Deletes all rows from the customer_family_price table. + * + * @param ConnectionInterface $con the connection to use + * @return int The number of affected rows (if supported by underlying database driver). + */ + public static function doDeleteAll(ConnectionInterface $con = null) + { + return CustomerFamilyPriceQuery::create()->doDeleteAll($con); + } + + /** + * Performs an INSERT on the database, given a CustomerFamilyPrice or Criteria object. + * + * @param mixed $criteria Criteria or CustomerFamilyPrice object containing data that is used to create the INSERT statement. + * @param ConnectionInterface $con the ConnectionInterface connection to use + * @return mixed The new primary key. + * @throws PropelException Any exceptions caught during processing will be + * rethrown wrapped into a PropelException. + */ + public static function doInsert($criteria, ConnectionInterface $con = null) + { + if (null === $con) { + $con = Propel::getServiceContainer()->getWriteConnection(CustomerFamilyPriceTableMap::DATABASE_NAME); + } + + if ($criteria instanceof Criteria) { + $criteria = clone $criteria; // rename for clarity + } else { + $criteria = $criteria->buildCriteria(); // build Criteria from CustomerFamilyPrice object + } + + + // Set the correct dbName + $query = CustomerFamilyPriceQuery::create()->mergeWith($criteria); + + try { + // use transaction because $criteria could contain info + // for more than one table (I guess, conceivably) + $con->beginTransaction(); + $pk = $query->doInsert($con); + $con->commit(); + } catch (PropelException $e) { + $con->rollBack(); + throw $e; + } + + return $pk; + } + +} // CustomerFamilyPriceTableMap +// This is the static code needed to register the TableMap for this table with the main Propel class. +// +CustomerFamilyPriceTableMap::buildTableMap(); diff --git a/local/modules/CustomerFamily/Model/Map/CustomerFamilyTableMap.php b/local/modules/CustomerFamily/Model/Map/CustomerFamilyTableMap.php new file mode 100644 index 00000000..7a5308d3 --- /dev/null +++ b/local/modules/CustomerFamily/Model/Map/CustomerFamilyTableMap.php @@ -0,0 +1,492 @@ + array('Id', 'Code', 'CategoryRestrictionEnabled', 'BrandRestrictionEnabled', 'IsDefault', 'CreatedAt', 'UpdatedAt', ), + self::TYPE_STUDLYPHPNAME => array('id', 'code', 'categoryRestrictionEnabled', 'brandRestrictionEnabled', 'isDefault', 'createdAt', 'updatedAt', ), + self::TYPE_COLNAME => array(CustomerFamilyTableMap::ID, CustomerFamilyTableMap::CODE, CustomerFamilyTableMap::CATEGORY_RESTRICTION_ENABLED, CustomerFamilyTableMap::BRAND_RESTRICTION_ENABLED, CustomerFamilyTableMap::IS_DEFAULT, CustomerFamilyTableMap::CREATED_AT, CustomerFamilyTableMap::UPDATED_AT, ), + self::TYPE_RAW_COLNAME => array('ID', 'CODE', 'CATEGORY_RESTRICTION_ENABLED', 'BRAND_RESTRICTION_ENABLED', 'IS_DEFAULT', 'CREATED_AT', 'UPDATED_AT', ), + self::TYPE_FIELDNAME => array('id', 'code', 'category_restriction_enabled', 'brand_restriction_enabled', 'is_default', 'created_at', 'updated_at', ), + self::TYPE_NUM => array(0, 1, 2, 3, 4, 5, 6, ) + ); + + /** + * holds an array of keys for quick access to the fieldnames array + * + * first dimension keys are the type constants + * e.g. self::$fieldKeys[self::TYPE_PHPNAME]['Id'] = 0 + */ + protected static $fieldKeys = array ( + self::TYPE_PHPNAME => array('Id' => 0, 'Code' => 1, 'CategoryRestrictionEnabled' => 2, 'BrandRestrictionEnabled' => 3, 'IsDefault' => 4, 'CreatedAt' => 5, 'UpdatedAt' => 6, ), + self::TYPE_STUDLYPHPNAME => array('id' => 0, 'code' => 1, 'categoryRestrictionEnabled' => 2, 'brandRestrictionEnabled' => 3, 'isDefault' => 4, 'createdAt' => 5, 'updatedAt' => 6, ), + self::TYPE_COLNAME => array(CustomerFamilyTableMap::ID => 0, CustomerFamilyTableMap::CODE => 1, CustomerFamilyTableMap::CATEGORY_RESTRICTION_ENABLED => 2, CustomerFamilyTableMap::BRAND_RESTRICTION_ENABLED => 3, CustomerFamilyTableMap::IS_DEFAULT => 4, CustomerFamilyTableMap::CREATED_AT => 5, CustomerFamilyTableMap::UPDATED_AT => 6, ), + self::TYPE_RAW_COLNAME => array('ID' => 0, 'CODE' => 1, 'CATEGORY_RESTRICTION_ENABLED' => 2, 'BRAND_RESTRICTION_ENABLED' => 3, 'IS_DEFAULT' => 4, 'CREATED_AT' => 5, 'UPDATED_AT' => 6, ), + self::TYPE_FIELDNAME => array('id' => 0, 'code' => 1, 'category_restriction_enabled' => 2, 'brand_restriction_enabled' => 3, 'is_default' => 4, 'created_at' => 5, 'updated_at' => 6, ), + self::TYPE_NUM => array(0, 1, 2, 3, 4, 5, 6, ) + ); + + /** + * Initialize the table attributes and columns + * Relations are not initialized by this method since they are lazy loaded + * + * @return void + * @throws PropelException + */ + public function initialize() + { + // attributes + $this->setName('customer_family'); + $this->setPhpName('CustomerFamily'); + $this->setClassName('\\CustomerFamily\\Model\\CustomerFamily'); + $this->setPackage('CustomerFamily.Model'); + $this->setUseIdGenerator(true); + // columns + $this->addPrimaryKey('ID', 'Id', 'INTEGER', true, null, null); + $this->addColumn('CODE', 'Code', 'VARCHAR', true, 45, null); + $this->addColumn('CATEGORY_RESTRICTION_ENABLED', 'CategoryRestrictionEnabled', 'TINYINT', false, null, 0); + $this->addColumn('BRAND_RESTRICTION_ENABLED', 'BrandRestrictionEnabled', 'TINYINT', false, null, 0); + $this->addColumn('IS_DEFAULT', 'IsDefault', 'TINYINT', false, null, null); + $this->addColumn('CREATED_AT', 'CreatedAt', 'TIMESTAMP', false, null, null); + $this->addColumn('UPDATED_AT', 'UpdatedAt', 'TIMESTAMP', false, null, null); + } // initialize() + + /** + * Build the RelationMap objects for this table relationships + */ + public function buildRelations() + { + $this->addRelation('CustomerCustomerFamily', '\\CustomerFamily\\Model\\CustomerCustomerFamily', RelationMap::ONE_TO_MANY, array('id' => 'customer_family_id', ), 'CASCADE', null, 'CustomerCustomerFamilies'); + $this->addRelation('CustomerFamilyPrice', '\\CustomerFamily\\Model\\CustomerFamilyPrice', RelationMap::ONE_TO_MANY, array('id' => 'customer_family_id', ), 'CASCADE', 'RESTRICT', 'CustomerFamilyPrices'); + $this->addRelation('CustomerFamilyOrder', '\\CustomerFamily\\Model\\CustomerFamilyOrder', RelationMap::ONE_TO_MANY, array('id' => 'customer_family_id', ), null, 'CASCADE', 'CustomerFamilyOrders'); + $this->addRelation('CustomerFamilyAvailableCategory', '\\CustomerFamily\\Model\\CustomerFamilyAvailableCategory', RelationMap::ONE_TO_MANY, array('id' => 'customer_family_id', ), 'CASCADE', 'CASCADE', 'CustomerFamilyAvailableCategories'); + $this->addRelation('CustomerFamilyAvailableBrand', '\\CustomerFamily\\Model\\CustomerFamilyAvailableBrand', RelationMap::ONE_TO_MANY, array('id' => 'customer_family_id', ), 'CASCADE', 'CASCADE', 'CustomerFamilyAvailableBrands'); + $this->addRelation('CustomerFamilyI18n', '\\CustomerFamily\\Model\\CustomerFamilyI18n', RelationMap::ONE_TO_MANY, array('id' => 'id', ), 'CASCADE', null, 'CustomerFamilyI18ns'); + } // buildRelations() + + /** + * + * Gets the list of behaviors registered for this table + * + * @return array Associative array (name => parameters) of behaviors + */ + public function getBehaviors() + { + return array( + 'timestampable' => array('create_column' => 'created_at', 'update_column' => 'updated_at', ), + 'i18n' => array('i18n_table' => '%TABLE%_i18n', 'i18n_phpname' => '%PHPNAME%I18n', 'i18n_columns' => 'title', 'locale_column' => 'locale', 'locale_length' => '5', 'default_locale' => '', 'locale_alias' => '', ), + ); + } // getBehaviors() + /** + * Method to invalidate the instance pool of all tables related to customer_family * by a foreign key with ON DELETE CASCADE + */ + public static function clearRelatedInstancePool() + { + // Invalidate objects in ".$this->getClassNameFromBuilder($joinedTableTableMapBuilder)." instance pool, + // since one or more of them may be deleted by ON DELETE CASCADE/SETNULL rule. + CustomerCustomerFamilyTableMap::clearInstancePool(); + CustomerFamilyPriceTableMap::clearInstancePool(); + CustomerFamilyAvailableCategoryTableMap::clearInstancePool(); + CustomerFamilyAvailableBrandTableMap::clearInstancePool(); + CustomerFamilyI18nTableMap::clearInstancePool(); + } + + /** + * Retrieves a string version of the primary key from the DB resultset row that can be used to uniquely identify a row in this table. + * + * For tables with a single-column primary key, that simple pkey value will be returned. For tables with + * a multi-column primary key, a serialize()d version of the primary key will be returned. + * + * @param array $row resultset row. + * @param int $offset The 0-based offset for reading from the resultset row. + * @param string $indexType One of the class type constants TableMap::TYPE_PHPNAME, TableMap::TYPE_STUDLYPHPNAME + * TableMap::TYPE_COLNAME, TableMap::TYPE_FIELDNAME, TableMap::TYPE_NUM + */ + public static function getPrimaryKeyHashFromRow($row, $offset = 0, $indexType = TableMap::TYPE_NUM) + { + // If the PK cannot be derived from the row, return NULL. + if ($row[TableMap::TYPE_NUM == $indexType ? 0 + $offset : static::translateFieldName('Id', TableMap::TYPE_PHPNAME, $indexType)] === null) { + return null; + } + + return (string) $row[TableMap::TYPE_NUM == $indexType ? 0 + $offset : static::translateFieldName('Id', TableMap::TYPE_PHPNAME, $indexType)]; + } + + /** + * Retrieves the primary key from the DB resultset row + * For tables with a single-column primary key, that simple pkey value will be returned. For tables with + * a multi-column primary key, an array of the primary key columns will be returned. + * + * @param array $row resultset row. + * @param int $offset The 0-based offset for reading from the resultset row. + * @param string $indexType One of the class type constants TableMap::TYPE_PHPNAME, TableMap::TYPE_STUDLYPHPNAME + * TableMap::TYPE_COLNAME, TableMap::TYPE_FIELDNAME, TableMap::TYPE_NUM + * + * @return mixed The primary key of the row + */ + public static function getPrimaryKeyFromRow($row, $offset = 0, $indexType = TableMap::TYPE_NUM) + { + + return (int) $row[ + $indexType == TableMap::TYPE_NUM + ? 0 + $offset + : self::translateFieldName('Id', TableMap::TYPE_PHPNAME, $indexType) + ]; + } + + /** + * The class that the tableMap will make instances of. + * + * If $withPrefix is true, the returned path + * uses a dot-path notation which is translated into a path + * relative to a location on the PHP include_path. + * (e.g. path.to.MyClass -> 'path/to/MyClass.php') + * + * @param boolean $withPrefix Whether or not to return the path with the class name + * @return string path.to.ClassName + */ + public static function getOMClass($withPrefix = true) + { + return $withPrefix ? CustomerFamilyTableMap::CLASS_DEFAULT : CustomerFamilyTableMap::OM_CLASS; + } + + /** + * Populates an object of the default type or an object that inherit from the default. + * + * @param array $row row returned by DataFetcher->fetch(). + * @param int $offset The 0-based offset for reading from the resultset row. + * @param string $indexType The index type of $row. Mostly DataFetcher->getIndexType(). + One of the class type constants TableMap::TYPE_PHPNAME, TableMap::TYPE_STUDLYPHPNAME + * TableMap::TYPE_COLNAME, TableMap::TYPE_FIELDNAME, TableMap::TYPE_NUM. + * + * @throws PropelException Any exceptions caught during processing will be + * rethrown wrapped into a PropelException. + * @return array (CustomerFamily object, last column rank) + */ + public static function populateObject($row, $offset = 0, $indexType = TableMap::TYPE_NUM) + { + $key = CustomerFamilyTableMap::getPrimaryKeyHashFromRow($row, $offset, $indexType); + if (null !== ($obj = CustomerFamilyTableMap::getInstanceFromPool($key))) { + // We no longer rehydrate the object, since this can cause data loss. + // See http://www.propelorm.org/ticket/509 + // $obj->hydrate($row, $offset, true); // rehydrate + $col = $offset + CustomerFamilyTableMap::NUM_HYDRATE_COLUMNS; + } else { + $cls = CustomerFamilyTableMap::OM_CLASS; + $obj = new $cls(); + $col = $obj->hydrate($row, $offset, false, $indexType); + CustomerFamilyTableMap::addInstanceToPool($obj, $key); + } + + return array($obj, $col); + } + + /** + * The returned array will contain objects of the default type or + * objects that inherit from the default. + * + * @param DataFetcherInterface $dataFetcher + * @return array + * @throws PropelException Any exceptions caught during processing will be + * rethrown wrapped into a PropelException. + */ + public static function populateObjects(DataFetcherInterface $dataFetcher) + { + $results = array(); + + // set the class once to avoid overhead in the loop + $cls = static::getOMClass(false); + // populate the object(s) + while ($row = $dataFetcher->fetch()) { + $key = CustomerFamilyTableMap::getPrimaryKeyHashFromRow($row, 0, $dataFetcher->getIndexType()); + if (null !== ($obj = CustomerFamilyTableMap::getInstanceFromPool($key))) { + // We no longer rehydrate the object, since this can cause data loss. + // See http://www.propelorm.org/ticket/509 + // $obj->hydrate($row, 0, true); // rehydrate + $results[] = $obj; + } else { + $obj = new $cls(); + $obj->hydrate($row); + $results[] = $obj; + CustomerFamilyTableMap::addInstanceToPool($obj, $key); + } // if key exists + } + + return $results; + } + /** + * Add all the columns needed to create a new object. + * + * Note: any columns that were marked with lazyLoad="true" in the + * XML schema will not be added to the select list and only loaded + * on demand. + * + * @param Criteria $criteria object containing the columns to add. + * @param string $alias optional table alias + * @throws PropelException Any exceptions caught during processing will be + * rethrown wrapped into a PropelException. + */ + public static function addSelectColumns(Criteria $criteria, $alias = null) + { + if (null === $alias) { + $criteria->addSelectColumn(CustomerFamilyTableMap::ID); + $criteria->addSelectColumn(CustomerFamilyTableMap::CODE); + $criteria->addSelectColumn(CustomerFamilyTableMap::CATEGORY_RESTRICTION_ENABLED); + $criteria->addSelectColumn(CustomerFamilyTableMap::BRAND_RESTRICTION_ENABLED); + $criteria->addSelectColumn(CustomerFamilyTableMap::IS_DEFAULT); + $criteria->addSelectColumn(CustomerFamilyTableMap::CREATED_AT); + $criteria->addSelectColumn(CustomerFamilyTableMap::UPDATED_AT); + } else { + $criteria->addSelectColumn($alias . '.ID'); + $criteria->addSelectColumn($alias . '.CODE'); + $criteria->addSelectColumn($alias . '.CATEGORY_RESTRICTION_ENABLED'); + $criteria->addSelectColumn($alias . '.BRAND_RESTRICTION_ENABLED'); + $criteria->addSelectColumn($alias . '.IS_DEFAULT'); + $criteria->addSelectColumn($alias . '.CREATED_AT'); + $criteria->addSelectColumn($alias . '.UPDATED_AT'); + } + } + + /** + * Returns the TableMap related to this object. + * This method is not needed for general use but a specific application could have a need. + * @return TableMap + * @throws PropelException Any exceptions caught during processing will be + * rethrown wrapped into a PropelException. + */ + public static function getTableMap() + { + return Propel::getServiceContainer()->getDatabaseMap(CustomerFamilyTableMap::DATABASE_NAME)->getTable(CustomerFamilyTableMap::TABLE_NAME); + } + + /** + * Add a TableMap instance to the database for this tableMap class. + */ + public static function buildTableMap() + { + $dbMap = Propel::getServiceContainer()->getDatabaseMap(CustomerFamilyTableMap::DATABASE_NAME); + if (!$dbMap->hasTable(CustomerFamilyTableMap::TABLE_NAME)) { + $dbMap->addTableObject(new CustomerFamilyTableMap()); + } + } + + /** + * Performs a DELETE on the database, given a CustomerFamily or Criteria object OR a primary key value. + * + * @param mixed $values Criteria or CustomerFamily object or primary key or array of primary keys + * which is used to create the DELETE statement + * @param ConnectionInterface $con the connection to use + * @return int The number of affected rows (if supported by underlying database driver). This includes CASCADE-related rows + * if supported by native driver or if emulated using Propel. + * @throws PropelException Any exceptions caught during processing will be + * rethrown wrapped into a PropelException. + */ + public static function doDelete($values, ConnectionInterface $con = null) + { + if (null === $con) { + $con = Propel::getServiceContainer()->getWriteConnection(CustomerFamilyTableMap::DATABASE_NAME); + } + + if ($values instanceof Criteria) { + // rename for clarity + $criteria = $values; + } elseif ($values instanceof \CustomerFamily\Model\CustomerFamily) { // it's a model object + // create criteria based on pk values + $criteria = $values->buildPkeyCriteria(); + } else { // it's a primary key, or an array of pks + $criteria = new Criteria(CustomerFamilyTableMap::DATABASE_NAME); + $criteria->add(CustomerFamilyTableMap::ID, (array) $values, Criteria::IN); + } + + $query = CustomerFamilyQuery::create()->mergeWith($criteria); + + if ($values instanceof Criteria) { CustomerFamilyTableMap::clearInstancePool(); + } elseif (!is_object($values)) { // it's a primary key, or an array of pks + foreach ((array) $values as $singleval) { CustomerFamilyTableMap::removeInstanceFromPool($singleval); + } + } + + return $query->delete($con); + } + + /** + * Deletes all rows from the customer_family table. + * + * @param ConnectionInterface $con the connection to use + * @return int The number of affected rows (if supported by underlying database driver). + */ + public static function doDeleteAll(ConnectionInterface $con = null) + { + return CustomerFamilyQuery::create()->doDeleteAll($con); + } + + /** + * Performs an INSERT on the database, given a CustomerFamily or Criteria object. + * + * @param mixed $criteria Criteria or CustomerFamily object containing data that is used to create the INSERT statement. + * @param ConnectionInterface $con the ConnectionInterface connection to use + * @return mixed The new primary key. + * @throws PropelException Any exceptions caught during processing will be + * rethrown wrapped into a PropelException. + */ + public static function doInsert($criteria, ConnectionInterface $con = null) + { + if (null === $con) { + $con = Propel::getServiceContainer()->getWriteConnection(CustomerFamilyTableMap::DATABASE_NAME); + } + + if ($criteria instanceof Criteria) { + $criteria = clone $criteria; // rename for clarity + } else { + $criteria = $criteria->buildCriteria(); // build Criteria from CustomerFamily object + } + + if ($criteria->containsKey(CustomerFamilyTableMap::ID) && $criteria->keyContainsValue(CustomerFamilyTableMap::ID) ) { + throw new PropelException('Cannot insert a value for auto-increment primary key ('.CustomerFamilyTableMap::ID.')'); + } + + + // Set the correct dbName + $query = CustomerFamilyQuery::create()->mergeWith($criteria); + + try { + // use transaction because $criteria could contain info + // for more than one table (I guess, conceivably) + $con->beginTransaction(); + $pk = $query->doInsert($con); + $con->commit(); + } catch (PropelException $e) { + $con->rollBack(); + throw $e; + } + + return $pk; + } + +} // CustomerFamilyTableMap +// This is the static code needed to register the TableMap for this table with the main Propel class. +// +CustomerFamilyTableMap::buildTableMap(); diff --git a/local/modules/CustomerFamily/Model/Map/OrderProductPurchasePriceTableMap.php b/local/modules/CustomerFamily/Model/Map/OrderProductPurchasePriceTableMap.php new file mode 100644 index 00000000..531d5304 --- /dev/null +++ b/local/modules/CustomerFamily/Model/Map/OrderProductPurchasePriceTableMap.php @@ -0,0 +1,415 @@ + array('OrderProductId', 'PurchasePrice', 'SaleDayEquation', ), + self::TYPE_STUDLYPHPNAME => array('orderProductId', 'purchasePrice', 'saleDayEquation', ), + self::TYPE_COLNAME => array(OrderProductPurchasePriceTableMap::ORDER_PRODUCT_ID, OrderProductPurchasePriceTableMap::PURCHASE_PRICE, OrderProductPurchasePriceTableMap::SALE_DAY_EQUATION, ), + self::TYPE_RAW_COLNAME => array('ORDER_PRODUCT_ID', 'PURCHASE_PRICE', 'SALE_DAY_EQUATION', ), + self::TYPE_FIELDNAME => array('order_product_id', 'purchase_price', 'sale_day_equation', ), + self::TYPE_NUM => array(0, 1, 2, ) + ); + + /** + * holds an array of keys for quick access to the fieldnames array + * + * first dimension keys are the type constants + * e.g. self::$fieldKeys[self::TYPE_PHPNAME]['Id'] = 0 + */ + protected static $fieldKeys = array ( + self::TYPE_PHPNAME => array('OrderProductId' => 0, 'PurchasePrice' => 1, 'SaleDayEquation' => 2, ), + self::TYPE_STUDLYPHPNAME => array('orderProductId' => 0, 'purchasePrice' => 1, 'saleDayEquation' => 2, ), + self::TYPE_COLNAME => array(OrderProductPurchasePriceTableMap::ORDER_PRODUCT_ID => 0, OrderProductPurchasePriceTableMap::PURCHASE_PRICE => 1, OrderProductPurchasePriceTableMap::SALE_DAY_EQUATION => 2, ), + self::TYPE_RAW_COLNAME => array('ORDER_PRODUCT_ID' => 0, 'PURCHASE_PRICE' => 1, 'SALE_DAY_EQUATION' => 2, ), + self::TYPE_FIELDNAME => array('order_product_id' => 0, 'purchase_price' => 1, 'sale_day_equation' => 2, ), + self::TYPE_NUM => array(0, 1, 2, ) + ); + + /** + * Initialize the table attributes and columns + * Relations are not initialized by this method since they are lazy loaded + * + * @return void + * @throws PropelException + */ + public function initialize() + { + // attributes + $this->setName('order_product_purchase_price'); + $this->setPhpName('OrderProductPurchasePrice'); + $this->setClassName('\\CustomerFamily\\Model\\OrderProductPurchasePrice'); + $this->setPackage('CustomerFamily.Model'); + $this->setUseIdGenerator(false); + // columns + $this->addForeignPrimaryKey('ORDER_PRODUCT_ID', 'OrderProductId', 'INTEGER' , 'order_product', 'ID', true, null, null); + $this->addColumn('PURCHASE_PRICE', 'PurchasePrice', 'DECIMAL', false, 16, 0); + $this->addColumn('SALE_DAY_EQUATION', 'SaleDayEquation', 'LONGVARCHAR', true, null, null); + } // initialize() + + /** + * Build the RelationMap objects for this table relationships + */ + public function buildRelations() + { + $this->addRelation('OrderProduct', '\\CustomerFamily\\Model\\Thelia\\Model\\OrderProduct', RelationMap::MANY_TO_ONE, array('order_product_id' => 'id', ), 'CASCADE', 'RESTRICT'); + } // buildRelations() + + /** + * Retrieves a string version of the primary key from the DB resultset row that can be used to uniquely identify a row in this table. + * + * For tables with a single-column primary key, that simple pkey value will be returned. For tables with + * a multi-column primary key, a serialize()d version of the primary key will be returned. + * + * @param array $row resultset row. + * @param int $offset The 0-based offset for reading from the resultset row. + * @param string $indexType One of the class type constants TableMap::TYPE_PHPNAME, TableMap::TYPE_STUDLYPHPNAME + * TableMap::TYPE_COLNAME, TableMap::TYPE_FIELDNAME, TableMap::TYPE_NUM + */ + public static function getPrimaryKeyHashFromRow($row, $offset = 0, $indexType = TableMap::TYPE_NUM) + { + // If the PK cannot be derived from the row, return NULL. + if ($row[TableMap::TYPE_NUM == $indexType ? 0 + $offset : static::translateFieldName('OrderProductId', TableMap::TYPE_PHPNAME, $indexType)] === null) { + return null; + } + + return (string) $row[TableMap::TYPE_NUM == $indexType ? 0 + $offset : static::translateFieldName('OrderProductId', TableMap::TYPE_PHPNAME, $indexType)]; + } + + /** + * Retrieves the primary key from the DB resultset row + * For tables with a single-column primary key, that simple pkey value will be returned. For tables with + * a multi-column primary key, an array of the primary key columns will be returned. + * + * @param array $row resultset row. + * @param int $offset The 0-based offset for reading from the resultset row. + * @param string $indexType One of the class type constants TableMap::TYPE_PHPNAME, TableMap::TYPE_STUDLYPHPNAME + * TableMap::TYPE_COLNAME, TableMap::TYPE_FIELDNAME, TableMap::TYPE_NUM + * + * @return mixed The primary key of the row + */ + public static function getPrimaryKeyFromRow($row, $offset = 0, $indexType = TableMap::TYPE_NUM) + { + + return (int) $row[ + $indexType == TableMap::TYPE_NUM + ? 0 + $offset + : self::translateFieldName('OrderProductId', TableMap::TYPE_PHPNAME, $indexType) + ]; + } + + /** + * The class that the tableMap will make instances of. + * + * If $withPrefix is true, the returned path + * uses a dot-path notation which is translated into a path + * relative to a location on the PHP include_path. + * (e.g. path.to.MyClass -> 'path/to/MyClass.php') + * + * @param boolean $withPrefix Whether or not to return the path with the class name + * @return string path.to.ClassName + */ + public static function getOMClass($withPrefix = true) + { + return $withPrefix ? OrderProductPurchasePriceTableMap::CLASS_DEFAULT : OrderProductPurchasePriceTableMap::OM_CLASS; + } + + /** + * Populates an object of the default type or an object that inherit from the default. + * + * @param array $row row returned by DataFetcher->fetch(). + * @param int $offset The 0-based offset for reading from the resultset row. + * @param string $indexType The index type of $row. Mostly DataFetcher->getIndexType(). + One of the class type constants TableMap::TYPE_PHPNAME, TableMap::TYPE_STUDLYPHPNAME + * TableMap::TYPE_COLNAME, TableMap::TYPE_FIELDNAME, TableMap::TYPE_NUM. + * + * @throws PropelException Any exceptions caught during processing will be + * rethrown wrapped into a PropelException. + * @return array (OrderProductPurchasePrice object, last column rank) + */ + public static function populateObject($row, $offset = 0, $indexType = TableMap::TYPE_NUM) + { + $key = OrderProductPurchasePriceTableMap::getPrimaryKeyHashFromRow($row, $offset, $indexType); + if (null !== ($obj = OrderProductPurchasePriceTableMap::getInstanceFromPool($key))) { + // We no longer rehydrate the object, since this can cause data loss. + // See http://www.propelorm.org/ticket/509 + // $obj->hydrate($row, $offset, true); // rehydrate + $col = $offset + OrderProductPurchasePriceTableMap::NUM_HYDRATE_COLUMNS; + } else { + $cls = OrderProductPurchasePriceTableMap::OM_CLASS; + $obj = new $cls(); + $col = $obj->hydrate($row, $offset, false, $indexType); + OrderProductPurchasePriceTableMap::addInstanceToPool($obj, $key); + } + + return array($obj, $col); + } + + /** + * The returned array will contain objects of the default type or + * objects that inherit from the default. + * + * @param DataFetcherInterface $dataFetcher + * @return array + * @throws PropelException Any exceptions caught during processing will be + * rethrown wrapped into a PropelException. + */ + public static function populateObjects(DataFetcherInterface $dataFetcher) + { + $results = array(); + + // set the class once to avoid overhead in the loop + $cls = static::getOMClass(false); + // populate the object(s) + while ($row = $dataFetcher->fetch()) { + $key = OrderProductPurchasePriceTableMap::getPrimaryKeyHashFromRow($row, 0, $dataFetcher->getIndexType()); + if (null !== ($obj = OrderProductPurchasePriceTableMap::getInstanceFromPool($key))) { + // We no longer rehydrate the object, since this can cause data loss. + // See http://www.propelorm.org/ticket/509 + // $obj->hydrate($row, 0, true); // rehydrate + $results[] = $obj; + } else { + $obj = new $cls(); + $obj->hydrate($row); + $results[] = $obj; + OrderProductPurchasePriceTableMap::addInstanceToPool($obj, $key); + } // if key exists + } + + return $results; + } + /** + * Add all the columns needed to create a new object. + * + * Note: any columns that were marked with lazyLoad="true" in the + * XML schema will not be added to the select list and only loaded + * on demand. + * + * @param Criteria $criteria object containing the columns to add. + * @param string $alias optional table alias + * @throws PropelException Any exceptions caught during processing will be + * rethrown wrapped into a PropelException. + */ + public static function addSelectColumns(Criteria $criteria, $alias = null) + { + if (null === $alias) { + $criteria->addSelectColumn(OrderProductPurchasePriceTableMap::ORDER_PRODUCT_ID); + $criteria->addSelectColumn(OrderProductPurchasePriceTableMap::PURCHASE_PRICE); + $criteria->addSelectColumn(OrderProductPurchasePriceTableMap::SALE_DAY_EQUATION); + } else { + $criteria->addSelectColumn($alias . '.ORDER_PRODUCT_ID'); + $criteria->addSelectColumn($alias . '.PURCHASE_PRICE'); + $criteria->addSelectColumn($alias . '.SALE_DAY_EQUATION'); + } + } + + /** + * Returns the TableMap related to this object. + * This method is not needed for general use but a specific application could have a need. + * @return TableMap + * @throws PropelException Any exceptions caught during processing will be + * rethrown wrapped into a PropelException. + */ + public static function getTableMap() + { + return Propel::getServiceContainer()->getDatabaseMap(OrderProductPurchasePriceTableMap::DATABASE_NAME)->getTable(OrderProductPurchasePriceTableMap::TABLE_NAME); + } + + /** + * Add a TableMap instance to the database for this tableMap class. + */ + public static function buildTableMap() + { + $dbMap = Propel::getServiceContainer()->getDatabaseMap(OrderProductPurchasePriceTableMap::DATABASE_NAME); + if (!$dbMap->hasTable(OrderProductPurchasePriceTableMap::TABLE_NAME)) { + $dbMap->addTableObject(new OrderProductPurchasePriceTableMap()); + } + } + + /** + * Performs a DELETE on the database, given a OrderProductPurchasePrice or Criteria object OR a primary key value. + * + * @param mixed $values Criteria or OrderProductPurchasePrice object or primary key or array of primary keys + * which is used to create the DELETE statement + * @param ConnectionInterface $con the connection to use + * @return int The number of affected rows (if supported by underlying database driver). This includes CASCADE-related rows + * if supported by native driver or if emulated using Propel. + * @throws PropelException Any exceptions caught during processing will be + * rethrown wrapped into a PropelException. + */ + public static function doDelete($values, ConnectionInterface $con = null) + { + if (null === $con) { + $con = Propel::getServiceContainer()->getWriteConnection(OrderProductPurchasePriceTableMap::DATABASE_NAME); + } + + if ($values instanceof Criteria) { + // rename for clarity + $criteria = $values; + } elseif ($values instanceof \CustomerFamily\Model\OrderProductPurchasePrice) { // it's a model object + // create criteria based on pk values + $criteria = $values->buildPkeyCriteria(); + } else { // it's a primary key, or an array of pks + $criteria = new Criteria(OrderProductPurchasePriceTableMap::DATABASE_NAME); + $criteria->add(OrderProductPurchasePriceTableMap::ORDER_PRODUCT_ID, (array) $values, Criteria::IN); + } + + $query = OrderProductPurchasePriceQuery::create()->mergeWith($criteria); + + if ($values instanceof Criteria) { OrderProductPurchasePriceTableMap::clearInstancePool(); + } elseif (!is_object($values)) { // it's a primary key, or an array of pks + foreach ((array) $values as $singleval) { OrderProductPurchasePriceTableMap::removeInstanceFromPool($singleval); + } + } + + return $query->delete($con); + } + + /** + * Deletes all rows from the order_product_purchase_price table. + * + * @param ConnectionInterface $con the connection to use + * @return int The number of affected rows (if supported by underlying database driver). + */ + public static function doDeleteAll(ConnectionInterface $con = null) + { + return OrderProductPurchasePriceQuery::create()->doDeleteAll($con); + } + + /** + * Performs an INSERT on the database, given a OrderProductPurchasePrice or Criteria object. + * + * @param mixed $criteria Criteria or OrderProductPurchasePrice object containing data that is used to create the INSERT statement. + * @param ConnectionInterface $con the ConnectionInterface connection to use + * @return mixed The new primary key. + * @throws PropelException Any exceptions caught during processing will be + * rethrown wrapped into a PropelException. + */ + public static function doInsert($criteria, ConnectionInterface $con = null) + { + if (null === $con) { + $con = Propel::getServiceContainer()->getWriteConnection(OrderProductPurchasePriceTableMap::DATABASE_NAME); + } + + if ($criteria instanceof Criteria) { + $criteria = clone $criteria; // rename for clarity + } else { + $criteria = $criteria->buildCriteria(); // build Criteria from OrderProductPurchasePrice object + } + + + // Set the correct dbName + $query = OrderProductPurchasePriceQuery::create()->mergeWith($criteria); + + try { + // use transaction because $criteria could contain info + // for more than one table (I guess, conceivably) + $con->beginTransaction(); + $pk = $query->doInsert($con); + $con->commit(); + } catch (PropelException $e) { + $con->rollBack(); + throw $e; + } + + return $pk; + } + +} // OrderProductPurchasePriceTableMap +// This is the static code needed to register the TableMap for this table with the main Propel class. +// +OrderProductPurchasePriceTableMap::buildTableMap(); diff --git a/local/modules/CustomerFamily/Model/Map/ProductPurchasePriceTableMap.php b/local/modules/CustomerFamily/Model/Map/ProductPurchasePriceTableMap.php new file mode 100644 index 00000000..70a323dc --- /dev/null +++ b/local/modules/CustomerFamily/Model/Map/ProductPurchasePriceTableMap.php @@ -0,0 +1,475 @@ + array('ProductSaleElementsId', 'CurrencyId', 'PurchasePrice', ), + self::TYPE_STUDLYPHPNAME => array('productSaleElementsId', 'currencyId', 'purchasePrice', ), + self::TYPE_COLNAME => array(ProductPurchasePriceTableMap::PRODUCT_SALE_ELEMENTS_ID, ProductPurchasePriceTableMap::CURRENCY_ID, ProductPurchasePriceTableMap::PURCHASE_PRICE, ), + self::TYPE_RAW_COLNAME => array('PRODUCT_SALE_ELEMENTS_ID', 'CURRENCY_ID', 'PURCHASE_PRICE', ), + self::TYPE_FIELDNAME => array('product_sale_elements_id', 'currency_id', 'purchase_price', ), + self::TYPE_NUM => array(0, 1, 2, ) + ); + + /** + * holds an array of keys for quick access to the fieldnames array + * + * first dimension keys are the type constants + * e.g. self::$fieldKeys[self::TYPE_PHPNAME]['Id'] = 0 + */ + protected static $fieldKeys = array ( + self::TYPE_PHPNAME => array('ProductSaleElementsId' => 0, 'CurrencyId' => 1, 'PurchasePrice' => 2, ), + self::TYPE_STUDLYPHPNAME => array('productSaleElementsId' => 0, 'currencyId' => 1, 'purchasePrice' => 2, ), + self::TYPE_COLNAME => array(ProductPurchasePriceTableMap::PRODUCT_SALE_ELEMENTS_ID => 0, ProductPurchasePriceTableMap::CURRENCY_ID => 1, ProductPurchasePriceTableMap::PURCHASE_PRICE => 2, ), + self::TYPE_RAW_COLNAME => array('PRODUCT_SALE_ELEMENTS_ID' => 0, 'CURRENCY_ID' => 1, 'PURCHASE_PRICE' => 2, ), + self::TYPE_FIELDNAME => array('product_sale_elements_id' => 0, 'currency_id' => 1, 'purchase_price' => 2, ), + self::TYPE_NUM => array(0, 1, 2, ) + ); + + /** + * Initialize the table attributes and columns + * Relations are not initialized by this method since they are lazy loaded + * + * @return void + * @throws PropelException + */ + public function initialize() + { + // attributes + $this->setName('product_purchase_price'); + $this->setPhpName('ProductPurchasePrice'); + $this->setClassName('\\CustomerFamily\\Model\\ProductPurchasePrice'); + $this->setPackage('CustomerFamily.Model'); + $this->setUseIdGenerator(false); + // columns + $this->addForeignPrimaryKey('PRODUCT_SALE_ELEMENTS_ID', 'ProductSaleElementsId', 'INTEGER' , 'product_sale_elements', 'ID', true, null, null); + $this->addForeignPrimaryKey('CURRENCY_ID', 'CurrencyId', 'INTEGER' , 'currency', 'ID', true, null, null); + $this->addColumn('PURCHASE_PRICE', 'PurchasePrice', 'DECIMAL', false, 16, 0); + } // initialize() + + /** + * Build the RelationMap objects for this table relationships + */ + public function buildRelations() + { + $this->addRelation('ProductSaleElements', '\\CustomerFamily\\Model\\Thelia\\Model\\ProductSaleElements', RelationMap::MANY_TO_ONE, array('product_sale_elements_id' => 'id', ), 'CASCADE', 'RESTRICT'); + $this->addRelation('Currency', '\\CustomerFamily\\Model\\Thelia\\Model\\Currency', RelationMap::MANY_TO_ONE, array('currency_id' => 'id', ), 'CASCADE', 'RESTRICT'); + } // buildRelations() + + /** + * Adds an object to the instance pool. + * + * Propel keeps cached copies of objects in an instance pool when they are retrieved + * from the database. In some cases you may need to explicitly add objects + * to the cache in order to ensure that the same objects are always returned by find*() + * and findPk*() calls. + * + * @param \CustomerFamily\Model\ProductPurchasePrice $obj A \CustomerFamily\Model\ProductPurchasePrice object. + * @param string $key (optional) key to use for instance map (for performance boost if key was already calculated externally). + */ + public static function addInstanceToPool($obj, $key = null) + { + if (Propel::isInstancePoolingEnabled()) { + if (null === $key) { + $key = serialize(array((string) $obj->getProductSaleElementsId(), (string) $obj->getCurrencyId())); + } // if key === null + self::$instances[$key] = $obj; + } + } + + /** + * Removes an object from the instance pool. + * + * Propel keeps cached copies of objects in an instance pool when they are retrieved + * from the database. In some cases -- especially when you override doDelete + * methods in your stub classes -- you may need to explicitly remove objects + * from the cache in order to prevent returning objects that no longer exist. + * + * @param mixed $value A \CustomerFamily\Model\ProductPurchasePrice object or a primary key value. + */ + public static function removeInstanceFromPool($value) + { + if (Propel::isInstancePoolingEnabled() && null !== $value) { + if (is_object($value) && $value instanceof \CustomerFamily\Model\ProductPurchasePrice) { + $key = serialize(array((string) $value->getProductSaleElementsId(), (string) $value->getCurrencyId())); + + } elseif (is_array($value) && count($value) === 2) { + // assume we've been passed a primary key"; + $key = serialize(array((string) $value[0], (string) $value[1])); + } elseif ($value instanceof Criteria) { + self::$instances = []; + + return; + } else { + $e = new PropelException("Invalid value passed to removeInstanceFromPool(). Expected primary key or \CustomerFamily\Model\ProductPurchasePrice object; got " . (is_object($value) ? get_class($value) . ' object.' : var_export($value, true))); + throw $e; + } + + unset(self::$instances[$key]); + } + } + + /** + * Retrieves a string version of the primary key from the DB resultset row that can be used to uniquely identify a row in this table. + * + * For tables with a single-column primary key, that simple pkey value will be returned. For tables with + * a multi-column primary key, a serialize()d version of the primary key will be returned. + * + * @param array $row resultset row. + * @param int $offset The 0-based offset for reading from the resultset row. + * @param string $indexType One of the class type constants TableMap::TYPE_PHPNAME, TableMap::TYPE_STUDLYPHPNAME + * TableMap::TYPE_COLNAME, TableMap::TYPE_FIELDNAME, TableMap::TYPE_NUM + */ + public static function getPrimaryKeyHashFromRow($row, $offset = 0, $indexType = TableMap::TYPE_NUM) + { + // If the PK cannot be derived from the row, return NULL. + if ($row[TableMap::TYPE_NUM == $indexType ? 0 + $offset : static::translateFieldName('ProductSaleElementsId', TableMap::TYPE_PHPNAME, $indexType)] === null && $row[TableMap::TYPE_NUM == $indexType ? 1 + $offset : static::translateFieldName('CurrencyId', TableMap::TYPE_PHPNAME, $indexType)] === null) { + return null; + } + + return serialize(array((string) $row[TableMap::TYPE_NUM == $indexType ? 0 + $offset : static::translateFieldName('ProductSaleElementsId', TableMap::TYPE_PHPNAME, $indexType)], (string) $row[TableMap::TYPE_NUM == $indexType ? 1 + $offset : static::translateFieldName('CurrencyId', TableMap::TYPE_PHPNAME, $indexType)])); + } + + /** + * Retrieves the primary key from the DB resultset row + * For tables with a single-column primary key, that simple pkey value will be returned. For tables with + * a multi-column primary key, an array of the primary key columns will be returned. + * + * @param array $row resultset row. + * @param int $offset The 0-based offset for reading from the resultset row. + * @param string $indexType One of the class type constants TableMap::TYPE_PHPNAME, TableMap::TYPE_STUDLYPHPNAME + * TableMap::TYPE_COLNAME, TableMap::TYPE_FIELDNAME, TableMap::TYPE_NUM + * + * @return mixed The primary key of the row + */ + public static function getPrimaryKeyFromRow($row, $offset = 0, $indexType = TableMap::TYPE_NUM) + { + + return $pks; + } + + /** + * The class that the tableMap will make instances of. + * + * If $withPrefix is true, the returned path + * uses a dot-path notation which is translated into a path + * relative to a location on the PHP include_path. + * (e.g. path.to.MyClass -> 'path/to/MyClass.php') + * + * @param boolean $withPrefix Whether or not to return the path with the class name + * @return string path.to.ClassName + */ + public static function getOMClass($withPrefix = true) + { + return $withPrefix ? ProductPurchasePriceTableMap::CLASS_DEFAULT : ProductPurchasePriceTableMap::OM_CLASS; + } + + /** + * Populates an object of the default type or an object that inherit from the default. + * + * @param array $row row returned by DataFetcher->fetch(). + * @param int $offset The 0-based offset for reading from the resultset row. + * @param string $indexType The index type of $row. Mostly DataFetcher->getIndexType(). + One of the class type constants TableMap::TYPE_PHPNAME, TableMap::TYPE_STUDLYPHPNAME + * TableMap::TYPE_COLNAME, TableMap::TYPE_FIELDNAME, TableMap::TYPE_NUM. + * + * @throws PropelException Any exceptions caught during processing will be + * rethrown wrapped into a PropelException. + * @return array (ProductPurchasePrice object, last column rank) + */ + public static function populateObject($row, $offset = 0, $indexType = TableMap::TYPE_NUM) + { + $key = ProductPurchasePriceTableMap::getPrimaryKeyHashFromRow($row, $offset, $indexType); + if (null !== ($obj = ProductPurchasePriceTableMap::getInstanceFromPool($key))) { + // We no longer rehydrate the object, since this can cause data loss. + // See http://www.propelorm.org/ticket/509 + // $obj->hydrate($row, $offset, true); // rehydrate + $col = $offset + ProductPurchasePriceTableMap::NUM_HYDRATE_COLUMNS; + } else { + $cls = ProductPurchasePriceTableMap::OM_CLASS; + $obj = new $cls(); + $col = $obj->hydrate($row, $offset, false, $indexType); + ProductPurchasePriceTableMap::addInstanceToPool($obj, $key); + } + + return array($obj, $col); + } + + /** + * The returned array will contain objects of the default type or + * objects that inherit from the default. + * + * @param DataFetcherInterface $dataFetcher + * @return array + * @throws PropelException Any exceptions caught during processing will be + * rethrown wrapped into a PropelException. + */ + public static function populateObjects(DataFetcherInterface $dataFetcher) + { + $results = array(); + + // set the class once to avoid overhead in the loop + $cls = static::getOMClass(false); + // populate the object(s) + while ($row = $dataFetcher->fetch()) { + $key = ProductPurchasePriceTableMap::getPrimaryKeyHashFromRow($row, 0, $dataFetcher->getIndexType()); + if (null !== ($obj = ProductPurchasePriceTableMap::getInstanceFromPool($key))) { + // We no longer rehydrate the object, since this can cause data loss. + // See http://www.propelorm.org/ticket/509 + // $obj->hydrate($row, 0, true); // rehydrate + $results[] = $obj; + } else { + $obj = new $cls(); + $obj->hydrate($row); + $results[] = $obj; + ProductPurchasePriceTableMap::addInstanceToPool($obj, $key); + } // if key exists + } + + return $results; + } + /** + * Add all the columns needed to create a new object. + * + * Note: any columns that were marked with lazyLoad="true" in the + * XML schema will not be added to the select list and only loaded + * on demand. + * + * @param Criteria $criteria object containing the columns to add. + * @param string $alias optional table alias + * @throws PropelException Any exceptions caught during processing will be + * rethrown wrapped into a PropelException. + */ + public static function addSelectColumns(Criteria $criteria, $alias = null) + { + if (null === $alias) { + $criteria->addSelectColumn(ProductPurchasePriceTableMap::PRODUCT_SALE_ELEMENTS_ID); + $criteria->addSelectColumn(ProductPurchasePriceTableMap::CURRENCY_ID); + $criteria->addSelectColumn(ProductPurchasePriceTableMap::PURCHASE_PRICE); + } else { + $criteria->addSelectColumn($alias . '.PRODUCT_SALE_ELEMENTS_ID'); + $criteria->addSelectColumn($alias . '.CURRENCY_ID'); + $criteria->addSelectColumn($alias . '.PURCHASE_PRICE'); + } + } + + /** + * Returns the TableMap related to this object. + * This method is not needed for general use but a specific application could have a need. + * @return TableMap + * @throws PropelException Any exceptions caught during processing will be + * rethrown wrapped into a PropelException. + */ + public static function getTableMap() + { + return Propel::getServiceContainer()->getDatabaseMap(ProductPurchasePriceTableMap::DATABASE_NAME)->getTable(ProductPurchasePriceTableMap::TABLE_NAME); + } + + /** + * Add a TableMap instance to the database for this tableMap class. + */ + public static function buildTableMap() + { + $dbMap = Propel::getServiceContainer()->getDatabaseMap(ProductPurchasePriceTableMap::DATABASE_NAME); + if (!$dbMap->hasTable(ProductPurchasePriceTableMap::TABLE_NAME)) { + $dbMap->addTableObject(new ProductPurchasePriceTableMap()); + } + } + + /** + * Performs a DELETE on the database, given a ProductPurchasePrice or Criteria object OR a primary key value. + * + * @param mixed $values Criteria or ProductPurchasePrice object or primary key or array of primary keys + * which is used to create the DELETE statement + * @param ConnectionInterface $con the connection to use + * @return int The number of affected rows (if supported by underlying database driver). This includes CASCADE-related rows + * if supported by native driver or if emulated using Propel. + * @throws PropelException Any exceptions caught during processing will be + * rethrown wrapped into a PropelException. + */ + public static function doDelete($values, ConnectionInterface $con = null) + { + if (null === $con) { + $con = Propel::getServiceContainer()->getWriteConnection(ProductPurchasePriceTableMap::DATABASE_NAME); + } + + if ($values instanceof Criteria) { + // rename for clarity + $criteria = $values; + } elseif ($values instanceof \CustomerFamily\Model\ProductPurchasePrice) { // it's a model object + // create criteria based on pk values + $criteria = $values->buildPkeyCriteria(); + } else { // it's a primary key, or an array of pks + $criteria = new Criteria(ProductPurchasePriceTableMap::DATABASE_NAME); + // primary key is composite; we therefore, expect + // the primary key passed to be an array of pkey values + if (count($values) == count($values, COUNT_RECURSIVE)) { + // array is not multi-dimensional + $values = array($values); + } + foreach ($values as $value) { + $criterion = $criteria->getNewCriterion(ProductPurchasePriceTableMap::PRODUCT_SALE_ELEMENTS_ID, $value[0]); + $criterion->addAnd($criteria->getNewCriterion(ProductPurchasePriceTableMap::CURRENCY_ID, $value[1])); + $criteria->addOr($criterion); + } + } + + $query = ProductPurchasePriceQuery::create()->mergeWith($criteria); + + if ($values instanceof Criteria) { ProductPurchasePriceTableMap::clearInstancePool(); + } elseif (!is_object($values)) { // it's a primary key, or an array of pks + foreach ((array) $values as $singleval) { ProductPurchasePriceTableMap::removeInstanceFromPool($singleval); + } + } + + return $query->delete($con); + } + + /** + * Deletes all rows from the product_purchase_price table. + * + * @param ConnectionInterface $con the connection to use + * @return int The number of affected rows (if supported by underlying database driver). + */ + public static function doDeleteAll(ConnectionInterface $con = null) + { + return ProductPurchasePriceQuery::create()->doDeleteAll($con); + } + + /** + * Performs an INSERT on the database, given a ProductPurchasePrice or Criteria object. + * + * @param mixed $criteria Criteria or ProductPurchasePrice object containing data that is used to create the INSERT statement. + * @param ConnectionInterface $con the ConnectionInterface connection to use + * @return mixed The new primary key. + * @throws PropelException Any exceptions caught during processing will be + * rethrown wrapped into a PropelException. + */ + public static function doInsert($criteria, ConnectionInterface $con = null) + { + if (null === $con) { + $con = Propel::getServiceContainer()->getWriteConnection(ProductPurchasePriceTableMap::DATABASE_NAME); + } + + if ($criteria instanceof Criteria) { + $criteria = clone $criteria; // rename for clarity + } else { + $criteria = $criteria->buildCriteria(); // build Criteria from ProductPurchasePrice object + } + + + // Set the correct dbName + $query = ProductPurchasePriceQuery::create()->mergeWith($criteria); + + try { + // use transaction because $criteria could contain info + // for more than one table (I guess, conceivably) + $con->beginTransaction(); + $pk = $query->doInsert($con); + $con->commit(); + } catch (PropelException $e) { + $con->rollBack(); + throw $e; + } + + return $pk; + } + +} // ProductPurchasePriceTableMap +// This is the static code needed to register the TableMap for this table with the main Propel class. +// +ProductPurchasePriceTableMap::buildTableMap(); diff --git a/local/modules/CustomerFamily/Model/OrderProductPurchasePrice.php b/local/modules/CustomerFamily/Model/OrderProductPurchasePrice.php new file mode 100644 index 00000000..986f4f87 --- /dev/null +++ b/local/modules/CustomerFamily/Model/OrderProductPurchasePrice.php @@ -0,0 +1,10 @@ += 2.3.x + + For use with lower version of Thelia look for older tags on this module. + +## Installation + +### Manually + +* Copy the module into ```/local/modules/CustomerFamily``` directory and be sure that the name of the module is CustomerFamily. +* Activate it in your thelia administration panel + +### Composer + +Add it in your main thelia composer.json file + +``` +composer require thelia/customer-family-module:~1.5.0 +``` + +## Usage + +This module is visible in the BackOffice Customer Edit. + +Use the first tab to create, edit or remove families. You can also define default family, use to show specific price to unlogged customers. + +The second tab allows you to define how prices are calculated for each family, depending on the products purchase price. + +Product's prices are automatically changed in the 'product' loop, you don't need to use 'customer_family_pse_calculated_prices' loop (see below) to get product's prices. + +## Loops + +Use provided loops to display for example taxed or untaxed price depending on the customer's family. + +### customer_family + +This loop returns client families + +#### Input arguments + +|Argument |Description | +|--- |--- | +|**id** | family id | +|**exclude_id** | exclude family id | +|**is_default** | filter default family | + +#### Output values + +|Argument |Description | +|--- |--- | +|**CUSTOMER_FAMILY_ID** | customer family id | +|**CODE** | customer family code +|**TITLE_CUSTOMER_FAMILY** | customer family title | +|**IS_DEFAULT** | default customer family | + +#### Example +``` +{loop type="customer_family" name="customer_family_loop" current_product=$product_id limit="4"} + {$CODE} ({$TITLE_CUSTOMER_FAMILY}) +{/loop} +``` + +### customer_customer_family + +This loop returns customer family for specific customer or inverse + +#### Input arguments + +|Argument |Description | +|--- |--- | +|**customer_id** | customer id | +|**customer_family_id** | family id | +|**customer_family_code** | family code | + +#### Output values + +|Argument |Description | +|--- |--- | +|**CUSTOMER_FAMILY_ID** | customer family id | +|**CUSTOMER_ID** | customer id | +|**SIRET** | siret number | +|**VAT** | vat number id | + +#### Example +``` +{loop type="customer_customer_family" name="customer_customer_family_loop" customer_id="4"} + {SIRET} +{/loop} +``` + +### customer_family_price + +This loop returns the customer family's equation data + +#### Input arguments + +|Argument |Description | +|--- |--- | +|**customer_family_id** | family id | +|**promo** | equation for the promo price or not | +|**use_equation** | is the equation used to calculate price | + +#### Output values + +|Argument |Description | +|--- |--- | +|**CUSTOMER_FAMILY_ID** | customer family id | +|**PROMO** | equation for the promo price or not | +|**USE_EQUATION** | is the equation used to calculate price | +|**AMOUNT_ADDED_BEFORE** | amount directly added to the purchase price | +|**AMOUNT_ADDED_AFTER** | amount added to the purchase price after the multiplication | +|**COEFFICIENT** | coefficient the purchase price added to AMOUNT_ADDED_BEFORE is multiplied by | +|**IS_TAXED** | are taxes applied on the final calculated price | + +#### Example +``` +{loop type="customer_family_price" name="customer_family_price_loop" customer_family_id=1 promo=0} + {$AMOUNT_ADDED_BEFORE} + ... +{/loop} +``` + +### customer_family_pse_calculated_prices + +This loop returns the PSE's calculated price based on the given customer family & currency + +#### Input arguments + +|Argument |Description | +|--- |--- | +|**pse_id** | *mandatory*, PSE id | +|**currency_id** | currency id *(if not given, use default currency)* | +|**customer_family_id** | *mandatory*, customer family id | + +#### Output values + +|Argument |Description | +|--- |--- | +|**CALCULATED_PRICE** | customer family id | +|**CALCULATED_TAXED_PRICE** | equation for the promo price or not | +|**CALCULATED_PROMO_PRICE** | is the equation used to calculate price | +|**CALCULATED_TAXED_PROMO_PRICE** | amount directly added to the purchase price | + +#### Example +``` +{loop type="customer_family_pse_calculated_prices" name="customer_family_pse_calculated_prices_loop" pse_id=22 customer_family_id=1} + {$CALCULATED_TAXED_PRICE} + ... +{/loop} +``` + +## Form customer_family_customer_create_form + +This form extend customer_create_form + +### Fields + +|Name |Type |Required | +|--- |--- |--- | +|**customer_family_id** | integer | true | +|**siret** | string | false | +|**vat** | string | false | + +## Default + +By default, two families are created +* Private individual +* Professional diff --git a/local/modules/CustomerFamily/Service/CustomerFamilyService.php b/local/modules/CustomerFamily/Service/CustomerFamilyService.php new file mode 100644 index 00000000..e387fa99 --- /dev/null +++ b/local/modules/CustomerFamily/Service/CustomerFamilyService.php @@ -0,0 +1,210 @@ + + */ +class CustomerFamilyService +{ + protected $securityContext; + protected $taxEngine; + + public function __construct(SecurityContext $securityContext, TaxEngine $taxEngine) + { + $this->securityContext = $securityContext; + $this->taxEngine = $taxEngine; + } + + /** + * @param null $customerId + * @return mixed + * @throws \Propel\Runtime\Exception\PropelException + */ + public function getCustomerCustomerFamilyId($customerId = null) + { + $customerFamilyId = null; + + // Get given customer's family, else logged customer's one + if ($customerId !== null) { + $customerFamilyId = CustomerCustomerFamilyQuery::create() + ->filterByCustomerId($customerId) + ->select(CustomerCustomerFamilyTableMap::CUSTOMER_FAMILY_ID) + ->findOne(); + } elseif ($this->securityContext->hasCustomerUser()) { + $customerFamilyId = CustomerCustomerFamilyQuery::create() + ->filterByCustomerId($this->securityContext->getCustomerUser()->getId()) + ->select(CustomerCustomerFamilyTableMap::CUSTOMER_FAMILY_ID) + ->findOne(); + } + + // If no family found, get default one + if ($customerFamilyId === null) { + $customerFamilyId = CustomerFamilyQuery::create() + ->filterByIsDefault(1) + ->select(CustomerFamilyTableMap::ID) + ->findOne(); + } + + return $customerFamilyId; + } + + /** + * @param $pseId + * @param $currencyId + * @return \CustomerFamily\Model\ProductPurchasePrice|\Thelia\Model\ProductPrice + */ + public function getPseProductPurchasePrice($pseId, $currencyId) + { + return ProductPurchasePriceQuery::create() + ->filterByCurrencyId($currencyId) + ->findOneByProductSaleElementsId($pseId); + } + + /** + * @param $pseId + * @param $currencyId + * @return \Thelia\Model\ProductPrice + */ + public function getPseProductPrice($pseId, $currencyId) + { + return ProductPriceQuery::create() + ->filterByCurrencyId($currencyId) + ->findOneByProductSaleElementsId($pseId); + } + + /** + * @param $pseId + * @param $currencyId + * @return string + */ + public function getPurchasePrice($pseId, $currencyId) + { + $mode = CustomerFamily::getConfigValue('customer_family_price_mode', 0); + if ($mode == 1) { + $pseProductPrice = $this->getPseProductPrice($pseId, $currencyId); + return $pseProductPrice !== null ? $pseProductPrice->getPrice() : null; + } + $pseProductPurchasePrice = $this->getPseProductPurchasePrice($pseId, $currencyId); + return $pseProductPurchasePrice !== null ? $pseProductPurchasePrice->getPurchasePrice() : null; + } + + /** + * @param $customerFamilyId + * @param int $isPromo + * @param null $useEquation + * @return \CustomerFamily\Model\CustomerFamilyPrice + */ + public function getCustomerFamilyPrice($customerFamilyId, $isPromo = 0, $useEquation = null) + { + $search = CustomerFamilyPriceQuery::create() + ->filterByPromo($isPromo) + ->filterByCustomerFamilyId($customerFamilyId); + + if ($useEquation !== null) { + $search->filterByUseEquation($useEquation); + } + + return $search->findOne(); + } + + /** + * @param $pse + * @param $customerFamilyId + * @param null $currencyId + * @return array|null + */ + public function calculateCustomerFamilyPsePrice($pse, $customerFamilyId, $currencyId = null) + { + $taxCountry = $this->taxEngine->getDeliveryCountry(); + + // Get default currency if no one is given + if ($currencyId === null) { + $currencyId = Currency::getDefaultCurrency()->getId(); + } + + // If the purchase price & its price exist + if (null !== $productPurchasePrice = $this->getPurchasePrice($pse->getId(), $currencyId)) { + // Initialize prices + $price = $taxedPrice = $promoPrice = $taxedPromoPrice = null; + + // Standard price + if (null !== $customerFamilyPrice = $this->getCustomerFamilyPrice($customerFamilyId, 0, 1)) { + // Calculate price + $price = round( + ($productPurchasePrice + $customerFamilyPrice->getAmountAddedBefore()) + * $customerFamilyPrice->getMultiplicationCoefficient() + + $customerFamilyPrice->getAmountAddedAfter(), + 2 + ); + + $pse->setVirtualColumn('CUSTOMER_FAMILY_PRICE', $price); + + // Tax + try { + $taxedPrice = $pse->getTaxedPrice($taxCountry, 'CUSTOMER_FAMILY_PRICE'); + } catch (TaxEngineException $e) { + $taxedPrice = null; + } + } + + // Promo price + if (null !== $customerFamilyPromoPrice = $this->getCustomerFamilyPrice($customerFamilyId, 1, 1)) { + // Calculate promo price + $promoPrice = round( + ($productPurchasePrice + $customerFamilyPromoPrice->getAmountAddedBefore()) + * $customerFamilyPromoPrice->getMultiplicationCoefficient() + + $customerFamilyPromoPrice->getAmountAddedAfter(), + 2 + ); + + $pse->setVirtualColumn('CUSTOMER_FAMILY_PROMO_PRICE', $promoPrice); + + // Tax + try { + $taxedPromoPrice = $pse->getTaxedPrice($taxCountry, 'CUSTOMER_FAMILY_PROMO_PRICE'); + } catch (TaxEngineException $e) { + $taxedPromoPrice = null; + } + } + + return [ + 'price' => $price, + 'taxedPrice' => $taxedPrice, + 'promoPrice' => $promoPrice, + 'taxedPromoPrice' => $taxedPromoPrice + ]; + } + return null; + } + + /** + * @param $pse + * @param null $customerId + * @param null $currencyId + * @return array|null + * @throws \Propel\Runtime\Exception\PropelException + */ + public function calculateCustomerPsePrice($pse, $customerId = null, $currencyId = null) + { + // Get customer's family + $customerFamilyId = $this->getCustomerCustomerFamilyId($customerId); + + return $this->calculateCustomerFamilyPsePrice($pse, $customerFamilyId, $currencyId); + } +} \ No newline at end of file diff --git a/local/modules/CustomerFamily/composer.json b/local/modules/CustomerFamily/composer.json new file mode 100644 index 00000000..51217171 --- /dev/null +++ b/local/modules/CustomerFamily/composer.json @@ -0,0 +1,12 @@ +{ + "name": "thelia/customer-family-module", + "type": "thelia-module", + "license": "LGPL V3", + "description": "For creating customer families", + "require": { + "thelia/installer": "~1.0" + }, + "extra": { + "installer-name": "CustomerFamily" + } +} diff --git a/local/modules/CustomerFamily/templates/backOffice/default/assets/css/style.css b/local/modules/CustomerFamily/templates/backOffice/default/assets/css/style.css new file mode 100644 index 00000000..7facf66e --- /dev/null +++ b/local/modules/CustomerFamily/templates/backOffice/default/assets/css/style.css @@ -0,0 +1,3 @@ +table#combinations_list > tbody > tr.purchase-price > td { + border-top: none; +} \ No newline at end of file diff --git a/local/modules/CustomerFamily/templates/backOffice/default/assets/js/customer-create.js b/local/modules/CustomerFamily/templates/backOffice/default/assets/js/customer-create.js new file mode 100644 index 00000000..f70330fe --- /dev/null +++ b/local/modules/CustomerFamily/templates/backOffice/default/assets/js/customer-create.js @@ -0,0 +1,8 @@ +/* Hide professional fields if the customer is not a professional one. */ +$('#customer_family_code_select').change(function(){ + var data_code = $('#customer_family_code_select option:selected').attr('data-code'); + $('#customer-family-extra-fields').css( + 'display', + (data_code === 'particular' || data_code === 'none') ? 'none' : 'block' + ); +}); diff --git a/local/modules/CustomerFamily/templates/backOffice/default/assets/js/module-config-js.html b/local/modules/CustomerFamily/templates/backOffice/default/assets/js/module-config-js.html new file mode 100644 index 00000000..c2beb643 --- /dev/null +++ b/local/modules/CustomerFamily/templates/backOffice/default/assets/js/module-config-js.html @@ -0,0 +1,62 @@ +{javascripts file="assets/js/bootstrap-switch/bootstrap-switch.js"} + +{/javascripts} + + \ No newline at end of file diff --git a/local/modules/CustomerFamily/templates/backOffice/default/assets/js/product-creation-price.js b/local/modules/CustomerFamily/templates/backOffice/default/assets/js/product-creation-price.js new file mode 100644 index 00000000..71673bc3 --- /dev/null +++ b/local/modules/CustomerFamily/templates/backOffice/default/assets/js/product-creation-price.js @@ -0,0 +1,4 @@ +$("a.action-btn[href='#product_creation_dialog']").click(function() { + $('#price_without_tax').val(0); + $('#price_with_tax').val(0); +}); \ No newline at end of file diff --git a/local/modules/CustomerFamily/templates/backOffice/default/customer-create.html b/local/modules/CustomerFamily/templates/backOffice/default/customer-create.html new file mode 100644 index 00000000..87aa86e9 --- /dev/null +++ b/local/modules/CustomerFamily/templates/backOffice/default/customer-create.html @@ -0,0 +1,45 @@ +{form_field form=$form field='customer_family_code'} +
+ +
+ + {if $error } + {$message} + {assign var="error_focus" value="true"} + {/if} +
+
+{/form_field} + +{* Additional fields for CustomerCustomerFamily creation. Should not be displayed if the customer is a particular one. *} + diff --git a/local/modules/CustomerFamily/templates/backOffice/default/customer-edit.html b/local/modules/CustomerFamily/templates/backOffice/default/customer-edit.html new file mode 100644 index 00000000..1c67c8e0 --- /dev/null +++ b/local/modules/CustomerFamily/templates/backOffice/default/customer-edit.html @@ -0,0 +1,81 @@ +{loop name="customer_customer_family" type="customer_customer_family" customer_id=$customer_id} + {assign var="_customer_family_id_" value=$CUSTOMER_FAMILY_ID} + {assign var="_siret_" value=$SIRET} + {assign var="_vat_" value=$VAT} +{/loop} + +
+
+
+
{intl l="Family of this customer" d="customerfamily"}
+
+
+ {form name="customer.customer.family.form"} + + + {form_hidden_fields form=$form} + + {if $form_error}
{$form_error_message}
{/if} + + {form_field form=$form field='customer_id'} + + {/form_field} + + {form_field form=$form field='customer_family_id'} +
+ +
+ +
+
+ {/form_field} + + {form_field form=$form field="siret"} +
+ + +
+ + {if $error } + {$message} + {assign var="error_focus" value="true"} + {/if} +
+
+ {/form_field} + + {form_field form=$form field="vat"} +
+ + +
+ + {if $error } + {$message} + {assign var="error_focus" value="true"} + {/if} +
+
+ {/form_field} + +
+
+ + +
+
+ + + {/form} +
+
+
+
+
\ No newline at end of file diff --git a/local/modules/CustomerFamily/templates/backOffice/default/customer_family_module_configuration.html b/local/modules/CustomerFamily/templates/backOffice/default/customer_family_module_configuration.html new file mode 100644 index 00000000..f9e502a0 --- /dev/null +++ b/local/modules/CustomerFamily/templates/backOffice/default/customer_family_module_configuration.html @@ -0,0 +1,490 @@ +{extends file="admin-layout.tpl"} + +{block name="after-bootstrap-css"} + +{/block} + +{block name="no-return-functions"} + {$admin_current_location = 'module'} +{/block} + +{block name="page-title"}Configuration CustomerFamily{/block} + +{block name="check-resource"}admin.module{/block} +{block name="check-access"}view{/block} +{block name="check-module"}CustomerFamily{/block} + +{block name="main-content"} + +
+
+ {intl l="Customer Family" d='customerfamily.bo.default'} +
+ +
+
+ + + +
+ + +
+
+
+ {if $hide_flags != true} + + {/if} +
+ + {form name="customer.family.delete.form"} + {if $form_error} +
{$form_error_message}
+ + + + + + + + + + + + {ifloop rel="customer_family"} + + + {form name='customer_family_update_default_form'} + + + {form_hidden_fields form=$form} + + {form_field form=$form field="customer_family_id"} + + {/form_field} + + {/form} + + + {loop type="customer_family" name="customer_family" lang=$edit_language_id force_return="on"} + + + + + + + + {/loop} + {/ifloop} + {elseloop rel="customer_family"} + + + + {/elseloop} + + + + + + +
+ {intl l="ID"} + + {intl l="Code"} + + {intl l="Title"} + + {intl l="Default"} + + {intl l="Action"} +
+ {$CUSTOMER_FAMILY_ID} + + {$CODE} + + {$TITLE_CUSTOMER_FAMILY} + +
+ +
+
+ {intl l="Edit" d='customerfamily.bo.default'} + {intl l="Delete"} +
+ {intl l="No family" d='customerfamily.bo.default'} +
+ {form name="customer.family.create.form"} +
+ {if $form_error} +
{$form_error_message}
+ {/form_field} + {form_field form=$form field="code"} +
+ +
+ {/form_field} + {form_field form=$form field="title"} +
+ +
+ {/form_field} +
+ +
+
+ {/form} +
+
+
+ + {form name="customer.family.delete.form"} + + {/form} + + {form name="customer.family.update.form"} + + {/form} +
+ {form name="customer_family_price_mode"} +
+ {form_hidden_fields form=$form} + {form_field form=$form field="price_mode"} + + + {/form_field} +
+ {$label_attr.help} +
+
+ {/form} +
+
+ + +
+
+ + +
+
+ +

+ {intl l="Define if your prices are the products' ones or if they are calculated by the equation with your parameters." d='customerfamily.bo.default'} +

+

+ {intl l="Not using the equation will display the fix product price to customers." d='customerfamily.bo.default'} +

+

+ {intl l='Equation: ( ( product_purchase_price + fix_amount_1 ) x factor ) + fix_amount_2' d='customerfamily.bo.default'} +

+
+ + + + + + + + + + + + + + {loop type='customer_family' name='customerfamily_loop'} + + {assign var='amount_added_before' value=0} + {assign var='coefficient' value=1} + {assign var='amount_added_after' value=0} + {assign var='is_taxed' value=1} + {assign var='use_equation' value=0} + + + + {form name='customer_family_price_update'} + + + {form_hidden_fields form=$form} + + {form_field form=$form field='promo'} + + {/form_field} + + {loop type='customer_family_price' name='customer_family_price_loop' promo=0 customer_family_id=$CUSTOMER_FAMILY_ID} + {assign var='amount_added_before' value=$AMOUNT_ADDED_BEFORE} + {assign var='coefficient' value=$COEFFICIENT} + {assign var='amount_added_after' value=$AMOUNT_ADDED_AFTER} + {assign var='is_taxed' value=$IS_TAXED} + {assign var='use_equation' value=$USE_EQUATION} + {/loop} + + + + + + + + + + {/form} + + + {assign var='amount_added_before' value=0} + {assign var='coefficient' value=1} + {assign var='amount_added_after' value=0} + {assign var='is_taxed' value=1} + {assign var='use_equation' value=0} + + + + {form name='customer_family_price_update'} + + + {form_hidden_fields form=$form} + + {form_field form=$form field='promo'} + + {/form_field} + + {loop type='customer_family_price' name='customer_family_price_promo_loop' promo=1 customer_family_id=$CUSTOMER_FAMILY_ID} + {assign var='amount_added_before' value=$AMOUNT_ADDED_BEFORE} + {assign var='coefficient' value=$COEFFICIENT} + {assign var='amount_added_after' value=$AMOUNT_ADDED_AFTER} + {assign var='is_taxed' value=$IS_TAXED} + {assign var='use_equation' value=$USE_EQUATION} + {/loop} + + + + + + + + + + {/form} + + {/loop} + +
{intl l='Customer family' d='customerfamily.bo.default'}{intl l='Use equation' d='customerfamily.bo.default'}{intl l='Fix amount 1' d='customerfamily.bo.default'}{intl l='Factor' d='customerfamily.bo.default'}{intl l='Fix amount 2' d='customerfamily.bo.default'}{intl l='Show taxes' d='customerfamily.bo.default'}
{intl l='(need specific integration)' d='customerfamily.bo.default'}
{intl l='Save' d='customerfamily.bo.default'}
+ {$TITLE_CUSTOMER_FAMILY} + {form_field form=$form field="customer_family_id"} + + {/form_field} + + {form_field form=$form field="use_equation"} + + {/form_field} + + {form_field form=$form field="amount_added_before"} + + {/form_field} + + {form_field form=$form field="coefficient"} + + {/form_field} + + {form_field form=$form field="amount_added_after"} + + {/form_field} + + {form_field form=$form field="is_taxed"} + + {/form_field} + + +
+ {$TITLE_CUSTOMER_FAMILY} - {intl l='Promo' d='customerfamily.bo.default'} + {form_field form=$form field="customer_family_id"} + + {/form_field} + + {form_field form=$form field="use_equation"} + + {/form_field} + + {form_field form=$form field="amount_added_before"} + + {/form_field} + + {form_field form=$form field="coefficient"} + + {/form_field} + + {form_field form=$form field="amount_added_after"} + + {/form_field} + + {form_field form=$form field="is_taxed"} + + {/form_field} + + +
+
+
+
+ +
+
+ {loop type='customer_family' name='customerfamily_loop'} +
+
+
+ {$TITLE_CUSTOMER_FAMILY} +
+ +
+

{intl l="Choose what categories will be available for this customer family" d='customerfamily.bo.default'}

+ +
+ +
+
+ {/loop} +
+
+
+
+ {loop type='customer_family' name='customerfamily_loop'} +
+
+
+ {$TITLE_CUSTOMER_FAMILY} +
+ +
+

{intl l="Choose what brands will be available for this customer family" d='customerfamily.bo.default'}

+ +
+ +
+
+ {/loop} +
+
+
+
+
+ + + +{/block} + +{block name="javascript-initialization"} + +{/block} \ No newline at end of file diff --git a/local/modules/CustomerFamily/templates/backOffice/default/product-create-form.html b/local/modules/CustomerFamily/templates/backOffice/default/product-create-form.html new file mode 100644 index 00000000..a38ae072 --- /dev/null +++ b/local/modules/CustomerFamily/templates/backOffice/default/product-create-form.html @@ -0,0 +1,16 @@ +
+
+ {form_field field='purchase_price'} + {loop type="currency" name="default-currency" default_only="1" backend_context="1"} + + +
+ + {$SYMBOL} +
+ +
{intl l='Enter here the product purchase price in %title' title={$NAME}}
+ {/loop} + {/form_field} +
+
\ No newline at end of file diff --git a/local/modules/CustomerFamily/templates/backOffice/default/product-details-pricing.html b/local/modules/CustomerFamily/templates/backOffice/default/product-details-pricing.html new file mode 100644 index 00000000..d9cd22c7 --- /dev/null +++ b/local/modules/CustomerFamily/templates/backOffice/default/product-details-pricing.html @@ -0,0 +1,52 @@ +{loop type='product' name='product_default_pse_loop' id=$product_id visible='*' backend_context=1} + {loop type="product_purchase_price" name="product_purchase_price_loop" pse_id=$PRODUCT_SALE_ELEMENT currency_id=$edit_currency_id} + {assign var="purchasePrice" value=$PURCHASE_PRICE} + {/loop} + + {form_field field='purchase_price'} +
+ +
+ + {currency attr="symbol"} +
+
+ {/form_field} + + {if $purchasePrice !== ''} + {loop type='customer_family' name='customer_family_loop_prices'} + {loop type='customer_family_pse_calculated_prices' name='calculated_prices' pse_id=$PRODUCT_SALE_ELEMENT customer_family_id=$CUSTOMER_FAMILY_ID currency_id=$edit_currency_id} +
+ + + +
+ +
+
+ +
+ + {currency attr="symbol"} +
+
+
+ +
+
+ +
+ + {currency attr="symbol"} +
+
+
+
+
+ {/loop} + {/loop} + {/if} +{/loop} \ No newline at end of file diff --git a/local/modules/CustomerFamily/templates/backOffice/default/product-details-promo.html b/local/modules/CustomerFamily/templates/backOffice/default/product-details-promo.html new file mode 100644 index 00000000..971b602f --- /dev/null +++ b/local/modules/CustomerFamily/templates/backOffice/default/product-details-promo.html @@ -0,0 +1,42 @@ +{loop type='product' name='product_default_pse_promo_loop' id=$product_id visible='*' backend_context=1} + {loop type="product_purchase_price" name="product_purchase_price_loop" pse_id=$PRODUCT_SALE_ELEMENT currency_id=$edit_currency_id} + {assign var="purchasePrice" value=$PURCHASE_PRICE} + {/loop} + + {if $purchasePrice !== ''} + {loop type='customer_family' name='customer_family_loop_promo_prices'} + {loop type='customer_family_pse_calculated_prices' name='calculated_promo_prices' pse_id=$PRODUCT_SALE_ELEMENT customer_family_id=$CUSTOMER_FAMILY_ID currency_id=$edit_currency_id} +
+ + + +
+ +
+
+ +
+ + {currency attr="symbol"} +
+
+
+ +
+
+ +
+ + {currency attr="symbol"} +
+
+
+
+
+ {/loop} + {/loop} + {/if} +{/loop} \ No newline at end of file diff --git a/local/modules/CustomerFamily/templates/backOffice/default/product-edit-price.html b/local/modules/CustomerFamily/templates/backOffice/default/product-edit-price.html new file mode 100644 index 00000000..a747e591 --- /dev/null +++ b/local/modules/CustomerFamily/templates/backOffice/default/product-edit-price.html @@ -0,0 +1,53 @@ +{loop type="product_purchase_price" name="pse_purchase_price_loop" pse_id=$pseId currency_id=$edit_currency_id} + {assign var="purchasePrice" value=$PURCHASE_PRICE} +{/loop} + + + + + {form_field field='purchase_price' value_key=$idx} + + + + + + + + + {/form_field} + + +{if $purchasePrice !== ''} + {loop type='customer_family' name='customer_family_loop_prices'} + {loop type='customer_family_pse_calculated_prices' name='calculated_prices' pse_id=$pseId customer_family_id=$CUSTOMER_FAMILY_ID} + + + + + {intl l='Price for:' d='customerfamily.bo.default'} {$TITLE_CUSTOMER_FAMILY} + + + + + {intl l='Calculated price' d='customerfamily.bo.default'} + + + + + + + + + + {intl l='Calculated promo price' d='customerfamily.bo.default'} + + + + + + + + + {/loop} + {/loop} +{/if} \ No newline at end of file diff --git a/local/modules/CustomerFamily/templates/frontOffice/default/account-additional.html b/local/modules/CustomerFamily/templates/frontOffice/default/account-additional.html new file mode 100644 index 00000000..deb22996 --- /dev/null +++ b/local/modules/CustomerFamily/templates/frontOffice/default/account-additional.html @@ -0,0 +1,26 @@ +{default_translation_domain domain=$messageDomain} +{loop type="customer_customer_family" name="customer_customer_family" customer_id={$customerId} } +
+ {loop type="customer_family" name="customer_family" id={$CUSTOMER_FAMILY_ID} } + + + + + + + {if $CODE != $particular} + {* The Customer should have a SIRET and a VAT. Display them. *} + + + + + + + + + {/if} + + + {/loop} +
+{/loop} diff --git a/local/modules/CustomerFamily/templates/frontOffice/default/account-update.html b/local/modules/CustomerFamily/templates/frontOffice/default/account-update.html new file mode 100644 index 00000000..b92a09fb --- /dev/null +++ b/local/modules/CustomerFamily/templates/frontOffice/default/account-update.html @@ -0,0 +1,50 @@ +{default_translation_domain domain=$messageDomain} +
+
{intl l='Customer family'}
+
+ {form_field form=$form field='customer_family_code'} +
+ +
+ + {if $error } + {$message} + {assign var="error_focus" value="true"} + {/if} +
+
+ {/form_field} + {* Additional fields for CustomerCustomerFamily update. Should not be displayed if the customer is a particular one. *} +
+ {form_field form=$form field='siret' } +
+ +
+ + {if $error } + {$message} + {assign var="error_focus" value="true"} + {/if} +
+
+ {/form_field} + {form_field form=$form field='vat' } +
+ +
+ + {if $error } + {$message} + {assign var="error_focus" value="true"} + {/if} +
+
+ {/form_field} +
+
+
diff --git a/local/modules/CustomerFamily/templates/frontOffice/default/assets/js/register.js b/local/modules/CustomerFamily/templates/frontOffice/default/assets/js/register.js new file mode 100644 index 00000000..f14e53cd --- /dev/null +++ b/local/modules/CustomerFamily/templates/frontOffice/default/assets/js/register.js @@ -0,0 +1,16 @@ +$('#customer_family_code_select').change(customerFamilyShowProFields); + +/* Number for the customer family panel. */ +$(document).ready(function (e) { + $('#number-customer-family').text($('#register-customer-family').prevAll('fieldset').length + 1); + customerFamilyShowProFields(); +}); + +/* Hiding professional fields if the customer is not a professional one. */ +function customerFamilyShowProFields() { + var data_code = $('#customer_family_code_select option:selected').attr('data-code'); + $('#customer-family-extra-fields').css( + 'display', + (data_code === 'particular' || data_code === 'none') ? 'none' : 'block' + ); +} diff --git a/local/modules/CustomerFamily/templates/frontOffice/default/assets/js/update.js b/local/modules/CustomerFamily/templates/frontOffice/default/assets/js/update.js new file mode 100644 index 00000000..2429d5ac --- /dev/null +++ b/local/modules/CustomerFamily/templates/frontOffice/default/assets/js/update.js @@ -0,0 +1,11 @@ +/* Hiding professional fields if the customer is not a professional one. */ +function customerFamilyShowProFields() { + var data_code = $('#customer_family_code_select option:selected').attr('data-code'); + $('#customer-family-extra-fields').css( + 'display', + (data_code === 'particular' || data_code === 'none') ? 'none' : 'block' + ); +} + +$('#customer_family_code_select').change(customerFamilyShowProFields); +$(document).ready(customerFamilyShowProFields); diff --git a/local/modules/CustomerFamily/templates/frontOffice/default/register.html b/local/modules/CustomerFamily/templates/frontOffice/default/register.html new file mode 100644 index 00000000..ad52e87b --- /dev/null +++ b/local/modules/CustomerFamily/templates/frontOffice/default/register.html @@ -0,0 +1,50 @@ +{default_translation_domain domain=$messageDomain} +
+
. {intl l='Customer family'}
+
+ {form_field form=$form field='customer_family_code'} +
+ +
+ + {if $error } + {$message} + {assign var="error_focus" value="true"} + {/if} +
+
+ {/form_field} + {* Additional fields for CustomerCustomerFamily creation. Should not be displayed if the customer is a particular one. *} +
+ {form_field form=$form field='siret' } +
+ +
+ + {if $error } + {$message} + {assign var="error_focus" value="true"} + {/if} +
+
+ {/form_field} + {form_field form=$form field='vat' } +
+ +
+ + {if $error } + {$message} + {assign var="error_focus" value="true"} + {/if} +
+
+ {/form_field} +
+
+
diff --git a/local/modules/OrderComment/Config/config.xml b/local/modules/OrderComment/Config/config.xml new file mode 100644 index 00000000..dc2289f8 --- /dev/null +++ b/local/modules/OrderComment/Config/config.xml @@ -0,0 +1,42 @@ + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/local/modules/OrderComment/Config/module.xml b/local/modules/OrderComment/Config/module.xml new file mode 100644 index 00000000..e73e81b0 --- /dev/null +++ b/local/modules/OrderComment/Config/module.xml @@ -0,0 +1,18 @@ + + + OrderComment\OrderComment + + Allow customer to add comment to this order + + + Permet au client d'ajouter un commentaire à sa commande + + 1.2.3 + + Vincent Lopes-Vicente + vlopes@openstudio.fr + + classic + 2.1. + other + diff --git a/local/modules/OrderComment/Config/routing.xml b/local/modules/OrderComment/Config/routing.xml new file mode 100644 index 00000000..63448cf4 --- /dev/null +++ b/local/modules/OrderComment/Config/routing.xml @@ -0,0 +1,11 @@ + + + + + + OrderComment\Controller\OrderCommentController::setComment + + + diff --git a/local/modules/OrderComment/Config/schema.xml b/local/modules/OrderComment/Config/schema.xml new file mode 100644 index 00000000..a59d952f --- /dev/null +++ b/local/modules/OrderComment/Config/schema.xml @@ -0,0 +1,13 @@ + + + + + + + + + + +
+ +
diff --git a/local/modules/OrderComment/Config/thelia.sql b/local/modules/OrderComment/Config/thelia.sql new file mode 100644 index 00000000..6b11e304 --- /dev/null +++ b/local/modules/OrderComment/Config/thelia.sql @@ -0,0 +1,27 @@ + +# 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; + +-- --------------------------------------------------------------------- +-- order_comment +-- --------------------------------------------------------------------- + +DROP TABLE IF EXISTS `order_comment`; + +CREATE TABLE `order_comment` +( + `id` INTEGER NOT NULL AUTO_INCREMENT, + `order_id` INTEGER NOT NULL, + `comment` TEXT NOT NULL, + PRIMARY KEY (`id`), + INDEX `FI_order_comment_order_id` (`order_id`), + CONSTRAINT `fk_order_comment_order_id` + FOREIGN KEY (`order_id`) + REFERENCES `order` (`id`) + ON UPDATE RESTRICT + 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/OrderComment/Controller/OrderCommentController.php b/local/modules/OrderComment/Controller/OrderCommentController.php new file mode 100644 index 00000000..625c3292 --- /dev/null +++ b/local/modules/OrderComment/Controller/OrderCommentController.php @@ -0,0 +1,53 @@ +getRequest()); + + try { + $form = $this->validateForm($commentForm); + $data = $form->getData(); + $comment = $data['comment']; + + if (!empty($comment)) { + $this->getRequest()->getSession()->set('order-comment', $comment); + } + + return $this->generateRedirectFromRoute("order.delivery"); + + } catch (FormValidationException $e) { + $message = Translator::getInstance()->trans("Please check your input: %s", ['%s' => $e->getMessage()], Front::MESSAGE_DOMAIN); + } catch (PropelException $e) { + $this->getParserContext()->setGeneralError($e->getMessage()); + } catch (\Exception $e) { + $message = Translator::getInstance()->trans("Sorry, an error occurred: %s", ['%s' => $e->getMessage()], Front::MESSAGE_DOMAIN); + } + + if ($message !== false) { + $commentForm->setErrorMessage($message); + + $this->getParserContext() + ->addForm($commentForm) + ->setGeneralError($message) + ; + + return $this->generateRedirectFromRoute("cart.view"); + } + } +} diff --git a/local/modules/OrderComment/EventListeners/OrderEventListener.php b/local/modules/OrderComment/EventListeners/OrderEventListener.php new file mode 100644 index 00000000..bde65eb9 --- /dev/null +++ b/local/modules/OrderComment/EventListeners/OrderEventListener.php @@ -0,0 +1,63 @@ +requestStack = $requestStack; + } + + public static function getSubscribedEvents() + { + return array( + TheliaEvents::ORDER_AFTER_CREATE => array('onOrderCreate', 128), + TheliaEvents::ORDER_SET_DELIVERY_MODULE => array('onOrderSetDeliveryModule', 128), + ); + } + + public function onOrderSetDeliveryModule(OrderEvent $event) + { + $request = $this->requestStack->getCurrentRequest(); + $form = $request->request->get(OrderFormListener::THELIA_ORDER_DELIVERY_FORM_NAME); + + if (is_null($form) or !array_key_exists(OrderFormListener::ORDER_COMMENT_FORM_FIELD_NAME, $form)) { + return; + } + + $comment = $form[OrderFormListener::ORDER_COMMENT_FORM_FIELD_NAME]; + + if (!empty($comment)) { + $request->getSession()->set('order-comment', $comment); + } + } + + public function onOrderCreate(OrderEvent $event) + { + $session = $this->requestStack->getCurrentRequest()->getSession(); + $comment = $session->get('order-comment', null); + + $order = $event->getOrder(); + $orderId = $order->getId(); + + if ($orderId != null && !empty($comment)) { + $orderComment = new OrderComment(); + $orderComment->setOrderId($orderId); + $orderComment->setComment($comment); + $orderComment->save(); + + $session->set('order-comment', ''); + } + } +} diff --git a/local/modules/OrderComment/EventListeners/OrderFormListener.php b/local/modules/OrderComment/EventListeners/OrderFormListener.php new file mode 100644 index 00000000..64b0b3ac --- /dev/null +++ b/local/modules/OrderComment/EventListeners/OrderFormListener.php @@ -0,0 +1,33 @@ + array('addCommentFieldForDelivery', 128), + ); + } + + /** + * Callback used to add a comment field to the Thelia's OrderDelivery form. + * @param TheliaFormEvent $event + */ + public function addCommentFieldForDelivery(TheliaFormEvent $event) + { + CommentForm::addCommentFormField($event->getForm()->getFormBuilder()); + } +} diff --git a/local/modules/OrderComment/Form/CommentForm.php b/local/modules/OrderComment/Form/CommentForm.php new file mode 100644 index 00000000..cc0f48d2 --- /dev/null +++ b/local/modules/OrderComment/Form/CommentForm.php @@ -0,0 +1,31 @@ +formBuilder); + } + + public static function addCommentFormField(FormBuilderInterface $formBuilder) + { + $formBuilder + ->add( + 'comment', + 'textarea', + array( + 'required' => false + ) + ); + } + + public function getName() + { + return "order_comment_form"; + } +} diff --git a/local/modules/OrderComment/Hook/BackHook.php b/local/modules/OrderComment/Hook/BackHook.php new file mode 100644 index 00000000..6c07383c --- /dev/null +++ b/local/modules/OrderComment/Hook/BackHook.php @@ -0,0 +1,43 @@ + + */ +class BackHook extends BaseHook +{ + public function onOrderEditAfterOrderProductList(HookRenderEvent $event) + { + $content = $this->render("order-edit.html"); + $event->add($content); + } + + public function onOrderEditBillBottom(HookRenderEvent $event) + { + $content = $this->render("order-edit.html"); + $event->add($content); + } + + public function onOrderTabContent(HookRenderEvent $event) + { + $content = $this->render("order-edit.html"); + $event->add($content); + } + +} \ No newline at end of file diff --git a/local/modules/OrderComment/Hook/FrontHook.php b/local/modules/OrderComment/Hook/FrontHook.php new file mode 100644 index 00000000..c4f6e6e1 --- /dev/null +++ b/local/modules/OrderComment/Hook/FrontHook.php @@ -0,0 +1,39 @@ + + */ +class FrontHook extends BaseHook +{ + public function onCartBottom(HookRenderEvent $event) + { + $event->add($this->render("OrderComment/cart-comment.html")); + } + + public function onCartIncludeJs(HookRenderEvent $event) + { + $event->add(($this->addJS("OrderComment/assets/js/cart-comment-js.js"))); + } + + public function onDeliveryFormBottom(HookRenderEvent $event) + { + $event->add($this->render("OrderComment/comment-input.html")); + } +} \ No newline at end of file diff --git a/local/modules/OrderComment/Hook/PdfHook.php b/local/modules/OrderComment/Hook/PdfHook.php new file mode 100644 index 00000000..2e124e84 --- /dev/null +++ b/local/modules/OrderComment/Hook/PdfHook.php @@ -0,0 +1,35 @@ + + */ +class PdfHook extends BaseHook +{ + + /** + * @param HookRenderEvent $event + */ + public function onDeliveryAfterSummary(HookRenderEvent $event) + { + $order_id = intval($event->getArgument('order', null)); + + $event->add($this->render('delivery.after-summary.html', ['order_id' => $order_id])); + } +} diff --git a/local/modules/OrderComment/I18n/backOffice/default/en_US.php b/local/modules/OrderComment/I18n/backOffice/default/en_US.php new file mode 100644 index 00000000..f3725b82 --- /dev/null +++ b/local/modules/OrderComment/I18n/backOffice/default/en_US.php @@ -0,0 +1,6 @@ + 'Customer comment', + 'No comment for this order was defined.' => 'No comment for this order was defined.', +); diff --git a/local/modules/OrderComment/I18n/backOffice/default/fr_FR.php b/local/modules/OrderComment/I18n/backOffice/default/fr_FR.php new file mode 100644 index 00000000..08359a22 --- /dev/null +++ b/local/modules/OrderComment/I18n/backOffice/default/fr_FR.php @@ -0,0 +1,6 @@ + 'Commentaire client', + 'No comment for this order was defined.' => 'Aucun commentaire pour cette commande', +); diff --git a/local/modules/OrderComment/I18n/en_US.php b/local/modules/OrderComment/I18n/en_US.php new file mode 100644 index 00000000..6c521582 --- /dev/null +++ b/local/modules/OrderComment/I18n/en_US.php @@ -0,0 +1,5 @@ + 'Please check your input: %s', + 'Sorry, an error occurred: %s' => 'Sorry, an error occurred: %s' +); diff --git a/local/modules/OrderComment/I18n/fr_FR.php b/local/modules/OrderComment/I18n/fr_FR.php new file mode 100644 index 00000000..2863c7cd --- /dev/null +++ b/local/modules/OrderComment/I18n/fr_FR.php @@ -0,0 +1,5 @@ + 'Veuillez verifier vos données: %s', + 'Sorry, an error occured: %s' => 'Désolé une erreur est survenue: %s' +); diff --git a/local/modules/OrderComment/I18n/frontOffice/default/en_US.php b/local/modules/OrderComment/I18n/frontOffice/default/en_US.php new file mode 100644 index 00000000..35b0d15a --- /dev/null +++ b/local/modules/OrderComment/I18n/frontOffice/default/en_US.php @@ -0,0 +1,8 @@ + 'Add your comment', + 'Continue Shopping' => 'Continue Shopping', + 'Proceed checkout' => 'Proceed checkout', + 'Type your message here' => 'Type your message here', +); diff --git a/local/modules/OrderComment/I18n/frontOffice/default/fr_FR.php b/local/modules/OrderComment/I18n/frontOffice/default/fr_FR.php new file mode 100644 index 00000000..ac5b02e8 --- /dev/null +++ b/local/modules/OrderComment/I18n/frontOffice/default/fr_FR.php @@ -0,0 +1,8 @@ + 'Ajouter un commentaire', + 'Continue Shopping' => 'Continuer mes achats', + 'Proceed checkout' => 'Continuer la commande', + 'Type your message here' => 'Ecrivez votre commentaire ici', +); diff --git a/local/modules/OrderComment/LICENSE.txt b/local/modules/OrderComment/LICENSE.txt new file mode 100644 index 00000000..65c5ca88 --- /dev/null +++ b/local/modules/OrderComment/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/OrderComment/Loop/OrderCommentLoop.php b/local/modules/OrderComment/Loop/OrderCommentLoop.php new file mode 100644 index 00000000..73a874ed --- /dev/null +++ b/local/modules/OrderComment/Loop/OrderCommentLoop.php @@ -0,0 +1,54 @@ +filterByOrderId($this->getOrderId()); + + return $orderCommentQuery; + } + + /** + * @param LoopResult $loopResult + * + * @return LoopResult + */ + public function parseResults(LoopResult $loopResult) + { + /** @var \OrderComment\Model\OrderComment $orderComment */ + foreach ($loopResult->getResultDataCollection() as $orderComment) { + $loopResultRow = new LoopResultRow($orderComment); + + $loopResultRow->set("ORDER_COMMENT", $orderComment->getComment()); + $loopResult->addRow($loopResultRow); + } + + return $loopResult; + } +} diff --git a/local/modules/OrderComment/Loop/SessionOrderCommentLoop.php b/local/modules/OrderComment/Loop/SessionOrderCommentLoop.php new file mode 100644 index 00000000..a8884271 --- /dev/null +++ b/local/modules/OrderComment/Loop/SessionOrderCommentLoop.php @@ -0,0 +1,36 @@ + $this->request->getSession()->get('order-comment')]; + + return $item; + } + + public function parseResults(LoopResult $loopResult) + { + $item = $loopResult->getResultDataCollection(); + + $loopResultRow = new LoopResultRow(); + $loopResultRow->set('ORDER_COMMENT', $item['comment']); + + $loopResult->addRow($loopResultRow); + + return $loopResult; + } + + public function getArgDefinitions() + { + return new ArgumentCollection(); + } +} diff --git a/local/modules/OrderComment/Model/Base/OrderComment.php b/local/modules/OrderComment/Model/Base/OrderComment.php new file mode 100644 index 00000000..076be4e9 --- /dev/null +++ b/local/modules/OrderComment/Model/Base/OrderComment.php @@ -0,0 +1,1253 @@ +modifiedColumns; + } + + /** + * Has specified column been modified? + * + * @param string $col column fully qualified name (TableMap::TYPE_COLNAME), e.g. Book::AUTHOR_ID + * @return boolean True if $col has been modified. + */ + public function isColumnModified($col) + { + return $this->modifiedColumns && isset($this->modifiedColumns[$col]); + } + + /** + * Get the columns that have been modified in this object. + * @return array A unique list of the modified column names for this object. + */ + public function getModifiedColumns() + { + return $this->modifiedColumns ? array_keys($this->modifiedColumns) : []; + } + + /** + * Returns whether the object has ever been saved. This will + * be false, if the object was retrieved from storage or was created + * and then saved. + * + * @return boolean true, if the object has never been persisted. + */ + public function isNew() + { + return $this->new; + } + + /** + * Setter for the isNew attribute. This method will be called + * by Propel-generated children and objects. + * + * @param boolean $b the state of the object. + */ + public function setNew($b) + { + $this->new = (Boolean) $b; + } + + /** + * Whether this object has been deleted. + * @return boolean The deleted state of this object. + */ + public function isDeleted() + { + return $this->deleted; + } + + /** + * Specify whether this object has been deleted. + * @param boolean $b The deleted state of this object. + * @return void + */ + public function setDeleted($b) + { + $this->deleted = (Boolean) $b; + } + + /** + * Sets the modified state for the object to be false. + * @param string $col If supplied, only the specified column is reset. + * @return void + */ + public function resetModified($col = null) + { + if (null !== $col) { + if (isset($this->modifiedColumns[$col])) { + unset($this->modifiedColumns[$col]); + } + } else { + $this->modifiedColumns = array(); + } + } + + /** + * Compares this with another OrderComment instance. If + * obj is an instance of OrderComment, delegates to + * equals(OrderComment). Otherwise, returns false. + * + * @param mixed $obj The object to compare to. + * @return boolean Whether equal to the object specified. + */ + public function equals($obj) + { + $thisclazz = get_class($this); + if (!is_object($obj) || !($obj instanceof $thisclazz)) { + return false; + } + + if ($this === $obj) { + return true; + } + + if (null === $this->getPrimaryKey() + || null === $obj->getPrimaryKey()) { + return false; + } + + return $this->getPrimaryKey() === $obj->getPrimaryKey(); + } + + /** + * If the primary key is not null, return the hashcode of the + * primary key. Otherwise, return the hash code of the object. + * + * @return int Hashcode + */ + public function hashCode() + { + if (null !== $this->getPrimaryKey()) { + return crc32(serialize($this->getPrimaryKey())); + } + + return crc32(serialize(clone $this)); + } + + /** + * Get the associative array of the virtual columns in this object + * + * @return array + */ + public function getVirtualColumns() + { + return $this->virtualColumns; + } + + /** + * Checks the existence of a virtual column in this object + * + * @param string $name The virtual column name + * @return boolean + */ + public function hasVirtualColumn($name) + { + return array_key_exists($name, $this->virtualColumns); + } + + /** + * Get the value of a virtual column in this object + * + * @param string $name The virtual column name + * @return mixed + * + * @throws PropelException + */ + public function getVirtualColumn($name) + { + if (!$this->hasVirtualColumn($name)) { + throw new PropelException(sprintf('Cannot get value of inexistent virtual column %s.', $name)); + } + + return $this->virtualColumns[$name]; + } + + /** + * Set the value of a virtual column in this object + * + * @param string $name The virtual column name + * @param mixed $value The value to give to the virtual column + * + * @return OrderComment The current object, for fluid interface + */ + public function setVirtualColumn($name, $value) + { + $this->virtualColumns[$name] = $value; + + return $this; + } + + /** + * Logs a message using Propel::log(). + * + * @param string $msg + * @param int $priority One of the Propel::LOG_* logging levels + * @return boolean + */ + protected function log($msg, $priority = Propel::LOG_INFO) + { + return Propel::log(get_class($this) . ': ' . $msg, $priority); + } + + /** + * Populate the current object from a string, using a given parser format + * + * $book = new Book(); + * $book->importFrom('JSON', '{"Id":9012,"Title":"Don Juan","ISBN":"0140422161","Price":12.99,"PublisherId":1234,"AuthorId":5678}'); + * + * + * @param mixed $parser A AbstractParser instance, + * or a format name ('XML', 'YAML', 'JSON', 'CSV') + * @param string $data The source data to import from + * + * @return OrderComment The current object, for fluid interface + */ + public function importFrom($parser, $data) + { + if (!$parser instanceof AbstractParser) { + $parser = AbstractParser::getParser($parser); + } + + $this->fromArray($parser->toArray($data), TableMap::TYPE_PHPNAME); + + return $this; + } + + /** + * Export the current object properties to a string, using a given parser format + * + * $book = BookQuery::create()->findPk(9012); + * echo $book->exportTo('JSON'); + * => {"Id":9012,"Title":"Don Juan","ISBN":"0140422161","Price":12.99,"PublisherId":1234,"AuthorId":5678}'); + * + * + * @param mixed $parser A AbstractParser instance, or a format name ('XML', 'YAML', 'JSON', 'CSV') + * @param boolean $includeLazyLoadColumns (optional) Whether to include lazy load(ed) columns. Defaults to TRUE. + * @return string The exported data + */ + public function exportTo($parser, $includeLazyLoadColumns = true) + { + if (!$parser instanceof AbstractParser) { + $parser = AbstractParser::getParser($parser); + } + + return $parser->fromArray($this->toArray(TableMap::TYPE_PHPNAME, $includeLazyLoadColumns, array(), true)); + } + + /** + * Clean up internal collections prior to serializing + * Avoids recursive loops that turn into segmentation faults when serializing + */ + public function __sleep() + { + $this->clearAllReferences(); + + return array_keys(get_object_vars($this)); + } + + /** + * Get the [id] column value. + * + * @return int + */ + public function getId() + { + + return $this->id; + } + + /** + * Get the [order_id] column value. + * + * @return int + */ + public function getOrderId() + { + + return $this->order_id; + } + + /** + * Get the [comment] column value. + * + * @return string + */ + public function getComment() + { + + return $this->comment; + } + + /** + * Set the value of [id] column. + * + * @param int $v new value + * @return \OrderComment\Model\OrderComment The current object (for fluent API support) + */ + public function setId($v) + { + if ($v !== null) { + $v = (int) $v; + } + + if ($this->id !== $v) { + $this->id = $v; + $this->modifiedColumns[OrderCommentTableMap::ID] = true; + } + + + return $this; + } // setId() + + /** + * Set the value of [order_id] column. + * + * @param int $v new value + * @return \OrderComment\Model\OrderComment The current object (for fluent API support) + */ + public function setOrderId($v) + { + if ($v !== null) { + $v = (int) $v; + } + + if ($this->order_id !== $v) { + $this->order_id = $v; + $this->modifiedColumns[OrderCommentTableMap::ORDER_ID] = true; + } + + if ($this->aOrder !== null && $this->aOrder->getId() !== $v) { + $this->aOrder = null; + } + + + return $this; + } // setOrderId() + + /** + * Set the value of [comment] column. + * + * @param string $v new value + * @return \OrderComment\Model\OrderComment The current object (for fluent API support) + */ + public function setComment($v) + { + if ($v !== null) { + $v = (string) $v; + } + + if ($this->comment !== $v) { + $this->comment = $v; + $this->modifiedColumns[OrderCommentTableMap::COMMENT] = true; + } + + + return $this; + } // setComment() + + /** + * Indicates whether the columns in this object are only set to default values. + * + * This method can be used in conjunction with isModified() to indicate whether an object is both + * modified _and_ has some values set which are non-default. + * + * @return boolean Whether the columns in this object are only been set with default values. + */ + public function hasOnlyDefaultValues() + { + // otherwise, everything was equal, so return TRUE + return true; + } // hasOnlyDefaultValues() + + /** + * Hydrates (populates) the object variables with values from the database resultset. + * + * An offset (0-based "start column") is specified so that objects can be hydrated + * with a subset of the columns in the resultset rows. This is needed, for example, + * for results of JOIN queries where the resultset row includes columns from two or + * more tables. + * + * @param array $row The row returned by DataFetcher->fetch(). + * @param int $startcol 0-based offset column which indicates which restultset column to start with. + * @param boolean $rehydrate Whether this object is being re-hydrated from the database. + * @param string $indexType The index type of $row. Mostly DataFetcher->getIndexType(). + One of the class type constants TableMap::TYPE_PHPNAME, TableMap::TYPE_STUDLYPHPNAME + * TableMap::TYPE_COLNAME, TableMap::TYPE_FIELDNAME, TableMap::TYPE_NUM. + * + * @return int next starting column + * @throws PropelException - Any caught Exception will be rewrapped as a PropelException. + */ + public function hydrate($row, $startcol = 0, $rehydrate = false, $indexType = TableMap::TYPE_NUM) + { + try { + + + $col = $row[TableMap::TYPE_NUM == $indexType ? 0 + $startcol : OrderCommentTableMap::translateFieldName('Id', TableMap::TYPE_PHPNAME, $indexType)]; + $this->id = (null !== $col) ? (int) $col : null; + + $col = $row[TableMap::TYPE_NUM == $indexType ? 1 + $startcol : OrderCommentTableMap::translateFieldName('OrderId', TableMap::TYPE_PHPNAME, $indexType)]; + $this->order_id = (null !== $col) ? (int) $col : null; + + $col = $row[TableMap::TYPE_NUM == $indexType ? 2 + $startcol : OrderCommentTableMap::translateFieldName('Comment', TableMap::TYPE_PHPNAME, $indexType)]; + $this->comment = (null !== $col) ? (string) $col : null; + $this->resetModified(); + + $this->setNew(false); + + if ($rehydrate) { + $this->ensureConsistency(); + } + + return $startcol + 3; // 3 = OrderCommentTableMap::NUM_HYDRATE_COLUMNS. + + } catch (Exception $e) { + throw new PropelException("Error populating \OrderComment\Model\OrderComment object", 0, $e); + } + } + + /** + * Checks and repairs the internal consistency of the object. + * + * This method is executed after an already-instantiated object is re-hydrated + * from the database. It exists to check any foreign keys to make sure that + * the objects related to the current object are correct based on foreign key. + * + * You can override this method in the stub class, but you should always invoke + * the base method from the overridden method (i.e. parent::ensureConsistency()), + * in case your model changes. + * + * @throws PropelException + */ + public function ensureConsistency() + { + if ($this->aOrder !== null && $this->order_id !== $this->aOrder->getId()) { + $this->aOrder = null; + } + } // ensureConsistency + + /** + * Reloads this object from datastore based on primary key and (optionally) resets all associated objects. + * + * This will only work if the object has been saved and has a valid primary key set. + * + * @param boolean $deep (optional) Whether to also de-associated any related objects. + * @param ConnectionInterface $con (optional) The ConnectionInterface connection to use. + * @return void + * @throws PropelException - if this object is deleted, unsaved or doesn't have pk match in db + */ + public function reload($deep = false, ConnectionInterface $con = null) + { + if ($this->isDeleted()) { + throw new PropelException("Cannot reload a deleted object."); + } + + if ($this->isNew()) { + throw new PropelException("Cannot reload an unsaved object."); + } + + if ($con === null) { + $con = Propel::getServiceContainer()->getReadConnection(OrderCommentTableMap::DATABASE_NAME); + } + + // We don't need to alter the object instance pool; we're just modifying this instance + // already in the pool. + + $dataFetcher = ChildOrderCommentQuery::create(null, $this->buildPkeyCriteria())->setFormatter(ModelCriteria::FORMAT_STATEMENT)->find($con); + $row = $dataFetcher->fetch(); + $dataFetcher->close(); + if (!$row) { + throw new PropelException('Cannot find matching row in the database to reload object values.'); + } + $this->hydrate($row, 0, true, $dataFetcher->getIndexType()); // rehydrate + + if ($deep) { // also de-associate any related objects? + + $this->aOrder = null; + } // if (deep) + } + + /** + * Removes this object from datastore and sets delete attribute. + * + * @param ConnectionInterface $con + * @return void + * @throws PropelException + * @see OrderComment::setDeleted() + * @see OrderComment::isDeleted() + */ + public function delete(ConnectionInterface $con = null) + { + if ($this->isDeleted()) { + throw new PropelException("This object has already been deleted."); + } + + if ($con === null) { + $con = Propel::getServiceContainer()->getWriteConnection(OrderCommentTableMap::DATABASE_NAME); + } + + $con->beginTransaction(); + try { + $deleteQuery = ChildOrderCommentQuery::create() + ->filterByPrimaryKey($this->getPrimaryKey()); + $ret = $this->preDelete($con); + if ($ret) { + $deleteQuery->delete($con); + $this->postDelete($con); + $con->commit(); + $this->setDeleted(true); + } else { + $con->commit(); + } + } catch (Exception $e) { + $con->rollBack(); + throw $e; + } + } + + /** + * Persists this object to the database. + * + * If the object is new, it inserts it; otherwise an update is performed. + * All modified related objects will also be persisted in the doSave() + * method. This method wraps all precipitate database operations in a + * single transaction. + * + * @param ConnectionInterface $con + * @return int The number of rows affected by this insert/update and any referring fk objects' save() operations. + * @throws PropelException + * @see doSave() + */ + public function save(ConnectionInterface $con = null) + { + if ($this->isDeleted()) { + throw new PropelException("You cannot save an object that has been deleted."); + } + + if ($con === null) { + $con = Propel::getServiceContainer()->getWriteConnection(OrderCommentTableMap::DATABASE_NAME); + } + + $con->beginTransaction(); + $isInsert = $this->isNew(); + try { + $ret = $this->preSave($con); + if ($isInsert) { + $ret = $ret && $this->preInsert($con); + } else { + $ret = $ret && $this->preUpdate($con); + } + if ($ret) { + $affectedRows = $this->doSave($con); + if ($isInsert) { + $this->postInsert($con); + } else { + $this->postUpdate($con); + } + $this->postSave($con); + OrderCommentTableMap::addInstanceToPool($this); + } else { + $affectedRows = 0; + } + $con->commit(); + + return $affectedRows; + } catch (Exception $e) { + $con->rollBack(); + throw $e; + } + } + + /** + * Performs the work of inserting or updating the row in the database. + * + * If the object is new, it inserts it; otherwise an update is performed. + * All related objects are also updated in this method. + * + * @param ConnectionInterface $con + * @return int The number of rows affected by this insert/update and any referring fk objects' save() operations. + * @throws PropelException + * @see save() + */ + protected function doSave(ConnectionInterface $con) + { + $affectedRows = 0; // initialize var to track total num of affected rows + if (!$this->alreadyInSave) { + $this->alreadyInSave = true; + + // We call the save method on the following object(s) if they + // were passed to this object by their corresponding set + // method. This object relates to these object(s) by a + // foreign key reference. + + if ($this->aOrder !== null) { + if ($this->aOrder->isModified() || $this->aOrder->isNew()) { + $affectedRows += $this->aOrder->save($con); + } + $this->setOrder($this->aOrder); + } + + if ($this->isNew() || $this->isModified()) { + // persist changes + if ($this->isNew()) { + $this->doInsert($con); + } else { + $this->doUpdate($con); + } + $affectedRows += 1; + $this->resetModified(); + } + + $this->alreadyInSave = false; + + } + + return $affectedRows; + } // doSave() + + /** + * Insert the row in the database. + * + * @param ConnectionInterface $con + * + * @throws PropelException + * @see doSave() + */ + protected function doInsert(ConnectionInterface $con) + { + $modifiedColumns = array(); + $index = 0; + + $this->modifiedColumns[OrderCommentTableMap::ID] = true; + if (null !== $this->id) { + throw new PropelException('Cannot insert a value for auto-increment primary key (' . OrderCommentTableMap::ID . ')'); + } + + // check the columns in natural order for more readable SQL queries + if ($this->isColumnModified(OrderCommentTableMap::ID)) { + $modifiedColumns[':p' . $index++] = 'ID'; + } + if ($this->isColumnModified(OrderCommentTableMap::ORDER_ID)) { + $modifiedColumns[':p' . $index++] = 'ORDER_ID'; + } + if ($this->isColumnModified(OrderCommentTableMap::COMMENT)) { + $modifiedColumns[':p' . $index++] = 'COMMENT'; + } + + $sql = sprintf( + 'INSERT INTO order_comment (%s) VALUES (%s)', + implode(', ', $modifiedColumns), + implode(', ', array_keys($modifiedColumns)) + ); + + try { + $stmt = $con->prepare($sql); + foreach ($modifiedColumns as $identifier => $columnName) { + switch ($columnName) { + case 'ID': + $stmt->bindValue($identifier, $this->id, PDO::PARAM_INT); + break; + case 'ORDER_ID': + $stmt->bindValue($identifier, $this->order_id, PDO::PARAM_INT); + break; + case 'COMMENT': + $stmt->bindValue($identifier, $this->comment, PDO::PARAM_STR); + break; + } + } + $stmt->execute(); + } catch (Exception $e) { + Propel::log($e->getMessage(), Propel::LOG_ERR); + throw new PropelException(sprintf('Unable to execute INSERT statement [%s]', $sql), 0, $e); + } + + try { + $pk = $con->lastInsertId(); + } catch (Exception $e) { + throw new PropelException('Unable to get autoincrement id.', 0, $e); + } + $this->setId($pk); + + $this->setNew(false); + } + + /** + * Update the row in the database. + * + * @param ConnectionInterface $con + * + * @return Integer Number of updated rows + * @see doSave() + */ + protected function doUpdate(ConnectionInterface $con) + { + $selectCriteria = $this->buildPkeyCriteria(); + $valuesCriteria = $this->buildCriteria(); + + return $selectCriteria->doUpdate($valuesCriteria, $con); + } + + /** + * Retrieves a field from the object by name passed in as a string. + * + * @param string $name name + * @param string $type The type of fieldname the $name is of: + * one of the class type constants TableMap::TYPE_PHPNAME, TableMap::TYPE_STUDLYPHPNAME + * TableMap::TYPE_COLNAME, TableMap::TYPE_FIELDNAME, TableMap::TYPE_NUM. + * Defaults to TableMap::TYPE_PHPNAME. + * @return mixed Value of field. + */ + public function getByName($name, $type = TableMap::TYPE_PHPNAME) + { + $pos = OrderCommentTableMap::translateFieldName($name, $type, TableMap::TYPE_NUM); + $field = $this->getByPosition($pos); + + return $field; + } + + /** + * Retrieves a field from the object by Position as specified in the xml schema. + * Zero-based. + * + * @param int $pos position in xml schema + * @return mixed Value of field at $pos + */ + public function getByPosition($pos) + { + switch ($pos) { + case 0: + return $this->getId(); + break; + case 1: + return $this->getOrderId(); + break; + case 2: + return $this->getComment(); + break; + default: + return null; + break; + } // switch() + } + + /** + * Exports the object as an array. + * + * You can specify the key type of the array by passing one of the class + * type constants. + * + * @param string $keyType (optional) One of the class type constants TableMap::TYPE_PHPNAME, TableMap::TYPE_STUDLYPHPNAME, + * TableMap::TYPE_COLNAME, TableMap::TYPE_FIELDNAME, TableMap::TYPE_NUM. + * Defaults to TableMap::TYPE_PHPNAME. + * @param boolean $includeLazyLoadColumns (optional) Whether to include lazy loaded columns. Defaults to TRUE. + * @param array $alreadyDumpedObjects List of objects to skip to avoid recursion + * @param boolean $includeForeignObjects (optional) Whether to include hydrated related objects. Default to FALSE. + * + * @return array an associative array containing the field names (as keys) and field values + */ + public function toArray($keyType = TableMap::TYPE_PHPNAME, $includeLazyLoadColumns = true, $alreadyDumpedObjects = array(), $includeForeignObjects = false) + { + if (isset($alreadyDumpedObjects['OrderComment'][$this->getPrimaryKey()])) { + return '*RECURSION*'; + } + $alreadyDumpedObjects['OrderComment'][$this->getPrimaryKey()] = true; + $keys = OrderCommentTableMap::getFieldNames($keyType); + $result = array( + $keys[0] => $this->getId(), + $keys[1] => $this->getOrderId(), + $keys[2] => $this->getComment(), + ); + $virtualColumns = $this->virtualColumns; + foreach ($virtualColumns as $key => $virtualColumn) { + $result[$key] = $virtualColumn; + } + + if ($includeForeignObjects) { + if (null !== $this->aOrder) { + $result['Order'] = $this->aOrder->toArray($keyType, $includeLazyLoadColumns, $alreadyDumpedObjects, true); + } + } + + return $result; + } + + /** + * Sets a field from the object by name passed in as a string. + * + * @param string $name + * @param mixed $value field value + * @param string $type The type of fieldname the $name is of: + * one of the class type constants TableMap::TYPE_PHPNAME, TableMap::TYPE_STUDLYPHPNAME + * TableMap::TYPE_COLNAME, TableMap::TYPE_FIELDNAME, TableMap::TYPE_NUM. + * Defaults to TableMap::TYPE_PHPNAME. + * @return void + */ + public function setByName($name, $value, $type = TableMap::TYPE_PHPNAME) + { + $pos = OrderCommentTableMap::translateFieldName($name, $type, TableMap::TYPE_NUM); + + return $this->setByPosition($pos, $value); + } + + /** + * Sets a field from the object by Position as specified in the xml schema. + * Zero-based. + * + * @param int $pos position in xml schema + * @param mixed $value field value + * @return void + */ + public function setByPosition($pos, $value) + { + switch ($pos) { + case 0: + $this->setId($value); + break; + case 1: + $this->setOrderId($value); + break; + case 2: + $this->setComment($value); + break; + } // switch() + } + + /** + * Populates the object using an array. + * + * This is particularly useful when populating an object from one of the + * request arrays (e.g. $_POST). This method goes through the column + * names, checking to see whether a matching key exists in populated + * array. If so the setByName() method is called for that column. + * + * You can specify the key type of the array by additionally passing one + * of the class type constants TableMap::TYPE_PHPNAME, TableMap::TYPE_STUDLYPHPNAME, + * TableMap::TYPE_COLNAME, TableMap::TYPE_FIELDNAME, TableMap::TYPE_NUM. + * The default key type is the column's TableMap::TYPE_PHPNAME. + * + * @param array $arr An array to populate the object from. + * @param string $keyType The type of keys the array uses. + * @return void + */ + public function fromArray($arr, $keyType = TableMap::TYPE_PHPNAME) + { + $keys = OrderCommentTableMap::getFieldNames($keyType); + + if (array_key_exists($keys[0], $arr)) $this->setId($arr[$keys[0]]); + if (array_key_exists($keys[1], $arr)) $this->setOrderId($arr[$keys[1]]); + if (array_key_exists($keys[2], $arr)) $this->setComment($arr[$keys[2]]); + } + + /** + * Build a Criteria object containing the values of all modified columns in this object. + * + * @return Criteria The Criteria object containing all modified values. + */ + public function buildCriteria() + { + $criteria = new Criteria(OrderCommentTableMap::DATABASE_NAME); + + if ($this->isColumnModified(OrderCommentTableMap::ID)) $criteria->add(OrderCommentTableMap::ID, $this->id); + if ($this->isColumnModified(OrderCommentTableMap::ORDER_ID)) $criteria->add(OrderCommentTableMap::ORDER_ID, $this->order_id); + if ($this->isColumnModified(OrderCommentTableMap::COMMENT)) $criteria->add(OrderCommentTableMap::COMMENT, $this->comment); + + return $criteria; + } + + /** + * Builds a Criteria object containing the primary key for this object. + * + * Unlike buildCriteria() this method includes the primary key values regardless + * of whether or not they have been modified. + * + * @return Criteria The Criteria object containing value(s) for primary key(s). + */ + public function buildPkeyCriteria() + { + $criteria = new Criteria(OrderCommentTableMap::DATABASE_NAME); + $criteria->add(OrderCommentTableMap::ID, $this->id); + + return $criteria; + } + + /** + * Returns the primary key for this object (row). + * @return int + */ + public function getPrimaryKey() + { + return $this->getId(); + } + + /** + * Generic method to set the primary key (id column). + * + * @param int $key Primary key. + * @return void + */ + public function setPrimaryKey($key) + { + $this->setId($key); + } + + /** + * Returns true if the primary key for this object is null. + * @return boolean + */ + public function isPrimaryKeyNull() + { + + return null === $this->getId(); + } + + /** + * Sets contents of passed object to values from current object. + * + * If desired, this method can also make copies of all associated (fkey referrers) + * objects. + * + * @param object $copyObj An object of \OrderComment\Model\OrderComment (or compatible) type. + * @param boolean $deepCopy Whether to also copy all rows that refer (by fkey) to the current row. + * @param boolean $makeNew Whether to reset autoincrement PKs and make the object new. + * @throws PropelException + */ + public function copyInto($copyObj, $deepCopy = false, $makeNew = true) + { + $copyObj->setOrderId($this->getOrderId()); + $copyObj->setComment($this->getComment()); + if ($makeNew) { + $copyObj->setNew(true); + $copyObj->setId(NULL); // this is a auto-increment column, so set to default value + } + } + + /** + * Makes a copy of this object that will be inserted as a new row in table when saved. + * It creates a new object filling in the simple attributes, but skipping any primary + * keys that are defined for the table. + * + * If desired, this method can also make copies of all associated (fkey referrers) + * objects. + * + * @param boolean $deepCopy Whether to also copy all rows that refer (by fkey) to the current row. + * @return \OrderComment\Model\OrderComment Clone of current object. + * @throws PropelException + */ + public function copy($deepCopy = false) + { + // we use get_class(), because this might be a subclass + $clazz = get_class($this); + $copyObj = new $clazz(); + $this->copyInto($copyObj, $deepCopy); + + return $copyObj; + } + + /** + * Declares an association between this object and a ChildOrder object. + * + * @param ChildOrder $v + * @return \OrderComment\Model\OrderComment The current object (for fluent API support) + * @throws PropelException + */ + public function setOrder(ChildOrder $v = null) + { + if ($v === null) { + $this->setOrderId(NULL); + } else { + $this->setOrderId($v->getId()); + } + + $this->aOrder = $v; + + // Add binding for other direction of this n:n relationship. + // If this object has already been added to the ChildOrder object, it will not be re-added. + if ($v !== null) { + $v->addOrderComment($this); + } + + + return $this; + } + + + /** + * Get the associated ChildOrder object + * + * @param ConnectionInterface $con Optional Connection object. + * @return ChildOrder The associated ChildOrder object. + * @throws PropelException + */ + public function getOrder(ConnectionInterface $con = null) + { + if ($this->aOrder === null && ($this->order_id !== null)) { + $this->aOrder = OrderQuery::create()->findPk($this->order_id, $con); + /* The following can be used additionally to + guarantee the related object contains a reference + to this object. This level of coupling may, however, be + undesirable since it could result in an only partially populated collection + in the referenced object. + $this->aOrder->addOrderComments($this); + */ + } + + return $this->aOrder; + } + + /** + * Clears the current object and sets all attributes to their default values + */ + public function clear() + { + $this->id = null; + $this->order_id = null; + $this->comment = null; + $this->alreadyInSave = false; + $this->clearAllReferences(); + $this->resetModified(); + $this->setNew(true); + $this->setDeleted(false); + } + + /** + * Resets all references to other model objects or collections of model objects. + * + * This method is a user-space workaround for PHP's inability to garbage collect + * objects with circular references (even in PHP 5.3). This is currently necessary + * when using Propel in certain daemon or large-volume/high-memory operations. + * + * @param boolean $deep Whether to also clear the references on all referrer objects. + */ + public function clearAllReferences($deep = false) + { + if ($deep) { + } // if ($deep) + + $this->aOrder = null; + } + + /** + * Return the string representation of this object + * + * @return string + */ + public function __toString() + { + return (string) $this->exportTo(OrderCommentTableMap::DEFAULT_STRING_FORMAT); + } + + /** + * Code to be run before persisting the object + * @param ConnectionInterface $con + * @return boolean + */ + public function preSave(ConnectionInterface $con = null) + { + return true; + } + + /** + * Code to be run after persisting the object + * @param ConnectionInterface $con + */ + public function postSave(ConnectionInterface $con = null) + { + + } + + /** + * Code to be run before inserting to database + * @param ConnectionInterface $con + * @return boolean + */ + public function preInsert(ConnectionInterface $con = null) + { + return true; + } + + /** + * Code to be run after inserting to database + * @param ConnectionInterface $con + */ + public function postInsert(ConnectionInterface $con = null) + { + + } + + /** + * Code to be run before updating the object in database + * @param ConnectionInterface $con + * @return boolean + */ + public function preUpdate(ConnectionInterface $con = null) + { + return true; + } + + /** + * Code to be run after updating the object in database + * @param ConnectionInterface $con + */ + public function postUpdate(ConnectionInterface $con = null) + { + + } + + /** + * Code to be run before deleting the object in database + * @param ConnectionInterface $con + * @return boolean + */ + public function preDelete(ConnectionInterface $con = null) + { + return true; + } + + /** + * Code to be run after deleting the object in database + * @param ConnectionInterface $con + */ + public function postDelete(ConnectionInterface $con = null) + { + + } + + + /** + * Derived method to catches calls to undefined methods. + * + * Provides magic import/export method support (fromXML()/toXML(), fromYAML()/toYAML(), etc.). + * Allows to define default __call() behavior if you overwrite __call() + * + * @param string $name + * @param mixed $params + * + * @return array|string + */ + public function __call($name, $params) + { + if (0 === strpos($name, 'get')) { + $virtualColumn = substr($name, 3); + if ($this->hasVirtualColumn($virtualColumn)) { + return $this->getVirtualColumn($virtualColumn); + } + + $virtualColumn = lcfirst($virtualColumn); + if ($this->hasVirtualColumn($virtualColumn)) { + return $this->getVirtualColumn($virtualColumn); + } + } + + if (0 === strpos($name, 'from')) { + $format = substr($name, 4); + + return $this->importFrom($format, reset($params)); + } + + if (0 === strpos($name, 'to')) { + $format = substr($name, 2); + $includeLazyLoadColumns = isset($params[0]) ? $params[0] : true; + + return $this->exportTo($format, $includeLazyLoadColumns); + } + + throw new BadMethodCallException(sprintf('Call to undefined method: %s.', $name)); + } + +} diff --git a/local/modules/OrderComment/Model/Base/OrderCommentQuery.php b/local/modules/OrderComment/Model/Base/OrderCommentQuery.php new file mode 100644 index 00000000..dfb0a7bc --- /dev/null +++ b/local/modules/OrderComment/Model/Base/OrderCommentQuery.php @@ -0,0 +1,507 @@ +setModelAlias($modelAlias); + } + if ($criteria instanceof Criteria) { + $query->mergeWith($criteria); + } + + return $query; + } + + /** + * Find object by primary key. + * Propel uses the instance pool to skip the database if the object exists. + * Go fast if the query is untouched. + * + * + * $obj = $c->findPk(12, $con); + * + * + * @param mixed $key Primary key to use for the query + * @param ConnectionInterface $con an optional connection object + * + * @return ChildOrderComment|array|mixed the result, formatted by the current formatter + */ + public function findPk($key, $con = null) + { + if ($key === null) { + return null; + } + if ((null !== ($obj = OrderCommentTableMap::getInstanceFromPool((string) $key))) && !$this->formatter) { + // the object is already in the instance pool + return $obj; + } + if ($con === null) { + $con = Propel::getServiceContainer()->getReadConnection(OrderCommentTableMap::DATABASE_NAME); + } + $this->basePreSelect($con); + if ($this->formatter || $this->modelAlias || $this->with || $this->select + || $this->selectColumns || $this->asColumns || $this->selectModifiers + || $this->map || $this->having || $this->joins) { + return $this->findPkComplex($key, $con); + } else { + return $this->findPkSimple($key, $con); + } + } + + /** + * Find object by primary key using raw SQL to go fast. + * Bypass doSelect() and the object formatter by using generated code. + * + * @param mixed $key Primary key to use for the query + * @param ConnectionInterface $con A connection object + * + * @return ChildOrderComment A model object, or null if the key is not found + */ + protected function findPkSimple($key, $con) + { + $sql = 'SELECT ID, ORDER_ID, COMMENT FROM order_comment WHERE ID = :p0'; + try { + $stmt = $con->prepare($sql); + $stmt->bindValue(':p0', $key, PDO::PARAM_INT); + $stmt->execute(); + } catch (Exception $e) { + Propel::log($e->getMessage(), Propel::LOG_ERR); + throw new PropelException(sprintf('Unable to execute SELECT statement [%s]', $sql), 0, $e); + } + $obj = null; + if ($row = $stmt->fetch(\PDO::FETCH_NUM)) { + $obj = new ChildOrderComment(); + $obj->hydrate($row); + OrderCommentTableMap::addInstanceToPool($obj, (string) $key); + } + $stmt->closeCursor(); + + return $obj; + } + + /** + * Find object by primary key. + * + * @param mixed $key Primary key to use for the query + * @param ConnectionInterface $con A connection object + * + * @return ChildOrderComment|array|mixed the result, formatted by the current formatter + */ + protected function findPkComplex($key, $con) + { + // As the query uses a PK condition, no limit(1) is necessary. + $criteria = $this->isKeepQuery() ? clone $this : $this; + $dataFetcher = $criteria + ->filterByPrimaryKey($key) + ->doSelect($con); + + return $criteria->getFormatter()->init($criteria)->formatOne($dataFetcher); + } + + /** + * Find objects by primary key + * + * $objs = $c->findPks(array(12, 56, 832), $con); + * + * @param array $keys Primary keys to use for the query + * @param ConnectionInterface $con an optional connection object + * + * @return ObjectCollection|array|mixed the list of results, formatted by the current formatter + */ + public function findPks($keys, $con = null) + { + if (null === $con) { + $con = Propel::getServiceContainer()->getReadConnection($this->getDbName()); + } + $this->basePreSelect($con); + $criteria = $this->isKeepQuery() ? clone $this : $this; + $dataFetcher = $criteria + ->filterByPrimaryKeys($keys) + ->doSelect($con); + + return $criteria->getFormatter()->init($criteria)->format($dataFetcher); + } + + /** + * Filter the query by primary key + * + * @param mixed $key Primary key to use for the query + * + * @return ChildOrderCommentQuery The current query, for fluid interface + */ + public function filterByPrimaryKey($key) + { + + return $this->addUsingAlias(OrderCommentTableMap::ID, $key, Criteria::EQUAL); + } + + /** + * Filter the query by a list of primary keys + * + * @param array $keys The list of primary key to use for the query + * + * @return ChildOrderCommentQuery The current query, for fluid interface + */ + public function filterByPrimaryKeys($keys) + { + + return $this->addUsingAlias(OrderCommentTableMap::ID, $keys, Criteria::IN); + } + + /** + * Filter the query on the id column + * + * Example usage: + * + * $query->filterById(1234); // WHERE id = 1234 + * $query->filterById(array(12, 34)); // WHERE id IN (12, 34) + * $query->filterById(array('min' => 12)); // WHERE id > 12 + * + * + * @param mixed $id The value to use as filter. + * Use scalar values for equality. + * Use array values for in_array() equivalent. + * Use associative array('min' => $minValue, 'max' => $maxValue) for intervals. + * @param string $comparison Operator to use for the column comparison, defaults to Criteria::EQUAL + * + * @return ChildOrderCommentQuery The current query, for fluid interface + */ + public function filterById($id = null, $comparison = null) + { + if (is_array($id)) { + $useMinMax = false; + if (isset($id['min'])) { + $this->addUsingAlias(OrderCommentTableMap::ID, $id['min'], Criteria::GREATER_EQUAL); + $useMinMax = true; + } + if (isset($id['max'])) { + $this->addUsingAlias(OrderCommentTableMap::ID, $id['max'], Criteria::LESS_EQUAL); + $useMinMax = true; + } + if ($useMinMax) { + return $this; + } + if (null === $comparison) { + $comparison = Criteria::IN; + } + } + + return $this->addUsingAlias(OrderCommentTableMap::ID, $id, $comparison); + } + + /** + * Filter the query on the order_id column + * + * Example usage: + * + * $query->filterByOrderId(1234); // WHERE order_id = 1234 + * $query->filterByOrderId(array(12, 34)); // WHERE order_id IN (12, 34) + * $query->filterByOrderId(array('min' => 12)); // WHERE order_id > 12 + * + * + * @see filterByOrder() + * + * @param mixed $orderId The value to use as filter. + * Use scalar values for equality. + * Use array values for in_array() equivalent. + * Use associative array('min' => $minValue, 'max' => $maxValue) for intervals. + * @param string $comparison Operator to use for the column comparison, defaults to Criteria::EQUAL + * + * @return ChildOrderCommentQuery The current query, for fluid interface + */ + public function filterByOrderId($orderId = null, $comparison = null) + { + if (is_array($orderId)) { + $useMinMax = false; + if (isset($orderId['min'])) { + $this->addUsingAlias(OrderCommentTableMap::ORDER_ID, $orderId['min'], Criteria::GREATER_EQUAL); + $useMinMax = true; + } + if (isset($orderId['max'])) { + $this->addUsingAlias(OrderCommentTableMap::ORDER_ID, $orderId['max'], Criteria::LESS_EQUAL); + $useMinMax = true; + } + if ($useMinMax) { + return $this; + } + if (null === $comparison) { + $comparison = Criteria::IN; + } + } + + return $this->addUsingAlias(OrderCommentTableMap::ORDER_ID, $orderId, $comparison); + } + + /** + * Filter the query on the comment column + * + * Example usage: + * + * $query->filterByComment('fooValue'); // WHERE comment = 'fooValue' + * $query->filterByComment('%fooValue%'); // WHERE comment LIKE '%fooValue%' + * + * + * @param string $comment The value to use as filter. + * Accepts wildcards (* and % trigger a LIKE) + * @param string $comparison Operator to use for the column comparison, defaults to Criteria::EQUAL + * + * @return ChildOrderCommentQuery The current query, for fluid interface + */ + public function filterByComment($comment = null, $comparison = null) + { + if (null === $comparison) { + if (is_array($comment)) { + $comparison = Criteria::IN; + } elseif (preg_match('/[\%\*]/', $comment)) { + $comment = str_replace('*', '%', $comment); + $comparison = Criteria::LIKE; + } + } + + return $this->addUsingAlias(OrderCommentTableMap::COMMENT, $comment, $comparison); + } + + /** + * Filter the query by a related \OrderComment\Model\Thelia\Model\Order object + * + * @param \OrderComment\Model\Thelia\Model\Order|ObjectCollection $order The related object(s) to use as filter + * @param string $comparison Operator to use for the column comparison, defaults to Criteria::EQUAL + * + * @return ChildOrderCommentQuery The current query, for fluid interface + */ + public function filterByOrder($order, $comparison = null) + { + if ($order instanceof \OrderComment\Model\Thelia\Model\Order) { + return $this + ->addUsingAlias(OrderCommentTableMap::ORDER_ID, $order->getId(), $comparison); + } elseif ($order instanceof ObjectCollection) { + if (null === $comparison) { + $comparison = Criteria::IN; + } + + return $this + ->addUsingAlias(OrderCommentTableMap::ORDER_ID, $order->toKeyValue('PrimaryKey', 'Id'), $comparison); + } else { + throw new PropelException('filterByOrder() only accepts arguments of type \OrderComment\Model\Thelia\Model\Order or Collection'); + } + } + + /** + * Adds a JOIN clause to the query using the Order relation + * + * @param string $relationAlias optional alias for the relation + * @param string $joinType Accepted values are null, 'left join', 'right join', 'inner join' + * + * @return ChildOrderCommentQuery The current query, for fluid interface + */ + public function joinOrder($relationAlias = null, $joinType = Criteria::INNER_JOIN) + { + $tableMap = $this->getTableMap(); + $relationMap = $tableMap->getRelation('Order'); + + // create a ModelJoin object for this join + $join = new ModelJoin(); + $join->setJoinType($joinType); + $join->setRelationMap($relationMap, $this->useAliasInSQL ? $this->getModelAlias() : null, $relationAlias); + if ($previousJoin = $this->getPreviousJoin()) { + $join->setPreviousJoin($previousJoin); + } + + // add the ModelJoin to the current object + if ($relationAlias) { + $this->addAlias($relationAlias, $relationMap->getRightTable()->getName()); + $this->addJoinObject($join, $relationAlias); + } else { + $this->addJoinObject($join, 'Order'); + } + + return $this; + } + + /** + * Use the Order relation Order object + * + * @see useQuery() + * + * @param string $relationAlias optional alias for the relation, + * to be used as main alias in the secondary query + * @param string $joinType Accepted values are null, 'left join', 'right join', 'inner join' + * + * @return \OrderComment\Model\Thelia\Model\OrderQuery A secondary query class using the current class as primary query + */ + public function useOrderQuery($relationAlias = null, $joinType = Criteria::INNER_JOIN) + { + return $this + ->joinOrder($relationAlias, $joinType) + ->useQuery($relationAlias ? $relationAlias : 'Order', '\OrderComment\Model\Thelia\Model\OrderQuery'); + } + + /** + * Exclude object from result + * + * @param ChildOrderComment $orderComment Object to remove from the list of results + * + * @return ChildOrderCommentQuery The current query, for fluid interface + */ + public function prune($orderComment = null) + { + if ($orderComment) { + $this->addUsingAlias(OrderCommentTableMap::ID, $orderComment->getId(), Criteria::NOT_EQUAL); + } + + return $this; + } + + /** + * Deletes all rows from the order_comment table. + * + * @param ConnectionInterface $con the connection to use + * @return int The number of affected rows (if supported by underlying database driver). + */ + public function doDeleteAll(ConnectionInterface $con = null) + { + if (null === $con) { + $con = Propel::getServiceContainer()->getWriteConnection(OrderCommentTableMap::DATABASE_NAME); + } + $affectedRows = 0; // initialize var to track total num of affected rows + try { + // use transaction because $criteria could contain info + // for more than one table or we could emulating ON DELETE CASCADE, etc. + $con->beginTransaction(); + $affectedRows += parent::doDeleteAll($con); + // Because this db requires some delete cascade/set null emulation, we have to + // clear the cached instance *after* the emulation has happened (since + // instances get re-added by the select statement contained therein). + OrderCommentTableMap::clearInstancePool(); + OrderCommentTableMap::clearRelatedInstancePool(); + + $con->commit(); + } catch (PropelException $e) { + $con->rollBack(); + throw $e; + } + + return $affectedRows; + } + + /** + * Performs a DELETE on the database, given a ChildOrderComment or Criteria object OR a primary key value. + * + * @param mixed $values Criteria or ChildOrderComment object or primary key or array of primary keys + * which is used to create the DELETE statement + * @param ConnectionInterface $con the connection to use + * @return int The number of affected rows (if supported by underlying database driver). This includes CASCADE-related rows + * if supported by native driver or if emulated using Propel. + * @throws PropelException Any exceptions caught during processing will be + * rethrown wrapped into a PropelException. + */ + public function delete(ConnectionInterface $con = null) + { + if (null === $con) { + $con = Propel::getServiceContainer()->getWriteConnection(OrderCommentTableMap::DATABASE_NAME); + } + + $criteria = $this; + + // Set the correct dbName + $criteria->setDbName(OrderCommentTableMap::DATABASE_NAME); + + $affectedRows = 0; // initialize var to track total num of affected rows + + try { + // use transaction because $criteria could contain info + // for more than one table or we could emulating ON DELETE CASCADE, etc. + $con->beginTransaction(); + + + OrderCommentTableMap::removeInstanceFromPool($criteria); + + $affectedRows += ModelCriteria::delete($con); + OrderCommentTableMap::clearRelatedInstancePool(); + $con->commit(); + + return $affectedRows; + } catch (PropelException $e) { + $con->rollBack(); + throw $e; + } + } + +} // OrderCommentQuery diff --git a/local/modules/OrderComment/Model/Map/OrderCommentTableMap.php b/local/modules/OrderComment/Model/Map/OrderCommentTableMap.php new file mode 100644 index 00000000..b2b4bcf8 --- /dev/null +++ b/local/modules/OrderComment/Model/Map/OrderCommentTableMap.php @@ -0,0 +1,419 @@ + array('Id', 'OrderId', 'Comment', ), + self::TYPE_STUDLYPHPNAME => array('id', 'orderId', 'comment', ), + self::TYPE_COLNAME => array(OrderCommentTableMap::ID, OrderCommentTableMap::ORDER_ID, OrderCommentTableMap::COMMENT, ), + self::TYPE_RAW_COLNAME => array('ID', 'ORDER_ID', 'COMMENT', ), + self::TYPE_FIELDNAME => array('id', 'order_id', 'comment', ), + self::TYPE_NUM => array(0, 1, 2, ) + ); + + /** + * holds an array of keys for quick access to the fieldnames array + * + * first dimension keys are the type constants + * e.g. self::$fieldKeys[self::TYPE_PHPNAME]['Id'] = 0 + */ + protected static $fieldKeys = array ( + self::TYPE_PHPNAME => array('Id' => 0, 'OrderId' => 1, 'Comment' => 2, ), + self::TYPE_STUDLYPHPNAME => array('id' => 0, 'orderId' => 1, 'comment' => 2, ), + self::TYPE_COLNAME => array(OrderCommentTableMap::ID => 0, OrderCommentTableMap::ORDER_ID => 1, OrderCommentTableMap::COMMENT => 2, ), + self::TYPE_RAW_COLNAME => array('ID' => 0, 'ORDER_ID' => 1, 'COMMENT' => 2, ), + self::TYPE_FIELDNAME => array('id' => 0, 'order_id' => 1, 'comment' => 2, ), + self::TYPE_NUM => array(0, 1, 2, ) + ); + + /** + * Initialize the table attributes and columns + * Relations are not initialized by this method since they are lazy loaded + * + * @return void + * @throws PropelException + */ + public function initialize() + { + // attributes + $this->setName('order_comment'); + $this->setPhpName('OrderComment'); + $this->setClassName('\\OrderComment\\Model\\OrderComment'); + $this->setPackage('OrderComment.Model'); + $this->setUseIdGenerator(true); + // columns + $this->addPrimaryKey('ID', 'Id', 'INTEGER', true, null, null); + $this->addForeignKey('ORDER_ID', 'OrderId', 'INTEGER', 'order', 'ID', true, null, null); + $this->addColumn('COMMENT', 'Comment', 'LONGVARCHAR', true, null, null); + } // initialize() + + /** + * Build the RelationMap objects for this table relationships + */ + public function buildRelations() + { + $this->addRelation('Order', '\\OrderComment\\Model\\Thelia\\Model\\Order', RelationMap::MANY_TO_ONE, array('order_id' => 'id', ), 'CASCADE', 'RESTRICT'); + } // buildRelations() + + /** + * Retrieves a string version of the primary key from the DB resultset row that can be used to uniquely identify a row in this table. + * + * For tables with a single-column primary key, that simple pkey value will be returned. For tables with + * a multi-column primary key, a serialize()d version of the primary key will be returned. + * + * @param array $row resultset row. + * @param int $offset The 0-based offset for reading from the resultset row. + * @param string $indexType One of the class type constants TableMap::TYPE_PHPNAME, TableMap::TYPE_STUDLYPHPNAME + * TableMap::TYPE_COLNAME, TableMap::TYPE_FIELDNAME, TableMap::TYPE_NUM + */ + public static function getPrimaryKeyHashFromRow($row, $offset = 0, $indexType = TableMap::TYPE_NUM) + { + // If the PK cannot be derived from the row, return NULL. + if ($row[TableMap::TYPE_NUM == $indexType ? 0 + $offset : static::translateFieldName('Id', TableMap::TYPE_PHPNAME, $indexType)] === null) { + return null; + } + + return (string) $row[TableMap::TYPE_NUM == $indexType ? 0 + $offset : static::translateFieldName('Id', TableMap::TYPE_PHPNAME, $indexType)]; + } + + /** + * Retrieves the primary key from the DB resultset row + * For tables with a single-column primary key, that simple pkey value will be returned. For tables with + * a multi-column primary key, an array of the primary key columns will be returned. + * + * @param array $row resultset row. + * @param int $offset The 0-based offset for reading from the resultset row. + * @param string $indexType One of the class type constants TableMap::TYPE_PHPNAME, TableMap::TYPE_STUDLYPHPNAME + * TableMap::TYPE_COLNAME, TableMap::TYPE_FIELDNAME, TableMap::TYPE_NUM + * + * @return mixed The primary key of the row + */ + public static function getPrimaryKeyFromRow($row, $offset = 0, $indexType = TableMap::TYPE_NUM) + { + + return (int) $row[ + $indexType == TableMap::TYPE_NUM + ? 0 + $offset + : self::translateFieldName('Id', TableMap::TYPE_PHPNAME, $indexType) + ]; + } + + /** + * The class that the tableMap will make instances of. + * + * If $withPrefix is true, the returned path + * uses a dot-path notation which is translated into a path + * relative to a location on the PHP include_path. + * (e.g. path.to.MyClass -> 'path/to/MyClass.php') + * + * @param boolean $withPrefix Whether or not to return the path with the class name + * @return string path.to.ClassName + */ + public static function getOMClass($withPrefix = true) + { + return $withPrefix ? OrderCommentTableMap::CLASS_DEFAULT : OrderCommentTableMap::OM_CLASS; + } + + /** + * Populates an object of the default type or an object that inherit from the default. + * + * @param array $row row returned by DataFetcher->fetch(). + * @param int $offset The 0-based offset for reading from the resultset row. + * @param string $indexType The index type of $row. Mostly DataFetcher->getIndexType(). + One of the class type constants TableMap::TYPE_PHPNAME, TableMap::TYPE_STUDLYPHPNAME + * TableMap::TYPE_COLNAME, TableMap::TYPE_FIELDNAME, TableMap::TYPE_NUM. + * + * @throws PropelException Any exceptions caught during processing will be + * rethrown wrapped into a PropelException. + * @return array (OrderComment object, last column rank) + */ + public static function populateObject($row, $offset = 0, $indexType = TableMap::TYPE_NUM) + { + $key = OrderCommentTableMap::getPrimaryKeyHashFromRow($row, $offset, $indexType); + if (null !== ($obj = OrderCommentTableMap::getInstanceFromPool($key))) { + // We no longer rehydrate the object, since this can cause data loss. + // See http://www.propelorm.org/ticket/509 + // $obj->hydrate($row, $offset, true); // rehydrate + $col = $offset + OrderCommentTableMap::NUM_HYDRATE_COLUMNS; + } else { + $cls = OrderCommentTableMap::OM_CLASS; + $obj = new $cls(); + $col = $obj->hydrate($row, $offset, false, $indexType); + OrderCommentTableMap::addInstanceToPool($obj, $key); + } + + return array($obj, $col); + } + + /** + * The returned array will contain objects of the default type or + * objects that inherit from the default. + * + * @param DataFetcherInterface $dataFetcher + * @return array + * @throws PropelException Any exceptions caught during processing will be + * rethrown wrapped into a PropelException. + */ + public static function populateObjects(DataFetcherInterface $dataFetcher) + { + $results = array(); + + // set the class once to avoid overhead in the loop + $cls = static::getOMClass(false); + // populate the object(s) + while ($row = $dataFetcher->fetch()) { + $key = OrderCommentTableMap::getPrimaryKeyHashFromRow($row, 0, $dataFetcher->getIndexType()); + if (null !== ($obj = OrderCommentTableMap::getInstanceFromPool($key))) { + // We no longer rehydrate the object, since this can cause data loss. + // See http://www.propelorm.org/ticket/509 + // $obj->hydrate($row, 0, true); // rehydrate + $results[] = $obj; + } else { + $obj = new $cls(); + $obj->hydrate($row); + $results[] = $obj; + OrderCommentTableMap::addInstanceToPool($obj, $key); + } // if key exists + } + + return $results; + } + /** + * Add all the columns needed to create a new object. + * + * Note: any columns that were marked with lazyLoad="true" in the + * XML schema will not be added to the select list and only loaded + * on demand. + * + * @param Criteria $criteria object containing the columns to add. + * @param string $alias optional table alias + * @throws PropelException Any exceptions caught during processing will be + * rethrown wrapped into a PropelException. + */ + public static function addSelectColumns(Criteria $criteria, $alias = null) + { + if (null === $alias) { + $criteria->addSelectColumn(OrderCommentTableMap::ID); + $criteria->addSelectColumn(OrderCommentTableMap::ORDER_ID); + $criteria->addSelectColumn(OrderCommentTableMap::COMMENT); + } else { + $criteria->addSelectColumn($alias . '.ID'); + $criteria->addSelectColumn($alias . '.ORDER_ID'); + $criteria->addSelectColumn($alias . '.COMMENT'); + } + } + + /** + * Returns the TableMap related to this object. + * This method is not needed for general use but a specific application could have a need. + * @return TableMap + * @throws PropelException Any exceptions caught during processing will be + * rethrown wrapped into a PropelException. + */ + public static function getTableMap() + { + return Propel::getServiceContainer()->getDatabaseMap(OrderCommentTableMap::DATABASE_NAME)->getTable(OrderCommentTableMap::TABLE_NAME); + } + + /** + * Add a TableMap instance to the database for this tableMap class. + */ + public static function buildTableMap() + { + $dbMap = Propel::getServiceContainer()->getDatabaseMap(OrderCommentTableMap::DATABASE_NAME); + if (!$dbMap->hasTable(OrderCommentTableMap::TABLE_NAME)) { + $dbMap->addTableObject(new OrderCommentTableMap()); + } + } + + /** + * Performs a DELETE on the database, given a OrderComment or Criteria object OR a primary key value. + * + * @param mixed $values Criteria or OrderComment object or primary key or array of primary keys + * which is used to create the DELETE statement + * @param ConnectionInterface $con the connection to use + * @return int The number of affected rows (if supported by underlying database driver). This includes CASCADE-related rows + * if supported by native driver or if emulated using Propel. + * @throws PropelException Any exceptions caught during processing will be + * rethrown wrapped into a PropelException. + */ + public static function doDelete($values, ConnectionInterface $con = null) + { + if (null === $con) { + $con = Propel::getServiceContainer()->getWriteConnection(OrderCommentTableMap::DATABASE_NAME); + } + + if ($values instanceof Criteria) { + // rename for clarity + $criteria = $values; + } elseif ($values instanceof \OrderComment\Model\OrderComment) { // it's a model object + // create criteria based on pk values + $criteria = $values->buildPkeyCriteria(); + } else { // it's a primary key, or an array of pks + $criteria = new Criteria(OrderCommentTableMap::DATABASE_NAME); + $criteria->add(OrderCommentTableMap::ID, (array) $values, Criteria::IN); + } + + $query = OrderCommentQuery::create()->mergeWith($criteria); + + if ($values instanceof Criteria) { OrderCommentTableMap::clearInstancePool(); + } elseif (!is_object($values)) { // it's a primary key, or an array of pks + foreach ((array) $values as $singleval) { OrderCommentTableMap::removeInstanceFromPool($singleval); + } + } + + return $query->delete($con); + } + + /** + * Deletes all rows from the order_comment table. + * + * @param ConnectionInterface $con the connection to use + * @return int The number of affected rows (if supported by underlying database driver). + */ + public static function doDeleteAll(ConnectionInterface $con = null) + { + return OrderCommentQuery::create()->doDeleteAll($con); + } + + /** + * Performs an INSERT on the database, given a OrderComment or Criteria object. + * + * @param mixed $criteria Criteria or OrderComment object containing data that is used to create the INSERT statement. + * @param ConnectionInterface $con the ConnectionInterface connection to use + * @return mixed The new primary key. + * @throws PropelException Any exceptions caught during processing will be + * rethrown wrapped into a PropelException. + */ + public static function doInsert($criteria, ConnectionInterface $con = null) + { + if (null === $con) { + $con = Propel::getServiceContainer()->getWriteConnection(OrderCommentTableMap::DATABASE_NAME); + } + + if ($criteria instanceof Criteria) { + $criteria = clone $criteria; // rename for clarity + } else { + $criteria = $criteria->buildCriteria(); // build Criteria from OrderComment object + } + + if ($criteria->containsKey(OrderCommentTableMap::ID) && $criteria->keyContainsValue(OrderCommentTableMap::ID) ) { + throw new PropelException('Cannot insert a value for auto-increment primary key ('.OrderCommentTableMap::ID.')'); + } + + + // Set the correct dbName + $query = OrderCommentQuery::create()->mergeWith($criteria); + + try { + // use transaction because $criteria could contain info + // for more than one table (I guess, conceivably) + $con->beginTransaction(); + $pk = $query->doInsert($con); + $con->commit(); + } catch (PropelException $e) { + $con->rollBack(); + throw $e; + } + + return $pk; + } + +} // OrderCommentTableMap +// This is the static code needed to register the TableMap for this table with the main Propel class. +// +OrderCommentTableMap::buildTableMap(); diff --git a/local/modules/OrderComment/Model/OrderComment.php b/local/modules/OrderComment/Model/OrderComment.php new file mode 100644 index 00000000..d348364b --- /dev/null +++ b/local/modules/OrderComment/Model/OrderComment.php @@ -0,0 +1,10 @@ +findOne(); + } catch (\Exception $e) { + $database = new Database($con->getWrappedConnection()); + $database->insertSql(null, array(THELIA_ROOT . '/local/modules/OrderComment/Config/thelia.sql')); + } + } +} diff --git a/local/modules/OrderComment/Readme.md b/local/modules/OrderComment/Readme.md new file mode 100644 index 00000000..09e32ab5 --- /dev/null +++ b/local/modules/OrderComment/Readme.md @@ -0,0 +1,58 @@ +# OrderComment + +This module allows your customers to write a comment for an order. Then you can find this comment in the order detail page of the backoffice. + +![OrderComment preview](preview.png) + +## Installation + +### Manually + +* Copy the module into ```/local/modules/``` directory and be sure that the name of the module is OrderComment. +* Activate it in your thelia administration panel + +### Composer + +Add it in your main thelia composer.json file + +``` +composer require thelia/order-comment-module:~1.2 +``` + +## Loop + +OrderCommentLoop : order.comment.comment + +This loop return the comment of an order. + +### Input arguments + +|Argument |Description | +|--- |--- | +|**order_id** | Unique ID of the order (eg. order_id=5) | + +### Output arguments + +|Variable |Description | +|--- |--- | +|$ORDER_COMMENT | Content of the comment | + +### Example + +``` +{ifloop rel="order_comment_loop"} + {loop name="order_comment_loop" type="order.comment.comment" order_id="$order_id" } + {$ORDER_COMMENT} + {/loop} +{/ifloop} +{elseloop rel="order_comment_loop"} +

+ {intl l="No comment for this order was defined." d="ordercomment"} +

+{/elseloop} +``` + +## Other ? + +It may be convenient to display the comment on the detail page of the customer's order. +To do that, uses the loop described previously. \ No newline at end of file diff --git a/local/modules/OrderComment/composer.json b/local/modules/OrderComment/composer.json new file mode 100644 index 00000000..bb24cf71 --- /dev/null +++ b/local/modules/OrderComment/composer.json @@ -0,0 +1,11 @@ +{ + "name": "thelia/order-comment-module", + "license": "LGPL-3.0+", + "type": "thelia-module", + "require": { + "thelia/installer": "~1.1" + }, + "extra": { + "installer-name": "OrderComment" + } +} diff --git a/local/modules/OrderComment/preview.png b/local/modules/OrderComment/preview.png new file mode 100644 index 0000000000000000000000000000000000000000..5123ec5598fb4b6490e26da23d8d6f57a4feaecb GIT binary patch literal 97382 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

~1wfA-2Iq%0y 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 YDdi)5dvDq60^vvgrSgk{=SJTD14YIIp8x;= literal 0 HcmV?d00001 diff --git a/local/modules/OrderComment/templates/backOffice/default/order-edit.html b/local/modules/OrderComment/templates/backOffice/default/order-edit.html new file mode 100644 index 00000000..24931785 --- /dev/null +++ b/local/modules/OrderComment/templates/backOffice/default/order-edit.html @@ -0,0 +1,19 @@ +

+
+

+ {intl l="Customer comment" d="ordercomment.bo.default"} +

+
+
+ {$comment = ''} + {loop type="order.comment.comment" name="order_comment_loop" order_id=$order_id} + {$comment = $ORDER_COMMENT} + {/loop} + + {if $comment} + {$comment|nl2br nofilter} + {else} + {intl l="No comment for this order was defined." d="ordercomment.bo.default"} + {/if} +
+
diff --git a/local/modules/OrderComment/templates/frontOffice/default/OrderComment/assets/js/cart-comment-js.js b/local/modules/OrderComment/templates/frontOffice/default/OrderComment/assets/js/cart-comment-js.js new file mode 100644 index 00000000..09662919 --- /dev/null +++ b/local/modules/OrderComment/templates/frontOffice/default/OrderComment/assets/js/cart-comment-js.js @@ -0,0 +1 @@ +$('#cart > a').slice(-2).remove(); \ No newline at end of file diff --git a/local/modules/OrderComment/templates/frontOffice/default/OrderComment/cart-comment.html b/local/modules/OrderComment/templates/frontOffice/default/OrderComment/cart-comment.html new file mode 100644 index 00000000..042bde9f --- /dev/null +++ b/local/modules/OrderComment/templates/frontOffice/default/OrderComment/cart-comment.html @@ -0,0 +1,10 @@ +{form name="order.comment.form"} + + {form_hidden_fields form=$form} + + {include file="OrderComment/comment-input.html"} + + {intl l="Continue Shopping"} + + +{/form} diff --git a/local/modules/OrderComment/templates/frontOffice/default/OrderComment/comment-input.html b/local/modules/OrderComment/templates/frontOffice/default/OrderComment/comment-input.html new file mode 100644 index 00000000..ba0c5d53 --- /dev/null +++ b/local/modules/OrderComment/templates/frontOffice/default/OrderComment/comment-input.html @@ -0,0 +1,13 @@ +
+
+ {intl l="Add your comment" d="ordercomment.fo.default"} +
+
+ {if $form_error}
{$form_error_message}
{/if} + +
+ {form_field form=$form field='comment'} + + {/form_field} +
+
diff --git a/local/modules/OrderComment/templates/pdf/default/delivery.after-summary.html b/local/modules/OrderComment/templates/pdf/default/delivery.after-summary.html new file mode 100644 index 00000000..effa511c --- /dev/null +++ b/local/modules/OrderComment/templates/pdf/default/delivery.after-summary.html @@ -0,0 +1,11 @@ +{loop type="order.comment.comment" name="order_comment_loop" order_id="$order_id" } + + + + + +
+ {intl l="Message" d="ordercomment.bo.default"} :
+ {$ORDER_COMMENT|nl2br nofilter} +
+{/loop} \ No newline at end of file diff --git a/local/modules/VirtualProductDelivery/VirtualProductDelivery.php b/local/modules/VirtualProductDelivery/VirtualProductDelivery.php index b96226a6..44a0185f 100644 --- a/local/modules/VirtualProductDelivery/VirtualProductDelivery.php +++ b/local/modules/VirtualProductDelivery/VirtualProductDelivery.php @@ -17,9 +17,8 @@ use Thelia\Core\Translation\Translator; use Thelia\Model\Country; use Thelia\Model\LangQuery; use Thelia\Model\Message; -use Thelia\Model\State; use Thelia\Model\MessageQuery; -use Thelia\Module\AbstractDeliveryModule; +use Thelia\Model\State; use Thelia\Module\AbstractDeliveryModuleWithState; use Thelia\Module\Exception\DeliveryException;
+
+
+
+ {intl d='atos.bo.default' l="Atos Configuration"} +
+
+ +
+
+
+ {form name="atos_configuration"} + + {form_hidden_fields form=$form} + + {include file = "includes/inner-form-toolbar.html" + hide_flags = true + page_url = "{url path='/admin/module/Atos'}" + close_url = "{url path='/admin/modules'}" + } + + {if $form_error} +
+
+
{$form_error_message}
+
+
+ {/if} + +
+
+

{intl d='atos.bo.default' l="Atos-SIPS Platform configuration"}

+ + {render_form_field form=$form field="atos_merchantId" value=$atos_merchantId} + {render_form_field form=$form field="atos_certificate" value=$atos_certificate} + +
+ + +
{url path='/atos/callback'}
+ + + {intl d='atos.bo.default' l="This is the callback URL, that will be called by Atos SIPS after customer payment. Be sure that this URL is reachable by remote mechines"} + +
+
+ +
+

{intl d='atos.bo.default' l="Operation mode"}

+ + {render_form_field form=$form field="atos_mode" value=$atos_mode} + {render_form_field form=$form field="atos_allowed_ip_list" value=$atos_allowed_ip_list} + +

{intl d='atos.bo.default' l="Payment by N installment"}

+ + {loop name="multi-plugin-enabled" type="module" code="AtosNx" active="1"}{/loop} + {elseloop rel="multi-plugin-enabled"} +
+ {intl l="Install and activate Atos multiple times payment module (AtoxNx) to get configuration options." d='payzen.ai'} +
+ {/elseloop} + + {render_form_field form=$form field="nx_nb_installments" value=$nx_nb_installments|default:3} + {render_form_field form=$form field="nx_minimum_amount" value=$nx_minimum_amount|default:0} + {render_form_field form=$form field="nx_maximum_amount" value=$nx_maximum_amount|default:0} +
+ +
+
+ + {/form} + + + +
+
+
+
+