woocommerce/plugins/woocommerce-admin/src-internal/Admin/FeaturePlugin.php

316 lines
9.7 KiB
PHP
Raw Normal View History

<?php
/**
* WooCommerce Admin: Feature plugin main class.
*/
namespace Automattic\WooCommerce\Internal\Admin;
defined( 'ABSPATH' ) || exit;
use Automattic\WooCommerce\Admin\API;
use Automattic\WooCommerce\Internal\Admin\Install;
use Automattic\WooCommerce\Admin\Loader;
use \Automattic\WooCommerce\Admin\Notes\Notes;
use \Automattic\WooCommerce\Admin\Notes\OrderMilestones;
use \Automattic\WooCommerce\Admin\Notes\WooSubscriptionsNotes;
use \Automattic\WooCommerce\Admin\Notes\TrackingOptIn;
use \Automattic\WooCommerce\Admin\Notes\WooCommercePayments;
use \Automattic\WooCommerce\Admin\Notes\InstallJPAndWCSPlugins;
use \Automattic\WooCommerce\Admin\Notes\SetUpAdditionalPaymentTypes;
use \Automattic\WooCommerce\Admin\Notes\TestCheckout;
use \Automattic\WooCommerce\Admin\Notes\SellingOnlineCourses;
use \Automattic\WooCommerce\Internal\Admin\Notes\MerchantEmailNotifications;
use \Automattic\WooCommerce\Admin\Notes\WelcomeToWooCommerceForStoreUsers;
use \Automattic\WooCommerce\Admin\Notes\ManageStoreActivityFromHomeScreen;
use \Automattic\WooCommerce\Admin\Notes\NavigationNudge;
use \Automattic\WooCommerce\Admin\Notes\MagentoMigration;
use Automattic\WooCommerce\Admin\Features\Features;
use Automattic\WooCommerce\Admin\PluginsHelper;
use Automattic\WooCommerce\Admin\PluginsInstaller;
use Automattic\WooCommerce\Admin\ReportExporter;
use Automattic\WooCommerce\Admin\ReportsSync;
use Automattic\WooCommerce\Internal\Admin\CategoryLookup;
use Automattic\WooCommerce\Internal\Admin\Events;
/**
* Feature plugin main class.
*
* @internal This file will not be bundled with woo core, only the feature plugin.
* @internal Note this is not called WC_Admin due to a class already existing in core with that name.
*/
class FeaturePlugin {
/**
* The single instance of the class.
*
* @var object
*/
protected static $instance = null;
/**
* Constructor
*
* @return void
*/
protected function __construct() {}
/**
* Get class instance.
*
* @return object Instance.
*/
final public static function instance() {
if ( null === static::$instance ) {
static::$instance = new static();
}
return static::$instance;
}
/**
* Init the feature plugin, only if we can detect both Gutenberg and WooCommerce.
*/
public function init() {
// Load the page controller functions file first to prevent fatal errors when disabling WooCommerce Admin.
$this->define_constants();
require_once WC_ADMIN_ABSPATH . '/includes/page-controller-functions.php';
require_once WC_ADMIN_ABSPATH . '/src/Notes/DeprecatedNotes.php';
require_once WC_ADMIN_ABSPATH . '/includes/core-functions.php';
require_once WC_ADMIN_ABSPATH . '/includes/feature-config.php';
require_once WC_ADMIN_ABSPATH . '/includes/wc-admin-update-functions.php';
require_once WC_ADMIN_ABSPATH . '/includes/class-experimental-abtest.php';
register_activation_hook( WC_ADMIN_PLUGIN_FILE, array( $this, 'on_activation' ) );
register_deactivation_hook( WC_ADMIN_PLUGIN_FILE, array( $this, 'on_deactivation' ) );
if ( did_action( 'plugins_loaded' ) ) {
self::on_plugins_loaded();
} else {
// Make sure we hook into `plugins_loaded` before core's Automattic\WooCommerce\Package::init().
// If core is network activated but we aren't, the packaged version of WooCommerce Admin will
// attempt to use a data store that hasn't been loaded yet - because we've defined our constants here.
// See: https://github.com/woocommerce/woocommerce-admin/issues/3869.
add_action( 'plugins_loaded', array( $this, 'on_plugins_loaded' ), 9 );
}
}
/**
* Install DB and create cron events when activated.
*
* @return void
*/
public function on_activation() {
Install::create_tables();
Install::create_events();
}
/**
* Remove WooCommerce Admin scheduled actions on deactivate.
*
* @return void
*/
public function on_deactivation() {
// Don't clean up if the WooCommerce Admin package is in core.
// NOTE: Any future divergence from the core package will need to be accounted for here.
if ( defined( 'WC_ADMIN_PACKAGE_EXISTS' ) && WC_ADMIN_PACKAGE_EXISTS ) {
return;
}
// Check if we are deactivating due to dependencies not being satisfied.
// If WooCommerce is disabled we can't include files that depend upon it.
if ( ! $this->has_satisfied_dependencies() ) {
return;
}
$this->includes();
ReportsSync::clear_queued_actions();
Notes::clear_queued_actions();
wp_clear_scheduled_hook( 'wc_admin_daily' );
wp_clear_scheduled_hook( 'generate_category_lookup_table' );
}
/**
* Setup plugin once all other plugins are loaded.
*
* @return void
*/
public function on_plugins_loaded() {
$this->load_plugin_textdomain();
if ( ! $this->has_satisfied_dependencies() ) {
add_action( 'admin_init', array( $this, 'deactivate_self' ) );
add_action( 'admin_notices', array( $this, 'render_dependencies_notice' ) );
return;
}
$this->hooks();
$this->includes();
}
/**
* Define Constants.
*/
protected function define_constants() {
$this->define( 'WC_ADMIN_APP', 'wc-admin-app' );
$this->define( 'WC_ADMIN_ABSPATH', dirname( __DIR__, 2 ) . '/' );
$this->define( 'WC_ADMIN_DIST_JS_FOLDER', 'dist/' );
$this->define( 'WC_ADMIN_DIST_CSS_FOLDER', 'dist/' );
$this->define( 'WC_ADMIN_PLUGIN_FILE', WC_ADMIN_ABSPATH . 'woocommerce-admin.php' );
// WARNING: Do not directly edit this version number constant.
// It is updated as part of the prebuild process from the package.json value.
$this->define( 'WC_ADMIN_VERSION_NUMBER', '3.4.0-dev' );
}
/**
* Load Localisation files.
*/
protected function load_plugin_textdomain() {
load_plugin_textdomain( 'woocommerce-admin', false, basename( dirname( __DIR__ ) ) . '/languages' );
}
/**
* Include WC Admin classes.
*/
public function includes() {
// Initialize Database updates, option migrations, and Notes.
Install::init();
Events::instance()->init();
Notes::init();
// Initialize Plugins Installer.
PluginsInstaller::init();
PluginsHelper::init();
// Initialize API.
API\Init::instance();
if ( Features::is_enabled( 'analytics' ) ) {
// Initialize Reports syncing.
ReportsSync::init();
CategoryLookup::instance()->init();
// Initialize Reports exporter.
ReportExporter::init();
}
// Admin note providers.
// @todo These should be bundled in the features/ folder, but loading them from there currently has a load order issue.
new WooSubscriptionsNotes();
new OrderMilestones();
new TrackingOptIn();
new WooCommercePayments();
new InstallJPAndWCSPlugins();
new SetUpAdditionalPaymentTypes();
new TestCheckout();
new SellingOnlineCourses();
new WelcomeToWooCommerceForStoreUsers();
new ManageStoreActivityFromHomeScreen();
new NavigationNudge();
new MagentoMigration();
Remote inbox notification delivery (https://github.com/woocommerce/woocommerce-admin/pull/4143) * Poll and persist specs * Process specs into admin notes * Add send at time rule processor * Fix style issues * Clear actions before recreating them to avoid dupes * Trigger the RINDS engine when a plugin is activated * Unit test SendAtTimeRuleProcessor * Implement plugins activated rule processor * Don't throw exception for unrecognised rule type. Also unit test around this. * add url_is_action_query to tell whether to wrap the URL in wc_admin_url() call or not * Add NOT rule * revert change to install.php * Drop unimplemented resend after dismissal rule * Add OR rule * Explicitly make "fail" a type of rule that can be applied to a spec * Add plugin version rule processor * Tidy up, don't need to pass $spec everywhere * Remove meta record for action state - not really needed * Move spec runner into it's own class, add some checks around re-unactioning a note * Replace if..else with switch * Just update the option * Check that the JSON coming in is an array * Change OR rule to accept an array of operands * Add Pass rule processor * Fix specs that are initially not published * Rename send at rule to publish after * Add publish before rule * Remove unused interface * Can't use PHP7's anonymous classes * New notification: How to draw attention to your online store * Add feature flag for rule-base inbox notes * rename everything to RemoteInboxNotifications from RINDS * Fix merge fail * fix test * Change preunactioned to pending * Move feature flag check into Events.php * Refactor reading a data source * Rename poll_data_sources function * Refactor EvaluateAndGetStatus::evaluate to take the rule evaluator directly * Check that the response body exists * Add validation and defensive checks * Add rule processor interface * Update note created time on status change * Move non-test dependencies into processor constructors * Update to proposed live URL * Remove setting icon as it's being deprecated Co-authored-by: Rebecca Scott <me@becdetat.com>
2020-06-05 01:51:25 +00:00
Add merchant email notifications (https://github.com/woocommerce/woocommerce-admin/pull/5922) * Added MerchantEmailNotifications class * Added new type and Events refactor # Conflicts: # src/Events.php * Added templates * Refactored MerchantEmailNotifications and NotificationEmail * Templates refactored * Added email opening tracking endpoint * Added templates handling * Moved folder `MerchantEmailNotifications` * Fixed template extensibility * Fixed note `heading` check * Added default type in `get_template_filename` * Added tests * Removed bypass * Modified URL * Added required noteTypes * Added flag for functionallity * Fixed plain link * Fixed comment * Turned email notifications on by default This commit adds the code to turn email notifications on by default * Fixed email styles * Fixed typo * Renamed method "possible_send" as "run" * Removed unnecessary control * Fixed another typo * Renamed method as "get_notification_email_addresses" * Refactored method "send_merchant_notification" * Renamed plain-merchant-notification * Fixed tests * Merchant email notifications - Action triggering (https://github.com/woocommerce/woocommerce-admin/pull/5976) * Added templates # Conflicts: # includes/emails/plain-mechant-notification.php # Conflicts: # includes/emails/html-merchant-notification.php * Added note action triggering This commit adds the note actions triggering # Conflicts: # includes/emails/html-merchant-notification.php * Fixed error handling * Refactored "trigger_note_action" method * Fixed actions url * Fixed note URL * Added external redirect * Added image and html handling for email * Fixed tests * Fixed buttons style Co-authored-by: Fernando Marichal <contacto@fernandomarichal.com> * Add your first product: email notification (https://github.com/woocommerce/woocommerce-admin/pull/6024) * Added AddFirstProduct note # Conflicts: # src/Events.php * Added "AddFirstProduct" email note This commit adds the email note "AddFirstProduct" * Fixed image This commit removes the image img-product-light.svg to use a png instead. Otherwise, the gmail proxy would break the image * Fixed readme.txt Co-authored-by: Fernando Marichal <contacto@fernandomarichal.com> * Added readme.txt Co-authored-by: Fernando Marichal <contacto@fernandomarichal.com>
2021-01-13 00:09:22 +00:00
// Initialize MerchantEmailNotifications.
MerchantEmailNotifications::init();
}
/**
* Set up our admin hooks and plugin loader.
*/
protected function hooks() {
add_filter( 'woocommerce_admin_features', array( $this, 'replace_supported_features' ), 0 );
Loader::get_instance();
}
/**
* Get an array of dependency error messages.
*
* @return array
*/
protected function get_dependency_errors() {
$errors = array();
$wordpress_version = get_bloginfo( 'version' );
$minimum_wordpress_version = '5.4';
$minimum_woocommerce_version = '4.8';
$wordpress_minimum_met = version_compare( $wordpress_version, $minimum_wordpress_version, '>=' );
$woocommerce_minimum_met = class_exists( 'WooCommerce' ) && version_compare( WC_VERSION, $minimum_woocommerce_version, '>=' );
if ( ! $woocommerce_minimum_met ) {
$errors[] = sprintf(
/* translators: 1: URL of WooCommerce plugin, 2: The minimum WooCommerce version number */
__( 'The WooCommerce Admin feature plugin requires <a href="%1$s">WooCommerce</a> %2$s or greater to be installed and active.', 'woocommerce-admin' ),
'https://wordpress.org/plugins/woocommerce/',
$minimum_woocommerce_version
);
}
if ( ! $wordpress_minimum_met ) {
$errors[] = sprintf(
/* translators: 1: URL of WordPress.org, 2: The minimum WordPress version number */
__( 'The WooCommerce Admin feature plugin requires <a href="%1$s">WordPress</a> %2$s or greater to be installed and active.', 'woocommerce-admin' ),
'https://wordpress.org/',
$minimum_wordpress_version
);
}
return $errors;
}
/**
* Returns true if all dependencies for the wc-admin plugin are loaded.
*
* @return bool
*/
public function has_satisfied_dependencies() {
$dependency_errors = $this->get_dependency_errors();
return 0 === count( $dependency_errors );
}
/**
* Deactivates this plugin.
*/
public function deactivate_self() {
deactivate_plugins( plugin_basename( WC_ADMIN_PLUGIN_FILE ) );
unset( $_GET['activate'] ); // phpcs:ignore CSRF ok.
}
/**
* Notify users of the plugin requirements.
*/
public function render_dependencies_notice() {
$message = $this->get_dependency_errors();
printf( '<div class="error"><p>%s</p></div>', implode( ' ', $message ) ); /* phpcs:ignore xss ok. */
}
/**
* Overwrites the allowed features array using a local `feature-config.php` file.
*
* @param array $features Array of feature slugs.
*/
public function replace_supported_features( $features ) {
$feature_config = apply_filters( 'woocommerce_admin_get_feature_config', wc_admin_get_feature_config() );
$features = array_keys( array_filter( $feature_config ) );
return $features;
}
/**
* Define constant if not already set.
*
* @param string $name Constant name.
* @param string|bool $value Constant value.
*/
protected function define( $name, $value ) {
if ( ! defined( $name ) ) {
define( $name, $value );
}
}
/**
* Prevent cloning.
*/
private function __clone() {}
/**
* Prevent unserializing.
*/
public function __wakeup() {
die();
}
2019-08-14 23:35:02 +00:00
}