<?php
/**
 * Plugin Name: WooCommerce CronJob Tabanlı Saatli İndirim (Nitelik Ayarlanabilir)
 * Description: Sunucu cronjob ile tetiklenen REST endpoint’ler sayesinde seçili kategorilerde, sadece belirli attribute slug ve değerine sahip varyasyonların fiyatını düşürür.
 * Version: 1.2
 * Author: Siz
 * Text Domain: wc-cron-indirim
 */

if ( ! defined( 'ABSPATH' ) ) {
    exit; // Güvenlik: dosyaya direkt erişim engelli
}

class WCCronDiscountPlugin {

    const OPTION_NAME = 'wc_cron_discount_settings'; // Ayarların kaydedileceği WP option key

    public function __construct() {
        // Admin menü ve ayarlar
        add_action( 'admin_menu', array( $this, 'register_admin_menu' ) );
        add_action( 'admin_init', array( $this, 'register_settings' ) );

        // REST API endpoint’ler
        add_action( 'rest_api_init', array( $this, 'register_rest_routes' ) );
    }

    /**
     * Admin'de "Cron İndirim" menüsünü ekle
     */
    public function register_admin_menu() {
        add_menu_page(
            __( 'Cron İndirim', 'wc-cron-indirim' ),
            __( 'Cron İndirim', 'wc-cron-indirim' ),
            'manage_options',
            'wc-cron-discount-settings',
            array( $this, 'settings_page_html' ),
            'dashicons-clock', // Dashicon
            63
        );
    }

    /**
     * Ayarları kaydetmek ve form alanlarını tanımlamak
     */
    public function register_settings() {
        register_setting(
            'wc_cron_discount_settings_group',    // Settings group ID
            self::OPTION_NAME,                    // Option name
            array( $this, 'sanitize_settings' )   // Temizleme callback
        );

        add_settings_section(
            'wc_cron_discount_main_section',
            __( 'WooCommerce Cronjob Tabanlı İndirim Ayarları', 'wc-cron-indirim' ),
            array( $this, 'settings_section_description' ),
            'wc-cron-discount-settings'
        );

        // İndirim Miktarı
        add_settings_field(
            'discount_amount',
            __( 'İndirim Miktarı (TL)', 'wc-cron-indirim' ),
            array( $this, 'field_discount_amount_callback' ),
            'wc-cron-discount-settings',
            'wc_cron_discount_main_section'
        );

        // Kategori seçimi
        add_settings_field(
            'discount_categories',
            __( 'İndirim Uygulanacak Kategoriler', 'wc-cron-indirim' ),
            array( $this, 'field_discount_categories_callback' ),
            'wc-cron-discount-settings',
            'wc_cron_discount_main_section'
        );

        // Secret Key
        add_settings_field(
            'secret_key',
            __( 'Cron Güvenlik Anahtarı (Secret Key)', 'wc-cron-indirim' ),
            array( $this, 'field_secret_key_callback' ),
            'wc-cron-discount-settings',
            'wc_cron_discount_main_section'
        );

        // --- YENİ ALANLAR: Attribute Slug ve Değerleri ---
        
        // 1) Attribute Slug
        add_settings_field(
            'attribute_slug',
            __( 'Nitelik (Attribute) Slug', 'wc-cron-indirim' ),
            array( $this, 'field_attribute_slug_callback' ),
            'wc-cron-discount-settings',
            'wc_cron_discount_main_section'
        );

        // 2) Attribute Değerleri
        add_settings_field(
            'attribute_values',
            __( 'Nitelik Değerleri (Virgülle Ayır)', 'wc-cron-indirim' ),
            array( $this, 'field_attribute_values_callback' ),
            'wc-cron-discount-settings',
            'wc_cron_discount_main_section'
        );
    }

    /**
     * Ayar grubu açıklaması
     */
    public function settings_section_description() {
        echo '<p>'.esc_html__( 'Sunucu cronjob’unuzda bu eklentinin REST endpointlerini tetikleyerek otomatik indirim uygulayabilirsiniz.', 'wc-cron-indirim' ).'</p>';
    }

    /**
     * Ayar değerlerini temizleme
     */
    public function sanitize_settings( $input ) {
        $sanitized = array();

        // İndirim Miktarı
        if ( isset( $input['discount_amount'] ) ) {
            $sanitized['discount_amount'] = floatval( $input['discount_amount'] );
        }

        // Kategoriler
        if ( isset( $input['discount_categories'] ) && is_array( $input['discount_categories'] ) ) {
            $sanitized['discount_categories'] = array_map( 'intval', $input['discount_categories'] );
        } else {
            $sanitized['discount_categories'] = array();
        }

        // Secret Key
        if ( isset( $input['secret_key'] ) ) {
            $sanitized['secret_key'] = sanitize_text_field( $input['secret_key'] );
        }

        // Attribute Slug
        if ( isset( $input['attribute_slug'] ) ) {
            $sanitized['attribute_slug'] = sanitize_text_field( $input['attribute_slug'] );
        } else {
            $sanitized['attribute_slug'] = '';
        }

        // Attribute Değerleri
        if ( isset( $input['attribute_values'] ) ) {
            // Metni sanitize edip kaydedelim. Virgülle ayrılmış şekilde.
            $vals = sanitize_text_field( $input['attribute_values'] );
            $sanitized['attribute_values'] = $vals;
        } else {
            $sanitized['attribute_values'] = '';
        }

        return $sanitized;
    }

    /**
     * Form alanı: İndirim Miktarı
     */
    public function field_discount_amount_callback() {
        $options         = get_option( self::OPTION_NAME );
        $discount_amount = isset( $options['discount_amount'] ) ? $options['discount_amount'] : '';
        echo '<input type="number" step="0.01" name="'.self::OPTION_NAME.'[discount_amount]" value="'.esc_attr($discount_amount).'" style="width:150px;" placeholder="Ör: 10" />';
        echo '<p class="description">'.esc_html__( 'Ürünlerin normal fiyatından düşülecek miktar (TL).', 'wc-cron-indirim' ).'</p>';
    }

    /**
     * Form alanı: Kategori Seçimi (çoklu)
     */
    public function field_discount_categories_callback() {
        $options     = get_option( self::OPTION_NAME );
        $saved_cats  = isset( $options['discount_categories'] ) ? (array) $options['discount_categories'] : array();

        $terms = get_terms( array(
            'taxonomy'   => 'product_cat',
            'hide_empty' => false,
        ) );

        if ( ! empty( $terms ) && ! is_wp_error( $terms ) ) {
            echo '<select name="'.self::OPTION_NAME.'[discount_categories][]" multiple style="min-width:200px; height:120px;">';
            foreach ( $terms as $term ) {
                $selected = in_array( $term->term_id, $saved_cats ) ? 'selected' : '';
                echo '<option value="' . esc_attr( $term->term_id ) . '" ' . $selected . '>' . esc_html( $term->name ) . '</option>';
            }
            echo '</select>';
            echo '<p class="description">'.esc_html__( 'Birden fazla kategori seçebilirsiniz (Ctrl / Cmd tuşu).', 'wc-cron-indirim' ).'</p>';
        } else {
            echo '<p>'.esc_html__( 'Hiç kategori bulunamadı.', 'wc-cron-indirim' ).'</p>';
        }
    }

    /**
     * Form alanı: Secret Key
     */
    public function field_secret_key_callback() {
        $options    = get_option( self::OPTION_NAME );
        $secret_key = isset( $options['secret_key'] ) ? $options['secret_key'] : '';
        echo '<input type="text" name="'.self::OPTION_NAME.'[secret_key]" value="'.esc_attr($secret_key).'" style="width:300px;" placeholder="Ör: 12345abcde" />';
        echo '<p class="description">'.esc_html__( 'Cron tetiklemelerinde kullanacağınız anahtar. URL’de ?key=… şeklinde geçmelidir.', 'wc-cron-indirim' ).'</p>';
    }

    /**
     * Form alanı: Attribute Slug
     */
    public function field_attribute_slug_callback() {
        $options        = get_option( self::OPTION_NAME );
        $attribute_slug = isset( $options['attribute_slug'] ) ? $options['attribute_slug'] : '';
        echo '<input type="text" name="'.self::OPTION_NAME.'[attribute_slug]" value="'.esc_attr($attribute_slug).'" style="width:200px;" placeholder="Ör: pa_size" />';
        echo '<p class="description">'.esc_html__( 'Hangi attribute (nitelik) slug\'ını kullanacaksınız? Örneğin "pa_size" veya "pa_ebat".', 'wc-cron-indirim' ).'</p>';
    }

    /**
     * Form alanı: Attribute Değerleri
     */
    public function field_attribute_values_callback() {
        $options         = get_option( self::OPTION_NAME );
        $attribute_values = isset( $options['attribute_values'] ) ? $options['attribute_values'] : '';
        echo '<input type="text" name="'.self::OPTION_NAME.'[attribute_values]" value="'.esc_attr($attribute_values).'" style="width:300px;" placeholder="Ör: 26cm,32cm" />';
        echo '<p class="description">'.esc_html__( 'Bu attribute slug\'ındaki hangi değerler indirim kapsamına girecek? Virgülle ayırarak giriniz.', 'wc-cron-indirim' ).'</p>';
    }

    /**
     * Admin ayar sayfasının HTML içeriği
     */
    public function settings_page_html() {
        if ( ! current_user_can( 'manage_options' ) ) {
            return;
        }

        echo '<div class="wrap wc-cron-discount-admin">';
        echo '<h1><span class="dashicons dashicons-clock" style="font-size: 30px; vertical-align:middle;"></span> ';
        echo esc_html__( 'WooCommerce Cronjob İndirim Ayarları', 'wc-cron-indirim' ) . '</h1>';

        echo '<form method="post" action="options.php" style="background:#fff; padding:20px; margin-top:15px; border:1px solid #ddd;">';
        settings_fields( 'wc_cron_discount_settings_group' );
        do_settings_sections( 'wc-cron-discount-settings' );
        submit_button( __( 'Ayarları Kaydet', 'wc-cron-indirim' ) );
        echo '</form>';

        // Bilgi bloğu
        $options = get_option( self::OPTION_NAME );
        $secret  = isset( $options['secret_key'] ) ? $options['secret_key'] : 'SECRET_KEY';
        $siteurl = get_site_url( null, '', 'https' );

        echo '<div style="margin-top:20px; padding:15px; background:#f9f9f9; border:1px solid #ddd;">';
        echo '<h2>'.esc_html__( 'Cronjob Kullanım Bilgisi', 'wc-cron-indirim' ).'</h2>';
        echo '<p>'.esc_html__( 'Sunucunuzun gerçek cron özelliğini kullanarak, belirli saatlerde bu eklentinin API uç noktalarını çağırabilirsiniz:', 'wc-cron-indirim' ).'</p>';
        echo '<ul style="list-style:disc; margin-left:20px;">';
        echo '<li>'.esc_html__( 'İndirim Uygula (Uygulamak için):', 'wc-cron-indirim' ).'<br />
             <code>curl -X POST "' . $siteurl . '/wp-json/daily-discount/v1/apply?key=' . $secret . '"</code></li>';
        echo '<li>'.esc_html__( 'İndirimi Geri Al (Fiyatları Eski Haline Döndürmek için):', 'wc-cron-indirim' ).'<br />
             <code>curl -X POST "' . $siteurl . '/wp-json/daily-discount/v1/remove?key=' . $secret . '"</code></li>';
        echo '</ul>';
        echo '<p><strong>'.esc_html__( 'Örnek', 'wc-cron-indirim' ).':</strong> '.esc_html__( 'Her gün 11:00’de indirim başlatmak için', 'wc-cron-indirim' ).'
            <br /><code>0 11 * * * curl -X POST "' . $siteurl . '/wp-json/daily-discount/v1/apply?key=' . $secret . '"</code></p>';
        echo '<p>'.esc_html__( 'Her gün 14:00’de indirimi sonlandırmak için', 'wc-cron-indirim' ).'
            <br /><code>0 14 * * * curl -X POST "' . $siteurl . '/wp-json/daily-discount/v1/remove?key=' . $secret . '"</code></p>';
        echo '</div>';

        echo '</div>';
    }

    /**
     * REST API endpoint'lerini tanımla
     */
    public function register_rest_routes() {
        register_rest_route(
            'daily-discount/v1',
            '/apply',
            array(
                'methods'  => 'POST',
                'callback' => array( $this, 'rest_apply_discount' ),
            )
        );

        register_rest_route(
            'daily-discount/v1',
            '/remove',
            array(
                'methods'  => 'POST',
                'callback' => array( $this, 'rest_remove_discount' ),
            )
        );
    }

    /**
     * /apply endpoint - İndirim uygula (Cronjob POST)
     */
    public function rest_apply_discount( $request ) {
        // Güvenlik kontrolü
        if ( ! $this->check_secret_key( $request ) ) {
            return new WP_Error( 'forbidden', 'Geçersiz veya eksik anahtar.', array( 'status' => 403 ) );
        }

        $options = get_option( self::OPTION_NAME );
        $discount_amount  = isset( $options['discount_amount'] ) ? floatval( $options['discount_amount'] ) : 0;
        $category_ids     = isset( $options['discount_categories'] ) ? (array) $options['discount_categories'] : array();
        $attribute_slug   = isset( $options['attribute_slug'] ) ? $options['attribute_slug'] : '';
        $attribute_values = isset( $options['attribute_values'] ) ? $options['attribute_values'] : '';

        if ( $discount_amount <= 0 || empty( $category_ids ) ) {
            return array( 'success' => false, 'message' => 'İndirim miktarı veya kategoriler ayarlanmamış.' );
        }

        // Attribute değerlerini virgülden ayırıp dizi haline getirelim
        $attr_vals_array = array();
        if ( $attribute_values ) {
            $attr_vals_array = array_map( 'trim', explode(',', $attribute_values ) );
        }

        // Basit + Varyasyonlu
        $args = array(
            'status' => 'publish',
            'limit'  => -1,
            'type'   => array( 'simple','variable' ),
            'tax_query' => array(
                array(
                    'taxonomy' => 'product_cat',
                    'field'    => 'term_id',
                    'terms'    => $category_ids,
                ),
            ),
        );

        $products = wc_get_products( $args );
        $count    = 0;

        foreach ( $products as $product ) {
            if ( $product->is_type( 'simple' ) ) {
                // Basit ürün
                $this->apply_discount_to_product( $product, $discount_amount );
                $count++;

            } elseif ( $product->is_type( 'variable' ) ) {
                // Tüm varyasyonları
                $variation_ids = $product->get_children();

                foreach ( $variation_ids as $variation_id ) {
                    $variation = wc_get_product( $variation_id );
                    if ( $variation && $variation->is_type( 'variation' ) ) {
                        
                        // Nitelik kontrolü
                        if ( $attribute_slug && ! empty( $attr_vals_array ) ) {
                            // Varyasyon attribute'ları
                            $attributes = $variation->get_attributes();
                            // Örneğin: $attributes['pa_size'] = "26cm"

                            // Eğer bu varyasyonun aradığımız attribute'u var ve değer listedeyse indirim uygula
                            if ( isset($attributes[ $attribute_slug ]) && in_array( $attributes[ $attribute_slug ], $attr_vals_array ) ) {
                                $this->apply_discount_to_product( $variation, $discount_amount );
                                $count++;
                            }
                        } else {
                            // Hiç attribute ayarlamadıysanız, TÜM varyasyonlara uygula
                            $this->apply_discount_to_product( $variation, $discount_amount );
                            $count++;
                        }
                    }
                }
            }
        }

        return array(
            'success' => true,
            'message' => 'İndirim uygulandı. Etkilenen ürün/varyasyon sayısı: ' . $count,
        );
    }

    /**
     * /remove endpoint - İndirimi geri al (Cronjob POST)
     */
    public function rest_remove_discount( $request ) {
        // Güvenlik kontrolü
        if ( ! $this->check_secret_key( $request ) ) {
            return new WP_Error( 'forbidden', 'Geçersiz veya eksik anahtar.', array( 'status' => 403 ) );
        }

        $options = get_option( self::OPTION_NAME );
        $category_ids     = isset( $options['discount_categories'] ) ? (array) $options['discount_categories'] : array();
        $attribute_slug   = isset( $options['attribute_slug'] ) ? $options['attribute_slug'] : '';
        $attribute_values = isset( $options['attribute_values'] ) ? $options['attribute_values'] : '';

        if ( empty( $category_ids ) ) {
            return array( 'success' => false, 'message' => 'Hiç kategori seçilmemiş.' );
        }

        // Attribute değerlerini virgülden ayırıp dizi haline getirelim
        $attr_vals_array = array();
        if ( $attribute_values ) {
            $attr_vals_array = array_map( 'trim', explode(',', $attribute_values ) );
        }

        $args = array(
            'status' => 'publish',
            'limit'  => -1,
            'type'   => array( 'simple','variable' ),
            'tax_query' => array(
                array(
                    'taxonomy' => 'product_cat',
                    'field'    => 'term_id',
                    'terms'    => $category_ids,
                ),
            ),
        );

        $products = wc_get_products( $args );
        $count    = 0;

        foreach ( $products as $product ) {
            if ( $product->is_type( 'simple' ) ) {
                // Basit ürün geri yükle
                $this->remove_discount_from_product( $product );
                $count++;

            } elseif ( $product->is_type( 'variable' ) ) {
                // Varyasyonlu üründeki her varyasyonu geri yükle
                $variation_ids = $product->get_children();

                foreach ( $variation_ids as $variation_id ) {
                    $variation = wc_get_product( $variation_id );
                    if ( $variation && $variation->is_type( 'variation' ) ) {
                        
                        // Nitelik kontrolü
                        if ( $attribute_slug && ! empty( $attr_vals_array ) ) {
                            $attributes = $variation->get_attributes();
                            if ( isset($attributes[ $attribute_slug ]) && in_array( $attributes[ $attribute_slug ], $attr_vals_array ) ) {
                                $this->remove_discount_from_product( $variation );
                                $count++;
                            }
                        } else {
                            // Attribute ayarlı değilse, tüm varyasyonları geri yükle
                            $this->remove_discount_from_product( $variation );
                            $count++;
                        }
                    }
                }
            }
        }

        return array(
            'success' => true,
            'message' => 'Fiyatlar eski haline döndü. Etkilenen ürün/varyasyon sayısı: ' . $count,
        );
    }

    /**
     * Tek bir (basit veya varyasyon) ürüne indirim uygula
     */
    private function apply_discount_to_product( $product, $discount_amount ) {
        $product_id = $product->get_id();

        // Daha önce kaydedilmediyse eski fiyatı sakla
        if ( ! get_post_meta( $product_id, '_old_regular_price', true ) ) {
            $regular_price = $product->get_regular_price();
            update_post_meta( $product_id, '_old_regular_price', $regular_price );
        }

        // Yeni fiyat
        $current_price = floatval( $product->get_regular_price() );
        $new_price     = $current_price - $discount_amount;
        if ( $new_price < 0 ) {
            $new_price = 0;
        }

        $product->set_regular_price( $new_price );
        $product->save();
    }

    /**
     * Tek bir (basit veya varyasyon) ürünün eski fiyatını geri yükle
     */
    private function remove_discount_from_product( $product ) {
        $product_id = $product->get_id();
        $old_price  = get_post_meta( $product_id, '_old_regular_price', true );

        if ( $old_price ) {
            $product->set_regular_price( $old_price );
            $product->save();

            // Meta'yı sil
            delete_post_meta( $product_id, '_old_regular_price' );
        }
    }

    /**
     * Secret key kontrolü
     */
    private function check_secret_key( $request ) {
        $options    = get_option( self::OPTION_NAME );
        $saved_key  = isset( $options['secret_key'] ) ? $options['secret_key'] : '';
        $given_key  = $request->get_param('key');

        if ( ! $saved_key || ! $given_key || $given_key !== $saved_key ) {
            return false;
        }
        return true;
    }
}

new WCCronDiscountPlugin();
  • Sol menüde “Cron İndirim” sayfasına girin.
  • İndirim Miktarı (örn. 10 TL)
  • Kategoriler (hangi kategorilerde uygulanacak)
  • Secret Key (Cron tetikleme güvenlik anahtarı)
  • Nitelik (Attribute) Slug (örn. pa_size)
  • Nitelik Değerleri (örn. 26cm,32cm) – virgülle ayırın
  • Kaydedin.