365 lines
13 KiB
PHP
365 lines
13 KiB
PHP
<?php // phpcs:disable WordPress.Files.FileName.InvalidClassFileName -- Main plugin file; name dictated by WordPress plugin conventions.
|
|
/**
|
|
* Plugin Name: Complianz - Terms and Conditions
|
|
* Plugin URI: https://wordpress.org/plugins/complianz-terms-conditions
|
|
* Description: Plugin from Complianz to generate Terms & Conditions for your website.
|
|
* Version: 1.3.0
|
|
* Requires at least: 5.7
|
|
* Requires PHP: 7.4
|
|
* Text Domain: complianz-terms-conditions
|
|
* Domain Path: /languages
|
|
* Author: Complianz
|
|
* Author URI: https://complianz.io
|
|
*
|
|
* @package Complianz_Terms_Conditions
|
|
*/
|
|
|
|
/**
|
|
* Main plugin bootstrap file for Complianz Terms & Conditions.
|
|
*
|
|
* Declares the plugin header, defines the core COMPLIANZ_TC singleton class,
|
|
* registers activation hooks, and requires the global functions file. All
|
|
* plugin components (admin, wizard, document, REST API, Gutenberg block) are
|
|
* loaded and instantiated from here in response to the `plugins_loaded` hook.
|
|
*
|
|
* @package Complianz_Terms_Conditions
|
|
* @author Complianz
|
|
* @copyright 2023 Complianz.io
|
|
* @license GPL-2.0-or-later
|
|
* @link https://complianz.io
|
|
*
|
|
* @since 1.0.0
|
|
*/
|
|
|
|
/*
|
|
Copyright 2023 Complianz.io (email : support@complianz.io)
|
|
*/
|
|
|
|
// Prevent direct file access outside of the WordPress bootstrap.
|
|
defined( 'ABSPATH' ) || die( 'you do not have access to this page!' );
|
|
|
|
// Flag this as the free edition of the plugin (used by premium add-ons to detect edition).
|
|
define( 'cmplz_tc_free', true ); // phpcs:ignore Generic.NamingConventions.UpperCaseConstantName.ConstantNotUpperCase -- Established constant name used across the plugin ecosystem; renaming would break add-ons.
|
|
|
|
if ( ! function_exists( 'cmplz_tc_activation_check' ) ) {
|
|
/**
|
|
* Validates minimum environment requirements before the plugin is activated.
|
|
*
|
|
* Deactivates the plugin and shows a wp_die() notice when the server does not
|
|
* meet the minimum PHP or WordPress version requirements. This prevents fatal
|
|
* errors from being thrown on sites running older software stacks.
|
|
*
|
|
* @since 2.1.5
|
|
*
|
|
* @see deactivate_plugins()
|
|
* @see register_activation_hook()
|
|
*
|
|
* @return void
|
|
*/
|
|
function cmplz_tc_activation_check() {
|
|
if ( version_compare( PHP_VERSION, '7.4', '<' ) ) {
|
|
deactivate_plugins( plugin_basename( __FILE__ ) );
|
|
wp_die( esc_html__( 'Complianz - Terms & Conditions cannot be activated. The plugin requires PHP 7.4 or higher', 'complianz-terms-conditions' ) );
|
|
}
|
|
|
|
global $wp_version;
|
|
if ( version_compare( $wp_version, '4.9', '<' ) ) {
|
|
deactivate_plugins( plugin_basename( __FILE__ ) );
|
|
wp_die( esc_html__( 'Complianz - Terms & Conditions cannot be activated. The plugin requires WordPress 4.9 or higher', 'complianz-terms-conditions' ) );
|
|
}
|
|
}
|
|
// Run the environment check immediately on plugin activation.
|
|
register_activation_hook( __FILE__, 'cmplz_tc_activation_check' );
|
|
}
|
|
|
|
// phpcs:disable Universal.Files.SeparateFunctionsFromOO.Mixed -- Main plugin bootstrap file intentionally combines the plugin class with activation functions.
|
|
if ( ! class_exists( 'COMPLIANZ_TC' ) ) {
|
|
/**
|
|
* Core plugin class — singleton container for all Complianz T&C components.
|
|
*
|
|
* Manages plugin initialisation by setting up constants, requiring component
|
|
* files, registering WordPress hooks, and instantiating the individual
|
|
* sub-system objects (config, admin, wizard, document, etc.). Only one
|
|
* instance is ever created; use COMPLIANZ_TC::get_instance() to access it.
|
|
*
|
|
* Admin-only components (review prompt, admin UI, field handling, wizard,
|
|
* callback notices) are loaded and instantiated exclusively inside the
|
|
* is_admin() branch to avoid unnecessary overhead on the frontend.
|
|
*
|
|
* @package Complianz_Terms_Conditions
|
|
*
|
|
* @since 1.0.0
|
|
*/
|
|
class COMPLIANZ_TC {
|
|
|
|
/**
|
|
* Holds the single instance of this class.
|
|
*
|
|
* @since 1.0.0
|
|
* @access public
|
|
* @var COMPLIANZ_TC|null
|
|
*/
|
|
public static $instance;
|
|
|
|
/**
|
|
* Plugin configuration object (document types, field definitions, regions).
|
|
*
|
|
* @since 1.0.0
|
|
* @access public
|
|
* @var cmplz_tc_config
|
|
*/
|
|
public static $config;
|
|
|
|
/**
|
|
* Review prompt handler (shows the admin "please review us" notice).
|
|
*
|
|
* @since 1.0.0
|
|
* @access public
|
|
* @var cmplz_tc_review
|
|
*/
|
|
public static $review;
|
|
|
|
/**
|
|
* Admin UI controller (settings pages, menus, notices).
|
|
*
|
|
* @since 1.0.0
|
|
* @access public
|
|
* @var cmplz_tc_admin
|
|
*/
|
|
public static $admin;
|
|
|
|
/**
|
|
* Field renderer and option persistence handler.
|
|
*
|
|
* @since 1.0.0
|
|
* @access public
|
|
* @var cmplz_tc_field
|
|
*/
|
|
public static $field;
|
|
|
|
/**
|
|
* Step-by-step setup wizard controller.
|
|
*
|
|
* @since 1.0.0
|
|
* @access public
|
|
* @var cmplz_tc_wizard
|
|
*/
|
|
public static $wizard;
|
|
|
|
/**
|
|
* Placeholder for a future guided tour component (currently unused).
|
|
*
|
|
* @since 1.0.0
|
|
* @access public
|
|
* @var mixed
|
|
*/
|
|
public static $tour;
|
|
|
|
/**
|
|
* Document generator: builds, stores, and exports T&C documents.
|
|
*
|
|
* @since 1.0.0
|
|
* @access public
|
|
* @var cmplz_tc_document
|
|
*/
|
|
public static $document;
|
|
|
|
/**
|
|
* Initialises the plugin by setting up constants, loading files, and instantiating components.
|
|
*
|
|
* Called once via get_instance(). Admin-only components are conditionally
|
|
* loaded to avoid overhead on frontend requests.
|
|
*
|
|
* @since 1.0.0
|
|
* @access private
|
|
*/
|
|
private function __construct() {
|
|
self::setup_constants();
|
|
self::includes();
|
|
self::hooks();
|
|
|
|
self::$config = new cmplz_tc_config();
|
|
|
|
// Only instantiate heavy admin components when in the WordPress admin area.
|
|
if ( is_admin() ) {
|
|
self::$review = new cmplz_tc_review();
|
|
self::$admin = new cmplz_tc_admin();
|
|
self::$field = new cmplz_tc_field();
|
|
self::$wizard = new cmplz_tc_wizard();
|
|
}
|
|
|
|
// The document object is needed both on the frontend (shortcode) and in admin.
|
|
self::$document = new cmplz_tc_document();
|
|
}
|
|
|
|
/**
|
|
* Returns the single instance of COMPLIANZ_TC, creating it on first call.
|
|
*
|
|
* Implements the singleton pattern so that only one instance of the plugin
|
|
* class is ever active per request. All callers — including REST-API routes,
|
|
* shortcodes, and the PDF download endpoint — access plugin components
|
|
* through this method (e.g. COMPLIANZ_TC::$document).
|
|
*
|
|
* @since 1.0.0
|
|
* @access public
|
|
*
|
|
* @return COMPLIANZ_TC The single plugin instance.
|
|
*/
|
|
public static function get_instance() {
|
|
if ( ! isset( self::$instance ) && ! ( self::$instance instanceof COMPLIANZ ) ) {
|
|
self::$instance = new self();
|
|
}
|
|
|
|
return self::$instance;
|
|
}
|
|
|
|
/**
|
|
* Defines all plugin-wide constants used throughout the codebase.
|
|
*
|
|
* Centralises path, URL, and tuning constants so they are set once and
|
|
* available globally. The version constant appends a cache-busting timestamp
|
|
* when SCRIPT_DEBUG is enabled, forcing browsers to reload assets during
|
|
* active development.
|
|
*
|
|
* @since 1.0.0
|
|
* @access private
|
|
*
|
|
* @return void
|
|
*/
|
|
private function setup_constants() {
|
|
// Average minutes required to complete a single wizard question (used for time-estimate display).
|
|
define( 'CMPLZ_TC_MINUTES_PER_QUESTION', 0.18 );
|
|
// Reduced estimate used when the user opts for the quick-setup flow.
|
|
define( 'CMPLZ_TC_MINUTES_PER_QUESTION_QUICK', 0.1 );
|
|
// Admin menu position for the plugin's top-level menu item.
|
|
define( 'CMPLZ_TC_MAIN_MENU_POSITION', 40 );
|
|
// Trailing-slash URL to the plugin root directory.
|
|
define( 'cmplz_tc_url', plugin_dir_url( __FILE__ ) ); // phpcs:ignore Generic.NamingConventions.UpperCaseConstantName.ConstantNotUpperCase -- Lowercase constant name; established across codebase and add-ons.
|
|
// Trailing-slash filesystem path to the plugin root directory.
|
|
define( 'cmplz_tc_path', plugin_dir_path( __FILE__ ) ); // phpcs:ignore Generic.NamingConventions.UpperCaseConstantName.ConstantNotUpperCase -- Lowercase constant name; established across codebase and add-ons.
|
|
// Plugin basename (e.g. complianz-terms-conditions/complianz-terms-conditions.php).
|
|
define( 'cmplz_tc_plugin', plugin_basename( __FILE__ ) ); // phpcs:ignore Generic.NamingConventions.UpperCaseConstantName.ConstantNotUpperCase -- Lowercase constant name; established across codebase and add-ons.
|
|
// Absolute filesystem path to this main plugin file.
|
|
define( 'cmplz_tc_plugin_file', __FILE__ ); // phpcs:ignore Generic.NamingConventions.UpperCaseConstantName.ConstantNotUpperCase -- Lowercase constant name; established across codebase and add-ons.
|
|
// Append a timestamp in SCRIPT_DEBUG mode to bust browser/CDN asset caches.
|
|
$debug = ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) ? time() : '';
|
|
define( 'cmplz_tc_version', '1.3.0' . $debug ); // phpcs:ignore Generic.NamingConventions.UpperCaseConstantName.ConstantNotUpperCase -- Lowercase constant name; established across codebase and add-ons.
|
|
}
|
|
|
|
/**
|
|
* Requires all plugin component files in dependency order.
|
|
*
|
|
* Files are loaded conditionally where appropriate: the Gutenberg block is
|
|
* only included when the block editor is active; admin-only files are
|
|
* deferred to the is_admin() branch to avoid loading unnecessary code on
|
|
* public-facing requests.
|
|
*
|
|
* @since 1.0.0
|
|
* @access private
|
|
*
|
|
* @return void
|
|
*/
|
|
private function includes() {
|
|
// Document class is required on all requests (shortcode + PDF endpoint).
|
|
require_once cmplz_tc_path . 'class-document.php';
|
|
|
|
// Only load the Gutenberg block integration when the block editor is in use.
|
|
if ( cmplz_tc_uses_gutenberg() ) {
|
|
require_once plugin_dir_path( __FILE__ ) . 'gutenberg/block.php';
|
|
}
|
|
|
|
// REST API routes are registered on every request so they are always reachable.
|
|
require_once plugin_dir_path( __FILE__ ) . 'rest-api/rest-api.php';
|
|
|
|
// Admin-only files: defer loading to reduce frontend memory footprint.
|
|
if ( is_admin() ) {
|
|
require_once cmplz_tc_path . '/assets/icons.php';
|
|
require_once cmplz_tc_path . 'class-admin.php';
|
|
require_once cmplz_tc_path . 'class-review.php';
|
|
require_once cmplz_tc_path . 'class-field.php';
|
|
require_once cmplz_tc_path . 'class-wizard.php';
|
|
require_once cmplz_tc_path . 'callback-notices.php';
|
|
}
|
|
|
|
// Config is required on all requests: it holds document definitions and field maps.
|
|
require_once cmplz_tc_path . 'config/class-config.php';
|
|
}
|
|
|
|
/**
|
|
* Registers WordPress action and filter hooks for the plugin.
|
|
*
|
|
* Defers translation loading to the `init` hook to comply with WordPress 6.7+
|
|
* requirements (loading translations earlier triggers a _doing_it_wrong() notice
|
|
* in WP 6.7 and above).
|
|
*
|
|
* @since 1.0.0
|
|
* @access private
|
|
*
|
|
* @return void
|
|
*/
|
|
private function hooks() {
|
|
add_action(
|
|
'init',
|
|
function () {
|
|
// Load the plugin's text domain for i18n; deferred to init for WP 6.7 compatibility.
|
|
load_plugin_textdomain( 'complianz-terms-conditions' );
|
|
}
|
|
);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Boots the plugin on `plugins_loaded` at priority 9.
|
|
*
|
|
* Priority 9 (rather than the default 10) ensures the plugin instance is
|
|
* available before other plugins that hook at the default priority and may
|
|
* depend on COMPLIANZ_TC::$document or other static properties.
|
|
*/
|
|
add_action(
|
|
'plugins_loaded',
|
|
function () {
|
|
COMPLIANZ_TC::get_instance();
|
|
},
|
|
9
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Runs first-time setup tasks when the plugin is activated.
|
|
*
|
|
* Seeds the `cmplz_generate_pdf_languages` option with the current WordPress
|
|
* site locale so a PDF is generated for the active language on first use.
|
|
* Also sets a short-lived transient that triggers a redirect to the plugin
|
|
* settings page immediately after activation, giving users a smooth onboarding
|
|
* experience.
|
|
*
|
|
* The language seeding is guarded with a get_option() check so it only runs
|
|
* once; subsequent activations (e.g. after deactivate/reactivate) do not
|
|
* overwrite any languages the user may have added.
|
|
*
|
|
* @since 1.0.0
|
|
*
|
|
* @see cmplz_tc_sanitize_language()
|
|
* @see register_activation_hook()
|
|
*
|
|
* @return void
|
|
*/
|
|
function cmplz_tc_activation() {
|
|
// Seed the PDF languages list only on the very first activation.
|
|
if ( ! get_option( 'cmplz_generate_pdf_languages' ) ) {
|
|
// Build a map of sanitised locale → 1 (enabled) for the site's current locale.
|
|
$languages = array( cmplz_tc_sanitize_language( get_locale() ) => 1 );
|
|
// Remove any empty keys that result from an unrecognised locale format.
|
|
// @phpstan-ignore-next-line -- The value may be an empty string if the locale format is unrecognised.
|
|
$languages = array_filter( $languages );
|
|
update_option( 'cmplz_generate_pdf_languages', $languages );
|
|
}
|
|
// Set a transient consumed by the admin redirect handler to forward the user to settings.
|
|
set_transient( 'cmplz_tc_redirect_to_settings', true, DAY_IN_SECONDS );
|
|
}
|
|
register_activation_hook( __FILE__, 'cmplz_tc_activation' );
|
|
|
|
|
|
// Load global helper functions used throughout the plugin.
|
|
require_once plugin_dir_path( __FILE__ ) . 'functions.php';
|