Mini Shell
<?php
#chức năng tạo template trang sản phẩm để gen ra file tĩnh
require_once 'domain/domain.php';
function arr_search_key($array, $find){
foreach($array as $key => $value){
foreach($value as $v){
if($v == $find){
return $key;
break;
}
}
}
}
$domain = str_replace('www.','', $_SERVER['HTTP_HOST']);
$database = arr_search_key($domain_list, $domain);
define( 'DB_NAME', $database );
define( 'DB_USER', 'duytan' );
define( 'DB_PASSWORD', 'tandb' );
define( 'DB_HOST', 'localhost' ); //ip LAN ln_team
define( 'DB_CHARSET', 'utf8mb4' );
define( 'DB_COLLATE', '' );
define('WP_SITEURL', 'https://'.$domain);
define('WP_HOME', 'https://'.$domain);
if ( ! defined( 'ABSPATH' ) ) {
define( 'ABSPATH', __DIR__ . '/' );
}
define( 'WP_CONTENT_DIR', ABSPATH . 'wp-content' );
define('JSON_API', 'https://api-product-front.supover.com/api/v3/get-product-detail-json-id/');
$domain = $_SERVER['HTTP_HOST'];
$slug = isset($_GET['slug']) ? trim($_GET['slug']) : null;
if (empty($slug)) {
$exp = explode('/', $_SERVER['REQUEST_URI']);
$slug = $exp[2];
}
$url = 'https://' . $domain . '/product/' . $slug . '/';
#check template exits
$cacheDir = __DIR__ . '/cache_template/' . $domain;
$replace = [
'title' => 'REPLACE_PRODUCT_TITLE',
'product_id' => 'REPLACE_PRODUCT_ID',
'slug' => 'REPLACE_PRODUCT_SLUG',
'image' => 'REPLACE_PRODUCT_IMAGE',
'price' => 'REPLACE_PRODUCT_PRICE',
];
// Global persits data
$post = null;
$metas = [];
function load() {
global $post, $metas, $slug;
$conn = new mysqli(DB_HOST, DB_USER, DB_PASSWORD, DB_NAME);
$query = "SELECT ID, post_name, post_title, post_status FROM wp_posts WHERE post_name = '$slug' LIMIT 1";
$result = $conn->query($query) or die($conn->error);
while ($row = $result->fetch_assoc()) {
$post = $row;
}
if (empty($post) || $post['post_status'] != 'publish') {
header("HTTP/1.0 404 Not Found");
die('Page not found!');
}
$keys = '"json_shopify", "json_id", "external_id", "single_image", "_regular_price", "_price", "source", "single_image_old"';
$query = "SELECT meta_id, meta_key, meta_value FROM wp_postmeta WHERE post_id = ". $post['ID'] ." AND meta_key IN (". $keys .")";
$results = $conn->query($query) or die($conn->error);
while ($row = $results->fetch_assoc()) {
$metas[$row['meta_key']] = $row['meta_value'];
}
}
// Initial and load data first.
$cachePath = $cacheDir . '_v2.html';
try {
load();
if (!file_exists($cachePath)) {
# create template from first visit
$content = curl($url);
//check if exit data
if (strpos($content, 'kwpsupover/assets/js') !== false) {
if (!is_dir('cache_template')) { // dir doesn't exist, make it
mkdir('cache_template', 0777, true);
}
// Collect title variations
$title_variants = [];
preg_match('/<title>(.*?)<\/title>.*?"page_title":"(.*?)","post_type":.*?<h1 class="product-title product_title entry-title">(.*?)<\/.*?<label class="screen-reader-text" for="quantity.*?>(.*?)<\//sim', $content, $match_title);
preg_match('/"item":{"name":"(.*?)",.*?,"name":"(.*?)",/ims', $content, $match_json);
if (!empty($match_title)) {
unset($match_title[0]);
foreach ($match_title as $match) {
$matchTitle = trim($match);
$title_variants[] = $matchTitle;
$title_variants[] = html_entity_decode($matchTitle);
$title_variants[] = html_entity_decode(html_entity_decode($matchTitle));
}
}
if (!empty($match_json)) {
unset($match_json[0]);
foreach ($match_json as $mj) {
$title_variants[] = trim($mj);
}
}
// Prepare template
$template = $content;
$product_title = trim($post['post_title']);
$title_variants[] = $product_title;
$title_variants[] = json_encode($product_title);
$title_variants = array_diff($title_variants, ['Home']);
usort($title_variants, 'sort_weight');
$template = str_replace($title_variants, array_fill(0, count($title_variants), $replace['title']), $template);
$convertMeta = ImageUrlConvert($post['ID']);
$data = [
'product_id' => $post['ID'],
'slug' => $slug,
'image' => $convertMeta['image'],
'price' => $convertMeta['price']
];
$template = str_replace($data, array_slice($replace, 1), $template);
// Replace javascript json of product
$template = preg_replace('/<div class="product-thumbnails.*?<\/div>[\W]*?<\/div>/s', '', $template);
file_put_contents($cachePath, $template);
}
// Xuất kết quả
echo $content;
} else {
$template = file_get_contents($cachePath);
$new = [
'title' => htmlspecialchars(trim($post['post_title']), ENT_QUOTES),
'product_id' => $post['ID'],
'slug' => $slug,
'image' => ImageUrlConvert($post['ID'])['image'],
'price' => ImageUrlConvert($post['ID'])['price']
];
ob_start();
variation_generate($post['ID'], $post['post_title']);
$output = ob_get_clean();
$template = preg_replace('/<div id="dt_variation">.*?<\/div>/is', $output, $template);
//replace some old element to new element
echo str_replace(
$replace,
$new,
$template
);
echo '<!--4botv2-->';
}
} catch (\Exception $e) {
echo $e->getMessage();
}
function curl($url) {
$curl = curl_init($url);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curl, CURLOPT_USERAGENT, "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36");
curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($curl, CURLOPT_ENCODING, "gzip");
$content = curl_exec($curl);
curl_close($curl);
return $content;
}
function sort_weight($val1, $val2)
{
$a = strlen($val1);
$b = strlen($val2);
if ($a == $b) {
return 0;
}
return ($a < $b) ? -1 : 1;
}
function fetchProductJson()
{
global $metas, $post;
$productId = $post['ID'];
$product_json = $metas['json_shopify'] ?? null;
$json_id = $metas['json_id'] ?? null;
$design_id = $metas['external_id'] ?? null;
$single_image = $metas['single_image'] ?? null;
if($single_image != NULL && !empty($single_image)) {
include WP_CONTENT_DIR . '/plugins/kwpsupover/inc/sample_gm.php';
// Case single_image
$json = SampleGm::$json_sample;
$json = json_decode($json);
foreach ($json->images as $key => $image){
$json->images[$key]->src = $single_image;
}
return $json;
} else if(!empty($design_id)) {
include WP_CONTENT_DIR . '/plugins/kwpsupover/inc/sample_gm.php';
$gmJson = SampleGm::$json_sample;
//case design_id
$design_id = str_replace('88,','', $design_id);
$json = str_replace('design_id', $design_id, $gmJson);
return json_decode($json);
} else if(!empty($json_id)) {
//create cache json file
$cacheDir = WP_CONTENT_DIR . '/cache';
if (!file_exists($cacheDir)) {
mkdir($cacheDir, 0755, true);
}
$validity = 60 * 60; // 3600s = 1 hour
$filename = trim($json_id) . '.json';
$cachePath = $cacheDir .'/'. $filename;
if( file_exists($cachePath) && filectime($cachePath) > time() - $validity) {
// cache is valid, call it
$json = file_get_contents($cachePath);
} else {
// cache is invalid: recreate it
$json = curl(JSON_API.$json_id);
$json_decode = json_decode($json);
if (!empty($json) && !empty($json_decode->productId)){
file_put_contents($cachePath, $json);
}
}
$json_decode = json_decode($json);
//push to sv if json error "invalid type"
if (strpos($json, 'invalid type') !== false) {
//exit('post to sv');
file_get_contents('https://api-datacenter.supover.com/api/user/domain/fix-json-product-by-json-id/'.$json_id.'?api_key=1711134f-217c-4cc6-bd0f-85a3cc4a5ea2');
}
if (empty($json) || empty($json_decode->productId)){
//notice to tele
file_get_contents('https://supover.com/telemsg?text=json error '.WP_HOME.'?p='.$productId.' '.$json_id);
die('Product error. Please report issue to email [email protected]. Thank you <script>document.cookie = "wordpress_no_cache=true; expires=Thu, 18 Dec 2022 12:00:00 UTC; path='.get_the_permalink().'";</script>');
}
return $json_decode;
} else if (!empty($product_json)) { // case json_shopify
//fix lỗi show inch chracters
$product_json = str_replace(['u0022', 'u0027'], '', $product_json);
if (isJson($product_json) != 0){ //case sai format json
// exit('invalid');
echo '<meta http-equiv="refresh" content="1" URL="'.get_the_permalink().'?v='.rand(100, 500).'"><script>document.cookie = "wordpress_no_cache=true; expires=Thu, 18 Dec 2022 12:00:00 UTC; path='.get_the_permalink().'";</script>';
}
//case shopify_json
$json = json_decode($product_json);
//
if (empty($json->product->variants[0]->price)){
$price = $json->variants[0]->price;
} else {
$price = $json->product->variants[0]->price;
}
if (!empty($json->product)) {
$json = convertJsonData($json->product);
} else {
$json = $product_json;
//truong hop json custom nhung khong co single image
$single_image_old = $metas['single_image_old'] ?? null;
}
return json_decode($json);
} else {
return NULL;
}
}
function isJson($string) {
json_decode($string);
return json_last_error();
}
function cleanString($string) {
$string = str_replace(' ', '-', $string); // Replaces all spaces with hyphens.
return preg_replace('/[^A-Za-z0-9\-]/', '', $string); // Removes special chars.
}
// Main method to convert json data.
function convertJsonData($jsonArray) {
$options = [];
$variants = [];
$images = [];
// Get product options.
$attributes = $jsonArray->options;
if($attributes != NULL && sizeof($attributes) > 0) {
foreach ($attributes as $key => $attribute) {
$options[$attribute->name] = $attribute->values;
// array_push($options, $attribute->name);
}
}
// Get product varians.
$productVarians = $jsonArray->variants;
if($productVarians != NULL && sizeof($productVarians) > 0) {
foreach ($productVarians as $key1 => $variant) {
$item = [
"price"=>$variant->price,
"sku"=>$variant->sku,
"image_id"=>$variant->image_id
];
$itemOptions = [];
if(property_exists($variant, "option1")) {
array_push($itemOptions, $variant->option1);
}
if(property_exists( $variant, "option2")) {
array_push($itemOptions, $variant->option2);
}
if(property_exists( $variant, "option3")) {
array_push($itemOptions, $variant->option3);
}
$item["option"] = $itemOptions;
array_push($variants, $item);
}
}
// Get product iamges.
$productImages = $jsonArray->images;
if($productImages != NULL && sizeof($productImages) > 0) {
foreach ($productImages as $key2 => $image) {
$item = [
"id" => $image->id,
"src" => $image->src
];
array_push($images, $item);
}
}
$newJson = [
"options" =>$options,
"variants" => $variants,
"images" => $images
];
return json_encode($newJson);
}
function convertJson($jsonObject) {
$options = [];
$variants = [];
$images = [];
if(is_object($jsonObject)) {
if(property_exists($jsonObject, 'options')) {
// Get product options.
$attributes = $jsonObject->options;
if ($attributes != null) {
foreach ($attributes as $key => $attribute) {
if(is_numeric($key) && is_string($attribute)) {
if(!isset($options[$attribute])) {
$key = ucfirst($attribute);
$key = cleanString(ucfirst($key));
$options[$key] = [];
}
}else {
if(!isset($options[$key])) {
$key = cleanString(ucfirst($key));
$options[$key] = [];
}
}
}
}
// Get product images
$productImages = $jsonObject->images;
if ($productImages != null && sizeof($productImages) > 0) {
foreach ($productImages as $key2 => $image) {
$item = [
"id" => $image->id,
"src" => $image->src == null ? "" : $image->src
];
array_push($images, $item);
}
}
// Get product varians.
$productVarians = $jsonObject->variants;
if ($productVarians != null && sizeof($productVarians) > 0) {
foreach ($productVarians as $key1 => $variant) {
$item = [
"price" => round($variant->price, 2),
"sku"=>$variant->sku,
// Set default image if variant has not image id.
"image_id"=>$variant->image_id == null ? $images[0]['id'] : $variant->image_id
];
$itemOptions = [];
if (property_exists($variant, "option1")
&& $variant->option1 != null) {
array_push($itemOptions, str_replace('"', 'in', $variant->option1));
}
if (property_exists($variant, "option2")
&& $variant->option2 != null) {
array_push($itemOptions, str_replace('"', 'in', $variant->option2));
}
if (property_exists($variant, "option3")
&& $variant->option3 != null) {
array_push($itemOptions, str_replace('"', 'in', $variant->option3));
}
if(property_exists($variant, 'options')) {
$correctOption = [];
foreach ($variant->options as $option) {
if($option != null) {
$temp = str_replace("'", "", $option);
$temp = str_replace('"', 'in', $temp);
if(!array_search($temp, $correctOption)){
array_push($correctOption, $temp);
}
}
}
$itemOptions = $correctOption;
}
if(property_exists($variant, 'option')) {
$correctOption = [];
foreach ($variant->option as $option) {
if($option != NULL) {
$temp = str_replace("'", "", $option);
if(!array_search($temp, $correctOption)){
array_push($correctOption, $temp);
}
}
}
$itemOptions = $correctOption;
}
$item["option"] = $itemOptions;
array_push($variants, $item);
}
}
}
}
return [
"options" => $options,
"variants" => $variants,
"images" => $images
];
}
function getOptionValue($data) {
$variants = $data['variants'];
$options = $data['options'];
$i = 0;
foreach ($options as $k => &$option) {
foreach ($variants as $variant) {
$proOptions = $variant['option']; // safe_string($variant['option']); //tan add fix in
if(!in_array($proOptions[$i], $option)) {
array_push($option, $proOptions[$i]);
}
}
$i++;
}
return $options;
}
function genratePriceHtml($data) {
$price = array_column($data['variants'], 'price');
$min = 0;
$max = 0;
if(count($price) > 0) {
$min = min($price);
$max = max($price);
}
$price_html = null;
if ($min == $max) {
$price_html = '<span class="woocommerce-Price-amount amount"><span class="woocommerce-Price-amount amount"><span class="woocommerce-Price-currencySymbol">$</span>' . $min . '</span></span>';
} else {
$price_html = '<span class="woocommerce-Price-amount amount"><span class="woocommerce-Price-amount amount"><span class="woocommerce-Price-currencySymbol">$</span>' . $min . '</span></span> – <span class="woocommerce-Price-amount amount"><span class="woocommerce-Price-amount amount"><span class="woocommerce-Price-currencySymbol">$</span>' . $max . '</span></span>';
}
$price_html = "'" . $price_html . "'";
return $price_html;
}
function getDefaultViewOptions($variants, $selectedValue, $position, $default) {
$values = [];
$checked = array_pop($selectedValue);
foreach ($variants as $variant) {
$options = $variant['option'];
$containsSearch = 0 == count(array_diff($selectedValue, $options));
if($containsSearch && !in_array($variant['option'][$position], $values)) {
if($default != $variant['option'][$position]) {
array_push($values, $variant['option'][$position]);
}
}
}
return $values;
}
function genrateLayout($data, $productName) {
$options = $data['options'];
$variants = $data['variants'];
$html = '<table class="variations" cellspacing="0">';
$html .= '<tbody>';
$isCustomSize = 'style="display:none"';
if(
preg_match('/personali/', strtolower($productName))
|| preg_match('/custom/', strtolower($productName))
) {
$isCustomSize = '';
}
if($options != NULL || count($options) > 0) {
$selectedValue = [];
$i = 0;
foreach ($options as $option => $values) {
$html .= '<tr>';
$html .= '<td>';
$html .= '<span class="label-'.strtolower(str_replace(" ", "__", $option)).'" style="font-size: 17px; color: rgb(34, 34, 34); text-transform: capitalize;">'.$option.': <b>'.$values[0].'</b></span>';
$html .= '</td>';
$html .= '</tr>';
$html .= '<tr>';
$html .= '<td class="value woo-variation-items-wrapper">';
$html .= '<ul class="variable-items-wrapper reselect-clear option-'.strtolower(str_replace(" ", "__", $option)).'">';
if($i > 0 && count($selectedValue) > 0) {
$default = $values[0];
array_push($selectedValue, $default);
$html .= '<li class="variable-item selected" data-value="'.$default.'" data-option="'.$option.'">';
$html .= '<span class="variable-item-span variable-item-span-button">'.$default.'</span>';
$html .= '</li>';
$customValues = getDefaultViewOptions($variants, $selectedValue, $i, $default);
foreach ($customValues as $key => $value) {
$value = str_replace('"','in', $value); //tan them replace in
$html .= '<li class="variable-item" data-value="'.$value.'" data-option="'.$option.'">';
$html .= '<span class="variable-item-span variable-item-span-button">'.$value.'</span>';
$html .= '</li>';
}
}else {
foreach ($values as $key =>$value) {
$selected = '';
$value = str_replace('"','in', $value); //tan them replace in
if($key == 0) {
$selected = 'selected';
array_push($selectedValue, $value);
}
$html .= '<li class="variable-item '.$selected.'" data-value="'.$value.'" data-option="'.$option.'">';
$html .= '<span class="variable-item-span variable-item-span-button">'.$value.'</span>';
$html .= '</li>';
}
}
$html .= "</ul>";
$html .= '</td>';
$html .= '</tr>';
$i++;
}
$html .= '<tr ' . $isCustomSize . '>';
$html .= '<td>';
$html .= '<span id="attribute_custom_name" style="font-size: 17px; color: rgb(34, 34, 34); text-transform: capitalize;">Optional: <b>Custom text</b></span>';
$html .= '</td>';
$html .= '</tr>';
$html .= '<tr ' . $isCustomSize . '>';
$html .= '<td>';
$html .= '<input type="text" style="width: 100%; padding: 8px;" name="custom_text" value="" placeholder="Enter your custom text">';
$html .= '</td>';
$html .= '</tr>';
$html .= '<tr ' . $isCustomSize . '>';
$html .= '<td>';
$html .= '<span id="attribute_custom_file" style="font-size: 17px; color: rgb(34, 34, 34); text-transform: capitalize;">Optional: <b>Custom image (allow: png, jpg, gif)</b></span>';
$html .= '</td>';
$html .= '</tr>';
$html .= '<tr ' . $isCustomSize . '>';
$html .= '<td>';
$html .= '<input type="file" style="width: 100%; padding: 8px;" name="custom_file" id="custom_file" accept="image/*">';
$html .= '<input type="hidden" name="custom_file_name">';
$html .= '<input type="hidden" name="custom_file_url">';
$html .= '</td>';
$html .= '</tr>';
// $html .= '<tr>';
// $html .= '<td>';
foreach ($selectedValue as $value) {
$html .= '<input type="hidden" name="select_value[]" value="'.$value.'">';
}
// $html .= '</td>';
// $html .= '</tr>';
// $html .= '<tr>';
// $html .= '<td>';
$html .= '<input type="hidden" name="sku" value="">';
// $html .= '</td>';
// $html .= '</tr>';
// $html .= '<tr>';
// $html .= '<td>';
$html .= '<input type="hidden" name="image" value="">';
// $html .= '</td>';
// $html .= '</tr>';
// $html .= '<tr>';
// $html .= '<td>';
$html .= '<input type="hidden" name="price" value="">';
// $html .= '</td>';
// $html .= '</tr>';
// $html .= '<tr>';
// $html .= '<td>';
$html .= '<input type="hidden" name="name" value="">';
// $html .= '</td>';
// $html .= '<tr>';
// $html .= '<td>';
foreach ($options as $key => $option) {
$html .= '<input type="hidden" name="options[]" value="'.$key.'">';
}
$html .= '</td>';
}
$html .= '</tbody>';
$html .= "</table>";
return $html;
}
function ImageUrlConvert($product_id){
global $metas;
$json_id = $metas['json_id'] ?? null;
$single_image = $metas['single_image'] ?? null;
$price = $metas['_price'] ?? null;
$single_image_old = $metas['single_image_old'] ?? null;
if (!empty($single_image_old)){ //json_id, json_shopify
$img = $single_image_old;
if (strpos($single_image_old, 'http') === false) {
//case loi image link cua design id
$design_id = $metas['external_id'] ?? null;
$design_id = str_replace('88,', '', $design_id);
$img = "https://mockup.bizticket.net/image/1/$design_id/b0acae/front.jpg";
}
} elseif (!empty($single_image)){
//single image
$img = $single_image;
$price = "17.99";
} elseif (empty($single_image_old) && empty($json_id)){
//case shopify json cũ
$product_json = $metas['json_shopify'] ?? null;
$json = json_decode($product_json, true);
if (!empty($json['product'])) { //case json shopify
$img = $json['product']['images'][0]['src'];
}
else { //case json custom
// $img = $json['images'][0]['src'];
//exit();
}
if (empty($img)){ //case sp mac dinh
// $img = get_the_post_thumbnail_url($product_id);
}
} else {
// $img = get_the_post_thumbnail_url($product_id);
}
// DO not support default product yet to save performance
$return = [
'image' => $img,
'price' => $price
];
return $return;
}
function variation_generate($product_id, $productName)
{
global $metas;
// Only for custom single product
if (
!empty($metas['json_shopify']) ||
!empty($metas['json_id']) ||
!empty($metas['external_id']) ||
!empty($metas['single_image'])
) {
$rawJson = fetchProductJson();
$mJson = convertJson($rawJson);
// Fix value default
$setVarians = [];
array_push($setVarians, $mJson['variants']);
$j = 0;
foreach ($setVarians[0] as $setVarian) {
$i = 0;
foreach ($mJson['options'] as $key => $a) {
//echo $i;
if (!isset($setVarian['option'][$i])) {
array_push($setVarians[0][$j]['option'], 'default');
} else {
if (empty($setVarian['option'][$i])) {
$setVarian['option'][$key] = 'default';
}
}
$i++;
}
$j++;
}
$mJson['variants'] = $setVarians[0];
//-------------------
$options = getOptionValue($mJson);
$mJson['options'] = $options;
$price_html = genratePriceHtml($mJson);
$mViews = genrateLayout($mJson, $productName);
echo '<div id="dt_variation">';
echo ($mViews);
?>
<script>
jQuery(document).ready(function() {
jQuery("p.price").html(<?php echo $price_html ?>);
const variations = '<?php echo json_encode($mJson["variants"]) ?>';
const options = '<?php echo json_encode($mJson["options"]) ?>';
const images = '<?php echo json_encode($mJson["images"]) ?>';
tshirt.setVariations(variations);
tshirt.setOptions(options);
tshirt.setImages(images);
tshirt.setName('<?php echo $productName ?>')
});
</script>
</div>
<?php }
}