Wordpress page slug conflicts with media library item - wordpress

I created a new page which is assigned a custom template. When I visit that page's url I see what appears to be the default page layout (not my template) and the admin toolbar shows options pertaining to media (ex: Edit media).
After some head scratching, I deduced that somehow that url must point to a media item. I edited the page slug and "bingo" the actual page appears just as expected. When I visit the original url (from the first slug) I see the same media item.
Bottom line: It appears that coincidentally the page and the media item share the same name, and this was somehow causing WP's wires to get crossed.
My question: Can someone help me understand how/why this happens? Does wordpress create magic permalinks to everything in the media library (other than their location in wp-content/uploads/...)?
Note: The media item was uploaded normally into the media library (not FTP into the root directory, etc)

Yes, in WordPress you cannot have duplicate slugs/categories/taxonomies/tags. So if your theme allows for media files and permalinks to have their own page and the slug is the same as another one, it will usually append a number to it because the database does not like it.
media slug "example"
page slug "example" will not work since that slug exists already , if done in the admin it will automatically change the slug to "example-1".

I just had this problem and fixed it like this:
$post_s=get_posts('posts_per_page=-1');
foreach($post_s as $p){
$atts = get_posts('post_type=attachment&name='.$p->post_name.'&posts_per_page=-1&post_status=inherit');
foreach($atts as $att){
echo 'found!! '.$p->post_name;
// Update post 37
$my_post = array(
'ID' => $atts->ID,
'post_name' => $att->post_name.'-image'
);
// Update the post into the database
wp_update_post( $my_post );
}
}

This is a late answer, but I wanted to give a cleaner version of the answer that alesub gave.
function wp21418_append_to_post_name() {
// Checks to see if the option images_updated has been set or has a value of true.
if ( get_option( 'images_updated' ) === 'true' ) :
return;
endif;
// get all attachment posts.
$attachments = get_posts([
'post_type' => 'attachment',
'post_status' => 'inherit',
'name' => $p->slug,
'posts_per_page' => -1,
]);
// For each attachment, loop and update the post_name
foreach($attachments as $p){
$attachment = array(
'ID' => $p->ID,
'post_name' => $p->post_name.'-image'
);
// Update the post into the database
wp_update_post( $attachment );
}
// Once everything is looped, add the option to the database.
add_option( 'images_updated', 'true' );
}
add_action( 'after_setup_theme', 'wp21418_append_to_post_name' );
This function runs on an action hook right after the theme has setup. The first line checks to see if there is an option in the database images_updated. If that option exists, we bail on the function and it doesn't do any processing. Otherwise, if the option does not exist, it runs the function and sets the option at the very end.
This makes it so it will only run once. You don't have to remove the function after refresh. If you want to run it again, you can simply remove the if statement at the top. As a caveat: doing this will add another -image at the end of post_names even if they have -image already (e.g. -image-image)
There could be more file name checking for that situation. Will update the answer with that if someone really needs it.

I tried one of the suggested solutions, and ended up having attachment pages like /bob-image-image-image-image/.
I'd suggest that instead of using alesub or disinfor's code blindly, use a better option in the form of "Disable Media Pages" plugin.
https://github.com/joppuyo/disable-media-pages
It automatically sets all attachment slugs to an unique id, and there is the option to mangle any existing attachment slugs so they won't cause any issues in the future.

Related

Rank Math metabox preview for custom field

I've created a custom field in Rank Math...
add_action( 'rank_math/vars/register_extra_replacements', function(){
rank_math_register_var_replacement(
'op_shortcode',
[
'name' => esc_html__( 'OP ACF Field', 'rank-math' ),
'description' => esc_html__( 'Custom ACF field from ACF shortcodes.', 'rank-math' ),
'variable' => 'op_shortcode(field-name)',
'example' => esc_html__( 'Chrisad field value', 'rank-math' ),
],
'get_op_shortcode_callback'
);
});
function get_op_shortcode_callback( $shortcodename, $post_id ) {
global $post;
$post_id = "option"; // options page
$shortcodename = get_field( $shortcodename, $post_id, true );
return $shortcodename;
}
... it works in the frontend but I can't get it to be previewable in the backend metabox.
I wrote to Rank Math and the answer they gave first was, "There’s no additional code to be added to the filter since the custom variable is already working on the front end. For the preview to work, you need to ensure that the current content editor you are working on has WordPress editor support." (Which it does as far as I know because every other Rank Math variable is showing in the preview metabox).
Then they said, "When this happens it means that the custom variable you created contains code that cannot be rendered in the backend because the data is still not yet available." (I don't know what this means.)
And then finally, "The following article explains the default WordPress hooks firing sequence: http://rachievee.com/the-wordpress-hooks-firing-sequence/. Beyond that article, you will have to research further into how to get the variable to load. ACF support/forums might be able to help." (That's a 2015 article on hooks firing sequence which leads me to believe that there is a hook firing out of sequence but I can't figure it out).
I am just looking to see if anyone has any idea how to get the custom field I've registered to show up in the preview metabox in the backend (it is showing in the frontend).
Hope that makes sense.
Any help or insight is appreciated.

Custom post status not appearing

I am building a directory theme for a client of mine, and I like to add the feature of expiration in the posts by modifying the post status from publish to expired.
To achieve that, I am trying to register a new post status by using the following code:
add_action('init', 'registerStatus', 0);
function registerStatus()
{
$args = array(
'label' => _x('Expired', 'Status General Name', 'z' ),
'label_count' => _n_noop('Expired (%s)', 'Expired (%s)', 'z'),
'public' => true,
'show_in_admin_all_list' => true,
'show_in_admin_status_list' => true,
'exclude_from_search' => true
);
register_post_status('expired', $args);
}
The problem is that I cannot see the registered post status either in WordPress posts, either in my custom post type post statuses.
Am I doing something wrong?
Thanks to Ryan Bayne I was able to add a custom post status to the admin panel on the edit post page. There is no wordpress filter avaiable. His solution with jQuery is perfect. Here the code if anyone else is searching for a solution:
add_action( 'post_submitbox_misc_actions', 'my_post_submitbox_misc_actions' );
function my_post_submitbox_misc_actions(){
global $post;
//only when editing a post
if( $post->post_type == 'post' ){
// custom post status: approved
$complete = '';
$label = '';
if( $post->post_status == 'approved' ){
$complete = 'selected=\"selected\"';
$label = '<span id=\"post-status-display\"> Approved</span>';
}
echo '<script>'.
'jQuery(document).ready(function($){'.
'$("select#post_status").append('.
'"<option value=\"approved\" '.$complete.'>'.
'Approved'.
'</option>"'.
');'.
'$(".misc-pub-section label").append("'.$label.'");'.
'});'.
'</script>';
}
}
Custom post status functionality is still under development (as it has been for the past four years!), see https://core.trac.wordpress.org/ticket/12706, and comments on https://wordpress.stackexchange.com/q/67655/25765. More useful info here: https://wordpress.stackexchange.com/search?q=register_post_status.
Personally, I'd strongly discourage implementing custom post statuses, but if really necessary, you could take a look at how the Edit Flow plugin handles it.
This feature is still pending for future development
NOTICE:
This function does NOT add the registered post status to the admin panel. This functionality is pending future development. Please refer to Trac Ticket #12706. Consider the action hook post_submitbox_misc_actions for adding this parameter.
Now November 2014 and still issues with custom statuses. I think the original code posted is fine. Here is a video showing an issue you will run into when implementing custom post status though. There may be a workaround i.e. hooking into the posts query and doing a custom query but I've not started the research.
Screencast of posts not showing in the All table when a custom status is applied, however the posts can be found in the table view for each custom status. Click here to view short clip.
That screencast was taking while I worked on my new WTG Tasks Manager plugin. I will leave my design in the plugin as it is and hopefully it helps to encourage improvements in this area of WordPress.
For proper answer...my custom status do show on the Edit Post screen for my custom post type so that is possible. If you want to take a look at my plugins registration of custom post type and statuses go to directory "posttypes/tasks.php" and play around with a working example. Here is the plugins official page...
https://wordpress.org/plugins/wtg-tasks-manager/

Wordpress - using php to redirect to a different page

I am trying to create a form that when submitted, adds data to a mysql database and redirects to a success page.
I added this code to the bottom of my functions.php file:
add_action('init', 'form_submit');
function form_submit(){
global $wpdb;
if(isset($_POST['form_sub']))
{
$name= $_POST['name'];
$age= $_POST['age'];
$wpdb->insert(
'mytable',
array(
'name' => $name,
'age' => $age
),
array(
'%s',
'%s'
)
);
header("Location: http://www.google.com");
}
}
and added a form to my page that calls this function when submit is clicked.
When I try this, the data is added to the mysql database, but the redirect doesn't seem to work. Instead of going to google.com, it adds this to the top of the page:
Object Moved
This document may be found here
Where here is a link to google.com. Any idea on how to fix this? Thank you!
You are probably sending the redirect header too late (after the page is rendered).
Check this out: http://shibashake.com/wordpress-theme/wordpress-page-redirect
You can try to put out a javascript redirect if you can't get the header() or wp_redirect() out early enough.

Wordpress rss feed as post type with image/permalink

I have a friend who writes to a couple of different blogs and wants to pull stories from one that isn't so popular, onto his main blog with an rss feed and display an image from it too (since rss feeds have images, sometimes).
Displaying the rss feeds shouldn't be too hard, it's making them a custom post type that seems more difficult to me.
If anyone has any ideas, shoot.
EDIT:-
Does anyone know how to get an external rss feed to appear as a custom post type in wordpress?
A simple way may be to use Wordpress' own fetch_feed function:
http://codex.wordpress.org/Function_Reference/fetch_feed
A quick example (assuming you've already set up your custom post type):
function import_feed_items()
{
$feed = fetch_feed('http://feeds.bbci.co.uk/news/uk/rss.xml');
if( !is_wp_error($feed) )
{
if( $last_import = get_option('last_import') )
{
$last_import_time = $last_import;
} else {
$last_import_time = false;
}
$items = $feed->get_items();
$latest_item_time = false;
foreach ( $items as $item )
{
$item_date = $item->get_date('Y-m-d H:i:s');
if( $last_import_time && ($last_import_time >= strtotime($item_date)) )
{
continue;
}
$post = array(
'post_content' => $item->get_content(),
'post_date' => $item_date,
'post_title' => $item->get_title(),
'post_status' => 'publish',
'post_type' => 'custom_post_type'
);
wp_insert_post($post);
if( strtotime($item_date) > $latest_item_time )
{
$latest_item_time = strtotime($item_date);
}
}
if( false !== $latest_item_time )
{
update_option('last_import', $latest_item_time);
}
}
else
{
echo $feed->get_error_message();
}
}
add_action('wp', 'import_feed_items');
If there is an image tag in the content you could use php's DomDocument class to grab the url and upload it to your server so you can set it as the featured image.
http://codex.wordpress.org/Function_Reference/wp_insert_attachment
http://codex.wordpress.org/Function_Reference/set_post_thumbnail
Edit
corrected the timestamp check. This updated example uses the 'wp' hook to run so you can see the results quicker. It would be preferable to set this as a cron task. See http://codex.wordpress.org/Function_Reference/wp_schedule_event
The Feed to Post plugin is the perfect solution for importing multiple RSS items into your WordPress blog, you can even store them as posts or custom post types.
http://www.wprssaggregator.com/extension/feed-to-post/
Unfortunately I don't know a way off hand, but have you looked at modifying a plugin? There are tons of content curation plugins around (feedwordpress, autoblog, etc.). You could probably find the wp_insert_post() line somewhere and modify it to include your custom post type/taxonomies.
EDIT
Jumped into the plugin (feedwordpress) myself, and all the insert_post stuff is in syndicatedpost.class.php - the main wp_insert_post() on line 1538
EDIT if you fancy a giggle while reading throught that plugin code, you'll find many an instance of the f word... haha
Hey why dont you try this http://wordpress.org/extend/plugins/display-latest-rss-feeds/
It would pull rss feeds from any account and display it to your blog. Unfortunately it wont display images just the rss feeds title and its permalink to the original blog but you can easily modify the source code if you want.

Include postmeta in WordPress search

How can I tell the default WordPress search function to also look at the postmeta data?
For example, I have a postameta key called 'item_number' and if someone searches '113', I'd like for it to check the key's value as well as the post content.
Thanks!
A quick and dirty way to include meta values inside your searching scope: you can hook into pre_get_posts and add a meta_query like this:
Inside your functions.php:
add_filter( 'pre_get_posts', 'so_9224493_adjust_search_query');
function so_9224493_adjust_search_query( $query ) {
if ( !is_admin() && $query->is_search ) { //the !is_admin() boolean ensures that this does not affect your dashboard
$meta_query_arguments = array(
array(
'key' => 'item_number', //this is where you would put your meta key
'value' => $query->query_vars['s'],
'compare' => 'LIKE',
),
);
$query->set('meta_query', $meta_query_arguments);
};
}
The only problem with this route is that it will include the meta query so that your search query will only match posts that include the search term inside the Title/Content/Excerpt and the meta field, which might not be preferable for you.
You must replace your Wordpress search function with your own. Check this answer.
Very simple workaround: put all meta values you want to be searchable into post_exerpt field (use save_post action), so they will be found without any search modifications.
This site provided the answer I was looking for:
http://flav36rs.com/2010/03/15/extend-wordpress-search-to-include-custom-post-meta/
There are some helpful comments below the tutorial worth looking at if you run into problems.
EDIT:
The above link is dead.
Ultimately, I ended up writing a complete custom search query using JOINS to build the query I needed.

Resources