sections = $sections; $this->fields = $fields; } /** * Register the settings and all fields. * * @since 4.2.0 * * @return void */ function settings_init(): void { // Register a new setting this page. register_setting('cf7dtx_settings', 'cf7dtx_settings'); foreach ($this->sections as $section_id => $section) { // Register a new section. add_settings_section( $section_id, $section['title'], [$this, 'render_section'], 'cf7dtx_settings', ); } /* Register All The Fields. */ foreach ($this->fields as $field) { // Register a new field in the main section. add_settings_field( $field['id'], /* ID for the field. Only used internally. To set the HTML ID attribute, use $args['label_for']. */ $field['label'], /* Label for the field. */ [$this, 'render_field'], /* The name of the callback function. */ 'cf7dtx_settings', /* The menu page on which to display this field. */ $field['section'], /* The section of the settings page in which to show the box. */ [ 'label_for' => $field['id'], /* The ID of the field. */ 'class' => 'cf7dtx_row', /* The class of the field. */ 'field' => $field, /* Custom data for the field. */ ] ); } } /** * Add a subpage to the WordPress Settings menu. * * @since 4.2.0 * * @return void */ function options_page(): void { add_submenu_page( 'wpcf7', /* Parent Menu Slug */ 'Contact Form 7 - Dynamic Text Extension', /* Page Title */ 'Dynamic Text Extension', /* Menu Title */ $this->capability, /* Capability */ 'cf7dtx_settings', /* Menu Slug */ [$this, 'render_options_page'], /* Callback */ ); } /** * Render the settings page. * * @since 4.2.0 * * @return void */ function render_options_page(): void { // check user capabilities if (!current_user_can($this->capability)) { return; } if (isset($_GET['dismiss-access-keys-notice'])) { wpcf7dtx_set_update_access_scan_check_status('notice_dismissed'); ?>

render_back_to_settings_button(); ?>

handle_save_allows(); ?>

render_allow_keys_submission($r); ?>
num_forms_to_scan, $offset); ?>

render_scan_results($results); ?>

Scan Forms for Post Meta and User Data Keys

>

'cf7dtx_settings[' . $field['id'] . ']', 'textarea_rows' => 5, ) ); break; } case "email": { ?>

sections[$args['id']]['description']; ?>

' . __('Scan complete. No keys detected.', 'contact-form-7-dynamic-text-extension') . '

'; $this->render_back_to_settings_button(); return; } // Check if we need to scan another batch if ($results['forms_scanned'] === $this->num_forms_to_scan) { $offset = isset($_GET['offset']) ? $_GET['offset'] : 0; $next_offset = $offset + $this->num_forms_to_scan; echo '

'; echo sprintf( __('%1$s forms scanned. There may be more forms to scan.', 'contact-form-7-dynamic-text-extension'), $results['forms_scanned'], ); echo ' '; echo '' . sprintf( __('Scan %1$s more forms', 'contact-form-7-dynamic-text-extension'), $this->num_forms_to_scan ) . ''; echo '

'; } $settings = wpcf7dtx_get_settings(); $already_allowed_meta_keys = wpcf7dtx_parse_allowed_keys(wpcf7dtx_array_has_key('post_meta_allow_keys', $settings)); $already_allowed_user_keys = wpcf7dtx_parse_allowed_keys(wpcf7dtx_array_has_key('user_data_allow_keys', $settings)); // Check the results ahead of time to see if all of the keys are already in the allow list - if so, nothing to do $forms = $results['forms']; $all_keys_allowed = true; foreach ($forms as $form_id => $r) { if (count($r['meta_keys'])) { foreach ($r['meta_keys'] as $key) { if (!in_array($key, $already_allowed_meta_keys)) { $all_keys_allowed = false; break; } } if ($all_keys_allowed === false) break; } if (count($r['user_keys'])) { foreach ($r['user_keys'] as $key) { if (!in_array($key, $already_allowed_user_keys)) { $all_keys_allowed = false; break; } } if ($all_keys_allowed === false) break; } } if ($all_keys_allowed) { wpcf7dtx_set_update_access_scan_check_status('intervention_completed'); } ?>

$r) { ?>

Meta Keys

User Data Keys

render_back_to_settings_button(); ?>
$val) { if (str_starts_with($key, 'dtx_meta_key')) { $parts = explode('/', $key); $meta_keys[] = $parts[1]; } else if (str_starts_with($key, 'dtx_user_key')) { $parts = explode('/', $key); $user_keys[] = $parts[1]; } } // Add those keys in options $settings = wpcf7dtx_get_settings(); // Meta Data if (count($meta_keys)) { // Get already saved values $post_meta_allow_keys = isset($settings['post_meta_allow_keys']) ? wpcf7dtx_parse_allowed_keys($settings['post_meta_allow_keys']) : []; // Merge with new values $new = array_unique(array_merge($post_meta_allow_keys, $meta_keys)); $settings['post_meta_allow_keys'] = implode(PHP_EOL, $new); } // User Data if (count($user_keys)) { // Get already saved values $user_data_allow_keys = isset($settings['user_data_allow_keys']) ? wpcf7dtx_parse_allowed_keys($settings['user_data_allow_keys']) : []; // Merge with new values $new = array_unique(array_merge($user_data_allow_keys, $user_keys)); $settings['user_data_allow_keys'] = implode(PHP_EOL, $new); } // Update with new settings wpcf7dtx_update_settings($settings); // Mark as intervention complete wpcf7dtx_set_update_access_scan_check_status('intervention_completed'); return [ 'user' => $user_keys, 'meta' => $meta_keys, ]; } /** * Render Allow Keys Submission * * @since 4.2.0 * * @param array $results The results array * * @return void */ function render_allow_keys_submission($r) { ?>

:

:

render_back_to_settings_button(); } /** * Render Back to Settings Button * * @since 4.2.0 * * @return void */ function render_back_to_settings_button() { ?> « [ 'title' => __('Post Meta Access', 'contact-form-7-dynamic-text-extension'), 'description' => __('Control which post metadata the CF7 DTX shortcodes (CF7_get_custom_field) can access. By default, all metadata is protected, so you can open up access through these settings. Keep in mind that users with Contributor+ credentials can add shortcodes and therefore access this data, so make sure not to expose anything sensitive.') . ' ' . __('More Information', 'contact-form-7-dynamic-text-extension') . '', ], 'user_data_access' => [ 'title' => __('User Data Access', 'contact-form-7-dynamic-text-extension'), 'description' => __('Control which user data the CF7 DTX shortcodes (CF7_get_current_user) can access. By default, all user data is protected, so you can open up access through these settings. Keep in mind that users with Contributor+ credentials can add shortcodes and therefore access this data, so make sure not to expose anything sensitive.') . ' ' . __('More Information', 'contact-form-7-dynamic-text-extension') . '', ], ]; /** * Array of fields that should be displayed in the settings page. * * @var array $fields */ $fields = [ [ 'id' => 'post_meta_allow_keys', 'label' => __('Meta Key Allow List', 'contact-form-7-dynamic-text-extension'), 'description' => __('Allow access to these specific post metadata keys. Enter one per line.', 'contact-form-7-dynamic-text-extension'), 'type' => 'textarea', 'section' => 'post_meta_access', ], [ 'id' => 'post_meta_allow_all', 'label' => __('Allow Access to All Post Metadata', 'contact-form-7-dynamic-text-extension'), 'description' => __('**Use with caution.** Should only be enabled if all authorized users with editor privileges (Contributor+) are trusted and should have access to this data. All metadata from any post (including custom post types) will be accessible via the CF7_get_custom_field shortcode. If in doubt, use the Allow List to allow only specific keys.', 'contact-form-7-dynamic-text-extension'), 'type' => 'select', 'options' => [ 'disabled' => __('Disabled - Only Allow Access to Meta Key Allow List', 'contact-form-7-dynamic-text-extension'), 'enabled' => __('Enabled - Allow Access to All Post Metadata', 'contact-form-7-dynamic-text-extension'), ], 'section' => 'post_meta_access', ], [ 'id' => 'user_data_allow_keys', 'label' => __('User Data Key Allow List', 'contact-form-7-dynamic-text-extension'), 'description' => __('Allow access to these specific user data keys. Enter one per line.', 'contact-form-7-dynamic-text-extension'), 'type' => 'textarea', 'section' => 'user_data_access', ], [ 'id' => 'user_data_allow_all', 'label' => __('Allow Access to All User Data', 'contact-form-7-dynamic-text-extension'), 'description' => __('**Use with caution.** Should only be enabled if all authorized users with editor privileges (Contributor+) are trusted and should have access to this data. All of the current user\'s data fields will be accessible via the CF7_get_current_user shortcode. If in doubt, use the Allow List to allow only specific keys.', 'contact-form-7-dynamic-text-extension'), 'type' => 'select', 'options' => [ 'disabled' => __('Disabled - Only Allow Access to User Data Key Allow List', 'contact-form-7-dynamic-text-extension'), 'enabled' => __('Enabled - Allow Access to User Data', 'contact-form-7-dynamic-text-extension'), ], 'section' => 'user_data_access', ], ]; new CF7DTX_Plugin_Settings($sections, $fields); function wpcf7dtx_get_admin_scan_screen_url($offset = 0) { $path = 'admin.php?page=cf7dtx_settings&scan-meta-keys'; if ($offset) { $path .= '&offset=' . $offset; } return admin_url($path); } function wpcf7dtx_get_admin_settings_screen_url() { return admin_url('admin.php?page=cf7dtx_settings'); } /** * Search all CF7 forms for */ function wpcf7dtx_scan_forms_for_access_keys($num, $offset = 0) { $found = [ 'forms' => [], ]; $forms = []; if (function_exists('wpcf7_contact_form')) { $cf7forms = get_posts([ 'post_type' => 'wpcf7_contact_form', // 'numberposts' => $numposts, // sanity check 'posts_per_page' => $num, 'offset' => $offset, ]); $found['forms_scanned'] = count($cf7forms); // Loop through forms foreach ($cf7forms as $form) { // Search for the custom fields shortcode if ( strpos($form->post_content, 'CF7_get_custom_field') !== false || strpos($form->post_content, 'CF7_get_current_user') !== false ) { $cf7 = wpcf7_contact_form($form->ID); $forms[$form->ID] = [ 'title' => $cf7->title(), 'meta_keys' => [], 'user_keys' => [], 'admin_url' => admin_url("admin.php?page=wpcf7&post={$form->ID}&action=edit"), ]; $tags = $cf7->scan_form_tags(); // Check each tag foreach ($tags as $tag) { // Find dynamic tags if (str_starts_with($tag->type, 'dynamic')) { // Check each value foreach ($tag->values as $val) { // Find CF7_get_custom_field if (str_starts_with($val, 'CF7_get_custom_field')) { // Parse out the shortcode atts $atts = shortcode_parse_atts($val); if ($atts) { // Grab the meta key $meta_key = $atts['key']; // Add meta key to the list if ($meta_key) { $forms[$form->ID]['meta_keys'][] = $meta_key; } } } // Find CF7_get_current_user if (str_starts_with($val, 'CF7_get_current_user')) { // Parse out the shortcode atts $atts = shortcode_parse_atts($val); if ($atts) { // Grab user data key $key = $atts['key']; if ($key) { $forms[$form->ID]['user_keys'][] = $key; } } } } } } } } } $found['forms'] = $forms; return $found; }