gocodebox/lifterlms

View on GitHub
includes/admin/class.llms.admin.addons.php

Summary

Maintainability
B
6 hrs
Test Coverage
F
0%
<?php
/**
 * LifterLMS Add-On browser
 *
 * This is where the adds are, if you don't like it that's okay but i don't want to hear your complaints!
 *
 * @package LifterLMS/Admin/Classes
 *
 * @since 3.5.0
 * @version 7.1.0
 */

defined( 'ABSPATH' ) || exit;

/**
 * LLMS_Admin_AddOns class
 *
 * @since 3.5.0
 * @since 3.30.3 Explicitly define undefined properties.
 * @since 3.35.0 Sanitize input data.
 */
class LLMS_Admin_AddOns {

    /**
     * Data from `llms_get_add_ons()`.
     *
     * @var array
     * @since 3.5.0
     */
    public $data = array();

    /**
     * Retrieves the current section from the query string.
     *
     * @since 3.5.0
     * @since 3.22.0 Unknown.
     * @since 5.9.0 Stop using deprecated `FILTER_SANITIZE_STRING`.
     *
     * @return string
     */
    private function get_current_section() {

        $section = 'all';

        if ( isset( $_GET['page'] ) && 'llms-dashboard' === $_GET['page'] ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
            $section = 'featured';
        } elseif ( isset( $_GET['section'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
            $section = llms_filter_input_sanitize_string( INPUT_GET, 'section' );
        }

        return apply_filters( 'llms_admin_add_ons_get_current_section', $section );

    }

    /**
     * Retrieve addon data for the current section (tab) based off query string variables
     *
     * @return   array
     * @since    3.5.0
     * @version  3.22.0
     */
    private function get_current_section_content() {

        $sec = $this->get_current_section();

        $content = apply_filters( 'llms_admin_add_ons_get_current_section_default_content', array(), $sec );

        if ( ! $content ) {

            if ( 'all' === $sec ) {
                $content = $this->get_all();
            } elseif ( 'featured' === $sec ) {
                $content = $this->get_features();
            } else {
                $content = $this->get_products_for_cat( $sec );
            }
        }

        return apply_filters( 'llms_admin_add_ons_get_current_section_content', $content, $sec );
    }

    /**
     * Retrieve remote json data.
     *
     * @since 3.5.0
     * @since 3.22.2 Unknown.
     * @since 7.1.0 Use strict comparisons for `in_array()`.
     *
     * @return array|WP_Error
     */
    private function get_data() {

        $this->data = llms_get_add_ons();

        if ( ! is_wp_error( $this->data ) ) {
            foreach ( $this->data['items'] as $key => $addon ) {
                // Exclude the core plugin and helper plugin.
                if ( in_array( $addon['id'], array( 'lifterlms-com-lifterlms', 'lifterlms-com-lifterlms-helper' ), true ) ) {
                    unset( $this->data['items'][ $key ] );
                }

                // Exclude uncategorized Add-ons.
                if ( array_key_exists( 'uncategorized', $addon['categories'] ) ) {
                    unset( $this->data['items'][ $key ] );
                }
            }
        }

        return $this->data;

    }

    /**
     * Retrieve a list of addons for use on the All section
     *
     * @return   array
     * @since    7.5.0
     * @version  7.5.0
     */
    private function get_all() {

        $all = array();

        $addons = $this->data['items'];

        foreach ( $addons as $addon ) {
            // Exclude third-party Addons from the All section.
            if ( in_array( 'third-party', array_keys( $addon['categories'] ), true ) ) {
                    continue;
            }
            $all[] = $addon;
        }

        return $all;

    }

    /**
     * Retrieve a list of 'featured' addons for use on the general settings screen
     * Excludes already available products from current site's activations
     *
     * @return   array
     * @since    3.22.0
     * @version  3.22.0
     */
    private function get_features() {

        $features = array();

        // Addons to exclude.
        // Helper will filter this based on existing activations.
        $exclude = apply_filters( 'llms_admin_addon_features_exclude_ids', array() );

        $cats = array(
            'e-commerce',
            'bundles',
            'resources',
            'courses',
            'courses',
        );

        foreach ( $cats as $cat ) {
            $addon = $this->get_product_from_cat( $cat, $exclude );
            if ( $addon ) {
                $features[] = $addon;
                $exclude[]  = $addon['id'];
            }
            if ( 3 === count( $features ) ) {
                return $features;
            }
        }

        return $features;

    }

    /**
     * Get a random product from a category that doesn't exist in the list of excluded product ids.
     *
     * @since 3.22.0
     * @since 7.1.0 Use strict comparisons for `in_array()`.
     *
     * @param  string $cat      Category slug.
     * @param  array  $excludes List of product ids to exclude.
     * @return array|false
     */
    public function get_product_from_cat( $cat, $excludes ) {

        $addons = $this->get_products_for_cat( $cat, true );
        shuffle( $addons );

        foreach ( $addons as $addon ) {

            if ( in_array( 'third-party', array_keys( $addon['categories'] ), true ) ) {
                continue;
            }

            if ( ! in_array( $addon['id'], $excludes, true ) ) {
                return $addon;
            }
        }

        return false;

    }

    /**
     * Retrieve products for a specific category.
     *
     * @since 3.22.0
     * @since 7.1.0 Use strict comparisons for `in_array()`.
     *
     * @param string $cat Category slug.
     * @return array
     */
    private function get_products_for_cat( $cat, $include_bundles = true ) {

        $products = array();

        foreach ( $this->data['items'] as $item ) {

            $cats = array_keys( $item['categories'] );

            // Exclude bundles if bundles are not being included or requested.
            if ( 'bundles' !== $cat && ! $include_bundles && in_array( 'bundles', $cats, true ) ) {
                continue;
            }

            if ( in_array( $cat, $cats, true ) ) {
                $products[] = $item;
            }
        }

        return $products;

    }

    /**
     * Handle form submissions for managing license keys
     *
     * @return   void
     * @since    3.22.0
     * @version  3.22.0
     */
    public function handle_actions() {

        // Activate & deactivate addons.
        if ( llms_verify_nonce( '_llms_manage_addon_nonce', 'llms_manage_addon' ) ) {

            $this->handle_manage_addons();
            LLMS_Admin_Notices::output_notices();
        }

    }

    /**
     * Handle activation and deactivation of addons
     *
     * @since 3.22.0
     * @since 3.35.0 Sanitize input data.
     * @since 5.9.0 Stop using deprecated `FILTER_SANITIZE_STRING`.
     *
     * @return void
     */
    private function handle_manage_addons() {

        // phpcs:disable WordPress.Security.NonceVerification.Missing -- nonce is verified in $this->handle_actions() method.

        $actions = apply_filters(
            'llms_admin_add_ons_manage_actions',
            array(
                'activate',
                'deactivate',
            )
        );

        $errors  = array();
        $success = array();

        foreach ( $actions as $action ) {

            if ( empty( $_POST[ 'llms_' . $action ] ) ) {
                continue;
            }

            foreach ( llms_filter_input( INPUT_POST, 'llms_' . $action, FILTER_DEFAULT, FILTER_REQUIRE_ARRAY ) as $id ) {

                $addon = llms_get_add_on( $id );
                if ( ! method_exists( $addon, $action ) ) {
                    continue;
                }

                $ret = call_user_func( array( $addon, $action ) );
                if ( is_wp_error( $ret ) ) {
                    LLMS_Admin_Notices::flash_notice( $ret->get_error_message(), 'error' );
                } else {
                    LLMS_Admin_Notices::flash_notice( $ret );
                }
            }
        }

        // phpcs:enable WordPress.Security.NonceVerification.Missing

    }

    /**
     * Output HTML for the current screen
     *
     * @since 3.5.0
     * @since 3.28.0 Unknown.
     * @since 4.10.1 Use `hr.wp-header-end` in favor of a second (hidden) <h1> to "catch" admin notices.
     *
     * @return void
     */
    public function output() {

        if ( is_wp_error( $this->get_data() ) ) {
            _e( 'There was an error retrieving add-ons. Please try again.', 'lifterlms' );
            return;
        }
        ?>
        <div class="wrap lifterlms lifterlms-settings lifterlms-addons">

            <div class="llms-subheader">

                <h1><?php _e( 'LifterLMS Add-Ons, Courses, and Resources', 'lifterlms' ); ?></h1>
                <?php do_action( 'llms_addons_page_after_title' ); ?>

            </div>

            <div class="llms-inside-wrap">

                <?php $this->output_navigation(); ?>

                <hr class="wp-header-end">

                <form action="" method="POST">

                    <?php $this->output_content(); ?>

                    <?php wp_nonce_field( 'llms_manage_addon', '_llms_manage_addon_nonce' ); ?>

                    <div class="llms-addons-bulk-actions" id="llms-addons-bulk-actions">

                        <a class="llms-bulk-close" href="#">
                            <span class="screen-reader-text"><?php _e( 'Close', 'lifterlms' ); ?></span>
                            <i class="fa fa-times-circle" aria-hidden="true"></i>
                        </a>

                        <div class="llms-bulk-desc update">
                            <i class="fa fa-cloud-download" aria-hidden="true"></i>
                            <?php _e( 'Update', 'lifterlms' ); ?> <span></span>
                        </div>

                        <div class="llms-bulk-desc install">
                            <i class="fa fa-cloud-download" aria-hidden="true"></i>
                            <?php _e( 'Install', 'lifterlms' ); ?> <span></span>
                        </div>

                        <div class="llms-bulk-desc activate">
                            <i class="fa fa-plug" aria-hidden="true"></i>
                            <?php _e( 'Activate', 'lifterlms' ); ?> <span></span>
                        </div>

                        <div class="llms-bulk-desc deactivate">
                            <i class="fa fa-plug" aria-hidden="true"></i>
                            <?php _e( 'Deactivate', 'lifterlms' ); ?> <span></span>
                        </div>

                        <button class="llms-button-primary" name="llms_bulk_actions_submit" value="" type="submit"><?php _e( 'Apply', 'lifterlms' ); ?></button>

                    </div>

                </form>

            </div>

        </div>

        <?php
    }

    /**
     * Output HTML for a single addon
     *
     * @param    array $addon  associative array of add-on data
     * @return   void
     * @since    3.5.0
     * @version  3.22.0
     */
    private function output_addon( $addon ) {
        $current_tab = $this->get_current_section();
        include 'views/addons/addon-item.php';
    }

    /**
     * Output the addon list for the current section
     *
     * @return   void
     * @since    3.5.0
     * @version  3.22.0
     */
    private function output_content() {
        ?>
        <ul class="llms-addons-wrap section--<?php echo esc_attr( $this->get_current_section() ); ?>">

            <?php do_action( 'lifterlms_before_addons' ); ?>

            <?php
            foreach ( $this->get_current_section_content() as $addon ) {
                $addon = llms_get_add_on( $addon );
                $this->output_addon( $addon );
            }
            ?>

            <?php do_action( 'lifterlms_after_addons' ); ?>

        </ul>
        <?php
    }

    /**
     * Outputs most popular resources
     * used on general settings screen
     *
     * @return   void
     * @since    3.7.6
     * @version  3.7.6
     */
    public function output_for_settings() {

        if ( is_wp_error( $this->get_data() ) ) {

            _e( 'There was an error retrieving add-ons. Please try again.', 'lifterlms' );
            return;

        }
        $this->output_content();

    }

    /**
     * Output the navigation bar
     *
     * @return   void
     * @since    3.5.0
     * @version  3.22.0
     */
    private function output_navigation() {
        $curr_section = $this->get_current_section();
        ?>
        <nav class="llms-nav-tab-wrapper llms-nav-secondary">
            <ul class="llms-nav-items">
            <?php do_action( 'lifterlms_before_addons_nav', $curr_section ); ?>
                <?php
                foreach ( $this->data['categories'] as $name => $title ) :
                    $name   = sanitize_title( $name );
                    $title  = sanitize_text_field( $title );
                    $active = ( $this->get_current_section() === $name ) ? ' llms-active' : '';
                    ?>
                    <li class="llms-nav-item<?php echo $active; ?>"><a class="llms-nav-link" href="<?php echo esc_url( admin_url( 'admin.php?page=llms-add-ons&section=' . $name ) ); ?>"><?php echo $title; ?></a></li>
                <?php endforeach; ?>
                <li class="llms-nav-item<?php echo ( 'all' === $curr_section ) ? ' llms-active' : ''; ?>"><a class="llms-nav-link" href="<?php echo esc_url( admin_url( 'admin.php?page=llms-add-ons&section=all' ) ); ?>"><?php _e( 'All', 'lifterlms' ); ?></a></li>

            <?php do_action( 'lifterlms_after_addons_nav', $curr_section ); ?>
            </ul>
        </nav>
        <?php
    }

}