/* ---------------------------
* 1688 parser (fully corrected)
* --------------------------*/
private function parse_1688_product_data($html, $url) {
libxml_use_internal_errors(true);
$dom = new DOMDocument();
@$dom->loadHTML($html);
$xpath = new DOMXPath($dom);
$product_data = array(
'title' => '',
'price' => '0',
'regular_price' => '0',
'images' => array(),
'description' => '',
'sku' => 'SKU-' . time(),
);
// ===== TITLE =====
$title_selectors = array(
'//*[@id="productTitle"]//div[contains(@class,"title-content")]/h1',
"//h1[@data-offer-title]",
"//h1[contains(@class,'title')]",
"//meta[@property='og:title']/@content"
);
foreach ($title_selectors as $sel) {
$nodes = $xpath->query($sel);
if ($nodes->length > 0) {
$product_data['title'] = ($sel === "//meta[@property='og:title']/@content")
? trim($nodes->item(0)->nodeValue)
: trim($nodes->item(0)->textContent);
$product_data['title'] = preg_replace('/\s*-\s*1688\.com\s*$/i', '', $product_data['title']);
if (!empty($product_data['title'])) break;
}
}
// ===== IMAGES =====
$all_images = array();
// 1. DOM selectors
$image_selectors = array(
'//*[@id="detailImg"]//img',
'//*[@id="dt-tab"]//img',
"//img[@data-src]",
"//img[@src]",
"//div[contains(@id,'desc-lazyload-container')]//img"
);
foreach ($image_selectors as $sel) {
$nodes = $xpath->query($sel);
foreach ($nodes as $node) {
$src = $node->getAttribute('data-src') ?: $node->getAttribute('src');
if ($src) {
if (strpos($src, '//') === 0) $src = 'https:' . $src;
$all_images[] = $this->clean_image_url($src, '1688');
}
}
}
// 2. Scripts JSON blobs / regex
$script_nodes = $xpath->query("//script");
foreach ($script_nodes as $script_node) {
$sc = $script_node->textContent;
// JSON arrays
if (preg_match('/(imageList|imageUrlList|imagePathList)\s*[:=]\s*(\[[^\]]+\])/i', $sc, $m)) {
$jsonfrag = $m[2];
$decoded = json_decode($jsonfrag, true);
if (is_array($decoded)) {
foreach ($decoded as $u) {
if (is_string($u)) {
if (strpos($u, '//') === 0) $u = 'https:' . $u;
$all_images[] = $this->clean_image_url($u, '1688');
} elseif (is_array($u) && isset($u[0])) {
$url = $u[0];
if (strpos($url, '//') === 0) $url = 'https:' . $url;
$all_images[] = $this->clean_image_url($url, '1688');
}
}
}
}
// Fallback regex for any URLs
if (preg_match_all('/https?:\/\/[^"\'\s]*\.(jpg|jpeg|png|webp)[^"\'\s]*/i', $sc, $m2)) {
foreach ($m2[0] as $u) {
if (strpos($u, '//') === 0) $u = 'https:' . $u;
$all_images[] = $this->clean_image_url($u, '1688');
}
}
}
// 3. Fallback HTML regex
if (empty($all_images)) {
if (preg_match_all('/
]+src=["\']([^"\']+)["\']/', $html, $matches)) {
foreach ($matches[1] as $src) {
if (strpos($src, '//') === 0) $src = 'https:' . $src;
$all_images[] = $this->clean_image_url($src, '1688');
}
}
}
$all_images = array_values(array_filter(array_unique($all_images)));
$product_data['images'] = array_slice($all_images, 0, 20);
// ===== DESCRIPTION =====
$desc_selectors = array(
"//div[contains(@class,'content') and contains(@class,'detail')]",
"//div[contains(@id,'mod-detail-description')]",
"//meta[@property='og:description']/@content"
);
foreach ($desc_selectors as $sel) {
$nodes = $xpath->query($sel);
if ($nodes->length > 0) {
$product_data['description'] = ($sel === "//meta[@property='og:description']/@content")
? trim($nodes->item(0)->nodeValue)
: trim($nodes->item(0)->textContent);
if (!empty($product_data['description'])) break;
}
}
// ===== PRICE =====
$price = '';
foreach ($script_nodes as $script_node) {
if (preg_match('/(price|offerPrice|rangePrice)\s*[:=]\s*["\']?([0-9.]+)/i', $script_node->textContent, $m)) {
$price = $m[2];
break;
}
}
if (!$price) {
$price_selectors = array(
"//span[contains(@class,'price')]",
"//div[contains(@class,'price')]",
"//span[contains(@class,'value')]",
"//em[contains(@class,'price')]"
);
foreach ($price_selectors as $sel) {
$els = $xpath->query($sel);
if ($els->length) {
$txt = preg_replace('/[^0-9.]/', '', trim($els->item(0)->textContent));
if ($txt) { $price = $txt; break; }
}
}
}
$product_data['price'] = $price ?: '0';
$product_data['regular_price'] = $product_data['price'];
libxml_clear_errors();
if (empty($product_data['title'])) {
return new WP_Error('parse_error', 'Could not extract product title from 1688.com');
}
return $product_data;
}
/* ---------------------------
* Helper: clean image URLs
* --------------------------*/
private function clean_image_url($url, $platform) {
$url = preg_replace('/\?.*$/', '', $url);
$url = preg_replace('/_\d+x\d+\.(jpg|png|webp|jpeg)$/i', '.$1', $url);
$url = preg_replace('/_Q\d+\.(jpg|png|webp|jpeg)$/i', '.$1', $url);
return $url;
}
Fatal error: Uncaught Error: Class "Shop_40_Core" not found in /var/www/shop40/wp-content/plugins/Shop-40 core/shop-40-core.php:29
Stack trace:
#0 /var/www/shop40/wp-includes/class-wp-hook.php(324): shop_40_core_init()
#1 /var/www/shop40/wp-includes/class-wp-hook.php(348): WP_Hook->apply_filters()
#2 /var/www/shop40/wp-includes/plugin.php(517): WP_Hook->do_action()
#3 /var/www/shop40/wp-settings.php(578): do_action()
#4 /var/www/shop40/wp-config.php(96): require_once('...')
#5 /var/www/shop40/wp-load.php(50): require_once('...')
#6 /var/www/shop40/wp-blog-header.php(13): require_once('...')
#7 /var/www/shop40/index.php(17): require('...')
#8 {main}
thrown in /var/www/shop40/wp-content/plugins/Shop-40 core/shop-40-core.php on line 29
Notice: Function _load_textdomain_just_in_time was called incorrectly. Translation loading for the woocommerce
domain was triggered too early. This is usually an indicator for some code in the plugin or theme running too early. Translations should be loaded at the init
action or later. Please see Debugging in WordPress for more information. (This message was added in version 6.7.0.) in /var/www/shop40/wp-includes/functions.php on line 6121