PluginProbe
Contact Forms by Cimatti / 2.2.32
Contact Forms by Cimatti v2.2.32
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.2.32, at admin/theme-helper.php

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