gocodebox/lifterlms

View on GitHub
includes/functions/llms.functions.certificate.php

Summary

Maintainability
A
3 hrs
Test Coverage
A
98%
<?php
/**
 * LifterLMS Certificate Functions
 *
 * @package LifterLMS/Functions
 *
 * @since 2.2.0
 * @version 6.11.0
 */

defined( 'ABSPATH' ) || exit;

/**
 * Retrieve the LLMS_User_Certificate instance for a given post.
 *
 * Expects the input post to be either an `llms_my_certificate` post. An `llms_certificate` post can be used
 * when `$preview_template` is `true`.
 *
 * @since 6.0.0
 *
 * @param WP_Post|int|null $post             A WP_Post object or a WP_Post ID. A falsy value will use the current global `$post` object (if one exists).
 * @param boolean          $preview_template If `true`, allows loading an `llms_certificate` post type for previewing the template.
 * @return LLMS_User_Certificate|boolean Returns the LLMS_User_Certificate object for the given post. Returns `false` if the post doesn't exist or is
 *                                       not of the expected post type.
 */
function llms_get_certificate( $post = null, $preview_template = false ) {

    $post = get_post( $post );
    if ( ! $post ) {
        return false;
    }

    if ( 'llms_my_certificate' === $post->post_type || ( 'llms_certificate' === $post->post_type && $preview_template ) ) {
        return new LLMS_User_Certificate( $post );
    }

    return false;

}

/**
 * Retrieve the content of a certificate.
 *
 * This allows utilizing the `LLMS_User_Certificate` class with an `llms_certificate` post type to render a preview
 * of the certificate template. The saved `post_content` will be merged (using the current user's information).
 *
 * This function is intended for use on the certificate's front-end display template. In order to retrieve the
 * raw content use `LLMS_User_Certificate->get( 'content' )` or `WP_Post->post_content`.
 *
 * @since 2.2.0
 * @since 3.18.0 Unknown.
 * @since 6.0.0 Use `llms_get_certificate()` and `LLMS_User_Certificate` methods.
 *                If this function is used out of the intended certificate context this will now
 *                return an empty string, whereas previously it returned the content of the post.
 * @since 6.4.0 Fixed issue with merge codes in reusable blocks by merging *after* filtering the post content.
 *
 * @param integer $id WP Post ID of the cert (optional if used within a loop).
 * @return string
 */
function llms_get_certificate_content( $id = 0 ) {

    $content = '';

    $certificate = llms_get_certificate( $id, true );
    if ( $certificate ) {

        // If `$id` was empty to use the global, ensure an id is available in filter on the return.
        $id = $certificate->get( 'id' );

        // Get raw content because we filter it again below.
        $content = $certificate->get( 'content', true );
    }

    /** WordPress core filter documented at {@link https://developer.wordpress.org/reference/hooks/the_content/}. */
    $content = apply_filters( 'the_content', $content );

    // Get merged content for templates.
    if ( 'llms_certificate' === get_post_type( $id ) ) {
        $content = $certificate->merge_content( $content );
    }

    /**
     * Filter the `post_content` of a certificate or certificate template.
     *
     * @since Unknown
     * @since 6.0.0 Added the `$certificate` parameter.
     *
     * @param string                     $content     The certificate content.
     * @param int                        $id          The ID of the certificate.
     * @param bool|LLMS_User_Certificate $certificate Certificate object or `false` if the post couldn't be found.
     */
    return apply_filters( 'lifterlms_certificate_content', $content, $id, $certificate );

}

/**
 * Retrieves a list of fonts available for use in certificates.
 *
 * @since 6.0.0
 * @since 6.11.0 Added internal call for certificate fonts, with external option enabled.
 *
 * @return array[] {
 *     Array of font definition arrays. The array key is the font's unique id.
 *
 *     @type string      $name The human-readable name of the font.
 *     @type string|null $href The href used to load the font or `null` for system or default fonts.
 *     @type string|null $css  The CSS `font-family` rule value.
 * }
 */
function llms_get_certificate_fonts() {
    /**
     * Determines whether or not webfonts are loaded from Google CDNs.
     *
     * @since 6.11.0
     *
     * @param bool $use_g_fonts If `true`, fonts are loaded from Google, otherwise they are loaded from the local site.
     */
    $use_g_fonts = apply_filters( 'llms_use_google_webfonts', false );
    $serif       = '"Iowan Old Style", "Apple Garamond", Baskerville, "Times New Roman", "Droid Serif", Times, "Source Serif Pro", serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"';

    $fonts = array(

        // Default fonts.
        'sans'                => array(
            'name'       => __( 'Sans-serif', 'lifterlms' ),
            'href'       => null,
            // From https://systemfontstack.com.
            'fontFamily' => '-apple-system, BlinkMacSystemFont, "avenir next", avenir, "segoe ui", "helvetica neue", helvetica, Ubuntu, roboto, noto, arial, sans-serif',
        ),
        'serif'               => array(
            'name'       => __( 'Serif', 'lifterlms' ),
            'href'       => null,
            // From https://systemfontstack.com.
            'fontFamily' => $serif,
        ),

        // Newspaper-style display fonts.
        'pirata-one'          => array(
            'name'       => 'Pirata One',
            'href'       => $use_g_fonts ? 'https://fonts.googleapis.com/css2?family=Pirata+One&display=swap' : LLMS_PLUGIN_URL . 'assets/css/pirata-one.css?ver=v22',
            'fontFamily' => '"Pirata One", ' . $serif,
        ),
        'unifraktur-maguntia' => array(
            'name'       => 'UnifrakturMaguntia',
            'href'       => $use_g_fonts ? 'https://fonts.googleapis.com/css2?family=UnifrakturMaguntia&display=swap' : LLMS_PLUGIN_URL . 'assets/css/unifraktur-maguntia.css?ver=v16',
            'fontFamily' => '"UnifrakturMaguntia", ' . $serif,
        ),

        // Cursive-style handwriting fonts.
        'dancing-script'      => array(
            'name'       => 'Dancing Script',
            'href'       => $use_g_fonts ? 'https://fonts.googleapis.com/css2?family=Dancing+Script&display=swap' : LLMS_PLUGIN_URL . 'assets/css/dancing-script.css?ver=v24',
            'fontFamily' => '"Dancing Script", ' . $serif,
        ),
        'imperial-script'     => array(
            'name'       => 'Imperial Script',
            'href'       => $use_g_fonts ? 'https://fonts.googleapis.com/css2?family=Imperial+Script&display=swap' : LLMS_PLUGIN_URL . 'assets/css/imperial-script.css?ver=v24',
            'fontFamily' => '"Imperial Script", ' . $serif,
        ),

    );

    /**
     * Filters the list of fonts available to certificates.
     *
     * @since 6.0.0
     *
     * @param array[] $fonts Array of font definitions, {@see llms_get_certificate_fonts()}.
     */

    return apply_filters( 'llms_certificate_fonts', $fonts );

}

/**
 * Retrieve an array of image data for a certificate background image
 *
 * If no image found, will default to the LifterLMS placeholder (which can be filtered for a custom placeholder).
 *
 * @since 2.2.0
 * @since 6.0.0 Use `LLMS_User_Certificate::get_background_image()`.
 *
 * @param int $id Optional. WP Certificate Post ID. Default is 0.
 *                When not provide the current post id will be used.
 * @return array Associative array of certificate image details
 */
function llms_get_certificate_image( $id = 0 ) {

    $id   = ( $id ) ? $id : get_the_ID();
    $cert = new LLMS_User_Certificate( $id );
    return $cert->get_background_image();

}

/**
 * Retrieve a list of merge codes that can be used in certificate templates.
 *
 * @since 6.0.0
 * @since 6.1.0 Changed `{current_date}` label from 'Earned Date' to 'Current Date' and added `{earned_date}` merge code.
 *
 * @return string[] Associative array of merge codes where the array key is the merge code and the array value is a name / description of the merge code.
 */
function llms_get_certificate_merge_codes() {

    return array(
        '{site_title}'     => __( 'Site Title', 'lifterlms' ),
        '{site_url}'       => __( 'Site URL', 'lifterlms' ),
        '{current_date}'   => __( 'Current Date', 'lifterlms' ),
        '{earned_date}'    => __( 'Earned Date', 'lifterlms' ),
        '{first_name}'     => __( 'Student First Name', 'lifterlms' ),
        '{last_name}'      => __( 'Student Last Name', 'lifterlms' ),
        '{email_address}'  => __( 'Student Email', 'lifterlms' ),
        '{student_id}'     => __( 'Student User ID', 'lifterlms' ),
        '{user_login}'     => __( 'Student Username', 'lifterlms' ),
        '{certificate_id}' => __( 'Certificate ID', 'lifterlms' ),
        '{sequential_id}'  => __( 'Sequential Certificate ID', 'lifterlms' ),
    );

}

/**
 * Retrieves registered certificate orientations.
 *
 * @since 6.0.0
 *
 * @return array Key value array where the array key is the orientation ID and the value is the
 *               translated name of the orientation.
 */
function llms_get_certificate_orientations() {

    $orientations = array(
        'portrait'  => __( 'Portrait', 'lifterlms' ),
        'landscape' => __( 'Landscape', 'lifterlms' ),
    );

    /**
     * Filters the list of available certificate orientations.
     *
     * @since 6.0.0
     *
     * @param array $orientations Array of orientations.
     */
    return apply_filters( 'llms_certificate_orientations', $orientations );

}

/**
 * Retrieve the next sequential ID for a given certificate template and optionally increment it.
 *
 * If there's no existing ID, a default ID of 1 will be used. This can be customized using the filter `llms_certificate_sequential_id_starting_number`.
 *
 * When an increment is requested, the new incremented ID will be automatically persisted to the database.
 *
 * @since 6.0.0
 *
 * @param integer $template_id WP_Post ID of the certificate template (`llms_certificate`) post.
 * @param boolean $increment   Whether or not to increment the current ID.
 * @return int
 */
function llms_get_certificate_sequential_id( $template_id, $increment = false ) {

    $key    = '_llms_sequential_id';
    $update = $increment;
    $id     = absint( get_post_meta( $template_id, $key, true ) );

    // No id, get the initial ID.
    if ( ! $id ) {

        /**
         * Determines the default starting number for the a certificate's sequential ID.
         *
         * The returned number *must* be an absolute integer (zero included). The returned value will be
         * passed through `absint()` to sanitize the filtered value.
         *
         * @since 6.0.0
         *
         * @param int $starting_id The starting number.
         * @param int $template_id WP_Post ID of the certificate template.
         */
        $starting_id = apply_filters( 'llms_certificate_sequential_id_starting_number', 1, $template_id );
        $id          = absint( $starting_id );
        $update      = true;

    }

    if ( $update ) {
        update_post_meta( $template_id, $key, $increment ? $id + 1 : $id );
    }

    /**
     * Filters the sequential ID number for a given certificate template.
     *
     * The returned number *must* be an absolute integer. The returned value will be
     * passed through `absint()` to sanitize the filtered value.
     *
     * @since 6.0.0
     *
     * @param int $id          The sequential ID.
     * @param int $template_id WP_Post ID of the certificate template.
     */
    return absint( apply_filters( 'llms_certificate_sequential_id', $id, $template_id ) );

}

/**
 * Retrieves a list of registered certificate sizes.
 *
 * @since 6.0.0
 *
 * @return {
 *     Array of sizes. The array key is the size's unique ID.
 *
 *     @type string $name   The translated name for the size.
 *     @type float  $width  The portrait width dimension of the size.
 *     @type float  $height The portrait height dimension of the size.
 *     @type string $unit   The unit used for the dimensions of the size. Must be the ID of a unit registered via {@see llms_get_certificate_units()}.
 * }
 */
function llms_get_certificate_sizes() {

    $sizes = array(
        // ISO 216 sizes.
        'A3'           => array(
            'name'   => _x( 'A3', 'Paper size name', 'lifterlms' ),
            'width'  => 297,
            'height' => 420,
            'unit'   => 'mm',
        ),
        'A4'           => array(
            'name'   => _x( 'A4', 'Paper size name', 'lifterlms' ),
            'width'  => 210,
            'height' => 297,
            'unit'   => 'mm',
        ),
        'A5'           => array(
            'name'   => _x( 'A5', 'Paper size name', 'lifterlms' ),
            'width'  => 148,
            'height' => 210,
            'unit'   => 'mm',
        ),
        // North American sizes.
        'LETTER'       => array(
            'name'   => _x( 'Letter', 'Paper size name', 'lifterlms' ),
            'width'  => 8.5,
            'height' => 11,
            'unit'   => 'in',
        ),
        'LEGAL'        => array(
            'name'   => _x( 'Legal', 'Paper size name', 'lifterlms' ),
            'width'  => 8.5,
            'height' => 14,
            'unit'   => 'in',
        ),
        'LEDGER'       => array(
            'name'   => _x( 'Ledger', 'Paper size name', 'lifterlms' ),
            'width'  => 11,
            'height' => 17,
            'unit'   => 'in',
        ),
        'USER_DEFINED' => array(
            'name'   => __( 'User defined', 'lifterlms' ),
            'width'  => get_option( 'lifterlms_certificate_default_user_defined_width', 400 ),
            'height' => get_option( 'lifterlms_certificate_default_user_defined_height', 400 ),
            'unit'   => get_option( 'lifterlms_certificate_default_user_defined_unit', 'mm' ),
        ),
    );

    /**
     * Filters registered certificate size options.
     *
     * @since 6.0.0
     *
     * @param array $sizes Array of registered sizes.
     */
    return apply_filters( 'llms_certificate_sizes', $sizes );

}

/**
 * Retrieves units available for certificate dimensions.
 *
 * @since 6.0.0
 *
 * @link https://developer.mozilla.org/en-US/docs/Web/CSS/length
 *
 * @return {
 *     Array of unit information. The array key is the unit ID, which should be a valid absolute length CSS unit.
 *
 *     @type string $name   Translated name of the unit.
 *     @type string $symbol Translated symbol used when displaying dimensions with the unit.
.* }
 */
function llms_get_certificate_units() {

    $units = array(
        'in' => array(
            'name'   => __( 'Inches', 'lifterlms' ),
            'symbol' => _x( '"', 'Symbol for inches', 'lifterlms' ),
        ),
        'mm' => array(
            'name'   => __( 'Millimeters', 'lifterlms' ),
            'symbol' => _x( 'mm', 'Symbol for millimeters', 'lifterlms' ),
        ),
    );

    /**
     * Filters the list of certificate dimension units.
     *
     * @since 6.0.0
     *
     * @param array $units Array of available units.
     */
    return apply_filters( 'llms_certificate_units', $units );

}

/**
 * Retrieve the title of a certificate
 *
 * This function is intended for use on the certificate's front-end display template.
 *
 * @since 2.2.0
 * @since 6.0.0 Use `LLMS_User_Certificate()` to retrieve the title for earned certificates.
 *
 * @param int $id WP Certificate Post ID. When not provide the current post id will be used.
 * @return string The title of the certificate.
 */
function llms_get_certificate_title( $id = 0 ) {

    $id          = $id ? $id : get_the_ID();
    $title       = '';
    $certificate = llms_get_certificate( $id, false );
    if ( $certificate ) {
        $title = $certificate->get( 'title' );
    } elseif ( 'llms_certificate' === get_post_type( $id ) ) {
        $title = get_post_meta( $id, '_llms_certificate_title', true );
    }

    /**
     * Filter the title of a certificate or certificate template.
     *
     * @since Unknown
     * @since 6.0.0 Added the `$certificate` parameter.
     *
     * @param string $title The certificate title.
     * @param int    $id    The ID of the certificate.
     */
    return apply_filters( 'lifterlms_certificate_title', $title, $id );

}

/**
 * Determines whether or not the block editor can be used to build certificates.
 *
 * The JS used for certificates in the block editor relies on WP functions and APIs available
 * since WordPress 5.8. Earlier versions of WordPress won't work.
 *
 * @since 6.0.0
 *
 * @return boolean
 */
function llms_is_block_editor_supported_for_certificates() {

    global $wp_version;
    $is_supported = version_compare( $wp_version, '5.8-src', '>=' );

    /**
     * Filters whether or not the block editor can be used for building certificates.
     *
     * By default, `$is_supported` will be `true` for WordPress 5.8 or later and false for versions less than
     * 5.8.
     *
     * This filter may be used to disable the block editor on later versions.
     *
     * @since 6.0.0
     *
     * @param boolean $is_supported Whether or not the block editor is supported.
     */
    return apply_filters( 'llms_block_editor_supported_for_certificates', $is_supported );

}

/**
 * Register the custom "print_certificate" image size
 *
 * @since 2.2.0
 *
 * @return void
 */
function llms_register_certificate_image_size() {

    $width  = get_option( 'lifterlms_certificate_bg_img_width', '800' );
    $height = get_option( 'lifterlms_certificate_bg_img_height', '616' );

    add_image_size( 'lifterlms_certificate_background', $width, $height, true );

}
add_action( 'after_setup_theme', 'llms_register_certificate_image_size' );