first commit
This commit is contained in:
@@ -0,0 +1,47 @@
|
||||
{
|
||||
"name": "wpdesk\/ltv-dashboard-widget",
|
||||
"description": "Library for displaying ltv widget in WordPress dashboard.",
|
||||
"license": "MIT",
|
||||
"keywords": [
|
||||
"wordpress",
|
||||
"notice",
|
||||
"admin"
|
||||
],
|
||||
"minimum-stability": "stable",
|
||||
"config": {
|
||||
"platform": {
|
||||
"php": "7.0"
|
||||
}
|
||||
},
|
||||
"require": {
|
||||
"php": ">=7.2"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit\/phpunit": "<7",
|
||||
"wp-coding-standards\/wpcs": "^0.14.1",
|
||||
"squizlabs\/php_codesniffer": "^3.0.2",
|
||||
"mockery\/mockery": "*",
|
||||
"10up\/wp_mock": "*",
|
||||
"wimg\/php-compatibility": "^8"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"FcfVendor\\WPDesk\\Dashboard\\": "src\/"
|
||||
}
|
||||
},
|
||||
"extra": {
|
||||
"text-domain": "wpdesk_ltv_dashboard_widget",
|
||||
"translations-folder": "lang",
|
||||
"po-files": {
|
||||
"pl_PL": "wpdesk-ltv-dashboard-widget-pl_PL.po"
|
||||
}
|
||||
},
|
||||
"autoload-dev": {},
|
||||
"scripts": {
|
||||
"phpcs": "phpcs",
|
||||
"phpunit-unit": "phpunit --configuration phpunit-unit.xml --coverage-text --colors=never",
|
||||
"phpunit-unit-fast": "phpunit --configuration phpunit-unit.xml --no-coverage",
|
||||
"phpunit-integration": "phpunit --configuration phpunit-integration.xml --coverage-text --colors=never",
|
||||
"phpunit-integration-fast": "phpunit --configuration phpunit-integration.xml --no-coverage"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,157 @@
|
||||
<?php
|
||||
|
||||
namespace FcfVendor\WPDesk\Dashboard;
|
||||
|
||||
final class DashboardWidget
|
||||
{
|
||||
const ID = 'flexible-checkout-fields';
|
||||
const MUTEX_HOOK = 'wpdesk/ltvdashboard/initialized';
|
||||
public function hooks()
|
||||
{
|
||||
if (\apply_filters(self::MUTEX_HOOK, \false) === \false) {
|
||||
\add_filter(self::MUTEX_HOOK, '__return_true');
|
||||
\add_action('wp_dashboard_setup', [$this, 'add_widget']);
|
||||
}
|
||||
}
|
||||
public function add_widget()
|
||||
{
|
||||
\wp_add_dashboard_widget(self::ID, \__('Grow your business with WP Desk', 'flexible-checkout-fields'), [$this, 'widget_output'], null, null, 'normal', 'high');
|
||||
}
|
||||
private function get_all_plugins_dirs() : array
|
||||
{
|
||||
$all_plugins = \array_keys(\get_plugins());
|
||||
return \array_map('dirname', $all_plugins);
|
||||
}
|
||||
private function filter_plugins_to_show(array $plugins) : array
|
||||
{
|
||||
\usort($plugins, static function ($a, $b) {
|
||||
return \strnatcmp($a['priority'], $b['priority']);
|
||||
});
|
||||
$installed_plugins_dir = $this->get_all_plugins_dirs();
|
||||
$plugins = \array_filter($plugins, static function ($plugin) use($installed_plugins_dir) {
|
||||
return !\in_array($plugin['slug'], $installed_plugins_dir, \true);
|
||||
});
|
||||
return \array_slice($plugins, 0, 3);
|
||||
}
|
||||
private function get_server() : string
|
||||
{
|
||||
$locale = \get_user_locale();
|
||||
if ($locale === 'pl_PL') {
|
||||
return 'www.wpdesk.pl';
|
||||
}
|
||||
return 'www.wpdesk.net';
|
||||
}
|
||||
private function get_utm_base() : string
|
||||
{
|
||||
return 'utm_source=dashboard-metabox&utm_campaign=dashboard-metabox';
|
||||
}
|
||||
private function get_widget_data() : array
|
||||
{
|
||||
$cache_key = \sprintf('wpdesk_ltv_%1$s_%2$s', self::ID, \get_user_locale());
|
||||
$cache_data = \get_transient($cache_key);
|
||||
if ($cache_data) {
|
||||
return $cache_data;
|
||||
} elseif ($cache_data === \false) {
|
||||
$response_data = $this->get_widget_data_from_remote();
|
||||
if ($response_data !== null) {
|
||||
\set_transient($cache_key, $response_data, 24 * 60 * 60);
|
||||
return $response_data;
|
||||
} else {
|
||||
\set_transient($cache_key, null, 6 * 60 * 60);
|
||||
}
|
||||
}
|
||||
return [];
|
||||
}
|
||||
/**
|
||||
* @return array|null
|
||||
*/
|
||||
private function get_widget_data_from_remote()
|
||||
{
|
||||
$response = \wp_remote_get(\sprintf('https://%s?wpdesk_api=1&t=1', $this->get_server()), ['timeout' => 10, 'sslverify' => \false]);
|
||||
if (!\is_array($response)) {
|
||||
return null;
|
||||
}
|
||||
$ret = \json_decode($response['body'], \true);
|
||||
if (!$ret || !\is_array($ret)) {
|
||||
return null;
|
||||
}
|
||||
return ['header' => $ret['header'] ?? null, 'plugins' => $this->filter_plugins_to_show($ret['plugins'] ?? []), 'footer' => $ret['footer'] ?? null];
|
||||
}
|
||||
public function widget_output()
|
||||
{
|
||||
$widget_data = $this->get_widget_data();
|
||||
$server = $this->get_server();
|
||||
$utm_base = $this->get_utm_base();
|
||||
if (!empty($widget_data)) {
|
||||
echo '<div class="wpdesk_ltv_dashboard_widget">';
|
||||
if ($widget_data['header']) {
|
||||
echo \wp_kses_post($widget_data['header']);
|
||||
}
|
||||
echo '<ul class="ltv-rows">';
|
||||
foreach ($widget_data['plugins'] as $plugin) {
|
||||
$plugin_url = \sprintf('%1$s?%2$s&utm_medium=more-info-button&utm_term=%3$s', $plugin['url'], $utm_base, $plugin['slug']);
|
||||
$add_to_cart_url = \sprintf('https://%1$s/?add-to-cart=%2$s&%3$s&utm_medium=buy-now-button&utm_term=%4$s', $server, $plugin['add_to_cart_id'], $utm_base, $plugin['slug']);
|
||||
echo '<li class="ltv-row">';
|
||||
if ($plugin['image']) {
|
||||
echo '<img src="' . \esc_url($plugin['image']) . '" alt="" />';
|
||||
}
|
||||
echo '<p><strong>' . \esc_html($plugin['name']) . '</strong></p>';
|
||||
echo '<div class="ltv-row-description">' . \wp_kses_post($plugin['description']) . '</div>';
|
||||
echo '<div class="ltv-buttons">';
|
||||
echo '<a class="button button-primary button-large" href="' . \esc_url($plugin_url) . '" target="_blank">' . \esc_html__('More info', 'flexible-checkout-fields') . '</a>';
|
||||
echo ' ';
|
||||
echo '<a class="button button-large" href="' . \esc_url($add_to_cart_url) . '" target="_blank">' . \esc_html__('Buy now', 'flexible-checkout-fields') . '</a>';
|
||||
echo '</div>';
|
||||
echo '</li>';
|
||||
}
|
||||
echo '</ul>';
|
||||
echo '<div class="ltv-footer">';
|
||||
if ($widget_data['footer']) {
|
||||
echo \wp_kses_post($widget_data['footer']);
|
||||
}
|
||||
echo '</div>';
|
||||
echo '</div>';
|
||||
?>
|
||||
<style>
|
||||
.wpdesk_ltv_dashboard_widget .ltv-rows {
|
||||
margin-left: -12px;
|
||||
margin-right: -12px;
|
||||
}
|
||||
|
||||
.wpdesk_ltv_dashboard_widget .ltv-row {
|
||||
padding: 6px 12px 24px;
|
||||
}
|
||||
|
||||
.wpdesk_ltv_dashboard_widget .ltv-row:nth-child(odd) {
|
||||
background-color: #f6f7f7;
|
||||
}
|
||||
|
||||
.wpdesk_ltv_dashboard_widget .ltv-row-description p {
|
||||
margin-top: 6px;
|
||||
}
|
||||
|
||||
.wpdesk_ltv_dashboard_widget img {
|
||||
display: block;
|
||||
margin: 0 auto 10px;
|
||||
width: 250px;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.wpdesk_ltv_dashboard_widget .ltv-buttons {
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
}
|
||||
|
||||
.wpdesk_ltv_dashboard_widget .ltv-footer {
|
||||
margin: 0 -12px;
|
||||
padding: 0 12px;
|
||||
}
|
||||
|
||||
.wpdesk_ltv_dashboard_widget .ltv-footer p {
|
||||
margin: 0;
|
||||
}
|
||||
</style>
|
||||
<?php
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
{
|
||||
"name": "wpdesk\/wp-basic-requirements",
|
||||
"authors": [
|
||||
{
|
||||
"name": "Krzysiek",
|
||||
"email": "krzysiek@wpdesk.pl"
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"php": ">=5.3"
|
||||
},
|
||||
"require-dev": {
|
||||
"php": ">=5.5",
|
||||
"phpunit\/phpunit": "<7",
|
||||
"wp-coding-standards\/wpcs": "^0.14.1",
|
||||
"squizlabs\/php_codesniffer": "^3.0.2",
|
||||
"mockery\/mockery": "*",
|
||||
"10up\/wp_mock": "*",
|
||||
"wimg\/php-compatibility": "^8"
|
||||
},
|
||||
"autoload": {},
|
||||
"autoload-dev": {
|
||||
"classmap": [
|
||||
"src",
|
||||
"tests"
|
||||
]
|
||||
},
|
||||
"extra": {
|
||||
"text-domain": "wp-basic-requirements",
|
||||
"translations-folder": "lang",
|
||||
"po-files": {
|
||||
"pl_PL": "pl_PL.po",
|
||||
"en_AU": "en_AU.po",
|
||||
"en_CA": "en_CA.po",
|
||||
"en_GB": "en_GB.po",
|
||||
"de_DE": "de_DE.po"
|
||||
}
|
||||
},
|
||||
"scripts": {
|
||||
"phpcs": "phpcs",
|
||||
"phpunit-unit": "phpunit --configuration phpunit-unit.xml --coverage-text --colors=never",
|
||||
"phpunit-unit-fast": "phpunit --configuration phpunit-unit.xml --no-coverage",
|
||||
"phpunit-integration": "phpunit --configuration phpunit-integration.xml --coverage-text --colors=never",
|
||||
"phpunit-integration-fast": "phpunit --configuration phpunit-integration.xml --no-coverage",
|
||||
"docs": "apigen generate"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,558 @@
|
||||
<?php
|
||||
|
||||
namespace FcfVendor;
|
||||
|
||||
if (!\interface_exists('FcfVendor\\WPDesk_Requirement_Checker')) {
|
||||
require_once __DIR__ . '/Requirement_Checker.php';
|
||||
}
|
||||
if (!\class_exists('FcfVendor\\WPDesk_Basic_Requirement_Checker')) {
|
||||
/**
|
||||
* Checks requirements for plugin
|
||||
* have to be compatible with PHP 5.3.x
|
||||
*/
|
||||
class WPDesk_Basic_Requirement_Checker implements \FcfVendor\WPDesk_Requirement_Checker
|
||||
{
|
||||
const EXTENSION_NAME_OPENSSL = 'openssl';
|
||||
const HOOK_ADMIN_NOTICES_ACTION = 'admin_notices';
|
||||
const HOOK_PLUGIN_DEACTIVATED_ACTION = 'deactivated_plugin';
|
||||
const HOOK_PLUGIN_ACTIVATED_ACTION = 'activated_plugin';
|
||||
const PLUGIN_INFO_KEY_NICE_NAME = 'nice_name';
|
||||
const PLUGIN_INFO_KEY_NAME = 'name';
|
||||
const PLUGIN_INFO_VERSION = 'version';
|
||||
const PLUGIN_INFO_FAKE_REQUIRED_MINIMUM_VERSION = '0.0';
|
||||
const PLUGIN_INFO_APPEND_PLUGIN_DATA = 'required_version';
|
||||
const PLUGIN_INFO_TRANSIENT_NAME = 'require_plugins_data';
|
||||
const PLUGIN_INFO_TRANSIENT_EXPIRATION_TIME = 16;
|
||||
/** @var string */
|
||||
protected $plugin_name;
|
||||
/** @var string */
|
||||
private $plugin_file;
|
||||
/** @var string */
|
||||
private $min_php_version;
|
||||
/** @var string */
|
||||
private $min_wp_version;
|
||||
/** @var string|null */
|
||||
private $min_wc_version = null;
|
||||
/** @var int|null */
|
||||
private $min_openssl_version = null;
|
||||
/** @var array */
|
||||
protected $plugin_require;
|
||||
/** @var bool */
|
||||
protected $should_check_plugin_versions = \false;
|
||||
/** @var array */
|
||||
private $module_require;
|
||||
/** @var array */
|
||||
private $setting_require;
|
||||
/** @var array */
|
||||
protected $notices;
|
||||
/** @var @string */
|
||||
private $text_domain;
|
||||
/**
|
||||
* @param string $plugin_file
|
||||
* @param string $plugin_name
|
||||
* @param string $text_domain
|
||||
* @param string $php_version
|
||||
* @param string $wp_version
|
||||
*/
|
||||
public function __construct($plugin_file, $plugin_name, $text_domain, $php_version, $wp_version)
|
||||
{
|
||||
$this->plugin_file = $plugin_file;
|
||||
$this->plugin_name = $plugin_name;
|
||||
$this->text_domain = $text_domain;
|
||||
$this->set_min_php_require($php_version);
|
||||
$this->set_min_wp_require($wp_version);
|
||||
$this->plugin_require = array();
|
||||
$this->module_require = array();
|
||||
$this->setting_require = array();
|
||||
$this->notices = array();
|
||||
}
|
||||
/**
|
||||
* @param string $version
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function set_min_php_require($version)
|
||||
{
|
||||
$this->min_php_version = $version;
|
||||
return $this;
|
||||
}
|
||||
/**
|
||||
* @param string $version
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function set_min_wp_require($version)
|
||||
{
|
||||
$this->min_wp_version = $version;
|
||||
return $this;
|
||||
}
|
||||
/**
|
||||
* @param string $version
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function set_min_wc_require($version)
|
||||
{
|
||||
$this->min_wc_version = $version;
|
||||
return $this;
|
||||
}
|
||||
/**
|
||||
* @param $version
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function set_min_openssl_require($version)
|
||||
{
|
||||
$this->min_openssl_version = $version;
|
||||
return $this;
|
||||
}
|
||||
/**
|
||||
* @param string $plugin_name Name in wp format dir/file.php
|
||||
* @param string $nice_plugin_name Nice plugin name for better looks in notice
|
||||
* @param string $plugin_require_version required plugin minimum version
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function add_plugin_require($plugin_name, $nice_plugin_name = null, $plugin_require_version = null)
|
||||
{
|
||||
if ($plugin_require_version) {
|
||||
$this->should_check_plugin_versions = \true;
|
||||
}
|
||||
$this->plugin_require[$plugin_name] = array(self::PLUGIN_INFO_KEY_NAME => $plugin_name, self::PLUGIN_INFO_KEY_NICE_NAME => $nice_plugin_name === null ? $plugin_name : $nice_plugin_name, self::PLUGIN_INFO_VERSION => $plugin_require_version === null ? self::PLUGIN_INFO_FAKE_REQUIRED_MINIMUM_VERSION : $plugin_require_version);
|
||||
return $this;
|
||||
}
|
||||
/**
|
||||
* Add plugin to require list. Plugin is from repository so we can ask for installation.
|
||||
*
|
||||
* @param string $plugin_name Name in wp format dir/file.php
|
||||
* @param string $version Required version of the plugin.
|
||||
* @param string $nice_plugin_name Nice plugin name for better looks in notice
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function add_plugin_repository_require($plugin_name, $version, $nice_plugin_name = null)
|
||||
{
|
||||
$this->plugin_require[$plugin_name] = array(self::PLUGIN_INFO_KEY_NAME => $plugin_name, self::PLUGIN_INFO_VERSION => $version, 'repository_url' => 'http://downloads.wordpress.org/plugin/' . \dirname($plugin_name) . '.latest-stable.zip', self::PLUGIN_INFO_KEY_NICE_NAME => $nice_plugin_name === null ? $plugin_name : $nice_plugin_name);
|
||||
return $this;
|
||||
}
|
||||
/**
|
||||
* @param string $module_name
|
||||
* @param string $nice_name Nice module name for better looks in notice
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function add_php_module_require($module_name, $nice_name = null)
|
||||
{
|
||||
if ($nice_name === null) {
|
||||
$this->module_require[$module_name] = $module_name;
|
||||
} else {
|
||||
$this->module_require[$module_name] = $nice_name;
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
/**
|
||||
* @param string $setting
|
||||
* @param mixed $value
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function add_php_setting_require($setting, $value)
|
||||
{
|
||||
$this->setting_require[$setting] = $value;
|
||||
return $this;
|
||||
}
|
||||
/**
|
||||
* Returns true if are requirements are met.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function are_requirements_met()
|
||||
{
|
||||
$this->notices = $this->prepare_requirement_notices();
|
||||
return \count($this->notices) === 0;
|
||||
}
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
private function prepare_requirement_notices()
|
||||
{
|
||||
$notices = array();
|
||||
if (!self::is_php_at_least($this->min_php_version)) {
|
||||
$notices[] = $this->prepare_notice_message(\sprintf(\__('The “%s” plugin cannot run on PHP versions older than %s. Please contact your host and ask them to upgrade.', $this->get_text_domain()), \esc_html($this->plugin_name), $this->min_php_version));
|
||||
}
|
||||
if (!self::is_wp_at_least($this->min_wp_version)) {
|
||||
$notices[] = $this->prepare_notice_message(\sprintf(\__('The “%s” plugin cannot run on WordPress versions older than %s. Please update WordPress.', $this->get_text_domain()), \esc_html($this->plugin_name), $this->min_wp_version));
|
||||
}
|
||||
if ($this->min_wc_version !== null && $this->can_check_plugin_version() && !self::is_wc_at_least($this->min_wc_version)) {
|
||||
$notices[] = $this->prepare_notice_message(\sprintf(\__('The “%s” plugin cannot run on WooCommerce versions older than %s. Please update WooCommerce.', $this->get_text_domain()), \esc_html($this->plugin_name), $this->min_wc_version));
|
||||
}
|
||||
if ($this->min_openssl_version !== null && !self::is_open_ssl_at_least($this->min_openssl_version)) {
|
||||
$notices[] = $this->prepare_notice_message(\sprintf(\__('The “%s” plugin cannot run without OpenSSL module version at least %s. Please update OpenSSL module.', $this->get_text_domain()), \esc_html($this->plugin_name), '0x' . \dechex($this->min_openssl_version)));
|
||||
}
|
||||
$notices = $this->append_plugin_require_notices($notices);
|
||||
$notices = $this->append_module_require_notices($notices);
|
||||
$notices = $this->append_settings_require_notices($notices);
|
||||
if ($this->should_check_plugin_versions) {
|
||||
$notices = $this->check_minimum_require_plugins_version_and_append_notices($notices);
|
||||
}
|
||||
return $notices;
|
||||
}
|
||||
/**
|
||||
* @param $min_version
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public static function is_php_at_least($min_version)
|
||||
{
|
||||
return \version_compare(\PHP_VERSION, $min_version, '>=');
|
||||
}
|
||||
/**
|
||||
* Prepares message in html format
|
||||
*
|
||||
* @param string $message
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function prepare_notice_message($message)
|
||||
{
|
||||
return '<div class="error"><p>' . $message . '</p></div>';
|
||||
}
|
||||
public function get_text_domain()
|
||||
{
|
||||
return $this->text_domain;
|
||||
}
|
||||
/**
|
||||
* @param string $min_version
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function is_wp_at_least($min_version)
|
||||
{
|
||||
return \version_compare(\get_bloginfo('version'), $min_version, '>=');
|
||||
}
|
||||
/**
|
||||
* Are plugins loaded so we can check the version
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function can_check_plugin_version()
|
||||
{
|
||||
return \did_action('plugins_loaded') > 0;
|
||||
}
|
||||
/**
|
||||
* Checks if plugin is active and have designated version. Needs to be enabled in deferred way.
|
||||
*
|
||||
* @param string $min_version
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function is_wc_at_least($min_version)
|
||||
{
|
||||
return \defined('WC_VERSION') && \version_compare(\WC_VERSION, $min_version, '>=');
|
||||
}
|
||||
/**
|
||||
* Checks if ssl version is valid
|
||||
*
|
||||
* @param int $required_version Version in hex. Version 9.6 is 0x000906000
|
||||
*
|
||||
* @return bool
|
||||
* @see https://www.openssl.org/docs/man1.1.0/crypto/OPENSSL_VERSION_NUMBER.html
|
||||
*
|
||||
*/
|
||||
public static function is_open_ssl_at_least($required_version)
|
||||
{
|
||||
return \defined('OPENSSL_VERSION_NUMBER') && \OPENSSL_VERSION_NUMBER > (int) $required_version;
|
||||
}
|
||||
/**
|
||||
* @param $notices array
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function check_minimum_require_plugins_version_and_append_notices($notices)
|
||||
{
|
||||
$required_plugins = $this->retrieve_required_plugins_data();
|
||||
if (\count($required_plugins) > 0) {
|
||||
foreach ($required_plugins as $plugin) {
|
||||
if (\version_compare($plugin['Version'], $plugin[self::PLUGIN_INFO_APPEND_PLUGIN_DATA], '<')) {
|
||||
$notices[] = $this->prepare_notice_message(\sprintf(\__('The “%1$s” plugin requires at least %2$s version of %3$s to work correctly. Please update it to its latest release.', $this->get_text_domain()), \esc_html($this->plugin_name), $plugin[self::PLUGIN_INFO_APPEND_PLUGIN_DATA], $plugin['Name']));
|
||||
}
|
||||
}
|
||||
}
|
||||
return $notices;
|
||||
}
|
||||
/**
|
||||
* Check the plugins directory and retrieve all plugin files with plugin data.
|
||||
*
|
||||
* @return array In format [ 'plugindir/pluginfile.php' => ['Name' => 'Plugin Name', 'Version' => '1.0.1', ...], ]
|
||||
*/
|
||||
private static function retrieve_plugins_data_in_transient()
|
||||
{
|
||||
static $never_executed = \true;
|
||||
if ($never_executed) {
|
||||
$never_executed = \false;
|
||||
/** Required when WC starts later and these data should be in cache */
|
||||
\add_filter('extra_plugin_headers', function ($headers = array()) {
|
||||
$headers[] = 'WC tested up to';
|
||||
$headers[] = 'WC requires at least';
|
||||
$headers[] = 'Woo';
|
||||
return \array_unique($headers);
|
||||
});
|
||||
}
|
||||
$plugins = \get_transient(self::PLUGIN_INFO_TRANSIENT_NAME);
|
||||
if ($plugins === \false) {
|
||||
if (!\function_exists('get_plugins')) {
|
||||
require_once \ABSPATH . '/wp-admin/includes/plugin.php';
|
||||
}
|
||||
$plugins = \function_exists('get_plugins') ? \get_plugins() : array();
|
||||
\set_transient(self::PLUGIN_INFO_TRANSIENT_NAME, $plugins, self::PLUGIN_INFO_TRANSIENT_EXPIRATION_TIME);
|
||||
}
|
||||
return $plugins;
|
||||
}
|
||||
/**
|
||||
* Check the plugins directory and retrieve all required plugin files with plugin data.
|
||||
*
|
||||
* @return array In format [ 'plugindir/pluginfile.php' => ['Name' => 'Plugin Name', 'Version' => '1.0.1', 'required_version' => '1.0.2']... ]
|
||||
*/
|
||||
private function retrieve_required_plugins_data()
|
||||
{
|
||||
$require_plugins = array();
|
||||
$plugins = self::retrieve_plugins_data_in_transient();
|
||||
if (\is_array($plugins)) {
|
||||
if (\count($plugins) > 0) {
|
||||
if (!empty($this->plugin_require)) {
|
||||
foreach ($this->plugin_require as $plugin) {
|
||||
$plugin_file_name = $plugin[self::PLUGIN_INFO_KEY_NAME];
|
||||
$plugin_version = $plugin[self::PLUGIN_INFO_VERSION];
|
||||
if (self::is_wp_plugin_active($plugin_file_name)) {
|
||||
$require_plugins[$plugin_file_name] = $plugins[$plugin_file_name];
|
||||
$require_plugins[$plugin_file_name][self::PLUGIN_INFO_APPEND_PLUGIN_DATA] = $plugin_version;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return $require_plugins;
|
||||
}
|
||||
/**
|
||||
* @param array $notices
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function append_plugin_require_notices($notices)
|
||||
{
|
||||
if (\count($this->plugin_require) > 0) {
|
||||
foreach ($this->plugin_require as $plugin_name => $plugin_info) {
|
||||
$notice = null;
|
||||
if (isset($plugin_info['repository_url'])) {
|
||||
$notice = $this->prepare_plugin_repository_require_notice($plugin_info);
|
||||
} elseif (!self::is_wp_plugin_active($plugin_name)) {
|
||||
$notice = $this->prepare_notice_message(\sprintf(\__('The “%s” plugin cannot run without %s active. Please install and activate %s plugin.', $this->get_text_domain()), \esc_html($this->plugin_name), \esc_html(\basename($plugin_info[self::PLUGIN_INFO_KEY_NICE_NAME])), \esc_html(\basename($plugin_info[self::PLUGIN_INFO_KEY_NICE_NAME]))));
|
||||
}
|
||||
if ($notice !== null) {
|
||||
$notices[] = $notice;
|
||||
}
|
||||
}
|
||||
}
|
||||
return $notices;
|
||||
}
|
||||
/**
|
||||
* Prepares WP install url and injects info about plugin to the WP update engine.
|
||||
*
|
||||
* @param array $plugin_info
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function prepare_plugin_repository_install_url($plugin_info)
|
||||
{
|
||||
$slug = \basename($plugin_info[self::PLUGIN_INFO_KEY_NAME]);
|
||||
$install_url = \self_admin_url('update.php?action=install-plugin&plugin=' . $slug);
|
||||
if (\function_exists('wp_nonce_url') && \function_exists('wp_create_nonce')) {
|
||||
$install_url = \wp_nonce_url($install_url, 'install-plugin_' . $slug);
|
||||
}
|
||||
\add_filter('plugins_api', function ($api, $action, $args) use($plugin_info, $slug) {
|
||||
if ('plugin_information' !== $action || \false !== $api || !isset($args->slug) || $slug !== $args->slug) {
|
||||
return $api;
|
||||
}
|
||||
$api = new \stdClass();
|
||||
$api->name = $plugin_info['nice_name'];
|
||||
// self in closures requires 5.4
|
||||
$api->version = '';
|
||||
$api->download_link = \esc_url($plugin_info['repository_url']);
|
||||
// self in closures requires 5.4
|
||||
return $api;
|
||||
}, 10, 3);
|
||||
return $install_url;
|
||||
}
|
||||
/**
|
||||
* @param array $plugin_info Internal required plugin info data.
|
||||
*
|
||||
* @return string|null Return null if no notice is needed.
|
||||
*/
|
||||
private function prepare_plugin_repository_require_notice($plugin_info)
|
||||
{
|
||||
$name = $plugin_info[self::PLUGIN_INFO_KEY_NAME];
|
||||
$nice_name = $plugin_info[self::PLUGIN_INFO_KEY_NICE_NAME];
|
||||
if (!self::is_wp_plugin_active($name)) {
|
||||
if (!self::is_wp_plugin_installed($name)) {
|
||||
$install_url = $this->prepare_plugin_repository_install_url($plugin_info);
|
||||
return $this->prepare_notice_message(\sprintf(\wp_kses(\__('The “%s” plugin requires free %s plugin. <a href="%s">Install %s →</a>', $this->get_text_domain()), array('a' => array('href' => array()))), $this->plugin_name, $nice_name, \esc_url($install_url), $nice_name));
|
||||
}
|
||||
$activate_url = 'plugins.php?action=activate&plugin=' . \urlencode($plugin_info[self::PLUGIN_INFO_KEY_NAME]) . '&plugin_status=all&paged=1&s';
|
||||
if (\function_exists('wp_create_nonce')) {
|
||||
$activate_url .= '&_wpnonce=' . \urlencode(\wp_create_nonce('activate-plugin_' . $name));
|
||||
}
|
||||
return $this->prepare_notice_message(\sprintf(\wp_kses(\__('The “%s” plugin requires activating %s plugin. <a href="%s">Activate %s →</a>', $this->get_text_domain()), array('a' => array('href' => array()))), $this->plugin_name, $nice_name, \esc_url(\admin_url($activate_url)), $nice_name));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
/**
|
||||
* Checks if plugin is active. Needs to be used in deferred way.
|
||||
*
|
||||
* @param string $plugin_file
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function is_wp_plugin_active($plugin_file)
|
||||
{
|
||||
$active_plugins = (array) \get_option('active_plugins', array());
|
||||
if (\is_multisite()) {
|
||||
$active_plugins = \array_merge($active_plugins, \get_site_option('active_sitewide_plugins', array()));
|
||||
}
|
||||
return \in_array($plugin_file, $active_plugins) || \array_key_exists($plugin_file, $active_plugins);
|
||||
}
|
||||
/**
|
||||
* Checks if plugin is installed. Needs to be enabled in deferred way.
|
||||
*
|
||||
* @param string $plugin_file
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function is_wp_plugin_installed($plugin_file)
|
||||
{
|
||||
$plugins_data = self::retrieve_plugins_data_in_transient();
|
||||
return \array_key_exists($plugin_file, (array) $plugins_data);
|
||||
}
|
||||
/**
|
||||
* @param array $notices
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function append_module_require_notices($notices)
|
||||
{
|
||||
if (\count($this->module_require) > 0) {
|
||||
foreach ($this->module_require as $module_name => $nice_module_name) {
|
||||
if (!self::is_module_active($module_name)) {
|
||||
$notices[] = $this->prepare_notice_message(\sprintf(\__('The “%s” plugin cannot run without %s PHP module installed. Please contact your host and ask them to install %s.', $this->get_text_domain()), \esc_html($this->plugin_name), \esc_html(\basename($nice_module_name)), \esc_html(\basename($nice_module_name))));
|
||||
}
|
||||
}
|
||||
}
|
||||
return $notices;
|
||||
}
|
||||
/**
|
||||
* @param string $name
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function is_module_active($name)
|
||||
{
|
||||
return \extension_loaded($name);
|
||||
}
|
||||
/**
|
||||
* @param array $notices
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function append_settings_require_notices($notices)
|
||||
{
|
||||
if (\count($this->setting_require) > 0) {
|
||||
foreach ($this->setting_require as $setting => $value) {
|
||||
if (!self::is_setting_set($setting, $value)) {
|
||||
$notices[] = $this->prepare_notice_message(\sprintf(\__('The “%s” plugin cannot run without %s PHP setting set to %s. Please contact your host and ask them to set %s.', $this->get_text_domain()), \esc_html($this->plugin_name), \esc_html(\basename($setting)), \esc_html(\basename($value)), \esc_html(\basename($setting))));
|
||||
}
|
||||
}
|
||||
}
|
||||
return $notices;
|
||||
}
|
||||
/**
|
||||
* @param string $name
|
||||
* @param mixed $value
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function is_setting_set($name, $value)
|
||||
{
|
||||
return \ini_get($name) === (string) $value;
|
||||
}
|
||||
/**
|
||||
* @return void
|
||||
*
|
||||
* @deprecated use render_notices or disable_plugin
|
||||
*/
|
||||
public function disable_plugin_render_notice()
|
||||
{
|
||||
\add_action(self::HOOK_ADMIN_NOTICES_ACTION, array($this, 'handle_render_notices_action'));
|
||||
}
|
||||
/**
|
||||
* Renders requirement notices in admin panel
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function render_notices()
|
||||
{
|
||||
\add_action(self::HOOK_ADMIN_NOTICES_ACTION, array($this, 'handle_render_notices_action'));
|
||||
}
|
||||
/**
|
||||
* Renders requirement notices in admin panel
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function disable_plugin()
|
||||
{
|
||||
\add_action(self::HOOK_ADMIN_NOTICES_ACTION, array($this, 'handle_deactivate_action'));
|
||||
}
|
||||
/**
|
||||
* @return void
|
||||
* @internal Do not use as public. Public only for wp action.
|
||||
*
|
||||
*/
|
||||
public function handle_deactivate_action()
|
||||
{
|
||||
if (isset($this->plugin_file)) {
|
||||
\deactivate_plugins(\plugin_basename($this->plugin_file));
|
||||
\delete_transient(self::PLUGIN_INFO_TRANSIENT_NAME);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Triggers the transient delete after plugin deactivated
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function transient_delete_on_plugin_version_changed()
|
||||
{
|
||||
\add_action(self::HOOK_PLUGIN_DEACTIVATED_ACTION, array($this, 'handle_transient_delete_action'));
|
||||
\add_action(self::HOOK_PLUGIN_ACTIVATED_ACTION, array($this, 'handle_transient_delete_action'));
|
||||
}
|
||||
/**
|
||||
* Handles the transient delete
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function handle_transient_delete_action()
|
||||
{
|
||||
\delete_transient(self::PLUGIN_INFO_TRANSIENT_NAME);
|
||||
}
|
||||
/**
|
||||
* Should be called as WordPress action
|
||||
*
|
||||
* @return void
|
||||
* @internal Do not use as public. Public only for wp action.
|
||||
*
|
||||
*/
|
||||
public function handle_render_notices_action()
|
||||
{
|
||||
foreach ($this->notices as $notice) {
|
||||
echo $notice;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
<?php
|
||||
|
||||
namespace FcfVendor;
|
||||
|
||||
if (!\class_exists('FcfVendor\\Basic_Requirement_Checker')) {
|
||||
require_once __DIR__ . '/Basic_Requirement_Checker.php';
|
||||
}
|
||||
if (!\class_exists('FcfVendor\\WPDesk_Basic_Requirement_Checker_With_Update_Disable')) {
|
||||
require_once __DIR__ . '/Basic_Requirement_Checker_With_Update_Disable.php';
|
||||
}
|
||||
/**
|
||||
* Falicitates createion of requirement checker
|
||||
*/
|
||||
class WPDesk_Basic_Requirement_Checker_Factory
|
||||
{
|
||||
const LIBRARY_TEXT_DOMAIN = 'flexible-checkout-fields';
|
||||
/**
|
||||
* Creates a simplest possible version of requirement checker.
|
||||
*
|
||||
* @param string $plugin_file
|
||||
* @param string $plugin_name
|
||||
* @param string|null $text_domain Text domain to use. If null try to use library text domain.
|
||||
*
|
||||
* @return WPDesk_Requirement_Checker
|
||||
*/
|
||||
public function create_requirement_checker($plugin_file, $plugin_name, $text_domain = null)
|
||||
{
|
||||
return new \FcfVendor\WPDesk_Basic_Requirement_Checker($plugin_file, $plugin_name, $text_domain, null, null);
|
||||
}
|
||||
/**
|
||||
* Creates a requirement checker according to given requirements array info.
|
||||
*
|
||||
* @param string $plugin_file
|
||||
* @param string $plugin_name
|
||||
* @param string $text_domain Text domain to use. If null try to use library text domain.
|
||||
* @param array $requirements Requirements array as given by plugin.
|
||||
*
|
||||
* @return WPDesk_Requirement_Checker
|
||||
*/
|
||||
public function create_from_requirement_array($plugin_file, $plugin_name, $requirements, $text_domain = null)
|
||||
{
|
||||
$requirements_checker = new \FcfVendor\WPDesk_Basic_Requirement_Checker_With_Update_Disable($plugin_file, $plugin_name, $text_domain, $requirements['php'], $requirements['wp']);
|
||||
if (isset($requirements['plugins'])) {
|
||||
foreach ($requirements['plugins'] as $requirement) {
|
||||
$version = isset($requirement['version']) ? $requirement['version'] : null;
|
||||
$requirements_checker->add_plugin_require($requirement['name'], $requirement['nice_name'], $version);
|
||||
}
|
||||
$requirements_checker->transient_delete_on_plugin_version_changed();
|
||||
}
|
||||
if (isset($requirements['repo_plugins'])) {
|
||||
foreach ($requirements['repo_plugins'] as $requirement) {
|
||||
$requirements_checker->add_plugin_repository_require($requirement['name'], $requirement['version'], $requirement['nice_name']);
|
||||
}
|
||||
}
|
||||
if (isset($requirements['modules'])) {
|
||||
foreach ($requirements['modules'] as $requirement) {
|
||||
$requirements_checker->add_php_module_require($requirement['name'], $requirement['nice_name']);
|
||||
}
|
||||
}
|
||||
return $requirements_checker;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
<?php
|
||||
|
||||
namespace FcfVendor;
|
||||
|
||||
if (!\class_exists('FcfVendor\\WPDesk_Basic_Requirement_Checker')) {
|
||||
require_once __DIR__ . '/Basic_Requirement_Checker.php';
|
||||
}
|
||||
if (!\class_exists('FcfVendor\\WPDesk_Basic_Requirement_Checker_With_Update_Disable')) {
|
||||
/**
|
||||
* Checks requirements for plugin. When required plugin is updated right now, then say that requirements are not met temporary.
|
||||
* have to be compatible with PHP 5.2.x
|
||||
*/
|
||||
class WPDesk_Basic_Requirement_Checker_With_Update_Disable extends \FcfVendor\WPDesk_Basic_Requirement_Checker
|
||||
{
|
||||
/**
|
||||
* Returns true if are requirements are met.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function are_requirements_met()
|
||||
{
|
||||
$has_been_met = parent::are_requirements_met();
|
||||
if (!$has_been_met) {
|
||||
return $has_been_met;
|
||||
}
|
||||
foreach ($this->plugin_require as $name => $plugin_info) {
|
||||
if ($this->is_currently_updated($name)) {
|
||||
$nice_name = $plugin_info[self::PLUGIN_INFO_KEY_NICE_NAME];
|
||||
$this->notices[] = $this->prepare_notice_message(\sprintf(\__('The “%s” plugin is temporarily disabled since the required %s plugin is being upgraded.', $this->get_text_domain()), $this->plugin_name, $nice_name, $nice_name));
|
||||
}
|
||||
}
|
||||
return \count($this->notices) === 0;
|
||||
}
|
||||
/**
|
||||
* Is plugin upgrading right now?
|
||||
*
|
||||
* @param string $name
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function is_currently_updated($name)
|
||||
{
|
||||
return isset($_GET['action']) && $_GET['action'] === 'upgrade-plugin' && $_GET['plugin'] === $name;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
<?php
|
||||
|
||||
namespace FcfVendor;
|
||||
|
||||
/**
|
||||
* Checks requirements for plugin
|
||||
* have to be compatible with PHP 5.2.x
|
||||
*/
|
||||
interface WPDesk_Requirement_Checker
|
||||
{
|
||||
/**
|
||||
* @param string $version
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function set_min_php_require($version);
|
||||
/**
|
||||
* @param string $version
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function set_min_wp_require($version);
|
||||
/**
|
||||
* @param string $version
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function set_min_wc_require($version);
|
||||
/**
|
||||
* @param $version
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function set_min_openssl_require($version);
|
||||
/**
|
||||
* @param string $plugin_name
|
||||
* @param string $nice_plugin_name Nice plugin name for better looks in notice
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function add_plugin_require($plugin_name, $nice_plugin_name = null);
|
||||
/**
|
||||
* @param string $module_name
|
||||
* @param string $nice_name Nice module name for better looks in notice
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function add_php_module_require($module_name, $nice_name = null);
|
||||
/**
|
||||
* @param string $setting
|
||||
* @param mixed $value
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function add_php_setting_require($setting, $value);
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function are_requirements_met();
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function disable_plugin_render_notice();
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function render_notices();
|
||||
/**
|
||||
* Renders requirement notices in admin panel
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function disable_plugin();
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
<?php
|
||||
|
||||
namespace FcfVendor;
|
||||
|
||||
interface WPDesk_Requirement_Checker_Factory
|
||||
{
|
||||
/**
|
||||
* @param $plugin_file
|
||||
* @param $plugin_name
|
||||
* @param $text_domain
|
||||
* @param $php_version
|
||||
* @param $wp_version
|
||||
*
|
||||
* @return WPDesk_Requirement_Checker
|
||||
*/
|
||||
public function create_requirement_checker($plugin_file, $plugin_name, $text_domain);
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
{
|
||||
"name": "wpdesk\/wp-builder",
|
||||
"authors": [
|
||||
{
|
||||
"name": "Krzysiek",
|
||||
"email": "krzysiek@wpdesk.pl"
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"php": ">=5.5"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit\/phpunit": "<7",
|
||||
"wp-coding-standards\/wpcs": "^0.14.1",
|
||||
"squizlabs\/php_codesniffer": "^3.0.2",
|
||||
"mockery\/mockery": "*",
|
||||
"10up\/wp_mock": "*",
|
||||
"wimg\/php-compatibility": "^8"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"FcfVendor\\WPDesk\\PluginBuilder\\": "src\/"
|
||||
},
|
||||
"classmap": [
|
||||
"src\/Plugin\/WithoutNamespace"
|
||||
]
|
||||
},
|
||||
"autoload-dev": {},
|
||||
"scripts": {
|
||||
"phpcs": "phpcs",
|
||||
"phpunit-unit": "phpunit --configuration phpunit-unit.xml --coverage-text --colors=never",
|
||||
"phpunit-unit-fast": "phpunit --configuration phpunit-unit.xml --no-coverage",
|
||||
"phpunit-integration": "phpunit --configuration phpunit-integration.xml --coverage-text --colors=never",
|
||||
"phpunit-integration-fast": "phpunit --configuration phpunit-integration.xml --no-coverage"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
namespace FcfVendor\WPDesk\PluginBuilder\BuildDirector;
|
||||
|
||||
use FcfVendor\WPDesk\PluginBuilder\Builder\AbstractBuilder;
|
||||
use FcfVendor\WPDesk\PluginBuilder\Plugin\AbstractPlugin;
|
||||
use FcfVendor\WPDesk\PluginBuilder\Storage\StorageFactory;
|
||||
class LegacyBuildDirector
|
||||
{
|
||||
/** @var AbstractBuilder */
|
||||
private $builder;
|
||||
public function __construct(\FcfVendor\WPDesk\PluginBuilder\Builder\AbstractBuilder $builder)
|
||||
{
|
||||
$this->builder = $builder;
|
||||
}
|
||||
/**
|
||||
* Builds plugin
|
||||
*/
|
||||
public function build_plugin()
|
||||
{
|
||||
$this->builder->build_plugin();
|
||||
$this->builder->init_plugin();
|
||||
$storage = new \FcfVendor\WPDesk\PluginBuilder\Storage\StorageFactory();
|
||||
$this->builder->store_plugin($storage->create_storage());
|
||||
}
|
||||
/**
|
||||
* Returns built plugin
|
||||
*
|
||||
* @return AbstractPlugin
|
||||
*/
|
||||
public function get_plugin()
|
||||
{
|
||||
return $this->builder->get_plugin();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
<?php
|
||||
|
||||
namespace FcfVendor\WPDesk\PluginBuilder\Builder;
|
||||
|
||||
use FcfVendor\WPDesk\PluginBuilder\Plugin\AbstractPlugin;
|
||||
use FcfVendor\WPDesk\PluginBuilder\Storage\PluginStorage;
|
||||
abstract class AbstractBuilder
|
||||
{
|
||||
/**
|
||||
* Create plugin class
|
||||
*/
|
||||
public function build_plugin()
|
||||
{
|
||||
}
|
||||
/**
|
||||
* Store plugin class in some kind of storage
|
||||
*/
|
||||
public function store_plugin(\FcfVendor\WPDesk\PluginBuilder\Storage\PluginStorage $storage)
|
||||
{
|
||||
}
|
||||
/**
|
||||
* Init plugin internal structure
|
||||
*/
|
||||
public function init_plugin()
|
||||
{
|
||||
}
|
||||
/**
|
||||
* Return built plugin
|
||||
* @return AbstractPlugin
|
||||
*/
|
||||
abstract function get_plugin();
|
||||
/**
|
||||
* Set settings class in plugin
|
||||
*
|
||||
* @param $settings
|
||||
*/
|
||||
public function set_settings($settings)
|
||||
{
|
||||
}
|
||||
/**
|
||||
* Set view class in plugin
|
||||
*
|
||||
* @param $view
|
||||
*/
|
||||
public function set_view($view)
|
||||
{
|
||||
}
|
||||
/**
|
||||
* Set tracker class in plugin
|
||||
*
|
||||
* @param $tracker
|
||||
*/
|
||||
public function set_tracker($tracker)
|
||||
{
|
||||
}
|
||||
/**
|
||||
* Set helper class in plugin
|
||||
*
|
||||
* @param $helper
|
||||
*/
|
||||
public function set_helper($helper)
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
<?php
|
||||
|
||||
namespace FcfVendor\WPDesk\PluginBuilder\Builder;
|
||||
|
||||
use FcfVendor\WPDesk\PluginBuilder\Plugin\AbstractPlugin;
|
||||
use FcfVendor\WPDesk\PluginBuilder\Plugin\ActivationAware;
|
||||
use FcfVendor\WPDesk\PluginBuilder\Storage\PluginStorage;
|
||||
/**
|
||||
* Builder that have info about activations
|
||||
*
|
||||
* Warning: We can't extend InfoBuilder.php as some old plugins(without wp-flow) will load the old version od InfoBuilder class that have private plugin property.
|
||||
*
|
||||
* @package WPDesk\PluginBuilder\Builder
|
||||
*/
|
||||
class InfoActivationBuilder extends \FcfVendor\WPDesk\PluginBuilder\Builder\AbstractBuilder
|
||||
{
|
||||
const FILTER_PLUGIN_CLASS = 'wp_builder_plugin_class';
|
||||
const HOOK_BEFORE_PLUGIN_INIT = 'wp_builder_before_plugin_init';
|
||||
const HOOK_AFTER_PLUGIN_INIT = 'wp_builder_before_init';
|
||||
/** @var AbstractPlugin */
|
||||
private $plugin;
|
||||
/** @var \WPDesk_Buildable */
|
||||
private $info;
|
||||
/** @var string */
|
||||
protected $storage_id;
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
private $is_active;
|
||||
/**
|
||||
* @param \WPDesk_Buildable $info
|
||||
* @param bool $is_active
|
||||
*/
|
||||
public function __construct(\FcfVendor\WPDesk_Buildable $info, $is_active)
|
||||
{
|
||||
$this->info = $info;
|
||||
$this->storage_id = $info->get_class_name();
|
||||
$this->is_active = $is_active;
|
||||
}
|
||||
/**
|
||||
* Builds instance of plugin
|
||||
*/
|
||||
public function build_plugin()
|
||||
{
|
||||
$class_name = \apply_filters(self::FILTER_PLUGIN_CLASS, $this->info->get_class_name());
|
||||
/** @var AbstractPlugin $plugin */
|
||||
$this->plugin = new $class_name($this->info);
|
||||
if ($this->plugin instanceof \FcfVendor\WPDesk\PluginBuilder\Plugin\ActivationAware && $this->is_active) {
|
||||
$this->plugin->set_active();
|
||||
}
|
||||
return $this->plugin;
|
||||
}
|
||||
public function store_plugin(\FcfVendor\WPDesk\PluginBuilder\Storage\PluginStorage $storage)
|
||||
{
|
||||
$storage->add_to_storage($this->storage_id, $this->plugin);
|
||||
}
|
||||
public function init_plugin()
|
||||
{
|
||||
\do_action(self::HOOK_BEFORE_PLUGIN_INIT, $this->plugin);
|
||||
$this->plugin->init();
|
||||
\do_action(self::HOOK_AFTER_PLUGIN_INIT, $this->plugin);
|
||||
}
|
||||
/**
|
||||
* @return AbstractPlugin
|
||||
*/
|
||||
public function get_plugin()
|
||||
{
|
||||
return $this->plugin;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
<?php
|
||||
|
||||
namespace FcfVendor\WPDesk\PluginBuilder\Builder;
|
||||
|
||||
use FcfVendor\WPDesk\PluginBuilder\Plugin\AbstractPlugin;
|
||||
use FcfVendor\WPDesk\PluginBuilder\Storage\PluginStorage;
|
||||
/**
|
||||
* @deprecated Should not be used as some old plugins are using it and we can't touch this.
|
||||
*
|
||||
* @package WPDesk\PluginBuilder\Builder
|
||||
*/
|
||||
class InfoBuilder extends \FcfVendor\WPDesk\PluginBuilder\Builder\AbstractBuilder
|
||||
{
|
||||
const FILTER_PLUGIN_CLASS = 'wp_builder_plugin_class';
|
||||
const HOOK_BEFORE_PLUGIN_INIT = 'wp_builder_before_plugin_init';
|
||||
const HOOK_AFTER_PLUGIN_INIT = 'wp_builder_before_init';
|
||||
/** @var AbstractPlugin */
|
||||
private $plugin;
|
||||
/** @var \WPDesk_Buildable */
|
||||
private $info;
|
||||
/** @var string */
|
||||
protected $storage_id;
|
||||
public function __construct(\FcfVendor\WPDesk_Buildable $info)
|
||||
{
|
||||
$this->info = $info;
|
||||
$this->storage_id = $info->get_class_name();
|
||||
}
|
||||
/**
|
||||
* Builds instance of plugin
|
||||
*/
|
||||
public function build_plugin()
|
||||
{
|
||||
$class_name = \apply_filters(self::FILTER_PLUGIN_CLASS, $this->info->get_class_name());
|
||||
/** @var AbstractPlugin $plugin */
|
||||
$this->plugin = new $class_name($this->info);
|
||||
}
|
||||
public function store_plugin(\FcfVendor\WPDesk\PluginBuilder\Storage\PluginStorage $storage)
|
||||
{
|
||||
$storage->add_to_storage($this->storage_id, $this->plugin);
|
||||
}
|
||||
public function init_plugin()
|
||||
{
|
||||
\do_action(self::HOOK_BEFORE_PLUGIN_INIT, $this->plugin);
|
||||
$this->plugin->init();
|
||||
\do_action(self::HOOK_AFTER_PLUGIN_INIT, $this->plugin);
|
||||
}
|
||||
/**
|
||||
* @return AbstractPlugin
|
||||
*/
|
||||
public function get_plugin()
|
||||
{
|
||||
return $this->plugin;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,203 @@
|
||||
<?php
|
||||
|
||||
namespace FcfVendor\WPDesk\PluginBuilder\Plugin;
|
||||
|
||||
/**
|
||||
* Base plugin with most basic functionalities used by every WPDesk plugin.
|
||||
*
|
||||
*
|
||||
* Known issues:
|
||||
*
|
||||
* The class name is too generic but can't be changed as it would introduce a major incompatibility for most of the plugins.
|
||||
* The $plugin_url, $docs_url and most other fields should be removed as they only litter the place but for compatibility reasons we can't do it right now.
|
||||
* Hook methods should be moved to external classes but for compatibility reasons we can't do it right now.
|
||||
*/
|
||||
abstract class AbstractPlugin extends \FcfVendor\WPDesk\PluginBuilder\Plugin\SlimPlugin
|
||||
{
|
||||
/**
|
||||
* Most info about plugin internals.
|
||||
*
|
||||
* @var \WPDesk_Plugin_Info
|
||||
*/
|
||||
protected $plugin_info;
|
||||
/**
|
||||
* Unique string for this plugin in [a-z_]+ format.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $plugin_namespace;
|
||||
/**
|
||||
* Absolute URL to the plugin dir.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $plugin_url;
|
||||
/**
|
||||
* Absolute URL to the plugin docs.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $docs_url;
|
||||
/**
|
||||
* Absolute URL to the plugin settings url.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $settings_url;
|
||||
/**
|
||||
* Support URL.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $support_url;
|
||||
/**
|
||||
* AbstractPlugin constructor.
|
||||
*
|
||||
* @param \WPDesk_Plugin_Info $plugin_info
|
||||
*/
|
||||
public function __construct($plugin_info)
|
||||
{
|
||||
$this->plugin_info = $plugin_info;
|
||||
$this->plugin_namespace = \strtolower($plugin_info->get_plugin_dir());
|
||||
$this->plugin_url = $this->plugin_info->get_plugin_url();
|
||||
$this->init_base_variables();
|
||||
}
|
||||
/**
|
||||
* Initialize internal state of the plugin.
|
||||
*
|
||||
* @return void
|
||||
* @deprecated Just use __construct to initialize plugin internal state.
|
||||
*
|
||||
*/
|
||||
public function init_base_variables()
|
||||
{
|
||||
}
|
||||
/**
|
||||
* Initializes plugin external state.
|
||||
*
|
||||
* The plugin internal state is initialized in the constructor and the plugin should be internally consistent after creation.
|
||||
* The external state includes hooks execution, communication with other plugins, integration with WC etc.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function init()
|
||||
{
|
||||
$this->hooks();
|
||||
}
|
||||
/**
|
||||
* Returns absolute path to the plugin dir.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_plugin_file_path()
|
||||
{
|
||||
return $this->plugin_info->get_plugin_file_name();
|
||||
}
|
||||
/**
|
||||
* Returns plugin text domain.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_text_domain()
|
||||
{
|
||||
return $this->plugin_info->get_text_domain();
|
||||
}
|
||||
/**
|
||||
* Returns unique string for plugin in [a-z_]+ format. Can be used as plugin id in various places like plugin slug etc.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_namespace()
|
||||
{
|
||||
return $this->plugin_namespace;
|
||||
}
|
||||
/**
|
||||
* Returns plugin absolute URL.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_plugin_url()
|
||||
{
|
||||
return \esc_url(\trailingslashit($this->plugin_url));
|
||||
}
|
||||
/**
|
||||
* Returns plugin absolute URL to dir with front end assets.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_plugin_assets_url()
|
||||
{
|
||||
return \esc_url(\trailingslashit($this->get_plugin_url() . 'assets'));
|
||||
}
|
||||
/**
|
||||
* @return $this
|
||||
* @deprecated For backward compatibility.
|
||||
*
|
||||
*/
|
||||
public function get_plugin()
|
||||
{
|
||||
return $this;
|
||||
}
|
||||
/**
|
||||
* Integrate with WordPress and with other plugins using action/filter system.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function hooks()
|
||||
{
|
||||
\add_action('admin_enqueue_scripts', [$this, 'admin_enqueue_scripts']);
|
||||
\add_action('wp_enqueue_scripts', [$this, 'wp_enqueue_scripts']);
|
||||
\add_action('plugins_loaded', [$this, 'load_plugin_text_domain']);
|
||||
\add_filter('plugin_action_links_' . \plugin_basename($this->get_plugin_file_path()), [$this, 'links_filter']);
|
||||
}
|
||||
/**
|
||||
* Initialize plugin test domain. This is a hook function. Do not execute directly.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function load_plugin_text_domain()
|
||||
{
|
||||
\load_plugin_textdomain($this->get_text_domain(), \false, $this->get_namespace() . '/lang/');
|
||||
}
|
||||
/**
|
||||
* Append JS scripts in the WordPress admin panel. This is a hook function. Do not execute directly.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function admin_enqueue_scripts()
|
||||
{
|
||||
}
|
||||
/**
|
||||
* Append JS scripts in WordPress. This is a hook function. Do not execute directly.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function wp_enqueue_scripts()
|
||||
{
|
||||
}
|
||||
/**
|
||||
* Initialize plugin admin links. This is a hook function. Do not execute directly.
|
||||
*
|
||||
* @param string[] $links
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
public function links_filter($links)
|
||||
{
|
||||
$support_link = \get_locale() === 'pl_PL' ? 'https://www.wpdesk.pl/support/' : 'https://www.wpdesk.net/support';
|
||||
if ($this->support_url) {
|
||||
$support_link = $this->support_url;
|
||||
}
|
||||
$plugin_links = ['<a target="_blank" href="' . $support_link . '">' . \__('Support', $this->get_text_domain()) . '</a>'];
|
||||
$links = \array_merge($plugin_links, $links);
|
||||
if ($this->docs_url) {
|
||||
$plugin_links = ['<a target="_blank" href="' . $this->docs_url . '">' . \__('Docs', $this->get_text_domain()) . '</a>'];
|
||||
$links = \array_merge($plugin_links, $links);
|
||||
}
|
||||
if ($this->settings_url) {
|
||||
$plugin_links = ['<a href="' . $this->settings_url . '">' . \__('Settings', $this->get_text_domain()) . '</a>'];
|
||||
$links = \array_merge($plugin_links, $links);
|
||||
}
|
||||
return $links;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
namespace FcfVendor\WPDesk\PluginBuilder\Plugin;
|
||||
|
||||
/**
|
||||
* Tag the plugin with this ingterface to hook it to the WordPress activation hook.
|
||||
*
|
||||
* Note: works from plugin flow ^2.2.
|
||||
*
|
||||
* @package WPDesk\PluginBuilder\Plugin
|
||||
*/
|
||||
interface Activateable
|
||||
{
|
||||
/**
|
||||
* Plugin activated in WordPress. Do not execute directly.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function activate();
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
namespace FcfVendor\WPDesk\PluginBuilder\Plugin;
|
||||
|
||||
/**
|
||||
* It means that this class is should know about SUBSCRIPTION activation
|
||||
*
|
||||
* @package WPDesk\PluginBuilder\Plugin
|
||||
*/
|
||||
interface ActivationAware
|
||||
{
|
||||
/**
|
||||
* Set the activation flag to true
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function set_active();
|
||||
/**
|
||||
* Is subscription active?
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function is_active();
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
<?php
|
||||
|
||||
namespace FcfVendor\WPDesk\PluginBuilder\Plugin;
|
||||
|
||||
/**
|
||||
* @deprecated nobody uses it :) And also this library is not a place for this class
|
||||
*
|
||||
* @package WPDesk\PluginBuilder\Plugin
|
||||
*/
|
||||
class ActivationTracker
|
||||
{
|
||||
/**
|
||||
* Namespace.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $namespace;
|
||||
/**
|
||||
* ActivationTracker constructor.
|
||||
*
|
||||
* @param string $namespace Namespace for settings.
|
||||
*/
|
||||
public function __construct($namespace)
|
||||
{
|
||||
$this->namespace = $namespace;
|
||||
}
|
||||
/**
|
||||
* Option name for date storage
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function get_option_name_activation_date()
|
||||
{
|
||||
return $this->namespace . '_activation';
|
||||
}
|
||||
/**
|
||||
* Returns activation date and sets it if were not set before
|
||||
*
|
||||
* @return int unix timestamp for activation datetime
|
||||
*/
|
||||
public function get_activation_date()
|
||||
{
|
||||
$activation_date = \get_option($this->get_option_name_activation_date());
|
||||
if (empty($activation_date)) {
|
||||
return $this->touch_activation_date();
|
||||
}
|
||||
return \intval($activation_date);
|
||||
}
|
||||
/**
|
||||
* Was activation more than two weeks before today
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function is_activated_more_than_two_weeks()
|
||||
{
|
||||
$two_weeks = 60 * 60 * 24 * 7 * 2;
|
||||
return $this->get_activation_date() + $two_weeks < \time();
|
||||
}
|
||||
/**
|
||||
* Sets activatiion date for today
|
||||
*
|
||||
* @return int unit timestamp for now
|
||||
*/
|
||||
public function touch_activation_date()
|
||||
{
|
||||
$now = \time();
|
||||
\update_option($this->get_option_name_activation_date(), $now);
|
||||
return $now;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
namespace FcfVendor\WPDesk\PluginBuilder\Plugin;
|
||||
|
||||
/**
|
||||
* Something that can be instantiated/hooked conditionally.
|
||||
*
|
||||
* @see https://github.com/mwpd/basic-scaffold/blob/master/src/Infrastructure/Conditional.php by Alain Schlesser
|
||||
*
|
||||
* @package WPDesk\PluginBuilder\Plugin
|
||||
*/
|
||||
interface Conditional
|
||||
{
|
||||
/**
|
||||
* Check whether the conditional object is currently needed.
|
||||
*
|
||||
* @return bool Whether the conditional object is needed.
|
||||
*/
|
||||
public static function is_needed();
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
namespace FcfVendor\WPDesk\PluginBuilder\Plugin;
|
||||
|
||||
/**
|
||||
* Tag the plugin with this ingterface to hook it to the WordPress deactivation hook.
|
||||
*
|
||||
* Note: works from plugin flow ^2.2.
|
||||
*
|
||||
* @package WPDesk\PluginBuilder\Plugin
|
||||
*/
|
||||
interface Deactivateable
|
||||
{
|
||||
/**
|
||||
* Plugin deactivate in WordPress. Do not execute directly.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function deactivate();
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
namespace FcfVendor\WPDesk\PluginBuilder\Plugin;
|
||||
|
||||
interface Hookable
|
||||
{
|
||||
/**
|
||||
* Init hooks (actions and filters).
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function hooks();
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
namespace FcfVendor\WPDesk\PluginBuilder\Plugin;
|
||||
|
||||
interface HookableCollection extends \FcfVendor\WPDesk\PluginBuilder\Plugin\Hookable
|
||||
{
|
||||
/**
|
||||
* Add hookable object.
|
||||
*
|
||||
* @param Hookable|HookablePluginDependant $hookable_object Hookable object.
|
||||
*/
|
||||
public function add_hookable(\FcfVendor\WPDesk\PluginBuilder\Plugin\Hookable $hookable_object);
|
||||
/**
|
||||
* Get hookable instance.
|
||||
*
|
||||
* @param string $class_name Class name.
|
||||
*
|
||||
* @return false|Hookable
|
||||
*/
|
||||
public function get_hookable_instance_by_class_name($class_name);
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
<?php
|
||||
|
||||
namespace FcfVendor\WPDesk\PluginBuilder\Plugin;
|
||||
|
||||
trait HookableParent
|
||||
{
|
||||
/**
|
||||
* Hookable objects.
|
||||
*
|
||||
* @var array[Hookable]
|
||||
*/
|
||||
private $hookable_objects = array();
|
||||
/**
|
||||
* Add hookable object.
|
||||
*
|
||||
* @param Hookable|HookablePluginDependant $hookable_object Hookable object.
|
||||
*/
|
||||
public function add_hookable(\FcfVendor\WPDesk\PluginBuilder\Plugin\Hookable $hookable_object)
|
||||
{
|
||||
if ($hookable_object instanceof \FcfVendor\WPDesk\PluginBuilder\Plugin\HookablePluginDependant) {
|
||||
$hookable_object->set_plugin($this);
|
||||
}
|
||||
$this->hookable_objects[] = $hookable_object;
|
||||
}
|
||||
/**
|
||||
* Get hookable instance.
|
||||
*
|
||||
* @param string $class_name Class name.
|
||||
*
|
||||
* @return false|Hookable
|
||||
*/
|
||||
public function get_hookable_instance_by_class_name($class_name)
|
||||
{
|
||||
foreach ($this->hookable_objects as $hookable_object) {
|
||||
if ($hookable_object instanceof $class_name) {
|
||||
return $hookable_object;
|
||||
}
|
||||
}
|
||||
return \false;
|
||||
}
|
||||
/**
|
||||
* Run hooks method on all hookable objects.
|
||||
*/
|
||||
protected function hooks_on_hookable_objects()
|
||||
{
|
||||
/** @var Hookable $hookable_object $hookable_object */
|
||||
foreach ($this->hookable_objects as $hookable_object) {
|
||||
if ($hookable_object instanceof \FcfVendor\WPDesk\PluginBuilder\Plugin\Conditional) {
|
||||
if ($hookable_object::is_needed()) {
|
||||
$hookable_object->hooks();
|
||||
}
|
||||
} else {
|
||||
$hookable_object->hooks();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
namespace FcfVendor\WPDesk\PluginBuilder\Plugin;
|
||||
|
||||
interface HookablePluginDependant extends \FcfVendor\WPDesk\PluginBuilder\Plugin\Hookable
|
||||
{
|
||||
/**
|
||||
* Set Plugin.
|
||||
*
|
||||
* @param AbstractPlugin $plugin Plugin.
|
||||
*
|
||||
* @return null
|
||||
*/
|
||||
public function set_plugin(\FcfVendor\WPDesk\PluginBuilder\Plugin\AbstractPlugin $plugin);
|
||||
/**
|
||||
* Get plugin.
|
||||
*
|
||||
* @return AbstractPlugin.
|
||||
*/
|
||||
public function get_plugin();
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
namespace FcfVendor\WPDesk\PluginBuilder\Plugin;
|
||||
|
||||
/**
|
||||
* @package WPDesk\PluginBuilder\Plugin
|
||||
*/
|
||||
trait PluginAccess
|
||||
{
|
||||
/**
|
||||
* Plugin.
|
||||
*
|
||||
* @var AbstractPlugin
|
||||
*/
|
||||
private $plugin;
|
||||
/**
|
||||
* Set plugin.
|
||||
*
|
||||
* @param AbstractPlugin $plugin Plugin.
|
||||
*/
|
||||
public function set_plugin(\FcfVendor\WPDesk\PluginBuilder\Plugin\AbstractPlugin $plugin)
|
||||
{
|
||||
$this->plugin = $plugin;
|
||||
}
|
||||
/**
|
||||
* Get plugin.
|
||||
*
|
||||
* @return AbstractPlugin
|
||||
*/
|
||||
public function get_plugin()
|
||||
{
|
||||
return $this->plugin;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
namespace FcfVendor\WPDesk\PluginBuilder\Plugin;
|
||||
|
||||
/**
|
||||
* Most clean plugin class with only most important details.
|
||||
*/
|
||||
abstract class SlimPlugin implements \FcfVendor\WPDesk_Translatable
|
||||
{
|
||||
/**
|
||||
* Initializes plugin external state.
|
||||
*
|
||||
* The plugin internal state is initialized in the constructor and the plugin should be internally consistent after creation.
|
||||
* The external state includes hooks execution, communication with other plugins, integration with WC etc.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public abstract function init();
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
<?php
|
||||
|
||||
namespace FcfVendor\WPDesk\PluginBuilder\Plugin;
|
||||
|
||||
/**
|
||||
* @deprecated Use wpdesk/wp-view
|
||||
*
|
||||
* @package WPDesk\PluginBuilder\Plugin
|
||||
*/
|
||||
trait TemplateLoad
|
||||
{
|
||||
/**
|
||||
* Plugin path.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $plugin_path;
|
||||
/**
|
||||
* Template path.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $template_path;
|
||||
/**
|
||||
* Init base variables for plugin
|
||||
*/
|
||||
public function init_template_base_variables()
|
||||
{
|
||||
$this->plugin_path = $this->plugin_info->get_plugin_dir();
|
||||
$this->template_path = $this->plugin_info->get_text_domain();
|
||||
}
|
||||
/**
|
||||
* Renders end returns selected template
|
||||
*
|
||||
* @param string $name Name of the template.
|
||||
* @param string $path Additional inner path to the template.
|
||||
* @param array $args args Accessible from template.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function load_template($name, $path = '', $args = array())
|
||||
{
|
||||
$plugin_template_path = \trailingslashit($this->plugin_path) . 'templates/';
|
||||
// Look within passed path within the theme - this is priority.
|
||||
$template = \locate_template(array(\trailingslashit($this->get_template_path()) . \trailingslashit($path) . $name . '.php'));
|
||||
if (!$template) {
|
||||
$template = $plugin_template_path . \trailingslashit($path) . $name . '.php';
|
||||
}
|
||||
\extract($args);
|
||||
\ob_start();
|
||||
include $template;
|
||||
return \ob_get_clean();
|
||||
}
|
||||
/**
|
||||
* Get template path.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_template_path()
|
||||
{
|
||||
return \trailingslashit($this->template_path);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
<?php
|
||||
|
||||
namespace FcfVendor;
|
||||
|
||||
/**
|
||||
* Have info about what class should be built by WPDesk_Builder
|
||||
*
|
||||
* have to be compatible with PHP 5.2.x
|
||||
*/
|
||||
interface WPDesk_Buildable
|
||||
{
|
||||
/** @return string */
|
||||
public function get_class_name();
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
namespace FcfVendor;
|
||||
|
||||
if (!\interface_exists('FcfVendor\\WPDesk_Translatable')) {
|
||||
require_once __DIR__ . '/Translatable.php';
|
||||
}
|
||||
/**
|
||||
* Have MUST HAVE info for plugin instantion
|
||||
*
|
||||
* have to be compatible with PHP 5.2.x
|
||||
*/
|
||||
interface WPDesk_Has_Plugin_Info extends \FcfVendor\WPDesk_Translatable
|
||||
{
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function get_plugin_file_name();
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function get_plugin_dir();
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function get_version();
|
||||
}
|
||||
@@ -0,0 +1,165 @@
|
||||
<?php
|
||||
|
||||
namespace FcfVendor;
|
||||
|
||||
if (!\interface_exists('FcfVendor\\WPDesk_Translatable')) {
|
||||
require_once __DIR__ . '/Translatable.php';
|
||||
}
|
||||
if (!\interface_exists('FcfVendor\\WPDesk_Buildable')) {
|
||||
require_once __DIR__ . '/Buildable.php';
|
||||
}
|
||||
if (!\interface_exists('FcfVendor\\WPDesk_Has_Plugin_Info')) {
|
||||
require_once __DIR__ . '/Has_Plugin_Info.php';
|
||||
}
|
||||
/**
|
||||
* Structure with core info about plugin
|
||||
*
|
||||
* have to be compatible with PHP 5.2.x
|
||||
*/
|
||||
class WPDesk_Plugin_Info implements \FcfVendor\WPDesk_Translatable, \FcfVendor\WPDesk_Buildable, \FcfVendor\WPDesk_Has_Plugin_Info
|
||||
{
|
||||
/** @var string */
|
||||
private $plugin_file_name;
|
||||
/** @var string */
|
||||
private $plugin_dir;
|
||||
/** @var string */
|
||||
private $plugin_url;
|
||||
/** @var string */
|
||||
private $class_name;
|
||||
/** @var string */
|
||||
private $version;
|
||||
/** @var string */
|
||||
private $product_id;
|
||||
/** @var string */
|
||||
private $plugin_name;
|
||||
/** @var \DateTimeInterface */
|
||||
private $release_date;
|
||||
/** string */
|
||||
private $text_domain;
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function get_plugin_file_name()
|
||||
{
|
||||
return $this->plugin_file_name;
|
||||
}
|
||||
/**
|
||||
* @param string $plugin_name
|
||||
*/
|
||||
public function set_plugin_file_name($plugin_name)
|
||||
{
|
||||
$this->plugin_file_name = $plugin_name;
|
||||
}
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function get_plugin_dir()
|
||||
{
|
||||
return $this->plugin_dir;
|
||||
}
|
||||
/**
|
||||
* @param string $plugin_dir
|
||||
*/
|
||||
public function set_plugin_dir($plugin_dir)
|
||||
{
|
||||
$this->plugin_dir = $plugin_dir;
|
||||
}
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function get_plugin_url()
|
||||
{
|
||||
return $this->plugin_url;
|
||||
}
|
||||
/**
|
||||
* @param string $plugin_url
|
||||
*/
|
||||
public function set_plugin_url($plugin_url)
|
||||
{
|
||||
$this->plugin_url = $plugin_url;
|
||||
}
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function get_version()
|
||||
{
|
||||
return $this->version;
|
||||
}
|
||||
/**
|
||||
* @param string $version
|
||||
*/
|
||||
public function set_version($version)
|
||||
{
|
||||
$this->version = $version;
|
||||
}
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function get_product_id()
|
||||
{
|
||||
return $this->product_id;
|
||||
}
|
||||
/**
|
||||
* @param string $product_id
|
||||
*/
|
||||
public function set_product_id($product_id)
|
||||
{
|
||||
$this->product_id = $product_id;
|
||||
}
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function get_plugin_name()
|
||||
{
|
||||
return $this->plugin_name;
|
||||
}
|
||||
/**
|
||||
* @param string $plugin_name
|
||||
*/
|
||||
public function set_plugin_name($plugin_name)
|
||||
{
|
||||
$this->plugin_name = $plugin_name;
|
||||
}
|
||||
/**
|
||||
* @return DateTimeInterface
|
||||
*/
|
||||
public function get_release_date()
|
||||
{
|
||||
return $this->release_date;
|
||||
}
|
||||
/**
|
||||
* @param \DateTimeInterface $release_date
|
||||
*/
|
||||
public function set_release_date($release_date)
|
||||
{
|
||||
$this->release_date = $release_date;
|
||||
}
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function get_class_name()
|
||||
{
|
||||
return $this->class_name;
|
||||
}
|
||||
/**
|
||||
* @param string $class_name
|
||||
*/
|
||||
public function set_class_name($class_name)
|
||||
{
|
||||
$this->class_name = $class_name;
|
||||
}
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function get_text_domain()
|
||||
{
|
||||
return $this->text_domain;
|
||||
}
|
||||
/**
|
||||
* @param $value
|
||||
*/
|
||||
public function set_text_domain($value)
|
||||
{
|
||||
$this->text_domain = $value;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
namespace FcfVendor;
|
||||
|
||||
/**
|
||||
* @deprecated Have typo so better use WPDesk_Translatable
|
||||
*/
|
||||
interface WPDesk_Translable
|
||||
{
|
||||
/** @return string */
|
||||
public function get_text_domain();
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
<?php
|
||||
|
||||
namespace FcfVendor;
|
||||
|
||||
if (!\interface_exists('FcfVendor\\WPDesk_Translable')) {
|
||||
require_once 'Translable.php';
|
||||
}
|
||||
/**
|
||||
* Have info about textdomain - how to translate texts
|
||||
*
|
||||
* have to be compatible with PHP 5.2.x
|
||||
*/
|
||||
interface WPDesk_Translatable extends \FcfVendor\WPDesk_Translable
|
||||
{
|
||||
/** @return string */
|
||||
public function get_text_domain();
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
<?php
|
||||
|
||||
namespace FcfVendor\WPDesk\PluginBuilder\Storage\Exception;
|
||||
|
||||
class ClassAlreadyExists extends \RuntimeException
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
<?php
|
||||
|
||||
namespace FcfVendor\WPDesk\PluginBuilder\Storage\Exception;
|
||||
|
||||
class ClassNotExists extends \RuntimeException
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
namespace FcfVendor\WPDesk\PluginBuilder\Storage;
|
||||
|
||||
use FcfVendor\WPDesk\PluginBuilder\Plugin\AbstractPlugin;
|
||||
interface PluginStorage
|
||||
{
|
||||
/**
|
||||
* @param string $class
|
||||
* @param AbstractPlugin $object
|
||||
*/
|
||||
public function add_to_storage($class, $object);
|
||||
/**
|
||||
* @param string $class
|
||||
*
|
||||
* @return AbstractPlugin
|
||||
*/
|
||||
public function get_from_storage($class);
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
namespace FcfVendor\WPDesk\PluginBuilder\Storage;
|
||||
|
||||
use FcfVendor\WPDesk\PluginBuilder\Plugin\AbstractPlugin;
|
||||
/**
|
||||
* Can store plugin instances in static variable
|
||||
*
|
||||
* @package WPDesk\PluginBuilder\Storage
|
||||
*/
|
||||
class StaticStorage implements \FcfVendor\WPDesk\PluginBuilder\Storage\PluginStorage
|
||||
{
|
||||
protected static $instances = [];
|
||||
/**
|
||||
* @param string $class
|
||||
* @param AbstractPlugin $object
|
||||
*/
|
||||
public function add_to_storage($class, $object)
|
||||
{
|
||||
if (isset(self::$instances[$class])) {
|
||||
throw new \FcfVendor\WPDesk\PluginBuilder\Storage\Exception\ClassAlreadyExists("Class {$class} already exists");
|
||||
}
|
||||
self::$instances[$class] = $object;
|
||||
}
|
||||
/**
|
||||
* @param string $class
|
||||
*
|
||||
* @return AbstractPlugin
|
||||
*/
|
||||
public function get_from_storage($class)
|
||||
{
|
||||
if (isset(self::$instances[$class])) {
|
||||
return self::$instances[$class];
|
||||
}
|
||||
throw new \FcfVendor\WPDesk\PluginBuilder\Storage\Exception\ClassNotExists("Class {$class} not exists in storage");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
<?php
|
||||
|
||||
namespace FcfVendor\WPDesk\PluginBuilder\Storage;
|
||||
|
||||
class StorageFactory
|
||||
{
|
||||
/**
|
||||
* @return PluginStorage
|
||||
*/
|
||||
public function create_storage()
|
||||
{
|
||||
return new \FcfVendor\WPDesk\PluginBuilder\Storage\WordpressFilterStorage();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
namespace FcfVendor\WPDesk\PluginBuilder\Storage;
|
||||
|
||||
use FcfVendor\WPDesk\PluginBuilder\Plugin\AbstractPlugin;
|
||||
/**
|
||||
* Can store plugin instances in WordPress filter system.
|
||||
*
|
||||
* @package WPDesk\PluginBuilder\Storage
|
||||
*/
|
||||
class WordpressFilterStorage implements \FcfVendor\WPDesk\PluginBuilder\Storage\PluginStorage
|
||||
{
|
||||
const STORAGE_FILTER_NAME = 'wpdesk_plugin_instances';
|
||||
/**
|
||||
* @param string $class
|
||||
* @param AbstractPlugin $object
|
||||
*/
|
||||
public function add_to_storage($class, $object)
|
||||
{
|
||||
\add_filter(self::STORAGE_FILTER_NAME, static function ($plugins) use($class, $object) {
|
||||
if (isset($plugins[$class])) {
|
||||
throw new \FcfVendor\WPDesk\PluginBuilder\Storage\Exception\ClassAlreadyExists("Class {$class} already exists");
|
||||
}
|
||||
$plugins[$class] = $object;
|
||||
return $plugins;
|
||||
});
|
||||
}
|
||||
/**
|
||||
* @param string $class
|
||||
*
|
||||
* @return AbstractPlugin
|
||||
*/
|
||||
public function get_from_storage($class)
|
||||
{
|
||||
$plugins = \apply_filters(self::STORAGE_FILTER_NAME, []);
|
||||
if (isset($plugins[$class])) {
|
||||
return $plugins[$class];
|
||||
}
|
||||
throw new \FcfVendor\WPDesk\PluginBuilder\Storage\Exception\ClassNotExists("Class {$class} not exists in storage");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
{
|
||||
"name": "wpdesk\/wp-code-sniffer",
|
||||
"description": "Library for WP Desk Coding Standards in plugins.",
|
||||
"license": "MIT",
|
||||
"keywords": [
|
||||
"wordpress",
|
||||
"code sniffer",
|
||||
"admin",
|
||||
"phpcs"
|
||||
],
|
||||
"homepage": "https:\/\/gitlab.com\/wpdesk\/wp-code-sniffer",
|
||||
"type": "phpcodesniffer-standard",
|
||||
"prefer-stable": true,
|
||||
"version": "1.2.3",
|
||||
"authors": [
|
||||
{
|
||||
"name": "grola",
|
||||
"email": "grola@wpdesk.net"
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"php": ">=7.0",
|
||||
"dealerdirect\/phpcodesniffer-composer-installer": "0.6|^0.7",
|
||||
"squizlabs\/php_codesniffer": "^3.6",
|
||||
"wp-coding-standards\/wpcs": "^2.3",
|
||||
"phpcompatibility\/phpcompatibility-wp": "^2.1.1"
|
||||
},
|
||||
"require-dev": {
|
||||
"roave\/security-advisories": "dev-latest"
|
||||
},
|
||||
"scripts": {
|
||||
"install-codestandards": [
|
||||
"Dealerdirect\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\Plugin::run"
|
||||
],
|
||||
"pre-package-install": [
|
||||
"@install-codestandards"
|
||||
],
|
||||
"post-package-update": [
|
||||
"@install-codestandards"
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
{
|
||||
"name": "wpdesk\/wp-codeception",
|
||||
"description": "Library for WP Desk Codeception tests.",
|
||||
"license": "MIT",
|
||||
"keywords": [
|
||||
"wordpress",
|
||||
"codeception",
|
||||
"admin"
|
||||
],
|
||||
"homepage": "https:\/\/gitlab.com\/wpdesk\/wp-codeception",
|
||||
"type": "composer-plugin",
|
||||
"minimum-stability": "stable",
|
||||
"authors": [
|
||||
{
|
||||
"name": "grola",
|
||||
"email": "grola@wpdesk.net"
|
||||
}
|
||||
],
|
||||
"config": {
|
||||
"sort-packages": true,
|
||||
"platform": {
|
||||
"php": "7.0.8"
|
||||
},
|
||||
"allow-plugins": {
|
||||
"kylekatarnls\/update-helper": true
|
||||
}
|
||||
},
|
||||
"require": {
|
||||
"php": ">=7.0.8",
|
||||
"ext-json": "*",
|
||||
"composer-plugin-api": "^1.1|^2",
|
||||
"albertofem\/rsync-lib": "^1.0",
|
||||
"bordoni\/phpass": "^0.3.5",
|
||||
"codeception\/module-asserts": "^1.3",
|
||||
"codeception\/module-cli": "^1.0",
|
||||
"codeception\/module-db": "^1.0",
|
||||
"codeception\/module-filesystem": "^1.0",
|
||||
"codeception\/module-phpbrowser": "^1.0",
|
||||
"codeception\/module-rest": "^1.2",
|
||||
"codeception\/module-webdriver": "^1.0",
|
||||
"codeception\/util-universalframework": "^1.0",
|
||||
"lucatume\/codeception-steppify": "^1.0",
|
||||
"lucatume\/wp-browser": "^2.4",
|
||||
"phpunit\/php-code-coverage": "^5.3",
|
||||
"symfony\/yaml": "^v3.4.47",
|
||||
"vlucas\/phpdotenv": "^4.2.0",
|
||||
"wp-cli\/admin-command": "^2.0",
|
||||
"wp-cli\/wp-cli-bundle": "^2.4"
|
||||
},
|
||||
"require-dev": {
|
||||
"10up\/wp_mock": "*"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"FcfVendor\\WPDesk\\Codeception\\": "src\/WPDesk\/Codeception",
|
||||
"FcfVendor\\Codeception\\Module\\": "src\/Codeception\/Module",
|
||||
"FcfVendor\\WPDesk\\Composer\\Codeception\\": "src\/WPDesk\/Composer"
|
||||
}
|
||||
},
|
||||
"autoload-dev": {},
|
||||
"scripts": {
|
||||
"phpcs": "phpcs"
|
||||
},
|
||||
"extra": {
|
||||
"class": "WPDesk\\Composer\\Codeception\\Plugin"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
<?php
|
||||
|
||||
namespace FcfVendor\WPDesk\Codeception\Command;
|
||||
|
||||
use FcfVendor\Codeception\Lib\Generator\Test;
|
||||
/**
|
||||
* Class code for codeception example test for WP Desk plugin activation.
|
||||
*
|
||||
* @package WPDesk\Codeception\Command
|
||||
*/
|
||||
class AcceptanceTestGenerator extends \FcfVendor\Codeception\Lib\Generator\Test
|
||||
{
|
||||
protected $template = <<<EOF
|
||||
<?php {{namespace}}
|
||||
|
||||
use WPDesk\\Codeception\\Tests\\Acceptance\\Cest\\AbstractCestForPluginActivation;
|
||||
|
||||
class {{name}} extends AbstractCestForPluginActivation {
|
||||
|
||||
\t/**
|
||||
\t * Deactivate plugins before tests.
|
||||
\t *
|
||||
\t * @param AcceptanceTester \$i .
|
||||
\t *
|
||||
\t * @throws \\Codeception\\Exception\\ModuleException .
|
||||
\t */
|
||||
\tpublic function _before( \$i ) {
|
||||
\t\t\$i->loginAsAdministrator();
|
||||
\t\t\$i->amOnPluginsPage();
|
||||
\t\t\$i->deactivatePlugin( \$this->getPluginSlug() );
|
||||
\t\t\$i->amOnPluginsPage();
|
||||
\t\t\$i->seePluginDeactivated( \$this->getPluginSlug() );
|
||||
\t\t\$i->amOnPluginsPage();
|
||||
\t\t\$i->deactivatePlugin( self::WOOCOMMERCE_PLUGIN_SLUG );
|
||||
\t\t\$i->amOnPluginsPage();
|
||||
\t\t\$i->seePluginDeactivated( self::WOOCOMMERCE_PLUGIN_SLUG );
|
||||
\t}
|
||||
|
||||
\t/**
|
||||
\t * Plugin activation.
|
||||
\t *
|
||||
\t * @param AcceptanceTester \$i .
|
||||
\t *
|
||||
\t * @throws \\Codeception\\Exception\\ModuleException .
|
||||
\t */
|
||||
\tpublic function pluginActivation( \$i ) {
|
||||
|
||||
\t\t\$i->loginAsAdministrator();
|
||||
|
||||
\t\t\$i->amOnPluginsPage();
|
||||
\t\t\$i->seePluginDeactivated( \$this->getPluginSlug() );
|
||||
|
||||
\t\t// This is an example and you should change it to current plugin.
|
||||
\t\t\$i->activateWPDeskPlugin(
|
||||
\t\t\t\$this->getPluginSlug(),
|
||||
\t\t\tarray( 'woocommerce' ),
|
||||
\t\t\tarray( 'The “WooCommerce Fakturownia” plugin cannot run without WooCommerce active. Please install and activate WooCommerce plugin.' )
|
||||
\t\t);
|
||||
|
||||
\t}
|
||||
}
|
||||
EOF;
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
<?php
|
||||
|
||||
namespace FcfVendor\WPDesk\Codeception\Command;
|
||||
|
||||
use FcfVendor\Codeception\Command\GenerateTest;
|
||||
use FcfVendor\Codeception\CustomCommandInterface;
|
||||
use FcfVendor\Symfony\Component\Console\Input\InputInterface;
|
||||
use FcfVendor\Symfony\Component\Console\Output\OutputInterface;
|
||||
/**
|
||||
* Generates codeception example test for WP Desk plugin activation.
|
||||
*
|
||||
* @package WPDesk\Codeception\Command
|
||||
*/
|
||||
class GeneratePluginActivation extends \FcfVendor\Codeception\Command\GenerateTest implements \FcfVendor\Codeception\CustomCommandInterface
|
||||
{
|
||||
/**
|
||||
* Get codeception command description.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getDescription()
|
||||
{
|
||||
return 'Generates plugin activation tests.';
|
||||
}
|
||||
/**
|
||||
* Returns the name of the command.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function getCommandName()
|
||||
{
|
||||
return 'generate:activation';
|
||||
}
|
||||
/**
|
||||
* Get generator class.
|
||||
*
|
||||
* @param array $config .
|
||||
* @param string $class .
|
||||
* @return AcceptanceTestGenerator
|
||||
*/
|
||||
protected function getGenerator($config, $class)
|
||||
{
|
||||
return new \FcfVendor\WPDesk\Codeception\Command\AcceptanceTestGenerator($config, $class);
|
||||
}
|
||||
/**
|
||||
* Execute command.
|
||||
*
|
||||
* @param InputInterface $input
|
||||
* @param OutputInterface $output
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function execute(\FcfVendor\Symfony\Component\Console\Input\InputInterface $input, \FcfVendor\Symfony\Component\Console\Output\OutputInterface $output)
|
||||
{
|
||||
$suite = $input->getArgument('suite');
|
||||
$class = $input->getArgument('class');
|
||||
$config = $this->getSuiteConfig($suite);
|
||||
$className = $this->getShortClassName($class);
|
||||
$path = $this->createDirectoryFor($config['path'], $class);
|
||||
$filename = $this->completeSuffix($className, 'Cest');
|
||||
$filename = $path . $filename;
|
||||
$gen = $this->getGenerator($config, $class);
|
||||
$res = $this->createFile($filename, $gen->produce());
|
||||
if (!$res) {
|
||||
$output->writeln("<error>Test {$filename} already exists</error>");
|
||||
return;
|
||||
}
|
||||
$output->writeln("<info>Test was created in {$filename}</info>");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
<?php
|
||||
|
||||
namespace FcfVendor\WPDesk\Codeception\Command;
|
||||
|
||||
use FcfVendor\Codeception\Command\GenerateTest;
|
||||
use FcfVendor\Codeception\CustomCommandInterface;
|
||||
use FcfVendor\Symfony\Component\Console\Input\InputInterface;
|
||||
use FcfVendor\Symfony\Component\Console\Output\OutputInterface;
|
||||
/**
|
||||
* Generates codeception example test for WP Desk plugin activation.
|
||||
*
|
||||
* @package WPDesk\Codeception\Command
|
||||
*/
|
||||
class GenerateWooCommerce extends \FcfVendor\Codeception\Command\GenerateTest implements \FcfVendor\Codeception\CustomCommandInterface
|
||||
{
|
||||
/**
|
||||
* Get codeception command description.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getDescription()
|
||||
{
|
||||
return 'Generates woocommerce tests.';
|
||||
}
|
||||
/**
|
||||
* Returns the name of the command.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function getCommandName()
|
||||
{
|
||||
return 'generate:woocommerce';
|
||||
}
|
||||
/**
|
||||
* Get generator class.
|
||||
*
|
||||
* @param array $config .
|
||||
* @param string $class .
|
||||
* @return WooCommerceTestGenerator
|
||||
*/
|
||||
protected function getGenerator($config, $class)
|
||||
{
|
||||
return new \FcfVendor\WPDesk\Codeception\Command\WooCommerceTestGenerator($config, $class);
|
||||
}
|
||||
/**
|
||||
* Execute command.
|
||||
*
|
||||
* @param InputInterface $input
|
||||
* @param OutputInterface $output
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function execute(\FcfVendor\Symfony\Component\Console\Input\InputInterface $input, \FcfVendor\Symfony\Component\Console\Output\OutputInterface $output)
|
||||
{
|
||||
$suite = $input->getArgument('suite');
|
||||
$class = $input->getArgument('class');
|
||||
$config = $this->getSuiteConfig($suite);
|
||||
$className = $this->getShortClassName($class);
|
||||
$path = $this->createDirectoryFor($config['path'], $class);
|
||||
$filename = $this->completeSuffix($className, 'Cest');
|
||||
$filename = $path . $filename;
|
||||
$gen = $this->getGenerator($config, $class);
|
||||
$res = $this->createFile($filename, $gen->produce());
|
||||
if (!$res) {
|
||||
$output->writeln("<error>Test {$filename} already exists</error>");
|
||||
return;
|
||||
}
|
||||
$output->writeln("<info>Test was created in {$filename}</info>");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
namespace FcfVendor\WPDesk\Codeception\Command;
|
||||
|
||||
use FcfVendor\Codeception\Lib\Generator\Test;
|
||||
/**
|
||||
* Class code for codeception example test for WP Desk plugin activation.
|
||||
*
|
||||
* @package WPDesk\Codeception\Command
|
||||
*/
|
||||
class WooCommerceTestGenerator extends \FcfVendor\Codeception\Lib\Generator\Test
|
||||
{
|
||||
protected $template = <<<EOF
|
||||
<?php {{namespace}}
|
||||
|
||||
use WPDesk\\Codeception\\Tests\\Acceptance\\Cest\\AbstractCestForWooCommerce;
|
||||
|
||||
/**
|
||||
* Common WooCommerce tests.
|
||||
*/
|
||||
class {{name}} extends AbstractCestForWooCommerce {
|
||||
|
||||
}
|
||||
EOF;
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
namespace FcfVendor\WPDesk\Composer\Codeception;
|
||||
|
||||
use FcfVendor\WPDesk\Composer\Codeception\Commands\CreateCodeceptionTests;
|
||||
use FcfVendor\WPDesk\Composer\Codeception\Commands\PrepareCodeceptionDb;
|
||||
use FcfVendor\WPDesk\Composer\Codeception\Commands\PrepareLocalCodeceptionTests;
|
||||
use FcfVendor\WPDesk\Composer\Codeception\Commands\PrepareLocalCodeceptionTestsWithCoverage;
|
||||
use FcfVendor\WPDesk\Composer\Codeception\Commands\PrepareParallelCodeceptionTests;
|
||||
use FcfVendor\WPDesk\Composer\Codeception\Commands\PrepareWordpressForCodeception;
|
||||
use FcfVendor\WPDesk\Composer\Codeception\Commands\RunCodeceptionTests;
|
||||
use FcfVendor\WPDesk\Composer\Codeception\Commands\RunLocalCodeceptionTests;
|
||||
use FcfVendor\WPDesk\Composer\Codeception\Commands\RunLocalCodeceptionTestsWithCoverage;
|
||||
/**
|
||||
* Links plugin commands handlers to composer.
|
||||
*/
|
||||
class CommandProvider implements \FcfVendor\Composer\Plugin\Capability\CommandProvider
|
||||
{
|
||||
public function getCommands()
|
||||
{
|
||||
return [new \FcfVendor\WPDesk\Composer\Codeception\Commands\CreateCodeceptionTests(), new \FcfVendor\WPDesk\Composer\Codeception\Commands\RunCodeceptionTests(), new \FcfVendor\WPDesk\Composer\Codeception\Commands\RunLocalCodeceptionTests(), new \FcfVendor\WPDesk\Composer\Codeception\Commands\RunLocalCodeceptionTestsWithCoverage(), new \FcfVendor\WPDesk\Composer\Codeception\Commands\PrepareCodeceptionDb(), new \FcfVendor\WPDesk\Composer\Codeception\Commands\PrepareWordpressForCodeception(), new \FcfVendor\WPDesk\Composer\Codeception\Commands\PrepareLocalCodeceptionTests(), new \FcfVendor\WPDesk\Composer\Codeception\Commands\PrepareLocalCodeceptionTestsWithCoverage(), new \FcfVendor\WPDesk\Composer\Codeception\Commands\PrepareParallelCodeceptionTests()];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
namespace FcfVendor\WPDesk\Composer\Codeception\Commands;
|
||||
|
||||
use FcfVendor\Composer\Command\BaseCommand as CodeceptionBaseCommand;
|
||||
use FcfVendor\Symfony\Component\Console\Output\OutputInterface;
|
||||
/**
|
||||
* Base for commands - declares common methods.
|
||||
*
|
||||
* @package WPDesk\Composer\Codeception\Commands
|
||||
*/
|
||||
abstract class BaseCommand extends \FcfVendor\Composer\Command\BaseCommand
|
||||
{
|
||||
/**
|
||||
* @param string $command
|
||||
* @param OutputInterface $output
|
||||
*/
|
||||
protected function execAndOutput($command, \FcfVendor\Symfony\Component\Console\Output\OutputInterface $output)
|
||||
{
|
||||
\passthru($command);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,375 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Class Env
|
||||
* @package WPDesk\Composer\Codeception\Commands
|
||||
*/
|
||||
namespace FcfVendor\WPDesk\Composer\Codeception\Commands;
|
||||
|
||||
use FcfVendor\Dotenv\Dotenv;
|
||||
/**
|
||||
* Env.
|
||||
*/
|
||||
class Configuration
|
||||
{
|
||||
const MYSQL_IP = 'MYSQL_IP';
|
||||
const MYSQL_DBNAME = 'MYSQL_DBNAME';
|
||||
const MYSQL_DBUSER = 'MYSQL_DBUSER';
|
||||
const MYSQL_DBPASSWORD = 'MYSQL_DBPASSWORD';
|
||||
const APACHE_DOCUMENT_ROOT = 'APACHE_DOCUMENT_ROOT';
|
||||
const WOOTESTS_IP = 'WOOTESTS_IP';
|
||||
const DEPENDENT_PLUGINS_DIR = 'DEPENDENT_PLUGINS_DIR';
|
||||
const TEST_SITE_WP_URL = 'TEST_SITE_WP_URL';
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $apache_document_root;
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $wptests_ip;
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $wptests_url;
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $dbhost;
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $dbname;
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $dbuser;
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $dbpassword;
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $dependent_plugins_dir;
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $plugin_slug;
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $plugin_dir;
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $plugin_file;
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $plugin_title;
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $plugin_product_id;
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private $repository_plugins;
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private $local_plugins;
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private $activate_plugins;
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private $prepare_database;
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private $theme_files;
|
||||
/**
|
||||
* Configuration constructor.
|
||||
*
|
||||
* @param $apache_document_root
|
||||
* @param $wptests_ip
|
||||
* @param $wptests_url
|
||||
* @param $dbhost
|
||||
* @param $dbname
|
||||
* @param $dbuser
|
||||
* @param $dbpassword
|
||||
* @param $dependent_plugins_dir
|
||||
* @param $plugin_slug
|
||||
* @param $plugin_dir
|
||||
* @param $plugin_file
|
||||
* @param $plugin_title
|
||||
* @param $plugin_product_id
|
||||
* @param $repository_plugins
|
||||
* @param $local_plugins
|
||||
* @param $activate_plugins
|
||||
* @param $prepare_database
|
||||
* @param $theme_files
|
||||
*/
|
||||
public function __construct($apache_document_root, $wptests_ip, $wptests_url, $dbhost, $dbname, $dbuser, $dbpassword, $dependent_plugins_dir, $plugin_slug, $plugin_dir, $plugin_file, $plugin_title, $plugin_product_id, $repository_plugins, $local_plugins, $activate_plugins, $prepare_database, $theme_files)
|
||||
{
|
||||
$this->apache_document_root = $apache_document_root;
|
||||
$this->wptests_ip = $wptests_ip;
|
||||
$this->wptests_url = $wptests_url;
|
||||
$this->dbhost = $dbhost;
|
||||
$this->dbname = $dbname;
|
||||
$this->dbuser = $dbuser;
|
||||
$this->dbpassword = $dbpassword;
|
||||
$this->dependent_plugins_dir = $dependent_plugins_dir;
|
||||
$this->plugin_slug = $plugin_slug;
|
||||
$this->plugin_dir = $plugin_dir;
|
||||
$this->plugin_file = $plugin_file;
|
||||
$this->plugin_title = $plugin_title;
|
||||
$this->plugin_product_id = $plugin_product_id;
|
||||
$this->repository_plugins = $repository_plugins;
|
||||
$this->local_plugins = $local_plugins;
|
||||
$this->activate_plugins = $activate_plugins;
|
||||
$this->prepare_database = $prepare_database;
|
||||
$this->theme_files = $theme_files;
|
||||
}
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getApacheDocumentRoot()
|
||||
{
|
||||
return $this->apache_document_root;
|
||||
}
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getWptestsIp()
|
||||
{
|
||||
return $this->wptests_ip;
|
||||
}
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getWptestsUrl()
|
||||
{
|
||||
return $this->wptests_url;
|
||||
}
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getDbhost()
|
||||
{
|
||||
return $this->dbhost;
|
||||
}
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getDbname()
|
||||
{
|
||||
return $this->dbname;
|
||||
}
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getDbuser()
|
||||
{
|
||||
return $this->dbuser;
|
||||
}
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getDbpassword()
|
||||
{
|
||||
return $this->dbpassword;
|
||||
}
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getDependentPluginsDir()
|
||||
{
|
||||
return $this->dependent_plugins_dir;
|
||||
}
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getPluginSlug()
|
||||
{
|
||||
return $this->plugin_slug;
|
||||
}
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getPluginDir()
|
||||
{
|
||||
return $this->plugin_dir;
|
||||
}
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getPluginFile()
|
||||
{
|
||||
return $this->plugin_file;
|
||||
}
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getPluginTitle()
|
||||
{
|
||||
return $this->plugin_title;
|
||||
}
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getPluginProductId()
|
||||
{
|
||||
return $this->plugin_product_id;
|
||||
}
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getRepositoryPlugins()
|
||||
{
|
||||
return $this->repository_plugins;
|
||||
}
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getLocalPlugins()
|
||||
{
|
||||
return $this->local_plugins;
|
||||
}
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getActivatePlugins()
|
||||
{
|
||||
return $this->activate_plugins;
|
||||
}
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getPrepareDatabase()
|
||||
{
|
||||
return $this->prepare_database;
|
||||
}
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getThemeFiles()
|
||||
{
|
||||
return $this->theme_files;
|
||||
}
|
||||
/**
|
||||
* Set env variables from configuration.
|
||||
*/
|
||||
public function prepareEnvForConfiguration()
|
||||
{
|
||||
$this->putEnv('WPDESK_PLUGIN_SLUG', $this->getPluginSlug());
|
||||
$this->putEnv('WPDESK_PLUGIN_FILE', $this->getPluginFile());
|
||||
$this->putEnv('WPDESK_PLUGIN_TITLE', $this->getPluginTitle());
|
||||
$this->putEnv('WPDESK_PLUGIN_PRODUCT_ID', $this->getPluginProductId());
|
||||
}
|
||||
/**
|
||||
* @param string $env_variable
|
||||
* @param string $value
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function putEnv($env_variable, $value)
|
||||
{
|
||||
\putenv($env_variable . '=' . $value);
|
||||
}
|
||||
/**
|
||||
* @param array $configuration .
|
||||
*
|
||||
* @return Configuration
|
||||
*/
|
||||
public static function createFromEnvAndConfiguration(array $configuration)
|
||||
{
|
||||
$dotenv = \FcfVendor\Dotenv\Dotenv::createImmutable(\getcwd() . '/../');
|
||||
$dotenv->safeLoad();
|
||||
$apache_document_root = self::prepareFromEnv(self::APACHE_DOCUMENT_ROOT, self::prepareApacheDocumentRoot());
|
||||
$wptests_ip = self::prepareFromEnv(self::WOOTESTS_IP, 'wptests.lh');
|
||||
$dbhost = self::prepareFromEnv(self::MYSQL_IP, 'mysqltests');
|
||||
$dbname = self::prepareFromEnv(self::MYSQL_DBNAME, 'wptest');
|
||||
$dbuser = self::prepareFromEnv(self::MYSQL_DBUSER, 'mysql');
|
||||
$dbpassword = self::prepareFromEnv(self::MYSQL_DBPASSWORD, 'mysql');
|
||||
$wptest_url = self::prepareFromEnv(self::TEST_SITE_WP_URL, 'http://wptests.lh');
|
||||
$dependent_plugins_dir = self::prepareFromEnv(self::DEPENDENT_PLUGINS_DIR, '../');
|
||||
if (isset($configuration['plugin-slug'])) {
|
||||
$plugin_slug = $configuration['plugin-slug'];
|
||||
} else {
|
||||
throw new \FcfVendor\WPDesk\Composer\Codeception\Commands\SettingsException('Missing plugin-slug setting!');
|
||||
}
|
||||
if (isset($configuration['plugin-file'])) {
|
||||
$plugin_file = $configuration['plugin-file'];
|
||||
} else {
|
||||
throw new \FcfVendor\WPDesk\Composer\Codeception\Commands\SettingsException('Missing plugin-file setting!');
|
||||
}
|
||||
$plugin_file_exploded = \explode('/', $plugin_file);
|
||||
$plugin_dir = $plugin_file_exploded[0];
|
||||
if (isset($configuration['plugin-title'])) {
|
||||
$plugin_title = $configuration['plugin-title'];
|
||||
} else {
|
||||
throw new \FcfVendor\WPDesk\Composer\Codeception\Commands\SettingsException('Missing plugin-title setting!');
|
||||
}
|
||||
if (isset($configuration['plugin-product-id'])) {
|
||||
$plugin_product_id = $configuration['plugin-product-id'];
|
||||
} else {
|
||||
$plugin_product_id = '';
|
||||
}
|
||||
$prepare_database = array();
|
||||
if (isset($configuration['prepare-database']) && \is_array($configuration['prepare-database'])) {
|
||||
$prepare_database = $configuration['prepare-database'];
|
||||
}
|
||||
$theme_files = array();
|
||||
if (isset($configuration['theme-files']) && \is_array($configuration['theme-files'])) {
|
||||
$theme_files = $configuration['theme-files'];
|
||||
}
|
||||
$repository_plugins = self::getPluginsSettings($configuration, 'repository');
|
||||
$local_plugins = self::getPluginsSettings($configuration, 'local');
|
||||
$activate_plugins = self::getPluginsSettings($configuration, 'activate');
|
||||
return new self($apache_document_root, $wptests_ip, $wptest_url, $dbhost, $dbname, $dbuser, $dbpassword, $dependent_plugins_dir, $plugin_slug, $plugin_dir, $plugin_file, $plugin_title, $plugin_product_id, $repository_plugins, $local_plugins, $activate_plugins, $prepare_database, $theme_files);
|
||||
}
|
||||
/**
|
||||
* @param string $env_variable .
|
||||
* @param string $default_value .
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private static function prepareFromEnv($env_variable, $default_value)
|
||||
{
|
||||
$value = \getenv($env_variable);
|
||||
$value = $value ? $value : $default_value;
|
||||
return $value;
|
||||
}
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
private static function prepareApacheDocumentRoot()
|
||||
{
|
||||
return self::isWindows() ? 'c:\\xampp\\htdocs\\wptests' : '/tmp/wptests';
|
||||
}
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public static function isWindows()
|
||||
{
|
||||
return \false !== \stristr(\PHP_OS, 'WIN') && \false === \stristr(\PHP_OS, 'DARWIN');
|
||||
}
|
||||
/**
|
||||
* @param array $configuration .
|
||||
* @param string $plugins_section .
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private static function getPluginsSettings(array $configuration, $plugins_section)
|
||||
{
|
||||
if (\is_array($configuration) && isset($configuration['plugins'], $configuration['plugins'][$plugins_section]) && \is_array($configuration['plugins'][$plugins_section])) {
|
||||
return $configuration['plugins'][$plugins_section];
|
||||
}
|
||||
return array();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
<?php
|
||||
|
||||
namespace FcfVendor\WPDesk\Composer\Codeception\Commands;
|
||||
|
||||
use FcfVendor\Composer\Downloader\FilesystemException;
|
||||
use FcfVendor\Symfony\Component\Console\Input\InputInterface;
|
||||
use FcfVendor\Symfony\Component\Console\Output\OutputInterface;
|
||||
/**
|
||||
* Codeception tests creator command.
|
||||
*
|
||||
* @package WPDesk\Composer\Codeception\Commands
|
||||
*/
|
||||
class CreateCodeceptionTests extends \FcfVendor\WPDesk\Composer\Codeception\Commands\BaseCommand
|
||||
{
|
||||
use SedTrait;
|
||||
/**
|
||||
* Configure command.
|
||||
*/
|
||||
protected function configure()
|
||||
{
|
||||
parent::configure();
|
||||
$this->setName('create-codeception-tests')->setDescription('Create codeception tests directories and files.');
|
||||
}
|
||||
/**
|
||||
* Copy file.
|
||||
*
|
||||
* @param string $source
|
||||
* @param string $dest
|
||||
* @param string $exceptionMessage
|
||||
* @throws FilesystemException
|
||||
*/
|
||||
private function copy($source, $dest, $exceptionMessage)
|
||||
{
|
||||
if (!\copy($source, $dest)) {
|
||||
throw new \FcfVendor\Composer\Downloader\FilesystemException($exceptionMessage);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Copy configuration files.
|
||||
*
|
||||
* @param $codeceptionDir
|
||||
* @param $testsDir
|
||||
* @param $codeceptionYml
|
||||
* @param $envConfig
|
||||
* @param $acceptanceYml
|
||||
* @param $bootstrapScript
|
||||
* @return void
|
||||
* @throws FilesystemException
|
||||
*/
|
||||
private function copyConfigurationFiles($codeceptionDir, $testsDir, $codeceptionYml, $envConfig, $acceptanceYml, $bootstrapScript)
|
||||
{
|
||||
if (!\file_exists('./' . $codeceptionYml)) {
|
||||
$this->copy('./vendor/wpdesk/wp-codeception/configuration/' . $codeceptionYml, './' . $codeceptionYml, 'Error copying codeception configuration file!');
|
||||
}
|
||||
if (!\file_exists('./' . $envConfig)) {
|
||||
$this->copy('./vendor/wpdesk/wp-codeception/configuration/' . $envConfig, './' . $envConfig, 'Error copying codeception env configuration file!');
|
||||
}
|
||||
if (\file_exists($testsDir . '/' . $acceptanceYml)) {
|
||||
\unlink($testsDir . '/' . $acceptanceYml);
|
||||
}
|
||||
$this->copy('./vendor/wpdesk/wp-codeception/configuration/' . $acceptanceYml, $testsDir . '/' . $acceptanceYml, 'Error copying codeception acceptance configuration file!');
|
||||
if (!\file_exists($codeceptionDir . '/' . $bootstrapScript)) {
|
||||
$this->copy('./vendor/wpdesk/wp-codeception/scripts/' . $bootstrapScript, $codeceptionDir . '/' . $bootstrapScript, 'Error copying codeception bootstrap script file!');
|
||||
}
|
||||
if (!@\file_exists($testsDir . '/_output')) {
|
||||
\mkdir($testsDir . '/_output', 0777, \true);
|
||||
}
|
||||
if (!\file_exists($testsDir . '/_output/.gitignore')) {
|
||||
$this->copy('./vendor/wpdesk/wp-codeception/configuration/_output.gitignore', $testsDir . '/_output/.gitignore', 'Error copying codeception acceptance output .gitignore file!');
|
||||
}
|
||||
if (!@\file_exists($testsDir . '/_support/_generated')) {
|
||||
\mkdir($testsDir . '/_support/_generated', 0777, \true);
|
||||
}
|
||||
if (!\file_exists($testsDir . '/_support/_generated/.gitignore')) {
|
||||
$this->copy('./vendor/wpdesk/wp-codeception/configuration/_generated.gitignore', $testsDir . '/_support/_generated/.gitignore', 'Error copying codeception acceptance output .gitignore file!');
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Inject traits into tester class.
|
||||
*
|
||||
* @param string $testsDir
|
||||
* @return void
|
||||
*/
|
||||
private function injectTraitsIntoTesterClass($testsDir)
|
||||
{
|
||||
$file_pattern = $testsDir . '/_support/AcceptanceTester.php';
|
||||
$pattern = "/use _generated\\\\AcceptanceTesterActions;/";
|
||||
$replace = "use _generated\\AcceptanceTesterActions;\n" . "\n\tuse \\WPDesk\\Codeception\\Tests\\Acceptance\\Tester\\TesterWordpressActions;" . "\n\tuse \\WPDesk\\Codeception\\Tests\\Acceptance\\Tester\\TesterWooCommerceActions;" . "\n\tuse \\WPDesk\\Codeception\\Tests\\Acceptance\\Tester\\TesterWPDeskActions;";
|
||||
$this->wpdeskSed($file_pattern, $pattern, $replace);
|
||||
}
|
||||
/**
|
||||
* Execute command.
|
||||
*
|
||||
* @param InputInterface $input
|
||||
* @param OutputInterface $output
|
||||
* @return void
|
||||
* @throws FilesystemException
|
||||
*/
|
||||
protected function execute(\FcfVendor\Symfony\Component\Console\Input\InputInterface $input, \FcfVendor\Symfony\Component\Console\Output\OutputInterface $output)
|
||||
{
|
||||
$codeceptionDir = './tests/codeception';
|
||||
$testsDir = $codeceptionDir . '/tests';
|
||||
$codeceptionYml = 'codeception.dist.yml';
|
||||
$envConfig = '.env.testing';
|
||||
$acceptanceYml = 'acceptance.suite.yml';
|
||||
$bootstrapScript = 'bootstrap.sh';
|
||||
if (!@\file_exists($testsDir)) {
|
||||
\mkdir($testsDir, 0777, \true);
|
||||
}
|
||||
$this->copyConfigurationFiles($codeceptionDir, $testsDir, $codeceptionYml, $envConfig, $acceptanceYml, $bootstrapScript);
|
||||
$this->execAndOutput('./vendor/bin/codecept bootstrap ' . $codeceptionDir, $output);
|
||||
$this->execAndOutput('./vendor/bin/codecept generate:activation acceptance ActivationCest', $output);
|
||||
$this->execAndOutput('./vendor/bin/codecept generate:woocommerce acceptance WooCommerceCest', $output);
|
||||
$this->injectTraitsIntoTesterClass($testsDir);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,273 @@
|
||||
<?php
|
||||
|
||||
namespace FcfVendor\WPDesk\Composer\Codeception\Commands;
|
||||
|
||||
use FcfVendor\Composer\Downloader\FilesystemException;
|
||||
use FcfVendor\Symfony\Component\Console\Input\InputInterface;
|
||||
use FcfVendor\Symfony\Component\Console\Output\OutputInterface;
|
||||
use FcfVendor\Symfony\Component\Yaml\Exception\ParseException;
|
||||
use FcfVendor\Symfony\Component\Yaml\Yaml;
|
||||
/**
|
||||
* Common methods for local Codeception tests.
|
||||
*/
|
||||
trait LocalCodeceptionTrait
|
||||
{
|
||||
private function getWpDeskConfiguration()
|
||||
{
|
||||
try {
|
||||
$wpdesk_configuration = \FcfVendor\Symfony\Component\Yaml\Yaml::parseFile(\getcwd() . '/tests/codeception/wpdesk.yml');
|
||||
} catch (\FcfVendor\Symfony\Component\Yaml\Exception\ParseException $e) {
|
||||
$wpdesk_configuration = array();
|
||||
}
|
||||
return \FcfVendor\WPDesk\Composer\Codeception\Commands\Configuration::createFromEnvAndConfiguration($wpdesk_configuration);
|
||||
}
|
||||
/**
|
||||
* @param OutputInterface $output
|
||||
* @param Configuration $configuration
|
||||
*/
|
||||
private function prepareWpConfig(\FcfVendor\Symfony\Component\Console\Output\OutputInterface $output, \FcfVendor\WPDesk\Composer\Codeception\Commands\Configuration $configuration)
|
||||
{
|
||||
$apache_document_root = $configuration->getApacheDocumentRoot();
|
||||
$this->executeWpCliAndOutput('config set WP_DEBUG true --raw', $output, $apache_document_root);
|
||||
$this->executeWpCliAndOutput('config set WP_DEBUG_LOG true --raw', $output, $apache_document_root);
|
||||
$this->executeWpCliAndOutput('config set WP_DEBUG_DISPLAY false --raw', $output, $apache_document_root);
|
||||
$this->executeWpCliAndOutput('config set WP_HOME ' . $configuration->getWptestsUrl(), $output, $apache_document_root);
|
||||
$this->executeWpCliAndOutput('config set WP_SITEURL ' . $configuration->getWptestsUrl(), $output, $apache_document_root);
|
||||
$this->executeWpCliAndOutput('config set WP_AUTO_UPDATE_CORE false --raw', $output, $apache_document_root);
|
||||
$this->executeWpCliAndOutput('config set AUTOMATIC_UPDATER_DISABLED false --raw', $output, $apache_document_root);
|
||||
$this->executeWpCliAndOutput('rewrite structure \'/%postname%/\'', $output, $apache_document_root);
|
||||
$this->replace_in_file($apache_document_root . '/wp-config.php', 'if ( isset( $_SERVER[\'HTTP_X_FORWARDED_PROTO\'] ) && \'https\' === $_SERVER[\'HTTP_X_FORWARDED_PROTO\'] ) { $_SERVER[\'HTTPS\'] = \'on\'; }', '');
|
||||
$this->replace_in_file($apache_document_root . '/wp-config.php', '<?php', '<?php if ( isset( $_SERVER[\'HTTP_X_FORWARDED_PROTO\'] ) && \'https\' === $_SERVER[\'HTTP_X_FORWARDED_PROTO\'] ) { $_SERVER[\'HTTPS\'] = \'on\'; }');
|
||||
}
|
||||
/**
|
||||
* @param string $filename
|
||||
* @param string $string_to_replace
|
||||
* @param string $replace_with
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function replace_in_file($filename, $string_to_replace, $replace_with)
|
||||
{
|
||||
$content = \file_get_contents($filename);
|
||||
$content_chunks = \explode($string_to_replace, $content);
|
||||
$content = \implode($replace_with, $content_chunks);
|
||||
\file_put_contents($filename, $content);
|
||||
}
|
||||
/**
|
||||
* @param OutputInterface $output
|
||||
* @param Configuration $configuration
|
||||
*/
|
||||
private function activatePlugins(\FcfVendor\Symfony\Component\Console\Output\OutputInterface $output, \FcfVendor\WPDesk\Composer\Codeception\Commands\Configuration $configuration)
|
||||
{
|
||||
$this->executeWpCliAndOutput('plugin deactivate --all', $output, $configuration->getApacheDocumentRoot());
|
||||
$plugins = '';
|
||||
foreach ($configuration->getRepositoryPlugins() as $plugin) {
|
||||
$plugins .= ' ' . $plugin;
|
||||
}
|
||||
if ($plugins) {
|
||||
$this->executeWpCliAndOutput('plugin install ' . $plugins, $output, $configuration->getApacheDocumentRoot());
|
||||
}
|
||||
foreach ($configuration->getLocalPlugins() as $plugin) {
|
||||
$source = $this->preparePathForRsync($this->prepareLocalPluginDir($plugin, $configuration->getDependentPluginsDir()) . '/*', $configuration::isWindows());
|
||||
$target = $this->preparePathForRsync($this->prepareTargetDir($plugin, $configuration) . '/', $configuration::isWindows());
|
||||
$rsync = 'rsync -a ' . $source . ' ' . $target . ' --exclude=node_modules --exclude=.git --exclude=tests --exclude=.idea';
|
||||
$output->writeln($rsync);
|
||||
$this->execAndOutput($rsync, $output);
|
||||
}
|
||||
$this->executeWpCliAndOutput('plugin status', $output, $configuration->getApacheDocumentRoot());
|
||||
$this->executeWpCliAndOutput('plugin list', $output, $configuration->getApacheDocumentRoot());
|
||||
foreach ($configuration->getActivatePlugins() as $plugin) {
|
||||
$this->executeWpCliAndOutput('plugin activate ' . $plugin, $output, $configuration->getApacheDocumentRoot());
|
||||
}
|
||||
$this->executeWpCliAndOutput('plugin activate ' . $configuration->getPluginDir(), $output, $configuration->getApacheDocumentRoot());
|
||||
}
|
||||
/**
|
||||
* @param string $plugin .
|
||||
*/
|
||||
private function prepareLocalPluginDir($plugin, $local_plugins_dir = \false)
|
||||
{
|
||||
if (!$local_plugins_dir) {
|
||||
$local_plugins_dir = \dirname(\getcwd());
|
||||
}
|
||||
return $this->trailingslashit($local_plugins_dir) . $plugin;
|
||||
}
|
||||
/**
|
||||
* @param $string
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function trailingslashit($string)
|
||||
{
|
||||
return \rtrim($string, '/\\') . '/';
|
||||
}
|
||||
/**
|
||||
* @param string $command
|
||||
* @param OutputInterface $output
|
||||
* @param string $apache_document_root
|
||||
*/
|
||||
private function executeWpCliAndOutput($command, \FcfVendor\Symfony\Component\Console\Output\OutputInterface $output, $apache_document_root)
|
||||
{
|
||||
$output->write("WPCLI: {$command}\n");
|
||||
$wp = "wp";
|
||||
$command = $wp . ' ' . $command . ' --allow-root --path=' . $apache_document_root;
|
||||
$this->execAndOutput($command, $output);
|
||||
}
|
||||
/**
|
||||
* @param string $plugin_dir
|
||||
* @param OutputInterface $output
|
||||
* @param Configuration $configuration
|
||||
* @param bool $coverage
|
||||
*/
|
||||
private function installPlugin(string $plugin_dir, \FcfVendor\Symfony\Component\Console\Output\OutputInterface $output, \FcfVendor\WPDesk\Composer\Codeception\Commands\Configuration $configuration, bool $coverage = \true)
|
||||
{
|
||||
$source = $this->preparePathForRsync(\getcwd() . '/*', $configuration::isWindows());
|
||||
$target = $this->preparePathForRsync($this->prepareTargetDir($plugin_dir, $configuration) . '/', $configuration::isWindows());
|
||||
$rsync = 'rsync -av ' . $source . ' ' . $target . ' --exclude=node_modules --exclude=.git --exclude=.idea --exclude=vendor --exclude=vendor_prefixed --exclude=tests/wordpress ';
|
||||
$this->execAndOutput($rsync, $output);
|
||||
\copy(\getcwd() . '/.env.testing', $this->prepareTargetDir($plugin_dir, $configuration) . '/.env.testing');
|
||||
if (!$coverage) {
|
||||
$this->execAndOutput('composer install --working-dir=' . $configuration->getApacheDocumentRoot() . '/wp-content/plugins/' . $plugin_dir, $output);
|
||||
$this->execAndOutput('composer install --no-dev --working-dir=' . $configuration->getApacheDocumentRoot() . '/wp-content/plugins/' . $plugin_dir, $output);
|
||||
} else {
|
||||
$this->execAndOutput('composer require --dev codeception/c3 --working-dir=' . $configuration->getApacheDocumentRoot() . '/wp-content/plugins/' . $plugin_dir, $output);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @param string $path
|
||||
* @param bool $is_windows
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function preparePathForRsync($path, $is_windows)
|
||||
{
|
||||
if ($is_windows) {
|
||||
$path = '/cygdrive/' . $path;
|
||||
$path = \str_replace(':', '', $path);
|
||||
$path = \str_replace('\\', '/', $path);
|
||||
}
|
||||
return $path;
|
||||
}
|
||||
/**
|
||||
* @param string $plugin_slug
|
||||
* @param Configuration $configuration
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function prepareTargetDir($plugin_slug, \FcfVendor\WPDesk\Composer\Codeception\Commands\Configuration $configuration)
|
||||
{
|
||||
return $configuration->getApacheDocumentRoot() . '/wp-content/plugins/' . $plugin_slug;
|
||||
}
|
||||
/**
|
||||
* @param Configuration $configuration
|
||||
* @param OutputInterface $output
|
||||
*/
|
||||
private function prepareCommonWpWcConfiguration(\FcfVendor\WPDesk\Composer\Codeception\Commands\Configuration $configuration, \FcfVendor\Symfony\Component\Console\Output\OutputInterface $output)
|
||||
{
|
||||
$this->executeWpCliAndOutput('db reset --yes', $output, $configuration->getApacheDocumentRoot());
|
||||
$this->executeWpCliAndOutput('core install --url=' . $configuration->getWptestsIp() . ' --title=Woo-tests --admin_user=admin --admin_password=admin --admin_email=grola@seostudio.pl --skip-email', $output, $configuration->getApacheDocumentRoot());
|
||||
$commands = array('theme activate storefront-wpdesk-tests', 'plugin activate woocommerce');
|
||||
$commands = \array_merge($commands, $this->prepareWcOptionsCommands(), $this->prepareTaxes(), $this->prepareShippingMethods(), $this->prepareWooCommercePages(), $this->prepareCustomer(), $this->prepareDisableRESTApiPermissions(), $this->prepareCreateProductsCommands(), $configuration->getPrepareDatabase());
|
||||
foreach ($commands as $command) {
|
||||
$this->executeWpCliAndOutput($command, $output, $configuration->getApacheDocumentRoot());
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
private function prepareWcOptionsCommands()
|
||||
{
|
||||
return array('option update woocommerce_admin_notices \'{}\'', 'option update storefront_nux_dismissed 1', 'option set woocommerce_store_address "al. Jana Pawła 12"', 'option set woocommerce_store_address_2 ""', 'option set woocommerce_store_city "Warszawa"', 'option set woocommerce_default_country "PL"', 'option set woocommerce_store_postalcode "22-100"', 'option set woocommerce_currency "PLN"', 'option set woocommerce_currency_pos "right_space"', 'option set woocommerce_product_type "physical"', 'option set woocommerce_allow_tracking "no"', 'option set --format=json woocommerce_stripe_settings \'{"enabled":"no","create_account":false,"email":false}\'', 'option set --format=json woocommerce_ppec_paypal_settings \'{"reroute_requests":false,"email":false}\'', 'option set --format=json woocommerce_cheque_settings \'{"enabled":"no"}\'', 'option set --format=json woocommerce_bacs_settings \'{"enabled":"no"}\'', 'option set --format=json woocommerce_cod_settings \'{"enabled":"yes"}\'', 'option set --format=json woocommerce_onboarding_profile \'{"skipped":true}\'', 'option set --format=json wc-admin-onboarding-profiler-reminder \'{"skipped":true}\'', 'option get woocommerce_onboarding_profile', 'option set woocommerce_task_list_hidden "yes"', 'option set woocommerce_task_list_hidden "yes"', 'option set woocommerce_show_marketplace_suggestions "no"');
|
||||
}
|
||||
/**
|
||||
* @return string[]
|
||||
*/
|
||||
private function prepareTaxes()
|
||||
{
|
||||
return array('wc tax create --country="PL" --rate=23 --name=VAT --shipping=true --user=admin', 'option set woocommerce_calc_taxes "yes"');
|
||||
}
|
||||
/**
|
||||
* @return string[]
|
||||
*/
|
||||
private function prepareShippingMethods()
|
||||
{
|
||||
return array('wc shipping_zone_method create 0 --method_id="flat_rate" --settings=\'{"title": "Flat rate", "cost":1, "tax_status": "taxable"}\' --enabled=true --user=admin');
|
||||
}
|
||||
/**
|
||||
* @return string[]
|
||||
*/
|
||||
private function prepareWooCommercePages()
|
||||
{
|
||||
return array('wc --user=admin tool run install_pages');
|
||||
}
|
||||
/**
|
||||
* @return string[]
|
||||
*/
|
||||
private function prepareCustomer()
|
||||
{
|
||||
return array('wc customer create --email=\'customer@woo.local\' --username="customer" --billing=\'{"first_name":"First","last_name":"Last","company":"WPDesk","address_1":"Street 1","city":"City","postcode": "53-030", "country": "PL", "phone": "012345678"}\' --password=\'customer\' --user=admin');
|
||||
}
|
||||
/**
|
||||
* @return string[]
|
||||
*/
|
||||
private function prepareDisableRESTApiPermissions()
|
||||
{
|
||||
return array('option set wpdesk_rest_api_disable_permissions "1"');
|
||||
}
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
private function prepareCreateProductsCommands()
|
||||
{
|
||||
return array($this->prepareCreateProductCommand('100', '100'), $this->prepareCreateProductCommand('10', '10'), $this->prepareCreateProductCommand('9', '9'), $this->prepareCreateProductCommand('1', '1'), $this->prepareCreateProductCommand('09', '0.9'), $this->prepareCreateProductCommand('009', '0.09'), $this->prepareCreateProductCommand('01', '0.1'), $this->prepareCreateProductCommand('001', '0.01'), $this->prepareCreateProductCommand('0001', '0.001'), $this->prepareCreateProductCommand('00001', '0.0001'));
|
||||
}
|
||||
/**
|
||||
* @param string $name
|
||||
* @param string $price
|
||||
* @param null|string $weight
|
||||
* @param null|string $sku
|
||||
* @param null|string $dimensions
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function prepareCreateProductCommand($name, $price, $weight = null, $sku = null, $dimensions = null)
|
||||
{
|
||||
$product_name = "Product {$name}";
|
||||
$weight = $weight ? $weight : $price;
|
||||
$sku = $sku ? $sku : 'product-' . $name;
|
||||
$dimensions = $dimensions ? $dimensions : '{"width":"' . $price . '","length":"' . $price . '","height":"' . $price . '"}';
|
||||
return "wc product create --name=\"{$product_name}\" --virtual=false --downloadable=false --type=simple --sku={$sku} --regular_price={$price} --weight={$weight} --dimensions='{$dimensions}' --user=admin";
|
||||
}
|
||||
/**
|
||||
* @param InputInterface $input
|
||||
* @param OutputInterface $output
|
||||
* @param bool $coverage
|
||||
*
|
||||
* @throws \Composer\Downloader\FilesystemException
|
||||
*/
|
||||
private function prepareLocalCodeceptionTests(\FcfVendor\Symfony\Component\Console\Input\InputInterface $input, \FcfVendor\Symfony\Component\Console\Output\OutputInterface $output, bool $coverage = \false)
|
||||
{
|
||||
$configuration = $this->getWpDeskConfiguration();
|
||||
$this->installPlugin($configuration->getPluginDir(), $output, $configuration, $coverage);
|
||||
$this->activatePlugins($output, $configuration);
|
||||
$this->prepareWpConfig($output, $configuration);
|
||||
$this->copyThemeFiles($configuration->getThemeFiles(), $configuration->getApacheDocumentRoot() . '/wp-content/themes/storefront-wpdesk-tests');
|
||||
$sep = \DIRECTORY_SEPARATOR;
|
||||
$codecept = "vendor{$sep}bin{$sep}codecept";
|
||||
$cleanOutput = $codecept . ' clean';
|
||||
$this->execAndOutput($cleanOutput, $output);
|
||||
}
|
||||
/**
|
||||
* @param array $theme_files
|
||||
* @param $theme_folder
|
||||
*
|
||||
* @throws FilesystemException
|
||||
*/
|
||||
private function copyThemeFiles(array $theme_files, $theme_folder)
|
||||
{
|
||||
foreach ($theme_files as $theme_file) {
|
||||
if (!\copy($theme_file, $this->trailingslashit($theme_folder) . \basename($theme_file))) {
|
||||
throw new \FcfVendor\Composer\Downloader\FilesystemException('Error copying theme file: ' . $theme_file);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
namespace FcfVendor\WPDesk\Composer\Codeception\Commands;
|
||||
|
||||
use FcfVendor\Symfony\Component\Console\Input\InputArgument;
|
||||
use FcfVendor\Symfony\Component\Console\Input\InputInterface;
|
||||
use FcfVendor\Symfony\Component\Console\Output\OutputInterface;
|
||||
use FcfVendor\Symfony\Component\Yaml\Exception\ParseException;
|
||||
use FcfVendor\Symfony\Component\Yaml\Yaml;
|
||||
/**
|
||||
* Prepare Database for Codeception tests command.
|
||||
*
|
||||
* @package WPDesk\Composer\Codeception\Commands
|
||||
*/
|
||||
class PrepareCodeceptionDb extends \FcfVendor\WPDesk\Composer\Codeception\Commands\BaseCommand
|
||||
{
|
||||
use LocalCodeceptionTrait;
|
||||
/**
|
||||
* Configure command.
|
||||
*/
|
||||
protected function configure()
|
||||
{
|
||||
parent::configure();
|
||||
$this->setName('prepare-codeception-db')->setDescription('Prepare codeception database.');
|
||||
}
|
||||
/**
|
||||
* Execute command.
|
||||
*
|
||||
* @param InputInterface $input
|
||||
* @param OutputInterface $output
|
||||
*
|
||||
* @return int 0 if everything went fine, or an error code
|
||||
*/
|
||||
protected function execute(\FcfVendor\Symfony\Component\Console\Input\InputInterface $input, \FcfVendor\Symfony\Component\Console\Output\OutputInterface $output)
|
||||
{
|
||||
$configuration = $this->getWpDeskConfiguration();
|
||||
$this->installPlugin($configuration->getPluginDir(), $output, $configuration);
|
||||
$this->prepareCommonWpWcConfiguration($configuration, $output);
|
||||
$this->prepareWpConfig($output, $configuration);
|
||||
$this->activatePlugins($output, $configuration);
|
||||
$this->executeWpCliAndOutput('db export ' . \getcwd() . '/tests/codeception/tests/_data/db.sql', $output, $configuration->getApacheDocumentRoot());
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
<?php
|
||||
|
||||
namespace FcfVendor\WPDesk\Composer\Codeception\Commands;
|
||||
|
||||
use FcfVendor\Composer\Downloader\FilesystemException;
|
||||
use FcfVendor\Symfony\Component\Console\Input\InputArgument;
|
||||
use FcfVendor\Symfony\Component\Console\Input\InputInterface;
|
||||
use FcfVendor\Symfony\Component\Console\Output\OutputInterface;
|
||||
use FcfVendor\Symfony\Component\Yaml\Exception\ParseException;
|
||||
use FcfVendor\Symfony\Component\Yaml\Yaml;
|
||||
/**
|
||||
* Codeception tests run command.
|
||||
*
|
||||
* @package WPDesk\Composer\Codeception\Commands
|
||||
*/
|
||||
class PrepareLocalCodeceptionTests extends \FcfVendor\WPDesk\Composer\Codeception\Commands\RunCodeceptionTests
|
||||
{
|
||||
use LocalCodeceptionTrait;
|
||||
/**
|
||||
* Configure command.
|
||||
*/
|
||||
protected function configure()
|
||||
{
|
||||
parent::configure();
|
||||
$this->setName('prepare-local-codeception-tests')->setDescription('Prepare local codeception tests.');
|
||||
}
|
||||
/**
|
||||
* Execute command.
|
||||
*
|
||||
* @param InputInterface $input
|
||||
* @param OutputInterface $output
|
||||
*
|
||||
* @return int 0 if everything went fine, or an error code
|
||||
*/
|
||||
protected function execute(\FcfVendor\Symfony\Component\Console\Input\InputInterface $input, \FcfVendor\Symfony\Component\Console\Output\OutputInterface $output)
|
||||
{
|
||||
$this->prepareLocalCodeceptionTests($input, $output, \false);
|
||||
return 0;
|
||||
}
|
||||
/**
|
||||
* @param array $theme_files
|
||||
* @param $theme_folder
|
||||
*
|
||||
* @throws FilesystemException
|
||||
*/
|
||||
private function copyThemeFiles(array $theme_files, $theme_folder)
|
||||
{
|
||||
foreach ($theme_files as $theme_file) {
|
||||
if (!\copy($theme_file, $this->trailingslashit($theme_folder) . \basename($theme_file))) {
|
||||
throw new \FcfVendor\Composer\Downloader\FilesystemException('Error copying theme file: ' . $theme_file);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
namespace FcfVendor\WPDesk\Composer\Codeception\Commands;
|
||||
|
||||
use FcfVendor\Composer\Downloader\FilesystemException;
|
||||
use FcfVendor\Symfony\Component\Console\Input\InputArgument;
|
||||
use FcfVendor\Symfony\Component\Console\Input\InputInterface;
|
||||
use FcfVendor\Symfony\Component\Console\Output\OutputInterface;
|
||||
use FcfVendor\Symfony\Component\Yaml\Exception\ParseException;
|
||||
use FcfVendor\Symfony\Component\Yaml\Yaml;
|
||||
/**
|
||||
* Codeception tests run command.
|
||||
*
|
||||
* @package WPDesk\Composer\Codeception\Commands
|
||||
*/
|
||||
class PrepareLocalCodeceptionTestsWithCoverage extends \FcfVendor\WPDesk\Composer\Codeception\Commands\RunCodeceptionTests
|
||||
{
|
||||
use LocalCodeceptionTrait;
|
||||
/**
|
||||
* Configure command.
|
||||
*/
|
||||
protected function configure()
|
||||
{
|
||||
parent::configure();
|
||||
$this->setName('prepare-local-codeception-tests-with-coverage')->setDescription('Prepare local codeception tests.');
|
||||
}
|
||||
/**
|
||||
* Execute command.
|
||||
*
|
||||
* @param InputInterface $input
|
||||
* @param OutputInterface $output
|
||||
* @return void
|
||||
*/
|
||||
protected function execute(\FcfVendor\Symfony\Component\Console\Input\InputInterface $input, \FcfVendor\Symfony\Component\Console\Output\OutputInterface $output)
|
||||
{
|
||||
$this->prepareLocalCodeceptionTests($input, $output, \true);
|
||||
$configuration = $this->getWpDeskConfiguration();
|
||||
$plugin_file = $configuration->getApacheDocumentRoot() . '/wp-content/plugins/' . $configuration->getPluginFile();
|
||||
\file_put_contents($plugin_file, "\ndefine('C3_CODECOVERAGE_ERROR_LOG_FILE', '/tmp/c3_error.log'); include __DIR__ . '/c3.php';", \FILE_APPEND);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
<?php
|
||||
|
||||
namespace FcfVendor\WPDesk\Composer\Codeception\Commands;
|
||||
|
||||
use FcfVendor\Symfony\Component\Console\Input\InputArgument;
|
||||
use FcfVendor\Symfony\Component\Console\Input\InputInterface;
|
||||
use FcfVendor\Symfony\Component\Console\Output\OutputInterface;
|
||||
use FcfVendor\Symfony\Component\Yaml\Exception\ParseException;
|
||||
use FcfVendor\Symfony\Component\Yaml\Yaml;
|
||||
/**
|
||||
* Split test to multiple directories for parallel running in CI.
|
||||
*
|
||||
* @package WPDesk\Composer\Codeception\Commands
|
||||
*/
|
||||
class PrepareParallelCodeceptionTests extends \FcfVendor\WPDesk\Composer\Codeception\Commands\BaseCommand
|
||||
{
|
||||
const NUMBER_OF_JOBS = 'number_of_jobs';
|
||||
/**
|
||||
* Configure command.
|
||||
*/
|
||||
protected function configure()
|
||||
{
|
||||
parent::configure();
|
||||
$this->setName('prepare-parallel-codeception-tests')->setDescription('Prepare parallel codeception tests.')->setDefinition(array(new \FcfVendor\Symfony\Component\Console\Input\InputArgument(self::NUMBER_OF_JOBS, \FcfVendor\Symfony\Component\Console\Input\InputArgument::OPTIONAL, 'Number of jobs.', '4')));
|
||||
}
|
||||
/**
|
||||
* Execute command.
|
||||
*
|
||||
* @param InputInterface $input
|
||||
* @param OutputInterface $output
|
||||
* @return void
|
||||
*/
|
||||
protected function execute(\FcfVendor\Symfony\Component\Console\Input\InputInterface $input, \FcfVendor\Symfony\Component\Console\Output\OutputInterface $output)
|
||||
{
|
||||
$numberOfJobs = (int) $input->getArgument(self::NUMBER_OF_JOBS);
|
||||
$acceptanceTestsDir = \getcwd() . '/tests/codeception/tests/acceptance';
|
||||
for ($i = 1; $i <= $numberOfJobs; $i++) {
|
||||
$parallelDir = $acceptanceTestsDir . '/' . $i;
|
||||
if (!\file_exists($parallelDir)) {
|
||||
\mkdir($parallelDir);
|
||||
}
|
||||
}
|
||||
$currentIndex = 1;
|
||||
$files = \scandir($acceptanceTestsDir);
|
||||
foreach ($files as $fileName) {
|
||||
$fileFullPath = $acceptanceTestsDir . '/' . $fileName;
|
||||
if (!\is_dir($fileFullPath)) {
|
||||
$targetPath = $acceptanceTestsDir . '/' . $currentIndex . '/' . $fileName;
|
||||
\copy($fileFullPath, $targetPath);
|
||||
$currentIndex++;
|
||||
if ($currentIndex > $numberOfJobs) {
|
||||
$currentIndex = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
<?php
|
||||
|
||||
namespace FcfVendor\WPDesk\Composer\Codeception\Commands;
|
||||
|
||||
use FcfVendor\Symfony\Component\Console\Input\InputArgument;
|
||||
use FcfVendor\Symfony\Component\Console\Input\InputInterface;
|
||||
use FcfVendor\Symfony\Component\Console\Output\OutputInterface;
|
||||
use FcfVendor\Symfony\Component\Yaml\Exception\ParseException;
|
||||
use FcfVendor\Symfony\Component\Yaml\Yaml;
|
||||
/**
|
||||
* Prepare Database for Codeception tests command.
|
||||
*
|
||||
* @package WPDesk\Composer\Codeception\Commands
|
||||
*/
|
||||
class PrepareWordpressForCodeception extends \FcfVendor\WPDesk\Composer\Codeception\Commands\BaseCommand
|
||||
{
|
||||
use LocalCodeceptionTrait;
|
||||
/**
|
||||
* Configure command.
|
||||
*/
|
||||
protected function configure()
|
||||
{
|
||||
parent::configure();
|
||||
$this->setName('prepare-wordpress-for-codeception')->setDescription('Prepare wordpress installation for codeception tests.');
|
||||
}
|
||||
/**
|
||||
* Execute command.
|
||||
*
|
||||
* @param InputInterface $input
|
||||
* @param OutputInterface $output
|
||||
*
|
||||
* @return int 0 if everything went fine, or an error code
|
||||
*/
|
||||
protected function execute(\FcfVendor\Symfony\Component\Console\Input\InputInterface $input, \FcfVendor\Symfony\Component\Console\Output\OutputInterface $output)
|
||||
{
|
||||
$configuration = $this->getWpDeskConfiguration();
|
||||
$this->installWP($output, $configuration);
|
||||
return 0;
|
||||
}
|
||||
/**
|
||||
* @param OutputInterface $output
|
||||
* @param Configuration $configuration
|
||||
*/
|
||||
private function installWP(\FcfVendor\Symfony\Component\Console\Output\OutputInterface $output, \FcfVendor\WPDesk\Composer\Codeception\Commands\Configuration $configuration)
|
||||
{
|
||||
if (!\file_exists($configuration->getApacheDocumentRoot())) {
|
||||
\mkdir($configuration->getApacheDocumentRoot(), 0777, \true);
|
||||
}
|
||||
$dbhost = $configuration->getDbhost();
|
||||
$dbname = $configuration->getDbname();
|
||||
$dbuser = $configuration->getDbuser();
|
||||
$dbpassword = $configuration->getDbpassword();
|
||||
$url = $configuration->getWptestsIp();
|
||||
$apache_document_root = $configuration->getApacheDocumentRoot();
|
||||
$this->executeWpCliAndOutput('core download --force', $output, $apache_document_root);
|
||||
$this->executeWpCliAndOutput("core config --dbhost={$dbhost} --dbname={$dbname} --dbuser={$dbuser} --dbpass={$dbpassword}", $output, $apache_document_root);
|
||||
$this->executeWpCliAndOutput("core install --url={$url} --title=Woo-tests --admin_user=admin --admin_password=admin --admin_email=tests@wpdesk.dev --skip-email", $output, $apache_document_root);
|
||||
\copy('./vendor/wpdesk/wp-codeception/wordpress/htaccess', $apache_document_root . '/.htaccess');
|
||||
$this->executeWpCliAndOutput('rewrite structure \'/%postname%/\'', $output, $apache_document_root);
|
||||
$this->executeWpCliAndOutput('plugin install woocommerce', $output, $apache_document_root);
|
||||
$this->executeWpCliAndOutput('theme activate storefront', $output, $apache_document_root);
|
||||
$this->executeWpCliAndOutput('theme delete storefront-wpdesk-tests', $output, $apache_document_root);
|
||||
$this->executeWpCliAndOutput('theme install storefront', $output, $apache_document_root);
|
||||
$this->executeWpCliAndOutput('theme install https://gitlab.com/wpdesk/storefront-wpdesk-tests/-/archive/master/storefront-wpdesk-tests-master.zip', $output, $apache_document_root);
|
||||
\rename($apache_document_root . '/wp-content/themes/storefront-wpdesk-tests-master', $apache_document_root . '/wp-content/themes/storefront-wpdesk-tests');
|
||||
$this->executeWpCliAndOutput('theme activate storefront-wpdesk-tests', $output, $apache_document_root);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
<?php
|
||||
|
||||
namespace FcfVendor\WPDesk\Composer\Codeception\Commands;
|
||||
|
||||
use FcfVendor\Symfony\Component\Console\Input\InputArgument;
|
||||
use FcfVendor\Symfony\Component\Console\Input\InputInterface;
|
||||
use FcfVendor\Symfony\Component\Console\Output\OutputInterface;
|
||||
/**
|
||||
* Codeception tests run command.
|
||||
*
|
||||
* @package WPDesk\Composer\Codeception\Commands
|
||||
*/
|
||||
class RunCodeceptionTests extends \FcfVendor\WPDesk\Composer\Codeception\Commands\BaseCommand
|
||||
{
|
||||
const SINGLE = 'single';
|
||||
const FAST = 'fast';
|
||||
const WOOCOMMERCE_VERSION = 'woo_version';
|
||||
/**
|
||||
* Configure command.
|
||||
*/
|
||||
protected function configure()
|
||||
{
|
||||
parent::configure();
|
||||
$this->setName('run-codeception-tests')->setDescription('Run codeception tests.')->setDefinition(array(new \FcfVendor\Symfony\Component\Console\Input\InputArgument(self::SINGLE, \FcfVendor\Symfony\Component\Console\Input\InputArgument::OPTIONAL, 'Name of Single test to run.', 'all'), new \FcfVendor\Symfony\Component\Console\Input\InputArgument(self::FAST, \FcfVendor\Symfony\Component\Console\Input\InputArgument::OPTIONAL, 'Fast tests - do not shutdown docker-compose.', 'slow'), new \FcfVendor\Symfony\Component\Console\Input\InputArgument(self::WOOCOMMERCE_VERSION, \FcfVendor\Symfony\Component\Console\Input\InputArgument::OPTIONAL, 'WooCommerce version to install.', '')));
|
||||
}
|
||||
/**
|
||||
* Execute command.
|
||||
*
|
||||
* @param InputInterface $input
|
||||
* @param OutputInterface $output
|
||||
*
|
||||
* @return int 0 if everything went fine, or an error code
|
||||
*/
|
||||
protected function execute(\FcfVendor\Symfony\Component\Console\Input\InputInterface $input, \FcfVendor\Symfony\Component\Console\Output\OutputInterface $output)
|
||||
{
|
||||
$dockerComposeYaml = 'vendor/wpdesk/wp-codeception/docker/docker-compose.yaml';
|
||||
$singleTest = $input->getArgument(self::SINGLE);
|
||||
$fastTest = $input->getArgument(self::FAST);
|
||||
$wooVersion = $input->getArgument(self::WOOCOMMERCE_VERSION);
|
||||
$cache_dir = \sys_get_temp_dir() . '/codeception_cache';
|
||||
if (!\file_exists($cache_dir)) {
|
||||
\mkdir($cache_dir, 0777, \true);
|
||||
}
|
||||
\putenv('TMP_CACHE_DIR=' . $cache_dir);
|
||||
$codecept_param = ' --html --verbose -f ';
|
||||
$additionalParameters = ' -e CODECEPT_PARAM="' . $codecept_param . '" ';
|
||||
if (!empty($singleTest) && 'all' !== $singleTest) {
|
||||
$additionalParameters .= ' -e CODECEPT_PARAM="' . $codecept_param . ' acceptance ' . $singleTest . '" ';
|
||||
}
|
||||
if (!empty($wooVersion)) {
|
||||
$additionalParameters .= ' -e WOOCOMMERCE_VERSION="' . $wooVersion . '" ';
|
||||
}
|
||||
$runTestsCommand = 'docker-compose -f ' . $dockerComposeYaml . ' run ' . $additionalParameters . 'codecept';
|
||||
$output->writeln('Codeception command: ' . $runTestsCommand);
|
||||
$this->execAndOutput($runTestsCommand, $output);
|
||||
if (empty($fastTest) || self::FAST !== $fastTest) {
|
||||
$this->execAndOutput('docker-compose -f ' . $dockerComposeYaml . ' down -v', $output);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
<?php
|
||||
|
||||
namespace FcfVendor\WPDesk\Composer\Codeception\Commands;
|
||||
|
||||
use FcfVendor\Symfony\Component\Console\Input\InputArgument;
|
||||
use FcfVendor\Symfony\Component\Console\Input\InputInterface;
|
||||
use FcfVendor\Symfony\Component\Console\Output\OutputInterface;
|
||||
use FcfVendor\Symfony\Component\Yaml\Exception\ParseException;
|
||||
use FcfVendor\Symfony\Component\Yaml\Yaml;
|
||||
/**
|
||||
* Codeception tests run command.
|
||||
*
|
||||
* @package WPDesk\Composer\Codeception\Commands
|
||||
*/
|
||||
class RunLocalCodeceptionTests extends \FcfVendor\WPDesk\Composer\Codeception\Commands\RunCodeceptionTests
|
||||
{
|
||||
use LocalCodeceptionTrait;
|
||||
/**
|
||||
* Configure command.
|
||||
*/
|
||||
protected function configure()
|
||||
{
|
||||
parent::configure();
|
||||
$this->setName('run-local-codeception-tests')->setDescription('Run local codeception tests.')->setDefinition(array(new \FcfVendor\Symfony\Component\Console\Input\InputArgument(self::SINGLE, \FcfVendor\Symfony\Component\Console\Input\InputArgument::OPTIONAL, 'Name of Single test to run.', ' ')));
|
||||
}
|
||||
/**
|
||||
* Execute command.
|
||||
*
|
||||
* @param InputInterface $input
|
||||
* @param OutputInterface $output
|
||||
*
|
||||
* @return int 0 if everything went fine, or an error code
|
||||
*/
|
||||
protected function execute(\FcfVendor\Symfony\Component\Console\Input\InputInterface $input, \FcfVendor\Symfony\Component\Console\Output\OutputInterface $output)
|
||||
{
|
||||
$configuration = $this->getWpDeskConfiguration();
|
||||
$this->prepareWpConfig($output, $configuration);
|
||||
$singleTest = $input->getArgument(self::SINGLE);
|
||||
$sep = \DIRECTORY_SEPARATOR;
|
||||
$codecept = "vendor{$sep}bin{$sep}codecept";
|
||||
$cleanOutput = $codecept . ' clean';
|
||||
$this->execAndOutput($cleanOutput, $output);
|
||||
$runLocalTests = $codecept . ' run -f --steps --html --verbose acceptance ' . $singleTest;
|
||||
$this->execAndOutput($runLocalTests, $output);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
<?php
|
||||
|
||||
namespace FcfVendor\WPDesk\Composer\Codeception\Commands;
|
||||
|
||||
use FcfVendor\Symfony\Component\Console\Input\InputArgument;
|
||||
use FcfVendor\Symfony\Component\Console\Input\InputInterface;
|
||||
use FcfVendor\Symfony\Component\Console\Output\OutputInterface;
|
||||
use FcfVendor\Symfony\Component\Yaml\Exception\ParseException;
|
||||
use FcfVendor\Symfony\Component\Yaml\Yaml;
|
||||
/**
|
||||
* Codeception tests run command.
|
||||
*
|
||||
* @package WPDesk\Composer\Codeception\Commands
|
||||
*/
|
||||
class RunLocalCodeceptionTestsWithCoverage extends \FcfVendor\WPDesk\Composer\Codeception\Commands\RunCodeceptionTests
|
||||
{
|
||||
use LocalCodeceptionTrait;
|
||||
/**
|
||||
* Configure command.
|
||||
*/
|
||||
protected function configure()
|
||||
{
|
||||
parent::configure();
|
||||
$this->setName('run-local-codeception-tests-with-coverage')->setDescription('Run local codeception tests.')->setDefinition(array(new \FcfVendor\Symfony\Component\Console\Input\InputArgument(self::SINGLE, \FcfVendor\Symfony\Component\Console\Input\InputArgument::OPTIONAL, 'Name of Single test to run.', ' ')));
|
||||
}
|
||||
/**
|
||||
* Execute command.
|
||||
*
|
||||
* @param InputInterface $input
|
||||
* @param OutputInterface $output
|
||||
*
|
||||
* @return int 0 if everything went fine, or an error code
|
||||
*/
|
||||
protected function execute(\FcfVendor\Symfony\Component\Console\Input\InputInterface $input, \FcfVendor\Symfony\Component\Console\Output\OutputInterface $output)
|
||||
{
|
||||
$configuration = $this->getWpDeskConfiguration();
|
||||
$this->prepareWpConfig($output, $configuration);
|
||||
$singleTest = $input->getArgument(self::SINGLE);
|
||||
$sep = \DIRECTORY_SEPARATOR;
|
||||
$codecept = "vendor{$sep}bin{$sep}codecept";
|
||||
$cleanOutput = $codecept . ' clean';
|
||||
$this->execAndOutput($cleanOutput, $output);
|
||||
$runLocalTests = $codecept . ' run -f --steps --html --coverage --coverage-xml --coverage-html --verbose acceptance ' . $singleTest;
|
||||
$this->execAndOutput($runLocalTests, $output);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
namespace FcfVendor\WPDesk\Composer\Codeception\Commands;
|
||||
|
||||
/**
|
||||
* Trait with a sed like command
|
||||
* @see https://pl.wikipedia.org/wiki/Sed_(program)
|
||||
*
|
||||
* @package WPDesk\Composer\GitPlugin\Command
|
||||
*/
|
||||
trait SedTrait
|
||||
{
|
||||
/**
|
||||
* SED.
|
||||
*
|
||||
* @param string $file_pattern .
|
||||
* @param string $pattern .
|
||||
* @param string $replace .
|
||||
*
|
||||
* @return string[] array of changed files
|
||||
*/
|
||||
private function wpdeskSed($file_pattern, $pattern, $replace)
|
||||
{
|
||||
$changed_files = [];
|
||||
foreach (\glob($file_pattern) as $filename) {
|
||||
$input = \file_get_contents($filename);
|
||||
$output = \preg_replace($pattern, $replace, $input);
|
||||
if ($output !== $input) {
|
||||
$changed_files[] = $filename;
|
||||
\file_put_contents($filename, $output);
|
||||
}
|
||||
}
|
||||
return $changed_files;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Class SettingsException
|
||||
* @package WPDesk\Composer\Codeception\Commands
|
||||
*/
|
||||
namespace FcfVendor\WPDesk\Composer\Codeception\Commands;
|
||||
|
||||
/**
|
||||
* Settings Exception.
|
||||
*/
|
||||
class SettingsException extends \RuntimeException
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
<?php
|
||||
|
||||
namespace FcfVendor\WPDesk\Composer\Codeception;
|
||||
|
||||
use FcfVendor\Composer\Composer;
|
||||
use FcfVendor\Composer\IO\IOInterface;
|
||||
use FcfVendor\Composer\Plugin\Capable;
|
||||
use FcfVendor\Composer\Plugin\PluginInterface;
|
||||
/**
|
||||
* Composer plugin.
|
||||
*
|
||||
* @package WPDesk\Composer\Codeception
|
||||
*/
|
||||
class Plugin implements \FcfVendor\Composer\Plugin\PluginInterface, \FcfVendor\Composer\Plugin\Capable
|
||||
{
|
||||
/**
|
||||
* @var Composer
|
||||
*/
|
||||
private $composer;
|
||||
/**
|
||||
* @var IOInterface
|
||||
*/
|
||||
private $io;
|
||||
public function activate(\FcfVendor\Composer\Composer $composer, \FcfVendor\Composer\IO\IOInterface $io)
|
||||
{
|
||||
$this->composer = $composer;
|
||||
$this->io = $io;
|
||||
}
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function deactivate(\FcfVendor\Composer\Composer $composer, \FcfVendor\Composer\IO\IOInterface $io)
|
||||
{
|
||||
$this->composer = $composer;
|
||||
$this->io = $io;
|
||||
}
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function uninstall(\FcfVendor\Composer\Composer $composer, \FcfVendor\Composer\IO\IOInterface $io)
|
||||
{
|
||||
$this->composer = $composer;
|
||||
$this->io = $io;
|
||||
}
|
||||
public function getCapabilities()
|
||||
{
|
||||
return [\FcfVendor\Composer\Plugin\Capability\CommandProvider::class => \FcfVendor\WPDesk\Composer\Codeception\CommandProvider::class];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
{
|
||||
"name": "wpdesk\/wp-logs",
|
||||
"authors": [
|
||||
{
|
||||
"name": "Krzysiek",
|
||||
"email": "krzysiek@wpdesk.pl"
|
||||
}
|
||||
],
|
||||
"config": {
|
||||
"platform": {
|
||||
"php": "7.0.19"
|
||||
},
|
||||
"allow-plugins": {
|
||||
"dealerdirect\/phpcodesniffer-composer-installer": true
|
||||
}
|
||||
},
|
||||
"require": {
|
||||
"php": ">=7.0|^8",
|
||||
"psr\/log": "^1",
|
||||
"monolog\/monolog": "^1.23",
|
||||
"wpdesk\/wp-notice": "^3.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit\/phpunit": "^5",
|
||||
"squizlabs\/php_codesniffer": "^3.0.2",
|
||||
"wpdesk\/wp-code-sniffer": "^1.2.3"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"FcfVendor\\WPDesk\\Logger\\": "src\/"
|
||||
}
|
||||
},
|
||||
"scripts": {
|
||||
"phpunit-unit": "phpunit --configuration phpunit-unit.xml --coverage-text --colors=never",
|
||||
"phpunit-unit-fast": "phpunit --configuration phpunit-unit.xml --no-coverage",
|
||||
"phpunit-integration": "phpunit --configuration phpunit-integration.xml --coverage-text --colors=never",
|
||||
"phpunit-integration-fast": "phpunit --configuration phpunit-integration.xml --no-coverage"
|
||||
},
|
||||
"extra": {
|
||||
"text-domain": "wp-logs",
|
||||
"translations-folder": "lang",
|
||||
"po-files": {
|
||||
"pl_PL": "pl_PL.po",
|
||||
"en_AU": "en_AU.po",
|
||||
"en_CA": "en_CA.po",
|
||||
"en_GB": "en_GB.po",
|
||||
"es_ES": "es_ES.po",
|
||||
"de_DE": "de_DE.po"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
<?php
|
||||
|
||||
namespace FcfVendor\WPDesk\Logger;
|
||||
|
||||
use FcfVendor\Monolog\Handler\HandlerInterface;
|
||||
use FcfVendor\Monolog\Logger;
|
||||
use FcfVendor\Monolog\Registry;
|
||||
/**
|
||||
* Manages and facilitates creation of logger
|
||||
*
|
||||
* @package WPDesk\Logger
|
||||
*/
|
||||
class BasicLoggerFactory implements \FcfVendor\WPDesk\Logger\LoggerFactory
|
||||
{
|
||||
/** @var string Last created logger name/channel */
|
||||
private static $lastLoggerChannel;
|
||||
/**
|
||||
* Creates logger for plugin
|
||||
*
|
||||
* @param string $name The logging channel/name of logger
|
||||
* @param HandlerInterface[] $handlers Optional stack of handlers, the first one in the array is called first, etc.
|
||||
* @param callable[] $processors Optional array of processors
|
||||
* @return Logger
|
||||
*/
|
||||
public function createLogger($name, $handlers = array(), array $processors = array())
|
||||
{
|
||||
if (\FcfVendor\Monolog\Registry::hasLogger($name)) {
|
||||
return \FcfVendor\Monolog\Registry::getInstance($name);
|
||||
}
|
||||
self::$lastLoggerChannel = $name;
|
||||
$logger = new \FcfVendor\Monolog\Logger($name, $handlers, $processors);
|
||||
\FcfVendor\Monolog\Registry::addLogger($logger);
|
||||
return $logger;
|
||||
}
|
||||
/**
|
||||
* Returns created Logger by name or last created logger
|
||||
*
|
||||
* @param string $name Name of the logger
|
||||
*
|
||||
* @return Logger
|
||||
*/
|
||||
public function getLogger($name = null)
|
||||
{
|
||||
if ($name === null) {
|
||||
$name = self::$lastLoggerChannel;
|
||||
}
|
||||
return \FcfVendor\Monolog\Registry::getInstance($name);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,114 @@
|
||||
<?php
|
||||
|
||||
namespace FcfVendor\WPDesk\Logger;
|
||||
|
||||
use FcfVendor\Monolog\Logger;
|
||||
use Psr\Log\LogLevel;
|
||||
use WP_Error;
|
||||
use Exception;
|
||||
/**
|
||||
* Facilitates creation of logger with default WPDesk settings
|
||||
*
|
||||
* @deprecated Only for backward compatibility. Please use injected Logger compatible with PSR
|
||||
*
|
||||
* @package WPDesk\Logger
|
||||
*/
|
||||
class LoggerFacade
|
||||
{
|
||||
const BACKTRACE_FILENAME_KEY = 'file';
|
||||
/** @var WPDeskLoggerFactory */
|
||||
private static $factory;
|
||||
/**
|
||||
* Get logger by name. If not exists create one.
|
||||
*
|
||||
* @param string $name Name of the logger
|
||||
* @return Logger
|
||||
*/
|
||||
public static function getLogger($name = \FcfVendor\WPDesk\Logger\WPDeskLoggerFactory::DEFAULT_LOGGER_CHANNEL_NAME)
|
||||
{
|
||||
if (self::$factory === null) {
|
||||
self::$factory = new \FcfVendor\WPDesk\Logger\WPDeskLoggerFactory();
|
||||
}
|
||||
return self::$factory->createWPDeskLogger($name);
|
||||
}
|
||||
/**
|
||||
* Snake case alias for getLogger
|
||||
*
|
||||
* @param string $name
|
||||
*
|
||||
* @return Logger
|
||||
*/
|
||||
public static function get_logger($name = \FcfVendor\WPDesk\Logger\WPDeskLoggerFactory::DEFAULT_LOGGER_CHANNEL_NAME)
|
||||
{
|
||||
return self::getLogger($name);
|
||||
}
|
||||
/**
|
||||
* If set, logs are disabled
|
||||
*
|
||||
* @param string $name Name of the logger
|
||||
*/
|
||||
public static function set_disable_log($name = \FcfVendor\WPDesk\Logger\WPDeskLoggerFactory::DEFAULT_LOGGER_CHANNEL_NAME)
|
||||
{
|
||||
self::$factory->disableLog($name);
|
||||
}
|
||||
/**
|
||||
* Log this exception into WPDesk logger
|
||||
*
|
||||
* @param WP_Error $e Error to log.
|
||||
* @param array $backtrace Backtrace information with snapshot of error env.
|
||||
* @param array $context Context to log
|
||||
* @param string $level Level of error.
|
||||
*
|
||||
* @see http://php.net/manual/en/function.debug-backtrace.php
|
||||
*/
|
||||
public static function log_wp_error(\WP_Error $e, array $backtrace, array $context = array(), $level = \Psr\Log\LogLevel::ERROR)
|
||||
{
|
||||
$message = 'Error: ' . \get_class($e) . ' Code: ' . $e->get_error_code() . ' Message: ' . $e->get_error_message();
|
||||
self::log_message_backtrace($message, $backtrace, $context, $level);
|
||||
}
|
||||
/**
|
||||
* Log this exception into WPDesk logger
|
||||
*
|
||||
* @param Exception $e Exception to log.
|
||||
* @param array $context Context to log
|
||||
* @param string $level Level of error.
|
||||
*/
|
||||
public static function log_exception(\Exception $e, array $context = array(), $level = \Psr\Log\LogLevel::ERROR)
|
||||
{
|
||||
$message = 'Exception: ' . \get_class($e) . ' Code: ' . $e->getCode() . ' Message: ' . $e->getMessage() . ' Stack: ' . $e->getTraceAsString();
|
||||
self::log_message($message, \array_merge($context, ['exception' => $e]), $e->getFile(), $level);
|
||||
}
|
||||
/**
|
||||
* Log message into WPDesk logger
|
||||
*
|
||||
* @param string $message Message to log.
|
||||
* @param array $context Context to log
|
||||
* @param string $source Source of the message - can be file name, class name or whatever.
|
||||
* @param string $level Level of error.
|
||||
*/
|
||||
public static function log_message($message, array $context = array(), $source = null, $level = \Psr\Log\LogLevel::DEBUG)
|
||||
{
|
||||
$logger = self::getLogger();
|
||||
if ($source !== null) {
|
||||
$context = \array_merge($context, ['source' => $source]);
|
||||
}
|
||||
$logger->log($level, $message, $context);
|
||||
}
|
||||
/**
|
||||
* Log message into WPDesk logger
|
||||
*
|
||||
* @param string $message Message to log.
|
||||
* @param array $backtrace Backtrace information with snapshot of error env.
|
||||
* @param array $context Context to log
|
||||
* @param string $level Level of error.
|
||||
*/
|
||||
public static function log_message_backtrace($message, array $backtrace, array $context = array(), $level = \Psr\Log\LogLevel::DEBUG)
|
||||
{
|
||||
$message .= ' Backtrace: ' . \json_encode($backtrace);
|
||||
$source = null;
|
||||
if (isset($backtrace[self::BACKTRACE_FILENAME_KEY])) {
|
||||
$source = $backtrace[self::BACKTRACE_FILENAME_KEY];
|
||||
}
|
||||
self::log_message($message, $context, $source, $level);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
namespace FcfVendor\WPDesk\Logger;
|
||||
|
||||
use FcfVendor\Monolog\Logger;
|
||||
/*
|
||||
* @package WPDesk\Logger
|
||||
*/
|
||||
interface LoggerFactory
|
||||
{
|
||||
/**
|
||||
* Returns created Logger
|
||||
*
|
||||
* @param string $name
|
||||
*
|
||||
* @return Logger
|
||||
*/
|
||||
public function getLogger($name);
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
<?php
|
||||
|
||||
namespace FcfVendor\WPDesk\Logger;
|
||||
|
||||
use Psr\Log\LogLevel;
|
||||
final class Settings
|
||||
{
|
||||
/** @var string */
|
||||
public $level = \Psr\Log\LogLevel::DEBUG;
|
||||
/** @var bool */
|
||||
public $use_wc_log = \true;
|
||||
/** @var bool */
|
||||
public $use_wp_log = \true;
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
<?php
|
||||
|
||||
declare (strict_types=1);
|
||||
namespace FcfVendor\WPDesk\Logger;
|
||||
|
||||
use FcfVendor\Monolog\Handler\HandlerInterface;
|
||||
use FcfVendor\Monolog\Handler\NullHandler;
|
||||
use FcfVendor\Monolog\Logger;
|
||||
use FcfVendor\Monolog\Handler\ErrorLogHandler;
|
||||
use FcfVendor\WPDesk\Logger\WC\WooCommerceHandler;
|
||||
final class SimpleLoggerFactory implements \FcfVendor\WPDesk\Logger\LoggerFactory
|
||||
{
|
||||
/** @var Settings */
|
||||
private $options;
|
||||
/** @var string */
|
||||
private $channel;
|
||||
/** @var Logger */
|
||||
private $logger;
|
||||
public function __construct(string $channel, \FcfVendor\WPDesk\Logger\Settings $options = null)
|
||||
{
|
||||
$this->channel = $channel;
|
||||
$this->options = $options ?? new \FcfVendor\WPDesk\Logger\Settings();
|
||||
}
|
||||
public function getLogger($name = null) : \FcfVendor\Monolog\Logger
|
||||
{
|
||||
if ($this->logger) {
|
||||
return $this->logger;
|
||||
}
|
||||
$logger = new \FcfVendor\Monolog\Logger($this->channel);
|
||||
if ($this->options->use_wc_log && \function_exists('wc_get_logger')) {
|
||||
$logger->pushHandler(new \FcfVendor\WPDesk\Logger\WC\WooCommerceHandler(\wc_get_logger(), $this->channel));
|
||||
}
|
||||
// Adding WooCommerce logger may have failed, if so add WP by default.
|
||||
if ($this->options->use_wp_log || empty($logger->getHandlers())) {
|
||||
$logger->pushHandler($this->get_wp_handler());
|
||||
}
|
||||
return $this->logger = $logger;
|
||||
}
|
||||
private function get_wp_handler() : \FcfVendor\Monolog\Handler\HandlerInterface
|
||||
{
|
||||
if (\defined('FcfVendor\\WP_DEBUG_LOG') && WP_DEBUG_LOG) {
|
||||
return new \FcfVendor\Monolog\Handler\ErrorLogHandler(\FcfVendor\Monolog\Handler\ErrorLogHandler::OPERATING_SYSTEM, $this->options->level);
|
||||
}
|
||||
return new \FcfVendor\Monolog\Handler\NullHandler();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
<?php
|
||||
|
||||
namespace FcfVendor\WPDesk\Logger\WC\Exception;
|
||||
|
||||
class WCLoggerAlreadyCaptured extends \RuntimeException
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,132 @@
|
||||
<?php
|
||||
|
||||
namespace FcfVendor\WPDesk\Logger\WC;
|
||||
|
||||
use FcfVendor\Monolog\Logger;
|
||||
use FcfVendor\WPDesk\Logger\WC\Exception\WCLoggerAlreadyCaptured;
|
||||
/**
|
||||
* Can capture default WooCommerce logger
|
||||
*
|
||||
* @package WPDesk\Logger
|
||||
*/
|
||||
class WooCommerceCapture
|
||||
{
|
||||
const WOOCOMMERCE_LOGGER_FILTER = 'woocommerce_logging_class';
|
||||
const WOOCOMMERCE_AFTER_IS_LOADED_ACTION = 'woocommerce_loaded';
|
||||
/** @var string Minimal version of WooCommerce supported by logger capture */
|
||||
const SUPPORTED_WC_VERSION = '3.5.0';
|
||||
/**
|
||||
* Is logger filter captured by library.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
private $isCaptured = \false;
|
||||
/**
|
||||
* Our monolog
|
||||
*
|
||||
* @var Logger
|
||||
*/
|
||||
private $monolog;
|
||||
/**
|
||||
* Original WC Logger
|
||||
*
|
||||
* @var \WC_Logger_Interface
|
||||
*/
|
||||
private $originalWCLogger;
|
||||
/**
|
||||
* WordPress hook function to return our logger
|
||||
*
|
||||
* @var ?callable
|
||||
*/
|
||||
private $captureHookFunction;
|
||||
/**
|
||||
* WordPress hook function to return original wc logger
|
||||
*
|
||||
* @var ?callable
|
||||
*/
|
||||
private $freeHookFunction;
|
||||
public function __construct(\FcfVendor\Monolog\Logger $monolog)
|
||||
{
|
||||
$this->monolog = $monolog;
|
||||
}
|
||||
/**
|
||||
* Prepares callable property captureHookFunction.
|
||||
* For it to work WC have to be loaded
|
||||
*/
|
||||
private function prepareCaptureHookCallable()
|
||||
{
|
||||
$monolog = $this->monolog;
|
||||
if ($this->captureHookFunction === null) {
|
||||
$this->captureHookFunction = function () use($monolog) {
|
||||
return new \FcfVendor\WPDesk\Logger\WC\WooCommerceMonologPlugin($monolog, $this->originalWCLogger);
|
||||
};
|
||||
$this->monolog->pushHandler(new \FcfVendor\WPDesk\Logger\WC\WooCommerceHandler($this->originalWCLogger));
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Is this version of WooCommerce is supported by logger capture
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function isSupportedWCVersion()
|
||||
{
|
||||
return \class_exists(\WooCommerce::class) && \version_compare(\WooCommerce::instance()->version, self::SUPPORTED_WC_VERSION, '>=');
|
||||
}
|
||||
/**
|
||||
* Capture WooCommerce logger and inject our decorated Logger
|
||||
*/
|
||||
public function captureWcLogger()
|
||||
{
|
||||
if (self::isSupportedWCVersion()) {
|
||||
if ($this->isCaptured) {
|
||||
throw new \FcfVendor\WPDesk\Logger\WC\Exception\WCLoggerAlreadyCaptured('Try to free wc logger first.');
|
||||
}
|
||||
if ($this->isWooCommerceLoggerAvailable()) {
|
||||
$this->prepareFreeHookCallable();
|
||||
$this->prepareCaptureHookCallable();
|
||||
\remove_filter(self::WOOCOMMERCE_LOGGER_FILTER, $this->freeHookFunction);
|
||||
\add_filter(self::WOOCOMMERCE_LOGGER_FILTER, $this->captureHookFunction);
|
||||
$this->isCaptured = \true;
|
||||
} elseif (\function_exists('add_action')) {
|
||||
\add_action(self::WOOCOMMERCE_AFTER_IS_LOADED_ACTION, [$this, 'captureWcLogger']);
|
||||
} else {
|
||||
$this->monolog->alert('Cannot capture WC - WordPress is not available.');
|
||||
}
|
||||
} else {
|
||||
$this->monolog->alert('Cannot capture WC - WooCommerce version is not supported.');
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Can i fetch WC Logger?
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function isWooCommerceLoggerAvailable()
|
||||
{
|
||||
return \function_exists('wc_get_logger');
|
||||
}
|
||||
/**
|
||||
* Prepares callable property freeHookFunction.
|
||||
* For it to work WC have to be loaded
|
||||
*/
|
||||
private function prepareFreeHookCallable()
|
||||
{
|
||||
if ($this->freeHookFunction === null) {
|
||||
$this->originalWCLogger = $logger = \wc_get_logger();
|
||||
$this->freeHookFunction = function () use($logger) {
|
||||
return $logger;
|
||||
};
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Remove WooCommerce logger injection
|
||||
*/
|
||||
public function freeWcLogger()
|
||||
{
|
||||
if ($this->isCaptured) {
|
||||
\remove_filter(self::WOOCOMMERCE_LOGGER_FILTER, $this->captureHookFunction);
|
||||
\add_filter(self::WOOCOMMERCE_LOGGER_FILTER, $this->freeHookFunction);
|
||||
$this->isCaptured = \false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
namespace FcfVendor\WPDesk\Logger\WC;
|
||||
|
||||
use FcfVendor\Monolog\Handler\AbstractProcessingHandler;
|
||||
use FcfVendor\Monolog\Logger;
|
||||
/**
|
||||
* Class WooCommerceFactory
|
||||
*/
|
||||
class WooCommerceHandler extends \FcfVendor\Monolog\Handler\AbstractProcessingHandler
|
||||
{
|
||||
const DEFAULT_WC_SOURCE = 'wpdesk-logger';
|
||||
/** @var \WC_Logger_Interface */
|
||||
private $wc_logger;
|
||||
/** @var string */
|
||||
private $channel;
|
||||
/**
|
||||
* Writes the record down to the log of the implementing handler
|
||||
*
|
||||
* @param array $record
|
||||
* @return void
|
||||
*/
|
||||
protected function write(array $record)
|
||||
{
|
||||
$context = \array_merge(['source' => $this->channel], $record['extra'], $record['context']);
|
||||
$this->wc_logger->log($this->convertMonologLevelToWC($record['level']), $record['message'], $context);
|
||||
}
|
||||
/**
|
||||
* @param int $level
|
||||
* @return string
|
||||
*/
|
||||
private function convertMonologLevelToWC($level)
|
||||
{
|
||||
return \FcfVendor\Monolog\Logger::getLevelName($level);
|
||||
}
|
||||
public function __construct(\WC_Logger_Interface $originalWcLogger, string $channel = self::DEFAULT_WC_SOURCE)
|
||||
{
|
||||
parent::__construct();
|
||||
$this->wc_logger = $originalWcLogger;
|
||||
$this->channel = $channel;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,165 @@
|
||||
<?php
|
||||
|
||||
namespace FcfVendor\WPDesk\Logger\WC;
|
||||
|
||||
use FcfVendor\Monolog\Logger;
|
||||
use Psr\Log\LogLevel;
|
||||
use WC_Log_Levels;
|
||||
/**
|
||||
* Can decorate monolog with WC_Logger_Interface
|
||||
*
|
||||
* @package WPDesk\Logger
|
||||
*/
|
||||
class WooCommerceMonologPlugin implements \WC_Logger_Interface
|
||||
{
|
||||
/** @var Logger */
|
||||
private $monolog;
|
||||
/** @var \WC_Logger */
|
||||
private $originalWCLogger;
|
||||
public function __construct(\FcfVendor\Monolog\Logger $monolog, \WC_Logger_Interface $originalLogger)
|
||||
{
|
||||
$this->monolog = $monolog;
|
||||
$this->originalWCLogger = $originalLogger;
|
||||
}
|
||||
/**
|
||||
* Method added for compatibility with \WC_Logger
|
||||
*
|
||||
* @param string $source
|
||||
*/
|
||||
public function clear($source = '')
|
||||
{
|
||||
$this->originalWCLogger->clear($source);
|
||||
}
|
||||
/**
|
||||
* Method added for compatibility with \WC_Logger
|
||||
*/
|
||||
public function clear_expired_logs()
|
||||
{
|
||||
$this->originalWCLogger->clear_expired_logs();
|
||||
}
|
||||
/**
|
||||
* Method for compatibility reason. Do not use.
|
||||
*
|
||||
* @param string $handle
|
||||
* @param string $message
|
||||
* @param string $level
|
||||
* @return bool|void
|
||||
*
|
||||
* @deprecated
|
||||
*/
|
||||
public function add($handle, $message, $level = \WC_Log_Levels::NOTICE)
|
||||
{
|
||||
$this->log($message, $level);
|
||||
}
|
||||
/**
|
||||
* System is unusable.
|
||||
*
|
||||
* @param string $message
|
||||
* @param array $context
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function emergency($message, $context = array())
|
||||
{
|
||||
$this->log(\Psr\Log\LogLevel::EMERGENCY, $message, $context);
|
||||
}
|
||||
public function log($level, $message, $context = [])
|
||||
{
|
||||
$this->monolog->log($level, $message, $context);
|
||||
}
|
||||
/**
|
||||
* Action must be taken immediately.
|
||||
*
|
||||
* Example: Entire website down, database unavailable, etc. This should
|
||||
* trigger the SMS alerts and wake you up.
|
||||
*
|
||||
* @param string $message
|
||||
* @param array $context
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function alert($message, $context = array())
|
||||
{
|
||||
$this->log(\Psr\Log\LogLevel::ALERT, $message, $context);
|
||||
}
|
||||
/**
|
||||
* Critical conditions.
|
||||
*
|
||||
* Example: Application component unavailable, unexpected exception.
|
||||
*
|
||||
* @param string $message
|
||||
* @param array $context
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function critical($message, $context = array())
|
||||
{
|
||||
$this->log(\Psr\Log\LogLevel::CRITICAL, $message, $context);
|
||||
}
|
||||
/**
|
||||
* Runtime errors that do not require immediate action but should typically
|
||||
* be logged and monitored.
|
||||
*
|
||||
* @param string $message
|
||||
* @param array $context
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function error($message, $context = array())
|
||||
{
|
||||
$this->log(\Psr\Log\LogLevel::ERROR, $message, $context);
|
||||
}
|
||||
/**
|
||||
* Exceptional occurrences that are not errors.
|
||||
*
|
||||
* Example: Use of deprecated APIs, poor use of an API, undesirable things
|
||||
* that are not necessarily wrong.
|
||||
*
|
||||
* @param string $message
|
||||
* @param array $context
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function warning($message, $context = array())
|
||||
{
|
||||
$this->log(\Psr\Log\LogLevel::WARNING, $message, $context);
|
||||
}
|
||||
/**
|
||||
* Normal but significant events.
|
||||
*
|
||||
* @param string $message
|
||||
* @param array $context
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function notice($message, $context = array())
|
||||
{
|
||||
$this->log(\Psr\Log\LogLevel::NOTICE, $message, $context);
|
||||
}
|
||||
/**
|
||||
* Interesting events.
|
||||
*
|
||||
* Example: User logs in, SQL logs.
|
||||
*
|
||||
* @param string $message
|
||||
* @param array $context
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function info($message, $context = array())
|
||||
{
|
||||
$this->log(\Psr\Log\LogLevel::INFO, $message, $context);
|
||||
}
|
||||
/**
|
||||
* Detailed debug information.
|
||||
*
|
||||
* @param string $message
|
||||
* @param array $context
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function debug($message, $context = array())
|
||||
{
|
||||
$this->log(\Psr\Log\LogLevel::DEBUG, $message, $context);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,127 @@
|
||||
<?php
|
||||
|
||||
namespace FcfVendor\WPDesk\Logger\WP;
|
||||
|
||||
class WPCapture
|
||||
{
|
||||
/** @var string */
|
||||
private $filename;
|
||||
const LOG_DIR = 'wpdesk-logs';
|
||||
public function __construct($filename)
|
||||
{
|
||||
$this->filename = $filename;
|
||||
}
|
||||
/**
|
||||
* Add notice for directory.
|
||||
*
|
||||
* @param string $dir Directory.
|
||||
*/
|
||||
private function add_notice_for_dir($dir)
|
||||
{
|
||||
new \FcfVendor\WPDesk\Notice\Notice(\sprintf(
|
||||
// Translators: directory.
|
||||
\__('Can not enable WP Desk Debug log! Cannot create directory %s or this directory is not writeable!', 'flexible-checkout-fields'),
|
||||
$dir
|
||||
), \FcfVendor\WPDesk\Notice\Notice::NOTICE_TYPE_ERROR);
|
||||
}
|
||||
/**
|
||||
* Add notice for file.
|
||||
*
|
||||
* @param string $file File..
|
||||
*/
|
||||
private function add_notice_for_file($file)
|
||||
{
|
||||
new \FcfVendor\WPDesk\Notice\Notice(\sprintf(
|
||||
// Translators: directory.
|
||||
\__('Can not enable WP Desk Debug log! Cannot create file %s!', 'flexible-checkout-fields'),
|
||||
$file
|
||||
), \FcfVendor\WPDesk\Notice\Notice::NOTICE_TYPE_ERROR);
|
||||
}
|
||||
/**
|
||||
* Is debug log writable.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function is_debug_log_writable_or_show_notice()
|
||||
{
|
||||
$log_dir = $this->get_log_dir();
|
||||
$log_file = $this->get_log_file();
|
||||
$index_file = $this->get_index_file();
|
||||
if (!\file_exists($log_dir)) {
|
||||
if (!\mkdir($log_dir, 0777, \true)) {
|
||||
$this->add_notice_for_dir($log_dir);
|
||||
return \false;
|
||||
}
|
||||
}
|
||||
if (!\file_exists($index_file)) {
|
||||
$index_html = \fopen($index_file, 'w');
|
||||
if (\false === $index_html) {
|
||||
$this->add_notice_for_file($index_file);
|
||||
return \false;
|
||||
} else {
|
||||
\fclose($index_html);
|
||||
}
|
||||
}
|
||||
if (!\file_exists($log_file)) {
|
||||
$log = \fopen($log_file, 'w');
|
||||
if (\false === $log) {
|
||||
$this->add_notice_for_file($log_file);
|
||||
return \false;
|
||||
} else {
|
||||
\fclose($log);
|
||||
}
|
||||
}
|
||||
if (!\is_writable($log_file)) {
|
||||
$this->add_notice_for_file($log_file);
|
||||
return \false;
|
||||
}
|
||||
return \true;
|
||||
}
|
||||
/**
|
||||
* Init debug log file.
|
||||
*/
|
||||
public function init_debug_log_file()
|
||||
{
|
||||
if ($this->is_debug_log_writable_or_show_notice()) {
|
||||
\ini_set('log_errors', 1);
|
||||
\ini_set('error_log', $this->get_log_file());
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Get uploads dir.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function get_uploads_dir()
|
||||
{
|
||||
$upload_dir = \wp_upload_dir();
|
||||
return \untrailingslashit($upload_dir['basedir']);
|
||||
}
|
||||
/**
|
||||
* Get log dir.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function get_log_dir()
|
||||
{
|
||||
return \trailingslashit($this->get_uploads_dir()) . self::LOG_DIR;
|
||||
}
|
||||
/**
|
||||
* Get log file.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_log_file()
|
||||
{
|
||||
return \trailingslashit($this->get_log_dir()) . $this->filename;
|
||||
}
|
||||
/**
|
||||
* Get log file.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function get_index_file()
|
||||
{
|
||||
return \trailingslashit($this->get_log_dir()) . 'index.html';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,209 @@
|
||||
<?php
|
||||
|
||||
namespace FcfVendor\WPDesk\Logger;
|
||||
|
||||
use Exception;
|
||||
use InvalidArgumentException;
|
||||
use LogicException;
|
||||
use FcfVendor\Monolog\Handler\NullHandler;
|
||||
use FcfVendor\Monolog\Logger;
|
||||
use FcfVendor\Monolog\Registry;
|
||||
use FcfVendor\Monolog\Handler\StreamHandler;
|
||||
use Psr\Log\LogLevel;
|
||||
use FcfVendor\WPDesk\Logger\WC\WooCommerceCapture;
|
||||
use FcfVendor\WPDesk\Logger\WP\WPCapture;
|
||||
/**
|
||||
* Manages and facilitates creation of logger
|
||||
*
|
||||
* @package WPDesk\Logger
|
||||
*/
|
||||
class WPDeskLoggerFactory extends \FcfVendor\WPDesk\Logger\BasicLoggerFactory
|
||||
{
|
||||
const DEFAULT_LOGGER_CHANNEL_NAME = 'wpdesk';
|
||||
/** @var string Log to file when level is */
|
||||
const LEVEL_WPDESK_FILE = \Psr\Log\LogLevel::DEBUG;
|
||||
/** @var string Log to wc logger when level is */
|
||||
const LEVEL_WC = \Psr\Log\LogLevel::ERROR;
|
||||
/** @var bool Will factory return null logger or not */
|
||||
public static $shouldLoggerBeActivated = \true;
|
||||
/**
|
||||
* Remove static instances. In general should be use only testing purposes.
|
||||
*
|
||||
* @param string $name Name of the logger
|
||||
*/
|
||||
public static function tearDown($name = self::DEFAULT_LOGGER_CHANNEL_NAME)
|
||||
{
|
||||
if (\FcfVendor\Monolog\Registry::hasLogger($name)) {
|
||||
\FcfVendor\Monolog\Registry::removeLogger($name);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Disable logger. Still exists but logs won't be saved
|
||||
*
|
||||
* @param string $name Name of the logger
|
||||
*/
|
||||
public function disableLog($name = self::DEFAULT_LOGGER_CHANNEL_NAME)
|
||||
{
|
||||
if (!\FcfVendor\Monolog\Registry::hasLogger($name)) {
|
||||
$this->createWPDeskLogger($name);
|
||||
}
|
||||
if (\FcfVendor\Monolog\Registry::hasLogger($name)) {
|
||||
/** @var Logger $logger */
|
||||
$logger = \FcfVendor\Monolog\Registry::getInstance($name);
|
||||
$this->removeAllHandlers($logger);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Creates default WPDesk logger.
|
||||
*
|
||||
* Requirements:
|
||||
* - get_option, add/remove_action, add/remove filter and WP_CONTENT_DIR should be available for logger.
|
||||
*
|
||||
* Assumptions:
|
||||
* - logger is actively working when 'wpdesk_helper_options' has 'debug_log' set to '1';
|
||||
* - fatal errors, exception and standard errors are recorded but in a transparent way;
|
||||
* - WooCommerce logger is captured and returns this logger; That is true of default logger is instantiated.
|
||||
* - logs are still correctly written to WooCommerce subsystem in a transparent way;
|
||||
* - all recorded errors are written to WPDesk file.
|
||||
*
|
||||
* @param string $name Name of the logger
|
||||
* @return Logger
|
||||
*/
|
||||
public function createWPDeskLogger($name = self::DEFAULT_LOGGER_CHANNEL_NAME)
|
||||
{
|
||||
if (!self::$shouldLoggerBeActivated) {
|
||||
return new \FcfVendor\Monolog\Logger($name);
|
||||
}
|
||||
if (\FcfVendor\Monolog\Registry::hasLogger($name)) {
|
||||
return \FcfVendor\Monolog\Registry::getInstance($name);
|
||||
}
|
||||
$logger = $this->createLogger($name);
|
||||
if (self::isWPLogPermitted()) {
|
||||
$this->appendMainLog($logger);
|
||||
}
|
||||
if ($name !== self::DEFAULT_LOGGER_CHANNEL_NAME) {
|
||||
$this->appendFileLog($logger, $this->getFileName($name));
|
||||
} else {
|
||||
$this->captureWooCommerce($logger);
|
||||
}
|
||||
return $logger;
|
||||
}
|
||||
/**
|
||||
* Is capturing the php log is permitted.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function isWPLogPermitted()
|
||||
{
|
||||
return \apply_filters('wpdesk_is_wp_log_capture_permitted', \true);
|
||||
}
|
||||
/**
|
||||
* @param $logger
|
||||
*/
|
||||
private function appendMainLog($logger)
|
||||
{
|
||||
$wpCapture = $this->captureWPLog();
|
||||
if (\is_writable($wpCapture->get_log_file())) {
|
||||
$this->appendFileLog($logger, $wpCapture->get_log_file());
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @param Logger $logger
|
||||
*/
|
||||
private function appendFileLog($logger, $filename)
|
||||
{
|
||||
try {
|
||||
$this->pushFileHandle($filename, $logger);
|
||||
} catch (\InvalidArgumentException $e) {
|
||||
$logger->emergency('Main log file could not be created - invalid filename.');
|
||||
} catch (\Exception $e) {
|
||||
$logger->emergency('Main log file could not be written.');
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @return WPCapture
|
||||
*/
|
||||
private function captureWPLog()
|
||||
{
|
||||
static $wpCapture;
|
||||
if (!$wpCapture) {
|
||||
$wpCapture = new \FcfVendor\WPDesk\Logger\WP\WPCapture(\basename($this->getFileName()));
|
||||
$wpCapture->init_debug_log_file();
|
||||
}
|
||||
return $wpCapture;
|
||||
}
|
||||
/**
|
||||
* Capture WooCommerce and add handle
|
||||
*
|
||||
* @param Logger $logger
|
||||
*/
|
||||
private function captureWooCommerce(\FcfVendor\Monolog\Logger $logger)
|
||||
{
|
||||
if (!\defined('FcfVendor\\WC_LOG_THRESHOLD')) {
|
||||
\define('FcfVendor\\WC_LOG_THRESHOLD', self::LEVEL_WC);
|
||||
}
|
||||
$wcIntegration = new \FcfVendor\WPDesk\Logger\WC\WooCommerceCapture($logger);
|
||||
$wcIntegration->captureWcLogger();
|
||||
}
|
||||
/**
|
||||
* Add WPDesk log file handle
|
||||
*
|
||||
* @param Logger $logger
|
||||
* @param string $filename Name of file with path
|
||||
*
|
||||
* @throws Exception If a missing directory is not buildable
|
||||
* @throws InvalidArgumentException If stream is not a resource or string
|
||||
*/
|
||||
private function pushFileHandle($filename, \FcfVendor\Monolog\Logger $logger)
|
||||
{
|
||||
$logger->pushHandler(new \FcfVendor\Monolog\Handler\StreamHandler($filename, self::LEVEL_WPDESK_FILE));
|
||||
}
|
||||
/**
|
||||
* Get filename old way
|
||||
*
|
||||
* @deprecated not sure if can remove
|
||||
*/
|
||||
public function getWPDeskFileName()
|
||||
{
|
||||
return $this->getFileName();
|
||||
}
|
||||
/**
|
||||
* Returns WPDesk filename.
|
||||
*
|
||||
* @param string $name Name of the logger
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getFileName($name = self::DEFAULT_LOGGER_CHANNEL_NAME)
|
||||
{
|
||||
$upload_dir = \wp_upload_dir();
|
||||
return \trailingslashit(\untrailingslashit($upload_dir['basedir'])) . \FcfVendor\WPDesk\Logger\WP\WPCapture::LOG_DIR . \DIRECTORY_SEPARATOR . $name . '_debug.log';
|
||||
}
|
||||
/**
|
||||
* Removes all handlers from logger
|
||||
*
|
||||
* @param Logger $logger
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function removeAllHandlers(\FcfVendor\Monolog\Logger $logger)
|
||||
{
|
||||
try {
|
||||
while (\true) {
|
||||
$logger->popHandler();
|
||||
}
|
||||
} catch (\LogicException $e) {
|
||||
$logger->pushHandler(new \FcfVendor\Monolog\Handler\NullHandler());
|
||||
}
|
||||
}
|
||||
/**
|
||||
* is WPDesk file log is working(writable, exists, connected).
|
||||
* @param string $name Name of the logger
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isLogWorking($name = self::DEFAULT_LOGGER_CHANNEL_NAME)
|
||||
{
|
||||
return \FcfVendor\Monolog\Registry::hasLogger($name);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
<?php
|
||||
|
||||
namespace FcfVendor;
|
||||
|
||||
if (!\defined('ABSPATH')) {
|
||||
exit;
|
||||
}
|
||||
if (!\class_exists('FcfVendor\\WPDesk_Logger_Factory')) {
|
||||
/**
|
||||
* @deprecated Only for backward compatibility. Please use injected Logger compatible with PSR
|
||||
*/
|
||||
class WPDesk_Logger_Factory
|
||||
{
|
||||
/**
|
||||
* Static logger storage
|
||||
*
|
||||
* @var WPDesk_Logger
|
||||
*/
|
||||
private static $logger = null;
|
||||
const BACKTRACE_FILENAME_KEY = 'file';
|
||||
const WPDESK_LOG_ACTION_NAME = 'wpdesk_log';
|
||||
/**
|
||||
* Creates and returns a logger
|
||||
*
|
||||
* @return WPDesk_Logger
|
||||
*/
|
||||
public static function create_logger()
|
||||
{
|
||||
if (empty(self::$logger)) {
|
||||
$logger = new \FcfVendor\WPDesk_Logger();
|
||||
$logger->attach_hooks();
|
||||
self::$logger = $logger;
|
||||
}
|
||||
return self::$logger;
|
||||
}
|
||||
/**
|
||||
* Log this exception into wpdesk logger
|
||||
*
|
||||
* @param WP_Error $e Error to log.
|
||||
* @param array $backtrace Backtrace information with snapshot of error env.
|
||||
*
|
||||
* @see http://php.net/manual/en/function.debug-backtrace.php
|
||||
*/
|
||||
public static function log_wp_error(\WP_Error $e, array $backtrace)
|
||||
{
|
||||
$message = 'Error: ' . \get_class($e) . ' Code: ' . $e->get_error_code() . ' Message: ' . $e->get_error_message();
|
||||
self::log_message_backtrace($message, \FcfVendor\WPDesk_Logger::ERROR, $backtrace);
|
||||
}
|
||||
/**
|
||||
* Log this exception into WPDesk logger
|
||||
*
|
||||
* @param Exception $e Exception to log.
|
||||
*/
|
||||
public static function log_exception(\Exception $e)
|
||||
{
|
||||
$message = 'Exception: ' . \get_class($e) . ' Code: ' . $e->getCode() . ' Message: ' . $e->getMessage() . ' Stack: ' . $e->getTraceAsString();
|
||||
self::log_message($message, $e->getFile(), \FcfVendor\WPDesk_Logger::ERROR);
|
||||
}
|
||||
/**
|
||||
* Log message into WPDesk logger
|
||||
*
|
||||
* @param string $message Message to log.
|
||||
* @param string $source Source of the message - can be file name, class name or whatever.
|
||||
* @param string $level Level of error.
|
||||
*/
|
||||
public static function log_message($message, $source = 'unknown', $level = \FcfVendor\WPDesk_Logger::DEBUG)
|
||||
{
|
||||
self::create_logger();
|
||||
\do_action(self::WPDESK_LOG_ACTION_NAME, $level, $source, $message);
|
||||
self::$logger->wpdesk_log($level, $source, $message);
|
||||
}
|
||||
/**
|
||||
* Log message into WPDesk logger
|
||||
*
|
||||
* @param string $message Message to log.
|
||||
* @param string $level Level of error.
|
||||
* @param array $backtrace Backtrace information with snapshot of error env.
|
||||
*/
|
||||
public static function log_message_backtrace($message, $level = \FcfVendor\WPDesk_Logger::DEBUG, array $backtrace)
|
||||
{
|
||||
$message .= ' Backtrace: ' . \json_encode($backtrace);
|
||||
if (isset($backtrace[self::BACKTRACE_FILENAME_KEY])) {
|
||||
$filename = $backtrace[self::BACKTRACE_FILENAME_KEY];
|
||||
} else {
|
||||
$filename = 'unknown';
|
||||
}
|
||||
self::log_message($message, $filename, $level);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
<?php
|
||||
|
||||
namespace FcfVendor;
|
||||
|
||||
if (!\defined('ABSPATH')) {
|
||||
exit;
|
||||
}
|
||||
if (!\class_exists('FcfVendor\\WPDesk_Logger')) {
|
||||
/**
|
||||
* @deprecated Only for backward compatibility. Please use injected Logger compatible with PSR
|
||||
*/
|
||||
class WPDesk_Logger
|
||||
{
|
||||
/** @var \Psr\Log\LoggerInterface */
|
||||
static $logger;
|
||||
const EMERGENCY = 'emergency';
|
||||
const ALERT = 'alert';
|
||||
const CRITICAL = 'critical';
|
||||
const ERROR = 'error';
|
||||
const WARNING = 'warning';
|
||||
const NOTICE = 'notice';
|
||||
const INFO = 'info';
|
||||
const DEBUG = 'debug';
|
||||
public function __construct()
|
||||
{
|
||||
if (!self::$logger) {
|
||||
$loggerFactroy = new \FcfVendor\WPDesk\Logger\WPDeskLoggerFactory();
|
||||
self::$logger = $loggerFactroy->createWPDeskLogger();
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Level strings mapped to integer severity.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $level_to_severity = [self::EMERGENCY => 800, self::ALERT => 700, self::CRITICAL => 600, self::ERROR => 500, self::WARNING => 400, self::NOTICE => 300, self::INFO => 200, self::DEBUG => 100];
|
||||
/**
|
||||
* Attach hooks
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function attach_hooks()
|
||||
{
|
||||
\add_action('plugins_loaded', [$this, 'plugins_loaded']);
|
||||
\add_filter('wpdesk_logger_level_options', [$this, 'wpdesk_logger_level_options']);
|
||||
}
|
||||
public function plugins_loaded()
|
||||
{
|
||||
if (\defined('WC_VERSION')) {
|
||||
if (\version_compare(\WC_VERSION, '3.0', '<')) {
|
||||
\add_action('wpdesk_log', [$this, 'wpdesk_log'], 10, 4);
|
||||
} else {
|
||||
\add_action('wpdesk_log', [$this, 'wpdesk_log_30'], 10, 4);
|
||||
}
|
||||
}
|
||||
}
|
||||
public function wpdesk_logger_level_options(array $options)
|
||||
{
|
||||
return ['disabled' => \__('Disabled', 'flexible-checkout-fields'), 'emergency' => \__('Emergency', 'flexible-checkout-fields'), 'alert' => \__('Alert', 'flexible-checkout-fields'), 'critical' => \__('Critical', 'flexible-checkout-fields'), 'error' => \__('Error', 'flexible-checkout-fields'), 'warning' => \__('Warning', 'flexible-checkout-fields'), 'notice' => \__('Notice', 'flexible-checkout-fields'), 'info' => \__('Info', 'flexible-checkout-fields'), 'debug' => \__('Debug', 'flexible-checkout-fields')];
|
||||
}
|
||||
/**
|
||||
* @param string $level
|
||||
* @param string $source
|
||||
* @param string $message
|
||||
* @param string $settings_level
|
||||
*/
|
||||
public function wpdesk_log($level, $source, $message, $settings_level = 'debug')
|
||||
{
|
||||
if (!isset($this->level_to_severity[$settings_level]) || !isset($this->level_to_severity[$level])) {
|
||||
return;
|
||||
}
|
||||
if ($this->level_to_severity[$settings_level] > $this->level_to_severity[$level]) {
|
||||
return;
|
||||
}
|
||||
if (\is_array($message) || \is_object($message)) {
|
||||
$message = \print_r($message, \true);
|
||||
}
|
||||
self::$logger->log($level, $message, ['source' => $source]);
|
||||
}
|
||||
public function wpdesk_log_30($level, $source, $message, $settings_level = 'debug')
|
||||
{
|
||||
if (!isset($this->level_to_severity[$settings_level]) || !isset($this->level_to_severity[$level])) {
|
||||
return;
|
||||
}
|
||||
if ($this->level_to_severity[$settings_level] > $this->level_to_severity[$level]) {
|
||||
return;
|
||||
}
|
||||
if (\is_array($message) || \is_object($message)) {
|
||||
$message = \print_r($message, \true);
|
||||
}
|
||||
self::$logger->log($level, $message, ['source' => $source]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
jQuery( document ).ready(function() {
|
||||
jQuery('.wpdesk-notice-gutenberg').each(function( index ) {
|
||||
var classList = jQuery(this).attr('class').split(/\s+/);
|
||||
var type = '';
|
||||
jQuery.each(classList, function(index, item) {
|
||||
if (item.startsWith('notice-')) {
|
||||
type = item.replace('notice-','');
|
||||
}
|
||||
});
|
||||
content = this.innerText;
|
||||
actions = [];
|
||||
jQuery.each(jQuery(this).find('a'), function(index, item) {
|
||||
text = item.innerText;
|
||||
actions.push({
|
||||
url: item.href,
|
||||
label: text.charAt(0).toUpperCase() + text.slice(1),
|
||||
});
|
||||
});
|
||||
isDismiss = jQuery(this).hasClass('is-dismissible');
|
||||
window.wp.data.dispatch( 'core/notices' ).createNotice(
|
||||
type,
|
||||
content,
|
||||
{
|
||||
isDismissible: isDismiss,
|
||||
actions: actions
|
||||
}
|
||||
);
|
||||
});
|
||||
} );
|
||||
@@ -0,0 +1,22 @@
|
||||
jQuery( document ).on( 'click', '.notice-dismiss', function() {
|
||||
var notice_name = jQuery(this).closest('div.notice').data('notice-name');
|
||||
var source = jQuery(this).closest('div.notice').data('source');
|
||||
if ('' !== notice_name) {
|
||||
jQuery.ajax({
|
||||
url: ajaxurl,
|
||||
type: 'post',
|
||||
data: {
|
||||
action: 'wpdesk_notice_dismiss',
|
||||
notice_name: notice_name,
|
||||
source: source,
|
||||
},
|
||||
success: function (response) {
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
jQuery( document ).on( 'click', '.notice-dismiss-link', function() {
|
||||
jQuery(this).closest('div.notice').data('source',jQuery(this).data('source'));
|
||||
jQuery(this).closest('div.notice').find('.notice-dismiss').click();
|
||||
});
|
||||
@@ -0,0 +1 @@
|
||||
jQuery(document).on("click",".notice-dismiss",function(){var a=jQuery(this).closest("div.notice").data("notice-name");var b=jQuery(this).closest("div.notice").data("source");if(""!==a){jQuery.ajax({url:ajaxurl,type:"post",data:{action:"wpdesk_notice_dismiss",notice_name:a,source:b},success:function(c){}})}});jQuery(document).on("click",".notice-dismiss-link",function(){jQuery(this).closest("div.notice").data("source",jQuery(this).data("source"));jQuery(this).closest("div.notice").find(".notice-dismiss").click()});
|
||||
@@ -0,0 +1,51 @@
|
||||
{
|
||||
"name": "wpdesk\/wp-notice",
|
||||
"description": "Library for displaying Wordpress notices.",
|
||||
"license": "MIT",
|
||||
"keywords": [
|
||||
"wordpress",
|
||||
"notice",
|
||||
"admin"
|
||||
],
|
||||
"homepage": "https:\/\/gitlab.com\/wpdesk\/wp-notice",
|
||||
"minimum-stability": "stable",
|
||||
"authors": [
|
||||
{
|
||||
"name": "grola",
|
||||
"email": "grola@wpdesk.net"
|
||||
}
|
||||
],
|
||||
"config": {
|
||||
"platform": {
|
||||
"php": "7.0"
|
||||
}
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.5",
|
||||
"wpdesk\/wp-builder": "^1.0|^2.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit\/phpunit": "<7",
|
||||
"wp-coding-standards\/wpcs": "^0.14.1",
|
||||
"squizlabs\/php_codesniffer": "^3.0.2",
|
||||
"mockery\/mockery": "*",
|
||||
"10up\/wp_mock": "*",
|
||||
"wimg\/php-compatibility": "^8"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"FcfVendor\\WPDesk\\Notice\\": "src\/WPDesk\/Notice\/"
|
||||
},
|
||||
"files": [
|
||||
"src\/WPDesk\/notice-functions.php"
|
||||
]
|
||||
},
|
||||
"autoload-dev": {},
|
||||
"scripts": {
|
||||
"phpcs": "phpcs",
|
||||
"phpunit-unit": "phpunit --configuration phpunit-unit.xml --coverage-text --colors=never",
|
||||
"phpunit-unit-fast": "phpunit --configuration phpunit-unit.xml --no-coverage",
|
||||
"phpunit-integration": "phpunit --configuration phpunit-integration.xml --coverage-text --colors=never",
|
||||
"phpunit-integration-fast": "phpunit --configuration phpunit-integration.xml --no-coverage"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
namespace FcfVendor;
|
||||
|
||||
require_once __DIR__ . '/vendor/autoload.php';
|
||||
if (!\class_exists('FcfVendor\\WPDesk\\Notice\\AjaxHandler')) {
|
||||
require_once __DIR__ . '/src/WPDesk/Notice/AjaxHandler.php';
|
||||
}
|
||||
if (!\class_exists('FcfVendor\\WPDesk\\Notice\\Notice')) {
|
||||
require_once __DIR__ . 'src/WPDesk/Notice/Notice.php';
|
||||
}
|
||||
if (!\class_exists('FcfVendor\\WPDesk\\Notice\\PermanentDismissibleNotice')) {
|
||||
require_once __DIR__ . '/src/WPDesk/Notice/PermanentDismissibleNotice.php';
|
||||
}
|
||||
if (!\class_exists('FcfVendor\\WPDesk\\Notice\\Factory')) {
|
||||
require_once __DIR__ . '/src/WPDesk/Notice/Factory.php';
|
||||
}
|
||||
require_once __DIR__ . '/src/WPDesk/notice-functions.php';
|
||||
@@ -0,0 +1,83 @@
|
||||
<?php
|
||||
|
||||
namespace FcfVendor\WPDesk\Notice;
|
||||
|
||||
use FcfVendor\WPDesk\PluginBuilder\Plugin\HookablePluginDependant;
|
||||
use FcfVendor\WPDesk\PluginBuilder\Plugin\PluginAccess;
|
||||
/**
|
||||
* Class AjaxHandler
|
||||
*
|
||||
* AjaxHandler for dismissible notices.
|
||||
*
|
||||
* @package WPDesk\Notice
|
||||
*/
|
||||
class AjaxHandler implements \FcfVendor\WPDesk\PluginBuilder\Plugin\HookablePluginDependant
|
||||
{
|
||||
use PluginAccess;
|
||||
const POST_FIELD_NOTICE_NAME = 'notice_name';
|
||||
const POST_FIELD_SOURCE = 'source';
|
||||
const SCRIPTS_VERSION = '4';
|
||||
const SCRIPT_HANDLE = 'wpdesk_notice';
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $assetsURL;
|
||||
/**
|
||||
* AjaxHandler constructor.
|
||||
*
|
||||
* @param string|null $assetsURL Assets URL.
|
||||
*/
|
||||
public function __construct($assetsURL = null)
|
||||
{
|
||||
$this->assetsURL = $assetsURL;
|
||||
}
|
||||
/**
|
||||
* Hooks.
|
||||
*/
|
||||
public function hooks()
|
||||
{
|
||||
if ($this->assetsURL) {
|
||||
\add_action('admin_enqueue_scripts', [$this, 'enqueueAdminScripts']);
|
||||
} else {
|
||||
\add_action('admin_head', [$this, 'addScriptToAdminHead']);
|
||||
}
|
||||
\add_action('wp_ajax_wpdesk_notice_dismiss', [$this, 'processAjaxNoticeDismiss']);
|
||||
}
|
||||
/**
|
||||
* Enqueue admin scripts.
|
||||
*/
|
||||
public function enqueueAdminScripts()
|
||||
{
|
||||
$suffix = \defined('SCRIPT_DEBUG') && \SCRIPT_DEBUG ? '' : '.min';
|
||||
\wp_register_script(self::SCRIPT_HANDLE, \trailingslashit($this->assetsURL) . 'js/notice' . $suffix . '.js', array('jquery'), self::SCRIPTS_VERSION);
|
||||
\wp_enqueue_script(self::SCRIPT_HANDLE);
|
||||
}
|
||||
/**
|
||||
* Add Java Script to admin header.
|
||||
*/
|
||||
public function addScriptToAdminHead()
|
||||
{
|
||||
include __DIR__ . '/views/admin-head-js.php';
|
||||
}
|
||||
/**
|
||||
* Process AJAX notice dismiss.
|
||||
*
|
||||
* Updates corresponded WordPress option and fires wpdesk_notice_dismissed_notice action with notice name.
|
||||
*/
|
||||
public function processAjaxNoticeDismiss()
|
||||
{
|
||||
if (isset($_POST[self::POST_FIELD_NOTICE_NAME])) {
|
||||
$noticeName = \sanitize_text_field($_POST[self::POST_FIELD_NOTICE_NAME]);
|
||||
if (isset($_POST[self::POST_FIELD_SOURCE])) {
|
||||
$source = \sanitize_text_field($_POST[self::POST_FIELD_SOURCE]);
|
||||
} else {
|
||||
$source = null;
|
||||
}
|
||||
\update_option(\FcfVendor\WPDesk\Notice\PermanentDismissibleNotice::OPTION_NAME_PREFIX . $noticeName, \FcfVendor\WPDesk\Notice\PermanentDismissibleNotice::OPTION_VALUE_DISMISSED);
|
||||
\do_action('wpdesk_notice_dismissed_notice', $noticeName, $source);
|
||||
}
|
||||
if (\defined('DOING_AJAX') && \DOING_AJAX) {
|
||||
die;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
namespace FcfVendor\WPDesk\Notice;
|
||||
|
||||
/**
|
||||
* Class Factory
|
||||
*
|
||||
* Factory for notices.
|
||||
* @package WPDesk\Notice
|
||||
*/
|
||||
class Factory
|
||||
{
|
||||
/**
|
||||
* Creates Notice object.
|
||||
*
|
||||
* @param string $noticeType Notice type.
|
||||
* @param string $noticeContent Notice content.
|
||||
* @param bool $isDismissible Is dismissible.
|
||||
* @param int $priority Priority.
|
||||
*
|
||||
* @return Notice
|
||||
*/
|
||||
public static function notice($noticeContent = '', $noticeType = 'info', $isDismissible = \false, $priority = 10)
|
||||
{
|
||||
return new \FcfVendor\WPDesk\Notice\Notice($noticeContent, $noticeType, $isDismissible, $priority);
|
||||
}
|
||||
/**
|
||||
* Creates PermanentDismissibleNotice object.
|
||||
*
|
||||
* @param string $noticeContent
|
||||
* @param string $noticeType
|
||||
* @param string $noticeName
|
||||
* @param int $priority
|
||||
*
|
||||
* @return PermanentDismissibleNotice
|
||||
*/
|
||||
public static function permanentDismissibleNotice($noticeContent = '', $noticeName = '', $noticeType = '', $priority = 10)
|
||||
{
|
||||
return new \FcfVendor\WPDesk\Notice\PermanentDismissibleNotice($noticeContent, $noticeName, $noticeType, $priority);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,251 @@
|
||||
<?php
|
||||
|
||||
namespace FcfVendor\WPDesk\Notice;
|
||||
|
||||
/**
|
||||
* Class Notice
|
||||
*
|
||||
* WordPress admin notice.
|
||||
* @package WPDesk\Notice
|
||||
*/
|
||||
class Notice
|
||||
{
|
||||
const NOTICE_TYPE_ERROR = 'error';
|
||||
const NOTICE_TYPE_WARNING = 'warning';
|
||||
const NOTICE_TYPE_SUCCESS = 'success';
|
||||
const NOTICE_TYPE_INFO = 'info';
|
||||
const ADMIN_FOOTER_BASE_PRIORITY = 9999999;
|
||||
/**
|
||||
* Notice type.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $noticeType;
|
||||
/**
|
||||
* Notice content.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $noticeContent;
|
||||
/**
|
||||
* Is dismissible.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $dismissible;
|
||||
/**
|
||||
* Notice hook priority.
|
||||
* @var int;
|
||||
*/
|
||||
protected $priority;
|
||||
/**
|
||||
* Is action added?
|
||||
* @var bool
|
||||
*/
|
||||
private $actionAdded = \false;
|
||||
/**
|
||||
* Attributes.
|
||||
*
|
||||
* @var string[]
|
||||
*/
|
||||
protected $attributes = array();
|
||||
/**
|
||||
* Show notice in gutenberg editor.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $showInGutenberg = \false;
|
||||
/**
|
||||
* WPDesk_Flexible_Shipping_Notice constructor.
|
||||
*
|
||||
* @param string $noticeContent Notice content.
|
||||
* @param string $noticeType Notice type.
|
||||
* @param bool $dismissible Is dismissible.
|
||||
* @param int $priority Notice priority.
|
||||
* @param array $attributes Attributes.
|
||||
* @param bool $showInGutenberg Show notice in gutenberg editor.
|
||||
*/
|
||||
public function __construct($noticeContent, $noticeType = 'info', $dismissible = \false, $priority = 10, $attributes = array(), $showInGutenberg = \false)
|
||||
{
|
||||
$this->noticeContent = $noticeContent;
|
||||
$this->noticeType = $noticeType;
|
||||
$this->dismissible = $dismissible;
|
||||
$this->priority = $priority;
|
||||
$this->attributes = $attributes;
|
||||
$this->showInGutenberg = $showInGutenberg;
|
||||
$this->addAction();
|
||||
}
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function isBlockEditor()
|
||||
{
|
||||
if (!\function_exists('get_current_screen')) {
|
||||
require_once \ABSPATH . '/wp-admin/includes/screen.php';
|
||||
}
|
||||
return \get_current_screen()->is_block_editor();
|
||||
}
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getNoticeContent()
|
||||
{
|
||||
return $this->noticeContent;
|
||||
}
|
||||
/**
|
||||
* @param string $noticeContent
|
||||
*/
|
||||
public function setNoticeContent($noticeContent)
|
||||
{
|
||||
$this->noticeContent = $noticeContent;
|
||||
}
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getNoticeType()
|
||||
{
|
||||
return $this->noticeType;
|
||||
}
|
||||
/**
|
||||
* @param string $noticeType
|
||||
*/
|
||||
public function setNoticeType($noticeType)
|
||||
{
|
||||
$this->noticeType = $noticeType;
|
||||
}
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function isDismissible()
|
||||
{
|
||||
return $this->dismissible;
|
||||
}
|
||||
/**
|
||||
* @param bool $dismissible
|
||||
*/
|
||||
public function setDismissible($dismissible)
|
||||
{
|
||||
$this->dismissible = $dismissible;
|
||||
}
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getPriority()
|
||||
{
|
||||
return $this->priority;
|
||||
}
|
||||
/**
|
||||
* @param int $priority
|
||||
*/
|
||||
public function setPriority($priority)
|
||||
{
|
||||
$this->priority = $priority;
|
||||
if ($this->actionAdded) {
|
||||
$this->removeAction();
|
||||
$this->addAction();
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Add notice action.
|
||||
*/
|
||||
protected function addAction()
|
||||
{
|
||||
if (!$this->actionAdded) {
|
||||
\add_action('admin_notices', [$this, 'showNotice'], $this->priority);
|
||||
\add_action('admin_footer', [$this, 'showNotice'], self::ADMIN_FOOTER_BASE_PRIORITY + \intval($this->priority));
|
||||
\add_action('admin_head', [$this, 'addGutenbergScript']);
|
||||
$this->actionAdded = \true;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Remove action.
|
||||
*/
|
||||
protected function removeAction()
|
||||
{
|
||||
if ($this->actionAdded) {
|
||||
\remove_action('admin_notices', [$this, 'showNotice'], $this->priority);
|
||||
\remove_action('admin_footer', [$this, 'showNotice'], self::ADMIN_FOOTER_BASE_PRIORITY + \intval($this->priority));
|
||||
$this->actionAdded = \false;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Enqueue admin scripts.
|
||||
*/
|
||||
public function addGutenbergScript()
|
||||
{
|
||||
if ($this->isBlockEditor()) {
|
||||
include_once __DIR__ . '/views/admin-head-js-gutenberg.php';
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Add attribute.
|
||||
*
|
||||
* @param string $name Name
|
||||
* @param string $value Value.
|
||||
*/
|
||||
public function addAttribute($name, $value)
|
||||
{
|
||||
$this->attributes[$name] = $value;
|
||||
}
|
||||
/**
|
||||
* Get notice class.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function getNoticeClass()
|
||||
{
|
||||
$notice_classes = ['notice'];
|
||||
if ('updated' === $this->noticeType) {
|
||||
$notice_classes[] = $this->noticeType;
|
||||
} else {
|
||||
$notice_classes[] = 'notice-' . $this->noticeType;
|
||||
}
|
||||
if ($this->dismissible) {
|
||||
$notice_classes[] = 'is-dismissible';
|
||||
}
|
||||
if (isset($this->attributes['class'])) {
|
||||
$notice_classes[] = $this->attributes['class'];
|
||||
}
|
||||
if ($this->showInGutenberg) {
|
||||
$notice_classes[] = 'wpdesk-notice-gutenberg';
|
||||
}
|
||||
return \implode(' ', $notice_classes);
|
||||
}
|
||||
/**
|
||||
* Get attributes as string.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function getAttributesAsString()
|
||||
{
|
||||
$attribute_string = \sprintf('class="%1$s"', \esc_attr($this->getNoticeClass()));
|
||||
foreach ($this->attributes as $attribute_name => $attribute_value) {
|
||||
if ('class' !== $attribute_name) {
|
||||
$attribute_string .= \sprintf(' %1$s="%2$s"', \esc_html($attribute_name), \esc_attr($attribute_value));
|
||||
}
|
||||
}
|
||||
return $attribute_string;
|
||||
}
|
||||
private function addParagraphToContent()
|
||||
{
|
||||
if (0 === \strpos($this->noticeContent, '<p>')) {
|
||||
return \false;
|
||||
}
|
||||
if (0 === \strpos($this->noticeContent, '<div>') || 0 === \strpos($this->noticeContent, '<div ')) {
|
||||
return \false;
|
||||
}
|
||||
return \true;
|
||||
}
|
||||
/**
|
||||
* Show notice;
|
||||
*/
|
||||
public function showNotice()
|
||||
{
|
||||
$this->removeAction();
|
||||
$noticeFormat = '<div %1$s>%2$s</div>';
|
||||
if ($this->addParagraphToContent()) {
|
||||
$noticeFormat = '<div %1$s><p>%2$s</p></div>';
|
||||
}
|
||||
echo \sprintf($noticeFormat, $this->getAttributesAsString(), $this->noticeContent);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
<?php
|
||||
|
||||
namespace FcfVendor\WPDesk\Notice;
|
||||
|
||||
/**
|
||||
* Class PermanentDismissibleNotice
|
||||
*
|
||||
* WordPress admin dismissible notice.
|
||||
* @package WPDesk\Notice
|
||||
*/
|
||||
class PermanentDismissibleNotice extends \FcfVendor\WPDesk\Notice\Notice
|
||||
{
|
||||
const OPTION_NAME_PREFIX = 'wpdesk_notice_dismiss_';
|
||||
const OPTION_VALUE_DISMISSED = '1';
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $noticeName;
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $noticeDismissOptionName;
|
||||
/**
|
||||
* WPDesk_Flexible_Shipping_Notice constructor.
|
||||
*
|
||||
* @param string $noticeContent Notice content.
|
||||
* @param string $noticeName Notice dismiss option name.
|
||||
* @param string $noticeType Notice type.
|
||||
* @param int $priority Priority
|
||||
* @param array $attributes Attributes.
|
||||
* @param bool $showInGutenberg Show notice in gutenberg editor.
|
||||
*/
|
||||
public function __construct($noticeContent, $noticeName, $noticeType = 'info', $priority = 10, $attributes = array(), $showInGutenberg = \false)
|
||||
{
|
||||
parent::__construct($noticeContent, $noticeType, \true, $priority, $attributes, $showInGutenberg);
|
||||
$this->noticeName = $noticeName;
|
||||
$this->noticeDismissOptionName = static::OPTION_NAME_PREFIX . $noticeName;
|
||||
if (self::OPTION_VALUE_DISMISSED === \get_option($this->noticeDismissOptionName, '')) {
|
||||
$this->removeAction();
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Undo dismiss notice.
|
||||
*/
|
||||
public function undoDismiss()
|
||||
{
|
||||
\delete_option($this->noticeDismissOptionName);
|
||||
$this->addAction();
|
||||
}
|
||||
/**
|
||||
* Get attributes as string.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function getAttributesAsString()
|
||||
{
|
||||
$attributesAsString = parent::getAttributesAsString();
|
||||
$attributesAsString .= \sprintf(' data-notice-name="%1$s"', \esc_attr($this->noticeName));
|
||||
$attributesAsString .= \sprintf(' id="wpdesk-notice-%1$s"', \esc_attr($this->noticeName));
|
||||
return $attributesAsString;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
namespace FcfVendor;
|
||||
|
||||
if (!\defined('ABSPATH')) {
|
||||
exit;
|
||||
}
|
||||
// Exit if accessed directly
|
||||
?>
|
||||
<script type="text/javascript">
|
||||
<?php
|
||||
include \dirname(__FILE__) . '/../../../../assets/js/gutenberg.js';
|
||||
?>
|
||||
</script>
|
||||
<?php
|
||||
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
namespace FcfVendor;
|
||||
|
||||
if (!\defined('ABSPATH')) {
|
||||
exit;
|
||||
}
|
||||
// Exit if accessed directly
|
||||
?>
|
||||
<script type="text/javascript">
|
||||
<?php
|
||||
include \dirname(__FILE__) . '/../../../../assets/js/notice.min.js';
|
||||
?>
|
||||
</script>
|
||||
<?php
|
||||
@@ -0,0 +1,228 @@
|
||||
<?php
|
||||
|
||||
namespace FcfVendor;
|
||||
|
||||
if (!\function_exists('FcfVendor\\WPDeskInitWpNoticeAjaxHandler')) {
|
||||
/**
|
||||
* Init notices AJAX Handler.
|
||||
*
|
||||
* @param string|null $assetsUrl
|
||||
*
|
||||
* @return \WPDesk\Notice\AjaxHandler
|
||||
*/
|
||||
function WPDeskInitWpNoticeAjaxHandler($assetsUrl = null)
|
||||
{
|
||||
$ajax_handler = new \FcfVendor\WPDesk\Notice\AjaxHandler($assetsUrl);
|
||||
$ajax_handler->hooks();
|
||||
return $ajax_handler;
|
||||
}
|
||||
}
|
||||
if (!\function_exists('FcfVendor\\wpdesk_init_wp_notice_ajax_handler')) {
|
||||
/**
|
||||
* Alias for {@see WPDeskInitNoticeAjaxHandler()} function.
|
||||
*
|
||||
* @param null $assetsUrl
|
||||
*
|
||||
* @return \WPDesk\Notice\AjaxHandler
|
||||
*/
|
||||
function wpdesk_init_wp_notice_ajax_handler($assetsUrl = null)
|
||||
{
|
||||
return \FcfVendor\WPDeskInitWpNoticeAjaxHandler($assetsUrl);
|
||||
}
|
||||
}
|
||||
if (!\function_exists('FcfVendor\\WPDeskWpNotice')) {
|
||||
/**
|
||||
* Creates Notice.
|
||||
*
|
||||
* @param string $noticeContent Notice content.
|
||||
* @param string $noticeType Notice type.
|
||||
* @param bool $dismissible Dismissible notice.
|
||||
* @param int $priority Notice priority,
|
||||
*
|
||||
* @return \WPDesk\Notice\Notice
|
||||
*/
|
||||
function WPDeskWpNotice($noticeContent, $noticeType = 'info', $dismissible = \false, $priority = 10)
|
||||
{
|
||||
return \FcfVendor\WPDesk\Notice\Factory::notice($noticeContent, $noticeType, $dismissible, $priority);
|
||||
}
|
||||
}
|
||||
if (!\function_exists('FcfVendor\\wpdesk_wp_notice')) {
|
||||
/**
|
||||
* Creates Notice.
|
||||
*
|
||||
* Alias for {@see WPDeskNotice()} function.
|
||||
*
|
||||
* @param string $noticeContent Notice content.
|
||||
* @param string $noticeType Notice type.
|
||||
* @param bool $dismissible Dismissible notice.
|
||||
* @param int $priority Notice priority,
|
||||
*
|
||||
* @return \WPDesk\Notice\Notice
|
||||
*/
|
||||
function wpdesk_wp_notice($noticeContent, $noticeType = 'info', $dismissible = \false, $priority = 10)
|
||||
{
|
||||
return \FcfVendor\WPDeskWpNotice($noticeContent, $noticeType, $dismissible, $priority);
|
||||
}
|
||||
}
|
||||
if (!\function_exists('FcfVendor\\WPDeskWpNoticeInfo')) {
|
||||
/**
|
||||
* Creates Notice Info.
|
||||
*
|
||||
* @param string $noticeContent Notice content.
|
||||
* @param bool $dismissible Dismissible notice.
|
||||
* @param int $priority Notice priority,
|
||||
*
|
||||
* @return \WPDesk\Notice\Notice
|
||||
*/
|
||||
function WPDeskWpNoticeInfo($noticeContent, $dismissible = \false, $priority = 10)
|
||||
{
|
||||
return \FcfVendor\WPDesk\Notice\Factory::notice($noticeContent, \FcfVendor\WPDesk\Notice\Notice::NOTICE_TYPE_INFO, $dismissible, $priority);
|
||||
}
|
||||
}
|
||||
if (!\function_exists('FcfVendor\\wpdesk_wp_notice_info')) {
|
||||
/**
|
||||
* Creates Notice Info.
|
||||
*
|
||||
* Alias for {@see WPDeskNoticeInfo()} function.
|
||||
*
|
||||
* @param string $noticeContent Notice content.
|
||||
* @param bool $dismissible Dismissible notice.
|
||||
* @param int $priority Notice priority,
|
||||
*
|
||||
* @return \WPDesk\Notice\Notice
|
||||
*/
|
||||
function wpdesk_wp_notice_info($noticeContent, $dismissible = \false, $priority = 10)
|
||||
{
|
||||
return \FcfVendor\WPDeskWpNoticeInfo($noticeContent, $dismissible, $priority);
|
||||
}
|
||||
}
|
||||
if (!\function_exists('FcfVendor\\WPDeskWpNoticeError')) {
|
||||
/**
|
||||
* Creates Notice Error.
|
||||
*
|
||||
* @param string $noticeContent Notice content.
|
||||
* @param bool $dismissible Dismissible notice.
|
||||
* @param int $priority Notice priority,
|
||||
*
|
||||
* @return \WPDesk\Notice\Notice
|
||||
*/
|
||||
function WPDeskWpNoticeError($noticeContent, $dismissible = \false, $priority = 10)
|
||||
{
|
||||
return \FcfVendor\WPDesk\Notice\Factory::notice($noticeContent, \FcfVendor\WPDesk\Notice\Notice::NOTICE_TYPE_ERROR, $dismissible, $priority);
|
||||
}
|
||||
}
|
||||
if (!\function_exists('FcfVendor\\wpdesk_wp_notice_error')) {
|
||||
/**
|
||||
* Creates Notice Error.
|
||||
*
|
||||
* Alias for {@see WPDeskNoticeError()} function.
|
||||
*
|
||||
* @param string $noticeContent Notice content.
|
||||
* @param bool $dismissible Dismissible notice.
|
||||
* @param int $priority Notice priority,
|
||||
*
|
||||
* @return \WPDesk\Notice\Notice
|
||||
*/
|
||||
function wpdesk_wp_notice_error($noticeContent, $dismissible = \false, $priority = 10)
|
||||
{
|
||||
return \FcfVendor\WPDeskWpNoticeError($noticeContent, $dismissible, $priority);
|
||||
}
|
||||
}
|
||||
if (!\function_exists('FcfVendor\\WPDeskWpNoticeWarning')) {
|
||||
/**
|
||||
* Creates Notice Warning.
|
||||
*
|
||||
* @param string $noticeContent Notice content.
|
||||
* @param bool $dismissible Dismissible notice.
|
||||
* @param int $priority Notice priority,
|
||||
*
|
||||
* @return \WPDesk\Notice\Notice
|
||||
*/
|
||||
function WPDeskWpNoticeWarning($noticeContent, $dismissible = \false, $priority = 10)
|
||||
{
|
||||
return \FcfVendor\WPDesk\Notice\Factory::notice($noticeContent, \FcfVendor\WPDesk\Notice\Notice::NOTICE_TYPE_WARNING, $dismissible, $priority);
|
||||
}
|
||||
}
|
||||
if (!\function_exists('FcfVendor\\wpdesk_wp_notice_warning')) {
|
||||
/**
|
||||
* Creates Notice Warning.
|
||||
*
|
||||
* Alias for {@see WPDeskNoticeWarning()} function.
|
||||
*
|
||||
* @param string $noticeContent Notice content.
|
||||
* @param bool $dismissible Dismissible notice.
|
||||
* @param int $priority Notice priority,
|
||||
*
|
||||
* @return \WPDesk\Notice\Notice
|
||||
*/
|
||||
function wpdesk_wp_notice_warning($noticeContent, $dismissible = \false, $priority = 10)
|
||||
{
|
||||
return \FcfVendor\WPDeskWpNoticeWarning($noticeContent, $dismissible, $priority);
|
||||
}
|
||||
}
|
||||
if (!\function_exists('FcfVendor\\WPDeskWpNoticeSuccess')) {
|
||||
/**
|
||||
* Creates Notice Success.
|
||||
*
|
||||
* @param string $noticeContent Notice content.
|
||||
* @param bool $dismissible Dismissible notice.
|
||||
* @param int $priority Notice priority,
|
||||
*
|
||||
* @return \WPDesk\Notice\Notice
|
||||
*/
|
||||
function WPDeskWpNoticeSuccess($noticeContent, $dismissible = \false, $priority = 10)
|
||||
{
|
||||
return \FcfVendor\WPDesk\Notice\Factory::notice($noticeContent, \FcfVendor\WPDesk\Notice\Notice::NOTICE_TYPE_SUCCESS, $dismissible, $priority);
|
||||
}
|
||||
}
|
||||
if (!\function_exists('FcfVendor\\wpdesk_wp_notice_success')) {
|
||||
/**
|
||||
* Creates Notice Success.
|
||||
*
|
||||
* Alias for {@see WPDeskNoticeSuccess()} function.
|
||||
*
|
||||
* @param string $noticeContent Notice content.
|
||||
* @param bool $dismissible Dismissible notice.
|
||||
* @param int $priority Notice priority,
|
||||
*
|
||||
* @return \WPDesk\Notice\Notice
|
||||
*/
|
||||
function wpdesk_wp_notice_success($noticeContent, $dismissible = \false, $priority = 10)
|
||||
{
|
||||
return \FcfVendor\WPDeskWpNoticeSuccess($noticeContent, $dismissible, $priority);
|
||||
}
|
||||
}
|
||||
if (!\function_exists('FcfVendor\\WPDeskPermanentDismissibleWpNotice')) {
|
||||
/**
|
||||
* Creates Permanent Dismissible Notice.
|
||||
*
|
||||
* @param string $noticeContent Notice content.
|
||||
* @param string $noticeType Notice type.
|
||||
* @param string $noticeName Notice name.
|
||||
* @param int $priority Notice priority.
|
||||
*
|
||||
* @return \WPDesk\Notice\Notice
|
||||
*/
|
||||
function WPDeskPermanentDismissibleWpNotice($noticeContent, $noticeName, $noticeType = 'info', $priority = 10)
|
||||
{
|
||||
return \FcfVendor\WPDesk\Notice\Factory::permanentDismissibleNotice($noticeContent, $noticeName, $noticeType, $priority);
|
||||
}
|
||||
}
|
||||
if (!\function_exists('FcfVendor\\wpdesk_permanent_dismissible_wp_notice')) {
|
||||
/**
|
||||
* Creates Permanent Dismissible Notice.
|
||||
*
|
||||
* Alias for {@see WPDeskPermanentDismissibleNotice()} function.
|
||||
*
|
||||
* @param string $noticeContent Notice content.
|
||||
* @param string $noticeName Notice name.
|
||||
* @param string $noticeType Notice type.
|
||||
* @param int $priority Notice priority.
|
||||
*
|
||||
* @return \WPDesk\Notice\Notice
|
||||
*/
|
||||
function wpdesk_permanent_dismissible_wp_notice($noticeContent, $noticeName, $noticeType = 'info', $priority = 10)
|
||||
{
|
||||
return \FcfVendor\WPDeskPermanentDismissibleWpNotice($noticeContent, $noticeName, $noticeType, $priority);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
{
|
||||
"name": "wpdesk\/wp-plugin-flow",
|
||||
"authors": [
|
||||
{
|
||||
"name": "Krzysiek",
|
||||
"email": "krzysiek@wpdesk.pl"
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"php": ">=5.6",
|
||||
"wpdesk\/wp-basic-requirements": "^3.2.3",
|
||||
"wpdesk\/wp-builder": "^1.4.4",
|
||||
"wpdesk\/wp-wpdesk-license": "^2.10.1",
|
||||
"wpdesk\/wp-wpdesk-helper": "^2.4",
|
||||
"wpdesk\/wp-wpdesk-tracker": "^2.3.1"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit\/phpunit": "<7",
|
||||
"wp-coding-standards\/wpcs": "^0.14.1",
|
||||
"squizlabs\/php_codesniffer": "^3.4.2",
|
||||
"10up\/wp_mock": "^0.2",
|
||||
"wpdesk\/wp-wpdesk-composer": "^2.3"
|
||||
},
|
||||
"autoload": {
|
||||
"classmap": [
|
||||
"src"
|
||||
]
|
||||
},
|
||||
"autoload-dev": {
|
||||
"classmap": [
|
||||
"vendor\/wpdesk\/wp-basic-requirements",
|
||||
"tests\/Stub"
|
||||
]
|
||||
},
|
||||
"extra": {
|
||||
"text-domain": "wp-plugin-flow",
|
||||
"translations-folder": "lang",
|
||||
"po-files": {
|
||||
"pl_PL": "pl_PL.po"
|
||||
}
|
||||
},
|
||||
"scripts": {
|
||||
"phpunit-unit": "phpunit --configuration phpunit-unit.xml --coverage-text --colors=never",
|
||||
"phpunit-unit-fast": "phpunit --configuration phpunit-unit.xml --no-coverage",
|
||||
"phpunit-integration": "phpunit --configuration phpunit-integration.xml --coverage-text --colors=never",
|
||||
"phpunit-integration-fast": "phpunit --configuration phpunit-integration.xml --no-coverage"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
<?php
|
||||
|
||||
namespace FcfVendor\WPDesk\Plugin\Flow\Initialization;
|
||||
|
||||
use FcfVendor\WPDesk\PluginBuilder\Plugin\Activateable;
|
||||
use FcfVendor\WPDesk\PluginBuilder\Plugin\Deactivateable;
|
||||
use FcfVendor\WPDesk\PluginBuilder\Plugin\SlimPlugin;
|
||||
use FcfVendor\WPDesk\PluginBuilder\Storage\StorageFactory;
|
||||
/**
|
||||
* Helps with plugin building concepts.
|
||||
*
|
||||
* @package WPDesk\Plugin\Flow\Initialization
|
||||
*/
|
||||
trait BuilderTrait
|
||||
{
|
||||
/**
|
||||
* Build plugin from info.
|
||||
*
|
||||
* @param \WPDesk_Plugin_Info $plugin_info
|
||||
*
|
||||
* @return SlimPlugin
|
||||
*/
|
||||
private function build_plugin(\FcfVendor\WPDesk_Plugin_Info $plugin_info)
|
||||
{
|
||||
$class_name = \apply_filters('wp_builder_plugin_class', $plugin_info->get_class_name());
|
||||
/** @var SlimPlugin $plugin */
|
||||
$plugin = new $class_name($plugin_info);
|
||||
return $plugin;
|
||||
}
|
||||
/**
|
||||
* Initialize WP register hooks that have to be fire before any other.
|
||||
*
|
||||
* @param \WPDesk_Plugin_Info $plugin_info
|
||||
* @param SlimPlugin $plugin
|
||||
*
|
||||
* @return SlimPlugin
|
||||
*/
|
||||
private function init_register_hooks(\FcfVendor\WPDesk_Plugin_Info $plugin_info, \FcfVendor\WPDesk\PluginBuilder\Plugin\SlimPlugin $plugin)
|
||||
{
|
||||
if ($plugin instanceof \FcfVendor\WPDesk\PluginBuilder\Plugin\Activateable) {
|
||||
\register_activation_hook($plugin_info->get_plugin_file_name(), [$plugin, 'activate']);
|
||||
}
|
||||
if ($plugin instanceof \FcfVendor\WPDesk\PluginBuilder\Plugin\Deactivateable) {
|
||||
\register_deactivation_hook($plugin_info->get_plugin_file_name(), [$plugin, 'deactivate']);
|
||||
}
|
||||
return $plugin;
|
||||
}
|
||||
/**
|
||||
* Store plugin for others to use.
|
||||
*
|
||||
* @param SlimPlugin $plugin
|
||||
*/
|
||||
private function store_plugin(\FcfVendor\WPDesk\PluginBuilder\Plugin\SlimPlugin $plugin)
|
||||
{
|
||||
$storageFactory = new \FcfVendor\WPDesk\PluginBuilder\Storage\StorageFactory();
|
||||
$storageFactory->create_storage()->add_to_storage(\get_class($plugin), $plugin);
|
||||
}
|
||||
/**
|
||||
* Init integration layer of the plugin.
|
||||
*
|
||||
* @param SlimPlugin $plugin
|
||||
*/
|
||||
private function init_plugin(\FcfVendor\WPDesk\PluginBuilder\Plugin\SlimPlugin $plugin)
|
||||
{
|
||||
\do_action('wp_builder_before_plugin_init', $plugin);
|
||||
$plugin->init();
|
||||
\do_action('wp_builder_before_init', $plugin);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
<?php
|
||||
|
||||
namespace FcfVendor\WPDesk\Plugin\Flow\Initialization\Simple;
|
||||
|
||||
use FcfVendor\WPDesk\Helper\PrefixedHelperAsLibrary;
|
||||
/**
|
||||
* Trait helps with helper initialization
|
||||
*
|
||||
* @package WPDesk\Plugin\Flow\Initialization\Simple
|
||||
*/
|
||||
trait HelperInstanceAsFilterTrait
|
||||
{
|
||||
/** @var \WPDesk\Helper\PrefixedHelperAsLibrary */
|
||||
private static $helper_instance;
|
||||
/**
|
||||
* Returns version of the helper. Inc when helper is changed and should be instantiated fist.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
private function get_helper_version()
|
||||
{
|
||||
return 5;
|
||||
}
|
||||
/**
|
||||
* Returns filter action name for helper instance
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function get_helper_action_name()
|
||||
{
|
||||
return 'wpdesk_helper_instance';
|
||||
}
|
||||
/**
|
||||
* Instantiate helper and return it
|
||||
*
|
||||
* @return PrefixedHelperAsLibrary
|
||||
*/
|
||||
private function get_helper_instance()
|
||||
{
|
||||
return \apply_filters($this->get_helper_action_name(), null);
|
||||
}
|
||||
/**
|
||||
* Prepare helper to be instantiated using wpdesk_helper_instance filter
|
||||
*
|
||||
* @return void|PrefixedHelperAsLibrary
|
||||
*/
|
||||
private function prepare_helper_action()
|
||||
{
|
||||
\class_exists(\WPDesk\Helper\HelperAsLibrary::class);
|
||||
// autoload this class
|
||||
\add_filter($this->get_helper_action_name(), function ($helper_instance) {
|
||||
if (\is_object($helper_instance)) {
|
||||
return $helper_instance;
|
||||
}
|
||||
if (\is_object(self::$helper_instance)) {
|
||||
return self::$helper_instance;
|
||||
}
|
||||
if (\apply_filters('wpdesk_can_start_helper', \true, $this->plugin_info)) {
|
||||
self::$helper_instance = new \FcfVendor\WPDesk\Helper\PrefixedHelperAsLibrary();
|
||||
self::$helper_instance->hooks();
|
||||
\do_action('wpdesk_helper_started', self::$helper_instance, $this->plugin_info);
|
||||
return self::$helper_instance;
|
||||
}
|
||||
}, 10 - $this->get_helper_version());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
namespace FcfVendor\WPDesk\Plugin\Flow\Initialization;
|
||||
|
||||
/**
|
||||
* Interface for factory of plugin initialization strategy
|
||||
*/
|
||||
interface InitializationFactory
|
||||
{
|
||||
/**
|
||||
* @param \WPDesk_Plugin_Info $info
|
||||
*
|
||||
* @return InitializationStrategy
|
||||
*/
|
||||
public function create_initialization_strategy(\FcfVendor\WPDesk_Plugin_Info $info);
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
namespace FcfVendor\WPDesk\Plugin\Flow\Initialization;
|
||||
|
||||
use FcfVendor\WPDesk\PluginBuilder\Plugin\SlimPlugin;
|
||||
/**
|
||||
* Interface for initialization strategy for plugin. How to initialize it?
|
||||
*/
|
||||
interface InitializationStrategy
|
||||
{
|
||||
/**
|
||||
* Run tasks that prepares plugin to work. Have to run before plugin loaded.
|
||||
*
|
||||
* @param \WPDesk_Plugin_Info $plugin_info
|
||||
*
|
||||
* @return SlimPlugin
|
||||
*/
|
||||
public function run_before_init(\FcfVendor\WPDesk_Plugin_Info $plugin_info);
|
||||
/**
|
||||
* Run task that integrates plugin with other dependencies. Can be run in plugins_loaded.
|
||||
*
|
||||
* @param \WPDesk_Plugin_Info $plugin_info
|
||||
*
|
||||
* @return SlimPlugin
|
||||
*/
|
||||
public function run_init(\FcfVendor\WPDesk_Plugin_Info $plugin_info);
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
namespace FcfVendor\WPDesk\Plugin\Flow\Initialization;
|
||||
|
||||
/**
|
||||
* Can disable shared plugin before it's loaded using plugin filename
|
||||
*/
|
||||
class PluginDisablerByFileTrait
|
||||
{
|
||||
/** @var string */
|
||||
private $plugin_file;
|
||||
/**
|
||||
* @param string $plugin_file
|
||||
*/
|
||||
public function __construct($plugin_file)
|
||||
{
|
||||
$this->plugin_file = $plugin_file;
|
||||
}
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function disable()
|
||||
{
|
||||
/**
|
||||
* @param WPDesk_Loader[] $loaders
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
$false_for_helper = function ($loaders) {
|
||||
return \array_filter($loaders, function ($loader) {
|
||||
try {
|
||||
// BIG HACK TO GET PRIVATE PROPERTY
|
||||
$reflection = new \ReflectionClass($loader);
|
||||
$property = $reflection->getProperty('loader_info');
|
||||
$property->setAccessible(\true);
|
||||
/** @var WPDesk_Composer_Loader_Info $inner_info */
|
||||
$inner_info = $property->getValue($loader);
|
||||
$plugin_info = $inner_info->get_plugin_info();
|
||||
return \basename($plugin_info->get_plugin_file_name()) !== \basename($this->plugin_file);
|
||||
} catch (\Exception $e) {
|
||||
return \true;
|
||||
}
|
||||
});
|
||||
};
|
||||
\add_filter('wp_autoloader_loader_loaders_to_load', $false_for_helper);
|
||||
\add_filter('wp_autoloader_loader_loaders_to_create', $false_for_helper);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
namespace FcfVendor\WPDesk\Plugin\Flow\Initialization\Simple;
|
||||
|
||||
use FcfVendor\WPDesk\Plugin\Flow\Initialization\InitializationFactory;
|
||||
use FcfVendor\WPDesk\Plugin\Flow\Initialization\InitializationStrategy;
|
||||
/**
|
||||
* Can decide if strategy is for free plugin or paid plugin
|
||||
*/
|
||||
class SimpleFactory implements \FcfVendor\WPDesk\Plugin\Flow\Initialization\InitializationFactory
|
||||
{
|
||||
/** @var bool */
|
||||
private $free;
|
||||
/**
|
||||
* @param bool $free True for free/repository plugin
|
||||
*/
|
||||
public function __construct($free = \false)
|
||||
{
|
||||
$this->free = $free;
|
||||
}
|
||||
/**
|
||||
* Create strategy according to the given flag
|
||||
*
|
||||
* @param \WPDesk_Plugin_Info $info
|
||||
*
|
||||
* @return InitializationStrategy
|
||||
*/
|
||||
public function create_initialization_strategy(\FcfVendor\WPDesk_Plugin_Info $info)
|
||||
{
|
||||
if ($this->free) {
|
||||
return new \FcfVendor\WPDesk\Plugin\Flow\Initialization\Simple\SimpleFreeStrategy($info);
|
||||
}
|
||||
return new \FcfVendor\WPDesk\Plugin\Flow\Initialization\Simple\SimplePaidStrategy($info);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
<?php
|
||||
|
||||
namespace FcfVendor\WPDesk\Plugin\Flow\Initialization\Simple;
|
||||
|
||||
use FcfVendor\WPDesk\Plugin\Flow\Initialization\ActivationTrait;
|
||||
use FcfVendor\WPDesk\Plugin\Flow\Initialization\BuilderTrait;
|
||||
use FcfVendor\WPDesk\Plugin\Flow\Initialization\InitializationStrategy;
|
||||
use FcfVendor\WPDesk\PluginBuilder\Plugin\SlimPlugin;
|
||||
/**
|
||||
* Initialize free plugin
|
||||
* - just build it already
|
||||
*/
|
||||
class SimpleFreeStrategy implements \FcfVendor\WPDesk\Plugin\Flow\Initialization\InitializationStrategy
|
||||
{
|
||||
use HelperInstanceAsFilterTrait;
|
||||
use TrackerInstanceAsFilterTrait;
|
||||
use BuilderTrait;
|
||||
/** @var \WPDesk_Plugin_Info */
|
||||
private $plugin_info;
|
||||
/** @var SlimPlugin */
|
||||
private $plugin;
|
||||
public function __construct(\FcfVendor\WPDesk_Plugin_Info $plugin_info)
|
||||
{
|
||||
$this->plugin_info = $plugin_info;
|
||||
}
|
||||
/**
|
||||
* Run tasks that prepares plugin to work. Have to run before plugin loaded.
|
||||
*
|
||||
* @param \WPDesk_Plugin_Info $plugin_info
|
||||
*
|
||||
* @return SlimPlugin
|
||||
*/
|
||||
public function run_before_init(\FcfVendor\WPDesk_Plugin_Info $plugin_info)
|
||||
{
|
||||
$this->plugin = $this->build_plugin($plugin_info);
|
||||
$this->init_register_hooks($plugin_info, $this->plugin);
|
||||
}
|
||||
/**
|
||||
* Run task that integrates plugin with other dependencies. Can be run in plugins_loaded.
|
||||
*
|
||||
* @param \WPDesk_Plugin_Info $plugin_info
|
||||
*
|
||||
* @return SlimPlugin
|
||||
*/
|
||||
public function run_init(\FcfVendor\WPDesk_Plugin_Info $plugin_info)
|
||||
{
|
||||
if (!$this->plugin) {
|
||||
$this->plugin = $this->build_plugin($plugin_info);
|
||||
}
|
||||
$this->prepare_helper_action();
|
||||
$this->prepare_tracker_action();
|
||||
$this->store_plugin($this->plugin);
|
||||
$this->init_plugin($this->plugin);
|
||||
return $this->plugin;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,135 @@
|
||||
<?php
|
||||
|
||||
namespace FcfVendor\WPDesk\Plugin\Flow\Initialization\Simple;
|
||||
|
||||
use FcfVendor\WPDesk\Helper\HelperRemover;
|
||||
use FcfVendor\WPDesk\Helper\PrefixedHelperAsLibrary;
|
||||
use FcfVendor\WPDesk\License\PluginRegistrator;
|
||||
use FcfVendor\WPDesk\Plugin\Flow\Initialization\ActivationTrait;
|
||||
use FcfVendor\WPDesk\Plugin\Flow\Initialization\BuilderTrait;
|
||||
use FcfVendor\WPDesk\Plugin\Flow\Initialization\PluginDisablerByFileTrait;
|
||||
use FcfVendor\WPDesk\Plugin\Flow\Initialization\InitializationStrategy;
|
||||
use FcfVendor\WPDesk\PluginBuilder\Plugin\ActivationAware;
|
||||
use FcfVendor\WPDesk\PluginBuilder\Plugin\SlimPlugin;
|
||||
/**
|
||||
* Initialize standard paid plugin
|
||||
* - register to helper
|
||||
* - initialize helper
|
||||
* - build with info about plugin active flag
|
||||
*/
|
||||
class SimplePaidStrategy implements \FcfVendor\WPDesk\Plugin\Flow\Initialization\InitializationStrategy
|
||||
{
|
||||
use HelperInstanceAsFilterTrait;
|
||||
use TrackerInstanceAsFilterTrait;
|
||||
use BuilderTrait;
|
||||
/** @var \WPDesk_Plugin_Info */
|
||||
private $plugin_info;
|
||||
/** @var SlimPlugin */
|
||||
private $plugin;
|
||||
public function __construct(\FcfVendor\WPDesk_Plugin_Info $plugin_info)
|
||||
{
|
||||
$this->plugin_info = $plugin_info;
|
||||
}
|
||||
/**
|
||||
* Run tasks that prepares plugin to work. Have to run before plugin loaded.
|
||||
*
|
||||
* @param \WPDesk_Plugin_Info $plugin_info
|
||||
*
|
||||
* @return SlimPlugin
|
||||
*/
|
||||
public function run_before_init(\FcfVendor\WPDesk_Plugin_Info $plugin_info)
|
||||
{
|
||||
$this->plugin = $this->build_plugin($plugin_info);
|
||||
$this->init_register_hooks($plugin_info, $this->plugin);
|
||||
}
|
||||
/**
|
||||
* Run task that integrates plugin with other dependencies. Can be run in plugins_loaded.
|
||||
*
|
||||
* @param \WPDesk_Plugin_Info $plugin_info
|
||||
*
|
||||
* @return SlimPlugin
|
||||
*/
|
||||
public function run_init(\FcfVendor\WPDesk_Plugin_Info $plugin_info)
|
||||
{
|
||||
if (!$this->plugin) {
|
||||
$this->plugin = $this->build_plugin($plugin_info);
|
||||
}
|
||||
$this->prepare_tracker_action();
|
||||
$registrator = $this->register_plugin();
|
||||
\add_action('plugins_loaded', function () use($registrator) {
|
||||
$this->init_helper();
|
||||
$is_plugin_subscription_active = $registrator instanceof \FcfVendor\WPDesk\License\PluginRegistrator && $registrator->is_active();
|
||||
if ($this->plugin instanceof \FcfVendor\WPDesk\PluginBuilder\Plugin\ActivationAware && $is_plugin_subscription_active) {
|
||||
$this->plugin->set_active();
|
||||
}
|
||||
$this->store_plugin($this->plugin);
|
||||
$this->init_plugin($this->plugin);
|
||||
}, $priority_before_flow_2_5_after_2_6 = -45);
|
||||
return $this->plugin;
|
||||
}
|
||||
/**
|
||||
* Register plugin for subscriptions and updates
|
||||
*
|
||||
* @return PluginRegistrator
|
||||
*
|
||||
* @see init_helper note
|
||||
*
|
||||
*/
|
||||
private function register_plugin()
|
||||
{
|
||||
if (\apply_filters('wpdesk_can_register_plugin', \true, $this->plugin_info)) {
|
||||
$registrator = new \FcfVendor\WPDesk\License\PluginRegistrator($this->plugin_info);
|
||||
$registrator->add_plugin_to_installed_plugins();
|
||||
return $registrator;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Helper is a component that gives:
|
||||
* - activation interface
|
||||
* - automatic updates
|
||||
* - logs
|
||||
* - some other feats
|
||||
*
|
||||
* NOTE:
|
||||
*
|
||||
* It's possible for this method to not found classes embedded here.
|
||||
* OTHER plugin in unlikely scenario that THIS plugin is disabled
|
||||
* can use this class and do not have this library dependencies as
|
||||
* these are loaded using composer.
|
||||
*
|
||||
* @return PrefixedHelperAsLibrary|null
|
||||
*/
|
||||
private function init_helper()
|
||||
{
|
||||
$this->prevent_older_helpers();
|
||||
$this->prepare_helper_action();
|
||||
return $this->get_helper_instance();
|
||||
}
|
||||
/**
|
||||
* Try to disable all other types of helpers
|
||||
*/
|
||||
private function prevent_older_helpers()
|
||||
{
|
||||
if (\apply_filters('wpdesk_can_hack_shared_helper', \true, $this->plugin_info)) {
|
||||
// hack to ensure that the class is loaded so other helpers are disabled
|
||||
\class_exists(\WPDesk\Helper\HelperAsLibrary::class, \true);
|
||||
}
|
||||
if (\apply_filters('wpdesk_can_supress_original_helper', \true, $this->plugin_info)) {
|
||||
$this->try_suppress_original_helper_load();
|
||||
// start supression only once. Prevent doing it again
|
||||
\add_filter('wpdesk_can_supress_original_helper', function () {
|
||||
return \false;
|
||||
});
|
||||
}
|
||||
if (\apply_filters('wpdesk_can_remove_old_helper_hooks', \true, $this->plugin_info)) {
|
||||
(new \FcfVendor\WPDesk\Helper\HelperRemover())->hooks();
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Tries to prevent original Helper from loading
|
||||
*/
|
||||
private function try_suppress_original_helper_load()
|
||||
{
|
||||
(new \FcfVendor\WPDesk\Plugin\Flow\Initialization\PluginDisablerByFileTrait('wpdesk-helper/wpdesk-helper.php'))->disable();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
<?php
|
||||
|
||||
namespace FcfVendor\WPDesk\Plugin\Flow\Initialization\Simple;
|
||||
|
||||
/**
|
||||
* Trait helps with tracker initialization
|
||||
*
|
||||
* @package WPDesk\Plugin\Flow\Initialization\Simple\
|
||||
*/
|
||||
trait TrackerInstanceAsFilterTrait
|
||||
{
|
||||
/** @var \WPDesk_Tracker_Interface */
|
||||
private static $tracker_instance;
|
||||
/**
|
||||
* Returns filter action name for tracker instance
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function get_tracker_action_name()
|
||||
{
|
||||
return 'wpdesk_tracker_instance';
|
||||
}
|
||||
/**
|
||||
* Returns version of the tracker. Inc when trackker is changed and should be instantiated fist.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
private function get_tracker_version()
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
/**
|
||||
* @return \WPDesk_Tracker_Interface
|
||||
*/
|
||||
private function get_tracker_instance()
|
||||
{
|
||||
return \apply_filters($this->get_tracker_action_name(), null);
|
||||
}
|
||||
/**
|
||||
* Prepare tracker to be instantiated using wpdesk_tracker_instance filter
|
||||
*
|
||||
* @return void|\WPDesk_Tracker
|
||||
*/
|
||||
private function prepare_tracker_action()
|
||||
{
|
||||
\class_exists(\WPDesk_Tracker_Factory::class);
|
||||
//autoload this class
|
||||
\add_filter($this->get_tracker_action_name(), function ($tracker_instance) {
|
||||
if (\is_object($tracker_instance)) {
|
||||
return $tracker_instance;
|
||||
}
|
||||
if (\is_object(self::$tracker_instance)) {
|
||||
return self::$tracker_instance;
|
||||
}
|
||||
if (\apply_filters('wpdesk_can_start_tracker', \true, $this->plugin_info)) {
|
||||
$tracker_factory = new \FcfVendor\WPDesk_Tracker_Factory_Prefixed();
|
||||
self::$tracker_instance = $tracker_factory->create_tracker(\basename($this->plugin_info->get_plugin_file_name()));
|
||||
\do_action('wpdesk_tracker_started', self::$tracker_instance, $this->plugin_info);
|
||||
return self::$tracker_instance;
|
||||
}
|
||||
}, 10 - $this->get_tracker_version());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,145 @@
|
||||
<?php
|
||||
|
||||
namespace FcfVendor\WPDesk\Plugin\Flow;
|
||||
|
||||
use FcfVendor\WPDesk\Plugin\Flow\Initialization\InitializationFactory;
|
||||
/**
|
||||
* Bootstrap plugin loading
|
||||
* - check requirements
|
||||
* - prepare plugin info
|
||||
* - delegate plugin building to the initializator
|
||||
*/
|
||||
final class PluginBootstrap
|
||||
{
|
||||
const LIBRARY_TEXT_DOMAIN = 'flexible-checkout-fields';
|
||||
const PRIORITY_BEFORE_FLOW_2_5 = -50;
|
||||
/** @var string */
|
||||
private $plugin_version;
|
||||
/** @var string */
|
||||
private $plugin_name;
|
||||
/** @var string */
|
||||
private $plugin_class_name;
|
||||
/** @var string */
|
||||
private $plugin_text_domain;
|
||||
/** @var string */
|
||||
private $plugin_dir;
|
||||
/** @var string */
|
||||
private $plugin_file;
|
||||
/** @var array */
|
||||
private $requirements;
|
||||
/** @var string */
|
||||
private $product_id;
|
||||
/**
|
||||
* Factory to build strategy how initialize that plugin
|
||||
*
|
||||
* @var InitializationFactory
|
||||
*/
|
||||
private $initialization_factory;
|
||||
/**
|
||||
* WPDesk_Plugin_Bootstrap constructor.
|
||||
*
|
||||
* @param string $plugin_version
|
||||
* @param string $plugin_release_timestamp
|
||||
* @param string $plugin_name
|
||||
* @param string $plugin_class_name
|
||||
* @param string $plugin_text_domain
|
||||
* @param string $plugin_dir
|
||||
* @param string $plugin_file
|
||||
* @param array $requirements
|
||||
* @param string $product_id
|
||||
* @param InitializationFactory $build_factory
|
||||
*/
|
||||
public function __construct($plugin_version, $plugin_release_timestamp, $plugin_name, $plugin_class_name, $plugin_text_domain, $plugin_dir, $plugin_file, array $requirements, $product_id, \FcfVendor\WPDesk\Plugin\Flow\Initialization\InitializationFactory $build_factory)
|
||||
{
|
||||
$this->plugin_version = $plugin_version;
|
||||
$this->plugin_name = $plugin_name;
|
||||
$this->plugin_class_name = $plugin_class_name;
|
||||
$this->plugin_text_domain = $plugin_text_domain;
|
||||
$this->plugin_dir = $plugin_dir;
|
||||
$this->plugin_file = $plugin_file;
|
||||
$this->requirements = $requirements;
|
||||
$this->product_id = $product_id;
|
||||
$this->initialization_factory = $build_factory;
|
||||
}
|
||||
/**
|
||||
* Run the plugin bootstrap
|
||||
*/
|
||||
public function run()
|
||||
{
|
||||
$plugin_info = $this->get_plugin_info();
|
||||
$this->init_translations($plugin_info);
|
||||
$strategy = $this->initialization_factory->create_initialization_strategy($plugin_info);
|
||||
$requirements_checker = $this->create_requirements_checker();
|
||||
if ($requirements_checker->are_requirements_met()) {
|
||||
$strategy->run_before_init($plugin_info);
|
||||
}
|
||||
$this->add_activation_hook_for_save_activation_date();
|
||||
\add_action('plugins_loaded', static function () use($strategy, $requirements_checker, $plugin_info) {
|
||||
if ($requirements_checker->are_requirements_met()) {
|
||||
$strategy->run_init($plugin_info);
|
||||
} else {
|
||||
$requirements_checker->render_notices();
|
||||
}
|
||||
}, self::PRIORITY_BEFORE_FLOW_2_5);
|
||||
}
|
||||
/**
|
||||
* Initialize activated_plugin action.
|
||||
* Action stores plugin activation date.
|
||||
* Example option name: plugin_activation_flexible-shipping/flexible-shipping.php
|
||||
*/
|
||||
private function add_activation_hook_for_save_activation_date()
|
||||
{
|
||||
\add_action('activated_plugin', static function ($plugin_file, $network_wide = \false) {
|
||||
if (!$network_wide) {
|
||||
$option_name = 'plugin_activation_' . $plugin_file;
|
||||
$activation_date = \get_option($option_name, '');
|
||||
if ('' === $activation_date) {
|
||||
$activation_date = \current_time('mysql');
|
||||
\update_option($option_name, $activation_date);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Adds text domain used in a library
|
||||
*/
|
||||
private function init_translations(\FcfVendor\WPDesk_Plugin_Info $plugin_info)
|
||||
{
|
||||
$lang_dir = 'lang';
|
||||
if (\method_exists($plugin_info, 'get_language_dir')) {
|
||||
$lang_dir = $plugin_info->get_language_dir();
|
||||
}
|
||||
\load_plugin_textdomain($plugin_info->get_text_domain(), \false, \basename($plugin_info->get_plugin_dir()) . "/{$lang_dir}/");
|
||||
}
|
||||
/**
|
||||
* Factory method creates requirement checker to run the checks
|
||||
*
|
||||
* @return \WPDesk_Requirement_Checker
|
||||
*/
|
||||
private function create_requirements_checker()
|
||||
{
|
||||
/** @var \WPDesk_Requirement_Checker_Factory $requirements_checker_factory */
|
||||
$requirements_checker_factory = new \FcfVendor\WPDesk_Basic_Requirement_Checker_Factory();
|
||||
return $requirements_checker_factory->create_from_requirement_array(__FILE__, $this->plugin_name, $this->requirements, $this->plugin_text_domain);
|
||||
}
|
||||
/**
|
||||
* Factory method creates \WPDesk_Plugin_Info to bootstrap info about plugin in one place
|
||||
*
|
||||
* TODO: move to WPDesk_Plugin_Info factory
|
||||
*
|
||||
* @return \WPDesk_Plugin_Info
|
||||
*/
|
||||
private function get_plugin_info()
|
||||
{
|
||||
$plugin_info = new \FcfVendor\WPDesk_Plugin_Info();
|
||||
$plugin_info->set_plugin_file_name(\plugin_basename($this->plugin_file));
|
||||
$plugin_info->set_plugin_name($this->plugin_name);
|
||||
$plugin_info->set_plugin_dir($this->plugin_dir);
|
||||
$plugin_info->set_class_name($this->plugin_class_name);
|
||||
$plugin_info->set_version($this->plugin_version);
|
||||
$plugin_info->set_product_id($this->product_id);
|
||||
$plugin_info->set_text_domain($this->plugin_text_domain);
|
||||
$plugin_info->set_plugin_url(\plugins_url(\dirname(\plugin_basename($this->plugin_file))));
|
||||
return $plugin_info;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
namespace FcfVendor;
|
||||
|
||||
/**
|
||||
* @var string $plugin_version
|
||||
* @var string $plugin_name
|
||||
* @var string $plugin_class_name
|
||||
* @var string $plugin_text_domain
|
||||
* @var string $plugin_dir
|
||||
* @var string $plugin_file
|
||||
* @var array $requirements
|
||||
* @var string $product_id
|
||||
*/
|
||||
if (!\defined('ABSPATH')) {
|
||||
die;
|
||||
}
|
||||
// Code in PHP >= 5.3 but understandable by older parsers
|
||||
if (\PHP_VERSION_ID > 50300) {
|
||||
require_once $plugin_dir . '/vendor/autoload.php';
|
||||
$plugin_init_factory = new \FcfVendor\WPDesk\Plugin\Flow\Initialization\Simple\SimpleFactory(\true);
|
||||
}
|
||||
require \dirname(__FILE__) . '/plugin-init-php52.php';
|
||||
@@ -0,0 +1,45 @@
|
||||
<?php
|
||||
|
||||
namespace FcfVendor;
|
||||
|
||||
/**
|
||||
* @var string $plugin_version
|
||||
* @var string $plugin_name
|
||||
* @var string $plugin_class_name
|
||||
* @var string $plugin_text_domain
|
||||
* @var string $plugin_dir
|
||||
* @var string $plugin_file
|
||||
* @var array $requirements
|
||||
* @var string $product_id
|
||||
* @var WPDesk\Plugin\Flow\Initialization\InitializationFactory|void $plugin_init_factory
|
||||
*/
|
||||
if (!\defined('ABSPATH')) {
|
||||
die;
|
||||
}
|
||||
// Code in PHP >= 5.3 but understandable by older parsers
|
||||
if (\PHP_VERSION_ID > 50300) {
|
||||
require_once $plugin_dir . '/vendor/autoload.php';
|
||||
if (!isset($plugin_init_factory)) {
|
||||
$plugin_init_factory = new \FcfVendor\WPDesk\Plugin\Flow\Initialization\Simple\SimpleFactory();
|
||||
}
|
||||
$bootstrap = new \FcfVendor\WPDesk\Plugin\Flow\PluginBootstrap(
|
||||
$plugin_version,
|
||||
null,
|
||||
// deprecated
|
||||
$plugin_name,
|
||||
$plugin_class_name,
|
||||
$plugin_text_domain,
|
||||
$plugin_dir,
|
||||
$plugin_file,
|
||||
$requirements,
|
||||
$product_id,
|
||||
$plugin_init_factory
|
||||
);
|
||||
$bootstrap->run();
|
||||
// all optional vars must be cleared
|
||||
unset($plugin_init_factory);
|
||||
} else {
|
||||
/** @noinspection PhpDeprecationInspection */
|
||||
$php52_function = \create_function('', 'echo sprintf( __("<p><strong style=\'color: red;\'>PHP version is older than 5.3 so no WP Desk plugins will work. Please contact your host and ask them to upgrade. </strong></p>", \'wp-plugin-flow\') );');
|
||||
\add_action('admin_notices', $php52_function);
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
{
|
||||
"name": "wpdesk\/wp-view",
|
||||
"authors": [
|
||||
{
|
||||
"name": "Krzysiek",
|
||||
"email": "krzysiek@wpdesk.pl"
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"php": ">=5.5"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit\/phpunit": "<7",
|
||||
"wp-coding-standards\/wpcs": "^0.14.1",
|
||||
"squizlabs\/php_codesniffer": "^3.0.2",
|
||||
"mockery\/mockery": "*",
|
||||
"10up\/wp_mock": "*",
|
||||
"wimg\/php-compatibility": "^8"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"FcfVendor\\WPDesk\\View\\": "src\/"
|
||||
}
|
||||
},
|
||||
"autoload-dev": {},
|
||||
"scripts": {
|
||||
"phpcs": "phpcs",
|
||||
"phpunit-unit": "phpunit --configuration phpunit-unit.xml --coverage-text --colors=never",
|
||||
"phpunit-unit-fast": "phpunit --configuration phpunit-unit.xml --no-coverage",
|
||||
"phpunit-integration": "phpunit --configuration phpunit-integration.xml --coverage-text --colors=never",
|
||||
"phpunit-integration-fast": "phpunit --configuration phpunit-integration.xml --no-coverage"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
<?php
|
||||
|
||||
namespace FcfVendor\WPDesk\View;
|
||||
|
||||
use FcfVendor\WPDesk\View\Renderer\SimplePhpRenderer;
|
||||
use FcfVendor\WPDesk\View\Resolver\ChainResolver;
|
||||
use FcfVendor\WPDesk\View\Resolver\DirResolver;
|
||||
use FcfVendor\WPDesk\View\Resolver\WPThemeResolver;
|
||||
/**
|
||||
* Facilitates building of the default plugin renderer.
|
||||
*
|
||||
* @package WPDesk\View
|
||||
*/
|
||||
class PluginViewBuilder
|
||||
{
|
||||
/** @var string */
|
||||
private $plugin_dir;
|
||||
/** @var string[] */
|
||||
private $template_dirs;
|
||||
/**
|
||||
* @param string $plugin_dir Plugin directory path(absolute path)
|
||||
* @param string|string[] $template_dir Directory or list of directories with templates to render
|
||||
*/
|
||||
public function __construct($plugin_dir, $template_dir = 'templates')
|
||||
{
|
||||
$this->plugin_dir = $plugin_dir;
|
||||
if (!\is_array($template_dir)) {
|
||||
$this->template_dirs = [$template_dir];
|
||||
} else {
|
||||
$this->template_dirs = $template_dir;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Creates simple renderer that search for the templates in plugin dir and in theme/child dir.
|
||||
*
|
||||
* For example if your plugin dir is /plugin, template dir is /templates, theme is /theme, and a child theme is /child
|
||||
* the templates will be loaded from(order is important):
|
||||
* - /child/plugin/*.php
|
||||
* - /theme/plugin/*.php
|
||||
* - /plugin/templates/*.php
|
||||
*
|
||||
* @return SimplePhpRenderer
|
||||
*/
|
||||
public function createSimpleRenderer()
|
||||
{
|
||||
$resolver = new \FcfVendor\WPDesk\View\Resolver\ChainResolver();
|
||||
$resolver->appendResolver(new \FcfVendor\WPDesk\View\Resolver\WPThemeResolver(\basename($this->plugin_dir)));
|
||||
foreach ($this->template_dirs as $dir) {
|
||||
$dir = \trailingslashit($this->plugin_dir) . \trailingslashit($dir);
|
||||
$resolver->appendResolver(new \FcfVendor\WPDesk\View\Resolver\DirResolver($dir));
|
||||
}
|
||||
return new \FcfVendor\WPDesk\View\Renderer\SimplePhpRenderer($resolver);
|
||||
}
|
||||
/**
|
||||
* Load templates using simple renderer.
|
||||
*
|
||||
* @param string $name Name of the template
|
||||
* @param string $path Additional path of the template ie. for path "path" the templates would be loaded from /plugin/templates/path/*.php
|
||||
* @param array $args Arguments for templates to use
|
||||
*
|
||||
* @return string Rendered template.
|
||||
*/
|
||||
public function loadTemplate($name, $path = '.', $args = array())
|
||||
{
|
||||
$renderer = $this->createSimpleRenderer();
|
||||
return $renderer->render(\trailingslashit($path) . $name, $args);
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user