wordpress replace text before showing it to the browser - wordpress

My website is built using Elementor using GeneratePress as default theme and I want to replace output final text with some values from the database. This plugin
Real-Time Find and Replace https://wordpress.org/plugins/real-time-find-and-replace/ is doing the replace functionality perfectly and it uses action:
//Handles find and replace for public pages
add_action( 'template_redirect', 'far_template_redirect' );
to replace text using code:
function far_ob_call( $buffer ) { // $buffer contains entire page
$far_settings = get_option( 'far_plugin_settings' );
if ( is_array( $far_settings['farfind'] ) ) {
foreach ( $far_settings['farfind'] as $key => $find ) {
if( isset( $far_settings['farregex'][$key] ) ) {
$buffer = preg_replace( $find, $far_settings['farreplace'][$key], $buffer );
} else {
$buffer = str_replace( $find, $far_settings['farreplace'][$key], $buffer );
}
}
}
return $buffer;
}
I can not use the plugin directly because it repalce text with text and I need to fetch data from database, so I have to make my own plugin. But, I found this blog: https://markjaquith.wordpress.com/2014/02/19/template_redirect-is-not-for-loading-templates/ that tells me to use a filter:
add_filter( 'template_include', 'my_callback' );
instead of the above action in plugin:
add_action( 'template_redirect', 'far_template_redirect' );
But the plugin is using the action.
What to use?
The plugin description says: "Set up find and replace rules that are executed AFTER a page is generated by WordPress, but BEFORE it is sent to a user's browser." this is what I exactly want. That is to replace text after page is generated and just before the page is sent to browser, but the plugin uses action for this, and other blogs suggest to use filter?

Related

how to change edit url with "Id" to edit url with "Slug" in Wordpress

I have this is WordPress Post editing Url:
https://example.com/wp-admin/post.php?post=ID&action=edit
and I want to change it to Slug Not the ID Like This:
https://example.com/wp-admin/post.php?post=Slug&action=edit
I was trying to edit the post with this Url but is not working:
https://example.com/wp-admin/post.php?post=MyPostSlug&action=edit
In order to change the edit post link structure, you can use the get_edit_post_link filter like so:
add_filter( 'get_edit_post_link', 'so_73914075_get_edit_post_link', 10, 3);
function so_73914075_get_edit_post_link($link, $post_id, $context) {
$post = get_post( $post_id );
if ( ! in_array( $post->post_type, array( 'post', 'page' ) ) ) {
return $link;
}
$post_type_object = get_post_type_object( $post->post_type );
if ( 'revision' === $post->post_type ) {
$action = '';
} elseif ( 'display' === $context ) {
$action = '&action=edit';
} else {
$action = '&action=edit';
}
if ( 'display' === $context ) {
$post_type = '&post-type=' . $post->post_type;
} else {
$post_type = '&post-type=' . $post->post_type;
}
$custom_edit_link = str_replace( '?post=%d', '?post-name=%s', $post_type_object->_edit_link );
return admin_url( sprintf( $custom_edit_link . $action . $post_type, $post->post_name ) );
}
This will change the edit links for regular posts and pages to something like this:
https://example.com/wp-admin/post.php?post-name=the-post-slug&action=edit&post-type=post
WARNING: make sure you limit this to only the post types you need to change the URL for. Making this change global will almost surely
have unintended effects over other plugins
However, making the admin panel actually load the edit screen is not that easy.
Looking at the source code of the wp-admin/post.php file, you will see that there is no way to hook into the flow and populate the $post_id variable with the post id matching the slug you are sending through.
That means you have 2 options:
RECOMMENDED Update the edit link to whatever format you want and then create an admin redirect function that pulls the slug from the initial URL and redirects to the actual edit page with the ?post=%d in it.
NOT RECOMMENDED Create a new admin edit page that will understand your URL structure and include the wp-admin/post.php after the code that pulls the $post_id based on the slug.
The 2nd method might come with lots of extra code you need to write to cover all the cases and all the instances a post reaches the post.php in the admin panel

Remove span tags from product name in Woocommerce My Account Downloads

I have problem with my woocommerce downloads section on WooCommerce "my account" > "Downloads": On product variations name, there is a <span> html tag that are visible:
I have tried to remove those "span" tags using:
add_filter( 'woocommerce_customer_available_downloads', 'remove_span_dl_name', 10, 7);
function remove_span_dl_name( $download ){
return str_replace( '<span> - </span>', ' - ',$download['download_name']);
}
but it removes all downloads altogether.
And I have also tried to remove those "span" tags using:
add_filter( 'woocommerce_available_download_link', 'remove_span_dl_name', 10, 7);
function remove_span_dl_name( $download ){
return str_replace( '<span> - </span>', ' - ',$download['download_name'] );
}
What is my mistake and how can I get rid of these tags?
The hook woocommerce_available_download_link is included in myaccount/my-downloads.php deprecated template since WooCommerce version 2.6 (the right template file that is used is myaccount/downloads.php).
Now as downloads are loaded through WC_Customer method get_downloadable_products(), you can to use woocommerce_customer_get_downloadable_products filter hook included in this method. Or also woocommerce_customer_available_downloads filter hook too.
To remove tags from product name, you can use str_replace() or much better and efficient strip_tags():
1). First way - Using strip_tags() function:
add_filter( 'woocommerce_customer_get_downloadable_products', 'remove_span_tags_from_product_name' );
// Or also
// add_filter( 'woocommerce_customer_available_downloads', 'remove_span_tags_from_product_name' );
function remove_span_tags_from_product_name( $downloads ){
// Only on my account downloads section
if ( ! is_wc_endpoint_url('downloads') )
return $downloads;
// Loop though downloads
foreach( $downloads as $key => $download ) {
// remove "span" html tags
$downloads[$key]['product_name'] = strip_tags( $download['product_name'] );
}
return $downloads;
}
2). Another way - Using str_replace() function:
add_filter( 'woocommerce_customer_get_downloadable_products', 'remove_span_tags_from_product_name' );
// Or also
// add_filter( 'woocommerce_customer_available_downloads', 'remove_span_tags_from_product_name' );
function remove_span_tags_from_product_name( $downloads ){
// Only on my account downloads section
if ( ! is_wc_endpoint_url('downloads') )
return $downloads;
// Loop though downloads
foreach( $downloads as $key => $download ) {
// remove "span" html tags
$downloads[$key]['product_name'] = str_replace( array('<span>', '</span>'), array('', ''), $download['product_name'] );
}
return $downloads;
}
Code goes in functions.php file of your active child theme (or active theme). Any way should work.
If you want that to work also everywhere ("order view", "Order received", emails notifications), remove:
// Only on my account downloads section
if ( ! is_wc_endpoint_url('downloads') )
return $downloads;

How to set homepage based on device with Wordpress?

I need to set a default homepage based on the visitor device (mobile/desktop), I tried the following code in plugin, but did not work.
if ( wp_is_mobile() ) {
$homepage = get_page_by_title( 'mobile' );
}else{
$homepage = get_page_by_title( 'home1' );
}
if ( $homepage ){
update_option( 'page_on_front', $homepage->ID );
update_option( 'show_on_front', 'page' );
}
it keeps loading the home1, which is selected from theme options.
Thanks,
Your current functionality wouldn't work, even if it "worked". You're attempting to set a site-wide option in the database based on the most recent visitor's device.
Using update_option() isn't in your best interest here. What you should be doing is programmatically changing the template that's loaded at run-time based on the user's device, using the template_include filter - that way you're not storing a (semi) permanent change in your database, which would get constantly overwritten countless times by any user and affect all other users.
This would end up looking something like this:
add_filter( 'template_include', 'so_52745088_homepage_template', 99 );
function so_52745088_homepage_template( $template ){
// Only execute on the front page, not pages/posts/cpts
if( is_front_page() ){
// Determine if mobile
if( wp_is_mobile() ){
// Make sure mobile homepage template is found
if( $home_template = locate_template( array( 'homepage-mobile.php' ) ) ){
return $new_template;
}
}
}
return $template;
}
If you don't have a separate page template for mobile, and it's just a regular ol' separate page, then you can look at using wp_safe_redirect() on any number of hooks, a common one being template_redirect, which would end up looking like this:
add_action( 'template_redirect', 'so_52745088_homepage_redirect' );
function so_52745088_homepage_redirect( $template ){
// Only execute on the front page, not pages/posts/cpts
if( is_front_page() ){
// Determine if mobile
if( wp_is_mobile() ){
wp_safe_redirect( 'mobile' );
exit;
}
}
}

Only show images/attachments within the gallery?

When i create a page, add a gallery, and browse this gallery on the front-end it will browse all the attachments that are associated with that page, instead of just the images within that gallery. Is there a way to filter all the other attachments and only show the images within a certain gallery? So that, for instance, when I delete the gallery and add a new gallery on the same page > only the new gallery is shown?
Any ideas?
This might not be the most elegant way, but i've found it very usefull.
Passing a post ID to the function below will load a gallery from the post_content of that post. So you would create a gallery and insert it into your post content, then in the template you run this function and will be returned with an array of attachments in that gallery which you are free to to whatever with, i.e slideshows and the likes.
function wp_load_gallery($post_id) {
$post = get_post( $post_id );
$regx = '/' . get_shortcode_regex() . '/';
preg_match( $regx, $post->post_content, $matches );
$ids = shortcode_parse_atts( $matches[3] );
$gallery = array( );
foreach( explode( ',', $ids['ids'] ) as $id ) {
if($id) {
$gallery[] = get_post( $id );
}
}
return $gallery;
}
Note that the shortcode is not cut from the content, so when you display the content you should run it through the strip_shortcodes function, i.e:
echo strip_shortcodes( get_the_content() );
This allows you to update the gallery whenever you want with whatever you want.
EDIT:
To simply display all images:
$gallery = wp_load_gallery($YOUR_POST_ID);
foreach($gallery as $image) {
echo wp_get_attachment_image($image->ID);
}

FeedWordPress - Save string as Custom Field

I am using the FeedWordPress plugin http://wordpress.org/extend/plugins/feedwordpress/ to pull posts from one site to another.
I have written a filter that after some help from Stack users successfully scans the $content and extracts the image URL into $new_content
define('FWPASTOPC_AUTHOR_NAME', 'radgeek');
add_filter(
/*hook=*/ 'syndicated_item_content',
/*function=*/ 'fwp_add_source_to_content',
/*order=*/ 10,
/*arguments=*/ 2
);
function fwp_add_source_to_content ($content, $post) {
// Use SyndicatedPost::author() to get author
// data in a convenient array
$content = $post->content();
// Authored by someone else
if( preg_match( '/<img[^>]+src\s*=\s*["\']?([^"\' ]+)[^>]*>/', $content, $matches ) ) {
$new_content .= 'URL IS '.$matches[0].'';
return $new_content;
}
else
{
}
}
What I wanted to do now was save this URL into a custom field instead of just returning it. Has anyone achieved anything similar?
So as I understand it, the plugin grabs content from external RSS feeds and creates them as posts in your website.
If this is the case, using your filter you should be able to grab the post ID within the $post variable.
So all you need is the add_post_meta() function to add a custom field to the specific post.
So including your code above it should look something like:
define('FWPASTOPC_AUTHOR_NAME', 'radgeek');
add_filter(
/*hook=*/ 'syndicated_item_content',
/*function=*/ 'fwp_add_source_to_content',
/*order=*/ 10,
/*arguments=*/ 2
);
function fwp_add_source_to_content ($content, $post) {
// Use SyndicatedPost::author() to get author
// data in a convenient array
$content = $post->content();
// Authored by someone else
if( preg_match( '/<img[^>]+src\s*=\s*["\']?([^"\' ]+)[^>]*>/', $content, $matches ) ) {
$new_content .= 'URL IS '.$matches[0].'';
//Add custom field with author info to post
add_post_meta($post->ID, 'post_author', $new_content);
return $new_content;
}
}

Resources