From f9ded57547b93e52a411efc630fbb61c69b8858c Mon Sep 17 00:00:00 2001 From: geraldbullard Date: Thu, 6 Nov 2014 17:25:31 -0500 Subject: [PATCH 01/11] fix for product categories box expansion with SEO URL's enabled --- catalog/includes/classes/category_tree.php | 4 +-- catalog/includes/functions/html_output.php | 17 +++++----- catalog/includes/modules/boxes/categories.php | 34 +++++++++++++++++-- .../modules/boxes/product_categories.php | 30 +++++++++++++++- 4 files changed, 71 insertions(+), 14 deletions(-) diff --git a/catalog/includes/classes/category_tree.php b/catalog/includes/classes/category_tree.php index fb7e82d87..7744b3940 100644 --- a/catalog/includes/classes/category_tree.php +++ b/catalog/includes/classes/category_tree.php @@ -247,8 +247,8 @@ function buildBranchArray($parent_id, $level = 0, $result = '') { } $result[] = array('id' => $category_link, - 'title' => str_repeat($this->spacer_string, $this->spacer_multiplier * $level) . $category['name'], - 'mode' => $category['mode']); + 'title' => str_repeat($this->spacer_string, $this->spacer_multiplier * $level) . $category['name'], + 'mode' => $category['mode']); if (isset($this->_data[$category_id]) && (($this->max_level == '0') || ($this->max_level > $level+1))) { if ($this->follow_cpath === true) { diff --git a/catalog/includes/functions/html_output.php b/catalog/includes/functions/html_output.php index ee0aae69e..81b8575f4 100644 --- a/catalog/includes/functions/html_output.php +++ b/catalog/includes/functions/html_output.php @@ -113,13 +113,14 @@ function lc_href_link($page = null, $parameters = null, $connection = 'NONSSL', $cat_ids = array(); // categories if ( (strpos($link, 'index.php') && strpos($link, 'cPath')) ) { - $cat_id = explode("_", substr($link, $cPathPos+6)); - if (count($cat_id) < 2) { - $cat_data = $lC_CategoryTree->getData($cat_id[0]); - $cat_ids = explode("_", substr($cat_data['query'], 6)); - } else { - $cat_ids = explode("_", substr($link, $cPathPos+6)); - } + //$cat_id = explode("_", substr($link, $cPathPos+6)); + //$r_cat_id = array_reverse($cat_id); + //if (count($cat_id) < 2) { + // $cat_data = $lC_CategoryTree->getData($r_cat_id[0]); + // $cat_ids = explode("_", substr($cat_data['query'], 6)); + //} else { + $cat_ids = explode("_", substr($link, $cPathPos+6)); + //} } // products if ( (strpos($link, 'products.php') && !strpos($link, 'featured_products') && !strpos($link, 'reviews') && !strpos($link, '?specials') && !strpos($link, '?new')) ) { @@ -162,7 +163,7 @@ function lc_href_link($page = null, $parameters = null, $connection = 'NONSSL', $cat_path .= strtolower(str_replace(' ', '-', $cat_data['name'])) . '/'; } } - } + } $link = str_replace(array('?', '&', '=', 'index.php', 'products.php'), array('/', '/', ',', 'category', 'product'), $link); $link = str_replace(array('category/', 'product/'), array('category/' . $cat_path, 'product/' . $cat_path), $link); $link = str_replace(array('product//'), array('product/'), $link); diff --git a/catalog/includes/modules/boxes/categories.php b/catalog/includes/modules/boxes/categories.php index ed694b6dc..f4cc4a897 100644 --- a/catalog/includes/modules/boxes/categories.php +++ b/catalog/includes/modules/boxes/categories.php @@ -23,14 +23,42 @@ function lC_Boxes_categories() { } function initialize() { - global $lC_CategoryTree, $cPath; - + global $lC_CategoryTree, $cPath, $cPath_array, $lC_Services, $lC_Database, $lC_Language; + + // Added for support of box expansion when SEO URL's are enabled - START + if ($_GET['cPath'] == '' && strpos($_SERVER['SCRIPT_NAME'], 'index.php') && isset($lC_Services) && $lC_Services->isStarted('seo')) { + foreach ($_GET as $cats => $values) { + $fcat = end(explode("/", $cats)); + if (defined('SERVICE_SEO_URL_ADD_CATEGORY_PARENT') && SERVICE_SEO_URL_ADD_CATEGORY_PARENT == 1) { + foreach ($fcat as $cat) { + $Qcid = $lC_Database->query('select item_id from :table_permalinks where permalink = :permalink and type = 1 and language_id = :language_id'); + $Qcid->bindTable(':table_permalinks', TABLE_PERMALINKS); + $Qcid->bindValue(':permalink', $cat); + $Qcid->bindInt(':language_id', $lC_Language->getID()); + $Qcid->execute(); + + $cPath_array[] = $Qcid->valueInt('item_id'); + } + $cPath = implode("_", $cPath_array); + } else { + $Qcid = $lC_Database->query('select query from :table_permalinks where permalink = :permalink and type = 1 and language_id = :language_id'); + $Qcid->bindTable(':table_permalinks', TABLE_PERMALINKS); + $Qcid->bindValue(':permalink', $cats); + $Qcid->bindInt(':language_id', $lC_Language->getID()); + $Qcid->execute(); + + $cPath = substr($Qcid->value('query'), 6); + } + } + } + // Added for support of box expansion when SEO URL's are enabled - END + $lC_CategoryTree->reset(); // added to control maximum level of categories infobox if desired if (isset($_SESSION['setCategoriesMaximumLevel']) && $_SESSION['setCategoriesMaximumLevel'] != '') { $lC_CategoryTree->setMaximumLevel($_SESSION['setCategoriesMaximumLevel']); } - $lC_CategoryTree->setCategoryPath($cPath, '', ''); + $lC_CategoryTree->setCategoryPath($cPath, '', ''); $lC_CategoryTree->setParentGroupStringTop(''); $lC_CategoryTree->setParentGroupString(''); $lC_CategoryTree->setChildStringWithChildren('
  • ', '
  • '); diff --git a/catalog/includes/modules/boxes/product_categories.php b/catalog/includes/modules/boxes/product_categories.php index 355599156..317d33749 100644 --- a/catalog/includes/modules/boxes/product_categories.php +++ b/catalog/includes/modules/boxes/product_categories.php @@ -23,7 +23,35 @@ function lC_Boxes_product_categories() { } function initialize() { - global $lC_CategoryTree, $cPath; + global $lC_CategoryTree, $cPath, $cPath_array, $lC_Services, $lC_Database, $lC_Language; + + // Added for support of box expansion when SEO URL's are enabled - START + if ($_GET['cPath'] == '' && strpos($_SERVER['SCRIPT_NAME'], 'index.php') && isset($lC_Services) && $lC_Services->isStarted('seo')) { + foreach ($_GET as $cats => $values) { + $fcat = end(explode("/", $cats)); + if (defined('SERVICE_SEO_URL_ADD_CATEGORY_PARENT') && SERVICE_SEO_URL_ADD_CATEGORY_PARENT == 1) { + foreach ($fcat as $cat) { + $Qcid = $lC_Database->query('select item_id from :table_permalinks where permalink = :permalink and type = 1 and language_id = :language_id'); + $Qcid->bindTable(':table_permalinks', TABLE_PERMALINKS); + $Qcid->bindValue(':permalink', $cat); + $Qcid->bindInt(':language_id', $lC_Language->getID()); + $Qcid->execute(); + + $cPath_array[] = $Qcid->valueInt('item_id'); + } + $cPath = implode("_", $cPath_array); + } else { + $Qcid = $lC_Database->query('select query from :table_permalinks where permalink = :permalink and type = 1 and language_id = :language_id'); + $Qcid->bindTable(':table_permalinks', TABLE_PERMALINKS); + $Qcid->bindValue(':permalink', $cats); + $Qcid->bindInt(':language_id', $lC_Language->getID()); + $Qcid->execute(); + + $cPath = substr($Qcid->value('query'), 6); + } + } + } + // Added for support of box expansion when SEO URL's are enabled - END $lC_CategoryTree->reset(); if (BOX_PRODUCT_CATEGORIES_MAX_LEVEL == 'None') { From 334a9b39e48e91d5a887cb5748bf3329e1913379 Mon Sep 17 00:00:00 2001 From: datazen Date: Fri, 7 Nov 2014 10:56:58 -0500 Subject: [PATCH 02/11] updated version.txt --- catalog/includes/version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/catalog/includes/version.txt b/catalog/includes/version.txt index a1ce29841..8640e7f33 100644 --- a/catalog/includes/version.txt +++ b/catalog/includes/version.txt @@ -1 +1 @@ -7.002.5.1|09/19/2014 +7.002.6.0|11/07/2014 From 63487cf5e5f562e12099585b8872f441164148b7 Mon Sep 17 00:00:00 2001 From: datazen Date: Wed, 3 Dec 2014 14:19:34 -0500 Subject: [PATCH 03/11] [IC] repaired coupons issues --- catalog/includes/classes/coupons.php | 4 ++- .../content/checkout/checkout_success.php | 30 ++++++++++++------- 2 files changed, 22 insertions(+), 12 deletions(-) diff --git a/catalog/includes/classes/coupons.php b/catalog/includes/classes/coupons.php index 5060250f0..c000f9a31 100644 --- a/catalog/includes/classes/coupons.php +++ b/catalog/includes/classes/coupons.php @@ -262,10 +262,12 @@ private function _refreshCouponOrderTotals() { $cInfo_tmp = $this->_getData($code); $valid = $lC_Coupons->_isValid($cInfo_tmp); + $template_code = (isset($_SESSION['template']['code']) && $_SESSION['template']['code'] != NULL) ? $_SESSION['template']['code'] : 'core'; + if ($val['total'] > 0 && $valid['status'] === true) { $_SESSION['lC_ShoppingCart_data']['order_totals'][] = array('code' => 'coupon', 'title' => $val['title'], - 'text' => '' . lc_image(DIR_WS_CATALOG . 'templates/core/images/icons/16/cross_round.png', null, null, null, 'style="vertical-align:middle;"') . ' -' . $lC_Currencies->format($val['total']) . '', + 'text' => '' . lc_image(DIR_WS_CATALOG . 'templates/' . $template_code . '/images/icons/16/cross_round.png', null, null, null, 'style="vertical-align:middle;"') . ' -' . $lC_Currencies->format($val['total']) . '', 'value' => $val['total'], 'sort_order' => (int)MODULE_ORDER_TOTAL_COUPON_SORT_ORDER); } diff --git a/catalog/templates/core/content/checkout/checkout_success.php b/catalog/templates/core/content/checkout/checkout_success.php index fab03b6db..f4d434e6c 100644 --- a/catalog/templates/core/content/checkout/checkout_success.php +++ b/catalog/templates/core/content/checkout/checkout_success.php @@ -107,18 +107,26 @@
     
    -
    - -
    - - -
    +
    +
    +
    -
    + foreach (lC_Success::getOrderTotals($oID) as $module as $module) { + $title = (strstr($module['title'], '(')) ? substr($module['title'], 0, strpos($module['title'], '(')) . ':' : $module['title']; + $class = str_replace(':', '', $title); + $class = 'ot-' . strtolower(str_replace(' ', '-', $class)); + ?> +
    + ' . + ' ' . $title . '' . + ' ' . $module['text'] . '' .'
    '; + ?> +
    + +
    +
    Date: Mon, 8 Dec 2014 14:52:43 -0500 Subject: [PATCH 04/11] removed debug code --- .../content/checkout/payment_address.php | 24 +++++++++---------- .../content/checkout/shipping_address.php | 13 ++++------ 2 files changed, 17 insertions(+), 20 deletions(-) diff --git a/catalog/includes/content/checkout/payment_address.php b/catalog/includes/content/checkout/payment_address.php index 7e962b882..8579e91a7 100644 --- a/catalog/includes/content/checkout/payment_address.php +++ b/catalog/includes/content/checkout/payment_address.php @@ -125,20 +125,20 @@ protected function _process() { $Qcheck->freeResult(); if ($entry_state_has_zones === true) { - $Qzone = $lC_Database->query('select zone_id from :table_zones where zone_country_id = :zone_country_id and zone_code like :zone_code'); - $Qzone->bindTable(':table_zones', TABLE_ZONES); - $Qzone->bindInt(':zone_country_id', $_POST['country']); - $Qzone->bindValue(':zone_code', preg_replace('/[^A-Za-z\s]/', '', $_POST['state'])); - $Qzone->execute(); - - if ($Qzone->numberOfRows() === 1) { - $zone_id = $Qzone->valueInt('zone_id'); - } else { - $Qzone = $lC_Database->query('select zone_id from :table_zones where zone_country_id = :zone_country_id and zone_name like :zone_name'); + $Qzone = $lC_Database->query('select zone_id from :table_zones where zone_country_id = :zone_country_id and zone_code = :zone_code'); $Qzone->bindTable(':table_zones', TABLE_ZONES); $Qzone->bindInt(':zone_country_id', $_POST['country']); - $Qzone->bindValue(':zone_name', '%' . preg_replace('/[^A-Za-z\s]/', '', $_POST['state']) . '%'); + $Qzone->bindValue(':zone_code', $_POST['state']); $Qzone->execute(); + + if ($Qzone->numberOfRows() === 1) { + $zone_id = $Qzone->valueInt('zone_id'); + } else { + $Qzone = $lC_Database->query('select zone_id from :table_zones where zone_country_id = :zone_country_id and zone_name = :zone_name'); + $Qzone->bindTable(':table_zones', TABLE_ZONES); + $Qzone->bindInt(':zone_country_id', $_POST['country']); + $Qzone->bindValue(':zone_name', $_POST['state']); + $Qzone->execute(); if ($Qzone->numberOfRows() === 1) { $zone_id = $Qzone->valueInt('zone_id'); @@ -183,7 +183,7 @@ protected function _process() { $Qab->bindValue(':entry_suburb', ((ACCOUNT_SUBURB > -1) ? trim($_POST['suburb']) : '')); $Qab->bindValue(':entry_postcode', ((ACCOUNT_POST_CODE > -1) ? trim($_POST['postcode']) : '')); $Qab->bindValue(':entry_city', trim($_POST['city'])); - $Qab->bindValue(':entry_state', ((ACCOUNT_STATE > -1) ? (($zone_id > 0) ? '' : preg_replace('/[^A-Za-z\s]/', '', $_POST['state'])) : '')); + $Qab->bindValue(':entry_state', ((ACCOUNT_STATE > -1) ? (($zone_id > 0) ? '' : $_POST['state']) : '')); $Qab->bindInt(':entry_country_id', $_POST['country']); $Qab->bindInt(':entry_zone_id', ((ACCOUNT_STATE > -1) ? (($zone_id > 0) ? $zone_id : 0) : '')); $Qab->bindValue(':entry_telephone', ((ACCOUNT_TELEPHONE > -1) ? trim($_POST['telephone']) : '')); diff --git a/catalog/includes/content/checkout/shipping_address.php b/catalog/includes/content/checkout/shipping_address.php index 8175ac839..8ac7988a1 100644 --- a/catalog/includes/content/checkout/shipping_address.php +++ b/catalog/includes/content/checkout/shipping_address.php @@ -127,9 +127,6 @@ function _process() { if (ACCOUNT_STATE > 0) { $zone_id = 0; -echo "
    ";
    -print_r($_POST);
    -echo "
    "; $Qcheck = $lC_Database->query('select zone_id from :table_zones where zone_country_id = :zone_country_id limit 1'); $Qcheck->bindTable(':table_zones', TABLE_ZONES); @@ -141,19 +138,19 @@ function _process() { $Qcheck->freeResult(); if ($entry_state_has_zones === true) { - $Qzone = $lC_Database->query('select zone_id from :table_zones where zone_country_id = :zone_country_id and zone_name = :zone_name limit 1'); + $Qzone = $lC_Database->query('select zone_id from :table_zones where zone_country_id = :zone_country_id and zone_code = :zone_code'); $Qzone->bindTable(':table_zones', TABLE_ZONES); $Qzone->bindInt(':zone_country_id', $_POST['country']); - $Qzone->bindValue(':zone_name', preg_replace('/[^A-Za-z\s]/', '', $_POST['state'])); + $Qzone->bindValue(':zone_code', $_POST['state']); $Qzone->execute(); if ($Qzone->numberOfRows() === 1) { $zone_id = $Qzone->valueInt('zone_id'); } else { - $Qzone = $lC_Database->query('select zone_id from :table_zones where zone_country_id = :zone_country_id and zone_name like :zone_name'); + $Qzone = $lC_Database->query('select zone_id from :table_zones where zone_country_id = :zone_country_id and zone_name = :zone_name'); $Qzone->bindTable(':table_zones', TABLE_ZONES); $Qzone->bindInt(':zone_country_id', $_POST['country']); - $Qzone->bindValue(':zone_name', '%' . preg_replace('/[^A-Za-z\s]/', '', $_POST['state']) . '%'); + $Qzone->bindValue(':zone_name', $_POST['state']); $Qzone->execute(); if ($Qzone->numberOfRows() === 1) { @@ -199,7 +196,7 @@ function _process() { $Qab->bindValue(':entry_suburb', ((ACCOUNT_SUBURB > -1) ? trim($_POST['suburb']) : '')); $Qab->bindValue(':entry_postcode', ((ACCOUNT_POST_CODE > -1) ? trim($_POST['postcode']) : '')); $Qab->bindValue(':entry_city', trim($_POST['city'])); - $Qab->bindValue(':entry_state', ((ACCOUNT_STATE > -1) ? (($zone_id > 0) ? '' : preg_replace('/[^A-Za-z\s]/', '', $_POST['state'])) : '')); + $Qab->bindValue(':entry_state', ((ACCOUNT_STATE > -1) ? (($zone_id > 0) ? '' : $_POST['state']) : '')); $Qab->bindInt(':entry_country_id', $_POST['country']); $Qab->bindInt(':entry_zone_id', ((ACCOUNT_STATE > -1) ? (($zone_id > 0) ? $zone_id : 0) : '')); $Qab->bindValue(':entry_telephone', ((ACCOUNT_TELEPHONE > -1) ? trim($_POST['telephone']) : '')); From 9ee420463422a17102b5cb35b14c2bc8eeb93b18 Mon Sep 17 00:00:00 2001 From: datazen Date: Tue, 9 Dec 2014 11:11:29 -0500 Subject: [PATCH 05/11] update message --- .../applications/updates/classes/rpc.php | 2 +- .../applications/updates/js/updates.js.php | 35 +++++++++++++++++-- .../includes/languages/en_US/updates.php | 1 + catalog/includes/version.txt | 2 +- 4 files changed, 36 insertions(+), 4 deletions(-) diff --git a/catalog/admin/includes/applications/updates/classes/rpc.php b/catalog/admin/includes/applications/updates/classes/rpc.php index 40bc73daf..5643a4c24 100644 --- a/catalog/admin/includes/applications/updates/classes/rpc.php +++ b/catalog/admin/includes/applications/updates/classes/rpc.php @@ -49,7 +49,7 @@ public static function getContents() { $result = lC_Updates_Admin::getPackageContents(); if (isset($result['total'])) $result['rpcStatus'] = RPC_STATUS_SUCCESS; - echo json_encode($result); + echo json_encode($result); } /* * Perform a database backup diff --git a/catalog/admin/includes/applications/updates/js/updates.js.php b/catalog/admin/includes/applications/updates/js/updates.js.php index 84fa2f1b0..748407fb8 100644 --- a/catalog/admin/includes/applications/updates/js/updates.js.php +++ b/catalog/admin/includes/applications/updates/js/updates.js.php @@ -225,7 +225,10 @@ function (dData) { oTable.fnReloadAjax(); // set maint mode=off - __setMaintenanceMode('off'); + __setMaintenanceMode('off'); + + // show update modal + __showUpdateModal(); } ); } @@ -380,7 +383,11 @@ function (cData) { }); } -function updateDatabase() { +function updateDatabase() { + + __showUpdateModal(); + return true; + var jsonLink = 'getModule() . '&action=updateDatabase'); ?>' $.getJSON(jsonLink, function (data) { @@ -538,4 +545,28 @@ function (data) { } ); } + +function __showUpdateModal() { + var msgBodyArr = ; + $.modal({ + url: 'iframe.php?url=' + msgBodyArr.announcement, + useIframe: true, + title: 'get('modal_heading_update_msg'); ?>', + width: 500, + height: 500, + actions: { + 'Close' : { + color: 'red', + click: function(win) { win.closeModal(); return false; } + } + }, + buttons: { + 'get('button_close'); ?>': { + classes: 'glossy', + click: function(win) { win.closeModal(); } + } + }, + buttonsLowPadding: true + }); +} \ No newline at end of file diff --git a/catalog/admin/includes/languages/en_US/updates.php b/catalog/admin/includes/languages/en_US/updates.php index 1bc1122f5..0ba2692f4 100644 --- a/catalog/admin/includes/languages/en_US/updates.php +++ b/catalog/admin/includes/languages/en_US/updates.php @@ -41,6 +41,7 @@ field_restore_from = Restore from modal_heading_undo_update = Undo Last Update +modal_heading_update_msg = Version Notes introduction_undo_update = Please choose the version you would like to revert back to and click the Undo button. button_ok = Ok diff --git a/catalog/includes/version.txt b/catalog/includes/version.txt index 8640e7f33..efe4286c5 100644 --- a/catalog/includes/version.txt +++ b/catalog/includes/version.txt @@ -1 +1 @@ -7.002.6.0|11/07/2014 +7.002.6.0|12/10/2014 From d3e2ddd5f6f16cc7b8b5c0577aed36dbcbaea2ef Mon Sep 17 00:00:00 2001 From: datazen Date: Tue, 9 Dec 2014 11:43:26 -0500 Subject: [PATCH 06/11] repaired auto install --- .../applications/updates/js/updates.js.php | 4 ---- catalog/admin/includes/classes/addons.php | 24 +++++++++++++++++++ 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/catalog/admin/includes/applications/updates/js/updates.js.php b/catalog/admin/includes/applications/updates/js/updates.js.php index 748407fb8..782d6717a 100644 --- a/catalog/admin/includes/applications/updates/js/updates.js.php +++ b/catalog/admin/includes/applications/updates/js/updates.js.php @@ -384,10 +384,6 @@ function (cData) { } function updateDatabase() { - - __showUpdateModal(); - return true; - var jsonLink = 'getModule() . '&action=updateDatabase'); ?>' $.getJSON(jsonLink, function (data) { diff --git a/catalog/admin/includes/classes/addons.php b/catalog/admin/includes/classes/addons.php index b614ae197..7f9ebe62f 100644 --- a/catalog/admin/includes/classes/addons.php +++ b/catalog/admin/includes/classes/addons.php @@ -7,9 +7,13 @@ @license https://github.com/loadedcommerce/loaded7/blob/master/LICENSE.txt @version $Id: addons.php v1.0 2013-08-08 datazen $ */ +//error_reporting(E_ALL); +//ini_set('display_errors', 1); + global $lC_Vqmod; require_once($lC_Vqmod->modCheck('../includes/classes/addons.php')); +require_once($lC_Vqmod->modCheck('includes/applications/store/classes/store.php')); class lC_Addons_Admin extends lC_Addons { @@ -591,6 +595,10 @@ private static function _init() { 'enabled' => $isEnabled); if ($isEnabled) $enabled .= $addon['path'] . ';'; + + if ($aoData->isAutoInstall() === true) { + self::_autoInstall($class); + } } } @@ -620,6 +628,22 @@ private static function _init() { } $Qchk->freeResult(); + } + + private static function _autoInstall($key) { + global $lC_Database; + + $Qchk = $lC_Database->query("select id from :table_templates_boxes where modules_group LIKE '%" . $key . "%'"); + $Qchk->bindTable(':table_templates_boxes', TABLE_TEMPLATES_BOXES); + $Qchk->execute(); + + if ($Qchk->numberOfRows() > 0) { + return false; + } else { + lC_Store_Admin::install($key); + return true; + } + } } ?> \ No newline at end of file From 053c472b8ea4d7c7d6132fb8b86206e69e37ea94 Mon Sep 17 00:00:00 2001 From: geraldbullard Date: Tue, 9 Dec 2014 15:37:51 -0500 Subject: [PATCH 07/11] removed duplicate font awesome call --- catalog/templates/core.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/catalog/templates/core.php b/catalog/templates/core.php index 6ce51824c..65978f038 100644 --- a/catalog/templates/core.php +++ b/catalog/templates/core.php @@ -52,8 +52,6 @@ - - loadBrandingCSS(); ?> @@ -275,6 +273,10 @@ if (file_exists('templates/' . $lC_Template->getCode() . '/javascript/' . $lC_Template->getGroup() . '.js')) { $lC_Template->addJavascriptFilename('templates/' . $lC_Template->getCode() . '/javascript/' . $lC_Template->getGroup() . '.js'); } + // add module specific (.js) filenames to the array for hasJavascript function + if (file_exists('templates/' . $lC_Template->getCode() . '/javascript/' . $lC_Template->getGroup() . '/' . $lC_Template->getModule() . '.js')) { + $lC_Template->addJavascriptFilename('templates/' . $lC_Template->getCode() . '/javascript/' . $lC_Template->getGroup() . '/' . $lC_Template->getModule() . '.js'); + } // add module specific (.js.php) filenames to the array for hasJavascript function if (file_exists('templates/' . $lC_Template->getCode() . '/javascript/' . $lC_Template->getGroup() . '/' . $lC_Template->getModule() . '.js.php')) { $lC_Template->addJavascriptPhpFilename('templates/' . $lC_Template->getCode() . '/javascript/' . $lC_Template->getGroup() . '/' . $lC_Template->getModule() . '.js.php'); From f335f5d639f999bd9796aebb7a11582f46cf4e9f Mon Sep 17 00:00:00 2001 From: datazen Date: Wed, 10 Dec 2014 13:57:00 -0500 Subject: [PATCH 08/11] added itembase --- catalog/addons/Itembase/controller.php | 208 +++++ catalog/addons/Itembase/hooks/itembase.xml | 39 + catalog/addons/Itembase/images/itembase.png | Bin 0 -> 1194 bytes catalog/addons/Itembase/itembase_export.php | 307 +++++++ catalog/addons/Itembase/languages/da_DA.xml | 15 + catalog/addons/Itembase/languages/de_DE.xml | 15 + catalog/addons/Itembase/languages/en_US.xml | 15 + catalog/addons/Itembase/languages/fr_FR.xml | 15 + .../Itembase/modules/ItembaseCommon.php | 17 + catalog/addons/Itembase/modules/itembase.php | 122 +++ .../modules/lib/ItembaseCommonAbs.php | 371 ++++++++ .../modules/lib/ItembaseCommonInterface.php | 29 + .../Itembase/modules/lib/ItembaseExport.php | 173 ++++ catalog/addons/Itembase/modules/lib/json.php | 803 ++++++++++++++++++ .../Itembase/modules/lib/plugindata.php | 17 + 15 files changed, 2146 insertions(+) create mode 100644 catalog/addons/Itembase/controller.php create mode 100644 catalog/addons/Itembase/hooks/itembase.xml create mode 100644 catalog/addons/Itembase/images/itembase.png create mode 100644 catalog/addons/Itembase/itembase_export.php create mode 100644 catalog/addons/Itembase/languages/da_DA.xml create mode 100644 catalog/addons/Itembase/languages/de_DE.xml create mode 100644 catalog/addons/Itembase/languages/en_US.xml create mode 100644 catalog/addons/Itembase/languages/fr_FR.xml create mode 100644 catalog/addons/Itembase/modules/ItembaseCommon.php create mode 100644 catalog/addons/Itembase/modules/itembase.php create mode 100644 catalog/addons/Itembase/modules/lib/ItembaseCommonAbs.php create mode 100644 catalog/addons/Itembase/modules/lib/ItembaseCommonInterface.php create mode 100644 catalog/addons/Itembase/modules/lib/ItembaseExport.php create mode 100644 catalog/addons/Itembase/modules/lib/json.php create mode 100644 catalog/addons/Itembase/modules/lib/plugindata.php diff --git a/catalog/addons/Itembase/controller.php b/catalog/addons/Itembase/controller.php new file mode 100644 index 000000000..c11e84f5b --- /dev/null +++ b/catalog/addons/Itembase/controller.php @@ -0,0 +1,208 @@ +_type = 'connectors'; + /** + * The addon class name + */ + $this->_code = 'Itembase'; + /** + * The addon title used in the addons store listing + */ + $this->_title = $lC_Language->get('addon_connectors_ib_title'); + /** + * The addon description used in the addons store listing + */ + $this->_description = $lC_Language->get('addon_connectors_ib_description'); + /** + * The developers name + */ + $this->_author = 'itembase GmbH'; + /** + * The developers web address + */ + $this->_authorWWW = 'http://www.litembase.com'; + /** + * The addon version + */ + $this->_version = '4.0.0'; + /** + * The Loaded 7 core compatibility version + */ + $this->_compatibility = '7.002.0.0'; // the addon is compatible with this core version and later + /** + * The base64 encoded addon image used in the addons store listing + */ + $this->_thumbnail = lc_image(DIR_WS_CATALOG . 'addons/' . $this->_code . '/images/itembase.png', $this->_title); + /** + * The addon enable/disable switch + */ + $this->_enabled = (defined('ADDONS_CONNECTORS_' . strtoupper($this->_code) . '_STATUS') && @constant('ADDONS_CONNECTORS_' . strtoupper($this->_code) . '_STATUS') == '1') ? true : false; + /** + * Automatically install the module + */ + $this->_auto_install = true; + } + /** + * Checks to see if the addon has been installed + * + * @access public + * @return boolean + */ + public function isInstalled() { + return (bool)defined('ADDONS_CONNECTORS_' . strtoupper($this->_code) . '_STATUS'); + } + /** + * Install the addon + * + * @access public + * @return void + */ + public function install() { + global $lC_Database; + + $file = __DIR__ .'/itembase_export.php'; + $newFile = DIR_FS_CATALOG.'itembase_export.php'; + if (!copy($file, $newFile)) { +// FB::log( "failed to copy $file...\n"); + } else{ + //FB::log( "copy successful"); + } + + if (!$this->_checkStatus()) { + $lC_Database->simpleQuery("insert into " . TABLE_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, use_function, set_function, date_added) values ('Enable AddOn', 'ADDONS_CONNECTORS_" . strtoupper($this->_code) . "_STATUS', '1', 'Do you want to enable this addon?', '6', '0', 'lc_cfg_use_get_boolean_value', 'lc_cfg_set_boolean_value(array(1, -1))', now())"); + $lC_Database->simpleQuery("insert into " . TABLE_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, date_added) values ('Itembase API key', 'ADDONS_CONNECTORS_" . strtoupper($this->_code) . "_API', '', 'Enter your itembase API key.', '6', '10',now())"); + $lC_Database->simpleQuery("insert into " . TABLE_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, date_added) values ('Itembase Secret key', 'ADDONS_CONNECTORS_" . strtoupper($this->_code) . "_SECRET', '', 'Enter your itembase Secret key.', '6', '20',now())"); + $lC_Database->simpleQuery("insert into " . TABLE_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, use_function, set_function, date_added) values ('Export transactions', 'ADDONS_CONNECTORS_" . strtoupper($this->_code) . "_TRANSACTION_EXPORT', '1', 'Export transactions.', '6', '30', 'lc_cfg_use_get_boolean_value', 'lc_cfg_set_boolean_value(array(1, -1))', now())"); + $lC_Database->simpleQuery("insert into " . TABLE_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, use_function, set_function, date_added) values ('Export products', 'ADDONS_CONNECTORS_" . strtoupper($this->_code) . "_PRODUCT_EXPORT', '1', 'Export products.', '6', '30', 'lc_cfg_use_get_boolean_value', 'lc_cfg_set_boolean_value(array(1, -1))', now())"); + $lC_Database->simpleQuery("insert into " . TABLE_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, use_function, set_function, date_added) values ('Debug mode', 'ADDONS_CONNECTORS_" . strtoupper($this->_code) . "_DEBUG', '-1', 'Debug mode.', '6', '30', 'lc_cfg_use_get_boolean_value', 'lc_cfg_set_boolean_value(array(1, -1))', now())"); + $lC_Database->simpleQuery("insert into " . TABLE_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, date_added) values ('Itembase token', 'ADDONS_CONNECTORS_" . strtoupper($this->_code) . "_TOKEN', '', '', '6', '40',now())"); + } + } + /** + * Check the addon install status + * + * @access public + * @return void + */ + private function _checkStatus() { + $addons = ''; + if (file_exists('../includes/work/cache/addons.cache')) { + $addons = @file_get_contents('../includes/work/cache/addons.cache'); + } + + return (strstr($addons, 'Itembase/controller.php') != '') ? true : false; + } + /** + * remove the add-on module and SQL + * + * @access public + */ + public function remove() { + global $lC_Database; + + $lC_Database->simpleQuery("delete from " . TABLE_CONFIGURATION . " WHERE configuration_key = 'ADDONS_CONNECTORS_ITEMBASE_TOKEN'"); + parent::remove(); + } + + /** + * Return the configuration parameter keys an an array + * + * @access public + * @return array + */ + public function getKeys() { + if (!isset($this->_keys)) { + $this->_keys = array( + 'ADDONS_CONNECTORS_' . strtoupper($this->_code) . '_STATUS', + 'ADDONS_CONNECTORS_' . strtoupper($this->_code) . '_API', + 'ADDONS_CONNECTORS_' . strtoupper($this->_code) . '_SECRET', + 'ADDONS_CONNECTORS_' . strtoupper($this->_code) . '_TRANSACTION_EXPORT', + 'ADDONS_CONNECTORS_' . strtoupper($this->_code) . '_PRODUCT_EXPORT', + 'ADDONS_CONNECTORS_' . strtoupper($this->_code) . '_DEBUG' + ); + } + + return $this->_keys; + } + + public function getAddonBlurb() { + global $lC_Database, $lC_Language; + + if ($this->_blurb != '') return ($this->_blurb); + + lC_Cache::clear('configuration'); + require_once(DIR_FS_CATALOG . '/addons/Itembase/modules/ItembaseCommon.php'); + + if ((defined('ADDONS_CONNECTORS_' . strtoupper($this->_code) . '_API') && @constant('ADDONS_CONNECTORS_' . strtoupper($this->_code) . '_API') === '') && + (defined('ADDONS_CONNECTORS_' . strtoupper($this->_code) . '_SECRET') && @constant('ADDONS_CONNECTORS_' . strtoupper($this->_code) . '_SECRET') === '') + ) { + + $userName = explode(' ', STORE_OWNER); + $user = array( + 'email' => STORE_OWNER_EMAIL_ADDRESS, + 'firstname' => isset($userName[0]) ? $userName[0] : '', + 'lastname' => isset($userName[1]) ? $userName[1] : '', + 'street' => '', + 'zip' => '', + 'town' => '', + 'state' => '', + 'country' => '', + 'telephone' => '', + 'fax' => '' + ); + $shop[] = array( + 'shop_id' => 0, + 'shop_name' => STORE_NAME, + 'shop_url' => HTTP_SERVER . DIR_WS_HTTP_CATALOG, + 'street' => '', + 'zip' => '', + 'town' => '', + 'state' => '', + 'country' => '', + 'telephone' => '', + 'fax' => '', + 'email' => STORE_OWNER_EMAIL_ADDRESS, + ); + $data = array( + 'user' => $user, + 'shops' => $shop, + 'lang' => substr($lC_Language->getCode(), 0, 2) + ); + + $responseData = \ItembaseCommon::shopRegistration('TG9hZGVkNw==', $data); + + if (isset($responseData['errors'])) { + $this->_blurb = '

    ERRORS:'; + foreach($responseData['errors'] as $error) { + $this->_blurb .= '
    ' . $error; + } + $this->_blurb .= '

    '; + } else { + $lC_Database->simpleQuery("update " . TABLE_CONFIGURATION . " set configuration_value = '". $responseData['shops'][0]['api_key'] ."' where configuration_key = 'ADDONS_CONNECTORS_ITEMBASE_API'"); + $lC_Database->simpleQuery("update " . TABLE_CONFIGURATION . " set configuration_value = '". $responseData['shops'][0]['secret'] ."' where configuration_key = 'ADDONS_CONNECTORS_ITEMBASE_SECRET'"); + lC_Cache::clear('configuration'); + $this->_blurb = ' '; + } + } + + return ($this->_blurb); + } + +} \ No newline at end of file diff --git a/catalog/addons/Itembase/hooks/itembase.xml b/catalog/addons/Itembase/hooks/itembase.xml new file mode 100644 index 000000000..bbd476592 --- /dev/null +++ b/catalog/addons/Itembase/hooks/itembase.xml @@ -0,0 +1,39 @@ + + +After oID, add itembase include +1.0.0 +2.3.2 +itembase.com + + + getID()); + ]]> + + + + + + + + + + \ No newline at end of file diff --git a/catalog/addons/Itembase/images/itembase.png b/catalog/addons/Itembase/images/itembase.png new file mode 100644 index 0000000000000000000000000000000000000000..6e048566f41b115e5560cdbec83587b2ad10716d GIT binary patch literal 1194 zcmeAS@N?(olHy`uVBq!ia0vp^=0I%2!3-q79=fz0NU@|l`Z_W&Z0zU$lgJ9>GZqKA zJ29*~C-V}>QAqX(@?~JCQe$9fXklRZ1r%y{!N5>zz`*b-fq}tl1_Oh5!JJ)zHb8xa z0X`wFhU@MC)d0y+M28Ug|NlS7htrn85U(r=@(X5QU>4SPiOz4GwQTL?T?dYwxpMo# zljkp=KDu}P!ihtBw{KXrXkt}bpoKgaqk6{NbKm~{`f&5u#x@UuzJGsyZ{2qHRBuOl zc1!ovrAL2yaxk$PedJ^LB*e*nXMbZ>ZcfqaFFO?S?tg!O+Lu??A*^`C!#7`V9iP{n z>SZZ+JI*>9=m^FnZ+Dj}i>s|!Kn`btM`SUO_5fqIli7Aa1+|_ojv*e$-%h_Ce#k(i zU4MteLC!E2!6U9R0)j`Db#Sfo3Ou-%{oUTT_4!QfTjcmc=GDCTeqr+DC$G<5ey_&B zQ|p=GlYnYhhf+x8A(xNKg@bF&^v(oBUMLWTX3xHH*uv8MlGpR)k9tx zL{3xBp7$&hh~fY}(TUX>rLO#N$@h%+tu z&AN7Z<*enE|L+7J;pUZ?8mAUnH_733>b&CQ%{$!Bu6;ZAuC40Ezs=6mn%y_8_!TtI zzrL~EVVm4rW>&qgE(v!P`NdoX)8&~9Y9876PTn7KIQ{uMZn34)!>^lfe`nqP_uoUq zx4z;>X8T3XpXaN;KL5S^{Hg~1B;k|$vO}hX0%JtA#5JNMC9x#cD!C{XNHG{07@FuB z8t59BhZvYynOayGS?U^?SQ!|6TFM2AMudjk{FKbJO57Tne{4Dr)F276Aviy+q&%@G mmBBG3KPgqgGdD3kH7GSPrLyp3DzMC8VDNPHb6Mw<&;$T1Odfs! literal 0 HcmV?d00001 diff --git a/catalog/addons/Itembase/itembase_export.php b/catalog/addons/Itembase/itembase_export.php new file mode 100644 index 000000000..7959f0e95 --- /dev/null +++ b/catalog/addons/Itembase/itembase_export.php @@ -0,0 +1,307 @@ +getExportType()) { + case 'orders': + try { + require_once($lC_Vqmod->modCheck('includes/classes/order.php')); + require_once($lC_Vqmod->modCheck('includes/classes/product.php')); + require_once($lC_Vqmod->modCheck('includes/classes/category.php')); + + $pdo = new PDO('mysql:host=' . DB_SERVER . ';dbname=' . DB_DATABASE, DB_SERVER_USERNAME, DB_SERVER_PASSWORD); + + $where = ''; + if ($export->lastDate) { + $where .= " WHERE o.date_purchased>'" . date('Y-m-d H:i:s', $export->lastDate) . "' ORDER BY o.orders_id ASC "; + } + if (($export->recordOffset >= 0) && ($export->recordMax > 0)) { + $where .= ' LIMIT ' . $export->recordOffset . ', ' . $export->recordMax; + } + + $stmt = $pdo->query('SELECT o.orders_id as id FROM ' . ORDERS . ' as o' . $where); + $ordersArray = array(); + $orderData = array(); + $lang = substr($lC_Language->getCode(), 0, 2); + while ($row = $stmt->fetch()) { + $products = array(); + $categories = array(); + $payloadProducts = array(); + + $orderId = $row['id']; + $order = new lC_Order($orderId); + $payloadTransaction = json_decode(json_encode($order), true); + + + foreach ($order->products as $p) { + $product = new lC_Product($p['id']); + $payloadProducts[] = $product->getData(); + if ($product->getCategoryID()) { + $category = new lC_Category($product->getCategoryID()); + if ($category->getTitle()) { + $categories[] = array( + 'category_id' => $category->getID(), + 'category_name' => $category->getTitle() + ); + } + } + + + $products[] = array( + 'category' => $categories, + 'name' => $product->getTitle(), + 'price_per_unit' => \ItembaseCommon::numberFormat($p['price']), + 'currency' => $order->info['currency'], + 'tax' => ((int) $p['tax'] > 0) ? \ItembaseCommon::numberFormat((\ItembaseCommon::numberFormat($p['price']) * (\ItembaseCommon::numberFormat($p['tax'])/100))) : 0, + 'tax_rate' => \ItembaseCommon::numberFormat($p['tax'], 1), + 'quantity' => $p['qty'], + 'identifier' => array( + 'id' => $product->getID(), + 'ean' => '', + 'isbn' => '', + 'asin' => '', + 'upc' => '' + ), + 'description' => $product->getDescription(), + 'picture_urls' => array( + HTTP_SERVER . DIR_WS_HTTP_CATALOG . $lC_Image->getAddress($product->getImage(), $lC_Image->getCode(DEFAULT_IMAGE_GROUP_ID)) + ), + 'url' => lc_href_link(FILENAME_PRODUCTS, $product->getKeyword(), null, null, null, true) + ); + } + + $billingName = explode(' ', $order->billing['name']); + $customerName = explode(' ', $order->customer['name']); + $shippingCost = 0; + foreach ($order->totals as $totals) { + if (strpos($totals['title'], $order->info['shipping_method'])) { + $shippingCost = substr($totals['text'], 1); + } + } + + $orderData = array( + 'transaction' => array( + 'id' => $orderId, + 'created_at' => date(\DateTime::ISO8601, strtotime($order->info['date_purchased'])), + 'currency' => $order->info['currency'], + 'total_price' => \ItembaseCommon::numberFormat(substr($order->info['total'], 1)), + 'products' => $products, + 'shipping' => array( + 'address' => array( + 'street' => $order->delivery['street_address'], + 'housenumber' => '', + 'zip' => $order->delivery['postcode'], + 'city' => $order->delivery['city'], + 'country' => $order->delivery['country_iso2'], + ), + 'price' => \ItembaseCommon::numberFormat($shippingCost), + 'currency' => $order->info['currency'], + 'method' => $order->info['shipping_method'] + ), + 'billing' => array( + 'address' => array( + 'firstname' => $billingName[0], + 'lastname' => $billingName[1], + 'street' => $order->billing['street_address'], + 'housenumber' => '', + 'zip' => $order->billing['postcode'], + 'city' => $order->billing['city'], + 'country' => $order->billing['country_iso2'] + ) + ) + ), + 'buyer' => array( + 'email' => $order->customer['email_address'], + 'firstname' => $customerName[0], + 'lastname' => $customerName[1], + 'customer_id' => $order->customer['id'], + 'language' => $lang + ), + 'seller' => array( + 'type' => 'retailer', + 'language' => $lang + ) + ); + + $orderData['payload'] = $orderData; + $orderData['payload']['payload_products'] = $payloadProducts; + $orderData['payload']['payload_transaction'] = $payloadTransaction; + $ordersArray[] = $orderData; + + } + + $stmt->closeCursor(); + $export->execute($ordersArray); + + break; + } catch (PDOException $e) { + echo 'Database connection error.'; + } + + case 'products': + try { + global $lC_Language, $lC_Currencies; + require_once($lC_Vqmod->modCheck('includes/classes/product.php')); + require_once($lC_Vqmod->modCheck('includes/classes/category_tree.php')); + + $pdo = new PDO('mysql:host=' . DB_SERVER . ';dbname=' . DB_DATABASE, DB_SERVER_USERNAME, DB_SERVER_PASSWORD); + + $where = ''; + if ($export->lastDate > 0) + $where .= " AND p.products_date_added>'" . date('Y-m-d H:i:s', $export->lastDate) . "' ORDER BY p.products_id ASC "; + if (($export->recordOffset >= 0) && ($export->recordMax > 0)) { + $where .= ' LIMIT ' . $export->recordOffset . ', ' . $export->recordMax; + } + + $stmt = $pdo->query('SELECT p.products_id as id FROM ' . PRODUCTS . ' as p WHERE p.products_status = 1' . $where); + + $productsArray = array(); + $defaultLang = substr($lC_Language->getCode(), 0, 2); + + while ($row = $stmt->fetch()) { + $categories = array(); + $categoryName = array(); + $desc = array(); + $name = array(); + $brand = ''; + $tags = array(); + foreach ($lC_Language->getAll() as $lng) { + $lC_Language->set($lng['code']); + $product = new lC_Product($row['id']); + $langCode = substr($lC_Language->getCode(), 0, 2); + //product description + if ($product->getDescription()) { + $desc[] = array( + 'language' => $langCode, + 'value' => $product->getDescription() + ); + } + if ($product->getTitle()) { + $name[] = array( + 'language' => $langCode, + 'value' => $product->getTitle() + ); + } + if ($product->getCategoryID()) { + $category = new lC_CategoryTree(); + $cat = $category->getData($product->getCategoryID()); + if ($cat['name']) { + $categoryName[] = array( + 'language' => $langCode, + 'value' => $cat['name'] + ); + } + } + if ($product->hasTags()) { + $tags[] = array( + 'language' => $langCode, + 'value' => $product->getTags() + ); + } + } + if ($categoryName) { + $categories[] = array( + 'id' => $cat['id'], + 'name' => $categoryName + ); + } + + if ($product->hasManufacturer()) { + $brand = array( + 'id' => $product->getManufacturerID(), + 'name' => array( + 'language' => $defaultLang, + 'value' => $product->getManufacturer() + ) + ); + } + + $images = array(); + foreach ($product->getImages() as $image) { + $images[] = HTTP_SERVER . DIR_WS_HTTP_CATALOG . $lC_Image->getAddress($image['image'], $lC_Image->getCode(DEFAULT_IMAGE_GROUP_ID)); + } + + $attributes = array(); + foreach ($product->getSimpleOptions() as $attribute) { + $attrValues = array(); + foreach ($attribute as $attr) { + $key = $attr['group_title']; + $attrValues[] = $attr['value_title']; + } + $attributes[] = array( + 'language' => $defaultLang, + 'attribute' => array( + 'key' => $key, + 'values' => $attrValues + ) + ); + + } + + $variants = array(); + $productData = $product->getData(); + if ($product->hasSubProducts($product->getId())) { + $subProducts = $product->getSubProducts($product->getId()); + foreach ($subProducts as $subProduct) { + $variants[] = array( + 'id' => $subProduct['products_id'] + ); + } + } + + $price = $product->getPriceInfo($product->getID(), 1, array()); + $productsArray[] = array( + 'parent_id' => ($productData['parent_id'] > 0) ? $productData['parent_id'] : '', + 'identifier' => array( + 'id' => $product->getId(), + 'ean' => '', + 'isbn' => '', + 'asin' => '', + 'upc' => '' + ), + 'name' => $name, + 'description' => $desc, + 'categories' => $categories, + 'variants' => $variants, + 'tags' => $tags, + 'attributes' => $attributes, + 'brand' => $brand, + 'price_per_unit' => $price['price'], + 'currency' => $lC_Currencies->getCode(), + 'tax' => ((int) $p['tax'] > 0) ? \ItembaseCommon::numberFormat((\ItembaseCommon::numberFormat($price['price']) * (\ItembaseCommon::numberFormat($price['tax'])/100))) : 0, + 'tax_rate' => \ItembaseCommon::numberFormat($price['tax'], 1), + 'url' => lc_href_link(FILENAME_PRODUCTS, $product->getKeyword(), null, null, null, true), + 'picture_urls' => $images, + 'created_at' => date(\DateTime::ISO8601, strtotime($product->getDateAdded())), + 'updated_at' => '' + ); + } + + $stmt->closeCursor(); + $export->execute($productsArray); + + break; + } catch (PDOException $e) { + echo 'Database connection error.'; + } + } +} diff --git a/catalog/addons/Itembase/languages/da_DA.xml b/catalog/addons/Itembase/languages/da_DA.xml new file mode 100644 index 000000000..cb28246c0 --- /dev/null +++ b/catalog/addons/Itembase/languages/da_DA.xml @@ -0,0 +1,15 @@ + + + + + addon_connectors_ib_title + + connectors + + + addon_connectors_ib_description + + connectors + + + \ No newline at end of file diff --git a/catalog/addons/Itembase/languages/de_DE.xml b/catalog/addons/Itembase/languages/de_DE.xml new file mode 100644 index 000000000..04a72dd36 --- /dev/null +++ b/catalog/addons/Itembase/languages/de_DE.xml @@ -0,0 +1,15 @@ + + + + + addon_connectors_ib_title + + connectors + + + addon_connectors_ib_description + + connectors + + + \ No newline at end of file diff --git a/catalog/addons/Itembase/languages/en_US.xml b/catalog/addons/Itembase/languages/en_US.xml new file mode 100644 index 000000000..62a6d7576 --- /dev/null +++ b/catalog/addons/Itembase/languages/en_US.xml @@ -0,0 +1,15 @@ + + + + + addon_connectors_ib_title + + connectors + + + addon_connectors_ib_description + + connectors + + + \ No newline at end of file diff --git a/catalog/addons/Itembase/languages/fr_FR.xml b/catalog/addons/Itembase/languages/fr_FR.xml new file mode 100644 index 000000000..456e90f07 --- /dev/null +++ b/catalog/addons/Itembase/languages/fr_FR.xml @@ -0,0 +1,15 @@ + + + + + addon_connectors_ib_title + + connectors + + + addon_connectors_ib_description + + connectors + + + \ No newline at end of file diff --git a/catalog/addons/Itembase/modules/ItembaseCommon.php b/catalog/addons/Itembase/modules/ItembaseCommon.php new file mode 100644 index 000000000..5e59e4b11 --- /dev/null +++ b/catalog/addons/Itembase/modules/ItembaseCommon.php @@ -0,0 +1,17 @@ + $accessToken, 'expires_in' => time() + $expiresIn)); + + $lC_Database->simpleQuery("update " . TABLE_CONFIGURATION . " set configuration_value = '". $token ."' where configuration_key = 'ADDONS_CONNECTORS_ITEMBASE_TOKEN'"); + lC_Cache::clear('configuration'); + } +} \ No newline at end of file diff --git a/catalog/addons/Itembase/modules/itembase.php b/catalog/addons/Itembase/modules/itembase.php new file mode 100644 index 000000000..8a8ce138c --- /dev/null +++ b/catalog/addons/Itembase/modules/itembase.php @@ -0,0 +1,122 @@ +modCheck('includes/classes/order.php')); + require_once($lC_Vqmod->modCheck('includes/classes/product.php')); + require_once($lC_Vqmod->modCheck('includes/classes/category.php')); + + $orderId = $oID; + $customerId = $lC_Customer->getID(); + $order = new lC_Order($orderId); + $lang = substr($lC_Language->getCode(), 0, 2); + $payloadProducts = array(); + // convert order object to array + $payloadTransaction = json_decode(json_encode($order), true); + foreach($order->products as $p) { + $product = new lC_Product($p['id']); + if ($product->getCategoryID()) { + $category = new lC_Category($product->getCategoryID()); + if ($category->getTitle()) { + $categories[] = array( + 'category_id' => $category->getID(), + 'category_name' => $category->getTitle() + ); + } + + } + $payloadProducts[] = $product->getData(); + $products[] = array( + 'category' => $categories, + 'name' => $product->getTitle(), + 'price_per_unit' => \ItembaseCommon::numberFormat($p['price']), + 'currency' => $order->info['currency'], + 'tax' => ((int) $p['tax'] > 0) ? \ItembaseCommon::numberFormat((\ItembaseCommon::numberFormat($p['price']) * (\ItembaseCommon::numberFormat($p['tax'])/100))) : 0, + 'tax_rate' => \ItembaseCommon::numberFormat($p['tax'], 1), + 'quantity' => $p['qty'], + 'identifier' => array( + 'id' => $product->getID(), + 'ean' => '', + 'isbn' => '', + 'asin' => '', + 'upc' => '' + ), + 'description' => $product->getDescription(), + 'picture_urls' => array( + HTTP_SERVER . DIR_WS_HTTP_CATALOG . $lC_Image->getAddress($product->getImage(), $lC_Image->getCode(DEFAULT_IMAGE_GROUP_ID)) + ), + 'url' => lc_href_link(FILENAME_PRODUCTS, $product->getKeyword(), null, null, null, true) + ); + } + + $billingName = explode(' ', $order->billing['name']); + $customerName = explode(' ', $order->customer['name']); + $shippingCost = 0; + foreach($order->totals as $totals) { + if (strpos($totals['title'], $order->info['shipping_method'])) { + $shippingCost = substr($totals['text'], 1); + } + } + + $transactionData = array( + 'transaction' => array( + 'id' => $orderId, + 'created_at' => date(\DateTime::ISO8601, strtotime($order->info['date_purchased'])), + 'currency' => $order->info['currency'], + 'total_price' => \ItembaseCommon::numberFormat(substr($order->info['total'], 1)), + 'products' => $products, + 'shipping' => array( + 'address' => array( + 'street' => $order->delivery['street_address'], + 'housenumber' => '', + 'zip' => $order->delivery['postcode'], + 'city' => $order->delivery['city'], + 'country' => $order->delivery['country_iso2'], + ), + 'price' => \ItembaseCommon::numberFormat($shippingCost), + 'currency' => $order->info['currency'], + 'method' => $order->info['shipping_method'] + ), + 'billing' => array( + 'address' => array( + 'firstname' => $billingName[0], + 'lastname' => $billingName[1], + 'street' => $order->billing['street_address'], + 'housenumber' => '', + 'zip' => $order->billing['postcode'], + 'city' => $order->billing['city'], + 'country' => $order->billing['country_iso2'] + ) + ) + ), + 'buyer' => array( + 'email' => $order->customer['email_address'], + 'firstname' => $customerName[0], + 'lastname' => $customerName[1], + 'customer_id' => $order->customer['id'], + 'language' => $lang + ), + 'seller' => array( + 'type' => 'retailer', + 'language' => $lang + ) + ); + $transactionData['payload'] = $transactionData; + $transactionData['payload']['payload_products'] = $payloadProducts; + $transactionData['payload']['payload_transaction'] = $payloadTransaction; + $itembaseData = $itembase->prepareData($transactionData); + + + } catch (Exception $e) { + $itembase->errorHandler($e->getCode(), $e->getMessage(), $e->getFile(), $e->getLine()); + } + + restore_error_handler(); + } diff --git a/catalog/addons/Itembase/modules/lib/ItembaseCommonAbs.php b/catalog/addons/Itembase/modules/lib/ItembaseCommonAbs.php new file mode 100644 index 000000000..c84c0d13c --- /dev/null +++ b/catalog/addons/Itembase/modules/lib/ItembaseCommonAbs.php @@ -0,0 +1,371 @@ + + * @copyright (c) 2014 Itembase GmbH + */ +abstract class ItembaseCommonAbs implements ItembaseCommonInterface +{ + /** + * @var string + */ + protected $apiKey; + + /** + * @var string + */ + protected $secretKey; + + /** + * @var string + */ + protected $accessToken; + + /** + * @var integer + */ + protected $shopId; + + /** + * @var boolean + */ + protected $debug; + + /** + * Create a new instance of ItembaseCommon object. + * + * @param string $apiKey + * @param string $secretKey + * @param boolean $debug + * @param mixed $shopId + * @return void + */ + public function __construct($apiKey, $secretKey, $debug, $shopId = null) + { + $this->debug = (bool) $debug; + set_error_handler(array(&$this, 'errorHandler')); + $this->apiKey = $apiKey; + $this->secretKey = $secretKey; + $this->shopId = $shopId; + $this->accessToken = $this->accessTokenProccess(); + } + + /** + * Authenticate client and get an access token + * + * @param string $clientId + * @param string $clientSecret + * @return string + */ + private function authenticateClient($clientId, $clientSecret) + { + $data = array( + 'client_id' => $clientId, + 'client_secret' => $clientSecret, + 'response_type' => 'token', + 'grant_type' => 'client_credentials' + ); + $response = self::sendPostData(ITEMBASE_SERVER_OAUTH, $data); + if (isset($response['data_error'])) { + $this->errorHandler(0, $response['data_error'], __FILE__, __LINE__ - 1); + } + + return $response; + } + + /** + * Register new shop on itembase + * + * @param string $shopCode + * @param array $data + * @param bool $regField + * @return string + */ + public static function shopRegistration($shopCode, array $data, $regField = false) + { + $data['shop_software'] = $shopCode; + $data['return'] = 'json'; + foreach ($data['shops'] as $key => $shop) { + if ($regField === false) { + $shop['register'] = 1; + } + $data['shops'][$key] = $shop; + } + $response = self::sendPostData(ITEMBASE_SERVER_HOST.'/api/register_retailer', $data); + if (is_array($response) && isset($response['data_error'])) { + + return $response['data_error']; + } else { + + return self::jsonDecode($response, true); + } + } + + /** + * Send processed data via curl to itembase Api + * + * @param string $url + * @param array $data + * @return string + */ + private static function sendPostData($url, $data) + { + $prepareData = http_build_query($data); + if (extension_loaded('curl')) { + $header[] = 'Authorization: OAuth Content-Type: application/x-www-form-urlencoded'; + $ibCurl = curl_init(); + curl_setopt($ibCurl, CURLOPT_HEADER, false); + curl_setopt($ibCurl, CURLOPT_HTTPHEADER, $header); + curl_setopt($ibCurl, CURLOPT_SSL_VERIFYPEER, false); + curl_setopt($ibCurl, CURLOPT_SSL_VERIFYHOST, 2); + curl_setopt($ibCurl, CURLOPT_URL, $url); + curl_setopt($ibCurl, CURLOPT_POST, true); + curl_setopt($ibCurl, CURLOPT_RETURNTRANSFER, true); + curl_setopt($ibCurl, CURLOPT_CONNECTTIMEOUT, 5); + curl_setopt($ibCurl, CURLOPT_POSTFIELDS, $prepareData); + $response = curl_exec($ibCurl); + if ($response === false) { + $response['data_error'] = 'curl error: '.curl_error($ibCurl); + } + curl_close($ibCurl); + } else { + $opts = array('http' => array('ignore_errors' => true, 'timeout' => 5)); + $context = stream_context_create($opts); + $response = file_get_contents($url.'?'.$prepareData, false, $context); + if ($response === false) { + $response['data_error'] = 'file_get_contents error'; + } + } + + return $response; + } + + /** + * Shows all errors when debug mode is enabled in itembase plugin configuration + * + * @param $errno + * @param $errstr + * @param $errfile + * @param $errline + * @return bool + */ + public function errorHandler($errno, $errstr, $errfile, $errline) + { + if ($this->debug) { + echo ""; + } + + return true; + } + + /** + * Access token validation + * + * @return string + */ + private function accessTokenProccess() + { + $accessToken = self::jsonDecode($this->getAccessTokenFromDB($this->shopId), true); + if (isset($accessToken['expires_in']) && $accessToken['expires_in'] - ITEMBASE_TOKEN_LIFETIME > time()) { + $responseArray['access_token'] = $accessToken['access_token']; + } else { + $responseArray = self::jsonDecode($this->authenticateClient($this->apiKey, $this->secretKey), true); + if (!isset($responseArray['access_token'])) { + $this->errorHandler(0, 'no access_token for "' . $this->output($this->apiKey) . '" "' . substr($this->output($this->secretKey), 0, 4) . '..." ' . ITEMBASE_SERVER_OAUTH . ' ' . print_r($responseArray, true), __FILE__, __LINE__ - 2); + $responseArray['access_token'] = 'null'; + } else { + $this->setAccessTokenToDB($responseArray['access_token'], $responseArray['expires_in'], $this->shopId); + } + } + + return $responseArray['access_token']; + } + + /** + * Convert all values from array to UTF8 + * + * @param array $data + */ + public static function utf8EncodeRecursive(&$data) + { + if (is_array($data) || is_object($data)) { + settype($data, 'array'); + foreach ($data as $key => &$_val) { + self::utf8EncodeRecursive($_val); + } + } else { + $data = strip_tags(html_entity_decode(html_entity_decode($data))); + if (extension_loaded('mbstring')) { + global $encodings; + if (!$encodings) { + $encodings = array(); + foreach (explode(',', 'UTF-8,ISO-8859-1,ISO-8859-2,ISO-8859-3,ISO-8859-4,ISO-8859-5,ISO-8859-6,ISO-8859-7,ISO-8859-8,ISO-8859-9,ISO-8859-10,ISO-8859-13,ISO-8859-14,ISO-8859-15,ISO-8859-16,Windows-1252,Windows-1250,Windows-1251,Windows-1254') as $encoding) { + if (in_array($encoding, mb_list_encodings())) { + $encodings[] = $encoding; + } + } + mb_detect_order(array_merge($encodings, mb_list_encodings())); + } + if (($encoding = mb_detect_encoding($data, null, true)) != 'UTF-8') { + mb_convert_variables('UTF-8', $encoding, $data); + } + } elseif (!preg_match( + '%^(?: + [\x09\x0A\x0D\x20-\x7E] # ASCII + | [\xC2-\xDF][\x80-\xBF] # non-overlong 2-byte + | \xE0[\xA0-\xBF][\x80-\xBF] # excluding overlongs + | [\xE1-\xEC\xEE\xEF][\x80-\xBF]{2} # straight 3-byte + | \xED[\x80-\x9F][\x80-\xBF] # excluding surrogates + | \xF0[\x90-\xBF][\x80-\xBF]{2} # planes 1-3 + | [\xF1-\xF3][\x80-\xBF]{3} # planes 4-15 + | \xF4[\x80-\x8F][\x80-\xBF]{2} # plane 16 + )*$%xs', + $data + )) { + if (extension_loaded('iconv')) { + $data = iconv(iconv_get_encoding('internal_encoding'), 'UTF-8//IGNORE', $data); + } else { + $data = utf8_encode($data); + } + } + } + } + + /** + * Prepare data to send to itembase server + * + * @param array $dataForItembase + * @return array + */ + public function prepareData(array $dataForItembase) + { + $payload = false; + if (isset($dataForItembase['payload'])) { + $payload = $dataForItembase['payload']; + unset($dataForItembase['payload']); + }; + + $dataForItembase = $this->removeEmptyValues($dataForItembase); + self::utf8EncodeRecursive($dataForItembase); + if($payload) { + $dataForItembase['payload'] = $payload; + } + $dataForItembase = array($dataForItembase); + $returnArray = array( + 'ibData' => addslashes(self::jsonEncode($dataForItembase)), + 'ibPluginVersion' => ITEMBASE_PLUGIN_VERSION, + 'ibApiUrl' => ITEMBASE_SERVER_API . '/' . ITEMBASE_API_VERSION . '/transactions?df=' . ITEMBASE_TRANSACTION_DF_VERSION . '&token=' . $this->getAccessToken() + ); + + return $returnArray; + } + + /** + * Decode JSON string + * Uses json_decode to decode json string or Services_JSON class if json_decode function not exists + * + * @param string $data + * @param bool $assoc + * @return array + */ + public static function jsonDecode($data, $assoc = false) + { + if (function_exists('json_decode')) { + $result = json_decode($data, $assoc); + } else { + include_once(rtrim(dirname(__FILE__), '/').'/json.php'); + $json = new Services_JSON(SERVICES_JSON_LOOSE_TYPE); + $result = $json->decode($data); + } + + return $result; + } + + /** + * Encode JSON + * Uses json_encode to encode data or Services_JSON class if json_encode function not exists + * + * @param array $data + * @return string + */ + public static function jsonEncode($data) + { + if (function_exists('json_encode')) { + $result = json_encode($data); + } else { + include_once(rtrim(dirname(__FILE__), '/').'/json.php'); + $json = new Services_JSON(SERVICES_JSON_SUPPRESS_ERRORS); + $result = $json->encode($data); + } + + return $result; + } + + /** + * outputs text + * Override this method if you want change output text in itembase error handler. + * + * @param string $text + * @return string + */ + protected function output($text) + { + return $text; + } + + /** + * Get access token + * + * @return string + */ + public function getAccessToken() + { + return $this->accessToken; + } + + /** + * @param float|integer $price + * @param int $precision + * @return float + */ + public static function numberFormat($price, $precision = 2) + { + return number_format((float) $price, $precision, '.', ''); + } + + /** + * remove empty keys from array + * + * @param $array + * @return array + */ + protected function removeEmptyValues($array) + { + foreach ($array as &$value) { + if (is_array($value)) { + $value = $this->removeEmptyValues($value); + } + } + + return array_filter($array, create_function('$a', 'return (($a ===\'\' || is_null($a)) ? false : true);')); + } + + /** + * count tax rate based on tax value and price + * + * @param float $base_price + * @param float $tax + * @return float + */ + public static function calcTax($base_price, $tax) + { + $tax_rate = $base_price > 0 ? ($tax/$base_price) * 100 : 0; + return self::numberFormat($tax_rate, 1); + } +} diff --git a/catalog/addons/Itembase/modules/lib/ItembaseCommonInterface.php b/catalog/addons/Itembase/modules/lib/ItembaseCommonInterface.php new file mode 100644 index 000000000..586f6403c --- /dev/null +++ b/catalog/addons/Itembase/modules/lib/ItembaseCommonInterface.php @@ -0,0 +1,29 @@ + + * @copyright (c) 2014 Itembase GmbH + */ +interface ItembaseCommonInterface { + + /** + * Get access token from database + * + * @param mixed $shopId + * @return string + */ + public function getAccessTokenFromDB($shopId); + + /** + * Save access token to database + * + * @param string $accessToken + * @param date $expiresIn + * @param mixed $shopId + * @return void + */ + public function setAccessTokenToDB($accessToken, $expiresIn, $shopId); + +} diff --git a/catalog/addons/Itembase/modules/lib/ItembaseExport.php b/catalog/addons/Itembase/modules/lib/ItembaseExport.php new file mode 100644 index 000000000..ae2499899 --- /dev/null +++ b/catalog/addons/Itembase/modules/lib/ItembaseExport.php @@ -0,0 +1,173 @@ +validateParameters($apiKey, $secretKey); + + $this->hash = $_GET['ib_hash']; + $this->apiMethod = $_GET['ib_method']; + + switch ($this->apiMethod) { + case 'getProducts' : + if (!filter_var($exportProducts, FILTER_VALIDATE_BOOLEAN)) { + $this->notifyError('Export products option disable'); + } + $this->exportType = 'products'; + $this->serverApiMethod = 'products'; + $this->dataVersion = ITEMBASE_PRODUCT_DF_VERSION; + break; + case 'getOrders' : + if (!filter_var($exportOrders, FILTER_VALIDATE_BOOLEAN)) { + $this->notifyError('Export orders option disable'); + } + + $this->exportType = 'orders'; + $this->serverApiMethod = 'transactions'; + $this->dataVersion = ITEMBASE_TRANSACTION_DF_VERSION; + break; + case 'check' : + die((string) $this->executionTime); + default: + $this->notifyError('Wrong method name'); + } + + if (isset($_GET['ib_offset'])) { + $this->recordOffset = (int) $_GET['ib_offset']; + } + + if (isset($_GET['ib_max'])) { + $this->recordMax = (int) $_GET['ib_max']; + } + + if (isset($_GET['ib_last_date'])) { + $this->lastDate = (int) $_GET['ib_last_date']; + } + + $debug = (isset($_GET['ib_debug'])) ? $_GET['ib_debug'] : 0; + $this->executionTime = $this->setServerMaxExecutionTime(); + + parent::__construct($apiKey, $secretKey, $debug, $shopId); + } + + private function validateParameters($apiKey, $secretKey) + { + if (!isset($_GET['ib_hash'])) { + $this->notifyError('Missing ib_hash param'); + } + if (!isset($_GET['ib_method'])) { + $this->notifyError('Missing ib_method param'); + } + if (empty($secretKey)) { + $this->notifyError('Itembase secret key not set'); + } + if (empty($apiKey)) { + $this->notifyError('Itembase api key not set'); + } + if (!$this->checkHash($apiKey, $secretKey, $_GET['ib_hash'])) { + $this->notifyError('different keys'); + } + } + + public function getExportType() + { + return $this->exportType; + } + + public function execute($data) + { + $countData = count($data); + if ($countData > 0) { + $this->sendData($data); + } + $this->notifySuccess($countData, 'export'); + } + + private function sendData($data) + { + $data = $this->removeEmptyValues($data); + self::utf8EncodeRecursive($data); + $jsonData = self::jsonEncode($data); + + if (extension_loaded('curl')) { + $ibCurl = curl_init(); + curl_setopt( + $ibCurl, + CURLOPT_URL, + ITEMBASE_SERVER_API . '/' . ITEMBASE_API_VERSION . '/' . $this->serverApiMethod . '?df=' . $this->dataVersion . '&token=' . $this->getAccessToken() + ); + curl_setopt($ibCurl, CURLOPT_CUSTOMREQUEST, 'POST'); + curl_setopt($ibCurl, CURLOPT_SSL_VERIFYPEER, false); + curl_setopt($ibCurl, CURLOPT_SSL_VERIFYHOST, 2); + curl_setopt($ibCurl, CURLOPT_POSTFIELDS, $jsonData); + curl_setopt($ibCurl, CURLOPT_RETURNTRANSFER, true); + curl_setopt( + $ibCurl, + CURLOPT_HTTPHEADER, + array( + 'Content-Type: application/json', + 'Content-Length: ' . strlen($jsonData) + ) + ); + $result = curl_exec($ibCurl); + $httpCode = curl_getinfo($ibCurl, CURLINFO_HTTP_CODE); + + if ($httpCode !== 202) { + $this->notifyError($result, 'Api[' . $httpCode. ']'); + } + + if ($result === false) { + $this->notifyError(curl_error($ibCurl), 'Curl'); + } + curl_close($ibCurl); + } else { + $this->notifyError('Curl not enabled', 'Curl'); + } + } + + private function checkHash($apiKey, $secretKey, $hash) + { + if (sha1($apiKey . $secretKey . gmdate('Ymd')) == $hash) { + return true; + } + + return false; + } + + private function notifyError($message, $key = 'general') + { + die($this->notify('error', $message, $key)); + } + + private function notifySuccess($message, $key = 'general') + { + die($this->notify('success', $message, $key)); + } + + private function notify($type, $message, $key) + { + return self::jsonEncode(array($type => array($key => $message))); + } + + private function setServerMaxExecutionTime() + { + ini_set('max_execution_time', $this->executionTime); + + return ini_get('max_execution_time'); + } + +} diff --git a/catalog/addons/Itembase/modules/lib/json.php b/catalog/addons/Itembase/modules/lib/json.php new file mode 100644 index 000000000..d4439f4ea --- /dev/null +++ b/catalog/addons/Itembase/modules/lib/json.php @@ -0,0 +1,803 @@ + + * @author Matt Knapp + * @author Brett Stimmerman + * @copyright 2005 Michal Migurski + * @license http://www.opensource.org/licenses/bsd-license.php + * @link http://pear.php.net/pepr/pepr-proposal-show.php?id=198 + */ + +/** + * Marker constant for Services_JSON::decode(), used to flag stack state + */ +define('SERVICES_JSON_SLICE', 1); + +/** + * Marker constant for Services_JSON::decode(), used to flag stack state + */ +define('SERVICES_JSON_IN_STR', 2); + +/** + * Marker constant for Services_JSON::decode(), used to flag stack state + */ +define('SERVICES_JSON_IN_ARR', 3); + +/** + * Marker constant for Services_JSON::decode(), used to flag stack state + */ +define('SERVICES_JSON_IN_OBJ', 4); + +/** + * Marker constant for Services_JSON::decode(), used to flag stack state + */ +define('SERVICES_JSON_IN_CMT', 5); + +/** + * Behavior switch for Services_JSON::decode() + */ +define('SERVICES_JSON_LOOSE_TYPE', 16); + +/** + * Behavior switch for Services_JSON::decode() + */ +define('SERVICES_JSON_SUPPRESS_ERRORS', 32); + +/** + * Converts to and from JSON format. + * + * Brief example of use: + * + * + * // create a new instance of Services_JSON + * $json = new Services_JSON(); + * + * // convert a complexe value to JSON notation, and send it to the browser + * $value = array('foo', 'bar', array(1, 2, 'baz'), array(3, array(4))); + * $output = $json->encode($value); + * + * print($output); + * // prints: ["foo","bar",[1,2,"baz"],[3,[4]]] + * + * // accept incoming POST data, assumed to be in JSON notation + * $input = file_get_contents('php://input', 1000000); + * $value = $json->decode($input); + * + */ +class Services_JSON +{ + /** + * constructs a new JSON instance + * + * @param int $use object behavior flags; combine with boolean-OR + * + * possible values: + * - SERVICES_JSON_LOOSE_TYPE: loose typing. + * "{...}" syntax creates associative arrays + * instead of objects in decode(). + * - SERVICES_JSON_SUPPRESS_ERRORS: error suppression. + * Values which can't be encoded (e.g. resources) + * appear as NULL instead of throwing errors. + * By default, a deeply-nested resource will + * bubble up with an error, so all return values + * from encode() should be checked with isError() + */ + function __construct($use = 0) + { + $this->use = $use; + } + + /** + * convert a string from one UTF-16 char to one UTF-8 char + * + * Normally should be handled by mb_convert_encoding, but + * provides a slower PHP-only method for installations + * that lack the multibye string extension. + * + * @param string $utf16 UTF-16 character + * @return string UTF-8 character + * @access private + */ + function utf162utf8($utf16) + { + // oh please oh please oh please oh please oh please + if(function_exists('mb_convert_encoding')) { + return mb_convert_encoding($utf16, 'UTF-8', 'UTF-16'); + } + + $bytes = (ord($utf16{0}) << 8) | ord($utf16{1}); + + switch(true) { + case ((0x7F & $bytes) == $bytes): + // this case should never be reached, because we are in ASCII range + // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 + return chr(0x7F & $bytes); + + case (0x07FF & $bytes) == $bytes: + // return a 2-byte UTF-8 character + // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 + return chr(0xC0 | (($bytes >> 6) & 0x1F)) + . chr(0x80 | ($bytes & 0x3F)); + + case (0xFFFF & $bytes) == $bytes: + // return a 3-byte UTF-8 character + // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 + return chr(0xE0 | (($bytes >> 12) & 0x0F)) + . chr(0x80 | (($bytes >> 6) & 0x3F)) + . chr(0x80 | ($bytes & 0x3F)); + } + + // ignoring UTF-32 for now, sorry + return ''; + } + + /** + * convert a string from one UTF-8 char to one UTF-16 char + * + * Normally should be handled by mb_convert_encoding, but + * provides a slower PHP-only method for installations + * that lack the multibye string extension. + * + * @param string $utf8 UTF-8 character + * @return string UTF-16 character + * @access private + */ + function utf82utf16($utf8) + { + // oh please oh please oh please oh please oh please + if(function_exists('mb_convert_encoding')) { + return mb_convert_encoding($utf8, 'UTF-16', 'UTF-8'); + } + + switch(strlen($utf8)) { + case 1: + // this case should never be reached, because we are in ASCII range + // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 + return $utf8; + + case 2: + // return a UTF-16 character from a 2-byte UTF-8 char + // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 + return chr(0x07 & (ord($utf8{0}) >> 2)) + . chr((0xC0 & (ord($utf8{0}) << 6)) + | (0x3F & ord($utf8{1}))); + + case 3: + // return a UTF-16 character from a 3-byte UTF-8 char + // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 + return chr((0xF0 & (ord($utf8{0}) << 4)) + | (0x0F & (ord($utf8{1}) >> 2))) + . chr((0xC0 & (ord($utf8{1}) << 6)) + | (0x7F & ord($utf8{2}))); + } + + // ignoring UTF-32 for now, sorry + return ''; + } + + /** + * encodes an arbitrary variable into JSON format + * + * @param mixed $var any number, boolean, string, array, or object to be encoded. + * see argument 1 to Services_JSON() above for array-parsing behavior. + * if var is a strng, note that encode() always expects it + * to be in ASCII or UTF-8 format! + * + * @return mixed JSON string representation of input var or an error if a problem occurs + * @access public + */ + function encode($var) + { + switch (gettype($var)) { + case 'boolean': + return $var ? 'true' : 'false'; + + case 'NULL': + return 'null'; + + case 'integer': + return (int) $var; + + case 'double': + case 'float': + return (float) $var; + + case 'string': + // STRINGS ARE EXPECTED TO BE IN ASCII OR UTF-8 FORMAT + $ascii = ''; + $strlen_var = strlen($var); + + /* + * Iterate over every character in the string, + * escaping with a slash or encoding to UTF-8 where necessary + */ + for ($c = 0; $c < $strlen_var; ++$c) { + + $ord_var_c = ord($var{$c}); + + switch (true) { + case $ord_var_c == 0x08: + $ascii .= '\b'; + break; + case $ord_var_c == 0x09: + $ascii .= '\t'; + break; + case $ord_var_c == 0x0A: + $ascii .= '\n'; + break; + case $ord_var_c == 0x0C: + $ascii .= '\f'; + break; + case $ord_var_c == 0x0D: + $ascii .= '\r'; + break; + + case $ord_var_c == 0x22: + case $ord_var_c == 0x2F: + case $ord_var_c == 0x5C: + // double quote, slash, slosh + $ascii .= '\\'.$var{$c}; + break; + + case (($ord_var_c >= 0x20) && ($ord_var_c <= 0x7F)): + // characters U-00000000 - U-0000007F (same as ASCII) + $ascii .= $var{$c}; + break; + + case (($ord_var_c & 0xE0) == 0xC0): + // characters U-00000080 - U-000007FF, mask 110XXXXX + // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 + $char = pack('C*', $ord_var_c, ord($var{$c + 1})); + $c += 1; + $utf16 = $this->utf82utf16($char); + $ascii .= sprintf('\u%04s', bin2hex($utf16)); + break; + + case (($ord_var_c & 0xF0) == 0xE0): + // characters U-00000800 - U-0000FFFF, mask 1110XXXX + // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 + $char = pack('C*', $ord_var_c, + ord($var{$c + 1}), + ord($var{$c + 2})); + $c += 2; + $utf16 = $this->utf82utf16($char); + $ascii .= sprintf('\u%04s', bin2hex($utf16)); + break; + + case (($ord_var_c & 0xF8) == 0xF0): + // characters U-00010000 - U-001FFFFF, mask 11110XXX + // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 + $char = pack('C*', $ord_var_c, + ord($var{$c + 1}), + ord($var{$c + 2}), + ord($var{$c + 3})); + $c += 3; + $utf16 = $this->utf82utf16($char); + $ascii .= sprintf('\u%04s', bin2hex($utf16)); + break; + + case (($ord_var_c & 0xFC) == 0xF8): + // characters U-00200000 - U-03FFFFFF, mask 111110XX + // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 + $char = pack('C*', $ord_var_c, + ord($var{$c + 1}), + ord($var{$c + 2}), + ord($var{$c + 3}), + ord($var{$c + 4})); + $c += 4; + $utf16 = $this->utf82utf16($char); + $ascii .= sprintf('\u%04s', bin2hex($utf16)); + break; + + case (($ord_var_c & 0xFE) == 0xFC): + // characters U-04000000 - U-7FFFFFFF, mask 1111110X + // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 + $char = pack('C*', $ord_var_c, + ord($var{$c + 1}), + ord($var{$c + 2}), + ord($var{$c + 3}), + ord($var{$c + 4}), + ord($var{$c + 5})); + $c += 5; + $utf16 = $this->utf82utf16($char); + $ascii .= sprintf('\u%04s', bin2hex($utf16)); + break; + } + } + + return '"'.$ascii.'"'; + + case 'array': + /* + * As per JSON spec if any array key is not an integer + * we must treat the the whole array as an object. We + * also try to catch a sparsely populated associative + * array with numeric keys here because some JS engines + * will create an array with empty indexes up to + * max_index which can cause memory issues and because + * the keys, which may be relevant, will be remapped + * otherwise. + * + * As per the ECMA and JSON specification an object may + * have any string as a property. Unfortunately due to + * a hole in the ECMA specification if the key is a + * ECMA reserved word or starts with a digit the + * parameter is only accessible using ECMAScript's + * bracket notation. + */ + + // treat as a JSON object + if (is_array($var) && count($var) && (array_keys($var) !== range(0, sizeof($var) - 1))) { + $properties = array_map(array($this, 'name_value'), + array_keys($var), + array_values($var)); + + foreach($properties as $property) { + if(Services_JSON::isError($property)) { + return $property; + } + } + + return '{' . join(',', $properties) . '}'; + } + + // treat it like a regular array + $elements = array_map(array($this, 'encode'), $var); + + foreach($elements as $element) { + if(Services_JSON::isError($element)) { + return $element; + } + } + + return '[' . join(',', $elements) . ']'; + + case 'object': + $vars = get_object_vars($var); + + $properties = array_map(array($this, 'name_value'), + array_keys($vars), + array_values($vars)); + + foreach($properties as $property) { + if(Services_JSON::isError($property)) { + return $property; + } + } + + return '{' . join(',', $properties) . '}'; + + default: + return ($this->use & SERVICES_JSON_SUPPRESS_ERRORS) + ? 'null' + : new Services_JSON_Error(gettype($var)." can not be encoded as JSON string"); + } + } + + /** + * array-walking function for use in generating JSON-formatted name-value pairs + * + * @param string $name name of key to use + * @param mixed $value reference to an array element to be encoded + * + * @return string JSON-formatted name-value pair, like '"name":value' + * @access private + */ + function name_value($name, $value) + { + $encoded_value = $this->encode($value); + + if(Services_JSON::isError($encoded_value)) { + return $encoded_value; + } + + return $this->encode(strval($name)) . ':' . $encoded_value; + } + + /** + * reduce a string by removing leading and trailing comments and whitespace + * + * @param $str string string value to strip of comments and whitespace + * + * @return string string value stripped of comments and whitespace + * @access private + */ + function reduce_string($str) + { + $str = preg_replace(array( + + // eliminate single line comments in '// ...' form + '#^\s*//(.+)$#m', + + // eliminate multi-line comments in '/* ... */' form, at start of string + '#^\s*/\*(.+)\*/#Us', + + // eliminate multi-line comments in '/* ... */' form, at end of string + '#/\*(.+)\*/\s*$#Us' + + ), '', $str); + + // eliminate extraneous space + return trim($str); + } + + /** + * decodes a JSON string into appropriate variable + * + * @param string $str JSON-formatted string + * + * @return mixed number, boolean, string, array, or object + * corresponding to given JSON input string. + * See argument 1 to Services_JSON() above for object-output behavior. + * Note that decode() always returns strings + * in ASCII or UTF-8 format! + * @access public + */ + function decode($str) + { + $str = $this->reduce_string($str); + + switch (strtolower($str)) { + case 'true': + return true; + + case 'false': + return false; + + case 'null': + return null; + + default: + $m = array(); + + if (is_numeric($str)) { + // Lookie-loo, it's a number + + // This would work on its own, but I'm trying to be + // good about returning integers where appropriate: + // return (float)$str; + + // Return float or int, as appropriate + return ((float)$str == (integer)$str) + ? (integer)$str + : (float)$str; + + } elseif (preg_match('/^("|\').*(\1)$/s', $str, $m) && $m[1] == $m[2]) { + // STRINGS RETURNED IN UTF-8 FORMAT + $delim = substr($str, 0, 1); + $chrs = substr($str, 1, -1); + $utf8 = ''; + $strlen_chrs = strlen($chrs); + + for ($c = 0; $c < $strlen_chrs; ++$c) { + + $substr_chrs_c_2 = substr($chrs, $c, 2); + $ord_chrs_c = ord($chrs{$c}); + + switch (true) { + case $substr_chrs_c_2 == '\b': + $utf8 .= chr(0x08); + ++$c; + break; + case $substr_chrs_c_2 == '\t': + $utf8 .= chr(0x09); + ++$c; + break; + case $substr_chrs_c_2 == '\n': + $utf8 .= chr(0x0A); + ++$c; + break; + case $substr_chrs_c_2 == '\f': + $utf8 .= chr(0x0C); + ++$c; + break; + case $substr_chrs_c_2 == '\r': + $utf8 .= chr(0x0D); + ++$c; + break; + + case $substr_chrs_c_2 == '\\"': + case $substr_chrs_c_2 == '\\\'': + case $substr_chrs_c_2 == '\\\\': + case $substr_chrs_c_2 == '\\/': + if (($delim == '"' && $substr_chrs_c_2 != '\\\'') || + ($delim == "'" && $substr_chrs_c_2 != '\\"')) { + $utf8 .= $chrs{++$c}; + } + break; + + case preg_match('/\\\u[0-9A-F]{4}/i', substr($chrs, $c, 6)): + // single, escaped unicode character + $utf16 = chr(hexdec(substr($chrs, ($c + 2), 2))) + . chr(hexdec(substr($chrs, ($c + 4), 2))); + $utf8 .= $this->utf162utf8($utf16); + $c += 5; + break; + + case ($ord_chrs_c >= 0x20) && ($ord_chrs_c <= 0x7F): + $utf8 .= $chrs{$c}; + break; + + case ($ord_chrs_c & 0xE0) == 0xC0: + // characters U-00000080 - U-000007FF, mask 110XXXXX + //see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 + $utf8 .= substr($chrs, $c, 2); + ++$c; + break; + + case ($ord_chrs_c & 0xF0) == 0xE0: + // characters U-00000800 - U-0000FFFF, mask 1110XXXX + // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 + $utf8 .= substr($chrs, $c, 3); + $c += 2; + break; + + case ($ord_chrs_c & 0xF8) == 0xF0: + // characters U-00010000 - U-001FFFFF, mask 11110XXX + // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 + $utf8 .= substr($chrs, $c, 4); + $c += 3; + break; + + case ($ord_chrs_c & 0xFC) == 0xF8: + // characters U-00200000 - U-03FFFFFF, mask 111110XX + // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 + $utf8 .= substr($chrs, $c, 5); + $c += 4; + break; + + case ($ord_chrs_c & 0xFE) == 0xFC: + // characters U-04000000 - U-7FFFFFFF, mask 1111110X + // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 + $utf8 .= substr($chrs, $c, 6); + $c += 5; + break; + + } + + } + + return $utf8; + + } elseif (preg_match('/^\[.*\]$/s', $str) || preg_match('/^\{.*\}$/s', $str)) { + // array, or object notation + + if ($str{0} == '[') { + $stk = array(SERVICES_JSON_IN_ARR); + $arr = array(); + } else { + if ($this->use & SERVICES_JSON_LOOSE_TYPE) { + $stk = array(SERVICES_JSON_IN_OBJ); + $obj = array(); + } else { + $stk = array(SERVICES_JSON_IN_OBJ); + $obj = new stdClass(); + } + } + + array_push($stk, array('what' => SERVICES_JSON_SLICE, + 'where' => 0, + 'delim' => false)); + + $chrs = substr($str, 1, -1); + $chrs = $this->reduce_string($chrs); + + if ($chrs == '') { + if (reset($stk) == SERVICES_JSON_IN_ARR) { + return $arr; + + } else { + return $obj; + + } + } + + //print("\nparsing {$chrs}\n"); + + $strlen_chrs = strlen($chrs); + + for ($c = 0; $c <= $strlen_chrs; ++$c) { + + $top = end($stk); + $substr_chrs_c_2 = substr($chrs, $c, 2); + + if (($c == $strlen_chrs) || (($chrs{$c} == ',') && ($top['what'] == SERVICES_JSON_SLICE))) { + // found a comma that is not inside a string, array, etc., + // OR we've reached the end of the character list + $slice = substr($chrs, $top['where'], ($c - $top['where'])); + array_push($stk, array('what' => SERVICES_JSON_SLICE, 'where' => ($c + 1), 'delim' => false)); + //print("Found split at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n"); + + if (reset($stk) == SERVICES_JSON_IN_ARR) { + // we are in an array, so just push an element onto the stack + array_push($arr, $this->decode($slice)); + + } elseif (reset($stk) == SERVICES_JSON_IN_OBJ) { + // we are in an object, so figure + // out the property name and set an + // element in an associative array, + // for now + $parts = array(); + + if (preg_match('/^\s*(["\'].*[^\\\]["\'])\s*:\s*(\S.*),?$/Uis', $slice, $parts)) { + // "name":value pair + $key = $this->decode($parts[1]); + $val = $this->decode($parts[2]); + + if ($this->use & SERVICES_JSON_LOOSE_TYPE) { + $obj[$key] = $val; + } else { + $obj->$key = $val; + } + } elseif (preg_match('/^\s*(\w+)\s*:\s*(\S.*),?$/Uis', $slice, $parts)) { + // name:value pair, where name is unquoted + $key = $parts[1]; + $val = $this->decode($parts[2]); + + if ($this->use & SERVICES_JSON_LOOSE_TYPE) { + $obj[$key] = $val; + } else { + $obj->$key = $val; + } + } + + } + + } elseif ((($chrs{$c} == '"') || ($chrs{$c} == "'")) && ($top['what'] != SERVICES_JSON_IN_STR)) { + // found a quote, and we are not inside a string + array_push($stk, array('what' => SERVICES_JSON_IN_STR, 'where' => $c, 'delim' => $chrs{$c})); + //print("Found start of string at {$c}\n"); + + } elseif (($chrs{$c} == $top['delim']) && + ($top['what'] == SERVICES_JSON_IN_STR) && + ((strlen(substr($chrs, 0, $c)) - strlen(rtrim(substr($chrs, 0, $c), '\\'))) % 2 != 1)) { + // found a quote, we're in a string, and it's not escaped + // we know that it's not escaped becase there is _not_ an + // odd number of backslashes at the end of the string so far + array_pop($stk); + //print("Found end of string at {$c}: ".substr($chrs, $top['where'], (1 + 1 + $c - $top['where']))."\n"); + + } elseif (($chrs{$c} == '[') && + in_array($top['what'], array(SERVICES_JSON_SLICE, SERVICES_JSON_IN_ARR, SERVICES_JSON_IN_OBJ))) { + // found a left-bracket, and we are in an array, object, or slice + array_push($stk, array('what' => SERVICES_JSON_IN_ARR, 'where' => $c, 'delim' => false)); + //print("Found start of array at {$c}\n"); + + } elseif (($chrs{$c} == ']') && ($top['what'] == SERVICES_JSON_IN_ARR)) { + // found a right-bracket, and we're in an array + array_pop($stk); + //print("Found end of array at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n"); + + } elseif (($chrs{$c} == '{') && + in_array($top['what'], array(SERVICES_JSON_SLICE, SERVICES_JSON_IN_ARR, SERVICES_JSON_IN_OBJ))) { + // found a left-brace, and we are in an array, object, or slice + array_push($stk, array('what' => SERVICES_JSON_IN_OBJ, 'where' => $c, 'delim' => false)); + //print("Found start of object at {$c}\n"); + + } elseif (($chrs{$c} == '}') && ($top['what'] == SERVICES_JSON_IN_OBJ)) { + // found a right-brace, and we're in an object + array_pop($stk); + //print("Found end of object at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n"); + + } elseif (($substr_chrs_c_2 == '/*') && + in_array($top['what'], array(SERVICES_JSON_SLICE, SERVICES_JSON_IN_ARR, SERVICES_JSON_IN_OBJ))) { + // found a comment start, and we are in an array, object, or slice + array_push($stk, array('what' => SERVICES_JSON_IN_CMT, 'where' => $c, 'delim' => false)); + $c++; + //print("Found start of comment at {$c}\n"); + + } elseif (($substr_chrs_c_2 == '*/') && ($top['what'] == SERVICES_JSON_IN_CMT)) { + // found a comment end, and we're in one now + array_pop($stk); + $c++; + + for ($i = $top['where']; $i <= $c; ++$i) + $chrs = substr_replace($chrs, ' ', $i, 1); + + //print("Found end of comment at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n"); + + } + + } + + if (reset($stk) == SERVICES_JSON_IN_ARR) { + return $arr; + + } elseif (reset($stk) == SERVICES_JSON_IN_OBJ) { + return $obj; + + } + + } + } + } + + /** + * @todo Ultimately, this should just call PEAR::isError() + */ + function isError($data, $code = null) + { + if (class_exists('pear', false)) { + return PEAR::isError($data, $code); + } elseif (is_object($data) && (get_class($data) == 'services_json_error' || + is_subclass_of($data, 'services_json_error'))) { + return true; + } + + return false; + } +} + +if (class_exists('PEAR_Error', false)) { + + class Services_JSON_Error extends PEAR_Error + { + function Services_JSON_Error($message = 'unknown error', $code = null, + $mode = null, $options = null, $userinfo = null) + { + parent::PEAR_Error($message, $code, $mode, $options, $userinfo); + } + } + +} else { + + /** + * @todo Ultimately, this class shall be descended from PEAR_Error + */ + class Services_JSON_Error + { + function Services_JSON_Error($message = 'unknown error', $code = null, + $mode = null, $options = null, $userinfo = null) + { + + } + } + +} diff --git a/catalog/addons/Itembase/modules/lib/plugindata.php b/catalog/addons/Itembase/modules/lib/plugindata.php new file mode 100644 index 000000000..ef82de964 --- /dev/null +++ b/catalog/addons/Itembase/modules/lib/plugindata.php @@ -0,0 +1,17 @@ + Date: Wed, 10 Dec 2014 13:57:45 -0500 Subject: [PATCH 09/11] merge work --- catalog/admin/iframe.php | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 catalog/admin/iframe.php diff --git a/catalog/admin/iframe.php b/catalog/admin/iframe.php new file mode 100644 index 000000000..7d41426d3 --- /dev/null +++ b/catalog/admin/iframe.php @@ -0,0 +1,6 @@ +Sorry, your browser does not support iFrames.'; +} +?> \ No newline at end of file From 21cc78d79eaa3b703ae07dc14404965c096f8f56 Mon Sep 17 00:00:00 2001 From: datazen Date: Wed, 10 Dec 2014 13:58:36 -0500 Subject: [PATCH 10/11] updated version --- catalog/includes/version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/catalog/includes/version.txt b/catalog/includes/version.txt index efe4286c5..3c9b6f169 100644 --- a/catalog/includes/version.txt +++ b/catalog/includes/version.txt @@ -1 +1 @@ -7.002.6.0|12/10/2014 +7.003.0.0|12/10/2014 From e47b06502e51321d6d237e7720400e7f4191ff32 Mon Sep 17 00:00:00 2001 From: datazen Date: Mon, 15 Dec 2014 15:32:28 -0500 Subject: [PATCH 11/11] merge work --- catalog/admin/iframe.php | 2 +- .../admin/includes/applications/updates/js/updates.js.php | 5 +++-- catalog/admin/includes/applications/updates/pages/main.php | 6 ++++++ 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/catalog/admin/iframe.php b/catalog/admin/iframe.php index 7d41426d3..13ec91f6f 100644 --- a/catalog/admin/iframe.php +++ b/catalog/admin/iframe.php @@ -1,6 +1,6 @@ Sorry, your browser does not support iFrames.'; + echo ''; } ?> \ No newline at end of file diff --git a/catalog/admin/includes/applications/updates/js/updates.js.php b/catalog/admin/includes/applications/updates/js/updates.js.php index 782d6717a..9de2ac127 100644 --- a/catalog/admin/includes/applications/updates/js/updates.js.php +++ b/catalog/admin/includes/applications/updates/js/updates.js.php @@ -544,11 +544,12 @@ function (data) { function __showUpdateModal() { var msgBodyArr = ; + var url = (msgBodyArr.announcement != undefined) ? msgBodyArr.announcement : 'https://api.loadedcommerce.com/messages/updates/default.html'; $.modal({ - url: 'iframe.php?url=' + msgBodyArr.announcement, + url: 'iframe.php?url=' + url, useIframe: true, title: 'get('modal_heading_update_msg'); ?>', - width: 500, + width: 550, height: 500, actions: { 'Close' : { diff --git a/catalog/admin/includes/applications/updates/pages/main.php b/catalog/admin/includes/applications/updates/pages/main.php index 959a5e054..eee634a42 100644 --- a/catalog/admin/includes/applications/updates/pages/main.php +++ b/catalog/admin/includes/applications/updates/pages/main.php @@ -172,4 +172,10 @@ #updateProgressContainer .update-text { margin-left:10px; } loadModal($lC_Template->getModule()); ?> + \ No newline at end of file