deep-web-solutions/wordpress-framework-utilities

View on GitHub
src/includes/Dependencies/Checkers/WPPluginsChecker.php

Summary

Maintainability
A
2 hrs
Test Coverage
<?php

namespace DeepWebSolutions\Framework\Utilities\Dependencies\Checkers;

use DeepWebSolutions\Framework\Helpers\DataTypes\Arrays;
use DeepWebSolutions\Framework\Helpers\DataTypes\Booleans;
use DeepWebSolutions\Framework\Helpers\DataTypes\Strings;
use DeepWebSolutions\Framework\Helpers\FileSystem\FilesystemAwareTrait;
use DeepWebSolutions\Framework\Utilities\Dependencies\AbstractDependenciesChecker;

\defined( 'ABSPATH' ) || exit;

/**
 * Checks whether a list of WP Plugins is present or not.
 *
 * @since   1.0.0
 * @version 1.0.0
 * @author  Antonius Hegyes <a.hegyes@deep-web-solutions.com>
 * @package DeepWebSolutions\WP-Framework\Dependencies\Checkers
 */
class WPPluginsChecker extends AbstractDependenciesChecker {
    // region TRAITS

    use FilesystemAwareTrait;

    // endregion

    // region GETTERS

    /**
     * {@inheritDoc}
     *
     * @since   1.0.0
     * @version 1.0.0
     */
    public function get_type(): string {
        return 'active_plugins';
    }

    // endregion

    // region INHERITED METHODS

    /**
     * {@inheritDoc}
     *
     * @since   1.0.0
     * @version 1.0.0
     */
    public function register_dependency( $dependency ): bool {
        $validity = $this->is_dependency_valid( $dependency );
        if ( true === $validity ) {
            $dependency['name']   = $this->get_plugin_name( $dependency['plugin'], $dependency );
            $this->dependencies[] = $dependency;
        }

        return $validity;
    }

    /**
     * {@inheritDoc}
     *
     * @since   1.0.0
     * @version 1.0.0
     */
    public function get_missing_dependencies(): array {
        $missing = array();

        foreach ( $this->get_dependencies() as $dependency ) {
            $is_active = $this->is_plugin_active( $dependency['plugin'], $dependency );

            if ( ! $is_active ) {
                $missing[ $dependency['plugin'] ] = $dependency;
            } elseif ( isset( $dependency['min_version'] ) ) {
                $version = $this->get_active_plugin_version( $dependency['plugin'], $dependency );
                if ( \version_compare( $version, $dependency['min_version'], '<' ) ) {
                    $missing[ $dependency['plugin'] ] = $dependency + array( 'version' => $version );
                }
            }
        }

        return $missing;
    }

    // endregion

    // region HELPERS

    /**
     * {@inheritDoc}
     *
     * @since   1.0.0
     * @version 1.0.0
     */
    protected function is_dependency_valid( $dependency ): bool {
        return \is_array( $dependency ) && Arrays::has_string_keys( $dependency ) && isset( $dependency['plugin'] );
    }

    /**
     * {@inheritDoc}
     *
     * @since   1.0.0
     * @version 1.0.0
     */
    protected function get_dependency_key(): string {
        return 'plugin';
    }

    /**
     * Returns whether a given plugin is active or not.
     *
     * @since   1.0.0
     * @version 1.0.0
     *
     * @param   string  $plugin             Plugin to check.
     * @param   array   $plugin_config      Dependency configuration.
     *
     * @return  bool
     */
    protected function is_plugin_active( string $plugin, array $plugin_config ): bool {
        if ( isset( $plugin_config['active_checker'] ) && \is_callable( $plugin_config['active_checker'] ) ) {
            $is_active = Booleans::maybe_cast( \call_user_func( $plugin_config['active_checker'] ), false );
        } else {
            $is_active = \in_array( $plugin, (array) \get_option( 'active_plugins', array() ), true );
            if ( \is_multisite() && ! $is_active ) {
                $is_active = isset( \get_site_option( 'active_sitewide_plugins', array() )[ $plugin ] );
            }
        }

        return $is_active;
    }

    /**
     * Returns the version of an installed and active plugin.
     *
     * @since   1.0.0
     * @version 1.0.0
     *
     * @param   string  $plugin             Plugin to check.
     * @param   array   $plugin_config      Dependency configuration.
     *
     * @return  string
     */
    protected function get_active_plugin_version( string $plugin, array $plugin_config ): string {
        if ( isset( $plugin_config['version_getter'] ) && \is_callable( $plugin_config['version_getter'] ) ) {
            $version = \call_user_func( $plugin_config['version_getter'] );
        } else {
            $plugin_data = $this->get_plugin_data( $plugin, array( 'version' => 'Version' ) );
            $version     = \is_null( $plugin_data ) ? '0.0.0' : ( $plugin_data['version'] ?: '0.0.0' );
        }

        return $version;
    }

    /**
     * Returns a plugin's name.
     *
     * @since   1.0.0
     * @version 1.0.0
     *
     * @param   string  $plugin             Plugin to check.
     * @param   array   $plugin_config      Dependency configuration.
     *
     * @return  string
     */
    protected function get_plugin_name( string $plugin, array $plugin_config ): string {
        if ( $this->is_plugin_active( $plugin, $plugin_config ) ) {
            if ( isset( $plugin_config['name_getter'] ) && \is_callable( $plugin_config['name_getter'] ) ) {
                $plugin_name = Strings::maybe_cast( \call_user_func( $plugin_config['name_getter'] ), '' );
            } else {
                $plugin_data = $this->get_plugin_data(
                    $plugin,
                    array(
                        'name'        => 'Plugin Name',
                        'text_domain' => 'Text Domain',
                    )
                );
                if ( ! \is_null( $plugin_data ) ) {
                    $plugin_name = $plugin_data['name'] ?: ( $plugin_config['fallback_name'] ?? '' );
                    if ( ! empty( $plugin_data['text_domain'] ) ) {
                        $plugin_name = \__( $plugin_name, $plugin_data['text_domain'] ); // phpcs:ignore WordPress.WP.I18n
                    }
                } else {
                    $plugin_name = $plugin_config['fallback_name'] ?? '';
                }
            }
        } else {
            $plugin_name = $plugin_config['fallback_name'] ?? '';
        }

        return $plugin_name;
    }

    /**
     * Retrieves header data from a given plugin's file.
     *
     * @since   1.0.0
     * @version 1.0.0
     *
     * @param   string  $plugin     The active plugin.
     * @param   array   $headers    The headers to retrieve.
     *
     * @return  array|null
     */
    protected function get_plugin_data( string $plugin, array $headers ): ?array {
        $wp_filesystem = $this->get_wp_filesystem();
        return \is_null( $wp_filesystem ) ? null
            : \get_file_data( \trailingslashit( $wp_filesystem->wp_plugins_dir() ) . $plugin, $headers );
    }

    // endregion
}