How to hide a content on WordPress after receiving a certain number of views - wordpress

How can I hide content in a post or page after it has received a certain amount of views I have set using a shortcode in WordPress?
Let's say I make a post. I enclose some content in the shortcode. I set the content to be shown for just 500 views. Then once the post reaches 500 views, the content should disappear from the post or page.
I have tried so many other plugins but couldn't find any solutions to this. wp-limit-post-views plugin also didn't solve my problem. I need help on this.

You could try something like that:
function hide_contents_function($atts, $content) {
$attributes = shortcode_atts(
array(
'count' => 500
),
$atts
);
// Get the max counts for the current post from the DB.
// You could use either an options if the counter is global, or the post meta.
// For this example I am using options, but it's up to you the implementation
$total_count = get_option('total_count', 0);
// Alternative way using post meta to get the counter per page/post
$total_count = get_post_meta(get_the_ID(), 'post_view_count', true);
if ( ! $total_count ) {
$total_count = 0;
}
// If the count loaded from the DB is bigger than the count
// property value then return nothing.
if ( $total_count > (int)$attributes['count'] ) {
return '';
}
return do_shortcode($content);
}
add_shortcode('hide_contents', 'hide_contents_function');
The above code, will register a short code that accepts an attribute allowing you to control how many views you want to have before you hide the contents.
In this example I used a single value from options table, but you are free to use any method you like to count the total views of a single post.
To use this short code you can do something like that:
[hide_contents count="345"]I will be hidden after 345 views.[/hide_contents]
Note that if you have installed any cache system, your content will not be hidden if the page is cached! That's not a problem of the short code, but the problem will occur because of the cache.
Finally, remember to update the counter of the views on each post refresh :)

Related

Filter by Attribute not filtering on shop page

I’ve developed a new theme for a website, but i seem to have a problem related to widget Filter By Attribute.
When i use the filter, that comes with the gutenberg block editor for widgets, the filter attribute widget doesn’t filter anything. (i guess it uses ajax to filter, but its not filtering anything)
When i use the add_filter('use_widgets_block_editor', '__return_false'); to remove the gutenberg and use a new filter by attribute (which is a different widget, than the one that comes with Gutenberg), the widget works, because it filters the query by passing some params on the url, but has a problem. It shows variations that are out of stock, which is something that have been fixed with the new widget, using the product lookup tables, and it's exactly what i'm trying to achieve here.
I strongly believe this is related to the AJAX call it uses to filter the shop page, so i guess i'm missing an ID or Class, to the product wrapper or something.
Does anyone also had this problem?
If you want to see the page in question, is this one https://www.hiima-store.com/bch/shop/
When you go into Filters, you can see both widgets there. (there are two for sizes. the first one uses query params and the second one, is the one that is not filtering).
I did a custom script regarding that.
It might help someone with the same problem.
It will hide the product if the variation is out of stock.
add_action('woocommerce_before_shop_loop_item_title', 'out_of_stock_variations_loop');
function out_of_stock_variations_loop()
{
global $product;
if (isset($_GET["filter_size"])) { // check if the attribute is in the url
if ($product->product_type == 'variable') {
$available = $product->get_available_variations();
if ($available) foreach ($available as $instockvar) {
if (isset($instockvar['attributes']['attribute_pa_' . __('size', 'hiima')])) {
var_dump('entrei');
if (($instockvar['attributes']['attribute_pa_.' . __('size', 'hiima')] == $_GET['filter_size']) && (!$instockvar['max_qty'] > 0)) {
global $product;
$id = $product->get_id();
echo "<style>.post-$id{display: none}</style>";
}
}
}
}
if (!$product->is_in_stock()) {
global $product;
$id = $product->get_id();
echo "<style>.post-$id{display: none}</style>";
}
}
}

WP / Elementor Intercept Form and Redirect with Data

I have a form built in Elementor that I am looking to intercep, process the data and forward onto a third party then subsequently show the data on a "confirm" card.
I am able to build this whole process as a single page, setting each as display none with CSS then showing / hiding with JS as I receive AJAX responses. This isn't ideal as it breaks with JS turned off.
I haven't been able to find the right Elementor hook and way to populate a new page with PHP, has anyone had experience with this?
There are a few methods to POST data to another url from an Elementor web form.
One is using many of the API integrations such as Mailchimp, ActiveCampaign, Zapier etc. (see https://docs.elementor.com/article/281-form-faq) and (https://docs.elementor.com/category/405-integrations)
Another (very limited method) is by using the form's Action after Submit and choosing "redirect" and then using each field's short code as individual data strings in the url such as:
mysite.com/thank-you?fname=[field id="fname"]&lname=[field id="lname"]
You can even build your /thank-you/ page in Elementor to GET that data and populate Elementor elements such as text, title, links etc with the form field data. For example, I could drop a text element on the /thank-you/ page and choose dynamic instead of typing in the text area and from the dynamic drop down, choose "request parameter" and for the "type" choose GET and for the param name use your unique url keys such as fname, lname etc. You can even set prefix, suffix and even fallback text along with it.
Lastly, here is a write up on how to back end code passing data externally (https://developers.elementor.com/forms-api/#Form_New_Record_Action).
// A send custom WebHook
add_action( 'elementor_pro/forms/new_record', function( $record, $handler ) {
//make sure its our form
$form_name = $record->get_form_settings( 'form_name' );
// Replace MY_FORM_NAME with the name you gave your form
if ( 'MY_FORM_NAME' !== $form_name ) {
return;
}
$raw_fields = $record->get( 'fields' );
$fields = [];
foreach ( $raw_fields as $id => $field ) {
$fields[ $id ] = $field['value'];
}
// Replace HTTP://YOUR_WEBHOOK_URL with the actuall URL you want to post the form to
wp_remote_post( 'HTTP://YOUR_WEBHOOK_URL', [
'body' => $fields,
]);
}, 10, 2 );
And a thread with many more examples integrating with different APIs using that template as a primer (https://github.com/elementor/elementor/issues/2397)

Custom Columns Don't Display Anything

I have added a new column to a custom post type to display the post's ID. This works for the WordPress core post type, but not for my custom post type. I have tried using the manage_{post_type}_custom_column hook and just applying it to all posts, but neither works.
It DOES add the custom column headers, but I can't populate them with anything at all when viewing the custom post type.
This is what it looks like when viewing the custom post type
and
this is what it looks like when viewing a regular core post.
// Add post ID column to use an order ID in all posts view.
add_filter('manage_posts_columns', 'oms_order_id_header');
add_action('manage_posts_custom_column', 'oms_order_id_column', 10, 2);
function oms_order_id_header($columns) {
//Remove title column
//unset($columns['title']);
//Add new columns
$columns['order_id_header'] = 'Order ID';
$columns['customer_header'] = 'Customer';
$columns['author'] = 'Owner';
return $columns;
}
function oms_order_id_column( $column, $post_id ) {
if ($column == 'order_id_header') {
echo $post_id;
}
}
This turned out to be an issue with the post type being set to hierarchical. Hierarchical post types need to be targeted by a different action hook than the one used here.
Instead of manage_posts_custom_column, hierarchical post types need to use manage_pages_custom_column.
I just tried you code and it seems to be working perfect on my WordPress installation in both cases: Custom Post and Post.
Maybe your error is happening because your posts are drafts? I don't think so but maybe. (I tried your code also with drafts on my installation and it worked). Here is the screenshot:
Try printing "hello world" instead of the $post_id to check if it prints in all cases.

Change Wordpress feed <link> for one specific tag

I have an external page that reads a RSS feed for a tag. I can't change anything on the external page, so the challenge is to change the RSS feed on my side to match the requirements.
On the external page the 3 latest posts for a tag are shown, and at the end of the section (note: not after each post but after all 3 posts) there is a "View all" link. This link receives its value from the element in the feed, which is by default set to my blog homepage, e.g. http://myblog.com). For this specific tag the link should be http://myblog.com/tag/myspecialtag.
The requirement is that the "View all" link links to the tag page instead of the homepage.
My idea was to add a condition to the element to change the URL for this specific category. I tried to change the feed template as recommended here: Customizing feeds, but for some reason it doesn't change the template at all. The code I tried is the following:
remove_all_actions( 'do_feed_rss2' );
add_action( 'do_feed_rss2', 'change_feed_rss2', 10, 1 );
function change_feed_rss2( $for_comments ) {
$rss_template = get_template_directory() . '/feeds/feed-custom_rss2.php';
if( file_exists( $rss_template ) )
load_template( $rss_template );
else
do_feed_rss2( $for_comments ); // Call default function
}
Of course I created the custom feed template and stored it in the feeds directory in my theme.
As this didn't work I tried looking into filters/hooks but I couldn't find anything helpful regarding my issue. Any ideas on how to best solve this issue?
I came up with the following solution:
I created a new custom page template custom_rss-feed.php and copied the code from wp-includes/feed-rss.php into it. I assigned this template to a new page. Additionally I added a filter to get_bloginfo_rss like the following:
function alter_bloginfo_rss($value, $key) {
if ( $key === "url" &&
is_page_template("custom_rss-feed.php")
) {
return $value . "/my/custom/url";
}
return $value;
}
add_filter("get_bloginfo_rss", "alter_bloginfo_rss", 10, 2);

Hide link to a Views' view if the view is empty

I have a Drupal 6.14 site with Views module. I have a view and on the primary links I put a link to the view.
There is a way to hide the link in the primary menu only if the view is empty?
You could probably do this either via a theme or module implementation of preprocess_page (THEMENAME_preprocess_page(&$vars) or MODULENAME_preprocess_page(&$vars)), but mac above is correct in that views are not known to be empty or not until they are run, so there will be a performance hit.
Within the function, you should have access to the structured primary links array, so you can run the view:
$view = views_get_view('view_name');
// Swap out 'default' for a different display as needed. Also, $args are arguments, and can be left out if not applicable.
$output = $view->preview('default', $args);
if (empty($view->result)) {
// The view has no results, alter the primary links here to remove the link in question.
}
I am ready to be contradicted any moment as I never implemented anything like that, however I am under the impression that since views are essentially queries against the DB, you can't actually know if a view is empty until you actually invoke it.
Consider that - given you are speaking about primary links (shown on nearly every page of your site) this might be a serious performance hit, depending on the complexity of the view and on its "cacheability".
You should also consider whether the content of that view can be changed by other users browsing the site at the same time that "our" user: should the view become populated after "our" user has loaded the page, "our" user won't ever know.
As on how to achieve what you want, please see the accepted answer.
HTH!
I override views_embed_view() to only provide output if there is content, and then call my override from the theme layer:
function mymodule_embed_view($name, $display_id = 'default') {
// handle any add'l args (this hook supports optional params)
$args = func_get_args();
array_shift($args);
if (count($args)) {
array_shift($args);
}
$view = views_get_view($name);
$output = $view->preview($display,$args);
if ($view->result) {
return $output;
}
}
Then in the template file:
<?php
$view = mymodule_embed_view('view_name');
if (strlen($view) > 0) {
print $view;
}
?>

Resources