Changeset 3332124
- Timestamp:
- 07/22/2025 09:35:24 AM (8 months ago)
- Location:
- custom-permalinks
- Files:
-
- 12 added
- 4 deleted
- 20 edited
- 1 copied
-
tags/3.0.0 (copied) (copied from custom-permalinks/trunk)
-
tags/3.0.0/admin/class-custom-permalinks-admin.php (modified) (4 diffs)
-
tags/3.0.0/admin/class-custom-permalinks-post-types-settings.php (added)
-
tags/3.0.0/admin/class-custom-permalinks-post-types.php (modified) (4 diffs)
-
tags/3.0.0/admin/class-custom-permalinks-taxonomies.php (modified) (4 diffs)
-
tags/3.0.0/assets/css/about-plugins-2.8.0.min.css (deleted)
-
tags/3.0.0/assets/css/about-plugins-3.0.0.min.css (added)
-
tags/3.0.0/assets/css/post-settings-3.0.0.min.css (added)
-
tags/3.0.0/assets/js/post-settings-3.0.0.min.js (added)
-
tags/3.0.0/assets/js/script-form-2.8.0.min.js (deleted)
-
tags/3.0.0/assets/js/script-form-3.0.0.min.js (added)
-
tags/3.0.0/changelog.txt (modified) (1 diff)
-
tags/3.0.0/custom-permalinks.php (modified) (1 diff)
-
tags/3.0.0/includes/class-custom-permalinks-form.php (modified) (12 diffs)
-
tags/3.0.0/includes/class-custom-permalinks-frontend.php (modified) (8 diffs)
-
tags/3.0.0/includes/class-custom-permalinks-generate-post-permalinks.php (added)
-
tags/3.0.0/includes/class-custom-permalinks.php (modified) (4 diffs)
-
tags/3.0.0/readme.txt (modified) (1 diff)
-
tags/3.0.0/uninstall.php (modified) (3 diffs)
-
trunk/admin/class-custom-permalinks-admin.php (modified) (4 diffs)
-
trunk/admin/class-custom-permalinks-post-types-settings.php (added)
-
trunk/admin/class-custom-permalinks-post-types.php (modified) (4 diffs)
-
trunk/admin/class-custom-permalinks-taxonomies.php (modified) (4 diffs)
-
trunk/assets/css/about-plugins-2.8.0.min.css (deleted)
-
trunk/assets/css/about-plugins-3.0.0.min.css (added)
-
trunk/assets/css/post-settings-3.0.0.min.css (added)
-
trunk/assets/js/post-settings-3.0.0.min.js (added)
-
trunk/assets/js/script-form-2.8.0.min.js (deleted)
-
trunk/assets/js/script-form-3.0.0.min.js (added)
-
trunk/changelog.txt (modified) (1 diff)
-
trunk/custom-permalinks.php (modified) (1 diff)
-
trunk/includes/class-custom-permalinks-form.php (modified) (12 diffs)
-
trunk/includes/class-custom-permalinks-frontend.php (modified) (8 diffs)
-
trunk/includes/class-custom-permalinks-generate-post-permalinks.php (added)
-
trunk/includes/class-custom-permalinks.php (modified) (4 diffs)
-
trunk/readme.txt (modified) (1 diff)
-
trunk/uninstall.php (modified) (3 diffs)
Legend:
- Unmodified
- Added
- Removed
-
custom-permalinks/tags/3.0.0/admin/class-custom-permalinks-admin.php
r3138206 r3332124 22 22 23 23 /** 24 * JS file suffix extension. 25 * 26 * @var string 27 */ 28 private $js_file_suffix = '.min.js'; 29 30 /** 24 31 * Initializes WordPress hooks. 25 32 */ 26 33 public function __construct() { 27 34 /* 28 * C ssfile suffix (version number with extension).35 * CSS file suffix (version number with extension). 29 36 */ 30 37 $this->css_file_suffix = '-' . CUSTOM_PERMALINKS_VERSION . '.min.css'; 38 39 /* 40 * JS file suffix (version number with extension). 41 */ 42 $this->js_file_suffix = '-' . CUSTOM_PERMALINKS_VERSION . '.min.js'; 31 43 32 44 add_action( 'admin_init', array( $this, 'privacy_policy' ) ); … … 73 85 array( $this, 'taxonomy_permalinks_page' ) 74 86 ); 87 $post_settings_page = add_submenu_page( 88 'cp-post-permalinks', 89 __( 'Post Types Settings', 'custom-permalinks' ), 90 __( 'Post Types Settings', 'custom-permalinks' ), 91 'custom_permalinks_post_settings', 92 'custom-permalinks-post-settings', 93 array( $this, 'post_settings_page' ) 94 ); 75 95 $about_page = add_submenu_page( 76 96 'cp-post-permalinks', … … 91 111 ); 92 112 add_action( 113 'admin_print_styles-' . $post_settings_page, 114 array( $this, 'add_post_settings_style' ) 115 ); 116 add_action( 93 117 'admin_print_styles-' . $about_page . '', 94 118 array( $this, 'add_about_style' ) 119 ); 120 } 121 122 /** 123 * Add post settings page style. 124 * 125 * @since 3.0.0 126 */ 127 public function add_post_settings_style() { 128 wp_enqueue_script( 129 'custom-permalinks-post-settings', 130 plugins_url( 131 '/assets/js/post-settings' . $this->js_file_suffix, 132 CUSTOM_PERMALINKS_FILE 133 ), 134 array(), 135 CUSTOM_PERMALINKS_VERSION, 136 array( 137 'strategy' => 'async', 138 'in_footer' => true, 139 ) 140 ); 141 142 wp_enqueue_style( 143 'custom-permalinks-post-settings', 144 plugins_url( 145 '/assets/css/post-settings' . $this->css_file_suffix, 146 CUSTOM_PERMALINKS_FILE 147 ), 148 array(), 149 CUSTOM_PERMALINKS_VERSION 95 150 ); 96 151 } … … 140 195 public function taxonomy_permalinks_page() { 141 196 Custom_Permalinks_Taxonomies_Table::output(); 197 198 add_filter( 'admin_footer_text', array( $this, 'admin_footer_text' ), 1 ); 199 } 200 201 /** 202 * Calls another Function which shows the Post Types Settings Page. 203 * 204 * @since 3.0.0 205 */ 206 public function post_settings_page() { 207 new Custom_Permalinks_Post_Types_Settings(); 142 208 143 209 add_filter( 'admin_footer_text', array( $this, 'admin_footer_text' ), 1 ); -
custom-permalinks/tags/3.0.0/admin/class-custom-permalinks-post-types.php
r3136157 r3332124 26 26 27 27 $total_posts = wp_cache_get( 'total_posts_result', 'custom_permalinks' ); 28 if ( !$total_posts ) {28 if ( false === $total_posts ) { 29 29 $sql_query = " 30 30 SELECT COUNT(p.ID) FROM $wpdb->posts AS p … … 63 63 } 64 64 65 wp_cache_set( 'total_posts_result', $total_posts, 'custom_permalinks' );65 wp_cache_set( 'total_posts_result', $total_posts, 'custom_permalinks', 60 ); 66 66 } 67 67 … … 84 84 85 85 $posts = wp_cache_get( 'post_type_results', 'custom_permalinks' ); 86 if ( !$posts ) {86 if ( false === $posts ) { 87 87 $page_offset = ( $page_number - 1 ) * $per_page; 88 88 $order_by = 'p.ID'; … … 156 156 // phpcs:enable WordPress.Security.NonceVerification.Recommended 157 157 158 wp_cache_set( 'post_type_results', $posts, 'custom_permalinks' );158 wp_cache_set( 'post_type_results', $posts, 'custom_permalinks', 60 ); 159 159 } 160 160 -
custom-permalinks/tags/3.0.0/admin/class-custom-permalinks-taxonomies.php
r2844616 r3332124 39 39 public static function total_permalinks() { 40 40 $total_taxonomies = wp_cache_get( 'total_taxonomies_result', 'custom_permalinks' ); 41 if ( !$total_taxonomies ) {41 if ( false === $total_taxonomies ) { 42 42 $search_taxonomy = array(); 43 43 $taxonomy_table = get_option( 'custom_permalink_table' ); … … 66 66 } 67 67 68 wp_cache_set( 'total_taxonomies_result', $total_taxonomies, 'custom_permalinks' );68 wp_cache_set( 'total_taxonomies_result', $total_taxonomies, 'custom_permalinks', 60 ); 69 69 } 70 70 … … 85 85 public static function get_permalinks( $per_page = 20, $page_number = 1 ) { 86 86 $taxonomies = wp_cache_get( 'taxonomies_results', 'custom_permalinks' ); 87 if ( !$taxonomies ) {87 if ( false === $taxonomies ) { 88 88 $page_offset = ( $page_number - 1 ) * $per_page; 89 89 $taxonomy_table = get_option( 'custom_permalink_table' ); … … 130 130 } 131 131 132 wp_cache_set( 'taxonomies_results', $taxonomies, 'custom_permalinks' );132 wp_cache_set( 'taxonomies_results', $taxonomies, 'custom_permalinks', 60 ); 133 133 } 134 134 -
custom-permalinks/tags/3.0.0/changelog.txt
r2842482 r3332124 2 2 3 3 This file contains only old changelog. See readme.txt for newer versions. 4 5 = 2.8.0 - Apr 29, 2025 = 6 7 * Bug: 8 * Resolved pagination issue with custom permalinks (now supports /page/{number} format correctly). 9 * Enhancements: 10 * Added compatibility with Polylang 3.7. 11 * Metabox is now hidden for post types that are not publicly queryable. 12 13 = 2.7.0 - Aug 20, 2024 = 14 15 * Bug 16 * [Passing null to parameter string is deprecated](https://github.com/samiahmedsiddiqui/custom-permalinks/pull/86) 17 * [Fix PHP warning with empty permalink on new page/post](https://github.com/samiahmedsiddiqui/custom-permalinks/pull/87) 18 * [Authenticated(Editor+) Stored Cross-Site Scripting](https://github.com/samiahmedsiddiqui/custom-permalinks/pull/96) 19 * Enhancement: 20 * [Improve I18N](https://github.com/samiahmedsiddiqui/custom-permalinks/pull/72) 21 22 = 2.6.0 - Aug 15, 2024 = 23 24 * Feature Additions: 25 * Compatibility with PolyLang Plugin 26 27 = 2.5.2 - Feb 14, 2023 = 28 29 * Bug 30 * [Error in new update](https://wordpress.org/support/topic/error-in-new-update-3/) 31 32 = 2.5.1 - Feb 14, 2023 = 33 34 * Bug 35 * [“http//” is added in front of permalinks](https://github.com/samiahmedsiddiqui/custom-permalinks/issues/71) 36 37 = 2.5.0 - Jan 02, 2023 = 38 39 * Bugs 40 * [Retreiving info from installed plugin (GDPR)](https://wordpress.org/support/topic/retreiving-info-from-installed-plugin-gdpr/) 41 * Enhancement 42 * Same permalink with WPML different domain 43 44 = 2.4.0 - Nov 26, 2021 = 45 46 * Bugs 47 * [filter for leading special characters](https://wordpress.org/support/topic/filter-for-leading-special-characters/) 48 * [“search Permalinks” button doesn’t work. (part2)](https://wordpress.org/support/topic/search-permalinks-button-doesnt-work-part2/) 49 * [PHP 8 errors on first visit of Taxonomy Permalinks tab](https://github.com/samiahmedsiddiqui/custom-permalinks/issues/59) 50 * [Notice: Undefined variable: site_url in custom-permalinks/admin/class-custom-permalinks-post-types-table.php on line 306](https://github.com/samiahmedsiddiqui/custom-permalinks/issues/56) 51 * Enhancements 52 * [Pending Post Preview Link](https://wordpress.org/support/topic/pending-post-preview-link/) 4 53 5 54 = 2.3.0 - Sep 21, 2021 = -
custom-permalinks/tags/3.0.0/custom-permalinks.php
r3284095 r3332124 4 4 * Plugin URI: https://www.custompermalinks.com/ 5 5 * Description: Set custom permalinks on a per-post basis. 6 * Version: 2.8.06 * Version: 3.0.0 7 7 * Requires at least: 2.6 8 8 * Requires PHP: 7.0 -
custom-permalinks/tags/3.0.0/includes/class-custom-permalinks-form.php
r3284095 r3332124 44 44 add_action( 'add_meta_boxes', array( $this, 'permalink_edit_box' ) ); 45 45 add_action( 'save_post', array( $this, 'save_post' ), 10, 3 ); 46 add_action( 'pmxi_saved_post', array( $this, 'pmxi_post_permalink' ), 10, 3 ); 47 add_action( 48 'custom_permalinks_generate_post_permalink', 49 array( $this, 'generate_post_permalink' ), 50 10, 51 1 52 ); 46 53 add_action( 'delete_post', array( $this, 'delete_permalink' ), 10 ); 47 54 add_action( 'category_add_form', array( $this, 'term_options' ) ); … … 70 77 71 78 /** 72 * Initialize WordPress Hooks.79 * Check whether the permalink can be customized/generates on this post or not. 73 80 * 74 81 * @since 1.6.0 … … 79 86 * return bool false Whether to show Custom Permalink form or not. 80 87 */ 81 private function exclude_custom_permalinks( $post ) {88 private function is_permalink_customizable( $post ) { 82 89 $exclude_post_types = apply_filters( 83 90 'custom_permalinks_exclude_post_type', … … 347 354 348 355 $permalink = preg_replace( '/\s+/', '-', $permalink ); 349 $permalink = preg_replace( ' |-+|', '-', $permalink );356 $permalink = preg_replace( '/(\-+)/', '-', $permalink ); 350 357 $permalink = str_replace( '-/', '/', $permalink ); 351 358 $permalink = str_replace( '/-', '/', $permalink ); … … 365 372 366 373 /** 374 * Check whether the permalink exists or not. If exists append unique number 375 * at the end of it to prevent making duplicate permalinks. 376 * 377 * @since 3.0.0 378 * @access private 379 * 380 * @param int $post_id Post ID. 381 * @param string $permalink Permalink which is going to be set. 382 * @param string $language_code Page Language if multi-langauge is enabled. 383 * 384 * @return string 385 */ 386 private function check_permalink_exists( $post_id, $permalink, $language_code ) { 387 global $wpdb; 388 389 $trailing_slash = substr( $permalink, -1 ); 390 if ( '/' === $trailing_slash ) { 391 $permalink = rtrim( $permalink, '/' ); 392 } 393 394 $append_number = 1; 395 $init_permalink = $permalink; 396 while ( 1 ) { 397 // First, check permalink before appending number. 398 if ( 1 < $append_number ) { 399 $permalink = $init_permalink . '-' . $append_number; 400 } 401 402 if ( null !== $language_code ) { 403 // phpcs:disable WordPress.DB.DirectDatabaseQuery.NoCaching 404 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery 405 $existing_url_ids = $wpdb->get_col( 406 $wpdb->prepare( 407 "SELECT pm.`post_id` FROM $wpdb->postmeta AS pm 408 INNER JOIN $wpdb->posts AS p ON (p.`ID` = pm.`post_id`) 409 WHERE pm.`post_id` != %d 410 AND pm.`meta_key` = 'custom_permalink' 411 AND p.`post_status` != 'inherit' 412 AND (pm.`meta_value` = %s OR pm.`meta_value` = %s)", 413 $post_id, 414 $permalink, 415 $permalink . '/' 416 ) 417 ); 418 // phpcs:enable WordPress.DB.DirectDatabaseQuery.NoCaching 419 420 $check_exist_url = null; 421 foreach ( $existing_url_ids as $existing_url_id ) { 422 $existing_url_lang = get_post_meta( $existing_url_id, 'custom_permalink_language', true ); 423 if ( $existing_url_lang === $language_code ) { 424 $check_exist_url = 1; 425 break; 426 } 427 } 428 } else { 429 // phpcs:disable WordPress.DB.DirectDatabaseQuery.NoCaching 430 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery 431 $check_exist_url = $wpdb->get_var( 432 $wpdb->prepare( 433 "SELECT COUNT(pm.`post_id`) FROM $wpdb->postmeta AS pm 434 INNER JOIN $wpdb->posts AS p ON (p.`ID` = pm.`post_id`) 435 WHERE pm.`post_id` != %d 436 AND pm.`meta_key` = 'custom_permalink' 437 AND p.`post_status` != 'inherit' 438 AND (pm.`meta_value` = %s OR pm.`meta_value` = %s)", 439 $post_id, 440 $permalink, 441 $permalink . '/' 442 ) 443 ); 444 // phpcs:enable WordPress.DB.DirectDatabaseQuery.NoCaching 445 } 446 447 // Check URL should not be duplicated in any post Permalink. 448 if ( empty( $check_exist_url ) ) { 449 $existing_post_id = url_to_postid( $permalink ); 450 if ( 0 === $existing_post_id || $post_id === $existing_post_id ) { 451 break; 452 } 453 } 454 455 ++$append_number; 456 } 457 458 if ( '/' === $trailing_slash ) { 459 $permalink = $permalink . '/'; 460 } 461 462 if ( 0 === strpos( $permalink, '/' ) ) { 463 $permalink = substr( $permalink, 1 ); 464 } 465 466 return $permalink; 467 } 468 469 /** 470 * Clear post permalink cache if exists. 471 * 472 * @since 3.0.0 473 * @access private 474 * 475 * @param string $cached_permalink Permalink for which cache needs to be cleared. 476 */ 477 private function clear_post_permalink_cache( $cached_permalink ) { 478 if ( ! empty( $cached_permalink ) ) { 479 $cache_name = 'cp$_' . str_replace( '/', '-', $cached_permalink ) . '_#cp'; 480 $cache_exists = wp_cache_get( $cache_name, 'custom_permalinks' ); 481 if ( false !== $cache_exists ) { 482 wp_cache_delete( $cache_name, 'custom_permalinks' ); 483 } 484 } 485 } 486 487 /** 367 488 * Save per-post options. 368 489 * … … 371 492 * @param int $post_id Post ID. 372 493 * @param WP_Post $post Post object. 373 * 374 * @return void 375 */ 376 public function save_post( $post_id, $post ) { 377 if ( ! isset( $_REQUEST['_custom_permalinks_post_nonce'] ) 378 && ! isset( $_REQUEST['custom_permalink'] ) 494 * @param bool $update Whether this is an existing post being updated or not. 495 */ 496 public function save_post( $post_id, $post, $update ) { 497 /* 498 * Enable permalink regeneration on creating new post if permalink structure 499 * is defined for the post type. 500 */ 501 if ( ! $update ) { 502 $permalink_structure = ''; 503 $post_types_settings = get_option( 'custom_permalinks_post_types_settings', array() ); 504 505 if ( isset( $post_types_settings[ $post->post_type ] ) ) { 506 $permalink_structure = $post_types_settings[ $post->post_type ]; 507 } 508 509 /* 510 * Permalink structure is not defined in the Plugin Settings. 511 */ 512 if ( ! empty( $permalink_structure ) ) { 513 // Make it 1 to keep generating permalink on updating the post. 514 update_post_meta( $post_id, 'custom_permalink_regenerate_status', 1 ); 515 } 516 } 517 518 if ( 'auto-draft' === sanitize_title( $post->post_title ) ) { 519 return; 520 } 521 522 if ( isset( $_REQUEST['_custom_permalinks_post_nonce'] ) 523 && isset( $_REQUEST['custom_permalink'] ) 379 524 ) { 380 return; 381 } 382 383 $action = 'custom-permalinks_' . $post_id; 384 // phpcs:disable WordPress.Security.ValidatedSanitizedInput.MissingUnslash 385 // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized 386 if ( ! wp_verify_nonce( $_REQUEST['_custom_permalinks_post_nonce'], $action ) ) { 387 return; 388 } 389 // phpcs:enable WordPress.Security.ValidatedSanitizedInput.MissingUnslash 525 $action = 'custom-permalinks_' . $post_id; 526 // phpcs:disable WordPress.Security.ValidatedSanitizedInput.MissingUnslash 527 // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized 528 if ( ! wp_verify_nonce( $_REQUEST['_custom_permalinks_post_nonce'], $action ) ) { 529 return; 530 } 531 // phpcs:enable WordPress.Security.ValidatedSanitizedInput.MissingUnslash 532 } 533 534 if ( 'inherit' === $post->post_status ) { 535 $post_parent_id = $post->post_parent; 536 if ( ! empty( $post_parent_id ) ) { 537 $post_id = $post_parent_id; 538 $post = get_post( $post_parent_id ); 539 } 540 } 541 542 $current_permalink = get_post_meta( $post_id, 'custom_permalink', true ); 543 $is_refresh = get_post_meta( $post_id, 'custom_permalink_regenerate_status', true ); 544 545 // Make it 0 if not exist. 546 if ( empty( $is_refresh ) ) { 547 $is_refresh = 0; 548 } 549 550 /* 551 * Make sure that the post saved from quick edit form so, just make the 552 * $_REQUEST['custom_permalink'] same as $current_permalink to regenerate permalink 553 * if applicable. 554 */ 555 if ( ! isset( $_REQUEST['custom_permalink'] ) ) { 556 $_REQUEST['custom_permalink'] = $current_permalink; 557 } 558 559 $is_regenerated = false; 560 if ( 'trash' !== $post->post_status 561 && $current_permalink === $_REQUEST['custom_permalink'] 562 && 1 === (int) $is_refresh 563 ) { 564 $cp_post_permalinks = new Custom_Permalinks_Generate_Post_Permalinks(); 565 $is_regenerated = $cp_post_permalinks->generate( $post_id, $post ); 566 } 390 567 391 568 $cp_frontend = new Custom_Permalinks_Frontend(); 392 569 $original_link = $cp_frontend->original_post_link( $post_id ); 393 394 570 if ( ! empty( $_REQUEST['custom_permalink'] ) 395 571 && $_REQUEST['custom_permalink'] !== $original_link 572 && $_REQUEST['custom_permalink'] !== $current_permalink 396 573 ) { 397 574 $language_code = apply_filters( … … 403 580 ) 404 581 ); 582 if ( null !== $language_code ) { 583 update_post_meta( $post_id, 'custom_permalink_language', $language_code ); 584 } else { 585 delete_metadata( 'post', $post_id, 'custom_permalink_language' ); 586 } 405 587 406 588 $permalink = $this->sanitize_permalink( … … 409 591 $language_code 410 592 ); 593 $permalink = $this->check_permalink_exists( $post_id, $permalink, $language_code ); 411 594 $permalink = apply_filters( 412 595 'custom_permalink_before_saving', 413 596 $permalink, 414 $post_id 597 $post_id, 598 $language_code 415 599 ); 416 600 417 601 update_post_meta( $post_id, 'custom_permalink', $permalink ); 418 if ( null !== $language_code ) { 419 update_post_meta( $post_id, 'custom_permalink_language', $language_code ); 420 } else { 421 delete_metadata( 'post', $post_id, 'custom_permalink_language' ); 422 } 602 603 // Clear cache for the previous and updated permalink. 604 $this->clear_post_permalink_cache( $current_permalink ); 605 $this->clear_post_permalink_cache( $permalink ); 606 607 // If true means it triggers from the regeneration code so don't override it. 608 if ( ! $is_regenerated ) { 609 // Delete to prevent generating permalink on updating the post. 610 delete_post_meta( $post_id, 'custom_permalink_regenerate_status' ); 611 } 612 } 613 } 614 615 /** 616 * This action fires when WP All Import saves a post of any type. 617 * 618 * @since 3.0.0 619 * @access public 620 * 621 * @param int $post_id The ID of the item (post/user/taxonomy) saved or updated. 622 * @param SimpleXMLElement $xml_node The libxml resource of the current XML element. 623 * @param bool $is_update Returns 0 for new item 1 for updated item. 624 * 625 * @return void 626 */ 627 public function pmxi_post_permalink( $post_id, $xml_node, $is_update ) { 628 $post = get_post( $post_id ); 629 if ( is_object( $post ) && isset( $post->post_type ) ) { 630 $updated = false; 631 if ( 1 === $is_update ) { 632 $updated = true; 633 } 634 635 $this->save_post( $post_id, $post, $updated ); 636 } 637 } 638 639 /** 640 * Generates post permalink for the provided post id. 641 * 642 * @since 3.0.0 643 * @access public 644 * 645 * @param int $post_id Post ID. 646 * 647 * @return void 648 */ 649 public function generate_post_permalink( $post_id ) { 650 $post = get_post( $post_id ); 651 if ( is_object( $post ) && isset( $post->post_type ) ) { 652 $this->save_post( $post_id, $post, false ); 423 653 } 424 654 } … … 434 664 */ 435 665 public function delete_permalink( $post_id ) { 666 // Clear cache for the deleting post. 667 $permalink = get_post_meta( $post_id, 'custom_permalink', true ); 668 $this->clear_post_permalink_cache( $permalink ); 669 436 670 delete_metadata( 'post', $post_id, 'custom_permalink' ); 437 671 } … … 615 849 $post = get_post( $post_id ); 616 850 617 $ disable_cp = $this->exclude_custom_permalinks( $post );851 $is_customizable = $this->is_permalink_customizable( $post ); 618 852 $this->permalink_metabox = 1; 619 if ( $ disable_cp) {853 if ( $is_customizable ) { 620 854 return $html; 621 855 } … … 635 869 */ 636 870 public function meta_edit_form( $post ) { 637 $ disable_cp = $this->exclude_custom_permalinks( $post );638 if ( $ disable_cp) {871 $is_customizable = $this->is_permalink_customizable( $post ); 872 if ( $is_customizable ) { 639 873 wp_enqueue_script( 640 874 'custom-permalinks-form', … … 787 1021 true 788 1022 ); 789 790 echo esc_url( $home_url ) . 791 '<span id="editable-post-name" title="Click to edit this part of the permalink">';792 793 if ( isset( $postname ) && '' !== $postname ) : 794 ?>1023 ?> 1024 1025 <span id="uneditable-permalink"><?php echo esc_url( $home_url ); ?></span> 1026 <span id="editable-post-name" title="Click to edit this part of the permalink"> 1027 1028 <?php if ( isset( $postname ) && '' !== $postname ) : ?> 795 1029 796 1030 <input type="hidden" id="new-post-slug" class="text" value="<?php echo esc_attr( $postname ); ?>" /> -
custom-permalinks/tags/3.0.0/includes/class-custom-permalinks-frontend.php
r3284095 r3332124 77 77 add_filter( 'post_type_link', array( $this, 'custom_post_link' ), 10, 2 ); 78 78 add_filter( 'page_link', array( $this, 'custom_page_link' ), 10, 2 ); 79 add_filter( 'url_to_postid', array( $this, 'postid_to_customized_permalink' ), 10, 1 ); 79 80 add_filter( 'term_link', array( $this, 'custom_term_link' ), 10, 2 ); 80 81 add_filter( 'user_trailingslashit', array( $this, 'custom_trailingslash' ) ); … … 202 203 $posts = wp_cache_get( $cache_name, 'custom_permalinks' ); 203 204 204 if ( !$posts ) {205 if ( false === $posts ) { 205 206 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery 206 207 $posts = $wpdb->get_results( … … 238 239 } 239 240 240 wp_cache_set( $cache_name, $posts, 'custom_permalinks' ); 241 // Cache permalink for 24 hours. 242 wp_cache_set( $cache_name, $posts, 'custom_permalinks', 86400 ); 241 243 } 242 244 … … 267 269 } 268 270 269 if ( !$matched_post ) {271 if ( false === $matched_post ) { 270 272 $matched_post = array(); 271 273 … … 306 308 } 307 309 308 wp_cache_set( $cache_name, $matched_post, 'custom_permalinks' ); 310 // Cache permalink for 24 hours. 311 wp_cache_set( $cache_name, $matched_post, 'custom_permalinks', 86400 ); 309 312 310 313 return $matched_post; … … 713 716 } 714 717 715 $custom_permalink = '';716 $original_permalink = '';717 718 718 // Get request URI, strip parameters. 719 719 $url = wp_parse_url( get_bloginfo( 'url' ) ); … … 735 735 * @since 1.7.0 736 736 */ 737 $avoid_redirect = apply_filters( 738 'custom_permalinks_avoid_redirect', 739 $request 740 ); 741 737 $avoid_redirect = apply_filters( 'custom_permalinks_avoid_redirect', $request ); 742 738 if ( is_bool( $avoid_redirect ) && $avoid_redirect ) { 743 739 return; 744 740 } 745 741 746 if ( defined( 'POLYLANG_VERSION' ) ) { 747 $cp_form = new Custom_Permalinks_Form(); 748 $request = $cp_form->check_conflicts( $request ); 749 } 750 751 $request_no_slash = preg_replace( '@/+@', '/', trim( $request, '/' ) ); 752 $posts = $this->query_post( $request_no_slash ); 753 754 if ( ! isset( $posts[0]->ID ) || ! isset( $posts[0]->meta_value ) 755 || empty( $posts[0]->meta_value ) 756 ) { 757 global $wp_query; 758 759 /* 760 * If the post/tag/category we're on has a custom permalink, get it 761 * and check against the request. 762 */ 763 if ( ( is_single() || is_page() ) && ! empty( $wp_query->post ) ) { 764 $post = $wp_query->post; 765 $custom_permalink = get_post_meta( 766 $post->ID, 767 'custom_permalink', 768 true 769 ); 770 if ( 'page' === $post->post_type ) { 771 $original_permalink = $this->original_page_link( $post->ID ); 772 } else { 773 $original_permalink = $this->original_post_link( $post->ID ); 774 } 775 } elseif ( is_tag() || is_category() ) { 776 $the_term = $wp_query->get_queried_object(); 777 $custom_permalink = $this->term_permalink( $the_term->term_id ); 778 $original_permalink = $this->original_term_link( $the_term->term_id ); 742 $custom_permalink = ''; 743 $original_permalink = ''; 744 $get_post_id = url_to_postid( $this->request_uri ); 745 746 // Redirect original post permalink. 747 if ( ! empty( $get_post_id ) ) { 748 $custom_permalink = get_post_meta( $get_post_id, 'custom_permalink', true ); 749 if ( ! empty( $custom_permalink ) ) { 750 // Append any query component. 751 $custom_permalink .= strstr( $this->request_uri, '?' ); 752 753 wp_safe_redirect( home_url() . '/' . $custom_permalink, 301 ); 754 exit( 0 ); 779 755 } 780 756 } else { 781 $custom_permalink = $posts[0]->meta_value; 782 if ( 'page' === $posts[0]->post_type ) { 783 $original_permalink = $this->original_page_link( $posts[0]->ID ); 784 } else { 785 $original_permalink = $this->original_post_link( $posts[0]->ID ); 786 } 787 } 788 789 $custom_length = strlen( $custom_permalink ); 790 if ( $custom_permalink 791 && ( 792 substr( $request, 0, $custom_length ) !== $custom_permalink 793 || $request === $custom_permalink . '/' 794 ) 795 ) { 796 // Request doesn't match permalink - redirect. 797 $url = $custom_permalink; 798 $original_length = strlen( $original_permalink ); 799 800 if ( substr( $request, 0, $original_length ) === $original_permalink 801 && trim( $request, '/' ) !== trim( $original_permalink, '/' ) 757 if ( defined( 'POLYLANG_VERSION' ) ) { 758 $cp_form = new Custom_Permalinks_Form(); 759 $request = $cp_form->check_conflicts( $request ); 760 } 761 762 $request_no_slash = preg_replace( '@/+@', '/', trim( $request, '/' ) ); 763 $posts = $this->query_post( $request_no_slash ); 764 765 if ( ! isset( $posts[0]->ID ) || ! isset( $posts[0]->meta_value ) 766 || empty( $posts[0]->meta_value ) 802 767 ) { 803 // This is the original link; we can use this URL to derive the new one. 804 $url = preg_replace( 805 '@//*@', 806 '/', 807 str_replace( 808 trim( $original_permalink, '/' ), 809 trim( $custom_permalink, '/' ), 810 $request 811 ) 812 ); 813 $url = preg_replace( '@([^?]*)&@', '\1?', $url ); 814 } 815 816 // Append any query component. 817 $url .= strstr( $this->request_uri, '?' ); 818 819 wp_safe_redirect( home_url() . '/' . $url, 301 ); 820 exit( 0 ); 768 global $wp_query; 769 770 /* 771 * If the post/tag/category we're on has a custom permalink, get it 772 * and check against the request. 773 */ 774 if ( ( is_single() || is_page() ) && ! empty( $wp_query->post ) ) { 775 $post = $wp_query->post; 776 $custom_permalink = get_post_meta( 777 $post->ID, 778 'custom_permalink', 779 true 780 ); 781 if ( 'page' === $post->post_type ) { 782 $original_permalink = $this->original_page_link( $post->ID ); 783 } else { 784 $original_permalink = $this->original_post_link( $post->ID ); 785 } 786 } elseif ( is_tag() || is_category() ) { 787 $the_term = $wp_query->get_queried_object(); 788 $custom_permalink = $this->term_permalink( $the_term->term_id ); 789 $original_permalink = $this->original_term_link( $the_term->term_id ); 790 } 791 } 792 793 $custom_length = strlen( $custom_permalink ); 794 if ( $custom_permalink 795 && ( 796 substr( $request, 0, $custom_length ) !== $custom_permalink 797 || $request === $custom_permalink . '/' 798 ) 799 ) { 800 // Request doesn't match permalink - redirect. 801 $url = $custom_permalink; 802 $original_length = strlen( $original_permalink ); 803 804 if ( substr( $request, 0, $original_length ) === $original_permalink 805 && trim( $request, '/' ) !== trim( $original_permalink, '/' ) 806 ) { 807 // This is the original link; we can use this URL to derive the new one. 808 $url = preg_replace( 809 '@//*@', 810 '/', 811 str_replace( 812 trim( $original_permalink, '/' ), 813 trim( $custom_permalink, '/' ), 814 $request 815 ) 816 ); 817 $url = preg_replace( '@([^?]*)&@', '\1?', $url ); 818 } 819 820 // Append any query component. 821 $url .= strstr( $this->request_uri, '?' ); 822 823 wp_safe_redirect( home_url() . '/' . $url, 301 ); 824 exit( 0 ); 825 } 821 826 } 822 827 } … … 924 929 925 930 /** 931 * Fetch default permalink against the customized permalink. 932 * 933 * @since 3.0.0 934 * @access public 935 * 936 * @param string $permalink URL Permalink to check. 937 * 938 * @return string Default Permalink or the same permalink if not found. 939 */ 940 public function postid_to_customized_permalink( $permalink ) { 941 $customized_permalink = ltrim( substr( $permalink, strlen( $url ) ), '/' ); 942 if ( defined( 'POLYLANG_VERSION' ) ) { 943 $cp_form = new Custom_Permalinks_Form(); 944 $customized_permalink = $cp_form->check_conflicts( $customized_permalink ); 945 } 946 947 $customized_permalink = preg_replace( '@/+@', '/', trim( $customized_permalink, '/' ) ); 948 $posts = $this->query_post( $customized_permalink ); 949 if ( is_array( $posts ) && ! empty( $posts ) ) { 950 if ( 'draft' === $posts[0]->post_status 951 || 'pending' === $posts[0]->post_status 952 ) { 953 if ( 'page' === $posts[0]->post_type ) { 954 $original_url = '?page_id=' . $posts[0]->ID; 955 } else { 956 $original_url = '?post_type=' . $posts[0]->post_type . '&p=' . $posts[0]->ID; 957 } 958 } else { 959 $post_meta = trim( strtolower( $posts[0]->meta_value ), '/' ); 960 if ( 'page' === $posts[0]->post_type ) { 961 $get_original_url = $this->original_page_link( $posts[0]->ID ); 962 $original_url = preg_replace( 963 '@/+@', 964 '/', 965 str_replace( 966 $post_meta, 967 $get_original_url, 968 strtolower( $customized_permalink ) 969 ) 970 ); 971 } else { 972 $get_original_url = $this->original_post_link( $posts[0]->ID ); 973 $original_url = preg_replace( 974 '@/+@', 975 '/', 976 str_replace( 977 $post_meta, 978 $get_original_url, 979 strtolower( $customized_permalink ) 980 ) 981 ); 982 } 983 } 984 985 $permalink = $original_url; 986 } 987 988 return $permalink; 989 } 990 991 /** 926 992 * Filter to replace the term permalink with the custom one. 927 993 * -
custom-permalinks/tags/3.0.0/includes/class-custom-permalinks.php
r3284095 r3332124 19 19 * @var string 20 20 */ 21 public $version = ' 2.8.0';21 public $version = '3.0.0'; 22 22 23 23 /** … … 65 65 private function includes() { 66 66 include_once CUSTOM_PERMALINKS_PATH . 'includes/class-custom-permalinks-form.php'; 67 include_once CUSTOM_PERMALINKS_PATH . 'includes/class-custom-permalinks-generate-post-permalinks.php'; 67 68 include_once CUSTOM_PERMALINKS_PATH . 'includes/class-custom-permalinks-frontend.php'; 68 69 include_once CUSTOM_PERMALINKS_PATH . 'admin/class-custom-permalinks-admin.php'; 70 include_once CUSTOM_PERMALINKS_PATH . 'admin/class-custom-permalinks-post-types-settings.php'; 69 71 include_once CUSTOM_PERMALINKS_PATH . 'admin/class-custom-permalinks-post-types.php'; 70 72 include_once CUSTOM_PERMALINKS_PATH . 'admin/class-custom-permalinks-post-types-table.php'; … … 107 109 */ 108 110 public static function add_roles() { 109 $admin_role = get_role( 'administrator' ); 110 $cp_role = get_role( 'custom_permalinks_manager' ); 111 $current_version = get_option( 'custom_permalinks_plugin_version', -1 ); 111 $admin_role = get_role( 'administrator' ); 112 $cp_role = get_role( 'custom_permalinks_manager' ); 112 113 113 114 if ( ! empty( $admin_role ) ) { 115 $admin_role->add_cap( 'custom_permalinks_post_settings' ); 114 116 $admin_role->add_cap( 'cp_view_post_permalinks' ); 115 117 $admin_role->add_cap( 'cp_view_category_permalinks' ); … … 121 123 __( 'Custom Permalinks Manager' ), 122 124 array( 123 'cp_view_post_permalinks' => true, 124 'cp_view_category_permalinks' => true, 125 'custom_permalinks_post_settings' => true, 126 'cp_view_post_permalinks' => true, 127 'cp_view_category_permalinks' => true, 125 128 ) 126 129 ); -
custom-permalinks/tags/3.0.0/readme.txt
r3284095 r3332124 1 1 === Custom Permalinks === 2 2 Contributors: sasiddiqui 3 Tags: permalink, url, link, address, redirect, custom post type 3 Tags: permalink, url, link, address, redirect 4 Requires at least: 5.0 5 Requires PHP: 5.6 4 6 Tested up to: 6.8 5 Stable tag: 2.8.07 Stable tag: 3.0.0 6 8 License: GPLv3 7 9 License URI: https://www.gnu.org/licenses/gpl-3.0.html 8 10 9 Set custom permalinks on a per-post, per-tag or per-category basis.11 Custom Permalinks is a powerful WordPress plugin that grants you complete control over your site's URLs. Easily set unique, custom permalinks for any post, page, tag, or category, allowing you to design an ideal site structure. It includes features for defining post type-specific structures with dynamic tags and automatically redirects old URLs to your new custom ones. Developers can also leverage a wide array of filters for advanced customization. 10 12 11 13 == Description == 12 14 13 > In case of found any site breaking issue after upgrading to the latest version then please report the issue on [WordPress Forum](https://wordpress.org/support/plugin/custom-permalinks/) OR [GitHub](https://github.com/samiahmedsiddiqui/custom-permalinks) with complete information to reproduce the issue and move back to the old version. You can download any of the old version from here: https://wordpress.org/plugins/custom-permalinks/advanced/ 15 You want to take control of your WordPress site's URLs? The **Custom Permalinks** plugin gives you the power to set unique, custom URLs for any post, page, tag, or category. This means you can design your site's structure exactly how you envision it, rather than being limited by WordPress's default settings. When you set a custom permalink, the original post URL will be automatically redirected to your new, customized URL. 14 16 15 Lay out your site the way *you* want it. Set the URL of any post, page, tag or category to anything you want. Old permalinks will redirect properly to the new address. Custom Permalinks give you ultimate control over your site structure. 17 === Key Features === 16 18 17 > Be warned: *This plugin is not a replacement for WordPress's built-in permalink system*. Check your WordPress administration's "Permalinks" settings page first, to make sure that this doesn't already meet your needs. 19 * **Individual Permalink Control**: Assign unique URLs to any post, page, tag, or category. 20 * **Site Structure Control**: Gain ultimate control over how your site's URLs are organized. 21 * **Post Type Permalink Structures (v3.0.0+)**: Define custom permalink structures for each public Post Type using predefined tags, automatically generating URLs upon content creation. You can still manually edit any permalink. If left empty, default settings will apply. 18 22 19 This plugin is only useful for assigning custom permalinks for *individual* posts, pages, tags or categories. It will not apply whole permalink structures or automatically apply a category's custom permalink to the posts within that category. 23 === Getting Started: Plugin Settings === 20 24 21 == Filters == 25 You can configure Custom Permalinks by navigating to **Settings \> Custom Permalinks** in your WordPress Dashboard. 22 26 23 === A dd `PATH_INFO` in `$_SERVER` Variable===27 === Available Tags for Permalink Structures === 24 28 25 ` 26 add_filter( 'custom_permalinks_path_info', '__return_true' ); 27 ` 29 When setting up your custom permalink structures, you can use a variety of tags that will dynamically populate the URL. Here's a breakdown of what's available: 28 30 29 === Disable Redirects === 31 * **%year%**: The year of the post in four digits, eg: 2025 32 * **%monthnum%**: Month the post was published, in two digits, eg: 01 33 * **%day%**: Day the post was published in two digits, eg: 02 34 * **%hour%**: Hour of the day, the post was published, eg: 15 35 * **%minute%**: Minute of the hour, the post was published, eg: 43 36 * **%second%**: Second of the minute, the post was published, eg: 33 37 * **%post_id%**: The unique ID of the post, eg: 123 38 * **%category%**: A clean version of the category name (its slug). Nested sub-categories will appear as nested directories in the URL.. 39 * **%author%**: A sanitized version of the post author’s name. 40 * **%postname%**: A clean version of the post or page title (its slug). For example, "This Is A Great Post\!" becomes `this-is-a-great-post` in the URL. 41 * **%parent_postname%**: Similar to `%postname%`, but uses the immediate parent page's slug if a parent is selected. 42 * **%parents_postnames%**: Similar to `%postname%`, but includes all parent page slugs if parents are selected. 43 * **%title%**: The title of the post, converted to a slug. For example, "This Is A Great Post\!" becomes `this-is-a-great-post`. Unlike `%postname%` which is set once, `%title%` automatically updates in the permalink if the post title changes (unless the post is published or the permalink is manually edited). 44 * **%ctax_TAXONOMY_NAME%**: A clean version of a custom taxonomy's name. Replace `TAXONOMY_NAME` with the actual taxonomy name. You can also provide a default slug for when no category/taxonomy is selected by using `??` (e.g., `%ctax_type??sales%` will use "sales" as a default). 45 * **%ctax_parent_TAXONOMY_NAME%**: Similar to `%ctax_TAXONOMY_NAME%`, but includes the immediate parent category/tag slug in the URL if a parent is selected. 46 * **%ctax_parents_TAXONOMY_NAME%**: Similar to `%ctax_TAXONOMY_NAME%`, but includes all parent category/tag slugs in the URL if parents are selected. 47 * **%custom_permalinks_TAG_NAME%**: Developers have the flexibility to define their own custom tags(replace `_TAG_NAME` with your desired name). To ensure these tags resolve to the correct permalinks, simply apply the `custom_permalinks_post_permalink_tag` filter. 30 48 31 To disable complete redirects functionality provided by this plugin, add the filter that looks like this: 49 **Important Note:** For new posts, Custom Permalinks will keep updating the permalink while the post is in draft mode, assuming a structure is defined in the plugin settings. Once the post is published or its permalink is manually updated, the plugin will stop automatic updates for that specific post. 32 50 33 ` 34 function yasglobal_avoid_redirect( $permalink ) { 35 return true; 36 } 37 add_filter( 'custom_permalinks_avoid_redirect', 'yasglobal_avoid_redirect' ); 38 ` 51 === Custom Permalinks: Fine-Tuning with Filters === 39 52 40 === Disable Particular Redirects === 53 Custom Permalinks offers a range of **filters** that empower developers to precisely control its behavior. You can explore all available filters, complete with example code snippets, in our [GitHub repository](https://github.com/samiahmedsiddiqui/custom-permalinks). 41 54 42 To disable any specific redirect to be processed by this plugin, add the filter that looks like this: 55 **For Assistance:** 43 56 44 ` 45 function yasglobal_avoid_redirect( $permalink ) { 46 // Replace 'testing-hello-world/' with the permalink you want to avoid 47 if ( 'testing-hello-world/' === $permalink ) { 48 return true; 49 } 57 * **Premium Users:** If you need assistance implementing these filters, please don't hesitate to reach out to us via our [Premium contact support](https://www.custompermalinks.com/contact-us/). 58 * **Other Users:** You can also directly reach out to the plugin author via [LinkedIn](https://www.linkedin.com/in/sami-ahmed-siddiqui/). 50 59 51 return false; 52 } 53 add_filter( 'custom_permalinks_avoid_redirect', 'yasglobal_avoid_redirect' ); 54 ` 60 === Need Help or Found a Bug? === 55 61 56 === Exclude Permalink to be processed === 62 * **Support:** For one-on-one email support, consider purchasing [Custom Permalinks Premium](https://www.custompermalinks.com/#pricing-section). While some basic support may be provided on the WordPress.org forums, email support is prioritized for premium users. 63 * **Bug Reports:** If you encounter a bug, please report it on [GitHub](https://github.com/samiahmedsiddiqui/custom-permalinks). Make sure to provide complete information to reproduce the issue. GitHub is for bug reports, not general support questions. 57 64 58 To exclude any Permalink to be processed by the plugin, add the filter that looks like this: 59 60 ` 61 function yasglobal_xml_sitemap_url( $permalink ) { 62 if ( false !== strpos( $permalink, 'sitemap.xml' ) ) { 63 return '__true'; 64 } 65 66 return; 67 } 68 add_filter( 'custom_permalinks_request_ignore', 'yasglobal_xml_sitemap_url' ); 69 ` 70 71 === Exclude Post Type === 72 73 To remove custom permalink **form** from any post type, add the filter that looks like this: 74 75 ` 76 function yasglobal_exclude_post_types( $post_type ) { 77 // Replace 'custompost' with your post type name 78 if ( 'custompost' === $post_type ) { 79 return '__true'; 80 } 81 82 return '__false'; 83 } 84 add_filter( 'custom_permalinks_exclude_post_type', 'yasglobal_exclude_post_types' ); 85 ` 86 87 === Exclude Posts === 88 89 To exclude custom permalink **form** from any posts (based on ID, Template, etc), add the filter that looks like this: 90 91 ` 92 function yasglobal_exclude_posts( $post ) { 93 if ( 1557 === $post->ID ) { 94 return true; 95 } 96 97 return false; 98 } 99 add_filter( 'custom_permalinks_exclude_posts', 'yasglobal_exclude_posts' ); 100 ` 101 102 === Allow Accents Letters === 103 104 To allow accents letters, please add below-mentioned line in your theme `functions.php`: 105 106 ` 107 function yasglobal_permalink_allow_accents() { 108 return true; 109 } 110 add_filter( 'custom_permalinks_allow_accents', 'yasglobal_permalink_allow_accents' ); 111 ` 112 113 === Allow Uppercase Letters === 114 115 To allow uppercase letters/words, please add below-mentioned line in your theme `functions.php`: 116 117 ` 118 function yasglobal_allow_uppercaps() { 119 return true; 120 } 121 add_filter( 'custom_permalinks_allow_caps', 'yasglobal_allow_uppercaps' ); 122 ` 123 124 === Allow Redundant Hyphens === 125 126 To allow redundant hyphens, please add below-mentioned line in your theme `functions.php`: 127 128 ` 129 function yasglobal_redundant_hyphens() { 130 return true; 131 } 132 add_filter( 'custom_permalinks_redundant_hyphens', 'yasglobal_redundant_hyphens' ); 133 ` 134 135 === Manipulate Permalink Before Saving === 136 137 To make changes in permalink before saving, please use `custom_permalink_before_saving` filter. Here is an example to see how it works. 138 139 ` 140 function yasglobal_permalink_before_saving( $permalink, $post_id ) { 141 // Check trialing slash in the permalink. 142 if ( substr( $permalink, -1 ) !== '/' ) { 143 // If permalink doesn't contain trialing slash then add one. 144 $permalink .= '/'; 145 } 146 147 return $permalink; 148 } 149 add_filter( 'custom_permalink_before_saving', 'yasglobal_permalink_before_saving', 10, 2 ); 150 ` 151 152 === Remove `like` Query === 153 154 To remove `like` query to being work, add below-mentioned line in your theme `functions.php`: 155 ` 156 add_filter( 'cp_remove_like_query', '__return_false' ); 157 ` 158 159 Note: Use `custom_permalinks_like_query` filter if the URLs doesn't works for you after upgrading to `v1.2.9`. 160 161 === Thanks for the Support === 162 163 I do not always provide active support for the Custom Permalinks plugin on the WordPress.org forums, as I have prioritized the email support. One-on-one email support is available to people who bought [Custom Permalinks Premium](https://www.custompermalinks.com/#pricing-section) only. 164 165 === Bug reports === 166 167 Bug reports for Custom Permalinks are [welcomed on GitHub](https://github.com/samiahmedsiddiqui/custom-permalinks). Please note GitHub is not a support forum, and issues that aren't properly qualified as bugs will be closed. 65 If you experience any site-breaking issues after upgrading, please report them on the [WordPress Forum](https://wordpress.org/support/plugin/custom-permalinks/) or [GitHub](https://github.com/samiahmedsiddiqui/custom-permalinks) with detailed information. You can always revert to an older version by downloading it from [https://wordpress.org/plugins/custom-permalinks/advanced/](https://wordpress.org/plugins/custom-permalinks/advanced/). 168 66 169 67 == Installation == 68 You have two ways to install Custom Permalinks: 170 69 171 This process defines you the steps to follow either you are installing through WordPress or Manually from FTP. 70 #### From within WordPress 172 71 173 **From within WordPress** 72 1. Go to **Plugins \> Add New** in your WordPress dashboard. 73 2. Search for "Custom Permalinks". 74 3. Click "Install Now" and then "Activate" the plugin from your Plugins page. 174 75 175 1. Visit 'Plugins > Add New' 176 2. Search for Custom Permalinks 177 3. Activate Custom Permalinks from your Plugins page. 76 #### Manually via FTP 178 77 179 **Manually** 180 181 1. Upload the `custom-permalinks` folder to the `/wp-content/plugins/` directory 182 2. Activate Custom Permalinks through the 'Plugins' menu in WordPress 78 1. Download the `custom-permalinks` folder. 79 2. Upload the `custom-permalinks` folder to your `/wp-content/plugins/` directory. 80 3. Activate Custom Permalinks through the "Plugins" menu in your WordPress dashboard. 183 81 184 82 == Changelog == 185 83 186 = 2.8.0 - Apr 29, 2025 =84 = 3.0.0 - Jul 22, 2025 = 187 85 188 * Bug: 189 * Resolved pagination issue with custom permalinks (now supports /page/{number} format correctly). 190 * Enhancements: 191 * Added compatibility with Polylang 3.7. 192 * Metabox is now hidden for post types that are not publicly queryable. 86 This release of Custom Permalinks brings significant enhancements to post type permalink management, introduces new customization options, and refines the overall user and developer experience. 193 87 194 = 2.7.0 - Aug 20, 2024 = 88 **Added** 195 89 196 * Bug 197 * [Passing null to parameter string is deprecated](https://github.com/samiahmedsiddiqui/custom-permalinks/pull/86) 198 * [Fix PHP warning with empty permalink on new page/post](https://github.com/samiahmedsiddiqui/custom-permalinks/pull/87) 199 * [Authenticated(Editor+) Stored Cross-Site Scripting](https://github.com/samiahmedsiddiqui/custom-permalinks/pull/96) 200 * Enhancement: 201 * [Improve I18N](https://github.com/samiahmedsiddiqui/custom-permalinks/pull/72) 90 * **Post Type Permalink Structures:** Introduced robust functionality to define custom permalink structures for each public Post Type directly within the plugin settings. This allows for automatic URL generation based on predefined tags upon content creation, offering greater flexibility while still allowing manual edits. 91 * **New Available Permalink Tags:** Expanded the list of dynamic tags that can be used in permalink structures, including: 92 * `%parent_postname%`: For immediate parent page slugs. 93 * `%parents_postnames%`: For all parent page slugs. 94 * `%title%`: A dynamic slug that updates with post title changes (until published or manually edited). 95 * `%ctax_parent_TAXONOMY_NAME%`: For immediate parent custom taxonomy slugs. 96 * `%ctax_parents_TAXONOMY_NAME%`: For all parent custom taxonomy slugs. 97 * `%custom_permalinks_TAG_NAME%`: Allows developers to define and resolve their own custom tags. 98 * **WP All Import Compatibility:** Added support to generate/update permalinks when importing posts using the WP All Import plugin. 99 * **New Filter Examples:** Included clear code examples for `custom_permalinks_post_permalink_tag` to set custom values from ACF fields, and for programmatically generating permalinks for single posts and entire post types. 202 100 203 = 2.6.0 - Aug 15, 2024 = 101 **Improved** 204 102 205 * Feature Additions: 206 * Compatibility with PolyLang Plugin 207 208 = 2.5.2 - Feb 14, 2023 = 209 210 * Bug 211 * [Error in new update](https://wordpress.org/support/topic/error-in-new-update-3/) 212 213 = 2.5.1 - Feb 14, 2023 = 214 215 * Bug 216 * [“http//” is added in front of permalinks](https://github.com/samiahmedsiddiqui/custom-permalinks/issues/71) 217 218 = 2.5.0 - Jan 02, 2023 = 219 220 * Bugs 221 * [Retreiving info from installed plugin (GDPR)](https://wordpress.org/support/topic/retreiving-info-from-installed-plugin-gdpr/) 222 * Enhancement 223 * Same permalink with WPML different domain 224 225 = 2.4.0 - Nov 26, 2021 = 226 227 * Bugs 228 * [filter for leading special characters](https://wordpress.org/support/topic/filter-for-leading-special-characters/) 229 * [“search Permalinks” button doesn’t work. (part2)](https://wordpress.org/support/topic/search-permalinks-button-doesnt-work-part2/) 230 * [PHP 8 errors on first visit of Taxonomy Permalinks tab](https://github.com/samiahmedsiddiqui/custom-permalinks/issues/59) 231 * [Notice: Undefined variable: site_url in custom-permalinks/admin/class-custom-permalinks-post-types-table.php on line 306](https://github.com/samiahmedsiddiqui/custom-permalinks/issues/56) 232 * Enhancements 233 * [Pending Post Preview Link](https://wordpress.org/support/topic/pending-post-preview-link/) 103 * **Post Caching:** Enhanced post caching mechanisms and optimized cache deletion upon updates for better performance. 104 * **Permalink Retrieval:** Improved logic to allow fetching posts against customized permalinks. 105 * **Filter Documentation:** Refined existing filter descriptions and improved code formatting for clarity. 106 * **Plugin Purpose Clarity:** Updated documentation to explicitly state that original post URLs will automatically redirect to the customized URLs, ensuring seamless transitions. 234 107 235 108 = Earlier versions = -
custom-permalinks/tags/3.0.0/uninstall.php
r2575556 r3332124 15 15 delete_post_meta_by_key( 'custom_permalink' ); 16 16 delete_option( 'custom_permalink_table' ); 17 delete_option( 'custom_permalinks_post_types_settings' ); 17 18 18 19 $wp_role = get_role( 'administrator' ); … … 20 21 $wp_role->remove_cap( 'cp_view_post_permalinks' ); 21 22 $wp_role->remove_cap( 'cp_view_category_permalinks' ); 23 $wp_role->remove_cap( 'custom_permalinks_post_settings' ); 22 24 } 23 25 … … 26 28 $wp_role->remove_cap( 'cp_view_post_permalinks' ); 27 29 $wp_role->remove_cap( 'cp_view_category_permalinks' ); 30 $wp_role->remove_cap( 'custom_permalinks_post_settings' ); 28 31 29 32 remove_role( 'custom_permalinks_manager' ); -
custom-permalinks/trunk/admin/class-custom-permalinks-admin.php
r3138206 r3332124 22 22 23 23 /** 24 * JS file suffix extension. 25 * 26 * @var string 27 */ 28 private $js_file_suffix = '.min.js'; 29 30 /** 24 31 * Initializes WordPress hooks. 25 32 */ 26 33 public function __construct() { 27 34 /* 28 * C ssfile suffix (version number with extension).35 * CSS file suffix (version number with extension). 29 36 */ 30 37 $this->css_file_suffix = '-' . CUSTOM_PERMALINKS_VERSION . '.min.css'; 38 39 /* 40 * JS file suffix (version number with extension). 41 */ 42 $this->js_file_suffix = '-' . CUSTOM_PERMALINKS_VERSION . '.min.js'; 31 43 32 44 add_action( 'admin_init', array( $this, 'privacy_policy' ) ); … … 73 85 array( $this, 'taxonomy_permalinks_page' ) 74 86 ); 87 $post_settings_page = add_submenu_page( 88 'cp-post-permalinks', 89 __( 'Post Types Settings', 'custom-permalinks' ), 90 __( 'Post Types Settings', 'custom-permalinks' ), 91 'custom_permalinks_post_settings', 92 'custom-permalinks-post-settings', 93 array( $this, 'post_settings_page' ) 94 ); 75 95 $about_page = add_submenu_page( 76 96 'cp-post-permalinks', … … 91 111 ); 92 112 add_action( 113 'admin_print_styles-' . $post_settings_page, 114 array( $this, 'add_post_settings_style' ) 115 ); 116 add_action( 93 117 'admin_print_styles-' . $about_page . '', 94 118 array( $this, 'add_about_style' ) 119 ); 120 } 121 122 /** 123 * Add post settings page style. 124 * 125 * @since 3.0.0 126 */ 127 public function add_post_settings_style() { 128 wp_enqueue_script( 129 'custom-permalinks-post-settings', 130 plugins_url( 131 '/assets/js/post-settings' . $this->js_file_suffix, 132 CUSTOM_PERMALINKS_FILE 133 ), 134 array(), 135 CUSTOM_PERMALINKS_VERSION, 136 array( 137 'strategy' => 'async', 138 'in_footer' => true, 139 ) 140 ); 141 142 wp_enqueue_style( 143 'custom-permalinks-post-settings', 144 plugins_url( 145 '/assets/css/post-settings' . $this->css_file_suffix, 146 CUSTOM_PERMALINKS_FILE 147 ), 148 array(), 149 CUSTOM_PERMALINKS_VERSION 95 150 ); 96 151 } … … 140 195 public function taxonomy_permalinks_page() { 141 196 Custom_Permalinks_Taxonomies_Table::output(); 197 198 add_filter( 'admin_footer_text', array( $this, 'admin_footer_text' ), 1 ); 199 } 200 201 /** 202 * Calls another Function which shows the Post Types Settings Page. 203 * 204 * @since 3.0.0 205 */ 206 public function post_settings_page() { 207 new Custom_Permalinks_Post_Types_Settings(); 142 208 143 209 add_filter( 'admin_footer_text', array( $this, 'admin_footer_text' ), 1 ); -
custom-permalinks/trunk/admin/class-custom-permalinks-post-types.php
r3136157 r3332124 26 26 27 27 $total_posts = wp_cache_get( 'total_posts_result', 'custom_permalinks' ); 28 if ( !$total_posts ) {28 if ( false === $total_posts ) { 29 29 $sql_query = " 30 30 SELECT COUNT(p.ID) FROM $wpdb->posts AS p … … 63 63 } 64 64 65 wp_cache_set( 'total_posts_result', $total_posts, 'custom_permalinks' );65 wp_cache_set( 'total_posts_result', $total_posts, 'custom_permalinks', 60 ); 66 66 } 67 67 … … 84 84 85 85 $posts = wp_cache_get( 'post_type_results', 'custom_permalinks' ); 86 if ( !$posts ) {86 if ( false === $posts ) { 87 87 $page_offset = ( $page_number - 1 ) * $per_page; 88 88 $order_by = 'p.ID'; … … 156 156 // phpcs:enable WordPress.Security.NonceVerification.Recommended 157 157 158 wp_cache_set( 'post_type_results', $posts, 'custom_permalinks' );158 wp_cache_set( 'post_type_results', $posts, 'custom_permalinks', 60 ); 159 159 } 160 160 -
custom-permalinks/trunk/admin/class-custom-permalinks-taxonomies.php
r2844616 r3332124 39 39 public static function total_permalinks() { 40 40 $total_taxonomies = wp_cache_get( 'total_taxonomies_result', 'custom_permalinks' ); 41 if ( !$total_taxonomies ) {41 if ( false === $total_taxonomies ) { 42 42 $search_taxonomy = array(); 43 43 $taxonomy_table = get_option( 'custom_permalink_table' ); … … 66 66 } 67 67 68 wp_cache_set( 'total_taxonomies_result', $total_taxonomies, 'custom_permalinks' );68 wp_cache_set( 'total_taxonomies_result', $total_taxonomies, 'custom_permalinks', 60 ); 69 69 } 70 70 … … 85 85 public static function get_permalinks( $per_page = 20, $page_number = 1 ) { 86 86 $taxonomies = wp_cache_get( 'taxonomies_results', 'custom_permalinks' ); 87 if ( !$taxonomies ) {87 if ( false === $taxonomies ) { 88 88 $page_offset = ( $page_number - 1 ) * $per_page; 89 89 $taxonomy_table = get_option( 'custom_permalink_table' ); … … 130 130 } 131 131 132 wp_cache_set( 'taxonomies_results', $taxonomies, 'custom_permalinks' );132 wp_cache_set( 'taxonomies_results', $taxonomies, 'custom_permalinks', 60 ); 133 133 } 134 134 -
custom-permalinks/trunk/changelog.txt
r2842482 r3332124 2 2 3 3 This file contains only old changelog. See readme.txt for newer versions. 4 5 = 2.8.0 - Apr 29, 2025 = 6 7 * Bug: 8 * Resolved pagination issue with custom permalinks (now supports /page/{number} format correctly). 9 * Enhancements: 10 * Added compatibility with Polylang 3.7. 11 * Metabox is now hidden for post types that are not publicly queryable. 12 13 = 2.7.0 - Aug 20, 2024 = 14 15 * Bug 16 * [Passing null to parameter string is deprecated](https://github.com/samiahmedsiddiqui/custom-permalinks/pull/86) 17 * [Fix PHP warning with empty permalink on new page/post](https://github.com/samiahmedsiddiqui/custom-permalinks/pull/87) 18 * [Authenticated(Editor+) Stored Cross-Site Scripting](https://github.com/samiahmedsiddiqui/custom-permalinks/pull/96) 19 * Enhancement: 20 * [Improve I18N](https://github.com/samiahmedsiddiqui/custom-permalinks/pull/72) 21 22 = 2.6.0 - Aug 15, 2024 = 23 24 * Feature Additions: 25 * Compatibility with PolyLang Plugin 26 27 = 2.5.2 - Feb 14, 2023 = 28 29 * Bug 30 * [Error in new update](https://wordpress.org/support/topic/error-in-new-update-3/) 31 32 = 2.5.1 - Feb 14, 2023 = 33 34 * Bug 35 * [“http//” is added in front of permalinks](https://github.com/samiahmedsiddiqui/custom-permalinks/issues/71) 36 37 = 2.5.0 - Jan 02, 2023 = 38 39 * Bugs 40 * [Retreiving info from installed plugin (GDPR)](https://wordpress.org/support/topic/retreiving-info-from-installed-plugin-gdpr/) 41 * Enhancement 42 * Same permalink with WPML different domain 43 44 = 2.4.0 - Nov 26, 2021 = 45 46 * Bugs 47 * [filter for leading special characters](https://wordpress.org/support/topic/filter-for-leading-special-characters/) 48 * [“search Permalinks” button doesn’t work. (part2)](https://wordpress.org/support/topic/search-permalinks-button-doesnt-work-part2/) 49 * [PHP 8 errors on first visit of Taxonomy Permalinks tab](https://github.com/samiahmedsiddiqui/custom-permalinks/issues/59) 50 * [Notice: Undefined variable: site_url in custom-permalinks/admin/class-custom-permalinks-post-types-table.php on line 306](https://github.com/samiahmedsiddiqui/custom-permalinks/issues/56) 51 * Enhancements 52 * [Pending Post Preview Link](https://wordpress.org/support/topic/pending-post-preview-link/) 4 53 5 54 = 2.3.0 - Sep 21, 2021 = -
custom-permalinks/trunk/custom-permalinks.php
r3284095 r3332124 4 4 * Plugin URI: https://www.custompermalinks.com/ 5 5 * Description: Set custom permalinks on a per-post basis. 6 * Version: 2.8.06 * Version: 3.0.0 7 7 * Requires at least: 2.6 8 8 * Requires PHP: 7.0 -
custom-permalinks/trunk/includes/class-custom-permalinks-form.php
r3284095 r3332124 44 44 add_action( 'add_meta_boxes', array( $this, 'permalink_edit_box' ) ); 45 45 add_action( 'save_post', array( $this, 'save_post' ), 10, 3 ); 46 add_action( 'pmxi_saved_post', array( $this, 'pmxi_post_permalink' ), 10, 3 ); 47 add_action( 48 'custom_permalinks_generate_post_permalink', 49 array( $this, 'generate_post_permalink' ), 50 10, 51 1 52 ); 46 53 add_action( 'delete_post', array( $this, 'delete_permalink' ), 10 ); 47 54 add_action( 'category_add_form', array( $this, 'term_options' ) ); … … 70 77 71 78 /** 72 * Initialize WordPress Hooks.79 * Check whether the permalink can be customized/generates on this post or not. 73 80 * 74 81 * @since 1.6.0 … … 79 86 * return bool false Whether to show Custom Permalink form or not. 80 87 */ 81 private function exclude_custom_permalinks( $post ) {88 private function is_permalink_customizable( $post ) { 82 89 $exclude_post_types = apply_filters( 83 90 'custom_permalinks_exclude_post_type', … … 347 354 348 355 $permalink = preg_replace( '/\s+/', '-', $permalink ); 349 $permalink = preg_replace( ' |-+|', '-', $permalink );356 $permalink = preg_replace( '/(\-+)/', '-', $permalink ); 350 357 $permalink = str_replace( '-/', '/', $permalink ); 351 358 $permalink = str_replace( '/-', '/', $permalink ); … … 365 372 366 373 /** 374 * Check whether the permalink exists or not. If exists append unique number 375 * at the end of it to prevent making duplicate permalinks. 376 * 377 * @since 3.0.0 378 * @access private 379 * 380 * @param int $post_id Post ID. 381 * @param string $permalink Permalink which is going to be set. 382 * @param string $language_code Page Language if multi-langauge is enabled. 383 * 384 * @return string 385 */ 386 private function check_permalink_exists( $post_id, $permalink, $language_code ) { 387 global $wpdb; 388 389 $trailing_slash = substr( $permalink, -1 ); 390 if ( '/' === $trailing_slash ) { 391 $permalink = rtrim( $permalink, '/' ); 392 } 393 394 $append_number = 1; 395 $init_permalink = $permalink; 396 while ( 1 ) { 397 // First, check permalink before appending number. 398 if ( 1 < $append_number ) { 399 $permalink = $init_permalink . '-' . $append_number; 400 } 401 402 if ( null !== $language_code ) { 403 // phpcs:disable WordPress.DB.DirectDatabaseQuery.NoCaching 404 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery 405 $existing_url_ids = $wpdb->get_col( 406 $wpdb->prepare( 407 "SELECT pm.`post_id` FROM $wpdb->postmeta AS pm 408 INNER JOIN $wpdb->posts AS p ON (p.`ID` = pm.`post_id`) 409 WHERE pm.`post_id` != %d 410 AND pm.`meta_key` = 'custom_permalink' 411 AND p.`post_status` != 'inherit' 412 AND (pm.`meta_value` = %s OR pm.`meta_value` = %s)", 413 $post_id, 414 $permalink, 415 $permalink . '/' 416 ) 417 ); 418 // phpcs:enable WordPress.DB.DirectDatabaseQuery.NoCaching 419 420 $check_exist_url = null; 421 foreach ( $existing_url_ids as $existing_url_id ) { 422 $existing_url_lang = get_post_meta( $existing_url_id, 'custom_permalink_language', true ); 423 if ( $existing_url_lang === $language_code ) { 424 $check_exist_url = 1; 425 break; 426 } 427 } 428 } else { 429 // phpcs:disable WordPress.DB.DirectDatabaseQuery.NoCaching 430 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery 431 $check_exist_url = $wpdb->get_var( 432 $wpdb->prepare( 433 "SELECT COUNT(pm.`post_id`) FROM $wpdb->postmeta AS pm 434 INNER JOIN $wpdb->posts AS p ON (p.`ID` = pm.`post_id`) 435 WHERE pm.`post_id` != %d 436 AND pm.`meta_key` = 'custom_permalink' 437 AND p.`post_status` != 'inherit' 438 AND (pm.`meta_value` = %s OR pm.`meta_value` = %s)", 439 $post_id, 440 $permalink, 441 $permalink . '/' 442 ) 443 ); 444 // phpcs:enable WordPress.DB.DirectDatabaseQuery.NoCaching 445 } 446 447 // Check URL should not be duplicated in any post Permalink. 448 if ( empty( $check_exist_url ) ) { 449 $existing_post_id = url_to_postid( $permalink ); 450 if ( 0 === $existing_post_id || $post_id === $existing_post_id ) { 451 break; 452 } 453 } 454 455 ++$append_number; 456 } 457 458 if ( '/' === $trailing_slash ) { 459 $permalink = $permalink . '/'; 460 } 461 462 if ( 0 === strpos( $permalink, '/' ) ) { 463 $permalink = substr( $permalink, 1 ); 464 } 465 466 return $permalink; 467 } 468 469 /** 470 * Clear post permalink cache if exists. 471 * 472 * @since 3.0.0 473 * @access private 474 * 475 * @param string $cached_permalink Permalink for which cache needs to be cleared. 476 */ 477 private function clear_post_permalink_cache( $cached_permalink ) { 478 if ( ! empty( $cached_permalink ) ) { 479 $cache_name = 'cp$_' . str_replace( '/', '-', $cached_permalink ) . '_#cp'; 480 $cache_exists = wp_cache_get( $cache_name, 'custom_permalinks' ); 481 if ( false !== $cache_exists ) { 482 wp_cache_delete( $cache_name, 'custom_permalinks' ); 483 } 484 } 485 } 486 487 /** 367 488 * Save per-post options. 368 489 * … … 371 492 * @param int $post_id Post ID. 372 493 * @param WP_Post $post Post object. 373 * 374 * @return void 375 */ 376 public function save_post( $post_id, $post ) { 377 if ( ! isset( $_REQUEST['_custom_permalinks_post_nonce'] ) 378 && ! isset( $_REQUEST['custom_permalink'] ) 494 * @param bool $update Whether this is an existing post being updated or not. 495 */ 496 public function save_post( $post_id, $post, $update ) { 497 /* 498 * Enable permalink regeneration on creating new post if permalink structure 499 * is defined for the post type. 500 */ 501 if ( ! $update ) { 502 $permalink_structure = ''; 503 $post_types_settings = get_option( 'custom_permalinks_post_types_settings', array() ); 504 505 if ( isset( $post_types_settings[ $post->post_type ] ) ) { 506 $permalink_structure = $post_types_settings[ $post->post_type ]; 507 } 508 509 /* 510 * Permalink structure is not defined in the Plugin Settings. 511 */ 512 if ( ! empty( $permalink_structure ) ) { 513 // Make it 1 to keep generating permalink on updating the post. 514 update_post_meta( $post_id, 'custom_permalink_regenerate_status', 1 ); 515 } 516 } 517 518 if ( 'auto-draft' === sanitize_title( $post->post_title ) ) { 519 return; 520 } 521 522 if ( isset( $_REQUEST['_custom_permalinks_post_nonce'] ) 523 && isset( $_REQUEST['custom_permalink'] ) 379 524 ) { 380 return; 381 } 382 383 $action = 'custom-permalinks_' . $post_id; 384 // phpcs:disable WordPress.Security.ValidatedSanitizedInput.MissingUnslash 385 // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized 386 if ( ! wp_verify_nonce( $_REQUEST['_custom_permalinks_post_nonce'], $action ) ) { 387 return; 388 } 389 // phpcs:enable WordPress.Security.ValidatedSanitizedInput.MissingUnslash 525 $action = 'custom-permalinks_' . $post_id; 526 // phpcs:disable WordPress.Security.ValidatedSanitizedInput.MissingUnslash 527 // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized 528 if ( ! wp_verify_nonce( $_REQUEST['_custom_permalinks_post_nonce'], $action ) ) { 529 return; 530 } 531 // phpcs:enable WordPress.Security.ValidatedSanitizedInput.MissingUnslash 532 } 533 534 if ( 'inherit' === $post->post_status ) { 535 $post_parent_id = $post->post_parent; 536 if ( ! empty( $post_parent_id ) ) { 537 $post_id = $post_parent_id; 538 $post = get_post( $post_parent_id ); 539 } 540 } 541 542 $current_permalink = get_post_meta( $post_id, 'custom_permalink', true ); 543 $is_refresh = get_post_meta( $post_id, 'custom_permalink_regenerate_status', true ); 544 545 // Make it 0 if not exist. 546 if ( empty( $is_refresh ) ) { 547 $is_refresh = 0; 548 } 549 550 /* 551 * Make sure that the post saved from quick edit form so, just make the 552 * $_REQUEST['custom_permalink'] same as $current_permalink to regenerate permalink 553 * if applicable. 554 */ 555 if ( ! isset( $_REQUEST['custom_permalink'] ) ) { 556 $_REQUEST['custom_permalink'] = $current_permalink; 557 } 558 559 $is_regenerated = false; 560 if ( 'trash' !== $post->post_status 561 && $current_permalink === $_REQUEST['custom_permalink'] 562 && 1 === (int) $is_refresh 563 ) { 564 $cp_post_permalinks = new Custom_Permalinks_Generate_Post_Permalinks(); 565 $is_regenerated = $cp_post_permalinks->generate( $post_id, $post ); 566 } 390 567 391 568 $cp_frontend = new Custom_Permalinks_Frontend(); 392 569 $original_link = $cp_frontend->original_post_link( $post_id ); 393 394 570 if ( ! empty( $_REQUEST['custom_permalink'] ) 395 571 && $_REQUEST['custom_permalink'] !== $original_link 572 && $_REQUEST['custom_permalink'] !== $current_permalink 396 573 ) { 397 574 $language_code = apply_filters( … … 403 580 ) 404 581 ); 582 if ( null !== $language_code ) { 583 update_post_meta( $post_id, 'custom_permalink_language', $language_code ); 584 } else { 585 delete_metadata( 'post', $post_id, 'custom_permalink_language' ); 586 } 405 587 406 588 $permalink = $this->sanitize_permalink( … … 409 591 $language_code 410 592 ); 593 $permalink = $this->check_permalink_exists( $post_id, $permalink, $language_code ); 411 594 $permalink = apply_filters( 412 595 'custom_permalink_before_saving', 413 596 $permalink, 414 $post_id 597 $post_id, 598 $language_code 415 599 ); 416 600 417 601 update_post_meta( $post_id, 'custom_permalink', $permalink ); 418 if ( null !== $language_code ) { 419 update_post_meta( $post_id, 'custom_permalink_language', $language_code ); 420 } else { 421 delete_metadata( 'post', $post_id, 'custom_permalink_language' ); 422 } 602 603 // Clear cache for the previous and updated permalink. 604 $this->clear_post_permalink_cache( $current_permalink ); 605 $this->clear_post_permalink_cache( $permalink ); 606 607 // If true means it triggers from the regeneration code so don't override it. 608 if ( ! $is_regenerated ) { 609 // Delete to prevent generating permalink on updating the post. 610 delete_post_meta( $post_id, 'custom_permalink_regenerate_status' ); 611 } 612 } 613 } 614 615 /** 616 * This action fires when WP All Import saves a post of any type. 617 * 618 * @since 3.0.0 619 * @access public 620 * 621 * @param int $post_id The ID of the item (post/user/taxonomy) saved or updated. 622 * @param SimpleXMLElement $xml_node The libxml resource of the current XML element. 623 * @param bool $is_update Returns 0 for new item 1 for updated item. 624 * 625 * @return void 626 */ 627 public function pmxi_post_permalink( $post_id, $xml_node, $is_update ) { 628 $post = get_post( $post_id ); 629 if ( is_object( $post ) && isset( $post->post_type ) ) { 630 $updated = false; 631 if ( 1 === $is_update ) { 632 $updated = true; 633 } 634 635 $this->save_post( $post_id, $post, $updated ); 636 } 637 } 638 639 /** 640 * Generates post permalink for the provided post id. 641 * 642 * @since 3.0.0 643 * @access public 644 * 645 * @param int $post_id Post ID. 646 * 647 * @return void 648 */ 649 public function generate_post_permalink( $post_id ) { 650 $post = get_post( $post_id ); 651 if ( is_object( $post ) && isset( $post->post_type ) ) { 652 $this->save_post( $post_id, $post, false ); 423 653 } 424 654 } … … 434 664 */ 435 665 public function delete_permalink( $post_id ) { 666 // Clear cache for the deleting post. 667 $permalink = get_post_meta( $post_id, 'custom_permalink', true ); 668 $this->clear_post_permalink_cache( $permalink ); 669 436 670 delete_metadata( 'post', $post_id, 'custom_permalink' ); 437 671 } … … 615 849 $post = get_post( $post_id ); 616 850 617 $ disable_cp = $this->exclude_custom_permalinks( $post );851 $is_customizable = $this->is_permalink_customizable( $post ); 618 852 $this->permalink_metabox = 1; 619 if ( $ disable_cp) {853 if ( $is_customizable ) { 620 854 return $html; 621 855 } … … 635 869 */ 636 870 public function meta_edit_form( $post ) { 637 $ disable_cp = $this->exclude_custom_permalinks( $post );638 if ( $ disable_cp) {871 $is_customizable = $this->is_permalink_customizable( $post ); 872 if ( $is_customizable ) { 639 873 wp_enqueue_script( 640 874 'custom-permalinks-form', … … 787 1021 true 788 1022 ); 789 790 echo esc_url( $home_url ) . 791 '<span id="editable-post-name" title="Click to edit this part of the permalink">';792 793 if ( isset( $postname ) && '' !== $postname ) : 794 ?>1023 ?> 1024 1025 <span id="uneditable-permalink"><?php echo esc_url( $home_url ); ?></span> 1026 <span id="editable-post-name" title="Click to edit this part of the permalink"> 1027 1028 <?php if ( isset( $postname ) && '' !== $postname ) : ?> 795 1029 796 1030 <input type="hidden" id="new-post-slug" class="text" value="<?php echo esc_attr( $postname ); ?>" /> -
custom-permalinks/trunk/includes/class-custom-permalinks-frontend.php
r3284095 r3332124 77 77 add_filter( 'post_type_link', array( $this, 'custom_post_link' ), 10, 2 ); 78 78 add_filter( 'page_link', array( $this, 'custom_page_link' ), 10, 2 ); 79 add_filter( 'url_to_postid', array( $this, 'postid_to_customized_permalink' ), 10, 1 ); 79 80 add_filter( 'term_link', array( $this, 'custom_term_link' ), 10, 2 ); 80 81 add_filter( 'user_trailingslashit', array( $this, 'custom_trailingslash' ) ); … … 202 203 $posts = wp_cache_get( $cache_name, 'custom_permalinks' ); 203 204 204 if ( !$posts ) {205 if ( false === $posts ) { 205 206 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery 206 207 $posts = $wpdb->get_results( … … 238 239 } 239 240 240 wp_cache_set( $cache_name, $posts, 'custom_permalinks' ); 241 // Cache permalink for 24 hours. 242 wp_cache_set( $cache_name, $posts, 'custom_permalinks', 86400 ); 241 243 } 242 244 … … 267 269 } 268 270 269 if ( !$matched_post ) {271 if ( false === $matched_post ) { 270 272 $matched_post = array(); 271 273 … … 306 308 } 307 309 308 wp_cache_set( $cache_name, $matched_post, 'custom_permalinks' ); 310 // Cache permalink for 24 hours. 311 wp_cache_set( $cache_name, $matched_post, 'custom_permalinks', 86400 ); 309 312 310 313 return $matched_post; … … 713 716 } 714 717 715 $custom_permalink = '';716 $original_permalink = '';717 718 718 // Get request URI, strip parameters. 719 719 $url = wp_parse_url( get_bloginfo( 'url' ) ); … … 735 735 * @since 1.7.0 736 736 */ 737 $avoid_redirect = apply_filters( 738 'custom_permalinks_avoid_redirect', 739 $request 740 ); 741 737 $avoid_redirect = apply_filters( 'custom_permalinks_avoid_redirect', $request ); 742 738 if ( is_bool( $avoid_redirect ) && $avoid_redirect ) { 743 739 return; 744 740 } 745 741 746 if ( defined( 'POLYLANG_VERSION' ) ) { 747 $cp_form = new Custom_Permalinks_Form(); 748 $request = $cp_form->check_conflicts( $request ); 749 } 750 751 $request_no_slash = preg_replace( '@/+@', '/', trim( $request, '/' ) ); 752 $posts = $this->query_post( $request_no_slash ); 753 754 if ( ! isset( $posts[0]->ID ) || ! isset( $posts[0]->meta_value ) 755 || empty( $posts[0]->meta_value ) 756 ) { 757 global $wp_query; 758 759 /* 760 * If the post/tag/category we're on has a custom permalink, get it 761 * and check against the request. 762 */ 763 if ( ( is_single() || is_page() ) && ! empty( $wp_query->post ) ) { 764 $post = $wp_query->post; 765 $custom_permalink = get_post_meta( 766 $post->ID, 767 'custom_permalink', 768 true 769 ); 770 if ( 'page' === $post->post_type ) { 771 $original_permalink = $this->original_page_link( $post->ID ); 772 } else { 773 $original_permalink = $this->original_post_link( $post->ID ); 774 } 775 } elseif ( is_tag() || is_category() ) { 776 $the_term = $wp_query->get_queried_object(); 777 $custom_permalink = $this->term_permalink( $the_term->term_id ); 778 $original_permalink = $this->original_term_link( $the_term->term_id ); 742 $custom_permalink = ''; 743 $original_permalink = ''; 744 $get_post_id = url_to_postid( $this->request_uri ); 745 746 // Redirect original post permalink. 747 if ( ! empty( $get_post_id ) ) { 748 $custom_permalink = get_post_meta( $get_post_id, 'custom_permalink', true ); 749 if ( ! empty( $custom_permalink ) ) { 750 // Append any query component. 751 $custom_permalink .= strstr( $this->request_uri, '?' ); 752 753 wp_safe_redirect( home_url() . '/' . $custom_permalink, 301 ); 754 exit( 0 ); 779 755 } 780 756 } else { 781 $custom_permalink = $posts[0]->meta_value; 782 if ( 'page' === $posts[0]->post_type ) { 783 $original_permalink = $this->original_page_link( $posts[0]->ID ); 784 } else { 785 $original_permalink = $this->original_post_link( $posts[0]->ID ); 786 } 787 } 788 789 $custom_length = strlen( $custom_permalink ); 790 if ( $custom_permalink 791 && ( 792 substr( $request, 0, $custom_length ) !== $custom_permalink 793 || $request === $custom_permalink . '/' 794 ) 795 ) { 796 // Request doesn't match permalink - redirect. 797 $url = $custom_permalink; 798 $original_length = strlen( $original_permalink ); 799 800 if ( substr( $request, 0, $original_length ) === $original_permalink 801 && trim( $request, '/' ) !== trim( $original_permalink, '/' ) 757 if ( defined( 'POLYLANG_VERSION' ) ) { 758 $cp_form = new Custom_Permalinks_Form(); 759 $request = $cp_form->check_conflicts( $request ); 760 } 761 762 $request_no_slash = preg_replace( '@/+@', '/', trim( $request, '/' ) ); 763 $posts = $this->query_post( $request_no_slash ); 764 765 if ( ! isset( $posts[0]->ID ) || ! isset( $posts[0]->meta_value ) 766 || empty( $posts[0]->meta_value ) 802 767 ) { 803 // This is the original link; we can use this URL to derive the new one. 804 $url = preg_replace( 805 '@//*@', 806 '/', 807 str_replace( 808 trim( $original_permalink, '/' ), 809 trim( $custom_permalink, '/' ), 810 $request 811 ) 812 ); 813 $url = preg_replace( '@([^?]*)&@', '\1?', $url ); 814 } 815 816 // Append any query component. 817 $url .= strstr( $this->request_uri, '?' ); 818 819 wp_safe_redirect( home_url() . '/' . $url, 301 ); 820 exit( 0 ); 768 global $wp_query; 769 770 /* 771 * If the post/tag/category we're on has a custom permalink, get it 772 * and check against the request. 773 */ 774 if ( ( is_single() || is_page() ) && ! empty( $wp_query->post ) ) { 775 $post = $wp_query->post; 776 $custom_permalink = get_post_meta( 777 $post->ID, 778 'custom_permalink', 779 true 780 ); 781 if ( 'page' === $post->post_type ) { 782 $original_permalink = $this->original_page_link( $post->ID ); 783 } else { 784 $original_permalink = $this->original_post_link( $post->ID ); 785 } 786 } elseif ( is_tag() || is_category() ) { 787 $the_term = $wp_query->get_queried_object(); 788 $custom_permalink = $this->term_permalink( $the_term->term_id ); 789 $original_permalink = $this->original_term_link( $the_term->term_id ); 790 } 791 } 792 793 $custom_length = strlen( $custom_permalink ); 794 if ( $custom_permalink 795 && ( 796 substr( $request, 0, $custom_length ) !== $custom_permalink 797 || $request === $custom_permalink . '/' 798 ) 799 ) { 800 // Request doesn't match permalink - redirect. 801 $url = $custom_permalink; 802 $original_length = strlen( $original_permalink ); 803 804 if ( substr( $request, 0, $original_length ) === $original_permalink 805 && trim( $request, '/' ) !== trim( $original_permalink, '/' ) 806 ) { 807 // This is the original link; we can use this URL to derive the new one. 808 $url = preg_replace( 809 '@//*@', 810 '/', 811 str_replace( 812 trim( $original_permalink, '/' ), 813 trim( $custom_permalink, '/' ), 814 $request 815 ) 816 ); 817 $url = preg_replace( '@([^?]*)&@', '\1?', $url ); 818 } 819 820 // Append any query component. 821 $url .= strstr( $this->request_uri, '?' ); 822 823 wp_safe_redirect( home_url() . '/' . $url, 301 ); 824 exit( 0 ); 825 } 821 826 } 822 827 } … … 924 929 925 930 /** 931 * Fetch default permalink against the customized permalink. 932 * 933 * @since 3.0.0 934 * @access public 935 * 936 * @param string $permalink URL Permalink to check. 937 * 938 * @return string Default Permalink or the same permalink if not found. 939 */ 940 public function postid_to_customized_permalink( $permalink ) { 941 $customized_permalink = ltrim( substr( $permalink, strlen( $url ) ), '/' ); 942 if ( defined( 'POLYLANG_VERSION' ) ) { 943 $cp_form = new Custom_Permalinks_Form(); 944 $customized_permalink = $cp_form->check_conflicts( $customized_permalink ); 945 } 946 947 $customized_permalink = preg_replace( '@/+@', '/', trim( $customized_permalink, '/' ) ); 948 $posts = $this->query_post( $customized_permalink ); 949 if ( is_array( $posts ) && ! empty( $posts ) ) { 950 if ( 'draft' === $posts[0]->post_status 951 || 'pending' === $posts[0]->post_status 952 ) { 953 if ( 'page' === $posts[0]->post_type ) { 954 $original_url = '?page_id=' . $posts[0]->ID; 955 } else { 956 $original_url = '?post_type=' . $posts[0]->post_type . '&p=' . $posts[0]->ID; 957 } 958 } else { 959 $post_meta = trim( strtolower( $posts[0]->meta_value ), '/' ); 960 if ( 'page' === $posts[0]->post_type ) { 961 $get_original_url = $this->original_page_link( $posts[0]->ID ); 962 $original_url = preg_replace( 963 '@/+@', 964 '/', 965 str_replace( 966 $post_meta, 967 $get_original_url, 968 strtolower( $customized_permalink ) 969 ) 970 ); 971 } else { 972 $get_original_url = $this->original_post_link( $posts[0]->ID ); 973 $original_url = preg_replace( 974 '@/+@', 975 '/', 976 str_replace( 977 $post_meta, 978 $get_original_url, 979 strtolower( $customized_permalink ) 980 ) 981 ); 982 } 983 } 984 985 $permalink = $original_url; 986 } 987 988 return $permalink; 989 } 990 991 /** 926 992 * Filter to replace the term permalink with the custom one. 927 993 * -
custom-permalinks/trunk/includes/class-custom-permalinks.php
r3284095 r3332124 19 19 * @var string 20 20 */ 21 public $version = ' 2.8.0';21 public $version = '3.0.0'; 22 22 23 23 /** … … 65 65 private function includes() { 66 66 include_once CUSTOM_PERMALINKS_PATH . 'includes/class-custom-permalinks-form.php'; 67 include_once CUSTOM_PERMALINKS_PATH . 'includes/class-custom-permalinks-generate-post-permalinks.php'; 67 68 include_once CUSTOM_PERMALINKS_PATH . 'includes/class-custom-permalinks-frontend.php'; 68 69 include_once CUSTOM_PERMALINKS_PATH . 'admin/class-custom-permalinks-admin.php'; 70 include_once CUSTOM_PERMALINKS_PATH . 'admin/class-custom-permalinks-post-types-settings.php'; 69 71 include_once CUSTOM_PERMALINKS_PATH . 'admin/class-custom-permalinks-post-types.php'; 70 72 include_once CUSTOM_PERMALINKS_PATH . 'admin/class-custom-permalinks-post-types-table.php'; … … 107 109 */ 108 110 public static function add_roles() { 109 $admin_role = get_role( 'administrator' ); 110 $cp_role = get_role( 'custom_permalinks_manager' ); 111 $current_version = get_option( 'custom_permalinks_plugin_version', -1 ); 111 $admin_role = get_role( 'administrator' ); 112 $cp_role = get_role( 'custom_permalinks_manager' ); 112 113 113 114 if ( ! empty( $admin_role ) ) { 115 $admin_role->add_cap( 'custom_permalinks_post_settings' ); 114 116 $admin_role->add_cap( 'cp_view_post_permalinks' ); 115 117 $admin_role->add_cap( 'cp_view_category_permalinks' ); … … 121 123 __( 'Custom Permalinks Manager' ), 122 124 array( 123 'cp_view_post_permalinks' => true, 124 'cp_view_category_permalinks' => true, 125 'custom_permalinks_post_settings' => true, 126 'cp_view_post_permalinks' => true, 127 'cp_view_category_permalinks' => true, 125 128 ) 126 129 ); -
custom-permalinks/trunk/readme.txt
r3284095 r3332124 1 1 === Custom Permalinks === 2 2 Contributors: sasiddiqui 3 Tags: permalink, url, link, address, redirect, custom post type 3 Tags: permalink, url, link, address, redirect 4 Requires at least: 5.0 5 Requires PHP: 5.6 4 6 Tested up to: 6.8 5 Stable tag: 2.8.07 Stable tag: 3.0.0 6 8 License: GPLv3 7 9 License URI: https://www.gnu.org/licenses/gpl-3.0.html 8 10 9 Set custom permalinks on a per-post, per-tag or per-category basis.11 Custom Permalinks is a powerful WordPress plugin that grants you complete control over your site's URLs. Easily set unique, custom permalinks for any post, page, tag, or category, allowing you to design an ideal site structure. It includes features for defining post type-specific structures with dynamic tags and automatically redirects old URLs to your new custom ones. Developers can also leverage a wide array of filters for advanced customization. 10 12 11 13 == Description == 12 14 13 > In case of found any site breaking issue after upgrading to the latest version then please report the issue on [WordPress Forum](https://wordpress.org/support/plugin/custom-permalinks/) OR [GitHub](https://github.com/samiahmedsiddiqui/custom-permalinks) with complete information to reproduce the issue and move back to the old version. You can download any of the old version from here: https://wordpress.org/plugins/custom-permalinks/advanced/ 15 You want to take control of your WordPress site's URLs? The **Custom Permalinks** plugin gives you the power to set unique, custom URLs for any post, page, tag, or category. This means you can design your site's structure exactly how you envision it, rather than being limited by WordPress's default settings. When you set a custom permalink, the original post URL will be automatically redirected to your new, customized URL. 14 16 15 Lay out your site the way *you* want it. Set the URL of any post, page, tag or category to anything you want. Old permalinks will redirect properly to the new address. Custom Permalinks give you ultimate control over your site structure. 17 === Key Features === 16 18 17 > Be warned: *This plugin is not a replacement for WordPress's built-in permalink system*. Check your WordPress administration's "Permalinks" settings page first, to make sure that this doesn't already meet your needs. 19 * **Individual Permalink Control**: Assign unique URLs to any post, page, tag, or category. 20 * **Site Structure Control**: Gain ultimate control over how your site's URLs are organized. 21 * **Post Type Permalink Structures (v3.0.0+)**: Define custom permalink structures for each public Post Type using predefined tags, automatically generating URLs upon content creation. You can still manually edit any permalink. If left empty, default settings will apply. 18 22 19 This plugin is only useful for assigning custom permalinks for *individual* posts, pages, tags or categories. It will not apply whole permalink structures or automatically apply a category's custom permalink to the posts within that category. 23 === Getting Started: Plugin Settings === 20 24 21 == Filters == 25 You can configure Custom Permalinks by navigating to **Settings \> Custom Permalinks** in your WordPress Dashboard. 22 26 23 === A dd `PATH_INFO` in `$_SERVER` Variable===27 === Available Tags for Permalink Structures === 24 28 25 ` 26 add_filter( 'custom_permalinks_path_info', '__return_true' ); 27 ` 29 When setting up your custom permalink structures, you can use a variety of tags that will dynamically populate the URL. Here's a breakdown of what's available: 28 30 29 === Disable Redirects === 31 * **%year%**: The year of the post in four digits, eg: 2025 32 * **%monthnum%**: Month the post was published, in two digits, eg: 01 33 * **%day%**: Day the post was published in two digits, eg: 02 34 * **%hour%**: Hour of the day, the post was published, eg: 15 35 * **%minute%**: Minute of the hour, the post was published, eg: 43 36 * **%second%**: Second of the minute, the post was published, eg: 33 37 * **%post_id%**: The unique ID of the post, eg: 123 38 * **%category%**: A clean version of the category name (its slug). Nested sub-categories will appear as nested directories in the URL.. 39 * **%author%**: A sanitized version of the post author’s name. 40 * **%postname%**: A clean version of the post or page title (its slug). For example, "This Is A Great Post\!" becomes `this-is-a-great-post` in the URL. 41 * **%parent_postname%**: Similar to `%postname%`, but uses the immediate parent page's slug if a parent is selected. 42 * **%parents_postnames%**: Similar to `%postname%`, but includes all parent page slugs if parents are selected. 43 * **%title%**: The title of the post, converted to a slug. For example, "This Is A Great Post\!" becomes `this-is-a-great-post`. Unlike `%postname%` which is set once, `%title%` automatically updates in the permalink if the post title changes (unless the post is published or the permalink is manually edited). 44 * **%ctax_TAXONOMY_NAME%**: A clean version of a custom taxonomy's name. Replace `TAXONOMY_NAME` with the actual taxonomy name. You can also provide a default slug for when no category/taxonomy is selected by using `??` (e.g., `%ctax_type??sales%` will use "sales" as a default). 45 * **%ctax_parent_TAXONOMY_NAME%**: Similar to `%ctax_TAXONOMY_NAME%`, but includes the immediate parent category/tag slug in the URL if a parent is selected. 46 * **%ctax_parents_TAXONOMY_NAME%**: Similar to `%ctax_TAXONOMY_NAME%`, but includes all parent category/tag slugs in the URL if parents are selected. 47 * **%custom_permalinks_TAG_NAME%**: Developers have the flexibility to define their own custom tags(replace `_TAG_NAME` with your desired name). To ensure these tags resolve to the correct permalinks, simply apply the `custom_permalinks_post_permalink_tag` filter. 30 48 31 To disable complete redirects functionality provided by this plugin, add the filter that looks like this: 49 **Important Note:** For new posts, Custom Permalinks will keep updating the permalink while the post is in draft mode, assuming a structure is defined in the plugin settings. Once the post is published or its permalink is manually updated, the plugin will stop automatic updates for that specific post. 32 50 33 ` 34 function yasglobal_avoid_redirect( $permalink ) { 35 return true; 36 } 37 add_filter( 'custom_permalinks_avoid_redirect', 'yasglobal_avoid_redirect' ); 38 ` 51 === Custom Permalinks: Fine-Tuning with Filters === 39 52 40 === Disable Particular Redirects === 53 Custom Permalinks offers a range of **filters** that empower developers to precisely control its behavior. You can explore all available filters, complete with example code snippets, in our [GitHub repository](https://github.com/samiahmedsiddiqui/custom-permalinks). 41 54 42 To disable any specific redirect to be processed by this plugin, add the filter that looks like this: 55 **For Assistance:** 43 56 44 ` 45 function yasglobal_avoid_redirect( $permalink ) { 46 // Replace 'testing-hello-world/' with the permalink you want to avoid 47 if ( 'testing-hello-world/' === $permalink ) { 48 return true; 49 } 57 * **Premium Users:** If you need assistance implementing these filters, please don't hesitate to reach out to us via our [Premium contact support](https://www.custompermalinks.com/contact-us/). 58 * **Other Users:** You can also directly reach out to the plugin author via [LinkedIn](https://www.linkedin.com/in/sami-ahmed-siddiqui/). 50 59 51 return false; 52 } 53 add_filter( 'custom_permalinks_avoid_redirect', 'yasglobal_avoid_redirect' ); 54 ` 60 === Need Help or Found a Bug? === 55 61 56 === Exclude Permalink to be processed === 62 * **Support:** For one-on-one email support, consider purchasing [Custom Permalinks Premium](https://www.custompermalinks.com/#pricing-section). While some basic support may be provided on the WordPress.org forums, email support is prioritized for premium users. 63 * **Bug Reports:** If you encounter a bug, please report it on [GitHub](https://github.com/samiahmedsiddiqui/custom-permalinks). Make sure to provide complete information to reproduce the issue. GitHub is for bug reports, not general support questions. 57 64 58 To exclude any Permalink to be processed by the plugin, add the filter that looks like this: 59 60 ` 61 function yasglobal_xml_sitemap_url( $permalink ) { 62 if ( false !== strpos( $permalink, 'sitemap.xml' ) ) { 63 return '__true'; 64 } 65 66 return; 67 } 68 add_filter( 'custom_permalinks_request_ignore', 'yasglobal_xml_sitemap_url' ); 69 ` 70 71 === Exclude Post Type === 72 73 To remove custom permalink **form** from any post type, add the filter that looks like this: 74 75 ` 76 function yasglobal_exclude_post_types( $post_type ) { 77 // Replace 'custompost' with your post type name 78 if ( 'custompost' === $post_type ) { 79 return '__true'; 80 } 81 82 return '__false'; 83 } 84 add_filter( 'custom_permalinks_exclude_post_type', 'yasglobal_exclude_post_types' ); 85 ` 86 87 === Exclude Posts === 88 89 To exclude custom permalink **form** from any posts (based on ID, Template, etc), add the filter that looks like this: 90 91 ` 92 function yasglobal_exclude_posts( $post ) { 93 if ( 1557 === $post->ID ) { 94 return true; 95 } 96 97 return false; 98 } 99 add_filter( 'custom_permalinks_exclude_posts', 'yasglobal_exclude_posts' ); 100 ` 101 102 === Allow Accents Letters === 103 104 To allow accents letters, please add below-mentioned line in your theme `functions.php`: 105 106 ` 107 function yasglobal_permalink_allow_accents() { 108 return true; 109 } 110 add_filter( 'custom_permalinks_allow_accents', 'yasglobal_permalink_allow_accents' ); 111 ` 112 113 === Allow Uppercase Letters === 114 115 To allow uppercase letters/words, please add below-mentioned line in your theme `functions.php`: 116 117 ` 118 function yasglobal_allow_uppercaps() { 119 return true; 120 } 121 add_filter( 'custom_permalinks_allow_caps', 'yasglobal_allow_uppercaps' ); 122 ` 123 124 === Allow Redundant Hyphens === 125 126 To allow redundant hyphens, please add below-mentioned line in your theme `functions.php`: 127 128 ` 129 function yasglobal_redundant_hyphens() { 130 return true; 131 } 132 add_filter( 'custom_permalinks_redundant_hyphens', 'yasglobal_redundant_hyphens' ); 133 ` 134 135 === Manipulate Permalink Before Saving === 136 137 To make changes in permalink before saving, please use `custom_permalink_before_saving` filter. Here is an example to see how it works. 138 139 ` 140 function yasglobal_permalink_before_saving( $permalink, $post_id ) { 141 // Check trialing slash in the permalink. 142 if ( substr( $permalink, -1 ) !== '/' ) { 143 // If permalink doesn't contain trialing slash then add one. 144 $permalink .= '/'; 145 } 146 147 return $permalink; 148 } 149 add_filter( 'custom_permalink_before_saving', 'yasglobal_permalink_before_saving', 10, 2 ); 150 ` 151 152 === Remove `like` Query === 153 154 To remove `like` query to being work, add below-mentioned line in your theme `functions.php`: 155 ` 156 add_filter( 'cp_remove_like_query', '__return_false' ); 157 ` 158 159 Note: Use `custom_permalinks_like_query` filter if the URLs doesn't works for you after upgrading to `v1.2.9`. 160 161 === Thanks for the Support === 162 163 I do not always provide active support for the Custom Permalinks plugin on the WordPress.org forums, as I have prioritized the email support. One-on-one email support is available to people who bought [Custom Permalinks Premium](https://www.custompermalinks.com/#pricing-section) only. 164 165 === Bug reports === 166 167 Bug reports for Custom Permalinks are [welcomed on GitHub](https://github.com/samiahmedsiddiqui/custom-permalinks). Please note GitHub is not a support forum, and issues that aren't properly qualified as bugs will be closed. 65 If you experience any site-breaking issues after upgrading, please report them on the [WordPress Forum](https://wordpress.org/support/plugin/custom-permalinks/) or [GitHub](https://github.com/samiahmedsiddiqui/custom-permalinks) with detailed information. You can always revert to an older version by downloading it from [https://wordpress.org/plugins/custom-permalinks/advanced/](https://wordpress.org/plugins/custom-permalinks/advanced/). 168 66 169 67 == Installation == 68 You have two ways to install Custom Permalinks: 170 69 171 This process defines you the steps to follow either you are installing through WordPress or Manually from FTP. 70 #### From within WordPress 172 71 173 **From within WordPress** 72 1. Go to **Plugins \> Add New** in your WordPress dashboard. 73 2. Search for "Custom Permalinks". 74 3. Click "Install Now" and then "Activate" the plugin from your Plugins page. 174 75 175 1. Visit 'Plugins > Add New' 176 2. Search for Custom Permalinks 177 3. Activate Custom Permalinks from your Plugins page. 76 #### Manually via FTP 178 77 179 **Manually** 180 181 1. Upload the `custom-permalinks` folder to the `/wp-content/plugins/` directory 182 2. Activate Custom Permalinks through the 'Plugins' menu in WordPress 78 1. Download the `custom-permalinks` folder. 79 2. Upload the `custom-permalinks` folder to your `/wp-content/plugins/` directory. 80 3. Activate Custom Permalinks through the "Plugins" menu in your WordPress dashboard. 183 81 184 82 == Changelog == 185 83 186 = 2.8.0 - Apr 29, 2025 =84 = 3.0.0 - Jul 22, 2025 = 187 85 188 * Bug: 189 * Resolved pagination issue with custom permalinks (now supports /page/{number} format correctly). 190 * Enhancements: 191 * Added compatibility with Polylang 3.7. 192 * Metabox is now hidden for post types that are not publicly queryable. 86 This release of Custom Permalinks brings significant enhancements to post type permalink management, introduces new customization options, and refines the overall user and developer experience. 193 87 194 = 2.7.0 - Aug 20, 2024 = 88 **Added** 195 89 196 * Bug 197 * [Passing null to parameter string is deprecated](https://github.com/samiahmedsiddiqui/custom-permalinks/pull/86) 198 * [Fix PHP warning with empty permalink on new page/post](https://github.com/samiahmedsiddiqui/custom-permalinks/pull/87) 199 * [Authenticated(Editor+) Stored Cross-Site Scripting](https://github.com/samiahmedsiddiqui/custom-permalinks/pull/96) 200 * Enhancement: 201 * [Improve I18N](https://github.com/samiahmedsiddiqui/custom-permalinks/pull/72) 90 * **Post Type Permalink Structures:** Introduced robust functionality to define custom permalink structures for each public Post Type directly within the plugin settings. This allows for automatic URL generation based on predefined tags upon content creation, offering greater flexibility while still allowing manual edits. 91 * **New Available Permalink Tags:** Expanded the list of dynamic tags that can be used in permalink structures, including: 92 * `%parent_postname%`: For immediate parent page slugs. 93 * `%parents_postnames%`: For all parent page slugs. 94 * `%title%`: A dynamic slug that updates with post title changes (until published or manually edited). 95 * `%ctax_parent_TAXONOMY_NAME%`: For immediate parent custom taxonomy slugs. 96 * `%ctax_parents_TAXONOMY_NAME%`: For all parent custom taxonomy slugs. 97 * `%custom_permalinks_TAG_NAME%`: Allows developers to define and resolve their own custom tags. 98 * **WP All Import Compatibility:** Added support to generate/update permalinks when importing posts using the WP All Import plugin. 99 * **New Filter Examples:** Included clear code examples for `custom_permalinks_post_permalink_tag` to set custom values from ACF fields, and for programmatically generating permalinks for single posts and entire post types. 202 100 203 = 2.6.0 - Aug 15, 2024 = 101 **Improved** 204 102 205 * Feature Additions: 206 * Compatibility with PolyLang Plugin 207 208 = 2.5.2 - Feb 14, 2023 = 209 210 * Bug 211 * [Error in new update](https://wordpress.org/support/topic/error-in-new-update-3/) 212 213 = 2.5.1 - Feb 14, 2023 = 214 215 * Bug 216 * [“http//” is added in front of permalinks](https://github.com/samiahmedsiddiqui/custom-permalinks/issues/71) 217 218 = 2.5.0 - Jan 02, 2023 = 219 220 * Bugs 221 * [Retreiving info from installed plugin (GDPR)](https://wordpress.org/support/topic/retreiving-info-from-installed-plugin-gdpr/) 222 * Enhancement 223 * Same permalink with WPML different domain 224 225 = 2.4.0 - Nov 26, 2021 = 226 227 * Bugs 228 * [filter for leading special characters](https://wordpress.org/support/topic/filter-for-leading-special-characters/) 229 * [“search Permalinks” button doesn’t work. (part2)](https://wordpress.org/support/topic/search-permalinks-button-doesnt-work-part2/) 230 * [PHP 8 errors on first visit of Taxonomy Permalinks tab](https://github.com/samiahmedsiddiqui/custom-permalinks/issues/59) 231 * [Notice: Undefined variable: site_url in custom-permalinks/admin/class-custom-permalinks-post-types-table.php on line 306](https://github.com/samiahmedsiddiqui/custom-permalinks/issues/56) 232 * Enhancements 233 * [Pending Post Preview Link](https://wordpress.org/support/topic/pending-post-preview-link/) 103 * **Post Caching:** Enhanced post caching mechanisms and optimized cache deletion upon updates for better performance. 104 * **Permalink Retrieval:** Improved logic to allow fetching posts against customized permalinks. 105 * **Filter Documentation:** Refined existing filter descriptions and improved code formatting for clarity. 106 * **Plugin Purpose Clarity:** Updated documentation to explicitly state that original post URLs will automatically redirect to the customized URLs, ensuring seamless transitions. 234 107 235 108 = Earlier versions = -
custom-permalinks/trunk/uninstall.php
r2575556 r3332124 15 15 delete_post_meta_by_key( 'custom_permalink' ); 16 16 delete_option( 'custom_permalink_table' ); 17 delete_option( 'custom_permalinks_post_types_settings' ); 17 18 18 19 $wp_role = get_role( 'administrator' ); … … 20 21 $wp_role->remove_cap( 'cp_view_post_permalinks' ); 21 22 $wp_role->remove_cap( 'cp_view_category_permalinks' ); 23 $wp_role->remove_cap( 'custom_permalinks_post_settings' ); 22 24 } 23 25 … … 26 28 $wp_role->remove_cap( 'cp_view_post_permalinks' ); 27 29 $wp_role->remove_cap( 'cp_view_category_permalinks' ); 30 $wp_role->remove_cap( 'custom_permalinks_post_settings' ); 28 31 29 32 remove_role( 'custom_permalinks_manager' );
Note: See TracChangeset
for help on using the changeset viewer.