<?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 '';
}
}

Ailes de Kite – Ailes de Kitesurf Freeride, Vagues, Freestyle | Glissevolution

Ailes de kite

Il y a 5 produits.

Les News du Blog Glissevolution

Ailes de Kitesurf – GlissEvolution

L’Aile de Kitesurf : Le Cœur de Votre Équipement

L’aile de kitesurf est l’élément central de votre matériel. C’est elle qui détermine votre style de navigation, que vous soyez passionné de freeride, de surf dans les vagues, de big air ou de freestyle.
Chez GlissEvolution, nous vous proposons une large sélection d’ailes de kite adaptées à tous les niveaux et toutes les pratiques.

Comment Choisir Son Aile de Kitesurf ?

Le choix de votre aile dépend de trois critères essentiels :

  • Votre niveau : débutant, intermédiaire ou confirmé.

  • Votre pratique : freeride, vague, freestyle ou foil.

  • Les conditions de navigation : vent léger, modéré ou fort, et spécificités de votre spot.

Nos guides d’achat d’ailes de kitesurf et nos experts en magasin sont là pour vous aider à sélectionner l’aile idéale afin de maximiser vos sensations et vos performances.

Les Meilleures Marques d’Ailes de Kitesurf

Chez GlissEvolution, nous travaillons avec les plus grandes marques pour vous garantir performance, innovation et fiabilité :

  • Duotone : référence mondiale, réputée pour ses innovations et sa robustesse.

  • Eleveight : polyvalente et performante, adaptée à tous les styles.

  • F-ONE : incontournable pour le freeride, les vagues et le big air.

  • Reedin, HB Surfkite, Airush, Flysurfer : des modèles adaptés à chaque discipline et profil de rider.

Nos ailes sont testées et approuvées par des riders du monde entier, vous assurant une qualité haut de gamme.

Besoin d’Aide pour Choisir Votre Aile ?

Sélectionner la bonne aile peut sembler complexe. Notre équipe est disponible par téléphone, en boutique et via notre site pour vous fournir un accompagnement personnalisé.
Vous bénéficierez de recommandations adaptées à votre niveau, vos objectifs et vos spots de navigation.

Pourquoi Choisir GlissEvolution ?

  • Une sélection experte des meilleures marques du marché.

  • Des conseils personnalisés pour adapter votre aile à votre pratique.

  • Une gamme d’ailes d’occasion contrôlées pour des solutions accessibles et fiables.

Que vous soyez débutant ou rider expérimenté, GlissEvolution est votre partenaire pour des sessions de kitesurf inoubliables.

Explorez notre collection d’ailes de kitesurf dès maintenant et trouvez le modèle qui transformera vos sessions sur l’eau.