Limit output results of an array - php

I wanna limit the result to 10 elements (10 words). This is the code I got:
function ls_bp_hashtags_cloud() {
$args = array () ;
if ( bp_is_activity_component() ) {
$toHead = __( 'Popular Hashtags across network' , 'bp-hashtags' ) ;
}
if ( bp_is_user_activity() ) {
$toHead = __( 'Hashtags by user' , 'bp-hashtags' ) ;
$args[ 'user_id' ] = bp_displayed_user_id() ;
}
if ( bp_is_group_activity() || bp_is_group_home() ) {
$toHead = __( 'Hashtags in group' , 'bp-hashtags' ) ;
$args[ 'if_activity_item_id' ] = bp_get_current_group_id() ;
}
echo '<div align="right"><h5>' . $toHead . '</h5>' ;
echo ls_bp_hashtags_generate_cloud( $args ) ;
echo '</div>' ;
}
And thisone below is the ls_bp_hashtags_generate_cloud() function:
function ls_bp_hashtags_generate_cloud( $args = array() ) {
$hashtags = ls_bp_hashtags_get_hashtags( $args );
$defaults = array(
'smallest' => 10, 'largest' => 10, 'unit' => 'pt', 'number' => 0,
'format' => 'flat', 'separator' => ",\n\n", 'orderby' => 'count', 'order' => 'DESC',
'topic_count_text_callback' => 'default_topic_count_text',
'topic_count_scale_callback' => 'default_topic_count_scale', 'filter' => 1
);
$args = wp_parse_args( $args, $defaults );
extract( $args );
$tag_cloud = wp_generate_tag_cloud( $hashtags, $args );
$tag_cloud = '<div class="hashtags">' . $tag_cloud . '</div>';
return $tag_cloud;
}
I got this other one too, not sure if it's needed:
function ls_bp_hashtags_get_hashtags( $args = array() ) {
global $wpdb;
$bp = buddypress();
$link = $bp->root_domain . "/" . $bp->activity->slug . "/" . BP_ACTIVITY_HASHTAGS_SLUG . "/";
bp_hashtags_set_constants();
$data = maybe_unserialize( get_site_option( 'ls_bp_hashtags' ) );
if ( $data['style']['show_hashsymbol'] == '1' ) {
$hashtag_name = ' CONCAT( "#", hashtag_name)';
} else {
$hashtag_name = 'hashtag_name ';
}
$toWhere = ls_bp_hashtags_generate_query_limitations( $args );
$results = $wpdb->get_results( 'SELECT COUNT(hashtag_name) as count, '
. $hashtag_name . ' as name, '
. 'CONCAT("' . $link . '", hashtag_slug) as link
FROM ' . BP_HASHTAGS_TABLE . ' WHERE 1=1 ' . $toWhere . ' GROUP BY hashtag_name' );
return $results;
}
The first snippet I pasted here is in one file while the last 2 snippets are in another file.
I think I have to modify the function ls_bp_hashtags_generate_cloud(), the point is I don't know how to do that. I tried with array_slice() and with $sql = "SELECT * FROM bp_activity LIMIT 10"; I checked mysql database, my ashtags are located in bp_ashtags table, but when I open this table I see each hashtag is referred to be in bp_activity table.
This function gives me the ashtags cloud of my buddypress activity stream page, so it gives me all the ahstags present in the database, instead I wanna limit the result to just 10 #ashtags (it's a wordpress website). That said I'm really a novice so please if you can help me giving me the whole snippet to add and where to put it, I know almost nothing about php coding. If you need to know other things about this code, just tell me; thisone is an extract so I don't know if I'm missing something for the solution. Thank you in advance

Yes, I have to modify the function ls_bp_hashtags_generate_cloud(), the point is I don't know how to do that. I tried with array_slice() and with $sql = "SELECT * FROM bp_activity LIMIT 10"; I checked mysql database, my ashtags are located in bp_ashtags table, but when I open this table I see each hashtag is referred to be in bp_activity table. This function gives me the ashtags cloud of my buddypress activity stream page, so it gives me all the ahstags present in the database, instead I wanna limit the result to just 10 #ashtags (it's a wordpress website). That said I'm really a novice so please if you can help me giving me the whole snippet to add and where to put it.

Related

Wordpress: Automatically change URLs in the_content section

The solution from here isn't solving our problem.
I have already a solution to change all links in a field form in our theme. I am using different arrays for every network like $example_network_1 $example_network_2 with a PHP foreach for each affiliate network.
Now I need a solution to use this same arrays for the content of a WordPress post.
This solution is working for one network, but it caused a 404e Error for YouTube videos. We put the URL from a YouTube video and WordPress generates automatically an embedded video. With the following code we get a 404 error iframe or something like this.
We need a solution for more than one network.
I am very thankful for every help!
$example_network_1 = array(
array('shop'=>'shop1.com','id'=>'11111'),
array('shop'=>'shop2.co.uk','id'=>'11112'),
);
$example_network_2 = array(
array('shop'=>'shop-x1.com','id'=>'11413'),
array('shop'=>'shop-x2.net','id'=>'11212'),
);
add_filter( 'the_content', 'wpso_change_urls' ) ;
function wpso_found_urls( $matches ) {
global $example_network_1,$example_network_2;
foreach( $example_network_1 as $rule ) {
if (strpos($matches[0], $rule['shop']) !== false) {
$raw_url = trim( $matches[0], '"' ) ;
return '"https://www.network-x.com/click/'. $rule['id'].'lorem_lorem='.rawurlencode($raw_url ) . '"';
}
/*
foreach( $example_network_2 as $rule ) {
if (strpos($matches[0], $rule['shop']) !== false) {
$raw_url = trim( $matches[0], '"' ) ;
return '"https://www.network-y.com/click/'. $rule['id'].'lorem='.rawurlencode($raw_url ) . '"';
}
*/
}
}
function wpso_change_urls( $content ) {
global $example_network_1,example_network_2;
return preg_replace_callback( '/"+(http|https)(\:\/\/\S*'. $example_network_1 ['shop'] .'\S*")/', 'wpso_found_urls', $content ) ;
// return preg_replace_callback( '/"+(http|https)(\:\/\/\S*'. $example_network_2 ['shop'] .'\S*")/', 'wpso_found_urls', $content ) ;
}
autoembed is hooked at the_content with priority 8 on wp-includes/class-wp-embed.php:39
Try to lower the priority of the the_content filter so that the URL replacement happens before the embed, something like this:
add_filter( 'the_content', function ( $content ) {
/*
* Here, we define the replacements for each site in the network.
* '1' = main blog
* '2' = site 2 in the network, and so on
*
* To add more sites, just add the key number '3', etc
*/
$network_replacements = [
'1' => [
[ 'shop' => 'shop1.com', 'id' => '11111' ],
[ 'shop' => 'shop2.co.uk', 'id' => '11112' ],
],
'2' => [
[ 'shop' => 'shop-x1.com', 'id' => '11413' ],
[ 'shop' => 'shop-x2.net', 'id' => '11212' ],
]
];
// Early bail: Current blog ID does not have replacements defined
if ( ! array_key_exists( get_current_blog_id(), $network_replacements ) ) {
return $content;
}
$replacements = $network_replacements[ get_current_blog_id() ];
return preg_replace_callback( '/"+(http|https)(\:\/\/\S*' . $replacements['shop'] . '\S*")/', function( $matches ) use ( $replacements ) {
foreach ( $replacements as $rule ) {
if ( strpos( $matches[0], $rule['shop'] ) !== false ) {
$raw_url = trim( $matches[0], '"' );
return '"https://www.network-x.com/click/' . $rule['id'] . 'lorem_lorem=' . rawurlencode( $raw_url ) . '"';
}
}
}, $content );
}, 1, 1 );
This is not a copy and paste solution, but should get you going. You might need to tweak your "preg_replace_callback" code, but you said it was working so I just left it is it was.
If preventing the wp auto-embed works, then just add this line to your theme functions.php
remove_filter( 'the_content', array( $GLOBALS['wp_embed'], 'autoembed' ), 8 );
I wrote solution without test. Your code is hard to test without your site but I think that problem is with regex. Callback is hard to debugging. My version below.
First step, change your structure. I suspect that domains are unique. One dimensional array is more useful.
$domains = array(
'shop1.com'=>'11111',
'shop2.co.uk'=>'11112',
'shop-x1.com'=>'11413',
'shop-x2.net'=>'11212',
);
Next:
$dangerouschars = array(
'.'=>'\.',
);
function wpso_change_urls( $content ) {
global $domains,$dangerouschars;
foreach($domains as $domain=>$id){
$escapedDomain = str_replace(array_keys($dangerouschars),array_values($dangerouschars), $domain);
if (preg_match_all('/=\s*"(\s*https?:\/\/(www\.)?'.$escapedDomain.'[^"]+)\s*"\s+/mi', $content, $matches)){
// $matches[0] - ="https://example.com"
// $matches[1] - https://example.com
for($i = 0; $i<count($matches[0]); $i++){
$matchedUrl = $matches[1][$i];
$url = rawurlencode($matchedUrl);
//is very important to replace with ="..."
$content = str_replace($matches[0][$i], "=\"https://www.network-x.com/click/{$id}lorem_lorem={$url}\" ", $content);
}
}
}
return $content;
}
Example script

counting content with tag in foreach loop wordpress

I am trying to show only tags which have more than specific number of posts. To achieve this I modified my tag-links.php code as below. But with this code I got some weird behavior. My page don't show any tag below the number of content, it is ok, but sometimes it also hides other tags. when I refresh the page it will show different tags or don't show any tags. I am newbie with php syntax, so I am not sure but code seems correct. Can you tell me the code problem, or any practical approach to solve my problem.
PS: code also include this function, every tag redirect user to random post with this specific tag, it works well.
<?php
$tags = get_the_tags( $post->ID );
$separator = ' ';
$output = '';
if ( $tags ) {
$link = "";
$xnumber = 0; //number for contents with specific tag
echo '<div class="entry-tags">';
echo "<p><span>" . __( ) . "</span>";
foreach ( $tags as $tag ) {
$posts = get_posts("post_type=post&orderby=rand");
foreach($posts as $post) {
if(has_tag($tag->term_id)) {
$xnumber++;
if($xnumber >= 1) {
$link = get_permalink($post);
break 1;
} else { }
} else { }
}
if($xnumber >= 1) {
$output .= '<a href="' . esc_url( $link ) . '" title="'
. esc_attr( sprintf( __( "View all posts tagged %s",
'tracks' ), $tag->name ) ) . '">' . esc_html( $tag->name )
. '</a>' . $separator;
unset($link);
unset($xnumber);
} else {
unset($link);
unset($xnumber);
}
}
echo trim( $output, $separator );
echo "</p>";
echo "</div>";
}
Ok, so a couple of things:
1) You arent using the get_posts function the way it's documented. You should be passing in an array of settings. Here's the link to documentation: https://developer.wordpress.org/reference/functions/get_posts/
2) The get_posts() function has a default limit of 5 records. And you're bringing back the list in random order. So, sometimes the 5 records you get will have the tag you're looking for, and sometimes it wont. If you want it to check more records, you'll need to change the numberposts.
Following example displays posts tagged with 'jazz', under 'genre' custom taxonomy, using 'tax_query':
$args = array(
'tax_query' => array(
array(
'taxonomy' => 'genre',
'field' => 'slug',
'terms' => 'jazz'
)
)
);
$postslist = get_posts( $args );
That may be more what you're looking for...
A better example using post tags:
$args = array(
'tax_query' => array(
array(
'taxonomy' => 'post_tag',
'field' => 'slug',
'terms' => $tag
)
)
};

Duplicate per-product shipping extension information - WooCommerce

on my wordpress site I have WooCommerce and the WooCommerce per product shipping extension (https://docs.woocommerce.com/document/per-product-shipping/). I currently have an issue, this is that whenever I duplicate a woocommerce product the per-product shipping information is not copied. I have tried to find a solution for this and have got the following code however I have not been able to get it work, can anyone see what is going wrong in the following
add_action( 'woocommerce_product_duplicate', 'wdm_duplicate_pps_entries',10,2);
function wdm_duplicate_pps_entries( $new_id, $post) {
global $wpdb;
$id = isset( $_REQUEST['post'] ) ? absint( $_REQUEST['post'] ) : '';
if(!empty($id)) {
$query = "Select * From " . $wpdb->prefix . "woocommerce_per_product_shipping_rule
Where product_id = '" . $id . "'";
$result = $wpdb->get_results($query);
$table_name = $wpdb->prefix . "woocommerce_per_product_shipping_rule";
foreach($result as $single_result) {
$data = array('product_id' => $new_id, 'rule_country' => $single_result->rule_country, 'rule_state' => $single_result->rule_state,'rule_postcode' => $single_result->rule_postcode,'rule_cost' => $single_result->rule_cost,'rule_item_cost' => $single_result->rule_item_cost,'rule_order' => $single_result->rule_order);
$wpdb->insert($table_name,$data);
}
}
}
This is an example of the additonal info I am trying to copy -
UPDATE: Wordpress has fixed this bug
The below code working perfect.
add_action( 'woocommerce_duplicate_product', 'wdm_duplicate_pps_entries',10,2);
function wdm_duplicate_pps_entries( $new_id, $post) {
global $wpdb;
$id = isset( $_REQUEST['post'] ) ? absint( $_REQUEST['post'] ) : '';
if(!empty($id)) {
$query = "Select * From " . WC_PRODUCT_VENDORS_PER_PRODUCT_SHIPPING_TABLE . "
Where product_id = '" . $id . "'";
$result = $wpdb->get_results($query);
$table_name = WC_PRODUCT_VENDORS_PER_PRODUCT_SHIPPING_TABLE;
foreach($result as $single_result) {
$data = array('product_id' => $new_id, 'rule_country' => $single_result->rule_country, 'rule_state' => $single_result->rule_state,'rule_postcode' => $single_result->rule_postcode,'rule_cost' => $single_result->rule_cost,'rule_item_cost' => $single_result->rule_item_cost,'rule_order' => $single_result->rule_order);
$wpdb->insert($table_name,$data);
}
}
}

How to separate gallery from content in wordpress?

What I want to do
I have a website that uses a CMS I wrote some time ago, and now I am trying to migrate it to wordpress.
At the existing implementation, when someone writes a post, they can add some extra images that are shown as a gallery at the end of the post, as you can see in this page for example (sorry for non english page): http://apollonpatras.gr/news/562/i-bradia-ton-xorigon-parousiasi-xorigikou-programmatos-kai-eisitirion-diarkeias/.
How I think I can do it
I am thinking about letting the users create wordpress galleries and at post save time intercept the post contents and store the gallery image ids in a postmeta field so I can show them however I want.
Also, I will have to strip the galleries from the content before they are shown, since I will show them in my own way later.
What I am trying so far
add_filter('content_save_pre', 'intercept_galleries', 99);
function intercept_galleries($content) {
if (get_post_type() !== 'post') {
return $content;
}
if (has_shortcode($content, 'gallery')) {
// The [gallery] short code exists.
$a = get_post_gallery(0, false);
update_post_meta(get_the_ID(), 'has_gallery', 1);
update_post_meta(get_the_ID(), 'gallery_items', $a['ids']);
} else {
update_post_meta(get_the_ID(), 'has_gallery', 0);
update_post_meta(get_the_ID(), 'gallery_items', "");
}
return $content;
}
add_filter('the_content', 'remove_shortcodes_from_content');
function remove_shortcodes_from_content($content) {
return strip_shortcodes($content);
}
Where it goes wrong
Looks like when the post is originally saved, the postmeta field "has_gallery" is set to 1, but the field "gallery_items" is empty.
When I go to the wordpress editor and just hit update, the fields are absolutely correct.
Also the hook to remove shortcodes from the content is working.
What am I looking for
How can I fix this problem? Also, is there something wrong/stupid with the way I decided to do this? Would some other way be cleaner/easier/faster etc?
Thank you for your time
I've done this a few times and here's how I do it.
First I create a function that will display the gallery in the way that I want. You can modify this according to how you require you gallery markup to be:
function my_gallery_shortcode( $attr ) {
$post = get_post();
if ( ! empty( $attr['ids'] ) ) {
$attr['include'] = $attr['ids'];
}
extract( shortcode_atts( array(
'order' => 'ASC',
'orderby' => 'post__in',
'id' => $post->ID,
'columns' => 3,
'size' => 'large',
'include' => '',
), $attr));
$id = (int) $id;
$columns = (int) $columns;
if ( 'RAND' == $order ) {
$orderby = 'none';
}
if ( ! empty( $include ) ) {
$_attachments = get_posts( array( 'include' => $include, 'post_status' => 'inherit', 'post_type' => 'attachment', 'post_mime_type' => 'image', 'order' => $order, 'orderby' => $orderby ) );
$attachments = array();
foreach ( $_attachments as $key => $val ) {
$attachments[$val->ID] = $_attachments[$key];
}
}
if ( empty( $attachments ) ) {
return '';
}
$output = '<div class="slideshow"><ul>';
foreach ( $attachments as $id => $attachment ) {
$thumb = wp_get_attachment_image_src( $id, 'large', false );
$output .= '<li><img src="' . $thumb[0] . '" width="' . $thumb[1] . '" height="' . $thumb[2] . '" alt="' . get_post_meta( $id, '_wp_attachment_image_alt', true ) . '" /></li>';
}
$output .= '</ul></div>';
return $output;
}
You can complicate or simply the function above according to your requirements.
Then in your theme's functions.php add this:
add_shortcode( 'gallery', 'my_gallery_shortcode' );
Now you have two choices:
1) You can allow your user to add a gallery to the main page content by way of them editing the page in question and going to Media > Create Gallery
This will insert the gallery short code which will be formatted according to your function my_gallery_shortcode(), however the gallery can be managed via WordPress's gallery functionality in the admin area and is stored in the database by WordPress in the conventional way.
or
2) You could create a separate WYSIWYG field either through additional code in your functions.php file, or by using a plugin such as Advanced Custom Fields. You would then use this additional WYSIWYG field to allow the user to insert the gallery shortcode in the same way as above. This is virtually the same as option 1 above but you'd have more flexibility as to where you output and position the gallery on the page.
I hope this helps anyone looking to do the same thing.

Adding custom meta into wordpress search

I'm currently trying to add my theme posts custom meta values into search query, but it's not working for me. For example _My_meta_value_key3 is product code, but if i try to search it, wp don't find the match. I really want to make this without any plugins so any suggestions are welcome. Also, this code is currently located in theme functions.
function My_custom_search_query( $query ) {
if ($query->is_search()) {
$query->set('meta_query', array(
array(
'key' => '_My_meta_value_key',
'value' => $query->query_vars['s'],
'compare' => 'LIKE'
),
array(
'key' => '_My_meta_value_key2',
'value' => $query->query_vars['s'],
'compare' => 'LIKE'
),
array(
'key' => '_My_meta_value_key3',
'value' => $query->query_vars['s'],
'compare' => 'LIKE'
)
));
return $query;
};}
add_filter( 'pre_get_posts', 'My_custom_search_query');
I've spent an hour searching for a solution and there was nothing that works so I had to write the solution on my own. It is tested and working with Wordpress 5.3.1 and is the only solution that solves this problem I could find on the internet.
Place the following code in your functions.php file to hook into posts_clauses filter.
/**
* Include meta fields in search
*
* #author Mindaugas // meevly.com
* #link https://meevly.com/services/custom-wordpress-themes-and-plugins/
*
* #param array $pieces query pieces.
* #param WP_Query $args query object.
* #return array
*/
function mv_meta_in_search_query( $pieces, $args ) {
global $wpdb;
if ( ! empty( $args->query['s'] ) ) { // only run on search query.
$keywords = explode(' ', get_query_var('s'));
$escaped_percent = $wpdb->placeholder_escape(); // WordPress escapes "%" since 4.8.3 so we can't use percent character directly.
$query = "";
foreach ($keywords as $word) {
$query .= " (unique_postmeta_selector.meta_value LIKE '{$escaped_percent}{$word}{$escaped_percent}') OR ";
}
if ( ! empty( $query ) ) { // append necessary WHERE and JOIN options.
$pieces['where'] = str_replace( "((({$wpdb->posts}.post_title LIKE '{$escaped_percent}", "( {$query} (({$wpdb->posts}.post_title LIKE '{$escaped_percent}", $pieces['where'] );
$pieces['join'] = $pieces['join'] . " INNER JOIN {$wpdb->postmeta} AS unique_postmeta_selector ON ({$wpdb->posts}.ID = unique_postmeta_selector.post_id) ";
}
}
return $pieces;
}
add_filter( 'posts_clauses', 'mv_meta_in_search_query', 20, 2 );
And your query should look like the following. Please note that suppress_filters => false is mandatory! It will not work without it.
$search_posts_array = array(
'suppress_filters' => false,
's' => $keyword,
);
$search_results = get_posts( $search_posts_array );
Please do not hesitate to credit if I saved you tons of time! :)
Found this http://wpdevsnippets.com/extend-search-include-custom-fields-without-plugin/ :
function custom_search_where($pieces) {
// filter to select search query
if (is_search() && !is_admin()) {
global $wpdb;
$custom_fields = array('field1','field2'); // Array for custom meta fields
$keywords = explode(' ', get_query_var('s'));
$query = "";
foreach ($custom_fields as $field) {
foreach ($keywords as $word) {
$query .= "((mypm1.meta_key = '".$field."')";
$query .= " AND (mypm1.meta_value LIKE '%{$word}%')) OR ";
}
}
if (!empty($query)) {
// add to where clause
$pieces['where'] = str_replace("(((wp_posts.post_title LIKE '%", "( {$query} ((wp_posts.post_title LIKE '%", $pieces['where']);
$pieces['join'] = $pieces['join'] . " INNER JOIN {$wpdb->postmeta} AS mypm1 ON ({$wpdb->posts}.ID = mypm1.post_id)";
}
}
return ($pieces);
}
add_filter('posts_clauses', 'custom_search_where', 20, 1);

Categories