<?php
if ( !defined( 'ABSPATH' ) ) {
exit;
}
//メールフォームの textarea にひらがなが無ければ送信できない（contact form7）
add_filter('wpcf7_validate_textarea', 'wpcf7_validation_textarea_hiragana', 10, 2);
add_filter('wpcf7_validate_textarea*', 'wpcf7_validation_textarea_hiragana', 10, 2);
function wpcf7_validation_textarea_hiragana($result, $tag)
{
$name = $tag['name'];
$value = (isset($_POST[$name])) ? (string) $_POST[$name] : '';
if ($value !== '' && !preg_match('/[ぁ-ん]/u', $value)) {
$result['valid'] = false;
$result['reason'] = array($name => 'エラー / この内容は送信できません。');
}
return $result;
}
add_action( 'wp_enqueue_scripts', function() {
if ( !is_page('contact-form') ) {
// Contact Form 7
wp_dequeue_script('contact-form-7');
wp_dequeue_style('contact-form-7');
// reCaptcha (BestWebSoft)
wp_dequeue_script('bws_google_captcha');
wp_dequeue_script('google-recaptcha');
}
}, 100 ); // 投稿一覧にURLコラムを追加
add_filter( 'manage_posts_columns', function( $columns ) {
$columns['post_url'] = '記事URL';
$columns['custom_checkbox'] = 'index申請';
return $columns;
});
// 内容の表示（URLとチェックボックス）
add_action( 'manage_posts_custom_column', function( $column, $post_id ) {
if ( 'post_url' === $column ) {
$post_url = get_permalink( $post_id );
echo '<input type="text" value="' . esc_url(//projector-zukan.com/wp-content/themes/affinger-child/$post_url) . '" readonly style="width: 100%;">';
}
if ( 'custom_checkbox' === $column ) {
$checked_status = get_post_meta( $post_id, '_custom_checkbox_status', true );
$checked = ( $checked_status === 'checked' ) ? 'checked' : '';
echo '<input type="checkbox" class="custom-status-checkbox" data-postid="' . esc_attr( $post_id ) . '" ' . $checked . '>';
}
}, 10, 2 );
// 保存用Ajax処理
add_action( 'wp_ajax_update_checkbox_status', function() {
if ( isset( $_POST['post_id'] ) && isset( $_POST['checked_status'] ) ) {
update_post_meta( intval( $_POST['post_id'] ), '_custom_checkbox_status', sanitize_text_field( $_POST['checked_status'] ) );
wp_send_json_success();
}
wp_send_json_error();
});
// 管理画面用JavaScript
add_action( 'admin_footer', function() {
?>
<script>
jQuery(document).ready(function($) {
$('.custom-status-checkbox').on('change', function() {
$.ajax({
url: ajaxurl, type: 'POST',
data: { action: 'update_checkbox_status', post_id: $(this).data('postid'), checked_status: $(this).prop('checked') ? 'checked' : 'unchecked', _ajax_nonce: '<?php echo wp_create_nonce( 'update_checkbox_status' ); ?>' }
});
});
});
</script>
<?php
});
add_action( 'wp_footer', 'pz_output_faqpage_schema' );
function pz_output_faqpage_schema() {
if ( ! is_singular( 'post' ) ) return;
$content = get_the_content();
// st-accordionクラスのdetailsタグを全て取得
preg_match_all(
'/<details[^>]*class="[^"]*st-accordion[^"]*"[^>]*>.*?<summary[^>]*>(.*?)<\/summary>(.*?)<\/details>/si',
$content,
$matches
);
if ( empty( $matches[1] ) ) return;
$faq_items = [];
foreach ( $matches[1] as $i => $question ) {
$q = wp_strip_all_tags( $question );
$a = wp_strip_all_tags( $matches[2][ $i ] );
$q = trim( $q );
$a = trim( $a );
if ( $q && $a ) {
$faq_items[] = [
'@type'          => 'Question',
'name'           => $q,
'acceptedAnswer' => [
'@type' => 'Answer',
'text'  => $a,
],
];
}
}
if ( empty( $faq_items ) ) return;
$schema = [
'@context'   => 'https://schema.org',
'@type'      => 'FAQPage',
'mainEntity' => $faq_items,
];
echo '<script type="application/ld+json">'
. wp_json_encode( $schema, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES )
. '</script>' . "\n";
} add_action( 'wp_head', 'pz_output_organization_schema' );
function pz_output_organization_schema() {
if ( ! is_front_page() && ! is_singular() ) return;
$schema = [
'@context' => 'https://schema.org',
'@type'    => 'Organization',
'name'     => 'プロジェクター図鑑',
'url'      => 'https://projector-zukan.com/',
'logo'     => [
'@type'  => 'ImageObject',
'url'    => 'https://projector-zukan.com/wp-content/uploads/2026/04/bb70b4b4b9c2820c41f8f88c3c2959aa.webp',
],
];
echo '<script type="application/ld+json">'
. wp_json_encode( $schema, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES )
. '</script>' . "\n";
} add_action( 'wp_head', 'pz_add_preconnect', 1 );
function pz_add_preconnect() {
?>
<!-- DNS Prefetch / Preconnect -->
<link rel="preconnect" href="https://fonts.googleapis.com" crossorigin>
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link rel="preconnect" href="https://pagead2.googlesyndication.com" crossorigin>
<link rel="dns-prefetch" href="https://www.google-analytics.com">
<?php
} add_filter( 'wp_get_attachment_image_attributes', 'pz_add_alt_to_thumbnail', 10, 3 );
function pz_add_alt_to_thumbnail( $attr, $attachment, $size ) {
if ( empty( $attr['alt'] ) ) {
$attr['alt'] = get_the_title( $attachment->post_parent );
if ( empty( $attr['alt'] ) ) {
$attr['alt'] = get_the_title();
}
}
return $attr;
} add_action( 'template_redirect', function () {
if ( is_admin() ) {
return;
}
ob_start( function ( $html ) {
// フッターロゴの空 <a>（複数クラスに対応）に aria-label を付与
$new = preg_replace(
'/(<p class="footer-description[^>]*>\s*<a )(href)/i',
'$1aria-label="プロジェクター図鑑 トップページ" $2',
$html
);
// 置換に失敗（null）した場合は元のHTMLをそのまま返す
return ( $new !== null ) ? $new : $html;
} );
}, 1 );