WordPress: Having trouble in pagination for plugin settings page - wordpress

Developing a plugin in WordPress and getting well but stuck on pagination for the plugin page. Here is my code downloaded from internet ( got reference from here )
$items = $wpdb->get_var($wpdb->prepare("SELECT COUNT(*) FROM $wpdb->review_media GROUP BY post_id")); // number of total rows in the database
// tested and got results as commented
print_r($items); // say this is outputs value 2
echo $rm_options['list_per_page']; // this is my option set with value 1
if($items > 0) {
$p = new pagination;
$p->items($items);
$p->limit(empty($rm_options['list_per_page']) ? 20 : $rm_options['list_per_page']); // Limit entries per page
$p->target("admin.php?page=moderate.php");
$p->currentPage($_GET[$p->paging]); // Gets and validates the current page
$p->calculate(); // Calculates what to show
$p->parameterName('paging');
$p->adjacents(1); //No. of page away from the current page
if(!isset($_GET['paging'])) {
$p->page = 1;
} else {
$p->page = $_GET['paging'];
}
//Query for limit paging
$limit = "LIMIT " . ($p->page - 1) * $p->limit . ", " . $p->limit;
} else {
echo "No Record Found";
}
When I don't group my query by post_id it is working fine but as soon as I grouped its behaving weird. It is creating a pagination links and getting blank page. I think the reason is grouping the row. But don't know how to solve this.
Here is my table screenshot
Thanks a lot for your help...

If you use WordPress WP_List_Table class, it will take care of the pagination and provide a default table experience for the user.
This tutorial covers it all, the pagination part is:
function prepare_items() {
[...]
$per_page = 5;
$current_page = $this->get_pagenum();
$total_items = count($this->example_data);
// only necessary because we have sample data
$this->found_data = array_slice($this->example_data,(($current_page-1)*$per_page),$per_page);
$this->set_pagination_args( array(
'total_items' => $total_items, //WE have to calculate the total number of items
'per_page' => $per_page //WE have to determine how many items to show on a page
) );
$this->items = $this->found_data;
}
And here's the full plugin shown in the tutorial. And in this other plugin you can see WP_List_Table in action using database data.

Related

wordpress remove post status count from cms

I want to remove the post status count from WordPress edit.php.
My WordPress CMS have more than 500,000 posts. The publish count is loaded every time you open the page. The following query is fired every time.
This makes my Wordpress CMS loading very slow.
SELECT post_status, COUNT( * ) AS num_posts FROM wp_posts WHERE post_type = 'post' GROUP BY post_status
By tracing the code, I've worked up the only solution that I can see.
The filter bulk_post_updated_messages is ONLY called on the edit.php screen.
The counts are not calculated (in class-wp-posts-list-table.php, get_views method) if the global variable $locked_post_status is not empty.
By gluing these two pieces of information together, I've got a solution that you can use by dropping it into your theme's functions.php file:
// Hook this filter, only called on the `edit.php` screen.
// It's not the "correct" filter, but it's the only one we can leverage
// so we're hijacking it a bit.
add_filter('bulk_post_updated_messages', 'suppress_counts', 10, 2);
// We need to let the function "pass through" the intended filter content, so accept the variable $bulk_messages
function suppress_counts($bulk_messages) {
// If the GET "post_type" is not set, then it's the "posts" type
$post_type = (isset($_GET['post_type'])) ? $_GET['post_type'] : 'post';
// List any post types you would like to KEEP counts for in this array
$exclude_post_types = array('page');
// Global in the variable so we can modify it
global $locked_post_status;
// If the post type is not in the "Exclude" list, then set the $locked variable
if ( ! in_array($post_type, $exclude_post_types)) {
$locked_post_status = TRUE;
}
// Don't forget to return this so the filtered content still displays!
return $bulk_messages;
}
i came up with this solution.
//Disable Article Counter - query runs for about 1-2 seconds
add_filter('admin_init', function () {
foreach (get_post_types() as $type) {
$cache_key = _count_posts_cache_key($type, "readable");
$counts = array_fill_keys(get_post_stati(), 1);
wp_cache_set($cache_key, (object)$counts, 'counts');
}
}, -1);
add_action('admin_head', function () {
$css = '<style>';
$css .= '.subsubsub a .count { display: none; }';
$css .= '</style>';
echo $css;
});
the post counter uses the wp-cache, the idea behind this approach is, to prefill the cache with the "correct" object containing 1's (0 would skip the status from being clickable) - at the earliest moment.
it results in all stati being displayed - with 1's and the query is not run et-all
in addition it returns a css snippet to hide the (1)

Get all product variations of a product given its ID in Woocommerce

I have a custom page where I'm trying to list every products in the store along with their variations.
Also, I'm trying to list the variations' prices sorted by the product attribute with slug 'size'
For testing, I'm trying to get the variations of a single product with the ID 381
My code yet is
$handle=new WC_Product('381');
$variations1=$handle->get_avaialable_variations();
foreach ($variations1 as $key => $value) {
echo '<option value="'.$value['variation_id'].'">'.implode('/',$value['attributes']).'-'.$value['price_html'].'</option>';
}
But the error I'm getting is
PHP Fatal error: Call to undefined method WC_Product::get_avaialable_variations()
I tried using
$handle=new WC_Product_Variable('381');
instead of
$handle=new WC_Product('381');
But the error is the same.
Any help here?
Try this code.
$handle=new WC_Product_Variable('12');
$variations1=$handle->get_children();
foreach ($variations1 as $value) {
$single_variation=new WC_Product_Variation($value);
echo '<option value="'.$value.'">'.implode(" / ", $single_variation->get_variation_attributes()).'-'.get_woocommerce_currency_symbol().$single_variation->price.'</option>';
}
Note: Use this $single_variation->get_price_html() but its outputs with html span tag which results in getting hidden in option tags.
Tested the above code and the results are as follows.
Let me know if that worked for you too.
You had a typo in your code - get_avaialable_variations
It should be get_available_variations
function get_variation_data_from_variation_id($item_id) {
$_product = new WC_Product_Variation($item_id);
$variation_data = $_product->get_variation_attributes(); // variation data in array
$variation_detail = woocommerce_get_formatted_variation($variation_data, true); // this will give all variation detail in one line
// $variation_detail = woocommerce_get_formatted_variation( $variation_data, false); // this will give all variation detail one by one
return $variation_data; // $variation_detail will return string containing variation detail which can be used to print on website
// return $variation_data; // $variation_data will return only the data which can be used to store variation data
}
I found this before on stackoverflow couldn't remember the link (please edit if find the link to the answer with this method). it shows the variation data for output. the method takes variation id as perameter.
output:
.

Wordpress get attachment of post doesn't work

I'm trying to retrieve all the attachment of a specific post, but it doesn't work for the moment. Here is the code :
$args = array(
'post_type' => 'attachment',
'posts_per_page' => -1,
'post_parent' => $id
);
$attachments = get_posts($args);
Where Id is the id of my post. I've tried also with new WP_Query() but it didn't worked neither. Both ways return an empty result.
Does anyone have an idea what I'm doing wrong here ?
Thanks
EDIT
Ok, I think I know what's going wront.
When using this arguments for the get_posts function, it will return the images uploaded through the "Add a media" button in the specific post.
So basically, let's say that on my first post, I've uploaded all the images I would need for all my future post. If I apply the request on the first post, I will retrieve all the images, even the one that I don't use in this post.
If I apply this function to another post, because I didn't uploaded any file in this post, the function will retrieve an empty array.
Does anyone have an idea how I can retrieve all the images used in a specific post ? So not only uploaded, but really integrated into the post or added to a custom field ?
Thanks
When using get_posts to fetch attachments, you need to set post_status to inherit. Also, check out the get_children function:
$args = array(
'post_type' => 'attachment',
'post_mime_type' => 'image',
'numberposts' => -1,
'post_status' => 'inherit',
'post_parent' => $id
);
$attachments = get_children( $args );
Case: using ACF, I created an repeater field 'resort_pics' for my gallery, which has 2 fields 'picture_title' as text and 'picture' as an picture type.
Then happily uploaded 100 photos, some of them were same for several posts so I only clicked those from uploaded gallery (I will use term of "referenced images" for those).
Problem : then one happy day I noticed all "referenced images" are missing in our api.
Cause :
As noted at documentation comment from 'Uriahs Victor' (https://developer.wordpress.org/reference/functions/get_attached_media/)
Important to note that this function only returns the attachments that
were first uploaded/added to the post. Uploading an image to Post A(ID
1) and then adding that image later to Post B(ID 2) would give an
empty array if the following code was used:
$media = get_attached_media( 'image', 2 );
var_dump( $media );
Real cause :
Real source of all this problem is The thing that information about "reference images" are not stored in 'wp_posts' table but are actually stored in 'wp_postmeta', so by just querying 'wp_posts' table or using get_attached_media() which only looks there also you will not get all attachements for post.
Solution :
Lets take an example of post with ID - $postId which has defined
repeater - 'resort_pics', field in repeater with image 'picture'. (created with ACF plugin)
First get all attachements for our post (resort) (including images/pdfs and so on) with classic way (can be also used 'get_attached_media'):
$images = $wpdb->get_results("select ID,guid from wp_posts where post_parent = " . $postId . " and `post_type`= 'attachment'");
where guid is 'url' to an attachement, lets index those in array where key will be post id of an attachement
$mapImages = [];
foreach ($images as $image) {
$mapImages[$image->ID] = $image->guid;
}
Now we have all atachements but are missing all referenced images/files.
Lets continue by selecting all meta for our post (resort).
$metas = $wpdb->get_results("select meta_key,meta_value from wp_postmeta where post_id=" . $postId);
And index them by an meta key
$mapMetas = [];
foreach ($metas as $meta) {
$mapMetas[$meta->meta_key] = $meta->meta_value;
}
Lets say our post ($postId) has an 9 entries in 'resort_pics' with an image uploaded to its 'picture' field, then $mapMetas['resort_pics'] will have an value of 8.
Now the way how repeater fields keys are stored in $mapMetas array, is actually an :
'resort_pics_0_picture' -> itsPostId (5640 for example)
'resort_pics_1_picture' -> itsPostId (5641 for example)
'resort_pics_2_picture' -> itsPostId (5642 for example)
...
'resort_pics_8_picture' -> itsPostId (5648 for example)
Knowing this we can get simply all image urls for "resort_pics"
for ($i = 0; $i < $mapMetas['resort_pics']; $i++) {
$picture = [];
$picture['name'] = $mapMetas['resort_pics_' . $i . '_picture_title'];
$picture['url'] = $mapImages[$mapMetas['resort_pics_' . $i . '_picture']];
$pictures[] = $picture;
}
You may already get to this point, simply from $mapMetas get image ID and using it get an image url from $mapImages.
Lets say 'resort_pics_1_picture' is 'referenced' one (not directly uploaded image), we have its id '5641' but since its not connected to our $postID but to some other post id when it was actually uploaded. Its missing in our $mapImages array, so lets edit this code a bit.
for ($i = 0; $i < $mapMetas['resort_pics']; $i++) {
$picture = [];
$picture['name'] = $mapMetas['resort_pics_' . $i . '_picture_title'];
$picture['url'] = getAttachmentOrItsReferenceUrl('resort_pics_' . $i . '_picture', $mapImages, $mapMetas);
$pictures[] = $picture;
}
We have added an getAttachementOrItsReferenceUrl() method, which will simply first check if we already have this image (all uploaded to this post) and if not will fetch image data by its post id from 'wp_posts' table..
function getAttachmentOrItsReferenceUrl($code, $allAttachmentById, $allPostMetaByKey) {
global $wpdb;
$attachmentUrl = $allAttachmentById[$allPostMetaByKey[$code]];
if($attachmentUrl === null && isset($allPostMetaByKey[$code]) && $allPostMetaByKey[$code] !== '') {
$attachments = $wpdb->get_results("select ID,guid from wp_posts where ID = " . $allPostMetaByKey[$code]);
foreach ($attachments as $image) {
return $image->guid;
break;
}
} else {
return $attachmentUrl;
}
return "";
}
Finnal thoughts :
If you know your fields structure you can build up its key pretty straightforward
For an example
'rooms' repeater which has inside 'room_gallery' repeater which has inside 'image' image field.
'rooms_0_room_gallery_0_image'
--
$mapMetas['rooms'] - number of rooms
$mapMetas['rooms_' . $i . '_room_gallery'] - number of gallery images for room
--
'rooms_' . $i . '_room_gallery_' . $j . '_image'
How heavy is it ? Not really, if you are like me, having only small amount of referenced images you wont even feel it. All we added to load is an one meta query for an post, if no images are referenced that's all, then for every referenced image there is one more query, but its query on ID should be fast. There is a lot of way how to make load less, for example not do query for every single missing image, but do single query at the end with 'where in (id1,id2..)' to have single query to get all, or after fetching new image data, store it in some global array by its id, and check this array before fetching image for next posts (so if one image is stored in 200 posts, and you are fetching all it would make only 1 query), you got the point I leave it just at the ideas since this is bloody long post even without that :)
Hope this will help anybody in future.

Wordpress XML-RPC post success but don't work with long body

I use code below to post via XML-RPC, it does success. But when I send a long string $bodypost, my post doesn't have body content. I test it with html code, it's working, then I remove all space, my $bodypost just have 1 line with about 4000 words, it's not working.
How can I fix it?
<?php
function send_post($titlepost, $bodypost, $categorypost, $keywordspost )
{
require_once("IXR_Library.php.inc");
$encoding='UTF-8';
$client->debug = false; //Set it to false in Production Environment
$title= $titlepost; // $title variable will insert your blog title
$body= $bodypost; // $body will insert your blog content (article content)
$category=$categorypost; // Comma seperated pre existing categories. Ensure that these categories exists in your blog.
$keywords=$keywordspost;
$customfields=array('key'=>'Author-bio', 'value'=>'Autor Bio Here'); // Insert your custom values like this in Key, Value format
$title = htmlentities($title,ENT_NOQUOTES,$encoding);
$keywords = htmlentities($keywords,ENT_NOQUOTES,$encoding);
$content = array(
'title'=>$title,
'description'=>$body,
'mt_allow_comments'=>0, // 1 to allow comments
'mt_allow_pings'=>0, // 1 to allow trackbacks
'post_type'=>'post',
'mt_keywords'=>$keywords,
'categories'=>array($category),
'custom_fields' => array($customfields)
);
// Create the client object
$client = new IXR_Client('http://www.domain.com/xmlrpc.php');
$username = "abc";
$password = "abc";
$params = array(0,$username,$password,$content,true); // Last parameter is 'true' which means post immideately, to save as draft set it as 'false'
// Run a query for PHP
if (!$client->query('metaWeblog.newPost', $params)) {
die('Something went wrong - '.$client->getErrorCode().' : '.$client->getErrorMessage());
}
else
echo "Article Posted Successfully";
}
?>
I found how to fix it. This code does not work if my body code is give by source code of default Wordpress editor, but if I change it to CkEditor it's working!

how to alter drupal-6 view-2 query

I'm trying to update view query using drupal hook_views_pre_execute().
It's updating the query properly but even my query returning only couple of record, in view page it's showing pagination at the bottom but i've set the page limit 10. Can any one advise me how to resolve this issue.
function mymodule_views_pre_execute(&$view)
{
switch($view->name)
{
case 'test_merchandise':
$view->build_info['query'] = "MY QUERY";
drupal_set_message($view->build_info['query']);
break;
}
}
if you want to alter views query then use this method
function modulename_views_query_alter(&$view, &$query){
if ( $view->name == 'test_merchandise' ) {
//here you will get the whole $query object and alter only the place you want change
$query->orderby[0] = "substring(node_data_field_date_field_date_value,1,4) DESC";
echo "<pre>";print_r($query);echo "</pre>";
}
}

Resources