PluginProbe
Contact Forms by Cimatti / 2.1.0
Contact Forms by Cimatti v2.1.0
2.3.6 2.3.5 2.3.0 2.2.32 2.2.4 2.2.0 2.1.2 2.1.1 trunk 1.0 1.1 1.2 1.2.1 1.3 1.3.1 1.3.2 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 All 62 releases
contact-forms / classes / Element / PostSelect.php

PostSelect.php in Contact Forms by Cimatti 2.1.0, at classes/Element/PostSelect.php

156 lines 5.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * PostSelect Element for Contact Forms
4 *
5 * Renders an accessible searchable dropdown for selecting posts/pages.
6 * Uses AJAX for lazy loading to handle sites with thousands of posts.
7 * WPML compatible - shows only posts from current language.
8 *
9 * Key features:
10 * - AJAX-powered search with pagination
11 * - Keyboard accessible (arrow keys, Enter, Escape)
12 * - WCAG 2.2 AA / European Accessibility Act compliant
13 * - Matches standard .pfbc-select styling
14 *
15 * @package Contact Forms
16 * @subpackage Element
17 * @since 2.0.0-beta.29
18 */
19
20 // phpcs:disable WordPress.Security.EscapeOutput.OutputNotEscaped -- PFBC framework extension
21 class AccuaForm_Element_PostSelect extends AccuaForm_OptionElement {
22
23 /**
24 * @var string Post type to query
25 */
26 protected $post_type = 'page';
27
28 /**
29 * @var string Extra query arguments (query string format)
30 */
31 protected $extra_args = '';
32
33 /**
34 * @var string AJAX URL for fetching posts
35 */
36 protected $ajax_url = '';
37
38 /**
39 * @var string Nonce for AJAX requests
40 */
41 protected $nonce = '';
42
43 /**
44 * Default attributes
45 */
46 protected $attributes = array('class' => 'pfbc-select pfbc-post-select');
47
48 /**
49 * Constructor
50 *
51 * @param string $label The field label.
52 * @param string $name The field name attribute.
53 * @param string $post_type Post type to query (default: 'page').
54 * @param string $extra_args Extra query arguments in query string format.
55 * @param array|null $properties Optional element properties.
56 */
57 public function __construct($label, $name, $post_type = 'page', $extra_args = '', ?array $properties = null) {
58 // Initialize with empty options - will be loaded via AJAX
59 parent::__construct($label, $name, array(), $properties);
60
61 $this->post_type = $post_type;
62 $this->extra_args = $extra_args;
63 $this->ajax_url = admin_url('admin-ajax.php');
64 $this->nonce = wp_create_nonce('accua_forms_get_posts');
65
66 // Add data attributes for JavaScript
67 $this->attributes['data-post-type'] = $this->post_type;
68 $this->attributes['data-ajax-url'] = $this->ajax_url;
69 $this->attributes['data-nonce'] = $this->nonce;
70 if (!empty($this->extra_args)) {
71 $this->attributes['data-extra-args'] = $this->extra_args;
72 }
73 }
74
75 /**
76 * Render the post select element
77 *
78 * Outputs a native select that will be enhanced by JavaScript for search/AJAX.
79 * Falls back to a working select if JavaScript is disabled (with initial options).
80 */
81 public function render() {
82 $this->applyAriaAttributes();
83
84 // Get current value
85 $value = '';
86 if (isset($this->attributes['value'])) {
87 $value = is_array($this->attributes['value']) ? reset($this->attributes['value']) : $this->attributes['value'];
88 }
89
90 // Store selected value for AJAX to include in first page
91 if (!empty($value)) {
92 $this->attributes['data-selected'] = $value;
93 }
94
95 // Generate unique ID for this element (access attributes array directly)
96 $id = isset($this->attributes['id']) ? $this->attributes['id'] : '';
97 if (empty($id)) {
98 $id = 'pfbc-post-select-' . uniqid();
99 $this->attributes['id'] = $id;
100 }
101
102 // Start rendering
103 echo '<div class="pfbc-post-select-wrapper" data-enhanced="false">';
104
105 // Native select element (will be hidden when JS enhances it)
106 echo '<select', $this->getAttributes(array('value', 'selected', 'data-post-type', 'data-ajax-url', 'data-nonce', 'data-extra-args', 'data-selected')), '>';
107
108 // Empty option first - empty text like Country field does (floating label shows the field name)
109 echo '<option value=""></option>';
110
111 // If we have a selected value, fetch and render that post
112 if (!empty($value) && is_numeric($value)) {
113 $selected_post = get_post(absint($value));
114 if ($selected_post) {
115 echo '<option value="', esc_attr($selected_post->ID), '" selected="selected">', esc_html($selected_post->post_title), '</option>';
116 }
117 }
118
119 echo '</select>';
120
121 // Hidden data attributes for JS
122 echo '<input type="hidden" class="pfbc-post-select-config"';
123 echo ' data-post-type="', esc_attr($this->post_type), '"';
124 echo ' data-ajax-url="', esc_attr($this->ajax_url), '"';
125 echo ' data-nonce="', esc_attr($this->nonce), '"';
126 if (!empty($this->extra_args)) {
127 echo ' data-extra-args="', esc_attr($this->extra_args), '"';
128 }
129 if (!empty($value)) {
130 echo ' data-selected="', esc_attr($value), '"';
131 }
132 echo ' />';
133
134 echo '</div>';
135 }
136
137 /**
138 * Get the post type for this select
139 *
140 * @return string
141 */
142 public function getPostType() {
143 return $this->post_type;
144 }
145
146 /**
147 * Get the extra query arguments
148 *
149 * @return string
150 */
151 public function getExtraArgs() {
152 return $this->extra_args;
153 }
154 }
155 // phpcs:enable WordPress.Security.EscapeOutput.OutputNotEscaped
156