| @@ -118,20 +118,24 @@ | ||
| 118 | 118 | $new_instance['post_content'] = isset( $_POST['frm_style_setting']['post_content'] ) ? $this->sanitize_post_content( wp_unslash( $_POST['frm_style_setting']['post_content'] ) ) : ''; // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized, WordPress.Security.NonceVerification.Missing, SlevomatCodingStandard.Files.LineLength.LineTooLong |
| 119 | 119 | $new_instance['post_content']['custom_css'] = $custom_css; |
| 120 | 120 | unset( $custom_css ); |
| 121 | 121 | |
| 122 | - if ( ! empty( $new_instance['post_content']['single_style_custom_css'] ) ) { | |
| 123 | - $css_scope = 'frm_style_' . $new_instance['post_name']; | |
| 124 | - $new_instance['post_content']['single_style_custom_css'] = $css_scope_helper->nest( $new_instance['post_content']['single_style_custom_css'], $css_scope ); | |
| 125 | - } | |
| 126 | - | |
| 127 | 122 | $new_instance['post_type'] = FrmStylesController::$post_type; |
| 128 | 123 | $new_instance['post_status'] = 'publish'; |
| 129 | 124 | |
| 130 | 125 | if ( ! $id ) { |
| 131 | - $new_instance['post_name'] = $new_instance['post_title']; | |
| 126 | + // For a new style (including a duplicate), the post_name is derived from the title. | |
| 127 | + // Resolve slug uniqueness up front (WordPress appends -2, -3, etc. to duplicate slugs) | |
| 128 | + // so the CSS scope below matches the slug WordPress will actually store. | |
| 129 | + $slug = sanitize_title( $new_instance['post_title'] ); | |
| 130 | + $new_instance['post_name'] = wp_unique_post_slug( $slug, 0, $new_instance['post_status'], $new_instance['post_type'], 0 ); | |
| 132 | 131 | } |
| 133 | 132 | |
| 133 | + if ( ! empty( $new_instance['post_content']['single_style_custom_css'] ) ) { | |
| 134 | + $css_scope = 'frm_style_' . $new_instance['post_name']; | |
| 135 | + $new_instance['post_content']['single_style_custom_css'] = $css_scope_helper->nest( $new_instance['post_content']['single_style_custom_css'], $css_scope ); | |
| 136 | + } | |
| 137 | + | |
| 134 | 138 | $default_settings = $this->get_defaults(); |
| 135 | 139 | |
| 136 | 140 | foreach ( $default_settings as $setting => $default ) { |
| 137 | 141 | if ( ! isset( $new_instance['post_content'][ $setting ] ) ) { |
| @@ -411,18 +415,80 @@ | ||
| 411 | 415 | |
| 412 | 416 | $this->clear_cache(); |
| 413 | 417 | |
| 414 | 418 | $css = $this->get_css_content( $filename ); |
| 415 | - $create_file = new FrmCreateFile( | |
| 416 | - array( | |
| 417 | - 'file_name' => FrmStylesController::get_file_name(), | |
| 418 | - 'new_file_path' => FrmAppHelper::plugin_path() . '/css', | |
| 419 | - ) | |
| 420 | - ); | |
| 419 | + $create_file = new FrmCreateFile( self::get_create_style_file_args() ); | |
| 421 | 420 | $create_file->create_file( $css ); |
| 422 | 421 | |
| 423 | 422 | update_option( 'frmpro_css', $css, false ); |
| 424 | 423 | set_transient( 'frmpro_css', $css, MONTH_IN_SECONDS ); |
| 424 | + } | |
| 425 | + | |
| 426 | + /** | |
| 427 | + * @since 6.32 | |
| 428 | + * | |
| 429 | + * @return array | |
| 430 | + */ | |
| 431 | + private static function get_create_style_file_args() { | |
| 432 | + $add_css_to_uploads_dir = self::add_css_to_uploads_dir(); | |
| 433 | + $create_file_args = array( | |
| 434 | + 'file_name' => FrmStylesController::get_file_name(), | |
| 435 | + 'new_file_path' => self::get_generated_css_file_path( $add_css_to_uploads_dir ), | |
| 436 | + ); | |
| 437 | + | |
| 438 | + if ( $add_css_to_uploads_dir ) { | |
| 439 | + $create_file_args['folder_name'] = 'formidable/css'; | |
| 440 | + } | |
| 441 | + | |
| 442 | + return $create_file_args; | |
| 443 | + } | |
| 444 | + | |
| 445 | + /** | |
| 446 | + * @since 6.32 | |
| 447 | + * | |
| 448 | + * @param bool $add_css_to_uploads_dir | |
| 449 | + * | |
| 450 | + * @return string | |
| 451 | + */ | |
| 452 | + public static function get_generated_css_file_path( $add_css_to_uploads_dir ) { | |
| 453 | + if ( $add_css_to_uploads_dir ) { | |
| 454 | + return self::target_css_uploads_dir(); | |
| 455 | + } | |
| 456 | + return self::target_css_plugin_dir(); | |
| 457 | + } | |
| 458 | + | |
| 459 | + /** | |
| 460 | + * Returns true if generated css file should be saved in the uploads directory. | |
| 461 | + * | |
| 462 | + * @since 6.32 | |
| 463 | + * | |
| 464 | + * @return bool | |
| 465 | + */ | |
| 466 | + public static function add_css_to_uploads_dir() { | |
| 467 | + /** | |
| 468 | + * @since 6.32 | |
| 469 | + * | |
| 470 | + * @param bool $add_css_to_uploads_dir | |
| 471 | + */ | |
| 472 | + return apply_filters( 'frm_add_css_to_uploads_dir', ! wp_is_file_mod_allowed( 'frm_save_css_to_plugin_folder' ) ); | |
| 473 | + } | |
| 474 | + | |
| 475 | + /** | |
| 476 | + * @since 6.32 | |
| 477 | + * | |
| 478 | + * @return string | |
| 479 | + */ | |
| 480 | + private static function target_css_uploads_dir() { | |
| 481 | + return wp_upload_dir()['basedir'] . '/formidable/css'; | |
| 482 | + } | |
| 483 | + | |
| 484 | + /** | |
| 485 | + * @since 6.32 | |
| 486 | + * | |
| 487 | + * @return string | |
| 488 | + */ | |
| 489 | + private static function target_css_plugin_dir() { | |
| 490 | + return FrmAppHelper::plugin_path() . '/css'; | |
| 425 | 491 | } |
| 426 | 492 | |
| 427 | 493 | /** |
| 428 | 494 | * @param string $filename |