WP Learndash plugin, get userdata related to courses and lessons - wordpress

Hi I am using learndash Wordpress plugin. I want to get the data related to a user tht how many courses he is enrolled in and how many has he completed. Is there a way to check this? does learndash provide any solution for this or should I query data myself?
Any help is appreciated. Thanks in advance.
Please ask for any more details if you want.

You can use the following to get all course ID's the current user is currently enrolled to:
learndash_user_get_enrolled_courses(get_current_user_id())

I found that all is stored inside the table learndash_user_activity and you can query that table to get user stats.
For example I get the list of the in-progress users for a given course with the following query:
public static function get_inprogress_users_for_course( $course_id )
{
global $wpdb;
if( empty( $course_id ) ) return [];
$results = $wpdb->get_results( "SELECT `user_id` FROM `" . $wpdb->prefix . "learndash_user_activity` "
."WHERE `course_id` = '" . intval( $course_id ) . "' "
."AND `activity_type` = 'lesson' "
."GROUP BY `user_id`" );
return $results;
}
In the same way, you can get all the IDs of the users ever enrolled to a course changing activity_type from 'lesson' to 'course' in the query, and if you want to only get enrolled course by a user, you can add the user_id to the query, like this:
public static function get_courses_for_user( $user_id )
{
global $wpdb;
if( empty( $course_id ) ) return [];
$results = $wpdb->get_results( "SELECT * FROM `" . $wpdb->prefix . "learndash_user_activity` "
."WHERE `user_id` = '" . intval( $user_id ) . "' "
."AND `activity_type` = 'course' "
."GROUP BY `course_id`" );
return $results;
}
I know this is not exactly what you were searching for, but it could still be useful.

You can return anything using wp_query. Try this:
function wpso49370180_get_course_name($courseid) {
global $wpdb;
$user_id = the_author_meta( 'ID' ); //alt method below
$query_course = "SELECT post_title
FROM wp_posts
WHERE post_type = 'sfwd-courses'
AND post_status NOT IN ( 'trash','auto-draft','inherit' )
AND post_author='$user_id' LIMIT 10";
return $wpdb->get_var($query_course);
}
You will need to either know the user_id or get it from the post (sfwd-quiz, sfwd-course, sfwd-lesson) -see below.
The data you want can be all (*) You will have to do a meta_query if you want deeper data that is not in the post_type tables.
/**
* Gets the author of the specified post. Can also be used inside the loop
* to get the ID of the author of the current post, by not passing a post ID.
* Outside the loop you must pass a post ID.
*
* #param int $post_id ID of post
* #return int ID of post author
*/
function wpso49370180_get_author( $post_id = 0 ){
$post = get_post( $post_id );
return $post->post_author;
}

Related

WordPress How can I get post_id from thumbnail_id?

I'm developing wordpress plugin.
I need to find out post_id from thumbnail_id(not reverse !).
How can I do this?
You can get result by this code
global $wpdb;
$_thumbnail_id = {thumbnail id};
$sql = "SELECT `post_id` FROM `wp_postmeta` WHERE `meta_value` = $_thumbnail_id";
$result = $wpdb->get_results( $sql, ARRAY_A );
//access first returned post id
var_dump($result[0]['post_id']);
If you added same image for multiple posts there will be multiple returns.
You can use get_the_ID() to get the post id. You can find this function in wp-includes/post-template.php
function get_the_ID() {
$post = get_post();
return ! empty( $post ) ? $post->ID : false;
}

A Wordpress cronjob to cancel WC orders for a product that was deleted?

I have a project where a user can actually delete their own virtual product they have put up for sale and there may actually be some active orders on that product at the time of its deletion. I figured the best solution would be to add a cronjob that runs every 10 minutes, using a real cron, via crontab, rather than the Wordpress virtual cron, which I have already enacted - but the question is, how do I get all of the orders for a product and then change the status of all of those products to cancelled rather than deleting them, for posterity.
Any help will be appreciated, thank you.
So, worked it out... safer and just generally better way of doing this. Rather than a cronjob, you hook on post deletion and when a product is actually deleted you perform the query required. You find all the attached orders that are not already complete and you cancel those upcoming / pending orders.
function get_order_ids_by_product_id( $product_id, $order_status = array( 'wc-completed' ) ){
global $wpdb;
$results = $wpdb->get_col("
SELECT order_items.order_id
FROM {$wpdb->prefix}woocommerce_order_items as order_items
LEFT JOIN {$wpdb->prefix}woocommerce_order_itemmeta as order_item_meta ON order_items.order_item_id = order_item_meta.order_item_id
LEFT JOIN {$wpdb->posts} AS posts ON order_items.order_id = posts.ID
WHERE posts.post_type = 'shop_order'
AND posts.post_status NOT IN ( '" . implode( "','", $order_status ) . "' )
AND order_items.order_item_type = 'line_item'
AND order_item_meta.meta_key = '_product_id'
AND order_item_meta.meta_value = '$product_id'
");
return $results;
}
add_action( 'before_delete_post', 'check_for_active_orders' );
function check_for_active_orders($post_id){
$WC_Product = wc_get_product( $post_id );
$orders_ids = get_order_ids_by_product_id( $post_id );
if(count($orders_ids) > 0){
foreach($orders_ids as $oid){
$order = new WC_Order($oid);
$order->update_status('cancelled', 'This product has been removed.');
}
}
}
Hopefully it'll help someone else in the near future.

sort wordpress posts by title, ignore articles like “the”, “a”, “an”

I'm sorting my posts alphabetically by Title, like so:
<?php
{
$posts = get_posts($query_string .
'&orderby=title&order=asc&posts_per_page=-1');
}
get_template_part( 'loop', 'category' );
?>
I'd like to exclude articles such as "the", "a", and "an" from the sort.
What would be the best way to accomplish this?
Thanks!
I don't know any simple way to do that but you can do this,
For achieving this you need to add a custom meta field to the post. Name it mytitle (say).
For the new posts you add, it is simple, you have to add your modified title(removing a, an, the from the title) in the mytitle custom field in the add posts page.
For old posts it is a bit tricky, you have to write a php code to retrieve the titles of the post remove 'a','an','the' from them using php preg_replace and add it to the postmeta table of your wordpress database using something like this:
<?php //inside loop
$query=INSERT INTO xyz_postmeta (post_id, meta_key, meta_value) VALUES ($postid, 'mytitle' $title);
$wpdb->query('$query'); ?>
where $postid is the post id inside the loop and $title is your modified title.
Now you have updated all the previous posts with custom mytitle field.
Now to display, you have to use a custom loop (not the loop included in the theme).
Here is how you can make a basic custom loop to display posts sorted in order of mytitle.
$querystr = "
SELECT wposts.*
FROM $wpdb->posts wposts, $wpdb->postmeta wpostmeta
WHERE wposts.ID = wpostmeta.post_id
AND wpostmeta.meta_key = 'mytitle'
AND wposts.post_type = 'post'
AND wposts.post_status = 'publish'
ORDER BY wpostmeta.meta_value ASC
";
Now you can execute the query by any means you want. Wordpres provides various methods to do so. Here's a link
For example you can do something like this
$pageposts = $wpdb->get_results($querystr, OBJECT);
foreach ( $pageposts as $pagepost )
{
echo $pagepost->post_title;
//do other stuff to display content, meta etc..
}
You can actually achieve this by manipulating the ORDERBY clause using the posts_orderby_request filter, and using TRIM to ignore articles "the", "a", and "an". Here's an example:
<?php
add_filter( 'posts_orderby_request', 'myproject_title_sort', 10, 2 );
/**
* Ignore opening articles when sorting by Title.
*
* #param string $orderby Order by parameter.
* #param WP_Query $query WP Query object.
*
* #return string
*/
function myproject_title_sort( $orderby, $query ) {
global $wpdb;
// Be sure to add a condition that matches your criteria (post type, archive, etc).
// In this example, we bail early if it's an Admin query, or not a main query.
if ( is_admin() || ! $query->is_main_query() ) {
return $orderby;
}
// This is another check to see if we're on a particular post type archive.
if ( ! $query->is_post_type_archive( 'my-post-type' ) ) {
return $orderby;
}
$title_col = $wpdb->posts . '.post_title';
// Check if we are sorting by post_title.
// You may need to use a separate `pre_get_posts` filter to sort by "title" if not already doing so.
if ( false === strpos( $orderby, $title_col ) ) {
return $orderby;
}
$ignore = "TRIM( LEADING 'the ' FROM LOWER( TRIM( LEADING 'a ' FROM LOWER( TRIM( LEADING 'an ' FROM LOWER( $title_col ) ) ) ) ) )";
$orderby = str_replace( $title_col, $ignore, $orderby );
return $orderby;
}

get_page_by_title in Wordpress. How to use to fetch posts?

Recently, Wordpress added in the Trac that you can fetch posts by title using:
get_page_by_title
Instead of querying the database straight up. If I wanted to get post titled "my farm", how would I change the parameters so it is searching for a post (or a post type?):
$page_title='Joey in the forest';
'character' is a post type. But don't know how to work this. I assume the default return is the id, which would be $post->ID. Not sure what would be the equivalent if I use a post type.
Thanks for anyone's help on this
I wrote a function (linked in the bug report) which does exactly that:
/**
* Retrieves a post/page/custom-type/taxonomy ID by its title.
*
* Returns only the first result. If you search for a post title
* that you have used more than once, restrict the type.
* Or don’t use this function. :)
* Simple usage:
* $page_start_id = id_by_title('Start');
*
* To get the ID of a taxonomy (category, tag, custom) set $tax
* to the name of this taxonomy.
* Example:
* $cat_css_id = id_by_title('CSS', 0, 'category');
*
* The result is cached internally to save db queries.
*
* #param string $title
* #param string $type Restrict the post type.
* #param string|bool $tax Taxonomy to search for.
* #return int ID or -1 on failure
*/
function id_by_title($title, $type = 'any', $tax = FALSE)
{
static $cache = array ();
$title = mysql_real_escape_string( trim($title, '"\'') );
// Unique index for the cache.
$index = "$title-$type-" . ( $tax ? $tax : 0 );
if ( isset ( $cache[$index] ) )
{
return $cache[$index];
}
if ( $tax )
{
$taxonomy = get_term_by('name', $title, $tax);
$cache[$index] = $taxonomy ? $taxonomy->term_id : -1;
return $cache[$index];
}
$type_sql = 'any' == $type
? ''
: "AND post_type = '"
. mysql_real_escape_string($type) . "'";
global $wpdb;
$query = "SELECT ID FROM $wpdb->posts
WHERE (
post_status = 'publish'
AND post_title = '$title'
$type_sql
)
LIMIT 1";
$result = $wpdb->get_results($query);
$cache[$index] = empty ( $result ) ? -1 : (int) $result[0]->ID;
return $cache[$index];
}
Since I hit upon this page, others might as well.
get_page_by_title() also handles Posts and custom post types.
Please be aware that it gets the first post/page item in the database even if the post is trashed.
Sample:
$post = get_page_by_title('sample-post','post');
echo $post->ID

wordpress num rows, how?

I'm creating a plugin for wordpress and I need to check if a post with a specific title exist or not. This to prevent duplicates, how can I query this and see if it returned true or false?
I’m using this code to get the ID of a post/page by title:
function get_id_by_name($name)
{
global $wpdb;
$id = $wpdb->get_col(
"SELECT ID FROM $wpdb->posts
WHERE post_status = 'publish'
AND post_title = '$name'
LIMIT 1");
return empty ( $id ) ? -1: (int) $id[0];
}
If the post doesn’t exists, the function return -1.

Resources