How to show each user their running total of a custom field? - php

I'll start by throwing myself on the mercy of you fine people as a complete newb to php and stackoverflow. I've searched for the answer here and elsewhere and I'm having trouble piecing it all together.
Here's my problem-
I've set up a form (using gravity forms) where logged in users can log "flight hours" after every flight. I'm using gravity forms to post this data to a custom post called "my-flight-record" where I've mapped all the fields from the form. Now, I simply want to show the user a running total of one field, wpcf-total-flight-time, but i only want to show the user their own total time.
Here's the code i'm currently using, but it sums ALL entries. I only want to sum the entry for the current user (who should also be logged in before they can even see this page).
<?php
//get current user
global $current_user;
get_currentuserinfo();
$userPosts = get_posts(array('author' => $current_user->ID, 'post_type'=> 'my-flight-record'));
// loop to create array of ids by user
foreach ($userPosts as $post) {
setup_postdata($post);
$ids[] = get_the_ID();
}
$idList = implode(",", $ids);
$meta_key = 'wpcf-total-flight-time';//set this to your custom field meta key
$allflighthours = $wpdb->get_col($wpdb->prepare("
SELECT meta_value
FROM $wpdb->postmeta
WHERE meta_key = %s
AND post_id in (" . $idList . ")", $meta_key));
echo 'My total flight hours logged = ' . array_sum( $allflighthours) . ''; ?>
This code results in a total, but for everyone, not just logged in user. Also, the '$idList = implode(",", $ids);' line results in an error for me.
Please help me help myself! I'm sure I've left out vital info - let me know what i'm missing!

Why do you need two separate database queries? Try this:
<?php
//get current user
global $current_user;
get_currentuserinfo();
$userPosts = get_posts(array('author' => $current_user->ID,
'post_type'=> 'my-flight-record'));
//initialize an empty array
$flight_hours = array();
// loop to create array of ids by user
foreach ($userPosts as $post) {
setup_postdata($post);
$flight_hours[] = get_post_meta(get_the_ID(), 'wpcf-total-flight-time', true);
}
printf('My total flight hours logged = %s ', array_sum( $flight_hours) ); ?>
As ipauler notes in his answer, you should implement some error checking to make sure there is a logged in user, and the wpcf-total-flight-time data is both present and valid.

First you need to check if user is logged in
Some example from wordpress documentation
if(!is_user_logged_in()) {
//no user logged in
}
http://codex.wordpress.org/Function_Reference/get_currentuserinfo#Parameters
//get current user
global $current_user;
if(is_user_logged_in()) {
get_currentuserinfo();
$userPosts = get_posts(array('author' => $current_user->ID, 'post_type'=> 'my-flight-record'));
// loop to create array of ids by user
foreach ($userPosts as $post) {
setup_postdata($post);
$ids[] = get_the_ID();
}
$idList = implode(",", $ids);
$meta_key = 'wpcf-total-flight-time';//set this to your custom field meta key
$allflighthours = $wpdb->get_col($wpdb->prepare("
SELECT meta_value
FROM $wpdb->postmeta
WHERE meta_key = %s
AND post_id in (" . $idList . ")", $meta_key));
echo 'My total flight hours logged = ' . array_sum( $allflighthours) . '';
}

Related

Make a SELECT WHERE query of a custom field unique for each user ID

I'm using MemberMouse for Wordpress to handle reoccurring subscriptions and I need to add a members directory (MemberMouse do not offer this) that queries MemberMouse for the info. About a dozen fields on the MemberMouse signup form are custom fields, a mixture of text and drop downs, plus one checkbox that lets the user decide if they want to appear in the directory or not.
My PHP knowledge is limited but so far I have written a small test item just to make sure I can return a result from the MemberMouse custom field and so far I have this:
global $wpdb;
$args = array(
'role' => 'paid-member',
'orderby' => 'user_nicename',
'order' => 'DSC'
);
$users = get_users( $args );
echo '<ul>';
foreach ( $users as $user ) {
$is_in_database = $wpdb->get_var( "SELECT value FROM mm_custom_field_data WHERE custom_field_id = '1' " );
echo '<li>' . esc_html( $user->display_name ) . ' [' . esc_html( $user->user_email ) . ']</li>';
echo 'Custom Field Data: '.$is_in_database.' </br></br>';
}
echo '</ul>';
This sort of works, it lists the members name and email, but where I pull the data from the custom field, it shows the first value in the database for all users rather than the unique value that is in this field for each user. How do I make it check each USER ID separately and get the custom value for that user?
I have about 8 or so of these 'SELECT' queries to add for each person.
Thank-you
You are fetching always the same data with:
$is_in_database = $wpdb->get_var( "SELECT value FROM mm_custom_field_data WHERE custom_field_id = '1' " );
If you want to return a custom field data based on the user displayed, you need to do a SELECT filtered by the ID of the user. Something like that should do the trick:
$is_in_database = $wpdb->get_var($wpdb->prepare(
"
SELECT value
FROM mm_custom_field_data
WHERE user_id = %d
",
$user->ID
));
I don't know mm_custom_field_data table structure, but I suppose that the column containing the ID of the user is user_id. You should check, just to be safe.

Creating a custom table of orders in WooCommerce - taking ages to loop through orders

I am creating a section of my WooCommerce website where my corporate clients can log on and see which of their employees have made orders.
In order to do this, I'm planning to use a WP_List_Table which will be populated by some data.
However, I am struggling to create my data array because of the size of our posts table and our order-base (c. 10000 orders), it takes ages to run through the loop.
Here is my code to create a basic array of email addresses - but Wordpress throws a fatal error after 30 seconds.
Does anyone have an idea of how I can do this in a way which will work better? Thoughts much appreciated.
// Set the parameters for a orders
$customer_orders = get_posts( array(
'numberposts' => -1,
'post_type' => 'shop_order',
'post_status' => array_keys( wc_get_order_statuses() ),
) );
// Pull a list of order IDs
$orderids = [];
foreach ($customer_orders as $customer_order) {
$orderids[] = $customer_order->ID;
}
// Create a list of orders
$orders = [];
foreach ($orderids as $orderid) {
$order = wc_get_order($orderid);
$order_company = $order->get_billing_company();
if($order_company = 'Corporate Client Name') {
$orders[] = $order->get_billing_email();
}
}
print_r($orders);
You should better use a custom SQL query, filtered directly by 'Corporate Client Name' billing company name. This will avoid to go through your 5000 orders. Here is that code:
// Filtering by a company from the beginning
$order_company = 'Corporate Client Name';
global $wpdb;
$table_postmeta = $wpdb->prefix . "postmeta";
// 1. First SQL query the order IDs related to 'Corporate Client Name'
$results = $wpdb->get_col( "
SELECT post_id
FROM $table_postmeta
WHERE $table_postmeta.meta_key LIKE '_billing_company'
AND $table_postmeta.meta_value = '$order_company'
" );
// Convert the array of IDs in a coma separated string
$orders_str = implode(',', $results);
// 2. Second SQL query get the emails from order IDs related to 'Corporate Client Name'
$emails = $wpdb->get_col( "
SELECT meta_value
FROM $table_postmeta
WHERE $table_postmeta.meta_key LIKE '_billing_email'
AND $table_postmeta.post_id IN ($orders_str)
" );
// Testing output
print_r( $emails );
This code is tested and works

How can I list all editors of a WordPress page, including those who edited (saved page) without creating a proper revision?

I'm trying to display a list of the people who have authored AND edited a page in Wordpress, not just the people who have authored revisions. the_modified_author() gives me the name of the person who last saved the page. birgire suggested this code to get the list of all editors, but it seems to only show the authors of the original post and all revisions, and doesn't include the names of those who saved a change that wasn't actually a revision:
function get_the_modified_authors_wpse_99226(){
global $wpdb;
$authors = array();
$results = $wpdb->get_results( $wpdb->prepare("SELECT post_author FROM $wpdb->posts WHERE (post_type = '%s' AND ID = %d) OR (post_type = 'revision' AND post_parent = %d) GROUP BY post_author", get_post_type( get_the_ID() ), get_the_ID(), get_the_ID() ) );
foreach($results as $row){
$authors[] = get_the_author_meta('display_name', $row->post_author );
}
return implode(", ", $authors);
}
Sometimes people edit a page (for example, they make an edit to a custom field) and then update the post. When that happens, they would be listed under the_modified_author() but would not be considered an author of a revision.
What I need is a combined list of both revision authors AND those people who have edited (saved) the page without creating a revision. Sort of like the function for modified_author but without the '_edit_last', true part.
Is this possible?
Please try the below code :
$revisions = $wpdb->get_results("select * from {$wpdb->posts} where post_parent={$post_id} and post_type='revision'")
You may need to do some change according to your need.

Searching a custom table in wordpress

I'm currently building a site for a client and they want a search feature that will search all of the products they supply.
I have created a new table in the database called sc_products and then tried the below code in a wordpress template page but I don't appear to be getting anywhere. If anyone knows how I can get this working that would be awesome!
<?php
/*
Template Name: myTemp
*/
function search_it() {
if ( is_search() && isset($_GET['s'])) {
global $wpdb;
$address_table = $wpdb->prefix . "sc_products";
$myrows = $wpdb->get_results( 'SELECT product FROM ' . $sc_products );
foreach ( $myrows as $single_row ) {
global $single_row;
}
$product = $single_row->product;
}
return $product;
}
$city = search_it();
echo $city;
get_search_form();
?>
There's a couple of things going on here, let's see if we can work them out.
Here's your modified function which should perform a search, with comments throughout to help explain what's going on.
NOTES:
1. You declare $address_table, but then use $sc_products. That can't be correct, as $sc_products is not defined.
2. This answer is based on the column names you provided in comments - IF they are not an exact match, you'll need to update them, INCLUDING matching case. If it's not Application, but instead application, you'll need to make that change.
function search_it() {
// If this is a search, and the search variable is set
if ( is_search() && isset( $_GET['s'] ) ) {
// Global in $wpdb so we can run a query
global $wpdb;
// Build the table name - glue the table prefix onto the front of the table name of "sc_products"
$address_table = $wpdb->prefix . "sc_products";
// Get the search term into a variable for convenience
$search = $_GET['s'];
// To use "LIKE" with the wildcards (%), we have to do some funny business:
$search = "%{$search}%";
// Build the where clause using $wpdb->prepare to prevent SQL injection attacks
// Searching ALL THREE of our columns: Product, Application, Sector
$where = $wpdb->prepare( 'WHERE Product LIKE %s OR Application LIKE %s OR Sector LIKE %s', $search, $search, $search );
// Execute the query with our WHERE clause
// NOTE: Your code originally used "$sc_products", but that variable was not defined - so have replaced to the proper $address_table here.
$results = $wpdb->get_results( "SELECT product FROM {$address_table} {$where}" );
// return the results. No need to put into an array, it's already an array
return $product;
}
// For consistency, return an empty array if not a search / no search term
return array();
}
// USAGE:
// Run the query
$cities = search_it();
// You can't echo an array!
// echo $city;
// var_dump to see the whole array
var_dump( $cities );
// More useful USAGE:
$cities = search_it();
// If there's any results
if ( ! empty( $cities ) ) {
// Output a title
echo '<h1>Product Search Results:</h1>';
// Loop over the results
foreach( $cities AS $city ) {
// $wpdb returns an array of objects, so output the object properties
echo '<h2>' . $city->Product . '</h2>';
echo '<p>' . $city->Application . '</p>';
echo '<p>' . $city->Sector . '</p>';
}
}
get_search_form();

WordPress: Count all comments by user then count meta data on comments

I have set some custom meta against certain comments for users using this function: add_comment_meta( $wp_comment_id, 'accepted', true );
What I want to do is show for each user on their profile /author/username is how many of these special comments they have so for example if a user made 20 comments and 5 had this meta data of accepted equalling true then the value would be 5.
How could I do this? Thanks.
I'm assuming this is the latest version of wordpress. You can see the database schema diagram here: http://codex.wordpress.org/images/9/9e/WP3.0-ERD.png
I haven't tested this, but something LIKE this should do the trick:
<?php
getCommentCount('John', 'accepted', 'true');
function getCommentCount($author_name, $meta_key, $meta_value){
if(empty($author_name)){
return;
}
$author_name = trim($author_name);
$sql = 'SELECT count(*) FROM ' . $wpdb->comments . ' comments '
. ' INNER JOIN ' . $wpdb->commentmeta . ' meta ON comments.comment_ID = meta.comment_id '
. ' WHERE comments.comment_author = %s AND meta.meta_key = %s ANd meta.value = %s ';
$commentCount = $wpdb->get_var($wpdb->prepare($sql, $author_name, $meta_key, $meta_value));
return $commentCount;
}
i dont understand what do you mean by "count meta data"...
whice value in meta data.. do you mean the user's meta data or the comment.
Anyhow - in order to count comments by a specific user you can...
Put this code in your functions php
function countUserComments($userID) {
$args = array(
'user_id' => $userID
);
$comments = get_comments( $args );
echo count($comments);
}
The you can use it anywhere where you got a user id available to you like so
<?php echo countUserComments($user->ID); ?>
.
Hope this helps anyone ;)
Cheers, Sagive

Categories