diff --git a/components/footer/variation-default.php b/components/footer/variation-default.php
index 8977067f..9fb3354b 100644
--- a/components/footer/variation-default.php
+++ b/components/footer/variation-default.php
@@ -28,11 +28,9 @@
-
-
diff --git a/footer.php b/footer.php
index 2baaef17..d57eeacd 100644
--- a/footer.php
+++ b/footer.php
@@ -16,11 +16,23 @@
'absint',
+ 'choices' => array( '2' => '2', '3' => '3', '4' => '4', '6' => '6' ),
+ ) );
+
// FOOTER: Copyright Text ===============
self::add_memberlite_setting_control( $wp_customize, 'copyright_textbox', __( 'Copyright Text', 'memberlite' ), 'memberlite_footer_options', array(
'transport' => 'postMessage',
'sanitize_callback' => array( 'Memberlite_Customize', 'sanitize_text_with_links' ),
'sanitize_js_callback' => array( 'Memberlite_Customize', 'sanitize_js_text_with_links' ),
) );
+
+ // FOOTER: Pattern Footer Heading ========
+ self::add_memberlite_heading( $wp_customize, 'memberlite_pattern_footer_heading', __( 'Variation Settings', 'memberlite' ), 'memberlite_footer_options' );
+
+ // FOOTER: Footer CPT ===================
+ $footer_choices = memberlite_get_footer_variations();
+
+ // FOOTER: Variations, Global ===============
+ self::add_memberlite_setting_control( $wp_customize, 'memberlite_default_footer_slug', __( 'Default Footer', 'memberlite' ), 'memberlite_footer_options', array(
+ 'type' => 'select',
+ 'sanitize_callback' => 'sanitize_key',
+ 'choices' => $footer_choices,
+ 'default' => '0',
+ 'description' => __( 'Choose which footer pattern to display all across the site.', 'memberlite' ),
+ ) );
+
+ // FOOTER: Variations, Blog & Archives ===============
+ self::add_memberlite_setting_control( $wp_customize, 'memberlite_archives_footer_slug', __( 'Blog & Archives Footer', 'memberlite' ), 'memberlite_footer_options', array(
+ 'type' => 'select',
+ 'sanitize_callback' => 'sanitize_key',
+ 'choices' => $footer_choices,
+ 'default' => '0',
+ 'description' => __( 'Choose which footer pattern to display on your blog and post archives.', 'memberlite' ),
+ ) );
+
+ // FOOTER: Variations, Single Post ===============
+ self::add_memberlite_setting_control( $wp_customize, 'memberlite_post_footer_slug', __( 'Single Post Footer', 'memberlite' ), 'memberlite_footer_options', array(
+ 'type' => 'select',
+ 'sanitize_callback' => 'sanitize_key',
+ 'choices' => $footer_choices,
+ 'default' => '0',
+ 'description' => __( 'Choose which footer pattern to display on the single post view.', 'memberlite' ),
+ ) );
+
+ // FOOTER: Variations, Pages ===============
+ self::add_memberlite_setting_control( $wp_customize, 'memberlite_page_footer_slug', __( 'Pages Footer', 'memberlite' ), 'memberlite_footer_options', array(
+ 'type' => 'select',
+ 'sanitize_callback' => 'sanitize_key',
+ 'choices' => $footer_choices,
+ 'default' => '0',
+ 'description' => __( 'Choose which footer pattern to display on your pages.', 'memberlite' ),
+ ) );
}
/**
diff --git a/inc/editor-settings.php b/inc/editor-settings.php
index e2cd0dae..6cff52f0 100644
--- a/inc/editor-settings.php
+++ b/inc/editor-settings.php
@@ -36,6 +36,18 @@ function memberlite_register_editor_settings_post_meta(): void {
}
) );
+ register_post_meta( 'page', '_memberlite_footer_override', array(
+ 'show_in_rest' => true,
+ 'type' => 'string',
+ 'single' => true,
+ 'default' => '',
+ 'label' => __( 'Select Footer', 'memberlite' ),
+ 'sanitize_callback' => 'sanitize_key',
+ 'auth_callback' => function() {
+ return current_user_can( 'edit_posts' );
+ }
+ ) );
+
register_post_meta( 'page', '_memberlite_hide_page_nav', array(
'show_in_rest' => true,
'single' => true,
@@ -76,10 +88,15 @@ function memberlite_enqueue_custom_editor_assets(): void {
true
);
- // Get existing theme mods that we're moving into the settings
- wp_localize_script( 'memberlite-custom-settings', 'memberlite_theme_mod_settings', array(
- 'showPrevNextSinglePages' => get_theme_mod( 'memberlite_page_nav', true )
- ) );
+ // Get existing theme mods, and get footer variations to populate the footer override setting
+ wp_localize_script(
+ 'memberlite-custom-settings',
+ 'memberliteEditorData',
+ array(
+ 'showPrevNextSinglePages' => get_theme_mod( 'memberlite_page_nav', true ),
+ 'footerVariations' => memberlite_get_footer_variations(),
+ )
+ );
}
add_action( 'enqueue_block_editor_assets', 'memberlite_enqueue_custom_editor_assets' );
diff --git a/inc/variations.php b/inc/variations.php
index dc5b3e45..901bd3b2 100644
--- a/inc/variations.php
+++ b/inc/variations.php
@@ -7,15 +7,86 @@
* @since 7.0
*/
+/*
+ * Checks location-specific theme_mods first (single post, page, archives),
+ * then falls back to the global default footer setting.
+ *
+ * @since TBD
+ *
+ * @return string post_name of the memberlite_footer post, or '0' if none is set.
+ */
+function memberlite_get_current_footer_post_name() {
+ // Per-page override takes priority over all Customizer settings.
+ if ( is_singular() ) {
+ $override = get_post_meta( get_the_ID(), '_memberlite_footer_override', true );
+ if ( '' !== $override ) {
+ return $override;
+ }
+ }
+
+ $post_name = '0';
+
+ if ( is_singular( 'post' ) ) {
+ $post_name = get_theme_mod( 'memberlite_post_footer_slug', '0' );
+ } elseif ( is_page() ) {
+ $post_name = get_theme_mod( 'memberlite_page_footer_slug', '0' );
+ } elseif ( is_archive() || is_home() ) {
+ $post_name = get_theme_mod( 'memberlite_archives_footer_slug', '0' );
+ }
+
+ // Fall back to the global default if the context-specific setting is unset.
+ if ( empty( $post_name ) || '0' === $post_name ) {
+ $post_name = get_theme_mod( 'memberlite_default_footer_slug', '0' );
+ }
+
+ return $post_name;
+}
+
/**
- * Get the current variation for a given slug.
+ * Render a footer variation.
*
- * @since 7.0
+ * Looks up the memberlite_footer CPT post by post_name (as stored in the
+ * theme_mod) and renders its block content. Does nothing if the post is not
+ * found; the legacy footer fallback is handled upstream in footer.php.
*
- * @param string $slug The slug for the variation type (e.g., 'footer').
- * @return string The current variation slug, or 'default' if not set.
+ * @since TBD
+ * @param string $post_name The post_name of the memberlite_footer post to render.
*/
-function memberlite_get_variation( $slug ) {
- $variation = get_theme_mod( "memberlite_{$slug}_variation", 'default' );
- return ( empty( $variation ) ) ? 'default' : $variation;
+function memberlite_render_footer_variation( $post_name ) {
+ if ( ! empty( $post_name ) && '0' !== $post_name ) {
+ $footer_post = get_page_by_path( $post_name, OBJECT, 'memberlite_footer' );
+
+ if ( $footer_post ) {
+ echo do_blocks( $footer_post->post_content ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
+ }
+ }
+}
+
+/**
+ * Get memberlite_footer posts for our variation options
+ *
+ * @since TBD
+ *
+ * @return array
+ */
+function memberlite_get_footer_variations(): array {
+ $footer_posts = get_posts( array(
+ 'post_type' => 'memberlite_footer',
+ 'post_status' => 'publish',
+ 'posts_per_page' => -1,
+ 'orderby' => 'title',
+ 'order' => 'ASC',
+ ) );
+
+ $footer_choices = array(
+ '0' => __( '— Use legacy footer —', 'memberlite' ),
+ );
+
+ if ( ! empty( $footer_posts ) ) {
+ foreach ( $footer_posts as $footer_post ) {
+ $footer_choices[ $footer_post->post_name ] = $footer_post->post_title;
+ }
+ }
+
+ return $footer_choices;
}
diff --git a/patterns/footer-01.php b/patterns/footer-01.php
index f57285c5..2eecde25 100644
--- a/patterns/footer-01.php
+++ b/patterns/footer-01.php
@@ -5,17 +5,18 @@
* Description: Footer with two rows, 4 columns on top of 2.
* Categories: memberlite-footer, footer
* Keywords: footer, variation
+ * Post Types: memberlite_footer
* @package WordPress
* @subpackage Memberlite
* @since TBD
*/
?>
-
-