Plugin Directory

Changeset 3731157


Ignore:
Timestamp:
10/06/2026 03:42:54 PM (3 weeks ago)
Author:
carlosbanyuls
Message:

Release 1.0.25: fix category pillar same-slug URLs

Location:
honoko-core/trunk
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • honoko-core/trunk/README.md

    r3727887 r3731157  
    1 # HONOKO Core 1.0.24
     1# HONOKO Core 1.0.25
    22
    33Persistent visual Builder, pillar pages, content clusters and SEO tools for HONOKO.
    4 
    5 HONOKO Core can be used with third-party WordPress themes. HONOKO Theme remains the optional presentation layer designed for the complete HONOKO experience.
    64
    75This package is the WordPress.org-ready free Core component. It uses the `honoko_` public namespace and contains no premium implementation code.
    … …  
    97## Resources
    108
    11 Official website and HONOKO Theme: https://honokotheme.com/ 
    129HONOKO Builder icon artwork, Copyright 2026 Carlos Banyuls. 
    13 License: GPL-2.0-or-later.
     10License: GPL-2.0-or-later. 
     11Source: https://honokotheme.com/
  • honoko-core/trunk/honoko-core.php

    r3727887 r3731157  
    44 * Plugin URI: https://honokotheme.com/
    55 * Description: Persistent visual Builder, pillar pages, content clusters and SEO tools for HONOKO.
    6  * Version: 1.0.24
     6 * Version: 1.0.25
    77 * Requires at least: 6.4
    88 * Requires PHP: 7.4
    … …  
    1414 */
    1515if ( ! defined( 'ABSPATH' ) ) exit;
    16 define( 'HONOKO_CORE_VERSION', '1.0.24' );
     16define( 'HONOKO_CORE_VERSION', '1.0.25' );
    1717define( 'HONOKO_CORE_DIR', plugin_dir_path( __FILE__ ) );
    1818define( 'HONOKO_CORE_URI', plugin_dir_url( __FILE__ ) );
  • honoko-core/trunk/inc/clusters.php

    r3725229 r3731157  
    3737    return ( $term && ! is_wp_error( $term ) ) ? $term : null;
    3838}
     39
     40
     41/**
     42 * HONOKO pillar pages intentionally share the category slug.
     43 *
     44 * WordPress itself normally allows a Page and a category to use the same slug,
     45 * but no-category-base/permalink plugins can mark category slugs as invalid
     46 * hierarchical post slugs. In that situation WordPress silently changes a
     47 * pillar such as /trabajos/ to /trabajos-2/. HONOKO owns that collision on
     48 * purpose and its request routing below resolves /trabajos/ to the pillar Page.
     49 *
     50 * Short-circuit WordPress slug uniquing only for root Pages whose requested
     51 * slug matches a real category and only when another non-trashed root Page is
     52 * not already using that slug.
     53 */
     54function honoko_pillar_page_slug_conflict( $slug, $post_id = 0 ) {
     55    $existing = get_page_by_path( sanitize_title( $slug ), OBJECT, 'page' );
     56    if ( ! $existing || (int) $existing->ID === (int) $post_id ) return false;
     57    if ( (int) $existing->post_parent !== 0 ) return false;
     58    return ! in_array( $existing->post_status, array( 'trash', 'auto-draft' ), true );
     59}
     60
     61function honoko_pillar_preserve_category_slug( $override_slug, $slug, $post_id, $post_status, $post_type, $post_parent ) {
     62    if ( 'page' !== $post_type || (int) $post_parent !== 0 ) return $override_slug;
     63    if ( function_exists( 'honoko_seo_pillar_same_slug_enabled' ) && ! honoko_seo_pillar_same_slug_enabled() ) return $override_slug;
     64
     65    $slug = sanitize_title( $slug );
     66    if ( '' === $slug ) return $override_slug;
     67
     68    $term = get_term_by( 'slug', $slug, 'category' );
     69    if ( ! ( $term instanceof WP_Term ) ) return $override_slug;
     70    if ( honoko_pillar_page_slug_conflict( $slug, $post_id ) ) return $override_slug;
     71
     72    return $slug;
     73}
     74add_filter( 'pre_wp_unique_post_slug', 'honoko_pillar_preserve_category_slug', 999, 6 );
     75
     76/**
     77 * Persist the automatic same-slug relationship once the Page is saved.
     78 * Explicit term/page mappings keep priority and are never replaced by another
     79 * Page merely because it happens to use the same slug.
     80 */
     81function honoko_pillar_sync_same_slug_mapping( $post_id, $post, $update ) {
     82    unset( $update );
     83    if ( ! ( $post instanceof WP_Post ) || 'page' !== $post->post_type ) return;
     84    if ( wp_is_post_revision( $post_id ) || wp_is_post_autosave( $post_id ) ) return;
     85    if ( (int) $post->post_parent !== 0 || in_array( $post->post_status, array( 'trash', 'auto-draft' ), true ) ) return;
     86    if ( function_exists( 'honoko_seo_pillar_same_slug_enabled' ) && ! honoko_seo_pillar_same_slug_enabled() ) return;
     87
     88    $term = get_term_by( 'slug', $post->post_name, 'category' );
     89    if ( ! ( $term instanceof WP_Term ) ) return;
     90
     91    $mapped_page = absint( get_term_meta( $term->term_id, '_honoko_pillar_page_id', true ) );
     92    if ( $mapped_page && $mapped_page !== (int) $post_id ) {
     93        $mapped_status = get_post_status( $mapped_page );
     94        if ( $mapped_status && ! in_array( $mapped_status, array( 'trash', 'auto-draft' ), true ) ) return;
     95    }
     96
     97    update_post_meta( $post_id, '_honoko_pillar_taxonomy', 'category' );
     98    update_post_meta( $post_id, '_honoko_pillar_term_id', (int) $term->term_id );
     99    update_term_meta( $term->term_id, '_honoko_pillar_page_id', (int) $post_id );
     100}
     101add_action( 'save_post_page', 'honoko_pillar_sync_same_slug_mapping', 20, 3 );
    39102
    40103function honoko_pillar_url_for_term( $term ) {
    … …  
    387450}, 10, 2 );
    388451add_filter( 'wp_insert_post_data', function( $data, $postarr ) {
     452    if ( ! is_admin() || ( $data['post_type'] ?? '' ) !== 'page' || ! empty( $data['post_parent'] ) ) return $data;
     453
     454    $post_id = absint( $postarr['ID'] ?? 0 );
    389455    $term_id = honoko_pillar_request_term_id();
    390     if ( is_admin() && $data['post_type'] === 'page' && $term_id && empty( $data['post_name'] ) ) {
     456    $target_slug = '';
     457
     458    // New pillar opened from HONOKO -> Pillars & clusters.
     459    if ( $term_id ) {
    391460        $term = get_term( $term_id, 'category' );
    392         if ( $term && ! is_wp_error( $term ) ) $data['post_name'] = $term->slug;
    393     }
     461        if ( $term && ! is_wp_error( $term ) ) $target_slug = sanitize_title( $term->slug );
     462    }
     463
     464    // Existing pillar affected by a no-category-base/permalink rule may already
     465    // have been changed to slug-2. Restore the category slug when the Page title
     466    // still identifies the same pillar and no real Page collision exists.
     467    if ( '' === $target_slug ) {
     468        $current_slug = sanitize_title( $data['post_name'] ?? '' );
     469        if ( preg_match( '/^(.+)-(\\d+)$/', $current_slug, $matches ) ) {
     470            $base_slug = sanitize_title( $matches[1] );
     471            $term = get_term_by( 'slug', $base_slug, 'category' );
     472            $title_matches = sanitize_title( $data['post_title'] ?? '' ) === $base_slug;
     473            $cluster_matches = false;
     474            if ( ! empty( $data['post_content'] ) ) {
     475                $cluster_matches = false !== strpos( (string) $data['post_content'], 'category="' . $base_slug . '"' )
     476                    || false !== strpos( (string) $data['post_content'], "category='" . $base_slug . "'" );
     477            }
     478            if ( $term instanceof WP_Term && ( $title_matches || $cluster_matches ) ) $target_slug = $base_slug;
     479        }
     480    }
     481
     482    if ( '' !== $target_slug && ! honoko_pillar_page_slug_conflict( $target_slug, $post_id ) ) {
     483        $data['post_name'] = $target_slug;
     484    }
     485
    394486    return $data;
    395487}, 10, 2 );
  • honoko-core/trunk/readme.txt

    r3727887 r3731157  
    55Tested up to: 7.1
    66Requires PHP: 7.4
    7 Stable tag: 1.0.24
     7Stable tag: 1.0.25
    88License: GPLv2 or later
    99License URI: https://www.gnu.org/licenses/gpl-2.0.html
    1010
    11 A visual content builder with pillar pages, content clusters and SEO tools. Pair it with HONOKO Theme for the complete experience.
     11A visual content builder with pillar pages, content clusters, and SEO tools.
    1212
    1313== Description ==
    … …  
    1515HONOKO Core keeps persistent content functionality separate from presentation. It provides the free HONOKO Builder, Frontend Builder, pillar-page mapping, content clusters, SEO metadata, Schema markup, XML sitemap generation and the free HONOKO block set.
    1616
    17 HONOKO Builder works independently with third-party WordPress themes. Install HONOKO Core on your existing WordPress site and use HONOKO Builder to build pages with rows, columns and blocks without changing your current theme.
    18 
    19 **Get the complete HONOKO experience with HONOKO Theme.**
    20 
    21 HONOKO Theme is designed specifically for HONOKO Core and provides the intended visual presentation and Builder workflow.
    22 
    23 [Download HONOKO Theme from the official website](https://honokotheme.com/)
    24 
    25 The plugin can remain active when you change themes, so Builder content and SEO data are not tied to a specific presentation layer. HONOKO Core can also be used with third-party WordPress themes.
     17The plugin can remain active when you change themes, so Builder content and SEO data are not tied to a specific presentation layer.
    2618
    2719HONOKO Core is fully functional without HONOKO Pro. An optional premium add-on is available separately and is not included in this plugin.
    … …  
    3325= Do I need the HONOKO theme? =
    3426
    35 No. HONOKO Core also works with third-party WordPress themes and keeps its persistent content features available when you change themes.
    36 
    37 For the intended HONOKO visual presentation and complete Builder workflow, use the free HONOKO Theme:
    38 
    39 [Get HONOKO Theme](https://honokotheme.com/)
     27No. Core keeps its persistent content features available when another theme is active. The HONOKO theme provides the intended visual presentation.
    4028
    4129= Does Core send site content to HONOKO servers? =
    … …  
    4836
    4937== Changelog ==
     38
     39= 1.0.25 =
     40* Keeps category pillar pages on the exact category slug when no-category-base or permalink rules would otherwise append a numeric suffix such as `-2`.
     41* Automatically syncs the category and Page mapping after a same-slug pillar is saved.
     42* Repairs an existing suffixed pillar slug on the next save when its title or HONOKO cluster block clearly matches the category.
    5043
    5144= 1.0.24 =
    … …  
    8477* Uses an English source msgid for the Quote block so English installations no longer see a Spanish label.
    8578
     79
    8680= 1.0.17 =
    8781* Removed the auxiliary SOURCE.md file from the production package; source-code/build documentation remains in readme.txt.
    … …  
    118112== Upgrade Notice ==
    119113
     114= 1.0.25 =
     115Fixes same-slug category pillar URLs so HONOKO can keep `/category-slug/` instead of WordPress changing the Page to `/category-slug-2/`.
     116
    120117= 1.0.24 =
    121118Keeps each post in HONOKO Builder after choosing Builder on third-party themes, until the WordPress editor is explicitly selected.
    … …  
    142139== Resources ==
    143140
    144 Official HONOKO website and HONOKO Theme:
    145 https://honokotheme.com/
    146 
    147141HONOKO Builder icon artwork, Copyright 2026 Carlos Banyuls.
    148142License: GPL-2.0-or-later.
     143Source: https://honokotheme.com/
Note: See TracChangeset for help on using the changeset viewer.