/**
* Theme Functions for DTM Sale Information Site
* Includes: Maintenance Mode, Sorting/Filtering Logic, Script Enqueueing, Search Keyword Handling
* Based on plan: sort_filter_plan_20250422
* Final version incorporating user's latest code and search keyword handling.
*/
/* --- Maintenance Mode Code ---
function maintenance_mode() {
if ( ! current_user_can( 'edit_themes' ) && ! is_user_logged_in() ) {
wp_die( 'ただいまサイトメンテナンス中です。ご迷惑をおかけしますが、しばらくお待ちください。' );
}
}
add_action( 'get_header', 'maintenance_mode' );
*/
// --- Sorting and Filtering Logic ---
function my_custom_sale_item_query_mods( $query ) {
// Exit if in admin area or not the main query.
if ( is_admin() || ! $query->is_main_query() ) {
return;
}
// --- ▼▼▼ MODIFICATION START: Check for sale_item archive OR search ▼▼▼ ---
// Only apply modifications to the 'sale_item' post type archive.
// Also check if it's a search result page IF the post_type is specifically set to 'sale_item' OR 'keyword' is used
$is_sale_item_archive = $query->is_post_type_archive( 'sale_item' );
// Check if 'keyword' is set, implying a search from our custom form
$is_sale_item_search_via_keyword = isset( $_GET['keyword'] ) && !empty( trim( $_GET['keyword'] ) ) && isset( $_GET['post_type'] ) && $_GET['post_type'] === 'sale_item';
// Also consider if 's' is set and post_type is sale_item (e.g., direct URL access)
$is_sale_item_search_via_s = $query->is_search() && $query->get('post_type') === 'sale_item';
// Apply mods if it's the archive or a relevant search
if ( $is_sale_item_archive || $is_sale_item_search_via_keyword || $is_sale_item_search_via_s ) {
// --- ★★★ NEW: Handle 'keyword' parameter from custom search form ★★★ ---
if ( isset( $_GET['keyword'] ) && ! empty( trim( $_GET['keyword'] ) ) ) {
// Set the main query's search parameter ('s') from 'keyword'
$query->set( 's', sanitize_text_field( $_GET['keyword'] ) );
// Ensure post_type is set correctly when using keyword
if ($query->get('post_type') !== 'sale_item') {
$query->set('post_type', 'sale_item');
}
// Mark that this is a search query internally if needed
$query->is_search = true; // Explicitly set search context
}
// --- ★★★ End NEW ★★★ ---
// --- ▲▲▲ MODIFICATION END ▲▲▲ ---
// --- Base Filtering: Only show 'on sale' items by default (Apply only on archive, not search results) ---
// --- ▼▼▼ MODIFICATION START: Condition to apply base filter ▼▼▼ ---
// Apply only if it's the archive page AND not a search triggered by 'keyword' or 's'
if ( $is_sale_item_archive && ! $query->is_search() ) {
// --- ▲▲▲ MODIFICATION END ▲▲▲ ---
$show_all = isset( $_GET['show_all'] ) && $_GET['show_all'] === '1';
$meta_query = $query->get( 'meta_query' ) ?: [];
if (!is_array($meta_query)) { $meta_query = []; }
if (!isset($meta_query['relation'])) { $meta_query['relation'] = 'AND';}
if ( ! $show_all ) {
// ★★★ Verify 'is_on_sale' field name and value ('1', true, etc.) ★★★
$meta_query['on_sale_clause'] = [
'key' => 'is_on_sale',
'value' => '1', // ★★★ Value Check ★★★
'compare' => '=',
];
}
// Only set meta query here if it was modified
if (!empty($meta_query['on_sale_clause']) || isset($meta_query['relation'])) {
$query->set( 'meta_query', $meta_query );
}
}
// --- Filtering Conditions (Applied to both archive and search if params exist) ---
$meta_query = $query->get( 'meta_query' ) ?: []; // Get potentially modified meta query
if (!is_array($meta_query)) { $meta_query = []; }
if (!isset($meta_query['relation'])) { $meta_query['relation'] = 'AND';}
// Filter by Sale Period (End Date)
// ★★★ Verify 'soonest_sale_end_date' field name and Ymd format ★★★
if ( ! empty( $_GET['filter_period'] ) ) {
$period = sanitize_key( $_GET['filter_period'] );
$today_ymd = current_time( 'Ymd' );
if ( $period === 'today' ) {
$meta_query['period_clause'] = [
'key' => 'soonest_sale_end_date', // ★★★ Name Check ★★★
'value' => $today_ymd,
'compare' => '=',
'type' => 'DATE',
];
} elseif ( $period === 'within_week' ) {
$one_week_later_ymd = date( 'Ymd', strtotime( '+6 days', current_time( 'timestamp' ) ) );
$meta_query['period_clause'] = [
'key' => 'soonest_sale_end_date', // ★★★ Name Check ★★★
'value' => [ $today_ymd, $one_week_later_ymd ],
'compare' => 'BETWEEN',
'type' => 'DATE',
];
}
}
// Filter by Price Range (USD based)
// ★★★ Verify 'current_lowest_sale_price_usd' field name and numeric value ★★★
$min_price = isset( $_GET['min_price'] ) && is_numeric( $_GET['min_price'] ) ? (float) $_GET['min_price'] : null;
$max_price = isset( $_GET['max_price'] ) && is_numeric( $_GET['max_price'] ) ? (float) $_GET['max_price'] : null;
if ( $min_price !== null || $max_price !== null ) {
if ( $min_price !== null && $max_price !== null && $min_price > $max_price ) {
$temp = $min_price; $min_price = $max_price; $max_price = $temp;
}
if ( $min_price !== null && $max_price !== null ) {
$meta_query['price_clause'] = [
'key' => 'current_lowest_sale_price_usd', // ★★★ Name Check ★★★
'value' => [ $min_price, $max_price ],
'compare' => 'BETWEEN',
'type' => 'DECIMAL(10,2)', // Adjust precision if needed
];
} elseif ( $min_price !== null ) {
$meta_query['price_clause'] = [
'key' => 'current_lowest_sale_price_usd', // ★★★ Name Check ★★★
'value' => $min_price,
'compare' => '>=',
'type' => 'DECIMAL(10,2)',
];
} elseif ( $max_price !== null ) {
$meta_query['price_clause'] = [
'key' => 'current_lowest_sale_price_usd', // ★★★ Name Check ★★★
'value' => $max_price,
'compare' => '<=',
'type' => 'DECIMAL(10,2)',
];
}
}
// Apply the combined meta query (again, to ensure all clauses are included)
// Make sure not to overwrite existing meta query if only sorting is applied
if (count($meta_query) > 1 || (count($meta_query) == 1 && !isset($meta_query['relation']))) { // Check if clauses were added
$query->set( 'meta_query', $meta_query );
}
// --- Sorting Conditions (Applied to both archive and search if param exists) ---
if ( ! empty( $_GET['sort'] ) ) {
$sort_key = sanitize_key( $_GET['sort'] );
switch ( $sort_key ) {
case 'price_asc':
// ★★★ Verify 'current_lowest_sale_price_usd' field name ★★★
$query->set( 'meta_key', 'current_lowest_sale_price_usd' );
$query->set( 'orderby', 'meta_value_num' );
$query->set( 'order', 'ASC' );
break;
case 'price_desc':
// ★★★ Verify 'current_lowest_sale_price_usd' field name ★★★
$query->set( 'meta_key', 'current_lowest_sale_price_usd' );
$query->set( 'orderby', 'meta_value_num' );
$query->set( 'order', 'DESC' );
break;
case 'discount_desc':
// ★★★ Verify 'discount_percentage' field name ★★★
$query->set( 'meta_key', 'discount_percentage' );
$query->set( 'orderby', 'meta_value_num' );
$query->set( 'order', 'DESC' );
break;
case 'end_date_asc':
// ★★★ Verify 'soonest_sale_end_date' field name ★★★
$current_meta_query_sort = $query->get('meta_query');
if (!is_array($current_meta_query_sort)) $current_meta_query_sort = [];
$current_meta_query_sort['end_date_exists_clause'] = [
'key' => 'soonest_sale_end_date', // ★★★ Name Check ★★★
'compare' => 'EXISTS'
];
if (!isset($current_meta_query_sort['relation'])) $current_meta_query_sort['relation'] = 'AND';
$query->set('meta_query', $current_meta_query_sort);
$query->set( 'orderby', [ 'meta_value' => 'ASC', 'date' => 'DESC' ] );
$query->set( 'meta_key', 'soonest_sale_end_date' ); // ★★★ Name Check ★★★
break;
case 'date_desc':
$query->set( 'orderby', 'date' );
$query->set( 'order', 'DESC' );
break;
default:
// Keep default order (relevance for search, date for archive) unless specified
// --- ▼▼▼ MODIFICATION START: Default orderby condition ▼▼▼ ---
if ( $is_sale_item_archive && !$query->is_search() && empty($query->get('orderby')) ) { // Apply default only if archive, not search and not already set
$query->set( 'orderby', 'date' );
$query->set( 'order', 'DESC' );
} // For search, WordPress default relevance is usually fine
// --- ▲▲▲ MODIFICATION END ▲▲▲ ---
}
} else {
// Default sort order if no 'sort' param (date for archive, relevance for search)
// --- ▼▼▼ MODIFICATION START: Default orderby condition ▼▼▼ ---
if ( $is_sale_item_archive && !$query->is_search() ) { // Apply default only if archive and not search
$query->set( 'orderby', 'date' );
$query->set( 'order', 'DESC' );
}
// --- ▲▲▲ MODIFICATION END ▲▲▲ ---
}
} // end if $is_sale_item_archive || $is_sale_item_search_via_keyword || $is_sale_item_search_via_s
}
add_action( 'pre_get_posts', 'my_custom_sale_item_query_mods' );
// --- Generate HTML for Active Filters ---
function my_get_current_filters_html() {
$filters_html = '';
$base_url = get_post_type_archive_link( 'sale_item' );
$current_args = $_GET;
$sort_labels = [
'price_asc' => '価格が安い順 (USD)',
'price_desc' => '価格が高い順 (USD)',
'discount_desc' => '割引率が大きい順',
'end_date_asc' => 'セール終了が近い順',
'date_desc' => '新着順',
];
$period_labels = [
'today' => '今日終了',
'within_week' => '1週間以内終了',
];
// --- ▼▼▼ NEW: Handle 'keyword' for filter display ▼▼▼ ---
$search_term = isset( $current_args['keyword'] ) ? sanitize_text_field($current_args['keyword']) : '';
if ( !empty($search_term) ) {
$remove_args = $current_args;
unset( $remove_args['keyword'], $remove_args['s'] ); // Remove both keyword and s
$remove_url = add_query_arg( $remove_args, $base_url );
$filters_html .= '
検索: "' . esc_html( $search_term ) . '" × ';
}
// --- ▲▲▲ NEW ▲▲▲ ---
// Display Sort Order
if ( ! empty( $current_args['sort'] ) ) {
$current_sort_key = sanitize_key( $current_args['sort'] );
if ( isset( $sort_labels[$current_sort_key] ) ) {
$remove_args = $current_args; unset( $remove_args['sort'] );
$remove_url = add_query_arg( $remove_args, $base_url );
$filters_html .= '並び順: ' . esc_html( $sort_labels[$current_sort_key] ) . ' × ';
}
}
// Display Period Filter
if ( ! empty( $current_args['filter_period'] ) ) {
$current_period_key = sanitize_key( $current_args['filter_period'] );
if ( isset( $period_labels[$current_period_key] ) ) {
$remove_args = $current_args; unset( $remove_args['filter_period'] );
$remove_url = add_query_arg( $remove_args, $base_url );
$filters_html .= '期間: ' . esc_html( $period_labels[$current_period_key] ) . ' × ';
}
}
// Display Price Filter
$min_price = isset( $current_args['min_price'] ) && is_numeric( $current_args['min_price'] ) ? (float) $current_args['min_price'] : null;
$max_price = isset( $current_args['max_price'] ) && is_numeric( $current_args['max_price'] ) ? (float) $current_args['max_price'] : null;
if ( $min_price !== null || $max_price !== null ) {
$price_label = '価格 (USD): ';
$remove_args = $current_args; unset( $remove_args['min_price'], $remove_args['max_price'] );
if ( $min_price !== null && $max_price !== null && $min_price <= $max_price ) { $price_label .= '$' . esc_html( number_format( $min_price, 2 ) ) . ' ~ $' . esc_html( number_format( $max_price, 2 ) ); }
elseif ( $min_price !== null ) { $price_label .= '$' . esc_html( number_format( $min_price, 2 ) ) . ' 以上'; }
elseif ( $max_price !== null ) { $price_label .= '$' . esc_html( number_format( $max_price, 2 ) ) . ' 以下'; }
$remove_url = add_query_arg( $remove_args, $base_url );
$filters_html .= '' . $price_label . ' × ';
}
// Display "Clear All Filters" Link
// --- ▼▼▼ MODIFICATION START: Include search term in condition ▼▼▼ ---
$has_filters = ! empty( $current_args['sort'] )
|| ! empty( $current_args['filter_period'] )
|| isset( $current_args['min_price'] )
|| isset( $current_args['max_price'] )
|| ! empty( $search_term ); // Check if keyword filter is active
// --- ▲▲▲ MODIFICATION END ▲▲▲ ---
if ( $has_filters ) {
$remove_all_args = [];
if (isset($current_args['show_all']) && $current_args['show_all'] === '1') { $remove_all_args['show_all'] = '1'; }
// Don't preserve s or keyword when clearing all
$remove_all_url = add_query_arg( $remove_all_args, $base_url );
$filters_html .= 'すべてのフィルターを解除 ';
}
return $filters_html;
}
// --- Enqueue Scripts and Styles ---
function my_enqueue_theme_scripts() {
// Enqueue scripts/styles only on the relevant pages
// --- ▼▼▼ MODIFICATION START: Condition for loading scripts ▼▼▼ ---
$load_scripts = false;
if ( is_post_type_archive( 'sale_item' ) || is_tax( 'maker' ) || is_tax( 'product_category' ) ) {
$load_scripts = true;
} elseif ( is_search() ) {
// Load scripts on search results page ONLY if the search is for 'sale_item'
// Check either 'post_type' GET param OR if the query object is set to 'sale_item'
global $wp_query; // Make sure $wp_query is available
// Check if post_type is explicitly set to sale_item in GET or query vars
if ( (isset($_GET['post_type']) && $_GET['post_type'] === 'sale_item') || ($wp_query->get('post_type') === 'sale_item') ) {
// Further check if the search was initiated via 'keyword' from our form
if (isset($_GET['keyword'])) {
$load_scripts = true;
}
// Or if it was a standard search ('s' param) targeting sale_item
elseif (isset($_GET['s'])) {
$load_scripts = true;
}
}
}
// --- ▲▲▲ MODIFICATION END ▲▲▲ ---
if ( $load_scripts ) {
// Enqueue noUiSlider
wp_enqueue_style( 'nouislider-style', 'https://cdnjs.cloudflare.com/ajax/libs/noUiSlider/15.7.1/nouislider.min.css', [], '15.7.1' );
wp_enqueue_script( 'nouislider-script', 'https://cdnjs.cloudflare.com/ajax/libs/noUiSlider/15.7.1/nouislider.min.js', [], '15.7.1', true );
// Enqueue Custom Script
wp_enqueue_script( 'my-custom-script', get_stylesheet_directory_uri() . '/js/script.js', ['jquery', 'nouislider-script'], '1.3', true ); // Version bump
// Localize Script Data
global $wpdb;
// ★★★ Verify 'current_lowest_sale_price_usd' field name ★★★
$meta_key_for_max_price = 'current_lowest_sale_price_usd'; // Use variable for easier changes
$max_price_db = $wpdb->get_var( $wpdb->prepare( "SELECT MAX( CAST( meta_value AS DECIMAL(10,2) ) ) FROM $wpdb->postmeta WHERE meta_key = %s", $meta_key_for_max_price ) );
$slider_max_price = $max_price_db ? ceil( (float) $max_price_db ) : 5000; // Default 5000 if no data
$current_min_price = isset( $_GET['min_price'] ) && is_numeric( $_GET['min_price'] ) ? (float) $_GET['min_price'] : 0;
$current_max_price = isset( $_GET['max_price'] ) && is_numeric( $_GET['max_price'] ) ? (float) $_GET['max_price'] : $slider_max_price;
// Validate current min/max against slider range
if ($current_max_price > $slider_max_price) { $current_max_price = $slider_max_price; }
if ($current_min_price < 0) { $current_min_price = 0; }
if ($current_min_price > $current_max_price) { $current_min_price = $current_max_price; }
wp_localize_script( 'my-custom-script', 'saleItemData', [
'currentMinPrice' => $current_min_price,
'currentMaxPrice' => $current_max_price,
'sliderMaxPrice' => $slider_max_price,
'currentQueryParams' => $_GET, // Pass all GET params
'ajax_url' => admin_url( 'admin-ajax.php' )
]);
}
}
add_action( 'wp_enqueue_scripts', 'my_enqueue_theme_scripts' );
// --- Other Theme Setup / Includes (Keep as provided by user) ---
$inc_dir = get_stylesheet_directory() . '/inc';
require_once( $inc_dir . '/custom-seo.php' );
require_once( $inc_dir . '/admin-custom-tools.php' );
require_once( $inc_dir . '/custom-shortcode.php' );
require_once( $inc_dir . '/custom-widgets.php' );
require_once( $inc_dir . '/archive-only-sale.php' );
/**
* Chart.js とカスタムグラフスクリプトを single-sale_item.php で読み込む
* ★ 別のデータベースに接続し、USDとJPY両方のセール価格履歴を取得 (データ連携最終修正) ★
*/
function enqueue_sale_item_chart_scripts() {
// single-sale_item.php が表示されている場合のみ実行
if ( is_singular( 'sale_item' ) ) {
global $post;
// --- 1. Chart.js ライブラリの読み込み ---
wp_enqueue_script( 'chart-js', 'https://cdn.jsdelivr.net/npm/chart.js@4.4.2/dist/chart.umd.min.js', array(), '4.4.2', true );
// --- 2. 自作グラフ描画スクリプトの読み込み ---
$chart_js_path = get_stylesheet_directory() . '/js/price-chart.js';
$chart_js_uri = get_stylesheet_directory_uri() . '/js/price-chart.js';
if ( file_exists( $chart_js_path ) ) {
wp_enqueue_script( 'price-chart', $chart_js_uri, array('chart-js'), filemtime( $chart_js_path ), true );
} else {
error_log('Error: price-chart.js not found at ' . $chart_js_path);
// スクリプトがない場合は localize も実行しない
return;
}
// --- 3. 価格履歴データを取得・整形してJavaScriptに渡す ---
$chart_labels = array();
$chart_data_usd = array();
$chart_data_jpy = array();
$reference_price_usd = null; // Initialize reference price
// --- 3a. 参照価格(USD)を取得 ---
$reference_price_usd_raw = get_field('reference_price_usd', $post->ID);
// ★ 取得した値が数値または数値文字列の場合のみ float にキャスト、それ以外は null ★
if (isset($reference_price_usd_raw) && is_numeric($reference_price_usd_raw)) {
$reference_price_usd = (float)$reference_price_usd_raw;
} else {
// error_log("[Price Chart] Reference USD price not found or invalid for post ID: " . $post->ID . ". Value: " . print_r($reference_price_usd_raw, true));
}
// --- 3b. データベースから日ごとの最安セール価格(USD & JPY)を取得 ---
$product_id_field = get_field('product_id', $post->ID);
if ( !empty( $product_id_field ) && is_numeric( $product_id_field ) ) {
$target_product_id = (int)$product_id_field;
// error_log("[Price Chart DEBUG] Target Product ID: " . $target_product_id);
// --- 別データベースへの接続 ---
$custom_db = null; $db_error = null;
if ( defined('CUSTOM_DB_USER') && defined('CUSTOM_DB_PASSWORD') && defined('CUSTOM_DB_NAME') && defined('CUSTOM_DB_HOST') ) {
if (class_exists('wpdb')) {
$custom_db = new wpdb( CUSTOM_DB_USER, CUSTOM_DB_PASSWORD, CUSTOM_DB_NAME, CUSTOM_DB_HOST );
if ( ! empty( $custom_db->error ) ) { $db_error = "Custom DB Connection Error: " . print_r($custom_db->error, true); error_log("[Price Chart DEBUG] " . $db_error); $custom_db = null; }
// else { error_log("[Price Chart DEBUG] Custom DB Connection successful."); } // 成功ログ
} else { $db_error = "wpdb class not found."; error_log("[Price Chart DEBUG] " . $db_error); }
} else { $db_error = "Custom DB Credentials not defined."; error_log("[Price Chart DEBUG] " . $db_error); }
// --- 接続ここまで ---
if ( $custom_db instanceof wpdb ) {
$table_name = 'price_history'; // ★ テーブル名確認
$sql_query_string = "
SELECT DATE(created_at) as history_date, MIN(price_usd) as min_price_usd, MIN(price_jpy) as min_price_jpy
FROM `{$table_name}`
WHERE product_id = %d AND (price_usd IS NOT NULL OR price_jpy IS NOT NULL) AND created_at >= DATE_SUB(CURDATE(), INTERVAL 1095 DAY)
GROUP BY DATE(created_at) ORDER BY history_date ASC";
if (isset($sql_query_string) && isset($target_product_id)) {
$sql = $custom_db->prepare($sql_query_string, $target_product_id);
if ($sql) {
// error_log("[Price Chart DEBUG] Executing SQL: " . $sql); // ★実行するSQLをログ出力
$results = $custom_db->get_results( $sql, ARRAY_A );
if ($custom_db->last_error) {
// error_log("[Price Chart DEBUG] Custom DB Query Error: " . $custom_db->last_error);
} else {
// ★クエリ成功後の結果件数をログ出力
// error_log("[Price Chart DEBUG] Custom DB Query returned " . count($results) . " rows.");
if ( !empty( $results ) && is_array($results) ) {
$wp_timezone = new DateTimeZone(wp_timezone_string());
// error_log("[Price Chart DEBUG] Processing " . count($results) . " results..."); // ★ループ開始ログ
foreach ( $results as $row_index => $row ) {
// ★各行の内容をログ出力
// error_log("[Price Chart DEBUG] Row " . $row_index . ": " . print_r($row, true));
if (isset($row['history_date']) && ($row['min_price_usd'] !== null || $row['min_price_jpy'] !== null) && preg_match('/^\d{4}-\d{2}-\d{2}$/', $row['history_date'])) {
$date_obj = DateTime::createFromFormat('Y-m-d', $row['history_date'], $wp_timezone);
if ($date_obj instanceof DateTime) {
$formatted_date = $date_obj->format('Y/m/d');
$usd_val = isset($row['min_price_usd']) ? (float)$row['min_price_usd'] : null;
$jpy_val = isset($row['min_price_jpy']) ? (float)$row['min_price_jpy'] : null;
$chart_labels[] = $formatted_date;
$chart_data_usd[] = $usd_val;
$chart_data_jpy[] = $jpy_val;
// ★処理したデータをログ出力
// error_log("[Price Chart DEBUG] Processed Row " . $row_index . ": Date=" . $formatted_date . ", USD=" . var_export($usd_val, true) . ", JPY=" . var_export($jpy_val, true));
} else {
// error_log("[Price Chart DEBUG] Failed to parse date in Row " . $row_index . ": " . $row['history_date']);
}
} else {
// error_log("[Price Chart DEBUG] Invalid data or missing keys in Row " . $row_index . ": " . print_r($row, true));
}
}
// error_log("[Price Chart DEBUG] Finished processing results."); // ★ループ終了ログ
} else {
// error_log("[Price Chart] No valid price history rows found after query for product_id: " . $target_product_id);
}
}
} else { // error_log("[Price Chart DEBUG] wpdb::prepare failed.");
}
} else { // error_log("[Price Chart DEBUG] SQL string or target_product_id missing.");
}
} else { // error_log("[Price Chart] Custom DB connection failed or invalid.");
}
} else { // error_log("[Price Chart] product_id field missing or invalid.");
}
// --- 4. JavaScriptにデータを渡す ---
// 常に localize を実行し、JS側で最終判断させる
// error_log("[Price Chart DEBUG] Final data for JS - Labels: " . count($chart_labels) . ", USD: " . count($chart_data_usd) . ", JPY: " . count($chart_data_jpy) . ", Ref: " . var_export($reference_price_usd, true));
wp_localize_script(
'price-chart',
'priceChartData',
array(
'labels' => $chart_labels, // ラベル配列 (空の場合あり)
'data_usd' => $chart_data_usd, // USD価格配列 (null含む, 空の場合あり)
'data_jpy' => $chart_data_jpy, // JPY価格配列 (null含む, 空の場合あり)
'reference_usd' => $reference_price_usd // 参照価格 (float or null)
)
);
} // end if is_singular('sale_item')
}
add_action( 'wp_enqueue_scripts', 'enqueue_sale_item_chart_scripts' );
セール商品│エルミュ!~DAW&プラグインセール情報サイト~
DTM/DAW/プラグイン/音源セール一覧
Uncaught Error: Call to undefined function my_get_current_filters_html() in /home/noybrog/er-music.jp/public_html/music-app/wp-content/themes/the-thor-child/archive-sale_item.php on line 163
Call stack:
include()
wp-includes/template-loader.php:106 require_once('/home/noybrog/er-mus.../template-loader.php')
wp-blog-header.php:19 require('/home/noybrog/er-mus...p/wp-blog-header.php')
index.php:17 Query Monitor