<?php
if (!defined('_PS_VERSION_')) {
exit;
}

class OffreSpecialeBadge extends Module
{
const BADGE_TYPES = array('BF10', 'BF20', 'BF30');

public function __construct()
{
$this->name = 'offrespecialebadge';
$this->tab = 'front_office_features';
$this->version = '1.0.1';
$this->author = 'Greg';
$this->need_instance = 0;

parent::__construct();

$this->displayName = $this->l('Offre Spéciale Badge');
$this->description = $this->l('Ajoute des badges d\'offre spéciale (BF10, BF20, BF30) sur des produits spécifiques');
}

public function install()
{
// Créer la table
$sql = 'CREATE TABLE IF NOT EXISTS `' . _DB_PREFIX_ . 'offre_speciale_products` (
`id_product` int(11) NOT NULL,
`badge_type` varchar(10) NOT NULL,
`date_add` datetime NOT NULL,
PRIMARY KEY (`id_product`),
KEY `badge_type` (`badge_type`)
) ENGINE=' . _MYSQL_ENGINE_ . ' DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;';

return parent::install()
&& Db::getInstance()->execute($sql)
&& $this->registerHook('displayProductListReviews')
&& $this->registerHook('displayProductAdditionalInfo')
&& $this->registerHook('header')
&& $this->registerHook('displayAfterBodyOpeningTag')
&& $this->registerHook('actionOutputHTMLBefore');
}

public function uninstall()
{
// Supprimer la table
$sql = 'DROP TABLE IF EXISTS `' . _DB_PREFIX_ . 'offre_speciale_products`';

return parent::uninstall()
&& Db::getInstance()->execute($sql);
}

public function hookHeader()
{
// Ajouter le CSS
$this->context->controller->addCSS($this->_path . 'views/css/offrespeciale.css');

// Ajouter le JavaScript pour gérer les shortcodes côté client
$this->context->controller->addJS($this->_path . 'views/js/offrespeciale.js');

// Récupérer TOUS les badges pour injection en JavaScript
$allBadges = $this->getAllBadgesForJS();

// Injecter les données des badges en JavaScript
$idProduct = 0;
if (isset($this->context->controller->php_self) && $this->context->controller->php_self == 'product') {
$idProduct = (int)Tools::getValue('id_product');
}

$badgeData = $this->getBadgeForProduct($idProduct);

Media::addJsDef(array(
'offreSpecialeBadgeData' => array(
'currentProductId' => $idProduct,
'currentBadge' => $badgeData,
'allBadges' => $allBadges,
'ajaxUrl' => $this->context->link->getModuleLink('offrespecialebadge', 'ajax', array(), true)
)
));
}

/**
* Récupère tous les badges pour injection JavaScript
*/
private function getAllBadgesForJS()
{
$badges = Db::getInstance()->executeS('
SELECT id_product, badge_type
FROM `' . _DB_PREFIX_ . 'offre_speciale_products`
');

$badgesArray = array();
if ($badges) {
foreach ($badges as $badge) {
$badgesArray[$badge['id_product']] = $badge['badge_type'];
}
}

return $badgesArray;
}

/**
* Hook pour remplacer les shortcodes dans le HTML avant affichage
*/
public function hookActionOutputHTMLBefore($params)
{
if (isset($params['html'])) {
$params['html'] = $this->processShortcodes($params['html']);
}
}

/**
* Traite les shortcodes dans le contenu HTML
*/
private function processShortcodes($html)
{
// Pattern pour {offre_badge} ou {offre_badge id=123}
$pattern = '/\{offre_badge(?:\s+id=(\d+))?\}/';

$html = preg_replace_callback($pattern, function($matches) {
$idProduct = isset($matches[1]) ? (int)$matches[1] : 0;

// Si pas d'ID fourni, essayer de récupérer le produit actuel
if (!$idProduct && isset($this->context->controller->php_self) && $this->context->controller->php_self == 'product') {
$idProduct = (int)Tools::getValue('id_product');
}

if ($idProduct) {
return $this->displayBadge($idProduct);
}

return '<span class="offre-badge-placeholder" data-product-id="current"></span>';
}, $html);

return $html;
}

private function getBadgeForProduct($productId)
{
if (!$productId) {
return null;
}

$badge = Db::getInstance()->getRow('
SELECT badge_type
FROM `' . _DB_PREFIX_ . 'offre_speciale_products`
WHERE id_product = ' . (int)$productId
);

return $badge ? $badge['badge_type'] : null;
}

public function getContent()
{
$output = '';

// Traitement de l'ajout de produits
if (Tools::isSubmit('submitOffreSpecialeProducts')) {
$badgeType = Tools::getValue('BADGE_TYPE');
$products = Tools::getValue('OFFRE_PRODUCTS');

if (!in_array($badgeType, self::BADGE_TYPES)) {
$output .= $this->displayError($this->l('Type de badge invalide'));
} else {
$result = $this->addProducts($products, $badgeType);

if ($result['success']) {
$output .= $this->displayConfirmation(
sprintf($this->l('%d produit(s) ajouté(s) avec le badge %s'), $result['added'], $badgeType)
);
}
if ($result['errors'] > 0) {
$output .= $this->displayWarning(
sprintf($this->l('%d produit(s) déjà présent(s) ou invalide(s)'), $result['errors'])
);
}
}
}

// Traitement de la suppression d'un badge spécifique
if (Tools::isSubmit('submitClearBadge')) {
$badgeType = Tools::getValue('clear_badge_type');
if ($this->clearBadgeProducts($badgeType)) {
$output .= $this->displayConfirmation(
sprintf($this->l('Tous les produits du badge %s ont été supprimés'), $badgeType)
);
}
}

// Traitement de la suppression totale
if (Tools::isSubmit('submitClearAll')) {
if ($this->clearAllProducts()) {
$output .= $this->displayConfirmation($this->l('Tous les produits ont été supprimés'));
}
}

// Traitement de la suppression d'un produit spécifique
if (Tools::isSubmit('deleteProduct')) {
$idProduct = (int)Tools::getValue('id_product');
if ($this->removeProduct($idProduct)) {
$output .= $this->displayConfirmation($this->l('Produit supprimé'));
}
}

return $output . $this->displayShortcodeInfo() . $this->displayForm() . $this->displayCurrentProducts();
}

public function displayShortcodeInfo()
{
$html = '<div class="alert alert-info">
<h4><i class="icon-code"></i> ' . $this->l('Utilisation des shortcodes dans Creative Elements') . '</h4>
<p><strong>' . $this->l('Pour afficher le badge d\'un produit spécifique :') . '</strong></p>
<code>{offre_badge id=5139}</code>
<p style="margin-top: 10px;"><strong>' . $this->l('Pour afficher le badge du produit actuel (page produit) :') . '</strong></p>
<code>{offre_badge}</code>
<p style="margin-top: 10px;"><strong>' . $this->l('Alternative avec balise HTML (fonctionne partout) :') . '</strong></p>
<code>&lt;span class="offre-badge-shortcode" data-product-id="5139"&gt;&lt;/span&gt;</code>
<p style="margin-top: 5px;"><em>' . $this->l('Pour le produit actuel :') . '</em></p>
<code>&lt;span class="offre-badge-shortcode" data-product-id="current"&gt;&lt;/span&gt;</code>
</div>';

return $html;
}

public function displayForm()
{
$badgeOptions = array();
foreach (self::BADGE_TYPES as $badge) {
$badgeOptions[] = array(
'id' => $badge,
'name' => $badge
);
}

$fields_form = array(
'form' => array(
'legend' => array(
'title' => $this->l('Ajouter des produits avec badge'),
'icon' => 'icon-tag'
),
'input' => array(
array(
'type' => 'select',
'label' => $this->l('Type de badge'),
'name' => 'BADGE_TYPE',
'required' => true,
'options' => array(
'query' => $badgeOptions,
'id' => 'id',
'name' => 'name'
)
),
array(
'type' => 'textarea',
'label' => $this->l('IDs des produits'),
'desc' => $this->l('Entrez les IDs séparés par des virgules, espaces ou retours à la ligne (ex: 1, 5, 12, 45)'),
'name' => 'OFFRE_PRODUCTS',
'rows' => 5,
'cols' => 60,
'required' => true,
),
),
'submit' => array(
'title' => $this->l('Ajouter les produits'),
'class' => 'btn btn-default pull-right',
'icon' => 'process-icon-plus'
),
'buttons' => array(
array(
'href' => AdminController::$currentIndex . '&configure=' . $this->name . '&submitClearAll=1&token=' . Tools::getAdminTokenLite('AdminModules'),
'title' => $this->l('Tout supprimer'),
'icon' => 'process-icon-eraser',
'class' => 'btn btn-danger',
'js' => 'return confirm(\'' . $this->l('Êtes-vous sûr de vouloir supprimer tous les produits ?') . '\');'
)
)
),
);

$helper = new HelperForm();
$helper->module = $this;
$helper->name_controller = $this->name;
$helper->token = Tools::getAdminTokenLite('AdminModules');
$helper->currentIndex = AdminController::$currentIndex . '&configure=' . $this->name;
$helper->submit_action = 'submitOffreSpecialeProducts';

return $helper->generateForm(array($fields_form));
}

public function displayCurrentProducts()
{
$html = '';

foreach (self::BADGE_TYPES as $badgeType) {
$products = $this->getProductsByBadge($badgeType);

$html .= '<div class="panel">
<div class="panel-heading">
<i class="icon-tag"></i> ' . sprintf($this->l('Produits avec badge %s'), $badgeType) . ' (' . count($products) . ')
<span class="panel-heading-action">
<a href="' . AdminController::$currentIndex . '&configure=' . $this->name
. '&submitClearBadge=1&clear_badge_type=' . $badgeType
. '&token=' . Tools::getAdminTokenLite('AdminModules') . '"
class="btn btn-default btn-sm"
onclick="return confirm(\'' . sprintf($this->l('Supprimer tous les produits du badge %s ?'), $badgeType) . '\');">
<i class="icon-eraser"></i> ' . $this->l('Vider ce badge') . '
</a>
</span>
</div>';

if (empty($products)) {
$html .= '<div class="alert alert-info" style="margin: 10px;">'
. sprintf($this->l('Aucun produit avec le badge %s'), $badgeType)
. '</div>';
} else {
$html .= '<table class="table"><thead><tr>
<th>ID</th>
<th>' . $this->l('Nom du produit') . '</th>
<th>' . $this->l('Référence') . '</th>
<th>' . $this->l('Date d\'ajout') . '</th>
<th>' . $this->l('Actions') . '</th>
</tr></thead><tbody>';

foreach ($products as $product) {
$productObj = new Product($product['id_product'], false, $this->context->language->id);
$html .= '<tr>
<td>' . (int)$product['id_product'] . '</td>
<td>' . ($productObj->name ?: $this->l('Produit introuvable')) . '</td>
<td>' . $productObj->reference . '</td>
<td>' . $product['date_add'] . '</td>
<td>
<a href="' . AdminController::$currentIndex . '&configure=' . $this->name
. '&deleteProduct=1&id_product=' . (int)$product['id_product']
. '&token=' . Tools::getAdminTokenLite('AdminModules') . '"
class="btn btn-default btn-sm" onclick="return confirm(\'' . $this->l('Supprimer ce produit ?') . '\');">
<i class="icon-trash"></i>
</a>
</td>
</tr>';
}

$html .= '</tbody></table>';
}

$html .= '</div>';
}

return $html;
}

private function addProducts($productsString, $badgeType)
{
// Nettoyer et extraire les IDs
$productsString = preg_replace('/[^0-9,\s\n\r]/', '', $productsString);
$productIds = preg_split('/[\s,\n\r]+/', $productsString, -1, PREG_SPLIT_NO_EMPTY);
$productIds = array_unique(array_map('intval', $productIds));

$added = 0;
$errors = 0;

foreach ($productIds as $idProduct) {
if ($idProduct <= 0) {
$errors++;
continue;
}

// Vérifier si le produit existe
if (!Product::existsInDatabase($idProduct, 'product')) {
$errors++;
continue;
}

// Supprimer l'ancien badge si existant
Db::getInstance()->delete('offre_speciale_products', 'id_product = ' . (int)$idProduct);

// Insérer le nouveau
$result = Db::getInstance()->insert('offre_speciale_products', array(
'id_product' => (int)$idProduct,
'badge_type' => pSQL($badgeType),
'date_add' => date('Y-m-d H:i:s')
));

if ($result) {
$added++;
} else {
$errors++;
}
}

return array('success' => $added > 0, 'added' => $added, 'errors' => $errors);
}

private function clearAllProducts()
{
return Db::getInstance()->execute('TRUNCATE TABLE `' . _DB_PREFIX_ . 'offre_speciale_products`');
}

private function clearBadgeProducts($badgeType)
{
return Db::getInstance()->delete('offre_speciale_products', 'badge_type = "' . pSQL($badgeType) . '"');
}

private function removeProduct($idProduct)
{
return Db::getInstance()->delete('offre_speciale_products', 'id_product = ' . (int)$idProduct);
}

private function getProductsByBadge($badgeType)
{
return Db::getInstance()->executeS('
SELECT id_product, badge_type, date_add
FROM `' . _DB_PREFIX_ . 'offre_speciale_products`
WHERE badge_type = "' . pSQL($badgeType) . '"
ORDER BY date_add DESC
');
}

public function hookDisplayProductListReviews($params)
{
if (!isset($params['product']['id_product'])) {
return;
}

return $this->displayBadge($params['product']['id_product']);
}

public function hookDisplayProductAdditionalInfo($params)
{
if (!isset($params['product']['id_product'])) {
return;
}

return $this->displayBadge($params['product']['id_product']);
}

public function displayBadge($productId)
{
$badge = Db::getInstance()->getRow('
SELECT badge_type
FROM `' . _DB_PREFIX_ . 'offre_speciale_products`
WHERE id_product = ' . (int)$productId
);

if ($badge && isset($badge['badge_type'])) {
$badgeType = $badge['badge_type'];
$badgeClass = 'badge-offre-' . strtolower($badgeType);

return '<span class="badge-offre-speciale ' . $badgeClass . '">' . $badgeType . '</span>';
}

return '';
}
}

Kitesurf shop : achat aile de kitesurf, planche, aile, harnais, foil -

Kitesurf : ailes, planches, foil, barres, harnais, ...

Il y a 1 produit.

Les News du Blog Glissevolution

Kitesurf Shop – Matériel de Kitesurf chez GlissEvolution

Matériel de Kitesurf pour Tous les Niveaux

Chez GlissEvolution, nous proposons un large choix de matériel de kitesurf pour débutants, intermédiaires et experts. Que vous cherchiez à apprendre, progresser ou repousser vos limites, nous avons l’équipement qu’il vous faut. Bien choisir son matériel est essentiel pour progresser rapidement et rider en toute sécurité.

Twintips et Directionnelles

  • Planches twintip : idéales pour le freestyle et le big air, elles offrent un pop puissant et une excellente accroche.

  • Planches surf : parfaites pour le wave riding, elles apportent vitesse, maniabilité et fluidité dans les vagues.

Nos best-sellers incluent des modèles comme la Duotone Jaime ou l’Eleveight Process. Consultez notre guide d’achat planche de kitesurf pour trouver la board adaptée à votre style de ride.

Nos packs kitesurf complets sont conçus pour les riders sortant d’école ou souhaitant s’équiper d’un matériel prêt à naviguer. Chaque pack inclut aile, planche, barre et harnais, sélectionnés parmi les plus grandes marques : Duotone, F-ONE, Eleveight.
Un choix idéal pour progresser avec un matériel fiable, testé et garanti.

Bien Choisir Son Aile

Les ailes de kitesurf se déclinent en plusieurs formes :

  • C-shape pour le freestyle radical

  • Delta-shape pour la polyvalence

  • Ailes à boudin pour la stabilité

  • Ailes à caisson pour la performance en vent léger

Nous proposons les dernières nouveautés Duotone, F-ONE et Eleveight. Consultez notre guide d’achat ailes de kitesurf pour affiner votre choix.

Le harnais est essentiel pour votre confort et vos performances :

  • Harnais culotte : conseillé aux débutants et aux riders recherchant maintien lombaire.

  • Harnais ceinture : privilégié par les kitesurfeurs confirmés pour sa liberté de mouvement.

Nos sélections incluent des modèles de ION, Ride Engine et Manera.

Découvrez tous les accessoires indispensables :

  • Barres de kitesurf précises et durables

  • Pompes manuelles et électriques

  • Pièces détachées et bagagerie

Un rayon complet pour équiper votre aile et votre planche.

GlissEvolution propose aussi du matériel de kitesurf d’occasion contrôlé par nos experts. Profitez d’un excellent rapport qualité-prix et échangez votre ancien équipement contre du neuf.
Nos kits de réparation prolongent la durée de vie de votre aile ou planche.

Le kitefoil est la discipline tendance pour voler au-dessus de l’eau avec fluidité. Nous proposons des packs complets et des foils de marques réputées : Duotone, F-ONE, Takuma, Sabfoil, Cloud 9.
Idéal pour découvrir de nouvelles sensations, même par vent léger.

Protégez votre matériel avec nos housses de kitesurf adaptées aux voyages et au quotidien. Marques disponibles : ION, Mystic, Manera. L’accessoire indispensable pour sécuriser vos ailes, planches et barres.

Notre équipe de passionnés est à votre service pour vous guider dans le choix de votre équipement. Nous mettons à jour régulièrement nos bonnes affaires, promotions et nouveautés pour vous offrir le meilleur du kitesurf.

GlissEvolution, votre kitesurf shop en ligne et magasin spécialisé, vous accompagne depuis 2005 dans la pratique des sports de glisse.

Découvrez dès maintenant notre rayon kitesurf : ailes, planches, barres, harnais, accessoires et packs complets.

Consultez aussi nos guides d’achat kitesurf pour bien choisir votre matériel selon votre niveau et votre style de pratique.