<?php /** * TNT OFFICIAL MODULE FOR PRESTASHOP. * * @author GFI Informatique <www.gfi.fr> * @copyright 2016-2017 GFI Informatique, 2016-2017 TNT * @license https://opensource.org/licenses/MIT MIT License */ require_once _PS_MODULE_DIR_.'tntofficiel/tntofficiel.php'; require_once _PS_MODULE_DIR_.'tntofficiel/libraries/TNTOfficiel_Logger.php'; require_once _PS_MODULE_DIR_.'tntofficiel/libraries/TNTOfficiel_Debug.php'; require_once _PS_MODULE_DIR_.'tntofficiel/libraries/TNTOfficiel_Carrier.php'; class TNTOfficiel_Install { /** @var array */ public static $arrHookList = array( // Header 'displayBackOfficeHeader', 'actionAdminControllerSetMedia', 'displayHeader', // Front-Office display carrier. 'displayBeforeCarrier', 'displayCarrierList', // Front-Office display Order created. //'displayOrderConfirmation', // Front-Office order detail. 'displayOrderDetail', // Back-Office order detail. 'displayAdminOrder', // Carrier updated. 'actionCarrierUpdate', // Order status before changed. 'actionOrderStatusUpdate', 'actionOrderStatusPostUpdate', // Order created. 'actionValidateOrder', // //'actionDeliveryPriceByWeight', //'actionDeliveryPriceByPrice', // //'displayPayment', //'displayPaymentReturn', //'actionPaymentConfirmation', //'actionCartSave', //'actionCarrierProcess', // //'actionObjectAddBefore', //'actionObjectAddAfter', //'actionObjectUpdateBefore', //'actionObjectUpdateAfter', //'actionObjectDeleteBefore', //'actionObjectDeleteAfter', //'actionObjectOrderAddBefore', //'actionObjectOrderAddAfter', //'actionObjectOrderUpdateBefore', //'actionObjectOrderUpdateAfter', //'actionObjectOrderDeleteBefore', //'actionObjectOrderDeleteAfter', ); /** @var array */ public static $arrConfigUpdateDeleteList = array( //'TNT_CARRIER_ID' Carrier ID is created on installCarrier, then preserved. //'TNT_GOOGLE_MAP_API_KEY' Google Map API Key is created on config form submit, then preserved. // Authentication information. 'TNT_CARRIER_USERNAME' => '', 'TNT_CARRIER_ACCOUNT' => '', 'TNT_CARRIER_PASSWORD' => '', // Is Authentication information validated. 'TNT_CARRIER_ACTIVATED' => false, // Show pickup number in AdminOrdersController. 'TNT_CARRIER_PICKUP_NUMBER_SHOW' => '', // Max weight (kg) per parcel. 'TNT_CARRIER_MAX_PACKAGE_B2B' => '30.0', 'TNT_CARRIER_MAX_PACKAGE_B2C' => '20.0', // Comma separated list of item cart attributes. 'TNT_CARRIER_ASSOCIATIONS' => '', // MiddleWare JSON-RPC URL. 'TNT_CARRIER_MIDDLEWARE_URL' => 'https://solutions-ecommerce.tnt.fr/api/handler', // MiddleWare IFrame URL. 'TNT_CARRIER_MIDDLEWARE_SHORT_URL' => 'https://solutions-ecommerce.tnt.fr/login', 'TNT_CARRIER_SOAP_WSDL' => 'https://www.tnt.fr/service/?wsdl', // <TABLE>.<ROW> for ./libraries/TNTOfficiel_Address.php // DB fields used as default values for delivery address extra data. 'TNT_CARRIER_ADDRESS_EMAIL' => 'customer.email', 'TNT_CARRIER_ADDRESS_PHONE' => 'address.phone_mobile', 'TNT_CARRIER_ADDRESS_BUILDING' => '', 'TNT_CARRIER_ADDRESS_INTERCOM' => '', 'TNT_CARRIER_ADDRESS_FLOOR' => '' ); /** @var array */ public static $arrTemplateOverrideList = array( array( 'fileName' => 'view.tpl', 'directorySrc' => 'views/templates/admin/override/controllers/admin/templates/orders/helpers/view/', 'directoryDst' => 'controllers/admin/templates/orders/helpers/view/', ), ); /** * Prevent Construct. */ final private function __construct() { trigger_error(sprintf('%s() %s is static.', __FUNCTION__, get_class($this)), E_USER_ERROR); } /** * Create a new directory with default index.php file. * * @param $arrArgDirectoryList an array of directories. */ public static function makeModuleDir($arrArgDirectoryList) { $strIndexFileContent = <<<PHP <?php header("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); header("Last-Modified: ".gmdate("D, d M Y H:i:s")." GMT"); header("Cache-Control: no-store, no-cache, must-revalidate"); header("Cache-Control: post-check=0, pre-check=0", false); header("Pragma: no-cache"); header("Location: ../"); exit; PHP; foreach ($arrArgDirectoryList as $strDirectory) { // If directory do not exist, create it. if (!is_dir(_PS_MODULE_DIR_.$strDirectory)) { if (!mkdir(_PS_MODULE_DIR_.$strDirectory, 0777, true)) { return false; } } $rscFile = fopen(_PS_MODULE_DIR_.$strDirectory.'index.php', 'w'); if ($rscFile === false) { return false; } fwrite($rscFile, $strIndexFileContent); fclose($rscFile); } return true; } public static function clearCache() { // Clear Smarty cache. Tools::clearSmartyCache(); // Clear XML cache ('/config/xml/'). Tools::clearXMLCache(); // Clear current theme cache (/themes/<THEME>/cache/'). Media::clearCache(); // Clear class index cache for PrestaShopAutoload ('/cache/class_index.php'). Tools::generateIndex(); /* // Check cache '/cache/class_index.php' $objPSAutoload = PrestaShopAutoload::getInstance(); if ( !$objPSAutoload->_include_override_path || //!Configuration::get('PS_DISABLE_OVERRIDES') || $objPSAutoload->getClassPath('AdminOrdersController') !== 'override/controllers/admin/AdminOrdersController.php' || $objPSAutoload->getClassPath('Order') !== 'override/classes/order/Order.php' || $objPSAutoload->getClassPath('OrderHistory') !== 'override/classes/order/OrderHistory.php' ) { // Warning !! } */ } /** * Update settings fields. * * @return bool */ public static function updateSettings() { TNTOfficiel_Debug::log(array('msg' => '>>', 'file' => __FILE__, 'line' => __LINE__)); $boolUpdated = true; foreach (TNTOfficiel_Install::$arrConfigUpdateDeleteList as $strCfgName => $mxdValue) { $boolUpdated = $boolUpdated && Configuration::updateValue($strCfgName, $mxdValue); } return $boolUpdated; } /** * Delete settings fields. * * @return bool */ public static function deleteSettings() { TNTOfficiel_Debug::log(array('msg' => '>>', 'file' => __FILE__, 'line' => __LINE__)); $boolDeleted = true; foreach (TNTOfficiel_Install::$arrConfigUpdateDeleteList as $strCfgName => $mxdValue) { $boolDeleted = $boolDeleted && Configuration::deleteByName($strCfgName); } return $boolDeleted; } /** * Creates the admin Tab. * * @param $arrArgTabNameLang Module name displayed. * * @return bool */ public static function createTab($arrArgTabNameLang) { TNTOfficiel_Debug::log(array('msg' => '>>', 'file' => __FILE__, 'line' => __LINE__)); // Creates the parent tab $parentTab = new Tab(); $parentTab->class_name = 'AdminTNTOfficiel'; $parentTab->name = $arrArgTabNameLang; $parentTab->module = TNTOfficiel::MODULE_NAME; $parentTab->id_parent = 0; // TODO : AdminParentShipping as parent ? //$parentTab->id_parent = Tab::getIdFromClassName('AdminParentShipping'); $boolResult = (bool)($parentTab->add()); /* if (version_compare(_PS_VERSION_, '1.6', '<')) { $childrenTab = new Tab(); $childrenTab->class_name = 'AdminTNTOfficiel'; $childrenTab->name = $arrTabNameLang; $childrenTab->module = $strModuleName; $childrenTab->id_parent = Tab::getIdFromClassName('AdminTNTOfficiel'); $boolResult15 = (bool)($childrenTab->add()); return $boolResult && $boolResult15; } */ return $boolResult; } /** * Delete the admin Tab. * * @return bool */ public static function deleteTab() { TNTOfficiel_Debug::log(array('msg' => '>>', 'file' => __FILE__, 'line' => __LINE__)); $objTabsPSCollection = Tab::getCollectionFromModule(TNTOfficiel::MODULE_NAME)->getAll(); foreach ($objTabsPSCollection as $tab) { if (!$tab->delete()) { return false; } } return true; } /** * Update table. * * @return bool */ public static function upgradeTables_1_2_20() { TNTOfficiel_Debug::log(array('msg' => '>>', 'file' => __FILE__, 'line' => __LINE__)); $strTablePrefix = _DB_PREFIX_; // Test if table tnt_extra_address_data exist. $strSQLTableExtraExist = <<<SQL SHOW TABLES LIKE '${strTablePrefix}tnt_extra_address_data'; SQL; // Test if table tnt_order exist. $strSQLTableOrderExist = <<<SQL SHOW TABLES LIKE '${strTablePrefix}tnt_order'; SQL; // Test if table tnt_parcel exist. $strSQLTableParcelExist = <<<SQL SHOW TABLES LIKE '${strTablePrefix}tnt_parcel'; SQL; // Dop unused log table. $strSQLTableLogDropTable = <<<SQL DROP TABLE IF EXISTS `${strTablePrefix}tnt_log`; SQL; // Add column to tnt_extra_address_data table. $strSQLTableExtraAddColumns = <<<SQL ALTER TABLE `${strTablePrefix}tnt_extra_address_data` ADD COLUMN `carrier_code` VARCHAR(64) NOT NULL DEFAULT '' AFTER `id_address`, ADD COLUMN `carrier_label` VARCHAR(255) NOT NULL DEFAULT '' AFTER `carrier_code`, ADD COLUMN `delivery_point` TEXT NULL AFTER `carrier_label`, ADD COLUMN `delivery_price` DECIMAL(20,6) NOT NULL DEFAULT '0.000000' AFTER `delivery_point`; SQL; // Rename and change existing columns to tnt_extra_address_data table. $strSQLTableExtraChangeColumns = <<<SQL ALTER TABLE `${strTablePrefix}tnt_extra_address_data` CHANGE COLUMN `id_extra_address_data` `id_tntofficiel_cart` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT FIRST, CHANGE COLUMN `id_address` `id_cart` INT(10) UNSIGNED NOT NULL AFTER `id_tntofficiel_cart`, CHANGE COLUMN `email` `customer_email` VARCHAR(128) NOT NULL DEFAULT '' AFTER `delivery_price`, CHANGE COLUMN `mobile_phone` `customer_mobile` VARCHAR(32) NOT NULL DEFAULT '' AFTER `customer_email`, CHANGE COLUMN `building_number` `address_building` VARCHAR(16) NOT NULL DEFAULT '' AFTER `customer_mobile`, CHANGE COLUMN `intercom_code` `address_accesscode` VARCHAR(16) NOT NULL DEFAULT '' AFTER `address_building`, CHANGE COLUMN `floor` `address_floor` VARCHAR(16) NOT NULL DEFAULT '' AFTER `address_accesscode`; SQL; // Rename tnt_extra_address_data table to tntofficiel_cart. $strSQLTableExtraRenameTable = <<<SQL ALTER TABLE `${strTablePrefix}tnt_extra_address_data` RENAME `${strTablePrefix}tntofficiel_cart`; SQL; // Rename and change existing columns to tnt_order table. $strSQLTableOrderChangeColumns = <<<SQL ALTER TABLE `${strTablePrefix}tnt_order` CHANGE COLUMN `id_tnt_order` `id_tntofficiel_order` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT FIRST, CHANGE COLUMN `id_order` `id_order` INT(10) UNSIGNED NOT NULL AFTER `id_tntofficiel_order`, CHANGE COLUMN `tnt_product_code` `carrier_code` VARCHAR(64) NOT NULL DEFAULT '' AFTER `id_order`, CHANGE COLUMN `tnt_product_label` `carrier_label` VARCHAR(255) NOT NULL DEFAULT '' AFTER `carrier_code`, CHANGE COLUMN `tnt_xett` `carrier_xett` VARCHAR(5) NOT NULL DEFAULT '' AFTER `carrier_label`, CHANGE COLUMN `tnt_pex` `carrier_pex` VARCHAR(4) NOT NULL DEFAULT '' AFTER `carrier_xett`, CHANGE COLUMN `bt` `bt_filename` VARCHAR(64) NOT NULL DEFAULT '' AFTER `carrier_pex`, CHANGE COLUMN `shipped` `is_shipped` TINYINT(1) NOT NULL DEFAULT '0' AFTER `bt_filename`, CHANGE COLUMN `previous_state` `previous_state` INT(10) UNSIGNED NULL DEFAULT NULL AFTER `is_shipped`, CHANGE COLUMN `pickup_number` `pickup_number` VARCHAR(50) NOT NULL DEFAULT '' AFTER `previous_state`, CHANGE COLUMN `shipping_date` `shipping_date` VARCHAR(10) NOT NULL DEFAULT '' AFTER `pickup_number`, CHANGE COLUMN `due_date` `due_date` VARCHAR(10) NOT NULL DEFAULT '' AFTER `shipping_date`, CHANGE COLUMN `start_date` `start_date` VARCHAR(10) NOT NULL DEFAULT '' AFTER `due_date`; SQL; // Rename tnt_order table to tntofficiel_order. $strSQLTableOrderRenameTable = <<<SQL ALTER TABLE `${strTablePrefix}tnt_order` RENAME `${strTablePrefix}tntofficiel_order`; SQL; // Change columns. $strSQLTableParcelChangeColumns = <<<SQL ALTER TABLE `${strTablePrefix}tnt_parcels` CHANGE COLUMN `id_parcel` `id_parcel` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT FIRST, CHANGE COLUMN `id_order` `id_order` INT(10) UNSIGNED NOT NULL AFTER `id_parcel`, CHANGE COLUMN `weight` `weight` DECIMAL(20,6) NOT NULL DEFAULT '0.000000'; SQL; // Rename tnt_parcels table to tntofficiel_order_parcels. $strSQLTableParcelRenameTable = <<<SQL ALTER TABLE `${strTablePrefix}tnt_parcels` RENAME `${strTablePrefix}tntofficiel_order_parcels`; SQL; $objDB = Db::getInstance(); // Delete table log. if (!$objDB->execute($strSQLTableLogDropTable)) { return false; } // Update table tnt_extra_address_data if exist. $arrDBResult = $objDB->executeS($strSQLTableExtraExist); if(count($arrDBResult) === 1) { if (!$objDB->execute($strSQLTableExtraAddColumns) || !$objDB->execute($strSQLTableExtraChangeColumns) || !$objDB->execute($strSQLTableExtraRenameTable) ) { return false; } } // Update tnt_order if exist. $arrDBResult = $objDB->executeS($strSQLTableOrderExist); if(count($arrDBResult) === 1) { if (!$objDB->execute($strSQLTableOrderChangeColumns) || !$objDB->execute($strSQLTableOrderRenameTable) ) { return false; } } // Update tnt_parcel if exist. $arrDBResult = $objDB->executeS($strSQLTableParcelExist); if(count($arrDBResult) === 1) { if (!$objDB->execute($strSQLTableParcelChangeColumns) || !$objDB->execute($strSQLTableParcelRenameTable) ) { return false; } } return true; } /** * Creates the tables needed by the module. * * @return bool */ public static function createTables() { TNTOfficiel_Debug::log(array('msg' => '>>', 'file' => __FILE__, 'line' => __LINE__)); // Update if required. TNTOfficiel_Install::upgradeTables_1_2_20(); $strTablePrefix = _DB_PREFIX_; $strTableEngine = _MYSQL_ENGINE_; // Create tntofficiel_cart table. $strSQLCreateCart = <<<SQL CREATE TABLE IF NOT EXISTS `${strTablePrefix}tntofficiel_cart` ( `id_tntofficiel_cart` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, `id_cart` INT(10) UNSIGNED NOT NULL, `carrier_code` VARCHAR(64) NOT NULL DEFAULT '', `carrier_label` VARCHAR(255) NOT NULL DEFAULT '', `delivery_point` TEXT NULL, `delivery_price` DECIMAL(20,6) NOT NULL DEFAULT '0.000000', `customer_email` VARCHAR(128) NOT NULL DEFAULT '', `customer_mobile` VARCHAR(32) NOT NULL DEFAULT '', `address_building` VARCHAR(16) NOT NULL DEFAULT '', `address_accesscode` VARCHAR(16) NOT NULL DEFAULT '', `address_floor` VARCHAR(16) NOT NULL DEFAULT '', PRIMARY KEY (`id_tntofficiel_cart`) ) ENGINE = ${strTableEngine} DEFAULT CHARSET='utf8' COLLATE='utf8_general_ci'; SQL; // Create tntofficiel_order table. $strSQLCreateOrder = <<<SQL CREATE TABLE IF NOT EXISTS `${strTablePrefix}tntofficiel_order` ( `id_tntofficiel_order` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, `id_order` INT(10) UNSIGNED NOT NULL, `carrier_code` VARCHAR(64) NOT NULL DEFAULT '', `carrier_label` VARCHAR(255) NOT NULL DEFAULT '', `carrier_xett` VARCHAR(5) NOT NULL DEFAULT '', `carrier_pex` VARCHAR(4) NOT NULL DEFAULT '', `bt_filename` VARCHAR(64) NOT NULL DEFAULT '', `is_shipped` TINYINT(1) NOT NULL DEFAULT '0', `previous_state` INT(10) UNSIGNED NULL DEFAULT NULL, `pickup_number` VARCHAR(50) NOT NULL DEFAULT '', `shipping_date` VARCHAR(10) NOT NULL DEFAULT '', -- DATETIME NOT NULL, `due_date` VARCHAR(10) NOT NULL DEFAULT '', `start_date` VARCHAR(10) NOT NULL DEFAULT '', PRIMARY KEY (`id_tntofficiel_order`) ) ENGINE = ${strTableEngine} DEFAULT CHARSET='utf8' COLLATE='utf8_general_ci'; SQL; // Create tntofficiel_order_parcels table. $strSQLCreateParcels = <<<SQL CREATE TABLE IF NOT EXISTS `${strTablePrefix}tntofficiel_order_parcels` ( `id_parcel` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, `id_order` INT(10) UNSIGNED NOT NULL, `weight` DECIMAL(20,6) NOT NULL DEFAULT '0.000000', `tracking_url` TEXT, `parcel_number` VARCHAR(16), `pdl` TEXT, PRIMARY KEY (`id_parcel`) ) ENGINE = ${strTableEngine} DEFAULT CHARSET='utf8' COLLATE='utf8_general_ci'; SQL; $objDB = Db::getInstance(); if (!$objDB->execute($strSQLCreateCart) || !$objDB->execute($strSQLCreateOrder) || !$objDB->execute($strSQLCreateParcels) ) { return false; } return true; } /** * Create or Restore an existing TNT carrier. * * @return bool */ public static function installCarrier() { TNTOfficiel_Debug::log(array('msg' => '>>', 'file' => __FILE__, 'line' => __LINE__)); // Try to undelete previously deleted carrier. $boolResult = TNTOfficiel_Carrier::undeleteGlobalCarrier(); // If not succeed. if (!$boolResult) { // Create a new one. $boolResult = TNTOfficiel_Carrier::createGlobalCarrier(); } return $boolResult; } /** * Add a template override in the override directory. * * @param $strArgModuleDir Module absolute Path. * @return array */ public static function overrideTemplates($strArgModuleDir) { TNTOfficiel_Debug::log(array('msg' => '>>', 'file' => __FILE__, 'line' => __LINE__)); $arrErrors = array(); foreach (TNTOfficiel_Install::$arrTemplateOverrideList as $arrTemplateOverride) { $strPathTemplateSrc = $strArgModuleDir.$arrTemplateOverride['directorySrc']; $strFileTemplateSrc = $strPathTemplateSrc.$arrTemplateOverride['fileName']; $strPathTemplateDst = _PS_OVERRIDE_DIR_.$arrTemplateOverride['directoryDst']; $strFileTemplateDst = $strPathTemplateDst.$arrTemplateOverride['fileName']; try { // Create directory if unexist. if (!is_dir($strPathTemplateDst)) { mkdir($strPathTemplateDst, 0777, true); } // Copy new template file. if (!copy($strFileTemplateSrc, $strFileTemplateDst)) { $arrErrors[] = sprintf(Tools::displayError('Impossible d\'installer la surcharge "%s"'), $arrTemplateOverride['fileName']); } } catch (Exception $objException) { $objFileLogger = new FileLogger(); $objFileLogger->setFilename(_PS_ROOT_DIR_.'/log/'.date('Ymd').'_tnt_exception.log'); $objFileLogger->logError($objException->getMessage()); $arrErrors[] = sprintf(Tools::displayError('Impossible d\'installer la surcharge "%s"'), $arrTemplateOverride['fileName']); } } return $arrErrors; } /** * Delete a template override in the override directory. * * @return array */ public static function unOverrideTemplates() { TNTOfficiel_Debug::log(array('msg' => '>>', 'file' => __FILE__, 'line' => __LINE__)); $arrErrors = array(); // Unoverride templates. foreach (TNTOfficiel_Install::$arrTemplateOverrideList as $arrTemplateOverride) { $strPathTemplateDst = _PS_OVERRIDE_DIR_.$arrTemplateOverride['directoryDst']; $strFileTemplateDst = $strPathTemplateDst.$arrTemplateOverride['fileName']; try { // Create directory if not found. if (!is_dir($strPathTemplateDst)) { mkdir($strPathTemplateDst, 0777, true); } // Delete previous template file if exist. if (file_exists($strFileTemplateDst)) { if(!unlink($strFileTemplateDst)) { $arrErrors[] = sprintf(Tools::displayError('Impossible de supprimer la surcharge "%s"'), $arrTemplateOverride['fileName']); } } } catch (Exception $objException) { $objFileLogger = new FileLogger(); $objFileLogger->setFilename(_PS_ROOT_DIR_.'/log/'.date('Ymd').'_tnt_exception.log'); $objFileLogger->logError($objException->getMessage()); $arrErrors[] = sprintf(Tools::displayError('Impossible de supprimer la surcharge "%s"'), $arrTemplateOverride['fileName']); } } return $arrErrors; } }