diff --git a/admin/importers/class-convertkit-admin-importer-convertkit-legacy-forms.php b/admin/importers/class-convertkit-admin-importer-convertkit-legacy-forms.php new file mode 100644 index 000000000..fc491d34a --- /dev/null +++ b/admin/importers/class-convertkit-admin-importer-convertkit-legacy-forms.php @@ -0,0 +1,280 @@ +description = __( 'Kit Legacy Forms are being phased out. Use this tool to replace Kit Form shortcodes and blocks using a Legacy Form with a new Kit Form.', 'convertkit' ); + + // Register this as an importer, if ConvertKit Legacy Forms exist. + add_filter( 'convertkit_get_form_importers', array( $this, 'register' ) ); + + } + + /** + * Returns an array of Kit Legacy Forms form IDs and titles. + * + * @since 3.3.5 + * + * @return array + */ + public function get_forms() { + + // Query resource class to fetch legacy forms. + $forms = array(); + $convertkit_forms = new ConvertKit_Resource_Forms( 'settings' ); + if ( $convertkit_forms->exist() ) { + foreach ( $convertkit_forms->get() as $form ) { + // Skip if not a Legacy Form. + if ( ! $convertkit_forms->is_legacy( $form['id'] ) ) { + continue; + } + + $forms[ $form['id'] ] = $form['name']; + } + } + + return $forms; + + } + + /** + * Returns an array of legacy Kit form IDs (as strings) for use in + * filtering shortcodes/blocks that reference them. + * + * @since 3.3.5 + * + * @return array + */ + private function get_legacy_form_ids() { + + $legacy_ids = array(); + $convertkit_forms = new ConvertKit_Resource_Forms( 'settings' ); + + if ( ! $convertkit_forms->exist() ) { + return $legacy_ids; + } + + foreach ( $convertkit_forms->get() as $form ) { + if ( ! $convertkit_forms->is_legacy( $form['id'] ) ) { + continue; + } + $legacy_ids[] = (string) $form['id']; + } + + return $legacy_ids; + + } + + /** + * Overrides the parent method to: + * - return form IDs found in both shortcodes AND blocks (the parent only + * handles shortcodes), and + * - filter the result so only legacy form IDs are returned. + * + * @since 3.3.5 + * + * @param string $content Content containing Kit Form shortcodes / blocks. + * @return array + */ + public function get_form_ids_from_content( $content ) { + + // Get shortcode-derived form IDs from the parent. + $shortcode_ids = parent::get_form_ids_from_content( $content ); + + // Get block-derived form IDs (parent only handles shortcodes). + $block_ids = $this->get_block_form_ids_from_content( $content ); + + // Combine and filter to legacy form IDs only. + $all_ids = array_unique( array_merge( $shortcode_ids, $block_ids ) ); + $legacy_ids = $this->get_legacy_form_ids(); + + // Cast both sides to strings for safe comparison. + $all_ids = array_map( 'strval', $all_ids ); + + return array_values( array_intersect( $all_ids, $legacy_ids ) ); + + } + + /** + * Returns an array of form IDs from convertkit/form blocks in the given + * content. Walks innerBlocks recursively. + * + * @since 3.3.5 + * + * @param string $content Content containing Kit Form blocks. + * @return array + */ + private function get_block_form_ids_from_content( $content ) { + + return $this->extract_block_form_ids( parse_blocks( $content ) ); + + } + + /** + * Recursively walks blocks (and innerBlocks) and returns an array of form + * IDs from any convertkit/form block's `form` attribute. + * + * @since 3.3.5 + * + * @param array $blocks Blocks. + * @return array + */ + private function extract_block_form_ids( $blocks ) { + + $form_ids = array(); + + // Normalise the block ID attribute(s) to an array so we can match + // against multiple attribute names (e.g. both `form` and `id`). + $id_attributes = (array) $this->block_id_attribute; + + foreach ( $blocks as $block ) { + if ( ! empty( $block['innerBlocks'] ) ) { + $form_ids = array_merge( + $form_ids, + $this->extract_block_form_ids( $block['innerBlocks'] ) + ); + } + + if ( $block['blockName'] !== $this->block_name ) { + continue; + } + + // Record the form ID from the first matching attribute. If a block + // somehow has both `form` and `id` set, they'd be the same value, so + // we stop after the first match to avoid double-counting. + foreach ( $id_attributes as $id_attribute ) { + if ( empty( $block['attrs'][ $id_attribute ] ) ) { + continue; + } + $form_ids[] = (string) $block['attrs'][ $id_attribute ]; + break; + } + } + + return $form_ids; + + } + + /** + * Overrides the parent method to only return post IDs whose content + * contains a Kit Form shortcode or block referencing a legacy form ID. + * + * The parent's broad SQL match returns any post containing a + * `[convertkit_form` shortcode or `