This commit is contained in:
2024-05-20 15:37:46 +03:00
commit 00b7dbd0b7
10404 changed files with 3285853 additions and 0 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,10 @@
<?php
namespace WebpConverterVendor\MattPlugins\DeactivationModal\Exception;
/**
* .
*/
class DuplicatedFormOptionKeyException extends \Exception
{
}

View File

@ -0,0 +1,10 @@
<?php
namespace WebpConverterVendor\MattPlugins\DeactivationModal\Exception;
/**
* .
*/
class DuplicatedFormValueKeyException extends \Exception
{
}

View File

@ -0,0 +1,10 @@
<?php
namespace WebpConverterVendor\MattPlugins\DeactivationModal\Exception;
/**
* .
*/
class UnknownFormOptionKeyException extends \Exception
{
}

View File

@ -0,0 +1,13 @@
<?php
namespace WebpConverterVendor\MattPlugins\DeactivationModal;
interface Hookable
{
/**
* Init hooks (actions and filters).
*
* @return void
*/
public function hooks();
}

View File

@ -0,0 +1,49 @@
<?php
namespace WebpConverterVendor\MattPlugins\DeactivationModal;
use WebpConverterVendor\MattPlugins\DeactivationModal\Model\FormOptions;
use WebpConverterVendor\MattPlugins\DeactivationModal\Model\FormTemplate;
use WebpConverterVendor\MattPlugins\DeactivationModal\Model\FormValues;
use WebpConverterVendor\MattPlugins\DeactivationModal\Service\AssetsPrinterService;
use WebpConverterVendor\MattPlugins\DeactivationModal\Service\TemplateGeneratorService;
/**
* Manages the modal displayed when the plugin is deactivated.
*/
class Modal
{
const MODAL_TEMPLATE_PATH = __DIR__ . '/../templates/modal.php';
const MODAL_ASSETS_PATH_CSS = __DIR__ . '/../assets/build/css/styles.css';
const MODAL_ASSETS_PATH_JS = __DIR__ . '/../assets/build/js/scripts.js';
/**
* @var string
*/
private $plugin_slug;
/**
* @var string
*/
private $form_template;
/**
* @var FormOptions
*/
private $form_options;
/**
* @var FormValues
*/
private $form_values;
/**
* @param string $plugin_slug Example: "plugin-name".
* @param FormTemplate $form_template Information about the deactivation modal template.
* @param FormOptions $form_options List of plugin deactivation reasons to choose from.
* @param FormValues $form_values Values sent in the request that reports the plugin deactivation.
*/
public function __construct(string $plugin_slug, FormTemplate $form_template, FormOptions $form_options, FormValues $form_values)
{
$this->plugin_slug = $plugin_slug;
$this->form_template = $form_template;
$this->form_options = $form_options;
$this->form_values = $form_values;
(new AssetsPrinterService($this->plugin_slug))->hooks();
(new TemplateGeneratorService($this->plugin_slug, $this->form_template, $this->form_options, $this->form_values))->hooks();
}
}

View File

@ -0,0 +1,104 @@
<?php
namespace WebpConverterVendor\MattPlugins\DeactivationModal\Model;
/**
* Stores information about the selectable reason of the plugin deactivation.
*/
class FormOption
{
/**
* @var string Key of the deactivation reason.
*/
private $key;
/**
* @var int Order priority (ascending).
*/
private $priority;
/**
* @var string Label of the reason option.
*/
private $label;
/**
* @var callable|null A function that returns a message visible after selecting the reason (may contain HTML).
*/
private $message;
/**
* @var string|null Label of additional question (visible after selecting the reason in the form).
*/
private $question;
/**
* @param string $key Key of the deactivation reason.
* @param int $priority Order priority (ascending).
* @param string $label Label of the reason option.
* @param callable $message A function that returns a message visible after selecting the reason (may contain
* HTML).
* @param string $question Label of additional question (visible after selecting the reason in the form).
*/
public function __construct(string $key, int $priority, string $label, callable $message = null, string $question = null)
{
$this->key = $key;
$this->priority = $priority;
$this->label = $label;
$this->message = $message;
$this->question = $question;
}
public function get_key() : string
{
return $this->key;
}
public function get_priority() : int
{
return $this->priority;
}
/**
* @param int $priority Order priority (ascending).
*/
public function set_priority(int $priority) : self
{
$this->priority = $priority;
return $this;
}
public function get_label() : string
{
return $this->label;
}
/**
* @param string $label Label of the reason option.
*/
public function set_label(string $label) : self
{
$this->label = $label;
return $this;
}
/**
* @return callable|null
*/
public function get_message()
{
return $this->message;
}
/**
* @param string|null $message Message visible after selecting the reason in the form (may contain HTML).
*/
public function set_message(string $message = null) : self
{
$this->message = $message;
return $this;
}
/**
* @return string|null
*/
public function get_question()
{
return $this->question;
}
/**
* @param string|null $question Label of additional question (visible after selecting the reason in the form).
*/
public function set_question(string $question = null) : self
{
$this->question = $question;
return $this;
}
}

View File

@ -0,0 +1,73 @@
<?php
namespace WebpConverterVendor\MattPlugins\DeactivationModal\Model;
use WebpConverterVendor\MattPlugins\DeactivationModal\Exception\DuplicatedFormOptionKeyException;
use WebpConverterVendor\MattPlugins\DeactivationModal\Exception\UnknownFormOptionKeyException;
/**
* Manages the list of deactivation reason in the form.
*/
class FormOptions
{
/**
* @var FormOption[]
*/
private $options = [];
/**
* @param FormOption $new_option .
*
* @throws DuplicatedFormOptionKeyException
*/
public function set_option(FormOption $new_option) : self
{
foreach ($this->options as $option) {
if ($option->get_key() === $new_option->get_key()) {
throw new DuplicatedFormOptionKeyException($new_option->get_key());
}
}
$this->options[] = $new_option;
return $this;
}
/**
* @param string $option_key .
*
* @throws UnknownFormOptionKeyException
*/
public function delete_option(string $option_key) : self
{
foreach ($this->options as $option_index => $option) {
if ($option->get_key() === $option_key) {
unset($this->options[$option_index]);
return $this;
}
}
throw new UnknownFormOptionKeyException($option_key);
}
/**
* @param string $option_key .
* @param callable $update_callback Example: "function ( FormOption $option ) { }".
*
* @throws UnknownFormOptionKeyException
*/
public function update_option(string $option_key, callable $update_callback) : self
{
foreach ($this->options as $option) {
if ($option->get_key() === $option_key) {
\call_user_func($update_callback, $option);
return $this;
}
}
throw new UnknownFormOptionKeyException($option_key);
}
/**
* @return FormOption[]
*/
public function get_options() : array
{
$options = $this->options;
\usort($options, function (FormOption $option_a, FormOption $option_b) {
return $option_a->get_priority() <=> $option_b->get_priority();
});
return $options;
}
}

View File

@ -0,0 +1,98 @@
<?php
namespace WebpConverterVendor\MattPlugins\DeactivationModal\Model;
/**
* Stores information about the deactivation modal template.
*/
class FormTemplate
{
/**
* @var string
*/
private $api_url;
/**
* @var string
*/
private $form_title;
/**
* @var string
*/
private $form_desc;
/**
* @var string
*/
private $button_submit_label;
/**
* @var string
*/
private $button_skip_label;
/**
* @var string|null
*/
private $logo_url;
/**
* @var string|null
*/
private $notice_message;
/**
* @var string
*/
private $field_name_reason = 'request_reason';
/**
* @var string
*/
private $field_name_comment = 'request_comment_%s';
public function __construct(string $api_url, string $form_title, string $form_desc, string $button_submit_label, string $button_skip_label, string $logo_url = null, string $notice_message = null)
{
$this->api_url = $api_url;
$this->form_title = $form_title;
$this->form_desc = $form_desc;
$this->button_submit_label = $button_submit_label;
$this->button_skip_label = $button_skip_label;
$this->logo_url = $logo_url;
$this->notice_message = $notice_message;
}
public function get_api_url() : string
{
return $this->api_url;
}
public function get_form_title() : string
{
return $this->form_title;
}
public function get_form_desc() : string
{
return $this->form_desc;
}
public function get_button_submit_label() : string
{
return $this->button_submit_label;
}
public function get_button_skip_label() : string
{
return $this->button_skip_label;
}
/**
* @return string|null
*/
public function get_logo_url()
{
return $this->logo_url;
}
/**
* @return string|null
*/
public function get_notice_message()
{
return $this->notice_message;
}
public function get_field_name_reason() : string
{
return $this->field_name_reason;
}
public function get_field_name_comment() : string
{
return $this->field_name_comment;
}
}

View File

@ -0,0 +1,35 @@
<?php
namespace WebpConverterVendor\MattPlugins\DeactivationModal\Model;
/**
* Stores information about the additional value sent in the request reporting plugin deactivation.
*/
class FormValue
{
/**
* @var string Key of the additional value.
*/
private $key;
/**
* @var callable A function that returns a text value.
*/
private $value_callback;
/**
* @param string $key Key of the additional value.
* @param callable $value_callback A function that returns a text value.
*/
public function __construct(string $key, callable $value_callback)
{
$this->key = $key;
$this->value_callback = $value_callback;
}
public function get_key() : string
{
return $this->key;
}
public function get_value_callback() : callable
{
return $this->value_callback;
}
}

View File

@ -0,0 +1,37 @@
<?php
namespace WebpConverterVendor\MattPlugins\DeactivationModal\Model;
use WebpConverterVendor\MattPlugins\DeactivationModal\Exception\DuplicatedFormValueKeyException;
/**
* It manages the list of additional information sent in the request reporting plugin deactivation.
*/
class FormValues
{
/**
* @var FormValue[]
*/
private $values = [];
/**
* @param FormValue $new_value .
*
* @throws DuplicatedFormValueKeyException
*/
public function set_value(FormValue $new_value) : self
{
foreach ($this->values as $value) {
if ($value->get_key() === $new_value->get_key()) {
throw new DuplicatedFormValueKeyException($new_value->get_key());
}
}
$this->values[] = $new_value;
return $this;
}
/**
* @return FormValue[]
*/
public function get_values() : array
{
return $this->values;
}
}

View File

@ -0,0 +1,75 @@
<?php
namespace WebpConverterVendor\MattPlugins\DeactivationModal\Model;
/**
* Stores information containing request data reporting plugin deactivation.
*/
class RequestData
{
/**
* @var string
*/
private $plugin_slug;
/**
* @var string|null
*/
private $reason_key = null;
/**
* @var string|null
*/
private $additional_info = null;
/**
* @var array
*/
private $additional_data = [];
/**
* @param string $plugin_slug .
*/
public function __construct(string $plugin_slug)
{
$this->plugin_slug = $plugin_slug;
}
public function get_plugin_slug() : string
{
return $this->plugin_slug;
}
public function set_reason_key(string $reason_key = null) : self
{
$this->reason_key = $reason_key;
return $this;
}
/**
* @return string|null
*/
public function get_reason_key()
{
return $this->reason_key;
}
public function set_additional_info(string $additional_info = null) : self
{
$this->additional_info = $additional_info;
return $this;
}
/**
* @return string|null
*/
public function get_additional_info()
{
return $this->additional_info;
}
public function set_additional_data(array $additional_data) : self
{
$this->additional_data = $additional_data;
return $this;
}
public function set_additional_data_item(string $data_key, string $data_value) : self
{
$this->additional_data[$data_key] = $data_value;
return $this;
}
public function get_additional_data() : array
{
return $this->additional_data;
}
}

View File

@ -0,0 +1,55 @@
<?php
namespace WebpConverterVendor\MattPlugins\DeactivationModal\Service;
use WebpConverterVendor\MattPlugins\DeactivationModal\Hookable;
use WebpConverterVendor\MattPlugins\DeactivationModal\Modal;
/**
* Prints the needed contents of CSS and JS files on the plugin list page.
*/
class AssetsPrinterService implements Hookable
{
const PLUGIN_NAME_VARIABLE = '{__PLUGIN_SLUG__}';
/**
* @var string
*/
private $plugin_slug;
public function __construct(string $plugin_slug)
{
$this->plugin_slug = $plugin_slug;
}
/**
* {@inheritdoc}
*/
public function hooks()
{
add_action('admin_print_styles-plugins.php', [$this, 'load_styles']);
add_action('admin_print_footer_scripts-plugins.php', [$this, 'load_scripts']);
}
public function load_styles()
{
?>
<style id="deactivation-modal-css_<?php
echo esc_attr($this->plugin_slug);
?>">
<?php
$plugin_slug = $this->plugin_slug;
include_once Modal::MODAL_ASSETS_PATH_CSS;
?>
</style>
<?php
}
public function load_scripts()
{
?>
<script id="deactivation-modal-js_<?php
echo esc_attr($this->plugin_slug);
?>">
<?php
$plugin_slug = $this->plugin_slug;
include_once Modal::MODAL_ASSETS_PATH_JS;
?>
</script>
<?php
}
}

View File

@ -0,0 +1,52 @@
<?php
namespace WebpConverterVendor\MattPlugins\DeactivationModal\Service;
use WebpConverterVendor\MattPlugins\DeactivationModal\Hookable;
use WebpConverterVendor\MattPlugins\DeactivationModal\Modal;
use WebpConverterVendor\MattPlugins\DeactivationModal\Model\FormOptions;
use WebpConverterVendor\MattPlugins\DeactivationModal\Model\FormTemplate;
use WebpConverterVendor\MattPlugins\DeactivationModal\Model\FormValues;
/**
* Prints the deactivation modal template on the plugin list page.
*/
class TemplateGeneratorService implements Hookable
{
/**
* @var string
*/
private $plugin_slug;
/**
* @var FormTemplate
*/
private $form_template;
/**
* @var FormOptions
*/
private $form_options;
/**
* @var FormValues
*/
private $form_values;
public function __construct(string $plugin_slug, FormTemplate $form_template, FormOptions $form_options, FormValues $form_values)
{
$this->plugin_slug = $plugin_slug;
$this->form_template = $form_template;
$this->form_options = $form_options;
$this->form_values = $form_values;
}
/**
* {@inheritdoc}
*/
public function hooks()
{
add_action('admin_print_footer_scripts-plugins.php', [$this, 'load_template'], 0);
}
public function load_template()
{
$params = ['plugin_slug' => $this->plugin_slug, 'form_template' => $this->form_template, 'form_options' => $this->form_options, 'form_values' => $this->form_values];
\extract($params);
// phpcs:ignore WordPress.PHP.DontExtract.extract_extract
require_once Modal::MODAL_TEMPLATE_PATH;
}
}

View File

@ -0,0 +1,179 @@
<?php
namespace WebpConverterVendor;
/**
* @var string $plugin_slug .
* @var MattPlugins\DeactivationModal\Model\FormTemplate $form_template .
* @var MattPlugins\DeactivationModal\Model\FormOptions $form_options .
* @var MattPlugins\DeactivationModal\Model\FormValues $form_values .
*
* @package Gbiorczyk\DeactivationModal
*/
?>
<div class="mattDeactivationModal"
data-matt-deactivation-modal="<?php
echo esc_attr($plugin_slug);
?>"
hidden>
<div class="mattDeactivationModal__wrapper">
<form action="<?php
echo esc_url($form_template->get_api_url());
?>"
method="POST"
class="mattDeactivationModal__form"
data-matt-deactivation-modal-form>
<button type="button"
class="mattDeactivationModal__close dashicons dashicons-no"
data-matt-deactivation-modal-button-close></button>
<?php
if ($form_template->get_logo_url() === null) {
?>
<div class="mattDeactivationModal__headline">
<?php
echo wp_kses_post($form_template->get_form_title());
?>
</div>
<?php
} else {
?>
<div class="mattDeactivationModal__headline" style="background-image: url(<?php
echo esc_attr($form_template->get_logo_url());
?>);">
<?php
echo wp_kses_post($form_template->get_form_title());
?>
</div>
<?php
}
?>
<div class="mattDeactivationModal__desc">
<?php
echo wp_kses_post($form_template->get_form_desc());
?>
</div>
<ul class="mattDeactivationModal__options">
<?php
foreach ($form_options->get_options() as $option) {
$option_id = \sprintf('option-%1$s-%2$s', $plugin_slug, $option->get_key());
?>
<li class="mattDeactivationModal__option">
<input type="radio"
name="<?php
echo esc_attr($form_template->get_field_name_reason());
?>"
value="<?php
echo esc_attr($option->get_key());
?>"
id="<?php
echo esc_attr($option_id);
?>"
class="mattDeactivationModal__optionInput">
<label
for="<?php
echo esc_attr($option_id);
?>"
class="mattDeactivationModal__optionLabel">
<?php
echo esc_html($option->get_label());
?>
</label>
<div class="mattDeactivationModal__optionExtra">
<?php
$message = $option->get_message() !== null ? \call_user_func($option->get_message()) : null;
if ($message !== null) {
?>
<div class="mattDeactivationModal__optionMessage">
<?php
echo wp_kses_post($message);
?>
</div>
<?php
}
?>
<?php
if ($option->get_question() !== null) {
?>
<div class="mattDeactivationModal__optionBox">
<label
for="<?php
echo esc_attr($option_id);
?>-message"
class="mattDeactivationModal__optionBoxLabel">
<?php
echo esc_html($option->get_question());
?>
</label>
<textarea class="mattDeactivationModal__optionBoxTextarea"
name="<?php
echo esc_attr(\sprintf($form_template->get_field_name_comment(), $option->get_key()));
?>"
id="<?php
echo esc_attr($option_id);
?>-message"
placeholder=". . ."
rows="2"></textarea>
</div>
<?php
}
?>
</div>
</li>
<?php
}
?>
</ul>
<?php
if ($form_template->get_notice_message() !== null) {
?>
<div class="mattDeactivationModal__notice">
<?php
echo wp_kses_post($form_template->get_notice_message());
?>
</div>
<?php
}
?>
<ul class="mattDeactivationModal__buttons">
<li class="mattDeactivationModal__button">
<button type="submit"
class="mattDeactivationModal__buttonInner mattDeactivationModal__buttonInner--blue"
data-matt-deactivation-modal-button-submit>
<?php
echo esc_html($form_template->get_button_submit_label());
?>
</button>
</li>
<li class="mattDeactivationModal__button">
<button type="button"
class="mattDeactivationModal__buttonInner mattDeactivationModal__buttonInner--gray"
data-matt-deactivation-modal-button-skip>
<?php
echo esc_html($form_template->get_button_skip_label());
?>
</button>
</li>
</ul>
<?php
foreach ($form_values->get_values() as $form_value) {
?>
<input type="hidden"
name="<?php
echo esc_attr($form_value->get_key());
?>"
value="<?php
echo esc_attr(\call_user_func($form_value->get_value_callback()));
?>">
<?php
}
?>
</form>
</div>
</div>
<?php