if ( ! defined( 'ABSPATH' ) ) {
exit; // Ne fusson közvetlenül!
}
class SF_SH_Sync_Plugin {
/**
* A logfájl helye.
*/
const LOG_FILE = WP_CONTENT_DIR . '/sf-sync-log.txt';
/**
* A Superfaktúra‑adatok ideiglenes JSON fájlja.
*/
const PRODUCTS_FILE = WP_CONTENT_DIR . '/sf-products.json';
/**
* Superfaktúra API hitelesítési adatok –
* ✱✱✱ Módosítsd a saját kulcsaidra! ✱✱✱
*/
const SF_EMAIL = 'kacsalla@mentha.hu';
const SF_API_KEY = 'fZPZrkWIyz3wLdjRS6ND3bqRR07XWESc';
const SF_COMPANY_ID = '74660';
const SF_API_URL = 'https://moja.superfaktura.sk/stock_items/index.json';
/**
* Singleton példány.
* @var self|null
*/
private static $instance = null;
/**
* @return self
*/
public static function instance() {
if ( null === self::$instance ) {
self::$instance = new self();
}
return self::$instance;
}
/**
* Konstruktor: hookok regisztrálása.
*/
private function __construct() {
add_action( 'admin_menu', array( $this, 'register_menu' ) );
add_action( 'admin_post_sf_sh_run_sync', array( $this, 'handle_sync_request' ) );
}
/**
* Admin menü létrehozása.
*/
public function register_menu() {
add_menu_page(
__( 'SF → SH szinkron', 'sf-sh-sync' ),
'SF → SH szinkron',
'manage_woocommerce',
'sf-sh-sync',
array( $this, 'render_admin_page' ),
'dashicons-update',
56
);
}
/**
* Admin oldal renderelése.
*/
public function render_admin_page() {
if ( ! current_user_can( 'manage_woocommerce' ) ) {
wp_die( __( 'Nincs jogosultságod a művelethez.', 'sf-sh-sync' ) );
}
echo '
' . esc_html__( 'SF → SH szinkron', 'sf-sh-sync' ) . ' ';
if ( isset( $_GET['synced'] ) && '1' === $_GET['synced'] ) {
echo '
' . esc_html__( 'A szinkronizáció elindult. A napló azonnal frissül.', 'sf-sh-sync' ) . '
';
}
echo '
';
// Log megjelenítése
echo '
' . esc_html__( 'Napló (utolsó 100 sor)', 'sf-sh-sync' ) . ' ';
if ( file_exists( self::LOG_FILE ) ) {
echo '
';
} else {
echo '
' . esc_html__( 'Még nem jött létre napló.', 'sf-sh-sync' ) . '
';
}
echo '
';
}
/**
* A POST‑kérés feldolgozása, amikor a gombot megnyomták.
*/
public function handle_sync_request() {
if ( ! current_user_can( 'manage_woocommerce' ) ) {
wp_die( __( 'Nincs jogosultságod a művelethez.', 'sf-sh-sync' ) );
}
check_admin_referer( 'sf_sh_sync_nonce', 'sf_sh_sync_nonce_field' );
// Hosszú futás engedélyezése
@set_time_limit( 0 );
if ( function_exists( 'ignore_user_abort' ) ) {
@ignore_user_abort( true );
}
$this->log( '––––––––––––––––– Szinkron indítva –––––––––––––––––' );
$this->phase1_create_lookup();
$this->phase2_download_sf_data();
$this->phase3_process_products();
$this->log( '––––––––––––––––– Szinkron befejezve –––––––––––––––' );
wp_redirect( add_query_arg( 'synced', '1', menu_page_url( 'sf-sh-sync', false ) ) );
exit;
}
/* ---------------------------------------------------------------------
* FÁZIS 1
* ---------------------------------------------------------------------*/
private function phase1_create_lookup() {
global $wpdb;
$table_name = $wpdb->prefix . 'sh_hun_product_sku';
$charset_collate = $wpdb->get_charset_collate();
require_once ABSPATH . 'wp-admin/includes/upgrade.php';
$sql = "CREATE TABLE $table_name (
sku VARCHAR(32) NOT NULL,
post_id BIGINT(20) UNSIGNED NOT NULL,
UNIQUE KEY sku (sku)
) $charset_collate;";
dbDelta( $sql );
// Magyar nyelvű termékek összegyűjtése (WPML‑hez feltételezve)
$translations_table = $wpdb->prefix . 'icl_translations';
$product_ids = $wpdb->get_col( "SELECT element_id FROM $translations_table WHERE element_type IN ('post_product','post_product_variation') AND language_code = 'hu'" );
if ( empty( $product_ids ) ) {
$this->log( 'Nincs magyar nyelvű termék.' );
return;
}
$inserted = 0;
$postmeta_table = $wpdb->prefix . 'postmeta';
foreach ( $product_ids as $post_id ) {
$sku = $wpdb->get_var( $wpdb->prepare( "SELECT meta_value FROM $postmeta_table WHERE post_id = %d AND meta_key = '_sku'", $post_id ) );
if ( ! empty( $sku ) ) {
$res = $wpdb->replace(
$table_name,
array(
'sku' => $sku,
'post_id' => $post_id,
),
array( '%s', '%d' )
);
if ( false !== $res ) {
$inserted++;
}
}
}
$this->log( sprintf( 'FÁZIS 1: %d sor került a %s táblába.', $inserted, $table_name ) );
}
/* ---------------------------------------------------------------------
* FÁZIS 2
* ---------------------------------------------------------------------*/
private function phase2_download_sf_data() {
$this->log( 'FÁZIS 2: Termékadatok letöltése a Superfaktúrától...' );
$headers = array(
'Authorization' => sprintf( 'SFAPI email=%s&apikey=%s&company_id=%s', self::SF_EMAIL, self::SF_API_KEY, self::SF_COMPANY_ID ),
);
$page = 1;
$per_page = 100;
$all = array();
while ( true ) {
$url = add_query_arg( 'page', $page, self::SF_API_URL );
$response = wp_remote_get( $url, array( 'headers' => $headers, 'timeout' => 30 ) );
if ( is_wp_error( $response ) ) {
$this->log( 'cURL hiba: ' . $response->get_error_message() );
return;
}
$code = wp_remote_retrieve_response_code( $response );
if ( 200 !== $code ) {
$this->log( 'HTTP hiba kód: ' . $code );
return;
}
$body = wp_remote_retrieve_body( $response );
$json = json_decode( $body, true );
$count = count( $json );
if ( $count === 0 ) {
break;
}
$all = array_merge( $all, $json );
$this->log( sprintf( 'FÁZIS 2: %d. oldal (%d termék) letöltve.', $page, $count ) );
if ( $count < $per_page ) {
break;
}
$page++;
}
// Adatok mentése JSON-be
if ( false === file_put_contents( self::PRODUCTS_FILE, wp_json_encode( $all, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE ) ) ) {
$this->log( 'Hiba a JSON fájl írása során.' );
return;
}
$this->log( 'FÁZIS 2: Termékadatok sikeresen elmentve a ' . self::PRODUCTS_FILE . ' fájlba.' );
}
/* ---------------------------------------------------------------------
* FÁZIS 3
* ---------------------------------------------------------------------*/
private function phase3_process_products() {
global $wpdb;
if ( ! file_exists( self::PRODUCTS_FILE ) ) {
$this->log( 'FÁZIS 3: Nem található a JSON fájl.' );
return;
}
$json_content = file_get_contents( self::PRODUCTS_FILE );
if ( false === $json_content ) {
$this->log( 'FÁZIS 3: Hiba a JSON fájl beolvasása során.' );
return;
}
$data = json_decode( $json_content, true );
if ( JSON_ERROR_NONE !== json_last_error() ) {
$this->log( 'FÁZIS 3: JSON hiba – ' . json_last_error_msg() );
return;
}
$lookup_table = $wpdb->prefix . 'sh_hun_product_sku';
$postmeta_table = $wpdb->prefix . 'postmeta';
$updated_count = 0;
foreach ( $data as $item ) {
if ( ! isset( $item['StockItem']['sku'], $item['StockItem']['stock'] ) ) {
continue;
}
$sku = $item['StockItem']['sku'];
$new_stock = intval( $item['StockItem']['stock'] );
$post_id = $wpdb->get_var( $wpdb->prepare( "SELECT post_id FROM $lookup_table WHERE sku = %s", $sku ) );
if ( empty( $post_id ) ) {
continue;
}
// Aktuális stock meta lekérése
$current_stock = $wpdb->get_var( $wpdb->prepare( "SELECT meta_value FROM $postmeta_table WHERE post_id = %d AND meta_key = '_stock'", $post_id ) );
if ( null === $current_stock ) {
continue;
}
$current_stock = intval( $current_stock );
if ( $current_stock !== $new_stock ) {
$res = $wpdb->update(
$postmeta_table,
array( 'meta_value' => $new_stock ),
array(
'post_id' => $post_id,
'meta_key' => '_stock',
),
array( '%d' ),
array( '%d', '%s' )
);
if ( false !== $res ) {
$updated_count++;
}
// _stock_status kezelése
$current_status = $wpdb->get_var( $wpdb->prepare( "SELECT meta_value FROM $postmeta_table WHERE post_id = %d AND meta_key = '_stock_status'", $post_id ) );
if ( 0 === $current_stock && $new_stock > 0 && 'outofstock' === $current_status ) {
$wpdb->update( $postmeta_table, array( 'meta_value' => 'instock' ), array( 'post_id' => $post_id, 'meta_key' => '_stock_status' ), array( '%s' ), array( '%d', '%s' ) );
} elseif ( $current_stock > 0 && 0 === $new_stock && 'instock' === $current_status ) {
$backorders = $wpdb->get_var( $wpdb->prepare( "SELECT meta_value FROM $postmeta_table WHERE post_id = %d AND meta_key = '_backorders'", $post_id ) );
$new_status = ( 'yes' === $backorders ) ? 'onbackorder' : 'outofstock';
$wpdb->update( $postmeta_table, array( 'meta_value' => $new_status ), array( 'post_id' => $post_id, 'meta_key' => '_stock_status' ), array( '%s' ), array( '%d', '%s' ) );
}
}
}
$this->log( 'FÁZIS 3: Készlet frissítve, módosított rekordok száma: ' . $updated_count );
// WooCommerce attribute lookup frissítés ütemezése – Action Scheduler
if ( function_exists( 'as_schedule_single_action' ) ) {
as_schedule_single_action( time(), 'woocommerce_run_product_attribute_lookup_update_callback', array( $updated_count, 0 ) );
$this->log( 'FÁZIS 3: woocommerce_run_product_attribute_lookup_update_callback hook ütemezve.' );
} else {
$this->log( 'FÁZIS 3: Action Scheduler nem elérhető, a hook nem került ütemezésre.' );
}
// JSON törlése
@unlink( self::PRODUCTS_FILE );
}
/* ---------------------------------------------------------------------
* SEGÉD
* ---------------------------------------------------------------------*/
/**
* Üzenet bejegyzése a naplóba.
* @param string $msg
*/
private function log( $msg ) {
$line = gmdate( 'Y-m-d H:i:s' ) . ' – ' . $msg . PHP_EOL; // UTC idő; módosítsd, ha helyi kell
file_put_contents( self::LOG_FILE, $line, FILE_APPEND );
}
}
// Inicializálás
SF_SH_Sync_Plugin::instance();
Kentucky Absorb nyeregemelő - Spicehorse
Kentucky Absorb nyeregemelő SKU:
42505
5 rétegű felépítés
Csökkenti a ló hátára nehezedő nyomást
“Anti-slip” elcsúszás gátlás, gyors száradás
Vékony műbőr réteg, hogy enyhítse a nyomást a marnál
Mosógépben mosható 30°-on (szárítógépbe nem tehető)
Színek: kék-fehér-barna / fekete-fehér-barna / fekete-fehér-fekete
Az 5 rétegű felépítésének köszönhetően, a Kentucky Horsewear Absorb nyeregemelő tökéletesen kiegyenlíti és minimalizálja a nyereg és a lovas által okozott nyomást. Nagyobb kényelmet nyújt mind a lónak mind pedig a lovasnak.
Az Absorb nyeregemelő 4 cm vastag és több különböző technológiájú anyagból készült. A belső réteg egy abszorbens (sokk elnyelő) anyagból, memória habból és egy ütéscsillapító gél anyagból áll. A külső réteg pedig mikroszálas szellőzőnyílásokkal van ellátva a gyorsabb száradás érdekében és csúszásgátlóval rendelkezik. Az Absorb nyeregemelő maximális védelmet, nyomáscsökkentést és kényelmet biztosít a ló számára. Tisztítása, karbantartása egyszerű, mosógépben 30°-on mosható (szárítógépbe nem tehető).
Ez a weboldal sütiket (cookie-kat) használ a vásárlási élmény javítása érdekében. Gondoljuk egyet értesz ezzel, de ha mégis szeretnéd, a sütiket ki tudod kapcsolni a böngésző beállításaiban. Elfogad Tovább Adatvédelmi nyilatkozat