Remove attachment slug from url in wordpress - php

I’m trying to remove the attachment slug from the attachment URL generated by wordpress. My current URL structure looks like:
www.site.com/category/folder/attachment/file
I made a function for that but the url output I’m getting is www.site.com/folder/file, its missing the category. Any idea how I can fix that? Here is what I got so far:
function wpd_attachment_link( $link, $post_id ){
$post = get_post( $post_id );
$post_data = get_post($post->post_parent);
return home_url( single_cat_title('', false)."/".$post_data->post_name."/". $post->post_title );
}
add_filter( 'attachment_link', 'wpd_attachment_link', 20, 2 );
P.S: i know that can be done if i change the permalink structure from the main wordpress menu, but dont want to change the current permalink structure.

Try following code:
function __filter_rewrite_rules( $rules )
{
$_rules = array();
foreach ( $rules as $rule => $rewrite )
$_rules[ str_replace( 'attachment/', '/', $rule ) ] = $rewrite;
return $_rules;
}
add_filter( 'rewrite_rules_array', '__filter_rewrite_rules' );
function __filter_attachment_link( $link )
{
return preg_replace( '#attachment/(.+)$#', '/$1', $link );
}
add_filter( 'attachment_link', '__filter_attachment_link' );

Related

Change get_author_posts_url / Author URL via filter in Wordpress

I would like to modify the get_author_posts_url function to get a custom taxonomy guest author slug that I have created.
Is there a way to change the following function to fetch a custom taxonomy link? I have used a filter to register the guest author as the post author by using a custom taxonomy, but I couldn't find a way to connect it to this get_author_posts_url function:
function get_author_posts_url( $author_id, $author_nicename = '' ) {
global $wp_rewrite;
$author_id = (int) $author_id;
$link = $wp_rewrite->get_author_permastruct();
if ( empty( $link ) ) {
$file = home_url( '/' );
$link = $file . '?author=' . $author_id;
} else {
if ( '' === $author_nicename ) {
$user = get_userdata( $author_id );
if ( ! empty( $user->user_nicename ) ) {
$author_nicename = $user->user_nicename;
}
}
$link = str_replace( '%author%', $author_nicename, $link );
$link = home_url( user_trailingslashit( $link ) );
}
Besides using the following filter, I also added the custom taxonomy (autoria) as the base slug instead of the /author slug. It's all working in the way that it is registering the custom author as the post author and also creating a custom taxonomy link in which I can access all posts by a certain custom author, but whenever I try to fetch the Author_URL it still shows the user that created the post (admin).
The filter I'm using is:
add_filter( 'the_author', 'guest_author_name' );
add_filter( 'get_the_author_display_name', 'guest_author_name' );
function guest_author_name( $name ) {
global $post;
$author = wp_get_post_terms( $post->ID, 'autoria', array( 'fields' => 'names' ) );
$author = implode( ', ', $author );
if ( $author )
$name = $author;
return $name;
}
Is there a way to connect this guest_author_name function to register the URL as well?
Thanks a lot, any help is appreciated

wordpress custom post type with custom category

I have created a custom post with the "products" name in the template and I want to add a custom category (products_cat) to this custom post.
I followed the steps until now, the URLs used to open as below (no custom categories)
https://example.com/products/ custom post title
Now I want the URLs to open with custom categories that I have added to that product. ( As follows) :
https://example.com/products/term1/term2/ ... / term n/ custom post title
I wrote the following code which changes the addresses exactly as I want
function wpa_course_post_link( $post_link, $id = 0 ){
$post = get_post($id);
$array = array();
if ( is_object( $post ) || $post->post_type != 'products'){
$terms = wp_get_object_terms( $post->ID, 'products_cat' );
foreach ( $terms as $list ) {
array_push( $array, $list->slug );
}
$category = implode('/', $array);
if( $terms ){
return str_replace( '%products_cat%' , $category , $post_link );
} else {
return str_replace( '%products_cat%' , "" , $post_link );
}
}
return $post_link;
}
add_filter( 'post_type_link', 'wpa_course_post_link', 1, 3 );
But when I click on the product with a new link, I get a 404 error
Note: I have clicked save once in the permilink and i used:
flush_rewrite_rules();
Can anyone solve the problem?
thanks

Rewrite Rules WordPress Returning Category Page Instead of Individual post

I'm trying to change the permalink only to one specific category and it works good on the changing, but the content isn't right.
It's showing the categories page with a lot of posts instead of the proper content of that post.
Can someone help me with this?
The code:
function custom_permalink( $permalink, $post, $leavename ) {
// Get the categories for the post
$category = get_the_category($post->ID);
if ( !empty($category) && $category[0]->cat_name == "Educational" ) {
$permalink = trailingslashit( home_url('/Educational/'. $post->post_name .'/' ) );
}
return $permalink;
}
add_filter( 'post_link', 'custom_permalink', 10, 3);
function custom_rewrite_rules( $wp_rewrite ) {
// This rule will will match the post id in %postname%-%post_id% struture
$new_rules['^Educational/([^/]+)/?$'] = 'index.php?name=$matches[1]';
$new_rules['^Educational/([^/]+)/?$'] = 'index.php?name=$matches[2]';
$new_rules['^Educational/?$'] = 'index.php?cat=61';
$wp_rewrite->rules = $new_rules + $wp_rewrite->rules;
return $wp_rewrite;
}
add_action('generate_rewrite_rules', 'custom_rewrite_rules');

Wordpress Category for pages

I'm having a problem with receiving the value from %category% in $wp_rewrite->page_structure :
function custom_page_rules() {
global $wp_rewrite;
$wp_rewrite->page_structure = $wp_rewrite->root .'/%category%/%pagename%';
//flush_rewrite_rules();
}
add_action( 'init', 'custom_page_rules',1 );
How can I receive the %category% in a $wp_rewrite->page_structure?
Now it returns:
http://example.com/%category%/the-page-slug/
Instead:
http://example.com/my-cat-slug/the-page-slug/
Note Categories for pages are working well:
http://example.com/my-cat-slug/
returns all pages from this category.
A solution could be:
function rudr_post_permalink( $url, $post ){
if( !is_object( $post ) )
$post = get_post( $post_id );
$replace = $post->post_name;
/* We should use a post ID to make a replacement. It is required if you use urf-8 characters in your URLs */
if( $post->ID == 1 )
$replace = 'hello-planet';
if( $post->ID == 12 )
$replace = 'Contacts';
$url = str_replace($post->post_name, $replace, $url );
return $url;
}
add_filter( 'post_link', 'rudr_post_permalink', 'edit_files', 2 );
add_filter( 'page_link', 'rudr_post_permalink', 'edit_files', 2 );
add_filter( 'post_type_link', 'rudr_post_permalink', 'edit_files', 2 );
Which is explained here
You can change the if( $post->ID == 1 ) to anything you need.
I have changed the whole code to add categories in the URL's when it are pages.
Regards, Danny

Wordpress custom post type rewrite rule matches all pages

I've created a custom post type with a rewrite to use the grandparent relationship as the URL like so:
function cpt_child(){
$args = array(
//code
'rewrite' => array( 'slug' => '%grandparent%/%parent%', 'with_front' => false),
);
register_post_type( 'child', $args );
}
add_action( 'init', 'cpt_child' );
Then I update the permalink:
add_filter( 'post_type_link', 'filter_the_post_type_link', 1, 2 );
function filter_the_post_type_link( $post_link, $post ) {
switch( $post->post_type ) {
case 'child':
$post_link = get_bloginfo( 'url' );
$relationship_child = p2p_type('children_to_parents')->get_adjacent_items($post->ID);
$parent = $relationship['parent']->post_name;
$relationship_parent = p2p_type('parents_to_grandparents')->get_adjacent_items($parent['parent']->ID);
$grandparent = $relationship_parent['parent']->post_name;
$post_link .= "/{$grandparent}/";
$post_link .= "{$parent}/";
$post_link .= "{$post->post_name}";
break;
}
return $post_link;
}
This all works great, but unfortunately the rewrite rule matches regular pages as well which makes them 404.
I can prevent this by adding a custom slug, for example 'relationship': http://example.com/relationship/grandparent/parent/child
But I'd really like to use http://example.com/grandparent/parent/child and have it not break regular pages.
I might have to resort to using non native Wordpress rewrites using htaccess.
Thanks in advance!
I managed to find a solution thanks to Milo's previous answers on other related questions. I found this particular post Remove base slug in CPT & CT, use CT in permalink to be extremely helpful.
My initial CPT with grandparent relationship rewrite remains the same:
function cpt_child(){
$args = array(
//code
'rewrite' => array( 'slug' => '%grandparent%/%parent%', 'with_front' => false),
);
register_post_type( 'child', $args );
}
add_action( 'init', 'cpt_child' );
Then I update the permalink:
add_filter( 'post_type_link', 'filter_the_post_type_link', 1, 2 );
function filter_the_post_type_link( $post_link, $post ) {
switch( $post->post_type ) {
case 'child':
$post_link = get_bloginfo( 'url' );
$relationship_child = p2p_type('children_to_parents')->get_adjacent_items($post->ID);
$parent = $relationship['parent']->post_name;
$relationship_parent = p2p_type('parents_to_grandparents')->get_adjacent_items($parent['parent']->ID);
$grandparent = $relationship_parent['parent']->post_name;
$post_link .= "/{$grandparent}/";
$post_link .= "{$parent}/";
$post_link .= "{$post->post_name}";
break;
}
return $post_link;
}
Hooked into request and changed query based on request vars that match my needs. Added is_admin() check to prevent request filter from changing the CPT's back end.
// URL rewrite pages 404 fix
if ( ! is_admin() ) {
function svbr_fix_requests( $request ){
// if it's not a section request and request is not empty treat request as page or post
if( ( ! array_key_exists( 'section' , $request ) ) && ( ! empty($request) ) ){
$request['post_type'] = array( 'post', 'page' );
}
// return request vars
return $request;
}
add_filter( 'request', 'svbr_fix_requests' );
}
Because we changed the query vars we have to add template functionality.
// Use single_template filter to properly redirect to page.php and custom page templates
function svbr_get_template_file($single_template) {
global $post;
$page_custom_template = get_post_meta( $post->ID, '_wp_page_template', true );
if ($post->post_type == 'page') {
if($page_custom_template != 'default') {
// We are using a child theme, so get_stylesheet_directory()
$single_template = get_stylesheet_directory() . '/' . $page_custom_template;
}
else {
$single_template = get_template_directory() . '/page.php';
}
}
return $single_template;
}
add_filter( 'single_template', 'svbr_get_template_file' );
Last but not least we have to add the template class to the body for styling purposes.
// Add template class to body
add_filter( 'body_class', 'template_class_name' );
function template_class_name( $classes ) {
global $post;
$page_custom_template = get_post_meta( $post->ID, '_wp_page_template', true );
$page_custom_template = str_replace('.php','',$page_custom_template);
$page_custom_template = 'page-template-' . $page_custom_template;
// add 'class-name' to the $classes array
$classes[] = $page_custom_template;
// return the $classes array
return $classes;
}

Categories