プラグインなしでウィジェット設定をエクスポート・インポートする方法

Cocoonカスタマイズ集
この記事は約11分で読めます。
記事内に広告が含まれています。

はじめに

WordPressサイトの引越しやバックアップの際、ウィジェットの配置エリアや各ウィジェットの中身(設定値)を手動で再設定するのは非常に手間がかかります。
標準機能のエクスポートでは余計なデータまで含まれてしまい、プラグインを増やすのもサイトの肥大化に繋がります。

そこで、プラグイン「Widget Importer & Exporter」などを使用せずに、ウィジェット情報(設定値・配置エリア)をエクスポート・インポートする機能を追加します。

この記事では、この方法について説明します。

完成イメージ

実装手順

以下のコードをfunctions.phpに追加します。

// ウィジェットページに追加
add_action('load-widgets.php', function () {
  $screen = get_current_screen();

  if ($screen && $screen->id === 'widgets') {
    // エクスポート用nonceを生成
    $export_nonce = wp_create_nonce('widget_io_action');
    $export_url   = admin_url('?action=widget_io_export_action&widget_io_nonce=' . $export_nonce);

    // インポート用nonceを生成
    $import_nonce = wp_create_nonce('widget_io_action');
    $import_url   = admin_url('admin-post.php');

    ob_start();
    ?>
    <div class="widget-io">
      <p><strong>ウィジェット設定のエクスポート・インポート</strong></p>

      <div class="widget-io__export">
        <h4><span class="dashicons dashicons-database-export"></span> エクスポート</h4>
        <p>現在のエリア配置と設定値をJSONファイルとして保存します。</p>
        <p><a href="<?php echo esc_url($export_url); ?>" class="button button-secondary widget-io__button">JSONファイルをダウンロード</a></p>
      </div>

      <hr style="margin: 15px 0; border: 0; border-top: 1px solid #ccc;" />

      <div class="widget-io__import">
        <h4><span class="dashicons dashicons-database-import"></span> インポート</h4>
        <p>エクスポートしたJSONファイルを選択して、設定を復元します。</p>
        <form id="widget-io-form" class="widget-io__form" method="post" enctype="multipart/form-data" action="<?php echo esc_url($import_url); ?>">
          <input type="hidden" name="action" value="widget_io_import_action" />
          <input type="hidden" name="widget_io_nonce" value="<?php echo esc_attr($import_nonce); ?>" />
          <div class="widget-io__file-area">
            <input type="file" name="widget_io_file" accept=".json" required />
            <input type="submit" class="button button-primary widget-io__button" value="インポート" onclick="return confirm('現在のウィジェット設定が上書きされます。よろしいですか?');" />
          </div>
        </form>
      </div>
    </div>
    <?php
    $html = ob_get_clean();

    $screen->add_help_tab([
      'id'      => 'widget-io-help-tab',
      'title'   => '設定の移行',
      'content' => $html,
    ]);
  }
});


// 対象のエクスポート処理を実行
add_action('admin_init', function () {
  if (!isset($_GET['action']) || $_GET['action'] !== 'widget_io_export_action') {
    return;
  }

  // nonceチェック
  if (!isset($_GET['widget_io_nonce']) || !wp_verify_nonce($_GET['widget_io_nonce'], 'widget_io_action')) {
    wp_die('セキュリティ検証に失敗しました。');
  }

  // 権限チェック
  if (!current_user_can('manage_options')) {
    wp_die('権限がありません。');
  }

  // 配置情報を取得
  $sidebars_widgets = get_option('sidebars_widgets');

  // 各ウィジェットの設定値を取得
  $widget_instances = [];
  global $wp_registered_widgets;

  if (!empty($wp_registered_widgets)) {
    foreach ($wp_registered_widgets as $widget) {
      // 各ウィジェットの「ベース名」を取得
      if (isset($widget['callback'][0]) && is_object($widget['callback'][0]) && method_exists($widget['callback'][0], 'get_settings')) {
        $id_base = $widget['callback'][0]->id_base;

        if (!isset($widget_instances[$id_base])) {
          // オプション名で保存されている設定インスタンスを取得
          $widget_instances[$id_base] = get_option('widget_' . $id_base);
        }
      }
    }
  }

  $export_data = [
    'sidebars'  => $sidebars_widgets,
    'instances' => $widget_instances,
  ];

  // JSON形式でファイルをダウンロード
  header('Content-Type: application/json; charset=utf-8');
  header('Content-Disposition: attachment; filename="wp-widgets-export-' . date('Y-m-d') . '.json"');
  header('Pragma: no-cache');
  header('Expires: 0');

  echo json_encode($export_data, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
  exit;
});


// インポート実行処理
add_action('admin_post_widget_io_import_action', function () {
  // nonceチェック
  if (!isset($_POST['widget_io_nonce']) || !wp_verify_nonce($_POST['widget_io_nonce'], 'widget_io_action')) {
    wp_die('セキュリティ検証に失敗しました。');
  }

  // 権限チェック
  if (!current_user_can('manage_options')) {
    wp_die('権限がありません。');
  }

  if (!isset($_FILES['widget_io_file']) || $_FILES['widget_io_file']['error'] !== UPLOAD_ERR_OK) {
    set_transient('my_admin_notice', [
      'type'    => 'error',
      'message' => 'インポートに失敗しました。',
    ], 30);

    wp_safe_redirect(admin_url('widgets.php'));
    exit;
  }

  // 一時ファイルのテキストを取得
  $json_content = file_get_contents($_FILES['widget_io_file']['tmp_name']);
  $data         = json_decode($json_content, true);

  if (!$data || !isset($data['sidebars']) || !isset($data['instances'])) {
    set_transient('my_admin_notice', [
      'type'    => 'error',
      'message' => 'インポートに失敗しました。',
    ], 30);

    wp_safe_redirect(admin_url('widgets.php'));
    exit;
  }

  // ウィジェットのデータを復元
  foreach ($data['instances'] as $id_base => $settings) {
    if (!empty($settings)) {
      update_option('widget_' . $id_base, $settings);
    }
  }

  // ウィジェットエリアのデータを復元
  update_option('sidebars_widgets', $data['sidebars']);

  set_transient('my_admin_notice', [
    'type'    => 'success',
    'message' => 'ウィジェットの設定を正常にインポートしました。',
  ], 30);

  wp_safe_redirect(admin_url('widgets.php'));
  exit;
});


// 通知メッセージを出力
add_action('admin_notices', function () {
  if ($notice = get_transient('my_admin_notice')) {
    echo '<div class="notice notice-' . esc_attr($notice['type']) . ' is-dismissible"><p>' . esc_html($notice['message']) . '</p></div>';
    delete_transient('my_admin_notice');
  }
});

注意点

移行先とのテーマ・エリアの互換性

  • ウィジェットエリア名の一致が必須
    エクスポート元とインポート先で、ウィジェットエリア(「サイドバー」「フッター左」など)の内部識別名が完全に一致している必要があります。
    テーマが異なると、インポートしたウィジェットが画面に表示されません。
  • テーマ変更時は「使用停止中」へ移動
    エリア名が一致しない場合、データ自体は取り込まれますが、ウィジェットは全て管理画面最下部の「使用停止中のウィジェット」の中に格納されます。(その場合は手動で配置し直す必要があります)

インポート時の上書き(リセット)の挙動

  • 既存の配置は全て上書きされる
    インポートを実行すると、現在のサイトのウィジェット配置(並び順や個数)は、JSONファイルに保存されていた時点の状態へ完全に上書き(差し替え)されます。
  • JSONにない既存ウィジェットはエリア外へ
    インポート先のサイトにだけ存在する(JSONデータには含まれていない)ウィジェットがあった場合、それらは現在のエリアから自動的に外され、「使用停止中のウィジェット」へ移動します。

プラグインやテーマ固有のウィジェットへの依存

  • プラグインの事前有効化が必要
    「お問い合わせフォーム」や「人気記事ギャラリー」など、外部プラグインが提供しているウィジェットを移行する場合、インポート先のサイトでもあらかじめそのプラグインが有効化されている必要があります。
  • 無効化状態でのインポートはデータが消失するリスク
    プラグインが未有効の状態でインポートを行うと、WordPressがそのウィジェットを認識できず、配置や設定値が無視(スキップ)されてしまいます。

さいごに

今回紹介した方法を使えば、プラグインを使わずに、ウィジェットの配置や設定値をピンポイントで移行・バックアップできるようになります。

テーマの引っ越しやサイトの複製、あるいは日々のバックアップ作業がダッシュボード上のボタン操作だけで完結し、メンテナンス性も大幅に向上します。
余計なデータを削ぎ落とした軽量なサイト運営を目指す方は、ぜひこのカスタム機能を試してみてください。

タイトルとURLをコピーしました