Display wp author meta url without 'http' - wordpress

I'm using the WP function: get_the_author_meta('user_url');
When I echo that to the browser it automatically prepends 'http://' to the URL. How can I avoid this, so that my URLs show exactly as they are entered on the user settings page.
Thanks is advance.

$author_url = get_the_author_meta('user_url'); // e.g. http://www.example.com
$to_remove = array( 'http://', 'https://' );
foreach ( $to_remove as $item ) {
$author_url = str_replace($item, '', $author_url); // to: www.example.com
}
echo $author_url; // now it will not have the http:// part you wish to avoid.

str_replace is probably the most efficient way of doing this.
$author_url = str_replace(array( 'http://', 'https://' ), '', get_the_author_meta('user_url'));
Other URL modification techniques.
For more complicated string replacements which match you could look at using preg_replace .
There is a function called http-build-url() which is included in the php_http.dll extension which might be more suitable for some use cases.

Related

Custom Taxonomies and how to stay in them when the posts have multiple terms selected?

Wondering if anyone can help me think this one out?
Whilst in lock-down, I've been putting together a simple site to organise my collection of Retro Gaming Adverts covering systems from the Atari 2600 up to the N64. I've still got a few 1000 to add to the site (takes time) but i've come across an issue I'm not sure how to implement a fix for.
You can browse the adverts by system through their single post pages but if an advert covers multiple systems it messes up the previous and next posts link and will drop you into another system.
For Example: If you're using the next and previous post links to go through the "mega drive / genesis" section once you get to " Battletoads and Double Dragon " when you press the next post arrow this time you're suddenly going through adverts tagged as NES, due to the fact thats the first term associated with it.
See : https://www.retrogameads.com/system/mega-drive/ and click on the first advert, then keep pressing the next arrow and you'll see what i mean.
I guess I could post each advert multiple times for each system but I don't like the idea of that.
Anyone got any suggestions on how I could work out what Term the user was browsing and keep them in that one?
Bare in mind this site is a work in progress so the design is just something basic till i work out the best way to organise things.
Let me know your thoughts.
Update:
Current method for getting prev next posts...
<?php
$terms = get_the_terms( $post->ID, 'system' );
$i = 0;
$systems = array();
foreach ( $terms as $term ) {
$systems[$i] = $term->slug;
$i++;
}
$postlist_args = array(
'posts_per_page' => -1,
'post_type' => 'portfolio',
'system' => $systems[0],
'order' => 'ASC',
'orderby' => 'title'
);
$postlist = get_posts( $postlist_args );
$ids = array();
foreach ($postlist as $thepost) {
$ids[] = $thepost->ID;
}
$thisindex = array_search($post->ID, $ids);
$previd = $ids[$thisindex-1];
$nextid = $ids[$thisindex+1];
?>
<div class="prev_next">
<?php
if ( !empty($previd) ) {
echo '<div class="older"><a rel="prev" href="' . get_permalink($previd). '">‹</a></div>';
}
if ( !empty($nextid) ) {
echo '<div class="newer"><a rel="next" href="' . get_permalink($nextid). '">›</a></div>';
}
?>
When you click on an advert, you're essentially visiting the single page for that advert. At that moment, WP does not know/remember that the user only wants to see adverts from the system you clicked.
How are you rendering the previous/next links right now?
One possible solution could be to add a parameter to the URL and then take this into account in the PHP code when rendering the previous/next links. (/portfolio/advert-name/?system=mega-drive for example)
Edit: Of course the URL could also be made prettier... if you want to put in some extra work, you could register a permalink of the form /portfolio/mega-drive/advert-name/ for example. But this would require a bit more work.
Would that work? I think it would be the best solution considering the alternatives.
Update: For the actual implementation, the get_next_post_where and get_previous_post_where filters might prove to be very useful. You could make it so that it takes the system parameter into account for the previous/next links.
Another option: You could also set up a PHP session and remember the current system that way, but then you will require a PHP session, which is not a good thing, and it will also prevent you from using full page caching (performance optimization).
Yet another option would be to remember the current system client-side through a cookie. But in that case you have caching issues again unless you load the previous/next links through AJAX.
After reading the update on your question, I have the following notes:
system is not a valid argument and will be ignored on the get_posts() call.
the method you use to get the previous and next posts is very inefficient, because you query the whole database, and then you save everything in memory, and then you comb through the whole result set in memory, using a lot of unnecessary ram and CPU power
So how can we improve this?
Simple: Use the get_previous_post and get_next_post functions on the $post. It accepts three arguments. Here is the example for get_next_post (but get_previous_post is basically the same):
get_next_post( bool $in_same_term = false, array|string $excluded_terms = '', string $taxonomy = 'category' )
Now if you set $in_same_term to true then the next post will be of a post that shares at least one taxonomy term (system in our case).
You also have to set $taxonomy to system because that is the custom taxonomy.
And the other parameter is $excluded_terms. Too bad there is no $included_terms otherwise we could just put the system we want in there. But we can do it another way... We can filter out the current system (in the system GET parameter in our URL) and keep all other systems as systems to exclude.
So let's build what we need now.
global $post;
// What system did we come from?
$system = $_GET['system'] ?? null; // Set to null if nothing was specified (uses PHP's null coalescing operator available since PHP 7
// Exclude nothing by default
$excluded_term_ids = [];
// If we came here by clicking on a system, then exclude all other systems so the previous/next links will be of the same system only
if ($system) {
// Retrieve system terms for this post
$terms = get_the_terms( $post, 'system' );
// Filter the list of terms to remove the system we came from
// This way we can create a list of terms to exclude
$excluded_terms = array_filter( $terms, function ( $term ) use ( $system ) {
return $term->slug != $system;
} );
// The get_previous_post and get_next_post functions expect $excluded_terms to be an array of term IDs, so we must map the WP_Term objects into IDs
$excluded_term_ids = array_map( function ( $term ) {
return $term->term_id;
}, $excluded_terms );
}
// Retrieve previous and next post
$previous_post = $post->get_previous_post( true, $excluded_term_ids, 'system' );
$previous_post = $post->get_next_post( true, $excluded_term_ids, 'system' );
// Echo out the page links
// And don't forget to re-add the ?system= parameter to the URL
$url_suffix = $system ? ('?system=' . $system) : '';
if ( $previous_post ) {
echo '<div class="older"><a rel="prev" href="' . get_permalink($previous_post) . $url_suffix . '">‹</a></div>';
}
if ( $next_post ) {
echo '<div class="newer"><a rel="next" href="' . get_permalink($next_post) . $url_suffix . '">›</a></div>';
}
NOTE: Untested code.. So there might be a small bug somewhere.. Let me know if you encounter an issue with this code..
Important: On the page of a system, you must now also add '?system=current-system' to the URLs that you render.
Probably something like: echo get_permalink($advert) . '?system=' . $post->post_name (could be different depending on how your code is on that screen..)

WP Rest API get post by slug with special characters (ex: !&')

I have posts with slugs with special characters. One of them is the following:
http://localhost/wp-json/wp/v2/posts?slug=my-post!
Unfortunately, WP REST API not showing the content since it has (!) within the slug.
Is there any solution you guys would recommend?
I have found the solution (at least for my case), not sure if it'll work for you but may indicate you the way to go. We need to tap into the function used to sanitize the slugs, as I said in my comment, by default is wp_parse_slug_list. Looking at the code the function that actually sanitizes the slug is sanitize_title.
Looking at the source code, wp_parse_slug_list calls sanitize_title with only one argument, which means that the context used is save. This means that, for posts that were already saved without being sanitized by this function, the slug won't match and the post will be inaccessible through the API. The solution is to change the sanitizing function slightly by adding a filter:
add_filter('rest_post_collection_params', function($query_params) {
$query_params['slug']['sanitize_callback'] = 'sanitize_rest_api_slug';
return $query_params;
}, 20, 1);
function sanitize_rest_api_slug( $list ) {
if ( ! is_array( $list ) ) {
$list = preg_split( '/[\s,]+/', $list );
}
foreach ( $list as $key => $value ) {
$list[ $key ] = sanitize_title( $value, '', 'query' );
}
return array_unique( $list );
}
The filter is actually being applied on the function get_collection_params() on the class-wp-rest-posts-controller class, but if you look at the source code, the filter has a variable depending on the post_type, so if you have another special kind of posts defined (besides post) you need to add/change a filter for that kind as well.
I hope this helps somebody else like me, even if it's too late for your issue.

Is it possible to change pagination permalinks in WP?

The default link for pagination looks like "site.com/articles/page/2", but I need to do the page number as parameter(example: "site.com/articles?page=2"). I've tried to use add_filter function:
add_filter('get_pagenum_link', 'edit_paginate_url');
function edit_paginate_url($url){
$pagenum = preg_match("/\/\d\//", $url, $pagenum);
$pagenum = preg_replace("/\//", "", $pagenum);
$url = preg_replace("/\/page\/\d/", "?page=", $url);
return $url . $pagenum;
}
But it didn't work. It returns url like: "site.com/articles0/page/2/" (this filter only adds zero symbol before pagination part of url).
Follow the below url in which you have to set base and format as per your requirements.
https://codex.wordpress.org/Function_Reference/paginate_links

File path without domain name from wp_get_attachment_url()

wp_get_attachment_url() process full file path like
http://example.com/wp-content/uploads/2014/12/aura.mp3
I want the url without http://example.com/
So, I want above example as wp-content/uploads/2014/12/aura.mp3 instead of http://example.com/wp-content/uploads/2014/12/aura.mp3. How to do it?
You can really easily explode it by / and then take the part with index 3. Example
$url = wp_get_attachment_url(id); //id is file's id
$urllocal = explode(site_url(), $url)[1]; //output local path
Here is the WordPress way using WordPress functions (avoid hacking):
$fullsize_path = get_attached_file( $attachment_id ); // Full path
$filename_only = basename( get_attached_file( $attachment_id ) ); // Just the file name
WordPress has tons of functions, so first try to find the function on the docs: https://developer.wordpress.org/reference/functions/get_attached_file/
You can use PHP's function explode.
Here is the code:
<?php
$image_url = wp_get_attachment_url( 9 ); //ID of your attachment
$my_image_url = explode('/',$image_url,4);
echo $my_image_url[3];
?>
You can implode your entire url on / and array_slice from the end, then implode it back in on /.
$url = wp_get_attachment_url($item->ID); //id is file's id
$url_relative = implode(array_slice(explode('/', $url),-3,3),'/');
//Returns: 2019/08/image.jpg
That way if your WordPress is on a subdomain or localhost or the images are on S3 it won't crash.

RSS WordPress SimplePie claiming valid URL as invalid

I'm trying to load a RSS feed with Wordpress's built-in SimplePie.
include_once(ABSPATH . WPINC . '/feed.php');
$rssURL = 'http://missionstkitts.blogspot.com//feeds/posts/default';
$rss = fetch_feed($rssURL);
To debug, I used print_r($rss); and I get a WordPress error object:
WP_Error Object
(
[errors] => Array
(
[simplepie-error] => Array
(
[0] => WP HTTP Error: A valid URL was not provided.
)
)
[error_data] => Array
(
)
)
But, frustratingly, if I print $rssURL and then copy and paste it it goes straight to the correct feed. What is going on?
Since this is the first hit in google, probably worth me adding this possible solution:
For our instance - an intranet site, pulling an rss feed from another internal page, which in-turn resolves to an RFC1918 private address the feed was being blocked by Wordpress's URL checker for security reasons.
The easiest fix in my instance was to add the following to functions.php, but this does have security implications so be sure you understand it before you add it:
add_filter( 'http_request_args', function( $args ) {
$args['reject_unsafe_urls'] = false;
return $args;
} );
Further discussion and more information at - https://core.trac.wordpress.org/ticket/24646
By adding preg_match for specific urls we can minimize the amount of parsed unsafed urls:
function http_request_local( $args, $url ) {
if ( preg_match('/xml|rss|feed/', $url) ){
$args['reject_unsafe_urls'] = false;
}
return $args;
}
add_filter( 'http_request_args', 'http_request_local', 5, 2 );
So, while the above answers work, I think that there's a way to do this that is better to make sure that you're limiting the scope of where you're making the URL request to instead of allowing everything to go. So I'm proving the following information to anyone who stumbles across this just in case it helps.
This answer is useful if the resulting calls are to internal servers cross-communicating on private IPs but are still publicly accessible.
The snippet below is to be run on the site that's calling the RSS feed. The site that is providing the feed does not need this.
add_filter('http_request_host_is_external', function($bool, $host, $url){
if($url === 'https://www.example.com/news/feed/' && $host === 'www.example.com'){
return true;
}
}, 10, 3);

Resources