PluginProbe
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More / 6.32
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More v6.32
6.35 6.34 6.33.1 6.33 6.32.1 6.32 6.31 6.25 6.25.1 6.26 6.26.1 6.27 6.28 6.29 6.3 6.3.1 6.3.2 6.30 6.4 6.4.1 6.4.2 6.5 6.5.1 6.5.2 6.5.3 All 141 releases
← All changes | classes/controllers/FrmStylesController.php +108 -13 6.306.32 View file →
@@ -20,8 +20,17 @@
20 20 */
21 21 private static $message;
22 22
23 23 /**
24 + * Cache of the active style object keyed by form ID.
25 + *
26 + * @since 6.32
27 + *
28 + * @var array
29 + */
30 + private static $active_style = array();
31 +
32 + /**
24 33 * @return void
25 34 */
26 35 public static function load_pro_hooks() {
27 36 if ( FrmAppHelper::pro_is_installed() ) {
@@ -237,17 +246,18 @@
237 246 *
238 247 * @return void
239 248 */
240 249 private static function get_url_to_custom_style( &$stylesheet_urls ) {
241 - $file_name = '/css/' . self::get_file_name();
250 + $add_css_to_uploads_dir = FrmStyle::add_css_to_uploads_dir();
251 + $file_path = FrmStyle::get_generated_css_file_path( $add_css_to_uploads_dir ) . '/' . self::get_file_name();
242 252
243 - if ( is_readable( FrmAppHelper::plugin_path() . $file_name ) ) {
244 - $url = FrmAppHelper::plugin_url() . $file_name;
245 - } else {
246 - $url = admin_url( 'admin-ajax.php?action=frmpro_css' );
253 + if ( ! is_readable( $file_path ) ) {
254 + $stylesheet_urls['formidable'] = admin_url( 'admin-ajax.php?action=frmpro_css' );
255 + return;
247 256 }
248 257
249 - $stylesheet_urls['formidable'] = $url;
258 + $base_url = $add_css_to_uploads_dir ? wp_upload_dir()['baseurl'] . '/formidable/css/' : FrmAppHelper::plugin_url() . '/css/';
259 + $stylesheet_urls['formidable'] = $base_url . self::get_file_name();
250 260 }
251 261
252 262 /**
253 263 * Use a different stylesheet per site in a multisite install
@@ -623,22 +633,44 @@
623 633 $style = $active_style;
624 634 break;
625 635
626 636 case 'duplicate':
627 - $style = clone $active_style;
628 - $new_style = $frm_style->get_new();
637 + $style = clone $active_style;
638 + $new_style = $frm_style->get_new();
639 + $new_name = self::get_new_style_post_name( $new_style->post_name );
640 +
641 + // The single style custom CSS is nested under the old style's scope. Re-scope it to the
642 + // new style's scope so it unnests correctly for display and re-nests correctly on save.
643 + if ( ! empty( $style->post_content['single_style_custom_css'] ) ) {
644 + $css_scope_helper = new FrmCssScopeHelper();
645 + $unnested_css = $css_scope_helper->unnest( $style->post_content['single_style_custom_css'], 'frm_style_' . $style->post_name ); // phpcs:ignore SlevomatCodingStandard.Files.LineLength.LineTooLong
646 + $style->post_content['single_style_custom_css'] = $css_scope_helper->nest( $unnested_css, 'frm_style_' . $new_name );
647 + }
648 +
629 649 $style->ID = $new_style->ID;
630 - $style->post_name = $new_style->post_name;
631 - unset( $new_style );
650 + $style->post_name = $new_name;
651 + unset( $new_style, $new_name );
632 652 break;
633 653
634 654 case 'new_style':
635 - $style = $frm_style->get_new();
655 + $style = $frm_style->get_new();
656 + $style->post_name = self::get_new_style_post_name( $style->post_name );
636 657 break;
637 - }
658 + }//end switch
638 659
639 660 if ( in_array( $view, array( 'duplicate', 'new_style' ), true ) ) {
640 - $style->post_title = FrmAppHelper::simple_get( 'style_name' );
661 + // A new or duplicated style has no ID yet, so the Rename modal updates the post_title input
662 + // instead of calling an endpoint. Prefer that posted title over $_GET['style_name'] when present.
663 + $posted_title = '';
664 +
665 + // phpcs:ignore WordPress.Security.NonceVerification.Missing
666 + if ( isset( $_POST['frm_style_setting']['post_title'] ) ) {
667 + // The nonce is verified in FrmStylesController::save_style before this renders.
668 + // phpcs:ignore WordPress.Security.NonceVerification.Missing
669 + $posted_title = sanitize_text_field( wp_unslash( $_POST['frm_style_setting']['post_title'] ) );
670 + }
671 +
672 + $style->post_title = '' !== $posted_title ? $posted_title : FrmAppHelper::simple_get( 'style_name' );
641 673 $style->menu_order = 0;
642 674 }
643 675
644 676 if ( ! isset( $style ) ) {
@@ -662,8 +694,27 @@
662 694 include $style_views_path . 'show.php';
663 695 }
664 696
665 697 /**
698 + * Derive the temporary post_name (CSS scope slug) for a new or duplicated style from the chosen
699 + * style name so the displayed scope matches the slug WordPress will store on save.
700 + *
701 + * Falls back to the auto-generated key when no style name was provided so the scope is never empty.
702 + *
703 + * @since 6.32
704 + *
705 + * @param string $fallback The auto-generated post_name to use when no style name is chosen.
706 + *
707 + * @return string
708 + */
709 + private static function get_new_style_post_name( $fallback ) {
710 + $style_name = FrmAppHelper::simple_get( 'style_name' );
711 + $slug = $style_name ? sanitize_title( $style_name ) : '';
712 +
713 + return $slug ? $slug : $fallback;
714 + }
715 +
716 + /**
666 717 * @since 6.0
667 718 *
668 719 * @return string
669 720 */
@@ -1228,8 +1279,52 @@
1228 1279 }
1229 1280
1230 1281 $frm_style = new FrmStyle( $style );
1231 1282 return $frm_style->get_one();
1283 + }
1284 +
1285 + /**
1286 + * Get the active style object for a field's form.
1287 + *
1288 + * @since 6.32
1289 + *
1290 + * @param array|int $field The 'field' array.
1291 + *
1292 + * @return object
1293 + */
1294 + public static function get_active_style( $field ) {
1295 + if ( ! is_array( $field ) ) {
1296 + return new stdClass();
1297 + }
1298 +
1299 + $form_id = $field['parent_form_id'] ?? $field['form_id'];
1300 +
1301 + if ( isset( self::$active_style[ $form_id ] ) ) {
1302 + return self::$active_style[ $form_id ];
1303 + }
1304 +
1305 + $active_style = self::get_form_style( $form_id );
1306 +
1307 + if ( ! is_object( $active_style ) ) {
1308 + $active_style = new stdClass();
1309 + }
1310 +
1311 + self::$active_style[ $form_id ] = $active_style;
1312 +
1313 + return self::$active_style[ $form_id ];
1314 + }
1315 +
1316 + /**
1317 + * Get the style setting key that stores the alignment for a field type.
1318 + *
1319 + * @since 6.32
1320 + *
1321 + * @param string $field_type
1322 + *
1323 + * @return string
1324 + */
1325 + public static function get_align_key_for_style_settings( $field_type ) {
1326 + return 'checkbox' === $field_type ? 'check_align' : 'radio_align';
1232 1327 }
1233 1328
1234 1329 /**
1235 1330 * @param string $class