*/ private static array $products = []; /** @var array */ private static array $terms = []; /** * ID товара или вариации по GUID (включая черновики и корзину, чтобы не плодить дубли). */ public static function productId(string $guid): int { if (isset(self::$products[$guid])) { return self::$products[$guid]; } global $wpdb; // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- поиск по служебным полям во время обмена: нужен свежий результат без кеша; значения через prepare() $rows = $wpdb->get_results($wpdb->prepare( "SELECT pm.post_id AS id, pm.meta_key AS k FROM {$wpdb->postmeta} pm INNER JOIN {$wpdb->posts} p ON p.ID = pm.post_id WHERE pm.meta_key IN (%s, %s) AND pm.meta_value = %s AND p.post_type IN ('product', 'product_variation') ORDER BY p.ID ASC LIMIT 50", self::META, self::LEGACY_META, $guid )); $id = self::pick((array) $rows, [Lang::class, 'preferDefaultPost']); if ($id > 0) { self::$products[$guid] = $id; // Нашли только по старому полю — запоминаем GUID в своём. if (get_post_meta($id, self::META, true) === '') { update_post_meta($id, self::META, $guid); } } return $id; } /** * Другие товары с тем же GUID — переводы Polylang/WPML (оригинал обновляет обмен, переводы — нет). * * @return list */ public static function translationIds(string $guid, int $exceptId): array { global $wpdb; // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- поиск по служебным полям во время обмена: нужен свежий результат без кеша; значения через prepare() return array_map('intval', $wpdb->get_col($wpdb->prepare( "SELECT DISTINCT pm.post_id FROM {$wpdb->postmeta} pm INNER JOIN {$wpdb->posts} p ON p.ID = pm.post_id AND p.post_type = 'product' WHERE pm.meta_key IN (%s, %s) AND pm.meta_value = %s AND pm.post_id <> %d LIMIT 50", self::META, self::LEGACY_META, $guid, $exceptId ))); } public static function rememberProduct(string $guid, int $id): void { self::$products[$guid] = $id; } public static function termId(string $guid, string $taxonomy): int { $key = $taxonomy . '|' . $guid; if (isset(self::$terms[$key])) { return self::$terms[$key]; } global $wpdb; // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- поиск по служебным полям во время обмена: нужен свежий результат без кеша; значения через prepare() $rows = $wpdb->get_results($wpdb->prepare( "SELECT tm.term_id AS id FROM {$wpdb->termmeta} tm INNER JOIN {$wpdb->term_taxonomy} tt ON tt.term_id = tm.term_id WHERE tm.meta_key IN (%s, %s) AND tm.meta_value = %s AND tt.taxonomy = %s ORDER BY tm.term_id ASC LIMIT 50", self::META, self::LEGACY_META, $guid, $taxonomy )); $id = self::pick((array) $rows, [Lang::class, 'preferDefaultTerm']); if ($id > 0) { self::$terms[$key] = $id; if (get_term_meta($id, self::META, true) === '') { update_term_meta($id, self::META, $guid); } } return $id; } public static function rememberTerm(string $guid, string $taxonomy, int $id): void { self::$terms[$taxonomy . '|' . $guid] = $id; } /** * ID картинки в медиатеке по хешу файла (чтобы не загружать одно и то же повторно). */ public static function attachmentByMeta(string $key, string $hash): int { global $wpdb; // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- поиск по служебным полям во время обмена: нужен свежий результат без кеша; значения через prepare() return (int) $wpdb->get_var($wpdb->prepare( "SELECT pm.post_id FROM {$wpdb->postmeta} pm INNER JOIN {$wpdb->posts} p ON p.ID = pm.post_id AND p.post_type = 'attachment' WHERE pm.meta_key = %s AND pm.meta_value = %s ORDER BY pm.post_id ASC LIMIT 1", $key, $hash )); } /** * Сколько товаров на сайте связано с 1С (для сводки в настройках). */ public static function countProducts(): int { global $wpdb; // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- поиск по служебным полям во время обмена: нужен свежий результат без кеша; значения через prepare() return (int) $wpdb->get_var($wpdb->prepare( "SELECT COUNT(DISTINCT pm.post_id) FROM {$wpdb->postmeta} pm INNER JOIN {$wpdb->posts} p ON p.ID = pm.post_id AND p.post_type = 'product' AND p.post_status <> 'trash' WHERE pm.meta_key IN (%s, %s)", self::META, self::LEGACY_META )); } /** * @param list $rows */ private static function pick(array $rows, callable $prefer): int { $ids = array_values(array_unique(array_map(static fn(object $r): int => (int) $r->id, $rows))); return $ids ? (int) $prefer($ids) : 0; } }