inc = __DIR__ . '/'; $this->name = 'amem/admin'; add_filter( 'display_post_states', array( $this, 'add_display_post_states' ), 10, 2 ); add_action( 'admin_notices', array( $this, 'render_notices' ), 1 ); add_action( 'show_user_profile', array( $this, 'render_custom_user_profile_fields'), 10 ); add_action( 'edit_user_profile', array( $this, 'render_custom_user_profile_fields'), 10 ); // ACF 6.8.7+ 는 save_user() 에서 ACF *location* 이 유저를 타깃하는 필드그룹의 // 키만 허용(get_allowed_field_keys)한다. AM 은 location 이 아니라 role→form 으로 // 필드를 출력하므로 그 키들이 통째로 누락되어 저장이 조용히 스킵된다. // render_custom_user_profile_fields() 와 동일한 소스로 실제 출력 필드 키를 다시 허용. add_filter( 'acf/form/user/allowed_field_keys', array( $this, 'allow_account_field_keys' ), 19, 2 ); add_action( 'amem_doaction_install_core_pages', array( $this, 'install_core_pages' ) ); add_action( 'amem_doaction_not_install_core_pages', array( $this, 'not_install_core_pages' ) ); // add_action( 'acf/input/admin_footer', array( $this, 'field_group_scripts') ); add_action( 'admin_init', array( $this, 'install_amem_core_pages'),10 ); // Field group admin customizations add_action( 'current_screen', array( $this, 'field_group_current_screen' ), 11 ); add_action( 'save_post_acf-field-group', array( $this, 'check_amem_field_group' ), 10 ); add_action( 'acf/input/admin_head', array( $this, 'field_group_admin_head' ), 11 ); if ( !get_option( '__amem_migirate_form_meta_keys' ) ) { $this->migirate_form_meta_keys(); } } function screens() { return apply_filters( 'amem/admin/screens', ['acf_page_amem_settings', 'acf_page_amem_dashboard'] ); } function edit_screens() { return apply_filters( 'amem/admin/edit_screens', ['amem-form', 'edit-amem-form'] ); } protected function migirate_form_meta_keys() { global $wpdb; if ( !get_option( '__amem_migirate_form_meta_keys' ) ) { // Fix dev version meta keys $form_ids = $wpdb->get_col( $wpdb->prepare( "SELECT ID FROM `{$wpdb->posts}` WHERE post_type = %s", 'amem-form' ) ); if ( $form_ids ) { $ids = array_map( 'absint', $form_ids ); $placeholders = implode( ',', array_fill( 0, count( $ids ), '%d' ) ); // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- $placeholders is generated dynamically from safe absint() values $wpdb->query( $wpdb->prepare( "UPDATE `{$wpdb->postmeta}` SET meta_key = REPLACE(meta_key, 'amem_form_', '') WHERE meta_key LIKE %s AND post_id IN ({$placeholders})", array_merge( array( 'amem\_form\_%' ), $ids ) ) ); } update_option( '__amem_migirate_form_meta_keys', 1 ); } } /** * notice 호출 * * @since 1.0.0 */ function render_notices() { if ( ! current_user_can( 'manage_options' ) ) { return; } $this->notices(); } /** * 기본 폼, 페이지 생성을 위한 notice * * @since 1.0.0 */ function notices() { // Re-init options while doing install core pages $notice = ''; if ( current_user_can( 'manage_options' ) && ! get_option( 'amem_default_installed' ) ) { $url = add_query_arg( array( 'amem_do_action' => 'install_core_pages', '_wpnonce' => wp_create_nonce( 'install_core_pages' ), ) ); $not_url = add_query_arg( array( 'amem_do_action' => 'not_install_core_pages', '_wpnonce' => wp_create_nonce( 'install_core_pages' ), ) ); ob_start(); ?>

 

options->get('accform/account_form_showadmin') ) { // Removed option and provides hook if ( apply_filters( 'amem/account/fields/showadmin', true ) ) { $field_groups = $this->get_user_account_field_group($user); if( $field_groups ){ acf_form_data( array( 'screen' => 'user', 'post_id' => 'user_'.$user->ID, 'validation' => 1, ) ); $bypass = amem()->fields->predefined_fields(); echo ''; echo '

' . esc_html__('Advanced Members User Account Fields', 'advanced-members') . '

'; foreach ( $field_groups as $field_group ) { // vars $fields = acf_get_fields( $field_group ); foreach ( $fields as $k => $field ) { if ( in_array($field['name'], $bypass) ) unset($fields[$k]); } if ( $fields ) acf_render_fields( $fields, 'user_'. $user->ID , 'tr', $field_group['instruction_placement'] ); } echo '
'; } } } public function add_display_post_states( $post_states, $post ) { foreach ( amem()->config->get_core_pages() as $page_key => $page_value ) { $page_id = amem()->options->get( amem()->options->get_core_page_id($page_key) ); if ( $page_id == $post->ID ) { $post_states[ 'amem_' . $page_key ] = sprintf( 'Adv. Members %s', $page_value['label'] ); } } return $post_states; } /** * 사용자의 Account 필드 그룹 전달 * * @since 1.0.0 * * @param WP_User $user 사용자 object * @return array $field_groups 해당하는 form 의 필드그룹 */ function get_user_account_field_group( $user ) { $user_roles = $user->roles; if (!empty($user_roles)) { $user_role = array_shift($user_roles); } $role = $user_role; $account_option = amem()->options->options['accform']; if( is_array($user_role) ){ $role = $user_role[0]; } $role = apply_filters( 'amem/admin/account/role', $role, $user, (array) $user->roles ); $form_id = isset($account_option['default'])? $account_option['default'] : 0 ; if( isset( $account_option['rules'] ) ){ foreach ($account_option['rules'] as $account_role) { if( $role == $account_role['role'] ){ $form_id = $account_role['value']; } } } if( !$form_id ){ return array(); } $field_group_keys = array(); $form = amem_get_form( $form_id ); $field_groups = amem_get_form_field_groups( $form['key'] ); /* foreach ($field_groups as $key => $field_group) { // $field_group_keys[$key] = $field_group['key']; } */ return $field_groups; } /** * ACF 6.8.7+ 유저 저장 화이트리스트에 AM account 폼 필드 키를 추가. * * ACF 6.8.7 의 save_user() 는 `acf_get_field_groups(['user_form'=>'edit'])` * (=ACF location 기반) 로 허용 키 목록을 만들고, 제출된 $_POST['acf'] 를 그 키로 * 교집합한다. AM 은 location 이 아니라 role→form 매칭으로 필드를 출력하므로 AM * 필드 키가 목록에서 빠져 교집합이 비고, 저장이 통째로 스킵된다. * 주의(핵심): profile_update 저장 시점에는 primary role 만 세팅돼 있고 보조 role * (예: ame_rex_other_roles 의 haru_company_client)은 아직 재적용 전이다. 그래서 * role→form 해석(get_user_account_field_group)이 렌더 때와 다른 폼(기본 폼)을 골라 * 실제 렌더된 필드그룹 키가 누락된다. 따라서 role 에 의존하지 않고 account 설정의 * 모든 폼(default + 모든 rule)의 필드 키를 union 으로 허용한다. 실제 저장은 ACF 가 * 제출된 키에 대해서만 수행하고 렌더는 role 로 이미 게이트되므로 over-allow 는 무해. * * @since 1.0.0 * * @param array $keys 허용된 최상위 $_POST['acf'] 키. * @param int $user_id 저장 대상 사용자 ID. * @return array */ function allow_account_field_keys( $keys, $user_id ) { // render 와 동일한 노출 게이트 — 관리자에 폼을 안 그리면 허용할 것도 없음. if ( ! apply_filters( 'amem/account/fields/showadmin', true ) ) { return $keys; } $account_option = isset( amem()->options->options['accform'] ) ? (array) amem()->options->options['accform'] : array(); // account 설정의 모든 폼 id 수집 (default + 모든 role rule). role 해석에 의존하지 않음. $form_ids = array(); if ( ! empty( $account_option['default'] ) ) { $form_ids[] = $account_option['default']; } if ( ! empty( $account_option['rules'] ) && is_array( $account_option['rules'] ) ) { foreach ( $account_option['rules'] as $rule ) { if ( ! empty( $rule['value'] ) ) { $form_ids[] = $rule['value']; } } } $form_ids = array_unique( array_filter( $form_ids ) ); if ( empty( $form_ids ) ) { return $keys; } $bypass = ( isset( amem()->fields ) && method_exists( amem()->fields, 'predefined_fields' ) ) ? (array) amem()->fields->predefined_fields() : array(); foreach ( $form_ids as $form_id ) { $form = amem_get_form( $form_id ); if ( empty( $form['key'] ) ) { continue; } $field_groups = amem_get_form_field_groups( $form['key'] ); foreach ( (array) $field_groups as $field_group ) { $fields = acf_get_fields( $field_group ); if ( ! $fields ) { continue; } foreach ( $fields as $field ) { // predefined(계정) 필드는 render 에서 unset 되어 acf[] 로 출력되지 않으므로 제외. if ( in_array( $field['name'], $bypass, true ) ) { continue; } if ( ! empty( $field['key'] ) ) { $keys[] = $field['key']; } } } } return array_values( array_unique( $keys ) ); } public function install_amem_core_pages() { if ( !empty($_REQUEST['amem_do_action']) && isset($_REQUEST['_wpnonce']) && wp_verify_nonce( $_REQUEST['_wpnonce'], 'install_core_pages' ) ){ do_action( 'amem_doaction_'. sanitize_text_field($_REQUEST['amem_do_action']) ); } } public function not_install_core_pages() { amem()->setup()->not_install_core_pages(); } public function install_core_pages() { amem()->setup()->install_default_forms(); } function is_amem_field_group($post_id, $force_check = false) { if ( !$force_check ) return get_post_meta($post_id, '_is_amem', true); $field_group = acf_get_internal_post_type( $post_id, 'acf-field-group' ); $is_amem = false; if ( $field_group['location'] ) { foreach ( $field_group['location'] as $i => $rules ) { foreach( $rules as $j => $rule ) { if ( $rule['param'] == 'amem_form' ) { $is_amem = true; break; } } } } return $is_amem; } function field_group_admin_head() { global $field_group; $screen = get_current_screen(); if ( acf_is_screen('acf-field-group') && $screen->action == 'add' && isset($field_group) && empty($field_group['locations']) && !empty($_GET['amem_form']) && strpos($_GET['amem_form'], 'form_') === 0 ) { $field_group['location'] = array( // Group 0. array( // Rule 0. array( 'param' => 'amem_form', 'operator' => '==', 'value' => sanitize_key( $_GET['amem_form'] ), ), ), ); } } function field_group_current_screen() { if ( ! acf_is_screen( "edit-acf-field-group" ) ) { return; } // add_filter( "views_edit-acf-field-group", array( $this, 'field_group_admin_table_views' ), 10, 1 ); // add_filter( 'display_post_states', array( $this, 'field_group_display_post_states' ), 11, 2 ); add_filter( 'request', array( $this, 'field_group_query_vars' ), 11 ); } function update_amem_field_group_count() { add_action( 'shutdown', array( $this, '_update_amem_field_group_count' ) ); } function _update_amem_field_group_count() { global $wpdb; static $counted; if ( isset( $counted) ) return; $this->migrate_is_amem_field_group(); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- internal count query $query = $wpdb->prepare( "SELECT COUNT(DISTINCT p.ID) FROM $wpdb->posts p INNER JOIN $wpdb->postmeta pm ON (p.ID = pm.post_id) WHERE 1=1 AND pm.meta_key LIKE %s AND pm.meta_value <> '' ", '_is_amem' ); $count = $wpdb->get_var( $query ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared -- $query is built via $wpdb->prepare() above update_option( 'amem_field_group_count', (int) $count ); return $count; } function get_amem_field_group_count() { $count = get_option( 'amem_field_group_count', null ); $count = null; if ( is_null( $count ) ) { $this->migrate_is_amem_field_group(); $count= $this->_update_amem_field_group_count(); } return (int) $count; } protected function migrate_is_amem_field_group() { global $wpdb; $migrated = get_option( '_migrate_is_amem_form_field_group' ); if ( $migrated ) return; $compare = '%s:5:\"param\";s:9:\"amem_form\"%'; // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- one-time migration query $sql = $wpdb->prepare( "SELECT ID FROM $wpdb->posts WHERE post_type LIKE %s AND post_content LIKE %s", 'acf-field-group', $compare ); $field_groups = $wpdb->get_col( $sql ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared -- $sql is built via $wpdb->prepare() above if ( $field_groups ) { foreach ( $field_groups as $field_group ) { // update_post_meta( $field_group, '_is_amem', true ); $this->check_amem_field_group( $field_group ); } } update_option( '_migrate_is_amem_form_field_group', true ); } function check_amem_field_group($post_id) { $field_group = acf_get_internal_post_type( $post_id, 'acf-field-group' ); delete_post_meta( $post_id, '_is_amem_form' ); $is_amem = false; if ( $field_group['location'] ) { foreach ( $field_group['location'] as $i => $rules ) { foreach( $rules as $j => $rule ) { if ( $rule['param'] == 'amem_form' && $rule['operator'] == '==' && $rule['value'] ) { add_post_meta( $post_id, '_is_amem_form', $rule['value'] ); $is_amem = true; } } } } if ( $is_amem ) { update_post_meta( $post_id, '_is_amem', true ); } else { delete_post_meta( $post_id, '_is_amem' ); } $this->update_amem_field_group_count(); } function field_group_display_post_states($post_states, $post) { $is_amem = $this->is_amem_field_group($post->ID); if ( $is_amem ) { $post_states['is_amem'] = ' ' . __( 'Advanced Members', 'advanced-members' ); } return $post_states; } function field_group_admin_table_views($views) { global $wp_list_table, $wp_query; $fg_admoin = acf_get_instance( 'ACF_Admin_Field_Groups' ); $count = $this->get_amem_field_group_count(); $amem_form = 'true'; if ( !empty($_GET['amem_form']) && is_numeric( $_GET['amem_form']) ) { $amem_form = (int) $amem_form; } $views['amem'] = sprintf( '%s (%s)', ( !empty($_GET['amem_form']) ? 'class="current"' : '' ), esc_url( $fg_admoin->get_admin_url( '&amem_form='.$amem_form ) ), esc_html( __( 'Advanced Members', 'advanced-members' ) ), $count ); return $views; } function field_group_query_vars($query_vars) { if ( ! acf_is_screen( "edit-acf-field-group" ) ) { return $query_vars; } if ( empty($_REQUEST['amem_form']) ) { return $query_vars; } if ( empty($query_vars['meta_query']) ) { $query_vars['meta_query'] = []; } $amem_form = $_REQUEST['amem_form']; if ( $amem_form == 'true' ) { $query_vars['meta_query'][] = [ 'key' => '_is_amem', 'compare' => 'EXISTS' ]; } else { $query_vars['meta_query'][] = [ 'key' => '_is_amem_form', 'value' => $amem_form ]; } return $query_vars; } } amem()->register_module('admin', ADMIN::getInstance()); endif; // class_exists check