feat: release B2B Trade theme 2.1.0
This commit is contained in:
+314
-36
@@ -74,82 +74,360 @@ function fragrance_trade_filter_cases_archive( $query ) {
|
||||
if ( is_admin() || ! $query->is_main_query() ) {
|
||||
return;
|
||||
}
|
||||
// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Public archive filtering is read-only.
|
||||
if ( $query->is_post_type_archive( 'case' ) && ! empty( $_GET['case_type'] ) ) {
|
||||
$query->set( 'case_type', sanitize_text_field( wp_unslash( $_GET['case_type'] ) ) );
|
||||
}
|
||||
}
|
||||
add_action( 'pre_get_posts', 'fragrance_trade_filter_cases_archive' );
|
||||
|
||||
/** One-time setup on theme activation: migrate products and create pages. */
|
||||
function fragrance_trade_setup_site_on_activation() {
|
||||
if ( get_option( 'fragrance_trade_setup_done' ) ) {
|
||||
return;
|
||||
/** Return the default service records created for a fresh installation. */
|
||||
function fragrance_trade_service_seeds() {
|
||||
return array(
|
||||
'b2b_product_1' => array(
|
||||
'title' => __( '隐形车衣(TPU 保护膜)', 'fragrance-trade' ),
|
||||
'content' => __( '透明保护膜覆盖车漆表面,可帮助降低日常轻微划痕、飞石和污渍对漆面的影响。具体性能取决于所选产品系列。', 'fragrance-trade' ),
|
||||
'excerpt' => __( '车漆保护 · 透明外观 · 日常养护', 'fragrance-trade' ),
|
||||
),
|
||||
'b2b_product_2' => array(
|
||||
'title' => __( '彩色改色膜', 'fragrance-trade' ),
|
||||
'content' => __( '通过不同颜色和表面质感改变车辆外观,可根据车型、原车颜色和日常使用场景选择亮面、哑光等效果。', 'fragrance-trade' ),
|
||||
'excerpt' => __( '颜色选择 · 表面质感 · 外观焕新', 'fragrance-trade' ),
|
||||
),
|
||||
'b2b_product_3' => array(
|
||||
'title' => __( '隔热防爆膜', 'fragrance-trade' ),
|
||||
'content' => __( '用于车窗隔热与紫外线防护,可结合透光需求、隐私需求和法规要求选择适合的产品参数。', 'fragrance-trade' ),
|
||||
'excerpt' => __( '隔热需求 · 紫外线防护 · 车窗适用', 'fragrance-trade' ),
|
||||
),
|
||||
'b2b_product_4' => array(
|
||||
'title' => __( '陶瓷隔热膜', 'fragrance-trade' ),
|
||||
'content' => __( '陶瓷类隔热膜适合关注隔热表现和车内电子信号使用的车主,实际参数与适用位置以具体产品说明为准。', 'fragrance-trade' ),
|
||||
'excerpt' => __( '陶瓷膜料 · 信号兼容 · 隔热方案', 'fragrance-trade' ),
|
||||
),
|
||||
'b2b_product_5' => array(
|
||||
'title' => __( '天窗冰甲', 'fragrance-trade' ),
|
||||
'content' => __( '面向全景天窗的隔热保护项目,需要结合天窗结构、玻璃状况和所选膜料确认是否适合施工。', 'fragrance-trade' ),
|
||||
'excerpt' => __( '全景天窗 · 隔热需求 · 安装评估', 'fragrance-trade' ),
|
||||
),
|
||||
'b2b_product_6' => array(
|
||||
'title' => __( '前挡专用膜', 'fragrance-trade' ),
|
||||
'content' => __( '前挡膜重点平衡透光视野、隔热需求和夜间驾驶体验,选购时应核对产品参数及当地法规要求。', 'fragrance-trade' ),
|
||||
'excerpt' => __( '前挡适用 · 透光视野 · 隔热需求', 'fragrance-trade' ),
|
||||
),
|
||||
'b2b_product_7' => array(
|
||||
'title' => __( '个性定制彩绘膜', 'fragrance-trade' ),
|
||||
'content' => __( '可根据参考图和车辆尺寸沟通定制外观方案,制作前确认图案、颜色、覆盖范围与交付效果。', 'fragrance-trade' ),
|
||||
'excerpt' => __( '图案沟通 · 方案确认 · 定制施工', 'fragrance-trade' ),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/** Hashes of the previous untouched seed copy, used to avoid overwriting edited services. */
|
||||
function fragrance_trade_legacy_service_hashes() {
|
||||
return array(
|
||||
'b2b_product_1' => array( 'content' => '4ceefcf5b0d6835b2043eb974862641c4605408b249c47142a1384f8c6aba5a0', 'excerpt' => '474adc2b0a9cb84519f25b32f2aebaf66b7530c582d33a63fc428a70063982dd' ),
|
||||
'b2b_product_2' => array( 'content' => 'c587d08672a5a73bd9d675a1aaa105b1dec46331a099649474a4669097c41707', 'excerpt' => 'edbbf896ccab06c5cbc79922f2130c190cb4dcd9720d427abd861c5d866d9de2' ),
|
||||
'b2b_product_3' => array( 'content' => '49a236ff415f92de3c0a789ee42a7ea1083c60779f4dab3d80a162e9fbc534f7', 'excerpt' => '3be7e723aa8cfe1b5ce753e1ede8ceb5eb7122242a8bfde5dc6870e26291111e' ),
|
||||
'b2b_product_4' => array( 'content' => '96db23ecaebbe16a7fd90254f098d9d652367ea200fe658792a7097082017d56', 'excerpt' => '3e59947da9a09130aeb65c0695c4b0ca1b78737e2cc320184a05ab0b4ca18424' ),
|
||||
'b2b_product_5' => array( 'content' => '36d83bd3a439f92cdd89c4fb1e863e748d843733a9865b4740e9466c9ba0c916', 'excerpt' => '7e1985099340d070b75b2caa292cb877850bd7e7ed74a14d181dc98780d09666' ),
|
||||
'b2b_product_6' => array( 'content' => 'caf3a595cc58b69861d66dbb92a04cfdddbe6ebfe7ef10a47e00e5cbbc112ea1', 'excerpt' => '1f1fb96587343da8d3fd938ec47f8f7abfb0a57c52a447c7b84997973ce57999' ),
|
||||
'b2b_product_7' => array( 'content' => 'b1fda0e7a0c7b3445c61ac1ee1e53c7e27c0612c2e8706901f4a1c07d26959a0', 'excerpt' => '0815c3e0d55c9c491ecfa80d264f2c18e5112ab87e3366bc3bd7ca89c76a951c' ),
|
||||
);
|
||||
}
|
||||
|
||||
/** Find an existing seed by marker so a failed setup can be retried safely. */
|
||||
function fragrance_trade_find_seeded_service( $seed_key ) {
|
||||
$ids = get_posts(
|
||||
array(
|
||||
'post_type' => 'service',
|
||||
'post_status' => array( 'publish', 'pending', 'draft', 'auto-draft', 'future', 'private', 'inherit', 'trash' ),
|
||||
'posts_per_page' => 1,
|
||||
'fields' => 'ids',
|
||||
'meta_key' => '_fragrance_seed_key',
|
||||
'meta_value' => $seed_key,
|
||||
'no_found_rows' => true,
|
||||
)
|
||||
);
|
||||
return $ids ? (int) $ids[0] : 0;
|
||||
}
|
||||
|
||||
/** Locate an untouched service created by an older theme version and add its seed marker. */
|
||||
function fragrance_trade_find_legacy_seed_service( $seed_key, $seed, $legacy_hashes ) {
|
||||
$posts = get_posts(
|
||||
array(
|
||||
'post_type' => 'service',
|
||||
'post_status' => array( 'publish', 'pending', 'draft', 'auto-draft', 'future', 'private', 'inherit', 'trash' ),
|
||||
'title' => $seed['title'],
|
||||
'posts_per_page' => 5,
|
||||
'no_found_rows' => true,
|
||||
)
|
||||
);
|
||||
foreach ( $posts as $post ) {
|
||||
if (
|
||||
hash_equals( $legacy_hashes['content'], hash( 'sha256', $post->post_content ) )
|
||||
&& hash_equals( $legacy_hashes['excerpt'], hash( 'sha256', $post->post_excerpt ) )
|
||||
) {
|
||||
update_post_meta( $post->ID, '_fragrance_seed_key', $seed_key );
|
||||
return (int) $post->ID;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Update only untouched seed copy; preserve every service that an administrator edited. */
|
||||
function fragrance_trade_migrate_seed_service_copy( &$errors ) {
|
||||
$changed = false;
|
||||
$legacy_hashes = fragrance_trade_legacy_service_hashes();
|
||||
|
||||
foreach ( fragrance_trade_service_seeds() as $seed_key => $seed ) {
|
||||
$post_id = fragrance_trade_find_seeded_service( $seed_key );
|
||||
if ( ! $post_id && isset( $legacy_hashes[ $seed_key ] ) ) {
|
||||
$post_id = fragrance_trade_find_legacy_seed_service( $seed_key, $seed, $legacy_hashes[ $seed_key ] );
|
||||
}
|
||||
if ( ! $post_id || ! isset( $legacy_hashes[ $seed_key ] ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$post = get_post( $post_id );
|
||||
$update = array( 'ID' => $post_id );
|
||||
if ( hash_equals( $legacy_hashes[ $seed_key ]['content'], hash( 'sha256', $post->post_content ) ) ) {
|
||||
$update['post_content'] = $seed['content'];
|
||||
}
|
||||
if ( hash_equals( $legacy_hashes[ $seed_key ]['excerpt'], hash( 'sha256', $post->post_excerpt ) ) ) {
|
||||
$update['post_excerpt'] = $seed['excerpt'];
|
||||
}
|
||||
if ( 1 === count( $update ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$updated = wp_update_post( $update, true );
|
||||
if ( is_wp_error( $updated ) ) {
|
||||
$errors[] = sprintf(
|
||||
/* translators: 1: service title, 2: error message. */
|
||||
__( '无法更新服务“%1$s”的默认文案:%2$s', 'fragrance-trade' ),
|
||||
$seed['title'],
|
||||
$updated->get_error_message()
|
||||
);
|
||||
continue;
|
||||
}
|
||||
$changed = true;
|
||||
}
|
||||
|
||||
$product_fallbacks = array(
|
||||
'products/placeholder-01.svg',
|
||||
'products/placeholder-02.svg',
|
||||
'products/placeholder-03.svg',
|
||||
'products/placeholder-04.svg',
|
||||
'products/placeholder-05.svg',
|
||||
'products/placeholder-06.svg',
|
||||
'products/placeholder-07.svg',
|
||||
);
|
||||
for ( $index = 1; $index <= count( $product_fallbacks ); $index++ ) {
|
||||
$title = fragrance_trade_get_mod( 'b2b_product_' . $index . '_title' );
|
||||
return $changed;
|
||||
}
|
||||
|
||||
/** Create seed services while preserving legacy Customizer product values. */
|
||||
function fragrance_trade_create_seed_services( &$errors ) {
|
||||
if ( get_option( 'fragrance_trade_setup_done' ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$changed = false;
|
||||
foreach ( fragrance_trade_service_seeds() as $seed_key => $seed ) {
|
||||
if ( fragrance_trade_find_seeded_service( $seed_key ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$title = get_theme_mod( $seed_key . '_title', $seed['title'] );
|
||||
if ( ! $title ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$post_id = wp_insert_post(
|
||||
array(
|
||||
'post_type' => 'service',
|
||||
'post_title' => $title,
|
||||
'post_content' => fragrance_trade_get_mod( 'b2b_product_' . $index . '_text' ),
|
||||
'post_excerpt' => fragrance_trade_get_mod( 'b2b_product_' . $index . '_specs' ),
|
||||
'post_content' => get_theme_mod( $seed_key . '_text', $seed['content'] ),
|
||||
'post_excerpt' => get_theme_mod( $seed_key . '_specs', $seed['excerpt'] ),
|
||||
'post_status' => 'publish',
|
||||
)
|
||||
),
|
||||
true
|
||||
);
|
||||
if ( $post_id && ! is_wp_error( $post_id ) ) {
|
||||
$image = fragrance_trade_get_mod( 'b2b_product_' . $index . '_image', '' );
|
||||
if ( $image ) {
|
||||
update_post_meta( $post_id, '_service_image', $image );
|
||||
}
|
||||
if ( is_wp_error( $post_id ) ) {
|
||||
$errors[] = sprintf(
|
||||
/* translators: 1: service title, 2: error message. */
|
||||
__( '无法创建服务“%1$s”:%2$s', 'fragrance-trade' ),
|
||||
$title,
|
||||
$post_id->get_error_message()
|
||||
);
|
||||
continue;
|
||||
}
|
||||
|
||||
update_post_meta( $post_id, '_fragrance_seed_key', $seed_key );
|
||||
$image = get_theme_mod( $seed_key . '_image', '' );
|
||||
if ( $image ) {
|
||||
update_post_meta( $post_id, '_service_image', $image );
|
||||
}
|
||||
$changed = true;
|
||||
}
|
||||
|
||||
return $changed;
|
||||
}
|
||||
|
||||
/** Find a conventional page, including the renamed slug WordPress uses in Trash. */
|
||||
function fragrance_trade_find_required_page( $slug ) {
|
||||
$pages = get_posts(
|
||||
array(
|
||||
'post_type' => 'page',
|
||||
'post_status' => array( 'publish', 'pending', 'draft', 'auto-draft', 'future', 'private', 'inherit', 'trash' ),
|
||||
'post_name__in' => array( $slug, $slug . '__trashed' ),
|
||||
'posts_per_page' => 1,
|
||||
'orderby' => 'post_name__in',
|
||||
'no_found_rows' => true,
|
||||
)
|
||||
);
|
||||
return $pages ? $pages[0] : null;
|
||||
}
|
||||
|
||||
/** Create or repair the required pages without changing existing content or status. */
|
||||
function fragrance_trade_create_required_pages( &$errors ) {
|
||||
$pages = array(
|
||||
'home' => array( 'post_title' => __( '首页', 'fragrance-trade' ), 'template' => '' ),
|
||||
'about' => array( 'post_title' => __( '关于门店', 'fragrance-trade' ), 'template' => 'page-about.php' ),
|
||||
'faq' => array( 'post_title' => __( '常见问题', 'fragrance-trade' ), 'template' => 'page-faq.php' ),
|
||||
'contact' => array( 'post_title' => __( '预约/联系', 'fragrance-trade' ), 'template' => 'page-contact.php' ),
|
||||
'contact' => array( 'post_title' => __( '联系我们', 'fragrance-trade' ), 'template' => 'page-contact.php' ),
|
||||
);
|
||||
$created = array();
|
||||
$result = array( 'changed' => false, 'pages' => array() );
|
||||
|
||||
foreach ( $pages as $slug => $data ) {
|
||||
$existing = get_page_by_path( $slug );
|
||||
if ( $existing ) {
|
||||
$created[ $slug ] = $existing->ID;
|
||||
$page = fragrance_trade_find_required_page( $slug );
|
||||
if ( $page ) {
|
||||
if ( $data['template'] && get_page_template_slug( $page->ID ) !== $data['template'] ) {
|
||||
$updated = wp_update_post(
|
||||
array(
|
||||
'ID' => $page->ID,
|
||||
'page_template' => $data['template'],
|
||||
),
|
||||
true
|
||||
);
|
||||
if ( is_wp_error( $updated ) ) {
|
||||
$errors[] = sprintf(
|
||||
/* translators: 1: page title, 2: error message. */
|
||||
__( '无法更新页面“%1$s”的模板:%2$s', 'fragrance-trade' ),
|
||||
$page->post_title,
|
||||
$updated->get_error_message()
|
||||
);
|
||||
} else {
|
||||
$result['changed'] = true;
|
||||
}
|
||||
}
|
||||
if ( 'publish' !== $page->post_status ) {
|
||||
// Preserve user-owned draft and trash states; the admin notice below explains the impact.
|
||||
} else {
|
||||
$result['pages'][ $slug ] = $page->ID;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
$id = wp_insert_post(
|
||||
|
||||
$page_id = wp_insert_post(
|
||||
array(
|
||||
'post_type' => 'page',
|
||||
'post_name' => $slug,
|
||||
'post_title' => $data['post_title'],
|
||||
'post_status' => 'publish',
|
||||
'page_template' => $data['template'],
|
||||
)
|
||||
),
|
||||
true
|
||||
);
|
||||
if ( $id && ! is_wp_error( $id ) ) {
|
||||
$created[ $slug ] = $id;
|
||||
if ( is_wp_error( $page_id ) ) {
|
||||
$errors[] = sprintf(
|
||||
/* translators: 1: page title, 2: error message. */
|
||||
__( '无法创建页面“%1$s”:%2$s', 'fragrance-trade' ),
|
||||
$data['post_title'],
|
||||
$page_id->get_error_message()
|
||||
);
|
||||
continue;
|
||||
}
|
||||
$result['changed'] = true;
|
||||
$result['pages'][ $slug ] = $page_id;
|
||||
}
|
||||
|
||||
if ( ! empty( $created['home'] ) ) {
|
||||
update_option( 'page_on_front', $created['home'] );
|
||||
return $result;
|
||||
}
|
||||
|
||||
/** Versioned and retryable site setup. */
|
||||
function fragrance_trade_maybe_setup_site() {
|
||||
$target_version = 3;
|
||||
if ( (int) get_option( 'fragrance_trade_schema_version', 0 ) >= $target_version ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$errors = array();
|
||||
$seed_changed = fragrance_trade_create_seed_services( $errors );
|
||||
$copy_changed = fragrance_trade_migrate_seed_service_copy( $errors );
|
||||
$page_result = fragrance_trade_create_required_pages( $errors );
|
||||
|
||||
if ( ! empty( $page_result['pages']['home'] ) ) {
|
||||
update_option( 'page_on_front', $page_result['pages']['home'] );
|
||||
update_option( 'show_on_front', 'page' );
|
||||
}
|
||||
if ( $seed_changed || $copy_changed || $page_result['changed'] ) {
|
||||
flush_rewrite_rules();
|
||||
}
|
||||
|
||||
flush_rewrite_rules();
|
||||
if ( $errors ) {
|
||||
update_option( 'fragrance_trade_setup_errors', array_values( array_unique( $errors ) ), false );
|
||||
return;
|
||||
}
|
||||
|
||||
delete_option( 'fragrance_trade_setup_errors' );
|
||||
update_option( 'fragrance_trade_setup_done', 1 );
|
||||
update_option( 'fragrance_trade_schema_version', $target_version );
|
||||
}
|
||||
add_action( 'after_switch_theme', 'fragrance_trade_setup_site_on_activation' );
|
||||
add_action( 'after_switch_theme', 'fragrance_trade_maybe_setup_site' );
|
||||
add_action( 'admin_init', 'fragrance_trade_maybe_setup_site' );
|
||||
|
||||
/** Show actionable setup failures until they are resolved. */
|
||||
function fragrance_trade_setup_errors_notice() {
|
||||
if ( ! current_user_can( 'switch_themes' ) ) {
|
||||
return;
|
||||
}
|
||||
$errors = get_option( 'fragrance_trade_setup_errors', array() );
|
||||
if ( ! $errors || ! is_array( $errors ) ) {
|
||||
return;
|
||||
}
|
||||
?>
|
||||
<div class="notice notice-error">
|
||||
<p><strong><?php esc_html_e( 'B2B Trade 主题初始化未完成', 'fragrance-trade' ); ?></strong></p>
|
||||
<ul>
|
||||
<?php foreach ( $errors as $error ) : ?>
|
||||
<li><?php echo esc_html( $error ); ?></li>
|
||||
<?php endforeach; ?>
|
||||
</ul>
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
add_action( 'admin_notices', 'fragrance_trade_setup_errors_notice' );
|
||||
|
||||
/** Warn when a conventional page exists but is not published. */
|
||||
function fragrance_trade_page_status_notice() {
|
||||
if ( ! current_user_can( 'edit_pages' ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$unpublished = array();
|
||||
foreach ( array( 'home', 'about', 'faq', 'contact' ) as $slug ) {
|
||||
$page = fragrance_trade_find_required_page( $slug );
|
||||
if ( $page && 'publish' !== $page->post_status ) {
|
||||
$unpublished[] = $page->post_title;
|
||||
}
|
||||
}
|
||||
if ( ! $unpublished ) {
|
||||
return;
|
||||
}
|
||||
?>
|
||||
<div class="notice notice-warning">
|
||||
<p>
|
||||
<strong><?php esc_html_e( 'B2B Trade 约定页面尚未发布', 'fragrance-trade' ); ?></strong>
|
||||
<?php
|
||||
printf(
|
||||
/* translators: %s: comma-separated page titles. */
|
||||
esc_html__( '主题保留了这些页面的当前状态,不会自动发布或恢复它们:%s。请确认状态后再用于前台导航。', 'fragrance-trade' ),
|
||||
esc_html( implode( '、', $unpublished ) )
|
||||
);
|
||||
?>
|
||||
</p>
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
add_action( 'admin_notices', 'fragrance_trade_page_status_notice' );
|
||||
|
||||
Reference in New Issue
Block a user