/** * Get all Packs that contains the given item in the corresponding declination. * * @param \ProductCore $item * @param integer $item_attribute_id * @param integer $id_lang Optional * @return Array[Pack] The packs that contains the given item, with special dynamic attribute [pack_item_quantity] */ public function getPacksContainingItem($item, $item_attribute_id, $id_lang = false) { if ($id_lang === false) { $configuration = \PrestaShop\PrestaShop\Adapter\ServiceLocator::get('\\PrestaShop\\PrestaShop\\Core\\ConfigurationInterface'); $id_lang = (int) $configuration->get('PS_LANG_DEFAULT'); } return \PackCore::getPacksContainingItem($item->id, $item_attribute_id, $id_lang); }
/** * Execute modules for specified hook * * @param string $hook_name Hook Name * @param array $hook_args Parameters for the functions * @param int $id_module Execute hook for this module only * @param bool $array_return If specified, module output will be set by name in an array * @param bool $check_exceptions Check permission exceptions * @param bool $use_push Force change to be refreshed on Dashboard widgets * @param int $id_shop If specified, hook will be execute the shop with this ID * * @throws \PrestaShopException * * @return string/array modules output */ public function exec($hook_name, $hook_args = array(), $id_module = null, $array_return = false, $check_exceptions = true, $use_push = false, $id_shop = null) { try { return \HookCore::exec($hook_name, $hook_args, $id_module, $array_return, $check_exceptions, $use_push, $id_shop); } catch (\Exception $e) { $logger = \PrestaShop\PrestaShop\Adapter\ServiceLocator::get('logger'); $logger->error(sprintf('Exception on hook %s for module %s. %s', $hook_name, $id_module, $e->getMessage())); } }
/** * * @param Address $address * @param mixed $type An additional parameter for the tax manager (ex: tax rules id for TaxRuleTaxManager) */ public function __construct(Address $address, $type, \PrestaShop\PrestaShop\Core\ConfigurationInterface $configurationManager = null) { if ($configurationManager === null) { $this->configurationManager = \PrestaShop\PrestaShop\Adapter\ServiceLocator::get('\\PrestaShop\\PrestaShop\\Core\\ConfigurationInterface'); } else { $this->configurationManager = $configurationManager; } $this->address = $address; $this->type = $type; }
/** * Returns the taxes calculator associated to the carrier * * @since 1.5 * * @param Address $address Address * * @return TaxCalculator Tax calculator object */ public function getTaxCalculator(Address $address, $id_order = null, $use_average_tax_of_products = false) { if ($use_average_tax_of_products) { return \PrestaShop\PrestaShop\Adapter\ServiceLocator::get('AverageTaxOfProductsTaxCalculator')->setIdOrder($id_order); } else { $tax_manager = TaxManagerFactory::getManager($address, $this->getIdTaxRulesGroup()); return $tax_manager->getTaxCalculator(); } }
public function notificationAction() { $translator = $this->get('translator'); $modulesProvider = $this->get('prestashop.core.admin.data_provider.module_interface'); $moduleRepository = $this->get('prestashop.core.admin.module.repository'); $filters = new AddonListFilter(); $filters->setType(AddonListFilterType::MODULE | AddonListFilterType::SERVICE)->setStatus(AddonListFilterStatus::INSTALLED); $installedProducts = $moduleRepository->getFilteredList($filters); $modules = new \stdClass(); foreach (array('to_configure', 'to_update') as $subpart) { $modules->{$subpart} = array(); } foreach ($installedProducts as $installedProduct) { $warnings = array(); $moduleProvider = $this->get('prestashop.adapter.data_provider.module'); $moduleName = $installedProduct->attributes->get('name'); if ($moduleProvider->isModuleMainClassValid($moduleName)) { require_once _PS_MODULE_DIR_ . $moduleName . '/' . $moduleName . '.php'; $module = \PrestaShop\PrestaShop\Adapter\ServiceLocator::get($moduleName); $warnings = $module->warning; } if (!empty($warnings)) { $modules->to_configure[] = (object) $installedProduct; } if ($installedProduct->canBeUpgraded()) { $modules->to_update[] = (object) $installedProduct; } } foreach ($modules as $moduleLabel => $modulesPart) { $modules->{$moduleLabel} = $modulesProvider->generateAddonsUrls($modulesPart); $modules->{$moduleLabel} = $this->getPresentedProducts($modulesPart); } return $this->render('PrestaShopBundle:Admin/Module:notifications.html.twig', array('layoutHeaderToolbarBtn' => $this->getToolbarButtons(), 'layoutTitle' => $translator->trans('Module notifications', array(), 'Admin.Modules.Feature'), 'modules' => $modules, 'requireAddonsSearch' => false, 'requireBulkActions' => false, 'enableSidebar' => true, 'help_link' => $this->generateSidebarLink('AdminModules'), 'requireFilterStatus' => false)); }
* versions in the future. If you wish to customize PrestaShop for your * needs please refer to http://www.prestashop.com for more information. * * @author PrestaShop SA <*****@*****.**> * @copyright 2007-2015 PrestaShop SA * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) * International Registered Trademark & Property of PrestaShop SA */ use PrestaShop\PrestaShop\Adapter\ServiceLocator; use PrestaShop\PrestaShop\Core\ContainerBuilder; use Symfony\Component\HttpKernel\CacheWarmer\CacheWarmerAggregate; use Symfony\Component\Yaml\Yaml; use Symfony\Component\Filesystem\Filesystem; $container_builder = new ContainerBuilder(); $container = $container_builder->build(); ServiceLocator::setServiceContainerInstance($container); if (!file_exists(_PS_CACHE_DIR_)) { @mkdir(_PS_CACHE_DIR_); $warmer = new CacheWarmerAggregate([new PrestaShopBundle\Cache\LocalizationWarmer(_PS_VERSION_, 'en')]); $warmer->warmUp(_PS_CACHE_DIR_); } $configDirectory = __DIR__ . '/../app/config'; $phpParametersFilepath = $configDirectory . '/parameters.php'; $yamlParametersFilepath = $configDirectory . '/parameters.yml'; $filesystem = new Filesystem(); $exportPhpConfigFile = function ($config, $destination) use($filesystem) { return $filesystem->dumpFile($destination, '<?php return ' . var_export($config, true) . ';' . "\n"); }; // Bootstrap an application with parameters.yml, which has been installed before PHP parameters file support if (!file_exists($phpParametersFilepath) && file_exists($yamlParametersFilepath)) { $parameters = Yaml::parse($yamlParametersFilepath);
public function delete() { /* * @since 1.5.0 * It is NOT possible to delete a product if there are currently: * - physical stock for this product * - supply order(s) for this product */ if (Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT') && $this->advanced_stock_management) { $stock_manager = StockManagerFactory::getManager(); $physical_quantity = $stock_manager->getProductPhysicalQuantities($this->id, 0); $real_quantity = $stock_manager->getProductRealQuantities($this->id, 0); if ($physical_quantity > 0) { return false; } if ($real_quantity > $physical_quantity) { return false; } $warehouse_product_locations = \PrestaShop\PrestaShop\Adapter\ServiceLocator::get('\\PrestaShop\\PrestaShop\\Core\\Foundation\\Database\\EntityManager')->getRepository('WarehouseProductLocation')->findByIdProduct($this->id); foreach ($warehouse_product_locations as $warehouse_product_location) { $warehouse_product_location->delete(); } $stocks = \PrestaShop\PrestaShop\Adapter\ServiceLocator::get('\\PrestaShop\\PrestaShop\\Core\\Foundation\\Database\\EntityManager')->getRepository('Stock')->findByIdProduct($this->id); foreach ($stocks as $stock) { $stock->delete(); } } $result = parent::delete(); // Removes the product from StockAvailable, for the current shop StockAvailable::removeProductFromStockAvailable($this->id); $result &= $this->deleteProductAttributes() && $this->deleteImages(); // If there are still entries in product_shop, don't remove completely the product if ($this->hasMultishopEntries()) { return true; } Hook::exec('actionProductDelete', array('id_product' => (int) $this->id, 'product' => $this)); if (!$result || !GroupReduction::deleteProductReduction($this->id) || !$this->deleteCategories(true) || !$this->deleteProductFeatures() || !$this->deleteTags() || !$this->deleteCartProducts() || !$this->deleteAttributesImpacts() || !$this->deleteAttachments(false) || !$this->deleteCustomization() || !SpecificPrice::deleteByProductId((int) $this->id) || !$this->deletePack() || !$this->deleteProductSale() || !$this->deleteSearchIndexes() || !$this->deleteAccessories() || !$this->deleteFromAccessories() || !$this->deleteFromSupplier() || !$this->deleteDownload() || !$this->deleteFromCartRules()) { return false; } return true; }
/** * This function returns the total cart amount * * @param bool $withTaxes With or without taxes * @param int $type Total type enum * - Cart::ONLY_PRODUCTS * - Cart::ONLY_DISCOUNTS * - Cart::BOTH * - Cart::BOTH_WITHOUT_SHIPPING * - Cart::ONLY_SHIPPING * - Cart::ONLY_WRAPPING * - Cart::ONLY_PRODUCTS_WITHOUT_SHIPPING * - Cart::ONLY_PHYSICAL_PRODUCTS_WITHOUT_SHIPPING * @param bool $use_cache Allow using cache of the method CartRule::getContextualValue * * @return float Order total */ public function getOrderTotal($with_taxes = true, $type = Cart::BOTH, $products = null, $id_carrier = null, $use_cache = true) { // Dependencies $address_factory = \PrestaShop\PrestaShop\Adapter\ServiceLocator::get('\\PrestaShop\\PrestaShop\\Adapter\\AddressFactory'); $price_calculator = \PrestaShop\PrestaShop\Adapter\ServiceLocator::get('\\PrestaShop\\PrestaShop\\Adapter\\Product\\PriceCalculator'); $configuration = \PrestaShop\PrestaShop\Adapter\ServiceLocator::get('\\PrestaShop\\PrestaShop\\Core\\ConfigurationInterface'); $ps_tax_address_type = $configuration->get('PS_TAX_ADDRESS_TYPE'); $ps_use_ecotax = $configuration->get('PS_USE_ECOTAX'); $ps_round_type = $configuration->get('PS_ROUND_TYPE'); $ps_ecotax_tax_rules_group_id = $configuration->get('PS_ECOTAX_TAX_RULES_GROUP_ID'); $compute_precision = $configuration->get('_PS_PRICE_COMPUTE_PRECISION_'); if (!$this->id) { return 0; } $type = (int) $type; $array_type = array(Cart::ONLY_PRODUCTS, Cart::ONLY_DISCOUNTS, Cart::BOTH, Cart::BOTH_WITHOUT_SHIPPING, Cart::ONLY_SHIPPING, Cart::ONLY_WRAPPING, Cart::ONLY_PRODUCTS_WITHOUT_SHIPPING, Cart::ONLY_PHYSICAL_PRODUCTS_WITHOUT_SHIPPING); // Define virtual context to prevent case where the cart is not the in the global context $virtual_context = Context::getContext()->cloneContext(); $virtual_context->cart = $this; if (!in_array($type, $array_type)) { die(Tools::displayError()); } $with_shipping = in_array($type, array(Cart::BOTH, Cart::ONLY_SHIPPING)); // if cart rules are not used if ($type == Cart::ONLY_DISCOUNTS && !CartRule::isFeatureActive()) { return 0; } // no shipping cost if is a cart with only virtuals products $virtual = $this->isVirtualCart(); if ($virtual && $type == Cart::ONLY_SHIPPING) { return 0; } if ($virtual && $type == Cart::BOTH) { $type = Cart::BOTH_WITHOUT_SHIPPING; } if ($with_shipping || $type == Cart::ONLY_DISCOUNTS) { if (is_null($products) && is_null($id_carrier)) { $shipping_fees = $this->getTotalShippingCost(null, (bool) $with_taxes); } else { $shipping_fees = $this->getPackageShippingCost((int) $id_carrier, (bool) $with_taxes, null, $products); } } else { $shipping_fees = 0; } if ($type == Cart::ONLY_SHIPPING) { return $shipping_fees; } if ($type == Cart::ONLY_PRODUCTS_WITHOUT_SHIPPING) { $type = Cart::ONLY_PRODUCTS; } $param_product = true; if (is_null($products)) { $param_product = false; $products = $this->getProducts(); } if ($type == Cart::ONLY_PHYSICAL_PRODUCTS_WITHOUT_SHIPPING) { foreach ($products as $key => $product) { if ($product['is_virtual']) { unset($products[$key]); } } $type = Cart::ONLY_PRODUCTS; } $order_total = 0; if (Tax::excludeTaxeOption()) { $with_taxes = false; } $products_total = array(); $ecotax_total = 0; foreach ($products as $product) { // products refer to the cart details if ($virtual_context->shop->id != $product['id_shop']) { $virtual_context->shop = new Shop((int) $product['id_shop']); } if ($ps_tax_address_type == 'id_address_invoice') { $id_address = (int) $this->id_address_invoice; } else { $id_address = (int) $product['id_address_delivery']; } // Get delivery address of the product from the cart if (!$address_factory->addressExists($id_address)) { $id_address = null; } // The $null variable below is not used, // but it is necessary to pass it to getProductPrice because // it expects a reference. $null = null; $price = $price_calculator->getProductPrice((int) $product['id_product'], $with_taxes, (int) $product['id_product_attribute'], 6, null, false, true, $product['cart_quantity'], false, (int) $this->id_customer ? (int) $this->id_customer : null, (int) $this->id, $id_address, $null, $ps_use_ecotax, true, $virtual_context, true, (int) $product['id_customization']); $address = $address_factory->findOrCreate($id_address, true); if ($with_taxes) { $id_tax_rules_group = Product::getIdTaxRulesGroupByIdProduct((int) $product['id_product'], $virtual_context); $tax_calculator = TaxManagerFactory::getManager($address, $id_tax_rules_group)->getTaxCalculator(); } else { $id_tax_rules_group = 0; } if (in_array($ps_round_type, array(Order::ROUND_ITEM, Order::ROUND_LINE))) { if (!isset($products_total[$id_tax_rules_group])) { $products_total[$id_tax_rules_group] = 0; } } elseif (!isset($products_total[$id_tax_rules_group . '_' . $id_address])) { $products_total[$id_tax_rules_group . '_' . $id_address] = 0; } switch ($ps_round_type) { case Order::ROUND_TOTAL: $products_total[$id_tax_rules_group . '_' . $id_address] += $price * (int) $product['cart_quantity']; break; case Order::ROUND_LINE: $product_price = $price * $product['cart_quantity']; $products_total[$id_tax_rules_group] += Tools::ps_round($product_price, $compute_precision); break; case Order::ROUND_ITEM: default: $product_price = $price; $products_total[$id_tax_rules_group] += Tools::ps_round($product_price, $compute_precision) * (int) $product['cart_quantity']; break; } } foreach ($products_total as $key => $price) { $order_total += $price; } $order_total_products = $order_total; if ($type == Cart::ONLY_DISCOUNTS) { $order_total = 0; } // Wrapping Fees $wrapping_fees = 0; // With PS_ATCP_SHIPWRAP on the gift wrapping cost computation calls getOrderTotal with $type === Cart::ONLY_PRODUCTS, so the flag below prevents an infinite recursion. $include_gift_wrapping = !$configuration->get('PS_ATCP_SHIPWRAP') || $type !== Cart::ONLY_PRODUCTS; if ($this->gift && $include_gift_wrapping) { $wrapping_fees = Tools::convertPrice(Tools::ps_round($this->getGiftWrappingPrice($with_taxes), $compute_precision), Currency::getCurrencyInstance((int) $this->id_currency)); } if ($type == Cart::ONLY_WRAPPING) { return $wrapping_fees; } $order_total_discount = 0; $order_shipping_discount = 0; if (!in_array($type, array(Cart::ONLY_SHIPPING, Cart::ONLY_PRODUCTS)) && CartRule::isFeatureActive()) { // First, retrieve the cart rules associated to this "getOrderTotal" if ($with_shipping || $type == Cart::ONLY_DISCOUNTS) { $cart_rules = $this->getCartRules(CartRule::FILTER_ACTION_ALL); } else { $cart_rules = $this->getCartRules(CartRule::FILTER_ACTION_REDUCTION); // Cart Rules array are merged manually in order to avoid doubles foreach ($this->getCartRules(CartRule::FILTER_ACTION_GIFT) as $tmp_cart_rule) { $flag = false; foreach ($cart_rules as $cart_rule) { if ($tmp_cart_rule['id_cart_rule'] == $cart_rule['id_cart_rule']) { $flag = true; } } if (!$flag) { $cart_rules[] = $tmp_cart_rule; } } } $id_address_delivery = 0; if (isset($products[0])) { $id_address_delivery = is_null($products) ? $this->id_address_delivery : $products[0]['id_address_delivery']; } $package = array('id_carrier' => $id_carrier, 'id_address' => $id_address_delivery, 'products' => $products); // Then, calculate the contextual value for each one $flag = false; foreach ($cart_rules as $cart_rule) { // If the cart rule offers free shipping, add the shipping cost if (($with_shipping || $type == Cart::ONLY_DISCOUNTS) && $cart_rule['obj']->free_shipping && !$flag) { $order_shipping_discount = (double) Tools::ps_round($cart_rule['obj']->getContextualValue($with_taxes, $virtual_context, CartRule::FILTER_ACTION_SHIPPING, $param_product ? $package : null, $use_cache), $compute_precision); $flag = true; } // If the cart rule is a free gift, then add the free gift value only if the gift is in this package if ((int) $cart_rule['obj']->gift_product) { $in_order = false; if (is_null($products)) { $in_order = true; } else { foreach ($products as $product) { if ($cart_rule['obj']->gift_product == $product['id_product'] && $cart_rule['obj']->gift_product_attribute == $product['id_product_attribute']) { $in_order = true; } } } if ($in_order) { $order_total_discount += $cart_rule['obj']->getContextualValue($with_taxes, $virtual_context, CartRule::FILTER_ACTION_GIFT, $package, $use_cache); } } // If the cart rule offers a reduction, the amount is prorated (with the products in the package) if ($cart_rule['obj']->reduction_percent > 0 || $cart_rule['obj']->reduction_amount > 0) { $order_total_discount += Tools::ps_round($cart_rule['obj']->getContextualValue($with_taxes, $virtual_context, CartRule::FILTER_ACTION_REDUCTION, $package, $use_cache), $compute_precision); } } $order_total_discount = min(Tools::ps_round($order_total_discount, 2), (double) $order_total_products) + (double) $order_shipping_discount; $order_total -= $order_total_discount; } if ($type == Cart::BOTH) { $order_total += $shipping_fees + $wrapping_fees; } if ($order_total < 0 && $type != Cart::ONLY_DISCOUNTS) { return 0; } if ($type == Cart::ONLY_DISCOUNTS) { return $order_total_discount; } return Tools::ps_round((double) $order_total, $compute_precision); }
/** * For a given id_product and id_product_attribute updates the quantity available * If $avoid_parent_pack_update is true, then packs containing the given product won't be updated * * @param int $id_product * @param int $id_product_attribute Optional * @param int $delta_quantity The delta quantity to update * @param int $id_shop Optional */ public static function updateQuantity($id_product, $id_product_attribute, $delta_quantity, $id_shop = null) { if (!Validate::isUnsignedId($id_product)) { return false; } $product = new Product((int) $id_product); if (!Validate::isLoadedObject($product)) { return false; } $stockManager = \PrestaShop\PrestaShop\Adapter\ServiceLocator::get('\\PrestaShop\\PrestaShop\\Core\\Stock\\StockManager'); $stockManager->updateQuantity($product, $id_product_attribute, $delta_quantity, $id_shop = null); return true; }
/** * Get the new module presenter class of the specified name provided. * It contains data from its instance, the disk, the database and from the marketplace if exists. * * @param string $name The technical name of the module * * @return \PrestaShop\PrestaShop\Adapter\Module\Module */ public function getModule($name) { $php_file_path = _PS_MODULE_DIR_ . $name . '/' . $name . '.php'; /* Data which design the module class */ $attributes = array('name' => $name); $disk = array(); $database = array(); // Get filemtime of module main class (We do this directly with an error suppressor to go faster) $current_filemtime = (int) @filemtime($php_file_path); // We check that we have data from the marketplace try { $module_catalog_data = $this->adminModuleProvider->getCatalogModules(array('name' => $name)); $attributes = array_merge($attributes, (array) array_shift($module_catalog_data)); } catch (Exception $e) { $this->logger->alert($this->translator->trans('Loading data from Addons failed. %error_details%', array('%error_details%' => $e->getMessage()), 'Admin.Modules.Notification')); } // Now, we check that cache is up to date if (isset($this->cache[$name]['disk']['filemtime']) && $this->cache[$name]['disk']['filemtime'] === $current_filemtime) { // OK, cache can be loaded and used directly $attributes = array_merge($attributes, $this->cache[$name]['attributes']); $disk = $this->cache[$name]['disk']; } else { // NOPE, we have to fulfil the cache with the module data $disk = array('filemtime' => $current_filemtime, 'filemtime' => $current_filemtime, 'is_present' => (int) $this->moduleProvider->isOnDisk($name), 'is_valid' => 0, 'version' => null); $main_class_attributes = array(); if ($this->moduleProvider->isModuleMainClassValid($name)) { require_once $php_file_path; // We load the main class of the module, and get its properties $tmp_module = \PrestaShop\PrestaShop\Adapter\ServiceLocator::get($name); foreach (array('warning', 'name', 'tab', 'displayName', 'description', 'author', 'author_uri', 'limited_countries', 'need_instance') as $data_to_get) { if (isset($tmp_module->{$data_to_get})) { $main_class_attributes[$data_to_get] = $tmp_module->{$data_to_get}; } } $main_class_attributes['parent_class'] = get_parent_class($name); $main_class_attributes['is_configurable'] = (int) method_exists($tmp_module, 'getContent'); $disk['is_valid'] = 1; $disk['version'] = $tmp_module->version; $attributes = array_merge($attributes, $main_class_attributes); } else { $main_class_attributes['warning'] = 'Invalid module class'; } $this->cache[$name]['attributes'] = $main_class_attributes; $this->cache[$name]['disk'] = $disk; } foreach (array('logo.png', 'logo.gif') as $logo) { $logo_path = _PS_MODULE_DIR_ . $name . DIRECTORY_SEPARATOR . $logo; if (file_exists($logo_path)) { $attributes['img'] = __PS_BASE_URI__ . basename(_PS_MODULE_DIR_) . '/' . $name . '/' . $logo; break; } } // Get data from database $database = $this->moduleProvider->findByName($name); return new Module($attributes, $disk, $database); }
public function initContent() { if (Tools::isSubmit('addnewmodule') && $this->context->mode == Context::MODE_HOST) { $this->display = 'add'; $this->context->smarty->assign(array('iso_code' => $this->context->language->iso_code)); return parent::initContent(); } $this->meta_title = 'Modules'; // If we are on a module configuration, no need to load all modules if (Tools::getValue('configure') != '') { $this->context->smarty->assign(array('maintenance_mode' => !(bool) Configuration::Get('PS_SHOP_ENABLE'))); return true; } $this->initToolbar(); $this->initPageHeaderToolbar(); // Init $smarty = $this->context->smarty; $autocomplete_list = 'var moduleList = ['; $category_filtered = array(); $filter_categories = explode('|', Configuration::get('PS_SHOW_CAT_MODULES_' . (int) $this->id_employee)); if (count($filter_categories) > 0) { foreach ($filter_categories as $fc) { if (!empty($fc)) { $category_filtered[$fc] = 1; } } } if (empty($category_filtered) && Tools::getValue('tab_module')) { $category_filtered[Tools::getValue('tab_module')] = 1; } foreach ($this->list_modules_categories as $k => $v) { $this->list_modules_categories[$k]['nb'] = 0; } // Retrieve Modules Preferences $modules_preferences = ''; $tab_modules_preferences = array(); $modules_preferences_tmp = Db::getInstance()->executeS('SELECT * FROM `' . _DB_PREFIX_ . 'module_preference` WHERE `id_employee` = ' . (int) $this->id_employee); $tab_modules_preferences_tmp = Db::getInstance()->executeS('SELECT * FROM `' . _DB_PREFIX_ . 'tab_module_preference` WHERE `id_employee` = ' . (int) $this->id_employee); foreach ($tab_modules_preferences_tmp as $i => $j) { $tab_modules_preferences[$j['module']][] = $j['id_tab']; } foreach ($modules_preferences_tmp as $k => $v) { if ($v['interest'] == null) { unset($v['interest']); } if ($v['favorite'] == null) { unset($v['favorite']); } $modules_preferences[$v['module']] = $v; } // Retrieve Modules List $modules = Module::getModulesOnDisk(true, $this->logged_on_addons, $this->id_employee); $this->initModulesList($modules); $this->nb_modules_total = count($modules); $module_errors = array(); $module_success = array(); $upgrade_available = array(); $dont_filter = false; //Add succes message for one module update if (Tools::getValue('updated') && Tools::getValue('module_name')) { $module_names = (string) Tools::getValue('module_name'); if (strpos($module_names, '|')) { $module_names = explode('|', $module_names); $dont_filter = true; } if (!is_array($module_names)) { $module_names = (array) $module_names; } foreach ($modules as $km => $module) { if (in_array($module->name, $module_names)) { $module_success[] = array('name' => $module->displayName, 'message' => array(0 => sprintf($this->l('Current version: %s'), $module->version))); } } } if (Tools::getValue('allUpdated')) { $this->confirmations[] = $this->l('All modules updated successfully.'); } // Browse modules list foreach ($modules as $km => $module) { //if we are in favorites view we only display installed modules if (Tools::getValue('select') == 'favorites' && !$module->id) { unset($modules[$km]); continue; } // Upgrade Module process, init check if a module could be upgraded if (Module::initUpgradeModule($module)) { // When the XML cache file is up-to-date, the module may not be loaded yet if (!class_exists($module->name)) { if (!file_exists(_PS_MODULE_DIR_ . $module->name . '/' . $module->name . '.php')) { continue; } require_once _PS_MODULE_DIR_ . $module->name . '/' . $module->name . '.php'; } if ($object = ServiceLocator::get($module->name)) { /** @var Module $object */ $object->runUpgradeModule(); if (count($errors_module_list = $object->getErrors())) { $module_errors[] = array('name' => $module->displayName, 'message' => $errors_module_list); } elseif (count($conf_module_list = $object->getConfirmations())) { $module_success[] = array('name' => $module->displayName, 'message' => $conf_module_list); } unset($object); } } elseif (Module::getUpgradeStatus($module->name)) { // When the XML cache file is up-to-date, the module may not be loaded yet if (!class_exists($module->name)) { if (file_exists(_PS_MODULE_DIR_ . $module->name . '/' . $module->name . '.php')) { require_once _PS_MODULE_DIR_ . $module->name . '/' . $module->name . '.php'; $object = ServiceLocator::get($module->name); $module_success[] = array('name' => $module->name, 'message' => array(0 => sprintf($this->l('Current version: %s'), $object->version), 1 => $this->l('No file upgrades applied (none exist).'))); } else { continue; } } unset($object); } // Make modules stats $this->makeModulesStats($module); // Assign warnings if ($module->active && isset($module->warning) && !empty($module->warning) && !$this->ajax) { $href = Context::getContext()->link->getAdminLink('AdminModules', true) . '&module_name=' . $module->name . '&tab_module=' . $module->tab . '&configure=' . $module->name; $this->context->smarty->assign('text', sprintf($this->l('%1$s: %2$s'), $module->displayName, $module->warning)); $this->context->smarty->assign('module_link', $href); $this->displayWarning($this->context->smarty->fetch('controllers/modules/warning_module.tpl')); } // AutoComplete array $autocomplete_list .= json_encode(array('displayName' => (string) $module->displayName, 'desc' => (string) $module->description, 'name' => (string) $module->name, 'author' => (string) $module->author, 'image' => isset($module->image) ? (string) $module->image : '', 'option' => '')) . ', '; // Apply filter if ($this->isModuleFiltered($module) && Tools::getValue('select') != 'favorites') { unset($modules[$km]); } else { if (isset($modules_preferences[$modules[$km]->name])) { $modules[$km]->preferences = $modules_preferences[$modules[$km]->name]; } $this->fillModuleData($module, 'array', null, 'back-office,AdminModules,index'); $module->categoryName = isset($this->list_modules_categories[$module->tab]['name']) ? $this->list_modules_categories[$module->tab]['name'] : $this->list_modules_categories['others']['name']; } unset($object); if ($module->installed && isset($module->version_addons) && $module->version_addons) { $upgrade_available[] = array('anchor' => ucfirst($module->name), 'name' => $module->name, 'displayName' => $module->displayName); } if (in_array($module->name, $this->list_partners_modules)) { $module->type = 'addonsPartner'; } if (isset($module->description_full) && trim($module->description_full) != '') { $module->show_quick_view = true; } } // Don't display categories without modules $cleaned_list = array(); foreach ($this->list_modules_categories as $k => $list) { if ($list['nb'] > 0) { $cleaned_list[$k] = $list; } } // Actually used for the report of the upgraded errors if (count($module_errors)) { $html = $this->generateHtmlMessage($module_errors); $this->errors[] = sprintf(Tools::displayError('The following module(s) were not upgraded successfully: %s.'), $html); } if (count($module_success)) { $html = $this->generateHtmlMessage($module_success); $this->confirmations[] = sprintf($this->l('The following module(s) were upgraded successfully: %s.'), $html); } ConfigurationKPI::updateValue('UPDATE_MODULES', count($upgrade_available)); if (count($upgrade_available) == 0 && (int) Tools::getValue('check') == 1) { $this->confirmations[] = $this->l('Everything is up-to-date'); } // Init tpl vars for smarty $tpl_vars = array('token' => $this->token, 'upgrade_available' => $upgrade_available, 'currentIndex' => self::$currentIndex, 'dirNameCurrentIndex' => dirname(self::$currentIndex), 'ajaxCurrentIndex' => str_replace('index', 'ajax-tab', self::$currentIndex), 'autocompleteList' => rtrim($autocomplete_list, ' ,') . '];', 'showTypeModules' => $this->filter_configuration['PS_SHOW_TYPE_MODULES_' . (int) $this->id_employee], 'showCountryModules' => $this->filter_configuration['PS_SHOW_COUNTRY_MODULES_' . (int) $this->id_employee], 'showInstalledModules' => $this->filter_configuration['PS_SHOW_INSTALLED_MODULES_' . (int) $this->id_employee], 'showEnabledModules' => $this->filter_configuration['PS_SHOW_ENABLED_MODULES_' . (int) $this->id_employee], 'nameCountryDefault' => Country::getNameById($this->context->language->id, Configuration::get('PS_COUNTRY_DEFAULT')), 'isoCountryDefault' => $this->iso_default_country, 'categoryFiltered' => $category_filtered, 'modules' => $modules, 'nb_modules' => $this->nb_modules_total, 'nb_modules_favorites' => count($this->context->employee->favoriteModulesList()), 'nb_modules_installed' => $this->nb_modules_installed, 'nb_modules_uninstalled' => $this->nb_modules_total - $this->nb_modules_installed, 'nb_modules_activated' => $this->nb_modules_activated, 'nb_modules_unactivated' => $this->nb_modules_installed - $this->nb_modules_activated, 'list_modules_categories' => $cleaned_list, 'list_modules_authors' => $this->modules_authors, 'add_permission' => $this->access('add'), 'tab_modules_preferences' => $tab_modules_preferences, 'kpis' => $this->renderKpis(), 'module_name' => Tools::getValue('module_name'), 'page_header_toolbar_title' => $this->page_header_toolbar_title, 'page_header_toolbar_btn' => $this->page_header_toolbar_btn, 'modules_uri' => __PS_BASE_URI__ . basename(_PS_MODULE_DIR_), 'dont_filter' => $dont_filter, 'is_contributor' => (int) $this->context->cookie->is_contributor, 'maintenance_mode' => !(bool) Configuration::Get('PS_SHOP_ENABLE'), 'debug_mode' => (bool) _PS_MODE_DEV_); if ($this->logged_on_addons) { $tpl_vars['logged_on_addons'] = 1; $tpl_vars['username_addons'] = $this->context->cookie->username_addons; } $smarty->assign($tpl_vars); }
public function test_get_delegates_to_service_container() { ServiceLocator::setServiceContainerInstance(new Container()); $this->assertInstanceOf('\\PrestaShop\\PrestaShop\\Core\\Foundation\\IoC\\Container', ServiceLocator::get('\\PrestaShop\\PrestaShop\\Core\\Foundation\\IoC\\Container')); }
/** * Return available modules * * @param bool $use_config in order to use config.xml file in module dir * @return array Modules */ public static function getModulesOnDisk($use_config = false, $logged_on_addons = false, $id_employee = false) { global $_MODULES; // Init var $module_list = array(); $module_name_list = array(); $modules_name_to_cursor = array(); $errors = array(); // Get modules directory list and memory limit $modules_dir = Module::getModulesDirOnDisk(); $modules_installed = array(); $result = Db::getInstance()->executeS(' SELECT m.name, m.version, mp.interest, module_shop.enable_device FROM `' . _DB_PREFIX_ . 'module` m ' . Shop::addSqlAssociation('module', 'm') . ' LEFT JOIN `' . _DB_PREFIX_ . 'module_preference` mp ON (mp.`module` = m.`name` AND mp.`id_employee` = ' . (int) $id_employee . ')'); foreach ($result as $row) { $modules_installed[$row['name']] = $row; } foreach ($modules_dir as $module) { $module_errors = array(); if (Module::useTooMuchMemory()) { $module_errors[] = Tools::displayError('All modules cannot be loaded due to memory limit restrictions, please increase your memory_limit value on your server configuration'); break; } $iso = substr(Context::getContext()->language->iso_code, 0, 2); // Check if config.xml module file exists and if it's not outdated if ($iso == 'en') { $config_file = _PS_MODULE_DIR_ . $module . '/config.xml'; } else { $config_file = _PS_MODULE_DIR_ . $module . '/config_' . $iso . '.xml'; } $xml_exist = file_exists($config_file); $need_new_config_file = $xml_exist ? @filemtime($config_file) < @filemtime(_PS_MODULE_DIR_ . $module . '/' . $module . '.php') : true; // If config.xml exists and that the use config flag is at true if ($use_config && $xml_exist && !$need_new_config_file) { // Load config.xml libxml_use_internal_errors(true); $xml_module = @simplexml_load_file($config_file); if (!$xml_module) { $module_errors[] = Tools::displayError(sprintf('%1s could not be loaded.', $config_file)); break; } foreach (libxml_get_errors() as $error) { $module_errors[] = '[' . $module . '] ' . Tools::displayError('Error found in config file:') . ' ' . htmlentities($error->message); } libxml_clear_errors(); // If no errors in Xml, no need instand and no need new config.xml file, we load only translations if (!count($module_errors) && (int) $xml_module->need_instance == 0) { $file = _PS_MODULE_DIR_ . $module . '/' . Context::getContext()->language->iso_code . '.php'; if (Tools::file_exists_cache($file) && (include_once $file)) { if (isset($_MODULE) && is_array($_MODULE)) { $_MODULES = !empty($_MODULES) ? array_merge($_MODULES, $_MODULE) : $_MODULE; } } $item = new stdClass(); $item->id = 0; $item->warning = ''; foreach ($xml_module as $k => $v) { $item->{$k} = (string) $v; } $item->displayName = stripslashes(Translate::getModuleTranslation((string) $xml_module->name, Module::configXmlStringFormat($xml_module->displayName), (string) $xml_module->name)); $item->description = stripslashes(Translate::getModuleTranslation((string) $xml_module->name, Module::configXmlStringFormat($xml_module->description), (string) $xml_module->name)); $item->author = stripslashes(Translate::getModuleTranslation((string) $xml_module->name, Module::configXmlStringFormat($xml_module->author), (string) $xml_module->name)); $item->author_uri = isset($xml_module->author_uri) && $xml_module->author_uri ? stripslashes($xml_module->author_uri) : false; if (isset($xml_module->confirmUninstall)) { $item->confirmUninstall = Translate::getModuleTranslation((string) $xml_module->name, html_entity_decode(Module::configXmlStringFormat($xml_module->confirmUninstall)), (string) $xml_module->name); } $item->active = 0; $item->onclick_option = false; $item->trusted = Module::isModuleTrusted($item->name); $module_list[$item->name . '_disk'] = $item; $module_name_list[] = '\'' . pSQL($item->name) . '\''; $modules_name_to_cursor[Tools::strtolower(strval($item->name))] = $item; } } // If use config flag is at false or config.xml does not exist OR need instance OR need a new config.xml file if (!$use_config || !$xml_exist || isset($xml_module->need_instance) && (int) $xml_module->need_instance == 1 || $need_new_config_file) { // If class does not exists, we include the file if (!class_exists($module, false)) { // Get content from php file $file_path = _PS_MODULE_DIR_ . $module . '/' . $module . '.php'; $file = trim(file_get_contents(_PS_MODULE_DIR_ . $module . '/' . $module . '.php')); if (substr($file, 0, 5) == '<?php') { $file = substr($file, 5); } if (substr($file, -2) == '?>') { $file = substr($file, 0, -2); } // We check any parse error before including the file. // If (false) is a trick to not load the class with "eval". // This way require_once will works correctly // But namespace and use statements need to be removed $content = preg_replace('/\\n[\\s\\t]*?use\\s.*?;/', '', $file); $content = preg_replace('/\\n[\\s\\t]*?namespace\\s.*?;/', '', $content); try { if (substr(`php -l {$file_path}`, 0, 16) == 'No syntax errors' || eval('if (false){ ' . $content . ' }') !== false) { require_once _PS_MODULE_DIR_ . $module . '/' . $module . '.php'; } else { throw new ParseError("Parse error"); } } catch (ParseError $e) { $errors[] = sprintf(Tools::displayError('%1$s (parse error in %2$s)'), $module, substr($file_path, strlen(_PS_ROOT_DIR_))); } preg_match('/\\n[\\s\\t]*?namespace\\s.*?;/', $file, $ns); if (!empty($ns)) { $ns = preg_replace('/\\n[\\s\\t]*?namespace\\s/', '', $ns[0]); $ns = rtrim($ns, ';'); $module = $ns . '\\' . $module; } } // If class exists, we just instanciate it if (class_exists($module, false)) { try { $tmp_module = \PrestaShop\PrestaShop\Adapter\ServiceLocator::get($module); $item = new stdClass(); $item->id = (int) $tmp_module->id; $item->warning = $tmp_module->warning; $item->name = $tmp_module->name; $item->version = $tmp_module->version; $item->tab = $tmp_module->tab; $item->displayName = $tmp_module->displayName; $item->description = stripslashes($tmp_module->description); $item->author = $tmp_module->author; $item->author_uri = isset($tmp_module->author_uri) && $tmp_module->author_uri ? $tmp_module->author_uri : false; $item->limited_countries = $tmp_module->limited_countries; $item->parent_class = get_parent_class($module); $item->is_configurable = $tmp_module->is_configurable = method_exists($tmp_module, 'getContent') ? 1 : 0; $item->need_instance = isset($tmp_module->need_instance) ? $tmp_module->need_instance : 0; $item->active = $tmp_module->active; $item->trusted = Module::isModuleTrusted($tmp_module->name); $item->currencies = isset($tmp_module->currencies) ? $tmp_module->currencies : null; $item->currencies_mode = isset($tmp_module->currencies_mode) ? $tmp_module->currencies_mode : null; $item->confirmUninstall = isset($tmp_module->confirmUninstall) ? html_entity_decode($tmp_module->confirmUninstall) : null; $item->description_full = stripslashes($tmp_module->description_full); $item->additional_description = isset($tmp_module->additional_description) ? stripslashes($tmp_module->additional_description) : null; $item->compatibility = isset($tmp_module->compatibility) ? (array) $tmp_module->compatibility : null; $item->nb_rates = isset($tmp_module->nb_rates) ? (array) $tmp_module->nb_rates : null; $item->avg_rate = isset($tmp_module->avg_rate) ? (array) $tmp_module->avg_rate : null; $item->badges = isset($tmp_module->badges) ? (array) $tmp_module->badges : null; $item->url = isset($tmp_module->url) ? $tmp_module->url : null; $item->onclick_option = method_exists($module, 'onclickOption') ? true : false; if ($item->onclick_option) { $href = Context::getContext()->link->getAdminLink('Module', true) . '&module_name=' . $tmp_module->name . '&tab_module=' . $tmp_module->tab; $item->onclick_option_content = array(); $option_tab = array('desactive', 'reset', 'configure', 'delete'); foreach ($option_tab as $opt) { $item->onclick_option_content[$opt] = $tmp_module->onclickOption($opt, $href); } } $module_list[$item->name . '_disk'] = $item; if (!$xml_exist || $need_new_config_file) { self::$_generate_config_xml_mode = true; $tmp_module->_generateConfigXml(); self::$_generate_config_xml_mode = false; } unset($tmp_module); } catch (Exception $e) { } } else { $module_errors[] = sprintf(Tools::displayError('%1$s (class missing in %2$s)'), $module, substr($file_path, strlen(_PS_ROOT_DIR_))); } } $errors = array_merge($errors, $module_errors); } // Get modules information from database if (!empty($module_name_list)) { $list = Shop::getContextListShopID(); $sql = 'SELECT m.id_module, m.name, ( SELECT COUNT(*) FROM ' . _DB_PREFIX_ . 'module_shop ms WHERE m.id_module = ms.id_module AND ms.id_shop IN (' . implode(',', $list) . ') ) as total FROM ' . _DB_PREFIX_ . 'module m WHERE LOWER(m.name) IN (' . Tools::strtolower(implode(',', $module_name_list)) . ')'; $results = Db::getInstance()->executeS($sql); foreach ($results as $result) { if (isset($modules_name_to_cursor[Tools::strtolower($result['name'])])) { $module_cursor = $modules_name_to_cursor[Tools::strtolower($result['name'])]; $module_cursor->id = (int) $result['id_module']; $module_cursor->active = $result['total'] == count($list) ? 1 : 0; } } } // Get Default Country Modules and customer module $files_list = array(array('type' => 'addonsNative', 'file' => _PS_ROOT_DIR_ . self::CACHE_FILE_DEFAULT_COUNTRY_MODULES_LIST, 'loggedOnAddons' => 0), array('type' => 'addonsMustHave', 'file' => _PS_ROOT_DIR_ . self::CACHE_FILE_MUST_HAVE_MODULES_LIST, 'loggedOnAddons' => 0), array('type' => 'addonsBought', 'file' => _PS_ROOT_DIR_ . self::CACHE_FILE_CUSTOMER_MODULES_LIST, 'loggedOnAddons' => 1)); foreach ($files_list as $f) { if (file_exists($f['file']) && ($f['loggedOnAddons'] == 0 || $logged_on_addons)) { if (Module::useTooMuchMemory()) { $errors[] = Tools::displayError('All modules cannot be loaded due to memory limit restrictions, please increase your memory_limit value on your server configuration'); break; } $file = $f['file']; $content = Tools::file_get_contents($file); $xml = @simplexml_load_string($content, null, LIBXML_NOCDATA); if ($xml && isset($xml->module)) { foreach ($xml->module as $modaddons) { $flag_found = 0; foreach ($module_list as $k => &$m) { if (Tools::strtolower($m->name) == Tools::strtolower($modaddons->name) && !isset($m->available_on_addons)) { $flag_found = 1; if ($m->version != $modaddons->version && version_compare($m->version, $modaddons->version) === -1) { $module_list[$k]->version_addons = $modaddons->version; } } } if ($flag_found == 0) { $item = new stdClass(); $item->id = 0; $item->warning = ''; $item->type = strip_tags((string) $f['type']); $item->name = strip_tags((string) $modaddons->name); $item->version = strip_tags((string) $modaddons->version); $item->tab = strip_tags((string) $modaddons->tab); $item->displayName = strip_tags((string) $modaddons->displayName); $item->description = stripslashes(strip_tags((string) $modaddons->description)); $item->description_full = stripslashes(strip_tags((string) $modaddons->description_full)); $item->author = strip_tags((string) $modaddons->author); $item->limited_countries = array(); $item->parent_class = ''; $item->onclick_option = false; $item->is_configurable = 0; $item->need_instance = 0; $item->not_on_disk = 1; $item->available_on_addons = 1; $item->trusted = Module::isModuleTrusted($item->name); $item->active = 0; $item->description_full = stripslashes($modaddons->description_full); $item->additional_description = isset($modaddons->additional_description) ? stripslashes($modaddons->additional_description) : null; $item->compatibility = isset($modaddons->compatibility) ? (array) $modaddons->compatibility : null; $item->nb_rates = isset($modaddons->nb_rates) ? (array) $modaddons->nb_rates : null; $item->avg_rate = isset($modaddons->avg_rate) ? (array) $modaddons->avg_rate : null; $item->badges = isset($modaddons->badges) ? (array) $modaddons->badges : null; $item->url = isset($modaddons->url) ? $modaddons->url : null; if (isset($item->description_full) && trim($item->description_full) != '') { $item->show_quick_view = true; } if (isset($modaddons->img)) { $item->image = Module::copyModAddonsImg($modaddons); } if ($item->type == 'addonsMustHave') { $item->addons_buy_url = strip_tags((string) $modaddons->url); $prices = (array) $modaddons->price; $id_default_currency = Configuration::get('PS_CURRENCY_DEFAULT'); foreach ($prices as $currency => $price) { if ($id_currency = Currency::getIdByIsoCode($currency)) { $item->price = (double) $price; $item->id_currency = (int) $id_currency; if ($id_default_currency == $id_currency) { break; } } } } $module_list[$item->name . '_feed'] = $item; } if (isset($module_list[$modaddons->name . '_disk'])) { $module_list[$modaddons->name . '_disk']->description_full = stripslashes(strip_tags((string) $modaddons->description_full)); $module_list[$modaddons->name . '_disk']->additional_description = stripslashes(strip_tags((string) $modaddons->additional_description)); $module_list[$modaddons->name . '_disk']->image = Module::copyModAddonsImg($modaddons); $module_list[$modaddons->name . '_disk']->show_quick_view = true; } } } } } foreach ($module_list as $key => &$module) { if (defined('_PS_HOST_MODE_') && in_array($module->name, self::$hosted_modules_blacklist)) { unset($module_list[$key]); } elseif (isset($modules_installed[$module->name])) { $module->installed = true; $module->database_version = $modules_installed[$module->name]['version']; $module->interest = $modules_installed[$module->name]['interest']; $module->enable_device = $modules_installed[$module->name]['enable_device']; } else { $module->installed = false; $module->database_version = 0; $module->interest = 0; } } usort($module_list, create_function('$a,$b', 'return strnatcasecmp($a->displayName, $b->displayName);')); if ($errors) { if (!isset(Context::getContext()->controller) && !Context::getContext()->controller->controller_name) { echo '<div class="alert error"><h3>' . Tools::displayError('The following module(s) could not be loaded') . ':</h3><ol>'; foreach ($errors as $error) { echo '<li>' . $error . '</li>'; } echo '</ol></div>'; } else { foreach ($errors as $error) { Context::getContext()->controller->errors[] = $error; } } } return $module_list; }
/** * Builds the object * * @param int|null $id If specified, loads and existing object from DB (optional). * @param int|null $id_lang Required if object is multilingual (optional). * @param int|null $id_shop ID shop for objects with multishop tables. * * @throws PrestaShopDatabaseException * @throws PrestaShopException */ public function __construct($id = null, $id_lang = null, $id_shop = null) { $class_name = get_class($this); if (!isset(ObjectModel::$loaded_classes[$class_name])) { $this->def = ObjectModel::getDefinition($class_name); $this->setDefinitionRetrocompatibility(); if (!Validate::isTableOrIdentifier($this->def['primary']) || !Validate::isTableOrIdentifier($this->def['table'])) { throw new PrestaShopException('Identifier or table format not valid for class ' . $class_name); } ObjectModel::$loaded_classes[$class_name] = get_object_vars($this); } else { foreach (ObjectModel::$loaded_classes[$class_name] as $key => $value) { $this->{$key} = $value; } } if ($id_lang !== null) { $this->id_lang = Language::getLanguage($id_lang) !== false ? $id_lang : Configuration::get('PS_LANG_DEFAULT'); } if ($id_shop && $this->isMultishop()) { $this->id_shop = (int) $id_shop; $this->get_shop_from_context = false; } if ($this->isMultishop() && !$this->id_shop) { $this->id_shop = Context::getContext()->shop->id; } if ($id) { $entity_mapper = \PrestaShop\PrestaShop\Adapter\ServiceLocator::get("\\PrestaShop\\PrestaShop\\Adapter\\EntityMapper"); $entity_mapper->load($id, $id_lang, $this, $this->def, $this->id_shop, self::$cache_objects); } }
/** * This method allows to fulfill the object order_invoice with sales figures */ protected function setInvoiceDetails($order_invoice) { if (!$order_invoice || !is_object($order_invoice)) { return; } $address = new Address((int) $this->{Configuration::get('PS_TAX_ADDRESS_TYPE')}); $carrier = new Carrier((int) $this->id_carrier); $tax_calculator = Configuration::get('PS_ATCP_SHIPWRAP') ? \PrestaShop\PrestaShop\Adapter\ServiceLocator::get('AverageTaxOfProductsTaxCalculator')->setIdOrder($this->id) : $carrier->getTaxCalculator($address); $order_invoice->total_discount_tax_excl = $this->total_discounts_tax_excl; $order_invoice->total_discount_tax_incl = $this->total_discounts_tax_incl; $order_invoice->total_paid_tax_excl = $this->total_paid_tax_excl; $order_invoice->total_paid_tax_incl = $this->total_paid_tax_incl; $order_invoice->total_products = $this->total_products; $order_invoice->total_products_wt = $this->total_products_wt; $order_invoice->total_shipping_tax_excl = $this->total_shipping_tax_excl; $order_invoice->total_shipping_tax_incl = $this->total_shipping_tax_incl; $order_invoice->shipping_tax_computation_method = $tax_calculator->computation_method; $order_invoice->total_wrapping_tax_excl = $this->total_wrapping_tax_excl; $order_invoice->total_wrapping_tax_incl = $this->total_wrapping_tax_incl; $order_invoice->save(); if (Configuration::get('PS_ATCP_SHIPWRAP')) { $wrapping_tax_calculator = \PrestaShop\PrestaShop\Adapter\ServiceLocator::get('AverageTaxOfProductsTaxCalculator')->setIdOrder($this->id); } else { $wrapping_tax_manager = TaxManagerFactory::getManager($address, (int) Configuration::get('PS_GIFT_WRAPPING_TAX_RULES_GROUP')); $wrapping_tax_calculator = $wrapping_tax_manager->getTaxCalculator(); } $order_invoice->saveCarrierTaxCalculator($tax_calculator->getTaxesAmount($order_invoice->total_shipping_tax_excl, $order_invoice->total_shipping_tax_incl, _PS_PRICE_COMPUTE_PRECISION_, $this->round_mode)); $order_invoice->saveWrappingTaxCalculator($wrapping_tax_calculator->getTaxesAmount($order_invoice->total_wrapping_tax_excl, $order_invoice->total_wrapping_tax_incl, _PS_PRICE_COMPUTE_PRECISION_, $this->round_mode)); }