/** * ------------------------------------------------------------ * 注意: * ・以下を、現在有効なテーマ(子テーマ推奨)の functions.php の「末尾」に貼り付けてください。 * ・このコードが無くても route.php の分岐A・B・D は正常動作します(分岐Cだけが働きません)。 * * 動作: * ・管理画面にアクセス(ログイン済みで管理画面を表示)すると、判定用cookieを付与する。 * ・そのcookieを持つブラウザは、route.php 側で「許可IPと同等」= サイト通常表示になる。 * ・cookieは「セッションcookie」なので、ブラウザを閉じると自動的に消える。 * ・管理画面からログアウトしたときも削除する。 * * ※ PHP 7.3 以上が必要です(setcookie の配列オプションを使用)。 * ------------------------------------------------------------ */ // ★ zzzzz/route.php の設定($admin_cookie_name / $admin_cookie_secret)と必ず同じ値にすること ★ if (!defined('ADMIN_ACCESS_COOKIE_NAME')) define('ADMIN_ACCESS_COOKIE_NAME', 'bloom_admin'); if (!defined('ADMIN_ACCESS_COOKIE_SECRET')) define('ADMIN_ACCESS_COOKIE_SECRET', 'CHANGE_THIS_SECRET_12345'); // ---- 管理画面にアクセスしたら(ログイン済みのみ)セッションcookieを付与 ---- if (!function_exists('bloom_set_admin_cookie')) { function bloom_set_admin_cookie() { if (!is_user_logged_in()) { return; // ログインしていない訪問者には付与しない(自己付与による不正防止) } // すでに正しい値で付与済みなら再送しない if (isset($_COOKIE[ADMIN_ACCESS_COOKIE_NAME]) && hash_equals(ADMIN_ACCESS_COOKIE_SECRET, (string) $_COOKIE[ADMIN_ACCESS_COOKIE_NAME])) { return; } setcookie(ADMIN_ACCESS_COOKIE_NAME, ADMIN_ACCESS_COOKIE_SECRET, [ 'expires' => 0, // 0 = セッションcookie(ブラウザを閉じると消える) 'path' => '/', // サイト全体で有効 'secure' => is_ssl(), // httpsのときだけ送信 'httponly' => true, // JavaScriptから読めない(安全) 'samesite' => 'Lax', ]); // 同一リクエスト内でもすぐ有効化しておく $_COOKIE[ADMIN_ACCESS_COOKIE_NAME] = ADMIN_ACCESS_COOKIE_SECRET; } // admin_init はログイン済みで管理画面を表示したときに実行される add_action('admin_init', 'bloom_set_admin_cookie'); } // ---- ログアウト時に削除 ---- if (!function_exists('bloom_clear_admin_cookie')) { function bloom_clear_admin_cookie() { setcookie(ADMIN_ACCESS_COOKIE_NAME, '', [ 'expires' => time() - 3600, // 過去時刻で失効させる 'path' => '/', 'secure' => is_ssl(), 'httponly' => true, 'samesite' => 'Lax', ]); unset($_COOKIE[ADMIN_ACCESS_COOKIE_NAME]); } add_action('wp_logout', 'bloom_clear_admin_cookie'); } /** * ------------------------------------------------------------ * アクセス制御(IP/リファラ判定によるリダイレクト・404)は * mu-plugin(wp-content/mu-plugins/ecpid-early-gate.php)へ移設済み。 * このファイルには「サイト表示に必要な機能」だけを残しています。 * * - ecpid_get_server_base() … SQLite等の外部ファイルパス取得(下記機能で使用) * - メタディスクリプション出力 * - 関連商品の非表示 * - [rep] ショートコード(共有SQLiteから値を読み込み) * - タイトル / パンくずでのショートコード実行 * - WooCommerce 価格の SQLite 上書き * ------------------------------------------------------------ */ if (!defined('ABSPATH')) { exit; } /** * 外部ファイル用の「サーバーのユーザー領域」を取得する。 * ABSPATH 例: /home/wfucohup/ec-pid.com/ → /home/wfucohup を返す * ※ mu-plugin 側でも同名関数を定義しているため function_exists でガード * (mu-plugin が無くても、この functions.php 単体で動作します)。 */ if (!function_exists('ecpid_get_server_base')) { function ecpid_get_server_base() { if (defined('ABSPATH') && preg_match('#^(/home/[^/]+)/#', ABSPATH, $m)) { return $m[1]; } } } /* ============================================================ * メタディスクリプション出力(商品ページのカスタムフィールド) * ============================================================ */ function add_custom_description() { if ( function_exists( 'is_product' ) && is_product() ) { global $post; if ( $post instanceof WP_Post ) { $description = get_post_meta( $post->ID, 'prd_description', true ); if ( $description ) { echo ''; } } } } add_action('wp_head', 'add_custom_description'); /* ============================================================ * 関連商品を非表示 * ============================================================ */ remove_action( 'woocommerce_after_single_product_summary', 'woocommerce_output_related_products', 20 ); /* ============================================================ * [rep] ショートコード:共有SQLiteファイルから値を読み込む(本番用:エラー非表示版) * ============================================================ */ add_shortcode('rep', function($atts) { $key = isset($atts['k']) ? $atts['k'] : ''; $params = explode('_', $key); if (count($params) !== 3) return ''; list($site_name, $pid, $col_name) = $params; $allowed_cols = ['unit', 'lot']; if (!in_array($col_name, $allowed_cols)) return ''; $db_path = ecpid_get_server_base() . '/zzzzz/product_price.sqlite'; if (!file_exists($db_path)) return ''; try { $db = new PDO("sqlite:$db_path"); $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); $sql = "SELECT {$col_name} FROM common_data WHERE site = :site AND pid = :pid LIMIT 1"; $stmt = $db->prepare($sql); $stmt->execute([':site' => $site_name, ':pid' => $pid]); $result = $stmt->fetchColumn(); if ($result !== false) { // 数値であればカンマ区切り(number_format)にする if (is_numeric($result)) { $result = number_format((float)$result); } return esc_html($result); } else { return ''; } } catch (PDOException $e) { return ''; } }); /* ============================================================ * タイトル / パンくずでショートコードを実行する * ============================================================ */ //