upgraded controllers and admin link builder

This commit is contained in:
O K
2025-09-26 13:07:27 +03:00
parent 2d21de9cbd
commit 4fdb52de0c
5 changed files with 342 additions and 229 deletions

View File

@@ -15,13 +15,10 @@ class ProductLinkCheckerCategoryModuleFrontController extends ModuleFrontControl
{ {
parent::init(); parent::init();
// Security check: Validate the token, same as the other controller if (!Tools::getValue('token') || Tools::getValue('token') !== Configuration::get('PLC_SECURITY_TOKEN')) {
$token = Tools::getValue('token'); $response = new JsonResponse(['error' => 'Not Authorized'], 403);
$storedToken = Configuration::get('PLC_SECURITY_TOKEN'); $response->send();
exit;
if (!$token || $token !== $storedToken) {
header('HTTP/1.1 403 Forbidden');
exit('Invalid security token.');
} }
} }
@@ -29,31 +26,11 @@ class ProductLinkCheckerCategoryModuleFrontController extends ModuleFrontControl
{ {
parent::initContent(); parent::initContent();
header('Content-Type: application/json');
$categoriesData = []; $categoriesData = [];
$collection = new PrestaShopCollection('Category'); $collection = new PrestaShopCollection('Category');
$id_shop_filter = (int)Tools::getValue('plc_id_shop'); foreach ((array)Tools::getValue('plc_id_shop', Shop::getShops(true, null, true)) as $id_shop) {
$id_lang_filter = (int)Tools::getValue('plc_id_lang'); foreach ((array)Tools::getValue('plc_id_lang', Language::getLanguages(false, false, true)) as $id_lang) {
// Determine which shops to scan
if ($id_shop_filter) {
$shop_ids = [$id_shop_filter];
} else {
$shop_ids = Shop::getShops(true, null, true);
}
// Determine which languages to scan
if ($id_lang_filter) {
$lang_ids = [$id_lang_filter];
} else {
$lang_ids = Language::getLanguages(true, false, true);
}
foreach ($shop_ids as $id_shop) {
foreach ($lang_ids as $id_lang) {
foreach ($collection as $cat) { foreach ($collection as $cat) {
@@ -62,6 +39,8 @@ class ProductLinkCheckerCategoryModuleFrontController extends ModuleFrontControl
continue; continue;
} }
$data = [ $data = [
'id_lang' => $id_lang,
'id_shop' => $id_shop,
'id_category' => $category->id, 'id_category' => $category->id,
'id_parent' => $category->id_parent, 'id_parent' => $category->id_parent,
'active' => $category->active, 'active' => $category->active,

View File

@@ -1,94 +0,0 @@
<?php
/**
* Product Link Checker Generate Controller
*/
class ProductLinkCheckerGenerateModuleFrontController extends ModuleFrontController
{
public function init()
{
parent::init();
// Security check: Validate the token
$token = Tools::getValue('token');
$storedToken = Configuration::get('PLC_SECURITY_TOKEN');
if (!$token || $token !== $storedToken) {
header('HTTP/1.1 403 Forbidden');
exit('Invalid security token.');
}
}
public function initContent()
{
parent::initContent();
header('Content-Type: application/json');
$id_shop_filter = (int)Tools::getValue('plc_id_shop');
$id_lang_filter = (int)Tools::getValue('plc_id_lang');
// Determine which shops to scan
if ($id_shop_filter) {
$shop_ids = [$id_shop_filter];
} else {
$shop_ids = Shop::getShops(true, null, true);
}
// Determine which languages to scan
if ($id_lang_filter) {
$lang_ids = [$id_lang_filter];
} else {
$lang_ids = Language::getLanguages(true, false, true);
}
$all_links = [];
foreach ($shop_ids as $id_shop) {
foreach ($lang_ids as $id_lang) {
// Get all active products for the current shop and language
$products = Product::getProducts($id_lang, 0, 0, 'id_product', 'ASC', false, true);
foreach ($products as $product_data) {
$product = new Product($product_data['id_product'], false, $id_lang, $id_shop);
// Skip invalid products
if (!Validate::isLoadedObject($product)) {
continue;
}
// Get base product link
$base_link = $this->context->link->getProductLink($product, null, null, null, $id_lang, $id_shop);
$all_links[] = $base_link;
// Get links for combinations if they exist
if ($product->hasAttributes()) {
$combinations = $product->getAttributesResume($id_lang);
if ($combinations) {
foreach ($combinations as $combination) {
$combo_link = $this->context->link->getProductLink(
$product,
null,
null,
null,
$id_lang,
$id_shop,
$combination['id_product_attribute'],
false,
false,
true // Add attribute anchor
);
$all_links[] = $combo_link;
}
}
}
}
}
}
// Remove duplicates that might occur in complex shop setups and output JSON
echo json_encode(array_values(array_unique($all_links)), JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES);
exit;
}
}

View File

@@ -7,121 +7,128 @@
* with detailed information for external services. * with detailed information for external services.
*/ */
use Symfony\Component\HttpFoundation\JsonResponse;
class ProductLinkCheckerProductModuleFrontController extends ModuleFrontController class ProductLinkCheckerProductModuleFrontController extends ModuleFrontController
{ {
/**
* @see FrontController::init()
*/
public function init() public function init()
{ {
parent::init(); parent::init();
// Security check: Validate the token, same as the other controller // Security check: Validate the token, same as the other controller
$token = Tools::getValue('token'); if (!Tools::getValue('token') || Tools::getValue('token') !== Configuration::get('PLC_SECURITY_TOKEN')) {
$storedToken = Configuration::get('PLC_SECURITY_TOKEN'); $response = new JsonResponse(['error' => 'Not Authorized'], 403);
$response->send();
if (!$token || $token !== $storedToken) { exit;
header('HTTP/1.1 403 Forbidden');
exit('Invalid security token.');
} }
} }
/**
* @see FrontController::initContent()
*/
public function initContent() public function initContent()
{ {
parent::initContent(); parent::initContent();
header('Content-Type: application/json'); $productsData = [];
$collection = new PrestaShopCollection('Product');
$id_shop_filter = (int)Tools::getValue('plc_id_shop'); foreach ((array)Tools::getValue('plc_id_shop', Shop::getShops(true, null, true)) as $id_shop) {
$id_lang_filter = (int)Tools::getValue('plc_id_lang'); foreach ((array)Tools::getValue('plc_id_lang', Language::getLanguages(false, false, true)) as $id_lang) {
// Determine which shops to scan foreach ($collection as $p) {
if ($id_shop_filter) { $product = new Product((int)$p->id, false, $id_lang, $id_shop);
$shop_ids = [$id_shop_filter];
} else {
$shop_ids = Shop::getShops(true, null, true);
}
// Determine which languages to scan
if ($id_lang_filter) {
$lang_ids = [$id_lang_filter];
} else {
$lang_ids = Language::getLanguages(true, false, true);
}
$all_product_data = [];
foreach ($shop_ids as $id_shop) {
foreach ($lang_ids as $id_lang) {
// Get all active products for the current shop and language
$products = Product::getProducts($id_lang, 0, 0, 'id_product', 'ASC', false, true);
foreach ($products as $product_data) {
$product = new Product($product_data['id_product'], false, $id_lang, $id_shop);
// Skip invalid or unloaded products
if (!Validate::isLoadedObject($product)) { if (!Validate::isLoadedObject($product)) {
continue; continue;
} }
if (Tools::getValue('plc_only_active') && !$product->active) {
continue;
}
// Handle products with attribute combinations
// 2. Add data for all attribute combinations
if ($product->hasAttributes()) { if ($product->hasAttributes()) {
// getAttributeCombinations provides detailed data for each combination
$combinations = $product->getAttributeCombinations($id_lang); $combinations = $product->getAttributeCombinations($id_lang);
if ($combinations) {
foreach ($combinations as $combination) { foreach ($combinations as $combination) {
if (!isset($all_product_data[$product->id . '_' . $combination['id_product_attribute']])) { $index = $product->id . '_' . $combination['id_product_attribute'];
$all_product_data[$product->id . '_' . $combination['id_product_attribute']] = [ if (!isset($productsData[$index])) {
$productsData[$index] = [
'id_lang' => (int)$id_lang,
'id_shop' => (int)$id_shop,
'id_product' => (int)$product->id, 'id_product' => (int)$product->id,
'id_product_attribute' => (int)$combination['id_product_attribute'], 'id_product_attribute' => (int)$combination['id_product_attribute'],
'meta_title' => $product->meta_title, // Meta is usually product-level 'active' => (bool)$product->active,
'meta_description' => $product->meta_description, 'link' => $this->context->link->getProductLink(
// Title and descriptions are also from the main product $product,
'title' => $product->name, null,
'description' => Tools::getValue('plc_no_description') ? null : $product->description, null,
'description_short' => Tools::getValue('plc_no_description_short') ? null : $product->description_short, null,
// These fields are specific to the combination (int)$id_lang,
'mpn' => $combination['mpn'] ?? null, (int)$id_shop,
'reference' => $combination['reference'] ?? null, (int)$combination['id_product_attribute'],
'ean13' => $combination['ean13'] ?? null, false
'upc' => $combination['upc'] ?? null, ),
'id_language' => (int)$id_lang,
'id_shop' => (int)$id_shop,
'link' => $this->context->link->getProductLink($product, null, null, null, (int)$id_lang, (int)$id_shop, (int)$combination['id_product_attribute']),
'link_rewrite' => $product->link_rewrite,
]; ];
// Conditionally add data based on URL flags
Tools::getValue('plc_name') ? $productsData[$index]['name'] = $product->name : null;
Tools::getValue('plc_link_rewrite') ? $productsData[$index]['link_rewrite'] = $product->link_rewrite : null;
Tools::getValue('plc_description') ? $productsData[$index]['description'] = $product->description : null;
Tools::getValue('plc_description_short') ? $productsData[$index]['description_short'] = $product->description_short : null;
Tools::getValue('plc_meta_title') ? $productsData[$index]['meta_title'] = $product->meta_title : null;
Tools::getValue('plc_meta_description') ? $productsData[$index]['meta_description'] = $product->meta_description : null;
Tools::getValue('plc_reference') ? $productsData[$index]['reference'] = $combination['reference'] : null;
Tools::getValue('plc_ean13') ? $productsData[$index]['ean13'] = $combination['ean13'] : null;
Tools::getValue('plc_upc') ? $productsData[$index]['upc'] = $combination['upc'] : null;
Tools::getValue('plc_mpn') ? $productsData[$index]['mpn'] = $combination['mpn'] : null;
} }
$all_product_data[$product->id . '_' . $combination['id_product_attribute']]['attributes'][] = [
$productsData[$index]['attributes'][] = [
'group_name' => $combination['group_name'] ?? null, 'group_name' => $combination['group_name'] ?? null,
'attribute_name' => $combination['attribute_name'] ?? null, 'attribute_name' => $combination['attribute_name'] ?? null,
]; ];
} }
} } else { // Handle simple products (without combinations)
} else { // 1. Add the main product data (as a product without a specific combination) $index = $product->id . '_' . 0;
$all_product_data[] = [ $productsData[$index] = [
'id_product' => (int)$product->id, 'id_lang' => (int)$id_lang,
'id_product_attribute' => 0, // 0 for the main product
'meta_title' => $product->meta_title,
// Grouping meta fields for clarity
'meta_description' => $product->meta_description,
'title' => $product->name,
'description' => Tools::getValue('plc_no_description') ? null : $product->description,
'description_short' => Tools::getValue('plc_no_description_short') ? null : $product->description_short,
'mpn' => $product->mpn ?? null,
'reference' => $product->reference ?? null,
'ean13' => $product->ean13 ?? null,
'upc' => $product->upc ?? null,
'id_language' => (int)$id_lang,
'id_shop' => (int)$id_shop, 'id_shop' => (int)$id_shop,
'link' => $this->context->link->getProductLink($product), 'id_product' => (int)$product->id,
'link_rewrite' => $product->link_rewrite, 'id_product_attribute' => 0,
'active' => (bool)$product->active,
'link' => $this->context->link->getProductLink(
$product,
null,
null,
null,
(int)$id_lang,
(int)$id_shop,
0,
false
),
]; ];
// Conditionally add data based on URL flags
Tools::getValue('plc_name') ? $productsData[$index]['name'] = $product->name : null;
Tools::getValue('plc_link_rewrite') ? $productsData[$index]['link_rewrite'] = $product->link_rewrite : null;
Tools::getValue('plc_description') ? $productsData[$index]['description'] = $product->description : null;
Tools::getValue('plc_description_short') ? $productsData[$index]['description_short'] = $product->description_short : null;
Tools::getValue('plc_meta_title') ? $productsData[$index]['meta_title'] = $product->meta_title : null;
Tools::getValue('plc_meta_description') ? $productsData[$index]['meta_description'] = $product->meta_description : null;
Tools::getValue('plc_reference') ? $productsData[$index]['reference'] = $product->reference : null;
Tools::getValue('plc_ean13') ? $productsData[$index]['ean13'] = $product->ean13 : null;
Tools::getValue('plc_upc') ? $productsData[$index]['upc'] = $product->upc : null;
Tools::getValue('plc_mpn') ? $productsData[$index]['mpn'] = $product->mpn : null;
} }
} }
} }
} }
// Output the final array as a JSON object $response = new JsonResponse($productsData);
echo json_encode($all_product_data, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES); $response->send();
exit; exit;
} }
} }

View File

@@ -1,4 +1,5 @@
<?php <?php
/** /**
* Product Link Checker * Product Link Checker
* *
@@ -17,7 +18,7 @@ class ProductLinkChecker extends Module
{ {
$this->name = 'productlinkchecker'; $this->name = 'productlinkchecker';
$this->tab = 'seo'; $this->tab = 'seo';
$this->version = '1.0.0'; $this->version = '2.0.0';
$this->author = 'Panariga'; $this->author = 'Panariga';
$this->need_instance = 0; $this->need_instance = 0;
$this->ps_versions_compliancy = ['min' => '1.7.0', 'max' => _PS_VERSION_]; $this->ps_versions_compliancy = ['min' => '1.7.0', 'max' => _PS_VERSION_];
@@ -62,11 +63,37 @@ class ProductLinkChecker extends Module
*/ */
public function getContent() public function getContent()
{ {
// Define the available data fields for each controller based on your code
$product_fields = [
'plc_name' => $this->l('Name'),
'plc_link_rewrite' => $this->l('Link Rewrite'),
'plc_description' => $this->l('Description'),
'plc_description_short' => $this->l('Short Description'),
'plc_meta_title' => $this->l('Meta Title'),
'plc_meta_description' => $this->l('Meta Description'),
'plc_reference' => $this->l('Reference'),
'plc_ean13' => $this->l('EAN13'),
'plc_upc' => $this->l('UPC'),
'plc_mpn' => $this->l('MPN'),
];
$category_fields = [
'plc_name' => $this->l('Name'),
'plc_link_rewrite' => $this->l('Link Rewrite'),
'plc_description' => $this->l('Description'),
'plc_additional_description' => $this->l('Additional Description'),
'plc_meta_title' => $this->l('Meta Title'),
'plc_meta_description' => $this->l('Meta Description'),
];
$this->context->smarty->assign([ $this->context->smarty->assign([
'security_token' => Configuration::get('PLC_SECURITY_TOKEN'), 'security_token' => Configuration::get('PLC_SECURITY_TOKEN'),
'shops' => Shop::getShops(true, null, true), 'shops' => Shop::getShops(true, null, true),
'languages' => Language::getLanguages(true), 'languages' => Language::getLanguages(true),
'base_controller_url' => $this->context->link->getModuleLink($this->name, 'generate', [], true), 'product_controller_url' => $this->context->link->getModuleLink($this->name, 'product', [], true),
'category_controller_url' => $this->context->link->getModuleLink($this->name, 'category', [], true),
'product_fields' => $product_fields,
'category_fields' => $category_fields,
]); ]);
return $this->display(__FILE__, 'views/templates/admin/configure.tpl'); return $this->display(__FILE__, 'views/templates/admin/configure.tpl');

View File

@@ -4,34 +4,228 @@
<i class="icon-link"></i> {l s='Product Link Checker Configuration' mod='productlinkchecker'} <i class="icon-link"></i> {l s='Product Link Checker Configuration' mod='productlinkchecker'}
</div> </div>
<div class="alert alert-warning"> <div class="alert alert-info">
<h4><i class="icon-key"></i> {l s='Your Security Token' mod='productlinkchecker'}</h4> <h4><i class="icon-key"></i> {l s='Your Security Token' mod='productlinkchecker'}</h4>
<p>{l s='Use this token to access the link generator. Keep it secret!' mod='productlinkchecker'}</p> <p>{l s='Use this token to access the link generators below. Keep it secret!' mod='productlinkchecker'}</p>
<p><strong>{$security_token|escape:'html':'UTF-8'}</strong></p> <p><strong>{$security_token|escape:'html':'UTF-8'}</strong></p>
</div> </div>
<div class="panel"> <div class="panel">
<div class="panel-heading"> <div class="panel-heading">
<i class="icon-list"></i> {l s='Available URLs' mod='productlinkchecker'} <i class="icon-cogs"></i> {l s='URL Generator' mod='productlinkchecker'}
</div> </div>
<div class="list-group">
<a href="{$base_controller_url}?token={$security_token|escape:'html':'UTF-8'}" target="_blank" class="list-group-item">
<strong>{l s='All Shops & All Languages' mod='productlinkchecker'}</strong><br>
<code>{$base_controller_url}?token={$security_token|escape:'html':'UTF-8'}</code>
</a>
<!-- Nav tabs -->
<ul class="nav nav-tabs" role="tablist">
<li role="presentation" class="active"><a href="#products" aria-controls="products" role="tab" data-toggle="tab"><i class="icon-tags"></i> {l s='Product Links' mod='productlinkchecker'}</a></li>
<li role="presentation"><a href="#categories" aria-controls="categories" role="tab" data-toggle="tab"><i class="icon-folder"></i> {l s='Category Links' mod='productlinkchecker'}</a></li>
</ul>
<!-- Tab panes -->
<div class="tab-content">
{* --- PRODUCT URL BUILDER --- *}
<div role="tabpanel" class="tab-pane active" id="products">
<form class="form-horizontal" id="product-url-builder">
<h4>{l s='1. Select Filters' mod='productlinkchecker'}</h4>
<div class="form-group">
<label class="col-lg-3 control-label">{l s='Shop' mod='productlinkchecker'}</label>
<div class="col-lg-9">
<select name="plc_id_shop" class="plc-builder-input" data-type="product">
<option value="">{l s='All Shops' mod='productlinkchecker'}</option>
{foreach from=$shops item=shop} {foreach from=$shops item=shop}
<a href="{$base_controller_url}?token={$security_token|escape:'html':'UTF-8'}&plc_id_shop={$shop.id_shop|intval}" target="_blank" class="list-group-item"> <option value="{$shop.id_shop|intval}">{$shop.name|escape:'html':'UTF-8'}</option>
<strong>{l s='Shop:' mod='productlinkchecker'} {$shop.name|escape:'html':'UTF-8'} ({l s='All Languages' mod='productlinkchecker'})</strong><br> {/foreach}
<code>{$base_controller_url}?token={$security_token|escape:'html':'UTF-8'}&plc_id_shop={$shop.id_shop|intval}</code> </select>
</a> </div>
</div>
<div class="form-group">
<label class="col-lg-3 control-label">{l s='Language' mod='productlinkchecker'}</label>
<div class="col-lg-9">
<select name="plc_id_lang" class="plc-builder-input" data-type="product">
<option value="">{l s='All Languages' mod='productlinkchecker'}</option>
{foreach from=$languages item=lang} {foreach from=$languages item=lang}
<a href="{$base_controller_url}?token={$security_token|escape:'html':'UTF-8'}&plc_id_shop={$shop.id_shop|intval}&plc_id_lang={$lang.id_lang|intval}" target="_blank" class="list-group-item"> <option value="{$lang.id_lang|intval}">{$lang.name|escape:'html':'UTF-8'}</option>
<strong>{l s='Shop:' mod='productlinkchecker'} {$shop.name|escape:'html':'UTF-8'} | {l s='Language:' mod='productlinkchecker'} {$lang.name|escape:'html':'UTF-8'}</strong><br> {/foreach}
<code>{$base_controller_url}?token={$security_token|escape:'html':'UTF-8'}&plc_id_shop={$shop.id_shop|intval}&plc_id_lang={$lang.id_lang|intval}</code> </select>
</div>
</div>
<div class="form-group">
<label class="col-lg-3 control-label">{l s='Status' mod='productlinkchecker'}</label>
<div class="col-lg-9">
<span class="switch prestashop-switch fixed-width-lg">
<input type="radio" name="plc_only_active" id="plc_only_active_prod_on" value="1" class="plc-builder-input" data-type="product">
<label for="plc_only_active_prod_on">{l s='Active Only' mod='productlinkchecker'}</label>
<input type="radio" name="plc_only_active" id="plc_only_active_prod_off" value="" class="plc-builder-input" data-type="product" checked="checked">
<label for="plc_only_active_prod_off">{l s='All' mod='productlinkchecker'}</label>
<a class="slide-button btn"></a>
</span>
</div>
</div>
<hr>
<h4>{l s='2. Select Data Fields to Include' mod='productlinkchecker'}</h4>
<div class="form-group">
<div class="col-lg-9 col-lg-offset-3">
{foreach from=$product_fields key=key item=label}
<div class="checkbox">
<label>
<input type="checkbox" name="{$key|escape:'html':'UTF-8'}" value="1" class="plc-builder-input" data-type="product"> {$label|escape:'html':'UTF-8'}
</label>
</div>
{/foreach}
</div>
</div>
<hr>
<h4>{l s='3. Generated URL' mod='productlinkchecker'}</h4>
<div class="form-group">
<div class="col-lg-12">
<div class="input-group">
<input type="text" id="generated-url-product" class="form-control" readonly>
<span class="input-group-btn">
<button class="btn btn-default" type="button" onclick="copyToClipboard('product')">
<i class="icon-copy"></i> {l s='Copy' mod='productlinkchecker'}
</button>
<a href="#" id="open-url-product" target="_blank" class="btn btn-primary">
<i class="icon-external-link"></i> {l s='Open' mod='productlinkchecker'}
</a> </a>
</span>
</div>
</div>
</div>
</form>
</div>
{* --- CATEGORY URL BUILDER --- *}
<div role="tabpanel" class="tab-pane" id="categories">
<form class="form-horizontal" id="category-url-builder">
<h4>{l s='1. Select Filters' mod='productlinkchecker'}</h4>
<div class="form-group">
<label class="col-lg-3 control-label">{l s='Shop' mod='productlinkchecker'}</label>
<div class="col-lg-9">
<select name="plc_id_shop" class="plc-builder-input" data-type="category">
<option value="">{l s='All Shops' mod='productlinkchecker'}</option>
{foreach from=$shops item=shop}
<option value="{$shop.id_shop|intval}">{$shop.name|escape:'html':'UTF-8'}</option>
{/foreach} {/foreach}
</select>
</div>
</div>
<div class="form-group">
<label class="col-lg-3 control-label">{l s='Language' mod='productlinkchecker'}</label>
<div class="col-lg-9">
<select name="plc_id_lang" class="plc-builder-input" data-type="category">
<option value="">{l s='All Languages' mod='productlinkchecker'}</option>
{foreach from=$languages item=lang}
<option value="{$lang.id_lang|intval}">{$lang.name|escape:'html':'UTF-8'}</option>
{/foreach} {/foreach}
</select>
</div>
</div>
<div class="form-group">
<label class="col-lg-3 control-label">{l s='Status' mod='productlinkchecker'}</label>
<div class="col-lg-9">
<span class="switch prestashop-switch fixed-width-lg">
<input type="radio" name="plc_only_active" id="plc_only_active_cat_on" value="1" class="plc-builder-input" data-type="category">
<label for="plc_only_active_cat_on">{l s='Active Only' mod='productlinkchecker'}</label>
<input type="radio" name="plc_only_active" id="plc_only_active_cat_off" value="" class="plc-builder-input" data-type="category" checked="checked">
<label for="plc_only_active_cat_off">{l s='All' mod='productlinkchecker'}</label>
<a class="slide-button btn"></a>
</span>
</div>
</div>
<hr>
<h4>{l s='2. Select Data Fields to Include' mod='productlinkchecker'}</h4>
<div class="form-group">
<div class="col-lg-9 col-lg-offset-3">
{foreach from=$category_fields key=key item=label}
<div class="checkbox">
<label>
<input type="checkbox" name="{$key|escape:'html':'UTF-8'}" value="1" class="plc-builder-input" data-type="category"> {$label|escape:'html':'UTF-8'}
</label>
</div>
{/foreach}
</div>
</div>
<hr>
<h4>{l s='3. Generated URL' mod='productlinkchecker'}</h4>
<div class="form-group">
<div class="col-lg-12">
<div class="input-group">
<input type="text" id="generated-url-category" class="form-control" readonly>
<span class="input-group-btn">
<button class="btn btn-default" type="button" onclick="copyToClipboard('category')">
<i class="icon-copy"></i> {l s='Copy' mod='productlinkchecker'}
</button>
<a href="#" id="open-url-category" target="_blank" class="btn btn-primary">
<i class="icon-external-link"></i> {l s='Open' mod='productlinkchecker'}
</a>
</span>
</div>
</div>
</div>
</form>
</div>
</div> </div>
</div> </div>
</div> </div>
<script>
document.addEventListener('DOMContentLoaded', function() {
// Base URLs and token from Smarty
const baseUrls = {
product: '{$product_controller_url|escape:'javascript':'UTF-8'}',
category: '{$category_controller_url|escape:'javascript':'UTF-8'}'
};
const token = '{$security_token|escape:'javascript':'UTF-8'}';
// Function to build the URL based on selected options
const buildUrl = (type) => {
let baseUrl = baseUrls[type];
let params = new URLSearchParams();
params.append('token', token);
const form = document.getElementById(type + '-url-builder');
const inputs = form.querySelectorAll('.plc-builder-input');
inputs.forEach(input => {
if (input.type === 'checkbox' || input.type === 'radio') {
if (input.checked && input.value) {
params.append(input.name, input.value);
}
} else { // select
if (input.value) {
params.append(input.name, input.value);
}
}
});
const finalUrl = baseUrl + '?' + params.toString();
document.getElementById('generated-url-' + type).value = finalUrl;
document.getElementById('open-url-' + type).href = finalUrl;
};
// Attach event listeners to all inputs
document.querySelectorAll('.plc-builder-input').forEach(input => {
input.addEventListener('change', (event) => {
buildUrl(event.target.dataset.type);
});
});
// Initial build for both tabs on page load
buildUrl('product');
buildUrl('category');
});
// Simple copy to clipboard function
function copyToClipboard(type) {
const urlInput = document.getElementById('generated-url-' + type);
urlInput.select();
document.execCommand('copy');
// Optional: show a small feedback message
showSuccessMessage('{l s="URL copied to clipboard!" mod='productlinkchecker' js=1}');
}
</script>