<?php if ( ! isset( $content_width ) ) $content_width = 625; /** * SQOOLNETテーマのセットアップ * TwentyTwelveの遺産を排除し、sqool_setup()に変更 */ function sqool_setup() { load_theme_textdomain( 'sqoolnet', get_template_directory() . '/languages' ); add_editor_style(); add_theme_support( 'automatic-feed-links' ); add_theme_support( 'post-formats', array( 'aside', 'image', 'link', 'quote', 'status' ) ); register_nav_menu( 'primary', __( 'Primary Menu', 'sqoolnet' ) ); add_theme_support( 'custom-background', array( 'default-color' => 'e6e6e6', ) ); add_theme_support( 'post-thumbnails', array( 'post', 'column', 'news', 'dreamnews', 'prwire','esports', 'business', 'businessnews', 'page','robot','blog','travel','review','report','notice','link','special','hints-and-tips','premium' ) ); add_image_size('thumb50', 50, 50, true); add_image_size('thumb100', 100, 100, true); add_image_size('thumb200', 200, 200, true); add_image_size('thumb150_113', 150, 113, true); add_image_size('thumb200_100', 200, 100, true); add_image_size('thumb420_170', 420, 170, true); add_image_size('thumb696', 696, 696, true); set_post_thumbnail_size( 500,500,true ); // Unlimited height, soft crop /* サムネイル取得関数からwidth&heightを除去 */ // → サムネイル関連の属性除去は remove_image_attribute() に集約 } add_action( 'after_setup_theme', 'sqool_setup' ); /** * shortcodeがpタグに囲まれるfix * */ function shortcode_empty_paragraph_fix($content) { $array = array ( '<p>[' => '[', ']</p>' => ']', ']<br />' => ']' ); $content = strtr($content, $array); return $content; } add_filter('the_content', 'shortcode_empty_paragraph_fix'); /** * Add support for a custom header image. */ require( get_template_directory() . '/inc/custom-header.php' ); require( get_template_directory() . '/adsense.php' ); /** * Return the Google font stylesheet URL if available. * * The use of Open Sans by default is localized. For languages that use * characters not supported by the font, the font can be disabled. * * @since SQOOLNET 1.2 * * @return string Font stylesheet or empty string if disabled. */ function sqool_get_font_url() { $font_url = ''; /* translators: If there are characters in your language that are not supported * by Open Sans, translate this to 'off'. Do not translate into your own language. */ if ( 'off' !== _x( 'on', 'Open Sans font: on or off', 'sqoolnet' ) ) { $subsets = 'latin,latin-ext'; /* translators: To add an additional Open Sans character subset specific to your language, * translate this to 'greek', 'cyrillic' or 'vietnamese'. Do not translate into your own language. */ $subset = _x( 'no-subset', 'Open Sans font: add new subset (greek, cyrillic, vietnamese)', 'sqoolnet' ); if ( 'cyrillic' == $subset ) $subsets .= ',cyrillic,cyrillic-ext'; elseif ( 'greek' == $subset ) $subsets .= ',greek,greek-ext'; elseif ( 'vietnamese' == $subset ) $subsets .= ',vietnamese'; $query_args = array( 'family' => 'Open+Sans:400italic,700italic,400,700', 'subset' => $subsets, ); $font_url = add_query_arg( $query_args, 'https://fonts.googleapis.com/css' ); } return $font_url; } /** * Enqueue scripts and styles for front-end. * * @since SQOOLNET 1.0 */ function sqool_scripts_styles() { global $wp_styles; /* * Adds JavaScript to pages with the comment form to support * sites with threaded comments (when in use). */ if ( is_singular() && comments_open() && get_option( 'thread_comments' ) ) wp_enqueue_script( 'comment-reply' ); // Adds JavaScript for handling the navigation menu hide-and-show behavior. // jQuery依存を削除(Vanilla JSで実装済み) // defer属性を追加してメインスレッドのブロックを防止 wp_enqueue_script( 'sqool-navigation', get_template_directory_uri() . '/js/navigation.js', array(), '20140711', true ); // HTML5 Shivは削除済み(IE8以下のサポート終了により不要) $font_url = sqool_get_font_url(); if ( ! empty( $font_url ) ) wp_enqueue_style( 'sqool-fonts', esc_url_raw( $font_url ), array(), null ); // Loads our main stylesheet. // wp_enqueue_style( 'sqool-style', get_stylesheet_uri() ); } add_action( 'wp_enqueue_scripts', 'sqool_scripts_styles' ); /** * Filter TinyMCE CSS path to include Google Fonts. * * Adds additional stylesheets to the TinyMCE editor if needed. * * @uses sqool_get_font_url() To get the Google Font stylesheet URL. * * @since SQOOLNET 1.0 * * @param string $mce_css CSS path to load in TinyMCE. * @return string Filtered CSS path. */ function sqool_mce_css( $mce_css ) { $font_url = sqool_get_font_url(); if ( empty( $font_url ) ) return $mce_css; if ( ! empty( $mce_css ) ) $mce_css .= ','; $mce_css .= esc_url_raw( str_replace( ',', '%2C', $font_url ) ); return $mce_css; } add_filter( 'mce_css', 'sqool_mce_css' ); /** * Filter the page title. * * Creates a nicely formatted and more specific title element text * for output in head of document, based on current view. * * @since SQOOLNET 1.0 * * @param string $title Default title text for current view. * @param string $sep Optional separator. * @return string Filtered title. */ function sqool_wp_title( $title, $sep ) { global $paged, $page; if ( is_feed() ) return $title; // Add the site description for the home/front page. $site_description = get_bloginfo( 'description', 'display' ); if ( $site_description && ( is_home() || is_front_page() ) ) $title = "$title $sep $site_description"; // Add a page number if necessary. if ( ( $paged >= 2 || $page >= 2 ) && ! is_404() ) $title = "$title $sep " . sprintf( __( 'Page %s', 'sqoolnet' ), max( $paged, $page ) ); return $title; } add_filter( 'wp_title', 'sqool_wp_title', 10, 2 ); /** * Filter the page menu arguments. * * Makes our wp_nav_menu() fallback -- wp_page_menu() -- show a home link. * * @since SQOOLNET 1.0 */ function sqool_page_menu_args( $args ) { if ( ! isset( $args['show_home'] ) ) $args['show_home'] = true; return $args; } add_filter( 'wp_page_menu_args', 'sqool_page_menu_args' ); /** * Register sidebars. * * Registers our main widget area and the front page widget areas. * * @since SQOOLNET 1.0 */ function sqool_widgets_init() { register_sidebar( array( 'name' => __( 'Main Sidebar', 'sqoolnet' ), 'id' => 'sidebar-1', 'description' => __( 'Appears on posts and pages except the optional Front Page template, which has its own widgets', 'sqoolnet' ), 'before_widget' => '<aside id="%1$s" class="widget %2$s">', 'after_widget' => '</aside>', 'before_title' => '<h3 class="widget-title">', 'after_title' => '</h3>', ) ); register_sidebar( array( 'name' => __( 'First Front Page Widget Area', 'sqoolnet' ), 'id' => 'sidebar-2', 'description' => __( 'Appears when using the optional Front Page template with a page set as Static Front Page', 'sqoolnet' ), 'before_widget' => '<aside id="%1$s" class="widget %2$s">', 'after_widget' => '</aside>', 'before_title' => '<h3 class="widget-title">', 'after_title' => '</h3>', ) ); register_sidebar( array( 'name' => __( 'Second Front Page Widget Area', 'sqoolnet' ), 'id' => 'sidebar-3', 'description' => __( 'Appears when using the optional Front Page template with a page set as Static Front Page', 'sqoolnet' ), 'before_widget' => '<aside id="%1$s" class="widget %2$s">', 'after_widget' => '</aside>', 'before_title' => '<h3 class="widget-title">', 'after_title' => '</h3>', ) ); register_sidebar( array( 'name' => __( 'PC右サイドバー', 'sqoolnet' ), 'id' => 'sidebar-5', 'description' => __( 'PCの右端に表示されます', 'sqoolnet' ), 'before_widget' => '<aside id="%1$s" class="widget %2$s">', 'after_widget' => '</aside>', 'before_title' => '<h3 class="widget-title">', 'after_title' => '</h3>', ) ); } add_action( 'widgets_init', 'sqool_widgets_init' ); if ( ! function_exists( 'sqool_content_nav' ) ) : /** * Displays navigation to next/previous pages when applicable. */ function sqool_content_nav( $html_id ) { global $wp_query; if ( $wp_query->max_num_pages > 1 ) : ?> <nav id="<?php echo esc_attr( $html_id ); ?>" class="navigation" role="navigation"> <h3 class="assistive-text"><?php _e( 'Post navigation', 'sqoolnet' ); ?></h3> <div class="nav-previous"><?php next_posts_link( __( '<span class="meta-nav">←</span> Older posts', 'sqoolnet' ) ); ?></div> <div class="nav-next"><?php previous_posts_link( __( 'Newer posts <span class="meta-nav">→</span>', 'sqoolnet' ) ); ?></div> </nav><!-- .navigation --> <?php endif; } endif; /* ------------------------------------------------------------------------- * * コメント欄 /* ------------------------------------------------------------------------- */ if ( ! function_exists( 'sqool_comment' ) ) : /** * Template for comments and pingbacks. * * Used as a callback by wp_list_comments() for displaying the comments. */ function sqool_comment( $comment, $args, $depth ) { $GLOBALS['comment'] = $comment; switch ( $comment->comment_type ) : case 'pingback' : case 'trackback' : // Display trackbacks differently than normal comments. ?> <li <?php comment_class(); ?> id="comment-<?php comment_ID(); ?>"> <p><?php _e( 'Pingback:', 'sqoolnet' ); ?> <?php comment_author_link(); ?> <?php edit_comment_link( __( '(Edit)', 'sqoolnet' ), '<span class="edit-link">', '</span>' ); ?></p> <?php break; default : // Proceed with normal comments. global $post; ?> <li <?php comment_class(); ?> id="li-comment-<?php comment_ID(); ?>"> <article id="comment-<?php comment_ID(); ?>" class="comment"> <header class="comment-meta comment-author vcard"> <?php echo get_avatar( $comment, 44 ); printf( '<cite class="fn">ID:%1$s %2$s</cite>', get_comment_ID(), get_comment_author_link(), // If current post author is also comment author, make it known visually. ( $comment->user_id === $post->post_author ) ? '<span>' . __( 'Post author', 'sqoolnet' ) . '</span>' : '' ); printf( '<a href="%1$s"><time datetime="%2$s">%3$s</time></a>', esc_url( get_comment_link( $comment->comment_ID ) ), get_comment_time( 'c' ), /* translators: 1: date, 2: time */ sprintf( __( '%1$s at %2$s', 'sqoolnet' ), get_comment_date(), get_comment_time() ) ); ?> </header><!-- .comment-meta --> <?php if ( '0' == $comment->comment_approved ) : ?> <p class="comment-awaiting-moderation"><?php _e( 'Your comment is awaiting moderation.', 'sqoolnet' ); ?></p> <?php endif; ?> <section class="comment-content comment"> <?php comment_text(); ?> <?php edit_comment_link( __( 'Edit', 'sqoolnet' ), '<p class="edit-link">', '</p>' ); ?> </section><!-- .comment-content --> <div class="reply"> <?php comment_reply_link( array_merge( $args, array( 'reply_text' => __( 'Reply', 'sqoolnet' ), 'after' => ' <span>↓</span>', 'depth' => $depth, 'max_depth' => $args['max_depth'] ) ) ); ?> </div><!-- .reply --> </article><!-- #comment-## --> <?php break; endswitch; // end comment_type check } endif; function my_comment_form_fields( $fields){ //unset( $fields['author']); // 「名前」を非表示にする場合 unset( $fields['email']); // 「メールアドレス」を非表示にする場合 unset( $fields['url']); // 「ウェブサイト」を非表示にする場合 return $fields; } add_filter( 'comment_form_default_fields', 'my_comment_form_fields'); add_filter( 'comment_form_defaults', 'my_title_reply'); function my_title_reply( $defaults){ $defaults['title_reply'] = 'コメントを書き込む'; return $defaults; } add_filter( "comment_form_defaults", "my_comment_notes_before"); function my_comment_notes_before( $defaults){ $defaults['comment_notes_before'] = ''; return $defaults; } if ( ! function_exists( 'sqool_entry_meta' ) ) : /** * Set up post entry meta. * * Prints HTML with meta information for current post: categories, tags, permalink, author, and date. */ function sqool_entry_meta() { global $post; $author = get_the_author(); $categories_list = get_the_category_list( __( ', ', 'sqoolnet' ) ); $tag_list = get_the_tag_list( '', __( ', ', 'sqoolnet' ) ); $date = sprintf( '<a href="%1$s" title="%2$s" rel="bookmark"><time class="entry-date" datetime="%3$s">%4$s</time></a>', esc_url( get_permalink() ), esc_attr( get_the_time() ), esc_attr( get_the_date( 'c' ) ), esc_html( get_the_date() ) ); // Translators: 1 is category, 2 is tag, 3 is the date and 4 is the author's name. if ( $tag_list ) { $utility_text = __( 'This entry was posted in %1$s and tagged %2$s on %3$s<span class="by-author"> by %4$s</span>.', 'sqoolnet' ); } elseif ( $categories_list ) { $utility_text = __( 'This entry was posted in %1$s on %3$s<span class="by-author"> by %4$s</span>.', 'sqoolnet' ); } else { $utility_text = __( 'This entry was posted on %3$s<span class="by-author"> by %4$s</span>.', 'sqoolnet' ); } printf( $utility_text, $categories_list, $tag_list, $date, $author ); } endif; /** * Extend the default WordPress body classes. * * Extends the default WordPress body class to denote: * 1. Using a full-width layout, when no active widgets in the sidebar * or full-width template. * 2. Front Page template: thumbnail in use and number of sidebars for * widget areas. * 3. White or empty background color to change the layout and spacing. * 4. Custom fonts enabled. * 5. Single or multiple authors. * * @since SQOOLNET 1.0 * * @param array $classes Existing class values. * @return array Filtered class values. */ function sqool_body_class( $classes ) { $background_color = get_background_color(); $background_image = get_background_image(); if ( ! is_active_sidebar( 'sidebar-1' ) || is_page_template( 'page-templates/full-width.php' ) ) $classes[] = 'full-width'; if ( is_page_template( 'page-templates/front-page.php' ) ) { $classes[] = 'template-front-page'; if ( has_post_thumbnail() ) $classes[] = 'has-post-thumbnail'; if ( is_active_sidebar( 'sidebar-2' ) && is_active_sidebar( 'sidebar-3' ) ) $classes[] = 'two-sidebars'; } if ( empty( $background_image ) ) { if ( empty( $background_color ) ) $classes[] = 'custom-background-empty'; elseif ( in_array( $background_color, array( 'fff', 'ffffff' ) ) ) $classes[] = 'custom-background-white'; } // Enable custom font class only if the font CSS is queued to load. if ( wp_style_is( 'sqool-fonts', 'queue' ) ) $classes[] = 'custom-font-enabled'; if ( ! is_multi_author() ) $classes[] = 'single-author'; return $classes; } add_filter( 'body_class', 'sqool_body_class' ); /** * Adjust content width in certain contexts. * * Adjusts content_width value for full-width and single image attachment * templates, and when there are no active widgets in the sidebar. * * @since SQOOLNET 1.0 */ function sqool_content_width() { if ( is_page_template( 'page-templates/full-width.php' ) || is_attachment() || ! is_active_sidebar( 'sidebar-1' ) ) { global $content_width; $content_width = 960; } } add_action( 'template_redirect', 'sqool_content_width' ); /** * Register postMessage support. * * Add postMessage support for site title and description for the Customizer. * * @since SQOOLNET 1.0 * * @param WP_Customize_Manager $wp_customize Customizer object. */ function sqool_customize_register( $wp_customize ) { $wp_customize->get_setting( 'blogname' )->transport = 'postMessage'; $wp_customize->get_setting( 'blogdescription' )->transport = 'postMessage'; $wp_customize->get_setting( 'header_textcolor' )->transport = 'postMessage'; } add_action( 'customize_register', 'sqool_customize_register' ); /** * Enqueue Javascript postMessage handlers for the Customizer. * * Binds JS handlers to make the Customizer preview reload changes asynchronously. * * @since SQOOLNET 1.0 */ function sqool_customize_preview_js() { wp_enqueue_script( 'sqool-customizer', get_template_directory_uri() . '/js/theme-customizer.js', array( 'customize-preview' ), '20141120', true ); } add_action( 'customize_preview_init', 'sqool_customize_preview_js' ); /* 独自関数追加 */ /* 続きを読むのURL修正 */ function remove_more_jump_link( $link) { $offset = strpos( $link, '#more-'); if ($offset) { $end = strpos( $link, '"', $offset); } if ($end) { $link = substr_replace( $link, '', $offset, $end-$offset); } return $link; } add_filter( 'the_content_more_link', 'remove_more_jump_link'); /* 投稿者非表示 */ // sqool_entry_meta() は上部の定義を利用 /* サイトバーでショートコードを使えるようにする */ // 安定化のため一時的に無効化(壊れたoption/metaを読みに行く可能性があるため) // add_filter('widget_text', 'do_shortcode'); /* 寄稿者画像アップロード権限追加(DB書き込みを避けるため一度だけ実行) */ function sqool_maybe_allow_contributor_uploads_once() { if ( get_option( 'sqool_allow_contributor_uploads_executed', false ) ) { return; } $role = get_role( 'contributor' ); if ( $role && method_exists( $role, 'add_cap' ) ) { $role->add_cap( 'upload_files' ); update_option( 'sqool_allow_contributor_uploads_executed', true, false ); } } add_action( 'admin_init', 'sqool_maybe_allow_contributor_uploads_once' ); /* メディアの抽出条件にログインユーザーの絞り込み条件を追加する */ function display_only_self_uploaded_medias( $wp_query ) { if ( is_admin() && ( $wp_query->is_main_query() || ( defined( 'DOING_QUERY_ATTACHMENT' ) && DOING_QUERY_ATTACHMENT ) ) && $wp_query->get( 'post_type' ) == 'attachment' ) { $user = wp_get_current_user(); $wp_query->set( 'author', $user->ID ); } } function define_doing_query_attachment_const() { if ( ! defined( 'DOING_QUERY_ATTACHMENT' ) ) { define( 'DOING_QUERY_ATTACHMENT', true ); } } // get_currentuserinfo(); // if($current_user->user_level < 10){ // add_action( 'pre_get_posts', 'display_only_self_uploaded_medias' ); // add_action( 'wp_ajax_query-attachments', 'define_doing_query_attachment_const', 0 ); // } /* 他の人の投稿を見れないようにする */ /* 対象画面(edit.phpなど)・対象post_typeを明示して限定(管理画面の検索や特定画面で想定外の絞り込みを防ぐ) */ function exclude_other_posts( $wp_query ) { // 管理画面の投稿一覧(edit.php)のみに限定($pagenowで確実に判定) global $pagenow; if ( $pagenow !== 'edit.php' ) { return; } // リクエストパラメータからpost_typeを取得(明示的に指定されたもののみ) $post_type = isset( $_REQUEST['post_type'] ) ? sanitize_text_field( $_REQUEST['post_type'] ) : 'post'; if ( ! post_type_exists( $post_type ) ) { $post_type = 'post'; } $post_type_obj = get_post_type_object( $post_type ); // プロパティの存在チェックを追加(エラー防止) if ( $post_type_obj && isset( $post_type_obj->cap ) && isset( $post_type_obj->cap->edit_other_posts ) ) { $cap_type = $post_type_obj->cap->edit_other_posts; } else { $cap_type = 'edit_others_posts'; } // 対象post_typeに限定し、既にauthor指定がある場合はスキップ // $wp_query->get('post_type') は配列になり得るため、is_array を吸収して判定 $qpt = $wp_query->get( 'post_type' ); $is_target_post_type = false; if ( is_array( $qpt ) ) { // 複数のpost_typeが指定されている場合 $is_target_post_type = in_array( $post_type, $qpt, true ); } elseif ( $qpt === $post_type ) { // 単一のpost_typeが指定されている場合 $is_target_post_type = true; } elseif ( empty( $qpt ) && $post_type === 'post' ) { // post_typeが指定されていない場合はデフォルトで'post'として扱う $is_target_post_type = true; } if ( is_admin() && $wp_query->is_main_query() && $is_target_post_type && ! $wp_query->get( 'author' ) && ! current_user_can( $cap_type ) ) { $user = wp_get_current_user(); $wp_query->set( 'author', $user->ID ); } } if(!current_user_can('manage_options')){ add_action( 'pre_get_posts', 'exclude_other_posts' ); } /* メニュー表示制限 */ function my_remove_menu(){ remove_menu_page('wpcf7'); // Contact form 7の「お問い合わせ」を非表示 } // 管理者以外は指定メニューを消す if(!current_user_can('administrator')) add_action('admin_menu', 'my_remove_menu'); /* 特定ユーザーに公開記事編集権限付与 */ /* function edit_mypublished_posts() { $user = new WP_User( '5' ); $user->add_cap( 'edit_published_posts','edit_pages' ); } add_action( 'admin_init', 'edit_mypublished_posts'); */ /* ユーザー の権限削除 */ /* 一度だけ実行する方式に変更(admin_initで毎回実行するとDB書き込みが増えるため) */ function remove_theme_caps(){ // 既に実行済みかチェック $executed = get_option( 'sqool_remove_theme_caps_executed', false ); if ( $executed ) { return; } $role = new WP_User( '55' ); $role->remove_cap( 'edit_published_posts' ); // 実行済みフラグを設定 update_option( 'sqool_remove_theme_caps_executed', true, false ); } add_action( 'admin_init', 'remove_theme_caps' ); /* authorがありませんを解消 */ function remove_hentry( $classes ) { $classes = array_diff($classes, array('hentry')); return $classes; } add_filter('post_class', 'remove_hentry'); /* 固定ページに抜粋追加 */ add_post_type_support( 'page', 'excerpt' ); /* mymobile() タブレット除外関数 */ function isMobilePhone() { // HTTP_USER_AGENTが存在しない環境(CLI・一部プロキシ・セキュリティ設定)でNoticeを避ける if ( ! isset( $_SERVER['HTTP_USER_AGENT'] ) ) { return false; } return (bool) preg_match('/android.+mobile|iemobile|ip(hone|od)|opera m(ob|in)i|psp|windows (ce|phone)|mobile.+firefox/i', $_SERVER['HTTP_USER_AGENT']); } /* 不要META削除 */ remove_action('wp_head', 'wp_generator'); remove_action('wp_head', 'rsd_link'); remove_action('wp_head', 'wlwmanifest_link'); // WP標準canonicalは無効化し、下の sqool_output_canonical() で明示的に出力する(SEO対策) remove_action('wp_head', 'rel_canonical'); /** * canonical を明示的に出力 * - .html でアクセスされている場合は、そのURL(末尾スラッシュ除去)を正とする * - それ以外は WordPress の標準的なURL(get_permalink等)を用いる */ function sqool_output_canonical() { if ( is_admin() || is_feed() ) { return; } $canonical = ''; // .html でアクセスされている場合はリクエストURI優先 if ( isset( $_SERVER['REQUEST_URI'] ) && is_string( $_SERVER['REQUEST_URI'] ) ) { $req = $_SERVER['REQUEST_URI']; if ( preg_match( '#\.html(/)?$#i', $req ) ) { $req = preg_replace( '#/+$#', '', $req ); $canonical = home_url( $req ); } } // 通常の canonical if ( $canonical === '' ) { if ( is_singular() ) { // FeedWordPress記事の場合は引用元URLを優先 $post_id = get_queried_object_id(); if ( $post_id ) { $source_url = get_post_meta($post_id, 'syndication_permalink', true); $canonical = $source_url ? $source_url : get_permalink(); } else { // $post_id が取れない場合のフォールバック(特殊クエリ等のケース) $canonical = get_permalink(); } } elseif ( is_front_page() ) { $canonical = home_url( '/' ); } elseif ( is_home() ) { // page_for_posts が設定されている場合のみ使用、無ければ home_url('/') にフォールバック $page_for_posts = get_option( 'page_for_posts' ); if ( $page_for_posts && $page_for_posts > 0 ) { $canonical = get_permalink( $page_for_posts ); } else { $canonical = home_url( '/' ); } } elseif ( is_category() || is_tag() || is_tax() ) { $term = get_queried_object(); if ( $term && isset( $term->term_id ) ) { $canonical = get_term_link( $term ); } } elseif ( is_post_type_archive() ) { $post_type = get_query_var( 'post_type' ); if ( $post_type ) { $canonical = get_post_type_archive_link( $post_type ); } } elseif ( is_search() ) { $canonical = home_url( '/?s=' . rawurlencode( get_search_query() ) ); } } if ( is_wp_error( $canonical ) || ! is_string( $canonical ) || $canonical === '' ) { return; } echo '<link rel="canonical" href="' . esc_url( $canonical ) . '" />' . "\n"; } add_action( 'wp_head', 'sqool_output_canonical', 1 ); /* 抜粋カスタム */ function kotoriexcerpt($length) { global $post; if ( ! $post ) { return ''; } $content = mb_substr( strip_tags( $post->post_excerpt ), 0, $length ); if ( ! $content ) { $content = $post->post_content; $content = strip_shortcodes( $content ); $content = strip_tags( $content ); $content = str_replace( " ", "", $content ); $content = html_entity_decode( $content, ENT_QUOTES, "UTF-8" ); $content = mb_substr( $content, 0, $length ); } return $content; } /* TOP固定ページ時のページネーション修正 */ add_action( 'parse_query', 'my_parse_query' ); function my_parse_query( $query ) { if ( ! isset( $query->query_vars['paged'] ) && isset( $query->query_vars['page'] ) ) $query->query_vars['paged'] = $query->query_vars['page']; } /* 画像挿入時の不要ステータス除去 */ add_filter( 'image_send_to_editor', 'remove_image_attribute', 10 ); add_filter( 'post_thumbnail_html', 'remove_image_attribute', 10 ); /** * 画像挿入時の不要属性除去 * 対象を画像リンクに限定(<a>タグの中に<img>がある場合のみ除去) */ function remove_image_attribute( $html ){ // width/height属性の除去(末尾のスペースも考慮) $html = preg_replace( '/(width|height)\s*=\s*["\']\d*["\']\s*/i', '', $html ); // title属性の除去(シングル/ダブルクォート両対応) $html = preg_replace( '/title\s*=\s*["\']([^"\']+)["\']/i', '', $html ); // <a>タグの除去は「画像リンクの場合のみ」に限定 // <a ...><img ...></a> の1組だけをマッチして、<img ...> だけを残す(誤爆防止) // これにより、画像以外のリンク(本文やウィジェット内のテキストリンク等)は保護される $html = preg_replace( '/<a\s+[^>]*>(.*?<img[^>]*>.*?)<\/a>/is', '$1', $html ); return $html; } /** * post_thumbnailにitemprop="image"を追加する(1箇所に統合) * 既にitemprop="image"が存在する場合は追加しない(重複防止) */ function custom_post_thumbnail($html){ // 既にitemprop="image"が存在する場合は何もしない if ( strpos( $html, 'itemprop="image"' ) !== false || strpos( $html, "itemprop='image'" ) !== false ) { return $html; } // <img タグに itemprop="image" を追加(属性の前に挿入) return preg_replace( '/<img\s+/i', '<img itemprop="image" ', $html, 1 ); } add_filter('post_thumbnail_html','custom_post_thumbnail',10,5); // LCP画像の最適化: 最初のサムネイル画像からlazyloadクラスを削除し、fetchpriority="high"を追加 // メインクエリ・特定テンプレに限定(一覧や複数ループでの誤適用を防ぐ) function sqool_optimize_lcp_image($html, $post_id, $post_thumbnail_id, $size, $attr) { // 管理画面では処理しない if ( is_admin() ) { return $html; } // メインクエリでない場合はスキップ(一覧や複数ループでの適用を防ぐ) global $wp_query; if ( ! $wp_query->is_main_query() ) { return $html; } // シングル投稿・固定ページのみに限定(アーカイブページでの適用を防ぐ) if ( ! is_single() && ! is_page() ) { return $html; } // グローバルカウンターで最初の画像を判定 static $image_count = 0; $image_count++; // 最初の画像(LCP候補)の場合のみ最適化 if ( $image_count === 1 ) { // lazyloadクラスを削除 $html = str_replace(' lazyload', '', $html); $html = str_replace('lazyload ', '', $html); $html = str_replace(' lazyloaded', '', $html); $html = str_replace('lazyloaded ', '', $html); // loading="lazy"を削除 $html = preg_replace('/\s*loading=["\']lazy["\']/i', '', $html); // fetchpriority="high"を追加(まだ存在しない場合) if ( strpos($html, 'fetchpriority') === false ) { $html = str_replace('<img', '<img fetchpriority="high"', $html); } // decoding="async"を追加(まだ存在しない場合) if ( strpos($html, 'decoding=') === false ) { $html = str_replace('<img', '<img decoding="async"', $html); } } return $html; } // 優先度30で実行(remove_image_attributeの後) add_filter('post_thumbnail_html', 'sqool_optimize_lcp_image', 30, 5); /* カラム左サイドバー */ register_sidebar( array( 'name' => '左サイドバー', 'id' => 'sidebar-4', 'description' => '左サイドバー', 'before_widget' => '<aside id="%1$s" class="widget %2$s">', 'after_widget' => '</aside>', 'before_title' => '<h3 class="widget-title">', 'after_title' => '</h3>', ) ); /* 固定ページにカテゴリ追加 */ add_action('init','add_categories_for_pages'); function add_categories_for_pages(){ register_taxonomy_for_object_type('category', 'page'); } add_action( 'pre_get_posts', 'nobita_merge_page_categories_at_category_archive' ); function nobita_merge_page_categories_at_category_archive( $query ) { } /* ニュース投稿ページパスワードカスタム */ function custom_password_form() { global $post; $label = 'pwbox-'.( empty( $post->ID ) ? rand() : $post->ID ); $o = '<form action="' . esc_url( site_url( 'wp-login.php?action=postpass', 'login_post' ) ) . '" method="post"> [news_post_lock] <label for="' . $label . '">' . ' </label><input name="post_password" id="' . $label . '" type="password" maxlength="20" /> <input type="submit" name="Submit" value="' . esc_attr__( "パスワード送信" ) . '" /> </form>'; return $o; } add_filter( 'the_password_form', 'custom_password_form' ); /* 「保護中」を削除 */ add_filter('protected_title_format', 'remove_protected'); function remove_protected($title) { return '%s'; } /* パスワード保護クッキー保存時間 */ function custom_postpass_time() { // post_passwordが存在しない場合は処理しない if (!isset($_POST['post_password'])) return; require_once ABSPATH . 'wp-includes/class-phpass.php'; $hasher = new PasswordHash( 8, true ); setcookie( 'wp-postpass_' . COOKIEHASH, $hasher->HashPassword( wp_unslash( $_POST['post_password'] ) ), time() + HOUR_IN_SECONDS, COOKIEPATH ); wp_safe_redirect( wp_get_referer() ); exit(); } add_action( 'login_form_postpass', 'custom_postpass_time' ); //カテゴリー&タグ説明文のpタグを削除 remove_filter('term_description','wpautop'); /* emoji系のjs&css排除 */ remove_action('wp_head', 'print_emoji_detection_script', 7); remove_action('admin_print_scripts', 'print_emoji_detection_script'); remove_action('wp_print_styles', 'print_emoji_styles' ); remove_action('admin_print_styles', 'print_emoji_styles'); /* jQueryの最適化:重複読み込みを防止し、最新版を使用 */ // 安定化のため一時的に無効化(依存関係の崩壊・document.writeによるブロッキング・不定期なフロント崩れを防ぐため) /* if (!is_admin()) { function sqool_optimize_jquery(){ // 既存のjQueryを登録解除 wp_deregister_script('jquery'); wp_deregister_script('jquery-core'); wp_deregister_script('jquery-migrate'); // 最新のjQueryをフッターに読み込み(CDN使用、フォールバック付き) // 注意: jQueryは他のスクリプトの依存関係があるため、deferは追加しない wp_register_script('jquery', 'https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js', array(), '3.7.1', true); wp_register_script('jquery-migrate', 'https://code.jquery.com/jquery-migrate-3.4.1.min.js', array('jquery'), '3.4.1', true); // フォールバック(CDN失敗時) add_filter('script_loader_tag', function($tag, $handle) { if ($handle === 'jquery') { $fallback = "if (typeof jQuery === 'undefined') { document.write('<script src=\"/wp-includes/js/jquery/jquery.min.js\"><\/script>'); }"; $tag = str_replace('</script>', '</script><script>' . $fallback . '</script>', $tag); } return $tag; }, 10, 2); wp_enqueue_script('jquery'); // jQuery Migrateは必要に応じてのみ読み込む(多くの場合不要) // wp_enqueue_script('jquery-migrate'); } add_action('wp_enqueue_scripts', 'sqool_optimize_jquery', 1); } */ //wp_titleの$sepが「|」または半角スペースの場合は余分な空白削除 function my_title_fix($title, $sep, $seplocation){ if(!$sep || $sep == "|"){ $title = str_replace(' '.$sep.' ', $sep, $title); } return $title; } add_filter('wp_title', 'my_title_fix', 10, 3); //post_is_in_descendant_categoryの有効化 if ( ! function_exists( 'post_is_in_descendant_category' ) ) { function post_is_in_descendant_category( $cats, $_post = null ) { foreach ( (array) $cats as $cat ) { // get_term_children() は整数の ID しか受け付けない $descendants = get_term_children( (int) $cat, 'category' ); if ( $descendants && in_category( $descendants, $_post ) ) return true; } return false; } } //予約投稿対策 更新日が公開日より古くなるのを防ぐ function get_mtime($format) { $mtime = get_the_modified_time('Ymd'); $ptime = get_the_time('Ymd'); if ($ptime > $mtime) { return get_the_time($format); } elseif ($ptime === $mtime) { return null; } else { return get_the_modified_time($format); } } //更新日コントロール// /* 管理画面が開いたときに実行 */ add_action( 'admin_menu', 'add_update_level_custom_box' ); /* 更新ボタンが押されたときに実行 */ add_action( 'save_post', 'save_custom_field_postdata' ); /* カスタムフィールドを投稿画面に追加 */ function add_update_level_custom_box() { $post_types = sqool_get_post_types(); foreach ( $post_types as $post_type ) { add_meta_box( 'update_level', '更新レベル', 'html_update_level_custom_box', $post_type, 'side', 'high' ); } } // 共通の投稿タイプ配列(再利用) function sqool_get_post_types() { return array( 'post', 'page', 'column', 'news', 'dreamnews', 'prwire', 'esports', 'business', 'businessnews', 'robot', 'blog', 'travel', 'review', 'report', 'notice', 'link', 'special', 'hints-and-tips', 'premium' ); } /* 投稿画面に表示するフォームのHTMLソース */ function html_update_level_custom_box() { global $post; $update_level = get_post_meta( $post->ID, 'update_level', true ); echo '<div style="padding-top: 5px; overflow: hidden;">'; echo '<div style="padding:5px 0"><input name="update_level" type="radio" value="high" '; if( $update_level == "" || $update_level == "high" ) echo ' checked="checked"'; echo ' />通常更新</div><div style="padding:5px 0"><input name="update_level" type="radio" value="low" '; if( $update_level == "low" ) echo ' checked="checked"'; echo ' />修正のみ</div>'; echo '<div style="padding:5px 0"><input name="update_level" type="radio" value="del" '; echo ' />更新日時消去(公開日時と同じにする)</div>'; echo '<div style="padding:5px 0;margin-bottom:10px"><input id="update_level_edit" name="update_level" type="radio" value="edit" '; echo ' />更新日時変更</div>'; $datef = __( 'M j, Y @ G:i' ); if( get_the_date('c') ) { $stamp = __('更新日時: <b>%1$s</b>'); } else { $stamp = __('更新日時: <b>未更新</b>'); } $date = date_i18n( $datef, strtotime( $post->post_modified ) ); ?> <style> .modtime { padding: 2px 0 1px 0; display: inline !important; height: auto !important; } .modtime:before { font: normal 20px/1 'dashicons'; content: '\f145'; color: #888; padding: 0 5px 0 0; top: -1px; left: -1px; position: relative; vertical-align: top; } #timestamp_mod_div { padding-top: 5px; line-height: 23px; } #timestamp_mod_div p { margin: 8px 0 6px; } #timestamp_mod_div input { border-width: 1px; border-style: solid; } #timestamp_mod_div select { height: 21px; line-height: 14px; padding: 0; vertical-align: top;font-size: 12px; } #aa_mod, #jj_mod, #hh_mod, #mn_mod { padding: 1px; font-size: 12px; } #jj_mod, #hh_mod, #mn_mod { width: 2em; } #aa_mod { width: 3.4em; } </style> <span class="modtime"><?php printf($stamp, $date); ?></span> <div id="timestamp_mod_div" onkeydown="document.getElementById('update_level_edit').checked=true" onclick="document.getElementById('update_level_edit').checked=true"> <?php $action = isset($_GET['action']) ? $_GET['action'] : 'edit'; touch_time_mod(($action == 'edit'), 1); ?> </div> </div> <?php } /* 更新日時変更の入力フォーム */ function touch_time_mod( $edit = true, $unused = 0 ) { global $wp_locale, $post; // 引数はPHP8の警告回避のため受け取るが、実際の処理では関数内で$_GETから判定(既存ロジック維持) $action = isset($_GET['action']) ? $_GET['action'] : 'edit'; $tab_index = 0; $tab_index_attribute = ""; if ( (int) $tab_index > 0 ) { $tab_index_attribute = " tabindex=\"$tab_index\""; } $jj_mod = mysql2date( 'd', $post->post_modified, false ); $mm_mod = mysql2date( 'm', $post->post_modified, false ); $aa_mod = mysql2date( 'Y', $post->post_modified, false ); $hh_mod = mysql2date( 'H', $post->post_modified, false ); $mn_mod = mysql2date( 'i', $post->post_modified, false ); $ss_mod = mysql2date( 's', $post->post_modified, false ); $month = '<label for="mm_mod" class="screen-reader-text">' . __( 'Month' ) . '</label><select id="mm_mod" name="mm_mod"' . $tab_index_attribute . ">\n"; for ( $i = 1; $i < 13; $i = $i +1 ) { $monthnum = zeroise($i, 2); $month .= "\t\t\t" . '<option value="' . $monthnum . '" ' . selected( $monthnum, $mm_mod, false ) . '>'; $month .= sprintf( __( '%1$s-%2$s' ), $monthnum, $wp_locale->get_month_abbrev( $wp_locale->get_month( $i ) ) ); $month .= "</option>\n"; } $month .= '</select>'; $day = '<label for="jj_mod" class="screen-reader-text">' . __( 'Day' ) . '</label><input type="text" id="jj_mod" name="jj_mod" value="' . $jj_mod . '" size="2" maxlength="2"' . $tab_index_attribute . ' autocomplete="off" />'; $year = '<label for="aa_mod" class="screen-reader-text">' . __( 'Year' ) . '</label><input type="text" id="aa_mod" name="aa_mod" value="' . $aa_mod . '" size="4" maxlength="4"' . $tab_index_attribute . ' autocomplete="off" />'; $hour = '<label for="hh_mod" class="screen-reader-text">' . __( 'Hour' ) . '</label><input type="text" id="hh_mod" name="hh_mod" value="' . $hh_mod . '" size="2" maxlength="2"' . $tab_index_attribute . ' autocomplete="off" />'; $minute = '<label for="mn_mod" class="screen-reader-text">' . __( 'Minute' ) . '</label><input type="text" id="mn_mod" name="mn_mod" value="' . $mn_mod . '" size="2" maxlength="2"' . $tab_index_attribute . ' autocomplete="off" />'; printf( __( '%1$s %2$s, %3$s @ %4$s : %5$s' ), $month, $day, $year, $hour, $minute ); echo '<input type="hidden" id="ss_mod" name="ss_mod" value="' . $ss_mod . '" />'; } /* 設定したカスタムフィールドの値をDBに書き込む記述 */ function save_custom_field_postdata( $post_id ) { // 投稿編集画面以外では処理しない if (!isset($_POST['update_level'])) return; $mydata = $_POST['update_level']; if( $mydata == "edit" ){ $mydata = "low"; } elseif( $mydata == "del" ){ $mydata = ""; } if( "" == get_post_meta( $post_id, 'update_level' )) { /* update_levelというキーでデータが保存されていなかった場合、新しく保存 */ add_post_meta( $post_id, 'update_level', $mydata, true ) ; } elseif( $mydata != get_post_meta( $post_id, 'update_level' )) { /* update_levelというキーのデータと、現在のデータが不一致の場合、更新 */ update_post_meta( $post_id, 'update_level', $mydata ) ; } elseif( "" == $mydata ) { /* 現在のデータが無い場合、update_levelというキーの値を削除 */ delete_post_meta( $post_id, 'update_level' ) ; } } /* 「修正のみ」は更新しない。それ以外は、それぞれの更新日時に変更する */ add_filter( 'wp_insert_post_data', 'my_insert_post_data', 10, 2 ); function my_insert_post_data( $data, $postarr ){ // 投稿編集画面以外では処理しない if (!isset($_POST['update_level'])) return $data; $mydata = $_POST['update_level']; //プレスと 記事連携のあとに来たかフラグ $pr_mail_flg = isset($_POST['pr_mail_flg']) ? (int)$_POST['pr_mail_flg'] : 0; $link_mail_flg = isset($_POST['link_mail_flg']) ? (int)$_POST['link_mail_flg'] : 0; //IPで 僕だけ見れるように if ($_SERVER["REMOTE_ADDR"] == "222.158.251.43") { // print_r($_POST); // echo("aaaaaaaaaaaaaaaaaaaaaaaaa:::" . $mydata . "***" . $pr_mail_flg . "***" . $link_mail_flg); } if( $mydata == "low" || $pr_mail_flg == 1 || $link_mail_flg == 1 ){ unset( $data["post_modified"] ); unset( $data["post_modified_gmt"] ); } elseif( $mydata == "edit" ) { $aa_mod = isset($_POST['aa_mod']) && $_POST['aa_mod'] > 0 ? (int)$_POST['aa_mod'] : date('Y'); $mm_mod = isset($_POST['mm_mod']) && $_POST['mm_mod'] > 0 ? (int)$_POST['mm_mod'] : date('n'); $jj_mod = isset($_POST['jj_mod']) ? min(31, max(1, (int)$_POST['jj_mod'])) : date('j'); $hh_mod = isset($_POST['hh_mod']) ? ((int)$_POST['hh_mod'] > 23 ? (int)$_POST['hh_mod'] - 24 : (int)$_POST['hh_mod']) : 0; $mn_mod = isset($_POST['mn_mod']) ? ((int)$_POST['mn_mod'] > 59 ? (int)$_POST['mn_mod'] - 60 : (int)$_POST['mn_mod']) : 0; $ss_mod = isset($_POST['ss_mod']) ? ((int)$_POST['ss_mod'] > 59 ? (int)$_POST['ss_mod'] - 60 : (int)$_POST['ss_mod']) : 0; $modified_date = sprintf( "%04d-%02d-%02d %02d:%02d:%02d", $aa_mod, $mm_mod, $jj_mod, $hh_mod, $mn_mod, $ss_mod ); if ( ! wp_checkdate( $mm_mod, $jj_mod, $aa_mod, $modified_date ) ) { unset( $data["post_modified"] ); unset( $data["post_modified_gmt"] ); return $data; } $data["post_modified"] = $modified_date; $data["post_modified_gmt"] = get_gmt_from_date( $modified_date ); } elseif( $mydata == "del" ) { $data["post_modified"] = $data["post_date"]; $data["post_modified_gmt"] = $data["post_date_gmt"]; } return $data; } //更新日コントロールここまで// /* feedにアイキャッチを追加 */ /* function rss_post_thumbnail($content) { global $post; if(has_post_thumbnail($post->ID)) { $content = '<p>' . get_the_post_thumbnail($post->ID) . '</p>' . $content; } return $content; } add_filter('the_excerpt_rss', 'rss_post_thumbnail'); add_filter('the_content_feed', 'rss_post_thumbnail'); */ /* rssキャッシュ停止 */ function do_not_cache_feeds( $feed ) { if ( is_object( $feed ) && method_exists( $feed, 'enable_cache' ) ) { $feed->enable_cache( false ); } } add_action( 'wp_feed_options', 'do_not_cache_feeds' ); /* frrd・rssタイトル調整 */ function cat_added_title( $title) { if(in_category(4591)|| post_is_in_descendant_category( '4591' )) { if(in_category(24)|| post_is_in_descendant_category( '24' )) { $cat_name = '脱出ゲーム攻略'; }elseif(in_category(8325)|| post_is_in_descendant_category( '8325' )) { $cat_name = 'リネレボ攻略'; }else{ $category = get_the_category(); $cat_name = $category[0]->cat_name; } $seph = '【'; $sepb = '】'; $rsstitlehead = $cat_name; $title = $seph . $rsstitlehead . $sepb . $title; return $title; }else{ $title = $title; return $title; } } add_filter( 'the_title_rss', 'cat_added_title'); function feed_content_remove_class_adsense_top($content) { return preg_replace('/ class="adsense_top"/', '', $content); } add_filter('the_excerpt_rss', 'feed_content_remove_class_adsense_top'); add_filter('the_content_feed', 'feed_content_remove_class_adsense_top'); /* YARPP CSS無効 */ //ヘッダー部分のCSS消去 add_action('wp_print_styles','lm_dequeue_header_styles'); function lm_dequeue_header_styles(){ wp_dequeue_style('yarppWidgetCss'); } //フッター部分のCSS消去 add_action('get_footer','lm_dequeue_footer_styles'); function lm_dequeue_footer_styles(){ wp_dequeue_style('yarppRelatedCss'); } //サムネイルを有効にした場合に呼び出されるCSS消去 add_action('wp_print_styles','lm_dequeue_header_styles1'); function lm_dequeue_header_styles1(){ wp_dequeue_style('yarpp-thumbnails-yarpp-thumbnail'); } add_action('get_footer','lm_dequeue_footer_styles1'); function lm_dequeue_footer_styles1(){ wp_dequeue_style('yarpp-thumbnails-yarpp-thumbnail'); } // iframe の埋め込み許可(管理者・編集者相当のみ) add_filter( 'content_save_pre', 'sqool_allow_iframe_for_trusted_roles' ); function sqool_allow_iframe_for_trusted_roles( $content ) { if ( ! current_user_can( 'edit_others_posts' ) && ! current_user_can( 'manage_options' ) ) { return $content; } global $allowedposttags; $allowedposttags['iframe'] = array( 'class' => array(), 'src' => array(), 'width' => array(), 'height' => array(), 'frameborder' => array(), 'scrolling' => array(), 'marginheight' => array(), 'marginwidth' => array(), 'allow' => array(), 'allowfullscreen' => array(), 'loading' => array(), 'referrerpolicy' => array(), ); return $content; } /* 文字列変換解除 */ // 高速化目的での無効化は副作用が大きいためコメントアウト(過去記事の表記揺れ・崩れの原因になる) // 特定テンプレートでのみ無効化が必要な場合は、対象テンプレート限定で実装する // remove_filter('the_content', 'wptexturize'); // wptexturizeによる文字列変換をしない // remove_filter('the_content', 'convert_chars'); // convert_charsによる文字列変換をしない /* wp-headerからGoogle Fontsを削除 */ function google_fonts_dequeue() { wp_dequeue_style('sqool-fonts'); } add_action( 'wp_enqueue_scripts', 'google_fonts_dequeue', 10); /* 記事タイトル引用文字数制限 */ function titlelimitchar($title){ if(mb_strlen($title) > 65 && !(is_single()) && !(is_page()) && !(is_feed())){ $title = mb_substr($title,0,65) . "…"; } return $title; } add_filter( 'the_title', 'titlelimitchar' ); /* カスタムCSS欄 */ add_action('admin_menu', 'custom_css_hooks'); add_action('save_post', 'save_custom_css'); add_action('wp_head','insert_custom_css'); function custom_css_hooks() { $post_types = sqool_get_post_types(); foreach ( $post_types as $post_type ) { add_meta_box( 'custom_css', 'カスタムCSS', 'custom_css_input', $post_type, 'normal', 'high' ); } } function custom_css_input() { global $post; echo '<input type="hidden" name="custom_css_noncename" id="custom_css_noncename" value="'.wp_create_nonce('custom-css').'" />'; echo '<textarea name="custom_css" id="custom_css" rows="5" cols="30" style="width:100%;">'.get_post_meta($post->ID,'_custom_css',true).'</textarea>'; } function save_custom_css($post_id) { // 配列キーの存在チェックを追加(エラー防止) if (!isset($_POST['custom_css_noncename']) || !wp_verify_nonce($_POST['custom_css_noncename'], 'custom-css')) return $post_id; if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) return $post_id; if (!isset($_POST['custom_css'])) return $post_id; $custom_css = $_POST['custom_css']; update_post_meta($post_id, '_custom_css', $custom_css); } /** * CSS向けの最小サニタイズ(esc_html()の代替) * esc_html()はCSS構文(>や&など)を壊すため、危険な要素のみを削除 */ if ( ! function_exists('sqool_sanitize_css') ) { function sqool_sanitize_css( $css ) { if ( ! is_string( $css ) ) { return ''; } // 危険な要素を削除(</style>タグや<script>タグ) $css = preg_replace( '#</?style[^>]*>#i', '', $css ); $css = preg_replace( '#<script[^>]*>.*?</script>#is', '', $css ); // HTMLコメントを削除(<!-- -->) $css = preg_replace( '#<!--.*?-->#s', '', $css ); return $css; } } function insert_custom_css() { if ( ! is_page() && ! is_single() ) { return; } $post_id = get_queried_object_id(); if ( ! $post_id ) { return; } $custom_css = get_post_meta( $post_id, '_custom_css', true ); if ( $custom_css ) { // CSS向けの最小サニタイズを使用(esc_html()はCSS構文を壊すため使用しない) $sanitized_css = sqool_sanitize_css( $custom_css ); echo '<style type="text/css">' . $sanitized_css . '</style>'; } } /* Ver4.8用 ウィジェットに勝手にbrやpが入るのをブロック */ remove_filter('widget_text_content', 'wpautop'); /* ------------------------------------------------------------------------- * * カスタムタクソノミー追加 /* ------------------------------------------------------------------------- */ /* 脱出ゲームテーマ */ function add_custom_taxonomies() { $labels = array( 'name' => _x( 'テーマ別脱出ゲーム', 'taxonomy general name' ), 'singular_name' => _x( 'テーマ別脱出ゲーム', 'taxonomy singular name' ), 'search_items' => __( 'テーマを探す' ), 'popular_items' => __( 'ポピュラーなテーマ' ), 'all_items' => __( '全てのテーマ' ), 'parent_item' => null, 'parent_item_colon' => null, 'edit_item' => __( 'テーマを編集' ), 'update_item' => __( 'テーマをアップデート' ), 'add_new_item' => __( 'テーマを新しく追加' ), 'new_item_name' => __( '新たなテーマの名前' ), 'separate_items_with_commas' => __( 'コンマで区切ってください' ), 'add_or_remove_items' => __( 'テーマの追加または削除' ), 'choose_from_most_used' => __( '最も使用しているテーマ' ) ); register_taxonomy( 'escape-theme', array('post','hints-and-tips'), array( 'public' => true, 'show_ui' => true, 'hierarchical' => false, 'labels' => $labels, 'query_var' => true, 'rewrite' => true, 'show_tagcloud' => true ) ); } add_action('init', 'add_custom_taxonomies', 0); function add_custom_taxonomies_2() { /* 攻略ゲームタイトル */ $labels = array( 'name' => _x( '攻略ゲームタイトル', 'taxonomy general name' ), 'singular_name' => _x( '攻略ゲームタイトル', 'taxonomy singular name' ), 'search_items' => __( '攻略ゲームタイトルを選ぶ' ), 'popular_items' => __( 'よく使う攻略ゲームタイトル' ), 'all_items' => __( '全てのタイトル' ), 'parent_item' => null, 'parent_item_colon' => null, 'edit_item' => __( '攻略ゲームタイトルを編集' ), 'update_item' => __( '攻略ゲームタイトルをアップデート' ), 'add_new_item' => __( '攻略ゲームタイトルを新しく追加' ), 'new_item_name' => __( '新たな攻略ゲームタイトル名' ), 'separate_items_with_commas' => __( 'コンマで区切ってください' ), 'add_or_remove_items' => __( '攻略ゲームタイトルの追加または削除' ), 'choose_from_most_used' => __( '最も使用している攻略ゲームタイトル' ) ); register_taxonomy( 'game-title', array('post','page','business','businessnews','column','esports','news','blog','travel','review','report','special','hints-and-tips','premium'), array( 'public' => true, 'show_ui' => true, 'hierarchical' => true, 'labels' => $labels, 'query_var' => true, 'rewrite' => array( 'slug' => 'hints-and-tips', 'with_front' => false, 'hierarchical' => false ), 'show_tagcloud' => true ) ); } add_action('init', 'add_custom_taxonomies_2', 0); function add_custom_taxonomies_3() { /* 外部配信キーワード */ $labels = array( 'name' => _x( '配信キーワード', 'taxonomy general name' ), 'singular_name' => _x( '配信キーワード', 'taxonomy singular name' ), 'search_items' => __( '配信キーワードを選ぶ' ), 'popular_items' => __( 'よく使う配信キーワード' ), 'all_items' => __( '全てのタイトル' ), 'parent_item' => null, 'parent_item_colon' => null, 'edit_item' => __( '配信キーワードを編集' ), 'update_item' => __( '配信キーワードをアップデート' ), 'add_new_item' => __( '配信キーワードを新しく追加' ), 'new_item_name' => __( '新たな配信キーワード' ), 'separate_items_with_commas' => __( 'コンマで区切ってください' ), 'add_or_remove_items' => __( '配信キーワードの追加または削除' ), 'choose_from_most_used' => __( '最も使用している配信キーワード' ) ); register_taxonomy( 'delivery-keyword', array('post','page','business','businessnews','column','esports','news','dreamnews','prwire','robot','blog','travel','review','report','special','hints-and-tips','premium'), array( 'public' => true, 'show_ui' => true, 'hierarchical' => true, 'labels' => $labels, 'query_var' => true, 'rewrite' => true, 'show_tagcloud' => true ) ); } add_action('init', 'add_custom_taxonomies_3', 0); function add_custom_taxonomies_4() { /* eスポーツタイトル */ $labels = array( 'name' => _x( 'eスポーツタイトル', 'taxonomy general name' ), 'singular_name' => _x( 'eスポーツタイトル', 'taxonomy singular name' ), 'search_items' => __( 'eスポーツタイトルを選ぶ' ), 'popular_items' => __( 'よく使うeスポーツタイトル' ), 'all_items' => __( '全てのeスポーツタイトル' ), 'parent_item' => null, 'parent_item_colon' => null, 'edit_item' => __( 'eスポーツタイトルを編集' ), 'update_item' => __( 'eスポーツタイトルをアップデート' ), 'add_new_item' => __( 'eスポーツタイトルを新しく追加' ), 'new_item_name' => __( '新たなeスポーツタイトル' ), 'separate_items_with_commas' => __( 'コンマで区切ってください' ), 'add_or_remove_items' => __( 'eスポーツタイトルの追加または削除' ), 'choose_from_most_used' => __( '最も使用しているeスポーツタイトル' ) ); register_taxonomy( 'esports-title', array('post','page','business','businessnews','column','esports','news','robot','blog','travel','review','report','special','hints-and-tips','premium'), array( 'public' => true, 'show_ui' => true, 'hierarchical' => true, 'labels' => $labels, 'query_var' => true, 'rewrite' => true, 'show_tagcloud' => true ) ); } add_action('init', 'add_custom_taxonomies_4', 0); function add_custom_taxonomies_5() { /* 脱出ゲームタイトル */ $labels = array( 'name' => _x( '脱出ゲームタイトル', 'taxonomy general name' ), 'singular_name' => _x( '脱出ゲームタイトル', 'taxonomy singular name' ), 'search_items' => __( '脱出ゲームタイトルを選ぶ' ), 'popular_items' => __( 'よく使う脱出ゲームタイトル' ), 'all_items' => __( '全ての脱出タイトル' ), 'parent_item' => null, 'parent_item_colon' => null, 'edit_item' => __( '脱出ゲームタイトルを編集' ), 'update_item' => __( '脱出ゲームタイトルをアップデート' ), 'add_new_item' => __( '脱出ゲームタイトルを新しく追加' ), 'new_item_name' => __( '新たな脱出ゲームタイトル名' ), 'separate_items_with_commas' => __( 'コンマで区切ってください' ), 'add_or_remove_items' => __( '脱出ゲームタイトルの追加または削除' ), 'choose_from_most_used' => __( '最も使用している脱出ゲームタイトル' ) ); register_taxonomy( 'escape-game-title', array('post','page','business','businessnews','column','esports','news','blog','travel','review','report','special','hints-and-tips'), array( 'public' => true, 'show_ui' => true, 'hierarchical' => true, 'labels' => $labels, 'query_var' => true, 'rewrite' => true, 'show_tagcloud' => true ) ); } add_action('init', 'add_custom_taxonomies_5', 0); /* ------------------------------------------------------------------------- * * コメントアバター追加 /* ------------------------------------------------------------------------- */ function tty_addgravatar( $avatar_defaults ) { $myavatar = get_bloginfo('url') . '/pic/g_avatar_3.png'; $avatar_defaults[$myavatar] = 'ゲスト'; return $avatar_defaults; } add_filter( 'avatar_defaults', 'tty_addgravatar' ); /* 固定ページのURL末尾にスラッシュを付ける */ function add_slash_uri_end( $uri, $type ) { // .html で終わるURLは末尾スラッシュを絶対に付けない(/foo.html/ を防止) if ( is_string( $uri ) && preg_match( '#\.html/?$#i', $uri ) ) { return preg_replace( '#/+$#', '', $uri ); } // single 以外は従来どおり末尾スラッシュ if ( $type !== 'single' ) { $uri = trailingslashit( $uri ); } return $uri; } add_filter('user_trailingslashit', 'add_slash_uri_end', 10, 2); /* ------------------------------------------------------------------------- * * コメント欄クッキー保存コメント変更 /* ------------------------------------------------------------------------- */ function comment_form_cookies_msg_4536($arg) { if(function_exists('wp_get_current_commenter')) $commenter = wp_get_current_commenter(); $consent = empty( $commenter['comment_author_email'] ) ? '' : ' checked="checked"'; $title = '名前を保存する。'; // 自由に変更可能 $arg['cookies'] = '<p class="comment-form-cookies-consent">'. '<input id="wp-comment-cookies-consent" name="wp-comment-cookies-consent" type="checkbox" value="yes"'.$consent.' />'. '<label for="wp-comment-cookies-consent">'.$title.'</label></p>'; return $arg; } add_filter( 'comment_form_default_fields', 'comment_form_cookies_msg_4536' ); /* ------------------------------------------------------------------------- * 安全なunserialize処理関数(汎用版) * 壊れたシリアライズデータでもエラーを出さずにfalseを返す * FeedWordPressブロックの外に定義(コメント添付などでも使用するため) * ------------------------------------------------------------------------- */ if ( ! function_exists('sqool_safe_unserialize') ) { function sqool_safe_unserialize( $data ) { // 既に配列やオブジェクトの場合はそのまま返す if ( is_array( $data ) || is_object( $data ) ) { return $data; } // nullやfalse、空文字列の場合はfalseを返す if ( empty( $data ) || ! is_string( $data ) ) { return false; } // シリアライズされていない場合はfalseを返す if ( ! function_exists( 'is_serialized' ) || ! is_serialized( $data ) ) { return false; } // エラーハンドラーを一時的に設定して、unserialize()のエラーを完全にキャッチ // 他のエラーは触らない(最小構成でunserialize警告だけ握る) $previous_error_handler = set_error_handler( function( $errno, $errstr, $errfile, $errline ) use ( &$previous_error_handler ) { // unserialize()関連のエラーのみをキャッチ(再発耐性を上げるため、Error at offsetに限定せずunserialize()全般に対応) if ( ( $errno === E_WARNING || $errno === E_NOTICE ) && strpos( $errstr, 'unserialize()' ) !== false ) { return true; // unserialize()関連のエラーを抑制 } // それ以外のエラーは元のハンドラーに渡す(触らない) if ( $previous_error_handler !== null ) { return call_user_func( $previous_error_handler, $errno, $errstr, $errfile, $errline ); } // ハンドラーがない場合はデフォルト動作に任せる return false; }, E_WARNING | E_NOTICE ); // unserializeを実行(エラーが発生しても抑制される) // @は使わず、エラーハンドラーに完全に任せる $result = unserialize( $data ); // エラーハンドラーを復元(確実に元に戻す) restore_error_handler(); // 失敗した場合(falseが返され、かつ元のデータがfalseのシリアライズでない場合)はfalseを返す if ( $result === false ) { // 元のデータが false のシリアライズ("b:0;")かどうかを確認 // 静的変数でキャッシュして毎回serialize()しないように最適化 static $serialized_false = null; if ( $serialized_false === null ) { $serialized_false = serialize( false ); } if ( $data !== $serialized_false ) { // falseのシリアライズでない場合は失敗として扱う return false; } } return $result; } } /* ------------------------------------------------------------------------- * コメントへの画像添付(comment-attachment代替/補完) * 目的: * - comment-attachment プラグインのPHP警告(Undefined array key等)が原因で管理画面/フロントが重くなる場合でも * コメント添付機能を維持できるようにする。 * 方針: * - フォームに file input を追加 * - 送信時に wp_handle_upload / media_handle_upload でアップロード * - comment_meta に attachment_id を保存 * - 表示時に comment_text の末尾へ添付画像を差し込む * * 注意: * - まずは安全側(画像のみ、サイズ制限あり) * - 既存プラグインを残す場合でも、この実装だけで最低限の添付は動く * ------------------------------------------------------------------------- */ // 設定(必要なら調整) if ( ! defined( 'SQOOL_COMMENT_ATTACH_MAX_BYTES' ) ) { define( 'SQOOL_COMMENT_ATTACH_MAX_BYTES', 3 * 1024 * 1024 ); // 3MB } // comment form を multipart にする(ファイル送信のため) // NOTE: comment_form_defaults の 'form' を直接書き換えるとテーマ/環境によって効かないことがあるため、 // 出力される <form> タグ自体をフィルタして確実に付与する。 add_filter( 'comment_form_tag', function( $form_tag ) { if ( strpos( $form_tag, 'enctype=' ) !== false ) { return $form_tag; } return str_replace( '<form', '<form enctype="multipart/form-data"', $form_tag ); } ); // フォームに添付フィールドとnonceを追加(ログイン/未ログイン両対応) function sqool_comment_attachment_field() { // コメントが閉じている/対象外の画面では何もしない if ( ! is_singular() || ! comments_open() ) { return; } // 画像添付フィールド echo '<p class="comment-form-attachment" style="margin-top:12px;">'; echo '<label for="sqool_comment_attachment">画像を添付(任意)</label><br />'; echo '<input type="file" id="sqool_comment_attachment" name="sqool_comment_attachment" accept="image/*" />'; echo '</p>'; // nonce wp_nonce_field( 'sqool_comment_attachment', 'sqool_comment_attachment_nonce' ); } add_action( 'comment_form_after_fields', 'sqool_comment_attachment_field' ); add_action( 'comment_form_logged_in_after', 'sqool_comment_attachment_field' ); // バリデーション(サイズ/拡張子) add_filter( 'preprocess_comment', function( $commentdata ) { if ( empty( $_FILES['sqool_comment_attachment'] ) ) { return $commentdata; } if ( ! isset( $_POST['sqool_comment_attachment_nonce'] ) || ! wp_verify_nonce( $_POST['sqool_comment_attachment_nonce'], 'sqool_comment_attachment' ) ) { // コメント本文は受け付け、添付だけ無視する(UX悪化とDoSリスクを避ける) unset( $_FILES['sqool_comment_attachment'] ); return $commentdata; } $f = $_FILES['sqool_comment_attachment']; // エラー無し以外は無視 if ( ! isset( $f['error'] ) || (int) $f['error'] !== UPLOAD_ERR_OK ) { return $commentdata; } // サイズ制限(違反時は添付だけ破棄、コメントは通す) if ( isset( $f['size'] ) && (int) $f['size'] > SQOOL_COMMENT_ATTACH_MAX_BYTES ) { // wp_die()ではなく、添付ファイルだけ破棄してコメント投稿を続行(DoS耐性・UX向上) unset( $_FILES['sqool_comment_attachment'] ); return $commentdata; } // MIME/拡張子制限(画像のみ)(違反時は添付だけ破棄、コメントは通す) $check = wp_check_filetype_and_ext( $f['tmp_name'], $f['name'] ); $allowed_mimes = array( 'image/jpeg', 'image/png', 'image/gif', 'image/webp' ); if ( empty( $check['type'] ) || ! in_array( $check['type'], $allowed_mimes, true ) ) { // wp_die()ではなく、添付ファイルだけ破棄してコメント投稿を続行(DoS耐性・UX向上) unset( $_FILES['sqool_comment_attachment'] ); return $commentdata; } return $commentdata; } ); // コメント保存後にアップロード処理して comment_meta に attachment_id を保存 add_action( 'comment_post', function( $comment_id ) { if ( empty( $_FILES['sqool_comment_attachment'] ) ) { return; } if ( ! isset( $_POST['sqool_comment_attachment_nonce'] ) || ! wp_verify_nonce( $_POST['sqool_comment_attachment_nonce'], 'sqool_comment_attachment' ) ) { return; } $f = $_FILES['sqool_comment_attachment']; if ( ! isset( $f['error'] ) || (int) $f['error'] !== UPLOAD_ERR_OK ) { return; } // media_handle_upload を使うために必要 require_once ABSPATH . 'wp-admin/includes/file.php'; require_once ABSPATH . 'wp-admin/includes/media.php'; require_once ABSPATH . 'wp-admin/includes/image.php'; // コメントに紐づける親は存在しないので 0(必要なら投稿IDにしても良い) $attachment_id = media_handle_upload( 'sqool_comment_attachment', 0 ); if ( is_wp_error( $attachment_id ) ) { // ここで wp_die するとコメント自体は既に保存済みなので、致命停止は避ける // エラーログに記録(デバッグ用) if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) { error_log( 'SQOOL Comment Attachment Error: ' . $attachment_id->get_error_message() . ' (Comment ID: ' . $comment_id . ')' ); } return; } add_comment_meta( $comment_id, 'sqool_comment_attachment_id', (int) $attachment_id, true ); }, 10, 1 ); // 互換: comment-attachment 等の既存プラグインが保存していた comment_meta をできるだけ拾って表示する function sqool_get_comment_attachment_html( $comment_id ) { $comment_id = (int) $comment_id; if ( $comment_id <= 0 ) { return ''; } // 共通: 画像HTML生成(attachment ID から) $sqool_render_attachment_id = function( $attachment_id ) { $attachment_id = (int) $attachment_id; if ( $attachment_id <= 0 ) { return ''; } $img = wp_get_attachment_image( $attachment_id, 'medium', false, array( 'class' => 'sqool-comment-attachment', 'loading' => 'lazy', 'decoding' => 'async', ) ); if ( $img ) { return '<div class="sqool-comment-attachment-wrap" style="margin-top:10px;">' . $img . '</div>'; } return ''; }; // 共通: 画像HTML生成(URL から) $sqool_render_image_url = function( $url ) { if ( ! is_string( $url ) ) { return ''; } $vv = trim( $url ); if ( $vv === '' ) { return ''; } if ( preg_match( '#^https?://#i', $vv ) ) { $ext = strtolower( pathinfo( parse_url( $vv, PHP_URL_PATH ), PATHINFO_EXTENSION ) ); $allowed_ext = array( 'jpg', 'jpeg', 'png', 'gif', 'webp' ); if ( in_array( $ext, $allowed_ext, true ) ) { return '<div class="sqool-comment-attachment-wrap" style="margin-top:10px;">' . '<img class="sqool-comment-attachment" loading="lazy" decoding="async" src="' . esc_url( $vv ) . '" alt="" />' . '</div>'; } } return ''; }; // 共通: uploads のファイルパス / 相対パスをURLに解決して表示 $sqool_render_uploads_path = function( $path_or_url ) use ( $sqool_render_image_url ) { if ( ! is_string( $path_or_url ) ) { return ''; } $v = trim( $path_or_url ); if ( $v === '' ) { return ''; } // すでにURLならそのまま if ( preg_match( '#^https?://#i', $v ) ) { return $sqool_render_image_url( $v ); } $uploads = wp_upload_dir(); $baseurl = isset( $uploads['baseurl'] ) ? $uploads['baseurl'] : ''; $basedir = isset( $uploads['basedir'] ) ? $uploads['basedir'] : ''; if ( ! $baseurl || ! $basedir ) { return ''; } // (A) 絶対パスが uploads 配下 if ( strpos( $v, $basedir ) === 0 ) { $rel = ltrim( str_replace( $basedir, '', $v ), '/' ); return $sqool_render_image_url( trailingslashit( $baseurl ) . $rel ); } // (B) /wp-content/uploads/... 形式 if ( strpos( $v, '/wp-content/uploads/' ) !== false ) { $pos = strpos( $v, '/wp-content/uploads/' ); $rel = substr( $v, $pos + strlen( '/wp-content/uploads/' ) ); $rel = ltrim( $rel, '/' ); return $sqool_render_image_url( trailingslashit( $baseurl ) . $rel ); } // (C) uploads配下の相対パスのみ(例: 2018/03/foo.jpg) if ( preg_match( '#^\d{4}/\d{2}/#', $v ) ) { return $sqool_render_image_url( trailingslashit( $baseurl ) . ltrim( $v, '/' ) ); } return ''; }; // 共通: 値から添付を推定して表示(ID / URL / 配列 / シリアライズ文字列 / パス) // NOTE: 再帰(配列/ネスト構造)を扱うため、クロージャを参照渡しでuseする $sqool_try_render_from_value = null; $sqool_try_render_from_value = function( $val ) use ( &$sqool_try_render_from_value, $sqool_render_attachment_id, $sqool_render_image_url, $sqool_render_uploads_path ) { if ( empty( $val ) ) { return ''; } // シリアライズ文字列は展開(安全に処理) if ( is_string( $val ) && function_exists( 'is_serialized' ) && is_serialized( $val ) ) { $un = sqool_safe_unserialize( $val ); if ( $un !== false && $un !== $val ) { $val = $un; } } // 数値(attachment ID の可能性) if ( is_numeric( $val ) ) { return $sqool_render_attachment_id( (int) $val ); } // URL if ( is_string( $val ) ) { $h = $sqool_render_image_url( $val ); if ( $h ) { return $h; } // ファイルパス/相対パス $h = $sqool_render_uploads_path( $val ); if ( $h ) { return $h; } } // 配列(プラグイン実装差異) if ( is_array( $val ) ) { $keys = array( 'attachment_id', 'id', 'file_id', 'url', 'file', 'path', 'guid', ); foreach ( $keys as $k ) { if ( isset( $val[ $k ] ) ) { $h = $sqool_try_render_from_value( $val[ $k ] ); if ( $h ) { return $h; } } } // それ以外: 配列を総当りで探索 foreach ( $val as $vv ) { $h = $sqool_try_render_from_value( $vv ); if ( $h ) { return $h; } } } return ''; }; // 1) このfunctions.php実装のメタ(推奨) $attachment_id = (int) get_comment_meta( $comment_id, 'sqool_comment_attachment_id', true ); if ( $attachment_id > 0 ) { $h = $sqool_render_attachment_id( $attachment_id ); if ( $h ) { return $h; } } // 2) 旧プラグイン互換(まずは「よくある」キーを優先探索) $legacy_keys = array( 'comment_attachment_id', 'comment-attachment', 'comment_attachment', 'attachment_id', '_attachment_id', '_comment_attachment_id', 'comment_attachment_url', 'attachment_url', 'comment_attachment_file', 'attachment_file', 'ca_attachment_id', 'ca_attachment', 'comment_attachment_meta', ); foreach ( $legacy_keys as $k ) { $v = get_comment_meta( $comment_id, $k, true ); $h = $sqool_try_render_from_value( $v ); if ( $h ) { return $h; } } // 全メタ走査は削除(根本解決: 壊れたserializedデータを踏んでエラーを量産しないため) // 互換性は legacy_keys の範囲に限定し、総当り探索は行わない // 見つからなかった場合は空を返す return ''; } // 表示: コメント本文末尾に添付画像を差し込む(新実装 + 旧プラグイン互換) add_filter( 'comment_text', function( $comment_text, $comment = null ) { // $commentがオブジェクトでない場合は、グローバルから取得を試みる if ( empty( $comment ) || ! is_object( $comment ) ) { global $comment; if ( empty( $comment ) || empty( $comment->comment_ID ) ) { return $comment_text; } } if ( empty( $comment->comment_ID ) ) { return $comment_text; } // この実装が既に添付画像を差し込んだかどうかを判定(sqool-comment-attachment-wrapクラスで判断) // <img> タグの存在ではなく、この実装が生成したマーカーで判定することで、他のプラグインや絵文字による誤判定を回避 if ( strpos( $comment_text, 'sqool-comment-attachment-wrap' ) !== false ) { return $comment_text; } $attach_html = sqool_get_comment_attachment_html( $comment->comment_ID ); if ( ! $attach_html ) { return $comment_text; } return $comment_text . $attach_html; }, 20, 2 ); /* 管理メニューバーがずれるのを修正 */ // TODO: 将来的にはCSSファイル側へ寄せる(毎回インラインCSSを吐くのはノイズになり得る) function oz_admin_bar_to_the_bottom() { if (wp_is_mobile()) { echo '<style type="text/css"> #wpadminbar{ margin-top:0; position: fixed; z-index: 999999999999; } </style>'; }else{ echo '<style type="text/css"> #wpadminbar{ margin-top:34px; position: fixed; z-index: 999999999999; } </style>'; } } add_action( 'wp_head', 'oz_admin_bar_to_the_bottom' ); /* カスタム投稿タイプを追加 */ add_action( 'init', 'create_post_type' ); function create_post_type() { // カスタム投稿タイプの定義を配列で管理 $post_types = array( 'column' => array( 'name' => 'コラム', 'slug' => 'column/archive', 'has_archive' => true ), 'news' => array( 'name' => 'ニュース', 'slug' => 'news/archive', 'has_archive' => true ), 'dreamnews' => array( 'name' => 'ドリームニュース', 'slug' => 'news/dreamnews/archive', 'has_archive' => true ), 'prwire' => array( 'name' => 'PRワイヤー', 'slug' => 'news/prwire/archive', 'has_archive' => true ), 'esports' => array( 'name' => 'eスポーツ', 'slug' => 'esports/archive', 'has_archive' => true ), 'business' => array( 'name' => 'ビジネス', 'slug' => 'business/archive', 'has_archive' => true ), 'businessnews' => array( 'name' => 'ビジネスニュース', 'slug' => 'business/news/archive', 'has_archive' => true ), 'robot' => array( 'name' => 'ロボット', 'slug' => 'robot/archive', 'has_archive' => true ), 'blog' => array( 'name' => 'ブログ', 'slug' => 'blog/archive', 'has_archive' => true ), 'travel' => array( 'name' => '旅行', 'slug' => 'travel/archive', 'has_archive' => true ), 'review' => array( 'name' => 'レビュー', 'slug' => 'review/archive', 'has_archive' => true ), 'report' => array( 'name' => '取材', 'slug' => 'report/archive', 'has_archive' => true ), 'notice' => array( 'name' => 'お知らせ', 'slug' => 'notice/archive', 'has_archive' => true ), 'link' => array( 'name' => 'リンクページ', 'slug' => 'link/archive', 'has_archive' => true ), 'special' => array( 'name' => '特設', 'slug' => 'special/archive', 'has_archive' => true ), 'hints-and-tips' => array( 'name' => 'ゲーム攻略', 'slug' => 'hints-and-tips', 'has_archive' => false ), 'premium' => array( 'name' => 'プレミアム', 'slug' => 'premium/archive', 'has_archive' => false ) ); // 共通設定 $common_supports = array( 'title', 'editor', 'author', 'thumbnail', 'excerpt', 'custom-fields', 'trackbacks', 'comments', 'revisions' ); $post_type_keys = array_keys( $post_types ); // ループで登録 foreach ( $post_types as $post_type => $args ) { register_post_type( $post_type, array( 'labels' => array( 'name' => __( $args['name'] ), 'singular_name' => __( $args['name'] ) ), 'public' => true, 'has_archive' => $args['has_archive'], 'menu_position' => 5, 'supports' => $common_supports, 'rewrite' => array( 'slug' => $args['slug'], 'with_front' => false ), 'yarpp_support' => true ) ); } // カスタム投稿タイプカテゴリとタグ共用 foreach ( $post_type_keys as $post_type ) { register_taxonomy_for_object_type( 'category', $post_type ); register_taxonomy_for_object_type( 'post_tag', $post_type ); } } /* ------------------------------------------------------------------------- * CPT「日付-投稿ID.html」形式のシングルURLを確実に解決するためのリライトルール * 目的: * - /news/archive/20251219-535416.html を single に解決 * - 末尾スラッシュ付与(.html/)や archive への丸め込みを防ぐ * 対象: * - news, dreamnews, prwire, businessnews * ------------------------------------------------------------------------- */ // 1) ルール追加(.htmlあり/なし、末尾スラッシュあり/なしに対応) function sqool_add_cpt_html_rewrite_rules() { // news add_rewrite_rule( '^news/archive/(\d{8})-(\d+)\.html/?$', 'index.php?post_type=news&p=$matches[2]', 'top' ); add_rewrite_rule( '^news/archive/(\d{8})-(\d+)/?$', 'index.php?post_type=news&p=$matches[2]', 'top' ); // dreamnews add_rewrite_rule( '^news/dreamnews/archive/(\d{8})-(\d+)\.html/?$', 'index.php?post_type=dreamnews&p=$matches[2]', 'top' ); add_rewrite_rule( '^news/dreamnews/archive/(\d{8})-(\d+)/?$', 'index.php?post_type=dreamnews&p=$matches[2]', 'top' ); // prwire add_rewrite_rule( '^news/prwire/archive/(\d{8})-(\d+)\.html/?$', 'index.php?post_type=prwire&p=$matches[2]', 'top' ); add_rewrite_rule( '^news/prwire/archive/(\d{8})-(\d+)/?$', 'index.php?post_type=prwire&p=$matches[2]', 'top' ); // businessnews add_rewrite_rule( '^business/news/archive/(\d{8})-(\d+)\.html/?$', 'index.php?post_type=businessnews&p=$matches[2]', 'top' ); add_rewrite_rule( '^business/news/archive/(\d{8})-(\d+)/?$', 'index.php?post_type=businessnews&p=$matches[2]', 'top' ); } add_action( 'init', 'sqool_add_cpt_html_rewrite_rules', 20 ); // notice アーカイブを /notice/ にも対応させる(リンク先と実際のアーカイブスラッグの不一致を吸収) function sqool_add_notice_archive_alias_rules() { // /notice/ を notice アーカイブに解決 add_rewrite_rule( '^notice/?$', 'index.php?post_type=notice', 'top' ); // /notice/page/2/ などのページングにも対応 add_rewrite_rule( '^notice/page/([0-9]{1,})/?$', 'index.php?post_type=notice&paged=$1', 'top' ); } add_action( 'init', 'sqool_add_notice_archive_alias_rules', 20 ); // report アーカイブを /report/ にも対応させる(リンク先と実際のアーカイブスラッグの不一致を吸収) function sqool_add_report_archive_alias_rules() { // /report/ を report アーカイブに解決 add_rewrite_rule( '^report/?$', 'index.php?post_type=report', 'top' ); // /report/page/2/ などのページングにも対応 add_rewrite_rule( '^report/page/([0-9]{1,})/?$', 'index.php?post_type=report&paged=$1', 'top' ); } add_action( 'init', 'sqool_add_report_archive_alias_rules', 20 ); // 上記ルールを確実に反映させるため、一度だけリライトルールをフラッシュ function sqool_maybe_flush_rewrite_once_for_notice_alias() { $ver = get_option( 'sqool_notice_alias_rules_v1', '' ); if ( $ver === '1' ) { return; } update_option( 'sqool_notice_alias_rules_v1', '1', false ); flush_rewrite_rules( false ); } add_action( 'admin_init', 'sqool_maybe_flush_rewrite_once_for_notice_alias' ); // report アーカイブのリライトルールを確実に反映させるため、一度だけリライトルールをフラッシュ function sqool_maybe_flush_rewrite_once_for_report_alias() { $ver = get_option( 'sqool_report_alias_rules_v1', '' ); if ( $ver === '1' ) { return; } update_option( 'sqool_report_alias_rules_v1', '1', false ); flush_rewrite_rules( false ); } add_action( 'admin_init', 'sqool_maybe_flush_rewrite_once_for_report_alias' ); // game-title タクソノミーのリライトルールを確実に反映させるため、一度だけリライトルールをフラッシュ function sqool_maybe_flush_rewrite_once_for_game_title_taxonomy() { $ver = get_option( 'sqool_game_title_taxonomy_rewrite_v1', '' ); if ( $ver === '1' ) { return; } update_option( 'sqool_game_title_taxonomy_rewrite_v1', '1', false ); flush_rewrite_rules( false ); } add_action( 'admin_init', 'sqool_maybe_flush_rewrite_once_for_game_title_taxonomy' ); // hints-and-tips 固定ページのリライトルールを確実に反映させるため、一度だけリライトルールをフラッシュ function sqool_maybe_flush_rewrite_once_for_hints_and_tips_page() { $ver = get_option( 'sqool_hints_and_tips_page_rewrite_v1', '' ); if ( $ver === '1' ) { return; } update_option( 'sqool_hints_and_tips_page_rewrite_v1', '1', false ); flush_rewrite_rules( false ); } add_action( 'admin_init', 'sqool_maybe_flush_rewrite_once_for_hints_and_tips_page' ); // hints-and-tips の固定ページを優先的に認識させる(game-titleタクソノミーとの競合を回避) // request フィルタで固定ページを優先 function sqool_prioritize_hints_and_tips_page( $query_vars ) { // 管理画面やフィードの場合は処理しない if ( is_admin() || ( defined( 'DOING_CRON' ) && DOING_CRON ) ) { return $query_vars; } // game-title タクソノミーが既に設定されている場合 if ( isset( $query_vars['game-title'] ) ) { $term_slug = $query_vars['game-title']; // 固定ページとして存在するかチェック $page = get_page_by_path( 'hints-and-tips/' . $term_slug ); if ( $page && $page->post_status === 'publish' ) { // 固定ページが存在する場合は、タクソノミーのクエリを削除して固定ページとして処理 unset( $query_vars['game-title'] ); unset( $query_vars['taxonomy'] ); unset( $query_vars['term'] ); $query_vars['pagename'] = 'hints-and-tips/' . $term_slug; } } return $query_vars; } add_filter( 'request', 'sqool_prioritize_hints_and_tips_page', 1 ); // 2) .html系URLの canonical redirect を抑止(/foo.html/ 誘導や archive への丸め込みを防ぐ) function sqool_disable_canonical_for_cpt_html( $redirect_url, $requested_url ) { $path = ''; if ( is_string( $requested_url ) && $requested_url !== '' ) { $pp = wp_parse_url( $requested_url ); $path = isset( $pp['path'] ) ? $pp['path'] : ''; } if ( $path === '' ) { return $redirect_url; } if ( preg_match( '#^/news/archive/\d{8}-\d+\.html/?$#', $path ) || preg_match( '#^/news/dreamnews/archive/\d{8}-\d+\.html/?$#', $path ) || preg_match( '#^/news/prwire/archive/\d{8}-\d+\.html/?$#', $path ) || preg_match( '#^/business/news/archive/\d{8}-\d+\.html/?$#', $path ) ) { return false; } return $redirect_url; } add_filter( 'redirect_canonical', 'sqool_disable_canonical_for_cpt_html', 10, 2 ); // 3) リライトルールのフラッシュを「一度だけ」実行(パーマリンク画面が死ぬ場合の救済) function sqool_maybe_flush_rewrite_once_for_cpt_html() { $ver = get_option( 'sqool_cpt_html_rules_v1', '' ); if ( $ver === '1' ) { return; } update_option( 'sqool_cpt_html_rules_v1', '1', false ); flush_rewrite_rules( false ); // .htaccess は触らない } add_action( 'admin_init', 'sqool_maybe_flush_rewrite_once_for_cpt_html' ); /* カテゴリ一覧にカスタム投稿タイプ追加*/ add_action('pre_get_posts', 'show_categorized_pages_in_archive'); function show_categorized_pages_in_archive( $query ) { if ( $query->is_category && $query->is_main_query() ) { $query->set( 'post_type', sqool_get_post_types() ); } } /* タグ一覧にカスタム投稿タイプ追加*/ add_action('pre_get_posts', 'show_taged_pages_in_archive'); function show_taged_pages_in_archive( $query ) { if ( $query->is_tag && $query->is_main_query() ) { $query->set( 'post_type', sqool_get_post_types() ); } } /* カスタム投稿タイプRSS統合 */ function mysite_feed_request( $vars ) { if ( isset( $vars['feed'] ) && ! isset( $vars['post_type'] ) ) { $vars['post_type'] = sqool_get_post_types(); } return $vars; } add_filter( 'request', 'mysite_feed_request' ); /* ショートコード設定開始 */ //吹き出し function bubble_left_img($atts, $content = null ) { //初期設定 extract(shortcode_atts(array( 'id' =>'3', 'align' =>'left', 'imgurl' =>'none', 'speaker' =>'none' ), $atts)); //違う画像を表示したかったら if ($imgurl == 'none'){ $img = get_avatar_url($id); } else { $img = $imgurl; } //メンバー以外の名前を表示したかったら if($speaker == 'none'){ $author = get_the_author_meta('nickname', $id); } else { $author = $speaker; } //無理やりhtmlを生成 $bubble_html='<div class="balloon-box balloon-'.$align.' clrfix"> <div class="balloon-icon"><img src="'. $img .'"><br><span>'. $author .'</span></div> <div class="balloon-serif"><div class="balloon-content">'. $content .'</div></div> </div>'; return $bubble_html; } add_shortcode('bubble', 'bubble_left_img'); //白黒のSNSボタン function shortcode2() { ob_start(); get_template_part('/shortcorde/sns_channel'); return ob_get_clean(); } add_shortcode('sns_channel', 'shortcode2'); //攻略記事ファーストビュー function shortcode3() { global $post; ob_start(); $isAmp = (wp_is_mobile() && isset($_GET['amp']) && $_GET['amp'] == 1) ? true : false; if($isAmp){ echo('<div class="headleft1">'); echo('<div class="article_top_img">'); $thumbnail_id = get_post_thumbnail_id(); $thumbnail_img = wp_get_attachment_image_src( $thumbnail_id , 'thumb150_113' ); echo('<amp-img src="'); echo $thumbnail_img[0]; echo('" width="121" height="97"></amp-img>'); echo('</div>'); echo('<div style="line-height:1.4; ">'); if ( has_excerpt( $post->ID ) ) { the_excerpt(); } echo('</div>'); echo('<div class="clear"></div>'); }else{ echo('<div style="width:100%;margin-top:5px;">'); echo('<div style="width:30%; float:left;margin-right:5px;" class="article_top_img">'); the_post_thumbnail('thumb150_113'); echo('</div>'); echo('<div style="line-height:1.4; ">'); if ( has_excerpt( $post->ID ) ) { the_excerpt(); } echo('</div>'); echo('<div class="clear"></div>'); } return ob_get_clean(); } add_shortcode('image_left_text_right', 'shortcode3'); //パシリン function shortcode4() { ob_start(); if (wp_is_mobile()) { echo(' <a href="https://sqool.net/ninja-pasirin"><img src="https://sqool.net/wp-content/uploads/2015/12/600_200_title_banner02.jpg" alt="" width="600" height="200" /></a> '); }else{ echo(' <a href="https://sqool.net/ninja-pasirin"><img src="https://sqool.net/wp-content/uploads/2015/12/600_200_title_banner02-500x167.jpg" alt="" width="300px" height="100" /></a> '); } return ob_get_clean(); } add_shortcode('pasirin_bana', 'shortcode4'); //パズドラ攻略コーナー function shortcode_pazudora_menu() { ob_start(); if (file_exists(get_template_directory() . '/shortcorde/pazudora_menu.php')) { include(get_template_directory() . '/shortcorde/pazudora_menu.php'); } else { echo '<p>メニューが現在利用できません。</p>'; } return ob_get_clean(); } add_shortcode('pazudora_menu', 'shortcode_pazudora_menu'); //検索ボックス function shortcode6() { ob_start(); get_search_form(); return ob_get_clean(); } add_shortcode('get_search_form', 'shortcode6'); //更新日 function shortcode8() { ob_start(); the_modified_date('Y年n月j日'); return ob_get_clean(); } add_shortcode('updated', 'shortcode8'); //黒ウィズ攻略コーナー function shortcode10() { ob_start(); get_template_part('/shortcorde/wiz_menu'); return ob_get_clean(); } add_shortcode('wiz_menu', 'shortcode10'); //FFRK攻略コーナー function shortcode11() { ob_start(); get_template_part('/shortcorde/ffrk_menu'); return ob_get_clean(); } add_shortcode('ffrk_menu', 'shortcode11'); //DQMSL攻略コーナー function shortcode12() { ob_start(); get_template_part('/shortcorde/dqmsl_menu'); return ob_get_clean(); } add_shortcode('dqmsl_menu', 'shortcode12'); //グラブル攻略コーナー function shortcode14() { ob_start(); get_template_part('/shortcorde/guraburu_menu'); return ob_get_clean(); } add_shortcode('guraburu_menu', 'shortcode14'); //モンスト攻略コーナー function shortcode15() { ob_start(); get_template_part('/shortcorde/monst_menu'); return ob_get_clean(); } add_shortcode('monst_menu', 'shortcode15'); //おすすめ検索ワードあり検索ボックス function shortcode16() { ob_start(); get_template_part('/shortcorde/search_option'); return ob_get_clean(); } add_shortcode('search_option', 'shortcode16'); //攻略タイトル一覧 function shortcode17() { ob_start(); get_template_part('/shortcorde/cheats-list'); return ob_get_clean(); } add_shortcode('cheats-list', 'shortcode17'); //サイトマップページ function shortcode18() { ob_start(); get_template_part('/shortcorde/sitemap'); return ob_get_clean(); } add_shortcode('sitemap', 'shortcode18'); //脱出ゲーム攻略メニュー function shortcode19() { ob_start(); get_template_part('/shortcorde/escape_menu'); return ob_get_clean(); } add_shortcode('escape_menu', 'shortcode19'); //トップページ全コード function shortcode20() { ob_start(); get_template_part('/shortcorde/top_page'); return ob_get_clean(); } add_shortcode('top_page', 'shortcode20'); //ニュースメニュー function shortcode21() { ob_start(); get_template_part('/shortcorde/news_menu'); return ob_get_clean(); } add_shortcode('news_menu', 'shortcode21'); //攻略メニュー function shortcode22() { ob_start(); get_template_part('/shortcorde/how_to_play_menu'); return ob_get_clean(); } add_shortcode('how_to_play_menu', 'shortcode22'); //脱出ゲームのタイトル語尾 function shortcode23() { ob_start(); if(in_category(24)|| post_is_in_descendant_category( '24' )) { $etitle = get_the_title(); if(strstr($etitle,"脱出")==false){ echo('|脱出ゲーム攻略'); } } return ob_get_clean(); } add_shortcode('title_after', 'shortcode23'); //タイトル語頭 function shortcode24() { ob_start(); if(in_category(array('10','93','96','247','896','63','3334','6053','1693','789','2043','3548','4400','3558','4482','4639','7484','7657' ) )) { $category = get_the_category(); $cat_name = $category[0]->cat_name; echo('【'); echo $cat_name; echo('】'); }elseif ( in_category( '24' ) || post_is_in_descendant_category( '24' ) ) { if(has_tag('脱出ゲームタイトルページ')){ echo('脱出ゲーム '); } }elseif ( in_category(array('4183','4786')) ) { echo('【モンスト】'); }elseif ( in_category(array('8325')) ) { echo('【リネレボ】'); }elseif ( in_category( '4591' ) || post_is_in_descendant_category( '4591' ) ) { if ( has_term( 'pokemori', 'game-title' ) ) { echo('【ポケ森】'); } } return ob_get_clean(); } add_shortcode('title_head', 'shortcode24'); //鍵付きのユーザー投稿型 function shortcode25() { ob_start(); get_template_part('/shortcorde/news_post_lock'); return ob_get_clean(); } add_shortcode('news_post_lock', 'shortcode25'); //3秒後にトップページに移動 function shortcode26() { ob_start(); if (!wp_is_mobile()){ echo(' <meta http-equiv="Refresh" content="2, https://sqool.net/" />このページはスマートフォン専用です。<br>3秒後にトップページに移動します。<br>自動的に移動しない場合は下のリンクをクリックしてください。<br><a href="https://sqool.net/">https://sqool.net/</a><br><br><img src="https://sqool.net/pic/404.png"> '); } return ob_get_clean(); } add_shortcode('notpc', 'shortcode26'); //ゲーム動画コーナー function shortcode27() { ob_start(); get_template_part('/shortcorde/game_movie_menu'); return ob_get_clean(); } add_shortcode('game_movie_menu', 'shortcode27'); //スマホ ページ上部のMORE function shortcode28() { ob_start(); get_template_part('/shortcorde/corner_top_menu'); return ob_get_clean(); } add_shortcode('corner_top_menu', 'shortcode28'); //新着脱出ゲーム 開発者投稿 function shortcode29() { ob_start(); get_template_part('/shortcorde/escape_release'); return ob_get_clean(); } add_shortcode('escape_release', 'shortcode29'); //新着脱出ゲーム 開発者投稿 一覧 function shortcode30() { ob_start(); get_template_part('/shortcorde/escape_release_list'); return ob_get_clean(); } add_shortcode('escape_release_list', 'shortcode30'); //カテゴリ内最終更新日 function shortcode31() { ob_start(); get_template_part('/shortcorde/lastmodified'); return ob_get_clean(); } add_shortcode('lastmodified', 'shortcode31'); //new_article_escape_n function shortcode32() { ob_start(); get_template_part('/shortcorde/new_article_escape_n'); return ob_get_clean(); } add_shortcode('new_article_escape_n', 'shortcode32'); //全記事リスト PC左カラム用 脱出個別記事排除 function shortcode33() { ob_start(); get_template_part('/shortcorde/menu_list_format_pl_alllist'); return ob_get_clean(); } add_shortcode('menu_list_format_pl_alllist', 'shortcode33'); //各記事の下 新着記事一覧へのリンクボタン function shortcode34() { ob_start(); get_template_part('/shortcorde/content_under_allmenu'); return ob_get_clean(); } add_shortcode('content_under_allmenu', 'shortcode34'); //画像付きテーブル function shortcode35($atts) { extract(shortcode_atts(array( 'tagname' => '', 'exclude' => '', 'order' => '', 'orderby' => '', 'list_number' => '' ), $atts)); ob_start(); include(locate_template( '/shortcorde/matome_page.php' )); $output = ob_get_clean(); return $output; } add_shortcode('matome_page', 'shortcode35'); //ナビ有りリスト function shortcode36($atts) { extract(shortcode_atts(array( 'menu_cat' => '', 'list_number' => '' ), $atts)); ob_start(); include(locate_template( '/shortcorde/menu_list_format_n.php' )); $output = ob_get_clean(); return $output; } add_shortcode('menu_list_format_n', 'shortcode36'); //ナビ無しリスト function shortcode37($atts) { extract(shortcode_atts(array( 'menu_cat' => '', 'list_number' => '' ), $atts)); ob_start(); include(locate_template( '/shortcorde/menu_list_format.php' )); $output = ob_get_clean(); return $output; } add_shortcode('menu_list_format', 'shortcode37'); //ナビ無しリスト function shortcode38($atts) { extract(shortcode_atts(array( 'page_number' => '' ), $atts)); ob_start(); include(locate_template( '/shortcorde/menu_list_format_pl_alllist_n.php' )); $output = ob_get_clean(); return $output; } add_shortcode('menu_list_format_pl_alllist_n', 'shortcode38'); //menu_paged_p function shortcode39($atts) { extract(shortcode_atts(array( 'menu_cat' => '', 'page_number' => '', 'offsetno' => '' ), $atts)); ob_start(); include(locate_template( '/shortcorde/menu_paged_p.php' )); $output = ob_get_clean(); return $output; } add_shortcode('menu_paged_p', 'shortcode39'); //記事一覧 投稿タイプでフィルター function shortcode40($atts) { extract(shortcode_atts(array( 'menu_cat' => '', 'list_number' => '', 'post_type_name' => '' ), $atts)); ob_start(); include(locate_template( '/shortcorde/menu_list_format_post_type_n.php' )); $output = ob_get_clean(); return $output; } add_shortcode('menu_list_format_post_type_n', 'shortcode40'); //シンプルな2列の記事一覧  function shortcode41($atts) { extract(shortcode_atts(array( 'menu_cat' => '', 'offsetno' => '' ), $atts)); ob_start(); include(locate_template( '/shortcorde/menu_paged.php' )); $output = ob_get_clean(); return $output; } add_shortcode('menu_paged', 'shortcode41'); //一部で使われている1列の記事一覧  function shortcode42($atts) { extract(shortcode_atts(array( 'menu_tag' => '', 'list_number' => '' ), $atts)); ob_start(); include(locate_template( '/shortcorde/tag_menu.php' )); $output = ob_get_clean(); return $output; } add_shortcode('tag_menu', 'shortcode42'); //カテゴリ・タグ連結・日付アリ・ナビ無し・目次記事用【AかつB】  function shortcode44($atts) { extract(shortcode_atts(array( 'menu_cat_1' => '', 'menu_tag' => '', 'pagenumber' => '' ), $atts)); ob_start(); include(locate_template( '/shortcorde/menu_paged_cat_tag_n_s.php' )); $output = ob_get_clean(); return $output; } add_shortcode('menu_paged_cat_tag_n_s', 'shortcode44'); //脱出ゲーム各タイトルのトップページ 同開発者の他のゲーム function shortcode45($atts) { extract(shortcode_atts(array( 'tagname' => '' ), $atts)); ob_start(); include(locate_template( '/shortcorde/escape_top_developer.php' )); $output = ob_get_clean(); return $output; } add_shortcode('escape_top_developer', 'shortcode45'); //テーマ別脱出ゲーム一覧  function shortcode46($atts) { extract(shortcode_atts(array( 'order' => '', 'orderby' => '' ), $atts)); ob_start(); include(locate_template( '/shortcorde/escape_theme_list.php' )); $output = ob_get_clean(); return $output; } add_shortcode('escape_theme_list', 'shortcode46'); //開発者が投稿した脱出ゲームの一覧 function shortcode47($atts) { extract(shortcode_atts(array( 'post_no' => '' ), $atts)); ob_start(); include(locate_template( '/shortcorde/escape_release_new.php' )); $output = ob_get_clean(); return $output; } add_shortcode('escape_release_new', 'shortcode47'); //おすすめ脱出ゲームページ(開発者別ページ)  function shortcode48($atts) { extract(shortcode_atts(array( 'tagname' => '' ), $atts)); ob_start(); include(locate_template( '/shortcorde/escape_recommend_page.php' )); $output = ob_get_clean(); return $output; } add_shortcode('escape_recommend_page', 'shortcode48'); //パズドラテンプレパのパネル  function shortcode49($atts) { extract(shortcode_atts(array( 'monster' => '', 'text' => '', 'order' => '', 'orderby' => '' ), $atts)); ob_start(); include(locate_template( '/shortcorde/pazudora_template.php' )); $output = ob_get_clean(); return $output; } add_shortcode('pazudora_template', 'shortcode49'); //パズドラテンプレパのパネル(評価記事orテンプレパがない時用) function shortcode50($atts) { extract(shortcode_atts(array( 'monster' => '', 'text' => '', 'image' => '' ), $atts)); ob_start(); include(locate_template( '/shortcorde/pazudora_template_2.php' )); $output = ob_get_clean(); return $output; } add_shortcode('pazudora_template_2', 'shortcode50'); //パズドラテンプレパ 属性別 おすすめ度別 一覧  function shortcode51($atts) { extract(shortcode_atts(array( 'tagname' => '', 'orderby' => '', 'key' => '', 'value' => '', 'exclude' => '' ), $atts)); ob_start(); include(locate_template( '/shortcorde/pazudora_template_list.php' )); $output = ob_get_clean(); return $output; } add_shortcode('pazudora_template_list', 'shortcode51'); //menu_list_format_pn(右サイドバーで使用中) function shortcode52($atts) { extract(shortcode_atts(array( 'menu_cat' => '', 'list_number' => '' ), $atts)); ob_start(); include(locate_template( '/shortcorde/menu_list_format_pn.php' )); $output = ob_get_clean(); return $output; } add_shortcode('menu_list_format_pn', 'shortcode52'); //menu_list_format_pl(左サイドバーで使用中【お知らせ】) function shortcode53($atts) { extract(shortcode_atts(array( 'menu_cat' => '', 'list_number' => '' ), $atts)); ob_start(); include(locate_template( '/shortcorde/menu_list_format_pl.php' )); $output = ob_get_clean(); return $output; } add_shortcode('menu_list_format_pl', 'shortcode53'); //左右2枠 タグ用 function shortcode54($atts) { extract(shortcode_atts(array( 'tagname' => '', 'page_no' => '' ), $atts)); ob_start(); include(locate_template( '/shortcorde/menu_paged_tag.php' )); $output = ob_get_clean(); return $output; } add_shortcode('menu_paged_tag', 'shortcode54'); //記事下 記事一覧 投稿タイプでフィルター function shortcode55($atts) { extract(shortcode_atts(array( 'menu_cat' => '', 'list_number' => '', 'post_type_name' => '' ), $atts)); ob_start(); include(locate_template( '/shortcorde/menu_list_format_post_type.php' )); $output = ob_get_clean(); return $output; } add_shortcode('menu_list_format_post_type', 'shortcode55'); //記事下 記事一覧 投稿タイプでフィルター(AMP) function shortcode56($atts) { extract(shortcode_atts(array( 'menu_cat' => '', 'list_number' => '', 'post_type_name' => '' ), $atts)); ob_start(); include(locate_template( '/shortcorde/menu_list_format_post_type_amp.php' )); $output = ob_get_clean(); return $output; } add_shortcode('menu_list_format_post_type_amp', 'shortcode56'); //カテゴリとタグのOR結合メニュー ナビ無し function shortcode57($atts) { extract(shortcode_atts(array( 'menu_cat_1' => '', 'menu_tag' => '', 'pagenumber' => '' ), $atts)); ob_start(); include(locate_template( '/shortcorde/menu_paged_cat_tag_n.php' )); $output = ob_get_clean(); return $output; } add_shortcode('menu_paged_cat_tag_n', 'shortcode57'); //カテゴリとタグのOR結合メニュー ナビ無し(AMP) function shortcode58($atts) { extract(shortcode_atts(array( 'menu_cat_1' => '', 'menu_tag' => '', 'pagenumber' => '' ), $atts)); ob_start(); include(locate_template( '/shortcorde/menu_paged_cat_tag_n_amp.php' )); $output = ob_get_clean(); return $output; } add_shortcode('menu_paged_cat_tag_n_amp', 'shortcode58'); //指定した数だけ大きい画像など(注目) function shortcode59($atts) { extract(shortcode_atts(array( 'notable_cat' => '', 'notable_tag' => '', 'notable_page' => '' ), $atts)); ob_start(); include(locate_template( '/shortcorde/notable_list.php' )); $output = ob_get_clean(); return $output; } add_shortcode('notable_list', 'shortcode59'); //カテゴリ+ゲームタイトルでの記事リスト 左右2枠 function shortcode60($atts) { extract(shortcode_atts(array( 'menu_cat' => '', 'game_title' => '', 'pagenumber' => '16' ), $atts)); ob_start(); include(locate_template( '/shortcorde/menu_paged_game_title.php' )); $output = ob_get_clean(); return $output; } add_shortcode('menu_paged_game_title', 'shortcode60'); //アーカイブページ コンテンツ下 記事一覧 function shortcode61($atts) { extract(shortcode_atts(array( 'post_type' => '', 'notable_page' => '' ), $atts)); ob_start(); include(locate_template( '/shortcorde/notable_1.php' )); $output = ob_get_clean(); return $output; } add_shortcode('notable_1', 'shortcode61'); //ビジネス記事一覧リスト function shortcode62($atts) { extract(shortcode_atts(array( 'list_number' => '', 'post_type_name' => 'business', // デフォルト値を設定 ), $atts)); ob_start(); include(locate_template( '/shortcorde/menu_list_format_post_type_n_business.php' )); $output = ob_get_clean(); return $output; } add_shortcode('menu_list_format_post_type_n_business', 'shortcode62'); //eスポーツ記事一覧リスト function shortcode63($atts) { extract(shortcode_atts(array( 'list_number' => '', 'post_type_name' => 'esports', // デフォルト値を設定 ), $atts)); ob_start(); include(locate_template( '/shortcorde/menu_list_format_post_type_n_esports.php' )); $output = ob_get_clean(); return $output; } add_shortcode('menu_list_format_post_type_n_esports', 'shortcode63'); //ドリームニュース function shortcode64() { ob_start(); get_template_part('/shortcorde/menu_paged_dreamnews'); return ob_get_clean(); } add_shortcode('menu_paged_dreamnews', 'shortcode64'); //PRワイヤー function shortcode65() { ob_start(); get_template_part('/shortcorde/menu_paged_prwire'); return ob_get_clean(); } add_shortcode('menu_paged_prwire', 'shortcode65'); //攻略タイトル記事リスト function shortcode66($atts) { extract(shortcode_atts(array( 'menu_title' => '', 'offsetno' => '' ), $atts)); ob_start(); include(locate_template( '/shortcorde/menu_paged_gametitle.php' )); $output = ob_get_clean(); return $output; } add_shortcode('menu_paged_gametitle', 'shortcode66'); //ヤスヒロ攻略コーナー function shortcode13() { ob_start(); get_template_part('/shortcorde/yasuhiro_menu'); return ob_get_clean(); } add_shortcode('yasuhiro_menu', 'shortcode13'); /* ショートコード設定ここまで */ /* Smart News */ add_action( 'do_feed_smartnews', 'do_feed_smartnews' ); function do_feed_smartnews() { $feed_template = get_template_directory() . '/smartnews.php'; load_template( $feed_template ); } /* Smart News test */ add_action( 'do_feed_smartnews_test', 'do_feed_smartnews_test' ); function do_feed_smartnews_test() { $feed_template = get_template_directory() . '/smartnews_test.php'; load_template( $feed_template ); } /* LINE News */ add_action( 'do_feed_linerss', 'do_feed_linerss' ); function do_feed_linerss() { $feed_template = get_template_directory() . '/linerss.php'; load_template( $feed_template ); } /* LINE News_test */ add_action( 'do_feed_linerss_test', 'do_feed_linerss_test' ); function do_feed_linerss_test() { $feed_template = get_template_directory() . '/linerss_test.php'; load_template( $feed_template ); } // RSSフィードから除くものを指定 ※カスタムフィールドによりRSS除外とするための設定 function exclude_tag_rss($query) { if ($query->is_feed) { $query->set('meta_query', array( array( 'key'=>'exclusion_from_wprss', 'compare' => 'NOT EXISTS' ), array( 'key'=>'exclusion_from_wprss', 'value'=>'1', 'compare'=>'!=' ), 'relation'=>'OR' ) ); } } add_filter('pre_get_posts', 'exclude_tag_rss'); // RSSの本文から不要な属性を削除 function feed_content_remove_class($content) { return preg_replace('/ (class|style|alt|itemprop)="(.*?)"/', '', $content); } add_filter('the_excerpt_rss', 'feed_content_remove_class'); add_filter('the_content_feed', 'feed_content_remove_class'); /* 画像キャプション使用時のHTMLタグ変更 */ add_shortcode('caption', 'my_img_caption_shortcode'); function my_img_caption_shortcode($attr, $content = null) { if ( ! isset( $attr['caption'] ) ) { if ( preg_match( '#((?:<a [^>]+>s*)?<img [^>]+>(?:s*</a>)?)(.*)#is', $content, $matches ) ) { $content = $matches[1]; $attr['caption'] = trim( $matches[2] ); } } $output = apply_filters('img_caption_shortcode', '', $attr, $content); if ( $output != '' ) return $output; extract(shortcode_atts(array( 'id' => '', 'align' => 'alignnone', 'width' => '', 'caption' => '' ), $attr, 'caption')); if ( 1 > (int) $width || empty($caption) ) return $content; if ( $id ) $id = 'id="' . esc_attr($id) . '" '; return '<p>' . do_shortcode( $content ) . '<aside class="wp-caption-text">▲' . $caption . '</aside></p>'; } /*画像キャプションを無効化する*/ add_filter( 'disable_captions', '__return_true' ); function my_gallery_default_type_set_link( $settings ) { $settings['galleryDefaults']['link'] = 'none'; $settings['galleryDefaults']['columns'] = '2'; $settings['galleryDefaults']['size'] = 'medium'; return $settings; } add_filter( 'media_view_settings', 'my_gallery_default_type_set_link'); /* 管理画面のメディア一覧: 月別フィルタ(年/月ドロップダウン) を無効化 * 目的: attachment の YEAR/MONTH DISTINCT 集計クエリを抑止して管理画面負荷を下げる * 影響: メディア一覧の月別絞り込みUIが消えるだけ。アップロードURLの /yyyy/mm/ 構造は変更されない。 */ // upload.php の一覧テーブル(WP_List_Table::months_dropdown)を完全に無効化(UI表示もクエリも止める) add_filter( 'disable_months_dropdown', function( $disable, $post_type ) { if ( 'attachment' === $post_type ) { return true; } return $disable; }, 10, 2 ); // 念のため: months_dropdown のDBクエリをショートサーキット(disable_months_dropdownが効かない環境向け) add_filter( 'pre_months_dropdown_query', function( $months, $post_type ) { if ( 'attachment' === $post_type ) { return array(); } return $months; }, 10, 2 ); // メディアモーダル(添付ファイル選択UI)側の月別フィルタ生成も停止 add_filter( 'media_library_months_with_files', '__return_empty_array' ); /* 管理画面のメディア一覧: 種別フィルタ(画像/動画/音声など)の生成を抑止 * 目的: get_available_post_mime_types() の DISTINCT post_mime_type クエリを抑止して負荷を下げる * 影響: upload.php の「すべてのメディア」ドロップダウン(種別絞り込み)が実質無効化されるだけ。 */ add_filter( 'get_available_post_mime_types', function( $mimes, $type ) { if ( is_admin() && 'attachment' === $type ) { return array(); // 抽出クエリ回避 } return $mimes; }, 10, 2 ); //空白のaltに記事タイトルを設定する function change_any_texts($text){ $img_post_title = get_the_title(); $replace = array( 'alt=""' => 'alt="'.$img_post_title.'"' ); $text = str_replace(array_keys($replace), $replace, $text); return $text; } add_filter('the_content', 'change_any_texts'); // Customize YouTube oEmbed Code - 遅延読み込みで最適化 function custom_youtube_oembed($code){ if(strpos($code, 'youtu.be') !== false || strpos($code, 'youtube.com') !== false){ // パラメータを追加して遅延読み込みを有効化 $html = preg_replace("@src=(['\"])?([^'\">\s]*)@", "src=$1$2&showinfo=0&rel=0&loading=lazy", $code); $html = preg_replace('/ width="\d+"/', '', $html); $html = preg_replace('/ height="\d+"/', '', $html); // loading="lazy"属性を追加(iframeが存在する場合) if (strpos($html, '<iframe') !== false) { $html = preg_replace('/<iframe/', '<iframe loading="lazy"', $html); } $html = '<div class="youtube">' . $html . '</div>'; return $html; } return $code; } add_filter('embed_handler_html', 'custom_youtube_oembed'); add_filter('embed_oembed_html', 'custom_youtube_oembed'); /* Public Post Previewの有効期限延長 */ add_filter( 'ppp_nonce_life', 'my_nonce_life' ); function my_nonce_life() { return 60 * 60 * 24 * 7;// 7 日間(秒×分×時間×日) } /* 表示オプションにカスタムフィールドを表示 */ // ACF側の「WP標準カスタムフィールドを消す」設定を有効化(標準UI削除の方針と整合性を取る) add_filter('acf/settings/remove_wp_meta_box', '__return_true'); //コメントが許可されているか function is_comment_open(){ global $post; if ( isset($post->comment_status) ) { return $post->comment_status == 'open'; } return false; } //はてぶ風ブログカード(リンクカード)生成 //サイトドメインを取得 function get_this_site_domain(){ //ドメイン情報を$results[1]に取得する preg_match( '/https?:\/\/(.+?)\//i', admin_url(), $results ); return $results[1]; } //本文抜粋を取得する関数(綺麗な抜粋文を作成するため) //使用方法:http://nelog.jp/get_the_custom_excerpt function get_the_custom_excerpt($content, $length) { $length = ($length ? $length : 70);//デフォルトの長さを指定する $content = preg_replace('/<!--more-->.+/is',"",$content); //moreタグ以降削除 $content = strip_shortcodes($content);//ショートコード削除 $content = strip_tags($content);//タグの除去 $content = str_replace(" ","",$content);//特殊文字の削除(今回はスペースのみ) $content = mb_substr($content,0,$length);//文字列を指定した長さで切り取る return $content; } //本文中のURLをブログカードタグに変更する function url_to_blog_card($the_content) { // キャッシュキーを生成(同じコンテンツの再処理を防ぐ) static $processed_content = array(); $content_hash = md5($the_content); if (isset($processed_content[$content_hash])) { return $processed_content[$content_hash]; } // 処理回数を制限(無限ループ防止) static $process_count = 0; if ($process_count > 10) { $processed_content[$content_hash] = $the_content; return $the_content; } $process_count++; if ( is_singular() ) {//投稿ページもしくは固定ページのとき //1行にURLのみが期待されている行(URL)を全て$mに取得 $res = preg_match_all('/^(<p>)?(<a.+?>)?https?:\/\/'.preg_quote(get_this_site_domain()).'\/[-_.!~*\'()a-zA-Z0-9;\/?:\@&=+\$,%#]+(<\/a>)?(<\/p>)?(<br ? \/>)?$/im', $the_content,$m); // マッチしたURLが多すぎる場合は処理をスキップ(パフォーマンス保護) if (count($m[0]) > 5) { $processed_content[$content_hash] = $the_content; return $the_content; } // 投稿IDのキャッシュ(同じリクエスト内での重複クエリを防ぐ) static $url_to_id_cache = array(); //マッチしたURL一つ一つをループしてカードを作成 foreach ($m[0] as $match) { $url = strip_tags($match);//URL // キャッシュから投稿IDを取得 if (!isset($url_to_id_cache[$url])) { $url_to_id_cache[$url] = url_to_postid( $url ); } $id = $url_to_id_cache[$url]; if ( !$id ) continue;//IDを取得できない場合はループを飛ばす // 投稿情報のキャッシュ static $post_cache = array(); if (!isset($post_cache[$id])) { $post_cache[$id] = get_post($id); } $post = $post_cache[$id]; if ( !$post ) continue; $title = $post->post_title;//タイトルの取得 $date = mysql2date('Y-m-d H:i', $post->post_date);//投稿日の取得 $excerpt = get_the_custom_excerpt($post->post_content, 90);//抜粋の取得 $thumbnail = get_the_post_thumbnail($id, 'thumb100', array('style' => 'width:100px;height:100px;', 'class' => 'blog-card-thumb-image'));//サムネイルの取得(要100×100のサムネイル設定) if ( !$thumbnail ) {//サムネイルが存在しない場合 $thumbnail = '<img src="'.get_template_directory_uri().'/images/no-image.png" style="width:100px;height:100px;" />'; } //取得した情報からブログカードのHTMLタグを作成 $tag = '<div class="blog-card"><div class="blog-card-thumbnail"><a href="'.$url.'" class="blog-card-thumbnail-link">'.$thumbnail.'</a></div><div class="blog-card-content"><div class="blog-card-title"><a href="'.$url.'" class="blog-card-title-link">'.$title.'</a></div><div class="blog-card-excerpt">'.$excerpt.'</div></div><div class="blog-card-footer clear"><span class="blog-card-date">'.$date.'</span></div></div>'; //本文中のURLをブログカードタグで置換 $the_content = preg_replace('{'.preg_quote($match).'}', $tag , $the_content, 1); } } // 処理結果をキャッシュ $processed_content[$content_hash] = $the_content; return $the_content;//置換後のコンテンツを返す } add_filter('the_content','url_to_blog_card');//本文表示をフック //oembed無効 add_filter( 'embed_oembed_discover', '__return_false' ); //Embeds remove_action( 'parse_query', 'wp_oembed_parse_query' ); remove_action( 'wp_head', 'wp_oembed_remove_discovery_links' ); remove_action( 'wp_head', 'wp_oembed_remove_host_js' ); //Wordpress4.5.3でポスト時に再び表示されるようになってしまったので対処 remove_filter( 'pre_oembed_result', 'wp_filter_pre_oembed_result'); //line rss function line_rss($content, $del_url) { //linerssの為の処理 $regexp = '/\<aside id=\"linerss\"\>[\s\S]*?\<\/aside\>/'; $content2 = preg_replace($regexp, '', $content); //特定のURLを削除(アフィリエイト、ストアへの誘導系) foreach($del_url as $key => $value) { if ($value) { $value2 = str_replace("/", "\/", $value); $regexp2 = '/\<h2\>.*\<\/h2\>\n\<p\>\<a href=\"' . $value2 . '.*\<\/a\>\<\/p\>/'; $content2 = preg_replace($regexp2, '', $content2); $regexp2 = '/\<a href=\"' . $value2 . '.*\<\/a\>/'; $content2 = preg_replace($regexp2, '', $content2); } } //lineurlで囲われたの以外 <a helfのタグを消す テキストは残す //一旦 lineurlのタグを特殊なものに置き換え $content2_2 = str_replace("<aside id=\"lineurl\"><a href=", "[lineurl]", $content2); $content2_3 = str_replace("</a></aside>", "[/lineurl]", $content2_2); //ダウンロード削除 $regexp5 = '/\<h2\>.*ダウンロード.*\<\/h2\>\n\<div[\s\S]*?\<\/ul\>\n\<\/div\>/'; $content2_4 = preg_replace($regexp5, '', $content2_3); //Aタグを 全て消してみる $regexp3 = '/\<a href=\".+\"\>/'; $content3 = preg_replace($regexp3, '', $content2_4); $regexp4 = '/\<\/a\>/'; $content4 = preg_replace($regexp4, '(※リンクは省略しています)', $content3); //lineurlのタグを戻す $content4_2 = str_replace("[lineurl]", "<a href=", $content4); $content4_3 = str_replace("[/lineurl]", "</a>", $content4_2); // echo $content4_3; return $content4_3; } // フッター用スクリプトを読み込み(最適化版) if ( ! is_admin() ) { function sqool_enqueue_footer_scripts() { wp_enqueue_script( 'sqool-footer-scripts', get_template_directory_uri() . '/js/footer-scripts.js', array(), // jQuery依存を削除 '1.0.1', // バージョン更新(最適化版) true // フッター読み込み ); // テーマディレクトリのURLをJavaScript変数として出力 wp_localize_script('sqool-footer-scripts', 'sqoolTheme', array( 'jsUrl' => get_template_directory_uri() . '/js/' )); } add_action('wp_enqueue_scripts', 'sqool_enqueue_footer_scripts', 20); // 非クリティカルなスクリプトにdefer属性を付与 function sqool_add_defer_to_scripts( $tag, $handle, $src ) { // 除外リスト(同期読み込みが必要なスクリプト) $excluded = array( 'jquery', 'jquery-core', 'jquery-migrate', 'comment-reply', 'clipboard.min.js' ); // navigation.jsはdeferで読み込む(メインスレッドのブロックを防止) if ( $handle === 'sqool-navigation' ) { return str_replace( ' src', ' defer src', $tag ); } // 除外リストに含まれていないスクリプトにdeferを追加 foreach ( $excluded as $exclude ) { if ( strpos( $handle, $exclude ) !== false || strpos( $src, $exclude ) !== false ) { return $tag; } } // defer属性を追加 return str_replace( ' src', ' defer src', $tag ); } add_filter( 'script_loader_tag', 'sqool_add_defer_to_scripts', 10, 3 ); } /////////////////////////////////////////////////////////////////////////////////////////////// //プレスリリースの掲載の通知系 /////////////////////////////////////////////////////////////////////////////////////////////// add_action( 'admin_init', 'pr_mail_init' ); function pr_mail_init() { $post_types = sqool_get_post_types(); //投稿ページ サイドバー add_meta_box( 'pr_mail_side_post', 'プレスリリースの掲載の通知', 'pr_mail_side', $post_types, 'side' ); //投稿ページ add_meta_box( 'pr_mail_post', 'プレスリリースの掲載の通知 メール入力', 'pr_mail', $post_types ); } //プレスリリースの掲載の通知 サイド function pr_mail_side( $param ) { global $wpdb; //データベースを触るためのおまじない global $post; echo '<div id="js-list-pr-mail"></div><br><input type="hidden" name="pr_mail_flg" id="pr_mail_flg" value="" /><button id="pr_mail_btn"> 送信 </button><BR>'; // テーブルが存在するかチェック(エラーを抑制してチェック) $table_name = $wpdb->prefix . 'mail_history'; $wpdb->suppress_errors( true ); $table_exists = $wpdb->get_var( $wpdb->prepare( "SHOW TABLES LIKE %s", $table_name ) ); $wpdb->suppress_errors( false ); if ( $table_exists ) { $get_data = $wpdb->get_results( $wpdb->prepare( "SELECT mail, send_date FROM {$wpdb->prefix}mail_history WHERE post_id = %d AND type = 0 ORDER BY send_date DESC LIMIT 3", $post->ID ) ); // エラーが発生した場合は無視(テーブルが存在しない場合など) if ( $wpdb->last_error ) { $wpdb->last_error = ''; // エラーをクリア } elseif ( $get_data ) { foreach ( $get_data as $d ) { echo "<BR><b>・" . esc_html( $d->mail ) . "</b><BR> (" . esc_html( $d->send_date ) . ")"; } } } } //プレスリリースの掲載の通知 function pr_mail( $param ) { //sqool用のグローバルデータ群 require("inc/global.php"); global $post; //メールの記事URLの部分を置き換える $pr_mail_txt2 = str_replace('<pr_mail_txt>', esc_url(get_permalink()), $pr_mail_txt); // $paramは投稿情報 echo '<input type="hidden" id="pr_mail_title" value="' . $pr_mail_title . '***' . $post->ID . '" />'; echo 'メールアドレス:<input type="text" id="pr_mail_email" size="40" value="" /><BR>'; echo '<textarea id="pr_mail_txt" rows="10" cols="120">' . $pr_mail_txt2 . '</textarea>'; } //プレスリリースの掲載のメール送るためのAJAX設定 function ajax_pr_mail_scripts($hook_suffix) { // 投稿編集画面(post.php/post-new.php)かつ対象投稿タイプのみ読み込む $screen = get_current_screen(); if (!$screen || !in_array($screen->base, ['post', 'post-new'], true)) return; if (!in_array($screen->post_type, sqool_get_post_types(), true)) return; $handle = 'pr_mail'; $file = get_template_directory_uri() . '/js/' . $handle . '.js'; wp_register_script( $handle, $file, array( 'jquery' ) ); $action = 'pr-mail-action'; wp_localize_script($handle, 'PR_MAIL_AJAX', [ 'api' => admin_url('admin-ajax.php'), 'action' => $action, 'nonce' => wp_create_nonce($action) ]); wp_enqueue_script($handle); } add_action('admin_enqueue_scripts', 'ajax_pr_mail_scripts'); //プレスリリースの掲載のメール送る コールバック function ajax_pr_mail_call () { //sqool用のグローバルデータ群 require("inc/global.php"); global $wpdb; //データベースを触るためのおまじない $action = 'pr-mail-action'; $data = ''; if(check_ajax_referer($action, 'nonce', false)) { if ($_SERVER['REQUEST_METHOD'] === 'POST') { $title_and_id = $_POST["pr_mail_title"]; $email = $_POST["pr_mail_email"]; $info = $_POST["pr_mail_info"]; $headers = []; $headers[] = 'From: ' . $pr_to_mail[0]; //タイトルと記事IDに分ける $title_and_id2 = explode("***",$title_and_id); $title = $title_and_id2[0]; $post_id = $title_and_id2[1]; //メール送信 wp_mail($email, $title, $info, $headers, ""); //DBに保存(テーブルが存在する場合のみ) $table_name = $wpdb->prefix . 'mail_history'; $wpdb->suppress_errors( true ); $table_exists = $wpdb->get_var( $wpdb->prepare( "SHOW TABLES LIKE %s", $table_name ) ); $wpdb->suppress_errors( false ); if ( $table_exists ) { $wpdb->insert( $wpdb->prefix . 'mail_history', array( 'post_id' => $post_id, 'mail' => $email, 'type' => 0 ), array( '%d', '%s', '%d' ) ); // エラーが発生した場合は無視 if ( $wpdb->last_error ) { $wpdb->last_error = ''; } } status_header('200'); $data = 'OK'; } } else { status_header('403'); $data = 'Forbidden'; } header('Content-Type: application/json; charset=UTF-8'); echo $data; die(); } add_action('wp_ajax_pr-mail-action', 'ajax_pr_mail_call'); add_action('wp_ajax_nopriv_pr-mail-action', 'ajax_pr_mail_call'); /////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////// //記事連携の通知系 /////////////////////////////////////////////////////////////////////////////////////////////// add_action('admin_init', 'link_mail_init'); function link_mail_init() { $post_types = sqool_get_post_types(); //投稿ページ サイドバー add_meta_box( 'link_mail_side_post', '記事連携の通知', 'link_mail_side', $post_types, 'side' ); //投稿ページ add_meta_box( 'link_mail_post', '記事連携の通知 メール入力', 'link_mail', $post_types ); } //記事連携の通知 サイド function link_mail_side( $param ) { global $wpdb; //データベースを触るためのおまじない global $post; echo '<div id="js-list-link-mail"></div><br><input type="hidden" name="link_mail_flg" id="link_mail_flg" value="" /><button id="link_mail_btn"> 送信 </button><BR>'; // テーブルが存在するかチェック(エラーを抑制してチェック) $table_name = $wpdb->prefix . 'mail_history'; $wpdb->suppress_errors( true ); $table_exists = $wpdb->get_var( $wpdb->prepare( "SHOW TABLES LIKE %s", $table_name ) ); $wpdb->suppress_errors( false ); if ( $table_exists ) { $get_data = $wpdb->get_results( $wpdb->prepare( "SELECT send_date FROM {$wpdb->prefix}mail_history WHERE post_id = %d AND type = 1 ORDER BY send_date DESC LIMIT 3", $post->ID ) ); // エラーが発生した場合は無視(テーブルが存在しない場合など) if ( $wpdb->last_error ) { $wpdb->last_error = ''; // エラーをクリア } elseif ( $get_data ) { foreach ( $get_data as $d ) { echo "<BR><b>・送信しました!</b><BR> (" . esc_html( $d->send_date ) . ")"; } } } } //記事連携の通知 function link_mail( $param ) { //sqool用のグローバルデータ群 require("inc/global.php"); global $post; //メールの記事URLの部分を置き換える $link_mail_txt2 = str_replace('<link_mail_txt>', esc_url(get_permalink()), $link_mail_txt); // $paramは投稿情報 echo '<input type="hidden" id="link_mail_title" value="' . $link_mail_title . '***' . $post->ID . '" />'; echo '<textarea id="link_mail_txt" rows="10" cols="120">' . $link_mail_txt2 . '</textarea>'; } //記事連携のメール送るためのAJAX設定 function ajax_link_mail_scripts($hook_suffix) { // 投稿編集画面(post.php/post-new.php)かつ対象投稿タイプのみ読み込む $screen = get_current_screen(); if (!$screen || !in_array($screen->base, ['post', 'post-new'], true)) return; if (!in_array($screen->post_type, sqool_get_post_types(), true)) return; $handle = 'link_mail'; $file = get_template_directory_uri() . '/js/' . $handle . '.js'; wp_register_script( $handle, $file, array( 'jquery' ) ); $action = 'link-mail-action'; wp_localize_script($handle, 'LINK_MAIL_AJAX', [ 'api' => admin_url('admin-ajax.php'), 'action' => $action, 'nonce' => wp_create_nonce($action) ]); wp_enqueue_script($handle); } add_action('admin_enqueue_scripts', 'ajax_link_mail_scripts'); //記事連携のメール送る コールバック function ajax_link_mail_call () { //sqool用のグローバルデータ群 require("inc/global.php"); global $wpdb; //データベースを触るためのおまじない $action = 'link-mail-action'; $data = ''; if(check_ajax_referer($action, 'nonce', false)) { if ($_SERVER['REQUEST_METHOD'] === 'POST') { $title_and_id = $_POST["link_mail_title"]; $info = $_POST["link_mail_info"]; $headers = []; $headers[] = 'From: ' . $pr_to_mail[1]; //タイトルと記事IDに分ける $title_and_id2 = explode("***",$title_and_id); $title = $title_and_id2[0]; $post_id = $title_and_id2[1]; //CCのメール分ループ for ($i=1; $i<count($link_to_mail); $i++) { $headers[] = 'cc: ' . $link_to_mail[$i] . '<' . $link_to_mail[$i] . '>'; } //メール送信 wp_mail($link_to_mail[0], $title, $info, $headers, ""); //DBに保存(テーブルが存在する場合のみ) $table_name = $wpdb->prefix . 'mail_history'; $wpdb->suppress_errors( true ); $table_exists = $wpdb->get_var( $wpdb->prepare( "SHOW TABLES LIKE %s", $table_name ) ); $wpdb->suppress_errors( false ); if ( $table_exists ) { $wpdb->insert( $wpdb->prefix . 'mail_history', array( 'post_id' => $post_id, 'mail' => $link_to_mail[0], 'type' => 1 ), array( '%d', '%s', '%d' ) ); // エラーが発生した場合は無視 if ( $wpdb->last_error ) { $wpdb->last_error = ''; } } status_header('200'); $data = 'OK'; } } else { status_header('403'); $data = 'Forbidden'; } header('Content-Type: application/json; charset=UTF-8'); echo $data; die(); } add_action('wp_ajax_link-mail-action', 'ajax_link_mail_call'); add_action('wp_ajax_nopriv_link-mail-action', 'ajax_link_mail_call'); /////////////////////////////////////////////////////////////////////////////////////////////// // ショートコード用テンプレート読み込み共通関数 function sqool_load_shortcode_template( $template_path ) { $full_path = get_template_directory() . '/' . ltrim( $template_path, '/' ); if ( file_exists( $full_path ) ) { ob_start(); include( $full_path ); return ob_get_clean(); } return ''; } // 広告関連のショートコード function shortcode_sp_article_middle() { return sqool_load_shortcode_template( '/shortcorde/ads/sp/article_middle.php' ); } function shortcode_sp_article_under() { return sqool_load_shortcode_template( '/shortcorde/ads/sp/article_under.php' ); } function shortcode_pc_article_under() { return sqool_load_shortcode_template( '/shortcorde/ads/pc/article_under.php' ); } function shortcode_pc_more() { return sqool_load_shortcode_template( '/shortcorde/ads/pc/more.php' ); } // LINE関連のショートコード関数 function shortcode_line_rss() { return sqool_load_shortcode_template( '/shortcorde/line/rss.php' ); } // メール送信機能の改善 function send_notification_email($to, $subject, $message, $headers = array(), $attachments = array()) { if (!is_email($to)) { return new WP_Error('invalid_email', '無効なメールアドレスです'); } $default_headers = array( 'Content-Type: text/html; charset=UTF-8', 'From: ' . get_bloginfo('name') . ' <' . get_option('admin_email') . '>' ); $headers = wp_parse_args($headers, $default_headers); return wp_mail($to, $subject, $message, $headers, $attachments); } // メール履歴の保存 function save_mail_history($post_id, $email, $type) { global $wpdb; if (!is_numeric($post_id) || !is_email($email) || !is_numeric($type)) { return false; } $table_name = $wpdb->prefix . 'mail_history'; // テーブルが存在するかチェック $wpdb->suppress_errors( true ); $table_exists = $wpdb->get_var( $wpdb->prepare( "SHOW TABLES LIKE %s", $table_name ) ); $wpdb->suppress_errors( false ); if ( ! $table_exists ) { return false; } $data = array( 'post_id' => $post_id, 'mail' => sanitize_email($email), 'type' => $type, 'send_date' => current_time('mysql') ); $format = array('%d', '%s', '%d', '%s'); $result = $wpdb->insert($table_name, $data, $format); // エラーが発生した場合は無視 if ( $wpdb->last_error ) { $wpdb->last_error = ''; return false; } return $result; } // メール送信のAJAXハンドラー function handle_mail_notification() { check_ajax_referer('mail-notification', 'nonce'); if (!current_user_can('edit_posts')) { wp_send_json_error('権限がありません'); } $post_id = isset($_POST['post_id']) ? intval($_POST['post_id']) : 0; $email = isset($_POST['email']) ? sanitize_email($_POST['email']) : ''; $type = isset($_POST['type']) ? intval($_POST['type']) : 0; $message = isset($_POST['message']) ? wp_kses_post($_POST['message']) : ''; if (!$post_id || !$email || !$message) { wp_send_json_error('必要な情報が不足しています'); } $result = send_notification_email($email, get_the_title($post_id), $message); if (is_wp_error($result)) { wp_send_json_error($result->get_error_message()); } save_mail_history($post_id, $email, $type); wp_send_json_success('メールを送信しました'); } add_action('wp_ajax_mail-notification', 'handle_mail_notification'); // ショートコードの登録を整理 function register_shortcodes() { // 広告関連のショートコード add_shortcode('sp_article_middle', 'shortcode_sp_article_middle'); add_shortcode('sp_article_under', 'shortcode_sp_article_under'); add_shortcode('pc_article_under', 'shortcode_pc_article_under'); add_shortcode('pc_more', 'shortcode_pc_more'); // LINE関連のショートコード add_shortcode('line_rss', 'shortcode_line_rss'); // その他のショートコード add_shortcode('monst_articles', 'shortcode_monst_articles'); } add_action('init', 'register_shortcodes'); // モンスト記事一覧のショートコード function shortcode_monst_articles() { $post_type_name = 'post'; $menu_cat = 96; $list_number = 10; $paged = get_query_var('paged') ? get_query_var('paged') : 1; $args = array( 'post_type' => $post_type_name, 'cat' => $menu_cat, 'posts_per_page' => $list_number, 'paged' => $paged, 'orderby' => 'modified' ); ob_start(); include(dirname(__FILE__) . '/shortcorde/menu_list_format_post_type_n.php'); return ob_get_clean(); } // [pc_right_1st] ショートコード function shortcode_pc_right_1st() { ob_start(); ?> <script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-9466219394364041" crossorigin="anonymous"></script> <!-- SQOOL.NET PC 右メニュー上 --> <ins class="adsbygoogle" style="display:inline-block;width:300px;height:250px" data-ad-client="ca-pub-9466219394364041" data-ad-slot="6165067396"></ins> <script> (adsbygoogle = window.adsbygoogle || []).push({}); </script> <?php return ob_get_clean(); } add_shortcode('pc_right_1st', 'shortcode_pc_right_1st'); //記事中Adsショートコード読み込み require_once get_template_directory() . '/shortcorde/ads/sp/article_middle.php'; require_once get_template_directory() . '/shortcorde/ads/sp/article_under.php'; require_once get_template_directory() . '/shortcorde/ads/pc/article_under.php'; require_once get_template_directory() . '/shortcorde/ads/pc/more.php'; require_once get_template_directory() . '/shortcorde/line/rss.php'; // [more_short] ショートコード定義 function sqool_more_short_shortcode($atts, $content = null) { if (wp_is_mobile()) { return do_shortcode('[more_sp_code]'); } else { return do_shortcode('[more_pc_code]'); } } add_shortcode('more_short', 'sqool_more_short_shortcode'); // [article_under_ad] ショートコード定義(デバイス判定でフル版を表示) function sqool_article_under_ad_shortcode($atts, $content = null) { if (wp_is_mobile()) { return do_shortcode('[article_under_ad_sp_code]'); } else { return do_shortcode('[article_under_ad_pc]'); } } add_shortcode('article_under_ad', 'sqool_article_under_ad_shortcode'); // [article_under_ad_short] ショートコード定義(デバイス判定でショート版を表示) function sqool_article_under_ad_short_shortcode($atts, $content = null) { if (wp_is_mobile()) { return do_shortcode('[article_under_ad_sp_s]'); } else { return do_shortcode('[article_under_ad_pc_s]'); } } add_shortcode('article_under_ad_short', 'sqool_article_under_ad_short_shortcode'); // タグリストのショートコード require_once get_template_directory() . '/shortcorde/use_taglist_in_top.php'; /* ---------------------------------------------------- * Lotus RSS: チェックボックス * ---------------------------------------------------- */ function sqool_add_lotus_export_checkbox() { $post_types = sqool_get_post_types(); foreach ( $post_types as $pt ) { add_meta_box( 'sqool_lotus_rss_box', 'Lotus RSS 連携', 'sqool_lotus_rss_box_html', $pt, 'side', 'default' ); } } add_action( 'add_meta_boxes', 'sqool_add_lotus_export_checkbox' ); function sqool_lotus_rss_box_html( $post ) { $value = get_post_meta( $post->ID, 'lotus_rss', true ); wp_nonce_field( 'sqool_lotus_rss_nonce', 'sqool_lotus_rss_nonce_field' ); ?> <p> <label> <input type="checkbox" name="lotus_rss" value="1" <?php checked( $value, '1' ); ?> /> この記事を Lotus RSS に含める </label> </p> <?php } function sqool_save_lotus_rss_meta( $post_id ) { if ( ! isset( $_POST['sqool_lotus_rss_nonce_field'] ) || ! wp_verify_nonce( $_POST['sqool_lotus_rss_nonce_field'], 'sqool_lotus_rss_nonce' ) ) return; if ( defined('DOING_AUTOSAVE') && DOING_AUTOSAVE ) return; if ( isset($_POST['lotus_rss']) && $_POST['lotus_rss'] === '1' ) { update_post_meta( $post_id, 'lotus_rss', '1' ); } else { delete_post_meta( $post_id, 'lotus_rss' ); } } add_action( 'save_post', 'sqool_save_lotus_rss_meta' ); /* ---------------------------------------------------- * Lotus RSS /feed/lotus/ * ---------------------------------------------------- */ function sqool_register_lotus_feed() { add_feed( 'lotus', 'sqool_load_lotus_feed_template' ); } add_action( 'init', 'sqool_register_lotus_feed' ); function sqool_load_lotus_feed_template() { $template = locate_template( 'feed-lotus.php' ); if ( $template ) { load_template( $template ); } else { load_template( ABSPATH . WPINC . '/feed-rss2.php' ); } } // Lotus RSS フィードのクエリを制御(lotus_rss=1 の記事のみ) add_action( 'pre_get_posts', function( $query ) { if ( ! is_admin() && $query->is_main_query() && is_feed( 'lotus' ) ) { $query->set( 'meta_key', 'lotus_rss' ); $query->set( 'meta_value', '1' ); $query->set( 'post_type', sqool_get_post_types() ); } } ); /* ---------------------------------------------------- * 自動アイキャッチ画像設定(Auto Featured Image代替) * 投稿保存時に、本文の最初の画像を自動的にアイキャッチ画像に設定 * 再帰ガード付き(名前付き関数+処理中だけ一時的にremove/add) * ---------------------------------------------------- */ function sqool_auto_set_featured_image($post_id, $post, $update) { // 再帰ガード: 処理中フラグをチェック static $processing = false; if ($processing) return; // 1) 自動保存・リビジョン・権限チェック if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) return; if (wp_is_post_revision($post_id)) return; if (!current_user_can('edit_post', $post_id)) return; // 2) 許可された投稿タイプのみ処理 $allowed_post_types = sqool_get_post_types(); if (!in_array($post->post_type, $allowed_post_types, true)) return; // 3) 既にアイキャッチ画像が設定されている場合はスキップ if (has_post_thumbnail($post_id)) return; // 4) コンテンツが必要 $content = $post->post_content ?? ''; if ($content === '') return; // 再帰ガード: 処理開始 $processing = true; // 処理中は一時的にsave_postフックを外す(再帰防止) remove_action('save_post', 'sqool_auto_set_featured_image', 10); $attachment_id = 0; $found_img_tag = false; // 5) まず、wp-image-123 のようなクラスからIDを高速取得(最優先) if (preg_match('/wp-image-(\d+)/', $content, $m_id)) { $maybe_id = (int)$m_id[1]; if ($maybe_id > 0 && get_post($maybe_id)) { $attachment_id = $maybe_id; $found_img_tag = true; } } // 6) 次に、コンテンツから最初の画像URLを抽出して解決 if (!$attachment_id && preg_match('/<img[^>]+src=["\']([^"\']+)["\']/i', $content, $m)) { $found_img_tag = true; $img_url = $m[1]; // URLの正規化(クエリ文字列を削除: ?ver=... や ?resize=... など) $img_url = preg_replace('/\?.*$/', '', $img_url); // URLからアタッチメントIDを取得 $attachment_id = (int) attachment_url_to_postid($img_url); if (!$attachment_id) { // リサイズされた画像URL(例: image-300x200.jpg)から元の画像を解決 $attachment_id = sqool_try_resolve_attachment_id_from_resized_url($img_url); } // 画像タグはあるが添付IDに解決できない(外部画像等)場合は、誤設定を避けるため何もしない if (!$attachment_id) { add_action('save_post', 'sqool_auto_set_featured_image', 10, 3); $processing = false; return; } } // 7) 記事内に画像タグが無い場合のみ、デフォルト画像(OGP)を設定 if (!$attachment_id && !$found_img_tag) { $attachment_id = sqool_get_default_og_image_id(); if (!$attachment_id) { add_action('save_post', 'sqool_auto_set_featured_image', 10, 3); $processing = false; return; } } // 8) アイキャッチ画像を設定 if ($attachment_id > 0) { set_post_thumbnail($post_id, $attachment_id); } // 再帰ガード: 処理終了(フックを戻す) add_action('save_post', 'sqool_auto_set_featured_image', 10, 3); $processing = false; } add_action('save_post', 'sqool_auto_set_featured_image', 10, 3); /** * デフォルトOGP画像のアタッチメントIDを取得(キャッシュ付き) * メディアライブラリから「og-image.jpg」を検索 * 見つからない場合は0を返す */ function sqool_get_default_og_image_id(): int { // staticでメモ化(同一リクエスト内での再実行を防止) static $cached_id = null; if ($cached_id !== null) { return $cached_id; } // オプションからキャッシュを取得(DB検索を回避) $cached_id = get_option('sqool_default_og_image_id', false); if ($cached_id !== false) { $cached_id = (int)$cached_id; // キャッシュされたIDが有効か確認 if ($cached_id > 0 && get_post($cached_id)) { return $cached_id; } // 無効な場合はキャッシュをクリア delete_option('sqool_default_og_image_id'); $cached_id = null; } // まず、テーマ内のデフォルト画像URLから試行(メディアライブラリにアップロード済みの場合) $default_og_image_url = get_template_directory_uri() . '/images/og-image.jpg'; $attachment_id = attachment_url_to_postid($default_og_image_url); if ($attachment_id) { $cached_id = (int)$attachment_id; update_option('sqool_default_og_image_id', $cached_id); return $cached_id; } // メディアライブラリからファイル名で検索(postmetaの_wp_attached_fileを使用してより正確に) global $wpdb; $filename = 'og-image.jpg'; // _wp_attached_fileメタデータで検索(guidより正確) $attachment = $wpdb->get_var($wpdb->prepare( "SELECT p.ID FROM {$wpdb->posts} p INNER JOIN {$wpdb->postmeta} pm ON p.ID = pm.post_id WHERE p.post_type = 'attachment' AND p.post_mime_type LIKE 'image%%' AND pm.meta_key = '_wp_attached_file' AND pm.meta_value LIKE %s LIMIT 1", '%' . $wpdb->esc_like($filename) . '%' )); $cached_id = $attachment ? (int)$attachment : 0; // 見つかった場合はキャッシュに保存 if ($cached_id > 0) { update_option('sqool_default_og_image_id', $cached_id); } return $cached_id; } /** * リサイズされた画像URLからアタッチメントIDを解決 * 例: image-300x200.jpg -> image.jpg */ function sqool_try_resolve_attachment_id_from_resized_url(string $img_url): int { $path = wp_parse_url($img_url, PHP_URL_PATH); if (!$path) return 0; $filename = basename($path); // 拡張子の前に -300x200 のようなパターンを削除 $original = preg_replace('/-\d+x\d+(?=\.\w+$)/', '', $filename); if ($original === $filename) return 0; // 元のファイル名でURLを再構築 $base = preg_replace('/' . preg_quote($filename, '/') . '$/', $original, $img_url); $id = attachment_url_to_postid($base); return $id ? (int)$id : 0; } /* ---------------------------------------------------- * カスタムフィールドUIの無効化(パフォーマンス改善) * WordPress標準の「カスタムフィールド」メタボックス(postcustom)を無効化 * postmeta自体は残るので、ACFやテーマ/プラグインのメタはそのまま動く * ---------------------------------------------------- */ add_action('add_meta_boxes', function () { // すべての投稿タイプに対してカスタムフィールドUIを無効化 $post_types = sqool_get_post_types(); foreach ($post_types as $post_type) { remove_meta_box('postcustom', $post_type, 'normal'); } }, 999); // 優先度999で、他のメタボックス追加後に実行 /* ---------------------------------------------------- * FeedWordPressプラグインのunserializeエラー修正 * プラグインの関数を上書きして、安全なmaybe_unserialize()を使用 * ---------------------------------------------------- */ if ( function_exists('is_syndicated') ) { /** * 安全なunserialize処理(エラーを完全に抑制) * 壊れたシリアライズデータでもエラーを出さずにfalseを返す * 配列を期待する場合に使用 */ if ( ! function_exists('sqool_safe_maybe_unserialize') ) { function sqool_safe_maybe_unserialize( $data ) { // 既に配列の場合はそのまま返す if ( is_array( $data ) ) { return $data; } // nullやfalse、空文字列の場合はfalseを返す if ( empty( $data ) || ! is_string( $data ) ) { return false; } // シリアライズされていない場合はfalseを返す if ( ! function_exists( 'is_serialized' ) || ! is_serialized( $data ) ) { return false; } // エラーハンドラーを一時的に設定して、unserialize()のエラーを完全にキャッチ // 他のエラーは触らない(最小構成でunserialize警告だけ握る) $previous_error_handler = set_error_handler( function( $errno, $errstr, $errfile, $errline ) use ( &$previous_error_handler ) { // unserialize()関連のエラーのみをキャッチ(再発耐性を上げるため、Error at offsetに限定せずunserialize()全般に対応) if ( ( $errno === E_WARNING || $errno === E_NOTICE ) && strpos( $errstr, 'unserialize()' ) !== false ) { return true; // unserialize()関連のエラーを抑制 } // それ以外のエラーは元のハンドラーに渡す(触らない) if ( $previous_error_handler !== null ) { return call_user_func( $previous_error_handler, $errno, $errstr, $errfile, $errline ); } // ハンドラーがない場合はデフォルト動作に任せる return false; }, E_WARNING | E_NOTICE ); // unserializeを実行(エラーハンドラーが警告を抑制する) // @演算子は使わず、エラーハンドラーに完全に任せる(根本解決) $result = maybe_unserialize( $data ); // エラーハンドラーを復元(確実に元に戻す) if ( $previous_error_handler !== null ) { restore_error_handler(); } else { // ハンドラーが設定されなかった場合は何もしない restore_error_handler(); } // 結果が配列でない場合はfalseを返す if ( ! is_array( $result ) ) { return false; } return $result; } } // sqool_safe_unserialize() はコメント添付セクションで定義済み(FeedWordPressブロック外) // add_boilerplate_simple() 関数を安全なバージョンで上書き if ( ! function_exists('add_boilerplate_simple_safe') ) { function add_boilerplate_simple_safe ($element, $title, $id = NULL) { // 早期リターン: シンジケートされていない記事は処理しない if (!$id || !is_syndicated($id)) { return $title; } // キャッシュキーを生成(同じ投稿IDとelementの組み合わせでキャッシュ) static $result_cache = array(); $cache_key = $id . '_' . $element; // キャッシュに失敗フラグがある場合は早期リターン(破損データの再処理を避ける) if (isset($result_cache[$cache_key]) && $result_cache[$cache_key] === false) { return $title; } // キャッシュに結果がある場合はそれを返す if (isset($result_cache[$cache_key])) { return $result_cache[$cache_key]; } // メタデータの取得とunserialize処理をキャッシュ static $meta_cache = array(); if (!isset($meta_cache[$id])) { $meta = get_feed_meta('boilerplate rules', $id); // メタデータが存在し、配列でない場合は安全にunserializeを試行 if ( $meta && ! is_array( $meta ) ) { $meta = sqool_safe_maybe_unserialize( $meta ); // 失敗した場合はfalseを設定 if ( ! is_array( $meta ) ) { $meta = false; } } elseif ( ! $meta ) { $meta = false; } // メタデータをキャッシュ(falseもキャッシュして再処理を避ける) $meta_cache[$id] = $meta; // 壊れたデータを検出した場合は、データベースからも削除(根本解決) if ( $meta === false && function_exists( 'get_feed_meta' ) ) { $raw_meta = get_feed_meta('boilerplate rules', $id); // シリアライズデータだが、unserializeに失敗した場合 if ( $raw_meta && is_string( $raw_meta ) && function_exists( 'is_serialized' ) && is_serialized( $raw_meta ) ) { // 安全なunserializeを使用(エラーを抑制してunserializeを試行) $test_unserialize = sqool_safe_unserialize( $raw_meta ); // 失敗した場合(壊れたデータ)は、メタデータを削除 if ( $test_unserialize === false && $raw_meta !== serialize( false ) ) { // データベースから壊れたメタデータを削除(根本解決) // get_feed_meta() は get_post_meta() 経由なので、直接削除はしない // 代わりに、キャッシュに false を保存して再処理を避ける } } } } else { $meta = $meta_cache[$id]; } // メタデータが無効な場合はグローバルオプションを取得 if ( ! is_array( $meta ) || empty( $meta ) ) { // グローバルオプションもキャッシュ static $global_meta_cache = null; static $global_meta_checked = false; if ( $global_meta_cache === null ) { $global_meta_value = get_option( 'feedwordpress_boilerplate', false ); // グローバルオプションも安全にunserializeを試行 if ( $global_meta_value && ! is_array( $global_meta_value ) ) { $original_value = $global_meta_value; $global_meta_value = sqool_safe_maybe_unserialize( $global_meta_value ); // 壊れたデータを検出した場合、データベースから削除(根本解決) if ( ! is_array( $global_meta_value ) && ! $global_meta_checked ) { $global_meta_checked = true; // シリアライズデータだが、unserializeに失敗した場合 if ( is_string( $original_value ) && function_exists( 'is_serialized' ) && is_serialized( $original_value ) ) { // 安全なunserializeを使用(エラーを抑制してunserializeを試行) $test_unserialize = sqool_safe_unserialize( $original_value ); // 失敗した場合(壊れたデータ)は、オプションを削除して根本解決 if ( $test_unserialize === false && $original_value !== serialize( false ) ) { // 壊れたデータをデータベースから削除 delete_option( 'feedwordpress_boilerplate' ); // ログに記録(デバッグ用、本番環境ではコメントアウト推奨) // error_log( 'SQOOL: 壊れたfeedwordpress_boilerplateオプションを削除しました' ); } } } if ( ! is_array( $global_meta_value ) ) { $global_meta_value = false; } } $global_meta_cache = $global_meta_value; } $meta = $global_meta_cache; } $result = $title; if (is_array($meta) and !empty($meta)) : foreach ($meta as $rule) : if ($element==$rule['element']) : // add_boilerplate_reformat関数の存在チェックを追加 if (function_exists('add_boilerplate_reformat')) { $rule['template'] = add_boilerplate_reformat($rule['template'], $element, $id); } if ('before'==$rule['placement']) : $result = $rule['template'] . ' ' . $result; else : $result = $result . ' ' . $rule['template']; endif; endif; endforeach; endif; // 結果をキャッシュ(変更がない場合もキャッシュして再処理を避ける) $result_cache[$cache_key] = $result; return $result; } } // add_boilerplate_content() 関数を安全なバージョンで上書き if ( ! function_exists('add_boilerplate_content_safe') ) { function add_boilerplate_content_safe ($content) { // 早期リターン: シンジケートされていない記事は処理しない if (!is_syndicated()) { return $content; } // コンテンツハッシュベースのキャッシュ(同じコンテンツの再処理を防ぐ) static $content_cache = array(); $content_hash = md5($content); // キャッシュに失敗フラグがある場合は早期リターン(破損データの再処理を避ける) if (isset($content_cache[$content_hash]) && $content_cache[$content_hash] === false) { return $content; } // キャッシュに結果がある場合はそれを返す if (isset($content_cache[$content_hash])) { return $content_cache[$content_hash]; } // メタデータの取得とunserialize処理をキャッシュ(グローバルキャッシュ) static $global_content_meta_cache = null; if ($global_content_meta_cache === null) { $meta = get_feed_meta('boilerplate rules'); // メタデータが存在し、配列でない場合は安全にunserializeを試行 if ( $meta && ! is_array( $meta ) ) { $meta = sqool_safe_maybe_unserialize( $meta ); // 失敗した場合はfalseを設定 if ( ! is_array( $meta ) ) { $meta = false; } } elseif ( ! $meta ) { $meta = false; } // メタデータが無効な場合はグローバルオプションを取得 if ( ! is_array( $meta ) || empty( $meta ) ) { $global_meta_value = get_option( 'feedwordpress_boilerplate', false ); // グローバルオプションも安全にunserializeを試行 if ( $global_meta_value && ! is_array( $global_meta_value ) ) { $global_meta_value = sqool_safe_maybe_unserialize( $global_meta_value ); if ( ! is_array( $global_meta_value ) ) { $global_meta_value = false; } } $meta = $global_meta_value; } // メタデータをキャッシュ(falseもキャッシュして再処理を避ける) $global_content_meta_cache = $meta; } else { $meta = $global_content_meta_cache; } $result = $content; if (is_array($meta) and !empty($meta)) : foreach ($meta as $rule) : if ('post'==$rule['element']) : // add_boilerplate_reformat関数の存在チェックを追加 if (function_exists('add_boilerplate_reformat')) { $rule['template'] = add_boilerplate_reformat($rule['template'], 'post'); } if ('before'==$rule['placement']) : $result = $rule['template'] . "\n" . $result; else : $result = $result . "\n" . $rule['template']; endif; endif; endforeach; endif; // 結果をキャッシュ(変更がない場合もキャッシュして再処理を避ける) $content_cache[$content_hash] = $result; return $result; } } // プラグインの関数を上書き(プラグインが読み込まれた後に実行) // initアクションで実行(プラグインのフィルター追加後に確実に実行される) add_action('init', function() { // プラグインの関数が存在する場合のみ処理 if ( ! function_exists('add_boilerplate_simple') || ! function_exists('is_syndicated') ) { return; } // 一度だけ実行するように静的変数を使用(重要:504エラー対策) static $already_processed = false; if ( $already_processed ) { return; } $already_processed = true; // 元の関数を削除して、安全なバージョンに置き換え $hookOrder = get_option('feedwordpress_boilerplate_hook_order', 10); // 元のフィルターを削除(複数の優先度を試行) remove_filter('the_title', 'add_boilerplate_title', $hookOrder); remove_filter('get_the_excerpt', 'add_boilerplate_excerpt', $hookOrder); remove_filter('the_content', 'add_boilerplate_content', $hookOrder); remove_filter('the_content_rss', 'add_boilerplate_content', $hookOrder); // デフォルト優先度でも削除を試行(プラグインの設定が異なる場合に備える) remove_filter('the_title', 'add_boilerplate_title', 10); remove_filter('get_the_excerpt', 'add_boilerplate_excerpt', 10); remove_filter('the_content', 'add_boilerplate_content', 10); remove_filter('the_content_rss', 'add_boilerplate_content', 10); // 安全なバージョンを追加 add_filter('the_title', function($title, $id = NULL) { return add_boilerplate_simple_safe('title', $title, $id); }, $hookOrder, 2); add_filter('get_the_excerpt', function($title, $id = NULL) { return add_boilerplate_simple_safe('excerpt', $title, $id); }, $hookOrder, 1); add_filter('the_content', 'add_boilerplate_content_safe', $hookOrder, 1); add_filter('the_content_rss', 'add_boilerplate_content_safe', $hookOrder, 1); }, 20); // 優先度20で、プラグインの初期化後に実行 } /** * Custom Post Type Permalinks - pluginless implementation * 旧 Custom Post Type Permalinks プラグインの設定を functions.php で再現 * * 方針: * - 日付ベース(news / dreamnews / prwire / businessnews)は「固定スラッグ + 日付+ID」で解決する * 例: /news/archive/20251219-535416.html * - 旧実装のように「スラッグ用プレースホルダ」を name にマッピングしない(これが404の主因) * - postnameベースは「固定スラッグ + post_name」で解決する */ function sqool_set_custom_post_type_permalinks() { global $wp_rewrite; // 日付ベースの構造(※フルパスで固定) $date_based_post_types = array( 'news' => '/news/archive/%year%%monthnum%%day%-%post_id%.html', 'dreamnews' => '/news/dreamnews/archive/%year%%monthnum%%day%-%post_id%.html', 'prwire' => '/news/prwire/archive/%year%%monthnum%%day%-%post_id%.html', 'businessnews' => '/business/news/archive/%year%%monthnum%%day%-%post_id%.html', ); // 投稿名ベースの構造(※各CPTのrewrite[slug]に従う) $postname_based_post_types = array( 'column' => '/%postname%.html', 'esports' => '/%postname%.html', 'business' => '/%postname%.html', 'robot' => '/%postname%.html', 'blog' => '/%postname%.html', 'travel' => '/%postname%.html', 'review' => '/%postname%.html', 'report' => '/%postname%.html', 'notice' => '/%postname%.html', 'link' => '/%postname%.html', 'special' => '/%postname%.html', 'premium' => '/%postname%.html', ); // ----------------------------- // 日付ベース: ルール(解決は post_id で行う) // ----------------------------- foreach ( $date_based_post_types as $post_type => $permastruct ) { if ( ! post_type_exists( $post_type ) ) { continue; } $pt_object = get_post_type_object( $post_type ); if ( ! $pt_object || false === $pt_object->rewrite ) { continue; } // permastruct を登録(生成用) $wp_rewrite->add_permastruct( $post_type, $permastruct, array( 'with_front' => false ) ); // 解決用: 明示的に rewrite_rule を追加(name を使わず p=ID で確定) // yyyymmdd-id.html をパースして ID を取り出す switch ( $post_type ) { case 'news': add_rewrite_rule( '^news/archive/([0-9]{4})([0-9]{2})([0-9]{2})-([0-9]+)\\.html$', 'index.php?post_type=news&p=$4', 'top' ); break; case 'dreamnews': add_rewrite_rule( '^news/dreamnews/archive/([0-9]{4})([0-9]{2})([0-9]{2})-([0-9]+)\\.html$', 'index.php?post_type=dreamnews&p=$4', 'top' ); break; case 'prwire': add_rewrite_rule( '^news/prwire/archive/([0-9]{4})([0-9]{2})([0-9]{2})-([0-9]+)\\.html$', 'index.php?post_type=prwire&p=$4', 'top' ); break; case 'businessnews': add_rewrite_rule( '^business/news/archive/([0-9]{4})([0-9]{2})([0-9]{2})-([0-9]+)\\.html$', 'index.php?post_type=businessnews&p=$4', 'top' ); break; } } // ----------------------------- // 投稿名ベース: permastruct(生成は post_name、解決は WP の通常動作に任せる) // ----------------------------- foreach ( $postname_based_post_types as $post_type => $structure ) { if ( ! post_type_exists( $post_type ) ) { continue; } $pt_object = get_post_type_object( $post_type ); if ( ! $pt_object || false === $pt_object->rewrite ) { continue; } $slug = isset( $pt_object->rewrite['slug'] ) ? $pt_object->rewrite['slug'] : ''; $slug = trim( (string) $slug, '/' ); if ( $slug === '' ) { continue; } // %postname% を %post_type% に置き換え $permalink = '/' . $slug . $structure; $permalink = str_replace( '%postname%', '%' . $post_type . '%', $permalink ); // 投稿タイプのプレースホルダーを登録(name 解決) add_rewrite_tag( '%' . $post_type . '%', '([^/]+)', 'post_type=' . $post_type . '&name=' ); $wp_rewrite->add_permastruct( $post_type, $permalink, array( 'with_front' => false ) ); } // hints-and-tips: カスタムタクソノミー %game-title% を含む構造(既存ロジック維持、ただしslugプレースホルダは使わない) if ( post_type_exists( 'hints-and-tips' ) ) { $pt_object = get_post_type_object( 'hints-and-tips' ); if ( $pt_object && false !== $pt_object->rewrite ) { $slug = isset( $pt_object->rewrite['slug'] ) ? trim( (string) $pt_object->rewrite['slug'], '/' ) : ''; if ( $slug ) { $permalink = '/' . $slug . '/%game-title%/%hints-and-tips%.html'; add_rewrite_tag( '%hints-and-tips%', '([^/]+)', 'post_type=hints-and-tips&name=' ); add_rewrite_tag( '%game-title%', '([^/]+)', 'game-title=' ); $wp_rewrite->add_permastruct( 'hints-and-tips', $permalink, array( 'with_front' => false ) ); } } } } add_action( 'init', 'sqool_set_custom_post_type_permalinks', 20 ); // パーマリンク生成時にプレースホルダーを置換 function sqool_custom_post_type_permalink( $post_link, $post, $leavename ) { global $wp_rewrite; if ( ! $wp_rewrite->using_permalinks() ) { return $post_link; } $post_type = $post->post_type; $pt_object = get_post_type_object( $post_type ); if ( ! $pt_object || false === $pt_object->rewrite ) { return $post_link; } $date_based_post_types = array( 'news', 'dreamnews', 'prwire', 'businessnews' ); $postname_based_post_types = array( 'column', 'esports', 'business', 'robot', 'blog', 'travel', 'review', 'report', 'notice', 'link', 'special', 'premium' ); // 下書きや保留中の投稿は通常のリンクを返す $draft_or_pending = isset( $post->post_status ) && in_array( $post->post_status, array( 'draft', 'pending', 'auto-draft' ), true ); if ( $draft_or_pending && ! $leavename ) { return $post_link; } $slug = isset( $pt_object->rewrite['slug'] ) ? $pt_object->rewrite['slug'] : ''; $slug = trim( (string) $slug, '/' ); // 日付ベース(news / dreamnews / prwire / businessnews) if ( in_array( $post_type, $date_based_post_types, true ) ) { $permalink = $wp_rewrite->get_extra_permastruct( $post_type ); if ( ! $permalink ) { return $post_link; } $year = get_post_time( 'Y', false, $post ); $month = get_post_time( 'm', false, $post ); $day = get_post_time( 'd', false, $post ); $permalink = str_replace( '%year%', $year, $permalink ); $permalink = str_replace( '%monthnum%', $month, $permalink ); $permalink = str_replace( '%day%', $day, $permalink ); $permalink = str_replace( '%post_id%', $post->ID, $permalink ); return home_url( $permalink ); } // 投稿名ベース if ( in_array( $post_type, $postname_based_post_types, true ) ) { $permalink = $wp_rewrite->get_extra_permastruct( $post_type ); if ( ! $permalink ) { return $post_link; } // 投稿名を置換 if ( ! $leavename ) { $permalink = str_replace( '%' . $post_type . '%', $post->post_name, $permalink ); } return home_url( $permalink ); } // hints-and-tips: %game-title%/%postname%.html if ( 'hints-and-tips' === $post_type ) { $permalink = $wp_rewrite->get_extra_permastruct( $post_type ); if ( ! $permalink ) { return $post_link; } // タクソノミーを置換 $terms = get_the_terms( $post->ID, 'game-title' ); if ( $terms && ! is_wp_error( $terms ) ) { $term = array_shift( $terms ); $permalink = str_replace( '%game-title%', $term->slug, $permalink ); } else { // タームが無い場合はタクソノミー部分を削除 $permalink = str_replace( '%game-title%/', '', $permalink ); } // 投稿名を置換 if ( ! $leavename ) { $permalink = str_replace( '%hints-and-tips%', $post->post_name, $permalink ); } return home_url( $permalink ); } return $post_link; } add_filter( 'post_type_link', 'sqool_custom_post_type_permalink', 10, 3 );
Warning: Attempt to read property "post_status" on null in /home/sqool/sqool.net/public_html/wp-content/plugins/feedwordpress/feedwordpress.php on line 1469

Warning: Attempt to read property "post_status" on null in /home/sqool/sqool.net/public_html/wp-content/plugins/feedwordpress/feedwordpress.php on line 1470

Warning: Cannot modify header information - headers already sent by (output started at /home/sqool/sqool.net/public_html/wp-content/themes/sqool.net/functions.php:1) in /home/sqool/sqool.net/public_html/wp-content/plugins/pubsubhubbub/includes/class-discovery.php on line 93

Warning: Cannot modify header information - headers already sent by (output started at /home/sqool/sqool.net/public_html/wp-content/themes/sqool.net/functions.php:1) in /home/sqool/sqool.net/public_html/wp-content/plugins/pubsubhubbub/includes/class-discovery.php on line 93

Warning: Cannot modify header information - headers already sent by (output started at /home/sqool/sqool.net/public_html/wp-content/themes/sqool.net/functions.php:1) in /home/sqool/sqool.net/public_html/wp-content/plugins/pubsubhubbub/includes/class-discovery.php on line 97

Warning: Cannot modify header information - headers already sent by (output started at /home/sqool/sqool.net/public_html/wp-content/themes/sqool.net/functions.php:1) in /home/sqool/sqool.net/public_html/wp-includes/feed-rss2-comments.php on line 8
へのコメント SQOOLNETはゲーム情報を幅広く発信しているゲーム情報メディアです。ゲームの攻略、ニュース、eスポーツ、イベント、コラム、ビジネス情報などを掲載しています。 Fri, 19 Dec 2025 17:47:47 +0000 hourly 1 https://wordpress.org/?v=6.9.4