prefix . 'aieo_dmm_brand_extras'; } public static function managed_taxonomies() { return (array) apply_filters( 'aieo_dmm_brand_extras_taxonomies', array('product_brand') ); } public static function get($taxonomy, $term_id) { $taxonomy = (string) $taxonomy; $term_id = (int) $term_id; if ($taxonomy === '' || $term_id <= 0) { return self::defaults(); } $key = $taxonomy . ':' . $term_id; if (isset(self::$request_cache[$key])) { return self::$request_cache[$key]; } $cache_key = 'aieo_be:' . $key; $cached = wp_cache_get($cache_key, self::CACHE_GROUP); if (is_array($cached)) { self::$request_cache[$key] = $cached; return $cached; } global $wpdb; $table = self::table(); $row = $wpdb->get_row($wpdb->prepare( "SELECT * FROM {$table} WHERE taxonomy = %s AND term_id = %d LIMIT 1", $taxonomy, $term_id ), ARRAY_A); $row = is_array($row) ? $row : array(); $merged = self::defaults(); foreach ($merged as $col => $default) { if (array_key_exists($col, $row) && $row[$col] !== null) { $merged[$col] = $row[$col]; } } $merged['logo_image_id'] = $merged['logo_image_id'] ? (int) $merged['logo_image_id'] : null; $merged['hero_image_id'] = $merged['hero_image_id'] ? (int) $merged['hero_image_id'] : null; $merged['supplier_term_id'] = $merged['supplier_term_id'] ? (int) $merged['supplier_term_id'] : null; $merged['promo'] = (int) $merged['promo'] === 1 ? 1 : 0; $merged['priority'] = (int) $merged['priority']; $merged['bias'] = (float) $merged['bias']; $merged['gross_margin'] = ($merged['gross_margin'] === null || $merged['gross_margin'] === '') ? null : (float) $merged['gross_margin']; $gallery = $merged['gallery_image_ids']; if (is_string($gallery) && $gallery !== '') { $decoded = json_decode($gallery, true); $merged['gallery_image_ids'] = is_array($decoded) ? array_values(array_filter(array_map('intval', $decoded))) : array(); } else { $merged['gallery_image_ids'] = array(); } $merged['taxonomy'] = $taxonomy; $merged['term_id'] = $term_id; wp_cache_set($cache_key, $merged, self::CACHE_GROUP, self::CACHE_TTL); self::$request_cache[$key] = $merged; return $merged; } public static function save($taxonomy, $term_id, array $patch) { global $wpdb; $taxonomy = (string) $taxonomy; $term_id = (int) $term_id; if ($taxonomy === '' || $term_id <= 0) { return false; } $clean = self::sanitize($patch); if (empty($clean)) { return true; } $clean['taxonomy'] = $taxonomy; $clean['term_id'] = $term_id; $clean['updated_at'] = current_time('mysql', true); $table = self::table(); $existing_id = $wpdb->get_var($wpdb->prepare( "SELECT id FROM {$table} WHERE taxonomy = %s AND term_id = %d LIMIT 1", $taxonomy, $term_id )); if ($existing_id) { $r = $wpdb->update($table, $clean, array('id' => (int) $existing_id)); } else { $clean['created_at'] = $clean['updated_at']; $r = $wpdb->insert($table, $clean); } if ($r === false) { return false; } $key = $taxonomy . ':' . $term_id; unset(self::$request_cache[$key]); wp_cache_delete('aieo_be:' . $key, self::CACHE_GROUP); return true; } public static function delete($taxonomy, $term_id) { global $wpdb; $taxonomy = (string) $taxonomy; $term_id = (int) $term_id; if ($taxonomy === '' || $term_id <= 0) { return false; } $wpdb->delete(self::table(), array('taxonomy' => $taxonomy, 'term_id' => $term_id)); $key = $taxonomy . ':' . $term_id; unset(self::$request_cache[$key]); wp_cache_delete('aieo_be:' . $key, self::CACHE_GROUP); return true; } public static function defaults() { return array( 'logo_image_id' => null, 'hero_image_id' => null, 'headline' => '', 'history_text' => '', 'ambassadors_text' => '', 'importer_text' => '', 'website_url' => '', 'promo' => 0, 'priority' => 0, 'bias' => 0.0, 'gross_margin' => null, 'supplier_term_id' => null, 'footer_text' => '', 'gallery_image_ids' => array(), ); } public static function effective_margin_pct($term_id, $taxonomy = 'product_brand') { $row = self::get($taxonomy, (int) $term_id); if (isset($row['gross_margin']) && $row['gross_margin'] !== null && (float) $row['gross_margin'] > 0) { return (float) $row['gross_margin']; } return class_exists('AIEO_DMM') ? (float) AIEO_DMM::get_gross_margin_pct() : 60.0; } public static function margin_pct_for_product($product_id) { $product_id = (int) $product_id; $lookup_id = $product_id; if ($product_id > 0 && get_post_type($product_id) === 'product_variation') { $parent = (int) wp_get_post_parent_id($product_id); if ($parent > 0) { $lookup_id = $parent; } } foreach (self::managed_taxonomies() as $tax) { $terms = wp_get_post_terms($lookup_id, $tax, array('fields' => 'ids')); if (is_wp_error($terms) || empty($terms)) { continue; } foreach ($terms as $tid) { $row = self::get($tax, (int) $tid); if (isset($row['gross_margin']) && $row['gross_margin'] !== null && (float) $row['gross_margin'] > 0) { return (float) $row['gross_margin']; } } } return class_exists('AIEO_DMM') ? (float) AIEO_DMM::get_gross_margin_pct() : 60.0; } private static function sanitize(array $patch) { $out = array(); if (array_key_exists('logo_image_id', $patch)) { $v = (int) $patch['logo_image_id']; $out['logo_image_id'] = $v > 0 ? $v : null; } if (array_key_exists('hero_image_id', $patch)) { $v = (int) $patch['hero_image_id']; $out['hero_image_id'] = $v > 0 ? $v : null; } if (array_key_exists('headline', $patch)) { $out['headline'] = sanitize_text_field((string) $patch['headline']); } foreach (array('history_text', 'ambassadors_text', 'importer_text', 'footer_text') as $k) { if (array_key_exists($k, $patch)) { $out[$k] = wp_kses_post((string) $patch[$k]); } } if (array_key_exists('website_url', $patch)) { $url = esc_url_raw((string) $patch['website_url']); $out['website_url'] = strlen($url) > 500 ? substr($url, 0, 500) : $url; } if (array_key_exists('promo', $patch)) { $out['promo'] = !empty($patch['promo']) ? 1 : 0; } if (array_key_exists('priority', $patch)) { $out['priority'] = (int) $patch['priority']; } if (array_key_exists('bias', $patch)) { $bias = (float) $patch['bias']; if ($bias < 0) { $bias = 0; } if ($bias > 1) { $bias = 1; } $out['bias'] = $bias; } if (array_key_exists('gross_margin', $patch)) { $v = $patch['gross_margin']; if ($v === null || $v === '') { $out['gross_margin'] = null; } else { $m = (float) $v; if ($m < 1) { $m = 1; } if ($m > 99) { $m = 99; } $out['gross_margin'] = $m; } } if (array_key_exists('supplier_term_id', $patch)) { $v = (int) $patch['supplier_term_id']; $out['supplier_term_id'] = $v > 0 ? $v : null; } if (array_key_exists('gallery_image_ids', $patch)) { $ids = (array) $patch['gallery_image_ids']; $clean_ids = array(); foreach ($ids as $id) { $id = (int) $id; if ($id > 0) { $clean_ids[] = $id; } } $out['gallery_image_ids'] = wp_json_encode(array_values(array_unique($clean_ids))); } return $out; } public static function flush_request_cache() { self::$request_cache = array(); } public static function bootstrap() { static $done = false; if ($done) { return; } $done = true; add_action('delete_term', array(__CLASS__, 'on_delete_term'), 10, 3); } public static function on_delete_term($term_id, $tt_id, $taxonomy) { if (in_array((string) $taxonomy, self::managed_taxonomies(), true)) { self::delete((string) $taxonomy, (int) $term_id); } } }