PluginProbe ʕ •ᴥ•ʔ
CloudSecure WP Security / 1.4.8
CloudSecure WP Security v1.4.8
1.4.10 1.4.9 trunk 0.9.0 1.0.2 1.1.0 1.1.1 1.1.2 1.1.3 1.2.0 1.2.1 1.2.2 1.2.3 1.2.4 1.2.5 1.2.6 1.2.7 1.3.1 1.3.10 1.3.11 1.3.12 1.3.13 1.3.14 1.3.15 1.3.16 1.3.17 1.3.18 1.3.19 1.3.2 1.3.20 1.3.21 1.3.22 1.3.23 1.3.24 1.3.3 1.3.4 1.3.5 1.3.6 1.3.7 1.3.8 1.3.9 1.4.0 1.4.1 1.4.2 1.4.3 1.4.4 1.4.5 1.4.6 1.4.7 1.4.8
cloudsecure-wp-security / modules / cli / class-cloudsecure-wp-cli-base.php
cloudsecure-wp-security / modules / cli Last commit date
commands 2 months ago README.md 2 months ago class-cloudsecure-wp-cli-base.php 8 months ago class-cloudsecure-wp-cli.php 8 months ago
class-cloudsecure-wp-cli-base.php
792 lines
1 <?php
2 /**
3 * CloudSecure WP Security CLI Base Class
4 *
5 * @package CloudSecure_WP_Security
6 */
7
8 if ( ! defined( 'ABSPATH' ) ) {
9 exit;
10 }
11
12 if ( ! class_exists( 'WP_CLI' ) ) {
13 return;
14 }
15
16 /**
17 * CloudSecure WP Security CLI Base Class
18 * �
19 �通機能を提供するベースクラス
20 */
21 abstract class CloudSecureWP_CLI_Base extends WP_CLI_Command {
22
23 /**
24 * @var CloudSecureWP
25 */
26 protected $plugin;
27
28 /**
29 * 機能名とクラスのマッピング
30 */
31 protected const FEATURE_MAP = array(
32 'disable-login' => 'disable_login',
33 'rename-login-page' => 'rename_login_page',
34 'unify-messages' => 'unify_messages',
35 'two-factor-authentication' => 'two_factor_authentication',
36 'captcha' => 'captcha',
37 'restrict-admin-page' => 'restrict_admin_page',
38 'disable-access-system-file' => 'disable_access_system_file',
39 'disable-author-query' => 'disable_author_query',
40 'disable-xmlrpc' => 'disable_xmlrpc',
41 'disable-restapi' => 'disable_restapi',
42 'waf' => 'waf',
43 'login-notification' => 'login_notification',
44 'update-notice' => 'update_notice',
45 'server-error-notification' => 'server_error_notification',
46 'login-log' => 'login_log',
47 );
48
49 /**
50 * 機能の説明
51 */
52 protected const FEATURE_DESCRIPTIONS = array(
53 'disable-login' => 'ログイン無効化',
54 'rename-login-page' => 'ログインURL変更',
55 'unify-messages' => 'ログインエラーメッセージ統一',
56 'two-factor-authentication' => '2段階認証',
57 'captcha' => '画像認証追加',
58 'restrict-admin-page' => '管理画面アクセス制限',
59 'disable-access-system-file' => '設定ファイルアクセス防止',
60 'disable-author-query' => 'ユーザー名漏えい防止',
61 'disable-xmlrpc' => 'XML-RPC無効化',
62 'disable-restapi' => 'REST API無効化',
63 'waf' => 'シンプルWAF',
64 'login-notification' => 'ログイン通知',
65 'update-notice' => 'アップデート通知',
66 'server-error-notification' => 'サーバーエラー通知',
67 'login-log' => 'ログイン履歴',
68 );
69
70 /**
71 * htaccessを使用する機能のリスト
72 */
73 protected const HTACCESS_FEATURES = array(
74 'restrict-admin-page',
75 'rename-login-page',
76 'disable-xmlrpc',
77 );
78
79 /**
80 * 設定値が存在しない機能のリスト
81 * (有効無効の切り替えのみで、設定値の表示・変更が不要な機能)
82 */
83 protected const CONFIG_EXCLUDED_FEATURES = array(
84 'login-log',
85 );
86
87 /**
88 * 改行コードの置換文字列
89 */
90 protected const NEWLINE_PLACEHOLDER = '__CLDSEC_NEWLINE__';
91
92 /**
93 * WAF攻撃タイプの文字列リスト
94 */
95 protected const WAF_ATTACK_TYPES = array( 'sql', 'xss', 'command', 'code', 'mail' );
96
97 /**
98 * WAF攻撃タイプのビットマッピング
99 */
100 protected const WAF_ATTACK_TYPE_BITS = array(
101 'sql' => 1, // SQLインジェクション
102 'xss' => 2, // クロスサイトスクリプティング
103 'command' => 4, // OSコマンドインジェクション
104 'code' => 8, // コードインジェクション
105 'mail' => 16, // メールヘッダインジェクション
106 );
107
108 /**
109 * 特別なWordPressオプション保存処理が�
110 要な機能のリスト
111 */
112 protected const SPECIAL_PROCESSING_FEATURES = array(
113 'two-factor-authentication',
114 'server-error-notification',
115 );
116
117 /**
118 * 特別なWordPressオプション設定�
119 目の定数定義
120 */
121 protected const SPECIAL_SETTING_KEYS = array(
122 'TWO_FACTOR_ENABLED_ROLES' => 'enabled_roles',
123 'TWO_FACTOR_USER_REGISTRATIONS' => 'user_registrations',
124 'SERVER_ERROR_EMAIL_NOTIFICATION' => 'email_notification',
125 );
126
127 /**
128 * 特別なWordPressオプションの定数定義
129 */
130 protected const WORDPRESS_OPTION_NAMES = array(
131 'TWO_FACTOR_ROLES' => 'cloudsecurewp_two_factor_authentication_roles',
132 'TWO_FACTOR_REGISTRATIONS' => 'cloudsecurewp_two_factor_authentication_user_registrations',
133 'SERVER_ERROR_EMAIL' => 'cloudsecurewp_enable_email_server_error_notification',
134 );
135
136 /**
137 * 設定タイプ定義(各機能・設定キーごとの型�
138 報)
139 */
140 protected const SETTING_TYPES = array(
141 'textarea' => array(
142 'login-notification' => array( 'body' ),
143 ),
144 'array' => array(
145 'restrict-admin-page' => array( 'paths' ),
146 'disable-restapi' => array( 'exclude' ),
147 'two-factor-authentication' => array( 'enabled_roles' ),
148 ),
149 'boolean' => array(
150 'rename-login-page' => array( 'disable_redirect' ),
151 'login-notification' => array( 'admin_only' ),
152 'server-error-notification' => array( 'email_notification' ),
153 ),
154 'bitflag' => array(
155 'waf' => array( 'available_rules' ),
156 ),
157 'internal' => array(
158 'waf' => array( 'send_at' ),
159 'update-notice' => array( 'last_notice' ),
160 ),
161 );
162
163 public function __construct() {
164 $this->init_plugin();
165 }
166
167 /**
168 * �
169 �通の機能検証処理
170 *
171 * @param array $args コマンド引数
172 * @param bool $check_config_excluded CONFIG_EXCLUDED_FEATURESのチェックを行うかどうか
173 * @return array 検証結果 ['success' => bool, 'error' => string, 'feature_name' => string, 'description' => string, 'feature_instance' => object] (success=trueの場合のみ後半3�
174 目が有効)
175 */
176 protected function validate_feature_arguments( $args, $check_config_excluded = true ) {
177 // 利用可能な機能一覧を事前に計算(エラーメッセージで使用)
178 $available_features = array_keys( self::FEATURE_MAP );
179 if ( $check_config_excluded ) {
180 $available_features = array_diff( $available_features, self::CONFIG_EXCLUDED_FEATURES );
181 }
182
183 // 引数が�
184 �列でない場合はエラー
185 if ( ! is_array( $args ) ) {
186 return array(
187 'success' => false,
188 'error' => '引数が正しく渡されていません。',
189 );
190 }
191
192 // 機能名が指定されていない、または空の場合はエラー
193 if ( count( $args ) === 0 || empty( $args[0] ) ) {
194 return array(
195 'success' => false,
196 'error' => '機能名を指定してください。利用可能な機能: ' . implode( ', ', $available_features ),
197 );
198 }
199
200 // 複数の機能名が指定されている場合はエラー
201 if ( count( $args ) > 1 ) {
202 return array(
203 'success' => false,
204 'error' => '機能名は1つのみ指定してください。複数の機能を同時に操作することはできません。指定された引数: ' . implode( ', ', $args ),
205 );
206 }
207
208 // 引数を文字列として取得
209 $feature_name = (string) $args[0];
210
211 // 機能名が存在するかチェック
212 if ( ! isset( self::FEATURE_MAP[ $feature_name ] ) ) {
213 return array(
214 'success' => false,
215 'error' => "機能 '{$feature_name}' は存在しません。利用可能な機能: " . implode( ', ', $available_features ),
216 );
217 }
218
219 // 設定値が存在しない機能を除外(�
220 要な場合のみ)
221 if ( $check_config_excluded && in_array( $feature_name, self::CONFIG_EXCLUDED_FEATURES, true ) ) {
222 return array(
223 'success' => false,
224 'error' => "機能 '{$feature_name}' は設定値が存在しないため、このコマンドでは操作できません。利用可能な機能: " . implode( ', ', $available_features ),
225 );
226 }
227
228 // 機能の説明を取得
229 $description = self::FEATURE_DESCRIPTIONS[ $feature_name ] ?? $feature_name;
230
231 // 機能インスタンスを取得
232 $feature_instance = $this->get_feature_instance( $feature_name );
233
234 if ( ! $feature_instance ) {
235 return array(
236 'success' => false,
237 'error' => "機能 '{$feature_name}' ({$description}) のインスタンスを取得できませんでした。",
238 );
239 }
240
241 return array(
242 'success' => true,
243 'feature_name' => $feature_name,
244 'description' => $description,
245 'feature_instance' => $feature_instance,
246 );
247 }
248
249 /**
250 * エラーレスポンスを出力して終了
251 *
252 * @param array $data エラーデータ
253 * @param int $exit_code 終了コード(デフォルト: 1)
254 */
255 protected function output_error_response( $data, $exit_code = 1 ) {
256 $response = array(
257 'result' => 'error',
258 'data' => $data,
259 );
260 WP_CLI::line( wp_json_encode( $response, JSON_UNESCAPED_UNICODE ) );
261 exit( (int) $exit_code );
262 }
263
264 /**
265 * 成功レスポンスを出力して終了
266 *
267 * @param array $data レスポンスデータ
268 * @param int $exit_code 終了コード(デフォルト: 0)
269 */
270 protected function output_success_response( $data, $exit_code = 0 ) {
271 WP_CLI::line( wp_json_encode( $data, JSON_UNESCAPED_UNICODE ) );
272 exit( (int) $exit_code );
273 }
274
275 /**
276 * プラグインインスタンスを初期化
277 */
278 protected function init_plugin() {
279 global $cloudsecurewp;
280
281 // メインプラグインのグローバルインスタンスが存在する場合はそれを使用
282 if ( isset( $cloudsecurewp ) && is_object( $cloudsecurewp ) ) {
283 WP_CLI::debug( 'CloudSecure WP プラグインのインスタンスを使用します。' );
284 $this->plugin = $cloudsecurewp;
285 return;
286 }
287
288 WP_CLI::debug( 'CloudSecure WP プラグインのインスタンスを新しく作成します。' );
289
290 // 存在しない場合は新しく作成
291 $plugin_file = dirname( __DIR__, 2 ) . '/cloudsecure-wp.php';
292
293 // CloudSecureWPクラスが読み込まれていない場合は読み込み
294 if ( ! class_exists( 'CloudSecureWP' ) ) {
295 require_once dirname( __DIR__ ) . '/cloudsecure-wp.php';
296 }
297
298 $cloudsecurewp_info_datas = array(
299 'version' => 'Version',
300 'plugin_name' => 'Plugin Name',
301 'text_domain' => 'Text Domain',
302 );
303
304 $cloudsecurewp_info = get_file_data( $plugin_file, $cloudsecurewp_info_datas );
305 $cloudsecurewp_info['plugin_path'] = plugin_dir_path( $plugin_file );
306 $cloudsecurewp_info['plugin_url'] = plugin_dir_url( $plugin_file );
307
308 WP_CLI::debug( 'CloudSecure WP CLI - Plugin Info: ' . wp_json_encode( $cloudsecurewp_info ) );
309
310 $this->plugin = new CloudSecureWP( $cloudsecurewp_info );
311 }
312
313 /**
314 * プラグイン機能インスタンスを取得
315 *
316 * @param string $feature_name
317 * @return object|null
318 */
319 protected function get_feature_instance( $feature_name ) {
320 if ( ! isset( self::FEATURE_MAP[ $feature_name ] ) ) {
321 WP_CLI::warning( "機能 '{$feature_name}' がFEATURE_MAPに見つかりません" );
322 return null;
323 }
324
325 $property_name = self::FEATURE_MAP[ $feature_name ];
326 $getter_method = 'get_' . $property_name;
327
328 WP_CLI::debug( "{$getter_method} の呼び出しを試行中" );
329
330 // プラグインインスタンスの存在確認
331 if ( ! $this->plugin ) {
332 WP_CLI::warning( 'プラグインインスタンスが利用できません' );
333 return null;
334 }
335
336 // CloudSecureWPクラスにgetterメソッドがある場合はそれを使用
337 if ( method_exists( $this->plugin, $getter_method ) ) {
338 try {
339 return $this->plugin->$getter_method();
340 } catch ( Exception $e ) {
341 WP_CLI::warning( "{$getter_method} の呼び出しエラー: " . $e->getMessage() );
342 return null;
343 }
344 } else {
345 WP_CLI::warning( "getter メソッド '{$getter_method}' が見つかりません" );
346 return null;
347 }
348 }
349
350 /**
351 * 設定タイプを判定する統一メソッド
352 *
353 * @param string $type 判定したい設定タイプ (textarea|array|boolean|bitflag|internal)
354 * @param string $feature_name 機能名
355 * @param string $setting_key 設定キー
356 * @return bool
357 */
358 protected function is_setting_type( $type, $feature_name, $setting_key ) {
359 if ( ! isset( self::SETTING_TYPES[ $type ] ) ) {
360 return false;
361 }
362
363 $type_settings = self::SETTING_TYPES[ $type ];
364
365 if ( ! isset( $type_settings[ $feature_name ] ) ) {
366 return false;
367 }
368
369 return in_array( $setting_key, $type_settings[ $feature_name ], true );
370 }
371
372 /**
373 * テキストエリア設定かどうかを判定
374 *
375 * @param string $feature_name 機能名
376 * @param string $setting_key 設定キー
377 * @return bool
378 */
379 protected function is_textarea_setting( $feature_name, $setting_key ) {
380 return $this->is_setting_type( 'textarea', $feature_name, $setting_key );
381 }
382
383 /**
384 * テキストエリア値を�
385 �力用形式に変換(プレースホルダー→実際の改行)
386 *
387 * @param string $text 変換対象のテキスト
388 * @return string 変換後のテキスト
389 */
390 protected function convert_placeholder_to_textarea( $text ) {
391 return str_replace( self::NEWLINE_PLACEHOLDER, "\n", $text );
392 }
393
394 /**
395 * テキストエリア値を表示用形式に変換(実際の改行→プレースホルダー)
396 *
397 * @param string $text 変換対象のテキスト
398 * @return string 変換後のテキスト
399 */
400 protected function convert_textarea_to_placeholder( $text ) {
401 return str_replace( array( "\r\n", "\n", "\r" ), self::NEWLINE_PLACEHOLDER, $text );
402 }
403
404 /**
405 * �
406 �列設定かどうかを判定
407 *
408 * @param string $feature_name 機能名
409 * @param string $setting_key 設定キー
410 * @return bool
411 */
412 protected function is_array_setting( $feature_name, $setting_key ) {
413 return $this->is_setting_type( 'array', $feature_name, $setting_key );
414 }
415
416 /**
417 * �
418 �列値を�
419 �力用形式に変換(カンマ区切り文字列→�
420 �列)
421 *
422 * @param string $value カンマ区切り文字列
423 * @return array 変換後の�
424 �列
425 */
426 protected function convert_string_to_array( $value ) {
427 $array_values = explode( ',', $value );
428
429 if ( ! is_array( $array_values ) ) {
430 return array();
431 }
432
433 $validated_values = array();
434 foreach ( $array_values as $val ) {
435 // 空白を除去
436 $val = preg_replace( '|\s|', '', $val );
437 if ( ! empty( $val ) ) {
438 $validated_values[] = $val;
439 }
440 }
441
442 // 重複を除去
443 $validated_values = array_unique( $validated_values );
444
445 return array_values( $validated_values );
446 }
447
448 /**
449 * �
450 �列値を表示用形式に変換(�
451 �列→カンマ区切り文字列)
452 *
453 * @param array $value �
454 �列
455 * @return string 変換後のカンマ区切り文字列
456 */
457 protected function convert_array_to_string( $value ) {
458 // �
459 �列でない場合は空文字列を返す
460 if ( ! is_array( $value ) ) {
461 return '';
462 }
463
464 // 空�
465 �列の場合は空文字列を返す
466 if ( empty( $value ) ) {
467 return '';
468 }
469
470 return implode( ',', $value );
471 }
472
473 /**
474 * boolean設定かどうかを判定
475 *
476 * @param string $feature_name 機能名
477 * @param string $setting_key 設定キー
478 * @return bool
479 */
480 protected function is_boolean_setting( $feature_name, $setting_key ) {
481 return $this->is_setting_type( 'boolean', $feature_name, $setting_key );
482 }
483
484 /**
485 * boolean値を�
486 �力用形式に変換(1→t、0→f)
487 *
488 * @param string $value �
489 �力値
490 * @return string 変換後の値
491 */
492 protected function convert_display_to_boolean( $value ) {
493 // 文字列として扱う
494 $value = (string) $value;
495
496 // 1 → t への変換
497 if ( $value === '1' ) {
498 return 't';
499 }
500
501 // 0 → f への変換
502 if ( $value === '0' ) {
503 return 'f';
504 }
505
506 // その他の値はそのまま返す
507 return $value;
508 }
509
510 /**
511 * boolean値を表示用形式に変換(t→1、f→0)
512 *
513 * @param string $value �
514 部値
515 * @return string 変換後の値
516 */
517 protected function convert_boolean_to_display( $value ) {
518 // 文字列として扱う
519 $value = (string) $value;
520
521 // t → 1 への変換
522 if ( $value === 't' ) {
523 return '1';
524 }
525
526 // f → 0 への変換
527 if ( $value === 'f' ) {
528 return '0';
529 }
530
531 // その他の値はそのまま返す
532 return $value;
533 }
534
535 /**
536 * ビットフラグ設定かどうかを判定
537 *
538 * @param string $feature_name 機能名
539 * @param string $setting_key 設定キー
540 * @return bool
541 */
542 protected function is_bitflag_setting( $feature_name, $setting_key ) {
543 return $this->is_setting_type( 'bitflag', $feature_name, $setting_key );
544 }
545
546 /**
547 * ビットフラグ値を表示用形式に変換(ビット値→文字列�
548 �列)
549 *
550 * @param string $feature_name 機能名
551 * @param string $setting_key 設定キー
552 * @param int $bit_value ビット値
553 * @return array 文字列�
554 �列
555 */
556 protected function convert_bitflag_to_strings( $feature_name, $setting_key, $bit_value ) {
557 if ( $feature_name === 'waf' && $setting_key === 'available_rules' ) {
558 $result = array();
559 foreach ( self::WAF_ATTACK_TYPE_BITS as $string => $bit ) {
560 if ( ( $bit_value & $bit ) > 0 ) {
561 $result[] = $string;
562 }
563 }
564
565 return $result;
566 }
567
568 return array();
569 }
570
571 /**
572 * ビットフラグ値を�
573 �力用形式に変換(文字列�
574 �列→ビット値)
575 *
576 * @param string $feature_name 機能名
577 * @param string $setting_key 設定キー
578 * @param array $strings 文字列�
579 �列
580 * @return int ビット値
581 */
582 protected function convert_strings_to_bitflag( $feature_name, $setting_key, $strings ) {
583 // �
584 �列形式であることを確認
585 if ( ! is_array( $strings ) ) {
586 return 0;
587 }
588
589 if ( $feature_name === 'waf' && $setting_key === 'available_rules' ) {
590 $result = 0;
591 foreach ( $strings as $attack_type ) {
592 if ( isset( self::WAF_ATTACK_TYPE_BITS[ $attack_type ] ) ) {
593 $result |= self::WAF_ATTACK_TYPE_BITS[ $attack_type ];
594 }
595 }
596
597 return $result;
598 }
599
600 return 0;
601 }
602
603 /**
604 * �
605 部設定(ユーザーが直接設定すべきでない)かどうかを判定
606 *
607 * @param string $feature_name
608 * @param string $setting_key
609 * @return bool
610 */
611 protected function is_internal_setting( $feature_name, $setting_key ) {
612 return $this->is_setting_type( 'internal', $feature_name, $setting_key );
613 }
614
615 /**
616 * WordPress管理画面と同様のサニタイズ処理を適用
617 *
618 * @param string $feature_name 機能名
619 * @param string $setting_key 設定キー
620 * @param mixed $value 設定値
621 * @return mixed サニタイズ済み設定値
622 */
623 protected function sanitize_setting_value( $feature_name, $setting_key, $value ) {
624 // WordPress関数の存在チェック
625 if ( ! function_exists( 'sanitize_text_field' ) || ! function_exists( 'sanitize_textarea_field' ) ) {
626 // WordPress環境でない場合はそのまま返す
627 return $value;
628 }
629
630 // テキストエリア設定の場合(bodyのみ)
631 if ( $this->is_textarea_setting( $feature_name, $setting_key ) ) {
632 return stripslashes( sanitize_textarea_field( $value ) );
633 }
634
635 // �
636 �列設定やビットフラグ設定も含め、その他の設定は通常のテキストフィールドとして処理
637 return sanitize_text_field( $value );
638 }
639
640 /**
641 * 設定値を表示用形式に変換
642 *
643 * @param string $feature_name 機能名
644 * @param string $setting_key 設定キー
645 * @param string $value 設定値
646 * @return string 変換後の値
647 */
648 protected function normalize_value_for_display( $feature_name, $setting_key, $value ) {
649 // boolean設定の場合、t→1、f→0に変換
650 if ( $this->is_boolean_setting( $feature_name, $setting_key ) ) {
651 return $this->convert_boolean_to_display( $value );
652 }
653
654 // ビットフラグ設定の場合、文字列�
655 �列に変換してカンマ区切りで返す
656 if ( $this->is_bitflag_setting( $feature_name, $setting_key ) ) {
657 $strings = $this->convert_bitflag_to_strings( $feature_name, $setting_key, (int) $value );
658 return implode( ',', $strings );
659 }
660
661 // その他の設定はそのまま返す
662 return $value;
663 }
664
665 /**
666 * 設定値を�
667 �力用形式に変換
668 *
669 * @param string $feature_name 機能名
670 * @param string $setting_key 設定キー
671 * @param mixed $value �
672 �力値(文字列または�
673 �列)
674 * @return mixed 変換後の値
675 */
676 protected function normalize_value_for_input( $feature_name, $setting_key, $value ) {
677 // boolean設定の場合、1→t、0→fに変換
678 if ( $this->is_boolean_setting( $feature_name, $setting_key ) ) {
679 return $this->convert_display_to_boolean( $value );
680 }
681
682 // ビットフラグ設定の場合、�
683 �列をビット値に変換
684 if ( $this->is_bitflag_setting( $feature_name, $setting_key ) ) {
685 return (string) $this->convert_strings_to_bitflag( $feature_name, $setting_key, $value );
686 }
687
688 // その他の設定はそのまま返す
689 return $value;
690 }
691
692 /**
693 * 特別な設定(WordPressオプション)を取得して正規化する
694 *
695 * @param string $feature_name 機能名
696 * @param array $configuration 設定�
697 �列(参�
698 �渡し)
699 * @return void
700 */
701 protected function add_special_configuration_settings( $feature_name, &$configuration ) {
702 // 2段階認証の特別な設定
703 if ( $feature_name === 'two-factor-authentication' ) {
704 $this->add_two_factor_authentication_settings( $configuration );
705 }
706
707 // サーバーエラー通知の特別な設定
708 if ( $feature_name === 'server-error-notification' ) {
709 $this->add_server_error_notification_settings( $feature_name, $configuration );
710 }
711 }
712
713 /**
714 * 2段階認証の特別な設定を追加
715 *
716 * @param array $configuration 設定�
717 �列(参�
718 �渡し)
719 * @return void
720 */
721 private function add_two_factor_authentication_settings( &$configuration ) {
722 // WordPress関数の存在チェック
723 if ( ! function_exists( 'wp_roles' ) || ! function_exists( 'get_option' ) ) {
724 return;
725 }
726
727 $wp_roles = wp_roles();
728 if ( ! $wp_roles || ! isset( $wp_roles->roles ) ) {
729 return;
730 }
731
732 $all_roles = array_keys( $wp_roles->roles );
733 $enabled_roles = get_option( self::WORDPRESS_OPTION_NAMES['TWO_FACTOR_ROLES'], $all_roles );
734 $configuration['enabled_roles'] = implode( ',', $enabled_roles );
735
736 // ユーザーの認証キー登録状況を取得(statusコマンドの場合)
737 $configuration['user_registrations'] = $this->get_two_factor_user_registrations();
738 }
739
740 /**
741 * 2段階認証のユーザー登録状況を取得
742 *
743 * @return string
744 */
745 protected function get_two_factor_user_registrations() {
746 // WordPress関数の存在チェック
747 if ( ! function_exists( 'get_users' ) ) {
748 return '';
749 }
750
751 $users = get_users();
752 $registrations = array();
753
754 // 2段階認証機能のインスタンスを取得
755 $two_factor_instance = $this->get_feature_instance( 'two-factor-authentication' );
756
757 foreach ( $users as $user ) {
758 if ( $two_factor_instance && method_exists( $two_factor_instance, 'show_2factor_state_2user_list' ) ) {
759 $status = $two_factor_instance->show_2factor_state_2user_list( '', 'is_2factor', $user->ID );
760
761 // "設定済"→1、"未設定"→0 で出力
762 $status_num = ( $status === '設定済' ) ? '1' : '0';
763 $registrations[] = $user->user_login . ':' . $status_num;
764 }
765 }
766
767 return implode( ',', $registrations );
768 }
769
770 /**
771 * サーバーエラー通知の特別な設定を追加
772 *
773 * @param string $feature_name 機能名
774 * @param array $configuration 設定�
775 �列(参�
776 �渡し)
777 * @return void
778 */
779 private function add_server_error_notification_settings( $feature_name, &$configuration ) {
780 // WordPress関数の存在チェック
781 if ( ! function_exists( 'get_option' ) ) {
782 return;
783 }
784
785 $enable_email_server_error_notification = get_option( self::WORDPRESS_OPTION_NAMES['SERVER_ERROR_EMAIL'], 't' );
786 // boolean値の表示用正規化(t→1、f→0)
787 $enable_email_server_error_notification = $this->normalize_value_for_display( $feature_name, 'email_notification', $enable_email_server_error_notification );
788 $configuration['email_notification'] = $enable_email_server_error_notification;
789 }
790
791 }
792