PluginProbe
Contact Forms by Cimatti / 2.3.5
Contact Forms by Cimatti v2.3.5
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 / admin / theme-helper.php

theme-helper.php in Contact Forms by Cimatti 2.3.5, at admin/theme-helper.php

329 lines 13.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Contact Forms - Theme Helper
4 *
5 * A developer tool to detect CSS conflicts between themes and Contact Forms styling.
6 * Scans loaded stylesheets for rules that may override Contact Forms classes.
7 *
8 * @package ContactForms
9 * @since 2.0.0-beta.6
10 */
11
12 if (!defined('ABSPATH')) {
13 exit;
14 }
15
16 /**
17 * Get list of Contact Forms CSS classes to monitor for conflicts
18 */
19 function accua_forms_get_monitored_css_classes() {
20 return array(
21 // Error handling
22 'pfbc-error',
23 'pfbc-error-heading',
24 'pfbc-error-list',
25 'pfbc-inline-error',
26 'pfbc-error-message',
27
28 // Field structure
29 'pfbc-fieldwrap',
30 'pfbc-invalid',
31 'pfbc-element-has-error',
32 'pfbc-element',
33 'pfbc-elementbottom',
34 'pfbc-label',
35 'pfbc-help',
36 'pfbc-description',
37 'pfbc-required',
38
39 // Form inputs
40 'pfbc-textbox',
41 'pfbc-textarea',
42 'pfbc-select',
43 'pfbc-checkbox',
44 'pfbc-buttons',
45
46 // Color picker
47 'pfbc-color-wrapper',
48 'pfbc-color-input',
49 'pfbc-color-hex',
50
51 // Inline labels
52 'pfbc-inline-label-wrapper',
53 'pfbc-floating-label',
54
55 // Form layouts
56 'accua-form',
57 'accua-form-view-standard',
58 'accua-form-view-sidebyside',
59 'accua-form-view-inlinelabel',
60
61 // Misc
62 'accua_form_api_throbbler',
63 'accua_forms_recaptcha2_container',
64 );
65 }
66
67 /**
68 * Render Theme Helper admin page
69 */
70 function accua_forms_theme_helper_page() {
71 if (!current_user_can('manage_options')) {
72 wp_die( esc_html__('You do not have sufficient permissions to access this page.', 'contact-forms') );
73 }
74 ?>
75 <div id="accua_forms_theme_helper_page" class="accua_forms_admin_page wrap">
76 <h1><?php esc_html_e('Contact Forms - Theme Helper', 'contact-forms'); ?></h1>
77 <?php accua_forms_theme_helper_content(); ?>
78
79 <span id="accua-forms-version"><?php
80 $plugin_data = get_plugin_data( ACCUA_FORMS_FILE );
81 echo esc_html( $plugin_data['Name'] ); ?> - <a href="https://www.cimatti.it/en/wordpress-plugins/contact-forms/"><?php
82 esc_html_e('Version', 'contact-forms'); echo ' ' . esc_html( $plugin_data['Version'] ); ?></a></span>
83 </div>
84 <?php
85 }
86
87 /**
88 * Render Theme Helper content (shared between standalone page and settings tab)
89 */
90 function accua_forms_theme_helper_content() {
91 ?>
92
93 <p class="description">
94 <?php esc_html_e('This tool scans CSS stylesheets to detect rules that may conflict with Contact Forms styling. It helps identify theme customizations that could cause layout issues with form error messages, field spacing, and other elements.', 'contact-forms'); ?>
95 </p>
96
97 <div class="postbox" id="theme-helper-controls" style="margin: 20px 0;">
98 <div class="postbox-header"><h2><?php esc_html_e('Scan Options', 'contact-forms'); ?></h2></div>
99 <div class="inside">
100
101 <div style="margin-bottom: 15px;">
102 <button type="button" id="scan-current-page" class="button button-primary">
103 <?php esc_html_e('Scan Admin Stylesheets', 'contact-forms'); ?>
104 </button>
105 <span class="description" style="margin-left: 10px;">
106 <?php esc_html_e('Instant scan of all CSS loaded on this page', 'contact-forms'); ?>
107 </span>
108 </div>
109
110 <div style="margin-bottom: 15px;">
111 <label for="scan-url" style="display: block; margin-bottom: 5px; font-weight: 600;">
112 <?php esc_html_e('Scan Frontend URL:', 'contact-forms'); ?>
113 </label>
114 <input type="url" id="scan-url" style="width: 400px; max-width: 100%;"
115 placeholder="<?php echo esc_attr(home_url('/your-form-page/')); ?>" />
116 <button type="button" id="scan-url-button" class="button">
117 <?php esc_html_e('Scan URL', 'contact-forms'); ?>
118 </button>
119 <p class="description">
120 <?php esc_html_e('Enter a URL of a page containing a Contact Form to scan its CSS for conflicts.', 'contact-forms'); ?>
121 </p>
122 </div>
123 </div></div>
124
125 <div id="theme-helper-status" style="display: none; margin: 20px 0; padding: 15px; border-left: 4px solid #0073aa; background: #f0f6fc;">
126 <span id="status-message"><?php esc_html_e('Ready to scan', 'contact-forms'); ?></span>
127 </div>
128
129 <div id="theme-helper-results" style="display: none; margin: 20px 0;">
130 <div class="postbox">
131 <div class="postbox-header"><h2><?php esc_html_e('Scan Results', 'contact-forms'); ?></h2></div>
132 <div class="inside">
133 <div id="results-summary" style="margin-bottom: 20px; padding: 15px; background: #f6f7f7; border: 1px solid #e0e0e0;">
134 <!-- Summary will be inserted here -->
135 </div>
136
137 <table class="wp-list-table widefat fixed striped" id="conflicts-table">
138 <thead>
139 <tr>
140 <th scope="col" style="width: 25%;"><?php esc_html_e('Stylesheet', 'contact-forms'); ?></th>
141 <th scope="col" style="width: 10%;"><?php esc_html_e('Line', 'contact-forms'); ?></th>
142 <th scope="col" style="width: 25%;"><?php esc_html_e('Selector', 'contact-forms'); ?></th>
143 <th scope="col" style="width: 40%;"><?php esc_html_e('Conflicting Properties', 'contact-forms'); ?></th>
144 </tr>
145 </thead>
146 <tbody id="conflicts-tbody">
147 <!-- Results will be inserted here -->
148 </tbody>
149 </table>
150 </div></div>
151 </div>
152
153 <div class="postbox" id="theme-helper-info" style="margin-top: 20px;">
154 <div class="postbox-header"><h2><?php esc_html_e('How to Fix Conflicts', 'contact-forms'); ?></h2></div>
155 <div class="inside">
156 <ol>
157 <li>
158 <strong><?php esc_html_e('Identify the source:', 'contact-forms'); ?></strong>
159 <?php esc_html_e('The "Stylesheet" column shows which CSS file contains the conflicting rule.', 'contact-forms'); ?>
160 </li>
161 <li>
162 <strong><?php esc_html_e('Find the exact line:', 'contact-forms'); ?></strong>
163 <?php esc_html_e('The "Line" column shows approximately where in the file the rule is located.', 'contact-forms'); ?>
164 </li>
165 <li>
166 <strong><?php esc_html_e('Modify or remove the rule:', 'contact-forms'); ?></strong>
167 <?php esc_html_e('Edit your theme\'s CSS file (usually style.css or a custom CSS file) to remove or adjust the conflicting properties.', 'contact-forms'); ?>
168 </li>
169 <li>
170 <strong><?php esc_html_e('Use child theme:', 'contact-forms'); ?></strong>
171 <?php esc_html_e('If the conflict is in a parent theme, create a child theme and override the conflicting styles there.', 'contact-forms'); ?>
172 </li>
173 </ol>
174
175 <h4><?php esc_html_e('Common Conflicts', 'contact-forms'); ?></h4>
176 <ul>
177 <li><code>.pfbc-invalid</code>, <code>.pfbc-fieldwrap</code> - <?php esc_html_e('Error message spacing', 'contact-forms'); ?></li>
178 <li><code>.pfbc-element</code> - <?php esc_html_e('Field element layout', 'contact-forms'); ?></li>
179 <li><code>.pfbc-inline-error</code> - <?php esc_html_e('Inline error positioning', 'contact-forms'); ?></li>
180 <li><code>.accua-form-view-*</code> - <?php esc_html_e('Form layout styles', 'contact-forms'); ?></li>
181 </ul>
182 </div></div>
183 <?php
184 }
185
186 /**
187 * AJAX handler for fetching CSS from a URL
188 */
189 add_action('wp_ajax_accua_forms_fetch_url_css', 'accua_forms_fetch_url_css');
190 function accua_forms_fetch_url_css() {
191 check_ajax_referer('accua_theme_helper', 'nonce');
192
193 if (!current_user_can('manage_options')) {
194 wp_send_json_error(array('message' => __('Permission denied', 'contact-forms')));
195 }
196
197 $url = isset($_POST['url']) ? esc_url_raw(wp_unslash($_POST['url'])) : '';
198
199 if (empty($url)) {
200 wp_send_json_error(array('message' => __('No URL provided', 'contact-forms')));
201 }
202
203 // Fetch the HTML page
204 $response = wp_remote_get($url, array(
205 'timeout' => 30,
206 'sslverify' => false,
207 ));
208
209 if (is_wp_error($response)) {
210 wp_send_json_error(array('message' => $response->get_error_message()));
211 }
212
213 $html = wp_remote_retrieve_body($response);
214
215 if (empty($html)) {
216 wp_send_json_error(array('message' => __('Empty response from URL', 'contact-forms')));
217 }
218
219 // Parse HTML to find stylesheet URLs
220 $stylesheets = array();
221
222 // Match <link rel="stylesheet" href="...">
223 preg_match_all('/<link[^>]+rel=["\']stylesheet["\'][^>]+href=["\']([^"\']+)["\'][^>]*>/i', $html, $matches);
224 if (!empty($matches[1])) {
225 $stylesheets = array_merge($stylesheets, $matches[1]);
226 }
227
228 // Also match href before rel
229 preg_match_all('/<link[^>]+href=["\']([^"\']+)["\'][^>]+rel=["\']stylesheet["\'][^>]*>/i', $html, $matches);
230 if (!empty($matches[1])) {
231 $stylesheets = array_merge($stylesheets, $matches[1]);
232 }
233
234 $stylesheets = array_unique($stylesheets);
235
236 // Fetch each stylesheet and combine content
237 $css_data = array();
238 $base_url = trailingslashit(dirname($url));
239 $site_url = trailingslashit(wp_parse_url($url, PHP_URL_SCHEME) . '://' . wp_parse_url($url, PHP_URL_HOST));
240
241 foreach ($stylesheets as $stylesheet_url) {
242 // Handle relative URLs
243 if (strpos($stylesheet_url, '//') === 0) {
244 $stylesheet_url = wp_parse_url($url, PHP_URL_SCHEME) . ':' . $stylesheet_url;
245 } elseif (strpos($stylesheet_url, '/') === 0) {
246 $stylesheet_url = rtrim($site_url, '/') . $stylesheet_url;
247 } elseif (strpos($stylesheet_url, 'http') !== 0) {
248 $stylesheet_url = $base_url . $stylesheet_url;
249 }
250
251 // Skip external CDN stylesheets (Google Fonts, etc.)
252 if (strpos($stylesheet_url, 'fonts.googleapis.com') !== false ||
253 strpos($stylesheet_url, 'cdnjs.cloudflare.com') !== false ||
254 strpos($stylesheet_url, 'cdn.jsdelivr.net') !== false) {
255 continue;
256 }
257
258 $css_response = wp_remote_get($stylesheet_url, array(
259 'timeout' => 15,
260 'sslverify' => false,
261 ));
262
263 if (!is_wp_error($css_response)) {
264 $css_content = wp_remote_retrieve_body($css_response);
265 if (!empty($css_content)) {
266 $css_data[] = array(
267 'url' => $stylesheet_url,
268 'content' => $css_content,
269 );
270 }
271 }
272 }
273
274 // Also look for inline styles
275 preg_match_all('/<style[^>]*>(.*?)<\/style>/is', $html, $inline_matches);
276 if (!empty($inline_matches[1])) {
277 foreach ($inline_matches[1] as $index => $inline_css) {
278 if (!empty(trim($inline_css))) {
279 $css_data[] = array(
280 'url' => $url . ' (inline style #' . ($index + 1) . ')',
281 'content' => $inline_css,
282 );
283 }
284 }
285 }
286
287 // Detect Contact Forms version from remote site
288 $remote_cf_version = null;
289
290 // Check for Contact Forms CSS version in URL params (e.g., frontend.css?ver=69)
291 foreach ($stylesheets as $stylesheet_url) {
292 // Match both old and new CSS paths
293 if (strpos($stylesheet_url, 'contact-forms/assets/css/frontend.css') !== false ||
294 strpos($stylesheet_url, 'contact-forms/assets/css/accua-form-api.css') !== false ||
295 strpos($stylesheet_url, 'contact-forms/accua-form-api.css') !== false) { // Old path
296 // Extract version from query string
297 $parsed = wp_parse_url($stylesheet_url);
298 if (!empty($parsed['query'])) {
299 parse_str($parsed['query'], $query_params);
300 if (!empty($query_params['ver'])) {
301 $remote_cf_version = $query_params['ver'];
302 break;
303 }
304 }
305 }
306 }
307
308 // Also try to find version in HTML comments or meta tags
309 if (!$remote_cf_version) {
310 // Look for Contact Forms generator meta or comment
311 if (preg_match('/Contact Forms[^0-9]*([0-9]+\.[0-9]+\.[0-9]+[^"\s]*)/i', $html, $version_match)) {
312 $remote_cf_version = $version_match[1];
313 }
314 }
315
316 // Get current plugin version
317 $plugin_data = get_plugin_data(ACCUA_FORMS_FILE);
318 $current_version = $plugin_data['Version'];
319
320 wp_send_json_success(array(
321 'stylesheets' => $css_data,
322 'count' => count($css_data),
323 'remoteContactFormsVersion' => $remote_cf_version,
324 'remoteCssVersion' => $remote_cf_version, // CSS version number
325 'currentVersion' => $current_version,
326 'currentCssVersion' => ACCUA_FORMS_CSS_VERSION,
327 ));
328 }
329