webtasarimofis adlı üyeden alıntı: mesajı görüntüle
Merhaba Arkadaşlar, Hayırlı Ramazanlar.
Woocommerce ile ticaret sitemi yapmaya çalışıyorum. Bir yerde takıldım. Hergün saat 11:00 ile 14:00 arasında belirli kategorilerdeki ürünlerin hepsinin otomatik 10 TL düşmesini istiyorum. 14:01 oldumu fiyatlar eski haline gelecek. Böyle bir eklenti var mı. Birde Eski fiyatının üzerinde çizgi falan olmayacak 2 fiyat gözükmeyecek tek fiyat görünecek.
şimdiden hepinize teşekkür ederim.
<?php
/**
 * Plugin Name: WooCommerce CronJob Tabanlı Saatli İndirim (Varyasyon Desteği)
 * Description: Sunucu cronjob ile tetiklenen REST endpoint’ler sayesinde seçili kategorilerdeki basit & varyasyonlu ürünlerin normal fiyatını indirim yapar/günceller.
 * Version: 1.0
 * Author: X
 * Text Domain: wc-cron-indirim
 */

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

class WCCronDiscountPlugin {

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

    public function __construct() {
        // Eklenti yüklenince admin ayarlarını ve REST endpointlerini kaydet
        add_action( 'admin_menu', array( $this, 'register_admin_menu' ) );
        add_action( 'admin_init', array( $this, 'register_settings' ) );

        // REST API endpointleri
        add_action( 'rest_api_init', array( $this, 'register_rest_routes' ) );
    }

    /**
     * Admin menüde "Cron İndirim" sayfası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: saat ikonu
            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'
        );
    }

    /**
     * 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 (term id array)
        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'] );
        }

        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 güvenlik için kullanacağınız anahtar. URL’de ?key=… şeklinde geçmelidir.', '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
        $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'i - Cronjob tarafından tetiklenir, indirim uygular
     */
    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();

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

        // Ürünleri (basit + varyasyonlu) çekmek için type => array('simple','variable') kullanıyoruz
        $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' ) ) {
                // Varyasyonlu ürün: tüm varyasyonlarını çek
                $variation_ids = $product->get_children();
                foreach ( $variation_ids as $variation_id ) {
                    $variation = wc_get_product( $variation_id );
                    if ( $variation && $variation->is_type( 'variation' ) ) {
                        $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'i - Cronjob tarafından tetiklenir, fiyatları eski haline döndürür
     */
    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();

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

        // Basit + varyasyonlu ürünleri al
        $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ünün tüm varyasyonlarını 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' ) ) {
                        $this->remove_discount_from_product( $variation );
                        $count++;
                    }
                }
            }
        }

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

    /**
     * Ürüne indirim uygula (basit veya varyasyon)
     */
    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 = $product->get_regular_price();
        $new_price     = floatval( $current_price ) - floatval( $discount_amount );
        if ( $new_price < 0 ) {
            $new_price = 0;
        }

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

    /**
     * Üründeki indirimli fiyatı kaldır, eski fiyata döndür
     */
    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 bilgisini sil, bir sonrakine temiz başlansın
            delete_post_meta( $product_id, '_old_regular_price' );
        }
    }

    /**
     * Secret key kontrolü (Cron’dan gelen istekte ?key=SECRET_KEY eşleşiyor mu?)
     */
    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;
    }
}

// Başlat
new WCCronDiscountPlugin();
  • Sunucunuzdaki (cPanel vb.) Cron Job bölümüne girin.
  • İndirim başlangıç saatiniz için (örneğin her gün 11:00’da) şu komutu ekleyin:
    0 11 * * * curl -X POST "https://SİTEADRESİNİZ/wp-json/daily-discount/v1/apply?key=SIFRELI_ANAHTARINIZ"
  • İndirim bitiş saatiniz için (örneğin her gün 14:00’da) şu komutu ekleyin:
    0 14 * * * curl -X POST "https://SİTEADRESİNİZ/wp-json/daily-discount/v1/remove?key=SIFRELI_ANAHTARINIZ"
  • SIFRELI_ANAHTARINIZ değeri, eklentinin ayar sayfasında girdiğiniz Secret Key değeriyle aynı olmalıdır.