Same url of image and post

Hi,
I upload image my-image.jpg and it automatically create page with this image - mywebsite.com/my-image/
Than I create post with title "My-image" and I want url mywebsite.com/my-image/ for this post but it is used so it creates mywebsite.com/my-image1/
Please how to avoid this behavior?
Pages like "/my-image/" for my-image.jpg are useless and it blocks great urls for posts.
Thanks,
Jiri

  • James Morris

    Hello Jiri

    I hope you are well today.

    This can be accomplished with the following code:

    <?php if( ! defined( 'ABSPATH' ) ) { die(); }
    
    /**
     * Plugin Name: Disable Attachment Pages
     * Plugin URI: https://gschoppe.com/wordpress/disable-attachment-pages
     * Description: Completely disable attachment pages the right way. No forced redirects or 404s, no reserved slugs.
     * Author: Greg Schoppe
     * Author URI: https://gschoppe.com/
     * Version: 1.0.0
     **/
    
     if( ! class_exists( 'GJSDisableAttachmentPages' ) ) {
     	class GJSDisableAttachmentPages {
     		public static function Instance() {
     			static $instance = null;
     			if ($instance === null) {
     				$instance = new self();
     			}
     			return $instance;
     		}
    
     		private function __construct() {
     			$this->init();
    			register_activation_hook( __FILE__, 'flush_rewrite_rules' );
    			register_deactivation_hook( __FILE__, 'flush_rewrite_rules' );
     		}
    
    		public function init() {
    			add_filter( 'rewrite_rules_array', array( $this, 'remove_attachment_rewrites' ) );
    			add_filter( 'wp_unique_post_slug', array( $this, 'wp_unique_post_slug' ), 10, 6 );
    			add_filter( 'request', array( $this, 'remove_attachment_query_var' ) );
    			add_filter( 'attachment_link'  , array( $this, 'change_attachment_link_to_file' ), 10, 2 );
    			// just in case everything else fails, and somehow an attachment page is requested
    			add_action( 'template_redirect', array( $this, 'redirect_attachment_pages_to_file' ) );
    			// this does nothing currently, but maybe someday will, if WordPress standardizes attachments as a post type
    			add_filter('register_post_type_args', array( $this, 'make_attachments_private' ), 10, 2);
    		}
    
    		public function remove_attachment_rewrites( $rules ) {
    			foreach ( $rules as $pattern => $rewrite ) {
    				if ( preg_match( '/([\?&]attachment=\$matches\[)/', $rewrite ) ) {
    					unset( $rules[$pattern] );
    				}
    			}
    			return $rules;
    		}
    
    		// this function is a trimmed down version of <code>wp_unique_post_slug</code> from WordPress 4.8.3
    		public function wp_unique_post_slug( $slug, $post_ID, $post_status, $post_type, $post_parent, $original_slug ) {
    			global $wpdb, $wp_rewrite;
    
    			if ( $post_type =='nav_menu_item' ) {
    				return $slug;
    			}
    
    			if ( $post_type == "attachment" ) {
    				$prefix = apply_filters( 'gjs_attachment_slug_prefix', 'wp-attachment-', $original_slug, $post_ID, $post_status, $post_type, $post_parent );
    				if ( ! $prefix ) {
    					return $slug;
    				}
    				// remove this filter and rerun with the prefix
    				remove_filter( 'wp_unique_post_slug', array( $this, 'wp_unique_post_slug' ), 10 );
    				$slug = wp_unique_post_slug( $prefix . $original_slug, $post_ID, $post_status, $post_type, $post_parent );
    				add_filter( 'wp_unique_post_slug', array( $this, 'wp_unique_post_slug' ), 10, 6 );
    				return $slug;
    			}
    
    			if ( ! is_post_type_hierarchical( $post_type ) ) {
    				return $slug;
    			}
    
    			$feeds = $wp_rewrite->feeds;
    			if( ! is_array( $feeds ) ) {
    				$feeds = array();
    			}
    
    			/*
    			 * NOTE: This is the big change. We are NOT checking attachments along with our post type
    			 */
    			$slug = $original_slug;
    			$check_sql = "SELECT post_name FROM $wpdb->posts WHERE post_name = %s AND post_type IN ( %s ) AND ID != %d AND post_parent = %d LIMIT 1";
    			$post_name_check = $wpdb->get_var( $wpdb->prepare( $check_sql, $slug, $post_type, $post_ID, $post_parent ) );
    
    			/**
    			 * Filters whether the post slug would make a bad hierarchical post slug.
    			 *
    			 * @since 3.1.0
    			 *
    			 * @param bool   $bad_slug    Whether the post slug would be bad in a hierarchical post context.
    			 * @param string $slug        The post slug.
    			 * @param string $post_type   Post type.
    			 * @param int    $post_parent Post parent ID.
    			 */
    			if ( $post_name_check || in_array( $slug, $feeds ) || 'embed' === $slug || preg_match( "@^($wp_rewrite->pagination_base)?\d+$@", $slug )  || apply_filters( 'wp_unique_post_slug_is_bad_hierarchical_slug', false, $slug, $post_type, $post_parent ) ) {
    				$suffix = 2;
    				do {
    					$alt_post_name = _truncate_post_slug( $slug, 200 - ( strlen( $suffix ) + 1 ) ) . "-$suffix";
    					$post_name_check = $wpdb->get_var( $wpdb->prepare( $check_sql, $alt_post_name, $post_type, $post_ID, $post_parent ) );
    					$suffix++;
    				} while ( $post_name_check );
    				$slug = $alt_post_name;
    			}
    
    			return $slug;
    		}
    
    		public function remove_attachment_query_var( $vars ) {
    			if ( ! empty( $vars['attachment'] ) ) {
    				$vars['page'] = '';
    				$vars['name'] = $vars['attachment'];
    				unset( $vars['attachment'] );
    			}
    
    			return $vars;
    		}
    
    		public function make_attachments_private( $args, $slug ) {
    			if ( $slug == 'attachment' ) {
    				$args['public'] = false;
    				$args['publicly_queryable'] = false;
    			}
    			return $args;
    		}
    
    		public function change_attachment_link_to_file( $url, $id ) {
    			$attachment_url = wp_get_attachment_url( $id );
    			if ( $attachment_url ) {
    				return $attachment_url;
    			}
    			return $url;
    		}
    
    		public function redirect_attachment_pages_to_file() {
    			if ( is_attachment() ) {
    				$id = get_the_ID();
    				$url = wp_get_attachment_url( $id );
    				if ( $url ) {
    					wp_redirect( $url, 301 );
    					die;
    				}
    			}
    		}
     	}
     	GJSDisableAttachmentPages::Instance();
     }

    Please see https://gschoppe.com/wordpress/disable-attachment-pages/ for more information on how this works and how to implement it on your site.

    I've tested this on a fresh install of WordPress and the end result is all links point back to the image file itself rather than the attachment page.

    Let us know if you have any further questions. We'll be happy to help! :slight_smile:

    Best regards,

    James Morris

Thank NAME, for their help.

Let NAME know exactly why they deserved these points.

Gift a custom amount of points.