← All changes
|
admin/importers/class-convertkit-admin-importer.php
+117
-40
3.3.1
→
3.4.6
View file →
| @@ -32,8 +32,17 @@ | ||
| 32 | 32 | */ |
| 33 | 33 | public $title = ''; |
| 34 | 34 | |
| 35 | 35 | /** |
| 36 | + * Holds the importer description. | |
| 37 | + * | |
| 38 | + * @since 3.3.5 | |
| 39 | + * | |
| 40 | + * @var string | |
| 41 | + */ | |
| 42 | + public $description = ''; | |
| 43 | + | |
| 44 | + /** | |
| 36 | 45 | * Holds the shortcode name for the third party Form plugin. |
| 37 | 46 | * |
| 38 | 47 | * @since 3.1.0 |
| 39 | 48 | * |
| @@ -41,13 +50,17 @@ | ||
| 41 | 50 | */ |
| 42 | 51 | public $shortcode_name = ''; |
| 43 | 52 | |
| 44 | 53 | /** |
| 45 | - * Holds the shortcode ID attribute name for the third party Form plugin. | |
| 54 | + * Holds the shortcode ID attribute name(s) for the third party Form plugin. | |
| 46 | 55 | * |
| 56 | + * Accepts a string for a single attribute (e.g. 'form'), or an array of | |
| 57 | + * strings for plugins where the form ID may appear under multiple attribute | |
| 58 | + * names (e.g. ['form', 'id']). | |
| 59 | + * | |
| 47 | 60 | * @since 3.1.0 |
| 48 | 61 | * |
| 49 | - * @var bool|string | |
| 62 | + * @var bool|string|array | |
| 50 | 63 | */ |
| 51 | 64 | public $shortcode_id_attribute = false; |
| 52 | 65 | |
| 53 | 66 | /** |
| @@ -59,13 +72,17 @@ | ||
| 59 | 72 | */ |
| 60 | 73 | public $block_name = ''; |
| 61 | 74 | |
| 62 | 75 | /** |
| 63 | - * Holds the block ID attribute name for the third party Form plugin. | |
| 76 | + * Holds the block ID attribute name(s) for the third party Form plugin. | |
| 64 | 77 | * |
| 78 | + * Accepts a string for a single attribute (e.g. 'form'), or an array of | |
| 79 | + * strings for plugins where the form ID may appear under multiple attribute | |
| 80 | + * names (e.g. ['form', 'id']). | |
| 81 | + * | |
| 65 | 82 | * @since 3.1.6 |
| 66 | 83 | * |
| 67 | - * @var bool|string | |
| 84 | + * @var bool|string|array | |
| 68 | 85 | */ |
| 69 | 86 | public $block_id_attribute = false; |
| 70 | 87 | |
| 71 | 88 | /** |
| @@ -98,11 +115,12 @@ | ||
| 98 | 115 | } |
| 99 | 116 | |
| 100 | 117 | // Add this importer to the list of importers. |
| 101 | 118 | $importers[ $this->name ] = array( |
| 102 | - 'name' => $this->name, | |
| 103 | - 'title' => $this->title, | |
| 104 | - 'forms' => $this->get_forms(), | |
| 119 | + 'name' => $this->name, | |
| 120 | + 'title' => $this->title, | |
| 121 | + 'description' => $this->description, | |
| 122 | + 'forms' => $this->get_forms(), | |
| 105 | 123 | ); |
| 106 | 124 | |
| 107 | 125 | return $importers; |
| 108 | 126 | |
| @@ -243,8 +261,11 @@ | ||
| 243 | 261 | |
| 244 | 262 | // Replace the third party Form Shortcode with the Kit Form Shortcode. |
| 245 | 263 | $post_content = $this->replace_shortcodes_in_content( $post_content, $third_party_form_id, $form_id ); |
| 246 | 264 | |
| 265 | + // Double escape backslashes so that wp_update_post doesn't remove them. | |
| 266 | + $post_content = str_replace( '\\', '\\\\', $post_content ); | |
| 267 | + | |
| 247 | 268 | // Update the Post content. |
| 248 | 269 | wp_update_post( |
| 249 | 270 | array( |
| 250 | 271 | 'ID' => $post_id, |
| @@ -274,24 +295,41 @@ | ||
| 274 | 295 | // If there's no shortcode ID attribute, match shortcodes with or without any attribute. |
| 275 | 296 | if ( ! $this->shortcode_id_attribute ) { |
| 276 | 297 | $pattern = '/\[' // Start regex with an opening square bracket. |
| 277 | 298 | . preg_quote( $this->shortcode_name, '/' ) // Match the shortcode name, escaping any regex special chars. |
| 299 | + . '(?=[\s\]\/])' // Ensure the shortcode name is complete, so e.g. [name_other] isn't matched. | |
| 278 | 300 | . '[^\]]*?\]/i'; // Match any other characters (non-greedy) up to the closing square bracket, case-insensitive. |
| 279 | - } else { | |
| 301 | + | |
| 302 | + return preg_replace( | |
| 303 | + $pattern, | |
| 304 | + '[convertkit_form form="' . $form_id . '"]', | |
| 305 | + $content | |
| 306 | + ); | |
| 307 | + } | |
| 308 | + | |
| 309 | + // Normalise the shortcode ID attribute to an array, so importers can | |
| 310 | + // declare a single attribute (string) or multiple attributes (array). | |
| 311 | + $id_attributes = (array) $this->shortcode_id_attribute; | |
| 312 | + | |
| 313 | + // Run a replacement pass per attribute name. | |
| 314 | + foreach ( $id_attributes as $id_attribute ) { | |
| 280 | 315 | $pattern = '/\[' // Start regex with an opening square bracket. |
| 281 | 316 | . preg_quote( $this->shortcode_name, '/' ) // Match the shortcode name, escaping any regex special chars. |
| 317 | + . '(?=[\s\]\/])' // Ensure the shortcode name is complete, so e.g. [name_other] isn't matched. | |
| 282 | 318 | . '[^\]]*?' // Match any characters that are not a closing square bracket, non-greedy. |
| 283 | - . '\b' . preg_quote( $this->shortcode_id_attribute, '/' ) // Match the id attribute word boundary and escape as needed. | |
| 319 | + . '\s' . preg_quote( $id_attribute, '/' ) // Match the id attribute, preceded by whitespace so e.g. data-id isn't matched. | |
| 284 | 320 | . '\s*=\s*' // Match optional whitespace around an equals sign. |
| 285 | - . '(?:"' . preg_quote( (string) $third_party_form_id, '/' ) . '"|\'' . preg_quote( (string) $third_party_form_id, '/' ) . '\'|' . preg_quote( (string) $third_party_form_id, '/' ) . ')' // Match the form ID, double quotes, single quotes or unquoted. | |
| 321 | + . '(?:"' . preg_quote( (string) $third_party_form_id, '/' ) . '"|\'' . preg_quote( (string) $third_party_form_id, '/' ) . '\'|' . preg_quote( (string) $third_party_form_id, '/' ) . '(?=[\s\]\/]))' // Match the exact form ID, double quotes, single quotes or unquoted. | |
| 286 | 322 | . '[^\]]*?\]/i'; // Match any other characters (non-greedy) up to the closing square bracket, case-insensitive. |
| 323 | + | |
| 324 | + $content = preg_replace( | |
| 325 | + $pattern, | |
| 326 | + '[convertkit_form form="' . $form_id . '"]', | |
| 327 | + $content | |
| 328 | + ); | |
| 287 | 329 | } |
| 288 | 330 | |
| 289 | - return preg_replace( | |
| 290 | - $pattern, | |
| 291 | - '[convertkit_form id="' . $form_id . '"]', | |
| 292 | - $content | |
| 293 | - ); | |
| 331 | + return $content; | |
| 294 | 332 | |
| 295 | 333 | } |
| 296 | 334 | |
| 297 | 335 | /** |
| @@ -345,8 +383,9 @@ | ||
| 345 | 383 | // If there's no shortcode ID attribute, match shortcodes with or without any attribute and treat any match as a single "form". |
| 346 | 384 | if ( ! $this->shortcode_id_attribute ) { |
| 347 | 385 | $pattern = '/\[' // Start regex with an opening square bracket. |
| 348 | 386 | . preg_quote( $this->shortcode_name, '/' ) // Match the shortcode name, escaping any regex special chars. |
| 387 | + . '(?=[\s\]\/])' // Ensure the shortcode name is complete, so e.g. [name_other] isn't matched. | |
| 349 | 388 | . '(?:\s+[^\]]*)?' // Optionally match any attributes (key/value pairs), non-greedy. |
| 350 | 389 | . '[^\]]*?\]/i'; // Match up to closing bracket, case-insensitive. |
| 351 | 390 | |
| 352 | 391 | preg_match_all( $pattern, $content, $matches ); |
| @@ -358,31 +397,40 @@ | ||
| 358 | 397 | |
| 359 | 398 | return array(); |
| 360 | 399 | } |
| 361 | 400 | |
| 362 | - // Legacy: Extract where attribute is required. | |
| 363 | - $pattern = '/\[' // Start regex with an opening square bracket. | |
| 364 | - . preg_quote( $this->shortcode_name, '/' ) // Match the shortcode name, escaping any regex special chars. | |
| 365 | - . '(?:\s+[^\]]*)?' // Optionally match any attributes (key/value pairs), non-greedy. | |
| 366 | - . preg_quote( $this->shortcode_id_attribute, '/' ) // Match the id attribute name. | |
| 367 | - . '\s*=\s*' // Optional whitespace, equals sign, optional whitespace. | |
| 368 | - . '(?:"([^"]+)"|\'([^\']+)\'|([^\s\]]+))' // Capture double quoted, single quoted or unquoted value. | |
| 369 | - . '[^\]]*?\]/i'; // Match up to closing bracket, case-insensitive. | |
| 401 | + // Normalise the shortcode ID attribute to an array, so importers can | |
| 402 | + // declare a single attribute (string) or multiple attributes (array). | |
| 403 | + $id_attributes = (array) $this->shortcode_id_attribute; | |
| 370 | 404 | |
| 371 | - preg_match_all( $pattern, $content, $matches ); | |
| 405 | + // Extract form IDs, running a match pass per attribute name. | |
| 406 | + $form_ids = array(); | |
| 407 | + foreach ( $id_attributes as $id_attribute ) { | |
| 408 | + $pattern = '/\[' // Start regex with an opening square bracket. | |
| 409 | + . preg_quote( $this->shortcode_name, '/' ) // Match the shortcode name, escaping any regex special chars. | |
| 410 | + . '(?=[\s\]\/])' // Ensure the shortcode name is complete, so e.g. [name_other] isn't matched. | |
| 411 | + . '(?:\s+[^\]]*)?' // Optionally match any attributes (key/value pairs), non-greedy. | |
| 412 | + . preg_quote( $id_attribute, '/' ) // Match the id attribute name. | |
| 413 | + . '\s*=\s*' // Optional whitespace, equals sign, optional whitespace. | |
| 414 | + . '(?:"([^"]+)"|\'([^\']+)\'|([^\s\]]+))' // Capture double quoted, single quoted or unquoted value. | |
| 415 | + . '[^\]]*?\]/i'; // Match up to closing bracket, case-insensitive. | |
| 372 | 416 | |
| 373 | - // Extract form IDs: They could be in either $matches[1] (double quoted), $matches[2] (single quoted) or $matches[3] (unquoted). | |
| 374 | - $form_ids = array_values( | |
| 375 | - array_filter( | |
| 376 | - array_merge( | |
| 377 | - isset( $matches[1] ) ? $matches[1] : array(), | |
| 378 | - isset( $matches[2] ) ? $matches[2] : array(), | |
| 379 | - isset( $matches[3] ) ? $matches[3] : array() | |
| 417 | + preg_match_all( $pattern, $content, $matches ); | |
| 418 | + | |
| 419 | + // Extract form IDs: They could be in either $matches[1] (double quoted), $matches[2] (single quoted) or $matches[3] (unquoted). | |
| 420 | + $form_ids = array_merge( | |
| 421 | + $form_ids, | |
| 422 | + array_filter( | |
| 423 | + array_merge( | |
| 424 | + isset( $matches[1] ) ? $matches[1] : array(), | |
| 425 | + isset( $matches[2] ) ? $matches[2] : array(), | |
| 426 | + isset( $matches[3] ) ? $matches[3] : array() | |
| 427 | + ) | |
| 380 | 428 | ) |
| 381 | - ) | |
| 382 | - ); | |
| 429 | + ); | |
| 430 | + } | |
| 383 | 431 | |
| 384 | - return $form_ids; | |
| 432 | + return array_values( array_unique( $form_ids ) ); | |
| 385 | 433 | |
| 386 | 434 | } |
| 387 | 435 | |
| 388 | 436 | /** |
| @@ -496,9 +544,9 @@ | ||
| 496 | 544 | continue; |
| 497 | 545 | } |
| 498 | 546 | |
| 499 | 547 | // Skip if not a third party form block. |
| 500 | - if ( strpos( $block['blockName'], $this->block_name ) === false ) { | |
| 548 | + if ( $block['blockName'] !== $this->block_name ) { | |
| 501 | 549 | continue; |
| 502 | 550 | } |
| 503 | 551 | |
| 504 | 552 | // If the block ID attribute is not set, the third party Plugin doesn't use IDs, |
| @@ -503,15 +551,29 @@ | ||
| 503 | 551 | |
| 504 | 552 | // If the block ID attribute is not set, the third party Plugin doesn't use IDs, |
| 505 | 553 | // so there's no need to check the $third_party_form_id matches the block attribute. |
| 506 | 554 | if ( $this->block_id_attribute ) { |
| 507 | - // Skip if the attribute doesn't exist i.e. the block was not configured. | |
| 508 | - if ( ! array_key_exists( $this->block_id_attribute, $block['attrs'] ) ) { | |
| 509 | - continue; | |
| 555 | + // Normalise the block ID attribute to an array, so importers can | |
| 556 | + // declare a single attribute (string) or multiple attributes (array). | |
| 557 | + $id_attributes = (array) $this->block_id_attribute; | |
| 558 | + | |
| 559 | + // Check if at least one attribute contains the third party form ID. | |
| 560 | + $matched = false; | |
| 561 | + foreach ( $id_attributes as $id_attribute ) { | |
| 562 | + if ( ! array_key_exists( $id_attribute, $block['attrs'] ) ) { | |
| 563 | + continue; | |
| 564 | + } | |
| 565 | + | |
| 566 | + if ( ! $this->block_id_attribute_matches( $block['attrs'][ $id_attribute ], $third_party_form_id ) ) { | |
| 567 | + continue; | |
| 568 | + } | |
| 569 | + | |
| 570 | + $matched = true; | |
| 571 | + break; | |
| 510 | 572 | } |
| 511 | 573 | |
| 512 | - // Skip if the third party form ID doesn't exist within the third party form block's attribute. | |
| 513 | - if ( stripos( $block['attrs'][ $this->block_id_attribute ], (string) $third_party_form_id ) === false ) { | |
| 574 | + // Skip if none of the configured ID attributes match. | |
| 575 | + if ( ! $matched ) { | |
| 514 | 576 | continue; |
| 515 | 577 | } |
| 516 | 578 | } |
| 517 | 579 | |
| @@ -527,8 +589,23 @@ | ||
| 527 | 589 | ); |
| 528 | 590 | } |
| 529 | 591 | |
| 530 | 592 | return $blocks; |
| 593 | + | |
| 594 | + } | |
| 595 | + | |
| 596 | + /** | |
| 597 | + * Returns whether the given block ID attribute value matches the third party form ID. | |
| 598 | + * | |
| 599 | + * @since 3.4.5 | |
| 600 | + * | |
| 601 | + * @param mixed $value Block ID attribute value. | |
| 602 | + * @param string|int $third_party_form_id Third Party Form ID. | |
| 603 | + * @return bool | |
| 604 | + */ | |
| 605 | + protected function block_id_attribute_matches( $value, $third_party_form_id ) { | |
| 606 | + | |
| 607 | + return (string) $value === (string) $third_party_form_id; | |
| 531 | 608 | |
| 532 | 609 | } |
| 533 | 610 | |
| 534 | 611 | } |