| Current Path : /home/ereika83/public_html/wp-content/plugins/learndash-course-grid/includes/ |
| Current File : /home/ereika83/public_html/wp-content/plugins/learndash-course-grid/includes/class-utilities.php |
<?php
/**
* Utilities class.
*
* @since 2.0.0
*
* @package LearnDash\Course_Grid
*/
namespace LearnDash\Course_Grid;
if ( ! defined( 'ABSPATH' ) ) {
exit();
}
/**
* Class Utilities.
*/
class Utilities
{
/**
* Gets a template path based on the provided file name.
*
* @since 2.0.0
*
* @param string $template Template file name, without extension.
*
* @return string|false Template path if found, false if not.
*/
public static function get_template( $template )
{
$template_file = $template . '.php';
$template = locate_template( 'learndash/course-grid/' . $template_file );
$template_in_allowed_directory = (
( is_string( realpath( $template ) ) && is_string( realpath( STYLESHEETPATH ) ) && 0 === strpos( realpath( $template ), realpath( STYLESHEETPATH ) ) )
|| ( is_string( realpath( $template ) ) && is_string( realpath( TEMPLATEPATH ) ) && 0 === strpos( realpath( $template ), realpath( TEMPLATEPATH ) ) )
|| ( is_string( realpath( $template ) ) && is_string( ABSPATH . WPINC . '/theme-compat/' ) && 0 === strpos( realpath( $template ), ABSPATH . WPINC . '/theme-compat/' ) )
);
if ( $template && $template_in_allowed_directory ) {
return $template;
} elseif ( file_exists( LEARNDASH_COURSE_GRID_PLUGIN_TEMPLATE_PATH . $template_file ) ) {
return LEARNDASH_COURSE_GRID_PLUGIN_TEMPLATE_PATH . $template_file;
} else {
return false;
}
}
public static function get_template_url( $template_file )
{
$template = locate_template( 'learndash/course-grid/' . $template_file );
$template_in_allowed_directory = (
( is_string( realpath( $template ) ) && is_string( realpath( STYLESHEETPATH ) ) && 0 === strpos( realpath( $template ), realpath( STYLESHEETPATH ) ) )
|| ( is_string( realpath( $template ) ) && is_string( realpath( TEMPLATEPATH ) ) && 0 === strpos( realpath( $template ), realpath( TEMPLATEPATH ) ) )
|| ( is_string( realpath( $template ) ) && is_string( ABSPATH . WPINC . '/theme-compat/' ) && 0 === strpos( realpath( $template ), ABSPATH . WPINC . '/theme-compat/' ) )
);
if ( $template && $template_in_allowed_directory ) {
return get_stylesheet_directory_uri() . '/learndash/course-grid/' . $template_file;
} elseif ( file_exists( LEARNDASH_COURSE_GRID_PLUGIN_TEMPLATE_PATH . $template_file ) ) {
return LEARNDASH_COURSE_GRID_PLUGIN_TEMPLATE_URL . $template_file;
} else {
return false;
}
}
public static function get_pagination_template( $type )
{
return self::get_template( 'pagination/' . $type );
}
public static function get_pagination_style()
{
return self::get_template_url( 'pagination/style.css' );
}
public static function get_pagination_script()
{
return self::get_template_url( 'pagination/script.js' );
}
public static function get_skin_layout( $skin )
{
return self::get_template( 'skins/' . $skin . '/layout' );
}
public static function get_skin_item( $skin )
{
return self::get_template( 'skins/' . $skin . '/item' );
}
public static function get_card_layout( $card )
{
return self::get_template( 'cards/' . $card . '/layout' );
}
public static function get_skin_style( $skin )
{
return self::get_template_url( 'skins/' . $skin . '/style.css' );
}
public static function get_skin_script( $skin )
{
return self::get_template_url( 'skins/' . $skin . '/script.js' );
}
public static function get_card_style( $card )
{
return self::get_template_url( 'cards/' . $card . '/style.css' );
}
public static function get_card_script( $card )
{
return self::get_template_url( 'cards/' . $card . '/script.js' );
}
/**
* Parses a textual representation of taxonomies and their terms. Used by Shortcode Attributes.
*
* @since 2.0.5
*
* @param string $taxonomies Taxonomy data separated by semicolons, with the taxonomy name followed by a colon and terms separated by commas. Example: taxonomy1:term1,term2;taxonomy2:term3,term4.
*
* @return array<string,array{terms: array<string>} Parsed taxonomy data.
*/
public static function parse_taxonomies( $taxonomies )
{
$taxonomies = ! empty( $taxonomies ) ? array_filter( explode( ';', sanitize_text_field( $taxonomies ) ) ) : [];
$results = [];
foreach ( $taxonomies as $taxonomy_entry ) {
$taxonomy_parts = explode( ':', $taxonomy_entry );
if ( empty( $taxonomy_parts[0] ) || empty( $taxonomy_parts[1] ) ) {
continue;
}
$taxonomy = trim( $taxonomy_parts[0] );
$terms = array_map( 'trim', explode( ',', $taxonomy_parts[1] ) );
if ( ! empty( $taxonomy ) && ! empty( $terms ) ) {
$results[ $taxonomy ] = [
'terms' => $terms,
];
}
}
return $results;
}
/**
* Build Post Query Args to use based on the provided Args.
*
* @since 2.0.5
*
* @param array<string,mixed> $atts Post Query Args to start with.
*
* @return array<string,mixed> Modified Post Query Args.
*/
public static function build_posts_query_args( $atts = [] )
{
if ( empty( $atts['per_page'] ) ) {
$atts['per_page'] = -1;
}
$tax_query = [];
$taxonomies = ! empty( $atts['taxonomies'] ) ? array_filter( explode( ';', sanitize_text_field( str_replace( '"', '', wp_unslash( $atts['taxonomies'] ) ) ) ) ) : [];
foreach ( $taxonomies as $taxonomy_entry ) {
$taxonomy_parts = explode( ':', $taxonomy_entry );
if ( empty( $taxonomy_parts[0] ) || empty( $taxonomy_parts[1] ) ) {
continue;
}
$taxonomy = trim( $taxonomy_parts[0] );
$terms = array_map( 'trim', explode( ',', $taxonomy_parts[1] ) );
if ( ! empty( $taxonomy ) && ! empty( $terms ) ) {
$tax_query[] = [
'taxonomy' => $taxonomy,
'field' => 'slug',
'terms' => $terms,
];
}
}
$tax_query['relation'] = 'OR';
$post__in = null;
if ( in_array( $atts['post_type'], [ 'sfwd-courses', 'groups' ] ) ) {
$user_id = get_current_user_id();
if ( isset( $atts['enrollment_status'] ) && $atts['enrollment_status'] == 'enrolled' ) {
$courses = learndash_user_get_enrolled_courses( $user_id );
$group_ids = learndash_get_users_group_ids( $user_id );
$groups_courses = learndash_get_groups_courses_ids( $user_id, $group_ids );
$course_ids = array_merge( $courses, $groups_courses );
if ( $atts['post_type'] == 'sfwd-courses' ) {
$post_ids = $course_ids;
if ( isset( $atts['progress_status'] ) && ! empty( $atts['progress_status'] ) ) {
$progress_status = [ strtoupper( $atts['progress_status'] ) ];
$activity_query_args = [
'post_types' => 'sfwd-courses',
'activity_types' => 'course',
'activity_status' => $progress_status,
'orderby_order' => 'users.ID, posts.post_title',
'date_format' => 'F j, Y H:i:s',
'per_page' => '',
];
$activity_query_args['user_ids'] = [ $user_id ];
$activity_query_args['post_ids'] = $post_ids;
$user_courses_reports = learndash_reports_get_activity( $activity_query_args );
$user_courses_ids = [];
if ( ! empty( $user_courses_reports['results'] ) ) {
foreach ( $user_courses_reports['results'] as $result ) {
if ( in_array( 'COMPLETED', $progress_status, true ) ) {
if ( ! empty( $result->activity_completed ) ) {
$user_courses_ids[] = absint( $result->post_id );
}
}
if ( in_array( 'IN_PROGRESS', $progress_status, true ) ) {
if ( ( ! empty( $result->activity_started ) ) && ( empty( $result->activity_completed ) ) ) {
$user_courses_ids[] = absint( $result->post_id );
}
}
if ( in_array( 'NOT_STARTED', $progress_status, true ) ) {
if ( empty( $result->activity_started ) ) {
$user_courses_ids[] = absint( $result->post_id );
}
}
}
$post_ids = $user_courses_ids;
} else {
// It means course with such progress status doesn't exist,
// we return empty array
$post_ids = [];
}
}
} elseif ( $atts['post_type'] == 'groups' ) {
$post_ids = $group_ids;
}
if ( empty( $post_ids ) ) {
// Add literal 0 in an array because post__in param
// ignores empty array
$post_ids = [ 0 ];
}
} elseif ( isset( $atts['enrollment_status'] ) && $atts['enrollment_status'] == 'not-enrolled' ) {
$price_types = [ 'open', 'free', 'paynow', 'subscribe', 'closed' ];
$all_posts = [];
foreach ( $price_types as $price_type ) {
$post_ids_by_price_type = learndash_get_posts_by_price_type( $atts['post_type'], $price_type );
$all_posts = array_merge( $all_posts, $post_ids_by_price_type );
}
$courses = learndash_user_get_enrolled_courses( $user_id );
$group_ids = learndash_get_users_group_ids( $user_id );
$groups_courses = learndash_get_groups_courses_ids( $user_id, $group_ids );
$course_ids = array_merge( $courses, $groups_courses );
if ( $atts['post_type'] == 'sfwd-courses' ) {
$post_ids = array_diff( $all_posts, $course_ids );
} elseif ( $atts['post_type'] == 'groups' ) {
$post_ids = array_diff( $all_posts, $group_ids );
}
} elseif ( empty( $atts['enrollment_status'] ) ) {
$price_types = [
LEARNDASH_PRICE_TYPE_OPEN,
LEARNDASH_PRICE_TYPE_FREE,
LEARNDASH_PRICE_TYPE_PAYNOW,
LEARNDASH_PRICE_TYPE_SUBSCRIBE,
LEARNDASH_PRICE_TYPE_CLOSED,
];
$all_posts = [];
foreach ( $price_types as $price_type ) {
$all_posts = array_merge(
$all_posts,
learndash_get_posts_by_price_type(
$atts['post_type'],
$price_type
)
);
}
$post_ids = $all_posts;
}
// Add literal 0 in an array because post__in param ignores empty array.
// TODO: Write test to check if it works with all enrollment statuses argument and without it.
$post__in = ! empty( $post_ids ) ? $post_ids : [ 0 ];
}
$query_args = apply_filters( 'learndash_course_grid_query_args', [
'post_type' => sanitize_text_field( $atts['post_type'] ),
'posts_per_page' => intval( $atts['per_page'] ),
'post_status' => 'publish',
'orderby' => sanitize_text_field( $atts['orderby'] ),
'order' => sanitize_text_field( $atts['order'] ),
'tax_query' => $tax_query,
'post__in' => $post__in,
], $atts, $filter = null );
return $query_args;
}
public static function get_post_types()
{
$post_types = get_post_types( [
'public' => true,
], 'objects' );
$excluded_post_types = self::get_excluded_post_types();
$returned_post_types = [];
foreach ( $post_types as $slug => $post_type ) {
if ( in_array( $slug, $excluded_post_types ) ) {
continue;
}
$returned_post_types[ $slug ] = $post_type;
}
return apply_filters( 'learndash_course_grid_post_types', $returned_post_types );
}
public static function get_post_types_slugs()
{
$post_types = self::get_post_types();
$temp_post_types = [];
foreach ( $post_types as $slug => $post_type ) {
$temp_post_types[] = $slug;
}
$post_types = $temp_post_types;
return $post_types;
}
public static function get_post_types_for_block_editor()
{
$post_types = self::get_post_types();
$returned_post_types = [];
foreach ( $post_types as $slug => $post_type ) {
$returned_post_types[] = [
'label' => $post_type->label,
'value' => $slug,
];
}
return apply_filters( 'learndash_course_grid_block_editor_post_types', $returned_post_types );
}
/**
* Get a list of excluded Post Types for queries.
*
* @since 2.0.0
*
* @return array<string>
*/
public static function get_excluded_post_types()
{
/**
* Filters the list of excluded Post Types for queries.
*
* @since 2.0.0
*
* @param array<string>
*/
return apply_filters(
'learndash_course_grid_excluded_post_types',
[
'sfwd-transactions',
'sfwd-essays',
'sfwd-assignment',
'sfwd-certificates',
'attachment',
]
);
}
public static function get_image_sizes_for_block_editor()
{
$sizes = get_intermediate_image_sizes();
$image_sizes = [];
foreach ( $sizes as $size ) {
$image_sizes[] = [
'label' => $size,
'value' => $size,
];
}
return apply_filters( 'learndash_course_grid_block_editor_image_sizes', $image_sizes );
}
public static function get_orderby_for_block_editor()
{
$orderby = [
[
'label' => __( 'ID', 'learndash-course-grid' ),
'value' => 'ID',
],
[
'label' => __( 'Title', 'learndash-course-grid' ),
'value' => 'title',
],
[
'label' => __( 'Published Date', 'learndash-course-grid' ),
'value' => 'date',
],
[
'label' => __( 'Modified Date', 'learndash-course-grid' ),
'value' => 'modified',
],
[
'label' => __( 'Author', 'learndash-course-grid' ),
'value' => 'author',
],
[
'label' => __( 'Menu Order', 'learndash-course-grid' ),
'value' => 'menu_order',
],
];
return apply_filters( 'learndash_course_grid_block_editor_orderby', $orderby );
}
public static function get_taxonomies_for_block_editor()
{
$taxonomies = get_taxonomies( [ 'public' => true ], 'objects' );
$return = [];
foreach ( $taxonomies as $tax ) {
$return[] = [
'label' => $tax->label,
'value' => $tax->name,
];
}
return apply_filters( 'learndash_course_grid_block_editor_taxonomies', $return );
}
public static function get_paginations_for_block_editor()
{
return apply_filters( 'learndash_course_grid_block_editor_paginations', [
[
'label' => __( 'Load More Button', 'learndash-course-grid' ),
'value' => 'button',
],
[
'label' => __( 'Infinite Scrolling', 'learndash-course-grid' ),
'value' => 'infinite',
],
[
'label' => __( 'Disable', 'learndash-course-grid' ),
'value' => 'false',
],
] );
}
public static function generate_random_id()
{
return substr( uniqid( 'ld-cg-' ) , 0, 16 );
}
/**
* Retrieves the amount of time it takes for the course to be completed.
*
* @since 2.0.0
*
* @param int $post_id Post ID that the Course Grid saved on.
* @param string $format Format to display the time in. Defaults to "plain", which just outputs the saved value. "output" will format it as something like "1 hour 30 minutes".
*
* @return string Formatted duration.
*/
public static function get_duration( $post_id, $format = 'plain' )
{
$duration = get_post_meta( $post_id, '_learndash_course_grid_duration', true );
if ( ! empty( $duration ) && is_numeric( $duration ) ) {
switch ( $format ) {
case 'plain':
$duration = $duration;
break;
case 'output':
$duration_h = is_numeric( $duration ) ? floor( $duration / HOUR_IN_SECONDS ) : null;
$duration_m = is_numeric( $duration ) ? floor( ( $duration % HOUR_IN_SECONDS ) / MINUTE_IN_SECONDS ) : null;
$duration = sprintf( _x( '%d h %d min', 'Duration, e.g. 1 hour 30 minutes', 'learndash-course-grid' ), $duration_h, $duration_m );
break;
default:
$duration = false;
break;
}
}
return $duration;
}
/**
* Formats the displayed price for a Course.
*
* @since 2.0.5
*
* @param string $price Input price.
* @param string $format How to format the price. Defaults to "plain", which does nothing. "output" will format it as currency.
*
* @return string Formatted price.
*/
public static function format_price( $price, $format = 'plain' )
{
if ( $format == 'output' ) {
preg_match( '/(((\d+)[,\.]?)*(\d+)([\.,]?\d+)?)/', $price, $matches );
$price = $matches[1];
if ( ! empty( $price ) ) {
$match_comma_decimal = preg_match( '/(?:\d+\.?)*\d+(,\d{1,2})$/', $price, $comma_matches );
$match_dot_decimal = preg_match( '/(?:\d+,?)*\d+(\.\d{1,2})$/', $price, $dot_matches );
if ( $match_comma_decimal ) {
$has_decimal = ! empty( $comma_matches[1] ) ? true : false;
$thousands_separator = '.';
$decimal_separator = ',';
$price = str_replace( '.', '', $price );
$price = str_replace( ',', '.', $price );
} else {
$has_decimal = ! empty( $dot_matches[1] ) ? true : false;
$thousands_separator = ',';
$decimal_separator = '.';
$price = str_replace( ',', '', $price );
}
$price = floatval( $price );
if ( $has_decimal ) {
$price = number_format( $price, 2, $decimal_separator, $thousands_separator );
} else {
$price = number_format( $price, 0, $decimal_separator, $thousands_separator );
}
}
return $price;
}
return $price;
}
/**
* Helper method similar to checked() that also has the ability to set the given input element as disabled.
*
* @since 2.0.5
*
* @param mixed $checked Value being searched for.
* @param array<mixed> $data Value to search within.
* @param bool $disabled Whether to mark the found value as disabled after marking it as checked.
*
* @return void
*/
public static function checked_array( $checked, $data, $disabled = false )
{
$output = '';
if ( is_array( $data ) && in_array( $checked, $data ) ) {
$output .= 'checked="checked"';
if ( $disabled ) {
$output .= ' disabled="disabled"';
}
}
echo $output;
}
public static function associative_list_pluck( $list, $find_key, &$returned_list = [] )
{
foreach ( $list as $key => $value ) {
if ( $key === $find_key ) {
if ( is_array( $value ) ) {
foreach ( $value as $sub_key => $sub_value ) {
if ( isset( $sub_value[ $key ] ) ) {
unset( $sub_value[ $key ] );
}
array_push( $returned_list, $sub_value );
}
} else {
array_push( $returned_list, $value );
}
}
if ( is_array( $value ) ) {
$returned_list = self::associative_list_pluck( $value, $find_key, $returned_list );
}
}
return $returned_list;
}
}