<?php
/**
* Plugin Name: WooCommerce CronJob Tabanlı Saatli İndirim (Nitelik Ayarlanabilir)
* Description: Sunucu cronjob ile tetiklenen REST endpointler 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 endpointler
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 cronjobunuzda 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. URLde ?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:00de 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:00de 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.