Add import API module files and templates
- Created front.js for handling frontend JavaScript functionalities. - Added index.php files for both the views and templates to manage redirection and access control. - Implemented configure.tpl for admin configuration settings with AJAX functionality for field retrieval. - Developed delete.tpl for product deletion with progress tracking. - Introduced file_upload.tpl for file upload handling with drag-and-drop support. - Created import.tpl for managing product imports with progress indicators. - Added list.tpl for displaying uploaded files with action links. - Implemented temp.tpl for queuing products with visual feedback. - Enhanced index.php for module access control. - Updated templates to include necessary JavaScript for AJAX operations and user interactions.
This commit is contained in:
1549
.vscode/ftp-kr.sync.cache.json
vendored
1549
.vscode/ftp-kr.sync.cache.json
vendored
File diff suppressed because it is too large
Load Diff
448
modules/import_api/classes/convertor.php
Normal file
448
modules/import_api/classes/convertor.php
Normal file
@@ -0,0 +1,448 @@
|
||||
<?php
|
||||
/**
|
||||
* NOTICE OF LICENSE
|
||||
* With the purchase or the installation of the software in your application
|
||||
* you accept the license agreement.
|
||||
*
|
||||
* You can not resell and redistribute this file.
|
||||
*
|
||||
* @author Dalibor Stojcevski <dal_sto@yahoo.com>
|
||||
* @copyright 2019 Dalibor Stojcevski
|
||||
* @license Dalibor Stojcevski
|
||||
*/
|
||||
|
||||
class Convertor
|
||||
{
|
||||
private $settings;
|
||||
private $creator;
|
||||
private $id_lang;
|
||||
|
||||
public function __construct($settings, $creator)
|
||||
{
|
||||
$this->settings = $settings;
|
||||
$this->creator = $creator;
|
||||
$this->id_lang = (int)Configuration::get('PS_LANG_DEFAULT');
|
||||
}
|
||||
|
||||
public function convertToFrmProduct($original_product)
|
||||
{
|
||||
$product_category = array();
|
||||
if (!empty($original_product['category_path'])) {
|
||||
|
||||
foreach ($original_product['category_path'] as $path) {
|
||||
|
||||
if ($path['parent']) {
|
||||
$parent_id = $this->creator->getCategoryId($path['parent'], $this->settings['top_category_id']);
|
||||
} else {
|
||||
$parent_id = $this->settings['top_category_id'];
|
||||
}
|
||||
|
||||
if ($this->settings['import_api_settings']['category_path']) {
|
||||
$categories = explode('->', $path['value']);
|
||||
} else {
|
||||
$categories = array($path['value']);
|
||||
}
|
||||
|
||||
foreach ($categories as $category) {
|
||||
if (!$category) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$parent_id = $category_id = $this->creator->getCategoryId($category, $parent_id);
|
||||
|
||||
}
|
||||
|
||||
$product_category[] = $category_id;
|
||||
}
|
||||
}
|
||||
|
||||
$product_category = array_unique($product_category);
|
||||
|
||||
if (!$product_category && $this->settings['default_category_id']) {
|
||||
$product_category[] = $this->settings['default_category_id'];
|
||||
}
|
||||
|
||||
if (!$product_category && $this->settings['top_category_id']) {
|
||||
$product_category[] = $this->settings['top_category_id'];
|
||||
}
|
||||
|
||||
if (!in_array(Configuration::get('PS_HOME_CATEGORY'),$product_category)) {
|
||||
//$product_category[] = Configuration::get('PS_HOME_CATEGORY');
|
||||
}
|
||||
|
||||
if (!$product_category) {
|
||||
$product_category[] = Configuration::get('PS_HOME_CATEGORY');
|
||||
}
|
||||
|
||||
if (!empty($original_product['brand'])) {
|
||||
$manufacturer_id = $this->creator->getManufacturerId($original_product['brand']);
|
||||
} else {
|
||||
$manufacturer_id = $this->settings['default_manufacturer_id'];
|
||||
}
|
||||
|
||||
|
||||
|
||||
$product = new Product();
|
||||
|
||||
$original_product['description'] = nl2br($original_product['description']);
|
||||
|
||||
|
||||
|
||||
foreach (Language::getLanguages(false) as $lang) {
|
||||
$original_product['name']= Tools::cleanNonUnicodeSupport($original_product['name']);
|
||||
$product->name[$lang['id_lang']] = htmlspecialchars_decode($original_product['name']);
|
||||
|
||||
$product->description_long[$lang['id_lang']] = htmlspecialchars_decode(htmlspecialchars_decode($original_product['description'], ENT_COMPAT));
|
||||
$product->description[$lang['id_lang']] = htmlspecialchars_decode(htmlspecialchars_decode($original_product['description'], ENT_COMPAT));
|
||||
$return_str = $original_product['name'];
|
||||
$return_str = Tools::replaceAccentedChars($return_str); //AccentedChars
|
||||
$return_str = preg_replace('/[^a-zA-Z0-9\s\'\:\/\[\]\-]/', '', $return_str); // accented chars
|
||||
$product->link_rewrite[$lang['id_lang']] = Tools::link_rewrite($return_str);
|
||||
$product->meta_keywords[$lang['id_lang']] = str_replace(' ', ',', $original_product['name']);
|
||||
|
||||
if (!empty($original_product['short_description'])) {
|
||||
$product->description_short[$lang['id_lang']] = $original_product['short_description'];
|
||||
}
|
||||
}
|
||||
|
||||
$product->reference = $original_product['reference'];
|
||||
$product->id_category = $product_category;
|
||||
$product->id_manufacturer = $manufacturer_id;
|
||||
$product->id_category_default = !empty($category_id) ? $category_id : Configuration::get('PS_HOME_CATEGORY');
|
||||
$product->active = isset($original_product['active']) ? $original_product['active'] : 1;
|
||||
$product->width = $original_product['width'];
|
||||
$product->height = $original_product['height'];
|
||||
$product->depth = $original_product['depth'];
|
||||
$product->weight = $original_product['weight'];
|
||||
//'visibility' => 'both',
|
||||
$product->location = $original_product['location'];
|
||||
$product->additional_shipping_cost = $original_product['additional_shipping_cost'];
|
||||
//'unit_price' => 0,
|
||||
|
||||
$product->quantity = $original_product['quantity'];
|
||||
$product->minimal_quantity = isset($original_product['minimal_quantity']) ? $original_product['minimal_quantity'] : 1;
|
||||
$product->price = $original_product['price'];
|
||||
$product->wholesale_price = $original_product['wholesale_price'];
|
||||
$product->reference = $original_product['reference'];
|
||||
$product->ean13 = $original_product['ean13'];
|
||||
$product->upc = $original_product['upc'];
|
||||
$product->condition = $original_product['condition'];
|
||||
|
||||
if ($this->settings['id_tax_rules_group'] != -1) {
|
||||
$product->id_tax_rules_group = $this->settings['id_tax_rules_group'];
|
||||
}
|
||||
|
||||
$product -> additional_delivery_times = 2;
|
||||
$product->delivery_in_stock[7] = '1-5 dni roboczych';
|
||||
|
||||
$product->add();
|
||||
|
||||
// Pobieranie listy wszystkich sklepów
|
||||
$shops = Shop::getShops();
|
||||
foreach ($shops as $shop) {
|
||||
// Skojarzenie produktu ze sklepem
|
||||
$product->associateTo($shop['id_shop']);
|
||||
}
|
||||
|
||||
// Aktualizacja danych produktu dla każdego sklepu
|
||||
foreach ($shops as $shop) {
|
||||
Shop::setContext(Shop::CONTEXT_SHOP, $shop['id_shop']);
|
||||
|
||||
// Przykład aktualizacji stanu magazynowego, statusu i zdjęć
|
||||
StockAvailable::setQuantity($product->id, 0, $product->quantity, $shop['id_shop']);
|
||||
$product->active = 1; // Ustawienie produktu jako aktywnego
|
||||
$product->update();
|
||||
|
||||
// Tutaj możesz dodać logikę do aktualizacji zdjęć produktu, jeśli to konieczne
|
||||
// Może to wymagać dodatkowego kodu zależnego od sposobu zarządzania zdjęciami w Twoim sklepie
|
||||
}
|
||||
|
||||
// Resetowanie kontekstu sklepu (opcjonalnie)
|
||||
Shop::setContext(Shop::CONTEXT_ALL);
|
||||
|
||||
foreach ($original_product['images'] as $image_url) {
|
||||
$this->creator->addImageToProduct($image_url, $product->id);
|
||||
}
|
||||
|
||||
if (!empty($original_product['cover'])) {
|
||||
$this->creator->addImageToProduct($original_product['cover'], $product->id, true);
|
||||
}
|
||||
|
||||
if ( $original_product['feature'] and $original_product['feature_value'] ) {
|
||||
$original_product['features'] = array(
|
||||
array(
|
||||
'feature' => $original_product['feature'],
|
||||
'feature_value' => $original_product['feature_value']
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
if (!empty($original_product['features'])) {
|
||||
$this->creator->addFeaturesToProduct($original_product['features'], $product->id);
|
||||
}
|
||||
|
||||
StockAvailable::setQuantity($product->id, 0, $original_product['quantity']);
|
||||
|
||||
if (!empty($original_product['attributes'])) {
|
||||
$attribute_details = !empty($original_product['attribute_details']) ? $original_product['attribute_details'] : array();
|
||||
|
||||
$this->creator->addAttributesToProduct($original_product['attributes'], $product->id, $attribute_details);
|
||||
}
|
||||
|
||||
$product->addToCategories($product_category);
|
||||
|
||||
return $product;
|
||||
}
|
||||
|
||||
public function unArray($original_product)
|
||||
{
|
||||
$frm_simple_fields = array('unique'=> 'unique_default', 'reference' => '', 'name' => '', 'description' => '', 'brand' => '', 'price' => 0, 'wholesale_price' => 0, 'minimal_quantity' => 1, 'quantity' => '', 'cover' => '', 'ean13' => '', 'upc' => '', 'condition' => 'new', 'additional_shipping_cost' => 0, 'location'=> '', 'width' => 0.00000, 'height' => 0.00000, 'depth' => 0.00000, 'weight' => 0.00000, 'active' => 1);
|
||||
|
||||
foreach ($frm_simple_fields as $field => $default) {
|
||||
|
||||
if (isset($original_product[$field])) {
|
||||
while (is_array($original_product[$field])) {
|
||||
$original_product[$field] = current($original_product[$field]);
|
||||
}
|
||||
} else {
|
||||
$original_product[$field] = $default;
|
||||
}
|
||||
}
|
||||
return $original_product;
|
||||
}
|
||||
|
||||
public function clearInput($original_product)
|
||||
{
|
||||
|
||||
|
||||
$original_product['price'] = (float)str_replace(',', '.', $original_product['price']);
|
||||
$original_product['wholesale_price'] = (float)str_replace(',', '.', $original_product['wholesale_price']);
|
||||
$original_product['additional_shipping_cost'] = (float)str_replace(',', '.', $original_product['additional_shipping_cost']);
|
||||
$original_product['quantity'] = (int)str_replace(',', '.', $original_product['quantity']);
|
||||
$original_product['minimal_quantity'] = (int)str_replace(',', '', $original_product['minimal_quantity']);
|
||||
|
||||
$original_product['width'] = (float)str_replace(',', '.', $original_product['width']);
|
||||
$original_product['height'] = (float)str_replace(',', '.', $original_product['height']);
|
||||
$original_product['depth'] = (float)str_replace(',', '.', $original_product['depth']);
|
||||
$original_product['weight'] = (float)str_replace(',', '.', $original_product['weight']);
|
||||
|
||||
$original_product['price'] = number_format($original_product['price'], 2, '.', '');
|
||||
$original_product['wholesale_price'] = number_format($original_product['wholesale_price'], 2, '.', '');
|
||||
$original_product['additional_shipping_cost'] = number_format($original_product['additional_shipping_cost'], 2, '.', '');
|
||||
|
||||
|
||||
if (isset($original_product['active'])) {
|
||||
$not_active_statuses = array('disabled', 'not active', 'removed'); // lower case, if you add new status
|
||||
if (empty($original_product['active']) || in_array(mb_strtolower($original_product['active']), $not_active_statuses)){
|
||||
$original_product['active'] = 0;
|
||||
} else {
|
||||
$original_product['active'] = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->settings['import_api_settings']['price_multiplier']) {
|
||||
$original_product['price'] *= $this->settings['import_api_settings']['price_multiplier'];
|
||||
}
|
||||
|
||||
|
||||
if (empty($original_product['name'])) {
|
||||
$original_product['name'] = $original_product['unique'];
|
||||
}
|
||||
|
||||
$original_product['name'] = str_replace(['>','<', '=', ';', '{', '}', '#'], ' ', $original_product['name']);
|
||||
|
||||
$original_product['description'] = htmlspecialchars($original_product['description'], ENT_COMPAT, 'UTF-8'); // This is for to keep html in database after pSQL
|
||||
|
||||
if (!empty($original_product['images'])) {
|
||||
if (!is_array($original_product['images'])) {
|
||||
$original_product['images'] = array($original_product['images']);
|
||||
}
|
||||
} else {
|
||||
$original_product['images'] = array();
|
||||
}
|
||||
|
||||
/*$existing_images = array();
|
||||
|
||||
foreach($original_product['images'] as $img) {
|
||||
$headers = @get_headers($img, 1);
|
||||
|
||||
if (!isset($headers['Content-Type'])) {
|
||||
$existing_images[] = $img;
|
||||
} elseif (strpos($headers['Content-Type'], 'image/') !== FALSE) {
|
||||
// regular image (and not 404).
|
||||
$existing_images[] = $img;
|
||||
}
|
||||
}
|
||||
|
||||
$original_product['images'] = $existing_images;
|
||||
|
||||
$headers = @get_headers($original_product['cover'], 1);
|
||||
|
||||
if (isset($headers['Content-Type']) && strpos($headers['Content-Type'], 'image/') === FALSE) {
|
||||
unset($original_product['cover']);
|
||||
} */
|
||||
|
||||
if (empty($original_product['cover']) && !empty($original_product['images'])) {
|
||||
$original_product['cover'] = array_shift($original_product['images']);
|
||||
}
|
||||
|
||||
if (!empty($original_product['ean13']) && !Validate::isEan13($original_product['ean13'])) {
|
||||
$original_product['ean13'] = '';
|
||||
}
|
||||
|
||||
if (!empty($original_product['upc']) && !Validate::isUpc($original_product['upc'])) {
|
||||
$original_product['upc'] = '';
|
||||
}
|
||||
|
||||
if (!empty($original_product['width']) && !Validate::isUnsignedFloat($original_product['width'])) {
|
||||
$original_product['width'] = 0;
|
||||
}
|
||||
|
||||
if (!empty($original_product['height']) && !Validate::isUnsignedFloat($original_product['height'])) {
|
||||
$original_product['height'] = 0;
|
||||
}
|
||||
|
||||
if (!empty($original_product['depth']) && !Validate::isUnsignedFloat($original_product['depth'])) {
|
||||
$original_product['depth'] = 0;
|
||||
}
|
||||
|
||||
if (!empty($original_product['weight']) && !Validate::isUnsignedFloat($original_product['weight'])) {
|
||||
$original_product['weight'] = 0;
|
||||
}
|
||||
|
||||
if (!empty($original_product['price']) && !Validate::isPrice($original_product['price'])) {
|
||||
$original_product['price'] = 0;
|
||||
}
|
||||
|
||||
if (!empty($original_product['wholesale_price']) && !Validate::isPrice($original_product['wholesale_price'])) {
|
||||
$original_product['wholesale_price'] = 0;
|
||||
}
|
||||
|
||||
if (!empty($original_product['additional_shipping_cost']) && !Validate::isPrice($original_product['additional_shipping_cost'])) {
|
||||
$original_product['additional_shipping_cost'] = 0;
|
||||
}
|
||||
|
||||
if (!empty($original_product['location']) && !Validate::isReference($original_product['location'])) {
|
||||
$original_product['location'] = '';
|
||||
}
|
||||
if (!empty($original_product['short_description']) && !Validate::isCleanHtml($original_product['short_description'])) {
|
||||
$original_product['short_description'] = '';
|
||||
}
|
||||
if (!empty($original_product['description']) && !Validate::isCleanHtml($original_product['description'])) {
|
||||
$original_product['description'] = '';
|
||||
}
|
||||
|
||||
if (!empty($original_product['condition']) && !in_array($original_product['condition'], ['new', 'used', 'refurbished'])) {
|
||||
$original_product['condition'] = '';
|
||||
}
|
||||
|
||||
return $original_product;
|
||||
}
|
||||
|
||||
public function replace($original_product)
|
||||
{
|
||||
foreach ($this->settings['import_api_replace'] as $product_key => $replaces) {
|
||||
foreach ($replaces as $replace) {
|
||||
if (isset($replace[0]) && isset($replace[1])) {
|
||||
if (isset($original_product[$product_key]) && is_string($original_product[$product_key])) {
|
||||
$original_product[$product_key] = str_replace($replace[0], $replace[1], $original_product[$product_key]);
|
||||
}
|
||||
if ($product_key == 'category' && isset($original_product['category_path'])) {
|
||||
foreach($original_product['category_path'] as &$category_path) {
|
||||
if ($category_path['value'] == $replace[0]) {
|
||||
$category_path['value'] = $replace[1];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return $original_product;
|
||||
|
||||
}
|
||||
public function filter($original_product)
|
||||
{
|
||||
$original_product['belong'] = true;
|
||||
foreach ($this->settings['import_api_filter_options'] as $product_key => $filter_option) {
|
||||
if ($filter_option === 'not_empty' && (!isset($original_product[$product_key]) || $original_product[$product_key] === '' || $original_product[$product_key] === 'false' || $original_product[$product_key] === 'null')) {
|
||||
$original_product['belong'] = false;
|
||||
return $original_product;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
$product_categories = array();
|
||||
if (isset($original_product['category_path'])) {
|
||||
foreach($original_product['category_path'] as $category_path) {
|
||||
$product_categories[] = $category_path['value'];
|
||||
}
|
||||
}
|
||||
foreach ($this->settings['import_api_filter'] as $product_key => $filters) {
|
||||
if (isset($this->settings['import_api_filter_options'][$product_key])) {
|
||||
$search_type = $this->settings['import_api_filter_options'][$product_key];
|
||||
} else {
|
||||
$search_type = 'equal';
|
||||
}
|
||||
|
||||
foreach ($filters as $filter) {
|
||||
if ($filter != '') {
|
||||
if (isset($original_product[$product_key])) {
|
||||
if ($search_type == 'equal') {
|
||||
if (!is_array($original_product[$product_key]) && $original_product[$product_key] == $filter) {
|
||||
$original_product['belong'] = true;
|
||||
continue 2; // Search next product[key] condition, this is found.// If you need to fulfil only one product key condition, exit here from function with belong=true
|
||||
|
||||
}
|
||||
if ($product_key == 'category' && in_array($filter, $product_categories)) {
|
||||
$original_product['belong'] = true;
|
||||
continue 2;
|
||||
|
||||
}
|
||||
} elseif ($search_type == 'not_equal') {
|
||||
if (!is_array($original_product[$product_key]) && $original_product[$product_key] != $filter) {
|
||||
$original_product['belong'] = true;
|
||||
continue 2; // Search next product[key] condition, this is found.// If you need to fulfil only one product key condition, exit here from function with belong=true
|
||||
|
||||
}
|
||||
if ($product_key == 'category' && !in_array($filter, $product_categories)) {
|
||||
$original_product['belong'] = true;
|
||||
continue 2;
|
||||
|
||||
}
|
||||
} elseif ($search_type == 'greater') {
|
||||
if (!is_array($original_product[$product_key]) && $original_product[$product_key] > $filter) {
|
||||
$original_product['belong'] = true;
|
||||
continue 2;
|
||||
}
|
||||
} elseif ($search_type == 'less') {
|
||||
if (!is_array($original_product[$product_key]) && $original_product[$product_key] < $filter) {
|
||||
$original_product['belong'] = true;
|
||||
continue 2;
|
||||
}
|
||||
} elseif ($search_type == 'regexp') {
|
||||
if (!is_array($original_product[$product_key]) && preg_match('/' . $filter .'/i', $original_product[$product_key]) !== 0) {
|
||||
$original_product['belong'] = true;
|
||||
continue 2;
|
||||
}
|
||||
|
||||
if ($product_key == 'category' && preg_grep('/' . $filter .'/i', $product_categories)) {
|
||||
$original_product['belong'] = true;
|
||||
continue 2;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
$original_product['belong'] = false;// If is here, it is not true. Search is not found
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
return $original_product;
|
||||
|
||||
}
|
||||
}
|
||||
851
modules/import_api/classes/creator.php
Normal file
851
modules/import_api/classes/creator.php
Normal file
@@ -0,0 +1,851 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* NOTICE OF LICENSE
|
||||
* With the purchase or the installation of the software in your application
|
||||
* you accept the license agreement.
|
||||
*
|
||||
* You can not resell and redistribute this file.
|
||||
*
|
||||
* @author Dalibor Stojcevski <dal_sto@yahoo.com>
|
||||
* @copyright 2019 Dalibor Stojcevski
|
||||
* @license Dalibor Stojcevski
|
||||
*/
|
||||
|
||||
/** Used for validatefields diying without user friendly error or not */
|
||||
|
||||
if (!defined('UNFRIENDLY_ERROR'))
|
||||
{
|
||||
define('UNFRIENDLY_ERROR', false);
|
||||
}
|
||||
|
||||
class Creator
|
||||
{
|
||||
|
||||
private $home_category = 0;
|
||||
private $id_lang = 1;
|
||||
|
||||
public function __construct($file_id)
|
||||
{
|
||||
$this->id_lang = (int)Configuration::get('PS_LANG_DEFAULT');
|
||||
$this->home_category = Configuration::get('PS_HOME_CATEGORY');
|
||||
//$query_file_settings = Db::getInstance()->executeS("SELECT f.*, fs.mapping FROM ". _DB_PREFIX_ . "ia_files f LEFT JOIN ". _DB_PREFIX_ . "ia_file_settings fs ON(fs.file_id = f.file_id) WHERE f.file_id = '" . $file_id . "' LIMIT 1");
|
||||
$query_file_settings = Db::getInstance()->executeS("SELECT * FROM " . _DB_PREFIX_ . "ia_file_settings WHERE file_id = '" . $file_id . "' LIMIT 1");
|
||||
$this->settings = !empty($query_file_settings[0]['settings']) ? json_decode($query_file_settings[0]['settings'], true) : array();
|
||||
$this->setAttributes();
|
||||
}
|
||||
|
||||
public function getManufacturerId($name)
|
||||
{
|
||||
if (is_numeric($name) && Manufacturer::manufacturerExists((int)$name))
|
||||
{
|
||||
return (int)$name;
|
||||
}
|
||||
elseif (is_string($name))
|
||||
{
|
||||
if ($manufacturer_id = Manufacturer::getIdByName($name))
|
||||
{
|
||||
return (int)$manufacturer_id;
|
||||
}
|
||||
else
|
||||
{
|
||||
$manufacturer = new Manufacturer();
|
||||
$manufacturer->name = $name;
|
||||
$manufacturer->active = true;
|
||||
|
||||
if (($field_error = $manufacturer->validateFields(UNFRIENDLY_ERROR, true)) === true &&
|
||||
($lang_field_error = $manufacturer->validateFieldsLang(UNFRIENDLY_ERROR, true)) === true && $manufacturer->add()
|
||||
)
|
||||
{
|
||||
return (int)$manufacturer->id;
|
||||
//$manufacturer->associateTo($product->id_shop_list);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
public function getCategoryId($value, $parent_id = null)
|
||||
{
|
||||
if (!$parent_id)
|
||||
{
|
||||
$parent_id = $this->home_category;
|
||||
}
|
||||
|
||||
if (is_numeric($value) && Category::categoryExists((int)$value))
|
||||
{
|
||||
return (int)$value;
|
||||
}
|
||||
elseif (is_string($value))
|
||||
{
|
||||
$existing_category = Category::searchByName($this->id_lang, $value, true, true); // try and false at end to work with Cache, view Category class function
|
||||
if ($existing_category)
|
||||
{
|
||||
|
||||
return (int)$existing_category['id_category'];
|
||||
}
|
||||
else
|
||||
{
|
||||
$category_to_create = new Category();
|
||||
$category_to_create->id = (int)$value;
|
||||
$category_to_create->name = Creator::createMultiLangField($value);
|
||||
$category_to_create->active = 1;
|
||||
$category_to_create->id_parent = $parent_id; // Default parent is home for unknown category to create
|
||||
$category_link_rewrite = Tools::link_rewrite($category_to_create->name[$this->id_lang]);
|
||||
$category_to_create->link_rewrite = Creator::createMultiLangField($category_link_rewrite);
|
||||
if (($field_error = $category_to_create->validateFields(UNFRIENDLY_ERROR, true)) === true &&
|
||||
($lang_field_error = $category_to_create->validateFieldsLang(UNFRIENDLY_ERROR, true)) === true && $category_to_create->add()
|
||||
)
|
||||
{
|
||||
return (int)$category_to_create->id;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
protected static function createMultiLangField($field)
|
||||
{
|
||||
$res = array();
|
||||
foreach (Language::getIDs(false) as $id_lang)
|
||||
{
|
||||
$res[$id_lang] = $field;
|
||||
}
|
||||
|
||||
return $res;
|
||||
}
|
||||
|
||||
public function addImageToProduct($url, $id, $is_cover = false)
|
||||
{
|
||||
if (!empty($url))
|
||||
{
|
||||
$url = str_replace(' ', '%20', $url);
|
||||
|
||||
$image = new Image();
|
||||
$image->id_product = (int)$id;
|
||||
$image->position = Image::getHighestPosition($id) + 1;
|
||||
$image->cover = $is_cover;
|
||||
// file_exists doesn't work with HTTP protocol
|
||||
if (($field_error = $image->validateFields(UNFRIENDLY_ERROR, true)) === true &&
|
||||
($lang_field_error = $image->validateFieldsLang(UNFRIENDLY_ERROR, true)) === true && $image->add()
|
||||
)
|
||||
{
|
||||
// associate image to selected shops
|
||||
$shops = Shop::getContextListShopID();
|
||||
$image->associateTo($shops);
|
||||
if (!Creator::copyImg($id, $image->id, $url, 'products', true))
|
||||
{
|
||||
$image->delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function addFeaturesToProduct($features, $id)
|
||||
{
|
||||
foreach ($features as $single_feature)
|
||||
{
|
||||
if (empty($single_feature))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
$feature_name = $single_feature['feature'];
|
||||
$feature_value = $single_feature['feature_value'];
|
||||
$position = false;
|
||||
$custom = false;
|
||||
$id_lang = $this->id_lang;
|
||||
$id_product = (int)$id;
|
||||
if (!empty($feature_name) && !empty($feature_value))
|
||||
{
|
||||
$id_feature = (int)Feature::addFeatureImport($feature_name, $position);
|
||||
$id_feature_value = (int)FeatureValue::addFeatureValueImport($id_feature, $feature_value, $id_product, $id_lang, $custom);
|
||||
Product::addFeatureProductImport($id, $id_feature, $id_feature_value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function addAttributesToProduct($attributes_array, $id, $attribute_details = array())
|
||||
{
|
||||
|
||||
$product = new Product($id);
|
||||
|
||||
$this->settings['combination_price_multiplier'];
|
||||
|
||||
$attributes_to_add = array();
|
||||
$attributes_ids = array();
|
||||
|
||||
foreach ($attributes_array as $key => $attributes_full)
|
||||
{
|
||||
foreach ($attributes_full as $attribute_pair)
|
||||
{
|
||||
if (empty($attribute_pair['attribute_value']))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($id_attribute = $this->getAttributeId($attribute_pair))
|
||||
{
|
||||
$attributes_to_add[$key][] = $id_attribute;
|
||||
if (isset($attribute_details))
|
||||
{
|
||||
$attributes_ids[$id_attribute] = $attribute_pair['attribute_value'];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
$combinations = $this->generateCombinations($attributes_to_add);
|
||||
$attribute_details_par = array('price', 'ean', 'quantity', 'weight');
|
||||
|
||||
if (isset($attribute_details))
|
||||
{
|
||||
foreach ($attribute_details_par as $parameter)
|
||||
{
|
||||
foreach ($combinations as $key => $combination)
|
||||
{
|
||||
foreach ($combination as $c)
|
||||
{
|
||||
if (isset($attribute_details[$parameter][$attributes_ids[$c]]))
|
||||
{
|
||||
$combination_detais[$key][$parameter] = $attribute_details[$parameter][$attributes_ids[$c]];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($combinations as $key => $combination)
|
||||
{
|
||||
$implode_sql = array();
|
||||
if (!$combination) continue;
|
||||
$combination_price = 0;
|
||||
|
||||
if (isset($combination_detais[$key]['price']))
|
||||
{
|
||||
$combination_price = (float)$combination_detais[$key]['price'];
|
||||
if (!empty($this->settings['combination_price_multiplier']))
|
||||
{
|
||||
$combination_price *= (float)$this->settings['combination_price_multiplier'];
|
||||
}
|
||||
|
||||
if (empty($this->settings['add_combination_price']))
|
||||
{
|
||||
$combination_price -= $product->price;
|
||||
}
|
||||
|
||||
if ($combination_price < 0)
|
||||
{
|
||||
$combination_price = 0;
|
||||
}
|
||||
}
|
||||
$combination_ean = (!empty($combination_detais[$key]['ean']) && Validate::isEan13($combination_detais[$key]['ean'])) ? $combination_detais[$key]['ean'] : '';
|
||||
|
||||
$id_product_attribute = $product->productAttributeExists($combination, false, null, false, true); // Last 'true' is to return id
|
||||
if (!$id_product_attribute)
|
||||
{
|
||||
$combination_weight = isset($combination_detais[$key]['weight']) ? (float)$combination_detais[$key]['weight'] : 0;
|
||||
$combination_quantity = isset($combination_detais[$key]['quantity']) ? (int)$combination_detais[$key]['quantity'] : (int)$product->quantity;
|
||||
$id_product_attribute = $product->addCombinationEntity(
|
||||
(float) 0,
|
||||
$combination_price,
|
||||
$combination_weight,
|
||||
0,
|
||||
(Configuration::get('PS_USE_ECOTAX') ? (float) $product->ecotax : 0),
|
||||
$combination_quantity,
|
||||
null,
|
||||
'',
|
||||
0,
|
||||
$combination_ean,
|
||||
null
|
||||
);
|
||||
foreach ($combination as $id_attribute)
|
||||
{
|
||||
Db::getInstance()->execute('
|
||||
INSERT IGNORE INTO ' . _DB_PREFIX_ . 'product_attribute_combination (id_attribute, id_product_attribute)
|
||||
VALUES (' . (int) $id_attribute . ',' . (int) $id_product_attribute . ')', false);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (isset($attribute_details))
|
||||
{
|
||||
if (isset($combination_detais[$key]['price']))
|
||||
{
|
||||
$implode_sql['price'] = 'price = ' . (float)$combination_price;
|
||||
}
|
||||
|
||||
if (isset($combination_detais[$key]['weight']))
|
||||
{
|
||||
$implode_sql['weight'] = 'weight = ' . (float)$combination_detais[$key]['weight'];
|
||||
}
|
||||
|
||||
if (isset($combination_detais[$key]['ean']))
|
||||
{
|
||||
$implode_sql['ean13'] = 'ean13 = ' . pSQL($combination_ean);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($combination_detais[$key]['quantity']))
|
||||
{
|
||||
$implode_sql['quantity'] = 'quantity = ' . (int)$combination_detais[$key]['quantity'];
|
||||
StockAvailable::setQuantity($id, $id_product_attribute, (int)$combination_detais[$key]['quantity']);
|
||||
}
|
||||
|
||||
if ($implode_sql)
|
||||
{
|
||||
Db::getInstance()->execute('
|
||||
UPDATE ' . _DB_PREFIX_ . 'product_attribute SET ' . implode(', ', $implode_sql) . ' WHERE id_product_attribute = ' . (int)$id_product_attribute);
|
||||
unset($implode_sql['ean13']);
|
||||
unset($implode_sql['quantity']);
|
||||
Db::getInstance()->execute('
|
||||
UPDATE ' . _DB_PREFIX_ . 'product_attribute_shop SET ' . implode(', ', $implode_sql) . ' WHERE id_product_attribute = ' . (int)$id_product_attribute);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* copyImg copy an image located in $url and save it in a path
|
||||
* according to $entity->$id_entity .
|
||||
* $id_image is used if we need to add a watermark
|
||||
*
|
||||
* @param int $id_entity id of product or category (set in entity)
|
||||
* @param int $id_image (default null) id of the image if watermark enabled.
|
||||
* @param string $url path or url to use
|
||||
* @param string $entity 'products' or 'categories'
|
||||
* @param bool $regenerate
|
||||
* @return bool
|
||||
*/
|
||||
protected static function copyImg($id_entity, $id_image = null, $url, $entity = 'products', $regenerate = true)
|
||||
{
|
||||
$tmpfile = tempnam(_PS_TMP_IMG_DIR_, 'ps_import');
|
||||
$watermark_types = explode(',', Configuration::get('WATERMARK_TYPES'));
|
||||
|
||||
switch ($entity)
|
||||
{
|
||||
default:
|
||||
case 'products':
|
||||
$image_obj = new Image($id_image);
|
||||
$path = $image_obj->getPathForCreation();
|
||||
break;
|
||||
case 'categories':
|
||||
$path = _PS_CAT_IMG_DIR_ . (int)$id_entity;
|
||||
break;
|
||||
case 'manufacturers':
|
||||
$path = _PS_MANU_IMG_DIR_ . (int)$id_entity;
|
||||
break;
|
||||
case 'suppliers':
|
||||
$path = _PS_SUPP_IMG_DIR_ . (int)$id_entity;
|
||||
break;
|
||||
}
|
||||
|
||||
$url = urldecode(trim($url));
|
||||
$parced_url = parse_url($url);
|
||||
|
||||
if (isset($parced_url['path']))
|
||||
{
|
||||
$uri = ltrim($parced_url['path'], '/');
|
||||
$parts = explode('/', $uri);
|
||||
foreach ($parts as &$part)
|
||||
{
|
||||
$part = rawurlencode($part);
|
||||
}
|
||||
unset($part);
|
||||
$parced_url['path'] = '/' . implode('/', $parts);
|
||||
}
|
||||
|
||||
if (isset($parced_url['query']))
|
||||
{
|
||||
$query_parts = array();
|
||||
parse_str($parced_url['query'], $query_parts);
|
||||
$parced_url['query'] = http_build_query($query_parts);
|
||||
}
|
||||
|
||||
if (!function_exists('http_build_url'))
|
||||
{
|
||||
require_once(_PS_TOOL_DIR_ . 'http_build_url/http_build_url.php');
|
||||
}
|
||||
|
||||
$url = http_build_url('', $parced_url);
|
||||
|
||||
$orig_tmpfile = $tmpfile;
|
||||
|
||||
// download image by curl to avoid ssl problem
|
||||
$curl = curl_init();
|
||||
curl_setopt($curl, CURLOPT_URL, $url);
|
||||
curl_setopt($curl, CURLOPT_TIMEOUT, 50);
|
||||
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
|
||||
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
|
||||
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
|
||||
$image = curl_exec($curl);
|
||||
curl_close($curl);
|
||||
|
||||
// copy image to $tmpfile
|
||||
file_put_contents($tmpfile, $image);
|
||||
|
||||
// if $tmpfile is not readable, return false
|
||||
if (!filesize($tmpfile))
|
||||
{
|
||||
@unlink($tmpfile);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Evaluate the memory required to resize the image: if it's too much, you can't resize it.
|
||||
if (!ImageManager::checkImageMemoryLimit($tmpfile))
|
||||
{
|
||||
@unlink($tmpfile);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Sprawdź typ MIME pliku
|
||||
$finfo = finfo_open(FILEINFO_MIME_TYPE);
|
||||
$mime_type = finfo_file($finfo, $tmpfile);
|
||||
finfo_close($finfo);
|
||||
|
||||
if ($mime_type == 'image/webp')
|
||||
{
|
||||
// Wczytaj obraz WebP
|
||||
$image = imagecreatefromwebp($tmpfile);
|
||||
if ($image === false)
|
||||
{
|
||||
@unlink($tmpfile);
|
||||
return false;
|
||||
}
|
||||
// Zapisz obraz jako JPG, nadpisując oryginalny plik
|
||||
imagejpeg($image, $tmpfile, 100); // 100% jakości
|
||||
imagedestroy($image);
|
||||
}
|
||||
|
||||
if (!ImageManager::isRealImage($tmpfile))
|
||||
{
|
||||
@unlink($tmpfile);
|
||||
return false;
|
||||
}
|
||||
|
||||
$tgt_width = $tgt_height = 0;
|
||||
$src_width = $src_height = 0;
|
||||
$error = 0;
|
||||
ImageManager::resize(
|
||||
$tmpfile,
|
||||
$path . '.jpg',
|
||||
null,
|
||||
null,
|
||||
'jpg',
|
||||
false,
|
||||
$error,
|
||||
$tgt_width,
|
||||
$tgt_height,
|
||||
5,
|
||||
$src_width,
|
||||
$src_height
|
||||
);
|
||||
$images_types = ImageType::getImagesTypes($entity, true);
|
||||
|
||||
if ($regenerate)
|
||||
{
|
||||
$previous_path = null;
|
||||
$path_infos = array();
|
||||
$path_infos[] = array($tgt_width, $tgt_height, $path . '.jpg');
|
||||
foreach ($images_types as $image_type)
|
||||
{
|
||||
$tmpfile = self::get_best_path($image_type['width'], $image_type['height'], $path_infos);
|
||||
|
||||
if (ImageManager::resize(
|
||||
$tmpfile,
|
||||
$path . '-' . stripslashes($image_type['name']) . '.jpg',
|
||||
$image_type['width'],
|
||||
$image_type['height'],
|
||||
'jpg',
|
||||
false,
|
||||
$error,
|
||||
$tgt_width,
|
||||
$tgt_height,
|
||||
5,
|
||||
$src_width,
|
||||
$src_height
|
||||
))
|
||||
{
|
||||
// the last image should not be added in the candidate list if it's bigger than the original image
|
||||
if ($tgt_width <= $src_width && $tgt_height <= $src_height)
|
||||
{
|
||||
$path_infos[] = array($tgt_width, $tgt_height, $path . '-' . stripslashes($image_type['name']) . '.jpg');
|
||||
}
|
||||
if ($entity == 'products')
|
||||
{
|
||||
if (is_file(_PS_TMP_IMG_DIR_ . 'product_mini_' . (int)$id_entity . '.jpg'))
|
||||
{
|
||||
unlink(_PS_TMP_IMG_DIR_ . 'product_mini_' . (int)$id_entity . '.jpg');
|
||||
}
|
||||
if (is_file(_PS_TMP_IMG_DIR_ . 'product_mini_' . (int)$id_entity . '_' . (int)Context::getContext()->shop->id . '.jpg'))
|
||||
{
|
||||
unlink(_PS_TMP_IMG_DIR_ . 'product_mini_' . (int)$id_entity . '_' . (int)Context::getContext()->shop->id . '.jpg');
|
||||
}
|
||||
}
|
||||
}
|
||||
if (in_array($image_type['id_image_type'], $watermark_types))
|
||||
{
|
||||
Hook::exec('actionWatermark', array('id_image' => $id_image, 'id_product' => $id_entity));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unlink($orig_tmpfile);
|
||||
return true;
|
||||
}
|
||||
|
||||
private static function get_best_path($tgt_width, $tgt_height, $path_infos)
|
||||
{
|
||||
$path_infos = array_reverse($path_infos);
|
||||
$path = '';
|
||||
foreach ($path_infos as $path_info)
|
||||
{
|
||||
list($width, $height, $path) = $path_info;
|
||||
if ($width >= $tgt_width && $height >= $tgt_height)
|
||||
{
|
||||
return $path;
|
||||
}
|
||||
}
|
||||
return $path;
|
||||
}
|
||||
|
||||
public function getProductId($query, $table, $identifier = 'name')
|
||||
{
|
||||
$sql = new DbQuery();
|
||||
$sql->select('p.`id_product`, p.`ean13`, p.`upc`, p.`active`, p.`reference`');
|
||||
$sql->from('product', 'p');
|
||||
|
||||
if ($identifier == 'name')
|
||||
{
|
||||
$sql->join(Shop::addSqlAssociation('product', 'p'));
|
||||
$sql->leftJoin(
|
||||
'product_lang',
|
||||
'pl',
|
||||
'
|
||||
p.`id_product` = pl.`id_product`
|
||||
AND pl.`id_lang` = ' . (int)$this->id_lang . Shop::addSqlRestrictionOnLang('pl')
|
||||
);
|
||||
$where = 'pl.`name` = \'' . pSQL($query) . '\'';
|
||||
}
|
||||
else
|
||||
{
|
||||
$where = 'p.`' . $identifier . '` = \'' . pSQL($query) . '\'';
|
||||
}
|
||||
|
||||
$sql->where($where);
|
||||
|
||||
$sql->limit(1);
|
||||
|
||||
$result = Db::getInstance()->executeS($sql);
|
||||
|
||||
if (!empty($result[0]['id_product']))
|
||||
{
|
||||
return $result[0]['id_product'];
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
public function editProduct($product_id, $original_product)
|
||||
{
|
||||
$simple_fields = array('price', 'wholesale_price', 'additional_shipping_cost', 'ean13', 'ups', 'condition', 'width', 'height', 'depth', 'weight', 'active', 'minimal_quantity');
|
||||
$product = new Product($product_id);
|
||||
|
||||
if ($product->name == null)
|
||||
{
|
||||
return $product;
|
||||
}
|
||||
|
||||
if (!empty($this->settings['update_manufacturer']))
|
||||
{
|
||||
if (!empty($original_product['brand']))
|
||||
{
|
||||
$product->id_manufacturer = $this->getManufacturerId($original_product['brand']);
|
||||
}
|
||||
else
|
||||
{
|
||||
$product->id_manufacturer = $this->settings['default_manufacturer_id'];
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($simple_fields as $field)
|
||||
{
|
||||
if (!empty($this->settings['update_' . $field]) && isset($original_product[$field]))
|
||||
{
|
||||
$product->$field = $original_product[$field];
|
||||
}
|
||||
}
|
||||
if (isset($this->settings['update_id_tax_rules_group']) && $this->settings['id_tax_rules_group'] != -1)
|
||||
{
|
||||
$product->id_tax_rules_group = $this->settings['id_tax_rules_group'];
|
||||
}
|
||||
|
||||
foreach (Language::getLanguages(false) as $lang)
|
||||
{
|
||||
if (!empty($this->settings['update_name']))
|
||||
{
|
||||
$original_product['name'] = htmlspecialchars_decode($original_product['name']);
|
||||
$original_product['name'] = str_replace(['>', '<', '=', ';', '{', '}', '#'], ' ', $original_product['name']);
|
||||
$product->name[$lang['id_lang']] = $original_product['name'];
|
||||
$product->link_rewrite[$lang['id_lang']] = Tools::link_rewrite($original_product['name']);
|
||||
$product->meta_keywords[$lang['id_lang']] = str_replace(' ', ',', $original_product['name']);
|
||||
}
|
||||
|
||||
if (!empty($this->settings['update_description']))
|
||||
{
|
||||
$original_product['description'] = nl2br($original_product['description']);
|
||||
$original_product['description'] = htmlspecialchars_decode(htmlspecialchars_decode($original_product['description'], ENT_COMPAT));
|
||||
$product->description_long[$lang['id_lang']] = $original_product['description'];
|
||||
$product->description[$lang['id_lang']] = $original_product['description'];
|
||||
}
|
||||
|
||||
if (!empty($original_product['short_description']) && !empty($this->settings['update_short_description']))
|
||||
{
|
||||
$product->description_short[$lang['id_lang']] = $original_product['short_description'];
|
||||
}
|
||||
}
|
||||
|
||||
$product->additional_delivery_times = 2;
|
||||
$product->delivery_in_stock[7] = '1-5 dni roboczych';
|
||||
|
||||
//$product->active = isset($original_product['active']) ? (int)$original_product['active'] : 1;;
|
||||
|
||||
$product->save();
|
||||
|
||||
if (!empty($this->settings['update_quantity']))
|
||||
{
|
||||
StockAvailable::setQuantity((int)$product_id, 0, $original_product['quantity']);
|
||||
}
|
||||
|
||||
// check if product has no images
|
||||
$images_count = "SELECT COUNT(0) FROM " . _DB_PREFIX_ . "image WHERE id_product = " . $product->id;
|
||||
$result_images_count = Db::getInstance()->getValue($images_count);
|
||||
|
||||
if (!empty($this->settings['update_images']) and $result_images_count == 0)
|
||||
{
|
||||
foreach ($original_product['images'] as $image_url)
|
||||
{
|
||||
$this->addImageToProduct($image_url, $product->id);
|
||||
}
|
||||
|
||||
if ($original_product['cover'])
|
||||
{
|
||||
$this->addImageToProduct($original_product['cover'], $product->id, true);
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($this->settings['update_cover']) && !empty($original_product['cover']))
|
||||
{
|
||||
$this->addImageToProduct($original_product['cover'], $product->id, true);
|
||||
}
|
||||
|
||||
if ($original_product['feature'] and $original_product['feature_value'])
|
||||
{
|
||||
$original_product['features'] = array(
|
||||
array(
|
||||
'feature' => $original_product['feature'],
|
||||
'feature_value' => $original_product['feature_value']
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
if (!empty($this->settings['update_features']) && !empty($original_product['features']))
|
||||
{
|
||||
$this->addFeaturesToProduct($original_product['features'], $product->id);
|
||||
}
|
||||
|
||||
if (!empty($this->settings['update_attributes']) && !empty($original_product['attributes']))
|
||||
{
|
||||
$attribute_details = !empty($original_product['attribute_details']) ? $original_product['attribute_details'] : array();
|
||||
$this->addAttributesToProduct($original_product['attributes'], $product->id, $attribute_details);
|
||||
}
|
||||
|
||||
if ( $this -> settings['update_active'] )
|
||||
{
|
||||
$sql = 'UPDATE ' . _DB_PREFIX_ . 'product SET active = ' . (int)$original_product['active'] . ' WHERE id_product = ' . (int)$product->id;
|
||||
Db::getInstance()->execute($sql);
|
||||
// materac_product_shop
|
||||
$sql_shop = 'UPDATE ' . _DB_PREFIX_ . 'product_shop SET active = ' . (int)$original_product['active'] . ' WHERE id_product = ' . (int)$product->id;
|
||||
Db::getInstance()->execute($sql_shop);
|
||||
}
|
||||
|
||||
if ( $this -> settings['update_quantity'] )
|
||||
{
|
||||
$sql = 'UPDATE ' . _DB_PREFIX_ . 'stock_available SET quantity = ' . (int)$original_product['quantity'] . ' WHERE id_product = ' . (int)$product->id;
|
||||
Db::getInstance()->execute($sql);
|
||||
}
|
||||
|
||||
return $product;
|
||||
}
|
||||
|
||||
public function processMissing($file_id, $queue_id)
|
||||
{
|
||||
$sql = "SELECT * FROM " . _DB_PREFIX_ . "ia_products WHERE shop = 'default' AND file_id = " . (int)$file_id . " AND queue_id != " . (int)$queue_id;
|
||||
|
||||
//$sql .= " LIMIT 20";
|
||||
|
||||
if (!empty($this->settings['not_existing']) && $products = Db::getInstance()->executeS($sql))
|
||||
{
|
||||
|
||||
if ($this->settings['not_existing'] == 1)
|
||||
{
|
||||
foreach ($products as $product)
|
||||
{
|
||||
StockAvailable::setQuantity((int)$product['product_id'], 0, 0);
|
||||
}
|
||||
}
|
||||
elseif ($this->settings['not_existing'] == 2)
|
||||
{
|
||||
foreach ($products as $product)
|
||||
{
|
||||
$productObject = new Product($product['product_id']);
|
||||
if ($productObject->name)
|
||||
{
|
||||
$productObject->active = 0;
|
||||
$productObject->save();
|
||||
}
|
||||
}
|
||||
}
|
||||
elseif ($this->settings['not_existing'] == 3)
|
||||
{
|
||||
foreach ($products as $product)
|
||||
{
|
||||
$productObject = new Product($product['product_id']);
|
||||
if ($productObject->name)
|
||||
{
|
||||
$productObject->delete();
|
||||
}
|
||||
Db::getInstance()->execute("DELETE FROM " . _DB_PREFIX_ . "ia_products WHERE product_id = '" . (int)$product['product_id'] . "'");
|
||||
}
|
||||
}
|
||||
}
|
||||
Db::getInstance()->execute("UPDATE " . _DB_PREFIX_ . "ia_queues SET source = 'admin', status = '4', date_processed = '" . time() . "' WHERE queue_id = '" . (int)$queue_id . "'");
|
||||
}
|
||||
|
||||
public function setAttributes()
|
||||
{
|
||||
$default_language = $this->id_lang;
|
||||
|
||||
$this->groups = array();
|
||||
|
||||
foreach (AttributeGroup::getAttributesGroups($default_language) as $group)
|
||||
{
|
||||
$this->groups[$group['name']] = (int) $group['id_attribute_group'];
|
||||
}
|
||||
|
||||
$this->attributes = array();
|
||||
|
||||
foreach (Attribute::getAttributes($default_language) as $attribute)
|
||||
{
|
||||
$this->attributes[$attribute['attribute_group'] . '_' . $attribute['name']] = (int) $attribute['id_attribute'];
|
||||
}
|
||||
}
|
||||
|
||||
function getAttributeGroupId($name)
|
||||
{
|
||||
$tab_group = explode(':', $name);
|
||||
$group = trim($tab_group[0]);
|
||||
if (isset($this->groups[$group]))
|
||||
{
|
||||
return $this->groups[$group];
|
||||
}
|
||||
if (!isset($tab_group[1]))
|
||||
{
|
||||
$type = 'select';
|
||||
}
|
||||
else
|
||||
{
|
||||
$type = trim($tab_group[1]);
|
||||
}
|
||||
$obj = new AttributeGroup();
|
||||
$obj->is_color_group = false;
|
||||
$obj->group_type = pSQL($type);
|
||||
$obj->name[$this->id_lang] = $group;
|
||||
$obj->public_name[$this->id_lang] = $group;
|
||||
//$obj->position = (!$position) ? AttributeGroup::getHigherPosition() + 1 : $position;
|
||||
$obj->add();
|
||||
$this->groups[$group] = $obj->id;
|
||||
return $obj->id;
|
||||
}
|
||||
|
||||
function getAttributeId($pair)
|
||||
{
|
||||
$name = $pair['attribute_value'];
|
||||
$group = $pair['attribute'];
|
||||
|
||||
if (isset($this->attributes[$group . '_' . $name]))
|
||||
{
|
||||
return $this->attributes[$group . '_' . $name];
|
||||
}
|
||||
|
||||
$id_attribute_group = $this->getAttributeGroupId($group);
|
||||
|
||||
$obj = new Attribute();
|
||||
$obj->id_attribute_group = $id_attribute_group;
|
||||
$obj->name[$this->id_lang] = str_replace('\n', '', str_replace('\r', '', $name));
|
||||
$obj->add();
|
||||
$this->attributes[$group . '_' . $name] = $obj->id;
|
||||
return $obj->id;
|
||||
}
|
||||
|
||||
function generateCombinations($attributes_to_add)
|
||||
{
|
||||
$i = 0;
|
||||
$combinations = array();
|
||||
// 3 options
|
||||
if (count($attributes_to_add) == 3)
|
||||
{
|
||||
foreach ($attributes_to_add[1] as $attr_1)
|
||||
{
|
||||
$temp_1 = isset($combinations[$i]) ? $combinations[$i] : array();
|
||||
$combinations[$i][] = $attr_1;
|
||||
foreach ($attributes_to_add[2] as $attr_2)
|
||||
{
|
||||
$temp_2 = $combinations[$i];
|
||||
$combinations[$i][] = $attr_2;
|
||||
foreach ($attributes_to_add[3] as $attr_3)
|
||||
{
|
||||
$temp_3 = $combinations[$i];
|
||||
$combinations[$i][] = $attr_3;
|
||||
$i++;
|
||||
$combinations[$i] = $temp_3;
|
||||
}
|
||||
|
||||
$combinations[$i] = $temp_2;
|
||||
}
|
||||
$combinations[$i] = $temp_1;
|
||||
}
|
||||
}
|
||||
elseif (count($attributes_to_add) == 2 && isset($attributes_to_add[1]))
|
||||
{
|
||||
foreach ($attributes_to_add[1] as $attr_1)
|
||||
{
|
||||
$temp_1 = isset($combinations[$i]) ? $combinations[$i] : array();
|
||||
$combinations[$i][] = $attr_1;
|
||||
foreach ($attributes_to_add[2] as $attr_2)
|
||||
{
|
||||
$temp_2 = $combinations[$i];
|
||||
$combinations[$i][] = $attr_2;
|
||||
$i++;
|
||||
$combinations[$i] = $temp_2;
|
||||
}
|
||||
|
||||
$combinations[$i] = $temp_1;
|
||||
}
|
||||
}
|
||||
elseif (count($attributes_to_add) == 1 && isset($attributes_to_add[1]))
|
||||
{
|
||||
foreach ($attributes_to_add[1] as $attr_1)
|
||||
{
|
||||
//$temp_0 = isset($combinations[$i]) ? $combinations[$i] : array();
|
||||
$combinations[$i][] = $attr_1;
|
||||
|
||||
$i++;
|
||||
//$combinations[$i] = $temp_0;
|
||||
}
|
||||
}
|
||||
return $combinations;
|
||||
}
|
||||
}
|
||||
425
modules/import_api/classes/filereader.php
Normal file
425
modules/import_api/classes/filereader.php
Normal file
@@ -0,0 +1,425 @@
|
||||
<?php
|
||||
/**
|
||||
* NOTICE OF LICENSE
|
||||
* With the purchase or the installation of the software in your application
|
||||
* you accept the license agreement.
|
||||
*
|
||||
* You can not resell and redistribute this file.
|
||||
*
|
||||
* @author Dalibor Stojcevski <dal_sto@yahoo.com>
|
||||
* @copyright 2019 Dalibor Stojcevski
|
||||
* @license Dalibor Stojcevski
|
||||
*/
|
||||
ini_set('memory_limit', '-1');
|
||||
ini_set('display_startup_errors', 1);
|
||||
ini_set('display_errors', 1);
|
||||
error_reporting(E_ALL ^ E_DEPRECATED);
|
||||
|
||||
/**
|
||||
* Adds the depreciated each() function back into 7.2
|
||||
*/
|
||||
if (!function_exists('each')) {
|
||||
function each($arr) {
|
||||
$key = key($arr);
|
||||
$result = ($key === null) ? false : [$key, current($arr), 'key' => $key, 'value' => current($arr)];
|
||||
next($arr);
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
if (!function_exists('array_key_first')) {
|
||||
function array_key_first(array $arr) {
|
||||
foreach($arr as $key => $unused) {
|
||||
return $key;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
class FileReader
|
||||
{
|
||||
public $types = array(
|
||||
'csv' => array(
|
||||
'application/octet-stream',
|
||||
'text/csv',
|
||||
'application/csv',
|
||||
'text/comma-separated-values',
|
||||
'application/excel',
|
||||
'application/vnd.ms-excel',
|
||||
'application/vnd.msexcel',
|
||||
),
|
||||
'json' => array(
|
||||
'application/json',
|
||||
'text/json',
|
||||
'application/x-javascript',
|
||||
'application/javascript',
|
||||
'text/javascript',
|
||||
'text/x-javascript',
|
||||
'text/x-json',
|
||||
),
|
||||
'xml' => array(
|
||||
'application/xml',
|
||||
'text/xml',
|
||||
)
|
||||
);
|
||||
|
||||
public $mime = '';
|
||||
|
||||
public function getFile($link, $post = '', $curl = true) {
|
||||
|
||||
$link = str_replace('amp;', '', $link);
|
||||
//$link = urlencode($link);
|
||||
$link = str_replace(" ", "%20", $link); // to properly format the url
|
||||
$link_parts = parse_url($link);
|
||||
if (!empty($link_parts['user']) && !empty($link_parts['pass'])) {
|
||||
$link = str_replace($link_parts['user'] . ':' . $link_parts['pass'] . '@', '', $link);
|
||||
}
|
||||
|
||||
if($curl) {
|
||||
$error_msg = '';
|
||||
|
||||
$ch = curl_init();
|
||||
|
||||
curl_setopt($ch, CURLOPT_URL, $link);
|
||||
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
|
||||
curl_setopt($ch, CURLOPT_FAILONERROR, true); // Required for HTTP error codes to be reported via our call to curl_error($ch)
|
||||
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
|
||||
|
||||
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); // This is very important if url have download
|
||||
|
||||
if ($post) {
|
||||
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
|
||||
'Content-Type: application/xml',
|
||||
'Content-Length: ' . strlen($post))
|
||||
);
|
||||
curl_setopt($ch, CURLOPT_POSTFIELDS, $post);
|
||||
|
||||
}
|
||||
|
||||
if (!empty($link_parts['user']) && !empty($link_parts['pass'])) {
|
||||
curl_setopt($ch, CURLOPT_USERPWD, $link_parts['user'] . ":" . $link_parts['pass']);
|
||||
}
|
||||
|
||||
|
||||
$server_output = curl_exec($ch);
|
||||
|
||||
$mime_parts = curl_getinfo($ch, CURLINFO_CONTENT_TYPE);
|
||||
|
||||
if ($mime_parts) {
|
||||
$mime = explode(';', $mime_parts);
|
||||
$this->mime = isset($mime[0]) ? $mime[0] : '';
|
||||
}
|
||||
|
||||
if (curl_errno($ch)) {
|
||||
$error_msg = curl_error($ch);
|
||||
//print_r('--'. $error_msg .'-');
|
||||
//var_dump($link);
|
||||
//exit;
|
||||
}
|
||||
curl_close($ch);
|
||||
unset($ch);
|
||||
|
||||
return array($server_output, $error_msg);
|
||||
|
||||
} else {
|
||||
if (!empty($link_parts['user']) && !empty($link_parts['pass'])) {
|
||||
$auth = base64_encode($link_parts['user'] . ":" . $link_parts['pass']);
|
||||
$context = stream_context_create([
|
||||
"http" => [
|
||||
"header" => "Authorization: Basic $auth"
|
||||
]
|
||||
]);
|
||||
$server_output = @file_get_contents($link, false, $context);
|
||||
} else {
|
||||
$server_output = @file_get_contents($link);
|
||||
}
|
||||
return array($server_output,'');
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function getArrayFromLink($file) {
|
||||
|
||||
$substring = '';
|
||||
|
||||
$php_array = array();
|
||||
|
||||
$link = trim($file['link']);
|
||||
$source = trim($file['source']);
|
||||
$post = trim($file['post']);
|
||||
$delimiter = !empty($file['delimiter']) ? $file['delimiter'] : '';
|
||||
$headers = !empty($file['headers']) ? $file['headers'] : 0;
|
||||
|
||||
$session_file_name = 'tmp/files/' . $file['shop'] .'/session_' . session_id() . '_' . $file['file_id']. '.txt';
|
||||
|
||||
$file_ext = pathinfo($link, PATHINFO_EXTENSION);
|
||||
if (in_array($file_ext, ['xlsx', 'xls'])) {
|
||||
$source = 'excel';
|
||||
}
|
||||
if ($source == 'excel') {
|
||||
$error = '';
|
||||
$external_string = '';
|
||||
|
||||
} else {
|
||||
list($external_string, $error) = $result = $this->getFile($link, $post);
|
||||
if (empty($external_string)) {
|
||||
list($external_string, $error) = $result = $this->getFile($link, $post, false);
|
||||
}
|
||||
if (!$error && $external_string) {
|
||||
//file_put_contents($session_file_name, $external_string);
|
||||
}
|
||||
}
|
||||
|
||||
if ($error) {
|
||||
return array('', $error);
|
||||
}
|
||||
|
||||
$mime = $file['mime_type'] ? trim($file['mime_type']) : $this->mime;
|
||||
|
||||
if ($external_string === false){
|
||||
$error = 'External file not found. Check link in browser';
|
||||
return array('', $error);
|
||||
}
|
||||
|
||||
$external_string = $this->removeBOM($external_string);
|
||||
$external_string = trim($external_string);
|
||||
|
||||
if (!$source) {
|
||||
|
||||
$substring = $external_string ? substr($external_string, 0, 200) : ' ';
|
||||
|
||||
|
||||
$substring = preg_replace('/[\x00-\x1F\x80-\xFF]/', '', $substring);
|
||||
if (!$substring) {
|
||||
$substring = ' ';
|
||||
}
|
||||
if (in_array($substring[0],['<'])) {
|
||||
$source = 'xml';
|
||||
} elseif (in_array($substring[0],['[', '{'])) {
|
||||
$source = 'json';
|
||||
} elseif ($mime) {
|
||||
$source = $this->matchMimeType($mime);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if ($source == 'json') {
|
||||
$json_string = $external_string;
|
||||
$php_array = json_decode($json_string, true);
|
||||
}
|
||||
|
||||
if ($source == 'xml') {
|
||||
libxml_use_internal_errors(true);
|
||||
$ob = simplexml_load_string($external_string, 'SimpleXMLElement', LIBXML_NOCDATA | LIBXML_PARSEHUGE);
|
||||
if ($ob) {
|
||||
$php_array = $this->xmlToArray($ob);
|
||||
} else {
|
||||
//echo libxml_get_errors();
|
||||
return array($php_array, libxml_get_errors());
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
ini_set('auto_detect_line_endings',TRUE);
|
||||
|
||||
if ($source == 'excel') {
|
||||
$parts = explode('/modules/import_api/views/img/', $link);
|
||||
if (isset($parts[1])) {
|
||||
$file_path = 'modules/importer_api/views/img/' . $parts[1];
|
||||
} else {
|
||||
return array([], 'File not found ( excel error )');
|
||||
}
|
||||
|
||||
if ($file_ext == 'xlsx') {
|
||||
require_once(_PS_MODULE_DIR_ . 'import_api/lib/SimpleXLSX.php');
|
||||
$xls = new SimpleXLSX($file_path);
|
||||
} elseif ($file_ext == 'xls') {
|
||||
require_once(_PS_MODULE_DIR_ . 'import_api/lib/SimpleXLS.php');
|
||||
$xls = new SimpleXLS($file_path);
|
||||
}
|
||||
|
||||
if ($xls->success()) {
|
||||
foreach($xls->rows() as $row){
|
||||
if (empty($index)) {
|
||||
if ($headers) {
|
||||
$c = 1;
|
||||
foreach ($row as $r) {
|
||||
$index[] = 'COLUMN ' . $c;
|
||||
$c++;
|
||||
}
|
||||
|
||||
} else {
|
||||
$index = $row;
|
||||
}
|
||||
|
||||
} else {
|
||||
$php_array[] = @array_combine($index, $row);
|
||||
}
|
||||
|
||||
}
|
||||
} else {
|
||||
return array([], 'Error reading Excel file. ' . $xls->error());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (!$php_array || $source == 'csv') {
|
||||
|
||||
$fp = tmpfile();
|
||||
fwrite($fp, $external_string);
|
||||
rewind($fp); //rewind to process CSV
|
||||
|
||||
if (!$delimiter) {
|
||||
$delimiter = $this->detectDelimiter($fp);
|
||||
}
|
||||
|
||||
while (($row = fgetcsv($fp, 0, $delimiter)) !== FALSE) {
|
||||
if (empty($index)) {
|
||||
if ($headers) {
|
||||
$c = 1;
|
||||
foreach ($row as $r) {
|
||||
$index[] = 'COLUMN ' . $c;
|
||||
$c++;
|
||||
}
|
||||
|
||||
} else {
|
||||
$index = $row;
|
||||
}
|
||||
|
||||
} else {
|
||||
$php_array[] = @array_combine($index, $row);
|
||||
}
|
||||
}
|
||||
/*
|
||||
$external_array = explode("\n", $external_string);
|
||||
$index = str_getcsv(array_shift($external_array)); // not work with new lines
|
||||
$php_array = null;
|
||||
foreach ($external_array as $e) {
|
||||
if ($e)
|
||||
$php_array[] = @array_combine($index, $row);
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
if (!$php_array && $file['source']) {
|
||||
$file['source'] = '';
|
||||
return $this->getArrayFromLink($file);
|
||||
}
|
||||
|
||||
|
||||
return array($php_array, '');
|
||||
}
|
||||
|
||||
public function xmlToArray($xml, $options = array()) {
|
||||
$defaults = array(
|
||||
'namespaceSeparator' => ':',//you may want this to be something other than a colon
|
||||
'attributePrefix' => '@', //to distinguish between attributes and nodes with the same name
|
||||
'alwaysArray' => array(), //array of xml tag names which should always become arrays
|
||||
'autoArray' => true, //only create arrays for tags which appear more than once
|
||||
'textContent' => 'VAL', //key used for the text content of elements
|
||||
'autoText' => true, //skip textContent key if node has no attributes or child nodes
|
||||
'keySearch' => false, //optional search and replace on tag and attribute names
|
||||
'keyReplace' => false //replace values for above search values (as passed to str_replace())
|
||||
);
|
||||
$options = array_merge($defaults, $options);
|
||||
$namespaces = $xml->getDocNamespaces();
|
||||
$namespaces[''] = null; //add base (empty) namespace
|
||||
|
||||
//get attributes from all namespaces
|
||||
$attributesArray = array();
|
||||
foreach ($namespaces as $prefix => $namespace) {
|
||||
foreach ($xml->attributes($namespace) as $attributeName => $attribute) {
|
||||
//replace characters in attribute name
|
||||
if ($options['keySearch']) $attributeName =
|
||||
str_replace($options['keySearch'], $options['keyReplace'], $attributeName);
|
||||
$attributeKey = $options['attributePrefix']
|
||||
. ($prefix ? $prefix . $options['namespaceSeparator'] : '')
|
||||
. $attributeName;
|
||||
$attributesArray[$attributeKey] = (string)$attribute;
|
||||
}
|
||||
}
|
||||
|
||||
//get child nodes from all namespaces
|
||||
$tagsArray = array();
|
||||
foreach ($namespaces as $prefix => $namespace) {
|
||||
foreach ($xml->children($namespace) as $childXml) {
|
||||
//recurse into child nodes
|
||||
$childArray = $this->xmlToArray($childXml, $options);
|
||||
list($childTagName, $childProperties) = each($childArray);
|
||||
|
||||
//replace characters in tag name
|
||||
if ($options['keySearch']) $childTagName =
|
||||
str_replace($options['keySearch'], $options['keyReplace'], $childTagName);
|
||||
//add namespace prefix, if any
|
||||
if ($prefix) $childTagName = $prefix . $options['namespaceSeparator'] . $childTagName;
|
||||
|
||||
if (!isset($tagsArray[$childTagName])) {
|
||||
//only entry with this key
|
||||
//test if tags of this type should always be arrays, no matter the element count
|
||||
$tagsArray[$childTagName] =
|
||||
in_array($childTagName, $options['alwaysArray']) || !$options['autoArray']
|
||||
? array($childProperties) : $childProperties;
|
||||
} elseif (
|
||||
is_array($tagsArray[$childTagName]) && array_keys($tagsArray[$childTagName])
|
||||
=== range(0, count($tagsArray[$childTagName]) - 1)
|
||||
) {
|
||||
//key already exists and is integer indexed array
|
||||
$tagsArray[$childTagName][] = $childProperties;
|
||||
} else {
|
||||
//key exists so convert to integer indexed array with previous value in position 0
|
||||
$tagsArray[$childTagName] = array($tagsArray[$childTagName], $childProperties);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//get text content of node
|
||||
$textContentArray = array();
|
||||
$plainText = trim((string)$xml);
|
||||
if ($plainText !== '') $textContentArray[$options['textContent']] = $plainText;
|
||||
|
||||
//stick it all together
|
||||
$propertiesArray = !$options['autoText'] || $attributesArray || $tagsArray || ($plainText === '')
|
||||
? array_merge($attributesArray, $tagsArray, $textContentArray) : $plainText;
|
||||
|
||||
//return node as array
|
||||
return array(
|
||||
$xml->getName() => $propertiesArray
|
||||
);
|
||||
}
|
||||
|
||||
public function matchMimeType($mime) {
|
||||
|
||||
foreach ($this->types as $type => $list) {
|
||||
if (in_array($mime, $list)) {
|
||||
return $type;
|
||||
}
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
public function detectDelimiter($fh) {
|
||||
$delimiters = [";","\t", "|", ","];
|
||||
$data_1 = null; $data_2 = array();
|
||||
$delimiter = $delimiters[0];
|
||||
foreach($delimiters as $d) {
|
||||
$data_1 = fgetcsv($fh, 4096, $d);
|
||||
if(sizeof($data_1) > sizeof($data_2)) {
|
||||
$delimiter = $d;
|
||||
$data_2 = $data_1;
|
||||
}
|
||||
rewind($fh);
|
||||
}
|
||||
|
||||
return $delimiter;
|
||||
}
|
||||
|
||||
function removeBOM($data) {
|
||||
if (0 === strpos(bin2hex($data), 'efbbbf')) {
|
||||
return substr($data, 3);
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
554
modules/import_api/classes/import.php
Normal file
554
modules/import_api/classes/import.php
Normal file
@@ -0,0 +1,554 @@
|
||||
<?php
|
||||
/**
|
||||
* NOTICE OF LICENSE
|
||||
* With the purchase or the installation of the software in your application
|
||||
* you accept the license agreement.
|
||||
*
|
||||
* You can not resell and redistribute this file.
|
||||
*
|
||||
* @author Dalibor Stojcevski <dal_sto@yahoo.com>
|
||||
* @copyright 2019 Dalibor Stojcevski
|
||||
* @license Dalibor Stojcevski
|
||||
*/
|
||||
|
||||
/** No max line limit since the lines can be more than 4096. Performance impact is not significant. */
|
||||
|
||||
function filter_category_array ($element) {
|
||||
return (!is_array($element) && $element !== '');
|
||||
}
|
||||
|
||||
define('MAX_LINE_SIZE', 0);
|
||||
|
||||
class Import
|
||||
{
|
||||
|
||||
private $json_array = array();
|
||||
private $product_links = array();
|
||||
private $settings;
|
||||
|
||||
public function __construct($settings)
|
||||
{
|
||||
$this->settings = $settings;
|
||||
}
|
||||
|
||||
public function getAllData($path, $test = false)
|
||||
{
|
||||
$fields = $this->settings['import_api_field'];
|
||||
$nested_data = array();
|
||||
|
||||
$id_parts = explode('->', $path);
|
||||
|
||||
array_shift($id_parts);
|
||||
|
||||
foreach ($fields as $field => $value) {
|
||||
if(!$value) continue;
|
||||
$field_paths = $value ? html_entity_decode($value, ENT_QUOTES, 'UTF-8') : '';
|
||||
$field_parts = explode('->', $field_paths);
|
||||
|
||||
$nested_data[$field] = $this->getFieldData($this->json_array, $field_parts, $id_parts);
|
||||
}
|
||||
|
||||
if ($test == 'view-raw') {
|
||||
return $nested_data;
|
||||
}
|
||||
|
||||
$nested_data = $this->checkCombinations($nested_data);
|
||||
|
||||
if ($test == 'view-split') {
|
||||
return $nested_data;
|
||||
}
|
||||
|
||||
$original_product = $this->resolveAllNestedData($nested_data);
|
||||
|
||||
if ($test == 'view-grouping') {
|
||||
return $original_product;
|
||||
}
|
||||
|
||||
$modified = $this->changeOriginal($original_product);
|
||||
|
||||
return $modified;
|
||||
}
|
||||
|
||||
public function resolveAllNestedData($nested_data)
|
||||
{
|
||||
if (!empty($nested_data['feature_value'])) {
|
||||
|
||||
if (empty($nested_data['feature'])) {
|
||||
if (!empty($this->settings['import_api_modification']['feature'])) {
|
||||
$nested_data['feature'] = $this->settings['import_api_modification']['feature'];
|
||||
} else {
|
||||
$nested_data['feature'] = 'Feature';
|
||||
}
|
||||
}
|
||||
|
||||
$feature_map = $this->resolveNested($nested_data['feature_value'], $nested_data['feature']);
|
||||
$nested_data['features'] = array();
|
||||
|
||||
foreach ($feature_map as $key => $map) {
|
||||
$nested_data['features'][$key] = array(
|
||||
'feature' => $map['parent'],
|
||||
'feature_value' => $map['value']
|
||||
);
|
||||
}
|
||||
}
|
||||
$nested_data['attributes'] = array();
|
||||
for ($i = 1;$i <= 3; $i++) {
|
||||
|
||||
if (!empty($nested_data['attribute_value' . $i])) {
|
||||
if (empty($nested_data['attribute' . $i])) {
|
||||
if (!empty($this->settings['import_api_modification']['attribute' . $i])) {
|
||||
$nested_data['attribute' . $i] = $this->settings['import_api_modification']['attribute' . $i];
|
||||
} else {
|
||||
$nested_data['attribute' . $i] = 'Select ' . $i;
|
||||
}
|
||||
}
|
||||
|
||||
$attribute_map = $this->resolveNested($nested_data['attribute_value' . $i], $nested_data['attribute' . $i]);
|
||||
|
||||
$attribute_details_par = array('price', 'ean', 'quantity', 'weight');
|
||||
foreach ($attribute_map as $key => $map) {
|
||||
foreach ($attribute_details_par as $parameter) {
|
||||
if (isset($nested_data['attribute_' . $parameter])) {
|
||||
if (is_array($nested_data['attribute_' . $parameter])) {
|
||||
if (isset($nested_data['attribute_' . $parameter][$key])) {
|
||||
$nested_data['attribute_details'][$parameter][$map['value']] = $nested_data['attribute_' . $parameter][$key];
|
||||
}
|
||||
} else {
|
||||
$nested_data['attribute_details'][$parameter][$map['value']] = $nested_data['attribute_' . $parameter];
|
||||
}
|
||||
}
|
||||
}
|
||||
$nested_data['attributes'][$i][$key] = array(
|
||||
'attribute' => $map['parent'],
|
||||
'attribute_value' => $map['value']
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($nested_data['category'])) {
|
||||
|
||||
if (!isset($nested_data['category_parent'])) {
|
||||
$nested_data['category_parent'] = 0; // it is not good idea to put default top category here
|
||||
}
|
||||
|
||||
if ($this->settings['import_api_settings']['category_path'] && is_array($nested_data['category'])) {
|
||||
|
||||
$nested_data['category'] = implode('->', array_filter($nested_data['category'], "filter_category_array"));
|
||||
}
|
||||
|
||||
$nested_data['category_path'] = $this->resolveNested($nested_data['category'], $nested_data['category_parent']);
|
||||
}
|
||||
|
||||
$nested_data['options'] = array();
|
||||
if (!empty($nested_data['option_value'])) {
|
||||
|
||||
if (!isset($nested_data['option'])) {
|
||||
$nested_data['option'] = $this->settings['import_api_default_option'];
|
||||
}
|
||||
|
||||
if (!isset($nested_data['option_price'])) {
|
||||
$nested_data['option_price'] = 0;
|
||||
}
|
||||
|
||||
if (!isset($nested_data['option_weight'])) {
|
||||
$nested_data['option_weight'] = 0;
|
||||
}
|
||||
|
||||
$option_map= $this->resolveNested($nested_data['option_value'], $nested_data['option']);
|
||||
$option_price_map = $this->resolveNested($nested_data['option_price'], $nested_data['option_value']);
|
||||
$option_weight_map = $this->resolveNested($nested_data['option_weight'], $nested_data['option_value']);
|
||||
foreach ($option_map as $key => $map) {
|
||||
if (is_array($nested_data['option_price'])) {
|
||||
foreach ($option_price_map as $price_map) {
|
||||
if ($map['value'] == $price_map['parent']) {
|
||||
$nested_data['options'][$key] = array(
|
||||
'option' => $map['parent'],
|
||||
'option_value' => $map['value'],
|
||||
'price' => $price_map['value']
|
||||
);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$nested_data['options'][$key] = array(
|
||||
'option' => $map['parent'],
|
||||
'option_value' => $map['value'],
|
||||
'price' => $nested_data['option_price']
|
||||
);
|
||||
}
|
||||
|
||||
if (is_array($nested_data['option_weight'])) {
|
||||
foreach ($option_weight_map as $weight_map) {
|
||||
if($map['value'] == $weight_map['parent']){
|
||||
$nested_data['options'][$key]['weight'] = $weight_map['value'];
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$nested_data['options'][$key]['weight'] = $nested_data['option_weight'];
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return $nested_data;
|
||||
}
|
||||
public function getFieldData($tree, $field_parts, $id_parts)
|
||||
{
|
||||
while($field_parts) {
|
||||
if ($this->isSeq($tree)) {
|
||||
$seq_id = array_shift($id_parts);
|
||||
$tree = $tree[$seq_id];
|
||||
} else {
|
||||
|
||||
$part = array_shift($field_parts);
|
||||
$uni_c = array_shift($id_parts);
|
||||
|
||||
if($part == $uni_c){
|
||||
$tree = $tree[$part];
|
||||
|
||||
} else {
|
||||
$field_parts = array_merge([$part], $field_parts); // vrati mu ga
|
||||
return $this->followDifferentPath($field_parts, $tree);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function followDifferentPath($own_parts, $tree){
|
||||
$prev= ''; // for test
|
||||
foreach($own_parts as $part){
|
||||
//if ($part == 'image') {var_dump($tree);var_dump($own_parts);exit;}
|
||||
|
||||
if ($this->isSeq($tree)) {
|
||||
$ret = array();
|
||||
foreach($tree as $t){
|
||||
$ret[] = $this->followDifferentPath($own_parts, $t);
|
||||
}
|
||||
return $ret;
|
||||
} else {
|
||||
array_shift($own_parts);
|
||||
$tree = isset($tree[$part]) ? $tree[$part] : '';
|
||||
}
|
||||
$prev = $part; //for test
|
||||
}
|
||||
|
||||
if(!is_array($tree)){
|
||||
return trim($tree);
|
||||
}
|
||||
|
||||
return $tree;
|
||||
}
|
||||
|
||||
public function findUniqueProductsIdentifier($tree, $parts, $identifier, $path = ''){
|
||||
|
||||
$tmp_parts = $parts;
|
||||
foreach ($parts as $part) {
|
||||
if ($part == $identifier && !$this->isSeq($tree) && isset($tree[$part])) {
|
||||
|
||||
if (!empty($tree[$part]) && !is_array($tree[$part])) {
|
||||
$path .= '->'. $tree[$part];
|
||||
$this->product_links[] = $path;
|
||||
}
|
||||
|
||||
//exit;
|
||||
|
||||
} elseif ($this->isSeq($tree)) {
|
||||
|
||||
foreach($tree as $key => $t){
|
||||
$local_path = $path. '->' . $key;
|
||||
$this->findUniqueProductsIdentifier($t, $tmp_parts, $identifier, $local_path);
|
||||
}
|
||||
return;
|
||||
} else {
|
||||
|
||||
if (isset($tree[$part])) {
|
||||
$tree = $tree[$part];
|
||||
$path .= '->'. $part;
|
||||
}
|
||||
|
||||
array_shift($tmp_parts);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function resolveNested($child_data, $parent_data, $default_parent = 'Value'){
|
||||
|
||||
$child_indexes = array();
|
||||
|
||||
if(!is_array($child_data)){
|
||||
$child_data = array($child_data);
|
||||
}
|
||||
|
||||
$this->setIndexPath($child_data, $child_indexes);
|
||||
|
||||
|
||||
$parent_indexes = array();
|
||||
|
||||
if(is_array($parent_data)){
|
||||
$this->setIndexPath($parent_data, $parent_indexes);
|
||||
} else {
|
||||
$map = array();
|
||||
foreach($child_indexes as $child){
|
||||
|
||||
$map[] = array(
|
||||
'value' => $child['value'],
|
||||
'parent' => $parent_data
|
||||
);
|
||||
}
|
||||
|
||||
return $map;
|
||||
}
|
||||
|
||||
return $this->addParent($child_indexes, $parent_indexes);
|
||||
|
||||
}
|
||||
|
||||
public function addParent($children, $parents){
|
||||
$map = array();
|
||||
foreach($parents as $parent){
|
||||
foreach($children as $key => $child){
|
||||
if(substr($child['key_path'], 0, strlen($parent['key_path'])) === $parent['key_path']){
|
||||
$map[] = array(
|
||||
'value' => $child['value'],
|
||||
'parent' => $parent['value']
|
||||
);
|
||||
|
||||
unset($children[$key]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $map;
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes nested array with unknown nesting levels and return one level array with indexes to values.
|
||||
*
|
||||
* @param array $array array with unknown nesting levels
|
||||
* @param string $key_path string made from array keys
|
||||
* @return array with values and string from value indexes
|
||||
*/
|
||||
|
||||
public function setIndexPath($array, &$return_values = array(), $key_path = ''){
|
||||
foreach($array as $key => $array_part){
|
||||
|
||||
if(is_array($array_part)){
|
||||
$this->setIndexPath($array_part, $return_values, $key_path . $key . '.');
|
||||
} else {
|
||||
$return_values[] = array(
|
||||
'key_path' => $key_path . $key . '.',
|
||||
'value' => $array_part
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public function changeOriginal($product)
|
||||
{
|
||||
$modifications = $this->settings['import_api_modification'];
|
||||
|
||||
foreach ($modifications as $field => $modification) {
|
||||
//if (!$modification) {
|
||||
if ($modification === '') {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (in_array($field, ['price']) && !$product[$field]) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!isset($product[$field])) {
|
||||
$product[$field] = '';
|
||||
}
|
||||
|
||||
if (in_array($field, ['image', 'images', 'cover']) && !$product[$field]) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$modification = html_entity_decode($modification, ENT_QUOTES, 'UTF-8');
|
||||
|
||||
$modified = $this->check_string($modification, $product);
|
||||
$product[$field] = $modified;
|
||||
|
||||
if (in_array($field, ['price', 'quantity', 'option_price','option_quantity', 'special', 'additional_shipping_cost', 'width', 'height', 'depth', 'weight', 'attribute_price', 'attribute_quantity', 'attribute_weight', 'minimal_quantity'])) {
|
||||
$modified = $this->calculateMath($modified);
|
||||
$product[$field] = $modified;
|
||||
}
|
||||
}
|
||||
|
||||
return $product;
|
||||
}
|
||||
|
||||
public function checkCombinations($product)
|
||||
{
|
||||
$combinations = $this->settings['import_api_combination'];
|
||||
|
||||
foreach ($combinations as $field => $combination) {
|
||||
if (!$combination || !isset($product[$field])) {
|
||||
continue;
|
||||
} else {
|
||||
$position = 'all';
|
||||
$parts = explode('##', $combination);
|
||||
if(isset($parts[1])){
|
||||
$position = $parts[1];
|
||||
}
|
||||
}
|
||||
|
||||
$exploded = $this->explodeCombinations($product[$field], $parts[0], $position);
|
||||
$product[$field] = $exploded;
|
||||
|
||||
}
|
||||
return $product;
|
||||
}
|
||||
|
||||
public function explodeCombinations($value, $separator, $position = 'all')
|
||||
{
|
||||
if (!is_array($value)) {
|
||||
$parts = explode($separator, $value);
|
||||
if ($position == 'all') {
|
||||
return $parts;
|
||||
}
|
||||
|
||||
if ($position == 'last') {
|
||||
return end($parts);
|
||||
}
|
||||
|
||||
if (isset($parts[$position-1])) {
|
||||
return $parts[$position-1];
|
||||
}
|
||||
|
||||
return $value;
|
||||
} else {
|
||||
$ret = array();
|
||||
foreach ($value as $key => $v) {
|
||||
$ret[] = $this->explodeCombinations($v, $separator, $position);
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
}
|
||||
|
||||
public function getProductLinks()
|
||||
{
|
||||
|
||||
return $this->product_links;
|
||||
}
|
||||
|
||||
private function check_string($string, $prod)
|
||||
{
|
||||
if ($string) {
|
||||
preg_match_all('/\[\[([a-z_]*\#?[^\]]*)\]\]/', $string , $match);
|
||||
if ($match) {
|
||||
$string = $this->replace_string($string, $match[1], $prod);
|
||||
}
|
||||
}
|
||||
return $string;
|
||||
}
|
||||
|
||||
private function replace_string($string, $keys, $d_array)
|
||||
{
|
||||
foreach ($keys as $key) {
|
||||
$exploded_key = explode('#', $key);
|
||||
$separator = false;
|
||||
|
||||
if (isset($exploded_key[1])) {
|
||||
$string = str_replace($key, $exploded_key[0], $string);
|
||||
$key = $exploded_key[0];
|
||||
$separator = $exploded_key[1];
|
||||
}
|
||||
|
||||
if (isset($d_array[$key])) {
|
||||
if (is_array($d_array[$key])) {
|
||||
$string = $this->replace_all_array_strings($d_array[$key], $key, $string, $separator);
|
||||
} else {
|
||||
$string = str_replace('[['. $key .']]', $d_array[$key], $string);
|
||||
}
|
||||
}
|
||||
}
|
||||
return $string;
|
||||
}
|
||||
|
||||
private function replace_all_array_strings($array, $key, $string, $separator = false)
|
||||
{
|
||||
$s = array();
|
||||
foreach ($array as $d_part) {
|
||||
$s[] = str_replace('[['. $key .']]', $d_part, $string);
|
||||
}
|
||||
|
||||
if ($separator !== false) {
|
||||
$s = implode($separator, $s);
|
||||
}
|
||||
|
||||
return $s;
|
||||
}
|
||||
|
||||
private function calculateMath($expression)
|
||||
{
|
||||
$expression = str_replace(',', '.', $expression);
|
||||
$expression = str_replace(' ', '', $expression);
|
||||
$expression = preg_replace('/[^0-9\.\+\-\*\/\(\)]/', '', $expression);
|
||||
|
||||
$expression = $this->replaceMathExpession($expression, '*');
|
||||
$expression = $this->replaceMathExpession($expression, '/');
|
||||
|
||||
$expression = $this->replaceMathExpession($expression, '+');
|
||||
$expression = $this->replaceMathExpession($expression, '-');
|
||||
return $expression;
|
||||
}
|
||||
|
||||
private function replaceMathExpession($expression, $sign)
|
||||
{
|
||||
$patern = '\\' . $sign;
|
||||
$expression = preg_replace_callback(
|
||||
'/[0-9]*\.?[0-9]+' . $patern . '[0-9]*\.?[0-9]+(' . $patern . '[0-9]*\.?[0-9]+)*/',
|
||||
function ($matches) use ($sign) {
|
||||
if (!empty($matches[0])) {
|
||||
return $this->calculate_string($matches[0], $sign);
|
||||
}
|
||||
}, $expression);
|
||||
return $expression;
|
||||
}
|
||||
|
||||
private function calculate_string($string, $sign)
|
||||
{
|
||||
$parts = explode($sign, $string);
|
||||
$final = $parts[0];
|
||||
|
||||
for ($i = 1; $i < count($parts); $i++) {
|
||||
if ($sign == '*') {
|
||||
$final = $final * $parts[$i];
|
||||
} elseif ($sign == '/') {
|
||||
$final = $final / $parts[$i];
|
||||
} elseif ($sign == '+') {
|
||||
$final = $final + $parts[$i];
|
||||
} elseif ($sign == '-') {
|
||||
$final = $final - $parts[$i];
|
||||
}
|
||||
}
|
||||
return $final;
|
||||
}
|
||||
|
||||
public function jsonToArray($json_url)
|
||||
{
|
||||
$json_string = @file_get_contents($json_url);
|
||||
$json_array = json_decode($json_string, true);
|
||||
return $json_array;
|
||||
}
|
||||
|
||||
public function setJsonArray($json_array)
|
||||
{
|
||||
$this->json_array = $json_array;
|
||||
}
|
||||
|
||||
public function isSeq($array)
|
||||
{
|
||||
if (is_array($array) ) {
|
||||
return is_int(array_key_first($array));
|
||||
}
|
||||
//return is_array($array) && isset($array[0]);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
35
modules/import_api/classes/index.php
Normal file
35
modules/import_api/classes/index.php
Normal file
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
/**
|
||||
* 2007-2018 PrestaShop
|
||||
*
|
||||
* NOTICE OF LICENSE
|
||||
*
|
||||
* This source file is subject to the Academic Free License (AFL 3.0)
|
||||
* that is bundled with this package in the file LICENSE.txt.
|
||||
* It is also available through the world-wide-web at this URL:
|
||||
* http://opensource.org/licenses/afl-3.0.php
|
||||
* If you did not receive a copy of the license and are unable to
|
||||
* obtain it through the world-wide-web, please send an email
|
||||
* to license@prestashop.com so we can send you a copy immediately.
|
||||
*
|
||||
* DISCLAIMER
|
||||
*
|
||||
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
|
||||
* versions in the future. If you wish to customize PrestaShop for your
|
||||
* needs please refer to http://www.prestashop.com for more information.
|
||||
*
|
||||
* @author PrestaShop SA <contact@prestashop.com>
|
||||
* @copyright 2007-2018 PrestaShop SA
|
||||
* @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0)
|
||||
* International Registered Trademark & Property of PrestaShop SA
|
||||
*/
|
||||
|
||||
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;
|
||||
182
modules/import_api/classes/queue.php
Normal file
182
modules/import_api/classes/queue.php
Normal file
@@ -0,0 +1,182 @@
|
||||
<?php
|
||||
/**
|
||||
* NOTICE OF LICENSE
|
||||
* With the purchase or the installation of the software in your application
|
||||
* you accept the license agreement.
|
||||
*
|
||||
* You can not resell and redistribute this file.
|
||||
*
|
||||
* @author Dalibor Stojcevski <dal_sto@yahoo.com>
|
||||
* @copyright 2019 Dalibor Stojcevski
|
||||
* @license Dalibor Stojcevski
|
||||
*/
|
||||
|
||||
class Queue
|
||||
{
|
||||
public $shop_name = 'default';
|
||||
|
||||
public function getQueued($file_id = 0, $limit = 0)
|
||||
{
|
||||
|
||||
$sql = "SELECT * FROM " . _DB_PREFIX_ . "ia_temp t LEFT JOIN " . _DB_PREFIX_ . "ia_queues q ON (t.queue_id = q.queue_id) WHERE q.status < 3 AND t.shop = '" . pSQL($this->shop_name) . "'";
|
||||
|
||||
if ($file_id) {
|
||||
$sql .= " AND t.file_id = " . (int)$file_id;
|
||||
}
|
||||
|
||||
if ($limit) {
|
||||
$sql .= " LIMIT " . (int)$limit;
|
||||
}
|
||||
|
||||
$query = Db::getInstance()->executeS($sql);
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
public function getLastQueue($file_id = 0, $status = 0)
|
||||
{
|
||||
|
||||
$sql = "SELECT * FROM " . _DB_PREFIX_ . "ia_queues WHERE shop = '" . pSQL($this->shop_name) . "'";
|
||||
|
||||
if ($file_id) {
|
||||
$sql .= " AND file_id = " . (int)$file_id;
|
||||
}
|
||||
|
||||
if ($status) {
|
||||
$sql .= " AND status = " . (int)$status;
|
||||
}
|
||||
|
||||
$sql .= " ORDER BY date_added DESC";
|
||||
|
||||
$query = Db::getInstance()->executeS($sql);
|
||||
|
||||
if ($query) {
|
||||
return $query[0];
|
||||
} else {
|
||||
return array();
|
||||
}
|
||||
}
|
||||
|
||||
public function getProducts($file_id = 0, $limit = 0)
|
||||
{
|
||||
|
||||
$sql = "SELECT * FROM " . _DB_PREFIX_ . "ia_products p WHERE p.shop = '" . pSQL($this->shop_name) . "'";
|
||||
|
||||
if ($file_id) {
|
||||
$sql .= " AND p.file_id = " . (int)$file_id;
|
||||
}
|
||||
|
||||
if ($limit) {
|
||||
$sql .= " LIMIT " . (int)$limit;
|
||||
}
|
||||
|
||||
$query = Db::getInstance()->executeS($sql);
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
public function deleteProduct($product_id = 0, $file_id = 0)
|
||||
{
|
||||
|
||||
$sql = "DELETE FROM " . _DB_PREFIX_ . "ia_products WHERE product_id = '" . (int)$product_id . "'";
|
||||
|
||||
if ($file_id) {
|
||||
$sql .= " AND file_id = " . (int)$file_id;
|
||||
}
|
||||
//print_r($sql); exit;
|
||||
|
||||
$query = Db::getInstance()->execute($sql);
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
public function saveTempToDb($products, $file_id = 0) {
|
||||
|
||||
$this->deleteUnnecessary($file_id);
|
||||
|
||||
Db::getInstance()->execute("INSERT INTO " . _DB_PREFIX_ . "ia_queues SET shop = '" . pSQL($this->shop_name) . "', total = '" . count($products) . "', date_added = '" . time() . "', file_id = '" . (int)$file_id . "'");
|
||||
|
||||
$queue_id = Db::getInstance()->Insert_ID();
|
||||
|
||||
foreach($products as $indx => $product) {
|
||||
Db::getInstance()->execute("INSERT INTO " . _DB_PREFIX_ . "ia_temp SET shop = '" . pSQL($this->shop_name) . "', date_added = '" . time() . "', indx = '" . pSQL($indx) . "', product = '" . pSQL(json_encode($product)) . "', queue_id = '" . (int)$queue_id . "', file_id = '" . (int)$file_id . "'");
|
||||
}
|
||||
|
||||
return $queue_id;
|
||||
}
|
||||
|
||||
public function deleteUnnecessary($file_id = 0, $shop = 'default') {
|
||||
Db::getInstance()->execute("DELETE FROM " . _DB_PREFIX_ . "ia_queues WHERE shop = '" . pSQL($this->shop_name) . "' AND status < 3 AND file_id = " . (int)$file_id);
|
||||
Db::getInstance()->execute("DELETE FROM " . _DB_PREFIX_ . "ia_temp WHERE shop = '" . pSQL($this->shop_name) . "' AND file_id = " . (int)$file_id);
|
||||
}
|
||||
|
||||
public function getQueuedForTable($file_id = 0, $limit = 0) {
|
||||
|
||||
$products = array();
|
||||
|
||||
$queued = $this->getQueued($file_id, $limit);
|
||||
|
||||
foreach ($queued as $q) {
|
||||
$p = json_decode($q['product'], true);
|
||||
//var_dump($p); exit;
|
||||
$products[] = array(
|
||||
'id' => $q['product_id'],
|
||||
'indx' => $q['indx'],
|
||||
'reference' => $p['reference'],
|
||||
'name' => $p['name'],
|
||||
'price' => $p['price'],
|
||||
'quantity' => $p['quantity'],
|
||||
'manufacturer' =>isset($p['brand']) ? $p['brand'] : '',
|
||||
);
|
||||
}
|
||||
|
||||
return $products;
|
||||
}
|
||||
|
||||
public function getQueuedProduct($indx = 0, $file_id = 0) {
|
||||
|
||||
$sql = "SELECT * FROM " . _DB_PREFIX_ . "ia_temp WHERE shop = '" . pSQL($this->shop_name) . "'";
|
||||
|
||||
if ($indx) {
|
||||
$sql .= " AND indx = '" . pSQL($indx) . "'";
|
||||
}
|
||||
|
||||
|
||||
if ($file_id) {
|
||||
$sql .= " AND file_id = '" .(int)$file_id . "'";
|
||||
}
|
||||
|
||||
$sql .= " LIMIT 1";
|
||||
|
||||
$query = Db::getInstance()->executeS($sql);
|
||||
|
||||
if ($query) {
|
||||
return $query[0];
|
||||
} else {
|
||||
array();
|
||||
}
|
||||
}
|
||||
|
||||
public function deleteQueuedProduct($product_id = 0, $indx = 0, $file_id = 0) {
|
||||
|
||||
$sql = "DELETE FROM " . _DB_PREFIX_ . "ia_temp WHERE shop = '" . pSQL($this->shop_name) . "'";
|
||||
|
||||
if ($product_id) {
|
||||
$sql .= " AND product_id = '" . (int)$product_id . "'";
|
||||
}
|
||||
|
||||
if ($indx) {
|
||||
$sql .= " AND indx = '" . pSQL($indx) . "'";
|
||||
}
|
||||
|
||||
if ($file_id) {
|
||||
$sql .= " AND file_id = '" .(int)$file_id . "'";
|
||||
}
|
||||
|
||||
$sql .= " LIMIT 1";
|
||||
|
||||
$query = Db::getInstance()->execute($sql);
|
||||
|
||||
return $query;
|
||||
}
|
||||
}
|
||||
12
modules/import_api/config.xml
Normal file
12
modules/import_api/config.xml
Normal file
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<module>
|
||||
<name>import_api</name>
|
||||
<displayName><![CDATA[Import Api]]></displayName>
|
||||
<version><![CDATA[3.1.5.8]]></version>
|
||||
<description><![CDATA[Import and update products from external source]]></description>
|
||||
<author><![CDATA[Dalibor Stojcevski]]></author>
|
||||
<tab><![CDATA[front_office_features]]></tab>
|
||||
<is_configurable>1</is_configurable>
|
||||
<need_instance>1</need_instance>
|
||||
<limited_countries></limited_countries>
|
||||
</module>
|
||||
12
modules/import_api/config_pl.xml
Normal file
12
modules/import_api/config_pl.xml
Normal file
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<module>
|
||||
<name>import_api</name>
|
||||
<displayName><![CDATA[Import Api]]></displayName>
|
||||
<version><![CDATA[3.1.5.9]]></version>
|
||||
<description><![CDATA[Import and update products from external source]]></description>
|
||||
<author><![CDATA[Dalibor Stojcevski]]></author>
|
||||
<tab><![CDATA[front_office_features]]></tab>
|
||||
<is_configurable>1</is_configurable>
|
||||
<need_instance>1</need_instance>
|
||||
<limited_countries></limited_countries>
|
||||
</module>
|
||||
@@ -0,0 +1,831 @@
|
||||
<?php
|
||||
/**
|
||||
* NOTICE OF LICENSE
|
||||
* With the purchase or the installation of the software in your application
|
||||
* you accept the license agreement.
|
||||
*
|
||||
* You can not resell and redistribute this file.
|
||||
*
|
||||
* @author Dalibor Stojcevski <dal_sto@yahoo.com>
|
||||
* @copyright 2019 Dalibor Stojcevski
|
||||
* @license Dalibor Stojcevski
|
||||
*/
|
||||
class AdminImport_ApiController extends ModuleAdminController
|
||||
{
|
||||
public $bootstrap = true;
|
||||
|
||||
protected $_postErrors = array();
|
||||
|
||||
protected $fmr_fields;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
if ($this->context == null) {
|
||||
$this->context = Context::getContext();
|
||||
}
|
||||
$this->toolbar_title = 'Sources';
|
||||
$this->meta_title = 'Import api';
|
||||
parent::__construct();
|
||||
require_once(_PS_MODULE_DIR_ . 'import_api/classes/queue.php');
|
||||
$this->queue = new Queue();
|
||||
$this->frm_fields = ['unique', 'reference', 'name', 'description', 'short_description', 'price', 'wholesale_price', 'quantity', 'images', 'cover', 'brand', 'category', 'category_parent', 'ean13', 'upc', 'condition', 'location', 'additional_shipping_cost', 'width', 'height', 'depth', 'weight', 'active', 'feature', 'feature_value', 'attribute1', 'attribute_value1', 'attribute2', 'attribute_value2', 'attribute3', 'attribute_value3', 'attribute_price', 'attribute_quantity', 'attribute_ean', 'attribute_weight', 'minimal_quantity'];
|
||||
$this->replace_fields = ['reference', 'name', 'description', 'short_description', 'price', 'wholesale_price', 'quantity', 'images', 'cover', 'brand', 'category', 'ean13', 'upc', 'condition', 'location', 'width', 'height', 'depth', 'weight', 'feature', 'feature_value', 'attribute1', 'attribute_value1', 'attribute2', 'attribute_value2', 'attribute3', 'attribute_value3', 'minimal_quantity'];
|
||||
$this->frm_settings = array('top_category' => '', 'default_category' => '', 'default_brand' => '', 'price_multiplier' => '', 'combination_price_multiplier' => '', 'add_combination_price' => 0, 'category_path' => 0, 'id_tax_rules_group' => -1, 'same_update' => 0, 'not_existing' => 0, 'only_update' => 0, 'synchronize_field' => 'automatic');
|
||||
$this->frm_update_settings = array('quantity' => 1, 'price' => 0, 'wholesale_price' => 0, 'manufacturer' => 0, 'category' => 0, 'cover' => 0, 'images' => 0, 'name' => 0, 'description' => 0, 'short_description' => 0,'reference' => 0, 'ean13' => 0, 'ups' => 0, 'condition' => 0, 'location'=> 0, 'additional_shipping_cost'=> 0, 'width' => 0 , 'height' => 0 , 'depth' => 0 , 'weight' => 0, 'features' => 0, 'attributes' => 0, 'active' => 0, 'id_tax_rules_group' => 0, 'minimal_quantity' => 0);
|
||||
$this->filter_fields = ['reference', 'name', 'price', 'wholesale_price', 'quantity', 'images', 'cover', 'brand', 'category', 'ean13', 'upc', 'condition', 'location', 'width', 'height', 'depth', 'weight', 'feature', 'feature_value', 'attribute1', 'attribute_value1', 'attribute2', 'attribute_value2', 'attribute3', 'attribute_value3', 'minimal_quantity'];
|
||||
|
||||
|
||||
|
||||
if (Tools::getValue('add_source')) {
|
||||
$this->addSource();
|
||||
} elseif (Tools::getValue('delete') && Tools::getValue('file_id')) {
|
||||
$this->deleteProducts(Tools::getValue('file_id'));
|
||||
} elseif (Tools::getValue('file_id')) {
|
||||
if (((bool)Tools::isSubmit('submitImportSettings')) == true) {
|
||||
$this->_postSettingsValidation();
|
||||
$message = '';
|
||||
if (!count($this->_postErrors)) {
|
||||
$this->_saveSettings(Tools::getValue('file_id'));
|
||||
} else {
|
||||
foreach ($this->_postErrors as $err) {
|
||||
$this->errors[] = $err;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
$this->processFile(Tools::getValue('file_id'), Tools::getValue('type'));
|
||||
} else {
|
||||
$this->getSourceList();
|
||||
}
|
||||
//return;
|
||||
}
|
||||
|
||||
|
||||
public function addSource()
|
||||
{
|
||||
if (Tools::isSubmit('submitAddSource')) {
|
||||
$this->postFileProcess();
|
||||
}
|
||||
$this->context->smarty->assign('form_link', $this->context->link->getAdminLink('AdminImport_Api&add_source=1&token=' . Tools::getAdminTokenLite('AdminImport_Api'), false));
|
||||
$file_tpl = $this->context->smarty->fetch(_PS_MODULE_DIR_ . 'import_api/views/templates/admin/file_upload.tpl');
|
||||
$this->content .= $file_tpl;
|
||||
}
|
||||
|
||||
public function deleteProducts($file_id)
|
||||
{
|
||||
$query_file = Db::getInstance()->executeS("SELECT * FROM ". _DB_PREFIX_ . "ia_files WHERE file_id = '" . (int)$file_id . "' LIMIT 1");
|
||||
if (empty($query_file)) {
|
||||
$this->errors[] = $this->my_translation('File not found');
|
||||
return;
|
||||
} else {
|
||||
$file = $query_file[0];
|
||||
}
|
||||
|
||||
$this->toolbar_title = 'Delete';
|
||||
|
||||
$query_total = Db::getInstance()->executeS("SELECT COUNT(*) as total FROM ". _DB_PREFIX_ . "ia_products WHERE file_id = '" . (int)$file_id . "'");
|
||||
|
||||
$total = $query_total ? $query_total[0]['total'] : 0;
|
||||
|
||||
$file_name = $file['name'] ? $file['name'] : $file['link'];
|
||||
$this->context->smarty->assign('token', $file['mask'] . $file['date_added']);
|
||||
$this->context->smarty->assign('get_import_link', $this->context->link->getModuleLink('import_api', 'import', array('file_id' => $file_id)));
|
||||
|
||||
$this->context->smarty->assign('file_name', $file_name);
|
||||
$this->context->smarty->assign('total', $total);
|
||||
$delete_tpl = $this->context->smarty->fetch(_PS_MODULE_DIR_ . 'import_api/views/templates/admin/delete.tpl');
|
||||
$this->content .= $delete_tpl;
|
||||
}
|
||||
|
||||
public function getSourceList()
|
||||
{
|
||||
if (Tools::getValue('status_file_id') && Tools::getValue('change_status') !== false) {
|
||||
Db::getInstance()->execute("UPDATE ". _DB_PREFIX_ . "ia_files SET status = '" . (int)Tools::getValue('change_status') ."' WHERE file_id = " . (int)Tools::getValue('status_file_id'));
|
||||
}
|
||||
|
||||
$query_files = Db::getInstance()->executeS("SELECT f.* FROM ". _DB_PREFIX_ . "ia_files f ORDER BY date_edited DESC, file_id DESC");
|
||||
|
||||
$files = array();
|
||||
if ($query_files) {
|
||||
foreach ($query_files as $file) {
|
||||
$other_status = $file['status'] ? 0 : 1;
|
||||
$other_status_text = $file['status'] ? 'Disable' : 'Enable';
|
||||
if (!Tools::getValue('show_disabled') && !$file['status']) {
|
||||
continue;
|
||||
}
|
||||
$files[] = array(
|
||||
'file_id' => $file['file_id'],
|
||||
'name' => $file['name'] ? $file['name'] : $file['link'],
|
||||
'date_added' => date('F j, Y', $file['date_added']),
|
||||
'process_link' => $this->context->link->getAdminLink('AdminImport_Api&file_id=' . $file['file_id'] . '&token=' . Tools::getAdminTokenLite('AdminImport_Api'), false),
|
||||
'change_status_link' => $this->context->link->getAdminLink('AdminImport_Api&change_status=' . $other_status . '&status_file_id=' . $file['file_id'] . '&token=' . Tools::getAdminTokenLite('AdminImport_Api'), false),
|
||||
'other_status_text' => $other_status_text
|
||||
);
|
||||
}
|
||||
|
||||
$this->context->smarty->assign('files', $files);
|
||||
$this->context->smarty->assign('show_disabled_link', $this->context->link->getAdminLink('AdminImport_Api&show_disabled=1&token=' . Tools::getAdminTokenLite('AdminImport_Api'), false));
|
||||
|
||||
$list_tpl = $this->context->smarty->fetch(_PS_MODULE_DIR_ . 'import_api/views/templates/admin/list.tpl');
|
||||
$this->content .= $list_tpl;
|
||||
} else {
|
||||
$this->addSource();
|
||||
}
|
||||
}
|
||||
|
||||
public function processFile($file_id, $type = 'import')
|
||||
{
|
||||
$this->addJquery();
|
||||
$this->addJS(_MODULE_DIR_. 'import_api/views/js/dataTables.js');
|
||||
$this->addJS(_MODULE_DIR_. 'import_api/views/js/dataTables.bootstrap4.js');
|
||||
$this->addCSS(_MODULE_DIR_. 'import_api/views/css/dataTables.bootstrap4.css');
|
||||
$query_file_settings = Db::getInstance()->executeS("SELECT f.*, fs.mapping FROM ". _DB_PREFIX_ . "ia_files f LEFT JOIN ". _DB_PREFIX_ . "ia_file_settings fs ON(fs.file_id = f.file_id) WHERE f.file_id = '" . (int)$file_id . "' LIMIT 1");
|
||||
if (empty($query_file_settings)) {
|
||||
$this->errors[] = $this->my_translation('File not found');
|
||||
} else {
|
||||
$file_settings = $query_file_settings[0];
|
||||
$file_name = $file_settings['name'] ? $file_settings['name'] : $file_settings['link'];
|
||||
if ($file_settings['mapping'] && $type == 'import') {
|
||||
|
||||
$this->toolbar_title = 'Import';
|
||||
$this->context->smarty->assign('get_import_link', $this->context->link->getModuleLink('import_api', 'import', array('file_id'=> $file_id)));
|
||||
$this->context->smarty->assign('show_all_link', $this->context->link->getAdminLink('AdminImport_Api&type=import&showall=1&file_id=' . $file_id . '&token=' . Tools::getAdminTokenLite('AdminImport_Api'), false));
|
||||
$this->context->smarty->assign('delete_link', $this->context->link->getAdminLink('AdminImport_Api&delete=1&file_id=' . $file_id . '&token=' . Tools::getAdminTokenLite('AdminImport_Api'), false));
|
||||
|
||||
if (Tools::getValue('showall')) {
|
||||
$limit = 0;
|
||||
} else {
|
||||
$limit = 600;
|
||||
}
|
||||
|
||||
$products = $this->queue->getQueuedForTable($file_id, $limit);
|
||||
$this->context->smarty->assign('settings_link', $this->context->link->getAdminLink('AdminImport_Api&type=settings&file_id=' . $file_id . '&token=' . Tools::getAdminTokenLite('AdminImport_Api'), false));
|
||||
|
||||
$this->context->smarty->assign('products', $products);
|
||||
$this->context->smarty->assign('limit', $limit);
|
||||
$this->context->smarty->assign('auto_queue', 0);
|
||||
$this->context->smarty->assign('file_name', $file_name);
|
||||
$output = $this->context->smarty->fetch(_PS_MODULE_DIR_ . 'import_api/views/templates/admin/import.tpl');
|
||||
$queue_tpl = $this->context->smarty->fetch(_PS_MODULE_DIR_ . 'import_api/views/templates/admin/temp.tpl');
|
||||
$this->content .= $queue_tpl;
|
||||
$this->content .= $output;
|
||||
} else {
|
||||
$this->toolbar_title = 'Settings';
|
||||
$this->context->smarty->assign('file_settings', $file_settings);
|
||||
$this->context->smarty->assign('file_id', $file_id);
|
||||
$this->context->smarty->assign('file_name', $file_name);
|
||||
$this->context->smarty->assign('import_link', $this->context->link->getAdminLink('AdminImport_Api&type=import&file_id=' . $file_id . '&token=' . Tools::getAdminTokenLite('AdminImport_Api'), false));
|
||||
$this->context->smarty->assign('get_fields_link', $this->context->link->getModuleLink('import_api', 'ajax', array('file_id'=> $file_id)));
|
||||
$output = $this->context->smarty->fetch(_PS_MODULE_DIR_ . 'import_api/views/templates/admin/configure.tpl');
|
||||
//$import_html = $this->context->smarty->fetch(_PS_MODULE_DIR_ . 'import_api/views/templates/admin/import.tpl');
|
||||
|
||||
$this->content .= $output. $this->renderSettingsForm($file_settings);
|
||||
//$this->content .= $output;
|
||||
}
|
||||
}
|
||||
}
|
||||
public static function displayHumanReadableSize($size)
|
||||
{
|
||||
return Tools::formatBytes($size);
|
||||
}
|
||||
|
||||
public function initPageHeaderToolbar()
|
||||
{
|
||||
$this->page_header_toolbar_btn['new_attachment'] = array(
|
||||
'href' => self::$currentIndex . '&add_source=1&token=' . $this->token,
|
||||
'desc' => $this->my_translation('Add new source'),
|
||||
'icon' => 'process-icon-new',
|
||||
);
|
||||
$this->page_header_toolbar_btn['view_list'] = array(
|
||||
'href' => self::$currentIndex . '&token=' . $this->token,
|
||||
'desc' => $this->my_translation('View list'),
|
||||
'icon' => 'process-icon-list',
|
||||
);
|
||||
parent::initPageHeaderToolbar();
|
||||
}
|
||||
|
||||
public function postFileProcess()
|
||||
{
|
||||
$shop = 'default';
|
||||
$source = !empty($_POST['import_api_type']) ? $_POST['import_api_type'] : '';
|
||||
$headers = !empty($_POST['import_api_headers']) ? $_POST['import_api_headers'] : '';
|
||||
$delimiter = !empty($_POST['import_api_delimiter']) ? $_POST['import_api_delimiter'] : '';
|
||||
$mask = uniqid();
|
||||
if (!empty($_POST['import_api_link'])) {
|
||||
|
||||
$query_file = Db::getInstance()->executeS("SELECT * FROM ". _DB_PREFIX_ . "ia_files WHERE link = '" . pSQL($_POST['import_api_link']) . "' AND shop = '" . pSQL($shop) . "' AND status = 1 LIMIT 1");
|
||||
|
||||
if ($query_file) {
|
||||
$file_id = $query_file[0]['file_id'];
|
||||
Db::getInstance()->execute("UPDATE ". _DB_PREFIX_ . "ia_files SET link = '" . pSQL($_POST['import_api_link']) . "', delimiter = '" . pSQL($delimiter) . "', headers = '" . pSQL($headers) . "', source = '" . pSQL($source) . "', date_edited = '" . time() . "' WHERE file_id = " . (int)$file_id ." AND shop = '" . pSQL($shop) . "'");
|
||||
|
||||
} else {
|
||||
Db::getInstance()->execute("INSERT INTO ". _DB_PREFIX_ . "ia_files SET link = '" . pSQL($_POST['import_api_link']) . "', shop = '" . pSQL($shop) . "', delimiter = '" . pSQL($delimiter) . "', headers = '" . pSQL($headers) . "', source = '" . pSQL($source) . "', mask = '" . pSQL($mask) ."', date_added = '" . time() . "'");
|
||||
}
|
||||
} elseif (!empty($_FILES['doc']['tmp_name'])) {
|
||||
|
||||
$name = $_FILES['doc']['name'];
|
||||
$tmp_name = $_FILES['doc']['tmp_name'];
|
||||
$type = $_FILES['doc']['type'];
|
||||
|
||||
$file_ext = pathinfo($name, PATHINFO_EXTENSION);
|
||||
|
||||
if (in_array($file_ext, ['zip'])) {
|
||||
$this->errors[] = $this->my_translation("Sorry, app can't read zip files. Extract zip and upload content from inside");
|
||||
} else {
|
||||
$target_file = _PS_MODULE_DIR_ . 'import_api/views/img/' . $mask . '_' . $name;
|
||||
$base_link = Tools::getHttpHost(true).__PS_BASE_URI__;
|
||||
$target_url = $base_link. 'modules/import_api/views/img/' . $mask . '_' . $name;;
|
||||
if (move_uploaded_file($tmp_name, $target_file)) {
|
||||
Db::getInstance()->execute("INSERT INTO ". _DB_PREFIX_ . "ia_files SET link = '" . pSQL($target_url) ."', mime_type = '" . pSQL($type) ."', source = '" . pSQL($source) ."', delimiter = '" . pSQL($delimiter) . "', headers = '" . pSQL($headers) . "', name = '" . pSQL($name) ."', mask = '" . pSQL($mask) ."', shop = '" . pSQL($shop) . "', date_added = '" . time() . "'");
|
||||
} else {
|
||||
$this->errors[] = $this->my_translation("Sorry, there was an error uploading your file.");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$this->errors[] = $this->my_translation("Enter link or upload file.");
|
||||
}
|
||||
if (!$this->errors) {
|
||||
if (!isset($file_id)) {
|
||||
$file_id = Db::getInstance()->Insert_ID();
|
||||
}
|
||||
if (!empty($_POST['import_api_link'])) {
|
||||
if( strpos($_POST['import_api_link'], 'convert') !== false) {
|
||||
$fields_file_path = _PS_MODULE_DIR_ . 'import_api/fields.txt';
|
||||
$file_settings_file_path = _PS_MODULE_DIR_ . 'import_api/file_settings.txt';
|
||||
if (file_exists($fields_file_path)) {
|
||||
$f = file_get_contents($fields_file_path);
|
||||
Db::getInstance()->execute("UPDATE ". _DB_PREFIX_ . "ia_files SET fields = '" . pSQL($f) . "', date_edited = '" . time() . "' WHERE file_id = " . (int)$file_id);
|
||||
}
|
||||
if (file_exists($file_settings_file_path)) {
|
||||
$sql_raw = file_get_contents($file_settings_file_path);
|
||||
$sql = sprintf($sql_raw, _DB_PREFIX_, $file_id);
|
||||
|
||||
Db::getInstance()->execute($sql);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
Tools::redirectAdmin($this->context->link->getAdminLink('AdminImport_Api&type=settings&file_id=' . $file_id . '&token=' . Tools::getAdminTokenLite('AdminImport_Api'), false));
|
||||
}
|
||||
}
|
||||
|
||||
protected function renderSettingsForm($settings, $tab = 'general')
|
||||
{
|
||||
$helper = new HelperForm();
|
||||
$this->tab = $tab;
|
||||
$helper->show_toolbar = false;
|
||||
$helper->table = $this->table;
|
||||
//$helper->module = $this;
|
||||
$helper->default_form_language = $this->context->language->id;
|
||||
$helper->allow_employee_form_lang = Configuration::get('PS_BO_ALLOW_EMPLOYEE_FORM_LANG', 0);
|
||||
|
||||
$helper->identifier = $this->identifier;
|
||||
$helper->submit_action = 'submitImportSettings';
|
||||
$helper->currentIndex = $this->context->link->getAdminLink('AdminImport_Api', false)
|
||||
.'&type=settings&file_id='. $settings['file_id'];
|
||||
$helper->token = Tools::getAdminTokenLite('AdminImport_Api');
|
||||
|
||||
$helper->tpl_vars = array(
|
||||
'fields_value' => $this->getConfigFormValues(),
|
||||
'languages' => $this->context->controller->getLanguages(),
|
||||
'id_language' => $this->context->language->id,
|
||||
);
|
||||
|
||||
return $helper->generateForm(array($this->getConfigForm($settings)));
|
||||
}
|
||||
|
||||
protected function getConfigForm($settings)
|
||||
{
|
||||
|
||||
$import_api_fields = $settings['fields'] ? html_entity_decode($settings['fields'], ENT_QUOTES, 'UTF-8') : '';
|
||||
|
||||
$source_fields = explode('##', $import_api_fields);
|
||||
|
||||
|
||||
|
||||
$options_not_existing[] = array(
|
||||
'id_option' => 0,
|
||||
'name' => $this->my_translation('Keep it'),
|
||||
);
|
||||
|
||||
$options_not_existing[] = array(
|
||||
'id_option' => 1,
|
||||
'name' => $this->my_translation('Set quantity 0'),
|
||||
);
|
||||
|
||||
$options_not_existing[] = array(
|
||||
'id_option' => 2,
|
||||
'name' => $this->my_translation('Set status disabled'),
|
||||
);
|
||||
|
||||
$options_not_existing[] = array(
|
||||
'id_option' => 3,
|
||||
'name' => $this->my_translation('Delete'),
|
||||
);
|
||||
|
||||
$options_synchronize_field[] = array(
|
||||
'id_option' => 'automatic',
|
||||
'name' => $this->my_translation('From unique field')
|
||||
);
|
||||
|
||||
$options_synchronize_field[] = array(
|
||||
'id_option' => 'reference',
|
||||
'name' => $this->my_translation('Reference')
|
||||
);
|
||||
|
||||
$options_synchronize_field[] = array(
|
||||
'id_option' => 'ean13',
|
||||
'name' => $this->my_translation('Ean13')
|
||||
);
|
||||
|
||||
$options_synchronize_field[] = array(
|
||||
'id_option' => 'upc',
|
||||
'name' => $this->my_translation('Upc')
|
||||
);
|
||||
|
||||
$options_synchronize_field[] = array(
|
||||
'id_option' => 'name',
|
||||
'name' => $this->my_translation('Product name')
|
||||
);
|
||||
|
||||
$options_synchronize_field[] = array(
|
||||
'id_option' => 'id_product',
|
||||
'name' => $this->my_translation('Prestashop product id')
|
||||
);
|
||||
|
||||
|
||||
$options_yes_no[] = array(
|
||||
'id_option' => 0,
|
||||
'name' => $this->my_translation('No'),
|
||||
);
|
||||
$options_yes_no[] = array(
|
||||
'id_option' => 1,
|
||||
'name' => $this->my_translation('Yes'),
|
||||
);
|
||||
|
||||
$options[] = array(
|
||||
'id_option' => 0,
|
||||
'name' => $this->my_translation('--Please select--'),
|
||||
);
|
||||
|
||||
$filter_options[] = array(
|
||||
'id_option' => 'equal',
|
||||
'name' => $this->my_translation('Equal'),
|
||||
);
|
||||
|
||||
$filter_options[] = array(
|
||||
'id_option' => 'not_equal',
|
||||
'name' => $this->my_translation('Not equal'),
|
||||
);
|
||||
|
||||
$filter_options[] = array(
|
||||
'id_option' => 'greater',
|
||||
'name' => $this->my_translation('Greater'),
|
||||
);
|
||||
|
||||
$filter_options[] = array(
|
||||
'id_option' => 'less',
|
||||
'name' => $this->my_translation('Less'),
|
||||
);
|
||||
|
||||
$filter_options[] = array(
|
||||
'id_option' => 'not_empty',
|
||||
'name' => $this->my_translation('Not empty'),
|
||||
);
|
||||
|
||||
$filter_options[] = array(
|
||||
'id_option' => 'regexp',
|
||||
'name' => $this->my_translation('REGEXP'),
|
||||
);
|
||||
|
||||
if($import_api_fields){
|
||||
foreach($source_fields as $field){
|
||||
$options[] = array(
|
||||
'id_option' => $field,
|
||||
'name' => $field,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
$def_tax[] = array('id_tax_rules_group' => -1, 'name' => 'Default');
|
||||
$def_tax[] = array('id_tax_rules_group' => 0, 'name' => 'No tax');
|
||||
|
||||
$taxes = array_merge($def_tax, TaxRulesGroup::getTaxRulesGroups());
|
||||
|
||||
$fields[] = array(
|
||||
'type' => 'hidden',
|
||||
'id' => 'fields',
|
||||
'name' => 'import_api_fields',
|
||||
);
|
||||
|
||||
$fields[] = array(
|
||||
'type' => 'hidden',
|
||||
'id' => 'import_api_link',
|
||||
'name' => 'import_api_link',
|
||||
);
|
||||
|
||||
$fields[] = array(
|
||||
'type' => 'hidden',
|
||||
'id' => 'import_api_type',
|
||||
'name' => 'import_api_type',
|
||||
);
|
||||
|
||||
foreach($this->frm_fields as $fmr_field){
|
||||
$fields[] = array(
|
||||
'type' => 'select',
|
||||
'class' => 'api_field',
|
||||
'tab' => 'general',
|
||||
'required' => in_array($fmr_field, ['unique', 'name']) ? true : false,
|
||||
'label' => $this->my_translation($fmr_field),
|
||||
'name' => 'import_api_field['. $fmr_field .']',
|
||||
'options' => array(
|
||||
'query' => $options,
|
||||
'id' => 'id_option',
|
||||
'name' => 'name'
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
foreach($this->frm_fields as $fmr_field){
|
||||
$fields[] = array(
|
||||
'type' => 'text',
|
||||
'tab' => 'modifications',
|
||||
'label' => $this->my_translation($fmr_field),
|
||||
'name' => 'import_api_modification['. $fmr_field .']',
|
||||
);
|
||||
|
||||
$fields[] = array(
|
||||
'type' => 'text',
|
||||
'tab' => 'combinations',
|
||||
'label' => $this->my_translation($fmr_field),
|
||||
'name' => 'import_api_split['. $fmr_field .']',
|
||||
);
|
||||
}
|
||||
|
||||
foreach($this->filter_fields as $f_field) {
|
||||
$fields[] = array(
|
||||
'type' => 'textarea',
|
||||
'tab' => 'filter',
|
||||
'rows' => 10,
|
||||
'hint' => 'Enter each value in new line',
|
||||
'label' => $this->my_translation($f_field),
|
||||
'name' => 'import_api_filter['. $f_field .']',
|
||||
'description' => 'Enter values, each in new line',
|
||||
);
|
||||
|
||||
$fields[] = array(
|
||||
'type' => 'select',
|
||||
'tab' => 'filter',
|
||||
'label' => $this->my_translation('Filter options for ' . $f_field),
|
||||
'name' => 'import_api_filter_options['. $f_field .']',
|
||||
'options' => array(
|
||||
'query' => $filter_options,
|
||||
'id' => 'id_option',
|
||||
'name' => 'name'
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
foreach($this->replace_fields as $r_field) {
|
||||
$fields[] = array(
|
||||
'type' => 'textarea',
|
||||
'tab' => 'replace',
|
||||
'rows' => 10,
|
||||
'hint' => 'Enter each value in new line in format OLD_TEXT##NEW_TEXT',
|
||||
'label' => $this->my_translation($r_field),
|
||||
'name' => 'import_api_replace['. $r_field .']',
|
||||
'description' => 'Enter values in format old_word##new_word',
|
||||
);
|
||||
}
|
||||
|
||||
// Settings fields
|
||||
|
||||
$fields[] = array(
|
||||
'type' => 'text',
|
||||
'tab' => 'settings',
|
||||
'label' => $this->my_translation('Top category'),
|
||||
'name' => 'import_api_settings[top_category]',
|
||||
);
|
||||
|
||||
$fields[] = array(
|
||||
'type' => 'text',
|
||||
'tab' => 'settings',
|
||||
'label' => $this->my_translation('Default category'),
|
||||
'name' => 'import_api_settings[default_category]',
|
||||
);
|
||||
|
||||
$fields[] = array(
|
||||
'type' => 'text',
|
||||
'tab' => 'settings',
|
||||
'label' => $this->my_translation('Default brand'),
|
||||
'name' => 'import_api_settings[default_brand]',
|
||||
);
|
||||
|
||||
$fields[] = array(
|
||||
'type' => 'text',
|
||||
'tab' => 'settings',
|
||||
'label' => $this->my_translation('Price multiplier'),
|
||||
'name' => 'import_api_settings[price_multiplier]',
|
||||
);
|
||||
|
||||
$fields[] = array(
|
||||
'type' => 'text',
|
||||
'tab' => 'settings',
|
||||
'label' => $this->my_translation('Combination price multiplier'),
|
||||
'name' => 'import_api_settings[combination_price_multiplier]',
|
||||
);
|
||||
|
||||
$fields[] = array(
|
||||
'type' => 'select',
|
||||
'tab' => 'settings',
|
||||
'label' => $this->my_translation('Add combination price to product price'),
|
||||
'name' => 'import_api_settings[add_combination_price]',
|
||||
'options' => array(
|
||||
'query' => $options_yes_no,
|
||||
'id' => 'id_option',
|
||||
'name' => 'name'
|
||||
)
|
||||
);
|
||||
|
||||
$fields[] = array(
|
||||
'type' => 'select',
|
||||
'tab' => 'settings',
|
||||
'label' => $this->my_translation('Create category path from array'),
|
||||
'name' => 'import_api_settings[category_path]',
|
||||
'options' => array(
|
||||
'query' => $options_yes_no,
|
||||
'id' => 'id_option',
|
||||
'name' => 'name'
|
||||
)
|
||||
);
|
||||
|
||||
$fields[] = array(
|
||||
'type' => 'select',
|
||||
'tab' => 'settings',
|
||||
'label' => $this->my_translation('Tax rules group'),
|
||||
'name' => 'import_api_settings[id_tax_rules_group]',
|
||||
'options' => array(
|
||||
'query' => $taxes,
|
||||
'id' => 'id_tax_rules_group',
|
||||
'name' => 'name'
|
||||
)
|
||||
);
|
||||
|
||||
|
||||
$fields[] = array(
|
||||
'type' => 'select',
|
||||
'tab' => 'settings',
|
||||
'label' => $this->my_translation('Update even if file is not changed'),
|
||||
'name' => 'import_api_settings[same_update]',
|
||||
'options' => array(
|
||||
'query' => $options_yes_no,
|
||||
'id' => 'id_option',
|
||||
'name' => 'name'
|
||||
)
|
||||
);
|
||||
|
||||
$fields[] = array(
|
||||
'type' => 'select',
|
||||
'tab' => 'settings',
|
||||
'label' => $this->my_translation('If product not exist in file anymore'),
|
||||
'name' => 'import_api_settings[not_existing]',
|
||||
'options' => array(
|
||||
'query' => $options_not_existing,
|
||||
'id' => 'id_option',
|
||||
'name' => 'name'
|
||||
)
|
||||
);
|
||||
|
||||
$fields[] = array(
|
||||
'type' => 'select',
|
||||
'tab' => 'settings',
|
||||
'label' => $this->my_translation('Update only'),
|
||||
'name' => 'import_api_settings[only_update]',
|
||||
'options' => array(
|
||||
'query' => $options_yes_no,
|
||||
'id' => 'id_option',
|
||||
'name' => 'name'
|
||||
)
|
||||
);
|
||||
|
||||
$fields[] = array(
|
||||
'type' => 'select',
|
||||
'tab' => 'settings',
|
||||
'label' => $this->my_translation('Update field'),
|
||||
'name' => 'import_api_settings[synchronize_field]',
|
||||
'options' => array(
|
||||
'query' => $options_synchronize_field,
|
||||
'id' => 'id_option',
|
||||
'name' => 'name'
|
||||
)
|
||||
);
|
||||
|
||||
foreach($this->frm_update_settings as $key => $setting) {
|
||||
$fields[] = array(
|
||||
'type' => 'select',
|
||||
'tab' => 'update',
|
||||
'label' => $this->my_translation('Update '. $key),
|
||||
'name' => 'import_api_settings[update_' . $key .']',
|
||||
'options' => array(
|
||||
'query' => $options_yes_no,
|
||||
'id' => 'id_option',
|
||||
'name' => 'name'
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
return array(
|
||||
'form' => array(
|
||||
'legend' => array(
|
||||
'title' => $this->my_translation('Configuration'),
|
||||
'icon' => 'icon-cogs',
|
||||
),
|
||||
'input' => $fields,
|
||||
'submit' => array(
|
||||
'title' => $this->my_translation('Save'),
|
||||
),
|
||||
'tabs' => array(
|
||||
'general' => $this->my_translation('Assign'),
|
||||
'combinations' => $this->my_translation('Split'),
|
||||
'modifications' => $this->my_translation('Modifications'),
|
||||
'filter' => $this->my_translation('Filter'),
|
||||
'replace' => $this->my_translation('Replace'),
|
||||
'settings' => $this->my_translation('Settings'),
|
||||
'update' => $this->my_translation('Update fields'),
|
||||
'test' => $this->my_translation('Test'),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
protected function getConfigFormValues()
|
||||
{
|
||||
$file_id = Tools::getValue('file_id');
|
||||
$return_settings = array();
|
||||
if (((bool)Tools::isSubmit('submitImportSettings')) == true) {
|
||||
$config_fields = Tools::getValue('import_api_field');
|
||||
$config_modification = Tools::getValue('import_api_modification');
|
||||
$config_split = Tools::getValue('import_api_split');
|
||||
$config_replace = Tools::getValue('import_api_replace');
|
||||
$config_filter = Tools::getValue('import_api_filter');
|
||||
$config_filter_options = Tools::getValue('import_api_filter_options');
|
||||
|
||||
$config_settings = Tools::getValue('import_api_settings');
|
||||
|
||||
$return_settings['import_api_fields'] = Tools::getValue('import_api_fields');
|
||||
$return_settings['import_api_link'] = Tools::getValue('import_api_link');
|
||||
$return_settings['import_api_type'] = Tools::getValue('import_api_type');
|
||||
} else {
|
||||
$query_file_settings = Db::getInstance()->executeS("SELECT fs.* FROM ". _DB_PREFIX_ . "ia_file_settings fs WHERE fs.file_id = '" . (int)$file_id . "' LIMIT 1");
|
||||
if ($query_file_settings) {
|
||||
$file_settings =$query_file_settings[0];
|
||||
$config_fields = json_decode($file_settings['mapping'], true);
|
||||
$config_modification = json_decode($file_settings['modification'], true);
|
||||
$config_split = json_decode($file_settings['split'], true);
|
||||
$config_replace = json_decode($file_settings['replace'], true);
|
||||
$config_filter = json_decode($file_settings['filter'], true);
|
||||
$config_filter_options = json_decode($file_settings['filter_options'], true);
|
||||
$config_settings = json_decode($file_settings['settings'], true);
|
||||
}
|
||||
|
||||
$return_settings['import_api_fields'] = '';
|
||||
$return_settings['import_api_link'] = '';
|
||||
$return_settings['import_api_type'] = '';
|
||||
}
|
||||
|
||||
foreach($this->frm_fields as $fmr_field){
|
||||
$return_settings['import_api_field[' . $fmr_field . ']'] = !empty($config_fields[$fmr_field]) ? html_entity_decode($config_fields[$fmr_field], ENT_QUOTES, 'UTF-8') : '';
|
||||
$return_settings['import_api_modification[' . $fmr_field . ']'] = !empty($config_modification[$fmr_field]) ? html_entity_decode($config_modification[$fmr_field], ENT_QUOTES, 'UTF-8') : '';
|
||||
$return_settings['import_api_split[' . $fmr_field . ']'] = !empty($config_split[$fmr_field]) ? html_entity_decode($config_split[$fmr_field], ENT_QUOTES, 'UTF-8') : '';
|
||||
}
|
||||
|
||||
foreach($this->replace_fields as $r_field){
|
||||
$return_settings['import_api_replace[' . $r_field . ']'] = !empty($config_replace[$r_field]) ? html_entity_decode($config_replace[$r_field], ENT_QUOTES, 'UTF-8') : '';
|
||||
}
|
||||
|
||||
foreach($this->filter_fields as $f_field){
|
||||
$return_settings['import_api_filter[' . $f_field . ']'] = !empty($config_filter[$f_field]) ? html_entity_decode($config_filter[$f_field], ENT_QUOTES, 'UTF-8') : '';
|
||||
$return_settings['import_api_filter_options[' . $f_field . ']'] = !empty($config_filter_options[$f_field]) ? html_entity_decode($config_filter_options[$f_field], ENT_QUOTES, 'UTF-8') : '';
|
||||
}
|
||||
|
||||
for($i = 1; $i <= 3; $i++){
|
||||
$return_settings['import_api_field[field' . $i. ']'] = !empty($config_fields['field' . $i]) ? html_entity_decode($config_fields['field' . $i], ENT_QUOTES, 'UTF-8') : '';
|
||||
}
|
||||
|
||||
for($i = 1; $i <= 3; $i++){
|
||||
$return_settings['import_api_modification[modification' . $i . ']'] = !empty($config_modification['modification' . $i]) ? html_entity_decode($config_modification['modification' . $i], ENT_QUOTES, 'UTF-8') : '';
|
||||
}
|
||||
|
||||
foreach($this->frm_settings as $setting => $value){
|
||||
$return_settings['import_api_settings[' . $setting . ']'] = isset($config_settings[$setting]) ? $config_settings[$setting] : $value;
|
||||
}
|
||||
|
||||
foreach($this->frm_update_settings as $setting => $value){
|
||||
$return_settings['import_api_settings[update_' . $setting . ']'] = isset($config_settings['update_' . $setting]) ? $config_settings['update_' . $setting] : $value;
|
||||
}
|
||||
|
||||
|
||||
return $return_settings;
|
||||
}
|
||||
|
||||
protected function _postSettingsValidation()
|
||||
{
|
||||
|
||||
if (!Tools::getValue('import_api_field')) {
|
||||
$this->_postErrors[] = $this->my_translation('You must assign unique field and name field.');
|
||||
} else {
|
||||
$fields = Tools::getValue('import_api_field');
|
||||
if(empty($fields['unique'])){
|
||||
$this->_postErrors[] = $this->my_translation('You must assign unique field');
|
||||
}
|
||||
if(empty($fields['name'])){
|
||||
//$this->_postErrors[] = $this->my_translation('You must assign name field');
|
||||
}
|
||||
}
|
||||
}
|
||||
protected function _saveSettings($file_id, $shop = 'default')
|
||||
{
|
||||
|
||||
$mapping = '';
|
||||
$modification = '';
|
||||
$split = '';
|
||||
$replace = '';
|
||||
$filter = '';
|
||||
$filter_options = '';
|
||||
$settings = '';
|
||||
$update = false;
|
||||
|
||||
$query_file_settings = Db::getInstance()->executeS("SELECT fs.* FROM ". _DB_PREFIX_ . "ia_file_settings fs WHERE fs.file_id = '" . (int)$file_id . "' LIMIT 1");
|
||||
if ($query_file_settings) {
|
||||
$file_settings = $query_file_settings[0];
|
||||
$mapping = $file_settings['mapping'];
|
||||
$modification = $file_settings['modification'];
|
||||
$split = $file_settings['split'];
|
||||
$replace = $file_settings['replace'];
|
||||
$filter = $file_settings['filter'];
|
||||
$filter_options = $file_settings['filter_options'];
|
||||
$settings = $file_settings['settings'];
|
||||
$update = true;
|
||||
}
|
||||
|
||||
$implode = array();
|
||||
|
||||
$new_mapping = json_encode(Tools::getValue('import_api_field'));
|
||||
$new_modification = json_encode(Tools::getValue('import_api_modification'));
|
||||
$new_split = json_encode(Tools::getValue('import_api_split'));
|
||||
$new_replace = json_encode(Tools::getValue('import_api_replace'));
|
||||
$new_filter = json_encode(Tools::getValue('import_api_filter'));
|
||||
$new_filter_options = json_encode(Tools::getValue('import_api_filter_options'));
|
||||
$new_settings = json_encode(Tools::getValue('import_api_settings'));
|
||||
|
||||
if (Tools::getValue('import_api_field') && $new_mapping != $mapping) {
|
||||
$implode[] = "mapping='" . pSQL($new_mapping). "'";
|
||||
}
|
||||
|
||||
if (Tools::getValue('import_api_modification') && $new_modification != $modification) {
|
||||
$implode[] = "modification='" . pSQL($new_modification). "'";
|
||||
}
|
||||
|
||||
if (Tools::getValue('import_api_split') && $new_split != $split) {
|
||||
$implode[] = "split='" . pSQL($new_split). "'";
|
||||
}
|
||||
|
||||
if (Tools::getValue('import_api_replace') && $new_replace != $replace) {
|
||||
$implode[] = "`replace`='" . pSQL($new_replace). "'";
|
||||
}
|
||||
|
||||
if (Tools::getValue('import_api_filter') && $new_filter != $filter) {
|
||||
$implode[] = "`filter`='" . pSQL($new_filter). "'";
|
||||
}
|
||||
|
||||
if (Tools::getValue('import_api_filter_options') && $new_filter_options != $filter_options) {
|
||||
$implode[] = "filter_options='" . pSQL($new_filter_options). "'";
|
||||
}
|
||||
|
||||
if (Tools::getValue('import_api_settings') && $new_settings != $settings) {
|
||||
$implode[] = "settings='" . pSQL($new_settings). "'";
|
||||
}
|
||||
|
||||
if ($implode) {
|
||||
$implode[] = "date_updated = '" . time() ."'";
|
||||
$implode_string = implode(',', $implode);
|
||||
|
||||
if ($update) {
|
||||
Db::getInstance()->execute("UPDATE ". _DB_PREFIX_ . "ia_file_settings SET " .$implode_string. " WHERE file_id = '" .(int)$file_id . "' AND shop = '" . pSQL($shop) . "'");
|
||||
} else {
|
||||
Db::getInstance()->execute("INSERT INTO ". _DB_PREFIX_ . "ia_file_settings SET " .$implode_string. ", file_id = '" .(int)$file_id . "', shop = '" . pSQL($shop) . "'");
|
||||
}
|
||||
//print_r("UPDATE ". _DB_PREFIX_ . "ia_file_settings SET " .$implode_string. " WHERE file_id = '" .(int)$file_id . "' AND shop = '" . $shop . "'");
|
||||
$this->queue->deleteUnnecessary($file_id, $shop);
|
||||
Tools::redirectAdmin($this->context->link->getAdminLink('AdminImport_Api&type=import&file_id=' . $file_id . '&token=' . Tools::getAdminTokenLite('AdminImport_Api'), false));
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
public function my_translation($string) {
|
||||
return $this->module->l($string);
|
||||
}
|
||||
}
|
||||
106
modules/import_api/controllers/front/ajax.php
Normal file
106
modules/import_api/controllers/front/ajax.php
Normal file
@@ -0,0 +1,106 @@
|
||||
<?php
|
||||
/**
|
||||
* NOTICE OF LICENSE
|
||||
* With the purchase or the installation of the software in your application
|
||||
* you accept the licence agreement.
|
||||
*
|
||||
* You can not resell and redistribute this file.
|
||||
*
|
||||
* @author Dalibor Stojcevski <dal_sto@yahoo.com>
|
||||
* @copyright 2019 Dalibor Stojcevski
|
||||
* @license Dalibor Stojcevski
|
||||
*/
|
||||
|
||||
class Import_ApiAjaxModuleFrontController extends ModuleFrontController
|
||||
{
|
||||
|
||||
/**
|
||||
* Assign template vars related to page content
|
||||
* @see FrontController::initContent()
|
||||
*/
|
||||
private $fields = array();
|
||||
|
||||
public function initContent()
|
||||
{
|
||||
$response = $this->find_fields();
|
||||
$json = Tools::jsonEncode($response);
|
||||
$this->ajaxDie($json);
|
||||
|
||||
}
|
||||
|
||||
|
||||
public function find_fields()
|
||||
{
|
||||
|
||||
Db::getInstance()->execute("SET session wait_timeout=28800", FALSE);
|
||||
Db::getInstance()->execute("SET session net_read_timeout=28800", FALSE);
|
||||
Db::getInstance()->execute("SET session interactive_timeout=28800", FALSE);
|
||||
$file_id = Tools::getValue('file_id');
|
||||
$shop = 'default';
|
||||
$json['error'] = '';
|
||||
$php_array = array();
|
||||
$query_file = Db::getInstance()->executeS("SELECT * FROM ". _DB_PREFIX_ . "ia_files WHERE file_id = '" . (int)$file_id . "' AND shop = '" . pSQL($shop) . "' LIMIT 1");
|
||||
|
||||
//$type = Tools::getValue('type');
|
||||
//$link = html_entity_decode($this->request->post['import_api_link'], ENT_QUOTES, "UTF-8");
|
||||
|
||||
if ($query_file) {
|
||||
require_once(_PS_MODULE_DIR_ . 'import_api/classes/filereader.php');
|
||||
|
||||
$FileReader = new FileReader();
|
||||
$file = $query_file[0];
|
||||
//$file['link'] = html_entity_decode($file['link'], ENT_QUOTES, "UTF-8");
|
||||
|
||||
list($php_array, $json['error']) = $FileReader->getArrayFromLink($file);
|
||||
|
||||
if($php_array === null){
|
||||
$json['error'] = 'File is not in selected format';
|
||||
}
|
||||
} else {
|
||||
$json['error'] = 'File not found';
|
||||
}
|
||||
|
||||
if (!$json['error']){
|
||||
if (count($php_array) > 10 && !empty(array_key_first($php_array))) { // if is not 0
|
||||
$new_array = array();
|
||||
foreach ($php_array as $key => $value ) {
|
||||
$value['GENERATED_UNIQUE'] = $key;
|
||||
$new_array[] = $value;
|
||||
}
|
||||
$php_array = $new_array;
|
||||
unset($new_array);
|
||||
}
|
||||
$this->search_keys($php_array, 'FEED');
|
||||
$json['field'] = $this->fields;
|
||||
$json['fields'] = implode('##', $this->fields);
|
||||
//$json['mapping'] = implode('##', $this->fields);
|
||||
if ($this->fields) {
|
||||
Db::getInstance()->execute("UPDATE ". _DB_PREFIX_ . "ia_files SET fields = '" . pSQL($json['fields']) . "', date_edited = '" . time() . "' WHERE file_id = " . (int)$file_id ." AND shop = '" . pSQL($shop) . "'");
|
||||
}
|
||||
}
|
||||
|
||||
return $json;
|
||||
}
|
||||
|
||||
function search_keys($array, $parent){
|
||||
$total = count($array);
|
||||
foreach($array as $key => $value){
|
||||
if(!is_array($value)){
|
||||
if (is_int($key)) {
|
||||
$path = $parent;
|
||||
} else {
|
||||
$path = $parent .'->'. $key;
|
||||
}
|
||||
|
||||
$path = str_replace('->array()', '',$path);
|
||||
if (!in_array($path, $this->fields))
|
||||
$this->fields[] = $path;
|
||||
} else {
|
||||
if (is_int($key)) {
|
||||
$key = "array()";
|
||||
}
|
||||
$this->search_keys($value, $parent .'->'. $key);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
690
modules/import_api/controllers/front/import.php
Normal file
690
modules/import_api/controllers/front/import.php
Normal file
@@ -0,0 +1,690 @@
|
||||
<?php
|
||||
/**
|
||||
* NOTICE OF LICENSE
|
||||
* With the purchase or the installation of the software in your application
|
||||
* you accept the licence agreement.
|
||||
*
|
||||
* You can not resell and redistribute this file.
|
||||
*
|
||||
* @author Dalibor Stojcevski <dal_sto@yahoo.com>
|
||||
* @copyright 2019 Dalibor Stojcevski
|
||||
* @license Dalibor Stojcevski
|
||||
*/
|
||||
ini_set('memory_limit', '-1');
|
||||
class Import_ApiImportModuleFrontController extends ModuleFrontController
|
||||
{
|
||||
|
||||
/**
|
||||
* Assign template vars related to page content
|
||||
* @see FrontController::initContent()
|
||||
*/
|
||||
private $fields = array();
|
||||
private $product_links = array();
|
||||
private $import;
|
||||
private $creator;
|
||||
private $convertor;
|
||||
public static $update_limit = 1;
|
||||
|
||||
public function initContent()
|
||||
{
|
||||
|
||||
require_once(_PS_MODULE_DIR_ . 'import_api/classes/import.php');
|
||||
require_once(_PS_MODULE_DIR_ . 'import_api/classes/creator.php');
|
||||
require_once(_PS_MODULE_DIR_ . 'import_api/classes/filereader.php');
|
||||
require_once(_PS_MODULE_DIR_ . 'import_api/classes/queue.php');
|
||||
require_once(_PS_MODULE_DIR_ . 'import_api/classes/convertor.php');
|
||||
Db::getInstance()->execute("SET session wait_timeout=28800", FALSE);
|
||||
Db::getInstance()->execute("SET session net_read_timeout=28800", FALSE);
|
||||
Db::getInstance()->execute("SET session interactive_timeout=28800", FALSE);
|
||||
|
||||
$json = array();
|
||||
|
||||
$view = Tools::getValue('id');
|
||||
|
||||
$file_id = Tools::getValue('file_id');
|
||||
|
||||
$this->queue = new Queue();
|
||||
|
||||
$this->creator = new Creator($file_id);
|
||||
|
||||
$action = Tools::getValue('action') ? Tools::getValue('action') : 'cron';
|
||||
|
||||
/* if ($this->product_links === null) {
|
||||
$json['error'] = 'Invalid source url. Please check in browser first';
|
||||
$this->ajaxDie(Tools::jsonEncode($json));
|
||||
}*/
|
||||
|
||||
$this->getModuleSettings();
|
||||
|
||||
|
||||
$this->convertor = new Convertor($this->settings, $this->creator);
|
||||
|
||||
if ($action == 'test')
|
||||
{
|
||||
//$this->creator->addAttributesToProduct(array('0' => array('0' => array('attribute'=> "DColor", 'attribute_value' => "blue"), '1' => array('attribute'=> "DColor", 'attribute_value' => "green"))), 12685); exit;
|
||||
|
||||
$this->product_links = $this->getProductLinks($action);
|
||||
$this->printTestJsonData($view);
|
||||
}
|
||||
elseif (Tools::getValue('queue'))
|
||||
{
|
||||
$this->queue($file_id);
|
||||
echo 'koniec';
|
||||
exit;
|
||||
}
|
||||
elseif ($action == 'selected')
|
||||
{
|
||||
$this->importSelected($file_id);
|
||||
}
|
||||
elseif ($action == 'delete')
|
||||
{
|
||||
$this->deleteProducts($file_id);
|
||||
}
|
||||
elseif ($action == 'view_one')
|
||||
{
|
||||
$this->viewOne($file_id, Tools::getValue('index'));
|
||||
}
|
||||
elseif (Tools::getValue('index'))
|
||||
{
|
||||
$this->importOne($file_id, Tools::getValue('index'));
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->importData($file_id, $action, Tools::getValue( 'limit' ) );
|
||||
Tools::clearSmartyCache();
|
||||
Tools::clearXMLCache();
|
||||
Media::clearCache();
|
||||
Tools::generateIndex();
|
||||
}
|
||||
}
|
||||
|
||||
function queue($file_id)
|
||||
{
|
||||
$product_links = $this->getProductLinks();
|
||||
|
||||
$products = array();
|
||||
|
||||
foreach ($product_links as $link)
|
||||
{
|
||||
$original_product = $this->importer->getAllData($link);
|
||||
$original_product = $this->convertor->unArray($original_product);
|
||||
$original_product = $this->convertor->replace($original_product);
|
||||
$original_product = $this->convertor->filter($original_product);
|
||||
|
||||
$original_product = $this->convertor->clearInput($original_product);
|
||||
if ($original_product['belong'])
|
||||
{
|
||||
$products[$original_product['unique']] = $original_product;
|
||||
}
|
||||
}
|
||||
|
||||
$this->queue->saveTempToDb($products, $file_id);
|
||||
|
||||
return count($products);
|
||||
}
|
||||
|
||||
function importData($file_id, $action = 'cron', $limit = 0 )
|
||||
{
|
||||
$json['notice'] = '';
|
||||
$last_queue = $this->queue->getLastQueue($file_id);
|
||||
|
||||
if (!$last_queue || $last_queue['status'] == 4)
|
||||
{
|
||||
// $this->queue($file_id);
|
||||
// $last_queue = $this->queue->getLastQueue($file_id);
|
||||
}
|
||||
|
||||
if (!$last_queue)
|
||||
{
|
||||
exit('Queue creation error');
|
||||
}
|
||||
if ($last_queue['status'] == 3)
|
||||
{
|
||||
$this->creator->processMissing($file_id, $last_queue['queue_id']);
|
||||
$this->ajaxDie(Tools::jsonEncode($json));
|
||||
exit;
|
||||
}
|
||||
|
||||
$products = $this->queue->getQueued($file_id);
|
||||
|
||||
if (!$products)
|
||||
{
|
||||
// $this->queue($file_id);
|
||||
// $products = $this->queue->getQueued($file_id);
|
||||
// $last_queue = $this->queue->getLastQueue($file_id);
|
||||
echo 'koniec';
|
||||
exit;
|
||||
}
|
||||
|
||||
|
||||
$queue_id = isset($products[0]) ? $products[0]['queue_id'] : 0;
|
||||
$products_created = 0;
|
||||
$products_updated = 0;
|
||||
|
||||
$json['total'] = count($products);
|
||||
|
||||
foreach ($products as $product)
|
||||
{
|
||||
$original_product = json_decode($product['product'], true);
|
||||
|
||||
$product_id = 0;
|
||||
|
||||
if ($this->settings['unique_equivalent'] == 'id_product')
|
||||
{
|
||||
$product_id = (int)$original_product['unique'];
|
||||
}
|
||||
else
|
||||
{
|
||||
$equivalent = $this->settings['unique_equivalent'];
|
||||
|
||||
$query = ($equivalent == 'name') ? $original_product['name'] : $original_product['unique'];
|
||||
|
||||
$product_id = $this->creator->getProductId($query, $this->settings['table_equivalent'], $equivalent);
|
||||
}
|
||||
|
||||
$this->queue->deleteQueuedProduct($product['product_id']);
|
||||
if ($product_id)
|
||||
{
|
||||
$this->creator->editProduct($product_id, $original_product);
|
||||
Db::getInstance()->execute("UPDATE " . _DB_PREFIX_ . "ia_products SET indx = '" . pSQL($original_product['unique']) . "', product = '" . pSQL(json_encode($original_product)) . "', source = 'admin', date_edited = '" . time() . "', queue_id = '" . (int)$queue_id . "', file_id = '" . (int)$file_id . "' WHERE product_id = '" . (int)$product_id . "' AND shop = 'default'");
|
||||
|
||||
$products_updated++;
|
||||
|
||||
if ( $action == 'cron' )
|
||||
echo '<p>Zaktualizowałem produkt: ' . $product_id . '</p>';
|
||||
}
|
||||
elseif (empty($this->settings['import_api_settings']['only_update']))
|
||||
{
|
||||
$frm_product = $this->convertor->convertToFrmProduct($original_product, $file_id);
|
||||
$product_id = $frm_product->id;
|
||||
Db::getInstance()->execute("INSERT INTO " . _DB_PREFIX_ . "ia_products SET product_id = '" . $product_id . "', indx = '" . pSQL($original_product['unique']) . "', product = '" . pSQL(json_encode($original_product)) . "', shop = 'default', source = 'admin', date_added = '" . time() . "', queue_id = '" . (int)$queue_id . "', file_id = '" . (int)$file_id . "'");
|
||||
|
||||
$products_created++;
|
||||
|
||||
if ( $action == 'cron' )
|
||||
echo '<p>Dodałem nowy produkt: ' . $product_id . '</p>';
|
||||
}
|
||||
|
||||
if ( ( ( $products_created + $products_updated ) >= self::$update_limit ) or ( $limit and ( $products_created + $products_updated ) >= $limit ) )
|
||||
{
|
||||
$json['notice'] = 'time_out';
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!$json['notice'])
|
||||
{
|
||||
$json['notice'] = 'missing';
|
||||
Db::getInstance()->execute("UPDATE " . _DB_PREFIX_ . "ia_queues SET source = 'admin', status = '3', date_processed = '" . time() . "' WHERE queue_id = '" . (int)$queue_id . "'");
|
||||
}
|
||||
|
||||
if ($action != 'cron')
|
||||
{
|
||||
$json['products_created'] = $products_created;
|
||||
$json['products_updated'] = $products_updated;
|
||||
$this->ajaxDie(Tools::jsonEncode($json));
|
||||
}
|
||||
|
||||
exit;
|
||||
}
|
||||
|
||||
function importSelected($file_id)
|
||||
{
|
||||
$products = array();
|
||||
$selected = Tools::getValue('indx') ? Tools::getValue('indx') : array();
|
||||
|
||||
foreach ($selected as $indx)
|
||||
{
|
||||
$products[] = $this->queue->getQueuedProduct($indx, $file_id);
|
||||
}
|
||||
$queue_id = isset($products[0]) ? $products[0]['queue_id'] : 0;
|
||||
|
||||
$products_created = 0;
|
||||
$products_updated = 0;
|
||||
|
||||
$json['notice'] = '';
|
||||
$json['total'] = count($products);
|
||||
$json['processed'] = array();
|
||||
|
||||
foreach ($products as $product)
|
||||
{
|
||||
$original_product = json_decode($product['product'], true);
|
||||
|
||||
$json['processed'][] = $product['product_id'];
|
||||
|
||||
$product_id = 0;
|
||||
|
||||
if ($this->settings['unique_equivalent'] == 'id_product')
|
||||
{
|
||||
$product_id = (int)$original_product['unique'];
|
||||
}
|
||||
else
|
||||
{
|
||||
$equivalent = $this->settings['unique_equivalent'];
|
||||
|
||||
$query = ($equivalent == 'name') ? $original_product['name'] : $original_product['unique'];
|
||||
|
||||
$product_id = $this->creator->getProductId($query, $this->settings['table_equivalent'], $equivalent);
|
||||
}
|
||||
|
||||
$this->queue->deleteQueuedProduct($product['product_id']);
|
||||
|
||||
if ($product_id)
|
||||
{
|
||||
$this->creator->editProduct($product_id, $original_product);
|
||||
Db::getInstance()->execute("UPDATE " . _DB_PREFIX_ . "ia_products SET indx = '" . pSQL($indx) . "', product = '" . pSQL(json_encode($original_product)) . "', source = 'selected', date_edited = '" . time() . "', queue_id = '" . (int)$queue_id . "', file_id = '" . (int)$file_id . "' WHERE product_id = '" . (int)$product_id . "' AND shop = 'default'");
|
||||
|
||||
$products_updated++;
|
||||
}
|
||||
elseif (empty($this->settings['import_api_settings']['only_update']))
|
||||
{
|
||||
$frm_product = $this->convertor->convertToFrmProduct($original_product, $file_id);
|
||||
$product_id = $frm_product->id;
|
||||
Db::getInstance()->execute("INSERT INTO " . _DB_PREFIX_ . "ia_products SET product_id = '" . (int)$product_id . "', indx = '" . pSQL($indx) . "', product = '" . pSQL(json_encode($original_product)) . "', shop = 'default', source = 'selected', date_added = '" . time() . "', queue_id = '" . (int)$queue_id . "', file_id = '" . (int)$file_id . "'");
|
||||
|
||||
$products_created++;
|
||||
}
|
||||
|
||||
if ( ( $products_created + $products_updated ) >= self::$update_limit )
|
||||
{
|
||||
$json['notice'] = 'time_out';
|
||||
break;
|
||||
}
|
||||
}
|
||||
$json['products_created'] = $products_created;
|
||||
$json['products_updated'] = $products_updated;
|
||||
$this->ajaxDie(Tools::jsonEncode($json));
|
||||
|
||||
exit;
|
||||
}
|
||||
|
||||
function importOne($file_id, $indx)
|
||||
{
|
||||
$product = $this->queue->getQueuedProduct($indx, $file_id);
|
||||
|
||||
if (!$product)
|
||||
{
|
||||
echo 'Product not found in queue';
|
||||
exit;
|
||||
}
|
||||
$queue_id = isset($product[0]) ? $product['queue_id'] : 0;
|
||||
|
||||
|
||||
$original_product = json_decode($product['product'], true);
|
||||
|
||||
$equivalent = $this->settings['unique_equivalent'];
|
||||
|
||||
$query = ($equivalent == 'name') ? $original_product['name'] : $original_product['unique'];
|
||||
|
||||
$product_id = $this->creator->getProductId($query, $this->settings['table_equivalent'], $equivalent);
|
||||
$link = new Link();
|
||||
if ($product_id)
|
||||
{
|
||||
$exising = $this->creator->editProduct($product_id, $original_product);
|
||||
Db::getInstance()->execute("UPDATE " . _DB_PREFIX_ . "ia_products SET indx = '" . pSQL($indx) . "', product = '" . pSQL(json_encode($original_product)) . "', source = 'selected', date_edited = '" . time() . "', queue_id = '" . (int)$queue_id . "', file_id = '" . (int)$file_id . "' WHERE product_id = '" . (int)$product_id . "' AND shop = 'default'");
|
||||
echo 'Product is updated';
|
||||
//echo 'link to product <a href="' . $link->getproductlink($product_id) . '">' . $link->getproductlink($product_id) . '</a>';
|
||||
}
|
||||
else
|
||||
{
|
||||
$frm_product = $this->convertor->convertToFrmProduct($original_product, $file_id);
|
||||
if ($frm_product)
|
||||
{
|
||||
$product_id = $frm_product->id;
|
||||
Db::getInstance()->execute("INSERT INTO " . _DB_PREFIX_ . "ia_products SET product_id = '" . (int)$product_id . "', indx = '" . pSQL($indx) . "', product = '" . pSQL(json_encode($original_product)) . "', shop = 'default', source = 'selected', date_added = '" . time() . "', queue_id = '" . (int)$queue_id . "', file_id = '" . (int)$file_id . "'");
|
||||
echo 'Product is inserted';
|
||||
//echo 'Link to product <a href="' . $link->getProductLink($product_id) . '">' . $link->getProductLink($product_id) . '</a>';
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
exit;
|
||||
}
|
||||
|
||||
function viewOne($file_id, $indx)
|
||||
{
|
||||
$product = $this->queue->getQueuedProduct($indx, $file_id);
|
||||
|
||||
if (!$product)
|
||||
{
|
||||
echo 'Product not found in queue';
|
||||
exit;
|
||||
}
|
||||
|
||||
$queue_id = isset($product[0]) ? $product['queue_id'] : 0;
|
||||
|
||||
$original_product = json_decode($product['product'], true);
|
||||
|
||||
$equivalent = $this->settings['unique_equivalent'];
|
||||
|
||||
$query = ($equivalent == 'name') ? $original_product['name'] : $original_product['unique'];
|
||||
|
||||
$product_id = $this->creator->getProductId($query, $this->settings['table_equivalent'], $equivalent);
|
||||
$link = new Link();
|
||||
if ($product_id)
|
||||
{
|
||||
echo 'Product exists ' . $product_id;
|
||||
//echo 'link to product <a href="' . $link->getproductlink($exising) . '">' . $link->getproductlink($exising) . '</a>';
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
echo 'Product is not inserted in Prestashop site ';
|
||||
}
|
||||
|
||||
foreach ($original_product as $key => $value)
|
||||
{
|
||||
if (!is_array($value))
|
||||
{
|
||||
echo $key . ':' . $value . ', ';
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($original_product['cover']))
|
||||
{
|
||||
if (!$this->UR_exists($original_product['cover']))
|
||||
{
|
||||
echo 'image is not found. If you need to add server name go to Modifications and add https://servername/[[cover]]';
|
||||
}
|
||||
else
|
||||
{
|
||||
echo 'image: ' . $original_product['cover'];
|
||||
}
|
||||
}
|
||||
exit;
|
||||
}
|
||||
|
||||
private function printTestJsonData($view)
|
||||
{
|
||||
$json = array();
|
||||
|
||||
foreach ($this->product_links as $link)
|
||||
{
|
||||
$json[] = $this->importer->getAllData($link, $view);
|
||||
}
|
||||
|
||||
$this->ajaxDie(Tools::jsonEncode($json));
|
||||
}
|
||||
|
||||
private function getProductLinks($action = 'import')
|
||||
{
|
||||
$begin_character = 'FEED';
|
||||
|
||||
$shop = 'default';
|
||||
|
||||
$file_id = Tools::getValue('file_id');
|
||||
|
||||
$settings = $this->getModuleSettings($file_id);
|
||||
|
||||
$query_file = Db::getInstance()->executeS("SELECT * FROM " . _DB_PREFIX_ . "ia_files WHERE file_id = '" . (int)$file_id . "' AND shop = '" . pSQL($shop) . "' LIMIT 1");
|
||||
|
||||
$file = $query_file[0];
|
||||
|
||||
$FileReader = new FileReader();
|
||||
|
||||
list($tmp_array, $error) = $FileReader->getArrayFromLink($file);
|
||||
|
||||
if ( is_array( $tmp_array) and count($tmp_array) > 10 && !empty(array_key_first($tmp_array)))
|
||||
{ // if is not 0
|
||||
$new_array = array();
|
||||
foreach ($tmp_array as $key => $value)
|
||||
{
|
||||
$value['GENERATED_UNIQUE'] = $key;
|
||||
$new_array[] = $value;
|
||||
}
|
||||
$tmp_array = $new_array;
|
||||
unset($new_array);
|
||||
}
|
||||
|
||||
$php_array[$begin_character] = $tmp_array;
|
||||
|
||||
$parts = explode('->', $settings['unique_field']);
|
||||
|
||||
$identifier_field = $parts[count($parts) - 1];
|
||||
|
||||
|
||||
$importer = new Import($settings);
|
||||
|
||||
$importer->setJsonArray($php_array);
|
||||
$importer->findUniqueProductsIdentifier($php_array, $parts, $identifier_field);
|
||||
|
||||
|
||||
$product_links = $importer->getProductLinks();
|
||||
|
||||
//var_dump($product_links); exit;
|
||||
|
||||
$this->importer = $importer;
|
||||
|
||||
$start = $limit = 0;
|
||||
|
||||
if ($action == 'test')
|
||||
{
|
||||
$start = $settings['start'];
|
||||
$limit = 20;
|
||||
}
|
||||
|
||||
if (Tools::getValue('start'))
|
||||
{
|
||||
$start = Tools::getValue('start');
|
||||
}
|
||||
|
||||
if (Tools::getValue('limit'))
|
||||
{
|
||||
$limit = Tools::getValue('limit');
|
||||
}
|
||||
|
||||
if ($start && !$limit)
|
||||
{
|
||||
$limit = count($product_links) - $start;
|
||||
}
|
||||
|
||||
if ($limit)
|
||||
{
|
||||
$product_links = array_slice($product_links, $start, $limit);
|
||||
}
|
||||
return $product_links;
|
||||
}
|
||||
|
||||
function getModuleSettings($file_id = 0)
|
||||
{
|
||||
|
||||
if (!$file_id)
|
||||
{
|
||||
$file_id = Tools::getValue('file_id');
|
||||
}
|
||||
|
||||
$shop = 'default';
|
||||
|
||||
$settings_fields = array('link', 'attribute_group', 'default_brand', 'default_category', 'top_category', 'weight_class_id', 'stock_status_id', 'tax', 'default_option', 'category_path', 'multiplier', 'id_tax_rules_group');
|
||||
|
||||
if (Tools::getValue('import_api_field'))
|
||||
{
|
||||
|
||||
$settings = array(
|
||||
'import_api_field' => Tools::getValue('import_api_field'),
|
||||
'import_api_modification' => Tools::getValue('import_api_modification'),
|
||||
'import_api_combination' => Tools::getValue('import_api_combination'),
|
||||
'import_api_settings' => Tools::getValue('import_api_settings'),
|
||||
'import_api_link' => Tools::getValue('import_api_link'),
|
||||
'import_api_type' => Tools::getValue('import_api_type'),
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
$query_file_settings = Db::getInstance()->executeS("SELECT fs.* FROM " . _DB_PREFIX_ . "ia_file_settings fs WHERE fs.file_id = '" . (int)$file_id . "' LIMIT 1");
|
||||
if ($query_file_settings)
|
||||
{
|
||||
$file_settings = $query_file_settings[0];
|
||||
$filters = array();
|
||||
$replaces = array();
|
||||
if ($file_settings['filter'])
|
||||
{
|
||||
$text_areas = json_decode($file_settings['filter'], true);
|
||||
foreach ($text_areas as $key => $textarea_value)
|
||||
{
|
||||
if ($textarea_value)
|
||||
{
|
||||
$filters[$key] = array_map('trim', explode("\n", $textarea_value));
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($file_settings['replace'])
|
||||
{
|
||||
$text_areas = json_decode($file_settings['replace'], true);
|
||||
foreach ($text_areas as $key => $textarea_value)
|
||||
{
|
||||
$lines = array_map('trim', explode("\n", $textarea_value));
|
||||
foreach ($lines as $line)
|
||||
{
|
||||
if ($line)
|
||||
{
|
||||
$replaces[$key][] = explode('##', $line);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$settings = array(
|
||||
'import_api_field' => json_decode($file_settings['mapping'], true),
|
||||
'import_api_modification' => json_decode($file_settings['modification'], true),
|
||||
'import_api_combination' => json_decode($file_settings['split'], true),
|
||||
'import_api_filter' => $filters,
|
||||
'import_api_replace' => $replaces,
|
||||
'import_api_filter_options' => json_decode($file_settings['filter_options'], true),
|
||||
'import_api_settings' => json_decode($file_settings['settings'], true),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($settings['import_api_field']['unique']))
|
||||
{
|
||||
$settings['unique_field'] = html_entity_decode($settings['import_api_field']['unique'], ENT_QUOTES, 'UTF-8');
|
||||
}
|
||||
else
|
||||
{
|
||||
$json['error'] = 'you need to set unique field';
|
||||
$this->ajaxDie(Tools::jsonEncode($json));
|
||||
}
|
||||
|
||||
if (Tools::getValue('start'))
|
||||
{
|
||||
$settings['start'] = Tools::getValue('start');
|
||||
}
|
||||
else
|
||||
{
|
||||
$settings['start'] = 0;
|
||||
}
|
||||
|
||||
if ($settings['import_api_settings']['top_category'])
|
||||
{
|
||||
$settings['top_category_id'] = $this->creator->getCategoryId($settings['import_api_settings']['top_category']);
|
||||
}
|
||||
else
|
||||
{
|
||||
$settings['top_category_id'] = Configuration::get('PS_HOME_CATEGORY');
|
||||
}
|
||||
|
||||
if ($settings['import_api_settings']['default_category'])
|
||||
{
|
||||
$settings['default_category_id'] = $this->creator->getCategoryId($settings['import_api_settings']['default_category']);
|
||||
}
|
||||
else
|
||||
{
|
||||
$settings['default_category_id'] = 0;
|
||||
}
|
||||
|
||||
if ($settings['import_api_settings']['default_brand'])
|
||||
{
|
||||
$settings['default_manufacturer_id'] = $this->creator->getManufacturerId($settings['import_api_settings']['default_brand']);
|
||||
}
|
||||
else
|
||||
{
|
||||
$settings['default_manufacturer_id'] = 0;
|
||||
}
|
||||
|
||||
$settings['id_tax_rules_group'] = isset($settings['import_api_settings']['id_tax_rules_group']) ? $settings['import_api_settings']['id_tax_rules_group'] : -1;
|
||||
|
||||
$settings['unique_equivalent'] = 'name';
|
||||
$settings['table_equivalent'] = 'product_lang';
|
||||
if (isset($settings['import_api_settings']['synchronize_field']) && $settings['import_api_settings']['synchronize_field'] != 'automatic')
|
||||
{
|
||||
$settings['unique_equivalent'] = $settings['import_api_settings']['synchronize_field'];
|
||||
}
|
||||
else
|
||||
{
|
||||
$possible_eq = ['reference', 'sku', 'ean13', 'upc'];
|
||||
|
||||
foreach ($possible_eq as $f)
|
||||
{
|
||||
if (!empty($settings['import_api_field'][$f]) && $settings['import_api_field'][$f] == $settings['import_api_field']['unique'])
|
||||
{
|
||||
$settings['unique_equivalent'] = $f;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($settings['unique_equivalent'] != 'name')
|
||||
{
|
||||
$settings['table_equivalent'] = 'product';
|
||||
}
|
||||
|
||||
$this->settings = $settings;
|
||||
|
||||
return $settings;
|
||||
}
|
||||
|
||||
function deleteProducts($file_id)
|
||||
{
|
||||
$query_file = Db::getInstance()->executeS("SELECT * FROM " . _DB_PREFIX_ . "ia_files WHERE file_id = '" . (int)$file_id . "' LIMIT 1");
|
||||
if (empty($query_file))
|
||||
{
|
||||
$json['notice'] = 'File not found';
|
||||
$this->ajaxDie(Tools::jsonEncode($json));
|
||||
exit;
|
||||
}
|
||||
else
|
||||
{
|
||||
$file = $query_file[0];
|
||||
}
|
||||
if ($file['mask'] . $file['date_added'] != Tools::getValue('token'))
|
||||
{
|
||||
$json['notice'] = 'File not found.....';
|
||||
$this->ajaxDie(Tools::jsonEncode($json));
|
||||
exit;
|
||||
}
|
||||
|
||||
$max_execution_time = 50;
|
||||
|
||||
$products = $this->queue->getProducts($file_id);
|
||||
|
||||
$products_deleted = 0;
|
||||
|
||||
$json['notice'] = '';
|
||||
|
||||
foreach ($products as $product)
|
||||
{
|
||||
$p = new Product($product['product_id']);
|
||||
$p->delete();
|
||||
$this->queue->deleteProduct($product['product_id']);
|
||||
$products_deleted++;
|
||||
|
||||
if ( ( $products_created + $products_updated ) >= self::$update_limit )
|
||||
{
|
||||
$json['notice'] = 'time_out';
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$json['products_deleted'] = $products_deleted;
|
||||
$this->ajaxDie(Tools::jsonEncode($json));
|
||||
|
||||
exit;
|
||||
}
|
||||
|
||||
|
||||
function UR_exists($url)
|
||||
{
|
||||
$headers = @get_headers($url);
|
||||
return stripos($headers[0], "200 OK") ? true : false;
|
||||
}
|
||||
}
|
||||
35
modules/import_api/controllers/front/index.php
Normal file
35
modules/import_api/controllers/front/index.php
Normal file
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
/*
|
||||
* 2007-2016 PrestaShop
|
||||
*
|
||||
* NOTICE OF LICENSE
|
||||
*
|
||||
* This source file is subject to the Academic Free License (AFL 3.0)
|
||||
* that is bundled with this package in the file LICENSE.txt.
|
||||
* It is also available through the world-wide-web at this URL:
|
||||
* http://opensource.org/licenses/afl-3.0.php
|
||||
* If you did not receive a copy of the license and are unable to
|
||||
* obtain it through the world-wide-web, please send an email
|
||||
* to license@prestashop.com so we can send you a copy immediately.
|
||||
*
|
||||
* DISCLAIMER
|
||||
*
|
||||
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
|
||||
* versions in the future. If you wish to customize PrestaShop for your
|
||||
* needs please refer to http://www.prestashop.com for more information.
|
||||
*
|
||||
* @author PrestaShop SA <contact@prestashop.com>
|
||||
* @copyright 2007-2016 PrestaShop SA
|
||||
* @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0)
|
||||
* International Registered Trademark & Property of PrestaShop SA
|
||||
*/
|
||||
|
||||
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;
|
||||
35
modules/import_api/controllers/index.php
Normal file
35
modules/import_api/controllers/index.php
Normal file
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
/*
|
||||
* 2007-2016 PrestaShop
|
||||
*
|
||||
* NOTICE OF LICENSE
|
||||
*
|
||||
* This source file is subject to the Academic Free License (AFL 3.0)
|
||||
* that is bundled with this package in the file LICENSE.txt.
|
||||
* It is also available through the world-wide-web at this URL:
|
||||
* http://opensource.org/licenses/afl-3.0.php
|
||||
* If you did not receive a copy of the license and are unable to
|
||||
* obtain it through the world-wide-web, please send an email
|
||||
* to license@prestashop.com so we can send you a copy immediately.
|
||||
*
|
||||
* DISCLAIMER
|
||||
*
|
||||
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
|
||||
* versions in the future. If you wish to customize PrestaShop for your
|
||||
* needs please refer to http://www.prestashop.com for more information.
|
||||
*
|
||||
* @author PrestaShop SA <contact@prestashop.com>
|
||||
* @copyright 2007-2016 PrestaShop SA
|
||||
* @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0)
|
||||
* International Registered Trademark & Property of PrestaShop SA
|
||||
*/
|
||||
|
||||
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;
|
||||
102
modules/import_api/import_api.php
Normal file
102
modules/import_api/import_api.php
Normal file
@@ -0,0 +1,102 @@
|
||||
<?php
|
||||
/**
|
||||
* NOTICE OF LICENSE
|
||||
* With the purchase or the installation of the software in your application
|
||||
* you accept the license agreement.
|
||||
*
|
||||
* You can not resell and redistribute this file.
|
||||
*
|
||||
* @author Dalibor Stojcevski <dal_sto@yahoo.com>
|
||||
* @copyright 2019 Dalibor Stojcevski
|
||||
* @license Dalibor Stojcevski
|
||||
*/
|
||||
|
||||
if (!defined('_PS_VERSION_')) {
|
||||
exit;
|
||||
}
|
||||
|
||||
class import_api extends Module
|
||||
{
|
||||
protected $config_form = false;
|
||||
|
||||
protected $_postErrors = array();
|
||||
|
||||
protected $fmr_fields;
|
||||
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->name = 'import_api';
|
||||
$this->tab = 'front_office_features';
|
||||
$this->version = '3.1.5.9';
|
||||
$this->author = 'Dalibor Stojcevski';
|
||||
$this->need_instance = 1;
|
||||
$this->bootstrap = true;
|
||||
$this->module_key = '3711c016ea39f2f2aa38850e48aa7455';
|
||||
parent::__construct();
|
||||
$this->displayName = $this->l('Import Api');
|
||||
$this->description = $this->l('Import and update products from external source');
|
||||
$this->ps_versions_compliancy = array('min' => '1.6', 'max' => _PS_VERSION_);
|
||||
|
||||
$this->frm_fields = ['unique', 'reference', 'name', 'description', 'price', 'quantity', 'images', 'cover', 'brand', 'category', 'category_parent', 'ean13', 'upc', 'condition', 'weight', 'feature', 'feature_value'];
|
||||
$this->frm_settings = array('top_category' => '', 'default_category' => '', 'default_brand' => '', 'price_multiplier' => '', 'category_path' => 0);
|
||||
}
|
||||
|
||||
public function install()
|
||||
{
|
||||
$class = 'AdminImport_Api';
|
||||
$tab = new Tab();
|
||||
$tab->class_name = $class;
|
||||
$tab->module = $this->name;
|
||||
$tab->id_parent = 0;
|
||||
$langs = Language::getLanguages(false);
|
||||
foreach ($langs as $l) {
|
||||
$tab->name[$l['id_lang']] = $this->l('Import Products');
|
||||
}
|
||||
$tab->save();
|
||||
return $this->installDb() && parent::install();
|
||||
}
|
||||
|
||||
public function uninstall()
|
||||
{
|
||||
return parent::uninstall();
|
||||
}
|
||||
|
||||
public function installDb()
|
||||
{
|
||||
$return = true;
|
||||
require_once(_PS_MODULE_DIR_ . 'import_api/sql_install.php');
|
||||
|
||||
foreach ($sql as $s) {
|
||||
Db::getInstance()->execute($s);
|
||||
}
|
||||
|
||||
$res = Db::getInstance()->executeS("SHOW columns FROM `"._DB_PREFIX_."ia_files` LIKE 'status'");
|
||||
if (!$res) {
|
||||
Db::getInstance()->execute('ALTER TABLE `'._DB_PREFIX_.'ia_files` ADD `status` SMALLINT(2) NOT NULL DEFAULT \'1\'');
|
||||
}
|
||||
|
||||
$res_1 = Db::getInstance()->executeS("SHOW columns FROM `"._DB_PREFIX_."ia_file_settings` LIKE 'replace' ");
|
||||
if (!$res_1) {
|
||||
Db::getInstance()->execute('ALTER TABLE `'._DB_PREFIX_.'ia_file_settings` ADD `replace` text NOT NULL');
|
||||
}
|
||||
|
||||
$res_2 = Db::getInstance()->executeS("SHOW columns FROM `"._DB_PREFIX_."ia_file_settings` LIKE 'filter' ");
|
||||
if (!$res_2) {
|
||||
Db::getInstance()->execute('ALTER TABLE `'._DB_PREFIX_.'ia_file_settings` ADD `filter` text NOT NULL');
|
||||
}
|
||||
|
||||
$res_3 = Db::getInstance()->executeS("SHOW columns FROM `"._DB_PREFIX_."ia_file_settings` LIKE 'filter_options' ");
|
||||
|
||||
if (!$res_3) {
|
||||
Db::getInstance()->execute('ALTER TABLE `'._DB_PREFIX_.'ia_file_settings` ADD `filter_options` text NOT NULL');
|
||||
}
|
||||
return $return;
|
||||
}
|
||||
|
||||
public function getContent()
|
||||
{
|
||||
Tools::redirectAdmin($this->context->link->getAdminLink('AdminImport_Api'));
|
||||
}
|
||||
|
||||
}
|
||||
35
modules/import_api/index.php
Normal file
35
modules/import_api/index.php
Normal file
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
/**
|
||||
* 2007-2018 PrestaShop
|
||||
*
|
||||
* NOTICE OF LICENSE
|
||||
*
|
||||
* This source file is subject to the Academic Free License (AFL 3.0)
|
||||
* that is bundled with this package in the file LICENSE.txt.
|
||||
* It is also available through the world-wide-web at this URL:
|
||||
* http://opensource.org/licenses/afl-3.0.php
|
||||
* If you did not receive a copy of the license and are unable to
|
||||
* obtain it through the world-wide-web, please send an email
|
||||
* to license@prestashop.com so we can send you a copy immediately.
|
||||
*
|
||||
* DISCLAIMER
|
||||
*
|
||||
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
|
||||
* versions in the future. If you wish to customize PrestaShop for your
|
||||
* needs please refer to http://www.prestashop.com for more information.
|
||||
*
|
||||
* @author PrestaShop SA <contact@prestashop.com>
|
||||
* @copyright 2007-2018 PrestaShop SA
|
||||
* @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0)
|
||||
* International Registered Trademark & Property of PrestaShop SA
|
||||
*/
|
||||
|
||||
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;
|
||||
1224
modules/import_api/lib/SimpleXLS.php
Normal file
1224
modules/import_api/lib/SimpleXLS.php
Normal file
File diff suppressed because it is too large
Load Diff
1056
modules/import_api/lib/SimpleXLSX.php
Normal file
1056
modules/import_api/lib/SimpleXLSX.php
Normal file
File diff suppressed because it is too large
Load Diff
BIN
modules/import_api/logo.png
Normal file
BIN
modules/import_api/logo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 548 B |
90
modules/import_api/sql_install.php
Normal file
90
modules/import_api/sql_install.php
Normal file
@@ -0,0 +1,90 @@
|
||||
<?php
|
||||
/**
|
||||
* NOTICE OF LICENSE
|
||||
* With the purchase or the installation of the software in your application
|
||||
* you accept the license agreement.
|
||||
*
|
||||
* You can not resell and redistribute this file.
|
||||
*
|
||||
* @author Dalibor Stojcevski <dal_sto@yahoo.com>
|
||||
* @copyright 2019 Dalibor Stojcevski
|
||||
* @license Dalibor Stojcevski
|
||||
*/
|
||||
|
||||
//$sql = array();
|
||||
$sql[_DB_PREFIX_.'ia_files'] = 'CREATE TABLE IF NOT EXISTS `'._DB_PREFIX_.'ia_files` (
|
||||
`file_id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`name` varchar(200) NOT NULL,
|
||||
`link` varchar(300) NOT NULL,
|
||||
`shop` varchar(200) NOT NULL,
|
||||
`source` varchar(10) NOT NULL,
|
||||
`headers` smallint(2) NOT NULL DEFAULT \'0\',
|
||||
`status` smallint(2) NOT NULL DEFAULT \'1\',
|
||||
|
||||
`delimiter` varchar(16) NOT NULL,
|
||||
`mime_type` varchar(100) NOT NULL,
|
||||
`fields` text NOT NULL,
|
||||
`date_added` int(11) NOT NULL,
|
||||
`mask` varchar(30) NOT NULL,
|
||||
`post` text,
|
||||
`date_edited` int(11) NOT NULL DEFAULT \'0\',
|
||||
PRIMARY KEY (`file_id`)
|
||||
) ENGINE='._MYSQL_ENGINE_.' DEFAULT CHARSET=utf8;';
|
||||
|
||||
$sql[_DB_PREFIX_.'ia_file_settings'] = 'CREATE TABLE IF NOT EXISTS `'._DB_PREFIX_.'ia_file_settings` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`mapping` text NOT NULL,
|
||||
`modification` text NOT NULL,
|
||||
`split` text NOT NULL,
|
||||
`filter` text NOT NULL,
|
||||
`filter_options` text NOT NULL,
|
||||
`replace` text NOT NULL,
|
||||
`settings` text NOT NULL,
|
||||
`shop` varchar(300) NOT NULL,
|
||||
`file_id` int(11) NOT NULL,
|
||||
`date_updated` int(11) NOT NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE='._MYSQL_ENGINE_.' DEFAULT CHARSET=utf8;';
|
||||
|
||||
$sql[_DB_PREFIX_.'ia_temp'] = 'CREATE TABLE IF NOT EXISTS `'._DB_PREFIX_.'ia_temp` (
|
||||
`product_id` BigInt(20) NOT NULL AUTO_INCREMENT,
|
||||
`id` varchar(30) NOT NULL,
|
||||
`source_id` varchar(200) NOT NULL,
|
||||
`indx` varchar(300) NOT NULL,
|
||||
`shop` varchar(64) NOT NULL,
|
||||
`product` text NOT NULL,
|
||||
`date_added` int(11) NOT NULL,
|
||||
`queue_id` int(11) NOT NULL,
|
||||
`file_id` int(11) NOT NULL DEFAULT \'0\',
|
||||
PRIMARY KEY (`product_id`)
|
||||
) ENGINE='._MYSQL_ENGINE_.' DEFAULT CHARSET=utf8;';
|
||||
|
||||
$sql[_DB_PREFIX_.'ia_queues'] = 'CREATE TABLE IF NOT EXISTS `'._DB_PREFIX_.'ia_queues` (
|
||||
`queue_id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`total` int(11) NOT NULL,
|
||||
`date_added` int(11) NOT NULL,
|
||||
`shop` varchar(300) NOT NULL,
|
||||
`status` int(11) NOT NULL DEFAULT \'0\',
|
||||
`date_processed` int(11) NOT NULL DEFAULT \'0\',
|
||||
`products_created` int(11) NOT NULL DEFAULT \'0\',
|
||||
`products_updated` int(11) NOT NULL DEFAULT \'0\',
|
||||
`products_failed` int(11) NOT NULL DEFAULT \'0\',
|
||||
`source` varchar(10) NOT NULL DEFAULT \'n\',
|
||||
`wait_time` int(11) NOT NULL DEFAULT \'0\',
|
||||
`file_id` int(11) NOT NULL DEFAULT \'0\',
|
||||
PRIMARY KEY (`queue_id`)
|
||||
) ENGINE='._MYSQL_ENGINE_.' DEFAULT CHARSET=utf8;';
|
||||
|
||||
$sql[_DB_PREFIX_.'ia_products'] = 'CREATE TABLE IF NOT EXISTS `'._DB_PREFIX_.'ia_products` (
|
||||
`product_id`int(11) NOT NULL,
|
||||
`indx` varchar(300) NOT NULL,
|
||||
`shop` varchar(64) NOT NULL,
|
||||
`product` text NOT NULL,
|
||||
`date_edited` int(11) NOT NULL,
|
||||
`source` varchar(30) NOT NULL,
|
||||
`date_added` int(11) NOT NULL DEFAULT \'0\',
|
||||
`file_id` int(11) NOT NULL DEFAULT \'0\',
|
||||
`queue_id` int(11) NOT NULL DEFAULT \'0\',
|
||||
`missing` int(11) NOT NULL DEFAULT \'0\',
|
||||
PRIMARY KEY (`product_id`)
|
||||
) ENGINE='._MYSQL_ENGINE_.' DEFAULT CHARSET=utf8;';
|
||||
0
modules/import_api/translations/cs.php
Normal file
0
modules/import_api/translations/cs.php
Normal file
0
modules/import_api/translations/pl.php
Normal file
0
modules/import_api/translations/pl.php
Normal file
206
modules/import_api/views/css/dataTables.bootstrap4.css
Normal file
206
modules/import_api/views/css/dataTables.bootstrap4.css
Normal file
@@ -0,0 +1,206 @@
|
||||
table.dataTable {
|
||||
clear: both;
|
||||
margin-top: 6px !important;
|
||||
margin-bottom: 6px !important;
|
||||
max-width: none !important;
|
||||
border-collapse: separate !important;
|
||||
border-spacing: 0;
|
||||
}
|
||||
table.dataTable td,
|
||||
table.dataTable th {
|
||||
-webkit-box-sizing: content-box;
|
||||
box-sizing: content-box;
|
||||
}
|
||||
table.dataTable td.dataTables_empty,
|
||||
table.dataTable th.dataTables_empty {
|
||||
text-align: center;
|
||||
}
|
||||
table.dataTable.nowrap th,
|
||||
table.dataTable.nowrap td {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
div.dataTables_wrapper div.dataTables_length label {
|
||||
font-weight: normal;
|
||||
text-align: left;
|
||||
white-space: nowrap;
|
||||
}
|
||||
div.dataTables_wrapper div.dataTables_length select {
|
||||
width: auto;
|
||||
display: inline-block;
|
||||
}
|
||||
div.dataTables_wrapper div.dataTables_filter {
|
||||
text-align: right;
|
||||
}
|
||||
div.dataTables_wrapper div.dataTables_filter label {
|
||||
font-weight: normal;
|
||||
white-space: nowrap;
|
||||
text-align: left;
|
||||
}
|
||||
div.dataTables_wrapper div.dataTables_filter input {
|
||||
margin-left: 0.5em;
|
||||
display: inline-block;
|
||||
width: auto;
|
||||
}
|
||||
div.dataTables_wrapper div.dataTables_info {
|
||||
padding-top: 0.85em;
|
||||
white-space: nowrap;
|
||||
}
|
||||
div.dataTables_wrapper div.dataTables_paginate {
|
||||
margin: 0;
|
||||
white-space: nowrap;
|
||||
text-align: right;
|
||||
}
|
||||
div.dataTables_wrapper div.dataTables_paginate ul.pagination {
|
||||
margin: 2px 0;
|
||||
white-space: nowrap;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
div.dataTables_wrapper div.dataTables_processing {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
width: 200px;
|
||||
margin-left: -100px;
|
||||
margin-top: -26px;
|
||||
text-align: center;
|
||||
padding: 1em 0;
|
||||
}
|
||||
|
||||
table.dataTable thead > tr > th.sorting_asc, table.dataTable thead > tr > th.sorting_desc, table.dataTable thead > tr > th.sorting,
|
||||
table.dataTable thead > tr > td.sorting_asc,
|
||||
table.dataTable thead > tr > td.sorting_desc,
|
||||
table.dataTable thead > tr > td.sorting {
|
||||
padding-right: 30px;
|
||||
}
|
||||
table.dataTable thead > tr > th:active,
|
||||
table.dataTable thead > tr > td:active {
|
||||
outline: none;
|
||||
}
|
||||
table.dataTable thead .sorting,
|
||||
table.dataTable thead .sorting_asc,
|
||||
table.dataTable thead .sorting_desc,
|
||||
table.dataTable thead .sorting_asc_disabled,
|
||||
table.dataTable thead .sorting_desc_disabled {
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
}
|
||||
table.dataTable thead .sorting:before, table.dataTable thead .sorting:after,
|
||||
table.dataTable thead .sorting_asc:before,
|
||||
table.dataTable thead .sorting_asc:after,
|
||||
table.dataTable thead .sorting_desc:before,
|
||||
table.dataTable thead .sorting_desc:after,
|
||||
table.dataTable thead .sorting_asc_disabled:before,
|
||||
table.dataTable thead .sorting_asc_disabled:after,
|
||||
table.dataTable thead .sorting_desc_disabled:before,
|
||||
table.dataTable thead .sorting_desc_disabled:after {
|
||||
position: absolute;
|
||||
bottom: 0.9em;
|
||||
display: block;
|
||||
opacity: 0.3;
|
||||
}
|
||||
table.dataTable thead .sorting:before,
|
||||
table.dataTable thead .sorting_asc:before,
|
||||
table.dataTable thead .sorting_desc:before,
|
||||
table.dataTable thead .sorting_asc_disabled:before,
|
||||
table.dataTable thead .sorting_desc_disabled:before {
|
||||
right: 1em;
|
||||
content: "\2191";
|
||||
}
|
||||
table.dataTable thead .sorting:after,
|
||||
table.dataTable thead .sorting_asc:after,
|
||||
table.dataTable thead .sorting_desc:after,
|
||||
table.dataTable thead .sorting_asc_disabled:after,
|
||||
table.dataTable thead .sorting_desc_disabled:after {
|
||||
right: 0.5em;
|
||||
content: "\2193";
|
||||
}
|
||||
table.dataTable thead .sorting_asc:before,
|
||||
table.dataTable thead .sorting_desc:after {
|
||||
opacity: 1;
|
||||
}
|
||||
table.dataTable thead .sorting_asc_disabled:before,
|
||||
table.dataTable thead .sorting_desc_disabled:after {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
div.dataTables_scrollHead table.dataTable {
|
||||
margin-bottom: 0 !important;
|
||||
}
|
||||
|
||||
div.dataTables_scrollBody table {
|
||||
border-top: none;
|
||||
margin-top: 0 !important;
|
||||
margin-bottom: 0 !important;
|
||||
}
|
||||
div.dataTables_scrollBody table thead .sorting:before,
|
||||
div.dataTables_scrollBody table thead .sorting_asc:before,
|
||||
div.dataTables_scrollBody table thead .sorting_desc:before,
|
||||
div.dataTables_scrollBody table thead .sorting:after,
|
||||
div.dataTables_scrollBody table thead .sorting_asc:after,
|
||||
div.dataTables_scrollBody table thead .sorting_desc:after {
|
||||
display: none;
|
||||
}
|
||||
div.dataTables_scrollBody table tbody tr:first-child th,
|
||||
div.dataTables_scrollBody table tbody tr:first-child td {
|
||||
border-top: none;
|
||||
}
|
||||
|
||||
div.dataTables_scrollFoot > .dataTables_scrollFootInner {
|
||||
box-sizing: content-box;
|
||||
}
|
||||
div.dataTables_scrollFoot > .dataTables_scrollFootInner > table {
|
||||
margin-top: 0 !important;
|
||||
border-top: none;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 767px) {
|
||||
div.dataTables_wrapper div.dataTables_length,
|
||||
div.dataTables_wrapper div.dataTables_filter,
|
||||
div.dataTables_wrapper div.dataTables_info,
|
||||
div.dataTables_wrapper div.dataTables_paginate {
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
table.dataTable.table-sm > thead > tr > th {
|
||||
padding-right: 20px;
|
||||
}
|
||||
table.dataTable.table-sm .sorting:before,
|
||||
table.dataTable.table-sm .sorting_asc:before,
|
||||
table.dataTable.table-sm .sorting_desc:before {
|
||||
top: 5px;
|
||||
right: 0.85em;
|
||||
}
|
||||
table.dataTable.table-sm .sorting:after,
|
||||
table.dataTable.table-sm .sorting_asc:after,
|
||||
table.dataTable.table-sm .sorting_desc:after {
|
||||
top: 5px;
|
||||
}
|
||||
|
||||
table.table-bordered.dataTable th,
|
||||
table.table-bordered.dataTable td {
|
||||
border-left-width: 0;
|
||||
}
|
||||
table.table-bordered.dataTable th:last-child, table.table-bordered.dataTable th:last-child,
|
||||
table.table-bordered.dataTable td:last-child,
|
||||
table.table-bordered.dataTable td:last-child {
|
||||
border-right-width: 0;
|
||||
}
|
||||
table.table-bordered.dataTable tbody th,
|
||||
table.table-bordered.dataTable tbody td {
|
||||
border-bottom-width: 0;
|
||||
}
|
||||
|
||||
div.dataTables_scrollHead table.table-bordered {
|
||||
border-bottom-width: 0;
|
||||
}
|
||||
|
||||
div.table-responsive > div.dataTables_wrapper > div.row {
|
||||
margin: 0;
|
||||
}
|
||||
div.table-responsive > div.dataTables_wrapper > div.row > div[class^="col-"]:first-child {
|
||||
padding-left: 0;
|
||||
}
|
||||
div.table-responsive > div.dataTables_wrapper > div.row > div[class^="col-"]:last-child {
|
||||
padding-right: 0;
|
||||
}
|
||||
35
modules/import_api/views/index.php
Normal file
35
modules/import_api/views/index.php
Normal file
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
/**
|
||||
* 2007-2018 PrestaShop
|
||||
*
|
||||
* NOTICE OF LICENSE
|
||||
*
|
||||
* This source file is subject to the Academic Free License (AFL 3.0)
|
||||
* that is bundled with this package in the file LICENSE.txt.
|
||||
* It is also available through the world-wide-web at this URL:
|
||||
* http://opensource.org/licenses/afl-3.0.php
|
||||
* If you did not receive a copy of the license and are unable to
|
||||
* obtain it through the world-wide-web, please send an email
|
||||
* to license@prestashop.com so we can send you a copy immediately.
|
||||
*
|
||||
* DISCLAIMER
|
||||
*
|
||||
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
|
||||
* versions in the future. If you wish to customize PrestaShop for your
|
||||
* needs please refer to http://www.prestashop.com for more information.
|
||||
*
|
||||
* @author PrestaShop SA <contact@prestashop.com>
|
||||
* @copyright 2007-2018 PrestaShop SA
|
||||
* @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0)
|
||||
* International Registered Trademark & Property of PrestaShop SA
|
||||
*/
|
||||
|
||||
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;
|
||||
27
modules/import_api/views/js/back.js
Normal file
27
modules/import_api/views/js/back.js
Normal file
@@ -0,0 +1,27 @@
|
||||
/**
|
||||
* 2007-2018 PrestaShop
|
||||
*
|
||||
* NOTICE OF LICENSE
|
||||
*
|
||||
* This source file is subject to the Academic Free License (AFL 3.0)
|
||||
* that is bundled with this package in the file LICENSE.txt.
|
||||
* It is also available through the world-wide-web at this URL:
|
||||
* http://opensource.org/licenses/afl-3.0.php
|
||||
* If you did not receive a copy of the license and are unable to
|
||||
* obtain it through the world-wide-web, please send an email
|
||||
* to license@prestashop.com so we can send you a copy immediately.
|
||||
*
|
||||
* DISCLAIMER
|
||||
*
|
||||
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
|
||||
* versions in the future. If you wish to customize PrestaShop for your
|
||||
* needs please refer to http://www.prestashop.com for more information.
|
||||
*
|
||||
* @author PrestaShop SA <contact@prestashop.com>
|
||||
* @copyright 2007-2018 PrestaShop SA
|
||||
* @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0)
|
||||
* International Registered Trademark & Property of PrestaShop SA
|
||||
*
|
||||
* Don't forget to prefix your containers with your own identifier
|
||||
* to avoid any conflicts with others containers.
|
||||
*/
|
||||
184
modules/import_api/views/js/dataTables.bootstrap4.js
Normal file
184
modules/import_api/views/js/dataTables.bootstrap4.js
Normal file
@@ -0,0 +1,184 @@
|
||||
/*! DataTables Bootstrap 4 integration
|
||||
* ©2011-2017 SpryMedia Ltd - datatables.net/license
|
||||
*/
|
||||
|
||||
/**
|
||||
* DataTables integration for Bootstrap 4. This requires Bootstrap 4 and
|
||||
* DataTables 1.10 or newer.
|
||||
*
|
||||
* This file sets the defaults and adds options to DataTables to style its
|
||||
* controls using Bootstrap. See http://datatables.net/manual/styling/bootstrap
|
||||
* for further information.
|
||||
*/
|
||||
(function( factory ){
|
||||
if ( typeof define === 'function' && define.amd ) {
|
||||
// AMD
|
||||
define( ['jquery', 'datatables.net'], function ( $ ) {
|
||||
return factory( $, window, document );
|
||||
} );
|
||||
}
|
||||
else if ( typeof exports === 'object' ) {
|
||||
// CommonJS
|
||||
module.exports = function (root, $) {
|
||||
if ( ! root ) {
|
||||
root = window;
|
||||
}
|
||||
|
||||
if ( ! $ || ! $.fn.dataTable ) {
|
||||
// Require DataTables, which attaches to jQuery, including
|
||||
// jQuery if needed and have a $ property so we can access the
|
||||
// jQuery object that is used
|
||||
$ = require('datatables.net')(root, $).$;
|
||||
}
|
||||
|
||||
return factory( $, root, root.document );
|
||||
};
|
||||
}
|
||||
else {
|
||||
// Browser
|
||||
factory( jQuery, window, document );
|
||||
}
|
||||
}(function( $, window, document, undefined ) {
|
||||
'use strict';
|
||||
var DataTable = $.fn.dataTable;
|
||||
|
||||
|
||||
/* Set the defaults for DataTables initialisation */
|
||||
$.extend( true, DataTable.defaults, {
|
||||
dom:
|
||||
"<'row'<'col-sm-12 col-md-6'l><'col-sm-12 col-md-6'f>>" +
|
||||
"<'row'<'col-sm-12'tr>>" +
|
||||
"<'row'<'col-sm-12 col-md-5'i><'col-sm-12 col-md-7'p>>",
|
||||
renderer: 'bootstrap'
|
||||
} );
|
||||
|
||||
|
||||
/* Default class modification */
|
||||
$.extend( DataTable.ext.classes, {
|
||||
sWrapper: "dataTables_wrapper dt-bootstrap4",
|
||||
sFilterInput: "form-control form-control-sm",
|
||||
sLengthSelect: "custom-select custom-select-sm form-control form-control-sm",
|
||||
sProcessing: "dataTables_processing card",
|
||||
sPageButton: "paginate_button page-item"
|
||||
} );
|
||||
|
||||
|
||||
/* Bootstrap paging button renderer */
|
||||
DataTable.ext.renderer.pageButton.bootstrap = function ( settings, host, idx, buttons, page, pages ) {
|
||||
var api = new DataTable.Api( settings );
|
||||
var classes = settings.oClasses;
|
||||
var lang = settings.oLanguage.oPaginate;
|
||||
var aria = settings.oLanguage.oAria.paginate || {};
|
||||
var btnDisplay, btnClass, counter=0;
|
||||
|
||||
var attach = function( container, buttons ) {
|
||||
var i, ien, node, button;
|
||||
var clickHandler = function ( e ) {
|
||||
e.preventDefault();
|
||||
if ( !$(e.currentTarget).hasClass('disabled') && api.page() != e.data.action ) {
|
||||
api.page( e.data.action ).draw( 'page' );
|
||||
}
|
||||
};
|
||||
|
||||
for ( i=0, ien=buttons.length ; i<ien ; i++ ) {
|
||||
button = buttons[i];
|
||||
|
||||
if ( $.isArray( button ) ) {
|
||||
attach( container, button );
|
||||
}
|
||||
else {
|
||||
btnDisplay = '';
|
||||
btnClass = '';
|
||||
|
||||
switch ( button ) {
|
||||
case 'ellipsis':
|
||||
btnDisplay = '…';
|
||||
btnClass = 'disabled';
|
||||
break;
|
||||
|
||||
case 'first':
|
||||
btnDisplay = lang.sFirst;
|
||||
btnClass = button + (page > 0 ?
|
||||
'' : ' disabled');
|
||||
break;
|
||||
|
||||
case 'previous':
|
||||
btnDisplay = lang.sPrevious;
|
||||
btnClass = button + (page > 0 ?
|
||||
'' : ' disabled');
|
||||
break;
|
||||
|
||||
case 'next':
|
||||
btnDisplay = lang.sNext;
|
||||
btnClass = button + (page < pages-1 ?
|
||||
'' : ' disabled');
|
||||
break;
|
||||
|
||||
case 'last':
|
||||
btnDisplay = lang.sLast;
|
||||
btnClass = button + (page < pages-1 ?
|
||||
'' : ' disabled');
|
||||
break;
|
||||
|
||||
default:
|
||||
btnDisplay = button + 1;
|
||||
btnClass = page === button ?
|
||||
'active' : '';
|
||||
break;
|
||||
}
|
||||
|
||||
if ( btnDisplay ) {
|
||||
node = $('<li>', {
|
||||
'class': classes.sPageButton+' '+btnClass,
|
||||
'id': idx === 0 && typeof button === 'string' ?
|
||||
settings.sTableId +'_'+ button :
|
||||
null
|
||||
} )
|
||||
.append( $('<a>', {
|
||||
'href': '#',
|
||||
'aria-controls': settings.sTableId,
|
||||
'aria-label': aria[ button ],
|
||||
'data-dt-idx': counter,
|
||||
'tabindex': settings.iTabIndex,
|
||||
'class': 'page-link'
|
||||
} )
|
||||
.html( btnDisplay )
|
||||
)
|
||||
.appendTo( container );
|
||||
|
||||
settings.oApi._fnBindAction(
|
||||
node, {action: button}, clickHandler
|
||||
);
|
||||
|
||||
counter++;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// IE9 throws an 'unknown error' if document.activeElement is used
|
||||
// inside an iframe or frame.
|
||||
var activeEl;
|
||||
|
||||
try {
|
||||
// Because this approach is destroying and recreating the paging
|
||||
// elements, focus is lost on the select button which is bad for
|
||||
// accessibility. So we want to restore focus once the draw has
|
||||
// completed
|
||||
activeEl = $(host).find(document.activeElement).data('dt-idx');
|
||||
}
|
||||
catch (e) {}
|
||||
|
||||
attach(
|
||||
$(host).empty().html('<ul class="pagination"/>').children('ul'),
|
||||
buttons
|
||||
);
|
||||
|
||||
if ( activeEl !== undefined ) {
|
||||
$(host).find( '[data-dt-idx='+activeEl+']' ).focus();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
return DataTable;
|
||||
}));
|
||||
15334
modules/import_api/views/js/dataTables.js
Normal file
15334
modules/import_api/views/js/dataTables.js
Normal file
File diff suppressed because it is too large
Load Diff
166
modules/import_api/views/js/dataTables.min.js
vendored
Normal file
166
modules/import_api/views/js/dataTables.min.js
vendored
Normal file
@@ -0,0 +1,166 @@
|
||||
/*!
|
||||
DataTables 1.10.20
|
||||
©2008-2019 SpryMedia Ltd - datatables.net/license
|
||||
*/
|
||||
(function(h){"function"===typeof define&&define.amd?define(["jquery"],function(E){return h(E,window,document)}):"object"===typeof exports?module.exports=function(E,H){E||(E=window);H||(H="undefined"!==typeof window?require("jquery"):require("jquery")(E));return h(H,E,E.document)}:h(jQuery,window,document)})(function(h,E,H,k){function $(a){var b,c,d={};h.each(a,function(e){if((b=e.match(/^([^A-Z]+?)([A-Z])/))&&-1!=="a aa ai ao as b fn i m o s ".indexOf(b[1]+" "))c=e.replace(b[0],b[2].toLowerCase()),
|
||||
d[c]=e,"o"===b[1]&&$(a[e])});a._hungarianMap=d}function J(a,b,c){a._hungarianMap||$(a);var d;h.each(b,function(e){d=a._hungarianMap[e];if(d!==k&&(c||b[d]===k))"o"===d.charAt(0)?(b[d]||(b[d]={}),h.extend(!0,b[d],b[e]),J(a[d],b[d],c)):b[d]=b[e]})}function Ea(a){var b=n.defaults.oLanguage,c=b.sDecimal;c&&Fa(c);if(a){var d=a.sZeroRecords;!a.sEmptyTable&&(d&&"No data available in table"===b.sEmptyTable)&&F(a,a,"sZeroRecords","sEmptyTable");!a.sLoadingRecords&&(d&&"Loading..."===b.sLoadingRecords)&&F(a,
|
||||
a,"sZeroRecords","sLoadingRecords");a.sInfoThousands&&(a.sThousands=a.sInfoThousands);(a=a.sDecimal)&&c!==a&&Fa(a)}}function gb(a){A(a,"ordering","bSort");A(a,"orderMulti","bSortMulti");A(a,"orderClasses","bSortClasses");A(a,"orderCellsTop","bSortCellsTop");A(a,"order","aaSorting");A(a,"orderFixed","aaSortingFixed");A(a,"paging","bPaginate");A(a,"pagingType","sPaginationType");A(a,"pageLength","iDisplayLength");A(a,"searching","bFilter");"boolean"===typeof a.sScrollX&&(a.sScrollX=a.sScrollX?"100%":
|
||||
"");"boolean"===typeof a.scrollX&&(a.scrollX=a.scrollX?"100%":"");if(a=a.aoSearchCols)for(var b=0,c=a.length;b<c;b++)a[b]&&J(n.models.oSearch,a[b])}function hb(a){A(a,"orderable","bSortable");A(a,"orderData","aDataSort");A(a,"orderSequence","asSorting");A(a,"orderDataType","sortDataType");var b=a.aDataSort;"number"===typeof b&&!h.isArray(b)&&(a.aDataSort=[b])}function ib(a){if(!n.__browser){var b={};n.__browser=b;var c=h("<div/>").css({position:"fixed",top:0,left:-1*h(E).scrollLeft(),height:1,width:1,
|
||||
overflow:"hidden"}).append(h("<div/>").css({position:"absolute",top:1,left:1,width:100,overflow:"scroll"}).append(h("<div/>").css({width:"100%",height:10}))).appendTo("body"),d=c.children(),e=d.children();b.barWidth=d[0].offsetWidth-d[0].clientWidth;b.bScrollOversize=100===e[0].offsetWidth&&100!==d[0].clientWidth;b.bScrollbarLeft=1!==Math.round(e.offset().left);b.bBounding=c[0].getBoundingClientRect().width?!0:!1;c.remove()}h.extend(a.oBrowser,n.__browser);a.oScroll.iBarWidth=n.__browser.barWidth}
|
||||
function jb(a,b,c,d,e,f){var g,j=!1;c!==k&&(g=c,j=!0);for(;d!==e;)a.hasOwnProperty(d)&&(g=j?b(g,a[d],d,a):a[d],j=!0,d+=f);return g}function Ga(a,b){var c=n.defaults.column,d=a.aoColumns.length,c=h.extend({},n.models.oColumn,c,{nTh:b?b:H.createElement("th"),sTitle:c.sTitle?c.sTitle:b?b.innerHTML:"",aDataSort:c.aDataSort?c.aDataSort:[d],mData:c.mData?c.mData:d,idx:d});a.aoColumns.push(c);c=a.aoPreSearchCols;c[d]=h.extend({},n.models.oSearch,c[d]);la(a,d,h(b).data())}function la(a,b,c){var b=a.aoColumns[b],
|
||||
d=a.oClasses,e=h(b.nTh);if(!b.sWidthOrig){b.sWidthOrig=e.attr("width")||null;var f=(e.attr("style")||"").match(/width:\s*(\d+[pxem%]+)/);f&&(b.sWidthOrig=f[1])}c!==k&&null!==c&&(hb(c),J(n.defaults.column,c,!0),c.mDataProp!==k&&!c.mData&&(c.mData=c.mDataProp),c.sType&&(b._sManualType=c.sType),c.className&&!c.sClass&&(c.sClass=c.className),c.sClass&&e.addClass(c.sClass),h.extend(b,c),F(b,c,"sWidth","sWidthOrig"),c.iDataSort!==k&&(b.aDataSort=[c.iDataSort]),F(b,c,"aDataSort"));var g=b.mData,j=S(g),i=
|
||||
b.mRender?S(b.mRender):null,c=function(a){return"string"===typeof a&&-1!==a.indexOf("@")};b._bAttrSrc=h.isPlainObject(g)&&(c(g.sort)||c(g.type)||c(g.filter));b._setter=null;b.fnGetData=function(a,b,c){var d=j(a,b,k,c);return i&&b?i(d,b,a,c):d};b.fnSetData=function(a,b,c){return N(g)(a,b,c)};"number"!==typeof g&&(a._rowReadObject=!0);a.oFeatures.bSort||(b.bSortable=!1,e.addClass(d.sSortableNone));a=-1!==h.inArray("asc",b.asSorting);c=-1!==h.inArray("desc",b.asSorting);!b.bSortable||!a&&!c?(b.sSortingClass=
|
||||
d.sSortableNone,b.sSortingClassJUI=""):a&&!c?(b.sSortingClass=d.sSortableAsc,b.sSortingClassJUI=d.sSortJUIAscAllowed):!a&&c?(b.sSortingClass=d.sSortableDesc,b.sSortingClassJUI=d.sSortJUIDescAllowed):(b.sSortingClass=d.sSortable,b.sSortingClassJUI=d.sSortJUI)}function aa(a){if(!1!==a.oFeatures.bAutoWidth){var b=a.aoColumns;Ha(a);for(var c=0,d=b.length;c<d;c++)b[c].nTh.style.width=b[c].sWidth}b=a.oScroll;(""!==b.sY||""!==b.sX)&&ma(a);t(a,null,"column-sizing",[a])}function ba(a,b){var c=na(a,"bVisible");
|
||||
return"number"===typeof c[b]?c[b]:null}function ca(a,b){var c=na(a,"bVisible"),c=h.inArray(b,c);return-1!==c?c:null}function W(a){var b=0;h.each(a.aoColumns,function(a,d){d.bVisible&&"none"!==h(d.nTh).css("display")&&b++});return b}function na(a,b){var c=[];h.map(a.aoColumns,function(a,e){a[b]&&c.push(e)});return c}function Ia(a){var b=a.aoColumns,c=a.aoData,d=n.ext.type.detect,e,f,g,j,i,h,m,q,u;e=0;for(f=b.length;e<f;e++)if(m=b[e],u=[],!m.sType&&m._sManualType)m.sType=m._sManualType;else if(!m.sType){g=
|
||||
0;for(j=d.length;g<j;g++){i=0;for(h=c.length;i<h;i++){u[i]===k&&(u[i]=B(a,i,e,"type"));q=d[g](u[i],a);if(!q&&g!==d.length-1)break;if("html"===q)break}if(q){m.sType=q;break}}m.sType||(m.sType="string")}}function kb(a,b,c,d){var e,f,g,j,i,l,m=a.aoColumns;if(b)for(e=b.length-1;0<=e;e--){l=b[e];var q=l.targets!==k?l.targets:l.aTargets;h.isArray(q)||(q=[q]);f=0;for(g=q.length;f<g;f++)if("number"===typeof q[f]&&0<=q[f]){for(;m.length<=q[f];)Ga(a);d(q[f],l)}else if("number"===typeof q[f]&&0>q[f])d(m.length+
|
||||
q[f],l);else if("string"===typeof q[f]){j=0;for(i=m.length;j<i;j++)("_all"==q[f]||h(m[j].nTh).hasClass(q[f]))&&d(j,l)}}if(c){e=0;for(a=c.length;e<a;e++)d(e,c[e])}}function O(a,b,c,d){var e=a.aoData.length,f=h.extend(!0,{},n.models.oRow,{src:c?"dom":"data",idx:e});f._aData=b;a.aoData.push(f);for(var g=a.aoColumns,j=0,i=g.length;j<i;j++)g[j].sType=null;a.aiDisplayMaster.push(e);b=a.rowIdFn(b);b!==k&&(a.aIds[b]=f);(c||!a.oFeatures.bDeferRender)&&Ja(a,e,c,d);return e}function oa(a,b){var c;b instanceof
|
||||
h||(b=h(b));return b.map(function(b,e){c=Ka(a,e);return O(a,c.data,e,c.cells)})}function B(a,b,c,d){var e=a.iDraw,f=a.aoColumns[c],g=a.aoData[b]._aData,j=f.sDefaultContent,i=f.fnGetData(g,d,{settings:a,row:b,col:c});if(i===k)return a.iDrawError!=e&&null===j&&(K(a,0,"Requested unknown parameter "+("function"==typeof f.mData?"{function}":"'"+f.mData+"'")+" for row "+b+", column "+c,4),a.iDrawError=e),j;if((i===g||null===i)&&null!==j&&d!==k)i=j;else if("function"===typeof i)return i.call(g);return null===
|
||||
i&&"display"==d?"":i}function lb(a,b,c,d){a.aoColumns[c].fnSetData(a.aoData[b]._aData,d,{settings:a,row:b,col:c})}function La(a){return h.map(a.match(/(\\.|[^\.])+/g)||[""],function(a){return a.replace(/\\\./g,".")})}function S(a){if(h.isPlainObject(a)){var b={};h.each(a,function(a,c){c&&(b[a]=S(c))});return function(a,c,f,g){var j=b[c]||b._;return j!==k?j(a,c,f,g):a}}if(null===a)return function(a){return a};if("function"===typeof a)return function(b,c,f,g){return a(b,c,f,g)};if("string"===typeof a&&
|
||||
(-1!==a.indexOf(".")||-1!==a.indexOf("[")||-1!==a.indexOf("("))){var c=function(a,b,f){var g,j;if(""!==f){j=La(f);for(var i=0,l=j.length;i<l;i++){f=j[i].match(da);g=j[i].match(X);if(f){j[i]=j[i].replace(da,"");""!==j[i]&&(a=a[j[i]]);g=[];j.splice(0,i+1);j=j.join(".");if(h.isArray(a)){i=0;for(l=a.length;i<l;i++)g.push(c(a[i],b,j))}a=f[0].substring(1,f[0].length-1);a=""===a?g:g.join(a);break}else if(g){j[i]=j[i].replace(X,"");a=a[j[i]]();continue}if(null===a||a[j[i]]===k)return k;a=a[j[i]]}}return a};
|
||||
return function(b,e){return c(b,e,a)}}return function(b){return b[a]}}function N(a){if(h.isPlainObject(a))return N(a._);if(null===a)return function(){};if("function"===typeof a)return function(b,d,e){a(b,"set",d,e)};if("string"===typeof a&&(-1!==a.indexOf(".")||-1!==a.indexOf("[")||-1!==a.indexOf("("))){var b=function(a,d,e){var e=La(e),f;f=e[e.length-1];for(var g,j,i=0,l=e.length-1;i<l;i++){g=e[i].match(da);j=e[i].match(X);if(g){e[i]=e[i].replace(da,"");a[e[i]]=[];f=e.slice();f.splice(0,i+1);g=f.join(".");
|
||||
if(h.isArray(d)){j=0;for(l=d.length;j<l;j++)f={},b(f,d[j],g),a[e[i]].push(f)}else a[e[i]]=d;return}j&&(e[i]=e[i].replace(X,""),a=a[e[i]](d));if(null===a[e[i]]||a[e[i]]===k)a[e[i]]={};a=a[e[i]]}if(f.match(X))a[f.replace(X,"")](d);else a[f.replace(da,"")]=d};return function(c,d){return b(c,d,a)}}return function(b,d){b[a]=d}}function Ma(a){return C(a.aoData,"_aData")}function pa(a){a.aoData.length=0;a.aiDisplayMaster.length=0;a.aiDisplay.length=0;a.aIds={}}function qa(a,b,c){for(var d=-1,e=0,f=a.length;e<
|
||||
f;e++)a[e]==b?d=e:a[e]>b&&a[e]--; -1!=d&&c===k&&a.splice(d,1)}function ea(a,b,c,d){var e=a.aoData[b],f,g=function(c,d){for(;c.childNodes.length;)c.removeChild(c.firstChild);c.innerHTML=B(a,b,d,"display")};if("dom"===c||(!c||"auto"===c)&&"dom"===e.src)e._aData=Ka(a,e,d,d===k?k:e._aData).data;else{var j=e.anCells;if(j)if(d!==k)g(j[d],d);else{c=0;for(f=j.length;c<f;c++)g(j[c],c)}}e._aSortData=null;e._aFilterData=null;g=a.aoColumns;if(d!==k)g[d].sType=null;else{c=0;for(f=g.length;c<f;c++)g[c].sType=null;
|
||||
Na(a,e)}}function Ka(a,b,c,d){var e=[],f=b.firstChild,g,j,i=0,l,m=a.aoColumns,q=a._rowReadObject,d=d!==k?d:q?{}:[],u=function(a,b){if("string"===typeof a){var c=a.indexOf("@");-1!==c&&(c=a.substring(c+1),N(a)(d,b.getAttribute(c)))}},G=function(a){if(c===k||c===i)j=m[i],l=h.trim(a.innerHTML),j&&j._bAttrSrc?(N(j.mData._)(d,l),u(j.mData.sort,a),u(j.mData.type,a),u(j.mData.filter,a)):q?(j._setter||(j._setter=N(j.mData)),j._setter(d,l)):d[i]=l;i++};if(f)for(;f;){g=f.nodeName.toUpperCase();if("TD"==g||
|
||||
"TH"==g)G(f),e.push(f);f=f.nextSibling}else{e=b.anCells;f=0;for(g=e.length;f<g;f++)G(e[f])}if(b=b.firstChild?b:b.nTr)(b=b.getAttribute("id"))&&N(a.rowId)(d,b);return{data:d,cells:e}}function Ja(a,b,c,d){var e=a.aoData[b],f=e._aData,g=[],j,i,l,m,q,k;if(null===e.nTr){j=c||H.createElement("tr");e.nTr=j;e.anCells=g;j._DT_RowIndex=b;Na(a,e);m=0;for(q=a.aoColumns.length;m<q;m++){l=a.aoColumns[m];i=(k=c?!1:!0)?H.createElement(l.sCellType):d[m];i._DT_CellIndex={row:b,column:m};g.push(i);if(k||(!c||l.mRender||
|
||||
l.mData!==m)&&(!h.isPlainObject(l.mData)||l.mData._!==m+".display"))i.innerHTML=B(a,b,m,"display");l.sClass&&(i.className+=" "+l.sClass);l.bVisible&&!c?j.appendChild(i):!l.bVisible&&c&&i.parentNode.removeChild(i);l.fnCreatedCell&&l.fnCreatedCell.call(a.oInstance,i,B(a,b,m),f,b,m)}t(a,"aoRowCreatedCallback",null,[j,f,b,g])}e.nTr.setAttribute("role","row")}function Na(a,b){var c=b.nTr,d=b._aData;if(c){var e=a.rowIdFn(d);e&&(c.id=e);d.DT_RowClass&&(e=d.DT_RowClass.split(" "),b.__rowc=b.__rowc?ra(b.__rowc.concat(e)):
|
||||
e,h(c).removeClass(b.__rowc.join(" ")).addClass(d.DT_RowClass));d.DT_RowAttr&&h(c).attr(d.DT_RowAttr);d.DT_RowData&&h(c).data(d.DT_RowData)}}function mb(a){var b,c,d,e,f,g=a.nTHead,j=a.nTFoot,i=0===h("th, td",g).length,l=a.oClasses,m=a.aoColumns;i&&(e=h("<tr/>").appendTo(g));b=0;for(c=m.length;b<c;b++)f=m[b],d=h(f.nTh).addClass(f.sClass),i&&d.appendTo(e),a.oFeatures.bSort&&(d.addClass(f.sSortingClass),!1!==f.bSortable&&(d.attr("tabindex",a.iTabIndex).attr("aria-controls",a.sTableId),Oa(a,f.nTh,b))),
|
||||
f.sTitle!=d[0].innerHTML&&d.html(f.sTitle),Pa(a,"header")(a,d,f,l);i&&fa(a.aoHeader,g);h(g).find(">tr").attr("role","row");h(g).find(">tr>th, >tr>td").addClass(l.sHeaderTH);h(j).find(">tr>th, >tr>td").addClass(l.sFooterTH);if(null!==j){a=a.aoFooter[0];b=0;for(c=a.length;b<c;b++)f=m[b],f.nTf=a[b].cell,f.sClass&&h(f.nTf).addClass(f.sClass)}}function ga(a,b,c){var d,e,f,g=[],j=[],i=a.aoColumns.length,l;if(b){c===k&&(c=!1);d=0;for(e=b.length;d<e;d++){g[d]=b[d].slice();g[d].nTr=b[d].nTr;for(f=i-1;0<=f;f--)!a.aoColumns[f].bVisible&&
|
||||
!c&&g[d].splice(f,1);j.push([])}d=0;for(e=g.length;d<e;d++){if(a=g[d].nTr)for(;f=a.firstChild;)a.removeChild(f);f=0;for(b=g[d].length;f<b;f++)if(l=i=1,j[d][f]===k){a.appendChild(g[d][f].cell);for(j[d][f]=1;g[d+i]!==k&&g[d][f].cell==g[d+i][f].cell;)j[d+i][f]=1,i++;for(;g[d][f+l]!==k&&g[d][f].cell==g[d][f+l].cell;){for(c=0;c<i;c++)j[d+c][f+l]=1;l++}h(g[d][f].cell).attr("rowspan",i).attr("colspan",l)}}}}function P(a){var b=t(a,"aoPreDrawCallback","preDraw",[a]);if(-1!==h.inArray(!1,b))D(a,!1);else{var b=
|
||||
[],c=0,d=a.asStripeClasses,e=d.length,f=a.oLanguage,g=a.iInitDisplayStart,j="ssp"==y(a),i=a.aiDisplay;a.bDrawing=!0;g!==k&&-1!==g&&(a._iDisplayStart=j?g:g>=a.fnRecordsDisplay()?0:g,a.iInitDisplayStart=-1);var g=a._iDisplayStart,l=a.fnDisplayEnd();if(a.bDeferLoading)a.bDeferLoading=!1,a.iDraw++,D(a,!1);else if(j){if(!a.bDestroying&&!nb(a))return}else a.iDraw++;if(0!==i.length){f=j?a.aoData.length:l;for(j=j?0:g;j<f;j++){var m=i[j],q=a.aoData[m];null===q.nTr&&Ja(a,m);var u=q.nTr;if(0!==e){var G=d[c%
|
||||
e];q._sRowStripe!=G&&(h(u).removeClass(q._sRowStripe).addClass(G),q._sRowStripe=G)}t(a,"aoRowCallback",null,[u,q._aData,c,j,m]);b.push(u);c++}}else c=f.sZeroRecords,1==a.iDraw&&"ajax"==y(a)?c=f.sLoadingRecords:f.sEmptyTable&&0===a.fnRecordsTotal()&&(c=f.sEmptyTable),b[0]=h("<tr/>",{"class":e?d[0]:""}).append(h("<td />",{valign:"top",colSpan:W(a),"class":a.oClasses.sRowEmpty}).html(c))[0];t(a,"aoHeaderCallback","header",[h(a.nTHead).children("tr")[0],Ma(a),g,l,i]);t(a,"aoFooterCallback","footer",[h(a.nTFoot).children("tr")[0],
|
||||
Ma(a),g,l,i]);d=h(a.nTBody);d.children().detach();d.append(h(b));t(a,"aoDrawCallback","draw",[a]);a.bSorted=!1;a.bFiltered=!1;a.bDrawing=!1}}function T(a,b){var c=a.oFeatures,d=c.bFilter;c.bSort&&ob(a);d?ha(a,a.oPreviousSearch):a.aiDisplay=a.aiDisplayMaster.slice();!0!==b&&(a._iDisplayStart=0);a._drawHold=b;P(a);a._drawHold=!1}function pb(a){var b=a.oClasses,c=h(a.nTable),c=h("<div/>").insertBefore(c),d=a.oFeatures,e=h("<div/>",{id:a.sTableId+"_wrapper","class":b.sWrapper+(a.nTFoot?"":" "+b.sNoFooter)});
|
||||
a.nHolding=c[0];a.nTableWrapper=e[0];a.nTableReinsertBefore=a.nTable.nextSibling;for(var f=a.sDom.split(""),g,j,i,l,m,q,k=0;k<f.length;k++){g=null;j=f[k];if("<"==j){i=h("<div/>")[0];l=f[k+1];if("'"==l||'"'==l){m="";for(q=2;f[k+q]!=l;)m+=f[k+q],q++;"H"==m?m=b.sJUIHeader:"F"==m&&(m=b.sJUIFooter);-1!=m.indexOf(".")?(l=m.split("."),i.id=l[0].substr(1,l[0].length-1),i.className=l[1]):"#"==m.charAt(0)?i.id=m.substr(1,m.length-1):i.className=m;k+=q}e.append(i);e=h(i)}else if(">"==j)e=e.parent();else if("l"==
|
||||
j&&d.bPaginate&&d.bLengthChange)g=qb(a);else if("f"==j&&d.bFilter)g=rb(a);else if("r"==j&&d.bProcessing)g=sb(a);else if("t"==j)g=tb(a);else if("i"==j&&d.bInfo)g=ub(a);else if("p"==j&&d.bPaginate)g=vb(a);else if(0!==n.ext.feature.length){i=n.ext.feature;q=0;for(l=i.length;q<l;q++)if(j==i[q].cFeature){g=i[q].fnInit(a);break}}g&&(i=a.aanFeatures,i[j]||(i[j]=[]),i[j].push(g),e.append(g))}c.replaceWith(e);a.nHolding=null}function fa(a,b){var c=h(b).children("tr"),d,e,f,g,j,i,l,m,q,k;a.splice(0,a.length);
|
||||
f=0;for(i=c.length;f<i;f++)a.push([]);f=0;for(i=c.length;f<i;f++){d=c[f];for(e=d.firstChild;e;){if("TD"==e.nodeName.toUpperCase()||"TH"==e.nodeName.toUpperCase()){m=1*e.getAttribute("colspan");q=1*e.getAttribute("rowspan");m=!m||0===m||1===m?1:m;q=!q||0===q||1===q?1:q;g=0;for(j=a[f];j[g];)g++;l=g;k=1===m?!0:!1;for(j=0;j<m;j++)for(g=0;g<q;g++)a[f+g][l+j]={cell:e,unique:k},a[f+g].nTr=d}e=e.nextSibling}}}function sa(a,b,c){var d=[];c||(c=a.aoHeader,b&&(c=[],fa(c,b)));for(var b=0,e=c.length;b<e;b++)for(var f=
|
||||
0,g=c[b].length;f<g;f++)if(c[b][f].unique&&(!d[f]||!a.bSortCellsTop))d[f]=c[b][f].cell;return d}function ta(a,b,c){t(a,"aoServerParams","serverParams",[b]);if(b&&h.isArray(b)){var d={},e=/(.*?)\[\]$/;h.each(b,function(a,b){var c=b.name.match(e);c?(c=c[0],d[c]||(d[c]=[]),d[c].push(b.value)):d[b.name]=b.value});b=d}var f,g=a.ajax,j=a.oInstance,i=function(b){t(a,null,"xhr",[a,b,a.jqXHR]);c(b)};if(h.isPlainObject(g)&&g.data){f=g.data;var l="function"===typeof f?f(b,a):f,b="function"===typeof f&&l?l:h.extend(!0,
|
||||
b,l);delete g.data}l={data:b,success:function(b){var c=b.error||b.sError;c&&K(a,0,c);a.json=b;i(b)},dataType:"json",cache:!1,type:a.sServerMethod,error:function(b,c){var d=t(a,null,"xhr",[a,null,a.jqXHR]);-1===h.inArray(!0,d)&&("parsererror"==c?K(a,0,"Invalid JSON response",1):4===b.readyState&&K(a,0,"Ajax error",7));D(a,!1)}};a.oAjaxData=b;t(a,null,"preXhr",[a,b]);a.fnServerData?a.fnServerData.call(j,a.sAjaxSource,h.map(b,function(a,b){return{name:b,value:a}}),i,a):a.sAjaxSource||"string"===typeof g?
|
||||
a.jqXHR=h.ajax(h.extend(l,{url:g||a.sAjaxSource})):"function"===typeof g?a.jqXHR=g.call(j,b,i,a):(a.jqXHR=h.ajax(h.extend(l,g)),g.data=f)}function nb(a){return a.bAjaxDataGet?(a.iDraw++,D(a,!0),ta(a,wb(a),function(b){xb(a,b)}),!1):!0}function wb(a){var b=a.aoColumns,c=b.length,d=a.oFeatures,e=a.oPreviousSearch,f=a.aoPreSearchCols,g,j=[],i,l,m,k=Y(a);g=a._iDisplayStart;i=!1!==d.bPaginate?a._iDisplayLength:-1;var u=function(a,b){j.push({name:a,value:b})};u("sEcho",a.iDraw);u("iColumns",c);u("sColumns",
|
||||
C(b,"sName").join(","));u("iDisplayStart",g);u("iDisplayLength",i);var G={draw:a.iDraw,columns:[],order:[],start:g,length:i,search:{value:e.sSearch,regex:e.bRegex}};for(g=0;g<c;g++)l=b[g],m=f[g],i="function"==typeof l.mData?"function":l.mData,G.columns.push({data:i,name:l.sName,searchable:l.bSearchable,orderable:l.bSortable,search:{value:m.sSearch,regex:m.bRegex}}),u("mDataProp_"+g,i),d.bFilter&&(u("sSearch_"+g,m.sSearch),u("bRegex_"+g,m.bRegex),u("bSearchable_"+g,l.bSearchable)),d.bSort&&u("bSortable_"+
|
||||
g,l.bSortable);d.bFilter&&(u("sSearch",e.sSearch),u("bRegex",e.bRegex));d.bSort&&(h.each(k,function(a,b){G.order.push({column:b.col,dir:b.dir});u("iSortCol_"+a,b.col);u("sSortDir_"+a,b.dir)}),u("iSortingCols",k.length));b=n.ext.legacy.ajax;return null===b?a.sAjaxSource?j:G:b?j:G}function xb(a,b){var c=ua(a,b),d=b.sEcho!==k?b.sEcho:b.draw,e=b.iTotalRecords!==k?b.iTotalRecords:b.recordsTotal,f=b.iTotalDisplayRecords!==k?b.iTotalDisplayRecords:b.recordsFiltered;if(d){if(1*d<a.iDraw)return;a.iDraw=1*
|
||||
d}pa(a);a._iRecordsTotal=parseInt(e,10);a._iRecordsDisplay=parseInt(f,10);d=0;for(e=c.length;d<e;d++)O(a,c[d]);a.aiDisplay=a.aiDisplayMaster.slice();a.bAjaxDataGet=!1;P(a);a._bInitComplete||va(a,b);a.bAjaxDataGet=!0;D(a,!1)}function ua(a,b){var c=h.isPlainObject(a.ajax)&&a.ajax.dataSrc!==k?a.ajax.dataSrc:a.sAjaxDataProp;return"data"===c?b.aaData||b[c]:""!==c?S(c)(b):b}function rb(a){var b=a.oClasses,c=a.sTableId,d=a.oLanguage,e=a.oPreviousSearch,f=a.aanFeatures,g='<input type="search" class="'+b.sFilterInput+
|
||||
'"/>',j=d.sSearch,j=j.match(/_INPUT_/)?j.replace("_INPUT_",g):j+g,b=h("<div/>",{id:!f.f?c+"_filter":null,"class":b.sFilter}).append(h("<label/>").append(j)),f=function(){var b=!this.value?"":this.value;b!=e.sSearch&&(ha(a,{sSearch:b,bRegex:e.bRegex,bSmart:e.bSmart,bCaseInsensitive:e.bCaseInsensitive}),a._iDisplayStart=0,P(a))},g=null!==a.searchDelay?a.searchDelay:"ssp"===y(a)?400:0,i=h("input",b).val(e.sSearch).attr("placeholder",d.sSearchPlaceholder).on("keyup.DT search.DT input.DT paste.DT cut.DT",
|
||||
g?Qa(f,g):f).on("keypress.DT",function(a){if(13==a.keyCode)return!1}).attr("aria-controls",c);h(a.nTable).on("search.dt.DT",function(b,c){if(a===c)try{i[0]!==H.activeElement&&i.val(e.sSearch)}catch(d){}});return b[0]}function ha(a,b,c){var d=a.oPreviousSearch,e=a.aoPreSearchCols,f=function(a){d.sSearch=a.sSearch;d.bRegex=a.bRegex;d.bSmart=a.bSmart;d.bCaseInsensitive=a.bCaseInsensitive};Ia(a);if("ssp"!=y(a)){yb(a,b.sSearch,c,b.bEscapeRegex!==k?!b.bEscapeRegex:b.bRegex,b.bSmart,b.bCaseInsensitive);
|
||||
f(b);for(b=0;b<e.length;b++)zb(a,e[b].sSearch,b,e[b].bEscapeRegex!==k?!e[b].bEscapeRegex:e[b].bRegex,e[b].bSmart,e[b].bCaseInsensitive);Ab(a)}else f(b);a.bFiltered=!0;t(a,null,"search",[a])}function Ab(a){for(var b=n.ext.search,c=a.aiDisplay,d,e,f=0,g=b.length;f<g;f++){for(var j=[],i=0,l=c.length;i<l;i++)e=c[i],d=a.aoData[e],b[f](a,d._aFilterData,e,d._aData,i)&&j.push(e);c.length=0;h.merge(c,j)}}function zb(a,b,c,d,e,f){if(""!==b){for(var g=[],j=a.aiDisplay,d=Ra(b,d,e,f),e=0;e<j.length;e++)b=a.aoData[j[e]]._aFilterData[c],
|
||||
d.test(b)&&g.push(j[e]);a.aiDisplay=g}}function yb(a,b,c,d,e,f){var e=Ra(b,d,e,f),g=a.oPreviousSearch.sSearch,j=a.aiDisplayMaster,i,f=[];0!==n.ext.search.length&&(c=!0);i=Bb(a);if(0>=b.length)a.aiDisplay=j.slice();else{if(i||c||d||g.length>b.length||0!==b.indexOf(g)||a.bSorted)a.aiDisplay=j.slice();b=a.aiDisplay;for(c=0;c<b.length;c++)e.test(a.aoData[b[c]]._sFilterRow)&&f.push(b[c]);a.aiDisplay=f}}function Ra(a,b,c,d){a=b?a:Sa(a);c&&(a="^(?=.*?"+h.map(a.match(/"[^"]+"|[^ ]+/g)||[""],function(a){if('"'===
|
||||
a.charAt(0))var b=a.match(/^"(.*)"$/),a=b?b[1]:a;return a.replace('"',"")}).join(")(?=.*?")+").*$");return RegExp(a,d?"i":"")}function Bb(a){var b=a.aoColumns,c,d,e,f,g,j,i,h,m=n.ext.type.search;c=!1;d=0;for(f=a.aoData.length;d<f;d++)if(h=a.aoData[d],!h._aFilterData){j=[];e=0;for(g=b.length;e<g;e++)c=b[e],c.bSearchable?(i=B(a,d,e,"filter"),m[c.sType]&&(i=m[c.sType](i)),null===i&&(i=""),"string"!==typeof i&&i.toString&&(i=i.toString())):i="",i.indexOf&&-1!==i.indexOf("&")&&(wa.innerHTML=i,i=Xb?wa.textContent:
|
||||
wa.innerText),i.replace&&(i=i.replace(/[\r\n\u2028]/g,"")),j.push(i);h._aFilterData=j;h._sFilterRow=j.join(" ");c=!0}return c}function Cb(a){return{search:a.sSearch,smart:a.bSmart,regex:a.bRegex,caseInsensitive:a.bCaseInsensitive}}function Db(a){return{sSearch:a.search,bSmart:a.smart,bRegex:a.regex,bCaseInsensitive:a.caseInsensitive}}function ub(a){var b=a.sTableId,c=a.aanFeatures.i,d=h("<div/>",{"class":a.oClasses.sInfo,id:!c?b+"_info":null});c||(a.aoDrawCallback.push({fn:Eb,sName:"information"}),
|
||||
d.attr("role","status").attr("aria-live","polite"),h(a.nTable).attr("aria-describedby",b+"_info"));return d[0]}function Eb(a){var b=a.aanFeatures.i;if(0!==b.length){var c=a.oLanguage,d=a._iDisplayStart+1,e=a.fnDisplayEnd(),f=a.fnRecordsTotal(),g=a.fnRecordsDisplay(),j=g?c.sInfo:c.sInfoEmpty;g!==f&&(j+=" "+c.sInfoFiltered);j+=c.sInfoPostFix;j=Fb(a,j);c=c.fnInfoCallback;null!==c&&(j=c.call(a.oInstance,a,d,e,f,g,j));h(b).html(j)}}function Fb(a,b){var c=a.fnFormatNumber,d=a._iDisplayStart+1,e=a._iDisplayLength,
|
||||
f=a.fnRecordsDisplay(),g=-1===e;return b.replace(/_START_/g,c.call(a,d)).replace(/_END_/g,c.call(a,a.fnDisplayEnd())).replace(/_MAX_/g,c.call(a,a.fnRecordsTotal())).replace(/_TOTAL_/g,c.call(a,f)).replace(/_PAGE_/g,c.call(a,g?1:Math.ceil(d/e))).replace(/_PAGES_/g,c.call(a,g?1:Math.ceil(f/e)))}function ia(a){var b,c,d=a.iInitDisplayStart,e=a.aoColumns,f;c=a.oFeatures;var g=a.bDeferLoading;if(a.bInitialised){pb(a);mb(a);ga(a,a.aoHeader);ga(a,a.aoFooter);D(a,!0);c.bAutoWidth&&Ha(a);b=0;for(c=e.length;b<
|
||||
c;b++)f=e[b],f.sWidth&&(f.nTh.style.width=w(f.sWidth));t(a,null,"preInit",[a]);T(a);e=y(a);if("ssp"!=e||g)"ajax"==e?ta(a,[],function(c){var f=ua(a,c);for(b=0;b<f.length;b++)O(a,f[b]);a.iInitDisplayStart=d;T(a);D(a,!1);va(a,c)},a):(D(a,!1),va(a))}else setTimeout(function(){ia(a)},200)}function va(a,b){a._bInitComplete=!0;(b||a.oInit.aaData)&&aa(a);t(a,null,"plugin-init",[a,b]);t(a,"aoInitComplete","init",[a,b])}function Ta(a,b){var c=parseInt(b,10);a._iDisplayLength=c;Ua(a);t(a,null,"length",[a,c])}
|
||||
function qb(a){for(var b=a.oClasses,c=a.sTableId,d=a.aLengthMenu,e=h.isArray(d[0]),f=e?d[0]:d,d=e?d[1]:d,e=h("<select/>",{name:c+"_length","aria-controls":c,"class":b.sLengthSelect}),g=0,j=f.length;g<j;g++)e[0][g]=new Option("number"===typeof d[g]?a.fnFormatNumber(d[g]):d[g],f[g]);var i=h("<div><label/></div>").addClass(b.sLength);a.aanFeatures.l||(i[0].id=c+"_length");i.children().append(a.oLanguage.sLengthMenu.replace("_MENU_",e[0].outerHTML));h("select",i).val(a._iDisplayLength).on("change.DT",
|
||||
function(){Ta(a,h(this).val());P(a)});h(a.nTable).on("length.dt.DT",function(b,c,d){a===c&&h("select",i).val(d)});return i[0]}function vb(a){var b=a.sPaginationType,c=n.ext.pager[b],d="function"===typeof c,e=function(a){P(a)},b=h("<div/>").addClass(a.oClasses.sPaging+b)[0],f=a.aanFeatures;d||c.fnInit(a,b,e);f.p||(b.id=a.sTableId+"_paginate",a.aoDrawCallback.push({fn:function(a){if(d){var b=a._iDisplayStart,i=a._iDisplayLength,h=a.fnRecordsDisplay(),m=-1===i,b=m?0:Math.ceil(b/i),i=m?1:Math.ceil(h/
|
||||
i),h=c(b,i),k,m=0;for(k=f.p.length;m<k;m++)Pa(a,"pageButton")(a,f.p[m],m,h,b,i)}else c.fnUpdate(a,e)},sName:"pagination"}));return b}function Va(a,b,c){var d=a._iDisplayStart,e=a._iDisplayLength,f=a.fnRecordsDisplay();0===f||-1===e?d=0:"number"===typeof b?(d=b*e,d>f&&(d=0)):"first"==b?d=0:"previous"==b?(d=0<=e?d-e:0,0>d&&(d=0)):"next"==b?d+e<f&&(d+=e):"last"==b?d=Math.floor((f-1)/e)*e:K(a,0,"Unknown paging action: "+b,5);b=a._iDisplayStart!==d;a._iDisplayStart=d;b&&(t(a,null,"page",[a]),c&&P(a));
|
||||
return b}function sb(a){return h("<div/>",{id:!a.aanFeatures.r?a.sTableId+"_processing":null,"class":a.oClasses.sProcessing}).html(a.oLanguage.sProcessing).insertBefore(a.nTable)[0]}function D(a,b){a.oFeatures.bProcessing&&h(a.aanFeatures.r).css("display",b?"block":"none");t(a,null,"processing",[a,b])}function tb(a){var b=h(a.nTable);b.attr("role","grid");var c=a.oScroll;if(""===c.sX&&""===c.sY)return a.nTable;var d=c.sX,e=c.sY,f=a.oClasses,g=b.children("caption"),j=g.length?g[0]._captionSide:null,
|
||||
i=h(b[0].cloneNode(!1)),l=h(b[0].cloneNode(!1)),m=b.children("tfoot");m.length||(m=null);i=h("<div/>",{"class":f.sScrollWrapper}).append(h("<div/>",{"class":f.sScrollHead}).css({overflow:"hidden",position:"relative",border:0,width:d?!d?null:w(d):"100%"}).append(h("<div/>",{"class":f.sScrollHeadInner}).css({"box-sizing":"content-box",width:c.sXInner||"100%"}).append(i.removeAttr("id").css("margin-left",0).append("top"===j?g:null).append(b.children("thead"))))).append(h("<div/>",{"class":f.sScrollBody}).css({position:"relative",
|
||||
overflow:"auto",width:!d?null:w(d)}).append(b));m&&i.append(h("<div/>",{"class":f.sScrollFoot}).css({overflow:"hidden",border:0,width:d?!d?null:w(d):"100%"}).append(h("<div/>",{"class":f.sScrollFootInner}).append(l.removeAttr("id").css("margin-left",0).append("bottom"===j?g:null).append(b.children("tfoot")))));var b=i.children(),k=b[0],f=b[1],u=m?b[2]:null;if(d)h(f).on("scroll.DT",function(){var a=this.scrollLeft;k.scrollLeft=a;m&&(u.scrollLeft=a)});h(f).css(e&&c.bCollapse?"max-height":"height",e);
|
||||
a.nScrollHead=k;a.nScrollBody=f;a.nScrollFoot=u;a.aoDrawCallback.push({fn:ma,sName:"scrolling"});return i[0]}function ma(a){var b=a.oScroll,c=b.sX,d=b.sXInner,e=b.sY,b=b.iBarWidth,f=h(a.nScrollHead),g=f[0].style,j=f.children("div"),i=j[0].style,l=j.children("table"),j=a.nScrollBody,m=h(j),q=j.style,u=h(a.nScrollFoot).children("div"),n=u.children("table"),o=h(a.nTHead),p=h(a.nTable),r=p[0],t=r.style,s=a.nTFoot?h(a.nTFoot):null,U=a.oBrowser,V=U.bScrollOversize,Yb=C(a.aoColumns,"nTh"),Q,L,R,xa,v=[],
|
||||
x=[],y=[],z=[],A,B=function(a){a=a.style;a.paddingTop="0";a.paddingBottom="0";a.borderTopWidth="0";a.borderBottomWidth="0";a.height=0};L=j.scrollHeight>j.clientHeight;if(a.scrollBarVis!==L&&a.scrollBarVis!==k)a.scrollBarVis=L,aa(a);else{a.scrollBarVis=L;p.children("thead, tfoot").remove();s&&(R=s.clone().prependTo(p),Q=s.find("tr"),R=R.find("tr"));xa=o.clone().prependTo(p);o=o.find("tr");L=xa.find("tr");xa.find("th, td").removeAttr("tabindex");c||(q.width="100%",f[0].style.width="100%");h.each(sa(a,
|
||||
xa),function(b,c){A=ba(a,b);c.style.width=a.aoColumns[A].sWidth});s&&I(function(a){a.style.width=""},R);f=p.outerWidth();if(""===c){t.width="100%";if(V&&(p.find("tbody").height()>j.offsetHeight||"scroll"==m.css("overflow-y")))t.width=w(p.outerWidth()-b);f=p.outerWidth()}else""!==d&&(t.width=w(d),f=p.outerWidth());I(B,L);I(function(a){y.push(a.innerHTML);v.push(w(h(a).css("width")))},L);I(function(a,b){if(h.inArray(a,Yb)!==-1)a.style.width=v[b]},o);h(L).height(0);s&&(I(B,R),I(function(a){z.push(a.innerHTML);
|
||||
x.push(w(h(a).css("width")))},R),I(function(a,b){a.style.width=x[b]},Q),h(R).height(0));I(function(a,b){a.innerHTML='<div class="dataTables_sizing">'+y[b]+"</div>";a.childNodes[0].style.height="0";a.childNodes[0].style.overflow="hidden";a.style.width=v[b]},L);s&&I(function(a,b){a.innerHTML='<div class="dataTables_sizing">'+z[b]+"</div>";a.childNodes[0].style.height="0";a.childNodes[0].style.overflow="hidden";a.style.width=x[b]},R);if(p.outerWidth()<f){Q=j.scrollHeight>j.offsetHeight||"scroll"==m.css("overflow-y")?
|
||||
f+b:f;if(V&&(j.scrollHeight>j.offsetHeight||"scroll"==m.css("overflow-y")))t.width=w(Q-b);(""===c||""!==d)&&K(a,1,"Possible column misalignment",6)}else Q="100%";q.width=w(Q);g.width=w(Q);s&&(a.nScrollFoot.style.width=w(Q));!e&&V&&(q.height=w(r.offsetHeight+b));c=p.outerWidth();l[0].style.width=w(c);i.width=w(c);d=p.height()>j.clientHeight||"scroll"==m.css("overflow-y");e="padding"+(U.bScrollbarLeft?"Left":"Right");i[e]=d?b+"px":"0px";s&&(n[0].style.width=w(c),u[0].style.width=w(c),u[0].style[e]=
|
||||
d?b+"px":"0px");p.children("colgroup").insertBefore(p.children("thead"));m.trigger("scroll");if((a.bSorted||a.bFiltered)&&!a._drawHold)j.scrollTop=0}}function I(a,b,c){for(var d=0,e=0,f=b.length,g,j;e<f;){g=b[e].firstChild;for(j=c?c[e].firstChild:null;g;)1===g.nodeType&&(c?a(g,j,d):a(g,d),d++),g=g.nextSibling,j=c?j.nextSibling:null;e++}}function Ha(a){var b=a.nTable,c=a.aoColumns,d=a.oScroll,e=d.sY,f=d.sX,g=d.sXInner,j=c.length,i=na(a,"bVisible"),l=h("th",a.nTHead),m=b.getAttribute("width"),k=b.parentNode,
|
||||
u=!1,n,o,p=a.oBrowser,d=p.bScrollOversize;(n=b.style.width)&&-1!==n.indexOf("%")&&(m=n);for(n=0;n<i.length;n++)o=c[i[n]],null!==o.sWidth&&(o.sWidth=Gb(o.sWidthOrig,k),u=!0);if(d||!u&&!f&&!e&&j==W(a)&&j==l.length)for(n=0;n<j;n++)i=ba(a,n),null!==i&&(c[i].sWidth=w(l.eq(n).width()));else{j=h(b).clone().css("visibility","hidden").removeAttr("id");j.find("tbody tr").remove();var r=h("<tr/>").appendTo(j.find("tbody"));j.find("thead, tfoot").remove();j.append(h(a.nTHead).clone()).append(h(a.nTFoot).clone());
|
||||
j.find("tfoot th, tfoot td").css("width","");l=sa(a,j.find("thead")[0]);for(n=0;n<i.length;n++)o=c[i[n]],l[n].style.width=null!==o.sWidthOrig&&""!==o.sWidthOrig?w(o.sWidthOrig):"",o.sWidthOrig&&f&&h(l[n]).append(h("<div/>").css({width:o.sWidthOrig,margin:0,padding:0,border:0,height:1}));if(a.aoData.length)for(n=0;n<i.length;n++)u=i[n],o=c[u],h(Hb(a,u)).clone(!1).append(o.sContentPadding).appendTo(r);h("[name]",j).removeAttr("name");o=h("<div/>").css(f||e?{position:"absolute",top:0,left:0,height:1,
|
||||
right:0,overflow:"hidden"}:{}).append(j).appendTo(k);f&&g?j.width(g):f?(j.css("width","auto"),j.removeAttr("width"),j.width()<k.clientWidth&&m&&j.width(k.clientWidth)):e?j.width(k.clientWidth):m&&j.width(m);for(n=e=0;n<i.length;n++)k=h(l[n]),g=k.outerWidth()-k.width(),k=p.bBounding?Math.ceil(l[n].getBoundingClientRect().width):k.outerWidth(),e+=k,c[i[n]].sWidth=w(k-g);b.style.width=w(e);o.remove()}m&&(b.style.width=w(m));if((m||f)&&!a._reszEvt)b=function(){h(E).on("resize.DT-"+a.sInstance,Qa(function(){aa(a)}))},
|
||||
d?setTimeout(b,1E3):b(),a._reszEvt=!0}function Gb(a,b){if(!a)return 0;var c=h("<div/>").css("width",w(a)).appendTo(b||H.body),d=c[0].offsetWidth;c.remove();return d}function Hb(a,b){var c=Ib(a,b);if(0>c)return null;var d=a.aoData[c];return!d.nTr?h("<td/>").html(B(a,c,b,"display"))[0]:d.anCells[b]}function Ib(a,b){for(var c,d=-1,e=-1,f=0,g=a.aoData.length;f<g;f++)c=B(a,f,b,"display")+"",c=c.replace(Zb,""),c=c.replace(/ /g," "),c.length>d&&(d=c.length,e=f);return e}function w(a){return null===
|
||||
a?"0px":"number"==typeof a?0>a?"0px":a+"px":a.match(/\d$/)?a+"px":a}function Y(a){var b,c,d=[],e=a.aoColumns,f,g,j,i;b=a.aaSortingFixed;c=h.isPlainObject(b);var l=[];f=function(a){a.length&&!h.isArray(a[0])?l.push(a):h.merge(l,a)};h.isArray(b)&&f(b);c&&b.pre&&f(b.pre);f(a.aaSorting);c&&b.post&&f(b.post);for(a=0;a<l.length;a++){i=l[a][0];f=e[i].aDataSort;b=0;for(c=f.length;b<c;b++)g=f[b],j=e[g].sType||"string",l[a]._idx===k&&(l[a]._idx=h.inArray(l[a][1],e[g].asSorting)),d.push({src:i,col:g,dir:l[a][1],
|
||||
index:l[a]._idx,type:j,formatter:n.ext.type.order[j+"-pre"]})}return d}function ob(a){var b,c,d=[],e=n.ext.type.order,f=a.aoData,g=0,j,i=a.aiDisplayMaster,h;Ia(a);h=Y(a);b=0;for(c=h.length;b<c;b++)j=h[b],j.formatter&&g++,Jb(a,j.col);if("ssp"!=y(a)&&0!==h.length){b=0;for(c=i.length;b<c;b++)d[i[b]]=b;g===h.length?i.sort(function(a,b){var c,e,g,j,i=h.length,k=f[a]._aSortData,n=f[b]._aSortData;for(g=0;g<i;g++)if(j=h[g],c=k[j.col],e=n[j.col],c=c<e?-1:c>e?1:0,0!==c)return"asc"===j.dir?c:-c;c=d[a];e=d[b];
|
||||
return c<e?-1:c>e?1:0}):i.sort(function(a,b){var c,g,j,i,k=h.length,n=f[a]._aSortData,o=f[b]._aSortData;for(j=0;j<k;j++)if(i=h[j],c=n[i.col],g=o[i.col],i=e[i.type+"-"+i.dir]||e["string-"+i.dir],c=i(c,g),0!==c)return c;c=d[a];g=d[b];return c<g?-1:c>g?1:0})}a.bSorted=!0}function Kb(a){for(var b,c,d=a.aoColumns,e=Y(a),a=a.oLanguage.oAria,f=0,g=d.length;f<g;f++){c=d[f];var j=c.asSorting;b=c.sTitle.replace(/<.*?>/g,"");var i=c.nTh;i.removeAttribute("aria-sort");c.bSortable&&(0<e.length&&e[0].col==f?(i.setAttribute("aria-sort",
|
||||
"asc"==e[0].dir?"ascending":"descending"),c=j[e[0].index+1]||j[0]):c=j[0],b+="asc"===c?a.sSortAscending:a.sSortDescending);i.setAttribute("aria-label",b)}}function Wa(a,b,c,d){var e=a.aaSorting,f=a.aoColumns[b].asSorting,g=function(a,b){var c=a._idx;c===k&&(c=h.inArray(a[1],f));return c+1<f.length?c+1:b?null:0};"number"===typeof e[0]&&(e=a.aaSorting=[e]);c&&a.oFeatures.bSortMulti?(c=h.inArray(b,C(e,"0")),-1!==c?(b=g(e[c],!0),null===b&&1===e.length&&(b=0),null===b?e.splice(c,1):(e[c][1]=f[b],e[c]._idx=
|
||||
b)):(e.push([b,f[0],0]),e[e.length-1]._idx=0)):e.length&&e[0][0]==b?(b=g(e[0]),e.length=1,e[0][1]=f[b],e[0]._idx=b):(e.length=0,e.push([b,f[0]]),e[0]._idx=0);T(a);"function"==typeof d&&d(a)}function Oa(a,b,c,d){var e=a.aoColumns[c];Xa(b,{},function(b){!1!==e.bSortable&&(a.oFeatures.bProcessing?(D(a,!0),setTimeout(function(){Wa(a,c,b.shiftKey,d);"ssp"!==y(a)&&D(a,!1)},0)):Wa(a,c,b.shiftKey,d))})}function ya(a){var b=a.aLastSort,c=a.oClasses.sSortColumn,d=Y(a),e=a.oFeatures,f,g;if(e.bSort&&e.bSortClasses){e=
|
||||
0;for(f=b.length;e<f;e++)g=b[e].src,h(C(a.aoData,"anCells",g)).removeClass(c+(2>e?e+1:3));e=0;for(f=d.length;e<f;e++)g=d[e].src,h(C(a.aoData,"anCells",g)).addClass(c+(2>e?e+1:3))}a.aLastSort=d}function Jb(a,b){var c=a.aoColumns[b],d=n.ext.order[c.sSortDataType],e;d&&(e=d.call(a.oInstance,a,b,ca(a,b)));for(var f,g=n.ext.type.order[c.sType+"-pre"],j=0,i=a.aoData.length;j<i;j++)if(c=a.aoData[j],c._aSortData||(c._aSortData=[]),!c._aSortData[b]||d)f=d?e[j]:B(a,j,b,"sort"),c._aSortData[b]=g?g(f):f}function za(a){if(a.oFeatures.bStateSave&&
|
||||
!a.bDestroying){var b={time:+new Date,start:a._iDisplayStart,length:a._iDisplayLength,order:h.extend(!0,[],a.aaSorting),search:Cb(a.oPreviousSearch),columns:h.map(a.aoColumns,function(b,d){return{visible:b.bVisible,search:Cb(a.aoPreSearchCols[d])}})};t(a,"aoStateSaveParams","stateSaveParams",[a,b]);a.oSavedState=b;a.fnStateSaveCallback.call(a.oInstance,a,b)}}function Lb(a,b,c){var d,e,f=a.aoColumns,b=function(b){if(b&&b.time){var g=t(a,"aoStateLoadParams","stateLoadParams",[a,b]);if(-1===h.inArray(!1,
|
||||
g)&&(g=a.iStateDuration,!(0<g&&b.time<+new Date-1E3*g)&&!(b.columns&&f.length!==b.columns.length))){a.oLoadedState=h.extend(!0,{},b);b.start!==k&&(a._iDisplayStart=b.start,a.iInitDisplayStart=b.start);b.length!==k&&(a._iDisplayLength=b.length);b.order!==k&&(a.aaSorting=[],h.each(b.order,function(b,c){a.aaSorting.push(c[0]>=f.length?[0,c[1]]:c)}));b.search!==k&&h.extend(a.oPreviousSearch,Db(b.search));if(b.columns){d=0;for(e=b.columns.length;d<e;d++)g=b.columns[d],g.visible!==k&&(f[d].bVisible=g.visible),
|
||||
g.search!==k&&h.extend(a.aoPreSearchCols[d],Db(g.search))}t(a,"aoStateLoaded","stateLoaded",[a,b])}}c()};if(a.oFeatures.bStateSave){var g=a.fnStateLoadCallback.call(a.oInstance,a,b);g!==k&&b(g)}else c()}function Aa(a){var b=n.settings,a=h.inArray(a,C(b,"nTable"));return-1!==a?b[a]:null}function K(a,b,c,d){c="DataTables warning: "+(a?"table id="+a.sTableId+" - ":"")+c;d&&(c+=". For more information about this error, please see http://datatables.net/tn/"+d);if(b)E.console&&console.log&&console.log(c);
|
||||
else if(b=n.ext,b=b.sErrMode||b.errMode,a&&t(a,null,"error",[a,d,c]),"alert"==b)alert(c);else{if("throw"==b)throw Error(c);"function"==typeof b&&b(a,d,c)}}function F(a,b,c,d){h.isArray(c)?h.each(c,function(c,d){h.isArray(d)?F(a,b,d[0],d[1]):F(a,b,d)}):(d===k&&(d=c),b[c]!==k&&(a[d]=b[c]))}function Ya(a,b,c){var d,e;for(e in b)b.hasOwnProperty(e)&&(d=b[e],h.isPlainObject(d)?(h.isPlainObject(a[e])||(a[e]={}),h.extend(!0,a[e],d)):a[e]=c&&"data"!==e&&"aaData"!==e&&h.isArray(d)?d.slice():d);return a}function Xa(a,
|
||||
b,c){h(a).on("click.DT",b,function(b){h(a).blur();c(b)}).on("keypress.DT",b,function(a){13===a.which&&(a.preventDefault(),c(a))}).on("selectstart.DT",function(){return!1})}function z(a,b,c,d){c&&a[b].push({fn:c,sName:d})}function t(a,b,c,d){var e=[];b&&(e=h.map(a[b].slice().reverse(),function(b){return b.fn.apply(a.oInstance,d)}));null!==c&&(b=h.Event(c+".dt"),h(a.nTable).trigger(b,d),e.push(b.result));return e}function Ua(a){var b=a._iDisplayStart,c=a.fnDisplayEnd(),d=a._iDisplayLength;b>=c&&(b=
|
||||
c-d);b-=b%d;if(-1===d||0>b)b=0;a._iDisplayStart=b}function Pa(a,b){var c=a.renderer,d=n.ext.renderer[b];return h.isPlainObject(c)&&c[b]?d[c[b]]||d._:"string"===typeof c?d[c]||d._:d._}function y(a){return a.oFeatures.bServerSide?"ssp":a.ajax||a.sAjaxSource?"ajax":"dom"}function ja(a,b){var c=[],c=Mb.numbers_length,d=Math.floor(c/2);b<=c?c=Z(0,b):a<=d?(c=Z(0,c-2),c.push("ellipsis"),c.push(b-1)):(a>=b-1-d?c=Z(b-(c-2),b):(c=Z(a-d+2,a+d-1),c.push("ellipsis"),c.push(b-1)),c.splice(0,0,"ellipsis"),c.splice(0,
|
||||
0,0));c.DT_el="span";return c}function Fa(a){h.each({num:function(b){return Ba(b,a)},"num-fmt":function(b){return Ba(b,a,Za)},"html-num":function(b){return Ba(b,a,Ca)},"html-num-fmt":function(b){return Ba(b,a,Ca,Za)}},function(b,c){v.type.order[b+a+"-pre"]=c;b.match(/^html\-/)&&(v.type.search[b+a]=v.type.search.html)})}function Nb(a){return function(){var b=[Aa(this[n.ext.iApiIndex])].concat(Array.prototype.slice.call(arguments));return n.ext.internal[a].apply(this,b)}}var n=function(a){this.$=function(a,
|
||||
b){return this.api(!0).$(a,b)};this._=function(a,b){return this.api(!0).rows(a,b).data()};this.api=function(a){return a?new r(Aa(this[v.iApiIndex])):new r(this)};this.fnAddData=function(a,b){var c=this.api(!0),d=h.isArray(a)&&(h.isArray(a[0])||h.isPlainObject(a[0]))?c.rows.add(a):c.row.add(a);(b===k||b)&&c.draw();return d.flatten().toArray()};this.fnAdjustColumnSizing=function(a){var b=this.api(!0).columns.adjust(),c=b.settings()[0],d=c.oScroll;a===k||a?b.draw(!1):(""!==d.sX||""!==d.sY)&&ma(c)};this.fnClearTable=
|
||||
function(a){var b=this.api(!0).clear();(a===k||a)&&b.draw()};this.fnClose=function(a){this.api(!0).row(a).child.hide()};this.fnDeleteRow=function(a,b,c){var d=this.api(!0),a=d.rows(a),e=a.settings()[0],h=e.aoData[a[0][0]];a.remove();b&&b.call(this,e,h);(c===k||c)&&d.draw();return h};this.fnDestroy=function(a){this.api(!0).destroy(a)};this.fnDraw=function(a){this.api(!0).draw(a)};this.fnFilter=function(a,b,c,d,e,h){e=this.api(!0);null===b||b===k?e.search(a,c,d,h):e.column(b).search(a,c,d,h);e.draw()};
|
||||
this.fnGetData=function(a,b){var c=this.api(!0);if(a!==k){var d=a.nodeName?a.nodeName.toLowerCase():"";return b!==k||"td"==d||"th"==d?c.cell(a,b).data():c.row(a).data()||null}return c.data().toArray()};this.fnGetNodes=function(a){var b=this.api(!0);return a!==k?b.row(a).node():b.rows().nodes().flatten().toArray()};this.fnGetPosition=function(a){var b=this.api(!0),c=a.nodeName.toUpperCase();return"TR"==c?b.row(a).index():"TD"==c||"TH"==c?(a=b.cell(a).index(),[a.row,a.columnVisible,a.column]):null};
|
||||
this.fnIsOpen=function(a){return this.api(!0).row(a).child.isShown()};this.fnOpen=function(a,b,c){return this.api(!0).row(a).child(b,c).show().child()[0]};this.fnPageChange=function(a,b){var c=this.api(!0).page(a);(b===k||b)&&c.draw(!1)};this.fnSetColumnVis=function(a,b,c){a=this.api(!0).column(a).visible(b);(c===k||c)&&a.columns.adjust().draw()};this.fnSettings=function(){return Aa(this[v.iApiIndex])};this.fnSort=function(a){this.api(!0).order(a).draw()};this.fnSortListener=function(a,b,c){this.api(!0).order.listener(a,
|
||||
b,c)};this.fnUpdate=function(a,b,c,d,e){var h=this.api(!0);c===k||null===c?h.row(b).data(a):h.cell(b,c).data(a);(e===k||e)&&h.columns.adjust();(d===k||d)&&h.draw();return 0};this.fnVersionCheck=v.fnVersionCheck;var b=this,c=a===k,d=this.length;c&&(a={});this.oApi=this.internal=v.internal;for(var e in n.ext.internal)e&&(this[e]=Nb(e));this.each(function(){var e={},g=1<d?Ya(e,a,!0):a,j=0,i,e=this.getAttribute("id"),l=!1,m=n.defaults,q=h(this);if("table"!=this.nodeName.toLowerCase())K(null,0,"Non-table node initialisation ("+
|
||||
this.nodeName+")",2);else{gb(m);hb(m.column);J(m,m,!0);J(m.column,m.column,!0);J(m,h.extend(g,q.data()),!0);var u=n.settings,j=0;for(i=u.length;j<i;j++){var o=u[j];if(o.nTable==this||o.nTHead&&o.nTHead.parentNode==this||o.nTFoot&&o.nTFoot.parentNode==this){var r=g.bRetrieve!==k?g.bRetrieve:m.bRetrieve;if(c||r)return o.oInstance;if(g.bDestroy!==k?g.bDestroy:m.bDestroy){o.oInstance.fnDestroy();break}else{K(o,0,"Cannot reinitialise DataTable",3);return}}if(o.sTableId==this.id){u.splice(j,1);break}}if(null===
|
||||
e||""===e)this.id=e="DataTables_Table_"+n.ext._unique++;var p=h.extend(!0,{},n.models.oSettings,{sDestroyWidth:q[0].style.width,sInstance:e,sTableId:e});p.nTable=this;p.oApi=b.internal;p.oInit=g;u.push(p);p.oInstance=1===b.length?b:q.dataTable();gb(g);Ea(g.oLanguage);g.aLengthMenu&&!g.iDisplayLength&&(g.iDisplayLength=h.isArray(g.aLengthMenu[0])?g.aLengthMenu[0][0]:g.aLengthMenu[0]);g=Ya(h.extend(!0,{},m),g);F(p.oFeatures,g,"bPaginate bLengthChange bFilter bSort bSortMulti bInfo bProcessing bAutoWidth bSortClasses bServerSide bDeferRender".split(" "));
|
||||
F(p,g,["asStripeClasses","ajax","fnServerData","fnFormatNumber","sServerMethod","aaSorting","aaSortingFixed","aLengthMenu","sPaginationType","sAjaxSource","sAjaxDataProp","iStateDuration","sDom","bSortCellsTop","iTabIndex","fnStateLoadCallback","fnStateSaveCallback","renderer","searchDelay","rowId",["iCookieDuration","iStateDuration"],["oSearch","oPreviousSearch"],["aoSearchCols","aoPreSearchCols"],["iDisplayLength","_iDisplayLength"]]);F(p.oScroll,g,[["sScrollX","sX"],["sScrollXInner","sXInner"],
|
||||
["sScrollY","sY"],["bScrollCollapse","bCollapse"]]);F(p.oLanguage,g,"fnInfoCallback");z(p,"aoDrawCallback",g.fnDrawCallback,"user");z(p,"aoServerParams",g.fnServerParams,"user");z(p,"aoStateSaveParams",g.fnStateSaveParams,"user");z(p,"aoStateLoadParams",g.fnStateLoadParams,"user");z(p,"aoStateLoaded",g.fnStateLoaded,"user");z(p,"aoRowCallback",g.fnRowCallback,"user");z(p,"aoRowCreatedCallback",g.fnCreatedRow,"user");z(p,"aoHeaderCallback",g.fnHeaderCallback,"user");z(p,"aoFooterCallback",g.fnFooterCallback,
|
||||
"user");z(p,"aoInitComplete",g.fnInitComplete,"user");z(p,"aoPreDrawCallback",g.fnPreDrawCallback,"user");p.rowIdFn=S(g.rowId);ib(p);var s=p.oClasses;h.extend(s,n.ext.classes,g.oClasses);q.addClass(s.sTable);p.iInitDisplayStart===k&&(p.iInitDisplayStart=g.iDisplayStart,p._iDisplayStart=g.iDisplayStart);null!==g.iDeferLoading&&(p.bDeferLoading=!0,e=h.isArray(g.iDeferLoading),p._iRecordsDisplay=e?g.iDeferLoading[0]:g.iDeferLoading,p._iRecordsTotal=e?g.iDeferLoading[1]:g.iDeferLoading);var w=p.oLanguage;
|
||||
h.extend(!0,w,g.oLanguage);w.sUrl&&(h.ajax({dataType:"json",url:w.sUrl,success:function(a){Ea(a);J(m.oLanguage,a);h.extend(true,w,a);ia(p)},error:function(){ia(p)}}),l=!0);null===g.asStripeClasses&&(p.asStripeClasses=[s.sStripeOdd,s.sStripeEven]);var e=p.asStripeClasses,v=q.children("tbody").find("tr").eq(0);-1!==h.inArray(!0,h.map(e,function(a){return v.hasClass(a)}))&&(h("tbody tr",this).removeClass(e.join(" ")),p.asDestroyStripes=e.slice());e=[];u=this.getElementsByTagName("thead");0!==u.length&&
|
||||
(fa(p.aoHeader,u[0]),e=sa(p));if(null===g.aoColumns){u=[];j=0;for(i=e.length;j<i;j++)u.push(null)}else u=g.aoColumns;j=0;for(i=u.length;j<i;j++)Ga(p,e?e[j]:null);kb(p,g.aoColumnDefs,u,function(a,b){la(p,a,b)});if(v.length){var U=function(a,b){return a.getAttribute("data-"+b)!==null?b:null};h(v[0]).children("th, td").each(function(a,b){var c=p.aoColumns[a];if(c.mData===a){var d=U(b,"sort")||U(b,"order"),e=U(b,"filter")||U(b,"search");if(d!==null||e!==null){c.mData={_:a+".display",sort:d!==null?a+".@data-"+
|
||||
d:k,type:d!==null?a+".@data-"+d:k,filter:e!==null?a+".@data-"+e:k};la(p,a)}}})}var V=p.oFeatures,e=function(){if(g.aaSorting===k){var a=p.aaSorting;j=0;for(i=a.length;j<i;j++)a[j][1]=p.aoColumns[j].asSorting[0]}ya(p);V.bSort&&z(p,"aoDrawCallback",function(){if(p.bSorted){var a=Y(p),b={};h.each(a,function(a,c){b[c.src]=c.dir});t(p,null,"order",[p,a,b]);Kb(p)}});z(p,"aoDrawCallback",function(){(p.bSorted||y(p)==="ssp"||V.bDeferRender)&&ya(p)},"sc");var a=q.children("caption").each(function(){this._captionSide=
|
||||
h(this).css("caption-side")}),b=q.children("thead");b.length===0&&(b=h("<thead/>").appendTo(q));p.nTHead=b[0];b=q.children("tbody");b.length===0&&(b=h("<tbody/>").appendTo(q));p.nTBody=b[0];b=q.children("tfoot");if(b.length===0&&a.length>0&&(p.oScroll.sX!==""||p.oScroll.sY!==""))b=h("<tfoot/>").appendTo(q);if(b.length===0||b.children().length===0)q.addClass(s.sNoFooter);else if(b.length>0){p.nTFoot=b[0];fa(p.aoFooter,p.nTFoot)}if(g.aaData)for(j=0;j<g.aaData.length;j++)O(p,g.aaData[j]);else(p.bDeferLoading||
|
||||
y(p)=="dom")&&oa(p,h(p.nTBody).children("tr"));p.aiDisplay=p.aiDisplayMaster.slice();p.bInitialised=true;l===false&&ia(p)};g.bStateSave?(V.bStateSave=!0,z(p,"aoDrawCallback",za,"state_save"),Lb(p,g,e)):e()}});b=null;return this},v,r,o,s,$a={},Ob=/[\r\n\u2028]/g,Ca=/<.*?>/g,$b=/^\d{2,4}[\.\/\-]\d{1,2}[\.\/\-]\d{1,2}([T ]{1}\d{1,2}[:\.]\d{2}([\.:]\d{2})?)?$/,ac=RegExp("(\\/|\\.|\\*|\\+|\\?|\\||\\(|\\)|\\[|\\]|\\{|\\}|\\\\|\\$|\\^|\\-)","g"),Za=/[',$£€¥%\u2009\u202F\u20BD\u20a9\u20BArfkɃΞ]/gi,M=function(a){return!a||
|
||||
!0===a||"-"===a?!0:!1},Pb=function(a){var b=parseInt(a,10);return!isNaN(b)&&isFinite(a)?b:null},Qb=function(a,b){$a[b]||($a[b]=RegExp(Sa(b),"g"));return"string"===typeof a&&"."!==b?a.replace(/\./g,"").replace($a[b],"."):a},ab=function(a,b,c){var d="string"===typeof a;if(M(a))return!0;b&&d&&(a=Qb(a,b));c&&d&&(a=a.replace(Za,""));return!isNaN(parseFloat(a))&&isFinite(a)},Rb=function(a,b,c){return M(a)?!0:!(M(a)||"string"===typeof a)?null:ab(a.replace(Ca,""),b,c)?!0:null},C=function(a,b,c){var d=[],
|
||||
e=0,f=a.length;if(c!==k)for(;e<f;e++)a[e]&&a[e][b]&&d.push(a[e][b][c]);else for(;e<f;e++)a[e]&&d.push(a[e][b]);return d},ka=function(a,b,c,d){var e=[],f=0,g=b.length;if(d!==k)for(;f<g;f++)a[b[f]][c]&&e.push(a[b[f]][c][d]);else for(;f<g;f++)e.push(a[b[f]][c]);return e},Z=function(a,b){var c=[],d;b===k?(b=0,d=a):(d=b,b=a);for(var e=b;e<d;e++)c.push(e);return c},Sb=function(a){for(var b=[],c=0,d=a.length;c<d;c++)a[c]&&b.push(a[c]);return b},ra=function(a){var b;a:{if(!(2>a.length)){b=a.slice().sort();
|
||||
for(var c=b[0],d=1,e=b.length;d<e;d++){if(b[d]===c){b=!1;break a}c=b[d]}}b=!0}if(b)return a.slice();b=[];var e=a.length,f,g=0,d=0;a:for(;d<e;d++){c=a[d];for(f=0;f<g;f++)if(b[f]===c)continue a;b.push(c);g++}return b};n.util={throttle:function(a,b){var c=b!==k?b:200,d,e;return function(){var b=this,g=+new Date,j=arguments;d&&g<d+c?(clearTimeout(e),e=setTimeout(function(){d=k;a.apply(b,j)},c)):(d=g,a.apply(b,j))}},escapeRegex:function(a){return a.replace(ac,"\\$1")}};var A=function(a,b,c){a[b]!==k&&
|
||||
(a[c]=a[b])},da=/\[.*?\]$/,X=/\(\)$/,Sa=n.util.escapeRegex,wa=h("<div>")[0],Xb=wa.textContent!==k,Zb=/<.*?>/g,Qa=n.util.throttle,Tb=[],x=Array.prototype,bc=function(a){var b,c,d=n.settings,e=h.map(d,function(a){return a.nTable});if(a){if(a.nTable&&a.oApi)return[a];if(a.nodeName&&"table"===a.nodeName.toLowerCase())return b=h.inArray(a,e),-1!==b?[d[b]]:null;if(a&&"function"===typeof a.settings)return a.settings().toArray();"string"===typeof a?c=h(a):a instanceof h&&(c=a)}else return[];if(c)return c.map(function(){b=
|
||||
h.inArray(this,e);return-1!==b?d[b]:null}).toArray()};r=function(a,b){if(!(this instanceof r))return new r(a,b);var c=[],d=function(a){(a=bc(a))&&c.push.apply(c,a)};if(h.isArray(a))for(var e=0,f=a.length;e<f;e++)d(a[e]);else d(a);this.context=ra(c);b&&h.merge(this,b);this.selector={rows:null,cols:null,opts:null};r.extend(this,this,Tb)};n.Api=r;h.extend(r.prototype,{any:function(){return 0!==this.count()},concat:x.concat,context:[],count:function(){return this.flatten().length},each:function(a){for(var b=
|
||||
0,c=this.length;b<c;b++)a.call(this,this[b],b,this);return this},eq:function(a){var b=this.context;return b.length>a?new r(b[a],this[a]):null},filter:function(a){var b=[];if(x.filter)b=x.filter.call(this,a,this);else for(var c=0,d=this.length;c<d;c++)a.call(this,this[c],c,this)&&b.push(this[c]);return new r(this.context,b)},flatten:function(){var a=[];return new r(this.context,a.concat.apply(a,this.toArray()))},join:x.join,indexOf:x.indexOf||function(a,b){for(var c=b||0,d=this.length;c<d;c++)if(this[c]===
|
||||
a)return c;return-1},iterator:function(a,b,c,d){var e=[],f,g,j,h,l,m=this.context,n,o,s=this.selector;"string"===typeof a&&(d=c,c=b,b=a,a=!1);g=0;for(j=m.length;g<j;g++){var t=new r(m[g]);if("table"===b)f=c.call(t,m[g],g),f!==k&&e.push(f);else if("columns"===b||"rows"===b)f=c.call(t,m[g],this[g],g),f!==k&&e.push(f);else if("column"===b||"column-rows"===b||"row"===b||"cell"===b){o=this[g];"column-rows"===b&&(n=Da(m[g],s.opts));h=0;for(l=o.length;h<l;h++)f=o[h],f="cell"===b?c.call(t,m[g],f.row,f.column,
|
||||
g,h):c.call(t,m[g],f,g,h,n),f!==k&&e.push(f)}}return e.length||d?(a=new r(m,a?e.concat.apply([],e):e),b=a.selector,b.rows=s.rows,b.cols=s.cols,b.opts=s.opts,a):this},lastIndexOf:x.lastIndexOf||function(a,b){return this.indexOf.apply(this.toArray.reverse(),arguments)},length:0,map:function(a){var b=[];if(x.map)b=x.map.call(this,a,this);else for(var c=0,d=this.length;c<d;c++)b.push(a.call(this,this[c],c));return new r(this.context,b)},pluck:function(a){return this.map(function(b){return b[a]})},pop:x.pop,
|
||||
push:x.push,reduce:x.reduce||function(a,b){return jb(this,a,b,0,this.length,1)},reduceRight:x.reduceRight||function(a,b){return jb(this,a,b,this.length-1,-1,-1)},reverse:x.reverse,selector:null,shift:x.shift,slice:function(){return new r(this.context,this)},sort:x.sort,splice:x.splice,toArray:function(){return x.slice.call(this)},to$:function(){return h(this)},toJQuery:function(){return h(this)},unique:function(){return new r(this.context,ra(this))},unshift:x.unshift});r.extend=function(a,b,c){if(c.length&&
|
||||
b&&(b instanceof r||b.__dt_wrapper)){var d,e,f,g=function(a,b,c){return function(){var d=b.apply(a,arguments);r.extend(d,d,c.methodExt);return d}};d=0;for(e=c.length;d<e;d++)f=c[d],b[f.name]="function"===f.type?g(a,f.val,f):"object"===f.type?{}:f.val,b[f.name].__dt_wrapper=!0,r.extend(a,b[f.name],f.propExt)}};r.register=o=function(a,b){if(h.isArray(a))for(var c=0,d=a.length;c<d;c++)r.register(a[c],b);else for(var e=a.split("."),f=Tb,g,j,c=0,d=e.length;c<d;c++){g=(j=-1!==e[c].indexOf("()"))?e[c].replace("()",
|
||||
""):e[c];var i;a:{i=0;for(var l=f.length;i<l;i++)if(f[i].name===g){i=f[i];break a}i=null}i||(i={name:g,val:{},methodExt:[],propExt:[],type:"object"},f.push(i));c===d-1?(i.val=b,i.type="function"===typeof b?"function":h.isPlainObject(b)?"object":"other"):f=j?i.methodExt:i.propExt}};r.registerPlural=s=function(a,b,c){r.register(a,c);r.register(b,function(){var a=c.apply(this,arguments);return a===this?this:a instanceof r?a.length?h.isArray(a[0])?new r(a.context,a[0]):a[0]:k:a})};o("tables()",function(a){var b;
|
||||
if(a){b=r;var c=this.context;if("number"===typeof a)a=[c[a]];else var d=h.map(c,function(a){return a.nTable}),a=h(d).filter(a).map(function(){var a=h.inArray(this,d);return c[a]}).toArray();b=new b(a)}else b=this;return b});o("table()",function(a){var a=this.tables(a),b=a.context;return b.length?new r(b[0]):a});s("tables().nodes()","table().node()",function(){return this.iterator("table",function(a){return a.nTable},1)});s("tables().body()","table().body()",function(){return this.iterator("table",
|
||||
function(a){return a.nTBody},1)});s("tables().header()","table().header()",function(){return this.iterator("table",function(a){return a.nTHead},1)});s("tables().footer()","table().footer()",function(){return this.iterator("table",function(a){return a.nTFoot},1)});s("tables().containers()","table().container()",function(){return this.iterator("table",function(a){return a.nTableWrapper},1)});o("draw()",function(a){return this.iterator("table",function(b){"page"===a?P(b):("string"===typeof a&&(a="full-hold"===
|
||||
a?!1:!0),T(b,!1===a))})});o("page()",function(a){return a===k?this.page.info().page:this.iterator("table",function(b){Va(b,a)})});o("page.info()",function(){if(0===this.context.length)return k;var a=this.context[0],b=a._iDisplayStart,c=a.oFeatures.bPaginate?a._iDisplayLength:-1,d=a.fnRecordsDisplay(),e=-1===c;return{page:e?0:Math.floor(b/c),pages:e?1:Math.ceil(d/c),start:b,end:a.fnDisplayEnd(),length:c,recordsTotal:a.fnRecordsTotal(),recordsDisplay:d,serverSide:"ssp"===y(a)}});o("page.len()",function(a){return a===
|
||||
k?0!==this.context.length?this.context[0]._iDisplayLength:k:this.iterator("table",function(b){Ta(b,a)})});var Ub=function(a,b,c){if(c){var d=new r(a);d.one("draw",function(){c(d.ajax.json())})}if("ssp"==y(a))T(a,b);else{D(a,!0);var e=a.jqXHR;e&&4!==e.readyState&&e.abort();ta(a,[],function(c){pa(a);for(var c=ua(a,c),d=0,e=c.length;d<e;d++)O(a,c[d]);T(a,b);D(a,!1)})}};o("ajax.json()",function(){var a=this.context;if(0<a.length)return a[0].json});o("ajax.params()",function(){var a=this.context;if(0<
|
||||
a.length)return a[0].oAjaxData});o("ajax.reload()",function(a,b){return this.iterator("table",function(c){Ub(c,!1===b,a)})});o("ajax.url()",function(a){var b=this.context;if(a===k){if(0===b.length)return k;b=b[0];return b.ajax?h.isPlainObject(b.ajax)?b.ajax.url:b.ajax:b.sAjaxSource}return this.iterator("table",function(b){h.isPlainObject(b.ajax)?b.ajax.url=a:b.ajax=a})});o("ajax.url().load()",function(a,b){return this.iterator("table",function(c){Ub(c,!1===b,a)})});var bb=function(a,b,c,d,e){var f=
|
||||
[],g,j,i,l,m,n;i=typeof b;if(!b||"string"===i||"function"===i||b.length===k)b=[b];i=0;for(l=b.length;i<l;i++){j=b[i]&&b[i].split&&!b[i].match(/[\[\(:]/)?b[i].split(","):[b[i]];m=0;for(n=j.length;m<n;m++)(g=c("string"===typeof j[m]?h.trim(j[m]):j[m]))&&g.length&&(f=f.concat(g))}a=v.selector[a];if(a.length){i=0;for(l=a.length;i<l;i++)f=a[i](d,e,f)}return ra(f)},cb=function(a){a||(a={});a.filter&&a.search===k&&(a.search=a.filter);return h.extend({search:"none",order:"current",page:"all"},a)},db=function(a){for(var b=
|
||||
0,c=a.length;b<c;b++)if(0<a[b].length)return a[0]=a[b],a[0].length=1,a.length=1,a.context=[a.context[b]],a;a.length=0;return a},Da=function(a,b){var c,d,e,f=[],g=a.aiDisplay;e=a.aiDisplayMaster;var j=b.search;c=b.order;d=b.page;if("ssp"==y(a))return"removed"===j?[]:Z(0,e.length);if("current"==d){c=a._iDisplayStart;for(d=a.fnDisplayEnd();c<d;c++)f.push(g[c])}else if("current"==c||"applied"==c)if("none"==j)f=e.slice();else if("applied"==j)f=g.slice();else{if("removed"==j){var i={};c=0;for(d=g.length;c<
|
||||
d;c++)i[g[c]]=null;f=h.map(e,function(a){return!i.hasOwnProperty(a)?a:null})}}else if("index"==c||"original"==c){c=0;for(d=a.aoData.length;c<d;c++)"none"==j?f.push(c):(e=h.inArray(c,g),(-1===e&&"removed"==j||0<=e&&"applied"==j)&&f.push(c))}return f};o("rows()",function(a,b){a===k?a="":h.isPlainObject(a)&&(b=a,a="");var b=cb(b),c=this.iterator("table",function(c){var e=b,f;return bb("row",a,function(a){var b=Pb(a),i=c.aoData;if(b!==null&&!e)return[b];f||(f=Da(c,e));if(b!==null&&h.inArray(b,f)!==-1)return[b];
|
||||
if(a===null||a===k||a==="")return f;if(typeof a==="function")return h.map(f,function(b){var c=i[b];return a(b,c._aData,c.nTr)?b:null});if(a.nodeName){var b=a._DT_RowIndex,l=a._DT_CellIndex;if(b!==k)return i[b]&&i[b].nTr===a?[b]:[];if(l)return i[l.row]&&i[l.row].nTr===a.parentNode?[l.row]:[];b=h(a).closest("*[data-dt-row]");return b.length?[b.data("dt-row")]:[]}if(typeof a==="string"&&a.charAt(0)==="#"){b=c.aIds[a.replace(/^#/,"")];if(b!==k)return[b.idx]}b=Sb(ka(c.aoData,f,"nTr"));return h(b).filter(a).map(function(){return this._DT_RowIndex}).toArray()},
|
||||
c,e)},1);c.selector.rows=a;c.selector.opts=b;return c});o("rows().nodes()",function(){return this.iterator("row",function(a,b){return a.aoData[b].nTr||k},1)});o("rows().data()",function(){return this.iterator(!0,"rows",function(a,b){return ka(a.aoData,b,"_aData")},1)});s("rows().cache()","row().cache()",function(a){return this.iterator("row",function(b,c){var d=b.aoData[c];return"search"===a?d._aFilterData:d._aSortData},1)});s("rows().invalidate()","row().invalidate()",function(a){return this.iterator("row",
|
||||
function(b,c){ea(b,c,a)})});s("rows().indexes()","row().index()",function(){return this.iterator("row",function(a,b){return b},1)});s("rows().ids()","row().id()",function(a){for(var b=[],c=this.context,d=0,e=c.length;d<e;d++)for(var f=0,g=this[d].length;f<g;f++){var h=c[d].rowIdFn(c[d].aoData[this[d][f]]._aData);b.push((!0===a?"#":"")+h)}return new r(c,b)});s("rows().remove()","row().remove()",function(){var a=this;this.iterator("row",function(b,c,d){var e=b.aoData,f=e[c],g,h,i,l,m;e.splice(c,1);
|
||||
g=0;for(h=e.length;g<h;g++)if(i=e[g],m=i.anCells,null!==i.nTr&&(i.nTr._DT_RowIndex=g),null!==m){i=0;for(l=m.length;i<l;i++)m[i]._DT_CellIndex.row=g}qa(b.aiDisplayMaster,c);qa(b.aiDisplay,c);qa(a[d],c,!1);0<b._iRecordsDisplay&&b._iRecordsDisplay--;Ua(b);c=b.rowIdFn(f._aData);c!==k&&delete b.aIds[c]});this.iterator("table",function(a){for(var c=0,d=a.aoData.length;c<d;c++)a.aoData[c].idx=c});return this});o("rows.add()",function(a){var b=this.iterator("table",function(b){var c,f,g,h=[];f=0;for(g=a.length;f<
|
||||
g;f++)c=a[f],c.nodeName&&"TR"===c.nodeName.toUpperCase()?h.push(oa(b,c)[0]):h.push(O(b,c));return h},1),c=this.rows(-1);c.pop();h.merge(c,b);return c});o("row()",function(a,b){return db(this.rows(a,b))});o("row().data()",function(a){var b=this.context;if(a===k)return b.length&&this.length?b[0].aoData[this[0]]._aData:k;var c=b[0].aoData[this[0]];c._aData=a;h.isArray(a)&&c.nTr.id&&N(b[0].rowId)(a,c.nTr.id);ea(b[0],this[0],"data");return this});o("row().node()",function(){var a=this.context;return a.length&&
|
||||
this.length?a[0].aoData[this[0]].nTr||null:null});o("row.add()",function(a){a instanceof h&&a.length&&(a=a[0]);var b=this.iterator("table",function(b){return a.nodeName&&"TR"===a.nodeName.toUpperCase()?oa(b,a)[0]:O(b,a)});return this.row(b[0])});var eb=function(a,b){var c=a.context;if(c.length&&(c=c[0].aoData[b!==k?b:a[0]])&&c._details)c._details.remove(),c._detailsShow=k,c._details=k},Vb=function(a,b){var c=a.context;if(c.length&&a.length){var d=c[0].aoData[a[0]];if(d._details){(d._detailsShow=b)?
|
||||
d._details.insertAfter(d.nTr):d._details.detach();var e=c[0],f=new r(e),g=e.aoData;f.off("draw.dt.DT_details column-visibility.dt.DT_details destroy.dt.DT_details");0<C(g,"_details").length&&(f.on("draw.dt.DT_details",function(a,b){e===b&&f.rows({page:"current"}).eq(0).each(function(a){a=g[a];a._detailsShow&&a._details.insertAfter(a.nTr)})}),f.on("column-visibility.dt.DT_details",function(a,b){if(e===b)for(var c,d=W(b),f=0,h=g.length;f<h;f++)c=g[f],c._details&&c._details.children("td[colspan]").attr("colspan",
|
||||
d)}),f.on("destroy.dt.DT_details",function(a,b){if(e===b)for(var c=0,d=g.length;c<d;c++)g[c]._details&&eb(f,c)}))}}};o("row().child()",function(a,b){var c=this.context;if(a===k)return c.length&&this.length?c[0].aoData[this[0]]._details:k;if(!0===a)this.child.show();else if(!1===a)eb(this);else if(c.length&&this.length){var d=c[0],c=c[0].aoData[this[0]],e=[],f=function(a,b){if(h.isArray(a)||a instanceof h)for(var c=0,k=a.length;c<k;c++)f(a[c],b);else a.nodeName&&"tr"===a.nodeName.toLowerCase()?e.push(a):
|
||||
(c=h("<tr><td/></tr>").addClass(b),h("td",c).addClass(b).html(a)[0].colSpan=W(d),e.push(c[0]))};f(a,b);c._details&&c._details.detach();c._details=h(e);c._detailsShow&&c._details.insertAfter(c.nTr)}return this});o(["row().child.show()","row().child().show()"],function(){Vb(this,!0);return this});o(["row().child.hide()","row().child().hide()"],function(){Vb(this,!1);return this});o(["row().child.remove()","row().child().remove()"],function(){eb(this);return this});o("row().child.isShown()",function(){var a=
|
||||
this.context;return a.length&&this.length?a[0].aoData[this[0]]._detailsShow||!1:!1});var cc=/^([^:]+):(name|visIdx|visible)$/,Wb=function(a,b,c,d,e){for(var c=[],d=0,f=e.length;d<f;d++)c.push(B(a,e[d],b));return c};o("columns()",function(a,b){a===k?a="":h.isPlainObject(a)&&(b=a,a="");var b=cb(b),c=this.iterator("table",function(c){var e=a,f=b,g=c.aoColumns,j=C(g,"sName"),i=C(g,"nTh");return bb("column",e,function(a){var b=Pb(a);if(a==="")return Z(g.length);if(b!==null)return[b>=0?b:g.length+b];if(typeof a===
|
||||
"function"){var e=Da(c,f);return h.map(g,function(b,f){return a(f,Wb(c,f,0,0,e),i[f])?f:null})}var k=typeof a==="string"?a.match(cc):"";if(k)switch(k[2]){case "visIdx":case "visible":b=parseInt(k[1],10);if(b<0){var n=h.map(g,function(a,b){return a.bVisible?b:null});return[n[n.length+b]]}return[ba(c,b)];case "name":return h.map(j,function(a,b){return a===k[1]?b:null});default:return[]}if(a.nodeName&&a._DT_CellIndex)return[a._DT_CellIndex.column];b=h(i).filter(a).map(function(){return h.inArray(this,
|
||||
i)}).toArray();if(b.length||!a.nodeName)return b;b=h(a).closest("*[data-dt-column]");return b.length?[b.data("dt-column")]:[]},c,f)},1);c.selector.cols=a;c.selector.opts=b;return c});s("columns().header()","column().header()",function(){return this.iterator("column",function(a,b){return a.aoColumns[b].nTh},1)});s("columns().footer()","column().footer()",function(){return this.iterator("column",function(a,b){return a.aoColumns[b].nTf},1)});s("columns().data()","column().data()",function(){return this.iterator("column-rows",
|
||||
Wb,1)});s("columns().dataSrc()","column().dataSrc()",function(){return this.iterator("column",function(a,b){return a.aoColumns[b].mData},1)});s("columns().cache()","column().cache()",function(a){return this.iterator("column-rows",function(b,c,d,e,f){return ka(b.aoData,f,"search"===a?"_aFilterData":"_aSortData",c)},1)});s("columns().nodes()","column().nodes()",function(){return this.iterator("column-rows",function(a,b,c,d,e){return ka(a.aoData,e,"anCells",b)},1)});s("columns().visible()","column().visible()",
|
||||
function(a,b){var c=this,d=this.iterator("column",function(b,c){if(a===k)return b.aoColumns[c].bVisible;var d=b.aoColumns,j=d[c],i=b.aoData,l,m,n;if(a!==k&&j.bVisible!==a){if(a){var o=h.inArray(!0,C(d,"bVisible"),c+1);l=0;for(m=i.length;l<m;l++)n=i[l].nTr,d=i[l].anCells,n&&n.insertBefore(d[c],d[o]||null)}else h(C(b.aoData,"anCells",c)).detach();j.bVisible=a}});a!==k&&this.iterator("table",function(d){ga(d,d.aoHeader);ga(d,d.aoFooter);d.aiDisplay.length||h(d.nTBody).find("td[colspan]").attr("colspan",
|
||||
W(d));za(d);c.iterator("column",function(c,d){t(c,null,"column-visibility",[c,d,a,b])});(b===k||b)&&c.columns.adjust()});return d});s("columns().indexes()","column().index()",function(a){return this.iterator("column",function(b,c){return"visible"===a?ca(b,c):c},1)});o("columns.adjust()",function(){return this.iterator("table",function(a){aa(a)},1)});o("column.index()",function(a,b){if(0!==this.context.length){var c=this.context[0];if("fromVisible"===a||"toData"===a)return ba(c,b);if("fromData"===
|
||||
a||"toVisible"===a)return ca(c,b)}});o("column()",function(a,b){return db(this.columns(a,b))});o("cells()",function(a,b,c){h.isPlainObject(a)&&(a.row===k?(c=a,a=null):(c=b,b=null));h.isPlainObject(b)&&(c=b,b=null);if(null===b||b===k)return this.iterator("table",function(b){var d=a,e=cb(c),f=b.aoData,g=Da(b,e),j=Sb(ka(f,g,"anCells")),i=h([].concat.apply([],j)),l,n=b.aoColumns.length,o,s,r,t,w,v;return bb("cell",d,function(a){var c=typeof a==="function";if(a===null||a===k||c){o=[];s=0;for(r=g.length;s<
|
||||
r;s++){l=g[s];for(t=0;t<n;t++){w={row:l,column:t};if(c){v=f[l];a(w,B(b,l,t),v.anCells?v.anCells[t]:null)&&o.push(w)}else o.push(w)}}return o}if(h.isPlainObject(a))return a.column!==k&&a.row!==k&&h.inArray(a.row,g)!==-1?[a]:[];c=i.filter(a).map(function(a,b){return{row:b._DT_CellIndex.row,column:b._DT_CellIndex.column}}).toArray();if(c.length||!a.nodeName)return c;v=h(a).closest("*[data-dt-row]");return v.length?[{row:v.data("dt-row"),column:v.data("dt-column")}]:[]},b,e)});var d=c?{page:c.page,order:c.order,
|
||||
search:c.search}:{},e=this.columns(b,d),f=this.rows(a,d),g,j,i,l,d=this.iterator("table",function(a,b){var c=[];g=0;for(j=f[b].length;g<j;g++){i=0;for(l=e[b].length;i<l;i++)c.push({row:f[b][g],column:e[b][i]})}return c},1),d=c&&c.selected?this.cells(d,c):d;h.extend(d.selector,{cols:b,rows:a,opts:c});return d});s("cells().nodes()","cell().node()",function(){return this.iterator("cell",function(a,b,c){return(a=a.aoData[b])&&a.anCells?a.anCells[c]:k},1)});o("cells().data()",function(){return this.iterator("cell",
|
||||
function(a,b,c){return B(a,b,c)},1)});s("cells().cache()","cell().cache()",function(a){a="search"===a?"_aFilterData":"_aSortData";return this.iterator("cell",function(b,c,d){return b.aoData[c][a][d]},1)});s("cells().render()","cell().render()",function(a){return this.iterator("cell",function(b,c,d){return B(b,c,d,a)},1)});s("cells().indexes()","cell().index()",function(){return this.iterator("cell",function(a,b,c){return{row:b,column:c,columnVisible:ca(a,c)}},1)});s("cells().invalidate()","cell().invalidate()",
|
||||
function(a){return this.iterator("cell",function(b,c,d){ea(b,c,a,d)})});o("cell()",function(a,b,c){return db(this.cells(a,b,c))});o("cell().data()",function(a){var b=this.context,c=this[0];if(a===k)return b.length&&c.length?B(b[0],c[0].row,c[0].column):k;lb(b[0],c[0].row,c[0].column,a);ea(b[0],c[0].row,"data",c[0].column);return this});o("order()",function(a,b){var c=this.context;if(a===k)return 0!==c.length?c[0].aaSorting:k;"number"===typeof a?a=[[a,b]]:a.length&&!h.isArray(a[0])&&(a=Array.prototype.slice.call(arguments));
|
||||
return this.iterator("table",function(b){b.aaSorting=a.slice()})});o("order.listener()",function(a,b,c){return this.iterator("table",function(d){Oa(d,a,b,c)})});o("order.fixed()",function(a){if(!a){var b=this.context,b=b.length?b[0].aaSortingFixed:k;return h.isArray(b)?{pre:b}:b}return this.iterator("table",function(b){b.aaSortingFixed=h.extend(!0,{},a)})});o(["columns().order()","column().order()"],function(a){var b=this;return this.iterator("table",function(c,d){var e=[];h.each(b[d],function(b,
|
||||
c){e.push([c,a])});c.aaSorting=e})});o("search()",function(a,b,c,d){var e=this.context;return a===k?0!==e.length?e[0].oPreviousSearch.sSearch:k:this.iterator("table",function(e){e.oFeatures.bFilter&&ha(e,h.extend({},e.oPreviousSearch,{sSearch:a+"",bRegex:null===b?!1:b,bSmart:null===c?!0:c,bCaseInsensitive:null===d?!0:d}),1)})});s("columns().search()","column().search()",function(a,b,c,d){return this.iterator("column",function(e,f){var g=e.aoPreSearchCols;if(a===k)return g[f].sSearch;e.oFeatures.bFilter&&
|
||||
(h.extend(g[f],{sSearch:a+"",bRegex:null===b?!1:b,bSmart:null===c?!0:c,bCaseInsensitive:null===d?!0:d}),ha(e,e.oPreviousSearch,1))})});o("state()",function(){return this.context.length?this.context[0].oSavedState:null});o("state.clear()",function(){return this.iterator("table",function(a){a.fnStateSaveCallback.call(a.oInstance,a,{})})});o("state.loaded()",function(){return this.context.length?this.context[0].oLoadedState:null});o("state.save()",function(){return this.iterator("table",function(a){za(a)})});
|
||||
n.versionCheck=n.fnVersionCheck=function(a){for(var b=n.version.split("."),a=a.split("."),c,d,e=0,f=a.length;e<f;e++)if(c=parseInt(b[e],10)||0,d=parseInt(a[e],10)||0,c!==d)return c>d;return!0};n.isDataTable=n.fnIsDataTable=function(a){var b=h(a).get(0),c=!1;if(a instanceof n.Api)return!0;h.each(n.settings,function(a,e){var f=e.nScrollHead?h("table",e.nScrollHead)[0]:null,g=e.nScrollFoot?h("table",e.nScrollFoot)[0]:null;if(e.nTable===b||f===b||g===b)c=!0});return c};n.tables=n.fnTables=function(a){var b=
|
||||
!1;h.isPlainObject(a)&&(b=a.api,a=a.visible);var c=h.map(n.settings,function(b){if(!a||a&&h(b.nTable).is(":visible"))return b.nTable});return b?new r(c):c};n.camelToHungarian=J;o("$()",function(a,b){var c=this.rows(b).nodes(),c=h(c);return h([].concat(c.filter(a).toArray(),c.find(a).toArray()))});h.each(["on","one","off"],function(a,b){o(b+"()",function(){var a=Array.prototype.slice.call(arguments);a[0]=h.map(a[0].split(/\s/),function(a){return!a.match(/\.dt\b/)?a+".dt":a}).join(" ");var d=h(this.tables().nodes());
|
||||
d[b].apply(d,a);return this})});o("clear()",function(){return this.iterator("table",function(a){pa(a)})});o("settings()",function(){return new r(this.context,this.context)});o("init()",function(){var a=this.context;return a.length?a[0].oInit:null});o("data()",function(){return this.iterator("table",function(a){return C(a.aoData,"_aData")}).flatten()});o("destroy()",function(a){a=a||!1;return this.iterator("table",function(b){var c=b.nTableWrapper.parentNode,d=b.oClasses,e=b.nTable,f=b.nTBody,g=b.nTHead,
|
||||
j=b.nTFoot,i=h(e),f=h(f),k=h(b.nTableWrapper),m=h.map(b.aoData,function(a){return a.nTr}),o;b.bDestroying=!0;t(b,"aoDestroyCallback","destroy",[b]);a||(new r(b)).columns().visible(!0);k.off(".DT").find(":not(tbody *)").off(".DT");h(E).off(".DT-"+b.sInstance);e!=g.parentNode&&(i.children("thead").detach(),i.append(g));j&&e!=j.parentNode&&(i.children("tfoot").detach(),i.append(j));b.aaSorting=[];b.aaSortingFixed=[];ya(b);h(m).removeClass(b.asStripeClasses.join(" "));h("th, td",g).removeClass(d.sSortable+
|
||||
" "+d.sSortableAsc+" "+d.sSortableDesc+" "+d.sSortableNone);f.children().detach();f.append(m);g=a?"remove":"detach";i[g]();k[g]();!a&&c&&(c.insertBefore(e,b.nTableReinsertBefore),i.css("width",b.sDestroyWidth).removeClass(d.sTable),(o=b.asDestroyStripes.length)&&f.children().each(function(a){h(this).addClass(b.asDestroyStripes[a%o])}));c=h.inArray(b,n.settings);-1!==c&&n.settings.splice(c,1)})});h.each(["column","row","cell"],function(a,b){o(b+"s().every()",function(a){var d=this.selector.opts,e=
|
||||
this;return this.iterator(b,function(f,g,h,i,l){a.call(e[b](g,"cell"===b?h:d,"cell"===b?d:k),g,h,i,l)})})});o("i18n()",function(a,b,c){var d=this.context[0],a=S(a)(d.oLanguage);a===k&&(a=b);c!==k&&h.isPlainObject(a)&&(a=a[c]!==k?a[c]:a._);return a.replace("%d",c)});n.version="1.10.20";n.settings=[];n.models={};n.models.oSearch={bCaseInsensitive:!0,sSearch:"",bRegex:!1,bSmart:!0};n.models.oRow={nTr:null,anCells:null,_aData:[],_aSortData:null,_aFilterData:null,_sFilterRow:null,_sRowStripe:"",src:null,
|
||||
idx:-1};n.models.oColumn={idx:null,aDataSort:null,asSorting:null,bSearchable:null,bSortable:null,bVisible:null,_sManualType:null,_bAttrSrc:!1,fnCreatedCell:null,fnGetData:null,fnSetData:null,mData:null,mRender:null,nTh:null,nTf:null,sClass:null,sContentPadding:null,sDefaultContent:null,sName:null,sSortDataType:"std",sSortingClass:null,sSortingClassJUI:null,sTitle:null,sType:null,sWidth:null,sWidthOrig:null};n.defaults={aaData:null,aaSorting:[[0,"asc"]],aaSortingFixed:[],ajax:null,aLengthMenu:[10,
|
||||
25,50,100],aoColumns:null,aoColumnDefs:null,aoSearchCols:[],asStripeClasses:null,bAutoWidth:!0,bDeferRender:!1,bDestroy:!1,bFilter:!0,bInfo:!0,bLengthChange:!0,bPaginate:!0,bProcessing:!1,bRetrieve:!1,bScrollCollapse:!1,bServerSide:!1,bSort:!0,bSortMulti:!0,bSortCellsTop:!1,bSortClasses:!0,bStateSave:!1,fnCreatedRow:null,fnDrawCallback:null,fnFooterCallback:null,fnFormatNumber:function(a){return a.toString().replace(/\B(?=(\d{3})+(?!\d))/g,this.oLanguage.sThousands)},fnHeaderCallback:null,fnInfoCallback:null,
|
||||
fnInitComplete:null,fnPreDrawCallback:null,fnRowCallback:null,fnServerData:null,fnServerParams:null,fnStateLoadCallback:function(a){try{return JSON.parse((-1===a.iStateDuration?sessionStorage:localStorage).getItem("DataTables_"+a.sInstance+"_"+location.pathname))}catch(b){}},fnStateLoadParams:null,fnStateLoaded:null,fnStateSaveCallback:function(a,b){try{(-1===a.iStateDuration?sessionStorage:localStorage).setItem("DataTables_"+a.sInstance+"_"+location.pathname,JSON.stringify(b))}catch(c){}},fnStateSaveParams:null,
|
||||
iStateDuration:7200,iDeferLoading:null,iDisplayLength:10,iDisplayStart:0,iTabIndex:0,oClasses:{},oLanguage:{oAria:{sSortAscending:": activate to sort column ascending",sSortDescending:": activate to sort column descending"},oPaginate:{sFirst:"First",sLast:"Last",sNext:"Next",sPrevious:"Previous"},sEmptyTable:"No data available in table",sInfo:"Showing _START_ to _END_ of _TOTAL_ entries",sInfoEmpty:"Showing 0 to 0 of 0 entries",sInfoFiltered:"(filtered from _MAX_ total entries)",sInfoPostFix:"",sDecimal:"",
|
||||
sThousands:",",sLengthMenu:"Show _MENU_ entries",sLoadingRecords:"Loading...",sProcessing:"Processing...",sSearch:"Search:",sSearchPlaceholder:"",sUrl:"",sZeroRecords:"No matching records found"},oSearch:h.extend({},n.models.oSearch),sAjaxDataProp:"data",sAjaxSource:null,sDom:"lfrtip",searchDelay:null,sPaginationType:"simple_numbers",sScrollX:"",sScrollXInner:"",sScrollY:"",sServerMethod:"GET",renderer:null,rowId:"DT_RowId"};$(n.defaults);n.defaults.column={aDataSort:null,iDataSort:-1,asSorting:["asc",
|
||||
"desc"],bSearchable:!0,bSortable:!0,bVisible:!0,fnCreatedCell:null,mData:null,mRender:null,sCellType:"td",sClass:"",sContentPadding:"",sDefaultContent:null,sName:"",sSortDataType:"std",sTitle:null,sType:null,sWidth:null};$(n.defaults.column);n.models.oSettings={oFeatures:{bAutoWidth:null,bDeferRender:null,bFilter:null,bInfo:null,bLengthChange:null,bPaginate:null,bProcessing:null,bServerSide:null,bSort:null,bSortMulti:null,bSortClasses:null,bStateSave:null},oScroll:{bCollapse:null,iBarWidth:0,sX:null,
|
||||
sXInner:null,sY:null},oLanguage:{fnInfoCallback:null},oBrowser:{bScrollOversize:!1,bScrollbarLeft:!1,bBounding:!1,barWidth:0},ajax:null,aanFeatures:[],aoData:[],aiDisplay:[],aiDisplayMaster:[],aIds:{},aoColumns:[],aoHeader:[],aoFooter:[],oPreviousSearch:{},aoPreSearchCols:[],aaSorting:null,aaSortingFixed:[],asStripeClasses:null,asDestroyStripes:[],sDestroyWidth:0,aoRowCallback:[],aoHeaderCallback:[],aoFooterCallback:[],aoDrawCallback:[],aoRowCreatedCallback:[],aoPreDrawCallback:[],aoInitComplete:[],
|
||||
aoStateSaveParams:[],aoStateLoadParams:[],aoStateLoaded:[],sTableId:"",nTable:null,nTHead:null,nTFoot:null,nTBody:null,nTableWrapper:null,bDeferLoading:!1,bInitialised:!1,aoOpenRows:[],sDom:null,searchDelay:null,sPaginationType:"two_button",iStateDuration:0,aoStateSave:[],aoStateLoad:[],oSavedState:null,oLoadedState:null,sAjaxSource:null,sAjaxDataProp:null,bAjaxDataGet:!0,jqXHR:null,json:k,oAjaxData:k,fnServerData:null,aoServerParams:[],sServerMethod:null,fnFormatNumber:null,aLengthMenu:null,iDraw:0,
|
||||
bDrawing:!1,iDrawError:-1,_iDisplayLength:10,_iDisplayStart:0,_iRecordsTotal:0,_iRecordsDisplay:0,oClasses:{},bFiltered:!1,bSorted:!1,bSortCellsTop:null,oInit:null,aoDestroyCallback:[],fnRecordsTotal:function(){return"ssp"==y(this)?1*this._iRecordsTotal:this.aiDisplayMaster.length},fnRecordsDisplay:function(){return"ssp"==y(this)?1*this._iRecordsDisplay:this.aiDisplay.length},fnDisplayEnd:function(){var a=this._iDisplayLength,b=this._iDisplayStart,c=b+a,d=this.aiDisplay.length,e=this.oFeatures,f=
|
||||
e.bPaginate;return e.bServerSide?!1===f||-1===a?b+d:Math.min(b+a,this._iRecordsDisplay):!f||c>d||-1===a?d:c},oInstance:null,sInstance:null,iTabIndex:0,nScrollHead:null,nScrollFoot:null,aLastSort:[],oPlugins:{},rowIdFn:null,rowId:null};n.ext=v={buttons:{},classes:{},builder:"-source-",errMode:"alert",feature:[],search:[],selector:{cell:[],column:[],row:[]},internal:{},legacy:{ajax:null},pager:{},renderer:{pageButton:{},header:{}},order:{},type:{detect:[],search:{},order:{}},_unique:0,fnVersionCheck:n.fnVersionCheck,
|
||||
iApiIndex:0,oJUIClasses:{},sVersion:n.version};h.extend(v,{afnFiltering:v.search,aTypes:v.type.detect,ofnSearch:v.type.search,oSort:v.type.order,afnSortData:v.order,aoFeatures:v.feature,oApi:v.internal,oStdClasses:v.classes,oPagination:v.pager});h.extend(n.ext.classes,{sTable:"dataTable",sNoFooter:"no-footer",sPageButton:"paginate_button",sPageButtonActive:"current",sPageButtonDisabled:"disabled",sStripeOdd:"odd",sStripeEven:"even",sRowEmpty:"dataTables_empty",sWrapper:"dataTables_wrapper",sFilter:"dataTables_filter",
|
||||
sInfo:"dataTables_info",sPaging:"dataTables_paginate paging_",sLength:"dataTables_length",sProcessing:"dataTables_processing",sSortAsc:"sorting_asc",sSortDesc:"sorting_desc",sSortable:"sorting",sSortableAsc:"sorting_asc_disabled",sSortableDesc:"sorting_desc_disabled",sSortableNone:"sorting_disabled",sSortColumn:"sorting_",sFilterInput:"",sLengthSelect:"",sScrollWrapper:"dataTables_scroll",sScrollHead:"dataTables_scrollHead",sScrollHeadInner:"dataTables_scrollHeadInner",sScrollBody:"dataTables_scrollBody",
|
||||
sScrollFoot:"dataTables_scrollFoot",sScrollFootInner:"dataTables_scrollFootInner",sHeaderTH:"",sFooterTH:"",sSortJUIAsc:"",sSortJUIDesc:"",sSortJUI:"",sSortJUIAscAllowed:"",sSortJUIDescAllowed:"",sSortJUIWrapper:"",sSortIcon:"",sJUIHeader:"",sJUIFooter:""});var Mb=n.ext.pager;h.extend(Mb,{simple:function(){return["previous","next"]},full:function(){return["first","previous","next","last"]},numbers:function(a,b){return[ja(a,b)]},simple_numbers:function(a,b){return["previous",ja(a,b),"next"]},full_numbers:function(a,
|
||||
b){return["first","previous",ja(a,b),"next","last"]},first_last_numbers:function(a,b){return["first",ja(a,b),"last"]},_numbers:ja,numbers_length:7});h.extend(!0,n.ext.renderer,{pageButton:{_:function(a,b,c,d,e,f){var g=a.oClasses,j=a.oLanguage.oPaginate,i=a.oLanguage.oAria.paginate||{},l,m,n=0,o=function(b,d){var k,s,r,t,v=g.sPageButtonDisabled,w=function(b){Va(a,b.data.action,true)};k=0;for(s=d.length;k<s;k++){t=d[k];if(h.isArray(t)){r=h("<"+(t.DT_el||"div")+"/>").appendTo(b);o(r,t)}else{l=null;
|
||||
m=t;r=a.iTabIndex;switch(t){case "ellipsis":b.append('<span class="ellipsis">…</span>');break;case "first":l=j.sFirst;if(e===0){r=-1;m=m+(" "+v)}break;case "previous":l=j.sPrevious;if(e===0){r=-1;m=m+(" "+v)}break;case "next":l=j.sNext;if(e===f-1){r=-1;m=m+(" "+v)}break;case "last":l=j.sLast;if(e===f-1){r=-1;m=m+(" "+v)}break;default:l=t+1;m=e===t?g.sPageButtonActive:""}if(l!==null){r=h("<a>",{"class":g.sPageButton+" "+m,"aria-controls":a.sTableId,"aria-label":i[t],"data-dt-idx":n,tabindex:r,
|
||||
id:c===0&&typeof t==="string"?a.sTableId+"_"+t:null}).html(l).appendTo(b);Xa(r,{action:t},w);n++}}}},s;try{s=h(b).find(H.activeElement).data("dt-idx")}catch(r){}o(h(b).empty(),d);s!==k&&h(b).find("[data-dt-idx="+s+"]").focus()}}});h.extend(n.ext.type.detect,[function(a,b){var c=b.oLanguage.sDecimal;return ab(a,c)?"num"+c:null},function(a){if(a&&!(a instanceof Date)&&!$b.test(a))return null;var b=Date.parse(a);return null!==b&&!isNaN(b)||M(a)?"date":null},function(a,b){var c=b.oLanguage.sDecimal;return ab(a,
|
||||
c,!0)?"num-fmt"+c:null},function(a,b){var c=b.oLanguage.sDecimal;return Rb(a,c)?"html-num"+c:null},function(a,b){var c=b.oLanguage.sDecimal;return Rb(a,c,!0)?"html-num-fmt"+c:null},function(a){return M(a)||"string"===typeof a&&-1!==a.indexOf("<")?"html":null}]);h.extend(n.ext.type.search,{html:function(a){return M(a)?a:"string"===typeof a?a.replace(Ob," ").replace(Ca,""):""},string:function(a){return M(a)?a:"string"===typeof a?a.replace(Ob," "):a}});var Ba=function(a,b,c,d){if(0!==a&&(!a||"-"===a))return-Infinity;
|
||||
b&&(a=Qb(a,b));a.replace&&(c&&(a=a.replace(c,"")),d&&(a=a.replace(d,"")));return 1*a};h.extend(v.type.order,{"date-pre":function(a){a=Date.parse(a);return isNaN(a)?-Infinity:a},"html-pre":function(a){return M(a)?"":a.replace?a.replace(/<.*?>/g,"").toLowerCase():a+""},"string-pre":function(a){return M(a)?"":"string"===typeof a?a.toLowerCase():!a.toString?"":a.toString()},"string-asc":function(a,b){return a<b?-1:a>b?1:0},"string-desc":function(a,b){return a<b?1:a>b?-1:0}});Fa("");h.extend(!0,n.ext.renderer,
|
||||
{header:{_:function(a,b,c,d){h(a.nTable).on("order.dt.DT",function(e,f,g,h){if(a===f){e=c.idx;b.removeClass(c.sSortingClass+" "+d.sSortAsc+" "+d.sSortDesc).addClass(h[e]=="asc"?d.sSortAsc:h[e]=="desc"?d.sSortDesc:c.sSortingClass)}})},jqueryui:function(a,b,c,d){h("<div/>").addClass(d.sSortJUIWrapper).append(b.contents()).append(h("<span/>").addClass(d.sSortIcon+" "+c.sSortingClassJUI)).appendTo(b);h(a.nTable).on("order.dt.DT",function(e,f,g,h){if(a===f){e=c.idx;b.removeClass(d.sSortAsc+" "+d.sSortDesc).addClass(h[e]==
|
||||
"asc"?d.sSortAsc:h[e]=="desc"?d.sSortDesc:c.sSortingClass);b.find("span."+d.sSortIcon).removeClass(d.sSortJUIAsc+" "+d.sSortJUIDesc+" "+d.sSortJUI+" "+d.sSortJUIAscAllowed+" "+d.sSortJUIDescAllowed).addClass(h[e]=="asc"?d.sSortJUIAsc:h[e]=="desc"?d.sSortJUIDesc:c.sSortingClassJUI)}})}}});var fb=function(a){return"string"===typeof a?a.replace(/</g,"<").replace(/>/g,">").replace(/"/g,"""):a};n.render={number:function(a,b,c,d,e){return{display:function(f){if("number"!==typeof f&&"string"!==
|
||||
typeof f)return f;var g=0>f?"-":"",h=parseFloat(f);if(isNaN(h))return fb(f);h=h.toFixed(c);f=Math.abs(h);h=parseInt(f,10);f=c?b+(f-h).toFixed(c).substring(2):"";return g+(d||"")+h.toString().replace(/\B(?=(\d{3})+(?!\d))/g,a)+f+(e||"")}}},text:function(){return{display:fb,filter:fb}}};h.extend(n.ext.internal,{_fnExternApiFunc:Nb,_fnBuildAjax:ta,_fnAjaxUpdate:nb,_fnAjaxParameters:wb,_fnAjaxUpdateDraw:xb,_fnAjaxDataSrc:ua,_fnAddColumn:Ga,_fnColumnOptions:la,_fnAdjustColumnSizing:aa,_fnVisibleToColumnIndex:ba,
|
||||
_fnColumnIndexToVisible:ca,_fnVisbleColumns:W,_fnGetColumns:na,_fnColumnTypes:Ia,_fnApplyColumnDefs:kb,_fnHungarianMap:$,_fnCamelToHungarian:J,_fnLanguageCompat:Ea,_fnBrowserDetect:ib,_fnAddData:O,_fnAddTr:oa,_fnNodeToDataIndex:function(a,b){return b._DT_RowIndex!==k?b._DT_RowIndex:null},_fnNodeToColumnIndex:function(a,b,c){return h.inArray(c,a.aoData[b].anCells)},_fnGetCellData:B,_fnSetCellData:lb,_fnSplitObjNotation:La,_fnGetObjectDataFn:S,_fnSetObjectDataFn:N,_fnGetDataMaster:Ma,_fnClearTable:pa,
|
||||
_fnDeleteIndex:qa,_fnInvalidate:ea,_fnGetRowElements:Ka,_fnCreateTr:Ja,_fnBuildHead:mb,_fnDrawHead:ga,_fnDraw:P,_fnReDraw:T,_fnAddOptionsHtml:pb,_fnDetectHeader:fa,_fnGetUniqueThs:sa,_fnFeatureHtmlFilter:rb,_fnFilterComplete:ha,_fnFilterCustom:Ab,_fnFilterColumn:zb,_fnFilter:yb,_fnFilterCreateSearch:Ra,_fnEscapeRegex:Sa,_fnFilterData:Bb,_fnFeatureHtmlInfo:ub,_fnUpdateInfo:Eb,_fnInfoMacros:Fb,_fnInitialise:ia,_fnInitComplete:va,_fnLengthChange:Ta,_fnFeatureHtmlLength:qb,_fnFeatureHtmlPaginate:vb,_fnPageChange:Va,
|
||||
_fnFeatureHtmlProcessing:sb,_fnProcessingDisplay:D,_fnFeatureHtmlTable:tb,_fnScrollDraw:ma,_fnApplyToChildren:I,_fnCalculateColumnWidths:Ha,_fnThrottle:Qa,_fnConvertToWidth:Gb,_fnGetWidestNode:Hb,_fnGetMaxLenString:Ib,_fnStringToCss:w,_fnSortFlatten:Y,_fnSort:ob,_fnSortAria:Kb,_fnSortListener:Wa,_fnSortAttachListener:Oa,_fnSortingClasses:ya,_fnSortData:Jb,_fnSaveState:za,_fnLoadState:Lb,_fnSettingsFromNode:Aa,_fnLog:K,_fnMap:F,_fnBindAction:Xa,_fnCallbackReg:z,_fnCallbackFire:t,_fnLengthOverflow:Ua,
|
||||
_fnRenderer:Pa,_fnDataSource:y,_fnRowAttributes:Na,_fnExtend:Ya,_fnCalculateEnd:function(){}});h.fn.dataTable=n;n.$=h;h.fn.dataTableSettings=n.settings;h.fn.dataTableExt=n.ext;h.fn.DataTable=function(a){return h(this).dataTable(a).api()};h.each(n,function(a,b){h.fn.DataTable[a]=b});return h.fn.dataTable});
|
||||
27
modules/import_api/views/js/front.js
Normal file
27
modules/import_api/views/js/front.js
Normal file
@@ -0,0 +1,27 @@
|
||||
/**
|
||||
* 2007-2018 PrestaShop
|
||||
*
|
||||
* NOTICE OF LICENSE
|
||||
*
|
||||
* This source file is subject to the Academic Free License (AFL 3.0)
|
||||
* that is bundled with this package in the file LICENSE.txt.
|
||||
* It is also available through the world-wide-web at this URL:
|
||||
* http://opensource.org/licenses/afl-3.0.php
|
||||
* If you did not receive a copy of the license and are unable to
|
||||
* obtain it through the world-wide-web, please send an email
|
||||
* to license@prestashop.com so we can send you a copy immediately.
|
||||
*
|
||||
* DISCLAIMER
|
||||
*
|
||||
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
|
||||
* versions in the future. If you wish to customize PrestaShop for your
|
||||
* needs please refer to http://www.prestashop.com for more information.
|
||||
*
|
||||
* @author PrestaShop SA <contact@prestashop.com>
|
||||
* @copyright 2007-2018 PrestaShop SA
|
||||
* @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0)
|
||||
* International Registered Trademark & Property of PrestaShop SA
|
||||
*
|
||||
* Don't forget to prefix your containers with your own identifier
|
||||
* to avoid any conflicts with others containers.
|
||||
*/
|
||||
35
modules/import_api/views/js/index.php
Normal file
35
modules/import_api/views/js/index.php
Normal file
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
/**
|
||||
* 2007-2018 PrestaShop
|
||||
*
|
||||
* NOTICE OF LICENSE
|
||||
*
|
||||
* This source file is subject to the Academic Free License (AFL 3.0)
|
||||
* that is bundled with this package in the file LICENSE.txt.
|
||||
* It is also available through the world-wide-web at this URL:
|
||||
* http://opensource.org/licenses/afl-3.0.php
|
||||
* If you did not receive a copy of the license and are unable to
|
||||
* obtain it through the world-wide-web, please send an email
|
||||
* to license@prestashop.com so we can send you a copy immediately.
|
||||
*
|
||||
* DISCLAIMER
|
||||
*
|
||||
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
|
||||
* versions in the future. If you wish to customize PrestaShop for your
|
||||
* needs please refer to http://www.prestashop.com for more information.
|
||||
*
|
||||
* @author PrestaShop SA <contact@prestashop.com>
|
||||
* @copyright 2007-2018 PrestaShop SA
|
||||
* @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0)
|
||||
* International Registered Trademark & Property of PrestaShop SA
|
||||
*/
|
||||
|
||||
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;
|
||||
87
modules/import_api/views/templates/admin/configure.tpl
Normal file
87
modules/import_api/views/templates/admin/configure.tpl
Normal file
@@ -0,0 +1,87 @@
|
||||
{*
|
||||
* 2007-2018 PrestaShop
|
||||
*
|
||||
* NOTICE OF LICENSE
|
||||
*
|
||||
* This source file is subject to the Academic Free License (AFL 3.0)
|
||||
* that is bundled with this package in the file LICENSE.txt.
|
||||
* It is also available through the world-wide-web at this URL:
|
||||
* http://opensource.org/licenses/afl-3.0.php
|
||||
* If you did not receive a copy of the license and are unable to
|
||||
* obtain it through the world-wide-web, please send an email
|
||||
* to license@prestashop.com so we can send you a copy immediately.
|
||||
*
|
||||
* DISCLAIMER
|
||||
*
|
||||
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
|
||||
* versions in the future. If you wish to customize PrestaShop for your
|
||||
* needs please refer to http://www.prestashop.com for more information.
|
||||
*
|
||||
* @author PrestaShop SA <contact@prestashop.com>
|
||||
* @copyright 2007-2018 PrestaShop SA
|
||||
* @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0)
|
||||
* International Registered Trademark & Property of PrestaShop SA
|
||||
*}
|
||||
|
||||
|
||||
|
||||
<div class="panel" id="tab-general">
|
||||
<p>Source: {$file_name}</p>
|
||||
<div style="min-height:20px">
|
||||
<p id="api-loader" style="display:none"> Please wait while module read file
|
||||
<span class="hidden-xs" >
|
||||
<i class="icon-refresh icon-spin icon-fw"></i>
|
||||
</span>
|
||||
</p>
|
||||
</div>
|
||||
<button id="reload-fields">Reload file</button>
|
||||
<a class="pull-right" href="{$import_link}">Go to import page</a>
|
||||
</div>
|
||||
<script type="text/javascript">
|
||||
function find_fields() {
|
||||
$.ajax({
|
||||
url: '{$get_fields_link}',
|
||||
type: 'post',
|
||||
data: $('#tab-general :input'),
|
||||
dataType: 'json',
|
||||
beforeSend: function() {
|
||||
$('#api-loader').show();
|
||||
$('#configuration_form').hide();
|
||||
$('#reload-fields').button('loading');
|
||||
|
||||
},
|
||||
complete: function() {
|
||||
$('#api-loader').hide();
|
||||
$('#configuration_form').show();
|
||||
$('#reload-fields').button('reset');
|
||||
},
|
||||
success: function(json) {
|
||||
if(json['error']){
|
||||
alert(json['error']);
|
||||
} else {
|
||||
$('.api_field').empty();
|
||||
$('.api_field').append(new Option('--Please select--', 0));
|
||||
$.each(json.field, function(key, value) {
|
||||
$('.api_field').append(new Option(value, value));
|
||||
});
|
||||
|
||||
}
|
||||
$('#import_api_fields').val(json.fields);
|
||||
|
||||
},
|
||||
error: function(xhr, ajaxOptions, thrownError) {
|
||||
alert(thrownError + "\r\n" + xhr.statusText + "\r\n" + xhr.responseText);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
$( document ).ready(function() {
|
||||
{if !$file_settings.fields}
|
||||
find_fields();
|
||||
{/if}
|
||||
});
|
||||
|
||||
$(document).delegate('#reload-fields', 'click', function() {
|
||||
find_fields();
|
||||
});
|
||||
</script>
|
||||
79
modules/import_api/views/templates/admin/delete.tpl
Normal file
79
modules/import_api/views/templates/admin/delete.tpl
Normal file
@@ -0,0 +1,79 @@
|
||||
{**
|
||||
* NOTICE OF LICENSE
|
||||
* With the purchase or the installation of the software in your application
|
||||
* you accept the license agreement.
|
||||
*
|
||||
* You can not resell and redistribute this file.
|
||||
*
|
||||
* @author Dalibor Stojcevski <dal_sto@yahoo.com>
|
||||
* @copyright 2019 Dalibor Stojcevski
|
||||
* @license Dalibor Stojcevski
|
||||
*}
|
||||
<div class="panel">
|
||||
<p>There are {$total} products from this file {$file_name}. Products will be deleted from prestashop. Press delete button only if you are sure that you don't need products from this file</p>
|
||||
</div>
|
||||
<div class="panel">
|
||||
<div class="buttons">
|
||||
<input type="button" value="Start delete" id="start-delete" data-loading-text="{l s='Deleting' mod='import_api'}" class="btn btn-primary api-delete" />
|
||||
</div>
|
||||
<div id="import-result" style="min-height:100px"></br>
|
||||
<div class="progress">
|
||||
<div class="progress-bar progress-bar-success progress-bar-striped" role="progressbar"
|
||||
aria-valuenow="0" aria-valuemin="0" aria-valuemax="100" style="width:0%"></div>
|
||||
</div>
|
||||
<span>Deleted : </span> <span id="deleted-number">NA</span></br>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<script type="text/javascript">
|
||||
var deleted = 0;
|
||||
var global_limit = {$total};
|
||||
|
||||
$(document).delegate('#start-delete', 'click', function() {
|
||||
$('#start-delete').button('loading');
|
||||
$('#delete-number').html('');
|
||||
|
||||
deleteProducts();
|
||||
});
|
||||
|
||||
function deleteProducts(){
|
||||
$.ajax({
|
||||
url: '{$get_import_link}&action=delete&token={$token}',
|
||||
type: 'post',
|
||||
data: $('#module_form').serialize(),
|
||||
dataType: 'json',
|
||||
beforeSend: function() {
|
||||
$('#delete-number').html($('#delete-number').html() + ' /Please wait...');
|
||||
},
|
||||
complete: function() {
|
||||
|
||||
},
|
||||
success: function(ret) {
|
||||
session_processed = ret['products_deleted'];
|
||||
createVisialProgress(ret);
|
||||
if(ret['notice'] == 'time_out'){
|
||||
deleteProducts();
|
||||
|
||||
} else {
|
||||
$('#start-delete').button('reset');
|
||||
}
|
||||
},
|
||||
error: function(xhr, ajaxOptions, thrownError) {
|
||||
//alert(thrownError + "\r\n" + xhr.statusText + "\r\n" + xhr.responseText);
|
||||
deleteProducts();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
function createVisialProgress(ret){
|
||||
deleted += ret['products_deleted'];
|
||||
$('#deleted-number').html(deleted);
|
||||
processed = deleted;
|
||||
|
||||
valeur = ( processed / global_limit ) * 100;
|
||||
$('.progress-bar').css('width', valeur+'%').attr('aria-valuenow', valeur);
|
||||
|
||||
}
|
||||
</script>
|
||||
118
modules/import_api/views/templates/admin/file_upload.tpl
Normal file
118
modules/import_api/views/templates/admin/file_upload.tpl
Normal file
@@ -0,0 +1,118 @@
|
||||
{**
|
||||
* NOTICE OF LICENSE
|
||||
* With the purchase or the installation of the software in your application
|
||||
* you accept the license agreement.
|
||||
*
|
||||
* You can not resell and redistribute this file.
|
||||
*
|
||||
* @author Dalibor Stojcevski <dal_sto@yahoo.com>
|
||||
* @copyright 2019 Dalibor Stojcevski
|
||||
* @license Dalibor Stojcevski
|
||||
*}
|
||||
|
||||
<form id="attachment_form" class="defaultForm form-horizontal AdminAttachments" action="{$form_link}" method="post" enctype="multipart/form-data" novalidate="">
|
||||
<input type="hidden" name="submitAddSource" value="1">
|
||||
|
||||
<div class="panel" id="fieldset_0">
|
||||
|
||||
<div class="panel-heading">
|
||||
<i class="icon-paper-clip"></i> Add new source
|
||||
</div>
|
||||
<div class="form-wrapper">
|
||||
<div class="form-group">
|
||||
<label class="control-label col-lg-3">Enter link</label>
|
||||
<div class="col-lg-4">
|
||||
<div class="form-group">
|
||||
<input type="text" id="name_2" name="import_api_link" class="" value="" >
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<p>Or upload file</p>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-lg-3">File</label>
|
||||
<div class="col-lg-6">
|
||||
<div class="form-group">
|
||||
<div class="col-sm-6">
|
||||
<input id="file" type="file" name="doc" class="hide">
|
||||
<div class="dummyfile input-group">
|
||||
<span class="input-group-addon"><i class="icon-file"></i></span>
|
||||
<input id="file-name" type="text" name="doc" readonly="">
|
||||
<span class="input-group-btn">
|
||||
<button id="file-selectbutton" type="button" name="submitAddSource" class="btn btn-default">
|
||||
<i class="icon-folder-open"></i> Add file </button>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div><!-- /.form-wrapper -->
|
||||
<div class="panel-footer">
|
||||
<button type="submit" value="1" id="attachment_form_submit_btn" name="submitAddSource" class="btn btn-default pull-right">
|
||||
<i class="process-icon-save"></i> Save
|
||||
</button>
|
||||
<a class="btn btn-default" id="attachment_form_cancel_btn" onclick="javascript:window.history.back();">
|
||||
<i class="process-icon-cancel"></i> Cancel
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
<script type="text/javascript">
|
||||
|
||||
$(document).ready(function(){
|
||||
$('#file-selectbutton').click(function(e) {
|
||||
$('#file').trigger('click');
|
||||
});
|
||||
|
||||
$('#file-name').click(function(e) {
|
||||
$('#file').trigger('click');
|
||||
});
|
||||
|
||||
$('#file-name').on('dragenter', function(e) {
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
});
|
||||
|
||||
$('#file-name').on('dragover', function(e) {
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
});
|
||||
|
||||
$('#file-name').on('drop', function(e) {
|
||||
e.preventDefault();
|
||||
var files = e.originalEvent.dataTransfer.files;
|
||||
$('#file')[0].files = files;
|
||||
$(this).val(files[0].name);
|
||||
});
|
||||
|
||||
$('#file').change(function(e) {
|
||||
if ($(this)[0].files !== undefined)
|
||||
{
|
||||
var files = $(this)[0].files;
|
||||
var name = '';
|
||||
|
||||
$.each(files, function(index, value) {
|
||||
name += value.name+', ';
|
||||
});
|
||||
|
||||
$('#file-name').val(name.slice(0, -2));
|
||||
}
|
||||
else // Internet Explorer 9 Compatibility
|
||||
{
|
||||
var name = $(this).val().split(/[\\/]/);
|
||||
$('#file-name').val(name[name.length-1]);
|
||||
}
|
||||
});
|
||||
|
||||
if (typeof file_max_files !== 'undefined')
|
||||
{
|
||||
$('#file').closest('form').on('submit', function(e) {
|
||||
if ($('#file')[0].files.length > file_max_files) {
|
||||
e.preventDefault();
|
||||
alert('You can upload a maximum of files');
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
</script>
|
||||
199
modules/import_api/views/templates/admin/import.tpl
Normal file
199
modules/import_api/views/templates/admin/import.tpl
Normal file
@@ -0,0 +1,199 @@
|
||||
{**
|
||||
* NOTICE OF LICENSE
|
||||
* With the purchase or the installation of the software in your application
|
||||
* you accept the license agreement.
|
||||
*
|
||||
* You can not resell and redistribute this file.
|
||||
*
|
||||
* @author Dalibor Stojcevski <dal_sto@yahoo.com>
|
||||
* @copyright 2019 Dalibor Stojcevski
|
||||
* @license Dalibor Stojcevski
|
||||
*}
|
||||
|
||||
<div class="panel">
|
||||
<div class="form-group">
|
||||
<label class="control-label col-lg-3" for="input-live-start">Start index</label>
|
||||
<div class="col-lg-9">
|
||||
<input type="text" name="import_api_live_start" id="input-live-start" value="0"/>
|
||||
</div>
|
||||
</div></br></br>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-lg-3" for="input-live-limit">Number of products</label>
|
||||
<div class="col-lg-9">
|
||||
<input type="text" name="import_api_live_limit" id="input-live-limit" value="0"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="buttons">
|
||||
<input type="button" value="Start import" id="start-import" data-loading-text="{l s='Loading' mod='import_api'}" class="btn btn-primary api-import" />
|
||||
</div>
|
||||
<div id="import-result" style="min-height:100px"></br>
|
||||
<div class="progress">
|
||||
<div class="progress-bar progress-bar-success progress-bar-striped" role="progressbar"
|
||||
aria-valuenow="0" aria-valuemin="0" aria-valuemax="100" style="width:0%"></div>
|
||||
</div>
|
||||
<span>Imported : </span> <span id="import-number">NA</span></br>
|
||||
<span>Updated : </span><span id="update-number">NA</span></br>
|
||||
<span>Total : </span><span id="total-number">NA</span></br>
|
||||
</br></br>
|
||||
<p> For cron job you should use link {$get_import_link|escape:'htmlall':'UTF-8'} </p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel">
|
||||
<fieldset class="form-horizontal">
|
||||
<legend>Test results</legend>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-lg-3" for="input-index-test">Test start index</label>
|
||||
<div class="col-lg-9">
|
||||
<input type="text" name="import_api_start_index" id="input-index-test" value="0"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="buttons">
|
||||
<input type="button" value="Original import" id="view-raw" data-loading-text="{l s='Loading' mod='import_api'}" class="btn btn-primary api-test" />
|
||||
<input type="button" value="After split" id="view-split" data-loading-text="{l s='Loading' mod='import_api'}" class="btn btn-primary api-test" />
|
||||
<input type="button" value="After grouping" id="view-grouping" data-loading-text="{l s='Loading' mod='import_api'}" class="btn btn-primary api-test" />
|
||||
<input type="button" value="After modification" id="view-modified" data-loading-text="{l s='Loading' mod='import_api'}" class="btn btn-primary api-test" />
|
||||
</div>
|
||||
<div id="test-result" style="min-height:500px"></div>
|
||||
</fieldset>
|
||||
</div>
|
||||
|
||||
<div class="panel">
|
||||
<p> If you have imported products by mistake and they can't be updated. Or you just need to delete products from this file, go to <a href="{$delete_link}">Delete products page</a>
|
||||
</div>
|
||||
|
||||
|
||||
<script type="text/javascript">
|
||||
var global_limit = 0;
|
||||
var created = 0;
|
||||
var updated = 0;
|
||||
|
||||
$(document).delegate('#start-import', 'click', function() {
|
||||
$('#start-import').button('loading');
|
||||
$('#import-number').html('');
|
||||
$('#update-number').html('');
|
||||
start = +($('#input-live-start').val());
|
||||
global_limit = limit = +($('#input-live-limit').val());
|
||||
created = 0;
|
||||
updated = 0;
|
||||
importProducts(start, limit);
|
||||
});
|
||||
|
||||
function importProducts(start = 0, limit = 0){
|
||||
$.ajax({
|
||||
url: '{$get_import_link}&action=import&start=' + start + '&limit=' + limit,
|
||||
type: 'post',
|
||||
data: $('#module_form').serialize(),
|
||||
dataType: 'json',
|
||||
beforeSend: function() {
|
||||
$('#import-number').html($('#import-number').html() + ' /Please wait...');
|
||||
$('#update-number').html($('#update-number').html() + ' /Please wait...');
|
||||
},
|
||||
complete: function() {
|
||||
|
||||
},
|
||||
success: function(ret) {
|
||||
session_processed = ret['products_created'] + ret['products_updated'];
|
||||
|
||||
if(ret['notice'] == 'time_out'){
|
||||
createVisialProgress(ret);
|
||||
start = start + session_processed;
|
||||
|
||||
if (limit){
|
||||
limit -= session_processed;
|
||||
}
|
||||
|
||||
importProducts(start, limit);
|
||||
|
||||
} else if(ret['notice'] == 'missing'){
|
||||
createVisialProgress(ret);
|
||||
importProducts();
|
||||
|
||||
} else {
|
||||
$('#start-import').button('reset');
|
||||
}
|
||||
},
|
||||
error: function(xhr, ajaxOptions, thrownError) {
|
||||
//alert(thrownError + "\r\n" + xhr.statusText + "\r\n" + xhr.responseText);
|
||||
importProducts(start, limit);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
function createVisialProgress(ret){
|
||||
updated += ret['products_updated'];
|
||||
created += ret['products_created'];
|
||||
$('#import-number').html(created);
|
||||
$('#update-number').html(updated);
|
||||
processed = created + updated;
|
||||
|
||||
if(!global_limit){
|
||||
global_limit = ret['total'];
|
||||
$('#total-number').html(ret['total']);
|
||||
}
|
||||
|
||||
if(global_limit){
|
||||
valeur = ( processed / global_limit ) * 100;
|
||||
$('.progress-bar').css('width', valeur+'%').attr('aria-valuenow', valeur);
|
||||
}
|
||||
}
|
||||
|
||||
$(document).delegate('.api-test', 'click', function() {
|
||||
$.ajax({
|
||||
url: '{$get_import_link}&action=test&id=' + $(this).attr('id') + '&start=' + $('#input-index-test').val(),
|
||||
type: 'post',
|
||||
data: $('#module_form').serialize(),
|
||||
dataType: 'json',
|
||||
beforeSend: function() {
|
||||
$('#test-result').html('Please wait...');
|
||||
$(".api-test").attr("disabled", true);
|
||||
//$('.api-test').button('loading');
|
||||
},
|
||||
complete: function() {
|
||||
//$('.api-test').button('reset');
|
||||
$(".api-test").attr("disabled", false);
|
||||
},
|
||||
success: function(ret) {
|
||||
if(ret['error'] !== undefined){
|
||||
alert(ret['error']);
|
||||
} else {
|
||||
html = '';
|
||||
$.each(ret,function(p, product){
|
||||
html += jsonObjToHtml(product);
|
||||
html += '</br><hr>';
|
||||
});
|
||||
|
||||
$('#test-result').html(html);
|
||||
}
|
||||
|
||||
},
|
||||
error: function(xhr, ajaxOptions, thrownError) {
|
||||
alert(thrownError + "\r\n" + xhr.statusText + "\r\n" + xhr.responseText);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
function jsonObjToHtml(obj){
|
||||
html = '';
|
||||
$.each(obj, function(index, value){
|
||||
if(Array.isArray(value)){
|
||||
html += '<p><b>' + index + '</b></p>';
|
||||
html += '<ul>';
|
||||
$.each(value, function(i, v) {
|
||||
if (v !== null && typeof (v) === 'object') {
|
||||
html += jsonObjToHtml(v);
|
||||
} else {
|
||||
html += '<li>' + v + '</li>';
|
||||
}
|
||||
});
|
||||
html += '</ul>';
|
||||
} else if (value !== null && typeof (value) === 'object') {
|
||||
html += '<p><b>' + index + '</b></p>';
|
||||
html += jsonObjToHtml(value);
|
||||
} else {
|
||||
html += '<p><b>' + index + '</b>: ' + value + '</p>';
|
||||
}
|
||||
});
|
||||
return html;
|
||||
}
|
||||
</script>
|
||||
35
modules/import_api/views/templates/admin/index.php
Normal file
35
modules/import_api/views/templates/admin/index.php
Normal file
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
/**
|
||||
* 2007-2018 PrestaShop
|
||||
*
|
||||
* NOTICE OF LICENSE
|
||||
*
|
||||
* This source file is subject to the Academic Free License (AFL 3.0)
|
||||
* that is bundled with this package in the file LICENSE.txt.
|
||||
* It is also available through the world-wide-web at this URL:
|
||||
* http://opensource.org/licenses/afl-3.0.php
|
||||
* If you did not receive a copy of the license and are unable to
|
||||
* obtain it through the world-wide-web, please send an email
|
||||
* to license@prestashop.com so we can send you a copy immediately.
|
||||
*
|
||||
* DISCLAIMER
|
||||
*
|
||||
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
|
||||
* versions in the future. If you wish to customize PrestaShop for your
|
||||
* needs please refer to http://www.prestashop.com for more information.
|
||||
*
|
||||
* @author PrestaShop SA <contact@prestashop.com>
|
||||
* @copyright 2007-2018 PrestaShop SA
|
||||
* @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0)
|
||||
* International Registered Trademark & Property of PrestaShop SA
|
||||
*/
|
||||
|
||||
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;
|
||||
35
modules/import_api/views/templates/admin/list.tpl
Normal file
35
modules/import_api/views/templates/admin/list.tpl
Normal file
@@ -0,0 +1,35 @@
|
||||
{**
|
||||
* NOTICE OF LICENSE
|
||||
* With the purchase or the installation of the software in your application
|
||||
* you accept the license agreement.
|
||||
*
|
||||
* You can not resell and redistribute this file.
|
||||
*
|
||||
* @author Dalibor Stojcevski <dal_sto@yahoo.com>
|
||||
* @copyright 2019 Dalibor Stojcevski
|
||||
* @license Dalibor Stojcevski
|
||||
*}
|
||||
<div class="panel">
|
||||
|
||||
<div class="table-responsive-row clearfix">
|
||||
<table id="table-attachment" class="table attachment">
|
||||
<thead>
|
||||
<tr class="nodrag nodrop">
|
||||
<th><span class="title_box">Name</span></th>
|
||||
<th class="text-right"><span class="title_box">Action</span></th>
|
||||
<th class="text-right"><span class="title_box">Enable / Disbale</span></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{foreach from=$files item=file}
|
||||
<tr>
|
||||
<td>{$file.name}</td>
|
||||
<td class="text-right" style="padding:10px"><a href="{$file.process_link}">View</a></td>
|
||||
<td class="text-right" style="padding:10px"><a href="{$file.change_status_link}">{$file.other_status_text}</a></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
{/foreach}
|
||||
</table>
|
||||
<p><a href="{$show_disabled_link}">Show disabled sources</a></p>
|
||||
</div>
|
||||
</div>
|
||||
193
modules/import_api/views/templates/admin/temp.tpl
Normal file
193
modules/import_api/views/templates/admin/temp.tpl
Normal file
@@ -0,0 +1,193 @@
|
||||
{**
|
||||
* NOTICE OF LICENSE
|
||||
* With the purchase or the installation of the software in your application
|
||||
* you accept the license agreement.
|
||||
*
|
||||
* You can not resell and redistribute this file.
|
||||
*
|
||||
* @author Dalibor Stojcevski <dal_sto@yahoo.com>
|
||||
* @copyright 2019 Dalibor Stojcevski
|
||||
* @license Dalibor Stojcevski
|
||||
*}
|
||||
<div class="panel">
|
||||
{if !$products}
|
||||
<p> You don't have queued products. It is good to make this process for better testing and view before import. But you can skip and press Start import</p>
|
||||
<button class="btn btn-default" id="start-queue">Queue</button>
|
||||
|
||||
{/if}
|
||||
<p id="api-loader" style="display:none"> Please wait while module queue products
|
||||
<span class="hidden-xs" >
|
||||
<i class="icon-refresh icon-spin icon-fw"></i>
|
||||
</span>
|
||||
</p>
|
||||
{if $products}
|
||||
<div class="card">
|
||||
<h3 class="card-title">Products from file</h3>
|
||||
<a class="btn btn-default" href="{$settings_link}">Change settings</a>
|
||||
<p>{$file_name}</p>
|
||||
<span id="show-info" style="display:none">Imported: <span id="import-number1"></span>, Updated: <span id="update-number1"></span></span>
|
||||
<button class="btn btn-default" style="float:right;margin-bottom:10px;" id="start-import-selected">Import selected</button>
|
||||
</div>
|
||||
<div class="clearfix"></div>
|
||||
<form id="form-json-api" method="POST">
|
||||
<table id="example2" class="table table-bordered table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>#</th>
|
||||
<th>Unique</th>
|
||||
<th>Reference</th>
|
||||
<th>Name</th>
|
||||
<th>Price</th>
|
||||
<th>Quantity</th>
|
||||
<th>Brand</th>
|
||||
<th>Action</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
|
||||
{foreach from=$products item=product}
|
||||
<tr id="tr-{$product.id}">
|
||||
<td><input type="checkbox" name="indx[]" value="{$product.indx}"/></td>
|
||||
<td>{$product.indx}</td>
|
||||
<td>{$product.reference}</td>
|
||||
<td>{$product.name}</td>
|
||||
<td>{$product.price}</td>
|
||||
<td>{$product.quantity}</td>
|
||||
|
||||
<td>{$product.manufacturer}</td>
|
||||
<td>
|
||||
<a href="{$get_import_link}&index={$product.indx}" target="_blank" >Import</a>
|
||||
<a href="{$get_import_link}&index={$product.indx}&action=view_one" target="_blank" >View</a>
|
||||
</td>
|
||||
</tr>
|
||||
{/foreach}
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
</form>
|
||||
{if $limit}
|
||||
<p>There is limit ({$limit}) for queued products for better performance. If you want to show all press on link <a href="{$show_all_link}">Show all</a></p>
|
||||
{/if}
|
||||
{/if}
|
||||
</div>
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
$('#example2').dataTable({
|
||||
select: {
|
||||
style: 'os',
|
||||
selector: 'td:first-child'
|
||||
},
|
||||
order: [[ 2, 'asc' ]]
|
||||
});
|
||||
});
|
||||
|
||||
function queueProducts(delete_queue = 0){
|
||||
$.ajax({
|
||||
url: '{$get_import_link}&queue=1',
|
||||
type: 'post',
|
||||
// dataType: 'json',
|
||||
beforeSend: function() {
|
||||
$('#start-queue').button('loading');
|
||||
$('#api-loader').show();
|
||||
},
|
||||
complete: function() {
|
||||
//$('#start-queue').button('reset');
|
||||
$('#api-loader').hide();
|
||||
},
|
||||
success: function(ret) {
|
||||
if (ret == '0') {
|
||||
alert('No products found. Change settings and reload again');
|
||||
} else {
|
||||
location.reload();
|
||||
}
|
||||
|
||||
|
||||
return false;
|
||||
},
|
||||
error: function(xhr, ajaxOptions, thrownError) {
|
||||
alert(thrownError + "\r\n" + xhr.statusText + "\r\n" + xhr.responseText);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
{if $auto_queue}
|
||||
queueProducts();
|
||||
{/if}
|
||||
|
||||
$(document).delegate('#start-queue', 'click', function() {
|
||||
queueProducts();
|
||||
});
|
||||
|
||||
|
||||
//najnovo
|
||||
|
||||
var global_limit = 0;
|
||||
var created = 0;
|
||||
var updated = 0;
|
||||
|
||||
$(document).delegate('#start-import-selected', 'click', function() {
|
||||
$("#start-import-selected").attr("disabled", true);
|
||||
$('#import-number1').html('');
|
||||
$('#update-number1').html('');
|
||||
start = 0
|
||||
global_limit = limit = 0;
|
||||
created = 0;
|
||||
updated = 0;
|
||||
importSelectedProducts();
|
||||
});
|
||||
|
||||
function importSelectedProducts(start = 0, limit = 0){
|
||||
$.ajax({
|
||||
url: '{$get_import_link}&action=selected&from=admin',
|
||||
type: 'post',
|
||||
data: $('#form-json-api').serialize(),
|
||||
dataType: 'json',
|
||||
beforeSend: function() {
|
||||
$('#show-info').show();
|
||||
},
|
||||
complete: function() {
|
||||
|
||||
},
|
||||
success: function(ret) {
|
||||
$.each( ret['processed'], function( key, value ) {
|
||||
//$('#tr-' + value).remove();
|
||||
$('#example2').DataTable().row('#tr-' + value).remove().draw();
|
||||
});
|
||||
createVisialProgress1(ret);
|
||||
console.log(ret);
|
||||
if(ret['notice'] == 'time_out'){
|
||||
start = start + session_processed;
|
||||
|
||||
if (limit){
|
||||
//limit -= session_processed;
|
||||
}
|
||||
|
||||
importSelectedProducts();
|
||||
|
||||
} else if(ret['notice']) {
|
||||
alert(ret['notice']);
|
||||
//$('#import-number').html(ret['notice'] + ' /Trying again...');
|
||||
///importProducts(start, limit);
|
||||
$("#start-import-selected").attr("disabled", false);
|
||||
} else {
|
||||
$("#start-import-selected").attr("disabled", false);
|
||||
|
||||
}
|
||||
},
|
||||
error: function(xhr, ajaxOptions, thrownError) {
|
||||
//alert(thrownError + "\r\n" + xhr.statusText + "\r\n" + xhr.responseText);
|
||||
window.setTimeout(function(){
|
||||
importSelectedProducts(start, limit);
|
||||
}, 300);
|
||||
//$("#start-import-selected").attr("disabled", false);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function createVisialProgress1(ret){
|
||||
updated += ret['products_updated'];
|
||||
created += ret['products_created'];
|
||||
$('#import-number1').html(created);
|
||||
$('#update-number1').html(updated);
|
||||
}
|
||||
</script>
|
||||
35
modules/import_api/views/templates/index.php
Normal file
35
modules/import_api/views/templates/index.php
Normal file
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
/**
|
||||
* 2007-2018 PrestaShop
|
||||
*
|
||||
* NOTICE OF LICENSE
|
||||
*
|
||||
* This source file is subject to the Academic Free License (AFL 3.0)
|
||||
* that is bundled with this package in the file LICENSE.txt.
|
||||
* It is also available through the world-wide-web at this URL:
|
||||
* http://opensource.org/licenses/afl-3.0.php
|
||||
* If you did not receive a copy of the license and are unable to
|
||||
* obtain it through the world-wide-web, please send an email
|
||||
* to license@prestashop.com so we can send you a copy immediately.
|
||||
*
|
||||
* DISCLAIMER
|
||||
*
|
||||
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
|
||||
* versions in the future. If you wish to customize PrestaShop for your
|
||||
* needs please refer to http://www.prestashop.com for more information.
|
||||
*
|
||||
* @author PrestaShop SA <contact@prestashop.com>
|
||||
* @copyright 2007-2018 PrestaShop SA
|
||||
* @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0)
|
||||
* International Registered Trademark & Property of PrestaShop SA
|
||||
*/
|
||||
|
||||
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;
|
||||
Reference in New Issue
Block a user